From 088bdba0fbcff1e74dad385ecf834f26086bc205 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Fri, 9 Aug 2024 11:19:16 +0100 Subject: [PATCH] Import libzypp_17.35.9.orig.tar.gz [dgit import orig libzypp_17.35.9.orig.tar.gz] --- .clang-format | 117 + .clang-tidy | 18 + .gitattributes | 2 + .gitignore | 15 + .obs/workflows.yml | 20 + .travis.yml | 30 + CMakeLists.txt | 438 + COPYING | 21 + Makefile.cvs | 30 + VERSION.cmake | 68 + cmake/modules/FindGpgme.cmake | 413 + cmake/modules/FindOpenSSL.cmake | 100 + cmake/modules/FindReadline.cmake | 42 + cmake/modules/FindRpm.cmake | 96 + cmake/modules/FindUdev.cmake | 23 + cmake/modules/FindZsync.cmake | 34 + cmake/modules/FindZypp.cmake | 66 + cmake/modules/Findlibproxy.cmake | 7 + cmake/modules/ZyppCommon.cmake | 151 + cmake/modules/printrpmver.c.in | 8 + doc/CMakeLists.txt | 69 + doc/autodoc/CMakeLists.txt | 74 + doc/autodoc/Doxyfile.cmake | 217 + doc/autoinclude/ApplicationMetada.doc | 15 + doc/autoinclude/CodePitfalls.doc | 60 + doc/autoinclude/EnvironmentVariables.doc | 64 + doc/autoinclude/FeatureTest.doc | 85 + doc/autoinclude/Mainpage.doc | 67 + doc/autoinclude/Modalias.doc | 18 + doc/autoinclude/PatternPackages.doc | 95 + doc/autoinclude/Plugin-Commit.doc | 115 + doc/autoinclude/Plugin-Repoverification.doc | 34 + doc/autoinclude/Plugin-System.doc | 75 + doc/autoinclude/Plugins.doc | 234 + doc/autoinclude/README | 54 + doc/autoinclude/RepoVariables.doc | 40 + doc/autoinclude/Services.doc | 241 + doc/autoinclude/SolverVendorChange.doc | 86 + doc/autoinclude/Testcases.doc | 121 + doc/autoinclude/Threads.doc | 26 + doc/autoinclude/UserData.doc | 17 + doc/autoinclude/g_BOOST.doc | 12 + doc/autoinclude/g_LIBSOLV.doc | 7 + doc/autoinclude/g_ZyppHistory.doc | 89 + doc/autoinclude/groups.doc | 28 + .../notes/n_ResPool_nomorenameiter | 71 + doc/locks.5.txt | 153 + doc/zypp-CheckAccessDeleted.1.txt | 39 + doc/zypp-NameReqPrv.1.txt | 72 + libzypp.pc.cmake | 14 + libzypp.spec.cmake | 443 + mkChangelog | 258 + needreboot | 20 + package/libzypp-rpmlint.cmake | 1 + package/libzypp.changes | 13124 ++++++++++++++++ po/CMakeLists.txt | 70 + po/PotfileDiff.sh | 13 + po/PotfileUpadte.sh | 30 + po/af.po | 5963 +++++++ po/ar.po | 6078 +++++++ po/ast.po | 5214 ++++++ po/be.po | 5331 +++++++ po/bg.po | 6119 +++++++ po/bn.po | 5940 +++++++ po/bs.po | 5855 +++++++ po/ca.po | 6562 ++++++++ po/cs.po | 6306 ++++++++ po/cy.po | 5677 +++++++ po/da.po | 5458 +++++++ po/de.po | 6166 ++++++++ po/el.po | 6079 +++++++ po/en_GB.po | 5909 +++++++ po/es.po | 6178 ++++++++ po/et.po | 5445 +++++++ po/fa.po | 5467 +++++++ po/fi.po | 5745 +++++++ po/fr.po | 6178 ++++++++ po/gl.po | 6412 ++++++++ po/gu.po | 5938 +++++++ po/he.po | 5837 +++++++ po/hi.po | 5859 +++++++ po/hr.po | 5440 +++++++ po/hu.po | 6372 ++++++++ po/id.po | 5993 +++++++ po/it.po | 5568 +++++++ po/ja.po | 5518 +++++++ po/ka.po | 5798 +++++++ po/km.po | 5434 +++++++ po/ko.po | 5688 +++++++ po/ku.po | 5382 +++++++ po/lt.po | 5552 +++++++ po/mk.po | 5586 +++++++ po/mr.po | 5934 +++++++ po/nb.po | 5656 +++++++ po/nl.po | 5639 +++++++ po/nn.po | 5270 +++++++ po/pa.po | 5954 +++++++ po/pl.po | 5514 +++++++ po/pt.po | 6223 ++++++++ po/pt_BR.po | 6123 +++++++ po/ro.po | 5479 +++++++ po/ru.po | 5536 +++++++ po/si.po | 5254 +++++++ po/sk.po | 5505 +++++++ po/sl.po | 6067 +++++++ po/sr.po | 5617 +++++++ po/sv.po | 5758 +++++++ po/ta.po | 5951 +++++++ po/th.po | 5437 +++++++ po/tr.po | 6712 ++++++++ po/uk.po | 5698 +++++++ po/vi.po | 5233 ++++++ po/wa.po | 5724 +++++++ po/xh.po | 5969 +++++++ po/zh_CN.po | 5489 +++++++ po/zh_TW.po | 5484 +++++++ po/zu.po | 5964 +++++++ po/zypp.pot | 5171 ++++++ shared/CMakeLists.txt | 14 + shared/commit/CommitMessages.cc | 463 + shared/commit/CommitMessages.h | 212 + shared/tvm/tvmsettings.cc | 1 + shared/tvm/tvmsettings.h | 70 + systemCheck | 13 + tests/CMakeLists.txt | 20 + tests/README | 29 + .../11.0-update/repodata/deltainfo.xml.gz | Bin 0 -> 206608 bytes .../data/11.0-update/repodata/primary.xml.gz | Bin 0 -> 726875 bytes tests/data/11.0-update/repodata/repomd.xml | 33 + .../data/11.0-update/repodata/repomd.xml.asc | 7 + .../data/11.0-update/repodata/repomd.xml.key | 37 + .../11.0-update/repodata/updateinfo.xml.gz | Bin 0 -> 62833 bytes .../data/Mirrorlist/remote-site/metalink.xml | 34 + tests/data/Mirrorlist/remote-site/mirrors.txt | 5 + .../OBS_zypp_svn-11.1/repodata/primary.xml.gz | Bin 0 -> 9633 bytes .../OBS_zypp_svn-11.1/repodata/repomd.xml | 21 + .../OBS_zypp_svn-11.1/repodata/repomd.xml.asc | 7 + .../OBS_zypp_svn-11.1/repodata/repomd.xml.key | 19 + tests/data/PoolReuseIds/SeqA/SEQA.repo | 28 + .../data/PoolReuseIds/SeqA/zypp-control.yaml | 35 + tests/data/PoolReuseIds/SeqB/SeqB.repo | 28 + .../data/PoolReuseIds/SeqB/zypp-control.yaml | 35 + tests/data/TCNamespaceRecommends/@System.repo | 21 + tests/data/TCNamespaceRecommends/update.repo | 37 + .../TCNamespaceRecommends/zypp-control.yaml | 46 + tests/data/TCSelectable/@System.repo | 27 + tests/data/TCSelectable/RepoHIGH.repo | 31 + tests/data/TCSelectable/RepoLOW.repo | 35 + tests/data/TCSelectable/RepoMID.repo | 31 + tests/data/TCSelectable/RepoSRC.repo | 13 + tests/data/TCSelectable/zypp-control.yaml | 70 + tests/data/TCWhatObsoletes/@System.repo | 26 + tests/data/TCWhatObsoletes/zypp-control.yaml | 36 + tests/data/TCdup/@System.repo | 31 + tests/data/TCdup/update.repo | 20 + tests/data/TCdup/zypp-control.yaml | 46 + tests/data/dummywebroot/Readme | 3 + .../data/lighttpdconf/conf.d/access_log.conf | 27 + tests/data/lighttpdconf/conf.d/auth.conf | 27 + tests/data/lighttpdconf/conf.d/compress.conf | 31 + tests/data/lighttpdconf/conf.d/debug.conf | 49 + .../data/lighttpdconf/conf.d/dirlisting.conf | 55 + tests/data/lighttpdconf/conf.d/expire.conf | 22 + tests/data/lighttpdconf/conf.d/fastcgi.conf | 20 + tests/data/lighttpdconf/conf.d/maybessl.sh | 7 + tests/data/lighttpdconf/conf.d/mime.conf | 594 + tests/data/lighttpdconf/lighttpd.conf | 448 + tests/data/nginxconf/mime.types | 95 + tests/data/nginxconf/nginx.conf | 104 + tests/data/nginxconf/nossl.conf | 0 tests/data/nginxconf/ssl.conf | 2 + .../repodata/primary.xml.gz | Bin 0 -> 17674 bytes .../obs_virtualbox_11_1/repodata/repomd.xml | 21 + .../repodata/repomd.xml.asc | 7 + .../repodata/repomd.xml.key | 20 + tests/data/openSUSE-11.1/content | 122 + .../gpg-pubkey-0dfb3188-41ed929b.asc | 17 + .../gpg-pubkey-307e3d54-481f30aa.asc | 13 + .../gpg-pubkey-3d25d3d9-36e12d04.asc | 30 + .../gpg-pubkey-56b4177a-47965b33.asc | 19 + .../gpg-pubkey-7e2e3b05-4816488f.asc | 20 + .../gpg-pubkey-9c800aca-481f343a.asc | 37 + .../gpg-pubkey-a1912208-446a0899.asc | 31 + tests/data/openSUSE-11.1/media.1/media | 3 + tests/data/openSUSE-11.1/media.1/products | 1 + tests/data/openSUSE-11.1/media.1/products.asc | 7 + tests/data/openSUSE-11.1/media.1/products.key | 19 + .../setup/descr/dvd-11.1-46.1.x86_64.pat.gz | Bin 0 -> 155178 bytes .../descr/non_oss-11.1-46.1.x86_64.pat.gz | Bin 0 -> 3831 bytes .../suse/setup/descr/packages.DU.gz | Bin 0 -> 147899 bytes .../suse/setup/descr/packages.cs.gz | Bin 0 -> 401506 bytes .../suse/setup/descr/packages.en.gz | Bin 0 -> 401472 bytes .../suse/setup/descr/packages.gz | Bin 0 -> 618996 bytes .../openSUSE-11.1/suse/setup/descr/patterns | 2 + tests/data/vsftpconf/vsftpd.conf | 101 + tests/data/webconf/ssl/ca/ca.crt | 32 + tests/data/webconf/ssl/ca/ca.key | 51 + tests/data/webconf/ssl/certstore/7dd4d2a5.0 | 1 + tests/data/webconf/ssl/certstore/ca.pem | 32 + tests/data/webconf/ssl/openssl.cnf | 25 + tests/data/webconf/ssl/server.crt | 30 + tests/data/webconf/ssl/server.csr | 28 + tests/data/webconf/ssl/server.key | 51 + tests/data/webconf/ssl/server.pem | 81 + tests/lib/CMakeLists.txt | 44 + tests/lib/FtpServer.cc | 379 + tests/lib/FtpServer.h | 86 + tests/lib/TestSetup.h | 377 + tests/lib/TestTools.h | 29 + tests/lib/WebServer.cc | 590 + tests/lib/WebServer.h | 150 + tests/media/CMakeLists.txt | 3 + tests/media/CredentialFileReader_test.cc | 39 + tests/media/CredentialManager_test.cc | 113 + tests/media/MediaProducts_test.cc | 9 + tests/media/MetaLinkParser_test.cc | 76 + tests/media/data/credentials.cat | 24 + tests/media/data/credentials.d/cred1 | 2 + .../data/openSUSE-11.3-NET-i586.iso.meta4 | 602 + .../data/openSUSE-11.3-NET-i586.iso.metalink | 607 + tests/media/data/other.xml.gz.meta4 | 634 + tests/media/file_exists_test.cc | 130 + tests/media/media1_test.cc | 39 + tests/media/media2_test.cc | 153 + tests/media/media3_test.cc | 159 + tests/media/media4_test.cc | 102 + tests/media/metalink/metalink.dockerfile | 38 + tests/media/mymediaverifier.h | 65 + tests/media/throw_if_not_exists_test.cc | 37 + tests/parser/CMakeLists.txt | 7 + tests/parser/HistoryLogReader_test.cc | 40 + tests/parser/HistoryLogReader_test.dat | 14 + tests/parser/ProductFileReader_test.cc | 47 + tests/parser/ProductFileReader_test.dat | 61 + tests/parser/RepoFileReader_test.cc | 58 + tests/parser/RepoindexFileReader_test.cc | 69 + tests/parser/inifile/CMakeLists.txt | 2 + tests/parser/inifile/data/1.ini | 54 + tests/parser/inifile/data/2.ini | 12 + tests/parser/inifile/inidict_test.cc | 57 + tests/parser/inifile/iniparser_test.cc | 84 + tests/parser/yum/CMakeLists.txt | 1 + tests/parser/yum/RepomdFileReader_test.cc | 98 + tests/parser/yum/data/repomd-1.xml | 39 + tests/parser/yum/data/repomd-1.xml.solution | 17 + tests/repo/CMakeLists.txt | 20 + tests/repo/DUdata_test.cc | 112 + tests/repo/ExtendedMetadata_test.cc | 236 + tests/repo/MirrorList_test.cc | 33 + tests/repo/PluginServices_test.cc | 52 + .../repodata/CHECKSUM-license-prod.tar.gz | Bin 0 -> 373 bytes .../repo/repodata/CHECKSUM-license.tar.gz | Bin 0 -> 384 bytes .../RepoLicense/repo/repodata/license.de.txt | 1 + .../RepoLicense/repo/repodata/license.fr.txt | 1 + .../RepoLicense/repo/repodata/license.txt | 1 + .../repo/repodata/no-acceptance-needed | 0 .../repo/RepoLicense/repo/repodata/repomd.xml | 11 + tests/repo/RepoLicense_test.cc | 48 + .../signed_repo/repodata/repomd.xml | 3 + .../signed_repo/repodata/repomd.xml.asc | 9 + .../signed_repo/repodata/repomd.xml.key | Bin 0 -> 363 bytes .../unknownkey_repo/repodata/repomd.xml | 3 + .../unknownkey_repo/repodata/repomd.xml.asc | 9 + .../unsigned_repo/repodata/repomd.xml | 3 + .../wrongsig_repo/repodata/repomd.xml | 4 + .../wrongsig_repo/repodata/repomd.xml.asc | 9 + .../wrongsig_repo/repodata/repomd.xml.key | Bin 0 -> 363 bytes tests/repo/RepoSigcheck_test.cc | 375 + tests/repo/RepoVariables_test.cc | 251 + tests/repo/susetags/CMakeLists.txt | 2 + tests/repo/susetags/Downloader_test.cc | 165 + .../data/addon_in_subdir/media.1/build | 1 + .../addon_in_subdir/media.1/directory.yast | 6 + .../data/addon_in_subdir/media.1/media | 3 + .../data/addon_in_subdir/media.1/products | 1 + .../data/addon_in_subdir/updates/SHA1SUMS | 2 + .../data/addon_in_subdir/updates/content | 19 + .../data/addon_in_subdir/updates/content.asc | 7 + .../data/addon_in_subdir/updates/content.key | 439 + .../addon_in_subdir/updates/directory.yast | 2 + .../addon_in_subdir/updates/license.tar.gz | Bin 0 -> 45 bytes .../updates/suse/i586/SHA1SUMS | 1 + .../updates/suse/setup/descr/SHA1SUMS | 4 + .../updates/suse/setup/descr/directory.yast | 4 + .../updates/suse/setup/descr/packages | 63 + .../updates/suse/setup/descr/packages.DU | 58 + .../updates/suse/setup/descr/packages.en | 20 + tests/repo/susetags/data/dudata/repo/content | 2 + .../susetags/data/dudata/repo/media.1/media | 3 + .../dudata/repo/suse/setup/descr/packages | 8 + .../dudata/repo/suse/setup/descr/packages.DU | 16 + .../repo/susetags/data/dudata/system/content | 2 + .../susetags/data/dudata/system/media.1/media | 3 + .../dudata/system/suse/setup/descr/packages | 4 + .../system/suse/setup/descr/packages.DU | 10 + .../susetags/data/shared_attributes/content | 30 + .../suse/setup/descr/packages | 32 + .../suse/setup/descr/packages.DU | 7 + .../suse/setup/descr/packages.en | 7 + .../data/stable-x86-subset-gz/content | 42 + .../data/stable-x86-subset-gz/content.asc | Bin 0 -> 72 bytes .../data/stable-x86-subset-gz/content.key | 135 + .../data/stable-x86-subset-gz/control.xml | 793 + .../gpg-pubkey-0dfb3188-41ed929b.asc | 17 + .../gpg-pubkey-307e3d54-44201d5d.asc | 13 + .../gpg-pubkey-3d25d3d9-36e12d04.asc | 30 + .../gpg-pubkey-7e2e3b05-44748aba.asc | 20 + .../gpg-pubkey-9c800aca-40d8063e.asc | 37 + .../gpg-pubkey-a1912208-446a0899.asc | 31 + .../stable-x86-subset-gz/installation.xml | 109 + .../data/stable-x86-subset-gz/license.tar.gz | Bin 0 -> 45 bytes .../media.1/directory.yast | 6 + .../stable-x86-subset-gz/media.1/info.txt | 38 + .../data/stable-x86-subset-gz/media.1/media | 3 + .../stable-x86-subset-gz/media.1/products | 1 + .../stable-x86-subset-gz/media.1/products.asc | 7 + .../stable-x86-subset-gz/media.1/products.key | 37 + .../setup/descr/kde-10.3-71.noarch.pat.gz | Bin 0 -> 4692 bytes .../suse/setup/descr/packages.DU.gz | Bin 0 -> 4491 bytes .../suse/setup/descr/packages.en.gz | Bin 0 -> 408 bytes .../suse/setup/descr/packages.es.gz | Bin 0 -> 480 bytes .../suse/setup/descr/packages.gz | Bin 0 -> 2438 bytes .../suse/setup/descr/patterns.gz | Bin 0 -> 45 bytes .../susetags/data/stable-x86-subset/content | 42 + .../data/stable-x86-subset/content.asc | Bin 0 -> 72 bytes .../data/stable-x86-subset/content.key | 135 + .../data/stable-x86-subset/control.xml | 793 + .../gpg-pubkey-0dfb3188-41ed929b.asc | 17 + .../gpg-pubkey-307e3d54-44201d5d.asc | 13 + .../gpg-pubkey-3d25d3d9-36e12d04.asc | 30 + .../gpg-pubkey-7e2e3b05-44748aba.asc | 20 + .../gpg-pubkey-9c800aca-40d8063e.asc | 37 + .../gpg-pubkey-a1912208-446a0899.asc | 31 + .../data/stable-x86-subset/installation.xml | 109 + .../data/stable-x86-subset/license.tar.gz | Bin 0 -> 45 bytes .../stable-x86-subset/media.1/directory.yast | 6 + .../data/stable-x86-subset/media.1/info.txt | 38 + .../data/stable-x86-subset/media.1/media | 3 + .../data/stable-x86-subset/media.1/products | 1 + .../stable-x86-subset/media.1/products.asc | 7 + .../stable-x86-subset/media.1/products.key | 37 + .../suse/setup/descr/kde-10.3-71.noarch.pat | 178 + .../suse/setup/descr/packages | 512 + .../suse/setup/descr/packages.DU | 498 + .../suse/setup/descr/packages.en | 47 + .../suse/setup/descr/packages.es | 47 + .../suse/setup/descr/patterns | 2 + tests/repo/yum/CMakeLists.txt | 2 + tests/repo/yum/YUMDownloader_test.cc | 81 + .../repodata/filelists.xml.gz | Bin 0 -> 4344 bytes .../10.2-updates-subset/repodata/other.xml.gz | Bin 0 -> 20305 bytes .../repodata/patch-fetchmsttfonts.sh-2333.xml | 295 + .../repodata/patch-flash-player-2359.xml | 71 + .../repodata/patch-glabels-2348.xml | 81 + .../repodata/patch-gv-2350.xml | 111 + .../repodata/patch-openssl-2349.xml | 297 + .../repodata/patch-tar-2351.xml | 114 + .../10.2-updates-subset/repodata/patches.xml | 27 + .../repodata/primary.xml.gz | Bin 0 -> 11779 bytes .../10.2-updates-subset/repodata/repomd.xml | 27 + .../repodata/repomd.xml.asc | 7 + .../repodata/repomd.xml.key | 24 + .../yum/data/ZCHUNK/repodata/filelists.xml.gz | 0 .../data/ZCHUNK/repodata/filelists.xml.zck | 0 .../yum/data/ZCHUNK/repodata/other.xml.gz | 0 .../yum/data/ZCHUNK/repodata/other.xml.zck | 0 .../yum/data/ZCHUNK/repodata/patterns.xml.gz | 0 .../yum/data/ZCHUNK/repodata/primary.xml.gz | 0 .../yum/data/ZCHUNK/repodata/primary.xml.zck | 0 .../repo/yum/data/ZCHUNK/repodata/repomd.xml | 70 + .../yum/data/ZCHUNK/repodata/repomd.xml.asc | Bin 0 -> 326 bytes .../yum/data/ZCHUNK/repodata/repomd.xml.key | 30 + .../data/extensions/repodata/filelists.xml.gz | Bin 0 -> 284 bytes .../yum/data/extensions/repodata/other.xml.gz | Bin 0 -> 211 bytes .../data/extensions/repodata/primary.xml.gz | Bin 0 -> 901 bytes .../yum/data/extensions/repodata/repomd.xml | 44 + .../data/extensions/repodata/susedata.xml.gz | Bin 0 -> 481 bytes .../data/extensions/repodata/suseinfo.xml.gz | Bin 0 -> 66 bytes tests/sat/BlacklistedPool/@System.repo | 10 + tests/sat/BlacklistedPool/Repo.repo | 34 + tests/sat/BlacklistedPool/zypp-control.yaml | 43 + tests/sat/Blacklisted_test.cc | 82 + tests/sat/CMakeLists.txt | 17 + tests/sat/IdString_test.cc | 59 + tests/sat/LookupAttr_test.cc | 240 + tests/sat/Map_test.cc | 68 + tests/sat/Pool_test.cc | 100 + tests/sat/Queue_test.cc | 51 + tests/sat/SolvParsing_test.cc | 131 + tests/sat/SolvableSpec_test.cc | 112 + tests/sat/Solvable_test.cc | 215 + tests/sat/WhatObsoletes_test.cc | 35 + tests/sat/WhatProvides_test.cc | 62 + tests/zypp/Arch_test.cc | 79 + tests/zypp/CMakeLists.txt | 87 + tests/zypp/Capabilities_test.cc | 192 + tests/zypp/CheckSum_test.cc | 53 + tests/zypp/ContentType_test.cc | 66 + tests/zypp/CpeId_test.cc | 452 + tests/zypp/Date_test.cc | 10 + tests/zypp/Deltarpm_test.cc | 70 + tests/zypp/Digest_test.cc | 35 + tests/zypp/DrunkenBishop_test.cc | 90 + tests/zypp/Dup_test.cc | 67 + tests/zypp/Edition_test.cc | 38 + tests/zypp/ExtendedPool_test.cc | 101 + tests/zypp/Fetcher_test.cc | 376 + tests/zypp/FileChecker_test.cc | 89 + tests/zypp/Flags_test.cc | 92 + tests/zypp/GZStream_test.cc | 80 + tests/zypp/InstanceId_test.cc | 46 + tests/zypp/KeyRingTestReceiver.h | 142 + tests/zypp/KeyRing_test.cc | 318 + tests/zypp/Locale_test.cc | 173 + tests/zypp/Locks_test.cc | 118 + tests/zypp/MediaSetAccess_test.cc | 329 + tests/zypp/PathInfo_test.cc | 213 + tests/zypp/Pathname_test.cc | 166 + tests/zypp/PluginFrame_test.cc | 188 + tests/zypp/PoolQueryCC_test.cc | 126 + tests/zypp/PoolQuery_test.cc | 989 ++ tests/zypp/ProgressData_test.cc | 129 + tests/zypp/Proxy_test.cc | 19 + tests/zypp/PtrTypes_test.cc | 152 + tests/zypp/PublicKey_test.cc | 54 + tests/zypp/PurgeKernels_test.cc | 396 + tests/zypp/RWPtr_test.cc | 83 + tests/zypp/RepoInfo_test.cc | 48 + tests/zypp/RepoManager_test.cc | 288 + tests/zypp/RepoStatus_test.cc | 56 + tests/zypp/ResKind_test.cc | 32 + tests/zypp/ResStatus_test.cc | 243 + tests/zypp/Resolvable_test.cc | 38 + tests/zypp/Resolver_test.cc | 100 + tests/zypp/RpmPkgSigCheck_test.cc | 278 + tests/zypp/Selectable_test.cc | 354 + tests/zypp/SetRelationMixin_test.cc | 142 + tests/zypp/SetTracker_test.cc | 103 + tests/zypp/Signature_test.cc | 29 + tests/zypp/StrMatcher_test.cc | 210 + tests/zypp/StringV_test.cc | 236 + tests/zypp/Target_test.cc | 56 + tests/zypp/Url_test.cc | 318 + tests/zypp/UserData_test.cc | 87 + tests/zypp/Vendor_test.cc | 94 + tests/zypp/ZChunk_test.cc | 33 + tests/zypp/base/CMakeLists.txt | 4 + tests/zypp/base/ExternalProgram_test.cc | 268 + tests/zypp/base/Glob_test.cc | 59 + tests/zypp/base/Glob_test.dat/file | 0 tests/zypp/base/Glob_test.dat/file.xml | 0 tests/zypp/base/Glob_test.dat/file.xml.gz | 0 tests/zypp/base/String_test.cc | 483 + tests/zypp/base/Sysconfig_test.cc | 75 + tests/zypp/base/data/ExternalProgram/echo.sh | 13 + tests/zypp/base/data/Sysconfig/proxy | 51 + tests/zypp/data/Delta/repodata/deltainfo.xml | 17 + tests/zypp/data/Delta/repodata/primary.xml.gz | Bin 0 -> 86272 bytes tests/zypp/data/Delta/repodata/repomd.xml | 33 + tests/zypp/data/Delta/repodata/repomd.xml.asc | 43 + tests/zypp/data/Delta/repodata/repomd.xml.key | 43 + .../data/Delta/repodata/updateinfo.xml.gz | Bin 0 -> 4657 bytes .../remote-site/baseindex/directory.yast | 2 + .../remote-site/baseindex/subdir1/SHA1SUMS | 2 + .../baseindex/subdir1/SHA1SUMS.asc | 7 + .../baseindex/subdir1/SHA1SUMS.key | 49 + .../baseindex/subdir1/directory.yast | 6 + .../baseindex/subdir1/subdir1-file1.txt | 1 + .../baseindex/subdir1/subdir1-file2.txt | 1 + .../remote-site/baseindex/subdir2/SHA1SUMS | 1 + .../baseindex/subdir2/SHA1SUMS.asc | 7 + .../baseindex/subdir2/SHA1SUMS.key | 49 + .../baseindex/subdir2/directory.yast | 5 + .../baseindex/subdir2/subdir2-file1.txt | 1 + .../complexdir-broken/directory.yast | 3 + .../complexdir-broken/subdir1/SHA1SUMS | 2 + .../complexdir-broken/subdir1/SHA1SUMS.asc | 7 + .../complexdir-broken/subdir1/SHA1SUMS.key | 49 + .../complexdir-broken/subdir1/directory.yast | 6 + .../subdir1/subdir1-file1.txt | 1 + .../subdir1/subdir1-file2.txt | 1 + .../complexdir-broken/subdir2/SHA1SUMS | 1 + .../complexdir-broken/subdir2/SHA1SUMS.asc | 7 + .../complexdir-broken/subdir2/SHA1SUMS.key | 49 + .../complexdir-broken/subdir2/directory.yast | 5 + .../subdir2/subdir2-file1.txt | 1 + .../remote-site/complexdir/directory.yast | 2 + .../remote-site/complexdir/subdir1/SHA1SUMS | 2 + .../complexdir/subdir1/SHA1SUMS.asc | 7 + .../complexdir/subdir1/SHA1SUMS.key | 49 + .../complexdir/subdir1/directory.yast | 6 + .../complexdir/subdir1/subdir1-file1.txt | 1 + .../complexdir/subdir1/subdir1-file2.txt | 1 + .../remote-site/complexdir/subdir2/SHA1SUMS | 1 + .../complexdir/subdir2/SHA1SUMS.asc | 7 + .../complexdir/subdir2/SHA1SUMS.key | 49 + .../complexdir/subdir2/directory.yast | 5 + .../complexdir/subdir2/subdir2-file1.txt | 1 + .../contentindex-broken-digest/content | 3 + .../contentindex-broken-digest/content.asc | 7 + .../contentindex-broken-digest/content.key | 49 + .../contentindex-broken-digest/directory.yast | 3 + .../subdir1/directory.yast | 6 + .../subdir1/subdir1-file1.txt | 1 + .../subdir1/subdir1-file2.txt | 1 + .../subdir2/directory.yast | 5 + .../subdir2/subdir2-file1.txt | 1 + .../Fetcher/remote-site/contentindex/content | 3 + .../remote-site/contentindex/content.asc | 7 + .../remote-site/contentindex/content.key | 49 + .../remote-site/contentindex/directory.yast | 2 + .../contentindex/subdir1/directory.yast | 6 + .../contentindex/subdir1/subdir1-file1.txt | 1 + .../contentindex/subdir1/subdir1-file2.txt | 1 + .../contentindex/subdir2/directory.yast | 5 + .../contentindex/subdir2/subdir2-file1.txt | 1 + .../Fetcher/remote-site/diffs/file-1-2.diff | 7 + .../remote-site/diffs/file-1-2.diff.gz | Bin 0 -> 713 bytes .../Fetcher/remote-site/diffs/file-2-3.diff | 36 + .../remote-site/diffs/file-2-3.diff.gz | Bin 0 -> 342 bytes .../Fetcher/remote-site/diffs/file-3-4.diff | 5 + .../remote-site/diffs/file-3-4.diff.gz | Bin 0 -> 711 bytes .../remote-site/diffs/file-4-current.diff | 5 + .../remote-site/diffs/file-4-current.diff.gz | Bin 0 -> 899 bytes .../data/Fetcher/remote-site/directory.yast | 10 + .../zypp/data/Fetcher/remote-site/file-1.txt | 64 + .../zypp/data/Fetcher/remote-site/file-2.txt | 70 + .../zypp/data/Fetcher/remote-site/file-3.txt | 105 + .../zypp/data/Fetcher/remote-site/file-4.txt | 109 + .../data/Fetcher/remote-site/file-current.txt | 113 + .../Fetcher/remote-site/file-current.txt.asc | 98 + .../Fetcher/remote-site/file-current.txt.key | 32 + .../remote-site/images-file-unsigned/content | 143 + .../images-file-unsigned/images/images.xml | 345 + .../Fetcher/remote-site/images-file/content | 143 + .../remote-site/images-file/content.asc | 7 + .../remote-site/images-file/content.key | 49 + .../remote-site/images-file/images/images.xml | 345 + tests/zypp/data/FileChecker/hello.txt | 1 + tests/zypp/data/FileChecker/hello.txt.asc | 7 + tests/zypp/data/FileChecker/hello.txt.key | 214 + tests/zypp/data/FileChecker/hello2.txt | 2 + tests/zypp/data/KeyRing/installkey.gpg | Bin 0 -> 1757 bytes tests/zypp/data/KeyRing/private.asc | 33 + tests/zypp/data/KeyRing/public.asc | 30 + tests/zypp/data/KeyRing/readme.txt | 2 + tests/zypp/data/KeyRing/repomd.xml | 21 + tests/zypp/data/KeyRing/repomd.xml.asc | 7 + tests/zypp/data/KeyRing/repomd.xml.corrupted | 21 + tests/zypp/data/Locks/locks | 1 + tests/zypp/data/PoolQuery/savedqueries | 11 + tests/zypp/data/PoolQueryCC/rxnames.xml | 21 + tests/zypp/data/PublicKey/multikey.asc | 38 + tests/zypp/data/PublicKey/multikey2.asc | 214 + tests/zypp/data/PublicKey/susekey.asc | 37 + .../zypp/data/PurgeKernels/arch/@System.repo | 485 + .../data/PurgeKernels/arch/zypp-control.yaml | 38 + .../PurgeKernels/fancybuildnr/@System.repo | 155 + .../fancybuildnr/zypp-control.yaml | 38 + .../data/PurgeKernels/flavour/@System.repo | 356 + .../PurgeKernels/flavour/zypp-control.yaml | 38 + .../PurgeKernels/kernel-base/@System.repo | 81 + .../kernel-base/zypp-control.yaml | 38 + .../data/PurgeKernels/rckrnl/@System.repo | 34 + .../PurgeKernels/rckrnl/zypp-control.yaml | 38 + .../data/PurgeKernels/rebuild/@System.repo | 86 + .../PurgeKernels/rebuild/zypp-control.yaml | 38 + .../data/PurgeKernels/simple/@System.repo | 350 + .../PurgeKernels/simple/zypp-control.yaml | 38 + .../data/PurgeKernels/withdeps/@System.repo | 223 + .../PurgeKernels/withdeps/zypp-control.yaml | 38 + .../plugin-service-lib-1/services/service | 13 + .../plugin-service-lib-2/services/service | 8 + tests/zypp/data/RepoManager/proprietary.repo | 14 + .../zypp/data/RepoManager/repo/repoindex.xml | 24 + .../data/RepoManager/repos.d/filesharing.repo | 7 + .../RepoManager/repos.d/home:dmacvicar.repo | 7 + .../data/RepoManager/repos.d/proprietary.repo | 5 + tests/zypp/data/RepoManager/repos.d/ruby.repo | 7 + .../RepoManager/second/repo/repoindex.xml | 17 + tests/zypp/data/RpmPkgSigCheck/no.rpm | 0 tests/zypp/data/RpmPkgSigCheck/signed.key | 19 + tests/zypp/data/RpmPkgSigCheck/signed.rpm | Bin 0 -> 6932 bytes .../data/RpmPkgSigCheck/signed_broken.rpm | Bin 0 -> 6933 bytes .../RpmPkgSigCheck/signed_broken_header.rpm | Bin 0 -> 6933 bytes tests/zypp/data/RpmPkgSigCheck/unsigned.rpm | Bin 0 -> 5772 bytes .../data/RpmPkgSigCheck/unsigned_broken.rpm | Bin 0 -> 5773 bytes .../RpmPkgSigCheck/unsigned_broken_header.rpm | Bin 0 -> 5773 bytes tests/zypp/data/Target/product.prod | 36 + tests/zypp/data/Vendor/vendors.d/ati | 3 + tests/zypp/data/Vendor/vendors.d/nvidia | 3 + .../data/mediasetaccess/src1/cd1/dir/file1 | 1 + .../data/mediasetaccess/src1/cd1/dir/file2 | 1 + .../mediasetaccess/src1/cd1/dir/subdir/file | 1 + .../mediasetaccess/src1/cd1/dir/test-big.txt | 15 + .../data/mediasetaccess/src1/cd1/test-big.txt | 29 + .../data/mediasetaccess/src1/cd1/test.txt | 1 + .../data/mediasetaccess/src1/cd1/x.media1 | 0 .../data/mediasetaccess/src1/cd2/test.txt | 1 + .../data/mediasetaccess/src1/cd2/x.mediabad | 1 + .../data/mediasetaccess/src1/cd3/test.txt | 1 + .../data/mediasetaccess/src1/cd3/x.media3 | 0 tests/zypp/data/mediasetaccess/src2/test.txt | 1 + tests/zypp/data/mediasetaccess/src2/x.media | 0 tests/zyppng/CMakeLists.txt | 10 + tests/zyppng/EventLoop_test.cc | 99 + tests/zyppng/IOBuffer_test.cc | 174 + tests/zyppng/Pipelines_test.cc | 380 + tests/zyppng/UnixSignalSource_test.cc | 141 + tests/zyppng/data/downloader/auth-http.meta | 36 + tests/zyppng/data/downloader/auth-https.meta | 36 + tests/zyppng/data/downloader/media.1/media | 3 + .../downloader/primary-deltatemplate.xml.zck | Bin 0 -> 274659 bytes tests/zyppng/data/downloader/primary.xml.zck | Bin 0 -> 274638 bytes .../data/downloader/primary.xml.zck.meta | 22 + tests/zyppng/data/downloader/test.txt | 7595 +++++++++ tests/zyppng/data/downloader/test.txt.meta | 29 + .../data/downloader/test_noblock.txt.meta | 18 + tests/zyppng/data/process/echo.sh | 16 + tests/zyppng/data/provide/cd1/file1 | 1 + tests/zyppng/data/provide/cd1/media.1/media | 3 + tests/zyppng/data/provide/cd2/file2 | 1 + tests/zyppng/data/provide/cd2/media.2/media | 3 + tests/zyppng/data/provide/cd3/file3 | 1 + tests/zyppng/data/provide/cd3/media.3/media | 3 + tests/zyppng/data/provide/cd4/file4 | 1 + tests/zyppng/data/provide/cd4/media.4/media | 3 + tests/zyppng/io/AsyncDataSource_test.cc | 386 + tests/zyppng/io/CMakeLists.txt | 5 + tests/zyppng/io/Process_test.cc | 368 + tests/zyppng/io/UnixSocket_test.cc | 416 + tests/zyppng/media/CMakeLists.txt | 9 + tests/zyppng/media/EvDownloader_test.cc | 699 + .../media/NetworkRequestDispatcher_test.cc | 736 + tests/zyppng/media/Provider_test.cc | 1221 ++ tests/zyppng/rpc/CMakeLists.txt | 3 + tests/zyppng/rpc/StompMessageStream_test.cc | 441 + tools/CMakeLists.txt | 60 + tools/CalculateReusableBlocks.cc | 86 + tools/DiskUsageCounter.cc | 54 + tools/DownloadFiles.cc | 259 + tools/DumpSelectable.cc | 170 + tools/ProvideSignedDirectory.cc | 55 + tools/ScanTwHistory | 32 + tools/ToolScanRepos.cc | 136 + tools/argparse.h | 340 + tools/migrate-sources/CMakeLists.txt | 9 + tools/migrate-sources/migrate-sources.cc | 185 + tools/patch_find_bug.cc | 113 + tools/percent-encode.cc | 38 + tools/refresh-ng/CMakeLists.txt | 14 + tools/refresh-ng/main.cc | 214 + tools/refresh-ng/output.h | 269 + tools/repomirror/CMakeLists.txt | 16 + tools/repomirror/main.cc | 405 + tools/repomirror/output.h | 295 + tools/zypp-CheckAccessDeleted.cc | 176 + tools/zypp-NameReqPrv.cc | 529 + tools/zypp-cpeid.cc | 66 + tools/zypp-install.cc | 270 + tools/zypp-list.cc | 170 + tools/zypp-media-chksum/CMakeLists.txt | 34 + tools/zypp-media-chksum/main.cc | 138 + tools/zypp-media-copy/CMakeLists.txt | 34 + tools/zypp-media-copy/main.cc | 147 + tools/zypp-media-dir/CMakeLists.txt | 36 + tools/zypp-media-dir/dirprovider.cc | 135 + tools/zypp-media-dir/dirprovider.h | 27 + tools/zypp-media-dir/main.cc | 28 + tools/zypp-media-disc/CMakeLists.txt | 44 + tools/zypp-media-disc/discprovider.cc | 404 + tools/zypp-media-disc/discprovider.h | 31 + tools/zypp-media-disc/main.cc | 27 + tools/zypp-media-disk/CMakeLists.txt | 36 + tools/zypp-media-disk/diskprovider.cc | 363 + tools/zypp-media-disk/diskprovider.h | 25 + tools/zypp-media-disk/main.cc | 26 + tools/zypp-media-http/CMakeLists.txt | 37 + tools/zypp-media-http/main.cc | 21 + tools/zypp-media-http/networkprovider.cc | 494 + tools/zypp-media-http/networkprovider.h | 80 + tools/zypp-media-iso/CMakeLists.txt | 51 + tools/zypp-media-iso/isoprovider.cc | 399 + tools/zypp-media-iso/isoprovider.h | 42 + tools/zypp-media-iso/main.cc | 27 + tools/zypp-media-nfs/CMakeLists.txt | 36 + tools/zypp-media-nfs/main.cc | 23 + tools/zypp-media-nfs/nfsprovider.cc | 262 + tools/zypp-media-nfs/nfsprovider.h | 25 + tools/zypp-media-smb/CMakeLists.txt | 36 + tools/zypp-media-smb/main.cc | 26 + tools/zypp-media-smb/smbprovider.cc | 342 + tools/zypp-media-smb/smbprovider.h | 24 + tools/zypp-media-tvm/CMakeLists.txt | 34 + tools/zypp-media-tvm/main.cc | 23 + tools/zypp-media-tvm/testvmprovider.cc | 344 + tools/zypp-media-tvm/testvmprovider.h | 41 + tools/zypp-pubkey.cc | 146 + tools/zypp-rpm/BinHeader.cc | 432 + tools/zypp-rpm/BinHeader.h | 156 + tools/zypp-rpm/CMakeLists.txt | 50 + tools/zypp-rpm/errorcodes.h | 35 + tools/zypp-rpm/main.cc | 1033 ++ tools/zypp-runpurge.cc | 83 + zypp-core/APIConfig.h.in | 22 + zypp-core/AutoDispose.h | 346 + zypp-core/ByteArray.h | 59 + zypp-core/ByteCount.cc | 105 + zypp-core/ByteCount.h | 167 + zypp-core/CMakeLists.txt | 449 + zypp-core/CheckSum.cc | 216 + zypp-core/CheckSum.h | 139 + zypp-core/Date.cc | 247 + zypp-core/Date.h | 271 + zypp-core/Digest.cc | 380 + zypp-core/Digest.h | 176 + zypp-core/ExternalProgram.cc | 570 + zypp-core/ExternalProgram.h | 327 + zypp-core/Globals.h | 120 + zypp-core/KVMap | 1 + zypp-core/ManagedFile.h | 32 + zypp-core/OnMediaLocation | 1 + zypp-core/Pathname.cc | 326 + zypp-core/Pathname.h | 222 + zypp-core/ShutdownLock.cc | 43 + zypp-core/ShutdownLock_p.h | 45 + zypp-core/TriBool.h | 78 + zypp-core/Url.cc | 899 ++ zypp-core/Url.h | 871 + zypp-core/UserData.h | 237 + zypp-core/base/CleanerThread.cc | 85 + zypp-core/base/CleanerThread_p.h | 28 + zypp-core/base/DefaultIntegral | 1 + zypp-core/base/DtorReset | 1 + zypp-core/base/Easy.h | 116 + zypp-core/base/EnumClass.h | 91 + zypp-core/base/Errno.h | 65 + zypp-core/base/Exception.cc | 229 + zypp-core/base/Exception.h | 472 + zypp-core/base/ExternalDataSource.cc | 147 + zypp-core/base/ExternalDataSource.h | 130 + zypp-core/base/FileStreamBuf | 1 + zypp-core/base/Flags.h | 199 + zypp-core/base/Function.h | 51 + zypp-core/base/Gettext.cc | 63 + zypp-core/base/Gettext.h | 67 + zypp-core/base/GzStream | 1 + zypp-core/base/Hash.h | 50 + zypp-core/base/IOStream.cc | 158 + zypp-core/base/IOStream.h | 213 + zypp-core/base/IOTools.cc | 187 + zypp-core/base/IOTools.h | 95 + zypp-core/base/InputStream | 1 + zypp-core/base/Iterable.h | 97 + zypp-core/base/Iterator.h | 297 + zypp-core/base/LogControl.cc | 977 ++ zypp-core/base/LogControl.h | 229 + zypp-core/base/LogTools.h | 536 + zypp-core/base/Logger.h | 192 + zypp-core/base/NonCopyable.h | 34 + zypp-core/base/ProfilingFormater.cc | 60 + zypp-core/base/ProfilingFormater.h | 44 + zypp-core/base/ProvideNumericId | 1 + zypp-core/base/PtrTypes.h | 647 + zypp-core/base/ReferenceCounted.cc | 58 + zypp-core/base/ReferenceCounted.h | 144 + zypp-core/base/Regex.cc | 130 + zypp-core/base/Regex.h | 193 + zypp-core/base/SimpleStreambuf | 1 + zypp-core/base/String.cc | 523 + zypp-core/base/String.h | 1106 ++ zypp-core/base/StringV.cc | 188 + zypp-core/base/StringV.h | 293 + zypp-core/base/Unit.cc | 42 + zypp-core/base/Unit.h | 106 + zypp-core/base/UserRequestException | 1 + zypp-core/base/Xml.cc | 20 + zypp-core/base/Xml.h | 225 + zypp-core/base/ZckStream | 1 + zypp-core/base/defaultintegral.h | 104 + zypp-core/base/dtorreset.h | 85 + zypp-core/base/fXstream | 1 + zypp-core/base/filestreambuf.cc | 62 + zypp-core/base/filestreambuf.h | 71 + zypp-core/base/fxstream.h | 96 + zypp-core/base/gzstream.cc | 210 + zypp-core/base/gzstream.h | 168 + zypp-core/base/inputstream.cc | 174 + zypp-core/base/inputstream.h | 144 + zypp-core/base/providenumericid.h | 100 + zypp-core/base/simplestreambuf.h | 218 + zypp-core/base/userrequestexception.cc | 65 + zypp-core/base/userrequestexception.h | 107 + zypp-core/base/zckstream.cc | 163 + zypp-core/base/zckstream.h | 77 + zypp-core/fs/PathInfo.cc | 1259 ++ zypp-core/fs/PathInfo.h | 813 + zypp-core/fs/TmpPath.cc | 332 + zypp-core/fs/TmpPath.h | 220 + zypp-core/fs/WatchFile | 1 + zypp-core/fs/watchfile.h | 110 + zypp-core/kvmap.h | 205 + zypp-core/onmedialocation.cc | 164 + zypp-core/onmedialocation.h | 137 + zypp-core/parser/IniDict | 1 + zypp-core/parser/IniParser | 1 + zypp-core/parser/ParseException | 1 + zypp-core/parser/Sysconfig | 1 + zypp-core/parser/inidict.cc | 186 + zypp-core/parser/inidict.h | 172 + zypp-core/parser/iniparser.cc | 148 + zypp-core/parser/iniparser.h | 96 + zypp-core/parser/parseexception.cc | 65 + zypp-core/parser/parseexception.h | 53 + zypp-core/parser/sysconfig.cc | 155 + zypp-core/parser/sysconfig.h | 72 + zypp-core/parser/xml/XmlEscape.cc | 119 + zypp-core/parser/xml/XmlEscape.h | 61 + zypp-core/rpc/PluginFrame.cc | 496 + zypp-core/rpc/PluginFrame.h | 297 + zypp-core/rpc/PluginFrameException.cc | 41 + zypp-core/rpc/PluginFrameException.h | 40 + zypp-core/ui/ProgressData | 1 + zypp-core/ui/progressdata.cc | 159 + zypp-core/ui/progressdata.h | 428 + zypp-core/url/UrlBase.cc | 1458 ++ zypp-core/url/UrlBase.h | 1103 ++ zypp-core/url/UrlException.h | 150 + zypp-core/url/UrlUtils.cc | 326 + zypp-core/url/UrlUtils.h | 261 + zypp-core/zyppng/async/AsyncOp | 1 + zypp-core/zyppng/async/asyncop.h | 309 + zypp-core/zyppng/base/AbstractEventSource | 1 + zypp-core/zyppng/base/AutoDisconnect | 1 + zypp-core/zyppng/base/Base | 1 + zypp-core/zyppng/base/EventDispatcher | 1 + zypp-core/zyppng/base/EventLoop | 1 + zypp-core/zyppng/base/Signals | 1 + zypp-core/zyppng/base/SocketNotifier | 1 + zypp-core/zyppng/base/Timer | 1 + zypp-core/zyppng/base/UnixSignalSource | 1 + zypp-core/zyppng/base/abstracteventsource.cc | 62 + zypp-core/zyppng/base/abstracteventsource.h | 92 + zypp-core/zyppng/base/autodisconnect.h | 35 + zypp-core/zyppng/base/base.cc | 76 + zypp-core/zyppng/base/base.h | 196 + zypp-core/zyppng/base/eventdispatcher.h | 200 + zypp-core/zyppng/base/eventdispatcher_glib.cc | 605 + zypp-core/zyppng/base/eventloop.h | 76 + zypp-core/zyppng/base/eventloop_glib.cc | 47 + zypp-core/zyppng/base/linuxhelpers.cc | 92 + .../base/private/abstracteventsource_p.h | 34 + zypp-core/zyppng/base/private/base_p.h | 31 + .../base/private/eventdispatcher_glib_p.h | 104 + .../zyppng/base/private/eventloop_glib_p.h | 25 + .../zyppng/base/private/linuxhelpers_p.h | 87 + zypp-core/zyppng/base/private/threaddata_p.h | 45 + zypp-core/zyppng/base/signals.h | 377 + zypp-core/zyppng/base/socketnotifier.cc | 92 + zypp-core/zyppng/base/socketnotifier.h | 124 + zypp-core/zyppng/base/statemachine.h | 608 + zypp-core/zyppng/base/threaddata.cc | 64 + zypp-core/zyppng/base/timer.cc | 192 + zypp-core/zyppng/base/timer.h | 146 + zypp-core/zyppng/base/unixsignalsource.cpp | 156 + zypp-core/zyppng/base/unixsignalsource.h | 36 + zypp-core/zyppng/base/zyppglobal.h | 228 + zypp-core/zyppng/core/ByteArray | 1 + zypp-core/zyppng/core/Env | 1 + zypp-core/zyppng/core/IdString | 1 + zypp-core/zyppng/core/String | 1 + zypp-core/zyppng/core/Url | 1 + zypp-core/zyppng/core/bytearray.h | 25 + zypp-core/zyppng/core/env.h | 21 + zypp-core/zyppng/core/idstring.h | 21 + zypp-core/zyppng/core/string.h | 107 + zypp-core/zyppng/core/url.h | 18 + zypp-core/zyppng/io/AsyncDataSource | 1 + zypp-core/zyppng/io/IODevice | 1 + zypp-core/zyppng/io/Process | 1 + zypp-core/zyppng/io/SockAddr | 1 + zypp-core/zyppng/io/Socket | 1 + zypp-core/zyppng/io/abstractspawnengine.cc | 214 + zypp-core/zyppng/io/asyncdatasource.cpp | 387 + zypp-core/zyppng/io/asyncdatasource.h | 105 + zypp-core/zyppng/io/forkspawnengine.cc | 631 + zypp-core/zyppng/io/iobuffer.cc | 248 + zypp-core/zyppng/io/iodevice.cc | 411 + zypp-core/zyppng/io/iodevice.h | 213 + .../zyppng/io/private/abstractspawnengine_p.h | 113 + .../zyppng/io/private/asyncdatasource_p.h | 39 + .../zyppng/io/private/forkspawnengine_p.h | 66 + zypp-core/zyppng/io/private/iobuffer_p.h | 64 + zypp-core/zyppng/io/private/iodevice_p.h | 54 + zypp-core/zyppng/io/private/sockaddr_p.h | 19 + zypp-core/zyppng/io/private/socket_p.h | 122 + zypp-core/zyppng/io/process.cpp | 302 + zypp-core/zyppng/io/process.h | 116 + zypp-core/zyppng/io/sockaddr.cpp | 32 + zypp-core/zyppng/io/sockaddr.h | 54 + zypp-core/zyppng/io/socket.cc | 892 ++ zypp-core/zyppng/io/socket.h | 230 + zypp-core/zyppng/meta/FunctionTraits | 1 + zypp-core/zyppng/meta/Functional | 1 + zypp-core/zyppng/meta/TypeTraits | 1 + zypp-core/zyppng/meta/function_traits.h | 77 + zypp-core/zyppng/meta/functional.h | 79 + zypp-core/zyppng/meta/type_traits.h | 135 + zypp-core/zyppng/pipelines/Algorithm | 1 + zypp-core/zyppng/pipelines/AsyncResult | 1 + zypp-core/zyppng/pipelines/Await | 1 + zypp-core/zyppng/pipelines/Expected | 1 + zypp-core/zyppng/pipelines/Lift | 1 + zypp-core/zyppng/pipelines/MTry | 1 + zypp-core/zyppng/pipelines/Redo | 1 + zypp-core/zyppng/pipelines/Transform | 1 + zypp-core/zyppng/pipelines/Wait | 1 + zypp-core/zyppng/pipelines/algorithm.h | 223 + zypp-core/zyppng/pipelines/asyncresult.h | 343 + zypp-core/zyppng/pipelines/await.h | 71 + zypp-core/zyppng/pipelines/expected.h | 716 + zypp-core/zyppng/pipelines/lift.h | 80 + zypp-core/zyppng/pipelines/mtry.h | 68 + zypp-core/zyppng/pipelines/redo.h | 150 + zypp-core/zyppng/pipelines/transform.h | 79 + zypp-core/zyppng/pipelines/wait.h | 138 + zypp-core/zyppng/rpc/stompframestream.cc | 327 + zypp-core/zyppng/rpc/stompframestream.h | 193 + zypp-core/zyppng/thread/AsyncQueue | 1 + zypp-core/zyppng/thread/Wakeup | 1 + zypp-core/zyppng/thread/asyncqueue.cc | 111 + zypp-core/zyppng/thread/asyncqueue.h | 171 + .../zyppng/thread/private/asyncqueue_p.h | 26 + zypp-core/zyppng/thread/wakeup.cpp | 44 + zypp-core/zyppng/thread/wakeup.h | 58 + zypp-core/zyppng/ui/ProgressObserver | 1 + zypp-core/zyppng/ui/UserInterface | 1 + zypp-core/zyppng/ui/UserRequest | 1 + zypp-core/zyppng/ui/private/userinterface_p.h | 22 + zypp-core/zyppng/ui/progressobserver.cc | 358 + zypp-core/zyppng/ui/progressobserver.h | 261 + zypp-core/zyppng/ui/userinterface.cc | 32 + zypp-core/zyppng/ui/userinterface.h | 48 + zypp-core/zyppng/ui/userrequest.cc | 119 + zypp-core/zyppng/ui/userrequest.h | 175 + zypp-curl/CMakeLists.txt | 193 + zypp-curl/CurlConfig | 1 + zypp-curl/ProxyInfo | 1 + zypp-curl/TransferSettings | 1 + zypp-curl/auth/CurlAuthData | 1 + zypp-curl/auth/curlauthdata.cc | 129 + zypp-curl/auth/curlauthdata.h | 107 + zypp-curl/curlconfig.cc | 185 + zypp-curl/curlconfig.h | 57 + zypp-curl/curlhelper.cc | 530 + zypp-curl/ng/network/AuthData | 1 + zypp-curl/ng/network/DownloadSpec | 1 + zypp-curl/ng/network/Downloader | 1 + zypp-curl/ng/network/MirrorControl | 1 + zypp-curl/ng/network/NetworkRequestDispatcher | 1 + zypp-curl/ng/network/NetworkRequestError | 1 + zypp-curl/ng/network/Request | 1 + zypp-curl/ng/network/TransferSettings | 1 + zypp-curl/ng/network/authdata.h | 32 + zypp-curl/ng/network/curlmultiparthandler.cc | 728 + zypp-curl/ng/network/curlmultiparthandler.h | 189 + zypp-curl/ng/network/downloader.cc | 421 + zypp-curl/ng/network/downloader.h | 273 + zypp-curl/ng/network/downloadspec.cc | 169 + zypp-curl/ng/network/downloadspec.h | 116 + zypp-curl/ng/network/mirrorcontrol.cc | 302 + .../ng/network/networkrequestdispatcher.cc | 547 + .../ng/network/networkrequestdispatcher.h | 193 + zypp-curl/ng/network/networkrequesterror.cc | 321 + zypp-curl/ng/network/networkrequesterror.h | 108 + zypp-curl/ng/network/private/downloader_p.h | 117 + .../network/private/downloaderstates/base_p.h | 119 + .../downloaderstates/basicdownloader_p.cc | 211 + .../downloaderstates/basicdownloader_p.h | 71 + .../private/downloaderstates/detectmeta_p.cc | 119 + .../private/downloaderstates/detectmeta_p.h | 81 + .../private/downloaderstates/final_p.cc | 23 + .../private/downloaderstates/final_p.h | 38 + .../private/downloaderstates/initial_p.cc | 68 + .../private/downloaderstates/initial_p.h | 71 + .../private/downloaderstates/metalink_p.cc | 164 + .../private/downloaderstates/metalink_p.h | 69 + .../downloaderstates/metalinkinfo_p.cc | 123 + .../private/downloaderstates/metalinkinfo_p.h | 68 + .../downloaderstates/mirrorhandling_p.cc | 70 + .../downloaderstates/mirrorhandling_p.h | 70 + .../private/downloaderstates/normal_p.cc | 35 + .../private/downloaderstates/normal_p.h | 47 + .../downloaderstates/preparemulti_p.cc | 247 + .../private/downloaderstates/preparemulti_p.h | 95 + .../downloaderstates/rangedownloader_p.cc | 441 + .../downloaderstates/rangedownloader_p.h | 93 + .../network/private/downloaderstates/zck_p.cc | 296 + .../network/private/downloaderstates/zck_p.h | 85 + zypp-curl/ng/network/private/mediadebug_p.h | 45 + .../ng/network/private/mirrorcontrol_p.h | 132 + .../private/networkrequestdispatcher_p.h | 77 + .../network/private/networkrequesterror_p.h | 41 + zypp-curl/ng/network/private/request_p.h | 192 + zypp-curl/ng/network/request.cc | 1056 ++ zypp-curl/ng/network/request.h | 293 + zypp-curl/ng/network/transfersettings.h | 23 + zypp-curl/parser/MediaBlockList | 1 + zypp-curl/parser/MetaLinkParser | 1 + zypp-curl/parser/ZsyncParser | 1 + zypp-curl/parser/mediablocklist.cc | 1104 ++ zypp-curl/parser/mediablocklist.h | 164 + zypp-curl/parser/metadatahelper.cc | 59 + zypp-curl/parser/metadatahelper.h | 38 + zypp-curl/parser/metalinkparser.cc | 537 + zypp-curl/parser/metalinkparser.h | 88 + zypp-curl/parser/zsyncparser.cc | 203 + zypp-curl/parser/zsyncparser.h | 56 + zypp-curl/private/curlhelper_p.h | 109 + zypp-curl/proxyinfo.cc | 60 + zypp-curl/proxyinfo.h | 66 + zypp-curl/proxyinfo/ProxyInfoLibproxy | 1 + zypp-curl/proxyinfo/ProxyInfoSysconfig | 1 + zypp-curl/proxyinfo/proxyinfoimpl.h | 84 + zypp-curl/proxyinfo/proxyinfolibproxy.cc | 214 + zypp-curl/proxyinfo/proxyinfolibproxy.h | 71 + zypp-curl/proxyinfo/proxyinfos.h | 23 + zypp-curl/proxyinfo/proxyinfosysconfig.cc | 67 + zypp-curl/proxyinfo/proxyinfosysconfig.h | 54 + zypp-curl/transfersettings.cc | 321 + zypp-curl/transfersettings.h | 215 + zypp-history.lr | 11 + zypp-media/CDTools | 1 + zypp-media/CMakeLists.txt | 142 + zypp-media/FileCheckException | 1 + zypp-media/MediaConfig | 1 + zypp-media/MediaException | 1 + zypp-media/Mount | 1 + zypp-media/auth/AuthData | 1 + zypp-media/auth/CredentialFileReader | 1 + zypp-media/auth/CredentialManager | 1 + zypp-media/auth/authdata.cc | 96 + zypp-media/auth/authdata.h | 89 + zypp-media/auth/credentialfilereader.cc | 150 + zypp-media/auth/credentialfilereader.h | 50 + zypp-media/auth/credentialmanager.cc | 512 + zypp-media/auth/credentialmanager.h | 196 + zypp-media/cdtools.cc | 103 + zypp-media/cdtools.h | 29 + zypp-media/filecheckexception.cc | 12 + zypp-media/filecheckexception.h | 43 + zypp-media/mediaconfig.cc | 130 + zypp-media/mediaconfig.h | 100 + zypp-media/mediaexception.cc | 227 + zypp-media/mediaexception.h | 576 + zypp-media/mount.cc | 276 + zypp-media/mount.h | 157 + zypp-media/ng/HeaderValueMap | 1 + zypp-media/ng/LazyMediaHandle | 1 + zypp-media/ng/MediaVerifier | 1 + zypp-media/ng/Provide | 1 + zypp-media/ng/ProvideFwd | 1 + zypp-media/ng/ProvideItem | 1 + zypp-media/ng/ProvideRes | 1 + zypp-media/ng/ProvideSpec | 1 + zypp-media/ng/attachedmediainfo.cc | 62 + zypp-media/ng/headervaluemap.cc | 247 + zypp-media/ng/headervaluemap.h | 197 + zypp-media/ng/lazymediahandle.h | 105 + zypp-media/ng/mediaverifier.cc | 137 + zypp-media/ng/mediaverifier.h | 100 + zypp-media/ng/private/attachedmediainfo_p.h | 60 + zypp-media/ng/private/provide_p.h | 150 + zypp-media/ng/private/providedbg_p.h | 43 + zypp-media/ng/private/providefwd_p.h | 36 + zypp-media/ng/private/provideitem_p.h | 206 + zypp-media/ng/private/providemessage_p.h | 596 + zypp-media/ng/private/providequeue_p.h | 143 + zypp-media/ng/private/provideres_p.h | 23 + zypp-media/ng/provide-configvars.h | 28 + zypp-media/ng/provide.cc | 1321 ++ zypp-media/ng/provide.h | 203 + zypp-media/ng/providefwd.h | 32 + zypp-media/ng/provideitem.cc | 1208 ++ zypp-media/ng/provideitem.h | 192 + zypp-media/ng/providemessage.cc | 712 + zypp-media/ng/providequeue.cc | 784 + zypp-media/ng/provideres.cc | 46 + zypp-media/ng/provideres.h | 74 + zypp-media/ng/providespec.cc | 288 + zypp-media/ng/providespec.h | 206 + zypp-media/ng/worker/DeviceDriver | 1 + zypp-media/ng/worker/MountingWorker | 1 + zypp-media/ng/worker/ProvideWorker | 1 + zypp-media/ng/worker/devicedriver.cc | 381 + zypp-media/ng/worker/devicedriver.h | 202 + zypp-media/ng/worker/mountingworker.cc | 191 + zypp-media/ng/worker/mountingworker.h | 41 + zypp-media/ng/worker/provideworker.cc | 466 + zypp-media/ng/worker/provideworker.h | 215 + zypp-tui/Application | 1 + zypp-tui/CMakeLists.txt | 90 + zypp-tui/Config | 1 + zypp-tui/Table.cc | 468 + zypp-tui/Table.h | 645 + zypp-tui/application.cc | 83 + zypp-tui/application.h | 60 + zypp-tui/config.cc | 32 + zypp-tui/config.h | 56 + zypp-tui/output/AliveCursor.h | 80 + zypp-tui/output/Out.cc | 180 + zypp-tui/output/Out.h | 1180 ++ zypp-tui/output/OutNormal.cc | 462 + zypp-tui/output/OutNormal.h | 76 + zypp-tui/output/PromptOptions | 1 + zypp-tui/output/Utf8.h | 197 + zypp-tui/output/promptoptions.cc | 196 + zypp-tui/output/promptoptions.h | 121 + zypp-tui/utils/ansi.h | 864 + zypp-tui/utils/colors.cc | 149 + zypp-tui/utils/colors.h | 92 + zypp-tui/utils/console.cc | 82 + zypp-tui/utils/console.h | 48 + zypp-tui/utils/richtext.cc | 275 + zypp-tui/utils/richtext.h | 51 + zypp-tui/utils/text.cc | 68 + zypp-tui/utils/text.h | 659 + zypp.conf | 704 + zypp/APIConfig.h | 1 + zypp/Application.cc | 31 + zypp/Application.h | 48 + zypp/Arch.cc | 586 + zypp/Arch.h | 375 + zypp/AutoDispose.h | 1 + zypp/Bit.h | 344 + zypp/Bitmap.h | 22 + zypp/ByteArray.h | 1 + zypp/ByteCount.h | 1 + zypp/CMakeLists.txt | 1072 ++ zypp/Callback.h | 319 + zypp/CapMatch.cc | 41 + zypp/CapMatch.h | 102 + zypp/Capabilities.cc | 72 + zypp/Capabilities.h | 193 + zypp/Capability.cc | 728 + zypp/Capability.h | 405 + zypp/Changelog.cc | 32 + zypp/Changelog.h | 64 + zypp/CheckSum.cc | 11 + zypp/CheckSum.h | 17 + zypp/ContentType.h | 142 + zypp/CountryCode.cc | 418 + zypp/CountryCode.h | 75 + zypp/CpeId.cc | 1056 ++ zypp/CpeId.h | 304 + zypp/Date.h | 1 + zypp/Dep.cc | 111 + zypp/Dep.h | 123 + zypp/Digest.cc | 74 + zypp/Digest.h | 33 + zypp/DiskUsageCounter.cc | 359 + zypp/DiskUsageCounter.h | 228 + zypp/DownloadMode.cc | 52 + zypp/DownloadMode.h | 63 + zypp/Edition.cc | 138 + zypp/Edition.h | 193 + zypp/ExternalProgram.h | 1 + zypp/Fetcher.cc | 934 ++ zypp/Fetcher.h | 357 + zypp/FileChecker.cc | 118 + zypp/FileChecker.h | 155 + zypp/Filter.h | 219 + zypp/Glob.cc | 63 + zypp/Glob.h | 271 + zypp/Globals.h | 1 + zypp/HistoryLog.cc | 359 + zypp/HistoryLog.h | 139 + zypp/HistoryLogData.cc | 333 + zypp/HistoryLogData.h | 469 + zypp/IdString.cc | 92 + zypp/IdString.h | 249 + zypp/IdStringType.h | 353 + zypp/InstanceId.cc | 114 + zypp/InstanceId.h | 110 + zypp/KVMap.h | 1 + zypp/KeyContext.h | 27 + zypp/KeyManager.cc | 545 + zypp/KeyManager.h | 96 + zypp/KeyRing.cc | 514 + zypp/KeyRing.h | 354 + zypp/KeyRingContexts.cc | 142 + zypp/KeyRingContexts.h | 101 + zypp/LanguageCode.cc | 1165 ++ zypp/LanguageCode.h | 74 + zypp/Locale.cc | 229 + zypp/Locale.h | 120 + zypp/Locks.cc | 495 + zypp/Locks.h | 153 + zypp/ManagedFile.h | 12 + zypp/MediaProducts.h | 127 + zypp/MediaSetAccess.cc | 501 + zypp/MediaSetAccess.h | 398 + zypp/Misc.h | 18 + zypp/OnMediaLocation.h | 1 + zypp/Package.cc | 305 + zypp/Package.h | 167 + zypp/PackageKeyword.h | 49 + zypp/Patch.cc | 353 + zypp/Patch.h | 315 + zypp/PathInfo.cc | 52 + zypp/PathInfo.h | 77 + zypp/Pathname.h | 1 + zypp/Pattern.cc | 412 + zypp/Pattern.h | 128 + zypp/PluginExecutor.cc | 184 + zypp/PluginExecutor.h | 97 + zypp/PluginScript.cc | 532 + zypp/PluginScript.h | 197 + zypp/PluginScriptException.cc | 41 + zypp/PluginScriptException.h | 65 + zypp/PoolItem.cc | 234 + zypp/PoolItem.h | 213 + zypp/PoolItemBest.cc | 104 + zypp/PoolItemBest.h | 163 + zypp/PoolQuery.cc | 1863 +++ zypp/PoolQuery.h | 628 + zypp/PoolQueryResult.cc | 35 + zypp/PoolQueryResult.h | 234 + zypp/PoolQueryUtil.tcc | 78 + zypp/ProblemSolution.cc | 179 + zypp/ProblemSolution.h | 119 + zypp/ProblemTypes.h | 50 + zypp/Product.cc | 295 + zypp/Product.h | 254 + zypp/ProgressData.h | 1 + zypp/ProvideFilePolicy.cc | 36 + zypp/ProvideFilePolicy.h | 59 + zypp/PublicKey.cc | 716 + zypp/PublicKey.h | 484 + zypp/PurgeKernels.cc | 697 + zypp/PurgeKernels.h | 73 + zypp/Range.cc | 114 + zypp/Range.h | 91 + zypp/Rel.cc | 125 + zypp/Rel.h | 177 + zypp/RelCompare.h | 232 + zypp/RepoInfo.cc | 988 ++ zypp/RepoInfo.h | 588 + zypp/RepoManager.cc | 279 + zypp/RepoManager.h | 665 + zypp/RepoManagerFlags.h | 56 + zypp/RepoManagerOptions.cc | 66 + zypp/RepoManagerOptions.h | 74 + zypp/RepoStatus.cc | 255 + zypp/RepoStatus.h | 127 + zypp/Repository.cc | 448 + zypp/Repository.h | 517 + zypp/ResFilters.h | 345 + zypp/ResKind.cc | 77 + zypp/ResKind.h | 102 + zypp/ResObject.cc | 61 + zypp/ResObject.h | 156 + zypp/ResObjects.h | 22 + zypp/ResPool.cc | 156 + zypp/ResPool.h | 483 + zypp/ResPoolProxy.cc | 338 + zypp/ResPoolProxy.h | 311 + zypp/ResStatus.cc | 158 + zypp/ResStatus.h | 754 + zypp/ResTraits.h | 155 + zypp/Resolvable.cc | 35 + zypp/Resolvable.h | 176 + zypp/Resolver.cc | 187 + zypp/Resolver.h | 501 + zypp/ResolverFocus.cc | 75 + zypp/ResolverFocus.h | 51 + zypp/ResolverNamespace.h | 69 + zypp/ResolverProblem.cc | 158 + zypp/ResolverProblem.h | 106 + zypp/ServiceInfo.cc | 242 + zypp/ServiceInfo.h | 232 + zypp/Signature.cc | 30 + zypp/Signature.h | 37 + zypp/SrcPackage.cc | 62 + zypp/SrcPackage.h | 64 + zypp/SysContent.cc | 457 + zypp/SysContent.h | 265 + zypp/Target.cc | 144 + zypp/Target.h | 262 + zypp/TmpPath.cc | 11 + zypp/TmpPath.h | 12 + zypp/TriBool.h | 1 + zypp/Url.h | 1 + zypp/UserData.h | 1 + zypp/Vendor.h | 30 + zypp/VendorAttr.cc | 343 + zypp/VendorAttr.h | 171 + zypp/VendorSupportOptions.cc | 65 + zypp/VendorSupportOptions.h | 101 + zypp/ZConfig.cc | 1351 ++ zypp/ZConfig.h | 612 + zypp/ZYpp.cc | 104 + zypp/ZYpp.h | 177 + zypp/ZYppCallbacks.h | 1068 ++ zypp/ZYppCommit.h | 26 + zypp/ZYppCommitPolicy.cc | 198 + zypp/ZYppCommitPolicy.h | 116 + zypp/ZYppCommitResult.cc | 129 + zypp/ZYppCommitResult.h | 200 + zypp/ZYppFactory.cc | 483 + zypp/ZYppFactory.h | 83 + zypp/base/Algorithm.h | 84 + zypp/base/Backtrace.cc | 106 + zypp/base/Backtrace.h | 38 + zypp/base/Collector.h | 66 + zypp/base/Counter.h | 49 + zypp/base/Debug.h | 185 + zypp/base/DefaultIntegral.h | 1 + zypp/base/DrunkenBishop.cc | 409 + zypp/base/DrunkenBishop.h | 130 + zypp/base/DtorReset.h | 1 + zypp/base/Easy.h | 1 + zypp/base/EnumClass.h | 1 + zypp/base/Env.h | 78 + zypp/base/Errno.h | 1 + zypp/base/Exception.h | 1 + zypp/base/ExternalDataSource.h | 1 + zypp/base/Flags.h | 1 + zypp/base/Function.h | 1 + zypp/base/Functional.h | 282 + zypp/base/Gettext.h | 1 + zypp/base/GzStream.h | 1 + zypp/base/Hash.h | 1 + zypp/base/IOStream.h | 1 + zypp/base/IOTools.h | 1 + zypp/base/InputStream.h | 1 + zypp/base/Iterable.h | 1 + zypp/base/Iterator.h | 1 + zypp/base/Json.h | 383 + zypp/base/LocaleGuard.h | 66 + zypp/base/LogControl.h | 1 + zypp/base/LogTools.h | 1 + zypp/base/Logger.h | 1 + zypp/base/Measure.cc | 259 + zypp/base/Measure.h | 125 + zypp/base/NamedValue.h | 161 + zypp/base/NonCopyable.h | 1 + zypp/base/ProfilingFormater.h | 1 + zypp/base/ProvideNumericId.h | 1 + zypp/base/PtrTypes.h | 1 + zypp/base/Random.cc | 51 + zypp/base/Random.h | 48 + zypp/base/ReferenceCounted.h | 17 + zypp/base/Regex.h | 1 + zypp/base/SerialNumber.cc | 101 + zypp/base/SerialNumber.h | 184 + zypp/base/SetRelationMixin.cc | 44 + zypp/base/SetRelationMixin.h | 242 + zypp/base/SetTracker.h | 197 + zypp/base/Signal.h | 84 + zypp/base/SimpleStreambuf.h | 1 + zypp/base/StrMatcher.cc | 349 + zypp/base/StrMatcher.h | 410 + zypp/base/String.h | 1 + zypp/base/StringV.h | 1 + zypp/base/Sysconfig.h | 1 + zypp/base/TypeTraits.h | 58 + zypp/base/Unit.h | 1 + zypp/base/UserRequestException.h | 1 + zypp/base/ValueTransform.h | 168 + zypp/base/WatchFile.h | 1 + zypp/base/Xml.h | 1 + zypp/base/ZckStream.h | 1 + zypp/base/fXstream.h | 1 + zypp/libzypp.map | 12 + zypp/media/CredentialFileReader.h | 1 + zypp/media/CredentialManager.h | 1 + zypp/media/CurlConfig.h | 1 + zypp/media/MediaBlockList.h | 1 + zypp/media/MediaCD.cc | 674 + zypp/media/MediaCD.h | 77 + zypp/media/MediaCIFS.cc | 471 + zypp/media/MediaCIFS.h | 62 + zypp/media/MediaCurl.cc | 1588 ++ zypp/media/MediaCurl.h | 183 + zypp/media/MediaDIR.cc | 184 + zypp/media/MediaDIR.h | 55 + zypp/media/MediaDISK.cc | 409 + zypp/media/MediaDISK.h | 62 + zypp/media/MediaException.h | 1 + zypp/media/MediaHandler.cc | 1358 ++ zypp/media/MediaHandler.h | 719 + zypp/media/MediaHandlerFactory.cc | 174 + zypp/media/MediaHandlerFactory.h | 37 + zypp/media/MediaISO.cc | 311 + zypp/media/MediaISO.h | 77 + zypp/media/MediaManager.cc | 1014 ++ zypp/media/MediaManager.h | 936 ++ zypp/media/MediaMultiCurl.cc | 1818 +++ zypp/media/MediaMultiCurl.h | 84 + zypp/media/MediaNFS.cc | 261 + zypp/media/MediaNFS.h | 65 + zypp/media/MediaNetwork.cc | 618 + zypp/media/MediaNetwork.h | 83 + zypp/media/MediaNetworkCommonHandler.cc | 96 + zypp/media/MediaNetworkCommonHandler.h | 70 + zypp/media/MediaPlugin.cc | 62 + zypp/media/MediaPlugin.h | 52 + zypp/media/MediaPriority.cc | 107 + zypp/media/MediaPriority.h | 101 + zypp/media/MediaSource.cc | 29 + zypp/media/MediaSource.h | 157 + zypp/media/MediaUserAuth.h | 1 + zypp/media/MetaLinkParser.h | 1 + zypp/media/Mount.h | 1 + zypp/media/ProxyInfo.h | 1 + zypp/media/TransferSettings.h | 1 + zypp/media/UrlResolverPlugin.cc | 102 + zypp/media/UrlResolverPlugin.h | 73 + zypp/media/proxyinfo/ProxyInfoImpl.h | 1 + zypp/media/proxyinfo/ProxyInfoLibproxy.h | 1 + zypp/media/proxyinfo/ProxyInfoSysconfig.h | 1 + zypp/media/proxyinfo/ProxyInfos.h | 1 + zypp/misc/CheckAccessDeleted.cc | 606 + zypp/misc/CheckAccessDeleted.h | 133 + zypp/misc/DefaultLoadSystem.cc | 114 + zypp/misc/DefaultLoadSystem.h | 64 + zypp/misc/HelixHelpers.h | 321 + zypp/misc/LoadTestcase.cc | 242 + zypp/misc/LoadTestcase.h | 87 + zypp/misc/TestcaseSetup.cc | 260 + zypp/misc/TestcaseSetup.h | 136 + zypp/misc/TestcaseSetupImpl.h | 85 + zypp/misc/YamlTestcaseHelpers.h | 330 + zypp/ng/Context | 1 + zypp/ng/RepoManager | 1 + zypp/ng/UserRequest | 1 + zypp/ng/context.cc | 72 + zypp/ng/context.h | 93 + zypp/ng/private/context_p.h | 35 + zypp/ng/private/repomanager_p.h | 37 + zypp/ng/progressobserveradaptor.cc | 63 + zypp/ng/progressobserveradaptor.h | 36 + zypp/ng/repo/Downloader | 1 + zypp/ng/repo/Refresh | 1 + zypp/ng/repo/downloader.cc | 59 + zypp/ng/repo/downloader.h | 74 + zypp/ng/repo/refresh.cc | 154 + zypp/ng/repo/refresh.h | 148 + zypp/ng/repo/workflows/plaindir.cc | 98 + zypp/ng/repo/workflows/plaindir.h | 37 + zypp/ng/repo/workflows/repodownloaderwf.cc | 419 + zypp/ng/repo/workflows/repodownloaderwf.h | 71 + zypp/ng/repo/workflows/repomanagerwf.cc | 1211 ++ zypp/ng/repo/workflows/repomanagerwf.h | 72 + zypp/ng/repo/workflows/rpmmd.cc | 182 + zypp/ng/repo/workflows/rpmmd.h | 42 + zypp/ng/repo/workflows/serviceswf.cc | 749 + zypp/ng/repo/workflows/serviceswf.h | 43 + zypp/ng/repo/workflows/susetags.cc | 340 + zypp/ng/repo/workflows/susetags.h | 49 + zypp/ng/repomanager.cc | 1479 ++ zypp/ng/repomanager.h | 510 + zypp/ng/reporthelper.cc | 260 + zypp/ng/reporthelper.h | 169 + zypp/ng/userrequest.cc | 118 + zypp/ng/userrequest.h | 251 + zypp/ng/workflows/checksumwf.cc | 153 + zypp/ng/workflows/checksumwf.h | 48 + zypp/ng/workflows/contextfacade.cc | 61 + zypp/ng/workflows/contextfacade.h | 59 + zypp/ng/workflows/downloadwf.cc | 221 + zypp/ng/workflows/downloadwf.h | 65 + zypp/ng/workflows/keyringwf.cc | 354 + zypp/ng/workflows/keyringwf.h | 84 + zypp/ng/workflows/logichelpers.h | 229 + zypp/ng/workflows/mediafacade.cc | 600 + zypp/ng/workflows/mediafacade.h | 132 + zypp/ng/workflows/repoinfowf.cc | 222 + zypp/ng/workflows/repoinfowf.h | 28 + zypp/ng/workflows/signaturecheckwf.cc | 68 + zypp/ng/workflows/signaturecheckwf.h | 35 + zypp/parser/HistoryLogReader.cc | 244 + zypp/parser/HistoryLogReader.h | 170 + zypp/parser/IniDict.h | 1 + zypp/parser/IniParser.h | 1 + zypp/parser/ParseException.h | 1 + zypp/parser/ParserProgress.h | 105 + zypp/parser/ProductFileReader.cc | 290 + zypp/parser/ProductFileReader.h | 179 + zypp/parser/RepoFileReader.cc | 264 + zypp/parser/RepoFileReader.h | 118 + zypp/parser/RepoindexFileReader.cc | 282 + zypp/parser/RepoindexFileReader.h | 95 + zypp/parser/ServiceFileReader.cc | 183 + zypp/parser/ServiceFileReader.h | 90 + zypp/parser/schema/repoindex.rnc | 40 + zypp/parser/susetags/ContentFileReader.cc | 274 + zypp/parser/susetags/ContentFileReader.h | 103 + zypp/parser/susetags/RepoIndex.cc | 49 + zypp/parser/susetags/RepoIndex.h | 76 + zypp/parser/xml/Node.cc | 89 + zypp/parser/xml/Node.h | 175 + zypp/parser/xml/Parse.h | 115 + zypp/parser/xml/ParseDef.cc | 481 + zypp/parser/xml/ParseDef.h | 245 + zypp/parser/xml/ParseDefConsume.cc | 176 + zypp/parser/xml/ParseDefConsume.h | 374 + zypp/parser/xml/ParseDefException.cc | 62 + zypp/parser/xml/ParseDefException.h | 76 + zypp/parser/xml/ParseDefTraits.h | 56 + zypp/parser/xml/Reader.cc | 237 + zypp/parser/xml/Reader.h | 203 + zypp/parser/xml/XmlEscape.h | 1 + zypp/parser/xml/XmlString.cc | 58 + zypp/parser/xml/XmlString.h | 118 + zypp/parser/xml/libxmlfwd.cc | 83 + zypp/parser/xml/libxmlfwd.h | 41 + zypp/parser/yum/RepomdFileReader.cc | 248 + zypp/parser/yum/RepomdFileReader.h | 76 + zypp/parser/yum/schema/common-inc.rnc | 76 + zypp/parser/yum/schema/common-inc.rng | 141 + zypp/parser/yum/schema/deltainfo.rnc | 21 + zypp/parser/yum/schema/deltainfo.rng | 48 + zypp/parser/yum/schema/filelists.rnc | 17 + zypp/parser/yum/schema/filelists.rng | 36 + zypp/parser/yum/schema/other.rnc | 18 + zypp/parser/yum/schema/other.rng | 32 + zypp/parser/yum/schema/patch.rnc | 146 + zypp/parser/yum/schema/patch.rng | 270 + zypp/parser/yum/schema/patches.rnc | 16 + zypp/parser/yum/schema/patches.rng | 30 + zypp/parser/yum/schema/patterns.rnc | 30 + zypp/parser/yum/schema/patterns.rng | 87 + zypp/parser/yum/schema/primary.rnc | 88 + zypp/parser/yum/schema/primary.rng | 241 + zypp/parser/yum/schema/product.rnc | 22 + zypp/parser/yum/schema/product.rng | 56 + zypp/parser/yum/schema/products.rnc | 15 + zypp/parser/yum/schema/products.rng | 38 + zypp/parser/yum/schema/repomd.rnc | 29 + zypp/parser/yum/schema/repomd.rng | 82 + zypp/parser/yum/schema/rnc2rng | 7 + zypp/parser/yum/schema/rpm-inc.rnc | 45 + zypp/parser/yum/schema/rpm-inc.rng | 101 + zypp/parser/yum/schema/susedata.rnc | 31 + zypp/parser/yum/schema/susedata.rng | 69 + zypp/parser/yum/schema/suseinfo.rnc | 19 + zypp/parser/yum/schema/suseinfo.rng | 32 + zypp/parser/yum/schema/updateinfo.rnc | 51 + zypp/parser/yum/schema/updateinfo.rng | 129 + zypp/parser/yum/schema/validate-all | 149 + zypp/pool/ByIdent.h | 105 + zypp/pool/PoolImpl.cc | 60 + zypp/pool/PoolImpl.h | 498 + zypp/pool/PoolStats.cc | 46 + zypp/pool/PoolStats.h | 81 + zypp/pool/PoolTraits.h | 100 + zypp/repo/Applydeltarpm.cc | 195 + zypp/repo/Applydeltarpm.h | 83 + zypp/repo/DeltaCandidates.cc | 118 + zypp/repo/DeltaCandidates.h | 93 + zypp/repo/MediaInfoDownloader.cc | 42 + zypp/repo/MediaInfoDownloader.h | 39 + zypp/repo/PackageDelta.cc | 140 + zypp/repo/PackageDelta.h | 99 + zypp/repo/PackageProvider.cc | 720 + zypp/repo/PackageProvider.h | 107 + zypp/repo/PluginRepoverification.cc | 316 + zypp/repo/PluginRepoverification.h | 128 + zypp/repo/PluginServices.cc | 90 + zypp/repo/PluginServices.h | 65 + zypp/repo/RepoException.cc | 137 + zypp/repo/RepoException.h | 289 + zypp/repo/RepoInfoBase.cc | 175 + zypp/repo/RepoInfoBase.h | 199 + zypp/repo/RepoMirrorList.cc | 175 + zypp/repo/RepoMirrorList.h | 44 + zypp/repo/RepoProvideFile.cc | 350 + zypp/repo/RepoProvideFile.h | 103 + zypp/repo/RepoType.cc | 65 + zypp/repo/RepoType.h | 73 + zypp/repo/RepoVariables.cc | 587 + zypp/repo/RepoVariables.h | 141 + zypp/repo/SUSEMediaVerifier.cc | 209 + zypp/repo/SUSEMediaVerifier.h | 86 + zypp/repo/ServiceType.cc | 64 + zypp/repo/ServiceType.h | 83 + zypp/repo/SrcPackageProvider.cc | 42 + zypp/repo/SrcPackageProvider.h | 61 + zypp/repo/yum/RepomdFileCollector.cc | 165 + zypp/repo/yum/RepomdFileCollector.h | 54 + zypp/sat/FileConflicts.cc | 167 + zypp/sat/FileConflicts.h | 96 + zypp/sat/LocaleSupport.cc | 51 + zypp/sat/LocaleSupport.h | 129 + zypp/sat/LookupAttr.cc | 827 + zypp/sat/LookupAttr.h | 616 + zypp/sat/LookupAttrTools.h | 225 + zypp/sat/Map.cc | 137 + zypp/sat/Map.h | 136 + zypp/sat/Pool.cc | 346 + zypp/sat/Pool.h | 310 + zypp/sat/Queue.cc | 146 + zypp/sat/Queue.h | 139 + zypp/sat/SolvAttr.cc | 177 + zypp/sat/SolvAttr.h | 214 + zypp/sat/SolvIterMixin.cc | 69 + zypp/sat/SolvIterMixin.h | 213 + zypp/sat/Solvable.cc | 823 + zypp/sat/Solvable.h | 584 + zypp/sat/SolvableSet.cc | 41 + zypp/sat/SolvableSet.h | 120 + zypp/sat/SolvableSpec.cc | 207 + zypp/sat/SolvableSpec.h | 133 + zypp/sat/SolvableType.h | 284 + zypp/sat/Transaction.cc | 474 + zypp/sat/Transaction.h | 406 + zypp/sat/WhatObsoletes.cc | 176 + zypp/sat/WhatObsoletes.h | 111 + zypp/sat/WhatProvides.cc | 188 + zypp/sat/WhatProvides.h | 243 + zypp/sat/detail/PoolImpl.cc | 675 + zypp/sat/detail/PoolImpl.h | 402 + zypp/sat/detail/PoolMember.h | 158 + zypp/solver/Types.h | 24 + zypp/solver/detail/ItemCapKind.h | 93 + zypp/solver/detail/ProblemSolutionCombi.cc | 57 + zypp/solver/detail/ProblemSolutionCombi.h | 97 + zypp/solver/detail/ProblemSolutionIgnore.cc | 59 + zypp/solver/detail/ProblemSolutionIgnore.h | 65 + zypp/solver/detail/Resolver.cc | 688 + zypp/solver/detail/Resolver.h | 263 + zypp/solver/detail/SATResolver.cc | 1711 ++ zypp/solver/detail/SATResolver.h | 240 + zypp/solver/detail/SolutionAction.cc | 172 + zypp/solver/detail/SolutionAction.h | 187 + zypp/solver/detail/SolverQueueItem.cc | 108 + zypp/solver/detail/SolverQueueItem.h | 129 + zypp/solver/detail/SolverQueueItemDelete.cc | 127 + zypp/solver/detail/SolverQueueItemDelete.h | 85 + zypp/solver/detail/SolverQueueItemInstall.cc | 127 + zypp/solver/detail/SolverQueueItemInstall.h | 84 + .../detail/SolverQueueItemInstallOneOf.cc | 143 + .../detail/SolverQueueItemInstallOneOf.h | 86 + zypp/solver/detail/SolverQueueItemLock.cc | 130 + zypp/solver/detail/SolverQueueItemLock.h | 84 + zypp/solver/detail/SolverQueueItemUpdate.cc | 118 + zypp/solver/detail/SolverQueueItemUpdate.h | 84 + zypp/solver/detail/SystemCheck.cc | 172 + zypp/solver/detail/SystemCheck.h | 81 + zypp/solver/detail/Testcase.cc | 400 + zypp/solver/detail/Testcase.h | 64 + zypp/solver/detail/Testcase_helix.cc | 620 + zypp/solver/detail/Types.h | 56 + zypp/target/CommitPackageCache.cc | 165 + zypp/target/CommitPackageCache.h | 119 + zypp/target/CommitPackageCacheImpl.cc | 33 + zypp/target/CommitPackageCacheImpl.h | 122 + zypp/target/CommitPackageCacheReadAhead.cc | 186 + zypp/target/CommitPackageCacheReadAhead.h | 120 + zypp/target/HardLocksFile.cc | 87 + zypp/target/HardLocksFile.h | 127 + zypp/target/RequestedLocalesFile.cc | 95 + zypp/target/RequestedLocalesFile.h | 114 + zypp/target/RpmPostTransCollector.cc | 444 + zypp/target/RpmPostTransCollector.h | 82 + zypp/target/SolvIdentFile.cc | 103 + zypp/target/SolvIdentFile.h | 116 + zypp/target/TargetCallbackReceiver.cc | 209 + zypp/target/TargetCallbackReceiver.h | 125 + zypp/target/TargetException.cc | 40 + zypp/target/TargetException.h | 74 + zypp/target/TargetImpl.cc | 3068 ++++ .../TargetImpl.commitFindFileConflicts.cc | 175 + zypp/target/TargetImpl.h | 250 + zypp/target/modalias/Modalias.cc | 245 + zypp/target/modalias/Modalias.h | 102 + zypp/target/rpm/BinHeader.cc | 458 + zypp/target/rpm/BinHeader.h | 174 + zypp/target/rpm/RpmCallbacks.cc | 17 + zypp/target/rpm/RpmCallbacks.h | 109 + zypp/target/rpm/RpmDb.cc | 2278 +++ zypp/target/rpm/RpmDb.h | 512 + zypp/target/rpm/RpmException.cc | 87 + zypp/target/rpm/RpmException.h | 265 + zypp/target/rpm/RpmFlags.h | 68 + zypp/target/rpm/RpmHeader.cc | 1054 ++ zypp/target/rpm/RpmHeader.h | 221 + zypp/target/rpm/librpm.h | 35 + zypp/target/rpm/librpmDb.cc | 848 + zypp/target/rpm/librpmDb.h | 480 + zypp/ui/SelFilters.h | 95 + zypp/ui/Selectable.cc | 342 + zypp/ui/Selectable.h | 602 + zypp/ui/SelectableImpl.cc | 665 + zypp/ui/SelectableImpl.h | 633 + zypp/ui/SelectableTraits.h | 140 + zypp/ui/Status.cc | 58 + zypp/ui/Status.h | 69 + zypp/ui/UserWantedPackages.cc | 120 + zypp/ui/UserWantedPackages.h | 45 + zypp/url/UrlBase.h | 1 + zypp/url/UrlException.h | 1 + zypp/url/UrlUtils.h | 1 + zypp/zypp_detail/ZYppImpl.cc | 351 + zypp/zypp_detail/ZYppImpl.h | 165 + zypp/zypp_detail/ZYppReadOnlyHack.h | 35 + zypp/zypp_detail/keyring_p.h | 189 + zypp/zypp_detail/urlcredentialextractor_p.h | 91 + 1710 files changed, 606268 insertions(+) create mode 100644 .clang-format create mode 100644 .clang-tidy create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .obs/workflows.yml create mode 100644 .travis.yml create mode 100644 CMakeLists.txt create mode 100644 COPYING create mode 100644 Makefile.cvs create mode 100644 VERSION.cmake create mode 100644 cmake/modules/FindGpgme.cmake create mode 100644 cmake/modules/FindOpenSSL.cmake create mode 100644 cmake/modules/FindReadline.cmake create mode 100644 cmake/modules/FindRpm.cmake create mode 100644 cmake/modules/FindUdev.cmake create mode 100644 cmake/modules/FindZsync.cmake create mode 100644 cmake/modules/FindZypp.cmake create mode 100644 cmake/modules/Findlibproxy.cmake create mode 100644 cmake/modules/ZyppCommon.cmake create mode 100644 cmake/modules/printrpmver.c.in create mode 100644 doc/CMakeLists.txt create mode 100644 doc/autodoc/CMakeLists.txt create mode 100644 doc/autodoc/Doxyfile.cmake create mode 100644 doc/autoinclude/ApplicationMetada.doc create mode 100644 doc/autoinclude/CodePitfalls.doc create mode 100644 doc/autoinclude/EnvironmentVariables.doc create mode 100644 doc/autoinclude/FeatureTest.doc create mode 100644 doc/autoinclude/Mainpage.doc create mode 100644 doc/autoinclude/Modalias.doc create mode 100644 doc/autoinclude/PatternPackages.doc create mode 100644 doc/autoinclude/Plugin-Commit.doc create mode 100644 doc/autoinclude/Plugin-Repoverification.doc create mode 100644 doc/autoinclude/Plugin-System.doc create mode 100644 doc/autoinclude/Plugins.doc create mode 100644 doc/autoinclude/README create mode 100644 doc/autoinclude/RepoVariables.doc create mode 100644 doc/autoinclude/Services.doc create mode 100644 doc/autoinclude/SolverVendorChange.doc create mode 100644 doc/autoinclude/Testcases.doc create mode 100644 doc/autoinclude/Threads.doc create mode 100644 doc/autoinclude/UserData.doc create mode 100644 doc/autoinclude/g_BOOST.doc create mode 100644 doc/autoinclude/g_LIBSOLV.doc create mode 100644 doc/autoinclude/g_ZyppHistory.doc create mode 100644 doc/autoinclude/groups.doc create mode 100644 doc/autoinclude/notes/n_ResPool_nomorenameiter create mode 100644 doc/locks.5.txt create mode 100644 doc/zypp-CheckAccessDeleted.1.txt create mode 100644 doc/zypp-NameReqPrv.1.txt create mode 100644 libzypp.pc.cmake create mode 100644 libzypp.spec.cmake create mode 100755 mkChangelog create mode 100644 needreboot create mode 100644 package/libzypp-rpmlint.cmake create mode 100644 package/libzypp.changes create mode 100644 po/CMakeLists.txt create mode 100755 po/PotfileDiff.sh create mode 100755 po/PotfileUpadte.sh create mode 100644 po/af.po create mode 100644 po/ar.po create mode 100644 po/ast.po create mode 100644 po/be.po create mode 100644 po/bg.po create mode 100644 po/bn.po create mode 100644 po/bs.po create mode 100644 po/ca.po create mode 100644 po/cs.po create mode 100644 po/cy.po create mode 100644 po/da.po create mode 100644 po/de.po create mode 100644 po/el.po create mode 100644 po/en_GB.po create mode 100644 po/es.po create mode 100644 po/et.po create mode 100644 po/fa.po create mode 100644 po/fi.po create mode 100644 po/fr.po create mode 100644 po/gl.po create mode 100644 po/gu.po create mode 100644 po/he.po create mode 100644 po/hi.po create mode 100644 po/hr.po create mode 100644 po/hu.po create mode 100644 po/id.po create mode 100644 po/it.po create mode 100644 po/ja.po create mode 100644 po/ka.po create mode 100644 po/km.po create mode 100644 po/ko.po create mode 100644 po/ku.po create mode 100644 po/lt.po create mode 100644 po/mk.po create mode 100644 po/mr.po create mode 100644 po/nb.po create mode 100644 po/nl.po create mode 100644 po/nn.po create mode 100644 po/pa.po create mode 100644 po/pl.po create mode 100644 po/pt.po create mode 100644 po/pt_BR.po create mode 100644 po/ro.po create mode 100644 po/ru.po create mode 100644 po/si.po create mode 100644 po/sk.po create mode 100644 po/sl.po create mode 100644 po/sr.po create mode 100644 po/sv.po create mode 100644 po/ta.po create mode 100644 po/th.po create mode 100644 po/tr.po create mode 100644 po/uk.po create mode 100644 po/vi.po create mode 100644 po/wa.po create mode 100644 po/xh.po create mode 100644 po/zh_CN.po create mode 100644 po/zh_TW.po create mode 100644 po/zu.po create mode 100644 po/zypp.pot create mode 100644 shared/CMakeLists.txt create mode 100644 shared/commit/CommitMessages.cc create mode 100644 shared/commit/CommitMessages.h create mode 100644 shared/tvm/tvmsettings.cc create mode 100644 shared/tvm/tvmsettings.h create mode 100644 systemCheck create mode 100644 tests/CMakeLists.txt create mode 100644 tests/README create mode 100644 tests/data/11.0-update/repodata/deltainfo.xml.gz create mode 100644 tests/data/11.0-update/repodata/primary.xml.gz create mode 100644 tests/data/11.0-update/repodata/repomd.xml create mode 100644 tests/data/11.0-update/repodata/repomd.xml.asc create mode 100644 tests/data/11.0-update/repodata/repomd.xml.key create mode 100644 tests/data/11.0-update/repodata/updateinfo.xml.gz create mode 100644 tests/data/Mirrorlist/remote-site/metalink.xml create mode 100644 tests/data/Mirrorlist/remote-site/mirrors.txt create mode 100644 tests/data/OBS_zypp_svn-11.1/repodata/primary.xml.gz create mode 100644 tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml create mode 100644 tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.asc create mode 100644 tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.key create mode 100644 tests/data/PoolReuseIds/SeqA/SEQA.repo create mode 100644 tests/data/PoolReuseIds/SeqA/zypp-control.yaml create mode 100644 tests/data/PoolReuseIds/SeqB/SeqB.repo create mode 100644 tests/data/PoolReuseIds/SeqB/zypp-control.yaml create mode 100644 tests/data/TCNamespaceRecommends/@System.repo create mode 100644 tests/data/TCNamespaceRecommends/update.repo create mode 100644 tests/data/TCNamespaceRecommends/zypp-control.yaml create mode 100644 tests/data/TCSelectable/@System.repo create mode 100644 tests/data/TCSelectable/RepoHIGH.repo create mode 100644 tests/data/TCSelectable/RepoLOW.repo create mode 100644 tests/data/TCSelectable/RepoMID.repo create mode 100644 tests/data/TCSelectable/RepoSRC.repo create mode 100644 tests/data/TCSelectable/zypp-control.yaml create mode 100644 tests/data/TCWhatObsoletes/@System.repo create mode 100644 tests/data/TCWhatObsoletes/zypp-control.yaml create mode 100644 tests/data/TCdup/@System.repo create mode 100644 tests/data/TCdup/update.repo create mode 100644 tests/data/TCdup/zypp-control.yaml create mode 100644 tests/data/dummywebroot/Readme create mode 100644 tests/data/lighttpdconf/conf.d/access_log.conf create mode 100644 tests/data/lighttpdconf/conf.d/auth.conf create mode 100644 tests/data/lighttpdconf/conf.d/compress.conf create mode 100644 tests/data/lighttpdconf/conf.d/debug.conf create mode 100644 tests/data/lighttpdconf/conf.d/dirlisting.conf create mode 100644 tests/data/lighttpdconf/conf.d/expire.conf create mode 100644 tests/data/lighttpdconf/conf.d/fastcgi.conf create mode 100755 tests/data/lighttpdconf/conf.d/maybessl.sh create mode 100644 tests/data/lighttpdconf/conf.d/mime.conf create mode 100644 tests/data/lighttpdconf/lighttpd.conf create mode 100644 tests/data/nginxconf/mime.types create mode 100644 tests/data/nginxconf/nginx.conf create mode 100644 tests/data/nginxconf/nossl.conf create mode 100644 tests/data/nginxconf/ssl.conf create mode 100644 tests/data/obs_virtualbox_11_1/repodata/primary.xml.gz create mode 100644 tests/data/obs_virtualbox_11_1/repodata/repomd.xml create mode 100644 tests/data/obs_virtualbox_11_1/repodata/repomd.xml.asc create mode 100644 tests/data/obs_virtualbox_11_1/repodata/repomd.xml.key create mode 100644 tests/data/openSUSE-11.1/content create mode 100644 tests/data/openSUSE-11.1/gpg-pubkey-0dfb3188-41ed929b.asc create mode 100644 tests/data/openSUSE-11.1/gpg-pubkey-307e3d54-481f30aa.asc create mode 100644 tests/data/openSUSE-11.1/gpg-pubkey-3d25d3d9-36e12d04.asc create mode 100644 tests/data/openSUSE-11.1/gpg-pubkey-56b4177a-47965b33.asc create mode 100644 tests/data/openSUSE-11.1/gpg-pubkey-7e2e3b05-4816488f.asc create mode 100644 tests/data/openSUSE-11.1/gpg-pubkey-9c800aca-481f343a.asc create mode 100644 tests/data/openSUSE-11.1/gpg-pubkey-a1912208-446a0899.asc create mode 100644 tests/data/openSUSE-11.1/media.1/media create mode 100644 tests/data/openSUSE-11.1/media.1/products create mode 100644 tests/data/openSUSE-11.1/media.1/products.asc create mode 100644 tests/data/openSUSE-11.1/media.1/products.key create mode 100644 tests/data/openSUSE-11.1/suse/setup/descr/dvd-11.1-46.1.x86_64.pat.gz create mode 100644 tests/data/openSUSE-11.1/suse/setup/descr/non_oss-11.1-46.1.x86_64.pat.gz create mode 100644 tests/data/openSUSE-11.1/suse/setup/descr/packages.DU.gz create mode 100644 tests/data/openSUSE-11.1/suse/setup/descr/packages.cs.gz create mode 100644 tests/data/openSUSE-11.1/suse/setup/descr/packages.en.gz create mode 100644 tests/data/openSUSE-11.1/suse/setup/descr/packages.gz create mode 100644 tests/data/openSUSE-11.1/suse/setup/descr/patterns create mode 100644 tests/data/vsftpconf/vsftpd.conf create mode 100644 tests/data/webconf/ssl/ca/ca.crt create mode 100644 tests/data/webconf/ssl/ca/ca.key create mode 120000 tests/data/webconf/ssl/certstore/7dd4d2a5.0 create mode 100644 tests/data/webconf/ssl/certstore/ca.pem create mode 100644 tests/data/webconf/ssl/openssl.cnf create mode 100644 tests/data/webconf/ssl/server.crt create mode 100644 tests/data/webconf/ssl/server.csr create mode 100644 tests/data/webconf/ssl/server.key create mode 100644 tests/data/webconf/ssl/server.pem create mode 100644 tests/lib/CMakeLists.txt create mode 100644 tests/lib/FtpServer.cc create mode 100644 tests/lib/FtpServer.h create mode 100644 tests/lib/TestSetup.h create mode 100644 tests/lib/TestTools.h create mode 100644 tests/lib/WebServer.cc create mode 100644 tests/lib/WebServer.h create mode 100644 tests/media/CMakeLists.txt create mode 100644 tests/media/CredentialFileReader_test.cc create mode 100644 tests/media/CredentialManager_test.cc create mode 100644 tests/media/MediaProducts_test.cc create mode 100644 tests/media/MetaLinkParser_test.cc create mode 100644 tests/media/data/credentials.cat create mode 100644 tests/media/data/credentials.d/cred1 create mode 100644 tests/media/data/openSUSE-11.3-NET-i586.iso.meta4 create mode 100644 tests/media/data/openSUSE-11.3-NET-i586.iso.metalink create mode 100644 tests/media/data/other.xml.gz.meta4 create mode 100644 tests/media/file_exists_test.cc create mode 100644 tests/media/media1_test.cc create mode 100644 tests/media/media2_test.cc create mode 100644 tests/media/media3_test.cc create mode 100644 tests/media/media4_test.cc create mode 100644 tests/media/metalink/metalink.dockerfile create mode 100644 tests/media/mymediaverifier.h create mode 100644 tests/media/throw_if_not_exists_test.cc create mode 100644 tests/parser/CMakeLists.txt create mode 100644 tests/parser/HistoryLogReader_test.cc create mode 100644 tests/parser/HistoryLogReader_test.dat create mode 100644 tests/parser/ProductFileReader_test.cc create mode 100644 tests/parser/ProductFileReader_test.dat create mode 100644 tests/parser/RepoFileReader_test.cc create mode 100644 tests/parser/RepoindexFileReader_test.cc create mode 100644 tests/parser/inifile/CMakeLists.txt create mode 100644 tests/parser/inifile/data/1.ini create mode 100644 tests/parser/inifile/data/2.ini create mode 100644 tests/parser/inifile/inidict_test.cc create mode 100644 tests/parser/inifile/iniparser_test.cc create mode 100644 tests/parser/yum/CMakeLists.txt create mode 100644 tests/parser/yum/RepomdFileReader_test.cc create mode 100644 tests/parser/yum/data/repomd-1.xml create mode 100644 tests/parser/yum/data/repomd-1.xml.solution create mode 100644 tests/repo/CMakeLists.txt create mode 100644 tests/repo/DUdata_test.cc create mode 100644 tests/repo/ExtendedMetadata_test.cc create mode 100644 tests/repo/MirrorList_test.cc create mode 100644 tests/repo/PluginServices_test.cc create mode 100644 tests/repo/RepoLicense/repo/repodata/CHECKSUM-license-prod.tar.gz create mode 100644 tests/repo/RepoLicense/repo/repodata/CHECKSUM-license.tar.gz create mode 100644 tests/repo/RepoLicense/repo/repodata/license.de.txt create mode 100644 tests/repo/RepoLicense/repo/repodata/license.fr.txt create mode 100644 tests/repo/RepoLicense/repo/repodata/license.txt create mode 100644 tests/repo/RepoLicense/repo/repodata/no-acceptance-needed create mode 100644 tests/repo/RepoLicense/repo/repodata/repomd.xml create mode 100644 tests/repo/RepoLicense_test.cc create mode 100644 tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml create mode 100644 tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml.asc create mode 100644 tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml.key create mode 100644 tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml create mode 100644 tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml.asc create mode 100644 tests/repo/RepoSigcheck/unsigned_repo/repodata/repomd.xml create mode 100644 tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml create mode 100644 tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml.asc create mode 100644 tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml.key create mode 100644 tests/repo/RepoSigcheck_test.cc create mode 100644 tests/repo/RepoVariables_test.cc create mode 100644 tests/repo/susetags/CMakeLists.txt create mode 100644 tests/repo/susetags/Downloader_test.cc create mode 100644 tests/repo/susetags/data/addon_in_subdir/media.1/build create mode 100644 tests/repo/susetags/data/addon_in_subdir/media.1/directory.yast create mode 100644 tests/repo/susetags/data/addon_in_subdir/media.1/media create mode 100644 tests/repo/susetags/data/addon_in_subdir/media.1/products create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/SHA1SUMS create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/content create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/content.asc create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/content.key create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/directory.yast create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/license.tar.gz create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/suse/i586/SHA1SUMS create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/SHA1SUMS create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/directory.yast create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.DU create mode 100644 tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.en create mode 100644 tests/repo/susetags/data/dudata/repo/content create mode 100644 tests/repo/susetags/data/dudata/repo/media.1/media create mode 100644 tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages create mode 100644 tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages.DU create mode 100644 tests/repo/susetags/data/dudata/system/content create mode 100644 tests/repo/susetags/data/dudata/system/media.1/media create mode 100644 tests/repo/susetags/data/dudata/system/suse/setup/descr/packages create mode 100644 tests/repo/susetags/data/dudata/system/suse/setup/descr/packages.DU create mode 100644 tests/repo/susetags/data/shared_attributes/content create mode 100644 tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages create mode 100644 tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.DU create mode 100644 tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.en create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/content create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/content.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/content.key create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/control.xml create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-0dfb3188-41ed929b.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-307e3d54-44201d5d.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-3d25d3d9-36e12d04.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-7e2e3b05-44748aba.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-9c800aca-40d8063e.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-a1912208-446a0899.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/installation.xml create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/license.tar.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/media.1/directory.yast create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/media.1/info.txt create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/media.1/media create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/media.1/products create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.key create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/kde-10.3-71.noarch.pat.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/packages.DU.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/packages.en.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/packages.es.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/packages.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/patterns.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset/content create mode 100644 tests/repo/susetags/data/stable-x86-subset/content.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/content.key create mode 100644 tests/repo/susetags/data/stable-x86-subset/control.xml create mode 100644 tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-0dfb3188-41ed929b.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-307e3d54-44201d5d.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-3d25d3d9-36e12d04.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-7e2e3b05-44748aba.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-9c800aca-40d8063e.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-a1912208-446a0899.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/installation.xml create mode 100644 tests/repo/susetags/data/stable-x86-subset/license.tar.gz create mode 100644 tests/repo/susetags/data/stable-x86-subset/media.1/directory.yast create mode 100644 tests/repo/susetags/data/stable-x86-subset/media.1/info.txt create mode 100644 tests/repo/susetags/data/stable-x86-subset/media.1/media create mode 100644 tests/repo/susetags/data/stable-x86-subset/media.1/products create mode 100644 tests/repo/susetags/data/stable-x86-subset/media.1/products.asc create mode 100644 tests/repo/susetags/data/stable-x86-subset/media.1/products.key create mode 100644 tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/kde-10.3-71.noarch.pat create mode 100644 tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages create mode 100644 tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.DU create mode 100644 tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.en create mode 100644 tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.es create mode 100644 tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/patterns create mode 100644 tests/repo/yum/CMakeLists.txt create mode 100644 tests/repo/yum/YUMDownloader_test.cc create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/filelists.xml.gz create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/other.xml.gz create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/patch-fetchmsttfonts.sh-2333.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/patch-flash-player-2359.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/patch-glabels-2348.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/patch-gv-2350.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/patch-openssl-2349.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/patch-tar-2351.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/patches.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/primary.xml.gz create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.asc create mode 100644 tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.key create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/filelists.xml.gz create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/filelists.xml.zck create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/other.xml.gz create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/other.xml.zck create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/patterns.xml.gz create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/primary.xml.gz create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/primary.xml.zck create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/repomd.xml create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/repomd.xml.asc create mode 100644 tests/repo/yum/data/ZCHUNK/repodata/repomd.xml.key create mode 100644 tests/repo/yum/data/extensions/repodata/filelists.xml.gz create mode 100644 tests/repo/yum/data/extensions/repodata/other.xml.gz create mode 100644 tests/repo/yum/data/extensions/repodata/primary.xml.gz create mode 100644 tests/repo/yum/data/extensions/repodata/repomd.xml create mode 100644 tests/repo/yum/data/extensions/repodata/susedata.xml.gz create mode 100644 tests/repo/yum/data/extensions/repodata/suseinfo.xml.gz create mode 100644 tests/sat/BlacklistedPool/@System.repo create mode 100644 tests/sat/BlacklistedPool/Repo.repo create mode 100644 tests/sat/BlacklistedPool/zypp-control.yaml create mode 100644 tests/sat/Blacklisted_test.cc create mode 100644 tests/sat/CMakeLists.txt create mode 100644 tests/sat/IdString_test.cc create mode 100644 tests/sat/LookupAttr_test.cc create mode 100644 tests/sat/Map_test.cc create mode 100644 tests/sat/Pool_test.cc create mode 100644 tests/sat/Queue_test.cc create mode 100644 tests/sat/SolvParsing_test.cc create mode 100644 tests/sat/SolvableSpec_test.cc create mode 100644 tests/sat/Solvable_test.cc create mode 100644 tests/sat/WhatObsoletes_test.cc create mode 100644 tests/sat/WhatProvides_test.cc create mode 100644 tests/zypp/Arch_test.cc create mode 100644 tests/zypp/CMakeLists.txt create mode 100644 tests/zypp/Capabilities_test.cc create mode 100644 tests/zypp/CheckSum_test.cc create mode 100644 tests/zypp/ContentType_test.cc create mode 100644 tests/zypp/CpeId_test.cc create mode 100644 tests/zypp/Date_test.cc create mode 100644 tests/zypp/Deltarpm_test.cc create mode 100644 tests/zypp/Digest_test.cc create mode 100644 tests/zypp/DrunkenBishop_test.cc create mode 100644 tests/zypp/Dup_test.cc create mode 100644 tests/zypp/Edition_test.cc create mode 100644 tests/zypp/ExtendedPool_test.cc create mode 100644 tests/zypp/Fetcher_test.cc create mode 100644 tests/zypp/FileChecker_test.cc create mode 100644 tests/zypp/Flags_test.cc create mode 100644 tests/zypp/GZStream_test.cc create mode 100644 tests/zypp/InstanceId_test.cc create mode 100644 tests/zypp/KeyRingTestReceiver.h create mode 100644 tests/zypp/KeyRing_test.cc create mode 100644 tests/zypp/Locale_test.cc create mode 100644 tests/zypp/Locks_test.cc create mode 100644 tests/zypp/MediaSetAccess_test.cc create mode 100644 tests/zypp/PathInfo_test.cc create mode 100644 tests/zypp/Pathname_test.cc create mode 100644 tests/zypp/PluginFrame_test.cc create mode 100644 tests/zypp/PoolQueryCC_test.cc create mode 100644 tests/zypp/PoolQuery_test.cc create mode 100644 tests/zypp/ProgressData_test.cc create mode 100644 tests/zypp/Proxy_test.cc create mode 100644 tests/zypp/PtrTypes_test.cc create mode 100644 tests/zypp/PublicKey_test.cc create mode 100644 tests/zypp/PurgeKernels_test.cc create mode 100644 tests/zypp/RWPtr_test.cc create mode 100644 tests/zypp/RepoInfo_test.cc create mode 100644 tests/zypp/RepoManager_test.cc create mode 100644 tests/zypp/RepoStatus_test.cc create mode 100644 tests/zypp/ResKind_test.cc create mode 100644 tests/zypp/ResStatus_test.cc create mode 100644 tests/zypp/Resolvable_test.cc create mode 100644 tests/zypp/Resolver_test.cc create mode 100644 tests/zypp/RpmPkgSigCheck_test.cc create mode 100644 tests/zypp/Selectable_test.cc create mode 100644 tests/zypp/SetRelationMixin_test.cc create mode 100644 tests/zypp/SetTracker_test.cc create mode 100644 tests/zypp/Signature_test.cc create mode 100644 tests/zypp/StrMatcher_test.cc create mode 100644 tests/zypp/StringV_test.cc create mode 100644 tests/zypp/Target_test.cc create mode 100644 tests/zypp/Url_test.cc create mode 100644 tests/zypp/UserData_test.cc create mode 100644 tests/zypp/Vendor_test.cc create mode 100644 tests/zypp/ZChunk_test.cc create mode 100644 tests/zypp/base/CMakeLists.txt create mode 100644 tests/zypp/base/ExternalProgram_test.cc create mode 100644 tests/zypp/base/Glob_test.cc create mode 100644 tests/zypp/base/Glob_test.dat/file create mode 100644 tests/zypp/base/Glob_test.dat/file.xml create mode 100644 tests/zypp/base/Glob_test.dat/file.xml.gz create mode 100644 tests/zypp/base/String_test.cc create mode 100644 tests/zypp/base/Sysconfig_test.cc create mode 100755 tests/zypp/base/data/ExternalProgram/echo.sh create mode 100644 tests/zypp/base/data/Sysconfig/proxy create mode 100644 tests/zypp/data/Delta/repodata/deltainfo.xml create mode 100644 tests/zypp/data/Delta/repodata/primary.xml.gz create mode 100644 tests/zypp/data/Delta/repodata/repomd.xml create mode 100644 tests/zypp/data/Delta/repodata/repomd.xml.asc create mode 100644 tests/zypp/data/Delta/repodata/repomd.xml.key create mode 100644 tests/zypp/data/Delta/repodata/updateinfo.xml.gz create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir1/SHA1SUMS create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir1/SHA1SUMS.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir1/SHA1SUMS.key create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir1/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir1/subdir1-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir1/subdir1-file2.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir2/SHA1SUMS create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir2/SHA1SUMS.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir2/SHA1SUMS.key create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir2/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/baseindex/subdir2/subdir2-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir1/SHA1SUMS create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir1/SHA1SUMS.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir1/SHA1SUMS.key create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir1/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir1/subdir1-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir1/subdir1-file2.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir2/SHA1SUMS create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir2/SHA1SUMS.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir2/SHA1SUMS.key create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir2/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir-broken/subdir2/subdir2-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir1/SHA1SUMS create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir1/SHA1SUMS.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir1/SHA1SUMS.key create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir1/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir1/subdir1-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir1/subdir1-file2.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir2/SHA1SUMS create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir2/SHA1SUMS.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir2/SHA1SUMS.key create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir2/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/complexdir/subdir2/subdir2-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/content create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/content.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/content.key create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/subdir1/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/subdir1/subdir1-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/subdir1/subdir1-file2.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/subdir2/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex-broken-digest/subdir2/subdir2-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/content create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/content.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/content.key create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/subdir1/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/subdir1/subdir1-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/subdir1/subdir1-file2.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/subdir2/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/contentindex/subdir2/subdir2-file1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-1-2.diff create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-1-2.diff.gz create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-2-3.diff create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-2-3.diff.gz create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-3-4.diff create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-3-4.diff.gz create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-4-current.diff create mode 100644 tests/zypp/data/Fetcher/remote-site/diffs/file-4-current.diff.gz create mode 100644 tests/zypp/data/Fetcher/remote-site/directory.yast create mode 100644 tests/zypp/data/Fetcher/remote-site/file-1.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/file-2.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/file-3.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/file-4.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/file-current.txt create mode 100644 tests/zypp/data/Fetcher/remote-site/file-current.txt.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/file-current.txt.key create mode 100644 tests/zypp/data/Fetcher/remote-site/images-file-unsigned/content create mode 100644 tests/zypp/data/Fetcher/remote-site/images-file-unsigned/images/images.xml create mode 100644 tests/zypp/data/Fetcher/remote-site/images-file/content create mode 100644 tests/zypp/data/Fetcher/remote-site/images-file/content.asc create mode 100644 tests/zypp/data/Fetcher/remote-site/images-file/content.key create mode 100644 tests/zypp/data/Fetcher/remote-site/images-file/images/images.xml create mode 100644 tests/zypp/data/FileChecker/hello.txt create mode 100644 tests/zypp/data/FileChecker/hello.txt.asc create mode 100644 tests/zypp/data/FileChecker/hello.txt.key create mode 100644 tests/zypp/data/FileChecker/hello2.txt create mode 100644 tests/zypp/data/KeyRing/installkey.gpg create mode 100644 tests/zypp/data/KeyRing/private.asc create mode 100644 tests/zypp/data/KeyRing/public.asc create mode 100644 tests/zypp/data/KeyRing/readme.txt create mode 100644 tests/zypp/data/KeyRing/repomd.xml create mode 100644 tests/zypp/data/KeyRing/repomd.xml.asc create mode 100644 tests/zypp/data/KeyRing/repomd.xml.corrupted create mode 100644 tests/zypp/data/Locks/locks create mode 100644 tests/zypp/data/PoolQuery/savedqueries create mode 100644 tests/zypp/data/PoolQueryCC/rxnames.xml create mode 100644 tests/zypp/data/PublicKey/multikey.asc create mode 100644 tests/zypp/data/PublicKey/multikey2.asc create mode 100644 tests/zypp/data/PublicKey/susekey.asc create mode 100644 tests/zypp/data/PurgeKernels/arch/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/arch/zypp-control.yaml create mode 100644 tests/zypp/data/PurgeKernels/fancybuildnr/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/fancybuildnr/zypp-control.yaml create mode 100644 tests/zypp/data/PurgeKernels/flavour/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/flavour/zypp-control.yaml create mode 100644 tests/zypp/data/PurgeKernels/kernel-base/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/kernel-base/zypp-control.yaml create mode 100644 tests/zypp/data/PurgeKernels/rckrnl/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/rckrnl/zypp-control.yaml create mode 100644 tests/zypp/data/PurgeKernels/rebuild/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/rebuild/zypp-control.yaml create mode 100644 tests/zypp/data/PurgeKernels/simple/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/simple/zypp-control.yaml create mode 100644 tests/zypp/data/PurgeKernels/withdeps/@System.repo create mode 100644 tests/zypp/data/PurgeKernels/withdeps/zypp-control.yaml create mode 100755 tests/zypp/data/RepoManager/plugin-service-lib-1/services/service create mode 100755 tests/zypp/data/RepoManager/plugin-service-lib-2/services/service create mode 100644 tests/zypp/data/RepoManager/proprietary.repo create mode 100644 tests/zypp/data/RepoManager/repo/repoindex.xml create mode 100644 tests/zypp/data/RepoManager/repos.d/filesharing.repo create mode 100644 tests/zypp/data/RepoManager/repos.d/home:dmacvicar.repo create mode 100644 tests/zypp/data/RepoManager/repos.d/proprietary.repo create mode 100644 tests/zypp/data/RepoManager/repos.d/ruby.repo create mode 100644 tests/zypp/data/RepoManager/second/repo/repoindex.xml create mode 100644 tests/zypp/data/RpmPkgSigCheck/no.rpm create mode 100644 tests/zypp/data/RpmPkgSigCheck/signed.key create mode 100644 tests/zypp/data/RpmPkgSigCheck/signed.rpm create mode 100644 tests/zypp/data/RpmPkgSigCheck/signed_broken.rpm create mode 100644 tests/zypp/data/RpmPkgSigCheck/signed_broken_header.rpm create mode 100644 tests/zypp/data/RpmPkgSigCheck/unsigned.rpm create mode 100644 tests/zypp/data/RpmPkgSigCheck/unsigned_broken.rpm create mode 100644 tests/zypp/data/RpmPkgSigCheck/unsigned_broken_header.rpm create mode 100644 tests/zypp/data/Target/product.prod create mode 100644 tests/zypp/data/Vendor/vendors.d/ati create mode 100644 tests/zypp/data/Vendor/vendors.d/nvidia create mode 100644 tests/zypp/data/mediasetaccess/src1/cd1/dir/file1 create mode 100644 tests/zypp/data/mediasetaccess/src1/cd1/dir/file2 create mode 100644 tests/zypp/data/mediasetaccess/src1/cd1/dir/subdir/file create mode 100644 tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt create mode 100644 tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt create mode 100644 tests/zypp/data/mediasetaccess/src1/cd1/test.txt create mode 100644 tests/zypp/data/mediasetaccess/src1/cd1/x.media1 create mode 100644 tests/zypp/data/mediasetaccess/src1/cd2/test.txt create mode 100644 tests/zypp/data/mediasetaccess/src1/cd2/x.mediabad create mode 100644 tests/zypp/data/mediasetaccess/src1/cd3/test.txt create mode 100644 tests/zypp/data/mediasetaccess/src1/cd3/x.media3 create mode 100644 tests/zypp/data/mediasetaccess/src2/test.txt create mode 100644 tests/zypp/data/mediasetaccess/src2/x.media create mode 100644 tests/zyppng/CMakeLists.txt create mode 100644 tests/zyppng/EventLoop_test.cc create mode 100644 tests/zyppng/IOBuffer_test.cc create mode 100644 tests/zyppng/Pipelines_test.cc create mode 100644 tests/zyppng/UnixSignalSource_test.cc create mode 100644 tests/zyppng/data/downloader/auth-http.meta create mode 100644 tests/zyppng/data/downloader/auth-https.meta create mode 100644 tests/zyppng/data/downloader/media.1/media create mode 100644 tests/zyppng/data/downloader/primary-deltatemplate.xml.zck create mode 100644 tests/zyppng/data/downloader/primary.xml.zck create mode 100644 tests/zyppng/data/downloader/primary.xml.zck.meta create mode 100644 tests/zyppng/data/downloader/test.txt create mode 100644 tests/zyppng/data/downloader/test.txt.meta create mode 100644 tests/zyppng/data/downloader/test_noblock.txt.meta create mode 100755 tests/zyppng/data/process/echo.sh create mode 100644 tests/zyppng/data/provide/cd1/file1 create mode 100644 tests/zyppng/data/provide/cd1/media.1/media create mode 100644 tests/zyppng/data/provide/cd2/file2 create mode 100644 tests/zyppng/data/provide/cd2/media.2/media create mode 100644 tests/zyppng/data/provide/cd3/file3 create mode 100644 tests/zyppng/data/provide/cd3/media.3/media create mode 100644 tests/zyppng/data/provide/cd4/file4 create mode 100644 tests/zyppng/data/provide/cd4/media.4/media create mode 100644 tests/zyppng/io/AsyncDataSource_test.cc create mode 100644 tests/zyppng/io/CMakeLists.txt create mode 100644 tests/zyppng/io/Process_test.cc create mode 100644 tests/zyppng/io/UnixSocket_test.cc create mode 100644 tests/zyppng/media/CMakeLists.txt create mode 100644 tests/zyppng/media/EvDownloader_test.cc create mode 100644 tests/zyppng/media/NetworkRequestDispatcher_test.cc create mode 100644 tests/zyppng/media/Provider_test.cc create mode 100644 tests/zyppng/rpc/CMakeLists.txt create mode 100644 tests/zyppng/rpc/StompMessageStream_test.cc create mode 100644 tools/CMakeLists.txt create mode 100644 tools/CalculateReusableBlocks.cc create mode 100644 tools/DiskUsageCounter.cc create mode 100644 tools/DownloadFiles.cc create mode 100644 tools/DumpSelectable.cc create mode 100644 tools/ProvideSignedDirectory.cc create mode 100755 tools/ScanTwHistory create mode 100644 tools/ToolScanRepos.cc create mode 100644 tools/argparse.h create mode 100644 tools/migrate-sources/CMakeLists.txt create mode 100644 tools/migrate-sources/migrate-sources.cc create mode 100644 tools/patch_find_bug.cc create mode 100644 tools/percent-encode.cc create mode 100644 tools/refresh-ng/CMakeLists.txt create mode 100644 tools/refresh-ng/main.cc create mode 100644 tools/refresh-ng/output.h create mode 100644 tools/repomirror/CMakeLists.txt create mode 100644 tools/repomirror/main.cc create mode 100644 tools/repomirror/output.h create mode 100644 tools/zypp-CheckAccessDeleted.cc create mode 100644 tools/zypp-NameReqPrv.cc create mode 100644 tools/zypp-cpeid.cc create mode 100644 tools/zypp-install.cc create mode 100644 tools/zypp-list.cc create mode 100644 tools/zypp-media-chksum/CMakeLists.txt create mode 100644 tools/zypp-media-chksum/main.cc create mode 100644 tools/zypp-media-copy/CMakeLists.txt create mode 100644 tools/zypp-media-copy/main.cc create mode 100644 tools/zypp-media-dir/CMakeLists.txt create mode 100644 tools/zypp-media-dir/dirprovider.cc create mode 100644 tools/zypp-media-dir/dirprovider.h create mode 100644 tools/zypp-media-dir/main.cc create mode 100644 tools/zypp-media-disc/CMakeLists.txt create mode 100644 tools/zypp-media-disc/discprovider.cc create mode 100644 tools/zypp-media-disc/discprovider.h create mode 100644 tools/zypp-media-disc/main.cc create mode 100644 tools/zypp-media-disk/CMakeLists.txt create mode 100644 tools/zypp-media-disk/diskprovider.cc create mode 100644 tools/zypp-media-disk/diskprovider.h create mode 100644 tools/zypp-media-disk/main.cc create mode 100644 tools/zypp-media-http/CMakeLists.txt create mode 100644 tools/zypp-media-http/main.cc create mode 100644 tools/zypp-media-http/networkprovider.cc create mode 100644 tools/zypp-media-http/networkprovider.h create mode 100644 tools/zypp-media-iso/CMakeLists.txt create mode 100644 tools/zypp-media-iso/isoprovider.cc create mode 100644 tools/zypp-media-iso/isoprovider.h create mode 100644 tools/zypp-media-iso/main.cc create mode 100644 tools/zypp-media-nfs/CMakeLists.txt create mode 100644 tools/zypp-media-nfs/main.cc create mode 100644 tools/zypp-media-nfs/nfsprovider.cc create mode 100644 tools/zypp-media-nfs/nfsprovider.h create mode 100644 tools/zypp-media-smb/CMakeLists.txt create mode 100644 tools/zypp-media-smb/main.cc create mode 100644 tools/zypp-media-smb/smbprovider.cc create mode 100644 tools/zypp-media-smb/smbprovider.h create mode 100644 tools/zypp-media-tvm/CMakeLists.txt create mode 100644 tools/zypp-media-tvm/main.cc create mode 100644 tools/zypp-media-tvm/testvmprovider.cc create mode 100644 tools/zypp-media-tvm/testvmprovider.h create mode 100644 tools/zypp-pubkey.cc create mode 100644 tools/zypp-rpm/BinHeader.cc create mode 100644 tools/zypp-rpm/BinHeader.h create mode 100644 tools/zypp-rpm/CMakeLists.txt create mode 100644 tools/zypp-rpm/errorcodes.h create mode 100644 tools/zypp-rpm/main.cc create mode 100644 tools/zypp-runpurge.cc create mode 100644 zypp-core/APIConfig.h.in create mode 100644 zypp-core/AutoDispose.h create mode 100644 zypp-core/ByteArray.h create mode 100644 zypp-core/ByteCount.cc create mode 100644 zypp-core/ByteCount.h create mode 100644 zypp-core/CMakeLists.txt create mode 100644 zypp-core/CheckSum.cc create mode 100644 zypp-core/CheckSum.h create mode 100644 zypp-core/Date.cc create mode 100644 zypp-core/Date.h create mode 100644 zypp-core/Digest.cc create mode 100644 zypp-core/Digest.h create mode 100644 zypp-core/ExternalProgram.cc create mode 100644 zypp-core/ExternalProgram.h create mode 100644 zypp-core/Globals.h create mode 100644 zypp-core/KVMap create mode 100644 zypp-core/ManagedFile.h create mode 100644 zypp-core/OnMediaLocation create mode 100644 zypp-core/Pathname.cc create mode 100644 zypp-core/Pathname.h create mode 100644 zypp-core/ShutdownLock.cc create mode 100644 zypp-core/ShutdownLock_p.h create mode 100644 zypp-core/TriBool.h create mode 100644 zypp-core/Url.cc create mode 100644 zypp-core/Url.h create mode 100644 zypp-core/UserData.h create mode 100644 zypp-core/base/CleanerThread.cc create mode 100644 zypp-core/base/CleanerThread_p.h create mode 100644 zypp-core/base/DefaultIntegral create mode 100644 zypp-core/base/DtorReset create mode 100644 zypp-core/base/Easy.h create mode 100644 zypp-core/base/EnumClass.h create mode 100644 zypp-core/base/Errno.h create mode 100644 zypp-core/base/Exception.cc create mode 100644 zypp-core/base/Exception.h create mode 100644 zypp-core/base/ExternalDataSource.cc create mode 100644 zypp-core/base/ExternalDataSource.h create mode 100644 zypp-core/base/FileStreamBuf create mode 100644 zypp-core/base/Flags.h create mode 100644 zypp-core/base/Function.h create mode 100644 zypp-core/base/Gettext.cc create mode 100644 zypp-core/base/Gettext.h create mode 100644 zypp-core/base/GzStream create mode 100644 zypp-core/base/Hash.h create mode 100644 zypp-core/base/IOStream.cc create mode 100644 zypp-core/base/IOStream.h create mode 100644 zypp-core/base/IOTools.cc create mode 100644 zypp-core/base/IOTools.h create mode 100644 zypp-core/base/InputStream create mode 100644 zypp-core/base/Iterable.h create mode 100644 zypp-core/base/Iterator.h create mode 100644 zypp-core/base/LogControl.cc create mode 100644 zypp-core/base/LogControl.h create mode 100644 zypp-core/base/LogTools.h create mode 100644 zypp-core/base/Logger.h create mode 100644 zypp-core/base/NonCopyable.h create mode 100644 zypp-core/base/ProfilingFormater.cc create mode 100644 zypp-core/base/ProfilingFormater.h create mode 100644 zypp-core/base/ProvideNumericId create mode 100644 zypp-core/base/PtrTypes.h create mode 100644 zypp-core/base/ReferenceCounted.cc create mode 100644 zypp-core/base/ReferenceCounted.h create mode 100644 zypp-core/base/Regex.cc create mode 100644 zypp-core/base/Regex.h create mode 100644 zypp-core/base/SimpleStreambuf create mode 100644 zypp-core/base/String.cc create mode 100644 zypp-core/base/String.h create mode 100644 zypp-core/base/StringV.cc create mode 100644 zypp-core/base/StringV.h create mode 100644 zypp-core/base/Unit.cc create mode 100644 zypp-core/base/Unit.h create mode 100644 zypp-core/base/UserRequestException create mode 100644 zypp-core/base/Xml.cc create mode 100644 zypp-core/base/Xml.h create mode 100644 zypp-core/base/ZckStream create mode 100644 zypp-core/base/defaultintegral.h create mode 100644 zypp-core/base/dtorreset.h create mode 100644 zypp-core/base/fXstream create mode 100644 zypp-core/base/filestreambuf.cc create mode 100644 zypp-core/base/filestreambuf.h create mode 100644 zypp-core/base/fxstream.h create mode 100644 zypp-core/base/gzstream.cc create mode 100644 zypp-core/base/gzstream.h create mode 100644 zypp-core/base/inputstream.cc create mode 100644 zypp-core/base/inputstream.h create mode 100644 zypp-core/base/providenumericid.h create mode 100644 zypp-core/base/simplestreambuf.h create mode 100644 zypp-core/base/userrequestexception.cc create mode 100644 zypp-core/base/userrequestexception.h create mode 100644 zypp-core/base/zckstream.cc create mode 100644 zypp-core/base/zckstream.h create mode 100644 zypp-core/fs/PathInfo.cc create mode 100644 zypp-core/fs/PathInfo.h create mode 100644 zypp-core/fs/TmpPath.cc create mode 100644 zypp-core/fs/TmpPath.h create mode 100644 zypp-core/fs/WatchFile create mode 100644 zypp-core/fs/watchfile.h create mode 100644 zypp-core/kvmap.h create mode 100644 zypp-core/onmedialocation.cc create mode 100644 zypp-core/onmedialocation.h create mode 100644 zypp-core/parser/IniDict create mode 100644 zypp-core/parser/IniParser create mode 100644 zypp-core/parser/ParseException create mode 100644 zypp-core/parser/Sysconfig create mode 100644 zypp-core/parser/inidict.cc create mode 100644 zypp-core/parser/inidict.h create mode 100644 zypp-core/parser/iniparser.cc create mode 100644 zypp-core/parser/iniparser.h create mode 100644 zypp-core/parser/parseexception.cc create mode 100644 zypp-core/parser/parseexception.h create mode 100644 zypp-core/parser/sysconfig.cc create mode 100644 zypp-core/parser/sysconfig.h create mode 100644 zypp-core/parser/xml/XmlEscape.cc create mode 100644 zypp-core/parser/xml/XmlEscape.h create mode 100644 zypp-core/rpc/PluginFrame.cc create mode 100644 zypp-core/rpc/PluginFrame.h create mode 100644 zypp-core/rpc/PluginFrameException.cc create mode 100644 zypp-core/rpc/PluginFrameException.h create mode 100644 zypp-core/ui/ProgressData create mode 100644 zypp-core/ui/progressdata.cc create mode 100644 zypp-core/ui/progressdata.h create mode 100644 zypp-core/url/UrlBase.cc create mode 100644 zypp-core/url/UrlBase.h create mode 100644 zypp-core/url/UrlException.h create mode 100644 zypp-core/url/UrlUtils.cc create mode 100644 zypp-core/url/UrlUtils.h create mode 100644 zypp-core/zyppng/async/AsyncOp create mode 100644 zypp-core/zyppng/async/asyncop.h create mode 100644 zypp-core/zyppng/base/AbstractEventSource create mode 100644 zypp-core/zyppng/base/AutoDisconnect create mode 100644 zypp-core/zyppng/base/Base create mode 100644 zypp-core/zyppng/base/EventDispatcher create mode 100644 zypp-core/zyppng/base/EventLoop create mode 100644 zypp-core/zyppng/base/Signals create mode 100644 zypp-core/zyppng/base/SocketNotifier create mode 100644 zypp-core/zyppng/base/Timer create mode 100644 zypp-core/zyppng/base/UnixSignalSource create mode 100644 zypp-core/zyppng/base/abstracteventsource.cc create mode 100644 zypp-core/zyppng/base/abstracteventsource.h create mode 100644 zypp-core/zyppng/base/autodisconnect.h create mode 100644 zypp-core/zyppng/base/base.cc create mode 100644 zypp-core/zyppng/base/base.h create mode 100644 zypp-core/zyppng/base/eventdispatcher.h create mode 100644 zypp-core/zyppng/base/eventdispatcher_glib.cc create mode 100644 zypp-core/zyppng/base/eventloop.h create mode 100644 zypp-core/zyppng/base/eventloop_glib.cc create mode 100644 zypp-core/zyppng/base/linuxhelpers.cc create mode 100644 zypp-core/zyppng/base/private/abstracteventsource_p.h create mode 100644 zypp-core/zyppng/base/private/base_p.h create mode 100644 zypp-core/zyppng/base/private/eventdispatcher_glib_p.h create mode 100644 zypp-core/zyppng/base/private/eventloop_glib_p.h create mode 100644 zypp-core/zyppng/base/private/linuxhelpers_p.h create mode 100644 zypp-core/zyppng/base/private/threaddata_p.h create mode 100644 zypp-core/zyppng/base/signals.h create mode 100644 zypp-core/zyppng/base/socketnotifier.cc create mode 100644 zypp-core/zyppng/base/socketnotifier.h create mode 100644 zypp-core/zyppng/base/statemachine.h create mode 100644 zypp-core/zyppng/base/threaddata.cc create mode 100644 zypp-core/zyppng/base/timer.cc create mode 100644 zypp-core/zyppng/base/timer.h create mode 100644 zypp-core/zyppng/base/unixsignalsource.cpp create mode 100644 zypp-core/zyppng/base/unixsignalsource.h create mode 100644 zypp-core/zyppng/base/zyppglobal.h create mode 100644 zypp-core/zyppng/core/ByteArray create mode 100644 zypp-core/zyppng/core/Env create mode 100644 zypp-core/zyppng/core/IdString create mode 100644 zypp-core/zyppng/core/String create mode 100644 zypp-core/zyppng/core/Url create mode 100644 zypp-core/zyppng/core/bytearray.h create mode 100644 zypp-core/zyppng/core/env.h create mode 100644 zypp-core/zyppng/core/idstring.h create mode 100644 zypp-core/zyppng/core/string.h create mode 100644 zypp-core/zyppng/core/url.h create mode 100644 zypp-core/zyppng/io/AsyncDataSource create mode 100644 zypp-core/zyppng/io/IODevice create mode 100644 zypp-core/zyppng/io/Process create mode 100644 zypp-core/zyppng/io/SockAddr create mode 100644 zypp-core/zyppng/io/Socket create mode 100644 zypp-core/zyppng/io/abstractspawnengine.cc create mode 100644 zypp-core/zyppng/io/asyncdatasource.cpp create mode 100644 zypp-core/zyppng/io/asyncdatasource.h create mode 100644 zypp-core/zyppng/io/forkspawnengine.cc create mode 100644 zypp-core/zyppng/io/iobuffer.cc create mode 100644 zypp-core/zyppng/io/iodevice.cc create mode 100644 zypp-core/zyppng/io/iodevice.h create mode 100644 zypp-core/zyppng/io/private/abstractspawnengine_p.h create mode 100644 zypp-core/zyppng/io/private/asyncdatasource_p.h create mode 100644 zypp-core/zyppng/io/private/forkspawnengine_p.h create mode 100644 zypp-core/zyppng/io/private/iobuffer_p.h create mode 100644 zypp-core/zyppng/io/private/iodevice_p.h create mode 100644 zypp-core/zyppng/io/private/sockaddr_p.h create mode 100644 zypp-core/zyppng/io/private/socket_p.h create mode 100644 zypp-core/zyppng/io/process.cpp create mode 100644 zypp-core/zyppng/io/process.h create mode 100644 zypp-core/zyppng/io/sockaddr.cpp create mode 100644 zypp-core/zyppng/io/sockaddr.h create mode 100644 zypp-core/zyppng/io/socket.cc create mode 100644 zypp-core/zyppng/io/socket.h create mode 100644 zypp-core/zyppng/meta/FunctionTraits create mode 100644 zypp-core/zyppng/meta/Functional create mode 100644 zypp-core/zyppng/meta/TypeTraits create mode 100644 zypp-core/zyppng/meta/function_traits.h create mode 100644 zypp-core/zyppng/meta/functional.h create mode 100644 zypp-core/zyppng/meta/type_traits.h create mode 100644 zypp-core/zyppng/pipelines/Algorithm create mode 100644 zypp-core/zyppng/pipelines/AsyncResult create mode 100644 zypp-core/zyppng/pipelines/Await create mode 100644 zypp-core/zyppng/pipelines/Expected create mode 100644 zypp-core/zyppng/pipelines/Lift create mode 100644 zypp-core/zyppng/pipelines/MTry create mode 100644 zypp-core/zyppng/pipelines/Redo create mode 100644 zypp-core/zyppng/pipelines/Transform create mode 100644 zypp-core/zyppng/pipelines/Wait create mode 100644 zypp-core/zyppng/pipelines/algorithm.h create mode 100644 zypp-core/zyppng/pipelines/asyncresult.h create mode 100644 zypp-core/zyppng/pipelines/await.h create mode 100644 zypp-core/zyppng/pipelines/expected.h create mode 100644 zypp-core/zyppng/pipelines/lift.h create mode 100644 zypp-core/zyppng/pipelines/mtry.h create mode 100644 zypp-core/zyppng/pipelines/redo.h create mode 100644 zypp-core/zyppng/pipelines/transform.h create mode 100644 zypp-core/zyppng/pipelines/wait.h create mode 100644 zypp-core/zyppng/rpc/stompframestream.cc create mode 100644 zypp-core/zyppng/rpc/stompframestream.h create mode 100644 zypp-core/zyppng/thread/AsyncQueue create mode 100644 zypp-core/zyppng/thread/Wakeup create mode 100644 zypp-core/zyppng/thread/asyncqueue.cc create mode 100644 zypp-core/zyppng/thread/asyncqueue.h create mode 100644 zypp-core/zyppng/thread/private/asyncqueue_p.h create mode 100644 zypp-core/zyppng/thread/wakeup.cpp create mode 100644 zypp-core/zyppng/thread/wakeup.h create mode 100644 zypp-core/zyppng/ui/ProgressObserver create mode 100644 zypp-core/zyppng/ui/UserInterface create mode 100644 zypp-core/zyppng/ui/UserRequest create mode 100644 zypp-core/zyppng/ui/private/userinterface_p.h create mode 100644 zypp-core/zyppng/ui/progressobserver.cc create mode 100644 zypp-core/zyppng/ui/progressobserver.h create mode 100644 zypp-core/zyppng/ui/userinterface.cc create mode 100644 zypp-core/zyppng/ui/userinterface.h create mode 100644 zypp-core/zyppng/ui/userrequest.cc create mode 100644 zypp-core/zyppng/ui/userrequest.h create mode 100644 zypp-curl/CMakeLists.txt create mode 100644 zypp-curl/CurlConfig create mode 100644 zypp-curl/ProxyInfo create mode 100644 zypp-curl/TransferSettings create mode 100644 zypp-curl/auth/CurlAuthData create mode 100644 zypp-curl/auth/curlauthdata.cc create mode 100644 zypp-curl/auth/curlauthdata.h create mode 100644 zypp-curl/curlconfig.cc create mode 100644 zypp-curl/curlconfig.h create mode 100644 zypp-curl/curlhelper.cc create mode 100644 zypp-curl/ng/network/AuthData create mode 100644 zypp-curl/ng/network/DownloadSpec create mode 100644 zypp-curl/ng/network/Downloader create mode 100644 zypp-curl/ng/network/MirrorControl create mode 100644 zypp-curl/ng/network/NetworkRequestDispatcher create mode 100644 zypp-curl/ng/network/NetworkRequestError create mode 100644 zypp-curl/ng/network/Request create mode 100644 zypp-curl/ng/network/TransferSettings create mode 100644 zypp-curl/ng/network/authdata.h create mode 100644 zypp-curl/ng/network/curlmultiparthandler.cc create mode 100644 zypp-curl/ng/network/curlmultiparthandler.h create mode 100644 zypp-curl/ng/network/downloader.cc create mode 100644 zypp-curl/ng/network/downloader.h create mode 100644 zypp-curl/ng/network/downloadspec.cc create mode 100644 zypp-curl/ng/network/downloadspec.h create mode 100644 zypp-curl/ng/network/mirrorcontrol.cc create mode 100644 zypp-curl/ng/network/networkrequestdispatcher.cc create mode 100644 zypp-curl/ng/network/networkrequestdispatcher.h create mode 100644 zypp-curl/ng/network/networkrequesterror.cc create mode 100644 zypp-curl/ng/network/networkrequesterror.h create mode 100644 zypp-curl/ng/network/private/downloader_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/base_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/detectmeta_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/detectmeta_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/final_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/final_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/initial_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/initial_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/metalink_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/metalink_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/normal_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/normal_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/preparemulti_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/preparemulti_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.h create mode 100644 zypp-curl/ng/network/private/downloaderstates/zck_p.cc create mode 100644 zypp-curl/ng/network/private/downloaderstates/zck_p.h create mode 100644 zypp-curl/ng/network/private/mediadebug_p.h create mode 100644 zypp-curl/ng/network/private/mirrorcontrol_p.h create mode 100644 zypp-curl/ng/network/private/networkrequestdispatcher_p.h create mode 100644 zypp-curl/ng/network/private/networkrequesterror_p.h create mode 100644 zypp-curl/ng/network/private/request_p.h create mode 100644 zypp-curl/ng/network/request.cc create mode 100644 zypp-curl/ng/network/request.h create mode 100644 zypp-curl/ng/network/transfersettings.h create mode 100644 zypp-curl/parser/MediaBlockList create mode 100644 zypp-curl/parser/MetaLinkParser create mode 100644 zypp-curl/parser/ZsyncParser create mode 100644 zypp-curl/parser/mediablocklist.cc create mode 100644 zypp-curl/parser/mediablocklist.h create mode 100644 zypp-curl/parser/metadatahelper.cc create mode 100644 zypp-curl/parser/metadatahelper.h create mode 100644 zypp-curl/parser/metalinkparser.cc create mode 100644 zypp-curl/parser/metalinkparser.h create mode 100644 zypp-curl/parser/zsyncparser.cc create mode 100644 zypp-curl/parser/zsyncparser.h create mode 100644 zypp-curl/private/curlhelper_p.h create mode 100644 zypp-curl/proxyinfo.cc create mode 100644 zypp-curl/proxyinfo.h create mode 100644 zypp-curl/proxyinfo/ProxyInfoLibproxy create mode 100644 zypp-curl/proxyinfo/ProxyInfoSysconfig create mode 100644 zypp-curl/proxyinfo/proxyinfoimpl.h create mode 100644 zypp-curl/proxyinfo/proxyinfolibproxy.cc create mode 100644 zypp-curl/proxyinfo/proxyinfolibproxy.h create mode 100644 zypp-curl/proxyinfo/proxyinfos.h create mode 100644 zypp-curl/proxyinfo/proxyinfosysconfig.cc create mode 100644 zypp-curl/proxyinfo/proxyinfosysconfig.h create mode 100644 zypp-curl/transfersettings.cc create mode 100644 zypp-curl/transfersettings.h create mode 100644 zypp-history.lr create mode 100644 zypp-media/CDTools create mode 100644 zypp-media/CMakeLists.txt create mode 100644 zypp-media/FileCheckException create mode 100644 zypp-media/MediaConfig create mode 100644 zypp-media/MediaException create mode 100644 zypp-media/Mount create mode 100644 zypp-media/auth/AuthData create mode 100644 zypp-media/auth/CredentialFileReader create mode 100644 zypp-media/auth/CredentialManager create mode 100644 zypp-media/auth/authdata.cc create mode 100644 zypp-media/auth/authdata.h create mode 100644 zypp-media/auth/credentialfilereader.cc create mode 100644 zypp-media/auth/credentialfilereader.h create mode 100644 zypp-media/auth/credentialmanager.cc create mode 100644 zypp-media/auth/credentialmanager.h create mode 100644 zypp-media/cdtools.cc create mode 100644 zypp-media/cdtools.h create mode 100644 zypp-media/filecheckexception.cc create mode 100644 zypp-media/filecheckexception.h create mode 100644 zypp-media/mediaconfig.cc create mode 100644 zypp-media/mediaconfig.h create mode 100644 zypp-media/mediaexception.cc create mode 100644 zypp-media/mediaexception.h create mode 100644 zypp-media/mount.cc create mode 100644 zypp-media/mount.h create mode 100644 zypp-media/ng/HeaderValueMap create mode 100644 zypp-media/ng/LazyMediaHandle create mode 100644 zypp-media/ng/MediaVerifier create mode 100644 zypp-media/ng/Provide create mode 100644 zypp-media/ng/ProvideFwd create mode 100644 zypp-media/ng/ProvideItem create mode 100644 zypp-media/ng/ProvideRes create mode 100644 zypp-media/ng/ProvideSpec create mode 100644 zypp-media/ng/attachedmediainfo.cc create mode 100644 zypp-media/ng/headervaluemap.cc create mode 100644 zypp-media/ng/headervaluemap.h create mode 100644 zypp-media/ng/lazymediahandle.h create mode 100644 zypp-media/ng/mediaverifier.cc create mode 100644 zypp-media/ng/mediaverifier.h create mode 100644 zypp-media/ng/private/attachedmediainfo_p.h create mode 100644 zypp-media/ng/private/provide_p.h create mode 100644 zypp-media/ng/private/providedbg_p.h create mode 100644 zypp-media/ng/private/providefwd_p.h create mode 100644 zypp-media/ng/private/provideitem_p.h create mode 100644 zypp-media/ng/private/providemessage_p.h create mode 100644 zypp-media/ng/private/providequeue_p.h create mode 100644 zypp-media/ng/private/provideres_p.h create mode 100644 zypp-media/ng/provide-configvars.h create mode 100644 zypp-media/ng/provide.cc create mode 100644 zypp-media/ng/provide.h create mode 100644 zypp-media/ng/providefwd.h create mode 100644 zypp-media/ng/provideitem.cc create mode 100644 zypp-media/ng/provideitem.h create mode 100644 zypp-media/ng/providemessage.cc create mode 100644 zypp-media/ng/providequeue.cc create mode 100644 zypp-media/ng/provideres.cc create mode 100644 zypp-media/ng/provideres.h create mode 100644 zypp-media/ng/providespec.cc create mode 100644 zypp-media/ng/providespec.h create mode 100644 zypp-media/ng/worker/DeviceDriver create mode 100644 zypp-media/ng/worker/MountingWorker create mode 100644 zypp-media/ng/worker/ProvideWorker create mode 100644 zypp-media/ng/worker/devicedriver.cc create mode 100644 zypp-media/ng/worker/devicedriver.h create mode 100644 zypp-media/ng/worker/mountingworker.cc create mode 100644 zypp-media/ng/worker/mountingworker.h create mode 100644 zypp-media/ng/worker/provideworker.cc create mode 100644 zypp-media/ng/worker/provideworker.h create mode 100644 zypp-tui/Application create mode 100644 zypp-tui/CMakeLists.txt create mode 100644 zypp-tui/Config create mode 100644 zypp-tui/Table.cc create mode 100644 zypp-tui/Table.h create mode 100644 zypp-tui/application.cc create mode 100644 zypp-tui/application.h create mode 100644 zypp-tui/config.cc create mode 100644 zypp-tui/config.h create mode 100644 zypp-tui/output/AliveCursor.h create mode 100644 zypp-tui/output/Out.cc create mode 100644 zypp-tui/output/Out.h create mode 100644 zypp-tui/output/OutNormal.cc create mode 100644 zypp-tui/output/OutNormal.h create mode 100644 zypp-tui/output/PromptOptions create mode 100644 zypp-tui/output/Utf8.h create mode 100644 zypp-tui/output/promptoptions.cc create mode 100644 zypp-tui/output/promptoptions.h create mode 100644 zypp-tui/utils/ansi.h create mode 100644 zypp-tui/utils/colors.cc create mode 100644 zypp-tui/utils/colors.h create mode 100644 zypp-tui/utils/console.cc create mode 100644 zypp-tui/utils/console.h create mode 100644 zypp-tui/utils/richtext.cc create mode 100644 zypp-tui/utils/richtext.h create mode 100644 zypp-tui/utils/text.cc create mode 100644 zypp-tui/utils/text.h create mode 100644 zypp.conf create mode 100644 zypp/APIConfig.h create mode 100644 zypp/Application.cc create mode 100644 zypp/Application.h create mode 100644 zypp/Arch.cc create mode 100644 zypp/Arch.h create mode 100644 zypp/AutoDispose.h create mode 100644 zypp/Bit.h create mode 100644 zypp/Bitmap.h create mode 100644 zypp/ByteArray.h create mode 100644 zypp/ByteCount.h create mode 100644 zypp/CMakeLists.txt create mode 100644 zypp/Callback.h create mode 100644 zypp/CapMatch.cc create mode 100644 zypp/CapMatch.h create mode 100644 zypp/Capabilities.cc create mode 100644 zypp/Capabilities.h create mode 100644 zypp/Capability.cc create mode 100644 zypp/Capability.h create mode 100644 zypp/Changelog.cc create mode 100644 zypp/Changelog.h create mode 100644 zypp/CheckSum.cc create mode 100644 zypp/CheckSum.h create mode 100644 zypp/ContentType.h create mode 100644 zypp/CountryCode.cc create mode 100644 zypp/CountryCode.h create mode 100644 zypp/CpeId.cc create mode 100644 zypp/CpeId.h create mode 100644 zypp/Date.h create mode 100644 zypp/Dep.cc create mode 100644 zypp/Dep.h create mode 100644 zypp/Digest.cc create mode 100644 zypp/Digest.h create mode 100644 zypp/DiskUsageCounter.cc create mode 100644 zypp/DiskUsageCounter.h create mode 100644 zypp/DownloadMode.cc create mode 100644 zypp/DownloadMode.h create mode 100644 zypp/Edition.cc create mode 100644 zypp/Edition.h create mode 100644 zypp/ExternalProgram.h create mode 100644 zypp/Fetcher.cc create mode 100644 zypp/Fetcher.h create mode 100644 zypp/FileChecker.cc create mode 100644 zypp/FileChecker.h create mode 100644 zypp/Filter.h create mode 100644 zypp/Glob.cc create mode 100644 zypp/Glob.h create mode 100644 zypp/Globals.h create mode 100644 zypp/HistoryLog.cc create mode 100644 zypp/HistoryLog.h create mode 100644 zypp/HistoryLogData.cc create mode 100644 zypp/HistoryLogData.h create mode 100644 zypp/IdString.cc create mode 100644 zypp/IdString.h create mode 100644 zypp/IdStringType.h create mode 100644 zypp/InstanceId.cc create mode 100644 zypp/InstanceId.h create mode 100644 zypp/KVMap.h create mode 100644 zypp/KeyContext.h create mode 100644 zypp/KeyManager.cc create mode 100644 zypp/KeyManager.h create mode 100644 zypp/KeyRing.cc create mode 100644 zypp/KeyRing.h create mode 100644 zypp/KeyRingContexts.cc create mode 100644 zypp/KeyRingContexts.h create mode 100644 zypp/LanguageCode.cc create mode 100644 zypp/LanguageCode.h create mode 100644 zypp/Locale.cc create mode 100644 zypp/Locale.h create mode 100644 zypp/Locks.cc create mode 100644 zypp/Locks.h create mode 100644 zypp/ManagedFile.h create mode 100644 zypp/MediaProducts.h create mode 100644 zypp/MediaSetAccess.cc create mode 100644 zypp/MediaSetAccess.h create mode 100644 zypp/Misc.h create mode 100644 zypp/OnMediaLocation.h create mode 100644 zypp/Package.cc create mode 100644 zypp/Package.h create mode 100644 zypp/PackageKeyword.h create mode 100644 zypp/Patch.cc create mode 100644 zypp/Patch.h create mode 100644 zypp/PathInfo.cc create mode 100644 zypp/PathInfo.h create mode 100644 zypp/Pathname.h create mode 100644 zypp/Pattern.cc create mode 100644 zypp/Pattern.h create mode 100644 zypp/PluginExecutor.cc create mode 100644 zypp/PluginExecutor.h create mode 100644 zypp/PluginScript.cc create mode 100644 zypp/PluginScript.h create mode 100644 zypp/PluginScriptException.cc create mode 100644 zypp/PluginScriptException.h create mode 100644 zypp/PoolItem.cc create mode 100644 zypp/PoolItem.h create mode 100644 zypp/PoolItemBest.cc create mode 100644 zypp/PoolItemBest.h create mode 100644 zypp/PoolQuery.cc create mode 100644 zypp/PoolQuery.h create mode 100644 zypp/PoolQueryResult.cc create mode 100644 zypp/PoolQueryResult.h create mode 100644 zypp/PoolQueryUtil.tcc create mode 100644 zypp/ProblemSolution.cc create mode 100644 zypp/ProblemSolution.h create mode 100644 zypp/ProblemTypes.h create mode 100644 zypp/Product.cc create mode 100644 zypp/Product.h create mode 100644 zypp/ProgressData.h create mode 100644 zypp/ProvideFilePolicy.cc create mode 100644 zypp/ProvideFilePolicy.h create mode 100644 zypp/PublicKey.cc create mode 100644 zypp/PublicKey.h create mode 100644 zypp/PurgeKernels.cc create mode 100644 zypp/PurgeKernels.h create mode 100644 zypp/Range.cc create mode 100644 zypp/Range.h create mode 100644 zypp/Rel.cc create mode 100644 zypp/Rel.h create mode 100644 zypp/RelCompare.h create mode 100644 zypp/RepoInfo.cc create mode 100644 zypp/RepoInfo.h create mode 100644 zypp/RepoManager.cc create mode 100644 zypp/RepoManager.h create mode 100644 zypp/RepoManagerFlags.h create mode 100644 zypp/RepoManagerOptions.cc create mode 100644 zypp/RepoManagerOptions.h create mode 100644 zypp/RepoStatus.cc create mode 100644 zypp/RepoStatus.h create mode 100644 zypp/Repository.cc create mode 100644 zypp/Repository.h create mode 100644 zypp/ResFilters.h create mode 100644 zypp/ResKind.cc create mode 100644 zypp/ResKind.h create mode 100644 zypp/ResObject.cc create mode 100644 zypp/ResObject.h create mode 100644 zypp/ResObjects.h create mode 100644 zypp/ResPool.cc create mode 100644 zypp/ResPool.h create mode 100644 zypp/ResPoolProxy.cc create mode 100644 zypp/ResPoolProxy.h create mode 100644 zypp/ResStatus.cc create mode 100644 zypp/ResStatus.h create mode 100644 zypp/ResTraits.h create mode 100644 zypp/Resolvable.cc create mode 100644 zypp/Resolvable.h create mode 100644 zypp/Resolver.cc create mode 100644 zypp/Resolver.h create mode 100644 zypp/ResolverFocus.cc create mode 100644 zypp/ResolverFocus.h create mode 100644 zypp/ResolverNamespace.h create mode 100644 zypp/ResolverProblem.cc create mode 100644 zypp/ResolverProblem.h create mode 100644 zypp/ServiceInfo.cc create mode 100644 zypp/ServiceInfo.h create mode 100644 zypp/Signature.cc create mode 100644 zypp/Signature.h create mode 100644 zypp/SrcPackage.cc create mode 100644 zypp/SrcPackage.h create mode 100644 zypp/SysContent.cc create mode 100644 zypp/SysContent.h create mode 100644 zypp/Target.cc create mode 100644 zypp/Target.h create mode 100644 zypp/TmpPath.cc create mode 100644 zypp/TmpPath.h create mode 100644 zypp/TriBool.h create mode 100644 zypp/Url.h create mode 100644 zypp/UserData.h create mode 100644 zypp/Vendor.h create mode 100644 zypp/VendorAttr.cc create mode 100644 zypp/VendorAttr.h create mode 100644 zypp/VendorSupportOptions.cc create mode 100644 zypp/VendorSupportOptions.h create mode 100644 zypp/ZConfig.cc create mode 100644 zypp/ZConfig.h create mode 100644 zypp/ZYpp.cc create mode 100644 zypp/ZYpp.h create mode 100644 zypp/ZYppCallbacks.h create mode 100644 zypp/ZYppCommit.h create mode 100644 zypp/ZYppCommitPolicy.cc create mode 100644 zypp/ZYppCommitPolicy.h create mode 100644 zypp/ZYppCommitResult.cc create mode 100644 zypp/ZYppCommitResult.h create mode 100644 zypp/ZYppFactory.cc create mode 100644 zypp/ZYppFactory.h create mode 100644 zypp/base/Algorithm.h create mode 100644 zypp/base/Backtrace.cc create mode 100644 zypp/base/Backtrace.h create mode 100644 zypp/base/Collector.h create mode 100644 zypp/base/Counter.h create mode 100644 zypp/base/Debug.h create mode 100644 zypp/base/DefaultIntegral.h create mode 100644 zypp/base/DrunkenBishop.cc create mode 100644 zypp/base/DrunkenBishop.h create mode 100644 zypp/base/DtorReset.h create mode 100644 zypp/base/Easy.h create mode 100644 zypp/base/EnumClass.h create mode 100644 zypp/base/Env.h create mode 100644 zypp/base/Errno.h create mode 100644 zypp/base/Exception.h create mode 100644 zypp/base/ExternalDataSource.h create mode 100644 zypp/base/Flags.h create mode 100644 zypp/base/Function.h create mode 100644 zypp/base/Functional.h create mode 100644 zypp/base/Gettext.h create mode 100644 zypp/base/GzStream.h create mode 100644 zypp/base/Hash.h create mode 100644 zypp/base/IOStream.h create mode 100644 zypp/base/IOTools.h create mode 100644 zypp/base/InputStream.h create mode 100644 zypp/base/Iterable.h create mode 100644 zypp/base/Iterator.h create mode 100644 zypp/base/Json.h create mode 100644 zypp/base/LocaleGuard.h create mode 100644 zypp/base/LogControl.h create mode 100644 zypp/base/LogTools.h create mode 100644 zypp/base/Logger.h create mode 100644 zypp/base/Measure.cc create mode 100644 zypp/base/Measure.h create mode 100644 zypp/base/NamedValue.h create mode 100644 zypp/base/NonCopyable.h create mode 100644 zypp/base/ProfilingFormater.h create mode 100644 zypp/base/ProvideNumericId.h create mode 100644 zypp/base/PtrTypes.h create mode 100644 zypp/base/Random.cc create mode 100644 zypp/base/Random.h create mode 100644 zypp/base/ReferenceCounted.h create mode 100644 zypp/base/Regex.h create mode 100644 zypp/base/SerialNumber.cc create mode 100644 zypp/base/SerialNumber.h create mode 100644 zypp/base/SetRelationMixin.cc create mode 100644 zypp/base/SetRelationMixin.h create mode 100644 zypp/base/SetTracker.h create mode 100644 zypp/base/Signal.h create mode 100644 zypp/base/SimpleStreambuf.h create mode 100644 zypp/base/StrMatcher.cc create mode 100644 zypp/base/StrMatcher.h create mode 100644 zypp/base/String.h create mode 100644 zypp/base/StringV.h create mode 100644 zypp/base/Sysconfig.h create mode 100644 zypp/base/TypeTraits.h create mode 100644 zypp/base/Unit.h create mode 100644 zypp/base/UserRequestException.h create mode 100644 zypp/base/ValueTransform.h create mode 100644 zypp/base/WatchFile.h create mode 100644 zypp/base/Xml.h create mode 100644 zypp/base/ZckStream.h create mode 100644 zypp/base/fXstream.h create mode 100644 zypp/libzypp.map create mode 100644 zypp/media/CredentialFileReader.h create mode 100644 zypp/media/CredentialManager.h create mode 100644 zypp/media/CurlConfig.h create mode 100644 zypp/media/MediaBlockList.h create mode 100644 zypp/media/MediaCD.cc create mode 100644 zypp/media/MediaCD.h create mode 100644 zypp/media/MediaCIFS.cc create mode 100644 zypp/media/MediaCIFS.h create mode 100644 zypp/media/MediaCurl.cc create mode 100644 zypp/media/MediaCurl.h create mode 100644 zypp/media/MediaDIR.cc create mode 100644 zypp/media/MediaDIR.h create mode 100644 zypp/media/MediaDISK.cc create mode 100644 zypp/media/MediaDISK.h create mode 100644 zypp/media/MediaException.h create mode 100644 zypp/media/MediaHandler.cc create mode 100644 zypp/media/MediaHandler.h create mode 100644 zypp/media/MediaHandlerFactory.cc create mode 100644 zypp/media/MediaHandlerFactory.h create mode 100644 zypp/media/MediaISO.cc create mode 100644 zypp/media/MediaISO.h create mode 100644 zypp/media/MediaManager.cc create mode 100644 zypp/media/MediaManager.h create mode 100644 zypp/media/MediaMultiCurl.cc create mode 100644 zypp/media/MediaMultiCurl.h create mode 100644 zypp/media/MediaNFS.cc create mode 100644 zypp/media/MediaNFS.h create mode 100644 zypp/media/MediaNetwork.cc create mode 100644 zypp/media/MediaNetwork.h create mode 100644 zypp/media/MediaNetworkCommonHandler.cc create mode 100644 zypp/media/MediaNetworkCommonHandler.h create mode 100644 zypp/media/MediaPlugin.cc create mode 100644 zypp/media/MediaPlugin.h create mode 100644 zypp/media/MediaPriority.cc create mode 100644 zypp/media/MediaPriority.h create mode 100644 zypp/media/MediaSource.cc create mode 100644 zypp/media/MediaSource.h create mode 100644 zypp/media/MediaUserAuth.h create mode 100644 zypp/media/MetaLinkParser.h create mode 100644 zypp/media/Mount.h create mode 100644 zypp/media/ProxyInfo.h create mode 100644 zypp/media/TransferSettings.h create mode 100644 zypp/media/UrlResolverPlugin.cc create mode 100644 zypp/media/UrlResolverPlugin.h create mode 100644 zypp/media/proxyinfo/ProxyInfoImpl.h create mode 100644 zypp/media/proxyinfo/ProxyInfoLibproxy.h create mode 100644 zypp/media/proxyinfo/ProxyInfoSysconfig.h create mode 100644 zypp/media/proxyinfo/ProxyInfos.h create mode 100644 zypp/misc/CheckAccessDeleted.cc create mode 100644 zypp/misc/CheckAccessDeleted.h create mode 100644 zypp/misc/DefaultLoadSystem.cc create mode 100644 zypp/misc/DefaultLoadSystem.h create mode 100644 zypp/misc/HelixHelpers.h create mode 100644 zypp/misc/LoadTestcase.cc create mode 100644 zypp/misc/LoadTestcase.h create mode 100644 zypp/misc/TestcaseSetup.cc create mode 100644 zypp/misc/TestcaseSetup.h create mode 100644 zypp/misc/TestcaseSetupImpl.h create mode 100644 zypp/misc/YamlTestcaseHelpers.h create mode 100644 zypp/ng/Context create mode 100644 zypp/ng/RepoManager create mode 100644 zypp/ng/UserRequest create mode 100644 zypp/ng/context.cc create mode 100644 zypp/ng/context.h create mode 100644 zypp/ng/private/context_p.h create mode 100644 zypp/ng/private/repomanager_p.h create mode 100644 zypp/ng/progressobserveradaptor.cc create mode 100644 zypp/ng/progressobserveradaptor.h create mode 100644 zypp/ng/repo/Downloader create mode 100644 zypp/ng/repo/Refresh create mode 100644 zypp/ng/repo/downloader.cc create mode 100644 zypp/ng/repo/downloader.h create mode 100644 zypp/ng/repo/refresh.cc create mode 100644 zypp/ng/repo/refresh.h create mode 100644 zypp/ng/repo/workflows/plaindir.cc create mode 100644 zypp/ng/repo/workflows/plaindir.h create mode 100644 zypp/ng/repo/workflows/repodownloaderwf.cc create mode 100644 zypp/ng/repo/workflows/repodownloaderwf.h create mode 100644 zypp/ng/repo/workflows/repomanagerwf.cc create mode 100644 zypp/ng/repo/workflows/repomanagerwf.h create mode 100644 zypp/ng/repo/workflows/rpmmd.cc create mode 100644 zypp/ng/repo/workflows/rpmmd.h create mode 100644 zypp/ng/repo/workflows/serviceswf.cc create mode 100644 zypp/ng/repo/workflows/serviceswf.h create mode 100644 zypp/ng/repo/workflows/susetags.cc create mode 100644 zypp/ng/repo/workflows/susetags.h create mode 100644 zypp/ng/repomanager.cc create mode 100644 zypp/ng/repomanager.h create mode 100644 zypp/ng/reporthelper.cc create mode 100644 zypp/ng/reporthelper.h create mode 100644 zypp/ng/userrequest.cc create mode 100644 zypp/ng/userrequest.h create mode 100644 zypp/ng/workflows/checksumwf.cc create mode 100644 zypp/ng/workflows/checksumwf.h create mode 100644 zypp/ng/workflows/contextfacade.cc create mode 100644 zypp/ng/workflows/contextfacade.h create mode 100644 zypp/ng/workflows/downloadwf.cc create mode 100644 zypp/ng/workflows/downloadwf.h create mode 100644 zypp/ng/workflows/keyringwf.cc create mode 100644 zypp/ng/workflows/keyringwf.h create mode 100644 zypp/ng/workflows/logichelpers.h create mode 100644 zypp/ng/workflows/mediafacade.cc create mode 100644 zypp/ng/workflows/mediafacade.h create mode 100644 zypp/ng/workflows/repoinfowf.cc create mode 100644 zypp/ng/workflows/repoinfowf.h create mode 100644 zypp/ng/workflows/signaturecheckwf.cc create mode 100644 zypp/ng/workflows/signaturecheckwf.h create mode 100644 zypp/parser/HistoryLogReader.cc create mode 100644 zypp/parser/HistoryLogReader.h create mode 100644 zypp/parser/IniDict.h create mode 100644 zypp/parser/IniParser.h create mode 100644 zypp/parser/ParseException.h create mode 100644 zypp/parser/ParserProgress.h create mode 100644 zypp/parser/ProductFileReader.cc create mode 100644 zypp/parser/ProductFileReader.h create mode 100644 zypp/parser/RepoFileReader.cc create mode 100644 zypp/parser/RepoFileReader.h create mode 100644 zypp/parser/RepoindexFileReader.cc create mode 100644 zypp/parser/RepoindexFileReader.h create mode 100644 zypp/parser/ServiceFileReader.cc create mode 100644 zypp/parser/ServiceFileReader.h create mode 100644 zypp/parser/schema/repoindex.rnc create mode 100644 zypp/parser/susetags/ContentFileReader.cc create mode 100644 zypp/parser/susetags/ContentFileReader.h create mode 100644 zypp/parser/susetags/RepoIndex.cc create mode 100644 zypp/parser/susetags/RepoIndex.h create mode 100644 zypp/parser/xml/Node.cc create mode 100644 zypp/parser/xml/Node.h create mode 100644 zypp/parser/xml/Parse.h create mode 100644 zypp/parser/xml/ParseDef.cc create mode 100644 zypp/parser/xml/ParseDef.h create mode 100644 zypp/parser/xml/ParseDefConsume.cc create mode 100644 zypp/parser/xml/ParseDefConsume.h create mode 100644 zypp/parser/xml/ParseDefException.cc create mode 100644 zypp/parser/xml/ParseDefException.h create mode 100644 zypp/parser/xml/ParseDefTraits.h create mode 100644 zypp/parser/xml/Reader.cc create mode 100644 zypp/parser/xml/Reader.h create mode 100644 zypp/parser/xml/XmlEscape.h create mode 100644 zypp/parser/xml/XmlString.cc create mode 100644 zypp/parser/xml/XmlString.h create mode 100644 zypp/parser/xml/libxmlfwd.cc create mode 100644 zypp/parser/xml/libxmlfwd.h create mode 100644 zypp/parser/yum/RepomdFileReader.cc create mode 100644 zypp/parser/yum/RepomdFileReader.h create mode 100644 zypp/parser/yum/schema/common-inc.rnc create mode 100644 zypp/parser/yum/schema/common-inc.rng create mode 100644 zypp/parser/yum/schema/deltainfo.rnc create mode 100644 zypp/parser/yum/schema/deltainfo.rng create mode 100644 zypp/parser/yum/schema/filelists.rnc create mode 100644 zypp/parser/yum/schema/filelists.rng create mode 100644 zypp/parser/yum/schema/other.rnc create mode 100644 zypp/parser/yum/schema/other.rng create mode 100644 zypp/parser/yum/schema/patch.rnc create mode 100644 zypp/parser/yum/schema/patch.rng create mode 100644 zypp/parser/yum/schema/patches.rnc create mode 100644 zypp/parser/yum/schema/patches.rng create mode 100644 zypp/parser/yum/schema/patterns.rnc create mode 100644 zypp/parser/yum/schema/patterns.rng create mode 100644 zypp/parser/yum/schema/primary.rnc create mode 100644 zypp/parser/yum/schema/primary.rng create mode 100644 zypp/parser/yum/schema/product.rnc create mode 100644 zypp/parser/yum/schema/product.rng create mode 100644 zypp/parser/yum/schema/products.rnc create mode 100644 zypp/parser/yum/schema/products.rng create mode 100644 zypp/parser/yum/schema/repomd.rnc create mode 100644 zypp/parser/yum/schema/repomd.rng create mode 100755 zypp/parser/yum/schema/rnc2rng create mode 100644 zypp/parser/yum/schema/rpm-inc.rnc create mode 100644 zypp/parser/yum/schema/rpm-inc.rng create mode 100644 zypp/parser/yum/schema/susedata.rnc create mode 100644 zypp/parser/yum/schema/susedata.rng create mode 100644 zypp/parser/yum/schema/suseinfo.rnc create mode 100644 zypp/parser/yum/schema/suseinfo.rng create mode 100644 zypp/parser/yum/schema/updateinfo.rnc create mode 100644 zypp/parser/yum/schema/updateinfo.rng create mode 100755 zypp/parser/yum/schema/validate-all create mode 100644 zypp/pool/ByIdent.h create mode 100644 zypp/pool/PoolImpl.cc create mode 100644 zypp/pool/PoolImpl.h create mode 100644 zypp/pool/PoolStats.cc create mode 100644 zypp/pool/PoolStats.h create mode 100644 zypp/pool/PoolTraits.h create mode 100644 zypp/repo/Applydeltarpm.cc create mode 100644 zypp/repo/Applydeltarpm.h create mode 100644 zypp/repo/DeltaCandidates.cc create mode 100644 zypp/repo/DeltaCandidates.h create mode 100644 zypp/repo/MediaInfoDownloader.cc create mode 100644 zypp/repo/MediaInfoDownloader.h create mode 100644 zypp/repo/PackageDelta.cc create mode 100644 zypp/repo/PackageDelta.h create mode 100644 zypp/repo/PackageProvider.cc create mode 100644 zypp/repo/PackageProvider.h create mode 100644 zypp/repo/PluginRepoverification.cc create mode 100644 zypp/repo/PluginRepoverification.h create mode 100644 zypp/repo/PluginServices.cc create mode 100644 zypp/repo/PluginServices.h create mode 100644 zypp/repo/RepoException.cc create mode 100644 zypp/repo/RepoException.h create mode 100644 zypp/repo/RepoInfoBase.cc create mode 100644 zypp/repo/RepoInfoBase.h create mode 100644 zypp/repo/RepoMirrorList.cc create mode 100644 zypp/repo/RepoMirrorList.h create mode 100644 zypp/repo/RepoProvideFile.cc create mode 100644 zypp/repo/RepoProvideFile.h create mode 100644 zypp/repo/RepoType.cc create mode 100644 zypp/repo/RepoType.h create mode 100644 zypp/repo/RepoVariables.cc create mode 100644 zypp/repo/RepoVariables.h create mode 100644 zypp/repo/SUSEMediaVerifier.cc create mode 100644 zypp/repo/SUSEMediaVerifier.h create mode 100644 zypp/repo/ServiceType.cc create mode 100644 zypp/repo/ServiceType.h create mode 100644 zypp/repo/SrcPackageProvider.cc create mode 100644 zypp/repo/SrcPackageProvider.h create mode 100644 zypp/repo/yum/RepomdFileCollector.cc create mode 100644 zypp/repo/yum/RepomdFileCollector.h create mode 100644 zypp/sat/FileConflicts.cc create mode 100644 zypp/sat/FileConflicts.h create mode 100644 zypp/sat/LocaleSupport.cc create mode 100644 zypp/sat/LocaleSupport.h create mode 100644 zypp/sat/LookupAttr.cc create mode 100644 zypp/sat/LookupAttr.h create mode 100644 zypp/sat/LookupAttrTools.h create mode 100644 zypp/sat/Map.cc create mode 100644 zypp/sat/Map.h create mode 100644 zypp/sat/Pool.cc create mode 100644 zypp/sat/Pool.h create mode 100644 zypp/sat/Queue.cc create mode 100644 zypp/sat/Queue.h create mode 100644 zypp/sat/SolvAttr.cc create mode 100644 zypp/sat/SolvAttr.h create mode 100644 zypp/sat/SolvIterMixin.cc create mode 100644 zypp/sat/SolvIterMixin.h create mode 100644 zypp/sat/Solvable.cc create mode 100644 zypp/sat/Solvable.h create mode 100644 zypp/sat/SolvableSet.cc create mode 100644 zypp/sat/SolvableSet.h create mode 100644 zypp/sat/SolvableSpec.cc create mode 100644 zypp/sat/SolvableSpec.h create mode 100644 zypp/sat/SolvableType.h create mode 100644 zypp/sat/Transaction.cc create mode 100644 zypp/sat/Transaction.h create mode 100644 zypp/sat/WhatObsoletes.cc create mode 100644 zypp/sat/WhatObsoletes.h create mode 100644 zypp/sat/WhatProvides.cc create mode 100644 zypp/sat/WhatProvides.h create mode 100644 zypp/sat/detail/PoolImpl.cc create mode 100644 zypp/sat/detail/PoolImpl.h create mode 100644 zypp/sat/detail/PoolMember.h create mode 100644 zypp/solver/Types.h create mode 100644 zypp/solver/detail/ItemCapKind.h create mode 100644 zypp/solver/detail/ProblemSolutionCombi.cc create mode 100644 zypp/solver/detail/ProblemSolutionCombi.h create mode 100644 zypp/solver/detail/ProblemSolutionIgnore.cc create mode 100644 zypp/solver/detail/ProblemSolutionIgnore.h create mode 100644 zypp/solver/detail/Resolver.cc create mode 100644 zypp/solver/detail/Resolver.h create mode 100644 zypp/solver/detail/SATResolver.cc create mode 100644 zypp/solver/detail/SATResolver.h create mode 100644 zypp/solver/detail/SolutionAction.cc create mode 100644 zypp/solver/detail/SolutionAction.h create mode 100644 zypp/solver/detail/SolverQueueItem.cc create mode 100644 zypp/solver/detail/SolverQueueItem.h create mode 100644 zypp/solver/detail/SolverQueueItemDelete.cc create mode 100644 zypp/solver/detail/SolverQueueItemDelete.h create mode 100644 zypp/solver/detail/SolverQueueItemInstall.cc create mode 100644 zypp/solver/detail/SolverQueueItemInstall.h create mode 100644 zypp/solver/detail/SolverQueueItemInstallOneOf.cc create mode 100644 zypp/solver/detail/SolverQueueItemInstallOneOf.h create mode 100644 zypp/solver/detail/SolverQueueItemLock.cc create mode 100644 zypp/solver/detail/SolverQueueItemLock.h create mode 100644 zypp/solver/detail/SolverQueueItemUpdate.cc create mode 100644 zypp/solver/detail/SolverQueueItemUpdate.h create mode 100644 zypp/solver/detail/SystemCheck.cc create mode 100644 zypp/solver/detail/SystemCheck.h create mode 100644 zypp/solver/detail/Testcase.cc create mode 100644 zypp/solver/detail/Testcase.h create mode 100644 zypp/solver/detail/Testcase_helix.cc create mode 100644 zypp/solver/detail/Types.h create mode 100644 zypp/target/CommitPackageCache.cc create mode 100644 zypp/target/CommitPackageCache.h create mode 100644 zypp/target/CommitPackageCacheImpl.cc create mode 100644 zypp/target/CommitPackageCacheImpl.h create mode 100644 zypp/target/CommitPackageCacheReadAhead.cc create mode 100644 zypp/target/CommitPackageCacheReadAhead.h create mode 100644 zypp/target/HardLocksFile.cc create mode 100644 zypp/target/HardLocksFile.h create mode 100644 zypp/target/RequestedLocalesFile.cc create mode 100644 zypp/target/RequestedLocalesFile.h create mode 100644 zypp/target/RpmPostTransCollector.cc create mode 100644 zypp/target/RpmPostTransCollector.h create mode 100644 zypp/target/SolvIdentFile.cc create mode 100644 zypp/target/SolvIdentFile.h create mode 100644 zypp/target/TargetCallbackReceiver.cc create mode 100644 zypp/target/TargetCallbackReceiver.h create mode 100644 zypp/target/TargetException.cc create mode 100644 zypp/target/TargetException.h create mode 100644 zypp/target/TargetImpl.cc create mode 100644 zypp/target/TargetImpl.commitFindFileConflicts.cc create mode 100644 zypp/target/TargetImpl.h create mode 100644 zypp/target/modalias/Modalias.cc create mode 100644 zypp/target/modalias/Modalias.h create mode 100644 zypp/target/rpm/BinHeader.cc create mode 100644 zypp/target/rpm/BinHeader.h create mode 100644 zypp/target/rpm/RpmCallbacks.cc create mode 100644 zypp/target/rpm/RpmCallbacks.h create mode 100644 zypp/target/rpm/RpmDb.cc create mode 100644 zypp/target/rpm/RpmDb.h create mode 100644 zypp/target/rpm/RpmException.cc create mode 100644 zypp/target/rpm/RpmException.h create mode 100644 zypp/target/rpm/RpmFlags.h create mode 100644 zypp/target/rpm/RpmHeader.cc create mode 100644 zypp/target/rpm/RpmHeader.h create mode 100644 zypp/target/rpm/librpm.h create mode 100644 zypp/target/rpm/librpmDb.cc create mode 100644 zypp/target/rpm/librpmDb.h create mode 100644 zypp/ui/SelFilters.h create mode 100644 zypp/ui/Selectable.cc create mode 100644 zypp/ui/Selectable.h create mode 100644 zypp/ui/SelectableImpl.cc create mode 100644 zypp/ui/SelectableImpl.h create mode 100644 zypp/ui/SelectableTraits.h create mode 100644 zypp/ui/Status.cc create mode 100644 zypp/ui/Status.h create mode 100644 zypp/ui/UserWantedPackages.cc create mode 100644 zypp/ui/UserWantedPackages.h create mode 100644 zypp/url/UrlBase.h create mode 100644 zypp/url/UrlException.h create mode 100644 zypp/url/UrlUtils.h create mode 100644 zypp/zypp_detail/ZYppImpl.cc create mode 100644 zypp/zypp_detail/ZYppImpl.h create mode 100644 zypp/zypp_detail/ZYppReadOnlyHack.h create mode 100644 zypp/zypp_detail/keyring_p.h create mode 100644 zypp/zypp_detail/urlcredentialextractor_p.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..6e27cb0 --- /dev/null +++ b/.clang-format @@ -0,0 +1,117 @@ +--- +Language: Cpp +AccessModifierOffset: -2 +AlignAfterOpenBracket: DontAlign +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Right +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 80 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 2 +ContinuationIndentWidth: 2 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 2 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepLineBreaksForNonEmptyLines: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: All +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 1000000 +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: true +SpacesInSquareBrackets: true +Standard: Cpp11 +TabWidth: 4 +UseTab: Never +... diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..41e1469 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,18 @@ +Checks: + - bugprone-use-after-move + - bugprone-move-forwarding-reference + - modernize-use-override + - performance-move-const-arg + - cppcoreguidelines-prefer-member-initializer + - cppcoreguidelines-special-member-functions + - performance-inefficient-vector-operation + - performance-for-range-copy + - bugprone-copy-constructor-init + # - bugprone-dangling-handle + - bugprone-dynamic-static-initializers + - bugprone-unsafe-functions + - -clang-diagnostic-unused-command-line-argument + - -clang-diagnostic-ignored-optimization-argument +WarningsAsErrors: 'bugprone-use-after-move' +CheckOptions: + performance-move-const-arg.CheckTriviallyCopyableMove: false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..17787a1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +*.po merge=binary +*.pot merge=binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..10da3ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +build +*.orig +*.rej +*.swp +*.kate-swp +#* +.#* +*# +.*project +.externalToolBuilders +.settings +*flymake.h.gch +CMakeLists.txt.user* +.vscode +.cache diff --git a/.obs/workflows.yml b/.obs/workflows.yml new file mode 100644 index 0000000..deb4c68 --- /dev/null +++ b/.obs/workflows.yml @@ -0,0 +1,20 @@ +ci_workflow: + steps: + - branch_package: + source_project: zypp:ci:libzypp + source_package: libzypp + target_project: home:zypp-team + filters: + event: pull_request + +master_workflow: + steps: + - branch_package: + source_project: zypp:ci:libzypp + source_package: libzypp + target_project: home:zypp-team + filters: + event: push + branches: + only: + - master \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ff38f54 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,30 @@ +sudo: required +dist: trusty +group: stable +language: c++ +os: linux + +services: +- docker + +before_install: +- cat /proc/cpuinfo +- docker pull opensuse:tumbleweed +- docker run -i -d --name test opensuse:tumbleweed bash +- docker exec test zypper ref +- docker exec test zypper in -y --recommends cmake openssl-devel boost-devel dejagnu doxygen gcc-c++ gettext-devel graphviz libxml2-devel libproxy-devel pkg-config libsolv-devel libsolv-tools ruby rpm-devel libcurl-devel libboost_program_options*-devel libboost_test*-devel libudev-devel xorg-x11-fonts-core xorg-x11-fonts texlive-lm-fonts libgpgme-devel gpgme libboost_thread1_* +- docker exec test zypper in -y "rubygem(asciidoctor)" + +script: +- docker cp ../libzypp/ test:/root +- docker exec test mkdir /root/build +- docker exec test bash -c "cd /root/build && cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_SKIP_RPATH=1 ../libzypp" +- docker exec test bash -c "cd /root/build && make -j4 VERBOSE=1" +- docker exec test bash -c "cd /root/build && make -j4 -C doc/autodoc" +- docker exec test bash -c "cd /root/build && make -j4 -C po translations" +- docker exec test bash -c "cd /root/build && make -j4 -C tests" +- docker exec test bash -c "cd /root/build/tests && LD_LIBRARY_PATH=\$PWD/../zypp:\$LD_LIBRARY_PATH ctest -VV ." + +on: + repo: openSUSE/libzypp + tags: true diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..786e1aa --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,438 @@ +cmake_minimum_required(VERSION 3.1) + +PROJECT(LIBZYPP) +SET( PACKAGE "libzypp" ) +# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked +SET( CMAKE_MODULE_PATH + ${LIBZYPP_SOURCE_DIR}/cmake/modules + ${CMAKE_MODULE_PATH} +) +INCLUDE(ZyppCommon) +INCLUDE(CMakePushCheckState) + +# allow name libraries by name mixed with full +# paths +if(COMMAND cmake_policy) + cmake_policy(SET CMP0003 NEW) +endif(COMMAND cmake_policy) + +OPTION (ENABLE_BUILD_DOCS "Build documentation by default?" OFF) +OPTION (ENABLE_BUILD_TRANS "Build translation files by default?" OFF) +OPTION (ENABLE_BUILD_TESTS "Build and run test suite by default?" OFF) +OPTION (ENABLE_ZSTD_COMPRESSION "Build with zstd compression support?" OFF) +OPTION (ENABLE_VISIBILITY_HIDDEN "Build with hidden visibility by default?" OFF) +OPTION (ENABLE_ZCHUNK_COMPRESSION "Build with zchunk compression support?" OFF) +# Helps with bug https://bugzilla.gnome.org/show_bug.cgi?id=784550 , Segfault during signal emission when slots are cleared +OPTION (ENABLE_SIGC_BLOCK_WORKAROUND "Enable a workaround for older sigcpp libraries?" OFF ) +OPTION (DISABLE_MEDIABACKEND_TESTS "Disable Tests depending on Nginx and libfcgi?" OFF) + +OPTION (DISABLE_LIBPROXY "Build without libproxy support even if package is installed?" OFF) +OPTION (DISABLE_AUTODOCS "Do not require doxygen being installed (required to build autodocs)?" OFF) +OPTION (EXPORT_NG_API "Export experimental libzypp API" OFF) +# This option will reroute all tool binaries to the libzypp build dir instead of taking those installed in the default directories. +OPTION (ENABLE_DEVEL_BUILD "Developer build, use zypp tools directly from build dir rather than the default locations" OFF) +OPTION (INSTALL_NG_BINARIES "Installs the NG binaries, disabled for now since we are not actively using them." OFF) +# Distros using just zypper may want to enable this as default earlier +OPTION (ENABLE_PREVIEW_SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER "[preview] Force zypper into using a single rpm transaction to install" OFF) + +OPTION (ENABLE_CLANG_TIDY "Enables static checks with clang-tidy" OFF) +OPTION (ENABLE_CPPCHECK "Enables static checks with cppcheck" OFF) +OPTION (ENABLE_UBSAN_CHECKS "Enables the undefined behavior sanitizer runtime checks in debug builds." OFF) + +#-------------------------------------------------------------------------------- +SET (have_system x) + +IF (DEBIAN) + MESSAGE (STATUS "Building for Debian") + SET (ENABLE_BUILD_DOCS ON) + SET (ENABLE_BUILD_TRANS ON) + SET (ENABLE_BUILD_TESTS ON) + SET (have_system ${have_system}x) +ENDIF (DEBIAN) + +# general flags used for all targets +add_library( zypp_general_compiler_flags INTERFACE ) + +IF ( ENABLE_DEVEL_BUILD ) + MESSAGE( WARNING "Zypp devel build enabled, do not do this in production" ) + SET( ZYPP_RPM_BINARY "${LIBZYPP_BINARY_DIR}/tools/zypp-rpm/zypp-rpm") + SET( ZYPP_WORKER_PATH "${LIBZYPP_BINARY_DIR}/tools/workers" ) + if ( ZYPP_STACK_BUILD ) + target_compile_definitions( zypp_general_compiler_flags INTERFACE ZYPP_REPO2SOLV_PATH="${zypp-stack_BINARY_DIR}/libsolv/tools/repo2solv" ) + target_compile_definitions( zypp_general_compiler_flags INTERFACE ZYPP_RPMDB2SOLV_PATH="${zypp-stack_BINARY_DIR}/libsolv/tools/rpmdb2solv" ) + endif() +ELSE() + SET( ZYPP_RPM_BINARY "${ZYPP_LIBEXEC_INSTALL_DIR}/zypp-rpm") + SET( ZYPP_WORKER_PATH "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF( ENABLE_DEVEL_BUILD ) + +message ( "Using zypp-rpm from path: ${ZYPP_RPM_BINARY}" ) +target_compile_definitions(zypp_general_compiler_flags INTERFACE ZYPP_RPM_BINARY="${ZYPP_RPM_BINARY}" ) +target_compile_definitions(zypp_general_compiler_flags INTERFACE ZYPP_WORKER_PATH="${ZYPP_WORKER_PATH}") + +IF (${have_system} STREQUAL x) + MESSAGE (STATUS "Building for SUSE") +ENDIF (${have_system} STREQUAL x) + +IF (${have_system} STRGREATER xx) + MESSAGE (FATAL_ERROR "Can only build for one system type.") +ENDIF (${have_system} STRGREATER xx) +#-------------------------------------------------------------------------------- + + +find_package(FindPkgConfig, QUIET) +INCLUDE( ${LIBZYPP_SOURCE_DIR}/VERSION.cmake ) + +MATH( EXPR LIBZYPP_NUMVERSION "${LIBZYPP_MAJOR} * 10000 + ${LIBZYPP_MINOR} * 100 + ${LIBZYPP_PATCH}" ) +MATH( EXPR LIBZYPP_CURRENT "${LIBZYPP_MAJOR} * 100 + ${LIBZYPP_MINOR}" ) +MATH( EXPR LIBZYPP_AGE "${LIBZYPP_MINOR} - ${LIBZYPP_COMPATMINOR}" ) +# Libtool wanted current:patch:age +# But cmake is not libtool, it wants the verbatim suffix to libzypp.so +MATH( EXPR LIBZYPP_SO_FIRST "${LIBZYPP_CURRENT}-${LIBZYPP_AGE}" ) +SET( VERSION "${LIBZYPP_MAJOR}.${LIBZYPP_MINOR}.${LIBZYPP_PATCH}" ) +CONFIGURE_FILE ( zypp-core/APIConfig.h.in zypp-core/APIConfig.h ) + +SET (CMAKE_CXX_STANDARD ${ZYPPCOMMON_CXX_STANDARD}) +SET (CMAKE_CXX_EXTENSIONS OFF) + +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) +CHECK_C_COMPILER_FLAG("-Werror=format-security" CC_FORMAT_SECURITY) +CHECK_CXX_COMPILER_FLAG("-Werror=format-security" CXX_FORMAT_SECURITY) + +SET( CMAKE_THREAD_PREFER_PTHREAD TRUE ) +FIND_PACKAGE( Threads REQUIRED ) +IF ( NOT CMAKE_USE_PTHREADS_INIT ) + MESSAGE( FATAL_ERROR "No pthreads found" ) +ENDIF ( NOT CMAKE_USE_PTHREADS_INIT ) + + +target_compile_options( zypp_general_compiler_flags INTERFACE "-pthread" "-fno-strict-aliasing" "-g" "-Wall" "-Wp,-D_GLIBCXX_ASSERTIONS" ) +target_link_options( zypp_general_compiler_flags INTERFACE "-pthread" "-fno-strict-aliasing" "-g" "-Wall" "-Wp,-D_GLIBCXX_ASSERTIONS" ) +target_compile_options( zypp_general_compiler_flags INTERFACE "-fvisibility-inlines-hidden" "-Woverloaded-virtual" "-Wnon-virtual-dtor" "-ftemplate-backtrace-limit=0" ) +target_link_options( zypp_general_compiler_flags INTERFACE "-fvisibility-inlines-hidden" "-Woverloaded-virtual" "-Wnon-virtual-dtor" "-ftemplate-backtrace-limit=0" ) + +IF ( ENABLE_VISIBILITY_HIDDEN ) + target_compile_options( zypp_general_compiler_flags INTERFACE "-fvisibility=hidden" ) + target_link_options( zypp_general_compiler_flags INTERFACE "-fvisibility=hidden" ) +ENDIF( ENABLE_VISIBILITY_HIDDEN ) + +IF(${CXX_FORMAT_SECURITY}) + target_compile_options( zypp_general_compiler_flags INTERFACE "-Werror=format-security") + target_link_options( zypp_general_compiler_flags INTERFACE "-Werror=format-security") +ENDIF(${CXX_FORMAT_SECURITY}) + + +#cli args ignored by clang, it still prints a noisy warning though +if ( NOT "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + target_compile_options( zypp_general_compiler_flags INTERFACE "-Wl,-as-needed" ) + target_link_options( zypp_general_compiler_flags INTERFACE "-Wl,-as-needed" ) + + if( ENABLE_UBSAN_CHECKS ) + target_compile_options( zypp_general_compiler_flags INTERFACE "$<$:-fsanitize=undefined>" ) + target_link_options( zypp_general_compiler_flags INTERFACE "$<$:-fsanitize=undefined>" ) + endif() +endif() + +INCLUDE(CheckFunctionExists) +CHECK_FUNCTION_EXISTS(pipe2 PIPE2_FOUND) +IF(${PIPE2_FOUND}) + target_compile_definitions( zypp_general_compiler_flags INTERFACE HAVE_PIPE2 ) +ENDIF(${PIPE2_FOUND}) + +target_compile_definitions(zypp_general_compiler_flags INTERFACE _FILE_OFFSET_BITS=64 ) +target_compile_definitions(zypp_general_compiler_flags INTERFACE $<$>:ZYPP_NDEBUG NDEBUG> ) + +target_compile_options( zypp_general_compiler_flags INTERFACE $<$>:-O2>) +target_link_options ( zypp_general_compiler_flags INTERFACE $<$>:-O2>) + +SET( LIBZYPP_VERSION_INFO "${LIBZYPP_SO_FIRST}.${LIBZYPP_AGE}.${LIBZYPP_PATCH}" ) +SET( LIBZYPP_SOVERSION_INFO "${LIBZYPP_SO_FIRST}" ) + +GENERATE_PACKAGING(${PACKAGE} ${VERSION}) + +INCLUDE(CPack) +#################################################################### +FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options unit_test_framework thread) +IF (Boost_FOUND) + MESSAGE( STATUS "boost found: includes in ${Boost_INCLUDE_DIRS}, library in ${Boost_LIBRARY_DIRS}") + target_include_directories( zypp_general_compiler_flags INTERFACE ${Boost_INCLUDE_DIRS}) + target_link_directories( zypp_general_compiler_flags INTERFACE ${Boost_LIBRARY_DIRS}) +ENDIF(Boost_FOUND) + +FIND_PACKAGE(Gettext REQUIRED) +IF (GETTEXT_FOUND) + MESSAGE(STATUS "Found Gettext: ${GETTEXT_SOURCE}") + target_include_directories( zypp_general_compiler_flags INTERFACE ${GETTEXT_INCLUDE_DIR}) +ELSE (GETTEXT_FOUND) + MESSAGE( FATAL_ERROR "Gettext not found" ) +ENDIF (GETTEXT_FOUND) + +FIND_PACKAGE(CURL REQUIRED) +IF ( NOT CURL_FOUND) + MESSAGE( FATAL_ERROR " curl not found" ) +ELSE ( NOT CURL_FOUND) + target_include_directories( zypp_general_compiler_flags INTERFACE ${CURL_INCLUDE_DIRS}) +ENDIF( NOT CURL_FOUND) + +FIND_PACKAGE(LibXml2 REQUIRED) +IF ( NOT LIBXML2_FOUND) + MESSAGE( FATAL_ERROR " libxml not found" ) +ELSE ( NOT LIBXML2_FOUND) + target_include_directories( zypp_general_compiler_flags INTERFACE ${LIBXML2_INCLUDE_DIR}) +ENDIF( NOT LIBXML2_FOUND) + +FIND_PACKAGE(ZLIB REQUIRED) +IF ( NOT ZLIB_FOUND) + MESSAGE( FATAL_ERROR " zlib not found" ) +ELSE ( NOT ZLIB_FOUND) + target_include_directories( zypp_general_compiler_flags INTERFACE ${ZLIB_INCLUDE_DIR}) +ENDIF( NOT ZLIB_FOUND) + +FIND_PACKAGE(YAML-CPP REQUIRED) +IF ( NOT YAML-CPP_FOUND) + MESSAGE( FATAL_ERROR " yaml-cpp not found" ) +ELSE ( NOT YAML-CPP_FOUND) + target_include_directories( zypp_general_compiler_flags INTERFACE ${YAML_CPP_INCLUDE_DIR}) + IF ( NOT YAML_CPP_LIBRARIES ) + # Must have been found by config insted of module, use target instead. + SET( YAML_CPP_LIBRARIES "yaml-cpp" ) + ENDIF ( NOT YAML_CPP_LIBRARIES ) +ENDIF( NOT YAML-CPP_FOUND) + +#Allow to override the libsolv install location +if( ZYPP_STACK_BUILD ) + set ( LibSolv_FOUND TRUE ) + SET ( LibSolv_INCLUDE_DIRS ${ZYPP_STACK_INCLUDE_DIRS} ) + SET ( LibSolv_LIBRARIES libsolvext libsolv ) +else() + FIND_PACKAGE(LibSolv REQUIRED ext) + #SET(LibSolv_USE_STATIC_LIBS ON) + IF ( NOT LibSolv_FOUND ) + MESSAGE( FATAL_ERROR " libsolv not found" ) + ELSE() + # static case: Assert libsolv.a ist the last one linked + SET(LibSolv_LIBRARIES ${LibSolv_LIBRARIES} ${LIBSOLV_LIBRARY}) + ENDIF() + + # detecting libsolv features, so we know which libraries to link this is still required even if we were asked to build + # without zstd support + include(CheckSymbolExists) + cmake_push_check_state(RESET) + set(CMAKE_REQUIRED_INCLUDES ${LibSolv_INCLUDE_DIRS} ${CMAKE_REQUIRED_INCLUDES}) + CHECK_SYMBOL_EXISTS( LIBSOLVEXT_FEATURE_ZLIB_COMPRESSION "solv/solvversion.h" SOLV_NEED_ZLIB ) + CHECK_SYMBOL_EXISTS( LIBSOLVEXT_FEATURE_LZMA_COMPRESSION "solv/solvversion.h" SOLV_NEED_LZMA ) + CHECK_SYMBOL_EXISTS( LIBSOLVEXT_FEATURE_BZIP2_COMPRESSION "solv/solvversion.h" SOLV_NEED_BZIP2 ) + CHECK_SYMBOL_EXISTS( LIBSOLVEXT_FEATURE_ZSTD_COMPRESSION "solv/solvversion.h" SOLV_NEED_ZSTD ) + cmake_pop_check_state() + + # no check for system zchunk, default is usually to use the libsolv internal libs + #CHECK_SYMBOL_EXISTS( LIBSOLVEXT_FEATURE_ZCHUNK_COMPRESSION "solv/solvversion.h" SOLV_NEED_ZCHUNK ) + #if ( SOLV_NEED_ZCHUNK ) + # FIND_PACKAGE(PkgConfig REQUIRED) + # PKG_CHECK_MODULES(ZCHUNK zck REQUIRED) + # set(LibSolv_LIBRARIES ${LibSolv_LIBRARIES} ${ZCHUNK_LIBRARIES}) + #endif () + + if ( SOLV_NEED_ZLIB ) + FIND_PACKAGE (ZLIB REQUIRED) + SET(LibSolv_LIBRARIES ${LibSolv_LIBRARIES} ${ZLIB_LIBRARY}) + endif () + if ( SOLV_NEED_LZMA ) + FIND_LIBRARY(LZMA_LIBRARY NAMES lzma liblzma REQUIRED) + SET(LibSolv_LIBRARIES ${LibSolv_LIBRARIES} ${LZMA_LIBRARY}) + endif () + if ( SOLV_NEED_BZIP2 ) + FIND_PACKAGE (BZip2 REQUIRED) + SET(LibSolv_LIBRARIES ${LibSolv_LIBRARIES} ${BZIP2_LIBRARIES}) + endif () + if ( SOLV_NEED_ZSTD ) + FIND_LIBRARY (ZSTD_LIBRARY NAMES zstd REQUIRED) + SET(LibSolv_LIBRARIES ${LibSolv_LIBRARIES} ${ZSTD_LIBRARY}) + endif () +endif( ZYPP_STACK_BUILD ) + +target_include_directories( zypp_general_compiler_flags INTERFACE ${LibSolv_INCLUDE_DIRS} ) + +pkg_search_module(GPGME gpgme>=1.8.0) +IF ( GPGME_FOUND ) + MESSAGE(STATUS "Found gpgme ${GPGME_VERSION}" ) + target_include_directories( zypp_general_compiler_flags INTERFACE ${GPGME_INCLUDE_DIRS} ) + target_link_directories( zypp_general_compiler_flags INTERFACE ${GPGME_LIBRARY_DIRS} ) +ELSE() + FIND_PACKAGE(Gpgme REQUIRED) + IF ( NOT GPGME_PTHREAD_FOUND ) + MESSAGE( FATAL_ERROR " gpgme not found" ) + ELSE() + target_include_directories( zypp_general_compiler_flags INTERFACE ${GPGME_INCLUDES} ) + target_link_directories( zypp_general_compiler_flags INTERFACE ${GPGME_LIBRARY_DIR} ) + SET(GPGME_LIBRARIES ${GPGME_PTHREAD_LIBRARIES}) + ENDIF() +ENDIF() + +FIND_PACKAGE(OpenSSL REQUIRED) + +FIND_PACKAGE(Udev) +IF ( NOT UDEV_FOUND ) + MESSAGE(WARNING "No udev found. CD device detection will be poor") +ELSE ( NOT UDEV_FOUND ) + target_compile_definitions( zypp_general_compiler_flags INTERFACE HAVE_UDEV) +ENDIF ( NOT UDEV_FOUND ) + +IF( DISABLE_LIBPROXY ) + MESSAGE( STATUS "libproxy support disabled" ) +ELSE( DISABLE_LIBPROXY ) + target_compile_definitions( zypp_general_compiler_flags INTERFACE WITH_LIBPROXY_SUPPORT) +ENDIF( DISABLE_LIBPROXY ) + +FIND_PROGRAM( DOXYGEN doxygen ) +IF ( NOT DOXYGEN ) + IF ( DISABLE_AUTODOCS ) + MESSAGE( STATUS "doxygen is not available. Can't build the documentation." ) + ELSE ( DISABLE_AUTODOCS ) + MESSAGE( FATAL_ERROR "doxygen not found: install doxygen to build the documentation!" ) + ENDIF ( DISABLE_AUTODOCS ) +ELSE ( NOT DOXYGEN ) + MESSAGE( STATUS "doxygen found: ${DOXYGEN}" ) +ENDIF ( NOT DOXYGEN ) + +if (ENABLE_CLANG_TIDY) + FIND_PROGRAM( CLANG-TIDY clang-tidy ) + if ( CLANG-TIDY ) + message( "Enabling clang-tidy checks") + set( ZYPP_CXX_CLANG_TIDY ${CLANG-TIDY} ) + else ( CLANG-TIDY ) + message(WARNING "clang-tidy not found.") + endif( CLANG-TIDY ) +endif(ENABLE_CLANG_TIDY) + +if ( ENABLE_CPPCHECK ) + FIND_PROGRAM( CPPCHECK cppcheck ) + if ( CPPCHECK ) + message( "Enabling cppcheck") + set(ZYPP_CXX_CPPCHECK ${CPPCHECK};–std=c++17;--suppress=rethrowNoCurrentException) + else ( CPPCHECK ) + message(WARNING "cppcheck not found.") + endif( CPPCHECK ) +endif(ENABLE_CPPCHECK) + +# https://bugzilla.gnome.org/show_bug.cgi?id=784550 +IF (ENABLE_ZCHUNK_COMPRESSION) + MESSAGE("Building with zchunk support enabled.") + PKG_CHECK_MODULES (ZCHUNK zck REQUIRED) + message("ZCHUNK FLAGS ${ZCHUNK_CFLAGS} ") + target_compile_options( zypp_general_compiler_flags INTERFACE ${ZCHUNK_CFLAGS} ) + target_link_options( zypp_general_compiler_flags INTERFACE ${ZCHUNK_CFLAGS} ) + target_compile_definitions( zypp_general_compiler_flags INTERFACE ENABLE_ZCHUNK_COMPRESSION=1 ) +ENDIF(ENABLE_ZCHUNK_COMPRESSION) + +IF(ENABLE_SIGC_BLOCK_WORKAROUND) + message("Building with sigcpp block workaround") + target_compile_definitions( zypp_general_compiler_flags INTERFACE LIBZYPP_USE_SIGC_BLOCK_WORKAROUND=1) +ENDIF(ENABLE_SIGC_BLOCK_WORKAROUND) + +pkg_check_modules ( SIGCPP REQUIRED sigc++-2.0 ) +target_include_directories( zypp_general_compiler_flags INTERFACE ${SIGCPP_INCLUDE_DIRS} ) + +pkg_check_modules ( LIBGLIB REQUIRED glib-2.0 ) +target_include_directories( zypp_general_compiler_flags INTERFACE ${LIBGLIB_INCLUDE_DIRS} ) + +MESSAGE(STATUS "soname: ${LIBZYPP_VERSION_INFO}") +MESSAGE(STATUS "version: ${VERSION}") + +MESSAGE(STATUS "Writing pkg-config file...") +CONFIGURE_FILE(${LIBZYPP_SOURCE_DIR}/libzypp.pc.cmake ${LIBZYPP_BINARY_DIR}/libzypp.pc @ONLY) +INSTALL( FILES ${LIBZYPP_BINARY_DIR}/libzypp.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig ) + +MESSAGE(STATUS "FindZypp.cmake will be installed in ${CMAKE_INSTALL_PREFIX}/share/cmake/Modules") +INSTALL( FILES ${LIBZYPP_SOURCE_DIR}/cmake/modules/FindZypp.cmake DESTINATION ${CMAKE_INSTALL_PREFIX}/share/cmake/Modules ) +INSTALL( FILES ${LIBZYPP_SOURCE_DIR}/cmake/modules/ZyppCommon.cmake DESTINATION ${CMAKE_INSTALL_PREFIX}/share/cmake/Modules ) + +#################################################################### +# config templates +# (don't forget to mention them in the .spec file) +#################################################################### + +MESSAGE(STATUS "zypp.conf will be installed in ${SYSCONFDIR}/zypp") +INSTALL( FILES ${LIBZYPP_SOURCE_DIR}/zypp.conf DESTINATION ${SYSCONFDIR}/zypp ) + +MESSAGE(STATUS "needreboot will be installed in ${SYSCONFDIR}/zypp/") +INSTALL( FILES ${LIBZYPP_SOURCE_DIR}/needreboot DESTINATION ${SYSCONFDIR}/zypp ) + +#install systemCheck +MESSAGE(STATUS "systemCheck will be installed in ${SYSCONFDIR}/zypp") +INSTALL( FILES ${LIBZYPP_SOURCE_DIR}/systemCheck DESTINATION ${SYSCONFDIR}/zypp ) + +# logrotate config file +INSTALL( FILES ${LIBZYPP_SOURCE_DIR}/zypp-history.lr DESTINATION ${SYSCONFDIR}/logrotate.d ) + +IF ( ENABLE_PREVIEW_SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER ) + MESSAGE( STATUS "[preview] Force zypper into using a single rpm transaction to install" ) + target_compile_definitions( zypp_general_compiler_flags INTERFACE SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER ) +ENDIF ( ENABLE_PREVIEW_SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER ) + + +#usage requirements for all libs +add_library( zypp_lib_compiler_flags INTERFACE) +target_compile_options( zypp_lib_compiler_flags INTERFACE "-fPIC" "-rdynamic" "-Wl,--no-allow-shlib-undefined" "-Wl,--no-undefined") +target_link_options ( zypp_lib_compiler_flags INTERFACE "-fPIC" "-rdynamic" "-Wl,--no-allow-shlib-undefined" "-Wl,--no-undefined" ) +target_link_libraries ( zypp_lib_compiler_flags INTERFACE zypp_general_compiler_flags ) + +#usage requirements for all executables +add_library( zypp_exe_compiler_flags INTERFACE) +target_compile_options( zypp_exe_compiler_flags INTERFACE "-fpie" "-pie" "-Wl,--no-undefined" ) +target_link_options ( zypp_exe_compiler_flags INTERFACE "-fpie" "-pie" "-Wl,--no-undefined" ) +target_link_libraries ( zypp_exe_compiler_flags INTERFACE zypp_general_compiler_flags ) + + +MACRO(ADD_TESTS) + FOREACH( loop_var ${ARGV} ) + SET_SOURCE_FILES_PROPERTIES( ${loop_var}_test.cc COMPILE_FLAGS "-DBOOST_TEST_DYN_LINK -DBOOST_TEST_MAIN -DBOOST_AUTO_TEST_MAIN=\"\" " ) + ADD_EXECUTABLE( ${loop_var}_test ${loop_var}_test.cc ) + + SET(TEST_REQ_LIBS ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY} ) + IF(NOT DISABLE_MEDIABACKEND_TESTS) + LIST( APPEND TEST_REQ_LIBS zypp_test_utils ) + ENDIF() + + TARGET_LINK_LIBRARIES( ${loop_var}_test PUBLIC zypp_exe_compiler_flags ) + TARGET_LINK_LIBRARIES( ${loop_var}_test PUBLIC ${TEST_REQ_LIBS} ) + TARGET_LINK_LIBRARIES( ${loop_var}_test PUBLIC zypp-allsym ) + ADD_TEST( ${loop_var}_test ${CMAKE_CURRENT_BINARY_DIR}/${loop_var}_test --catch_system_errors=no) + ENDFOREACH( loop_var ) +ENDMACRO(ADD_TESTS) + +# Macro to set the log group for a list of files +MACRO( SET_LOGGROUP _group _files ) + SET_SOURCE_FILES_PROPERTIES( ${_files} COMPILE_FLAGS -DZYPP_BASE_LOGGER_LOGGROUP=\\"${_group}\\" ) + FOREACH (_currentFile ${ARGN}) +#MESSAGE( STATUS "setting loggroup to \"${_group}\" for ${_currentFile}" ) + SET_SOURCE_FILES_PROPERTIES( ${_currentFile} COMPILE_FLAGS -DZYPP_BASE_LOGGER_LOGGROUP=\\"${_group}\\" ) + ENDFOREACH (_currentFile ${ARGN}) +ENDMACRO( SET_LOGGROUP ) + +#################################################################### +# SUBDIRECTORIES # +#################################################################### +ADD_SUBDIRECTORY( zypp-core ) +ADD_SUBDIRECTORY( zypp-media ) +ADD_SUBDIRECTORY( zypp-curl ) +ADD_SUBDIRECTORY( zypp-tui ) +ADD_SUBDIRECTORY( zypp ) +ADD_SUBDIRECTORY( tools ) +ADD_SUBDIRECTORY( shared ) +ADD_SUBDIRECTORY( doc ) + +IF ( ENABLE_BUILD_TRANS ) + ADD_SUBDIRECTORY( po ) +ELSE ( ENABLE_BUILD_TRANS ) + ADD_SUBDIRECTORY( po EXCLUDE_FROM_ALL ) +ENDIF ( ENABLE_BUILD_TRANS ) + +IF ( ENABLE_BUILD_TESTS ) + ADD_SUBDIRECTORY( tests ) +ELSE ( ENABLE_BUILD_TESTS ) + ADD_SUBDIRECTORY( tests EXCLUDE_FROM_ALL ) +ENDIF ( ENABLE_BUILD_TESTS ) +INCLUDE(CTest) +ENABLE_TESTING() diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..9cb364b --- /dev/null +++ b/COPYING @@ -0,0 +1,21 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +Copyright (C) 2000-2002 Ximian, Inc. +Copyright (C) 2005-2018 SUSE LINUX Products GmbH, Nuernberg, Germany. + +ZYpp is licensed under the GNU General Public License version 2 +or later. The text of the GNU General Public License can be viewed at +http://www.gnu.org/licenses/gpl.html + +As a special exception, you have permission to link this program +with the following libraries and distribute executables, as long as you +follow the requirements of the GNU GPL in regard to all of the +software in the executable aside from the following libraries: +- OpenSSL (http://www.openssl.org) diff --git a/Makefile.cvs b/Makefile.cvs new file mode 100644 index 0000000..3dfffe4 --- /dev/null +++ b/Makefile.cvs @@ -0,0 +1,30 @@ +# Generic Makefile.cvs for CMake-based projects: +# +# Create a subdirecory build/ and call cmake from there with /usr prefix. +# +# Intentionally using /usr rather than the default /usr/local since this is for +# internal use, and we are the distribution makers: /usr/local is off limits +# for us. +# +# Author: Stefan Hundhammer + +BUILD_SUBDIR = build +HERE_FROM_BUILD_SUBDIR = .. +PREFIX = /usr +CMAKE = /usr/bin/cmake + +all: cmake + + +cmake: create-build-subdir create-toplevel-makefile + ( cd $(BUILD_SUBDIR) && $(CMAKE) -DCMAKE_INSTALL_PREFIX=$(PREFIX) $(HERE_FROM_BUILD_SUBDIR) ) + + +create-build-subdir: + test -d $(BUILD_SUBDIR) || mkdir $(BUILD_SUBDIR) + + +create-toplevel-makefile: + echo 'all:' >Makefile + echo -e '\t$$(MAKE) $$(MAKEFLAGS) -C $(BUILD_SUBDIR)' >>Makefile + diff --git a/VERSION.cmake b/VERSION.cmake new file mode 100644 index 0000000..11fabe8 --- /dev/null +++ b/VERSION.cmake @@ -0,0 +1,68 @@ +# ================================================== +# Versioning +# ========== +# +# MAJOR Major number for this branch. +# +# MINOR The most recent interface number this +# library implements. +# +# COMPATMINOR The latest binary compatible minor number +# this library implements. +# +# PATCH The implementation number of the current interface. +# +# +# - The package VERSION will be MAJOR.MINOR.PATCH. +# +# - Libtool's -version-info will be derived from MAJOR, MINOR, PATCH +# and COMPATMINOR (see configure.ac). +# +# - Changing MAJOR always breaks binary compatibility. +# +# - Changing MINOR doesn't break binary compatibility by default. +# Only if COMPATMINOR is changed as well. +# +# +# 1) After branching from TRUNK increment TRUNKs MAJOR and +# start with version `MAJOR.0.0' and also set COMPATMINOR to 0. +# +# 2) Update the version information only immediately before a public release +# of your software. More frequent updates are unnecessary, and only guarantee +# that the current interface number gets larger faster. +# +# 3) If the library source code has changed at all since the last update, +# then increment PATCH. +# +# 4) If any interfaces have been added, removed, or changed since the last +# update, increment MINOR, and set PATCH to 0. +# +# 5) If any interfaces have been added since the last public release, then +# leave COMPATMINOR unchanged. (binary compatible change) +# +# 6) If any interfaces have been removed since the last public release, then +# set COMPATMINOR to MINOR. (binary incompatible change) +# ================================================== + +#======= +# - MOST IMPORTANT: +# - Before you submitt to git: +# - Remember the new version in 'LAST RELEASED:' +# - State the new version in the changes file by adding a line +# "- version MAJOR.MINOR.PATCH (COMPATMINOR)" +# - Commit changes and version files together in a separate +# commit using -m 'changes MAJOR.MINOR.PATCH (COMPATMINOR)' +# - Tag the above commit with 'MAJOR.MINOR.PATCH' using +# -m "tagging MAJOR.MINOR.PATCH". +# +# - Consider calling ./mkChangelog to assist you. +# See './mkChangelog -h' for help. +# +SET(LIBZYPP_MAJOR "17") +SET(LIBZYPP_COMPATMINOR "35") +SET(LIBZYPP_MINOR "35") +SET(LIBZYPP_PATCH "9") +# +# LAST RELEASED: 17.35.9 (35) +# (The number in parenthesis is LIBZYPP_COMPATMINOR) +#======= diff --git a/cmake/modules/FindGpgme.cmake b/cmake/modules/FindGpgme.cmake new file mode 100644 index 0000000..7a014ed --- /dev/null +++ b/cmake/modules/FindGpgme.cmake @@ -0,0 +1,413 @@ +# Taken from gpgmepp project +# +# 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 copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# - Try to find the gpgme library +# +# Algorithm: +# - Windows: +# On Windows, there's three gpgme variants: gpgme{,-glib,-qt}. +# - The variant used determines the event loop integration possible: +# - gpgme: no event loop integration possible, only synchronous operations supported +# - gpgme-glib: glib event loop integration possible, only asynchronous operations supported +# - gpgme-qt: qt event loop integration possible, only asynchronous operations supported +# - GPGME_{VANILLA,GLIB,QT}_{FOUND,LIBRARIES} will be set for each of the above +# - GPGME_INCLUDES is the same for all of the above +# - GPGME_FOUND is set if any of the above was found +# - *nix: +# There's also three variants: gpgme{,-pthread,-pth}. +# - The variant used determines the multithreaded use possible: +# - gpgme: no multithreading support available +# - gpgme-pthread: multithreading available using POSIX threads +# - gpgme-pth: multithreading available using GNU PTH (cooperative multithreading) +# - GPGME_{VANILLA,PTH,PTHREAD}_{FOUND,LIBRARIES} will be set for each of the above +# - GPGME_INCLUDES is the same for all of the above +# - GPGME_FOUND is set if any of the above was found +# +# GPGME_LIBRARY_DIR - the directory where the libraries are located + +# +# THIS IS ALMOST A 1:1 COPY OF FindAssuan.cmake in kdepim. +# Any changes here likely apply there, too. +# + +include(FeatureSummary) + +# do away with crappy condition repetition on else/endfoo +set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS_gpgme_saved ${CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS} ) +set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true ) + +#if this is built-in, please replace, if it isn't, export into a MacroToBool.cmake of its own +macro( macro_bool_to_bool FOUND_VAR ) + foreach( _current_VAR ${ARGN} ) + if ( ${FOUND_VAR} ) + set( ${_current_VAR} TRUE ) + else() + set( ${_current_VAR} FALSE ) + endif() + endforeach() +endmacro() + +#HACK: local copy... +MACRO(MACRO_BOOL_TO_01 FOUND_VAR ) + FOREACH (_current_VAR ${ARGN}) + IF(${FOUND_VAR}) + SET(${_current_VAR} 1) + ELSE(${FOUND_VAR}) + SET(${_current_VAR} 0) + ENDIF(${FOUND_VAR}) + ENDFOREACH(_current_VAR) +ENDMACRO(MACRO_BOOL_TO_01) + + +if ( WIN32 ) + + # On Windows, we don't have a gpgme-config script, so we need to + # look for the stuff ourselves: + + # in cmake, AND and OR have the same precedence, there's no + # subexpressions, and expressions are evaluated short-circuit'ed + # IOW: CMake if() suxx. + # Starting with CMake 2.6.3 you can group if expressions with (), but we + # don't require 2.6.3 but 2.6.2, we can't use it. Alex + set( _seem_to_have_cached_gpgme false ) + if ( GPGME_INCLUDES ) + if ( GPGME_VANILLA_LIBRARIES OR GPGME_QT_LIBRARIES OR GPGME_GLIB_LIBRARIES ) + set( _seem_to_have_cached_gpgme true ) + endif() + endif() + + if ( _seem_to_have_cached_gpgme ) + + macro_bool_to_bool( GPGME_VANILLA_LIBRARIES GPGME_VANILLA_FOUND ) + macro_bool_to_bool( GPGME_GLIB_LIBRARIES GPGME_GLIB_FOUND ) + macro_bool_to_bool( GPGME_QT_LIBRARIES GPGME_QT_FOUND ) + # this would have been preferred: + #set( GPGME_*_FOUND macro_bool_to_bool(GPGME_*_LIBRARIES) ) + + if ( GPGME_VANILLA_FOUND OR GPGME_GLIB_FOUND OR GPGME_QT_FOUND ) + set( GPGME_FOUND true ) + else() + set( GPGME_FOUND false ) + endif() + + else() + + set( GPGME_FOUND false ) + set( GPGME_VANILLA_FOUND false ) + set( GPGME_GLIB_FOUND false ) + set( GPGME_QT_FOUND false ) + + find_path( GPGME_INCLUDES gpgme.h + ${CMAKE_INCLUDE_PATH} + ${CMAKE_INSTALL_PREFIX}/include + ) + + find_library( _gpgme_vanilla_library NAMES gpgme libgpgme gpgme-11 libgpgme-11 + PATHS + ${CMAKE_LIBRARY_PATH} + ${CMAKE_INSTALL_PREFIX}/lib + ) + + find_library( _gpgme_glib_library NAMES gpgme-glib libgpgme-glib gpgme-glib-11 libgpgme-glib-11 + PATHS + ${CMAKE_LIBRARY_PATH} + ${CMAKE_INSTALL_PREFIX}/lib + ) + + find_library( _gpgme_qt_library NAMES gpgme-qt libgpgme-qt gpgme-qt-11 libgpgme-qt-11 + PATHS + ${CMAKE_LIBRARY_PATH} + ${CMAKE_INSTALL_PREFIX}/lib + ) + + find_library( _gpg_error_library NAMES gpg-error libgpg-error gpg-error-0 libgpg-error-0 + PATHS + ${CMAKE_LIBRARY_PATH} + ${CMAKE_INSTALL_PREFIX}/lib + ) + + set( GPGME_INCLUDES ${GPGME_INCLUDES} ) + + if ( _gpgme_vanilla_library AND _gpg_error_library ) + set( GPGME_VANILLA_LIBRARIES ${_gpgme_vanilla_library} ${_gpg_error_library} ) + set( GPGME_VANILLA_FOUND true ) + set( GPGME_FOUND true ) + endif() + + if ( _gpgme_glib_library AND _gpg_error_library ) + set( GPGME_GLIB_LIBRARIES ${_gpgme_glib_library} ${_gpg_error_library} ) + set( GPGME_GLIB_FOUND true ) + set( GPGME_FOUND true ) + endif() + + if ( _gpgme_qt_library AND _gpg_error_library ) + set( GPGME_QT_LIBRARIES ${_gpgme_qt_library} ${_gpg_error_library} ) + set( GPGME_QT_FOUND true ) + set( GPGME_FOUND true ) + endif() + + endif() + + # these are Unix-only: + set( GPGME_PTHREAD_FOUND false ) + set( GPGME_PTH_FOUND false ) + set( HAVE_GPGME_PTHREAD 0 ) + set( HAVE_GPGME_PTH 0 ) + + macro_bool_to_01( GPGME_FOUND HAVE_GPGME ) + macro_bool_to_01( GPGME_VANILLA_FOUND HAVE_GPGME_VANILLA ) + macro_bool_to_01( GPGME_GLIB_FOUND HAVE_GPGME_GLIB ) + macro_bool_to_01( GPGME_QT_FOUND HAVE_GPGME_QT ) + +else() # not WIN32 + + # On *nix, we have the gpgme-config script which can tell us all we + # need to know: + + # see WIN32 case for an explanation of what this does: + set( _seem_to_have_cached_gpgme false ) + if ( GPGME_INCLUDES ) + if ( GPGME_VANILLA_LIBRARIES OR GPGME_PTHREAD_LIBRARIES OR GPGME_PTH_LIBRARIES ) + set( _seem_to_have_cached_gpgme true ) + endif() + endif() + + if ( _seem_to_have_cached_gpgme ) + + macro_bool_to_bool( GPGME_VANILLA_LIBRARIES GPGME_VANILLA_FOUND ) + macro_bool_to_bool( GPGME_PTHREAD_LIBRARIES GPGME_PTHREAD_FOUND ) + macro_bool_to_bool( GPGME_PTH_LIBRARIES GPGME_PTH_FOUND ) + + if ( GPGME_VANILLA_FOUND OR GPGME_PTHREAD_FOUND OR GPGME_PTH_FOUND ) + set( GPGME_FOUND true ) + else() + set( GPGME_FOUND false ) + endif() + + else() + + set( GPGME_FOUND false ) + set( GPGME_VANILLA_FOUND false ) + set( GPGME_PTHREAD_FOUND false ) + set( GPGME_PTH_FOUND false ) + + find_program( _GPGMECONFIG_EXECUTABLE NAMES gpgme-config ) + + # if gpgme-config has been found + if ( _GPGMECONFIG_EXECUTABLE ) + + message( STATUS "Found gpgme-config at ${_GPGMECONFIG_EXECUTABLE}" ) + + exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --version OUTPUT_VARIABLE GPGME_VERSION ) + + set( _GPGME_MIN_VERSION "1.1.7" ) + + if ( ${GPGME_VERSION} VERSION_LESS ${_GPGME_MIN_VERSION} ) + + message( STATUS "The installed version of gpgme is too old: ${GPGME_VERSION} (required: >= ${_GPGME_MIN_VERSION})" ) + + else() + + message( STATUS "Found gpgme v${GPGME_VERSION}, checking for flavours..." ) + + exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --libs OUTPUT_VARIABLE _gpgme_config_vanilla_libs RETURN_VALUE _ret ) + if ( _ret ) + set( _gpgme_config_vanilla_libs ) + endif() + + exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --thread=pthread --libs OUTPUT_VARIABLE _gpgme_config_pthread_libs RETURN_VALUE _ret ) + if ( _ret ) + set( _gpgme_config_pthread_libs ) + endif() + + exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --thread=pth --libs OUTPUT_VARIABLE _gpgme_config_pth_libs RETURN_VALUE _ret ) + if ( _ret ) + set( _gpgme_config_pth_libs ) + endif() + + # append -lgpg-error to the list of libraries, if necessary + foreach ( _flavour vanilla pthread pth ) + if ( _gpgme_config_${_flavour}_libs AND NOT _gpgme_config_${_flavour}_libs MATCHES "lgpg-error" ) + set( _gpgme_config_${_flavour}_libs "${_gpgme_config_${_flavour}_libs} -lgpg-error" ) + endif() + endforeach() + + if ( _gpgme_config_vanilla_libs OR _gpgme_config_pthread_libs OR _gpgme_config_pth_libs ) + + exec_program( ${_GPGMECONFIG_EXECUTABLE} ARGS --cflags OUTPUT_VARIABLE _GPGME_CFLAGS ) + + if ( _GPGME_CFLAGS ) + string( REGEX REPLACE "(\r?\n)+$" " " _GPGME_CFLAGS "${_GPGME_CFLAGS}" ) + string( REGEX REPLACE " *-I" ";" GPGME_INCLUDES "${_GPGME_CFLAGS}" ) + endif() + + foreach ( _flavour vanilla pthread pth ) + if ( _gpgme_config_${_flavour}_libs ) + + set( _gpgme_library_dirs ) + set( _gpgme_library_names ) + string( TOUPPER "${_flavour}" _FLAVOUR ) + + string( REGEX REPLACE " +" ";" _gpgme_config_${_flavour}_libs "${_gpgme_config_${_flavour}_libs}" ) + + foreach( _flag ${_gpgme_config_${_flavour}_libs} ) + if ( "${_flag}" MATCHES "^-L" ) + string( REGEX REPLACE "^-L" "" _dir "${_flag}" ) + file( TO_CMAKE_PATH "${_dir}" _dir ) + set( _gpgme_library_dirs ${_gpgme_library_dirs} "${_dir}" ) + elseif( "${_flag}" MATCHES "^-l" ) + string( REGEX REPLACE "^-l" "" _name "${_flag}" ) + set( _gpgme_library_names ${_gpgme_library_names} "${_name}" ) + endif() + endforeach() + + set( GPGME_${_FLAVOUR}_FOUND true ) + + foreach( _name ${_gpgme_library_names} ) + set( _gpgme_${_name}_lib ) + + # if -L options were given, look only there + if ( _gpgme_library_dirs ) + find_library( _gpgme_${_name}_lib NAMES ${_name} PATHS ${_gpgme_library_dirs} NO_DEFAULT_PATH ) + endif() + + # if not found there, look in system directories + if ( NOT _gpgme_${_name}_lib ) + find_library( _gpgme_${_name}_lib NAMES ${_name} ) + endif() + + # if still not found, then the whole flavour isn't found + if ( NOT _gpgme_${_name}_lib ) + if ( GPGME_${_FLAVOUR}_FOUND ) + set( GPGME_${_FLAVOUR}_FOUND false ) + set( _not_found_reason "dependant library ${_name} wasn't found" ) + endif() + endif() + + set( GPGME_${_FLAVOUR}_LIBRARIES ${GPGME_${_FLAVOUR}_LIBRARIES} "${_gpgme_${_name}_lib}" ) + endforeach() + + #check_c_library_exists_explicit( gpgme gpgme_check_version "${_GPGME_CFLAGS}" "${GPGME_LIBRARIES}" GPGME_FOUND ) + if ( GPGME_${_FLAVOUR}_FOUND ) + message( STATUS " Found flavour '${_flavour}', checking whether it's usable...yes" ) + else() + message( STATUS " Found flavour '${_flavour}', checking whether it's usable...no" ) + message( STATUS " (${_not_found_reason})" ) + endif() + endif() + + endforeach( _flavour ) + + # ensure that they are cached + # This comment above doesn't make sense, the four following lines seem to do nothing. Alex + set( GPGME_INCLUDES ${GPGME_INCLUDES} ) + set( GPGME_VANILLA_LIBRARIES ${GPGME_VANILLA_LIBRARIES} ) + set( GPGME_PTHREAD_LIBRARIES ${GPGME_PTHREAD_LIBRARIES} ) + set( GPGME_PTH_LIBRARIES ${GPGME_PTH_LIBRARIES} ) + + if ( GPGME_VANILLA_FOUND OR GPGME_PTHREAD_FOUND OR GPGME_PTH_FOUND ) + set( GPGME_FOUND true ) + else() + set( GPGME_FOUND false ) + endif() + + endif() + + endif() + + endif() + + endif() + + # these are Windows-only: + set( GPGME_GLIB_FOUND false ) + set( GPGME_QT_FOUND false ) + set( HAVE_GPGME_GLIB 0 ) + set( HAVE_GPGME_QT 0 ) + + macro_bool_to_01( GPGME_FOUND HAVE_GPGME ) + macro_bool_to_01( GPGME_VANILLA_FOUND HAVE_GPGME_VANILLA ) + macro_bool_to_01( GPGME_PTHREAD_FOUND HAVE_GPGME_PTHREAD ) + macro_bool_to_01( GPGME_PTH_FOUND HAVE_GPGME_PTH ) + +endif() # WIN32 | Unix + + +set( _gpgme_flavours "" ) + +if ( GPGME_VANILLA_FOUND ) + set( _gpgme_flavours "${_gpgme_flavours} vanilla" ) +endif() + +if ( GPGME_GLIB_FOUND ) + set( _gpgme_flavours "${_gpgme_flavours} Glib" ) +endif() + +if ( GPGME_QT_FOUND ) + set( _gpgme_flavours "${_gpgme_flavours} Qt" ) +endif() + +if ( GPGME_PTHREAD_FOUND ) + set( _gpgme_flavours "${_gpgme_flavours} pthread" ) +endif() + +if ( GPGME_PTH_FOUND ) + set( _gpgme_flavours "${_gpgme_flavours} pth" ) +endif() + +# determine the library in one of the found flavours, can be reused e.g. by FindQgpgme.cmake, Alex +foreach(_currentFlavour vanilla glib qt pth pthread) + if(NOT GPGME_LIBRARY_DIR) + get_filename_component(GPGME_LIBRARY_DIR "${_gpgme_${_currentFlavour}_lib}" PATH) + endif() +endforeach() + +if ( NOT Gpgme_FIND_QUIETLY ) + + if ( GPGME_FOUND ) + message( STATUS "Usable gpgme flavours found: ${_gpgme_flavours}" ) + else() + message( STATUS "No usable gpgme flavours found." ) + endif() + +endif() + +if ( Gpgme_FIND_REQUIRED AND NOT GPGME_FOUND ) + message( FATAL_ERROR "Did not find GPGME" ) +endif() + + +if ( WIN32 ) + set( _gpgme_homepage "http://www.gpg4win.org" ) +else() + set( _gpgme_homepage "http://www.gnupg.org/related_software/gpgme" ) +endif() + +set_package_properties(Gpgme PROPERTIES + DESCRIPTION "The GnuPG Made Easy (GPGME) library)" + URL ${_gpgme_homepage}) + +set( CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS_gpgme_saved ) + diff --git a/cmake/modules/FindOpenSSL.cmake b/cmake/modules/FindOpenSSL.cmake new file mode 100644 index 0000000..dd967d1 --- /dev/null +++ b/cmake/modules/FindOpenSSL.cmake @@ -0,0 +1,100 @@ +# - Try to find the OpenSSL encryption library +# Once done this will define +# +# OPENSSL_FOUND - system has the OpenSSL library +# OPENSSL_INCLUDE_DIR - the OpenSSL include directory +# OPENSSL_LIBRARIES - The libraries needed to use OpenSSL + +if (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) + + # in cache already + SET(OPENSSL_FOUND TRUE) + +else (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) + + FIND_PATH(OPENSSL_INCLUDE_DIR openssl/ssl.h + /usr/include/ + /usr/local/include/ + $ENV{ProgramFiles}/OpenSSL/include/ + $ENV{SystemDrive}/OpenSSL/include/ + ) + + if(WIN32 AND MSVC) + # /MD and /MDd are the standard values - if somone wants to use + # others, the libnames have to change here too + # see http://www.openssl.org/support/faq.html#PROG2 for their meaning + + FIND_LIBRARY(SSL_EAY_DEBUG NAMES ssleay32MDd + PATHS + $ENV{ProgramFiles}/OpenSSL/lib/VC/ + $ENV{SystemDrive}/OpenSSL/lib/VC/ + ) + FIND_LIBRARY(SSL_EAY_RELEASE NAMES ssleay32MD + PATHS + $ENV{ProgramFiles}/OpenSSL/lib/VC/ + $ENV{SystemDrive}/OpenSSL/lib/VC/ + ) + FIND_LIBRARY(LIB_EAY_DEBUG NAMES libeay32MDd + PATHS + $ENV{ProgramFiles}/OpenSSL/lib/VC/ + $ENV{SystemDrive}/OpenSSL/lib/VC/ + ) + FIND_LIBRARY(LIB_EAY_RELEASE NAMES libeay32MD + PATHS + $ENV{ProgramFiles}/OpenSSL/lib/VC/ + $ENV{SystemDrive}/OpenSSL/lib/VC/ + ) + + IF(MSVC_IDE) + IF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) + SET(OPENSSL_LIBRARIES optimized ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE} debug ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG}) + ELSE(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) + MESSAGE(FATAL_ERROR "Could not find the debug and release version of openssl") + ENDIF(SSL_EAY_DEBUG AND SSL_EAY_RELEASE) + ELSE(MSVC_IDE) + STRING(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER) + IF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug) + SET(OPENSSL_LIBRARIES ${SSL_EAY_DEBUG} ${LIB_EAY_DEBUG}) + ELSE(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug) + SET(OPENSSL_LIBRARIES ${SSL_EAY_RELEASE} ${LIB_EAY_RELEASE}) + ENDIF(CMAKE_BUILD_TYPE_TOLOWER MATCHES debug) + ENDIF(MSVC_IDE) + MARK_AS_ADVANCED(SSL_EAY_DEBUG SSL_EAY_RELEASE LIB_EAY_DEBUG LIB_EAY_RELEASE) + else(WIN32 AND MSVC) + + FIND_LIBRARY(OPENSSL_LIBRARIES NAMES ssl ssleay32 ssleay32MD libeay32 libeay32MD + PATHS + /usr/lib + /usr/local/lib + ) + FIND_LIBRARY(CRYPTO_LIBRARIES crypto + PATHS + /usr/lib + /usr/local/lib + ) + + endif(WIN32 AND MSVC) + + if (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) + set(OPENSSL_FOUND TRUE) + endif (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) + + if (CRYPTO_LIBRARIES) + set(CRYPTO_FOUND TRUE) + message(STATUS "Found libcrypto: ${CRYPTO_LIBRARIES}") + endif (CRYPTO_LIBRARIES) + + if (OPENSSL_FOUND) + if (NOT OpenSSL_FIND_QUIETLY) + message(STATUS "Found OpenSSL: ${OPENSSL_LIBRARIES}") + endif (NOT OpenSSL_FIND_QUIETLY) + else (OPENSSL_FOUND) + if (OpenSSL_FIND_REQUIRED) + message(FATAL_ERROR "Could NOT find OpenSSL") + endif (OpenSSL_FIND_REQUIRED) + endif (OPENSSL_FOUND) + + MARK_AS_ADVANCED(OPENSSL_INCLUDE_DIR OPENSSL_LIBRARIES) + +endif (OPENSSL_INCLUDE_DIR AND OPENSSL_LIBRARIES) + diff --git a/cmake/modules/FindReadline.cmake b/cmake/modules/FindReadline.cmake new file mode 100644 index 0000000..a5adae9 --- /dev/null +++ b/cmake/modules/FindReadline.cmake @@ -0,0 +1,42 @@ +# - Find readline library +# This module looks for the GNU gettext tools. This module defines the +# following values: +# + +if(READLINE_INCLUDE_DIR AND READLINE_LIBRARY) + # Already in cache, be silent + set(READLINE_FIND_QUIETLY TRUE) +endif(READLINE_INCLUDE_DIR AND READLINE_LIBRARY) + +set(READLINE_LIBRARY) +set(READLINE_INCLUDE_DIR) + +FIND_PATH(READLINE_INCLUDE_DIR readline/readline.h + /usr/include + /usr/include/readline + /usr/local/include + /usr/include/readline +) + +# make find_library look only for shared lib +# otherwise it would find the static libreadline.a +SET(CMAKE_FIND_LIBRARY_SUFFIXES_BACKUP ${CMAKE_FIND_LIBRARY_SUFFIXES}) +SET(CMAKE_FIND_LIBRARY_SUFFIXES ".so") +FIND_LIBRARY(READLINE_LIBRARY readline + PATHS + /usr/lib + /usr/lib64 + /usr/local/lib + /usr/local/lib64 +) +SET(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_BACKUP}) + +if(READLINE_INCLUDE_DIR AND READLINE_LIBRARY) + MESSAGE( STATUS "readline found: includes in ${READLINE_INCLUDE_DIR}, library in ${READLINE_LIBRARY}") + set(READLINE_FOUND TRUE) +else(READLINE_INCLUDE_DIR AND READLINE_LIBRARY) + MESSAGE( STATUS "readline not found") +endif(READLINE_INCLUDE_DIR AND READLINE_LIBRARY) + +MARK_AS_ADVANCED(READLINE_INCLUDE_DIR READLINE_LIBRARY) + diff --git a/cmake/modules/FindRpm.cmake b/cmake/modules/FindRpm.cmake new file mode 100644 index 0000000..32c8329 --- /dev/null +++ b/cmake/modules/FindRpm.cmake @@ -0,0 +1,96 @@ + +cmake_policy(PUSH) +cmake_policy(SET CMP0054 NEW) # if() quoted variables not dereferenced + +if(RPM_INCLUDE_DIR AND RPM_LIBRARY) + # Already in cache, be silent + set(RPM_FIND_QUIETLY TRUE) +endif(RPM_INCLUDE_DIR AND RPM_LIBRARY) + +set(RPM_LIBRARY) +set(RPMIO_LIBRARY) +set(RPM_INCLUDE_DIR) + +FIND_PATH(RPM_INCLUDE_DIR rpm/rpmdb.h + /usr/include + /usr/local/include +) + +set(RPM_SUSPECT_VERSION "RPM_SUSPECT_VERSION-NOTFOUND" ) +if ( RPM_INCLUDE_DIR ) + FIND_PATH(RPM_SUSPECT_VERSION rpm/rpm4compat.h + ${RPM_INCLUDE_DIR} + NO_DEFAULT_PATH + ) + if ( RPM_SUSPECT_VERSION ) + set(RPM_SUSPECT_VERSION "5.x" ) + else ( RPM_SUSPECT_VERSION ) + set(RPM_SUSPECT_VERSION "4.x" ) + endif ( RPM_SUSPECT_VERSION ) +endif ( RPM_INCLUDE_DIR ) + + +FIND_LIBRARY(RPM_LIBRARY NAMES rpm + PATHS + /usr/lib + /usr/local/lib +) + +FIND_LIBRARY(RPMIO_LIBRARY NAMES rpmio + PATHS + /usr/lib + /usr/local/lib +) + + +if(RPM_INCLUDE_DIR AND RPM_LIBRARY AND RPMIO_LIBRARY) + MESSAGE( STATUS "rpm found: includes in ${RPM_INCLUDE_DIR}, library in ${RPM_LIBRARY}, librpmio in ${RPMIO_LIBRARY} (suspect ${RPM_SUSPECT_VERSION})") + + if ( "${RPM_SUSPECT_VERSION}" STREQUAL "4.x" ) + set( ZYPP_RPM_VERSION_INCL "rpm/rpmlib.h" ) + else() + set( ZYPP_RPM_VERSION_INCL "rpm/rpmtag.h" ) + endif() + + configure_file( "${CMAKE_CURRENT_LIST_DIR}/printrpmver.c.in" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/printrpmver.c" @ONLY ) + + try_run( RPM_VER_EXITCODE RPM_VER_COMPRESULT + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp" + "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/printrpmver.c" + LINK_LIBRARIES ${RPM_LIBRARY} + CMAKE_FLAGS -DINCLUDE_DIRECTORIES="${RPM_INCLUDE_DIR}" + COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} + COMPILE_OUTPUT_VARIABLE RPM_PRINTVER_COMPILE_OUTPUT + RUN_OUTPUT_VARIABLE RPM_LIB_VER + ) + + if ( NOT RPM_VER_COMPRESULT OR NOT RPM_VER_EXITCODE EQUAL 0 ) + message( WARNING "Could not determine rpm version" ) + if ( NOT RPM_VER_COMPRESULT ) + message( WARNING "Compilation failed: ") + message( WARNING "${RPM_PRINTVER_COMPILE_OUTPUT}") + endif() + else () + string(REGEX MATCHALL "[^.^-]+" RPM_VER_PARTS "${RPM_LIB_VER}") + list( LENGTH RPM_VER_PARTS RPM_VER_PARTS_CNT ) + + if ( RPM_VER_PARTS_CNT GREATER_EQUAL 3 ) + + list( GET RPM_VER_PARTS 0 RPM_LIB_VER_MAJ ) + list( GET RPM_VER_PARTS 1 RPM_LIB_VER_MIN ) + list( GET RPM_VER_PARTS 2 RPM_LIB_VER_PATCH ) + message ( STATUS "Detected RPM version is: maj:${RPM_LIB_VER_MAJ} min:${RPM_LIB_VER_MIN} patch:${RPM_LIB_VER_PATCH}" ) + set(RPM_FOUND TRUE) + + endif() + endif() + + +else(RPM_INCLUDE_DIR AND RPM_LIBRARY AND RPMIO_LIBRARY) + MESSAGE( STATUS "rpm not found") +endif(RPM_INCLUDE_DIR AND RPM_LIBRARY AND RPMIO_LIBRARY) + +MARK_AS_ADVANCED(RPM_INCLUDE_DIR RPM_LIBRARY) + +cmake_policy(POP) diff --git a/cmake/modules/FindUdev.cmake b/cmake/modules/FindUdev.cmake new file mode 100644 index 0000000..afc2854 --- /dev/null +++ b/cmake/modules/FindUdev.cmake @@ -0,0 +1,23 @@ + +SET( UDEV_LIBRARY ) +SET( UDEV_INCLUDE_DIR ) + +FIND_PATH( UDEV_INCLUDE_DIR libudev.h + /usr/include + /usr/local/include +) + +FIND_LIBRARY( UDEV_LIBRARY NAMES udev + PATHS + /usr/lib + /usr/local/lib +) + +# check if udev is usable for us +INCLUDE (CheckSymbolExists) +SET(CMAKE_REQUIRED_LIBRARIES udev) +CHECK_SYMBOL_EXISTS(udev_enumerate_new libudev.h USABLE_UDEV) +SET(CMAKE_REQUIRED_LIBRARIES "") + +FIND_PACKAGE_HANDLE_STANDARD_ARGS( Udev DEFAULT_MSG UDEV_LIBRARY UDEV_INCLUDE_DIR USABLE_UDEV) +MARK_AS_ADVANCED( UDEV_LIBRARY UDEV_INCLUDE_DIR ) diff --git a/cmake/modules/FindZsync.cmake b/cmake/modules/FindZsync.cmake new file mode 100644 index 0000000..abb3896 --- /dev/null +++ b/cmake/modules/FindZsync.cmake @@ -0,0 +1,34 @@ + +if(ZSYNC_INCLUDE_DIR AND ZSYNC_LIBRARY) + # Already in cache, be silent + set(ZSYNC_FIND_QUIETLY TRUE) +endif(ZSYNC_INCLUDE_DIR AND ZSYNC_LIBRARY) + +set(ZSYNC_LIBRARY) +set(ZSYNC_INCLUDE_DIR) + +FIND_PATH(ZSYNC_INCLUDE_DIR zsync.h + /usr/include + /usr/local/include +) + +FIND_LIBRARY(ZSYNC_LIBRARY NAMES zsync + PATHS + /usr/lib + /usr/local/lib +) + +FIND_LIBRARY(RCKSUM_LIBRARY NAMES rcksum + PATHS + /usr/lib + /usr/local/lib +) + +if(ZSYNC_INCLUDE_DIR AND ZSYNC_LIBRARY AND RCKSUM_LIBRARY) + MESSAGE( STATUS "zsync found: includes in ${ZSYNC_INCLUDE_DIR}, library in ${ZSYNC_LIBRARY}") + set(ZSYNC_FOUND TRUE) +else(ZSYNC_INCLUDE_DIR AND ZSYNC_LIBRARY) + MESSAGE( STATUS "zsync not found") +endif(ZSYNC_INCLUDE_DIR AND ZSYNC_LIBRARY AND RCKSUM_LIBRARY) + +MARK_AS_ADVANCED(ZSYNC_INCLUDE_DIR ZSYNC_LIBRARY RCKSUM_LIBRARY) \ No newline at end of file diff --git a/cmake/modules/FindZypp.cmake b/cmake/modules/FindZypp.cmake new file mode 100644 index 0000000..beca02b --- /dev/null +++ b/cmake/modules/FindZypp.cmake @@ -0,0 +1,66 @@ + +IF (DEFINED ZYPP_PREFIX) + MESSAGE(STATUS "ZYpp library prefix set to ${ZYPP_PREFIX}") +ELSE (DEFINED ZYPP_PREFIX) + MESSAGE(STATUS "ZYpp path not set. Looking for it.") +ENDIF (DEFINED ZYPP_PREFIX) + +if(ZYPP_INCLUDE_DIR AND ZYPP_LIBRARY) + # Already in cache, be silent + SET(ZYPP_FIND_QUIETLY TRUE) +endif(ZYPP_INCLUDE_DIR AND ZYPP_LIBRARY) + +set(ZYPP_LIBRARY) +set(ZYPP_INCLUDE_DIR) + +IF (DEFINED ZYPP_PREFIX) + MESSAGE( STATUS "Looking in ${ZYPP_PREFIX}") + FIND_PATH(ZYPP_INCLUDE_DIR zypp/ZYpp.h + ${ZYPP_PREFIX}/include + NO_DEFAULT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH + ) + FIND_LIBRARY(ZYPP_LIBRARY NAMES zypp + PATHS + ${ZYPP_PREFIX}/lib + ${ZYPP_PREFIX}/lib64 + NO_DEFAULT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH + ) + + FIND_LIBRARY(ZYPP_TUI_LIBRARY NAMES zypp-tui + PATHS + ${ZYPP_PREFIX}/lib + ${ZYPP_PREFIX}/lib64 + NO_DEFAULT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH + ) + +ELSE (DEFINED ZYPP_PREFIX) + FIND_PATH(ZYPP_INCLUDE_DIR zypp/ZYpp.h + /usr/include + /usr/local/include + ) + FIND_LIBRARY(ZYPP_LIBRARY NAMES zypp + PATHS + /usr/lib + /usr/local/lib + ) + FIND_LIBRARY(ZYPP_TUI_LIBRARY NAMES zypp-tui + PATHS + /usr/lib + /usr/local/lib + ) +ENDIF (DEFINED ZYPP_PREFIX) + +if(ZYPP_INCLUDE_DIR AND ZYPP_LIBRARY) + MESSAGE( STATUS "ZYpp found: includes in ${ZYPP_INCLUDE_DIR}, library in ${ZYPP_LIBRARY}, tui library in ${ZYPP_TUI_LIBRARY}") + set(ZYPP_FOUND TRUE) +else(ZYPP_INCLUDE_DIR AND ZYPP_LIBRARY) + MESSAGE( FATAL "ZYpp not found") +endif(ZYPP_INCLUDE_DIR AND ZYPP_LIBRARY) + +MARK_AS_ADVANCED(ZYPP_INCLUDE_DIR ZYPP_LIBRARY) diff --git a/cmake/modules/Findlibproxy.cmake b/cmake/modules/Findlibproxy.cmake new file mode 100644 index 0000000..b6d9454 --- /dev/null +++ b/cmake/modules/Findlibproxy.cmake @@ -0,0 +1,7 @@ +# The "real" libproxy provides its own Findlibproxy.cmake but saner, simpler +# alternatives like the PacRunner replacement which *just* queries PacRunner +# directly will only provide a .pc file. So use pkg-config to find it... + +INCLUDE ( FindPkgConfig ) + +PKG_CHECK_MODULES( LIBPROXY libproxy-1.0 ) diff --git a/cmake/modules/ZyppCommon.cmake b/cmake/modules/ZyppCommon.cmake new file mode 100644 index 0000000..a697107 --- /dev/null +++ b/cmake/modules/ZyppCommon.cmake @@ -0,0 +1,151 @@ +include(GNUInstallDirs) + +# Library +IF ( DEFINED LIB ) + SET ( LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${LIB}" ) +ELSE ( DEFINED LIB ) + SET ( LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" ) +ENDIF ( DEFINED LIB ) +MESSAGE(STATUS "Libraries will be installed in ${LIB_INSTALL_DIR}" ) +# Headers +IF (DEFINED INCLUDE) + SET (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${INCLUDE}") +else (DEFINED INCLUDE) + SET (INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/include") +ENDIF (DEFINED INCLUDE) +MESSAGE (STATUS "Header files will be installed in ${INCLUDE_INSTALL_DIR}") + +# system configuration dir (etc) +IF( NOT DEFINED SYSCONFDIR ) + IF ( ${CMAKE_INSTALL_PREFIX} STREQUAL "/usr" ) + # if installing in usr, set sysconfg to etc + SET( SYSCONFDIR /etc ) + ELSE ( ${CMAKE_INSTALL_PREFIX} STREQUAL "/usr" ) + SET ( SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc" ) + ENDIF ( ${CMAKE_INSTALL_PREFIX} STREQUAL "/usr" ) +ENDIF( NOT DEFINED SYSCONFDIR ) +MESSAGE(STATUS "Config files will be installed in ${SYSCONFDIR}" ) + +# install directory for private executables that are not for the user +SET ( ZYPP_LIBEXEC_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBEXECDIR}/zypp" ) + +# usr INSTALL_PREFIX +IF( DEFINED CMAKE_INSTALL_PREFIX ) + SET( INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} ) +ELSE( DEFINED CMAKE_INSTALL_PREFIX ) + SET( INSTALL_PREFIX /usr ) +ENDIF( DEFINED CMAKE_INSTALL_PREFIX ) + +# system configuration dir (etc) +IF( NOT DEFINED MANDIR ) + SET( MANDIR ${INSTALL_PREFIX}/share/man ) +ENDIF( NOT DEFINED MANDIR ) +MESSAGE( "** Manual files will be installed in ${MANDIR}" ) + +#################################################################### +# CONFIGURATION # +#################################################################### + +IF( NOT DEFINED DOC_INSTALL_DIR ) + SET( DOC_INSTALL_DIR + "${CMAKE_INSTALL_PREFIX}/share/doc/packages/${PACKAGE}" + CACHE PATH "The install dir for documentation (default prefix/share/doc/packages/${PACKAGE})" + FORCE + ) +ENDIF( NOT DEFINED DOC_INSTALL_DIR ) + +#################################################################### +# INCLUDES # +#################################################################### + +SET( ZYPPCOMMON_CXX_STANDARD 17 ) +#SET (CMAKE_INCLUDE_DIRECTORIES_BEFORE ON) +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR} ${PROJECT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} SYSTEM ) + +#################################################################### +# RPM SPEC # +#################################################################### + +MACRO(SPECFILE) + MESSAGE(STATUS "Writing spec file...") + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/${PACKAGE}.spec.cmake ${PROJECT_BINARY_DIR}/package/${PACKAGE}.spec @ONLY) + MESSAGE(STATUS "I hate you rpm-lint...!!!") + IF (EXISTS ${PROJECT_SOURCE_DIR}/package/${PACKAGE}-rpmlint.cmake) + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/package/${PACKAGE}-rpmlint.cmake ${PROJECT_BINARY_DIR}/package/${PACKAGE}-rpmlintrc @ONLY) + ENDIF (EXISTS ${PROJECT_SOURCE_DIR}/package/${PACKAGE}-rpmlint.cmake) +ENDMACRO(SPECFILE) + +MACRO(PKGCONFGFILE) + MESSAGE(STATUS "Writing pkg-config file...") + CONFIGURE_FILE(${PROJECT_SOURCE_DIR}/libzypp.pc.cmake ${PROJECT_BINARY_DIR}/libzypp.pc @ONLY) + INSTALL( FILES ${PROJECT_BINARY_DIR}/libzypp.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig ) +ENDMACRO(PKGCONFGFILE) + +#################################################################### +# INSTALL # +#################################################################### + +MACRO(GENERATE_PACKAGING PACKAGE VERSION) + + # The following components are regex's to match anywhere (unless anchored) + # in absolute path + filename to find files or directories to be excluded + # from source tarball. + SET (CPACK_SOURCE_IGNORE_FILES + # hidden files + "/\\\\..+$" + # temporary files + "\\\\.swp$" + # backup files + "~$" + # others + "\\\\.#" + "/#" + "/build/" + "/_build/" + # used before + "/CVS/" + "\\\\.o$" + "\\\\.lo$" + "\\\\.la$" + "Makefile\\\\.in$" + ) + + #SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Novell's package management core engine.") + SET(CPACK_PACKAGE_VENDOR "Novell Inc.") + #SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/ReadMe.txt") + #SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/Copyright.txt") + #SET(CPACK_PACKAGE_VERSION_MAJOR ${version_major}) + #SET(CPACK_PACKAGE_VERSION_MINOR ${version_minor}) + #SET(CPACK_PACKAGE_VERSION_PATCH ${version_patch}) + SET( CPACK_GENERATOR "TBZ2") + SET( CPACK_SOURCE_GENERATOR "TBZ2") + SET( CPACK_SOURCE_PACKAGE_FILE_NAME "${PACKAGE}-${VERSION}" ) + INCLUDE(CPack) + + SPECFILE() + + if ( ZYPP_STACK_BUILD ) + set( target_prefix "${PROJECT_NAME}_" ) + endif() + + ADD_CUSTOM_TARGET( ${target_prefix}svncheck + COMMAND cd ${PROJECT_SOURCE_DIR} && LC_ALL=C git status | grep -q "nothing to commit .working directory clean." + ) + + SET( AUTOBUILD_COMMAND + COMMAND ${CMAKE_COMMAND} -E remove ${PROJECT_BINARY_DIR}/package/*.tar.bz2 + COMMAND ${CMAKE_MAKE_PROGRAM} package_source + COMMAND ${CMAKE_COMMAND} -E copy ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.bz2 ${PROJECT_BINARY_DIR}/package + COMMAND ${CMAKE_COMMAND} -E remove ${CPACK_SOURCE_PACKAGE_FILE_NAME}.tar.bz2 + COMMAND ${CMAKE_COMMAND} -E copy "${PROJECT_SOURCE_DIR}/package/${PACKAGE}.changes" "${PROJECT_BINARY_DIR}/package/${PACKAGE}.changes" + ) + + ADD_CUSTOM_TARGET( ${target_prefix}srcpackage_local + ${AUTOBUILD_COMMAND} + ) + + ADD_CUSTOM_TARGET( ${target_prefix}srcpackage + COMMAND ${CMAKE_MAKE_PROGRAM} svncheck + ${AUTOBUILD_COMMAND} + ) +ENDMACRO(GENERATE_PACKAGING) diff --git a/cmake/modules/printrpmver.c.in b/cmake/modules/printrpmver.c.in new file mode 100644 index 0000000..6cbd4df --- /dev/null +++ b/cmake/modules/printrpmver.c.in @@ -0,0 +1,8 @@ +#include +#include <@ZYPP_RPM_VERSION_INCL@> + +int main ( int argc , char* argv[] ) +{ + printf("%s\n", rpmEVR); + return 0; +} diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt new file mode 100644 index 0000000..41d2342 --- /dev/null +++ b/doc/CMakeLists.txt @@ -0,0 +1,69 @@ +IF ( ENABLE_BUILD_DOCS ) + ADD_SUBDIRECTORY( autodoc ) +ELSE ( ENABLE_BUILD_DOCS ) + ADD_SUBDIRECTORY( autodoc EXCLUDE_FROM_ALL ) +ENDIF ( ENABLE_BUILD_DOCS ) + +FIND_PROGRAM(A2X a2x) +IF (A2X) +MESSAGE("a2x found: ${A2X}") +SET(ASCDOC_CMD ${A2X} -D ${CMAKE_CURRENT_BINARY_DIR} -f manpage) +ENDIF (A2X) + +FIND_PROGRAM(ASCIIDOC asciidoctor) +IF (ASCIIDOC) +MESSAGE("asciidoctor found: ${ASCIIDOC}") +SET(ASCDOC_CMD ${ASCIIDOC} -D ${CMAKE_CURRENT_BINARY_DIR} -b manpage -d manpage) +ENDIF (ASCIIDOC) + +IF (NOT ASCDOC_CMD) +MESSAGE(FATAL_ERROR "Could not find a2x or asciidoctor, please install either one of them.") +ENDIF() + +function(ADD_A2X_MANPAGES) + set(options) + set(oneValueArgs MAN_INST_PATH) + set(multiValueArgs MAN_PAGES1 MAN_PAGES2 MAN_PAGES3 MAN_PAGES4 MAN_PAGES5 MAN_PAGES6 MAN_PAGES7 MAN_PAGES8) + cmake_parse_arguments(A2X "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN} ) + + set(ALL_MAN_PAGES) + + FOREACH (MAN_IDX RANGE 1 8) + IF (NOT DEFINED A2X_MAN_PAGES${MAN_IDX}) + CONTINUE() + ENDIF() + + FOREACH (curr_PAGE ${A2X_MAN_PAGES${MAN_IDX}}) + ADD_CUSTOM_COMMAND ( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${curr_PAGE} + COMMAND ${ASCDOC_CMD} ${CMAKE_CURRENT_SOURCE_DIR}/${curr_PAGE}.txt + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${curr_PAGE}.txt + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Building manpage ${curr_PAGE}" + ) + + ADD_CUSTOM_TARGET( + ${curr_PAGE}_Target ALL + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${curr_PAGE} + ) + + INSTALL ( + FILES ${CMAKE_CURRENT_BINARY_DIR}/${curr_PAGE} + DESTINATION "${A2X_MAN_INST_PATH}/man${MAN_IDX}" + ) + + ENDFOREACH () + ENDFOREACH() +endfunction(ADD_A2X_MANPAGES) + +SET (libzypp_MAN1 + zypp-CheckAccessDeleted.1 zypp-NameReqPrv.1) + +SET (libzypp_MAN5 + locks.5) + +ADD_A2X_MANPAGES( + MAN_INST_PATH ${MANDIR} + MAN_PAGES1 ${libzypp_MAN1} + MAN_PAGES5 ${libzypp_MAN5} +) diff --git a/doc/autodoc/CMakeLists.txt b/doc/autodoc/CMakeLists.txt new file mode 100644 index 0000000..294c19b --- /dev/null +++ b/doc/autodoc/CMakeLists.txt @@ -0,0 +1,74 @@ +### ################################################## +IF ( DOXYGEN ) +### ################################################## + +FIND_PROGRAM( DOT dot ) +IF ( NOT DOT ) + MESSAGE( "dot not found: you should install graphviz." ) + SET( HAVE_DOT NO ) +ELSE ( NOT DOT ) + SET( HAVE_DOT YES ) +ENDIF ( NOT DOT ) + +SET( ZYPP_PROJECT_ROOT ${LIBZYPP_SOURCE_DIR} ) + +STRING( JOIN " " ZYPP_SOURCE_DIRS + ${LIBZYPP_SOURCE_DIR}/zypp + ${LIBZYPP_SOURCE_DIR}/zypp-core + ${LIBZYPP_SOURCE_DIR}/zypp-curl + ${LIBZYPP_SOURCE_DIR}/zypp-media + ${LIBZYPP_SOURCE_DIR}/zypp-proto + ${LIBZYPP_SOURCE_DIR}/zypp-tui +) +SET( ZYPP_DOCINCLUDE_DIR ${LIBZYPP_SOURCE_DIR}/doc/autoinclude ) + +SET( DOXYGEN_INPUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile ) +SET( DOXYGEN_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/html/index.html ) +SET( DOXYGEN_WARNINGS ${CMAKE_CURRENT_BINARY_DIR}/Doxywarnings ) +FILE( MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html ) + +### ################################################## + +CONFIGURE_FILE( + ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.cmake + ${DOXYGEN_INPUT} + @ONLY + ) + +### ################################################## + +ADD_CUSTOM_COMMAND ( + OUTPUT ${DOXYGEN_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E echo_append "Building Documentation..." + COMMAND ${DOXYGEN} ${DOXYGEN_INPUT} || { echo '*** IGNORE FAILED DOXYGEN - DOC MIGHT BE INCOMPLETE!'\; true\; } + COMMAND ${CMAKE_COMMAND} -E echo "Done." + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${DOXYGEN_INPUT} +) + +ADD_CUSTOM_TARGET( doc ALL + DEPENDS ${DOXYGEN_OUTPUT} +) + +ADD_CUSTOM_TARGET( doc_forced + COMMAND ${CMAKE_COMMAND} -E echo_append "Building Documentation..." + COMMAND ${DOXYGEN} ${DOXYGEN_INPUT} || { echo '*** IGNORE FAILED DOXYGEN - DOC MIGHT BE INCOMPLETE!'\; true\; } + COMMAND ${CMAKE_COMMAND} -E echo "Done." + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${DOXYGEN_INPUT} +) + +### ################################################## + +INSTALL( FILES + ${CMAKE_CURRENT_BINARY_DIR}/libzypp.doxytag + DESTINATION ${DOC_INSTALL_DIR}/libzypp/libzypp.doxytag +) + +INSTALL( DIRECTORY + ${CMAKE_CURRENT_BINARY_DIR}/html + DESTINATION ${DOC_INSTALL_DIR}/libzypp +) +### ################################################## +ENDIF ( DOXYGEN ) +### ################################################## diff --git a/doc/autodoc/Doxyfile.cmake b/doc/autodoc/Doxyfile.cmake new file mode 100644 index 0000000..1795adf --- /dev/null +++ b/doc/autodoc/Doxyfile.cmake @@ -0,0 +1,217 @@ +# Doxyfile 1.4.4 + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = @PACKAGE@ +PROJECT_NUMBER = @VERSION@ +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = @ZYPP_PROJECT_ROOT@ +STRIP_FROM_INC_PATH = @ZYPP_PROJECT_ROOT@ +#STRIP_FROM_INC_PATH = @ZYPP_PROJECT_ROOT@/zypp @ZYPP_PROJECT_ROOT@/zypp-core +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = YES +MULTILINE_CPP_IS_BRIEF = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +SEPARATE_MEMBER_PAGES = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = YES +EXTRACT_PRIVATE = YES +EXTRACT_STATIC = YES +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = NO +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = YES +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = @DOXYGEN_WARNINGS@ +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = @ZYPP_SOURCE_DIRS@ +FILE_PATTERNS = *.h *.hh *.hxx *.hpp *.h++ *.c *.cc *.cxx *.cpp *.c++ *.tcc *.hcc *.doc +RECURSIVE = YES +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +#EXCLUDE_PATTERNS = */zyppng/* +EXAMPLE_PATH = @ZYPP_DOCINCLUDE_DIR@ +EXAMPLE_PATTERNS = +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = YES +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = NO +REFERENCES_RELATION = NO +USE_HTAGS = NO +VERBATIM_HEADERS = NO +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = YES +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = YES +TREEVIEW_WIDTH = 250 +USE_MATHJAX = YES +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = NO +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = NO +XML_OUTPUT = xml +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = @PACKAGE@.doxytag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = NO +HAVE_DOT = @HAVE_DOT@ +CLASS_GRAPH = YES +COLLABORATION_GRAPH = NO +GROUP_GRAPHS = NO +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = NO +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_DEPTH = 0 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/doc/autoinclude/ApplicationMetada.doc b/doc/autoinclude/ApplicationMetada.doc new file mode 100644 index 0000000..880b3c3 --- /dev/null +++ b/doc/autoinclude/ApplicationMetada.doc @@ -0,0 +1,15 @@ +/** + +\page zypp-appdata [Dropped in Code 15] Code 12 Application Metadata + +\author Michael Andres + +
+ +\section zypp-appdata_intro Intro + +In Code12 we introduced \c application as new kind of resolvable object (see e.g. http://worldofgnome.org/gnome-software-on-opensuse). + +In Code15 (with libyzpp-17.7.0) we dropped type \c application due to poor AppStream metadata support (bsc#1100095, bsc#1104415). + +*/ diff --git a/doc/autoinclude/CodePitfalls.doc b/doc/autoinclude/CodePitfalls.doc new file mode 100644 index 0000000..71d0cca --- /dev/null +++ b/doc/autoinclude/CodePitfalls.doc @@ -0,0 +1,60 @@ +namespace zypp +{ +/** \page CodePitfalls Code Pitfalls - Frequently made mistakes + +\section TriBoolCompare Comparing TriBool values + + Comparing two \ref TriBool values is not as easy as it might look like, + because the \c TriBool::operator== and \c TriBool::operator!= return + a \ref TriBool. + + For example is (indeterminate==indeterminate) not \c true, but + \c indeterminate. That's why the following snippet does not do what the + author expected: + + \code + // buggy option class + struct Option + { + public: + Option() + : _value( indeterminate ) + {} + + bool get() const + { return ( _value == indeterminate ) ? true : bool(_value); } + + void set( bool new_r ) + { _value = new_r; } + + private: + tribool _value; + }; + \endcode + + You find that \c get() returns \c false as long as the option is unset, + and not \c true as the code suggests. That's because (_value==indeterminate) + returns \c indeterminate. + + \note Always use \c indeterminate(_value) to test whether a TriBools value is \c indeterminate: + + \code + bool get() const + { return indeterminate( _value ) ? true : bool(_value); } + \endcode + + \code + tribool _value; + ... + if ( indeterminate( _value ) ) + { ... } // indeterminate + else if ( _value ) + { ... } // true + else + { ... } // false + \endcode +
+ + +*/ +} diff --git a/doc/autoinclude/EnvironmentVariables.doc b/doc/autoinclude/EnvironmentVariables.doc new file mode 100644 index 0000000..1789df1 --- /dev/null +++ b/doc/autoinclude/EnvironmentVariables.doc @@ -0,0 +1,64 @@ +/** + +\page zypp-envars Environment Variables + +\author Michael Andres + +\section zypp-envars-intro Environment Variables + +Note that for Boolean variables we usually test whether the variable exists and not for the assigned value. + +\subsection zypp-envars-config zypp config options + +\li \c ZYPP_CONF= Location of the zypp.conf file. +\li \c ZYPP_LOCK_TIMEOUT= If zypp is locked by another process wait this number of seconds for the lock becoming available. A negative value will wait forever. + +\subsection zypp-envars-repos Variables related to repositories + +\li \c ZYPP_REPO_RELEASEVER= Overwrite the \c $releasever variable in repository URLs and names (\see zypp::repo::RepoVariablesStringReplacer). + +\subsection zypp-envars-commit Variables related to commit + +\li \c ZYPP_IS_RUNNING=1 Set during commit so packages pre/post/trigger scripts can detect whether rpm was called from within libzypp. +\li \c ZYPP_SINGLE_RPMTRANS=1 Enable alternative and !!!experimental!!! commit strategy where all rpm operations are executed in a single rpm transaction, which results in much faster commits. + +\subsection zypp-envars-logging Variables related to logging + +\li \c ZYPP_LOGFILE= Location of the logfile to write or \c - for stderr. +\li \c ZYPP_FULLLOG=1 Even more verbose logging (usually not needed). +\li \c ZYPP_LIBSOLV_FULLLOG=1 Verbose logging when resolving dependencies. +\li (\c ZYPP_LIBSAT_FULLLOG=1) deprecated since \c libzypp-10.x, prefer \c ZYPP_LIBSOLV_FULLLOG +\li \c LIBSOLV_DEBUGMASK= Pass value to libsolv::pool_setdebugmask + +\li \c ZYPP_MEDIANETWORK=1 Turn on the media network backend (the upcoming default). +\li \c ZYPP_MEDIA_CURL_DEBUG=<1|2> Log http headers, if \c 2 also log server responses. +\li \c ZYPP_MEDIA_CURL_IPRESOLVE=<4|6> Tell curl to resolve names to IPv4/IPv6 addresses only. +\li \c ZYPP_METALINK_DEBUG=1 Log URL and priority of the mirrors parsed from a metalink file. +\li \c ZYPP_MULTICURL=0 Turn off multicurl (metalink and zsync) and fall back to plain libcurl. + +\li \c ZYPP_RPM_DEBUG=1 Log verbose output from all rpm commands. + +\subsection zypp-envars-mediabackend Selecting the mediabackend to use. + +\li \c ZYPP_MULTICURL=0 Turn off multicurl (metalink and zsync) and fall back to plain libcurl. +\li \c ZYPP_MEDIANETWORK=1 Turn on the new multithreaded backend (experimental) + +\subsection zypp-envars-plugin Variables related to plugins + +\li \c ZYPP_PLUGIN_DEBUG=1 Verbose logging from plugin framework. +\li \c ZYPP_PLUGIN_TIMEOUT= Send/receive timeout for plugin communication. +\li \c ZYPP_PLUGIN_SEND_TIMEOUT= Send timeout for plugin communication. +\li \c ZYPP_PLUGIN_RECEIVE_TIMEOUT= Receive timeout for plugin communication. + +\li \c ZYPP_PLUGIN_APPDATA_FORCE_COLLECT=1 Make RepoManager trigger the appdata collector plugin unconditionally. Can be used with \c 'zypper \c lr' (as root) to trigger an initial collect rather than calling \c 'zypper \c ref \c -f' or waiting for some repo to be refreshed. + +\subsection zypp-envars-misc Variables not for common use (test and debug) + +\li \c ZYPP_MODALIAS_SYSFS= Use this instead of \c /sys to evaluate modaliases. +\li \c ZYPP_COMMIT_NO_PACKAGE_CACHE=1 +\li \c ZYPP_TESTSUITE_FAKE_ARCH Never use this! +\li \c ZYPPTMPDIR= +\li \c ZYPP_LOCKFILE_ROOT= Hack to circumvent the currently poor --root support. +\li \c ZYPP_PROFILING=1 + +*/ diff --git a/doc/autoinclude/FeatureTest.doc b/doc/autoinclude/FeatureTest.doc new file mode 100644 index 0000000..6198792 --- /dev/null +++ b/doc/autoinclude/FeatureTest.doc @@ -0,0 +1,85 @@ +/** + +\page feature-test Testing for provided features. + +\author Michael Andres + +
+\section intro Introduction + +The libzypp rpm package will indicate the presence of certain features by using special \c Provides: + +\verbatim + # Provides: libzypp(FEATURE) = FEATURE_VERSION + Provides: libzypp(code10) = 0 +\endverbatim + +Packages requiring a feature may use the corresponding \c Requires: in their .spec file. + + +
+\section features Features +
+ +
plugin
+
+
version 0
+
General ability to provide and handle plugins.
+
version 0.1
+
Bugfix: don't reject header values containing a ':'.
+
+ +
plugin:commit
+
+
\ref plugin-commit
+
version 0
+
Basic plugin indicating start and end of commit.
+
version 1
+
Added COMMITBEGIN/COMMITEND.
+
+ +
plugin:repoverification
+
+
\ref plugin-repoverification
+
version 0
+
Repository metadata verification beyond GPG.
+
+ +
plugin:services
+
+
\ref plugin-services
+
version 0
+
Provide a client a list of repositories.
+
version 1
+
Support multiple repo baseurls in plugin services.
+
+ +
plugin:system
+
+
\ref plugin-system
+
version 0
+
Plugin executed when system content change is detected (by now SUSE Manager/spacewalk only).
+
version 1
+
Plugin executed when system content change is detected (all installed plugins).
+
+ +
plugin:urlresolver
+
+
\ref plugin-url-resolver
+
version 0
+
Convert urls of scheme "plugin" into a supported scheme.
+
+ +
repovarexpand
+
+
\ref zypp-repovars
+
version 0
+
Also support braced variables, shell like default and alternate values.
+
version 1
+
Also support user defined repo variables in /etc/zypp/vars.d.
+
version 1.1
+
Support repo variables in an URIs \c host and \c port component.
+
+
+ +*/ diff --git a/doc/autoinclude/Mainpage.doc b/doc/autoinclude/Mainpage.doc new file mode 100644 index 0000000..85613c3 --- /dev/null +++ b/doc/autoinclude/Mainpage.doc @@ -0,0 +1,67 @@ +/** \mainpage Welcome to libzypp + +\section intro Introduction + +Welcome to the libzypp documentation. + +libzypp is the package management library that powers applications like YaST, zypper and the openSUSE/SLE implementation of PackageKit. + +\section whatis What is libzypp? + +libzypp provides all the functionality for a package manager: + +- An API for package repository management, supporting most common repository metadata formats and signed repositories. +- An API for solving packages, products, patterns and patches (installation, removal, update and distribution upgrade operations) dependencies, with additional features like locking. +- An API for commiting the transaction to the system over a rpm target. Supporting deltarpm calculation, media changing and installation order calculation. +- An API for browsing available and installed software, with some facilities for programs with an user interface. +- A suite of maintained solving testcases representing common and uncommon operations on Linux software management + +\section impl Implementation + +libzypp is implemented as a C++ library with experimental bindings available for python and ruby. + +\section otherfunc Other functionality offered by libzypp + +Most of libzypp functionality is implemented over components provided also by libzypp: + +- Media abstraction library offering a common interface over local files, http,ftp,iso,nfs and other protocols. + +\section thirdpfunc 3rd party software libzypp is based on + +Additionally, some functionality libzypp uses is based on 3rd party libraries: + +- SAT solver library, for dependency solving and repository data storage and querying +- curl, that powers some protocols of the media abstraction component +- boost, for misc. utilities like shared pointers, functors and algorithms. + +\section join Join the community + +Visit our web site at : http://en.opensuse.org/Libzypp or #zypp on irc.freenode.net + +\section license License + +\code +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +Copyright (C) 2000-2002 Ximian, Inc. +Copyright (C) 2005 SUSE Linux Products GmbH + +ZYpp is licensed under the GNU General Public License version 2 +or later. The text of the GNU General Public License can be viewed at +http://www.gnu.org/licenses/gpl.html + +As a special exception, you have permission to link this program +with the following libraries and distribute executables, as long as you +follow the requirements of the GNU GPL in regard to all of the +software in the executable aside from the following libraries: +- OpenSSL (http://www.openssl.org) +\endcode + +*/ \ No newline at end of file diff --git a/doc/autoinclude/Modalias.doc b/doc/autoinclude/Modalias.doc new file mode 100644 index 0000000..9481b63 --- /dev/null +++ b/doc/autoinclude/Modalias.doc @@ -0,0 +1,18 @@ +/** + +\page zypp-modalias Hardware (modalias) dependencies + +\author Michael Andres + +
+ +Rpm packages which support a specific hardware and should be installed automatically if this hardware is present use \c modalias() supplements. \c FNMATCH(3) is used to match the defined pattern against the systems modalias definitions. + +\note Special characters not allowed to occur in a spec-files \c Supplements: definition may be %Hexencoded. + +\code + # of:NfirmwareT*Craspberrypi,bcm2835-firmwareC* + Supplements: modalias(of:NfirmwareT*Craspberrypi%2Cbcm2835-firmwareC*) +\endcode + +*/ diff --git a/doc/autoinclude/PatternPackages.doc b/doc/autoinclude/PatternPackages.doc new file mode 100644 index 0000000..3d87237 --- /dev/null +++ b/doc/autoinclude/PatternPackages.doc @@ -0,0 +1,95 @@ +/** + +\page zypp-pattern-packages Code 12 Pattern Packages + +\author Michael Andres + +
+ +\section zypp-pattern-packages_intro Intro + +Since Code12 (SLES-12) we utilize a new method of defining patterns, as opposed to the older XML-based patterns files. A pattern and its dependencies are now represented by a rpm package and the few pattern specific properties are provided by the package. No extra XML-file is needed. + +By convention a patterns-package for a pattern:FOO is named patterns-[*-]FOO and is must provide pattern() = FOO. Usually the patterns-package name has a distribution or product identifier embedded, like in patterns-sles-Minimal or patterns-openSUSE-xfce. + +The patterns content is expressed by the patterns-packages' dependencies to other packages and patterns-packages. + +The list of patterns-package provides used for the new pattern autogeneration: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Basic provides relevant for package management (libzypp/zypper):
Provides: pattern() = FOOThe patterns name: FOO. Additional attributes like version, release, architecture, summary and description are taken from the pattenrs-package.
Provides: pattern-visible()A UI hint telling whether the pattern should be shown to the user. If the provides is missing, the UI will usually hide the pattern in lists and output. This is mainly used for helper patterns defining a basic content which is then required/recommended by different (visible) patterns.
Additional pattern properties not used by libzypp, but provided by the API mainly for the YAST UI:
Provides: pattern-icon() = STRINGName of an icon the UI should use for this pattern.
Provides: pattern-order() = STRINGA string used by the UI for sorting patterns rather than 'by name'. Usually some 4-digit string like "1750"
Provides: pattern-category() = STRINGThe category name used in the UI in English (en).
Provides: pattern-category(de) = STRINGThe category name translated. E.g. into German (de).
Provides: pattern-includes() = STRINGHint for the UI to include an other patterns content (i.e. its required and recommended packages) in this patterns content list. Usually used to embed the content of an invisible pattern in a visible one.
Provides: pattern-extends() = STRINGReverse-includes. Hint for the UI to include this patterns content (i.e. its required and recommended packages) in an other patterns content list. Usually used to embed the content of an invisible pattern in a visible one.
STRING must be url-hexencoded so that it does not contain any characters that rpm-provides can't have.
+ E.g.: ' ' => %20 / ',' => %2C / '-' => %2D
+ +\code +patterns-sles-Minimal-12-37.1.x86_64.rpm + PROVIDES { + pattern() == Minimal + pattern-icon() == pattern-basis + pattern-order() == 1099 + pattern-visible() + pattern-category() == Base%20Technologies + pattern-category(ar) == %D8%A7%D9%84%D8%AA%D9%83%D9%86%D9%88%D9%84%D9%88%D8%AC%D9%8A%D8%A7%D8%AA%20%D8%A7%D9%84%D8%A3%D8%B3%D8%A7%D8%B3%D9%8A%D8%A9 + pattern-category(ca) == Tecnologies%20de%20base + pattern-category(cs) == Z%C3%A1kladn%C3%AD%20technologie + pattern-category(da) == Basisteknologier + pattern-category(de) == Basistechnologien + ... +} + REQUIRES { + systemd + coreutils + insserv + aaa_base + ... +} + RECOMMENDS (22){ + grub2 + rpcbind + nfs-client + rsyslog + ... +} +\endcode + +*/ diff --git a/doc/autoinclude/Plugin-Commit.doc b/doc/autoinclude/Plugin-Commit.doc new file mode 100644 index 0000000..e03173e --- /dev/null +++ b/doc/autoinclude/Plugin-Commit.doc @@ -0,0 +1,115 @@ +/** + +\page plugin-commit Commit plugin + +\author Michael Andres + +
+\section intro Introduction + +This is a statefull plugin executed during \ref zypp::ZYpp::commit. At the beginning of a commit all plugins found in \c /usr/lib/zypp/plugins/commit are launched. The plugins will receive messages as commit proceeds. Unless otherwise specified messages received need to be confirmed by sending an \c ACC message. Sending back an unexpected or \c ERROR message execution of the plugin will be canceled. + +If you have e.g. \c zypp-plugin-python installed a basic commit plugin could look like this: + +\verbatim +#!/usr/bin/env python +# +# zypp commit plugin +# +import os +import sys +from zypp_plugin import Plugin + +class MyPlugin(Plugin): + + def PLUGINBEGIN(self, headers, body): + # commit is going to start. + if headers.has_key('userdata'): + print "Commit starts with TID '%s'" % headers['userdata'] + self.ack() + + def PLUGINEND(self, headers, body): + # commit ended + self.ack() + +plugin = MyPlugin() +plugin.main() +\endverbatim + +\see \ref plugin-writing + +
+\section pluginbegin PLUGINBEGIN +\verbatim +PLUGINBEGIN +userdata:TIDfoo42 + +^@ +\endverbatim +Sent as 1st message after the plugin was launched. Prepare your plugin and send an \c ACC message when you are done. Commit will start after all plugins are initialized. + +\li \c userdata:stringval Optional header sent if the application has provided a user data string. \see \ref zypp-userdata + + +
+\section commitbegin COMMITBEGIN (added in v1) +\verbatim +COMMITBEGIN + +{ +"TransactionStepList": [ ,... ] +} +^@ +\endverbatim +Sent before installation actually starts. The body contains a JSON encoded object providing the \c TransactionStepList, basically the list of install/remove actions the the commit is going to perform. Each \c TransactionStep is encoded as JSON object: +\verbatim + = { + "type": # [optional] + "stage": # [optional] + "solvable": +} + + = # ignore; implicit or non-package actions + | "-" # remove + | "+" # install + | "M" # multi version install; install keeping the old version; e.g. kernel + + = # todo + | "ok" # done + | "err" # failed + + = { + "n": # name + "e": # epoch if not 0 [optional] + "v": # version + "r": # release + "a": # architecture +} +\endverbatim + +\see \ref zypp::sat::Transaction::Step + +
+\section commitend COMMITEND (added in v1) +\verbatim +COMMITEND + +{ +"TransactionStepList": [ ,... ] +} +^@ +\endverbatim +Sent at the end of commit. The body contains a JSON encoded object providing the final \c TransactionStepList. The \c StepStage indicates whether the action succeeded, failed or was skipped (still 'todo'). + +\see \ref commitbegin + +
+\section pluginend PLUGINEND +\verbatim +PLUGINEND + +^@ +\endverbatim +This message is sent at the end of commit. You should receive this message even if commit was aborted by some unexpected exception. + +*/ diff --git a/doc/autoinclude/Plugin-Repoverification.doc b/doc/autoinclude/Plugin-Repoverification.doc new file mode 100644 index 0000000..7ddef1f --- /dev/null +++ b/doc/autoinclude/Plugin-Repoverification.doc @@ -0,0 +1,34 @@ +/** + +\page plugin-repoverification Repository metadata verification plugin + +\author Michael Andres + +
+\section intro Introduction + +Stateless plugins found in \c /usr/lib/zypp/plugins/repoverification are called during a repository metadata refresh, immediately after a repositories master index file has been downloaded and before any further GPG checks are performed. The plugins determine whether the repository is allowed to be used on the system or not. If a plugin returns not-zero, the repository is discarded and can not be used. + +All executable plugins found in \c /usr/lib/zypp/plugins/repoverification (relative to the RepoManagers root directory) are launched in arbitrary order. If the RepoManagers root directory is not \c /, the plugins are executed via \c chroot. + +Arguments passed to the plugin are: +
+ +
--file PATH
+
Path to the repositories master index file.
+ +
--fsig PATH
+
Path to the master index files detached gpg signature. A path is always supplied, but whether it actually denotes a file depends on whether the master index file is actually signed.
+ +
--fkey PATH
+
Path to the ascii armored GPG key that signed the signature. A path is always supplied, but whether it actually denotes a file depends on whether the key is provided by the repo.
+ +
--ralias NAME
+
The alias of the repository.
+ +
+ +All output written to stdout/stderr is forwarded to the application (zypper,YAST,PK...) and may become visible to the user. All output written to stderr is also captured in the logfile, in case logging is enabled by the application. + +\see \ref plugin-writing +*/ diff --git a/doc/autoinclude/Plugin-System.doc b/doc/autoinclude/Plugin-System.doc new file mode 100644 index 0000000..5642c32 --- /dev/null +++ b/doc/autoinclude/Plugin-System.doc @@ -0,0 +1,75 @@ +/** + +\page plugin-system System plugin + +\author Michael Andres + +
+\section intro Introduction + +This is a statefull plugin executed at the end of \ref zypp::ZYpp::commit, if the system content has change, i.e. if packages have actually been installed or deleted. + +All plugins found in \c /usr/lib/zypp/plugins/system are launched. Unless otherwise specified, messages received need to be confirmed by sending an \c ACC message. Sending back an unexpected or \c ERROR message, the execution of the plugin will be canceled. + +If you have e.g. \c zypp-plugin-python installed a basic system plugin could look like this: + +\verbatim +#!/usr/bin/env python +# +# zypp system plugin +# +import os +import sys +from zypp_plugin import Plugin + +class MyPlugin(Plugin): + + def PACKAGESETCHANGED(self, headers, body): + + // Installation has ended. The set of installed packages has changed. + // .... + + self.ack() + def + +plugin = MyPlugin() +plugin.main() +\endverbatim + +\see \ref plugin-writing + +
+\section pluginbegin PLUGINBEGIN +\verbatim +PLUGINBEGIN +userdata:TIDfoo42 + +^@ +\endverbatim +Sent as 1st message after the plugin was launched. Prepare your plugin and send an \c ACC message when you are done. + +\li \c userdata:stringval Optional header sent if the application has provided a user data string. \see \ref zypp-userdata + + +
+\section packagesetchanged PACKAGESETCHANGED +\verbatim +PACKAGESETCHANGED + +^@ +\endverbatim +Installation has ended. The set of installed packages has changed. + +\see \ref zypp::sat::Transaction::Step + +
+\section pluginend PLUGINEND +\verbatim +PLUGINEND + +^@ +\endverbatim +This message is sent at the end before the plugin is closed. You should receive this message even if the action was aborted by some unexpected exception. + + +*/ diff --git a/doc/autoinclude/Plugins.doc b/doc/autoinclude/Plugins.doc new file mode 100644 index 0000000..2f7eb00 --- /dev/null +++ b/doc/autoinclude/Plugins.doc @@ -0,0 +1,234 @@ +/** + +\page zypp-plugins Extending ZYpp: Plugins and Hooks + +\author Duncan Mac-Vicar P. +\author Michael Andres + +
+\section plugins-intro Introduction + +Plugins allow one to extend the ZYpp package manager without the need to change +code. Plugins are designed as external programs so that they can be written in any language. + +\section plugin-protocols Plugin protocols + +Depending on the complexity and need for future extension, plugins talk +to ZYpp using two methods. + +\subsection plugin-protocol-stateless Stateless + +This type of plugin receive input reading the standard input, and answer ZYpp writing to the standard output. This means the plugin is executed once per hook and they are stateless (unless the plugin keeps the state out of process). + +\subsection plugin-protocol-stateful Stateful + +This type of plugin is called by ZYpp and a conversation using a simple protocol. The protocol is based on STOMP https://stomp.github.io (Streaming Text Orientated Messaging Protocol). Messages (called "frames") look like the following: + +\verbatim +COMMAND +param1:val1 +param2:val2 +... +Thus a COMMAND followed by key:value header lines +and a multiline body separated from header +by an empty line and terminated by NUL. +^@ +\endverbatim + +\note ^@ is a null (control-@ in ASCII) byte. + +
+\section plugin-writing Writing plugins + +A python class is offered as a helper to handle communication between the plugin and +libzypp. It is available by installing \c zypp-plugin-python. + +\verbatim +zypper in -C zypp-plugin-python +\endverbatim + +The plugin must define a method for each message it may receive from \ref libzypp. Message header list and body are passed to the method as arguments. + +\verbatim +#!/usr/bin/env python +# +# zypp plugin +# +import os +import sys +from zypp_plugin import Plugin + +class MyPlugin(Plugin): + + def SAMPLE( self, headers, body ): + # called upon revieving a SAMPLE message + ... + if ( ok ): + self.ack() + else: + self.error( { "aheader":"header value" }, "body\n(multiline text ok)" ) + +plugin = MyPlugin() +plugin.main() +\endverbatim + +Two methods \c ack and \c error are available to send back a standard \c ACK or \c ERROR message. You may optionally pass header entries and a multiline body. For sending custom messages use \c answer, which takes the command name as 1st argument, followed by optional header entries and a multiline body. + +Plugin closes \c stdin and exits when receiving a \c _DISCONNECT message. Upon an \c ACK response to \c _DISCONNECT libzypp will not attempt to kill the script. An exit value different than \c 0 may be set via an \c 'exit' header in \c ACK. + +\verbatim + def _DISCONNECT( self, headers, body ): + sys.stding.close() + self.ack( {'exit':'99'}, 'Famous last words.' ) +\endverbatim + +
+\section plugins-impl Developers: Implementation + +Plugins are implemented in the following classes: + +- \ref zypp::PluginScript (Plugin as an external program) +- \ref zypp::PluginScriptException +- \ref zypp::PluginFrame (Message for the stateful protocol) +- \ref zypp::PluginFrameException +- \ref zypp::repo::PluginServices (Finds Service plugins) + +The plugins default location is obtained from \ref zypp::ZConfig::pluginsPath() + +
+\section plugin-toc Supported plugins + +\subpage plugin-commit Escort installation of packages + +\subpage plugin-system Receive notification if system content has changed + +\subpage plugin-repoverification Repository metadata verification beyond GPG + +\ref plugin-services + +\ref plugin-url-resolver + +\ref plugin-appdata + +
+\section plugin-services Service plugins + +ZYpp will find a subscribed service for each executable located in /usr/lib/zypp/plugins/services and will set the alias as the executable name. The type will be set to "plugin". + +Service plugins are used to provide a client a list of repositories from a central location where more complex logic is needed than a simple remote xml index accessible via http (in that case you can use \ref services-remote "Remote Services"). + +\subsection plugin-services-example1 Example: Management console + +You have a custom mass management application that controls the repositories each client muss have. While you can use \ref services-remote "Remote Services" and subscribe each client to an url in the server providing a dynamic repoindex.xml based on the client, if you need to pass custom information in order for the server to calculate the repository list (e.g. number of CPUs) or the protocol that the client and the server and client speak is proprietary, you may implement the service locally, as an executable that will be installed in each client /usr/lib/zypp/plugins/services directory (it may be installed from a package). + +\subsection plugin-services-how How to write a Services plugin + +When listing services, ZYpp will find each plugin service as a subscribed service. + +Service plugins are Stateless. When services are refreshed, ZYpp will call each plugin and the repository list will be taken from the output of the script in INI format (same as how they are stored in /etc/zypp/repos.d). + +For our example: + +\verbatim +# example plugin output +# comments are ignored +[repo1] +name=Base repository +summary=Standard repository +baseurl=http://server.com/repo1 +type=rpm-md + +# multiple repositories can be present in the output + +[repo2] +... +\endverbatim + +The repositories will be added on service refresh with the alias present in the output, prefixed by the service alias (in this case, the executable name). + +To protect your code from e.g python modules writing their own messages to stdout, you should use a copy of stdout and redirect stdout to stderr (Python3 may need a slightly different print syntax): + +\verbatim +#!/usr/bin/python +import sys +sendback = sys.stdout +sys.stdout = sys.stderr + +print >>sendback, "# example plugin output" +print >>sendback, "# comments are ignored" +print >>sendback, "[repo1]" +print >>sendback, "name=Base repository" +... +\endverbatim + +
+\section plugin-url-resolver Url Resolver plugins + +Url resolver plugins convert urls of scheme "plugin" into the output of the plugin named $name using the protocol. Thanks to the protocol, each header returned is also added as HTTP headers. The current protocol sequence is: + +ZYpp sees a repository whose url has the format: + +\verbatim +plugin:foo?param1=val1¶m2=val2 +\endverbatim + +ZYpp tries to execute a plugin named foo (in /usr/lib/zypp/plugins/urlresolver) and call it with the following protocol: + +\verbatim + RESOLVEURL + param1:val1 + param2:val2 + ... + ^@ +\endverbatim + +The plugin answers: + +\verbatim + RESOLVEDURL: + header1:val1 + header2:val2 + ... + http://realurl.com?opts=vals + ^@ +\endverbatim + +And this url is used instead. + +\subsection plugin-urlresolver-example Example + +You have a repository with url: + + plugin:lan + +The script looks which distribution you have installed, and via SLP finds the right repositories in the lan and selects the update one and returns it url. But in addition, it adds a header with the update status that can be collected on the server side. + +This type of plugin can be combined with service plugins, because a local service could return a list of repos like this: + +\verbatim + [distro] + name=Distribution repository + baseurl=plugin:lan?repo=distro + [update] + name=Update repository + baseurl=plugin:lan?repo=update +\endverbatim + +\note +In this example, the service plugin could have inmediately resolved the urls and returned http://realurl, but the url resolver allows also to add HTTP headers to the request. + +
+\section plugin-appdata Appdata refresh plugins (repo change) + +Stateless plugins found in /usr/lib/zypp/plugins/appdata are called whenever any of the system repos has changed (added/removed/renamed/modified) or has been refreshed. Detailed information \b what exactly has changed is not available. (scripts are executed IFF euid is '0' and --root is not used). For every enabled system repo we pass alias type and metadata path on the commandline like this: + +\verbatim + -R REPO_ALIAS -t REPO_TYPE -p REPO_METADATA_PATH -R NEXT_REPO.... +\endverbatim + +\note REPO_TYPE can be e.g. "rpm-md", "yast2", "plaindir" or "NONE" indicating the repo was not yet probed. + +\note REPO_METADATA_PATH can be empty or a not existing directory, indicating valid metadata for the repo are not yet available. + +Scripts are executed 'fire and forget' whenever a RepoManager instance that performed changes goes out of scope. So it's up to the script to protect against concurrency. +*/ diff --git a/doc/autoinclude/README b/doc/autoinclude/README new file mode 100644 index 0000000..cc16030 --- /dev/null +++ b/doc/autoinclude/README @@ -0,0 +1,54 @@ +All .doc files here will be parsed and included in the autodocs generated +by doxygen (see http://www.doxygen.org/). All the other files here (mostly +below notes) are available to be vervatim included in some documentation +block using: + + /** \include somefile + */ + or + /** \example + */ + + +The .doc files here will mostly provide: + +- The content of the main index page (defined in Mainpage.doc). + +- Other related documentation pages: + + /*! \page page1 A documentation page + Leading text. + \section sec An example section + This page contains the subsections \ref subsection1 and \ref subsection2. + For more info see page \ref page2. + \subsection subsection1 The first subsection + Text. + \subsection subsection2 The second subsection + More text. + */ + + /*! \page page2 Another page + Even more info. + */ + +Those pages will per default appear in the documentations 'Related Pages' +section, unless you refer to them from within soome other page by using +'\subpage': + + /** \mainpage A simple manual + + Some general info. + + This manual is divided in the following sections: + - \subpage intro + - \subpage advanced "Advanced usage" + */ + + +- Documentation for a group of classes defined by \ingroup: + + /*! \defgroup g_Resolvable Resolvable Objects + Some explanation. + */ + +- And whatever else we don't want to keep in the header files. diff --git a/doc/autoinclude/RepoVariables.doc b/doc/autoinclude/RepoVariables.doc new file mode 100644 index 0000000..89c6d71 --- /dev/null +++ b/doc/autoinclude/RepoVariables.doc @@ -0,0 +1,40 @@ +/** + +\page zypp-repovars Repository Variables + +\author Michael Andres + +\section zypp-repovars-intro Repository Variables + +Within a \c .repo or \c .service file, the name and URLs are subject to variable substitution. + +Variables are e.g. useful for related repositories like packman (http://ftp.gwdg.de/pub/linux/packman/suse/$releasever), which shall always fit the installed distribution, even after a distribution upgrade. To help performing a distribution upgrade, the value of \c $releasever can be overwritten in zypper using the \c --releasever global option. This way you can easily switch all repositories using \c $releasever to the new version (provided the server layouts did not change and new repos are already available). + +The variable expander also supports shell like definition of default and alternate values. + +\see \ref zypp::repo::RepoVarExpand Variable expander + + +\subsection zypp-repoars-builtin Builtin repository variables + +\li \c $arch - + The system's CPU architecture. + +\li \c $basearch - + The base architecture of the system. For example, iX86 machines have a base architecture of \c i386, while AMD64 and Intel64 have \c x86_64. + +\li \c $releasever - + The version of your openSUSE or SUSE Linux. The value is obtained from the /product/version XML-node in /etc/products.d/baseproduct. + +\li \c $releasever_minor +\li \c $releasever_major - + \c $releasever_major will be set to the leading portion up to (but not including) the 1st dot; \c $releasever_minor to the trailing portion after the 1st dot. If there's no dot in \c $releasever, \c $releasever_major is the same as \c $releasever and \c $releasever_minor is empty. + + +\subsection zypp-repoars-userdefined User defined repository variables [requires 'libzypp(repovarexpand) >= 1'] + +A custom repository variable is defined by creating a file in \c /etc/zypp/vars.d. The variable name equals the file name. The files first line (up to but not including the newline character) defines the variables value. Valid variable(file) names consist of alphanumeric chars and '_' only. + +Variable substitution within an URIs authority [requires 'libzypp(repovarexpand) >= 1.1'] is limited to \c host and \c port. Bash style definition of default and alternate values is not supported. No variables can be used in an URIs \c scheme, \c user and \c password. + +*/ diff --git a/doc/autoinclude/Services.doc b/doc/autoinclude/Services.doc new file mode 100644 index 0000000..7bc69d2 --- /dev/null +++ b/doc/autoinclude/Services.doc @@ -0,0 +1,241 @@ +/** + +\page zypp-services Services + +\author Duncan Mac-Vicar P. + +Services provide a list of repositories. So when the service is refreshed, the repositories specified by the service service is synced with the local repository list. + +\section service-types Classes of services + +There are two classes of services: + +\subsection services-remote Remote Services + +Remote services are a subscription to a remote server, that provide a list of repositories that will be synced with the previous list of repositories for the same service. + +By default, the remote services list is stored in the \ref /etc/zypp/services.d directory in standard INI files. Each file can contain more than one service. + +The format is the following: + +\verbatim +[servicealias] +name=My Service +url=http://customers.maintenance.company.com/service +enabled=true +autorefresh=true +type=nu +\endverbatim + +The type "nu" stands for Novell Update, which gives a customer the repositories it is entitled to access. The type "ris" is an extended version of the "nu" type. +Additionally, the file could contain "repostoenable" and "repostodisable" entries, which contain a list of repository aliases to enable or disable on the next refresh. This line is modified by other programs to force enabling or disabling a certain repository. + +From the remote side, the service url needs to provide a repoindex.xml file with the repository list: + +\verbatim + + + +... + +\endverbatim + +\subsection services-plugin Plugin Services + +\ref plugin-services "Plugin services" are simple scripts that return a list of repositories. They are installed locally in the system using packages. For each script installed ZYpp will “see” a service of type “plugin”. When you refresh the service, the repositories this script returns as output will be added (or removed and kept in sync if they change afterwards). + +A plugin service is a program installed in /usr/lib/zypp/plugins/services. + +Once a program called "foobar" is installed, listing services will show it: + +\verbatim +> zypper ls +# | Alias | Name | Enabled | Refresh | Type +---+------------------+--------------+---------+---------+------- +1 | foobar | foobar | Yes | Yes | plugin +... +... +\endverbatim + +When this service is refreshed, the program will be executed and it will return +the list of repositories in the same .repo files format that can be found in +/etc/zypp/repos.d: + +\verbatim +# output returned by the plugin + +[repo-oss] +name=oss +enabled=1 +autorefresh=0 +baseurl=http://download.opensuse.org//distribution/11.4/repo/oss +type=yast2 +keeppackages=0 + +... +\endverbatim + +As you can see, the main advantage of plugin services is that they can read information from the client and calculate the repository list from there. Nothing prevents a plugin service to still interact with a server to get the repository list. + +The main disadvantage is that you have logic in the client side that in case of bugs or changes, needs to be updated. + +Spacewalk integration is implemented using plugin services. The plugin talks XML-RPC to the server and asks for the list of channels the system is subscribed to. The plugin needs to read the server address and perform the login. + +However, the spacewalk plugin service does have an extra indirection, as the repository list returned are not plain urls, but urls of the type plugin:$name?params, which use the urlresolver plugin to get the real url. This is not necessary, and here it is done because it allows to add custom headers to the HTTP requests. You can read more about urlresolver plugins \ref plugin-url-resolver here. + +\section service-refresh Refreshing services + +Using zypper, you can refresh services by executing + +\verbatim +zypper refs +\endverbatim + +The repositories that are listed in the service will be added, using the reposotiy alias specified in the service index prefixed by the service alias: e.g. "myservice:myrepository". Repositories that vanished from the service will be automatically removed. + +\section service-examples Example usecases + +\subsection services-usecase-1 Usecase #1: The project with multiple repositories and layers + +Imagine the following usecase (with this one I am using some real request from our KDE guys) + +The build service provides a KDE4 repository. Which in turn requires the Qt4 repository, because is built on openSUSE 11.0 + the new Qt4 repo. + +When looking at this problem, repository dependencies is what comes to head in the first place. But forget about them. If package dependencies are complicated right now, imagine adding a secondary (and duplicated) layer of information. Packages already know their dependencies. + +Now imagine our KDE guys can provide an URL, which you add to zypper. And this url returns a dynamic list of repositories. And zypper adds and remove repositories based on the information returned by this url on every refresh. + +\subsection services-usecase-2 Usecase #2: Update repositories based on the customer + +This is actually where services where originated. Services were present in Novell ZenWorks. How it works? + +The service url nu.novell.com is added to the system. But in this url also a customer id is present as a http username. When you registered, Novell knows the subscription and products this system is linked to and what entitlements the customer has. The service can then return a dynamic list of repositories based on the customer preferences, products and entitlements. The customer does not need to keep them manually in sync. + +Now that we don’t have Zenworks in the base system, we still want this cool functionality for our customers, therefore ZYpp now implements services natively. + +Technically, this even allows us to offer hotfixes to L3 supported customers on the fly: the system is marked on the server side as being hotfixed, and an extra temporary repository with the PTF (Problem Temporary Fix) packages is added to this system list of repositories. + +\subsection services-usecase-3 Usecase #3: Dynamic repository collections + +You are a build service user, and you have an account, and of course you have a list of watched projects you are interested to. What if you could keep your system repositores in sync with your watched project list. + +Or what if the build service could offer a service based on keywords or other data: like http://build.opensuse.org/services/mostpopular/repo/repoindex.xml would contain dynamically the 15 most popular repositories. You add that service, and then ZYpp does the work for you of adding new popular repositories, and remove the old ones. + +\subsection services-usecase-4 Usecase #4: Collect openSUSE core repos in one service + +Some people prefer to keep and maintain the distros core repos within one local service rather than managing the repos individually. Since version 14.21.0 libzypp supports a simple form of variable replacement within a repoindex.xml file, which makes this even easier. + +To use a local RIS service create a directory /somewhere on your disk (or accessible via http, nfs, etc.) and create the file +./repo/repoindex.xml inside. A repoindex.xml for openSUSE Leap 15.1 might look like this: + +\verbatim + + + + + + + + + + + + + + + + + + + + + +\endverbatim + +%{VAR} always refers to the value defined in the repoindex tag. Reserved names are 'ttl' and 'alias'. + +- ttl="SECONDS" defines the matadata's expected time to live in case autorefresh is turned on for the service. It's the number of seconds that should pass before the service is autorefreshed again. It is not available as variable. +- %{alias} is available within a repo tag after the alias was defined there. + +Given the file is located at /somewhere/repo/repoindex.xml, add the service by: +\verbatim +zypper sa /somewhere openSUSE +\endverbatim + +Manually refresh the service (incl. its repos) with: +\verbatim +zypper refs -r +\endverbatim + +Refreshing the service will evaluate the repoindex.xml and adjust the Services repos accordingly. The repos alias will be prefixed by the service name: +\verbatim +zypper lr +> # | Alias | Name | Enabled | ... | Refresh +> ---+-------------------------+-----------------------+---------+-...-+-------- +> 9 | openSUSE:debug-non-oss | debug-non-oss (15.1) | No | ... | ---- +> 10 | openSUSE:debug-oss | debug-oss (15.1) | No | ... | ---- +> 11 | openSUSE:repo-non-oss | repo-non-oss (15.1) | Yes | ... | Yes +> 12 | openSUSE:repo-oss | repo-oss (15.1) | Yes | ... | Yes +> 13 | openSUSE:source-non-oss | source-non-oss (15.1) | No | ... | ---- +> 14 | openSUSE:source-oss | source-oss (15.1) | No | ... | ---- +> 15 | openSUSE:upadte-non-oss | upadte-non-oss (15.1) | Yes | ... | Yes +> 16 | openSUSE:update-oss | update-oss (15.1) | Yes | ... | Yes +\endverbatim + +After editing the repoindex.xml you must manually refresh the service to takeover the changes, or you turn on autorefresh for the service (depends on how often you change the content): +\verbatim +zypper ms -r openSUSE +\endverbatim + +Rather than hardcoding the distver="15.1", you can also use a repo variable like distver="${releasever}". + +\section service-impl Developers: Implementation + +Services are implemented in the following classes: + +- \ref zypp::repo::ServiceType (Service types enumeration) +- \ref zypp::parser::ServiceFileReader (.service file parser) +- \ref zypp::ServiceInfo Information about a service (.service file data) +- \ref zypp::repo::PluginServices (Services as plugins) +- \ref zypp::parser::RepoindexFileReader (NU and RIS remote service index XML parser) +- \ref zypp::repo::ServiceRepos (Repositories in a service) + + +*/ diff --git a/doc/autoinclude/SolverVendorChange.doc b/doc/autoinclude/SolverVendorChange.doc new file mode 100644 index 0000000..6e3977a --- /dev/null +++ b/doc/autoinclude/SolverVendorChange.doc @@ -0,0 +1,86 @@ +/** + +\page pg_zypp-solv-vendorchange Solver - Vendor protection + +\author Michael Andres + +\section zypp-solv-vendorchange Vendor protection rule + +Tracing a packages origin \c libzypp uses the packages \c vendor string. The \c vendor string is part of the rpm header and thus defined at the time the package was built. It stays the same, no matter which repository was used to ship the package. Using \c rpm is one way to retrieve a packages \c vendor string: + +\code +$ rpm -q --qf '%{name} \tvendor: %{vendor}\n' libzypp nautilus libdvdread3 +libzypp vendor: openSUSE +nautilus vendor: obs://build.opensuse.org/GNOME +libdvdread3 vendor: http://packman.links2linux.de +\endcode + +Also several \c zypper commands will display a packages \c vendor: + +\code +$ zypper info libzypp + +Information for package libzypp: + +Repository: openSUSE-11.4-Update +Name: libzypp +Version: 8.12.6-0.2.1 +Arch: x86_64 +Vendor: openSUSE <=== +Installed: Yes +Status: up-to-date +Installed Size: 7.0 MiB +Summary: Package, Patch, Pattern, and Product Management +Description: +Package, Patch, Pattern, and Product Management +\endcode + +\subsection zypp-solv-vendorchange-rule The vendor protection rule is quite simple: + +\note When looking for an installed packages \e update \e candidate, we are looking for a package originated by the \e same \e vendor (not repository!) as the \e installed one. + + +\section zypp-solv-vendorchange-tune Vendor protection tuning + +The \e brute \e force method is to turn off all vendor protection in \c /etc/zypp/zypp.conf: + +\code +## +## EXPERTS ONLY: Per default the solver will not replace packages of +## different vendors, unless you explicitly ask to do so. Setting this +## option to TRUE will disable this vendor check (unless the application +## explicitly re-enables it). Packages will then be considered based on +## repository priority and version only. This may easily damage your system. +## +## CHANGING THE DEFAULT IS NOT RECOMMENDED. +## +## Valid values: boolean +## Default value: false +## +solver.allowVendorChange = true +\endcode + +\subsection zypp-solv-vendorchange-equiv Groups of equivalent vendor strings + +A built in example for this is the \c vendor string \c SuSE. All vendor strings starting (case insensitive) with \c "suse", are considered to be the \e same \e vendor and their packages may replace each other without asking. + +You may define your own classes of equivalent \c vendor strings by creating an entry in the \c /etc/zypp/vendors.d directory. For each group of \c vendor strings create a file, name it as you like, with the following content: + +\code +[main] +## A comma separated list of equivalent vendor string (prefixes!) +## Example: +## vendors = suse,opensuse +vendors = +\endcode + +\note A built in rule unifying \c "suse" and \c "opensuse" was disabled in libzypp-16.7.1. The above example would recreate it. + +\note Within the \c "opensuse*" namespace exact matches (case insensitive) are required. The above example will allow switching between \c "suse*" and \c "opensuse" but not e.g. \c "opensuse build service". + + +\section zypp-solv-vendorchange-Impl Related classes + +\li \ref zypp::VendorAttr (vendor string equivalence and \c vendors.d parser) + +*/ diff --git a/doc/autoinclude/Testcases.doc b/doc/autoinclude/Testcases.doc new file mode 100644 index 0000000..022af6e --- /dev/null +++ b/doc/autoinclude/Testcases.doc @@ -0,0 +1,121 @@ +/** \page Testcases Writing and tunning testcases + +\section Introduction Introduction + +ZYpp has a suite of tests located in under test/ directory of the source tree. + +Right now, tests are grouped into + +- media : tests related to downloading and the http/ftp/nfs/iso abstraction layer +- parser : tests related to classes that offer file format parsing +- repo : tests related to repository handling +- sat : tests related to the sat-solver integration +- zypp : tests related to the main libzypp classes and APIs + +Tests are written using boost test library. + +- Boost Test Library +- The Unit Test Framework +- The UTF testing tools reference + +\section Anatomy Anatomy of a ZYpp testcase + +The file should be in one of the described groups, and by general rule it is named ClassName_test.cc where ClassName is the name of the class or module the test covers. + +Data and fixtures are stored in data/ directories in each test group. However groups may use and reference data from other test groups. The macro \ref TESTS_SRC_DIR is defined as the tests/ directory located in libzypp source directory. You can build the paths to the data/fixtures using that macro. + +A simple testcase: + +\code +#include "zypp/Date.h" +#include + +BOOST_AUTO_TEST_CASE(date_test) +{ + std::string format = "%Y-%m-%d %H:%M:%S"; + std::string date = "2009-02-14 00:31:30"; + BOOST_CHECK_EQUAL(zypp::Date(date,format).form(format), date); +} +\endcode + +\section Building Building and running the testsuite + +- Build the testsuite + +\verbatim +$ cd build +$ cmake -DCMAKE_INSTALL_PREFIX=/prefix .. +$ cd tests +$ make +\endverbatim + +- Run a simple test + +\verbatim +$ zypp/Date_test +Running 1 test case... + +*** No errors detected +\endverbatim + +- Run all tests + +\verbatim +$ ctest . +\endverbatim + +\section + + +\verbatim + - added tests/data/openSUSE-11.1 containing raw susetags metadata. + Keeping .solv files in svn is somewhat inconvenient, as you must rebuild them + if something in libsolv changes. +\endverbatim + +\verbatim + - added tests/include as location for includes that might be used in multiple + testcases. +\endverbatim + +\verbatim + - added tests/include/TestSetup.h to ease building a test environment below + some tempdir. Currently supports easy setup of Target, RepoManager and + loading data (raw metadata and .solv files) into the pool. + + That's how it currently looks like: + + #include "TestSetup.h" + + BOOST_AUTO_TEST_CASE(WhatProvides) + { + TestSetup test( Arch_x86_64 ); // use x86_64 as system arch + test.loadTarget(); // initialize and load target + test.loadRepo( TESTS_SRC_DIR"/data/openSUSE-11.1" ); + + This is all you need to setup Target, RepoManager below some temp directory + and load the raw metadata into the pool. + + In case you want to setup the system below some fix directory, use: + + TestSetup test( "/tmp/mydir", Arch_x86_64 ); + + You directory is used as it is and not removed at the end. +\endverbatim + +\verbatim + - Added support for loading helix files e.g. from testcases. This is what + you need to load all repos from a solver testcase into the pool: + + #include "TestSetup.h" + + BOOST_AUTO_TEST_CASE(test) + { + TestSetup test( Arch_x86_64 ); + test.loadTestcaseRepos( "/suse/ma/BUGS/153548/YaST2/solverTestcase" ); + +\endverbatim + +\section References + +*/ diff --git a/doc/autoinclude/Threads.doc b/doc/autoinclude/Threads.doc new file mode 100644 index 0000000..b2a9c61 --- /dev/null +++ b/doc/autoinclude/Threads.doc @@ -0,0 +1,26 @@ +/** + +\page thread Libzypp and threads + +\author Michael Andres + +\section thread_intro Libzypp and threads + +Libzypp is \b not thread safe. + +Before we can think about using threads in libzypp, or even libzypp in threads, a bunch of components have to be fixed. + +\li \c Logging as one one of the core components has to become threadsafe. + +\li \c SmartPointer as one of the core patterns implementing resource control need to become threadsafe + +\li \c ...more + + +\subsection thread_loggin Logging in threads + +\see http://accu.org/index.php/journals/1539, http://www.pantheios.org/ + +Need to estimate performance impact when making the current zypp::log implementation threadsafe. Current implementation is based on STL streams with a custom linebuffer. + +*/ \ No newline at end of file diff --git a/doc/autoinclude/UserData.doc b/doc/autoinclude/UserData.doc new file mode 100644 index 0000000..cd7d544 --- /dev/null +++ b/doc/autoinclude/UserData.doc @@ -0,0 +1,17 @@ +/** +\page zypp-userdata User data as transaction id + +\author Michael Andres + +
+\section userdata-introduction Introduction + +It is possible to store a user defined data string via \ref zypp::ZConfig::setUserData inside libzypp for use as a transaction id. \c Zypper e.g. supports this via its global '--userdata ' option. + +\li Setting a new user data string, a line will be written to the log file. So you can \c grep for it, or for '(setUserData)' to find all locations where user data strings were set. + +\li The user data string will also be passed to commit plugins, so they can make use of it. The btrfs e.g would be able to tag created snapshots with this string. \see \ref plugin-commit + +\li The user data string will appear on each histoy line logging package or repository related events (install, delete, add, modify). \see \ref zypp::HistoryLog and zypp::parser::HistoryLogReader + +*/ diff --git a/doc/autoinclude/g_BOOST.doc b/doc/autoinclude/g_BOOST.doc new file mode 100644 index 0000000..df2fa86 --- /dev/null +++ b/doc/autoinclude/g_BOOST.doc @@ -0,0 +1,12 @@ +/** \namespace boost \ref BOOST +*/ +/** \defgroup BOOST Boost libraries. + +Boost provides free peer-reviewed portable C++ source libraries. +Several \c ::boost names were dragged or typedefed into +namespace \c ::zypp. +\see http://www.boost.org/ + +*/ + + diff --git a/doc/autoinclude/g_LIBSOLV.doc b/doc/autoinclude/g_LIBSOLV.doc new file mode 100644 index 0000000..6295767 --- /dev/null +++ b/doc/autoinclude/g_LIBSOLV.doc @@ -0,0 +1,7 @@ +/** \namespace zypp::sat \ref LIBSOLV +*/ +/** \defgroup LIBSOLV Libsolv interface + +Interface to sat-pool and sat-solver. + +*/ diff --git a/doc/autoinclude/g_ZyppHistory.doc b/doc/autoinclude/g_ZyppHistory.doc new file mode 100644 index 0000000..c701713 --- /dev/null +++ b/doc/autoinclude/g_ZyppHistory.doc @@ -0,0 +1,89 @@ +/** \defgroup g_ZyppHistory Libzypp History File + +Log important events like installation/deletion of packages and repositories. + + +\section g_ZyppHistory_Location Location + +The default location is \c /var/log/zypp/history. This can be changed via \c history.logfile key in \c /etc/zypp/zypp.conf. + + +\section g_ZyppHistory_Format Format + +\li CSV file with pipe character (|) as the value separator +\li one event per line +\li different actions have different set of values (columns), see the tables below +\li lines starting with # are treated as comments + +\see \ref zypp-userdata + +\subsection g_ZyppHistory_Format_Colummn Action Columns + +\subsubsection g_ZyppHistory_Format_Colummn_Install Install +A package has been installed. +\li \b 1 timestamp +\li \b 2 action ID (\c "install") +\li \b 3 package name +\li \b 4 package epoch:version-release +\li \b 5 package architecture +\li \b 6 requested by (user@hostname, pid:appname, or empty (solver)) +\li \b 7 repository alias +\li \b 8 package checksum +\li \b 9 userdata/transactionId + +\subsubsection g_ZyppHistory_Format_Colummn_Remove Remove +A package has been removed. +\li \b 1 timestamp +\li \b 2 action ID (\c "remove") +\li \b 3 package name +\li \b 4 package epoch:version-release +\li \b 5 package architecture +\li \b 6 requested by (user@hostname, pid:appname, or empty (solver)) +\li \b 7 userdata/transactionId + +\subsubsection g_ZyppHistory_Format_Colummn_Radd Radd +A repository has been added. +\li \b 1 timestamp +\li \b 2 action ID (\c "radd") +\li \b 3 repository alias +\li \b 4 primary URL +\li \b 5 userdata/transactionId + +\subsubsection g_ZyppHistory_Format_Colummn_Rremove Rremove +A repository has been removed. +\li \b 1 timestamp +\li \b 2 action ID (\c "rremove") +\li \b 3 repository alias +\li \b 4 userdata/transactionId + +\subsubsection g_ZyppHistory_Format_Colummn_Ralias Ralias +A repository alias has changed. +\li \b 1 timestamp +\li \b 2 action ID (\c "ralias") +\li \b 3 old alias +\li \b 4 new alias +\li \b 5 userdata/transactionId + +\subsubsection g_ZyppHistory_Format_Colummn_Rurl Rurl +The primary URL of a repository has changed. +\li \b 1 timestamp +\li \b 2 action ID (\c "rurl") +\li \b 3 repository alias +\li \b 4 new URL +\li \b 5 userdata/transactionId + + +\section g_ZyppHistory_Example Example + +\code +2008-09-24 11:48:58|rremove|packman +2008-09-24 11:50:02|radd |packman|http://packman.iu-bremen.de/suse/11.0 +2008-09-24 11:53:10|install|amarok-yauap|1.4.10-25|x86_64||factory|4421dfa718ab73c805c1c695c97b1b67f39bf2f3 +2008-09-24 11:53:25|install|amarok-lang|1.4.10-25|x86_64||factory|691030edafcc4fbc22aa225350f9de32974e4bc2 +# Additional rpm output: +# warning: /var/cache/zypp/packages/packman/x86_64/amarok-1.4.10-100.pm.1.x86_64.rpm: Header V3 DSA signature: NOKEY, key ID 9a795806 +# +2008-09-24 11:53:45|install|amarok|1.4.10-100.pm.1|x86_64|root@kompost|packman|ee0fffa1e4eeaaeb8799bd05c6882ef74100d681 +\endcode + +*/ diff --git a/doc/autoinclude/groups.doc b/doc/autoinclude/groups.doc new file mode 100644 index 0000000..4369f48 --- /dev/null +++ b/doc/autoinclude/groups.doc @@ -0,0 +1,28 @@ +//////////////////////////////////////////////////////////////////////////////// +// Short or empty group definitions. Move them to a sepearate .doc file if +// more text is provided. +//////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_EnumerationClass Enumeration Class +*/ +//////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_RAII RAII solutions + \see http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization +*/ +//////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_CRTP CRTP solutions + \see http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern +*/ +//////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_BackenSpecific Backend Specific +*/ +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_Functor Filters and Functors +*/ +//////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_Algorithm Algorithms +*/ +//////////////////////////////////////////////////////////////////////////////// +/*! \defgroup g_Parser Parser +*/ +//////////////////////////////////////////////////////////////////////////////// diff --git a/doc/autoinclude/notes/n_ResPool_nomorenameiter b/doc/autoinclude/notes/n_ResPool_nomorenameiter new file mode 100644 index 0000000..2be1405 --- /dev/null +++ b/doc/autoinclude/notes/n_ResPool_nomorenameiter @@ -0,0 +1,71 @@ + +I tagged the byName iterator as deprecated, so the compiler tells you +where it is used. Please review the code and check whether byIdent is +an appropriate replacement. + + +-- +The 'old' zypp pool internally maintained a byName index, so it was a +fast way to iterate the pool by name and filter by kind to visit e.g. +all packages named foo: + + invokeOnEach( pool.byNameBegin( name ), pool.byNameEnd( name ), + resfilter::ByKind( kind ), + action() ); + + for_( it, pool.byNameBegin( name ), pool.byNameEnd( name ) ) + { + if ( (*it)->kind() == kind ) + { + ... + } + } + +This is no longer true. + + + +In contrary, byName now is a 'quite expensive' iteration. It's faster to +rewrite these loops using byIdent (and no filter): + + invokeOnEach( pool.byIdentBegin( kind, name ), + pool.byIdentEnd( kind, name ), + action() ); + + for_( it, pool.byIdentBegin( kind, name ), pool.byNameEnd( kind, name ) ) + { + ... + } + + +How to construct the byIdent iterator: + + ResPool::byIdentBegin( poolItem ) // using this poolItems kind and name + ResPool::byIdentBegin( kind, name ) // explicit kind and name + ResPool::byIdentBegin( name ) // or templated kind + + + +-- + +If you prefer using iterator in a for' loop, but dislike to figure out +the exact type of the iterator, you may find the 'for_' macro convenient: + + #include "zypp/base/Easy.h" + + for_( it, pool.byIdentBegin( kind, name ), + pool.byIdentEnd( kind, name ) ) + { + PoolItem copy = *it; + } + + +instead of: + + for ( ResPool::byIdent_iterator it = pool.byIdentBegin( kind, name ), + end = pool.byIdentEnd( kind, name ); + it != end, ++it ) + { + PoolItem copy = *it; + } + diff --git a/doc/locks.5.txt b/doc/locks.5.txt new file mode 100644 index 0000000..cfd94d0 --- /dev/null +++ b/doc/locks.5.txt @@ -0,0 +1,153 @@ +LOCKS(5) +======== +:man manual: LIBZYPP +:man source: SUSE Linux + + +NAME +---- +locks - libzypp locking file + + +DESCRIPTION +----------- +The file '/etc/zypp/locks' is read by libzypp at start-up if 'zypp.conf' allows it. The entries are used for initial locking of packages. Locking a package means not allowing to install or uninstall it. + +Valid entries are of the form: + +'attribute'*:* 'value':: + Where attributes and their values are described below. + +Locks are separated by an empty lines. + + +ATTRIBUTES +---------- +All attributes are lower-case. + +*repo*:: + specifies repository restriction. Only alias is accepted. + + By default all repositories match. + +*type*:: + resolvable type restriction. The values can be *package*, *patch*, *pattern*, *product* and *srcpackage*. + + By default all types match. + + +*case_sensitive*:: + if strings are matched case sensitive. The values are *true*, *false*, *on*, *off*. + + The default is case insensitive. + + +*install_status*:: + status of object. Possible states are *installed*, *not-installed* and *all*. If more install statuses are specified then the last one is used. The values are *installed* for all packages which are installed, *non-installed* for packages which can be installed or reinstalled and *all* for both. + + The default is *all*. + + +*match_type*:: + type of string matching in values. Does not affect *type* and *repo* which must be specified exactly. The values are *exact*, *substring*, *regex* for regular expressions, *glob* for matching as on the command line, and *word*. + + The default is *substring*. + +*query_string*:: + String to be matched in multiple attributes. Should be restricted by another attribute with empty value (it is recommended, because without restriction expect some performance problems). + +*version*:: + Restrict the lock only to some versions. It contains two parts: an optional operator and the version. + + The operator is *==*, *!=*, *<*, *>*, *<=*, *>=*. If operator is not specified then *==* is used. + + The version has the format ['epoch'*:*+]+'version'[*-*'release']. + + Example: *version: < 0:0.11.4-2* + +*solvable_name*:: + name of object (e.g. zypper) + +*solvable_summary*:: + summary of object + +*solvable_arch*:: + architecture of object (e.g. x86_64, i586) + +*solvable_description*:: + description of object + +*solvable_eula*:: + license text of objects which request accepting license by user + +*solvable_license*:: + license of package (only for package) (e.g. GPL2) + +*solvable_keywords*:: + keywords which specify package (only for package) + +*solvable_authors*:: + authors of package (only for package) + +*solvable_group*:: + package group (only for package) (e.g. Development/Tools/Version Control ) + +*update_reference_type*:: + reference for update (e.g. bugzilla,cve) (only for patches) + + +EXAMPLES +-------- +*Exact Package*:: + This is the way YaST UI does it. Lock k3b (e.g. you don't want to update it). +-------------------- +-----locks----- +type: package +solvable_name: k3b +match_type: exact +case_sensitive: on +-------------------- + +*Package Wildcard*:: + This is the way "zypper addlock cross-*-gcc-icecream-backend" does it. +-------------------- +-----locks----- +type: package +solvable_name: cross-*-gcc-icecream-backend +match_type: glob +case_sensitive: on +-------------------- + +*Versioned Lock*:: + Do not install new GCC. This format is used when converting from the openSUSE-10.3 lock format. +-------------------- +-----locks----- +solvable_name: gcc +match_type: glob +version: > 4.2 +-------------------- + +*Anything named KDE*:: + Locks everything which contains kde in the name. +-------------------- +-----locks----- +solvable_name: kde +-------------------- + +*Anything mentioning KDE*:: + Locks everything which contains kde in the name, summary, or description. +-------------------- +-----locks----- +query_string: kde +solvable_name: +solvable_summary: +solvable_description: +-------------------- + + +HOMEPAGE +-------- +This manual page only covers the most important attributes. The complete list is available at http://en.opensuse.org/Libzypp/Locksfile + + +AUTHORS +------- +Josef Reidinger +Manual page contributions by Martin Vidner . + + +SEE ALSO +-------- +zypper(8) diff --git a/doc/zypp-CheckAccessDeleted.1.txt b/doc/zypp-CheckAccessDeleted.1.txt new file mode 100644 index 0000000..a25b0fd --- /dev/null +++ b/doc/zypp-CheckAccessDeleted.1.txt @@ -0,0 +1,39 @@ +ZYPP-CHECKACCESSDELETED(1) +========================== +:man manual: LIBZYPP +:man source: SUSE Linux + + +NAME +---- +zypp-CheckAccessDeleted - List processes which access deleted files + + +SYNOPSIS +-------- +*zypp-CheckAccessDeleted* [_OPTION_]... + + +DESCRIPTION +----------- +List running processes which access deleted files. This may help to identify services and processes which need to be restarted after an update, e.g. if they still refer to meanwhile deleted libraries. The output is similar to `*zypper ps*' but does not sort out processes accessing normal files only. + + +OPTIONS +------- +*--help*:: + display help and exit +*--zypper*:: + use less verbose zypper mode to list processes +*--debugFile* 'filename':: + Reads process and opened files information from a file that was created by zypper previously + + +AUTHORS +------- +Michael Andres + + +SEE ALSO +-------- +zypper(8) diff --git a/doc/zypp-NameReqPrv.1.txt b/doc/zypp-NameReqPrv.1.txt new file mode 100644 index 0000000..cc1708f --- /dev/null +++ b/doc/zypp-NameReqPrv.1.txt @@ -0,0 +1,72 @@ +ZYPP-NAMEREQPRV(1) +================== +:man manual: LIBZYPP +:man source: SUSE Linux + + +NAME +---- +zypp-NameReqPrv - Investigate packages and dependencies in solver test-cases + + +SYNOPSIS +-------- +*zypp-NameReqPrv* [*--root* 'DIR'] [['OPTIONS'] 'NAME'...]... + + +DESCRIPTION +----------- +Load all enabled repositories (without refresh) and search for occurrences of regular expression 'NAME' in package names or dependencies. In case 'DIR' denotes a directory containing a solver test-case, repositories and settings provided by the test-case are loaded instead. + +A solver test-case is an abstract of repositories, packages, hardware and dependency resolution related settings which can be created by using zyppers *--debug-solver* option. Attached to a bug report the test-case helps investigating the reported behavior. Options and output of this command are tailored to this use-case and may change as needed. + +Reported matches show the packages 'internal id', 'name', 'version' and 'architecture', 'priority' and name of the providing 'repository', 'vendor', 'buildtime' and the locations matching 'NAME'. + +-------------------- +2431 zypper-1.9.16-22.2.x86_64 (99)@System openSUSE 1400499579 + nam: zypper +40947 zypper-1.9.3-1.1.x86_64 (99)repo-oss (13.1) openSUSE 1383049437 + nam: zypper +56140 zypper-1.9.16-22.2.x86_64 (99)repo-oss-update (13.1) openSUSE 1400499579 + nam: zypper +-------------------- + + +OPTIONS +------- +*--root* 'DIR':: + Load repos from the system located below 'DIR'. If 'DIR' denotes a solver test-case, the test-case is loaded. +*--installed*:: + Process installed packages only. +*-i*/*-I*:: + Turn on/off case insensitive search (default on) +*-n*/*-N*:: + Turn on/off looking for names (default on) +*-p*/*-P*:: + Turn on/off looking for provides (default off) +*-r*/*-R*:: + Turn on/off looking for requires (default off) +*-c*/*-C*:: + Turn on/off looking for conflicts (default off) +*-o*/*-O*:: + Turn on/off looking for obsoletes (default off) +*-m*/*-M*:: + Turn on/off looking for recommends (default off) +*-s*/*-S*:: + Turn on/off looking for supplements (default off) +*-a*:: + Short for *-n -p -r* +*-A*:: + Short for *-n -P -R* +*-D* 'PKG':: + Dump dependencies of package 'PKG' (exact name). + + +AUTHORS +------- +Michael Andres + + +SEE ALSO +-------- +zypper(8) diff --git a/libzypp.pc.cmake b/libzypp.pc.cmake new file mode 100644 index 0000000..6e3e970 --- /dev/null +++ b/libzypp.pc.cmake @@ -0,0 +1,14 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@LIB_INSTALL_DIR@/zypp +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@ + +Name: @PACKAGE@ +Version: @VERSION@ +Description: Package, Patch, Pattern, and Product Management + +Libs: -L${libdir} -lzypp +Cflags: -I${includedir} -D_FILE_OFFSET_BITS=64 @ZYPP_CFLAGS@ + +features=@ZYPP_FEATURES@ + diff --git a/libzypp.spec.cmake b/libzypp.spec.cmake new file mode 100644 index 0000000..4d87111 --- /dev/null +++ b/libzypp.spec.cmake @@ -0,0 +1,443 @@ +# +# spec file for package libzypp +# +# Copyright (c) 2023 SUSE LLC +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + +%if 0%{?suse_version} > 1500 || 0%{?sle_version} >= 150400 || (0%{?is_opensuse} && 0%{?sle_version} >= 150100) +%bcond_without zchunk +%else +%bcond_with zchunk +%endif + +# libsolvs external references might require us to link against zstd, bz2, xz +%if 0%{?sle_version} >= 150000 || 0%{?suse_version} >= 1500 +%bcond_without zstd +%else +%bcond_with zstd +%endif +%if 0%{?sle_version} >= 120300 || 0%{?suse_version} >= 1330 || !0%{?suse_version} +%bcond_without bz2 +%bcond_without xz +%else +%bcond_with bz2 +%bcond_with xz +%endif + +%bcond_without mediabackend_tests + +# older libsigc versions have a bug that causes a segfault +# when clearing connections during signal emission +# see https://bugzilla.gnome.org/show_bug.cgi?id=784550 +%if 0%{?sle_version} < 150200 +%bcond_without sigc_block_workaround +%else +%bcond_with sigc_block_workaround +%endif + + +%if 0%{?suse_version} > 1500 || 0%{?sle_version} >= 150600 +%bcond_without visibility_hidden +%else +%bcond_with visibility_hidden +%endif + +# Distros using just zypper may want to enable this as default earlier +%bcond_with enable_preview_single_rpmtrans_as_default_for_zypper + +Name: libzypp +Version: @VERSION@ +Release: 0 +License: GPL-2.0-or-later +URL: https://github.com/openSUSE/libzypp +Summary: Library for package, patch, pattern and product management +Group: System/Packages +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Source: %{name}-%{version}.tar.bz2 +Source1: %{name}-rpmlintrc +Provides: yast2-packagemanager +Obsoletes: yast2-packagemanager + +# bsc#1227793: python zypp-plugin < 0.6.4 rejects stomp headers including a '-' +Conflicts: python2-zypp-plugin < 0.6.4 +Conflicts: python3-zypp-plugin < 0.6.4 + +# Features we provide (update doc/autoinclude/FeatureTest.doc): +Provides: libzypp(plugin) = 0.1 +Provides: libzypp(plugin:appdata) = 0 +Provides: libzypp(plugin:commit) = 1 +Provides: libzypp(plugin:services) = 1 +Provides: libzypp(plugin:system) = 1 +Provides: libzypp(plugin:urlresolver) = 0 +Provides: libzypp(plugin:repoverification) = 0 +Provides: libzypp(repovarexpand) = 1.1 + +%if 0%{?suse_version} +Recommends: logrotate +# lsof is used for 'zypper ps': +Recommends: lsof +%endif +BuildRequires: cmake >= 3.1 +BuildRequires: pkgconfig(openssl) +BuildRequires: pkgconfig(libudev) +%if 0%{?suse_version} >= 1330 +BuildRequires: libboost_headers-devel +BuildRequires: libboost_program_options-devel +BuildRequires: libboost_test-devel +BuildRequires: libboost_thread-devel +%else +BuildRequires: boost-devel +%endif +BuildRequires: dejagnu +BuildRequires: doxygen +BuildRequires: texlive-latex +BuildRequires: texlive-xcolor +BuildRequires: texlive-newunicodechar +BuildRequires: texlive-dvips +BuildRequires: ghostscript +BuildRequires: gcc-c++ >= 7 +BuildRequires: gettext-devel +BuildRequires: graphviz +BuildRequires: libxml2-devel +BuildRequires: yaml-cpp-devel + +# we are loading libproxy dynamically, however we have +# a failsafe unit test that links against libproxy to make +# sure the API did not change +BuildRequires: libproxy-devel + +#keep the libproxy runtime requires for old releases +%if 0%{?suse_version} && 0%{?suse_version} <= 1500 && 0%{?sle_version} <= 150500 +Requires: libproxy1 +%endif + +%if 0%{?fedora_version} || 0%{?rhel_version} || 0%{?centos_version} +BuildRequires: pkgconfig +%else +BuildRequires: pkg-config +%endif + +BuildRequires: libsolv-devel >= 0.7.24 +%if 0%{?suse_version} > 1500 || 0%{?sle_version} >= 150600 +BuildRequires: libsolv-tools-base >= 0.7.29 +%requires_eq libsolv-tools-base +Requires: ( findutils if libsolv-tools-base <= 0.7.31 ) +%else +BuildRequires: libsolv-tools +%requires_eq libsolv-tools +%endif + +BuildRequires: glib2-devel +BuildRequires: libsigc++2-devel +BuildRequires: readline-devel >= 5.1 + +# required for testsuite +%if %{with mediabackend_tests} +BuildRequires: nginx +BuildRequires: vsftpd +%endif + +Requires: rpm +BuildRequires: rpm + +%if 0%{?suse_version} +BuildRequires: rpm-devel > 4.4 +%endif + +%if 0%{?fedora_version} || 0%{?rhel_version} >= 600 || 0%{?centos_version} >= 600 +BuildRequires: popt-devel +BuildRequires: rpm-devel > 4.4 +%endif + +%if 0%{?mandriva_version} +BuildRequires: librpm-devel > 4.4 +%endif + +%if 0%{?suse_version} +BuildRequires: libgpgme-devel +#testsuite +%if %{with mediabackend_tests} +BuildRequires: FastCGI-devel +%endif +%else +BuildRequires: gpgme-devel +#testsuite +%if %{with mediabackend_tests} +BuildRequires: fcgi-devel +%endif +%endif + +%define min_curl_version 7.19.4 +BuildRequires: libcurl-devel >= %{min_curl_version} +%if 0%{?suse_version} +# Code11+ +Requires: libcurl4 >= %{min_curl_version} +%else +# Other distros (Fedora) +Requires: libcurl >= %{min_curl_version} +%endif + +# required for documentation +%if 0%{?suse_version} >= 1330 +BuildRequires: rubygem(asciidoctor) +%else +BuildRequires: asciidoc +BuildRequires: libxslt-tools +%endif + +%if %{with zchunk} +BuildRequires: libzck-devel +%endif + +%if %{with zstd} +BuildRequires: libzstd-devel +%endif + +%if %{with bz2} +%if 0%{?suse_version} +BuildRequires: libbz2-devel +%else +BuildRequires: bzip2-devel +%endif +%endif + +%if %{with xz} +BuildRequires: xz-devel +%endif + +%description +libzypp is the package management library that powers applications +like YaST, zypper and the openSUSE/SLE implementation of PackageKit. + +libzypp provides functionality for a package manager: + + * An API for package repository management, supporting most common + repository metadata formats and signed repositories. + * An API for solving packages, products, patterns and patches + (installation, removal, update and distribution upgrade + operations) dependencies, with additional features like locking. + * An API for commiting the transaction to the system over a rpm + target. Supporting deltarpm calculation, media changing and + installation order calculation. + * An API for browsing available and installed software, with some + facilities for programs with an user interface. + +%package devel +Summary: Header files for libzypp, a library for package management +Group: Development/Libraries/C and C++ +Provides: yast2-packagemanager-devel +Obsoletes: yast2-packagemanager-devel +Provides: libzypp-tui-devel = 1 +%if 0%{?suse_version} >= 1330 +Requires: libboost_headers-devel +Requires: libboost_program_options-devel +Requires: libboost_test-devel +Requires: libboost_thread-devel +%else +Requires: boost-devel +%endif +Requires: bzip2 +Requires: glibc-devel +Requires: libstdc++-devel +Requires: libxml2-devel +Requires: libzypp = %{version} +Requires: pkgconfig(openssl) +Requires: popt-devel +Requires: rpm-devel > 4.4 +Requires: zlib-devel +Requires: libudev-devel +%if 0%{?suse_version} +# Code11+ +Requires: libcurl-devel >= %{min_curl_version} +%else +# Other distros (Fedora) +Requires: libcurl-devel >= %{min_curl_version} +%endif +%if 0%{?suse_version} +%requires_ge libsolv-devel +%else +Requires: libsolv-devel +%endif + +%description devel +Development files for libzypp, a library for package, patch, pattern +and product management. + +%package devel-doc +Summary: Developer documentation for libzypp +Group: Documentation/HTML + +%description devel-doc +Developer documentation for libzypp. + +%prep +%autosetup -p1 + +%build +mkdir build +cd build +%if 0%{?suse_version} > 1500 +# Bug 1189788 - UsrMerge: filesystem package breaks system when upgraded in a single rpm transaction +# While the bug is not fixed, we don't allow ZYPP_SINGLE_RPMTRANS=1 on a not UsrMerged system +export CFLAGS="%{optflags} -DNO_SINGLETRANS_USERMERGE" +export CXXFLAGS="%{optflags} -DNO_SINGLETRANS_USERMERGE" +%else +export CFLAGS="%{optflags}" +export CXXFLAGS="%{optflags}" +%endif +unset EXTRA_CMAKE_OPTIONS + +cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -DENABLE_BUILD_DOCS=TRUE \ + -DENABLE_BUILD_TRANS=TRUE \ + -DENABLE_BUILD_TESTS=TRUE \ + -DDOC_INSTALL_DIR=%{_docdir} \ + -DLIB=%{_lib} \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_SKIP_RPATH=1 \ + -DCMAKE_INSTALL_LIBEXECDIR=%{_libexecdir} \ + %{?with_visibility_hidden:-DENABLE_VISIBILITY_HIDDEN=1} \ + %{?with_zchunk:-DENABLE_ZCHUNK_COMPRESSION=1} \ + %{?with_zstd:-DENABLE_ZSTD_COMPRESSION=1} \ + %{?with_sigc_block_workaround:-DENABLE_SIGC_BLOCK_WORKAROUND=1} \ + %{!?with_mediabackend_tests:-DDISABLE_MEDIABACKEND_TESTS=1} \ + %{?with enable_preview_single_rpmtrans_as_default_for_zypper:-DENABLE_PREVIEW_SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER=1} \ + ${EXTRA_CMAKE_OPTIONS} \ + .. +make %{?_smp_mflags} VERBOSE=1 + +%install +cd build +%make_install +%if 0%{?fedora_version} || 0%{?rhel_version} >= 600 || 0%{?centos_version} >= 600 +ln -s %{_sysconfdir}/yum.repos.d %{buildroot}/%{_sysconfdir}/zypp/repos.d +%else +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/repos.d +%endif +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/services.d +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/systemCheck.d +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/vars.d +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/vendors.d +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/multiversion.d +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/needreboot.d +mkdir -p %{buildroot}/%{_sysconfdir}/zypp/credentials.d +mkdir -p %{buildroot}/%{_prefix}/lib/zypp +mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins +mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/appdata +mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/commit +mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/services +mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/system +mkdir -p %{buildroot}/%{_prefix}/lib/zypp/plugins/urlresolver +mkdir -p %{buildroot}/%{_var}/lib/zypp +mkdir -p %{buildroot}/%{_var}/log/zypp +mkdir -p %{buildroot}/%{_var}/cache/zypp + +# Default to 'solver.dupAllowVendorChange = false' on TW and post SLE12 +%if 0%{?suse_version} >= 1330 || "%{distribution}" == "openSUSE Tumbleweed" +sed -i "s|# solver.dupAllowVendorChange = true|solver.dupAllowVendorChange = false|g" %{buildroot}%{_sysconfdir}/zypp/zypp.conf +%endif + +cd .. + +# Create filelist with translations +%{find_lang} zypp + +%if %{defined _distconfdir} +# Move logratate files form /etc/logrotate.d to /usr/etc/logrotate.d +mkdir -p %{buildroot}/%{_distconfdir}/logrotate.d +mv %{buildroot}/%{_sysconfdir}/logrotate.d/zypp-history.lr %{buildroot}%{_distconfdir}/logrotate.d +%endif + +%check +pushd build/tests +LD_LIBRARY_PATH="$(pwd)/../zypp:$LD_LIBRARY_PATH" ctest --output-on-failure . +popd + +%if %{defined _distconfdir} +%pre +# Prepare for migration to /usr/etc; save any old .rpmsave +for i in logrotate.d/zypp-history.lr; do + test -f %{_sysconfdir}/${i}.rpmsave && mv -v %{_sysconfdir}/${i}.rpmsave %{_sysconfdir}/${i}.rpmsave.old ||: +done +%endif + +%if %{defined _distconfdir} +%posttrans +# Migration to /usr/etc, restore just created .rpmsave +for i in logrotate.d/zypp-history.lr; do + test -f %{_sysconfdir}/${i}.rpmsave && mv -v %{_sysconfdir}/${i}.rpmsave %{_sysconfdir}/${i} ||: +done +%endif + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%files -f zypp.lang +%defattr(-,root,root) +%if 0%{?suse_version} >= 1500 +%license COPYING +%endif +%dir %{_sysconfdir}/zypp +%if 0%{?fedora_version} || 0%{?rhel_version} >= 600 || 0%{?centos_version} >= 600 +%{_sysconfdir}/zypp/repos.d +%else +%dir %{_sysconfdir}/zypp/repos.d +%endif +%dir %{_sysconfdir}/zypp/services.d +%dir %{_sysconfdir}/zypp/systemCheck.d +%dir %{_sysconfdir}/zypp/vars.d +%dir %{_sysconfdir}/zypp/vendors.d +%dir %{_sysconfdir}/zypp/multiversion.d +%config(noreplace) %{_sysconfdir}/zypp/needreboot +%dir %{_sysconfdir}/zypp/needreboot.d +%dir %{_sysconfdir}/zypp/credentials.d +%config(noreplace) %{_sysconfdir}/zypp/zypp.conf +%config(noreplace) %{_sysconfdir}/zypp/systemCheck +%if %{defined _distconfdir} +%{_distconfdir}/logrotate.d/zypp-history.lr +%else +%config(noreplace) %{_sysconfdir}/logrotate.d/zypp-history.lr +%endif +%dir %{_var}/lib/zypp +%if "%{_libexecdir}" != "%{_prefix}/lib" +%dir %{_libexecdir}/zypp +%endif +%dir %attr(750,root,root) %{_var}/log/zypp +%dir %{_var}/cache/zypp +%{_prefix}/lib/zypp +%{_datadir}/zypp +%{_bindir}/* +%{_libexecdir}/zypp/zypp-rpm +%{_libdir}/libzypp*so.* +%doc %{_mandir}/man1/*.1.* +%doc %{_mandir}/man5/*.5.* + +%files devel +%defattr(-,root,root) +%{_libdir}/libzypp.so +%{_libdir}/libzypp-tui.a +%{_datadir}/cmake/Modules/* +%{_includedir}/zypp +%{_includedir}/zypp-core +%{_includedir}/zypp-media +%{_includedir}/zypp-curl +%{_includedir}/zypp-tui +%{_libdir}/pkgconfig/libzypp.pc + +%files devel-doc +%defattr(-,root,root) +%{_docdir}/%{name} + +%changelog diff --git a/mkChangelog b/mkChangelog new file mode 100755 index 0000000..6d4303e --- /dev/null +++ b/mkChangelog @@ -0,0 +1,258 @@ +#! /bin/bash + +function Recho() { echo -e "\e[0;31m""$@""\e[0m"; } +function Gecho() { echo -e "\e[0;32m""$@""\e[0m"; } +function Becho() { echo -e "\e[0;34m""$@""\e[0m"; } + +function errexit() { + exec >&2 + Recho "Error: $@" + exit 1 +} + +function usage() { + exec >&2 + cat </dev/null || { + Recho "!!!" + Recho "!!! There is no LAST_RELEASE tag '$LAST_RELEASE'. Check manually. " + Recho "!!! (git tag -m 'tagging $LAST_RELEASE' '$LAST_RELEASE' ?commit?)" + Recho "!!!" + exit 8 +} + +if [ "$DRYRUN" == "1" ]; then + newchangesentry + sameVersion && { + Becho "!!! Version is unchanged at $LAST_RELEASE ($LAST_COMPAT)." + } + exit 0 +fi + +# check version file +# +while true; do + # $LAST_RELEASE + # $LAST_COMPAT + # $THIS_RELEASE + # $THIS_COMPAT + sameVersion && { + newchangesentry + Becho "!!! Version is unchanged at $LAST_RELEASE ($LAST_COMPAT)." + read -n 1 -p "$(Gecho "(a)bort, (c)ontinue, (P) patch, (M) minor, (I) incompat minor, (e)dit version [e]: ")" RES + echo + case "${RES:-e}" in + [eE]*) + Edit $VERSIONFILE + eval $(getversion) + continue + ;; + [cC]) + Becho "!!! Leave $VERSIONFILE untouched" + break + ;; + [P]) + setversion LIBZYPP_PATCH $(($THIS_PATCH + 1)) + eval $(getversion) + continue + ;; + [M]) + setversion LIBZYPP_MINOR $(($THIS_MINOR + 1)) + setversion LIBZYPP_PATCH 0 + eval $(getversion) + continue + ;; + [I]) + setversion LIBZYPP_COMPATMINOR $(($THIS_MINOR + 1)) + setversion LIBZYPP_MINOR $(($THIS_MINOR + 1)) + setversion LIBZYPP_PATCH 0 + eval $(getversion) + continue + ;; + *) + errexit "aborted" + ;; + esac + } + break +done + +# prepare changes file +# +TMPFILE=$(mktemp) +trap " [ -f \"$TMPFILE\" ] && /bin/rm -f -- \"$TMPFILE\" " 0 1 2 3 13 15 +{ newchangesentry; cat $CHANGESFILE; } >$TMPFILE + +RES=e +while [ "$RES" == "e" ]; do + Edit $TMPFILE + echo + awk '{print}/^----------/{n=n+1; if ( n == 2 ) exit 0; }' $TMPFILE + read -n 1 -p "$(Gecho "(a)bort, (c)ontinue, (s)ubmitt, (e)dit [e]: ")" RES + echo + case "${RES:-e}" in + [eE]*) + RES=e + ;; + [cCsS]) + Becho "!!! Store new $CHANGESFILE" + mv $TMPFILE $CHANGESFILE + chmod 644 $CHANGESFILE + + test "$RES" == "s" && { + if [ "$LAST_RELEASE" == "$THIS_RELEASE" ]; then + git add "$CHANGESFILE" && git commit -m "changes" + else + Becho "!!! Remember new version $THIS_RELEASE in $VERSIONFILE" + sed -i "s/^# LAST RELEASED:.*$/# LAST RELEASED: $THIS_RELEASE ($THIS_COMPAT)/" $VERSIONFILE + if git add "$CHANGESFILE" "$VERSIONFILE" \ + && git commit -m "changes $THIS_RELEASE ($THIS_COMPAT)" \ + && git tag -m "tagging $THIS_RELEASE" "$THIS_RELEASE" HEAD; then + Becho "!!!" + Becho "!!! Do not forget to push the commit and the tag: $(Gecho git push --tags origin HEAD)" + Becho "!!!" + else + Recho "!!!" + Recho "!!! Commit failed. Check manually. (git reset HEAD~)" + Recho "!!!" + exit 9 + fi + fi + } + ;; + *) + Becho "!!! Leave $CHANGESFILE untouched" + ;; + esac +done diff --git a/needreboot b/needreboot new file mode 100644 index 0000000..3f07038 --- /dev/null +++ b/needreboot @@ -0,0 +1,20 @@ +## +## This file may contain packages which will trigger the reboot-needed hint. +## So the user gets informed that the system should be rebooted after +## one of these packages was updated. +## +## This config file is for the systems administrator. +## Additional configuration files can be placed in /etc/zypp/needreboot.d +## +## For packages the intended way would be to provide 'installhint(reboot-needed)' +## if the package wants to trigger the needreboot hint. If the hint should be +## shown for packages not providing 'installhint(reboot-needed)', list them here. +## +## Format: Each line must contain either a 'PACKAGENAME' or 'provides:CAPABILITY' +## to include all packages providing a dependency match for 'CAPABILITY'. +## Lines starting with '#' and empty lines are ignored. +## +## Example: +## provides:kernel +## kernel-firmware +## diff --git a/package/libzypp-rpmlint.cmake b/package/libzypp-rpmlint.cmake new file mode 100644 index 0000000..4aa496b --- /dev/null +++ b/package/libzypp-rpmlint.cmake @@ -0,0 +1 @@ +addFilter("libzypp.* shlib-policy-name-error") diff --git a/package/libzypp.changes b/package/libzypp.changes new file mode 100644 index 0000000..2350d27 --- /dev/null +++ b/package/libzypp.changes @@ -0,0 +1,13124 @@ +------------------------------------------------------------------- +Mon Aug 5 12:04:25 CEST 2024 - ma@suse.de + +- single_rpmtrans: fix installation of .src.rpms (bsc#1228647) +- version 17.35.9 (35) + +------------------------------------------------------------------- +Fri Aug 2 12:46:50 CEST 2024 - ma@suse.de + +- Make sure not to statically linked installed tools (bsc#1228787) +- version 17.35.8 (35) + +------------------------------------------------------------------- +Thu Aug 1 17:35:44 CEST 2024 - ma@suse.de + +- MediaPluginType must be resolved to a valid MediaHandler + (bsc#1228208) +- version 17.35.7 (35) + +------------------------------------------------------------------- +Tue Jul 30 16:59:53 CEST 2024 - ma@suse.de + +- Export CredentialManager for legacy YAST versions (bsc#1228420) +- version 17.35.6 (35) + +------------------------------------------------------------------- +Tue Jul 30 15:55:38 CEST 2024 - ma@suse.de + +- Export asSolvable for YAST (bsc#1228420) +- Fix 4 typos in zypp.conf. +- version 17.35.5 (35) + +------------------------------------------------------------------- +Tue Jul 23 14:19:39 CEST 2024 - ma@suse.de + +- Fix typo in the geoip update pipeline (bsc#1228206) +- Export RepoVariablesStringReplacer for yast2 (bsc#1228138) +- version 17.35.4 (35) + +------------------------------------------------------------------- +Mon Jul 15 16:13:25 CEST 2024 - ma@suse.de + +- Translation: updated .pot file. +- Conflict with python zypp-plugin < 0.6.4 (bsc#1227793) + Older zypp-plugins reject stomp headers including a '-'. Like the + 'content-length' header we may send. +- Fix int overflow in Provider (fixes #559) + This patch fixes an issue in safe_strtonum which caused + timestamps to overflow in the Provider message parser. +- Fix error reporting on repoindex.xml parse error (bsc#1227625) +- version 17.35.3 (35) + +------------------------------------------------------------------- +Tue Jul 9 11:28:36 CEST 2024 - ma@suse.de + +- Keep UrlResolverPlugin API public (fixes #560) +- Blacklist /snap executables for 'zypper ps' (bsc#1226014) +- Fix handling of buddies when applying locks (bsc#1225267) + Buddy pairs (like -release package and product) internally share + the same status object. When applying locks from query results + the locked bit must be set if either item is locked. +- version 17.35.2 (35) + +------------------------------------------------------------------- +Tue Jul 2 12:30:20 CEST 2024 - ma@suse.de + +- Install zypp/APIConfig.h legacy include (fixes #557) +- version 17.35.1 (35) + +------------------------------------------------------------------- +Fri Jun 28 17:48:09 CEST 2024 - ma@suse.de + +- Update soname due to RepoManager refactoring and cleanup. +- version 17.35.0 (35) + +------------------------------------------------------------------- +Mon Jun 24 12:48:00 CEST 2024 - ma@suse.de + +- Workaround broken libsolv-tools-base requirements (fixes + openSUSE/zypper#551) +- Strip ssl_clientkey from repo urls (bsc#1226030) +- Remove protobuf build dependency. +- Lazily attach medium during refresh workflows (bsc#1223094) +- Refactor RepoManager and add Service workflows. +- version 17.34.2 (34) + +------------------------------------------------------------------- +Fri May 31 12:19:45 CEST 2024 - ma@suse.de + +- zypp-tui: Make sure translated texts use the correct textdomain + (fixes #551) +- Skip libproxy1 requires for tumbleweed. +- version 17.34.1 (34) + +------------------------------------------------------------------- +Tue May 14 16:17:41 UTC 2024 - Dirk Müller + +- don't require libproxy1 on tumbleweed, it is optional now + +-------------------------------------------------------------------- +Tue May 14 14:21:13 CEST 2024 - bzeller@suse.de + +- version 17.34.0 (34) +- Fix versioning scheme + +------------------------------------------------------------------ +Mon May 13 11:48:13 CEST 2024 - bzeller@suse.de + +- version 17.33.4 (35) + +------------------------------------------------------------------- +Thu May 9 13:43:39 UTC 2024 - Dirk Müller + +- add one more missing export for libyui-qt-pkg + +------------------------------------------------------------------- +Wed May 8 14:05:16 CEST 2024 - bzeller@suse.de + +- Revert eintrSafeCall behavior to setting errno to 0. +- version 17.33.3 (34) + +------------------------------------------------------------------- +Mon May 6 08:28:32 UTC 2024 - Dirk Müller + +- fix up requires_eq usage for libsolv-tools-base +- add one more missing export for PackageKit +- version 17.33.2 + +------------------------------------------------------------------- +Fri May 3 14:06:58 CEST 2024 - ma@suse.de + +- version 17.33.1 (33) + +------------------------------------------------------------------- +Fri May 3 11:31:43 UTC 2024 - Dirk Müller + +- switch to reduced size libsolv-tools-base (jsc#PED-8153) + +------------------------------------------------------------------- +Fri May 3 12:52:22 CEST 2024 - ma@suse.de + +- Fixed check for outdated repo metadata as non-root user + (bsc#1222086) +- Add ZYPP_API for exported functions and switch to + visibility=hidden (jsc#PED-8153) +- Dynamically resolve libproxy (jsc#PED-8153) +- version 17.33.0 (33) + +------------------------------------------------------------------- +Mon Apr 29 12:00:59 CEST 2024 - ma@suse.de + +- Fix download from gpgkey URL (bsc#1223430, fixes openSUSE/zypper#546) +- version 17.32.6 (32) + +------------------------------------------------------------------- +Fri Apr 19 15:58:26 CEST 2024 - ma@suse.de + +- Don't try to refresh volatile media as long as raw metadata are + present (bsc#1223094) +- version 17.32.5 (32) + +------------------------------------------------------------------- +Wed Apr 17 17:07:52 CEST 2024 - ma@suse.de + +- Fix creation of sibling cache dirs with too restrictive mode + (bsc#1222398) + Some install workflows in YAST may lead to too restrictive (0700) + raw cache directories in case of newly created repos. Later + commands running with user privileges may not be able to access + these repos. +- version 17.32.4 (32) + +------------------------------------------------------------------- +Thu Apr 11 16:10:46 CEST 2024 - ma@suse.de + +- Update RepoStatus fromCookieFile according to the files mtime + (bsc#1222086) +- TmpFile: Don't call chmod if makeSibling failed. +- version 17.32.3 (32) + +------------------------------------------------------------------- +Tue Apr 2 16:08:58 CEST 2024 - ma@suse.de + +- Fixup New VendorSupportOption flag VendorSupportSuperseded + (jsc#OBS-301, jsc#PED-8014) + Fixed the name of the keyword to "support_superseded" as it was + agreed on in jsc#OBS-301. +- version 17.32.2 (32) + +------------------------------------------------------------------- +Thu Mar 28 17:56:04 CET 2024 - ma@suse.de + +- Add resolver option 'removeUnneeded' to file weak remove jobs + for unneeded packages (bsc#1175678) +- version 17.32.1 (32) + +------------------------------------------------------------------- +Fri Mar 22 18:16:32 CET 2024 - ma@suse.de + +- Add resolver option 'removeOrphaned' for distupgrade + (bsc#1221525) +- New VendorSupportOption flag VendorSupportSuperseded + (jsc#OBS-301, jsc#PED-8014) +- Tests: fix vsftpd.conf where SUSE and Fedora use different + defaults (fixes #522) +- Add default stripe minimum (#529) +- Don't expose std::optional where YAST/PK explicitly use c++11. +- Digest: Avoid using the deprecated OPENSSL_config. +- version 17.32.0 (32) + +------------------------------------------------------------------- +Tue Feb 20 17:30:42 CET 2024 - ma@suse.de + +- ProblemSolution::skipsPatchesOnly overload to handout the + patches. +- Remove https->http redirection exceptions for + download.opensuse.org. +- version 17.31.32 (22) + +------------------------------------------------------------------- +Wed Feb 7 10:25:39 CET 2024 - ma@suse.de + +- tui: allow to access the underlying ostream of out::Info. +- Add MLSep: Helper to produce not-NL-terminated multi line + output. +- version 17.31.31 (22) + +------------------------------------------------------------------- +Tue Feb 6 10:36:24 CET 2024 - ma@suse.de + +- applydeltaprm: Create target directory if it does not exist + (bsc#1219442) +- Add ProblemSolution::skipsPatchesOnly (for openSUSE/zypper#514) +- Fix problems with EINTR in ExternalDataSource::getline (fixes + bsc#1215698) +- version 17.31.30 (22) + +------------------------------------------------------------------- +Tue Jan 23 16:10:26 CET 2024 - ma@suse.de + +- CheckAccessDeleted: fix running_in_container detection + (bsc#1218782) +- Detect CURLOPT_REDIR_PROTOCOLS_STR availability at runtime + (bsc#1218831) +- Make Wakeup class EINTR safe. +- Add a way to cancel media operations on shutdown + (openSUSE/zypper#522) + This patch adds a mechanism to signal libzypp that a shutdown was + requested, usually when CTRL+C was pressed by the user. Currently + only the media backend will utilize this, but can be extended to + all code paths that use g_poll() to wait for events. +- Manually poll fds for curl in MediaCurl. + Using curl_easy_perform does not give us the required control on + when we want to cancel a download. Switching to the MultiCurl + implementation with a external poll() event loop will give us + much more freedom and helps us to improve our Ctrl+C handling. +- Move reusable curl poll code to curlhelper.h. +- version 17.31.29 (22) + +------------------------------------------------------------------- +Tue Jan 9 15:38:42 CET 2024 - ma@suse.de + +- Fix to build with libxml 2.12.x (fixes #505) +- version 17.31.28 (22) + +------------------------------------------------------------------- +Fri Dec 22 17:12:31 CET 2023 - ma@suse.de + +- CheckAccessDeleted: fix 'running in container' filter + (bsc#1218291) +- version 17.31.27 (22) + +------------------------------------------------------------------- +Thu Dec 21 18:14:32 CET 2023 - ma@suse.de + +- Call zypp commit plugins during transactional update (fixes #506) +- Add support for loongarch64 (fixes #504) +- Teach MediaMultiCurl to download HTTP Multibyte ranges. +- Teach zsync downloads to MultiCurl. +- Expand RepoVars in URLs downloading a .repo file (bsc#1212160) + Convenient and helps documentation as it may refer to a single + command for a bunch of distributions. Like e.g. "zypper ar + 'https://server.my/$releasever/my.repo'". +- version 17.31.26 (22) + +------------------------------------------------------------------- +Thu Dec 14 11:09:24 CET 2023 - ma@suse.de + +- Fix build issue with zchunk build flags (fixes #500) +- version 17.31.25 (22) + +------------------------------------------------------------------- +Thu Dec 14 10:48:01 CET 2023 - ma@suse.de + +- Open rpmdb just once during execution of %posttrans scripts + (bsc#1216412) +- Avoid using select() since it does not support fd numbers > + 1024 (fixes #447) +- tools/DownloadFiles: use standard zypp progress bar (fixes #489) +- Revert "Color download progress bar" (fixes #475) + Cyan is already used for the output of RPM scriptlets. Avoid this + colorific collision between download progress bar and scriptlet + output. +- Fix ProgressBar's calculation of the printed tag position (fixes #494) +- Switch zypp::Digest to Openssl 3.0 Provider API (fixes #144) +- Fix usage of deprecated CURL features (fixes #486) +- version 17.31.24 (22) + +------------------------------------------------------------------- +Wed Oct 25 16:03:51 CEST 2023 - ma@suse.de + +- Stop using boost version 1 timer library (fixes #489, + bsc#1215294) +- version 17.31.23 (22) + +------------------------------------------------------------------- +Thu Oct 12 14:26:36 CEST 2023 - ma@suse.de + +- Preliminary disable 'rpm --runposttrans' usage for chrooted + systems (bsc#1216091) + This limits the %transfiletrigger(postun|in) support in the + default installer if --root is used (as described in bsc#1041742). + The chrooted execution of the scripts in 'rpm --runposttrans' + broke in rpm-4.18. It's expected to be fixed in rpm-4.19. + Then we'll enable the feature again. +- fix comment typo on zypp.conf (boo#1215979) +- version 17.31.22 (22) + +------------------------------------------------------------------- +Thu Sep 21 14:54:42 CEST 2023 - ma@suse.de + +- Attempt to delay %transfiletrigger(postun|in) execution if rpm + supports it (bsc#1041742) + Decide during installation whether rpm is capable of delayed + %posttrans %transfiletrigger(postun|in) execution or whether we + can just handle the packages %posttrans. On TW a delayed + %transfiletrigger handling is possible since rpm-4.17. +- Make sure the old target is deleted before a new one is created + (bsc#1203760) +- version 17.31.21 (22) + +------------------------------------------------------------------- +Thu Aug 24 15:33:45 CEST 2023 - ma@suse.de + +- Fixup changes for 17.31.16. Remove faulty reference to a bug + actually fixed in 2019. +- version 17.31.20 (22) + +------------------------------------------------------------------- +Wed Aug 16 16:54:34 CEST 2023 - ma@suse.de + +- Fix zypp-tui/output/Out.h to build with clang. +- Fix zypp/Arch.h for clang (fixes #478) + Clang seems to have issues with picking the overload in + std::men_fn if there is a static overload of a member function. + We need to explicitely specify the correct type of the function + pointer. To make sure this would not break compiling a + application with clang that builds against libzypp this patch + works around the problem. +- version 17.31.19 (22) + +------------------------------------------------------------------- +Fri Aug 4 17:40:19 CEST 2023 - ma@suse.de + +- SINGLE_RPMTRANS: Respect ZYPP_READONLY_HACK when checking the + zypp-rpm lock (fixes openSUSE/openSUSE-repos#29) +- version 17.31.18 (22) + +------------------------------------------------------------------- +Fri Jul 28 12:26:54 CEST 2023 - ma@suse.de + +- Fix wrong filesize exceeded dl abort in zyppng::Downloader + (bsc#1213673) + In some cases when downloading very small files we can run into + issues when the URL is protected by credentials. +- version 17.31.17 (22) + +------------------------------------------------------------------- +Mon Jul 24 16:58:18 CEST 2023 - ma@suse.de + +- Fix negative ZYPP_LOCK_TIMEOUT not waiting forever (bsc#1213231) +- Don't cleanup orphaned dirs if read-only mode was promised + (bsc#1210740) +- version 17.31.16 (22) + +------------------------------------------------------------------- +Wed Jun 28 12:34:18 CEST 2023 - ma@suse.de + +- Fix build against protobuf >= 22 (fixes #465, closes #466) + Port away from protobuf_generate_cpp. Upstream protobuf does not + export protobuf_generate_cpp by default anymore. + Use protobuf_generate instead, which is also available on older + versions. +- Remove SUSE < SLE11 constructs (fixes #464). +- version 17.31.15 (22) + +------------------------------------------------------------------- +Thu Jun 15 12:00:07 CEST 2023 - ma@suse.de + +- build: honor libproxy.pc's includedir (bsc#1212222) +- Curl: trim all custom headers (bsc#1212187) + HTTP/2 RFC 9113 forbids fields ending with a space. So we make + sure all custom headers are trimmed. This also includes headers + returned by URL-Resolver plugins. +- version 17.31.14 (22) + +------------------------------------------------------------------- +Mon Jun 12 16:37:13 CEST 2023 - ma@suse.de + +- curl: Trim user agent string (bsc#1212187) + HTTP/2 RFC 9113 forbids fields ending with a space. Violation + results in curl error: 92: HTTP/2 PROTOCOL_ERROR. +- version 17.31.13 (22) + +------------------------------------------------------------------- +Mon Jun 5 12:15:55 CEST 2023 - ma@suse.de + +- Do not unconditionally release a medium if provideFile failed + (bsc#1211661) +- libzypp.spec.cmake: remove duplicate file listing. +- version 17.31.12 (22) + +------------------------------------------------------------------- +Fri Apr 28 13:40:07 CEST 2023 - ma@suse.de + +- MediaCurl: Fix endless loop if wrong credentials are stored in + credentials.cat (bsc#1210870) + Since libzypp-17.31.7 wrong credentials stored in credentials.cat + may lead to an endless loop. Rather than asking for the right + credentials, the stored ones are used again and again. +- zypp.conf: Introduce 'download.connect_timeout' [60 sec.] + (bsc#1208329) + Maximum time in seconds that you allow the connection phase to + the server to take. This only limits the connection phase, it has + no impact once it has connected. (see also CURLOPT_CONNECTTIMEOUT) +- commit: Try to provide /dev fs if not present (fixes #444) +- fix build with boost 1.82. +- version 17.31.11 (22) + +------------------------------------------------------------------- +Mon Apr 24 08:30:44 CEST 2023 - aschnell@suse.com + +- fix build with boost 1.82 + +------------------------------------------------------------------- +Thu Apr 13 16:48:40 CEST 2023 - ma@suse.de + +- BuildRequires: libsolv-devel >= 0.7.24 for x86_64_v[234] + support. +- version 17.31.10 (22) + +------------------------------------------------------------------- +Fri Mar 31 18:35:00 CEST 2023 - ma@suse.de + +- Workround bsc#1195633 while libsolv <= 0.7.23 is used. +- Fix potential endless loop in new ZYPP_MEDIANETWORK. +- ZYPP_METALINK_DEBUG=1: Log URL and priority of the mirrors + parsed from a metalink file. +- multicurl: propagate ssl settings stored in repo url + (boo#1127591) + Closes #335. +- Teach MediaNetwork to retry on HTTP2 errors. +- fix CapDetail to return Rel::NONE if an EXPRESSION is used as a + NAMED cap. +- Capability: support parsing richdeps from string. +- defaultLoadSystem: default to LS_NOREFRESH if not root. +- Detect x86_64_v[234]: Fix LZCNT bit used in detection (fixes + #439) + Merges rpm-software-management/rpm#2412: The bit for LZCNT is in + CPUID 0x80000001, not 1. +- Detect x86_64_v[234] architecture levels (fixes #439) +- Support x86_64_v[234] architecture levels (for #439) +- version 17.31.9 (22) + +------------------------------------------------------------------- +Mon Feb 13 16:48:56 CET 2023 - ma@suse.de + +- ProgressData: enforce reporting the INIT||END state + (bsc#1206949) +- ps: fix service detection on newer Tumbleweed systems + (bsc#1205636) +- version 17.31.8 (22) + +------------------------------------------------------------------- +Sat Dec 24 02:22:11 CET 2022 - ma@suse.de + +- Hint to "zypper removeptf" to remove PTFs. +- Removing a PTF without enabled repos should always fail + (bsc#1203248) + Without enabled repos, the dependent PTF-packages would be + removed (not replaced!) as well. To remove a PTF "zypper install + -- -PTF" or a dedicated "zypper removeptf PTF" should be used. + This will update the installed PTF packages to theit latest + version. +- version 17.31.7 (22) + +------------------------------------------------------------------- +Fri Nov 25 13:41:55 CET 2022 - ma@suse.de + +- Avoid calling getsockopt when we know the info already. + This patch hopefully fixes logging on WSL, getsockopt seems to + not be fully supported but the code required it when accepting + new socket connections. (for bsc#1178233) +- Enhance yaml-cpp detection (fixes #428) +- No need to redirect 'history.logfile=/dev/null' into the target. +- MultiCurl: Make sure to reset the progress function when + falling back. +- version 17.31.6 (22) + +------------------------------------------------------------------- +Mon Nov 7 13:09:46 CET 2022 - ma@suse.de + +- Create '.no_auto_prune' in the package cache dir to prevent auto + cleanup of orphaned repositories (bsc#1204956) +- properly reset range requests (bsc#1204548) +- version 17.31.5 (22) + +------------------------------------------------------------------- +Mon Oct 17 12:53:40 CEST 2022 - ma@suse.de + +- Do not clean up MediaSetAccess before using the geoip file + (fixes #424) +- version 17.31.4 (22) + +------------------------------------------------------------------- +Fri Oct 14 14:09:51 CEST 2022 - ma@suse.de + +- Improve download of optional files (fixes #416) +- Do not use geoip rewrites if the repo has explicit country + settings. +- Implement geoIP feature for zypp. + This patch adds a feature to rewrite request URLs to the repo + servers by querying a geoIP file from download.opensuse.org. This + file can return a redirection target depending on the clients IP + adress, this way we can directly contact a local mirror of d.o.o + instead. The redir target stays valid for 24hrs. + This feature can be disabled in zypp.conf by setting + 'download.use_geoip_mirror = false'. +- Use a dynamic fallback for BLKSIZE in downloads. + When not receiving a blocklist via metalink file from the server + MediaMultiCurl used to fallback to a fixed, relatively small + BLKSIZE. This patch changes the fallback into a dynamic value + based on the filesize using a similar metric as the MirrorCache + implementation on the server side. +- Skip media.1/media download for http repo status calc. + This patch allows zypp to skip a extra media.1/media download to + calculate if a repository needs to be refreshed. This + optimisation only takes place if the repo does specify only + downloading base urls. +- version 17.31.3 (22) + +------------------------------------------------------------------- +Wed Oct 5 18:02:15 CEST 2022 - ma@suse.de + +- Resolver: Fix missing --[no]-recommends initialization in + update (fixes #openSUSE/zypper#459, bsc#1201972) +- Log ONLY_NAMESPACE_RECOMMENDED because this is what corresponds + to --[no]-recommends. +- version 17.31.2 (22) + +------------------------------------------------------------------- +Fri Sep 2 16:38:42 CEST 2022 - ma@suse.de + +- UsrEtc: Store logrotate files in %{_distconfdir} if defined + (fixes #402) +- Log backtrace on SIGABRT too. +- Need to explicitly enable building experimental code. Otherwise + an old Notcurses++ package which happens to be present in the + buildenv breaks the build (fixes #412). +- Work around libyui/libyui#78 on code 15.4 and older. +- Stop using std::*ary_function; deprecated and removed in c++17. +- Don't expose header files which use types not available in + c++11. In 15.3 and older, YAST and PK compile with -std=c++11. +- Remove no longer needed %post code (bsc#1203649) +- Enable zck support for SLE15-SP4 and newer. On Leap it is enabled + since 15.1 (bsc#1189282) +- version 17.31.1 (22) + +------------------------------------------------------------------- +Tue Jul 19 16:03:01 CEST 2022 - ma@suse.de + +- Add PoolItem::statusReinit to reset the status it's initial + state in the ResPool (might help bsc#1199895) + This may either be 'KEEP_STATE bySOLVER' or 'LOCKED byUSER' if + the PoolItem matched a hard lock defined in /etc/zypp/locks. +- Fix building with GCC 13 on i586 (fixes #407, fixes #396) +- Be prepared to receive exceptions from curl_easy_cleanup + (bsc#1201092) +- Don't auto-flag kernel-firmware as 'reboot-needed' (bsc#1200993) +- Remove Medianetwork and dependend code. + This commit removes the MediaNetwork tech preview and all related + code. First reason for this is that MediaNetwork was just meant + as a way to test the new CURL based downloader and second: since + the Provide API is going to completely replace the current media + backend it would be extra work to ensure that changes on the + Downloader do not break MediaNetwork. +- version 17.31.0 (22) + +------------------------------------------------------------------- +Tue Jul 5 10:29:19 CEST 2022 - ma@suse.de + +- Fix building with GCC 12.x release (#396) +- version 17.30.3 (22) + +------------------------------------------------------------------- +Wed Jun 15 12:07:22 CEST 2022 - ma@suse.de + +- appdata plugin: Pass path to the repodata/ directory inside the + cache (bsc#1197684) +- zypp-rpm: flush rpm script output buffer before sending + endOfScriptTag. +- version 17.30.2 (22) + +------------------------------------------------------------------- +Mon May 30 14:37:57 CEST 2022 - ma@suse.de + +- PluginRepoverification: initial version hooked into + repo::Downloader and repo refresh. +- Immediately start monitoring the download.transfer_timeout. + Do not wait until the first data arrived. (bsc#1199042) +- singletrans: no dry-run commit if doing just download-only. +- Work around cases where sat repo.start points to an invalid + solvable. May happen if (wrong arch) solvables were removed + at the beginning of the repo. +- fix misplaced #endif SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER + (fixes #388) +- version 17.30.1 (22) + +------------------------------------------------------------------- +Fri Mar 25 17:08:46 CET 2022 - ma@suse.de + +- ZConfig: Update solver settings if target changes (bsc#1196368) +- version 17.30.0 (22) + +------------------------------------------------------------------- +Mon Mar 21 09:04:36 CET 2022 - ma@suse.de + +- Fix possible hang in singletrans mode (bsc#1197134) +- Do 2 retries if mount is still busy. +- version 17.29.7 (22) + +------------------------------------------------------------------- +Mon Mar 14 15:40:04 CET 2022 - ma@suse.de + +- Fix package signature check (bsc#1184501) + Pay attention that header and payload are secured by a valid + signature and report more detailed which signature is missing. +- Retry umount if device is busy (bsc#1196061, closes #381) + A previously released ISO image may need a bit more time to + release it's loop device. So we wait a bit and retry. +- Fix serializing/deserializing type mismatch in zypp-rpm + protocol (bsc#1196925) +- Fix handling of ISO media in releaseAll (bsc#1196061) +- Hint on common ptf resolver conflicts (bsc#1194848) +- version 17.29.6 (22) + +------------------------------------------------------------------- +Thu Feb 24 13:47:26 CET 2022 - ma@suse.de + +- Hint on ptf<>patch resolver conflicts (bsc#1194848) +- version 17.29.5 (22) + +------------------------------------------------------------------- +Tue Feb 8 10:52:48 CET 2022 - ma@suse.de + +- Fix handling of redirected command in-/output (bsc#1195326) + This fixes delays at the end of zypper operations, where + zypper unintentionally waits for appdata plugin scripts to + complete. +- version 17.29.4 (22) + +------------------------------------------------------------------- +Tue Feb 1 18:49:00 CET 2022 - ma@suse.de + +- Public header files on older distros must use c++11 + (bsc#1194597) +- Fix exception handling when reading or writing credentials + (bsc#1194898) +- version 17.29.3 (22) + +------------------------------------------------------------------- +Thu Jan 20 17:29:52 CET 2022 - ma@suse.de + +- Fix Legacy include (bsc#1194597) +- version 17.29.2 (22) + +------------------------------------------------------------------- +Mon Jan 10 13:02:11 CET 2022 - ma@suse.de + +- Fix broken install path for parser compat headers (fixes #372, + bsc#1194597) +- RepoManager: remember exec errors in exception history + (bsc#1193007) +- version 17.29.1 (22) + +------------------------------------------------------------------- +Thu Dec 23 16:01:31 CET 2021 - ma@suse.de + +- Use the default zypp.conf settings if no zypp.conf exists + (bsc#1193488) +- Fix wrong encoding of iso: URL components (bsc#954813) +- Handle armv8l as armv7hl compatible userland. +- Introduce zypp-curl a sublibrary for CURL related code. +- zypp-rpm: Increase rpm loglevel if ZYPP_RPM_DEBUG is set. +- Save all signatures associated with a public key in its + PublicKeyData. +- version 17.29.0 (22) + +------------------------------------------------------------------- +Thu Nov 11 15:12:44 CET 2021 - ma@suse.de + +- Disable logger in the child after fork (bsc#1192436) +- version 17.28.8 (22) + +------------------------------------------------------------------- +Thu Nov 4 15:16:29 CET 2021 - ma@suse.de + +- Check log writer before accessing it (fixes #355, bsc#1192337) +- Save locks: Update an existing locks changed comment string. +- Allow uname-r format in purge kernels keepspec (fixes + openSUSE/zypper#418) +- version 17.28.7 (22) + +------------------------------------------------------------------- +Mon Oct 18 12:02:57 CEST 2021 - ma@suse.de + +- Zypper should keep cached files if transaction is aborted + (bsc#1190356) + Singletrans mode currently does not keep files around if the + transaction is aborted. This patch fixes the problem. +- Require a minimum number of mirrors for multicurl (bsc#1191609) +- Use procfs to detect nr of open fd's if rlimit is too high + (bsc#1191324) + Especially in a VM iterating over all possible fd's to close open + ones right before a exec() slows down zypper unnecessarily. This + patch uses /proc/self/fd to iterate over open fd's in case rlimit + is above 1024. +- po: Fix some lost '%' signs in positional args (bsc#1191370) +- RepoManager: Don't probe for plaindir repo if URL schema is + plugin: (bsc#1191286) +- version 17.28.6 (22) + +------------------------------------------------------------------- +Mon Oct 4 12:46:46 CEST 2021 - ma@suse.de + +- Downloader does not respect checkExistsOnly flag (bsc#1190712) + A missing check causes zyppng::Downloader to always download full + files even if the checkExistsOnly flag is set. This patch adds + the missing logic. +- Fix kernel-*-livepatch removal in purge-kernels (bsc#1190815) + The kernel-*-livepatch packages are supposed to serve as a stable + handle for the ephemeral kernel livepatch packages. See + FATE#320268 for details. As part of the kernel live patching + ecosystem, kernel-*-livepatch packages should not block the + purge-kernels step. +- version 17.28.5 (22) + +------------------------------------------------------------------- +Fri Sep 17 10:41:56 CEST 2021 - ma@suse.de + +- Make sure to keep states alives while transitioning + (bsc#1190199) +- May set techpreview variables for testing in /etc/zypp/zypp.conf. + If environment variables are unhandy one may enable the desired + techpreview in zypp.conf as well: + [main] + techpreview.ZYPP_SINGLE_RPMTRANS=1 + techpreview.ZYPP_MEDIANETWORK=1 +- version 17.28.4 (22) + +------------------------------------------------------------------- +Fri Sep 3 14:34:19 CEST 2021 - ma@suse.de + +- CMake/spec: Add option to force SINGLE_RPMTRANS as default for + zypper (fixes #340) +- Make sure singleTrans is zypper-only for now. +- Do not double check signatures and keys (bsc#1190059) +- version 17.28.3 (22) + +------------------------------------------------------------------- +Tue Aug 31 10:49:51 CEST 2021 - ma@suse.de + +- Workaround Bug 1189788: Don't allow ZYPP_SINGLE_RPMTRANS=1 on a + not UsrMerged Tumbleweed system. +- version 17.28.2 (22) + +------------------------------------------------------------------- +Mon Aug 23 08:39:15 CEST 2021 - ma@suse.de + +- Fix crashes in logging code when shutting down (bsc#1189031) +- version 17.28.1 (22) + +------------------------------------------------------------------- +Mon Jul 26 11:48:28 CEST 2021 - ma@suse.de + +- Rephrase vendor conflict message in case 2 packages are + involved (bsc#1187760) + This covers the case where not the packages itself would change + its vendor, but replaces a package from a different vendor. +- Fix solver jobs for PTFs (bsc#1186503) +- spec: switch to pkgconfig(openssl) +- Show key fpr from signature when signature check fails + (bsc#1187224) + Rpm by default only shows the short key ID when checking the + signature of a package fails. This patch reads the signatures + from the RPM headers and replaces she short IDs with the key + fingerprints fetched from the signatures. +- Implement alternative single transaction commit strategy. + This patch adds a experimental commit strategy that runs all + operations in a single rpm transaction, speeding up the execution + a lot. +- Use ZYPP_MEDIANETWORK=1 to enable the experimental new media + backend. +- Implement zchunk download, refactor Downloader backend. +- Fix purge-kernels fails with kernels from Kernel:HEAD + (bsc#1187738) + There recently was a change in the kernel package naming scheme + in regards to rc kernels. Since kernel upstream uses characters + in the version that are not allowed in rpm versions a "-rc" was + previously replaced with ".rc" which broke sorting by version, to + fix this issue it was replaced with "~rc", which unfortunately + broke the purge-kernels logic. This patch makes sure purge-kernel + does apply the same conversion. +- version 17.28.0 (22) + +------------------------------------------------------------------- +Thu Jun 10 17:34:14 CEST 2021 - ma@suse.de + +- Enhance XML output of repo GPG options (fixes openSUSE/zypper#390) + In addition to the effective values, add optional attributes + showing the raw values actually present in the .repo file. + (raw_gpgcheck, raw_repo_gpgcheck, raw_pkg_gpgcheck) +- Link all executables with -pie (bsc#1186447) +- Ship an empty /etc/zypp/needreboot per default (fixes #311, jsc#PM-2645) + If packages want to trigger the reboot-needed hiint upon installation + they may provide 'installhint(reboot-needed)'. + Builtin packages triggering the hint without the provides are + only kernel and kernel-firmware related. +- Add Solvable::isBlacklisted as superset of retracted and ptf + packages (bsc#1186503) +- Fix segv if ZYPP_FULLOG is set (fixes #317) +- version 17.27.0 (22) + +------------------------------------------------------------------- +Tue Jun 1 19:10:35 CEST 2021 - ma@suse.de + +- Work around download.o.o broken https redirects. +- Allow trusted repos to add additional signing keys (bsc#1184326) + Repositories signed with a trusted gpg key may import additional + package signing keys. This is needed if different keys were used + to sign the the packages shipped by the repository. +- MediaCurl: Fix logging of redirects. +- Use 15.3 resolver problem and solution texts on all distros. +- $ZYPP_LOCK_TIMEOUT: Let negative values wait forever for the + zypp lock (bsc#1184399) + Helps boot time services like 'zypper purge-kernels' to wait for + the zypp lock until other services using zypper have completed. +- Fix purge-kernels is broken in Leap 15.3 (bsc#1185325) + Leap 15.3 introduces a new kernel package called + kernel-flavour-extra, which contain kmp's. Currently kmp's are + detected by name ".*-kmp(-.*)?" but this does not work which + those new packages. This patch fixes the problem by checking + packages for kmod(*) and ksym(*) provides and only falls back to + name checking if the package in question does not provide one of + those. +- Introduce zypp-runpurge, a tool to run purge-kernels on + testcases. +- version 17.26.0 (22) + +------------------------------------------------------------------- +Wed Apr 28 15:34:01 CEST 2021 - ma@suse.de + +- Properly handle permission denied when providing optional files + (bsc#1185239) +- Fix service detection with cgroupv2 (bsc#1184997) +- version 17.25.10 (22) + +------------------------------------------------------------------- +Thu Apr 22 15:52:19 CEST 2021 - ma@suse.de + +- Add missing includes for GCC 11 (bsc#1181874) +- Fix unsafe usage of static in media verifier. +- Solver: Avoid segfault if no system is loaded (bsc#1183628) +- MediaVerifier: Relax media set verification in case of a single + not-volatile medium (bsc#1180851) +- Do no cleanup in custom cache dirs (bsc#1182936) +- ZConfig: let pubkeyCachePath follow repoCachePath. +- version 17.25.9 (22) + +------------------------------------------------------------------- +Wed Feb 24 17:07:52 CET 2021 - ma@suse.de + +- Try to provide a mounted /proc in --root installs (bsc#1181328) + Some systemd tools require /proc to be mounted and fail if it's + not there. +- Enable release packages to request a releaxed suse/opensuse + vendorcheck in dup when migrating. (bsc#1182629) +- version 17.25.8 (22) + +------------------------------------------------------------------- +Wed Feb 17 09:06:49 CET 2021 - ma@suse.de + +- Patch: Identify well-known category names (bsc#1179847) + This allows to use the RH and SUSE patch categrory names + synonymously: + (recommendedi = bugfix) and (optional = feature = enhancement). +- Add missing includes for GCC 11 compatibility. (bsc#1181874) +- Fix %posttrans script execution (fixes #265) + The scripts are execuable. No need to call them through 'sh -c'. +- Commit: Fix rpmdb compat symlink in case rpm got removed. +- Repo: Allow multiple baseurls specified on one line (fixes #285) +- Regex: Fix memory leak and undefined behavior. +- Add rpm buildrequires for test suite (fixes #279) +- Use rpmdb2solv new -D switch to tell the location ob the + rpmdatabase to use. +- BuildRequires: libsolv-devel >= 0.7.17. +- version 17.25.7 (22) + +------------------------------------------------------------------- +Tue Jan 12 19:34:03 CET 2021 - ma@suse.de + +- Rephrase solver problem descriptions (jsc#SLE-8482) +- Adapt to changed gpg2/libgpgme behavior (bsc#1180721) +- Multicurl backend breaks with with unknown filesize (fixes #277) +- version 17.25.6 (22) + +------------------------------------------------------------------- +Fri Dec 11 16:52:54 CET 2020 - ma@suse.de + +- Fix lsof monitoring (bsc#1179909) +- version 17.25.5 (22) + +------------------------------------------------------------------- +Thu Dec 3 17:06:35 CET 2020 - ma@suse.de + +- Prevent librpmDb iterator from accidentally creating an empty + rpmdb in / (repoened bsc#1178910) +- Fix update of gpg keys with elongated expire date (bsc#1179222) +- needreboot: remove udev from the list (bsc#1179083) +- Prefer /run over /var/run. +- version 17.25.4 (22) + +------------------------------------------------------------------- +Fri Nov 27 10:17:50 CET 2020 - ma@suse.de + +- RepoManager: Carefully tidy up the caches. Remove non-directory + entries. (bsc#1178966) +- RpmDb: If no database exists use the _dbpath configured in rpm. + Still makes sure a compat symlink at /var/lib/rpm exists in case + the configures _dbpath is elsewhere. (bsc#1178910) +- Url: Hide known password entries when writing the query part + (bsc#1050625 bsc#1177583, CVE-2017-9271) +- adapt testcase to change introduced by libsolv#402. +- RepoManager: Force refresh if repo url has changed (bsc#1174016) +- RepoInfo: ignore legacy type= in a .repo file and let RepoManager + probe (bsc#1177427, Fixes openSUSE/zypper#357). +- version 17.25.3 (22) + +------------------------------------------------------------------- +Wed Oct 7 12:05:33 CEST 2020 - ma@suse.de + +- Bump version to force rebuild against a fixed libsolv. + (bsc#1177238, bsc#1177275) +- version 17.25.2 (22) + +------------------------------------------------------------------- +Fri Sep 25 13:39:38 CEST 2020 - ma@suse.de + +- Fix bsc#1176902: When kernel-rt has been installed, the + purge-kernels service fails during boot. +- Use package name provides as group key in purge-kernel + (bsc#1176740 bsc#1176192) + kernel-default-base has new packaging, where the kernel uname -r + does not reflect the full package version anymore. This patch + adds additional logic to use the most generic/shortest edition + each package provides with %{packagename}= to group the + kernel packages instead of the rpm versions. + This also changes how the keep-spec for specific versions is + applied, instead of matching the package versions, each of the + package name provides will be matched. +- version 17.25.1 (22) + +------------------------------------------------------------------- +Fri Sep 18 16:45:49 CEST 2020 - ma@suse.de + +- RepoInfo: Return the type of the local metadata cache as + fallback (bsc#1176435) +- VendorAttr: Fix broken "suse,opensuse" equivalence handling. + Enhance API and testcases. (bsc#1174918) +- Update docs regarding 'opensuse' namepace matching. +- New solver testcase format. +- Link against libzsd to close libsolvs open references + (as we link statically) +- BuildRequires: libsolv-devel >= 0.7.15. +- version 17.25.0 (22) + +------------------------------------------------------------------- +Fri Aug 28 17:09:59 CEST 2020 - ma@suse.de + +- VendorAttr: Const-correct API and let Target provide its + settings (bsc#1174918) +- Support buildnr with commit hash in purge-kernels (bsc#1175342) + This adds special behaviour for when a kernel version has the + rebuild counter before the kernel commit hash. +- Improve Italian traslation of the "breaking dependencies" + message (bsc#1173529) +- Make sure reading from lsof does not block forever (bsc#1174240) +- Just collect details for the signatures found (fixes #229) +- version 17.24.2 (22) + +------------------------------------------------------------------- +Thu Jul 16 18:04:18 CEST 2020 - ma@suse.de + +- Fix bsc#1174011 auth=basic ignored in some cases (bsc#1174011) + Proactively send credentials if the URL specifes '?auth=basic' + and a username. +- ZYPP_MEDIA_CURL_DEBUG: Strip credentials in header log (bsc#1174011) +- version 17.24.1 (22) + +------------------------------------------------------------------- +Tue Jul 14 13:19:56 CEST 2020 - ma@suse.de + +- Completey rework the purge-kernels algorithm (fix bsc#1173106) + The new code is closer to the original perl script, grouping the + packages by name before applying the keep spec. +- Set ZYPP_RPM_DEBUG=1 to capture verbose rpm command output + (implements #228) +- version 17.24.0 (22) + +------------------------------------------------------------------- +Fri Jun 26 14:13:10 CEST 2020 - ma@suse.de + +- Fix core dump with corrupted history file (bsc#1170801) +- version 17.23.8 (22) + +------------------------------------------------------------------- +Tue Jun 23 17:44:21 CEST 2020 - ma@suse.de + +- Enable zchunk metadata download if libsolv supports it. +- version 17.23.7 (22) + +------------------------------------------------------------------- +Thu Jun 4 11:45:03 CEST 2020 - ma@suse.de + +- Revert "Enable zchunk on SLE-15-SP2". +- version 17.23.6 (22) + +------------------------------------------------------------------- +Wed May 27 18:50:32 CEST 2020 - ma@suse.de + +- Enable zchunk on SLE-15-SP2. +- Older kernel-devel packages are not properly purged (bsc#1171224) +- doc: enhance service plugin example. +- version 17.23.5 (22) + +------------------------------------------------------------------- +Thu Apr 9 12:52:10 CEST 2020 - ma@suse.de + +- Get retracted patch status from updateinfo data (jsc#SLE-8770) + libsolv injects the indicator provides into packages only. +- remove 'using namespace std;' (bsc#1166610, fixes #218) +- Online doc: add 'Hardware (modalias) dependencies' page + (fixes #216) +- version 17.23.4 (22) + +------------------------------------------------------------------- +Wed Mar 25 15:26:14 CET 2020 - ma@suse.de + +- Add HistoryLogReader actionFilter to parse only specific + HistoryActionIDs. +- version 17.23.3 (22) + +------------------------------------------------------------------- +Fri Mar 20 12:28:18 CET 2020 - ma@suse.de + +- RepoVariables: Add safe guard in case the caller does not own a + zypp instance. +- Enable c++17. Define libyzpp CXX_STANDARD in ZyppCommon.cmake. +- version 17.23.2 (22) + +------------------------------------------------------------------- +Mon Mar 2 19:53:51 CET 2020 - ma@suse.de + +- Fix package status computation regarding unneeded, orphaned, recommended + and suggested packages (broken in 17.23.0) (bsc#1165476) +- version 17.23.1 (22) + +------------------------------------------------------------------- +Fri Feb 21 16:06:57 CET 2020 - ma@suse.de + +- Log patch status changes to history (jsc#SLE-5116) +- Allow to disable all WebServer dependent tests when building. OBS + wants to be able to get rid of the nginx/FastCGI-devel build + requirement. Use 'rpmbuild --without mediabackend_tests' or + 'cmake -DDISABLE_MEDIABACKEND_TESTS=1'. +- version 17.23.0 (22) + +------------------------------------------------------------------- +Fri Feb 7 14:56:40 CET 2020 - ma@suse.de + +- update translations +- Replace mongoose/webrick with nginx in test suite. + This patch makes use of nginx to replace the current WebServer + mongoose implementation. Also adds support for registering + callback functions for certain URL requests via FCGI, making it + possible to mock HTTP responses and test more complex HTTP setups. +- boost: Fix deprecated auto_unit_test.hpp includes. +- Disable zchunk on Leap-15.0 and SLE15-* while there is no libzck. +- Fix decision whether to download ZCHUNK files. + libzypp and libsolv must both be able to read the format. +- version 17.22.1 (22) + +------------------------------------------------------------------- +Thu Jan 23 16:30:19 CET 2020 - ma@suse.de + +- yum::Downloader: Prefer zchunk compressed metadata if libvsolv + supports it. +- BuildRequires: libsolv-devel >= 0.7.11. +- version 17.22.0 (22) + +------------------------------------------------------------------- +Mon Jan 20 12:53:12 CET 2020 - ma@suse.de + +- Selectable: Fix highestAvailableVersionObj if only retracted + packages are available. Avoid using retracted items as candidate + (jsc#SLE-8770) +- version 17.21.0 (20) + +------------------------------------------------------------------- +Thu Dec 19 13:28:00 CET 2019 - ma@suse.de + +- BuildRequires: libsolv-devel >= 0.7.10. +- RpmDb: Become rpmdb backend independent (jsc#SLE-7272) +- RpmDb: Close API offering a custom rpmdb path + It's actually not needed and for this to work also libsolv needs + to support it. You can sill use a librpmDb::db_const_iterator to + access a database at a custom location (ro). +- Remove legacy rpmV3database conversion code. +- version 17.20.0 (20) + +------------------------------------------------------------------- +Wed Dec 11 09:51:10 CET 2019 - ma@suse.de + +- MediaCurl: assert cookie file has mode 0600 (bsc#1158763, CVE-2019-18900) +- version 17.19.0 (12) + +------------------------------------------------------------------- +Mon Dec 9 10:22:56 CET 2019 - ma@suse.de + +- dup: fix removing orphaned packages dropped by to-be-installed + products (bsc#1155819) +- version 17.18.1 (12) + +------------------------------------------------------------------- +Thu Dec 5 14:23:52 CET 2019 - ma@suse.de + +- Resolver: add solution actions for SOLVER_SOLUTION_BLACK + (retracted/PTF) +- Solvable: add isRetracted and isPtf attributes. +- version 17.18.0 (12) + +------------------------------------------------------------------- +Thu Nov 28 18:20:04 CET 2019 - ma@suse.de + +- Introduce PurgeKernels class (bsc#1155198) + Adds libzypp API to mark all obsolete kernels according to the + existing purge-kernel script rules. +- Add solver jobs for retracted packages and ptfs. + Support for ptf packages and retract ed patches. +- Do not enforce 'en' being in RequestedLocales (bsc#1155678) + If the user decides to have a system without explicit language + support he may do so. +- Pass correct posttrans script argument (fixes #190) +- BuildRequires: libsolv-devel >= 0.7.8. +- version 17.17.0 (12) + +------------------------------------------------------------------- +Tue Oct 29 14:54:51 CET 2019 - ma@suse.de + +- Expose new libsolv API via C++ counterparts + (openSUSE/zypper#214) +- BuildRequires: libsolv-devel >= 0.7.7 +- version 17.16.0 (12) + +------------------------------------------------------------------- +Fri Oct 18 17:20:08 CEST 2019 - ma@suse.de + +- Fix empty metalink downloads if filesize is unknown (bsc#1153557) +- Recognize riscv64 as architecture +- Fix installation of new header file (fixes #185) +- zypp.conf: Introduce `solver.focus` to define the resolvers general + attitude when resolving jobs. (bsc#1146415) +- New container detection algorithm for zypper ps (bsc#1146947) +- version 17.15.0 (12) + +------------------------------------------------------------------- +Thu Sep 26 14:08:51 CEST 2019 - ma@suse.de + +- Revert "Use CURL_HTTP_VERSION_2TLS if available" (bsc#1146027) +- doc: add service example using variables +- Fix build with rpm >= 4.15 (fixes #172) +- version 17.14.1 (12) + +------------------------------------------------------------------- +Mon Aug 5 13:03:55 CEST 2019 - ma@suse.de + +- PublicKey::algoName: supply key algorithm and length +- version 17.14.0 (12) + +------------------------------------------------------------------- +Thu Jul 25 17:25:10 CEST 2019 - ma@suse.de + +- MediaCurl: Fix leaking filedescriptors (bsc#1116995) +- commit: Run file conflict check on dry-run (best with download-only) + (bsc#1140039) +- commit: do not remove orphan products if the .prod file is owned by + a package (bsc#1139795) +- version 17.13.0 (12) + +------------------------------------------------------------------- +Tue May 28 16:50:14 CEST 2019 - ma@suse.de + +- Drop unused InterProcessMutex class and test +- Drop unused WebpinResult class and test +- Give posttrans script a parameter of 0 (issue #168) +- Use CURL_HTTP_VERSION_2TLS if available (fixes #141) +- version 17.12.0 (12) + +------------------------------------------------------------------- +Thu Apr 4 13:24:40 CEST 2019 - ma@suse.de + +- Enhance scanning /sys for modaliases (bsc#1130161) +- version 17.11.4 (9) + +------------------------------------------------------------------- +Tue Apr 2 18:15:12 CEST 2019 - ma@suse.de + +- Prevent SEGV if the application sets an empty TextLocale (bsc#1127026) + +------------------------------------------------------------------- +Mon Apr 1 08:49:45 UTC 2019 - Christophe Giboudeaux + +- Fix build with CMake >= 3.14.0: + Starting with CMake 3.14, EXCLUDE_FROM_ALL now spreads from + directories to targets. 'make -C someSubdir' when 'someSubdir' + uses the 'EXCLUDE_FROM_ALL' keyword does nothing. (gh/libzypp#libzypp#165) + +------------------------------------------------------------------- +Thu Mar 21 12:35:39 CET 2019 - ma@suse.de + +- KeyManager: Work around bsc#1127220 [libgpgme] no error upon + incomplete import due to signal received. +- MediaCurl: add hint to check SCC for an expired regcode on + http error 403 (bsc#965786) +- version 17.11.3 (9) + +------------------------------------------------------------------- +Mon Feb 25 12:07:19 CET 2019 - ma@suse.de + +- Correctly handle exceptions when verifying the medium (bsc#1065022) +- Only write type field when probing (bsc#1114908) +- Don't blame user on TargetAbortedException (bsc#978193) +- version 17.11.2 (9) + +------------------------------------------------------------------- +Thu Jan 31 17:41:21 CET 2019 - ma@suse.de + +- CheckAccessDeleted: Suppress reporting `/memfd:` pseudo files + (bsc#1123843) +- MediaCurl: improve reporting https->http redirection errors +- Prevent SEGV if the application sets an empty TextLocale +- Url: don't force printing an empty authority if the schema does not + allow authority at all +- Try to the missing rpmDB compat symlink in case the rpm package got + deleted (bsc#1122471) +- version 17.11.1 (9) + +------------------------------------------------------------------- +Fri Jan 11 10:24:33 CET 2019 - ma@suse.de + +- PoolItemBest: Optionally prefer not locked packages (for bsc#1113296) +- ui::Selectable: add `hasLocks` to indicate a partially locked + item (for bsc#1113296) +- version 17.11.0 (9) + +------------------------------------------------------------------- +Tue Dec 18 14:01:19 CET 2018 - ma@suse.de + +- Simplify complex locks so zypper can display them (bsc#1112911) +- version 17.10.3 (9) + +------------------------------------------------------------------- +Mon Dec 10 16:57:34 CET 2018 - ma@suse.de + +- commit: set `SYSTEMD_OFFLINE=1` during chrooted commits (bsc#1118758) +- no-recommends: Nevertheless consider resolver namespaces (hardware, + language,..supporting packages) (FATE#325513) +- BuildRequires: libsolv-devel >= 0.7.2 + (SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED) +- Remove world-readable bit from /var/log/zypp (bsc#1099019) +- version 17.10.2 (9) + +------------------------------------------------------------------- +Wed Nov 28 14:40:26 CET 2018 - ma@suse.de + +- Adapt to changes in upcoming Boost 1.69.0 +- Do not fail service-refresh on a empty repoindex.xml (bnc#1116840) +- version 17.10.1 (9) + +------------------------------------------------------------------- +Mon Nov 26 12:14:49 CET 2018 - ma@suse.de + +- str: recognize 'always' and 'never' as valid boolean strings +- Fix needreboot code to use SolvableSpec parser (fate#326451) +- SolvableSpec: Define a set of Solvables by ident and provides +- version 17.10.0 (9) + +------------------------------------------------------------------- +Wed Nov 14 11:48:35 CET 2018 - ma@suse.de + +- Provide needreboot config files in /etc/zypp (fate#326451, fixes #140) +- Need to fix soname due to libsolv ABI changes (bsc#1115341) +- version 17.9.0 (9) + +------------------------------------------------------------------- +Mon Oct 29 12:20:40 CET 2018 - ma@suse.de + +- Adapt to changed type names in libsolv-0.7 +- Package needreboot file (fate#326451) +- Fix definitions of gettext macros (fixes #135) +- version 17.8.1 (2) + +------------------------------------------------------------------- +Fri Oct 12 14:01:19 CEST 2018 - ma@suse.de + +- Add infrastructure to flag specific packages to trigger a + reboot needed hint (fate#326451) +- Adapt to libsolv: Drop support for REPOKEY_TYPE_U32 +- Resolver: add setInr to request solving namespaces +- ResolverNamespace: add No/AllResolverNamespaces constants +- version 17.8.0 (2) + +------------------------------------------------------------------- +Mon Oct 1 14:04:15 CEST 2018 - ma@suse.de + +- Fix blocking wait for finished child process (bsc#1109877) +- version 17.7.2 (2) + +------------------------------------------------------------------- +Fri Sep 28 14:38:01 CEST 2018 - ma@suse.de + +- Fix conversion of string and glob to regex when compiling queries + (bsc#1099982, bsc#939392, bsc#556664) +- version 17.7.1 (2) + +------------------------------------------------------------------- +Fri Sep 7 12:07:39 CEST 2018 - ma@suse.de + +- Drop type application due to poor metadata support (bsc#1100095, + bsc#1104415) +- version 17.7.0 (2) + +------------------------------------------------------------------- +Thu Sep 6 12:16:25 CEST 2018 - ma@suse.de + +- Automatically fetch repository signing key from gpgkey url + (bsc#1088037) +- lsof: use '-K i' if lsof supports it (bsc#1099847,bsc#1036304) +- version 17.6.4 (2) + +------------------------------------------------------------------- +Thu Aug 30 16:44:56 CEST 2018 - ma@suse.de + +- Check for not imported keys after multi key import from rpmdb + (bsc#1096217) +- version 17.6.3 (2) + +------------------------------------------------------------------- +Tue Aug 21 18:46:35 CEST 2018 - ma@suse.de + +- fixup! Add filesize check for downloads with known size (bsc#408814) + Fix detetction of metalink downloads and prevent aborting if + a metalink file is larger than the expected data file. +- version 17.6.2 (2) + +------------------------------------------------------------------- +Fri Aug 17 14:52:14 CEST 2018 - ma@suse.de + +- Adapt to changes in libgpgme11-11.1.0 breaking the signature + verification (bsc#1100427) +- Use %license (bsc#1082318) +- BuildRequires: libsolv-devel >= 0.6.35 (for bsc#1100095) +- changes: add CVE numbers +- version 17.6.1 (2) + +------------------------------------------------------------------- +Fri Aug 3 11:11:25 CEST 2018 - ma@suse.de + +- RepoInfo::provideKey: add report telling where we look for missing + keys. +- Support listing gpgkey URLs in repo files (bsc#1088037) +- Add new report to request user approval for importing a package key +- Handle http error 502 Bad Gateway in curl backend (bsc #1070851) + (fixes openSUSE/zypper#177) +- Add filesize check for downloads with known size (bsc#408814) +- Removed superfluous space in translation (bsc#1102019) +- version 17.6.0 (2) + +------------------------------------------------------------------- +Thu Jul 19 12:57:21 CEST 2018 - ma@suse.de + +- Prevent the system from sleeping during a commit + (fixes openSUSE/zypper#135) +- RepoManager: Explicitly request repo2solv to generate application + pseudo packages. +- version 17.5.2 (2) + +------------------------------------------------------------------- +Wed Jul 18 10:55:49 CEST 2018 - ma@suse.de + +- libzypp-devel should not require cmake (bsc#1101349) +- Avoid zombies from ExternalProgram +- Update ApiConfig +- fix typo +- version 17.5.1 (2) + +------------------------------------------------------------------- +Mon Jul 9 14:43:15 CEST 2018 - ma@suse.de + +- HardLocksFile: Prevent against empty commit without Target having + been been loaded (bsc#1096803) +- lsof: use '-K i' if lsof supports it (bsc#1099847) +- PackageProvider: Validate deta rpms before caching (bsc#1091624, + bsc#1088705, CVE-2018-7685) +- PackageProvider: Validate downloaded rpm package signatures + before caching (bsc#1091624, bsc#1088705, CVE-2018-7685) +- version 17.5.0 (2) + +------------------------------------------------------------------- +Mon Jun 25 10:48:55 CEST 2018 - ma@suse.de + +- Flags: make it std=c++14 ready +- Replace 'redhat-release' with generic 'system-release' (#120) +- Ignore /var, /tmp and /proc in zypper ps (bsc#1096617) +- Show GPGME version in log +- version 17.4.0 (2) + +------------------------------------------------------------------- +Thu Apr 26 18:07:11 CEST 2018 - ma@suse.de + +- Avoid zombie tar processes (bsc#1076192) +- Replace the terminology 'uninstallable' with 'not installable' + (bsc#1029392) +- version 17.3.1 (2) + +------------------------------------------------------------------- +Mon Apr 9 13:11:50 CEST 2018 - ma@suse.de + +- Show progressbar when running posttrans scripts +- Execute service plugin script chrooted to the RepoManagers root + (bsc#1080693) +- Make sure the product file comes from /etc/products.d for the + fallback product search (bsc#1086602) +- Introduce ZConfig::repoManagerRoot to support having diverging + target and repomanager root paths +- Rename `stderr` as it can be a macro (fixes #102) +- version 17.3.0 (2) + +------------------------------------------------------------------- +Tue Mar 13 18:03:42 CET 2018 - ma@suse.de + +- Protect code against broken translations (bsc#1082711) +- Fix broken translated format strings +- Deprecate the use of asciidoc for new releases +- version 17.2.2 (2) + +------------------------------------------------------------------- +Wed Mar 7 11:22:02 CET 2018 - ma@suse.de + +- PoolQuery::addDependency add overload to define an individual + Match::Mode (bsc#1043166) +- version 17.2.1 (2) + +------------------------------------------------------------------- +Thu Mar 1 17:46:39 CET 2018 - bzeller@suse.de + +- Add /var/lib/gdm to CheckAccessDeleted blacklist (bsc#1079991) +- Use gpgme instead of calling gpg2 binary directly +- Fix leak in Digest.cc (bsc#1075978) +- version 17.2.0 (2) + +------------------------------------------------------------------- +Tue Feb 20 18:03:24 CET 2018 - ma@suse.de + +- RpmDb::checkPackage: fix parsing localized rpm output (bsc#1076415) +- Replace libexpat with libxml +- Fix libzypp tests failing with `-Wp,-D_GLIBCXX_ASSERTIONS` + compiler flag (fixes #84) +- BuildRequire gpg2 as testcases need it (fixes #84) +- version 17.1.3 (0) + +------------------------------------------------------------------- +Fri Feb 2 16:07:08 CET 2018 - ma@suse.de + +- Fix crash when installing broken rpm packages (bsc#1078284) +- Testcase: Minor fix writing update testcases +- version 17.1.2 (0) + +------------------------------------------------------------------- +Mon Jan 15 17:01:33 CET 2018 - ma@suse.de + +- Adapt rpm package verification to changes in rpm-4.14 (bsc#1076018) +- version 17.1.1 (0) + +------------------------------------------------------------------- +Thu Jan 4 17:49:06 CET 2018 - ma@suse.de + +- plugin: don't reject header values containing a ':' (bsc#1074687) +- Locks: Don't store duplicate locks (bsc#969569) +- version 17.1.0 (0) + +------------------------------------------------------------------- +Wed Dec 6 13:29:42 CET 2017 - ma@suse.de + +- Fix default for solver.allowNameChange (bsc#1071466) +- version 17.0.5 (0) + +------------------------------------------------------------------- +Mon Dec 4 11:09:24 CET 2017 - ma@suse.de + +- Stop BuildRequire dropped boost-devel (bsc#1062782) +- version 17.0.4 (0) + +------------------------------------------------------------------- +Tue Nov 28 18:21:51 CET 2017 - ma@suse.de + +- When importing multiple keys, export the individual keys + ascii armored for import into the rpmdb (bsc#1069381) +- version 17.0.3 (0) + +------------------------------------------------------------------- +Thu Nov 23 12:33:51 CET 2017 - ma@suse.de + +- Don't filter procs with a different mnt namespace (bsc#1068708) +- Support repo variables in an URIs host:port component + (bsc#1057640, bsc#1067605) +- version 17.0.2 (0) + +------------------------------------------------------------------- +Fri Nov 10 15:25:20 CET 2017 - ma@suse.de + +- Solvable: fix inconsistent retrieval of mediaNr (bsc#1065677) +- version 17.0.1 (0) + +------------------------------------------------------------------- +Tue Nov 7 16:14:31 CET 2017 - ma@suse.de + +- Locale: Fix possible segfault (bsc#1064999) +- RpmDb: Remove excess keys in the zypp keyring when exporting keys only + (bsc#1064380) +- KeyRing: Fix deleted keys not removed from rpmdb too (bsc#1064380) +- Flag gpg keycache dirty when adding/removing keys (bsc#1064380) +- Version 17.x for CODE-15, 16.x. is continued on SuSE-SLE-12-SP2-Branch +- version 17.0.0 (0) + +------------------------------------------------------------------- +Thu Oct 12 18:04:38 CEST 2017 - ma@suse.de + +- Fix media handling in presence of a repo path prefix (bsc#1062561) +- version 16.17.3 (0) + +------------------------------------------------------------------- +Wed Oct 11 16:29:48 CEST 2017 - ma@suse.de + +- Fix RepoProvideFile ignoring a repo path prefix (bsc#1062561) +- version 16.17.2 (0) + +------------------------------------------------------------------- +Fri Sep 22 12:16:34 CEST 2017 - ma@suse.de + +- Default to 'solver.dupAllowVendorChange = false' on SLE15 + (FATE#323478) +- Remove unused legacy notify-message script (bsc#1058783) +- version 16.17.1 (0) + +------------------------------------------------------------------- +Fri Sep 8 18:05:30 CEST 2017 - ma@suse.de + +- Support multiple product licenses in repomd (FATE#322276) +- version 16.17.0 (0) + +------------------------------------------------------------------- +Thu Sep 7 12:27:44 CEST 2017 - ma@suse.de + +- Propagate 'rpm --import' errors (bsc#1057188) +- Fix typos in zypp.conf +- version 16.16.0 (0) + +------------------------------------------------------------------- +Mon Aug 28 16:05:36 CEST 2017 - ma@suse.de + +- Add testcase to compile (bsc#1055920) +- version 16.15.6 (0) + +------------------------------------------------------------------- +Fri Aug 25 14:08:43 CEST 2017 - ma@suse.de + +- Adapt to work with GnuPG 2.1.23 (bsc#1054088) +- version 16.15.5 (0) + +------------------------------------------------------------------- +Fri Aug 25 12:51:43 CEST 2017 - ma@suse.de + +- verifyFileSignature: Support signing with subkeys (bsc#1008325) +- PublicKey: Scan and provide subkey information. +- Enhance sort order for media.1/products (bsc#1054671) +- Drop detection and support for rpm-4.4 (fixes #77) +- version 16.15.4 (0) + +------------------------------------------------------------------- +Fri Aug 11 15:29:40 CEST 2017 - ma@suse.de + +- RepoInfo: add enum GpgCheck for convenient gpgcheck mode handling + (bsc#1045735) +- Fix repo/pkg checks to follow explicitly defined gpgcheck in a + .repo file +- version 16.15.3 (0) + +------------------------------------------------------------------- +Fri Jul 21 13:26:48 CEST 2017 - ma@suse.de + +- Weaken fix for bsc#1038984 if 'gpgcheck=0' in libzypp-16.15.x only. + This will allow some already released products to adapt to the + behavioral changes introduced by fixing bsc#1038984, while systems + with a default configuration (gpgcheck=1) already benefit from + the fix in libzypp-16.15.x. For details see section + 'Signature checking' in /etc/zypp/zypp.conf. +- Fix gpg-pubkey release (creation time) computation (bsc#1036659) +- update lsof blacklist (bsc#1046417) +- version 16.15.2 (0) + +------------------------------------------------------------------- +Tue Jul 18 13:18:16 CEST 2017 - ma@suse.de + +- Be sure bad packages do not stay in the cache + (bsc#1045735, CVE-2017-9269) +- version 16.15.1 (0) + +------------------------------------------------------------------- +Mon Jul 17 16:38:14 CEST 2017 - ma@suse.de + +- PackageProvider: enforce a signed package if pkgGpgCheckIsMandatory +- Add RpmDb::checkPackageSignature to report unsigned packages +- Fix repo gpg check workflows, mainly for unsigned repos and packages + (bsc#1045735, bsc#1038984, CVE-2017-7435, CVE-2017-7436, CVE-2017-9269) +- version 16.15.0 (0) + +------------------------------------------------------------------- +Wed Jul 12 17:06:14 CEST 2017 - ma@suse.de + +- repo refresh: Re-probe if the repository type changes (bsc#1048315) +- MediaCurl: Propagate proper error code to DownloadProgressReport + (bsc#1047785) +- Allow to trigger an appdata refresh unconditionally (bsc#1009745) +- Support custom repo variables defined in /etc/zypp/vars.d (fixes #68) +- rename: handle EXDEV error on OverlayFS +- version 16.14.0 (0) + +------------------------------------------------------------------- +Fri Jun 30 14:25:29 CEST 2017 - ma@suse.de + +- Adapt loop mounting of iso images (bsc#1038132, bsc#1033236) +- Adjust zypp.conf for openSUSE Tumbleweed (bsc#1031756) +- Change arch variable names conflicting with compiler macros (fixes #70) +- Fix potential crash if repo has no baseurl (bnc#1043218) +- version 16.13.0 (0) + +------------------------------------------------------------------- +Wed May 31 11:49:07 CEST 2017 - ma@suse.de + +- Testcase: add missing solver flags (bsc#1041889) +- version 16.12.0 (0) + +------------------------------------------------------------------- +Fri May 12 11:36:52 CEST 2017 - ma@suse.de + +- add identIsAutoInstalled convenience methods +- make gcc6 happy +- version 16.11.0 (0) + +------------------------------------------------------------------- +Thu May 11 15:23:28 CEST 2017 - ma@suse.de + +- Use a common workflow for downloading packages and srcpackages. + This includes a common way of handling and reposrting gpg signature + and checks. (bsc#1037210) +- PackageProvider: as well support downloading SrcPackage (for bsc#1037210) +- version 16.10.0 (0) + +------------------------------------------------------------------- +Thu Apr 27 16:03:32 CEST 2017 - ma@suse.de + +- PoolQuery: Treat explicit queries for 'kind:name' correctly + (bsc#1035729) +- version 16.9.0 (0) + +------------------------------------------------------------------- +Fri Apr 21 16:23:51 CEST 2017 - ma@suse.de + +- Add API to control resolver job to update all packages (FATE#320653) +- Remove legacy vendor equivalence between 'suse' and 'opensuse' + (bsc#1030686) +- version 16.8.0 (0) + +------------------------------------------------------------------- +Fri Apr 21 09:40:32 CEST 2017 - ma@suse.de + +- RepoInfo: Allow temporary repos to control their metadata + directories (bsc#1032632) +- Arch: add armv5tl +- version 16.7.0 (0) + +------------------------------------------------------------------- +Thu Mar 30 15:00:30 CEST 2017 - ma@suse.de + +- Recognize license tarball in rpmmd repos (FATE#316159) +- Fix media verification to properly propagate media access errors + (bsc#1031093) +- version 16.6.1 (0) + +------------------------------------------------------------------- +Mon Mar 27 17:10:52 CEST 2017 - ma@suse.de + +- Fix invalidation of PoolItems if Pool IDs are reused (bsc#1028661) +- version 16.6.0 (0) + +------------------------------------------------------------------- +Mon Mar 27 09:33:26 CEST 2017 - ma@suse.de + +- Fix X-libcurl-Empty-Header-Workaround (bsc#1030919) +- version 16.5.2 (0) + +------------------------------------------------------------------- +Tue Mar 21 13:38:08 CET 2017 - ma@suse.de + +- MediaCurl: Treat http response 410(Gone) like 404(Not Found) + (bsc#1030136) +- version 16.5.1 (0) + +------------------------------------------------------------------- +Thu Mar 16 14:06:03 CET 2017 - ma@suse.de + +- Support multi-volume repomd repositories (FATE#320544) +- MediaCurl: ZYPP_MEDIA_CURL_IPRESOLVE=<4|6> to force name resolution + to IPv4/IPv6 only (fixes openSUSE/zypper#49) +- Add support for openssl >= 1.1 +- version 16.5.0 (0) + +------------------------------------------------------------------- +Mon Feb 20 10:10:43 CET 2017 - ma@suse.de + +- PublicKey: Create tmpdirs inside ZYpp::tmpPath (bsc#926844) +- Don't create AnonymousUniqueId in chroot (bsc#1024741) +- version 16.4.3 (0) + +------------------------------------------------------------------- +Tue Feb 14 12:07:14 CET 2017 - ma@suse.de + +- dumpAsXmlOnL: xml escape node content (bsc#1024909) +- version 16.4.2 (0) + +------------------------------------------------------------------- +Fri Feb 3 13:40:04 CET 2017 - ma@suse.de + +- MediaMultiCurl: Trigger aliveCallback when downloading metalink + files (bsc#1021291) +- version 16.4.1 (0) + +------------------------------------------------------------------- +Thu Jan 26 13:03:37 CET 2017 - ma@suse.de + +- Add API for updating the AutoInstalled db +- MediaCD: Fix mountpoint creation after failing udf mount (bsc#1022046) +- fix misleading indentation (fixes #65) +- Fix compilation error reported by GCC7 (#63). +- Prefer calling "repo2solv" rather than "repo2solv.sh" +- version 16.4.0 (0) + +------------------------------------------------------------------- +Wed Dec 14 12:24:23 CET 2016 - ma@suse.de + +- Don't raise FileCheckException if user accepted a package with wrong + digest (bsc#1014265) +- Also provide the exception history when requesting a media failed + (bsc#1010952) +- version 16.3.2 (0) + +------------------------------------------------------------------- +Tue Oct 11 18:04:18 CEST 2016 - ma@suse.de + +- Let 'dup --from' leave an updateTestcase- in /var/log (bsc#1004096) +- version 16.3.1 (0) + +------------------------------------------------------------------- +Tue Oct 11 11:41:47 CEST 2016 - ma@suse.de + +- RepoInfo: Allow parsing multiple gpgkey= URLs (bsc#1003748) +- version 16.3.0 (0) + +------------------------------------------------------------------- +Tue Sep 20 11:41:48 CEST 2016 - ma@suse.de + +- guessPackageSpec: Don't break globbing (fixes openSUSE/zypper#97) +- version 16.2.5 (0) + +------------------------------------------------------------------- +Thu Sep 15 15:27:15 CEST 2016 - ma@suse.de + +- RepoFileReader: fix parsing of multiline url entries (bsc#964932) +- Allow repo type 'rpm' as alias for 'rpm-md' (fixes openSUSE/zypper#100) +- version 16.2.4 (0) + +------------------------------------------------------------------- +Fri Sep 9 16:43:30 CEST 2016 - ma@suse.de + +- xmlout::Node: Allow adding nore attributes while the start node + is not closed (FATE#320699) +- Fixes broken XML output introduced by an unwanted change in 16.2.2 + (bsc#998344) +- version 16.2.3 (0) + +------------------------------------------------------------------- +Wed Aug 10 17:10:41 CEST 2016 - ma@suse.de + +- Report numeric curl error if code is unrecognized (bsc#992302) +- multicurl: propagate proxy settings stored in repo url (bsc#933839) +- version 16.2.2 (0) + +------------------------------------------------------------------- +Thu Jul 21 13:09:33 CEST 2016 - ma@suse.de + +- Rebuild .solv-files not matching the parsers LIBSOLV_TOOLVERSION +- BuildRequires: libsolv-devel >= 0.6.23 +- version 16.2.1 (0) + +------------------------------------------------------------------- +Mon Jul 18 16:36:25 CEST 2016 - ma@suse.de + +- Product: Offer tri-state hasEndOfLife details (FATE#320699) +- version 16.2.0 (0) + +------------------------------------------------------------------- +Thu Jul 14 19:02:57 CEST 2016 - ma@suse.de + +- use more user friendly command names for "zypper ps" (bsc#980541) +- version 16.1.3 (0) + +------------------------------------------------------------------- +Thu Jul 14 15:39:03 CEST 2016 - ma@suse.de + +- Don't do media number substitution on URLs of medium #1 (bsc#798470) +- version 16.1.2 (0) + +------------------------------------------------------------------- +Tue Jul 5 11:39:11 CEST 2016 - ma@suse.de + +- Fix Shrink pool if all repos are removed (bsc#899755, bsc#987573) +- version 16.1.1 (0) + +------------------------------------------------------------------- +Fri Jun 24 12:33:29 CEST 2016 - ma@suse.de + +- API enahncements for zypper (FATE#320447) +- version 16.1.0 (0) + +------------------------------------------------------------------- +Tue Jun 21 11:11:03 CEST 2016 - ma@suse.de + +- Filter duplicate resolver solutions (bsc#985674) +- zypp.conf: Add download.media_mountdir: Path where media are + preferably mounted or downloaded (FATE#319462) +- version 16.0.5 (0) + +------------------------------------------------------------------- +Wed Jun 15 12:36:27 CEST 2016 - ma@suse.de + +- Fix bug in removeRepository which may keep an empty .repo file + rather than deleting it (bsc#984494) +- version 16.0.4 (0) + +------------------------------------------------------------------- +Mon Jun 13 12:53:03 CEST 2016 - ma@suse.de + +- Shrink pool if all repos are removed (bnc#899755) +- Avoid direct BuildRequire on libudev-devel (#60) +- version 16.0.3 (0) + +------------------------------------------------------------------- +Tue Jun 7 18:43:31 CEST 2016 - ma@suse.de + +- Allow PackageKit to drop the zypp lock (bnc#899755) +- Avoid superfluous rebuilding of indices when solving +- version 16.0.2 (0) + +------------------------------------------------------------------- +Sun Jun 5 16:12:42 CEST 2016 - ma@suse.de + +- po: upadte makefiles +- DefaultIntegral: provide asString (for FATE#320447) +- version 16.0.1 (0) + +------------------------------------------------------------------- +Fri May 13 08:45:53 CEST 2016 - ma@suse.de + +- Prepare cmake to maintain the .pot and .po files in git. Add + initial .po file set derived from tarballs. Translations are now + maintained via Weblate. +- Provide 'libzypp(plugin:services) = 1' after fixing bsc#933760 +- Bump major version for Factory, 15.x is continued on SuSE-SLE-12-SP1-Branch +- version 16.0.0 (0) + +------------------------------------------------------------------- +Thu Apr 28 14:17:09 CEST 2016 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Apr 28 14:04:36 CEST 2016 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Apr 25 14:59:41 CEST 2016 - ma@suse.de + +- Fix credential file parser losing entries with known URL but + different user name (bsc#933760) +- RepoManager: allow extraction of multiple baseurls for service + repos (bsc#964932) +- addRepository: fix to use the correct history file for logging +- specfile: add /etc/zypp/credentials.d to the file list +- version 15.22.0 (19) + +------------------------------------------------------------------- +Mon Apr 18 15:03:13 CEST 2016 - ma@suse.de + +- RepoindexFileReader: fix service metadata TTL default value (bsc#967828) +- version 15.21.7 (19) + +------------------------------------------------------------------- +Fri Apr 15 11:31:08 CEST 2016 - ma@suse.de + +- DiskUsageCounter: Limit estimated waste per file (bsc#974275) +- version 15.21.6 (19) + +------------------------------------------------------------------- +Fri Mar 18 13:37:22 CET 2016 - ma@suse.de + +- Use PluginExecutor for commit- and system-hooks (bnc#971637) +- BuildRequires: libsolv-devel >= 0.6.19 (bnc#971018) +- version 15.21.5 (19) + +------------------------------------------------------------------- +Sun Mar 13 01:13:08 CET 2016 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Mar 10 01:13:24 CET 2016 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Mar 1 12:34:53 CET 2016 - ma@suse.de + +- media: Send stats header to download.opensuse.org only (bsc#955801) +- fix build-compare (#57, #58) +- version 15.21.4 (19) + +------------------------------------------------------------------- +Thu Feb 18 18:38:52 CET 2016 - ma@suse.de + +- yum::Downloader: Download only wanted 'susedata.LANG' files + (FATE#320518) +- version 15.21.3 (19) + +------------------------------------------------------------------- +Thu Feb 4 16:38:14 CET 2016 - ma@suse.de + +- installSrcPackage: trigger progress callback (bsc#580902) +- version 15.21.2 (19) + +------------------------------------------------------------------- +Thu Feb 4 01:13:31 CET 2016 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Jan 29 11:40:51 CET 2016 - ma@suse.de + +- Don't buildrequire graphviz-gnome (bsc#964150) +- Unwanted btrfs subvolumes must be filtered by device (not fsid) + (fixes #54) +- version 15.21.1 (19) + +------------------------------------------------------------------- +Thu Jan 21 01:13:29 CET 2016 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Jan 20 17:12:42 CET 2016 - ma@suse.de + +- Filter unwanted btrfs subvolumes (fixes #54, closes #55, bnc#949945) +- RepoInfo: Provide access to repo content keywords +- Build with boost-1.60.0 +- version 15.21.0 (19) + +------------------------------------------------------------------- +Thu Jan 14 01:13:17 CET 2016 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jan 7 01:13:28 CET 2016 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Dec 24 01:13:13 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Dec 11 19:07:09 CET 2015 - ma@suse.de + +- ResPoolProxy: make begin/end pairs Iterable +- String: Format and FormatNAC classes based on boost::format +- DefaultIntegral: provide initial value +- More specific exception message if GPG binary is missing (bsc#637791) +- version 15.20.0 (19) + +------------------------------------------------------------------- +Thu Dec 10 01:14:50 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Dec 3 01:13:11 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Nov 22 01:13:29 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Nov 19 01:16:03 CET 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Nov 19 01:13:40 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Nov 16 12:27:02 CET 2015 - ma@suse.de + +- createPot: Fix plural form detection (bsc#955053) +- version 15.19.7 (19) + +------------------------------------------------------------------- +Thu Nov 12 01:13:26 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Nov 8 01:13:11 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Nov 6 11:08:46 CET 2015 - ma@suse.de + +- Add testcase for uncached repo-variables. +- Fixed Japanese translations (bsc#949196) +- version 15.19.6 (19) + +------------------------------------------------------------------- +Fri Nov 6 10:56:44 CET 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Nov 5 01:15:12 CET 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Nov 5 01:13:24 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Nov 3 10:52:01 CET 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Nov 3 10:51:43 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Oct 23 17:10:18 CEST 2015 - ma@suse.de + +- Fix broken product: <-> -release package relation (bnc#951782) +- version 15.19.5 (19) + +------------------------------------------------------------------- +Thu Oct 22 12:23:29 CEST 2015 - ma@suse.de + +- Use a uniform translation set for SLE and openSUSE (bnc#948924) +- fix Plugin-services not updating repo GPGCheck settings (bnc#951402) +- version 15.19.4 (19) + +------------------------------------------------------------------- +Sun Oct 18 01:13:27 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Oct 15 01:13:57 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Oct 14 16:36:27 CEST 2015 - ma@suse.de + +- make Solvable::asUserString more readable (bnc#949957) +- version 15.19.3 (19) + +------------------------------------------------------------------- +Sun Oct 11 01:13:12 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Oct 8 01:14:43 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Oct 7 13:11:48 CEST 2015 - ma@suse.de + +- fix suse_version test (bsc#949046) +- version 15.19.2 (19) + +------------------------------------------------------------------- +Wed Oct 7 11:06:24 CEST 2015 - ma@suse.de + +- Locks: fix using namespaces (for FATE#318299) +- version 15.19.1 (19) + +------------------------------------------------------------------- +Mon Oct 5 12:27:49 CEST 2015 - ma@suse.de + +- fix reserved identifier violation (fixes #51) +- solver: speed up collecting pool data to build the job queue +- doc: short abstract about 'Code 12 Application Metadata' +- version 15.19.0 (19) + +------------------------------------------------------------------- +Tue Sep 29 17:51:48 CEST 2015 - ma@suse.de + +- solver verify: multiversion property needs to be assigned to + installed items too. +- ZYppCommitResult: add attemptToModify to indicate an attempt to + actually install/remove was made (bsc#946750, FATE#319467) +- version 15.18.0 (14) + +------------------------------------------------------------------- +Mon Sep 28 12:19:26 CEST 2015 - ma@suse.de + +- SetTracker: fix computation of change sets (bsc#946898) +- version 15.17.2 (14) + +------------------------------------------------------------------- +Fri Sep 25 11:42:28 CEST 2015 - ma@suse.de + +- Pattern: support dynamic computation of pattern visibility (bsc#900769) +- Avoid URL rewrite if probing local cache directories (bsc#946129) +- version 15.17.1 (14) + +------------------------------------------------------------------- +Mon Sep 21 16:57:45 CEST 2015 - ma@suse.de + +- Dummy (FATE#318827) to make Sles-changelog-checker stop whining. +- version 15.17.0 (14) + +------------------------------------------------------------------- +Mon Sep 21 16:09:50 CEST 2015 - ma@suse.de + +- Glob: fix reserved identifier violation +- version 15.16.2 (14) + +------------------------------------------------------------------- +Tue Sep 15 15:02:45 CEST 2015 - ma@suse.de + +- CheckAccessDeleted: Identify services by systemd cgroup (FATE#318827) +- version 15.16.1 (14) + +------------------------------------------------------------------- +Mon Sep 14 12:21:30 CEST 2015 - ma@suse.de + +- Reload multiversion setting from the target zypp.conf (bnc#906096) +- version 15.16.0 (14) + +------------------------------------------------------------------- +Sun Sep 13 01:15:26 CEST 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Sep 13 01:13:30 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 10 01:16:00 CEST 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Sep 4 13:49:33 CEST 2015 - ma@suse.de + +- Don't cache repo releasever (bnc#943563) +- Selectable: allow setPickStatus for non-multiversion packages + (bnc#943870) +- ResPoolProxy: add ScopedSaveState +- version 15.15.0 (14) + +------------------------------------------------------------------- +Tue Sep 1 18:19:27 CEST 2015 - ma@suse.de + +- zypp.conf: add solver.dupAllow{Downgrade,NameChange,ArchChange, + VendorChange} default options for tuning distribution upgrades. +- Remove obsolete method (bsc#941398) (fixes #50) +- fix invalid XML (bnc#942518) +- version 15.14.0 (14) + +------------------------------------------------------------------- +Sun Aug 30 01:13:07 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 27 01:14:20 CEST 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 20 01:13:09 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Aug 16 01:13:23 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 13 18:16:52 CEST 2015 - ma@suse.de + +- Support caching of service metadata. A TTL for the service + metadata may be provided in the repoindex.xml itself. The + default is 'no caching'. (FATE#318136) +- Fix setting dup_allow* solver options (bnc#941463) +- Don't make zypper encode {} around repo vars (bnc#941453) +- version 15.13.0 (11) + +------------------------------------------------------------------- +Thu Aug 13 01:13:43 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Aug 11 18:48:57 CEST 2015 - ma@suse.de + +- History: Add 'command' tag showing who triggered the commit. + The corresponding HistoryLogData class for parsing is + HistoryLogDataStampCommand. Available data are the commandline + executed, user@hostname and userdata/transactionID. (FATE#312298) +- Add convenience comparison PoolItem<>ResObject::constPtr +- Fixes for SWIG 2.x +- version 15.12.0 (11) + +------------------------------------------------------------------- +Mon Aug 10 16:22:06 CEST 2015 - ma@suse.de + +- Make multiversion an individual solvables property (FATE#318778) +- SolvableType: common api to access solvable properties +- Support for MIPS architectures +- version 15.11.0 (11) + +------------------------------------------------------------------- +Sun Aug 9 01:13:24 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Aug 2 01:13:27 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 30 16:13:49 CEST 2015 - ma@suse.de + +- Resolver: Track changed requested locales and adjust installed + packages accordingly. (part of FATE#318099) +- Testcase: Store autoinstalled packages +- Locale: Make it IdString based +- Get rid of std::tr1:: hashes +- Flags: Fix to work with 'enum class' +- Hide away resolver internals +- version 15.10.0 (10) + +------------------------------------------------------------------- +Thu Jul 30 01:13:30 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Jul 28 14:14:54 CEST 2015 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Jul 27 09:30:38 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Jul 26 01:13:37 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 16 01:13:33 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Jul 12 01:13:20 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 9 16:43:12 CEST 2015 - ma@suse.de + +- Resolver allow tuning DUP mode solver flags (FATE#319128) +- version 15.9.0 (5) + +------------------------------------------------------------------- +Fri Jul 3 08:23:04 CEST 2015 - ma@suse.de + +- Flags: add stringify +- add asString for Patch::InteractiveFlag +- version 15.8.0 (5) + +------------------------------------------------------------------- +Thu Jul 2 01:13:24 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Jul 1 14:00:42 CEST 2015 - ma@suse.de + +- add asString for Patch::Category +- version 15.7.0 (5) + +------------------------------------------------------------------- +Mon Jun 29 17:43:00 CEST 2015 - ma@suse.de + +- Fix lost pathname when importing repo keys (bnc#936373) +- Disable code swig does not understand +- version 15.6.0 (5) + +------------------------------------------------------------------- +Sat Jun 27 17:07:32 CEST 2015 - ma@suse.de + +- Patch: fixup testing Category and Severity flags (FATE#318760) +- version 15.5.0 (5) + +------------------------------------------------------------------- +Fri Jun 12 12:14:04 CEST 2015 - ma@suse.de + +- Add details to the default signature verification problem report +- PathInfo: Avoid ExternalProgram in clean_dir +- call rpmdb2solv without executing user-supplied scripts (bnc#926853) +- version 15.4.1 (3) + +------------------------------------------------------------------- +Thu Jun 11 01:13:31 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jun 4 01:13:22 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Jun 3 13:00:59 CEST 2015 - ma@suse.de + +- Enhance solv.idx file handling to support zypper bash completion +- Fix SSL client certificate authentication via URL option + ssl_clientcert/ssl_clientkey (bnc#932393) +- version 15.4.0 (3) + +------------------------------------------------------------------- +Thu May 28 01:13:23 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun May 24 18:17:38 CEST 2015 - ma@suse.de + +- Downloader: Accept unsigned repository if pkgGpgCheck is ON. +- FindFileConflicts: avoid nested exception on user abort (bnc#931601) +- Support for *.check files in the systemCheck.d directory (#45) +- version 15.3.0 (3) + +------------------------------------------------------------------- +Sun May 24 01:13:19 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon May 18 10:46:10 CEST 2015 - ma@suse.de + +- zypp.conf: Add config values for gpgcheck, repo_gpgcheck + and pkg_gpgcheck. The default behavior 'gpgcheck=On' will + automatically turn on the gpg signature check for packages + downloaded from repository with unsigned metadata. If the + repo metadata are signed, a faster comparison via checksums + is done. By explicitly setting repo_gpgcheck or pkg_gpgcheck + you can enforce the signature check of repository metadata + or downloaded packages to be always performed. Those defaults + can be overwritten per repository. (FATE#314603) +- version 15.2.0 (2) + +------------------------------------------------------------------- +Wed May 13 14:04:04 CEST 2015 - ma@suse.de + +- Write solv.idx to speed up bash tab completion (bnc#928650) +- version 15.1.3 (1) + +------------------------------------------------------------------- +Fri May 8 11:44:44 CEST 2015 - ma@suse.de + +- gcc5 fixes +- Fix repo alias containing ']' not handled correctly (bnc#929528) +- Fix SEGV when dumping rpm header with epoch (bnc#929483) +- version 15.1.2 (1) + +------------------------------------------------------------------- +Mon Apr 27 14:43:53 CEST 2015 - ma@suse.de + +- PubliKey: fix reference to temporary data +- version 15.1.1 (1) + +------------------------------------------------------------------- +Thu Apr 23 01:13:15 CEST 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Apr 22 10:50:00 CEST 2015 - ma@suse.de + +- ZYpp: Changed ZYpp::Ptr to be a shared_ptr; + a precondition for fixing bnc-899755 +- rpmmd: support 'metalink=' in .repo (for zypper#63) +- RepoMirrorList: ignore comments and malformed urls in mirrorlist +- PathInfo: remove minor/major conflicting with GNU libc macros + DiskUsageCounter: remove ctors taking 'magic' bool flags + ZyppCallbacks: remove unused PatchDownload callbacks +- version 15.1.0 (1) + +------------------------------------------------------------------- +Thu Apr 2 19:06:56 CEST 2015 - ma@suse.de + +- POODLE: libzypp should only talk TLS (bnc#903405) +- Bump major version for Factory, 14.x is continued on SuSE-SLE-12-Branch +- version 15.0.0 (0) + +------------------------------------------------------------------- +Thu Apr 2 16:01:43 CEST 2015 - ma@suse.de + +- Fixes to build with gcc5 +- RepoProvideFile: Suppress MediaChangeReport while testing + multiple baseurls (bnc#899510) +- version 14.38.1 (30) + +------------------------------------------------------------------- +Thu Mar 19 16:44:39 CET 2015 - ma@suse.de + +- Suppress MediaChangeReport while testing multiple baseurls (bnc#899510) +- version 14.38.0 (30) + +------------------------------------------------------------------- +Mon Mar 16 14:05:28 CET 2015 - ma@suse.de + +- add support for SHA224/384/512 +- version 14.37.1 (30) + +------------------------------------------------------------------- +Wed Mar 11 09:22:46 CET 2015 - ma@suse.de + +- New RepoVarExpand: Functor expanding repo variables in a + string . Supports bash style default ${v:-w}' and alternate ${v:+w} + values (FATE#318354) +- Easy.h: Use __typeof__ rather than typeof in header +- Support repo variable replacement in service url +- Support repo variable replacement in gpg url +- Gettext.h: Fallback to ::gettext if accidentally included + outside libzypp +- version 14.37.0 (30) + +------------------------------------------------------------------- +Sun Feb 22 01:13:12 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Feb 19 01:13:13 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Feb 15 01:13:28 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Feb 12 01:13:34 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Feb 9 16:05:38 CET 2015 - ma@suse.de + +- Don't execute scripts in /tmp or /var/tmp, as they could be + mounted noexec for security reasons (bnc#915928) +- zypp/PublicKey.cc: Use GPG_BINARY from KeyRing +- Support $releasever_major/$releasever_minor repo variables + (FATE#318354) +- version 14.36.0 (30) + +------------------------------------------------------------------- +Sun Feb 8 01:13:14 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Feb 5 01:13:27 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Feb 1 01:13:10 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jan 29 01:13:12 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jan 22 01:13:36 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Jan 21 10:28:49 CET 2015 - ma@suse.de + +- PathInfo: Deprecate major/minor in favor of new devMajor/devMinor. + The old names clash with GNU libc macros. +- version 14.35.0 (30) + +------------------------------------------------------------------- +Sun Jan 18 01:13:09 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jan 15 01:13:12 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Jan 12 15:04:17 CET 2015 - ma@suse.de + +- Properly propagate repo variables in service refresh. +- Let $ZYPP_REPO_RELEASEVER overwrite $releasever in .repo files + (bnc#911658) +- Call pool_set_rootdir to properly check for file conflicts. +- Use xgettext --boost to support boost-format (%N%) +- version 14.34.0 (30) + +------------------------------------------------------------------- +Sun Jan 11 01:13:15 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jan 8 01:13:23 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jan 1 01:13:29 CET 2015 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Dec 21 01:13:33 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Dec 19 10:05:00 CET 2014 - ma@suse.de + +- Parse and offer productRegisterFlavor attribute (bnc#896224) +- version 14.33.0 (30) + +------------------------------------------------------------------- +Thu Dec 18 01:13:20 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Dec 17 18:44:26 CET 2014 - ma@suse.de + +- Improve conflict message for locked packages (bnc#828631) +- Fix broken de-escaping in str::splitEscaped (bnc#909772) +- cleanup loging +- version 14.32.2 (30) + +------------------------------------------------------------------- +Fri Dec 12 14:00:01 CET 2014 - ma@suse.de + +- CheckAccessDeleted: Filter PIDs running in a container (bnc#909143) +- version 14.32.1 (30) + +------------------------------------------------------------------- +Wed Dec 10 16:06:04 CET 2014 - ma@suse.de + +- suppress informal license (no need to accept) upon update (bnc#908976) +- version 14.32.0 (30) + +------------------------------------------------------------------- +Mon Dec 8 14:53:00 CET 2014 - ma@suse.de + +- Adapt to gpg-2.1 (bnc#908135) +- rpm: do not obsolete yast2-packagemanager-devel by libzypp-devel-doc +- replaceAll: fix endless loop on empty search string +- version 14.31.0 (30) + +------------------------------------------------------------------- +Thu Nov 27 07:40:30 UTC 2014 - dimstar@opensuse.org + +- Do not provide/obsolete yast2-packagemanager-devel by the -doc + package: the -devel package already does that. +- Minor .spec cleanup (remove Authors section). + +------------------------------------------------------------------- +Tue Nov 11 17:09:28 CET 2014 - ma@suse.de + +- Call rpm with '--noglob' (bnc#892431) +- Downloader: unify workflow downloading a (signed) master index file +- Fix iostream includes (fixes #34) +- Explicitly call libsolv:pool_setdisttype (fixes #36) +- version 14.30.2 (30) + +------------------------------------------------------------------- +Sun Nov 9 01:13:17 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Nov 2 01:14:10 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Oct 27 11:38:00 CET 2014 - ma@suse.de + +- doc: add hint to code 12 pattern packages +- MediaCurl: Fix URL path concatenation (bnc#901590) +- Move doxygen html doc to libzypp-devel-doc (bnc#901691) +- Remove non-breaking spaces from changes file +- Control lifetime of downloaded mirrorlist +- version 14.30.1 (30) + +------------------------------------------------------------------- +Thu Oct 16 11:03:11 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Oct 15 15:07:09 CEST 2014 - ma@suse.de + +- Store baseurls in list as order expresses preference +- Support parsing multiple baseurls from a repo file (bnc#899510) +- Fix handling local mirrorlist= files in .repo (bnc#899510) +- Provide missing man pages (fixes #33) +- Enable building autodocs, translations and test per default on debian +- Fix several typos in output messages and comments (fixes #29) +- Make the include dir path configurable (fixes #27) +- version 14.30.0 (30) + +------------------------------------------------------------------- +Fri Oct 10 16:01:31 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 (bnc#899603) + +------------------------------------------------------------------- +Thu Oct 9 01:13:15 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Oct 5 01:14:42 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Sep 28 01:13:30 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 25 17:59:06 CEST 2014 - ma@suse.de + +- Trigger appdata plugin when system repos have changed (bnc#866257) +- Protect against race when destructing globals +- BuildRequire libsolv-tools as libsolv-devel no longer does +- version 14.29.4 (29) + +------------------------------------------------------------------- +Thu Sep 25 01:15:42 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Sep 23 17:07:45 CEST 2014 - ma@suse.de + +- Fix computation of userinstalled items (bnc#897404) +- version 14.29.3 (29) + +------------------------------------------------------------------- +Tue Sep 23 10:55:08 CEST 2014 - ma@suse.de + +- Adapt to API changes in rpm.4.12 +- SLE-12 (suse_version 1315) uses it's own translations set + (bnc#897176) +- version 14.29.2 (29) + +------------------------------------------------------------------- +Sun Sep 21 01:13:25 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 18 15:47:50 CEST 2014 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 18 15:47:34 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 18 15:46:11 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Sep 17 13:18:23 CEST 2014 - ma@suse.de + +- adjust BuildRequires +- version 14.29.1 (29) + +------------------------------------------------------------------- +Tue Sep 16 10:45:39 CEST 2014 - ma@suse.de + +- DiskUsageCounter: Set growonly on detetcted snapshotting btrfs + partitions (bnc#896176) +- DiskUsageCounter: Allow MountPoint to store fstype +- DiskUsageCounter: Support setting 'growonly' partition hint + (bnc#896176) +- version 14.29.0 (29) + +------------------------------------------------------------------- +Fri Sep 5 12:46:57 CEST 2014 - ma@suse.de + +- Make Repository::isUpdateRepo also check for being referenced + by products (bnc#892579) +- Report repositories skipped as nonroot due to insufficient + permission (bnc#893260) +- version 14.28.0 (28) + +------------------------------------------------------------------- +Thu Sep 4 01:14:34 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Aug 29 14:46:25 CEST 2014 - ma@suse.de + +- PackageProvider: consider toplevel cache if --root or --pkg-cachedir + is used. +- Cleanup orpahned cache dirs only at zypp.conf default locations + (bnc#891515) +- Remove orphaned package caches on refresh (bnc#888919) +- version 14.27.2 (27) + +------------------------------------------------------------------- +Sun Aug 24 01:16:00 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Aug 18 14:01:06 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 31 19:22:56 CEST 2014 - ma@suse.de + +- Fix gpg key creation/modification date computation to properly + update trusted keys stored in the rpm database. +- version 14.27.1 (27) + +------------------------------------------------------------------- +Mon Jul 28 11:32:40 CEST 2014 - mls@suse.de + +- reverted last commit to make yast2-pkg-bindings build again + +------------------------------------------------------------------- +Fri Jul 25 12:56:17 CEST 2014 - ma@suse.de + +- JobReport: extend callback to allow passing UserData +- hardlinkCopy must not fail if proc/sys/fs/protected_hardlink is on +- adapt to changed boost::error_category throw specifier +- version 14.27.0 (27) + +------------------------------------------------------------------- +Fri Jul 18 08:57:39 CEST 2014 - ma@suse.de + +- Execute install scripts with cwd==/ (bnc#886764) +- fix wrong '//' when extending URLs with an empty path (bnc#885254) +- version 14.26.1 (26) + +------------------------------------------------------------------- +Mon Jul 14 17:46:14 CEST 2014 - ma@suse.de + +- refreshService: add option to force repo status reset +- Strip local filenames and args from URL. +- version 14.26.0 (26) + +------------------------------------------------------------------- +Fri Jul 11 13:42:43 CEST 2014 - ma@suse.de + +- Support RepoInfo content keywords (FATE#316287) +- fix parsing repomd.xml twice +- version 14.25.0 (23) + +------------------------------------------------------------------- +Wed Jun 11 07:36:48 CEST 2014 - ma@suse.de + +- Patch: add isCategory/isSeverity convenience +- If available provide info in ServiceException +- version 14.24.0 (23) + +------------------------------------------------------------------- +Wed Jun 4 11:49:32 CEST 2014 - ma@suse.de + +- Cleanup orphanded service repos on the fly (bnc#649846) +- Service refresh must not attempt to modify plugin services +- version 14.23.0 (23) + +------------------------------------------------------------------- +Wed May 28 13:41:22 CEST 2014 - ma@suse.de + +- Fix service methods to throw ServiceException, not RepoException. +- version 14.22.0 (22) + +------------------------------------------------------------------- +Tue May 27 16:31:21 CEST 2014 - ma@suse.de + +- Let ServiceRefresh en-/disable repos with respect to previous state + and user modifications. +- RepoindexFileReader: support variable substitution +- Parse optional autorefresh attribute from repoindex.xml +- version 14.21.0 (20) + +------------------------------------------------------------------- +Wed May 14 13:52:38 CEST 2014 - ma@suse.de + +- Add DownloadResolvableReport::infoInCache +- Adjust transfer timeout settings (bnc#877405) +- Fix computation of update candidate (bnc#834858) +- version 14.20.0 (20) + +------------------------------------------------------------------- +Thu May 8 18:54:25 CEST 2014 - ma@suse.de + +- KeyRingReport: New infoVerify callback showing the trusted key + that will be used for verification. +- version 14.19.0 (19) + +------------------------------------------------------------------- +Sun May 4 01:15:49 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 1 01:15:38 CEST 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Apr 28 15:34:44 CEST 2014 - ma@suse.de + +- Derive initial AutoInstalled file from history +- Target: maintain AutoInstalled database file +- version 14.18.0 (17) + +------------------------------------------------------------------- +Tue Apr 15 17:03:30 CEST 2014 - ma@suse.de + +- Factor out CommitPackageCache for standalone usage. (Fate#317077) +- version 14.17.5 (17) + +------------------------------------------------------------------- +Fri Apr 11 16:16:11 CEST 2014 - ma@suse.de + +- history: log %posttrans errors and output +- adapt to libsolv cannges +- version 14.17.4 (17) + +------------------------------------------------------------------- +Fri Apr 4 14:29:13 CEST 2014 - ma@suse.de + +- Log warning if baseproduct symlink is dangling or missing +- version 14.17.3 (17) + +------------------------------------------------------------------- +Thu Apr 3 19:18:48 CEST 2014 - ma@suse.de + +- RepoManager: Fix RepoStatus computation and refresh of PLAINDIR repos. +- Recreate solv file caches if content may change even if raw metadata + are unchanged (here: new pattern, product and application data). +- version 14.17.2 (17) + +------------------------------------------------------------------- +Wed Apr 2 18:09:47 CEST 2014 - ma@suse.de + +- CpeId: Basic functionality incl. matching +- New SetRelationMixin +- version 14.17.1 (17) + +------------------------------------------------------------------- +Mon Mar 31 10:23:42 CEST 2014 - ma@suse.de + +- Use dummy licenses in test data (bnc#862471) +- Install zypp-NameReqPrv helper for evaluating testcases. +- version 14.17.0 (17) + +------------------------------------------------------------------- +Tue Mar 18 14:55:11 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Feb 26 15:06:06 CET 2014 - ma@suse.de + +- Ignore failed-eject-exception on media change (bnc#865705) +- version 14.16.1 (16) + +------------------------------------------------------------------- +Tue Feb 25 13:42:13 CET 2014 - ma@suse.de + +- Remove duplicate code detecting known kinds and move it to + ResKind::explicitBuiltin. +- version 14.16.0 (16) + +------------------------------------------------------------------- +Sun Feb 23 21:52:55 CET 2014 - ma@suse.de + +- Optionally exclude suggested packages from pattern content (bnc#857671) +- Fix pattern content for auto-pattens (bnc#864087) +- Don't report missing filelists for non-packages (bnc#864314) +- adapt to new rpm weak dependency tags +- version 14.15.0 (15) + +------------------------------------------------------------------- +Fri Feb 14 13:51:46 CET 2014 - ma@suse.de + +- Provide ContentIdentifier of required update repositories in Product + (Fate#316160) +- Support CpeId in Repository and Product attributes (Fate#316160) +- Add API for retrieving repository ContentRevision and ContentIdentifier + (Fate#316160) +- version 14.14.0 (14) + +------------------------------------------------------------------- +Thu Feb 13 10:28:24 CET 2014 - ma@suse.de + +- Adjust solver defaults to changed soft lock handling (bnc#863275) +- Avoid confusing solver decisions by not storing soft locks (bnc#863275) +- version 14.13.0 (13) + +------------------------------------------------------------------- +Tue Feb 11 21:22:58 CET 2014 - ma@suse.de + +- Add Product::endOfLife attribute (Fate#316172) +- Let Product::shortName fallback to name. +- Remove license text from test data (bnc#862471) +- version 14.12.0 (12) + +------------------------------------------------------------------- +Sun Feb 2 01:13:59 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Jan 31 19:09:28 CET 2014 - ma@suse.de + +- Introduce new solvable kind: Application (as provided by appdata.xml) +- version 14.11.0 (7) + +------------------------------------------------------------------- +Fri Jan 31 17:37:29 CET 2014 - ma@suse.de + +- String helper for printing indented text. +- Offer translated names for dependency types. +- version 14.10.0 (7) + +------------------------------------------------------------------- +Thu Jan 30 01:13:40 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Jan 29 10:28:16 CET 2014 - ma@suse.de + +- No fileconflict check if DownloadOnly. +- version 14.9.0 (7) + +------------------------------------------------------------------- +Sat Jan 25 17:07:45 CET 2014 - ma@suse.de + +- Collect and execute %posttrans scripts delayed (Fate#313506) +- BuildRequire libsolv implementing (Fate#309385) +- version 14.8.0 (7) + +------------------------------------------------------------------- +Fri Jan 24 11:26:52 CET 2014 - ma@suse.de + +- Patterns are no longer pseudo installed (Fate#309385) +- version 14.7.0 (7) + +------------------------------------------------------------------- +Fri Jan 24 08:41:13 CET 2014 - ma@suse.de + +- Check for file conflicts in commit (bnc#673720) +- Add asUserSting: human readable (translated) string representation +- Add file conflict detection during commit (bnc#673720) +- Add Transaction::installedResult +- version 14.6.0 (6) + +------------------------------------------------------------------- +Mon Jan 20 17:14:48 CET 2014 - ma@suse.de + +- Fix cleanup code removing the @System solv file. (bnc#853065) +- Fix missing priority in RepoInfo::dumpAsXML (bnc#855845) +- version 14.5.0 (4) + +------------------------------------------------------------------- +Tue Jan 14 18:38:49 CET 2014 - ma@suse.de + +- Improve ProgressData reporting. +- Allow xml::escape directly dumping to a stream. +- Add support for repo authentication using SSL client certificates + (bnc#683914) +- Enhance Queue to perform COW +- fix documentation +- version 14.4.0 (4) + +------------------------------------------------------------------- +Thu Jan 9 01:13:40 CET 2014 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Dec 13 19:36:34 CET 2013 - ma@suse.de + +- Polish DiskUsageCounter +- Add Bitmap type (aka sat::Map) +- Remove obsolete DiskUsage class +- version 14.3.0 (3) + +------------------------------------------------------------------- +Thu Dec 12 18:01:18 CET 2013 - ma@suse.de + +- Fix disk usage computation for single packages (bnc#852943) +- version 14.2.1 (2) + +------------------------------------------------------------------- +Wed Dec 4 12:54:30 UTC 2013 - jreidinger@suse.com + +- Drop package-manager script as it is already deprecated and + packagekit usage in desktop invalidates it. If someone really + need it, then place it to proper top level package which can + decide what GUI is proper for given task. + +------------------------------------------------------------------- +Wed Nov 20 16:32:30 CET 2013 - ma@suse.de + +- Extend commit plugin to send the transaction list (Fate#316203) +- Add base/Json.h: JSON encoder for e.g. sending data to plugins +- Re-evaluate dropped packages list on upgrade, even if product + remains unchanged (bnc#849251). +- Add ppc64le architecture +- Add m68k architecture +- version 14.2.0 (2) + +------------------------------------------------------------------- +Fri Oct 25 14:21:31 CEST 2013 - ma@suse.de + +- Always properly initialize pool storage (bnc#846565) +- version 14.1.1 (0) + +------------------------------------------------------------------- +Thu Oct 17 17:57:54 CEST 2013 - ma@suse.de + +- Add Package isCached and cachedLocation methods +- fixed PluginFrame::hasKey +- version 14.1.0 (0) + +------------------------------------------------------------------- +Thu Oct 10 01:13:48 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Oct 6 01:13:51 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Oct 3 01:14:59 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Oct 2 19:25:58 CEST 2013 - ma@suse.de + +- fix handling symlinks in export pathname on NFSv4 (bnc#804544) +- Bump major version for Factory + 13.1 is continued on SuSE-Code-13_1-Branch +- version 14.0.0 (0) + +------------------------------------------------------------------- +Sun Sep 29 01:15:02 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Sep 22 01:14:26 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Sep 18 17:06:06 CEST 2013 - ma@suse.de + +- Allow multiversionSpec manipulation in ZConfig +- Fix string hexdecoding +- Avoid parsing gpg subkeys but still parse multiple keys +- version 13.7.0 (6) + +------------------------------------------------------------------- +Sun Sep 15 01:14:55 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 12 01:15:29 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 5 01:13:43 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Sep 2 17:04:37 CEST 2013 - ma@suse.de + +- Avoid parsing gpg subkeys +- Use explicit operator bool in TmpPath +- Must keep legacy rpm level flag (bnc#838039) +- version 13.6.0 (6) + +------------------------------------------------------------------- +Sun Sep 1 01:14:03 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 29 01:13:44 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Aug 27 19:10:37 CEST 2013 - ma@suse.de + +- remove deprecated methods +- fix key expiry date parsing (bnc#828672) +- Provide additional keys data in case the ASCII armored blob + containes multiple keys +- No rpmdb key import in readony mode (bnc#828672) +- Fix rpmdb key import/export (bnc#828672) +- Reduce amount of gpg calls when importing/exporting keys. +- Add public accessible PublicKeyData/PublicKeyScanner classes +- fix ASCII armored PublicKey parsing (bnc#828672) +- fix typo (bnc#761985) +- Fix multiversion update candidate to respect an installed objects + arch and vendor (bnc#820444) +- fix logfile truncation introduced by previous fix for (bnc#825490) +- Swig can't handle move constructor +- Workaround bnc#819354 by executing rpm in /. (bnc#827609) +- Try to detect Arch_ppc64p7 (requires glibc-2.16: getauxval) +- Fix file probing via tftp:// (bnc#803316) +- Add armv7hl to armv6hl compat to be in sync with libsolv. +- Support for armv6hl +- version 13.5.0 (5) + +------------------------------------------------------------------- +Thu Aug 22 01:13:25 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Aug 18 01:13:20 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 15 01:13:27 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 8 01:13:27 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Aug 4 01:13:59 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 1 01:13:52 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 25 01:13:40 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 18 01:13:43 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Jul 14 01:13:38 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 11 01:13:49 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Jun 21 20:24:39 CEST 2013 - ma@suse.de + +- Fix testcases failing if local pathnames contain umlauts +- Pathname: add move constructor and fix assign +- Set logfile permission upon file creation only (bnc#825490) +- Add arch ppc64p7 +- version 13.4.0 (4) + +------------------------------------------------------------------- +Tue Jun 11 11:37:48 CEST 2013 - ma@suse.de + +- Speedup scanning for modaliases (bnc#824110) +- version 13.3.0 (2) + +------------------------------------------------------------------- +Sun May 26 01:13:15 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 23 01:13:13 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 16 12:22:48 CEST 2013 - ma@suse.de + +- Remove deprecated old stuff (aria2 support, + old InstallOrder, old History parser) +- version 13.2.0 (2) + +------------------------------------------------------------------- +Thu May 16 01:13:47 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun May 12 01:13:39 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 9 01:13:54 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 2 11:07:52 CEST 2013 - ma@suse.de + +- Discourage using SafeBool in favor of explicit operator bool +- version 13.1.0 (1) + +------------------------------------------------------------------- +Mon Apr 29 10:41:46 CEST 2013 - ma@suse.de + +- Testsuite: Workaround boost::thread being not header only since + boost-1.50 (boost ticket 7085) +- Adaptions to smart_pointer changes in boost-1.53; mainly introduce + explicit operator bool; constructible and comparable with nullptr_t. +- Bump major version for Factory + 12.x is continued on SuSE-Code-12_3-Branch +- version 13.0.0 (0) + +------------------------------------------------------------------- +Sun Apr 28 01:14:07 CEST 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Apr 5 14:26:35 CEST 2013 - ma@suse.de + +- added new fuction zypp::ZYpp::provideSrcPackage +- Treat opensuse-education as separate vendor (bnc#812608) +- AArch64 support +- version 12.11.0 (0) + +------------------------------------------------------------------- +Wed Mar 27 12:31:17 CET 2013 - ma@suse.de + +- added tftp-support (bnc#803316) +- version 12.10.1 (0) + +------------------------------------------------------------------- +Tue Mar 26 13:06:21 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Mar 21 01:13:45 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Mar 10 01:14:01 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Mar 7 14:13:42 CET 2013 - ma@suse.de + +- Adapt to libsolv dataiterator fixes + (returning random data in some cases) +- Require and adapt to changes in libsolv-0.3.0 +- version 12.10.0 (0) + +------------------------------------------------------------------- +Thu Mar 7 01:13:25 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Mar 3 01:15:52 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Feb 27 08:41:18 CET 2013 - ma@suse.de + +- Rephrase error message if 'lsof' is not installed (bnc#694427) +- version 12.9.0 (0) + +------------------------------------------------------------------- +Fri Feb 15 12:49:18 CET 2013 - ma@suse.de + +- Handle dangling update script symlinks in instsys. (bnc#803751) +- version 12.8.1 (0) + +------------------------------------------------------------------- +Thu Feb 14 01:13:28 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Feb 7 01:16:50 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Feb 4 12:35:51 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Jan 22 11:06:55 CET 2013 - ma@suse.de + +- make multicurl suppress progress reports for the metalink download +- work around libcurl bug that sometimes gives us old values in the + progress callback +- version 12.8.0 (0) + +------------------------------------------------------------------- +Fri Jan 18 14:07:50 CET 2013 - ma@suse.de + +- Reduce logging +- MediaMultiCurl: throw AbortRequestException if aborted by user +- version 12.7.0 (0) + +------------------------------------------------------------------- +Sun Jan 13 01:13:23 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Jan 6 01:13:17 CET 2013 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Dec 27 01:13:27 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Dec 17 13:31:15 CET 2012 - ma@suse.de + +- Add NamedValue<_Tp>: Simple value<>name mapping supporting aliases +- Enable zypper to remove zypp locks without evaluating the + query (bnc#792901) +- Configure curl to "not fix the BEAST attack" (bnc#779177) +- version 12.6.0 (0) + +------------------------------------------------------------------- +Sun Dec 16 01:13:16 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Dec 3 14:31:59 CET 2012 - ma@suse.de + +- HistoryLogReader: new HistoryLogData based API for parsing the new + history file entries (fate#312521) + The old HistoryItem based API is deprecated but will + still be available for a while if you compile with + -DWITH_DEPRECATED_HISTORYITEM_API. +- Write userdata string to history log (fate#312521) +- Add HistoryLogReader testcases +- Adapt to libsolv 'medianr'-changes +- version 12.5.0 (0) + +------------------------------------------------------------------- +Thu Nov 22 01:14:42 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Nov 18 01:13:44 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Nov 13 15:40:10 CET 2012 - ma@suse.de + +- Forward userdata string to commit plugins in BEGINPLUGIN (fate#312521) +- Extend ZConfig to store a user defined string value (fate#312521) +- Add SIGSEGV handler trying to log a stack trace +- Add zypp::dumpBacktrace to dump current stack trace to a stream. +- Use gettext plural handling (bnc#784666) +- version 12.4.0 (0) + +------------------------------------------------------------------- +Sun Nov 4 01:13:21 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Oct 24 10:40:38 CEST 2012 - ma@suse.de + +- Add simple sysconfig::write (bnc#766598) +- For installed products also filelists when trying to find the buddy + (bnc#784900) +- Provide information whether product license needs to be accepted. +- version 12.3.0 (0) + +------------------------------------------------------------------- +Thu Oct 18 01:13:43 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Oct 7 01:13:41 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Oct 1 11:00:42 CEST 2012 - ma@suse.de + +- Enable multiversion kernel and set multiversion.kernels in + /etc/zypp/zypp.conf to keep the latest, latest-1 and the running. +- Fix typo (bnc#782801) +- Relax evaluation of patch category tags (case insensitive) + +------------------------------------------------------------------- +Sun Sep 30 01:13:18 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Sep 16 01:14:34 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Sep 12 10:28:00 CEST 2012 - ma@suse.de + +- Add str::commonPrefix +- version 12.2.0 (0) + +------------------------------------------------------------------- +Sun Sep 9 01:13:25 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Sep 5 11:56:54 CEST 2012 - gs@suse.de + +- Provide Target::reload() +- version 12.1.0 (0) + +------------------------------------------------------------------- +Sun Aug 26 01:13:31 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 23 01:13:47 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Aug 19 01:14:11 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 16 01:13:43 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Aug 10 12:53:47 CEST 2012 - ma@suse.de + +- Implement $ZYPP_LOCK_TIMEOUT: number of seconds to wait for a + zypplock becoming available (bnc#772965) +- Unify update-scripts with same content(md5sum) (bnc#773575) +- version 12.0.1 (0) + +------------------------------------------------------------------- +Thu Aug 9 01:15:12 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 2 11:55:00 CEST 2012 - ma@suse.de + +- set $ZYPP_IS_RUNNING during commit +- Bump major version for Factory + 11.x is continued on SuSE-Code-12_2-Branch +- version 12.0.0 (0) + +------------------------------------------------------------------- +Thu Aug 2 01:14:11 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Aug 1 15:32:40 CEST 2012 - ma@suse.de + +- Fixed typo (bnc#773467) +- Erase any old repo instance from pool when (re)loading from cache +- filter zero sized devices in disk usage counter(bnc#769819) +- fix isSoftLocked computation +- fix possibly reporting timeout as "aborted by user" (bnc#665327) +- do not fork the uuidgen program, use kernel interface instead +- remove obsolete hicolor-icon-theme BuildRequires +- version 11.7.0 (6) + +------------------------------------------------------------------- +Sun Jul 29 01:13:31 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 19 01:13:43 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Jul 1 01:13:31 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jun 28 01:14:27 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Jun 25 15:23:10 CEST 2012 - ma@suse.de + +- zypp.conf:servicesdir is ignored (bnc#765528) +- allow libcurl to take proxy from environment iff proxy is not + configured or disallowed (bnc#745404) +- version 11.6.3 (6) + +------------------------------------------------------------------- +Sun Jun 24 01:14:32 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jun 14 01:13:35 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Jun 8 15:57:22 CEST 2012 - ma@suse.de + +- Adjust weaklock fix + +------------------------------------------------------------------- +Fri Jun 8 14:16:15 CEST 2012 - ma@suse.de + +- Fix processing of weak locks (bnc#749418, bnc#765164) +- [valgrind] don't dereference if we may be past the end of the repositories. +- add armv7hl workaround for Adrian +- version 11.6.2 (6) + +------------------------------------------------------------------- +Sun Jun 3 01:14:09 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 31 10:07:37 UTC 2012 - dmacvicar@suse.com + +- fix an invalid read revealed by valgrind in + RepositoryIterator::increment() + +------------------------------------------------------------------- +Sun May 20 01:13:30 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 17 01:15:25 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun May 13 01:14:15 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue May 8 13:39:22 CEST 2012 - ma@suse.de + +- Use ld version script to hide symbols outside zypp namespace (bnc#755324) +- remove base/Deprecated.h (macros now in APIConfig.h) +- Disribute Easy.h in APIConfig.h +- Add APIConfig.h providing ZYPP_API and ZYPP_LOCAL macros +- version 11.6.0 (6) + +------------------------------------------------------------------- +Fri May 4 11:18:17 CEST 2012 - ma@suse.de + +- build with gcc-4.7 (bnc#755324) +- version 11.5.0 (5) + +------------------------------------------------------------------- +Wed Apr 25 18:50:20 CEST 2012 - ma@suse.de + +- Fix lost device info when mounting CD/DVD + +------------------------------------------------------------------- +Sun Apr 22 01:15:46 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Apr 19 10:19:05 CEST 2012 - ma@suse.de + +- Always consider (block) devices passed as url option (bnc#755815) + +------------------------------------------------------------------- +Thu Apr 19 01:14:57 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Apr 18 18:38:06 CEST 2012 - ma@suse.de + +- Fix install progress hopping back and forth +- Try to create a missing destination dir before switching to tmp + space (bnc#755239) + +------------------------------------------------------------------- +Mon Apr 16 14:52:35 CEST 2012 - ma@suse.de + +- ResStatus: add 'unneeded' bit (determined by solver) +- Force using gcc-4.6 until it builds with 4.7 +- Support multiversion definitions being read from files in /etc/zypp/multiversion.d. +- Workaround doxygen SEGV and accept incomplete docs (until bnc#755402 is fixed) +- Rename zypp::sat::AttrMatcher to zypp::StrMatcher (base/StrMatcher.h) +- Support (source)package download by non-root user (bnc#755239) +- Delay construction of ZYppGlobalLock until its actually needed (bnc#575096) +- Fix buddy handling in solver results +- Simplify Selectable::multiversionInstall +- Don't cache defaultCandidate as it depends on solver::allowVendorChange flag (bnc#754286) +- version 11.4.0 (4) + +------------------------------------------------------------------- +Tue Apr 10 12:11:37 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Apr 8 01:13:24 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Apr 5 01:16:21 CEST 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Mar 26 14:47:59 CEST 2012 - ma@suse.de + +- Cleanup orphaned media attach points (bnc#751221) +- Show max support status if package is in multiple repos (bnc#735841) +- Parse proxy user/pass from url (bnc#752497) +- Add CMake option to disable libproxy usage and disable it on SLE. (bnc#752500) +- version 11.3.0 (1) + +------------------------------------------------------------------- +Thu Mar 15 00:31:25 CET 2012 - ma@suse.de + +- Add API for patch severity (bnc#733723, FATE#312633) +- version 11.2.0 (1) + +------------------------------------------------------------------- +Tue Mar 13 13:04:48 CET 2012 - ma@suse.de + +- Force libproxy into using "/etc/sysconfig/proxy" if it exists (bnc#679322) +- Apply soft locks by name and not per package (bnc#749418) +- version 11.1.1 (1) + +------------------------------------------------------------------- +Fri Feb 3 13:18:01 CET 2012 - ma@suse.de + +- Add Fetcher support for CHECKSUMS file (replaceing SHA1SUMS) (bnc#744302) +- Build with -fvisibility-inlines-hidden +- CheckAccessDeleted: avoid duplicate entries for the same PID (bnc#716972) +- Correctly use user:pass directly embedded in a proxy url (bnc#740764) +- new sat::Map - Libsolv (bit)Map wrapper. +- always set splitprovides to true now that libsolv handles them better +- version 11.1.0 (1) + +------------------------------------------------------------------- +Thu Feb 2 01:14:17 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Jan 29 01:14:28 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Jan 22 01:13:30 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Jan 10 18:31:41 CET 2012 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Dec 23 14:51:25 CET 2011 - ma@suse.de + +- Adapt Repository iteration to libsolv changes. +- Add sat::Pool tests +- Fix Flags<> api to be more consistent and add testcase. +- Set min_curl_version 7.19.4 (bnc#735284) +- Doc: add some words about 'Solver - Vendor protection' +- version 11.0.0 (0) + +------------------------------------------------------------------- +Thu Dec 1 01:13:37 CET 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Nov 28 18:08:42 CET 2011 - ma@suse.de + +- Fix and optimize Pathname ctor and provide testcases (bnc#721128) +- Open all file descriptors with O_CLOEXEC to avoid leaks and races +- Some improvements to the services documentation +- Fix RW_pointer comparison with underlying smart pointer type. +- version 10.3.5 (3) + +------------------------------------------------------------------- +Sun Nov 27 01:13:10 CET 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Nov 17 01:13:15 CET 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Nov 11 13:38:42 CET 2011 - ma@suse.de + +- Try to find and use some CD/DVD device even if HAL/UDEV detection + fails (bnc#724807) +- Static initialization problem fixes (by Harald Fernengel) +- version 10.3.4 (3) + +------------------------------------------------------------------- +Mon Nov 7 15:45:28 CET 2011 - ma@suse.de + +- Don't use proxy if disabled (bnc#696805) +- version 10.3.3 (3) + +------------------------------------------------------------------- +Mon Nov 7 13:49:44 UTC 2011 - dimstar@opensuse.org + +- Add pkg-config BuildRequires: We fail to detect libproxy due to + the missing pkg-config. Additionally, we have a .pc file + ourselfes, which we do not get the provides for [bnc#696805] + +------------------------------------------------------------------- +Thu Nov 3 14:58:42 CET 2011 - ma@suse.de + +- Let RepoInfo::keepPackages properly default to FALSE (bnc#727385) +- version 10.3.2 (3) + +------------------------------------------------------------------- +Thu Nov 3 01:13:12 CET 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Oct 30 01:14:41 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Oct 27 01:14:10 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Oct 24 13:35:56 CEST 2011 - ma@suse.de + +- Explicitly include textLocale in package translation download + +------------------------------------------------------------------- +Mon Oct 24 09:37:31 CEST 2011 - ma@suse.de + +- Update libversion info (due to ABI change in 10.2.0 (bnc#725407) +- version 10.3.1 (3) + +------------------------------------------------------------------- +Sun Oct 23 01:13:11 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Oct 21 11:47:39 CEST 2011 - ma@suse.de + +- Add zypp.conf option repo.refresh.locales: A list of locales for + which translated package descriptions should be downloaded if + available. +- Explixitly set CURLOPT_PROXYAUTH +- version 10.3.0 (1) + +------------------------------------------------------------------- +Tue Oct 18 16:45:13 CEST 2011 - ma@suse.de + +- Add arch armv7tnhl and armv7thl +- Fix RepoVariablesReplacer to compute substitution values on demand only +- PathInfo::hardlinkCopy: fix handling cross-device links +- version 10.2.0 (1) + +------------------------------------------------------------------- +Sun Oct 16 01:13:37 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Oct 13 11:50:26 CEST 2011 - ma@suse.de + +- Must not differ between type nfs and nfs4 when checking the mount + table (bnc#710269) +- version 10.1.1 (1) + +------------------------------------------------------------------- +Thu Oct 13 01:13:37 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Oct 11 15:20:43 CEST 2011 - ma@suse.de + +- Switch to using libsolv instead of satsolver +- version 10.1.0 (1) + +------------------------------------------------------------------- +Sun Oct 9 01:13:16 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Oct 6 01:14:00 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Sep 20 09:57:04 CEST 2011 - ma@suse.de + +- Bump major version for Factory; 9.x is continued on SLE-11-SP2-Branch +- version 10.0.0 (0) + +------------------------------------------------------------------- +Tue Sep 13 10:51:53 CEST 2011 - ma@suse.de + +- Enhance Selectable API +- version 9.11.0 (8) + +------------------------------------------------------------------- +Sun Sep 11 01:18:59 CEST 2011 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Sep 11 01:13:12 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 8 01:19:28 CEST 2011 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 8 01:14:08 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Sep 7 12:38:23 CEST 2011 - ma@suse.de + +- Explicitly require rpm. +- version 9.10.2 (8) + +------------------------------------------------------------------- +Sun Sep 4 01:16:54 CEST 2011 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Sep 4 01:13:27 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Sep 1 01:13:36 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Aug 29 10:51:04 CEST 2011 - ma@suse.de + +- Extend mount entry comparison fix (bnc#710269) +- version 9.10.2 (8) + +------------------------------------------------------------------- +Thu Aug 25 01:17:06 CEST 2011 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Aug 22 13:57:16 CEST 2011 - ma@suse.de + +- Update sle-zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Aug 14 01:13:21 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Aug 7 01:16:07 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Aug 5 15:20:07 CEST 2011 - ma@suse.de + +- Attempt to fix smb mount entry comparison (bnc#710269) +- version 9.10.1 (8) + +------------------------------------------------------------------- +Thu Aug 4 14:54:47 CEST 2011 - ma@suse.de + +- Allow to turn Resolvers upgrade mode on and off (bnc#709480) +- Fix reading of integer arrays from rpm headers (bnc#709716) +- version 9.10.0 (8) + +------------------------------------------------------------------- +Thu Aug 4 01:14:00 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jul 28 13:04:10 CEST 2011 - ma@suse.de + +- Evaluate CURLINFO_CONDITION_UNMET on zero sized successful transfers, + if compiled against libcurl-7.19.4 or above. (bnc#692260) +- version 9.9.2 (8) + +------------------------------------------------------------------- +Mon Jul 25 16:20:37 CEST 2011 - ma@suse.de + +- Always read /proc/mounts when looking for mounted media (bnc#705893) +- version 9.9.1 (8) + +------------------------------------------------------------------- +Fri Jul 22 13:12:34 CEST 2011 - ma@suse.de + +- MediaUserAuth: Do not expose libcurl header files. +- version 9.9.0 (8) + +------------------------------------------------------------------- +Mon Jul 18 11:33:25 CEST 2011 - ma@suse.de + +- More initialize parser structure fixes. (bnc#705181) +- version 9.8.7 (8) + +------------------------------------------------------------------- +Fri Jul 15 15:15:01 CEST 2011 - ma@suse.de + +- Check for /etc/sysconfig/storage changes before solving (bnc#702365) +- version 9.8.6 (8) + +------------------------------------------------------------------- +Fri Jul 15 13:58:53 CEST 2011 - ma@suse.de + +- Properly initialize parser structures (bnc#705181) +- version 9.8.5 (8) + +------------------------------------------------------------------- +Thu Jul 7 15:53:17 CEST 2011 - ma@suse.de + +- Fix tests for available libcurl version. +- version 9.8.4 (8) + +------------------------------------------------------------------- +Thu Jul 7 01:13:47 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Jul 4 10:41:42 CEST 2011 - ma@suse.de + +- Make fix for bnc#702576 more robust. +- Enhance fix for bnc#699435. Return an error if download in advance + failed to provide all packages, so zypper does not silently quit. +- version 9.8.3 (8) + +------------------------------------------------------------------- +Thu Jun 30 01:13:43 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Jun 29 12:23:24 CEST 2011 - ma@suse.de + +- Always compute transaction from pool (bnc#702576) +- version 9.8.2 (8) + +------------------------------------------------------------------- +Tue Jun 28 16:04:50 CEST 2011 - ma@suse.de + +- Add feature provides for supported plugins. + +------------------------------------------------------------------- +Tue Jun 21 10:44:47 CEST 2011 - dmacvicar@suse.de + +- Add configuration template for automatic kernel + purge (feature#312018) to zypp.conf + +------------------------------------------------------------------- +Tue Jun 14 13:38:00 CEST 2011 - ma@suse.de + +- Fix download loop to skip non-install actions. (bnc#699435) +- version 9.8.1 (8) + +------------------------------------------------------------------- +Sun Jun 12 01:13:36 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Jun 9 09:34:51 CEST 2011 - ma@suse.de + +- Fix missing return value. + +------------------------------------------------------------------- +Wed Jun 8 12:58:54 CEST 2011 - ma@suse.de + +- Simplify ZYppCommitResult by using filtered Transaction::action_iterator. +- version 9.8.0 (8) + +------------------------------------------------------------------- +Tue Jun 7 14:12:35 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Jun 7 12:42:20 CEST 2011 - ma@suse.de + +- Fix transaction ORDER_BY_MEDIANR. +- version 9.7.0 (5) + +------------------------------------------------------------------- +Fri Jun 3 23:12:05 CEST 2011 - ma@suse.de + +- Basic commit plugins implemented. They may be used to implement pre/post + commit actions like taking file system snapshots (fate#303699) +- version 9.6.0 (5) + +------------------------------------------------------------------- +Tue May 31 17:27:45 CEST 2011 - ma@suse.de + +- Do commit based on sat::Transaction. +- version 9.5.0 (5) + +------------------------------------------------------------------- +Tue May 31 12:09:17 CEST 2011 - ma@suse.de + +- Assert rpm database directory is created before rpmtsInitDB is + called (bnc#697115) + +------------------------------------------------------------------- +Tue May 31 11:46:57 CEST 2011 - dheidler@suse.de + +- fix var definition order in PackageProvider +- fix operator~ return datatype for flags (ctor is explicit) +- add method interactiveFlags to Patch describing what makes it + interactive +- version 9.4.0 (3) + +------------------------------------------------------------------- +Tue May 31 10:12:12 CEST 2011 - ma@suse.de + +- Recommend 'lsof' (for zypper ps) (bnc#694427, bnc#684466) + +------------------------------------------------------------------- +Mon May 30 17:14:14 CEST 2011 - dheidler@suse.de + +- Switch patch interactive-check to flags +- version 9.3.0 (3) + +------------------------------------------------------------------- +Sun May 29 01:13:42 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri May 27 17:02:05 CEST 2011 - ma@suse.de + +- fix specfile to handle sles translations if available + +------------------------------------------------------------------- +Fri May 27 09:51:13 CEST 2011 - ma@suse.de + +- Avoid using #elifdef directive. + +------------------------------------------------------------------- +Thu May 26 01:13:43 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed May 25 09:22:28 CEST 2011 - ma@suse.de + +- Add a fallback gnome-packagekit updater in package-manager (bnc#667504) +- Backport changelog entries from SLE11-SP1 branch. Bugs mentioned here + were either fixed without bnc# or do not apply to this branch. This is + to make the changelog checker happy: + - Set proper defaults for service repos (bnc#673943) + +------------------------------------------------------------------- +Tue May 24 12:43:32 CEST 2011 - dheidler@suse.de + +- add option ignore_reboot_flag to Patch::interactive (bnc#665853) +- version 9.2.0 (2) + +------------------------------------------------------------------- +Mon May 23 16:12:32 CEST 2011 - dheidler@suse.de + +- respect patch content license when determinating interactive status +- version 9.1.2 (1) + +------------------------------------------------------------------- +Mon May 23 12:05:10 CEST 2011 - ma@suse.de + +- More rpm-4.9 fixes +- Disable rpm V3toV4 conversion while not working with rpm 4.9 + +------------------------------------------------------------------- +Sun May 22 01:14:21 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri May 20 17:11:10 CEST 2011 - ma@suse.de + +- Fix for rpm-4.9 +- version 9.1.1 (1) + +------------------------------------------------------------------- +Fri May 20 13:43:38 CEST 2011 - ma@suse.de + +- Disable use if rpm-4.4 legacy interface (dropped in 4.9) (bnc#691089) +- Fix poolquery handling repo restrictions correctly. (bnc#661976) +- version 9.1.0 (1) + +------------------------------------------------------------------- +Wed May 18 14:10:20 CEST 2011 - dmacvicar@suse.de + +- Allow MediaCD to build against HAL or nothing + if udev is not present + +------------------------------------------------------------------- +Mon May 16 14:42:09 CEST 2011 - dmacvicar@suse.de + +- forward port all changes to make it build in Code10 + +------------------------------------------------------------------- +Mon May 16 11:51:51 UTC 2011 - dmacvicar@suse.de + +- make -Werror=format-security optional and used only if + supported + +------------------------------------------------------------------- +Sun May 15 01:13:47 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu May 12 01:13:54 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri May 6 13:22:35 CEST 2011 - dheidler@suse.de + +- delete old metadata temp directories +- version 9.0.3 (0) + +------------------------------------------------------------------- +Wed Apr 27 17:17:00 CEST 2011 - dheidler@suse.de + +- fix max_concurrent_connections option in MultiCurl (bnc#596089) +- version 9.0.2 (0) + +------------------------------------------------------------------- +Sun Apr 17 01:13:40 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Apr 12 18:49:32 CEST 2011 - dheidler@suse.de + +- check for permissions before writing (fixes bnc#683509) +- version 9.0.1 (0) + +------------------------------------------------------------------- +Tue Apr 5 12:08:27 CEST 2011 - ma@suse.de + +- Switch ResPoolProxy to use multimap in order to allow iteration + of all Selectables of all kinds. +- Add upper/lower_bound iteration to MapKVIterator. +- Add stream output for multimap/set. +- version 9.0.0 (0) + +------------------------------------------------------------------- +Mon Apr 4 15:08:08 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Apr 4 15:04:47 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Apr 4 15:03:55 CEST 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Mar 10 01:13:39 CET 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun Mar 6 01:13:41 CET 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Feb 16 14:24:27 UTC 2011 - dmacvicar@suse.de + +- Do not look for $releasever 's value if there is no variable + in the url: parses product file again and again +- version 8.12.2 (10) + +------------------------------------------------------------------- +Thu Feb 10 16:01:46 CET 2011 - ma@suse.de + +- Remove package-manager.desktop file (bnc#329635) +- version 8.12.1 (10) + +------------------------------------------------------------------- +Tue Jan 25 10:09:22 CET 2011 - ma@suse.de + +- Apply patch introducing armv7nhl:armv7hl + +------------------------------------------------------------------- +Tue Jan 18 12:28:19 UTC 2011 - dmacvicar@suse.de + +- allow for Repo Index Services to set the enabled state of + repositories from the server side. +- Fix priority not being set on reading service indexes +- version 8.12.0 (10) + +------------------------------------------------------------------- +Fri Jan 14 12:45:18 CET 2011 - ma@suse.de + +- Add new ServicePlugin Exceptions. + +------------------------------------------------------------------- +Thu Jan 13 01:13:32 CET 2011 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Dec 23 14:42:02 CET 2010 - dheidler@suse.de + +- add method to check if there are manually configured urls +- version 8.11.0 (10) + +------------------------------------------------------------------- +Thu Dec 23 11:31:22 CET 2010 - dheidler@suse.de + +- create cache directory, if it doesn't exist + when saving mirrorlist +- version 8.10.6 (10) + +------------------------------------------------------------------- +Wed Dec 22 12:38:22 CET 2010 - dheidler@suse.de + +- moved keepPackages code to RepoInfo::Impl +- version 8.10.5 (10) + +------------------------------------------------------------------- +Tue Dec 21 13:29:06 CET 2010 - dheidler@suse.de + +- Fix caching of mirrorlist files +- version 8.10.4 (10) + +------------------------------------------------------------------- +Thu Dec 16 19:46:00 CET 2010 - ma@suse.de + +- Do not export keyring if rpmdb is initialised, but target isn't + (bnc#659494) +- version 8.10.3 (10) + +------------------------------------------------------------------- +Fri Dec 10 17:17:07 CET 2010 - dheidler@suse.de + +- Catch RPM-Exeption when instaling the Distribution (bnc#658714) +- version 8.10.2 (10) + +------------------------------------------------------------------- +Wed Dec 8 14:15:12 CET 2010 - dheidler@suse.de + +- fix retrieval of distributionVersion if target is not initialized +- MultiCurl: make sure the server responds with "partial content", + fixes corrupt downloads if the metalink file contains no checksums +- version 8.10.1 (10) + +------------------------------------------------------------------- +Wed Dec 1 17:39:16 CET 2010 - dheidler@suse.de + +- Added ReplacerVar caching in RepoInfo +- Automaticly remove empty mirrorlist-files +- version 8.10.0 (10) + +------------------------------------------------------------------- +Tue Nov 30 17:11:32 CET 2010 - dheidler@suse.de + +- Added MirrorList caching +- version 8.9.0 (7) + +------------------------------------------------------------------- +Mon Nov 29 12:31:37 CET 2010 - ma@suse.de + +- Icons for libzypp should go into desktop-data. (bnc#329635) +- version 8.8.2 (7) + +------------------------------------------------------------------- +Wed Nov 24 11:55:59 CET 2010 - ma@suse.de + +- Properly handle FTP response 550. (bnc#645747) +- version 8.8.1 (7) + +------------------------------------------------------------------- +Fri Nov 19 11:24:39 CET 2010 - mls@suse.de + +- fix access of freed memory in MultiCurl (bnc#654600) + +------------------------------------------------------------------- +Sun Nov 7 01:13:39 CET 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Nov 3 16:06:46 CET 2010 - dheidler@suse.de + +- added metalink support +- version 8.8.0 (7) + +------------------------------------------------------------------- +Thu Oct 21 18:15:31 CEST 2010 - ma@suse.de + +- Feed the ProvideFilePolicy progress callback in addition to any + connected media::DownloadProgressReport (bnc#545106) +- version 8.7.1 (7) + +------------------------------------------------------------------- +Wed Oct 13 16:14:13 CEST 2010 - dheidler@suse.de + +- Make MetaLinkParser accept InputStreams +- Make MetaLinkParser accept Pathnames insted of strings +- Fix MetaLinkv4 hash parsing +- Add MetaLinkParser test +- version 8.7.0 (7) + +------------------------------------------------------------------- +Mon Oct 11 17:06:17 CEST 2010 - ma@suse.de + +- Use timeouts in plugin script communication. +- Fix ExternalProgram to correctly remember exit status. +- version 8.6.0 (5) + +------------------------------------------------------------------- +Sun Oct 10 01:13:40 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Oct 8 08:43:02 UTC 2010 - dmacvicar@novell.com + +- fix services not being linked to their file after being + saved + +------------------------------------------------------------------- +Thu Oct 7 09:02:26 CEST 2010 - jkupec@suse.cz + +- Don't use aria2c for FTP (bnc #641328) + +------------------------------------------------------------------- +Wed Oct 6 15:39:59 UTC 2010 - dmacvicar@novell.com + +- implementation for url resolver plugins +- version 8.5.0 (5) + +------------------------------------------------------------------- +Wed Oct 6 16:54:15 CEST 2010 - dheidler@suse.de + +- Use DownloadInHeaps as default, when there is nothing configured + and when the target root is set to "/". (bnc#591476) +- version 8.4.0 (4) + +------------------------------------------------------------------- +Tue Sep 28 17:12:51 CEST 2010 - dheidler@suse.de + +- fixed replacing releasever (for fedora systems) - (bnc#637470) +- version 8.3.0 (0) + +------------------------------------------------------------------- +Fri Sep 24 13:07:25 CEST 2010 - mls@suse.de + +- fix metalink4 parsing [bnc#641484] + +------------------------------------------------------------------- +Thu Sep 23 01:13:45 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Sep 20 15:31:31 UTC 2010 - dmacvicar@novell.com + +- Allow per repository proxy settings like yum does. + Including setting it to _none_ overriding the + system proxy. + Patch from Zhang, Qiang +- version 8.2.1 (0) + +------------------------------------------------------------------- +Fri Sep 10 17:06:34 CEST 2010 - dheidler@suse.de + +- fixed replacing basearch (for fedora systems) - (bnc#637473) +- version 8.2.0 (0) + +------------------------------------------------------------------- +Fri Sep 10 11:57:29 CEST 2010 - ma@suse.de + +- Report download failures in commit result (bnc#431854) +- Fix Solvable::onSystemByUser returning true for uninstalled solvables. +- version 8.1.3 (0) + +------------------------------------------------------------------- +Tue Aug 31 20:01:26 CEST 2010 - ma@suse.de + +- Fix download-only not to omit source packages (bnc#635596) +- version 8.1.2 (0) + +------------------------------------------------------------------- +Thu Aug 26 01:13:38 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Aug 13 12:33:26 UTC 2010 - dmacvicar@novell.com + +- fix basearch url variable +- use the right release package name on fedora + +------------------------------------------------------------------- +Tue Aug 10 13:18:08 CEST 2010 - ma@suse.de + +- MediaDISK: Use blkid to verify disk volumes. (bnc#623226) +- version 8.1.1 (0) + +------------------------------------------------------------------- +Sun Aug 8 01:13:37 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Thu Aug 5 01:13:53 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Aug 3 16:17:04 CEST 2010 - ma@suse.de + +- Fix memory leaks. + +------------------------------------------------------------------- +Mon Aug 2 11:58:57 CEST 2010 - ma@suse.de + +- Enhance PoolItem interface to assist patch classification. (bnc#627316) +- version 8.1.0 (0) + +------------------------------------------------------------------- +Tue Jul 27 15:38:00 CEST 2010 - ma@suse.de + +- Fix bug in PoolQuery::addDependency +- Disable MediaAria and enable MultiCurl as default http/ftp backend. + MultiCurl implements MetaLink and Zsync support using libcurl. In + case of trouble set ZYPP_MULTICURL=0 in the envirionment to disable + the new backend. +- version 8.0.1 (0) + +------------------------------------------------------------------- +Mon Jul 26 17:05:14 CEST 2010 - ma@suse.de + +- Bump heads major version after 11.3 branched away. +- version 8.0.0 (0) + +------------------------------------------------------------------- +Thu Jul 22 01:13:27 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed Jul 7 13:56:49 CEST 2010 - ma@suse.de + +- Add PoolQuery for name, edition AND architecture in one go. (bnc#614362) +- version 7.8.0 (6) + +------------------------------------------------------------------- +Mon Jul 5 13:03:57 CEST 2010 - ma@suse.de + +- Fix requirement to /usr/bin/uuidgen (bnc#613304) + +------------------------------------------------------------------- +Sun Jul 4 01:13:29 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue Jun 29 17:46:13 CEST 2010 - ma@suse.de + +- Fix CURLOPT_MAX_RECV_SPEED_LARGE expecting a curl_off_t argument. + +------------------------------------------------------------------- +Tue Jun 29 10:22:06 CEST 2010 - ma@suse.de + +- Respect zypp.conf policy settings when solving for update. + +------------------------------------------------------------------- +Fri Jun 25 11:35:52 CEST 2010 - ma@suse.de + +- Don't bloat logfile by logging install progess values. + +------------------------------------------------------------------- +Thu Jun 10 01:13:49 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Mon Jun 7 17:52:50 CEST 2010 - ma@suse.de + +- Add missing Date constant declarations. +- version 7.7.5 (6) + +------------------------------------------------------------------- +Mon Jun 7 11:46:58 CEST 2010 - ma@suse.de + +- Prevent against daemons launched in rpm %post, that do not close + their filedescriptors. Original fix was accidentally reverted. + (bnc#174548) +- version 7.7.4 (6) + +------------------------------------------------------------------- +Sun Jun 6 01:13:52 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri Jun 4 17:14:17 CEST 2010 - ma@suse.de + +- Fix default evaluation of recommendations of installed + packages (bnc#605490) +- version 7.7.3 (6) + +------------------------------------------------------------------- +Thu Jun 3 01:14:08 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri May 21 20:00:55 CEST 2010 - ma@suse.de + +- Fix broken IdStringType comparison (bnc#607572) +- version 7.7.2 (6) + +------------------------------------------------------------------- +Thu May 20 21:01:05 CEST 2010 - ma@suse.de + +- Fix packages provided via delta rpm being placed in + the wrong package cache (bnc#607583) +- version 7.7.1 (6) + +------------------------------------------------------------------- +Thu May 20 01:13:49 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Tue May 18 18:02:44 CEST 2010 - ma@suse.de + +- Fix arch detection on sprac (bug #566291) +- Arch: add sparc64v and sparcv9v and armv7l +- RepoManager: refresh repo if last refresh is in the future (bnc#593617) +- version 7.6.1 (6) + +------------------------------------------------------------------- +Mon May 17 15:25:14 CEST 2010 - ma@suse.de + +- Fix package-manager-su to support LXDE (Andrea Florio) (bnc#582235) +- Cleanup spec file (Pavol Rusnak) +- version 7.6.0 (6) + +------------------------------------------------------------------- +Sun May 16 01:13:39 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Wed May 12 19:09:54 CEST 2010 - ma@suse.de + +- Add methods to evaluate gpg geys expiration dates. +- Export all rpmDb keys to the zypp trusted keyring in one go. +- version 7.6.0 (6) + +------------------------------------------------------------------- +Wed May 12 17:35:44 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sun May 9 01:13:45 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Sat May 8 01:13:43 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 + +------------------------------------------------------------------- +Fri May 7 01:13:55 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 (Revision: 54959) + +------------------------------------------------------------------- +Wed May 5 14:49:39 CEST 2010 - ma@suse.de + +- Update zypp-po.tar.bz2 (Revision: 54959) + +------------------------------------------------------------------- +Tue May 4 01:13:43 CEST 2010 - ma@suse.de + +- Update translations. + +------------------------------------------------------------------- +Mon May 3 18:12:36 CEST 2010 - ma@suse.de + +- Improve solver.cleandepsOnRemove result by evaluating the install + history to find packages installed on behalf of a user request (not + auto added by the solver). +- version 7.5.0 (5) + +------------------------------------------------------------------- +Sat May 1 01:13:43 CEST 2010 - ma@suse.de + +- Update translations. + +------------------------------------------------------------------- +Fri Apr 30 01:13:46 CEST 2010 - ma@suse.de + +- Update translations. + +------------------------------------------------------------------- +Thu Apr 29 17:10:29 CEST 2010 - ma@suse.de + +- Cleanup when deleting packages. New zypp.conf expert option + solver.cleandepsOnRemove telling whether the solver should per + default try to remove packages exclusively required by the ones + he's asked to delete (default false). +- Resolver::cleandepsOnRemove API to allow applications to change + the solver option. +- version 7.4.0 (4) + +------------------------------------------------------------------- +Thu Apr 29 01:13:40 CEST 2010 - ma@suse.de + +- Update translations. + +------------------------------------------------------------------- +Wed Apr 28 16:35:04 CEST 2010 - ma@suse.de + +- Enable splitprovides on update. + +------------------------------------------------------------------- +Wed Apr 28 01:13:37 CEST 2010 - ma@suse.de + +- Update translations. + +------------------------------------------------------------------- +Tue Apr 27 17:42:20 CEST 2010 - ma@suse.de + +- Selectable: Classify broken but locked patch as isUnwanted (bnc#577118) +- version 7.3.0 (2) + +------------------------------------------------------------------- +Tue Apr 27 11:25:17 CEST 2010 - ma@suse.de + +- Use libudev to detect available cd/dvd devices (bnc#590707,fate#308980) +- Fix specfile to BuildRequire libudev-devel. +- version 7.2.0 (2) + +------------------------------------------------------------------- +Mon Apr 26 11:57:23 CEST 2010 - ma@suse.de + +- Support URLs and ISOs ending on 'Media1', 'Media2', etc., when + rewiting the URL to access a specific media number. By now only + nanmes ending on 'CD' or 'DVD' were supported. (bnc#594850) + +------------------------------------------------------------------- +Fri Apr 23 01:13:34 CEST 2010 - ma@suse.de + +- Update translations. + +------------------------------------------------------------------- +Wed Apr 21 01:13:38 CEST 2010 - ma@suse.de + +- Update translations. + +------------------------------------------------------------------- +Tue Apr 20 16:56:59 CEST 2010 - ma@suse.de + +- /etc/zypp/locks: Allow to specify edition ranges with + solvable:name and dependencies. +- version 7.1.1 (1) + +------------------------------------------------------------------- +Thu Apr 15 12:49:01 CEST 2010 - ma@suse.de + +- Provide name of the lock holder in ZYppFactoryException. (bnc#580513) +- version 7.1.0 (1) + +------------------------------------------------------------------- +Wed Apr 14 15:09:18 CEST 2010 - ma@suse.de + +- Using boost-1.42 requires -fno-strict-aliasing (bnc#595545) +- Bump major version for 11.3 development. +- version 7.0.0 (0) + +------------------------------------------------------------------- +Tue Apr 13 14:36:31 CEST 2010 - ma@suse.de + +- Fix parsing port from IPv6 URL (bnc#593385) + +------------------------------------------------------------------- +Fri Mar 26 19:23:59 CET 2010 - ma@suse.de + +- Propagate ZConfig::setTextLocale to pool. (bnc#588850) +- version 6.31.3 (31) + +------------------------------------------------------------------- +Fri Mar 26 13:50:08 CET 2010 - ma@suse.de + +- Fix guessing package spec to match package names only. (bnc#590864) +- version 6.31.2 (31) + +------------------------------------------------------------------- +Tue Mar 23 16:55:56 CET 2010 - ma@suse.de + +- Add static Target::distributionLabel to return the baseproducts + shortName and summary. Mainlu used for the bootloader menu. (bnc #586303) +- version 6.31.1 (31) + +------------------------------------------------------------------- +Thu Mar 18 17:17:02 CET 2010 - ma@suse.de + +- Fix broken bit values in enum VendorSupportOption (bnc#589331) +- version 6.31.0 (31) + +------------------------------------------------------------------- +Fri Mar 12 14:46:25 CET 2010 - ma@suse.de + +- Fix handling of symlinked packages in package cache. (bnc #585409) +- version 6.30.5 (19) + +------------------------------------------------------------------- +Tue Feb 23 19:05:04 CET 2010 - jkupec@suse.cz + +- Avoiding use of 'guest' if 'credentials' is used when moutning + a CIFS share. This caused 'permission denied' error with certain + server configurations (bnc #560496). + +------------------------------------------------------------------- +Tue Feb 23 17:31:05 CET 2010 - ma@suse.de + +- Check if a downloaded file actually exists even if aria2c returned 0. + (bnc #564816) +- version 6.30.3 (19) + +------------------------------------------------------------------- +Mon Feb 22 15:25:34 CET 2010 - jkupec@suse.cz + +- Made CURLE_PARTIAL_FILE an auto-retry error (bnc #471436) + +------------------------------------------------------------------- +Mon Feb 22 13:09:09 CET 2010 - ma@suse.de + +- Turn off cookies when retrieving services repoindex.xml (bnc #573897) +- Consider pending disable requests when removing service repositories. (bnc #572634) +- version 6.30.1 (19) + +------------------------------------------------------------------- +Sun Feb 21 14:11:49 CET 2010 - jkupec@suse.cz + +- RepoManager::cleanCacheDirGarbage added for removing directories + which do not belong to any of known repos (bnc #467693) +- version 6.30.0 (19) + +------------------------------------------------------------------- +Thu Feb 11 13:40:49 CET 2010 - ma@suse.de + +- On SLE aria2 is not required, so conflict with a too old aria2 + version installed. (bnc #578052) +- version 6.29.5 (19) + +------------------------------------------------------------------- +Wed Feb 10 12:45:21 CET 2010 - ma@suse.de + +- Fix package-manager script wrongly escaping UTF-8 chars in path + names (bnc #571410) +- version 6.29.4 (19) + +------------------------------------------------------------------- +Mon Feb 8 13:21:40 CET 2010 - ma@suse.de + +- Support an alternate SLE-SP1 translation set. +- version 6.29.3 (19) + +------------------------------------------------------------------- +Wed Feb 3 15:57:13 CET 2010 - ma@suse.de + +- Remember the enabled state of removed service repositories. This + way we are able to restore service repositories correctly after a + subscrition expired and gets renewed. (bnc #572634) +- version 6.29.2 (19) + +------------------------------------------------------------------- +Thu Jan 28 16:12:25 CET 2010 - jkupec@suse.cz + +- Abort aria2c download when the progress callback receives 'false' + (bnc #545106) + +------------------------------------------------------------------- +Tue Jan 19 14:50:15 CET 2010 - ma@suse.de + +- Evaluate SolvAttr::repositoryToolVersion to prevent loading + outdated solv files. (bnc #570623) +- version 6.29.0 (19) + +------------------------------------------------------------------- +Fri Jan 15 18:15:26 CET 2010 - jkupec@suse.cz + +- Use regex to parse aria2c progress lines (bnc #570917) +- version 6.28.1 (19) + +------------------------------------------------------------------- +Thu Jan 7 12:25:24 CET 2010 - jkupec@suse.cz + +- Set SignatureFileChecker context even if the key is not known + (bnc #495977) +- version 6.28.0 (19) + +------------------------------------------------------------------- +Thu Dec 10 17:18:34 CET 2009 - jkupec@suse.cz + +- RepoInfoBase::label() added for use in UI messages, plus + ZConfig::repoLabelIsAlias() + +------------------------------------------------------------------- +Tue Dec 8 19:41:17 CET 2009 - ma@suse.de + +- Fix transaction building in presence of multiversion installable items. +- version 6.27.1 (19) + +------------------------------------------------------------------- +Fri Dec 4 17:19:58 CET 2009 - ma@suse.de + +- Improve multiversion status handling and installation. (fate #305311) +- version 6.27.0 (19) + +------------------------------------------------------------------- +Fri Dec 4 14:56:19 CET 2009 - jkupec@suse.cz + +- Don't allow an alias to start with '.' (bnc #473834) + +------------------------------------------------------------------- +Thu Dec 3 12:00:16 CET 2009 - ma@suse.de + +- PickList and status interface for handling packages which are + installable in multiple versions. (fate #305311) +- version 6.26.0 (19) + +------------------------------------------------------------------- +Wed Dec 2 13:10:43 CET 2009 - ma@suse.de + +- Add Selectable::highestAvailableVersionObj. Returns the highest + available package version, ignoring priorities and policies. (bnc #557557) +- version 6.25.0 (19) + +------------------------------------------------------------------- +Mon Nov 30 17:56:02 CET 2009 - ma@suse.de + +- Also parse tag from .prod files section. +- version 6.24.3 (19) + +------------------------------------------------------------------- +Fri Nov 27 11:20:34 CET 2009 - ma@suse.de + +- Fix chroot execution of update scripts. (bnc #558813) +- version 6.24.3 (19) + +------------------------------------------------------------------- +Thu Nov 26 16:06:52 CET 2009 - jkupec@suse.cz + +- Fixed parsing of download speed from aria2c (bnc #537870) + +------------------------------------------------------------------- +Wed Nov 25 16:28:29 CET 2009 - ma@suse.de + +- Add ui::Selecatble interface for picking specific package versions + to install or delete if multiversion install is on. +- version 6.24.0 (19) + +------------------------------------------------------------------- +Fri Nov 20 13:30:02 CET 2009 - ma@suse.de + +- Parse zypp.conf multiversion option and make the setting available + in pool and resolver. +- version 6.23.0 (19) + +------------------------------------------------------------------- +Mon Nov 16 16:27:39 CET 2009 - ma@suse.de + +- Specfile fixes to build on sle11-sp1. +- Fix repository probing and building in presence of productdir. (bnc #553712) +- version 6.22.3 (19) + +------------------------------------------------------------------- +Thu Nov 12 15:31:10 UTC 2009 - dmacvicar@suse.de + +- Forward port and document already present changes + from Code11-Branch + * void SEGV if trying to access data of installed packages, that were + deleted behind our back (bnc #530595) + * ProxyInfoSysconfig: take care variables get initialized. + * Fix parsing of rpm.install.excludedocs option (bnc #518883) + * Use rpm variables in specfile. (bnc #512466) + * Fix to compile with -Werror=format-security + * Fix packageand() in testcase generation + * Don't link unneeded libraries. (bnc #490895) + * Fix Patch::categoryEnum. + * Adapt to changed satsolver API. (bnc #480303) + * Taking ALL translations for generating GMO files (bnc #458739) + * Advice users to contact NCC if access to a 'novell.com' + repository is denied (bnc #464586). +- version 6.22.2 (19) + +------------------------------------------------------------------- +Thu Nov 12 11:53:04 CET 2009 - ma@suse.de + +- Raised the limit of redirections from 3 to 6 (bnc #465532) +- Following redirections also for https (bnc #545722). +- Following https redirections requires at least libcurl4-7.19.4. (bnc #553895) +- Do not report cached packages as being downloaded. (bnc #545295) +- Per default do not collect and report deleted files outside bin and lib + directories for 'zypper ps'. (bnc #554480) +- version 6.22.1 (19) + +------------------------------------------------------------------- +Wed Nov 11 13:54:52 CET 2009 - ma@suse.de + +- CheckAccessDeleted: Per default do not collect and report deleted files + that outside bin and lib directories. 'zypper ps' reporting false positive + seems to confuse. (bnc #554480) + +------------------------------------------------------------------- +Wed Nov 11 11:45:01 CET 2009 - ma@suse.de + +- Following https redirections requires at least libcurl4-7.19.4. (bnc #553895) + +------------------------------------------------------------------- +Fri Nov 6 22:16:10 CET 2009 - ma@suse.de + +- dup: Process drop list only if product actually changes. (bnc #552180) +- Selectable: Consider allowed arch/noarch changes when comuting candiadates. +- version 6.22.0 (19) + +------------------------------------------------------------------- +Mon Nov 2 21:33:40 CET 2009 - ma@suse.de + +- Enhance interface for zypper. (bnc #551956) +- version 6.21.4 (19) + +------------------------------------------------------------------- +Mon Nov 2 20:03:31 CET 2009 - ma@suse.de + +- CIFS/SMB: Support mountoption 'noguest' to prevent passing 'guest' option + to mount. "cifs://server/share/path?mountoptions=noguest,ro" (bnc #547354) +- version 6.21.3 (19) + +------------------------------------------------------------------- +Mon Nov 2 16:35:33 CET 2009 - ma@suse.de + +- CheckAccessDeleted: Avoid reporting false positive due to insufficient + permission. + +------------------------------------------------------------------- +Mon Nov 2 13:59:33 CET 2009 - ma@suse.de + +- Don't try to access droplist of dropped products. (bnc #551697) +- version 6.21.2 (19) + +------------------------------------------------------------------- +Fri Oct 30 12:30:48 CET 2009 - ma@suse.de + +- Don't try to use an empty proxy string. (bnc #551314) +- MediaSMB failed to pass the --workgroup option to mount. (bnc #547354) +- version 6.21.1 (19) + +------------------------------------------------------------------- +Fri Oct 30 11:28:05 CET 2009 - ma@suse.de + +- New class PoolItemBest: Find the best candidates e.g. in a PoolQuery + result. ui::Selectabe enhancements. Both will aid applications to + install package sets determined by query results. (bnc # 548392) +- Fix upgradeRepo solution to keep obsolete packages. (bnc #550915) +- Updated iso3166-1 country codes (bnc #531350) +- version 6.21.0 (19) + +------------------------------------------------------------------- +Tue Oct 27 12:30:29 CET 2009 - ma@suse.de + +- Add Resolver::upgradingRepo demanded by GUI. (bnc #548551) +- version 6.20.0 (19) + +------------------------------------------------------------------- +Thu Oct 22 15:09:57 CEST 2009 - ma@suse.de + +- Fixes to make libzypp-bindings compile. +- version 6.19.3 (19) + +------------------------------------------------------------------- +Tue Oct 20 16:06:13 CEST 2009 - ma@suse.de + +- Credentials are passed as commandline options to aria2c, so strip any + 'user@' from the URL. Otherwise aria will use an empty password for + this URL and authentication will fail. (bnc #544634) +- version 6.19.2 (19) + +------------------------------------------------------------------- +Mon Oct 19 13:39:31 CEST 2009 - ma@suse.de + +- Repository::setInfo: Propagate priority changes to the solver to + avoid reloading the whole repo (bnc #498266). +- version 6.19.1 (19) + +------------------------------------------------------------------- +Thu Oct 15 20:48:02 CEST 2009 - ma@suse.de + +- ResStatus: add isOrphaned to test whether a package is not provided + by any enabled repository. Orphaned packages are usually good candidates + for cleanup unless the providing repository was intentionally disabled. +- version 6.19.0 (19) + +------------------------------------------------------------------- +Thu Oct 15 17:28:38 CEST 2009 - dmacvicar@suse.de + +- aria2: pass credentials in a file instead of the command line + which is logged. +- aria2: we get the url in the progress if there is no response + from the server yet, handle that to avoid flooding the log. +- version 6.18.2 (17) + +------------------------------------------------------------------- +Thu Oct 15 16:56:25 CEST 2009 - ma@suse.de + +- Performing a dist upgrade the solver may try to delete old and no + longer provided (dropped) packages, even if they do not cause any + dependency problem. This behaviour may be trurned off via zypp.conf + option solver.upgradeRemoveDropedPackages. (bnc #539543) +- New zypp.conf option solver.upgradeRemoveDropedPackages (true). +- Add Product::droplist: List of dropped packages, i.e. packages no + longer provided by a product. +- version 6.18.1 (17) + +------------------------------------------------------------------- +Wed Oct 7 16:45:21 CEST 2009 - ma@suse.de + +- Return update messages via ZYppCommitResult. Support variable + substitution in notification command. (fate #301175) +- Fix evaluation of no_proxy entries (bnc #543337) +- aria/curl: Fix header data in case the target is + not initialized when downloading. +- version 6.18.0 (17) + +------------------------------------------------------------------- +Thu Sep 24 17:21:45 CEST 2009 - ma@suse.de + +- Add zypp.conf option update.messages.notify: Command to be invoked + to send update messages. (fate #301175) +- version 6.17.2 (17) + +------------------------------------------------------------------- +Tue Sep 22 20:32:38 CEST 2009 - ma@suse.de + +- Add Selectable::updateCandidateObj returning the candidate for + update, if there is one. The updateCandidate must not violate + any active solver policy. +- version 6.17.1 (17) + +------------------------------------------------------------------- +Fri Sep 18 17:20:37 CEST 2009 - ma@suse.de + +- Make sure rpmReadConfigFiles was called before using librpm (bnc #539603). +- Remove dead rpm database caching code from class RpmDb. +- version 6.17.0 (17) + +------------------------------------------------------------------- +Fri Sep 11 15:13:30 CEST 2009 - ma@km13.de + +- New commit.downloadMode option in zypp.conf. Allows to set a + prefered download policy for commit. +- version 6.16.0 (11) + +------------------------------------------------------------------- +Thu Sep 10 19:03:01 CEST 2009 - ma@suse.de + +- Support nfs4 (nfs4://... or nfs://...?type=nfs4) (fate #306451) +- Added Url::schemeIsLocal, schemeIsRemote, schemeIsVolatile and + schemeIsDownloading. +- version 6.15.0 (11) + +------------------------------------------------------------------- +Wed Sep 9 15:02:18 CEST 2009 - ma@suse.de + +- Add Capability::guessPackageSpec; parser also supporting "name-ver-rel.arch" + formats for building Capabilities(originally "name.arch=ver-rel"). +- version 6.14.3 (11) + +------------------------------------------------------------------- +Mon Sep 7 17:31:20 CEST 2009 - ma@suse.de + +- Fix resolution to force installation even if dependencies are missing. + (bnc #531564) +- Rephrase solver resolution to point out if a package will break. + (bnc #520083) + +------------------------------------------------------------------- +Fri Sep 4 12:19:50 CEST 2009 - ma@suse.de + +- Lock rpms architecture only on distupgrade of the running system. + (bnc #458520) +- version 6.14.2 (11) + +------------------------------------------------------------------- +Thu Sep 3 13:41:31 CEST 2009 - ma@suse.de + +- Fix PoolQuery comparison (bnc #528755) +- Fix serialization and restore of predicated PoolQueries. +- version 6.14.0 (11) + +------------------------------------------------------------------- +Mon Aug 31 15:17:01 CEST 2009 - ma@suse.de + +- package-manager script: Fall back to package selection if no + packages are passed on the commandline. (bnc #529137) + +------------------------------------------------------------------- +Fri Aug 28 17:33:55 CEST 2009 - dmacvicar@suse.de + +- package-manager script: + do not fail if kpackagekit is not installed (bnc #529510) +- version 6.13.3 (11) + +------------------------------------------------------------------- +Wed Aug 26 15:55:22 CEST 2009 - ma@suse.de + +- Tune CheckAccessDeleted to focus on libraries and executables. +- version 6.13.2 (11) + +------------------------------------------------------------------- +Thu Aug 6 18:18:21 CEST 2009 - ma@suse.de + +- Provide class CheckAccessDeleted and command zypp-CheckAccessDeleted + to check for running processes which access meanwhile deleted files or + libraries. This may be used after commit, when trying to figure out + which services need to be restated. (fate #300763). +- version 6.13.1 (11) + +------------------------------------------------------------------- +Mon Aug 3 18:46:13 CEST 2009 - ma@suse.de + +- New Resolver::addUpgradeRepo to perform a dist upgrade restricted to + certain repositories. +- version 6.13.0 (11) + +------------------------------------------------------------------- +Fri Jul 31 17:55:33 CEST 2009 - ma@suse.de + +- Remove confusing newlines in vendor change info (bnc #503859) +- Removing a package lock was not counted as state change (bnc #501850) +- Take solver_allowVendorChange option into account when computing the + Selectables default candidate. +- version 6.12.0 (11) + +------------------------------------------------------------------- +Wed Jul 29 13:36:19 CEST 2009 - ma@suse.de + +- Avoid deadlock after fork and failed exec. (bnc 493152) +- No need to manually detect the location of aria2 binary. +- version 6.11.4 (11) + +------------------------------------------------------------------- +Tue Jul 28 23:05:43 CEST 2009 - jkupec@suse.cz + +- Fixed parsing of download rate report (changed in aria2 1.4.0) + (bnc #513944) + +------------------------------------------------------------------- +Mon Jul 27 16:05:43 CEST 2009 - ma@suse.de + +- Create LogControl on demand instead of using a static var. (bnc #525339) +- version 6.11.2 (11) + +------------------------------------------------------------------- +Thu Jul 23 00:22:50 CEST 2009 - ma@km13.de + +- New misc::defaultLoadSystem: Convenience to create the ZYpp instance + and load target and enabled repositories. + +------------------------------------------------------------------- +Wed Jul 22 14:57:32 CEST 2009 - ma@suse.de + +- New class InstanceId to build strings to identify/retrieve specific + Solvables. +- version 6.11.1 (11) + +------------------------------------------------------------------- +Mon Jul 20 23:57:46 CEST 2009 - ma@km13.de + +- Add download policies to ZYppCommitPolicy, supporting DownloadOnly + and DownloadInAdvance. (fate #302159, fate #305624) +- version 6.11.0 (11) + +------------------------------------------------------------------- +Thu Jul 16 17:05:27 CEST 2009 - dmacvicar@suse.de + +- add support to the package-manager script to use kpackagekit + or gnome-packagekit if available, which allows to install local + rpms with one click from file manager following desktop policies + and fetching other dependencies if required. + (fate #306526) +- version 6.10.5 (10) + +------------------------------------------------------------------- +Thu Jul 16 16:25:24 CEST 2009 - ma@suse.de + +- New solver.upgradeTestcasesToKeep option in zypp.conf. It tells + how many dist upgrade solver testcases should be kept on the system. + Per default just the last two are kept. +- version 6.10.4 (10) + +------------------------------------------------------------------- +Wed Jul 15 17:53:43 CEST 2009 - ma@suse.de + +- Don't write a solver testcase when solving for dist upgrade, + but when actually committing. +- version 6.10.3 (10) + +------------------------------------------------------------------- +Wed Jul 15 16:45:39 CEST 2009 - ma@suse.de + +- Add new string Match::Mode STRINGSTART and STRINGEND. + +------------------------------------------------------------------- +Tue Jul 15 14:38:51 CEST 2009 - jkupec@suse.cz + +- log redirections when cURL media backend is used (fate #305320). + +------------------------------------------------------------------- +Tue Jul 14 18:15:51 CEST 2009 - ma@suse.de + +- Support "product version" detection on systems not using + /etc/product.d/baseproduct by looking for the first package + providing ZConfig::distroverpkg (defaults to redhat-release). +- version 6.10.2 (10) + +------------------------------------------------------------------- +Fri Jul 10 15:21:39 CEST 2009 - ma@suse.de + +- Adapt to boost_unit_test_framework-1.38. +- version 6.10.1 (10) + +------------------------------------------------------------------- +Wed Jul 8 16:19:31 CEST 2009 - ma@suse.de + +- Remove obsolete UpgradeStatistics class from libzypp. + +------------------------------------------------------------------- +Tue Jul 7 17:45:47 CEST 2009 - ma@suse.de + +- Fix HistoryLog to initialize on demand. +- version 6.10.0 (10) + +------------------------------------------------------------------- +Fri Jul 3 13:01:13 CEST 2009 - ma@suse.de + +- Fix parsing of rpm.install.excludedocs option (bnc #518883) + +------------------------------------------------------------------- +Fri Jul 3 09:20:56 CEST 2009 - ma@suse.de + +- When unmounting ISO images, don't mix up exceptions thrown by the + loop mounted ISO and those thrown by the media containing it. + (bnc #517856) + +------------------------------------------------------------------- +Thu Jul 2 16:42:42 CEST 2009 - ma@suse.de + +- Adapt to satsolvers improved dataiterator handling. +- version 6.9.3 (8) + +------------------------------------------------------------------- +Wed Jul 1 18:05:54 CEST 2009 - ma@suse.de + +- Support PoolQuery for sub-structures attributes. (fate #305503) +- version 6.9.2 (8) + +------------------------------------------------------------------- +Wed Jul 1 13:44:04 CEST 2009 - ma@suse.de + +- Running as non-root user use a temporary @System solvfile in case the + global one is outdated and needed refresh. (bnc #517183) +- version 6.9.1 (8) + +------------------------------------------------------------------- +Tue Jun 30 16:32:08 CEST 2009 - ma@suse.de + +- Enhance LookupAttr to allow direct query of attributes within + sub-structures (flexarrays). + +------------------------------------------------------------------- +Fri Jun 26 12:06:51 CEST 2009 - ma@suse.de + +- Enhance PoolQueryIterator to allow detailed inspection of attribute + matches. +- Prefer datadir stored as repo attribute, but fallback searching in + solvbales (old solv files do this). +- version 6.9.0 (8) + +------------------------------------------------------------------- +Tue Jun 23 13:29:36 CEST 2009 - ma@suse.de + +- Allow building libzypp with rpm-5 (experimental) +- version 6.8.3 (8) + +------------------------------------------------------------------- +Wed Jun 17 15:39:17 CEST 2009 - ma@suse.de + +- Allow building libzypp without HAL (not recommended). Without HAL + CD/DVD device detection is limited to /dev/dvd and /dev/cdrom. +- version 6.8.2 (8) + +------------------------------------------------------------------- +Fri Jun 5 21:16:45 CEST 2009 - ma@suse.de + +- Fix solver to use IdSting to avoid failing vendor checks. +- version 6.8.1 (8) + +------------------------------------------------------------------- +Thu Jun 4 14:22:58 CEST 2009 - ma@suse.de + +- Cleanup and remove deprecated interface methods. +- version 6.8.0 (8) + +------------------------------------------------------------------- +Fri May 29 20:12:55 CEST 2009 - ma@suse.de + +- Improve PoolQuery to allow queries on dependencies. (bnc #475682) +- version 6.7.0 (6) + +------------------------------------------------------------------- +Thu May 28 12:53:02 CEST 2009 - ma@suse.de + +- New solver.allowVendorChange expert option in zypp.conf. +- version 6.6.0 (6) + +------------------------------------------------------------------ +Wed May 20 14:23:07 CEST 2009 - ma@suse.de + +- Fix lost housekeeping data in modifyRepo (bnc #503207) + +------------------------------------------------------------------- +Fri May 8 16:43:47 CEST 2009 - ma@suse.de + +- Allow service refresh to change a repositories url (bnc #502157) + +------------------------------------------------------------------- +Tue May 5 13:39:08 CEST 2009 - ma@suse.de + +- Detect and compile with rpm 4.7 (bnc #444211) +- version 6.5.2 (5) + +------------------------------------------------------------------- +Mon May 4 16:19:54 CEST 2009 - ma@suse.de + +- Improve problem report on broken systemCheck rule (bnc #475144) + +------------------------------------------------------------------- +Mon Apr 27 15:26:54 CEST 2009 - ma@suse.de + +- In update repos providing multiple release package versions for + the same product, link a product to the latest version. (bnc #497696) + +------------------------------------------------------------------- +Mon Apr 27 14:28:07 CEST 2009 - ma@suse.de + +- New classes wraping satsolver datamatcher (Match and sat::AttrMatcher) +- Extend LookupAttr to support matching specific string patterns. +- Rewrote PoolQuery::Iterator (adapt to AttrMatcher, fixes and speedup) +- version 6.5.0 (5) + +------------------------------------------------------------------- +Thu Apr 16 12:49:40 CEST 2009 - ma@suse.de + +- Soft lock packages deleted on behalf of a user request. +- version 6.4.1 (2) + +------------------------------------------------------------------- +Tue Mar 31 15:51:32 CEST 2009 - ma@suse.de + +- New zypp.conf option 'download.media_preference': Hint which media + to prefer when installing packages (download vs. CD). +- version 6.4.0 (2) + +------------------------------------------------------------------ +Thu Mar 12 18:38:30 CET 2009 - ma@suse.de + +- Add Resolver::setSolveSrcPackages. Per default disable solving + of source package dependencies. We will later allow enabling + it per package. +- version 6.3.0 (2) + +------------------------------------------------------------------- +Fri Mar 6 17:17:26 CET 2009 - dmacvicar@suse.de + +- aria2: show the download speed in the right unit +- aria2: show the filename in progress, not the repository +- aria2: don't show done twice + +------------------------------------------------------------------- +Thu Mar 5 14:52:44 CET 2009 - ma@suse.de + +- Remove a lock if the locking process is in zombie state. (bnc #481577) + +------------------------------------------------------------------- +Wed Mar 4 00:13:19 CET 2009 - jkupec@suse.cz + +- zypp.conf: fixed and enabled 'servicesdir' + +------------------------------------------------------------------- +Tue Mar 3 13:38:11 CET 2009 - dmacvicar@suse.de + +- aria2: implement speed indicators (bnc#475506) +- aria2: implement progress indicators correctly (bnc#473846) +- aria2: fix broken pipe when looking for aria2c which caused + a fallback to curl. (bnc#480930) +- aria2: implement saving and reading mirror stats data in + /var/cache/zypp/aria2.stats +- aria2: handle failover correctly (bnc#481115) +- aria2: various improvements in error and report handling +- aria2: curl: reset settings on attach to avoid duplicate + headers +- version 6.2.1 (2) + +------------------------------------------------------------------- +Tue Mar 3 12:44:24 CET 2009 - ma@suse.de + +- Adapt to changed satsolver API. + +------------------------------------------------------------------- +Fri Feb 27 16:23:36 CET 2009 - dmacvicar@suse.de + +- Make sure Fetcher pass optional files as non-interactive +- Fixes file does not exist error when key/sig does not exist +- version 6.2.0 (2) + +------------------------------------------------------------------- +Thu Feb 26 13:49:56 CET 2009 - ma@suse.de + +- Use correct default for zconfig(solver.checkSystemFile) (bnc# 475144) + +------------------------------------------------------------------- +Thu Feb 26 01:25:33 CET 2009 - ma@suse.de + +- Prevent ResStatus from overriding user locks. (bnc #475230) + +------------------------------------------------------------------- +Sun Feb 22 15:27:11 CET 2009 - ma@suse.de + +- Never refresh repositories from CD/DVD, once they are created. (bnc #476429) + +------------------------------------------------------------------- +Sat Feb 21 18:31:17 CET 2009 - dmacvicar@suse.de + +Implemented the following options with aria backend: + +- download.max_concurrent_connections (default 2) + download.min_download_speed (default no limit) + download.max_download_speed (default no limit) + download.max_silent_tries (default 5) + +------------------------------------------------------------------- +Fri Feb 20 16:28:19 CET 2009 - dmacvicar@suse.de + +- MediaAria2c: allow disabling aria2 using ZYPP_ARIA2C=0. + Various improvements including file existence checking + Disable HEAD request if aria2c >= 1.20 + Restrict max connections to 2 for now. + +------------------------------------------------------------------- +Wed Feb 18 15:51:38 CET 2009 - ma@suse.de + +- Neither lose packages with empty name, nor SEGV when processing them. (bnc #470011) + +------------------------------------------------------------------- +Tue Feb 17 23:17:54 CET 2009 - ma@suse.de + +- Compute obsoletes based on names only (not considering provides) (bnc #471023) + +------------------------------------------------------------------- +Tue Feb 17 12:56:57 CET 2009 - jkupec@suse.cz + +- Fixed FTP authentication (bnc #472879) + +------------------------------------------------------------------- +Wed Feb 11 13:31:03 CET 2009 - ma@suse.de + +- Follow IEC and use the binary prefixes (KiB,MiB,GiB) for printing Byte + counts based on a power of 1024 (formerly just K,M,G). Byte counts based + on a power of 1000 stay unaffected (kB,MB,GB). + +------------------------------------------------------------------- +Mon Feb 9 13:14:26 CET 2009 - ma@suse.de + +- Fix installation prompting for the wrong CD/DVD. (bnc #472892) + +------------------------------------------------------------------- +Tue Feb 3 18:07:38 CET 2009 - ma@suse.de + +- Send any output from rpm install/delete scripts via callback, so + applications are able to display it. (bnc #369450) + +------------------------------------------------------------------- +Mon Feb 2 14:12:08 CET 2009 - ma@suse.de + +- Add missing translations (bnc #256289) + +------------------------------------------------------------------- +Wed Jan 28 14:37:28 CET 2009 - jkupec@suse.cz + +- HistoryLogReader added + +------------------------------------------------------------------- +Tue Jan 27 13:35:44 CET 2009 - ma@suse.de + +- Respect content-file DATDIR when downloading packages. (bnc #468612) + +------------------------------------------------------------------- +Tue Jan 27 13:28:54 CET 2009 - jkupec@suse.cz + +- Enabled CredentialManager for MediaSMB (bnc #460970). +- Ignore URL's username, password, and query string in AuthData + comparator in CredentialManager. + +------------------------------------------------------------------- +Mon Jan 26 12:41:07 CET 2009 - ma@suse.de + +- Let vendor checks per default differ between 'openSUSE Build Service' + and 'openSUSE' (bnc #467262). + +------------------------------------------------------------------- +Fri Jan 23 12:34:44 CET 2009 - ma@suse.de + +- Fix handling of plaindir repos on mounted devices (e.g. USB) (bnc #464778) +- Fix plaindir checksum computation not to to follow symlinks (bnc #464778) + +------------------------------------------------------------------- +Thu Jan 22 10:41:27 CET 2009 - ma@suse.de + +- Tell satsolver about product buddies (bnc #466565) + +------------------------------------------------------------------- +Fri Jan 9 17:01:10 CET 2009 - jkupec@suse.cz + +- handle HTTP 503 responses as temporary errors (bnc #462545) + +------------------------------------------------------------------- +Thu Dec 18 22:26:18 CET 2008 - ma@suse.de + +- Fixed lost user request to abort during commit. (bnc #388810, bnc #450273) +- revision 11954 +- version 5.25.0 (23) + +------------------------------------------------------------------- +Thu Dec 18 13:02:27 CET 2008 - ma@suse.de + +- Add Package::filelist, faster and less memory consuming + implementation of Package::filenames (now deprecated). +- revision 11949 + +------------------------------------------------------------------- +Thu Dec 11 21:39:50 CET 2008 - ma@suse.de + +- Add str::hexencode and str::hexdecode to encode special characters + in a string as %XX. +- Hexdecode modalias strings in rpm dependencies because rpm does not + allow comma, blank and other special chars. (bnc #456695) +- revision 11927 + +------------------------------------------------------------------- +Thu Dec 11 17:13:06 CET 2008 - ma@suse.de + +- Catch and report media errors when proving packages. (bnc #457652) +- revision 11926 + +------------------------------------------------------------------- +Wed Dec 10 16:09:08 CET 2008 - ma@suse.de + +- Remove obsolete zypp.conf::productsdir and deprecate + ZConfig::productsPath(). +- Monitor /etc/products.d to determine if @system.solv needs to be + rebuilt. (bnc #457933) +- revision 11923 +- version 5.24.7 (23) + +------------------------------------------------------------------- +Mon Dec 8 15:31:18 CET 2008 - ma@suse.de + +- Execute patch scripts chroot to the installed system. (bnc #456795) +- revision 11908 + +------------------------------------------------------------------- +Mon Dec 8 10:39:30 CET 2008 - schubi@suse.de + +- Make the solver reset function public (bnc #439373) +- Revision 11904 + +------------------------------------------------------------------- +Sun Dec 7 20:21:09 CET 2008 - coolo@suse.de + +- note for coolo: do not trust bash advisory from TPM colleagues + +------------------------------------------------------------------- +Fri Dec 5 14:22:11 CET 2008 - ma@suse.de + +- Fix solvers inappropriate selection as byUSER (bnc 455965) +- revision 11891 +- version 5.24.6 (23) + +------------------------------------------------------------------- +Thu Dec 4 11:10:35 CET 2008 - coolo@suse.de + +- fix %post script to not warn on fresh install + +------------------------------------------------------------------- +Mon Dec 1 19:38:24 CET 2008 - ma@suse.de + +- Fix install order computation losing some installed packages + pre-requirements. (bnc #439802) +- revision 11845 +- version 5.24.5 (23) + +------------------------------------------------------------------- +Fri Nov 28 16:33:56 CET 2008 - ma@suse.de + +- Prune soft locks to prevent installation but not update of + already installed packages. +- revision 11829 +- version 5.24.4 (23) + +------------------------------------------------------------------- +Fri Nov 28 11:36:03 CET 2008 - schubi@suse.de + +- Taking solutions which based on user requirements/conflict + "by User" solutions (bnc #442718) +- revision 11825 + +------------------------------------------------------------------- +Fri Nov 28 00:05:17 CET 2008 - ma@suse.de + +- Take into account the requirements of all obsoleted packages uninstall + scripts when computing the installation order. (bnc #439802) +- revision 11823 +- version 5.24.3 (23) + +------------------------------------------------------------------- +Thu Nov 27 14:45:07 CET 2008 - dmacvicar@suse.de + +- fix maybeUnsuported() method returning wrong result +- add testcase for future coverage +- don't force time based uuid for anonymous id string (bnc #449654) +- RELEASE: 5.24.2 (23) + +------------------------------------------------------------------- +Wed Nov 26 17:18:00 CET 2008 - ma@suse.de + +- Call 'repo2solv -R' (recursive scan) for plaindir repos. (bnc #443350) +- revision 11810 + +------------------------------------------------------------------- +Wed Nov 26 17:09:12 CET 2008 - dmacvicar@suse.de + +- SHA1SUMS.key is not imported by zypp as known key (bnc #446188) +- path and url in add_on_products.xml is evaluated wrong + (bnc #446170) + +------------------------------------------------------------------- +Mon Nov 24 17:47:35 CET 2008 - schubi@suse.de + +- activate locking for doUpdate (bnc #447684) +- revision 11792 +- RELEASE: 5.24.1 (23) + +------------------------------------------------------------------- +Fri Nov 21 16:56:10 CET 2008 - dmacvicar@suse.de + +- remove unused updaterepokey, replaced by repo + product information + +------------------------------------------------------------------- +Fri Nov 21 15:12:52 CET 2008 - jkupec@suse.cz + +- fixed uninitialized value in OnMediaLocation (bnc #447010) +- revision 11770 + +------------------------------------------------------------------- +Thu Nov 20 23:59:16 CET 2008 - ma@suse.de + +- Fix retrieval of deltarpm info. +- revision 11764 +- version 5.24.0 (23) + +------------------------------------------------------------------- +Thu Nov 20 22:15:28 CET 2008 - ma@suse.de + +- Fix retrieval of Repository attributes like timestamps, keywords + and product info. +- revision 11760 + +------------------------------------------------------------------- +Thu Nov 20 19:30:05 CET 2008 - ma@suse.de + +- Enhance class LookupAttr and add convenience class LookupRepoAttr to + iterate those solv file attributes which are not acssociated with a + solvable. E.g. product or deltarpm info. +- revision 11754 + +------------------------------------------------------------------- +Wed Nov 19 15:49:38 CET 2008 - jkupec@suse.cz + +- encode user-supplied URL strings before using them in the Url object + (bnc #446395, bnc #444267) +- revision 11720 + +------------------------------------------------------------------- +Wed Nov 19 15:15:14 CET 2008 - ma@suse.de + +- Support loading helix files. +- revision 11719 + +------------------------------------------------------------------- +Tue Nov 18 18:37:30 CET 2008 - ma@suse.de + +- Add class filesystem::Glob to find pathnames matching a pattern + by using ::glob. +- revision 11708 + +------------------------------------------------------------------- +Thu Nov 13 11:07:56 CET 2008 - schubi@suse.de + +- Taking care for ppc64 while distupgrade (bnc #443685) +- revision 11670 + +------------------------------------------------------------------- +Wed Nov 12 18:53:03 CET 2008 - ma@suse.de + +- Add Capability ctor from Arch and Name: (Arch_i386, "name") or + (Arch_i386, "name == 1.0"). +- revision 11669 + +------------------------------------------------------------------- +Wed Nov 12 14:31:20 CET 2008 - ma@suse.de + +- Take care to always reset CURLOPT_TIMECONDITION to prevent incomplete + downloads. (bnc #444109) +- revision 11656 +- version 5.23.0 (23) + +------------------------------------------------------------------- +Wed Nov 12 13:19:02 CET 2008 - ma@suse.de + +- Check for modaliases below /sys (bnc #430179) +- revision 11653 + +------------------------------------------------------------------- +Tue Nov 11 18:36:33 CET 2008 - ma@suse.de + +- Avoid superfluous file copying and gpg invocation in keyring handling. +- revision 11650 + +------------------------------------------------------------------- +Tue Nov 11 14:48:52 CET 2008 - ma@suse.de + +- Prevent fetcher from processing the same index file twice. (bnc #443644) +- revision 11648 +- version 5.22.0 (21) + +------------------------------------------------------------------- +Fri Nov 7 23:55:47 CET 2008 - ma@suse.de + +- Fix retrieval of patch contents and references attributes. (bnc #442200) +- revision 11641 +- version 5.21.0 (21) + +------------------------------------------------------------------- +Fri Nov 7 19:51:00 CET 2008 - ma@suse.de + +- Add CheckSum::asString. +- revision 11634 + +------------------------------------------------------------------- +Fri Nov 7 17:55:48 CET 2008 - ma@suse.de + +- revision 11631 +- version 5.20.0 (20) + +------------------------------------------------------------------- +Thu Nov 6 18:35:25 CET 2008 - dmacvicar@suse.de + +- re-add the flavor to the http header now using a flavor + cache that is updated on every target load. + Target::dstributionFlavor provides access to this cache + in case you need the last used flavor without loading + the target. + +------------------------------------------------------------------- +Thu Nov 6 16:23:03 CET 2008 - schubi@suse.de + +- added flag: ignorealreadyrecommended to the testcases (bnc #432136) +- revsion 11539 + +------------------------------------------------------------------- +Thu Nov 6 09:41:48 CET 2008 - schubi@suse.de + +- Adding rule rpm-arch for installed rpm package in order to avoid + unneeded architecture change. (bnc #441004) +- revision 11585 + +------------------------------------------------------------------- +Tue Nov 4 13:21:35 CET 2008 - jkupec@suse.cz + +- handle MediaTimeoutException also in MediaSetAccess::provideFile() + (bnc #439983) +- revision 11568 + +------------------------------------------------------------------- +Mon Nov 3 15:30:53 CET 2008 - dmacvicar@suse.de + +- merge contributions by Jon Nelson, the patches resolve + the following issues: +- disable the "Pragma: nocache" header which is automatically + used by curl. + re-enables the use of a caching http proxy (like squid or others) + and corrects (bnc #326208) +- don't generate an If-Modified-Since header if we don't have a + previous file to work with +- don't generate a Proxy-Authenticate header if one is not called + for. + +------------------------------------------------------------------- +Fri Oct 31 14:01:57 CET 2008 - ma@suse.de + +- Do not save solver locks (by APPL_HIGH). +- revision 11558 + +------------------------------------------------------------------- +Fri Oct 31 13:53:39 CET 2008 - dmacvicar@suse.de + +- fetcher.setOptions( Fetcher::AutoAddIndexes ) allows + for automatic signed index discovery. +- enqueueDir with checksum checking s now enqueueDigestedDir + +------------------------------------------------------------------- +Thu Oct 30 14:24:57 CET 2008 - schubi@suse.de + +- solutions: keep/lock will be done by APPL_HIGH. So they will not be + saved in the lockfiles +- "keep obsolete" will be handled with lock by APPL_HIGH (bnc #439134) +- revision 11549 + +------------------------------------------------------------------- +Wed Oct 29 14:14:16 CET 2008 - jkupec@suse.cz + +- throw a MediaTimeoutException also on http 504 (gateway timeout) + (bnc #425035) +- revision 11535 + +------------------------------------------------------------------- +Wed Oct 29 12:51:55 CET 2008 - ma@suse.de + +- Add 'sh4' architectures. +- revision 11534 + +------------------------------------------------------------------- +Tue Oct 28 22:01:40 CET 2008 - dmacvicar@suse.de + +- don't free the header before curl_perform as curl does not + copy it. (bnc#439532) + +------------------------------------------------------------------- +Tue Oct 28 16:47:36 CET 2008 - ma@suse.de + +- Add 'arm' architectures. +- revision 11525 + +------------------------------------------------------------------- +Tue Oct 28 10:07:13 CET 2008 - schubi@suse.de + +- regarding "keep obsolete" in the solutions (bnc #439134) +- revision 11517 + +------------------------------------------------------------------- +Mon Oct 27 10:51:01 CET 2008 - dmacvicar@suse.de + +- fix broken aria2c command line (bnc#438971) + +------------------------------------------------------------------- +Sun Oct 26 14:53:56 CET 2008 - coolo@suse.de + +- adding svn r11488 to fix compile of PackageKit + +------------------------------------------------------------------- +Fri Oct 24 18:12:34 CEST 2008 - ma@suse.de + +- Remove error prone methods from OnMediaLocation API to prevent + accidental missuse. (bnc #437328) +- revision 11487 +- version 5.19.0 (19) + +------------------------------------------------------------------- +Fri Oct 24 16:07:45 CEST 2008 - ma@suse.de + +- Provide the /etc/products.d enties filename as Product::referenceFilename. + Use it to remove orphan products. (bnc #432932) +- Fix media exception handling in commit (bnc #395704) +- revision 11485 +- version 5.18.0 (17) + +------------------------------------------------------------------- +Fri Oct 24 10:29:19 CEST 2008 - schubi@suse.de + +- Taking "unlock" instead of setTransact(false) in the solutions (bnc #436923) +- revision 11468 +- version 5.17.0 (17) + +------------------------------------------------------------------- +Wed Oct 22 14:33:10 CEST 2008 - ma@suse.de + +- For retrieving a product license fall back to license.tar.gz. (bnc #372386) +- revision 11447 + +------------------------------------------------------------------- +Wed Oct 22 14:16:33 CEST 2008 - dmacvicar@suse.de + +- move anonymous unique id to a private http header + X-ZYpp-AnonymousUniqueId (bnc#431571 ) + +------------------------------------------------------------------- +Wed Oct 22 12:58:35 CEST 2008 - ma@suse.de + +- Adapt to satsolver-0.12 API. +- Add Locale:: bestMatch to find the best match within a set of + available Locales. +- revision 11441 + +------------------------------------------------------------------- +Mon Oct 20 16:44:58 CEST 2008 - ma@suse.de + +- RepoInfo: Add methods to handle repository licenses. (bnc #372386) +- revision 11419 + +------------------------------------------------------------------- +Mon Oct 20 16:39:41 CEST 2008 - ma@suse.de + +- Adapt to changed satsolver dataiterator API. +- revision 11418 + +------------------------------------------------------------------- +Fri Oct 17 18:31:47 CEST 2008 - ma@suse.de + +- Secure download of license file on repo refresh (bnc #372386) +- revision 11398 + +------------------------------------------------------------------- +Fri Oct 17 17:26:25 CEST 2008 - ma@suse.de + +- Call 'repo2solv.sh -o' instead of using output redirection. (bnc #420046) +- revision 11397 + +------------------------------------------------------------------- +Thu Oct 16 17:57:15 CEST 2008 - jkupec@suse.cz + +- repository license methods added to RepoManager (bnc #372386) +- revision 11377 + +------------------------------------------------------------------- +Thu Oct 16 16:26:01 CEST 2008 - dmacvicar@suse.de + +- don't take into account stat information when looking + for remote SHA1SUMS (part of bnc#409927) + +------------------------------------------------------------------- +Wed Oct 15 18:01:48 CEST 2008 - jkupec@suse.cz + +- MediaSetAccess::provideOptionalFile() added +- revision 11369 + +------------------------------------------------------------------- +Wed Oct 15 18:01:48 CEST 2008 - jkupec@suse.cz +- version 5.16.1 (16) + +------------------------------------------------------------------- +Tue Oct 14 16:15:09 CEST 2008 - jkupec@suse.cz + +- don't initialize servicesTargetDistro via global ZYpp instance in + RepoManagerOptions() constructor (bnc #435184) +- revision 11342 + +------------------------------------------------------------------- +Mon Oct 13 19:12:40 CEST 2008 - jkupec@suse.cz + +- repository probing: check for other types of repo even on + MediaException, throw only if all fail (bnc #335906) +- revision 11332 + +------------------------------------------------------------------- +Mon Oct 13 14:16:25 CEST 2008 - ma@suse.de + +- Adapt to satsolver changes. +- revision 11331 +- version 5.16.0 (16) + +------------------------------------------------------------------- +Mon Oct 13 13:28:48 CEST 2008 - ma@suse.de + +- Fix reading delta rpm checksum from solv file. +- revision 11313 + +------------------------------------------------------------------- +Mon Oct 13 12:12:39 CEST 2008 - ma@suse.de + +- Fix package-manager script to properly quote arguments. (bnc #30903) +- revision 11311 + +------------------------------------------------------------------- +Mon Oct 13 11:03:04 CEST 2008 - schubi@suse.de + +- regarding orphaned resolvables +- removed old distupgrade algorithm +- revision 11307 + +------------------------------------------------------------------- +Sun Oct 12 13:55:51 CEST 2008 - jkupec@suse.cz + +- handle ftp response 530 (login failed) like http 403 + (bnc #433537) +- revision 11305 + +------------------------------------------------------------------- +Thu Oct 9 17:37:18 CEST 2008 - ma@suse.de + +- Adapt to satsolvers 'big solv data change'. +- revision 11294 + +------------------------------------------------------------------- +Thu Oct 9 17:18:18 CEST 2008 - schubi@suse.de + +- Taking the right solution actions for locked resolvables (bnc #400840) +- revision 11289 + +------------------------------------------------------------------- +Thu Oct 9 13:52:03 CEST 2008 - ma@suse.de + +- Add required copy-ctor and assignment operator to WhatProvides. + (bnc #433087) +- revision 11276 + +------------------------------------------------------------------- +Wed Oct 8 16:24:25 CEST 2008 - jkupec@suse.cz + +- detect and use unused loop device for mounting ISO images + (bnc #428009) +- revision 11262 +- version 5.15.1 (13) + +------------------------------------------------------------------- +Wed Oct 8 15:39:08 CEST 2008 - jkupec@suse.cz + +- fixed segfault when saving the probed repo type in + RepoManager::refreshMetadata() (bnc #431963) +- revision 11261 + +------------------------------------------------------------------- +Wed Oct 8 11:33:00 CEST 2008 - dmacvicar@suse.de + +- improve log message (bnc#429114) + +------------------------------------------------------------------- +Wed Oct 8 11:15:20 CEST 2008 - lslezak@suse.cz + +- disk usage - ignore /proc filesystem (bnc#418783) +- revision 11258 + +------------------------------------------------------------------- +Tue Oct 7 13:24:10 CEST 2008 - ma@suse.de + +- Fixed detection of loopback mounted iso-files. The mtab entry does + not necessarily mention the iso-file. (bnc #432504) +- revision 11252 +- version 5.15.0 (13) + +------------------------------------------------------------------- +Thu Oct 2 19:46:13 CEST 2008 - ma@suse.de + +- Add zypp.conf option 'download.use_deltarpmr.always' to enable using + delta rpms even if the package is available on a local source. + (Axel C. Frinke) +- revision 11235 +- version 5.14.0 (13) + +------------------------------------------------------------------- +Thu Oct 2 18:50:11 CEST 2008 - ma@suse.de + +- Add product attribute: PRODUCTLINE. +- revision 11234 + +------------------------------------------------------------------- +Thu Oct 2 17:18:19 CEST 2008 - ma@suse.de + +- Do not consider self provided requirements whan computing the + installation order. +- revision 11231 + +------------------------------------------------------------------- +Wed Oct 1 16:07:36 CEST 2008 - ma@suse.de + +- Rephrase missleading error message. (bnc #431229) +- revision 11222 + +------------------------------------------------------------------- +Tue Sep 30 17:23:48 CEST 2008 - ma@suse.de + +- Allow computation of disk usage per solvable. +- revision 11218 + +------------------------------------------------------------------- +Mon Sep 29 23:59:10 CEST 2008 - dmacvicar@suse.de + +- Merge aria2c Media handler code from Google SOC 2008 + (Gerard Farras) +- Only activated by making env var ZYPP_ARIA=1 + +------------------------------------------------------------------- +Mon Sep 29 15:56:17 CEST 2008 - jkupec@suse.cz + +- history: tell which package failed before logging rpm output or + error message (bnc #430585) +- no localization for history log comments +- revision 11202 + +------------------------------------------------------------------- +Mon Sep 29 13:43:08 CEST 2008 - ma@suse.de + +- Fix zypp::WhatProvides::empty returning inverse result. +- revision 11200 +- version 5.13.1 (13) + +------------------------------------------------------------------- +Sat Sep 27 23:36:19 CEST 2008 - jkupec@suse.cz + +- fixed endless loop when CredentialManager returns bad password +- CredentialManager now correctly updates password of existing + credentials +- revision 11187 + +------------------------------------------------------------------- +Fri Sep 26 15:37:50 CEST 2008 - ma@suse.de + +- Fix computation of Product::flavor. +- Add Product::productLine. A vendor specific string denoting the + product line. +- revision 11182 +- version 5.13.0 (13) + +------------------------------------------------------------------- +Fri Sep 26 15:25:33 CEST 2008 - jkupec@suse.cz + +- save user credentials after asking for them +- revision 11181 + +------------------------------------------------------------------- +Thu Sep 25 23:19:55 CEST 2008 - jkupec@suse.cz + +- ZConfig::credentialsGlobal{File,Dir}() added + (/etc/zypp/credentials.{cat,d}) +- revision 11176 + +------------------------------------------------------------------- +Thu Sep 25 17:09:44 CEST 2008 - jkupec@suse.cz + +- Target::setInstallationLogfile() removed from zypp/Target.h +- revision 11171 + +------------------------------------------------------------------- +Thu Sep 25 13:11:43 CEST 2008 - ma@suse.de + +- Remove obsolete zypp-query-pool binary. zypper provides all + the information one needs. +- revision 11160 + +------------------------------------------------------------------- +Wed Sep 24 19:11:19 CEST 2008 - jkupec@suse.cz + +- HistoryLog added and used to log package installs/removes and + repository adds, removes, url and alias changes into + history.logfile (/var/log/zypp/history) (fate #110205) +- str::escape(string, char) added +- revision 11150 +- version 5.12.1 (12) + +------------------------------------------------------------------- +Tue Sep 23 14:02:08 CEST 2008 - jkupec@suse.cz + +- CredentialManager: look for credentials with + wanted_url.startsWith(stored_url) +- RepoManager: don't pass service credentials down to repos if + their urls are not based on service's url. +- revision 11134 + +------------------------------------------------------------------- +Mon Sep 22 16:27:41 CEST 2008 - ma@suse.de + +- Remove superfluous PRODUCT_REFERENCES attribute. +- revision 11127 + +------------------------------------------------------------------- +Mon Sep 22 16:13:08 CEST 2008 - ma@suse.de + +- Add Url::hasCredentialsInAuthority test for username or password + being encoded in the authority component. I.e. user:pass@host. +- Handle repos to be disabled disable in service refresh. +- revision 11126 + +------------------------------------------------------------------- +Mon Sep 22 12:10:34 CEST 2008 - jkupec@suse.cz + +- provided context to keyring callbacks (bnc #370223) +- merged trust & import callbacks (bnc #366467) + (don't worry, still allows to trust && !import) +- revision 11113 + +------------------------------------------------------------------- +Fri Sep 19 13:17:38 CEST 2008 - ma@suse.de + +- Moved DefaultAcceptBits enum to class KeyRing (formerly KeyRingReort). +- revision 11102 + +------------------------------------------------------------------- +Thu Sep 18 16:11:23 CEST 2008 - ma@suse.de + +- Use service alias as namespace for it's repositories aliases. +- revision 11097 +- version 5.11.0 (11) + +------------------------------------------------------------------- +Thu Sep 18 12:45:25 CEST 2008 - jkupec@suse.cz + +- pass service's credentials down to repos +- support ?credentials=filepath in URL to specify credentials +- revision 11092 + +------------------------------------------------------------------- +Thu Sep 18 09:57:49 CEST 2008 - ma@suse.de + +- Add Product::isTargetDistribution to identify the systems installed + baseproduct. This should replace tests for Product::type is "base". +- revision 11089 + +------------------------------------------------------------------- +Wed Sep 17 18:05:44 CEST 2008 - jkupec@suse.cz + +- save user credentials when adding repos/services with URLs containing + the credentials (bnc #425462) +- revision 11085 + +------------------------------------------------------------------- +Wed Sep 17 15:08:54 CEST 2008 - ma@suse.de + +- Adapt to rpms new way of quoting whitespace in pathnames.(bnc #426924) +- revision 11082 + +------------------------------------------------------------------- +Tue Sep 16 18:41:39 CEST 2008 - ma@suse.de + +- Service handling fixes. Added ServiceException. +- revision 11077 + +------------------------------------------------------------------- +Mon Sep 15 11:40:04 CEST 2008 - ma@suse.de + +- Fix building of transaltions. +- revision 11064 + +------------------------------------------------------------------- +Sun Sep 14 00:10:21 CEST 2008 - jkupec@suse.cz + +- ServiceInfo.clearReposTo{Enable,Disable}() methods added +- revision 11060 + +------------------------------------------------------------------- +Fri Sep 12 18:24:28 CEST 2008 - ma@suse.de + +- Create new Service repos in disbaled sate. +- revision 11056 +- version 5.10.0 (10) + +------------------------------------------------------------------- +Fri Sep 12 16:04:54 CEST 2008 - ma@suse.de + +- Make registerTarget and registerRelease abvailable for installed + product. Required for registration. +- revision 11043 + +------------------------------------------------------------------- +Fri Sep 12 12:59:50 CEST 2008 - ma@suse.de + +- Add url lists query to Product interface. A generic query and + convenience methods to query urls for "releasenotes", "register", + "updateurls", "extraurls", "optionalurls" and "smolt" (bnc #413444) +- revision 11029 + +------------------------------------------------------------------- +Fri Sep 12 01:38:25 CEST 2008 - jkupec@suse.cz + +- ServiceType and ServiceInfo::type() added (contains only RIS for + now), service type probing added. +- Avoiding the use of 'path' for services (appending + the repoindex.xml's 'path' to the baseurl of created repos) +- renamed ServiceInfo::*catalog*() methods to *repo*() methods +- revision 11022 + +------------------------------------------------------------------- +Thu Sep 11 16:01:57 CEST 2008 - dmacvicar@suse.de + +- add Repostiroy::updateKeys and + Repository::providesUpdatesForKey(string) for repo and + product matching +- Provide Repository::isUpdateRepo + +------------------------------------------------------------------- +Thu Sep 11 14:41:28 CEST 2008 - ma@suse.de + +- Fix evaluation of vendor support flags. +- Adapt retrieval of registration data (targetDistribution, + targetDistributionRelease and targetDistributionFlavor). +- revision 11013 + +------------------------------------------------------------------- +Wed Sep 10 18:23:52 CEST 2008 - ma@suse.de + +- Follow gpgcheck tag in .repo file and do no check if disabled. +- revision 11010 +- version 5.9.0 (8) + +------------------------------------------------------------------- +Wed Sep 10 17:54:20 CEST 2008 - jkupec@suse.cz + +- added dumpAsXMLOn(stream,string) to ServiceInfo to print services + with content (repos) +- revision 11004 + +------------------------------------------------------------------- +Wed Sep 10 17:31:41 CEST 2008 - ma@suse.de + +- Remove obsolete product attributes. +- Store less packages in /var/lib/zypp/SoftLocks (bnc #418050) +- revision 11001 + +------------------------------------------------------------------- +Wed Sep 10 16:40:00 CEST 2008 - ma@suse.de + +- Provide product::updaterepoKey: Update repository indicator string. +- revision 11000 + +------------------------------------------------------------------- +Tue Sep 9 17:33:03 CEST 2008 - dmacvicar@suse.de + +- provide context about the repository (name/alias) if available when + checking signatures (bnc#370223) +- 5.8.0 + +------------------------------------------------------------------- +Tue Sep 9 13:04:11 CEST 2008 - ma@suse.de + +- Add ServiceInfo interface to define a set of catalogs (repository + aliases) to be enabled on next refresh. +- revision 10970 + +------------------------------------------------------------------- +Tue Sep 9 11:40:42 CEST 2008 - ma@suse.de + +- Fix reading of Traget::targetDistribution. +- Allow to configure default answers in signature verification workflow. +- revision 10968 + +------------------------------------------------------------------- +Mon Sep 8 17:11:02 CEST 2008 - jkupec@suse.cz + +- CredentialManager added to manage stored credentials +- MediaCurl adapted to use CredentialManager to read credentials +- revision 10958 + +------------------------------------------------------------------- +Fri Sep 5 11:40:05 CEST 2008 - jkupec@suse.cz + +- operator ==, !=, < definition moved to RepoInfoBase from + the derived classes +- fixed RepoInfo::dumpAsIniOn() to not print 'type' if it is unknown + (bnc #407515) +- {Repo,Service}Info::dumpAsXMLOn(ostream) added +- RepoInfo::dumpRepoOn() deprecated in favor of dumpAsIniOn() +- use shared_ptr instead of itrusive for {Repo,Service}Info +- revision 10931:10942 + +------------------------------------------------------------------- +Thu Sep 4 16:47:07 CEST 2008 - jkupec@suse.cz + +- RepoInfo{,Base} setters made void +- revision 10931 + +------------------------------------------------------------------- +Wed Sep 3 14:53:06 CEST 2008 - jkupec@suse.cz + +- skip repositories with non-matching target distro when reading + repoindex +- revision 10926 + +------------------------------------------------------------------- +Tue Sep 2 11:04:52 CEST 2008 - schubi@suse.de + +- Enabled distupgrade of the SAT solver. In order to use the old + distupgrade you can set the environment variable ZYPP_NO_SAT_UPDATE. + This variable will can be used until the old distupgrade mechanism will + be removed from libzypp. Have a look to above changelogs. +- revision 10911 +- version 5.7.0 (5) + +------------------------------------------------------------------- +Tue Aug 19 16:36:47 CEST 2008 - dmacvicar@suse.de + +- add Package::maybeUnsupported to remove duplicated + code in clients dealing with Package::vendorSupport + +------------------------------------------------------------------- +Tue Aug 19 11:04:52 CEST 2008 - schubi@suse.de + +- Reset transaction only if this solvable has no buddy (bnc #417799) + e.g. do not reset Products cause the concerning release package + could not already be installed. +- revision 10883 +- version 5.6.1 (5) + +------------------------------------------------------------------- +Mon Aug 18 17:31:02 CEST 2008 - dmacvicar@suse.de + +- don't report "may be outdated" for @System repo. + +------------------------------------------------------------------- +Fri Aug 15 20:20:07 CEST 2008 - ma@suse.de + +- Add Target::targetDistribution. Returns "distribution-arch" of + the installed base product. Used for registration and Service + refresh. (for Fate #304915) +- revision 10877 +- version 5.6.0 (5) + +------------------------------------------------------------------- +Fri Aug 15 17:42:58 CEST 2008 - ma@suse.de + +- Add method Product::replacedProducts to identify installed + Products that would be replaced by installing a new Product. + (for Fate #301997) +- revision 10876 + +------------------------------------------------------------------- +Fri Aug 15 15:30:32 CEST 2008 - ma@suse.de + +- Fixes to Selectable doing staus manipulation on non-USER level. +- revision 10873 + +------------------------------------------------------------------- +Fri Aug 15 14:23:02 CEST 2008 - ma@suse.de + +- Add method ZYpp::getTarget that returns the Target or a NULL pointer, + if it is not yet initialized. This is to avoid try/catch blocks just + to test whether the Target is initialized. (bnc #417556) +- Add method Target::assertRootPrefix. Pass a pathname and get back the + path prefixed with the tragets root, unless it already had that prefix. +- revision 10870 + +------------------------------------------------------------------- +Thu Aug 14 18:44:45 CEST 2008 - schubi@suse.de + +- Regarding error messages for Products correctly (FATE #304502) +- rev 10863 + +------------------------------------------------------------------- +Thu Aug 14 14:03:27 CEST 2008 - ma@suse.de + +- Let Selectable default to USER level. +- revision 10850 +- version 5.5.1 (5) + +------------------------------------------------------------------- +Wed Aug 13 21:01:25 CEST 2008 - ma@suse.de + +- Change Selectable API to support doing staus manipulation on + non-USER level. +- revision 10847 +- version 5.5.0 (5) + +------------------------------------------------------------------- +Wed Aug 13 16:48:49 CEST 2008 - dmacvicar@suse.de + +- support sat solver API for searching files + +------------------------------------------------------------------- +Wed Aug 13 15:12:45 CEST 2008 - ma@suse.de + +- Add ResPool::reposFind to get repositories by alias. +- revision 10835 + +------------------------------------------------------------------- +Tue Aug 12 19:37:36 CEST 2008 - ma@suse.de + +- Advise rpmdb2solv to parse the product database. +- revision 10824 +- version 5.4.0 (4) + +------------------------------------------------------------------- +Tue Aug 12 12:05:49 CEST 2008 - ma@suse.de + +- Offer a simpler, fate based status manipulation in ui::Selectable. + This is easier to handle, as the ui::Status always distinguishes + wheter an object is installed or not. +- revision 10814 + +------------------------------------------------------------------- +Mon Aug 11 18:00:40 CEST 2008 - ma@suse.de + +- Propagate default rpm install flags from zypp.conf via ZConfig and + ZYppCommitPolicy down to the installer. (FATE #302952) +- revision 10813 + +------------------------------------------------------------------- +Mon Aug 11 16:28:07 CEST 2008 - ma@suse.de + +- Add base::Flags (like qt's QFlags) a type-safe way of storing + OR-combinations of enum values. +- revision 10811 + +------------------------------------------------------------------- +Fri Aug 8 17:01:00 CEST 2008 - ma@suse.de + +- Add static ui::Selectable::get methods as convenient ctor + substitute. +- revision 10806 + +------------------------------------------------------------------- +Fri Aug 8 15:41:17 CEST 2008 - ma@suse.de + +- Adapt zypp-query-pool to new product handling. +- revision 10803 + +------------------------------------------------------------------- +Fri Aug 8 14:11:03 CEST 2008 - ma@suse.de + +- Don't pass epoch to 'rpm -e', it does not support it. +- revision 10800 + +------------------------------------------------------------------- +Fri Aug 8 13:27:42 CEST 2008 - ma@suse.de + +- Adapt to new product handling. Products are no longer pseudo + installed objects verified by the solver, but actually installed. + Thus removed satisfiedProduct iterator, fixed Selctables. +- Removed class ProductInfo as we keep Product. +- revision 10797 + +------------------------------------------------------------------- +Thu Aug 7 22:00:55 CEST 2008 - dmacvicar@suse.de + +- implement relogin suggested support (fate#304889) + +------------------------------------------------------------------- +Wed Aug 6 18:21:30 CEST 2008 - ma@suse.de + +- Detect correct download path even if repository type + is not set. (bnc #386386) +- revision 10768 + +------------------------------------------------------------------- +Wed Aug 6 17:15:48 CEST 2008 - ma@suse.de + +- Cleanup, mostly by removing, unused parser code and related classes. +- revision 10765 + +------------------------------------------------------------------- +Wed Aug 6 16:23:27 CEST 2008 - ma@suse.de + +- Don't let exception escape MediaSetAccess dtor (bnc #415017) +- revision 10763 + +------------------------------------------------------------------- +Mon Aug 4 19:34:27 CEST 2008 - ma@suse.de + +- Add new product attributes (flavor,referencePackage). +- Add PoolItem buddies, i.e. two PoolItems sharing the same status + object. This is used to keep the product resolvable and the + package providing the product metadata in sync. +- revision 10742 + +------------------------------------------------------------------- +Sat Aug 2 19:26:52 CEST 2008 - jkupec@suse.cz + +- support an optional url attribute in repoindex.xml's +- revision 10729 + +------------------------------------------------------------------- +Thu Jul 31 21:52:11 CEST 2008 - ma@suse.de + +- New class ProductInfo to provide product related metadata that + might be associated with a package. This will replace the Product + resolvable. +- revision 10715 + +------------------------------------------------------------------- +Thu Jul 31 19:01:54 CEST 2008 - dmacvicar@suse.de + +- generate a unique anonymous unique string per target + and add it to the agent string for better statistics + +------------------------------------------------------------------- +Thu Jul 31 19:01:14 CEST 2008 - ma@suse.de + +- Follow solver policy and make repository priority the highest + key, when ordering packages. Then architecture, and edition last. +- revision 10710 + +------------------------------------------------------------------- +Wed Jul 30 19:12:00 CEST 2008 - ma@suse.de + +- /var/lib/zypp and /var/cache/zypp should be owned by libzypp + (bnc #412094) +- revision 10702 + +------------------------------------------------------------------- +Wed Jul 30 12:47:48 CEST 2008 - jkupec@suse.cz + +- Service renamed to ServiceInfo +- RepoInfoBase added; RepoInfo and ServiceInfo now derive from it +- revision 10695 + +------------------------------------------------------------------- +Tue Jul 29 12:59:46 CEST 2008 - jkupec@suse.cz + +- fixed yum repos to work with non '/' base url post fix + (bnc #341617) +- revision 10662 + +------------------------------------------------------------------- +Mon Jul 28 18:13:24 CEST 2008 - ma@suse.de + +- Fixed SolvIterMixin::Selectable_iterator eating some solvables + (bnc #411339) +- revision 10680 + +------------------------------------------------------------------- +Fri Jul 25 20:12:55 CEST 2008 - ma@suse.de + +- Several changes to make libzypp-bindings compile using the original + header files and no private copies. (bnc #391831) +- revision 10668 +- version 5.3.0 + +------------------------------------------------------------------- +Wed Jul 23 17:17:47 CEST 2008 - jkupec@suse.cz + +- Service::enabled() added +- revision 10657 + +------------------------------------------------------------------- +Tue Jul 22 17:18:28 CEST 2008 - jkupec@suse.cz + +- Removed FRESHENS dependency type +- revision 10643 + +------------------------------------------------------------------- +Thu Jul 17 09:49:40 CEST 2008 - schubi@suse.de + +- Allow parallel installation of packages which have been defined + in zypp.conf (parameter "multiversion") Fate #302050 +- Additional check for broken system. + (defined in zypp.conv: solver.checkSystemFile) +- revision 10600 + +------------------------------------------------------------------- +Wed Jul 16 14:39:50 CEST 2008 - ma@suse.de + +- Add ui::Selectable::isNeeded to indicate patch relevance (bnc #409150) +- revision 10596 + +------------------------------------------------------------------- +Wed Jul 16 01:10:37 CEST 2008 - ma@suse.de + +- Remove Atom, Script, Message and other obsolete classes. +- revision 10592 + +------------------------------------------------------------------- +Mon Jul 14 13:36:26 CEST 2008 - ma@suse.de + +- Also report the name of the locking process in ZYppFactoryException + (bnc #280537) +- revision 10572 + +------------------------------------------------------------------- +Mon Jul 14 11:26:30 CEST 2008 - schubi@suse.de + +- corrected logging of solver settings +- regard locking while doUpdate (bnc #405427) +- revision 10564 + +------------------------------------------------------------------- +Sat Jul 12 22:14:32 CEST 2008 - jkupec@suse.cz + +- make curl use the right transfer mode + (CURLOPT_PROXY_TRANSFER_MODE) when proxy is used (bnc #306272) +- revision 10559 + +------------------------------------------------------------------- +Sat Jul 12 11:19:56 CEST 2008 - jkupec@suse.cz + +- reuse existing disk mounts (applied Marius' patch) (bnc #208222) +- revision 10557 + +------------------------------------------------------------------- +Wed Jul 9 18:13:58 CEST 2008 - ma@suse.de + +- Provide Package::url() if available in solv file. (bnc #402434) +- A missing cookie file must not be treated as an error. Simply + rebuild the cache (bnc #405867) +- Add 22x22 and 24x24 icons (bnc #329635) +- revision 10528 + +------------------------------------------------------------------- +Mon Jul 7 13:39:09 CEST 2008 - schubi@suse.de + +- Do not update an already updated package (bnc #400422) +- revision 10504 + +------------------------------------------------------------------- +Fri Jul 4 17:19:24 CEST 2008 - ma@suse.de + +- Also check if the fingerprint matches before importing updated keys. + (bnc #393160) +- revision 10500 + +------------------------------------------------------------------- +Mon Jun 30 23:55:20 CEST 2008 - dmacvicar@suse.de + +- forward port add message attribute to patches. +- port import newer keys if a trusted key is updated +- (bnc#393160) +- version 5.0.2 + +------------------------------------------------------------------- +Mon Jun 30 10:28:27 CEST 2008 - ma@suse.de + +- Fix permanent duplication of gpg keys in the rpm database. Also + retrieve correct creation and expire dates. (bnc #401259) +- Invoke gpg with --homdir, otherwise command fails if executed + within a wrapper. (bnc #401259) +- revision 10487 + +------------------------------------------------------------------- +Thu Jun 26 12:07:33 CEST 2008 - schubi@suse.de + +- version 5.0.1 +- revision 10464 + +------------------------------------------------------------------- +Thu Jun 19 17:55:35 CEST 2008 - ma@suse.de + +- Handle new patch messages and scripts in commit. Provide callbacks + to display the patch messages and give visual feedback on script + execution. (bnc #401220) +- revision 10411 + +------------------------------------------------------------------- +Thu Jun 19 17:35:59 CEST 2008 - ma@suse.de + +- Fix wrong parenthesis causing bug 399320 +- version +- revision + +------------------------------------------------------------------- +Tue Jun 10 09:52:03 CEST 2008 - jreidinger@suse.cz + +- improve performance of gsub +- change replace_all to replaceAll (same name convency) +- add tests for gsub and replaceAll +- revision 10366 + +------------------------------------------------------------------- +Fri Jun 6 13:29:59 CEST 2008 - ma@suse.de + +- Handle application/x-redhat-package-manager in package-manager.desktop + (bnc #391183) +- revision 10361 + +------------------------------------------------------------------- +Thu Jun 5 18:01:15 CEST 2008 - jkupec@suse.cz + +- X-SuSE-ControlCenter-System category added + to package-manager.desktop (bnc #302324) +- revision 10353 + +------------------------------------------------------------------- +Wed Jun 4 14:57:13 CEST 2008 - ma@suse.de + +- Fix crash when requesting disk usage without a target loaded. (bnc #396755) +- revision 10340 + +------------------------------------------------------------------- +Wed Jun 4 14:05:09 CEST 2008 - ma@suse.de + +- Fix memory corruption in curl media handler (bnc #396979) +- revision 10338 + +------------------------------------------------------------------- +Tue Jun 3 20:00:00 CEST 2008 - ma@suse.de + +- Take care satsolver recognizes 'Capability( "srcpackage:zypper" )' + as 'source package named zypper'. So these capabilities can be used + together with sat::Whatprovides or in resolver requests. (bnc #369893) +- revision 10335 + +------------------------------------------------------------------- +Tue Jun 3 15:40:37 CEST 2008 - jreidinger@suse.cz + +- allow aborting progress during removing packages. (bnc #389238) +- revision 10331 + +------------------------------------------------------------------- +Mon Jun 2 15:31:36 CEST 2008 - schubi@suse.de + +- New option for ignoring Obsoletes. This is used for installing more than + one pacakges with the same name but different versions. + Often used by kernel. +- r 10299 + +------------------------------------------------------------------- +Sun Jun 1 23:14:34 CEST 2008 - - ma@suse.de + +- Revert inappropriate Selectable cleanup. Fix Selectable + status computation. Unmaintained packages were wrongly + reported as unsinstalled. (bnc #394630) +- version 5.0.0 (4.x continued in SuSE-Linux-11_0-Branch) +- revision 10295 + +------------------------------------------------------------------- +Fri May 30 12:14:47 CEST 2008 - tgoettlicher@suse.de + +- fixed typo + +------------------------------------------------------------------- +Wed May 28 18:54:27 CEST 2008 - ma@suse.de + +- Reenable diskusage calculation (bnc #395051) +- version 4.25.1 +- revision 10273 + +------------------------------------------------------------------- +Wed May 28 18:50:11 CEST 2008 - jkupec@suse.cz + +- RepoManager::packagesPath(RepoInfo) added (bnc #394728) +- revision 10271 + +------------------------------------------------------------------- +Wed May 28 16:26:09 CEST 2008 - jkupec@suse.cz + +- RepoInfo: don't overwrite flags that have already been set externally + (bnc #394728) +- revision 10256 + +------------------------------------------------------------------- +Wed May 28 15:30:24 CEST 2008 - ma@suse.de + +- Create missing directories when saving config files. (bnc #395026) +- Fix undefined behaviour in RepoManager. +- revision 10255 + +------------------------------------------------------------------- +Wed May 28 15:23:44 CEST 2008 - schubi@suse.de + +- SOLVER_ERASE_SOLVABLE_NAME: As we do not know, if this request has come + from resolvePool or resolveQueue we will have to take care for both + cases. (bnc#393969) +- r 10252 + +------------------------------------------------------------------- +Tue May 27 22:35:37 CEST 2008 - coolo@suse.de + +- compile with RPM_OPT_FLAGS + +------------------------------------------------------------------- +Mon May 26 17:23:24 CEST 2008 - jkupec@suse.cz + +- old2new locks file converter script added to %post (jredinger) +- r 10227 + +------------------------------------------------------------------- +Mon May 26 11:48:35 CEST 2008 - schubi@suse.de + +- Do not regard packages with the same name while upgrading obsoleted + packages (bnc#394367) +- r 10219 + +------------------------------------------------------------------- +Sat May 24 01:23:44 CEST 2008 - dmacvicar@suse.de + +- revert commit don't check for existence of keys, + to avoid a non needed HEAD request. (related bnc#381280) + as it creates popup error callbacks due to the 404's in + the keys. Leave however the OnMediaLocation::optional() + API to look for another fix strategy. + +------------------------------------------------------------------- +Fri May 23 15:52:20 CEST 2008 - dmacvicar@suse.de + +- define path for messages and scripts and document + them in zypp.conf + +------------------------------------------------------------------- +Fri May 23 14:42:34 CEST 2008 - schubi@suse.de + +- Added IgnoreAlreadyRecommended flag. So recomments/suggest will + be ignored for already INSTALLED packages (bnc #389694) +- r 10202 + +------------------------------------------------------------------- +Fri May 23 10:22:47 CEST 2008 - schubi@suse.de + +- Packages which obsoletes and do NOT required other installed + packages will be installed if no other packages obsolete the installed package too. +- r 10196 + +------------------------------------------------------------------- +Thu May 22 02:22:29 CEST 2008 - dmacvicar@suse.de + +- fix filelist for installed packages (bnc#392544) +- fix changelog retrieval for installed packages + +------------------------------------------------------------------- +Wed May 21 13:50:00 CEST 2008 - dmacvicar@suse.de + +- deprecate Repository::name() and use alias() to + be consistent. Related to (bnc#383553) +- don't check for existence of keys, to avoid a non needed + HEAD request. (helps bnc#381280) +- 4.25.0 + +------------------------------------------------------------------- +Wed May 21 11:37:23 CEST 2008 - schubi@suse.de + +- added onlyRequires in the testcase (bnc #389184) + +------------------------------------------------------------------- +Tue May 20 12:12:27 CEST 2008 - jreidinger@suse.cz + +- allow installation and refreshing from repository with alias that + contains ' or " (bnc #392426) +- r10158 + +------------------------------------------------------------------- +Mon May 19 21:11:41 CEST 2008 - jkupec@suse.cz + +- delta rpm support reenabled +- r10150 + +------------------------------------------------------------------- +Mon May 19 18:13:19 CEST 2008 - schubi@suse.de + +- Resetting Delete Details in ResStatus correctly (bnc #391785) +- r 10145 + +------------------------------------------------------------------- +Mon May 19 11:47:06 CEST 2008 - dmacvicar@suse.de + +- when setting status to non installed for uninstalled packages + set the user transaction so they go to soft locks. + (related to bnc#389739 ) + +------------------------------------------------------------------- +Fri May 16 16:56:04 CEST 2008 - schubi@suse.de + +- Added new calls : isInstalledBy (const PoolItem item); + installs (const PoolItem item); +- r 10125 +- 4.23.0 + +------------------------------------------------------------------- +Fri May 16 16:49:04 CEST 2008 - jreidinger@suse.cz + +- don't run merge in save when toAdd/Remove queue is empty +- throw when locks cannot load its file +- r10124 + +------------------------------------------------------------------- +Fri May 16 09:59:09 CEST 2008 - jreidinger@suse.cz + +- throw more describing exception when repo probing failed + (bnc #389690) +- revision 10118 + +------------------------------------------------------------------- +Thu May 15 15:15:59 CEST 2008 - jreidinger@suse.cz + +- allow call only merge old locks and newly added/removed without + saving it to file +- -revision 10104 + +------------------------------------------------------------------- +Tue May 13 17:37:11 CEST 2008 - dmacvicar@suse.de + +- report non packages as keep installed if satisfied to the + user interace (Selectables) +- 4.21.3 + +------------------------------------------------------------------- +Tue May 13 15:50:28 CEST 2008 - jkupec@suse.cz + +- create /etc/zypp/products.d on install + +------------------------------------------------------------------- +Mon May 12 17:21:19 CEST 2008 - jkupec@suse.cz + +- /etc/zypp/products.d added to file list (bnc #385868) +- revision 10049 +- version 4.21.2 + +------------------------------------------------------------------- +Mon May 12 17:15:34 CEST 2008 - jkupec@suse.cz + +- call RemoveResolvableReport::problem() before finish() on error + (bnc #388810) +- revision 10045 + +------------------------------------------------------------------- +Sat May 10 21:57:29 CEST 2008 - coolo@suse.de + +- fix file list + +------------------------------------------------------------------- +Fri May 9 23:15:53 CEST 2008 - ma@suse.de + +- Product now retrieves all attributes from the solv file. +- version 4.21.1 +- revision 10031 + +------------------------------------------------------------------- +Fri May 9 21:28:42 CEST 2008 - ma@suse.de + +- Add zypp.conf option configdir (/etc/zypp) and arrange + all config files and directories to follow {configdir} + per default. +- Fix zypp-query-pool to print satisfied products and additional + products defined in {configdir}/products.d for registration. + (bnc #385868) +- version 4.21.0 +- revision 10029 + +------------------------------------------------------------------- +Fri May 9 15:30:40 CEST 2008 - jreidinger@suse.cz + +- implement remove duplicate entries in lock file (bnc#385967) + +------------------------------------------------------------------- +Fri May 9 15:15:32 CEST 2008 - ma@suse.de + +- Speedup rpmdb2solv by reusing an existing solv file. +- version 4.20.1 +- revision 10012 + +------------------------------------------------------------------- +Thu May 8 18:13:54 CEST 2008 - ma@suse.de + +- Fix failed package download due to unkown repository type (bnc #386386) +- revision 9995 + +------------------------------------------------------------------- +Thu May 8 16:33:37 CEST 2008 - ma@suse.de + +- Support optional root argument to RepoManagerOptions, to prefix all + path names taken from ZConfig. (bnc #388265) +- version 4.20.0 +- revision 9993 + +------------------------------------------------------------------- +Thu May 8 14:21:51 CEST 2008 - schubi@suse.de + +- new solution action for removing requirements/conflicts (bnc #387631) +- revision 9988 + +------------------------------------------------------------------- +Thu May 8 10:56:49 CEST 2008 - ma@suse.de + +- Provide enumerated patch category 'Patch::categoryEnum()' (bnc #159100) +- revision 9984 + +------------------------------------------------------------------- +Wed May 7 13:52:24 CEST 2008 - schubi@suse.de + +- DistUpgrade: searching for providers -> regarding name onl +- r 9977 + +------------------------------------------------------------------- +Tue May 6 17:35:59 CEST 2008 - dmacvicar@suse.de + +- add flag --registrable (-r) to query pool to avoid + using system as a filter +- 4.19.1 + +------------------------------------------------------------------- +Tue May 6 07:37:22 CEST 2008 - coolo@suse.de + +- return values in non-void functions + +------------------------------------------------------------------- +Mon May 5 14:08:20 CEST 2008 - jkupec@suse.cz + +- support multiple search strings in PoolQuery (ORed) +- revision 9945 + +------------------------------------------------------------------- +Mon May 5 09:55:29 CEST 2008 - schubi@suse.de + +- Switch off the upgrade mode of the + SAT solver cause the packages have already been evaluated by + the distupgrade machanism of libzypp. (bnc #386375) +- rev 9943 + +------------------------------------------------------------------- +Fri May 2 16:36:04 CEST 2008 - jreidinger@suse.cz + +- release file after copy to cache as soon as possible. + (bnc #381311) +- r9940 + +------------------------------------------------------------------- +Fri May 2 16:28:05 CEST 2008 - schubi@suse.de + +- Bugfix: keep states by user has been removed it the + package has not been installed BUT has been recommended by another package. + (bnc #385832) +- rev 9938 + +------------------------------------------------------------------- +Fri May 2 12:19:22 CEST 2008 - jreidinger@suse.cz + +- add isLocal function to Url which say if scheme is local or + internet. +- r9932 + +------------------------------------------------------------------- +Fri May 2 09:36:18 CEST 2008 - jreidinger@suse.cz + +- cache decision for repository depend on his url. +- http,ftp and smb cache packages. +- revision 9929 + +------------------------------------------------------------------- +Thu May 1 00:50:51 CEST 2008 - ma@suse.de + +- Load and maintain persistent hard locks stored in /etc/zypp/locks. + Locks are loaded together with the target, and changes are writen + back on commit. zypp.conf option locksfile.apply can be used to turn + this feature on or off. (FATE #120352) +- version 4.18.0 +- revision 9927 + +------------------------------------------------------------------- +Wed Apr 30 16:27:49 CEST 2008 - ma@suse.de + +- Add zypp.conf option solvfilesdir: Path where the repo solv files + are created. Default value: {cachedir}/solv. +- Target and repositories now save their solvfiles below {solvfilesdir} + in directories named after the repositories alias. +- version 4.18.0 +- revision 9913 + +------------------------------------------------------------------- +Wed Apr 30 14:19:16 CEST 2008 - jkupec@suse.cz + +- fixed filesystem::expandlink(Pathname) (bnc #368477) +- r9906 + +------------------------------------------------------------------- +Tue Apr 29 16:37:19 CEST 2008 - schubi@suse.de + +- cleanup in return values of doUpgrade and doUpdate +- r9886 +- 4.17.0 + +------------------------------------------------------------------- +Mon Apr 28 18:27:54 CEST 2008 - jkupec@suse.cz + +- check for valid pool in begin(), improve the code (bnc #384337) +- r9872 +- 4.16.0 + +------------------------------------------------------------------- +Mon Apr 28 15:40:09 CEST 2008 - mvidner@suse.cz + +- Updated package-manager-su from xdg-utils-1.0.2-48 (bnc#339549). + +------------------------------------------------------------------- +Mon Apr 28 15:25:46 CEST 2008 - schubi@suse.de + +- added translations + +------------------------------------------------------------------- +Mon Apr 28 11:15:47 CEST 2008 - jkupec@suse.cz + +- ostream operator<<(ostream,TriBool) added +- r9833 + +------------------------------------------------------------------- +Fri Apr 25 16:12:12 CEST 2008 - ma@suse.de + +- Prevent target::unload from creating a system repo in order + to unload it. (bnc 382297) +- version 4.15.2 +- revision 9822 + +------------------------------------------------------------------- +Fri Apr 25 14:15:17 CEST 2008 - ma@suse.de + +- Prevent deselected or deleted items from being re-selected due to + recommends (aka. persistent soft locks). Unlike hard locked, those + items will be automatically selected if required. The list of soft + locked items is stored in /var/lib/zypp/SoftLocks. +- version 4.15.1 +- revision 9818 + +------------------------------------------------------------------- +Wed Apr 23 22:24:00 CEST 2008 - ma@suse.de + +- Remove obsolete AdditionalCapabilities interface from ResPool. + Forward sat::Pool::RepositoryIterator. There's no more need to + maintain an extra Repository list in ResPool. +- revision 9806 + +------------------------------------------------------------------- +Wed Apr 23 21:12:56 CEST 2008 - ma@suse.de + +- Support dependencies requiring a specific architecture: + "name[.arch] [op edition]". See class Capability for details + about how to construct dependencies. (bnc #305445) +- version 4.15.0 +- revision 9805 + +------------------------------------------------------------------- +Tue Apr 22 17:39:28 CEST 2008 - dmacvicar@suse.de + +- patch attributes and deprecate old ones +- 4.14.0 + +------------------------------------------------------------------- +Tue Apr 22 15:44:34 CEST 2008 - jreidinger@suse.cz + +- change locks api - +- make more functions const +- replace add/remove by selectable to add/remove by ident or name and kind +- rename iterator to const_iterator to avoid confusion +- revision 9781 + +------------------------------------------------------------------- +Tue Apr 22 13:55:14 CEST 2008 - schubi@suse.de + +- Do architecture changes while "dup" in the external distribution + upgrade ONLY. bnc #382274 +- Added "ignore" to the solutions +- Added "self-conflicts" to the solution +- added new solver mechanism "resolveQueue" +- Bugfix broken/satisfied products +- rev 9776 + +------------------------------------------------------------------- +Tue Apr 22 10:33:03 CEST 2008 - ma@suse.de + +- Added Pattern::core returning the packages required by a pattern. + (see also Pattern::depends and Pattern::contents). +- revision 9771 + +------------------------------------------------------------------- +Mon Apr 21 15:38:10 CEST 2008 - ma@suse.de + +- Added Target::release(), returning the targets distribution + release string. +- revision 9761 + +------------------------------------------------------------------- +Sat Apr 19 01:08:04 CEST 2008 - ma@suse.de + +- per default abort if package installation fails. (bnc #381203) +- version 4.13.3 +- revision 9725 + +------------------------------------------------------------------- +Fri Apr 18 15:19:36 CEST 2008 - dmacvicar@suse.de + +- add ZYpp and curl version to http agent string + (bnc #381280) + +------------------------------------------------------------------- +Thu Apr 17 16:29:15 CEST 2008 - ma@suse.de + +- Fixed pools package index wrongly including source packages. (bnc #380283) +- version 4.13.2 +- revision 9683 + +------------------------------------------------------------------- +Wed Apr 16 15:00:19 CEST 2008 - ma@suse.de + +- Disable fast creation of @System.solv. It may produce wrong results + e.g. after a rebuilddb. +- version 4.13.1 +- revision 9666 + +------------------------------------------------------------------- +Wed Apr 16 12:50:09 CEST 2008 - ma@suse.de + +- initializeTarget now takes an additional option, telling whether to + rebuild an existing rpm database before using it. Default is false. + (bnc #308352) +- version 4.13.0 +- revision 9664 + +------------------------------------------------------------------- +Tue Apr 15 12:57:42 CEST 2008 - jreidinger@suse.cz + +- save do nothing if no locks added/removed +- fix bug with multiple save lock +- don't save same query multiple times +- improve tests +- revision 9644 + +------------------------------------------------------------------- +Tue Apr 15 09:34:29 CEST 2008 - schubi@suse.de + +- added new translations +- activate zypp-query-pool +- Revision 9637 +- 4.12.1 + +------------------------------------------------------------------- +Tue Apr 15 00:54:07 CEST 2008 - jkupec@suse.cz + +- Locks API cleaned-up, iterator added, light read() added +- PoolQuery::attribute(SolvAttr) getter added +- revision 9609 + +------------------------------------------------------------------- +Mon Apr 14 17:00:05 CEST 2008 - dmacvicar@suse.de + +- reenable zypp-query-pool +- 4.11.1 + +------------------------------------------------------------------- +Mon Apr 14 12:53:09 CEST 2008 - ma@suse.de + +- Enable evaluation of hardware dependencies. +- Enable evaluation of filesystem dependencies. +- revision 9605 + +------------------------------------------------------------------- +Sun Apr 13 02:17:25 CEST 2008 - jkupec@suse.cz + +- RawMetadataRefreshPolicy: CheckIfNeededIgnoreDelay added + needed for explicit refresh request +- revision 9574 + +------------------------------------------------------------------- +Fri Apr 11 21:55:21 CEST 2008 - ma@suse.de + +- Install ResPoolProxy index to speedup Solvable to Selectable + conversion. +- version 4.11.0 +- revision 9558 + +------------------------------------------------------------------- +Fri Apr 11 18:02:14 CEST 2008 - kkaempf@suse.de + +- Implement update scripts installed by packages. After every + package install /var/adm/update-scripts is scanned for the first + file starting with "-.-", which is then + executed. +- revision 9547 + +------------------------------------------------------------------- +Fri Apr 11 14:43:05 CEST 2008 - ma@suse.de + +- Fix SolvIterMixin to avioid multiple visits of the same Selectable. +- Add Resolvable::poolItem() providing access to the corresponding + PoolItem. API to query isRelevant/isSatisfied/isBroken was moved + to PoolItem. +- Add ResPool::satisfiedProductsBegin/End iterator over all products + whose dependencies are satisfied. This reflects the status determined + by the last solver run. (#368104) +- revision 9535 + +------------------------------------------------------------------- +Fri Apr 11 12:07:47 CEST 2008 - jreidinger@suse.cz + +- switch to new locks api +- revision 9524 + +------------------------------------------------------------------- +Wed Apr 9 21:24:54 CEST 2008 - ma@suse.de + +- Enable ui::Selectable lookup by Solvable/PoolItem in ResPoolProxy. +- Add SolvIterMixin: Base class providing PoolItem_iterator and + Selectable_iterator iterator types based on a Solvable iterator. +- Enhanced WhatProvides and SolvableSet to PoolItem_iterator to offer + PoolItem_iterator and Selectable_iterator. +- Add Solvable::SplitIdent: Helper class that splits an identifier + into kind and name. +- Provide methods Pattern::contents returning a collection of packages + associated with the pattern/patch. +- revision 9496 + +------------------------------------------------------------------- +Tue Apr 8 15:50:48 CEST 2008 - jreidinger@suse.cz + +- add comparing to PoolQuery +- revision 9466 + +------------------------------------------------------------------- +Tue Apr 8 13:18:30 CEST 2008 - jreidinger@suse.cz + +- move RepoInfo to universal RepoException. This can enable more verbose output - for frontend. (helps with bnc #377137) +- revision 9452 + +------------------------------------------------------------------- +Tue Apr 8 10:52:30 CEST 2008 - jreidinger@suse.cz + +- initial implementation of new locks (FATE #120118 and #120352) +- revision 9442 + +------------------------------------------------------------------- +Tue Apr 7 15:18:22 CEST 2008 - dmacvicar@suse.de + +- selectable API updates and changes +- 4.10.0 + +------------------------------------------------------------------- +Fri Apr 4 14:01:45 CEST 2008 - jreidinger@suse.cz + +- add split with respect to escaped delimeters and also for quotes +- revision 9373 + +------------------------------------------------------------------- +Thu Apr 3 12:55:50 CEST 2008 - ma@suse.de + +- Fixed some missing package and source package attributes. +- revision 9348 + +------------------------------------------------------------------- +Thu Apr 3 11:59:13 CEST 2008 - ma@suse.de + +- Allow to store a media label in MediaSetAccess. This label is + passed to a media change requests to describe which CD is + requested. (bnc #330094) +- Fixed some missing package and source package attributes. +- revision 9347 + +------------------------------------------------------------------- +Wed Apr 2 13:48:52 CEST 2008 - schubi@suse.de + +- Moved poolItem.status().isSatisfied(),.... to poolItem.isSatisfied() +- Removed establish state in ResStatus +- revision 9337 +- version 4.7.0 + +------------------------------------------------------------------- +Wed Apr 2 10:24:17 CEST 2008 - ma@suse.de + +- Add PoolItem::isSatisfied()/isBroken() to test whether + the items requirements are met. +- revision 9334 + +------------------------------------------------------------------- +Tue Apr 1 21:54:10 CEST 2008 - ma@suse.de + +- Extend sat::WhatProvides allows one to query for possible providers + of a collection of capabilies. E.g. all providers of a packages + requirements. +- Fixed retrieval of translated texts from .solv files, provided the + solv file contains them. +- revision 9328 + +------------------------------------------------------------------- +Tue Apr 1 16:17:44 CEST 2008 - jreidinger@suse.cz + +- initial implementation of serialize/recovery PoolQuery + (needed by FATE #120118) +- revision 9325 + +------------------------------------------------------------------- +Wed Mar 26 16:15:24 CET 2008 - ma@suse.de + +- Allow prioritizing repos by adding a line 'priority=N' to the + .repo file. Where N is an integer number from 1 (highest prio) + to 99 (least and default). (bnc #369827, fate #302872) +- version 4.6.1 +- revision 9276 + +------------------------------------------------------------------- +Mon Mar 24 21:17:05 CET 2008 - coolo@suse.de + +- support plaindir again (at least the most important parts) + +------------------------------------------------------------------- +Fri Mar 21 13:23:13 CET 2008 - jreidinger@suse.cz + +- Throwing special exception MediaBadCAException in case of SSL + certificate validation failure.(bnc #223512) +- revision 9250 + +------------------------------------------------------------------- +Fri Mar 21 12:38:39 CET 2008 - jreidinger@suse.cz + +- add new error IO_SOFT to media request callback for temporary + connection problem. (bnc #328822) +- add new media exception timeout when somethink fail due to exceed + timeout +- mediacurl throw timeout exception when timeouted +- revision 9246 + +------------------------------------------------------------------- +Thu Mar 20 15:00:24 CET 2008 - jreidinger@suse.cz + +- return more information from checking if metadata need refresh, + so user can get better info. (bnc #307249) +- revision 9231 + +------------------------------------------------------------------- +Tue Mar 18 21:59:04 CET 2008 - ma@suse.de + +- class sat::LocaleSupport: Convenience methods to manage support + for language specific packages. +- revision 9197 + +------------------------------------------------------------------- +Tue Mar 18 13:54:16 CET 2008 - jkupec@suse.cz + +- removed obsolete capability handling stuff (ma) +- version 4.5.0 + +------------------------------------------------------------------- +Tue Mar 18 11:42:51 CET 2008 - jreidinger@suse.cz + +- Don't mask skip and abort exception in Fetcher +- revision 9188 + +------------------------------------------------------------------- +Tue Mar 18 11:00:22 CET 2008 - jreidinger@suse.cz + +- action is correctly set in mediaRequest callback +- revision 9186 + +------------------------------------------------------------------- +Mon Mar 17 12:33:44 CET 2008 - ma@suse.de + +- Fix SEGV in commit (bnc# 371137) +- version 4.4.3 +- revision 9174 + +------------------------------------------------------------------- +Fri Mar 14 17:28:39 CET 2008 - ma@suse.de + +- version 4.4.2 + +------------------------------------------------------------------- +Fri Mar 14 14:27:43 CET 2008 - dmacvicar@suse.de + +- look for openssl in cmake, actually we build require it +- explicitly link against openssl and crypto, required to + compile in all platforms/distros. + +------------------------------------------------------------------- +Fri Mar 14 12:07:41 CET 2008 - jreidinger@suse.cz + +- Save repo type during refresh if type is NONE (f.e. lazy probing). +- revision 9153 + +------------------------------------------------------------------- +Fri Mar 14 11:34:24 CET 2008 - jreidinger@suse.cz + +- replace gpg escaped semicolon with real semicolon (bnc #355434) +- revision 9151 + +------------------------------------------------------------------- +Fri Mar 14 10:17:41 CET 2008 - jreidinger@suse.cz + +- make strings from RpmDb and Keyring exceptions translatable +- revision 9146 + +------------------------------------------------------------------- +Thu Mar 13 18:41:26 CET 2008 - dmacvicar@suse.de + +- fix retrieving keys (bnc #368099) +- version 4.4.1 + +------------------------------------------------------------------- +Thu Mar 13 18:40:57 CET 2008 - jreidinger@suse.cz + +- enable frontend to rewrite add_probe settings.(bnc #309612) +- Correct adding repo without type to lazy probing. +- revision 9135 + +------------------------------------------------------------------- +Thu Mar 13 17:59:52 CET 2008 - jreidinger@suse.cz + +- get better message if something fail when trying run rpm + (bnc #344584) +- revision 9133 + +------------------------------------------------------------------- +Thu Mar 13 12:33:13 CET 2008 - ma@suse.de + +- Add ExternalProgram::execError and ExternalProgram::command + to improve error reporting. +- revision 9112 + +------------------------------------------------------------------- +Thu Mar 13 11:45:20 CET 2008 - jkupec@suse.cz + +- release all media before requesting another (bnc #336881) +- revision 9110 + +------------------------------------------------------------------- +Thu Mar 13 11:32:56 CET 2008 - jkupec@suse.cz + +- getDetectedDevices added (fate #120298) +- revision 9108 + +------------------------------------------------------------------- +Wed Mar 12 15:55:14 CET 2008 - jkupec@suse.cz + +- media backend release() methods changed to take string & instead + of bool (needed for FATE #120298) +- media label, detected device list and current device arguments + added to the requestMedia callback +- version 4.4.0 + +------------------------------------------------------------------- +Wed Mar 12 14:16:07 CET 2008 - coolo@suse.de + +- fix for bnc#369543 + +------------------------------------------------------------------- +Mon Mar 10 13:30:04 CET 2008 - jkupec@suse.cz + +- provide download rate info (average and curent) in the + media::DownloadProgressReport for ftp/http (bnc #168935) +- r9074 + +------------------------------------------------------------------- +Mon Mar 10 12:45:03 CET 2008 - jkupec@suse.cz + +- cleanCache(): clean also .cookie files +- cleanTargetCache() added +- use escaped_alias() in rawcache_path_for_repoinfo() and + packagescache_path_for_repoinfo() +- r9068 + +------------------------------------------------------------------- +Fri Mar 7 19:59:10 CET 2008 - jkupec@suse.cz + +- fixed location of RPMs in subdirs when parsing plaindir repo + recursively (bnc #368218) +- revision 9060 + +------------------------------------------------------------------- +Thu Mar 6 13:42:53 CET 2008 - ma@suse.de + +- Do not filter any installed solvables. +- revision 9031 +- version 4.3.2 + +------------------------------------------------------------------- +Wed Mar 5 11:33:26 CET 2008 - ma@suse.de + +- Try to rebuild broken solv files in Target::load. +- revision 9015 + +------------------------------------------------------------------- +Tue Mar 4 18:17:41 CET 2008 - ma@suse.de + +- Try to rebuild broken solv files in RepoManager::loadFromCache. +- Fix RepoStatus::operator&& and RepoStatus testsuite. +- revision 9008 + +------------------------------------------------------------------- +Tue Mar 4 16:09:14 CET 2008 - schubi@suse.de + +- improved problem description while a vendor change +- improved problem description if a requirement cannot be fulfilled. Bug #358560 +- revision 9002 + +------------------------------------------------------------------- +Tue Mar 4 12:57:58 CET 2008 - ma@suse.de + +- Save and restore requested locales on target load/commit. +- revision 8999 + +------------------------------------------------------------------- +Mon Mar 3 17:10:26 CET 2008 - schubi@suse.de + +- (Update) Prevent reinstallation of installed packages. +- revision 8984 + +------------------------------------------------------------------- +Sun Mar 2 16:13:16 CET 2008 - coolo@suse.de + +- refresh metadata if there is no cache to unbreak compat with + kiwi (that relied on "zypper sa " to create a repo + that "zypper in" could work on) + +------------------------------------------------------------------- +Sun Mar 2 10:28:13 CET 2008 - coolo@suse.de + +- create cache directory before calling rpmdb2solv (in an empty + chroot) +- version 4.3.1 + +------------------------------------------------------------------- +Thu Feb 28 16:43:11 CET 2008 - jkupec@suse.cz + +- special exception message if server returns 403 response + (forbidden) (port from SP2) +- MediaException messages marked for translation + +------------------------------------------------------------------- +Wed Feb 27 10:31:24 CET 2008 - dmacvicar@suse.de + +- make sure we have target cache on target initialize +- version 4.3.0 + +------------------------------------------------------------------- +Tue Feb 26 13:59:03 CET 2008 - lslezak@suse.cz + +- DiskUsageCounter.cc - ignore "vfat", "fat", "ntfs" and "ntfs-3g" + file systems (#333166) +- rev. 8915 + +------------------------------------------------------------------- +Tue Feb 26 13:26:30 CET 2008 - ma@suse.de + +- Fixed Capabilites iterator exposing prereq marker. +- revision 8914 + +------------------------------------------------------------------- +Tue Feb 26 11:29:05 CET 2008 - schubi@suse.de + +- postinstall script fixed +- version 4.2.10 + +------------------------------------------------------------------- +Mon Feb 25 17:06:53 CET 2008 - schubi@suse.de + +- Testcases regards modaliases, rpmlib, ... correctly +- Revision 8904 + +------------------------------------------------------------------- +Mon Feb 25 13:20:26 CET 2008 - ma@suse.de + +- Remove obsolete sql database. (bnc#363224) +- revision 8898 + +------------------------------------------------------------------- +Fri Feb 22 14:03:59 CET 2008 - ma@suse.de + +- Take care target uses --root when creating solv files (bnc #363789) +- revision 8881 + +------------------------------------------------------------------- +Fri Feb 22 10:10:14 CET 2008 - schubi@suse.de + +- Unmaintained packages which does not fit to the updated system + (broken dependencies) will be deleted. +- revision 8867 + +------------------------------------------------------------------- +Fri Feb 22 07:20:35 CET 2008 - coolo@suse.de + +- let libzypp-devel require libsatsolver-devel + +------------------------------------------------------------------- +Wed Feb 20 13:47:56 CET 2008 - ma@suse.de + +- Cleanup unused /var/lib/zypp/cache in migrate_sources (#305160) +- revision 8833 + +------------------------------------------------------------------- +Tue Feb 19 16:21:12 CET 2008 - jkupec@suse.cz + +- media: fixed DownloadProgressReport.finish() url argument in + doGetFileCopy() +- revision 8815 + +------------------------------------------------------------------- +Tue Feb 19 11:21:59 CET 2008 - dmacvicar@suse.de + +- hardlink when possible to optimize data transfer + and space across caches. +- version 4.2.8 + +------------------------------------------------------------------- +Tue Feb 19 08:15:07 CET 2008 - coolo@suse.de + +- added some locale support to sat::Solvable +- version 4.2.7 + +------------------------------------------------------------------- +Mon Feb 18 14:15:48 CET 2008 - dmacvicar@suse.de + +- handle error messages better in doesFileExist too which is + used during probing. (bnc #362608) + +------------------------------------------------------------------- +Sun Feb 17 21:44:12 CET 2008 - dmacvicar@suse.de + +- Fetcher::reset() should not reset cache directories. + (bnc #348050) +- version 4.2.6 + +------------------------------------------------------------------- +Fri Feb 16 15:47:00 CET 2008 - dmacvicar@suse.de + +- Use CURLOPT_NOBODY instead of a CURLOPT_RANGE of 1 byte + for http and https, but this time set CURLOPT_HTTPGET back to 1 + so it actually works. This makes Media::doesFileExist + efficient for http and https. + (related to bnc #348050) +- version 4.2.5 + +------------------------------------------------------------------- +Fri Feb 15 10:52:59 CET 2008 - coolo@suse.de + +- using .solv files only now (fate #303018) +- revision 8699 + +------------------------------------------------------------------- +Tue Feb 12 17:10:48 CET 2008 - coolo@suse.de + +- fix architectures on distupgrade + +------------------------------------------------------------------- +Fri Feb 8 12:50:30 CET 2008 - coolo@suse.de + +- fixes from trunk merged + +------------------------------------------------------------------- +Fri Feb 1 17:45:07 CET 2008 - jkupec@suse.cz + +- fixed renaming a repo to an existing one (bnc #228216) +- revision 8431 + +------------------------------------------------------------------- +Sun Jan 27 21:35:13 CET 2008 - coolo@suse.de + +- fix changelog + +------------------------------------------------------------------- +Thu Jan 24 18:26:47 CET 2008 - jkupec@suse.cz + +- read .curlrc more robustly to obtain user-proxy (#330351) +- revision 8368 + +------------------------------------------------------------------- +Fri Jan 18 12:19:09 CET 2008 - coolo@suse.de + +- always buildrequire openssl-devel +- replacing strange utf-8 chars in changelog +- revision 8317 + +------------------------------------------------------------------- +Thu Jan 17 15:07:52 CET 2008 - jkupec@suse.cz + +- Saner NFS timeo default (#350309) +- revision 8314 + +------------------------------------------------------------------- +Thu Jan 17 12:03:10 CET 2008 - kkaempf@suse.de + +- support 'patterns.pat' and 'patterns.pat.gz' to read all + patterns in one go. +- rev 8309 + +------------------------------------------------------------------- +Tue Jan 15 14:56:21 CET 2008 - lslezak@suse.cz + +- added RpmDb::removePubkey(), call it from + KeyRing::Impl::deleteKey() - remove the GPG key from RPM when it + is removed from the trusted keyring +- revision 8288 + +------------------------------------------------------------------- +Mon Jan 14 17:11:15 CET 2008 - schubi@suse.de + +- Textchanges +- reduced logging in SAT-solver +- ordering solutions +- version 4.1.8 +- revision 8276 + +------------------------------------------------------------------- +Thu Jan 10 16:50:26 CET 2008 - schubi@suse.de + +- Enabled SAT solver via default. (removed ZYPP_SAT_SOLVER) + ZYPP_RC_SOLVER=1 will enable the old RedCapet solver +- Revision 8255 +- Version 4.1.7 + +------------------------------------------------------------------- +Wed Jan 2 18:24:34 CET 2008 - jkupec@suse.cz + +- Pathname zypp::filesystem::expandlink(const Pathname &) added +- if the provided file is a symlink, expand it (#274651) (this + probably won't work for schemes other than file/dir and cd/dvd) +- revision 8179 + +------------------------------------------------------------------- +Tue Dec 18 12:28:22 CET 2007 - aschnell@suse.de + +- fixed password handling in URLs (bug #347273) +- revision 8118 + +------------------------------------------------------------------- +Mon Dec 17 13:47:44 CET 2007 - ma@suse.de + +- Fixed default text locale detection not to use static variables. (#346872) +- version 4.1.6 +- revision 8116 + +------------------------------------------------------------------- +Mon Dec 10 12:46:26 CET 2007 - ma@suse.de + +- Log more details about zypp lock owner. (#294094) +- revision 8088 + +------------------------------------------------------------------- +Fri Dec 7 15:47:53 CET 2007 - ma@suse.de + +- Remove runtime dependency for libboost_filesystem (#345773) +- version 4.1.5 +- revision 8061 + +------------------------------------------------------------------- +Fri Nov 30 14:20:34 CET 2007 - schubi@suse.de + +- Enable SAT solver via environment variable ZYPP_SAT_SOLVER. + e.g.: ZYPP_SAT_SOLVER=1 zypper install foo +- version 4.1.4 +- revision 7998 + +------------------------------------------------------------------- +Wed Nov 28 15:12:33 CET 2007 - aschnell@suse.de + +- make IniParser more strict (bug #306697) + +------------------------------------------------------------------- +Mon Nov 26 13:19:34 CET 2007 - ma@suse.de + +- Fix missing packages in patch content list. (#340896) +- revision 7925 + +------------------------------------------------------------------- +Fri Nov 16 12:46:39 CET 2007 - coolo@suse.de + +- fix build + +------------------------------------------------------------------- +Wed Nov 14 14:23:23 CET 2007 - ma@suse.de + +- Output date strings in UTF-8. (#339423) +- revision 7807 + +------------------------------------------------------------------- +Tue Nov 13 13:40:03 CET 2007 - schubi@suse.de + +- fixes for new gcc +- version 4.1.3 +- r7788 + +------------------------------------------------------------------- +Mon Nov 5 15:22:33 CET 2007 - ma@suse.de + +- Don't mark failed patch scripts as installed. (#327523) +- version 4.1.2 +- revision 7744 + +------------------------------------------------------------------- +Wed Oct 31 09:19:59 CET 2007 - dmueller@suse.de + +- update rpmlint suppression + +------------------------------------------------------------------- +Fri Oct 26 15:12:24 CEST 2007 - aschnell@suse.de + +- fixed retrieval of epoch from rpmdb (bug #246680) + +------------------------------------------------------------------- +Thu Oct 25 16:29:24 CEST 2007 - aschnell@suse.de + +- allow non-existing "packages" file in susetags parser (bug + #309235) + +------------------------------------------------------------------- +Fri Oct 12 15:47:37 CEST 2007 - ma@suse.de + +- SMBIOS DMI modalias matching added (#333152) +- revision 7494 + +------------------------------------------------------------------- +Sat Oct 6 16:37:11 CEST 2007 - jkupec@suse.cz +- do not download the same file multiple times in one attach session + (#307098), r7456 +- special cdrom detection code for SCSI / Virtual CDROMs on iSeries + removed - should be correctly detected by HAL now + (#167629, #163971), r7452 +- version 4.1.1 + +------------------------------------------------------------------- +Fri Oct 05 10:35:47 CEST 2007 - aschnell@suse.de + +- filter architecture in plaindir parser (bug #330791) + +------------------------------------------------------------------- +Thu Oct 4 16:31:58 CEST 2007 - ma@suse.de + +- Throw constructing malformed checksums. (#189096) +- revision 7441 + +------------------------------------------------------------------- +Thu Oct 4 14:22:31 CEST 2007 - mvidner@suse.cz + +- Renamed templates back because proper qualification makes it work + too. +- 4.1.0 + +------------------------------------------------------------------- +Thu Oct 04 11:23:19 CEST 2007 - aschnell@suse.de + +- only look for repositories in file ending ".repo" (bug #294779) + +------------------------------------------------------------------- +Wed Oct 3 13:37:57 CEST 2007 - mvidner@suse.cz + +- Fixed compilation errors with GCC 4.3 by adding missing includes + and renaming templates: MaxBits to MaxBitsT, Mask to MaskT, + Compare to CompareEd. +- r7426 + +------------------------------------------------------------------- +Mon Oct 1 20:29:36 CEST 2007 - ma@suse.de + +- Incorporated patch from Michael Matz to speedup cache reading. +- revision 7413 + +------------------------------------------------------------------- +Fri Sep 28 18:40:59 CEST 2007 - schubi@suse.de + +- Resolvertestcase: + - log Repository info + - set keep state in the testcase + - handle vendor +- r 4707 + +------------------------------------------------------------------- +Thu Sep 27 17:13:14 CEST 2007 - ma@suse.de + +- Fixed pattern parser SEGV on broken pattern files. (#328546) +- revision 7402 + +------------------------------------------------------------------- +Wed Sep 26 11:08:14 CEST 2007 - schubi@suse.de + +- QueuItemRequire: Filter out all provider which have worser architecture, + are NOT noarch and have not the same name as the requirement. The + last one is needed for updating packages via patch/atoms. + Bug 328081 +- Revert changes of r 7340 +- r 7386 + +------------------------------------------------------------------- +Tue Sep 25 15:51:34 CEST 2007 - ma@suse.de + +- Add missing '--install' parameter in desktop file. (#308640) +- version 4.0.0 +- revision 7369 + +------------------------------------------------------------------- +Tue Sep 25 11:08:13 CEST 2007 - jkupec@suse.cz + +- release all attached media before attempting to eject (#293428) +- fixed parsing of --proxy-user parameter of .curlrc (#309139) +- revision 7352 +- version 3.26.0 + +------------------------------------------------------------------- +Mon Sep 24 16:10:32 CEST 2007 - dmacvicar@suse.de + +- provide a way to retrieve the metadata path. Used for + installation, which incorrectly creates a repository in + cache without adding it first, so metadata path is not + set and therefore it is not possible to setup a media + verifier on installation. Part of fix for (#293428) +- 3.25.0 + +------------------------------------------------------------------- +Mon Sep 24 15:48:47 CEST 2007 - schubi@suse.de + +- If more than one resolvables provide a requirements and have different + architecture take thatone with the best architecture. (Not regarding the + name). Bug: Branching too much while an installation of a multi-arch-DVD +- r 7340 +- version 3.24.8 + +------------------------------------------------------------------- +Fri Sep 21 15:50:30 CEST 2007 - schubi@suse.de + +- Checking the queue if an item will be deleted. If yes, the requirements + are not needed anymore. Bug 326384 +- version 3.24.7 +- r 7329 + +------------------------------------------------------------------- +Thu Sep 20 17:37:30 CEST 2007 - jkupec@suse.cz + +- don't probe the repository type upon saving if disabled (#326769) +- version 3.24.6 +- revision 7319 + +------------------------------------------------------------------- +Thu Sep 20 15:19:53 CEST 2007 - ma@suse.de + +- Avoid calling rpm repeatedly in case of an error. This is fault-prone, + esp. if the error occurred executing the packages post-install script. +- version 3.24.5 +- revision 7317 + +------------------------------------------------------------------- +Thu Sep 20 11:00:04 CEST 2007 - ma@suse.de + +- If a package is deselected by user, apply this soft lock to all + available versions of this package. +- version 3.24.4 +- revision 7316 + +------------------------------------------------------------------- +Wed Sep 19 17:45:12 CEST 2007 - schubi@suse.de + +- Update: Do not set an item to installation if there has been already set + one for installation which has the same NVA. Bug 326286 +- version 3.24.3 +- r 7311 + +------------------------------------------------------------------- +Wed Sep 19 14:19:49 CEST 2007 - ma@suse.de + +- Enable package cache during commit. (#326249) +- revision 7309 + +------------------------------------------------------------------- +Tue Sep 18 14:01:02 CEST 2007 - schubi@suse.de + +- Do not regarding requirements for packages which will be deleted in the + same solver run. Bug 310618 +- r 7292 +- version 3.24.2 + +------------------------------------------------------------------- +Mon Sep 17 16:33:14 CEST 2007 - jkupec@suse.cz + +- don't download filelists.xml.gz (#307105) +- version 3.24.1 +- revision 7269 + +------------------------------------------------------------------- +Mon Sep 17 15:51:04 CEST 2007 - ma@suse.de + +- Improve estimated diskusage while there is no valid + solver result. (#325617) +- revision 7266 + +------------------------------------------------------------------- +Mon Sep 17 15:22:47 CEST 2007 - schubi@suse.de + +-Bugfix in vendor change of a required resolvable (Correct error message) + Bug 310455 +- r 7262 + +------------------------------------------------------------------- +Mon Sep 17 12:36:28 CEST 2007 - lslezak@suse.cz + +- fixed DU parsing in inst-sys (#308659) +- revision 7256 + +------------------------------------------------------------------- +Fri Sep 14 22:57:54 CEST 2007 - ma@suse.de + +- Enable using patch and delta rpms. (#309124) +- version 3.24.0 +- revision 7253 + +------------------------------------------------------------------- +Thu Sep 13 17:59:55 CEST 2007 - ma@suse.de + +- On update do not delete unmaintained non-SuSE packages. +- version 3.23.2 +- revision 7239 + +------------------------------------------------------------------- +Thu Sep 13 13:02:39 CEST 2007 - lslezak@suse.cz + +- ZYppImpl::getPartitions() - don't return the current partitioning + when the partitioning hasn't been set - fixes DU parsing in + inst-sys (#308659) + +------------------------------------------------------------------- +Thu Sep 13 11:30:47 CEST 2007 - dmacvicar@suse.de + +- Throw specific exceptions during commit (#308511) +- 3.23.1 + +------------------------------------------------------------------- +Wed Sep 12 18:48:00 CEST 2007 - ma@suse.de + +- Various disk space calculation fixes. Susetags, plaindir and rpmdb + now provide more detailed disk usage information. + Yum metadata don't, so we book the package size to '/'. (#308362) +- version 3.23.0 +- revision 7225 + +------------------------------------------------------------------- +Wed Sep 12 15:48:41 CEST 2007 - schubi@suse.de + +- Regarding keep state while recycle old valid solver results. Bug 286889 +- r 7209 + +------------------------------------------------------------------- +Wed Sep 12 12:24:49 CEST 2007 - jkupec@suse.cz + +- report 100% progress on finishing RPM removal (bug #309431) +- revision 7200 + +------------------------------------------------------------------- +Tue Sep 11 17:25:35 CEST 2007 - schubi@suse.de + +- Update: rename language packages --> take that package which fits to the + selected language Bug 308098 +- r 7919 + +------------------------------------------------------------------- +Tue Sep 11 16:11:20 CEST 2007 - dmacvicar@suse.de + +- restore deltas and patch rpms from the cache (#309124) +- 3.22.8 + +------------------------------------------------------------------- +Tue Sep 11 14:54:44 CEST 2007 - ma@suse.de + +- Don't fail if a product is deleted multiple times (e.g. due to + obsoletes and an explicit deleted request). (#308746) +- version 3.22.7 +- revision 7184 + +------------------------------------------------------------------- +Tue Sep 11 13:52:47 CEST 2007 - jkupec@suse.cz + +- SYSCONFDIR variable added for modifying /etc + +------------------------------------------------------------------- +Tue Sep 11 12:18:11 CEST 2007 - schubi@suse.de + +- uninstallable resolvable -->suggested solution: delete; Bug 308164 +- r 7177 + +------------------------------------------------------------------- +Mon Sep 10 16:19:05 CEST 2007 - schubi@suse.de + +- new translations added +- r 7166 +- version 3.22.6 + +------------------------------------------------------------------- +Mon Sep 10 15:50:49 CEST 2007 - lslezak@suse.cz + +- fixed disk usage counting of updated packages (#308362) + +------------------------------------------------------------------- +Mon Sep 10 14:17:29 CEST 2007 - schubi@suse.de + +- Splitting packages: Take the package with the best + architecture,edition ONLY; Bug 308591 +- r 7160 + +------------------------------------------------------------------- +Mon Sep 10 10:55:45 CEST 2007 - lslezak@suse.cz + +- properly report fallback disk usage size (in kB instead of bytes) + when disk usage is not known (YUM repos) (#308475) + +------------------------------------------------------------------- +Fri Sep 7 13:27:26 CEST 2007 - ma@suse.de + +- Install a sample /etc/zypp.conf. (#306615) +- Fixed missing soversion symlink in package. +- version 3.22.5 +- revision 7150 + +------------------------------------------------------------------- +Fri Sep 7 13:03:48 CEST 2007 - schubi@suse.de + +- RequirementIsMet: return true only if ALL Atoms are NOT incomplete; Bug + 308252 +- r 7143 + +------------------------------------------------------------------- +Thu Sep 6 18:22:36 CEST 2007 - schubi@suse.de + +- Error: Select two candidate with the same name while update. + Solution: If there is a candidate which is already selected for installation --> + take thatone #308082 +- r 7132 + +------------------------------------------------------------------- +Thu Sep 6 14:11:58 CEST 2007 - ma@suse.de + +- Work arround installed patterns providing an empty vendor string. (#307743) +- Let the solver treat vendor suse and opensuse as equivalent. +- version 3.22.4 + +------------------------------------------------------------------- +Thu Sep 6 12:33:27 CEST 2007 - schubi@suse.de + +- Checking item before evaluating the concerning vendor. bug #307941 +- r 7119 + +------------------------------------------------------------------- +Wed Sep 6 02:24:37 CEST 2007 - dmacvicar@suse.de + +- Fix for bug #307163 - empty package descriptions + a.k.a shared tag not 100% implemented +- r 7117 +- version 3.22.3 + +------------------------------------------------------------------- +Wed Sep 5 17:52:37 CEST 2007 - schubi@suse.de + +- logging "reverse" NEEDED_BY in the detail description of solver + problems. +- improved error message if a requiremnt is not fulfilled Bug 307743 +- Add "ignore" option to the solution if a requirement is not fulfilled + Bug 304276 +- revision 7113 + +------------------------------------------------------------------- +Wed Sep 5 14:33:02 CEST 2007 - jkupec@suse.cz + +- fixed the order of operands of susetags local metadata status + computation which caused the YaST repositories to always get + refreshed (part of bug #304310) +- revision 7107 +- version 3.22.2 + +------------------------------------------------------------------- +Tue Sep 4 12:09:10 CEST 2007 - schubi@suse.de + +- comparing vendor with VendorAttr::equivalent +- revision 7103 + +------------------------------------------------------------------- +Mon Sep 3 18:43:51 CEST 2007 - schwab@suse.de + +- Use $RPM_OPT_FLAGS. + +------------------------------------------------------------------- +Mon Sep 3 17:14:02 CEST 2007 - ma@suse.de + +- Reset transact bits when switching status from + "update" to "protected" (#246976) +- version 3.22.1 +- revision 7094 + +------------------------------------------------------------------- +Mon Sep 3 13:56:42 CEST 2007 - schubi@suse.de + +- new translations added +- rev 7083 + +------------------------------------------------------------------- +Fri Aug 31 22:10:55 CEST 2007 - ma@suse.de + +- Added ability to switch off use of patch and delta rpms via zypp.conf (#305864) + [main] + download.use_patchrpm = no + download.use_deltarpm = no +- version 3.22.0 +- revision 7069 + +------------------------------------------------------------------- +Fri Aug 31 19:56:40 CEST 2007 - ma@suse.de + +- On demand translate patch requirements into a list of atoms. + Required by the UI to display packages acssociated with a patch. + (#300612) +- version 3.21.1 +- revision 7065 + +------------------------------------------------------------------- +Fri Aug 31 13:59:54 CEST 2007 - kkaempf@suse.de + +- enrich ResolverInfo with the reason if a user-initiated request + fails (#304325, #306240) +- r 7051 + +------------------------------------------------------------------- +Thu Aug 30 20:10:00 CEST 2007 - jkupec@suse.cz + +- added missing implementation of LogControl::setLineFormater() + (lslezak) +- version 3.21.0 +- revision 7041 + +------------------------------------------------------------------- +Thu Aug 30 18:55:15 CEST 2007 - jkupec@suse.cz + +- enable changing url in requestMedia callback (#294481) +- revision 7037 + +------------------------------------------------------------------- +Thu Aug 30 18:22:32 CEST 2007 - ma@suse.de + +- Filter readonly mount points in DiskUsageCounter (#297405) +- revision 7030 + +------------------------------------------------------------------- +Thu Aug 30 17:31:33 CEST 2007 - jkupec@suse.cz + +- remember the cause of the RepoException when refreshing metadata + (#301022) +- r7023 + +------------------------------------------------------------------- +Thu Aug 30 17:25:14 CEST 2007 - ma@suse.de + +- Safe fix for bug #299680. +- version 3.20.1 +- revision 7026 + +------------------------------------------------------------------- +Thu Aug 30 15:48:03 CEST 2007 - schubi@suse.de + +- Bugfix: If a requirement has been fulfilled by more than one language + resolvables only thatone will be taken which fits to the selected + language. +- r 7018 + +------------------------------------------------------------------- +Thu Aug 30 15:14:23 CEST 2007 - jkupec@suse.cz + +- correct error code for media errors in MediaCurl::doGetFileCopy() + affects only zypper error output, does not affect YaST +- r7013 + +------------------------------------------------------------------- +Wed Aug 29 18:28:41 CEST 2007 - jkupec@suse.cz + +- reverted blocking of requestMedia from r6271 (#301710) +- r6999 + +------------------------------------------------------------------- +Wed Aug 29 18:09:29 CEST 2007 - kkaempf@suse.de + +- prevent progress report in destructor (#299680) +- r6998 + +------------------------------------------------------------------- +Wed Aug 29 18:02:36 CEST 2007 - jkupec@suse.cz + +- treat non-filelists.xml entries as file provides capabilities + in YUM parser (#304701) +- r6992 + +------------------------------------------------------------------- +Wed Aug 29 16:32:01 CEST 2007 - kkaempf@suse.de + +- the media.1/media uniquely identifies a 'susetags' repo, not + the content file (#304200) + +------------------------------------------------------------------- +Wed Aug 29 15:42:17 CEST 2007 - jkupec@suse.cz + +- fixed locale dir (#304649) +- r6984 + +------------------------------------------------------------------- +Wed Aug 29 15:39:52 CEST 2007 - kkaempf@suse.de + +- don't treat normal package license as "license to confirm" + (#305906) + +------------------------------------------------------------------- +Wed Aug 29 15:28:53 CEST 2007 - ma@suse.de + +- Fixed fix for #293039. Segfault due to uninitialzed data. +- version 3.19.3 +- revision 6980 + +------------------------------------------------------------------- +Wed Aug 29 15:10:20 CEST 2007 - schubi@suse.de + +- reduced too much verbosed ResolverContext logging; Bug 303971 +- r 6977 + +------------------------------------------------------------------- +Wed Aug 29 13:55:28 CEST 2007 - ma@suse.de + +- Fixed PlainDir repositories to provide real disk usage data. For + repomd and others that do not provide any detailed disk usage info, + assume the packgage size is required below "/". Peviously they were + treated as being empy. +- version 3.19.2 +- revision 6972 + +------------------------------------------------------------------- +Wed Aug 29 13:36:42 CEST 2007 - schubi@suse.de + +- Add a new solver solution in the case of running in a timeout: + ProblemSolutionDoubleTimeout.h + #Bug 302496 +- revision 6970 + +------------------------------------------------------------------- +Wed Aug 29 11:23:26 CEST 2007 - dmacvicar@suse.de + +- bug in fix for (#292986) + +------------------------------------------------------------------- +Tue Aug 28 18:48:26 CEST 2007 - dmacvicar@suse.de + +- (#297001) - libzypp: can't skip broken packages +- re enable importing zypp keyring from rpm.(#302379) +- 3.19.1 + +------------------------------------------------------------------- +Tue Aug 28 17:30:30 CEST 2007 - kkaempf@suse.de + +- rename ResolvableQuery::iterateResolvablesByKindsAndStrings + to ResolvableQuery::iterateResolvablesByKindsAndStringsAndRepos + in order to support query-by-repo (#305384) +- fix iterateResolvablesByKindsAndStringsAndRepos to take any + number of kinds, names, or repos (#305347) +- remove ResolvableQuery::iterateResolvablesByKind, not needed +- version 3.19.0 +- rev 6935 + +------------------------------------------------------------------- +Tue Aug 28 11:27:53 CEST 2007 - dmacvicar@suse.de + +- real fix for reading signature ids. (#390535). +- delete metadata when removing repo (#301037). + +------------------------------------------------------------------- +Mon Aug 27 23:52:41 CEST 2007 - dmacvicar@suse.de + +- following behaviour for setPartitions + - if they are not set, they are detected + - if they are set, that value is used. + - if value set or detected is empty, all disk usage + information is read. Otherwise just values in those + mount points. + Should work for installation as long as detectPartitions + is empty at installation.(#293039) + +------------------------------------------------------------------- +Mon Aug 27 17:08:41 CEST 2007 - kkaempf@suse.de + +- Add ZConfig::overrideSystemArchitecture() to override zypp arch + from external, e.g. for the testcases +- Honor ZYPP_CONF environment variable to override the buit-in + /etc/zypp/zypp.conf +- Check architecture at handout() to prevent NULL ptr reference. +- Bug 301286 +- rev 6908 + +------------------------------------------------------------------- +Mon Aug 27 15:53:52 CEST 2007 - schubi@suse.de + +-The solver generate an establish call for all + resolvables which has filesystemcaps if there is not a valid result from a + former solver run available. This covers: + * Initial solver run + * Changing of filesystem whithin a workflow, cause the solver results will + be reset if the filesystem dependencies have been changed + Bug 271912 +- r 6901 + +------------------------------------------------------------------- +Sun Aug 26 15:49:27 CEST 2007 - kkaempf@suse.de + +- pass location to plaindir package (#303751) +- Add name of file in question to checksum/signature related + exceptions. +- pass basename of file to verifyFileSignatureWorkflow (instead of + empty string). +- filter out incompatible architectures when parsing sustags + repos (first half of #301286) +- r 6882 + +------------------------------------------------------------------- +Fri Aug 24 11:52:27 CEST 2007 - dmacvicar@suse.de + +- don't run source migration if yast is running in + intsys mode (#297136) +- signature and checksum verification fixes. Still pending + problem ZYpp getting no output from gpg when running from zypper. + (#302059) + +------------------------------------------------------------------- +Thu Aug 23 13:51:41 CEST 2007 - schubi@suse.de + +- Do not strip resolvables which have the same name but different kind + (ResolverInfo*) +- Flag info NEEDEDBY correctly if it will be used by freshen/supplement +- r 6830 + +------------------------------------------------------------------- +Wed Aug 22 18:58:44 CEST 2007 - mvidner@suse.cz + +- Do not use "a-z" in regexes. Fixes "Invalid Url scheme 'http'" in + the Estonian locale (#302525). + +------------------------------------------------------------------- +Wed Aug 22 17:59:39 CEST 2007 - aschnell@suse.de + +- added remembering of exception history at various places + +------------------------------------------------------------------- +Wed Aug 22 16:52:09 CEST 2007 - schubi@suse.de + +- Bugfixes concerning vendor handling: +- first bug: + Installed A-1.0(vendor SuSE) + Available A-2.0(other vendor) + A will not be regarded as "unmaintained". So it will not be deleted. +- second bug: + A need B-2.0. B-1.0 is installed but has another vendor. Report a + proper errmessage. +- Testcase : solution-tests/vendor-test.xml +- r 6812 +- 3.18.4 + +------------------------------------------------------------------- +Tue Aug 21 15:38:08 CEST 2007 - dmacvicar@suse.de + +- ignore HASH key for download (#300982) + +------------------------------------------------------------------- +Tue Aug 21 15:17:23 CEST 2007 - schubi@suse.de + +- Added explicitly_requested as parameter in ResolverContext::Uninstall + Bug 299819 +- revision 6794 + +------------------------------------------------------------------- +Tue Aug 21 13:06:44 CEST 2007 - dmacvicar@suse.de + +- If no mount information is available, parse all DU entries. +- read only hack mode for migrate-sources. We actually do add + repositories with it, but no harm. (#292986) +- fix some typos in exceptions (#301331) +- 3.18.3 + +------------------------------------------------------------------- +Mon Aug 20 16:06:36 CEST 2007 - schubi@suse.de + +- Do not regard explicit request in order to recognize updated packages + correctly. Bug 301676 +- Updated translations +- r 6766 +- 3.18.2 + +------------------------------------------------------------------- +Mon Aug 20 15:35:46 CEST 2007 - mvidner@suse.cz + +- package-manager script: Call /sbin/yast2 with full path because of + gnomesu (#269873). + +------------------------------------------------------------------- +Mon Aug 20 15:23:14 CEST 2007 - dmacvicar@suse.de + +- add support for the HASH key. (#300982) +- Use ContentFileParser in Downloader (instead of implementing + the parser again, it has a reason, Downloader was written first) +- update testcases and data to cover the new HASH key +- 3.18.1 + +------------------------------------------------------------------- +Mon Aug 20 13:21:34 CEST 2007 - kkaempf@suse.de + +- unify query API for kind and name, summary, description + (incomplete) +- rev 6761, version 3.18.0 + +------------------------------------------------------------------- +Fri Aug 17 12:30:55 CEST 2007 - kkaempf@suse.de + +- add iterateResolvablesByKindsAndName +- rev 6735, version 3.17.13 + +------------------------------------------------------------------- +Fri Aug 17 11:45:24 CEST 2007 - kkaempf@suse.de + +- rename ResolvableQuery::queryByName to iterateResolvablesByName +- fix reading of kind and repository in ResolvableQuery +- add reverse lookups in CacheTypes +- add iterateResolvablesByKind +- rev 6733 + +------------------------------------------------------------------- +Fri Aug 17 10:37:56 CEST 2007 - schubi@suse.de + +- shorten solver error messages Bug 259894 +- rev 6723 + +------------------------------------------------------------------- +Thu Aug 16 23:43:50 CEST 2007 - kkaempf@suse.de + +- fix ResolvableQuery::query(), add ResolvableQuery::queryByName() + install zypp/cache header files. +- rev 6719, version 3.16.13 + +------------------------------------------------------------------- +Thu Aug 16 17:21:52 CEST 2007 - kkaempf@suse.de + +- discard pattern files with incompatbile architecture, both + for download and for parsing. (#298716) +- rev 6711 + +------------------------------------------------------------------- +Thu Aug 16 17:12:45 CEST 2007 - kkaempf@suse.de + +- run sqlite asynchronously and add sql index files where + appropriate, gives 6x performance on certain operations. + Bumping cache schema version to 1004. + (#300998) +- rev 6710 + +------------------------------------------------------------------- +Thu Aug 16 17:08:58 CEST 2007 - kkaempf@suse.de + +- fix String::endsWith (#301038) +- rev 6709 + +------------------------------------------------------------------- +Thu Aug 16 11:16:25 CEST 2007 - schubi@suse.de + +- added an _explicitly_requested in QueueItemConflict ( as already in + QueueItemEstablish, QueueItemInstall, QueueItemUninstall ) in order to + remove the conflicting item without an error message. Bug 299819 +- rev 6699 + +------------------------------------------------------------------- +Thu Aug 16 07:23:31 CEST 2007 - jkupec@suse.cz + +- forgot to set default refresh policy in checkIfToRefreshMetadata +- repo.refresh.delay default set to 10 minutes +- 6693 + +------------------------------------------------------------------- +Wed Aug 15 15:32:36 CEST 2007 - schubi@suse.de + +- Bugfix while regarding correct vendor in update +- r6677 +- version 3.15.0 + +------------------------------------------------------------------- +Wed Aug 15 13:57:04 CEST 2007 - jkupec@suse.cz + +- repo.refresh.delay= (ZConfig, "main" section) support + added to delay next check & refresh until the specified number of + minutes has passed from the last check or refresh (FATE #301991). + Revisions: 6654, 6656, 6666, and 6667. +- filesystem::touch(Pathname) added (r6666) +- RepoManager::touchIndexFile(RepoInfo) added +- RepoManager::checkIfToRefreshMetadata(RepoInfo,Url,policy): + decision to do the refresh moved to this public method. +- r6667 + +------------------------------------------------------------------- +Wed Aug 15 12:38:26 CEST 2007 - schubi@suse.de + +- generate a resolver problem if addRequires does not find a resovable + #299486 +- rev 6660 + +------------------------------------------------------------------- +Tue Aug 14 15:54:15 CEST 2007 - schubi@suse.de + +- Prioritized delete request by the user BEFORE delete requests due + missing dependencies or conflicting dependencies. Bug 298322 +- rev 6640 + +------------------------------------------------------------------- +Fri Aug 10 20:49:20 CEST 2007 - jkupec@suse.cz + +- support also "Plaindir" as valid repo type name (#298622) +- revision 6616 +- version 3.14.0 + +------------------------------------------------------------------- +Fri Aug 10 18:03:06 CEST 2007 - dmacvicar@suse.de + +- fix segfault in Progress reporting +- progress report use name instead of alias (#298035) +- repoinfo returns alias if name is empty + +------------------------------------------------------------------- +Fri Aug 10 16:04:42 CEST 2007 - dmacvicar@suse.de + +- merge patch by dmueller to get rid of boost-regex + +------------------------------------------------------------------- +Fri Aug 10 13:50:40 CEST 2007 - dmacvicar@suse.de + +- dont create a second CacheStore in the same scope, will lock... + #297627 + +------------------------------------------------------------------- +Thu Aug 9 15:04:21 CEST 2007 - jkupec@suse.cz + +- fixed some RepoManager exception docs & history +- r6558 + +------------------------------------------------------------------- +Thu Aug 9 13:33:59 CEST 2007 - dmacvicar@suse.de + +- feature #302135: Graceful update of 3rd party packages + Automatic upgrading only sees packages from same vendor + This allows not needed to have those locked. +- Add persistent locks file which allow wildcards. Users + can lock certain packages adding lines like "kde* < 3.5" +- add applyLocks() to apply persistent locks before solving + +------------------------------------------------------------------- +Thu Aug 9 13:28:20 CEST 2007 - schubi@suse.de + +- recognize changes in the pool (e.g. changing /etc/sysconfig/storage + #271912 wq +- Added locking resolvables in the testcases +- rev 6544 + +------------------------------------------------------------------- +Wed Aug 8 16:04:07 CEST 2007 - dmacvicar@suse.de + +- add migrate-sources to %post (#292986) +- 3.13.15 + +------------------------------------------------------------------- +Wed Aug 8 13:32:52 CEST 2007 - jkupec@suse.cz + +- fixed bug with using wrong files from raw metadata cache + (bug #297611) (duncanmv) (r6501, already released in 3.13.14) + +------------------------------------------------------------------- +Wed Aug 8 12:42:39 CEST 2007 - schubi@suse.de + +- fix in "ignore conflicts" if the conflict has been caused by an obsolete + Bug# 297795 +- r 6517 + +------------------------------------------------------------------- +Tue Aug 7 17:04:47 CEST 2007 - dmacvicar@suse.de + +- implement susetags support for compressed metadata + and testcases. (feature #301916) +- implement disk usage in cache. For installation requires + some changes in YaST to setup the ZYpp getPartitions() + before repos are cached. (bug #293039) +- added testcases for diskusage +- 3.13.14 + +------------------------------------------------------------------- +Mon Aug 6 10:19:12 CEST 2007 - jkupec@suse.cz + +- fixed YUM parser to properly create source packages +- disabled reading of filelists.xml.gz by default (the data are + currently not stored anyway) +- revision 6481 +- version 3.13.13 + +------------------------------------------------------------------- +Sat Aug 4 01:03:19 CEST 2007 - ma@suse.de + +- Don't download unwanted translation files (#293740). +- revision 6470 + +------------------------------------------------------------------- +Fri Aug 3 23:52:18 CEST 2007 - ma@suse.de + +- Fix susetags repo to parse dikusage data (#293039) +- revision 6467 +- version 3.13.12 + +------------------------------------------------------------------- +Fri Aug 3 18:56:47 CEST 2007 - ma@suse.de + +- Add product attribute 'type' (aka 'category' which is now + deprecated). Adapted sustags and yum parsers to parse and + provide this value. +- revision 6464 +- version 3.13.11 + +------------------------------------------------------------------- +Fri Aug 3 17:29:56 CEST 2007 - dmacvicar@suse.de + +- fix modalias rel column number +- version 3.13.10 + +------------------------------------------------------------------- +Fri Aug 3 16:35:36 CEST 2007 - dmacvicar@suse.de + +- Implemented option repo.add.probe to allow probing + the added repositories +- version 3.13.9 + +------------------------------------------------------------------- +Fri Aug 3 16:07:46 CEST 2007 - schubi@suse.de + +- Fixed detection of renamed packages while update. +- Added new translations +- rev 6445 + +------------------------------------------------------------------- +Fri Aug 3 15:02:28 CEST 2007 - ma@suse.de + +- Speed up retrieving MediaNr attribute, as it slows down install + order calculation. (#297173) +- revision 6442 + +------------------------------------------------------------------- +Fri Aug 3 14:13:36 CEST 2007 - dmacvicar@suse.de + +- Fixed cache schema upgrade + +------------------------------------------------------------------- +Fri Aug 3 13:38:17 CEST 2007 - ma@suse.de + +- Fixed pattern includes and extends attributes. +- revision 6431 +- version 3.13.8 + +------------------------------------------------------------------- +Fri Aug 3 12:33:41 CEST 2007 - schubi@suse.de + +- API for retrieving additional dependencies" solver/detail/Resolver.h +- Handle additional dependencies in the testcases +- Handle system and language dependencies in the testcases correctly. +- r 6418 + +------------------------------------------------------------------- +Thu Aug 2 18:14:12 CEST 2007 - ma@suse.de + +- Indicate changed pool content if /etc/sysconfig/storage USED_FS_LIST + has changed. Resolver must discard any cached filesystem dependencies. + (required for #271912) +- revision 6404 + +------------------------------------------------------------------- +Thu Aug 2 16:37:06 CEST 2007 - ma@suse.de + +- Indicate changed pool content to the resolver. (required for #271912) +- revision 6398 +- version 3.13.7 + +------------------------------------------------------------------- +Thu Aug 2 10:16:16 CEST 2007 - schubi@suse.de + +- speedup error handling. Do not log ResolveInfo anymore. Set limit of 20 + problems. Bug 280387 +- r 6378 +- version 3.13.6 + +------------------------------------------------------------------- +Wed Aug 1 18:51:12 CEST 2007 - ma@suse.de + +- Added interface to install source packages via zypper. +- revision 6373 +- version 3.13.5 + +------------------------------------------------------------------- +Tue Jul 31 22:01:08 CEST 2007 - ma@suse.de + +- Added package attributes Package::sourcePkgName and + Package::sourcePkgEdition. Name and edition of the source + rpm this package was built from. +- Added ZYpp::installSrcPackage to install a single source package. +- revision 6353 +- version 3.13.4 + +------------------------------------------------------------------- +Tue Jul 31 19:06:54 CEST 2007 - ma@suse.de + +- Temorary files and directories created by makeSibling use the + same protection as the original. +- revision 6344 +- version 3.13.3 + +------------------------------------------------------------------- +Tue Jul 31 10:37:13 CEST 2007 - schubi@suse.de + +- Removed keepExtras from resolvePool. This will be handled + in the solver internally now. #294727 +- Checking if item really exists (#295544; ResolverInfoContainer.cc) +- revision 6317 +- version 3.13.2 + +------------------------------------------------------------------- +Mon Jul 30 17:23:19 CEST 2007 - ma@suse.de + +- Remove tribool from RepoInfo's interface. +- revision 6301 +- version 3.13.1 + +------------------------------------------------------------------- +Mon Jul 30 13:59:33 CEST 2007 - ma@suse.de + +- Fixed wrong media number reported by script, message and patch. +- Fixed script API to provide the scripts location on media (if not + inlined). +- Introduced ScripProvider to make a script available on the local + disk. +- revision 6288 +- version 3.13.0 + +------------------------------------------------------------------- +Fri Jul 27 18:08:42 CEST 2007 - jkupec@suse.cz + +- don't request media chage if the media is not changeable (like + e.g. http) +- revision 6271 +- version 3.12.1 + +------------------------------------------------------------------- +Fri Jul 27 17:40:44 CEST 2007 - dmacvicar@suse.de + +- progress ticks for clean cache +- ZConfig: remove default from names. +- re enable reading cache callbacks +- ini parser without boost::regexp + patch by dmueller (#152447) + +------------------------------------------------------------------- +Fri Jul 27 17:16:27 CEST 2007 - ma@suse.de + +- Fixed package to provide the location media number. (#294496) +- revision 6263 + +------------------------------------------------------------------- +Fri Jul 27 16:31:38 CEST 2007 - jkupec@suse.cz + +- RepoFileReader - ignore empty url keys (baseurl, mirrorlist, + gpgkey) instead of throwing bad url exception +- revision 6259 + +------------------------------------------------------------------- +Thu Jul 26 16:41:30 CEST 2007 - kkaempf@suse.de + +- Make clearing of extra dependencies/conflicts configurable when + resolvePool(). Leave the default as before (clear extras). + Bug # 294727 +- revision 6233 +- version 3.12.0 + +------------------------------------------------------------------- +Thu Jul 26 10:58:27 CEST 2007 - dmacvicar@suse.de + +- /var/lib/zypp/cache -> /var/cache/zypp + (#292419) +- ini parser without boost::regexp, patch by dmueller + (#152447) + +------------------------------------------------------------------- +Wed Jul 25 13:50:06 CEST 2007 - ma@suse.de + +- Make temp directory configurable via environment + variable ZYPPTMPDIR. +- revision 6202 +- version 3.11.11 + +------------------------------------------------------------------- +Tue Jul 24 17:55:49 CEST 2007 - ma@suse.de + +- Fixed bug in smart pointer comparison. + +------------------------------------------------------------------- +Mon Jul 23 13:05:53 CEST 2007 - ma@suse.de + +- Fix failing rename of metadata download directories across + filesystem boundaries. + +------------------------------------------------------------------- +Fri Jul 20 16:10:59 CEST 2007 - ma@suse.de + +- Fixed malicious gettext include. +- Make ZConfig a singleton. +- revision 6123 + +------------------------------------------------------------------- +Thu Jul 19 15:52:03 CEST 2007 - ma@suse.de + +- Fixed repo::provideFile to set a deleter for downloaded files + (#293004). +- revision 6094 +- version 3.11.10 + +------------------------------------------------------------------- +Thu Jul 19 12:58:12 CEST 2007 - ma@suse.de + +- Query ByRepository now takes as well an alias. + +------------------------------------------------------------------- +Wed Jul 18 16:40:35 CEST 2007 - dmacvicar@suse.de + +- fix retrieval of container attributes in cache + (#292698) + +------------------------------------------------------------------- +Wed Jul 18 16:12:06 CEST 2007 - ma@suse.de + +- Port zypp-query-pool (#292404) +- revision 6069 +- version 3.11.9 + +------------------------------------------------------------------- +Wed Jul 18 16:09:04 CEST 2007 - schubi@suse.de + +- added new calls in Resolver.h: addRequire,addConflict + +------------------------------------------------------------------- +Wed Jul 18 14:43:04 CEST 2007 - ma@suse.de + +- Fixed IniParser to allow '=' in values (#292669) +- revision 6063 + +------------------------------------------------------------------- +Wed Jul 18 14:16:59 CEST 2007 - dmacvicar@suse.de + +- allow / in alias (#292628) + +------------------------------------------------------------------- +Wed Jul 18 12:38:55 CEST 2007 - ma@suse.de + +- Fixed repo::provideFile to throw on error. +- Fixed ResolvableQuery to use 0 as default for non existing + numerical values. +- revision 6058 + +------------------------------------------------------------------- +Tue Jul 17 15:57:03 CEST 2007 - ma@suse.de + +- Fixed OnMediLocation to use safe defaults. Added setLocaltion and + additional ctor for convenience. +- revision 6047 + +------------------------------------------------------------------- +Tue Jul 17 10:45:39 CEST 2007 - schubi@suse.de + +- Evalute update canditate: + Take canditates only which are really installable. Bug 292077 + r 6034 + +------------------------------------------------------------------- +Mon Jul 16 15:41:31 CEST 2007 - jkupec@suse.cz + +- fixed some tribool bugs in RepoInfo +- revision 6022 + +------------------------------------------------------------------- +Mon Jul 16 11:43:33 CEST 2007 - dmacvicar@suse.de + +- fix reading of non existant repo +- r6018 +- first submission to stable +- fix keywords parsing in susetags parser +- version 3.11.8 + +------------------------------------------------------------------- +Wed Jul 11 19:14:47 CEST 2007 - jkupec@suse.cz + +- make resolvable query complete exceptionless with the database +- test that packages have some attributes +- disable progress adaptor for now +- revision 5977 +- version 3.11.7 + +------------------------------------------------------------------- +Wed Jul 11 14:37:02 CEST 2007 - ma@suse.de + +- fixed unresolved symbols +- revision 5972 +- version 3.11.6 + +------------------------------------------------------------------- +Wed Jul 11 13:31:39 CEST 2007 - ma@suse.de + +- fixed TranslatedText creating unwanted entries. +- fixed capability processing +- revision 5964 +- version 3.11.5 + +------------------------------------------------------------------- +Tue Jul 10 20:01:18 CEST 2007 - jkupec@suse.cz + +- MediaSetAccess::release() added +- Use attachDesiredMedia in MediaProducts +- Progress reporting improved +- revision 5959 +- version 3.11.4 + +------------------------------------------------------------------- +Tue Jul 10 14:23:13 CEST 2007 - ma@suse.de + +- fixed parsing translated texts. +- added source packages. +- revision 5947 +- version 3.11.3 + +------------------------------------------------------------------- +Tue Jul 10 13:11:31 CEST 2007 - jkupec@suse.cz + +- repo callbacks fixed +- Fixed YUM parser progress reporting +- Added CombinedProgressData +- make RepoImpl::resolvables() load lazy +- MediaProducts added for scanning products file +- Implement cache schema versioning and automatic invalidation of + cache when schema changes +- revision 5942 +- version 3.11.2 + +------------------------------------------------------------------- +Fri Jul 6 13:51:50 CEST 2007 - ma@suse.de + +- Propagate pools repository_iterator to the UI +- revision 5911 +- version 3.11.1 + +------------------------------------------------------------------- +Thu Jul 5 17:02:08 CEST 2007 - ma@suse.de + +- Package::location is now returns an OnMediaLocation +- archivesize() renamed to downloadSize() +- Allow to iterate all Repositories that contribute + Resolvables to the Pool. +- MediaSetAccess::provideDir added +- remove useless url check +- add old-api-style wrapper +- Add MediaProducts class +- revision 5892 +- version 3.11.0 + +------------------------------------------------------------------- +Thu Jul 5 09:31:02 CEST 2007 - schubi@suse.de + +- function isInstalledBy/installs + Added an initial installation flag which shows if the item has been + triggered for installation, or the dependency is already satisfied. +- Revision 5884 +- Version 3.4.0 + +------------------------------------------------------------------- +Tue Jul 3 13:07:31 CEST 2007 - jkupec@suse.cz + +- removed unused %{prefix}/lib/zypp from %files in spec file +- revision 5870 + +------------------------------------------------------------------- +Tue Jul 3 10:37:37 CEST 2007 - jkupec@suse.cz + +- Old API (SourceManager, metadata parsers) dropped in favor of the + new refactored ones (RepoManager, RepoParser(s), cache subtree, + repo subtree). +- Some new API improvements. +- revision 5868 +- version 3.10.0 (bumped minor to 10 to indicate refactoring branch) + +------------------------------------------------------------------- +Fri Jun 22 15:28:03 CEST 2007 - schubi@suse.de + +- New API calls which provides more information about one + resolvable after a solverrun: + isInstalledBy (const PoolItem_Ref item); + installs (const PoolItem_Ref item); +- Revision 5835 + +------------------------------------------------------------------- +Thu Jun 21 15:58:16 CEST 2007 - adrian@suse.de + +- fix changelog entry order + +------------------------------------------------------------------- +Wed Jun 20 11:47:33 CEST 2007 - schubi@suse.de + +- Ignore conflicting items which are uninstallable +- Create a "needed by" info if a requirement is still fulfilled. +- Allow only one needed_by and needed_by_capability in QueueItemInstall +- Added capability and type (REQUIRE, RECOMMEND,....) to + ResolverInfoNeededBy +- Evaluate ResolverInfoNeededBy for more information in the error + messages +- Enlarge detail description in the error messages +- Revision 5807 + +------------------------------------------------------------------- +Tue Jun 19 13:59:09 CEST 2007 - ma@suse.de + +- Fixes for gcc-4.2 +- revision 5786 +- version 3.3.1 + +------------------------------------------------------------------- +Mon Jun 18 17:20:45 CEST 2007 - mvidner@suse.cz + +- fixed so versioning from libtool to cmake +- 3.3.0 + +------------------------------------------------------------------- +Mon Jun 18 09:47:32 CEST 2007 - dmacvicar@suse.de + +- Use gpg2 instead of gpg for keyring and make + the package depend on it (#284211) + +------------------------------------------------------------------- +Mon Jun 11 17:02:49 CEST 2007 - schubi@suse.de + +- Required kmp packges FOR EACH installed/to_be_installed kernel will be installed. + New dependency "packageand(foo:bar)" which provides an AND dependency by + injecting a supplement/freshen. + e.G. package novell-cluster-services-kmp-smp + supplements: packageand(kernel-smp:novell-cluster-services-kmp) + Bug 255011 +- Dont check for architecture changes in atoms (#266178) +- Revision 5720 + +------------------------------------------------------------------- +Wed May 23 17:03:29 CEST 2007 - ma@suse.de + +- Fixed package-manager script (#275847) +- revision 5614 + +------------------------------------------------------------------- +Wed May 23 13:32:02 CEST 2007 - schubi@suse.de + +- fixed cmake +- version 3.2.2 + +------------------------------------------------------------------- +Wed May 23 11:25:55 CEST 2007 - schubi@suse.de + +- Reduced logging in order to speedup solving Bug 275100 +- revision 5603 +- version 3.2.1 + +------------------------------------------------------------------- +Tue May 15 14:03:34 CEST 2007 - ma@suse.de + +- Fix excess calls to releaseFile. (#274357) +- revision 5545 + +------------------------------------------------------------------- +Wed May 9 18:44:20 CEST 2007 - dmacvicar@suse.de + +- Fix importing keys into rpm. (#270125) +- r5527 + +------------------------------------------------------------------- +Wed Apr 18 14:56:17 CEST 2007 - ma@suse.de + +- Support filesystem dependencies to add needed filesystem RPMs + automatically (Fate 301966). +- revision 5404 +- version 3.2.0 + +------------------------------------------------------------------- +Mon Apr 16 11:23:15 CEST 2007 - jkupec@suse.cz + +- avoiding attaching media where not needed (#263207) +- r5381 + +------------------------------------------------------------------- +Fri Apr 13 17:32:55 CEST 2007 - dmacvicar@suse.de + +- fix FileCap with attributes +- r5376 + +------------------------------------------------------------------- +Thu Apr 12 02:33:18 CEST 2007 - ma@suse.de + +- Fixed computation of install order. Take requirements of + an installed packages uninstall scripts into account, if + the package is updated. (#258682) +- revision 5349 +- version 3.1.1 +------------------------------------------------------------------- +Wed Apr 11 15:24:01 CEST 2007 - ma@suse.de + +- Parse and provide package keywords. (Fate 120368) +- revision 5338 +- version 3.1.0 + +------------------------------------------------------------------- +Thu Apr 5 15:50:15 CEST 2007 - schubi@suse.de + +- Upgrade: Do NOT delete packages which have unresolved dependencies --> + Ask the user. Bug 258322 +- revision 5305 +- version 3.0.3 + +------------------------------------------------------------------- +Wed Apr 4 19:39:12 CEST 2007 - ma@suse.de + +- Fix restoring of Sources id root prefix is used. (#238165) +- revision 5299 +- version 3.0.2 + +------------------------------------------------------------------- +Wed Apr 4 15:33:54 CEST 2007 - jkupec@suse.cz + +- MediaManager::attachDesiredMedia() added to support multiple + (CD/DVD) drives (fate #3974) +- r5296 + +------------------------------------------------------------------- +Wed Mar 14 14:33:26 CET 2007 - schubi@suse.de + +- If there is no valid solver result and NOT all resolvables ( other + architecture) has been regarded, let the user decide making a new + solver run with ALL available resolvables. Bug 223440 +- reducing logging (error -> debug) bug 252921 +- Revision 5219 + +------------------------------------------------------------------- +Fri Mar 9 00:08:38 CET 2007 - ma@suse.de + +- Allow configuration of trusted vendors via + /var/lib/zypp/db/trustedVendors. (#186636) +- revision 5194 +- version 3.0.1 + +------------------------------------------------------------------- +Wed Mar 7 15:20:29 CET 2007 - dmacvicar@suse.de + +- libzypp-devel -> libzypp requirement is not versioned + (#251086) +- r5181 + +------------------------------------------------------------------- +Tue Mar 6 17:25:49 CET 2007 - schubi@suse.de + +- Using already existing valid solver results for further solver runs. + (partiell solving) +- r5169 + +------------------------------------------------------------------- +Fri Mar 2 16:11:16 CET 2007 - dmacvicar@suse.de + +- fix link order +- r5165 + +------------------------------------------------------------------- +Tue Feb 27 15:50:39 CET 2007 - dmacvicar@suse.de + +- merging from 10.2 / SP1 +- #247459 ftp probing + denied == dont exists in ftp +- r5124 + +------------------------------------------------------------------- +Tue Feb 27 15:35:06 CET 2007 - schubi@suse.de + +- Merging solver related stuff from SuSE-Linux-10_2-Branch ( till r5111): +- Simultaneouqusly establishing of items which are conflicting eachother is + useless. So only one will be established. Fixed in QueueItemInstall.cc + Bug 243595 +- Added new upgrade options to fine tune version and patch handling. + (F301990) +- The context of establishPool will be stored in Resolver and will be + regarded for the next solver run everytime. So it will be not reset by + any solver run anymore. + bug 191810 ( A broken patch will not be installed again) + +------------------------------------------------------------------- +Fri Feb 23 17:40:23 CET 2007 - jkupec@suse.cz + +- adding sotf,timeo=X nfs mount options by default (#235211) +- r5093 + +------------------------------------------------------------------- +Fri Feb 23 14:16:19 CET 2007 - jkupec@suse.cz + +- support for HTTP authentication prompt added (#190609) +- fixed problem with empty path in URL + in MediaCurl::doGetFileCopy() +- r5085 + +------------------------------------------------------------------- +Mon Feb 12 15:28:08 CET 2007 - jkupec@suse.cz + +- Merged revisions 4926-4993,4995,4998-5006 via svnmerge from + SuSE-Linux-10_2-Branch + +- verifySystem: Regarding patterns too. Bug 239750 (schubi) +- verifySystem: The result will be set to APPL_HIGH, so it will be not + reset by a second "normal" solver run. #239281 (schubi) +- yast2 reports invalid URL as 'unknown source type' + (#209961) (dmacvicar) +- Added freshen language dependency in supplemements too if there is no + entry in supplements. + #240617;IPA fonts are not installed even if select Japanese + language (schubi) +- Setting allowed authentication methods to "basic,digest" if none + provided in URL (#243006) (jkupec) +- Stopping after 50 valid solver results. Anymore would be useless. Bug + 243595 (schubi) +- r 5007 + +------------------------------------------------------------------- +Mon Feb 12 10:37:02 CET 2007 - mvidner@suse.cz + +- package-manager: use a generic su script from XDG (#235303, #244442) + +------------------------------------------------------------------- +Fri Feb 9 15:21:55 CET 2007 - jkupec@suse.cz + +- Setting allowed authentication methods to "basic,digest" if none + provided in URL (#243006) +- fixed gettext and rpath problems in configure.ac and Makefile.cvs + (mvidner) +- r4999 + +------------------------------------------------------------------- +Wed Feb 7 15:52:29 CET 2007 - jkupec@suse.cz + +- MediaCurlException::dumpOn() adjusted for ncurses dialogue + (#222602) +- 4984 + +------------------------------------------------------------------- +Mon Jan 29 13:10:37 CET 2007 - dmacvicar@suse.de + +- Merged revisions 4907-4926 from SuSE-Linux-10_2-Branch + +- update packages: changing architecture is only valid while an + system update and NOT while an update via a patch. Last fix does + not fit for every case. + Bug 230685 +- Patch has selected not the concerning package for update but + a package which has provided the required dependencies too. + Algorithmus: If there are exactly two providers which differ in architecture + prefer the better arch. + Fix: Regarding NVRA too. ( only if equal ) + Bug 238284 +- Download only English and Local translation + (#208457) +- Added solver parameter: + tryAllPossibilities: regarding every solver branch ( not only + branches with e.G. best architectures + preferHighestVersion: Prefer solver results which have a higher + version number. + Bug #238087 +- update packages: changing architecture is only valid while an + system update and NOT while an update via a patch. + Bug 230685 - x86_64 MozillaFirefox binaries in security update + repository + Fix of version 2.11.2 has not worked if the first founded item + had had another architecture. +- r4927 + +------------------------------------------------------------------- +Wed Jan 24 14:50:33 CET 2007 - lslezak@suse.cz + +- added ZYpp::getPartitions() - return the partitinoning + +------------------------------------------------------------------- +Wed Jan 24 14:20:28 CET 2007 - dmacvicar@suse.de + +- Merged revisions 4705-4906 via svnmerge from SuSE-Linux-10_2-Branch +- Corrupt download cannot be skipped + (#217425 and #224216) +- Enable package read ahead/caching in commit per default to reduce + interactive media changes. If the environment variable + ZYPP_COMMIT_NO_PACKAGE_CACHE is set, caching will be disabled. (F100182) +- added parameter not to reset resolver results while calling + freshen pool Bug: 235761 +- Prepare package read ahead/caching of packages in commit. Adatped the + workflow. Caching details are now hidden inside CommitPackageCache. + The current implementation still performs no read ahead. (for F100182) +- Skip invalid or broken rpm database entries. (#231211) +- verifySystem: check if the solution is valid after calling freshenPool() + Bug: 235761 +- Added own call for Resolver::verifySystem with additional + hardware/language check in order to keep binary compatibility + Fate #301224 +- Rpm requires additional quoting of special chars in filenames. + (#233967) +- Resolver::verifySystem checks for new hardware now by calling + freshenPool. This is configureable. Fate #301224 +- merged texts from proofread +- Don't consider patch/delta rpms if package architecture changes. + (#231254) +- update packages: changing architecture is only valid while an + system update and NOT while an update via a patch. + Bug 230685 - x86_64 MozillaFirefox binaries in security update repository +- verifySystem: Do only regard items which will be on the system after the + commit. Fate 301178 +- feature #301369 + Import listed GPG Keys from an trusted installation source +- fix return call in new xml parser +- Enable system resolvables in Helix parser (Revision 4787) +- deptestomatic: + Resetting transaction with the correct call; + bugfix; Added kind in keep state (Revision 4788) +- Wrong behaviour in soft install/uninstall. --> Setting Transact with + soft (Revision 4789) +- New call added: maySetToBeUninstalledSoft (Revision 4789) + Both are only functions for the solver (Revision 4789) +- Resetting "by causer" in order to distinguish from state + "keep by user". ( function setLock in order to remove lock) + (Revision 4789) +- Better fix for Bug 217574: Checking if the resolveable CAN be deleted soft + in QueueItemUninstall.cc (Revision 4790) +- Regarding "keep state by user". So avoiding "reselecting" by + other requirements. + Give a corresponding problem solution if a resolvable satisfy + a dependency, but has been set to keep by the user. + Bug : 222531 (Revision 4791) +- Allow to disable autoprotection of foreign vendor items. Required + in zmd-backend. (F301735). +- use sqlite-zmd if using > 10.2 in spec. Use the one available + durin compile. +- Item could has already been selected to soft uninstall (e.G. remove + pattern which recommend this item ). Do not throw an exception anymore. + bug#225278 +- Added syscontent::Reader: Parse serialized set of ResObjects. + (for F300729) +- If there has already been selected another item by the solver (e.g. from + another source) we will take thatone in order to avoid parallel + installation and there concerning error messages. + Bug 224698 +- In order to handle conflicting resolvable we try to update the + conflicting item. While evaluating these canditates an already selected + candidate will not be regarded. So it could be that an older package + will be selected for update although a newer has already been selected. Revision 4765 +- Conflicting items: The resolvable will be obsoleted by another. So it is useless finding an + update candidate and evaluate additional branches. +- r4907 + +------------------------------------------------------------------- +Mon Dec 4 15:38:12 CET 2006 - mt@suse.de + +- Improved realpath() wrapper in media handler class (#222521). +- revision 4758 + +------------------------------------------------------------------- +Thu Nov 30 09:15:20 CET 2006 - ma@suse.de + +- version 3.0.0 (2.x.x now in SuSE-Linux-10_2-Branch) +- revision 4713 + +------------------------------------------------------------------- +Wed Nov 29 19:20:24 CET 2006 - dmacvicar@suse.de + +- use sqlite-zmd package for the non yet shipped zypp2/ stuff + because backend uses this sqlite and it is no fun to + install one and the other to develop (as the -devel packages) + conflict. +- add cmake support for building zypp/ lib. + TODO: soinfo, compile testcases, devel, zypp2,docs + find rpm, curl and others. +- dont serialize interactive, as it is + calculated now. + (it was already fixed as we don't reimplement + the method, but we still serialized, parsed) +- r4709 + +------------------------------------------------------------------- +Tue Nov 28 22:40:12 CET 2006 - ma@suse.de + +- fixed Patch::interactive to return true as well, if the patch + itself has a licence. (#224192) +- revision 4702 +- version 2.9.2 + +------------------------------------------------------------------- +Tue Nov 28 16:36:56 CET 2006 - mt@suse.de + +- Added search for /sbin/vol_id tool - that is in /lib/udev/vol_id + on the installation image (#213852). +- revision 4700 + +------------------------------------------------------------------- +Tue Nov 28 11:44:52 CET 2006 - schubi@suse.de + +- Avoid duplicate pool entries; Bug 223750; second part of the fix +- r4698 +- Version 2.9.1 + +------------------------------------------------------------------- +Mon Nov 27 18:29:58 CET 2006 - schubi@suse.de + +- Pool has multi instances of an item in the pool. Reduced this error + to items which are identically at least. #217574 and #223750 +- r4695 + +------------------------------------------------------------------- +Mon Nov 27 17:37:44 CET 2006 - dmacvicar@suse.de + +- replace spaces to underscores in product names +- 2.8.7 +- r4688 + +------------------------------------------------------------------- +Mon Nov 27 16:54:03 CET 2006 - dmacvicar@suse.de + +- Mark some strings for translation (#219783 need it) +- r4682 + +------------------------------------------------------------------- +Mon Nov 27 16:17:07 CET 2006 - mt@suse.de + +- Added translations marks to hal, url and mutex exceptions (#23771) +- revision 4680 + +------------------------------------------------------------------- +Wed Nov 22 19:24:57 CET 2006 - dmacvicar@suse.de + +- don't make libzypp-devel depend on sqlite-devel as + headers from zypp2 are not installed yet +- r4663 + +------------------------------------------------------------------- +Wed Nov 22 15:23:55 CET 2006 - ma@suse.de + +- Return an error if fork failed. (#204807) +- Make Script execution abortable by user request. (#212949, F100233) +- revision 4660 +- version 2.8.6 + +------------------------------------------------------------------- +Tue Nov 21 16:25:03 CET 2006 - mvidner@suse.cz + +- Added package-manager wrapper script, with icon and .desktop (#222757). + (Used by gnome-main-menu) +- version 2.8.5 +- r4640 + +------------------------------------------------------------------- +Tue Nov 21 13:11:06 CET 2006 - mt@suse.de + +- Fixed target/hal - one more dbus_connection_close found (#216035) +- revision 4636 +- version 2.8.4 + +------------------------------------------------------------------- +Mon Nov 20 14:15:38 CET 2006 - schubi@suse.de + +- translation added + rev 4630 + version 2.8.3 + +------------------------------------------------------------------- +Mon Nov 20 11:02:04 CET 2006 - ma@suse.de + +- Process obsoletes when installing non-package objects. (#217352) +- revision 4621 +- version 2.8.2 + +------------------------------------------------------------------- +Fri Nov 17 16:57:39 CET 2006 - mt@suse.de + +- Implemented volume device check using /sbin/vol_id (#213852). +- Revision 4619 + +------------------------------------------------------------------- +Fri Nov 17 15:53:58 CET 2006 - schubi@suse.de + +- new translation added + +------------------------------------------------------------------- +Fri Nov 17 12:42:04 CET 2006 - mt@suse.de + +- Implemented an reuse of already existing foreign CD/DVD mount points + (e.g. automounted) - depends on REUSE_FOREIGN_MOUNTS flag (#220206). +- Added a fallback check of the volume.mount_point HAL property to + isAutoMountedMedia(); info.hal_mount.created_mount_point seems + to be not avaliable in newer HAL versions (on 10.2). +- Revision 4615 +- Version 2.8.1 + +------------------------------------------------------------------- +Thu Nov 16 23:39:15 CET 2006 - ma@suse.de + +- removed unused methods from Patch and PatchImplIf. Provided + reasonable default implementation for Patch::interactive. + (#221476). +- revision 4610 +- Version 2.8.0 + +------------------------------------------------------------------- +Thu Nov 16 15:32:04 CET 2006 - dmacvicar@suse.de + +- Handle media eject failures (#216545) +- r4606 + +------------------------------------------------------------------- +Wed Nov 15 22:41:51 CET 2006 - ma@suse.de + +- Reimplemented RpmDb::checkPackage using librpm API instead + of parsing "rpm --checksig" output. (#163202) +- Version 2.7.4 +- revision 4600 + +------------------------------------------------------------------- +Wed Nov 15 15:39:26 CET 2006 - schubi@suse.de + +- NEW behaviour of the solver: + Obsolete virtual provides. E.G.: + + Installed: + ----------- + Name: test-1.0-0 + + Name: moretest-1.0-0 + Provides: test + + To be installed + ------------------ + Name: nomoretest-1.0-0 + Obsoletes: test + + Result + -------- + test-1.0-0 AND moretest-1.0-0 will be deleted. In former versions only + test-1.0-0 had been deleted. Bug 220999 + +- Translations added + +Version 2.7.3 +rev 4593 + +------------------------------------------------------------------- +Tue Nov 14 16:32:49 CET 2006 - schubi@suse.de + +- Bugfix in generating solver testcases: + - added kind of capabilities in description file + - removed unneded channel from uninstall in command file + +------------------------------------------------------------------- +Mon Nov 13 18:35:01 CET 2006 - mt@suse.de + +- Try to call /bin/eject utility if the eject-ioctl fails. +- r4568 + +------------------------------------------------------------------- +Mon Nov 13 17:00:51 CET 2006 - dmacvicar@suse.de + +- ignore empty capabilities +- r4565 + +------------------------------------------------------------------- +Fri Nov 10 17:52:10 CET 2006 - dmacvicar@suse.de + +- make progress strings translatable (#219783) +- r4556 + +------------------------------------------------------------------- +Tue Nov 7 16:40:28 CET 2006 - schubi@suse.de + +- While deleting a selection all concerning recommended + packages will be deleted too. + BUT those packages should not be deleted which have been + set to KEEP by the user. bug 217574 + rev 4526 + VERSION: 2.7.2 + +------------------------------------------------------------------- +Tue Nov 7 13:12:49 CET 2006 - schubi@suse.de + +- Makefile in zypp2 fixed + Revision 4520 + +------------------------------------------------------------------- +Tue Nov 7 11:38:10 CET 2006 - schubi@suse.de + +- Translations added + Revision 4514 + VERSION: 2.7.1 + +------------------------------------------------------------------- +Mon Nov 6 12:32:22 CET 2006 - dmacvicar@suse.de + +- Make the parser more strict, rejecting broken sources + but showing the error line. + Last fix making the parser relax would break multitag + descriptions with empty lines, now we check dependencies + at a higher level. (reference #160607) +- r4501 + +------------------------------------------------------------------- +Fri Nov 3 11:04:19 CET 2006 - schubi@suse.de + +- New problem solution added: Unlock ALL resovables in order to speed up + problem solution. Bug 206453 + +------------------------------------------------------------------- +Fri Nov 3 10:29:08 CET 2006 - schubi@suse.de + +- Translations added + +------------------------------------------------------------------- +Thu Nov 2 17:15:19 CET 2006 - mt@suse.de + +- Fixed target/hal - removed dbus_connection_close calls, because + the connections are shared; unref the ref-counted handle only. + (#216035) +- r4442 + +------------------------------------------------------------------- +Thu Nov 2 16:18:27 CET 2006 - dmacvicar@suse.de + +- skipping unreachable packages won't work + (#215445) +- r4468 + +------------------------------------------------------------------- +Wed Oct 25 19:04:51 CEST 2006 - dmacvicar@suse.de + +- (#213793) Target store fails to recreate stored install-time (other + Date and ByteCount values as well) + +- skip comments and blank lines in multilists + fixes (#214877) - zen-updater is not installed by default + +- Automatically fix broken products when reading + the product database. + still pending: honour the read-only flag + Changes to make this possible include + using read_dir instead of boost directory + iterator. + +------------------------------------------------------------------- +Wed Oct 25 17:09:06 CEST 2006 - schubi@suse.de + +- added new class for generating solver testcases: + Testcase + +------------------------------------------------------------------- +Wed Oct 25 15:40:44 CEST 2006 - ma@suse.de + +- Finalized ui::PatternContents. (F301229) +- version 2.7.0 +- revision 4413 + +------------------------------------------------------------------- +Wed Oct 25 08:21:52 CEST 2006 - mvidner@suse.cz + +- Moved zypper and zypp-checkpatches(-wrapper) to zypper.rpm +- version 2.6.0 + +------------------------------------------------------------------- +Tue Oct 24 14:33:16 CEST 2006 - ma@suse.de + +- Added ui::PatternContents: Helper class that will compute a patterns + expanded install_packages set. (UI interface for F301229) +- revision 4387 + +------------------------------------------------------------------- +Tue Oct 24 09:06:24 CEST 2006 - mvidner@suse.cz + +- removed the last reference to /usr/lib64 to fix the build + +------------------------------------------------------------------- +Mon Oct 23 17:44:42 CEST 2006 - mvidner@suse.cz + +- added "zypper info" (jkupec) +- version 2.5.2 + +------------------------------------------------------------------- +Mon Oct 23 11:28:01 CEST 2006 - dmacvicar@suse.de + +- fix rpm db timestamp +- add extra urls and optional urls to product API +- r4378 + +------------------------------------------------------------------- +Fri Oct 20 16:55:44 CEST 2006 - mvidner@suse.cz + +- zypper: nicer progress reports, with or without --verbose. + +------------------------------------------------------------------- +Fri Oct 20 16:25:50 CEST 2006 - ma@suse.de + +- Fixed reloading of target data after commit. Broken since + rev 3880. +- version 2.5.1 +- revision 4365 + +------------------------------------------------------------------- +Fri Oct 20 16:22:09 CEST 2006 - dmacvicar@suse.de + +- put query-pool in /usr/lib/zypp and not lib64 +- r4363 + +------------------------------------------------------------------- +Fri Oct 20 12:16:06 CEST 2006 - dmacvicar@suse.de + +- revert keyring changes, causes endless loop (obvious) +- add dist-product information, adapt store +- version 2.5.0 +- r4355 + +------------------------------------------------------------------- +Fri Oct 20 11:04:26 CEST 2006 - ma@suse.de + +- zypp-query-pool: For products show additionally distributionName + and distributionEdition. (required by #205392) +- revision 4349 + +------------------------------------------------------------------- +Fri Oct 20 00:13:49 CEST 2006 - ma@suse.de + +- Add accessor for Product distributionName and distributionEdition. + (required by #205392) +- revision 4347 + +------------------------------------------------------------------- +Thu Oct 19 18:40:36 CEST 2006 - dmacvicar@suse.de + +- added test case for KeyRing +- fire trustedKeyAdded in all calls to import trusted key + not only in signature check workflow. +- r4342 + +------------------------------------------------------------------- +Thu Oct 19 18:27:02 CEST 2006 - mvidner@suse.cz + +- zypper update: implemented minimal version (patches only) +- zypper list-updates: changed default type from package to patch, + consider patches affecting the package manager separately + +------------------------------------------------------------------- +Thu Oct 19 14:09:33 CEST 2006 - dmacvicar@suse.de + +- version 2.4.1 +- r4338 + +------------------------------------------------------------------- +Thu Oct 19 14:05:18 CEST 2006 - dmacvicar@suse.de + +- add zypp-query-pool, so registration doesn't depend on + libzypp-zmd-backend being installed. Will remove from + backend when suseregister gets updated. + +------------------------------------------------------------------- +Thu Oct 19 12:31:08 CEST 2006 - schwab@suse.de + +- Make sure config.rpath is present. + +------------------------------------------------------------------- +Wed Oct 18 21:40:25 CEST 2006 - mvidner@suse.cz + +- zypper search: fixed uninitialized members that made all searches + exact and case sensitve + +------------------------------------------------------------------- +Wed Oct 18 13:13:16 CEST 2006 - dmacvicar@suse.de + +- zypp-checkpatches, write in the right file +- r4328 + +------------------------------------------------------------------- +Wed Oct 18 12:45:49 CEST 2006 - schubi@suse.de + +- Install resolvables although they are unneeded + if they have NOT the kind patch/atoms + Bug 210538 - freshens/supplements does not work with patterns +- r4326 + +------------------------------------------------------------------- +Tue Oct 17 19:17:39 CEST 2006 - mvidner@suse.cz + +- zypper service-add -r http://example.org/foo.repo (F#300641). + +------------------------------------------------------------------- +Tue Oct 17 18:29:34 CEST 2006 - dmacvicar@suse.de + +- zypp-checkpatches: + save version of the generated xml to + regenerate it if it changes. + save a random token in case of error to + force recreating xml file +- r4321 + +------------------------------------------------------------------- +Tue Oct 17 13:49:53 CEST 2006 - dmacvicar@suse.de + +- remove permissions for zypp checkpatches from spec +- r4318 + +------------------------------------------------------------------- +Tue Oct 17 12:36:57 CEST 2006 - dmacvicar@suse.de + +- registration fails because of wrong product data + (#205392) + use DISTPRODUCT,DISTVERSION to create the product + resolvable. have this resolvable provide + PRODUCT = VERSION +- r4312 + +------------------------------------------------------------------- +Mon Oct 16 18:05:56 CEST 2006 - mvidner@suse.cz + +- zypper service-add -r ./foo.repo (F#300641). + +------------------------------------------------------------------- +Mon Oct 16 15:02:00 CEST 2006 - jkupec@suse.cz + +- zypper: added case-sensitive search, search in descriptions and + summaries, search by resolvable type, substring and word + matching, support for wildcards +- Revision 4303 + +------------------------------------------------------------------- +Mon Oct 16 13:27:50 CEST 2006 - mvidner@suse.cz + +- Prevent the user from sending signals to zypp-checkpatches-wrapper + (#211286). + +------------------------------------------------------------------- +Mon Oct 16 12:57:56 CEST 2006 - schubi@suse.de + +- Dont incomplete an uninstalled resolvable, even not when establishing. + Incomplete only makes sense for installed resolvables (when they have broken + deps), for patches (because they are needed) and for atoms (because they are + used during patch calculation) + Bug 198379 + +- Do not branch for packages with the same NVE but different architectures. + Take the best architecture. + +------------------------------------------------------------------- +Fri Oct 13 16:51:43 CEST 2006 - dmacvicar@suse.de + +- implement rename source in sourcemanager +- r4286 + +------------------------------------------------------------------- +Fri Oct 13 14:32:44 CEST 2006 - dmacvicar@suse.de + +- YaST sources: set alias to product summary if empty +- show alias on logs. +- r4281 + +------------------------------------------------------------------- +Thu Oct 12 16:40:29 CEST 2006 - dmacvicar@suse.de + +- version 2.4.0 (bin incompat due to callback fixes) +- r4272 + +------------------------------------------------------------------- +Thu Oct 12 16:30:55 CEST 2006 - ma@suse.de + +- Provide additional solver status information to the UI. + (#162164,F301272) +- Fixed UI satus computation in presence of multiple available + candidates. +- revision 4264 +- version 2.3.1 + +------------------------------------------------------------------- +Thu Oct 12 15:45:12 CEST 2006 - dmacvicar@suse.de + +- remove const in MediaChangeReport requestMedia that + broke cd changing. +- r4262 + +------------------------------------------------------------------- +Wed Oct 11 08:35:48 CEST 2006 - mvidner@suse.cz + +- zypper: added search (jkupec) +- removed the suid bit from zypp-checkpatches-wrapper so that the + build passes until permissions.rpm is updated (~#211286). +- r4253 + +------------------------------------------------------------------- +Tue Oct 10 16:03:40 CEST 2006 - dmacvicar@suse.de + +- Log microseconds if ZYPP_PROFILING env var is enabled. +- r4252 + +------------------------------------------------------------------- +Mon Oct 9 18:15:19 CEST 2006 - dmacvicar@suse.de + +- YaST sources: + Factory cannot be set with 'refresh' enabled + (#204957) +- get rid of some const bool signatures in Source classes +- r4247 + +------------------------------------------------------------------- +Mon Oct 9 15:11:16 CEST 2006 - mvidner@suse.cz + +- Added zypp-checkpatches and a suid-root zypp-checkpatches-wrapper. + +------------------------------------------------------------------- +Fri Oct 6 13:23:32 CEST 2006 - schubi@suse.de + +- select the best solution: prefering the total amount of install/update + packages BEFORE source preferences. Bug 208784 + +------------------------------------------------------------------- +Fri Oct 6 11:55:11 CEST 2006 - dmacvicar@suse.de + +- Introduce a method to see if a source supports a + kind of resolvable at that time, so we can + init a YUM source like factory but avoid parsing + it if it contains no patches. +- add TODO +- zypp-checkpatches xml output +- r4235 + +------------------------------------------------------------------- +Mon Oct 2 16:34:03 CEST 2006 - mvidner@suse.cz + +- added a CLI preview: zypper +- revision 4214 +- version 2.2.3 + +------------------------------------------------------------------- +Mon Oct 2 15:11:26 CEST 2006 - dmacvicar@suse.de + +- FATE #100165: + Make Content File Aware of Different Architectures + expand %a in release notes with architecture + +------------------------------------------------------------------- +Fri Sep 29 16:10:46 CEST 2006 - ma@suse.de + +- Extended pattern parser to support includes/extends tags as hint + for the IO. (F301229) +- revision 4199 +- version 2.2.2 + +------------------------------------------------------------------- +Fri Sep 29 00:31:33 CEST 2006 - ma@suse.de + +- Enabled sending of ScriptResolvableReport. +- Changed ScriptResolvableReport::start to send local path + of script to be executed. +- revision 4190 +- version 2.2.1 + +------------------------------------------------------------------- +Wed Sep 27 14:14:33 CEST 2006 - ma@suse.de + +- Added ScriptResolvableReport. Callbacks triggered on script + execution during commit. (F100233) +- revision 4187 +- version 2.2.0 + +------------------------------------------------------------------- +Mon Sep 25 13:52:55 CEST 2006 - mvidner@suse.cz + +- fix: Url::getRegisteredSchemes() would always return nothing + +------------------------------------------------------------------- +Fri Sep 22 15:34:11 CEST 2006 - jkupec@suse.cz + +- Made the build dependency on gettext-devel explicit + +------------------------------------------------------------------- +Tue Sep 19 10:59:24 CEST 2006 - jsrain@suse.cz + +- adapted multi-media YUM sources according to official YUM + specification (F300743) + +------------------------------------------------------------------- +Mon Sep 18 17:42:26 CEST 2006 - lslezak@suse.cz + +- use RPM_OPT_FLAGS (meissner@suse.de) + +------------------------------------------------------------------- +Mon Sep 18 15:19:53 CEST 2006 - lslezak@suse.cz + +- SourceFactory::createFrom() - don't loose url,... +- r4160 + +------------------------------------------------------------------- +Mon Sep 18 12:00:46 CEST 2006 - kkaempf@suse.de + +- reduce logging in ResolvableImpl.cc +- rev 4157 + +------------------------------------------------------------------- +Thu Sep 14 15:59:47 CEST 2006 - schubi@suse.de + +- Replaced requirementIsMet by requirementIsInstalledOrUnneeded + in QueueItemInstall and QueueItemRequire + Bug 192535/204913 + removed fix:Thu Sep 7 18:31:46 CEST 2006 - schubi@suse.de + +------------------------------------------------------------------- +Thu Sep 14 12:44:53 CEST 2006 - lslezak@suse.cz + +- fixed SourceFactory::createFrom() - don't loose alias, + cachedir,... parameters + +------------------------------------------------------------------- +Thu Sep 14 10:21:02 CEST 2006 - mvidner@suse.cz + +- Use RPM Enhances only if detected at configure time, to allow + compilation with older rpm. +- callback params: use const string & instead of string (dmacvicar) + +------------------------------------------------------------------- +Thu Sep 7 18:31:46 CEST 2006 - schubi@suse.de + +- Do not regarding SATISFIED (regarding UNNEEDED) in isPresent if it is + a package/script/message + Bug: 192535 + +------------------------------------------------------------------- +Thu Sep 7 16:19:36 CEST 2006 - dmacvicar@suse.de + +- add Source_Ref::checksum() which in combination with + timestamp can give an idea of a source change. +- r4106 + +------------------------------------------------------------------- +Thu Sep 7 14:32:38 CEST 2006 - mvidner@suse.cz + +- Implemented fgzstreambuf::compressed_tell and fXstream::getbuf to + enable progress reporting on compressed streams. + +------------------------------------------------------------------- +Wed Sep 6 18:31:20 CEST 2006 - dmacvicar@suse.de + +- better error propagation +- r4096 + +------------------------------------------------------------------- +Tue Sep 5 19:22:56 CEST 2006 - mt@suse.de + +- Removed libblkid dependency - the workaround using libblkid to + check filesystem on XEN vbd mapped devices is obsolete, because + the info is avaliable via /dev/disk/by-label link now. (#197107) +- revision 4087 + +------------------------------------------------------------------- +Thu Aug 31 15:16:11 CEST 2006 - ma@suse.de + +- PackageProvider: Fixed broken retry. (#202163) +- revision 4071 + +------------------------------------------------------------------- +Wed Aug 30 23:50:55 CEST 2006 - ma@suse.de + +- Fixed RpmDb::makePackageFromHeader: Catch NULL Header passed as argument and refuse + to create a Package from a source package header. +- Added method Pathname::extension: Return all of the characters in name + after and including the last dot in the last element of name. +- PlaindirImpl: Disable rpm signature verification when scaning a directory for + rpms. Otherwise we'd need access to the rpm database to get the keys. +- revision 4069 + +------------------------------------------------------------------- +Wed Aug 30 17:42:40 CEST 2006 - schubi@suse.de + +- Do not regarding SATISFIED/UNNEEDED in isPresent if it is + a package/script/message + Bug: 192535 + +------------------------------------------------------------------- +Wed Aug 30 14:29:45 CEST 2006 - ma@suse.de + +- Speedup computation of number of rpm database entries. +- revision 4058 + +------------------------------------------------------------------- +Tue Aug 29 16:58:20 CEST 2006 - schubi@suse.de + +- Fixed endless loop in transactResObject + Bug 198095 - YaST2 Installaler crashes when selecting Gnome pattern to a KDE installation + +------------------------------------------------------------------- +Tue Aug 29 12:05:09 CEST 2006 - dmacvicar@suse.de + +- fix some testcases for tar file parser changes +- r4045 + +------------------------------------------------------------------- +Tue Aug 29 11:19:53 CEST 2006 - dmacvicar@suse.de + +- missing includes +- clean old callbacks +- r4041 + +------------------------------------------------------------------- +Fri Aug 25 14:32:07 CEST 2006 - schubi@suse.de + +- zyppPattern->install_packages returns SUGGESTED package too. + Bug 201476 + Revision 4036 + +------------------------------------------------------------------- +Fri Aug 25 13:05:33 CEST 2006 - schubi@suse.de + +- New behaviour in the solver: try with 'best' package first, try with 'all' + packages if this fails. + Bug :Bug 191983 + +------------------------------------------------------------------- +Fri Aug 25 11:35:48 CEST 2006 - dmacvicar@suse.de + +- libzypp 2.1.0 +- bump version due to incompatible callback changes in KeyRing + Sources + +------------------------------------------------------------------- +Thu Aug 24 15:34:45 CEST 2006 - dmacvicar@suse.de + +- new keyring callbacks +- separate trust key from import key +- use PublicKey class instead of params, to be able + to add more info like photos later (pending #181682) +- update zmart with those callbacks. +- better error handling (Exception types) +- make tmp file names more readable depending on the context +- r4026 + +------------------------------------------------------------------- +Tue Aug 22 22:35:30 CEST 2006 - dmacvicar@suse.de + +- decouple probing from source creation, using the new + media test for existence functions. +- r4019 + + +------------------------------------------------------------------- +Tue Aug 22 17:56:53 CEST 2006 - mt@suse.de + +- Fixed getDoesFileExist to reset the transfer range +- Added logging of curl debug messages to the zypp log. + The env var ZYPP_MEDIA_CURL_DEBUG=1 logs curl infos, + ZYPP_MEDIA_CURL_DEBUG=2 logs the in/out headers. +- r4018 + +------------------------------------------------------------------- +Fri Aug 18 14:57:35 CEST 2006 - kkaempf@suse.de + +- remove the /etc/sysconfig/zypp:REWRITE_KERNEL_DEPS = yes check; + see rev 3810 below. (#190163) +- rev 3998 + +------------------------------------------------------------------- +Thu Aug 17 18:15:14 CEST 2006 - dmacvicar@suse.de + +- fix uninstalling of atoms (noop) +- r3995 + +------------------------------------------------------------------- +Wed Aug 16 17:41:40 CEST 2006 - dmacvicar@suse.de + +- Implement initial verson of Media + doesFileExist, for future source probing. +- r3984 + +------------------------------------------------------------------- +Tue Aug 15 12:01:31 CEST 2006 - dmacvicar@suse.de + +- more dbus_connection_close fixes +- r3974 + +------------------------------------------------------------------- +Tue Aug 15 11:41:41 CEST 2006 - kkaempf@suse.de + +- clean up 'incomplete' handling in QueueItemEstablish. +- rev 3973. + +------------------------------------------------------------------- +Tue Aug 15 11:30:50 CEST 2006 - kkaempf@suse.de + +- Don't set 'incomplete' for uninstalled patterns or products. + (#198379) +- rev 3970. + +------------------------------------------------------------------- +Mon Aug 14 16:50:53 CEST 2006 - schubi@suse.de + +- Added new API calls: + setAdditionalProvide + setAdditionalConflict + setAdditionalRequire + +------------------------------------------------------------------- +Mon Aug 14 11:26:20 CEST 2006 - dmacvicar@suse.de + +- don't link examples to testsuite library. + +------------------------------------------------------------------- +Sat Aug 12 17:30:30 CEST 2006 - schwab@suse.de + +- Disable profiling to work around compiler bug. + +------------------------------------------------------------------- +Fri Aug 11 17:01:33 CEST 2006 - dmacvicar@suse.de + +- forward port 3924:3939 +- Add explicit finish callbacks for subtasks during ProvidePackage + to avoid UI confusion. +- rev3957 + +------------------------------------------------------------------- +Fri Aug 11 11:48:44 CEST 2006 - dmacvicar@suse.de + +- Introduce examples/ +- fix some svn ignores +- fix compilation. Use: dbus_connection_close +- rev 3943 + +------------------------------------------------------------------- +Thu Aug 10 16:32:36 CEST 2006 - dmacvicar@suse.de + +- Initial support for plain directory with rpms as source +- r3935 + +------------------------------------------------------------------- +Tue Aug 8 16:51:45 CEST 2006 - dmacvicar@suse.de + +- Move the target query by kind function to + a iterator, so we dont make a copy of the restore + the iterator works loading by demand too + +------------------------------------------------------------------- +Mon Aug 7 17:57:26 CEST 2006 - dmacvicar@suse.de + +- rename the new initTarget to initializeTarget, + leave the old one as is, but deprecate it. +- r3903 + +------------------------------------------------------------------- +Mon Aug 7 15:10:08 CEST 2006 - dmacvicar@suse.de + +- forward port from SLES10 branch , till 3888 +- Prefer to use available DeltaRpm or PatchRpm instead of downloading + full packages. (#168844) +- rpmdb : Do not use the deprecated POSIX API, but boost::regex +- version 2.0.0 +- rev 3893 + +------------------------------------------------------------------- +Fri Aug 4 15:20:13 CEST 2006 - dmacvicar@suse.de + +- Separate target init from adding resolvables, getting rid of the +uggly bool flag. +- dont clear the store each time Target::resolvables is called +- Load target resolvables on demand by kind, keep them cached later +- add Target::resolvablesByKind(kind) to allow query specific kind + without reading all kinds. Used to port TargetProduct, which + was reading the whole rpm database only to displayy base product + name in YaST help. +- commit to pkg-bindings and packager will follow. +- jsrain will port more yast stuff, especially inst_source which + startup time should by reduced by half afterwards. +- rev 3880 + +------------------------------------------------------------------- +Tue Aug 1 13:37:29 CEST 2006 - dmacvicar@suse.de + +- forward port: + rev 3786 fix to stalle tmpfiles broke patches. + SLES was released with this broken. 10.1 has a blocked + zypp update because this. + Attempt to fix this. (#192535) +- fix configure.ac sqlite-source build path +- rev 3858 + +------------------------------------------------------------------- +Fri Jul 21 10:58:58 CEST 2006 - dmacvicar@suse.de + +- link correctly + +------------------------------------------------------------------- +Wed Jul 19 13:50:57 CEST 2006 - dmacvicar@suse.de + +- dont link sqlite in the main lib. +- rev 3826 + +------------------------------------------------------------------- +Tue Jul 18 17:42:45 CEST 2006 - dmacvicar@suse.de + +- susetags: parse product parser regexp only once +- parse yum factory 5 sec. (from 30) faster using + another string find algorithm +- rev 3824 + +------------------------------------------------------------------- +Tue Jul 18 12:56:17 CEST 2006 - dmacvicar@suse.de + +- Digest: Don't read the stream character wise but reading blocks, + as advised by matz profiling. +- r3819 + +------------------------------------------------------------------- +Mon Jul 17 12:54:39 CEST 2006 - ma@suse.de + +- Add "openSUSE", "ATI Technologies Inc." and "Nvidia" to + trusted vendors. (#189573) +- revision 3804 + +------------------------------------------------------------------- +Thu Jul 13 12:52:58 CEST 2006 - dmacvicar@suse.de + +- backport fix for stalle tmpfile (#191311) +- rev 3788 + +------------------------------------------------------------------- +Wed Jun 28 13:22:22 CEST 2006 - mt@suse.de + +- deactivated media manager code that was disabling the + automounter (#172419) +- rev 3724 + +------------------------------------------------------------------- +Mon Jun 26 17:14:53 CEST 2006 - dmacvicar@suse.de + +- fix autorefresh (#186115) +- revision 3708 +------------------------------------------------------------------- +Fri Jun 23 13:41:18 CEST 2006 - ma@suse.de + +- forward port from SLE branch +- Set default permission for logfiles to 0640. (#187044) +- revision 3696 + +------------------------------------------------------------------- +Thu Jun 22 16:01:15 CEST 2006 - ma@suse.de + +- forward port from SLE branch +- Fixed installation of SP or Add-On product switching to media 2 + too early. (#186607) +- revision 3691 + +------------------------------------------------------------------- +Wed Jun 21 15:47:39 CEST 2006 - dmacvicar@suse.de + +- forward port from SLE branch +- Strip self provides without edition in Resolvable ctor. + (#186079) +- Source::provideResolvables not implemented in yum source type. + Product not set for packages that are available from update source + (#186920) +- Hook modalias() supplements without package to "kernel" (#184840) +- Allow on-demand SourceManager::restore() (#186678) +- Hook modalias() supplements without package to "kernel" (#184840) +- rev 3676 + +------------------------------------------------------------------- +Mon Jun 19 15:17:17 CEST 2006 - mt@suse.de + +- Fix adding resolving of path names for mount points (#181606) +- rev 3658 + +------------------------------------------------------------------- +Mon Jun 19 13:52:14 CEST 2006 - dmacvicar@suse.de + +- merge download algorithm and refactoring from branch + (#181204) + +------------------------------------------------------------------- +Thu Jun 15 17:53:40 CEST 2006 - mvidner@suse.cz + +- autodocs: use find+xargs to overcome command length limit, + do not call doxygen unnecessarily (#185334). +- rev 3645 + +------------------------------------------------------------------- +Thu Jun 15 07:26:29 CEST 2006 - kkaempf@suse.de + +- Dont use getZYpp in static constructor (#185198) + Bugfix #178292 was wrong. +- Only warn on incompleting installed resolvables (#185197) +- rev 3644 + +------------------------------------------------------------------- +Wed Jun 14 22:43:40 CEST 2006 - kkaempf@suse.de + +- Atoms might only be installed via patches (#184714) +- rev 3642 + +------------------------------------------------------------------- +Wed Jun 14 17:26:39 CEST 2006 - dmacvicar@suse.de + +- fix for the last stall tmpfile (#178292) +- r3637 + +------------------------------------------------------------------- +Wed Jun 14 12:06:57 CEST 2006 - mt@suse.de + +- Implemented transfer timeout inside of the progress callback. + The timeout value can be set using timeout url parameter, the + default transfer timeout is 180 seconds. (#181602) +- Added ssl_verify and ssl_capath url options used in https scheme, + allowing to change or disable the ssl verify options. (#171622) +- Added fallback on read failures of /etc/mtab to /proc/mounts. + Improved verbosity in mount and mount check related failure cases, + incl. /etc/mtab dump. (#181606) +- rev 3623 + +------------------------------------------------------------------- +Wed Jun 14 10:49:10 CEST 2006 - kkaempf@suse.de + +- combine knownAliases and knownUrls in a single function. +- rev 3616 + +------------------------------------------------------------------- +Mon Jun 12 16:27:46 CEST 2006 - kkaempf@suse.de + +- honor parallel installs in resolver context (#181103) +- rev 3592 + +------------------------------------------------------------------- +Mon Jun 12 15:37:10 CEST 2006 - dmacvicar@suse.de + +- right fix for tmpdir initialized in static constructor +- catch around provideJustFile in providePackage +-rev 3654 + +------------------------------------------------------------------- +Mon Jun 12 15:15:07 CEST 2006 - dmacvicar@suse.de + +- fix #182003 YUM packages without size +- rev 3587 + +------------------------------------------------------------------- +Mon Jun 12 14:58:55 CEST 2006 - kkaempf@suse.de + +- Allow to restore and remove by Url +- rev 3583 + +------------------------------------------------------------------- +Mon Jun 12 13:07:31 CEST 2006 - kkaempf@suse.de + +- make atoms parallel installable (#181103) +- rev 3580 + +------------------------------------------------------------------- +Fri Jun 9 16:28:11 CEST 2006 - dmacvicar@suse.de + +- Allow to restore by alias +- r3568 + +------------------------------------------------------------------- +Fri Jun 9 13:06:16 CEST 2006 - mvidner@suse.cz + +- Do not fork in a global destructor, perl dislikes it (#182672). + Fixes hanging ag_ldapserver and yast2-perl-bindings tests. + +------------------------------------------------------------------- +Thu Jun 8 16:24:55 CEST 2006 - ma@suse.de + +- Installation: Assert product information is stored to libzypp + database before reboot. (#181198) +- Version 1.2.0; revision 3553 + +------------------------------------------------------------------- +Wed Jun 7 13:55:23 CEST 2006 - visnov@suse.cz + +- Synchronize keys with rpm database before + closing access to it (#182338) +- rev 3533 + +------------------------------------------------------------------- +Wed Jun 7 11:40:46 CEST 2006 - mt@suse.de + +- Changed to just prefer DVD drives in "dvd:" scheme, instead of + filter out the non-DVD drives completely. Allows a fallback to + drives without the dvd HAL property e.g. in VMWare. (#177457) +- rev 3530 + +------------------------------------------------------------------- +Wed Jun 7 01:00:06 CEST 2006 - dmacvicar@suse.de + +- Merge fix for stalle tmpdir due to cyclic references, using a master + TmpDir for zypp. (#178292) . There is still 1 tmpdir to fix. +- rev 3521 + +------------------------------------------------------------------- +Wed Jun 7 01:00:05 CEST 2006 - dmacvicar@suse.de + +- Fixes unneeded file download, and add download callbacks + (still need yast side) #181204 and #160206 +- Fix stalle tmpdir due to cyclic references, using a master + TmpDir for zypp. # 178292 + +------------------------------------------------------------------- +Wed Jun 7 00:02:18 CEST 2006 - ma@suse.de + +- fixed memory leak in PersistentStorage (#168690) +- revision 3519 + +------------------------------------------------------------------- +Tue Jun 6 22:24:00 CEST 2006 - ma@suse.de + +- fixed memory leak in XMLSourceCacheParser (#168690) +- revision 3517 + +------------------------------------------------------------------- +Fri Jun 2 16:09:03 CEST 2006 - schubi@suse.de + +-latest fi translation added + Revision 3502 + +------------------------------------------------------------------- +Thu Jun 1 15:11:47 CEST 2006 - schubi@suse.de + +-All installed resolvables has been set to "satisfied" in + ResolverContext::unneeded . BUT: + Patch concerning resolvables have to be set to + "unneeded" although they are installed. In order + getting the state "no longer applicable" (Bug 171590) +- rev 3496 + +------------------------------------------------------------------- +Thu Jun 1 14:54:02 CEST 2006 - kkaempf@suse.de + +- compute status for scripts and messages so their freshens get + properly honored (aj with postgresql-server) +- rev 3494 + +------------------------------------------------------------------- +Thu Jun 1 13:57:48 CEST 2006 - dmacvicar@suse.de + +- revert not-used-yet rpmdb timestamp, as + it broke rpmdb::init(). (#180040) +- rev 3490 + +------------------------------------------------------------------- +Thu Jun 1 11:03:34 CEST 2006 - schubi@suse.de + +- updating gmo files, if po files has been changed; bug 164449 + +------------------------------------------------------------------- +Wed May 31 18:32:58 CEST 2006 - dmacvicar@suse.de + +- Dont download twice if starting from 1st time +- fix typo +- rev 3481 + +------------------------------------------------------------------- +Wed May 31 17:06:48 CEST 2006 - dmacvicar@suse.de + +- set cache dir only if storeMetadata is called as a public method.´ +- rev 3475 + +------------------------------------------------------------------- +Wed May 31 15:27:38 CEST 2006 - kkaempf@suse.de + +- schedule a package for installation if + - it freshens / supplements something + - it is not installed yet + (#178721) +- rev 3473 + +------------------------------------------------------------------- +Wed May 31 15:22:43 CEST 2006 - dmacvicar@suse.de + +- make susetags also implement download and check first. +- rev 3470 + +------------------------------------------------------------------- +Tue May 30 12:43:47 CEST 2006 - dmacvicar@suse.de + +- make yum more robust. Never parse from provideFile + but only from local disk. Make sure the cache + is consistent before recreating it. + the code is easier to follow and probably + faster. checksum and signatures are + checked on caching not on parsing. + Required to implement refresh for #154990 +- rev 3452 + +------------------------------------------------------------------- +Wed May 24 16:57:54 CEST 2006 - dmacvicar@suse.de + +- implement timestamp for YUM and SuseTags +- actually use the license to confirm in yum patches +- add prerequires tag in yum optonally to the bad designed + and nonintuitive pre=1 +- rev 3448 + +------------------------------------------------------------------- +Wed May 24 15:30:32 CEST 2006 - dmacvicar@suse.de + +- dont pass root on init but before. +- implement rpm db modification timestamp + not used yet +- move Helix source to testsuite out of the solver + so we can use it for target, storage tests +- add Source_Ref::timestamp(), default to now() + in order to implement smart sync of sources by zmd +- don't parse desc and summary twice +- fix a segfault with tranlated text +- fix broken size tag introduced in rev 3427 +- rev 3446 + +------------------------------------------------------------------- +Tue May 23 20:53:27 CEST 2006 - dmacvicar@suse.de + +- dont accept corrupt sources, improve logs + +------------------------------------------------------------------- +Tue May 23 17:26:41 CEST 2006 - ma@suse.de + +- Added PoolItem_Ref::statusReset. Resets the PoolItem status without + loosing autoprotection (eg. for foreign vendor). (assists #177469) +- rev 3431 + +------------------------------------------------------------------- +Tue May 23 17:04:04 CEST 2006 - jsrain@suse.cz + +- added mediaNr() to PatchRpm and DeltaRpm classes +- rev 3430 + +------------------------------------------------------------------- +Tue May 23 15:58:04 CEST 2006 - dmacvicar@suse.de + +- enable YUM license to confirm. + needed for #174476 +- adapt store to serialize and read all new resobject fields +- use install-time to now() when serializing (#174653) +- rev 3427 + +------------------------------------------------------------------- +Mon May 22 20:51:59 CEST 2006 - ma@suse.de + +- Do not violate install order when restricting commit to a certain + mediaNumber. (#170079) +- Version 1.1.0; rev 3423 + +------------------------------------------------------------------- +Mon May 22 19:03:20 CEST 2006 - mvidner@suse.cz + +- Added SourceManager::findSourceByUrl to overcome alias mismatches + (#177543). +- rev 3420 + +------------------------------------------------------------------- +Mon May 22 17:19:25 CEST 2006 - ma@suse.de + +- Order all objects according to prerequirements, not just packages. + (#173690) +- rev 3419 + +------------------------------------------------------------------- +Mon May 22 15:57:43 CEST 2006 - schubi@suse.de + +- Added new translation + +------------------------------------------------------------------- +Fri May 19 12:53:44 CEST 2006 - dmacvicar@suse.de + +- fix missing homedir option for gpg (#171055) +- rev 3415 + +------------------------------------------------------------------- +Thu May 18 19:08:52 CEST 2006 - ma@suse.de + +- Prevent against daemons launched in rpm %post, that do not close + their filedescriptors. (#174548) +- Version 1.0.1; rev 3413 + +------------------------------------------------------------------- +Thu May 18 16:51:41 CEST 2006 - jsrain@suse.cz + +- fixed media number of package retrieved as a part of a patch + (#174841) +- rev 3409 + +------------------------------------------------------------------- +Thu May 18 16:16:21 CEST 2006 - dmacvicar@suse.de + +- fix missing package descriptions due to filtered packages + by incompatible architectures. (#159109) +- rev 3404 + +------------------------------------------------------------------- +Thu May 18 16:08:42 CEST 2006 - kkaempf@suse.de + +- decrease logging in DiskUsageCounter and Modalias (#163186) +- rev 3406 + +------------------------------------------------------------------- +Thu May 18 10:43:47 CEST 2006 - ma@suse.de + +- Stay backward comapatible. + +------------------------------------------------------------------- +Tue May 16 21:35:27 CEST 2006 - ma@suse.de + +- Make basic attributes available through ResObject. +- Let ResObjects which do not require media access during + commit return ZERO sourceMediaNr (required for #173690) +- Version 1.0.0 +- rev 3390 + +------------------------------------------------------------------- +Tue May 16 15:11:35 CEST 2006 - kkaempf@suse.de + +- reduce logging verbosity (#163186) +- rev 3381 + +------------------------------------------------------------------- +Tue May 16 14:00:57 CEST 2006 - schubi@suse.de + +- setCandidate accept candidates with compatible architectures too. Not + only with the same architecture. Bug 172594 - If update package has + differet arch, UI display is wrong + +------------------------------------------------------------------- +Tue May 16 09:30:45 CEST 2006 - mvidner@suse.cz + +- Added Source_Ref::resStoreInitialized. + If we know that noone has seen the resolvables yet, we can skip + them too, eg. when deleting a source. (#174840) +- rev 3378 + +------------------------------------------------------------------- +Mon May 15 12:41:39 CEST 2006 - kkaempf@suse.de + +- Honor freshens as conditionals independant from the installed/ + uninstalled status (#174797) +- rev 3376 + +------------------------------------------------------------------- +Mon May 15 11:15:03 CEST 2006 - kkaempf@suse.de + +- State modifier "unneeded" is transitive for patches (#171590) +- rev 3375 + +------------------------------------------------------------------- +Thu May 11 17:42:29 CEST 2006 - schubi@suse.de + +- Do not transact itself (update) in the transactResObject mechanism + Bug 174290 + +------------------------------------------------------------------- +Thu May 11 16:37:51 CEST 2006 - mt@suse.de + +- Reenabled improved large file support flags (unintentionally + removed in rev 1544). Fixes bug #173753. +- Added large file support flags to libzypp.pc file allowing + consistence checks in the application using features variable +- rev 3366 + +------------------------------------------------------------------- +Thu May 11 10:49:36 CEST 2006 - mvidner@suse.cz + +- SourceManager: moved source deletion before creation + so that we can recreate a deleted one (#174295) +- removed dead code dealing with known_caches from SourceManager::store + (see r3195) +- r3362 + +------------------------------------------------------------------- +Thu May 11 10:15:14 CEST 2006 - jsrain@suse.cz + +- fixed returning product short name and summary if product read + from target store (#148625) +- rev 3360 + +------------------------------------------------------------------- +Wed May 10 11:39:06 CEST 2006 - jsrain@suse.cz + +- set media verifier on redirected medium (#172599) +- rev 3359 + +------------------------------------------------------------------- +Mon May 8 17:28:42 CEST 2006 - kkaempf@suse.de + +- fix 'transactResKind' to collect best providers by capability + and to recursively transact items of same kind (#170114) +- rev 3355 + +------------------------------------------------------------------- +Mon May 8 16:45:46 CEST 2006 - dmacvicar@suse.de + +- serialize the full URL to avoid missing password and other + url settings (#148108) +- rev 3353 + +------------------------------------------------------------------- +Fri May 5 17:47:14 CEST 2006 - mt@suse.de + +- Added a 60 sec connect timeout to MediaCurl (#172860) +- rev 3348 + +------------------------------------------------------------------- +Thu May 4 15:15:37 CEST 2006 - kkaempf@suse.de + +- re-fetch also .asc and .key files before checking signature + (#172597) +- rev 3350 (3345-10.1) + +------------------------------------------------------------------- +Wed May 3 17:40:45 CEST 2006 - dmacvicar@suse.de + +- Fix yum key verification, because a double variable declaration + +------------------------------------------------------------------- +Wed May 3 15:34:00 CEST 2006 - dmacvicar@suse.de + +- use --no-default-keyring to avoid creating a + default gpg dir in / (#171055) +- rev 3335 + +------------------------------------------------------------------- +Wed May 3 14:40:25 CEST 2006 - dmacvicar@suse.de + +- Fix YUM signature checking, we were passing the key instead of the + signature. +- When the user trust a key, sync again. Bye to the session trusted + keys and user being asked all the time. (#171213) +- r3332 + +------------------------------------------------------------------- +Wed May 3 14:22:02 CEST 2006 - ma@suse.de + +- Cleanup index tables when removing items from pool (#170564). + +------------------------------------------------------------------- +Wed May 3 12:23:36 CEST 2006 - kkaempf@suse.de + +- backout rev 3246->3275 of TargetImpl.cc +- add missing testsuite/utils/TestUtils.h +- rev 3330 + +------------------------------------------------------------------- +Wed May 3 12:13:38 CEST 2006 - dmacvicar@suse.de + +- more fixes for #171062, there were some files still not being + read from cache. +- r3327 + +------------------------------------------------------------------- +Tue May 2 18:41:44 CEST 2006 - dmacvicar@suse.de + +- cache keys and signature. Remove lot of duplicated code. (#171062) +- r3320 + +------------------------------------------------------------------- +Tue May 2 18:02:46 CEST 2006 - mt@suse.de + +- Disabled isUseableAttachPoint check in MediaDIR -- we do not + mount here anything, so it is OK to use any dir (171351). +- rev 3318 + +------------------------------------------------------------------- +Tue May 2 14:58:03 CEST 2006 - kkaempf@suse.de + +- parse "license-to-confirm" in primary.xml (#168437) +- rev 3312 + +------------------------------------------------------------------- +Mon May 1 17:44:29 CEST 2006 - kkaempf@suse.de + +- Don't try to store 'Atom', not needed and the backend store + rejects them anyways (addtion to #168610) +- rev 3306 + +------------------------------------------------------------------- +Mon May 1 04:43:01 CEST 2006 - mt@suse.de + +- Improved device check in MediaDISK using libblkid (Bug #158529) +- Allow to provide sysfs path via $SYSFS_PATH in MediaCD.cc and + added a check if it is a directory +- Added libcurl and libblkid checks to configure.ac +- Added e2fsprogs(-devel) requires to the spec file +- rev 3303 + +------------------------------------------------------------------- +Sat Apr 29 21:46:22 CEST 2006 - kkaempf@suse.de + +- dont download "other" during key check (#171041) +- rev 3294 + +------------------------------------------------------------------- +Sat Apr 29 11:05:15 CEST 2006 - kkaempf@suse.de + +- allow parallel installs of atoms (used to fulfill patch require- + ments, atoms aren't installed anyways) (#170098) +- some testsuite improvements. +- rev 3288 + +------------------------------------------------------------------- +Fri Apr 28 20:15:06 CEST 2006 - dmacvicar@suse.de + +- get rid of autobuild check when throwing exceptions without throw + but with a macro, returning a null pointer at the end (never reached). + +------------------------------------------------------------------- +Fri Apr 28 19:50:28 CEST 2006 - ma@suse.de + +- Do not violate install order when restricting commit to a certain + mediaNumber. (#170079) + +------------------------------------------------------------------- +Fri Apr 28 18:12:26 CEST 2006 - dmacvicar@suse.de + +- Don't use throw directly! + use ZYPP_THROW with a Exception class, otherwise package bindings + will not catch them. + Should fix crashes when reading broken sources with yast. +- rev 3272 + +------------------------------------------------------------------- +Fri Apr 28 15:29:32 CEST 2006 - schubi@suse.de + +- Bug 162064 - font packages are not installed for locale, e.g. khmer font not installed after CD1 + revision 3269 + +------------------------------------------------------------------- +Fri Apr 28 14:55:04 CEST 2006 - kkaempf@suse.de + +- revert bugfix #168906 (fom rev 3219), it filters too many errors. +- further improve on #168840 (from rev 3231), match on name-edition + when filtering by best arch. (#170098) +- rev 3268 + +------------------------------------------------------------------- +Fri Apr 28 13:01:58 CEST 2006 - dmacvicar@suse.de + +- #170093 , lot of package descriptions missing +- rev 3263 + +------------------------------------------------------------------- +Thu Apr 27 20:28:01 CEST 2006 - dmacvicar@suse.de + +- try to fix wrong permissions of /var/lib/zypp created + by old zypp, only when running as root they are fixed + (#169094) +- YUM: Verify signatures on factoryInit. + Dont provide other.xml. Cleanups, better logging. + When refreshing signed soruces, don't refresh is source + has not changed. +- YaST sources: don't refresh if media file has not changed. +- Show full url of index files in sources for signature validation + (mentioned in #170139 comment #3)- + +------------------------------------------------------------------- +Thu Apr 27 18:41:02 CEST 2006 - jsrain@suse.de + +- udpated media ID syntax for external scripts (to be consistent + with packages) (#170247) +- rev 3256 + +------------------------------------------------------------------- +Thu Apr 27 18:33:48 CEST 2006 - jsrain@suse.de + +- set media ID to 1 if not specified in YUM metadata (#167452) +- rev 3255 + +------------------------------------------------------------------- +Thu Apr 27 11:55:05 CEST 2006 - kkaempf@suse.de + +- If freshen and supplement are fulfilled, install any kind of + resolvable if not yet installed (#165746) +- rev 3249 + +------------------------------------------------------------------- +Wed Apr 26 18:00:42 CEST 2006 - kkaempf@suse.de + +- make downloaded script executable. (#169191) +- rev 3247 + +------------------------------------------------------------------- +Wed Apr 26 10:43:03 CEST 2006 - kkaempf@suse.de + +- Improve on last fix, compare only compatible archs. +- rev 3233 + +------------------------------------------------------------------- +Tue Apr 25 19:36:13 CEST 2006 - kkaempf@suse.de + +- Only choose best arch of multiple package atoms with identical + name (#168840) +- rev 3231 + +------------------------------------------------------------------- +Tue Apr 25 16:59:51 CEST 2006 - dmacvicar@suse.de + +- pass empty strings to UI as key properties if unknown key + (#169114) +- rev 3228 + +------------------------------------------------------------------- +Tue Apr 25 16:47:35 CEST 2006 - kkaempf@suse.de + +- refrain from parsing 'other.xml' (#159316) +- rev 3226 + +------------------------------------------------------------------- +Tue Apr 25 16:34:50 CEST 2006 - visnov@suse.cz + +- in source refresh, clean up the cache dir if fails +- do not require repomd.xml.asc when creating a cache (#163765) +- rev 3224 + +------------------------------------------------------------------- +Tue Apr 25 15:17:15 CEST 2006 - dmacvicar@suse.de + +- Check if a file exists before providing it, and just handling the + exception is not sufficient, because it can release the media. + it nows get all possible packages.X translations an then + it selects the candidate from the existing ones (#168654) +- rev 3221 + +------------------------------------------------------------------- +Tue Apr 25 12:28:17 CEST 2006 - kkaempf@suse.de + +- dont report conflicts if item is neither installed + nor to-be-installed (#168906) +- rev 3219 + +------------------------------------------------------------------- +Tue Apr 25 11:27:09 CEST 2006 - dmacvicar@suse.de + +- #168060 , propagate the file description or original + name to the UI and not the checked filename path, + which could be a tmp file. + Requires changes in pkg-manager, and probably zmd-helpers. +- rev 3215 + +------------------------------------------------------------------- +Mon Apr 24 18:27:59 CEST 2006 - dmacvicar@suse.de + +- /var/lib/zypp/db/languages/* are empty files (##168355) +- r3206 + +------------------------------------------------------------------- +Mon Apr 24 17:45:07 CEST 2006 - dmacvicar@suse.de + +- All resolvables must honor arch, so Arch_noarch in + target/store/XMLFilesBackend.cc is wrong (#160792) +- Introduced code to honour shared package descriptions + (#159109) +- r3204 + +------------------------------------------------------------------- +Mon Apr 24 16:43:48 CEST 2006 - jsrain@suse.de + +- replace '_' in YUM elements/attributes with '-' (#168762) +- rev 3201 + +------------------------------------------------------------------- +Mon Apr 24 16:15:02 CEST 2006 - mt@suse.de + +- Fixed iseries workaround - interchanged variables for scsi + devices, added debug messages about the steps (#163971). +- Added getenv NULL ptr check and verify of the $HOME dir's + and ~/.curlrc file's ownership (#163203). +- rev 3199 + +------------------------------------------------------------------- +Mon Apr 24 15:44:18 CEST 2006 - ma@suse.de + +- Use filesystem::TmpDir to create unique and unused Source cache + directories. (#168051) + +------------------------------------------------------------------- +Mon Apr 24 14:30:41 CEST 2006 - ma@suse.de + +- Enable signature checks per default. (#168525) + +------------------------------------------------------------------- +Mon Apr 24 11:20:17 CEST 2006 - visnov@suse.cz + +- fix callbacks for providing a single file (#160206) + +------------------------------------------------------------------- +Sun Apr 23 12:28:21 CEST 2006 - kkaempf@suse.de + +- If an installed package looses a dependency, the solver tries + to upgrade it. Limit the upgrade candidates to best arch, best + edition. +- filter 'other' entries with incompatible arch in yum parser. +- rev 3177 + +------------------------------------------------------------------- +Fri Apr 21 22:47:18 CEST 2006 - jsrain@suse.de + +- initialize the product category according to source (#168061) +- rev 3172 + +------------------------------------------------------------------- +Fri Apr 21 18:32:00 CEST 2006 - mvidner@suse.cz + +- delete only one older version of a xml-store resolvable + (half-baked, but the previous attempt was charred) + +------------------------------------------------------------------- +Fri Apr 21 17:49:18 CEST 2006 - jsrain@suse.de + +- moved license_to_confirm to primary.xml +- rev 3170 + +------------------------------------------------------------------- +Fri Apr 21 16:36:14 CEST 2006 - ma@suse.de + +- Removed deprecated oldstyle commit methods. + +------------------------------------------------------------------- +Fri Apr 21 15:58:14 CEST 2006 - mvidner@suse.cz + +- when installing a xml-store resolvable (all except package, + message, script), delete older versions (#160792). +- read selection edition from the XML store +- rev 3167 + +------------------------------------------------------------------- +Thu Apr 20 14:10:41 CEST 2006 - kkaempf@suse.de + +- properly clear transaction flag after successful commit + (see rev 3122, #164365, #167285) +- rev 3157 + +------------------------------------------------------------------- +Thu Apr 20 13:14:25 CEST 2006 - kkaempf@suse.de + +- recursively soft-uninstall recommended package on real uninstall, + not on update (#167603) +- rev 3155 + +------------------------------------------------------------------- +Thu Apr 20 13:01:28 CEST 2006 - dmacvicar@suse.de + +- fix #167605 (importing keys to rpm multiple times due to + wrong interpretation of rpm gpg versioning. +- add support for reading the rpm keys, with full id and fingerprint +- rev 3153 + +------------------------------------------------------------------- +Wed Apr 19 16:47:34 CEST 2006 - kkaempf@suse.de + +- don't add duplicate error infos to ResolverContext (#167309) +- rev 3146 + +------------------------------------------------------------------- +Wed Apr 19 14:10:10 CEST 2006 - kkaempf@suse.de + +- fix Resolver::transactReset() (see rev 3122) (#167285) +- rev 3140 + +------------------------------------------------------------------- +Wed Apr 19 13:48:26 CEST 2006 - ma@suse.de + +- Introduced $ZYPP_KEYRING_DEFAULT_ACCEPT_ALL. If this environment + variable is present, all signature checking callbacks will default + to 'accept', in case no recipient is present. + +------------------------------------------------------------------- +Wed Apr 19 11:37:47 CEST 2006 - dmacvicar@suse.de + +- read content file on construction, and make + provideProduct only insert the already + read product object into the store (#165826) + (dmacvicar) +- When the signature is not found, warn the + user about a unsigned source. When the + key is not found, do nothing, it can be in the + keyring already. (#166016) (dmacvicar) +- enable key verification only if + ZYPP_CHECKSIG env var is set (dmacvicar) +- r1529 + +------------------------------------------------------------------- +Tue Apr 18 20:41:48 CEST 2006 - kkaempf@suse.de + +- fix bugfix 164365, fix bug 167285 + Actually clear the transcation state instead of locking it + to 'dont transact' +- rev 3122 + +------------------------------------------------------------------- +Tue Apr 18 15:46:59 CEST 2006 - visnov@suse.cz + +- revert the signature/digest checking callbacks +- rev 3115 + +------------------------------------------------------------------- +Tue Apr 18 15:14:35 CEST 2006 - kkaempf@suse.de + +- Bugfix #165670 + - Honor keep requests. + - Dont flag "locked uninstall" as error if a keep request was + issued before. +- rev 3114 + +------------------------------------------------------------------- +Tue Apr 18 12:04:35 CEST 2006 - kkaempf@suse.de + +- rule out locked items during distribution upgrade as early + as possible. (#165670) +- rev 3110 + +------------------------------------------------------------------- +Mon Apr 17 16:04:35 CEST 2006 - kkaempf@suse.de + +- Bugfix #166212 + - use APPL_LOW as 'ui initiated, by solver' in transactKind() and + transactResObject(). + - resetTransaction(APPL_LOW) before resolving + - enhance transactCaps by using the same algorithm as in + QueueItemRequire + (before: transact all requires and recommends by name + now: transact best requires and recommends by provides) +- rev 3107 + +------------------------------------------------------------------- +Fri Apr 14 16:04:35 CEST 2006 - visnov@suse.cz + +- new callbacks for failing digest +- rev 3098 + +------------------------------------------------------------------- +Thu Apr 13 17:01:41 CEST 2006 - visnov@suse.cz + +- ask for file without a checksum (#165125) + +------------------------------------------------------------------- +Thu Apr 13 16:59:38 CEST 2006 - kkaempf@suse.de + +- dont install satisfied resolvables (#165843) +- rev 3095 + +------------------------------------------------------------------- +Thu Apr 13 16:00:21 CEST 2006 - kkaempf@suse.de + +- dont abort on failed "dry_run" (#164583) +- rev 3091 + +------------------------------------------------------------------- +Thu Apr 13 15:19:20 CEST 2006 - visnov@suse.cz + +- Ask user if signature file does not exist (#163765) +- handle repomd.xml.asc as optional file (#163765) +- rev 3089 + +------------------------------------------------------------------- +Thu Apr 13 13:52:08 CEST 2006 - schubi@suse.de + +- Bug 164365 - build 906: Deselecting a selection, all packages are still selected +- rev 3087 + +------------------------------------------------------------------- +Thu Apr 13 11:57:58 CEST 2006 - kkaempf@suse.de + +- Dont do transitive uninstalls on uninstalled or upgraded items. + (#165798) +- rev 3083 + +------------------------------------------------------------------- +Wed Apr 12 17:57:21 CEST 2006 - ma@suse.de + +- Added 'rpmNoSignature' to ZYppCommitPolicy (#163862) + +------------------------------------------------------------------- +Wed Apr 12 16:44:57 CEST 2006 - mvidner@suse.cz + +- Product::updateUrls: restore it from the XML store; + fixed content parsing (#163192). +- restore product flags fro the XML store +- rev 3074 + +------------------------------------------------------------------- +Wed Apr 12 13:48:25 CEST 2006 - kkaempf@suse.de + +- Only consider best arch/version (#165477) +- rev 3069 + +------------------------------------------------------------------- +Wed Apr 12 10:57:50 CEST 2006 - ma@suse.de + +- No need to parse tags at all if there is no item to store values + (e.g. data for unwanted arch). Fixed segv trying to store data in + NULL item. (#165479) +- rev3065 + +------------------------------------------------------------------- +Tue Apr 11 19:48:51 CEST 2006 - mt@suse.de + +- Improved Url path name "//" vs. "/%2f" handling; now if the + url has an authority, "/%2f" is used for ftp only (#163784) +- rev 3062 + +------------------------------------------------------------------- +Tue Apr 11 16:41:02 CEST 2006 - jsrain@suse.de + +- fixed storing patch scripts to target store (#159928) +- rev 3058 + +------------------------------------------------------------------- +Tue Apr 11 16:24:26 CEST 2006 - kkaempf@suse.de + +- if a patch is bad, only skip this patch, not everything + (#165200) +- rev 3057 + +------------------------------------------------------------------- +Tue Apr 11 15:42:32 CEST 2006 - ma@suse.de + +- Susetags:Selections: Allow parsing older .sel file formats. (#159851) +- Susetags:Pattern: Fixed parser. + +------------------------------------------------------------------- +Tue Apr 11 15:21:48 CEST 2006 - kkaempf@suse.de + +- when uninstalling, only re-establish installed items + supplementing the to-be-uninstalled one. (variant of #165111) +- rev 3054 + +------------------------------------------------------------------- +Tue Apr 11 14:17:00 CEST 2006 - ma@suse.de + +- Susetags:Package: Parse and provide ins/delnotify texts. + +------------------------------------------------------------------- +Tue Apr 11 13:01:31 CEST 2006 - kkaempf@suse.de + +- when checking freshens/supplements at install, only consider + best architecture/edition (#164453) +- rev 3051 + +------------------------------------------------------------------- +Tue Apr 11 10:31:41 CEST 2006 - kkaempf@suse.de + +- when checking for supplements, only consider best arch, best + edition for installation (#165111) +- rev 3047 + +------------------------------------------------------------------- +Tue Apr 11 10:23:14 CEST 2006 - schubi@suse.de + +- Bug 165117: build 910: Update: Splitted packages are selected for + all archs + +------------------------------------------------------------------- +Tue Apr 11 09:30:14 CEST 2006 - visnov@suse.cz + +- ask user if a file exists but does not have a checksum (#162797) +- rev 3044 + +------------------------------------------------------------------- +Mon Apr 10 22:39:34 CEST 2006 - jsrain@suse.de + +- parse time and size elements from delta and patch RPM +- rev 3043 + +------------------------------------------------------------------- +Mon Apr 10 18:55:03 CEST 2006 - mt@suse.de + +- Added detection of iSeries virtual CD (/dev/iseries/vcd[a-h]) + devices - on powerpc only (#163971) +- rev 3042 + +------------------------------------------------------------------- +Mon Apr 10 18:05:51 CEST 2006 - kkaempf@suse.de + +- fix endless loop in patches parsing. +- rev 3039 + +------------------------------------------------------------------- +Mon Apr 10 17:00:05 CEST 2006 - jsrain@suse.de + +- fixed media handling in SuSEtags source (#164879) +- rev 3037 + +------------------------------------------------------------------- +Mon Apr 10 16:30:54 CEST 2006 - kkaempf@suse.de + +- honor 'dry_run' on package remove (#164732) +- rev 3036 + +------------------------------------------------------------------- +Mon Apr 10 13:12:49 CEST 2006 - kkaempf@suse.de + +- add files from yum filelist as provides to package (#164731) +- rev 3032 + +------------------------------------------------------------------- +Mon Apr 10 11:10:37 CEST 2006 - kkaempf@suse.de + +- honor "+Enh:/-Enh:" in packages file (#156513) + +------------------------------------------------------------------- +Mon Apr 10 10:56:24 CEST 2006 - visnov@suse.cz + +- fix callback receiver signature to match the callback for removing + package + +------------------------------------------------------------------- +Mon Apr 10 10:32:22 CEST 2006 - mvidner@suse.cz + +- Added Product::updateUrls, from content/UPDATEURLS (#163192). +- rev 3024 + +------------------------------------------------------------------- +Sat Apr 8 12:03:37 CEST 2006 - schubi@suse.de + +- Bug 164440; Taking wrong architecture while updating obsoletes + splitted packages +- rev 3022 + +------------------------------------------------------------------- +Sat Apr 8 10:07:06 CEST 2006 - kkaempf@suse.de + +- allow relative paths with url file: +- dont filter atoms from going into pool, multi-arch patch + requirements need them. Instead, treat atoms with incompatible + architecture as unneeded. +- rev 3018 + +------------------------------------------------------------------- +Fri Apr 7 23:57:37 CEST 2006 - jsrain@suse.de + +- product now provides short name +- rev 3013 + +------------------------------------------------------------------- +Fri Apr 7 20:42:09 CEST 2006 - jsrain@suse.de + +- read metadata for packages from correct tags in patches (#163220) +- rev 3011 + +------------------------------------------------------------------- +Fri Apr 7 19:57:41 CEST 2006 - kkaempf@suse.de + +- more detailed resolver error reports (#162994) +- rev 3010 + +------------------------------------------------------------------- +Fri Apr 7 17:35:07 CEST 2006 - visnov@suse.cz + +- report package download progress (#160966) +- rev 3007 + +------------------------------------------------------------------- +Fri Apr 7 16:27:35 CEST 2006 - kkaempf@suse.de + +- transact also for languages (#163819) +- rev 3004 + +------------------------------------------------------------------- +Fri Apr 7 15:08:06 CEST 2006 - kkaempf@suse.de + +- loop through all affected ResObjects in transactResKind (#163819) +- rev 3002 + +------------------------------------------------------------------- +Fri Apr 7 12:42:35 CEST 2006 - kkaempf@suse.de + +- allow re-installation of non-packages (#162906) +- rev 2998 + +------------------------------------------------------------------- +Fri Apr 7 11:50:22 CEST 2006 - mt@suse.de + +- Added loop checking for scsi cdroms (/sys/block/srX) in case + HAL does not provide any drives like on iSeries (#163971). +- rev 2995 + +------------------------------------------------------------------- +Fri Apr 7 11:05:30 CEST 2006 - kkaempf@suse.de + +- add 'licenceToConfirm()' to Product. (#164375) + +------------------------------------------------------------------- +Fri Apr 7 10:36:05 CEST 2006 - ma@suse.de + +- Avoid excessive CD hopping on commit. But still far from + being perfect. (#159679) +- Fixed Target::commit: Despite dry_run set True, packages + were depeted. + +------------------------------------------------------------------- +Fri Apr 7 08:32:32 CEST 2006 - visnov@suse.cz + +- honour if user decides to skip a package in commit (#156031) + +------------------------------------------------------------------- +Thu Apr 6 18:14:30 CEST 2006 - jsrain@suse.de + +- fixed parsing external reference to script in patch (#163221) +- r2981 + +------------------------------------------------------------------- +Thu Apr 6 17:07:10 CEST 2006 - dmacvicar@suse.de + +- cache and provide content.asc/key optionally. Dont show a + popup if they dont exists. (dmacvicar) +- Actually abort when verify signature workflow is false. (dmacvicar) +- r2978 + +------------------------------------------------------------------- +Thu Apr 6 16:37:49 CEST 2006 - jsrain@suse.de + +- fixed setting autorefresh flag for installation sources + +------------------------------------------------------------------- +Thu Apr 6 15:53:02 CEST 2006 - kkaempf@suse.de + +- drop patches with incompatible architecture. +- rev 2972 + +------------------------------------------------------------------- +Thu Apr 6 15:33:11 CEST 2006 - mt@suse.de + +- Added info method to media verifier base and more debug info +- rev 2970 + +------------------------------------------------------------------- +Wed Apr 5 19:27:46 CEST 2006 - kkaempf@suse.de + +- Dont deny the "/" attach point in MediaDIR, since this is used + for all "file:" urls, esp. local packages. +- rev 2962 + +------------------------------------------------------------------- +Wed Apr 5 18:21:58 CEST 2006 - schubi@suse.de + +- Bug 159673 - only one conflict solvable per page + +------------------------------------------------------------------- +Wed Apr 5 18:01:37 CEST 2006 - kkaempf@suse.de + +- parse all dependencies of 'packages' file (#163773) +- rev 2957 + +------------------------------------------------------------------- +Wed Apr 5 17:47:04 CEST 2006 - dmacvicar@suse.de + +- Use the original media descr_dir on refresh for + suse tags source (#163196) +- r2952 + +------------------------------------------------------------------- +Wed Apr 5 16:44:08 CEST 2006 - kkaempf@suse.de + +- add Source::setUrl() for zmd backend helper. +- rev 2946 + +------------------------------------------------------------------- +Wed Apr 5 16:44:01 CEST 2006 - dmacvicar@suse.de + +- implement rpm keyring / zypp tmp keyring two-way syncronization at rpm +target init. (dmacvicar) +- r2949 + +------------------------------------------------------------------- +Wed Apr 5 16:28:42 CEST 2006 - mt@suse.de + +- Fixed MediaDISK to use a mount -oro,bind id the disk + partition is already attached e.g. by the automounter. + Try to mount it a second time may fail (#163486). +- rev 2944 + +------------------------------------------------------------------- +Wed Apr 5 15:04:31 CEST 2006 - kkaempf@suse.de + +- honor optional 3rd parameter to "=Loc:" key of packages (#154337) +- rev 2940 + +------------------------------------------------------------------- +Wed Apr 5 12:48:19 CEST 2006 - visnov@suse.cz + +- only try to create a source of a given type when restoring + from the persistent store (#162111) + +------------------------------------------------------------------- +Wed Apr 5 11:36:54 CEST 2006 - kkaempf@suse.de + +- parse all dependencies for patterns (.pat) files (#160602) +- drop YOUPATH and YOUURL from content file. +- rev 2924 + +------------------------------------------------------------------- +Wed Apr 5 09:27:08 CEST 2006 - visnov@suse.cz + +- properly initialize autorefresh for non-remote sources (#154990) +- rev 2919 + +------------------------------------------------------------------- +Tue Apr 4 19:19:39 CEST 2006 - mt@suse.de + +- Added flag to MediaManager::isUseableAttachPoint, whether + to check against system mount entries or not. +- Disallows one to use the attachpoints of another media handlers + as source path in MediaDIR. +- rev 2917 + +------------------------------------------------------------------- +Tue Apr 4 18:47:01 CEST 2006 - dmacvicar@suse.de + +-implement callbacks for when package verification (checksum) + fails, offer to retry or abort + +------------------------------------------------------------------- +Tue Apr 4 16:57:51 CEST 2006 - dmacvicar@suse.de + +- Fix construction of checksum objects when using non-standard + checksum algorithms +- Fix broken YUM cache +- r2913 + +------------------------------------------------------------------- +Tue Apr 4 16:54:44 CEST 2006 - kkaempf@suse.de + +- Keep packages with no version upgrade installed during + distribution upgrade (#162972) +- add 'transactReset()' helper function for UI. +- rev 2908 + +------------------------------------------------------------------- +Tue Apr 4 14:47:14 CEST 2006 - dmacvicar@suse.de + +- r2906 + +------------------------------------------------------------------- +Tue Apr 4 14:43:15 CEST 2006 - ma@suse.de + +- Fixed candidate handling in ui::Selectable. (#156589) + +------------------------------------------------------------------- +Tue Apr 4 14:06:23 CEST 2006 - dmacvicar@suse.de + +- fix #162984 , gpg hangs because the matching data file + for the key cannot be find. (dmacvicar) +- Fix restore of YUM source using the same cache dir semantics as + susetags instead of assuming there is a cache if a cache_dir + was given. (dmacvicar) + +------------------------------------------------------------------- +Tue Apr 4 12:37:51 CEST 2006 - kkaempf@suse.de + +- use DISTPRODUCT/DISTVERSION from content file to generate the + product name, version, and release. +- rev 2902 + +------------------------------------------------------------------- +Mon Apr 3 20:45:55 CEST 2006 - mt@suse.de + +- Removed broken forcing of absolute ftp paths added in rev2705 to + MediaCurl, refined cleanupPathName/setPathName in url (#154197). +- rev 2900 + +------------------------------------------------------------------- +Mon Apr 3 19:30:35 CEST 2006 - kkaempf@suse.de + +- add Resolver::freshenPool() (#156980) +- rev 2893 + +------------------------------------------------------------------- +Mon Apr 3 08:33:12 CEST 2006 - kkaempf@suse.de + +- skip incompatible archs in filelist parsing. +- restrict pathes to 'interesting' ones (/bin/, /sbin/, /lib/, + /lib64/, ...) +- rev 2886 + +------------------------------------------------------------------- +Sun Apr 2 22:18:06 CEST 2006 - kkaempf@suse.de + +- skip incompatible archs in primary parsing. +- rev 2883 + +------------------------------------------------------------------- +Sun Apr 2 11:17:56 CEST 2006 - kkaempf@suse.de + +- allow setting of source when parsing local .rpm (#147765) +- rev 2880 + +------------------------------------------------------------------- +Fri Mar 31 18:53:55 CEST 2006 - schubi@suse.de + +- Do not update packages over other architectures + +------------------------------------------------------------------- +Fri Mar 31 18:28:59 CEST 2006 - sh@suse.de + +- Added zypp/ui/UserWantedPackages to support the UI's + "automatic changes" dialog (bug #152700) + +------------------------------------------------------------------- +Fri Mar 31 18:02:05 CEST 2006 - jsrain@suse.de + +- use KeyRing class to validate repomd.xml (#160909) + +------------------------------------------------------------------- +Fri Mar 31 17:33:21 CEST 2006 - dmacvicar@suse.de + +- Product resolvables should be readable by normal users. + (#162474) (dmacvicar) +- implemented keyring and metadata signature verification + in susetags source +- dont delete the lock if we did not acquire it +- r2847 + +------------------------------------------------------------------- +Fri Mar 31 16:34:51 CEST 2006 - mt@suse.de + +- Added disabling of the automounter while MediaManager + init and restoring of the old state on exit (#154326). +- Implemented check if media (CD) is automounted or not +- rev 2840 + +------------------------------------------------------------------- +Fri Mar 31 13:27:09 CEST 2006 - mt@suse.de + +- Implemented several hal get/set/removeDeviceProperty wrappers +- Improved HalException allows one to fetch HAL/DBUS error componets +- rev 2830 + +------------------------------------------------------------------- +Fri Mar 31 12:44:25 CEST 2006 - kkaempf@suse.de + +- honor subscription status of catalogs (#162350) +- rev 2827 + +------------------------------------------------------------------- +Fri Mar 31 11:29:05 CEST 2006 - mt@suse.de + +- Enabled CD eject error reporting exceptions (#154326) +- rev 2822 + +------------------------------------------------------------------- +Fri Mar 31 06:40:51 CEST 2006 - kkaempf@suse.de + +- support "dry run" (#159467) +- implement "transactResKind" (#161400) +- rev 2817 + +------------------------------------------------------------------- +Thu Mar 30 17:22:49 CEST 2006 - jsrain@suse.de + +- add checksum for external patches (#159928) + +------------------------------------------------------------------- +Thu Mar 30 16:48:01 CEST 2006 - kkaempf@suse.de + +- calculate product architecture (#158198) + +------------------------------------------------------------------- +Wed Mar 29 23:28:13 CEST 2006 - jsrain@suse.de + +- fixed checking checksum of YUM metadata, added sha1 vs. sha256 + detection + +------------------------------------------------------------------- +Wed Mar 29 23:12:30 CEST 2006 - ma@suse.de + +- Auto protect installed packages from unknown vendor. (#157446) + +------------------------------------------------------------------- +Wed Mar 29 09:13:51 CEST 2006 - visnov@suse.de + +- added support for external scripts to metadata (#159928) (jsrain) +- fixed handling of Language resolvables (ma) +- fix leak in rpmdb (dmacvicar) +- added softlock for autoyast (#159466) (ma) +- Fixed exceptions in doGetFileCopy() to show full url + including the file instead of just the media base url. (mt) +- Provide Language::summary (ma) +- check patterns and selections file exist + before veryfing them (#161300) (dmacvicar) +- added YUM metadata checksum computation (jsrain) +- added interface to patch of a message (jsrain) +- r2734 + +------------------------------------------------------------------- +Mon Mar 27 23:57:16 CEST 2006 - jsrain@suse.de + +- added support for external scripts to metadata (#159928) +- r2709 + +------------------------------------------------------------------- +Sat Mar 25 22:08:26 CET 2006 - jsrain@suse.de + +- report separate exception when trying to start source cache again to + suppress incorrect error message in XEN installation +- r2682 + +------------------------------------------------------------------- +Fri Mar 24 18:16:22 CET 2006 - schubi@suse.de + +- Implement inter process locking in zypp. +- Added No medium found output +- splitting modaliases in supplements TOO +- parse also the available signing keys + +------------------------------------------------------------------- +Fri Mar 24 10:44:10 CET 2006 - visnov@suse.cz + +- release all media when removing source (#159754) (visnov) +- more testsuites (schubi) +- updated translations (schubi) +- added MediaNotEjectedException (mt) +- rev 2652 + +------------------------------------------------------------------- +Thu Mar 23 14:10:54 CET 2006 - dmacvicar@suse.de + +- fix patches descriptions (dmacvicar) +- fix source serialization (dmacvicar) +- metadata for kernel test (schubi) +- Arch tests updated (ma) +- classify NULL Ptr as unique (ma) +- Added host check, because file Url allows it now. (mt) +- prepare modalias fix (#159766) (ma) +- Provide iterator based access to SourceManager data. (ma) +- Fixed "file:" Url scheme config to allow relative paths; (mt) + RFC1738 says, it may contain a hostname as well... +- revision 2633 + +------------------------------------------------------------------- +Wed Mar 22 19:58:37 CET 2006 - visnov@suse.cz + +- pkg-config support (mvidner) +- close all medias when destructing MediaSet (jsrain) +- rev 2622 + +------------------------------------------------------------------- +Wed Mar 22 15:48:05 CET 2006 - dmacvicar@suse.de + +- Bug 159976 - build 804: Adding AddOn CD via ftp gives error (dmacvicar) +- Message callback implemented to show patch messages (visnov) +- Bug 159696 (schubi) +- provide transform_iterators to iterate over a maps keys or values (ma) +- added 'bool Arch::empty() const' test for an empty Arch string (ma) +- added script and message installation (jsrain) +- chooses the 'right' kernel now (kkaempf) +- Use noarch if no arch is specified in patches (dmacvicar) +- rev 2611 + +------------------------------------------------------------------- +Tue Mar 21 19:06:56 CET 2006 - mvidner@suse.cz + +- Added some debug output including the access id (mt) +- Bug #154326: Enabled FORCE_RELEASE_FOREIGN flag causing + release with eject=true on attached media, to umount + other mounts as well. (mt) +- 159483 - solver does not blame missing dependency (schubi) +- Added a variant of MediaHandler::forceRelaseAllMedia (ma) +- Fixed MediaCD::forceEject() to handle DELAYED_VERIFY + and use forceRelaseAllMedia if FORCE_RELEASE_FOREIGN=1 (ma) +- fixed ZYPP_RETHROW (#156430) (ma) +- patch for #156114 (visnov) +- fixed container.erase loops (ma) +- Fixed to reset desired (cached) flag before the action (mt) +- Removed return in forceRelaseAllMedia (void function) (mt) +- Parse nonexisting architecture to noarch so patches dont get + filtered by the pool (dmacvicar) +- 159512 - yast2-qt does not show label of to be installed products + anymore (dmacvicar) +- 159765 - Hidden patterns still visible (dmacvicar) +- Use noarch if no arch is specified. (dmacvicar) +- r2594 + +------------------------------------------------------------------- +Tue Mar 21 09:04:06 CET 2006 - visnov@suse.de + +- properly report error for media change callback +- rev 2579 + +------------------------------------------------------------------- +Mon Mar 20 23:02:07 CET 2006 - ma@suse.de + +- fixed memory leak in XMLNodeIterator (#157474) +- disabled storing filelist (YUMFileListParser) and changelog (YUMOtherParser) +- Renamed private MediaManager::forceMediaRelease + function to forceReleaseShared (more exact name) +- Implemented forceRelaseAllMedia() that can be + used to release also foreign (user) mounts. +- Added use of forceRelaseAllMedia for CD/DVDs + if FORCE_RELEASE_FOREIGN is 1 (default 0) +- little cleanup of the checkAttached function +- r2578 + +------------------------------------------------------------------- +Mon Mar 20 17:04:28 CET 2006 - mvidner@suse.cz + +- don't try to attach without exception handling (#158620) +- fix descriptions, as a new tag Des for selections exists now. +- fix #157683: failure after adding add-on product to install + sources +- added more files for translation +- resolve-dependencies.cc: establish pool +- parse-metadata.cc: catch bad URL +- set zmdid for atoms +- r2574 + +------------------------------------------------------------------- +Sun Mar 19 19:24:44 CET 2006 - kkaempf@suse.de + +- fix testsuite. +- provide edition and architecture for all kinds of yum + resolvables. +- fix ResStatus output. +- establish atoms correctly. +- treat requires to unneeded resolvables as fulfilled. +- rev 2559 + +------------------------------------------------------------------- +Sun Mar 19 00:05:17 CET 2006 - kkaempf@suse.de + +- fix the build +- only consider best architecture/version (#157594) +- prefer providers which supplement/enhance installed or + to-be-installed packages (fixes the tpctl-kmp issue) +- rev 2546 + +------------------------------------------------------------------- +Sat Mar 18 02:22:22 CET 2006 - kkaempf@suse.de + +- provide more filters for pkg-bindings (#158602) +- add SystemResObject to provide system (modalias, hal, ...) + capabilities. +- handle this during resolving. +- make the modalias and hal capability match the SystemResObject + by default, thereyby triggering a modalias (resp. hal) + evaluation. +- xmlstore: decouple target store from YUM schema. +- clean up moving of hal() and modalias() from provides to + supplements in ResolvableImpl. +- add PatchContents() for UI. +- handle Edition::noedition as empty string. +- r2537 + +------------------------------------------------------------------- +Tue Mar 14 23:32:44 CET 2006 - jsrain@suse.de + +- releasing all medias when asking for CD (#156981) +- r2471 + +------------------------------------------------------------------- +Tue Mar 14 19:38:43 CET 2006 - mvidner@suse.cz + +- ResStatus::resetTransact must return a value. +- Fixed random build failures in LanguageCode.cc. + (Rewrote the CodeMaps constructor so that gcc does not + optimize a 500-statement basic block.) +- Fix constructions of patch objects. Actually insert atoms in atoms + list. Insert atoms for package even if the package does not exists + in the source. Fixes #157628 (dmacvicar). +- Fixed license reading from susetags, #151834 (dmacvicar). +- r2468 + +------------------------------------------------------------------- +Tue Mar 14 16:59:42 CET 2006 - mvidner@suse.cz + +- added ResStatus::resetTransact (ma) +- bugfix for #156439 (schubi) +- Added Source_Ref::setAlias (#154913). +- Do not assume there is a product file when scanning for products + (visnov) +- function to disable all sources in the persistent store (visnov) +- dependency errors go to stdout, not stderr; output resolver info + directly to stderr (kkaempf) +- rev 2464 + +------------------------------------------------------------------- +Tue Mar 14 01:34:38 CET 2006 - kkaempf@suse.de + +- fix merging of resolver info (needed for #157684). +- errors are also important in ResolverInfo. +- improve debug output in ResolverContext. +- rev 2455 + +------------------------------------------------------------------- +Mon Mar 13 22:54:01 CET 2006 - jsrain@suse.de + +- delete RPMs downloaded via HTTP/FTP after installnig them + (#157011) +- fixed product registration (reverted autorefresh patch) (#157566) + +------------------------------------------------------------------- +Mon Mar 13 11:53:52 CET 2006 - kkaempf@suse.de + +- if root!="/", always prefer the upgrade candidate (#155472) +- implement license confirmed api for UI. +- prefer architecture over version in distribution upgrade + (#157501) +- clean up media handling. +- rev 2448 + +------------------------------------------------------------------- +Sun Mar 12 22:31:09 CET 2006 - kkaempf@suse.de + +- init Modalias properly. +- fix warnings in testcases. +- rev 2432 + +------------------------------------------------------------------- +Sat Mar 11 21:25:18 CET 2006 - kkaempf@suse.de + +- drop libjpeg-devel and sqlite-devel from build requires. + +------------------------------------------------------------------- +Sat Mar 11 08:16:53 CET 2006 - kkaempf@suse.de + +- implement 'modalias()' capability (#157406) +- make dependencies consistent, its 'freshens'. +- cope with user umounts of devices. +- add debug to SourceManager. +- rev 2418 + +------------------------------------------------------------------- +Fri Mar 10 16:20:41 CET 2006 - kkaempf@suse.de + +- allow version downgrade during distribution upgrade if the + newer package is coming from a trusted vendor (#155472) +- implement locale fallback +- 'freshen' -> 'freshens' in schema definitions to make it + consistent with all other dependency definitions. +- better error reporting for .pat and .sel files. +- rule out packages from dependency resolutions which are + de-selected by user (#155368) +- use locale fallbacks in package translations. +- refresh source when re-enabling it. +- rev 2406 + +------------------------------------------------------------------- +Tue Mar 7 21:18:19 CET 2006 - kkaempf@suse.de + +- split of libzypp-zmd-backend subpackage as a stand-alone + leaf package. +- encapsulate bool test for Source_Ref better. +- fixed stack overflow (ma). +- make testsuite build again. +- rev 2346 + +------------------------------------------------------------------- +Tue Mar 7 16:17:07 CET 2006 - kkaempf@suse.de + +- fixed URL rewriting for CD2 and following (#154762) +- fixed ResPoolProxy diffState (for proper ok/cancel support + in UI) +- added special exception class for aborting installation + (#154936) +- only auto-change directories if they end in CDn or DVDn. +- rev 2320. + +------------------------------------------------------------------- +Tue Mar 7 15:37:51 CET 2006 - kkaempf@suse.de + +- silently ignore multiple installs of the same package. +- fix disk usage for installs and uninstalls. +- rev 2308 + +------------------------------------------------------------------- +Mon Mar 6 22:22:57 CET 2006 - kkaempf@suse.de + +- zmd-backend: filter out incompatible architectures from + repository. +- rev 2298 + +------------------------------------------------------------------- +Mon Mar 6 21:35:24 CET 2006 - kkaempf@suse.de + +- sync libzypp media data with mtab. +- improve resolver error and solution reports. +- fix source cache reading (#155459). +- default cached sources to enabled (#155459). +- let each source provide public keys. +- rev 2297 + +------------------------------------------------------------------- +Sun Mar 5 15:48:29 CET 2006 - kkaempf@suse.de + +- only write by-sovler transactions back (#154976) +- rev 2278 + +------------------------------------------------------------------- +Sat Mar 4 12:36:40 CET 2006 - kkaempf@suse.de + +- release last used source at end of commit (#155002) +- rev 2277 + +------------------------------------------------------------------- +Fri Mar 3 23:14:50 CET 2006 - kkaempf@suse.de + +- cope with NULL values in zmd catalogs table (#153584) +- set YAST_IS_RUNNING in transact zmd helper (#154820) +- run SuSEconfig after transact zmd helper (#154820) +- add softTransact to honor user vs. soft requirements (#154650) +- honor all build keys provided by a package source. +- add source metadata refresh. +- add progress callbacks to zmd helpers. +- rev 2276 + +------------------------------------------------------------------- +Thu Mar 2 21:59:07 CET 2006 - kkaempf@suse.de + +- include .diffs into main source. +- catch exception when ejecting media which was unmounted externally + (#154697). +- init source in zmd-backend correctly (#154667) +- implement disk usage info for YaST. +- clean up XML schema files. +- catch CPUs identifying as 'i686' but being 'i586'. +- allow definition of preferred attach (mount) point for media. +- make resolver results more readable. +- use language fallbacks if none of multiple language providers + matches. +- get rid of ignoring wrong arch in resolver, having the wrong + architecture is prevented by other means. +- prepare for translations in exceptions. +- fix 'abort does not abort' +- implement 'flag' I/O in target cache backend. +- skip incompatibles architectures in packages. +- rev 2228 + +------------------------------------------------------------------- +Thu Mar 2 13:44:34 CET 2006 - kkaempf@suse.de + +- dont even provide src/nosrc from the source. +- rev 2169 + diffs + +------------------------------------------------------------------- +Wed Mar 1 17:23:23 CET 2006 - kkaempf@suse.de + +- Initialize commit result (#154409) +- release media if its wrong (#154326) +- dont copy src/nosrc packages to the pool (#154627) +- reduce XML logging. +- rev 2169 + diffs + +------------------------------------------------------------------- +Tue Feb 28 16:10:14 CET 2006 - kkaempf@suse.de + +- fix path of .po files (#154074). +- parse the correct package. file (kinda #154074). +- complain about bad "=Sel:" or "=Pat:" lines (#153065). +- reattach all released medias. +- raise exception instead of abort() on XML errors (#154104). +- update translations. +- PathInfo: implemented a copy_dir_content (variant of copy_dir) + and is_empty_dir utility function +- rev 2169 + +------------------------------------------------------------------- +Tue Feb 28 14:51:46 CET 2006 - kkaempf@suse.de + +- check freshens and supplements for packages (#154074). +- only complain about incomplete installed resolvables, + if they are uninstalled, schedule them for installation. + (#154074) +- add testcases for locale() provides. +- add lang_country -> lang fallback. +- have locale(parent:...) deps match any provides of 'parent' + also when uninstalling a package. +- rev 2148 + +------------------------------------------------------------------- +Tue Feb 28 10:35:15 CET 2006 - kkaempf@suse.de + +- change the locale(...) separator to ";" (#153791) +- complete "find-files" of zmd-backend. +- rev 2140 + +------------------------------------------------------------------- +Tue Feb 28 10:28:06 CET 2006 - visnov@suse.de + +- avoid attaching media when initializing source +- rev 2139 + +------------------------------------------------------------------- +Mon Feb 27 21:26:00 CET 2006 - kkaempf@suse.de + +- warn about misspelled 'locale(...)' provides +- add testcases +- rev 2134 + +------------------------------------------------------------------- +Mon Feb 27 20:19:40 CET 2006 - kkaempf@suse.de + +- fix the build +- rev 2129 + +------------------------------------------------------------------- +Mon Feb 27 18:15:16 CET 2006 - kkaempf@suse.de + +- provide available locales to application (#153583) +- honor 'requestedLocales' (language dependant packages) +- honor release requests for all holders of a device. +- silently re-attach after a forced release. +- solver improvements. +- handle source caches. +- proper logging in zmd backend helpers. +- rev 2127 + +------------------------------------------------------------------- +Mon Feb 27 13:44:39 CET 2006 - kkaempf@suse.de + +- upgrade always to best version and arch (#153577) +- reset 'transact' state for obsoleted packages (#153578) +- translation updates +- rev 2113 + +------------------------------------------------------------------- +Mon Feb 27 10:42:33 CET 2006 - kkaempf@suse.de + +- add support for 'local' .rpm packages to zmd-backend. +- rev 2101 + +------------------------------------------------------------------- +Sun Feb 26 20:24:10 CET 2006 - kkaempf@suse.de + +- fix build of zmd/backend. +- actually fill 'files' table in package-files. +- rev 2094 + +------------------------------------------------------------------- +Sun Feb 26 17:43:06 CET 2006 - kkaempf@suse.de + +- improve testcases. +- add 'setPossibleLocales()' to ZYpp, this defines the set + of possible locales to choose from (#153583) +- provide LanguageImpl and create 'Language' resolvables for + each 'possible' locale. +- fix YUM parsing of patches, insert 'atoms' to link patches + with packages. +- replace gzstream/ with own, existing implementation. +- honor locks in solver (#150231) +- sync pool with target after commit() properly (#150565, #153066) +- new zmd helper 'package-files' +- rev 2093 + +------------------------------------------------------------------- +Thu Feb 23 21:45:06 CET 2006 - kkaempf@suse.de + +- prevent multiple initializations of the target (#153124) +- implement 'loopback mounted ISO images' +- retain old package sources on upgrade. +- support compressed .xml files in 'repodata' type repositories. +- rev 2025 + +------------------------------------------------------------------- +Thu Feb 23 15:16:58 CET 2006 - kkaempf@suse.de + +- parse locale(...) provides and construct correct dependencies. + +------------------------------------------------------------------- +Thu Feb 23 14:16:44 CET 2006 - kkaempf@suse.de + +- always upgrade to candidate (#152760). +- fix typo in package sorting. +- prepare handling of locale provides. +- rev 1995 + +------------------------------------------------------------------- +Thu Feb 23 10:53:51 CET 2006 - kkaempf@suse.de + +- sort src/nosrc package to right list during commit. +- revert installtime/buildtime in susetags parser (#152760) +- rev 1990 + +------------------------------------------------------------------- +Thu Feb 23 10:22:08 CET 2006 - kkaempf@suse.de + +- reset state after successful commit (#153030) +- run "rpm -e" always with "--nodeps" (#153026) +- provide separate resolvable kind for src packages. +- extend status field for LOCK and LICENSE. +- add sameState()/diffState() for UI. +- provide 'best' candidate for UI. +- set 60 sec timeout for curl access. +- don't cross-compare solver results, takes too much time. +- provide sizes of installed packages. +- extend REQUIRES semantics in content file. +- add "parse-metadata" helper to zmd-backend. +- rev 1987 + +------------------------------------------------------------------- +Wed Feb 22 14:51:46 CET 2006 - kkaempf@suse.de + +- provide complete disk usage data (#152761) +- include upgrade flag when copying solver solution + back to pool (#152717) +- rev 1959 + +------------------------------------------------------------------- +Wed Feb 22 13:16:48 CET 2006 - kkaempf@suse.de + +- don't insert incompatible architectures to the pool (#151933) +- don't accept incompatible architectures from a repository + (#151933) +- separate rpm log (#151431). +- allow extended product requires. +- rev 1954 + +------------------------------------------------------------------- +Tue Feb 21 22:02:59 CET 2006 - kkaempf@suse.de + +- provide the XML schema files in the main package. (#152593) + +------------------------------------------------------------------- +Tue Feb 21 20:05:34 CET 2006 - kkaempf@suse.de + +- provide arch compat handling. +- implement data upload to zmd. +- fix source metadata caching on target. +- add 'supplements' dependencies to 'yum' parser. +- provide user agent identification to curl calls. +- move resolver branches (multiple alternatives) back in queue + (resolve known things first, then the unknown ones). +- clean up 'packages' parser. +- rev 1947 + +------------------------------------------------------------------- +Tue Feb 21 09:18:53 CET 2006 - kkaempf@suse.de + +- improve media mount/umount interface +- prepare class ArchCompat for proper architecture ordering + and compatibility handling. +- add returns to dummy functions in DbAccess. +- rev 1913 + +------------------------------------------------------------------- +Mon Feb 20 21:08:22 CET 2006 - kkaempf@suse.de + +- don't explictly delete to-be-upgraded packages. +- finish query-system, resolve-dependencies, and transact for + libzypp-zmd-backend. +- provide Pattern::category. +- move system architecture to toplevel. +- make target store pathname settable. +- speed up rpmdb reading by properly filtering unwanted file + provides. +- rev 1905 + +------------------------------------------------------------------- +Sun Feb 19 20:35:03 CET 2006 - kkaempf@suse.de + +- new translations. +- proofread texts. +- when comparing solutions, prefer higher versions. +- provide generic 'SafeBool' for bool conversions. +- add PtrTypes testsuites. +- rev 1876 + +------------------------------------------------------------------- +Fri Feb 17 21:43:51 CET 2006 - kkaempf@suse.de + +- integrate all diffs +- move Target::commit to toplevel API +- generalize dependency iterators and hash dependency + information in pool (for speedup) +- add 'supplements' as dependency +- make more pattern attributes available +- drop "smbfs" in favour of "cifs" (#151476) +- add metadata cache to sources (Beta4 bug) +- run "rpm -e" with name-version-release +- fix update conflicts +- rev 1864 + +------------------------------------------------------------------- +Thu Feb 16 20:02:19 CET 2006 - kkaempf@suse.de + +- fix-mediachange.diff: dont skip CD but retry after media change +- cd-eject-button.diff: fix CD url so YaST recognizes it and shows + 'eject' button +- release-forced-eject-no-ptrfix.diff: fix refcounting in ptrs + so media handle gets actually released and media unmounted. + +------------------------------------------------------------------- +Thu Feb 16 14:40:31 CET 2006 - kkaempf@suse.de + +- implement arch scoring +- prefer better arch (#151427) +- transitive depedencies of weak requirements are non-weak + (#151446) +- rev 1778 + diff + +------------------------------------------------------------------- +Wed Feb 15 18:19:12 CET 2006 - kkaempf@suse.de + +- ignore self and to-be-updated conflicts (#150844) +- fix enable of target store (for non-packages) +- rev 1778 + +------------------------------------------------------------------- +Wed Feb 15 13:11:28 CET 2006 - kkaempf@suse.de + +- fix "cd:" url (#151121) +- provide location() in public Package api +- allow running distribution upgrade in testmode +- extend HAL interface +- rev 1762 + +------------------------------------------------------------------- +Wed Feb 15 10:10:48 CET 2006 - kkaempf@suse.de + +- pass normal and locale packages from selections correctly. +- its "baseconf" for base selections. +- Make 'ZYpp' an obvious singleton. +- provide releasenotesUrl. +- dont continue upgrade without target. +- implement 'fake' hal for testing. +- fix package sizes. +- more solver testcases. +- rev 1754 + +------------------------------------------------------------------- +Tue Feb 14 20:52:02 CET 2006 - kkaempf@suse.de + +- extend requires of libzypp-devel +- provide package sizes for UI +- provide more UI helpers +- implement Product and related functions +- fix split provides in distribution upgrade +- provide locale information to system +- ask HAL for available devices +- reduce debug information in solver +- filter architectures in source, not in solver +- rev 1743 + +------------------------------------------------------------------- +Tue Feb 14 07:27:39 CET 2006 - visnov@suse.de + +- disable another testsuite for now +- fetch the default locale from environment +- support user-defined formatting of log +- rev 1710 + +------------------------------------------------------------------- +Mon Feb 13 20:41:36 CET 2006 - visnov@suse.de + +- providing basic product information from susetags source +- public API for preferred language +- implemented redirect of logging (#149001) +- report start/finish of source data parsing (#150211) +- store/restore source aliases properly (#150256) +- disable a lot of debug logging to speed up solver +- properly rewrite URL for CDn directory layouts (#149870) +- rev 1706 + +------------------------------------------------------------------- +Sun Feb 12 16:59:48 CET 2006 - kkaempf@suse.de + +- add save/restore state to facilitate UI 'cancel' +- enable target/store +- add 'forceResolve' call and flag to resolver to switch between + task-oriented ZMD and interactive YaST behaviour. +- Fix resolver problem solution texts. +- improve solver problem solution offerings. +- fix media access handling to better support multiple + requestors to single media. +- move the media number checking to the source (media requestor) + which knows how to verify the correct media. +- Fix CD ordering (#149871), adding testcases. +- Move 'PoolItemList' and 'PoolItemSet' typedefs inside classes. +- Add selections to testcases. +- rev 1673 + +------------------------------------------------------------------- +Sat Feb 11 10:17:15 CET 2006 - kukuk@suse.de + +- Fix missing return in Source.cc:124 + +------------------------------------------------------------------- +Fri Feb 10 18:41:29 CET 2006 - kkaempf@suse.de + +- cope with empty arch field in selections +- enable dummy "enableStorage" function +- rev 1610-branch + +------------------------------------------------------------------- +Fri Feb 10 15:36:43 CET 2006 - kkaempf@suse.de + +- fix random data return in Source.cc +- rev 1610 + +------------------------------------------------------------------- +Fri Feb 10 15:00:45 CET 2006 - kkaempf@suse.de + +- adapt zmd-backend to SourceImpl API change +- rev 1608 + +------------------------------------------------------------------- +Fri Feb 10 13:54:43 CET 2006 - kkaempf@suse.de + +- fix the packages parser bug. Now all packages are parsed + including (english) translations. + source/susetags is back to svn head. +- rev 1600 + +------------------------------------------------------------------- +Fri Feb 10 10:30:12 CET 2006 - kkaempf@suse.de + +- fix off-by-one bug in bitfield handling +- revert source/susetags to rev 1411 +- rev 1586 + +------------------------------------------------------------------- +Thu Feb 9 22:21:43 CET 2006 - kkaempf@suse.de + +- dont prereq-sort non-packages +- rev 1584 + +------------------------------------------------------------------- +Thu Feb 9 21:29:00 CET 2006 - kkaempf@suse.de + +- rev 1582 + +------------------------------------------------------------------- +Thu Feb 9 11:10:54 CET 2006 - kkaempf@suse.de + +- update to rev 1543 + +------------------------------------------------------------------- +Thu Feb 9 00:49:23 CET 2006 - ro@suse.de + +- require hal-devel in libzypp-devel +- re-merge fixes (RPM_OPT_FLAGS) + +------------------------------------------------------------------- +Wed Feb 8 23:53:58 CET 2006 - kkaempf@suse.de + +- make solver behaviour a bit more interactive +- rev 1537 + +------------------------------------------------------------------- +Wed Feb 8 18:45:21 CET 2006 - schwab@suse.de + +- Fix syntax error in configure script. +- Use RPM_OPT_FLAGS. + +------------------------------------------------------------------- +Wed Feb 8 17:03:37 CET 2006 - kkaempf@suse.de + +- update for qt ui integration +- rev 1504 + +------------------------------------------------------------------- +Tue Feb 7 23:18:09 CET 2006 - kkaempf@suse.de + +- split off libzypp-zmd-backend +- rev 1466 + +------------------------------------------------------------------- +Tue Feb 7 23:10:59 CET 2006 - kkaempf@suse.de + +- another update to svn + +------------------------------------------------------------------- +Mon Feb 6 20:42:22 CET 2006 - kkaempf@suse.de + +- finish rpm callbacks +- finish UI API +- fix state change resolver<->pool +- zmd backend stuff +- speed up tag file parsing +- rev 1405 + +------------------------------------------------------------------- +Mon Feb 6 16:53:03 CET 2006 - schubi@suse.de + +- disabling failing tests of s390 and ppc + +------------------------------------------------------------------- +Mon Feb 6 11:14:16 CET 2006 - schubi@suse.de + +- Snapshoot rev 1367 + +------------------------------------------------------------------- +Mon Feb 6 01:42:48 CET 2006 - kkaempf@suse.de + +- use hashes for pool +- rev 1343 + +------------------------------------------------------------------- +Fri Feb 3 14:21:47 CET 2006 - schubi@suse.de + +- removed Obsoletes: yast2-packagemanager + +------------------------------------------------------------------- +Fri Feb 3 11:36:19 CET 2006 - schubi@suse.de + +- Snapshoot 3 Feb 2005 (11:30) + +------------------------------------------------------------------- +Thu Feb 2 14:27:02 CET 2006 - schubi@suse.de + +- Snapshoot 2 Feb 2005 (14:00) + +------------------------------------------------------------------- +Thu Feb 2 12:23:03 CET 2006 - schubi@suse.de + +- Snapshoot 2 Feb 2005 ( integrating YaST ) + +------------------------------------------------------------------- +Wed Jan 25 21:37:50 CET 2006 - mls@suse.de + +- converted neededforbuild to BuildRequires + +------------------------------------------------------------------- +Sat Jan 14 08:51:55 CET 2006 - kkaempf@suse.de + +- Initial version + diff --git a/po/CMakeLists.txt b/po/CMakeLists.txt new file mode 100644 index 0000000..bfac1ae --- /dev/null +++ b/po/CMakeLists.txt @@ -0,0 +1,70 @@ +# Translation set name +SET( POT_NAME "zypp" ) + +# Creating the .pot file.... +# POT_FILE_DEPENDS was set in ../src +SET( POT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${POT_NAME}.pot ) + +SET( XGETTEXT_CMD "xgettext" ) +SET( XGETTEXT_OPTIONS -L C++ --boost --no-wrap --add-comments --add-location --foreign-user ) +SET( XGETTEXT_OPTIONS ${XGETTEXT_OPTIONS} --keyword=_ --keyword=_:1,2 --keyword=__ --keyword=N_ --keyword=PL_:1,2 ) +SET( XGETTEXT_OPTIONS ${XGETTEXT_OPTIONS} --copyright-holder=\"SuSE Linux GmbH, Nuernberg\" ) +SET( XGETTEXT_OPTIONS ${XGETTEXT_OPTIONS} --package-name=${POT_NAME} --default-domain=${POT_NAME} ) + +SET( _abs_POT_FILE_DEPENDS ) +SET( POT_FILE_DEPENDS ${POT_FILE_DEPENDS_ZYPP} ${POT_FILE_DEPENDS_ZYPP_CORE} ${POT_FILE_DEPENDS_ZYPP_MEDIA} ${POT_FILE_DEPENDS_ZYPP_CURL} ${POT_FILE_DEPENDS_ZYPP_TUI} ) +FOREACH( _currentDepends ${POT_FILE_DEPENDS} ) + SET( _abs_POT_FILE_DEPENDS ${_abs_POT_FILE_DEPENDS} ${LIBZYPP_SOURCE_DIR}/${_currentDepends} ) +ENDFOREACH() + +ADD_CUSTOM_COMMAND( OUTPUT ${POT_FILE} + COMMAND ${XGETTEXT_CMD} ${XGETTEXT_OPTIONS} --output=${POT_FILE} ${POT_FILE_DEPENDS} + WORKING_DIRECTORY ${LIBZYPP_SOURCE_DIR} + DEPENDS ${_abs_POT_FILE_DEPENDS} + COMMENT "Extract translatable messages to ${POT_FILE}" +) + + +# Creating the .gmo files out of the .po files +FILE( GLOB PO_FILES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.po" ) + +SET( GMO_FILES ) +FOREACH( _currentPoFile ${PO_FILES} ) + GET_FILENAME_COMPONENT( _absFile ${_currentPoFile} ABSOLUTE ) + GET_FILENAME_COMPONENT( _lang ${_absFile} NAME_WE ) + + SET( _poFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.po ) + SET( _gmoFile ${CMAKE_CURRENT_BINARY_DIR}/${_lang}.gmo ) + + ADD_CUSTOM_COMMAND( OUTPUT ${_gmoFile} + COMMAND ${GETTEXT_MSGMERGE_EXECUTABLE} --quiet --no-fuzzy-matching -o ${_poFile} ${_absFile} ${POT_FILE} + COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${_gmoFile} ${_poFile} + DEPENDS ${POT_FILE} ${_absFile} + COMMENT "Update ${_gmoFile}" + ) + + INSTALL( FILES ${_gmoFile} + DESTINATION share/locale/${_lang}/LC_MESSAGES + RENAME ${POT_NAME}.mo + ) + + SET( GMO_FILES ${GMO_FILES} ${_gmoFile} ) +ENDFOREACH() + + +# Provides the 'translations' target that +# creates the .gmo files out of the .po files +SET( SOURCE_POT_FILE ${CMAKE_CURRENT_SOURCE_DIR}/${POT_NAME}.pot ) + +ADD_CUSTOM_TARGET( translations ALL + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/PotfileDiff.sh ${SOURCE_POT_FILE} ${POT_FILE} | grep '^[+-][^+-]' || true + DEPENDS ${GMO_FILES} + COMMENT ".pot file diff..." +) + +ADD_CUSTOM_TARGET( potfile_update + COMMAND ./PotfileDiff.sh ${SOURCE_POT_FILE} ${POT_FILE} -q || ./PotfileUpadte.sh ${CMAKE_CURRENT_BINARY_DIR} + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS translations + COMMENT "Checking for uncommitted changes to the .pot file..." +) diff --git a/po/PotfileDiff.sh b/po/PotfileDiff.sh new file mode 100755 index 0000000..04a249c --- /dev/null +++ b/po/PotfileDiff.sh @@ -0,0 +1,13 @@ +#! /bin/bash +set -e +function extract() { grep '^\(msgid\|"\)' "$1" | grep -v "POT-Creation-Date" | sort -u; } + +OLDTMP=$(mktemp) +NEWTMP=$(mktemp) +trap "/bin/rm -f -- \"$OLDTMP\" \"$NEWTMP\"" 0 1 2 3 13 15 + +extract "$1" >"$OLDTMP" +extract "$2" >"$NEWTMP" + +shift 2 # additional args for diff +diff -u0 "$@" "$OLDTMP" "$NEWTMP" diff --git a/po/PotfileUpadte.sh b/po/PotfileUpadte.sh new file mode 100755 index 0000000..373a91d --- /dev/null +++ b/po/PotfileUpadte.sh @@ -0,0 +1,30 @@ +#! /bin/bash +set -e + +function errexit() { + echo "$0: $@" >&2 + exit 1 +} + +function currentBranch() +{ git rev-parse --abbrev-ref HEAD; } + +test "$(currentBranch)" == "master" || errexit "Not on master branch." +test "$(basename "$PWD")" == "po" || errexit "Cd to the po directory." + +test "$(git status --porcelain 2>/dev/null| grep '^[^ !?]' | wc -l)" == 0 || errexit "Index not clean: wont't commit" + +BINDIR="${1}" +test -z "$BINDIR" && errexit "Missing argument: BINDIR" +test -d "$BINDIR" || errexit "Not a directory: BINDIR '$BINDIR'" +echo "Updating .pot .po files from $BINDIR..." +for F in *.pot *.po; do + if [ -f "$BINDIR/$F" ]; then + cp "$BINDIR/$F" . + else + errexit "Missing file $BINDIR/$F (touch CMakeLists.txt?)" + fi +done + +git add -A *.pot *.po +git commit -m 'Translation: updated .pot file' diff --git a/po/af.po b/po/af.po new file mode 100644 index 0000000..fa1fe43 --- /dev/null +++ b/po/af.po @@ -0,0 +1,5963 @@ +# Copyright (C) 2006 SuSE Linux Products GmbH, Nuernberg +# This file is distributed under the same license as the package. +# +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2006-11-03 12:03\n" +"Last-Translator: Novell Language \n" +"Language-Team: Novell Language \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Onbekende land:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Geen kode nie" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Verenigde Arabiese Emirate" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua en Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanië" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenië" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Nederlands-Antille" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktika" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentinië" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikaanse Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Oostenryk" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australië" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Aland-eilande" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaijan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnië en Herzegowina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "België" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgarye" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrein" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Broenei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivië" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasilië" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhoetan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet-eiland" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belo-Rusland" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Cocos- (Keeling-) eilande" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Republiek van Sentraal-Afrika" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Switserland" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Ivoorkus" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cook-eilande" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kameroen" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Sjina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kaap Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Kersfees-eiland" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Siprus" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tseggiese Republiek" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Duitsland" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djiboeti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Denemarke" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikaanse Republiek" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algerië" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonië" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipte" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Wes-Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanje" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Ethiopië" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falkland-eilande (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federasie van Mikronesië" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faroë-eilande" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Frankryk" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Metropolitaanse Frankryk" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gaboen" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Verenigde Koninkryk" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgië" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Frans-Guyana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Duitsland" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambië" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinee" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekwatoriaal-Guinee" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Griekeland" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Suid-Georgia en die Suid-Sandwich-eilande" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinee-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard-eiland en McDonald-eilande" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroasië" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haïti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hongarye" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesië" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ierland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indië" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Brits-Indiese Oseaangebied" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Ysland" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italië" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaika" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordanië" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgisië" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodja" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comore" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "St. Kitts en Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Noord-Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Suid-Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Koeweit" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kaaimanseilande" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Lao Demokratiese Republiek" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Lebanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "St. Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberië" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litoue" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letland" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libië" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldowa" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "Mongo" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "San Marino" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshall-eilande" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Masedonië" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mianmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolië" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Noord-Mariana-eilande" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritanië" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maledive" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Maleisië" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mosambiek" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibië" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nieu-Kaledonië" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk-eilande" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigerië" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nederland" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noorweë" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauroe" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nieu-Seeland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Frans-Polinesië" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papoea-Nieu-Guinee" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Philippyne" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Pole" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "St. Pierre en Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestynse Gebied" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palaoe" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Roemenië" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "Serwies" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russiese Federasie" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi-Arabië" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomon-eilande" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelle" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Soedan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Swede" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapoer" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "St. Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slowenië" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard en Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slowakye" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalië" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tomé en Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Sirië" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- en Caicos-eiland" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tsjad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Franse Suidelike Gebiede" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tajikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Toerkmenië" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisië" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Oos-Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkye" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad en Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Toewaloe" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzanië" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Oekraïne" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Verenigde State van Kleiner Buite-eilande" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Verenigde State" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Oesbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikaanstad" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "St. Vincent en die Grenadine" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britse Maagde-eilande" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Maagde-eilande, .V.S.A." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Viëtnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis en Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Suid-Afrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambië" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s uitgediendes:%s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Misluk om die SM te begin." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Misluk om die SM te begin." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Inskywing nie gevind nie." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Onbekende taal:" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhazies" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinees" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asiaties (ander)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadies" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanies" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonquianse tale" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Suid-Altaïs" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharies" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Engels, Oud (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apache-tale" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabies" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramees" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonees" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armeens" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araukanies" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Kunsmatig (ander)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamees" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Astoeries" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapaskanse tale" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australiese tale" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avaries" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avesties" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aimara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaijaans" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Bandies" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke-tale" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambaries" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinees" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskies" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Balties (ander)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Belo-Russies" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berbers (ander)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (ander)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnies" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretons" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesië)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Boeginees" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgaars" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmees" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Kaddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Sentraal-Amerikaanse Indiaans (ander)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalaans" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukasies (ander)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Kelties (ander)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tjetjeens" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Sjinees" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukees" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook-jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewiaans" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Kerk-Slawies" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Chamiese tale" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Kopties" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Kornies" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsikaans" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreole en pidgintale, Engels-gebaseer (ander)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreole en pidgintale, Frans-gebaseer (ander)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreole en pidgintale, Portugees-gebaseer (ander)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krimse Tataars" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreole en pidgintale (ander)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kashubies" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Kushities (ander)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tsjeggies" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Deens" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Daiak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slawetaal (Athapaskies)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Drawidies (ander)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Laer Sorbies" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Nederlands, Middel- (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nederlands" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egipties (Antieke)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamities" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engels" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Engels, Middel- (ca.1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonies" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faroëes" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijiaans" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Fins" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fins-Oegries (ander)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Frans" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Frans, Middel- (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Frans, Oud- (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Fries" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulies" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gaïo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germaans (ander)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgies" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Duits" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertees" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gallies" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Iers" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galisies" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Duits, Middelhoog- (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Duits, Oudhoog- (ca.1050-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Goties" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grieks, Antieke (tot 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grieks, Moderne (tot 1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haïda" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haïties" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaïes" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebreeus" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligainon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittities" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Oppersorbies" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Hongaars" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Yslands" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Intertale" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Internasionale Hulptaalvereniging)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indies (ander)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesies" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-Europees (ander)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraans (ander)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Iroquoi-tale" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiaans" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javaans" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japannees" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeo-Persies" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeo-Arabies" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannadees" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazaks" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardies" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (ander)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanees" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikoejoe" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kiniarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreaans" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraeaans" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuaniama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Koerdies" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latyn" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letties" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghiaans" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgs" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litaus" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgies" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenia en Tanzanië)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Masedonies" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurees" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallees" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesies (ander)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Maleis" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mendies" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Iers, Middel- (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Verskillende tale" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (ander)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagassies" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltees" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Mantsjoe" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo-tale" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldawies" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongools" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Veelvoudige tale" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda-tale" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandees" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Maya-tale" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Noord-Amerikaanse Indiaans" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitaans" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, Suid-" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, Noord-" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Platduits" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanies (ander)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueaans" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Noors Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Noors Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Noors, Oud-" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Noors" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Noord-Sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubiese tale" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Klassieke Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitaans (na 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetiaans" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turks, Ottomaans (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomiese tale" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuaans (ander)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauaans" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persies, Oud- (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persies" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Philippyns (ander)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenisies" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Pools" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeiaans" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugees" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakrit-tale" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provensaals, Oud- (tot 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongaans" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romaans (ander)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Raeto-Romaans" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Sigeunertaal" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Roemeens" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russies" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Jakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Suid-Amerikaanse Indiaans (ander)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salishan-tale" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritaanse Aramees" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serwies" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliaans" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Skots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroasies" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semities (ander)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Iers, Oud- (tot 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Gebaretale" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouaanse tale" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetaans (ander)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slawies (ander)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slowaaks" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Sloweens" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Suid-Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Noord-Sami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Sami-tale (ander)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoaans" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdiaans" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalies" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, Suid-" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spaans" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinies" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Sahara (ander)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Soedanees" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumeries" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Sweeds" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siries" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahities" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (ander)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tartaars" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetaans" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinies" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Njassa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tonga-eilande)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmen" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Toemboeka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi-tale" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turks" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaïes (ander)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvinies" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Oedmoert" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Oegarities" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Oeighoer" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Oekraïnies" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Oembundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Onbepaal" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Oerdoe" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Oesbeks" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Viëtnamees" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Voties" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakashan-tale" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Warai" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Wallies" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbiese tale" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walloons" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmies" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Japees" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Joruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Jupik-tale" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotek" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1' bestaan nie." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1' bestaan nie." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "onbekend" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "Die skyf bestaan nie." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Onbekende opdrag" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ongeldige Url-skema '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "Kan gids %1 nie skep nie: %2." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Kan werkskermitem '%s' nie open nie" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Ongeldige uitvoerlêernaam." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Kan lêer nie vir skryf open nie." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Fout met lees vanaf slapskyf." + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Terugstel van hulpbronne" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Kan werkskermitem '%s' nie open nie" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "Die SM se naam kan nie met ’n syfer begin nie." + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr "Die SM se naam kan nie met ’n syfer begin nie." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +# continue button label +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Voortgaan?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "Pakket %s se integriteitsnagaan misluk. Wil u dit weer probeer aflaai?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Pakket %s se integriteitsnagaan misluk. Wil u dit weer probeer aflaai?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm-nagaan het misluk." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm het misluk." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "hulpbronsoort VAR1 ondersteun nie toon wysigings-eienskap nie" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Kan %s vanaf %s nie voorsien nie" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "Lêer %1 nie in die bewaarplek gevind nie." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "Kan die lêer nie skep nie." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "Ignoreer dié vereiste net hier" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "Ignoreer dié vereiste net hier" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "Verbindingsversoek aan:" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "Kan %s nie installeer nie vanweë afhanklikheidsprobleme" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "Geen voorsiening %s nie" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "Daar is geen installeerbare verskaffers van %s nie" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "Daar is geen installeerbare verskaffers van %s nie" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "Die navraag bestaan reeds." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Installasie is gestaak soos gelas." + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "Voer uit" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "Fout tydens sleutelenkriptering." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "het misluk" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Gewysigde konfigurasielêers vir %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm geberg %s as %s, maar dit was onmoontlik om die verskil te bepaal" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm geberg %s as %s.\n" +"Hier is die eerste 25 rëels van verskil:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm geskep %s as %s, maar dit was onmoontlik om die verskil te bepaal" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm geskep %s as %s.\n" +"Hier is die eerste 25 rëels van verskil:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "Bykomende rpm-uitset:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "geskepte rugsteun %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Inskywing nie gevind nie." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Inskywing nie gevind nie." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Inskywing nie gevind nie." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Kan lêer '%1' nie open nie." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Ongeldige LDAP URL-navraagstring" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Ongeldige LDAP URL-navraagparameter '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Kan Url-voorwerp nie kloon nie" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Ongeldige leë Url-voorwerpverwysing" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Kan Url-komponente nie ontleed nie" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url-skema laat nie ’n %s toe nie" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Ongeldige %s komponent '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Ongeldige %s komponent" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Navraagstring-ontleding nie vir hierdie URL ondersteun nie" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url-skema is ’n vereiste komponent" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Ongeldige Url-skema '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url-skema laat nie ’n gebruikernaam toe nie" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url-skema laat nie ’n wagwoord toe nie" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url-skema vereis ’n gasheerkomponent" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url-skema laat nie ’n gasheerkomponent toe nie" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Ongeldige gasheerkomponent '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url-skema laat nie ’n poort toe nie" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Ongeldige poortkomponent '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url-skema vereis padnaam" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relatiewe pad nie toegelaat indien magtiging bestaan nie" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Enkoderingstring bevat ’n NUL-greep" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Ongeldige parametermatryssplyt-skeierkarakter" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Ongeldige parameterbindingsplyt-skeierkarakter" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Ongeldige parametermatrysaansluit-skeierkarakter" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Opdrag uitgevoer wanneer verbind word" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Kan %s nie vind nie." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Kan %s nie vind nie." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Kan %s - %s nie open nie\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Misluk om module \"%s\" te laai." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Lêer %1 nie in die bewaarplek gevind nie." + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Kan nie na lêer %1 toe skryf nie." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 is nie ’n gids nie." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "Leë CA-naam." + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Ongeldige URL-skema '%1'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Kan werkskermitem '%s' nie open nie" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Toelatings geweier" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ja" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nee" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Waarskuwing" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Fout" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "gedoen" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "fout" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Waarskuwing" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Begin met ..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Nie gevind nie" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ja" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nee" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s voorsien %s, maar dit het ’n ander argitektuur." + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "opdrag om pakkette te oninstalleer" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "Geen voorsiening %s nie" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Die skyf bestaan nie." + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s is gesluit en kan nie ongeïnstalleer word nie." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "nie geïnstalleer nie" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s word benodig deur %s" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Kan %s nie installeer nie" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s verkeer in konflik met %s" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s uitgediendes %s" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s uitgediendes %s" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s verkeer in konflik met %s" + +#~ msgid "do not install %s" +#~ msgstr "moenie %s installeer nie" + +#~ msgid "keep %s" +#~ msgstr "hou %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "moenie %s installeer nie" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "Daar is geen installeerbare verskaffers van %s nie" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "Moenie waar oplossings ter sprake is, installeer of skrap nie" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s voorsien %s, maar dit het ’n ander argitektuur." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "Installeer %s, hoewel dit die argitektuur kan verander" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s uitgediendes %s" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "%s afgelaai vanaf %s" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Installasie" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Kan lêer '%1' nie open nie." + +#~ msgid "Hal Exception" +#~ msgstr "Hal-uitsondering" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext nie verbind nie" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive nie geïnisialiseer nie" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume nie geïnisialiseer nie" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Kan dbus-verbinding nie skep nie" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Kan libhal-konteks nie skep nie" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Kan dbus-verbinding nie stel nie" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Kan HAL-konteks nie inisialiseer nie -- hald loop nie?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Nie ’n CDROM-aandrywer nie" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Kan mutex-eienskappe nie inisialiseer nie" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Kan terugkerende mutex-eienskappe nie stel nie" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Kan terugkerende mutex nie inisialiseer nie" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Kan die mutex-slot nie verkry nie" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Kan die mutex-slot nie ontsluit nie" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Kan die openbare sleutel nie kry nie." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "nie geïnstalleer nie" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Kan %s - %s nie open nie\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serwië en Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Onbekende lys-opsie" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "kon afhanklikhede nie oplos nie" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Lêer %s het nie ’n nagaansom nie. \n" +#~ "Gebruik die lêer in elk geval?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Lêer %s het nie integriteitsnagaan geslaag met die volgende sleutel nie:\n" +#~ "%s|%s|%s\n" +#~ " Gebruik die lêer in elk geval?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Lêer %s het ’n ongeldige nagaansom. \n" +#~ "Verwag %s, kry %s\n" +#~ " Gebruik die lêer in elk geval?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Lêer %s het ’n onbekende nagaansom %s. \n" +#~ "Gebruik die lêer in elk geval?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Lêer %s is nie geteken nie.\n" +#~ "Gebruik dit in elk geval?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Lêer %s word geteken met ’n onbekende sleutel:\n" +#~ "%s|%s|%s\n" +#~ " Gebruik die lêer in elk geval?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Onbetroubare sleutel gevind:\n" +#~ "%s|%s|%s\n" +#~ " Vertrou sleutel?" + +#~ msgid "%s remove failed" +#~ msgstr "%s verwyder het misluk" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "Wysig u wagwoord" + +#~ msgid "rpm output:" +#~ msgstr "rpm-uitset:" + +#~ msgid "%s install failed" +#~ msgstr "%s installasie misluk" + +#~ msgid "%s installed ok" +#~ msgstr "%s geïnstalleer is goed" + +#~ msgid "%s remove ok" +#~ msgstr "%s verwyder is goed" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "" +#~ "%s voorsien hierdie afhanklikheid, maar sal die argitektuur van die " +#~ "geïnstalleerde item wysig" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "" +#~ "%s voorsien hierdie afhanklikheid, maar sal die argitektuur van die " +#~ "geïnstalleerde item wysig" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Moenie waar oplossings ter sprake is, installeer of skrap nie" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Ignoreer dat %s reeds gestel is om te installeer" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "Ignoreer die uitgediende %s in %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "Ignoreer hierdie konflik van %s" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "Ignoreer dié vereiste net hier" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "Installeer %s, hoewel dit die argitektuur kan verander" + +#~ msgid "Install missing resolvables" +#~ msgstr "Installeer ontbrekende oplossings" + +#~ msgid "Keep resolvables" +#~ msgstr "Hou oplossings" + +#~ msgid "Unlock these resolvables" +#~ msgstr "Ontsluit hierdie oplossings" + +#~ msgid "delete %s" +#~ msgstr "skrap %s?" + +#~ msgid "install %s" +#~ msgstr "installeer %s" + +#~ msgid "unlock %s" +#~ msgstr "ontsluit %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "ontsluit alle oplossings" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Kan lêer '%1' nie open nie." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "Fout tydens lees van sektor %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "Padparameter-ontleding nie vir hierdie URL ondersteun nie" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "Padparameter-ontleding nie vir hierdie URL ondersteun nie" + +#~ msgid "Software management is already running." +#~ msgstr "Sagtewarebestuur loop reeds." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s word vervang deur %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s vervang deur %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "Hierdie oplossings sal uit die stelsel geskrap word." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s sal nie ongeïnstalleer word nie, want dit word steeds vereis" + +#~ msgid "Invalid information" +#~ msgstr "Ongeldige inligting" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s word deur ander oplossings benodig" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s word benodig deur:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s verkeer in konflik met ander oplossings" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s verkeer in konflik met:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s maak ander oplossings uitgedien" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "Hierdie oplossings sal uit die stelsel geskrap word." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s hang van ander oplossings af" + +#~ msgid "%s depends on %s" +#~ msgstr "%s hang af van %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s hang af van:%s" + +#~ msgid "Child of" +#~ msgstr "Kind van" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "Daar is geen hulpbron wat hierdie vereiste ondersteun, beskikbaar nie." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "Toekomstige probleme wat bo/onder hierdie resolusie beskryf word, sal nie " +#~ "alle afhanklikhede oplos nie" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "Kan %s nie installeer nie, omdat dit in konflik verkeer met %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s word nie geïnstalleer nie en is as oninstalleerbaar gemerk" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s het vereistes waaraan nie voldoen is nie" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s het afhanklikhede wat ontbreek" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s kan nie geïnstalleer word nie vanweë ontbrekende afhanklikhede" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s vervul afhanklikhede van %s, maar sal ongeïnstalleer word" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s vervul afhanklikhede van %s, maar sal op u stelsel gehou word" + +#~ msgid "No need to install %s" +#~ msgstr "Geen nodigheid om %s te installeer nie" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "Kan %s nie installeer om die afhanklikhede van %s te vervul nie" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "Kan %s nie installeer om die afhanklikhede van %s te vervul nie" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s sal nie ongeïnstalleer word nie, want dit word steeds vereis" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "" +#~ "%s uitgediendes %s. Maar %s kan nie geskrap word nie, want dit is gesluit." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "Kan %s nie installeer nie, want dit verkeer in konflik" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s is oninstalleerbaar vanweë konflikte met %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "om %s vir %s te vereis tydens bywerk van %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s het nie die vereiste %s" + +#~ msgid ", Action: " +#~ msgstr ", Aksie:" + +#~ msgid ", Trigger: " +#~ msgstr ", Sneller:" + +#~ msgid "package" +#~ msgstr "pakket" + +#~ msgid "selection" +#~ msgstr "keuse" + +#~ msgid "pattern" +#~ msgstr "patroon" + +#~ msgid "product" +#~ msgstr "produk" + +#~ msgid "patch" +#~ msgstr "regstelling" + +#~ msgid "script" +#~ msgstr "skrip" + +#~ msgid "message" +#~ msgstr "boodskap" + +#~ msgid "atom" +#~ msgstr "atoom" + +#~ msgid "system" +#~ msgstr "stelsel" + +#~ msgid "Resolvable" +#~ msgstr "Oplossings" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "Merk van hierdie resolusiepoging as ongeldig." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "Merk van oplossing %s as oninstalleerbaar" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s word geskeduleer om geïnstalleer te word, maar dit is vanweë " +#~ "afhanklikheidsprobleme nie moontlik nie." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "Kan %s nie installeer nie, aangesien dit reeds gemerk is om " +#~ "ongeïnstalleer te word" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "" +#~ "Kan %s nie installeer nie, aangesien dit nie op hierdie stelsel van " +#~ "toepassing is nie." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "Kan %s nie installeer nie, aangesien %s reeds gemerk is om geïnstalleer " +#~ "te word" + +#~ msgid "This would invalidate %s." +#~ msgstr "Dit sal %s ongeldig maak." + +#~ msgid "Establishing %s" +#~ msgstr "Vestig van %s" + +#~ msgid "Installing %s" +#~ msgstr "Installeer van %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "Bywerk van %s na %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "Oorslaan van %s: reeds geïnstalleer" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "Daar is geen alternatief-geïnstalleerde verskaffers van %s nie" + +#~ msgid "for %s" +#~ msgstr "vir %s nie" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "Bywerking na %s om verwyder van %s te verhoed, is nie moontlik nie." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s voorsien %s, maar word geskeduleer om ongeïnstalleer te word." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "" +#~ "%s voorsien %s, maar ’n ander weergawe van daardie %s is reeds " +#~ "geïnstalleer." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s voorsien %s, maar dit is oninstalleerbaar. Probeer om dit alleen te " +#~ "installeer vir meer besonderhede." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s voorsien %s, maar dit is gesluit." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s voorsien %s, maar word geskeduleer om gehou te word." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s voorsien %s, maar dit het ’n ander argitektuur." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "Kan nie aan vereiste %s vir %s voldoen nie" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s word vereis deur ’n ander geïnstalleerde oplossing; gevolglik sal dit " +#~ "nie ontkoppel word nie." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s word vereis deur ’n ander geïnstalleerde oplossing; gevolglik sal dit " +#~ "nie ontkoppel word nie." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "" +#~ "’n Konflik oor %s (%s) vereis die verwydering van om-geïnstalleer-te-word-" +#~ "%s" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "Merk van %s as oninstalleerbaar vanweë konflikte oor %s" + +#~ msgid "from %s" +#~ msgstr "vanaf %s" + +#~ msgid " Error!" +#~ msgstr "Fout!" + +#~ msgid " Important!" +#~ msgstr "Belangrik!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s afgehang van %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s word benodig deur %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s word benodig deur %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s word vervang deur %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s word benodig deur %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s deel van %s" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s word benodig deur %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "Kan Url-magtiging nie ontleed nie" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "Ignoreer hierdie vereiste oor die algemeen" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s word vereis deur ’n ander om-geïnstalleer-te-word-oplossing; gevolglik " +#~ "sal dit nie ontkoppel word nie." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "" +#~ "Kan nie ’n lêer wat benodig word om bywerkinstallasie uit te voer, skep " +#~ "nie." + +#~ msgid "Unable to restore all sources." +#~ msgstr "Kan nie alle bronne terugstel nie." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "Ten minste een bron reeds geregistreer, gebergde bronne kan nie " +#~ "teruggestel word nie." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "Kan %s nie installeer om die afhanklikhede van %s te vervul nie" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s afhanklik van %s" + +#~ msgid "Reading index files" +#~ msgstr "Lees van indekslêers" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "" +#~ "Die getekende repomd.xml-lêer het nie die handtekeningnagaan geslaag nie." + +#~ msgid "Reading product from %s" +#~ msgstr "Lees van produk vanaf %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "Lees van lêerlys vanaf %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "Lees van pakkette vanaf %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "Lees van keuse vanaf %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "Lees van patroon vanaf %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "Lees van regstellingsindeks %s" + +#~ msgid "Reading patch %s" +#~ msgstr "Lees van regstelling %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "Die skriplêer het nie die nagaansomtoets geslaag nie." + +#~ msgid "Reading packages file" +#~ msgstr "Lees van pakkettelêer" + +#~ msgid "Reading translation: %s" +#~ msgstr "Lees van vertaling: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "Pakket %s se integriteitsnagaan misluk. Wil u dit weer probeer aflaai, of " +#~ "die installasie staak?" + +#~ msgid " miss checksum." +#~ msgstr "nagaansom ontbreek." + +#~ msgid " fails checksum verification." +#~ msgstr "slaag nie nagaansom-bevestiging nie." + +#~ msgid "Downloading %s" +#~ msgstr "Aflaai van %s" diff --git a/po/ar.po b/po/ar.po new file mode 100644 index 0000000..f55a914 --- /dev/null +++ b/po/ar.po @@ -0,0 +1,6078 @@ +# Arabic message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999 SuSE GmbH. +# Ghayss Tarraf , 2000. +# Mohammad Alhargan , 2011, 2012. +# moh , 2011. +# محمد الحرقان , 2012, 2013. +# malhargan , 2014. +# malhargan , 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2020-05-02 19:50+0000\n" +"Last-Translator: mohammad alhargan \n" +"Language-Team: Arabic \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 ? 4 : 5;\n" +"X-Generator: Weblate 3.6.1\n" +"X-Language-English: Arabic\n" +"X-Language-Local: Arabic*\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "دولة غير معروفة: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "بدون رمز" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "أندورا" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "الإمارات العربية المتحدة" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "افغانستان" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "أنتيغوا وباربودا" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "أنجيلا" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "البانيا" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "ارمينيا" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "هولندا" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "أنجولا" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "أنتاركتيكا" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "الأرجنتين" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "ساموا الأمريكية" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "النمسا" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "أستراليا" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "أروبا" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "جزر ألاند" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "أذربيجان" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "البوسنة والهرسك" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "بربادوس" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "بنغلاديش" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "بلجيكا" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "بوركينا فاسو" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "بلغاريا" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "البحرين" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "بوروندي" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "بنين" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "برمودا" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "بروناي دار السلام" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "بوليفيا" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "البرازيل" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "جزر البهاما" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "بوتان" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "جزيرة بوفيه" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "بوتسوانا" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "روسيا البيضاء" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "بليز" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "كندا" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "جزر كوكوس (كيلنج)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "الكونغو" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "جمهورية أفريقيا الوسطى" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "سويسرا" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "ساحل العاج" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "جزر كوك" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "تشيلي" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "الكاميرون" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "الصين" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "كولومبيا" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "كوستاريكا" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "كوبا" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "الرأس الأخضر" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "جزيرة الكريسماس" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "قبرص" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "جمهورية التشيك" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "ألمانيا" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "جيبوتي" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "الدنمارك" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "دومينيكان" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "جمهورية الدومينيكان" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "الجزائر" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "الإكوادور" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "استونيا" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "مصر" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "الصحراء الغربية" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "إرتيريا" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "أسبانيا" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "إثيوبيا" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "فنلندا" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "فيجي" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "جزر فوكلاند (مالفينس)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "اتحاد دول ميكرونيزيا" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "جزر فيرو" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "فرنسا" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "فرنسا المركزية" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "الجابون" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "المملكة المتحدة" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "غرينادا" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "جورجيا" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "جيانا الفرنسية" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "غويرنسي" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "غانا" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "جبل طارق" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "جرين لاند" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "جامبيا" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "غينيا" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "جوادلوب" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "غينيا الاستوائية" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "اليونان" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "جورجيا الجنوبية وجزر ساندويتش الجنوبية" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "غواتيمالا" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "جوام" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "غينيا بيساو" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "جيانا" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "هونج كونج" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "جزيرة هيرد وجزر ماكدونالد" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "هندوراس" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "كرواتيا" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "هايتي" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "المجر" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "إندونيسيا" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "أيرلندا" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "اسرائيل" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "جزيرة مان" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "الهند" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "مقاطعة المحيط الهندي البريطانية" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "العراق" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "إيران" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "أيسلندا" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "إيطاليا" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "جيرسي" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "جامايكا" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "الأردن" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "اليابان" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "كينيا" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "قيرقيزستان" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "كمبوديا" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "كيريباتي" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "جزر القمر" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "سانت كيتس ونيفيس" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "كوريا الشمالية" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "كوريا الجنوبية" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "الكويت" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "جزر كيمان" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "كازاخستان" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "جمهورية لاو الشعبية الديمقراطية" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "لبنان" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "سانت لوشا" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "ليشتنشتاين" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "سيريلانكا" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "ليبريا" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "ليسوتو" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "ليتوانيا" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "لوكسمبورغ" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "لاتفيا" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "ليبيا" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "المغرب" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "موناكو" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "مولدوفا" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "الجبل الأسود" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "سانت مارتن" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "مدغشقر" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "جزر مارشال" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "مقدونيا" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "مالي" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "ميانمار" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "منغوليا" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "ماكاو" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "جزر ماريانا الشمالية" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "مارتينيك" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "موريتانيا" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "مونتسيرات" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "مالطة" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "موريشيوس" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "جزر المالديف" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "مالاوي" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "المكسيك" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "ماليزيا" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "موزمبيق" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "ناميبيا" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "كاليدونيا الجديدة" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "النيجر" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "جزيرة نورفولك" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "نيجيريا" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "نيكاراجوا" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "هولندا" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "النرويج" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "نيبال" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "ناورو" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "نيوي" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "نيوزيلاندا" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "عمان" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "بنما" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "البيرو" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "بولينيسيا الفرنسية" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "بابواغينيا الجديدة" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "الفلبين" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "باكستان" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "بولندا" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "سان بيير ومكويلون" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "بيتكيرن" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "بورتوريكو" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "فلسطين" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "البرتغال" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "بالاو" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "باراغواي" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "قطر" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "ريونيون" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "رومانيا" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "صربيا" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "روسيا الاتحادية" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "رواندا" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "المملكة العربية السعودية" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "جزر سليمان" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "سيشل" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "السودان" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "السويد" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "سنغافورا" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "سانت هلينا" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "سلوفينيا" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "سفالبارد وجان ماين" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "سلوفاكيا" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "سيراليون" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "سان مارينو" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "السنغال" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "الصومال" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "سورينام" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "سان تومي وبرينسيبي" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "السلفادور" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "سوريا" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "سوازيلند" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "جزر توركس وكايكوس" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "تشاد" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "المقاطعات الجنوبية الفرنسية" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "توجو" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "تايلاند" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "طاجكستان" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "توكيلو" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "تركمانستان" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "تونس" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "تونجا" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "تيمور الشرقية" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "تركيا" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ترينيداد وتوباغو" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "توفالو" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "تايوان" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "تنزانيا" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "أوكرانيا" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "أوغندا" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "الجزر الفرعية النائية التابعة للولايات المتحدة الأميركية" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "الولايات المتحدة" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "الأوروغواي" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "أوزباكستان" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "الكرسي البابوي (دولة الفاتيكان)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "سانت فنسنت وجزر غرينادين" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "فنزويلا" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "جزر فيرجن البريطانية" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "جزر فيرجن الأمريكية" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "فيتنام" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "فانواتو" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "جزر والس وفوتونا" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "ساموا" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "اليمن" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "مايوت" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "جنوب أفريقيا" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "زامبيا" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "زيمبابوي" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "يوفر" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "متطلبات مبدئية" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "يتطلب" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "تعارضات" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "العناصر القديمة" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "يوصي" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "يقترح" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "يحسن" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "يُضيف" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "جرت محاولة استيراد المفتاح غير الموجود %s إلى حلقة المفاتيح %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "فشل استيراد المفتاح." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "فشل حذف المفتاح." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "ملف التوقيع %s غير موجود" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "لغة غير معروفة: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "الأفارية" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "أذربيجان" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "الأتشينيزية" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "الأكولية" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "الأدانجمية" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "الأديجه" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "الأفرو آسيوية - (أخرى)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "الأفريهيلية" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "الأفريكانس" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "الآينوية" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "الأكانية" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "الأكادية" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "الألبانية" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "الأليوتية" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "اللغات الأمريكية الهندية" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "الألطائية الجنوبية" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "الأمهرية" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "الإنجليزية القديمة (450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "اللغات الأباتشية" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "العربية" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "الآرامية" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "الأراجونية" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "الأرمينية" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "الأروكانية" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "الأراباهو" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "الصناعية (أخرى)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "الأراواكية" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "الأسامية" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "الأسترية" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "اللغات الأزباسكانية" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "اللغات الأسترالية" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "الأفاريكية" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "الأفستية" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "الأوادية" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "الأيمارا" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "الأذربيجانية" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "الباندا" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "اللغات الباميليكية" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "الباشكيرية" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "البلوشية" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "البامبارا" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "اللغة البالية" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "الباسك" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "الباسا" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "البلطيقية (أخرى)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "البيجا" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "بلاروسي" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "البيمبا" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "بنجلاديشي" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "البربرية (أخرى)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "البهوجبرية" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "البيهارية" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "البيكولية" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "البينية" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "البيسلامية" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "السيكسيكية" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "البانتو (أخرى)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "البوسنية" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "البراجية" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "البريتون" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "الباتاكية (إندونسيا)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "البرياتية" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "البجينيزية" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "البلغارية" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "البورمية" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "البلينية" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "الكادو" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "الهندية الأمريكية الوسطى (أخرى)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "الكاريبية" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "الكاتالانية" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "القوقازية (أخرى)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "السيبيونو" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "السلتية (أخرى)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "التشامورو" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "التشيبشا" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "الشيشانية" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "التشاجاتاى" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "الصينية" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "التشكيزية" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "المارية" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "الشينوك جارجون" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "الشوكتو" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "الشيباوايان" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "الشيروكى" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "سلافية كنسية" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "التشفاش" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "الشايان" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "اللغات التشاميكية" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "القبطية" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "الكورنية" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "الكورسيكية" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" +"الكرييولى واللغات المبسطة الأخرى للتفاهم بين الشعوب على أساس الإنجليزية " +"(أخرى)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" +"الكرييولى واللغات المبسطة الأخرى للتفاهم بين الشعوب على أساس الفرنسية (أخرى)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" +"الكرييولى واللغات المبسطة الأخرى للتفاهم بين الشعوب على أساس البرتغالية " +"(أخرى)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "الكري" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "لغة توركية كريمينية" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "الكرييولى واللغات المبسطة الأخرى للتفاهم بين الشعوب (أخرى)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "الكاشبايان" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "الكشيتيك (أخرى)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "التشيكية" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "الداكوتا" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "الدانماركية" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "الدارجوا" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "الدياك" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "الديلوير" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "السلافية (الأزباسكانية)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "الدوجريب" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "الدنكا" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "المالديفية" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "الدوجرى" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "الدرافيدين (أخرى)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "الصربية السفلى" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "الديولا" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "الهولندية الوسطى (1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "الهولندية" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "الدايلا" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "الزونخاية" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "الافيك" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "المصرية (القديمة)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "الاكاجك" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "الامايت" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "الإنجليزية" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "الإنجليزية الوسطى (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "الإسبرانتو" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "الإستونية" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "إيوي" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "الإيوندو" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "الفانج" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "الفارويز" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "الفانتى" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "الفيجية" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "الفلبينية" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "الفنلندية" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "فينو أجرايان (أخرى)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "الفون" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "الفرنسية" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "الفرنسية الوسطى (1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "الفرنسية القديمة (842-1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "الفريزيان" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "الفلة" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "الفريلايان" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "الجا" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "الجايو" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "الجبيا" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "الجرمانية (أخرى)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "الجورجية" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "الألمانية" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "الجيز" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "لغة أهل جبل طارق" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "الغيلية" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "الأيرلندية" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "الجاليكية" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "المنكية" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "الألمانية العليا الوسطى (1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "الألمانية العليا القديمة (750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "الجندى" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "الجورونتالو" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "الجرمانية" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "الجريبو" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "اليونانية القديمة (حتى 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "اليونانية الحديثة (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "الجوارانى" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "الغوجاراتية" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "جويتشن" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "الهيدا" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "الهايتية" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "الهوسا" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "لغة أهل الهاواى" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "العبرية" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "الهيريرو" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "الهيليجينون" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "الهيماتشالى" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "هندية" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "الحثية" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "الهمونجية" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "الهيرى موتو" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "الصربية العليا" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "المجرية" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "الهبا" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "الإيبان" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "الإيجبو" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "الآيسلندية" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "الإيدو" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "السيتشيون يى" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "الإيجو" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "الإينكتيتت" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "الإنترلينج" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "الإيلوكو" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "اللغة الوسيطة (جمعية اللغات المساعدة الدولية)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "الهندية (أخرى)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "الإندونيسية" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "الهندية الأوروبية (أخرى)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "الإنجوشية" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "الإينبياك" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "الإيرانية (أخرى)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "اللغات الإيروكويانية" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "الإيطالية" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "الجاوية" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "اللوجبان" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "اليابانية" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "الجيدو الفارسى" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "الجيدو العربي" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "الكارا كالباك" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "القبيلية" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "الكاتشين" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "الكالاليست" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "الكامبا" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "الكانادا" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "الكاريين" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "الكاشميرية" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "الكانيورى" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "الكوي" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "الكازاخستانية" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "الكاباردايان" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "الخاسي" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "الخويسان (أخرى)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "الخميرية" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "الخوتانيز" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "الكيكيو" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "الكينيارواندا" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "القيرغستانية" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "الكيمبندو" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "الكونكانية" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "الكومى" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "الكونغو" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "الكورية" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "الكوسراين" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "الكبيل" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "الكاراتشاى بالكار" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "الكرو" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "كوروخ" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "الكيونياما" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "الكميك" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "الكردية" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "الكتيناى" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "لادينو" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "اللاهندا" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "اللامبا" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "اللاوية" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "اللاتينية" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "اللاتفية" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "الليزجهايانية" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "الليمبورغية" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "اللينجالا" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "الليتوانية" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "المنغولية" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "اللوزى" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "اللوكسمبرجية" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "اللبا-لؤلؤ" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "اللبا-كاتانجا" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "الجاندا" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "اللوسينو" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "اللوندا" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "اللو (كينيا وتنزانيا)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "اللشاى" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "المقدونية" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "المادريز" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "الماجا" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "المارشالية" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "المايثلية" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "الماكاسار" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "الماليالام" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "الماندينغ" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "الموري" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "الأوسترونيسيان (أخرى)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "المراثي" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "الماساي" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "الملايو" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "الموكشا" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "الماندار" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "الميند" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "الأيرلندية الوسطى (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "الميكماكيونية" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "المينانجكاباو" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "اللغات المتنوعة" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "المون خمير (أخرى)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "المالاجاشية" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "المالطية" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "المانشو" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "المانيبرى" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "لغات مانوبو" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "الموهوك" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "المولدوفية" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "المنغولية" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "موسي" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "اللغات المتعددة" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "لغات المندا" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "كريك" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "الميرانديز" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "الماروارى" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "لغات المايا" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "اللغة الأرزية" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "الناهيوتل" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "الهندية الأمريكية الشمالية" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "اللغة النابولية" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "نافاجو" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "النديبيل الجنوبى" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "النديبيل الشمالي" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "الندونجا" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "الألمانية السفلى" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "النيبالية" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "نيبال فاسا" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "نياس" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "النيجر-كوردوفانايان (أخرى)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "نيويان" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "النينورسك النرويجي" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "البوكمال النرويجي" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "نوجاى" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "النورس القديم" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "النرويجية" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "سوتو الشمالي" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "اللغات النوبية" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "النوارية التقليدية" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "التشيتشوا" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "النيامويزى" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "النيانكول" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "النيورو" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "النزيما" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "أوكيتان (بعد 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "الأوجيبوا" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "الأورييا" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "الأورومو" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "الأوساج" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "الأوسيتيان" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "التركية العثمانية (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "اللغات العثمانية" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "الغينية (أخرى)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "البانجاسينان" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "البهلوية" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "البامبانجا" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "بانجابي" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "البابيامينتو" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "البالوان" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "الفارسية القديمة (600-400 قبل الميلاد)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "الفارسية" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "الفليبينية (أخرى)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "الفينيقية" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "البالية" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "البولندية" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "البوهنبيايان" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "البرتغالية" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "اللغات البراقريطية" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "البروفانسية القديمة (حتى 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "بوشتو" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "الكويتشوا" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "الراجاسثانية" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "الرابانى" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "الراروتونجانى" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "الرومانسية (أخرى)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "الرهايتو-رومانس" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "الرومانية" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "الرومانية" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "روندي" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "الروسية" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "السانداوي" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "السانجو" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "الياكت" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "الهندية الأمريكية الجنوبية (أخرى)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "لغات ساليشان" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "الآرامية السومارية" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "السنسكريتية" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "الساساك" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "السانتالي" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "الصربية" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "الصقلية" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "الأسكتلندية" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "الكرواتية" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "السيلكب" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "السامية (أخرى)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "الأيرلندية القديمة (إلى 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "لغات الإشارة" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "الشانية" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "السيدامو" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "السينهالا" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "لغات السيويون" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "الصينية التيبتية (أخرى)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "السلافية (أخرى)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "السلوفاكية" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "السلوفينية" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "السامية الجنوبية" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "السامية الشمالية" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "اللغات السامية (أخرى)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "اللول سامي" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "الإيناري سامي" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "الساموائية" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "السكولت سامي" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "الشونا" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "السيندي" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "السونينك" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "السوجديان" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "الصومالية" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "السونجهاى" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "سوتو الجنوبي" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "الأسبانية" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "السردينية" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "سيرير" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "النيلية الصحراوية (أخرى)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "السواتي" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "السوكوما" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "السودانية" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "السوسو" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "السومارية" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "السواحلية" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "السويدية" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "السريانية" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "التاهيتية" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "تاي (أخرى)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "التاميلية" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "التتارية" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "تيلوغو" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "التيمن" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "التيرينو" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "التيتم" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "الطاجكية" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "التاغالوغية" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "التايلاندية" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "التبتية" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "التيجر" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "التيجرينيا" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "التيف" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "الكلينجون" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "التلينغيتية" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "التاماشيك" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "تونجا (نياسا)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "تونجا (جزر تونجا)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "التوك بيسين" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "التسيمشيان" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "التسوانية" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "تسونجا" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "التركمانية" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "التامبوكا" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "اللغات التوبية" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "التركية" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "الألطائية (أخرى)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "التوي" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "توفاني" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "الأدمرت" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "اليجاريتيك" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "الأغورية" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "الأوكرانية" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "الأمبندو" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "غير محددة" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "الأردية" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "الأوزبكية" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "الفاي" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "الفيندا" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "الفيتنامية" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "الفولابوك" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "الفوتيك" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "لغات الواكاشان" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "الوالامو" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "الواراي" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "الواشو" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "الويلزية" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "اللغات الصربية" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "الولونية" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "الولوف" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "الكالميك" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "الهاوسا" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "الياو" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "اليابيز" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "الييدية" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "اليوروبية" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "اللغات اليوبيكية" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "الزابوتيك" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "الزيناجا" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "الزهيونج" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "الزاند" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "الزولو" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "الزونية" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "سيتم تنفيذ الإجراءات التالية:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "الصلاحية غير منتهية" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "نهاية الصلاحية:: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "تنتهي: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(الصلاحية غير منتهية)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(انتهت الصلاحية)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(ستنتهي الصلاحية خلال 24 ساعة)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(ستنتهي الصلاحية خلال %d يوم)" +msgstr[1] "(ستنتهي الصلاحية خلال يوم واحد)" +msgstr[2] "(ستنتهي الصلاحية خلال يومين)" +msgstr[3] "(ستنتهي الصلاحية خلال بضعة أيام)" +msgstr[4] "(ستنتهي الصلاحية خلال عدة أيام)" +msgstr[5] "(ستنتهي الصلاحية خلال %d من الأيام)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "غير معروف" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "غير مدعوم" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "المستوى 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "المستوى 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "المستوى 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "مطلوب عقد عميل إضافي" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "غير صالح" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "مستوى الدعم غير محدد" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "البائع لا يوفر الدعم." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"تحديد المشكلة والذي يعني دعمًا فنيًا مصممًا لتوفير معلومات التوافق والمساعدة في " +"التثبيت ودعم الاستخدام والصيانة المستمرة واستكشاف الأخطاء وإصلاحها الأساسي. " +"والمستوى 1 من الدعم ليس مخصصًا لتصحيح أخطاء عيوب المنتجات." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"عزل المشكلة، والذي يعني دعمًا فنيًا مصممًا لعمل نسخ مطابقة من مشاكل العملاء " +"وعزل منطقة المشكلة وتوفير حل للمشاكل التي لم يتم حلها من خلال دعم المستوى 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"حل المشكلة، والذي يعني دعمًا فنيًا مصممًا لحل المشاكل المعقدة من خلال إشراك " +"الهندسة في حل عيوب المنتج التي تم تحديدها في دعم المستوى 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "مطلوب عقد عميل إضافي للحصول على الدعم." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "خيار دعم غير معروف. الوصف غير متاح" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"يتم قفل إدارة النظام بواسطة التطبيق الذي يتضمن معرف العملية %d (%s).\n" +"الرجاء إغلاق هذا التطبيق قبل المحاولة مرة أخرى." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "وضع التطابق '%s' غير معروف" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "وضع التطابق '%s' غير معروف للنمط '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "تعبير عادي غير صالح '%s': regcomp أعاد %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "التعبير العادي '%s' غير صالح" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "التصديق '%s' مطلوب" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"تفضل بزيارة مركز عملاء SUSE للتحقق ما إذا كان التسجيل صالحًا وغير منته " +"الصلاحية بعد." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"تفضل بزيارة Novell Customer Center (مركز خدمة عملاء Novell) للتحقق من صلاحية " +"التسجيل وعدم انتهائها." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"إنشاء نقطة إرفاق: لا يمكن العثور على دليل قابل للكتابة لإنشاء نقطة إرفاق" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "الرجاء تثبيت حزمة 'lsof' أولًا." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "لا يمكن إنشاء دليل لذاكرة التخزين المؤقت لبيانات التعريف." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "حدث خطأ أثناء محاولة القراءة من '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "لا يمكن إنشاء %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "لم يتم العثور على بيانات تعريف صالحة في أي عنوان URL محدد" +msgstr[1] "لم يتم العثور على بيانات تعريف صالحة في عنوان URL المحدد" +msgstr[2] "لم يتم العثور على بيانات تعريف صالحة في عنواني URL المحددين" +msgstr[3] "لم يتم العثور على بيانات تعريف صالحة في بعض عناوين URL المحددة" +msgstr[4] "لم يتم العثور على بيانات تعريف صالحة في كثير من عناوين URL المحددة" +msgstr[5] "لم يتم العثور على بيانات تعريف صالحة في عناوين URL محددة أخرى" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "فشل التخزين المؤقت للمخزن (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "يتم الآن بناء الذاكرة المؤقتة لمخزن '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "لا يمكن إنشاء ذاكرة التخزين المؤقت في %s - لا توجد أذونات للكتابة." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "نوع مخزن غير معالج" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "إضافة المخزن '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "اسم ملف المخزن غير صالح في '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "تعذر فتح الملف '%s' للكتابة." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "حدث خطأ غير معروف أثناء القراءة من '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "تعذرت قراءة دليل المخازن '%1%': تم رفض الإذن" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "فشلت قراءة الدليل '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "تعذرت قراءة ملف المخزن '%1%': تم رفض الإذن" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "إزالة المخزن '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "لا يمكن معرفة مكان تخزين المخزن." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "لا يمكن حذف '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "لا يمكن معرفة مكان تخزين الخدمة." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "خدمة غير معروفة '%1%': تتم الآن إزالة مخزن الخدمة الوحيد '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "لا يمكن أن يبدأ الاسم المستعار للمخزن بنقطة." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "لا يمكن أن يبدأ الاسم المستعار للخدمة بنقطة." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +# continue button label +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "هل تريد المتابعة؟" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "المستودع %1% لم يقم بتعريف مفتاح إضافي 'مفتاح gpg=' عناوين المواقع." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "يتم البحث عن معرف لمفتاح gpg رقم %1% في المستودع %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "البحث عن مفتاح gpg للتشفير %1% في الذاكرة المؤقتة %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "السمة المطلوبة '%s' مفقودة." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "إحدى السمتين '%s' أو '%s' أو كلتيهما مطلوبة." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "فشل التحقق من التوقيع" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"يبدو أنه قد تم إتلاف الحزمة %s أثناء النقل. هل تريد إعادة محاولة الاسترداد؟" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "فشل تقديم الحزمة %s. هل تريد إعادة محاولة الاسترداد؟" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "فشل التحقق من applydeltarpm." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "فشل applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "لا تدعم الأداة الإضافية للخدمة تغيير إحدى السمات." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "لا يمكن توفير الملف '%s' من المخزن '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "لا يوجد عنوان url في المخزن." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"يتعارض ملف %1%\n" +" من الحزمة\n" +" %2%\n" +" مع الملف من الحزمة\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"يتعارض ملف %1%\n" +" من الحزمة\n" +" %2%\n" +" مع الملف من تثبيت\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"يتعارض ملف %1%\n" +" من تثبيت\n" +" %2%\n" +" مع الملف من الحزمة\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"يتعارض ملف %1%\n" +" من تثبيت\n" +" %2%\n" +" مع الملف من تثبيت\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"يتعارض ملف %1%\n" +" من الحزمة\n" +" %2%\n" +" مع الملف\n" +" %3%\n" +" من الحزمة\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"يتعارض ملف %1%\n" +" من الحزمة\n" +" %2%\n" +" مع الملف\n" +" %3%\n" +" من تثبيت\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"يتعارض ملف %1%\n" +" من تثبيت\n" +" %2%\n" +" مع الملف\n" +" %3%\n" +" من الحزمة\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"يتعارض ملف %1%\n" +" من تثبيت\n" +" %2%\n" +" مع الملف\n" +" %3%\n" +" من تثبيت\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "تعذر إنشاء sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "توقيف %s عن طريق تجاهل بعض تبعياتها" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "تجاهل بشكل عام لبعض التبعيات" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "طلبات متعارضة" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "بعض مشكلات التبعية" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "الطلب غير مدعوم" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "الموفرون المحذوفون: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"موفرون غير قابلين للتثبيت: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "الموفرون غير القابلين للتثبيت: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "سيؤدي هذا الطلب إلى تعطل النظام!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "تجاهل تحذير النظام المعطل" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "بتثبيت %1% على الرغم من أنه تم سحبه" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "تسمح بتثبيت PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "تثبيت %1% على الرغم من أنه مدرج في القائمة السوداء" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "تم إيقاف التثبيت وفقًا للتعليمات." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " مُنفَّذ" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " فشل التنفيذ" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "تم تنفيذ %s بالفعل كـ %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " تم تخطي التنفيذ أثناء الإيقاف" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "حدث خطأ أثناء إرسال رسالة إعلام بالتحديث." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "رسالة تحديث جديد" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "فشل RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "فشل استيراد المفتاح العمومي %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "أخفقت إزالة المفتاح العام %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "ملفات التكوين التي تم تغييرها لـ %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "قامت rpm بحفظ %s باعتبارها %s، ولكن تعذر تحديد الفرق" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"تم حفظ rpm %s باعتبارها %s.\n" +"فيما يلي أول 25 سطرًا من سطور الفرق:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "قامت rpm بإنشاء %s باعتبارها %s، ولكن تعذر تحديد الفرق" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"تم إنشاء %s من خلال rpm باعتبارها %s.\n" +"فيما يلي أول 25 سطرًا من سطور الفرق:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "مخرجات rpm إضافية" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "تم إنشاء النسخة الاحتياطية %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "تمت المصادقة على التوقيع" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "نوع التوقيع غير معروف" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "تعذر التحقق من التوقيع" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "تمت المصادقة على التوقيع، لكن المفتاح غير موثوق به" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "تواقيع المفتاح العمومي غير متوفرة" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "الملف غير موجود أو لا يمكن التحقق من توقيعه" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "الملف غير موقع" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" +"النوع المشكوك فيه '%s' للمجموع الاختباري لوحدات البايت %u الذي يبلغ '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "تعذر فتح pty (‏%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "لا يمكن فتح المسار (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "سلسلة استعلام URL لبروتوكول LDAP غير صالحة" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "معلمة استعلام URL لبروتوكول LDAP ‏'%s' غير صالحة" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "تعذر استنساخ كائن Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "مرجع كائن Url فارغ غير صالح" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "تعذر تحليل مكونات Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "المحفوظات:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "لا يسمح مخطط Url بـ %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "مكون %s غير صالح '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "مكون %s غير صالح" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "تحليل سلسلة الاستعلام غير مدعوم لعنوان URL هذا" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "يعتبر مخطط Url مكونًا مطلوبًا" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "مخطط Url '%s' غير صالح" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "لا يسمح مخطط Url بإدخال اسم مستخدم" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "لا يسمح مخطط Url بإدخال كلمة سر" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "يتطلب مخطط Url وجود مكون مضيف" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "لا يسمح مخطط Url بوجود مكون مضيف" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "مكون المضيف '%s' غير صالح" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "لا يسمح مخطط Url بإدخال منفذ" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "مكون المنفذ '%s' غير صالح" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "يتطلب مخطط Url وجود اسم مسار" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "غير مسموح بالمسار النسبي في حالة وجود سلطة" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "تحتوي السلسلة المُرمَّزة على وحدة بايت NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "حرف تقسيم مصفوفة المعلمات الفاصل غير صالح" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "حرف تقسيم مخطط المعلمات الفاصل غير صالح" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "حرف ربط مصفوفة المعلمات الفاصل غير صالح" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "تم إنهاء الأمر بالحالة %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "تم إنهاء الأمر بواسطة الإشارة %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "تم إنهاء الأمر بخطأ غير معروف." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "لا يمكن تغيير الجذر الافتراضي إلى '%s' (‏%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "لا يمكن تغيير الدليل الافتراضي إلى '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" +"لا يمكن إجراء تغيير الدليل الافتراضي إلى '%s' داخل تغيير الجذر الافتراضي " +"'%s' (‏%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "لا يمكن تنفيذ '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "تعذر تقسيم (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "فشل توصيل %s على %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "فشل إلغاء توصيل %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "اسم ملف غير صالح: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "لم يتم فتح الوسيط أثناء محاولة تنفيذ الإجراء '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "لم يتم العثور على الملف '%s' في الوسيط '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "لا يمكن كتابة الملف '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "لم يتم إرفاق الوسيط" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "نقطة إرفاق وسائط غير صالحة" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "فشلت تهيئة تحميل (curl) لـ '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "استثناء النظام '%s' في الوسيط '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "المسار '%s' في الوسيط '%s' ليس ملفًا." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "المسار '%s' في الوسيط '%s' ليس دليلاً." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI غير صالح" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "اسم مضيف فارغ في URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "نظام ملفات فارغ في URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "وجهة فارغة في URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "مخطط URI غير مدعوم في '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "لا يدعم الوسيط العملية" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"خطأ في إنزال (curl) لـ '%s':\n" +"رمز الخطأ: %s\n" +"رسالة الخطأ: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "حدث خطأ أثناء تعيين خيارات إنزال (curl) لـ '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "لا يحتوي مصدر الوسائط '%s' على الوسيط المطلوب" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "الوسيط '%s' مستخدَم بواسطة مثيل آخر" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "لا يمكن إخراج أي وسائط" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "لا يمكن إخراج الوسائط '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "تم رفض إذن الوصول إلى '%s'." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "تم تجاوز المهلة عند الوصول إلى '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "تجاوزت البيانات المحملة حجم الملف ,الحجم المتوقع للملف '%s' من '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "يتعذر الوصول إلى الموقع '%s' مؤقتًا." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " مشكلة في شهادة SSL، تحقق من أن شهادة CA صالحة لـ '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "أسلوب تصديق HTTP غير مدعوم '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "نعم" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "لا" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "ملاحظة:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "تحذير:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "خطأ:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "تم" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "الخطأ" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "تحذير: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "استرداد:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "بدء تشغيل" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "لم يتم العثور عليه" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "لا تتوفر أية تعليمات لهذه المطالبة." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "لا تتوفر أية تعليمات لهذا الخيار" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "إظهار كلّ الخيارات" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "نعم" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "لا" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "جارٍ تنفيذ برنامج %%posttrans النصي '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "جارٍ تنفيذ برامج %posttrans النصية" + +#~ msgid "Package is not signed!" +#~ msgstr "لم يتم توقيع الحزمة!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "لا ينتمي %s إلى مخزن ترقية التوزيع" + +#~ msgid "%s has inferior architecture" +#~ msgstr "هيكل %s غير ملائم" + +#~ msgid "problem with installed package %s" +#~ msgstr "توجد مشكلة بالحزمة المثبتة %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "لا يوجد مصدر لتوفير %s المطلوب" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "هل قمت بتمكين كل المخازن المطلوبة؟" + +#~ msgid "package %s does not exist" +#~ msgstr "الحزمة %s غير موجود" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "يتم توفير %s من خلال النظام ولا يمكن حذفه" + +#~ msgid "%s is not installable" +#~ msgstr "%s غير قابل للتثبيت" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "لا يوجد مصدر لتوفير %s المطلوب من قبل %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "لا يمكن تثبيت كل من %s و%s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "يتعارض %s مع %s المتوفر من قبل %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s يُبطِل %s المتوفر من قبل %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s المثبَت سيُبطل %s الموفَر بواسطة %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "المشكلة القابلة للحل %s تتعارض مع %s المتوفرة من نفسها" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s يتطلب %s، ولكن لا يمكن توفير هذا المتطلب" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "إزالة القفل للسماح بالحذف %s" + +#~ msgid "do not install %s" +#~ msgstr "عدم تثبيت %s" + +#~ msgid "keep %s" +#~ msgstr "الاحتفاظ بـ %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "إزالة القفل للسماح بالتثبيت %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "عدم طلب تثبيت المشاكل القابلة للحل التي توفر %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "عدم طلب حذف كل المشاكل القابلة للحل التي توفر %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "عدم تثبيت أحدث إصدار من %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "الحفاظ على %s بغض النظر عن الهيكل غير الملائم" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "تثبيت %s بغض النظر عن الهيكل غير الملائم" + +#~ msgid "keep obsolete %s" +#~ msgstr "الحفاظ على %s القديمة" + +#~ msgid "install %s from excluded repository" +#~ msgstr "تثبيت %s من المخزن المستبعد" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "تخفيض إصدار %s إلى %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "تغيير الهيكل الخاص بـ %s إلى %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "تثبيت %s (مع تغيير البائع)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "استبدال %s بـ %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "إلغاء تثبيت %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "لا يمكن فتح ملف القفل: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "يتم الآن تشغيل هذا الإجراء بالفعل من قبل برنامج آخر." + +#~ msgid "Hal Exception" +#~ msgstr "استثناء Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "عذرًا، تم إنشاء هذا الإصدار من libzypp بدون دعم HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext غير متصل" + +#~ msgid "HalDrive not initialized" +#~ msgstr "لم تتم تهيئة HalDrive" + +#~ msgid "HalVolume not initialized" +#~ msgstr "لم تتم تهيئة HalVolume" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "تعذر إنشاء اتصال dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: تعذر إنشاء سياق libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: تعذر تعيين اتصال dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "تعذرت تهيئة سياق HAL -- هل hald ليس قيد التشغيل؟" + +#~ msgid "Not a CDROM drive" +#~ msgstr "ليس محرك أقراص مضغوطة" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "تعذرت تهيئة سمات mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "تعذر تعيين سمة mutex المتكرر" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "تعذرت تهيئة mutex المتكرر" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "تعذر الحصول على قفل mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "تعذر تحرير قفل mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "فشل استيراد المفتاح العام من الملف %s‏: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "فشلت إزالة المفتاح العام %s‏: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "لا يمكن العثور على جهاز التسلسل المتاح لتوصيل ملف الصور من '%s'" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "عموما تجاهل بعض المعتمدات" + +#~ msgid "do not forbid installation of %s" +#~ msgstr "لا تمنع تثبيت %s" + +#~ msgid "do not keep %s installed" +#~ msgstr "عدم الإبقاء على %s مثبت" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "لا يمكن إنشاء المفتاح العام %s من %s إلى ملف حلقة المفاتيح %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "حاول استيراد مفتاح غير موجود %s إلى حلقة مفاتيح %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "لا يمكن تغيير مجلد العمل '/' داخل استجذار (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "فشل تهيئة تحميل (Metalink curl) '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "تحميل (metalink curl) خطأ '%s':\n" +#~ "رمز الخطأ: %s\n" +#~ "رسالة الخطأ: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "توقف التحميل في %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "توقف التحميل بواسطة المستخدم" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "حدث خطأ أثناء إعداد خيارات التحميل (metalink curl) ل '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "فشل في تحميل %s من%s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "صربيا ومونتنيجرو" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "خيار list غير معروف" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "تعذر حل التبعيات" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" diff --git a/po/ast.po b/po/ast.po new file mode 100644 index 0000000..9627581 --- /dev/null +++ b/po/ast.po @@ -0,0 +1,5214 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR SuSE Linux GmbH, Nuernberg +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +msgid "" +msgstr "" +"Project-Id-Version: zypper\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2017-05-07 15:28+0000\n" +"Last-Translator: Enol P \n" +"Language-Team: Asturian \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: Weblate 2.6\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "¿Siguir?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr "" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Sí" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Non" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Alvertencia: " + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Fallu" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "fecho" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "fallu" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Alvertencia: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Recibiendo:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "aniciando" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Nun s'alcontró" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "nun hai ayuda disponible pa esta opción" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "amosar toles opciones" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "sí" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "non" diff --git a/po/be.po b/po/be.po new file mode 100644 index 0000000..0676caa --- /dev/null +++ b/po/be.po @@ -0,0 +1,5331 @@ +# Belarusian message file for YaST2 (@memory@). +# Copyright (C) 2007 SUSE Linux Products GmbH. +# Alexander Nyakhaychyk , 2007 +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2006-01-04 08:58+0100\n" +"Last-Translator: Alexander Nyakhaychyk \n" +"Language-Team: Belarusian \n" +"Language: be\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: 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" + +#: zypp/CountryCode.cc:50 +#, fuzzy +msgid "Unknown country: " +msgstr "Невядомая каманда: %1" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Аб'яднаныя Арабскія Эміраты" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +#, fuzzy +msgid "Afghanistan" +msgstr "Пакістан" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Албанія" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +#, fuzzy +msgid "Netherlands Antilles" +msgstr "Нідэрланды" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Аргенціна" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Аўстрыя" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Аўстралія" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +#, fuzzy +msgid "Aland Islands" +msgstr "Фарэрскія астравы" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +#, fuzzy +msgid "Bosnia and Herzegovina" +msgstr "Боснія і Герцагавіна" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Бангладэш" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Бельгія" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Балгарыя" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +#, fuzzy +msgid "Bahrain" +msgstr "Бахрэйн" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Балівія" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +#, fuzzy +msgid "Bouvet Island" +msgstr "Фарэрскія астравы" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Батсвана" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Беларусь" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Канада" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "Сірыя" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Швейцарыя" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +#, fuzzy +msgid "Cook Islands" +msgstr "Фарэрскія астравы" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Чылі" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Калумбія" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Коста Рыка" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Чэхія" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Германія" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Данія" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +#, fuzzy +msgid "Dominica" +msgstr "Дамініканская Рэспубліка" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Дамініканская Рэспубліка" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Алжыр" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Эквадор" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Эстонія" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Егіпет" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Іспанія" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Фінляндыя" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Фарэрскія астравы" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Францыя" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +#, fuzzy +msgid "Grenada" +msgstr "Канада" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Грузія" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Германія" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Грэнландыя" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Грэцыя" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Гватэмала" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Гонк Конг" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Гандурас" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Харватыя" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Венгрыя" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Інданэзія" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ірландыя" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Ізраіль" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Індыя" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Ірак" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Ісландыя" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Італія" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Іарданія" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Японія" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +#, fuzzy +msgid "South Korea" +msgstr "Паўдневая Афрыка" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Кувейт" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +#, fuzzy +msgid "Cayman Islands" +msgstr "Фарэрскія астравы" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +#, fuzzy +msgid "Kazakhstan" +msgstr "Пакістан" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Ліван" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Ліхтэнштэйн" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Літва" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +#, fuzzy +msgid "Luxembourg" +msgstr "Люксембург" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Латвія" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Марока" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +#, fuzzy +msgid "Marshall Islands" +msgstr "Фарэрскія астравы" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Македонія" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +#, fuzzy +msgid "Mauritania" +msgstr "Літва" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Мальта" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +#, fuzzy +msgid "Malawi" +msgstr "Малайзія" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Мексіка" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Малайзія" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +#, fuzzy +msgid "New Caledonia" +msgstr "Македонія" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +#, fuzzy +msgid "Norfolk Island" +msgstr "Фарэрскія астравы" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +#, fuzzy +msgid "Nigeria" +msgstr "Алжыр" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Нікарагуа" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Нідэрланды" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Нарвегія" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Новая Зеландыя" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Аман" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Панама" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Перу" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Філіпіны" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Пакістан" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Польша" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Пуэрта Рыка" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Партугалія" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Парагвай" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Катар" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Румынія" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "Алжыр" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Саудаўская Аравія" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +#, fuzzy +msgid "Solomon Islands" +msgstr "Фарэрскія астравы" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Судан" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Швецыя" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Сінгапур" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Славенія" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Славакія" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Сальвадор" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +#, fuzzy +msgid "Swaziland" +msgstr "Тайланд" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Тайланд" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Таджыкістан" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +#, fuzzy +msgid "Turkmenistan" +msgstr "Таджыкістан" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Туніс" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Турцыя" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Тайвань" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Украіна" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +#, fuzzy +msgid "United States" +msgstr "Аб'яднаныя Арабскія Эміраты" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Уругвай" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Узбексітан" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Венесуэла" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Йемен" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Паўдневая Афрыка" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Зімбабве" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +#, fuzzy +msgid "Unknown language: " +msgstr "Невядомая каманда: %1" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +#, fuzzy +msgid "Albanian" +msgstr "Албанія" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "Паўдневая Афрыка" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +#, fuzzy +msgid "Apache Languages" +msgstr "&Мова" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +#, fuzzy +msgid "Australian Languages" +msgstr "Аўстралія" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +#, fuzzy +msgid "Belarusian" +msgstr "Беларусь" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +#, fuzzy +msgid "Batak (Indonesia)" +msgstr "Інданэзія" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +#, fuzzy +msgid "Bulgarian" +msgstr "Балгарыя" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +#, fuzzy +msgid "Catalan" +msgstr "Каталонія" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "&Мова" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +#, fuzzy +msgid "Danish" +msgstr "Завяршыць" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +#, fuzzy +msgid "Estonian" +msgstr "Эстонія" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +#, fuzzy +msgid "Faroese" +msgstr "Фарэрскія астравы" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +#, fuzzy +msgid "Filipino" +msgstr "Філіпіны" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +#, fuzzy +msgid "Finnish" +msgstr "Завяршыць" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +#, fuzzy +msgid "Georgian" +msgstr "Грузія" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +#, fuzzy +msgid "German" +msgstr "Германія" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +#, fuzzy +msgid "Hungarian" +msgstr "Венгрыя" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +#, fuzzy +msgid "Icelandic" +msgstr "Ісландыя" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "Літва" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +#, fuzzy +msgid "Indonesian" +msgstr "Інданэзія" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +#, fuzzy +msgid "Italian" +msgstr "Італія" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +#, fuzzy +msgid "Japanese" +msgstr "Японія" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +#, fuzzy +msgid "Kannada" +msgstr "Канада" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +#, fuzzy +msgid "Lao" +msgstr "Ліван" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +#, fuzzy +msgid "Latvian" +msgstr "Латвія" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "Люксембург" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +#, fuzzy +msgid "Lithuanian" +msgstr "Літва" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "Люксембург" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +#, fuzzy +msgid "Macedonian" +msgstr "Македонія" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +#, fuzzy +msgid "Malayalam" +msgstr "Малайзія" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "Малайзія" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "Малайзія" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +#, fuzzy +msgid "Maltese" +msgstr "Мальта" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "&Мова" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "Югаславія" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +#, fuzzy +msgid "Munda languages" +msgstr "Захаванне мовы..." + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "&Мова" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "Германія" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +#, fuzzy +msgid "Norwegian" +msgstr "Нарвегія" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "&Мова" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "&Мова" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +#, fuzzy +msgid "Philippine (Other)" +msgstr "Філіпіны" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +#, fuzzy +msgid "Portuguese" +msgstr "Партугалія" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "&Мова" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "Японія" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "Румынія" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +#, fuzzy +msgid "Romanian" +msgstr "Румынія" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +#, fuzzy +msgid "Russian" +msgstr "Расія" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "Захаванне мовы..." + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +#, fuzzy +msgid "Croatian" +msgstr "Харватыя" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "&Мова" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Захаванне мовы..." + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +#, fuzzy +msgid "Slovak" +msgstr "Славакія" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +#, fuzzy +msgid "Slovenian" +msgstr "Славенія" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +#, fuzzy +msgid "Lule Sami" +msgstr "Імя модуля" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +#, fuzzy +msgid "Swedish" +msgstr "Швецыя" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +#, fuzzy +msgid "Tai (Other)" +msgstr "Іншае" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "Катар" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +#, fuzzy +msgid "Tajik" +msgstr "Таджыкістан" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +#, fuzzy +msgid "Thai" +msgstr "Тайланд" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +#, fuzzy +msgid "Tswana" +msgstr "Батсвана" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "Турцыя" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "&Мова" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +#, fuzzy +msgid "Turkish" +msgstr "Турцыя" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +#, fuzzy +msgid "Ukrainian" +msgstr "Украіна" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +#, fuzzy +msgid "Uzbek" +msgstr "Узбексітан" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +#, fuzzy +msgid "Vietnamese" +msgstr "Імя файла" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "Захаванне мовы..." + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "&Мова" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "невядомы" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Невядомая каманда: %1" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Памылковае значэнне для опцыі '%1': %2" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +#, fuzzy +msgid "Unhandled repository type" +msgstr "Дадаць уключаныя сховішчы" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, fuzzy, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Даданне ўключаных сховішчаў..." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Невядомая опцыя для каманды '%1': %2" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Выдаленне непатрэбных сховішчаў..." + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Працягнуць?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr "" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Змяніць канфігурацыю IrDA" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, fuzzy, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Памылковае значэнне для опцыі '%1': %2" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, fuzzy, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Памылковае значэнне для опцыі '%1': %2" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Так" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Не" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Заўвага:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Папярэджванне:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Памылка:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "done" +msgstr "Інданэзія" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "Памылка" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Папярэджванне" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:421 +#, fuzzy +msgid "No help available for this prompt." +msgstr "Даведка не даступна" + +#: zypp-tui/output/OutNormal.cc:438 +#, fuzzy +msgid "no help available for this option" +msgstr "Даведка не даступна" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "да" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "не" + +#, fuzzy +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Выдаліць непатрэбныя сховішчы" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "Захаваць налады ўсталёўкі" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Захаваць налады ўсталёўкі" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "Праверыць інтэрнэт злучэнне" diff --git a/po/bg.po b/po/bg.po new file mode 100644 index 0000000..a5e7504 --- /dev/null +++ b/po/bg.po @@ -0,0 +1,6119 @@ +# translation of zypp.bg.po to Bulgarian +# translation of libzypp.bg.po to Bulgarian +# Bulgarian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) SuSE GmbH, 2000. +# Dimitar Boin , 2000. +# Y Gonch , 2000. +# Borislav Mitev , 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: zypp.bg\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2017-10-23 11:43+0000\n" +"Last-Translator: Dimitar Zahariev \n" +"Language-Team: Bulgarian \n" +"Language: bg\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: Weblate 2.13.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Неизвестна държава: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Без код" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Андора" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Обединени арабски емирства" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Афганистан" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Антигуа и Барбуда" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Ангила" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Албания" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Армения" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Холандски Антили" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Ангола" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Антарктика" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Аржентина" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Американска Самоа" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Австрия" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Австралия" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Аруба" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Алански Острови" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Азербайджан" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Босна и Херцеговина" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Барбадос" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Бангладеш" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Белгия" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Буркина Фасо" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "България" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Бахрейн" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Бурунди" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Бенин" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Бермуда" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Бруней" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Боливия" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Бразилия" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Бахами" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Бутан" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Остров Бувет" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Боцвана" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Беларус" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Белиз" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Канада" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Кокосови Острови" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Конго" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "Централноафриканска Република" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Швейцария" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Кот д'ивоар" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Острови Кук" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Чили" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Камерун" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Китай" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Колумбия" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Коста Рика" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Куба" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Капо Верде" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Коледни Острови" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Кипър" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Чешка република" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Германия" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Джибути" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Дания" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Доминика" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Доминиканска република" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Алжир" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Еквадор" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Естония" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Египет" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Западна Сахара" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Еритрея" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Испания" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Етиопия" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Финландия" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Фуджи" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Фолклендски Острови (Малвини)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Федерални Щати Микронезия" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Фароеви острови" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Франция" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Френска метрополия" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Габон" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Великобритания" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Гренада" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Грузия" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Френска Гвиана" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Гърнзи" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Гана" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Гибралтар" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Гренландия" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Гамбия" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Гвинея" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Гваделупа" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Екваториална Гвинея" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Гърция" + +# GS +# fuzzy +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Южни Сандвичеви Острови" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Гватемала" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Гуам" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Гвинея-Бисау" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Гияна" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Хонг Конг" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Хърд и МакДоналд Острови" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Хондурас" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Хърватска" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Хаити" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Унгария" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Индонезия" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ирландия" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Израел" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Индия" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Английски територии в Индийския океан" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Ирак" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Ирак" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Исландия" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Италия" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Ямайка" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Йордания" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Япония" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Кения" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Киргизтан" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Камбоджа" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Кирибати" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Комори" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Свети Китс и Невис" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Северна Корея" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Южна Корея" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Кувейт" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Кайманови Острови" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Казахстан" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Лао Народна Демократична Република" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Ливан" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Санта Лучия" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Лихтенщайн" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Шри Ланка" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Либерия" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Лесото" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Литва" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Люксембург" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Латвия" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Либерия" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Мароко" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Монако" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Молдова" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Черна Гора" + +# SM +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "Сан Марино" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Мадагаскар" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Маршалови Острови" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Македония" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Мали" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Мианмар" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Монголия" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Макао" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Северни Марианови Острови" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Мартиник" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Мавритания" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Монсерат" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Малта" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Мавриций" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Мали" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Малави" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Мексико" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Малайзия" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Мозамбик" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Намибия" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Нова Каледония" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Нигер" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Норфолк Остров" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Нигерия" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Никарагуа" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Холандия" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Норвегия" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Непал" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Науру" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Нию" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Нова Зеландия" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Оман" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Панама" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Перу" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Френска Полинезия" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Папуа Нова Гвинея" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Филипини" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Пакистан" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Полша" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Свети Пиер и Микелон" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Питкаирн" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Пуерто Рико" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Палестински територии" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Португалия" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Палау" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Парагвай" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Катар" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Риюниън" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Румъния" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Сърбия" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Руска Федерация" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Руанда" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Саудитска Арабия" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Соломонови Острови" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Сейшели" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Судан" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Швеция" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Сингапур" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Света Елена" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Словения" + +# SJ +# fuzzy +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Свалбард и Ян Майен Острови" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Словакия" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Сиера Леоне" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "Сан Марино" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Сенегал" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Сомалия" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Суринам" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Сао Томе и Принсипи" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Ел Салвадор" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Суринам" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Свазиленд" + +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Тюрк и Кайкос Острови" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Чад" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Франция Южни Територии" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Того" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Тайланд" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Таджикистан" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Токелау" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Туркменистан" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Тунис" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Тонга" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Източен Тимор" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Турция" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Тринидад и Тобаго" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Тувалу" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Тайван" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Танзания" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Украйна" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Уганда" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Малки Острови по крайбрежието на САЩ" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "САЩ" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Уругвай" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Узбекистан" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Ватикана" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Свети Винсент и Гренадин" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Венецуела" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Вирджински Острови (Великобритания)" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Вирджински Острови (САЩ)" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Виетнам" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Вануату" + +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Уолис и Футуна Острови" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Самоа" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Йемен" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Майот" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Южна Африка" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Замбия" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Зимбабве" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Доставя" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Изисква" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "В конфликт с" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s прави ненужно: %s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Препоръчва" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Предлага" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Подобрява" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Допълва" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Неуспешно зареждане на модула \"%s\"." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Неуспешно зареждане на модула \"%s\"." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "KScreensaver не е открит." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Неизвестен език: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Африкански" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Абхазки" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Ачински" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Аколи" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Адангме" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Адиге" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Афро-азиатски (друг)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Африхили" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Африкаанс" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Аину" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Акан" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Акадски" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Албански" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Алют" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +#, fuzzy +msgid "Algonquian Languages" +msgstr "Алгонквиански езици" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Южно-алтайски" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Амхарик" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Английски, стар (ок. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +#, fuzzy +msgid "Apache Languages" +msgstr "Апачи езици" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Арабски" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Арамайски" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Арагонски" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Арменски" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Араукански" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Арапахо" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Изкуствен (друг)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Аравак" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Асамески" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Астурийски" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +#, fuzzy +msgid "Athapascan Languages" +msgstr "Атапаскан езици" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +#, fuzzy +msgid "Australian Languages" +msgstr "Австралийски езици" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Аварски" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Авестански" + +# SZ +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Авадхи" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Аймара" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Азербайджански" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Банда" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +#, fuzzy +msgid "Bamileke Languages" +msgstr "Бамилеке езици" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Башкирски" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Балучи" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Бамбара" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Балинески" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Баски" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Баса" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Балтийски (друг)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Бея" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Беларуски" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Бебма" + +# SN +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Бенгалски" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Бербер (друг)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Бходжури" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Бихари" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Бикол" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Бини" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Бислама" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Сиксика" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Банту (друг)" + +# BJ +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Босненски" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Брая" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Бретон" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Батак (Индонезия)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Бурият" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Бугинески" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Български" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Бурмийски" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Блин" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Каддо" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Централно-американски индиански (друг)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Карибски" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Каталунски" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Кауказийски (друг)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Кебуано" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Келтски (друг)" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Коморийски" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Чибча" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Чеченски" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Чагатай" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Китайски" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Чуукски" + +# ML +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Мари" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +#, fuzzy +msgid "Chinook Jargon" +msgstr "Чинук жаргон" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Чоктау" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Чипеуан" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Чероки" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Църковно-славянски" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Чуваш" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Кайенски" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "Чамик езици" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Коптик" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Корнски" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Корсикански" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +#, fuzzy +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Креолски и пидгински, базиран на английски (друг)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +#, fuzzy +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Креолски и пидгински, базиран на френски (друг)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +#, fuzzy +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Креолски и пидгински, базиран на португалски (друг)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Крее" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Кримин татарски" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +#, fuzzy +msgid "Creoles and Pidgins (Other)" +msgstr "Креолски и пидгински (друг)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Кашубски" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Кушитик (друг)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Чешка" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Дакота" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Датска" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Доргава" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Даяк" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Делауеър" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Славе (Атапаскан)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Догриб" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Динка" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Дивехи" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Догри" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Дравидски (друг)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Долно-сорбийски" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "ДуалаДу" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Холандски, среден (ок. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Холандска" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Дюла" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Дзонга" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Ефик" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Египетски (древен)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Екаджук" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Еламите" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Английски" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Английски, среден (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Есперанто" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Естонска" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Еве" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Евондо" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Фанг" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Фаероски" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Фанти" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Фуджиянски" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Филипино" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Финландска" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Фино-угрийски (друг)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Фон" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Френска" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Френски, среден (ок. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Френски, стар (842-ок. 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Фризийски" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Фула" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Флюлийски" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Га" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Гайо" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Гбая" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Германски (друг)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Грузински" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Германска" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Гииз" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Гилбертезки" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Гаелски" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Ирландски" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Галицийски" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Манкс" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Немски, късно среден (ок. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Немски, късно стар (ок. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Гонди" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Горонтало" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Готски" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Гребо" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Гръцки, древен (до 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Гръцки, модерен (след 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Гуарани" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Гуджарити" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Гвич'ин" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Хайда" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Хаитски" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Хауза" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Хавайски" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Еврейски" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Хереро" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Хилигонски" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Химачали" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Хинди" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Хитите" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Хмонг" + +# HT +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Хири Моту" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Горно-сорбийски" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Унгарска" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Хупа" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Ибан" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Игбо" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Исландска" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Идо" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Сичуан юи" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ижо" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Инуктитут" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Интерезичен" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Илоко" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Интерлингва (Международна Асоциация за Помощен Език)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Индски (друг)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Индонезийски" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Индо-европейски (друг)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ингуш" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Инупиаг" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Ирански (друг)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +#, fuzzy +msgid "Iroquoian Languages" +msgstr "Ирокуонски езици" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Италианска" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Явайски" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Лоджбан" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Японска" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Юдейо-персийски" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Юдейо-арабски" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Кара-калпака-кал" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Кабил" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Качин" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Калаалисут" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Камба" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Канада" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Карен" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Кашмирски" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Канури" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Кави" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Казакски" + +# MR +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Кабардийски" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Каси" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Койсан (друг)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Хмерски" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Котанески" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Кикую" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Кинярванда" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Киргизки" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Кимбунду" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Конкани" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Коми" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Конго" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Корейски" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Косраейски" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Кпеле" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Карачай-балкар" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Крю" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Курук" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Куаняма" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Кумикумик" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Кюрдски" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Кутенай" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ладино" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Ланда" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Ламба" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Лао" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Латински" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Латвийски" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Лезганийски" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Лимбурган" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Лингала" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Литовска" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Монго" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Лози" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Люксембургски" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Луба-лулуя" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Луба-катанга" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ганда" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Луисено" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Лунда" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Луо (Кения и Танзания)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "Лушай" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Македонски" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Мадурейски" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Магахи" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Маршалски" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Майтили" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Макасар" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Малаялам" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Мандинго" + +# ML +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Маори" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Австронезийски (друг)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Марати" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Масаи" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Малайски" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Мокша" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Мандар" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Менде" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Ирландски, среден (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Ми'кмак" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Минанкубау" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "Разни езици" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Мон-кхмер (друг)" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Малагаси" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Малтийски" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Манчу" + +# ML +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Манпури" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "Манобо езици" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Мохаук" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Молдовски" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Монголски" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Моси" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "Множество езици" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Мунда езици" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Креек" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Мирандейски" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Марвари" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "Майски езици" + +# SY +# fuzzy +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Ерзя" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Нахуати" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Северна-американски индиански" + +# NP +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Неаполитански" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Навахо" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ндебеле, южен" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ндебеле, северерен" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ндонга" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Долно-германски" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Непалски" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Непал баса" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Ниас" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Нигер-гордофански (друг)" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Нюеан" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Норвежки нинорск" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Норвежки бокмал" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Ногай" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Норсе, стар" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Норвежка" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Северно сото" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "Нубийски езици" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Класически невари" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Чичева" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Нямвези" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Нянколе" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Ньоро" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Нзима" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Окцитан (след 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ожибва" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Ория" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Оромо" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Осаге" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Осетински" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Турски, отомански (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "Османски езици" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Папуански (друг)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Пангасински" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Пахлави" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Пампанга" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Панджаби" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Папияменто" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Палауан" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Персийски, стар (ок. 600-400 пр.н.е.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Персийски" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Филипински (друг)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Финикийски" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Пали" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Полска" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Понпейски" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Португалска" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "Пракрит езици" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Провенциален, стар (до 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Пущо" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Куечуа" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Раджастани" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Папануй" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Раротоган" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Романски (друг)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Раето-романс" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Романи" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Румънски" + +# RE +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Рунди" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Руска" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Сандауе" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Санго" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Якут" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Южно-американски индиански (друг)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "Салишан езици" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Самаритан арамаик" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Санскрит" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Сасак" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Сантали" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Сръбски" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Сицилиански" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Скотски" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Хърватска" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Селкуп" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Семитски (друг)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Ирландски, стар (до 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Знакови езици" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Шан" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Сидамо" + +# AO +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Синхала" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Сиуан езици" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Сино-тибетски (друг)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Славянски (друг)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Словашка" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Словенски" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Южно сами" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Северно сами" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "Сами езици (друг)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Люле сами" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Инари сами" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Самоански" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Сколт сами" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Шона" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Синди" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Синонке" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Согдийски" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Сомалийски" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Сонгхай" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Сото, южно" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Испанска" + +# MR +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Сардински" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Серер" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Нило-сахарски (друг)" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Свати" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Сукума" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Сундански" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Сусу" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Шумерски" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Свахили" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Шведска" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Сирийски" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Таитски" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Тай (друг)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Тамилски" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Татарски" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Телугу" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Тимне" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Терено" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Тетум" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Таджикски" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Тагалог" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Тайландски" + +# TW +# fuzzy +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Тибетски" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Тигре" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Тигриния" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Тив" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Клингон" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Тлингит" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Тамашек" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Тонга (Няса)" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Тонга (Острови Тонга)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Ток писин" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Цимашински" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Цвана" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Цонга" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Туркменски" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Тумбука" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "Тупи езици" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Турска" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Алтайски (друг)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Тви" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Тувински" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Удмурт" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Угаритски" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Уигурски" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Украинска" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Умбурду" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Неопределен" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Урду" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Узбекски" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Вай" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Венда" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Виетнамски" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Волапук" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Вотски" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "Вакашан езици" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Валамо" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Варай" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Вашо" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Уелски" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "Сорбийски езици" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Валун" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Волоф" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Калмик" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Ксоса" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Яо" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Япесе" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Юдийски" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Йоруба" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "Юпик езици" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Запотек" + +# SN +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Зенага" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Цуанг" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Занде" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Зулу" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Зуни" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "Пакетът не е подписан" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "неизвестно" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Неизвестен потребител: %s\n" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "невалидно име на услуга '%1'." + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Не може да се създаде %s: %m\n" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Достъпът до носителя за обновяване на драйверите е неуспешен." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "невалидно име на услуга '%1'." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Файлът не може да бъде отворен за запис." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Грешка при четенето от дискетата." + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Неуспешно зареждане на модула \"%s\"." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "%s не може да бъде инсталиран" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +#, fuzzy +msgid "Continue?" +msgstr "Продължаване" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +# %s is either BOOTP or DHCP +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "Настройването чрез %s бе неуспешно." + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Никой не доставя %s" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "Възникнала е грешка при създаването на временния файл %s: %m" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "Пренебрегване на това изискване само тук" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "Пренебрегване на това изискване само тук" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "%s не може да бъде инсталиран поради пробем със зависимостите" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "Никой не доставя %s" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "Няма инсталируеми доставчици на %s" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "Няма инсталируеми доставчици на %s" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +# %s is either BOOTP or DHCP +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "Настройването чрез %s бе неуспешно." + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "пропадна." + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Променени файлове с настройки за %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm запази %s като %s, но е невъзможно да се открие разликата" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm запази %s като %s.\n" +"Ето първите 25 реда от разликите:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm създаде %s като %s, но е невъзможно да се открие разликата" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm създаде %s като %s.\n" +"Ето първите 25 реда от разликите:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "Допълнителен изход от rpm:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "създадено резервно копие %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "KScreensaver не е открит." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "KScreensaver не е открит." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "KScreensaver не е открит." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Съмнителен тип '%s' за %u, код за проверка '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Възникнала е грешка при отварянето на %s: %m" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Възникнала е грешка при отварянето на %s: %m" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +#, fuzzy +msgid "Invalid empty Url object reference" +msgstr "Невалидно име за празно действие за услугата '%1'" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +#, fuzzy +msgid "History:" +msgstr "Преглед на историята" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, fuzzy, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "невалидно име на услуга '%1'." + +#: zypp-core/url/UrlBase.cc:247 +#, fuzzy, c-format, boost-format +msgid "Invalid %s component" +msgstr "Невалидна информация" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, fuzzy, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "невалидно име на услуга '%1'." + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Команда за изпълнение при свързване" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Възникнала е грешка при отварянето на %s: %m" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Неуспешно зареждане на модула \"%s\"." + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Неуспешно зареждане на модула \"%s\"." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Временният файл (%s) не може да бъде създаден: %m" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "%s не може да бъде инсталиран" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Да" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Не" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Предупреждение" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Грешка" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "done" +msgstr "Индонезия" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "Грешка" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Предупреждение" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Стартиране..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "не работи" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "да" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "не" + +#, fuzzy +#~ msgid "Package is not signed!" +#~ msgstr "Пакетът има невалидна сигнатура." + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s доставя %s, но има друга архитектура." + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "Никой не доставя %s" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Пакетът не е подписан" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s е заключен и не може да бъде деинсталиран." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "Инсталирането на %s бе неуспешно" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s е необходим на %s" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s не може да бъде инсталиран" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s е в конфликт с %s" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s прави ненужно %s" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s прави ненужно %s" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s е в конфликт с %s" + +#~ msgid "do not install %s" +#~ msgstr "без инсталиране на %s" + +#~ msgid "keep %s" +#~ msgstr "запазване на %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "без инсталиране на %s" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "Няма инсталируеми доставчици на %s" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "Без инсталиране или премахване на конфликтните пакети" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s доставя %s, но има друга архитектура." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "Инсталиране на %s, въпреки че ще промени архитектурата" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s прави ненужно %s" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "Обновяване на %s към %s" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Инсталиране" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Възникнала е грешка при отварянето на %s: %m" + +#, fuzzy +#~ msgid "Hal Exception" +#~ msgstr "Криптиране" + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "не е свързан" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "връзка канал-към-канал" + +#, fuzzy +#~ msgid "Not a CDROM drive" +#~ msgstr "Не са открити CD-ROM устройства." + +#, fuzzy +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Не може да се придобие заключването на zypp." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "без инсталиране на %s" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Неуспешно зареждане на модула \"%s\"." + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Сърбия и Черна Гора" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Непознат монитор:" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "" +#~ "%s не може да бъде инсталиран за задоволяване на зависимостите на %s" + +#~ msgid "%s remove failed" +#~ msgstr "Премахването на %s бе неуспешно" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "Невалидно име на устройство." + +#~ msgid "rpm output:" +#~ msgstr "Изход от rpm:" + +#~ msgid "%s install failed" +#~ msgstr "Инсталирането на %s бе неуспешно" + +#~ msgid "%s installed ok" +#~ msgstr "Инсталирането на %s бе успешно" + +#~ msgid "%s remove ok" +#~ msgstr "Премахването на %s бе успешно" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "" +#~ "%s задоволява тази зависимост, но ще промени архитектурата на " +#~ "инсталирания пакет" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "" +#~ "%s задоволява тази зависимост, но ще промени архитектурата на " +#~ "инсталирания пакет" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Без инсталиране или премахване на конфликтните пакети" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Пренебрегване на това, че %s е зададен вече за инсталиране" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "Пренебрегване на остарелите %s в %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "Пренебрегване на конфликта на %s" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "Пренебрегване на това изискване само тук" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "Инсталиране на %s, въпреки че ще промени архитектурата" + +#~ msgid "Install missing resolvables" +#~ msgstr "Инсталиране на липсващите пакети" + +#~ msgid "Keep resolvables" +#~ msgstr "Запазване на пакетите" + +#~ msgid "Unlock these resolvables" +#~ msgstr "Отключване на тези пакети" + +#~ msgid "delete %s" +#~ msgstr "изтриване на %s" + +#~ msgid "install %s" +#~ msgstr "инсталиране на %s" + +#~ msgid "unlock %s" +#~ msgstr "отключване на %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "отключване на всички пакети" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Възникнала е грешка при отварянето на %s: %m" + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "Грешка при четенето на сектор %u." + +#, fuzzy +#~ msgid "Software management is already running." +#~ msgstr "Услугите за PCMCIA карти вече работят." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s е заменен от %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s е заменен от %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "Тези пакети ще бъдат изтрити от системата." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s няма да бъде деинсталиран, защото все още е необходим" + +#~ msgid "Invalid information" +#~ msgstr "Невалидна информация" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s е необходим на друг пакет" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s е необходим на:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s е в конфликт с други пакети" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s е в конфликт с:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s прави ненужни други пакети" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "Тези пакети ще бъдат изтрити от системата." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s зависи от други пакети" + +#~ msgid "%s depends on %s" +#~ msgstr "%s зависи от %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s зависи от: %s" + +#~ msgid "Child of" +#~ msgstr "Дете на" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "Няма наличен ресурс за поддръжката на това изискване." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "Поради проблемите, които са показани по-долу/горе сега няма да могат да " +#~ "сеудовлетворят всички зависимости." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%s не може да бъде инсталиран, защото е в конфликт с %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s не е инсталиран и не може да бъде маркиран за деинсталиране." + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s има незадоволени изискания" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s има липсващи зависимости" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s не може да бъде инсталиран поради липсващи зависимости" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s задоволява зависимостите на %s, но ще бъде деинсталиран" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s задоволява зависимостите на %s, но ще бъде деинсталиран" + +#~ msgid "No need to install %s" +#~ msgstr "Няма нужда от инсталиране на %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "" +#~ "%s не може да бъде инсталиран за задоволяване на зависимостите на %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "" +#~ "%s не може да бъде инсталиран за задоволяване на зависимостите на %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s няма да бъде деинсталиран, защото все още е необходим" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "" +#~ "%s прави ненужен %s, но %s не може да бъде изтрит, защото е заключен." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "%s не може да бъде инсталиран, защото е в конфликт" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s е недеинсталируем поради конфликта с %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "за изисканото %s за %s, когато се обновява %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s липсва изискания %s" + +#~ msgid ", Action: " +#~ msgstr ", Действие:" + +#~ msgid ", Trigger: " +#~ msgstr ", задействане при:" + +#~ msgid "package" +#~ msgstr "пакет" + +#~ msgid "selection" +#~ msgstr "подбор" + +#~ msgid "pattern" +#~ msgstr "шаблон" + +#~ msgid "product" +#~ msgstr "продукт" + +#~ msgid "patch" +#~ msgstr "кръпка" + +#~ msgid "script" +#~ msgstr "скрипт" + +#~ msgid "message" +#~ msgstr "съобщение" + +#~ msgid "atom" +#~ msgstr "атом" + +#~ msgid "system" +#~ msgstr "система" + +#~ msgid "Resolvable" +#~ msgstr "Пакет" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "Маркиране на този опит за разрешаване като невалиден." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "Маркиране на пакета %s като деинсталируем" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s е подготвен за инсталиране, но това не е възможно заради проблеми със " +#~ "зависимости." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "Не може да се инсталира %s след като вече е маркиран за деинсталиране" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "" +#~ "%s не може да се инсталира след като вече не е приложим за тази система." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "Не може да се инсталира %s след като %s вече е маркиран за инсталиране" + +#~ msgid "This would invalidate %s." +#~ msgstr "Това ще направи невалиден %s." + +#~ msgid "Establishing %s" +#~ msgstr "Откриване на %s" + +#~ msgid "Installing %s" +#~ msgstr "Инсталиране на %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "Пропускане на %s: вече е инсталиран" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "Няма инсталирани алтернативни доставчици на %s" + +#~ msgid "for %s" +#~ msgstr "за %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "" +#~ "Не е възможно обновяването към %s за да се избегне премахването на %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s доставя %s, но е планирано за деинсталиране." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s доставя %s, но друга версия на %s вече е инсталирана." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s доставя %s, но е деинсталируем. Опитайте да го инсталирате ръчно за " +#~ "повече подробности." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s доставя %s, но е заключен." + +#, fuzzy +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s доставя %s, но е планирано за деинсталиране." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s доставя %s, но има друга архитектура." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "Не могат да се удовлетворят изискванията на %s за %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "%s се изисква от друг инсталиран пакет и няма да бъде премахнат." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "%s се изисква от друг инсталиран пакет и няма да бъде премахнат." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "" +#~ "Конфликтът с %s (%s) изисква премахването на %s, което е било подготвено " +#~ "за инсталиране" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "Маркиране на %s като деинсталируем поради конфликта с %s" + +#~ msgid "from %s" +#~ msgstr "от %s" + +#~ msgid " Error!" +#~ msgstr " Грешка!" + +#~ msgid " Important!" +#~ msgstr " Важно!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s зависи от %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s е необходим на %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s е необходим на %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s е заменен от %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s е необходим на %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s е част от %s" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s е необходим на %s" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "Пренебрегване на това изискване" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s се изисква от друг, маркиран за инсталиране пакет и няма да бъде " +#~ "премахнат." + +#~ msgid "%s dependend on %s" +#~ msgstr "от %s зависи %s" + +#, fuzzy +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "" +#~ "Проверката на контролната сума за подписания repomd.xml файл бе неушпешна" + +#, fuzzy +#~ msgid "Reading selection from %s" +#~ msgstr "Грешка при четенето на сектор %u." + +# progress indicator label +#, fuzzy +#~ msgid "Reading translation: %s" +#~ msgstr "Зареждане на инсталационната система" + +#~ msgid " miss checksum." +#~ msgstr "липсва контролната сума." + +#~ msgid " fails checksum verification." +#~ msgstr "неуспешно удостоверяване на контролната сума." + +#, fuzzy +#~ msgid "Downloading %s" +#~ msgstr "Грешка при зареждането на %1" + +#~ msgid "%s needed by %s" +#~ msgstr "%s е необходим на %s" + +#~ msgid "Cannot acquire zypp lock." +#~ msgstr "Не може да се придобие заключването на zypp." + +#~ msgid "Can't write the patch script to a temporary file." +#~ msgstr "Не може да се скрипта на кръпката във временен файл." + +#~ msgid "Target commit aborted by user." +#~ msgstr "Целевото извършване бе прекъснато от потребителя." + +#~ msgid "Failed check for the script file check sum" +#~ msgstr "Проверката на контролната сума за скрипта бе неуспешна" + +#~ msgid "Ok" +#~ msgstr "Добре" + +#~ msgid "The package is not OK for the following reasons:" +#~ msgstr "Пакетът не е наред поради следните причини:" + +#~ msgid "The package contains different version than expected" +#~ msgstr "Пакетът съдържа различна от очакваната версия" + +#~ msgid "The package file has incorrect MD5 sum" +#~ msgstr "Файлът на пакета има некоректна MD5 сума" + +#~ msgid "The package has no MD5 sum" +#~ msgstr "Пакетът няма MD5 сума" + +#~ msgid "The package archive has incorrect MD5 sum" +#~ msgstr "Архивът с пакетите има некоректна MD5 сума" + +#~ msgid "rpm failed for unkown reason, see log file" +#~ msgstr "" +#~ "rpm завърши с неуспех поради неизвестна причина, прегледайте файла-дневник" + +#~ msgid "Default" +#~ msgstr "Стандартно" + +#, fuzzy +#~ msgid "ignore architecture" +#~ msgstr "Архитектура" + +#, fuzzy +#~ msgid "Ignore this requirement for all other resolvables." +#~ msgstr "%s е необходим на друг пакет" + +#~ msgid "Deleting %s" +#~ msgstr "Изтриване на %s" + +#~ msgid "" +#~ "Can't install %s, since a resolvable of the same name is already marked " +#~ "as needing to be installed" +#~ msgstr "" +#~ "%s не може да се инсталира, след като пакет със същото име вече е " +#~ "маркиран за инсталиране" + +#~ msgid "%s cannot be uninstalled due missing dependencies" +#~ msgstr "%s не може да бъде деинсталиран поради липсващи зависимости" diff --git a/po/bn.po b/po/bn.po new file mode 100644 index 0000000..41c396f --- /dev/null +++ b/po/bn.po @@ -0,0 +1,5940 @@ +msgid "" +msgstr "" +"Project-Id-Version: @PACKAGE@\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2005-07-29 15:37+0530\n" +"Last-Translator: Priyavert Sharma\n" +"Language-Team: AgreeYa Solutions \n" +"Language: \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" +"\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "অজানা দেশ: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "কোড" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "বিক্রেতা" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "সংযুক্ত আরব আমিরাত" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "পাকিস্তান" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "এন্টিগা ও বারবুডা" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "এংগুইলা" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "আলবেনিয়া" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "আর্জেন্টিনা" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "নেদারল্যান্ড" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "এংগোলা" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "এন্টার্কটিকা" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "আর্জেন্টিনা" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "আমেরিকান সামোয়া" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "অস্ট্রিয়া" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "অস্ট্রেলিয়া" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "আরুবা" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "আজারবাইজান" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "বসনিয়া এবং হারজেগোভিনা" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "বার্বাডোজ" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "বাংলাদেশ" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "বেলজিয়াম" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "বারকিনা ফাসো" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "বুলগেরিয়া" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "বাহরাইন" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "বুরুন্ডি" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "বাহরাইন" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "জার্মান" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "ব্রুনেই দারুসসালাম" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "বলিভিয়া" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "ব্রাজিল" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "পানামা" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "ভুটান" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "বোটসোয়ানা" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "বেলারুস" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "বেলজিয়ান" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "কানাডা" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "কোকোস (কিলিং) দ্বীপপুঞ্জ" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "কনসোল" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "সিরিয়ান আরব প্রজাতন্ত্র" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "সুইজারল্যান্ড" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "কোট ডি'ইভোয়ার" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "চিলি" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "ক্যামেরা" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "চিলি" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "কলম্বিয়া" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "কোস্টারিকা" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "কিউবা" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "কেপ ভার্দে" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "ক্রিসমাষ আইল্যান্ড" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "সাইপ্রাস" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "চেক প্রজাতন্ত্র" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "জার্মানি" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "জিবৌটি" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "ডেনমার্ক" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "রোমানিয়া" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "ডোমেনিকান প্রজাতন্ত্র" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "আলজেরিয়া" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "ইকুয়েডর" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "এস্টোনিয়া" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "মিশর" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "পশ্চিমী সাহারা" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "ইরিট্রিয়া" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "স্পেন" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "এস্টোনিয়া" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "ফিনল্যান্ড" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "ফিজি" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "ফকল্যান্ড আইল্যান্ডস (মালভিনাস)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "ফেডারেটেড স্টেটস অফ মাইক্রোনেশিয়া" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "ফ্রান্স" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "মেট্রোপলিটান ফ্রান্স" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "নিষিদ্ধ" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "যুক্তরাজ্য" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "গ্রীনল্যান্ড" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "জর্জিয়া" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "ফ্রেঞ্চ (কানাডীয়)" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "জার্মানি" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "ঘানা" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "জিব্রাল্টার" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "গ্রীনল্যান্ড" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "&সাম্বা" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "গিনি" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "গুয়াদেলুপ" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "ইকোয়েটেরিয়াল গিনি" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "গ্রীস" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "সাউথ জর্জিয়া ও সাউথ স্যান্ডউইচ আইল্যান্ড" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "গুয়াতেমালা" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "গুয়াতেমালা" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "গিনি-বিসাউ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "গায়ানা" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "হংকং" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "হার্ড আইল্যান্ড ও ম্যাকডোনাল্ড আইল্যান্ডস" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "হন্ডুরাস" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "ক্রোয়েশিয়া" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "হাইতি" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "হাঙ্গেরী" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "ইন্দোনেশিয়া" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "আয়্যারল্যান্ড" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "ইসরাইল" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "ভারত" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "ব্রিটিশ ইন্ডিয়ান ওসান টেরিটরি" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "ইরাক" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "ইরাক" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "আইসল্যান্ড" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "ইটালী" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "জামাইকা" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "জর্ডান" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "জাপান" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "কীবোর্ড" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "কিরগিজস্তান" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "কলম্বিয়া" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "কিরিবাটি" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "কমোরোস" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "সেন্ট কিটস ও নেভিস" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "উত্তর কোরিয়া" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "দক্ষিন আফ্রিকা" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "কুয়েত" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "পাকিস্তান" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "লাও পিপলস ডেমোক্রেটিক রিপাব্লিক" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "লেবানন" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "সষেন্ট লুসিয়া" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "লাইসেন্স" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "শ্রীলঙ্কা" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "লাইবেরিয়া" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "লেসোথো" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "লিথুয়েনিয়া" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "লাক্সেমবার্গ" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "লাতভিয়া" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "লিবিয়া" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "মরোক্কো" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "মরোক্কো" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "স্লোভাক" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "মনিটর" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "সাম মারিনো" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "মাদাগাস্কার" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "ম্যাসেডোনিয়া" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "মালয়শিয়া" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "পানামা" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "মঙ্গোলিয়া" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "প্রধান" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "নর্দার্ন মারিয়ানা আইল্যান্ডস" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "মার্টিনিক" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "লিথুয়েনিয়া" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "মন্টসেরাট" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "মালটা" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "মরিশাস" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "মালদ্বীপ" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "মালটা" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "মেক্সিকো" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "মালয়শিয়া" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "মোজাম্বিক" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "&সাম্বা" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "ম্যাসেডোনিয়া" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "ঘড়ি" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "আলজেরিয়া" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "নিকারাগুয়া" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "নেদারল্যান্ড" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "নরওয়ে" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "নেপাল" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "নাউরু" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "নিউ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "নিউজিল্যান্ড" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "ওমান" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "পানামা" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "পেরু" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "ফ্রেঞ্চ (কানাডীয়)" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "পাপুয়া নিউ গিনি" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "ফিলিপাইন" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "পাকিস্তান" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "পোল্যান্ড" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "সেন্ট পিয়ের ও মিকেলন" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "পাকিস্তান" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "পোর্টোরিকো" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "প্যালেস্টিনিয়ান টেরিটরি" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "পর্তুগাল" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "প্যারাগুয়ে" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "প্যারাগুয়ে" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "কাতার" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "এলাকা (&R)" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "রোমানিয়া" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "খোঁজো" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "রাশিয়ান ফেডারেশন" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "কানাডা" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "সৌদী আরব" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "ফারো দ্বীপপূঞ্জ" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "সেশেলস" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "সুদান" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "সুইডেন" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "সিঙ্গাপুর" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "সেন্ট হেলেনা" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "স্লোভেনিয়া" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "সভালবার্ড ও জান মায়েন" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "স্লোভাকিয়া" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "সিয়েরা লিওন" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "সাম মারিনো" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "সেনেগাল" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "রোমানিয়া" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "সার্ভিসের নাম (&n)" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "সাও টোম ও প্রিন্সিপ" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "এল সালভাদর" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "সিরিয়া" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "থাইল্যান্ড" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "টার্কস ও কাইকোস আইল্যান্ড" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "পরিবর্তিত" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "ফ্রেঞ্চ সাউদার্ন টেরিটোরিজ" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "নিষিদ্ধ" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "থাইল্যান্ড" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "তাজিকিস্তান" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "টকেলাউ" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "তাজিকিস্তান" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "তিউনিশিয়া" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "মোট" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "ইষ্ট টিমর" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "তুর্কী" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ত্রিনিদাদ ও টোবাগো" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "টুভালু" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "তাইওয়ান" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "তানজানিয়া" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "ইউক্রেন" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "কানাডা" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "ইউনাইটেড স্টেটস মাইনর আউটলায়িং আইল্যান্ডস" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "সংযুক্ত আরব আমিরাত" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "উরুগুয়ে" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "উজবেকিস্থান" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "হোলি সি (ভ্যাটিকান সিটি স্টেট)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "সেন্ট ভিনসেন্ট ও গ্রেনাডাইন্স" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "ভেনিজুয়েলা" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "ব্রিটিশ ভার্জিন আইল্যান্ডস" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "ভার্জিন আইল্যান্ডস, ইউ এস" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "ফাইলের নাম" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "ভানুয়াতু" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "ওয়ালিস ও ফুটুনা" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "&সাম্বা" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "ইয়েমেন" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "মেয়ট" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "দক্ষিন আফ্রিকা" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "&সাম্বা" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "জিম্বাবুয়ে" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "প্রয়োজন হয় " + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s প্রাচীন করে দিয়েছে: %sকে" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "এন্ট্রি পাওয়া যায়নি" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "অজ্ঞাত ভাষা: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "আফার" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "আলবেনিয়া" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "ক্রিয়া (&c)" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "আকোলি" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "পরিসীমা" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "এডাইগ" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "আফ্রো-এশিয়াটিক (অন্যান্য)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "আফ্রিহিলি" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "আফ্রিকান্স" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "আইনু" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "আকান" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "আক্কাডিয়ান" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "আলবেনিয়া" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "আলিউট" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "প্রাথমিক ভাষা (&L)" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "দক্ষিন আফ্রিকা" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "আমহারিক" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "ইংরেজী, পুরাতন (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "ভাষাসমূহ" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "আরবী" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "আরামাইক" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "আরাগোনিজ" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "আর্জেন্টিনা" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "ইউক্রেনীয়" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "আরাপাহো" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "নকল (অন্যান্য)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "আরাওয়াক" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "একই" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "অস্ট্রিয়া" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "ইনস্টলকৃত ভাষা" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "আভারিক" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "আভেস্তান" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "অবধী" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "আয়মারা" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "আজারবাইজানি" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "কানাডা" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "ইনস্টলকৃত ভাষা" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "ব্রাজিল" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "বালুচি" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "ক্যামেরা" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "জাপানী" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "বাস্ক" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "ব্রাজিল" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "বালটিক (অন্যান্য)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "বেজা" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "বেলারুস" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "বেম্বা" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "বাংলা" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "বার্বার (অন্যান্য)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "ভোজপুরি" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "বাহরাইন" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "বিকোল" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "বিনি" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "বিসলামা" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "সিকসিকা" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "বানটু (অন্যান্য)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "বোটসোয়ানা" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "ব্রাজিল" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "বাহরাইন" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "ইন্দোনেশিয়া" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "বুলগেরিয়া" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "বুগিনিজ" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "বুলগেরিয়া" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "বাস মাউস " + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "বেলজিয়ান" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "কাড্ডো" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "মধ্য আমেরিকান ইন্ডিয়ান (অন্যান্য)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "ক্যারিব" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "ক্যাটালোনিয়া" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "ককেশীয় (অন্যান্য)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "লেবানন" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "সেল্টিক (অন্যান্য)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "চামোরো" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "চিবচা" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "ক্যাশ" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "চাগাতাই" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "চিলি" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "চুকেসে" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "প্রধান" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "চিনুক জার্গন" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "চোকটাও" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "চিপেওয়ান" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "চেরোকি" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "চার্চ স্লেভিক" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "চুভাশ" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "চেয়েন" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "কোস্টারিকা" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "ধারন করে" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "কোস্টারিকা" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "ক্রেওলস ও ইংরেজী, ইংরেজী-ভিত্তিক (অন্যান্য)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "ক্রেওলস ও পিজিনস ফরাসি-ভিত্তিক (অন্যান্য)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "ক্রেওলস ও পিজিনস পর্তুগিজ-ভিত্তিক (অন্যান্য)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "খালি" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "ক্রিমিয়ান তাতার" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "ক্রেওলস ও পিজিনস (অন্যান্য)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "কাশুবিয়ান" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "কাসিটিক (অন্যান্য)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "চেক" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "ডাকোটা" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "ড্যানিশ" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "ডারগোয়া" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "ডায়াক" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "হার্ডওয়্যার সনাক্ত করো" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "স্লেভ (আথাপাস্কান)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "ডোগরিব" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "ডিস্ক" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "ড্রাইভার" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "ডোগরি" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "দ্রাবিঢ়ীয় (অন্যান্য)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "লোয়ার সরবিয়ান" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "মালটা" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "ডাচ, মধ্য (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "ডাচ্" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ডিউলা" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "জোংখা" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "এফিক" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "ইজিপশিয়ান (প্রাচীন)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "একাজুক" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "এলামাইট" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "ইংরেজি (UK)" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "ইংরেজী, মধ্য (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "অভিজ্ঞ (&E)" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "এস্টোনীয়" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "ইউয়ি" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "এওন্ডো" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "পরিসীমা" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "খালি" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "ফান্টি" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "ফিনল্যান্ড" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "ফিলিপাইন" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "ফিনিশ" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "ফিনো-উগ্রিয়ান (অন্যান্য)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "ফন" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "ফ্রেঞ্চ" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "ফরাসি, মধ্য (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "ফরাসি, পুরাতন (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "শেষ করা হচ্ছে" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "সঙ্কেত" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "ফিনল্যান্ড" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "গা" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "গায়ো" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "গবায়া" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "জার্মান (deadkeys সহ)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "জর্জিয়া" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "জার্মান" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "গ্রীক" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "গিলবার্টিজ" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "গেলিক" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "তুর্কী" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "ইতালীয়" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "ম্যাংক্স" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "জার্মান, মধ্য উচ্চ (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "জার্মান, পুরাতন উচ্চ (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "শব্দ" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "গরোন্টালো" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "গথিক" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "গ্রুপ" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "গ্রীক, প্রাচীন (1453 অবধি)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "গ্রীক, আধুনিক (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "হাঙ্গেরীয়" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "গুজরাটি" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "গুইচ'ইন" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "হাইদা" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "পাকিস্তান" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "হাউসা" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "হাওয়াইয়ান" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "হিব্রু" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "সমস্যা" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "হিলগেনন" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "হিমাচলি" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "ধরন" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "হিটাইট" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "হমং" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "হিরি মটু" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "আপার সার্বিয়ান" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "হাঙ্গেরীয়" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "হুপা" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "ইবন" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "ইগবো" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "আইসল্যান্ডীয়" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ইদো" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "লিথুয়েনিয়া" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ইজো" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "ইনাখটিটাট" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "আভ্যন্তরীণ এলাকা" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "ইলোকো" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "ইন্টারলিঙ্গুয়া (ইন্টারন্যাশনাল অকজিলিয়ারি ল্যাংগুয়েজ অ্যাসোশিয়েশন)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "ইন্ডিক (অন্যান্য)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "ইন্দোনেশিয়া" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "ইন্দো-ইউরোপিয়ান (অন্যান্য)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "ইঙ্গুশ" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "ভারত" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "ইরানি (অন্যান্য)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "প্রাথমিক ভাষা (&L)" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "ইতালীয়" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "জাপানী" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "লেবানন" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "জাপানী" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "জুডেও-পার্সিয়ান" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "জুডেও-আরবী" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "কারা-কালপাক" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "সক্রিয় হয়েছে" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "খোঁজো" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "কলাল্লিসুট" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "&সাম্বা" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "কানাডা" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "বাহরাইন" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "কাশ্মীরি" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "কানুরি" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "কুয়েত" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "কাজাখ" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "কাবারডিয়ান" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "খাসি" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "খয়সান (অন্যান্য)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "ঘড়ি" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "খোটানিজ" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "কিকুয়ু" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "কিনয়ারোয়ান্ডা" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "কিরগিজ" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "ধরন" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "কোঙ্কনী" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "কোমি" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "কঙ্গো" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "জর্ডান" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "কোসরিয়ান" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "একই রাখো" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "কারাচে-বালকার" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "ক্রু" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "তুর্কী" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "পানামা" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "নকল" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "তুর্কী" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "কুয়েত" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "লোড করা হচ্ছে..." + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "কানাডা" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "&সাম্বা" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "লগ" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "লাতভিয়া" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "লাতভিয়া" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "বেলজিয়ান" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "লাক্সেমবার্গ" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "লিঙ্গালা" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "লিথুয়েনিয়ান" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "মনিটর" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "লোজি" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "লাক্সেমবার্গ" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "লুবা-লুলুয়া" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "লুবা-কাটাঙ্গা" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "কানাডা" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "লুইসেনো" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "শব্দ" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "লুও (কেনিয়া ও তানজানিয়া)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "থাইল্যান্ড" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "ম্যাসেডোনিয়া" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "মডিউলসমূহ" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "মাগাহি" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "মারশালিজ" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "মৈথিলি" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "মালয়শিয়া" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "মালয়শিয়া" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "সতর্কবাণী" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "প্রধান" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "অস্ট্রোনেশিয়ান (অন্যান্য)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "মারাঠি" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "মালয়শিয়া" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "মালটা" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "মোক্ষ" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "কানাডা" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "মোড" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "আইরিশ, মধ্য (900-1200) " + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "মি'কমাক" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "মিনাংকাবাউ" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "আপনার ভাষা নির্বাচন করুন:" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "মন-খমের (অন্যান্য)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "মালয়শিয়া" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "মালটা" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "চালু করো (&চ)" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "মণিপুরী" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "মোহক" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "যুগোস্লাভিয়া" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "মঙ্গোলিয়ান" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "মাউস" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "ইনস্টলকৃত ভাষা" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "ভাষাসমূহ" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "গ্রীক" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "মিরান্ডিজ" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "হার্ডওয়্যার তথ্য" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "ইরজিয়া" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "নাহুয়াটি" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "নর্থ আমেরিঅকন ইন্ডিয়ান" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "নিয়াপলিটান" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "নাভাজো" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "এনডেবেলে, দক্ষিণ" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "এনডেবেলে, উত্তর" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "এনডোংগা" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "জার্মান" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "নেপালী" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "নেপাল ভাষা" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "নিয়াস" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "নাইজার-কর্ডোফালিয়ান (অন্যান্য)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "নিউয়ান" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "নরওয়েজিয়ান" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "নরওয়েজিয়ান" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "নগাই" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "নরসে, পুরাতন" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "নরওয়েজিয়ান" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "নর্দার্ন সোথো" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "ক্লাসিকাল নেওয়ারি" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "চিলি" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "নাম" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "নিয়ানকোলে" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "নিয়োরো" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "এনজিমা" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "অক্কিটান 1500 পরবর্তী)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "অজিবোয়া" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "ওড়িয়া" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "ওরোমো" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "একই" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "রাশিয়ান" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "তুর্কী, অটোমান (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "পাপুয়ান (অন্যান্য)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "হাঙ্গেরীয়" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "পহলাভি" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "প্যারাগুয়ে" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "পানামা" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "পাপিয়ামেন্টো" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "প্যারাগুয়ে" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "পার্সিয়ান, পুরাতন (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "ভার্সন " + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "ফিলিপাইন" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "ফোনিসিয়ান" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "পোলিশ" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "পোলিশ" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr " ফোন্পিয়ান " + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "পর্তুগীজ" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "প্রাথমিক ভাষা (&L)" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "প্রভিন্সাল, পুরাতন (1500 অবধি)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "পুশতো" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "কোয়েচুয়া" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "তাজিকিস্তান" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "জাপান" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "রারোটোংগান" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "রোমান্স (অন্যান্য)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "রেটো-রোমান্স" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "রোমানিয়া" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "রোমানিয়া" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "চলছে" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "রাশিয়ান" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "কানাডা" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "পরিসীমা" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "ইয়াকুট" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "দক্ষিণ আমেরিকান ইন্ডিয়ান (অন্যান্য)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "সামারিটান আরামাইক" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "সংস্কৃত" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "সাসাক" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "ক্যাটালোনিয়া" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "খোঁজো" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "সিসিলিয়ান" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "স্তর" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "ক্রোয়েশীয়" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "সাহায্য" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "সেমিটিক (অন্যান্য)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "আইরিশ, পুরাতন (900 অবধি)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "ভাষাসমূহ" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "সুদান" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "সিডামো" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "সিংহল" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "সাইনো-টিবেটান (অন্যান্য)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "স্লেভিক (অন্যান্য)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "স্লোভাক" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "স্লোভেনিয়া" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "দক্ষিণী সামি" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "উত্তরীয় সামি" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "লুলে সামি" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "ইনারি সামি" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "&সাম্বা" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "স্কল্ট সামি" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "স্লোভেনিয়া" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "ধরন" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "চালিয়ে যাও (&চ)" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "সুদান" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "রোমানিয়া" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "সংহাই" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "সোথো, দক্ষিণী" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "স্প্যানিশ" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "ইউক্রেনীয়" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "সার্ভিস" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "নাইলো-সাহারান (অন্যান্য)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "স্পেন" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "সারসংক্ষেপ" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "সুদান" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "SMBus" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "সুদান" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "সোয়াহিলি" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "সুইডিশ" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "সার্ভিস" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "তাইওয়ান" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "তাই (অন্যান্য)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "পরিবার" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "কাতার" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "বেলজিয়াম" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "সময়" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "ট্রী" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Pentium" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "তাজিকিস্তান" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "টাগালগ" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "থাইল্যান্ড" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "তাইওয়ান" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "ট্রী" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "টাইগ্রিনিয়া" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "টিভ" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "ক্লিংগন" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "ট্লিংগিট" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "টামাশেক" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "টোংগা (নায়াসা)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "টোংগা (টোংগা দ্বীপ)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "টোকেন রিং" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "রাশিয়ান" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "বোটসোয়ানা" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "এস্টোনিয়া" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "তুর্কী" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "টুমবুকা" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "ভাষাসমূহ" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "তুর্কী" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "অল্টেইক (অন্যান্য)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "টুই" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "তিউনিশিয়া" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "উডমুর্ট" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "উগারিটিক" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "উইগুর" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "ইউক্রেনীয়" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "উমবুন্ডু" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "অনির্ধারিত" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "উর্দু" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "উজবেকিস্থান" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "ভাই" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "বিক্রেতা" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "ফাইলের নাম" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "ভোলাপুক" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "জয়স্টিক" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "ওয়ালামো" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "প্যারাগুয়ে" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "ওয়াশো" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "ওয়েলশ" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "ভাষা সংরক্ষন করা হচ্ছে..." + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "ওয়ালুন" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "উওলফ" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "কালমাইক" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "জোসা" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "ইয়াও" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "জাপানী" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "ইদ্দিশ" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "ইওরুবা" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "ভাষাসমূহ" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "জ্যাপোটেক" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "জেনাগা" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "পরিবর্তিত" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "পরিসীমা" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "জুলু" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "জুনি" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1' নেই" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1' নেই" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "অজানা" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "অজানা" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "অবৈধ Url যোজনা %s" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, fuzzy, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "সত্যতা যাচাইয়ের ধরন" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "ডায়রেক্টরি %1: %2 তৈরী করা যাচ্ছে না" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "'%s' ডেস্কটপ বস্তু খুলতে পারে না" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "রপ্তানি ফাইলনাম অবৈধ৷" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "লেখার জন্যে ফাইল খুলতে পারে না।" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "ফ্লপি ডিস্ক থেকে পড়ায় ত্রুটি।" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "সংস্থান পুনঃস্থাপন করছে" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "'%s' ডেস্কটপ বস্তু খুলতে পারে না" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "এগিয়ে যাবেন?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"%s প্যাকেজের শুদ্ধতা যাচাই ব্যর্থ হয়েছে। আপনি কি এটাকে পুনরায় ডাউনলোড করার চেষ্টা " +"করতে চান?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"%s প্যাকেজের শুদ্ধতা যাচাই ব্যর্থ হয়েছে। আপনি কি এটাকে পুনরায় ডাউনলোড করার চেষ্টা " +"করতে চান?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm যাচাই ব্যর্থ হয়েছে।" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm ব্যর্থ হয়েছে।" + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "সংস্থানের প্রকার VAR1 পরিবর।তন দেখান বৈশিষ্ট্যকে সমর্থন করে না" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "%s থেকে %s প্রদান করতে পারে না" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "রিপোসিটারিতে ফাইল %1 পাওয়া যায়নি" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "ফাইল তৈরী করা যাচ্ছে না" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "কিছু অমীমাংসিত আবশ্যকতা আছে..." + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "কিছু অমীমাংসিত আবশ্যকতা আছে..." + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "এর সাথে সংযোগের অনুরোধ: " + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "নির্ভরতা সমস্যাগুলির কারণে %s স্থাপন করতে পারে না" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "কোনওটাই %s প্রদান করে না" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "%s এর কোনও বিকল্প স্থাপনযোগ্য প্রদানকারী নেই" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "%s এর কোনও বিকল্প স্থাপনযোগ্য প্রদানকারী নেই" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "ইতিমধ্যে এই অনুরোধ করা হয়ে গিয়েছে" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "নির্দেশমত স্থাপনা বাতিল করা হয়েছে।" + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "সম্পাদন করুন" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "কী এনক্রিপশনে ত্রুটি" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "ব্যর্থ" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr " %s-এর জন্য পরিবর্তিত কনফিগারেশন ফাইলসমূহ :" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm %s কে %sরূপে সংরক্ষণ করেছিল ,কিন্তু পার্থক্য নিরূপণ করা অসম্ভব হয়েছিল " + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm %s কে %sরূপে সংরক্ষণ করেছিল।\n" +"এখানে পার্থক্যের প্রথম ২৫ টি লাইন দেওয়া আছে:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm %s কে %sরূপে সংরক্ষণ করেছিল ,কিন্তু পার্থক্য নিরূপণ করা অসম্ভব হয়েছিল " + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm %s কে %sরূপে তৈরি করেছিল।\n" +"এখানে পার্থক্যের প্রথম ২৫ টি লাইন দেওয়া আছে:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "অতিরিক্ত তথ্য" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "%s ব্যাকআপ তৈরী করছে" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "এন্ট্রি পাওয়া যায়নি" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "এন্ট্রি পাওয়া যায়নি" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "এন্ট্রি পাওয়া যায়নি" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "ফাইল খোলা যাচ্ছে না %1." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "অবৈধ LDAP URL অনুসন্ধান স্ট্রিং" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "অবৈধ LDAP URL অনুসন্ধান প্যারামিটার '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Url অনজেক্ট ক্লোন করতে অক্ষম" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "অবৈধ খালি Url অবজেক্ট রেফারেন্স" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Url কম্পোনেন্ট পার্স করতে অক্ষম" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url যোজনা %s এর অনুমতি দেয় না" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "অবৈধ %s কম্পোনেন্ট %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "অবৈধ %s কম্পোনেন্ট" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "এই URL এর জন্যে স্ট্রিং পার্সিং সমর্থিত নয়" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url যোজনা একটি আবশ্যিক কম্পোনেন্ট" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "অবৈধ Url যোজনা %s" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url যোজনা ব্যবহারকারীর নামের অনুমতি দেয় না" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url যোজনা পাসওয়ার্ডের অনুমতি দেয় না" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url যোজনার জন্য হোস্ট কম্পোনেন্ট" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url যোজনা হোস্ট কম্পোনেন্ট-এর অনুমতি দেয় না" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "অবৈধ হোস্ট কম্পোনেন্ট '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url যোজনা পোর্টের অনুমতি দেয় না" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "অবৈধ পোর্ট কম্পোনেন্ট '%s' " + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url যোজনার জন্য পথের নাম দরকার" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "অথরিটি বিদ্যমান থাকলে রিলেটিভ পথের অনুমতি নেই" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "এনকোডেড স্ট্রিংয়ে NUL বাইট আছে" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "অবৈধ প্যারামিটার এরে স্প্লিট সেপারেটর ক্যারেক্টার" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "অবৈধ প্যারামিটার ম্যাপ স্প্লিট সেপারেটর ক্যারেক্টার" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "অবৈধ প্যারামিটার এরে জয়েন সেপারেটর ক্যারেক্টার" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "সংযোগ সাধনের সময়ে আদেশ সম্পন্ন হয়েছে" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "%s খুঁজে পায় না।" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "%s খুঁজে পায় না।" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "%s খুলতে পারে নি - %s\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "মডিউল\"%s\" লোড করতে অসফল হয়েছে।" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "রিপোসিটারিতে ফাইল %1 পাওয়া যায়নি" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr " ফাইলে লেখা যাচ্ছে না %1." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 ডায়রেক্টরি না" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr " CA নাম শূণ্য" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "অবৈধ URL প্রকল্প '%1'৷" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "'%s' ডেস্কটপ বস্তু খুলতে পারে না" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "অনুমতি প্রত্যাখ্যাত" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "হ্যাঁ" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "না" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "পূর্বাভাস" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "ত্রুটি" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "ইন্দোনেশিয়া" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "ভুল" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "পূর্বাভাস" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "স্টর্টিং..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "পাওয়া যায় নি" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "হ্যাঁ" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "না" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s %s প্রদান করে, কিন্তু এটার অন্য একটা আর্কিটেকচার আছে।" + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "প্যাকেজ আনইনস্টল করার আদেশ" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "কোনওটাই %s প্রদান করে না" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "সার্টিফিকেট %1 অনুপস্থিত" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s লক করা আছে এবং আনইন্সটল করা যাবে না ।" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "ইনস্টল করা হয় নি" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s এর %s দরকার" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "in/ssTklইনস্টল করা যাবে না" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s-এর সঙ্গে %s-এর দ্বন্দ্ব" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s %sকে প্রাচীন করে দিয়েছে" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s %sকে প্রাচীন করে দিয়েছে" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s-এর সঙ্গে %s-এর দ্বন্দ্ব" + +#~ msgid "do not install %s" +#~ msgstr "%s ইন্সটল করে না" + +#~ msgid "keep %s" +#~ msgstr "%s রাখুন" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "%s ইন্সটল করে না" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "%s এর কোনও বিকল্প স্থাপনযোগ্য প্রদানকারী নেই" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "%1 এর দ্বন্দ্ব %2 এর সাথে" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s %s প্রদান করে, কিন্তু এটার অন্য একটা আর্কিটেকচার আছে।" + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "%s স্থাপন করুন যদিও এটা আর্কিটেকচার পালটে দেবে" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s %sকে প্রাচীন করে দিয়েছে" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "%s থেকে %s ডাউনলোড করেছে" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "স্থাপন" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "ফাইল খোলা যাচ্ছে না %1." + +#~ msgid "Hal Exception" +#~ msgstr "Hal ব্যতিক্রম" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext সংযুক্ত নয়" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive চালু নেই" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume চালু নেই" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "dbus সংযোগ তৈরি করতে অক্ষম" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: libhal কনটেক্সট তৈরি করতে পারে না" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: dbus সংযোগ নির্দিষ্ট করতে পারে না" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "HAL কনটেক্সট চালু করতে পারে না -- hald চলছে না?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "CDROM ড্রাইভ নয়" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "মিউটেক্স বৈশিষ্ট্য চালু করতে পারে না" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "রিকার্সিভ মিউটেক্স বৈশিষ্ট্য নির্দিষ্ট করতে পারে না" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "রিকার্সিভ মিউটেক্স চালু করতে পারে না" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "মিউটেক্স লক অর্জন করতে পারে না" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "মিউটেক্স লক মুক্ত করতে পারে না" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "পাব্লিক কী পাওয়া যাচ্ছে না" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "ইনস্টল করা হয় নি" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "%s খুলতে পারে নি - %s\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "সার্বিয়া ও মন্টেনেগ্রো" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "অজ্ঞাত তালিকাবিকল্প" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "নির্ভরতাগুলির সমাধান করতে পারে নি" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s ফাইলের কোনও চেকসাম নেই।\n" +#~ "তবুও ফাইলটি ব্যবহার করতে চান?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "নিচের কি দ্বারা %s ফাইলের শুদ্ধতা যাচাই ব্যর্থ হয়েছে:\n" +#~ "%s|%s|%s\n" +#~ "তবুও ফাইলটি ব্যবহার করতে চান?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s ফাইলের একটি অবৈধ চেকসাম আছে।\n" +#~ "%s প্রত্যাশিত ছিল, পাওয়া গেছে %sতবুও ফাইলটি ব্যবহার করতে চান?" + +#, fuzzy +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s ফাইলের একটি অজ্ঞাত চেকসাম আছে ।\n" +#~ "তবুও ফাইলটি ব্যবহার করতে চান?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "%s স্বাক্ষরিত নয়।\n" +#~ "তবুও ব্যবহার করতে চান?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "ফাইল %s একটি অজ্ঞাত কি দ্বারা স্বাক্ষরিত:\n" +#~ "%s|%s|%s\n" +#~ "তবুও ফাইলটি ব্যবহার করতে চান?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "অবিশ্বস্ত কি পাওয়া গেছে:\n" +#~ "%s|%s|%s\n" +#~ "কি-য়ের উপরে বিশ্বাস করবেন?" + +#~ msgid "%s remove failed" +#~ msgstr "%s অপসারণ ব্যর্থ হয়েছে" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "পাসওয়ার্ড পরিবর্তন" + +#~ msgid "rpm output:" +#~ msgstr "rpm আউটপুট" + +#~ msgid "%s install failed" +#~ msgstr "%s ইন্সটল ব্যর্থ হয়েছে " + +#~ msgid "%s installed ok" +#~ msgstr "%s ইন্সটল ঠিক আছে" + +#~ msgid "%s remove ok" +#~ msgstr "%s অপসারণ ঠিক আছে" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "%s এই নির্ভরতা প্রদান করে কিন্তু স্থাপিত আইটেমের আর্কিটেকচার পালটে দেবে " + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "%s এই নির্ভরতা প্রদান করে কিন্তু স্থাপিত আইটেমের আর্কিটেকচার পালটে দেবে " + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "%1 এর দ্বন্দ্ব %2 এর সাথে" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "%s ইতোমধ্যেই স্থাপিত হওয়া নির্দিষ্ট রয়েছে, এই বিষয়টি উপেক্ষা করুন" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "%s-এ অপ্রচলিত %s অগ্রাহ্য করুন" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%s এর দ্বন্দ্ব অগ্রাহ্য করুন" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "কিছু অমীমাংসিত আবশ্যকতা আছে..." + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "%s স্থাপন করুন যদিও এটা আর্কিটেকচার পালটে দেবে" + +#~ msgid "Install missing resolvables" +#~ msgstr "ড্রাইভার ইনস্টল করা হচ্ছে..." + +#~ msgid "Keep resolvables" +#~ msgstr "ড্রাইভার ইনস্টল করা হচ্ছে..." + +#~ msgid "Unlock these resolvables" +#~ msgstr "%1 এর দ্বন্দ্ব %2 এর সাথে" + +#~ msgid "delete %s" +#~ msgstr "%s মুছে ফেলুন" + +#~ msgid "install %s" +#~ msgstr "%s ইনস্টল করুন" + +#~ msgid "unlock %s" +#~ msgstr "%s আনলক করে" + +#~ msgid "unlock all resolvables" +#~ msgstr "%1 এর দ্বন্দ্ব %2 এর সাথে" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "ফাইল খোলা যাচ্ছে না %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "সেক্টর %u পড়ায় ত্রুটি।" + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "এই URL এর জন্যে পথ প্যারামিটার পার্সিং সমর্থিত নয়" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "এই URL এর জন্যে পথ প্যারামিটার পার্সিং সমর্থিত নয়" + +#~ msgid "Software management is already running." +#~ msgstr "সফ্টওয়্যার ম্যানেজমেন্ট ইতোমধ্যেই চলছে।" + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s প্রতিস্থাপিত হয়েছে %s দ্বারা" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s প্রতিস্থাপিত হয়েছে %s দ্বারা" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "এই রিজলভেবলগুলি সিস্টেম থেকে মুছে দেওয়া হবে।" + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s বিস্থাপিত হবে না কারণ এটার এখনও প্রয়োজন আছে" + +#~ msgid "Invalid information" +#~ msgstr "অবৈধ তথ্য" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "অন্যান্য রিজলভেবলের %s প্রয়োজন" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "এর %s দরকার:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "অন্যান্য বিশ্লেষ্যগুলির সঙ্গে %s এর দ্বন্দ্ব" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s-এর সঙ্গে দ্বন্দ্ব :\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s অন্যান্য রিজলভেবলগুলিকে প্রাচীন করে দিয়েছে" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "এই রিজলভেবলগুলি সিস্টেম থেকে মুছে দেওয়া হবে।" + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s অন্য রিজলভেবলগুলির উপরে নির্ভর করে" + +#~ msgid "%s depends on %s" +#~ msgstr "%s নির্ভর করে %s এর উপরে" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s নির্ভর করে এর উপরে: %s" + +#~ msgid "Child of" +#~ msgstr "এর সন্তান" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "এমন কোনও সংস্থান উপলব্ধ নেই যা এই প্রয়োজনটিকে সমর্থন করে" + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "এই রেজলিউশনের উপরে/নিচে বর্ণিত সমস্যাগুলি সমস্ত নির্ভরতাগুলির সমাধান করবে না" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%s স্থাপন করতে পারে না কারণ এটা %s এর সাথে বিবাদ তৈরি করছে" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s ইন্সটল করা নেই এবং আনইন্সটল হিসাবে চিহ্নিত করা হয়েছে" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s এর অপূর্ণ প্রয়োজন আছে" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s এর হারিয়ে যাওয়া নির্ভরশীলগুলি আছে" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "হারিয়ে যাওয়া নির্ভরশীলগুলির জন্য %s ইন্সটল করা যাবে না" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s %s এর নির্ভরতাগুলি পূরণ করে কিন্তু বিস্থাপিত হবে" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s %s এর নির্ভরতাগুলি পূরণ করে কিন্তু একে আপনার সিস্টেমে রাখা হবে" + +#~ msgid "No need to install %s" +#~ msgstr "%s ইন্সটল করার প্রয়োজন নেই" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "%s এর নির্ভরতাগুলি পূরণ করার জন্যে %s স্থাপন করতে পারে না" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "%s এর নির্ভরতাগুলি পূরণ করার জন্যে %s স্থাপন করতে পারে না" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s বিস্থাপিত হবে না কারণ এটার এখনও প্রয়োজন আছে" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "" +#~ "%s %s কে প্রাচীন করে দিয়েছে। কিন্তু %s মুছে দেওয়া যায় না কারণ এটা লক হয়ে আছে।" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "%s স্থাপন করতে পারে না কারণ এটা বিবাদ তৈরি করছে" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s এর সঙ্গে দ্বন্দ্বের জন্য %s ইন্সটল করার অযোগ্য" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "%s উন্নীত করার সময়ে %s এর জন্যে %s এর প্রয়োজনের জন্যে" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s %s প্রয়োজন হারিয়ে ফেলছে" + +#~ msgid ", Action: " +#~ msgstr "ক্রিয়া (&A)" + +#~ msgid ", Trigger: " +#~ msgstr ", ট্রিগার:" + +#~ msgid "package" +#~ msgstr "প্যাকেজ" + +#~ msgid "selection" +#~ msgstr "নির্বাচন" + +#~ msgid "pattern" +#~ msgstr "ধাঁচ" + +#~ msgid "product" +#~ msgstr "পণ্য" + +#~ msgid "patch" +#~ msgstr "প্যাচ" + +#~ msgid "script" +#~ msgstr "স্ক্রিপ্ট" + +#~ msgid "message" +#~ msgstr "বার্তা" + +#~ msgid "atom" +#~ msgstr "অণু" + +#~ msgid "system" +#~ msgstr "ব্যবস্থা" + +#~ msgid "Resolvable" +#~ msgstr "রিজলভেবল" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "এই রেজলিউশন প্রচেষ্টাকে অবৈধ রূপে চিহ্নিত করা হচ্ছে।" + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "%s রিজলভেবলকে বিস্থাপনের অযোগ্য রূপে চিহ্নিত করা হচ্ছে" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s স্থাপিত হওয়ার পরিকল্পনা আছে, কিন্তু নির্ভরতা সমস্যার কারণে এটা সম্ভব হচ্ছে না।" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "%s স্থাপন করতে পারে না যেহেতু এটা ইতোমধ্যেই বিস্থাপিত হওয়া প্রয়োজন বলে চিহ্নিত " +#~ "হয়েছে" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "%s স্থাপন করতে পারে না যেহেতু এটা এই ব্যবস্থার প্রতি প্রযোজ্য নয়।" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "%s স্থাপন করতে পারে না যেহেতু %s ইতোমধ্যেই স্থাপিত হওয়া প্রয়োজন বলে চিহ্নিত " +#~ "হয়েছে " + +#~ msgid "This would invalidate %s." +#~ msgstr "এটা %s কে অবৈধ করে দেবে।" + +#~ msgid "Establishing %s" +#~ msgstr "%s স্থাপন করছে" + +#~ msgid "Installing %s" +#~ msgstr "ইনস্টল করা হচ্ছে %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "%sকে %s এ উন্নীত করছে" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "%s ডিঙিয়ে যাচ্ছে :আগে থেকেই ইনস্টল করা আছে" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "%s এর কোনও বিকল্প স্থাপিত প্রদানকারী নেই" + +#~ msgid "for %s" +#~ msgstr "%s এর জন্য" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "%s অপসারণ এড়ানোর জন্যে %s এ উন্নীত হওয়া সম্ভব নয়।" + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s %s প্রদান করে, কিন্তু এটা বিস্থাপিত হওয়ার সূচী আছে।" + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s %s প্রদান করে, কিন্তু এই %s এর অপর একটি ভার্সন ইতোমধ্যেই স্থাপিত আছে।" + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s %s প্রদান করে, কিন্তু এটা বিস্থাপনযোগ্য নয়। আরও বিবরণের জন্যে এটাকে নিজে " +#~ "থেকে স্থাপনের চেষ্টা করুন। " + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s %s প্রদান করে, কিন্তু এটা লক হয়ে আছে।" + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s %s প্রদান করে, কিন্তু এটা রক্ষিত হওয়ার সূচী আছে।" + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s %s প্রদান করে, কিন্তু এটার অন্য একটা আর্কিটেকচার আছে।" + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "%s এর জন্য %s এর প্রয়োজন পূরণ করতে পারে না" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "অন্যান্য স্থাপিত রিজলভেবলের জন্য %s দরকার, তাই এটা আনলিঙ্কড হবে না। " + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "অন্যান্য স্থাপিত রিজলভেবলের জন্য %s দরকার, তাই এটা আনলিঙ্কড হবে না। " + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "%s (%s) নিয়ে বিবাদের জন্যে অন্যান্য স্থাপিত হতে চলা %s অপসারণের প্রয়োজন" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "%s নিয়ে বিবাদের কারণে %s কে বিস্থাপনের অযোগ্য রূপে চিহ্নিত করা হচ্ছে" + +#~ msgid "from %s" +#~ msgstr "%s থেকে" + +#~ msgid " Error!" +#~ msgstr "ত্রুটি" + +#~ msgid " Important!" +#~ msgstr "জরুরি!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s নির্ভর করে %s এর উপরে" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s এর %s দরকার" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s এর %s দরকার" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s প্রতিস্থাপিত হয়েছে %s দ্বারা" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s এর %s দরকার" + +#~ msgid "%s part of %s" +#~ msgstr "%s, %s এর অঙ্গ" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s এর %s দরকার" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "Url অথরিটি পার্স করতে অক্ষম" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "কিছু অমীমাংসিত আবশ্যকতা আছে..." + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "অন্যান্য স্থাপিত হতে চলা রিজলভেবলের জন্য %s দরকার, তাই এটা আনলিঙ্কড হবে না। " + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "আপডেট স্থাপনা সম্পাদনের জন্যে প্রয়োজনীয় ফাইল তৈরি করতে পারে না।" + +#~ msgid "Unable to restore all sources." +#~ msgstr "সকল উত্‍সগুলি পুনরুদ্ধার করতে অক্ষম।" + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "কমপক্ষে একটি উত্‍স ইতোমধ্যেই নথিবদ্ধ আছে, সঞ্চিত উত্‍সটি পুনরুদ্ধার করা যায় না।" + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "%s এর নির্ভরতাগুলি পূরণ করার জন্যে %s স্থাপন করা যায় না" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s নির্ভর করে %s এর উপরে" + +#~ msgid "Reading index files" +#~ msgstr "সূচীপত্র ফাইল পড়ছে" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "স্বাক্ষরিত repomd.xml ফাইল স্বাক্ষর যাচাইয়ে ব্যর্থ হয়েছে।" + +#~ msgid "Reading product from %s" +#~ msgstr "%s থেকে পণ্য পড়ছে" + +#~ msgid "Reading filelist from %s" +#~ msgstr "%s থেকে ফাইলতালিকা পড়ছে" + +#~ msgid "Reading packages from %s" +#~ msgstr "%s থেকে প্যাকেজ পড়ছে" + +#~ msgid "Reading selection from %s" +#~ msgstr "%s থেকে নির্বাচন পড়ছে" + +#~ msgid "Reading pattern from %s" +#~ msgstr "%s থেকে প্যাটার্ন পড়ছে" + +#~ msgid "Reading patches index %s" +#~ msgstr "%s প্যাচ ইনডেক্স পড়ছে" + +#~ msgid "Reading patch %s" +#~ msgstr "%s প্যাচ পড়ছে" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "স্ক্রিপ্ট ফাইল চেকসাম পরীক্ষায় ব্যর্থ হয়েছে" + +#~ msgid "Reading packages file" +#~ msgstr "প্যাকেজ ফাইল পড়ছে" + +#~ msgid "Reading translation: %s" +#~ msgstr "অনুবাদ পড়ছে: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "%s প্যাকেজের শুদ্ধতা যাচাই ব্যর্থ হয়েছে। আপনি কি এটাকে পুনরায় ডাউনলোড করার " +#~ "চেষ্টা করতে চান, নাকি স্থাপনা বাতিল করবেন?" + +#~ msgid " miss checksum." +#~ msgstr " অবুপস্থিত চেকসাম।" + +#~ msgid " fails checksum verification." +#~ msgstr "চেকসাম এর শুদ্ধতা যাচাই ব্যর্থ হয়েছে" + +#~ msgid "Downloading %s" +#~ msgstr "%s ডাউনলোড করছে" diff --git a/po/bs.po b/po/bs.po new file mode 100644 index 0000000..22338a7 --- /dev/null +++ b/po/bs.po @@ -0,0 +1,5855 @@ +# Bosnian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2001 SuSE GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Damir Bjelobradic , 2001. +# Amila Akagic , 2002. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2002-07-23 18:27+0200\n" +"Last-Translator: Damir Bjelobradic \n" +"Language-Team: Bosnian \n" +"Language: bs\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +#, fuzzy +msgid "No Code" +msgstr "nobody" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andora" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Ujedinjeni Arapski Emirati" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua i Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanija" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenija" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Nizozemski Antili" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktik" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Američka Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austrija" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australija" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +#, fuzzy +msgid "Aland Islands" +msgstr "Kajmanska ostrva" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbejdžan" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosna i Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +# BD +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladeš" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgija" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bugarska" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrein" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Bruneji" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivija" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazil" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahami" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Butan" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Ostrvo Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Bocvana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Bjelorusija" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosova ostrva" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "Centralnoafrička Republika" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Švicarska" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +#, fuzzy +msgid "Cote D'Ivoire" +msgstr "Obala Slonovače" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cook ostrva" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Čile" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbija" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kosta Rika" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Zelenortsko otočje" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Uskršnje ostrvo" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Kipar" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Češka Republika" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Njemačka" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Džibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danska" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominikanska Republika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikanska Republika" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algerija" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonija" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipat" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Zapadna Sahara" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritreja" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Španija" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopija" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finska" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandsko otočje" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faroe Otoci" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francuska" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Ujedinjeno Kraljevstvo (Velika Britanija)" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Džordžija" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Francuska Gvineja" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Njemačka" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Greenland" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambija" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Gvineja" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadelupa" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatorijalna Gvineja" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grčka" + +# GS +# fuzzy +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "South Georgia i South Sandwich ostrvo" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Gvineja Bisau" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Gvajana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +#, fuzzy +msgid "Heard Island and McDonald Islands" +msgstr "Heard ostrvo i McDonaldova ostrva" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Hondoras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Hrvatska" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Mađarska" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesija" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irska" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indija" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britansko-Indijska morska teritorija" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irak" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Iceland" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italija" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamajka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenija" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgistan" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambođa" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komori" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +#, fuzzy +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts and Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +#, fuzzy +msgid "North Korea" +msgstr "Sjeverna Irska" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +#, fuzzy +msgid "South Korea" +msgstr "Južni pol" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuvajt" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kajmanska ostrva" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazahstan" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +#, fuzzy +msgid "Lao People's Democratic Republic" +msgstr "Lao Narodna Demokratska Republika" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +#, fuzzy +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Linhenštajn" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Šri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberija" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesoto" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litvanija" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvija" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Liberija" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Moroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +# CG +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "Kongo" + +# SM +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "San Marino" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Maršalova ostrva" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonija" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolija" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makao" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Sjeverna Marijanska ostrva" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinik" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritanija" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauricijus" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Mali" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malavi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malezija" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibija" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nova Kaledonija" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk ostrvo" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigerija" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragva" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nizozemska" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norveška" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Novi Zeland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Francuska Polinezija" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nova Gvineja" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipini" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poljska" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +#, fuzzy +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre and Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitkairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Riko" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +#, fuzzy +msgid "Palestinian Territory" +msgstr "Britansko-Indijska morska teritorija" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paragvaj" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumunija" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "Srpski" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Ruska Federacija" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudijska Arabija" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomoska ostrva" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Sejšelsko otočje" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Švedska" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Saint Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenija" + +# SJ +# fuzzy +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard and Jan Mayen ostrva" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovačka" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalija" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome i Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Surinam" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Svazilend" + +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +#, fuzzy +msgid "Turks and Caicos Islands" +msgstr "Turks i Caicos ostrva" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Čad" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +#, fuzzy +msgid "French Southern Territories" +msgstr "Francuske Južne Teritorije" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tajland" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistan" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turska" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad i Tobago" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +# TW +# fuzzy +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tajland" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +#, fuzzy +msgid "Tanzania" +msgstr "Tasmanija" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrajina" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "United States Minor Outlying Islands" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "SAD" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Urugvaj" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikan (Sveta Zemlja)" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +#, fuzzy +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent and the Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venecuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +#, fuzzy +msgid "British Virgin Islands" +msgstr "Djevičansko otočje (U.S.)" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Djevičansko otočje (U.S.)" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vijetnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis i Futuna ostrva" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Južna Afrika" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambija" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabve" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "Izbrii" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +#, fuzzy +msgid "Afar" +msgstr "Afrika" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Azerbejdđanski" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +#, fuzzy +msgid "Achinese" +msgstr "Kineski" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +#, fuzzy +msgid "Akan" +msgstr "Azerbejdđanski" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +#, fuzzy +msgid "Akkadian" +msgstr "Azerbejdđanski" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +#, fuzzy +msgid "Albanian" +msgstr "Albanija" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +#, fuzzy +msgid "Aleut" +msgstr "Aleuta" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +#, fuzzy +msgid "Algonquian Languages" +msgstr "Odaberite vaš jezik:" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "Južna Afrika" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +#, fuzzy +msgid "Amharic" +msgstr "Afrika" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +#, fuzzy +msgid "Apache Languages" +msgstr "Jezik" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arapski" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +#, fuzzy +msgid "Aramaic" +msgstr "Arapski" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +#, fuzzy +msgid "Armenian" +msgstr "Armenija" + +# MR +#. language code: arn +#: zypp/LanguageCode.cc:211 +#, fuzzy +msgid "Araucanian" +msgstr "Mauritanija" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +#, fuzzy +msgid "Assamese" +msgstr "Poruke" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +#, fuzzy +msgid "Asturian" +msgstr "Austrija" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +#, fuzzy +msgid "Athapascan Languages" +msgstr "Australija" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +#, fuzzy +msgid "Australian Languages" +msgstr "Australija" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +#, fuzzy +msgid "Avaric" +msgstr "Arapski" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +#, fuzzy +msgid "Avestan" +msgstr "Aleuta" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +#, fuzzy +msgid "Aymara" +msgstr "Myanmar" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbejđanski" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +#, fuzzy +msgid "Banda" +msgstr "Kanada" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +#, fuzzy +msgid "Bamileke Languages" +msgstr "Jezik" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +#, fuzzy +msgid "Bashkir" +msgstr "Brazil" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +#, fuzzy +msgid "Bambara" +msgstr "Smarkand" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +#, fuzzy +msgid "Balinese" +msgstr "Kineski" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskijski" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +#, fuzzy +msgid "Basa" +msgstr "Baskijski" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bjeloruski" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +#, fuzzy +msgid "Bemba" +msgstr "Bermuda" + +# SN +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +#, fuzzy +msgid "Bengali" +msgstr "Senegal" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +#, fuzzy +msgid "Bihari" +msgstr "Bahrein" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +# BJ +#. language code: bin +#: zypp/LanguageCode.cc:273 +#, fuzzy +msgid "Bini" +msgstr "Benin" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +# BJ +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +#, fuzzy +msgid "Bosnian" +msgstr "Benin" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +#, fuzzy +msgid "Braj" +msgstr "Brazil" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonski" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +#, fuzzy +msgid "Batak (Indonesia)" +msgstr "Indonesija" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +#, fuzzy +msgid "Buriat" +msgstr "Bugarska" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +#, fuzzy +msgid "Buginese" +msgstr "Kineski" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bugarski" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +#, fuzzy +msgid "Blin" +msgstr "Belgijski" + +# TD +#. language code: cad +#: zypp/LanguageCode.cc:301 +#, fuzzy +msgid "Caddo" +msgstr "Čad" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +#, fuzzy +msgid "Carib" +msgstr "Maorski" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalanski" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +#, fuzzy +msgid "Cebuano" +msgstr "Libanon" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +#, fuzzy +msgid "Chamorro" +msgstr "Komori" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +#, fuzzy +msgid "Chibcha" +msgstr "Kina" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +#, fuzzy +msgid "Chechen" +msgstr "Češki" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +#, fuzzy +msgid "Chagatai" +msgstr "Šangaj" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kineski" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +#, fuzzy +msgid "Chuukese" +msgstr "Kineski" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +#, fuzzy +msgid "Mari" +msgstr "Maorski" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "Jezik" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +#, fuzzy +msgid "Coptic" +msgstr "Kosta Rika" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +#, fuzzy +msgid "Cornish" +msgstr "Irski" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +#, fuzzy +msgid "Corsican" +msgstr "Kosta Rika" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +#, fuzzy +msgid "Cree" +msgstr "&Napravi" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Češki" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +#, fuzzy +msgid "Dakota" +msgstr "Dakar" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danski" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +#, fuzzy +msgid "Dargwa" +msgstr "Darvin" + +#. language code: day +#: zypp/LanguageCode.cc:379 +#, fuzzy +msgid "Dayak" +msgstr "Dakar" + +#. language code: del +#: zypp/LanguageCode.cc:381 +#, fuzzy +msgid "Delaware" +msgstr "Hardware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +#, fuzzy +msgid "Dinka" +msgstr "Dominikanska Republika" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +#, fuzzy +msgid "Dogri" +msgstr "Maorski" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +#, fuzzy +msgid "Lower Sorbian" +msgstr "Srpski" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +#, fuzzy +msgid "Duala" +msgstr "Palau" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Holandski" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +#, fuzzy +msgid "Dyula" +msgstr "Dubai" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +#, fuzzy +msgid "Dzongkha" +msgstr "Tonga" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engleski" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonski" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +#, fuzzy +msgid "Fang" +msgstr "Zastave" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +#, fuzzy +msgid "Faroese" +msgstr "Faroe Otoci" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +#, fuzzy +msgid "Fanti" +msgstr "Atlantik" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +#, fuzzy +msgid "Fijian" +msgstr "Fidži" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +#, fuzzy +msgid "Filipino" +msgstr "Filipini" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finski" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francuski" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +#, fuzzy +msgid "Frisian" +msgstr "Francuska" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +#, fuzzy +msgid "Fulah" +msgstr "Zastave" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +#, fuzzy +msgid "Friulian" +msgstr "Finska" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +#, fuzzy +msgid "Ga" +msgstr "Guam" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +#, fuzzy +msgid "Gayo" +msgstr "Gabon" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +#, fuzzy +msgid "Gbaya" +msgstr "Gaza" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +#, fuzzy +msgid "Germanic (Other)" +msgstr "Njemački (Swiss)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +#, fuzzy +msgid "Georgian" +msgstr "Džordžija" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Njemački" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +#, fuzzy +msgid "Geez" +msgstr "Grčki" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +#, fuzzy +msgid "Gilbertese" +msgstr "Vijetnamski" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +#, fuzzy +msgid "Gaelic" +msgstr "Mali" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irski" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +#, fuzzy +msgid "Galician" +msgstr "Vatikan" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +#, fuzzy +msgid "Manx" +msgstr "Manila" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +# GA +#. language code: gon +#: zypp/LanguageCode.cc:491 +#, fuzzy +msgid "Gondi" +msgstr "Gabon" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +# GA +#. language code: grb +#: zypp/LanguageCode.cc:497 +#, fuzzy +msgid "Grebo" +msgstr "Gabon" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +#, fuzzy +msgid "Guarani" +msgstr "Mađarski" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +#, fuzzy +msgid "Gwich'in" +msgstr "Mičigen" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +#, fuzzy +msgid "Haida" +msgstr "Hardware" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "Haiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +#, fuzzy +msgid "Hawaiian" +msgstr "Havaji" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebrejski" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +#, fuzzy +msgid "Herero" +msgstr "Hebrejski" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +# HT +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +#, fuzzy +msgid "Hindi" +msgstr "Haiti" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +#, fuzzy +msgid "Hittite" +msgstr "Haiti" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +#, fuzzy +msgid "Hmong" +msgstr "Hong Kong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +#, fuzzy +msgid "Upper Sorbian" +msgstr "Srpski" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Mađarski" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +#, fuzzy +msgid "Iban" +msgstr "Irak" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandski" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "Litvanija" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +#, fuzzy +msgid "Interlingue" +msgstr "Nastavi" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +#, fuzzy +msgid "Iloko" +msgstr "Tokio" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Infoneziski" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +#, fuzzy +msgid "Ingush" +msgstr "Engleski" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +#, fuzzy +msgid "Inupiaq" +msgstr "Indija" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +#, fuzzy +msgid "Iroquoian Languages" +msgstr "Odaberite vaš jezik:" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italijanski" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +#, fuzzy +msgid "Javanese" +msgstr "Japanski" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +#, fuzzy +msgid "Lojban" +msgstr "Libanon" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japanski" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +#, fuzzy +msgid "Judeo-Persian" +msgstr "Infoneziski" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +#, fuzzy +msgid "Judeo-Arabic" +msgstr "Arapski" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +#, fuzzy +msgid "Kabyle" +msgstr "Uključeno" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +#, fuzzy +msgid "Kachin" +msgstr "Bahrein" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +# GM +#. language code: kam +#: zypp/LanguageCode.cc:597 +#, fuzzy +msgid "Kamba" +msgstr "Gambija" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +#, fuzzy +msgid "Kannada" +msgstr "Kanada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +#, fuzzy +msgid "Karen" +msgstr "Korejski" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +#, fuzzy +msgid "Kanuri" +msgstr "Kurdski" + +# MW +#. language code: kaw +#: zypp/LanguageCode.cc:607 +#, fuzzy +msgid "Kawi" +msgstr "Malavi" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +#, fuzzy +msgid "Kazakh" +msgstr "Kazahstan" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +#, fuzzy +msgid "Khasi" +msgstr "Tajlandski" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +#, fuzzy +msgid "Khotanese" +msgstr "Kineski" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +#, fuzzy +msgid "Kirghiz" +msgstr "Djevičanska ostrva" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +#, fuzzy +msgid "Kimbundu" +msgstr "Katmandu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +#, fuzzy +msgid "Konkani" +msgstr "Korejski" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +#, fuzzy +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korejski" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +#, fuzzy +msgid "Kosraean" +msgstr "Korejski" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +#, fuzzy +msgid "Kurukh" +msgstr "Turski" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +#, fuzzy +msgid "Kuanyama" +msgstr "Panama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdski" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +#, fuzzy +msgid "Kutenai" +msgstr "Kenija" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +#, fuzzy +msgid "Ladino" +msgstr "Libanon" + +# UG +#. language code: lah +#: zypp/LanguageCode.cc:657 +#, fuzzy +msgid "Lahnda" +msgstr "Uganda" + +# GM +#. language code: lam +#: zypp/LanguageCode.cc:659 +#, fuzzy +msgid "Lamba" +msgstr "Gambija" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +#, fuzzy +msgid "Lao" +msgstr "Libanon" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +#, fuzzy +msgid "Latin" +msgstr "Latviski" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latviski" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +#, fuzzy +msgid "Lezghian" +msgstr "Belgijski" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "Luksemburg" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +#, fuzzy +msgid "Lingala" +msgstr "Angola" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litvanski" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +#, fuzzy +msgid "Mongo" +msgstr "Kongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +#, fuzzy +msgid "Lozi" +msgstr "Prijava" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "Luksemburg" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +#, fuzzy +msgid "Ganda" +msgstr "Gana" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +#, fuzzy +msgid "Lunda" +msgstr "Zvuk" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "Tajlandski" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonski" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +#, fuzzy +msgid "Madurese" +msgstr "Maltski" + +# MW +#. language code: mag +#: zypp/LanguageCode.cc:701 +#, fuzzy +msgid "Magahi" +msgstr "Malavi" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +#, fuzzy +msgid "Marshallese" +msgstr "Maršalova ostrva" + +# ML +#. language code: mai +#: zypp/LanguageCode.cc:705 +#, fuzzy +msgid "Maithili" +msgstr "Mali" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +#, fuzzy +msgid "Makasar" +msgstr "Madagaskar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +#, fuzzy +msgid "Malayalam" +msgstr "Malezija" + +#. language code: man +#: zypp/LanguageCode.cc:711 +#, fuzzy +msgid "Mandingo" +msgstr "Upozorenje" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maorski" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +#, fuzzy +msgid "Marathi" +msgstr "Maorski" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +#, fuzzy +msgid "Masai" +msgstr "Malavi" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "Malta" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +#, fuzzy +msgid "Mandar" +msgstr "Myanmar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +#, fuzzy +msgid "Mende" +msgstr "Mod" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "Odaberite vaš jezik:" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "Madagaskar" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltski" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +#, fuzzy +msgid "Manchu" +msgstr "&Pokreni" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +#, fuzzy +msgid "Manipuri" +msgstr "Maorski" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "Managva" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "Moldova" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +#, fuzzy +msgid "Mongolian" +msgstr "Mongolija" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +#, fuzzy +msgid "Mossi" +msgstr "Maorski" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "Jezik" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +#, fuzzy +msgid "Munda languages" +msgstr "Jezik" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +#, fuzzy +msgid "Creek" +msgstr "Grčki" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +#, fuzzy +msgid "Mirandese" +msgstr "Maine" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +#, fuzzy +msgid "Marwari" +msgstr "Maorski" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "Managva" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +#, fuzzy +msgid "North American Indian" +msgstr "Sjeverna Irska" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +#, fuzzy +msgid "Ndonga" +msgstr "Tonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "Njemački" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +#, fuzzy +msgid "Nepali" +msgstr "Nepal" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +#, fuzzy +msgid "Nepal Bhasa" +msgstr "Nepal" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +#, fuzzy +msgid "Niuean" +msgstr "Niue" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +#, fuzzy +msgid "Norwegian Nynorsk" +msgstr "Norveški" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +#, fuzzy +msgid "Norwegian Bokmal" +msgstr "Norveški" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +#, fuzzy +msgid "Nogai" +msgstr "Tonga" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norveški" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +#, fuzzy +msgid "Northern Sotho" +msgstr "Sjeverna Irska" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "Jezik" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +#, fuzzy +msgid "Classical Newari" +msgstr "Ime klase" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +#, fuzzy +msgid "Chichewa" +msgstr "Čile" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +#, fuzzy +msgid "Nyamwezi" +msgstr "Naziv" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +#, fuzzy +msgid "Nyoro" +msgstr "Sjever" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +#, fuzzy +msgid "Nzima" +msgstr "Lima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +#, fuzzy +msgid "Oriya" +msgstr "Surinam" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +#, fuzzy +msgid "Oromo" +msgstr "root" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +#, fuzzy +msgid "Osage" +msgstr "Poruke" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +#, fuzzy +msgid "Ossetian" +msgstr "Ruski" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "Jezik" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +#, fuzzy +msgid "Pangasinan" +msgstr "Mađarski" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +#, fuzzy +msgid "Pahlavi" +msgstr "Palau" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +#, fuzzy +msgid "Pampanga" +msgstr "Paragvaj" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +#, fuzzy +msgid "Panjabi" +msgstr "Panama" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +#, fuzzy +msgid "Palauan" +msgstr "Palau" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +#, fuzzy +msgid "Persian" +msgstr "Srpski" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +#, fuzzy +msgid "Philippine (Other)" +msgstr "Filipini" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +#, fuzzy +msgid "Phoenician" +msgstr "Slovenski" + +# ML +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +#, fuzzy +msgid "Pali" +msgstr "Mali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Poljski" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +#, fuzzy +msgid "Pohnpeian" +msgstr "Infoneziski" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugalski" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "Jezik" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +#, fuzzy +msgid "Pushto" +msgstr "&Prilagođeno" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +#, fuzzy +msgid "Rajasthani" +msgstr "Kazahstan" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "Japan" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "Rumunija" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumunjki" + +# RE +#. language code: run rn +#: zypp/LanguageCode.cc:901 +#, fuzzy +msgid "Rundi" +msgstr "Reunion" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ruski" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +#, fuzzy +msgid "Sandawe" +msgstr "Kanada" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +#, fuzzy +msgid "Sango" +msgstr "Sajgon" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "Jezik" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +#, fuzzy +msgid "Sasak" +msgstr "Samoa" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +#, fuzzy +msgid "Santali" +msgstr "Šangaj" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Srpski" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +#, fuzzy +msgid "Sicilian" +msgstr "Mičigen" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +#, fuzzy +msgid "Scots" +msgstr "Jug" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Hrvatski" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +#, fuzzy +msgid "Selkup" +msgstr "Pomoć" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "Jezik" + +# GH +#. language code: shn +#: zypp/LanguageCode.cc:943 +#, fuzzy +msgid "Shan" +msgstr "Gana" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +#, fuzzy +msgid "Sidamo" +msgstr "Samoa" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Odaberite vaš jezik:" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovački" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenski" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +#, fuzzy +msgid "Northern Sami" +msgstr "Sjeverna Irska" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "Jezik" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +#, fuzzy +msgid "Samoan" +msgstr "Samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +#, fuzzy +msgid "Shona" +msgstr "Slovenija" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +#, fuzzy +msgid "Soninke" +msgstr "Nastavi" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +#, fuzzy +msgid "Sogdian" +msgstr "Prijava" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +#, fuzzy +msgid "Somali" +msgstr "Somalija" + +#. language code: son +#: zypp/LanguageCode.cc:985 +#, fuzzy +msgid "Songhai" +msgstr "Šangaj" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Španski" + +# MR +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +#, fuzzy +msgid "Sardinian" +msgstr "Mauritanija" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +#, fuzzy +msgid "Serer" +msgstr "Servis" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +#, fuzzy +msgid "Swati" +msgstr "Haiti" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +#, fuzzy +msgid "Sundanese" +msgstr "Sudan" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +#, fuzzy +msgid "Susu" +msgstr "Status" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +#, fuzzy +msgid "Sumerian" +msgstr "Srpski" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +#, fuzzy +msgid "Swahili" +msgstr "Svazilend" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Švedski" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +#, fuzzy +msgid "Syriac" +msgstr "Surinam" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +#, fuzzy +msgid "Tahitian" +msgstr "Tahiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamilski" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "Katar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +#, fuzzy +msgid "Telugu" +msgstr "Belgija" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +#, fuzzy +msgid "Timne" +msgstr "Vremenska zona" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +#, fuzzy +msgid "Tetum" +msgstr "&Testiraj" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +#, fuzzy +msgid "Tajik" +msgstr "Tajlandski" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tajlandski" + +# TW +# fuzzy +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +#, fuzzy +msgid "Tibetan" +msgstr "Tajland" + +# NE +#. language code: tig +#: zypp/LanguageCode.cc:1039 +#, fuzzy +msgid "Tigre" +msgstr "Niger" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +#, fuzzy +msgid "Tigrinya" +msgstr "Nigerija" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +#, fuzzy +msgid "Klingon" +msgstr "Sajgon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +#, fuzzy +msgid "Tamashek" +msgstr "Taškent" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +#, fuzzy +msgid "Tonga (Tonga Islands)" +msgstr "Solomoska ostrva" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +#, fuzzy +msgid "Tsimshian" +msgstr "Ruski" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +#, fuzzy +msgid "Tswana" +msgstr "Bocvana" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +#, fuzzy +msgid "Tsonga" +msgstr "Tonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "Turska" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +#, fuzzy +msgid "Tumbuka" +msgstr "Timbuktu" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "Jezik" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turski" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +#, fuzzy +msgid "Tuvinian" +msgstr "Tunisia" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +#, fuzzy +msgid "Ugaritic" +msgstr "Haiti" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +#, fuzzy +msgid "Ukrainian" +msgstr "Ukrajina" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +#, fuzzy +msgid "Uzbek" +msgstr "Uzbekistan" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +#, fuzzy +msgid "Vai" +msgstr "Vatikan" + +# VN +# fuzzy +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +#, fuzzy +msgid "Venda" +msgstr "Vijetnam" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vijetnamski" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +#, fuzzy +msgid "Votic" +msgstr "Vatikan" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "Managva" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +#, fuzzy +msgid "Walamo" +msgstr "Valonski" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +#, fuzzy +msgid "Waray" +msgstr "Paragvaj" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +#, fuzzy +msgid "Washo" +msgstr "Welsh" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Welsh" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "Odaberite vaš jezik:" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Valonski" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +#, fuzzy +msgid "Yapese" +msgstr "Japanski" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +#, fuzzy +msgid "Yoruba" +msgstr "Aruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "Jezik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +#, fuzzy +msgid "Zenaga" +msgstr "Grenada" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +#, fuzzy +msgid "Zhuang" +msgstr "Butan" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +#, fuzzy +msgid "Zuni" +msgstr "Tunis" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "nepoznat" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +#, fuzzy +msgid "invalid" +msgstr "&Instaliraj" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Ne mogu pokrenuti naredbu \"%s\"" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Ne mogu pokrenuti naredbu \"%s\"" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Couldn't open file: %s." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Ne mogu pokrenuti naredbu \"%s\"" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +#, fuzzy +msgid "Continue?" +msgstr "Nastavi" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +# %s is either BOOTP or DHCP +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "%s podešavanje nije uspjelo." + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "&Nemoj instalirati" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +# %s is either BOOTP or DHCP +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "%s podešavanje nije uspjelo." + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Editor konfiguracijskih datoteka" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "&Dodatne informacije za korisnika" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Naredba koja se izvršava pri spajanju" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Instaliram driver..." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Ne mogu pokrenuti naredbu \"%s\"" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Da" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ne" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Greška" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "done" +msgstr "Indonesija" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "Greška" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Postavke" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Novi moduli nisu pronađeni." + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +#, fuzzy +msgid "yes" +msgstr "Da" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "Nova instalacija" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "do not install %s" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "Izbrii" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "niste spojeni" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "channel to channel konekcija" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "rpm output:" +#~ msgstr "" +#~ "\n" +#~ "Izvještaj:" + +#, fuzzy +#~ msgid "%s install failed" +#~ msgstr "Nova instalacija" + +#, fuzzy +#~ msgid "%s installed ok" +#~ msgstr "&Da, instaliraj" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "install %s" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "No need to install %s" +#~ msgstr "&Da, instaliraj" + +#, fuzzy +#~ msgid ", Action: " +#~ msgstr "3D ubrzanje:" + +#, fuzzy +#~ msgid "Establishing %s" +#~ msgstr "Instaliram driver..." + +#, fuzzy +#~ msgid " Error!" +#~ msgstr "Greška" + +#~ msgid "Ok" +#~ msgstr "U redu" + +#, fuzzy +#~ msgid "Default" +#~ msgstr "&Podrazumjevani" + +#, fuzzy +#~ msgid "to be installed (soft)" +#~ msgstr "&Bootaj instalirani sistem" + +#, fuzzy +#~ msgid "to be uninstalled" +#~ msgstr "&Da, instaliraj" diff --git a/po/ca.po b/po/ca.po new file mode 100644 index 0000000..8e0a145 --- /dev/null +++ b/po/ca.po @@ -0,0 +1,6562 @@ +# Catalan message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2000, 2001 SuSE GmbH. +# Jaume Badiella , 2001. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-16 09:47+0000\n" +"Last-Translator: David Medina \n" +"Language-Team: Catalan \n" +"Language: ca\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: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "País desconegut: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Sense codi" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +# AE +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Unió dels Emirats Àrabs" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua i Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +# AL +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albània" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armènia" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antilles Holandeses" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antàrtida" + +# AR +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Americana" + +# AT +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Àustria" + +# AU +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Austràlia" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Illes Aland" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaidjan" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bòsnia i Hercegovina" + +# BB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +# BD +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangla Desh" + +# BE +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Bèlgica" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +# BG +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgària" + +# BH +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benín" + +# BM +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudes" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +# BO +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolívia" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasil" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahames" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Illa Bouvet" + +# BW +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +# BY +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Bielorússia" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +# CA +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canadà" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Illes Cocos (Keeling)" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "República Centreafricana" + +# CH +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Suïssa" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Costa d'Ivori" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Illes Cook" + +# CL +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Xile" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camerun" + +# CN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Xina" + +# CO +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colòmbia" + +# CR +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cap Verd" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Illa Christmas" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Xipre" + +# CZ +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "República Txeca" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Alemanya" + +# DJ +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +# DK +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dinamarca" + +# DM +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +# DO +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "República Dominicana" + +# DZ +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algèria" + +# EC +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Equador" + +# EE +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estònia" + +# EG +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipte" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sàhara Occidental" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +# ES +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Espanya" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiòpia" + +# FI +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlàndia" + +# FJ +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Illes Malvines (Falkland)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Estats federats de Micronèsia" + +# FO +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Illes Fèroe" + +# FR +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "França" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "França metropolitana" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Regne Unit" + +# GD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +# GE +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Geòrgia" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guaiana Francesa" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +# GI +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +# GL +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenlàndia" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gàmbia" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +# GP +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadalupe" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinea Equatorial" + +# GR +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grècia" + +# GS +# fuzzy +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Illes Geòrgia del Sud i Sandwich del Sud" + +# GT +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +# GU +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea Bissau" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +# HK +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Illa Heard i illes McDonald" + +# HN +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Hondures" + +# HR +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croàcia" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haití" + +# HU +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hongria" + +# ID +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonèsia" + +# IE +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanda" + +# IL +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Illa de l'home" + +# IN +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Índia" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Territori Britànic de l'Oceà Índic" + +# IQ +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraq" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +# IS +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islàndia" + +# IT +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Itàlia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +# JM +# fuzzy +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +# JO +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordània" + +# JP +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japó" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirguizistan" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodja" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comores" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Christopher i Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Corea del Nord" + +# ZA +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Corea del Sud" + +# KW +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Illes Caiman" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakhstan" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "República democràtica popular de Laos" + +# LB +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Líban" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Santa Lucia" + +# LI +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Libèria" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +# LT +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituània" + +# LU +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburg" + +# LV +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letònia" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libèria" + +# MA +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marroc" + +# MC +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Mònaco" + +# MD +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldàvia" + +# CG +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +# SM +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Sant Martí" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Illes Marshall" + +# MK +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedònia" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongòlia" + +# MO +# fuzzy +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macau" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Illes Mariannes del Nord" + +# MQ +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinica" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritània" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +# MT +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Maurici" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Mali" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +# MX +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mèxic" + +# MY +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malàisia" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Moçambic" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namíbia" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nova Caledònia" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Níger" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Illa Norfolk" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigèria" + +# NI +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +# NL +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Països Baixos" + +# NO +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noruega" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +# NR +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauruà" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +# NZ +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nova Zelanda" + +# OM +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +# PA +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panamà" + +# PE +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Perú" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinèsia francesa" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nova Guinea" + +# PH +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipines" + +# PK +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +# PL +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polònia" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint-Pierre-et-Miquelon" + +# PN +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +# PR +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Territori palestí" + +# PT +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +# PW +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +# PY +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguai" + +# QA +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Illa de la Reunió" + +# RO +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Sèrbia" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Rússia" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +# SA +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Aràbia Saudita" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Illes Salomó" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +# SD +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +# SE +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suècia" + +# SG +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Santa Helena" + +# SI +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Eslovènia" + +# SJ +# fuzzy +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Illes Svalbard i Jan Mayen" + +# SK +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Eslovàquia" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somàlia" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome i Príncipe" + +# SV +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Síria" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swazilàndia" + +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Illes Turks i Caicos" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Txad" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Territoris Francesos del Sud" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +# TH +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tailàndia" + +# TJ +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadjikistan" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelauès" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +# TN +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunísia" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor Oriental" + +# TR +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turquia" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinitat i Tobago" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvaluà" + +# TW +# fuzzy +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tailàndia" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzània" + +# UA +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ucraïna" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Illes Perifèriques Menors dels EUA" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Estats Units" + +# UY +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguai" + +# UZ +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Ciutat del Vaticà (Santa Seu)" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent i les Grenadines" + +# VE +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Veneçuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Illes Verges Britàniques" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Illes Verges Americanes" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Illes Wallis i Futuna" + +# WS +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +# YE +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Iemen" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +# ZA +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Sud-àfrica" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zàmbia" + +# ZW +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Proporciona" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Necessita prèviament" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Requereix" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Té conflicte" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Fa obsolet" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recomana" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Suggereix" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Millora" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Complementa" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "S'ha provat d'importar la clau no existent %s a l'anell de claus %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Ha fallat importar la clau." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Error a l'hora d'esborrar la clau." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "El fitxer de la firma diginal %s no s'ha trobat" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "L'idioma és desconegut: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Àfar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhàzia" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Atjeh" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adigué" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Llengües afroasiàtiques (altres)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Àkan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Accadi" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanès" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutià" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Llengües algonquines" + +# ZA +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altaic meridional" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amhàric" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Anglès antic (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Llengües Apatxe" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Àrab" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Arameu" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonès" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armeni" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucà" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Llengües artificials (altres)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arauac" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamès" + +# AT +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturià" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Llengües atapascanes" + +# AU +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Llengües australianes" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Àvar" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avèstic" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Àzeri" + +# CA +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Llengües bamileké" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Baixkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Balutxi" + +# GM +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinès" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basc" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Llengües bàltiques (altres)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorús" + +# BM +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +# SN +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengalí" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Llengües berbers (altres)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +# BH +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +# BJ +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Blackfoot" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Llengües bantus (altres)" + +# BW +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosni" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Francès" + +# ID +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonèsia)" + +# BG +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugui" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Búlgar" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birmà" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Bilin" + +# TD +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Llengües ameríndies d'Amèrica Central (altres)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Català" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Llengües caucàsiques (altres)" + +# LB +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Llengües cèltiques (altres)" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +# CN +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Txibtxa" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Txetxè" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Txagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Xinès" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +# ML +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Pidgin Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Eslavònic" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Txuvaix" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Xeienne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Llengües txàmiques" + +# CR +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Copte" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Còrnic" + +# CR +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Cors" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Criolls i pidgins (basats en l'anglès) (altres)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Criolls i pidgins (basats en el francès) (altres)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Criolls i pidgins (basats en el portuguès) (altres)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tàrtar de Crimea" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Llengües criolles i pidgins (altres)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Caixubi" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Llengües cuixítiques (altres)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Txec" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danès" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Darguà" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Daiak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (atapascà)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Llengües dravidianes (altres)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Baix sòrab" + +# PW +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Neerlandès mitjà (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Holandès" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egipci antic" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamita" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Anglès" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Anglès mitjà (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonià" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Feroès" + +# HT +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +# FJ +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijià" + +# PH +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Pilipí" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finès" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Llengües finoúgriques (altres)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francès" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francès mitjà (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francès antic (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisó" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Ful" + +# FI +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friülès" + +# GU +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +# LY +# fuzzy +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Llengües germàniques (altres)" + +# GE +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgià" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Alemany" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Gueez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertès" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaèlic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandès" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Gallec" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Alt alemany mitjà (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Alt alemany antic (ca.750-1050)" + +# IN +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gòtic" + +# GA +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grec antic (fins el 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grec modern (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guaraní" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Crioll haitià" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Haussa" + +# HT +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaià" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebreu" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +# IN +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hitita" + +# TO +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Alt Sorab" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Hongarès" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandès" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +# LT +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Ilocà" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Associació de la Llengua Auxiliar Internacional)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Llengües indoàries (altres)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesi" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Llengües indoeuropees (altres)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingúix" + +# IN +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Llengües iràniques (altres)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Iroquès" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italià" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanès" + +# LB +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonès" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeopersa" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeoàrab" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Cabilenc" + +# BH +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Grenlandès" + +# GM +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +# CA +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Caixmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +# MW +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardí" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Llengües khoisanes (altres)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanès" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuiu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirguís" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Congo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreà" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Balkar, karatxai" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +# PA +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kúmik" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurd" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +# LB +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Judeocastellà" + +# UG +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Panjabi occidental" + +# GM +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +# LB +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laosià" + +# LV +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Llatí" + +# LV +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letó" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lesguià" + +# LU +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburguès" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +# LT +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituà" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +# LU +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburguès" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseño" + +# SD +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (de Kenya i Tanzània)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedònic" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurès" + +# MW +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallès" + +# ML +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +# MY +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malaialam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Manding" + +# ML +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Llengües autronèsies (altres)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Massai" + +# MT +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malai" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Mordovià moksha" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Gaèlic irlandès mitjà (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Micmac" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Llengües mixtes" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Llengües monkhmers (altres)" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgaix" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltès" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manxú" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Llengües manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +# MD +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldau" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Llengües múltiples" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Llengües mundes" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandès" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Llengües maies" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Mordovià erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nàhuatl" + +# MP +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Llengües ameríndies septentrionals (altres)" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolità" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele meridional" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele septentrional" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Baix alemany" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalès" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Newari" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Llengües nigerokurdufanianes (altres)" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "(Noruec) nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "(Noruec) bokmal" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Noruec antic" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Noruec" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho del nord" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Llengües nubianes" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari clàssic" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Nyanja" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occità (després de 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osset" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turc otomà (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Llengües otomíes" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Llengües papús (altres)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinà" + +# PW +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +# PY +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +# PA +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +# PW +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauà" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persa antic (ca.600-400 aC)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persa" + +# PH +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Llengües filipines (altres)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenici" + +# ML +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polonès" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Ponapeà" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portuguès" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Pràcrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provençal antic (fins al 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Paixtú" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quítxua" + +# TJ +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +# JP +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Llengües romàniques (altres)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Retoromànic" + +# RO +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romaní" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romanès" + +# RE +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Kirundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rus" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +# WS +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Iacut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Llengües ameríndies meridionals (altres)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Llengües salish" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Arameu samarità" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sànscrit" + +# WS +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbi" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilià" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croat" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Llengües semítiques (altres)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Gaèlic irlandès antic (fins 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Llengües de signes" + +# SD +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +# WS +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singalès" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Llengües sioux (altres)" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Llengües sinotibetanes (altres)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Llengües eslaves (altres)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Eslovac" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Eslovè" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sami meridional" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Sami septentrional" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Llengües samis (altres)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Sami de Lule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Sami d'Inari" + +# WS +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoà" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Sami skolt" + +# SI +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +# SD +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdià" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +# TO +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, sud" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Espanyol" + +# MR +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sard" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Llengües niloticosaharianes (altres)" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swazi" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +# SD +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sondanès" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumeri" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Suahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Suec" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siríac" + +# TW +# fuzzy +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitià" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Llengües tai (altres)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tàmil" + +# QA +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tàtar" + +# BE +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +# TJ +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadjik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagàlog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tai" + +# TW +# fuzzy +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetà" + +# NE +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigré" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek (tamazight)" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tongà (Illes Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +# BW +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +# TR +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turcman" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Llengües tupís" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turc" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Llengües altaïques (altres)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +# TN +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvinià" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Votiac" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugarític" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uigur" + +# UA +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ucraïnès" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Sense determinar" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdú" + +# UZ +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbek" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamita" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Llengües wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +# PY +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Gal·lès" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sòrab" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Való" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wòlof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Calmuc" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapeà" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jiddisch" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Ioruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapoteca" + +# GD +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "(Tamazight) zenaga" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +# TV +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Es faran les accions següents:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "no caduca" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "va caducar el %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "caduca el %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(no caduca)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(CADUCADA)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(caduca d'aquí a 24 h)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(caduca d'aquí a %d dia)" +msgstr[1] "(caduca d'aquí a %d dies)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "desconegut" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "no suportat" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Nivell 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Nivell 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Nivell 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Contracte addicional de client necessari" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Descatalogat i substituït per un paquet diferent" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "invàlid" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "El nivell de suport no està especificat." + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "El proveïdor ja no n'ofereix suport." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Determinació de problema, la qual cosa significa suport tècnic dissenyat per " +"oferir compatibilitat d'informació, assistència d'instal·lació, suport d'ús, " +"manteniment continu i resolució bàsica de problemes. El suport de nivell 1 " +"no està pensat per corregir errors de defecte del producte." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"L'aïllament de problemes, que significa el suport tècnic dissenyat per " +"duplicar els problemes del client, aïlla l'àrea del problema i proporciona " +"la solució dels problemes no resolts pel nivell 1 de suport." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Resolució de problema, la qual cosa significa suport tècnic dissenyat per " +"resoldre problemes complexos a través d'enginyeria de resolució de defectes " +"de producte que s'han identificat amb el suport de nivell 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Un contracte addicional de client és necessari per obtenir-ne suport." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"El paquet s'ha descatalogat i s'ha substituït per un paquet nou amb un nom " +"diferent." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Opció de suport desconeguda. No n'hi ha descripció disponible." + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"La gestió del sistema està blocada per l'aplicació amb el pid %d (%s).\n" +"Tanqueu aquesta aplicació abans de tornar-ho a provar." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Mode de coincidència desconegut: \"%s\"" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Mode de coincidència desconegut \"%s\" per al patró %s" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Expressió regular no vàlida \"%s\": regcomp ha respost %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Expressió regular no vàlida: \"%s\"" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Cal autenticació per a '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Es tornarà a intentar..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Es deixarà estar després de %1% intents." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visiteu el Centre de clientela de SUSE per comprovar si el vostre registre " +"és vàlid i no ha caducat." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visiteu el Novell Customer Center per comprovar si el vostre registre encara " +"és vàlid i no ha caducat." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Crea un punt d'adjunció: no es pot trobar un directori d'escriptura per " +"crear un punt d'adjunció." + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Si us plau, instal·leu primer el paquet lsof." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "No es pot crear el directori cau de metadades." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Error en intentar llegir de '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "No es pot crear %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "No s'han trobat metadades vàlides a l'URL especificat" +msgstr[1] "No s'han trobat metadades vàlides als URL especificats" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" +"Ha fallat posar a la memòria cau el repositori (no s'ha pogut iniciar " +"repo2solv)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Error a l'hora de carregar el repositori (%d) a la memòria cau." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Construint la memòria cau del repositori %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" +"No es pot crear la memòria cau a %s - no se'n té permisos d'escriptura." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "Ha fallat posar a la memòria cau el repositori %1%." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Tipus de repositori no manejat" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Afegint el repositori %s" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nom de repositori no vàlid a \"%s\"" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "No es pot obrir el fitxer %s per a l'escriptura." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Error desconegut a l'hora de llegir '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "No es pot llegir el directori del repositori %1%: permís denegat" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Error a l'hora de llegir el directori %s" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "No es pot llegir el fitxer de repositori %1%: permís denegat" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "Netejant metadades" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "Netejant paquets" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "Netejant directoris de la cau" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "Netejant el directori: %1%" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "Netejant la cau" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "Carregant de la cau" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Suprimint el repositori %s" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "No es pot esbrinar on es desa el repositori." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "No es pot esborrar %s" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "Modificant el repositori" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "Refrescant el repositori: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "No s'ha sabut trobar on es guarda el servei." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Servei desconegut \"%1%\": suprimint el repositori de serveis orfe %2%" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "L'àlies del repositori no pot començar amb un punt." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "L'àlies del servei no pot començar amb un punt." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "No hi ha cap resum per al fitxer %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Resum desconegut %s per al fitxer %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Ha fallat la verificació del resum del fitxer %s." + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "El fitxer %s no està signat. Continuo?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "El fitxer %s del repositori %s no està signat. Continuo?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Voleu rebutjar la clau, confiar-hi temporalment o confiar-hi sempre?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Nom de la clau: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +"S'ha rebut %1% clau de signatura de paquets nova del repositori %2%:" +msgstr[1] "" +"S'han rebut %1% claus de signatura de paquets noves del repositori %2%:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Ha fallat la verificació de la signatura per al fitxer %1%." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"Ha fallat la verificació de la signatura per al fitxer %1% del repositori " +"%2%." + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Continuo?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "El fitxer %s està signat amb una clau desconeguda: %s. Continuo?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"El fitxer %s del repositori %s està signat amb una clau desconeguda: %s. " +"Continuo?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "El repositori %1% no defineix URL \"gpgkey=\" addicionals." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Cercant la clau gpg amb l'ID %1% al repositori %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Cercant la clau gpg amb l'ID %1% a la cau %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Falta l'atribut requerit \"%s\"." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Són necessaris l'atribut \"%s\" o \"%s\", o bé tots dos." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Ha fallat la verificació de la signatura" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"El paquet %s sembla que s'ha corromput durant la transferència. Voleu " +"intentar baixar-lo de nou?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "El paquet %s no s'ha pogut obtenir. Voleu intentar baixar-lo de nou?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "La comprovació de l'applydeltarpm ha fallat." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "ha fallat aplicar de l'RPM delta." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "El servei de complements (plugin) no permet canviar-ne un atribut." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "No es pot proporcionar el fitxer %s des del repositori %s" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "No URL al repositori." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Mitjà esperat: %1%/%2%. Identificat pel fitxer %3% amb aquest contingut:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"El fitxer %1%\n" +" del paquet\n" +" %2%\n" +" té conflicte amb el fitxer del paquet\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"El fitxer %1%\n" +" del paquet\n" +" %2%\n" +" té conflicte amb el fitxer de la instal·lació de\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"El fitxer %1%\n" +" de la instal·lació de\n" +" %2%\n" +" té conflicte amb el fitxer del paquet\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"El fitxer %1%\n" +" de la instal·lació de\n" +" %2%\n" +" té conflicte amb el fitxer de la instal·lació de\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"El fitxer %1%\n" +" del paquet\n" +" %2%\n" +" té conflicte amb el fitxer\n" +" %3%\n" +" del paquet\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"El fitxer %1%\n" +" del paquet\n" +" %2%\n" +" té conflicte amb el fitxer\n" +" %3%\n" +" de la instal·lació de\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"El fitxer %1%\n" +" de la instal·lació de\n" +" %2%\n" +" té conflicte amb el fitxer\n" +" %3%\n" +" del paquet\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"El fitxer %1%\n" +" de la instal·lació de\n" +" %2%\n" +" té conflicte amb el fitxer\n" +" %3%\n" +" de la instal·lació de\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "No es pot crear sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "trenca %s ignorant-ne algunes de les dependències" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "ignora generalment algunes dependències" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"el %1% instal·lat no pertany a un repositori d'actualització de la " +"distribució i s'ha de reemplaçar" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" +"el %1% per instal·lar no pertany a un repositori d'actualització de la " +"distribució" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "el %1% instal·lat té una arquitectura inferior" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "el %1% per instal·lar té una arquitectura inferior" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problema amb el %1% instal·lat" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "demandes conflictives" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "problemes de dependències" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "no hi ha res que proporcioni el %1% requerit" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Heu habilitat tots els repositoris requerits?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "el paquet requerit %1% no existeix" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "petició no suportada" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "%1% és proporcionat pel sistema i no es pot esborrar" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% no és instal·lable" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "no hi ha res que proporcioni %1%, necessari per al %2% instal·lat" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "no hi ha res que proporcioni %1%, necessari per al %2% per instal·lar" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "no es poden instal·lar tots dos: %1% i %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"el %1% instal·lat té conflicte amb %2%, proporcionat per l'instal·lat %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"el %1% instal·lat té conflicte amb el %2%, proporcionat per %3% per " +"instal·lar" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"el %1% per instal·lar té conflicte amb %2%, proporcionat per l'instal·lat %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"el %1% per instal·lar té conflicte amb el %2%, proporcionat per %3% per " +"instal·lar" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "el %1% instal·lat fa obsolet %2%, proporcionat per l'instal·lat %3%" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "el %1% instal·lat fa obsolet %2%, proporcionat per %3% per instal·lar" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"el %1% per instal·lar fa obsolet %2%, proporcionat per l'instal·lat %3%" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"el %1% per instal·lar fa obsolet %2%, proporcionat per %3% per instal·lar" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "el %1% instal·lat té conflicte amb %2%, proporcionat per si mateix" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "el %1% per instal·lar té conflicte amb %2%, proporcionat per si mateix" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"el %1% instal·lat requereix %2%, però aquest requisit no es pot proporcionar" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"el %1% per instal·lar requereix %2%, però aquest requisit no es pot " +"proporcionar" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "proveïdors suprimits: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"proveïdors no desistal·lables: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "proveïdors no desinstal·lables: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% encara no s'ha integrat plenament a %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Normalment voleu mantenir el PTF (format de text net) i opteu per no " +"instal·lar els pedaços de manteniment." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"La supressió del PTF %1% instal·lat en aquest context també suprimirà (no " +"substituirà!) els paquets PTF inclosos." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"El PTF s'hauria de suprimir cridant %1%. Això actualitzarà els paquets PTF " +"inclosos en lloc de suprimir-los." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Normalment, voleu mantenir el PTF o opteu per cancel·lar l'acció." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "El %1% instal·lat bloqueja l'acció desitjada." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Normalment, voleu mantenir el PTF i opteu per cancel·lar l'acció." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "suprimeix el bloqueig per permetre la supressió de %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "no instal·lis %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "mantén %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "suprimeix el bloqueig per permetre la instal·lació de %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Aquesta petició trencarà l'estabilitat del sistema!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignora l'avís de sistema trencat" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "no preguntis la instal·lació d'un resoluble que proporcioni %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "no preguntis la supressió de tots els resolubles que proporcionin %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "no instal·lis la versió més recent de %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "mantén %1% malgrat l'arquitectura inferior" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "instal·la %1% malgrat l'arquitectura inferior" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "mantén obsolet %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "instal·la %1% des d'un repositori exclòs" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "instal·la %1% tot i que ha estat retret" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "permet instal·lar el PTF (format de text net) %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "instal·la %1% tot i que és a la llista negra" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "degradació de %1% a %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "canvi d'arquitectura de %1% a %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"instal·la %1% (amb canvi de proveïdor)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"instal·la %1% del proveïdor %2%\n" +" i reemplaça %3% del proveïdor %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "reemplaçament de %1% per %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "desinstal·lació de %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Executant scripts posteriors a la transacció" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Executant l'script %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Sortida de l'script %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "La instal·lació s'ha avortat tal com heu indicat." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " executat" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " ha fallat l'execució" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s ja s'ha executat com a %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " execució omesa mentre s'avortava" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" +"S'ha produït un error durant l'enviament de la notificació d'actualització." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nou missatge d'actualització" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Senyal rebut: \"%1% (%2%)\", per garantir la coherència del sistema, no és " +"possible cancel·lar una transacció rpm en execució." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "No s'ha pogut executar la transacció a causa dels problemes següents:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Ha fallat l'RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Error a l'hora d'importar la clau pública %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Ha fallat suprimir la clau pública %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "La capçalera del paquet no està signada!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "El contingut del paquet no està signat!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Fitxers de configuració modificats per a %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"L'rpm ha desat %s com a %s però no ha estat possible determinar-ne la " +"diferència" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"L'rpm ha desat %s com a %s.\n" +"Aquestes són les primeres 25 línies de diferència:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"L'rpm ha creat %s com a %s però no ha estat possible determinar-ne la " +"diferència" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"L'rpm ha creat %s com a %s.\n" +"Aquestes són les primeres 25 línies de diferència:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Sortida addicional de l'rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "còpia de seguretat creada %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "La signatura és correcta" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tipus de signatura desconeguda" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "La signatura no es verifica" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "La signatura és correcta, però no és de confiança" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "La clau pública de signatures no està disponible" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "El fitxer no existeix o la signatura no es pot comprovar" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "El fitxer no està signat." + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tipus dubtós %s per a byte %u, suma de verificació \"%s\"" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "No es pot obrir pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "No es pot obrir pipe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "La cadena de consulta de l'URL de l'LDAP no és vàlida" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "El paràmetre de consulta de l'URL de l'LDAP \"%s\" no és vàlid" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "No es pot clonar l'objecte de l'URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "La referència d'objecte de l'URL buit no és vàlida" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "No es poden analitzar els components de l'URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historial:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "L'esquema de l'URL no permet un %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "El component %s no és vàlid %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Component de %s no vàlid" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "No s'admet l'anàlisi de cadenes de consulta per a aquesta URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "L'esquema de l'URL és un component necessari" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "L'esquema de l'URL \"%s\" no és vàlid" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "L'esquema de l'URL no permet un nom d'usuari" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "L'esquema de l'URL no permet una contrasenya" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "L'esquema de l'URL requereix un component d'amfitrió" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "L'esquema de l'URL no permet un component d'amfitrió" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "El component d'amfitrió \"%s\" no és vàlid." + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "L'esquema de l'URL no permet un port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "El component de port \"%s\" no és vàlid" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "L'esquema de l'URL requereix un nom de camí" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "No es permet un camí relatiu si existeix una autoritat" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "La cadena codificada conté un byte NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "El caràcter separador de divisió de matriu de paràmetres no és vàlid" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" +"El caràcter separador de divisió d'assignació de paràmetres no és vàlid" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "El caràcter separador d'unió de matriu de paràmetres no és vàlid" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "L'ordre ha acabat amb l'estatus %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "L'ordre s'ha aturat a causa del senyal %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "L'ordre s'ha executat sense que hi hagués cap error conegut." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "S'han donat arguments de generació no vàlids." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "No es pot crear la canonada de control." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "No es pot fer chroot a \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "No es pot fer chdir a \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "No es pot fer chdir a \"%s\" dins chroot \"%s\" (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "No es pot executar \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "No es pot bifurcar (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "No es pot executar %s, ha fallat l'ordre chdir (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "No es pot executar %s, ha fallat l'ordre chroot (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "No es pot executar %s, ha fallat l'ordre exec (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "No es pot executar %s, error inesperat." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Error a l'hora de muntar %s a %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Error a l'hora de desmuntar %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Mal nom de fitxer: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Mitjà no obert quan s'intentava fer l'acció \"%s\"." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "El fitxer %s no s'ha trobat al mitjà %s" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "No es pot escriure al fitxer %s." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "No hi ha un mitjà connectat" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Mal punt de contacte del mitjà" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "L'inici de la baixada (curl) ha fallat per a \"%s\"" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Excepció de sistema \"%s\" al mitjà \"%s\"." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "El camí \"%s\" del mitjà \"%s\" no és un fitxer." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "La ruta \"%s\" del suport %s no és un directori." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Malformat URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nom d'hoste buit a l'URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Sistema de fitxers buit a l'URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destinació buida a l'URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "L'esquema d'URL a %s no és vàlid." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operació no admesa pel mitjà" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Error de baixada (curl) per a %s:\n" +"Codi d'error: %s\n" +"Missatge d'error: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Hi ha hagut un error en establir les opcions de baixada (curl) per a %s:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "El suport font \"%s\" no conté el mitjà desitjat." + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "El mitjà \"%s\" l'està fent servir una altra instància." + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "No es pot expulsar el mitjà" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "No es pot expulsar el suport %s" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Permís per accedir a %s denegat." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "S'ha acabat el temps d'espera accedint a %s." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"Les dades baixades excedeixen la mida de fitxer esperada \"%s\" de \"%s\"." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "El lloc \"%s\" és temporalment inaccessible." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Problema de certificat SSL, verifiqueu que el certificat CA és correcte per " +"a \"%s\"." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "No hi ha recursos lliures disponibles per adjuntar el mitjà." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Mètode d'autenticació HTTP no suportat \"%s\"" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Error de baixada (curl) per a %s.\n" +"Codi de l'error: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Error de baixada (curl) per a %s.\n" +"No es pot obtenir la resposta d'HTTP.\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Sí" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "No" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Atenció!" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Avís!" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Error:" + +# ID +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "fet" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "atenció" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "error" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Avís! " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Obtenint" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "començant" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "no trobat" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "No hi ha ajuda per a aquesta entrada." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "no hi ha ajuda disponible per a aquesta opció" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "mostra totes les opcions" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "sí" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "no" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Executant l'script %%posttrans \"%1%\"" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Executant scripts %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "El paquet no està signat!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s no pertany a un repositori d'actualització de la distribució" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s té una arquitectura inferior" + +#~ msgid "problem with installed package %s" +#~ msgstr "problema amb el paquet instal·lat %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "Res proporciona %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Heu habilitat tots els repositoris demanats?" + +#~ msgid "package %s does not exist" +#~ msgstr "el paquet %s no existeix" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s està proveït pel sistema i no es pot esborrar" + +#~ msgid "%s is not installable" +#~ msgstr "%s no és instal·lable" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "Res proporciona %s, necessari per a %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "No es poden instal·lar %s i %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s entra en conflicte amb %s, proveït per %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s fa(n) obsolet(s) %s proveït(s) per %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "" +#~ "el(s) paquets(s) instal·lat(s) %s fa(n) obsolet(s) %s proporcionat(s) per " +#~ "%s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "" +#~ "la resolució %s entra en conflicte amb %s, proporcionat per si mateix" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s necessita %s, però aquest requeriment no es pot satisfer" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "suprimeix el bloqueig per permetre la supressió de %s" + +#~ msgid "do not install %s" +#~ msgstr "no instal·lis %s" + +#~ msgid "keep %s" +#~ msgstr "mantén %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "suprimeix el bloqueig per permetre la instal·lació de %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "no demanis instal·lar un resoluble que proporcioni %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "no demanis suprimir tots els resolubles que proporcionin %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "no instal·lis la versió més recent de %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "mantén %s malgrat l'arquitectura inferior" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "instal·la %s, encara que tingui una arquitectura inferior" + +#~ msgid "keep obsolete %s" +#~ msgstr "deixa obsolet %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "instal·la %s del repositori exclòs" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "degradació de %s a %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "canvi d'arquitectura de %s a %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "instal·la %s (amb canvi de proveïdor)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "reemplaçament de %s per %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "desinstal·lació de %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "No es pot obrir el fitxer de blocatge: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Aquesta acció ja l'està executant un altre programa." + +#~ msgid "Hal Exception" +#~ msgstr "Excepció de Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Perdoneu, però aquesta versió de libzypp va ser construïda sense suport " +#~ "de HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "El HalContext no està connectat" + +#~ msgid "HalDrive not initialized" +#~ msgstr "El HalDrive no està iniciat" + +#~ msgid "HalVolume not initialized" +#~ msgstr "El HalVolume no està iniciat" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "No es pot crear la connexió dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: No es pot crear el context libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: No es pot definir la connexió de dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "No es pot iniciar el context HAL. No s'executa hald?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "No és una unitat de CD-ROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "No es poden iniciar els atributs de mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "No es pot definir l'atribut de mutex recursiu" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "No es pot iniciar el mutex recursiu" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "No es pot obtenir el bloqueig de mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "No es pot alliberar el bloqueig de mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Error a l'hora d'importar la clau pública del fitxer %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Error en eliminar la clau pública %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "No es pot trobar un dispositiu de bucle disponible per muntar el fitxer " +#~ "d'imatge de \"%s\"" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "generalment ignora algunes dependències" + +#~ msgid "do not forbid installation of %s" +#~ msgstr "no prohibeixis la instal·lació de %s" + +#~ msgid "do not keep %s installed" +#~ msgstr "no mantinguis %s instal·lat" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "لا يمكن إنشاء المفتاح العام %s من %s إلى ملف حلقة المفاتيح %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "حاول استيراد مفتاح غير موجود %s إلى حلقة مفاتيح %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "لا يمكن تغيير مجلد العمل '/' داخل استجذار (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "فشل تهيئة تحميل (Metalink curl) '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "تحميل (metalink curl) خطأ '%s':\n" +#~ "رمز الخطأ: %s\n" +#~ "رسالة الخطأ: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "توقف التحميل في %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "توقف التحميل بواسطة المستخدم" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "حدث خطأ أثناء إعداد خيارات التحميل (metalink curl) ل '%s':" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "No es pot obrir %s - %s\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Sèrbia i Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "L'opció list és desconeguda" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "no s'han pogut resoldre dependències" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "El fitxer %s no conté cap suma de verificació.\n" +#~ "Voleu utilitzar aquest fitxer de tota manera?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "El fitxer %s no ha superat la comprovació d'integritat amb la següent " +#~ "clau:\n" +#~ "%s|%s|%s\n" +#~ "Voleu utilitzar el fitxer de tota manera?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "El fitxer %s conté una suma de verificació no vàlida.\n" +#~ "S'esperava %s, i s'ha trobat %s\n" +#~ "Voleu utilitzar aquest fitxer de tota manera?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "El fitxer %s conté la suma de verificació desconeguda %s.\n" +#~ "Voleu utilitzar aquest fitxer de tota manera?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "El fitxer %s no està signat.\n" +#~ "Voleu utilitzar-lo de tota manera?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "El fitxer %s s'ha signat amb una clau desconeguda:\n" +#~ "%s|%s|%s\n" +#~ "Voleu utilitzar aquest fitxer de tota manera?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "S'ha trobat una clau no fiable:\n" +#~ "%s|%s|%s\n" +#~ "Voleu que la clau sigui de confiança?" + +#~ msgid "%s remove failed" +#~ msgstr "S'ha produït un error en suprimir %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "La contrasenya de la CA no és vàlida." + +#~ msgid "rpm output:" +#~ msgstr "Sortida de l'rpm:" + +#~ msgid "%s install failed" +#~ msgstr "S'ha produït un error en instal·lar %s" + +#~ msgid "%s installed ok" +#~ msgstr "%s s'ha instal·lat correctament" + +#~ msgid "%s remove ok" +#~ msgstr "%s s'ha suprimit correctament" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "" +#~ "%s proporciona aquesta dependència però canviaria l'arquitectura de " +#~ "l'element instal·lat" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "" +#~ "%s proporciona aquesta dependència però canviaria l'arquitectura de " +#~ "l'element instal·lat" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "No instal·lis ni suprimeixis els ítems amb dependències relacionats" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Ignora que %s ja s'ha definit per a instal·lar-se" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "Ignora l'obsolet %s a %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "Ignora aquest conflicte de %s" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "Ignora aquest requisit només en aquest cas" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "Instal·la %s, encara que canviï l'arquitectura" + +#~ msgid "Install missing resolvables" +#~ msgstr "Instal·la els ítems amb dependències que falten" + +#~ msgid "Keep resolvables" +#~ msgstr "Conserva els ítems amb dependències" + +#~ msgid "Unlock these resolvables" +#~ msgstr "Desbloqueja aquests ítems amb dependències" + +#~ msgid "delete %s" +#~ msgstr "suprimeix %s" + +#~ msgid "install %s" +#~ msgstr "instal·la %s" + +#~ msgid "unlock %s" +#~ msgstr "desbloqueja %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "desbloqueja tots els ítems amb dependències" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "No es pot obrir el fitxer %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "Error en llegir el sector %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "No s'admet l'anàlisi de paràmetres de camí per a aquesta URL" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "No s'admet l'anàlisi de paràmetres de camí per a aquesta URL" + +#~ msgid "Software management is already running." +#~ msgstr "Ja s'està executant la gestió del programari." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s s'ha reemplaçat per %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s ha estat reemplaçat per %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "Aquests ítems amb dependències es suprimiran del sistema." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s no es desinstal·larà perquè encara es necessita" + +#~ msgid "Invalid information" +#~ msgstr "La informació no és vàlida" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "Altres ítems amb dependències necessiten %s" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s requereix:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s entra en conflicte amb altres ítems amb dependències" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s entra en conflicte amb:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s desactualitza altres ítems amb dependències" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s desactualitza:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "Aquests ítems amb dependències es suprimiran del sistema." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s depèn d'altres ítems amb dependències" + +#~ msgid "%s depends on %s" +#~ msgstr "%s depèn de %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s depèn de:%s" + +#~ msgid "Child of" +#~ msgstr "Fill de" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "No hi ha cap recurs disponible que admeti aquest requisit." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "Atesos els problemes descrits anteriorment o a continuació, aquesta " +#~ "resolució no resoldrà totes les dependències" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "No es pot instal·lar %s perquè entra en conflicte amb %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s no s'ha instal·lat i s'ha marcat com a no instal·lable" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s té requisits no complerts" + +#~ msgid "%s has missing dependencies" +#~ msgstr "Falten dependències per a %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s no es pot instal·lar atès que falten dependències" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s compleixen les dependències de %s però es desinstal·laran" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s compleixen les dependències de %s però es conservaran al sistema" + +#~ msgid "No need to install %s" +#~ msgstr "No cal instal·lar %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "No es pot instal·lar %s per a complir les dependències de %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "No es pot instal·lar %s per a complir les dependències de %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s no es desinstal·larà perquè encara es necessita" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "" +#~ "%s desactualitza %s. No obstant, %s no es pot suprimir perquè està " +#~ "bloquejat." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "No es pot instal·lar %s perquè entra en conflicte" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s no es pot instal·lar atesos els conflictes amb %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "per a requerir %s per a %s en actualitzar %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "A %s li falta el requisit %s" + +#~ msgid ", Action: " +#~ msgstr ", Acció: " + +#~ msgid ", Trigger: " +#~ msgstr ", Activador: " + +#~ msgid "package" +#~ msgstr "paquet" + +#~ msgid "selection" +#~ msgstr "selecció" + +#~ msgid "pattern" +#~ msgstr "patró" + +#~ msgid "product" +#~ msgstr "producte" + +#~ msgid "patch" +#~ msgstr "pedaç" + +#~ msgid "script" +#~ msgstr "script" + +#~ msgid "message" +#~ msgstr "missatge" + +#~ msgid "atom" +#~ msgstr "àtom" + +#~ msgid "system" +#~ msgstr "sistema" + +#~ msgid "Resolvable" +#~ msgstr "Resolvable" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "Es marcarà aquest intent de resolució com a no vàlid." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "Es marcarà l'ítem amb dependències %s com a no instal·lable" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s s'ha programat per a instal·lar-se, però això no és possible per " +#~ "problemes de dependència." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "No es pot instal·lar %s perquè ja s'ha marcat com a que necessita " +#~ "desinstal·lar-se" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "No es pot instal·lar %s perquè no s'aplica a aquest sistema." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "No es pot instal·lar %s perquè %s ja s'ha marcat com a que necessita " +#~ "instal·lar-se" + +#~ msgid "This would invalidate %s." +#~ msgstr "%s quedaria invalidat." + +#~ msgid "Establishing %s" +#~ msgstr "S'està establint %s" + +#~ msgid "Installing %s" +#~ msgstr "S'està instal·lant %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "S'està actualitzant %s a %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "S'està ignorant %s: ja s'ha instal·lat" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "No hi ha cap altre proveïdor alternatiu instal·lat de %s" + +#~ msgid "for %s" +#~ msgstr "per a %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "" +#~ "No és possible actualitzar a %s per tal d'evitar que es suprimeixi %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s proporciona %s, però s'ha programat per a desinstal·lar-se." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "" +#~ "%s proporciona %s, però ja hi ha instal·lada una altra versió d'aquest %s." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s proporciona %s, però no és instal·lable. Proveu d'instal·lar-lo per sí " +#~ "mateix per a més detalls." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s proporciona %s, però està bloquejat." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s proporciona %s, però s'ha programat per a conservar-se." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s proporciona %s, però té una altra arquitectura." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "No es pot satisfer el requisit %s per a %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "Un altre ítem amb dependències instal·lat necessita %s, de manera que no " +#~ "es desenllaçarà." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "Un altre ítem amb dependències instal·lat necessita %s, de manera que no " +#~ "es desenllaçarà." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s està bloquejat i no es pot desinstal·lar." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "" +#~ "Per causa d'un conflicte relacionat amb %s (%s), cal suprimir el %s que " +#~ "s'ha d'instal·lar" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "" +#~ "A causa de conflictes relacionats amb %s, es marcarà %s com a no " +#~ "instal·lable" + +#~ msgid "from %s" +#~ msgstr "de %s" + +#~ msgid " Error!" +#~ msgstr " Error" + +#~ msgid " Important!" +#~ msgstr " Important" + +#~ msgid "%s depended on %s" +#~ msgstr "%s depenia de %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s requereix %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s requereix %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s s'ha reemplaçat per %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s requereix %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s és part de %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "Temps d'espera de doble clic " + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s requereix %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "No es pot analitzar l'autoritat de l'URL" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "Ignora aquest requisit de manera general" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "Una altra solució que s'ha d'instal·lar necessita %s, de manera que no es " +#~ "desenllaçarà." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "" +#~ "No es pot crear un fitxer necessari per a executar la instal·lació de " +#~ "l'actualització." + +#~ msgid "Unable to restore all sources." +#~ msgstr "No es poden restaurar tots els recursos." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "Ja s'ha registrat al menys una font; no es poden restaurar les fonts " +#~ "emmagatzemades." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "No es pot instal·lar %s per a complir les dependències de %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s depend de %s" + +#~ msgid "Reading index files" +#~ msgstr "S'estan llegint els fitxers d'índex" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "" +#~ "El fitxer signat repomd.xml no ha superat la comprovació de signatura." + +#~ msgid "Reading product from %s" +#~ msgstr "S'està llegint el producte de %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "S'està llegint la llista de fitxers de %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "S'estan llegint els paquets de %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "S'està llegint la selecció de %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "S'està llegint el patró de %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "S'està llegint l'índex de pedaços %s" + +#~ msgid "Reading patch %s" +#~ msgstr "S'està llegint el pedaç %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "" +#~ "El fitxer de l'script no ha superat la prova de suma de verificació." + +#~ msgid "Reading packages file" +#~ msgstr "S'està llegint el fitxer de paquets" + +#~ msgid "Reading translation: %s" +#~ msgstr "S'està llegint la traducció: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "El paquet %s no ha superat la comprovació d'integritat. Voleu intentar " +#~ "baixar-lo de nou o avortar la instal·lació?" + +#~ msgid " miss checksum." +#~ msgstr "falta la suma de verificació." + +#~ msgid " fails checksum verification." +#~ msgstr " no supera la verificació de la suma de verificació." + +#~ msgid "Downloading %s" +#~ msgstr "S'està baixant %s" + +#, fuzzy +#~ msgid "Regarding all resolvables with a compatible architecture." +#~ msgstr "" +#~ "S'estan capturant els ítems amb dependències que coincideixen amb el " +#~ "criteri de cerca definit..." + +#, fuzzy +#~ msgid "Make a solver run with best architecture only." +#~ msgstr "" +#~ "S'estan capturant els ítems amb dependències que coincideixen amb el " +#~ "criteri de cerca definit..." + +#, fuzzy +#~ msgid "Regarding resolvables with best architecture only." +#~ msgstr "" +#~ "S'estan capturant els ítems amb dependències que coincideixen amb el " +#~ "criteri de cerca definit..." diff --git a/po/cs.po b/po/cs.po new file mode 100644 index 0000000..4994e81 --- /dev/null +++ b/po/cs.po @@ -0,0 +1,6306 @@ +# translation of zypp.po to +# Czech message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999-2001 SuSE GmbH. +# +# Petr Pavlik , 1999, 2000, 2001. +# Klara Cihlarova , 2006. +# Jakub Hegenbart , 2007. +# Marek Stopka , 2008. +# Klára Cihlářová , 2008. +# Vojtěch Zeisek , 2008. +# Marek Stopka , 2008. +# Radomír Černoch , 2009. +# Vojtěch Zeisek , 2010, 2015. +# Vít Pelčák , 2011. +# Jan Papež , 2011, 2013, 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-20 10:47+0000\n" +"Last-Translator: Aleš Kastner \n" +"Language-Team: Czech " +"\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: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Neznámá země: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Žádný kód" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Spojené arabské emiráty" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghánistán" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua a Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albánie" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Arménie" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Nizozemské Antily" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktida" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Americká Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Rakousko" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Austrálie" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Alandské ostrovy" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Ázerbájdžán" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosna a Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladéš" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgie" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulharsko" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrajn" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudy" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunej Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolívie" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazílie" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamy" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhútán" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet Island" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Bělorusko" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosové (Keelingovy) ostrovy" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Středoafrická republika" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Švýcarsko" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Pobřeží slonoviny" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookovy ostrovy" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Čína" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbie" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kostarika" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kapverdy" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Vánoční ostrov" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Kypr" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Česká republika" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Německo" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Džibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dánsko" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikánská republika" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alžírsko" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvádor" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonsko" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypt" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Západní Sahara" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Španělsko" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopie" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finsko" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandské ostrovy (Malvíny)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federativní státy Mikronésie" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faerské ostrovy" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francie" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Kontinentální Francie" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Velká Británie" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gruzie" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Francouzská Guajána" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grónsko" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambie" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Rovníková Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Řecko" + +# GS +# fuzzy +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Jižní Georgie a Jižní Sandwichovy ostrovy" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Ostrov Heard a McDonaldovi ostrovy" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Chorvatsko" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Maďarsko" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonésie" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irsko" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Ostrov Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indie" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britské indické oceánské teritorium" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irák" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Írán" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Itálie" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamajka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordánsko" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonsko" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Keňa" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kyrgyzstán" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodža" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komory" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts a Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Severní Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Jižní Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuvajt" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kajmanské ostrovy" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazachstán" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laoská lidově demokratická republika" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Svatá Lucie" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Lichtenštejnsko" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Srí Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Libérie" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litva" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Lucembursko" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Lotyšsko" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libye" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldávie" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Černá Hora" + +# SM +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Svatý Martin" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshallovy ostrovy" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonie" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar (Barma)" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolsko" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Severní Mariany" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinik" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritánie" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauricius" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Mali" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malajsie" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibie" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nové Kaledonie" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Ostrov Norfolk" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigérie" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nizozemí" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norsko" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepál" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nový Zéland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omán" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Francouzská Polynésie" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nová Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipíny" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pákistán" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polsko" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre a Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Portoriko" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestinské teritorium" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugalsko" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumunsko" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Srbsko" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Ruská Federace" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudská Arábie" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Šalamounovy ostrovy" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychely" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Súdán" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Švédsko" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Svatá Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovinsko" + +# SJ +# fuzzy +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Ostrovy Svalbard a Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovensko" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somálsko" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Svatý Tomáš a Princův ostrov" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Salvador" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Sýrie" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Svazijsko" + +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks a Caicos" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Čad" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Francouzská jižní teritoria" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thajsko" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistán" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistán" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunis" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Východní Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turecko" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad a Tobago" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tchaj-wan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzanie" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrajina" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Menší odlehlé ostrovy Spojených států" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Spojené státy" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistán" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikán" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Svatý Vincenc a Grenadiny" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britské Panenské ostrovy" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Panenské ostrovy, U.S." + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Ostrovy Wallis a Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Jižní Afrika" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambie" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Poskytuje" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Předpokládá" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Vyžaduje" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Konflikty" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Nahrazuje" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Doporučuje" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Navrhuje" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Vylepšuje" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Doplňuje" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Pokus o import neexistujícího klíče %s do klíčenky %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Nepodařilo se importovat klíč." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Nepodařilo se smazat klíč." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Soubor s podpisem %s nebyl nalezen" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Neznámý jazyk: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afarština" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abcházština" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Ačinézština" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afroasijské (jiné)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikánština" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadština" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albánština" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutština" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonkinské jazyky" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Jižní Altaj" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharština" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Angličtina, stará (cca. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apačské jazyky" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabština" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramejština" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonština" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Arménština" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Arakuánština" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Umělý (jiný)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Ásámština" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturian" + +# modules/inst_language.ycp:93 +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapascanské jazyky" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australské jazyky" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarština" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Jazyk Avesty" + +# SZ +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Avadhí" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymarština" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Ázerbájdžánština" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Jazyky Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Baškirština" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Bali" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskičtina" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltské (jiné)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Běloruština" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengálština" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berberské (jiné)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhodžpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihárština" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikolština" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Binijština" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantuské (jiné)" + +# BJ +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosenština" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonština" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonésie)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Burjatština" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugiština" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulharština" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Barmština" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Kado" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Středoamerické indiánské (jiné)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Karibské jazyky" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalánština" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kavkazské (jiné)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuánština" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltské (jiné)" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Čamorština" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Čibština" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Čečenština" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Čagatajské jazyky" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Čínština" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Čukština" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Marijština" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Slang Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctawština" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Čipeva" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Čerokézština" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Církevní slovanština" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Čejenština" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Čamicské jazyky" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptština" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Kornština" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsičtina" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreole a pidgin, založené na angličtině (jiné)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreole a pidgin, založené na francouzštině (jiné)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreole a pidgin, založené na portugalštině (jiné)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Krí" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krymská tatarština" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreole a pidgin (jiné)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kašubština" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Kušitské jazyky (jiné)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "České" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dánské" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Daják" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Athabaské jazyky" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Drávidské jazyky (jiné)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Dolní lužičtina" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Nizozemština, střední (cca 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nizozemština" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Staroegypština" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamština" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Angličtina" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Angličtina, střední (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonské" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faerština" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fidžijština" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipínština" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finské" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Ugrofinské (jiné)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francouzské" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francouzština, střední (cca 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francouzština, stará (842- cca 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Fríština" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fula" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Furlánština" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbejština" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germánské (jiné)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Gruzínština" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Němčina" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Giiz" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertština" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelština" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irština" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galicijština" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manština" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Středohornoněmčina (cca 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Starohornoněmčina (cca 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Góndí" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontálština" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gótština" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Starořečtina (do 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Novořečtina (od 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guaraní" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gudžarátština" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitština" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Havajština" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebrejština" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynonština" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himáčalí" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindština" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Chetitština" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +# HT +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hirimotu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Horní lužičtina" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Maďarština" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandština" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Ilokánsština" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (IALA)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indické (jiné)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonézština" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoevropské (jiné)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Inguština" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Íránské (jiné)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokézské jazyky" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italština" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Jávština" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonština" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Židovské perské jazyky" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Židovské arabské jazyky" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpakština" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabylština" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kačin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kambština" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannadština" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kašmírština" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanurijština" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazaština" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisanské (jiné)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmérština" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanština" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuju" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kyrgyzština" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkanština" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Konžština" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korejština" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kruština" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuaňama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumykština" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kudština" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahanda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laoština" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latina" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Lotyština" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburština" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litevština" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Lucemburština" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseňo" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luoština (Keňa a Tanzanie)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonština" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurština" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Maršalština" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasarština" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malajámština" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Malinština" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maorština" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronéské (jiné)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Maráthština" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masajština" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malajština" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandarština" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mendeština" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irština, střední (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mikmak" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabauština" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Různé jazyky" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-khmérské (jiné)" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgaština" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltština" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manču" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipurština" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Jazyky manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavština" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolština" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Více jazyků" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Mundské jazyky" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Krík" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Mayské jazyky" + +# SY +# fuzzy +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Severoamerické indiánské" + +# NP +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolština" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Jižní Ndebele" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Severní Ndebele" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Dolnoněmčina" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepálština" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepál Bhasa" + +# printers.ycp.noloc:1270 +# printers.ycp.noloc:1270 +# printers.ycp.noloc:1270 +# printers.ycp.noloc:1270 +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Niačtina" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Nigero-kordofánské (jiné)" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuečtina" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norština (Nynorsk)" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norština (Bokmal)" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norština, stará" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norština" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Severní Sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Núbijské jazyky" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newarština" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Čičeva" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankolština" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +# printers.ycp.noloc:1400 +# printers.ycp.noloc:1400 +# printers.ycp.noloc:1400 +# printers.ycp.noloc:1400 +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Okcitánština (po 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Orijština" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osetština" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Osmanská turečtina (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomianské jazyky" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuánština (jiné)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinština" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlaví" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Pandžábština" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palajština" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Staroperština (cca 600-400 př. n. l.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Perština" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipínské (jiné)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Féničtina" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Páli" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polština" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeiština" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugalština" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakritské jazyky" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Staroprovensálština (do 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Paštunština" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Kečuánština" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rádžáshánština" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanuiština (tahitština Velikonočního ostrova - Rapa-Nui)" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongánština (tahitština Velikonočního ostrova - Rapa-Nui)" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Románské (jiné)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Rétorománština" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romština" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumunština" + +# RE +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundština" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ruština" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandaweština" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sangoština" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Jakutština" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Jihoamerické indiánské (jiné)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salishanské jazyky" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritská Aramejština" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrt" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasačtina" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santálština" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Srbština" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilština" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Skotština" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Chorvatské" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkupština" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitské (jiné)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irština, stará (do 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Znakové řeči" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Šanština" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamské jazyky" + +# AO +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhalština" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouanské jazyky" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sinotibetské (jiné)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slovanské (jiné)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovenština" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovinština" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Jižní Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Severní Sami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Jazyky Sami (jiné)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lulejská Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inarijská Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoánština" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skoltská Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Šonština" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhština" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Soghdština" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somálština" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhajština" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Jihosotština" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Španělština" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinština" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Sererština" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilosaharské (jiné)" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundánština" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerština" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Svahilština" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Švédština" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syrština" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitština" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Thajské (jiné)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamilština" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatarština" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugština" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tádžičtina" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalština" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thajština" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetština" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigriňňa" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingonština" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamašek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tongánština (Nyasa)" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tongánština (Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshijské jazyky" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Čwana" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmenština" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Jazyky tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turečtina" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altajské (jiné)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Ťwiština" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvština" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritština" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Ujgurština" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrajinština" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Neurčený" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdština" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbečtina" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamština" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votština" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakashanské jazyky" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Velština" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Lužická srbština" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Valonština" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyčtina" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhoština" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Japština" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jidiš" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Jarubština" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Jazyky yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotécké jazyky" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zandština" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zuluština" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Budou provedeny následující akce:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "nevyprší nikdy" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "vypršel: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "vyprší: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(nevyprší nikdy)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(VYPRŠELO)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(vyprší během 24 hodin)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(vyprší během %d dne)" +msgstr[1] "(vyprší během %d dnů)" +msgstr[2] "(vyprší během %d dnů)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "neznámé" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nepodporováno" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Úroveň 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Úroveň 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Úroveň 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Je nutné uzavřít se zákazníkem další smlouvu" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Ukončeno a nahrazeno jiným balíčkem" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "neplatné" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Není určena úroveň podpory" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Poskytovatel neposkytuje podporu." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Detekce problému, tedy technická podpora zajišťuje informaci o slučitelnosti " +"produktů, asistenci při instalaci a používání, následnou údržbu a základní " +"řešení problémů. První úroveň podpory neslouží k opravám chyb v produktu." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Izolace problému, tedy podporu při zreplikování zákazníkova problému, " +"specifikace problematického místa a poskytuje řešení problémů, které neřeší " +"první úroveň." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Řešení problémů, tj. technická podpora, která řeší složité problémy " +"zajištěním technických pracovníků, kteří vyřeší vady produktů zjištěné na " +"úrovni 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Získání podpory vyžaduje další smlouvu se zákazníkem." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"Balíček byl zrušen/ukončen a byl nahrazen novým balíčkem s jiným názvem." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Neznámá volba podpory. Popis není dostupný" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Správa systému je uzamčena aplikací s identifikátorem PID %d (%s). \n" +"Ukončete tuto aplikaci a opakujte akci." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Neznámý mód shody '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Neznámý mód shody '%s' pro rys '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Chybný regulární výraz '%s': regcomp vrátil %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Neplatný regulární výraz: '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Pro '%s' je vyžadováno ověřování" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Zkusím to znovu..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Vzdávám se po %1% pokusech." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Pro kontrolu, zda je Vaše registrace platná a aktivní, navštivte Zákaznické " +"centrum SUSE." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Obraťte se na zákaznické centrum společnosti Novell a zkontrolujte, zda je " +"vaše registrace platná a zda nevypršela." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Vytvořit bod připojení: Nelze najít adresář, do kterého lze zapisovat, pro " +"vytvoření bodu připojení" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Nejprve nainstalujte balíček 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Nelze vytvořit adresář s mezipamětí metadat." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Chyba při čtení z '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Nelze vytvořit %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Na zadané adrese URL nebyla nalezena platná metadata" +msgstr[1] "Na zadaných adresách URL nebyla nalezena platná metadata" +msgstr[2] "Na zadaných adresách URL nebyla nalezena platná metadata" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "Nepodařilo se přenést úložiště do mezipaměti (nelze spustit repo2solv)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Chyba při načítání úložiště do mezipaměti (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Vytváří se vyrovnávací paměť úložiště '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Nelze vytvořit mezipaměť v %s - chybí oprávnění k zápisu." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "Nepodařilo se přenést úložiště %1% do mezipaměti" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Nepodporovaný typ úložiště" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Přidává se úložiště %s" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Název souboru úložiště na adrese URL „%s“ je neplatný" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Nelze otevřít soubor '%s' pro zápis." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Neznámá chyba při čtení z '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Nelze číst z adresáře úložiště %1%: Přístup odepřen" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Chyba při čtení z adresáře %s" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Nelze přečíst soubor úložiště %1%: Přístup odepřen" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "Čistění metadat" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "Čistění balíčků" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "Čistění adresářů mezipaměti" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "Čistění adresáře: %1%" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "Čistění mezipaměti" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "Načítání z mezipaměti" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Odebírá se úložiště %s" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Nelze zjistit umístění úložiště." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "'%s' nelze smazat" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "Úprava úložiště" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "Obnovení úložiště: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Nelze zjistit umístění služby." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Neznámá služba '%1%': Odstraňuje se osiřelé úložiště služby '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Alias úložiště nemůže začínat tečkou." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Alias služby nemůže začínat tečkou." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Žádný souhrn pro soubor %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Neznámý souhrn %s pro soubor %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Ověření souhrnu pro soubor '%s' se nezdařilo" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Soubor '%s' není podepsán, pokračovat?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Soubor '%s' z úložiště '%s' není podepsán, pokračovat?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Chcete klíč odmítnout, důvěřovat dočasně, nebo důvěřovat vždy?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Název klíče: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "Získán %1% nový podpisový klíč balíčku z úložiště \"%2%\":" +msgstr[1] "Získány %1% nové podpisové klíče balíčků z úložiště \"%2%\":" +msgstr[2] "Získáno %1% nových podpisových klíčů balíčků z úložiště \"%2%\":" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Ověření podpisu souboru '%1%' se nezdařilo." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "Ověření podpisu souboru '%1%' z úložiště '%2%' se nezdařilo." + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Pokračovat?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Soubor '%s' je podepsán neznámým klíčem '%s'. Pokračovat?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Soubor '%s' z úložiště '%s' je podepsán neznámým klíčem '%s'. Pokračovat?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Úložiště %1% nedefinuje přídavná URL 'gpgkey='." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Hledám ID klíče gpg %1% v úložišti %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Hledám ID klíče gpg %1% v paměti %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Chybí vyžadovaný atribut '%s'." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Je požadován alespoň jeden z atributů „%s“ a „%s“." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Ověření podpisu selhalo" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "Balíček %s se zřejmě poškodil během přenosu. Chcete pokus opakovat?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Nepodařilo se poskytnout balíček %s. Chcete jej stáhnout znovu?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Kontrola aplikování delta RPM se nezdařila." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "Aplikování delta RPM se nezdařilo." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Zásuvný modul Service nepodporuje změnu atributů." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Nelze poskytnout soubor '%s' z repozitáře '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Adresa URL nebyla nalezena v repozitáři." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "Očekáváno médium %1%/%2% identifikované podle souboru '%3%' s obsahem:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Soubor %1%\n" +" z balíčku\n" +" %2%\n" +" je v konfliktu se souborem z balíčku\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Soubor %1%\n" +" z balíčku\n" +" %2%\n" +" je v konfliktu se souborem instalovaným z\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Soubor %1%\n" +" instalovaný z\n" +" %2%\n" +" je v konfliktu se souborem z balíčku\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Soubor %1%\n" +" instalovaný z\n" +" %2%\n" +" je v konfliktu se souborem instalovaným z\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Soubor %1%\n" +" z balíčku\n" +" %2%\n" +" je v konfliktu se souborem\n" +" %3%\n" +" z balíčku\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Soubor %1%\n" +" z balíčku\n" +" %2%\n" +" je v konfliktu se souborem\n" +" %3%\n" +" instalovaným z\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Soubor %1%\n" +" instalovaný z\n" +" %2%\n" +" je v konfliktu se souborem\n" +" %3%\n" +" z balíčku\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Soubor %1%\n" +" instalovaný z\n" +" %2%\n" +" je v konfliktu se souborem\n" +" %3%\n" +" instalovaným z\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Nemohu vytvořit sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "porušit %s ignorováním některých z jeho závislostí" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "obecně ignorovat některé závislosti" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"nainstalované %1% nepochází z úložiště distribuce upgradů a musí být " +"nahrazeno" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "instalovaný %1% nepochází z distribučního úložiště" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "nainstalované %1% má starší architekturu" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "%1% k instalaci má starší architekturu" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problém s instalovaným %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "protichůdné požadavky" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "nějaký problém se závislostmi" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "nikdo neposkytuje požadované '%1%'" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Povolili jste všechna požadovaná úložiště?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "požadovaný balíček %1% neexistuje" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "nepodporovaný požadavek" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' poskytuje systém a nelze jej vymazat" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% není instalovatelný" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "nikdo neposkytuje '%1%' potřebné nainstalovaným %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "nikdo neposkytuje '%1%' potřebné k instalaci %2%" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "nelze nainstalovat %1% i %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"nainstalovaný %1% je v konfliktu s '%2%' poskytnutým nainstalovaným %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "nainstalovaný %1% je v konfliktu s '%2%' potřebným k instalaci %3%" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"%1%, který se má instalovat, je v konfliktu s '%2%' poskytnutým " +"nainstalovaným %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"má se instalovat %1%, ale je v konfliktu s '%2%' poskytnutým %3% k instalaci" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "nainstalované %1% zastarává '%2%' poskytované nainstalovaným %3%" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"nainstalované %1% zastarává '%2%' poskytované %3%, jež se má instalovat" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "má se instalovat %1% jež zastarává '%2%' poskytované instalovaným %3%" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"Má se instalovat %1%, jež zastarává '%2%' poskytované %3%, jež se má " +"instalovat" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "nainstalované %1% je v konfliktu s '%2%' poskytnutým samo sebou" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "má se instalovat %1%, ale je v konfliktu s '%2%' poskytnutým jím samým" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "nainstalované %1% vyžaduje '%2%', ale tento požadavek nelze splnit" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"má se instalovat %1% vyžadující '%2%', ale tento požadavek nelze splnit" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "odstranění poskytovatelé: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"neinstalovatelní poskytovatelé: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "neinstalovatelní poskytovatelé: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% ještě není plně zaintegrován do %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Obvykle budete chtít ponechat PTF a vybrat, že nechcete instalovat údržbové " +"záplaty." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Odstranění nainstalovaného %1% v tomto kontextu odstraní (nikoli nahradí!) " +"také obsažené balíčky PTF." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"Tímto se obsažené balíčky PTF aktualizují a neodstraní. PTF by měly být " +"odstraněny voláním '%1%'." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Obvykle chcete PTF ponechat nebo se rozhodnete akci zrušit." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Nainstalovaný %1% blokuje vyžadovanou akci." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Obvykle budete chtít ponechat PTF a vybrat zrušení této akce." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "odstraňte zámek, aby šlo odebrat %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "neinstalujte %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "ponechte %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "odstraňte zámek a tím povolte instalaci %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Tento požadavek poškodí váš systém!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorovat varování poškozeného systému" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "nežádejte instalaci řešení poskytující %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "nepožadovat smazání všech řešitelných problémů poskytujících% 1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "neinstalujte nejnovější verzi %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "ponechte %1% navzdory starší architektuře" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "instalujte %1% navzdory starší architektuře" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "zachovejte zastaralou %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "nainstalujte %1% z vyloučeného úložiště" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "instalovat %1%, ačkoli byl odvolán" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "umožnit instalaci PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "instalovat %1%, ačkoli je na indexu" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "downgrade z %1% na %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "změna architektury %1% na %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"nainstalovat %1% (se změnou dodavatele)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"instalovat %1% od dodavatele %2%\n" +" nahradit %3% od dodavatele %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "náhrada %1% %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "odinstalace %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Spuštění skriptů po transakci" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Spuštění skriptu %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Výstup skriptu %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Instalace byla zrušena podle příkazu." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " provedeno" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " provádění selhalo" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s je již prováděn jako %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " provádění přeskočeno během ukončování" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Chyba při odesílání oznámení o aktualizaci." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nová zpráva o aktualizaci" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Přijat signál: \"%1% (%2%)\" - kvůli konzistenci systému nelze zrušit " +"probíhající transakci RPM." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Provedení transakce se nezdařilo kvůli následujícím problémům:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM selhalo: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Nepodařilo se importovat veřejný klíč %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Nepodařilo se smazat veřejný klíč %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Hlavička balíčku není podepsaná!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Obsah balíčku není podepsán!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Změněné konfigurační soubory pro %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "Program rpm uložil %s jako %s, ale nebylo možné zjistit rozdíl" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"Program rpm uložil %s jako %s.\n" +"Prvních 25 řádek rozdílů:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "Program rpm vytvořil %s jako %s, ale nebylo možné zjistit rozdíl" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"Program rpm vytvořil %s jako %s.\n" +"Prvních 25 řádek rozdílů:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Další výstup programu rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "vytvořena záloha %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Podpis je v pořádku" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Neznámý typ podpisu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Podpis nelze ověřit" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Podpis je v pořádku, ale klíč není důvěryhodný" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Veřejný klíč podpisu není k dispozici" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Soubor neexistuje nebo podpis nemůže být zkontrolován" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Soubor není podepsaný" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Pochybný typ %s pro %u-bajtový kontrolní součet %s" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Nelze otevřít pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Nelze otevřít rouru (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Neplatný řetězec dotazu LDAP URL" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Neplatný parametr dotazu LDAP URL %s" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Nelze klonovat objekt URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Neplatný odkaz na objekt prázdného URL" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Nelze analyzovat součásti URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historie:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Schéma URL nepovoluje %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Neplatná %s součást %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Neplatná %s součást" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Pro toto URL není podporována analýza řetězce dotazu" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL schéma je vyžadovanou součástí" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Neplatné schéma URL %s" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Schéma URL nepovoluje uživatelské jméno" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Schéma URL nepovoluje heslo" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Schéma URL vyžaduje součást hostitele" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Schéma URL nepovoluje součást hostitele" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Neplatná součást hostitele %s" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Schéma URL nepovoluje port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Neplatná součást portu %s" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Schéma URL vyžaduje název cesty" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relativní cesta není povolena, pokud existuje autorita" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Zakódovaný řetězec obsahuje bajt NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Neplatný oddělovací znak pole parametrů" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Neplatný oddělovací znak mapy parametrů" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Neplatný oddělovací znak spojení pole parametrů" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Příkaz skončil se stavem %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Příkaz byl ukončen signálem %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Příkaz skončil s neznámou chybou." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Zadány neplatné argumenty spawn." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Nelze vytvořit řídicí kanál." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Nelze změnit kořenový adresář na '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Nelze změnit adresář na '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" +"Nelze změnit adresář na '%s' uvnitř chrootem změněného kořenového adresáře " +"'%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Nelze spustit '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Nelze forknout (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Nelze spustit '%s', chyba chdir (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Nelze spustit '%s', chyba chroot (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Nelze spustit '%s', chyba exec (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Nelze spustit '%s', neočekávaná chyba." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Nepodařilo se připojit %s do %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Nepodařilo se odpojit %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Špatný název souboru: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Při pokusu o provedení akce '%s' nebylo otevřeno médium." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Soubor '%s' nebyl nalezen na médiu '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Nemůžu zapsat do souboru '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Médium není připojeno" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Špatný bod připojení média" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Inicializace stažení (curl) '%s' selhala" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Systémová výjimka '%s' na médiu '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Cesta '%s' na médiu '%s' není souborem." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Cesta '%s' na médiu '%s' není adresářem." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Chybné URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Není vyplněno hostname v URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Prázdný souborový systém v URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Chybí cíl v URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Nepodporované schéma URI v '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operace není médiem podporována" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Chyba stahování (curl) pro '%s':\n" +"Kód chyby: %s\n" +"Chybová zpráva: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Při nastavení možností stahování (curl) pro '%s' došlo k chybě:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Zdroj média \"%s\" neobsahuje požadované médium" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Médium '%s' je používáno jinou instancí" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Nemůžu vysunout žádné médium" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Nemůžu vysunout médium '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Přístup k '%s' byl zamítnut." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Během přístupu k '%s' byl dosažen časový limit." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Stažená data překročila očekávanou velikost '%s' souboru '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Umístění '%s' je dočasně nedostupné." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Problém s SSL certifikátem, ověřte, že je certifikát certifikační autority " +"pro '%s' v pořádku." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Pro připojení média nejsou k dispozici žádné volné zdroje." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Nepodporovaná HTTP ověřovací metoda '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Chyba stahování (curl) pro '%s':\n" +"Kód chyby: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Chyba stahování (curl) pro '%s':\n" +"Nelze načíst odpověď HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ano" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ne" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Poznámka:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Pozor:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Chyba:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "dokončeno" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "upozornění" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "chyba" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Upozornění: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Získávám:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "startuji" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "nenalezeno" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "K této výzvě není k dispozici žádná nápověda." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "k této volbě není k dispozici žádná nápověda" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "zobrazí všechny volby" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ano" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ne" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Běží skript %%posttrans '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Běží skripty %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "Balíček není podepsaný!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s nenáleží do repozitáře pro aktualizaci distribuce" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s má podřadnou architekturu" + +#~ msgid "problem with installed package %s" +#~ msgstr "problém s nainstalovaným balíčkem %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "nic neposkytuje vyžádaný %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Máte povoleny všechny vyžadované repozitáře?" + +#~ msgid "package %s does not exist" +#~ msgstr "balíček %s neexistuje" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s je poskytováno systémem a nelze odinstalovat" + +#~ msgid "%s is not installable" +#~ msgstr "%s nelze nainstalovat" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "nic neposkytuje %s, který je požadován %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "Nelze nainstalovat %s a zároveň %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s koliduje s %s, poskytovatel: %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s nahrazuje %s, poskytovatel: %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "nainstalováno: %s, zastaralé: %s, poskytovatel: %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "vyřešitelné %s je v konfliktu s %s, které sám poskytuje" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s vyžaduje %s, ale tento požadavek nemůže být splněn" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "odebrat zámek pro umožnění odebrání %s" + +#~ msgid "do not install %s" +#~ msgstr "neinstalovat %s" + +#~ msgid "keep %s" +#~ msgstr "ponechat %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "odebrat zámek pro umožnění instalace položky %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "nenabízet řešení, která zahrnují %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "neptat se na smazání všech balíčků poskytujících %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "neinstalovat nejnovější verzi %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "ponechat %s i přes podřadnou architekturu" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "Instalovat %s i přes podřadnou architekturu" + +#~ msgid "keep obsolete %s" +#~ msgstr "ponechat zastaralý %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "instalovat %s z vyloučeného repozitáře" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "downgrade %s na %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "změna architektury z %s na %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "instalovat %s (i se změnou poskytovatele)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "nahrazení %s položkou %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "odinstalace %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Nelze otevřít soubor zámku: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Tato akce je právě spuštěna jiným programem." + +#~ msgid "Hal Exception" +#~ msgstr "Výjimka HAL" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Bohužel, tato verze libzypp byla sestavena bez podpory HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HALContext není připojen" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HALDrive není inicializovaný" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HALVolume není inicializovaný" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Nelze vytvořit připojení dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Nelze vytvořit kontext libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Nelze nastavit připojení dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Nelze inicializovat kontext HAL - je spuštěna služba hald?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Není jednotka CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Nelze inicializovat atributy mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Nelze nastavit rekurzivní atribut mutex" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Nelze inicializovat rekurzivní mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Nelze získat zámek mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Nelze uvolnit zámek mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Nepodařilo se importovat veřejný klíč ze souboru %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Nepodařilo se smazat veřejný klíč %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Nelze najít dostupné zařízení loop pro připojení souboru obrazu z '%s'" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "obecně ignorovat některé závislosti" + +#~ msgid "do not keep %s installed" +#~ msgstr "neudržovat %s nainstalován" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "Nemůžu vytvořit veřejný klíč %s z klíčenky %s do souboru %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "Pokus o import neexistujícího klíče %s mezi klíče %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Nemůžu změnit adresář na '/' uvnitř chrootu (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Inicializace stažení (Metalink curl) selhala na '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Stažení (Metalink curl) selhalo pro '%s':\n" +#~ "Chybový kód: %s\n" +#~ "Chybová zpráva: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Stahování přerušeno na %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Stahování přerušeno uživatelem" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Během zakládání stahování (metalink curl) došlo k chybě v nastavení pro " +#~ "'%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Nepodařilo se stáhnout %s z %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Srbsko a Černá Hora" + +#~ msgid "Unknown Distribution" +#~ msgstr "Neznámá distribuce" + +#~ msgid "ignore some dependencies of %s" +#~ msgstr "ignorovat některé závislosti %s" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Soubor %s nemá kontrolní součet.\n" +#~ "Chcete soubor přesto použít?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Nezdařila se kontrola integrity souboru %s s následujícím klíčem:\n" +#~ "%s|%s|%s\n" +#~ " Chcete soubor přesto použít?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Soubor %s má neplatný kontrolní součet.\n" +#~ "Očekáváno %s, nalezeno %s\n" +#~ "Chcete soubor přesto použít?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Soubor %s má neznámý kontrolní součet %s.\n" +#~ "Chcete soubor přesto použít?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Soubor %s není podepsán.\n" +#~ "Chcete jej přesto použít?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Soubor %s je podepsán neznámým klíčem:\n" +#~ "%s|%s|%s\n" +#~ " Chcete soubor přesto použít?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Byl nalezen nedůvěryhodný klíč:\n" +#~ "%s|%s|%s\n" +#~ " Chcete mu důvěřovat?" diff --git a/po/cy.po b/po/cy.po new file mode 100644 index 0000000..6a87ca2 --- /dev/null +++ b/po/cy.po @@ -0,0 +1,5677 @@ +# Welsh message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2003 SuSE Linux AG. +# Kevin Donnelly , 2003. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2003-09-23 10:33+0200\n" +"Last-Translator: Kevin Donnelly \n" +"Language-Team: Welsh \n" +"Language: cy\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 == 0 ? 0 : n == 1 ? 1 : n < 6 ? 2 : n == " +"6 ? 3 : 4);\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +#, fuzzy +msgid "No Code" +msgstr "Modd" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +#, fuzzy +msgid "Armenia" +msgstr "Affrica" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +#, fuzzy +msgid "Netherlands Antilles" +msgstr "Yr Iseldiroedd" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +#, fuzzy +msgid "Antarctica" +msgstr "Iwerydd" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +#, fuzzy +msgid "Argentina" +msgstr "Arizona" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Awstria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Awstralia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +#, fuzzy +msgid "Aruba" +msgstr "Dubai" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +#, fuzzy +msgid "Bosnia and Herzegovina" +msgstr "Bosnia & Herzegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Gwlad Belg" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bwlgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +#, fuzzy +msgid "Burundi" +msgstr "Brunei" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +#, fuzzy +msgid "Brazil" +msgstr "Dwyrain Brasil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +#, fuzzy +msgid "Bahamas" +msgstr "Panama" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +#, fuzzy +msgid "Bhutan" +msgstr "Bahrain" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +#, fuzzy +msgid "Bouvet Island" +msgstr "Queensland" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +#, fuzzy +msgid "Belarus" +msgstr "Beirut" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +#, fuzzy +msgid "Belize" +msgstr "Gwlad Belg" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +#, fuzzy +msgid "Congo" +msgstr "Hongkong" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "Gweriniaeth Czech" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Y Swistir" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +#, fuzzy +msgid "Chile" +msgstr "Tseina" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +#, fuzzy +msgid "Cameroon" +msgstr "Cairo" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Tseina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +#, fuzzy +msgid "Colombia" +msgstr "Colombo" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +#, fuzzy +msgid "Cuba" +msgstr "Ceuta" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +#, fuzzy +msgid "Christmas Island" +msgstr "Chile Easter Island" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Gweriniaeth Czech" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Yr Almaen" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Denmarc" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +#, fuzzy +msgid "Dominican Republic" +msgstr "Gweriniaeth Czech" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +#, fuzzy +msgid "Algeria" +msgstr "Algiers" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Yr Aifft" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Sbaen" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +#, fuzzy +msgid "Ethiopia" +msgstr "Estonia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Ffindir" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +#, fuzzy +msgid "Faroe Islands" +msgstr "Iwerddon" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Ffrainc" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Y Deyrnas Unedig" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Yr Almaen" + +#: zypp/CountryCode.cc:238 +#, fuzzy +msgid "Ghana" +msgstr "Gaza" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +#, fuzzy +msgid "Greenland" +msgstr "Iwerddon" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +#, fuzzy +msgid "Gambia" +msgstr "Jamaica" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +#, fuzzy +msgid "Guinea" +msgstr "Guam" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Groeg" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +#, fuzzy +msgid "Guyana" +msgstr "Guam" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +#, fuzzy +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +#, fuzzy +msgid "Honduras" +msgstr "Awr" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +#, fuzzy +msgid "Haiti" +msgstr "Hawaii" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hwngari" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Iwerddon" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +#, fuzzy +msgid "India" +msgstr "Inetd" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +#, fuzzy +msgid "Iraq" +msgstr "Israel" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +#, fuzzy +msgid "Iran" +msgstr "Iwerddon" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Gwlad yr Iâ" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Yr Eidal" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Siapan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +#, fuzzy +msgid "Kenya" +msgstr "Corea" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +#, fuzzy +msgid "Cambodia" +msgstr "Samoa" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +#, fuzzy +msgid "North Korea" +msgstr "Gogledd Iwerddon" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +#, fuzzy +msgid "South Korea" +msgstr "Pegwn y De" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lithuania" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latfia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +#, fuzzy +msgid "Libya" +msgstr "Lima" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +#, fuzzy +msgid "Morocco" +msgstr "Monaco" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldofa" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "Monaco" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "Shanghai" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +#, fuzzy +msgid "Mali" +msgstr "Malta" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +#, fuzzy +msgid "Myanmar" +msgstr "Panama" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +#, fuzzy +msgid "Mongolia" +msgstr "Monrovia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +#, fuzzy +msgid "Northern Mariana Islands" +msgstr "Gogledd Iwerddon" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +#, fuzzy +msgid "Mauritania" +msgstr "Lithuania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +#, fuzzy +msgid "Mauritius" +msgstr "Martinique" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +#, fuzzy +msgid "Malawi" +msgstr "Malta" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +#, fuzzy +msgid "Mexico" +msgstr "Mecsico Cyffredinol" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +#, fuzzy +msgid "Malaysia" +msgstr "Malta" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +#, fuzzy +msgid "Mozambique" +msgstr "Martinique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +#, fuzzy +msgid "Namibia" +msgstr "Nairobi" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +#, fuzzy +msgid "New Caledonia" +msgstr "Macedonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +#, fuzzy +msgid "Norfolk Island" +msgstr "Gogledd Iwerddon" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +#, fuzzy +msgid "Nicaragua" +msgstr "Managua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Yr Iseldiroedd" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norwy" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +#, fuzzy +msgid "Niue" +msgstr "Munud" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +#, fuzzy +msgid "New Zealand" +msgstr "Yr Iseldiroedd" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +#, fuzzy +msgid "Oman" +msgstr "Rh" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +#, fuzzy +msgid "Peru" +msgstr "Perth" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +#, fuzzy +msgid "Pakistan" +msgstr "Pitcairn" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Gwlad y Pwyl" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portiwgal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +#, fuzzy +msgid "Paraguay" +msgstr "Managua" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +#, fuzzy +msgid "Reunion" +msgstr "Rhedeg" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "Gwasanaeth" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +#, fuzzy +msgid "Rwanda" +msgstr "Canada" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +#, fuzzy +msgid "Sudan" +msgstr "Sbaen" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Sweden" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slofenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slofakia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +#, fuzzy +msgid "Somalia" +msgstr "Romania" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +#, fuzzy +msgid "Suriname" +msgstr "Enw'r gwasanae&th" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +#, fuzzy +msgid "Swaziland" +msgstr "Y Swistir" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +#, fuzzy +msgid "Chad" +msgstr "Wedi'u Newid" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +#, fuzzy +msgid "Togo" +msgstr "Tokyo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +#, fuzzy +msgid "Thailand" +msgstr "Ffindir" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +#, fuzzy +msgid "Tunisia" +msgstr "Tunis" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Twrci" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +#, fuzzy +msgid "Tuvalu" +msgstr "Zulu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +#, fuzzy +msgid "Taiwan" +msgstr "Vatican" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +#, fuzzy +msgid "Tanzania" +msgstr "Tasmania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Wcrain" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +#, fuzzy +msgid "Uganda" +msgstr "Canada" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +#, fuzzy +msgid "South Africa" +msgstr "Affrica" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +#, fuzzy +msgid "Zambia" +msgstr "Jamaica" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "&Dileu" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +#, fuzzy +msgid "Afar" +msgstr "Affrica" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +#, fuzzy +msgid "Abkhazian" +msgstr "Albania" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +#, fuzzy +msgid "Adangme" +msgstr "&Uwch" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +#, fuzzy +msgid "Afrikaans" +msgstr "Affrica" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +#, fuzzy +msgid "Ainu" +msgstr "Gweithred" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +#, fuzzy +msgid "Akan" +msgstr "Alaska" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +#, fuzzy +msgid "Albanian" +msgstr "Albania" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +#, fuzzy +msgid "Aleut" +msgstr "Aleutian" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +#, fuzzy +msgid "Algonquian Languages" +msgstr "Iaith" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "Gogledd Iwerddon" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +#, fuzzy +msgid "Amharic" +msgstr "Affrica" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +#, fuzzy +msgid "Apache Languages" +msgstr "Iaith" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +#, fuzzy +msgid "Arabic" +msgstr "Affrica" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +#, fuzzy +msgid "Aramaic" +msgstr "Jamaica" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +#, fuzzy +msgid "Armenian" +msgstr "Aleutian" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +#, fuzzy +msgid "Assamese" +msgstr "Negeseuon" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +#, fuzzy +msgid "Asturian" +msgstr "Awstria" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +#, fuzzy +msgid "Athapascan Languages" +msgstr "Awstralia" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +#, fuzzy +msgid "Australian Languages" +msgstr "Awstralia" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +#, fuzzy +msgid "Avaric" +msgstr "Affrica" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +#, fuzzy +msgid "Avestan" +msgstr "Aleutian" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +#, fuzzy +msgid "Banda" +msgstr "Canada" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +#, fuzzy +msgid "Bamileke Languages" +msgstr "Iaith" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +#, fuzzy +msgid "Bambara" +msgstr "Samarkand" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +#, fuzzy +msgid "Balinese" +msgstr "Pennawd" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +#, fuzzy +msgid "Basa" +msgstr "Alaska" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +#, fuzzy +msgid "Belarusian" +msgstr "Bwlgaria" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +#, fuzzy +msgid "Bemba" +msgstr "Bermuda" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +#, fuzzy +msgid "Bihari" +msgstr "Bahrain" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +#, fuzzy +msgid "Bini" +msgstr "Brunei" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +#, fuzzy +msgid "Breton" +msgstr "Freetown" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +#, fuzzy +msgid "Buriat" +msgstr "Bwlgaria" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +#, fuzzy +msgid "Bulgarian" +msgstr "Bwlgaria" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +#, fuzzy +msgid "Caddo" +msgstr "Cairo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +#, fuzzy +msgid "Carib" +msgstr "Cairo" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +#, fuzzy +msgid "Catalan" +msgstr "Casablanca" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +#, fuzzy +msgid "Cebuano" +msgstr "Ceuta" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +#, fuzzy +msgid "Chamorro" +msgstr "Cairo" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +#, fuzzy +msgid "Chibcha" +msgstr "Tseina" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +#, fuzzy +msgid "Chagatai" +msgstr "Shanghai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +#, fuzzy +msgid "Chinese" +msgstr "Tseina" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +#, fuzzy +msgid "Mari" +msgstr "Darwin" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "Iaith" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +#, fuzzy +msgid "Coptic" +msgstr "Costa Rica" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +#, fuzzy +msgid "Corsican" +msgstr "Costa Rica" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +#, fuzzy +msgid "Cree" +msgstr "Cre&u" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +#, fuzzy +msgid "Dakota" +msgstr "Dakar" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +#, fuzzy +msgid "Danish" +msgstr "&Gorffen" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +#, fuzzy +msgid "Dargwa" +msgstr "Darwin" + +#. language code: day +#: zypp/LanguageCode.cc:379 +#, fuzzy +msgid "Dayak" +msgstr "Dakar" + +#. language code: del +#: zypp/LanguageCode.cc:381 +#, fuzzy +msgid "Delaware" +msgstr "Caledwedd" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +#, fuzzy +msgid "Dinka" +msgstr "Dominica" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +#, fuzzy +msgid "Duala" +msgstr "Palau" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +#, fuzzy +msgid "Dutch" +msgstr "De" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +#, fuzzy +msgid "Dyula" +msgstr "Dubai" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +#, fuzzy +msgid "Esperanto" +msgstr "Dwyrain" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +#, fuzzy +msgid "Estonian" +msgstr "Estonia" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +#, fuzzy +msgid "Fang" +msgstr "Baneri" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +#, fuzzy +msgid "Fanti" +msgstr "Iwerydd" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +#, fuzzy +msgid "Fijian" +msgstr "Fiji" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +#, fuzzy +msgid "Finnish" +msgstr "&Gorffen" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +#, fuzzy +msgid "French" +msgstr "Greenwich" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +#, fuzzy +msgid "Frisian" +msgstr "Yn gorffen" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +#, fuzzy +msgid "Fulah" +msgstr "Baneri" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +#, fuzzy +msgid "Friulian" +msgstr "Ffindir" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +#, fuzzy +msgid "Ga" +msgstr "Guam" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +#, fuzzy +msgid "Gbaya" +msgstr "Gaza" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +#, fuzzy +msgid "Georgian" +msgstr "Yr Almaen" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +#, fuzzy +msgid "German" +msgstr "Yr Almaen" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +#, fuzzy +msgid "Geez" +msgstr "Groeg" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +#, fuzzy +msgid "Galician" +msgstr "Vatican" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +#, fuzzy +msgid "Manx" +msgstr "&Uchaf" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +#, fuzzy +msgid "Gujarati" +msgstr "Cyfnod" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +#, fuzzy +msgid "Gwich'in" +msgstr "Michigan" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +#, fuzzy +msgid "Haida" +msgstr "Caledwedd" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "Vatican" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +#, fuzzy +msgid "Hawaiian" +msgstr "Hawaii" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +#, fuzzy +msgid "Herero" +msgstr "gwall" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +#, fuzzy +msgid "Hmong" +msgstr "Hongkong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +#, fuzzy +msgid "Hungarian" +msgstr "Hwngari" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +#, fuzzy +msgid "Icelandic" +msgstr "Gwlad yr Iâ" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "Lithuania" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +#, fuzzy +msgid "Interlingue" +msgstr "Parhau" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +#, fuzzy +msgid "Iloko" +msgstr "Tokyo" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +#, fuzzy +msgid "Iroquoian Languages" +msgstr "Iaith" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +#, fuzzy +msgid "Italian" +msgstr "Yr Eidal" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +#, fuzzy +msgid "Javanese" +msgstr "Siapan" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +#, fuzzy +msgid "Japanese" +msgstr "Siapan" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +#, fuzzy +msgid "Kabyle" +msgstr "Alluogir" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +#, fuzzy +msgid "Kachin" +msgstr "Bahrain" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +#, fuzzy +msgid "Kamba" +msgstr "Katmandu" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +#, fuzzy +msgid "Kannada" +msgstr "Canada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +#, fuzzy +msgid "Karen" +msgstr "Corea" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +#, fuzzy +msgid "Kawi" +msgstr "Darwin" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +#, fuzzy +msgid "Kazakh" +msgstr "Gaza" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +#, fuzzy +msgid "Kirghiz" +msgstr "Virgin" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +#, fuzzy +msgid "Kimbundu" +msgstr "Katmandu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +#, fuzzy +msgid "Kongo" +msgstr "Hongkong" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +#, fuzzy +msgid "Korean" +msgstr "Corea" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +#, fuzzy +msgid "Kosraean" +msgstr "Corea" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +#, fuzzy +msgid "Kuanyama" +msgstr "Panama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +#, fuzzy +msgid "Kumyk" +msgstr "Dymi" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +#, fuzzy +msgid "Kutenai" +msgstr "Kuwait" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +#, fuzzy +msgid "Lahnda" +msgstr "Canada" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +#, fuzzy +msgid "Lamba" +msgstr "Lima" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +#, fuzzy +msgid "Latin" +msgstr "Lleoliad" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +#, fuzzy +msgid "Latvian" +msgstr "Latfia" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "Luxembourg" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +#, fuzzy +msgid "Lithuanian" +msgstr "Lithuania" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +#, fuzzy +msgid "Mongo" +msgstr "Monaco" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +#, fuzzy +msgid "Lozi" +msgstr "Mew&ngofnodi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "Luxembourg" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +#, fuzzy +msgid "Ganda" +msgstr "Canada" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "Tahiti" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +#, fuzzy +msgid "Macedonian" +msgstr "Macedonia" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +#, fuzzy +msgid "Madurese" +msgstr "Llygoden" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +#, fuzzy +msgid "Magahi" +msgstr "Managua" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +#, fuzzy +msgid "Makasar" +msgstr "Dakar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "" + +#. language code: man +#: zypp/LanguageCode.cc:711 +#, fuzzy +msgid "Mandingo" +msgstr "Rhybudd" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +#, fuzzy +msgid "Maori" +msgstr "Monrovia" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +#, fuzzy +msgid "Masai" +msgstr "Tasmania" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "Malta" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +#, fuzzy +msgid "Mandar" +msgstr "Manila" + +#. language code: men +#: zypp/LanguageCode.cc:731 +#, fuzzy +msgid "Mende" +msgstr "Modd" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "Managua" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "Managua" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +#, fuzzy +msgid "Maltese" +msgstr "Malta" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +#, fuzzy +msgid "Manchu" +msgstr "&Cychwyn" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "Managua" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "Moldofa" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +#, fuzzy +msgid "Mongolian" +msgstr "Monrovia" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +#, fuzzy +msgid "Mossi" +msgstr "Llygoden" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "Iaith" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +#, fuzzy +msgid "Munda languages" +msgstr "Iaith" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +#, fuzzy +msgid "Creek" +msgstr "Cre&u" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +#, fuzzy +msgid "Marwari" +msgstr "Caledwedd" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "Managua" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +#, fuzzy +msgid "North American Indian" +msgstr "Gogledd Iwerddon" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "Yr Almaen" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +#, fuzzy +msgid "Norwegian" +msgstr "Norwy" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +#, fuzzy +msgid "Northern Sotho" +msgstr "Gogledd Iwerddon" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "Iaith" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +#, fuzzy +msgid "Chichewa" +msgstr "Tseina" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +#, fuzzy +msgid "Nyoro" +msgstr "Gogledd" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +#, fuzzy +msgid "Nzima" +msgstr "Lima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +#, fuzzy +msgid "Osage" +msgstr "Negeseuon" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +#, fuzzy +msgid "Ossetian" +msgstr "Aleutian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "Iaith" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +#, fuzzy +msgid "Pangasinan" +msgstr "Panama" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +#, fuzzy +msgid "Pahlavi" +msgstr "Palau" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +#, fuzzy +msgid "Pampanga" +msgstr "Tasmania" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +#, fuzzy +msgid "Panjabi" +msgstr "Panama" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +#, fuzzy +msgid "Palauan" +msgstr "Palau" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +#, fuzzy +msgid "Persian" +msgstr "&Fersiwn RPC" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +#, fuzzy +msgid "Pali" +msgstr "Palau" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +#, fuzzy +msgid "Portuguese" +msgstr "Portiwgal" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "Iaith" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "Siapan" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "Romania" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +#, fuzzy +msgid "Romanian" +msgstr "Romania" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +#, fuzzy +msgid "Rundi" +msgstr "Rhedeg" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +#, fuzzy +msgid "Russian" +msgstr "Rwsia" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +#, fuzzy +msgid "Sandawe" +msgstr "Canada" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +#, fuzzy +msgid "Sango" +msgstr "Saigon" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "Iaith" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +#, fuzzy +msgid "Sasak" +msgstr "Samoa" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +#, fuzzy +msgid "Santali" +msgstr "Shanghai" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +#, fuzzy +msgid "Sicilian" +msgstr "Michigan" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +#, fuzzy +msgid "Scots" +msgstr "De" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +#, fuzzy +msgid "Croatian" +msgstr "Croatia" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +#, fuzzy +msgid "Selkup" +msgstr "Hepgor" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "Iaith" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +#, fuzzy +msgid "Shan" +msgstr "Shanghai" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +#, fuzzy +msgid "Sidamo" +msgstr "Samoa" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Iaith" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +#, fuzzy +msgid "Slovak" +msgstr "Slofakia" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +#, fuzzy +msgid "Slovenian" +msgstr "Slofenia" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +#, fuzzy +msgid "Northern Sami" +msgstr "Gogledd Iwerddon" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "Iaith" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +#, fuzzy +msgid "Samoan" +msgstr "Samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +#, fuzzy +msgid "Shona" +msgstr "Slofenia" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +#, fuzzy +msgid "Soninke" +msgstr "Parhau" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +#, fuzzy +msgid "Sogdian" +msgstr "Mew&ngofnodi" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +#, fuzzy +msgid "Somali" +msgstr "Romania" + +#. language code: son +#: zypp/LanguageCode.cc:985 +#, fuzzy +msgid "Songhai" +msgstr "Shanghai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +#, fuzzy +msgid "Spanish" +msgstr "Sbaen" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +#, fuzzy +msgid "Sardinian" +msgstr "Rhybudd" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +#, fuzzy +msgid "Serer" +msgstr "Gweinydd" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +#, fuzzy +msgid "Swati" +msgstr "Sbaen" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +#, fuzzy +msgid "Susu" +msgstr "Cyflwr" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +#, fuzzy +msgid "Swahili" +msgstr "Hawaii" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +#, fuzzy +msgid "Swedish" +msgstr "Sweden" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +#, fuzzy +msgid "Syriac" +msgstr "Gwasanaeth" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +#, fuzzy +msgid "Tahitian" +msgstr "Tahiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +#, fuzzy +msgid "Tamil" +msgstr "Tasmania" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "Qatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +#, fuzzy +msgid "Telugu" +msgstr "Gwlad Belg" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +#, fuzzy +msgid "Tetum" +msgstr "&Profi" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +#, fuzzy +msgid "Thai" +msgstr "Tahiti" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +#, fuzzy +msgid "Klingon" +msgstr "Saigon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +#, fuzzy +msgid "Tamashek" +msgstr "Tashkent" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +#, fuzzy +msgid "Tswana" +msgstr "Tasmania" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +#, fuzzy +msgid "Tsonga" +msgstr "Estonia" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "Twrci" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +#, fuzzy +msgid "Tumbuka" +msgstr "Timbuktu" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "Iaith" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +#, fuzzy +msgid "Turkish" +msgstr "Tunis" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +#, fuzzy +msgid "Tuvinian" +msgstr "Tunis" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +#, fuzzy +msgid "Ukrainian" +msgstr "Wcrain" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +#, fuzzy +msgid "Vai" +msgstr "Vatican" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +#, fuzzy +msgid "Venda" +msgstr "Grenada" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +#, fuzzy +msgid "Votic" +msgstr "Vatican" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "Managua" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +#, fuzzy +msgid "Welsh" +msgstr "Gorllewin" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "Iaith" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +#, fuzzy +msgid "Yapese" +msgstr "Ie" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "Iaith" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +#, fuzzy +msgid "Zenaga" +msgstr "Grenada" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +#, fuzzy +msgid "Zhuang" +msgstr "Wedi'u Newid" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +#, fuzzy +msgid "Zuni" +msgstr "Tunis" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "Bydd pecyn %1 yn cael ei arsefydlu" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "anhysbys" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +#, fuzzy +msgid "invalid" +msgstr "Arsefydlu" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Arsefydlu %s: \"%s\"" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Couldn't open file: %s." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Arsefydlu %s: \"%s\"" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "Arsefydlu" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Copïo ffeiliau ffurfweddu i'r cysawd a osodwyd" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Y gorchymyn a weithredir wrth gysylltu" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Arsefydlu %s: \"%s\"" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Arsefydlu %s: \"%s\"" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ie" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nage" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Gwall" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "Gwall" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "heb gysylltu" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +#, fuzzy +msgid "yes" +msgstr "Ie" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +#, fuzzy +#~ msgid "Package is not signed!" +#~ msgstr "Mae llofnod annilys gan yr RPM." + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "Saerniaeth:" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Bydd pecyn %1 yn cael ei arsefydlu" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "Rhaid arsefydlu'r pecynnau yma:" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "Methodd yr arsefydliad." + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Arsefydlu %s: \"%s\"" + +#, fuzzy +#~ msgid "do not install %s" +#~ msgstr "Arsefydlu %s: \"%s\"" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "Arsefydlu %s: \"%s\"" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "Gosod gyrrydd..." + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "&Dileu" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Arsefydlu %s: \"%s\"" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "heb gysylltu" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "Arsefydlu %s: \"%s\"" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "%s remove failed" +#~ msgstr "Methodd rpm." + +#, fuzzy +#~ msgid "%s install failed" +#~ msgstr "Methodd yr arsefydliad." + +#, fuzzy +#~ msgid "%s installed ok" +#~ msgstr "&Ie, gosod" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Gosod gyrrydd..." + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Gosod gyrrydd..." + +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "Gosod gyrrydd..." + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "Gosod gyrrydd..." + +#, fuzzy +#~ msgid "install %s" +#~ msgstr "Arsefydlu %s: \"%s\"" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "Gosod gyrrydd..." + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "Rhaid arsefydlu'r pecynnau yma:" + +#, fuzzy +#~ msgid "No need to install %s" +#~ msgstr "&Ie, gosod" + +#, fuzzy +#~ msgid ", Action: " +#~ msgstr "Gweithred" + +#, fuzzy +#~ msgid "Establishing %s" +#~ msgstr "Arsefydlu %s: \"%s\"" + +#, fuzzy +#~ msgid " Error!" +#~ msgstr "Gwall" + +#~ msgid "Ok" +#~ msgstr "Iawn" + +#, fuzzy +#~ msgid "The package file has incorrect MD5 sum" +#~ msgstr "Mae llofnod annilys gan yr RPM." + +#, fuzzy +#~ msgid "The package archive has incorrect MD5 sum" +#~ msgstr "Mae llofnod annilys gan yr RPM." + +#, fuzzy +#~ msgid "Default" +#~ msgstr "Rhag&osod" + +#, fuzzy +#~ msgid "to be installed (soft)" +#~ msgstr "&Ymgychwyn cysawd a osodwyd" + +#, fuzzy +#~ msgid "to be uninstalled" +#~ msgstr "ni arsefydlir y rhaglen" diff --git a/po/da.po b/po/da.po new file mode 100644 index 0000000..d74a797 --- /dev/null +++ b/po/da.po @@ -0,0 +1,5458 @@ +# Copyright (C) YEAR SuSE Linux GmbH, Nuernberg +# This file is distributed under the same license as the PACKAGE package. +# Martin Schlander , 2015. +# scootergrisen, 2017. +msgid "" +msgstr "" +"Project-Id-Version: libzypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2019-12-06 11:54+0000\n" +"Last-Translator: scootergrisen \n" +"Language-Team: Danish \n" +"Language: da\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: Weblate 3.6.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Ukendt land: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Ingen kode" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Forenede Arabiske Emirater" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua og Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanien" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenien" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Hollandske Antiller" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktis" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikansk Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Østrig" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australien" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Alandøerne" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbajdsjan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnien-Herzegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgien" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgarien" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasilien" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet-øen" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Hviderusland" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosøerne" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Centralafrikanske Republik" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Schweiz" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Elfenbenskysten" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cook-øerne" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Cameroun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kap Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Juleøen" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cypern" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tjekkiet" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Tyskland" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danmark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikanske Republik" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algeriet" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estland" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypten" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Vest-Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanien" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopien" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandsøerne (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "De forenede Micronesiske stater" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Færøerne" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Frankrig" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Metropolitansk Frankrig" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Storbritannien" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgien" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Fransk Guinea" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grønland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ækvatorialguinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grækenland" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Syd-Georgien og sydlige Sandwich-øer" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard Øen og McDonald Øerne" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatien" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungarn" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesien" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isle of Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indien" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britisk område indiske ocean" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italien" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgisistan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodia" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comorerne" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts og Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Nord Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Syd Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Caymanøerne" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kasakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litauen" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letland" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Liberia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshalløerne" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonien" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongoliet" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Nordmarianerne" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauretanien" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldiverne" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Ny Caledonien" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk Øen" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Holland" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norge" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "New Zealand" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Fransk Polynesien" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Ny Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filippinerne" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polen" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre og Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palæstinensisk territorie" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumænien" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbien" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russiske føderation" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudiarabien" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salomonøerne" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychellerne" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Sverige" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Saint Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenien" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard og Jan Mayen øerne" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakiet" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé og Príncipe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syrien" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- og Caicos-øerne" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tchad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Franske sydlige territorier" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadzjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunesien" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Øst-Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Tyrkiet" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad og Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraine" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Fjerne, mindre øer, USA" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "USA" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikanstaten" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Sankt Vincent og Grenadinerne" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Jomfruøerne (britisk)" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Jomfruøerne (USA)" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis og Futuna øerne" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Sydafrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Leverer" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Præ-kræver" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Kræver" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Konflikter" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Forælder" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Anbefaler" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Foreslår" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Forbedringer" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Supplerer" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Prøvede at importere ikke-eksisterende nøgle %s ind i nøgleringen %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Kunne ikke importere nøgle." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Sletning af nøgle mislykkedes." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Signaturfilen %s blev ikke fundet" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Ukendt sprog: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhazian" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinese" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adygejiensk" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asiatisk (Andre)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili (Kunstsprog)" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadian" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albansk" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonkine sprog" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Sydaltaisk" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharic" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Engelsk, Gammel (ca. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apachesprog" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabisk" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramæisk" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonisk" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armensk" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucariask" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Kunstige (Andre)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamese" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturisk" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapaskiske sprog" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australske sprog" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarisk" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Aserbadjansk" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke sprog" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinesisk" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskisk" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltisk (Andre)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Hviderussisk" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengalsk" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber-sprog" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika (Blackfoot)" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (Andre)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnisk" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonsk" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesien)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginesisk" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarsk" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmesisk" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Central Amerikanske Indian (Andre)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalansk" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukasisk (Andre)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltisk (Andre)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Chechen" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kinesisk" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Church Slavic" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Chamiske sprog" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Coptic" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornish" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corsicansk" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creolsk og Pidgin - engelsk-baseret (andre)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creolsk og Pidgin - fransk-baseret (andre)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creolsk og Pidgin - portugisisk-baseret (andre)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Crimean Tatar" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creoles og Pidgins (andre)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kasjubisk" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitisk (Andre)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tjekkisk" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dansk" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Athapan-slavisk" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidiansk (Andre)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Nedre sorbiansk" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Hollandsk, Middelalder (ca. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Hollandsk" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egyptisk (Oldtids-)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamitisk" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engelsk" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Engelsk, Middelalder (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estisk" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Færøsk" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijian" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filippinsk" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finsk" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finno-Ugrisk (Andre)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Fransk" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Fransk, Middelalder (ca. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Fransk, Gammel (ca. 842-1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisian" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulian" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germanske (andre)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgisk" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Tysk" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertesisk" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gælisk" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irsk" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galicisk" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Højtysk, Middelalder (ca. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Højtysk, Gammel (ca. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gothisk" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Græsk, Oldtid (til 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Græsk, Moderne (fra 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitisk" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiiansk" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebraisk" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindu" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittitisk" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Øvre sorbiansk" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ungarsk" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandsk" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indisk (Andre)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesisk" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-Europæisk (Andre)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iransk (Andre)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokesiske sprog" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiensk" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanesisk" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japansk" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Jødisk-persisk" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Jødisk-arabisk" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabylisk" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachinsk" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kasakhisk" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardisk" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (Andre)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmersk" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanesisk" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Congo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreansk" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraeansk" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkarisk" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdisk" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latinsk" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Lettisk" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgansk" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litauisk" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxembourgsk" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya og Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonsk" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Maduresisk" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallesisk" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesisk (Malayo-Polynesisk)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malaysisk" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irsk, Middelalder (ca. 900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Diverse sprog" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (Andre)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Madagaskariansk" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltesisk" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobosprog" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavisk" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolisk" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Flere sprog" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda sprog" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandesisk" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Mayanske sprog" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Nordamerikansk indisk" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitansk" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, syd" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, nord" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Nedertysk" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofaniansk (Niger-Congo)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueansk" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norsk" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norse, gammel" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norsk" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Nordsotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubianske sprog" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Traditionel newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (efter år 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Tyrkisk, Osmannisk (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomianske sprog" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuan-Australsk (Andre)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinansk" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauansk" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persisk, gammel (ca. 600-400 F.K.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persisk" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filippinsk (andre)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fønikisk" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polsk" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeiansk" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugisisk" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakritsprog" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provencalsk, Gammel (til 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthanisk" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongansk" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romansk (Andre)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Raeto-Romance" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumænsk" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russisk" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Sydamerikansk Indiansk (Andre)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salishanske sprog" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritansk Aramæisk" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbisk" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliansk" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Skotsk" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroatisk" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitisk (Andre)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irsk, Gammel (Indtil ca. 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Tegnsprog" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singhalesisk" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouxsprog" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetansk (Andre)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavisk (Andre)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakisk" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovensk" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sydsamisk (Lapland)" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Nordsamisk" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Samiske sprog (andre)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule-samisk" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Samisk" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoan" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Samisk" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spansk" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinian" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Saharansk (Sub-Saharansk Afrikansk)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundansk" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumeriansk" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Svensk" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syrisk" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitisk" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Thai (andre)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamilsk" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetansk" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tongaøerne)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshiansk" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmen" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupisprog" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Tyrkisk" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaisk (Turko-Tatarisk)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuviniansk" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritisk" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainsk" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Ikke fastsat" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbekisk" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamesisk" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakashanske sprog" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Walisisk" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbianske sprog" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Vallonsk" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jødisk" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupiske sprog" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Følgende handlinger udføres:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "udløber ikke" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "udløbet: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "udløber: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(udløber ikke)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(UDLØBET)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(udløber indenfor 24 t.)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(udløber om %d dag)" +msgstr[1] "(udløber om %d dage)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "ukendt" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "ikke-supporteret" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Niveau 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Niveau 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Niveau 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Yderligere kundekontrakt nødvendig" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "ugyldig" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Supportniveau er ikke angivet" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Leverandøren yder ikke support." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Problembestemmelse, som betyder teknisk support designet til at give " +"kompatibilitetsinformation, installationsassistance, brugssupport, løbende " +"vedligeholdelse og basal fejlsøgning. Niveau 1-support er ikke beregnet til " +"at rette produktfejl." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Problemisolering, som betyder teknisk support designet til at duplikere " +"kundeproblemer, isolere problemområdet og levere løsning på problemer som " +"ikke løses af niveau 1-support." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Problemløsning, som betyder teknisk support designet til at løse komplekse " +"problemer ved at inddrage udvikling i løsning af produktfejl som er blevet " +"identificeret af niveau 2-support." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "En yderligere kundekontrakt er nødvendig for at få support." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Ukendt support-mulighed. Beskrivelse ikke tilgængelig" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Systemhåndtering er låst af programmet med pid %d (%s).\n" +"
Luk dette program, før du prøver igen." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Ukendt matchtilstand \"%s\"" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Ukendt matchtilstand \"%s\" for mønstret \"%s\"" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Ugyldigt regulært udtryk '%s': Regcomp returnerede %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ugyldigt regulært udtryk '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autentificering påkrævet for '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Besøg SUSE-kundercenteret for at tjekke om din registrering er gyldig og " +"ikke er udløbet." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Besøg Novell-kundercenteret for at tjekke om din registrering er gyldig og " +"ikke er udløbet." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Opret tilknytningspunkt: Kan ikke finde en skrivbar mappe til oprettelse af " +"et tilknytningspunkt" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Installér pakken \"lsof\" først." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Kan ikke oprette mappe med metadata-cache." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Fejl under forsøg på at læse fra \"%s\"" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Kan ikke oprette %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Der blev ikke fundet gyldige metadata på den angivne URL" +msgstr[1] "Der blev ikke fundet gyldige metadata på de angivne URL'er" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Caching af softwarekilde (%d) mislykkedes." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Opbygger cache for softwarekilden '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Kan ikke oprette cache i %s - ingen skriverettigheder." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Ikke-håndteret softwarekilde-type" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Tilføjer softwarekilden '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Ugyldig softwarekilde-filnavn i \"%s\"" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Kan ikke åbne filen \"%s\" til skrivning." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Ukendt fejl ved læsning fra \"%s\"" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Kan ikke læse softwarekildemappen \"%1%\": Adgang nægtet" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Kunne ikke læse mappen \"%s\"" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Kan ikke læse softwarekildefilen \"%1%\": Adgang nægtet" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Fjerner softwarekilden '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Kan ikke regne ud hvor softwarekilden er lagret." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Kan ikke slette \"%s\"" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Kan ikke regne ud hvor tjenesten er lagret." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Ukendt tjeneste \"%1%\": Fjerner forældreløs tjeneste-softwarekilde \"%2%\"" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Alias for softwarekilde må ikke starte med punktum." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Alias for tjeneste må ikke starte med punktum." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Vil du fortsætte?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Softwarekilden %1% definerer ikke yderligere 'gpgkey='-URL'er." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Leder efter gpg nøgle-ID'et %1% i softwarearkivet %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Leder efter gpg nøgle-ID'et %1% i mellemlageret %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Den påkrævede attribut '%s' mangler." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "En af eller begge '%s'- og '%s'-attributterne er påkrævet." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Verificering af signatur mislykkedes" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Pakken %s lader til at være blevet defekt under overførslen. Vil du forsøge " +"at hente den igen?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Kunne ikke levere pakken %s. Vil du prøve at hente den igen?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm-kontrol mislykkedes." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm mislykkedes." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Tjeneste-plugin understøtter ikke ændring af en attribut." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Kan ikke levere filen '%s' fra softwarekilden '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Ingen URL i softwarekilden." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Filen %1%\n" +" fra pakken\n" +" %2%\n" +" er i konflikt med filen fra pakken\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Filen %1%\n" +" fra pakken\n" +" %2%\n" +" er i konflikt med filen fra installation af\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Filen %1%\n" +" fra installation af\n" +" %2%\n" +" er i konflikt med en fil fra pakken\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Filen %1%\n" +" fra installation af\n" +" %2%\n" +" er i konflikt med filen fra installation af\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Filen %1%\n" +" fra pakken\n" +" %2%\n" +" er i konflikt med filen\n" +" %3%\n" +" fra pakken\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Filen %1%\n" +" fra pakken\n" +" %2%\n" +" er i konflikt med filen\n" +" %3%\n" +" fra installation af\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Filen %1%\n" +" fra installation af\n" +" %2%\n" +" er i konflikt med filen\n" +" %3%\n" +" fra pakken\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Filen %1%\n" +" fra installation af\n" +" %2%\n" +" er i konflikt med filen\n" +" %3%\n" +" fra installation af\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Kan ikke oprette sat-pulje." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "ødelæg %s ved at ignorere nogle af dens afhængigheder" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "ignorér generelt nogle afhængigheder" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "modstridende forespørgsler" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "et eller andet afhængighedsproblem" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "ikke understøttet anmodning" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "slettede udbydere: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"ikke-installérbare leverandører: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "ikke-installérbare leverandører: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Denne anmodning vil ødelægge dit system!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorér advarslen om et ødelagt system" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "installér %1%, selvom den er blevet tilbagetrukket" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "giv tillade til installation af PTF'en %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "installér %1%, selvom den er sortlistet" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Installation er blevet afbrudt som ønsket." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " afviklet" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " afvikling mislykkedes" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s er allerede kørt som %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " afvikling skippet under afbrydelse" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Fejl under afsendelse af bekendtgørelse af opdateringsbesked." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Besked om ny opdatering" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM mislykkedes: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Import af offentlig nøgle %1% mislykkedes" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Fjernelse af den offentlige nøgle %1% mislykkedes" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Konfigurationsfiler er ændret for %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm gemte %s som %s, men det var umuligt at bestemme forskellen" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm gemt %s som %s.\n" +"Her er de første 25 linjer af forskelle:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm oprettede %s som %s, men det var umuligt at bestemme forskellen" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm oprettet %s som %s.\n" +"Her er de første 25 linjer af forskelle:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Yderligere rpm-output" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "backup %s blev oprettet" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Signatur er OK" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Ukendt signaturtype" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Signaturen verificerer ikke" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Signaturen er OK, men nøglen er ikke betroet" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Signaturens offentlige nøgle er ikke tilgængelig" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Filen findes ikke eller signaturen kan ikke tjekkes" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Filen er uden signatur" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tvivlsom type '%s' for %u byte checksum '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Kunne ikke åbne pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Kan ikke åbne dataledning (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Ugyldig LDAP URL-forespørgselsstreng" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Ugyldig LDAP URL-forespørgselsparameter '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Kan ikke klone URL-objekt" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Ugyldig tom URL-objektreference" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Kan ikke fortolke URL-komponenter" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historik:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "URL-oversigt tillader ikke %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Ugyldig %s-komponent '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Ugyldig %s-komponent" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Fortolkning af forespørgselsstreng er ikke understøttet af denne URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL-oversigt er en påkrævet komponent" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Ugyldig URL-oversigt '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "URL-oversigt tillader ikke et brugernavn" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "URL-oversigt tillader ikke en adgangskode" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "URL-oversigt kræver en værtskomponent" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "URL-oversigt tillader ikke en værtskomponent" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Ugyldig værtskomponent '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "URL-oversigt tillader ikke en port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Ugyldig portkomponent '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "URL-oversigt kræver et stinavn" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relativ sti er ikke tilladt hvis autoritet eksisterer" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Kodede strenge indeholder en NUL-byte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Ugyldigt skilletegn for parameter-array" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Ugyldigt skilletegn for parameter-map" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Ugyldigt skilletegn for parameter-array join" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Kommando afsluttet med status %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Kommando dræbtes af signalet %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Kommando afsluttet med ukendt fejl." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Kan ikke skifte rodmappe til '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Kan ikke skifte mappe til \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Kan ikke skifte mappe til \"%s\" indenfor chroot \"%s\" (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Kan ikke eksekvere '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Kan ikke forgrene (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Montering af %s mislykkedes på %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Afmontering af %s mislykkedes" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Dårligt filnavn: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Mediet åbnedes ikke under forsøg på at udføre handlingen '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Filen %s blev ikke fundet på mediet '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Kan ikke skrive filen '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Medie er ikke tilknyttet" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Dårligt tilknytningspunkt for medie" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Download (curl) initialisering mislykkede for '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Systemundtagelse '%s' på mediet '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Stien '%s' på mediet '%s' er ikke en fil." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Stien '%s' på mediet '%s' er ikke en mappe." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Dårligt formeret URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Tomt værtsmaskinenavn i URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Tomt filsystem i URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Tom destination i URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Ikke-understøttet URI-skema i '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operationen understøttes ikke af medie" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Download (curl)-fejl for '%s':\n" +"Fejlkode: %s\n" +"Fejlmeddelelse: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Fejl opstod under indstilling af download-tilvalg (curl) for \"%s\":" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Mediekilden '%s' indeholder ikke det ønskede medie" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Mediet '%s' er i brug af en anden instans" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Kan ikke skubbe noget medie ud" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Kan ikke skubbe mediet '%s' ud" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Adgangstilladelse til '%s' nægtet." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Tidsfrist udløbet ved tilgang af \"%s\"." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Downloadede data oversteg den ventede filstørrelse '%s' med '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Placeringen \"%s\" er midlertidigt utilgængelig." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL-certifikatproblem. Tjek at CA-certifikatet er OK for '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Ikke-understøttet HTTP autentificeringsmetode '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ja" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nej" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Bemærk:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Advarsel:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Fejl:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "udført" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "fejl" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Advarsel: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Henter:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "starter" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "ikke fundet" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Ingen hjælp tilgængelig for denne forespørgsel." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "ingen hjælp tilgængelig for dette tilvalg" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "vis alle tilvalg" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ja" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nej" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Udfører %%posttrans-scriptet '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Udfører %posttrans-scripts" + +#~ msgid "Package is not signed!" +#~ msgstr "Pakke er ikke signeret!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s hører ikke til en distopgradering-softwarekilde" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s har laverestående arkitektur" + +#~ msgid "problem with installed package %s" +#~ msgstr "problem med den installerede pakke %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "intet leverer forespurgt %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Har du aktiveret alle anmodede softwarekilder?" + +#~ msgid "package %s does not exist" +#~ msgstr "pakken %s findes ikke" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s leveres af systemet og kan ikke slettes" + +#~ msgid "%s is not installable" +#~ msgstr "%s kan ikke installeres" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "intet leverer %s, der kræves af %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "kan ikke installere både %s og %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s konflikter med %s, der leveres af %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s forælder %s, der leveres af %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "installerede %s forælder %s, der leveres af %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "solvable %s konflikter med %s, der leveres af den selv" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s kræver %s, men dette krav kan ikke leveres" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "fjern lås for at tillade fjernelse af %s" + +#~ msgid "do not install %s" +#~ msgstr "installér ikke %s" + +#~ msgid "keep %s" +#~ msgstr "behold %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "fjern lås for at tillade installation af %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "spørg ikke efter at installere en solvable, der leverer %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "spørg ikke efter at slette alle solvables, der leverer %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "installér ikke sidste nye version af %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "behold %s på trods af laverestående arkitektur" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "installér %s på trods af laverestående arkitektur" + +#~ msgid "keep obsolete %s" +#~ msgstr "behold forældet %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "installér %s fra ekskluderet softwarekilde" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "nedgradering af %s til %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "arkitekturændring af %s til %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "installér %s (med leverandørændring)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "udskiftning af %s med %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "afinstallation af %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Kan ikke åbne låsefilen: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Denne handling køres allerede af et andet program." + +#~ msgid "Hal Exception" +#~ msgstr "Hal-undtagelse" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Beklager, denne version af libzypp blev bygget uden HAL-understøttelse." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext er ikke tilsluttet" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive er ikke initialiseret" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume er ikke initialiseret" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Kan ikke oprette dbus-tilslutning" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: libhal-kontekst kan ikke oprettes" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: dbus-tilslutning kan ikke indstilles" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Kan ikke initialisere HAL-kontekst -- kører hald ikke?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Ikke et cd-rom-drev" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Mutex-attributter kan ikke initialiseres" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Rekursive mutex-attributter kan ikke angives" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Rekursive mutex-attributter kan ikke initialiseres" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Mutex-lås kan ikke hentes" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Mutex-lås kan ikke frigives" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Import af offentlig nøgle fra filen %s fejlede: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Fjernelse af den offentlige nøgle %s fejlede: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Kan ikke finde tilgængelig løkkeenhed til at montere imagefilen fra '%s'" diff --git a/po/de.po b/po/de.po new file mode 100644 index 0000000..1e07851 --- /dev/null +++ b/po/de.po @@ -0,0 +1,6166 @@ +# translation of zypp.de.po to German +# translation of zypp.de.po to +# @TITLE@ +# Copyright (C) 2006, SUSE Linux GmbH, Nuremberg +# +# This file is distributed under the same license as @PACKAGE@ package. FIRST +# +# +# Lars Vogdt , 2007. +# Stephan Kulow , 2007. +# Marko Schugardt , 2008,2009. +# Michael Skiba , 2008, 2012, 2013. +# Jannick Kuhr , 2008. +# Hermann-Josef Beckers , 2009. +# Hermann J. Beckers , 2011, 2014. +msgid "" +msgstr "" +"Project-Id-Version: zypp.de\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-18 10:47+0000\n" +"Last-Translator: Ettore Atalan \n" +"Language-Team: German " +"\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: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Unbekanntes Land: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Kein Code" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Vereinigte Arabische Emirate" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua und Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanien" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenien" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Niederländische Antillen" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktis" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentinien" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikanisch Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Österreich" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australien" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Aland-Inseln" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Aserbaidschan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnien-Herzegowina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesch" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgien" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgarien" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivien" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasilien" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvetinsel" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Weißrussland" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosinseln" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Zentralafrikanische Republik" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Schweiz" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Côte d'Ivoire" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookinseln" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbien" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kap Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Weihnachtsinsel" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Zypern" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tschechische Republik" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Deutschland" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Dschibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dänemark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikanische Republik" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algerien" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estland" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Ägypten" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Westsahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanien" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Äthiopien" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finnland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidschi" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandinseln (Malwinen)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Föderierte Staaten von Mikronesien" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Färöer-Inseln" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Frankreich" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Frankreich, Metropolitan" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabun" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Vereinigtes Königreich" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgien" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Französisch-Guayana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grönland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Griechenland" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Südgeorgien und die südlichen Sandwichinseln" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard-Insel und McDonald-Inseln" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatien" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungarn" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesien" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isle of Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indien" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britisches Territorium im Indischen Ozean" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italien" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaika" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordanien" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgisistan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodscha" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komoren" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "St. Kitts und Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Nordkorea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Südkorea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kaimaninseln" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kasachstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Demokratische Volksrepublik Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "St. Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litauen" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Lettland" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libyen" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldau" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshallinseln" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Mazedonien" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolei" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Nördliche Marianen" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauretanien" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Malediven" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mosambik" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Neukaledonien" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolkinsel" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Niederlande" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norwegen" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauruanisch" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Neuseeland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Französisch-Polynesien" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua-Neuguinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Philippinen" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polen" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "St. Pierre und Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palästinensische Autonomiegebiete" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumänien" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbien" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russische Föderation" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi-Arabien" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salomonen" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychellen" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Schweden" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "St. Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slowenien" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard und Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slowakei" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome und Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syrien" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swasiland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- und Caicosinseln" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tschad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Französische Süd- und Antarktisgebiete" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadschikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunesien" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Osttimor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Türkei" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad und Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tansania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraine" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Amerikanisch-Ozeanien" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "USA" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Usbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Heiliger Stuhl (Vatikan)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "St. Vincent und die Grenadinen" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britische Jungferninseln" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Amerikanische Jungferninseln" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis und Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Südafrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Sambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Simbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Bereitstellungen" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "setzt voraus" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Anforderungen" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Konflikte" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Veraltetete Pakete" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Empfehlungen" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Vorschläge" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Erweiterungen" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Zusätze" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" +"Versuch, nicht existierenden Schlüssel %s in Schlüsselbund %s zu importieren" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Importieren des Schlüssels fehlgeschlagen." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Fehler beim Löschen des Schlüssels." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Signaturdatei %s nicht gefunden" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Unbekannte Sprache: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar-Sprache" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abchasisch" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Aceh-Sprache" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acholi-Sprache" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme-Sprache" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adygeisch" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Andere afro-asiatische Sprachen" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan-Sprache" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadisch" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanisch" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutisch" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonkin-Sprachen" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altaisch" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharisch" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Altenglisch (ca. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apachen-Sprachen" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabisch" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramäisch" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonesisch" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armenisch" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Arauka-Sprachen" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho-Sprache" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Andere Kunstsprache" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak-Sprachen" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamesisch" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturianisch" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapaskische Sprachen" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australische Sprachen" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Awarisch" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Awestisch" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara-Sprache" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Aserbeidschanisch" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda-Sprache" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke-Sprache" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Baschkirisch" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Belutschisch" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara-Sprache" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinesisch" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskisch" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basaa-Sprache" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Andere baltische Sprachen" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Bedauye" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Weißrussisch" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba-Sprache" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Andere Berbersprachen" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol-Sprache" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini-Sprache" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Blackfoot-Sprache" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Andere Bantusprachen" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnisch" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj-Bhakha" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonisch" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak-Sprache" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Burjatisch" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugi-Sprache" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarisch" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmesisch" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Bilin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo-Sprachen" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Andere Indianersprachen (Zentralamerika)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Karibisch" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalanisch" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Andere kaukasische Sprachen" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Andere keltische Sprachen" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro-Sprache" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha-Sprachen" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tschetschenisch" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Tschagataisch" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinesisch" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Trukesisch" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook-Jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw-Sprache" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee-Sprache" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Kirchenslawisch" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Tschuwaschisch" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne-Sprache" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Cham-Sprachen" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptisch" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Kornisch" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsisch" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreolisch-Englisch (andere)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreolisch-Französisch (andere)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreolisch-Portugiesisch (andere)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree-Sprache" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krimtatarisch" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreolische Sprachen (Pidgin-Sprachen)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kaschubisch" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Andere kuschitische Sprachen" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tschechisch" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota-Sprache" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dänisch" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Darginisch" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dajakisch" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware-Sprache" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave-Sprache" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib-Sprache" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka-Sprache" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Maledivisch" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Andere drawidische Sprachen" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Niedersorbisch" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala-Sprachen" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Mittelniederländisch (ca. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Niederländisch" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula-Sprache" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Altägyptisch" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamisch" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Englisch" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Mittelenglisch (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estnisch" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe-Sprache" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Pangwe-Sprache" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Färöisch" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fante-Sprache" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fidschi-Sprache" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Pilipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finnisch" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Andere finnougrische Sprachen" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon-Sprache" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Französisch" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Mittelfranzösisch (ca. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Altfranzösisch (842-ca. 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Friesisch" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Ful" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulisch" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo-Sprache" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya-Sprache" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Andere germanische Sprachen" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgisch" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Deutsch" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Altäthiopisch" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertesisch" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gälisch" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irisch" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galicisch" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manxs" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Mittelhochdeutsch (ca. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Althochdeutsch (ca. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi-Sprache" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalesisch" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotisch" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo-Sprache" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Altgriechisch (bis 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Griechisch (nach 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani-Sprache" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati-Sprache" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Kutchin-Sprache" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida-Sprache" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitien" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Haussa-Sprache" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiisch" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebräisch" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero-Sprache" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon-Sprache" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hethitisch" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Miao-Sprachen" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri-Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Obersorbisch" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ungarisch" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa-Sprache" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban-Sprache" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Ibo-Sprache" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Isländisch" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Sinohoan" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Nosu" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo-Sprache" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingua" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Ilokano-Sprache" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Andere indoarische Sprachen" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesisch" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Andere indogermanische Sprachen" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Inguschisch" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupik" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Andere iranische Sprachen" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokesische Sprachen" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italienisch" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanisch" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japanisch" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Jüdisch-Persisch" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Jüdisch-Arabisch" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpakisch" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabylisch" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin-Sprache" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Grönländisch" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba-Sprache" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karenisch" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kaschmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri-Sprache" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kasachisch" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardinisch" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi-Sprache" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Andere Khoisan-Sprachen" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Kambodschanisch" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Andere Khoisan-Sprachen" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu-Sprache" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Rwanda-Sprache" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgisisch" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu-Sprache" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi-Sprache" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo-Sprache" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreanisch" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraeanisch" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle-Sprache" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karatschaisch" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru-Sprachen" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Oraon-Sprache" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kwanyama-Sprache" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumükisch" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdisch" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai-Sprache" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Judenspanisch" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba-Sprache (Bantusprache)" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laotisch" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latein" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Lettisch" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lesgisch" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgisch" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litauisch" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo-Sprache" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Rotse-Sprache" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgisch" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Lulua-Sprache" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga-Sprache" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda-Sprache" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno-Sprache" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda-Sprache" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo-Sprache" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai-Sprache" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonisch" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Maduresisch" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Khotta" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marschallesisch" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makassarisch" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Malinke-Sprache" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori-Sprache" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Andere austronesische Sprachen" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Massai-Sprache" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malaiisch" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Mokschamordwinisch" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandaresisch" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende-Sprache" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Mittelirisch (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Micmac-Sprache" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau-Sprache" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Verschiedene Sprachen" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Andere Mon-Khmer-Sprachen" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagassi-Sprache" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltesisch" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Mandschurisch" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Meithei-Sprache" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo-Sprache" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk-Sprache" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldauisch" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolisch" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi-Sprache" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Mehrere Sprachen" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Mundasprachen" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Muskogisch" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandesisch" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Maya-Sprachen" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erza-Mordwinisch" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Indianersprachen (Nordamerika)" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitanisch" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo-Sprache" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndbele-Sprache (Transvaal)" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele-Sprache (Simbabwe)" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Niederdeutsch" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Newari" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias-Sprache" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Andere Nigerkordofanische Sprachen" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niue-Sprache" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Bokmål" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogaisch" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Altnorwegisch" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norwegisch" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho-Sprache (Nord)" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubische Sprachen" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Alt-Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Nyanja-Sprache" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi-Sprache" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nikole-Sprache" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro-Sprache" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima-Sprache" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Okzitanisch (nach 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa-Sprache" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya-Sprache" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Galla-Sprache" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage-Sprache" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetisch" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Osmanisch (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomangue-Sprachen" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Andere Papuasprachen" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan-Sprache" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pehlewi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanggan-Sprache" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Pandschabi-Sprache" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palau-Sprache" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Altpersisch (ca. 600-400 v. Chr.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persisch" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Philippinen-Austronesisch (andere)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Phönikisch" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polnisch" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Ponapeianisch" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugiesisch" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prâkrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Altprovenzalisch (Altokzitanisch, bis 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Paschtu" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua-Sprache" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Osterinsel-Sprache" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotonganisch" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Andere romanische Sprachen" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Rätoromanisch" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romani (Sprache)" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumänisch" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi-Sprache" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russisch" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe-Sprache" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango-Sprache" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Jakutisch" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Andere Indianersprachen (Südamerika)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salish-Sprachen" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritanisch" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbisch" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sizilianisch" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Schottisch" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroatisch" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkupisch" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Andere semitische Sprachen" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Altirisch (bis 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Zeichensprachen" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Schan-Sprache" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo-Sprache" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singhalesisch" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Sioux-Sprachen" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Andere sinotibetische Sprachen" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Andere slawische Sprachen" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slowakisch" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slowenisch" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Südsamisch" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Nordsamisch" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Samisch (andere)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule-Samisch" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari-Samisch" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoanisch" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt-Lappisch" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Schona-Sprache" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi-Sprache" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke-Sprache" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdisch" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai-Sprache" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Süd-Sotho-Sprache" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spanisch" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardisch" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer-Sprache" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilosaharanische Sprachen" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swasi-Sprache" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma-Sprache" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanesisch" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerisch" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Schwedisch" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syrisch" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitisch" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Andere Thaisprachen" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatarisch" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu-Sprache" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Temne-Sprache" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno-Sprache" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum-Sprache" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadschikisch" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thailändisch" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetisch" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre-Sprache" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinja-Sprache" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv-Sprache" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingonisch" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit-Sprache" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamaseq" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Bantusprache, Sambia)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tongaisch" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Neumelanesisch" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian-Sprache" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana-Sprache" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga-Sprache" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmenisch" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka-Sprache" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Türkisch" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Andere altaische Sprachen" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi-Sprache" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuwinisch" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurtisch" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritisch" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uigurisch" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainisch" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Mbundu-Sprache" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Unbestimmt" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Usbekisch" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai-Sprache" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda-Sprache" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamesisch" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Wotisch" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakash-Sprachen" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo-Sprache" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo-Sprache" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Kymrisch" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbisch" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Wallonisch" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof-Sprache" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmückisch" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa-Sprache" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao-Sprache (Bantusprache)" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapesisch" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jiddisch" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba-Sprache" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupik-Sprache" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotekisch" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande-Sprachen" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu-Sprache" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni-Sprache" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Folgende Aktionen werden ausgeführt:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "läuft nicht ab" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "abgelaufen: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "läuft ab: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(läuft nicht ab)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(ABGELAUFEN)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(läuft innerhalb 24 Stunden ab)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(läuft innerhalb von %d Tag ab)" +msgstr[1] "(läuft innerhalb von %d Tagen ab)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "Unbekannt" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nicht unterstützt" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Stufe 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Stufe 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Stufe 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Zusätzlicher Kundenvertrag erforderlich" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Nicht mehr in Betrieb und durch ein anderes Paket ersetzt" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "ungültig" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Die Support-Stufe wurde nicht angegeben" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Der Anbieter bietet keinen Support an." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Problembestimmung bezeichnet den technischen Support, der " +"Kompatibilitätsinformationen, Hilfe bei der Installation, " +"Anwendungsunterstützung, fortlaufende Wartung und grundlegende Hilfe bei der " +"Fehlersuche bietet. Support der Stufe 1 ist nicht dazu gedacht, " +"Produktfehler zu beheben." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Problemisolierung bezeichnet den technischen Support, der Kundenprobleme " +"nachbildet, Problembereiche isoliert und Lösungen für Probleme bietet, die " +"nicht durch den Support der Stufe 1 behoben werden konnten." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Problemlösung bezeichnet den technischen Support, der komplexe Probleme " +"lösen soll, wobei das Engineering zur Beseitigung von Produktfehlern, die im " +"Support der Stufe 2 erkannt wurden, einbezogen wird." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" +"Ein zusätzlicher Kundenvertrag ist erforderlich, um Unterstützung zu " +"erhalten." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"Das Paket ist nicht mehr in Betrieb und wurde durch ein neueres Paket mit " +"einem anderen Namen ersetzt." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Unbekannte Support-Option. Keine Beschreibung vorhanden" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Die Systemverwaltung ist gesperrt durch die Anwendung mit PID %d (%s).\n" +"Schließen Sie diese Anwendung, bevor Sie es erneut versuchen." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Unbekannter Übereinstimmungsmodus '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Unbekannter Übereinstimmungsmodus %s für Schema %s" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Ungültiger regulärer Ausdruck '%s': regcomp gab %d zurück" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ungültiger regulärer Ausdruck '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Authentifizierung erforderlich für '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Werde es erneut versuchen..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Gebe nach %1% Versuchen auf." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Besuchen Sie den SUSE Customer Center zur Prüfung, ob Ihre Registrierung " +"gültig und nicht abgelaufen ist." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Besuchen Sie den Novell Customer Center zur Prüfung, ob Ihre Registrierung " +"gültig und nicht abgelaufen ist." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Anschlusspunkt erstellen: Kann kein schreibbares Verzeichnis finden, um " +"einen Anschlusspunkt zu erstellen" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Bitte zuerst Paket 'lsof' installieren." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Metadaten-Cache-Verzeichnis konnte nicht erstellt werden." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Fehler beim Versuch, aus '%s' zu lesen" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "%s konnte nicht erstellt werden" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Keine gültigen Metadaten bei dem festgelegten URL gefunden" +msgstr[1] "Keine gültigen Metadaten bei den festgelegten URLs gefunden" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Repo (%d) konnte nicht im Cache gespeichert werden." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Cache für Repository '%s' erzeugen" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" +"Cache konnte auf %s nicht erstellt werden - keine Schreibberechtigungen." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Unverarbeiteter Repository-Typ" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Repository '%s' hinzufügen" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Repo-Dateiname bei '%s' ungültig" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Datei '%s' konnte nicht zum Schreiben geöffnet werden." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Unbekannter Fehler beim Lesen aus '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Repo-Verzeichnis '%1%' kann nicht gelesen werden: Zugriff verweigert" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Verzeichnis '%s' konnte nicht gelesen werden" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Repo-Datei '%1%' kann nicht gelesen werden: Zugriff verweigert" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "Metadaten werden bereinigt" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "Pakete werden bereinigt" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "Zwischenspeicher-Verzeichnisse werden bereinigt" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "Verzeichnis wird bereinigt: %1%" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "Zwischenspeicher wird bereinigt" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "Aus dem Zwischenspeicher wird geladen" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Repository '%s' entfernen" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Speicherort des Repos kann nicht gefunden werden." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "'%s' kann nicht gelöscht werden" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "Repositorium wird geändert" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "Repositorium wird aufgefrischt: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Speicherort des Dienstes kann nicht gefunden werden." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Unbekannter Dienst '%1%': Verwaistes Dienst-Repository '%2%' wird entfernt" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Ein Repository-Alias darf nicht mit einem Punkt beginnen." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Ein Dienst-Alias darf nicht mit einem Punkt beginnen." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Kein Digest für Datei %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Unbekannter Digest %s für Datei %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Fehler beim Überprüfen des Digest für Datei '%s'" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Die Datei '%s' ist unsigniert. Weiter?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Die Datei '%s' aus dem Repository '%s' ist unsigniert. Weiter?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Wollen Sie den Schlüssel abweisen, ihm temporär oder immer vertrauen?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Schlüsselname: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "%1% neuen Paket-Signierschlüssel von Repository \"%2%\" erhalten:" +msgstr[1] "%1% neue Paket-Signierschlüssel von Repository \"%2%\" erhalten:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Signaturüberprüfung für Datei '%1%' fehlgeschlagen." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"Signaturüberprüfung für Datei '%1%' aus Repository '%2%' fehlgeschlagen." + +# internal key used: Ok +# internal key used: Ok +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Fortfahren?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Datei '%s' ist mit einem unbekannten Schlüssel '%s' signiert. Weiter?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Die Datei '%s' aus dem Repository '%s' ist mit einem unbekannten Schlüssel " +"'%s' signiert. Weiter?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Repository %1% definiert keine zusätzlichen 'gpgkey='-URLs." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Suche nach der GPG-Key-ID %1% im Repository %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Suche nach der GPG-Key-ID %1% im Cache %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Erforderliches Attribut '%s' fehlt." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Eines oder beide der Attribute '%s' oder '%s' sind erforderlich." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Fehler beim Überprüfen der Signatur" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Paket %s wurde anscheinend bei der Übertragung beschädigt. Möchten Sie " +"erneut versuchen, es abzurufen?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Paket %s konnte nicht bereitgestellt werden. Möchten Sie erneut versuchen, " +"es abzurufen?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Applydeltarpm-Prüfung nicht bestanden." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "Fehler bei applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Das Dienst-Plugin unterstützt keine Änderung von Attributen." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" +"Datei '%s' aus Repository '%s' kann nicht zur Verfügung gestellt werden" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Das Repository enthält keine URL." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Erwartetes Medium %1%/%2%, identifiziert durch Datei '%3%', mit dem Inhalt:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Datei %1%\n" +" aus Paket\n" +" %2%\n" +" im Konflikt mit Datei aus Paket\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Datei %1%\n" +" aus Paket\n" +" %2%\n" +" im Konflikt mit Datei aus Installation von\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Datei %1%\n" +" aus Installation von\n" +" %2%\n" +" im Konflikt mit Datei aus Paket\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Datei %1%\n" +" aus Installation von\n" +" %2%\n" +" im Konflikt mit Datei aus Installation von\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Datei %1%\n" +" aus Paket\n" +" %2%\n" +" im Konflikt mit Datei\n" +" %3%\n" +" aus Paket\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Datei %1%\n" +" aus Paket\n" +" %2%\n" +" im Konflikt mit Datei\n" +" %3%\n" +" aus Installation von\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Datei %1%\n" +" aus Installation von\n" +" %2%\n" +" im Konflikt mit Datei\n" +" %3%\n" +" aus Paket\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Datei %1%\n" +" aus Installation von\n" +" %2%\n" +" im Konflikt mit Datei\n" +" %3%\n" +" aus Installation von\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Sat-Pool kann nicht erstellt werden." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "%s durch Ignorieren einiger Abhängigkeiten brechen" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "Einige Abhängigkeiten allgemein ignorieren" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"das installierte %1% gehört nicht zu einem distupgrade-Repository und muss " +"ersetzt werden" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "das zu installierende %1% gehört nicht zu einem distupgrade-Repository" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "das installierte %1% hat eine minderwertige Architektur" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "das zu installierende %1% hat eine minderwertige Architektur" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "Problem mit dem installierten %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "In Konflikt stehende Anforderungen" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "Abhängigkeitsproblem" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "nichts stellt das angeforderte '%1%' bereit" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Haben Sie alle erforderlichen Repositorys aktiviert?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "das angeforderte Paket %1% ist nicht vorhanden" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "nicht unterstützte Anforderung" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' wird vom System bereitgestellt und kann nicht gelöscht werden" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% ist nicht installierbar" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "nichts stellt '%1%' bereit, das vom installierten %2% benötigt wird" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" +"nichts stellt '%1%' bereit, das vom zu installierenden %2% benötigt wird" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "kann nicht %1% und %2% installieren" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"das installierte %1% steht im Konflikt mit '%2%', das vom installierten %3% " +"bereitgestellt wird" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"das installierte %1% steht im Konflikt mit '%2%', das von dem zu " +"installierenden %3% bereitgestellt wird" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"das zu installierende %1% steht im Konflikt mit '%2%', das vom installierten " +"%3% bereitgestellt wird" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"das zu installierende %1% steht im Konflikt mit '%2%', das vom zu " +"installierenden %3% bereitgestellt wird" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"das installierte %1% ersetzt '%2%', das vom installierten %3% bereitgestellt " +"wird" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"das installierte %1% ersetzt '%2%', das durch das zu installierende %3% " +"bereitgestellt wird" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"das zu installierende %1% ersetzt '%2%', das vom installierten %3% " +"bereitgestellt wird" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"das zu installierende %1% ersetzt '%2%', das durch das zu installierende %3% " +"bereitgestellt wird" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"das installierte %1% steht im Konflikt mit dem von ihm selbst " +"bereitgestellten '%2%'" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"das zu installierende %1% steht im Konflikt mit dem von ihm selbst " +"bereitgestellten '%2%'" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"das installierte %1% erfordert '%2%', aber diese Anforderung kann nicht " +"bereitgestellt werden" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"das zu installierende %1% erfordert '%2%', aber diese Anforderung kann nicht " +"bereitgestellt werden" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "Gelöschte Anbieter: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"Nicht installierbare Anbieter: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "Nicht installierbare Anbieter: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% ist noch nicht vollständig in %2% integriert." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Normalerweise würden Sie das PTF behalten und die Wartungs-Patches nicht " +"installieren." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Das Entfernen des installierten %1% in diesem Zusammenhang entfernt (nicht " +"ersetzt!) auch die enthaltenen PTF-Pakete." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"Das PTF sollte durch den Aufruf von '%1%' entfernt werden. Dies aktualisiert " +"die enthaltenen PTF-Pakete, anstatt sie zu entfernen." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Normalerweise möchten Sie die PTF behalten oder die Aktion abbrechen." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Das installierte %1% blockiert die gewünschte Aktion." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Normalerweise möchten Sie das PTF behalten und brechen die Aktion ab." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "Sperre entfernen, um das Entfernen von %1% zuzulassen" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "%1% nicht installieren" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "%1% beibehalten" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "Sperre entfernen, um Installation von %1% zuzulassen" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Diese Anfrage bringt Ihr System zum Absturz!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "Warnung vor einem beschädigten System ignorieren" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" +"Installation eines auflösbaren Elements, das %1% bereitstellt, nicht " +"anfordern" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" +"Löschen aller auflösbaren Elemente, die %1% bereitstellen, nicht anfordern" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "neueste Version von %1% nicht installieren" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "%1% trotz der minderwertigen Architektur beibehalten" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "%1% trotz der minderwertigen Architektur installieren" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "veraltetes %1% beibehalten" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "%1% aus ausgeschlossenem Repository installieren" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "%1% installieren, obwohl es widerrufen wurde" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "Erlauben das PTF %1% zu installieren" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "%1% installieren, obwohl es geblacklistet ist" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "Herabstufung von %1% auf %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "Architekturänderung von %1% in %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"%1% installieren (mit Herstellerwechsel)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"%1% von Hersteller %2% installieren\n" +"und %3% von Hersteller %4% ersetzen" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "Ersetzung von %1% durch %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "Deinstallation von %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Nach-Transaktions-Skripte werden ausgeführt" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Skript %1% wird ausgeführt" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Ausgabe des Skripts %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Die Installation wurde gemäß Anweisung abgebrochen." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " ausgeführt" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " Ausführung fehlgeschlagen" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s bereits als %s ausgeführt)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " Ausführung beim Abbrechen übersprungen" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Fehler beim Senden der Aktualisierungsbenachrichtigung." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Neue Aktualisierungsbenachrichtigung" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Empfangenes Signal: „%1% (%2%)“, um die Konsistenz des Systems zu " +"gewährleisten, ist es nicht möglich, eine laufende rpm-Transaktion " +"abzubrechen." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" +"Die Ausführung der Transaktion ist aufgrund der folgenden Probleme " +"fehlgeschlagen:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM fehlgeschlagen: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Importieren des öffentlichen Schlüssels %1% fehlgeschlagen" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Entfernen des öffentlichen Schlüssels %1% fehlgeschlagen" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Paket-Kopfdaten sind nicht signiert!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Paket-Nutzdaten sind nicht signiert!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Geänderte Konfigurationsdateien für %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm hat %s als %s gespeichert, der Unterschied konnte jedoch nicht ermittelt " +"werden" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm hat %s als %s gespeichert.\n" +"Hier die ersten 25 Zeilen mit Unterschieden:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm hat %s als %s erstellt, der Unterschied konnte jedoch nicht ermittelt " +"werden" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm hat %s als %s erstellt.\n" +"Hier die ersten 25 Zeilen mit Unterschieden:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Zusätzliche rpm-Ausgabe" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "Sicherung %s erstellt" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Signatur ist OK" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Unbekannter Signaturtyp" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Signatur ist nicht OK" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Signatur ist OK, aber Schlüssel ist nicht verbürgt" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Öffentlicher Schlüssel für Signatur nicht verfügbar" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Datei nicht vorhanden oder Signatur kann nicht geprüft werden" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Datei ist unsigniert" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Typ '%s' für %u-Byte-Prüfsumme '%s' fragwürdig" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "PTY (%s) kann nicht geöffnet werden." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Pipe (%s) kann nicht geöffnet werden." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Unzulässige Abfragezeichenkette für die LDAP-URL" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Unzulässiger Abfrageparameter für die LDAP-URL '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "URL-Objekt kann nicht geklont werden" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Unzulässiger leerer URL-Objektverweis" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "URL-Komponenten können nicht analysiert werden" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Verlauf:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "%s laut URL-Schema nicht zulässig" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Unzulässige %s-Komponente: '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Unzulässige %s-Komponente" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" +"Die Analyse von Abfragezeichenketten wird für diese URL nicht unterstützt" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Das URL-Schema ist eine erforderliche Komponente" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "'%s' ist ein unzulässiges URL-Schema" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Benutzername laut URL-Schema nicht zulässig" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Passwort laut URL-Schema nicht zulässig" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Für das URL-Schema ist eine Host-Komponente erforderlich" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Host-Komponente laut URL-Schema nicht zulässig" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Unzulässige Host-Komponente: '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Port laut URL-Schema nicht zulässig" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Unzulässige Portkomponente: '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Für das URL-Schema ist ein Pfadname erforderlich" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" +"Die Angabe des relativen Pfads ist nicht erlaubt, wenn die " +"Zertifizierungsstelle vorhanden ist" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Verschlüsselte Zeichenfolge enthält ein NULL-Byte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Ungültiges Trennzeichen für Parameter-Array-Spaltung" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Ungültiges Trennzeichen für Parameterzuordnungs-Spaltung" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Ungültiges Trennzeichen für Parameter-Array-Zusammenführung" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Kommando mit Status %d beendet." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Kommando wurde mit Signal %d (%s) beendet." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Kommando mit unbekanntem Fehler beendet." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Ungültige Spawn-Argumente angegeben." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Steuer-Pipe kann nicht erstellt werden." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "chroot zu '%s' (%s) nicht möglich." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Wechsel zu '%s' nicht möglich (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Wechsel zu '%s' innerhalb chroot '%s' nicht möglich (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "exec '%s' (%s) nicht möglich." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "(%s) abzweigen nicht möglich." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "exec '%s' nicht möglich, chdir fehlgeschlagen (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "exec '%s' nicht möglich, chroot fehlgeschlagen (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "exec '%s' nicht möglich, exec fehlgeschlagen (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "exec '%s' nicht möglich, unerwarteter Fehler." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Einhängen von '%s' in '%s' ist fehlgeschlagen" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Aushängen von '%s' ist fehlgeschlagen" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Schlechter Dateiname: '%s'" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" +"Beim Versuch, Aktion '%s' durchzuführen, wurde das Medium nicht geöffnet." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Datei '%s' auf Medium '%s' nicht gefunden" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Datei '%s' kann nicht geschrieben werden." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Medium nicht angeschlossen" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Fehlerhafter Medienanschlusspunkt" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Fehler bei der Initialisierung von Download (curl) für '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Systemausnahme '%s' auf Medium '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Pfad '%s' auf Medium '%s' ist keine Datei." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Pfad '%s' auf Medium '%s' ist kein Verzeichnis." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Fehlerhaft gebildete URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Leerer Hostname in URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Leeres Dateisystem in URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Leeres Ziel in URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Nicht unterstütztes URI-Schema in '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Vorgang von Medium nicht unterstützt" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Fehler beim Download (curl) für '%s':\n" +"Fehlercode: '%s'\n" +"Fehlermeldung: '%s'\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Beim Festlegen der Download (curl)-Optionen für '%s' ist ein Fehler " +"aufgetreten:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Medienquelle '%s' enthält nicht das gewünschte Medium" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Medium '%s' wird von einer anderen Instanz verwendet" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Es kann kein Medium ausgeworfen werden" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Medium '%s' kann nicht ausgeworfen werden" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Zugriff auf '%s' verweigert." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Zeitüberschreitung beim Zugriff auf '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"Die heruntergeladenen Daten überschritten die erwartete Dateigröße '%s' von " +"'%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Auf den Standort '%s' kann zeitweise nicht zugegriffen werden." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" SSL-Zertifikat-Problem; überprüfen Sie, ob das CA-Zertifikat für '%s' in " +"Ordnung ist." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Keine freien Ressourcen zum Anhängen des Mediums verfügbar." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Nicht unterstützte HTTP-Authentifizierungsmethode '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Download (curl) Fehler für '%s':\n" +"Fehlercode: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Download (curl) Fehler für '%s':\n" +"HTTP-Antwort kann nicht abgerufen werden\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ja" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nein" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Hinweis:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Warnung:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Fehler:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "fertig" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "Achtung" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "Fehler" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Warnung: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Abrufen:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "Starten" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "Nicht gefunden" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Keine Hilfe für diese Eingabeaufforderung verfügbar." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "Keine Hilfe für diese Option verfügbar" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "zeigt alle Optionen" + +# For consistency, use the capitalized form #345187 +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ja" + +# For consistency, use the capitalized form #345187 +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nein" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "%%posttrans script '%1%' wird ausgeführt" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "%posttrans scripts werden ausgeführt" + +#~ msgid "Package is not signed!" +#~ msgstr "Paket ist nicht signiert!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s gehört nicht zu einem Distributionsaktualisierungs-Repository" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s besitzt eine nachrangige Architektur" + +#~ msgid "problem with installed package %s" +#~ msgstr "Problem mit installiertem Paket %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "Angefordertes %s wird nirgends zur Verfügung gestellt" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Wurden alle erforderlichen Repositorys aktiviert?" + +#~ msgid "package %s does not exist" +#~ msgstr "Paket %s existiert nicht" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s wird vom System bereitgestellt und kann nicht gelöscht werden" + +#~ msgid "%s is not installable" +#~ msgstr "%s ist nicht installierbar" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s benötigt von %s wird nirgends zur Verfügung gestellt" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s und %s können nicht gleichzeitig installiert sein" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "" +#~ "%s steht in Konflikt mit %s, das von %s zur Verfügung gestellt wurde" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s löst %s ab, das von %s zur Verfügung gestellt wurde" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "installiertes %s macht %s, welches durch %s angeboten wird, obsolet" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "" +#~ "Das auflösbare Element %s steht in Konflikt mit %s, das es selbst zur " +#~ "Verfügung gestellt hat" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s benötigt %s, kann jedoch nicht zur Verfügung gestellt werden" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "Sperre entfernen und Entfernen von %s zulassen" + +#~ msgid "do not install %s" +#~ msgstr "%s nicht installieren" + +#~ msgid "keep %s" +#~ msgstr "%s behalten" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "Sperre entfernen und Installation von %s zulassen" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "" +#~ "Installation eines auflösbaren Elements mit %s darf nicht angefordert " +#~ "werden" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "" +#~ "Löschen aller auflösbaren Elemente mit %s darf nicht angefordert werden" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "Neueste Version von %s darf nicht installiert werden" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s trotz der nachrangigen Architektur beibehalten" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "%s trotz der nachrangigen Architektur installieren" + +#~ msgid "keep obsolete %s" +#~ msgstr "veraltetes %s beibehalten" + +#~ msgid "install %s from excluded repository" +#~ msgstr "%s aus dem ausgeschlossenen Repository installieren" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "Downgrade von %s zu %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "Architekturwechsel von %s zu %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "%s installieren (mit Anbieterwechsel)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "Ersatz von %s durch %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "Deinstallation von %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Sperrdatei kann nicht geöffnet werden: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Die Aktion wird bereits von einem anderen Programm ausgeführt." + +#~ msgid "Hal Exception" +#~ msgstr "Hal-Ausnahme" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Diese Version von libzypp wurde ohne HAL-Unterstützung erstellt." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext nicht verbunden" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive nicht initialisiert" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume nicht initialisiert" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Dbus-Verbindung kann nicht hergestellt werden" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Erstellen des libhal-Kontexts nicht möglich" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "libhal_set_dbus_connection: Festlegen der dbus-Verbindung nicht möglich" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "HAL-Kontext kann nicht initialisiert werden -- Wird hald nicht ausgeführt?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Kein CDROM-Laufwerk" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Mutex-Attribute können nicht initialisiert werden" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Rekursives Mutex-Attribut kann nicht festgelegt werden" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Rekursiver Mutex kann nicht initialisiert werden" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Mutex-Sperre kann nicht abgerufen werden" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Mutex-Sperre kann nicht aufgehoben werden" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "" +#~ "Importieren des öffentlichen Schlüssels aus Datei %s fehlgeschlagen: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Entfernen des öffentlichen Schlüssels %s fehlgeschlagen: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Das verfügbare Loop-Device zum Einhängen der Datei aus '%s' kann nicht " +#~ "gefunden werden" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "einige Abhängigkeiten generell ignorieren" + +#~ msgid "do not forbid installation of %s" +#~ msgstr "Installation von %s nicht unterbinden" + +#~ msgid "do not keep %s installed" +#~ msgstr "%s nicht installiert lassen" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Der öffentliche Schlüssel %s vom Schlüsselring %s kann nicht in Datei %s " +#~ "erstellt werden" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "" +#~ "Es wurde versucht, den nicht vorhandenen Schlüssel %s in Schlüsselring %s " +#~ "zu importieren" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Es kann innerhalb des Chroot (%s) nicht zu '/' gewechselt werden." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "" +#~ "Initialisierung des Downloads (Metalink-Curl) für '%s' fehlgeschlagen" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Fehler beim Herunterladen (Metalink-Curl) für '%s':\n" +#~ "Fehlerkode: %s\n" +#~ "Fehlermeldung: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Dateiabbruf bei %d%% unterbrochen" + +#~ msgid "Download interrupted by user" +#~ msgstr "Dateiabbruf durch Benutzer unterbrochen" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Beim Setzen der Download-Optionen (Metalink-Curl) für '%s' ist ein Fehler " +#~ "aufgetreten:" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "%s konnte von %s nicht abgerufen werden" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbien und Montenegro" + +#~ msgid "Unknown Distribution" +#~ msgstr "Unbekannte Distribution" + +#~ msgid "ignore some dependencies of %s" +#~ msgstr "einige Abhängigkeiten von %s ignorieren" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Datei %s hat keine Prüfsumme.\n" +#~ "Datei trotzdem verwenden?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Datei %s hat die Integritätsprüfung mit dem folgenden Schlüssel nicht " +#~ "bestanden:\n" +#~ "%s|%s|%s\n" +#~ "Datei trotzdem verwenden?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Datei %s hat eine ungültige Prüfsumme.\n" +#~ "Erwartet %s, gefunden %s\n" +#~ "Datei trotzdem verwenden?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Datei %s hat eine unbekannte Prüfsumme %s.\n" +#~ "Datei trotzdem verwenden?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Datei %s ist unsigniert.\n" +#~ "Datei trotzdem verwenden?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Datei %s ist mit einem unbekanntem Schlüssel signiert:\n" +#~ "%s|%s|%s\n" +#~ "Datei trotzdem verwenden?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Nicht vertrauenswürdiger Schlüssel gefunden:\n" +#~ "%s|%s|%s\n" +#~ "Schlüssel als vertrauenswürdig betrachten?" + +#~ msgid "Timeout exceeded when access '%s'." +#~ msgstr "Zeitablauf beim Zugriff auf '%s'." diff --git a/po/el.po b/po/el.po new file mode 100644 index 0000000..71609f6 --- /dev/null +++ b/po/el.po @@ -0,0 +1,6079 @@ +msgid "" +msgstr "" +"Project-Id-Version: Greek (libzypp)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2018-04-29 12:02+0000\n" +"Last-Translator: Konstantina Tsolakoglou \n" +"Language-Team: Greek \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: Weblate 2.18\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Άγνωστη χώρα: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Κανένας κώδικας" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Ανδόρα" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Ηνωμένα Αραβικά Εμιράτα" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Αφγανιστάν" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Αντίγκουα και Μπαρμπούντα" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Αγκίλα" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Αλβανία" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Αρμενία" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Ολλανδικές Αντίλλες" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Ανγκόλα" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Ανταρκτική" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Αργεντινή" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Αμερικανική Σαμόα" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Αυστρία" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Αυστραλία" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Αρούμπα" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Νησιά Aland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Αζερμπαϊτζάν" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Βοσνία-Ερζεγοβίνη" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Μπαρμπάντος" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Μπανγκλαντες" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Βέλγιο" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Μπουρκίνα Φάσο" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Βουλγαρία" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Μπαχρέιν" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Μπουρούντι" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Μπενίν" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Βερμούδες" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Μπρουνέι Νταρουσαλάμ" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Βολιβία" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Βραζιλία" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Μπαχάμες" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Μπουτάν" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Νήσος Μπουβέ" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Μποτσουάνα" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Λευκορωσία" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Μπελίζ" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Καναδάς" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Νήσοι Κόκος (Κήλινγκ)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Κονγκό" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Κεντροαφρικανική Δημοκρατία" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Ελβετία" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Ακτή Ελεφαντοστού" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Νήσοι Κουκ" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Χιλή" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Καμερούν" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Κίνα" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Κολομβία" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Κόστα Ρίκα" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Κούβα" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Πράσινο Ακρωτήριο" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Νήσοι Χριστουγέννων" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Κύπρος" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Δημοκρατία της Τσεχίας" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Γερμανία" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Τζιμπουτί" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Δανία" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Δομινίκα" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Δομινικανή Δημοκρατία" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Αλγερία" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Εκουαδόρ" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Εσθονία" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Αίγυπτος" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Δυτική Σαχάρα" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Ερυθραία" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Ισπανία" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Αιθιοπία" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Φινλανδία" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Φίτζι" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Νήσοι Φώκλαντ (Μαλβίνες)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Κυβερνητικές Πολιτείες της Μικρονησίας" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Φερόες Νήσοι" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Γαλλία" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Μητροπολιτική Γαλλία" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Γκαμπόν" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Ηνωμένο Βασίλειο" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Γρανάδα" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Γεωργία" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Γαλλική Γουιάνα" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Γκάνα" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Γιβραλτάρ" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Γροιλανδία" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Γκάμπια" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Γουϊνέα" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Γουαδελούπη" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ισημερινή Γουϊνέα" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Ελλάδα" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Νότια Γεωργία και Νότια Νησιά Σάντουιτς" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Γουατεμάλα" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Γκουάμ" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Γουϊνέα-Μπισάου" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Γουιάνα" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Χονγκ Κονγκ" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Νησί Heard και Νησιά McDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Ονδούρας" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Κροατία" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Αϊτή" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ουγγαρία" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Ινδονησία" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ιρλανδία" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Ισραήλ" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isle of Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Ινδία" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Βρετανικά Εδάφη Ινδικού Ωκεανού" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Ιράκ" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Ιράν" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Ισλανδία" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Ιταλία" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Τζέρσεϋ" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Τζαμάικα" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Ιορδανία" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Ιαπωνία" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Κένυα" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Κιργιστάν" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Καμπότζη" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Κιριμπάτι" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Κομόρες" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Άγιος Χριστόφορος και Χιονία" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Βόρεια Κορέα" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Νότια Κορέα" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Κουβέιτ" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Νήσοι Κέιμαν" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Καζακστάν" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Λαική Δημοκρατία του Λάος" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Λίβανος" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Αγία Λουκία" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Λίχτενσταϊν" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Σρι Λάνκα" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Λιβερία" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Λεσότο" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Λιθουανία" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Λουξεμβούργο" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Λετονία" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Λιβύη" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Μαρόκο" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Μονακό" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Μολδαβία" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Μαυροβούνιο" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Άγιος Μαρίνος" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Μαδαγασκάρη" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Νήσοι Μάρσαλ" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Π.Γ.Δ.Μ." + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Μάλι" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Μιανμάρ" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Μογγολία" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Μακάο" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Νήσοι Βορείων Μαριάννων" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Μαρτινίκα" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Μαυριτανία" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Μονσεράτ" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Μάλτα" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Μαυρίτιος" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Μαλβίδες" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Μαλάουϊ" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Μεξικό" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Μαλαισία" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Μοζαμβίκη" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Ναμίμπια" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Νέα Καληδονία" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Νίγηρας" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Νήσοι Νόρφολκ" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Νιγηρία" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Νικαράγουα" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Ολλανδία" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Νορβηγία" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Νεπάλ" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Ναουρού" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Βράχος Πολυνησίας" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Νέα Ζηλανδία" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Ομάν" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Παναμάς" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Περού" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Γαλλική Πολυνησία" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Παπούα Νέα Γουϊνέα" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Φιλιππίνες" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Πακιστάν" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Πολωνία" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Άγιος Πέτρος και Μιχαήλ" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Νήσοι Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Πουέρτο Ρίκο" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Παλαιστινιακά Εδάφη" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Πορτογαλία" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Νήσοι Παλάου" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Παραγουάη" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Κατάρ" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Νήσος Ρεουνιόν" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Ρουμανία" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Σερβία" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Ρωσική Ομοσπονδία" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ρουάντα" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Σαουδική Αραβία" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Νήσοι Σολομώντος" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Σεϋχέλλες" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Σουδάν" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Σουηδία" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Σιγκαπούρη" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Νήσος Αγίας Ελένης" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Σλοβενία" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Σβάλμπαρντ και Γιαν Μάγεν" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Σλοβακία" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Σιέρρα Λεόνε" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "Άγιος Μαρίνος" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Σενεγάλη" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Σομαλία" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Σουρινάμ" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Σάο Τόμε και Πρίντσιπε" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Ελ Σαλβαδόρ" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Συρία" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Σουαζιλάνδη" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Νήσοι Turks και Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Τσαντ" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Νότια Γαλλικά Εδάφη" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Τόγκο" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Ταϊλάνδη" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Τατζικιστάν" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Τοκελάου" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Τουρκμενιστάν" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Τυνησία" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Τόγκα" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Ανατολικό Τιμόρ" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Τουρκία" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Τρινιντάντ και Τομπάγκο" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Τουβαλού" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Ταϊλάνδη" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Τανζανία" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ουκρανία" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Ουγκάντα" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Μικρά απομονωμένα νησιά Ηνωμένων Πολιτειών" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Ηνωμένες Πολιτείες της Αμερικής" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Ουρουγουάη" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Ουζμπεκιστάν" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Αγία Θέση (Πόλη Κράτος Βατικανού)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Άγιος Βικέντιος και Γρεναδίνες" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Βενεζουέλα" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Βρετανικά Παρθένα Νησιά" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Παρθένες Νήσοι, Η.Π.Α." + +# +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Βιετνάμ" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Βανουάτου" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Γουόλις και Φουτούνα" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Σαμόα" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Υεμένη" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Μαγιοτ" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Νότια Αφρική" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Ζάμπια" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Ζιμπάμπουε" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Παρέχει" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Προαπαιτεί" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Απαιτεί" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Συγκρούσεις" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Απαρχαιώνει" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Συνιστά" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Προτείνει" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Ενισχύει" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Συμπληρώνει" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Προσπάθεια εισαγωγής μη υπάρχοντος κλειδιού %s στην κλειδοθήκη %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Αποτυχία εισαγωγής κλειδιού." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Αποτυχία της διαγραφής κλειδιού." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Το αρχείο υπογραφής %s δε βρέθηκε" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Άγνωστη γλώσσα: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Αφάρ" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Αμπχαζία" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinese" + +# power saving scheme name, combo box and default contents of text entry +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Αφρο-Ασιατικά (Άλλο)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Αφριχίλι" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ιαπωνικά (Ainu)" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Ακκαδική γλώσσα" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Αλβανικά" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Γλώσσες Algonquian" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Νότια Αλτάι" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Αμχαρική γλώσσα" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Αγγλικά, παλαιά (450-110 μ.Χ.)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Γλώσσες Απάτσι" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Αραβικά" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Αραμαϊκά" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonese" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Αρμενικά" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Αραουκάνικα (Μαπούτσε)" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Αραπάχο" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Τεχνητή (Άλλο)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Αραουάκ" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamese" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturian" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Γλώσσες Athapascan" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Αυστραλιανές Γλώσσες" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Αβαρικά" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Αβεστική γλώσσα" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Αζερμπαϊτζανικά" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Γλώσσες Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinese" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Βάσκικα" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Βαλτικά (Άλλο)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Μπέχα" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Λευκορωσικά" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber (Other)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (Άλλη)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Βοσνιακά" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Breton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginese" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Βουλγαρικά" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmese" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Ινδιανικά Κεντρικής Αμερικής (Άλλο)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Διάλεκτος Καραϊβικής" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Καταλονικά" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Καυκάσια (Άλλο)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Κέλτικα (Άλλο)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Τσετσενικά" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Κινεζικά" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Λεξικό Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Church Slavic" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Χαμικές Γλώσσες" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Κοπτικά" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornish" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Κορσικά" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creoles and Pidgins, Βασισμένες στα Αγγλικά (Άλλο)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creoles and Pidgins, Βασισμένες στα Γαλλικά (Άλλο)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creoles and Pidgins, Βασισμένες στα Πορτογαλλικά (Άλλο)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Crimean Tatar" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creoles και Pidgins (Other)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kashubian" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitic (Other)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Τσέχικα" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Δανέζικα" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidian (Other)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Lower Sorbian" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Ολλανδικά, Μεσαίωνα (1050-1350 μ.Χ.)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Ολλανδικά" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Αιγυπτιακά (Αρχαία)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Αγγλικά" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Αγγλικά, Μεσαίωνα (1100-1500 μ.Χ.)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Εσπεράντο" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Εσθονικά" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faroese" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijian" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Φινλανδικά" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Φινο-Ουγγρικά (Άλλο)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Γαλλικά" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Γαλλικά, Μεσαίωνα (1400-1600 μ.Χ.)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Γαλλικά, Παλαιά (842-1400 μ.Χ.)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisian" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulian" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Γερμανικά (Άλλο)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Γεωργιανά" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Γερμανικά" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +# +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertese" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Ιρλανδικά" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galician" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Γερμανικά, Ύστερος Μεσαίωνας (1050-1500 μ.Χ.)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Γερμανικά, Ύστερα Παλαιά (750-1050 μ.Χ.)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gothic" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Ελληνικά, Αρχαία (μέχρι 1453 μ.Χ.)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Ελληνικά, Σύγχρονα (1453 μ.Χ. - )" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitian" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiian" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Εβραϊκά" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittite" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Upper Sorbian" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ουγγρικά" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Ισλανδικά" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Ινδικά (Άλλο)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Ινδονησιακά" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Ινδεο-Ευρωπαϊκά (Άλλο)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Ιρανικά (Άλλο)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Γλώσσες Iroquoian" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Ιταλικά" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanese" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Ιαπωνικά" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Ιουδαιο-Περσικά" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Ιουδαιο-Αραβικά" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (Other)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanese" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Κορεατικά" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Κουρδικά" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Λατινικά" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Λεττονικά" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgan" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Λιθουανικά" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxembourgish" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Γκάνα" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya and Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Λουσάι" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Σκοπιανικά" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurese" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallese" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesian (Άλλες)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Ιρλανδικά, Μεσαίωνα (900-1200 μ.Χ.)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Διάφορες Γλώσσες" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (Other)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagasy" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltese" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Γλώσσες Manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Μολδαβικά" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Μογγολικά" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Πολλαπλές Γλώσσες" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Γλώσσες Munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Γλώσσες Μάγια" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Ινδιανικά Βόρειας Αμερικής" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitan" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Ναβαχό" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, South" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, North" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Low German" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanian (Other)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norwegian Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norwegian Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Νορβηγικά, Παλαιά" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Νορβηγικά" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Northern Sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Γλώσσες Nubia" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Classical Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (post 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Τουρκικά, Οθωμανικής Περιόδου (1500-1928 μ.Χ.)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Γλώσσες Otomian" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Παπουανά (Άλλα)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Περσικά, Παλαιά (400 π.Χ - 600 μ.Χ.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Περσικά" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Φιλιππινιακά" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Φοινικικά" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Πολωνικά" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Πορτογαλική γλώσσα" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Γλώσσες Prakit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provencal, Old (to 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romance (Other)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Raeto-Romance" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romany" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Ρουμανικά" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ρωσικά" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Νότια Αμερικάνικα Ινδιάνικα (Άλλα)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Γλώσσες Salishan" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Αραμαϊκά Σαμαριτικά" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbian" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilian" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Κροατικά" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Σημιτική (Άλλη)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Ιρλανδικά, Παλαιά (μέχρι 900 μ.Χ.)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Νοηματικές Γλώσσες" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Γλώσσες Siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetan (Other)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Σλαβικά (Άλλο)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Σλοβακικά" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Σλοβένικα" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Southern Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Northern Sami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Γλώσσες Σαμι(Άλλες)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoan" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, Southern" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Ισπανικά" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinian" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Saharan (Other)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Σουδανικά" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Σουμεριακά" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Σουαχίλι" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Σουηδικά" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Συριακά" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitian" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (Άλλα)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Ταϊλανδέζικα" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetan" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Νήσοι Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmen" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Γλώσσες Τουπι" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Τούρκικα" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaic (Other)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvinian" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritic" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ουκρανικά" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Απροσδιόριστο" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbek" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +# +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Βιετναμικά" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Γλώσσες Γουακασάν" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Welsh" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Γλώσσες Sorbian" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Γλώσσες Εσκιμώων" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Ζουλού" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Οι ακόλουθες ενέργειες θα γίνουν:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "δεν λήγει" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "έληξε: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "λήγει: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(δεν λήγει)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(ΕΛΗΞΕ)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(λήγει μέσα σε 24ω)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(λήγει σε %d ημέρα)" +msgstr[1] "(λήγει σε %d ημέρες)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "άγνωστο" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "μη υποστηριζόμενο" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Επίπεδο 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Επίπεδο 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Επίπεδο 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Είναι απαραίτητη η συμπληρωματική σύμβαση πελάτη" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "μη έγκυρο" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Το επίπεδο υποστήριξης είναι απροσδιόριστο" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Ο κατασκευαστής δεν παρέχει υποστήριξη." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Προσδιορισμός προβλήματος, που σημαίνει πως η τεχνική υποστήριξη είναι " +"σχεδιασμένη για να παρέχει πληροφορίες συμβατότητας, βοήθεια εγκατάστασης, " +"υποστήριξη χρήσης, συνεχόμενη συντήρηση και βασική λύση προβλημάτων. Η " +"υποστήριξη επιπέδου 1 δεν προορίζεται για να διορθώνει σφάλματα " +"ελαττωματικών προϊόντων." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Απομόνωση προβλήματος, που σημαίνει πως η τεχνική υποστήριξη είναι " +"σχεδιασμένη για να αναπαράγει τα προβλήματα των πελατών, να απομονώνει την " +"περιοχή του προβλήματος και να παρέχει λύση για προβλήματα που δεν λύνονται " +"με την υποστήριξη Επιπέδου 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Επίλυση προβλήματος, που σημαίνει ότι η τεχνική υποστήριξη είναι σχεδιασμένη " +"για να επιλύει πολύπλοκα προβλήματα χρησιμοποιώντας μηχανική στην επίλυση " +"σφαλμάτων υλικού που έχουν επιβεβαιωθεί από την υποστήριξη Επιπέδου 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" +"Μια συμπληρωματική σύμβαση πελάτη είναι απαραίτητη για λήψη υποστήριξης." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Άγνωστη επιλογή υποστήριξης. Δεν υπάρχει διαθέσιμη περιγραφή" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Η διαχείριση συστήματος έχει κλειδωθεί από την εφαρμογή με pid %d (%s).\n" +"Κλείστε την εφαρμογή πριν ξαναπροσπαθήσετε." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Άγνωστη λειτουργία ταιριάσματος '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Άγνωστη λειτουργία ταιριάσματος '%s' για το pattern '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Μη έγκυρη κανονική έκφραση '%s': η εντολή regcomp επέστρεψε %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Μη έγκυρη κανονική έκφραση '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Απαιτείται πιστοποίηση για '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Επισκεφθείτε το Κέντρο Πελατών της Novell για να ελέγξετε εάν η εγγραφή σας " +"είναι έγκυρη και δεν έχει λήξει." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Δημιουργία σημείου προσάρτησης: Δεν είναι δυνατή η εύρεση εγγράψιμου " +"καταλόγου για τη δημιουργία σημείου προσάρτησης" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Παρακαλούμε εγκαταστήστε πρώτα το πακέτο 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Αδυναμία δημιουργίας καταλόγου μεταδεδομένων λανθάνουσας μνήμης." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Σφάλμα στην προσπάθεια ανάγνωσης από το '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Αδυναμία δημιουργίας %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Δεν βρέθηκαν έγκυρα μεταδεδομένα στην καθορισμένη URL" +msgstr[1] "Δεν βρέθηκαν έγκυρα μεταδεδομένα στις καθορισμένες URLs" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Αποτυχία αποθήκευσης στην λανθάνουσα μνήμη του αποθετηρίου (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Δημιουργία λανθάνουσας μνήμης αποθετηρίου '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" +"Αδυναμία δημιουργίας λανθάνουσας μνήμης στο %s - δεν έχετε δικαιώματα " +"εγγραφής." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Τύπος αδιαχείριστου αποθετηρίου" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Προσθήκη αποθετηρίου '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Μη έγκυρο όνομα αρχείου αποθετηρίου στο '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Αδυναμία ανοίγματος αρχείου '%s' για εγγραφή." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Άγνωστο σφάλμα κατά την ανάγνωση από '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Αδυναμία ανάγνωσης καταλόγου αποθετηρίου '%1%': Δεν έχετε δικαιώματα" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Αποτυχία ανάγνωσης καταλόγου '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Αδυναμία ανάγνωσης αρχείου αποθετηρίου '%1%': Δεν έχετε δικαιώματα" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Αφαίρεση αποθετηρίου '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Δεν είναι κατανοητό που είναι αποθηκευμένο το αποθετήριο." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Αδυναμία διαγραφής '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Δεν είναι κατανοητό που είναι αποθηκευμένη η υπηρεσία." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Άγνωστη υπηρεσία '%1%': Αφαίρεση του ορφανού αποθετηρίου υπηρεσιών '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Το alias του αποθετηρίου δεν μπορεί να ξεκινά από τελεία." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Το ψευδώνυμο της υπηρεσίας δεν μπορεί να ξεκινά με τελεία." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Συνέχεια;" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Λείπει το απαιτούμενο χαρακτηριστικό '%s'." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Μία ή και οι δύο ιδιότητες των '%s' ή '%s' χρειάζονται." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Απέτυχε η επαλήθευση της υπογραφής" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Το πακέτο %s φαίνεται πως καταστράφηκε κατά την μεταφορά. Θέλετε να " +"ξαναδοκιμάσετε ανάκτηση;" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Αποτυχία παροχής Πακέτου %s. Θέλετε να ξαναδοκιμάσετε ανάκτηση;" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Απέτυχε ο έλεγχος applydeltarpm." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "Αποτυχία applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Το πρόσθετο της υπηρεσίας δεν υποστηρίζει την αλλαγή μιας ιδιότητας." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Αδυναμία παροχής αρχείου '%s' από το αποθετήριο '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Δεν υπάρχει το URL στο αποθετήριο." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Το αρχείο %1%\n" +" από το πακέτο\n" +" %2%\n" +" συγκρούεται με το αρχείο από το πακέτο\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Το αρχείο %1%\n" +" από το πακέτο\n" +" %2%\n" +" συγκρούεται με το αρχείο από την εγκατάσταση του\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Το αρχείο %1%\n" +" από την εγκατάσταση του\n" +" %2%\n" +" συγκρούεται με το αρχείο από το πακέτο\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Το αρχείο %1%\n" +" από την εγκατάσταση του\n" +" %2%\n" +" συγκρούεται με το αρχείο από την εγκατάσταση του\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Το αρχείο %1%\n" +" από το πακέτο\n" +" %2%\n" +" συγκρούεται με το αρχείο\n" +" %3%\n" +" από το πακέτο\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Το αρχείο %1%\n" +" από το πακέτο\n" +" %2%\n" +" συγκρούεται με το αρχείο\n" +" %3%\n" +" από την εγκατάσταση του\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Το αρχείο %1%\n" +" από την εγκατάσταση του\n" +" %2%\n" +" συγκρούεται με το αρχείο\n" +" %3%\n" +" από το πακέτο\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Το αρχείο %1%\n" +" από την εγκατάσταση του\n" +" %2%\n" +" συγκρούεται με το αρχείο\n" +" %3%\n" +" από την εγκατάσταση του\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Αδυναμία δημιουργίας sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "διακοπή %s λόγω αγνόησης μερικών εξαρτήσεων του" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "γενικά αγνόηση μερικών εξαρτήσεων" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "συγκρουόμενες αιτήσεις" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "κάποιο πρόβλημα εξαρτήσεων" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "μη υποστηριζόμενο αίτημα" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "διαγραμμένοι πάροχοι: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"μη εγκαταστήσιμοι πάροχοι: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "Μη εγκαταστήσιμοι πάροχοι: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Το αίτημα αυτό θα καταστρέψει το σύστημα σας!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "αγνοήστε την προειδοποίηση ενός κατεστραμμένου συστήματος" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Η εγκατάσταση ματαιώθηκε σύμφωνα με τις οδηγίες." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " εκτελέστηκε" + +# %s is either BOOTP or DHCP +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " αποτυχία εκτέλεσηης" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "το %s έχει ήδη εκτελεστεί ως %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " η εκτέλεση παραλείφθηκε κατά την ματαίωση" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Σφάλμα κατά την αποστολή μηνύματος ειδοποίησης ενημέρωσης." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Νέο μήνυμα ενημέρωσης" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Το RPM απέτυχε: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Απέτυχε να εισάγει το δημόσιο κλειδί από το αρχείο %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Αδυναμία απομάκρυνσης του δημοσίου κλειδιού %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Αλλαγή αρχείων ρύθμισης για %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "Το rpm αποθήκευσε το %s ως %s αλλά ήταν αδύνατο να διαφανεί η διαφορά" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"Το rpm αποθήκευσε το %s ως %s.\n" +"Εδώ είναι οι πρώτες 25 γραμμές της διαφοράς:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "Το rpm δημιούργησε το %s ως %s αλλά ήταν αδύνατο να διαφανεί η διαφορά" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"To rpm δημιούργησε το %s ως %s.\n" +"Εδώ είναι οι πρώτες 25 σειρές της διαφοράς:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Επιπρόσθετο αποτέλεσμα rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "δημιουργήθηκε αντίγραφο ασφαλείας %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Η υπογραφή είναι εντάξει" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Άγνωστος τύπος υπογραφής" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Η υπογραφή δεν μπορεί να επαληθευτεί" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Η υπογραφή είναι εντάξει, αλλά το κλειδί δεν είναι έμπιστο" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Η υπογραφές του δημόσιου κλειδιού δεν είναι διαθέσιμες" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Το αρχείο δεν υπάρχει ή η υπογραφή δεν μπορεί να ελεχθεί" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Το αρχείο δεν είναι υπογεγραμμένο" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Ύποπτος τύπος '%s' για το %u byte στον αθροιστικό έλεγχο '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Αδυναμία ανοίγματος pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Αδυναμία ανοίγματος διασωλήνωσης (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Μη έγκυρο string αναζήτησης LDAP URL" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Μη έγκυρη παράμετρος αναζήτησης LDAP URL '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Αδυναμία κλωνοποίησης αντικειμένου Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Μη έγκυρη αναφορά αντικειμένου κενού Url" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Αδυναμία ανάλυσης συστατικών Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Ιστορικό:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Το σχήμα Url δεν επιτρέπει ένα %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "μη έγκυρο %s συστατικό '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "μη έγκυρο %s συστατικό" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" +"Δεν υποστηρίζεται η ανάλυση string ερωτήματος για αυτήν τη διεύθυνση URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Το σχήμα Url είναι ένα απαιτούμενο συστατικό" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Λανθασμένο σχήμα Url '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Το σχήμα Url δεν επιτρέπει όνομα χρήστη" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Το σχήμα Url δεν επιτρέπει συνθηματικό" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Το σχήμα Url απαιτεί ένα συστατικό συστήματος" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Το σχήμα Url δεν επιτρέπει ένα συστατικό συστήματος" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Μη έγκυρο συστατικό συστήματος '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Το σχήμα Url δεν σας επιτρέπει μια θύρα" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "μη έγκυρο συστατικό θύρας '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Το σχήμα Url απαιτεί όνομα διαδρομής" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Σχετική διαδρομή δεν επιτρέπεται εάν υπάρχει αρχή" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Κωδικοποιημένο string περιέχει ένα NUL byte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Μη έγκυρος διαχωριστικός χαρακτήρας χωριστής διάταξης παραμέτρων" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Μη έγκυρος διαχωριστικός χαρακτήρας χωριστού χάρτη παραμέτρων" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Μη έγκυρος διαχωριστικός χαρακτήρας ένωσης διατάξεων παραμέτρων" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Η εντολή τερματίστηκε με κατάσταση %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Η εντολή τερματίστηκε από το σήμα %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Η εντολή τερματίστηκε με άγνωστο σφάλμα." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Αδυναμία chroot σε '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Αδυναμία chdir στο '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Αδυναμία chdir στο '%s' μέσα σε chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Αδυναμία εκτέλεσης του '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Αδυναμία διακλάδωσης (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Αποτυχία προσάρτησης %s στο %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Αποτυχία από-προσάρτησης %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Εσφαλμένο όνομα αρχείου: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" +"Το μέσο δεν ανοίχτηκε κατά την προσπάθεια εκτέλεσης της ενέργειας '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Το αρχείο '%s' δεν βρέθηκε στο μέσο '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Αδυναμία εγγραφής αρχείο '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Το μέσο δεν είναι συνδεδεμένο" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Εσφαλμένο σημείο σύνδεσης μέσου" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Η αρχικοποίηση λήψης (curl) απέτυχε για '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Εξαίρεση '%s' συστήματος στο μέσο '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Η διαδρομή '%s' στο μέσο '%s' δεν είναι αρχείο." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Η διαδρομή '%s' στο μέσο '%s' δεν είναι κατάλογος." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Κακώς-διατυπωμένο URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Κενό όνομα συστήματος στην URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Κενό σύστημα αρχείων στην URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Κενός προορισμός στην URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Μη υποστηριζόμενο URl σχήμα στο '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Η λειτουργία δεν υποστηρίζεται από το μέσο" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Σφάλμα λήψεως (curl) για '%s':\n" +"Κωδικός σφάλματος: %s\n" +"Μήνυμα λάθους: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Προκλήθηκε σφάλμα κατά την διάρκεια ρύθμισης των επιλογών λήψης (curl) για " +"'%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Η πηγή του μέσου '%s' δεν περιέχει το επιθυμητό μέσο" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Το μέσο '%s' είναι σε χρήση από άλλο στιγμιότυπο" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Αδυναμία αποβολής κάποιου μέσου" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Αδυναμία αποβολής μέσου '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Άρνηση άδειας πρόσβασης στο '%s'." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Το χρονικό όριο εξαντλήθηκε όταν έγινε πρόσβαση '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Η τοποθεσία '%s' είναι προσωρινά μη προσβάσιμη." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Πρόβλημα πιστοποιητικού SSL, επαληθεύστε ότι το πιστοποιητικό CA είναι " +"εντάξει για '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Μη υποστηριζόμενη μέθοδος πιστοποίησης HTTP '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ναι" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Όχι" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Προειδοποιηση: " + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Σφάλμα" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "έγινε" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "σφάλμα" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Προειδοποιηση: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Λήψη:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "εκκίνηση" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Δεν βρέθηκε" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Καμία διαθέσιμη βοήθεια για αυτή την εντολή." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "καμία διαθέσιμη βοήθεια για αυτή την επιλογή" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "εμφάνιση όλων των επιλογών" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ναι" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "όχι" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Εκτέλεση %%posttrans script '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Εκτέλεση %posttrans scripts" + +#~ msgid "Package is not signed!" +#~ msgstr "Το πακέτο δεν είναι υπογεγραμμένο!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "το %s δεν ανήκει σε αποθετήριο αναβάθμισης της διανομής" + +#~ msgid "%s has inferior architecture" +#~ msgstr "το %s έχει υποδαιέστερη αρχιτεκτονική" + +#~ msgid "problem with installed package %s" +#~ msgstr "πρόβλημα με τα εγκατεστημένα πακέτα %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "τίποτα δεν παρέχει το ζητούμενο %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Έχετε ενεργοποιήσει όλα τα απαιτούμενα αποθετήρια;" + +#~ msgid "package %s does not exist" +#~ msgstr "το πακέτο %s δεν υπάρχει" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "το %s παρέχεται από το σύστημα και είναι αδύνατο να διαγραφεί" + +#~ msgid "%s is not installable" +#~ msgstr "το %s είναι μη εγκαταστάσιμο" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "τίποτα δεν παρέχει το %s που χρειάζεται από το %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "αδυναμία εγκατάστασης %s και %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "το %s συγκρούεται με %s που παρέχεται από το %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "Το %s απαρχαιώνει το %s που παρέχεται από το %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "το εγκατεστημένο %s απαρχαιώνει %s που παρέχεται από %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "το επιλύσιμο %s συγκρούεται με %s που παρέχεται από τον εαυτό του" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "το %s απαιτεί %s, αλλά αυτή η απαίτηση δεν μπορεί να παρασχεθεί" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "αφαίρεση κλειδώματος για να επιτραπεί η αφαίρεση του %s" + +#~ msgid "do not install %s" +#~ msgstr "να μην εγκατασταθεί το %s" + +#~ msgid "keep %s" +#~ msgstr "διατήρηση του %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "αφαίρεση κλειδώματος για να επιτραπεί η εγκατάσταση του %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "να μην ζητηθεί η εγκατάσταση όλων των επιλύσιμων παρέχοντας %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "να μην ζητηθεί η διαγραφή όλων των επιλύσιμων παρέχοντας %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "να μην εγκατασταθεί η νεότερη έκδοση του %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "διατήρηση του %s παρά την κατώτερη αρχιτεκτονική" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "εγκατάσταση του %s παρά την κατώτερη αρχιτεκτονική" + +#~ msgid "keep obsolete %s" +#~ msgstr "διατήρηση του απαρχαιωμένου %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "εγκατάσταση του %s από το εξαιρούμενο αποθετήριο" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "υποβάθμιση του %s σε %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "αλλαγή αρχιτεκτονικής από %s σε %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "εγκατάσταση %s (με αλλαγή προμηθευτή)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "αντικατάσταση του %s με το %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "απεγκατάσταση του %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Αδυναμία ανοίγματος αρχείου κλειδώματος: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Αυτή η ενέργεια εκτελείται ήδη από άλλο πρόγραμμα." + +#~ msgid "Hal Exception" +#~ msgstr "Εξαίρεση Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Συγγνώμη, αλλά αυτή η έκδοση του libzypp κατασκευάστηκε χωρίς υποστήριξη " +#~ "HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "Το HalContext δεν είναι συνδεμένο" + +#~ msgid "HalDrive not initialized" +#~ msgstr "Το HalDrive δεν είναι αρχικοποιημένο" + +#~ msgid "HalVolume not initialized" +#~ msgstr "Το HalVolume δεν είναι αρχικοποιημένο" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Αδυναμία δημιουργίας σύνδεσης dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Αδυναμία δημιουργίας περιεχομένου libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Αδυναμία ορισμού σύνδεσης dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "Αδυναμία αρχικοποίησης περιεχομένου HAL -- η υπηρεσία hald δεν εκτελείται;" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Δεν είναι οδηγός CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Αδυναμία αρχικοποίησης ιδιοτήτων mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Αδυναμία ορισμού παλινδρομικής ιδιότητας mutex" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Αδυναμία αρχικοποίησης παλινδρομικής mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Αδυναμία λήψης κλειδαριάς mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Αδυναμία απελευθέρωσης κλειδαριάς mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Απέτυχε να εισάγει το δημόσιο κλειδί από το αρχείο %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Αδυναμία απομάκρυνσης του δημοσίου κλειδιού %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Αδυναμία εύρεσης διαθέσιμης συσκευής βρόγχου για προσάρτηση αρχείου " +#~ "εικόνας δεδομένων από '%s'" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "Γενική αγνόησή κάποιων εξαρτήσεων" + +#~ msgid "do not forbid installation of %s" +#~ msgstr "να μην απαγορευτεί η εγκατάσταση του %s" + +#~ msgid "do not keep %s installed" +#~ msgstr "μην κρατήσετε το %s εγκατεστημένο" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Αδυναμία δημιουργίας δημοσίου κλειδιού %s από την κλειδοθήκη %s στο " +#~ "αρχείο %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "" +#~ "Εγίνε προσπάθεια προσθήκης μη υπάρχον κλειδιού %s στην κλειδοθήκη %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Δεν μπορεί chdir να '/' μέσα σε chroot (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Η αρχικοποίηση λήψης (Metalink curl) απέτυχε για '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Σφάλμα λήψης (metalink curl) για '%s':\n" +#~ "Κωδικός σφάλματος: %s\n" +#~ "Μήνυμα λάθους: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Το κατέβασμα διακόπηκε στο %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Το κατέβασμα διακόπηκε από τον χρήστη" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Σφάλμα προκλήθηκε κατά την διάρκεια ρύθμισης των ρυθμίσεων λήψεων " +#~ "(metalink curl) για '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Αδυναμία λήψεως %s από το %s" + +#~ msgid "Valid metadata not found at specified URL(s)" +#~ msgstr "Δεν βρέθηκαν έγκυρα μεταδεδομένα στο/α συγκεκριμένο/α URL(s)" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Σερβία και Μαυροβούνιο" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Άγνωστη επιλογή της list" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "αδυναμία επίλυσης εξαρτήσεων" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Το αρχείο %s δεν έχει ένα checksum.\n" +#~ "Χρήση αυτού του αρχείου παρ' αυτά;" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Το αρχείο %s απέτυχε στον έλεγχο ακεραιότητας με το ακόλουθο κλειδί:\n" +#~ "%s|%s|%s\n" +#~ "Χρήση αυτού του αρχείου παρ' αυτά;" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Το αρχείο %s έχει ένα λανθασμένο checksum.\n" +#~ "Αναμενόταν %s, βρέθηκε %s\n" +#~ "Χρήση αυτού του αρχείου παρ' αυτά;" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Το αρχείο %s έχει ένα άγνωστο checksum %s.\n" +#~ "Χρήση αυτού του αρχείου παρ' αυτά;" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Το αρχείο %s δεν είναι υπογεγραμμένο.\n" +#~ "Χρήση του παρ' αυτά;" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Το αρχείο %s είναι υπογεγραμμένο με ένα άγνωστο κλειδί::\n" +#~ "%s|%s|%s\n" +#~ "Χρήση αυτού του αρχείου παρ' αυτά;" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Βρέθηκε μη έμπιστο κλειδί:\n" +#~ "%s|%s|%s\n" +#~ "Θα εμπιστευτείτε αυτό το κλειδί;" + +#~ msgid "%s remove failed" +#~ msgstr "%s αφαίρεση απέτυχε" + +#~ msgid "Invalid user name or password." +#~ msgstr "Λανθασμένο όνομα χρήστη ή συνθηματικό." + +#~ msgid "rpm output:" +#~ msgstr "αποτέλεσμα rpm:" + +#~ msgid "%s install failed" +#~ msgstr "%s εγκατάσταση απέτυχε" + +#~ msgid "%s installed ok" +#~ msgstr "%s εγκατάσταση ok" + +#~ msgid "%s remove ok" +#~ msgstr "%s αφαίρεση ok" diff --git a/po/en_GB.po b/po/en_GB.po new file mode 100644 index 0000000..9c0c4e4 --- /dev/null +++ b/po/en_GB.po @@ -0,0 +1,5909 @@ +# translation of zypp.po to +# English message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2000, 2001 SuSE GmbH. +# +# James Ogley , 2000, 2001. +# Benjamin Weber , 2007. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2007-08-19 16:20+0100\n" +"Last-Translator: Benjamin Weber \n" +"Language-Team: \n" +"Language: \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: KBabel 1.11.4\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Unknown country: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "No Code" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "United Arab Emirates" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua and Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Netherlands Antilles" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarctica" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "American Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Aland Islands" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaijan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia and Herzegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgium" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet Island" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Cocos (Keeling) Islands" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Central African Republic" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Switzerland" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Cote D'Ivoire" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cook Islands" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Cameroon" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cape Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Christmas Island" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cyprus" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Czech Republic" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Germany" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Denmark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominican Republic" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algeria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Western Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spain" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Ethiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falkland Islands (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federated States of Micronesia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faroe Islands" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "France" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Metropolitan France" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "United Kingdom" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "French Guiana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Germany" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Greenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Equatorial Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Greece" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "South Georgia and the South Sandwich Islands" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard Island and McDonald Islands" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hungary" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ireland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "British Indian Ocean Territory" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraq" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Iceland" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italy" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kyrgyzstan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodia" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comoros" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts and Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "North Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "South Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Cayman Islands" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Lao People's Democratic Republic" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Lebanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lithuania" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libya" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Morocco" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "Mongo" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "San Marino" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshall Islands" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Northern Mariana Islands" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldives" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "New Caledonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk Island" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Netherlands" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norway" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "New Zealand" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "French Polynesia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua New Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Philippines" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poland" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre and Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestinian Territory" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "Serbian" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russian Federation" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi Arabia" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomon Islands" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Sweden" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Saint Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard and Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome and Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks and Caicos Islands" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "French Southern Territories" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tajikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "East Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkey" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad and Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraine" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "United States Minor Outlying Islands" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "United States" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Holy See (Vatican City State)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent and the Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "British Virgin Islands" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Virgin Islands, U.S." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis and Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "South Africa" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Provides" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Requires" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Conflicts" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s obsoletes:%s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recommends" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Suggests" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Enhances" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Supplements" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to start the VM." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to start the VM." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Source package '%s' not found." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Unknown language: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhazian" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinese" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asiatic (Other)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadian" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanian" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonquian Languages" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Southern Altai" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharic" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "English, Old (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apache Languages" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabic" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaic" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonese" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armenian" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucanian" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Artificial (Other)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamese" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturian" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapascan Languages" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australian Languages" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avaric" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaijani" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke Languages" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinese" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basque" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltic (Other)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Belarusian" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber (Other)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (Other)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnian" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Breton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginese" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarian" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmese" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Central American Indian (Other)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalan" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucasian (Other)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celtic (Other)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Chechen" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinese" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook Jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Church Slavic" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Chamic Languages" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Coptic" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornish" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corsican" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creoles and Pidgins, English-Based (Other)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creoles and Pidgins, French-Based (Other)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creoles and Pidgins, Portuguese-Based (Other)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Crimean Tatar" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creoles and Pidgins (Other)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kashubian" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitic (Other)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Czech" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danish" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidian (Other)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Lower Sorbian" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Dutch, Middle (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Dutch" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egyptian (Ancient)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "English" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "English, Middle (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonian" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faroese" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijian" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finnish" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finno-Ugrian (Other)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "French" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "French, Middle (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "French, Old (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisian" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulian" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germanic (Other)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgian" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "German" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertese" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irish" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galician" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "German, Middle High (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "German, Old High (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gothic" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Greek, Ancient (to 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Greek, Modern (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitian" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiian" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebrew" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittite" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Upper Sorbian" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Hungarian" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Icelandic" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indic (Other)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesian" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-European (Other)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iranian (Other)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Iroquoian Languages" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italian" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanese" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japanese" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeo-Persian" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeo-Arabic" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (Other)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanese" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korean" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdish" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latin" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvian" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgan" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lithuanian" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxembourgish" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya and Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedonian" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurese" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallese" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesian (Other)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irish, Middle (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Miscellaneous Languages" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (Other)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagasy" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltese" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo Languages" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavian" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolian" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Multiple Languages" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda languages" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Mayan Languages" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "North American Indian" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitan" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, South" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, North" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Low German" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanian (Other)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norwegian Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norwegian Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norse, Old" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norwegian" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Northern Sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubian Languages" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Classical Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (post 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turkish, Ottoman (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomian Languages" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuan (Other)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persian, Old (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persian" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Philippine (Other)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Phoenician" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polish" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portuguese" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakrit Languages" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provencal, Old (to 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romance (Other)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Raeto-Romance" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romany" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romanian" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russian" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "South American Indian (Other)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salishan Languages" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritan Aramaic" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbian" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilian" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croatian" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitic (Other)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irish, Old (to 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Sign Languages" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouan Languages" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetan (Other)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavic (Other)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovak" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenian" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Southern Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Northern Sami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Sami Languages (Other)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoan" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, Southern" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spanish" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinian" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Saharan (Other)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanese" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerian" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Swedish" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syriac" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitian" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (Other)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetan" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tonga Islands)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmen" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi Languages" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turkish" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaic (Other)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvinian" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritic" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainian" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Undetermined" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbek" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamese" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakashan Languages" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Welsh" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbian Languages" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupik Languages" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +#, fuzzy +msgid "Following actions will be done:" +msgstr "The following packages will be updated:\n" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1' does not exist." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1' does not exist." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "unknown" + +#: zypp/VendorSupportOptions.cc:17 +#, fuzzy +msgid "unsupported" +msgstr " - not supported" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "The disk does not exist." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Unknown command '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Unknown digest %s for file %s." + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Invalid Url scheme '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Authentication required for '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "Cannot create directory %1: %2." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, fuzzy, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Error parsing metadata for '%s':" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Cannot create %s: %m\n" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +#, fuzzy +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Valid metadata not found at specified URL(s)" +msgstr[1] "Valid metadata not found at specified URL(s)" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Building repository '%s' cache" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +#, fuzzy +msgid "Unhandled repository type" +msgstr "Uploaded %s to repository." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Adding repository '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Invalid export filename." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Cannot open file for writing." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Unknown command '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Removing repository '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Cannot stat '%s': %m\n" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "The VM's name cannot start with a digit." + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr "The VM's name cannot start with a digit." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Continue?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, fuzzy, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Required file is missing: " + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "Package %s fails integrity check. Do you want to retry?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Package %s fails integrity check. Do you want to retry?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm check failed." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm failed." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "resource type VAR1 does not support show changes feature" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Can't provide file %s from repository %s" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "No url in repository." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "Cannot create the file." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "Generally ignore this requirement" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "Generally ignore this requirement" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "Connection request to: " + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "Cannot install %s due to dependency problems" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +#, fuzzy +msgid "unsupported request" +msgstr " - not supported" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "None provides %s" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "There are no installable providers of %s" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "There are no installable providers of %s" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "The request already exists." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Installation has been aborted as directed." + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "Execute" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "Error during key encryption." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "failed" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Changed configuration files for %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm saved %s as %s, but it was impossible to determine the difference" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm created %s as %s, but it was impossible to determine the difference" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "Additional rpm output:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "created backup %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Source package '%s' not found." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Source package '%s' not found." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Source package '%s' not found." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Cannot open file %1." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Invalid LDAP URL query string" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Invalid LDAP URL query parameter '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Unable to clone Url object" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Invalid empty Url object reference" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Unable to parse Url components" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "History:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url scheme does not allow a %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Invalid %s component '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Invalid %s component" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Query string parsing not supported for this URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url scheme is a required component" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Invalid Url scheme '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url scheme does not allow a username" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url scheme does not allow a password" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url scheme requires a host component" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url scheme does not allow a host component" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Invalid host component '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url scheme does not allow a port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Invalid port component '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url scheme requires path name" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relative path not allowed if authority exists" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Encoded string contains a NUL byte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Invalid parameter array split separator character" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Invalid parameter map split separator character" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Invalid parameter array join separator character" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Command executed when connecting" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Can't find %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Can't find %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Unable to open %s - %s\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to load module \"%s\"." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "File %1 not found in the repository." + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Cannot write to file %1." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 is not a directory." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "Empty CA name." + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Invalid URL scheme '%1'." + +#: zypp-media/mediaexception.cc:131 +#, fuzzy +msgid "Operation not supported by medium" +msgstr "Profile version not supported by Apparmor module\n" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +#, fuzzy +msgid "Cannot eject any media" +msgstr "Cannot find any schemes." + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Cannot stat '%s': %m\n" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Permissions denied" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Unsupported HTTP authentication method '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Yes" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "No" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Warning" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Error" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "done" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "error" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Warning" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Starting..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Not found" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "yes" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "no" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s provides %s, but has another architecture." + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "Problem installing source package %s-%s:" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "None provides %s" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "backup does not exists" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s is locked and cannot be uninstalled." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "not installed" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s is needed by %s" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Cannot install %s" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s conflicts with %s" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s obsoletes %s" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s obsoletes %s" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s conflicts with %s" + +#~ msgid "do not install %s" +#~ msgstr "do not install %s" + +#~ msgid "keep %s" +#~ msgstr "keep %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "do not install %s" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "There are no installable providers of %s" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "Do not install or delete the resolvables concerned" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s provides %s, but has another architecture." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "Install %s although it would change the architecture" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s obsoletes %s" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "Updating %s to %s" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Installation of %s failed:" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Cannot open file %1." + +#~ msgid "Hal Exception" +#~ msgstr "Hal Exception" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext not connected" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive not initialised" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume not initialised" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Unable to create dbus connection" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Can't create libhal context" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Can't set dbus connection" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Unable to initialise HAL context -- hald not running?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Not a CDROM drive" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Can't initialise mutex attributes" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Can't set recursive mutex attribute" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Can't initialise recursive mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Can't acquire the mutex lock" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Can't release the mutex lock" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Unable to get the public key." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "not installed" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Unable to open %s - %s\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia and Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Unknown list option" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "could not resolve dependencies" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "File %s failed integrity check with the following key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" + +#~ msgid "%s remove failed" +#~ msgstr "%s remove failed" + +#~ msgid "Invalid user name or password." +#~ msgstr "Invalid user name or password." + +#~ msgid "rpm output:" +#~ msgstr "rpm output:" + +#~ msgid "%s install failed" +#~ msgstr "%s install failed" + +#~ msgid "%s installed ok" +#~ msgstr "%s installed ok" + +#~ msgid "%s remove ok" +#~ msgstr "%s remove ok" + +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" + +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Do not install or delete the resolvables concerned" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Ignore that %s is already set to install" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "Ignore the obsolete %s in %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "Ignore this conflict of %s" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "Ignore this requirement just here" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "Install %s although it would change the architecture" + +#~ msgid "Install missing resolvables" +#~ msgstr "Install missing resolvables" + +#~ msgid "Keep resolvables" +#~ msgstr "Keep resolvables" + +#~ msgid "Unlock these resolvables" +#~ msgstr "Unlock these resolvables" + +#~ msgid "delete %s" +#~ msgstr "delete %s" + +#~ msgid "install %s" +#~ msgstr "install %s" + +#~ msgid "unlock %s" +#~ msgstr "unlock %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "unlock all resolvables" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Cannot open file %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "Error reading repositories:" + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "Path Parameter parsing not supported for this URL" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "Path parameter parsing not supported for this URL" + +#~ msgid "Reading '%s' repository cache" +#~ msgstr "Reading '%s' repository cache" + +#~ msgid "Reading patch and delta rpms from '%s' repository cache" +#~ msgstr "Reading patch and delta rpms from '%s' repository cache" + +#~ msgid "Cleaning repository '%s' cache" +#~ msgstr "Cleaning repository '%s' cache" + +#~ msgid "Reading repository '%s' cache" +#~ msgstr "Reading repository '%s' cache" + +#~ msgid "Software management is already running." +#~ msgstr "Software management is already running." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s is replaced by %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s replaced by %s" + +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "%s will be deleted by the user.\n" + +#~ msgid "%s will be deleted by another application. (ApplLow/ApplHigh)\n" +#~ msgstr "%s will be deleted by another application. (ApplLow/ApplHigh)\n" + +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s will be installed by the user.\n" + +#~ msgid "%s will be installed by another application. (ApplLow/ApplHigh)\n" +#~ msgstr "%s will be installed by another application. (ApplLow/ApplHigh)\n" + +#, fuzzy +#~ msgid "No valid solution found within %d seconds" +#~ msgstr "No valid solution found with just resolvables of best architecture." + +#~ msgid "No valid solution found with just resolvables of best architecture." +#~ msgstr "No valid solution found with just resolvables of best architecture." + +#~ msgid "" +#~ "With this run only resolvables with the best architecture have been " +#~ "regarded.\n" +#~ msgstr "" +#~ "With this run only resolvables with the best architecture have been " +#~ "regarded.\n" + +#~ msgid "" +#~ "Regarding all possible resolvables takes time, but can come to a valid " +#~ "result." +#~ msgstr "" +#~ "Regarding all possible resolvables takes time, but can come to a valid " +#~ "result." + +#~ msgid "Invalid information" +#~ msgstr "Invalid information" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s is needed by other resolvables" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s is needed by:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s conflicts with other resolvables" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s conflicts with:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s obsoletes other resolvables" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "These resolvables will be deleted from the system." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s depends on other resolvables" + +#~ msgid "%s depends on %s" +#~ msgstr "%s depends on %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s depends on:%s" + +#~ msgid "Child of" +#~ msgstr "Child of" + +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "There is no resource available which supports this requirement." + +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" + +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "Cannot install %s, because it is conflicting with %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s is not installed and has been marked as not installable" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s has unfulfilled requirements" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s has missing dependencies" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s cannot be installed due to missing dependencies" + +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s fulfils dependencies of %s but will be uninstalled" + +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s fulfils dependencies of %s but will be kept on your system" + +#~ msgid "No need to install %s" +#~ msgstr "No need to install %s" + +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "Cannot install %s to fulfil the dependencies of %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "Cannot install %s to fulfil the dependencies of %s" + +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s will not be uninstalled, because it is still required" + +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s obsoletes %s. But %s cannot be deleted, because it is locked." + +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "Cannot install %s, because it is conflicting" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s is not installable due to conflicts with %s" + +#~ msgid "Requirememt %s cannot be fulfilled." +#~ msgstr "Requirement %s cannot be fulfilled." + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "for requiring %s for %s when upgrading %s" + +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s is lacking the requirement %s" + +#~ msgid ", Action: " +#~ msgstr ", Action: " + +#~ msgid ", Trigger: " +#~ msgstr ", Trigger: " + +#~ msgid "package" +#~ msgstr "package" + +#~ msgid "selection" +#~ msgstr "selection" + +#~ msgid "pattern" +#~ msgstr "pattern" + +#~ msgid "product" +#~ msgstr "product" + +#~ msgid "patch" +#~ msgstr "patch" + +#~ msgid "script" +#~ msgstr "script" + +#~ msgid "message" +#~ msgstr "message" + +#~ msgid "atom" +#~ msgstr "atom" + +#~ msgid "system" +#~ msgstr "system" + +#~ msgid "Resolvable" +#~ msgstr "Resolvable" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "Marking this resolution attempt as invalid." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "Marking resolvable %s as not installable" + +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." + +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" + +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "Can't install %s, because it does not apply to this system." + +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" + +#~ msgid "This would invalidate %s." +#~ msgstr "This would invalidate %s." + +#~ msgid "Establishing %s" +#~ msgstr "Establishing %s" + +#~ msgid "Installing %s" +#~ msgstr "Installing %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "Skipping %s: already installed" + +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "There are no alternative providers of %s installed" + +#~ msgid "for %s" +#~ msgstr "for %s" + +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "Upgrading to %s to avoid removing %s is not possible." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s provides %s, but is scheduled to be uninstalled." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "" +#~ "%s provides %s, but another version of that %s is already installed." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s provides %s, but it is not installable. Try installing it on its own " +#~ "for more details." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s provides %s, but it is locked." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s provides %s, but is scheduled to be kept." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s provides %s, but has another architecture." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "Can't satisfy requirement %s for %s" + +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." + +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." + +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "Marking %s as not installable due to conflicts over %s" + +#~ msgid "from %s" +#~ msgstr "from %s" + +#~ msgid " Error!" +#~ msgstr " Error!" + +#~ msgid " Important!" +#~ msgstr " Important!" + +#~ msgid "Make a solver run with ALL possibilities." +#~ msgstr "Make a solver run with ALL possibilities." + +#~ msgid "Regarding all resolvables with a compatible architecture." +#~ msgstr "Regarding all resolvables with a compatible architecture." + +#, fuzzy +#~ msgid "Make a solver run with best architecture only." +#~ msgstr "Make a solver run with ALL possibilities." + +#, fuzzy +#~ msgid "Regarding resolvables with best architecture only." +#~ msgstr "Regarding all resolvables with compatible architecture." + +#~ msgid "%s depended on %s" +#~ msgstr "%s depended on %s" + +#~ msgid "%s is recommended by %s" +#~ msgstr "%s is recommended by %s" + +#~ msgid "%s is suggested by %s" +#~ msgstr "%s is suggested by %s" + +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s is enhanced by %s" + +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s is supplemented by %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s part of %s" + +#, fuzzy +#~ msgid "Start the next solver run with doubled timeout." +#~ msgstr "Make a solver run with ALL possibilities." + +#~ msgid "%s is freshened by %s" +#~ msgstr "%s is freshened by %s" diff --git a/po/es.po b/po/es.po new file mode 100644 index 0000000..82f5376 --- /dev/null +++ b/po/es.po @@ -0,0 +1,6178 @@ +# translation of zypp.po to +# Ibán josé García Castillo , 2000. +# Javier Moreno , 2000. +# Jordi Jaen Pallares , 1999, 2000, 2001. +# Pablo Iranzo Gómez , 2000. +# Camaleón, 2007. +# César Sánchez Alonso , 2007. +# Miguel Angel Alvarez , 2008. +# Camaleón , 2008. +# translation of zypp.es.po to +# Spanish message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002, 2003 SuSE Linux AG. +# Copyright (C) 1999, 2000, 2001 SuSE GmbH. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-04-30 21:43+0000\n" +"Last-Translator: Antonio Simón \n" +"Language-Team: Spanish \n" +"Language: es\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: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "País desconocido: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Sin código" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Emiratos Árabes Unidos" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistán" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua y Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguila" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antillas Neerlandesas" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antártida" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Americana" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Islas Aland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaiyán" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia y Herzegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladés" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Bélgica" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahréin" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benín" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudas" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunéi Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bután" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Isla Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botsuana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Bielorrusia" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belice" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canadá" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Islas Cocos (Keeling)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "República Centroafricana" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Suiza" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Costa de Marfil" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Islas Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camerún" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cabo Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Isla Christmas" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Chipre" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "República Checa" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Alemania" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Yibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dinamarca" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "República Dominicana" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Argelia" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipto" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sáhara Occidental" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "España" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopía" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlandia" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiyi" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Islas Malvinas" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Estados Federados de Micronesia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Islas Feroe" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francia" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Francia metropolitana" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabón" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Reino Unido" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Granada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guayana francesa" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenlandia" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadalupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinea Ecuatorial" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grecia" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Georgia del Sur e Islas Sandwich del Sur" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Isla Heard e Islas McDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croacia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haití" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hungría" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanda" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isla de Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Territorios británicos del Océano Índico" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irán" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islandia" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordania" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japón" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirguistán" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Camboya" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comoras" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "San Cristóbal y Nieves" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Corea del Norte" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Corea del Sur" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Islas Caimán" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazajistán" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laso, República Democrática Popular" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Líbano" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Santa Lucía" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesoto" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituania" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburgo" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letonia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marruecos" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Mónaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavia" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "San Martín" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Islas Marshall" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Birmania" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Islas Marianas del Norte" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinica" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauricio" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldivas" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malaui" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "México" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malasia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nueva Caledonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Níger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Isla Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Países Bajos" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noruega" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauruano" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nueva Zelanda" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omán" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panamá" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Perú" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinesia Francesa" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papúa Nueva Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipinas" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistán" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polonia" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "San Pedro y Miquelón" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Territorios palestinos" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palaos" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Catar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunión" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumanía" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Federación Rusa" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arabia Saudí" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Islas Salomón" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudán" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suecia" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Santa Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Eslovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard y Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Eslovaquia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leona" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Santo Tomé y Príncipe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Siria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Suazilandia" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Islas Turcas y Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Territorios australes franceses" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tailandia" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tayikistán" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistán" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Túnez" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Tímor Oriental" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turquía" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad y Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalino" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwán" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ucrania" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Islas menores alejadas de los Estados Unidos" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Estados Unidos" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistán" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Santa Sede (Ciudad Estado del Vaticano)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "San Vicente y las Granadinas" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Islas Vírgenes Británicas" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Islas Vírgenes, EE.UU." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis y Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Sudáfrica" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabue" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Proporciona" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Requisitos previos" + +# clients/hwinfo.ycp:73 +# clients/hwinfo.ycp:73 +# clients/hwinfo.ycp:73 +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Requiere" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Conflictos" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Desplaza" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recomienda" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Sugiere" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Mejora" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Complementa" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" +"Se intentó importar una clave que no existe (%s) al almacén de claves %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Error al importar la clave." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Error al suprimir la clave." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "No se encuentra el archivo de firma %s" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Idioma desconocido: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abjasio" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinés" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acholi" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Circasiano" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-asiático (otros)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikáans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Acadio" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanés" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutiano" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Lenguas algoquinas" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altai meridional" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amhárico" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Inglés antiguo (450 - 1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Lenguas apache" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Árabe" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Arameo" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonés" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armenio" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucano" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapahoe" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Artificial (otros)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Asamés" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturiano" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Lenguas atapascanas" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Lenguas australianas" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Ávaro" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestano" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awetí" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aimara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaiyano" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Lenguas Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Beluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinés" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Vasco" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Báltico (otros)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorruso" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengalí" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Bereber (otros)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantú (otros)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnio" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretón" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriato" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugi" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Búlgaro" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birmano" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Cado" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Lenguas amerindias de Centroamérica (otros)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Caribe" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalán" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucásico (otros)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Céltico (otros)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Checheno" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chino" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukés" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Jerga Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choktaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewa" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cheroqui" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Eslavo eclesial" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvasio" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyén" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Lenguas chámicas" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Copto" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Córnico" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corso" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Criollos y pidgins basados en el inglés (otros)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Criollos y pidgins basados en el francés (otros)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Criollos y pidgins basados en el portugués (otros)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cri" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tártaro de Crimea" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Criollos y pidgins (otros)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Casubiano" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cusita (otros)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Checo" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danés" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Esclavo (atapascano)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Lenguas drávidas (otros)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Bajo sorabo" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Danés medieval (1050 - 1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Neerlandés" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egipcio (antiguo)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamita" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inglés" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Inglés medio (1100 - 1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonio" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewé" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Feroe" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fiyi" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finés" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fino-ungrio (otros)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francés" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francés medieval (1400 - 1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francés antiguo (842 - 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisón" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fula" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulano" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germánico (otros)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgiano" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Alemán" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertés" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaélico" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandés" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Gallego" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Alto alemán medieval (1050 - 1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Alto alemán antiguo (750 - 1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gótico" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Griego antiguo (hasta 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Griego moderno (desde 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guaraní" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitiano" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiano" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebreo" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynón" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hitita" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Alto sorabo" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Húngaro" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandés" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Yi de Sichuan" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingua" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Ilocano" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Asociación de la Lengua Auxiliar Internacional)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Índico (otros)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Bahasa" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoeuropeo (otros)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingusio" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraní (otros)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Lenguas iroquesas" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiano" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanés" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonés" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeo-persa" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeo-árabe" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Cabila" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Cachemir" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Canurio" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazaco" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Cherkeso" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Jasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Joisán (otros)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Jemer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Jotanés" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyo" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarruandés" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirguiso" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Congo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreano" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosrae" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpellé" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachái-Balcar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumico" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdo" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latín" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letón" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezgino" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgués" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituano" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgués" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenia y Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedonio" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurés" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshalés" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Macasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayamés" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandinga" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maorí" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austranesio (otros)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malayo" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mendé" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandés medieval (900 - 1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Varios idiomas" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Jemer (otros)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgache" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltés" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchú" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Lenguas manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohicano" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavo" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Varios idiomas" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Lenguas munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandés" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Lenguas mayas" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Lenguas amerindias de Norteamérica" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitano" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele meridional" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele septentrional" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Bajo alemán" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalés" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-cordofano (otros)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niue" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Noruego nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Noruego bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogáy" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Noruego antiguo" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Noruego" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho septentrional" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Lenguas nubias" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari clásico" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitano (posterior a 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osetio" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turco otomano (1500 - 1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Lenguas otomanas" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papú (otros)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Panganisano" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlevi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panyabí" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauano" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persa antiguo (600 - 400 a.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persa" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipino (otros)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenicio" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polaco" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Ponapeano" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugués" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Lenguas prácritas" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provenzal antiguo (hasta 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajastaní" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongano" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romance (otros)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Raeto-romance" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romaní" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumano" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ruso" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakuto" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Lenguas amerindias de Sudamérica (otros)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Lenguas salish" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Arameo samaritano" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sánscrito" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbio" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliano" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Escocés" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croata" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semítico (otros)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandés antiguo (hasta 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Lenguas de signos" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Lenguas siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-tibetano (otros)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Eslavo (otros)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Eslovaco" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Esloveno" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sami meridional" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Sami septentrional" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Lenguas sami (otros)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Sami lule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Sami inari" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoano" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Sami skolt" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninké" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdiano" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalí" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songay" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho meridional" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Español" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardo" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-sahariano (otros)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Sisuati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanés" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerio" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Suajili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Sueco" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siríaco" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitiano" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (otros)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tártaro" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telegu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tayiko" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalo" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetano" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigré" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigriña" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamasheq" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (islas Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshián" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tsuana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turcomano" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Lenguas Tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turco" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaico (otros)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvano" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurto" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugarítico" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uigur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ucraniano" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Indeterminado" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbeco" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamita" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votiaco" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Lenguas wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Galés" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Lenguas sórabas" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Valón" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Calmico" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapés" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Lenguas Yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapoteca" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Chuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulú" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuñi" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Se realizarán las siguientes acciones:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "no caduca" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "caducado: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "caduca: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(no caduca)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(CADUCADO)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(caduca en las próximas 24 horas)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(expira en %d día)" +msgstr[1] "(expira en %d días)" + +# clients/support_registration.ycp:225 include/support/registration.ycp:77 +# clients/support_askkey.ycp:246 include/support/supportio.ycp:79 +# +# clients/support_askkey.ycp:246 include/support/supportio.ycp:79 +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "desconocido" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "no compatible" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Nivel 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Nivel 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Nivel 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Se necesita un contrato adicional de cliente" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Se ha discontinuado y ha quedado obsoleto por otro paquete" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "no válido" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "El nivel de asistencia no se ha especificado" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "El proveedor no proporciona asistencia." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Determinación de problemas, lo que significa asistencia técnica diseñada " +"para proporcionar información de compatibilidad, asistencia para la " +"instalación, compatibilidad de uso, mantenimiento continuo y resolución " +"básica de problemas. La asistencia de nivel 1 no está pensada para corregir " +"errores por defectos del producto." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Aislamiento de problemas, lo que significa asistencia técnica diseñada para " +"reproducir los problemas del cliente, aislar el área problemática y " +"proporcionar soluciones para los problemas que no se resuelven mediante la " +"asistencia de nivel 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Resolución de problemas, lo que significa asistencia técnica diseñada para " +"resolver problemas complejos utilizando la ingeniería en la resolución de " +"los defectos de los productos identificados en la asistencia de nivel 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Para obtener asistencia se necesita un contrato adicional de cliente." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"El paquete se ha discontinuado y ha quedado obsoleto por un nuevo paquete " +"con otro nombre." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Opción de asistencia desconocida. Descripción no disponible" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"La gestión del sistema está bloqueada por la aplicación con pid %d (%s).\n" +"Cierre la aplicación antes de volver a intentarlo." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Modo de coincidencias '%s' desconocido" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Modo de coincidencias %s desconocido para el patrón %s" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Expresión regular %s no válida: regcomp ha devuelto %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Expresión regular '%s' no válida" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Se requiere autenticación para %s" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Se intentará de nuevo..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Renunciar después de %1% intentos." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visite el Centro de servicios al cliente de SUSE para comprobar si su " +"registro es válido y no ha caducado." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visite el Centro de servicios al cliente de Novell para comprobar si el " +"registro es válido y no ha caducado." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Creación de punto de conexión: no se encuentra ningún directorio en el que " +"se pueda escribir para crear un punto de conexión" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Instale primero el paquete lsof." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "No es posible crear el directorio para el caché de metadatos." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Error al intentar leer de %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "No es posible crear %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "No se han encontrado metadatos válidos en la URL especificada" +msgstr[1] "No se han encontrado metadatos válidos en las URL especificadas" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Error al añadir a caché el repositorio (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Construyendo el caché del repositorio %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "No es posible crear el caché en %s, no posee permisos de escritura." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Tipo de repositorio no gestionado" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Añadiendo el repositorio %s" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nombre de archivo del repositorio no válido en %s" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "No es posible abrir el archivo %s para escribir en él." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Error desconocido al leer de %s" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "No es posible leer el directorio de repositorio %1%: permiso denegado" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Error al leer el directorio %s" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "No es posible leer el archivo de repositorio %1%: permiso denegado" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Eliminando el repositorio %s" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "No es posible determinar dónde está almacenado el repositorio." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "No es posible suprimir %s" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "No es posible determinar dónde está almacenado el servicio." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Servicio desconocido %1%: se va a eliminar el repositorio de servicios " +"huérfano %2%" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "El alias del repositorio no puede comenzar con un punto." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "El alias del servicio no puede comenzar con un punto." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "No hay resumen para el archivo %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Resumen desconocido %s para el archivo %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Error de verificación del resumen para el archivo %s" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "El archivo %s no está asignado. ¿Desea continuar?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "El archivo %s del repositorio %s no está asignado. ¿Desea continuar?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" +"¿Desea rechazar la clave, confiar en ella temporalmente o confiar en ella " +"siempre?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Nombre de la clave: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +"Ha recibido %1% clave de firma de paquete nueva para el repositorio %2%:" +msgstr[1] "" +"Ha recibido %1% clave de firmas de paquete nuevas para el repositorio %2%:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Error de verificación de firma para el archivo %1%." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"Error de verificación de firma para el archivo %1% desde el repositorio %2%." + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "¿Desea continuar?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"El archivo %s está firmado con una clave desconocida %s. ¿Desea continuar?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"El archivo %s del repositorio %s está firmado con una clave desconocida %s. " +"¿Desea continuar?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "El repositorio %1% no define ningún URL 'gpgkey=' adicional." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Buscando la clave gpg identificada con %1% en el repositorio %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Buscando la clave gpg identificada con %1% en la caché %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Falta el atributo requerido %s." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Se requieren uno o ambos de los atributos %s o %s." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Error de verificación de firma" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Parece que el paquete %s se ha dañado durante la transferencia. ¿Desea " +"volver a intentar la recuperación?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Error al proporcionar el paquete %s. ¿Desea volver a intentar la " +"recuperación?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Error al comprobar applydeltarpm." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "Error de applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "El complemento del servicio no admite el cambio de un atributo." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "No es posible proporcionar el archivo %s desde el repositorio %s" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "No hay ninguna URL en el repositorio." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Medio esperado %1%/%2% identificado por el archivo «%3%», el cual contiene:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"El archivo %1%\n" +" del paquete\n" +" %2%\n" +" tiene un conflicto con un archivo del paquete\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"El archivo %1%\n" +" del paquete\n" +" %2%\n" +" tiene un conflicto con el archivo de la instalación de\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"El archivo %1%\n" +" de la instalación de\n" +" %2%\n" +" tiene un conflicto con un archivo del paquete\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"El archivo %1%\n" +" de la instalación de\n" +" %2%\n" +" tiene un conflicto con un archivo de la instalación de\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"El archivo %1%\n" +" del paquete\n" +" %2%\n" +" tiene un conflicto con el archivo\n" +" %3%\n" +" del paquete\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"El archivo %1%\n" +" del paquete\n" +" %2%\n" +" tiene un conflicto con el archivo\n" +" %3%\n" +" de la instalación de\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"El archivo %1%\n" +" de la instalación de\n" +" %2%\n" +" tiene un conflicto con el archivo\n" +" %3%\n" +" del paquete\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"El archivo %1%\n" +" de la instalación de\n" +" %2%\n" +" tiene un conflicto con el archivo\n" +" %3%\n" +" de la instalación de\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "No es posible crear sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "romper %s ignorando algunas de sus dependencias" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "ignorar en general algunas dependencias" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"el elemento %1% instalado no pertenece a un repositorio de actualización de " +"distribuciones y se debe sustituir" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" +"el elemento %1% que se va a instalar no pertenece a un repositorio de " +"actualización de distribuciones" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "el elemento %1% instalado tiene una arquitectura inferior" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "el elemento %1% que se va a instalar tiene una arquitectura inferior" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problema con el elemento %1% instalado" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "peticiones en conflicto" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "algún problema de dependencia" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "nada proporciona el elemento %1% pedido" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "¿Ha habilitado todos los repositorios requeridos?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "el paquete %1% pedido no existe" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "petición no admitida" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "%1% es proporcionado por el sistema y no se puede borrar" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% no es instalable" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "nada proporciona %1%, que el elemento %2% instalado necesita" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" +"nada proporciona %1%, que el elemento %2% que se va a instalar necesita" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "no es posible instalar %1% y %2% conjuntamente" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"el elemento %1% instalado tiene un conflicto con %2%, que proporciona el " +"elemento %3% instalado" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"el elemento %1% instalado tiene un conflicto con %2%, que proporciona el " +"elemento %3% que se va a instalar" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"el elemento %1% que se va a instalar tiene un conflicto con %2%, que " +"proporciona el elemento %3% instalado" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"el elemento %1% que se va a instalar tiene un conflicto con %2%, que " +"proporciona el elemento %3% que se va a instalar" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"el elemento %1% instalado desplaza a %2%, proporcionado por el elemento %3% " +"instalado" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"el elemento %1% instalado desplaza a %2%, proporcionado por el elemento %3% " +"que se va a instalar" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"el elemento %1% que se va a instalar desplaza a %2%, proporcionado por el " +"elemento %3% instalado" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"el elemento %1% que se va a instalar desplaza a %2%, proporcionado por el " +"elemento %3% que se va a instalar" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"el elemento %1% instalado tiene un conflicto con %2% proporcionado por sí " +"mismo" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"el elemento %1% que se va a instalar tiene un conflicto con %2% " +"proporcionado por sí mismo" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"el elemento %1% instalado requiere %2%, pero no se puede satisfacer este " +"requisito" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"el elemento %1% que se va a instalar requiere %2%, pero no se puede " +"satisfacer este requisito" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "proveedores suprimidos: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"proveedores no instalables: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "proveedores no instalables: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% aún no se ha integrado por completo en %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Lo habitual es conservar el PTF y no instalar los parches de mantenimiento." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Eliminar el %1% instalado en este contexto también eliminará (¡no " +"reemplazará!) los paquetes de PTF incluidos." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"El PTF debe eliminarse llamando a '%1%'. Esto actualizará los paquetes de " +"PTF incluidos en lugar de eliminarlos." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Lo habitual es conservar el PTF o cancelar la acción." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "El elemento %1% instalado bloquea la acción deseada." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Lo habitual es conservar el PTF y cancelar la acción." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "elimine el bloqueo para permitir la eliminación de %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "no instalar %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "mantener %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "elimine el bloqueo para permitir la instalación de %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Esta petición dañará su sistema." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorar la advertencia de daño del sistema" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "no pedir que se instale un elemento solucionable que proporcione %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" +"no perdir que se supriman todos los elementos solucionables que proporcionen " +"%1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "no instalar la versión más reciente de %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "mantener %1% a pesar de que su arquitectura sea inferior" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "instalar %1% a pesar de que su arquitectura sea inferior" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "mantener el elemento %1% obsoleto" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "instalar el elemento %1% del repositorio excluido" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "instalar %1% aunque se haya retraído" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "permitir la instalación de PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "instalar %1% aunque esté en la lista negra" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "bajar de versión %1% a %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "cambio de arquitectura de %1% a %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"instalar %1% (con cambio de proveedor)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"instalar %1% del proveedor %2%\n" +" reemplazando %3% del proveedor %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "sustitución de %1% con %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "desinstalación de %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Ejecutando guiones postransacción" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Ejecutando guion %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Resultado de guion %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "La instalación se ha cancelado siguiendo las indicaciones." + +# include/nis_server/io.ycp:567 +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " ejecutado" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " error de ejecución" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s ya se ha ejecutado como %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " ejecución omitida mientras se cancela" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Error al enviar la notificación del mensaje de actualización." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nuevo mensaje de actualización" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Se ha recibido la señal: \"%1% (%2%)\". Para garantizar la coherencia del " +"sistema, no es posible cancelar una transacción de rpm en ejecución." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" +"Falló la ejecución de la transacción debido a los siguientes problemas:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM fallido: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Error al importar la clave pública %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Error al eliminar la clave pública %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "¡Cabecera del paquete sin firmar!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "¡Contenido del paquete sin firmar!" + +# +# modules/Mail.ycp:458 +# modules/Mail.ycp:554 +# modules/Mail.ycp:554 +# modules/Mail.ycp:563 +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Se han modificado los archivos de configuración para %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm ha guardado %s como %s, pero no es posible determinar la diferencia" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ha guardado %s como %s.\n" +"A continuación se presentan las primeras 25 líneas de diferencia:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm ha creado %s como %s, pero no es posible determinar la diferencia" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ha creado %s como %s.\n" +"A continuación se presentan las primeras 25 líneas de diferencia:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Salida de rpm adicional" + +# include/nis_server/io.ycp:582 +# include/backup/ui.ycp:1286 +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "creada copia de seguridad %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "La firma es correcta" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tipo de firma desconocido" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "La firma no cumple la verificación" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "La firma es correcta, pero la clave no es de confianza" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "La clave pública de firma no está disponible" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "El archivo no existe o no es posible comprobar la firma" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "El fichero no está firmado" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tipo dudoso %s para el byte %u de la suma de comprobación %s" + +# include/backup/ui.ycp:1661 +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "No es posible abrir el pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "No es posible abrir el conducto (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Cadena de consulta URL LDAP no válida" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Parámetro de consulta URL LDAP %s no válido" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "No es posible clonar el objeto URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Referencia de objeto de URL vacío no válida" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "No es posible analizar los componentes de URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historial:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "El esquema de URL no permite un elemento %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Componente %s no válido %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Componente %s no válido" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" +"El análisis de cadenas de consulta no es compatible con esta dirección URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "El esquema de URL es un componente obligatorio" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Esquema %s de URL no válido" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "El esquema de URL no permite un nombre de usuario" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "El esquema de URL no permite una contraseña" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "El esquema de URL requiere un componente host" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "El esquema de URL no permite un componente host" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Componente de host no válido %s" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "El esquema de URL no permite un puerto" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Componente de puerto no válido %s" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "El esquema URL requiere un nombre de vía" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "No se permiten vías relativas si existe una autoridad" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "La cadena cifrada incluye un byte nulo" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Carácter separador de división de conjunto de parámetros no válido" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Carácter separador de división de asignación de parámetros no válido" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Carácter separador de unión de conjunto de parámetros no válido" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "El comando ha terminado con el estado %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "La señal %d (%s) ha interrumpido el comando." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "El comando ha terminado con un error desconocido." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Se han proporcionado argumentos spawn no válidos." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "No es posible crear una tubería de control." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "No es posible aplicar chroot a %s (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "No es posible cambiar al directorio %s (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "No es posible cambiar al directorio %s en chroot %s (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "No es posible ejecutar %s (%s)." + +# clients/printconf_write.ycp:121 +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "No es posible hacer fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "No es posible ejecutar '%s', chdir falló (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "No es posible ejecutar '%s', falló chroot (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "No es posible ejecutar '%s', falló exec (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "No es posible ejecutar '%s', error inesperado." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Error al montar %s en %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Error al desmontar %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nombre de archivo incorrecto: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "No se ha abierto el medio al intentar realizar la acción %s." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "No se encuentra el archivo %s en el medio %s" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "No es posible escribir el archivo %s." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Medio no conectado" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Punto de conexión de medio incorrecto" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Error de inicio de descarga (curl) para %s" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Excepción de sistema %s en el medio %s." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "La vía %s del medio %s no es un archivo." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "La vía %s del medio %s no es un directorio." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Formato de URI incorrecto" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nombre de host vacío en URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Sistema de archivos vacío en URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destino vacío en URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Esquema de URI no admitido en %s." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "El medio no admite la operación" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Error de descarga (curl) para %s:\n" +"Código de error: %s\n" +"Mensaje de error: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Error al definir las opciones de descarga (curl) para %s:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "El origen de medios %s no incluye el medio deseado" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "El medio %s está en uso en otra instancia" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "No es posible expulsar ningún medio" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "No es posible expulsar el medio '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Se ha denegado el permiso para acceder a %s." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Se ha superado el tiempo de espera al acceder a %s." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "La descarga de datos ha excedido el tamaño esperado '%s 1' de '%s 2'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "La ubicación '%s' está momentáneamente inaccesible." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Hay un problema con el certificado SSL. Compruebe que la autoridad de " +"certificación (CA) es correcta para %s." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "No hay recursos libres disponibles para adjuntar medios." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Método de autenticación HTTP no compatible %s" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"(curl) Error de descarga para '%s':\n" +"Código de error: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"(curl) Error de descarga para '%s':\n" +"No se recibió una respuesta HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Sí" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "No" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Nota:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Advertencia:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Error:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "terminado" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "atención" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "error" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Advertencia: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Recuperando:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "iniciando" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "no encontrado" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "No hay ayuda disponible para este mensaje." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "no hay ayuda disponible para esta opción" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "mostrar todas las opciones" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "si" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "no" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Ejecutando el guion %%posttrans %1%" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Ejecutando guiones %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "¡El paquete no está firmado!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s no pertenece a un repositorio distupgrade" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s posee una arquitectura inferior" + +#~ msgid "problem with installed package %s" +#~ msgstr "se ha producido un problema con el paquete instalado %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "no hay nada que proporcione el elemento %s pedido" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "¿Ha habilitado todos los repositorios pedidos?" + +#~ msgid "package %s does not exist" +#~ msgstr "el paquete %s no existe" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s proviene del sistema y no se puede eliminar" + +#~ msgid "%s is not installable" +#~ msgstr "%s no es instalable" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "no hay nada que proporcione %s, necesario para %s" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#~ msgid "cannot install both %s and %s" +#~ msgstr "no es posible instalar ambos elementos: %s y %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s está en conflicto con %s proporcionado por %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s deja obsoleto %s, proporcionado por %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s instalado, deja obsoleto a %s proporcionado por %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "" +#~ "La solución %s está en conflicto con %s, proporcionada por ella misma" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s requiere %s, pero este requisito no se puede cumplir" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "eliminar bloqueo para permitir la desinstalación de %s" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#~ msgid "do not install %s" +#~ msgstr "no instalar %s" + +#~ msgid "keep %s" +#~ msgstr "mantener %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "eliminar bloqueo para permitir la instalación de %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "no preguntar si se debe instalar una solución que proporciona %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "" +#~ "no preguntar si se deben suprimir todas las soluciones que proporcionan %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "no instalar la versión mas reciente de %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "mantener %s a pesar de la arquitectura inferior" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "instalar %s a pesar de la arquitectura inferior" + +#~ msgid "keep obsolete %s" +#~ msgstr "mantener el antiguo %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "instalar %s desde el repositorio excluido" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "restablecer versión anterior de %s a %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "cambio en la arquitectura de %s a %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "instalar %s (con cambio de proveedor)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "reemplazo de %s con %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "desinstalación de %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "No es posible abrir el archivo de bloqueo: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Otro programa ya está ejecutando esta acción." + +#~ msgid "Hal Exception" +#~ msgstr "Excepción de hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Lo sentimos, pero esta versión de libzypp se ha construido sin " +#~ "compatibilidad con HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext no está conectado" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive no se ha iniciado" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume no se ha iniciado" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "No es posible crear la conexión dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: no es posible crear el contexto libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "libhal_set_dbus_connection: no es posible establecer la conexión dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "No es posible iniciar el contexto HAL -- ¿Es posible que hald no se esté " +#~ "ejecutando?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "No es una unidad de CD-ROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "No es posible iniciar los atributos de mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "No es posible establecer el atributo de mutex recursivo" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "No es posible iniciar mutex recursivo" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "No es posible adquirir el bloqueo de mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "No es posible liberar el bloqueo de mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Error al importar la clave pública desde el archivo %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Error al eliminar la clave pública %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "No se encuentra ningún dispositivo de bucle disponible para montar el " +#~ "archivo de imagen desde %s" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "generalmente ignorar algunas dependencias" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#~ msgid "do not forbid installation of %s" +#~ msgstr "no prohibir la instalación de %s" + +#~ msgid "do not keep %s installed" +#~ msgstr "no mantener instalado %s" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "تعذر حل التبعيات" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "No se puede crear la clave pública %s del anillo de claves %s al archivo " +#~ "%s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "" +#~ "Se intentó importar la clave inexistente %s en el anillo de claves %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "No se puede cambiar de directorio a '/' dentro del chroot (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "" +#~ "La inicialización de la descarga (Metalink curl) ha fallado para '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Error en la descarga (metalink curl) de '%s':\n" +#~ "Código de error: %s\n" +#~ "Mensaje de error: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Descarga interrumpida en %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Descarga interrumpida por el usuario" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Se ha producido un error al establecer las opciones de descarga (metalink " +#~ "curl) para '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Error al descargar %s desde %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia y Montenegro" + +#~ msgid "Unknown Distribution" +#~ msgstr "Distribución desconocida" + +#~ msgid "Timeout exceeded when access '%s'." +#~ msgstr "Se ha sobrepasado el tiempo de espera al acceder a '%s'." diff --git a/po/et.po b/po/et.po new file mode 100644 index 0000000..33bc46e --- /dev/null +++ b/po/et.po @@ -0,0 +1,5445 @@ +# translation of zypp.et.po to Estonian +# translation of +# Copyright (C) 2006 SUSE Linux Products GmbH. +# Estonian message file for YaST2 (@memory@). +# +# Ain Vagula , 2006, 2007, 2009. +msgid "" +msgstr "" +"Project-Id-Version: zypp.et\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2019-12-08 11:54+0000\n" +"Last-Translator: Jaanus Ojangu \n" +"Language-Team: Estonian \n" +"Language: et\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 3.6.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Tundmatu riik " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Kood puudub" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Araabia Ühendemiraadid" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua ja Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albaania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armeenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Hollandi Antillid" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktika" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentiina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Ameerika Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Austraalia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Ahvenamaa" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Aserbaidžaan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia ja Hertsegoviina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgia" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrein" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Boliivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasiilia" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahama" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutaan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet' saar" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Valgevene" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kookosesaared" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Kesk-Aafrika Vabariik" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Šveits" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Elevandiluurannik" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cooki saared" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Tšiili" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Hiina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa-Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Roheneemesaared" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Jõulusaar" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Küpros" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tšehhi" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Saksamaa" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Taani" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikaani Vabariik" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alžeeria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Eesti" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egiptus" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Lääne-Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Hispaania" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etioopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Soome" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandi saared (Malviinid)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikroneesia Föderatsioon" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Fääri saared" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Prantsusmaa" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Prantsuse emamaa" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Suurbritannia" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gruusia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Prantsuse Guajaana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Gröönimaa" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatoriaal-Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Kreeka" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Lõuna-Georgia ja Lõuna-Sandwichi saared" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heardi saar ja McDonaldi saared" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Horvaatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungari" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indoneesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Iirimaa" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Iisrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Manni saar 'Isle of Man'" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Briti India ookeani ala" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iraan" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Itaalia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordaania" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Jaapan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Keenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kõrgõzstan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodža" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komoorid" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts ja Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Põhja-Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Lõuna-Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuveit" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kaimanisaared" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kasahstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Liibanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint-Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri-Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Libeeria" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Leedu" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Läti" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Liibüa" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshalli saared" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedoonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Birma" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongoolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Põhja-Mariaani saared" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritaania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldiivid" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mehhiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaisia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mosambiik" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namiibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Uus-Kaledoonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolki saar" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Holland" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norra" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Uus-Meremaa" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omaan" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peruu" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Prantsuse Polüneesia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Paapua Uus-Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipiinid" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poola" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre ja Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto-Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestiina haldusterritoorium" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Belau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumeenia" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Venemaa Föderatsioon" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi Araabia" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Saalomoni saared" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seišellid" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudaan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Rootsi" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Saint-Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Sloveenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard ja Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakkia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra-Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San-Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somaalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome ja Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Süüria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Svaasimaa" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks ja Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tšaad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Prantsuse Lõunaalad" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tai" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Türkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tuneesia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Ida-Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Türgi" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad ja Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tansaania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Ühendriikide hajasaared" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Ameerika Ühendriigid" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Usbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Püha Tool (Vatikan)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent ja Grenadiinid" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Briti Neitsisaared" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "USA Neitsisaared" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis ja Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jeemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Lõuna-Aafrika Vabariik" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Sambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Varustab" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Eeltingimused" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Vajab" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "On vastuolus" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Aegub" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Soovitab" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Soovitused" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Parandused" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Lisandid" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Prooviti võtmehoidjasse %s importida olematu võtme %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Võtme import nurjus." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Võtme kustutamine nurjus." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Allkirjade faili %s ei leitud" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Tundmatu keel: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afari" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abhaasi" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Atšehi" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Akoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adõgee" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afroaasia (muu)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaani" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akani" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akadi" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albaania" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleuudi" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonkini keeled" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altai" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amhaari" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Vanainglise (ca. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apatši keeled" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Araabia" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramea" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragoni" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armeenia" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araukaani" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Tehis (muu)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawaki" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assami" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Astuuria" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Atapaski keeled" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Austraalia keeled" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avaari" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avesta" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Avadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aimaraa" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Aserbaidžaani" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke keeled" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Baškiiri" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Belutši" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Bali" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baski" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Balti (muu)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Bedža" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Valgevene" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengaali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berberi (muu)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhodžpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihaari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikoli" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Edo" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (muu)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnia" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Bradži" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretooni" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Bataki (Indoneesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Burjaadi" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugi" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgaaria" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birma" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blini" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Kado" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Kesk-Ameerika indiaani (muu)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Kariibi" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalaani" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukaasia (muu)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Sebu" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keldi (muu)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Tšamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Tšibtša" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tšetšeeni" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Tšagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Hiina" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Tšuugi" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Tšinuki žargoon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Tšokto" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Tšipevai" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Tšerokii" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Kirikuslaavi" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Tšuvaši" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Šaieeni" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Chamic keeled" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Kopti" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Korni" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsika" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreoolid ja Pidginid, inglise keeles (muu)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreoolid ja Pidginid, prantsuse päritolu (muu)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreoolid ja Pidginid, Portugali põhine (muu)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Krii" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krimmitatari" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreoolid ja Pidginid (muu)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kašuubi" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitic (muu)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tšehhi" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Taani" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargi" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dajaki" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delavari" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Orjaindiaani (atapaski)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Koeraribi-Karujärve" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Maldiivi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidian (muu)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Alamsorbi" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Keskhollandi (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Hollandi" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Djula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Ibibio" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Vanaegiptuse" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekadžuki" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Eelami" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inglise" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Keskinglise (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Eesti" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Eve" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Jaunde" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fangi" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Fääri" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fidži" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipiini" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Soome" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Soomeugri (muu)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Foni" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Prantsuse" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Keskprantsuse (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Vanaprantsuse (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Friisi" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulbe" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friuuli" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Gaa" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gajo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaja" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germaani (muu)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Gruusia" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Saksa" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Etioopia" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilberti" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaeli" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Iiri" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galeegi" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Mänksi" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Keskülemsaksa (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Vanaülemsaksa (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gooti" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Vanakreeka (kuni 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Kreeka, tänapäevane (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guaranii" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gudžarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gvitšini" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haiiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Havai" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Heebrea" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligainoni" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himatšali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Heti" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmongi" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri-Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Ülemsorbi" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ungari" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Ibani" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Ibo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandi" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuani jii" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Idžo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktituti" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue (oktsidentaal)" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (rahvusvaheline abikeele assotsiatsioon)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "India (muu)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indoneesia" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoeuroopa (muu)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Inguši" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Injupiaki" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraani (muu)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokeesi keeled" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Itaalia" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Jaava" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban - tehiskeel" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Jaapani" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Juudipärsia" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Juudiaraabia" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpaki" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabiili" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Katšini" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Kareni" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kašmiiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kaavi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kasahhi" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardi-tšerkessi" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan - aafrika keeled (muu)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmeri" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Saki" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuju" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Ruanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgiisi" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Mbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korea" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosrae" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karatšai-balkaari" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kruu" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Oraoni" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Ambo" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumõki" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdi" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladiino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Ladina" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Läti" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lesgi" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgi" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Leedu" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Letseburgi" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luisenjo" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya ja Tansaania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lušei" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedoonia" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madura" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Maršalli" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makassari" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malajalami" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maoori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesian - aasia keeled (muud)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malai" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Mokša" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandari" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Keskiiri (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mikmaki" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Mitmesugused keeled" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (muud)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagassi" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Malta" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Mandžu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo keeled" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohoogi" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldova" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongoli" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Mitu keelt" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda keeled" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Maskogi" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Miranda" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marvari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Maaja keeled" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Ersa" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahua" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Põhja-Ameerika indiaani" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Naapoli" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Lõunandebele" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Põhjandebele" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Alamsaksa" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa keeled" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Niasi" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-kordofaani (Muud)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niue" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Uusnorra" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norra (bokmål)" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Vanapõhjala" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norra" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Põhjasotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nuubia keeled" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Klassikaline nevari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Njandža" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Njamvesi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nkole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Njoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Provansi (pärast 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Odžibvei" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oria" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Oseidži" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osseedi" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Osmanitürgi (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomi keeled" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Paapua (muu)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinani" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Pandžabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Belau" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Vanapärsia (u. 600-400 eKr.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Pärsia" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipiini (muu)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Foiniikia" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Paali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Poola" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Poonpei" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugali" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Praakriti keeled" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Vanaprovansi (kuni 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Puštu" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Ketšua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Radžastani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotonga" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romaani (muu)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Retoromaani" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Mustlaskeel" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumeenia" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Vene" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandave" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Jakuudi" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Lõuna-Ameerika indiaani (muu)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salishani keeled" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaaria aramea" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbia" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sitsiilia" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Šoti" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Horvaadi" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Sölkupi" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semiidi (muu)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Vanaiiri (kuni 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Märgikeeled" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Šani" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singali" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siuu keeled" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Hiina-Tiibeti keel (Muud)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slaavi (muu)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovaki" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Sloveeni" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Lõunasaami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Põhjasaami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Saami keeled (muu)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule saami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari saami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Koltasaami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Šona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdi" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somaali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Lõunasotho" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Hispaania" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardi" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Sereri" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Niiluse-Sahara (muu)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Svaasi" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sunda" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumeri" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Suahiili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Rootsi" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Assüüria" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahiiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (muu)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamili" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatari" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Temne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetumi" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadžiki" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalogi" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tiibeti" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigree" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinja" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tivi" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingoni" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingiti" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tuareegi" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tonga saarestik)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Uusmelaneesia" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tsvaana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Türkmeeni" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi keeled" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Türgi" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altai (muu)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Tvii" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuva" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurdi" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugariti" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uiguuri" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukraina" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Määramata" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Usbeki" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnami" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Vadja" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakashani keeled" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Volamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Varai" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Vašo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Kõmri" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbi keeled" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Vallooni" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Volofi" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmõki" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Koosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Jao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Japi" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jidiš" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Joruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Jupiki keeled" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Sapoteegi" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Tšuangi" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Suulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Sooritatakse järgmised tegevused:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "ei vanane" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "aegunud: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "aegub: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(ei vanane)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(AEGUNUD)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(aegub 24h jooksul)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(aegub %d päevaga)" +msgstr[1] "(aegub %d päevaga)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "tundmatu" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "toetamata" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Tase 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Tase 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Tase 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Vajalik on täiendav kliendileping" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "vigane" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Kasutajatoe tase pole määramata" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Müüja ei paku tuge." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Probleemi tuvastamine, mis tähendab tehnilist abi, et pakkuda ühilduvuse " +"teavet, paigaldusabi, kasutustuge, töösoleva hoolduse ja põhiliste " +"tõrkeotsingute jaoks. Tase 1 tugi pole mõeldud toote defektide vigade " +"parandamiseks." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Probleemide eraldamine, mis tähendab tehnilist tuge, mis on loodud klientide " +"probleemide dubleerimiseks, probleemipiirkonna isoleerimiseks ja probleemide " +"lahendamiseks ei sisaldu tase 1 toes." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Probleemi lahendamine, mis tähendab tehnilist tuge, mis on loodud keerukate " +"probleemide lahendamiseks, rakendades tehnilisi lahendusi tuvastatud " +"tootevigade kõrvaldamiseks, mis on kindlaks tehtud 2. taseme toe abil." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Kasutajatoe saamiseks on vajalik täiendav kliendileping." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Tundmatu toe valik. Kirjeldus pole saadaval" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Süsteemihaldus on lukustatud rakendusega pid %d (%s).\n" +"Enne uuesti proovimist sulgege see rakendus." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Tundmatu ühilduvusstaatus '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Tundmatu 'match mode' '%s' struktuurile '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Vigane regulaaravaldis '%s': recomp vastas %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Vigane regulaaravaldis '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autoriseerimine on nõutav '%s' jaoks" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Külastage SUSE kliendikeskust, et kontrollida, kas teie registreering on " +"kehtiv ega ole aegunud." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Külastage kliendikeskust, et kontrollida, kas teie registreerimine on kehtiv " +"ja kas see pole aegunud." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Lisamispunkti loomine: lisamispunkti loomiseks ei leia kirjutatavat kataloogi" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Palun esmalt paigaldage 'Isof' pakett." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Metaandmete vahemälu kataloogi ei saa luua." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Viga lugemisel asukohast '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Pole võimalik luua %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Valitud metaandmeid ei leitud määratud URL-ilt" +msgstr[1] "Valitud metaandmeid ei leitud määratud URL-delt" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Hoidla puhverdamine nurjus (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Loodava repositooriumi '%s' vahemälu" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Ei saa luua vahemälu kohas %s - puuduvad kirjutamise õigused." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Käsitlemata tarkvarahoidla tüüp" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Lisatakse repositoorium '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Vigane repo faili nimi '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Faili '%s' avamine kirjutamiseks nurjus." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Tundmatu viga '%s' lugemisel" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Ei saa lugeda repo kataloogi '%1%': Juurdepääs on keelatud" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Kataloogi '%s' lugemine nurjus" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Ei saa lugeda repo faili '%1%': Juurdepääs on keelatud" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Eemaldatakse hoidla '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Ei suuda tuvastada, kus hoidla asub." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Faili '%s' ei saa kustutada" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Ei suuda tuvastada, kus teenus asub." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Tundmatu teenus '%1%': Orvustunud teenuse repost '%2%' eemaldamine" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Hoidlat alias ei saa alata punktiga." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Teenuse alias ei saa alata täpiga." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Kas jätkata?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Repositoorium %1% ei defineeri täiendavat 'gpgkey=' URLi." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Otsitakse gpg võtme ID-d %1% repositooriumis %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Otsitakse gpg võtme ID-d %1% vahemälus %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Puudub nõutav argument '%s'." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Üks või mõlemad '%s' või '%s' atribuudid on nõutavad." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Allkirja võrdlemine nurjus" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Pakatt %s tundub olevat transpordi ajal rikutud. Kas te soovit proovida " +"uuesti vastu võtta?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Paketi %s saatmine nurjus. Kas proovida uuesti saata?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm kontrollimine nurjus." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm nurjus." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Teenuse lisaprogramm ei toeta atribuudi muutmist." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Ei saa faili '%s' tarkvarahoidlast '%s' hankida" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Repositooriumis ei ole URLi." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Faili %1%\n" +" paketist\n" +" %2%\n" +" on konfliktis failiga paketist\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Fail %1%\n" +" paketist\n" +" %2%\n" +" on vastuolus failiga paigaldusest\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Fail %1%\n" +" paigaldusest\n" +" %2%\n" +" on konfliktis failiga paketist\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Fail %1%\n" +" paigaldusest\n" +" %2%\n" +" on vastuolus failiga paigaldusest\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Fail %1%\n" +" paketist\n" +" %2%\n" +" on vastuolus failiga\n" +" %3%\n" +" paketist\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Fail %1%\n" +" paketist\n" +" %2%\n" +" on vastuolus failiga\n" +" %3%\n" +" paigaldusest\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Fail %1%\n" +" paigaldusest\n" +" %2%\n" +" on konfliktis failiga\n" +" %3%\n" +" paketist\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Fail %1%\n" +" paigaldusest\n" +" %2%\n" +" on vastuolus failiga\n" +" %3%\n" +" paigaldusest\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Faili ei sa luua sat-pooli." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "võib katki teha %s ignoneerides mõnda selle sõltuvust" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "üldiselt ignoreeritakse mõnda sõltuvust" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "vastuolulised päringud" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "mingi sõltuvuse probleem" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "mittetoetaud taotlus" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "kustutatud pakkujad: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"kättesaamatud varustajad: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "kättesaamatud varustajad: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "See päring rikub teie süsteemi!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignoreerige katkise süsteemi hoiatust" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "paigalda %1%, ehkki see on tagasi tõmmatud" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "lubage paigaldada PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "paigaldage %1%, kuigi see on mustas nimekirjas" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Paigaldamine on vastavalt juhistele katkestatud." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " käivitatud" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " käivitamine nurjus" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s juba käivitatud kui %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " käivitamine jäeti katkestamise käigus vahele" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Viga uuendusteate teavituse saatmisel." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Uus uuendusteade" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM nurjus: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Avaliku võtme %1% import nurjus" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Avaliku võtme %1% eemaldamine nurjus" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Muudetud seadistuste fail %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm salvestati %s nimega %s, kuid erinevust oli võimatu tuvastada" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm on salvestatud %s kui %s.\n" +"Siin on esimesed 25 erinevuse rida:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm loodi %s nimega %s, aga oli võimatu leida erinevusi" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm loodi %s nimega %s.\n" +"Siin toodud esimesed 25 rida erinevusi:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Täiendav rpm-i väljund" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "loodi varukoopia %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Allkiri on korras" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tundmatu allkirja tüüp" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Allkirja ei võrrelda" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Allkiri on õige aga võti ei ole usaldatav" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Allkirjade avalik võti pole saadaval" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Faili pole olemas või allkirja pole võimalik kontrollida" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Fail on allkirjastamata" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Kahtlane tüüp '%s' %u baitide kontrollsummale '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Ei saanud avada preudoterminali 'pty' (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Ei saa avada toru 'pipe' (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Vigane LDAP URL-i päringu kirje" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Vigane LDAP URL-i päringu parameeter '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Pole võimalik kloonida Url objekti" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Vigane tühja Url objekti referents" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Ei ole võimalik uurida Url komponente" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Ajalugu:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "URL kuju ei luba %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Vigane %s komponent '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Vigane %s komponent" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Selle URL-i puhul ei toetata päringu kirje uurimist" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL kuju on nõutav komponent" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Vigane Url kuju '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url kuju ei võimalda kasutajanime" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url kuju ei võimalda salasõna" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url kuju nõuab arvutinime komponenti" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url kuju ei võimalda arvutinime komponenti" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Vigane host komponent '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url kuju ei võimalda porti" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Vigane pordi komponent '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url kuju nõuab teekonna nime" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Suhteline tee pole lubatud, kui autoriseerimine on olemas" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Krüpteeritud rida sisaldab Nul baiti" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Vale parameetri reastuse jaotuse eraldusmärk" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Vigane parameeter kaardijaotuse eraldusmärk" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Vigane parameetrimassiivi liitumismärk" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Käsk lõpetati olekuga %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Käsk lõpetati signaaliga %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Käsk lõpetas tundmatu veaga." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Ei saa chroot läbi viia '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Ei saa kataloogi vahetada 'chdir '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Ei õnnestunud 'chdir' '%s' 'chroot' sees '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Ei saa käivitada '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "'fork' ei õnnestu (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Haakimine %s asukohas %s nurjus" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Lahtihaakimine %s nurjus" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Vigane faili nimi: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Toimingu '%s' sooritamisel meedium ei avanenud." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Faili '%s' ei leitud meediumil '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Faili '%s' ei saa kirjutada." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Meedium ei ole lisatud" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Vigane meedia lisamispunkt" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "'%s' allalaadimise (curl) initaliseerimine nurjus" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Süsteemi erand „%s” andmekandjal „%s”." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Tee sihtkohas '%s' andmekandjal '%s' ei ole fail." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Tee '%s' meediumil '%s' pole kataloog." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Vigane URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Tühi masina nimi URI-s" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Tühi failisüsteem on URl-l" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Tühi sihtkoht URl-s" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Mittetoetatud URl skeem '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "See tegevus ei ole meediumi poolt toetatud" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"'%s' allalaadimise (curl) viga:\n" +"Vea kood: %s\n" +"Veateade: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "'%s' allalaadimise valikute määramisel ilmnes viga:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Meediumi allikas '%s' ei sisalda soovitud andmekandjat" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Meedium '%s' on kasutuses teise kasutaja poolt" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Ühtegi andmekandjat ei saa väljutada" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Ei saa väljutada meediumi '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Ligipääs '%s' on keelatud." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "'%s juurdepääsu ajalimiit on ületatud." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Allalaaditud andmed ületasid faili suurust '%s' '%s' -st." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Asukoht '%s' on ajutiselt kättesaamatu." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" SSL-i probleem sertifikaadiga, kontolli, et SK sertifikaat sobiks '%s' " +"jaoks." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Mittetoetatud HTTP autoriseerimise meetod '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Jah" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ei" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Hoiatus" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Viga" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "valmis" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "viga" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Hoiatus" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +#, fuzzy +msgid "Retrieving:" +msgstr "Eemaldamine" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Alustamine..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Ei leitud" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "jah" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ei" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Käib %%posttrans script '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Käib %posttrans scripts" + +#~ msgid "Package is not signed!" +#~ msgstr "Pakett ei ole allkirjastatud!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s ei kuulu distupgrade tarkvarahoidlasse" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s on halvema arhitektuuriga" + +#~ msgid "problem with installed package %s" +#~ msgstr "Paigaldatud paketiga %s on probleem" + +#~ msgid "nothing provides requested %s" +#~ msgstr "kuskil ei pakuta nõutud %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Kas olete lubanud kõik taotletud hoidlad?" + +#~ msgid "package %s does not exist" +#~ msgstr "paketti %s pole olemas" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s on süsteemi poolt seatud ja ei ole eemaldatav" + +#~ msgid "%s is not installable" +#~ msgstr "%s pole paigaldatav" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "miski ei paku %s vajalikku %s -le" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "Ei saa paigaldada mõlemat %s ja %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s on konfliktis %s -ga hangituna %s poolt" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s aegub %s pakkujalt %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "paigaldatud %s aegub %s pakkujalt %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "lahendatav %s on vastuolus enda poolt pakutuga %s" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s nõuab %s, kuid seda nõuet ei saa täita" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "eemalda lukk, et lubada %s eemaldamist" + +#~ msgid "do not install %s" +#~ msgstr "ära paigalda %s" + +#~ msgid "keep %s" +#~ msgstr "jäta alles %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "eemalda lukustus %s paigalduse lubamiseks" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "ärge paluge paigaldada pakutavaid sõltuvuste lahendusi %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "ärge paluge kustutada kõiki pakutud sõltuvuste lahendusi %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "ära paigalda %s uusimat versiooni" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "jäta alles %s hoolimata halvemast arhitektuurist" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "paigaldage %s vaatamata madalamale arhitektuurile" + +#~ msgid "keep obsolete %s" +#~ msgstr "jäta aegunud %s alles" + +#~ msgid "install %s from excluded repository" +#~ msgstr "paigaldage %s välistatud hoidlast" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "tagasiviimine %s tasemele %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "arhitektuuri muutus %s teisele %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "paigalda %s (koos tarnija vahetusega)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "%s vahetamine %s vastu" + +#~ msgid "deinstallation of %s" +#~ msgstr "%s eemaldamine" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Ei saa avada lukustusfaili: %s" + +#~ msgid "Hal Exception" +#~ msgstr "Hal erand" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext pole ühendatud" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive pole initsialiseeritud" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume pole initsialiseeritud" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "Ainult minu loodud ühenduse korral" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Pole CDROM-seade" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Avaliku võtme %s eemaldamine nurjus: %s" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "paigaldamata" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "%s - %s ei saa avada\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia ja Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Tundmatu nimekirja säte" diff --git a/po/fa.po b/po/fa.po new file mode 100644 index 0000000..e3b43a3 --- /dev/null +++ b/po/fa.po @@ -0,0 +1,5467 @@ +# Mohammad Rezaei Seresht , 2014. +# hayyan , 2016. +msgid "" +msgstr "" +"Project-Id-Version: opensuse-i 18n\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2023-03-03 15:14+0000\n" +"Last-Translator: Mohammad Rezaei Seresht \n" +"Language-Team: Persian \n" +"Language: fa\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: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "کشور ناشناخته: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "بدون کد" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "آندورا" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "امارات متحده ی عربی" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "افغانستان" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "آنتیگوا و باربودا" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "آنگویلا" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "آلبانی" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "ارمنستان" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "آنتیل هلند" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "آنگولا" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "قاره قطب جنوب" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "آرژانتین" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "ساموآ" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "اتریش" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "استرالیا" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "اروبا" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "جزایر آلند" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "آذربایجان" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "بوسنی و هرزگوین" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "باربادوس" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "بنگلادش" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "بلژیک" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "بورکینا فاسو" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "بلغارستان" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "بحرین" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "بروندی" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "بنین" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "برمودا" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "برونئی دارالسلام" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "بولیوی" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "برزیل" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "باهاماس" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "بوتان" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "جزیره بووت" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "بوتسوانا" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "بلاروس" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "بلیز" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "کانادا" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "جزایر کوکوس (کیلینگ)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "کونگو" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "جمهوجمهوری آفریقای مرکزی" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "سوئیس" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "ساحل عاج" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "جزایر کوک" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "شیلی" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "کامرون" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "چین" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "کلمبیا" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "کاستاریکا" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "کوبا" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "کیپ ورد" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "جزیره ی کریسمس" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "قبرس" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "جمهوری چک" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "آلمان" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "جیبوتی" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "دانمارک" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "دومینیکا" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "جمهوری دومینیکن" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "الجزایر" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "اکوادر" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "استونی" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "مصر" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "صحرای غربی" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "اریتره" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "اسپانیا" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "اتیوپی" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "فنلاند" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "فیجی" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "جزایر فالکلند (مالویناس)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "ایالات فدرال میکرونزی" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "جزایر فارو" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "فرانسه" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "شهری فرانسه" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "گابن" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "انگلستان" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "گرانادا" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "گرجستان" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "گویان فرانسه" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "گرنزی" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "غنا" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "جبل الطارق" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "گرینلند" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "گامبیا" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "گینه" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "جزیره گوادلوپ" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "گینه استوایی" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "یونان" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "جورجیای جنوبی و جزایر ساندویچ جنوبی" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "گواتمالا" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "گوام" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "گینه بیسائو" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "گویان" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "هنگ کنگ" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "جزیره هرد و جزایر مک دونالد" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "هندوراس" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "کرواسی" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "هائیتی" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "مجارستان" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "اندونزی" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "ایرلند" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "اسرائیل" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "جزیره ی من" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "هند" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "قلمرو بریتانیا در اقیانوس هند" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "عراق" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "ایران" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "ایسلند" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "ایتالیا" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "جرسی" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "جامائیکا" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "اردن" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "ژاپن" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "کنیا" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "قرقیزستان" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "کلمبیا" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "کیریباتی" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "کومور" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "سنت کیتس و نویس" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "کره ی شمالی" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "کره ی جنوبی" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "کویت" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "جزایر کیمن" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "قزاقستان" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "جمهوری دموکراتیک خلق لائوس" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "لبنان" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "سنت لوسیا" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "لیختن اشتاین" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "سریلانکا" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "لیبریا" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "لسوتو" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "لیتوانی" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "لوکزامبورگ" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "لتونی" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "لیبی" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "مراکش" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "موناکو" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "مولدووا" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "مونته نگرو" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "سنت مارتین" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "ماداگاسکار" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "جزایر مارشال" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "مقدونیه" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "مالی" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "میانمار" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "مغولستان" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "ماکائو" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "جزایر ماریانای شمالی" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "مارتینیک" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "موریتانی" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "مونتسرات" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "مالت" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "موریس" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "مالدیو" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "مالاوی" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "مکزیک" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "مالزی" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "موزامبیک" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "نامیبیا" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "کالدونیای جدید" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "نیجر" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "جزیره نورفولک" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "نیجریه" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "نیکاراگوئه" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "هلند" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "نروژ" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "نپال" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "نائورو" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "نیوئه" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "نیوزیلند" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "عمان" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "پاناما" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "پرو" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "پلینزی فرانسه" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "پاپوآ گینه نو" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "فیلیپین" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "پاکستان" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "لهستان" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "سنت پیر و ماژلان" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "پیتکرن" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "پورتوریکو" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "سرزمین فلسطین" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "پرتغال" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "پالائو" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "پاراگوئه" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "قطر" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "رئونیون" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "رومانی" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "صربستان" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "روسیه" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "رواندا" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "عربستان سعودی" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "جزایر سلیمان" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "سیشل" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "سودان" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "سوئد" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "سنگاپور" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "سنت هلن" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "اسلوونی" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "سوالبارد و یان ماین" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "اسلواکی" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "سیرالئون" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "سان مارینو" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "سنگال" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "سومالی" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "سورینام" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "سائوتومه و پرینسیپ" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "السالوادور" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "سوریه" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "سوازیلند" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "جزایر تورکس و کایکوس" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "چاد" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "سرزمین های جنوبی فرانسه" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "توگو" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "تایلند" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "تاجیکستان" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "توکلائو" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "ترکمنستان" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "تونس" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "تونگا" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "شرق تیمور" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "ترکیه" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ترینیداد و توباگو" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "تووالو" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "تایوان" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "تانزانیا" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "اوکراین" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "اوگاندا" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "جزایر کوچک حاشیه های ایالات متحده" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "ایالات متحده" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "اوروگوئه" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "ازبکستان" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "واتیکان" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "سنت وینسنت و گرنادینها" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "ونزوئلا" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "جزایر ویرجین بریتانیا" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "جزایر ویرجین ایالات متحده." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "ویتنام" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "وانواتو" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "والیس و فوتونا" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "ساموآ" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "یمن" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "مایوت" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "آفریقای جنوبی" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "زامبیا" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "زیمباوه" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "ارائه میدهد" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "از پیش نیاز دارد" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "نیاز دارد" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "مغایر است با" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "منسوخ میکند" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "توصیه میکند" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "پیشنهاد میکند" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "بالا میبرد" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "تکمیل میکند" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "برای وارد کردن کلید ناموجود %s در دسته کلید %s تلاش شد" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "ناموفق در وارد کردن کلید." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "در حذف کلید ناموفق بود." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "پرونده ی امضای %s یافت نشد" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "زبان ناشناخته: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "افر" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "آبخازیا" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "آچه ای" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "آشولی" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "دانگمه" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "آدیغی" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "آفریقایی-آسیایی (دیگر)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "آفریهیلی" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "آفریکانس" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "آینو" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "آکانی" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "اکدی" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "آلبانیایی" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "اینوپیات" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "زبان‌های آلگونکویان" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "آلتای جنوبی" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "امهری" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "انگلیسی، قدیمی (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "زبانهای آپاچی" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "عربی" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "آرماییک" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "آراگونی" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "ارمنی" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "آراکانیان" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "آراپاهو" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "ساختگی (دیگر)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "آراواک" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "آسامی" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "آستوری" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "زبانهای آتاباسکی" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "زبانهای استرالیایی" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "آواری" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "اوستایی" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "اودهی" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "آیمارا" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "آذربایجانی" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "باندا" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "زبانهای بامیلیکی" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "باشقیری" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "بلوچی" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "بامبارا" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "بالی" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "باسکی" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "باسا" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "بالتیک (دیگر)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "بژایی" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "بلاروسی" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "بمبایی" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "بنگالی" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "بربر (دیگر)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "بوجپوری" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "بیهاری" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "بیکلی" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "بینی" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "بسلامایی" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "سیکسیکایی" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "بانتو (دیگر)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "بوسنیایی" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "براج" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "برتون" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "باتاک (اندونزی)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "بوریاتی" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "بوگینی" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "بلغاری" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "برمهایی" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "بلینی" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "کادو" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "هندی آمریکای مرکزی (دیگر)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "کاریبی" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "کاتالان" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "قفقازی (دیگر)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "سبویی" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "سلتیکی (دیگر)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "چامورو" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "چیبچا" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "چچن" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "جغتایی" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "چینی" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "چوکیسی" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "ماری" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "شینوک" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "چوکتاو" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "چیپواین" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "چروکی" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "کلیسای اسلاوی" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "چوواشی" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "شاینی" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "زبانهای چامیک" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "قبطی" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "کورنیش" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "کورسی" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "کرئولس و پیجینز، بر پایه ی انگلیسی (دیگر)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "کرئولس و پیجینز، بر پایه ی فرانسوی (دیگر)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "کرئولس و پیجینز، بر پایه ی پرتغالی (دیگر)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "کری" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "کریمه تاتار" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "کرئولس و پیجینز" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "کاشوبی" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "کوشی (دیگر)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "چکی" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "داکوتایی" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "دانمارکى" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "دارگوا" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "دایاک" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "دلاویر" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "برده (آتاباسکی)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "داگریب" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "دینکا" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "دیوهی" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "دوگری" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "دراویدی (دیگر)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "صربی پایین" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "دوآلایی" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "هلندی، میانی (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "هلندی" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "دیولا" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "دزونگخا" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "افیک" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "مصری (باستانی)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "اکاجوک" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "ایلامی" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "انگلیسی" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "انگلیسی، وسطی (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "اسپرانتو" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "استونیایی" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "اوه ای" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "اووندو" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "فانگ" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "فاروئی" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "فانتی" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "فیجی" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "فیلیپینی" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "فنلاندی" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "فینو-اوگریان (دیگر)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "فن" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "فرانسوی" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "فرانسوی، وسطی (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "فرانسوی، قدیمی (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "فریزی" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "فولا" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "فریولی" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "گا" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "گایو" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "بایا" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "ژرمنی (دیگر)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "گرجی" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "آلمانی" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "گیز" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "کیریباتی" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "زبان بومی اسکاتلندی" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "ایرلندی" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "گالیسی" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "مانی" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "آلمانی، میانه ی بالایی (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "آلمانی، قدیمی بالایی (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "گندی" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "گورونتالو" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "گوتیک" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "گربو" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "یونانی، باستانی (تا 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "یونانی، مدرن (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "گوارانی" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "گجراتی" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "جویشن" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "هایدا" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "هائیتی" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "هوسا" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "زبان هاوایی" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "عبری" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "هررو" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "هیلیگاینون" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "هیماچالی" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "هندی" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "هیتی" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "همانگ" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "هیری موتو" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "صربی بالا" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "مجارستانی" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "هاپا" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "ایبان" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "ایگبو" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "ایسلندی" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ایدو" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "سیچوان یی" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ایجو" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "اینوکتیتوت" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "ایلوکو" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "اینترلینگوا" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "هندو (دیگر)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "اندونزیایی" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "هندو-اروپایی (دیگر)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "اینگوش" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "اینوپیاک" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "ایرانی (دیگر)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "زبانهای ایروکویان" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "ایتالیایی" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "جاوه ای" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "لژبان" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "ژاپنی" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "یهودی-فارسی" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "یهودی-عربی" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "کارا-کالپاک" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "قبایلی" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "کاچینی" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "کالالیسوت" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "کامبا" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "کانادا" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "کارن" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "کشمیری" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "کنوری" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "کاوی" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "قزاقی" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "کاباردیان" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "خاصی" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "خویسان (دیگر)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "خمری" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "ختنی" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "کیکویو" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "کینیارواندایی" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "قرقیزی" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "کیمبوندو" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "کونکانی" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "کومی" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "کونگویی" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "کره ای" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "کوسرائی" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "کپله ای" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "قرهچای و بالکار" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "کرو" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "کوروخ" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "کوانیاما" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "قموقی" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "کردی" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "کونته ای" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "لادینو" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "لندا" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "لامبا" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "لائو" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "لاتین" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "لتونی" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "لزگی" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "لیمبورگان" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "لینگالا" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "لیتوانیایی" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "مونگویی" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "لوزی" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "لوکزامبورگی" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "لوبا-لولوا" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "لوبا-کاتانگا" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "گاندایی" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "لوییزنو" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "لوندا" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "لو (کنیا و تانزانیا)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "لوشای" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "مقدونی" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "مادورس" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "ماگهی" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "مارشالی" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "میتهیلی" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "ماکاسار" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "مالایایی" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "ماندینگو" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "آسترونزی (دیگر)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "مراتی" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "ماسایی" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "مالایا" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "موکشا" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "ماندار" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "منده" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "ایرلندی، وسطی (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "مینغکاباو" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "زبانهای متفرقه" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "مونی-خمری (دیگر)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "ماداگاسکاری" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "مالتی" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "مانچو" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "مانیپوری" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "زبانهای مانوبو" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "موهاک" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "مولداویایی" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "مغولی" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "موسی" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "چندین زبانه" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "زبانهای موندا" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "کریکی" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "میراندی" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "مارواری" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "زبانهای مایان" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "ارزیا" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "ناهواتل" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "هندی امریکای شمالی" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "ناپولی" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "ناواهو" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "اندهبله ای، جنوبی" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "اندهبله ای، شمالی" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "اندونگا" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "آلمانی سفلا" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "نپالی" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "نپال بهاسایی" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "نیاس" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "نیجر-کنگویی" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "نیویان" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "نروژی نینورسک" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "نروژی بوکمال" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "نوقایی" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "نورس، قدیمی" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "نروژی" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "شمالی سوتو" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "زبانهای نوبیایی" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "نواری کلاسیک" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "چیچوا" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "نیاموزی" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "نیانکولی" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "نیورو" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "انزیمایی" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "اکسیتان (بعد از 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "اوجیبوا" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "اوریا" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "اورومو" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "اوسیج" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "اوسته ای" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "ترکی، اوتامان (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "زبانهای اوتامیایی" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "پاپوآ (دیگر)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "پانگاسینانی" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "پهلوی" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "پامپانگا" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "پنجابی" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "پاپیامنتو" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "پالائویی" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "فارسی، قدیمی (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "فارسی" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "فیلیپینی (دیگر)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "فنیقی" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "پالی" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "لهستانی" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "پنپه ای" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "پرتغالی" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "زبانهای پراکریت" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "پرووونسال، قدیمی (تا 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "پشتو" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "کچوا" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "راجستانی" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "رپنویی" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "راروتونگا" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "رومی (دیگر)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "ریتو-رومانی" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "کولی" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "رومانیایی" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "روندیایی" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "روسی" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "سنداوی" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "سانگو" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "یاقوتی" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "هندی امریکای شمالی (دیگر)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "زبانهای سالیشان" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "سامری آرامی" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "سانسکریت" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "ساساک" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "سانتالی" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "صربی" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "سیسیلی" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "اسکاتلندی" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "کرواتی" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "سلکوپی" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "سامی (دیگر)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "ایرلندی، قدیمی (تا 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "زبانهای امضایی" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "شان" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "سیدامو" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "سینهالی" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "زبانهای سیوآن" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "چینی-تبتی (دیگر)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "اسلاوی (دیگر)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "اسلواکی" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "اسلونیایی" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "سامی جنوبی" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "سامی شمالی" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "زبانهای سامی (دیگر)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "لوله سامی" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "ایناری سامی" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "ساموایی" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "سامی اسکولت" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "شونا" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "سندی" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "سونینکه" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "سغدی" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "سومالی" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "سونغایی" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "سوتو، جنوبی" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "اسپانیایی" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "ساردنی" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "سرر" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "نیلو-ساهاران (دیگر)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "سواتی" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "سوکوما" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "ساندانس" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "سوسو" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "سومری" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "سواحیلی" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "سوئدی" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "سریانی" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "زبان تاهیتی" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "تای (دیگر)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "تامیل" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "تاتار" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "تلوگو" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "تیمنه ای" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "ترنو" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "تتوم" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "تاجیکی" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "تاگالوگ" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "تایلندی" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "تبتی" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "تیگر" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "تیگرینیا" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "تیو" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "کلینگون" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "تلینگیتی" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "طوارقی" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "تونگا (نیاسا)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "تونگا (جزایر تونگا)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "توک پیسین" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "سیمیشان" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "تسوانا" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "سونگا" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "ترکمن" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "تومبوکایی" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "زبانهای توپیایی" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "ترکی" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "آلتاییک (دیگر)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "توی" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "تووینیایی" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "ادمورت" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "اوگاریتی" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "اویغور" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "اوکراینی" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "آمباندو" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "نا معین" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "اردو" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "ازبکی" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "وای" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "وندا" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "ویتنامی" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "ولاپوک" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "وتیک" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "زبانهای واکاشان" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "والامو" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "وارای" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "وشوو" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "ولز" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "زبانهای سربی" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "والون" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "ولوف" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "کالمیک" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "خوزا" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "یائو" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "یاپیزی" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "ییدیش" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "یوروبا" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "زبانهای یوپیک" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "زاپوتکی" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "زناگا" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "ژوانگ" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "زند" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "زولو" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "زونی" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "این اعمال انجام خواهند شد:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "منقضی نمیشود" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "منقضی شده: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "تاریخ انقضا: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(منقضی نمیشود)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(منقضی شده است)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(در 24 ساعت منقضی میشود)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(در %d روز منقضی می شود)" +msgstr[1] "(در %d روز دیگر منقضی می شود)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "ناشناخته" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "پشتیبانی نشده" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "سطح 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "سطح 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "سطح 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "قرارداد اضافی مشتری نیاز است" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "نامعتبر" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "سطح پشتیبانی تعیین نشده است" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "فروشنده پشتیبانی ارائه نمیدهد." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"تعیین مشکل، که به معنای پشتیبانی تخصصی جهت مهیا کردن اطلاعات سازگاری، کمک در " +"نصب، پشتیبانی در استفاده، نگهداری در دست اقدام و عیب یابی پایه ای است. " +"پشتیبانی سطح 1 برای ترمیم خطاهای نقض محصول در نظر گرفته نشده است." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"انزوای مشکل، که به معنای پشتیبانی تخصصی جهت مشابه سازی مشکلات مشتری، انزوای " +"مکان مشکل و مهیا سازی روش حل برای مشکلاتی است که توسط پشتیبانی سطح 1 رفع " +"نشده است، طراحی شده است." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"روش حل مشکل، که به معنای پشتیبانی تخصصی طراحی شده جهت حل مشکلات پیچیده به " +"وسیله ی جذب مهندسی در حل نقص های محصول که توسط پشتیبانی سطح 2 شناسایی شده " +"است." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "یک قرارداد اضافی مشتری برای دریافت پشتیبانی نیاز است." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "اختیار پشتیبانی ناشناخته. تعاریف در دسترس نیستند" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"مدیریت سیستم توسط نرم افزار با pid %d (%s) قفل شده است.\n" +"این نرم افزار را قبل از تلاش مجدد ببندید." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "حالت تطابق ناشناخته '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "حالت تطابق ناشناخته '%s' برای الگوی '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "عبارت عادی نامعتبر '%s': regcompبازگرداند %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "عبارت عادی نامعتبر '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "احراز هویت برای '%s' مورد نیاز است" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "دوباره تلاش خواهد کرد..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "تسلیم شدن پس از %1% تلاش." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"برای بررسی اینکه آیا ثبت نام شما معتبر است و منقضی نشده است، به مرکز مشتریان " +"SUSE مراجعه کنید." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"مرکز مشتریان Novell را برای بررسی اینکه ثبت نام شما معتبر است و منقضی نشده " +"است را مشاهده کنید." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"ساخت نقطه ی اتصال: نمیتوان یک فهرست قابل نوشتن را برای ساخت نقطه ی اتصال یافت" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "لطفا ابتدا بسته ی 'lsof' را نصب کنید." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "نمیتوان فهرست کش شبه داده را ساخت." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "خطا در تلاش برای خواندن از '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "نمیتوان %s را ساخت" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "شبه داده ی معتبر در آدرس تعیین شده یافت نشد" +msgstr[1] "شبه داده ی معتبر در آدرس های تعیین شده یافت نشد" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "ناموفق در کش مخزن (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "در حال ساخت کش مخزن '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "نمیتوان کش را در %s ساخت - دسترسی نوشتن نیست." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "نوع مخزن کنترل نشده" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "در حال اضافه کردن مخزن '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "نام پرونده ی مخزن نامعتبر در '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "نمیتوان پرونده ی '%s' را برای نوشتن باز کرد." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "خطای ناشناس در خواندن از '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "نمیتوان فهرست مخزن '%1%' را خواند: دسترسی غیرمجاز است" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "ناموفق در خواندن مسیر '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "نمیتوان پرونده ی مخزن '%1%' را خواند: دسترسی غیرمجاز است" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "در حال حذف مخزن '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "نمیتوان کشف کرد که مخزن در کجا ذخیره شده است." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "'%s' را نمیتوان حذف کرد" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "نمیتوان کشف کرد سرویس در کجا ذخیره شده است." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "سرویس ناشناخته '%1%': در حال حذف مخزن سرویس جدا افتاده '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "نام مستعار مخزن نمیتواند با نقطه شروع شود." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "نام مستعار سرویس نمیتواند با نقطه شروع شود." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "مخزن %1% URL های اضافی 'gpgkey=' را تعریف نمی کند." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "در جستجوی شناسه کلید gpg %1% در مخزن %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "در جستجوی کلید gpg %1% در کش %2% ." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "صفت '%s' مفقود است." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "یک یا جفت صفتهای '%s' یا '%s' نیاز است." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "تایید امضا ناموفق بود" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"بسته ی %s ظاهرا در هنگام انتقال خراب شده است. آیا میخواهید دریافت را مجددا " +"امتحان کنید؟" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"در مهیا کردن بسته ی %s ناموفق بود. آیا میخواهید دریافت را مجددا امتحان کنید؟" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "بررسی applydeltarpm ناموفق بود." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm ناموفق بود." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "افزونه ی سرویس از تغییر صفت پشتیبانی نمیکند." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "نمیتوان پرونده ی '%s' از مخزن '%s' را مهیا کرد" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "هیچ آدرسی در مخزن نیست." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "محیط مورد انتظار %1%/%2% شناسایی شده توسط فایل \"%3%\" با محتوا:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"پرونده ی %1%\n" +" از بسته ی \n" +" %2%\n" +" متداخل است با پرونده ای از بسته ی\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"پرونده ی %1%\n" +" از بسته ی\n" +" %2%\n" +" متداخل است با پرونده ای از نصب\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"پرونده ی %1%\n" +" از نصب\n" +" %2%\n" +" متداخل است با پرونده ای از بسته ی\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"پرونده ی %1%\n" +" از نصب\n" +" %2%\n" +" متداخل است با پرونده ای از نصب\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"پرونده ی %1%\n" +" از بسته ی\n" +" %2%\n" +" متداخل است با پرونده ی\n" +" %3%\n" +" از بسته ی\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"پرونده ی %1%\n" +" از بسته ی\n" +" %2%\n" +" متداخل است با پرونده ی\n" +" %3%\n" +"از نصب\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"پرونده ی %1%\n" +" از نصب\n" +" %2%\n" +" متداخل است با پرونده ی\n" +" %3%\n" +" از بسته ی\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"پرونده ی %1%\n" +" از نصب\n" +" %2%\n" +" متداخل است با پرونده ی\n" +" %3%\n" +" از نصب\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "نمیتوان sat-pool را ساخت." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "شکستن %s با نادیده گرفتن برخی از وابستگیها" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "نادیده گرفته برخی وابستگیها به صورت عمومی" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "%1% نصب شده متعلق به مخزن disupgrade نیست و باید جایگزین شود" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "%1% که قرار است نصب شود به یک مخزن ارتقاء تعلق ندارد" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "%1% نصب شده دارای معماری ضعیفی است" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "%1% که قرار است نصب شود، معماری پایین‌تری دارد" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "مشکل با %1% نصب شده" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "درخواستهای متداخل" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "برخی مشکلات وابستگی" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "هیچ چیز \"% 1%\" درخواستی را ارائه نمی دهد" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "آیا تمام مخازن مورد نیاز را فعال کرده اید؟" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "بسته درخواستی %1% وجود ندارد" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "درخواست پشتیبانی نشده" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "\"%1%\" توسط سیستم ارائه شده است و قابل پاک کردن نیست" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% قابل نصب نیست" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "هیچ چیز «% 1%» مورد نیاز %2% نصب شده را فراهم نمی کند" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "هیچ چیز «% 1%» مورد نیاز برای نصب %2% را فراهم نمی کند" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "نمی تواند %1% و %2% را نصب کند" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "%1% نصب شده با \"%2%\" ارائه شده توسط %3% نصب شده در تضاد است" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "%1% نصب شده با \"%2%\" ارائه شده توسط %3% نصب شده در تضاد است" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "%1% برای نصب با \"%2%\" ارائه شده توسط %3% نصب شده در تضاد است" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "مورد نصب %1% با \"% 2%\" ارائه شده توسط \"%3%\" برای نصب در تضاد است" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "%1% نصب شده، \"%2%\" ارائه شده توسط %3% نصب شده منسوخ شده است" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "%1% نصب شده، \"%2%\" ارائه شده توسط %3% نصب شده منسوخ شده است" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "%1% نصب شده، \"%2%\" ارائه شده توسط %3% نصب شده منسوخ شده است" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "مورد نصب %1% منسوخ شده '%2%' ارائه شده توسط 3% برای نصب" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "%1% نصب شده با \"%2%\" ارائه شده توسط خودش در تضاد است" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "%1% که باید نصب شود با \"%2%\" ارائه شده توسط خودش تضاد دارد" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "%1% که باید نصب شود با \"%2%\" ارائه شده توسط خودش تضاد دارد" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "برای نصب %1% به \"%2%\" نیاز دارد، اما این نیاز قابل ارائه نیست" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "ارائه دهنده های حذف شده: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"ارائه دهندگان غیر قابل نصب: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "ارائه دهندگان غیر قابل نصب: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% هنوز به طور کامل در %2 ادغام نشده است." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "معمولاً می‌خواهید PTF را نگه دارید و وصله‌های نگهداری را نصب نکنید." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"حذف %1% نصب شده در این زمینه، بسته‌های PTF موجود را نیز حذف می‌کند (نه " +"جایگزین!)." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"PTF باید با فراخوانی '%1%' حذف شود. این کار بسته‌های PTF ارائه شده را به‌جای " +"حذف آن‌ها به‌روزرسانی می‌کند." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "معمولاً می‌خواهید PTF را نگه دارید یا کنش را لغو کنید." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "%1% نصب شده عمل مورد نظر را مسدود می کند." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "معمولاً می‌خواهید PTF را نگه دارید و کنش را لغو کنید." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "حذف قفل برای اجازه حذف %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "%1% را نصب نکن" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "نگه داشتن %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "حذف قفل برای اجازه نصب %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "این درخواست سیستم شما را خواهد شکست!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "نادیده گرفتن هشدار سیستم شکسته شده" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "درخواستی برای نصب یک قابل حل ارائه 1% نپرسید" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "درخواست حذف همه قابل حل‌های ارائه‌دهنده %1% نکنید" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "آخرین نسخه %1% را نصب نکنید" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "%1% را با وجود معماری پایین نگه دارید" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "با وجود معماری ضعیف، %1% را نصب کنید" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "منسوخ نگه داشتن %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "%1% را از مخزن حذف شده نصب کنید" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "%1% را نصب کنید اگرچه پس گرفته شده است" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "اجازه نصب PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "%1% را نصب کنید اگرچه در لیست سیاه قرار دارد" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "کاهش %1% به %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "تغییر معماری %1% به %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"نصب %1% (با تغییر vendor)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"نصب %1% از vendor %2%\n" +" جایگزینی %3% از vendor %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "جایگزینی %1% با %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "حذف نصب %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "نصب انصراف داده شد و یا جهتدار شد." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " اجرا شده" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " اجرا ناموفق بود" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s در حال حاظر اجرا شده به عنوان %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " اجرا در هنگام انصراف پرش شد" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "خطا در ارسال اعلام پیغام بروزرسانی." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "پیغام بروزرسانی جدید" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "اجرای تراکنش به دلیل مشکلات زیر انجام نشد:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM شکست خورد: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "ناموفق در وارد کردن کلید عمومی از پرونده ی %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "ناموفق در حذف کلید عمومی %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "سرصفحه بسته امضا نشده است!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "محموله بسته امضا نشده است!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "پرونده های پیکربندی تغییر کرده برای %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm ذخیره شد %s به عنوان %s، اما تعیین اختلاف امکانپذیر نبود" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ذخیره شد %s به عنوان %s\n" +"اینها 25 خط اولیه ی اختلاف ها هستند:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm ساخته شد %s به عنوان %s، اما تعیین اختلاف امکانپذیر نبود" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ساخته شد %s به عنوان %s\n" +"اینها 25 خط اولیه ی اختلاف ها هستند:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "خروجی rpm اضافی" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "پشتیبان ساخته شد %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "امضا خوب است" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "نوع امضا ناشناخته است" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "امضا قابل تایید نیست" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "امضا خوب است، اما کلید اعتمادسازی نشده است" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "کلید عمومی امضاها موجود نیست" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "پرونده موجود نیست و یا امضاها قابل بررسی نیستند" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "فایل تایید نشده" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "مورد مشکوک '%s' برای %u بایت checksum '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "نمیتوان pty (%s) را باز کرد." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "نمیتوان pipe (%s) را باز کرد." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "رشته ی پرس و جوی آدرس LDAP نامعتبر" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "پارامتر پرس و جوی آدرس LDAP نامعتبر '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "ناتوان در همزاد سازی آدرس شیء" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "مرجع شیء آدرس خالی نامعتبر" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "ناتوان در تجزیه ی اجزاء آدرس" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "تاریخچه:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "شکل آدرس یک %s را مجاز نمیکند" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "%s نامعتبر جزء %s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "جزء %s نامعتبر" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "تجزیه ی پرس و جوی رشته برای این آدرس پشتیبانی نمیشود" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "شکل آدرس یک جزء درخواستی است" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "شکل آدرس نامعتبر '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "شکل آدرس، نام کاربری را مجاز نمیکند" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "شکل آدرس، رمز عبور را مجاز نمیکند" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "شکل آدرس یک جزء میزبان را میخواهد" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "شکل آدرس یک جزء میزبان را اجازه نمیدهد" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "مؤلفه میزبان نامعتبر «%s»" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "شکل آدس یک درگاه را مجاز نمیکند" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "جزء درگاه نامعتبر '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "شکل آدرس یک نام مسیر را میخواهد" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "مسیر نسبی در صورت وجود مرجع مجاز نیست" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "رشته ی رمزی حاوی بایت NUL است" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "پارامتر کاراکتر جداکننده ی تقسیمگر آرایه نامعتبر" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "پارامتر کاراکتر جداکننده ی تقسیمگر نقشه نامعتبر" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "پارامتر کاراکتر جداکننده ی پیوند آرایه نامعتبر" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "دستور با وضعیت %d خارج شد." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "دستور با سیگنال %d (%s) کشته شد." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "دستور با خطای ناشناخته خارج شد." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "آرگومان های ارسال نامعتبر ارائه شده است." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "ایجاد لوله کنترل امکان پذیر نیست." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "نمیتوان chroot کرد به '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "نمیتوان chdir کرد به '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "نمیتوان chdir کرد به '%s' درون chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "'%s' (%s) را نمیتوان اجرا کرد." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "نمیتوان fork کرد (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "نمی‌توان «%s» را اجرا کرد، chdir ناموفق بود (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "نمی‌توان «%s» را اجرا کرد، chroot ناموفق بود (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "نمی‌توان «%s» را اجرا کرد، exec ناموفق بود (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "نمی‌توان «%s» را اجرا کرد، خطای غیرمنتظره." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "ناموفق در سوار کردن %s بر روی %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "ناموفق در پیاده سازی %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "نام پرونده ی بد: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "رسانه در هنگام تلاش برای انجام عمل '%s' باز نشده است." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "پرونده ی '%s' در رسانه ی '%s' یافت نشد" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "نمیتوان پرونده ی '%s' را نوشت." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "رسانه متصل نشده است" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "نقطه ی اتصال رسانه ی بد" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "مقداردهی دریافت (curl9) برای '%s' ناموفق بود" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "استثناء سیستم '%s' برای رسانه ی '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "مسیر '%s' در رسانه ی '%s' یک پرونده نیست." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "مسیر '%s' در رسانه ی '%s' یک فهرست نیست." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "ادرس بدشکل" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "نام میزبان خالی در آدرس" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "فایل سیستم خالی در آدرس" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "مسیر خالی در آدرس" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "شکل آدرس پشتیبانی نشده در '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "عملیات توسط رسانه پشتیبانی نشده است" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"خطای دریافت (curl) برای '%s':\n" +"کد خطا: %s \n" +"متن خطا: %s \n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "خطایی در هنگام تنظیم اختیارات دریافت (curl) برای '%s' رخ داد:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "منبع رسانه ی '%s' حاوی رسانه ی مطلوب نیست" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "رسانه ی '%s' توسط یک مورد دیگر در حال استفاده است" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "نمیتوان هیچ رسانه ای را خارج کرد" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "نمیتوان رسانه ی '%s' را خارج کرد" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "اجازه برای دسترسی به '%s' داده نشد." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "مهلت زمانی در هنگام دسترسی به '%s' پایان یافت." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"داده های دانلود شده از اندازه فایل مورد انتظار '%s' از '%s' فراتر رفته است." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "مکان '%s' به صورت موقتی غیر قابل دسترسی است." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " ایراد گواهی SSL، لطفا بررسی کنید که گواهی CA برای '%s' درست است." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "هیچ منبع رایگانی برای پیوست کردن رسانه موجود نیست." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "حالت احراز هویت پشتیبانی نشده '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"خطای دانلود (curl) برای '%s':\n" +"کد خطا: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"خطای دانلود (curl) برای '%s':\n" +"پاسخ HTTP قابل بازیابی نیست\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "در حال اجرای %%اسکریپت posttrans \"% 1%\"" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "اجرای %posttrans scripts" + +#~ msgid "Package is not signed!" +#~ msgstr "بسته مورد تایید نیست!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s مربوط به یک مخزن distupgrade نیست" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s دارای معماری نامرغوب است" + +#~ msgid "problem with installed package %s" +#~ msgstr "ایراد در بسته ی نصب شده ی %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "هیچ چیز %s درخواستی را مهیا نمیکند" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "آیا شما تمامی مخازن درخواستی را فعال کرده اید؟" + +#~ msgid "package %s does not exist" +#~ msgstr "بسته ی %s وجود ندارد" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s توسط سیستم مهیا شده است و نمیتواند حذف شود" + +#~ msgid "%s is not installable" +#~ msgstr "%s قابل نصب نیست" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "هیچ چیز %s که توسط %s مورد نیاز است را مهیا نمیکند" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "نمیتوان هردو %s و %s را نصب کرد" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s با %s که توسط %s مهیا شده است متداخل است" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s منسوخ میکند %s را که توسط %s مهیا شده است" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s نصب شده منسوخ میکند %s را که توسط %s مهیا شده است" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "حل شونده ی %s با %s مهیا شده توسط خودش متداخل است" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s میخواهد %s را، اما این نیازمندی قابل مهیا شدن نیست" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "قفل را جهت حذف %s پاک کنید" + +#~ msgid "do not install %s" +#~ msgstr "%s را نصب نکن" + +#~ msgid "keep %s" +#~ msgstr "%s را نگه دار" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "قفل را جهت نصب %s حذف کن" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "درباره ی نصب یک حل شونده که %s را ارائه میدهد سوال نکن" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "درباره ی حذف تمامی حل شونده ها که %s را ارائه میدهند سوال نکن" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "نسخه های جدیدتر %s را نصب نکن" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "نگهداری %s با وجود اینکه معماری نامرغوب دارد" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "نصب %s با وجود اینکه معماری نامرغوب دارد" + +#~ msgid "keep obsolete %s" +#~ msgstr "نگهداری %s منسوخ شده" + +#~ msgid "install %s from excluded repository" +#~ msgstr "نصب %s از مخزن مستثنی" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "تنزل درجه ی %s به %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "تغییر معماری %s به %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "نصب %s (با تغییر فروشنده) \n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "جایگزینی %s با %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "از نصب خارج کردن %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "نمیتوان فایل قفل را باز کرد: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "این عمل در حال حاظر در حال اجرا توسط یک نرم افزار دیگر است." + +#~ msgid "Hal Exception" +#~ msgstr "استثنای Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "عذخواهی میکنیم، اما این نسخه ی libzypp بدون پشتیبانی از HAL ساخته شده است." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext متصل نشده است" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive مقداردهی اولیه نشده است" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume مقداردهی نشده است" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "ناتوان در ساخت ارتباط dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: نمیتوان متن libhal را ساخت" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: نمیتوان ارتباط dbus را تنظیم کرد" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "ناتوان در مقداردهی به متن HAL -- آیا hald اجرا نمیشود؟" + +#~ msgid "Not a CDROM drive" +#~ msgstr "درایو CDROM نیست" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "نمیتوان صفات mutex را مقدار دهی اولیه کرد" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "نمیتوان صفت mutex بازگشتی را قرار داد" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "نمیتوان mutex بازگشتی را مقداردهی اولیه کرد" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "نمیتوان قفل mutex را دریافت کرد" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "نمیتوان قفل mutex را آزاد کرد" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "ناموفق در وارد کردن کلید عمومی از پرونده ی %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "ناموفق در حذف کلید عمومی %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "نمیتوان دستگاه حلقه را برای سوار کردن پرونده ی ایمیج از '%s' پیدا کرد" diff --git a/po/fi.po b/po/fi.po new file mode 100644 index 0000000..608bad4 --- /dev/null +++ b/po/fi.po @@ -0,0 +1,5745 @@ +# translation of zypp.fi.po to suomi +# translation of zypp.po to +# translation of zypp.fi.po to +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Finnish message file for YaST2 (@memory@). +# Copyright (C) 2003 SuSE Linux AG. +# +# Michael Hintsala , 2003. 2001. +# Ilkka Pirskanen , 2006, 2007. +# Jyri Palokangas , 2006, 2007. +# Jyri Palokangas , 2007. +# Sami Vento , 2007, 2009, 2010. +# Jyri Palokangas , 2008, 2009. +# Mikko Piippo , 2008. +# Jyri Palokangas , 2008, 2010, 2011, 2013, 2014. +# Harri Miettinen , 2010, 2011, 2013, 2014. +# Katariina Kemppainen , 2010, 2011, 2012. +msgid "" +msgstr "" +"Project-Id-Version: zypp.fi\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-02-21 11:42+0000\n" +"Last-Translator: Tommi Nieminen \n" +"Language-Team: Finnish \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-Generator: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Tuntematon maa: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Ei koodia" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Arabiemiirikunnat" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua ja Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Alankomaiden Antillit" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktis" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentiina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikan Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Itävalta" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +# CU +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# FO +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Ahvenanmaa" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaidzhan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia ja Hertsegovina" + +# BB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +# BD +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgia" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +# BH +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasilia" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahama" + +# BH +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +# FO +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvetinsaari" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +# BY +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Valko-Venäjä" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kookossaaret" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Keski-Afrikan tasavalta" + +# CH +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Sveitsi" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Norsunluurannikko" + +# FO +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookinsaaret" + +# CL +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +# CN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kiina" + +# CO +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kap Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Joulusaari" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Kypros" + +# CZ +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tšekki" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Saksa" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Tanska" + +# DM +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +# DO +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikaaninen tasavalta" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algeria" + +# EC +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +# EE +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Viro" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypti" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Länsi-Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Espanja" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Suomi" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandinsaaret" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikronesia" + +# FO +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Färsaaret" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Ranska" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Ranskan suurkaupungit" + +# GH +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Iso-Britannia" + +# GD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +# GE +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Ranskan Guayana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +# GL +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grönlanti" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +# GU +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Päiväntasaajan Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Kreikka" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Etelä-Georgia ja Eteläiset Sandwichsaaret" + +# GT +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +# GU +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +# GH +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard ja McDonaldinsaaret" + +# HN +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +# HR +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +# HU +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Unkari" + +# ID +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +# IE +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanti" + +# IL +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Mansaari" + +# IN +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Intia" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Brittiläinen Intian valtameren alue" + +# IQ +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +# IS +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islanti" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +# JM +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaika" + +# JO +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordania" + +# JP +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japani" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +# KZ +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgisia" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodzha" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komorit" + +# KN +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts ja Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Pohjois-Korea" + +# ZA +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Etelä-Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +# FO +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Caymansaaret" + +# KZ +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +# LT +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Liettua" + +# LU +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburg" + +# LV +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvia" + +# LR +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libya" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +# FO +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshallinsaaret" + +# MK +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonia" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +# MO +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Pohjois-Mariaanit" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +# MT +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +# MV +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Malediivit" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +# MX +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksiko" + +# MY +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malesia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mosambik" + +# GM +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Uusi-Kaledonia" + +# NG +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +# FO +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolkinsaari" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +# NI +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +# NL +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Alankomaat" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norja" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +# NZ +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Uusi-Seelanti" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +# PA +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +# PE +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Ranskan Polynesia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua-Uusi-Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filippiinit" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +# PL +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Puola" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint-Pierre ja Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestiina" + +# PT +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugali" + +# PW +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +# PY +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +# QA +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +# RO +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Venäjä" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi-Arabia" + +# FO +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salomonsaaret" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychellit" + +# SD +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Ruotsi" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Saint Helena" + +# SI +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Huippuvuoret ja Jan Mayen" + +# SK +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +# SY +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé ja Príncipe" + +# SV +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +# SY +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syyria" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swazimaa" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- ja Caicossaaret" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tshad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Ranskan eteläiset alueet" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +# TH +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thaimaa" + +# TJ +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadzhikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "tokelau" + +# TJ +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +# TN +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Itä-Timor" + +# TR +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkki" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad ja Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "tuvalu" + +# TW +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tansania" + +# UA +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Yhdysvaltain pienet erillissaaret" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Yhdysvallat" + +# UY +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Pyhä istuin (Vatikaani)" + +# VC +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent ja Grenadiinit" + +# VE +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# VI +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Brittiläiset Neitsytsaaret" + +# VI +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Yhdysvaltain Neitsytsaaret" + +# VN +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis ja Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +# ZA +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Etelä-Afrikka" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Sambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Tarjoaa" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Edellytykset" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Vaatii" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Ristiriidat" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Vanhentuneet" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Suosittelee" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Ehdottaa" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Parannukset" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Täydentää" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" +"Yritettiin lisätä avain %s avainrenkaaseen %s, mutta tiedostoa ei löydetty" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Avaimen tuonti epäonnistui." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Avaimen poisto epäonnistui." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Allekirjoitustiedostoa %s ei löydetty" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Tuntematon kieli: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "abhaasi" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "aceh" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "afroaasialaiset (muut)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "akkadi" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "albania" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "aleutti" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "algonkin-kielet" + +# ZA +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "altai, etelä-" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "amhara" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "englanti, muinais- (noin 450 - 1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "apaššikielet" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "arabia" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "aramea" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "aragonia" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "armenia" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "araukaani" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "keinotekoiset (muut)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "assami" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "asturia" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "athabasca-kielet" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "australialaiset kielet" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "avaari" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "avesta" + +# SZ +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "awadhi" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "azeri" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "bamileke-kielet" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "baškiiri" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "belutši" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "bali" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "baski" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "balttilaiset (muut)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "valkovenäjä" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "bemba" + +# BZ +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "berberikielet (muut)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "bhojpuri" + +# BH +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "bikol" + +# IN +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "mustajalka" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "bantukielet (muut)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "bosnia" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "bretoni" + +# ID +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "batak" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "burjaatti" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "bugi" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "bulgaria" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "burma" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Keski-Amerikan intiaanikielet (muut)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "karibi" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "katalaani" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "kaukasialaiset (muut)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "kelttiläiset (muut)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "chamorro" + +# CN +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "tšetšeeni" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "tšagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "kiina" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "chuuk" + +# ML +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "chinook jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "kirkkoslaavi" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "tšuvassi" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "cham-kielet" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "kopti" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "korni" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "korsika" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "kreolit ja pidginit, englantiin perustuvat (muut)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "kreolit ja pidginit, ranskaan perustuvat (muut)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "kreolit ja pidginit, portugaliin perustuvat (muut)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "krimintataari" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "kreolit ja pidginit (muut)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "kašubi" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "kuušilaiset (muut)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "tšekki" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "tanska" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "dargva" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "slave" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "dravidakielet (muut)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "alasorbi" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "hollanti, keski- (noin 1050 - 1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "hollanti" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "muinaisegypti" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "elam" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "englanti" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "englanti, keski- (1100 - 1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "viro" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "fääri" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "fidži" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "filippiini" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "suomi" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "suomalais-ugrilaiset (muut)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "ranska" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "ranska, keski- (noin 1400 - 1600 )" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "ranska, muinais- (842 - 1400)" + +# FR +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "friisi" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "fulani" + +# FR +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "friuli" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "gã" + +# GH +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "germaaniset (muut)" + +# GE +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "georgia" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "saksa" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "ge'ez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "kiribati" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "gaeli" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "iiri" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "galicia" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "saksa, keskiylä- (noin 1050 - 1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "saksa, muinaisylä- (noin 750 - 1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "gootti" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "kreikka, muinais- (ennen 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "kreikka (jälkeen 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "haiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "havaiji" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "heprea" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "himachali" + +# IN +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "heetti" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "hiri-motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "yläsorbi" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "unkari" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "hupa" + +# IR +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "islanti" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ido" + +# LT +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "sichuanin-yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "interlingua" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "indoarjalaiset (muut)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "indonesia" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "indoeurooppalaiset (muut)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "inguuši" + +# IN +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "iñupiak" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "iranilaiset (muut)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "irokeesikielet" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "italia" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "jaava" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "japani" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "juutalaispersia" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "juutalaisarabia" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "karakalpakki" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "kabyyli" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "kamba" + +# CA +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "kavi" + +# KZ +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "kazakki" + +# MR +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "kabardi" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "khoisan-kielet (muut)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "khotani" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "kikuju" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "ruanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "kirgiisi" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "korea" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "kosrae" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "karatšai-balkaari" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "kru-kielet" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "kurukh" + +# PA +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "kwanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "kumykki" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "kurdi" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "latina" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "latvia" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "lezgi" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "limburg" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "liettua" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "lozi" + +# LU +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "luxemburg" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "luba (Lulua)" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "luba (Katanga)" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "luiseño" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "luo (Kenia ja Tansania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "makedonia" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "madura" + +# MU +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "marshall" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "makassar" + +# MY +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "mandingo" + +# ML +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "austronesialaiset (muut)" + +# MU +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "marathi" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "maasai" + +# MT +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "malaiji" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "mokša" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "iiri, keski- (900 - 1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "micmac" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "luokittelemattomat kielet" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "mon-khmer-kielet (muut)" + +# MY +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "malagassi" + +# MV +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "malta" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "mantšu" + +# ML +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "manobo-kielet" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "moldavia" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "mongoli" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "monia kieliä" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "mundakielet" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "creek" + +# MV +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "mirandi" + +# MU +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "maya-kielet" + +# SY +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "ersä" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "nahuatl" + +# ZA +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Pohjois-Amerikan intiaanikielet" + +# ML +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "napoli" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "ndebele, etelä-" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "ndebele, pohjois-" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "alasaksa" + +# ML +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "newari" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "nigeriläis-kongolaiset (Muut)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "niue" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "norja (uusnorja)" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "norja (kirjanorja)" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "norja, muinais-" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "norja" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "sotho, pohjois-" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "nubialaiset kielet" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "klassinen newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "nyanja" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "oksitaani" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "ojibwa" + +# SY +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "osseetti" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "osmani" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "otomi-kielet" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "papualaiset (muut)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "pangasinan" + +# ML +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "pahlavi" + +# PY +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "pampanga" + +# PA +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "papiamentu" + +# PW +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "palau" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "persia, muinais- (noin 600 - 400 eKr.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "farsi" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "filippiiniläiset (muut)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "foinikia" + +# ML +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "paali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "puola" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "pohnpei" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "portugali" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "prakrit-kielet" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "provensaali, muinais- (ennen 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "pašto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "quechua" + +# KZ +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "rajasthani" + +# JP +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "rarotonga" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "romaaniset (muut)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "retoromaani" + +# RO +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "romania" + +# IN +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "venäjä" + +# SD +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "sandawe" + +# SD +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "jakuutti" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Etelä-Amerikan intiaanikielet (muut)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "sališilaiset kielet" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "samarianaramea" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "serbia" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "sisilia" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "skotti" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "kroatia" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "selkuppi" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "seemiläiset kielet (muut)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "iiri, muinais- (ennen 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "viittomakielet" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "sinhali" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "sioux-kielet" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "sinotiibetiläiset (muut)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "slaavilaiset (muut)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "slovakki" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "sloveeni" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "saame, etelä-" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "saame, pohjois-" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "saamelaiskielet (muut)" + +# ES +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "saame, luulajan-" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "saame, inarin-" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "saame, koltan-" + +# SI +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "sogdi" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "sotho, etelä-" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "espanja" + +# MR +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "sardi" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "niililäis-saharalaiset (muut)" + +# ES +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "swazi" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "sukuma" + +# SD +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "sunda" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "sumeri" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "ruotsi" + +# SY +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "syyria" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "tahiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "thaikielet (muut)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "tamil" + +# QA +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "tataari" + +# BE +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "temne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "tetum" + +# TJ +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "tadžikki" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "thai" + +# TW +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "tiibet" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "tigre" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "tonga (Malawi)" + +# FO +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "tonga (Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "tok-pisin" + +# FR +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "tsimshian" + +# TW +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "tswana" + +# EE +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "tsonga" + +# TR +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "turkmeeni" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "tupi-kielet" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "turkki" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "altailaiset (muut)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "twi" + +# TN +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "tuva" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "udmurtti" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "ugarit" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "uiguuri" + +# UA +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "ukraina" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "määrittämätön" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "uzbekki" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "vietnam" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "vatja" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "wakash-kielet" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "kymri" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "sorbin kielet" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "valloni" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "kalmukki" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "yap" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "jiddiš" + +# CU +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "joruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "jupikkikielet" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "sapoteekki" + +# BZ +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Tehdään seuraavat toiminnot:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "ei vanhene" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "vanhentunut: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "vanhenee: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(ei vanhene)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(VANHENTUNUT)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(vanhenee 24 tunnin kuluessa)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(vanhenee %d päivässä)" +msgstr[1] "(vanhenee %d päivässä)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "tuntematon" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "ei tuettu" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "1. Taso" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "2. Taso" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "3. Taso" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Erillinen asiakassopimus tarpeen" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "virheellinen" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Tuen tasoa ei ole määritetty" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Myyjä ei tarjoa tukea." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Ongelman määrittäminen, mikä tarkoittaa teknistä tukea, joka tarjoaa " +"yhteensopivuustietoja, asennustukea, käyttötukea, huoltoa ja perustason " +"ongelmanratkaisua. 1. tason tukea ei ole tarkoitettu korjaamaan tuotteen " +"puutteista johtuvia virheitä." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Ongelman eristäminen, mikä tarkoittaa teknistä tukea, joka tähtää asiakkaan " +"ongelmien toistamiseen, ongelma-alueen eristämiseen ja tarjoaa ratkaisuja " +"ongelmille, joita 1. tason tuki ei ratkaissut." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Ongelman ratkaiseminen, mikä tarkoittaa monimutkaisten ongelmien " +"ratkaisemiseen tarkoitettua teknistä tukea. Insinöörit korjaavat tuotteen " +"vikoja, jotka 2. tason tuki on tunnistanut." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Tuen saamiseksi edellytetään erillinen asiakassopimus." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Tuntematon tukivaihtoehto. Kuvausta ei ole saatavilla" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Prosessi %d (%s) on lukinnut järjestelmänhallinnan. \n" +"Sulje ohjelma ennen uutta yritystä." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Tuntematon tila \"%s\"" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Tuntematon tila \"%s\" hakulauseelle \"%s\"" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Virhe säännöllisessä lausekkeessa \"%s\": regcomp palautti %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Virhe säännöllisessä lausekkeessa \"%s\"" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "\"%s\" vaatii tunnistautumisen" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Yritetään uudelleen…" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Luovutetaan %1% yrityksen jälkeen." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Tarkista SUSEn asiakaskeskuksessa käymällä, onko rekisteröitymisesi voimassa." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Vieraile Novellin asiakaskeskuksessa tarkastamassa onko rekisteröintisi " +"voimassa ja ettei se ole vanhentunut." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Luo liitospiste: Kirjoitettavissa olevaa kansiota ei löydy liitospisteen " +"luomiseksi" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Asenna 'lsof' paketti ensiksi." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Metatiedon välimuistihakemistoa ei voi luoda." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Virhe luettaessa \"%s\"" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Ei voi luoda %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Annetusta verkko-osoitteesta ei löytynyt kelvollista metatietoa" +msgstr[1] "Annetuista verkko-osoitteista ei löytynyt kelvollista metatietoa" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Virhe asennuslähteen puskuroinnissa (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Rakennetaan asennuslähteen \"%s\" välimuistia" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Välimuistia %s ei voida luoda - ei kirjoitusoikeuksia." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Virheellinen asennuslähteen tyyppi" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Lisätään asennuslähdettä \"%s\"" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Virheellinen asennuslähteen tiedostonimi \"%s\"" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Tiedostoa \"%s\" ei voida avata kirjoitusta varten." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Tuntematon virhe luettaessa \"%s\"" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "repo hakemiston lukeminen ei onnistu '%1%': Pääsy estetty" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Hakemiston \"%s\" lukeminen ei onnistu" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "repo-tiedostoa '%1%' ei voitu lukea: Pääsy estetty" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Poistetaan asennuslähdettä \"%s\"" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Asennuslähteen sijaintia ei voida päätellä." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "\"%s\" poistaminen ei onnistu" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Palvelun sijaintia ei voida päätellä." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Tuntematon palvelu '%1%': Poistetaan orpo palvelulähde '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Asennuslähteen alias ei voi alkaa pisteellä." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Palvelun alias ei voi alkaa pisteellä." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Jatketaanko?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Asennuslähde %1% ei ole asettanut ”gpgkey=”-lisäverkko-osoitteita." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Etsitään GPG-avainta %1% asennuslähteestä %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Etsitään GPG-avainta %1% välimuistista %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Vaadittu ominaisuus \"%s\" puuttuu." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Tarvitaan joko %s tai %s -attribuutti." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Allekirjoituksen todennus epäonnistui" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "Paketti %s näyttää vioittuneen siirron aikana. Yritetäänkö uudelleen?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Virhe noudettaessa pakettia %s. Yritetäänkö uudelleen?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm-tarkistus epäonnistui." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm epäonnistui." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Palvelu-lisäosa ei tue ominaisuuksien muutosta." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Tiedoston \"%s\" nouto asennuslähteestä \"%s\" ei onnistu" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Asennuslähteen verkko-osoite puuttuu." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Odotettiin tiedoston ”%3%” mukaista tietovälinettä %1%/%2% sisältönään:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Tiedosto %1%\n" +" paketista\n" +" %2%\n" +" on ristiriidassa tiedoston kanssa joka kuuluu pakettiin\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Tiedosto %1%\n" +" paketista\n" +" %2%\n" +" on ristiriidassa tiedoston kanssa joka kuuluu asennukseen\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Tiedosto %1%\n" +" asennuksesta\n" +" %2%\n" +" on ristiriidassa tiedoston kanssa joka kuuluu pakettiin\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Tiedosto %1%\n" +" asennuksesta\n" +" %2%\n" +" on ristiriidassa tiedoston asennuksesta\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Tiedosto %1%\n" +" paketista\n" +" %2%\n" +" on ristriidassa tiedoston\n" +" %3%\n" +" paketista\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Tiedosto %1%\n" +" paketista\n" +" %2%\n" +" on ristiriidassa tiedoston\n" +" %3%\n" +" asennettavasta paketista\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Tiedosto %1%\n" +" asennuksesta\n" +" %2%\n" +" on ristiriidassa tiedoston\n" +" %3%\n" +" paketista\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Tiedosto %1%\n" +" asennuksesta\n" +" %2%\n" +" on ristiriidassa tiedoston\n" +" %3%\n" +" asennuksesta\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Sat-varaston luonti ei onnistu." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "jätä %s riippuvuuksia huomioimatta" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "jätä joitakin riippuvuuksia huomiotta" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "asennettu %1% ei kuulu jakelupäivityslähteeseen ja on korvattava" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "asennettava %1% ei kuulu jakelupäivityslähteeseen" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "asennetulla paketilla %1% on heikompi arkkitehtuuri" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "asennettavalla paketilla %1% on heikompi arkkitehtuuri" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "ongelma asennetussa paketissa %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "ristiriitaiset kyselyt" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "jokin riippuvuusongelma" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "mikään ei tarjoa pyydettyä pakettia ”%1%”" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Onko kaikki vaaditut asennuslähteet otettu käyttöön?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "pyydettyä pakettia %1% ei ole olemassa" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "pyyntöä ei tueta" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "paketin ”%1%” tarjoaa järjestelmä eikä sitä voi poistaa" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% ei ole asennettavissa" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "asennetun paketin %2% vaatimaa pakettia \"%1%” ei tarjoa mikään lähde" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" +"asennettavan paketin %2% vaatimaa pakettia ”%1%” ei tarjoa mikään lähde" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "ei voida asentaa sekä %1% että %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"asennettu %1% on ristiriidassa asennetun paketin %3% tarjoaman paketin ”%2%” " +"kanssa" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"asennettu paketti %1% on ristiriidassa asennettavan paketin %3% tarjoaman " +"paketin ”%2%” kanssa" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"asennettava paketti %1% on ristiriidassa asennetun paketin %3% tarjoaman " +"paketin ”%2%” kanssa" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"asennettava paketti %1% on ristiriidassa toisen asennettavan paketin %3% " +"tarjoaman paketin ”%2%” kanssa" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"asennettu paketti %1% vanhentaa toisen asennetun paketin %3% tarjoaman " +"paketin ”%2%”" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"asennettu paketti %1% vanhentaa asennettavan paketin %3% tarjoaman paketin " +"”%2%”" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"asennettava paketti %1% vanhentaa asennetun paketin %3% tarjoaman paketin " +"”%2%”" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"asennettava paketti %1% vanhentaa toisen asennettavan paketin %3% tarjoaman " +"paketin ”%2%”" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"asennettu paketti %1% on ristiriidassa itse tarjoamansa paketin ”%2“ kanssa" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"asennettava paketti %1% on ristiriidassa itsensä tarjoaman paketin ”%2%” " +"kanssa" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"asennettu paketti %1% vaatii paketin ”%2%” mutta vaatimusta ei voi täyttää" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"asennettava paketti %1% vaatii paketin ”%2%” mutta vaatimusta ei voi täyttää" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "poistetut tarjoajat: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"Poistettavissa olevat tarjoajat: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "poistetut tarjoajat: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% ei vielä ole täysin integroitu paikkaukseen %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Tavallisesti haluat säilyttää PTF:n ja olla asentamatta ylläpitopaikkauksia." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"%1%-asennuksen poisto tässä kontekstissa poistaa (ei korvaa!) myös " +"sisällytetyt PTF-paketit." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"PTF tulisi poistaa komennolla ”%1%”. Niiden poistamisen sijaan tämä " +"päivittää sisällytetyt PTF-paketit ." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Tavallisesti halunnet säilyttää PTF:n tai perua toimenpiteen." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Asennettu %1% estää halutun toimenpiteen." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Tavallisesti haluat säilyttää PTF:n ja perua toimenpiteen." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "avaa lukitus paketin %1% poistamiseksi" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "älä asenna pakettia %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "pidä %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "avaa lukitus paketin %1% asentamiseksi" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Tämä pyyntö rikkoo järjestelmän!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ohita varoitus rikkinäisestä järjestelmästä" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "älä kysy, asennetaanko paketin %1% tarjoavaa ratkaisua" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "älä kysy, poistetaanko paketin %1% tarjoavia ratkaisuja" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "älä asenna paketin %1% uusinta versiota" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "pidä %1% heikommasta arkkitehtuurista huolimatta" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "asenna %1% heikommasta arkkitehtuurista huolimatta" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "pidä vanhentunut %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "asenna %1% pois suljetusta asennuslähteestä" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "asenna %1%, vaikka se on vedetty takaisin" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "salli asentaa PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "asenna %1%, vaikka se on mustalistattu" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "päivitä alaspäin %1% -> %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "arkkitehtuurin muutos %1% -> %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"asenna %1% (tarjoaja muuttuu)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"asenna toimittajalta %2% %1%,\n" +"joka korvaa paketin %3% toimittajalta %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "korvataan %1% -> %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "poistetaan asennus: %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Suoritetaan toimenpiteen jälkeisiä skriptejä" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Suoritetaan skriptiä %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Skriptin %1% tuloste:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Asennus keskeytettiin." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " suoritettu" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " suoritus epäonnistui" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s on jo suoritettu nimellä %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " suoritus ohitettiin keskeytettäessä" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Virhe lähetettäessä päivityshuomautusta." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Uusi päivitysviesti" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Vastaanotettiin signaali ”%1% (%2%)”: järjestelmän eheyden varmistamiseksi " +"käynnissä olevaa RPM-toimenpidettä ei voi perua." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Toimenpidettä ei voitu suorittaa seuraavien ongelmien takia:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM-virhe: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Avaimen tuonti tiedostosta %1% epäonnistui" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Julkisen avaimen %1% poisto epäonnistui" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Paketin otsaketta ei ole allekirjoitettu!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Paketin sisältöä ei ole allekirjoitettu!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Muunnettiin paketin %s asetustiedostoja:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm tallensi tiedoston %s nimellä %s. Erojen selvittäminen ei onnistunut" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm tallensi tiedoston %s nimellä %s.\n" +"Tässä ensimmäiset 25 muuttunutta riviä:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm loi tiedoston %s nimellä %s, erojen selvittäminen ei onnistunut" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm loi tiedoston %s nimellä %s.\n" +"Tässä on ensimmäiset 25 vaihtunutta riviä:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "rpm-lisätuloste" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "luotiin varmuuskopio %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Allekirjoitus kelpaa" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tuntematon allekirjoituksen tyyppi" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Allekirjoitusta ei voida todentaa" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Allekirjoitus kelpaa, mutta avain ei ole luotettu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Allekirjoituksen julkinen avain ei ole saatavilla" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Tiedostoa ei ole tai allekirjoitusta ei voi tarkistaa" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Tiedosto on allekirjoittamaton" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Virheellinen tyyppi \"%s\" tavulle %u, tarkistussumma: \"%s\"" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "pty:n (%s) avaaminen ei onnistu." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Putken (%s) avaaminen ei onnistu." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Virheellinen LDAP URL -kysely" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Virheellinen LDAP URL -parametri: \"%s\"" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Verkko-osoite-objektin kahdentaminen ei onnistunut" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Virheellinen viittaus tyhjään URL-objektiin" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Verkko-osoitteen jäsentäminen ei onnistu" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historia:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Ei sallittu verkko-osoite: %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Virheellinen %s-komponentti \"%s\"" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Virheellinen %s-komponentti" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Tämän verkko-osoitteen jäsentäminen kyselyksi ei ole tuettu" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Verkko-osoite on pakollinen" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Virheellinen verkko-osoite: \"%s\"" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Verkko-osoite ei salli käyttäjänimeä" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Verkko-osoite ei salli salasanaa" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Verkko-osoite edellyttää konenimen" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Verkko-osoite ei salli konenimeä" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Virheellinen konenimi: \"%s\"" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Verkko-osoite ei salli portin määritystä" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Virheellinen porttimääritys: \"%s\"" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Verkko-osoite edellyttää polun määrittämistä" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" +"Suhteellisen polun määrittäminen ei ole sallittua, jos valtuuttaja on " +"määritetty" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Koodattu merkkijono sisältää NUL-tavun" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Virheellinen parametritaulukon jaon erotin" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Virheellinen parametrikartan jaon erotin" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Virheellinen parametritaulukon liitoksen erotin" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Komento päättyi tilaan %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Komento lopetettiin signaalilla %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Komento päättyi tuntemattomaan virheeseen." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Annettu virheellisiä spawn-parametreja." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Hallintaputkea ei voitu luoda." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Hakemistorajoitus (chroot) ei onnistu hakemistoon \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Kansion vaihto ”chdir %s” ei onnistu (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "chdir '%s' ei onnistu chroot '%s' sisällä (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "\"%s\" (%s) suorittaminen ei onnistu." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Haarauttaminen (fork) ei onnistu (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Ei voida suorittaa ”%s”: chdir epäonnistui (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Ei voida suorittaa ”%s”: chroot epäonnistui (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Ei voida suorittaa ”%s”: exec epäonnistui (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Ei voida suorittaa ”%s”: tuntematon syy." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "%s liittäminen liitospisteeseen %s epäonnistui" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Virhe irrotettaessa %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Virheellinen tiedostonimi: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Tietolähdettä ei avattu suoritettaessa \"%s\"." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Tiedostoa \"%s\" ei löydy tietovälineeltä \"%s\"" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Tiedostoon \"%s\" kirjoittaminen ei onnistu." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Tietolähdettä ei ole liitetty" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Virheellinen liitospiste" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Lataajan (curl) alustus osoitteelle \"%s\" epäonnistui" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Järjestelmäpoikkeus \"%s\" tietovälineellä \"%s\"." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Polku \"%s\" tietovälineellä \"%s\" ei ole tiedosto." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Polku \"%s\" tietovälineellä \"%s\" ei ole hakemisto." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Virheellisesti muotoiltu URI-osoite" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Tyhjä konenimi URI-osoitteessa" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Tyhjä tiedostojärjestelmä URI-osoitteessa" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Tyhjä kohde URI-osoitteessa" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Virheellinen verkko-osoite: \"%s\"." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Tietoväline ei tue toimintoa" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Latausvirhe (curl) %s:\n" +"Virhekoodi: %s\n" +"viesti: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Virhe määritettäessä kohteen '%s' latausasetuksia (curl):" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "\"%s\" ei sisällä haluttua tietolähdettä" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Tietolähde \"%s\" on varattu" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Tietovälineiden irrottaminen ei onnistu" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Tietovälineen \"%s\" irrottaminen ei onnistu" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Pääsy evätty kohteeseen \"%s\"." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Aikakatkaisu avattaessa \"%s\"." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Ladattu tieto ylittää odotetun tiedostokoon ”%s”/”%s”." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "\"%s\" ei ole hetkellisesti saatavilla." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL-ongelma: Tarkista että CA-varmenne kuuluu \"%s\"." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Ei vapaita resursseja tietovälineen liittämiseksi." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "HTTP-tunnistautumistapa \"%s\" ei ole tuettu" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Latausvirhe (curl) kohteelle ”%s”:\n" +"Virhekoodi: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Latausvirhe (curl) kohteelle ”%s”:\n" +"HTTP-vastausta ei saatu\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Kyllä" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ei" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Huomaa:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Varoitus:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Virhe:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "valmis" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "huomio" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "virhe" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Varoitus: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Ladataan:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "käynnistetään" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "ei löytynyt" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Tälle toiminnolle ei ole ohjetta." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "Tälle valinnalle ei ole ohjetta" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "näyttää kaikki valinnat" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "kyllä" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ei" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Suoritetaan %%posttrans-skriptiä ”%1%”" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Suoritetaan %posttrans-skriptejä" + +#~ msgid "Package is not signed!" +#~ msgstr "Pakettia ei ole allekirjoitettu!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s ei kuulu jakeluversion päivitysasennuslähteeseen" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s on alempaa arkkitehtuuria" + +#~ msgid "problem with installed package %s" +#~ msgstr "virhe asennettaessa pakettia %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "Mikään ei tarjoa pyydettyä %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Oletko ottanut käyttöön kaikki pyydetyt asennuslähteet?" + +#~ msgid "package %s does not exist" +#~ msgstr "pakettia %s ei ole olemassa" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s on järjestelmän tarjoama ja sitä ei voi poistaa" + +#~ msgid "%s is not installable" +#~ msgstr "%s ei ole asennettavissa" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "mikään ei tarjoa %s, jota %s tarvitsee" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "Ei voida asentaa molempia %s ja %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s on ristiriidassa %s (%s) kanssa" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s vanhentaa %s (%s)" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "asennettu %s vanhentaa %s (%s)" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s on ristiriidassa itsensä kanssa (%s)" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s tarvitsee %s, mutta sen asentaminen ei onnistu" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "poista lukitus salliaksesi %s poiston" + +#~ msgid "do not install %s" +#~ msgstr "älä asenna %s" + +#~ msgid "keep %s" +#~ msgstr "pidä %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "poista lukitus asentaaksesi: %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "älä kysy asennettaessa paketteja, jotka tuo %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "älä kysy poistettaessa paketteja, jotka tuo %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "älä asenna uusinta %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "Pidä %s vaikka se on alempaa arkkitehtuuria" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "asenna %s vaikka se on alempaa arkkitehtuuria" + +#~ msgid "keep obsolete %s" +#~ msgstr "pidä vanhentunut %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "Asennetaan %s poisjätetystä asennuslähteestä" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "päivitetään vanhempaan %s -> %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "arkkitehtuurin vaihto %s -> %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "asenna %s (vaihtaa tarjoajaa)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "Korvataan %s -> %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "poista %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Lukitustiedoston avaaminen ei onnistu: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Jokin toinen ohjelma suorittaa tätä toimintoa." + +#~ msgid "Hal Exception" +#~ msgstr "Hal-poikkeus" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Tämä versio libzypp-kirjastosta on käännetty ilman HAL-tukea." + +#~ msgid "HalContext not connected" +#~ msgstr "Hal-yhteyden muodostus ei onnistunut" + +#~ msgid "HalDrive not initialized" +#~ msgstr "Hal-asemaa ei ole alustettu" + +#~ msgid "HalVolume not initialized" +#~ msgstr "Hal-taltioa ei alustettu" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "dbus-yhteyden luonti epäonnistui" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: libhal-yhteyttä ei voitu luoda" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: dbus-yhteyden asettaminen ei onnistu" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "HAL-yhteyden alustus ei onnistu. Varmista, että \"hald\" on käynnissä." + +#~ msgid "Not a CDROM drive" +#~ msgstr "Kohde ei ole CD-asema" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Mutex-määritteiden alustaminen ei onnistu" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Rekursiivisten mutex-määritteiden asetus ei onnistu" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Rekursiivisten mutex-määritteiden alustaminen ei onnistu" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Mutex-lukitus ei onnistu" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Mutex-lukituksen vapauttaminen ei onnistu" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Avaimen tuonti tiedostosta %s epäonnistui: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Julkisen avaimen %s poisto epäonnistui: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Levykuvatiedoston \"%s\" liitämiseen tarvittavaa loop-laitetta ei löydy" + +#~ msgid "do not keep %s installed" +#~ msgstr "älä pidä %s asennettuna" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Julkisen avaimen %s tuonti avainrenkaasta %s tiedostoon %s ei onnistu" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Lataajan (Metalink curl) alustus osoitteelle \"%s\" epäonnistui" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Latausvirhe (metalink curl) %s:\n" +#~ "Virhekoodi: %s\n" +#~ "Viesti: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Lataus keskeytyi %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Käyttäjä keskeytti latauksen" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Virhe asetettaessa lataajan (metalink curl) valintoja osoitteelle \"%s\"." + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Virhe ladattaessa %s osoitteesta %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia ja Montenegro" diff --git a/po/fr.po b/po/fr.po new file mode 100644 index 0000000..7a0ff4b --- /dev/null +++ b/po/fr.po @@ -0,0 +1,6178 @@ +# translation of zypp.fr.po to +# French message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002, 2003 SuSE Linux AG. +# Copyright (C) 2000, 2001 SuSE GmbH. +# +# +# +# Patricia Vaz , 2003. +# Francoise Lermen , 2000, 2001, 2002. +# Karine Nguyen , 2001. +# Guillaume GARDET , 2008, 2009, 2010. +# Rémy Marquis , 2008. +# Rémy Marquis , 2008. +# Guillaume GARDET , 2011, 2013, 2014, 2015. +# Antoine Belvire , 2015. +# +msgid "" +msgstr "" +"Project-Id-Version: zypp.fr\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-05-01 17:43+0000\n" +"Last-Translator: Sophie Leroy \n" +"Language-Team: French \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: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Pays inconnu : " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Pas de code" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorre" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Émirats arabes unis" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua-et-Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanie" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Arménie" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antilles néerlandaises" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarctique" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentine" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa américaines" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Autriche" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australie" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Îles Åland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaïdjan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnie-Herzégovine" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbade" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgique" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgarie" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahreïn" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Bénin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudes" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivie" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brésil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhoutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Île Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Biélorussie" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Îles Cocos (Keeling)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "République centrafricaine" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Suisse" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Cote d'Ivoire" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Îles Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chili" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Cameroun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Chine" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombie" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cap Vert" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Île Christmas" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Chypre" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "République Tchèque" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Allemagne" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danemark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominique" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "République Dominicaine" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algérie" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Équateur" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonie" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Égypte" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sahara Occidental" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Erythrée" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Espagne" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Éthiopie" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlande" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Îles Malouines (Falkland)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "États fédérés de Micronésie" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Îles Féroé" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "France" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "France métropolitaine" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Royaume-Uni" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenade" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Géorgie" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guyane française" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernesey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambie" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinée" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinée équatoriale" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grèce" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Géorgie du Sud et Îles Sandwich" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinée Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong-Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Îles Heard et Mcdonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croatie" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haïti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hongrie" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonésie" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlande" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israël" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Île de Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Inde" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Territoire britannique de l'océan Indien" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islande" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italie" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaïque" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordanie" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japon" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirghizistan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodge" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comores" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint-Kitts-et-Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Corée du Nord" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Corée du sud" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Koweït" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Îles Caïmans" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "République démocratique populaire du Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Liban" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Sainte-Lucie" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituanie" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Lettonie" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libye" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroc" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavie" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Monténégro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint-Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Îles Marshall" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macédoine" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Birmanie" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolie" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Îles Marianne du nord" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritanie" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malte" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Île Maurice" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldives" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexique" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaisie" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibie" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nouvelle Calédonie" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Île Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Pays-Bas" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norvège" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Népal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauruan" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nouvelle Zélande" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Pérou" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polynésie française" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papouasie Nouvelle Guinée" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Philippines" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Pologne" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint-Pierre-et-Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Porto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Territoire palestinien" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palaos" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Roumanie" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbie" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Fédération de Russie" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arabie Saoudite" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Îles Salomon" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Soudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suède" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapour" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sainte-Hélène" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovénie" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard-et-an Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovaquie" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "Saint-Marin" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Sénégal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalie" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tomé-et-Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syrie" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Îles Turks-et-Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tchad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Terres australes et antarctiques françaises" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thaïlande" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkménistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisie" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor oriental" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turquie" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinité-et-Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzanie" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraine" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Ouganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Petites Îles Situées Près Des États-Unis" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "États-Unis" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Ouzbékistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Saint-Siège (État de la Cité du Vatican)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint-Vincent-et-les Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Îles Vierges britanniques" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Îles Vierges américaines" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Viêt Nam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis et Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yémen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Afrique du Sud" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambie" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Fournit" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Nécessite au préalable" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Nécessite" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Conflits" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Rend obsolète" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recommande" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Suggère" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Améliore" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Complète" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Tentative d'importation d'une clé inexistante %s dans le porte-clé %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Impossible d'importer la clé." + +# TLABEL restore_2002_08_07_0216__88 +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Impossible de supprimer la clé." + +# TLABEL linuxrc_2002_03_29_0036__117 +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Fichier de signature %s introuvable" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Langue inconnue : " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhaze" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Aceh" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adygué" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-asiatiques (autres langues)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainou" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadien" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanais" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aléute" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Langues algonquines" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altaï du Sud" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharic" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Anglo-saxon (vers 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Langues apaches" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabe" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaïn" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonais" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Arménien" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucan" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Artificielles (autres langues)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamais" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturien" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Langues athapascanes" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Langues australiennes" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avar" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestique" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azéri" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Langues bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bachkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baloutchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinais" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basque" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltiques (autres langues)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Bedja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Biélorusse" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berbères (autres langues)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bichlamar" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Pied-noir" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantoues (autres langues)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosniaque" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Breton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonésie)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Bouriate" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugi" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgare" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birman" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Indiennes d'Amérique centrale (autres langues)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Caribe" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalan" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucasiennes (autres langues)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celtiques (autres langues)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tchétchène" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Djaghatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinois" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukais" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Jargon chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Slavon liturgique" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Tchouvache" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Langues chames" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Copte" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornique" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corse" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Créoles et pidgins anglais (autres)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Créoles et pidgins français (autres)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Créoles et pidgins portugais (autres)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tatar de Crimée" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Créoles et pidgins divers" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kachoube" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Couchitiques (autres langues)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tchèque" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danois" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Esclave (athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Maldivien" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidiennes (autres langues)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Bas-sorabe" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Douala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Néerlandais moyen (vers 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Hollandais" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dioula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Égyptien (ancien)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Élamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Anglais" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Anglais moyen (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Espéranto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonien" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Éwe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Éwondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Féroien" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fidjien" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Philippin" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finnois" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finno-ougriennes (autres langues)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Français" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Français moyen (vers 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Français ancien (842-vers 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frison" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Peul" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Frioulan" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germaniques (autres langues)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Géorgien" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Allemand" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Guèze" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Kiribati" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaélique" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandais" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galicien" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Allemand, moyen haut (vers 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Allemand, ancien haut (vers 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gond" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gothique" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grec ancien (jusqu'à 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grec moderne (après 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Goudjrati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haïtien" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Haoussa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaïen" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hébreu" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittite" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Haut-sorabe" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Hongrois" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandais" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Yi de Sichuan" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Ilocano" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Association pour une langue auxiliaire internationale)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indo-aryennes (autres langues)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonésien" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-europénnnes (autres langues)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingouche" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraniennes (autres langues)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Langues iroquoises" + +# TLABEL partitioning_2002_01_04_0147__180 +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italien" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanais" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonais" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judéo-persan" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judéo-arabe" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanouri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardien" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (autres langues)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanais" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Rwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghize" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Kom" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coréen" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosrae" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karatchai balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Krou" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Ovambo" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Koumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurde" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Judéo-espagnol" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latin" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letton" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghien" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limbourgeois" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituanien" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxembourgeois" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseño" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya et Tanzanie)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macédonien" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madourais" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshall" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makassar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingue" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Malayo-polynésiennes (autres langues)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathe" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masaï" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malais" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksa" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mendé" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandais moyen (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Micmac" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Langues diverses" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-khmer (autres langues)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgache" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltais" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Mandchou" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Langues Manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldave" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Multilingue" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Langues mounda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Muskogee" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandais" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marvari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Langues maya" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erza" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Langues indiennes d'Amérique du Nord" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitain" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele (Sud)" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele (Nord)" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Allemand, bas" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Népalais" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepalbhasha" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Nigéro-congolaises (autres langues)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuéen" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norvégien nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norvégien bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogaï" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norrois, ancien" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norvégien" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho du Nord" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Langues nubiennes" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari classique" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nkore" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzema" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (après 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwé" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Galla" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossète" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turc ottoman (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Langues otomangues" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papoues (autres langues)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampangan" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Perse, ancien (vers 600-400 av. J.-C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persan" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Philippines (autres langues)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Phénicien" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polonais" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpei" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugais" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prâkrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provençal ancien (jusqu'à 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pachto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotonga" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romanes (autres langues)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Rhéto-roman" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Tsigane" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Roumain" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russe" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Iakoute" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Indiennes d'Amérique du Sud (autres langues)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Langues salish" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritain" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santal" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbe" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilien" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Écossais" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croate" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkoupe" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Sémitiques (autres langues)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandais ancien (jusqu'à 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Langues des signes" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Chan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singhalais" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Langues sioux" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-tibétaines (autres langues)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slaves (autres langues)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovaque" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovène" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sami du Sud" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Sami du Nord" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Sami, autres langues" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Sami de Lule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Sami d'Inari" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoan" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Sami skolt" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdien" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho du Sud" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Espagnol" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sarde" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Sérère" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-sahariennes (autres langues)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Soundanais" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Soussou" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumérien" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Suédois" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syriaque" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitien" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Thaïts (autres langues)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamoul" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Télougou" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Temne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadjik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thaï" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibétain" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrigna" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamacheq" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tongan (îles Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmène" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turc" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaïques (autres langues)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Touva" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Oudmourte" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ougaritique" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Ouïtour" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainien" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Indéterminé" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Ourdou" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Ouszbek" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vaï" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamien" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapït" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Vote" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Langues wakashennes" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Gallois" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Langues sorables" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Wallon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmouk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapois" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Langues yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotèque" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zoulou" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Les actions suivantes seront exécutées :" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "n'expire pas" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "a expiré le : %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "expire le : %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(n'expire pas)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(EXPIRÉ)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(expire dans les 24h)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(expire dans %d jour)" +msgstr[1] "(expire dans %d jours)" + +# TLABEL printer_2002_08_07_0216__54 +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "inconnu" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "non pris en charge" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Niveau 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Niveau 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Niveau 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Contrat client additionnel nécessaire" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Obsolète et remplacé par un autre paquet" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "invalide" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Le niveau du support n'est pas spécifié" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Le fournisseur ne fournit pas de support." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"La détermination d'un problème, ce qui signifie un appui technique visant à " +"fournir les informations de compatibilité, l'assistance à l'installation, le " +"soutien à l'utilisation, la maintenance et le dépannage de base. Le Support " +"de Niveau 1 ne vise pas à corriger les erreurs et défauts du produit." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"L'isolation de problème, ce qui signifie un appui technique visant à " +"reproduire les problèmes du client, isoler le problème et fournir une " +"résolution pour les problèmes non résolus par le Support de Niveau 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"La résolution de problème, ce qui signifie un appui technique visant à " +"résoudre des problèmes complexes en engageant des ingénieurs dans la " +"résolution des défauts du produit qui ont été identifiés par le Support de " +"Niveau 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Un contrat client additionel est nécessaire pour obtenir du support." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"Le paquet est obsolète et a été remplacé par un nouveau paquet portant un " +"autre nom." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Option de support inconnue. La description n'est pas disponible" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"La gestion du système est verrouillée par l'application avec le pid %d " +"(%s).\n" +"Fermez cette application avant de réessayer." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Mode de correspondance '%s' inconnu" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Mode de correspondance '%s' inconnu pour le modèle '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Expression régulière '%s' invalide : regcomp a retourné %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Expression régulière '%s' invalide" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Authentification requise pour '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Une nouvelle tentative va être effectuée..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Abandon après %1% tentatives." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visitez SUSE Customer Center pour vérifier si votre enregistrement est " +"valide et n'a pas expiré." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visitez le Novell Customer Center pour vérifier que votre inscription est " +"valide et qu'elle n'a pas expiré." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Création d'un point d'attache : Impossible de trouver un répertoire pour " +"créer un point d'attache" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Veuillez d'abord installer le paquet 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Impossible de créer le répertoire de cache des métadonnées." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Erreur lors de la tentative de lecture depuis '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Impossible de créer %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Aucune métadonnée valide trouvée à l'URL spécifiée" +msgstr[1] "Aucune métadonnée valide trouvée aux URL spécifiées" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +# TLABEL restore_2002_08_07_0216__88 +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Échec de la mise en cache du dépôt (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Construction du cache du dépôt '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Impossible de créer le cache dans %s - pas d'autorisation en écriture." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Type de dépôt non pris en charge" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Ajout du dépôt '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nom du fichier de dépôt non valide sur '%s'" + +# TLABEL kinternet_2002_02_20_2255__39 +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Impossible d'ouvrir le fichier '%s' en écriture." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Erreur de lecture inconnue depuis '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Impossible de lire le répertoire de dépôt '%1%' : permission refusée" + +# TLABEL restore_2002_08_07_0216__88 +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Impossible de lire le dossier '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Impossible de lire le fichier de dépôt '%1%' : permission refusée" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Suppression du dépôt '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Impossible de déterminer l'emplacement de stockage du dépôt." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Impossible de supprimer '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Impossible de déterminer l'emplacement de stockage du service." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Service '%1%' inconnu : suppression du dépôt de service orphelin '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "L'alias d'un dépôt ne peut pas commencer par un point." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "L'alias d'un service ne peut pas commencer par un point." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Pas de digest pour le fichier %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Digest %s inconnu pour le fichier %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "La vérification du digest a échoué pour le fichier '%s'" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Le fichier '%s' n'est pas signé. Continuer ?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Le fichier '%s' du dépôt '%s' n'est pas signé. Continuer ?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" +"Voulez-vous rejeter la clé, l'approuver temporairement ou l'approuver " +"toujours ?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Nom de la clé : %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "%1% nouvelle clé de signature de paquet reçue du dépôt \"%2%\" :" +msgstr[1] "%1% nouvelles clés de signature de paquet reçues du dépôt \"%2%\" :" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "La vérification de la signature a échoué pour le fichier '%1%'." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"La vérification de la signature a échoué pour le fichier '%1%' du dépôt " +"'%2%'." + +# internal key used: Ok +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Continuer ?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Le fichier '%s' est signé avec une clé inconnue '%s'. Continuer ?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Le fichier '%s' du dépôt '%s' est signé avec une clé inconnue '%s'. " +"Continuer ?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Le dépôt %1% ne définie pas d'URL 'gpgkey=' additionnelles." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Recherche de la clé gpg %1% dans le dépôt %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Recherche de la clé gpg %1% dans le cache %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "L'attribut requis '%s' est manquant." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Au moins un des attributs '%s' ou '%s' est requis." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Échec de la vérification de la signature" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Le paquet %s semble avoir été corrompu durant le transfert. Souhaitez-vous " +"essayer à nouveau de le récupérer ?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Impossible de fournir le paquet %s. Souhaitez-vous essayer à nouveau de le " +"récupérer ?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "La vérification d'applydeltarpm a échoué." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm a échoué." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Le plugin de service ne supporte pas la modification d'attribut." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Impossible de fournir '%s' à partir du dépôt '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Pas d'URL dans le dépôt." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Le media attendu %1%/%2% identifié par le fichier '%3%' avec le contenu :" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Le fichier %1%\n" +" du paquet\n" +" %2%\n" +" est en conflit avec le fichier du paquet\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Le fichier %1%\n" +" du paquet\n" +" %2%\n" +" est en conflit avec le fichier de l'installation de\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Le fichier %1%\n" +" de l'installation de\n" +" %2%\n" +" est en conflit avec le fichier du paquet\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Le fichier %1%\n" +" de l'installation de\n" +" %2%\n" +" est en conflit avec le fichier de l'installation de\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Le fichier %1%\n" +" du paquet\n" +" %2%\n" +" est en conflit avec le fichier\n" +" %3%\n" +" du paquet\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Le fichier %1%\n" +" du paquet\n" +" %2%\n" +" est en conflit avec le fichier\n" +" %3%\n" +" de l'installation de\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Le fichier %1%\n" +" de l'installation de\n" +" %2%\n" +" est en conflit avec le fichier\n" +" %3%\n" +" du paquet\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Le fichier %1%\n" +" de l'installation de\n" +" %2%\n" +" est en conflit avec le fichier\n" +" %3%\n" +" de l'installation de\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Impossible de créer la réserve sat." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "casser %s en ignorant certaines de ses dépendances" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "Ignorer généralement certaines dépendances" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"l'élément %1% installé n'appartient à aucun dépôt de mise à niveau de la " +"distribution et doit être remplacé" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" +"l'élément %1% à installer n'appartient à aucun dépôt de mise à niveau de la " +"distribution" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "l'élément %1% installé présente une architecture inférieure" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "l'élément %1% à installer présente une architecture inférieure" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problème avec l'élément %1% installé" + +# TLABEL kinternet_2002_02_20_2255__29 +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "requêtes conflictuelles" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "Problèmes de dépendance" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "rien ne fournit le/la '%1%' demandé(e)" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Avez-vous activé tous les dépôts requis ?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "le paquetage demandé %1% n'existe pas" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "Requête non supportée" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' est fourni par le système et ne peut pas être effacé" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% n'est pas installable" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "rien ne fournit '%1%' qui est nécessaire pour l'élément %2% installé" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" +"rien ne fournit '%1%' qui est nécessaire pour l'élément %2% à installer" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "impossible d'installer à la fois %1% et %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"l'élément %1% installé est en conflit avec '%2%' fourni par l'élément %3% " +"installé" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"l'élément %1% installé est en conflit avec '%2%' fourni par l'élément %3% à " +"installer" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"l'élément %1% à installer est en conflit avec '%2%' fourni par l'élément %3% " +"installé" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"l'élément %1% à installer est en conflit avec '%2%' fourni par l'élément %3% " +"à installer" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"l'élément %1% installé rend obsolète '%2%' fourni par l'élément %3% installé" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"l'élément %1% installé rend obsolète '%2%' fourni par l'élément %3% à " +"installer" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"l'élément %1% à installer rend obsolète '%2%' fourni par l'élément %3% " +"installé" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"l'élément %1% à installer rend obsolète '%2%' fourni par l'élément %3% à " +"installer" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "l'élément %1% installé est en conflit avec '%2%' fourni par lui-même" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"l'élément %1% à installer est en conflit avec '%2%' fourni par lui-même" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"l'élément %1% installé nécessite '%2%', mais cette exigence ne peut pas être " +"remplie" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"l'élement %1% à installer nécessite '%2%', mais cette exigence ne peut pas " +"être remplie" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "fournisseurs supprimés : " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"fournisseurs non installables : " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "fournisseurs non installables : " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% n'est pas totalement intégré dans %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Généralement, vous voulez conserver le PTF et choisir de ne pas installer " +"les correctifs de maintenance." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"La suppression du PTF installé %1% dans ce contexte supprimera (plutôt que " +"de remplacer !) les paquets PTF inclus également." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"Le PTF doit être supprimé en appelant '%1%'. Cela mettra à jour les paquets " +"PTF inclus plutôt que de les supprimer." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" +"Généralement, vous souhaitez conserver le PTF ou choisissez d'annuler " +"l'action." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Le %1% installé bloque l'action souhaitée." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" +"En général, vous souhaitez conserver les correctifs temporaires du programme " +"et choisissez d'annuler l'action." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "supprimer le verrouillage pour permettre la suppression de %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "ne pas installer %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "conserver %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "supprimer le verrouillage pour autoriser l'installation de %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Cette requête va casser votre système !" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorer l'avertissement d'un système cassé" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "ne pas demander d'installer un élément résolvable fournissant %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" +"ne pas demander de supprimer tous les éléments résolvables fournissant %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "ne pas installer la dernière version de %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "conserver %1% malgré l'architecture inférieure" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "installer %1% malgré l'architecture inférieure" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "conserver l'élément %1% obsolète" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "installer %1% à partir du dépôt exclu" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "installer %1% bien qu'il ait été retiré" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "autoriser l'installation du PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "installer %1% bien qu'il ait été placé en liste noire" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "rétrogradation de %1% à %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "modification de l'architecture de %1% vers %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"installer %1% (avec le changement de fournisseur)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"installer %1% du fournisseur %2%\n" +"en remplaçant %3% du fournisseur %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "remplacement de %1% par %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "désinstallation de %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Exécution des scripts ultérieurs à la transaction" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Exécution du script %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Sortie du script %1% :" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "L'installation a été abandonnée comme demandé." + +# TLABEL online_update_2002_01_04_0147__113 +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " exécuté" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " échec de l'exécution" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s déjà exécuté en tant que %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " exécution annulée lors de l'abandon" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Erreur lors de l'envoi de la notification de mise à jour par message." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nouveau message de mise à jour" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Signal reçu :\"%1% (%2%)\". Pour garantir la cohérence du système, il n'est " +"pas possible d'annuler une transaction rpm en cours d'exécution." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" +"L'exécution de la transaction a échoué en raison des problèmes suivants :" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Échec RPM : " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Impossible d'importer la clé publique %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Impossible de supprimer la clé publique %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "L'en-tête du paquet n'est pas signé !" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Le contenu du paquet n'est pas signé !" + +# TLABEL sw_single_2002_01_04_0147__11 +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Fichiers de configuration modifiés pour %s :" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm a enregistré %s sous le nom de %s, mais il a été impossible de " +"déterminer la différence" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm a enregistré %s sous %s.\n" +"Voici les 25 premières lignes qui diffèrent :\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm a créé %s sous le nom de %s, mais il a été impossible de déterminer la " +"différence" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm a créé %s sous le nom de %s.\n" +"Voici les 25 premières lignes qui diffèrent :\n" + +# TLABEL firewall_2002_03_14_2340__51 +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Sortie rpm supplémentaire" + +# TLABEL backup_2002_03_14_2340__102 +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "sauvegarde %s créée" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "La signature est correcte" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Type de signature inconnu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "La signature n'est pas vérifiée" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "La signature est correcte mais la clé n'est pas certifiée" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "La clé publique des signatures n'est pas disponible" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Le fichier n'existe pas ou la signature ne peut pas être vérifiée" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Le fichier n'est pas signé" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Type '%s' douteux pour %u octet(s) sur la somme de contrôle '%s'" + +# TLABEL backup_2002_03_14_2340__125 +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Impossible d'ouvrir pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Impossible d'ouvrir le pipe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Chaîne de requête d'URL LDAP non valide" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Paramètre de requête d'URL LDAP '%s' non valide" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Impossible de cloner l'objet d'URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Référence d'objet d'URL vide non valide" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Impossible d'analyser les composants de l'URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historique :" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Le schéma d'URL n'autorise pas de %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Composant '%s' non valide '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Composant %s non valide" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Analyse de la chaîne de requête non prise en charge pour cette URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Le schéma d'URL est un composant requis" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Schéma d'URL '%s' non valide" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Le schéma d'URL n'autorise pas de nom d'utilisateur" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Le schéma d'URL n'autorise pas de mot de passe" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Le schéma d'URL nécessite un composant d'hôte" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Le schéma d'URL n'autorise pas de composant d'hôte" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Composant d'hôte non valide '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Le schéma d'URL n'autorise pas de port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Composant de port non valide '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Le schéma d'URL requiert un nom de chemin" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Chemin relatif non autorisé en présence d'une autorité" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "La chaîne codée contient un octet NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" +"Caractère séparateur de division non valide pour l'ensemble de paramètres" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" +"Caractère séparateur de division non valide pour le mappage de paramètres" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" +"Caractère séparateur de catégorie de jonction non valide pour l'ensemble de " +"paramètres" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "La commande s'est terminée avec l'état %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "La commande a été supprimée par le signal %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "La commande s'est terminée à cause d'une erreur inconnue." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Argument spawn fournis non valides." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Impossible de créer un pipe de contrôle." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Impossible d'effectuer une commande chroot vers '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Impossible d'appliquer la commande chdir vers '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" +"Impossible d'appliquer la commande chdir à '%s' dans chroot '%s' ('%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Impossible d'exécuter '%s' (%s)." + +# TLABEL printconf_2002_03_14_2340__110 +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Impossible d'exécuter une commande fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Impossible d'exécuter '%s'. La commande chdir a échoué (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Impossible d'exécuter '%s'. La commande chroot a échoué (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Impossible d'exécuter '%s'. La commande exec a échoué (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Impossible d'exécuter '%s'. Erreur inattendue." + +# TLABEL restore_2002_08_07_0216__88 +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Impossible de monter %s sur %s" + +# TLABEL linuxrc_2002_03_29_0036__22 +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Impossible de démonter %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Mauvais nom de fichier : %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Le medium ne s'est pas ouvert lors de l'action '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Fichier '%s' introuvable sur le medium '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Impossible d'écrire dans le fichier '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Le medium n'est pas attaché" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Mauvais point d'attache du support" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Échec de l'initialisation du téléchargement (curl) pour '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Exception système '%s' sur le medium '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Le chemin '%s' sur le medium '%s' n'est pas un fichier." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Le chemin '%s' sur le medium '%s' n'est pas un répertoire." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI malformé" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nom d'hôte vide dans l'URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Système de fichiers vide dans l'URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destination vide dans l'URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Schéma URI non pris en charge dans '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Opération non prise en charge par le medium" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Erreur de téléchargement (curl) pour '%s' :\n" +"Code d'erreur : %s\n" +"Message d'erreur : %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Une erreur s'est produite lors de la configuration des options de " +"téléchargement (curl) pour '%s' :" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "La source de supports '%s' ne contient pas le support désiré" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Le medium '%s' est utilisé par une autre instance" + +# TLABEL profile-manager_2002_08_07_0216__9 +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Impossible d'éjecter un support" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Impossible d'éjecter le support '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Autorisation d'accès à '%s' refusée." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Temps maximal dépassé lors de l'accès à '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"Les données téléchargées dépassent la taille de fichier attendue '%s' de " +"'%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "L'emplacement '%s' est temporairement inaccessible." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Problème de certificat SSL, vérifiez que le certificat CA est OK pour '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Aucune ressource libre disponible pour attacher le support." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Méthode d'authentification HTTP '%s' non prise en charge" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Erreur de téléchargement (curl) pour « %s » :\n" +"Code d'erreur : %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Erreur de téléchargement (curl) pour « %s » :\n" +"Impossible d'obtenir une réponse HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Oui" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Non" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Note :" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Avertissement :" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Erreur :" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "fait" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "attention" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "erreur" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Avertissement : " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Récupération :" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "Démarrage" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "non trouvé" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Aucune aide disponible pour cette invite." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "Aucune aide disponible pour cette option" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "affiche toutes les options" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "oui" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "non" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Exécution du script %%posttrans « %1% »" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Exécution des scripts %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "Le paquet n'est pas signé !" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s n'appartient à aucun dépôt de mise à niveau de la distribution" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s a une architecture inférieure" + +#~ msgid "problem with installed package %s" +#~ msgstr "problème avec le paquet installé %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "rien ne fournit %s qui est requis" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Avez-vous activé tous les dépôts requis ?" + +#~ msgid "package %s does not exist" +#~ msgstr "Le paquet %s n'existe pas" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s est fourni par le système et ne peut être supprimé" + +# TLABEL partitioning_2002_01_04_0147__180 +#~ msgid "%s is not installable" +#~ msgstr "%s n'est pas installable" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "rien ne fournit %s, qui est requis par %s" + +# TLABEL partitioning_2002_01_04_0147__180 +#~ msgid "cannot install both %s and %s" +#~ msgstr "impossible d'installer simultanément %s et %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s est en conflit avec %s fourni par %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s rend obsolète %s fourni par %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s installé rend obsolète %s fourni par %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "L'élément %s est en conflit avec %s fourni par lui même" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s requiert %s, mais cette dépendance ne peut pas être fournie" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "enlever le verrou pour permettre la suppression de %s" + +# TLABEL partitioning_2002_01_04_0147__180 +#~ msgid "do not install %s" +#~ msgstr "ne pas installer %s" + +#~ msgid "keep %s" +#~ msgstr "conserver %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "enlever le verrou pour permettre l'installation de %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "ne pas demander d'installer un élément résoluble fournissant %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "" +#~ "ne pas demander de supprimer tous les éléments résolubles fournissant %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "ne pas installer une version plus récente de %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "conserver %s en dépit de l'architecture inférieure" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "installer %s en dépit de l'architecture inférieure" + +#~ msgid "keep obsolete %s" +#~ msgstr "conserver %s obsolète" + +#~ msgid "install %s from excluded repository" +#~ msgstr "installer %s depuis le dépôt exclu" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "installation d'une version moins récente de %s vers %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "changement de l'architecture %s à %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "installer %s (avec changement de fournisseur)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "remplacement de %s par %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "désinstallation de %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Impossible d'ouvrir le fichier verrouillé : %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Cette action est actuellement déjà exécutée par un autre programme." + +#~ msgid "Hal Exception" +#~ msgstr "Exception Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Désolé, cette version de libzypp a été construite sans la prise en charge " +#~ "HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext non connecté" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive non initialisé" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume non initialisé" + +# TLABEL linuxrc_2002_03_29_0036__141 +#~ msgid "Unable to create dbus connection" +#~ msgstr "Impossible de créer la connexion dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new : impossible de créer le contexte libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "libhal_set_dbus_connection : impossible de définir la connexion dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Impossible d'initialiser le contexte HAL -- hald fonctionne-t-il ?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Pas un lecteur de CD-ROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Impossible d'initialiser les attributs mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Impossible de définir l'attribut mutex récursif" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Impossible d'initialiser l'attribut mutex récursif" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Impossible d'acquérir le verrouillage mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Impossible de libérer le verrouillage mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Impossible d'importer la clé publique du fichier %s : %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Impossible de supprimer la clé publique %s : %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Impossible de trouver un périphérique de boucle pour monter le fichier " +#~ "image depuis '%s'" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "Ignorer généralement certaines dépendances" + +# TLABEL partitioning_2002_01_04_0147__180 +#~ msgid "do not forbid installation of %s" +#~ msgstr "ne pas interdire l'installation de %s" + +# TLABEL partitioning_2002_01_04_0147__180 +#~ msgid "do not keep %s installed" +#~ msgstr "ne pas laisser %s installé" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "صربيا ومونتنيجرو" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "خيار list غير معروف" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "تعذر حل التبعيات" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Impossible de créer la clé publiqe %s du porteclé %s dans le fichier %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "Essayé d'importer la clé non existante %s dans le porteclé %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Impossible de chdir à '/' dans un chroot (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "" +#~ "Échec de l'initialisation du téléchagement (Metalink curl) pour '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Erreur de téléchargement (metalink curl) pour '%s':\n" +#~ "Code erreur: %s\n" +#~ "Message erreur: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Téléchargement interrompu à %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Téléchargement interrompu par l'utilisateur" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Erreur survenue pendant la définition des options de téléchargement " +#~ "(metalink curl) pour '%s':" + +# TLABEL restore_2002_08_07_0216__88 +#~ msgid "Failed to download %s from %s" +#~ msgstr "Impossible de télécharger %s depuis %s" + +#~ msgid "Valid metadata not found at specified URL(s)" +#~ msgstr "Meta-donnée valide non trouvée à l'URL spécifiée" diff --git a/po/gl.po b/po/gl.po new file mode 100644 index 0000000..746eda9 --- /dev/null +++ b/po/gl.po @@ -0,0 +1,6412 @@ +# Galician translation of zypp +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2000, 2001 SuSE GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# +# +# Proxecto Trasno - Adaptación do software libre á lingua galega: Se desexas +# colaborar connosco, podes atopar máis información en +# +# Jesús Bravo Álvarez , 2000. +# Leandro Regueiro , 2008. +# Manuel A. Vazquez , 2010, 2011, 2013. +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2020-06-29 19:45+0000\n" +"Last-Translator: Manuel Vazquez \n" +"Language-Team: Galician \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: Weblate 3.6.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "País descoñecido: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Sen código" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +# US +# fuzzy +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Emiratos Árabes Unidos" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistán" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antiga e Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguila" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +# AM +# fuzzy +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antillas Neerlandesas" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antártida" + +# AR +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Arxentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Americana" + +# AT +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +# AU +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +# CU +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# FO +# fuzzy +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Illas Aland" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Acerbaixán" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia e Hercegovina" + +# BB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +# BD +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +# BE +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Bélxica" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +# BG +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +# BH +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benín" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudas" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +# BO +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasil" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +# BH +# fuzzy +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bután" + +# FO +# fuzzy +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Illa Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +# BY +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "República de Belarús" + +# BZ +# fuzzy +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +# CA +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canadá" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Illas de Cocos" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +# CF +# fuzzy +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "República Centroafricana" + +# CH +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Suíza" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Costa de Marfil" + +# FO +# fuzzy +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Illas Cook" + +# CL +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camerún" + +# CN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +# CO +# fuzzy +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cabo Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Illa de Nadal" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Chipre" + +# CZ +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "República Checa" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Alemaña" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Xibutí" + +# DK +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dinamarca" + +# DM +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +# DO +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "República Dominicana" + +# DZ +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alxeria" + +# EC +# fuzzy +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +# EE +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +# EG +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Exipto" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sáhara Occidental" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +# ES +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "España" + +# ET +# fuzzy +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Estonia" + +# FI +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlandia" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fixi" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Illas Falkland (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Estados Federados de Micronesia" + +# FO +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Illas Feroe" + +# FR +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francia" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Francia Metropolitana" + +# GH +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabón" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Reino Unido" + +# GD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Granada" + +# GE +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Xeorxia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Güiana Francesa" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +# fuzzy +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "China" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Xibraltar" + +# GL +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grenlandia" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +# GU +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadalupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinea Ecuatorial" + +# GR +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grecia" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Illas Xeorxia do Sur e Sandwich do Sur" + +# GT +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +# GU +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea Bissau" + +# GH +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Güiana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Illa Heard e Illas McDonald" + +# HN +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +# HR +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croacia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haití" + +# HU +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hungría" + +# ID +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +# IE +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanda" + +# IL +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Illa de Man" + +# IN +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Territorios británicos no Océano Índico" + +# IQ +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraq" + +# IR +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irán" + +# IS +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islandia" + +# IT +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +# JM +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Xamaica" + +# JO +# fuzzy +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Xordania" + +# JP +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Xapón" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +# KZ +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirguisistán" + +# KH +# fuzzy +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Camboxa" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comores" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts e Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Corea do Norte" + +# ZA +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Corea do Sur" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +# FO +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Illas Caimán" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Casaquistán" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "República Popular Democrática de Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Líbano" + +# LC +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Santa Lucía" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesoto" + +# LT +# fuzzy +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituania" + +# LU +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburgo" + +# LV +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letonia" + +# LR +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marrocos" + +# MO +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Mónaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavia" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "San Martín" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +# FO +# fuzzy +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Illas Marshall" + +# MK +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Malí" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Birmania" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +# MO +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macau" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Illas Marianas do Norte" + +# MU +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinica" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +# MT +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauricio" + +# MV +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldivas" + +# MW +# fuzzy +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Kanu" + +# MX +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "México" + +# MY +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaisia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +# GM +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nova Caledonia" + +# NG +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Níxer" + +# FO +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Illa de Norfolk" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nixeria" + +# NI +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +# NL +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Países Baixos" + +# NO +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noruega" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +# NZ +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nova Celandia" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omán" + +# PA +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panamá" + +# PE +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Perú" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinesia Francesa" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papúa-Nova Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipinas" + +# TJ +# fuzzy +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Paquistán" + +# PL +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polonia" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "San Pedro e Miguelón" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Porto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Territorios Palestinos" + +# PT +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +# PW +# fuzzy +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Paraguai" + +# PY +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguai" + +# QA +# fuzzy +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunión" + +# RO +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romanía" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Federación Rusa" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arabia Saudita" + +# FO +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Illas Salomón" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seicheles" + +# SD +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudán" + +# SE +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suecia" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Santa Helena" + +# SI +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Eslovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard e Jan Mayen" + +# SK +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Eslovaquia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Serra Leona" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +# SY +# fuzzy +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "San Tomé e Príncipe" + +# SV +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "O Salvador" + +# SY +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Siria" + +# SZ +# fuzzy +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Suacilandia" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Illas Turcos e Caicos" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Territorios Franceses do Sur" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +# TH +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tailandia" + +# TJ +# fuzzy +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Taiwán" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Toquelau" + +# TJ +# fuzzy +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistán" + +# TN +# fuzzy +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Rusia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor Leste" + +# TR +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turquía" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trindade e Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +# TW +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwán" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +# UA +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ucraína" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +# fuzzy +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Estados Unidos de América" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Estados Unidos de América" + +# UY +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguai" + +# TJ +# fuzzy +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Usbekistán" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Santa Sede (Cidade Estado do Vaticano)" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "San Vicente e Granadinas" + +# VE +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# VI +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Illas Virxes Británicas" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Illas Virxes Estadounidenses" + +# VN +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis e Futuna" + +# KH +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Iemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +# ZA +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Suráfrica" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Cimbabue" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Proporciona" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Requisitos previos" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Require" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Conflitos" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Desactualizados" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recomenda" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Suxire" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Mellora" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Suplementos" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Tentouse importar unha chave que non existe %s para o chaveiro %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Erro ao importar a chave." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Fallo ao eliminar a chave." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Non se atopou o ficheiro da sinatura %s" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Lingua descoñecida: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +# AZ +# fuzzy +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abxasio" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinés" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-asiáticas (outras)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadian" + +# AZ +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanés" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutiano" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Linguas Algonquinas" + +# ZA +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altai do Sur" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amhárico" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Anglo-Saxón (450-110 d.c)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Linguas Apache" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Árabe" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Arameo" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonés" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armenio" + +# MR +# fuzzy +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucano" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Artificiais (outras)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Asamés" + +# AT +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturiano" + +# AU +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Linguas athapascanas" + +# AU +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Linguas australianas" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avaric" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +# MM +# fuzzy +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aimará" + +# AZ +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Acerí" + +# CA +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Linguas Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkirés" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +# GM +# fuzzy +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinés" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Éuscaro" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Bálticas (Outras)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +# BY +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorruso" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +# BZ +# fuzzy +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengalí" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Bereber (Outras )" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +# BH +# fuzzy +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantú (Outras)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnio" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretón" + +# ID +# fuzzy +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesia)" + +# BG +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginés" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Búlgaro" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birmano" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +# TD +# fuzzy +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Indíxenas Centroamericanas (Outras)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Caribe" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalán" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucásicas (Outras)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celtas (Outras)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +# CN +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Checheno" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinés" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Xerga Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Eslavo eclesiástico" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheién" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Linguas Chamic" + +# HR +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Copto" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Córnico" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corso" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creoles e Pidgin, baseados no Inglés (Outras)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creoles e Pidgin, baseadas no Francés (Outras)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creoles e Pidgin, baseadas no Portugués (Other)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tártaro da Crimea" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creoles e Pidgin (Outras)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Casubio" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushiticas (Outras)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Checo" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dinamarqués" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +# DM +# fuzzy +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidicas (Outras)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Baixo Sorbio" + +# PW +# fuzzy +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Neerlandés Medio (1050-1350 d.c)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Holandés" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Exipto (Antigo)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Baixo Sorbio" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inglés" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Anglo Saxón Medio (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonio" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Feroés" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +# FI +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fixiano" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finlandés" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fino-Húngaras (outras)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francés" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francés Medio ( 1400-1600 d.c)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francés Antigo (842-1400 d.c)" + +# FR +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisio" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +# FI +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friuliano" + +# GU +# fuzzy +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +# GH +# fuzzy +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Xermánicas (Outras)" + +# GE +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Xeorxiano" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Alemán" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertés" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaélico" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandés" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galego" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Alemán, Medio Alto (1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Alemán, Antigo Alto (750-1500)" + +# IN +# fuzzy +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gótico" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grego Antigo (ata 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grego Moderno (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guaraní" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Guxarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitiano" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiiano" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebreo" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +# IN +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittite" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Alto Sórabo" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Húngaro" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandés" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +# LT +# fuzzy +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingua" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Asociación por unha Lingua Auxiliar Internacional)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Índicas (Outras)" + +# ID +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesio" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-Europeas (Outras)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +# IN +# fuzzy +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iranianas (Outras)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Linguas Iroquesas" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiano" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Xavanés" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Xaponés" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Xudeu-Persas" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Xudeo-Árabe" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +# BH +# fuzzy +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Groenlandés" + +# GM +# fuzzy +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +# CA +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kanada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Cachemirés" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +# MW +# fuzzy +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazaxio" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardiano" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (Outras)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanese" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kiniarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreano" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +# PA +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Curdo" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +# UG +# fuzzy +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +# GM +# fuzzy +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +# LV +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latín" + +# LV +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letón" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezguí" + +# LU +# fuzzy +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgués" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituano" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +# LU +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgués" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +# GH +# fuzzy +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +# SD +# fuzzy +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya e Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedonio" + +# MV +# fuzzy +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurese" + +# MW +# fuzzy +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marsellés" + +# ML +# fuzzy +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +# MY +# fuzzy +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +# MY +# fuzzy +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maorí" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronésicas (Outras)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +# MT +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malaio" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +# MM +# fuzzy +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Gaélico Irlandés, Medio (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Linguas varias" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (Outras)" + +# MY +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgaxe" + +# MV +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltés" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchú" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Linguas Manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +# BO +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavo" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Linguas múltiples" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Linguas Munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +# FM +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandés" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Linguas Maias" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuátl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Indíxenas Norteamericanas" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitano" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaxo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, Sur" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, Norte" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Baixo Alemán" + +# ML +# fuzzy +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalí" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Bhasa Nepalí" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanianas (Outras)" + +# NG +# fuzzy +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Noruegués Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Noruegués Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Nórdico Antigo" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Noruegués" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho Norte" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Linguas Nubias" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newarí Clásico" + +# CL +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitano (post 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Oseto" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turco, Otomano (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Linguas Otomi" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Pupuaenses (Outras)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +# PW +# fuzzy +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "1Pahlavi" + +# PY +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +# PA +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +# PW +# fuzzy +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persa Antigo (ca 600-400 B.C)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persa" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipinas (Outras)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenicio" + +# ML +# fuzzy +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polaco" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugués" + +# AU +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Linguas Pakrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provenzal Antigo (Ata 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +# TJ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +# JP +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Románicas, Outras Linguas" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Retorrománico" + +# RO +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romanés" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romanés" + +# IN +# fuzzy +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ruso" + +# CA +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +# SD +# fuzzy +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Indíxenas Sudamericanas (Outras)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Linguas Salish" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Amárico Samaritano" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sánscrito" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbio" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliano" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Escocés" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croata" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitas (Outras)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Gaélico Irlandés Antigo (ata o 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Linguas de Signos" + +# SD +# fuzzy +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Linguas Siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetanas (Outras)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Eslavas (Outras)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Eslovaco" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Esloveno" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sami Sur" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Sami Norte" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Sami, Outras Linguas" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Sami Lule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Sami Inari" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoano" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Sami Skolt" + +# SI +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +# SD +# fuzzy +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +# SO +# fuzzy +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalí" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho do sur" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Español" + +# MR +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardo" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo- Saharianas (Outras)" + +# ES +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +# SD +# fuzzy +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanés" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerio" + +# SZ +# fuzzy +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Suaxili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Sueco" + +# SY +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Sirio" + +# TW +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitiano" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (Outras)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +# QA +# fuzzy +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tártaro" + +# BE +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +# TJ +# fuzzy +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Taxiko" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalo" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tailandés" + +# TW +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetano" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +# NG +# fuzzy +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinia" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Illas Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +# TW +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +# EE +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +# TR +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turcomano" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Linguas Tupí" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turco" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaicas (Outras)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +# TN +# fuzzy +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvinian" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugarítico" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uigur" + +# UA +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ucraíno" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Non determinado" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Usbeco" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +# VN +# fuzzy +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamita" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Linguas Wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +# PY +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Galés" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Linguas Sorbias" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Valón" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Xidish" + +# CU +# fuzzy +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Ioruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Linguas Yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapoteca" + +# GD +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulú" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuñi" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Realizaranse as seguintes accións:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "non caduca" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "caducado: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "caduca: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(non caduca)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(CADUCADO)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(caduca dentro de 24h)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(caduca dentro de %d día)" +msgstr[1] "(caduca dentro de %d días)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "descoñecido" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "non soportado" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Nivel 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Nivel 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Nivel 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Contrato adicional de cliente necesario" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "incorrecto" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "O nivel de soporte non está especificado" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "O fabricante non fornece soporte." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Determinación do problema, o que significa soporte técnico designado para " +"prover información de compatibilidade, asistencia de instalación, soporte de " +"uso, mantemento sobre a marcha e solucións básicas. Nivel 1 de soporte está " +"pensado para corrixir erros por defectos do produto." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Illamento do problema, o que significa soporte técnico designado para " +"duplicar os problemas do cliente, illar a área problemática e prover unha " +"solución por problemas non resoltos polo Nivel 1 de soporte." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Resolución de problemas, significa soporte técnico designado para resolver " +"problemas complexos ao utilizar enxeñaría na resolución de produtos " +"defectuosos identificados polo Nivel 2 de soporte." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Un contrato adicional co cliente é necesario para recibir soporte." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Opción de soporte descoñecida. Descrición non dispoñible" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"A xestión do sistema está bloqueada polo aplicativo con pid %d (%s).\n" +"Peche este aplicativo antes de tentalo de novo." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Modo de coincidencias '%s' descoñecido" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Modo de coincidencias '%s' descoñecido para o patrón '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Expresión regular '%s' incorrecta: regcomp devolveu %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Expresión regular '%s' incorrecta" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autenticación necesaria para '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visite o Centro de servizos ao cliente de SUSE para comprobar se o seu " +"rexistro é correcto e non caducou." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visite o Novell Customer Center para verificar se o seu rexistro é válido e " +"non caducou." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Crear punto de inserción: non se atopa un directorio non que se poida " +"escribir e anexar o punto" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Instale primeiro o paquete 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Non se pode crear o directorio da caché de metadatos." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Erro ao ler desde '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Non se pode crear '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Metadatos válidos non atopados no URL especificado" +msgstr[1] "Metadatos válidos non atopados nos URLs especificados" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Fallo na caché do repositorio (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Construíndo a caché do repositorio '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Non se pode crear a caché en %s - non hai permisos de escritura." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Repositorio" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Engadindo o repositorio '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nome de ficheiro do repositorio incorrecto en '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Non se puido abrir '%s' para escribir." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Erro descoñecido ao ler desde '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Non foi posíbel ler o directorio do repositorio %1%: permiso denegado" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Erro ao ler o directorio '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Non foi posíbel ler o ficheiro de repositorio '%1%': permiso denegado" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Eliminando o repositorio '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Non se pode saber onde se atopa almacenado o repositorio." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Non se pode borrar '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Non se pode saber onde se atopa almacenado o servizo." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Servizo descoñecido de '%1%': eliminando o servizo orfo do repositorio '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "O alias do repositorio non pode comezar cun punto." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "O alias do servizo non pode comezar cun punto." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Desexa continuar?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "O repositorio %1% non ten definida URLs adicionais nos 'gpgkey='." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Buscando a chave gpg coa ID %1% no repositorio %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Buscando a chave gpg coa ID %1% no caché %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Falta o atributo requirido '%s'." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Necesítanse un ou ambos os dous atributos '%s' ou '%s'." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Fallou a verificación da sinatura" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"O paquete %s semella que se danou durante a transferencia. Quéreo volver " +"obter?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Non se puido fornecer o paquete %s. Quéreo volver obter?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "fallou na verificación de applydeltarpm." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "fallou applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "O engadido do servizo non soporta os cambios nos atributos." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Non se pode fornecer o ficheiro '%s' desde o repositorio '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Non hai ningún enderezo url no repositorio." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"O ficheiro %1%\n" +" do paquete\n" +" %2%\n" +" entra en conflito cun ficheiro do paquete\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"O ficheiro %1%\n" +" do paquete\n" +" %2%\n" +" entra en conflito cun ficheiro da instalación de\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"O ficheiro %1%\n" +" da instalación de\n" +" %2%\n" +" entra en conflito cun ficheiro do paquete\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"O ficheiro %1%\n" +" da instalación de\n" +" %2%\n" +" entra en conflito cun ficheiro da instalación de\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"O ficheiro %1%\n" +" do paquete\n" +" %2%\n" +" entra en conflito co ficheiro\n" +" %3%\n" +" do paquete\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"O ficheiro %1%\n" +" do paquete\n" +" %2%\n" +" entra en conflito co ficheiro\n" +" %3%\n" +" da instalación de\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"O ficheiro %1%\n" +" da instalación de\n" +" %2%\n" +" entra en conflito co ficheiro\n" +" %3%\n" +" do paquete\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"O ficheiro %1%\n" +" da instalación de\n" +" %2%\n" +" entra en conflito co ficheiro\n" +" %3%\n" +" da instalación de\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Non se pode crear sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "quebrar %s ao ignorar algunhas das dependencias" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "polo xeral ignorar algunhas dependencias" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "peticións en conflito" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "algúns problemas de dependencias" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "petición sen soporte" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "fornecedores eliminados: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"provedores non instalables: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "provedores non instalables: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Esta solicitude danará o seu sistema!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorar o aviso de sistema danado" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "permitir a instalación de PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "instalar %1% aínda que estea na lista negra" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Abortouse a instalación seguindo as indicacións." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " executado" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " fallou a execución" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s xa executado como %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " ignorada a execución ao abortar" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Erro ao enviar a notificación da mensaxe de actualización." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nova mensaxe de actualización" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Fallou RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Erro ao importar a chave pública %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Erro ao eliminar a chave pública %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Modificados os ficheiros de configuración para %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm gardou %s como %s, pero non se pode determinar a diferenza" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm gardou %s como %s.\n" +"A continuación amósanse as primeiras 25 liñas de diferenza:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm creou %s como %s, pero no se pode determinar a diferenza" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm creou %s como %s.\n" +"A continuación amósanse as primeiras 25 linas de diferenza:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Saída rpm adicional" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "copia de seguridade %s creada" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "A sinatura é correcta" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tipo de sinatura descoñecido" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "A sinatura non se dou verificado" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "A sinatura está correcta, mais non se confía na chave" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Non hai dispoñible unha sinatura pública da chave" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Ou o ficheiro non existe ou ou a sinatura non se pode verificar" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "O ficheiro está sen asinar" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tipo dubidoso '%s' para o byte %u suma de verificación '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Non se pode abrir pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Non se pode abrir a canalización (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Cadea de consulta URL LDAP incorrecta" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Parámetro de consulta URL LDAP '%s' incorrecto" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Non se pode clonar o obxecto URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Referencia de obxecto de URL baleiro incorrecto" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Non se poden analizar os compoñentes de URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historial:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "O esquema de Url non permite un elemento %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Compoñente '%s' incorrecto %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Compoñente %s incorrecto" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "A análise de cadeas de consulta non é compatible con este enderezo URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "O esquema de Url é un compoñente obrigatorio" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Esquema '%s' de URL incorrecto" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "O esquema de Url non permite un nome de usuario" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "O esquema de Url non permite un contrasinal" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "O esquema de Url require un compoñente de host" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "O esquema de Url non permite un compoñente host" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Compoñente de host incorrecto '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "O esquema de Url non permite un porto" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Compoñente de porto incorrecto '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "O esquema de Url require un nome de ruta" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Non se permiten rutas alternativas se existe unha autoridade" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "A cadea codificada inclúe un byte NULO" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" +"Parámetro de carácter de separación para a división de matrices incorrecto" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" +"Parámetro de carácter de separación para a división de mapas incorrecto" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" +"Parámetro de carácter de separación para a unión de matrices incorrecto" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "A orde rematou co estado %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "O sinal %d (%s) matou a orde." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "A orde rematou cun erro descoñecido." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Non se pode facer chroot a '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Non foi posíbel executar '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Non foi posíbel executar chdir '%s' dentro de '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Non se pode executar '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "No se pode facer fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Fallo ao montar %s en %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Fallo ao desmontar %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nome de ficheiro danado: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "O medio non se abriu cando se tentaba realizar a acción '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Non se atopa o ficheiro '%s' no medio '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Non se puido escribir o ficheiro '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Medio non anexado" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Punto de inserción de medio incorrecto" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "O inicio da descarga (curl) fallou para '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Excepción do sistema '%s' no medio '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "A ruta '%s' no medio '%s' non é un ficheiro." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "A ruta '%s' no medio '%s' non é un directorio." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Formato de URI incorrecto" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nome de host baleiro en URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Sistema de ficheiros baleiro en URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destino baleiro en URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Esquema de URL non soportado en '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operación non admitida polo medio" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Erro na descarga (curl) de '%s':\n" +"Código de erro: %s\n" +"Mensaxe de erro: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Ocorreu un erro ao establecer as opcións de descarga (curl) para '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "O medio fonte '%s' non contén o medio desexado" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "O medio '%s' está en uso por outra instancia" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Non é posible expulsar ningún medio" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Non se puido expulsar o soporte '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Permiso de acceso a '%s' denegado." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Tempo de espera excedido ao acceder a '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"Os datos descargados superan o tamaño de ficheiro '%s' esperado para '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "A localización '%s' está neste intre inaccesible." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Problema no certificado SSL, comprobe se a certificación CA é correcta para " +"'%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Método de autenticación HTTP non soportado '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Si" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Non" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Aviso:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Erro:" + +# ID +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "feito" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "erro" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Advertencia: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Obtendo:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "iniciando" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Non atopado" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Non hai axuda dispoñible para este indicador de ordes." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "Non hai axuda dispoñible para esta opción" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "si" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "non" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Executando o script %%posttrans '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Executando scripts de %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "O paquete non está asinado!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s non pertence ao repositorio de actualización da distribución" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s ten unha arquitectura inferior" + +#~ msgid "problem with installed package %s" +#~ msgstr "houbo un problema co paquete instalado %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "no hai nada que forneza o solicitado %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Activou todos os repositorios solicitados?" + +#~ msgid "package %s does not exist" +#~ msgstr "o paquete %s non existe" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s ofréceo o sistema e non se pode eliminar" + +#~ msgid "%s is not installable" +#~ msgstr "%s non é instalable" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "no hai nada que forneza %s e que o necesita %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "non se puido instalar %s e %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s ten un conflito con %s, fornecido por %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s está obsoleto %s fornecido por %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s instalado, deixa obsoleto a %s fornecido por %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "a solución %s ten conflitos con %s fornecida por esta mesma" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s require %s, pero este requirimento non pode ser fornecido" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "retirar os bloqueos para poder eliminar a %s" + +#~ msgid "do not install %s" +#~ msgstr "non instalar %s" + +#~ msgid "keep %s" +#~ msgstr "Manter %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "retirar os bloqueos para poder instalar a %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "non preguntar en caso de instalar algún elemento que forneza %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "" +#~ "non preguntar en caso de eliminar todos os elementos que fornecen %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "non instalar a versión máis recente de %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "manter %s sen importar que sexa dunha arquitectura inferior" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "instalar %s aínda que cambie a arquitectura" + +#~ msgid "keep obsolete %s" +#~ msgstr "manter o antigo %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "instalar %s desde os repositorios excluídos" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "desactualizar de %s a %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "modificación de arquitectura de %s para %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "instalar %s (con cambio de provedor)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "substitución de %s con %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "desinstalación de %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Non se pode abrir o ficheiro de bloqueo: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Esta acción xa está a ser executada por outro programa." + +#~ msgid "Hal Exception" +#~ msgstr "Excepción de hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Esta versión de libzypp foi compilada sen soporte para HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext non conectado" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive non inicializado" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume non inicializado" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Non foi posible crear a conexión co dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: non foi posible crear o contexto libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "libhal_set_dbus_connection: non se puido definir a conexión con dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "Non foi posible iniciar o contexto HAL - hald non está en execución?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Non é un dispositivo CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Non é posible iniciar os atributos de mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Non se pode establecer o atributo de mutex recursivo" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Non é posíbel inicializar mutex recursivo" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Non se pode adquirir o bloqueo de mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Non se pode liberar o bloqueo de mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Erro ao importar a chave pública desde o ficheiro %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Erro ao eliminar a chave pública %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Non é posible atopar un dispositivo bucle dispoñible para montar a imaxe " +#~ "desde '%s'" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "xeralmente ignorar algunhas dependencias" + +#~ msgid "do not forbid installation of %s" +#~ msgstr "non prohibir a instalación de %s" + +#~ msgid "do not keep %s installed" +#~ msgstr "non manter instalado %s" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "خيار list غير معروف" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Non se pode crear a chave pública %s do anel de chaves %s ao ficheiro %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "Tentouse importar a chave inexistente %s no anel de chaves %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Non se pode facer chdir a '/' dentro de chroot (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "O inicio da descarga (Metalink curl) fallou para '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Erro na descarga (metalink curl) de '%s':\n" +#~ "Código de erro: %s\n" +#~ "Mensaxe de erro: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Descarga interrompida en %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Descarga interrompida polo usuario" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Ocorreu un erro ao establecer as opcións de descarga (metalink curl) para " +#~ "'%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Erro ao descargar %s desde %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia e Montenegro" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "Depende de: !dependecies" + +#, fuzzy +#~ msgid "%s remove failed" +#~ msgstr "Eliminar elemento" + +#, fuzzy +#~ msgid "%s install failed" +#~ msgstr "Cron executouse con fallas" + +#, fuzzy +#~ msgid "%s installed ok" +#~ msgstr "Non instalado" + +#, fuzzy +#~ msgid "%s remove ok" +#~ msgstr "Eliminar elemento" diff --git a/po/gu.po b/po/gu.po new file mode 100644 index 0000000..0b5d13d --- /dev/null +++ b/po/gu.po @@ -0,0 +1,5938 @@ +msgid "" +msgstr "" +"Project-Id-Version: nis\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2006-11-11 18:41+0530\n" +"Last-Translator: Priyavert Sharma\n" +"Language-Team: AgreeYa Solutions\n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: KBabel 1.10.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "અજાણ્યો દેશ:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "કોડ નથી" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "એન્ડોરા" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "યૂનાઇટેડ આરબ એમિરાટ્સ" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "અફઘાનિસ્તાન" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "એન્ટિગુઆ અને બારબુડા" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "એન્ગુઇલા" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "અલ્બાનિયા" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "અર્મેનિયા" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "નેધરલેન્ડ્સ એન્ટિલેસ" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "એન્ગોલા" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "એન્ટાર્કટિકા" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "આર્જેન્ટિના" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "અમેરિકન સામોઆ" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "ઓસ્ટ્રિયા" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "ઓસ્ટ્રેલિયા" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "અરુબા" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "અલાન્ડ આઇલેન્ડ્સ" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "અઝેરબાઇજન" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "બોસ્નિયા અને હર્ઝેગોવિના" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "બાર્બાડોઝ" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "બાંગ્લાદેશ" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "બેલ્જીયમ" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "બર્કિના ફાસો" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "બલ્ગેરિયા" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "બહેરિન" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "બુરુંડી" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "બેનિન" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "બર્મુડા" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "બ્રૂનેઇ દારુસ્સાલમ" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "બોલિવિયા" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "બ્રાઝિલ" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "બહામસ" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "ભૂટાન" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "બૌવેટ આઇલેન્ડ" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "બોટ્સવાના" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "બેલારુસ" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "બેલાઇઝ" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "કેનેડા" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "કોકોસ (કિલિંગ) આઇલેન્ડ્સ" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "કોંગો" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "સેટ્રલ આફ્રિકન રિપબ્લિક" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "સ્વિટઝરલેન્ડ" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "કોટ ડિ'લ્વોઇરે" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "કુક આઇલેન્ડ્સ" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "ચિલિ" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "કેમેરુન" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "ચાઇના" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "કોલોમ્બિયા" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "કોસ્ટા રિકા" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "ક્યુબા" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "કેપ વર્ડે" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "ક્રિસ્ટમસ આઇલેન્ડ" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "સાઇપ્રસ" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "ચેઝ રિપબ્લિક" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "જર્મની" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "ડ્જિબૌટી" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "ડેનમાર્ક" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "ડોમિનિકા" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "ડોમિનિસિયન રિપબ્લિક" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "અલ્જેરિયા" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "એક્વાડોર" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "એસ્ટોનિયા" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "ઇજિપ્ત" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "વેસ્ટર્ન સહારા" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "એરિટરિયા" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "સ્પેન" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "એથિઓપિયા" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "ફિનલેન્ડ" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "ફિજિ" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "ફાલ્કલેન્ડ આઇલેન્ડ (માલ્વિનસ)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "ફેડરેટડ સ્ટેટ્સ ઓફ માઇક્રોનેસિયા" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "ફારોએ આઇલેન્ડ્સ" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "ફ્રાન્સ" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "મેટ્રોપોલિટન ફ્રાન્સ" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "ગબોન" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "યૂનાઇટેડ કિંગડોમ" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "ગ્રેનાડા" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "જ્યોર્જિયા" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "ફેન્ચ ગુઇઆના" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "જર્મની" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "ઘાના" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "જિબ્રાલ્ટર" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "ગ્રીનલેન્ડ" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "ગમ્બિયા" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "ગુનિયા" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "ગૌડેલૌપે" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "એક્વાટોરિયલ ગુનિયા" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "ગ્રીસ" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "સાઉથ જ્યોર્જિયા અને સાઉથ સેન્ડવિચ આઇલેન્ડ્સ" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "ગૌટેમાલા" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "ગુઆમ" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "ગુનિયા-બિસાઉ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "ગુયાના" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "હોંગ કોંગ" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "હર્ડ આઇલેન્ડ અને મેકડોનાલ્ડ આઇલેન્ડ્સ" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "હોંડુરાસ" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "ક્રોએશિયા" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "હૈતી" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "હંગેરી" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "ઇન્ડોનેશિયા" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "આયર્લેન્ડ" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "ઇઝરાયેલ" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "ઇન્ડિયા" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "બ્રિટિશ ઇન્ડિયન ઓસિયન ટેરિટરી" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "ઇરાક" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "ઇરાન" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "આઇસલેન્ડ" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "ઇટાલિ" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "જમૈકા" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "જોર્ડન" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "જાપાન" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "કેન્યા" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "ક્યરઝેસ્તાન" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "કંબોડિયા" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "કિરિબતી" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "કોમરોસ" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "સેંટ કિટ્સ અને નેવિસ" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "નોર્થ કોરિયા" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "સાઉથ કોરિયા" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "કુવૈત" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "કેયમેન આઇલેન્ડ્સ" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "કઝાક્સ્તાન" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "લાઓ પિપલ્સ ડેમોક્રેટિક રિપબ્લિક" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "લેબેનોન" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "સેંટ લુસિયા" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "લેઇચટેન્સ્ટેઇન" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "શ્રી લંકા" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "લિબેરિયા" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "લેસોથો" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "લિથુઆનિયા" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "લક્ઝેમબર્ગ" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "લેટિવા" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "લિબિયા" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "મોરોક્કો" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "મોનેકો" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "મોલ્ડોવા" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "મોંગો" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "સન મેરિનો" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "મડગાસ્કાર" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "માર્શેલ આઇલેન્ડ્સ" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "માસેડોનિયા" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "માલિ" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "મ્યાનમાર" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "મોંગોલિયા" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "મકાઓ" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "નોર્ધર્ન મારિયાના આઇલેન્ડ્સ" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "માર્ટિનિક" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "મૌરિટાનિયા" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "મોન્ટસેરાટ" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "માલ્ટા" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "મોરેશિયસ" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "માલદિવસ" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "મલાવિ" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "મેક્સિકો" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "મલેસિયા" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "મોઝામ્બિક" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "નામિબિયા" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "ન્યૂ કેલેડોનિયા" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "નાઇજેર" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "નોરફોલ્ક આઇલેન્ડ" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "નાઇજિરિયા" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "નિકારાગુઆ" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "નેધરલેન્ડસ" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "નોર્વે" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "નેપાલ" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "નૌરુ" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "નિયુએ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "ન્યૂ ઝીલેન્ડ" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "ઓમાન" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "પનામા" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "પેરુ" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "ફ્રેન્ચ પોલિનેસિયા" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "પાપુઆ ન્યૂ ગુનિયા" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "ફિલિપાઇન્સ" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "પાકિસ્તાન" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "પોલેન્ડ" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "સેંટ પિએરે અને મિકેલોન" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "પિટકેઇર્ન" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "પ્યૂએર્ટો રિકો" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "પેલેસ્ટિનિયન ટેરિટરી" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "પોર્ટુગલ" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "પલાઉ" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "પેરાગ્વે" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "કતાર" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "રિયૂનિયન" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "રોમાનિયા" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "સર્બિયન" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "રશિયન ફેડરેશન" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "રવાન્ડા" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "સાઉદી અરેબિયા" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "સોલોમન આઇલેન્ડ્સ" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "શેશેલ્સ" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "સુદાન" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "સ્વિડન" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "સિંગાપોર" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "સેંન્ટ હેલેના" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "સ્લોવેનિયા" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "સ્વાલબર્ડ અને જાન મયેન" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "સ્લોવેકિયા" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "સિયેરા લિયોન" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "સન મેરિનો" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "સેનેગલ" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "સોમાલિયા" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "સુરિનેમ" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "સાઓ ટોમ અને પ્રિન્સિપે" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "એલ સાલ્વાડોર" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "સિરિયા" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "સ્વાઝિલેન્ડ" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "ટર્કસ અને કઇકોસ આઇલેન્ડ" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "ચેડ" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "ફ્રેન્ચ સાઉધર્ન ટેરિટોરિસ" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "ટોગો" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "થાઈલેન્ડ" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "ટાઝિક્સ્તાન" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "તોકેલાઉ" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "ટર્કમેનિસ્તાન" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ટુનિસિયા" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "ટોંગા" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "ઇસ્ટ ટિમર" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "ટર્કી" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ત્રિનિદાદ અને ટોબાગો" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "ટુવાલુ" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "તાઇવાન" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "ટાન્ઝાનિયા" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "યુક્રેઇન" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "યુગાન્ડા" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "યૂનાઇટેડ સ્ટેટ્સ માઇનોર આઉટલાઇંગ આઇલેન્ડ્સ" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "યૂનાઇટેડ સ્ટેટ્સ" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "યુરુગ્વે" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "યુઝબેકિસ્તાન" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "હોલિ સી (વેટિકન સીટી સ્ટેટ)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "સેંટ વિન્સેન્ટ અને ધ ગ્રેનાડિનેસ" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "વેનેઝુએલા" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "બ્રિટીશ વર્જિન આઇલેન્ડ્સ" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "વર્જિન આઇલેન્ડ્સ, યુ.એસ." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "વિયેટનામ" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "વનુઆટુ" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "વોલિસ અને ફુટુના" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "સમોઆ" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "યેમન" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "મયોટે" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "સાઉથ આફ્રિકા" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "ઝામ્બિયા" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "ઝિમ્બાબ્વે" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s અલગ પાડવું : %s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "VM શરૂ કરવામાં નિષ્ફળ." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "VM શરૂ કરવામાં નિષ્ફળ." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "એન્ટ્રી મળી નહીં." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "અજાણી ભાષા:" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "અફર" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "અબકાઝિયન" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "અચાઈનિઝ" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "અકોલી" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "અડાનગ્મે" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "અડ્યાઘે" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "અફ્રો-એશિયાટીક (અન્ય)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "અફ્રિહિલિ" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "આફ્રિકન્સ" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "એઇનુ" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "અકાન" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "અકાડિયન" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "અલ્બાનિયન" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "એલુટ" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "એલ્ગોનક્વિયન ભાષાઓ" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "સાઉથર્ન અલટાઇ" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "એમહારિક" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "અંગ્રેજી, જૂનું (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "અપાચે ભાષાઓ" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "અરેબિક" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "અરામેઇક" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "આર્ગોનિઝ" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "આર્મેનિયન" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "અરાઉકેનિયન" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "અરાપાહો" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "આર્ટિફિસિયલ (અન્ય)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "અરાવક" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "આસામિઝ" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "ઓસ્ટ્રીયન" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "અથાપાસ્કેન ભાષાઓ" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "ઓસ્ટ્રેલિયન ભાષાઓ" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "અવારિક" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "અવેસ્ટન" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "અવધી" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "અયમારા" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "અઝેરબાઇજાની" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "બાન્ડા" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "બામિલેકે ભાષાઓ" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "બષ્કિર" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "બલુચિ" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "બમબારા" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "બાલિનેઝ" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "બાસ્ક" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "બાસા" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "બાલ્ટિક (અન્ય)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "બેજા" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "બેલારુશિયન" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "બેમ્બા" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "બેંગાલી" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "બેર્બેર (અન્ય)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "ભોજપૂરી" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "બિહારી" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "બિકોલ" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "બિનિ" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "બિસલામા" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "સિકસિકા" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "બાન્ટુ (અન્ય)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "બોસ્નિયન" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "બ્રજ" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "બ્રેટન" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "બટક (ઇન્ડોનેશિયા)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "બરિયટ" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "બુગિનેઝ" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "બલ્ગેરિયન" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "બરમિઝ" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "બ્લિન" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "કેડ્ડો" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "સેન્ટલ અમેરિકન ઇન્ડિયન (અન્ય)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "કેરિબ" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "કેટાલન" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "કૌકાસિયન (અન્ય)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "સેબુઆનો" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "સેલટિક (અન્ય)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "ચામોરો" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "ચિબ્ચા" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "ચેચન" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "ચગાટાઇ" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "ચાઈનિઝ" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "ચુકેસે" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "મારી" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "ચિનુક જાર્ગન" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "ચોક્ટાઓ" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "ચિપેવ્યાન" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "ચેરોકી" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "ચર્ચ સ્લાવિક" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "ચુવાસ" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "ચેયન્ને" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "ચામિક ભાષાઓ" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "કોપ્ટિક" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "કોર્નિશ" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "કોર્શિયન" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "ક્રેઓલેસ અને પિડગિન્સ, અંગ્રેજી-આધારિત (અન્ય)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "ક્રેઓલેસ અને પિડગિન્સ, ફ્રેન્ચ-આધારિત (અન્ય)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "ક્રેઓલેસ અને પિડગિન્સ, પોર્ટુગેઝ-આધારિત (અન્ય)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "ક્રી" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "ક્રિમિન ટટાર" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "ક્રેઓલેસ અને પિડગિન્સ (અન્ય)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "કશુબિયન" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "કુશિટિક (અન્ય)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "ચેઝ" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "ડેકોટા" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "ડેનિશ" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "ડર્ગવા" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "ડાયક" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "ડેલવારે" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "સ્લેવ (અથાપાસ્કેન)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "ડોગ્રિબ" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "ડિન્કા" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "ડિવેહી" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "ડોગરી" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "ડ્રવિડિયન (અન્ય)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "લોવર સોર્બિયન" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "ડૌલા" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "ડચ, મધ્ય (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "ડચ" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ડ્યુલા" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "ડ્ઝોનઘા" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "એફિક" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "ઇજિપ્ટિયન (પ્રાચીન)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "એકાજુક" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "એલામાઇટ" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "અંગ્રેજી" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "અંગ્રેજી, મધ્ય (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "એસ્પરાન્ટો" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "એસ્ટોનિયન" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "એવ" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "એવોન્ડો" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "ફેંગ" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "ફારોઇઝ" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "ફન્ટિ" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "ફિઝિયન" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "ફિલિપિનો" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "ફિનિશ" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "ફિન્નો-યુગ્રીયન (અન્ય)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "ફોન" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "ફ્રેન્ચ" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "ફ્રેન્ચ, મધ્ય (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "ફ્રેન્ચ, જૂનું (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "ફ્રિસિયન" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "ફુલાહ" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "ફ્રિયુલિયન" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "ગા" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "ગાયો" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "ગબાયા" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "જર્મેનિક (અન્ય)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "જ્યોર્જિયન" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "જર્મન" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "ગીઝ" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "ગીલબર્ટેઝ" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "ગાયેલિક" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "આઇરિશ" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "ગાલિસિયન" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "મેંક્ષ" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "જર્મન, મધ્ય ઊંચું (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "જર્મન, જૂનું ઊંચું (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "ગોન્ડી" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "ગોરોનટાલો" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "ગોથિક" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "ગ્રેબો" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "ગ્રીક, પ્રાચીન (to 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "ગ્રીક, આધુનિક (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "ગૌરાની" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "ગુજરાતી" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "ગ્વિચ'ઇન" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "હૈડા" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "હૈશિયન" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "હૌસા" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "હવાઇન" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "હેબ્રૂ" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "હેરેરો" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "હિલિગયનોન" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "હિમાચલિ" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "હિંદી" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "હિટીટે" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "હમોંગ" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "હિરિ મોટુ" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "અપર સોર્બિયન" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "હંગેરિયન" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "હુપા" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "ઇબાન" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "ઇગ્બો" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "આઇસલેન્ડિક" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ઇડો" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "સિચુયન યિ" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ઇજો" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "ઇનુક્ટિટટ" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "ઇન્ટરલિંગ્યુ" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "ઇલોકો" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "ઇન્ટરલિંગ્યુઆ (ઇન્ટરનેશનલ ઓક્ઝિલરી લેંગ્વેજ એસોસિયેશન)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "ઇન્ડિક (અન્ય)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "ઇન્ડોનેશિયન" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "ઇન્ડો-યુરોપિયન (અન્ય)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "ઇનગ્યુશ" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "ઇનુપિક" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "ઇરાનિયન (અન્ય)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "આઇરોક્વોયન ભાષાઓ" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "ઇટાલિયન" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "જાવાનિઝ" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "લોજબાન" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "જાપાનિઝ" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "જ્યુડેઓ-પર્સિયન" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "જ્યુડેઓ-અરેબિક" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "કારા-કલ્પક" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "કબય્લે" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "કચિન" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "કલાલિસટ" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "કમ્બા" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "કન્નડા" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "કરેન" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "કાશ્મીરી" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "કનૌરી" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "કાવિ" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "કઝાક" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "કબાર્ડિયન" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "ખાસિ" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "ખોઇસન (અન્ય)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "ખેમર" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "ખોટેનિઝ" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "કિકુયુ" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "કિનયરવાન્ડા" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "કિરઝિઝ" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "કિમબુંડું" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "કોંકણી" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "કોમિ" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "કોંગો" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "કોરિયન" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "કોસ્રેયિન" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "ક્પેલે" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "કરાચય-બલ્કર" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "ક્રૂ" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "કુરુખ" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "કૌનયામા" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "કુમય્ક" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "કુર્દિશ" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "કુટેનાઇ" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "લાડિનો" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "લાહ્ન્ડા" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "લામ્બા" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "લાઑ" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "લેટિન" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "લેટવિયન" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "લેઝઘિયન" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "લિમ્બર્ગન" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "લિંગાલા" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "લિથુઆનિયન" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "મોંગો" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "લોઝિ" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "લકઝેમબર્ગિશ" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "લુબા-લુલ્યુઆ" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "લુબા-કટનગા" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ગાન્ડા" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "લ્યુઇસેનો" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "લુન્ડા" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "લુઓ (કેન્યા અને ટાન્ઝાનિયા)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "લુશાઇ" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "મેસેડોનિયન" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "મડુરિઝ" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "મગાહિ" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "માર્શેલિઝ" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "મૈથિલિ" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "મકાસાર" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "મલયાલમ" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "મંડિંગો" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "માઓરી" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "ઓસ્ટ્રોનેસિયન (અન્ય)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "મરાઠી" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "મસાઇ" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "મલય" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "મોક્ષા" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "મંડર" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "મેન્ડે" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "આઈરિશ, મધ્ય (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "મિ-ક્મક" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "મિનંગકબાઉ" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "મિશ્ર ભાષાઓ" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "મોન-ખેમર (અન્ય)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "મલાગ્સે" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "મોલ્ટિઝ" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "મંચુ" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "મનિપુરી" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "મનોબો ભાષાઓ" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "મોહાક" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "મોલ્ડાવિયન" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "મોંગોલિયન" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "મોસિ" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "બહુવિધ ભાષાઓ" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "મુંડા ભાષાઓ" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "ક્રિક" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "મિરાંડેઝ" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "મારવારી" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "માયન ભાષાઓ" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "એર્ઝાયા" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "નહુઆટ્લે" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "નોર્થ અમેરિકન ઇન્ડિયન" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "નેપોલિટન" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "નવાજો" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "ન્ડેબેલે, સાઉથ" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "ન્ડેબેલે, નોર્થ" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ન્ડોનગા" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "લો જર્મન" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "નેપાલી" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "નેપાલ ભાષા" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "નિયાસ" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "નાઇજર-કોર્ડોફેનિયન (અન્ય)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "નિયુએન" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "નોર્વેજિયન ન્યનોર્સ્કે" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "નોર્વેજિયન બોકમલ" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "નોગાઈ" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "નોર્સે, જૂનું" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "નોર્વેજિયન" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "નોર્ધન સોથો" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "ન્યુબિયન ભાષાઓ" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "ક્લાસિકલ નેવારી" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "ચિચેવા" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "ન્યામવેઝિ" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "ન્યાનકોલે" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "ન્યોરો" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "ન્ઝિમા" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "ઓસિટન (પોસ્ટ 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "ઓજિબ્વા" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "ઓરિયા" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "ઓરોમો" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "ઓસેજ" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "ઓસેટિયઅન" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "ટર્કિસ, ઓટોમન (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "ઓટોમિયન ભાષાઓ" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "પેપુયન (અન્ય)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "પેન્ગાસિનન" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "પહલાવિ" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "પમપાન્ગા" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "પંજાબી" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "પપિયામેન્ટો" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "પલાઉન" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "પર્સિયન, જૂનું (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "પર્સિયન" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "ફિલિપાઇન્સ (અન્ય)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "ફોએનિસિયન" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "પાલી" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "પોલિશ" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "પોહ્નપેઇયન" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "પોર્ટુગીઝ" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "પ્રક્રિત ભાષાઓ" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "પ્રોવેન્કલ, જૂનું (to 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "પુશ્તો" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "ક્વેચુઆ" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "રાજસ્થાની" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "રપાનુઇ" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "રારોટોન્ગન" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "રોમાન્સ (અન્ય)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "રાએટો-રોમાન્સ" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "રોમાની" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "રોમાનિયન" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "રુન્ડી" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "રસિયન" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "સેન્ડવે" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "સેન્ગો" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "યાકુટ" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "સાઉથ અમેરિકન ઇન્ડિયન (અન્ય)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "સાલિશન ભાષાઓ" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "સમારિટન અરામેઇક" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "સંસ્ક્રિત" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "સસક" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "સનતાલિ" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "સર્બિયન" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "સિસિલિયન" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "સ્કોટ્સ" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "ક્રોએશિયન" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "સેલકપ" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "સેમિટિક (અન્ય)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "આઇરિશ, જૂનું (to 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "સાઇન ભાષાઓ" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "શાન" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "સિદામો" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "સિંહાલા" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "સિયુઅન ભાષાઓ" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "સિનો-ટિબેટિયન (અન્ય)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "સ્લેવિક (અન્ય)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "સ્લોવેક" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "સ્લોવેનિયન" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "સાઉધર્ન સામિ" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "નોર્ધર્ન સામિ" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "સામિ ભાષાઓ (અન્ય)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "લુલે સામિ" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "ઇનારિ સામિ" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "સામોઅન" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "સ્કોલ્ટ સામિ" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "શોના" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "સિંધી" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "સોનિનકે" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "સોગડિયન" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "સોમાલિ" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "સોંઘાઈ" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "સોથો, સાઉધર્ન" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "સ્પેનિશ" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "સર્દિનિયન" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "સેરેર" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "નિલો-સહારન (અન્ય)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "સ્વાતિ" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "સુકુમા" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "સનડેનેઝ" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "સુસુ" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "સુમેરિયન" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "સ્વાહિલિ" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "સ્વેડિશ" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "સાઇરિએક" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "તાહિશિયન" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "તાઇ (અન્ય)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "તામિલ" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "તાતાર" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "તેલુગુ" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "ટિમ્ને" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "ટેરેનો" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "તેટુમ" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "તાજિક" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "તાગાલોગ" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "થાઇ" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "ટિબેટન" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "ટાઇગ્રે" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "ટાઇગ્રીન્યા" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "ટિવ" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "ક્લિંગોન" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "ટ્લિનગિટ" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "ટામાશેક" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "ટોંગા (ન્યાસા)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "ટોંગા (ટોંગા આઇસલેન્ડ્સ)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "ટોક પિસિન" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "ત્સિમશિયન" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "ત્સ્વાના" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "ત્સોનગા" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "ટર્કમેન" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "ટુમબુકા" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "ટુપિ ભાષાઓ" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "ટર્કિશ" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "અલ્ટાઇક (અન્ય)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "ટ્વિ" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "ટુવિનિયન" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "ઉડમુર્ટ" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "યુગારિટિક" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "યુઇઘુર" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "યુક્રેઇનિયન" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "ઉમબુન્દુ" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "અનિશ્ચિત" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "ઊર્દૂ" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "ઉઝબેક" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "વાઈ" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "વેન્ડા" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "વિએટનામિઝ" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "વોલાપુક" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "વોટિક" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "વોકાશન ભાષાઓ" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "વાલામો" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "વારે" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "વાશો" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "વેલ્શ" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "સોરાબિયન ભાષાઓ" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "વલુન" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "વોલોફ" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "કલમ્યક" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "ક્ઝોસા" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "યોઆ" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "યાપેઝ" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "યિડ્ડિશ" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "યોરુબા" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "યુપિક ભાષાઓ" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "ઝાપોટેક" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "ઝેનેગા" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "ઝુઆંગ" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "ઝંડે" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "ઝુલુ" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "ઝુનિ" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1' અસ્તિત્વ ધરાવતી નથી." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1' અસ્તિત્વ ધરાવતી નથી." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "અપરિચિત" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "ડિસ્ક અસ્તિત્વ ધરાવતી નથી." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "અજાણ્યો કમાન્ડ" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "અમાન્ય Url યોજના '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "ડિરેક્ટરી %1 બનાવી શકાતી નથી: %2." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "%s ડેસ્કટોપ આઈટમ ખોલી શકાશે નહીં" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, fuzzy, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "સાધનો ઉમેરાય છે" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "એક્સપોર્ટ ફાઈલ નું નામ અમાન્ય છે." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "લખવા માટે ફાઇલ ખોલી શકાતી નથી." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "ફ્લોપી ડિસ્કમાંથી વાંચવામાં ભૂલ." + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "સાધનો ઉમેરાય છે" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "%s ડેસ્કટોપ આઈટમ ખોલી શકાશે નહીં" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "VM નું નામ આંકડાથી શરૂ થઇ શકે નહીં." + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr "VM નું નામ આંકડાથી શરૂ થઇ શકે નહીં." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "ચાલુ રાખવું છે? " + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"%s પેકેજ પૂર્ણતા ચકાસણીમાં નિષ્ફળ ગઇ છે. તમે તે ફરીથી ડાઉનલોડ કરવાનો પ્રયત્ન કરવા માંગો " +"છો?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"%s પેકેજ પૂર્ણતા ચકાસણીમાં નિષ્ફળ ગઇ છે. તમે તે ફરીથી ડાઉનલોડ કરવાનો પ્રયત્ન કરવા માંગો " +"છો?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm ચકાસણી કરવામાં નિષ્ફળ." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm નિષ્ફળ." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "સાધન પ્રકાર VAR1 ફેરફાર-બતાવો ફિચર ને આધાર આપતા નથી" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "%s માંથી %s પૂરું પાડી શકાતું નથી" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "રિપોસીટરીમાં ફાઈલ %1 મળી નહીં." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "ફાઈલ બનાવી શકાતી નથી." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "આ જરૂરિયાત અહીં માત્ર અવગણો" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "આ જરૂરિયાત અહીં માત્ર અવગણો" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "ને જોડાણ માટે વિનંતી કરો:" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "પરાધિનતા મૂશ્કેલીઓને કારણે %s સ્થાપિ શકાયું નથી" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "%s કોઇ આપતું નથી" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "%s ના કોઇ સ્થાપવાનું પૂરું પાડનાર નથી" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "%s ના કોઇ સ્થાપવાનું પૂરું પાડનાર નથી" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "રિક્વેસ્ટ અસ્તિત્વમાં છે જ." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "સૂચના પ્રમાણે સ્થાપન અટકાવેલું હતું." + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "ચલાવો" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "કી એન્ક્રીપ્ટશન દરમિયાન ભૂલ." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "નિષ્ફળ થયું" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s માટે કન્ફિગ્યુરેશન ફાઈલો બદલાઇ:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "%s તરીકે rpm એ %s સાચવ્યું પરંતુ તફાવત જુદો પાડવા તે અશક્ય હતું" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"%s તરીકે rpm એ %s સાચવ્યું.\n" +"અહીં તફાવતોના પ્રથમ 25 લાઇનો છે: \n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "%s તરીકે rpm એ %s રચ્યું પરંતુ તફાવત જુદો પાડવા તેઅશક્ય હતું" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"%s તરીકે rpm એ %s રચ્યું.\n" +"અહીં તફાવતોના પ્રથમ 25 લાઇનો છે:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "વધારાનું rpm આઉટપુટ:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "%s નું બેકઅપ રચાયું" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "એન્ટ્રી મળી નહીં." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "એન્ટ્રી મળી નહીં." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "એન્ટ્રી મળી નહીં." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "ફાઈલ ખુલી શકતી નથી: %1." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "ફાઈલ ખુલી શકતી નથી: %1." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "અમાન્ય LDAP URL ક્વેરિ સ્ટ્રીંગ" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "અમાન્ય LDAP URL ક્વેરિ પારમિતિ '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Url વસ્તુને ક્લોન કરવામાં અક્ષમ" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "અમાન્ય ખાલી Url વસ્તુ સંદર્ભ" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Url ઘટકોને પાર્સ કરવામાં અક્ષમ" + +#: zypp-core/base/Exception.cc:186 +#, fuzzy +msgid "History:" +msgstr "XF86History " + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url યોજના %s ને મંજૂરી આપતી નથી" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "અમાન્ય %s ઘટક '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "અમાન્ય %s ઘટક" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "આ URL માટે ક્વેરિ સ્ટ્રીંગ પાર્સિંગ સહાયિત નથી" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url યોજનાને ઘટક જરૂરી છે" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "અમાન્ય Url યોજના '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url યોજના વપરાશકર્તાને મંજૂરી આપતું નથી" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url યોજના પાસવર્ડને મંજૂરી આપતું નથી" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url યોજનાને હોસ્ટ ઘટક જરૂરી છે" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url યોજના હોસ્ટ ઘટકને મંજૂરી આપતું નથી" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "અમાન્ય હોસ્ટ ઘટક '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url યોજનાને પોર્ટને મંજૂરી આપતું નથી" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "અમાન્ય પોર્ટ ઘટક '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url યોજનાને માર્ગ નામ જરૂરી છે" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "હો અધિકૃતિ હાજર હોય તો રિલેટિવ માર્ગની મંજૂરી નથી" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "એનકોડેડ સ્ટ્રીંગમાં NUL બાઇટ સમાવિષ્ટ છે" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "અમાન્ય પારમિતિ એરે સ્પ્લિટ સેપરેટર કેરેક્ટર" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "અમાન્ય પારમિતિ મેપ સ્પ્લિટ સેપરેટર કેરેક્ટર" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "અમાન્ય પારમિતિ એરે જોઇન સ્પ્લિટ સેપરેટર કેરેક્ટર" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "જોડાય ત્યારે કમાન્ડ અમલમાં મૂકવો" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "%s શોધાઈ શકતો નથી." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "%s શોધાઈ શકતો નથી." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "ખુલી શક્તું નથી %s - %s\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "મોડ્યૂલ \"%s\" લોડ કરવામાં નિષ્ફળ." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "રિપોસીટરીમાં ફાઈલ %1 મળી નહીં." + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "ફાઈલ પર લખાઈ શકાતું નથી: %1." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 ડિરેક્ટરી નથી." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "CA નામ ખાલી છે." + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "URL સ્કીમ '%1' અમાન્ય" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "%s ડેસ્કટોપ આઈટમ ખોલી શકાશે નહીં" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr " મંજૂરીઓ નકારાઇ " + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "હા" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "ના" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "ચેતવણી" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "ભૂલ" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "પૂર્ણ થયું" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "ભૂલ" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "ચેતવણી" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "શરૂ થઇ રહ્યું છે..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr " મળ્યું નથી " + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "હા" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ના" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s, %s પૂરું પાડે છે, પરંતુ તેની પાસે બીજી સંરચના છે." + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "પેકેજીસનું સ્થાપન દૂર કરવાનો આદેશ" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "%s કોઇ આપતું નથી" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "ડિસ્ક અસ્તિત્વ ધરાવતી નથી." + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s લોક છે અને અસ્થાપિત થઇ શકશે નહીં" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "સ્થાપેલ નથી" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s દ્વારા %s જરૂરી હતું" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s સ્થાપિ શકાશે નહીં" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s, %s સાથે વિસંગત છે" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s અલગ પાડવું %s" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s અલગ પાડવું %s" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s, %s સાથે વિસંગત છે" + +#~ msgid "do not install %s" +#~ msgstr "%s સ્થાપશો નહીં" + +#~ msgid "keep %s" +#~ msgstr "%s રાખો" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "%s સ્થાપશો નહીં" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "%s ના કોઇ સ્થાપવાનું પૂરું પાડનાર નથી" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "સંબંધિત રિઝોલ્વેબલ્સ સ્થાપો કે કાઢો નહીં" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s, %s પૂરું પાડે છે, પરંતુ તેની પાસે બીજી સંરચના છે." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "%s સ્થાપો જો કે તે સંરચના બદલી શકે" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s અલગ પાડવું %s" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "%s માંથી %s ડાઉનલોડ થયું" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "સ્થાપન" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "ફાઈલ ખુલી શકતી નથી: %1." + +#~ msgid "Hal Exception" +#~ msgstr "હેલ અપવાદ" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext જોડાયેલ નથી" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive નો પ્રારંભ થઇ શક્યો નથી" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume નો પ્રારંભ થઇ શક્યો નથી" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "dbus જોડાણ રચવામાં અક્ષમ" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: libhal સંદર્ભ રચાઇ શક્યું નથી" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: dbus જોડાણ સેટ થઇ શક્યું નથી" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "HAL સંદર્ભ પ્રારંભ કરવામાં અક્ષમ -- હેલ્ડ ચાલતું નથી?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "સીડીરોમ ડ્રાઇવ નથી" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "મ્યૂટેક્ષ ગુણધર્મ શરૂ કરી શકાયો નથી" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "રિકર્સિવ મ્યૂટેક્ષ ગુણધર્મ સેટ કરી શકાયો નથી" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "રિકર્સિવ મ્યૂટેક્ષ શરૂ કરી શકાયો નથી" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "મ્યૂટેક્ષ લોક સંપાદિત કરી શકાયો નથી" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "મ્યૂટેક્ષ લોક છોડી શકાયું નથી" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "પબ્લીક કી લાવી શકાતી નથી." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "સ્થાપેલ નથી" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "ખુલી શક્તું નથી %s - %s\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "સેરબિયા અને મોન્ટેનેગ્રો" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "અજાણ્યી યાદી વિકલ્પ" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "આશ્રિતોને રિઝોલ્વ કરી શકાયા નહીં" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s ફાઇલ પાસે ચેકસમ નથી.\n" +#~ "કોઇ પણ રીતે ફાઇલ વાપરવી છે?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s ફાઈલ નીચેની કળ સાથે પૂર્ણતા ચકાસણીમાં નિષ્ફળ ગઇ છે :\n" +#~ "%s|%s|%s\n" +#~ "કોઇ પણ રીતે ફાઇલ વાપરવી છે?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s ફાઇલ પાસે અમાન્ય ચેકસમ છે.\n" +#~ "%s ની સંભાવના હતી, %s મળી \n" +#~ "કોઇ પણ રીતે ફાઇલ વાપરવી છે?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s ફાઇલ પાસે અજાણ્યું %s ચેકસમ છે.\n" +#~ "કોઇ પણ રીતે ફાઇલ વાપરવી છે?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "%s ફાઈલ સહી કરેલી નથી \n" +#~ "કોઇ પણ રીતે તે વાપરવી છે?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s અજાણી કળ સાથે સહી કરેલી છે :\n" +#~ "%s|%s|%s\n" +#~ "કોઇ પણ રીતે ફાઇલ વાપરવી છે??" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "અવિશ્વસનીય કળ શોધાઇ છે:\n" +#~ "%s|%s|%s\n" +#~ "કળ પર વિશ્વાસ કરવો છે?" + +#~ msgid "%s remove failed" +#~ msgstr "%s ને દૂર કરવામાં નિષ્ફળ" + +#~ msgid "rpm output:" +#~ msgstr "rpm આઉટપુટ:" + +#~ msgid "%s install failed" +#~ msgstr "%s નું સ્થાપન નિષ્ફળ" + +#~ msgid "%s installed ok" +#~ msgstr "%s નું સ્થાપન બરાબર" + +#~ msgid "%s remove ok" +#~ msgstr "%s ને દૂર કરવામાં બરાબર" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "%s આ પરાધિનતા પૂરી પાડે છે પરંતુ સ્થાપેલ બાબતનીસંરચના કદાચ બદલી શકે" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "%s આ પરાધિનતા પૂરી પાડે છે પરંતુ સ્થાપેલ બાબતનીસંરચના કદાચ બદલી શકે" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "સંબંધિત રિઝોલ્વેબલ્સ સ્થાપો કે કાઢો નહીં" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "પહેલેથી સ્થાપવા સેટ કરેલ તે %s અવગણો" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "%s માં અલગ પાડેલા %s ને અવગણો" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%s ની આ વિસંગતતા અવગણો" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "આ જરૂરિયાત અહીં માત્ર અવગણો" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "%s સ્થાપો જો કે તે સંરચના બદલી શકે" + +#~ msgid "Install missing resolvables" +#~ msgstr "છૂટી ગયેલા રિઝોલ્વેબલ્સ સ્થાપો" + +#~ msgid "Keep resolvables" +#~ msgstr "રિઝોલ્વેબલ્સ રાખો" + +#~ msgid "Unlock these resolvables" +#~ msgstr "આ રિઝોલ્વેબલ્સ અનલોક કરો" + +#~ msgid "delete %s" +#~ msgstr "%s કાઢી નાખો" + +#~ msgid "install %s" +#~ msgstr "%s સ્થાપો" + +#~ msgid "unlock %s" +#~ msgstr "%s ને અનલોક કરો" + +#~ msgid "unlock all resolvables" +#~ msgstr "બધા રિઝોલ્વેબલ્સ અનલોક કરો" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "ફાઈલ ખુલી શકતી નથી: %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "%u સેકટર વાંચતી વખતે ભૂલ." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "આ URL માટે માર્ગ પારમિતિ પાર્સિંગ સહાયિત નથી" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "આ URL માટે માર્ગ પારમિતિ પાર્સિંગ સહાયિત નથી" + +#~ msgid "Software management is already running." +#~ msgstr "સોફ્ટવેર મેનેજમેન્ટ પહેલેથી ચાલુ છે" + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s દ્વારા %s ની જગ્યાએ મુકયું" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s દ્વારા %s ની જગ્યાએ મુકાયું" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "આ રિઝોલ્વેબલ્સ સિસ્ટમમાંથી કાઢી નાખવામાં આવશે." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s અસ્થાપિત થશે નહીં કારણકે તે હજુ જરૂરી છે" + +#~ msgid "Invalid information" +#~ msgstr "અમાન્ય માહિતી" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "અન્ય રિઝોલ્વેબલ્સ દ્વારા %s જરૂરી હતું" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "દ્વારા %s જરૂરી હતુ:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s, અન્ય રિઝોલ્વેબલ્સ સાથે વિસંગત છે" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s આની સાથે વિસંગત છે :\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s અન્ય રિઝોલ્વેબલ્સ અલગ પાડે છે" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "આ રિઝોલ્વેબલ્સ સિસ્ટમમાંથી કાઢી નાખવામાં આવશે." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s અન્ય રિઝોલ્વેબલ્સ પર આધાર રાખે છે" + +#~ msgid "%s depends on %s" +#~ msgstr "%s, %s પર આધાર રાખે છે" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s પર આધાર રાખે છે : %s" + +#~ msgid "Child of" +#~ msgstr "નું ચાઇલ્ડ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "કોઇ સ્ત્રોત પ્રાપ્ય નથી જે આ જરૂરિયાતને સહાય કરે." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "આ રિઝોલ્યુશનની ઉપર/નીચે દર્શાવેલ બાકી નિકળતી મૂશ્કેલીઓ બધી પરાધિનતાઓનો ઉકેલલાવી " +#~ "શકશે નહીં" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%s સ્થાપિ શકાશે નહીં કારણકે તે %s સાથે વિસંગત છે" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s સ્થપાયું નથી અને અસ્થાપન તરીકે ચિહિત કર્યું હતું" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s પાસે અપૂર્ણ જરૂરિયાતો છે" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s પાસે છૂટી ગયેલી પરાધિનતા છે" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "છૂટી ગયેલી પરાધિનતાને કારણે %s સ્થાપિ શકાયું નથી" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s, %s ની પરાધિનતા પૂર્ણ કરે છે પરંતુ તે અસ્થાપિત કરાશે" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s, %s ની પરાધિનતા પૂર્ણ કરે છે પરંતુ તે તમારા સિસ્ટમ પર રાખશે" + +#~ msgid "No need to install %s" +#~ msgstr "%s સ્થાપવાની જરૂર નથી" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "%s ની પરાધિનતા પૂર્ણ કરવા %s સ્થાપી શકશે નહીં" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "%s ની પરાધિનતા પૂર્ણ કરવા %s સ્થાપી શકશે નહીં" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s અસ્થાપિત થશે નહીં કારણકે તે હજુ જરૂરી છે" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s અલગ પાડવું %s. પરંતુ %s કાઢી શકાશે નહીં કારણકે તે લોક કરેલું છે." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "%s સ્થાપિત કરી શકાશે નહીં કારણકે તે વિસંગત છે" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s સાથે વિસંગત હોવાથી %s અસ્થાપિત છે" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "જ્યારે %s અદ્યતન કરતા હોવ ત્યારે %s માટે %s જરૂરી છે" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s, %s જરૂરિયાત માટે છૂટી ગયેલ છે" + +#~ msgid ", Action: " +#~ msgstr ", કાર્ય :" + +#~ msgid ", Trigger: " +#~ msgstr ", ટ્રીગર :" + +#~ msgid "package" +#~ msgstr "પેકેજ" + +#~ msgid "selection" +#~ msgstr "પસંદગી" + +#~ msgid "pattern" +#~ msgstr "પેટર્ન" + +#~ msgid "product" +#~ msgstr "પ્રોડક્ટ" + +#~ msgid "patch" +#~ msgstr "પેચ" + +#~ msgid "script" +#~ msgstr "સ્ક્રિપ્ટ" + +#~ msgid "message" +#~ msgstr "સંદેશ" + +#~ msgid "atom" +#~ msgstr "એટમ" + +#~ msgid "system" +#~ msgstr "સિસ્ટમ" + +#~ msgid "Resolvable" +#~ msgstr "રિઝોલ્વેબલ્સ" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "આ ઠરાવ પ્રયત્ન અમાન્ય તરીકે ચિહિત કરો" + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "%s રિઝોલ્વેબલ્સ અસ્થાપિત તરીકે ચિહિત કરો" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "%s સ્થાપવા માટે નિયત છે, પરંતુ વિસંગત મૂશ્કેલીઓનેકારણે આ શક્ય નથી." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "અસ્થાપન માટે જરૂરી છે તે રીતે પહેલેથી ચિહિત છે ત્યાં સુધી %s સ્થાપી શકાશે નહીં" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "તે આ સિસ્ટમ સાથે લાગુ પડતુ નથી ત્યાં સુધી %s સ્થાપી શકાશે નહીં." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "સ્થાપન માટે જરૂરી છે તે રીતે %s પહેલેથી ચિહિત છે ત્યાં સુધી %s સ્થાપીશકાશે નહીં" + +#~ msgid "This would invalidate %s." +#~ msgstr "આ %s ને અપુષ્ટિ કરી શકશે" + +#~ msgid "Establishing %s" +#~ msgstr "%s સ્થપાઇ રહ્યું છે" + +#~ msgid "Installing %s" +#~ msgstr "%s સ્થાપન થઇ રહ્યું છે" + +#~ msgid "Updating %s to %s" +#~ msgstr "%s થી %s માં અદ્યતન થઇ રહ્યું છે" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "%s છોડાઇ રહ્યું છે : પહેલેથી સ્થાપિત છે" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "%s ના કોઇ વૈકલ્પિક સ્થાપવાનું પૂરું પાડનાર નથી" + +#~ msgid "for %s" +#~ msgstr "%s માટે" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "%s ને અદ્યતન કરવા, %s દૂર કરવાનું ટાળવાનું શક્ય નથી" + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s, %s પૂરું પાડે છે, પરંતુ અસ્થાપન માટે નિયત છે." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s, %s પૂરું પાડે છે, પરંતુ તે %s ની અન્ય આવૃતિ પહેલેથી સ્થાપિત છે." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s, %s પૂરું પાડે છે, પરંતુ તે અસ્થાપિત છે. વધુ વિગતો માટે તે તેના પોતાના પર સ્થાપવાનો " +#~ "પ્રયત્ન કરો." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s, %s પૂરું પાડે છે, પરંતુ તે લોક કરેલું છે." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s, %s પૂરું પાડે છે, પરંતુ તે રાખવા માટે નિયત કરાયેલું છે." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s, %s પૂરું પાડે છે, પરંતુ તેની પાસે બીજી સંરચના છે." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "%s માટે %s જરૂરિયાત સંતુષ્ટ કરી શકતું નથી" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "%s, અન્ય સ્થાપિત છે તે રિઝોલ્વેબલ દ્વારા જરૂરી છે, તેથી તે અનલિંક થઇ શકશેનહીં." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "%s, અન્ય સ્થાપિત છે તે રિઝોલ્વેબલ દ્વારા જરૂરી છે, તેથી તે અનલિંક થઇ શકશેનહીં." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "%s (%s) ની વિસંગતતા સ્થાપિત કરવાનું છે તે %s ને દૂર કરવાનું જરૂરી બનાવે છે" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "%s ની વિસંગતતાના કારણે %s ને અસ્થાપિત તરીકે ચિહિત કરો" + +#~ msgid "from %s" +#~ msgstr "%s માંથી" + +#~ msgid " Error!" +#~ msgstr "ભૂલ!" + +#~ msgid " Important!" +#~ msgstr "અગત્યનું!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s, %s પર આધાર રાખ્યો" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s દ્વારા %s જરૂરી હતું" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s દ્વારા %s જરૂરી હતું" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s દ્વારા %s ની જગ્યાએ મુકયું" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s દ્વારા %s જરૂરી હતું" + +#~ msgid "%s part of %s" +#~ msgstr "%s, %s નો ભાગ છે" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr " ડબલ-ક્લિક ટાઇમઆઉટ " + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s દ્વારા %s જરૂરી હતું" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "Url અધિકૃતિ પાર્સ કરવા અક્ષમ" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "સામાન્ય રીતે આ જરૂરિયાત અવગણો" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s, અન્ય સ્થાપિત કરવાનું છે તે રિઝોલ્વેબલ દ્વારા જરૂરી છે, તેથી તે અનલિંક થઇ શકશેનહીં." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "અદ્યતન સ્થાપન કરવામાં જરૂરી ફાઈલ રચી શકાઇ નથી" + +#~ msgid "Unable to restore all sources." +#~ msgstr "બધા સ્ત્રોતો પુનસ્થાપન કરવા અક્ષમ" + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "ઓછામાં ઓછું એક સ્ત્રોત પહેલેથી નોંધાયેલ છે, સંગ્રહ કરાયેલા સ્ત્રોતો પુનસંગ્રહ થઇ શકતો નથી." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "%s ની પરાધિનતા પૂર્ણ કરવા %s સ્થપાઇ શકશે નહીં" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s, %s પર આધારિત" + +#~ msgid "Reading index files" +#~ msgstr "ઇન્ડેક્સ ફાઇલો વંચાઇ રહી છે" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "સહી કરેલી repomd.xml ફાઇલ સહી તપાસવામાં નિષ્ફળ ગઇ." + +#~ msgid "Reading product from %s" +#~ msgstr "%s માંથી પ્રોડક્ટ વંચાઇ રહી છે" + +#~ msgid "Reading filelist from %s" +#~ msgstr "%s માંથી ફાઇલયાદી વંચાઇ રહી છે" + +#~ msgid "Reading packages from %s" +#~ msgstr "%s માંથી પેકેજીસ વંચાઇ રહ્યા છે" + +#~ msgid "Reading selection from %s" +#~ msgstr "%s માંથી પસંદગી વંચાઇ રહી છે" + +#~ msgid "Reading pattern from %s" +#~ msgstr "%s માંથી પેટર્ન વંચાઇ રહ્યા છે" + +#~ msgid "Reading patches index %s" +#~ msgstr "%s માંથી પેચિસ ઇન્ડેક્સ વંચાઇ રહ્યા છે" + +#~ msgid "Reading patch %s" +#~ msgstr "%s પેચ વંચાઇ રહ્યા છે" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "સ્ક્રિપ્ટ ફાઇલ ચેકસમ પરિક્ષણ કરવામાં નિષ્ફળ ગઇ." + +#~ msgid "Reading packages file" +#~ msgstr "પેકેજીસ ફાઇલ વંચાઇ રહી છે" + +#~ msgid "Reading translation: %s" +#~ msgstr "ભાષાંતર વંચાઈ રહ્યું છે : %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "%s પેકેજ પૂર્ણતા ચકાસણીમાં નિષ્ફળ ગઇ છે. તમે તે ફરીથી ડાઉનલોડ કરવાનો પ્રયત્ન કરવા " +#~ "માંગો છો.અથવા સ્થાપન અટકાવવું છે?" + +#~ msgid " miss checksum." +#~ msgstr "ચેકસમ છૂટી ગયું છે." + +#~ msgid " fails checksum verification." +#~ msgstr "ચેકસમ ખરાઇમાં નિષ્ફળ" + +#~ msgid "Downloading %s" +#~ msgstr "%s ડાઉનલોડ થઇ રહ્યું છે" diff --git a/po/he.po b/po/he.po new file mode 100644 index 0000000..32f74bc --- /dev/null +++ b/po/he.po @@ -0,0 +1,5837 @@ +# Hebrew message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2004 SuSE Linux AG. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2004-08-09 10:24+0200\n" +"Last-Translator: xxx \n" +"Language-Team: Hebrew \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=2; plural=n != 1;\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +#, fuzzy +msgid "No Code" +msgstr "מצב" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "איחוד הנסיכויות הערביות" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +#, fuzzy +msgid "Afghanistan" +msgstr "פקיסטן" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "אלבניה" + +# AR +#. :ALB:008: +#: zypp/CountryCode.cc:164 +#, fuzzy +msgid "Armenia" +msgstr "ארגנטינה" + +# NL +#. :ARM:051: +#: zypp/CountryCode.cc:165 +#, fuzzy +msgid "Netherlands Antilles" +msgstr "הולנד" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "" + +# AR +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "ארגנטינה" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +# AT +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "אוסטריה" + +# AU +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "אוסטרליה" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "" + +# IE +#. :ABW:533: +#: zypp/CountryCode.cc:173 +#, fuzzy +msgid "Aland Islands" +msgstr "איי פר-אר" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +#, fuzzy +msgid "Azerbaijan" +msgstr "אזרביג'נית" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +#, fuzzy +msgid "Bosnia and Herzegovina" +msgstr "בוסניה הרצגובינה" + +# BB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "ברבדוס" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "בנגלדש" + +# BE +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "בלגיה" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +# BG +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "בולגריה" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +#, fuzzy +msgid "Bahrain" +msgstr "בחריין" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +#, fuzzy +msgid "Benin" +msgstr "בנגאלית" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +#, fuzzy +msgid "Bermuda" +msgstr "גרמנית" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +# BO +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "בוליביה" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "" + +# PA +#. :BRA:076: +#: zypp/CountryCode.cc:188 +#, fuzzy +msgid "Bahamas" +msgstr "פנמה" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "" + +# IE +#. :BTN:064: +#: zypp/CountryCode.cc:190 +#, fuzzy +msgid "Bouvet Island" +msgstr "איי פר-אר" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "בוטסואנה" + +# BY +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "בלרוס" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +#, fuzzy +msgid "Belize" +msgstr "בלגית" + +# CA +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "קנדה" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "" + +# DO +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "סוריה" + +# CH +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "שוייץ" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +# IE +#. :CIV:384: +#: zypp/CountryCode.cc:201 +#, fuzzy +msgid "Cook Islands" +msgstr "איי פר-אר" + +# CL +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "צ'ילה" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "" + +# CN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "סין" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "קולומביה" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "קוסטה ריקה" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +# DO +#. :CYP:196: +#: zypp/CountryCode.cc:211 +#, fuzzy +msgid "Czech Republic" +msgstr "הרפובליקה הדומיניקנית" + +# DE +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "גרמניה" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "" + +# DK +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "דנמרק" + +# RO +#. :DNK:208: +#: zypp/CountryCode.cc:215 +#, fuzzy +msgid "Dominica" +msgstr "רומניה" + +# DO +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "הרפובליקה הדומיניקנית" + +# BG +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "אלג'יר" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "אקוודור" + +# EE +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "אסטוניה" + +# EG +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "מצרים" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +# ES +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "ספרד" + +# EE +#. :ESP:724: +#: zypp/CountryCode.cc:224 +#, fuzzy +msgid "Ethiopia" +msgstr "אסטוניה" + +# FI +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "פינלנד" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +# IE +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "איי פר-אר" + +# FR +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "צרפת" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "" + +# GD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "גרנדה" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr " ג'ורג'יה" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +#, fuzzy +msgid "French Guiana" +msgstr "צרפתית (קנדה)" + +# DE +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "גרמניה" + +# CN +#: zypp/CountryCode.cc:238 +#, fuzzy +msgid "Ghana" +msgstr "סין" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "" + +# GD +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "גרינלנד" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +# GR +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "יוון" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +# GT +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "גואטמלה" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +#, fuzzy +msgid "Guam" +msgstr "משחקים" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "הונג-קונג" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +# HN +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "הונדורס" + +# HR +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "קרואטיה" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +#, fuzzy +msgid "Haiti" +msgstr "המתן" + +# HU +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "הונגריה" + +# ID +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "אינדונזיה" + +# IE +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "אירלנד" + +# IL +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "ישראל" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +# IN +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "הודו" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +# IQ +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "עירק" + +# IQ +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +#, fuzzy +msgid "Iran" +msgstr "עירק" + +# IS +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "איסלנד" + +# IT +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "איטליה" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "" + +# JO +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "ירדן" + +# JP +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "יפן" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +#, fuzzy +msgid "Cambodia" +msgstr "קולומביה" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +# Frame description in suggested partition for mode accept modify .. +#. :KIR:296: +#: zypp/CountryCode.cc:275 +#, fuzzy +msgid "Comoros" +msgstr "בחרו" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "" + +# ZA +#. :PRK:408: +#: zypp/CountryCode.cc:278 +#, fuzzy +msgid "South Korea" +msgstr "דרום אפריקה" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "כווית " + +# IE +#. :KWT:414: +#: zypp/CountryCode.cc:280 +#, fuzzy +msgid "Cayman Islands" +msgstr "איי פר-אר" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +#, fuzzy +msgid "Kazakhstan" +msgstr "פקיסטן" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "לבנון" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +#, fuzzy +msgid "Sri Lanka" +msgstr "סרבית" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +# LT +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "ליטא" + +# LU +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "לוקסמבורג" + +# LV +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "לטביה" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "מרוקו" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +#, fuzzy +msgid "Monaco" +msgstr "שני" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +#, fuzzy +msgid "Moldova" +msgstr "סלובקית" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "לווין" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "" + +# IE +#. :MDG:450: +#: zypp/CountryCode.cc:299 +#, fuzzy +msgid "Marshall Islands" +msgstr "איי פר-אר" + +# MK +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "מקדונית" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +#, fuzzy +msgid "Mali" +msgstr "&דואר" + +# PA +#. :MLI:466: +#: zypp/CountryCode.cc:302 +#, fuzzy +msgid "Myanmar" +msgstr "פנמה" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +#, fuzzy +msgid "Macao" +msgstr "מאורית" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +#, fuzzy +msgid "Martinique" +msgstr "דקה" + +# LT +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +#, fuzzy +msgid "Mauritania" +msgstr "ליטא" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +# MT +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "מלטה" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +#, fuzzy +msgid "Maldives" +msgstr "מלטזית" + +# MT +#. :MDV:462: +#: zypp/CountryCode.cc:312 +#, fuzzy +msgid "Malawi" +msgstr "מלטה" + +# MX +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "מקסיקו" + +# MT +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "מלזיה " + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +#, fuzzy +msgid "Mozambique" +msgstr "נייד" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "" + +# MK +#. :NAM:516: +#: zypp/CountryCode.cc:317 +#, fuzzy +msgid "New Caledonia" +msgstr "מקדונית" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +# IE +#. :NER:562: +#: zypp/CountryCode.cc:319 +#, fuzzy +msgid "Norfolk Island" +msgstr "איי פר-אר" + +# BG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +#, fuzzy +msgid "Nigeria" +msgstr "אלג'יר" + +# PY +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "ניקאראגואה" + +# NL +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "הולנד" + +# NO +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "נורבגיה" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +#, fuzzy +msgid "Niue" +msgstr "דקה" + +# NZ +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "ניו זילנד" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "עומן" + +# PA +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "פנמה" + +# PE +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "פרו" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +#, fuzzy +msgid "French Polynesia" +msgstr "צרפתית (קנדה)" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "הפיליפינים" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "פקיסטן" + +# PL +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "פולין" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +#, fuzzy +msgid "Pitcairn" +msgstr "פקיסטן" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "פורטו ריקו" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +# PT +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "פורטוגל" + +# PA +#. :PRT:620: +#: zypp/CountryCode.cc:341 +#, fuzzy +msgid "Palau" +msgstr "פאלם" + +# PY +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "פרגואי" + +# MT +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "קטאר" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +#, fuzzy +msgid "Reunion" +msgstr "&אזור" + +# RO +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "רומניה" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "סרבית" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +# CA +#. :RUS:643: +#: zypp/CountryCode.cc:348 +#, fuzzy +msgid "Rwanda" +msgstr "קנדה" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "ערב הסעודית" + +# IE +#. :SAU:682: +#: zypp/CountryCode.cc:350 +#, fuzzy +msgid "Solomon Islands" +msgstr "איי פר-אר" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +# SD +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "סודן" + +# SE +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "שבדיה" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "סינגפור" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +# SI +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "סלובניה" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +# SK +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "סלובקיה" + +# Device type label +#. :SVK:703: +#: zypp/CountryCode.cc:359 +#, fuzzy +msgid "Sierra Leone" +msgstr "קו סיריאלי" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +#, fuzzy +msgid "Senegal" +msgstr "בנגאלית" + +# RO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +#, fuzzy +msgid "Somalia" +msgstr "רומניה" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +# SV +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "אל סלבדור" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +#, fuzzy +msgid "Syria" +msgstr "סרבית" + +# TH +#. :SYR:760: +#: zypp/CountryCode.cc:367 +#, fuzzy +msgid "Swaziland" +msgstr "תאילנד" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +# CA +#. :TCA:796: +#: zypp/CountryCode.cc:369 +#, fuzzy +msgid "Chad" +msgstr "כרטיס" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +# TH +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "תאילנד" + +# TW +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "טאג'יקיסטן" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +# TW +#. :TKL:772: +#: zypp/CountryCode.cc:375 +#, fuzzy +msgid "Turkmenistan" +msgstr "טאג'יקיסטן" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "טוניס" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +# TR +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "טורקיה" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +#, fuzzy +msgid "Tuvalu" +msgstr "דיבור" + +# TH +#. :TUV:798: +#: zypp/CountryCode.cc:382 +#, fuzzy +msgid "Taiwan" +msgstr "תאילנד" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +# UA +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "אוקראינה" + +# CA +#. :UKR:804: +#: zypp/CountryCode.cc:385 +#, fuzzy +msgid "Uganda" +msgstr "קנדה" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +#, fuzzy +msgid "United States" +msgstr "איחוד הנסיכויות הערביות" + +# UY +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "אורוגואי" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "אוסביקיסטן" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +# VE +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "ונצואלה" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +#, fuzzy +msgid "Vietnam" +msgstr "וייטנאמית" + +# ComboBox item +#. :VNM:704: +#: zypp/CountryCode.cc:396 +#, fuzzy +msgid "Vanuatu" +msgstr "מדריך" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "תימן" + +# ComboBox item +#. :YEM:887: +#: zypp/CountryCode.cc:400 +#, fuzzy +msgid "Mayotte" +msgstr "אדון" + +# ZA +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "דרום אפריקה" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "זימבבואה " + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +# main dialog: Button Delete partition +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "&מחק" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +#, fuzzy +msgid "Abkhazian" +msgstr "אלבניה" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +#, fuzzy +msgid "Achinese" +msgstr "סינית" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "אפריקנס" + +# Edit field label for linux partition size in non-graphical mode +#. language code: ain +#: zypp/LanguageCode.cc:179 +#, fuzzy +msgid "Ainu" +msgstr "לינוקס:" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +#, fuzzy +msgid "Akan" +msgstr "אפריקנס" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +#, fuzzy +msgid "Albanian" +msgstr "אלבניה" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +# BD +#. language code: alg +#: zypp/LanguageCode.cc:191 +#, fuzzy +msgid "Algonquian Languages" +msgstr "שפות" + +# ZA +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "דרום אפריקה" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +#, fuzzy +msgid "Amharic" +msgstr "ערבית" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +# BD +#. language code: apa +#: zypp/LanguageCode.cc:199 +#, fuzzy +msgid "Apache Languages" +msgstr "שפות" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "ערבית" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +#, fuzzy +msgid "Aramaic" +msgstr "ערבית" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +# AR +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +#, fuzzy +msgid "Armenian" +msgstr "ארגנטינה" + +# UA +#. language code: arn +#: zypp/LanguageCode.cc:211 +#, fuzzy +msgid "Araucanian" +msgstr "אוקראינית" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +#, fuzzy +msgid "Arapaho" +msgstr "גרף" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +#, fuzzy +msgid "Assamese" +msgstr "משחקים" + +# AT +#. language code: ast +#: zypp/LanguageCode.cc:221 +#, fuzzy +msgid "Asturian" +msgstr "אוסטריה" + +# BD +#. language code: ath +#: zypp/LanguageCode.cc:223 +#, fuzzy +msgid "Athapascan Languages" +msgstr "שפות" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +#, fuzzy +msgid "Australian Languages" +msgstr "רשימת כל השפות האפשרויות" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +#, fuzzy +msgid "Avaric" +msgstr "ערבית" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "אזרביג'נית" + +# CA +#. language code: bad +#: zypp/LanguageCode.cc:237 +#, fuzzy +msgid "Banda" +msgstr "קנדה" + +# BD +#. language code: bai +#: zypp/LanguageCode.cc:239 +#, fuzzy +msgid "Bamileke Languages" +msgstr "שפות" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +#, fuzzy +msgid "Balinese" +msgstr "בסיס" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "בסקית" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +#, fuzzy +msgid "Basa" +msgstr "בסיס" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +# BY +#. language code: bel be +#: zypp/LanguageCode.cc:259 +#, fuzzy +msgid "Belarusian" +msgstr "בלרוס" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "בנגאלית" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +#, fuzzy +msgid "Bihari" +msgstr "בחריין" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +#, fuzzy +msgid "Bosnian" +msgstr "רומנית" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "ברטונית" + +# ID +#. language code: btk +#: zypp/LanguageCode.cc:287 +#, fuzzy +msgid "Batak (Indonesia)" +msgstr "אינדונזיה" + +# BG +#. language code: bua +#: zypp/LanguageCode.cc:289 +#, fuzzy +msgid "Buriat" +msgstr "בולגריה" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +#, fuzzy +msgid "Buginese" +msgstr "סינית" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "בולגרית" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +#, fuzzy +msgid "Blin" +msgstr "בלגית" + +# CA +#. language code: cad +#: zypp/LanguageCode.cc:301 +#, fuzzy +msgid "Caddo" +msgstr "כרטיס" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +# CA +#. language code: car +#: zypp/LanguageCode.cc:305 +#, fuzzy +msgid "Carib" +msgstr "כרטיס" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "קטלונית" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +#, fuzzy +msgid "Cebuano" +msgstr "לבנון" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +# CN +#. language code: chb +#: zypp/LanguageCode.cc:317 +#, fuzzy +msgid "Chibcha" +msgstr "סין" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +#, fuzzy +msgid "Chechen" +msgstr "צ'כית" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "סינית" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +#, fuzzy +msgid "Chuukese" +msgstr "סינית" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +#, fuzzy +msgid "Mari" +msgstr "מאורית" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +# BD +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "שפות" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +#, fuzzy +msgid "Coptic" +msgstr "מיחשוב" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +#, fuzzy +msgid "Cornish" +msgstr "אירית" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +#, fuzzy +msgid "Corsican" +msgstr "קוסטה ריקה" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +# HR +# heading text +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +#, fuzzy +msgid "Cree" +msgstr "צור" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "צ'כית" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "דנית" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +#, fuzzy +msgid "Dayak" +msgstr "יום:" + +# Table header 4/4 +#. language code: del +#: zypp/LanguageCode.cc:381 +#, fuzzy +msgid "Delaware" +msgstr "חומרה" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +#, fuzzy +msgid "Dinka" +msgstr "כונן" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +#, fuzzy +msgid "Dogri" +msgstr "מאורית" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +#, fuzzy +msgid "Lower Sorbian" +msgstr "סרבית" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +#, fuzzy +msgid "Duala" +msgstr "יומי" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "הולנדית" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +#, fuzzy +msgid "English" +msgstr "אנגלית (אנגליה)" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "אספרנטו" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "אסטונית" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +# Column header: minimum = 4 characters fill with space if needed +#. language code: ewo +#: zypp/LanguageCode.cc:427 +#, fuzzy +msgid "Ewondo" +msgstr "סוף" + +# FR +#. language code: fan +#: zypp/LanguageCode.cc:429 +#, fuzzy +msgid "Fang" +msgstr "צרפת" + +# Label for free part of the partition in non-graphical mode +# Label for free part of the Windows partition in non-graphical mode +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +#, fuzzy +msgid "Faroese" +msgstr "פנוי:" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +#, fuzzy +msgid "Fanti" +msgstr "פונטים" + +# FI +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +#, fuzzy +msgid "Fijian" +msgstr "פינלנד" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +#, fuzzy +msgid "Filipino" +msgstr "הפיליפינים" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "פינית" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +#, fuzzy +msgid "Fon" +msgstr "פונטים" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "צרפתית" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +# label text +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +#, fuzzy +msgid "Frisian" +msgstr "&גירסת FS" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +# FI +#. language code: fur +#: zypp/LanguageCode.cc:457 +#, fuzzy +msgid "Friulian" +msgstr "פינלנד" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +#, fuzzy +msgid "Germanic (Other)" +msgstr "גרמנית (עם מקשים מתים)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +#, fuzzy +msgid "Georgian" +msgstr " ג'ורג'יה" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "גרמנית" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +#, fuzzy +msgid "Geez" +msgstr "יוונית" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +#, fuzzy +msgid "Gilbertese" +msgstr "וייטנאמית" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "אירית" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +#, fuzzy +msgid "Galician" +msgstr "איטלקית" + +# ComboBox item +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +#, fuzzy +msgid "Manx" +msgstr "מדריך" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +# SD +#. language code: gon +#: zypp/LanguageCode.cc:491 +#, fuzzy +msgid "Gondi" +msgstr "קול" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +#, fuzzy +msgid "Grebo" +msgstr "קבוצה" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +#, fuzzy +msgid "Guarani" +msgstr "הונגרית" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +#, fuzzy +msgid "Gujarati" +msgstr "אורך" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +# Table header 4/4 +#. language code: hai +#: zypp/LanguageCode.cc:511 +#, fuzzy +msgid "Haida" +msgstr "חומרה" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "לטבית" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "עברית" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +#, fuzzy +msgid "Herero" +msgstr "שגיאה" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +#, fuzzy +msgid "Hindi" +msgstr "סוג" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +#, fuzzy +msgid "Upper Sorbian" +msgstr "סרבית" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "הונגרית" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "איסלנדית" + +# Column header +#. language code: ido io +#: zypp/LanguageCode.cc:549 +#, fuzzy +msgid "Ido" +msgstr "Id" + +# LT +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "ליטא" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +#, fuzzy +msgid "Interlingue" +msgstr "המשך" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "אינדונזית" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +# IN +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +#, fuzzy +msgid "Inupiaq" +msgstr "הודו" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +# BD +#. language code: iro +#: zypp/LanguageCode.cc:575 +#, fuzzy +msgid "Iroquoian Languages" +msgstr "שפות" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "איטלקית" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +#, fuzzy +msgid "Javanese" +msgstr "יפנית" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +#, fuzzy +msgid "Lojban" +msgstr "לבנון" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "יפנית" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +#, fuzzy +msgid "Judeo-Persian" +msgstr "אינדונזית" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +#, fuzzy +msgid "Judeo-Arabic" +msgstr "ערבית" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +#, fuzzy +msgid "Kabyle" +msgstr "מאופשר" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +#, fuzzy +msgid "Kachin" +msgstr "בחריין" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +# CA +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +#, fuzzy +msgid "Kannada" +msgstr "קנדה" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +#, fuzzy +msgid "Karen" +msgstr "קוריאנית" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +#, fuzzy +msgid "Kanuri" +msgstr "כורדית" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +#, fuzzy +msgid "Kawi" +msgstr "כווית " + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +#, fuzzy +msgid "Khasi" +msgstr "תאילנדית" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +#, fuzzy +msgid "Khmer" +msgstr "אחר" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +#, fuzzy +msgid "Khotanese" +msgstr "סינית" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +#, fuzzy +msgid "Kimbundu" +msgstr "סוג" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +#, fuzzy +msgid "Konkani" +msgstr "קוריאנית" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "קוריאנית" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +#, fuzzy +msgid "Kosraean" +msgstr "קוריאנית" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +#, fuzzy +msgid "Kpelle" +msgstr "איות" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +#, fuzzy +msgid "Kurukh" +msgstr "טורקית" + +# PA +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +#, fuzzy +msgid "Kuanyama" +msgstr "פנמה" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +#, fuzzy +msgid "Kumyk" +msgstr "דמה" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "כורדית" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +#, fuzzy +msgid "Kutenai" +msgstr "כווית " + +#. language code: lad +#: zypp/LanguageCode.cc:655 +#, fuzzy +msgid "Ladino" +msgstr "רדיו" + +# CA +#. language code: lah +#: zypp/LanguageCode.cc:657 +#, fuzzy +msgid "Lahnda" +msgstr "קנדה" + +# Column header +#. language code: lam +#: zypp/LanguageCode.cc:659 +#, fuzzy +msgid "Lamba" +msgstr "תווית" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +#, fuzzy +msgid "Lao" +msgstr "לבנון" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +#, fuzzy +msgid "Latin" +msgstr "לטבית" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "לטבית" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +#, fuzzy +msgid "Lezghian" +msgstr "בלגית" + +# LU +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "לוקסמבורג" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "ליטאית" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +#, fuzzy +msgid "Lozi" +msgstr "&חיבור" + +# LU +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "לוקסמבורג" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +# CA +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +#, fuzzy +msgid "Ganda" +msgstr "קנדה" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +# SD +#. language code: lun +#: zypp/LanguageCode.cc:689 +#, fuzzy +msgid "Lunda" +msgstr "ראשון" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "תאילנדית" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "מקדונית" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +#, fuzzy +msgid "Madurese" +msgstr "מלטזית" + +# MT +#. language code: mag +#: zypp/LanguageCode.cc:701 +#, fuzzy +msgid "Magahi" +msgstr "מתמטיקה" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +#, fuzzy +msgid "Marshallese" +msgstr "מלטזית" + +# MT +#. language code: mai +#: zypp/LanguageCode.cc:705 +#, fuzzy +msgid "Maithili" +msgstr "מתמטיקה" + +# MT +#. language code: mak +#: zypp/LanguageCode.cc:707 +#, fuzzy +msgid "Makasar" +msgstr "מלזיה " + +# MT +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +#, fuzzy +msgid "Malayalam" +msgstr "מלזיה " + +#. language code: man +#: zypp/LanguageCode.cc:711 +#, fuzzy +msgid "Mandingo" +msgstr "אזהרה" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "מאורית" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +# MT +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +#, fuzzy +msgid "Marathi" +msgstr "מתמטיקה" + +# MT +#. language code: mas +#: zypp/LanguageCode.cc:721 +#, fuzzy +msgid "Masai" +msgstr "מלזיה " + +# MT +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "מלטה" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +# ComboBox item +#. language code: mdr +#: zypp/LanguageCode.cc:729 +#, fuzzy +msgid "Mandar" +msgstr "מדריך" + +#. language code: men +#: zypp/LanguageCode.cc:731 +#, fuzzy +msgid "Mende" +msgstr "מצב" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +# label text +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "בחרו שפה:" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +# MT +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "מלזיה " + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "מלטזית" + +# ComboBox item +#. language code: mnc +#: zypp/LanguageCode.cc:747 +#, fuzzy +msgid "Manchu" +msgstr "מדריך" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +#, fuzzy +msgid "Manipuri" +msgstr "מאורית" + +# BD +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "שפות" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "יגוסלביה" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +#, fuzzy +msgid "Mongolian" +msgstr "מקדונית" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +#, fuzzy +msgid "Mossi" +msgstr "מורס" + +# BD +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "שפות" + +# BD +#. language code: mun +#: zypp/LanguageCode.cc:763 +#, fuzzy +msgid "Munda languages" +msgstr "שפות" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +#, fuzzy +msgid "Creek" +msgstr "יוונית" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +#, fuzzy +msgid "Mirandese" +msgstr "מלטזית" + +# Table header 4/4 +#. language code: mwr +#: zypp/LanguageCode.cc:769 +#, fuzzy +msgid "Marwari" +msgstr "חומרה" + +# BD +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "שפות" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +# ComboBox item +#. language code: nah +#: zypp/LanguageCode.cc:775 +#, fuzzy +msgid "Nahuatl" +msgstr "מדריך" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +#, fuzzy +msgid "Navajo" +msgstr "ניווט" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "גרמנית" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +#, fuzzy +msgid "Nepali" +msgstr "בנגאלית" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +#, fuzzy +msgid "Norwegian Nynorsk" +msgstr "הנורבגית" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +#, fuzzy +msgid "Norwegian Bokmal" +msgstr "הנורבגית" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "הנורבגית" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "" + +# BD +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "שפות" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +# CL +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +#, fuzzy +msgid "Chichewa" +msgstr "צ'ילה" + +# table header texts +#. language code: nym +#: zypp/LanguageCode.cc:821 +#, fuzzy +msgid "Nyamwezi" +msgstr "שם" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +#, fuzzy +msgid "Ossetian" +msgstr "רוסית" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +# BD +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "שפות" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +#, fuzzy +msgid "Pangasinan" +msgstr "הונגרית" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +# PY +#. language code: pam +#: zypp/LanguageCode.cc:851 +#, fuzzy +msgid "Pampanga" +msgstr "פרגואי" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +#, fuzzy +msgid "Panjabi" +msgstr "פונוגאבי" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +#, fuzzy +msgid "Papiamento" +msgstr "ניהול" + +# PY +#. language code: pau +#: zypp/LanguageCode.cc:857 +#, fuzzy +msgid "Palauan" +msgstr "פרגואי" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +#, fuzzy +msgid "Persian" +msgstr "סרבית" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +#, fuzzy +msgid "Philippine (Other)" +msgstr "הפיליפינים" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +#, fuzzy +msgid "Phoenician" +msgstr "סלובנית" + +# PA +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +#, fuzzy +msgid "Pali" +msgstr "פאלם" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "פולנית" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +#, fuzzy +msgid "Pohnpeian" +msgstr "אינדונזית" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "פורטוגזית" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "שפה עיקרית: %1" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +# TW +#. language code: raj +#: zypp/LanguageCode.cc:885 +#, fuzzy +msgid "Rajasthani" +msgstr "טאג'יקיסטן" + +# JP +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "יפן" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +# RO +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "רומניה" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "רומנית" + +# SD +#. language code: run rn +#: zypp/LanguageCode.cc:901 +#, fuzzy +msgid "Rundi" +msgstr "קול" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "רוסית" + +# CA +#. language code: sad +#: zypp/LanguageCode.cc:905 +#, fuzzy +msgid "Sandawe" +msgstr "קנדה" + +# SD +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +#, fuzzy +msgid "Sango" +msgstr "סודן" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +#, fuzzy +msgid "Yakut" +msgstr "נקודת שבירה" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +# BD +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "שפות" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +# Column header: minimum = 5 characters fill with space if needed +#. language code: san sa +#: zypp/LanguageCode.cc:917 +#, fuzzy +msgid "Sanskrit" +msgstr "התחלה" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +#, fuzzy +msgid "Santali" +msgstr "לווין" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "סרבית" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +#, fuzzy +msgid "Scots" +msgstr "איקונים" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "קרואטית" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +#, fuzzy +msgid "Selkup" +msgstr "דלג" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +# BD +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "שפות" + +# SD +#. language code: shn +#: zypp/LanguageCode.cc:943 +#, fuzzy +msgid "Shan" +msgstr "סודן" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +# label text +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "בחרו שפה:" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "סלובקית" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "סלובנית" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +# BD +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "שפות" + +# label text +#. language code: smj +#: zypp/LanguageCode.cc:967 +#, fuzzy +msgid "Lule Sami" +msgstr "&שם למודול" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +#, fuzzy +msgid "Samoan" +msgstr "עומן" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +# SI +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +#, fuzzy +msgid "Shona" +msgstr "סלובניה" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +#, fuzzy +msgid "Sindhi" +msgstr "סוג" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +#, fuzzy +msgid "Soninke" +msgstr "המשך" + +# SD +#. language code: sog +#: zypp/LanguageCode.cc:981 +#, fuzzy +msgid "Sogdian" +msgstr "סודן" + +# RO +#. language code: som so +#: zypp/LanguageCode.cc:983 +#, fuzzy +msgid "Somali" +msgstr "רומניה" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "ספרדית" + +# UA +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +#, fuzzy +msgid "Sardinian" +msgstr "אוקראינית" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +#, fuzzy +msgid "Serer" +msgstr "שרת" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +# Column header: minimum = 5 characters fill with space if needed +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +#, fuzzy +msgid "Swati" +msgstr "התחלה" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +#, fuzzy +msgid "Sukuma" +msgstr "סיכום" + +# SD +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +#, fuzzy +msgid "Sundanese" +msgstr "סודן" + +# heading text +#. language code: sus +#: zypp/LanguageCode.cc:1003 +#, fuzzy +msgid "Susu" +msgstr "סטטוס" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +#, fuzzy +msgid "Sumerian" +msgstr "סרבית" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "שבדית" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +#, fuzzy +msgid "Syriac" +msgstr "שרות" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +#, fuzzy +msgid "Tahitian" +msgstr "לטבית" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +#, fuzzy +msgid "Tai (Other)" +msgstr "אחר" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "טמילית" + +# MT +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "קטאר" + +# BE +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +#, fuzzy +msgid "Telugu" +msgstr "בלגיה" + +# label text +#. language code: tem +#: zypp/LanguageCode.cc:1023 +#, fuzzy +msgid "Timne" +msgstr "אזור זמן" + +# MX +#. language code: ter +#: zypp/LanguageCode.cc:1025 +#, fuzzy +msgid "Tereno" +msgstr "מידעטקסט" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +#, fuzzy +msgid "Tetum" +msgstr "טקסט" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +#, fuzzy +msgid "Tajik" +msgstr "דיבור" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "תאילנדית" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +#, fuzzy +msgid "Tsimshian" +msgstr "רוסית" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +#, fuzzy +msgid "Tswana" +msgstr "בוטסואנה" + +# EE +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +#, fuzzy +msgid "Tsonga" +msgstr "אסטוניה" + +# TR +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "טורקיה" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +# BD +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "שפות" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "טורקית" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +#, fuzzy +msgid "Tuvinian" +msgstr "טוניס" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +# UA +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "אוקראינית" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +#, fuzzy +msgid "Uzbek" +msgstr "אוסביקיסטן" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +# GD +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +#, fuzzy +msgid "Venda" +msgstr "גרנדה" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "וייטנאמית" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +# BD +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "שפות" + +# PA +#. language code: wal +#: zypp/LanguageCode.cc:1109 +#, fuzzy +msgid "Walamo" +msgstr "פאלם" + +# PY +#. language code: war +#: zypp/LanguageCode.cc:1111 +#, fuzzy +msgid "Waray" +msgstr "פרגואי" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +#, fuzzy +msgid "Washo" +msgstr "וולשית" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "וולשית" + +# label text +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "בחרו שפה:" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +#, fuzzy +msgid "Kalmyk" +msgstr "דיבור" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "קוזה" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +#, fuzzy +msgid "Yapese" +msgstr "יפנית" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +# BD +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "שפות" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +# GD +#. language code: zen +#: zypp/LanguageCode.cc:1141 +#, fuzzy +msgid "Zenaga" +msgstr "גרנדה" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +#, fuzzy +msgid "Zhuang" +msgstr "&שינוי" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "זולו" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +# column description, if disk space is not known +# label text +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "לא ידוע" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +# IT +#: zypp/VendorSupportOptions.cc:33 +#, fuzzy +msgid "invalid" +msgstr "התקן" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +# Frame title for installation target hard disk / partition(s) +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "מתקין על:" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Couldn't open file: %s." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +# Frame title for installation target hard disk / partition(s) +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "מתקין על:" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +# IT +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "התקן" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +# Commandline help title +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "קורא קובץ הגדרות" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "מידע נוסף" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, fuzzy, c-format, boost-format +msgid "created backup %s" +msgstr "אל תיצור גיבויים" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "פקודה לביצוע כאשר מתחברים" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +# Frame title for installation target hard disk / partition(s) +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "מתקין על:" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +# Frame title for installation target hard disk / partition(s) +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "מתקין על:" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "כן" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "לא" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "שגיאה" + +# ID +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "done" +msgstr "אינדונזיה" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "שגיאה" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "לא מחובר" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +#, fuzzy +msgid "yes" +msgstr "כן" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "ארכיטקטורה:" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "התקנה נכשלה" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "מתקין על:" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "do not install %s" +#~ msgstr "מתקין על:" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "מתקין על:" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "מתקין דריבר..." + +# main dialog: Button Delete partition +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "&מחק" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "מתקין על:" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "לא מחובר" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "מתקין על:" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "%s remove failed" +#~ msgstr "rpm נכשל." + +#, fuzzy +#~ msgid "%s install failed" +#~ msgstr "התקנה נכשלה" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "מתקין דריבר..." + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "מתקין דריבר..." + +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "מתקין דריבר..." + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "מתקין דריבר..." + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "install %s" +#~ msgstr "מתקין על:" + +#, fuzzy +#~ msgid "unlock %s" +#~ msgstr "שעונים" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "מתקין דריבר..." + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "No need to install %s" +#~ msgstr "&בוט מערכת קיימת" + +#, fuzzy +#~ msgid ", Action: " +#~ msgstr "פעולה" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "Establishing %s" +#~ msgstr "מתקין על:" + +#, fuzzy +#~ msgid " Error!" +#~ msgstr "שגיאה" + +#~ msgid "Ok" +#~ msgstr "בסדר" + +#~ msgid "Default" +#~ msgstr "ברירת מחדל" diff --git a/po/hi.po b/po/hi.po new file mode 100644 index 0000000..279d79d --- /dev/null +++ b/po/hi.po @@ -0,0 +1,5859 @@ +# translation of zypp.hi.po to Hindi +# Sangeeta Kumari , 2007. +msgid "" +msgstr "" +"Project-Id-Version: zypp.hi\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2021-04-08 15:57+0000\n" +"Last-Translator: Panwar \n" +"Language-Team: Hindi \n" +"Language: hi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 3.6.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "अज्ञात देश : " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "कोई कोड नहीं" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "अंदोर्रा" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "संयुक्त अरब अमीरात" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "अफगानिस्तान" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "एंटीगुआ और बारबूडा" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "अंग्युला" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "अल्बानिया" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "अर्मेनिया" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "नीदरलैंड एंटीलस" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "अंगोला" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "अंटार्कटिक" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "अर्जेंटीना" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "अमेरिकी समोआ" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "आस्ट्रिया" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "आस्ट्रेलिया" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "अरूबा" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "अलांड आइलैंड्स" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "अज़रबैजान" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "बोस्निया और हर्जेगोविना" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "बारबाडोस" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "बांग्लादेश" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "बेल्ज़ियम" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "बुर्किना फासो" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "बुल्गारिया" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "बहरीन" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "बुरूंडी" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "बेनिन" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "बरमूडा" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "ब्रुनेई दारूस्सलम" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "बोलेविया" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "ब्राज़ील" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "बहामस" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "भूटान" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "बोउवेत आइसलैंड" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "बोत्सवाना" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "बेलारूस" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "बेलिजी" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "कनाडा" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "कोकोस (कीलिंग) आइलैंड्स" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "कांगो" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "मध्य अफ्रीकी गणराज्य" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "स्विट्ज़रलैंड" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "कोटे डी'आईवोर" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "कुक आइलैंड्स" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "चीले" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "कैमरून" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "चीन" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "कोलंबिया" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "कोस्टा रिका" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "क्यूबा" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "केप वेर्दे" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "क्रिसमस आइसलैंड" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "साइप्रस" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "चेक गणराज्य" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "जर्मनी" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "जिबूती" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "डेनमार्क" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "डोमिनिका" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "डोमिनिका गणराज्य" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "अल्ज़ीरिया" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "इक्वाडोर" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "एस्तोनिया" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "मिश्र" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "पश्चिमी सहारा" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "इरीट्रिया" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "स्पेन" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "इथियोपिया" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "फिनलैंड" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "फिज़ी" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "फाल्कलैंड आइलैंड्स (माल्विनास)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "माइक्रोनेशिया संघीय गणराज्य" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "फरोए आइलैंड्स" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "फ्रांस" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "मेट्रोपोलिटन फ्रांस" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "गाबोन" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "यूनाइटेड किंगडम" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "ग्रेनेडा" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "जार्जिया" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "फ्रेंच गुआना" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "जर्मनी" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "घाना" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "जिब्राल्टर" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "ग्रीनलैंड" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "गाम्बिया" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "गिनी" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "ग्वाडेलोप" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "विषुवतरेखीय गिनी" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "ग्रीस" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "दक्षिणी जॉर्जिया और साउथ सैंडविच आइलैंड्स" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "ग्वाटेमाला" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "गुआम" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "गिनी-बिसाउ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "गुआना" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "हांग-कांग" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "हेर्ड आइसलैंड और मैकडोनाल्ड आइलैंड्स" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "होंडुरास" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "क्रोएशिया" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "हाती" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "हंगरी" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "इंडोनेशिया" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "आयरलैंड" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "इज़रायल" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "भारत" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "ब्रिटिश भारतीय समुद्री क्षेत्र" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "इराक" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "इरान" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "आइसलैंड" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "इटली" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "जमाइका" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "जॉर्डन" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "जापान" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "केन्या" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "किर्गिज़तान" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "कंबोडिया" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "किरिबाती" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "कोमोरोस" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "सेंट किट्स और नेविस" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "उत्तरी कोरिया" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "दक्षिणी कोरिया" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "कुवैत" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "केमन आइलैंड" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "कज़ाकिस्तान" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "लाओ लोक जनवादी गणराज्य" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "लेबनान" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "सेंट लुसिया" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "लिचटेंसटीन" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "श्रीलंका" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "लिबेरिया" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "लेसोथो" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "लिथुआनिया" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "लक्ज़मबर्ग" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "लटाविया" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "लीबिया" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "मोरक्को" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "मोनाका" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "माल्दोवा" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "मोंगो" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "सैन मारिनो" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "मेडागास्कर" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "मार्शल आइलैंड्स" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "मकदूनिया" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "माली" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "म्यांमार" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "मंगोलिया" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "मकाउ" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "उत्तरी मारिआना आइलैंड" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "मारतिनिक" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "मॉरितानिया" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "मांतसेरा" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "माल्टा" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "मॉरीशस" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "मालदीव" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "मलावी" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "मेक्सिको" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "मलेशिया" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "मोजाम्बिक" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "नामीबिया" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "न्यू कैलडोनिया" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "नाइज़र" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "नॉरफोक आइसलैंड" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "नाइजीरिया" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "निकारागुआ" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "नीदरलैंड्स" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "नॉर्वे" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "नेपाल" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "नाउरू" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "नियू" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "न्यूजीलैंड" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "ओमान" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "पनामा" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "पेरू" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "फ्रेंच पॉलीनेशिया" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "पापुआ न्यू गिनी" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "फिलिपीन्स" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "पाकिस्तान" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "पोलैंड" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "सेंट पिअरे और मिक्यूलॉन" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "पिटकैरन" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "प्यूर्टो रिको" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "फिलीस्तीनी क्षेत्र" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "पुर्तगाल" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "पलाउ" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "पैरागुआ" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "कतर" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "रियूनियन" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "रोमानिया" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "सर्बियाई" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "रूसी महासंघ" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "रवांडा" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "सउदी अरब" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "सोलोमन आइलैंड" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "सेशेल्स" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "सूडान" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "स्वीडेन" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "सिंगापुर" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "सेंट हेलेना" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "स्लोविनिया" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "स्वालबार्ड और जेन मायेन" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "स्लोवाकिया" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "सिएरा लिओन" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "सैन मारिनो" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "सेनेगल" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "सोमालिया" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "सूरीनाम" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "साओ टोम और प्रिंसीप" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "अलसल्वाडोर" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "सीरिया" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "स्वाजिलैंड" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "तुर्क और कैकस आइलैंड" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "चाड" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "फ्रांसीसी दक्षिणी क्षेत्र" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "टोगो" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "थाईलैंड" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "तजाकिस्तान" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "तोकेलाउ" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "तुर्कमेनिस्तान" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ट्यूनेशिया" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "टोंगा" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "पूर्वी तिमोर" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "टर्की" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "त्रिनिदाद और टोबागो" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "तुवालू" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "ताइवान" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "तंजानिया" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "उक्रेन" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "उगांडा" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "संयुक्त राज्य के छोटे दूरस्थ द्वीप" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "संयुक्त राज्य" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "उरुग्वे" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "उज़बेकिस्तान" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "होली सी (वैटिकन सिटी राज्य)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "सेंट विनसेंट और द ग्रेनाडिनेस" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "वेनेजुएला" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "ब्रिटिश वर्जिन आइलैंड" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "वर्जिन आइलैंड, यू.एस." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "वियतनाम" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "वनुआतू" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "वालिस और फ्यूतूना" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "समोआ" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "यमन" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "मयोट्टे" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "दक्षिण अफ्रीका" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "जांबिया" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "जिम्बाबवे" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s पुराना कर देता है : %s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "%s %s नहीं मिला" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "अज्ञात भाषा : " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "अफार" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "अबखाजिआन" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "अचाइनीज" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "अकोली" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "अदांगमे" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "अदाइघे" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "अफ्रो-एशियाटिक(अन्य)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "अफ्रिहिली" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "अफ्रीकांस" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "ऐनू" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "अकान" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "अकादियान" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "अल्बेनियाई" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "एल्यूत" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "अलगांक्यूएन भाषाएं" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "दक्षिणी अल्ताई" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "अम्हारिक" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "अंग्रेजी, पुरानी (सीए. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "अपाची भाषाएं" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "अरबी" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "अरामाइक" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "अरागोनीज़" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "अर्मीनियाई" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "अरॉकेनियाई" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "अरापाहो" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "कृत्रिम (अन्य)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "अरावक" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "असमिया" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "अस्तूरियन" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "अथापास्कन भाषाएं" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "आस्ट्रेलियाई भाषाएं" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "अवारिक" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "अवेस्तान" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "अवधी" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "ऐमारा" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "अज़रबैजानी" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "बांदा" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "बमिलिक भाषाएं" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "बशकीर" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "बलूची" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "बंबारा" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "बलिनीज़" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "बास्क्यू" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "बासा" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "बाल्टिक (अन्य)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "बेजा" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "बेलारूसी" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "बेंबा" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "बंगाली" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "बेरबेर (अन्य)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "भोजपुरी" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "बिहारी" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "बिकोल" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "बिनि" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "बिसलामा" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "सिकसिका" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "बंतू (अन्य)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "बोस्नियाई" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "ब्रज" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "ब्रेटोन" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "बताक (इंडोनेशियाई)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "बुरियात" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "बुगीनीज़" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "बुल्गारियाई" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "बर्मी" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "ब्लिन" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "केडो" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "केंद्रीय अमेरिकी भारतीय (अन्य)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "केरिब" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "केटेलन" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "काकेशियाई (अन्य)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "सेब्यूनो" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "सेल्टीक (अन्य)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "चमोरो" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "चिबचा" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "चेचेन" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "छगाताई" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "चीनी" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "चुकीज़" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "मारी" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "चिनूक जार्गन" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "चोक्टॉ" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "चिप्यूयन" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "चेरोकी" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "चर्च स्लाविक" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "चुवास" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "चेयेन्ने" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "चामिक भाषाएं" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "कोप्टिक" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "कॉर्निश" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "कोर्सिकन" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "क्रियोलेस और पिडगिंस, अंग्रेजी-आधारित (अन्य)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "क्रियोलेस और पिडगिंस, फ्रांसीसी-आधारित (अन्य)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "क्रियोलेस और पिडगिंस, पुर्तगाली-आधारित (अन्य)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "क्री" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "क्रीमियाई तातार" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "क्रियोलेस और पिडगिंस (अन्य)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "कशुबियन" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "क्युशीटिक (अन्य)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "चेक" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "डाकोटा" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "दानिश" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "दरग्वा" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "दयाक" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "देलावारे" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "स्लेव (अथापास्कन)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "डोगरिब" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "दिन्का" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "दिवेही" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "डोगरी" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "द्रविड़ियन (अन्य)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "लोअर सोर्बियन" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "ड्यूला" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "डच, मध्य (सीए. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "डच" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ड्यूला" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "द्जोंगखा" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "इफिक" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "मिश्री (प्राचीन)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "इकाजुक" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "इलामाइट" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "अंग्रेजी" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "अंग्रेजी, मध्य (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "एस्परांतो" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "एस्टोनियाई" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "इवी" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "इवॉन्डो" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "फांग" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "फारोइसी" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "फांती" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "फिजी" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "फिलिपीनो" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "फिन्निश" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "फिन्नो-उगरियन (अन्य)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "फॉन" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "फ्रेंच" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "फ्रेंच, मध्य (सीए. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "फ्रेंच, प्राचीन (842- सीए.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "फ्रीशियन" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "फुलाह" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "फ्रीयूलियन" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "गा" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "गायो" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "ग्बाया" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "जर्मेनिक (अन्य)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "जॉर्जियाई" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "जर्मन" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "गीज" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "जिब्रालटीज़" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "गैलिक" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "आयरिश" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "गालीसियन" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "मैंक्स" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "जर्मन, मिडिल हाई (सीए. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "जर्मन, ओल्ड हाई (सीए. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "गोंडी" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "गोरोन्टालो" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "गोथिक" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "ग्रेबो" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "ग्रीक, प्राचीन (1453 तक)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "ग्रीक, आधुनिक (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "गुआरानी" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "गुजराती" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "ग्विच'इन" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "हैदा" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "हैती" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "हाउसा" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "हवाइयन" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "हिब्रू" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "हेरेरो" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "हिलिगेनोन" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "हिमांचली" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "हिंदी" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "हिटिटी" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "ह्मांग" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "हिरी मोटू" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "ऊपरी सोर्बियाई" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "हंगेरियाई" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "हूपा" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "इबान" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "इग्बो" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "आइसलैंडी" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "आइडो" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "सिचुआन यी" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "आइजो" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "इनुकटिटुट" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "इंटरलिंगुआ" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "आईलोको" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "इण्टर्लिङ्गुआ" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "इंडिक (अन्य)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "इंडोनेशियाई" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "इंडो-यूरोपीय (अन्य)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "इंगुश" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "इन्यूपिआक" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "इरानी (अन्य)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "इरोक्योइयाई भाषाएं" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "इतालवी" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "जावा" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "लोजबान" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "जापानी" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "जूडेओ-पर्सियन" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "जूडेओ-अरबी" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "कारा-कालपक" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "कबाइली" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "काचिन" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "कालाल्लीसट" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "कांबा" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "कन्नड़" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "केरीन" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "कश्मीरी" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "कनुरी" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "कावी" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "कजाक" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "कबार्डियन" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "खासी" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "खोईसान (अन्य)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "खमेर" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "खोतानीज़" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "किकूयू" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "किनयारवांडा" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "किर्गिज़" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "किंबुंदु" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "कोंकणी" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "कोमी" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "कांगो" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "कोरियाई" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "कोस्राइयन" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "क्पेले" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "काराचय-बलकार" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "क्रु" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "कुरुख" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "कुआनयामा" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "कुम्यक" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "कुर्दिश" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "कुतेनाई" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "लादिनो" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "लाहंडा" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "लांबा" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "लाओ" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "लैटिन" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "लाटवियाई" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "लेझियन" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "लिम्बर्गन" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "लिंगाला" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "लिथुआनियाई" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "मोंगो" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "लोज़ी" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "लक्ज़मबर्गिश" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "ल्यूबा-लुलुआ" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "ल्यूबा-कातांगा" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "गांडा" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "ल्युसेनो" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "लुंडा" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "लुओ (केन्या और तंजानिया)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "लुशाई" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "मकदूनियाई" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "मदुरीस" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "मगही" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "मार्शलीज़" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "मैथिली" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "मकासर" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "मलयालम" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "मंदिनगो" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "माओरी" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "असट्रोनेसियाई (अन्य)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "मराठी" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "मसाइ" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "मलय" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "मोक्स" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "मंदार" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "मेंदे" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "आइरिश, मध्य (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "मि'कमाक" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "मिनांग्काबाउ" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "विविध भाषाएं" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "मॉन-खमेर (अन्य)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "मलागासी" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "माल्टीज़" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "मंचू" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "मणिपुरी" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "मनोबो भाषाएं" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "मोहॉक" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "मोल्देवियाई" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "मंगोलियाई" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "मोस्सी" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "अनेकशः भाषाएं" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "मुंडा भाषाएं" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "क्रीक" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "मिरांडीज़" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "मारवाड़ी" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "मयान भाषाएं" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "एर्जया" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "नाहुआट्ल" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "उत्तरी अमेरिकी भारतीय" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "नेपोलिटन" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "नावाजो" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "न्डेबेले, दक्षिणी" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "न्डेबेले, उत्तरी" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "न्डोंगा" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "लो जर्मन" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "नेपाली" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "नेपाल भाषा" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "नियास" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "नाइज़र-कोरदोफानियाई (अन्य)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "नियूएन" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "नॉर्वेजियाई निनॉर्स्क" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "नॉर्वेजियाई बोकमाल" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "नोगाइ" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "नोर्स, पुरानी" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "नॉर्वेजियाई" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "उत्तरी सोथो" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "न्यूबिअन भाषाएं" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "क्लासिकी नेवारी" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "चिचेवा" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "न्यामवेज़ी" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "न्यानकोले" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "न्योरो" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "न्ज़ीमा" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "ओक्कीटन (1500 पश्चात)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "ओज़िब्वा" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "उड़िया" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "ओरोमो" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "ओसेग" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "ओस्सेटियन" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "तुर्कीश, ऑट्टोमन (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "ओटोमियाई भाषाएं" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "पापुअन (अन्य)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "पनगासिनान" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "पहलावी" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "पाम्पांगा" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "पंजाबी" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "पापीमेंटो" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "पालाउन" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "फारसी, पुरानी (सीए. 600-400 ई.पू.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "फारसी" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "फिलीपीनी (अन्य)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "फोएनिसिअन" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "पाली" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "पोलिश" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "पोहन्पिअन" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "पुर्तगाली" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "प्राकृत भाषाएं" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "प्रोवेंसल, पुरानी (1500 तक)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "पश्तो" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "क्वेचुआ" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "राजस्थानी" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "रापान्वी" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "रारोतांगन" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "रोमांस (अन्य)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "रेइतो-रोमांस" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "रोमानी" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "रोमानियाई" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "रूंडी" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "रूसी" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "संदावी" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "सांगो" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "याकूत" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "दक्षिणी अमेरिकी भारतीय (अन्य)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "सलीशान भाषाएं" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "समारिटन अरामिक" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "संस्कृत" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "ससाक" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "संथाली" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "सर्बियाई" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "सिसिलियाई" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "स्काट्स" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "क्रोएशियाई" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "सेलकप" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "सेमिटिक (अन्य)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "आइरिश, पुरानी (900 तक)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "संकेत भाषाएं" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "शान" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "सिडामो" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "सिंहल" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "सिओअन भाषाएं" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "चीनी-तिब्बती (अन्य)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "स्लाव (अन्य)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "स्लोवाक" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "स्लोवेनियाई" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "दक्षिणी सामी" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "उत्तरी सामी" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "सामी भाषाएं (अन्य)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "लूले सामी" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "इनारी सामी" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "सामोन" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "सकोल्त सामी" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "शोना" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "सिंधी" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "सोनिंकी" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "सोगदिया" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "सोमाली" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "सोंघाई" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "सोथो, दक्षिणी" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "स्पेनी" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "सार्डीनियाई" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "सेरेर" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "निलो-सहारन (अन्य)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "स्वाति" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "सुकूमा" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "सुंडानी" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "सुसु" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "सुमेरियाई" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "स्वाहिली" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "स्वीडिश" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "सीरियाई" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "ताहितियन" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "ताई (अन्य)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "तमिल" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "तातार" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "तेलगू" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "तिम्ने" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "तेरेनो" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "तेतम" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "ताज़िक" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "टॅगलॉग" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "थाई" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "तिब्बती" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "तिगरे" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "तिग्रिन्या" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "तीव" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "क्लिंगों" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "त्लिंगित" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "तमाशेक" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "तोंगा (न्यासा)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "तोंगा (तोंगा आइलैंड्स)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "तोक पिसिन" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "त्सीमसियाई" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "त्सवाना" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "त्सोंगा" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "तुर्कमानी" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "तुमबुका" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "तुपी भाषाएं" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "तुर्कीश" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "अल्टाइक (अन्य)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "त्वी" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "तुविनियाई" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "उदमर्त" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "उगारिटिक" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "उइघुर" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "उक्रेनी" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "उंबुंदु" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "अनिर्धारित" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "उर्दू" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "उज़्बेक" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "वाइ" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "वेंदा" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "वियतनामी" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "वोलापुक" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "वोटिक" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "वाकाशान भाषाएं" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "वलामो" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "वरे" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "वाशो" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "वेल्श" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "सोर्बिअन भाषाएं" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "वलून" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "वोलोफ" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "कल्मीक" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "क्होसा" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "याओ" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "यापी" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "यिद्दिश" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "योरूबा" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "यूपिक भाषाएं" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "ज़ापोटेक" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "ज़ेनागा" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "झुआंग" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "ज़ेंदे" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "जुलु" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "ज़ुनी" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1' मौजूद नहीं है।" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1' मौजूद नहीं है।" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "अन्जान" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "अनंजान" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "अमान्य Url स्कीम '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "डायरेक्टरी को सृजित नहीं कर सकता %1 : %2" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "डेस्कटॉप आइटम '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, fuzzy, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "संसाधन जोड़ रहा" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "अमान्य निर्यात फाइलनाम।" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "लेखन के लिए फाइल नहीं खोल सकता है।" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "फ्लोपी डिस्क पढ़ने में त्रुटि।" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "संसाधन जोड़ रहा" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "डेस्कटॉप आइटम '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "जारी रखें?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"पैकेज %s ने एकीकरण जांच को नाकाम किया। क्या आप इसकी डाउनलोडिंग का प्रयास फिर से करना " +"चाहते हैं?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"पैकेज %s ने एकीकरण जांच को नाकाम किया। क्या आप इसकी डाउनलोडिंग का प्रयास फिर से करना " +"चाहते हैं?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm जांच नाकाम रही।" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm नाकाम रहा।" + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "संसाधन प्रकार वीएआर1 परिवर्तन दर्शाएं विशेषता को सहयोग नहीं करता" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "%s से %s प्रदान नहीं कर सकता" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "कोष में फाइल %1 नहीं प्राप्त हुई।" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "फाइल को सृजित नहीं कर सकता है।" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "सिर्फ यहां पर इस आवश्यकता की अनदेखी कर दें" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "सिर्फ यहां पर इस आवश्यकता की अनदेखी कर दें" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "के लिए कनेक्शन आवेदन : " + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "निर्भरता समस्याओं के कारण %s का संस्थापन नहीं कर सकता" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "कोई नहीं %s प्रदान करता" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "%s का कोई संस्थापनयोग्य प्रदाता नहीं है" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "%s का कोई संस्थापनयोग्य प्रदाता नहीं है" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "अनुरोध पहले से ही मौजूद है।" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "जैसा निर्देशित था, संस्थापन छोड़ दिया गया।" + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "निष्‍पादन" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "कुंजी एन्क्रिप्शन के दौरान त्रुटि।" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "विफल" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s हेतु विन्यास फ़ाइलें जिन्हें बदला गया :" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm ने %s के रूप में %s सहेजा लेकिन अंतर निर्धारित करना असंभव था " + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ने %s के रूप में %s सहेजा।\n" +"यहां अंतर की पहली 25 पंक्तियां हैं :\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm ने %s के रूप में %s सृजित किया लेकिन अंतर निर्धारित करना असंभव था" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ने %s के रूप में %s सृजित किया।\n" +"यहां अंतर की पहली 25 पंक्तियां हैं :\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "अतिरिक्त rpm आउटपुट :" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "बैकअप %s सृजित" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "%s %s नहीं मिला" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "%s %s नहीं मिला" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "%s %s नहीं मिला" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "फाइल %1 को नहीं खोल सकता है।" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "अमान्य LDAP URL क्वेरी स्ट्रिंग" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "अमान्य LDAP URL क्वेरी मानक '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Url ऑब्जेक्ट क्लोन करने में अक्षम" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "अमान्य रिक्त Url ऑब्जेक्ट संदर्भ" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Url अवयवों को पार्ज करने में अक्षम" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "इतिहास:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url स्कीम किसी %s को अनुमति नहीं देती है" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "अमान्य %s अवयव '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "अमान्य %s अवयव" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "इस URL के लिए क्वेरी स्ट्रिंग पार्जिंग समर्थित नहीं है" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url स्कीम एक आवश्यक अवयव है" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "अमान्य Url स्कीम '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url स्कीम किसी उपयोगकर्ता नाम को अनुमति नहीं देती है" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url स्कीम किसी पासवर्ड को अनुमति नहीं देती है" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url स्कीम को एक होस्ट अवयव की आवश्यकता है" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "यूआरएल व्यवस्था द्वारा होस्ट अनुभाग स्वीकार्य नहीं है" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "अमान्य होस्ट अवयव '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "यूआरएल व्यवस्था द्वारा पोर्ट स्वीकार्य नहीं है" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "अमान्य पोर्ट अवयव '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url स्कीम को पथ नाम की आवश्यकता है" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "यदि प्राधिकरण मौजूद है तो सापेक्ष पथ को अनुमति नहीं है" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "एनकोडेड स्ट्रिंग में एक NUL बाइट समाविष्ट है" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "अमान्य मानक क्रमविन्यास सेपरेटर वर्ण पृथक करें" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "अमान्य मानक मानचित्र सेपरेटर वर्ण पृथक करें" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "अमान्य मानक क्रमविन्यास सेपरेटर वर्ण जोड़ें" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "जब कनेक्ट हो रहे हों तब चलाया जाने वाला कमांड" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "%s को नहीं ढूंढ सकता।" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "%s को नहीं ढूंढ सकता।" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "%s - %s को खोलने में अक्षम\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "\"%s\" मोड्यूल लोड करने में असफल।" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "कोष में फाइल %1 नहीं प्राप्त हुई।" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "फाइल %1 पर नहीं लिख सकता है। " + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 एक डायरेक्टरी नहीं है।" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "रिक्त CA नाम।" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "अमान्य URL स्कीम '%1'" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "डेस्कटॉप आइटम '%s'" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "अनुमति अस्वीकृत" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "हाँ" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "नहीं" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "चेतावनी" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "खराबी" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "हो गया" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "त्रुटि" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "चेतावनी" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "आरंभ हो रहा है..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "नहीं मिला" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "हाँ" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "नहीं" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s ही %s प्रदान करता है, लेकिन इसके पास कोई और स्थापत्य है।" + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "पैकेजों को असंस्थापित करने का कमांड" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "कोई नहीं %s प्रदान करता" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "प्रमाण पत्र %1 मौजूद नहीं है।" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s लॉक हो गया है और इसे असंस्थापित नहीं किया जा सकता।" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "इंस्टाल नहीं हुआ" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s को %s की आवश्यकता है" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s का संस्थापन नहीं कर सकता" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s का %s से टकराव है " + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s को %s पुराना कर देता है" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s को %s पुराना कर देता है" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s का %s से टकराव है " + +#~ msgid "do not install %s" +#~ msgstr "%s संस्थापित न करें" + +#~ msgid "keep %s" +#~ msgstr "%s रखें" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "%s संस्थापित न करें" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "%s का कोई संस्थापनयोग्य प्रदाता नहीं है" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "संबंधित रिजॉल्वेबल को संस्थापित या मिटाएं नहीं" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s ही %s प्रदान करता है, लेकिन इसके पास कोई और स्थापत्य है।" + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "%s को संस्थापित करें यद्यपि यह स्थापत्य को बदल देगा" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s को %s पुराना कर देता है" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "%s से %s तक अपडेट कर रहा है" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "अधिष्ठापन" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "फाइल %1 को नहीं खोल सकता है।" + +#~ msgid "Hal Exception" +#~ msgstr "हाल अपवाद" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext कनेक्ट नहीं किया गया" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive आरंभ नहीं किया गया " + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume आरंभ नहीं किया गया" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "dbus कनेक्शन सृजित करने में अक्षम" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: libhal संदर्भ को सृजित नहीं कर सकता" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection : dbus कनेक्शन को सेट नहीं कर सकता" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "HAL संदर्भ को आरंभ करने में अक्षम -- hald नहीं रन कर रहा?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "कोई सीडीरोम ड्राइव नहीं" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "म्यूटेक्स गुण को आरंभ नहीं कर सकता" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "रिकर्सिव म्यूटेक्स गुण को सेट नहीं कर सकता" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "रिकर्सिव म्यूटेक्स को आरंभ नहीं कर सकता" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "म्यूटेक्स लॉक को हासिल नहीं कर सकता" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "म्यूटेक्स लॉक को रिलीज़ नहीं कर सकता" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "सार्वजनिक कुंजी को प्राप्त करने में अक्षम।" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "इंस्टाल नहीं हुआ" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "%s - %s को खोलने में अक्षम\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "सर्बिया और मोंटेनेग्रो" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "अज्ञात सूची विकल्प" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "निर्भरता हल नहीं की जा सकती" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाइल %s में कोई चेकसम नहीं है।\n" +#~ "फिर भी फाइल का प्रयोग करें?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाइल %s निम्नलिखित कुंजी के साथ एकीकरण जांच में नाकाम रही :\n" +#~ "%s|%s|%s\n" +#~ "फिर भी फाइल का प्रयोग करें?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाइल %s में एक अमान्य चेकसम है।\n" +#~ "%s की उम्मीद थी, %s मिला\n" +#~ "फिर भी फाइल का प्रयोग करें?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाइल %s में एक अमान्य चेकसम %s है।\n" +#~ "फिर भी फाइल का प्रयोग करें?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "फाइल %s साइन की हुई नहीं है।\n" +#~ "फिर भी इसका प्रयोग करें?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाइल %s को एक अज्ञात कुंजी से साइन किया गया है :\n" +#~ "%s|%s|%s\n" +#~ "फिर भी फाइल का प्रयोग करें?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "गैर-भरोसेमंद कुंजी मिली है :\n" +#~ "%s|%s|%s\n" +#~ "कुंजी पर भरोसा करें?" + +#~ msgid "%s remove failed" +#~ msgstr "%s स्थानांतरण असफल रहा" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "कूटशब्द बदलो" + +#~ msgid "rpm output:" +#~ msgstr "rpm आउटपुट :" + +#~ msgid "%s install failed" +#~ msgstr "%s संस्थापन असफल " + +#~ msgid "%s installed ok" +#~ msgstr "%s संस्थापन ठीक" + +#~ msgid "%s remove ok" +#~ msgstr "%s स्थानांतरण ठीक" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "यह निर्भरता %s प्रदान करता है लेकिन यह संस्थापित वस्तु केस्थापत्य को बदल देगा" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "यह निर्भरता %s प्रदान करता है लेकिन यह संस्थापित वस्तु केस्थापत्य को बदल देगा" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "संबंधित रिजॉल्वेबल को संस्थापित या मिटाएं नहीं" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "%s संस्थापित होने के तैयार है इसको अनदेखा करें" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "%s को %s में हटाए जाने को अनदेखा करें" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%s के इस टकराव की अनदेखी कर दें" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "सिर्फ यहां पर इस आवश्यकता की अनदेखी कर दें" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "%s को संस्थापित करें यद्यपि यह स्थापत्य को बदल देगा" + +#~ msgid "Install missing resolvables" +#~ msgstr "छूटे रिजॉल्वेबल्स को संस्थापित करें" + +#~ msgid "Keep resolvables" +#~ msgstr "रिजॉल्वेबल्स रखें" + +#~ msgid "Unlock these resolvables" +#~ msgstr "इन रिजॉल्वेबल्स को अनलॉक करें" + +#~ msgid "delete %s" +#~ msgstr "%s मिटाएं" + +#~ msgid "install %s" +#~ msgstr "%s को संस्थापित करें" + +#~ msgid "unlock %s" +#~ msgstr "%s को अनलॉक करें" + +#~ msgid "unlock all resolvables" +#~ msgstr "समस्त रिजॉल्वेबल्स को अनलॉक करें" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "फाइल %1 को नहीं खोल सकता है।" + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "सेक्टर %u पढ़ने में त्रुटि।" + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "इस URL के लिए पथ मानक पार्जिंग समर्थित नहीं है" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "पथ मानक पार्जिंग इस URL के लिए समर्थित नहीं है" + +#~ msgid "Software management is already running." +#~ msgstr "सॉफ्टवेयर प्रबंधन पहले से ही रन कर रहा है।" + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s से %s को प्रतिस्थापित किया जाता है" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s से %s को प्रतिस्थापित किया गया" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "ये रिजॉल्वेबल्स सिस्टम से मिटा दिए जाएंगे।" + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s को असंस्थापित नहीं किया जाएगा क्योंकि इसकी आवश्यकता अब भी है" + +#~ msgid "Invalid information" +#~ msgstr "अमान्य सूचना" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "अन्य रिजॉल्वेबल्स को %s की आवश्यकता है" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "%s की इनको आवश्यकता है :%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s का अन्य रिजॉल्वेबल्स से टकराव है" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s का इनसे टकराव है :\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s अन्य रिजॉल्वेबल्स को पुराना कर देता है" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "ये रिजॉल्वेबल्स सिस्टम से मिटा दिए जाएंगे।" + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s अन्य रिजॉल्वेबल्स पर निर्भर करता है" + +#~ msgid "%s depends on %s" +#~ msgstr "%s पर %s निर्भर करता है " + +#~ msgid "%s depends on:%s" +#~ msgstr "%s इन पर निर्भर करता है :%s" + +#~ msgid "Child of" +#~ msgstr "की संतति" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "कोई स्रोत उपलब्ध नहीं है जो इस आवश्यकता को समर्थन दे।" + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "इस रिजॉल्यूशन के ऊपर/नीचे वर्णित शेष समस्याएं सभी निर्भरताओं कासमाधान नहीं करेंगी" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%s का संस्थापन नहीं कर सकता क्योंकि इसका %s के साथ टकराव है" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "" +#~ "%s संस्थापित नहीं किया गया है और अनइंस्टाल योग्य के रूप में चिह्नित कर दिया गया है" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s के पास ऐसी आवश्यकताएं हैं जो संतुष्ट नहीं हुई हैं" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s की छूटी हुई निर्भरताएं हैं" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s को छूटी हुई निर्भरताओं के कारण संस्थापित नहीं किया जा सका" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s की निर्भरताएं %s पूरी करता है लेकिन इसे असंस्थापित कर दिया जाएगा" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s की निर्भरताएं %s पूरी करता है लेकिन इसे आपके सिस्टम पर रखा जाएगा" + +#~ msgid "No need to install %s" +#~ msgstr "%s को संस्थापित करने की आवश्यकता नहीं है" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "%s की निर्भरताओं को पूरा करने के लिए %s को संस्थापित नहीं कर सकता" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "%s की निर्भरताओं को पूरा करने के लिए %s को संस्थापित नहीं कर सकता" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s को असंस्थापित नहीं किया जाएगा क्योंकि इसकी आवश्यकता अब भी है" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "" +#~ "%s पुराना कर देता है %s को। लेकिन %s को मिटाया नहीं जा सकता क्योंकि यह लॉक है।" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "%s को संस्थापित नहीं कर सकता क्योंकि यह टकराव पैदा करता है" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s असंस्थापनीय है क्योंकि इसका %s के साथ टकराव है" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "%s को अपग्रेड करते समय %s हेतु %s की आवश्यकता के लिए" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s में आवश्यकता %s छूटी हुई है" + +#~ msgid ", Action: " +#~ msgstr ", कार्रवाई :" + +#~ msgid ", Trigger: " +#~ msgstr ", ट्रिगर :" + +#~ msgid "package" +#~ msgstr "पैकेज" + +#~ msgid "selection" +#~ msgstr "चयन" + +#~ msgid "pattern" +#~ msgstr "पैटर्न" + +#~ msgid "product" +#~ msgstr "उत्पाद" + +#~ msgid "patch" +#~ msgstr "पैच" + +#~ msgid "script" +#~ msgstr "स्क्रिप्ट" + +#~ msgid "message" +#~ msgstr "संदेश" + +#~ msgid "atom" +#~ msgstr "परमाणु" + +#~ msgid "system" +#~ msgstr "सिस्टम" + +#~ msgid "Resolvable" +#~ msgstr "रिजॉल्वेबल" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "इस रिजॉल्यूशन प्रयास को अमान्य के रूप में चिन्हित करना" + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "रिजॉल्वेबल %s को अनइंस्टॉलेबल के रूप में चिन्हित करना" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s को संस्थापित किया जाना निर्धारित है, लेकिन निर्भरता समस्याओं के कारण यह संभव नहीं " +#~ "है।" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "%s को संस्थापित नहीं किया जा सकता क्योंकि इसे पहले ही असंस्थापित करने की जरूरत के रूप " +#~ "में चिन्हित किया गया है" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "%s को संस्थापित नहीं कर सकता क्योंकि यह इस सिस्टम पर लागू नहीं होता" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "%s को संस्थापित नहीं कर सकता, क्योंकि %s को पहले ही संस्थापित करने की जरूरत के रूप में " +#~ "चिन्हित किया गया है" + +#~ msgid "This would invalidate %s." +#~ msgstr "यह %s को अमान्य कर देगा।" + +#~ msgid "Establishing %s" +#~ msgstr "%s को स्थापित कर रहा है" + +#~ msgid "Installing %s" +#~ msgstr "%s को संस्थापित कर रहा है" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "%s को छोड़ दें : पहले ही संस्थापित हो गया है" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "%s का कोई वैकल्पिक संस्थापित प्रदाता नहीं है" + +#~ msgid "for %s" +#~ msgstr "%s के लिए" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "%s को हटाने से बचाने के लिए %s को अपग्रेड करना संभव नहीं।" + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s ही %s प्रदान करता है, लेकिन इसे असंस्थापित करना निर्धारित है।" + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "" +#~ "%s ही %s प्रदान करता है, लेकिन इस %s का एक अन्य संस्करण पहले ही संस्थापित है। " + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s ही %s प्रदान करता है, लेकिन यह असंस्थापनयोग्य है। अधिक जानकारी के लिए इसे स्वयं " +#~ "ही संस्थापित करने की कोशिश करें।" + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s ही %s प्रदान करता है, लेकिन यह लॉक है।" + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s ही %s प्रदान करता है, लेकिन इसे रखा जाना निर्धारित है।" + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s ही %s प्रदान करता है, लेकिन इसके पास कोई और स्थापत्य है।" + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "%s के लिए %s आवाश्यकताएं संतुष्ट नहीं कर सकता" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "संस्थापित हो चुके किसी अन्य रिजॉल्वेबल को %s की आवश्यकता है, अतः यह अनलिंक नहीं किया " +#~ "जा सकता।" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "संस्थापित हो चुके किसी अन्य रिजॉल्वेबल को %s की आवश्यकता है, अतः यह अनलिंक नहीं किया " +#~ "जा सकता।" + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "%s (%s) पर टकराव के लिए संस्थापित होने वाले %s को हटाए जाने की आवश्यकता है" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "%s पर टकराव होने के कारण %s को असंस्थापनीय के रूप में चिन्हित किया जा रहा है" + +#~ msgid "from %s" +#~ msgstr "%s से" + +#~ msgid " Error!" +#~ msgstr "त्रुटि!" + +#~ msgid " Important!" +#~ msgstr "महत्वपूर्ण!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s निर्भर है %s पर" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s को %s की आवश्यकता है" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s को %s की आवश्यकता है" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s से %s को प्रतिस्थापित किया जाता है" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s को %s की आवश्यकता है" + +#~ msgid "%s part of %s" +#~ msgstr "%s का %s भाग" diff --git a/po/hr.po b/po/hr.po new file mode 100644 index 0000000..1e7c726 --- /dev/null +++ b/po/hr.po @@ -0,0 +1,5440 @@ +# translation of zypp.hr.po to Croatian +# Croatian message file for YaST2 (@memory@) +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2001 SuSE GmbH. +# +# Vlatko Kosturjak , 2001. +# Krešimir Jozić , 2008, 2009, 2011. +msgid "" +msgstr "" +"Project-Id-Version: zypp.hr\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2011-04-03 12:05+0200\n" +"Last-Translator: Krešimir Jozić \n" +"Language-Team: Croatian \n" +"Language: hr\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%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Lokalize 1.0\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Nema koda" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andora" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Ujedinjeni arapski emirati" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua i Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanija" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenija" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Norveški Antili" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antartika" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Američka Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austrija" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australija" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbedžan" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosna i Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +# BD +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladeš" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgija" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bugarska" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivija" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazil" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahami" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Butan" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet Otok" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Bocvana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Bjelorusija" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Cocos (Keeling) Otočje" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Centralna Afrička Republika" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Švicarska" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Otočje Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Čile" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbija" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kostarika" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Capo Verde" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Uskršnje otočje" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cipar" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Republika Češka" + +# DE +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Njemačka" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danska" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikanska republika" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alžir" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonija" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipat" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritreja" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Španjolska" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopija" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finska" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falkland Otočje (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Otočje Faroe" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francuska" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Ujedinjeno Kraljevstvo" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Francuska Gvineja" + +# DE +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grenland" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambija" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Gvineja" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatorijalna Gvineja" + +# GR +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grčka" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Gvatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GN +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Gvineja-Bisau" + +# GH +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Gvajana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Hrvatska" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +# HU +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Madžarska" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonezija" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irska" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indija" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Teritorij Britanskog Indijskog Oceana" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italija" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamajka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenija" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgistan" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodža" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comoros" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Sjeverna Koreja" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Južna Koreja" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuvajt" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kajmansko otočje" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazahstan" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Lihtenštajn" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Šri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberija" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litva" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvija" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libija" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Crna Gora" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Sveti Martin" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonija" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mianmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolija" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Marinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritanija" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauricijus" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Mali" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malezija" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +# GM +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibija" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nova Kaledonija" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +# CK +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Otočje Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigerija" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragva" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nizozemska" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norveška" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Novi Zeland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Francuska Polinezija" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipini" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poljska" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Portoriko" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestinski teritorij" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paragvaj" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumunjska" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Srbija" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudijska Arabija" + +# CK +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomonski otoci" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Sejšeli" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Švedska" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenija" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovačka" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sijera Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalija" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Sirija" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Čad" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +# CG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tajland" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunis" + +# CG +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turska" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tajvan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzanija" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrajina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Sjedinjene Američke Države" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Urugvaj" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venecuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Faroe Otočje" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vijetnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Južna Afrika" + +# GM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambija" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabve" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Pruža" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Zahtijeva" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Sukobi" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Zastarjelo" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Preporuča" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Predlaže" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Poboljšava" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Dopunjava" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +# AZ +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikkans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanski" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arapski" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armenijski" + +# AZ +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +# AZ +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskijski" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bjeloruski" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +# BJ +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +# BJ +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +# BJ +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosanski" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonski" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bugarski" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +# TD +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalanski" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kineski" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptski" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korzikanski" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Češki" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danski" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nizozemski" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engleski" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonski" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipinski" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finski" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francuski" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germanski (ostali)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Njemački" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irski" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galicijski" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +# GA +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +# GA +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +# HT +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haićanski" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Havajski" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebrejski" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +# HT +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Mađarski" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandski" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonežanski" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Talijanski" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanski" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japanski" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +# GM +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +# MW +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korejski" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdski" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +# GM +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latinski" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvijski" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litvanski" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luksemburški" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonski" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +# MW +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +# ML +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maorski" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Razni jezici" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Malteški" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavijski" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolski" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Više jezika" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "" + +# ML +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalski" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norveški" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubijski jezici" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +# LY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomanski jezici" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Perzijski" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenički" + +# ML +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Poljski" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugalski" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumunjski" + +# BI +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ruski" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrt" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Srpski" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilijski" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Hrvatski" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitski (ostali)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +# GH +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovački" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenski" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoanski" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalski" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Španjolski" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinijski" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sudanski" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerski" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Suahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Švedski" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Sirijski" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamilski" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tajlandski" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingonski" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +# CK +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turski" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrajinski" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +# VN +# fuzzy +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vjetnamski" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Velški" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jidiš" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "(ne istječe)" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(ne istječe)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(ISTEKLO)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(istječe unutar 24 sata)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, fuzzy, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(istječe unutar 24 sata)" +msgstr[1] "(istječe unutar 24 sata)" +msgstr[2] "(istječe unutar 24 sata)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "nepoznato" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nije podržano" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "neispravno" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Neispravan regularni izraz '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "Ne mogu napraviti datoteku." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Ne mogu napraviti %s: %m\n" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Ne mogu obrisati '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Alias repozitorija ne može započeti s točkom." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Nastaviti?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "izvršavanje nije uspjelo" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +#, fuzzy +msgid "unsupported request" +msgstr "nije podržano" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "izvršeno" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr "izvršavanje nije uspjelo" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL shema je obavezna komponenta" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Neispravna Url shema '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relativna putanja nije dozvoljena ako postoji autoritet" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Ne mogu obrisati '%s'" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Neispravan URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Medij ne podržava operaciju" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Dozvola za pristup '%s' je odbijena." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Da" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ne" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Upozorenje:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Greška" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "gotovo" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "greška" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Upozorenje:" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Dohvaćam:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "pokrećem" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Datoteka nije pronađena: {0}" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "pomoć nije raspoloživa za ovaj izbor" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "da" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ne" + +#~ msgid "problem with installed package %s" +#~ msgstr "problem s instaliranim paketom %s" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Disk ne postoji." + +#~ msgid "do not install %s" +#~ msgstr "nemoj instalirati %s" + +#~ msgid "keep %s" +#~ msgstr "zadrži %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "deinstalacija %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "deinstalacija %s" + +#, fuzzy +#~ msgid "Hal Exception" +#~ msgstr "Šifriranje" + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "veza nije uspostavljena" + +#, fuzzy +#~ msgid "HalDrive not initialized" +#~ msgstr "Inicijalizacija mete nije uspjela:" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "Ne mogu napraviti datoteku rezervne kopije %1." + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Ne mogu skinuti %s sa %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Srbija i Crna Gora" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "Nesipravna lozinka" + +#, fuzzy +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Direktorij %1 je već na listi." + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Instaliram upravljački program..." + +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "Instaliram upravljački program..." + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "Instaliram upravljački program..." + +#, fuzzy +#~ msgid "install %s" +#~ msgstr "Instaliram na:" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "Instaliram upravljački program..." diff --git a/po/hu.po b/po/hu.po new file mode 100644 index 0000000..9745e34 --- /dev/null +++ b/po/hu.po @@ -0,0 +1,6372 @@ +# translation of zypp.hu.po to Hungarian +# translation of zypp.new.po to +# translation of zypp.po to +# translation of zypp.hu.po to +# Hungarian message File YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2000, 2001 SuSE GmbH. +# +# Marcel Hilzinger , 2001. +# Sári Gábor , 2000. +# Steve Varadi , 2000. +# Zoltán Levárdy , 1999. +# Kalman Kemenczy , 2006, 2007, 2008, 2009, 2010. +# Ervin Novak , 2008, 2011. +# Kalman Kemenczy , 2011, 2012, 2013. +msgid "" +msgstr "" +"Project-Id-Version: zypp.hu\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2019-03-23 20:19+0000\n" +"Last-Translator: Robert Taisz \n" +"Language-Team: Hungarian \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: Weblate 3.3\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Ismeretlen ország: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Nincs kód" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Egyesült Arab Emirátusok" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganisztán" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua és Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albánia" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Örményország" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Holland Antillák" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktisz" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentína" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikai Szamoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Ausztria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Ausztrália" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Aland-szigetek" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbajdzsán" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosznia-Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Banglades" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgium" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgária" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrein" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Szultanátus" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolívia" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazília" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahama-szigetek" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhután" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet-sziget" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Fehéroroszország" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kókusz-szigetek (Keeling)" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongó" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Közép-Afrikai Köztársaság" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Svájc" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Elefántcsontpart" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cook-szigetek" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kína" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Zöld-foki Köztársaság" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Karácsony-sziget" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Ciprus" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Csehország" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Németország" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Dzsibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dánia" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikai Köztársaság" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algéria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Észtország" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egyiptom" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Nyugat-Szahara" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanyolország" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiópia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finnország" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidzsi" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falkland-szigetek (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikronéziai Szövetségi Államok" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Feröer-szigetek" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Franciaország" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Nagyvárosi Franciaország" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Egyesült Királyság" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Grúzia" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Francia Guiana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghána" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltár" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grönland" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Egyenlítői Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Görögország" + +# GS +# fuzzy +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Dél-Georgia és a Dél-Sandwich-sziget" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Bissau-Guinea" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard-sziget és McDonald-szigetek" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Horvátország" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Magyarország" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonézia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Írország" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Man sziget" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Brit indiai-óceáni terület" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irán" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Izland" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Olaszország" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordánia" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japán" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgizisztán" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodzsa" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comore-szigetek" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts és Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Észak-Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Dél-Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuvait" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kajmán-szigetek" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazahsztán" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Lao Népi Demokratikus Népköztársaság" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Santa Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Srí Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Libéria" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litvánia" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Lettország" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Líbia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokkó" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +# CG +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegró" + +# SM +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint-Martin" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaszkár" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshall-szigetek" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedónia" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mianmar" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongólia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makaó" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Északi Mariana-szigetek" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritánia" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Málta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldív-szigetek" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexikó" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malajzia" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namíbia" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Új-Kaledónia" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk-sziget" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigéria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Hollandia" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norvégia" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepál" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Új-Zéland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omán" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Francia Polinézia" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Pápua Új-Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Fülöp-szigetek" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakisztán" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Lengyelország" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre és Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palesztin terület" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugália" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Románia" + +# src/trans.h:311 +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Szerbia" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Oroszország" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Szaúd-Arábia" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salamon-szigetek" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelle-szigetek" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Szudán" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Svédország" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Szingapúr" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Szent Ilona" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Szlovénia" + +# SJ +# fuzzy +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard és Jan Mayen-szigetek" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Szlovákia" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Szenegál" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Szomália" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome és Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Salvador" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Szíria" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Szváziföld" + +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- és Caicos-szigetek" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Csád" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Déli francia területek" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thaiföld" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tádzsikisztán" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Türkmenisztán" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunézia" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Kelet-Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Törökország" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad és Tobago" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tajvan" + +# TZ +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzánia" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrajna" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Amerikai Egyesült Államok - kisebb külső szigetek" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Amerikai Egyesült Államok" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Üzbegisztán" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikán (Szentszék)" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent és Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Brit Virgin-szigetek" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Virgin-szigetek (USA)" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis és Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Szamoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Dél-Afrika" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Szolgáltatásai:" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Előfeltételei:" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "A következőket igényli:" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Ütközik ezzel:" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Elavult" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "A következőket ajánlja:" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "A következőket javasolja:" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "A következőket javítja:" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "A következőket egészíti ki:" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Kísérlet nem létező kulcs (%s) importálására a(z) %s kulcstárban" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Nem sikerült importálni a kulcsot." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "A kulcs törlése sikertelen." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "A(z) %s aláírás-fájl nem található" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Ismeretlen nyelv: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "abház" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "akínai" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "acsoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "cserkesz" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "afro-ázsiai (egyéb)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "afrihili" + +# src/trans.h:281 src/trans.h:318 +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "akkád" + +# src/trans.h:282 +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "albán" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "algonkin nylevek" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "dél-altáji" + +# src/trans.h:283 +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "amhara" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "óangol (kb. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "apacs nyelvek" + +# src/trans.h:283 +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "arab" + +# src/trans.h:283 +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "arámi" + +# src/trans.h:294 +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "aragóniai" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "örmény" + +# src/trans.h:227 +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "araukán" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "mesterséges (egyéb)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "asszámi" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "asztúriai" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "athapaszka nyelvek" + +# modules/inst_sw_single.ycp:117 +# clients/inst_sw_single.ycp:1072 +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "ausztrál nyelvek" + +# src/trans.h:283 +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "avar" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "avesztán" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "avádi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "aymara" + +# src/trans.h:311 +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "azeri" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "banda" + +# modules/inst_sw_single.ycp:117 +# clients/inst_sw_single.ycp:1072 +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "bamileke nyelvek" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "baskír" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "balucsi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "bambara" + +# src/trans.h:220 +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "balinéz" + +# src/trans.h:284 +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "baszk" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "balti (egyéb)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "beja" + +# src/trans.h:286 +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "belorusz" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "bengáli" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "berber (egyéb)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "bhodzspuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "biszlama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "szikszika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "bantu (egyéb)" + +# src/trans.h:309 +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "bosnyák" + +# src/trans.h:285 +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "bradzs" + +# src/trans.h:285 +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "breton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "batak (Indonézia)" + +# src/trans.h:285 +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "burját" + +# src/trans.h:220 +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "buginéz" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "bolgár" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "burmai" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "közép-amerikai indián (egyéb)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "karib" + +# src/trans.h:287 +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "katalán" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "kaukázusi (egyéb)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "kelta (egyéb)" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "csamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "csibcsa" + +# src/trans.h:290 +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "csecsen" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "csagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "kínai" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "csúki" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "csinúk zsargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "csippewi" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "cseroki" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "egyházi szláv" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "csuvas" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "csejenn" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "hámi nyelvek" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "kopt" + +# src/trans.h:363 +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "cornwalli" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "korzikai" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "angol alapú kreol és pidgin (egyéb)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "francia alapú kreol és pidgin (egyéb)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "portugál alapú kreol és pidgin (egyéb)" + +# modules/inst_custom_part.ycp:498 +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "krí" + +# /usr/lib/YaST2/clients/lan_dns.ycp:87 +# clients/lan_dns.ycp:271 +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "krími tatár" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "kreol és pidgin (egyéb)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "kasub" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "kusiti (egyéb)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Cseh" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dán" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "dargva" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "dajak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "delavár" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "slave (athapaszkai)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "dravidi (Other)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "alsó-szorbiai" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "holland, középkori (kb. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "holland" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "djula" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "dzongha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "egyiptomi (ókori)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "ekadzsuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "elamit" + +# src/trans.h:293 +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "angol" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "angol, középkori (1100-1500)" + +# src/trans.h:298 +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "eszperantó" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "észt" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "ewe" + +# modules/inst_custom_part.ycp:493 +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "evondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "fang" + +# src/trans.h:294 +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "färöi" + +# modules/dialup/dialup.ycp:390 modules/dialup/dialup.ycp:400 +# modules/dialup/dialup.ycp:410 +# clients/lan_ISDN.ycp:908 +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "fidzsi" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Fülöp-szigeteki" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "finn" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "finn-ugor (egyéb)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "francia" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "francia, középkori (kb. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "ófrancia (842-kb. 1400)" + +# src/trans.h:227 +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "fríz" + +# /usr/lib/YaST2/clients/lan_inetd_custom.ycp:762 +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "fulah" + +# src/trans.h:227 +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "friuli" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "ga" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "germán (egyéb)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "grúz" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "német" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "geez" + +# src/trans.h:270 +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "gilberti" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "gaelic" + +# src/trans.h:303 +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "ír" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "galíciai" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "német, késő középkori (kb. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "német, késő ókori (kb. 750-1050)" + +# modules/sound/sound.ycp:204 modules/sound/sound.ycp:459 +# modules/sound/sound.ycp:473 modules/sound/sound.ycp:486 +# modules/sound/sound.ycp:536 modules/sound/sound.ycp:621 +# modules/sound/sound.ycp:683 modules/sound/sound.ycp:708 +# modules/sound/sound.ycp:719 modules/sound/sound.ycp:754 +# modules/sound/sound.ycp:801 modules/sound/sound.ycp:848 +# modules/sound/sound.ycp:874 modules/sound/sound.ycp:918 +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "gót" + +# clients/inst_sw_single.ycp:1298 +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "görög, ókori (1453-ig)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "görög, modern (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "gudzsarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "haida" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "haiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "hausza" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "hawaii" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "héber" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "himacsáli" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "hindi" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "hettita" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "hmong" + +# HT +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "hiri motu" + +# src/trans.h:311 +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "felső szorb" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "magyar" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "hupa" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "izlandi" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "szecsuani yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "idzso" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "inuktitut" + +# src/prefs.c:380 +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "interlingva" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "interlingva (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "indiai (egyéb)" + +# src/trans.h:302 +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "indonéz" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "indoeurópai (egyéb)" + +# src/trans.h:293 +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "ingus" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "inupiak" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "iráni (egyéb)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "irokéz nyelvek" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "olasz" + +# src/trans.h:222 +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "jávai" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "lodzsbai" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japán" + +# clients/inst_sw_single.ycp:1320 clients/inst_sw_single.ycp:1971 +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "judeo-perzsa" + +# src/trans.h:283 +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "judeo-arab" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "kara-kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "kabil" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "kacsin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "kasmíri" + +# src/trans.h:316 +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "kavi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "kazah" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "kabardi" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "hászi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "khoisan (egyéb)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "khotáni" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "kirgiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbunduk" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "komi" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "kongó" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "koreai" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "kozrai" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "karacsai-balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "kru" + +# src/trans.h:316 +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "kumik" + +# src/trans.h:316 +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "kurd" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "kutenai" + +# src/trans.h:47 src/trans.h:50 +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "lamba" + +# src/prefs.c:397 src/trans.h:125 +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "lao" + +# src/trans.h:47 src/trans.h:50 +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "latin" + +# src/trans.h:289 +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "lett" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "lezgiai" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "limburgi" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litván" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "luxemburgi" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "luba-lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "luba-katanga" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "luo (Kenya és Tanzánia)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "lushai" + +# src/trans.h:305 +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "macedón" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "maduri" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "magahi" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "marshall" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "maithili" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "makaszár" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "malajálam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "ausztronéziai (egyéb)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "marathi" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "maszáj" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "maláj" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "moksa" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "ír, középkori (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "vegyes nyelvek" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "mon-khmer (egyéb)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "malagázi" + +# src/trans.h:377 +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "máltai" + +# modules/dialup/dialup.ycp:391 modules/dialup/dialup.ycp:401 +# modules/dialup/dialup.ycp:411 +# clients/lan_ISDN.ycp:909 +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "mandzsu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "manobo nyelvek" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "mohauk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "moldáv" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "mossi" + +# modules/inst_sw_single.ycp:117 +# clients/inst_sw_single.ycp:1072 +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "több nyelv" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "munda nyelvek" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "krík" + +# src/trans.h:294 +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "mirandai" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "marvari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "maja nyelvek" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "erzia" + +# modules/dialup/dialup.ycp:391 modules/dialup/dialup.ycp:401 +# modules/dialup/dialup.ycp:411 +# clients/lan_ISDN.ycp:909 +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "észak-amerikai indián" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "nápolyi" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "navahó" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "dél-ndebelei" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "észak-ndebelei" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "alsó-német" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "nepáli" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "nepál-bhászai" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "niger-kordofáni (egyéb)" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "niuei" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "norvég nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "norvég Bokmal" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "norvég, régi" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "norvég" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "északi sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "núbiai nyelvek" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "klasszikus nevari" + +# src/trans.h:290 +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "csicseva" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "njamvézi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "okcitán (1500 utáni)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "odzsibva" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "orija" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "oszét" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "török, ottomán (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "otomi nyelvek" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "pápua (egyéb)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "pangazini" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "pandzsábi" + +# clients/lan_modem.ycp:602 +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "palaui" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "perzsa, régi (kb. i.e. 600-400)" + +# clients/inst_sw_single.ycp:1320 clients/inst_sw_single.ycp:1971 +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "perzsa" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Fülöp-szigeteki (egyéb)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "föníciai" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "páli" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "lengyel" + +# src/trans.h:302 +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "pompeji" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "portugál" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "prakrit nyelvek" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "provanszi, régi (1500-ig)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "kecsua" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "rádzsasztáni" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "rapanui" + +# menuentries/menuentry_lan_route.ycp:14 +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "rarotongai" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "romansz (egyéb)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "rétoromán" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "romany-i" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "román" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "orosz" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "szango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "jakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "dél-amerikai indián (egyéb)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "salishi nyelvek" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "szamaritánus arámi" + +# src/trans.h:193 +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "szanszkrit" + +# src/trans.h:193 +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "szaszak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "szantáli" + +# src/trans.h:311 +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "szerb" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "szicíliai" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "skót" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "horvát" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "sémi (egyéb)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "ír, régi (900-ig)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "jelnyelvek" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "sán" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "szidamo" + +# src/trans.h:270 +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "szinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "sziú nyelvek" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "sino-tibeti (egyéb)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "szláv (egyéb)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "szlovák" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "szlovén" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "déli számi" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "északi számi" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "számi nyelvek (egyéb)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "lule számi" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "inári számi" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "szamoai" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "szkolt számi" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "szindi" + +# modules/inst_sw_select.ycp:125 +# /usr/lib/YaST2/clients/inst_sw_select.ycp:194 +# clients/online_update.ycp:39 +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "szogdiai" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "szomáli" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "szonghai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "sotho, déli" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "spanyol" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "szardíniai" + +# clients/lan_nfs_fstab.ycp:272 +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "szerer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "nílus-szaharai (egyéb)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "szvázi" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "szukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "szundanéz" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "szuszu" + +# src/trans.h:311 +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "sumer" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "szuahéli" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "svéd" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "szír" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "tahiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "tai (egyéb)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "tatár" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "tádzsik" + +# src/trans.h:116 +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "tibeti" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "tigre" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "tigrinja" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "tamasek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "tonga (Nyasa)" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "tongai (Tonga-szigetek)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "tok pisin" + +# src/trans.h:227 +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "cimsiai" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "türkmén" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "tupi nyelvek" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "török" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "altáji (egyéb)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "tuvíniai" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "udmurti" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "ugariti" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "ujgur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "ukrán" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "umbundu" + +# src/prefs.c:380 +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "meghatározatlan" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "üzbég" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "venda" + +# src/trans.h:270 +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "vietnami" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "vóti" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "vakasai nyelvek" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "valamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "varai" + +# modules/inst_config_x11.ycp:127 +# /usr/lib/YaST2/clients/inst_config_x11.ycp:750 +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "vaso" + +# modules/inst_config_x11.ycp:127 +# /usr/lib/YaST2/clients/inst_config_x11.ycp:750 +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "walesi" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "szorbiai nyelvek" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "vallon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "kalmik" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "xhosa" + +# src/prefs.c:397 src/trans.h:125 +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "yapi" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "jiddis" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "joruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "jupik nyelvek" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "zapotek" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "zenaga" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "A rendszer a következő műveleteket hajtja végre:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "nem jár le" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "lejárt: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "lejár: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(nem jár le)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(LEJÁRT)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(24 órán belül lejár)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(%d napon belül lejár)" +msgstr[1] "(%d napon belül lejár)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "ismeretlen" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nem támogatott" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "1. szintű" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "2. szintű" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "3. szintű" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "További Ügyfélszerződés szükséges" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "érvénytelen" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Nincs meghatározva a támogatás szintje" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "A gyártó nem biztosít támogatást." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Probléma azonosítás, amely a kompatibilitási információ nyújtására, " +"telepítési segítségre, felhasználási támogatásra, folyamatos karbantartásra, " +"és alapszintű hibakeresésre terjed ki. Az 1. szintű támogatásnak nem célja a " +"termék hibáinak javítása." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Probléma izoláció, amely a vásárlói problémák reprodukálására, a problémák " +"beazonosítására és az 1. szintű támogatás által meg nem oldott problémák " +"javítására terjed ki." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Probléma megoldás, amely a fejlesztők bevonásával a 2. szintű támogatás " +"által beazonosított összetett termékhibák megoldását szolgálja." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "További ügyfélszerződés szükséges a támogatáshoz." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Ismeretlen támogatási opció. Leírás nem található" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"A rendszerkezelőt a %d (%s) pid-del rendelkező folyamat zárolta.\n" +"Kérem, zárja be az alkalmazást, majd próbálja újra." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Ismeretlen illeszkedőmód: '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Ismeretlen illeszkedőmód: '%s', a(z) %s mintához." + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Érvénytelen reguláris kifejezés '%s': regcomp visszatérési értéke: %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Érvénytelen reguláris kifejezés '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Felhasználóhitelesítés szükséges ehhez: '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Keresse fel a SUSE Ügyfélközpontot, és ellenőrizze, hogy a regisztrációja " +"érvényes-e, illetve nem járt-e le." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Látogassa meg a Novell Ügyfélközpotot (Novell Customer Center), hogy " +"ellenőrizni tudja, hogy a regisztrációja érvényes és nem jár re." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Csatlakoztatási pont létrehozása: Nem található írható könyvtár " +"csatlakoztatási pont létrehozásához" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Először az 'lsof' csomagot kell telepíteni." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Nem hozható létre a metaadat gyorsítótár-könyvtára." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Hiba történt a következőből való olvasás során: \"%s\"" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "A(z) %s nem hozható létre" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "A megadott URL-címen nem találhatók érvényes metaadatok" +msgstr[1] "A megadott URL-címeken nem találhatók érvényes metaadatok" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Nem sikerült a tároló gyorsítótárazása (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "A(z) '%s' telepítési forrás gyorsítótárának felépítése" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" +"Írási engedélyek hiányában nem hozható létre gyorsítótár a(z) %s helyen." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Nem kezelt tárolótípus" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "A(z) '%s' telepítési forrás hozzáadása" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Érvénytelen tárolónév: '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "A '%s' fájl nem nyitható meg írásra." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Ismeretlen hiba a '%s' beolvasása közben" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" +"A következő telepítésiforrás-könyvtár nem olvasható: '%1%': A rendszer " +"megtagadta az engedélyt" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Nem sikerült a(z) '%s' könyvtár beolvasása." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" +"A következő telepítésiforrás-fájl nem olvasható: '%1%': A rendszer " +"megtagadta az engedélyt" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "A(z) '%s' telepítési forrás eltávolítása" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Nem sikerült a tároló felismerése." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "A(z) '%s' törlése sikertelen" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Nem sikerült a szolgáltatás felismerése." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Ismeretlen '%1%' szolgáltatás: az árva '%2%' szolgáltatástároló eltávolítása" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "A telepítési forrás álneve nem kezdődhet ponttal." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "A szolgáltatás álneve nem kezdődhet ponttal." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Folytatja?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "A(z) %1% telepítési forrás nem definiál további 'gpgkey=' URL-címeket." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "%1% azonosítójú gpg-kulcs keresése a telepítési forrásban (%2%)." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "%1% azonosítójú gpg-kulcs keresése a gyorsítótárban (%2%)." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "'%s' szükséges paraméter hiányzik." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Legalább az egyik szükséges a '%s' és '%s' paraméterekből." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Az aláírás-ellenőrzés sikertelen" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"A(z) %s csomag megsérülhetett az átvitel közben. Megismétli az átvitelt?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Nem sikerült a %s csomag beszerzése. Megismétli az átvitelt?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "az applydeltarpm ellenőrzés sikertelen." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "az applydeltarpm futtatása sikertelen." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "A szolgáltatási bővítmény nem támogatja attribútum módosítását." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "A(z) '%s' fájlt nem biztosítja a(z) '%s' telepítési forrás" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "A telepítés forrás nem tartalmaz url-t." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"A(z) %1% fájl\n" +" (csomag:\n" +" %2%)\n" +" ütközik a(z)\n" +" %3% csomag fájljával" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"A(z) %1% fájl\n" +" (csomag:\n" +" %2%)\n" +" ütközik a(z)\n" +" %3% telepítés fájljával" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"A(z) %1% fájl\n" +" (telepítés:\n" +" %2%)\n" +" ütközik a(z) %3%\n" +" csomag fájljával" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"A(z) %1% fájl\n" +" (telepítés:\n" +" %2%)\n" +" ütközik a(z) %3%\n" +" telepítés fájljával" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"A(z) %1% fájl\n" +" (csomag:\n" +" %2%)\n" +" ütközik a(z)\n" +" %4%\n" +" csomag\n" +" %3% fájljával" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"A(z) %1% fájl\n" +" (csomag:\n" +" %2%)\n" +" ütközik a(z)\n" +" %4%\n" +" telepítés\n" +" %3% fájljával" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"A(z) %1% fájl\n" +" (telepítés:\n" +" %2%)\n" +" ütközik a(z)\n" +" %3%\n" +" fájllal (csomag:\n" +" %4%)" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"A(z) %1% fájl\n" +" (telepítés:\n" +" %2%)\n" +" ütközik a(z)\n" +" %3%\n" +" fájllal (telepítés:\n" +" %4%)" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Nem hozható létre sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "%s csomag megtörése néhány függőség figyelmen kívül hagyásával" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "egyes függőségek általános mellőzése" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "ütköző kérelmek" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "bizonyos függőségi probléma" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "nem támogatott kérelem" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "törölt csomagok: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"nem telepíthető szolgáltatók: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "nem telepíthető szolgáltatók: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "A kért módosítás a rendszer meghibásodásához vezet!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "a hibás rendszer figyelmeztetésének figyelmen kívül hagyása" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "A kérésnek megfelelően a telepítés megszakad." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " végrehajtva" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " végrehajtás sikertelen" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s már futtatva volt mint %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " megszakítás közben a végrehajtás átugorva" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Hiba történt a frissítési értesítés küldésekor." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Új frissítési üzenet" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM sikertelen: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Nem sikerült a(z) %1% fájlból importálni a publikus kulcsot" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "A(z) %1% publikus kulcs eltávolítása sikertelen" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +# modules/dialup/dialup.ycp:231 modules/dialup/dialup.ycp:246 +# modules/dialup/dialup.ycp:259 +# menuentries/menuentry_lan_sendmail.ycp:14 +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s módosított konfigurációs fájljai:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"Az rpm a következőként mentette %s-t: %s, de nem sikerült megállapítani a " +"különbséget" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"Az rpm a következőként mentette %s-t: %s.\n" +"A különbség első 25 sora:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"Az rpm a következőként hozta létre %s-t: %s, de nem sikerült megállapítani a " +"különbséget" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"Az rpm a következőként hozta létre %s-t: %s.\n" +"A különbség első 25 sora:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "További rpm kimenet" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "%s másolata létrehozva" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Az aláírás rendben van" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Ismeretlen típusú aláírás" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Az aláírás nem felelt meg az ellenőrzésen" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Az aláírás rendben van, de a kulcs nem megbízható" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Az aláírások nyilvános kulcsa nem érhető el" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "A fájl nem létezik, vagy nem ellenőrizhető az aláírása" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "A fájl nincs aláírva" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "'%s' bizonytalan típus %u byte, ellenőrzőösszeg '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "A pty nem nyitható meg (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "A cső nem nyitható meg (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Érvénytelen LDAP URL lekérdezési karakterlánc" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Érvénytelen LDAP URL lekérdezési paraméter: '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Az URL-objektum másolása sikertelen" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Érvénytelen üres URL-objektum hivatkozás" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Az URL-komponensek elemzése sikertelen" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Előzmények:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Az Url séma nem engedélyezi a(z) %s használatát" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Érvénytelen %s-komponens: '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Érvénytelen %s-komponens" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" +"A lekérdezési karakterlánc feldolgozása ehhez az URL-hez nem támogatott" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Az URL-séma megadása szükséges" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Érvénytelen URL-séma: '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Az URL-séma nem engedélyezi a felhasználónevet" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Az URL-séma nem engedélyezi a jelszót" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Az URL-sémában a gépkomponens (host) megadása kötelező" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Az Url séma megadása nem engedélyezi a gépkomponenst (host)" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Hibás gépkomponens (host): '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Az Url séma nem engedélyezi a portot" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Érvénytelen port komponens: '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Az Url sémában az elérési útvonal megadása szükséges" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" +"Megadott hitelesítő esetén a relatív elérési útvonal megadása nem támogatott" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "A kódolt karakterlánc NUL byte-ot tartalmaz" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" +"Érvénytelen tömbszétválasztás-elválasztó (array split separator) karakter" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" +"Érvénytelen leképezésszétválasztás-elválasztó (map split separator) karakter" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Érvénytelen tömbösszefűzés-elválasztó (array join separator) karakter" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "A parancs a következő állapottal lépett ki: %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "A parancs végrehajtását a(z) %d szignál megszakította (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "A parancs végrehajtása ismeretlen hibával leállt." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "A chroot sikertelen ide: '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Sikertelen chdir a(z) '%s' könyvtárra (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" +"Sikertelen chdir a(z) '%s' könyvtárra a következő gyökéren belül: '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "'%s' végrehajtása sikertelen (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "A forkolás sikertelen (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Nem sikerült a(z) %s felcsatolása ide: %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "A(z) %s eltávolítása sikertelen" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Hibás fájlnév: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" +"Az adathordozó elérése a(z) '%s' művelet végrehajtása közben nem sikerült." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "A(z) '%s' fájl nem található a(z) '%s' adathordozón" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "A fájl írása sikertelen: '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Az adathordozó nincs csatlakoztatva" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Hibás csatolási pont" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "A letöltés (curl) inicializálása meghiúsult: '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "%s rendszerkivétel történt a(z) '%s' adathordozón." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "A(z) '%s' elérési út a(z) '%s' adathordozón nem fájl." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "A(z) '%s' elérési út a(z) '%s' adathordozón nem könyvtár." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Hibás URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Üres hosztnév a hivatkozásban" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Üres fájlrendszer a hivatkozásban" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Üres cél a hivatkozásban" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Érvénytelen URI séma: '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Az adathordozó nem támogatja ezt a műveletet" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Letöltési (curl) hiba: '%s'\n" +"Hibakód: %s\n" +"Hibaüzenet: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Hiba történt a '%s' letöltési (curl) beállításainak beállítása közben:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "A '%s' adathordozó forrása nem tartalmazza a kívánt adathordozót" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Jelenleg egy másik folyamat használja a(z) '%s' adathordozót" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Nincs kiadható adathordozó" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "A(z) '%s' adathordozó kiadása sikertelen" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Hozzáférés megtagadva: '%s'." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Időtúllépés a '%s' elérése közben." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"A letöltött adatok mérete meghaladta a várt fájlméretet: '%s' (összesen: " +"'%s')." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "A '%s' hely ideiglenesen nem elérhető." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" hiba az SSL-tanúsítvánnyal, ellenőrizze, hogy megfelelő-e a CA tanúsítványa " +"a következőhöz: '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Nem támogatott HTTP hitelesítési metódus: '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Igen" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nem" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Megjegyzés:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Figyelmeztetés:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Hiba:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "kész" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "hiba" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Figyelmeztetés: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Letöltés:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "indítás" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "nem található" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Ennél a parancssornál nem érhető el a súgó." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "ehhez a paraméterhez nem tartozik súgó" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "az összes lehetőség megjelenítése" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "igen" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nem" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "'%1%' %%posttrans parancsfájl végrehajtása" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "%posttrans parancsfájlok végrehajtása" + +#~ msgid "Package is not signed!" +#~ msgstr "A csomag nincs aláírva." + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s nem tartozik a distupgrade telepítési forráshoz" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s alacsonyabb szintű architektúrával rendelkezik" + +#~ msgid "problem with installed package %s" +#~ msgstr "probléma a telepített csomaggal: %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "semmi nem biztosítja a(z) %s csomagot" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Minden szükséges telepítési forrást engedélyezett?" + +#~ msgid "package %s does not exist" +#~ msgstr "a(z) %s csomag nem létezik" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "A(z) %s a rendszertől származik, ezért törlése nem lehetséges." + +# modules/inst_target_part.ycp:676 +#~ msgid "%s is not installable" +#~ msgstr "%s nem telepíthető" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "" +#~ "semmi sem biztosítja a(z) %s csomagot,\n" +#~ "amely szükséges a(z) %s csomag telepítéséhez" + +# modules/inst_target_part.ycp:676 +#~ msgid "cannot install both %s and %s" +#~ msgstr "nem telepíthető %s és %s is" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s ütközik a(z) %s csomaggal, amit a(z) %s csomag biztosít" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s elavulttá teszi a(z) %s csomagot, amit a(z) %s csomag biztosít" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s elavulttá teszi a(z) %s csomagot, amit a(z) %s csomag biztosít" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s ütközik a(z) %s csomaggal, amit saját maga biztosít" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s csomagnak a következőre van szüksége: %s, de ez nem teljesíthető" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "távolítsa el a zárolást a(z) %s eltávolításának engedélyezéséhez" + +# modules/inst_target_part.ycp:676 +#~ msgid "do not install %s" +#~ msgstr "Ne telepítse a(z) %s csomagot" + +#~ msgid "keep %s" +#~ msgstr "%s megtartása" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "távolítsa el a zárolást a(z) %s telepítésének engedélyezéséhez" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "ne kérdezzen rá a %s-t biztosító feloldható telepítésére" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "ne kérdezzen rá a %s-t biztosító feloldhatók eltávolítására" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "Ne telepítse a(z) %s csomag legújabb verzióját" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s megtartása az alacsonyabb rendű architektúra ellenére" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "%s telepítése az alacsonyabb architektúra ellenére" + +#~ msgid "keep obsolete %s" +#~ msgstr "az elavult %s megtartása" + +#~ msgid "install %s from excluded repository" +#~ msgstr "%s telepítése a figyelmen kívül hagyott tárolóból" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "A(z) %s csomag visszafejlesztése a(z) %s csomagra" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "A(z) %s csomag helyett a(z) %s architektúrájú csomag telepítése" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "%s telepítése (gyártó megváltoztatásával)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "%s cseréje erre: %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "%s eltávolítása" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "A zárolt fájl nem nyitható meg: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Ezt a folyamatot már elindította egy másik program." + +#~ msgid "Hal Exception" +#~ msgstr "Hal kivétel" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "A libzypp ezen verziója HAL-támogatás nélkül készült." + +#~ msgid "HalContext not connected" +#~ msgstr "A HalContext nem kapcsolódott" + +#~ msgid "HalDrive not initialized" +#~ msgstr "A HalDriver inicializálása sikertelen" + +#~ msgid "HalVolume not initialized" +#~ msgstr "A HalVolume inicializálása sikertelen" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "A dbus kapcsolat létrehozása sikertelen" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: A libhal kontextus létrehozása sikertelen" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: A dbus kapcsolat beállítása sikertelen" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "A HAL kontextus inicializálása sikertelen -- lehetséges, hogy a hald nem " +#~ "fut?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "CD-ROM meghajtó nem található" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "A mutex attribútumok inicializációja sikertelen" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Rekurzív mutex attribútum nem állítható be" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "A rekurzív mutex attribútum inicializációja sikertelen" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "A mutex zárolása sikertelen" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "A mutex zárolása nem oldható fel" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Nem sikerült a(z) %s fájlból importálni a publikus kulcsot: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "A(z) %s publikus kulcs eltávolítása sikertelen: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Nincs elérhető hurokeszköz a '%s' által tartalmazott képfájl " +#~ "felcsatolásához" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "néhány függőség figyelmen kívül hagyása" + +# modules/inst_target_part.ycp:676 +#~ msgid "do not forbid installation of %s" +#~ msgstr "A(z) %s csomag telepítése" + +# modules/inst_target_part.ycp:676 +#~ msgid "do not keep %s installed" +#~ msgstr "A(z) %s csomag eltávolítása" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "صربيا ومونتنيجرو" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "خيار list غير معروف" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "تعذر حل التبعيات" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "A(z) %s publikus kulcs elkészítése %s kulcstartóból %s fájlba sikertelen" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "Nem létező kulcsot (%s) próbált a %s kulcstartóba importálni" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "A könyvtár '/'-ra váltása a chroot-ban sikertelen (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "A letöltés (Metalink curl) inicializálása meghiúsult: '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Letöltési (metalink curl) hiba: '%s'\n" +#~ "Hibakód: %s\n" +#~ "Hibaüzenet: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Letöltés megszakítva: at %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "A letöltés a felhasználó megszakította" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Hiba történt a '%s' letöltési (metalink curl) beállításainak beállítása " +#~ "közben:" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Nem sikerült a(z) %s letöltése innen: %s" diff --git a/po/id.po b/po/id.po new file mode 100644 index 0000000..fdd1464 --- /dev/null +++ b/po/id.po @@ -0,0 +1,5993 @@ +# Indonesian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999-2001 SuSE GmbH. +# I Made Wiryana , 1999. +# Kukuh Syafaat , 2017-2018. +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2023-09-23 11:15+0000\n" +"Last-Translator: Kukuh Syafaat \n" +"Language-Team: Indonesian \n" +"Language: id\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: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Negara tidak diketahui: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Tidak ada kode" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +# AE +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Uni Emirat Arab" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua dan Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +# AL +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Belanda Antilles" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antartika" + +# AR +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Amerika" + +# AT +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +# AU +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Kepulauan Aland" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaijan" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia Herzegovina" + +# BB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +# BD +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +# BE +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgia" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +# BG +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +# BH +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +# BM +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +# BO +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazil" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahama" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Pulau Bouvet" + +# BW +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +# BY +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarusia" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +# CA +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kepulauan Cocos (Keeling)" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Republik Afrika Tengah" + +# CH +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Swiss" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Pantai Gading" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Kepulauan Cook" + +# CL +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chili" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +# CN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Cina" + +# CO +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolombia" + +# CR +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kosta Rica" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Tanjung Verde" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Pulau Christmas" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Siprus" + +# CZ +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Republik Ceko" + +# DE +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Jerman" + +# DJ +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Jibouti" + +# DK +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Denmark" + +# DM +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +# DO +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Republik Dominika" + +# DZ +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Aljazair" + +# EC +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekuador" + +# EE +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +# EG +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Mesir" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sahara Barat" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +# ES +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanyol" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Ethiopia" + +# FI +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlandia" + +# FJ +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Kepulauan Malvinas" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federasi Mikronesia" + +# FO +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Kepulauan Faroe" + +# FR +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Perancis" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Perancis Metropolitan" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Inggris" + +# GD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +# GE +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Grujia" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guiana Perancis" + +# DE +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +# GI +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +# GL +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Greenland" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +# GP +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinea Equator" + +# GR +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Yunani" + +# GS +# fuzzy +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Georgia Selatan dan Pulau Sandwich Selatan" + +# GT +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +# GU +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +# HK +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Pulau Heard dan Kepulauan McDonald" + +# HN +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +# HR +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroasia" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +# HU +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hungaria" + +# ID +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +# IE +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlandia" + +# IL +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Palestina" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Pulau Man" + +# IN +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Wilayah Samudra Hindia Britania" + +# IQ +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +# IS +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islandia" + +# IT +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +# JM +# fuzzy +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaika" + +# JO +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Yordania" + +# JP +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Jepang" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgistan" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kamboja" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komoro" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Santa Kitts dan Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Korea Utara" + +# ZA +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Korea Selatan" + +# KW +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Pulau Cayman" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakhstan" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laos" + +# LB +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Santa Lucia" + +# LI +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +# LT +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lithuania" + +# LU +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +# LV +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvia" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Liberia" + +# MA +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +# MC +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +# MD +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +# CG +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +# SM +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "San Marino" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Kepulauan Marshall" + +# MK +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +# MO +# fuzzy +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makao" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Kepulauan Mariana Utara" + +# MQ +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +# MT +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Mali" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +# MX +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksiko" + +# MY +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Caledonia Baru" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Kepulauan Norfolk" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +# NI +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragua" + +# NL +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Belanda" + +# NO +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norwegia" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +# NR +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +# NZ +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Selandia Baru" + +# OM +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +# PA +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +# PE +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinesia Perancis" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nugini" + +# PH +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipina" + +# PK +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +# PL +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polandia" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Santa Pierre dan Miquelon" + +# PN +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +# PR +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestina" + +# PT +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugis" + +# PW +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +# PY +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +# QA +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +# RO +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Rusia" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +# SA +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arab Saudi" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Kepulauan Solomon" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +# SD +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +# SE +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Swedia" + +# SG +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapura" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Santa Helena" + +# SI +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +# SJ +# fuzzy +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Kepulauan Svalbard dan Jan Mayen" + +# SK +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakia" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome dan Principe" + +# SV +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Suriah" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Kepulauan Turks dan Caicos" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chad" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Perancis Selatan" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +# TH +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +# TJ +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tajikistan" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +# TN +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor Leste" + +# TR +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turki" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad dan Tobago" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +# TW +# fuzzy +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +# UA +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Kepulauan Terluar Kecil Amerika Serikat" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Amerika Serikat" + +# UY +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +# UZ +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Tahta Suci (Negara Kota Vatikan)" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent dan Grenadines" + +# VE +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Kepulauan Virgin Inggris" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Kepulauan Virgin, A.S." + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Kepulauan Wallis dan Futuna" + +# WS +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +# YE +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yaman" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +# ZA +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Afrika Selatan" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +# ZW +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Menyediakan" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Prasyarat" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Syarat" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Konflik" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Usang" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Rekomendasi" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Saran" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Meningkatkan" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Suplemen" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Mencoba untuk mengimpor kunci %s tidak ada ke keyring %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Gagal mengimpor kunci." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Gagal menghapus kunci." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Berkas tanda tangan %s tidak ditemukan" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Bahasa tidak diketahui: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +# AZ +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhazian" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Bahasa Aceh" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asiatic (Lainnya)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrika" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadia" + +# AL +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albania" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleut" + +# LK +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Bahasa Algonquian" + +# ZA +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altai Selatan" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharic" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Inggris, Kuno (sekitar 450-1100)" + +# LK +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Bahasa Athabaskan" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arab" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaic" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragon" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armenian" + +# MR +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucanian" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Buatan (Lainnya)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamese" + +# AT +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Austria" + +# AU +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athabaskan" + +# AU +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australia" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avar" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Myanmar" + +# AZ +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaijan" + +# CA +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +# LK +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +# GM +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Bahasa Bali" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basque" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Bassa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltic" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +# BY +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Belarus" + +# BM +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +# SN +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber (Lainnya)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +# BH +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +# BJ +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (Other)" + +# BW +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnia" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Breton" + +# ID +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak" + +# BG +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugis" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgaria" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmese" + +# BJ +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +# TD +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "India Amerika Tengah (Lainnya)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalan" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucasian (Lainnya)" + +# LB +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celtic (Lainnya)" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +# CN +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Chechen" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Cina" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook Jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Church Slavic" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +# LK +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Bahasa Chamic" + +# CR +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptik" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornish" + +# CR +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsika" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creoles dan Pidgins, Berbasis Bahasa Inggris (Lainnya)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creoles dan Pidgins, Berbasis Bahasa Perancis (Lainnya)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creoles dan Pidgins, Berbasis Bahasa Portugis (Lainnya)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Crimean Tatar" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creoles dan Pidgins (Lainnya)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kashubian" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitic (Lainnya)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Cekoslowakia" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Denmark" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +# DM +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidian (Lainnya)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Lower Sorbian" + +# PW +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Belanda, Tengah (sekitar 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Belanda" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Mesir Kuno" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inggris" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Inggris, Pertengahan (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonia" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +# FR +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +# FO +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Kepulauan Faroe" + +# HT +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +# FJ +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijian" + +# PH +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipina" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finlandia" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finno-Ugrian (Lainnya)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Prancis" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Prancis, Pertengahan (sekitar 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Prancis, Kuno (842-sekitar 1400)" + +# FR +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisian" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +# FI +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulian" + +# GU +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +# LY +# fuzzy +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Jerman (Lainnya)" + +# GE +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Grujia" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Jerman" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Yunani" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertese" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandia" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galisia" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Jerman, Menengah Tinggi (sekitar 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Jerman, Kuno Tinggi (sekitar 750-1050)" + +# IN +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "India" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gothic" + +# GA +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Yunani, Kuno (hingga 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Yunani, Modern (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarat" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich’in" + +# HT +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +# HT +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawai" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Israel" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +# IN +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "India" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Haiti" + +# TO +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Tonga" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Serbia" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Hongaria" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandia" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +# LT +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Asosiasi Bahasa Bantu Internasional)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indic (Lainnya)" + +# ID +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesia" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-Eropa (Lainnya)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +# IN +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iran (Lainnya)" + +# LK +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Bahasa Iroquoia" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italia" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Bahasa Jawa" + +# LB +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Jepang" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Yudeo-Persia" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Yudeo-Arab" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +# BH +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +# GM +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +# CA +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kanada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +# MW +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakhstan" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (Lainnya)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanese" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korea" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +# PA +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdish" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +# LB +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +# UG +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +# GM +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +# LB +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +# LV +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latin" + +# LV +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvia" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghian" + +# LU +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgan" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lithuania" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +# LU +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxembourg" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +# SD +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya dan Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Masedonia" + +# MV +# fuzzy +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madura" + +# MW +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Kepulauan Marshall" + +# ML +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +# MY +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesian (Lainnya)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +# MT +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandia, Pertengahan (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi’kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +# LK +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Ragam Bahasa" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (Lainnya)" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagasy" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltese" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +# KY +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Bahasa Manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +# MD +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavian" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolian" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +# LK +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Multi Bahasa" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Bahasa Munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +# KY +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Bahasa Mayan" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +# MP +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Indian Amerika Utara" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitan" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, Selatan" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, Utara" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Jerman Bawah" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanian (Lainnya)" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norwegian Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norwegian Bokmal" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norse, Kuno" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norwegia" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho Utara" + +# LK +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Bahasa Nubian" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari Klasik" + +# CL +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (setelah 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetia" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turkish, Ottoman (1500-1928)" + +# LK +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Bahasa Otomian" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papua (Lainnya)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +# PW +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +# PY +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +# PA +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +# PW +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persia, Kuno (sekitar 600-400 SM.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persia" + +# PH +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "FIlipina (Lainnya)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Phoenician" + +# ML +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polandia" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugis" + +# LK +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Bahasa Prakrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provencal, Kuno (hingga 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +# TJ +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +# JP +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romance (Other)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Raeto-Romance" + +# RO +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romany" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumania" + +# RE +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rusia" + +# CA +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +# WS +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Indian Amerika Selatan (Lainnya)" + +# LK +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Bahasa Salishan" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritan Aram" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskerta" + +# WS +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbia" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilian" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroasia" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitic (Lainnya)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandia, Kuno (hingga 900)" + +# LK +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Bahasa Sign" + +# SD +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +# WS +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +# LK +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Bahasa Siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetan (Lainnya)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavic (Lainnya)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakia" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenia" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Selatan Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Utara Sami" + +# LK +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Bahasa Sami (Lainnya)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +# WS +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +# SI +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +# SD +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalia" + +# TO +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, Selatan" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spanyol" + +# MR +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinian" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Saharan (Lainnya)" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +# SD +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Bahasa Sunda" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerian" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Swedia" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syriac" + +# TW +# fuzzy +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (Lainnya)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +# QA +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +# BE +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +# TJ +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +# TW +# fuzzy +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetan" + +# NE +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Kepulauan Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +# BW +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +# TR +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmenistan" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +# LK +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Bahasa Tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turkish" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaic (Lainnya)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +# TN +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvinian" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritic" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighur" + +# UA +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukraina" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Tidak dapat ditentukan" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +# UZ +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbekistan" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +# VN +# fuzzy +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +# VN +# fuzzy +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnam" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +# KY +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Bahasa Wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +# PY +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Welsh" + +# LK +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Bahasa Sorbian" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +# LK +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Bahasa Yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +# GD +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +# TV +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Tindakan berikut akan dilakukan:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "tidak kedaluwarsa" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "kedaluwarsa: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "kedaluwarsa: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(tidak kedaluwarsa)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(KEDALUWARSA)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(Kedaluwarsa dalam waktu 24 jam)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(Kedaluwarsa dalam %d hari)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "tidak dikenal" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "tidak didukung" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Level 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Level 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Level 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Kontrak Pelanggan Tambahan Diperlukan" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "tidak valid" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Tingkat dukungan tidak ditentukan" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Vendor tidak menyediakan dukungan." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Penentuan masalah, yang berarti dukungan teknis yang dirancang untuk " +"memberikan informasi kompatibilitas, bantuan instalasi, dukungan penggunaan, " +"pemeliharaan berlanjut dan pemecahan masalah dasar. Dukungan Level 1 tidak " +"dimaksudkan untuk memperbaiki kesalahan produk cacat." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Isolasi masalah, yang berarti dukungan teknis yang dirancang untuk " +"menduplikasi masalah pelanggan, mengisolasi pada area masalah dan memberikan " +"solusi untuk masalah tidak diselesaikan dengan Level 1 Support." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Penyelesaian masalah, yang berarti dukungan teknis dirancang untuk " +"menyelesaikan masalah yang kompleks dengan cara melibatkan teknik pada " +"penyelesaian produk yang cacat sebagaimana telah diidentifikasi oleh Support " +"Level 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Kontrak pelanggan tambahan diperlukan untuk mendapatkan dukungan." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Opsi dukungan tidak diketahui. Deskripsi tidak ditemukan" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Manajemen sistem dikunci oleh aplikasi dengan pid %d (%s).\n" +"Tutup aplikasi ini sebelum mengulang kembali." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Mode kecocokan '%s' tidak dikenal" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Mode kecocokan '%s' tidak dikenal untuk pola '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Ekspresi reguler '%s' tidak valid: regcomp kembali %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ekspresi reguler '%s' tidak valid" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autentikasi dibutuhkan untuk '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Akan mencoba lagi..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Menyerah setelah %1% mencoba." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Kunjungi Pusat Pelanggan SUSE untuk memeriksa apakah pendaftaran Anda valid " +"dan belum kedaluwarsa." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Kunjungi Pusat Pelanggan Novell untuk memeriksa apakah pendaftaran Anda " +"valid dan tidak kedaluwarsa." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Buat point lampiran: Tidak dapat menemukan direktori yang dapat ditulis " +"untuk membuat point lampiran" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Mohon pasang paket 'lsof' terlebih dahulu." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Tidak dapat membuat metadata direktori singgahan." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Galat saat membaca dari '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Tidak dapat membuat %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Metadata yang valid tidak ditemukan pada URL yang ditentukan" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Gagal untuk membuat repo singgahan (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Membangun repositori singgahan '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Tidak dapat membuat singgahan di %s - tidak ada izin untuk menulis." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Jenis repositori yang tidak tertangani" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Menambah repositori '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nama berkas repo tidak valid di '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Tidak dapat membuka berkas '%s' untuk menulis." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Galat tidak diketahui dari '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Tidak dapat membaca direktori repo '%1%': Izin ditolak" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Gagal membaca direktori '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Tidak dapat membaca berkas repo '%1%': Izin ditolak" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Menghapus reposotori '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Tidak dapat mengetahui di mana repo disimpan." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Tidak dapat menghapus '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Tidak dapat mengetahui di mana layanan disimpan." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Layanan tidak diketahui '%1%': Menghapus layanan repositori yang tidak " +"terpakai '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Alias repositori tidak dapat dimulai dengan titik." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Alias layanan tidak dapat dimulai dengan titik." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Lanjutkan?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Repositori %1% tidak mendefinisikan 'gpgkey=' URL tambahan." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Mencari kunci gpg ID %1% dalam repositori %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Mencari kunci gpg ID %1% dalam singgahan %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Kebutuhan atribut '%s' hilang." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Satu atau kedua dari '%s' or '%s' atribut dibutuhkan." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Verifikasi tanda tangan gagal" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Paket %s terlihat korup saat transfer berlangsung. Apakah anda henda " +"mengulang pemulihan?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Gagal untuk menyediakan paket %s. Apakah anda hendak memulai ulang pemulihan?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "pengecekan applydeltarpm gagal." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm gagal." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Layanan pengaya tidak mendukung perubahan atribut." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Tidak dapat meyediakan berkas '%s' dari repositori '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Tidak ada url pada repositori." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Media yang diharapkan %1%/%2% diidentifikasi oleh berkas '%3%' dengan konten:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Berkas %1%\n" +" dari paket\n" +" %2%\n" +" konflik dengan berkas dari paket\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Berkas %1%\n" +" dari paket\n" +" %2%\n" +" konflik dengan berkas dari pemasangan\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Berkas %1%\n" +" dari pemasangan\n" +" %2%\n" +" konflik dengan berkas dari paket\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Berkas %1%\n" +" dari pemasangan\n" +" %2%\n" +" konflik dengan berkas dari pemasangan\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Berkas %1%\n" +" dari paket\n" +" %2%\n" +" konflik dengan berkas\n" +" %3%\n" +" dari paket\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Berkas %1%\n" +" dari paket\n" +" %2%\n" +" konflik dengan berkas\n" +" %3%\n" +" dari pemasangan\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Berkas %1%\n" +" dari pemasangan\n" +" %2%\n" +" konflik dengan berkas\n" +" %3%\n" +" dari paket\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Berkas %1%\n" +" dari pemasangan\n" +" %2%\n" +" konflik dengan berkas\n" +" %3%\n" +" dari pemasangan\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Tidak dapat membuat sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "patahkan %s dengan mengabaikan beberapa dependensi" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "umumnya mengabaikan beberapa dependensi" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "%1% yang dipasang bukan milik repositori distupgrade dan harus diganti" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "yang akan dipasang %1% bukan milik repositori distupgrade" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "%1% yang terpasang memiliki arsitektur yang lebih rendah" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "yang akan dipasang %1% memiliki arsitektur yang lebih rendah" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "masalah dengan %1% yang terpasang" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "permintaan konflik" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "beberapa dependensi bermasalah" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "tidak ada yang menyediakan '%1%' yang diminta" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Apakah Anda mengaktifkan semua repositori yang diperlukan?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "paket yang diminta %1% tidak ada" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "permintaan tidak didukung" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' disediakan oleh sistem dan tidak dapat dihapus" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% tidak dapat dipasang" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "tidak ada yang menyediakan '%1%' yang diperlukan oleh %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "tidak ada yang menyediakan '%1%' yang diperlukan untuk dipasang %2%" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "tidak dapat memasang %1% dan %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "konflik %1% yang dipasang dengan '%2%' yang disediakan oleh %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"%1% yang dipasang bertentangan dengan '%2%' yang disediakan oleh yang akan " +"dipasang %3%" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"yang akan dipasang %1% konflik dengan '%2%' yang disediakan oleh %3% yang " +"terpasang" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"yang akan dipasang %1% konflik dengan '%2%' disediakan oleh yang akan " +"dipasang %3%" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "%1% usang yang terpasang '%2%' disediakan oleh %3% yang terpasang" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "%1% usang yang terpasang '%2%' disediakan oleh yang akan dipasang %3%" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "yang akan dipasang %1% usang '%2%' disediakan oleh %3% yang terpasang" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"yang akan dipasang %1% usang '%2%' disediakan oleh yang akan dipasang %3%" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"konflik %1% yang dipasang dengan '%2%' yang disediakan dengan sendirinya" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "yang akan dipasang %1% konflik dengan '%2%' yang disediakan sendiri" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"%1% yang dipasang membutuhkan '%2%', tetapi persyaratan ini tidak dapat " +"disediakan" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"yang akan dipasang %1% membutuhkan '%2%', tetapi persyaratan ini tidak dapat " +"disediakan" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "penyedia dihapus: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"penyedia tidak dapat dihapus: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "penyedia tidak dapat dihapus: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% belum sepenuhnya terintegrasi ke dalam %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Biasanya Anda ingin mempertahankan PTF dan memilih untuk tidak memasang " +"tambalan pemeliharaan." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Menghapus %1% yang dipasang dalam konteks ini akan menghapus (bukan " +"mengganti!) paket PTF yang disertakan juga." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"PTF harus dihapus dengan memanggil '%1%'. Ini akan memutakhirkan paket PTF " +"yang disertakan alih-alih menghapusnya." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" +"Biasanya Anda ingin mempertahankan PTF atau memilih untuk membatalkan " +"tindakan." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "%1% yang dipasang memblokir tindakan yang diinginkan." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" +"Biasanya Anda ingin mempertahankan PTF dan memilih untuk membatalkan " +"tindakan." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "hapus kunci untuk memungkinkan penghapusan %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "jangan pasang %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "pertahankan %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "hapus kunci untuk memungkinkan pemasangan %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Permintaan ini akan merusak sistem anda!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "abaikan peringatan sistem yang rusak" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "jangan meminta untuk memasang solvable yang menyediakan %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "jangan meminta untuk menghapus semua solvables yang menyediakan %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "jangan memasang versi terbaru %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "pertahankan %1% meskipun arsitekturnya lebih rendah" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "pasang %1% meskipun arsitekturnya lebih rendah" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "biarkan usang %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "pasang %1% dari repositori yang dikecualikan" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "pasang %1% meskipun telah ditarik kembali" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "memungkinkan untuk memasang PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "pasang %1% meskipun masuk daftar hitam" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "turunkan %1% ke %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "perubahan arsitektur dari %1% menjadi %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"pasang %1% (dengan perubahan vendor)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"pasang %1% dari vendor %2%\n" +" menggantikan %3% dari vendor %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "penggantian %1% dengan %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "pemasangan ulang %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Menjalankan skrip pasca transaksi" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Menjalankan skrip %1%." + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "%1% keluaran skrip:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Pemasangan dibatalkan sesuai perintah." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " tereksekusi" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " eksekusi gagal" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s sudah dieksekusi sebagai %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " eksekusi dilewati saat membatalkan" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Galat mengirim pesan notifikasi pemutakhiran." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Pesan baru" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Sinyal yang diterima :\"%1% (%2%)\", untuk memastikan konsistensi sistem, " +"tidak mungkin membatalkan transaksi rpm yang sedang berjalan." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Mengeksekusi transaksi gagal karena masalah berikut:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM gagal: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Gagal mengimpor kunci publik %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Gagal menghapus kunci publik %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Header paket tidak ditandatangani!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Payload paket tidak ditandatangani!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Mengubah berkas konfigurasi untuk %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm telah disimpan %s sebagai %s, tetapi tidak memungkinkan untuk menentukan " +"perbedaannya" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm %s telah disimpan sebagai %s.\n" +"Ini adalah perbedaan 25 baris pertama:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm telah disimpan %s sebagai %s, tetapi tidak memungkinkan untuk menentukan " +"perbedaannya" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm %s telah dibuat sebagai %s.\n" +"Ini adalah perbedaan 25 baris pertama:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Keluaran rpm tambahan" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "membuat cadangan %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Tanda tangan OK" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tanda tangan tidak dikenal" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Tanda tangan tidak terverifikasi" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Tanda tangan OK, tetapi kunci tidak terpercaya" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Tanda tangan kunci publik tidak tersedia" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Berkas tidak ada atau tanda tangan tidak dapat diperiksa" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Berkas tidak ditandatangani" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tipe ambigu '%s' untuk '%u' byte checksum '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Tidak dapat membuka pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Tidak dapat membuka pipe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "String kueri URL LDAP tidak valid" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Parameter kueri URL LDAP '%s’ tidak valid" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Tidak dapat mengkloning objek Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Referensi objek URL kosong tidak valid" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Tidak dapat mengurai komponen Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Riwayat:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Skema Url tidak diizinkan %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Komponen '%s' tidak valid %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Komponen '%s' tidak sah" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Pemrosesan string kueri tidak didukung untuk URL ini" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Skema url merupakan komponen yang diperlukan" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Skema url '%s' tidak valid" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Skema Url tidak memperbolehkan nama pengguna" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Skema Url tidak memperbolehkan kata sandi" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Skema Url membutuhkan komponen host" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Skema Url tidak memperbolehkan komponen host" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Komponen host '%s' tidak valid" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Skema Url tidak memperbolehkan port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Komponen Port '%s' tidak sah" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Skema url membutuhkan nama path" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Path relatif tidak dibolehkan bila otoritas ada" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "String yang dikodekan berisi byte NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Karakter pemisah susunan pemecah tidak valid" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Karakter pemisah parameter map tidak valid" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Karakter pemisah susunan join tidak valid" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Perintah berhenti dengan status %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Perintah terhenti oleh sinyal %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Perintah berhenti dengan galat yang tidak diketahui." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Argumen spawn yang diberikan tidak valid." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Tidak dapat membuat pipa kontrol." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Tidak dapat chroot untuk '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Tidak dapat membuka ke '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Tidak dapat chdir ke '%s' dalam chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Tidak dapat mengeksekusi '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Tidak dapat melakukan fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Tak bisa eksekusi '%s', chdir gagal (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Tak bisa eksekusi '%s', chroot gagal (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Tak bisa eksekusi '%s', eksekusi gagal (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Tak bisa eksekusi '%s', kesalahan tak terduga." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Gagal untuk mengaitkan %s pada %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Gagal untuk melepas %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nama berkas yang buruk: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Medium tidak dibuka ketika mencoba untuk melakukan tindakan '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Berkas '%s' tidak ditemukan pada medium '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Tidak dapat menulis berkas '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Medium tidak dilampirkan" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Media poin lampiran buruk" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Unduh (curl) inisialisasi gagal untuk '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Pengecualian sistem '%s' pada medium '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Lokasi '%s' pada medium '%s' bukan sebuah berkas." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Lokasi '%s' pada medium '%s' bukan sebuah direktori." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI yang salah bentuk" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nama host kosong pada URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Sistem berkas kosong pada URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Tujuan kosong pada URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Skema URI tidak didukung pada '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operasi tidak didukung oleh medium" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Unduh (curl) galat untuk '%s':\n" +"Kode galat: %s\n" +"Pesan galat: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Galat terjadi ketika mengatur unduhan (curl) pada opsi untuk '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Sumber media '%s' tidak berisi media yang diinginkan" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Medium '%s' sedang digunakan oleh instance lain" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Tidak dapat mengeluarkan media apapun" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Tidak dapat mengeluarkan media '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Izin untuk mengakses '%s' ditolak." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Batas waktu terlampaui saat mengakses '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Data yang diunduh melebihi ukuran yang diharapkan '%s' dari '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Lokasi '%s' tidak dapat diakses sementara waktu." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " Masalah SSL Sertifikat, pastikan CA cert sudah benar untuk '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Tidak ada sumber daya bebas yang tersedia untuk melampirkan media." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Metode autentikasi HTTP '%s' tidak didukung" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Kesalahan unduhan (curl) untuk '%s':\n" +"Kode kesalahan: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Kesalahan unduhan (curl) untuk '%s':\n" +"Tidak dapat mengambil respon HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ya" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Tidak" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Catatan:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Peringatan:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Galat:" + +# ID +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "selesai" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "perhatian" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "galat" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Peringatan: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Mengambil:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "mulai" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "tidak ditemukan" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Tidak ada bantuan yang tersedia untuk permintaan ini." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "tidak ada bantuan yang tersedia untuk opsi ini" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "tampilkan semua opsi" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ya" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "tidak" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Menjalankan skrip '%1%' %%posttrans" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Menjalankan skrip %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "Paket tidak ditandatangani!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s bukan milik repositori distupgrade" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s memiliki arsitektur yang lebih rendah" + +#~ msgid "problem with installed package %s" +#~ msgstr "masalah dengan paket %s yang telah terpasang" + +#~ msgid "nothing provides requested %s" +#~ msgstr "tidak ada ketersediaan yang meminta %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Apakah Anda mengaktifkan semua repositori yang diminta?" + +#~ msgid "package %s does not exist" +#~ msgstr "paket %s tidak tersedia" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s disediakan oleh sistem dan tidak dapat dihapus" + +#~ msgid "%s is not installable" +#~ msgstr "%s tidak dapat dipasang" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "tidak ada dukungan %s dibutuhkan oleh %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "tidak dapat memasang kedua %s dan %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s konflik dengan %s disediakan oleh %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s yang %s disediakan oleh %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "telah dipasang %s usang %s didukung oleh %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "dapat dipecahkan %s konflik dengan %s didukung dengan sendirinya" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s memerlukan %s, tetapi persyaratan ini tidak dapat disediakan" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "hapus kunci untuk memungkinkan penghapusan %s" + +#~ msgid "do not install %s" +#~ msgstr "jangan memasang %s" + +#~ msgid "keep %s" +#~ msgstr "simpan %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "hapus kunci untuk memungkinkan pemasangan %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "jangan meminta untuk memasang pemecahan yang didukung %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "jangan meminta untuk menghapus pemecahan yang didukung %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "jangan memasang versi terbaru dari %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "jaga %s meskipun arsitektur rendah" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "pasang %s meskipun arsitektur rendah" + +#~ msgid "keep obsolete %s" +#~ msgstr "biarkan usang %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "pasang %s dari repositori pengecualian" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "turunkan dari %s to %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "arsitektur berubah dari %s ke %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "pasang %s (dengan perubahan vendor)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "penggantian %s dengan %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "penghapusan dari %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Tidak dapat membuka berkas kunci: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Tindakan ini sudah dijalankan oleh program lain." + +#~ msgid "Hal Exception" +#~ msgstr "Pengecualian Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Maaf, tetapi versi dari libzypp yang digunakan ini dibangun tanpa " +#~ "dukungan HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext tidak tersambung" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive tidak dinisialisasi" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume tidak dinisialisasi" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Tidak dapat membuat koneksi dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Tak dapat membuat konteks libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Tak dapat mengatur koneksi dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Tak dapat menginisialisasi konteks HAL -- hald tidak berjalan?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Bukan CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Tak bisa menginialisasi atribut mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Tak bisa mengeset atribut rekursif mutex" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Tak bisa menginisialisasi mutex rekursif" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Tidak dapat memperoleh kunci mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Tak bisa membuka kunci mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Gagal mengimpor kunci publik dari berkas %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Gagal menghapus kunci publik %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Tidak dapat menemukan perangkat loop tersedia untuk mengaitkan file image " +#~ "dari '%s'" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "Italia" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Italia" + +#, fuzzy +#~ msgid "install %s" +#~ msgstr "Italia" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "Italia" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Tidak dapat membuka %s: %m" + +#, fuzzy +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "Parsing Parameter Path tidak didukung untuk url ini" + +#, fuzzy +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "Parsing parameter path tidak didukung untuk url ini" + +#, fuzzy +#~ msgid "Establishing %s" +#~ msgstr "Italia" + +#, fuzzy +#~ msgid "Installing %s" +#~ msgstr "Italia" + +#, fuzzy +#~ msgid "Unable to parse Url authority" +#~ msgstr "Tidak dapat memparse komponen otoritas url" + +#, fuzzy +#~ msgid "Unable to restore all sources." +#~ msgstr "Tidak dapat memparse komponen url utama" + +#, fuzzy +#~ msgid "Downloading %s" +#~ msgstr "Kesalahan memuatkan %1" diff --git a/po/it.po b/po/it.po new file mode 100644 index 0000000..33d622a --- /dev/null +++ b/po/it.po @@ -0,0 +1,5568 @@ +# translation of zypp.po to italiano +# Italian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999, 2000, 2001 SuSE GmbH. +# +# Franca Delcarlo , 1999, 2000, 2001. +# Karl Eichwalder , 2000. +# Bevacqua Giuseppe , 2008. +# Andrea Florio , 2008. +# Andrea Florio , 2008, 2009. +# Andrea Turrini , 2013, 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-05-04 16:43+0000\n" +"Last-Translator: Davide Aiello \n" +"Language-Team: Italian \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: Weblate 4.9.1\n" +"X-Poedit-Bookmarks: 370,-1,-1,-1,-1,-1,-1,-1,-1,-1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Paese sconosciuto: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Nessun codice" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Emirati Arabi Uniti" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua e Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antille olandesi" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antartide" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa americane" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Isole Aland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaijan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia-Erzegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgio" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasile" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Isola Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Bielorussia" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Isole Cocos (Keeling)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Repubblica Centrafricana" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Svizzera" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Costa d'Avorio" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Isole Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Cile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Cina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Capo Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Isola Christmas" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cipro" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Repubblica Ceca" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Germania" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Gibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danimarca" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Repubblica dominicana" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algeria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egitto" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sahara occidentale" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spagna" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlandia" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Isole Falkland (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Stati federati di Micronesia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Isole Faroe" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francia" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Francia metropolitana" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Regno Unito" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guiana francese" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibilterra" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenlandia" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadalupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinea equatoriale" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grecia" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Georgia meridionale e Isole Sandwich meridionali" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Isola Heard e isole McDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croazia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungheria" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanda" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israele" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isola di Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Territorio dell'Oceano indiano britannico" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraq" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islanda" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Giamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Giordania" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Giappone" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirghizistan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambogia" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comore" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts e Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Corea del Nord" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Corea del Sud" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Isole Cayman" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakistan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Repubblica democratica popolare del Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libano" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituania" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Lussemburgo" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Lettonia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marocco" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavia" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Isole Marshall" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Birmania" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Isole Marianne settentrionali" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinica" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldive" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Messico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malesia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambico" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nuova Caledonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Isola di Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Paesi Bassi" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norvegia" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nuova Zelanda" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Perù" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinesia francese" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nuova Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filippine" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polonia" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre e Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Portorico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Territorio palestinese" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portogallo" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Federazione russa" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arabia Saudita" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Isole Solomon" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Svezia" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sant'Elena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard e Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovacchia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé e Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Siria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Isole Turks e Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Territori francesi meridionali" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailandia" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tagikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor est" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turchia" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad e Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ucraina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Isole minori esterne degli Stati Uniti" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Stati Uniti" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Santa Sede (Città del Vaticano)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent e Grenadine" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Isole Vergini britanniche" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Isole Vergini, Stati Uniti" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis e Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Sud Africa" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Fornisce" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Prerequisiti" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Richiede" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "In conflitto con" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Obsoleti" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Raccomanda" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Suggerisce" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Migliora" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Integra" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Tentativo di importare la chiave inesistente %s nel portachiavi %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Impossibile importare la chiave." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Impossibile eliminare la chiave." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "La firma del file %s non è stata trovata" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Lingua sconosciuta: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhazo" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinese" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asiatico (altre)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Accadico" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanese" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Lingue algonchine" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altai meridionale" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amarico" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Inglese, antico (450-1100 circa)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Lingue Apache" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabo" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaico" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonese" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armeno" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucano" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Lingue artificiali (altre)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Aruaco" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamese" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturiano" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Lingue Athabaska" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Lingue australiane" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarico" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestano" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaigiano" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Lingue Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinese" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basco" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltico (altre)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorusso" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berbero (altre)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (altre)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosniaco" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretone" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginese" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgaro" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmese" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Indiano dell'America centrale (altre)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Caribico" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalano" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucasico (altre)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celtico (altre)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Ceceno" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Cinese" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Linguaggio Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Slavo ecclesiastico" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Lingue Chamic" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Copto" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornico" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corso" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creole e pidgin, basate sull'inglese (altro)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creole e pidgin, basate sul francese (altro)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creole e pidgin, basate sul portoghese (altro)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tataro della Crimea" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creole e pidgin (altre)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Casciubo" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cuscitico (altre)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Ceco" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danese" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slavo (Athabaska)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidiche (Altre)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Sorabo inferiore" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Olandese, medio (1050-1350 circa)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Olandese" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egiziano (antico)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Akajo" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamitico" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inglese" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Inglese, medio (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estone" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faroese" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Figiano" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filippino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finlandese" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Ugrofinnico (altre)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francese" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francese, medio (1400-1600 circa)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francese, antico (842-1400 circa)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisone" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fula" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulano" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Lingue germaniche (altre)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgiano" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Tedesco" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Ge'ez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertese" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelico" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandese" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galiziano" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Tedesco, medio-alto (1050-1500 circa)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Tedesco, antico alto (750-1050 circa)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotico" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Greco antico (fino al 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Greco moderno (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitiano" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiano" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Ebraico" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Ittita" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Sorabo superiore" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ungherese" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandese" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Associazione internazionale lingue ausiliarie)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indico (altre)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesiano" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Lingue indo-europee (altre)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraniano (altre)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Lingue irochesi" + +# TLABEL modules/inst_target_part.ycp:680 +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiano" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Giavanese" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Giapponese" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Giudeo-persiano" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Giudeo-arabico" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazako" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Cabardo" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (altre)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanese" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiso" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreano" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraeano" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachai-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Curdo" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latino" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Lettone" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezgiano" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburghese" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituano" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Lussemburghese" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya e Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedone" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurese" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallese" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesiano (altre)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandese, medio (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Lingue varie" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (altre)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgascio" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltese" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manciù" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Lingue Manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavo" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolo" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Lingue multiple" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Lingue munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Lingue maya" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Lingua Erza" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Indiano del Nord America" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napoletano" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, meridionale" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, settentrionale" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Tedesco, basso" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalese" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofaniano (altre)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueano" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norvegese Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norvegese Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norse, antico" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norvegese" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho, settentrionale" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Lingue nubiane" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari classico" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitano (dopo il 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osseto" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turco, ottomano (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Lingue otomiane" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuano (altre)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauano" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persiano, antico (600-400 a.C. circa)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persiano" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filippino (altre)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenicio" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polacco" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeiano" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portoghese" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Lingue Pracrito" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provenzale, antico (fino al 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pashtu" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongano" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romancio (altre)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Retoromanzo" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romeno" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romeno" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russo" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Indiano dell'America meridionale (altre)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Lingue Salish" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Aramaico samaritano" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanscrito" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbo" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliano" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scozzese" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croato" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Lingue semitiche (altre)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandese, antico (fino al 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Linguaggi dei segni" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singalese" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Lingue Siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetano (altre)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavo (altre)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovacco" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Sloveno" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sami meridionale" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Sami settentrionale" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Lingue Sami (altre)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Sami di Lule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Sami di Inari" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoano" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Sami skolt" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalo" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, meridionale" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spagnolo" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardo" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Sahariano (altre)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swazi" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanese" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumero" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Svedese" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siriaco" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitiano" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (altre)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tataro" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tagico" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetano" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrino" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Isole Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmeno" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Lingue Tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turco" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaico (altre)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvano" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurto" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritico" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uiguro" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ucraino" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Indeterminato" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbeko" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamita" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votico" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Lingue Wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Gallese" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Lingue sorabe" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Vallone" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Calmucco" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Lingue Yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Chuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Verranno eseguite le azioni indicate:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "non scade" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "scaduta: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "scade: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(non scade)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(SCADUTO)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(scade entro 24 ore)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(scade entro %d giorno)" +msgstr[1] "(scade entro %d giorni)" + +# TLABEL modules/inst_user.ycp:71 +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "sconosciuto" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "non supportato" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Livello 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Livello 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Livello 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Contratto clienti aggiuntivo necessario" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Non più supportato e sostituito da un pacchetto diverso" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "non valido" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Il livello di supporto non è specificato" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Il fornitore non fornisce supporto." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Identificazione del problema, ovvero supporto tecnico indirizzato a fornire " +"informazioni sulla compatibilità, assistenza per l'installazione, supporto " +"per l'utilizzo, manutenzione ordinaria e risoluzione dei problemi di base. " +"L'obiettivo del supporto di Livello 1 non è correggere errori e difetti del " +"prodotto." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Isolamento del problema, ovvero supporto tecnico indirizzato a riprodurre i " +"problemi del cliente, isolare l'area del problema e fornire una soluzione ai " +"problemi non risolti dal Supporto di Livello 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Risoluzione del problema, ovvero supporto tecnico indirizzato a risolvere " +"problemi complessi attraverso la programmazione nella correzione dei difetti " +"di prodotto che sono stati identificati dal Supporto di Livello 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "È necessario un contratto cliente aggiuntivo per ottenere supporto." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"Il pacchetto non è più supportato ed è stato sostituito da un nuovo " +"pacchetto con un nome diverso." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Opzione di supporto sconosciuta. Descrizione non disponibile" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"La gestione di sistemi è bloccata dall'applicazione con pid %d (%s).\n" +"Chiudere l'applicazione prima di riprovare." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Modalità di corrispondenza '%s' sconosciuta" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Modalità di corrispondenza '%s' sconosciuta per il modello '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Espressione regolare '%s' non valida: regcomp ha restituito %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Espressione regolare '%s' non valida" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "È richiesta l'autenticazione per '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Verrà eseguito un nuovo tentativo..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "L'operazione verrà annullata dopo %1% tentativi." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visitare SUSE Customer Center per verificare se la registrazione è valida e " +"che non sia scaduta." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visitare Novell Customer Center per verificare che la registrazione sia " +"valida e che non sia scaduta." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Creazione del punto di collegamento: impossibile trovare una directory " +"scrivibile per creare un punto di collegamento" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Installare prima il pacchetto 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Impossibile creare la directory della cache dei metadati." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Errore durante il tentativo di lettura da '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Impossibile creare %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Non sono stati trovati metadati validi all'URL specificato" +msgstr[1] "Non sono stati trovati metadati validi agli URL specificati" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Impossibile creare la cache del repo (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Costruzione della cache del repository '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Impossibile creare la cache in %s - permessi di scrittura mancanti." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Tipo di repository non gestito" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Aggiunta del repository '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nome file del repository non valido a '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Impossibile aprire il file '%s' in scrittura." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Errore sconosciuto durante la lettura da '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Impossibile leggere la directory '%1%' del repository: permesso negato" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Impossibile leggere la directory '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Impossibile leggere il file '%1%' del repository: permesso negato" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Rimozione del repository '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Impossibile trovare ubicazione di memorizzazione del repository." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Impossibile eliminare '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Impossibile trovare ubicazione di memorizzazione del servizio." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Servizio '%1%' sconosciuto: rimozione del repository dei servizi orfani '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "L'alias di un repository non può iniziare con un punto." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "L'alias di un servizio non può iniziare con un punto." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Nessun sommario per il file %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Sommario %s sconosciuto per il file %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Verifica del sommario non riuscita per il file '%s'" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Il file '%s' non è firmato. Continuare?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Il file '%s' dal repository '%s' non è firmato. Continuare?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" +"Rifiutare la chiave, considerarla temporaneamente attendibile o considerarla " +"sempre attendibile?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Nome della chiave: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +"Ricevuta %1% nuova chiave di firma del pacchetto dal repository \"%2%\":" +msgstr[1] "" +"Ricevute %1% nuove chiavi di firma del pacchetto dal repository \"%2%\":" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Verifica della firma non riuscita per il file '%1%'." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"Verifica della firma non riuscita per il file '%1%' dal repository '%2%'." + +# internal key used: Ok +# internal key used: Ok +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Continuare?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Il file '%s' è firmato con una chiave sconosciuta '%s'. Continuare?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Il file '%s' dal repository '%s' è firmato con una chiave sconosciuta '%s'. " +"Continuare?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Il repository %1% non definisce URL aggiuntivi 'gpgkey='." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Ricerca dell'ID %1% della chiave GPG nel repository %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Ricerca dell'ID %1% della chiave GPG nella cache %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "L'attributo richiesto '%s' è mancante." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Uno o entrambi gli attributi '%s' o '%s' sono richiesti." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Verifica della firma non riuscita" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Possibile danneggiamento del pacchetto %s durante il trasferimento. " +"Ritentare il recupero?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Impossibile fornire il pacchetto %s. Ritentare il recupero?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Verifica di applydeltarpm non riuscita." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm non riuscito." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Il plug-in del servizio non supporta la modifica di un attributo." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Impossibile fornire il file '%s' dal repository '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Nessun URL nel repository." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "Supporto previsto %1%/%2% identificato dal file '%3%' con contenuto:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Il file %1%\n" +" del pacchetto\n" +" %2%\n" +" è in conflitto con il file del pacchetto\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Il file %1%\n" +" del pacchetto\n" +" %2%\n" +" è in conflitto con il file dell'installazione di\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Il file %1%\n" +" dell'installazione di\n" +" %2%\n" +" è in conflitto con il file del pacchetto\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Il file %1%\n" +" dell'installazione di\n" +" %2%\n" +" è in conflitto con il file dell'installazione di\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Il file %1%\n" +" del pacchetto\n" +" %2%\n" +" è in conflitto con il file\n" +" %3%\n" +" del pacchetto\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Il file %1%\n" +" del pacchetto\n" +" %2%\n" +" è in conflitto con il file\n" +" %3%\n" +" dell'installazione di\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Il file %1%\n" +" dell'installazione di\n" +" %2%\n" +" è in conflitto con il file\n" +" %3%\n" +" del pacchetto\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Il file %1%\n" +" dell'installazione di\n" +" %2%\n" +" è in conflitto con il file\n" +" %3%\n" +" dell'installazione di\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Impossibile creare sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "installa comunque %s ignorando alcune delle sue dipendenze" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "generalmente ignora alcune dipendenze" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"%1% installato non appartiene a un repository di aggiornamento della " +"distribuzione e deve essere sostituito" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" +"%1% da installare non appartiene a un repository di aggiornamento della " +"distribuzione" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "%1% installato presenta un'architettura inferiore" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "%1% da installare presenta un'architettura inferiore" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problema con %1% installato" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "richieste in conflitto" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "alcuni problemi di dipendenze" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "nessun elemento fornisce '%1%' obbligatorio" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Sono stati abilitati tutti i repository richiesti?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "il pacchetto richiesto %1% non esiste" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "richiesta non supportata" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' viene fornito dal sistema e non può essere cancellato" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% non è installabile" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "nessun elemento fornisce '%1%' obbligatorio per %2% installato" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "nessun elemento fornisce '%1%' obbligatorio per %2% da installare" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "impossibile installare %1% e %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "%1% installato è in conflitto con '%2%' fornito da %3% installato" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "%1% installato è in conflitto con '%2%' fornito da %3% da installare" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "%1% da installare è in conflitto con '%2%' fornito da %3% installato" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"%1% da installare è in conflitto con '%2%' fornito da %3% da installare" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "%1% installato rende obsoleto '%2%' fornito da %3% installato" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "%1% installato rende obsoleto '%2%' fornito da %3% da installare" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "%1% da installare rende obsoleto '%2%' fornito da %3% installato" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "%1% da installare rende obsoleto '%2%' fornito da %3% da installare" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "%1% installato è in conflitto con '%2%' fornito da se stesso" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "%1% da installare è in conflitto con '%2%' fornito da se stesso" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"%1% installato richiede '%2%', ma non è possibile fornire questo requisito" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"%1% da installare richiede '%2%', ma non è possibile fornire questo requisito" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "provider cancellati: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"impossibile installare i provider: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "provider non installabili: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% non è ancora completamente integrato in %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"In genere, è consigliabile mantenere il PTF e scegliere di non installare le " +"patch di manutenzione." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"In questo contesto, la rimozione della %1% installata rimuoverà (non " +"sostituirà) anche i pacchetti PTF inclusi." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"Rimuovere la PTF richiamando '%1%'. In tal modo i pacchetti PTF inclusi " +"verranno aggiornati anziché rimossi." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" +"Di norma si suppone di voler mantenere la PTF o scegliere di annullare " +"l'azione." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "%1% installato blocca l'azione desiderata." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" +"In genere, è consigliabile mantenere il PTF e scegliere di annullare " +"l'azione." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "rimuovi il blocco per consentire la rimozione di %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "non installare %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "mantieni %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "rimuovi il blocco per consentire l'installazione di %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Questa richiesta potrebbe danneggiare il sistema!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignora avviso di sistema malfunzionante" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "non chiedere di installare un risolubile che fornisce %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "non chiedere di eliminare tutti i risolubili che forniscono %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "non installare la versione più recente di %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "mantieni %1% nonostante l'architettura inferiore" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "installa %1% nonostante l'architettura inferiore" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "mantieni %1% obsoleto" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "installa %1% dal repository escluso" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "installare %1% anche se è stato ritirato" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "consentire installazione di PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "Installare %1% anche se è nella black list" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "downgrade di %1% a %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "modifica di architettura di %1% in %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"installa %1% (con cambio di fornitore)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"installa %1% dal fornitore %2%\n" +" sostituzione di %3% del fornitore %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "sostituzione di %1% con %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "disinstallazione di %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Esecuzione script postransazionali in corso" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Esecuzione di %1% script in coro" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Output script %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "L'installazione è stata interrotta come indicato." + +# TLABEL modules/inst_config_x11.ycp:578 +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " eseguito" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " esecuzione non riuscita" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s già eseguito come %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " esecuzione saltata durante l'annullamento" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Errore nell'invio della notifica del messaggio di aggiornamento." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nuovo messaggio di aggiornamento" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Segnale ricevuto :\"%1% (%2%)\". Per garantire la coerenza del sistema, non " +"è possibile annullare una transazione rpm in esecuzione." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" +"L'esecuzione della transazione non è riuscita a causa dei seguenti problemi:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM non riuscito: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Errore importazione della chiave pubblica %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Errore rimozione della chiave pubblica %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "L'intestazione del pacchetto non è firmata!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Il contenuto del pacchetto non è firmato!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "File di configurazione modificati per %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm ha salvato %s come %s, tuttavia non è stato possibile determinare la " +"differenza" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ha salvato %s come %s.\n" +"Di seguito sono riportate le prime 25 righe di differenza:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm ha creato %s come %s, tuttavia non è stato possibile determinare la " +"differenza" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm ha creato %s come %s.\n" +"Di seguito sono riportate le prime 25 righe di differenza:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Output aggiuntivo di rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "creata copia di backup di %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "La firma è corretta" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tipo di firma sconosciuto" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "La firma non è verificabile" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "La firma è corretta, ma non è attendibile" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "La chiave pubblica delle firme non è disponibile" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Il file non esiste o la firma non può essere verificata" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "File non firmato" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tipo '%s' incerto per %u byte del codice di controllo '%s'" + +# TLABEL modules/sound/sound.ycp:620 +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Impossibile aprire pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Impossibile aprire pipe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Stringa di interrogazione URL LDAP non valida" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Parametro di interrogazione URL LDAP '%s' non valido" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Impossibile clonare l'oggetto url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Riferimento a oggetto url vuoto non valido" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Impossibile analizzare i componenti dell'url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Cronologia:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Lo schema url non consente un %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "%s componente '%s' non valido" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Componente %s non valido" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Analisi della stringa di interrogazione non supportata per questo URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Lo schema url è un componente obbligatorio" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Schema url '%s' non valido" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Lo schema url non consente un nome utente" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Lo schema url non consente una password" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Lo schema url richiede un componente host" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Lo schema url non consente un componente host" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Componente host '%s' non valido" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Lo schema url non consente una porta" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Componente porta '%s' non valido" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Lo schema url richiede un nome di percorso" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Percorso relativo non consentito se l'autorità esiste" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "La stringa codificata contiene un byte NULL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" +"Carattere di separazione di divisione della matrice di parametri non valido" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Carattere di separazione di divisione mappa di parametri non valido" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Carattere di separazione unione della matrice di parametri non valido" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Il comando è terminato con stato %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Il comando è stato terminato dal segnale %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Il comando è terminato con un errore sconosciuto." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Argomenti di distribuzione non validi forniti." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Impossibile creare la pipe di controllo." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Impossibile eseguire il comando chroot in '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Impossibile eseguire chdir verso '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Impossibile eseguire chdir verso '%s' dentro la chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Impossibile eseguire '%s' (%s)." + +# TLABEL modules/installation.ycp:287 +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Impossibile eseguire il comando fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Impossibile eseguire '%s', chdir non riuscito (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Impossibile eseguire '%s', chroot non riuscito (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Impossibile eseguire '%s'; esecuzione non riuscita (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Impossibile eseguire '%s', errore inaspettato." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Impossibile montare %s su %s." + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Impossibile smontare %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nome file errato: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Supporto non aperto durante il tentativo di esecuzione di '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "File '%s' non trovato sul supporto '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Impossibile scrivere il file '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Supporto non collegato" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Punto di collegamento supporto errato" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Inizializzazione download (curl) non riuscita per '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Eccezione di sistema '%s' sul supporto '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Il percorso '%s' sul supporto '%s' non è un file." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Il percorso '%s' sul supporto '%s' non è una directory." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Formato URI errato" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nome host vuoto nell'URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "File system vuoto nell'URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destinazione vuota nell'URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Schema URI non supportato in '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operazione non supportata dal supporto" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Errore di download (curl) per '%s':\n" +"Codice di errore: %s\n" +"Messaggio di errore: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Errore durante l'impostazione delle opzioni di download (curl) per '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "L'origine del supporto '%s' non contiene il supporto desiderato" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Supporto '%s' già utilizzato da un'altra istanza" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Impossibile espellere supporti" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Impossibile espellere il supporto '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Autorizzazione per accedere a '%s' rifiutata." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Timeout superato durante l'accesso a '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "I dati scaricati eccedono la dimensione attesa '%s' di '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "L'ubicazione '%s' è temporaneamente inaccessibile." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Problemi con il certificato SSL, verificare che il certificato CA sia " +"valido per '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Nessuna risorsa gratuita disponibile da collegare al supporto." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Metodo di autenticazione HTTP '%s' non supportato" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Errore di download (curl) per '%s':\n" +"Codice di errore %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Errore di download (curl) per '%s':\n" +"Impossibile recuperare la risposta HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Sì" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "No" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Nota:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Avvertenza:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Errore:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "fine" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "attenzione" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "errore" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Avvertenza: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Recupero di:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "avvio" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "non trovato" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Nessun aiuto disponibile per questa richiesta." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "nessun aiuto disponibile per questa opzione" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "mostra tutte le opzioni" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "sì" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "no" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Esecuzione dello script %%posttrans '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Esecuzione degli script %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "Il pacchetto non è firmato!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "" +#~ "%s non appartiene a un repository di aggiornamento della distribuzione" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s presenta un'architettura inferiore" + +#~ msgid "problem with installed package %s" +#~ msgstr "problema con il pacchetto installato %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "nessun elemento fornisce %s obbligatorio" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Sono stati abilitati tutti i repository richiesti?" + +#~ msgid "package %s does not exist" +#~ msgstr "il pacchetto %s non esiste" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s è fornito dal sistema e non può essere cancellato" + +# TLABEL modules/inst_target_part.ycp:680 +#~ msgid "%s is not installable" +#~ msgstr "impossibile installare %s" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "nessun elemento fornisce %s obbligatorio per %s" + +# TLABEL modules/inst_target_part.ycp:680 +#~ msgid "cannot install both %s and %s" +#~ msgstr "impossibile installare sia %s, sia %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s in conflitto con %s fornito da %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s rende obsoleto %s fornito da %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "l'installazione di %s rende obsoleto %s fornito da %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "il risolubile %s è in conflitto con %s fornito da se stesso" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s richiede %s, ma non è possibile fornire questa richiesta" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "rimuovi il blocco per consentire la rimozione di %s" + +# TLABEL modules/inst_target_part.ycp:680 +#~ msgid "do not install %s" +#~ msgstr "non installare %s" + +#~ msgid "keep %s" +#~ msgstr "mantieni %s" + +# TLABEL modules/inst_target_part.ycp:680 +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "rimuovi il blocco per consentire l'installazione di %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "non chiedere di installare un risolvibile che fornisce %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "non chiedere di eliminare tutti i risolvibili che forniscono %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "non installare la versione più recente di %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "mantieni %s nonostante l'architettura inferiore" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "installa %s nonostante l'architettura inferiore" + +#~ msgid "keep obsolete %s" +#~ msgstr "mantieni %s obsoleto" + +#~ msgid "install %s from excluded repository" +#~ msgstr "installa %s da repository escluso" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "downgrade di %s a %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "modifica dell'architettura di %s in %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "installa %s (con cambio di fornitore)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "sostituzione di %s con %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "disinstallazione di %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Impossibile aprire file bloccato: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Questa azione è stata già eseguita da un altro programma." + +#~ msgid "Hal Exception" +#~ msgstr "Eccezione Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "La versione di libzypp è stata creata senza il supporto per HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext non connesso" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive non inizializzato" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume non inizializzato" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Impossibile creare la connessione dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: impossibile creare il contesto libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "libhal_set_dbus_connection: impossibile impostare la connessione dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Impossibile inizializzare il contesto HAL - hald non in esecuzione?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Non è un'unità CD ROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Impossibile inizializzare gli attributi mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Impossibile impostare l'attributo mutex ricorsivo" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Impossibile inizializzare mutex ricorsivo" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Impossibile acquisire il blocco mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Impossibile rilasciare il blocco mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Errore importazione della chiave pubblica dal file %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Errore rimozione della chiave pubblica %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Impossibile trovare un dispositivo di loop disponibile per montare il " +#~ "file immagine da '%s'" + +# TLABEL modules/inst_target_part.ycp:680 +#~ msgid "do not keep %s installed" +#~ msgstr "non tenere installato %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Impossibile creare la chiave pubblica %s dal portachiavi %s per il file %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Inizializzazione dello scaricamento (metalink curl) per '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Errore di scaricamento (metalink curl) per '%s':\n" +#~ "Codice di errore: %s\n" +#~ "Messaggio di errore: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Scaricamento interrotto al %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Scaricamento interrotto dall'utente" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Si è verificato un errore durante l'impostazione delle opzioni di " +#~ "scaricamento (metalink curl) per '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Scaricamento di %s da %s fallito" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia e Montenegro" + +#~ msgid "Timeout exceeded when access '%s'." +#~ msgstr "Timeout superato mentre si accedeva a '%s'." diff --git a/po/ja.po b/po/ja.po new file mode 100644 index 0000000..d13048f --- /dev/null +++ b/po/ja.po @@ -0,0 +1,5518 @@ +# translation of zypp.po to Japanese +# Japanese message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2000, 2001 SuSE GmbH. +# +# Mike Fabian , 2000, 2001. +# Yasuhiko Kamata , 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-16 04:47+0000\n" +"Last-Translator: Yasuhiko Kamata \n" +"Language-Team: Japanese \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-Generator: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "不明な国: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "コードなし" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "アンドラ" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "アラブ首長国連邦" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "アフガニスタン" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "アンティグアおよびバーブーダ" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "アングイラ" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "アルバニア" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "アルメニア" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "オランダ領アンティル" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "アンゴラ" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "南極大陸" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "アルゼンチン" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "アメリカ領サモア" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "オーストリア" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "オーストラリア" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "アルーバ" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "オーランド諸島" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "アゼルバイジャン" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "ボスニア-ヘルツェゴヴィナ" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "バルバドス" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "バングラデシュ" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "ベルギー" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "ブルキナファソ" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "ブルガリア" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "バーレーン" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "ブルンディ" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "ベニン" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "バーミューダ" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "ブルネイダルサラーム国" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "ボリビア" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "ブラジル" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "バハマ" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "ブータン" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "ブーヴェ島" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "ボツワナ" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "ベラルーシ" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "ベリーズ" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "カナダ" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "ココス(キーリング)諸島" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "コンゴ" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "中央アフリカ共和国" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "スイス" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "コートディヴォワール" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "クック諸島" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "チリ" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "カメルーン" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "中国" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "コロンビア" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "コスタリカ" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "キューバ" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "カボベルデ" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "クリスマス島" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "キプロス" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "チェコ共和国" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "ドイツ" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "ジブティ" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "デンマーク" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "ドミニカ" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "ドミニカ共和国" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "アルジェリア" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "エクアドル" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "エストニア" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "エジプト" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "西サハラ" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "エリトリア" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "スペイン" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "エチオピア" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "フィンランド" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "フィジー" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "フォークランド諸島(マルビナス)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "ミクロネシア連邦" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "フェロー諸島" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "フランス" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "フランス本国" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "ガボン" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "英国" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "グレナダ" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "ジョージア" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "フランス領ギアナ" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "ガーンジー島" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "ガーナ" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "ジブラルタル" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "グリーンランド" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "ガンビア" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "ギニア" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "グアドループ" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "赤道ギニア" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "ギリシア" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "サウスジョージアおよびサウスサンドイッチ諸島" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "グアテマラ" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "グアム" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "ギニア-ビサウ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "ギニア" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "香港" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "ハード島およびマクドナルド諸島" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "ホンデュラス" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "クロアティア" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "ハイティ" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "ハンガリー" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "インドネシア" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "アイルランド" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "イスラエル" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "マン島" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "インド" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "英領インド洋植民地" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "イラク" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "イラン" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "アイスランド" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "イタリア" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "ジャージー" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "ジャマイカ" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "ヨルダン" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "日本" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "ケニア" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "キルギスタン" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "カンボジア" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "キリバス" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "コモロ" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "セントキッツネヴィス" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "北朝鮮" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "韓国" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "クウェート" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "ケイマン諸島" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "カザフスタン" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "ラオス人民民主共和国" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "レバノン" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "セントルシア" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "リヒテンシュタイン" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "スリランカ" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "リベリア" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "レソト" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "リトアニア" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "ルクセンブルク" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "ラトビア" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "リビア" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "モロッコ" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "モナコ" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "モルドバ" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "モンテネグロ" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "サンマルタン" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "マダガスカル" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "マーシャル諸島" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "マケドニア" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "マリ" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "ミャンマー" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "モンゴル" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "マカオ" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "北マリアナ諸島" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "マルティニク" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "モーリタニア" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "モントセラト" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "マルタ" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "モーリシャス" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "モルディブ" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "マラウイ" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "メキシコ" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "マレーシア" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "モザンビーク" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "ナミビア" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "ニューカレドニア" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "ニジェール" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "ノーフォーク島" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "ナイジェリア" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "ニカラグア" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "オランダ" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "ノルウェー" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "ネパール" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "ナウル語" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "ニウエ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "ニュージーランド" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "オマーン" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "パナマ" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "ペルー" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "フランス領ポリネシア" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "パプアニューギニア" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "フィリピン" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "パキスタン" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "ポーランド" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "サンピエールエミクロン" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "ピトケルン" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "プエルトリコ" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "パレスチナ地域" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "ポルトガル" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "パラウ" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "パラグアイ" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "カタール" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "レユニオン" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "ルーマニア" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "セルビア" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "ロシア連邦" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "ルワンダ" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "サウディアラビア" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "ソロモン諸島" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "セーシェル" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "スーダン" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "スウェーデン" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "シンガポール" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "セントヘレナ" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "スロベニア" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "スヴァールバルおよびヤンマイエン" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "スロバキア" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "シエラレオーネ" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "サンマリノ" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "セネガル" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "ソマリア" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "スリナム" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "サントーメ-プリンシペ" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "エルサルバドル" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "シリア" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "スイス" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "タークスアンドケーコス諸島" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "チャド" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "フランス南方領" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "トーゴ" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "タイ" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "タジキスタン" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "トケラウ語" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "トルクメニスタン" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "チュニジア" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "トンガ" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "東ティモール" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "トルコ" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "トリニダードトバゴ" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "ツバル" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "台湾" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "タンザニア" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "ウクライナ" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "ウガンダ" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "合衆国小離島" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "アメリカ合衆国" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "ウルグアイ" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "ウズベキスタン" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "教皇庁(ヴァティカン市国)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "セントヴィンセント-グレナディン" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "ベネズエラ" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "英領ヴァージン諸島" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "米国領ヴァージン諸島" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "ベトナム" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "ヴァヌアトゥ" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "ワリーエフトゥーナ" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "サモア" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "イエメン" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "マヨット" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "南アフリカ" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "ザンビア" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "ジンバブエ" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "提供" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "前提条件" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "必要" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "競合" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "廃止" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "推奨" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "提案" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "拡張" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "補足" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "存在しないキー %s をキーリング %s にインポートしようとしました" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "キーのインポートに失敗しました。" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "キーの削除に失敗しました。" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "署名ファイル %s が見つかりません" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "不明な言語: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "アファル語" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "アブハーズ語" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "アチェー語" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "アチョリ語" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "アダングメ語" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "アディゲ語" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "アフリカ-アジア語(その他)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "アフリヒリ語" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "アフリカーンス語" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "アイヌ語" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "アカン語" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "アッカド語" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "アルバニア語" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "アレウト語" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "アルゴンギン語" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "南アルタイ語" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "アムハラ語" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "古英語(ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "アパッチ語" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "アラビア語" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "アラム語" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "アラゴン語" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "アルメニア語" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "アラウカン語" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "アラパホー語" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "人工語(その他)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "アラワック語" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "アッサム語" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "アストゥリア語" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "アサパスカン語" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "オーストラリア語" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "アヴァール語" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "アヴェスター語" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "アワディー語" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "アイマラ語" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "アゼルバイジャン語" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "バンダ語" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "バミレケ語" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "バシキール語" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "バルーチー語" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "バンバラ語" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "バリ語" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "バスク語" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "バサ語" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "バルト語(その他)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "ベジャ語" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "ベラルーシ語" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "ベンバ語" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "ベンガル語" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "ベルベル語(その他)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "ボジュプリー語" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "ビハール語" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "ビコール語" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "ビニ語" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "ビスラマ語" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "シクシカ語" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "バントゥー語(その他)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "ボスニア語" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "ブラジ語" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "ブルトン語" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "バタク語(インドネシア)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "ブリヤート語" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "ブギス語" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "ブルガリア語" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "ビルマ語" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "ブラン語" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "カドー語" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "中央アメリカインディアン語(その他)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "カリブ語" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "カタロニア語" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "カフカス語(その他)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "セブアノ語" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "ケルト語(その他)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "チャモロ語" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "チブチャ語" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "チェチェン語" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "チャガタイ語" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "中国語" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "チヌーク語" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "マリ語" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "チヌークジャーゴン語" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "チョクトー語" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "チペワイアン語" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "チェロキー語" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "教会スラブ語" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "チュヴァシ語" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "シャイエン語" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "チャム語" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "コプト語" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "コーンウォール語" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "コルシカ語" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "英語が基盤のクレオール語・ピジン語(その他)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "フランス語が基盤のクレオール語・ピジン語(その他)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "ポルトガル語が基盤のクレオール語・ピジン語(その他)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "クリー語" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "クリミアタタール語" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "クレオール語・ピジン語(その他)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "カシューブ語" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "クシ語(その他)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "チェコ語" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "ダコタ語" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "デンマーク語" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "ダルギン語" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "ダヤク語" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "デラウェア語" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "スレーブ語(アタパスカ語)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "ドグリブ語" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "ディンカ語" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "ディヴェヒ語" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "ドグリー語" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "ドラヴィダ語(その他)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "低地ソルブ語" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "ドゥアーラ語" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "中世オランダ語(ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "オランダ語" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ディウラ語" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "ゾンカ語" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "エフィク語" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "エジプト語(古代)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "エカジュク語" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "エラム語" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "英語" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "中英語(1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "エスペラント語" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "エストニア語" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "エウェ語" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "エウォンド語" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "ファン語" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "フェロー語" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "ファンティ語" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "フィージー語" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "フィリピン語" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "フィンランド語" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "フィン-ウゴル語(その他)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "フォン語" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "フランス語" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "中世フランス語(ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "古フランス語(842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "フリースランド語" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "フラ語" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "フルイリアン語" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "ガー語" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "ガヨ語" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "バヤ語" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "ゲルマン諸語(その他)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "グルジア語" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "ドイツ語" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "ゲーズ語" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "ギルバート語" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "ガエリック語" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "アイルランド語" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "ガリシア語" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "マンクス語" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "中高ドイツ語(ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "古高ドイツ語(ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "ゴンド語" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "ゴロンタロ語" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "ゴート語" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "グレボ語" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "古代ギリシア語(-1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "現代ギリシア語(1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "グアラニー語" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "グジャラート語" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "グイッチン語" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "ハイダ語" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "ハイチ語" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "ハウサ語" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "ハワイ語" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "ヘブライ語" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "ヘレロ語" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "ヒリガイノン語" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "ヒマチャル語" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "ヒンディー語" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "ヒッタイト語" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "フモン語" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "モツ語" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "高地ソルブ語" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "ハンガリー語" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "フーパ語" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "イバン語" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "イボ語" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "アイスランド語" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "イド語" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "四川語" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "イジョ語" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "イヌクティトゥト語" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "インターリングァ語" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "イロコ語" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "インターリングァ(国際補助語協会)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "インド語(その他)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "インドネシア語" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "インド-ヨーロッパ語(その他)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "イングーシ語" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "イヌピアト語" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "イラン語(その他)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "イロコイ語" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "イタリア語" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "ジャワ語" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "ロジパン語" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "日本語" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "ユダヤ系ペルシア語" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "ユダヤ系アラビア語" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "カラカルパク語" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "カバイル語" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "カチン語" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "グリーンランド語" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "カンバ語" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "カナラ語" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "カレン語" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "カシミール語" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "カヌリ語" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "カウィ語" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "カザフ語" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "カバルダ語" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "カーシ語" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "コイサン語(その他)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "クメール語" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "コータン語" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "キクーユ語" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "キニヤルワンダ語" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "キルギス語" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "キンブンドゥー語" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "コンカニ語" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "コミ語" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "コンゴ語" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "韓国語" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "コスラエ語" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "クペル語" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "カラチャイバイカル語" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "クルー語" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "クルク語" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "クアニャマ語" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "クミク語" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "クルド語" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "クテナイ語" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ラディノ語" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "ラーンダ語" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "ランバ語" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "ラオ語" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "ラテン語" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "ラトビア語" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "レズギン語" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "リグリア語" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "リンガラ語" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "リトアニア語" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "モンゴ語" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "ロージー語" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "ルクセンブルク語" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "ルバ・ルルア語" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "ルバ・カタンガ語" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ガンダ語" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "ルイセーニョ語" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "ルンダ語" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "ルオ語(ケニアおよびタンザニア)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "ルシャイ語" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "マケドニア語" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "マドゥラ語" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "マガヒ語" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "マーシャル語" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "マイティリー語" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "マカッサル語" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "マラヤーラム語" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "マンディンゴ語" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "マオリ語" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "アウストロネシア語(その他)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "マラーティー語" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "マサイ語" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "マレー語" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "モクシャ語" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "マンダル語" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "メンデ語" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "中期アイルランド語(900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "ミックマック語" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "ミナンカバウ語" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "その他の言語" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "モン・クメール語(その他)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "マダガスカル語" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "マルタ語" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "満州語" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "マニプリ語" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "マノボ語" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "モホーク語" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "モルダヴィア語" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "モンゴル語" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "モシ語" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "複数言語" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "ムンダ語" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "クリーク語" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "ミランダ語" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "マールワーリー語" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "マヤ語" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "アルジア語" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "ナワトル語" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "北米インディアン語" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "ナポリ語" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "ナヴァホ語" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "南ヌデベレ語" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "北ヌデベレ語" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ンドンガ語" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "低地ドイツ語" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "ネパール語" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "ネワール語" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "ニアス語" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "ニジェール-コルフドファン語(その他)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "ニウエ語" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "ノルウェー・ニーノシュク語" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "ノルウェー・ブークモール語" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "ノガイ語" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "古代スカンディナヴィア語" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "ノルウェー語" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "北ソト語" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "ヌバ語" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "古典ネワール語" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "チェワ語" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "ムエジ語" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "ニャンコーレ語" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "ニョロ語" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "ンジマ語" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "プロヴァンス語(1500年以降)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "オジブウェー語" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "オリヤー語" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "オロモ語" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "オーセージ語" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "オセット語" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "オスマントルコ語(1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "オトミ語" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "パプア語(その他)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "パンガシナン語" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "パフレヴィ語" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "パンパンガ語" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "パンジャブ語" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "パピアメント語" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "パラウ諸島語" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "古ペルシア語(ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "ペルシア語" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "フィリピン語(その他)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "フェニキア語" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "パーリ語" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "ポーランド語" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "ポナペ語" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "ポルトガル語" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "プラークリット諸語" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "古期プロヴァンス語" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "プシュトゥー語" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "ケチュア語" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "ラージャスタニ語" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "ラパヌイ語" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "ラロトンガ語" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "ロマンス語(その他)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "レトロマン語" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "ジプシー語" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "ルーマニア語" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "ルンディ語" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "ロシア語" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "サンダウェ語" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "サンゴ語" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "ヤクート語" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "南アメリカインディアン語(その他)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "サリシュ語" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "サマリアアラム語" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "サンスクリット語" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "ササク語" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "サンターリー語" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "セルビア語" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "シシリア語" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "スコットランド語" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "クロアティア語" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "セルカーク語" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "セム語(その他)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "古代ケルト語(-900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "手話言語" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "シャン語" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "シダモ語" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "シンハラ語" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "スー語" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "シナ-チベット語(その他)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "スラヴ語(その他)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "スロバキア語" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "スロベニア語" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "南サーミ語" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "北サーミ語" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "サーミ諸語(その他)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "ルレオサーミ語" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "イナリサーミ語" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "サモア語" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "スコルトサーミ語" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "ショナ語" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "シンド語" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "ソニンケ語" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "ソグディアナ語" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "ソマリ語" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "ソンガイ語" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "南ソト語" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "スペイン語" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "サルデーニャ語" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "セレル語" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "ナイル-サハラ語(その他)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "スワート語" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "スクマ語" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "スンダ語" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "スス語" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "シュメール語" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "スワヒリ語" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "スウェーデン語" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "シリア語" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "タヒチ語" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "タイ語(その他)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "タミル語" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "タタール語" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "テルグ語" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "テムネ語" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "テレナ語" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "テトゥン語" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "タジク語" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "タガログ語" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "タイ語" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "チベット語" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "ティグレ語" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "ティグリニャ語" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "ティヴ語" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "クリンゴン語" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "トリンギット語" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "タマシェク語" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "トンガ語(ニアサ)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "トンガ語(トンガ諸島)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "トークピジン語" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "チムシアン語" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "ツワナ語" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "ツォンガ語" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "トルクメン語" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "トゥンブカ語" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "トゥピー語族" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "トルコ語" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "アルタイ語(その他)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "トウィ語" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "トゥヴァ語" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "ウドムルト語" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "ウガリット語" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "ウイグル語" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "ウクライナ語" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "ムブンドウ語" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "未確認" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "ウルドゥー語" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "ウズベク語" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "ヴァイ語" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "ヴェンダ語" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "ヴェトナム語" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "ヴォラピューク語" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "ヴォート語" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "ワカシ語族" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "ワッラモ語" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "ワライ語" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "ワショ語" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "ウェールズ語" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "ソルビア語族" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "ワロン語" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "オォロフ語" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "カルムイク語" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "コーサ語" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "ヤオ語" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "ヤップ語" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "イディッシュ語" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "ヨルバ語" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "ユピック語族" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "サポテク語" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "ゼナガ語" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "チワン語" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "ザンデ語" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "ズールー語" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "ズーニー語" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "以下の処理を実行する:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "無期限" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "有効期限 (期限切れ済み): %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "有効期限: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(無期限)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(期限切れ)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(24 時間以内に期限切れ)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(あと %d 日で期限切れ)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "不明" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "未対応" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Level 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Level 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Level 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "追加の顧客契約が必要" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "廃止され、別のパッケージに置き換えられました" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "無効" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "サポートのレベルが指定されていません" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "ベンダはサポートを提供していません。" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"問題の決定、それは互換性に関する情報やインストール支援、使用方法の対応や進行" +"中の保守、基本的なトラブルシューティングなどの技術サポートを指します。Level 1" +"サポートは、製品の欠陥によるエラーを修正しようとするものではありません。" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"問題の切り分け、それは顧客内での問題を共有し領域を切り分け、Level 1サポートで" +"は解決されていない問題について解決方法を提供する技術サポートを指します。" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"問題の解決、それは複雑な問題に対して技術者を従事させ、Level 2サポートで認識さ" +"れていない製品の欠陥を解決する技術サポートを指します。" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "サポートを得るには、追加の顧客契約が必要です。" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "パッケージは廃止され、別の名前の新しいパッケージに置き換えられました。" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "不明なサポートオプションです。説明は利用できません" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"システム管理はpid %d (%s)のアプリケーションによってロックされています。\n" +"再試行する前にこのアプリケーションを終了してください。" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "不明な該当モード「%s」" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "該当モード「%s」がパターン「%s」に対して不明です" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "正規表現 '%s' が正しくありません。regcompは %d を返しました" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "正規表現 '%s' が正しくありません" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "'%s' にアクセスするにはユーザ認証が必要です" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "再試行しています..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "%1% 回再試行したので中止しています。" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"SUSE カスタマーセンターを開いて、お使いの登録が有効であること、および期限切れ" +"になっていないことをご確認ください。" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Novellカスタマーセンターへアクセスし、登録が有効であるか、有効期限切れになっ" +"ていないかを確認してください。" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"接続点の作成: 接続点を作成するための書き込み可能なディレクトリが見つかりませ" +"ん" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "最初にパッケージ「lsof」をインストールしてください。" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "メタデータのキャッシュディレクトリを作成できません。" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "'%s' から読み取り時にエラーが発生しました" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "%s を作成できません" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "指定した URL には正しいメタデータがありません" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "リポジトリのキャッシュ作成に失敗しました ( repo2solv を開始できませんでした )" +" 。" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "リポジトリ (%d) のキャッシュに失敗しました。" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "リポジトリ '%s' のキャッシュを構築しています" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "%s にキャッシュを作成できません - 書き込み許可がありません。" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "%1% リポジトリのキャッシュ作成に失敗しました" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "未処理のリポジトリタイプ" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "リポジトリ '%s' を追加しています" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "'%s' にあるリポジトリのファイル名が正しくありません" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "ファイル '%s' を書き込み用に開くことができません。" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "'%s' からの読み取り時に不明なエラーが発生しました" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" +"リポジトリのディレクトリ '%1%' を読み込むことができません: 許可がありません" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "ディレクトリ '%s' の読み込みに失敗しました" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" +"リポジトリのファイル '%1%' を読み込むことができません: 許可がありません" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "メタデータを清掃しています" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "パッケージを清掃しています" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "キャッシュディレクトリを清掃しています" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "ディレクトリを清掃しています: %1%" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "キャッシュを清掃しています" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "キャッシュから読み込んでいます" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "リポジトリ '%s' を削除しています" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "リポジトリがどこに保存されたのかがわかりません。" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "'%s' を削除することができません" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "リポジトリを修正しています" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "リポジトリを更新しています: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "サービスの保管場所がわかりません。" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"不明なサービス '%1%' です: 孤立したサービスリポジトリ '%2%' を削除しています" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "リポジトリの別名をドットから始めることはできません。" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "サービスの別名をドットから始めることはできません。" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "ファイル %s のダイジェストはありません。" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "ファイル %s の不明なダイジェスト %s 。" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "ファイル '%s' のダイジェストの検証に失敗しました" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "ファイル '%s' は署名されていません。続行しますか?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "リポジトリ '%s' のファイル '%s' は署名されていません。続行しますか?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "キーを拒否しますか?一時的に信頼しますか?それとも常に信頼しますか?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "キーの名前: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +"リポジトリ \"%2%\" から %1% の新しいパッケージ署名キーを受け取りました:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "ファイル '%1%' の署名の検証に失敗しました。" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "リポジトリ '%2%' からのファイル '%1%' の署名の検証に失敗しました。" + +# internal key used: Ok +# internal key used: Ok +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "続行しますか?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "ファイル '%s' は不明なキー '%s' で署名されています。続行しますか?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"リポジトリ '%s' のファイル '%s' は不明なキー '%s' で署名されています。続行し" +"ますか?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "リポジトリ %1% は 'gpgkey=' で追加の URL を指定していません。" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "リポジトリ %2% 内で gpg キー ID %1% を検索しています。" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "キャッシュ %2% 内で gpg キー ID %1% を検索しています。" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "必要な属性 '%s' がありません。" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "'%s' または '%s' (もしくはその両方)の属性が必要です。" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "署名の検証に失敗しました" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "パッケージ %s は転送中に壊れてしまったようです。もう一度取得しますか?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "パッケージ %s の提供に失敗しました。取得を再試行しますか?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpmのチェックに失敗しました。" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpmが失敗しました。" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "サービスプラグインは属性の変更をサポートしていません。" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "ファイル '%s' をリポジトリ '%s' から提供することができません" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "リポジトリにURLが設定されていません。" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"必要なメディア %1%/%2% は '%3%' と記されているメディアで、下記のような内容が" +"含まれています:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"パッケージ %2% からの\n" +" ファイル %1% が、\n" +" パッケージ %3% からの\n" +" ファイルと\n" +" 競合しています" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"パッケージ %2% からの\n" +" ファイル %1% が、\n" +" %3% のインストールによる\n" +" ファイルと\n" +" 競合しています" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"%2% の\n" +" インストールによる\n" +" ファイル %1% が、パッケージ\n" +" %3% からのファイルと\n" +" 競合しています" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"%2% の\n" +" インストールによる\n" +" ファイル %1% が、\n" +" %3% のインストールによる\n" +" ファイルと競合しています" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"パッケージ %2% \n" +" からの\n" +" ファイル %1% が、\n" +"パッケージ %4% \n" +" からの\n" +"ファイル %3% と\n" +"競合しています" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"パッケージ %2% \n" +" からの\n" +" ファイル %1% が、\n" +" %4% のインストールによる\n" +" ファイル %3% と\n" +" 競合\n" +" しています" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"%2% の\n" +" インストールによる\n" +" ファイル %1% が、\n" +" パッケージ %4% \n" +" からのファイル %3%\n" +" と競合\n" +" しています" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"%2% の\n" +" インストールによる\n" +" ファイル %1% が、\n" +" %4% のインストール\n" +" による\n" +" ファイル %3%\n" +" と競合しています" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "sat-poolを作成できません。" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "いくつかの依存関係を無視することによって %s を壊します" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "いくつかの依存関係をおおよそ無視する" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"インストール済みの %1% は distupgrade リポジトリに属しておらず、置き換えなけ" +"ればならないものです" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "これからインストールする %1% は distupgrade リポジトリに属していません" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "インストール済みの %1% は下位のアーキテクチャに属しています" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "これからインストールする %1% は下位のアーキテクチャに属しています" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "インストール済みの %1% に問題があります" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "要求が矛盾しています" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "何らかの依存関係の問題" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "要求された '%1%' を提供するものがありません" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "必要なリポジトリを全て有効化していますか?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "要求されたパッケージ %1% は存在していません" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "サポートされていない要求" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' はシステム側で提供されているものであり、消去できません" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% はインストールできません" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" +"インストール済みの %2% によって必要とされている '%1%' を提供するものがありま" +"せん" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" +"これからインストールする %2% によって必要とされている '%1%' を提供するものが" +"ありません" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "%1% と %2% を同時にインストールすることはできません" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"インストール済みの %1% は、インストール済みの %3% によって提供される '%2%' と" +"矛盾します" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"インストール済みの %1% は、これからインストールする %3% によって提供される " +"'%2%' と矛盾します" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"これからインストールする %1% は、インストール済みの %3% によって提供される " +"'%2%' と矛盾します" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"これからインストールする %1% は、これからインストールする %3% によって提供さ" +"れる '%2%' と矛盾します" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"インストール済みの %1% は、インストール済みの %3% によって提供される '%2%' を" +"廃止します" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"インストール済みの %1% は、インストール済みの %3% によって提供される '%2%' を" +"廃止します" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"これからインストールする %1% は、インストール済みの %3% によって提供される " +"'%2%' を廃止します" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"これからインストールする %1% は、これからインストールする %2% によって提供さ" +"れる '%2%' を廃止します" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "インストール済みの %1% は、それ自身が提供する '%2%' と矛盾します" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "これからインストールする %1% は、それ自身が提供する '%2%' と矛盾します" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"インストール済みの %1% は '%2%' を必要としていますが、この要件を満たすものが" +"ありません" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"これからインストールする %1% は '%2%' を必要としていますが、この要件を満たす" +"ものがありません" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "削除したプロバイダ: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"インストール不可能なプロバイダ: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "インストール不可能なプロバイダ: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% は未だ %2% に完全統合されていません。" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"PTF をそのまま維持し、メンテナンスパッチをインストールしないように選択するの" +"が一般的です。" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"この状況下において、インストールされている %1% を削除すると、その中に含まれて" +"いる PTF パッケージも削除 (置換ではありません!) することになります。" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"PTF を削除したい場合は、 '%1%' を実行してください。このコマンドを実行すること" +"により、 PTF パッケージを削除せずに更新できます。" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "PTF はそのまま維持するか、処理をキャンセルするのが一般的です。" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "インストール済みの %1% が処理をブロックしています。" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "PTF をそのまま維持し、この処理をキャンセルするのが一般的です。" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "%1% を削除できるようにするには、ロックを解除してください" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "%1% をインストールしません" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "%1% を維持します" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "%1% をインストールできるようにするには、ロックを解除してください" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "この要求はシステムを壊してしまいます!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "システムが破壊される警告を無視する" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "%1% を提供する解決方法のインストールについて確認を行いません" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "%1% を提供する全ての解決方法の削除について確認を行いません" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "%1% の最新バージョンをインストールしません" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "下位のアーキテクチャですが、 %1% を維持します" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "下位のアーキテクチャですが、 %1% を維持します" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "古い %1% を維持します" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "除外されたリポジトリから %1% をインストールします" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "撤回済みの %1% をインストールする" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "PTF %1% のインストールを許可する" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "ブラックリスト設定されている %1% をインストールする" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "%1% を %2% にダウングレードします" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "%1% のアーキテクチャを %2% に変更します" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"%1% をインストールします (ベンダの変更を伴います)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"ベンダ %4% からの %3% を\n" +" ベンダ %2% からの %1% に置き換えてインストールします" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "%1% を %2% で置き換えます" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "%1% をアンインストールします" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "処理後スクリプトを実行しています" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "%1% スクリプトを実行しています" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "%1% スクリプトの出力:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "指示通りにインストールが中止されました。" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " 実行済み" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " 実行失敗" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s は %s として実行済みです)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " 中止しているため実行をスキップ" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "更新メッセージ通知の送信時にエラーが発生しました。" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "新しい更新メッセージ" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"シグナル \"%1% (%2%)\" を受信しましたが、システムの一貫性が確保できなくなるた" +"め、現在実行中の RPM トランザクションはキャンセルできません。" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "下記の問題が発生したことによって処理が失敗しました:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPMの失敗: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "公開鍵をファイル %1% からインポートすることができませんでした" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "公開鍵 %1% を削除することができませんでした" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "パッケージヘッダに署名がありません!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "パッケージペイロードに署名がありません!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s 向けに変更された設定ファイル:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpmは %s を %s として保存しましたが、差異を判別できませんでした" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpmは %s を %s として保存しました。\n" +"以下は差異のある最初の25行です。\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpmは %s を %s として作成しましたが、差異を判別できませんでした" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpmは %s を %s として作成しました。\n" +"以下は差異のある最初の25行です。\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "追加のrpm出力" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "バックアップ %s が作成されました" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "署名に問題はありません" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "不明な種類の署名です" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "署名は正しくありません" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "署名に問題はありませんが、キーを信頼していません" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "署名の公開鍵がありません" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "ファイルが存在しないか、署名を確認できません" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "ファイルに署名がありません" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" +"%2$u バイトのチェックサム '%3$s' は '%1$s' と思われますが、疑わしいタイプです" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "擬似端末(%s)を開くことができません。" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "パイプ(%s)を開くことができません。" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "無効なLDAP URLのクエリ文字列" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "無効なLDAP URLクエリパラメータ '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "URLオブジェクトを複製できません" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "無効な空のURLオブジェクト参照" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "URLコンポーネントを解析できません" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "履歴:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "URLスキームでは %s を許可していません" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "無効な %s コンポーネント '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "無効な %s コンポーネント" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "このURLに対して、クエリ文字列解析はサポートされていません" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URLスキームは必須のコンポーネントです" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "無効なURLスキーム '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "URLスキームではユーザ名を指定することは許されていません" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "URLスキームではパスワードを指定することは許されていません" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "URLスキームにはホスト部分が必要です" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "URLスキームではホスト部分を指定することは許されていません" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "無効なホスト部分 '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "URLスキームではポートの指定は許されていません" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "無効なポート部分 '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "URLスキームにはパス名が必要です" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "権限部分が存在する場合相対パスは許可されません" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "エンコードされた文字列にNULLバイトがあります" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "無効なパラメータ配列区切り文字" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "無効なパラメータマップ区切り文字" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "無効なパラメータ配列結合文字" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "コマンドは状態 %d で終了しました。" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "コマンドはシグナル %d (%s)で終了しました。" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "コマンドは不明なエラーで終了しました。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "正しくない実行パラメータが指定されました。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "制御パイプを作成できませんでした。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "'%s' (%s)にchrootすることができません。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "ディレクトリを '%s' (%s)に変更できません。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" +"chroot '%s' (%s)の実行中にディレクトリを '%s' に変更することはできません。" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "'%s' (%s)を実行することができません。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "fork (%s)することができません。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "'%s' を実行できません。 chdir が失敗しました (%s) 。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "'%s' を実行できません。 chroot が失敗しました (%s) 。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "'%s' を実行できません。 exec が失敗しました (%s) 。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "'%s' を実行できません。予期しないエラーです。" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "%s を %s にマウントできませんでした" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "%s をアンマウントできませんでした" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "不正なファイル名:%s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "アクション '%s' を実行しようとした際にメディアが開きませんでした。" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "ファイル「%s」がメディア「%s」に見つかりません" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "ファイル「%s」を書き込めません。" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "メディアが接続されていません" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "不正なメディアの接続点" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "「%s」のダウンロード(curl)準備が失敗しました" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "システム例外 '%s' がメディア '%s' で発生しました。" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "パス「%s」(メディア「%s」上)がファイルではありません。" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "パス「%s」(メディア「%s」上)はディレクトリではありません。" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "不正な形式のURI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "URIのホスト名が空です" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "URIのファイルシステムが空です" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "URIの宛先が空です" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "「%s」のURIスキーマがサポートされていません。" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "メディアでサポートされていない操作です" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"「%s」のダウンロード(curl)エラー:\n" +"エラーコード:%s\n" +"エラーメッセージ:%s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "「%s」のダウンロード(curl)オプションの設定中にエラーが発生しました:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "メディアソース「%s」に目的のメディアが含まれていません" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "メディア「%s」は別のインスタンスによって使用されています" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "メディアを取り出せません" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "メディア「%s」を取り出せません" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "'%s' へのアクセスが拒否されました。" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "'%s' にアクセスする際にタイムアウトになりました。" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"ダウンロードしたデータが期待するファイルサイズを超えています (期待するサイズ=" +"%s, 実際のサイズ=%s) 。" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "場所「%s」は一時的にアクセスできなくなっています。" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" SSL 証明書に問題があります。 '%s' について証明機関に問題がないかどうか確認し" +"てください。" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "メディアを接続するのに十分なリソースがありません。" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "未対応のHTTP認証方式 '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"'%s' のダウンロード (curl) でエラーが発生しました:\n" +"エラーコード: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"'%s' のダウンロード (curl) でエラーが発生しました:\n" +"HTTP レスポンスの取得ができませんでした\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "はい (y)" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "いいえ (n)" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "注意:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "警告:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "エラー:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "完了" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "注意" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "エラー" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "警告: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "取得しています:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "開始しています" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "見つかりません" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "このプロンプトに対するヘルプは用意されていません。" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "このオプションに対するヘルプは用意されていません" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "すべてのオプションを表示" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "はい" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "いいえ" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "%%posttrans スクリプト '%1%' を実行しています" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "%postrans スクリプトを実行しています" + +#~ msgid "Package is not signed!" +#~ msgstr "パッケージに署名がありません!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s はdistupgradeのリポジトリに属していません" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s は下位のアーキテクチャです" + +#~ msgid "problem with installed package %s" +#~ msgstr "インストール済みのパッケージ %s に問題が発生しました" + +#~ msgid "nothing provides requested %s" +#~ msgstr "要求した %s はどこからも提供されていません" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "すべての必要なリポジトリを有効化しましたか?" + +#~ msgid "package %s does not exist" +#~ msgstr "パッケージ %s は存在しません" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s はシステムが提供するもので、削除できません" + +#~ msgid "%s is not installable" +#~ msgstr "%s はインストールできません" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s (%s で必要)はどこからも提供されていません" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s と %s の両方をインストールすることはできません" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s は %s (%s から提供されている)と競合します" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s は %s (%s から提供されている)を古いものとして廃棄します" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "" +#~ "インストール済みの %s は、%s (%s から提供されている)を古いものとして廃棄し" +#~ "ます" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "解決方法 %s は自分自身で提供している %s と競合しています" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s は %s を必要としていますが、この要求を解決する方法がありません" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "%s の削除を許可するためにロックを削除する" + +#~ msgid "do not install %s" +#~ msgstr "%s をインストールしない" + +#~ msgid "keep %s" +#~ msgstr "%s を維持" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "%s のインストールを許可するためにロックを削除する" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "%s を提供する解決方法のインストールについて問い合わせない" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "%s を提供するすべての解決方法の削除について問い合わせない" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "%s の最新バージョンをインストールしない" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "下位のアーキテクチャである %s を維持する" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "下位のアーキテクチャである %s をインストールする" + +#~ msgid "keep obsolete %s" +#~ msgstr "古い %s を維持する" + +#~ msgid "install %s from excluded repository" +#~ msgstr "除外されたリポジトリから %s をインストールする" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "%s を %s にダウングレードする" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "アーキテクチャを %s から %s に変更する" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "%s をインストールする(ベンダを変更する)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "%s を %s で置き換える" + +#~ msgid "deinstallation of %s" +#~ msgstr "%s をアンインストールする" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "ロックファイルを開けません:%s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "この作業はすでに他のプログラムで実行されています。" + +#~ msgid "Hal Exception" +#~ msgstr "HAL例外" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "申し訳ありません。このバージョンのlibzyppはHALサポートなしで構築されていま" +#~ "す。" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContextが接続されていません" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDriveが準備されていません" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolumeが準備されていません" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "dbus接続を作成できません" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new:libhalコンテキストを作成できません" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection:dbus接続を設定できません" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "HALコンテキストを準備できません。haldが動作していない可能性があります。" + +#~ msgid "Not a CDROM drive" +#~ msgstr "CD ROMドライブではありません" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "相互排他属性を準備できません" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "再帰相互排他的属性を設定できません" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "再帰相互排他属性を準備できません" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "mutexロックを取得できません" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "mutexロックを解除できません" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "公開鍵をファイル %s からインポートすることができませんでした:%s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "公開鍵 %s を削除することができませんでした:%s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "「%s」からイメージファイルをマウントする使用可能なループデバイスが見つかり" +#~ "ません" diff --git a/po/ka.po b/po/ka.po new file mode 100644 index 0000000..4765654 --- /dev/null +++ b/po/ka.po @@ -0,0 +1,5798 @@ +# Georgian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2005 SUSE Linux Products GmbH. +# +# Aiet Kolkhi , 2005. +# George Machitidze , 2009. +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2023-01-28 15:14+0000\n" +"Last-Translator: Temuri Doghonadze \n" +"Language-Team: Georgian \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=1; plural=0;\n" +"X-Generator: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "უცნობი ქვეყანა: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "კოდის გარეშე" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "ანდირა" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "არაბეთის გაერთიანებული ემირატები" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "ავღანეთი" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "ანტიგუა და ბარბუდა" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "ანგილა" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "ალბანია" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "სომხეთი" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "ნიდერლანდების ანტილის კუნძულები (NL)" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "ანგოლა" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "ანტარქტიკა" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "არგენტინა" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "ამერიკული სამოა" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "ავსტრია" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "ავსტრალია" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "არუბა" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "ალანდის კუნძულები" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "აზერბაიჯანი" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "ბოსნია და ჰერცოგოვინა" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "ბარბადოსი" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "ბანგლადეში" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "ბელგია" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "ბურკინა ფასო" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "ბულგარეთი" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "ბაჰრეინი" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "ბურუნდი" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "ბენინი" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "ბერმუდები" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "ბრუნეი" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "ბოლივია" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "ბრაზილია" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "ბაჰამის კუნძულები" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "ბუტანი" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "ბუვეტის კუნძული" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "ბოცვანა" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "ბელორუსეთი" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "ბელიზი" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "კანადა" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "ქოქოს (კეელინგ) კუნძულები" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "კონგო" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "ცენტრალური აფრიკის რესპუბლიკა" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "შვეიცარია" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "კოტ-დ’ივუარი" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "კუკის კუნძულები (ახალი ზელანდია)" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "ჩილე" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "კამერუნი" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "ჩინეთი" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "კოლუმბია" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "კოსტა რიკა" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "კუბა" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "კაბო ვერდე" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "შობის კუნძული" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "კვიპროსი" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "ჩეხეთი" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "გერმანია" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "ჯიბუტი" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "დანია" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "დომინიკა" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "დომენიკის რესპუბლიკა" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "ალჟირი" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "ეკვადორი" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "ესტონეთი" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "ეგვიპტე" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "დასავლეთ საჰარა" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "ერითრეა" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "ესპანეთი" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "ეთიოპია" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "ფინეთი" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "ფიჯი" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "ფოლკლენდის კუნძულები" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "მიკრონეზიის ფედერალური შტატები" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "ფარერის კუნძულები" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "საფრანგეთი" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "გაბონი" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "დიდი ბრიტანეთი" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "გრენადა" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "საქართველო" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "ფრანგული გვიანა" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "გერნსი" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "განა" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "გიბრალტარი" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "გრენლანდია" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "გამბია" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "გვინეა" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "გვადალუპე" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "ეკვატორული გვინეა" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "საბერძნეთი" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "სამხრეთ ჯორჯია და სამხრეთ სენდვიჩის კუნძულები" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "გვატემალა" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "გუამი" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "გვინეა-ბისაუ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "გაიანა" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "ჰონგკონგი" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "ჰონდურასი" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "ხორვატია" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "ჰაიტი" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "უნგრეთი" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "ინდონეზია" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "ირლანდია" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "ისრაელი" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "მენის კუნძული" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "ინდოეთი" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "ბრიტანეთის ინდოეთის ოკეანის ტერიტორია" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "ერაყო" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "ირანი" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "ისლანდია" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "იტალია" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "ჯერსი" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "იამაიკა" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "იორდანია" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "იაპონია" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "კენია" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "ყირგიზეთი" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "კამბოჯა" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "კირიბატი" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "კომორი" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "სენტ კიტსი და ნევისი" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "ჩრდილოეთ კორეა" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "სამხრეთ კორეა" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "ქუვეიტი" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "კაიმანის კუნძულები" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "ყაზახეთი" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "ლაოსის სახალხო დემოკრატიული რესპუბლიკა" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "ლიბანი" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "წმინდა ლუჩია" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "ლიჰტენშტაინი" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "შრი ლანკა" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "ლიბერია" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "ლესოტო" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "ლიეტუვა" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "ლუქსემბურგი" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "ლატვია" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "ლიბია" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "მაროკო" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "მონაკო" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "მოლდოვა" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "მონტენეგრო" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "სენტ მარტინი" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "მადაგასკარი" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "მარშალის კუნძულები" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "მაკედონია" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "მალი" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "მიანმარი" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "მონღოლეთი" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "მაკაო" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "ჩრდილოეთ მარიანას კუნძულები" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "მარტინიკა" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "მავრიტანია" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "მონტსერატი" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "მალტა" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "მავრიკი" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "მალდივები" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "მალავი" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "მექსიკა" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "მალაიზია" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "მოზამბიკი" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "ნამიბია" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "ახალი კალედონია" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "ნიგერი" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "ნორფოლკის კუნძული" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "ნიგერია" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "ნიკარაგუა" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "ჰოლანდია" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "ნორვეგია" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "ნეპალი" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "ნაურუ" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "ნიუე" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "ახალი ზელანდია" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "ომანი" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "პანამა" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "პერუ" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "ფრანგული პოლინეზია" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "პაპუა ახალი გვინეა" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "ფილიპინები" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "პაკისტანი" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "პოლონეთი" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "წმინდა პიერი და მიქელონი" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "პიტკერნი" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "პუერტო რიკო" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "პალესტინის ტერიტორია" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "პორტუგალია" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "პალაუ" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "პარაგვაი" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "ყატარი" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "რეიუნიონი" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "რუმინეთი" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "სერბეთი" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "რუსეთის ფედერაცია" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "რუანდა" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "საუდის არაბეთი" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "სოლომონის კუნძულები" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "სეიშელები" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "სუდანი" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "შვედეთი" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "სინგაპური" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "წმინდა ელენე" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "სლოვენია" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "სვალბარდი და ან-მაიენი" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "სლოვაკეთი" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "სიერა ლეონე" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "სან მარინო" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "სენეგალი" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "სომალი" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "სურინამი" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "საო ტომე და პრინციპე" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "ელ სალვადორი" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "სირია" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "ესვატინი" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "ტერქსისა და კაიკოსის კუნძულები" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "ჩადი" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "ფრანგული სამხრეთ ტერიტორიები" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "ტოგო" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "ტაილანდი" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "ტაჯიკეთი" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "ტოკელაუ" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "თურქმენეთი" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ტუნისი" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "ტონგა" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "აღმოსავლეთ ტიმორი" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "თურქეთი" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ტრინიდადი და ტობაგო" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "ტუვალუ" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "ტაივანი" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "ტანზანია" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "უკრაინა" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "უგანდა" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "შეერთებული შტატების მცირე გარემდებარე კუნძულები" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "ამერიკის შეერთებული შტატები" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "ურუგვაი" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "უზბეკეთი" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "წმიდა საყდართან (ვატიკანის ქალაქი სახელმწიფო)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "სენტ ვინცენტი და გრენადინები" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "ვენესუელა" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "ბრიტანეთის ვირჯინიის კუნძულები" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "ვირჯინიის კუნძულები, აშშ." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "ვიეტნამი" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "ვანუატუ" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "ვალისი და ფუტუნა" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "სამოა" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "იემენი" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "მეიოტი" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "სამხრეთ აფრიკა" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "ზამბია" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "ზიმბაბვე" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "მომწოდებლები" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "ესაჭიროება" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "კონფლიქტები" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "მოძველებული" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "გასაღების შემოტანის შეცდომა." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "გასაღების წაშლის შეცდომა." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "უცნობი ენა: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "აფარი" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "აბხაზური" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "ადიღეური" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "აფრიკაანსი" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "აკანი" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "ალბანური" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "ამჰარული" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "ინგლუსური, ძველი (დაახლ. 450-1000)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "აპაჩის ენები" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "არაბული" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "არამეული" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "არაგონური" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "სომხური" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "ხელოვნური (სხვა)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "ასამური" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "ასთურიანული" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "ავსტრალიური ენები" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "ავესტანი" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "აიმარა" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "აზერბაიჯანული" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "ბაშკირი" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "ბალინური" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "ბასკური" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "ბალტიური (სხვა)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "ბეჟა" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "ბელორუსული" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "ბემბა" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "ბენგალური" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "ბიჰარი" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "ბისლამა" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "ბოსნიური" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "ბრეტონული" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "ბუგინური" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "ბულგარული" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "ბირმული" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "კატალანური" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "ჩამორო" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "ჩეჩნური" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "ჩინური" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "მარული" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "ჩეროკი" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "ეკლესიის სლავური" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "ჩუვაშური" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "შეიენი" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "კოპტური" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "კორნიშური" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "კორსიკული" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "ყირიმელი თათრული" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "კაშუბური" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "ჩეხური" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "დანიური" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "დელავერი" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "დივეხი" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "ქვედა სორბული" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "ჰოლანდიური" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "ძონგკხა" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "ინგლისური" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "ინგლისური, შუასაუკუნეების (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "ესპერანტო" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "ესტონური" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "ფაროული" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "ფიჯიური" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "ფილიპინები" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "ფინური" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "ფრანგული" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "ფრისული" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "ფრიულური" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "გა" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "ქართული" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "გერმანული" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "გელური" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "ირლანდიური" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "გალური" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "მენცი" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "გორონტალო" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "გოთური" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "გუარანი" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "გუჯარათული" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "ჰაუსა" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "ჰავაიური" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "ივრითი" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "ჰერერო" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "ინდური" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "ჰირი მოგუ" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "ზედა სორბიული" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "უნგრული" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "იგბო" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "ისლანდიური" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "იდო" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "ინუკტიტუტი" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "ოქსიდენტური" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "ინდონეზიური" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "ინუპიატი" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "ირანული (სხვა)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "იტალიური" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "იავური" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "იაპონური" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "ქაბილი" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "კაჩინი" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "კალაალისუტი" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "კანნადა" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "კაშმირი" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "ყაზახური" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "კხმერული" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "კიკუიუ" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "კენიარუანდა" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "ყირგიზული" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "კომი" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "კონგო" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "კორეული" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "ქურთული" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "ლაოსური" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "ლათინური" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "ლატვიური" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "ლიმბურგანული" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "ლინგალა" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "ლიტვური" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "ლუმბურგული" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "მაკედონური" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "მარშალური" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "მაითხილი" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "მალაიამი" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "მაორი" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "მარათი" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "მალაიური" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "მანდი" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "მალაგასი" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "მალტური" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "მოლდავური" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "მონღოლური" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "მუნდას ენები" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "ნეაპოლიტური" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "ნავაიო" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "სამხრეთ ნდებელე" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "ჩრდილო ნდებელური" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ნდონგა" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "ქვემოგერმანული" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "ნეპალური" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "ნორვეგიული ნიუნორსკი" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "ნორვეგიული" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "სამხრეთ-სოზო" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "ჩიჩევა" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "ორია" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "ორომო" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "ოსური" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "პანგასინანი" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "პამპანგა" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "სპარსული" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "ფონეტიკური" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "პალი" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "პოლონური" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "პორტუგალიური" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "პუშტო" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "კეჩუა" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "რომაული" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "რუმინული" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "რუნდი" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "რუსული" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "სანგო" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "იაკუტიური" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "სანსკრიტი" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "სანტალი" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "სერბული" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "სიცილიური" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "ხორვატული" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "შანი" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "სინჰალა" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "სლოვაკური" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "სლოვენური" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "ჩრდილო-საამური" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "სამოური" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "შონა" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "სინდი" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "სომალი" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "სამხრეთ-სოზო" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "ესპანური" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "სარდინიული" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "სვატი" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "სუნდური" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "სუაჰილი" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "შვედური" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "სირიული" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "ტაიტური" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "თამილური" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "თათრული" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "ტელუგური" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "ტაჯიკური" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "ტაგალოგური" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "ტაილანდური" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "ტიბეტური" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "ტიგრინია" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "ცვანა" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "ტონგა" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "თურქმენული" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "თურქული" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "ტვი" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "უდმურტული" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "უგარათული" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "უიღური" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "უკრაინული" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "ურდუ" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "უზბეკური" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "ვაი" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "ვენდა" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "ვიეტნამური" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "უელსური" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "ვალუნი" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "ვოლოფი" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "კალმიკური" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "ხოსა" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "იაო" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "იდიში" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "იორუბა" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "ჟუანგი" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "ზულუ" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "მხარდაუჭერელი" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "დონე 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "დონე 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "დონე 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "არასწორი" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "მითითებულ ბმულებზე სწორი მეტამონაცემების პოვნა შეუძლებელია" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "რეპოს (%d) კეშირების შეცდომა." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "ფაილის ('%s') ჩასაწერად გახსნის შეცდომა." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "საქაღალდის ('%s') წაკთხვის შეცდომა" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "გავაგრძლო?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "ხელმოწერის გადამოწმების შეცდომა" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "ურთიერთგამომრიცხავი მოთხოვნები" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "დამოკიდებულების რამდენიმე პრობლემა" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "მხარდაუჭერელი მოთხოვნა" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr "" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "RPM-ის დამატებითი გამონატანი" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "ისტორია:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "დიახ" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "არა" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "გაფთხილება:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "შეცდომა:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "მიღება:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "გაშვება" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "ვერ ვიპოვე" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "დიახ" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "არა" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "لا يمكن إنشاء المفتاح العام %s من %s إلى ملف حلقة المفاتيح %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "حاول استيراد مفتاح غير موجود %s إلى حلقة مفاتيح %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "لا يمكن تغيير مجلد العمل '/' داخل استجذار (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "فشل تهيئة تحميل (Metalink curl) '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "تحميل (metalink curl) خطأ '%s':\n" +#~ "رمز الخطأ: %s\n" +#~ "رسالة الخطأ: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "توقف التحميل في %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "توقف التحميل بواسطة المستخدم" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "حدث خطأ أثناء إعداد خيارات التحميل (metalink curl) ل '%s':" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "صربيا ومونتنيجرو" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "خيار list غير معروف" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "تعذر حل التبعيات" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." diff --git a/po/km.po b/po/km.po new file mode 100644 index 0000000..c31f1c0 --- /dev/null +++ b/po/km.po @@ -0,0 +1,5434 @@ +# translation of zypp.km.po to Khmer +# Copyright (C) YEAR SuSE Linux Products GmbH, Nuernberg +# This file is distributed under the same license as the PACKAGE package. +# Eng Vannak , 2006. +# Khoem Sokhem , 2006, 2007, 2008, 2009, 2010. +# Auk Piseth , 2007, 2008, 2009. +# Seng Sutha, 2010. +msgid "" +msgstr "" +"Project-Id-Version: zypp.km\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2010-06-03 08:04+0700\n" +"Last-Translator: Khoem Sokhem \n" +"Language-Team: Khmer \n" +"Language: \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: KBabel 1.11.4\n" +"X-Language: km-KH\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "ប្រទេស​ដែល​មិន​ស្គាល់ ៖ " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "គ្មាន​កូដ" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "អង់ដូរ៉ា" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "អារ៉ាប់​រួម" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "អាហ្គានីស្ថាន" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "អង់ទីហ្គា និង​បារប៊ុយដា" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "អង់ហ្គីឡា" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "អាល់បានី" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "អារមេនី" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "ហូល្លង់ អង់ទីល" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "អង់ហ្គោឡា" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "អង់តាកទិក" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "អាហ្សង់ទីន" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "សាម៉ូអា ​អាមេរិក" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "អូទ្រីស" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "អូស្ត្រាលី" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "អារូបា" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "កោះ​អាឡង់" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "អាហ្ស៊ែរបែហ្សង់" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "បូស្ន៊ី និង​​ហឺហ្ស៊េហ្គោវីណា" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "បារបាដូស" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "បង់ក្លាដេស" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "ប៊ែលហ្ស៊ិក" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "ប៊ូរគីណាហ្វាសូ" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "ប៊ុលហ្គារី" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "បារ៉ែន" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "ប៊ូរុនឌី" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "បេណាំង" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "ប៊េរមូដា" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "ប៊្រុយណេ ដារូសាឡាម" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "បូលីវី" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "ប្រេស៊ីល" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "បាហាម៉ាស" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "ប៊ូតាន" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "កោះ​ប៊ូវ៉េត" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "បុតស្វាណា" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "បេឡារុស្ស" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "បេលីហ្ស" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "កាណាដា" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "កោះ Cocos (Keeling)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "កុងហ្គោ" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "សាធារណរដ្ឋ​អាហ្វ្រិក​កណ្ដាល" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "ស្វ៊ីស" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "កូឌីហ្វ័រ" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "កោះ​កូក" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "ឈីលី" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "កាមេរ៉ូន" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "ចិន" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "កូឡុំប៊ី" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "កូស្តារីកា" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "គុយបា" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "កាបវែរ" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "កោះ​គ្រីស្តម៉ាស" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "ស៊ីពរ៍" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "សាធារណ​រដ្ឋ​ឆេក" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "អាល្លឺម៉ង់" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "ហ្ស៊ីបូទី" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "ដាណឺម៉ាក" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "ដូមីនីកា" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "សាធារណរដ្ឋ​ដូមីនីកែន" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "អាល់ហ្សេរី" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "អេក្វាឌ័រ" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "អេស្តូនី" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "អេហ្ស៊ីប" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "សាហារ៉ា​ខាង​លិច" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "អេរីទ្រា" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "អេស៉្បាញ" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "អេត្យូពី" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "ហ្វាំងឡង់" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "ហ្វីហ្ស៊ី" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "កោះ​ហ្វ៉កឡង់ (ម៉ាល់វីណា)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "រដ្ឋ​សហព័ន្ធ​មីក្រូណេស៊ី" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "កោះ​ហ្វារ៉ូ" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "បារាំង" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "ប្រទេស​ចំណុះ​បារាំង" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "ហ្គាបុង" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "ចក្រ​ភព​អង់គ្លេស" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "ហ្គ្រីណាដា" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "ហ្សកហ្ស៊ី" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "ហ្គូអ៊ីយ៉ាណា បារាំង" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "ហ្គើនស៊ី" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "ហ្គាណា" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "ហ្គីប្រាល់តា" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "ហ្គ្រីនលែន" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "ហ្គាំប៊ី" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "ហ្គីណេ" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "ហ្គូអាដឺលូប៉េ" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "ហ្គីណេ​អេក្វាទ័រ" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "ក្រិក" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "កោះ​ហ្សកហ្ស៊ី​ខាងត្បូង និង​ស៊េនវិច​ខាងត្បូង" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "ហ្គាតេម៉ាឡា" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "ហ្គាម" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "ហ្គីណេប៊ីសៅ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "ហ្គីយ៉ាណា" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "ហុងកុង" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "កោះ​ហ៊ើដ និង​កោះ​ម៉ាកដូណាល់" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "ហុងឌូរ៉ាស់" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "ក្រូអាត" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "ហៃទី" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "ហុងគ្រី" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "ឥណ្ឌូនេស៊ី" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "អៀរឡង់" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "អ៊ីស្រាអែល" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isle of Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "ឥណ្ឌា" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "អាណាចក្រ​ចក្រភព​អង់គ្លេស​នៅ​មហាសមុទ្រ​ឥណ្ឌា" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "អ៊ីរ៉ាក់" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "អ៊ីរ៉ង់" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "អ៊ីស្លង់" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "អ៊ីតាលី" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "ឈឺស៊ី" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "ចា​ម៉ៃកា" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "ហ្ស៊កដង់" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "ជប៉ុន" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "កេនយ៉ា" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "គៀរហ្គីស្តង់" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "កម្ពុជា" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "គិរិបាទី" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "កុំម៉ូរ៉ូស" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "សង់ឃីត និង​នេវីស" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "កូរ៉េ​ខាង​ជើង" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "កូរ៉េ​ខាង​ត្បូង" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "គុយ​វ៉ែត" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "កោះ​កៃម៉ាន" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "កាហ្សាក់ស្តង់" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "សាធារណរដ្ឋ​ប្រជាធិបតេយ្យ​ប្រជាមានិត​ឡាវ" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "លីបង់" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "សង់លូស៊ីយ៉ា" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "លិចទេនស្តែន" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "ស្រីលង្កា" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "លីបេរីយ៉ា" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "ឡេសូតូ" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "លីទុយអានី" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "លុចហ្សំបួរ" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "ឡាតវីយ៉ា" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "លីប៊ី" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "ម៉ារ៉ុក" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "ម៉ូណាកូ" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "ម៉ុលដូវ៉ា" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "​ម៉ុងតេណេហ្ក្រូ" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "សាន់ម៉ាទីន" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "ម៉ាដាហ្គាស្ការ" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "កោះ​ម៉ាស្យល" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "ម៉ាសេដូនី" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "ម៉ាលី" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "ភូមា" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "ម៉ុងហ្គោលី" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "ម៉ាកាវ" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "កោះ​ម៉ារៀណា​ភាគ​ខាង​ជើង" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "ម៉ារទីនីគ" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "ម៉ូរីតានី" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "ម៉ុងសេរ៉ា" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "ម៉ាល់តា" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "ម៉ូរីទុស" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "ម៉ាល់ឌីវ" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "ម៉ាឡាវី" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "ម៉ិចស៊ិក" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "ម៉ាឡេស៊ី" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "ម៉ូហ្សាំប៊ិក" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "ណាមីប៊ី" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "ញូវ កាលេដូនី" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "នីហ្សេរ" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "កោះ​ណរហ្វក" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "នីហ្សេរីយ៉ា" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "នីការ៉ាហ្គ័រ" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "ហូល្លង់" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "ន័រវែស" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "នេប៉ាល់" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "ណូរុ" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "នីវ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "ញូវ​ហ្សេលែន" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "អូម៉ង់" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "ប៉ាណាម៉ា" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "ប៉េរូ" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "ប៉ូលីនេស៊ី​បារាំង" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "ប៉ាពូញូវហ្គីណេ" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "ហ្វីលីពីន" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "ប៉ាគីស្ថាន" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "ប៉ូឡូញ" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "សង់​ព្យែរ និង​មីគុយអេឡុង" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "ពីតខាយរិន" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "ព័រតូរីកូ" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "ប៉ាឡេស្ទីន" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "ព័រទុយហ្គាល់" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "ប៉ាឡូ" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "ប៉ារ៉ាហ្គាយ" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "កាតារ" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "រេអុយញ៉ុង" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "រ៉ូម៉ានី" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "សែប៊ី" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "សហព័ន្ធ​រុស្ស៊ី" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "រវ៉ាន់ដា" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "អារ៉ាប៊ីសាអ៊ូឌីត" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "កោះ​សូឡូម៉ូន" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "សីស្ហែល" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "ស៊ូដង់" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "ស៊ុយអែត" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "សឹង្ហ​បុរី" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "សង់​ហេឡេណា" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "ស្លូវ៉ានី" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "ស្វាល់បាត និង​ហ្សង់ម៉ាយេន" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "ស្លូវ៉ាគី" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "សេរ៉ាឡេអូន" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "សាន់ម៉ារីណូ" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "សេណេហ្គាល់" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "សូម៉ាលី" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "ស៊ូរីណាមី" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "សៅតូម និង​ព្រីនស៊ីព" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "អែលសាល់វ៉ាឌ័រ" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "ស៊ីរី" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "ស្វាហ្ស៊ីឡង់" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "កោះ​ទួក និង​កៃកូស" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "ឆាដ" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "អាណាចក្រ​ខាង​ត្បូង​របស់​ បារាំង" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "តូហ្គោ" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "ថៃ" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "តាហ្ស៊ីគីស្តង់" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "តូកេឡាអ៊ូ" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "ទួគមេនីស្តង់" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ទុយណេស៊ី" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "តុងហ្គា" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "ទីម័រ​ខាង​កើត" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "ទួរគី" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ទ្រីនីដាដ និង​តូបាហ្គោ" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "ទុយវ៉ាលុយ" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "តៃវ៉ាន់" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "តង់ហ្សានី" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "អ៊ុយក្រែន" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "អ៊ូហ្គង់ដា" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "កោះ​ឆ្ងាយៗ​របស់​សហរដ្ឋ​អាមេរិក" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "សហរដ្ឋអាមេរិក" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "អ៊ុយរ៉ាហ្គាយ" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "អ៊ូហ្សបេគីស្តង់" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "ហូលីស៊ី (រដ្ឋ​បូរី​វ៉ាទីកង់)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "សង់វាំងសង់ និង​ហ្គ្រីណាឌីន" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "វេណេហ៊្សុយអេឡា" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "កោះ​វឺជីន អង់គ្លេស" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "កោះ​វឺជីន អាមេរិក" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "វៀតណាម" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "វ៉ានុយអាទុយ" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "វ៉ាលីស និង​ហ៊្វូ​ទុយណា" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "សាម៉ូអា" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "យេមែន" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "ម៉ាយុត" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "អាហ្វ្រិក​ខាង​ត្បូង" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "ហ្សាំប៊ី" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "ហ្ស៊ីមបាវ៉េ" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "ផ្ដល់" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "ទាមទារ" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "ប៉ះទង្គិច" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "លែង​ប្រើ %s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "អនុសាសន៍" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "ស្នើ" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "ធ្វើ​ឲ្យ​ប្រសើរ​ឡើង" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "ការ​បន្ថែម" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, fuzzy, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "នាំចូល​សោ %s ដែល​មិនមាន​ទៅ​ក្នុង keyring %s" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "បរាជ័យក្នុង​ការ​នាំចូល​សោ​សាធារណៈ​ពី​ឯកសារ %1%" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "បរាជ័យ​ក្នុង​ការ​លុប​សោ ។" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "រក​មិនឃើញ​ឯកសារ​ហត្ថលេខា %s ទេ" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "មិន​ស្គាល់​ភាសា ៖ " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "អាហ្វារ" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "អាប់​ខាហ៊្សាន" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "អាឈិណិស" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "អាកូលី" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "អាដង់ម៉េ" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "អាដអ៊ីហ្គ៉េ" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "អាហ្រ៉ូ-អាស៊ីយ៉ាទិក (ផ្សេង​ទៀត)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "អាហ្វ្រីហ៊ីលី" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "អាហ្វ្រីកាអាន" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "អាយនុយ" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "អាខាន់" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "អាក់កាយ៉ង់" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "អាល់បានី" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "អាឡេអ៊ុយ" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "ភាសា​អាល់កុងហ្គូអ៊ីយ៉ាន" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "អាល់តាយខាង​ត្បូង" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "អាមហារី" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "អង់គ្លេស បុរាណ (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "ភាសា​អាប៉ាឆេ" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "អារ៉ាប់" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "អារ៉ាម៉ាអ៊ិក" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "អារ៉ាហ្គោន" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "​អារមេនី" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "អារ៉ាអ៊ុយកានីយ៉ាន" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "អារ៉ាប៉ាអូ" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "សិប្បនិម្មិត (ផ្សេង​ទៀត)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "អារ៉ាវ៉ាក់" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "អាសាមីស" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "អាស្តុយរីយ៉ុង" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "ភាសា​អាតាប៉ាសាន" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "ភាសា​អូស្ត្រាលី" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "អាវារីក" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "អាវែស្តង់" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "អាវ៉ាឌី" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "អីម៉ារ៉ា" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "អាហ្ស៊ែរបែហ្សង់" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "បង់ដា" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "ភាសា​បាមីឡេកេ" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "បាសគៀរ" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "បាលូឈិ" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "បាម្បារា" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "បាលីណីស" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "​​បាស្កេ" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "បាសា" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "បាល់ទិក (ផ្សេង​ទៀត)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "បេចា" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "បេឡារុស្ស" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "បេមបា" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "​បេន្កាលី" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "បឺបឺ (ផ្សេង​ទៀត)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "បូជូរី" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "បិហារ" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "ប៊ីកុល" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "ប៊ីនី" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "បីសឡាម៉ា" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "ស៊ិកស៊ីកា" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "បង់ទុយ (ផ្សេង​ទៀត)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "បូស្នី" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "ប្រា" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "ប្រេតុង" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "បាតាក់ (ឥណ្ឌូនេស៊ី)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "ប៊ុយរីអាត" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "ប៊ុយហ្គីណេសេ" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "​​ប៊ុលហ្ការី" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "ភូមា" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "ប្លាំង" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "កាដូ" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "ឥណ្ឌា​កណ្ដាល​បែប​អាមេរិក (ផ្សេង​ទៀត)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "ការីប" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "កាតាឡាន" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "កាអ៊ូកាស៊ីយ៉ាន (ផ្សេង​ទៀត)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "កេប៊ូអាណូ" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "សែលតិក (ផ្សេង​ទៀត)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "ចាមូរូ" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "ឈីបចា" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "ចេចេន" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "ឆាហ្គាតាអ៊ី" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "ចិន" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "ឈូកេសេ" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "ម៉ារី" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "ឈីណូ ចាកុង" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "ឆូកតា" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "ឈីប៉េអ៊ីយ៉ាន" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "ចេរ៉ូគី" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "ឆឺច​ស្លាវិច" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "ចូវ៉ាស" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "ឆេអ៊ីយ៉េណេ" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "ភាសា​កាម៊ិក" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "កុបទិក" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "កូនីស" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "កូសីកា" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "ក្រេអូឡេ និង​ភីដហ្គីន ដែល​ផ្អែក​លើ​ភាសា​អង់គ្លេស (ផ្សេង​ទៀត)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "ក្រេអូឡេ និង​ភីដហ្គីន ដែល​ផ្អែក​លើ​ភាសា​បារាំង (ផ្សេង​ទៀត)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "ក្រេអូឡេ និង​ភីដហ្គីន ដែល​ផ្អែក​លើ​ភាសា​ព័រទុយហ្គាល់ (ផ្សេង​ទៀត)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "គ្រី" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "គ្រីម៉េអាន តាតារ" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "ក្រេអូឡេ និង​ភីដហ្គីន (ផ្សេង​ទៀត)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "កាស៊ូប៊ីយ៉ាន" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "គុយស៊ិទិក" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "ឆេក" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "ដាកូតា" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "ដាណឺម៉ាក" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "ដាកវ៉ា" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "ដាយ៉ាក" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "ដេឡាវ៉ារ៉េ" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "ស្លាវ (អាតាប៉ាសាន)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "ដូហ្គ្រីប" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "ឌីនកា" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "ឌីវេហី" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "ដូហ្គ្រី" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "ដ្រាវីឌីយ៉ាន (ផ្សេង​ទៀត)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "សូរប៊ីយ៉ាន​ក្រោម" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "ឌុយអាឡា" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "ហុល្លង់ កណ្ដាល (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "ហុល្លង់" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ឌុយឡា" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "ដុងហ្កា" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "អេហ្វ៊ីក" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "អេស្ស៊ីប (បុរាណ)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "អេកាជុក" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "អេឡាម៊ិតេ" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "អង់គ្លេស" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "អង់គ្លេស កណ្ដាល (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "អេស្ពេរ៉ាន់តូ" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "​​អេស្តូនី" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "អូវឹ" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "អេវ៉ុងដូ" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "ហ្វ៉ង់" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "ហ្វាអេរូស" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "ហ្វ៉ង់ទី" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "ហ្វ៊ីហ្ស៊ី" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "ហ្វ៊ីលីពីន" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "​ហ្វាំង​ឡង់" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "ហ្វាំងណូ អ៊ុយហ្គ្រីយ៉ាន (ផ្សេង​ទៀត)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "ហ្វុង" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "បារាំង" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "បារាំង កណ្ដាល (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "បារាំង បុរាណ (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "ហ្វ្រីស៊ាន" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "ហ្វូឡា" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "ហ្វ្រីអ៊ុយលីយ៉ាន" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "ហ្កា" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "ហ្កាយ៉ូ" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "ហ្កាយ៉ា" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "ហ្គឺម៉ានិក (ផ្សេង​ទៀត)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "ហ្សកហ្ស៊ី" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "អាល្លឺម៉ង់" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "ហ្គី" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "ហ្គីលបឺតេសេ" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "ហ្គាអេលិក" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "អៀរឡង់" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "ហ្គាលីស្យាន" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "ម៉ុង" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "អាល្លឺម៉ង់ កណ្ដាល ខ្ពស់ (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "អាល្លឺម៉ង់ បុរាណ ខ្ពស់ (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "ហ្គុងឌី" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "ហ្គូរ៉ុងតាឡូ" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "ហ្គោធិក" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "ហ្គ្រេបូ" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "ក្រិក បុរាណ (ដល់ 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "ក្រិក ទំនើប (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "ហ្គូរ៉ានី" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "ហ្កុយ៉ារាទី" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "ហ្គីចអ៊ីន" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "អៃអ៊ីដា" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "ហៃទី" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "ហូសា" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "អាវ៉ាអ៊ីយ៉ាន" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "ហេប្រូ" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "ហេរេអូ" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "អ៊ីលីហ្គាអ៊ីណុង" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "អ៊ីម៉ាឆាលី" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "ហិណ្ឌូ" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "អ៊ីទីតេ" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "ម៉ុង" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "ហ៊ី​រី​ម៉ូទូ" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "អាប​ផើ សូ​បៀន" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "​​ហុងគ្រី" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "អ៊ុយប៉ា" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "អ៊ីបាន" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "អ៊ីកបូ" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "អ៊ីស្លង់" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "អ៊ីឌូ" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "ស៊ី​ចួនអ៊ី" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "អ៊ីចូ" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "អ៊ីនូកទីទូត" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "អ៊ីង​តឺ​លីងគឹ" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "អ៊ីឡូកូ" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (សមាគមន៍​ភាសា​ជំនួយ​អន្តរជាតិ)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "អ៊ីនឌិក (ផ្សេង​ទៀត)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "ឥណ្ឌូនេស៊ី" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "ឥណ្ឌូអឺរ៉ុប (ផ្សេង​ទៀត)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "អ៊ីងហ្គូស" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "អ៊ីងអ៊ិយពីយ៉ាក" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "អ៊ីរ៉ង់ (ផ្សេង​ទៀត)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "ភាសា​អ៊ីរ៉ូគុយអូអ៊ីយ៉ាន" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "អ៊ីតាលី" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "យ៉ាវា" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "ឡូបាន" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "ជប៉ុន" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "ជុយឌីអូ-ប៉ឺស៊ីយ៉ាន" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "ជុយឌីអូ-អារ៉ាប់" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "ការា-កាល់ប៉ាក់" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "កាប៊ី" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "កាឈីន" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "កាឡាលីសុទ" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "កាំបា" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "កិណាដា" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "ការ៉ែន" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "កាស្មៀរ" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "កានុរី" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "កាវី" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "កាហ្សាក់ស្តង់" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "កាបាឌីយ៉ាន" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "ខាស៊ី" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "ខូអ៊ីសាន (ផ្សេង​ទៀត)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "ខ្មែរ" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "ខូតាណេសេ" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "គីគូយូ" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "គីនយ៉ាវាន់ដា" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "គៀរ​ហ្គី​ស្តង់" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "គីមប៊ុនឌុយ" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "​​កុងកានី" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "កូមី" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "កុងហ្គោ" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "កូរ៉េ" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "កូស្រាអេយ៉ាន" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "ខេឡេ" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "ការាឆៃ-បាល់ការ" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "គ្រុយ" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "គុយរ៊ូខ" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "គ័ន​យ៉ាមា" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "គុយម៊ិក" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "ឃឺដ" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "គុយតេណាអ៊ី" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ឡាឌីណូ" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "ឡានដា" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "ឡាមបា" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "ឡាវ" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "ឡាតាំង" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "ឡាតវីយ៉ា" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "ឡេសហ្គីយ៉ាន" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "លីបួគ" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "លីនហ្កា​ឡា" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "លីទុយអានី" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "ម៉ុងហ្គោ" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "ឡូហ្ស៊ី" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "លុចហ្សំបួរ" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "លុយបា-លុយលូអា" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "លូបាកាតុងហ្កា" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ភាង​ហ្គង់​ដា" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "លុយអ៊ីសេណូ" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "លុងដា" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "លុយអូ (កេនយ៉ា និង​តង់ហ្សានី)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "លុយសាអ៊ី" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "ម៉ាសេដូនី" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "ម៉ាឌុយរ៉េសេ" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "ម៉ាហ្គាអ៊ិ" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "ម៉ា​ស្យលីស" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "ម៉ាអ៊ីទីលី" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "ម៉ាកាសារ" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "ម៉ាឡាយ៉ាឡាម" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "ម៉ង់ដាំងហ្គោ" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "ម៉ោរី" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "អូស្ត្រូណេស៊ី (ផ្សេង​ទៀត)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "​​ម៉ារាធី" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "ម៉ាសាអ៊ិ" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "ម៉ាឡេស៊ី" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "ម៉ុកសា" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "ម៉ង់ដារ" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "ម៉ិនដេ" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "អៀរឡង់ កណ្ដាល (៩០០-១២០០)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "ម៊ិកម៉ា" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "ម៊ីណង់កាបាអុយ" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "ភាសា​ផ្សេងៗ" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "ខ្មែរ​មន (ផ្សេងទៀត)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "ម៉ាឡាហ្គាស៊ី" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "ម៉ាល់តា" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "ម៉ង់ឈូ" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "ម៉ានីពូរី" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "ភាសា​ម៉ាណូបូ" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "ម៉ូហាក់" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "ម៉ុល​ដាវី" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "ម៉ុងហ្គោលី" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "ម៉ូស៊ី" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "ពហុភាសា" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "ភាសា​មុនដា" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "ក្រេក" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "មីរង់ដេសេ" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "ម៉ារ៉ារី" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "ភាសា​ម៉ាអ៊ីយ៉ាន" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "អេរីយ៉ា" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "ណាអ៊ុយ៉ាល់" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "ឥណ្ឌា​ខាង​ជើង បែប​អាមេរិក" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "ណេអាប៉ូលីតង់" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "ណាវាហ្សូ" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "នដិបិលិ (ខាង​ត្បូង)" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "នដិបិលិ (ខាង​ជើង)" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "នដុងហ្កា" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "អាល្លឺម៉ង់​ក្រោម" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "នេប៉ាល់" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "បាសា នេប៉ាល់" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "នីយ៉ាស" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "នីហ្ស៊េ - ខដូហ្វានីយ៉ាន" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "នីអ៊ុយេអាន" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "​ន័រវែស ​នីនូស​" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "ន័រវេស បុកម៉ាល់" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "ណូហ្គាអ៊ិ" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "ណូសេ បុរាណ" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "ន័រវែស" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "សូធូ​ខាង​ជើង" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "ភាសា​នុយប្យ៉ាន" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "នីវ៉ារី​បុរាណ" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "ឈិចិវា" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "នីអាម៉េហ្ស៊ី" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "នីអាណូឡេ" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "នីអូរ៉ូ" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "នីម៉ា" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "អុកស៊ីតង់ (ក្រោយ ១៥០០)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "អុហ្សីបវា" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "អូរីយ៉ា" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "អូរ៉ូម៉ូ​" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "អូសា" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "អូសសិត្យុង" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "ទួគី អូតូម៉ង់ (១៥០០-១៩២៨)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "ភាសា​អូតូមីយ៉ាន" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "ប៉ាពុយអាន (ផ្សេង​ទៀត)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "ប៉ង់ហ្គាស៊ីណង់" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "ប៉ាឡាវី" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "ប៉ាមប៉ង់ហ្គា" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "ប៉ង់ចាប៊ី" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "ប៉ាពីយ៉ាម៉ិនតូ" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "ប៉ាឡាអ៊ុយ៉ាន" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "ពឺស៊ាន បុរាណ (ca. ៦០០-៤០០ B.C)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "ពឺស៊ាន" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "ហ្វីលីពីន (ផ្សេង​ទៀត)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "ផូអេនីស្យ៉ាន" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "បាលី" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "​ប៉ូឡូញ" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "ប៉ូណេអ៊ីយ៉ាន" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "​ព័រទុយហ្គាល់" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "ភាសា​ប្រ៉ាក្រិត" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "ប្រ៉ូវ៉ែនកាល់ បុរាណ (ដល់ ១៥០០)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "ពុហ្សតូ" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "កេទ្ជូអា" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "រ៉ាចាសតានិ" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "រ៉ាប៉ានុយអ៊ិ" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "រ៉ារ៉ូតុងហ្គង់" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "រ៉ូម៉ាំង (ផ្សេង​ទៀត)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "រ៉ាអេតូ-រ៉ូម៉ាំង" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "រ៉ូម៉ានី" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "រូម៉ានី" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "រុន្ឌី" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "រុស្ស៊ី" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "រ៉ុងឌី" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "សង់ហ្គោ" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "យ៉ាខឺត" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "ឥណ្ឌា​ខាង​ត្បូង​បែប​អាមេរិក (ផ្សេង​ទៀត)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "ភាសា​សាលីសាន" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "សាម៉ារីតង់ អារ៉ាម៉ាអ៊ិក" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "​សំស្ក្រឹត" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "សាសាក់" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "សង់តាលី" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "សែប៊ី" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "ស៊ីស៊ីល្យ៉ាន" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "ស្កុតថ៍" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "​ក្រូអាត" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "សែលគូប" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "សេម៉ីទិក (ផ្សេង​ទៀត)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "អៀរឡង់ បុរាណ (ដល់ ៩០០)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "ភាសា​សញ្ញា" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "ហ្សាន" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "ស៊ិដាម៉ូ" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "ស៊ីនហាឡា​" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "ភាសា​ស៊ិអួន" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "ស៊ីណូ-ទីបេ (ផ្សេង​ទៀត)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "ស្លាវិក (ផ្សេង​ទៀត)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "ស្លូវ៉ាគី" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "​​​ស្លូវ៉ានី" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "សាម៉ី​ខាង​ត្បូង" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "សាម៉ីខាង​ជើង" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "ភាសា​សាម៉ី (ផ្សេង​ទៀត)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "ឡូលេ សាម៉ី" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "អ៊ិណារី សាម៉ី" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "សាមូអាន" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "ស្កូលថ៍ សាម៉ី" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "សូណា" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "​​ស៊ីន្តី" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "សូណាំងកេ" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "សូដ្យ៊ាន" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "សូម៉ាលី" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "សុងហ្គាយ" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "សូធូ​ខាង​ត្បូង" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "អេស្ប៉ាញ" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "សារឌីនង់" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "សេរឺ" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "នីឡូ-សាហារង់ (ផ្សេង​ទៀត)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "ស្វាទី" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "ស៊ូគុយម៉ា" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "សាន់ដាណេស" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "ស៊ូស៊ូ" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "ស៊ូមេរាន" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "ស្វាហ៊ីលី" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "ស៊ុយអែដ" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "ស៊ីរី" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "តាហិតង់" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "តាអ៊ិ (ផ្សេង​ទៀត)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "តាមីល" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "​​តាតារ" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "តេលូហ្គូ" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "ទីមណេ" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "តេរ៉េណូ" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "តេទូម" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "តាដហ្ស៊ីគីស្តង់" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "តាហ្គាឡូក" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "ថៃ" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "ទីបេ" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "ធីហ្គ្រី" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "ទី​គ្រីនយ៉ា" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "ទីវ" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "ខ្លីង​ហ្កន" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "លីងហ្គីត" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "តាម៉ាហ្សែក" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "តុងហ្គា (និយ៉ាសា)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "តុងហ្គា (កោះ​តុងហ្គា)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "ស៊ីមស្យ៊ាន" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "ស្វាណា" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "សុងហ្កា" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "ទួគមេនីស្តង់" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "ទុមប៊ុយកា" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "ភាសា​ទុយពិ" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "ទួរគី" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "អាល់តាអ៊ិក (ផ្សេង​ទៀត)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "ទ្វី" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "ទុយវីនៀន" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "អ៊ុដម៉ឺត" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "យូហ្គារីទីក" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "វីហ្គៀរ" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "​​​អ៊ុយក្រែន" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "អ៊ូមប៊ុនឌុយ" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "មិន​អាច​កំណត់" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "អ៊ូ​រ្ឌូ" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "អ៊ូហ្សបេគីស្តង់" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "វ៉ាយ" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "វង់ដា" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "វៀតណាម" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "វ៉ូឡាពូក" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "វ៉ូទិក" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "ភាសា​វ៉ាកាហ្សាន" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "វ៉ាឡាម៉ូ" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "វ៉ារ៉ាយ" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "វ៉ាសូ" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "វែល" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "ភាសា​សរប៊ាន" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "វ៉ាឡុង" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "វូឡុហ្វ" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "កាល់មីក" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "ឃសា" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "យ៉ាវ" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "យ៉ាប៉េសេ" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "យីឌីហ្ស" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "យរូបា" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "ភាសា​យូពិក" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "ហ្សាប៉ូតិក" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "ហ្ស៊េណាហ្គា" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "ចួង" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "ហ្សង់ដេ" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "ហ្ស៊ូលូ" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "ហ្ស៊ូនី" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "អំពើ​ខាងក្រោម​នឹង​ត្រូវបាន​ធ្វើ​រួច ៖" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "(មិន​ផុត​កំណត់)" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(មិន​ផុត​កំណត់)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(បាន​ផុត​កំណត់)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(ផុត​កំណត់​ក្នុង​រយៈពេល ២៤ ម៉ោង)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, fuzzy, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(ផុត​កំណត់​ក្នុង​រយៈពេល ២៤ ម៉ោង)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "មិន​ស្គាល់" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "មិន​បានគាំទ្រ" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "កម្រិត ១" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "កម្រិត ២" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "កម្រិត ៣" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "ចាំបាច់​កិច្ចសន្យា​អតិថិជន​បន្ថែម" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "មិន​ត្រឹមត្រូវ" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "កម្រិត​គាំទ្រ​មិន​ត្រូវ​បាន​បញ្ជាក់" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "ក្រុមហ៊ុន​លក់​មិន​បាន​ផ្ដល់​កា​រគាំទ្រ​ទេ ។" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"ការ​កំណត់​បញ្ហា ដែល​មាន​ន័យ​ថា​ការគាំទ្រ​ផ្នែក​បច្ចេកទេស​បាន​រចនា​ដើម្បី​ផ្ដល់​ព័ត៌មាន​​ដែល​ឆប​គ្នា ជំនួយ​ការ​" +"ដំឡើង ការ​ប្រើការ​គាំទ្រ និង​ការ​ថែទាំ​ដែល​កំពុង​បន្ត និង​កា​រដោះស្រាយ​បញ្ហា​មូលដ្ឋាន ។ កា​រគាំទ្រ​កម្រិត​មួយ​" +"មិនមានបំណង​កែ​កំហុស​ផលិតផល​ឥតខ្ចោះ​ទេ ។" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"ការ​បំបែក​បញ្ហា ដែល​មាន​ន័យ​ថា​ការ​គាំទ្រ​ផ្នែក​បច្ចេកទេស​បាន​រចនា​ដើម្បី​ស្ទួន​បញ្ហា​របស់​អតិថិជន បំបែកបញ្ហា​ " +"និង​ផ្ដល់​ដំណោះស្រាយ​សម្រាប់​បញ្ហា​មិន​បាន​ដោះស្រាយ​ដោយ​ការគាំទ្រ​កម្រិត​ពីរ ។" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"ការ​ដោះស្រាយ​បញ្ហា ដែល​មានន័យ​ថា ការ​គាំទ្រ​ផ្នែក​បច្ចេកទេស​បាន​រចនា​ដើម្បី​ដោះស្រាយ​បញ្ហា​ស្មុគស្មាញ " +"ដោយ​ភ្ជាប់​វិស្វរកម្ម​នៅ​ក្នុង​ដំណោះស្រាយ​របស់​ផលិតផល​ដែល​ត្រូ​វបាន​បញ្ជាក់​ដោយ​ការ​គាំទ្រ​កម្រិត​ពីរ ។" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "កិច្ចសន្យា​អតិថិជន​បន្ថែម​ចាំបាច់​សម្រាប់​ទទួល​ជំនួយ ។" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "មិន​ស្គាល់​ជម្រើស​គាំទ្រ ។ មិនមាន​សេចក្ដីអធិប្បាយ" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"កា​រគ្រប់គ្រង​ប្រព័ន្ធ​ត្រូវ​បានចាក់​សោ​ដោយ​កម្មវិធី​ដែល​មាន pid %d (%s) ។\n" +"សូម​បិទ​កម្មវិធី​នេះ​មុន​នឹង​ព្យាយាម​ម្ដង​ទៀត ។" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "មិន​ស្គាល់​របៀប​ផ្គូផ្គង '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "មិន​ស្គាល់​របៀប​ផ្គូផ្គង '%s' សម្រាប់​លំនាំ '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "កន្សោម​ធម្មតា​មិនត្រឹមត្រូវ '%s' ៖ regcomp បាន​ត្រឡប់ %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "កន្សោម​ធម្មតា​មិន​ត្រឹមត្រូវ '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "បាន​ទាមទារ​ការ​ផ្ទៀងផ្ទាត់​ភាព​ត្រឹមត្រូវ​សម្រាប់ '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"មើល​មជ្ឈមណ្ឌល​អតិថិជន​របស់ Novell ដើម្បីពិនិត្យ​មើល​ថាតើ ការ​ចុះឈ្មោះ​ត្រឹមត្រូវ ហើយមិនបាន​ផុត​កំណត់ ។" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "មិន​អាច​បង្កើត​ថត​ឃ្លាំង​សម្ងាត់​របស់​ទិន្នន័យ​មេតា ។" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "កំហុស​ក្នុង​ការ​ព្យាយាម​អាន​ពី '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "មិន​អាច​បង្កើត​ %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +#, fuzzy +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "រក​មិន​ឃើញ​ទិន្នន័យ​មេតា​ដែល​ត្រឹមត្រូវ​នៅ URL ដែល​បាន​បញ្ជាក់" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "បាន​បរាជ័យ​ក្នុង​ការ​ឃ្លាំង​ជា​ឃ្លាំង​សម្ងាត់ (%d) ។" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "កំពុង​ស្ថាបនា​ឃ្លាំង '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "មិន​អាច​បង្កើត​ឃ្លាំង​សម្ងាត់​នៅ​ត្រង់​ %s - គ្មាន​សិទ្ធិ​ក្នុង​ការ​សរសេរ ។" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "ប្រភេទ​ឃ្លាំង​ដែល​មិន​បាន​ដោះស្រាយ" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "កំពុង​បន្ថែម​ឃ្លាំង '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "ឈ្មោះ​ឯកសារ​ឃ្លាំង​មិន​ត្រឹមត្រូវ​នៅ '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "មិន​អាច​បើក​ឯកសារ '%s' ដើម្បី​សរសេរ​បានទេ ។" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "មាន​កំហុស​ដែល​មិន​ស្គាល់​ក្នុង​ការ​អាន​ពី '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "បាន​បរាជ័យ​ក្នុង​ការ​អាន​ថត '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "យក​ឃ្លាំង '%s' ចេញ" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "មិន​អាច​ដោះស្រាយ​កន្លែង​ដែល​ឃ្លាំង​ត្រូវ​បាន​ទុក​បានទេ ។" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "មិនអាច​លុប '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "មិនអាច​​ដោះស្រាយ​កន្លែង​ដែល​សេវា​ត្រូវ​បានផ្ទុក​បានទេ ។" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "ឈ្មោះ​ក្លែងក្លាយ​ឃ្លាំង​មិន​អាច​ចាប់​ផ្តើម​ជា​មួយ​ចំណុច (.)បាន​ទេ ។" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "ឈ្មោះ​ក្លែងក្លាយ​សេវាមិន​អាច​​ចាប់​ផ្តើម​​ជាមួយចំណុច ​(.)​បាន​ទេ ។" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "បន្ត ?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "បាត់​គុណលក្ខណៈ​ដែល​ទាមទារ '%s' ។" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "បាន​ទាមទារ​គុណលក្ខណៈ​មួយ ឬ​ពីរ​របស់ '%s' ឬ '%s' ។" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr " បាន​បរាជ័យ​ក្នុងកា​រប្រតិបត្តិ" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "កញ្ចប់ %s ហាក់​បីជា​​ខូច​ក្នុងការ​ផ្ទេរ ។ តើ​អ្នកចង់​ព្យាយាម​ម្ដង​ទៀត​ទេ ?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "បាន​បរាជ័យ​ក្នុងកា​រផ្ដល់​កញ្ចប់ %s ។ តើអ្នក​ចង់​ព្យាយាម​យក​ម្ដង​ទៀត​ទេ ?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "ការ​ពិនិត្យ applydeltarpm បាន​បរាជ័យ ។" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm បាន​បរាជ័យ ។" + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "ប្រភេទ​ធនធាន VAR1 មិន​គាំទ្រ​លក្ខណៈ​ពិសេស​បង្ហាញ​ភាពផ្លាស់ប្ដូរ" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "មិនអាច​ផ្ដល់​ឯកសារ '%s' ពី​ឃ្លាំង '%s' បានទេ" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "គ្មាន url នៅ​ក្នុង​ឃ្លាំង ។" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "មិនអាច​បង្កើត sat-pool បានទេ ។" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "បំបែក %s ដោយ​មិនអើពើ​ភាព​អាស្រ័យ​របស់​វា​មួយ​ចំនួន" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "ជា​ទូទៅ​មិនអើពើ​នឹង​ភាព​អាស្រ័យ​មួយ​ចំនួន" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "សំណើ​ការ​ប៉ះទង្គិច" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "បញ្ហា​ភាព​អាស្រ័យ​មួយ​ចំនួន" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +#, fuzzy +msgid "unsupported request" +msgstr "មិន​បានគាំទ្រ" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "ក្រុមហ៊ុន​ផ្ដល់​ដែល​បាន​លុប ៖ " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"លុបក្រុមហ៊ុនផ្ដល់ ៖ " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "ក្រុមហ៊ុន​លក់​ដែល​អាច​លុបបាន ៖ " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "សំណើ​នេះ​នឹង​ធ្វើ​ឲ្យ​ប្រព័ន្ធ​របស់​អ្នក​ខូច !" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "មិនអើពើ​នឹង​ការ​ព្រមាន​របស់​ប្រព័ន្ធ​ដែល​ខូច" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "ការ​ដំឡើង ត្រូវបាន​បោះបង់​ដោយ​ផ្ទាល់ ។" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " បាន​ប្រតិបត្តិ" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " បាន​បរាជ័យ​ក្នុងកា​រប្រតិបត្តិ" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " ការ​ប្រតិបត្តិ​បាន​រំលង​ខណៈពេល​បោះបង់" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "កំហុស​ក្នុង​ការ​ផ្ញើ​ការ​ជូនដំណឹង​សារបច្ចុប្បន្នភាព​ ។" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "សារ​បច្ចុប្បន្នភាព​ថ្មី" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM បាន​បរាជ័យ ៖ " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "បរាជ័យក្នុង​ការ​នាំចូល​សោ​សាធារណៈ​ពី​ឯកសារ %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "បរាជ័យ​ក្នុងការ​យក​សោ​សាធារណៈ %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "បាន​ប្ដូរ​ឯកសារ​កំណត់​រចនាសម្ព័ន្ធ​សម្រាប់ %s ៖" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm បានរ​ក្សា​ទុក %s ជា %s ប៉ុន្តែ​វា​អាច​កំណត់​ភាព​ខុស​គ្នា" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm បាន​រក្សាទុក %s ជា %s ។\n" +"នេះ​ជា​បន្ទាត់ ២៥ ជួរ​ដំបូង​ខុសគ្នា៖\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm បាន​បង្កើត %s ជា %s ប៉ុន្តែ​វា​មិន​អាច​កំណត់​ភាព​ខុស​គ្នា" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm បាន​កំណត់ %s ជា %s ។\n" +"នេះ​ជា​បន្ទាត់ ២៥ ជួរ​ដំបូង​ខុសគ្នា ៖​\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "លទ្ធផល rpm បន្ថែម" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "បាន​បង្កើត​ព័ត៌មាន​បម្រុង %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "រក​មិនឃើញ​ឯកសារ​ហត្ថលេខា %s ទេ" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "រក​មិនឃើញ​ឯកសារ​ហត្ថលេខា %s ទេ" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "រក​មិនឃើញ​ឯកសារ​ហត្ថលេខា %s ទេ" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "ប្រភេទ​មិនច្បាស់ '%s' សម្រាប់ %u បៃ ឆេកសាំ '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "មិនអាច​បើក pty (%s) ។" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "មិនអាច​បើក​បំពង់ (%s) ។" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "ខ្សែអក្សរ​សំណួរ LDAP URL មិន​ត្រឹមត្រូវ" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "ប៉ារ៉ាម៉ែត្រ​សំណួរ LDAP URL មិន​ត្រឹមត្រូវ '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "មិនអាច​ក្លូន​វត្ថុ Url បាន​ឡើយ" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "សេចក្ដី​យោង​វត្ថុ Url ទទេ មិន​ត្រឹមត្រូវ" + +# ############################################################################### +# Old yast2-agents.po +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "មិនអាច​ញែក​សមាសភាគ Url បាន​ឡើយ" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "ប្រវត្តិ ៖" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "គ្រោងការណ៍ Url មិន​អនុញ្ញាត %s ទេ" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "សមាសភាគ %s មិន​ត្រឹមត្រូវ '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "សមាសភាគ %s មិន​ត្រឹមត្រូវ" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "មិនបាន​គាំទ្រ​ការញែក​ខ្សែអក្សរ​សំណួរ​សម្រាប់ URL នេះ​ឡើយ" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "គ្រោងការណ៍ Url មិនមែន​ជា​សមាសភាគ​ដែល​បាន​ទាមទារ​ឡើយ" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "គ្រោងការណ៍ Url មិន​ត្រឹមត្រូវ '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "គ្រោងការណ៍ Url មិន​អនុញ្ញាត​ឈ្មោះ​អ្នកប្រើ​ឡើយ" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "គ្រោងការណ៍ Url មិន​អនុញ្ញាត​ពាក្យ​សម្ងាត់​ឡើយ" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "គ្រោងការណ៍ Url ទាមទារ​សមាសភាគ​របស់​ម៉ាស៊ីន" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "គ្រោងការណ៍ Url មិនអនុញ្ញាត​សមាសភាគ​របស់​ម៉ាស៊ីន​ឡើយ" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "សមាសភាគ​របស់​ម៉ាស៊ីន​មិន​ត្រឹមត្រូវ '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "គ្រោងការណ៍ Url មិន​អនុញ្ញាត​ច្រក​ឡើយ" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "សមាសភាគ​ច្រក​មិន​ត្រឹមត្រូវ '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "គ្រោងការណ៍ Url ទាមទារ​ឈ្មោះ​ផ្លូវ" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "មិនបាន​អនុញ្ញាត​ផ្លូវ​ដែល​ទាក់ទង​ទេ ប្រសិន​បើ​មាន​អាជ្ញាធរ" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "ខ្សែអក្សរ​ដែល​បាន​អ៊ិនកូដ មាន NUL បៃ" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "តួអក្សរ​បំបែក​សម្រាប់​ពុះ​អារេ​ប៉ារ៉ាម៉ែត្រ មិន​ត្រឹមត្រូវ" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "តួអក្សរ​បំបែក​សម្រាប់​ពុះ​ផែនទី​ប៉ារ៉ាម៉ែត្រ មិន​ត្រឹមត្រូវ" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "តួអក្សរ​បំបែក​សម្រាប់​ត​អារេ​ប៉ារ៉ាម៉ែត្រ មិន​ត្រឹមត្រូវ" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "ពាក្យ​បញ្ជា​បាន​ចេញ​ដោយ​ស្ថានភាព %d ។" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "ពាក្យ​បញ្ជា​ត្រូវ​បាន​ផ្ដាច់​ដោយ​សញ្ញា %d (%s) ។" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "ពាក្យ​បញ្ជា​បាន​ចេញ ដោយ​មាន​កំហុស​មិន​ស្គាល់ ។" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "មិនអាច chroot ទៅ '%s' (%s) បានទេ ។" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "មិនអាច chroot ទៅ '%s' (%s) បានទេ ។" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "មិនអាច chdir ទៅ '/' ក្នុង chroot (%s) បានទេ ។" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "មិនអាច​ប្រតិបត្តិ '%s' (%s) ។" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "មិនអាច​បែងចែក (%s) បានទេ ។" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "បរាជ័យ​ក្នុង​ការ​ម៉ោន %s លើ %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "បរាជ័យ​ក្នុងការ​អាន់ម៉ោន %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "ឯកសារ​ខូច​ឈ្មោះ ៖ %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "ឧបករណ៍​ផ្ទុក​មិនបាន​បើក នៅពេល​ធ្វើ​អំពើ '%s' ។" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "រក​មិនឃើញ​ឯកសារ '%s' នៅ​លើ​ឧបករណ៍​ផ្ទុក​ទេ '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "មិនអាច​សរសេរ​ឯកសារ '%s' បានទេ ។" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "មិនបាន​ភ្ជាប់​ឧបករណ៍​ផ្ទុក" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "ចំណុច​ភ្ជាប់​ឧបករណ៍​ផ្ទុក​មិនត្រឹមត្រូវ" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "ទាញយក​ការ​ចាប់ផ្ដើម​បាន​បរាជ័យ​សម្រាប់ '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "ករណី​លើកលែង​ប្រព័ន្ធ '%s' នៅលើ​ឧបករណ៍​ផ្ទុក '%s' ។" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "ផ្លូវ '%s' នៅលើ​ឧបករណ៍​ផ្ទុក '%s' មិនមែន​ជា​ឯកសារ​ទេ ។" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "ផ្លូវ '%s' នៅលើ​ឧបករណ៍​ផ្ទុក '%s' មិនមែន​ជា​ថត​ទេ ។" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI មាន​ទ្រង់ទ្រាយ​មិនត្រឹមត្រូវ" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "ឈ្មោះ​ម៉ាស៊ីន​ទទេ​ក្នុង URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "ប្រព័ន្ធ​ឯកសា​ទទេ​នៅ​ក្នុង URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "គោលដៅ​ទទេ​នៅ​ក្នុង URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "គ្រោងការណ៍ URI ដែល​មិនបាន​គាំទ្រ​នៅ​ក្នុង '%s' ។" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "ប្រតិបត្តិការ​មិនបាន​គាំទ្រ​ដោយ​ឧបករណ៍​ផ្ទុក​ទេ" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"ទាញយក​កំហុស​សម្រាប់ '%s' ៖\n" +"កូដ​កំហុស ៖ %s\n" +"សារ​កំហុស ៖ %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "កំហុស​នៅពេល​កំណត់​ជម្រើស​ទាញយក​សម្រាប់ '%s' ៖" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "ប្រភព​ឧបករណ៍​ផ្ទុក '%s' មិនមាន​ឧបករណ៍​ផ្ទុក​ដែល​ត្រូវការ​ទេ" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "ឧបករណ៍​ផ្ទុក '%s' គឺ​កំពុង​ប្រើ​ដោយ​ឧបករណ៍​ផ្សេង" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "មិនអាច​ច្រាន​ឧបករណ៍​ផ្ទុក​ណាមួយ​ចេញ​ឡើយ" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "មិនអាច​ច្រាន​ឧបករណ៍​ផ្ទុក '%s' ចេញបានទេ" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "សិទ្ធិ​ចូល​ដំណើរការ​ទៅ '%s' បាន​បដិសេធ ។" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "អស់​ពេល​លើល​ពេល​ចូល​ដំណើរការ '%s' ។" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "ទីតាំង '%s' មិន​ដំណើរការ​ជា​បណ្ដោះអាសន្ន ។" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " បញ្ហា​វិញ្ញាបនបត្រ SSL ផ្ទៀងផ្ទាត់​ថា​វិញ្ញាបនបត្រ CA គឺ​ត្រឹមត្រូវ​សម្រាប់ '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "មិនបាន​គាំទ្រ​វិធីសាស្ត្រ​ផ្ទៀងផ្ទាត់​ភាពត្រឹមត្រូវ HTTP '%s' ឡើយ" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "បាទ/ចាស" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "ទេ" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "ព្រមាន ៖" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "កំហុស" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "ធ្វើរួច" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "កំហុស" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "ព្រមាន ៖" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "ទៅ​ប្រមូល​យក ៖" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "ចាប់ផ្តើម" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "រក​មិនឃើញ" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "គ្មាន​ជំនួយ​សម្រាប់​ប្រអប់​សំណួរ​នេះ​ទេ ។" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "គ្មាន​ជំនួយ​សម្រាប់​ជម្រើស​នេះ​ទេ" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "បាទ/ចាស" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ទេ" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s មិនមែនជា​របស់​ឃ្លាំង distupgrade នោះ​ទេ" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s មាន​​​ស្ថាបត្យកម្ម​ទាប​ជាង" + +#~ msgid "problem with installed package %s" +#~ msgstr "បញ្ហា​ជាមួយ​កញ្ចប់​ដែល​បាន​ដំឡើង %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "គ្មាន​អ្វី​ផ្ដល់ %s ដែលបាន​ស្នើ​ទេ" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "តើ​អ្នក​បាន​បើក​ឃ្លាំង​ដែល​បាន​ស្នើ​ទាំងអស់​ហើយឬនៅ ?" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "មិនមាន​ព័ត៌មាន​បម្រុង​ទុក​ទេ" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s ជាប់សោ និង​មិន​អាច​លុប​បាន​ឡើយ ។" + +#~ msgid "%s is not installable" +#~ msgstr "%s មិនអាច​ដំឡើងបាន" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "គ្មាន​អ្វី​ផ្ដល់ %s ដែល​ត្រូវការ​ដោយ %s ទេ" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "មិនអាច​ដំឡើង​ទាំង %s និង %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s ប៉ះទង្គិច​ជាមួយ %s ដែល​បាន​ផ្ដល់​ដោយ %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s លែងប្រើ %s ដែល​ផ្ដល់ដោយ %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s ដែល​បាន​ដំឡើង​លែង​ប្រើ %s ដែល​ផ្ដល់​ដោយ %s ហើយ" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "ការ​ប៉ះទង្គិច %s ដែល​អាច​ដោះស្រាយ​បាន​ជា​មួយ %s ដែល​បាន​ផ្ដល់​ដោយ​ខ្លួន​វា​ផ្ទាល់" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s ត្រូវការ %s ប៉ុន្តែ​តម្រូវការ​នេះ​មិនអាច​ផ្ដល់​បានទេ" + +#~ msgid "do not install %s" +#~ msgstr "កុំ​ដំឡើង %s" + +#~ msgid "keep %s" +#~ msgstr "រក្សា %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "កុំ​ហាម​ការ​ដំឡើង​នៃ %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "កុំ​ស្នើ​ឲ្យ​ដំឡើង​កញ្ចប់​ដោះស្រាយ​ដោយ​ផ្ដល់ %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "កុំ​ស្នើ​ឲ្យ​លុប​កញ្ចប់​ដោះស្រាយ​ទាំងអស់​ដោយ​ផ្ដល់ %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "កុំ​ដំឡើង​កំណែ​ថ្មីរបស់ %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "ទុក %s ទោះ​បី​ជា​ស្ថាបត្យកម្ម​ទាប​ក៏​ដោយ" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "ដំឡើង %s ទោះ​បីជា​ស្ថាបត្យកម្ម​ទាប​ក៏​ដោយ" + +#~ msgid "keep obsolete %s" +#~ msgstr "លែង​ប្រើ %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "ដំឡើង %s ពី​ឃ្លាំង​ដែល​បាន​ដក​ចេញ" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "បន្ទាប %s ទៅ %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "ការ​ផ្លាស់ប្ដូរ​ស្ថាបត្យកម្ម​នៃ %s ទៅ %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "ដំឡើង %s (ដោយ​មានការ​ផ្លាស់ប្ដូរ​របស់​អ្នក​លក់)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "ការ​ជំនួស %s ជាមួយ %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "ការ​លុប​នៃ %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "មិនអាច​បើក​ឯកសារ​សោ ៖ %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "អំពើ​នេះ កំពុង​រត់​ដោយ​កម្មវិធី​ផ្សេង​មួយ​ទៀត ។" + +#~ msgid "Hal Exception" +#~ msgstr "ការ​លើកលែង Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "សូមអភ័យទោស កំណែ​នៃ​ libzypp នេះ​ត្រូវ​បាន​ស្ថាបនា​ឡើង​ដោយ​គ្មាន​ការ​គាំទ្រ​ HAL ។" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext មិនបាន​តភ្ជាប់​ឡើយ" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive មិន​បាន​ចាប់ផ្ដើម​ឡើយ" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume មិនបាន​ចាប់ផ្ដើម​ឡើយ" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "មិនអាច​បង្កើត​ការ​តភ្ជាប់ dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new ៖ មិនអាច​បង្កើត​បរិបទ libhal បានឡើយ" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection ៖ មិនអាច​​កំណត់​ការ​តភ្ជាប់ dbus បានឡើយ" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "មិនអាច​ចាប់ផ្ដើម​បរិបទ HAL បានឡើយ -- hald មិន​កំពុង​រត់​ទេឬ ?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "មិន​មែន​ជា​ដ្រាយ​ស៊ីឌី​រ៉ូម​ទេ" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "មិនអាច​ចាប់ផ្ដើម​គុណលក្ខណៈ mutex បានឡើយ" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "មិនអាច​កំណត់​គុណលក្ខណៈ mutex ហៅ​ខ្លួនឯង​បានឡើយ" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "មិនអាច​ចាប់ផ្ដើម mutex ហៅខ្លួន​ឯង​បាន​ឡើយ" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "មិនអាច​យក​សោ mutex បានឡើយ" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "មិនអាច​លែង​សោ mutex បាន​ឡើយ" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "បរាជ័យក្នុង​ការ​នាំចូល​សោ​សាធារណៈ​ពី​ឯកសារ %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "បរាជ័យ​ក្នុងការ​យក​សោ​សាធារណៈ %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "មិន​អាច​រក​ឧបករណ៍​ដែល​មាន​ដើម្បីម៉ោន​ឯកសារ​រូបភាព​ពី '%s'" + +#~ msgid "do not keep %s installed" +#~ msgstr "កុំ​ទុក %s ឲ្យ​នៅ​ដំឡើង" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "មិនអាច​បង្កើត​សោ​សាធារណៈ %s ពី keyring %s ទៅ​ឯកសារ %s បានទេ" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "បានបរាជ័យ​ក្នុងកា​រចាប់ផ្ដើម (Metalink curl) សម្រាប់ '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "កំហុស​ក្នុងការ​ទាញយក (metalink curl) សម្រាប់ '%s' ៖\n" +#~ "កូដ​កំហុស ៖ %s\n" +#~ "សារ​កំហុស ៖ %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "ការ​ទាញយក​បានផ្អាក​នៅ %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "​ទាញយក​អ្វី​ដែលបាន​ផ្អាក​ដោយ​អ្នកប្រើ" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "កំហុស​បានកើតឡើង​ខណៈពេល​កំណត់​​ជម្រើស​ទាញយក (metalink curl) សម្រាប់ '%s' ៖" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "បាន​បរាជ័យ​ក្នុងកា​រទាញយក %s ពី %s" diff --git a/po/ko.po b/po/ko.po new file mode 100644 index 0000000..e7d77f5 --- /dev/null +++ b/po/ko.po @@ -0,0 +1,5688 @@ +# KOREAN message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2000, 2001 SuSE GmbH. +# Hwang, Sang-Jin +# +msgid "" +msgstr "" +"Project-Id-Version: zypp.ko\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2019-03-23 20:19+0000\n" +"Last-Translator: Hwajin Kim \n" +"Language-Team: Korean \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: Weblate 3.3\n" +"X-Poedit-SourceCharset: UTF-8\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "알 수 없는 국가: " + +# TextEntry label for phone network Areacode (german Vorwahl) +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "코드 없음" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "안도라" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "아랍에미리트" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "아프가니스탄" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "앤티가 바부다" + +# AO +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "앙귈라" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "알바니아" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "아르메니아" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "네덜란드령 안틸리스" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "앙골라" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "남극" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "아르헨티나" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "미국령 사모아" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "오스트리아" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "호주" + +# CU +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "아루바" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "올란드 제도" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "아제르바이잔" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "보스니아 헤르체코비나" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "바베이도스" + +# BD +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "방글라데시" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "벨기에" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "부르키나파소" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "불가리아" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "바레인" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "부룬디" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "베냉" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "버뮤다" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "브루나이" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "볼리비아" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "브라질" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "바하마" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "부탄" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "부베이 섬" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "보츠와나" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "벨라루스" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "벨리즈" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "캐나다" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "코코스 군도" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "콩고" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "중앙아프리카 공화국" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "스위스" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "코트디부와르" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "쿡 제도" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "칠레" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "카메룬" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "중국" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "콜롬비아" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "코스타리카" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "쿠바" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "카보베르데" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "크리스마스 섬" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "사이프러스" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "체코 공화국" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "독일" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "지부티" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "덴마크" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "도미니카" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "도미니카 공화국" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "알제리" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "에콰도르" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "에스토니아" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "이집트" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "서사하라" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "에리트레아" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "스페인" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "에티오피아" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "핀란드" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "피지" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "포클랜드 제도" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "마이크로네시아" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "파로에 아일랜드" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "프랑스" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "프랑스 본국" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "가봉" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "영국" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "그라나다" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "그루지아" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "파푸아뉴기니" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "건지" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "가나" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "지브롤터" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "그린란드" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "잠비아" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "기니" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "과들루프" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "적도 기니" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "그리스" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "사우스조지아 및 사우스샌드위치 군도" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "과테말라" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "괌" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "기니비사우" + +# GH +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "가이아나" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "홍콩" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "허드 섬 및 맥도날드 군도" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "온두라스" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "크로아티아" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "아이티" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "헝가리" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "인도네시아" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "아일랜드" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "이스라엘" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "맨 섬" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "인도" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "영인도 제도" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "이라크" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "이란" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "아이슬란드" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "이탈리아" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "저지" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "자메이카" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "요르단" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "일본" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "케냐" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "키르기스스탄" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "캄보디아" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "키리바시" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "코모로" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "세인트 크리스토퍼 네비스" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "북한" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "대한민국" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "쿠웨이트" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "케이맨 제도" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "카자흐스탄" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "라오스" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "레바논" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "세인트 루시아" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "리히텐슈타인" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "스리랑카" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "라이베리아" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "레소토" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "리투아니아" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "룩셈부르크" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "라트비아" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "리비아" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "모로코" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "모나코" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "몰도바" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "몬테네그로" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "산마리노" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "마다가스카르" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "마샬 군도" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "마케도니아" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "말리" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "미얀마" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "몽골" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "마카오" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "북마리아나 군도" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "마티니크" + +# MU +# fuzzy +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "모리타니아" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "몬트세라트" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "말타" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "모리셔스" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "몰디브" + +# ML +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "말라위" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "멕시코" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "말레이시아" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "모잠비크" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "나미비아" + +# help text for option 'value' +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "뉴 칼레도니아" + +# NG +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "니제르" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "노퍽 섬" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "나이지리아" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "니카라과" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "네덜란드" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "노르웨이" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "네팔" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "나우루" + +# table header label +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "니우에" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "뉴질랜드" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "오만" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "파나마" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "페루" + +# GF +# fuzzy +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "프랑스령 폴리네시아" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "파푸아뉴기니" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "필리핀" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "파키스탄" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "폴란드" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "세인트 피에르 미켈론" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "피트카이른" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "푸에르토리코" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "팔레스타인" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "포르투갈" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "팔라우" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "파라과이" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "카타르" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "레위니옹" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "루마니아" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "세르비아" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "러시아 연방" + +# UG +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "르완다" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "사우디아라비아" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "솔로몬 제도" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "세이셸" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "수단" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "스웨덴" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "싱가포르" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "세인트 헬레나" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "슬로베니아" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "스발바르드 얀마이엔" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "슬로바키아" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "시에라리온" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "산마리노" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "세네갈" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "소말리아" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "수리남" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "상투메 프린시페" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "엘살바도르" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "시리아" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "스와질란드" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "터크스케이커스 제도" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "차드" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "프랑스령 남부 지역" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "토고" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "태국" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "타지크스탄" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "토켈라우" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "투르크메니스탄" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "튀니지" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "통가" + +# Textentry label - lease time for IPs in the range +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "동티모르" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "터키" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "트리니다드 토바고" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "투발루" + +# TW +# fuzzy +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "대만" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "탄자니아" + +# "TW" : _("Taiwan R.O.C."), +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "우크라이나" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "우간다" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "미국령 소군도" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "미국" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "우루과이" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "우즈베키스탄" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "바티칸 시국" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "세인트 빈센트 그레나딘스" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "베네수엘라" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "영국령 버진 아일랜드" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "미국령 버진 아일랜드" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "베트남" + +# src/isdn/interface.ycp:258 src/isdn/lowlevel.ycp:52 +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "바누아투" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "월리스 푸투나" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "사모아" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "예멘" + +# Combobox - DNS adding zone - Type Master +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "마요티" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "남아프리카공화국" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "잠비아" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "짐바브웨" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "제공" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "전제조건" + +# tree node string +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "필수" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "충돌" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "폐기사항" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "권장사항" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "제안" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "기능 향상" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "보충" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "기존 키 %s을(를) 키링 %s(으)로 임포트하려고 했습니다." + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "키를 임포트하지 못했습니다." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "키를 삭제하지 못했습니다." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "서명 파일 %s을(를) 찾을 수 없습니다." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "알 수 없는 언어: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "아파르어" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "압카즈어" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "아체어" + +# power saving scheme name, combo box and default contents of text entry +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "아콜리어" + +# tree node string +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "아당메어" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "아닥헤어" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "아시아-아프리카어(기타)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "아프리히리어" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "아프리칸스어" + +# entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space +# are allowed, otherwise translartion won't be used +# try to keep short, may be shortened due to bootloader limitations +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "아이누어" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "아칸어" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "아카드어" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "알바니아어" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "알류트어" + +# src/config/proxy.y2cc:21 +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "알곤킨어" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "남부 알타이어" + +# Combobox item +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "암하라어" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "고대 영어(ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "아파치어" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "아랍어" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "아람어" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "아라곤어" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "아르메니아어" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "아라우칸어" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "아라파호어" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "기계어(기타)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "아라와크어" + +# src/isdn/complex.ycp:266 src/modem/complex.ycp:207 +# src/provider/complex.ycp:186 +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "아샘어" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "아스투리아어" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "아타파스카어" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "호주 언어" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "아바릭어" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "아베스타어" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "아와히어" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "아이마라어" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "아제르바이잔어" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "반다어" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "바미레케어" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "바슈키르어" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "발루치어" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "밤바라어" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "발리어" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "바스크어" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "바사어" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "발트어(기타)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "베자어" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "벨로루시어" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "벰바어" + +# SN +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "벵골어" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "베르베르어(기타)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "호즈푸리어" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "비하르어" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "비콜어" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "비니어" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "비슬라마어" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "식시카어" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "반투어(기타)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "보스니아어" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "브라어" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "브르타뉴어" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "바타크어(인도네시아)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "부랴트어" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "부기어" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "불가리아어" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "버마어" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "브린어" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "카도어" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "중앙아메리카 인디안어(기타)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "카리브어" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "카탈로니아어" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "카프카스어(기타)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "세부아노어" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "켈트어(기타)" + +# CM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "차모로어" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "치브차어" + +# tree node string +# tree node string - CPU information +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "체첸어" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "차가타이어" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "중국어" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "츄케스어" + +# ML +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "마리어" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "치누크 혼합어" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "촉토어" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "치페와이언어" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "체로키어" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "교회슬라브어" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "추바시어" + +# textentry label +# table header 1/2 +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "샤이엔어" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "카믹어" + +# src/config/routing.y2cc:11 +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "콥트어" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "콘월어" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "코르시카어" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "크레오리스와 피긴스어, 영어 기반(기타)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "크레오리스와 피긴스어, 프랑스어 기반(기타)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "크레오리스와 피긴스어, 포르투갈어 기반(기타)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "크리어" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "크리민 타타르어" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "크레오리스와 피긴스어(기타)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "카슈비아어" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "쿠시어(기타)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "체코어" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "다코타어" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "덴마크어" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "다르그와어" + +# combo box item +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "다야크어" + +# src/isdn/complex.ycp:260 +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "델라웨어어" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "슬라브어(아타파스카어)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "도그리브어" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "딩카어" + +# tree node string - means "hardware driver" +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "디베히어" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "도그리어" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "드라비다어(기타)" + +# combo box item +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "소르비아어(저지)" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "드와라어" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "네덜란드어, 중세(ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "네덜란드어" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "드율라어" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "종카어" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "이픽어" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "이집트어(고대)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "이카죽어" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "엘람어" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "영어" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "영어, 중세(1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "에스페란토어" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "에스토니아어" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "에웨어" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "이원도어" + +# tree node string +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "팡그어" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "페로스어" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "판티어" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "피지어" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "필리핀어" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "핀란드어" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "피노우그리아어(기타)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "폰어" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "프랑스어" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "프랑스어, 중세(ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "프랑스어, 고대(842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "프리지아어" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "풀라어" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "프리우리안어" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "가어" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "가요어" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "그바야어" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "독일어(기타)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "그루지아어" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "독일어" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "게이즈어" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "키리바시어" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "게일어" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "아일랜드어" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "갈리시아어" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "맹크스어" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "독일어, 중세 고지(ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "독일어, 고대 고지(ca.750-1050)" + +# GA +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "곤디어" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "고론탈로어" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "고트어" + +# GA +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "그리보어" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "그리스어, 고대(1453년까지)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "그리스어, 현대(1453년 이후)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "구아라니어" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "구자라트어" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "그위친어" + +# src/isdn/complex.ycp:260 +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "하이다어" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "아이티어" + +# combo box item +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "하우자어" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "하와이어" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "헤브루어" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "헤레로어" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "헤리가뇬어" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "히마차리어" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "힌디어" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "히타이트어" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "흐몽어" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "히리 모투어" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "소르비아어(고지)" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "헝가리어" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "후파어" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "이반어" + +# combo box item +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "이그보어" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "아이슬란드어" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "이도어" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "시츄안 이어" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "이조어" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "이눅티투트어" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "인터링게어" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "이로코어" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "국제어(국제보조어협회)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "인도어(기타)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "인도네시아어" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "인도유럽어(기타)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "인귀시어" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "이누피아크어" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "이란어(기타)" + +# src/config/proxy.y2cc:21 +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "이러쿼이어" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "이탈리아어" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "자바어" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "로반어" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "일본어" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "유대-페르시아어" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "유대-아라비아어" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "카라칼파크어" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "커바일어" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "카친어" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "그린란드어" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "캄바어" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "칸나다어" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "카렌어" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "카슈미르어" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "카누리어" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "카위어" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "카자흐어" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "카바르디어" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "카시어" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "코이산어(기타)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "크메르어" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "코탄스어" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "키쿠유어" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "키냐르완다어" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "키르기스어" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "킴분두어" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "코카니어" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "코미어" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "콩고어" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "한국어" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "코스라이엔어" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "크펠르어" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "카라챠이-발카르어" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "크루어" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "쿠르크어" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "쿠안야마어" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "쿠믹어" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "쿠르드어" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "쿠터네이어" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "라디노어" + +# UG +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "라한다어" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "람바어" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "라오어" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "라틴어" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "라트비아어" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "레즈기안어" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "림버거어" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "링갈라어" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "리투아니아어" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "몽고어" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "로지어" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "룩셈부르크어" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "루바-룰루아어" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "루바-카탄가어" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "간다어" + +# translators: table entry for Listen statements +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "루이세노어" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "룬다어" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "루오어(케냐 및 탄자니아)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "루샤이어" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "마케도니아어" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "마두라어" + +# src/isdn/interface.ycp:258 src/isdn/lowlevel.ycp:52 +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "마가히어" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "마셜제도어" + +# ML +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "마이틸리어" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "마카사어" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "말라얄람어" + +# this string is usually used as headline of a popup +# update warning +# the user has selected a 64bit partition (x86_64) for update +# but booted with the 32bit DVD (x86) +# This will replace all 64bit packages with 32bit counterparts. +# It is technically possibly but probably not what the user intended. +# update warning +# the user has selected a 32bit partition on a x86-64 computer for update +# but booted with the 64bit DVD (x86-64) +# This will replace all 64bit packages with 32bit counterparts. +# It is technically possibly but probably not what the user intended. +# install warning +# the computer system has a 64bit (x86-64) bit processor but +# the user booted from a 32bit installation medium +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "만딩고어" + +# tree node string +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "마오리어" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "오스트로네시아어(기타)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "마라티어" + +# ML +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "마사이어" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "말레이어" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "모크샤어" + +# UG +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "만다르어" + +# According to QIM Screenshot +# -ke- +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "멘데어" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "아일랜드어, 중세(900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "미크맥어" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "미낭카바우어" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "기타 언어" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "몬크메르어(기타)" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "마다가스카르어" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "몰타어" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "만주어" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "마니푸리어" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "마노보어" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "모호크어" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "몰다비아어" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "몽골어" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "모시어" + +# PushButton label +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "다국어" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "문다어" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "크리크어" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "미란다어" + +# src/isdn/complex.ycp:260 +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "마르와리어" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "마야어" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "엘즈야어" + +# src/isdn/interface.ycp:258 src/isdn/lowlevel.ycp:52 +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "나우아틀어" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "북아메리카 인디언어" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "나폴리어" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "나바조" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "은데벨레어, 남부" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "은데벨레어, 북부" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "느동가어" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "저지 독일어" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "네팔어" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "네와르어" + +# Translators: table column headings +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "니아스어" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "니제르-코르도파니아어(기타)" + +# Tv frequency table +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "니웨언어" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "뉘노르스크 노르웨이어" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "보크말 노르웨이어" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "노가이어" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "노르웨이어, 고대" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "노르웨이어" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "소토어, 북부" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "누비안어" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "네와르어(고전)" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "치츄어" + +# src/isdn/complex.ycp:266 src/modem/complex.ycp:207 +# src/provider/complex.ycp:186 +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "니암웨지어" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "니안콜어" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "뉴로어" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "느지마어" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "옥시트어(1500년 이후)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "오지브웨이어" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "오리야어" + +# User name for user: "root" +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "오로모어" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "오세이지어" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "오세티아어" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "터키어, 오스만(1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "오토미안어" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "파푸아어(기타)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "판가시난어" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "팔레비어" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "팜팡가어" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "펀잡어" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "파피아먼토어" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "파라우안어" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "페르시안 고대어(ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "페르시아어" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "필리핀어(기타)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "페니키아어" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "팔리어" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "폴란드어" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "폼페이어" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "포르투갈어" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "프라크리트어" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "프로벤칼어, 고대(1500년까지)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "푸시토어" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "케추아어" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "라자스탄어" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "라파누이어" + +# src/config/routing.y2cc:11 +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "라로통가어" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "로망스어(기타)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "레토로만어" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "집시어" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "루마니아어" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "룬디어" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "러시아어" + +# list item +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "산다웨어" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "산고어" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "야큐트어" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "남아메리카 인디언어(기타)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "샐리시어어" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "사마리아 아랍어" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "산스크리트어" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "사사크어" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "산탈리어" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "세르비아어" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "시칠리아어" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "스코틀랜드어" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "크로아티아어" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "셀쿠프어" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "셈어(기타)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "아일랜드어, 고대(900년까지)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "수화" + +# GH +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "샨어" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "시다모어" + +# text entry +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "신할라어" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "수족어" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "시노티베트어(기타)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "슬라브어(기타)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "슬로바키아어" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "슬로베니아어" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "남부 사미어" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "북부 사미어" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "사미어(기타)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "룰레 사미어" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "이나리 사미어" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "사모아어" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "스콜트 사미어" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "쇼나어" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "신디어" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "소닌케어" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "소그디엔어" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "소말리아어" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "송가이족어" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "소토어, 남부" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "스페인어" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "사르디니아어" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "세셀어" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "니로-사하람어(기타)" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "스와티어" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "수쿠마족어" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "순단어" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "수수어" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "수메르어" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "스와힐리어" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "스웨덴어" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "시리아어" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "타히티어" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "태국어(기타)" + +# tree node string - CPU information +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "타밀어" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "타타르어" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "텔루구어" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "팀니어" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "테레노어" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "테툼어" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "타지크어" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "타갈로그어" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "태국어" + +# TW +# fuzzy +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "티베트어" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "티그레어" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "티그리냐어" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "티비어" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "클링곤어" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "틀링기트어" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "타마섹어" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "통가어(니아사)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "통가어(통가섬)" + +# combo box entry, networking technology name +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "토크 피신어" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "트심시안어" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "츠와나어" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "총가어" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "투르크멘어" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "툼부카어" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "투피어" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "터어키어" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "알타이어(기타)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "트위어" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "투비니안어" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "우드무르트어" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "유가리틱어" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "위구르어" + +# "TW" : _("Taiwan R.O.C."), +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "우크라이나어" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "움분두어" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "확인되지 않음" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "우르두어" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "우즈벡어" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "바이어" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "벤다어" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "베트남어" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "볼라퓌크어" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "보틱어" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "와카샨어" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "왈라모어" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "와라이어" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "와쇼어" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "웨일즈어" + +# src/config/proxy.y2cc:21 +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "소르브어" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "왈론어" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "올로프어" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "칼미크어" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "코사족어" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "야오족어" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "얍페세어" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "이디시어" + +# CU +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "요루바어" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "야픽어" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "사포테크어" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "제나가어" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "주앙어" + +# Table header item - DNS listing zones +# table header +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "잔데어" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "줄루" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "주니어" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "다음 작업이 수행됨:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "만료되지 않음" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "만료됨: 1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "만료: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(만료되지 않음)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(만료됨)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(24시간 내 만료)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "%d(24시간 내 만료)" + +# translators: fallback name for a module at command line +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "알 수 없음" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "지원하지 않음" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "단계 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "단계 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "단계 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "추가 고객 계약 필수" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "잘못됨" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "지원 레벨이 지정되지 않았습니다." + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "제조업체에서 지원을 제공하지 않습니다." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Problem determination(문제 결정) - 호환성 정보, 설치 기술 지원, 사용 지원, 지" +"속적인 유지보수 및 기본적인 문제해결를 위한 기술 지원을 의미합니다. 레벨 1 지" +"원은 제품 결함 오류를 해결하기 위한 지원이 아닙니다." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Problem isolation(문제 격리) - 중복되는 문제, 문제 영역 격리, 그리고 레벨 1 " +"지원에서 해결할 수 없는 문제에 대한 해답 제공을 위해 만들어진 기술 지원 서비" +"스입니다." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Problem resolution(문제 해결) - 레벨 2 지원에서 식별된 제품 결함을 해결하기 " +"위해 엔지니어링 작업을 통해 복잡한 문제를 해결하도록 만들어진 기술 지원 서비" +"스입니다." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "지원을 받으려면 추가 고객 계약이 필요합니다." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "알 수 없는 지원 옵션입니다. 설명을 사용할 수 없습니다." + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"시스템 관리가 응용 프로그램에서 pid %d(%s)과(와) 함께 잠겼습니다.\n" +"다시 시도하기 전에 이 응용 프로그램을 닫으십시오." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "알 수 없는 일치 모드 '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "알 수 없는 일치 모드 '%s'(패턴 '%s')" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "잘못된 정규식 '%s': regcomp가 %d을(를) 반환했습니다." + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "잘못된 정규식 '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "'%s'에 대한 인증 필요" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"SUSE 고객 센터를 방문하여 등록이 올바른지, 등록이 만료되지 않았는지 확인합니" +"다." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"등록이 유효하고 만료되지 않았는지 확인하려면 Novell 고객 센터에 문의하십시오." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "연결점 생성: 연결점을 생성할 쓰기 가능한 디렉토리를 찾을 수 없습니다." + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "'lsof' 패키지를 먼저 설치하십시오." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "메타 데이터 캐시 디렉토리를 생성할 수 없습니다." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "'%s'에서 읽기를 시도하는 중에 오류가 발생했습니다." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "%s을(를) 생성할 수 없음" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "지정한 URL에는 유효한 메타데이터가 없음" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "리포지토리(%d)를 캐시하지 못했습니다." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "리포지토리 '%s' 캐시 빌드 중" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "%s에서 캐시를 생성할 수 없음 - 쓰기 권한이 없습니다." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "리포지토리 유형이 처리되지 않았습니다." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "'%s' 리포지토리 추가 중" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "'%s'에서 리포지토리 파일 이름이 잘못되었습니다." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "쓰기 위한 파일 '%s'을(를) 열 수 없습니다." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "'%s'에서 읽는 중에 알 수 없는 오류가 발생했습니다." + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "리포지토리 디렉토리 '%1%'을(를) 읽을 수 없음: 사용 권한 거부됨" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "디렉토리 '%s'을(를) 읽지 못했습니다." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "리포지토리 파일 '%1%'을(를) 읽을 수 없음: 사용 권한 거부됨" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "'%s' 리포지토리 제거 중" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "리포지토리가 저장된 위치를 알 수 없습니다." + +# Frame title for installation target hard disk / partition(s) +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "'%s'을(를) 삭제할 수 없습니다." + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "서비스가 저장된 위치를 알 수 없습니다." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "알 수 없는 서비스 '%1%': 독립 서비스 리포지토리 '%2%' 제거 중" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "리포지토리 별칭은 점(.)으로 시작할 수 없습니다." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "서비스 별칭은 점(.)으로 시작할 수 없습니다." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "계속하시겠습니까?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "%1% 리포지토리에서 추가 'gpgkey=' URL을 정의하지 않습니다." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "%2% 리포지토리에서 gpg 키 ID %1%을(를) 검색합니다." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "%2% 캐시에서 gpg 키 ID %1%을(를) 검색합니다." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "필수 특성 '%s'이(가) 누락되었습니다." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "'%s' 또는 '%s' 속성 중 하나 또는 둘 다가 필요합니다." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "서명 확인 실패" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "패키지 %s이(가) 전송 중에 손상된 것 같습니다. 다시 검색하시겠습니까?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "패키지 %s을(를) 제공하지 못했습니다. 다시 검색하시겠습니까?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm 검사 실패." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm 실패." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "서비스 플러그인이 특성 변경을 지원하지 않습니다." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "파일 '%s'을(를) 리포지토리 '%s'에서 제공할 수 없습니다." + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "리포지토리에 URL이 없습니다." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"%2%\n" +" 패키지의\n" +" %1% 파일이\n" +" %3%\n" +" 패키지의 파일과 충돌합니다." + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"%2%\n" +" 패키지의\n" +" %1% 파일이\n" +" %3%\n" +" 설치의 파일과 충돌합니다." + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"%2%\n" +" 설치의\n" +" %1% 파일이\n" +" %3%\n" +" 패키지의 파일과 충돌합니다." + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"%2%\n" +" 설치의\n" +" %1% 파일이\n" +" %3%\n" +" 설치의 파일과 충돌합니다." + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"%2%\n" +" 패키지의\n" +" %1% 파일이\n" +" %4%\n" +" 패키지의\n" +" %3%\n" +" 파일과 충돌합니다." + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"%2%\n" +" 패키지의\n" +" %1% 파일이\n" +" %4%\n" +" 설치의\n" +" %3%\n" +" 파일과 충돌합니다." + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"%2%\n" +" 설치의\n" +" %1% 파일이\n" +" %4%\n" +" 패키지의\n" +" %3%\n" +" 파일과 충돌합니다." + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"%2%\n" +" 설치의\n" +" %1% 파일이\n" +" %4%\n" +" 설치의\n" +" %3%\n" +" 파일과 충돌합니다." + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "sat-pool을 생성할 수 없습니다." + +# text is shown in a column of a package list entry +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "일부 종속성을 무시하여 %s을(를) 구분합니다." + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "일부 종속을 일반적으로 무시" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "요청 충돌" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "일부 종속성 문제" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "지원되지 않는 요청" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "삭제된 공급자: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"설치 불가능한 공급자: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "설치할 수 없는 공급자: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "이 요청은 시스템을 손상시킵니다!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "손상된 시스템에 대한 경고를 무시합니다." + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "설치가 지시된 대로 중단되었습니다." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " 실행됨" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " 실행 실패됨" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s이(가) 이미 %s(으)로 실행되었습니다." + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " 중단하는 중 실행 건너뜀" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "업데이트 메시지 알림을 보내는 중에 오류가 발생했습니다." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "새 업데이트 메시지" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM 실패: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "%1% 파일에서 공용 키를 임포트하지 못했습니다." + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "%1% 공용 키를 제거하지 못했습니다." + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +# progress stage +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s에 대한 구성 파일을 변경함:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "RPM은 %s을(를) %s(으)로 저장했지만, 차이점을 구분할 수 없습니다." + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"RPM이 %s을(를) %s(으)로 저장했습니다.\n" +"다음은 차이에 대한 처음 25개 행입니다.\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "RPM은 %s을(를) %s(으)로 생성했지만, 차이점을 구분할 수 없습니다." + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"RPM이 %s을(를) %s(으)로 만들었습니다.\n" +"다음은 차이에 대한 처음 25개 행입니다.\n" + +# dialog caption +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "추가 RPM 출력" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "백업 %s을(를) 만들었음" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "서명 정상" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "알 수 없는 서명 유형" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "서명을 확인할 수 없음" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "서명이 정상이지만 키를 신뢰할 수 없음" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "서명 공용 키 사용 불가" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "파일이 존재하지 않거나 서명을 확인할 수 없음" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "파일이 서명되지 않음" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "모호한 유형 '%s'(%u바이트 체크섬 '%s'에 대해)" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "pty(%s)를 열 수 없습니다." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "파이프(%s)를 열 수 없습니다." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "잘못된 LDAP URL 쿼리 스트링" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "LDAP URL 쿼리 파라미터 '%s'이(가) 잘못되었습니다." + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "URL 객체를 복제할 수 없습니다." + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "빈 URL 객체 참조는 잘못되었습니다." + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "URL 구성요소를 구문 분석할 수 없습니다." + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "이력:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "URL 구성표는 %s을(를) 허용하지 않습니다." + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "%s 구성요소 '%s'이(가) 잘못되었습니다." + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "%s 구성요소가 잘못되었습니다." + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "이 URL에 대해 쿼리 스트링 구문 분석이 지원되지 않습니다." + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL 구성표는 필수 구성요소입니다." + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "URL 구성표 '%s'이(가) 잘못되었습니다." + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "URL 구성표가 사용자 이름을 허용하지 않습니다." + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "URL 구성표가 비밀번호를 허용하지 않습니다." + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "URL 구성표에 호스트 구성요소가 필요합니다." + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "URL 구성표가 호스트 구성요소를 허용하지 않습니다." + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "호스트 구성요소 '%s'이(가) 잘못되었습니다." + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "URL 구성표가 포트를 허용하지 않습니다." + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "포트 구성요소 '%s'이(가) 잘못되었습니다." + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "URL 구성표에 경로 이름이 필요합니다." + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "기관이 있는 경우 상대 경로는 허용되지 않습니다." + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "인코드 스트링에 NUL 바이트가 포함되어 있습니다." + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "파라미터 배열 분할 구분 문자가 잘못되었습니다." + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "파라미터 맵 분할 구분 문자가 잘못되었습니다." + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "파라미터 배열 조인 구분 문자가 잘못되었습니다." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "상태 %d(으)로 명령이 종료되었습니다." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "명령이 신호 %d(%s)에 의해 종료되었습니다." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "알 수 없는 오류와 함께 명령이 종료되었습니다." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "'%s'(%s)에 대해 chroot할 수 없습니다." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "'%s'(%s)(으)로 chdir할 수 없습니다." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "'%s'(chroot '%s' 내부)(%s)(으)로 chdir할 수 없습니다." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "'%s'(%s)을(를) 실행할 수 없습니다." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "fork(%s)할 수 없습니다." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "%s을(를) %s에 마운트하지 못했습니다." + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "%s을(를) 마운트 해제하지 못했습니다." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "잘못된 파일 이름: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "'%s' 작업을 수행할 때 미디어를 열 수 없습니다." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "'%s' 파일을 '%s' 미디어에서 찾을 수 없습니다." + +# Frame title for installation target hard disk / partition(s) +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "'%s' 파일을 쓸 수 없습니다." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "미디어가 연결되지 않음" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "잘못된 미디어 연결점" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "'%s'에 대한 다운로드(CURL) 초기화 실패" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "시스템 예외 '%s'이(가) 미디어 '%s'에서 발생했습니다." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "'%s' 경로('%s' 미디어에 있음)가 파일이 아닙니다." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "'%s' 경로('%s' 미디어에 있음)가 디렉토리가 아닙니다." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "잘못된 URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "URI의 호스트 이름이 비어 있습니다." + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "URI의 파일 시스템이 비어 있습니다." + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "URI의 대상이 비어 있습니다." + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "'%s'에서 지원되지 않는 URI 구성표입니다." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "미디어에서 지원되지 않는 작업입니다." + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"'%s'에 대한 다운로드(CURL) 오류:\n" +"오류 코드: %s\n" +"오류 메시지: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "'%s'에 대한 다운로드(curl) 옵션을 설정하는 동안 오류가 발생했습니다." + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "미디어 소스 '%s'에 원하는 매체가 없습니다." + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "미디어 '%s'이(가) 다른 인스턴스에서 사용 중입니다." + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "미디어를 꺼낼 수 없습니다." + +# Frame title for installation target hard disk / partition(s) +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "미디어 '%s'을(를) 꺼낼 수 없습니다." + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "'%s' 액세스 권한이 거부되었습니다." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "'%s'에 액세스할 때 제한 시간이 초과되었습니다." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "다운로드한 데이터가 예상 파일 크기 '%s'/'%s'을(를) 초과했습니다." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "위치 '%s'에 일시적으로 액세스할 수 없습니다." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL 인증서 문제, '%s'의 CA 인증서에 문제가 없는지 확인하십시오." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "지원하지 않는 HTTP 인증 방법 '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "예" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "아니요" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "참조:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "경고:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "오류:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "완료" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "오류" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "경고: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "검색 중:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "시작 중" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "찾을 수 없음" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "이 프롬프트에 사용 가능한 도움말이 없습니다." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "이 옵션에 사용 가능한 도움말이 없습니다." + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "모든 옵션 표시" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "예" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "아니요" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "%%posttrans 스크립트 '%1%' 실행 중" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "%posttrans 스크립트 실행 중" + +#~ msgid "Package is not signed!" +#~ msgstr "패키지가 서명되지 않았습니다!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s이(가) 배포 업그레이드 리포지토리에 속해 있지 않습니다." + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s에 하위 아키텍처가 있습니다." + +#~ msgid "problem with installed package %s" +#~ msgstr "설치된 패키지 %s에 문제가 발생했습니다." + +#~ msgid "nothing provides requested %s" +#~ msgstr "요청한 %s이(가) 제공되지 않습니다." + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "요청한 모든 리포지토리를 활성화했습니까?" + +#~ msgid "package %s does not exist" +#~ msgstr "%s 패키지가 존재하지 않습니다." + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s은(는) 시스템에서 제공되며 지울 수 없습니다." + +#~ msgid "%s is not installable" +#~ msgstr "%s을(를) 설치할 수 없습니다." + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s(%s에서 필요)이(가) 제공되지 않습니다." + +# Frame title for installation target hard disk / partition(s) +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s과(와) %s을(를) 모두 설치할 수 없습니다." + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s이(가) %s(%s에서 제공)과(와) 충돌합니다." + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s이(가) %s(%s에서 제공)을(를) 폐기합니다." + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "설치된 %s이(가) %s(%s에서 제공)을(를) 제거합니다." + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "Solvable %s이(가) 자체적으로 제공된 %s과(와) 충돌합니다." + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s에 %s이(가) 필요하지만, 이 요구사항을 제공할 수 없습니다." + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "잠금 해제로 %s 제거 허용" + +# Frame title for installation target hard disk / partition(s) +#~ msgid "do not install %s" +#~ msgstr "%s 설치 안 함" + +#~ msgid "keep %s" +#~ msgstr "%s 유지" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "잠금 해제로 %s 설치 허용" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "%s을(를) 제공하는 solvable 설치를 묻지 않음" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "%s을(를) 제공하는 모든 solvable 삭제를 묻지 않음" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "%s의 최신 버전을 설치하지 않음" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "하위 아키텍처인 경우에도 %s 유지" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "하위 아키텍처인 경우에도 %s 설치" + +#~ msgid "keep obsolete %s" +#~ msgstr "구식 %s 유지" + +#~ msgid "install %s from excluded repository" +#~ msgstr "제외된 리포지토리에서 %s 설치" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "%s을(를) %s(으)로 다운그레이드" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "%s에서 %s(으)로 아키텍처 변경" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "%s 설치(벤더 변경)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "%s을(를) %s(으)로 대체" + +#~ msgid "deinstallation of %s" +#~ msgstr "%s 설치 제거" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "잠금 파일 %s을(를) 열 수 없습니다." + +#~ msgid "This action is being run by another program already." +#~ msgstr "이 동작은 이미 다른 프로그램에서 실행 중입니다." + +#~ msgid "Hal Exception" +#~ msgstr "Hal 예외" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "이 버전의 libzypp는 HAL 지원 없이 작성되었습니다." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext가 연결되지 않았음" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive가 초기화되지 않았음" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume이 초기화되지 않았음" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "dbus 연결을 생성할 수 없음" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: libhal 컨텍스트를 생성할 수 없음" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: dbus 연결을 설정할 수 없음" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "HAL 컨텍스트를 초기화할 수 없습니다. hald가 실행되고 있지 않습니까?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "CD-ROM 드라이브가 아님" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "mutex 특성을 초기화할 수 없습니다." + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "순환 mutex 특성을 설정할 수 없습니다." + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "순환 mutex를 초기화할 수 없습니다." + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "mutex 잠금을 획득할 수 없습니다." + +#~ msgid "Can't release the mutex lock" +#~ msgstr "mutex 잠금을 해제할 수 없습니다." + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "%s 파일에서 공용 키를 임포트하지 못했습니다. %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "%s 공용 키를 제거하지 못했습니다. %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "'%s'에서 이미지 파일을 탑재하기 위해 사용 가능한 루프 장치를 찾을 수 없습" +#~ "니다." + +# Frame title for installation target hard disk / partition(s) +#~ msgid "do not keep %s installed" +#~ msgstr "%s 의 설치를 그대로 두지 않음" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "공개 키 %s(%s 키링으로 부터)를 %s 파일에 생성 할 수 없음" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "'%s' 에 대한 다운로드 (메타링크 curl) 초기화에 실패" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "'%s' 에 대한 다운로드 (메타링크 curl) 오류 :\n" +#~ "오류 코드: %s\n" +#~ "오류 메시지: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "다운로드가 중단됨(%d%%)" + +#, fuzzy +#~ msgid "Download interrupted by user" +#~ msgstr "다운로드가 중단됨(%d%%)" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "'%s' 에 대한 다운로드 (메타링크 curl) 옵션을 설정 할 때 오류 발생:" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "%s로부터 %s로 다운로드에 실패" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "세르비아 몬테네그로" diff --git a/po/ku.po b/po/ku.po new file mode 100644 index 0000000..a7b6767 --- /dev/null +++ b/po/ku.po @@ -0,0 +1,5382 @@ +# Copyright © 2009 SUSE Linux Products GmbH. +# Kurdish Team , 2009. +# +msgid "" +msgstr "" +"Project-Id-Version: memory.ku.po\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2005-09-23 00:15+0200\n" +"Last-Translator: Kurdish Team \n" +"Language-Team: Kurdish Team \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: Plural-Forms: nplurals=2; plural=n != 1\n" + +#: zypp/CountryCode.cc:50 +#, fuzzy +msgid "Unknown country: " +msgstr "Vebijêrka nenas: %1" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +#, fuzzy +msgid "No Code" +msgstr "Kod" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andora" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Mîrtiyên Ereb ên Yekbûyî" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Efxanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Angîla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Arnavût" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +#, fuzzy +msgid "Armenia" +msgstr "Ermenî" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +#, fuzzy +msgid "Netherlands Antilles" +msgstr "Holanda" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +#, fuzzy +msgid "Angola" +msgstr "Mongolî" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +#, fuzzy +msgid "Antarctica" +msgstr "Bixweber" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Arjantîn" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Awusturya" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Awustralya" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +#, fuzzy +msgid "Aland Islands" +msgstr "Giravên Kayman" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +#, fuzzy +msgid "Azerbaijan" +msgstr "Azerbaycanî" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladeş" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belçîka" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaristan" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrayîn" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +#, fuzzy +msgid "Burundi" +msgstr "Rundî" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermûda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolîvya" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brezîlya" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +#, fuzzy +msgid "Bouvet Island" +msgstr "Giravên Faroye" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belîze" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +#, fuzzy +msgid "Congo" +msgstr "Kongoyî" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "Sûriye" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Swîsre" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +#, fuzzy +msgid "Cook Islands" +msgstr "Giravên Faroye" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Sîlî" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +#, fuzzy +msgid "Cameroon" +msgstr "Kamera" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +#, fuzzy +msgid "China" +msgstr "Çînî" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolombiya" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kosta Rîka" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kap Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Girava Noel" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Komara Çek" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Almanya" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Cîbutî" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danîmarka" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Domînîka" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Komara Domînîk" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Cezayîr" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvator" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonya" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Misir" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanya" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Fînlandiya" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fîjî" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Giravên Faroye" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Fransa" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Şahitiya Yekbuyî" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Girava Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gurcistan" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +#, fuzzy +msgid "French Guiana" +msgstr "Fransî (Kanada)" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Cebelîtariq" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Greenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadelûp" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Yewnanistan" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Hirvatistan" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +#, fuzzy +msgid "Haiti" +msgstr "Zimanê Haitian" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Macaristan" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Endonezya" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Îrlanda" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Îsraîl" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Girava Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Hindistan" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraq" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Îzlanda" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Îtalya" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamayîka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Urdin" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonya" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts û Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +#, fuzzy +msgid "North Korea" +msgstr "Amerîkaya Bakur" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +#, fuzzy +msgid "South Korea" +msgstr "Efrîka Basur" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kûveyt" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Giravên Kayman" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +#, fuzzy +msgid "Kazakhstan" +msgstr "Qazaxî" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Lubnan" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Lihtenstayn" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lîtvanya" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latviya" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Fas" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "San Marîno" + +#: zypp/CountryCode.cc:298 +#, fuzzy +msgid "Madagascar" +msgstr "Zimanê Malagasy" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +#, fuzzy +msgid "Marshall Islands" +msgstr "Giravên Faroye" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonya" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +#, fuzzy +msgid "Mongolia" +msgstr "Mongolî" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinîk" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +#, fuzzy +msgid "Mauritania" +msgstr "Morîtiyus" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Morîtiyus" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Giravên Maldiv" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +#, fuzzy +msgid "Malawi" +msgstr "Zimanê Malay" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexîko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malezya" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +#, fuzzy +msgid "Mozambique" +msgstr "Martinîk" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +#, fuzzy +msgid "New Caledonia" +msgstr "Makedonya" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +#, fuzzy +msgid "Norfolk Island" +msgstr "Giravên Faroye" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +#, fuzzy +msgid "Nigeria" +msgstr "Cezayîr" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nîkaragûa" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Holanda" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norweç" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +#, fuzzy +msgid "Nepal" +msgstr "Zimanê Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Naûrû" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Nîûe" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Zelandaya Nû" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Uman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Perû" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Fîlîpîn" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polonya" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitkayirn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Porto Rîko" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portekîz" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palawu" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reûnyon" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romanya" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Sirbîstan" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +#, fuzzy +msgid "Rwanda" +msgstr "Zimanê Banda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Si'ûdî Erebistan" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +#, fuzzy +msgid "Solomon Islands" +msgstr "Giravên Kayman" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sûdan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Swêd" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Sîngapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +#, fuzzy +msgid "Saint Helena" +msgstr "Saint Lucia" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenya" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakya" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marîno" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +#, fuzzy +msgid "Somalia" +msgstr "Zimanê Somalî" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +#, fuzzy +msgid "Suriname" +msgstr "Navê Pelê" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +#, fuzzy +msgid "Syria" +msgstr "Asûrî" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +#, fuzzy +msgid "Swaziland" +msgstr "Tayland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tayland" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tacîkistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Zimanê Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +#, fuzzy +msgid "Turkmenistan" +msgstr "Tirkmenî" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tûnis" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +#, fuzzy +msgid "Tonga" +msgstr "Zimanê Tsonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Tirkiye" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Zimanê Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taywan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrayna" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +#, fuzzy +msgid "Uganda" +msgstr "Zimanê Banda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +#, fuzzy +msgid "United States" +msgstr "Mîrtiyên Ereb ên Yekbûyî" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Ozbekîstan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +#, fuzzy +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Kitts û Nevis" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezûela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +#, fuzzy +msgid "Vietnam" +msgstr "Vietnamî" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +#, fuzzy +msgid "Vanuatu" +msgstr "Bi Destan" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayote" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Efrîka Basur" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Peydeker" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Pêwist" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Sepandina delta RPM têk çû" + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Sepandina delta RPM têk çû" + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Pel nehat dîtin." + +#: zypp/LanguageCode.cc:49 +#, fuzzy +msgid "Unknown language: " +msgstr "Zimanê Nayê Zanîn:" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Zimanê Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abxazî" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Açînezî" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Akolî" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Zimanê Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Zimanê Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Zimanê Afro-Asyatîk (Yên din)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrîhîlî" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Zimanê Efrîkî" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Zimanê Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Zimanê Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akadî" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanî" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Zimanê Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Zimanên Algonquyî" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altaya Başûrî" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharî" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Îngilîzî, Kevn (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Zimanên Apaçî" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Erebî" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaîkî" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Zimanê Aragonese" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Ermenî" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Arûkanî" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Zimanê Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Zêdehî (Yên din)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawakî" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Zimanê Assamese" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturî" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Zimanên Atapaskanî" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Zimanên Awustralî" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Zimanê Avaric" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestî" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadî" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Zimanê Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaycanî" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Zimanê Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Zimanên Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Zimanê Başkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Beluçî" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Zimanê Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Baliyî" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskî" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Zimanê Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltîk (Yên din)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Zimanê Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Belarusî" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Zimanê Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengalî" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber (Yên din)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Zimanê Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Biharî" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Zimanê Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Zimanê Bînî" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Zimanê Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Zimanê Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (Yên din)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnayî" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Zimanê Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Zimanê Breton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Endonezya)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriatî" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugînî" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarî" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Zimanê Burmese" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Zimanê Blinî" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Zimanê Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +#, fuzzy +msgid "Central American Indian (Other)" +msgstr "Dravîdî (Yên din)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Zimanê Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalan" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucasian (Yên din)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Zimanê Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Seltîk (Yên din)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Zimanê Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Zimanê Çibça" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Çeçenî" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Zimanê Çaxatay" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Çînî" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Zimanê Çukezî" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Marî" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Zimanê Çînok Cargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Çoktawî" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Çipewyanî" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Çerokî" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Silavîka Dêrê" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Çuvaşî" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Çeyenî" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Zimanên Çamîk" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Kiptî" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornişî" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsîkî" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Zimanê Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tatarî ya Kirimî" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +#, fuzzy +msgid "Creoles and Pidgins (Other)" +msgstr "Dravîdî (Yên din)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kaşûbî" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Kûştîk (Yên din)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Çekî" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Zimanê Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danîmarkî" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Zimanê Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Zimanê Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Zimanê Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Zimanê Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Zimanê Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Zimanê Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehî" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Zimanê Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravîdî (Yên din)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Sorbiya Jêrîn" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Zimanê Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Felemenkî, Navîn (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Felemenkî" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Zimanê Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Zimanê Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Misirî (Kevn)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Zimanê Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Zimanê Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Îngilîzî" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Îngilîzî, Navîn (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonî" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Zimanê Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Zimanê Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Zimanê Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Zimanê Faeroese" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Zimanê Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Zimanê Fijian" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Zimanê Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Fînikî" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finno-Ugrian (Yên din)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Zimanê Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Frensî" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Frensî, Navîn (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Frensî, Kevn (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Zimanê Frisian" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Zimanê Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulyan" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Zimanê Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Zimanê Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Zimanê Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Almanîkî (Yên din)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Gurcî" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Almanî" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Zimanê Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Zimanê Gilbertese" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelî" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Îrlandî" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Zimanê Galisî" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Zimanê Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Almanî, Navîn Bilind (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Almanî, Kevn Bilind (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Zimanê Gondî" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Zimanê Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotîk" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Zimanê Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grekî, Kevnare (heta 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grekî, Nûjen (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guaranî" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gucaratî" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Zimanê Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Zimanê Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Zimanê Haitian" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Zimanê Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawayî" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Îbranî" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Zimanê Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Zimanê Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Zimanê Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindî" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hîtîtî" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Zimanê Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Zimanê Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Zimanê Sorbiana Jorîn" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Macarî" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Zimanê Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Zimanê Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Zimanê Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Zimanê Îzlandî" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Zimanê Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Zimanê Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Zimanê Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Zimanê Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Zimanê Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Zimanê Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Hîndîk (Yên din)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Endonezî" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Hîndo-Ewropa (Yên din)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Zimanê Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Zimanê Inupiak" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Îranî (Yên din)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Zimanên Iraqî" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Îtalyanî" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Cavanezî" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Zimanê Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonî" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Cudî-Farsî" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Cudî-Erebî" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Zimanê Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Zimanê Kabîl" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Zimanê Kaçîn" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Zimanê Kalaallîsut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Zimanê Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannadî" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Zimanê Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kaşmîrî" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanurî" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Zimanê Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Qazaxî" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Zimanê Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Zimanê Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Xosî (Yên din)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Kamboçî" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Xotanezî" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyuyî" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Zimanê Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Qirxizî" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Zimanê Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Zimanê Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komî" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongoyî" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreyî" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosranî" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Zimanê Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karaçay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Zimanê Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Zimanê Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyamî" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Zimanê Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdî" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Zimanê Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Zimanê Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Zimanê Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Zimanê Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Zimanê Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latîn" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvianî" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Zimanê Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Ziman Liburgianisch" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Zimanê Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lîtwanî" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Zimanê Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Zimanê Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgişî" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Zimanê Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Zimanê Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganga" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Zimanê Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Zimanê Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Zimanê Luo (Kenya û Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Zimanê Luşayî" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonî" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurezî" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Zimanê Magahî" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Zimanê Marshallesisch" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maratî" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Zimanê Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Zimanê Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Zimanê Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maorî" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Awustranezî (Yên din)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Maratî" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Zimanê Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Zimanê Malay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Zimanê Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Zimanê Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Zimanê Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Îrîşî, Navîn (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Zimanê Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Zimanê Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Zimanên Cur bi cur" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (Yên din)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Zimanê Malagasy" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Zimanê Maltese" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Zimanê Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipurî" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Zimanên Manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Zimanê Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Zimanê Moldavya" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolî" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Zimanê Mossî" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Zimanên Piranî" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +#, fuzzy +msgid "Munda languages" +msgstr "Zimanên Munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Zimanê Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandezî" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwarî" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Zimanên Mayan" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Zimanê Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Zimanê Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +#, fuzzy +msgid "North American Indian" +msgstr "Amerîkaya Bakur" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitanî" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Zimanê Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Zimanê Ndebele, Başûr" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Zimanê Ndebele, Bakur" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Zimanê Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Almaniya Jêr" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Zimanê Nepal" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Zimanê Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Zimanê Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Nijer-Kordofanî (Yên din)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Zimanê Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norwecî ya Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norwecî ya Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Zimanê Nogaî" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norzî, Kevn" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norveçkî" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sothoya Bakurî" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Zimanên Nubian" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newariya Klasîk" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Zimanê Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezî" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Zimanê Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Zimanê Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Zimanê Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Ossetî (piştî 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Zimanê Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Zimanê Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Zimanê Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Zimanê Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osetî" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Tirkî, Osmanî (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Zimanên Osmanî" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuanî (Yên din)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangazînanî" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pehlevî" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Zimanê Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Pêncabî" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Zimanê Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Zimanê Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Farisî, Kevn (ca.600-400 P.Z)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Farsî" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Fîlîpînî (Yên din)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fonîcî" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Palî" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polonî" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Fonpeynî" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portekîzî" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Zimanên Prakrît" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provenkal, Kevn (heta 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Puşto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Zimanê Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Racastanî" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanûyî" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotonganî" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romanî (Yên din)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Reto-Romanî" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romî" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romanî" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundî" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rûsî" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sazndawî" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Zimanê Sangro" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakutî" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +#, fuzzy +msgid "South American Indian (Other)" +msgstr "Îranî (Yên din)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Zimanên Salîşî" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Zimanê Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Sirpkî" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +#, fuzzy +msgid "Sicilian" +msgstr "Friulyan" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Zimanê Xirwatî" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +#, fuzzy +msgid "Semitic (Other)" +msgstr "Seltîk (Yên din)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +#, fuzzy +msgid "Irish, Old (to 900)" +msgstr "Provenkal, Kevn (heta 1500)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "Zimanên Salîşî" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +#, fuzzy +msgid "Shan" +msgstr "Şangay" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sînhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Zimanên Salîşî" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +#, fuzzy +msgid "Sino-Tibetan (Other)" +msgstr "Finno-Ugrian (Yên din)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +#, fuzzy +msgid "Slavic (Other)" +msgstr "Baltîk (Yên din)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakî" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenî" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +#, fuzzy +msgid "Southern Sami" +msgstr "Samî ya Bakurî" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Samî ya Bakurî" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "Zimanên Çamîk" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Zimanê Samoan" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +#, fuzzy +msgid "Skolt Sami" +msgstr "Samî ya Bakurî" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Zimanê Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Zimanê Sind" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Zimanê Somalî" + +#. language code: son +#: zypp/LanguageCode.cc:985 +#, fuzzy +msgid "Songhai" +msgstr "Şangay" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Zimanê Sesotho" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spanî" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Zimanê Sardinisch" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +#, fuzzy +msgid "Serer" +msgstr "Zimanê Herero" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +#, fuzzy +msgid "Nilo-Saharan (Other)" +msgstr "Finno-Ugrian (Yên din)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swatî" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sudanî" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +#, fuzzy +msgid "Sumerian" +msgstr "Asturî" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Zimanê Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Swêdî" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Asûrî" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Zimanê Tahitî" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +#, fuzzy +msgid "Tai (Other)" +msgstr "Baltîk (Yên din)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamîlî" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatarî" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Zimanê Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajikî" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalogî" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tayî" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tîbetî" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Zimanê Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +#, fuzzy +msgid "Tiv" +msgstr "Zimanê Twi" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingonî" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +#, fuzzy +msgid "Tonga (Nyasa)" +msgstr "Zimanê Tonga (Giravên Toga)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Zimanê Tonga (Giravên Toga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Zimanê Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Zimanê Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Tirkmenî" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "Zimanên Nubian" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Tirkî" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +#, fuzzy +msgid "Altaic (Other)" +msgstr "Baltîk (Yên din)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Zimanê Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritikî" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Zimanê Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukraynî" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +#, fuzzy +msgid "Umbundu" +msgstr "Zimanê Kimbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Zimanê Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Ozbekî" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +#, fuzzy +msgid "Vai" +msgstr "Derbasdar" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Zimanê Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamî" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "Zimanên Salîşî" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Zimanê Welş" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "Zimanên Nubian" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walloonî" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolofî" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosî" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +#, fuzzy +msgid "Yao" +msgstr "Zimanê Lao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Eskenazî" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Zimanê Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "Zimanên Nubian" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zimanê Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zimanê Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "Bikarhêner tuneye." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "Bikarhêner tuneye." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "nenas" + +#: zypp/VendorSupportOptions.cc:17 +#, fuzzy +msgid "unsupported" +msgstr "Piştgirî" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +#, fuzzy +msgid "invalid" +msgstr "URL ya nederbasdar" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +#, fuzzy +msgid "Unknown support option. Description not available" +msgstr "tu rave tuneye " + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Servîsa '%1' nayê zanîn " + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Derbirîna bi Pergal(an)" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "Pelrêç nayê afirandin" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, fuzzy, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Di nivîsandina pela '%1' de çewtî çêbû" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "%1$s Biafirîne" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +#, fuzzy +msgid "Unhandled repository type" +msgstr "Çavkaniyê &Çalak Bike" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, fuzzy, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Arşîva %1 tê Afirandin" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Pela '%1' nayê vekirin" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Nekarî pelrêça '%1' biafirîne." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Arşîvan Rake" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Bi rastî bila '%1' jê bibe?" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "Arşîv nederbasdar e." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Bila bidomîne?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "Nivîsandina mîhengan têk çû" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "Çavkanî hilbijêre." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "Pelrêç nayê afirandin" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "Pakêtên nakokiyên wan hene" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +#, fuzzy +msgid "unsupported request" +msgstr "Piştgirî" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +#, fuzzy +msgid "Installation has been aborted as directed." +msgstr "Sazkirina di nav Pelrêç de" + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "Bixebitîne" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "Nivîsandina mîhengan têk çû" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Veavakirina IrDA biguherîne" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "Zêdetir vebijark" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Pel nehat dîtin." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Pel nehat dîtin." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Pel nehat dîtin." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "%s nehat vebûn." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Pela %1 nayê vekirin" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +#, fuzzy +msgid "Unable to clone Url object" +msgstr "&Venebû" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +#, fuzzy +msgid "Unable to parse Url components" +msgstr "&Venebû" + +#: zypp-core/base/Exception.cc:186 +#, fuzzy +msgid "History:" +msgstr "Pelrêça Mal:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, fuzzy, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Vebijêrka nederbasdar: %1" + +#: zypp-core/url/UrlBase.cc:247 +#, fuzzy, c-format, boost-format +msgid "Invalid %s component" +msgstr "Vebijêrka nederbasdar: %1" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +#, fuzzy +msgid "Url scheme is a required component" +msgstr "Navê bikarhêner pêwist e" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, fuzzy, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Vebijêrka nederbasdar: %1" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, fuzzy, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Vebijêrka nederbasdar: %1" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "%s nehat vebûn." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Jibergirtina %s pêk nehat." + +#: zypp-media/mediaexception.cc:48 +#, fuzzy, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Navê &pelê:" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Pakêta %1 derdorê nehat dîtin." + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Pela '%1' nayê vekirin" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, fuzzy, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Demê afirandina arşîvê de çewtiyek çêbû." + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +#, fuzzy +msgid "Cannot eject any media" +msgstr "Nikare cîhazan bibîne." + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Nikare cîhazan bibîne." + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Erê" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Na" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Hişyarî:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Çewtî" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "done" +msgstr "Endonezya" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "Çewtî" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Hişyarî:" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +#, fuzzy +msgid "Retrieving:" +msgstr "Tê rakirin" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Mîheng" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Tu nehat dîtin" + +#: zypp-tui/output/OutNormal.cc:421 +#, fuzzy +msgid "No help available for this prompt." +msgstr "Tu alîkarî tune ye." + +#: zypp-tui/output/OutNormal.cc:438 +#, fuzzy +msgid "no help available for this option" +msgstr "Tu alîkarî tune ye" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "erê" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "na" + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "Sazkirina pakêtên hewce pêk nehat." + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Pela %1 tune ye. " + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "Saz neke" + +#, fuzzy +#~ msgid "do not install %s" +#~ msgstr "Saz neke" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "Sazkirina nivîsbariyê" + +#, fuzzy +#~ msgid "do not install most recent version of %s" +#~ msgstr "Ji bo nû ve sazkirina guhertoya cuda" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "kêmkirin" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Moda Sazkirinê" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Pela %1 nayê vekirin" + +#, fuzzy +#~ msgid "Hal Exception" +#~ msgstr "Salix" + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "(negirêdayî)" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "Nekarî pelrêça '%1' biafirîne." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "Saz neke" + +#, fuzzy +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "Demê afirandina arşîvê de çewtiyek çêbû." + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Daxistina delta RPM têk çû: %1" diff --git a/po/lt.po b/po/lt.po new file mode 100644 index 0000000..2e2d094 --- /dev/null +++ b/po/lt.po @@ -0,0 +1,5552 @@ +# translation of zypp.po to lietuvių +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2000, 2001 SuSE GmbH. +# +# Jonas Gocentas , 2001. +# Linas Spraunius , 2000. +# Andrius Štikonas , 2006, 2007. +# Mindaugas Baranauskas , 2009, 2010, 2011, 2013, 2014, 2015, 2016. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-05-16 08:46+0000\n" +"Last-Translator: Mindaugas Baranauskas \n" +"Language-Team: Lithuanian \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: Weblate 5.5.5\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Nežinoma šalis: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Nėra kodo" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andora" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Jungtiniai Arabų Emyratai" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistanas" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antikva ir Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Angilija" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanija" + +# AM +# fuzzy +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armėnija" + +# AN +# fuzzy +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Olandijos Antilai" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarkika" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +# fuzzy +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Šiaurės Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austrija" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australija" + +# CU +# fuzzy +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Alandų salos" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaidžanas" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnija ir Hercogovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbadosas" + +# BD +# fuzzy +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladešas" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgija" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Fasas" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgarija" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahreinas" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundis" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Beninas" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudų" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunėjus Darusalamas" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivija" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazilija" + +# BS +# fuzzy +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamai" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Butanas" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Buvė sala" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botsvana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Gudija" + +# BZ +# fuzzy +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belizas" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosų (Kilingo) salos" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongas" + +# CF +# fuzzy +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Centrinės Afrikos Respublika" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Šveicarija" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Dramblio kaulo krantas" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Kuko salos" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Čilė" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerūnas" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kinija" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbija" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kosta Rika" + +# CU +# fuzzy +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Žaliasis kyšulys" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Kalėdų sala" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Kipras" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Čekijos Respublika" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Vokietija" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Džibutis" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danija" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikos respublika" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alžyras" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvadoras" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estija" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egiptas" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Vakarų Sachara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrėja" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Ispanija" + +# ET +# fuzzy +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopija" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Suomija" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Folklandų salos (Malvinai)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikronezijos Federacinės Valstijos" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Farerų salos" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Prancūzija" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Žemyninė Prancūzija" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabonas" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Jungtinė Karalystė" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gruzija" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Prancūzų Gviana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "" + +# GH +# fuzzy +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltaras" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grenlandija" + +# GM +# fuzzy +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambija" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Gvinėja" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Gvadelupa" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Pusiaujo Gvinėja" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Graikija" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Pietų Džordžija ir Pietų Sandvičo salos" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Gvatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guamas" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Bisau Gvinėja" + +# GH +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Gajana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Honkongas" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Herdo sala ir Makdonaldo salos" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Hondūras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatija" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haitis" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Vengrija" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonezija" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Airija" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izraelis" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Meno Sala" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indija" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britanijos teritorijos Indijos vandenyne" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irakas" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iranas" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islandija" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italija" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Džersis" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaika" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordanija" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonija" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenija" + +# KZ +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgiztanas" + +# KH +# fuzzy +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodža" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribatis" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komorai" + +# KN +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Sent Kitsas ir Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Šiaurės Korėja" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Pietų Korėja" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuveitas" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kaimanų salos" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazachstanas" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laoso Liaudies Demokratinė Respublika" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanas" + +# LC +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Lichtenšteinas" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Šri Lanka" + +# LR +# fuzzy +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberija" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotas" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lietuva" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Liuksemburgas" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvija" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libija" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokas" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monakas" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Juodkalnija" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Sent Martinas" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskaras" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Maršalo salos" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonija" + +# ML +# fuzzy +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Malis" + +# MM +# fuzzy +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mianmaras" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolija" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Šiaurės Marianų salos" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinika" + +# MR +# fuzzy +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritanija" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montseratas" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauricijus" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldyvai" + +# MW +# fuzzy +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malavis" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksika" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaizija" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambikas" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibija" + +# NC +# fuzzy +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Naujoji Kaledonija" + +# NG +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Nigeris" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolko salos" + +# NG +# fuzzy +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigerija" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragva" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Olandija" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norvegija" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepalas" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niujė" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Naujoji Zelandija" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omanas" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Prancūzų Polinezija" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Naujoji Gvinėja" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipinai" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistanas" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Lenkija" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Sen Pjeras ir Mikelonas" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Riko" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestinos teritorija" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugalija" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paragvajus" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Kataras" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunionas" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumunija" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbija" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Rusijos Federacija" + +# RW +# fuzzy +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudo Arabija" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Saliamono salos" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seišeliai" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudanas" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Švedija" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapūras" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Šv. Elenos sala" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovėnija" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbardas ir Jan Mayenas" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakija" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Siera Leonė" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marinas" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegalas" + +# SO +# fuzzy +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalis" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinamas" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "San Tomė ir Prinsipė" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Salvadoras" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Sirija" + +# SZ +# fuzzy +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Svazilandas" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Terkso ir Kaiko salos" + +# TD +# fuzzy +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Čadas" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Prancūzų pietinės teritorijos" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togas" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tailandas" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistanas" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmėnistanas" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisas" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tongas" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Rytų Timoras" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkija" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidadas ir Tobagas" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +# TW +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taivanis" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzanija" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +# UG +# fuzzy +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +# fuzzy +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Jungtinės Valstijos Mažosios Užjūrio Teritorijos" + +# US +# fuzzy +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Jungtinės Amerikos Valstijos" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Urugvajus" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistanas" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Šventasis Sostas (Vatikano miestas valstybė)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Šv. Vincentas ir Grenadinai" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venesuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britanijos Mergelių salos" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Suomija" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnamas" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Valis ir Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemenas" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Majotas" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Pietų Afrika" + +# ZM +# fuzzy +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambija" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabvė" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Pateikia" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Pirmiau reikalauja" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Reikalauja" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Konfliktuoja" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Pasenę" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Pataria" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Siūlo" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Pagerina" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Papildo" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Mėginta importuoti neegzistuojantį raktą %s į raktinę %s" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Nepavyko įkelti viešojo rakto %1%" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Rakto nepavyko pašalinti." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Parašo rinkmena %s nerasta" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Nežinoma kalba: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afarų" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abchazų" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Aziatų (Kita)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Būrų" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainų" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akanų" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akadų" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanų" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutų" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Pietų Altajaus" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharų" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Anglų, Senoji (apie 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apačių kalbos" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabų" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramėjų" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armėnų" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Mapudungunų" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Dirbtinė (kita)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Asamų" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturianų" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australijos kalbos" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaidžaniečių" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Baškirų" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balio" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskų" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltų (Kita)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beža" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Gudų" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengalų" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berberų (Kita)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (kita)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnių" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonų" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonezija)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Bugi" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarų" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birmiečių" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Centrinės Amerikos indėnų (Kita)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Karibų" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalonų" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukazo (kita)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltų (Kita)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamoro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Čečėnų" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kinų" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +# ML +# fuzzy +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Čerokių" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Bažnytinė slavų" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Čiuvašų" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Šajenas" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptų" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Kornų" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsikiečių" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreolai ir pidginai, anglų k. pagrindu (kiti)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreolai ir pidginai, prancūzų k. pagrindu (kiti)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreolai ir pidginai, portugalų k. pagrindu (kiti)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krymo totorių" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreolai ir pidginai (kiti)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kašubų" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Čekų" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danų" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Deleveras" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidų (kita)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Olandų, Vidurinioji (apie 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Olandų" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egipto (Senovės)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Anglų" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Anglų, Vidurinioji (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estų" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Farerų" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fidži" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipinų" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Suomių" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fino-Ugrų (Kita)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Prancūzų" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Prancūzų, Vidurinioji (apie 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Prancūzų, Senoji (842-apie 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Fryzų" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germanų (Kita)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Gruzinų" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Vokiečių" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gėlų" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Airių" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galų" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotų" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Graikų, senovės (iki 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Graikų, šiuolaikinė (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gudžarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haičio" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Havajiečių" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebrajų" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hetitų" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Vengrų" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Ibanų" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandų" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingua" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Tarptautinė pagalbinės kalbos asociacija)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indų (Kita)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indoneziečių" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoeuropiečių (Kita)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingušų" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iranėnų (kita)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokėzų kalbos" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italų" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javiečių" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonų" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Žydų-persų" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Žydų-arabų" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kačinų" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kašmyro" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakų" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Chmerų" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgizų" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korėjiečių" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdų" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laosiečių" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Lotynų" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvių" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lietuvių" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Liuksemburgiečių" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +# GH +# fuzzy +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenija ir Tanzanija)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lušai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonų" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurų" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Maršalų" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maitili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malajalių" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maorių" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marati" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malajų" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Mokša" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Airių, Vidurinioji (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Įvairios kalbos" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-chmerų (kita)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Madagaskaras" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltiečių" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo kalbos" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavų" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolų" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mosi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Kelios kalbos" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda kalbos" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Maruari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Majų kalbos" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Šiaurės Amerikos indėnų" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolio" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, Pietų" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, Šiaurės" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Žemutinė vokiečių" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepalo Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niujiečių" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norvegų Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norvegų Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norvegų, senovės" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norvegų" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Šiaurės Sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubiečių kalbos" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Orija" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osetų" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turkų Osmanų (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomų kalbos" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuasų (Kita)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palau" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persų, Senoji (apie 600-400 pr.m.e)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persų" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipinų (kita)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Finikiečių" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Lenkų" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugalų" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakritų kalbos" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pušto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Kečujų" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romanų (kita)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Reto romanų" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Čigonų" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumunų" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rusų" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandavų" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Jakutų" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Pietų Amerikos indėnų (Kita)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Saramiečių aramėjų" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrito" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbų" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilų" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Škotų" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroatų" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitų (Kita)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Airių, Senoji (iki 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Sign kalbos" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouan kalbos" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibeto (kita)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavų (Kita)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakų" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovėnų" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Pietų Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Šiaurės Sami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Sami kalbos (kita)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalių" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, Pietų" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Ispanų" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardiniečių" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Sererų" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Sacharos (kita)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Svati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sudaniečių" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Šumerų" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Svahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Švedų" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Sirų" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Taičio" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (kita)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamilų" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timnų" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadžikų" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalogų" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tajų" + +# TW +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibeto" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingonas" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamašekų" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tongas (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tongas (Tonga salos)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tsvana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmėnų" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi kalbos" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turkų" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altajaus (Kita)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Tvi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurtų" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritik" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighurų" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainiečių" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Nenurodyta" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbekų" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamo" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapukų" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votikų" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Vakašan kalbos" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Valamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Varėjų" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Vašo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Valų" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Valonų" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Volofo" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Jao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Japesų" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jidiš" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Joruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Jupikų kalbos" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotekų" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zandų" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Bus atlikti šie veiksmai:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "nesibaigiantis" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "baigėsi: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "baigiasi: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(galiojimas nepasibaigia)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(NEBEGALIOJA)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(baigsis per 24 valandas)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(baigsis po %d d.)" +msgstr[1] "(baigsis po %d d.)" +msgstr[2] "(baigsis po %d d.)" +msgstr[3] "(baigsis po %d d.)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "nežinoma" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nepalaikoma" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "1 lygis" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "2 lygis" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "3 lygis" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Reikalinga papildoma kliento sutartis" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Apleistas ir pakeistas kitu paketu" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "netinkama" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Palaikymo lygis nenurodytas" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Gamintojas nesuteikia palaikymo." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Problemos apibrėžimas, kuris reiškia techninį palaikymą, skirtą pateikti " +"suderinamumo informaciją, diegimo pagalbą, naudojimo palaikymą, atvykstančio " +"aptarnavimo ir pagrindinių nesklandumų šalinimo. 1 lygio palaikymas nesiekia " +"taisyti pačio produkto klaidų." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Problemos izoliavimas, kuris reiškia techninį palaikymą, skirtą dubliuoti " +"klientų problemas, izoliuoti problemos sritis ir pateikti problemų " +"sprendimus, kurių neišsprendė 1 lygio palaikymas." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Problemos sprendimas, kuris reiškia techninį palaikymą, skirtą spręsti " +"kompleksines problemas, užsiimant produkto defektais, tapatinamas su 2 lygio " +"palaikymu." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Norint gauti palaikymą, reikalinga papildoma kliento sutartis." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "Šis paketas apleistas, jį pakeitė kitas naujas paketas kitu vardu." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Nežinomo palaikymo parinktis. Aprašas neprieinamasq" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Sistemos tvarkytuvę užrakino programa, kurios pid %d (%s).\n" +"Užverkite šią programą ir bandykite iš naujo." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Nežinoma atitikmens veiksena „%s“" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Nežinoma atitikmens veiksena „%s“ šablonui „%s“" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Netinkamas reguliarusis reiškinys „%s“: regcomp grąžino %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Netinkamas reguliarusis reiškinys „%s“" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "%s reikalauja autentifikacijos" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Bandysima iš naujo..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Pasiduota po nesėkmingų bandymų (%1%)." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Apsilankykite SUSE klientų centre ir patikrinkite, ar jūsų registracija yra " +"tinkama ir galioja." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Apsilankykite Novell klientų aptarnavimo centre ir sužinosite, ar Jūsų " +"registracija dar nėra pasibaigusi." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Sukurti prijungimo vietą: nepavyksta prijungimo vietai rasti katalogo, " +"kuriame būtų galima rašyti" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Pirmiausia įdiekite „lsof“ paketą." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Nepavyko sukurti metaduomenų podėlio katalogo." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Klaida bandant nuskaityti „%s“" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Nepavyksta sukurti %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Nurodytu URL nerasta tinkamų meta duomenų" +msgstr[1] "Nurodytuose URL nerasta tinkamų meta duomenų" +msgstr[2] "Nurodytuose URL nerasta tinkamų meta duomenų" +msgstr[3] "Nurodytuose URL nerasta tinkamų meta duomenų" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Nepavyko įkelti į saugyklų podėlį (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Kuriamas saugyklos „%s“ podėlis" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Nepavyksta sukurti podėlio ties %s - nepakanka teisių." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Nesutvarkytas saugyklos tipas" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Pridedama saugykla „%s“" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Netinkamas saugyklos pavadinimas „%s“" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Nepavyksta atverti rinkmenos „%s“ įrašymui." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Nežinoma klaida skaitant iš „%s“" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Nepavyko perskaityti katalogo „%1%“: nepakanka leidimų" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Nepavyko nuskaityti katalogo „%s“" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Nepavyko perskaityti rinkmenos „%1%“: nepakanka leidimų" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Pašalinama saugykla „%s“" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Nepavyksta nustatyti, kur patalpinta ši saugykla" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Nepavyksta pašalinti „%s“" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Nepavyksta nustatyti, kur patalpinta ši paslauga" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Nežinoma paslauga „%1%“: pašalinama nebereikalinga paslaugų saugykla „%2%“" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Saugyklos pseudonimas negali prasidėti tašku." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Paslaugos pseudonimas negali prasidėti tašku." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Nėra %s rinkmenos santraukos." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Rinkmenai %s santrauka %s yra nežinoma." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Rinkmenos „%s“ santraukos patikrinimo klaida" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Rinkmena „%s“ nėra pasirašyta. Tęsti?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Rinkmena „%s“ iš „%s“ saugyklos nėra pasirašyta. Tęsti?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Atmesti raktą, raktu pasitikėti laikinai ar pasitikėti visada?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Rakto vardas: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "Iš „%2%“ saugyklos gautas %1% naujas paketų pasirašymo raktas:" +msgstr[1] "Iš „%2%“ saugyklos gauti %1% naujas paketų pasirašymo raktai:" +msgstr[2] "Iš „%2%“ saugyklos gauta %1% naujas paketų pasirašymo raktai:" +msgstr[3] "Iš „%2%“ saugyklos gautas %1% naujas paketų pasirašymo raktas:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Tęsti?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Rinkmena „%s“ iš „%s“ saugyklos pasirašyta nežinomu raktu „%s“. Tęsti?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Saugykla „%1%“ nenurodo papildomų „gpgkey=“ URL adresų." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "%2% saugykloje ieškoma GPG rakto su ID %1%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "%2% padėlyje ieškoma GPG rakto su ID %1%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Trūksta reikiamo atributo „%s“." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Reikia vieno ar abiejų, „%s“ ar „%s“ atributų." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Nepavyko patikrinti parašo" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Regis paketas %s buvo sugadintas perdavimo metu. Ar norėtumėte jį gauti iš " +"naujo?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Nepavyko pateikti paketo %s. Ar norėtumėte bandyti jį gauti iš naujo?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm patikrinti nepavyko." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm nepavyko." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Paslaugos papildinys nepalaiko atributų keitimo." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Nepavyksta pateikti rinkmenos „%s“ iš saugyklos „%s“" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Saugykloje nėra url." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Tikėtasi rasti laikmeną %1%/%2%, kuri identifikuojama pagal rinkmeną „%3%“ " +"su turiniu:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Rinkmena %1% ,\n" +" esanti pakete\n" +" %2% ,\n" +" konfliktuoja su rinkmena, esančia pakete\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Rinkmena %1%\n" +" iš paketo\n" +" %2%\n" +" konfliktuoja su rinkmena iš\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Rinkmena %1%\n" +" iš\n" +" %2%\n" +" konfliktuoja su rinkmena iš paketo\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Rinkmena %1%\n" +" iš\n" +" %2%\n" +" su rinkmena iš\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Rinkmena %1%\n" +" iš paketo\n" +" %2%\n" +" konfliktuoja su rinkmena\n" +" %3%\n" +" iš paketo\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Rinkmena %1%\n" +" iš paketo\n" +" %2%\n" +" konfliktuoja su rinkmena\n" +" %3%\n" +" iš\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Rinkmena %1%\n" +" iš\n" +" %2%\n" +" konfliktuoja su rinkmena\n" +" %3%\n" +" iš paketo\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Rinkmena %1%\n" +" iš\n" +" %2%\n" +" konfliktuoja su rinkmena\n" +" %3%\n" +" iš\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "nepaisyti kai kurių priklausomybių ir taip sugadinti %s " + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "apskritai ignoruoti kai kurias priklausomybes" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"įdiegtasis %1% nepriklauso „distupgrade“ saugyklai ir jį būtina pakeisti" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "įdiegtinas %1% nepriklauso „distupgrade“ saugyklai" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "įdiegtasis %1% yra žemesnės architektūros" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "įdiegtinas %1% yra žemesnės architektūros" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "nesklandumai su įdiegtu %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "konfliktuojantys reikalavimai" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "kai kurių priklausomybių problema" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "niekas nepateikia prašomo „%1%“" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Ar įgalinote visas reikalingas saugyklas?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "nepavyko rasti prašomo %1% paketo" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "nepalaikoma užklausa" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "kadangi sistema pateikia „%1%“, tad jo pašalinti negalima" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% neįmanoma įdiegti" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "niekas nepateikia „%1%“, kuris reikalingas įdiegtam %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "niekas nepateikia „%1%“, kuris reikalingas įdiegtinam %2%" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "negalima %1% ir %2% vienu metu" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "įdiegtasis %1% konfliktuoja su %2%, kurį pateikia įdiegtasis %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "įdiegtasis %1% konfliktuoja su %2%, kurį pateikia įdiegtinas %3%" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "įdiegtinasis %1% konfliktuoja su %2%, kurį pateikia įdiegtasis %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "įdiegtinasis %1% konfliktuoja su „%2%“, kurį pateikia įdiegtinasis %3%" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "įdiegtasis %1% pakeičia pasenusį „%2%“, kurį pateikė įdiegtasis %3%" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "įdiegtasis %1% pakeičia pasenusį „%2%“, kurį pateikia įdiegtinasis %3%" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "įdiegtinasis %1% pakeičia pasenusį „%2%“, kurį pateikė įdiegtasis %3%" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"įdiegtinasis %1% pakeičia pasenusį „%2%“, kurį pateikia įdiegtinasis %3%" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "įdiegtasis %1% konfliktuoja su „%2%“, kurį jis pats pateikia" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "įdiegtinasis %1% konfliktuoja su „%2%“, kurį jis pats pateikia" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"įdiegtasis %1% reikalauja „%2%“, bet šio reikalavimo neįmanoma patenkinti" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"įdiegtinasis %1% reikalauja „%2%“, bet šio reikalavimo neįmanoma patenkinti" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "pašalinti galimi pasiūlymai: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"netinkami įdiegti pasiūlymai: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "netinkami diegimui pasiūlymai: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% dar nėra pilnai suderinamas su %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Norimo veiksmo atlikti neleidžia įdiegtasis %1%." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "atrakinti ir leisti pašalinti %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "neįdiegti %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "išlaikyti %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "atrakinti ir leisti įdiegti %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Šis veiksmas sugadins jūsų sistemą!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "nepaisyti perspėjimų apie riziką sugadinti sistemą" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "nesiūlyti įdiegimo sprendimo, kuris pateikia %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "nesiūlyti pašalinimo sprendimų, kurie pateikia %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "nediegti naujausios %1% versijos" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "išlaikyti %1% nepaisant žemesnės architektūros" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "įdiegti %1% nepaisant žemesnės architektūros" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "išlaikyti pasenusį %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "įdiegti %1% iš neįtrauktos saugyklos" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "įdiegti %1%, nors jis atšauktas" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "įdiegti %1%, nors jis yra juodajame sąraše" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "%1% pakeisti senesniu %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "%1% architektūros pakeitimas į %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"įdiegti %1% (keičiant gamintoją)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"įdiegti %1% iš gamintojo %2%\n" +" pakeičiant %3% iš gamintojo %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "pakeisti %1% į %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "pašalinti %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Vykdomi potransakciniai scenarijai" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Vykdomas %1% scenarijus" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "%1% scenarijus grąžino:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Diegimas buvo nutrauktas pagal nurodymą." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " įvykdyta" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " įvykdyti nepavyko" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s jau įvykdytas kaip %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " nutraukiant vykdymas sustabdytas" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Siunčiant atnaujinimo pranešimą įvyko klaida." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Naujas atnaujinimo pranešimas" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Transakcijos atlikti nepavyko, iškilo nesklandumų:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM klaida:" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Nepavyko įkelti viešojo rakto %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Nepavyko pašalinti viešojo rakto %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Pakeistos %s konfigūracijos rinkmenos:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm išsaugojo %s kaip %s, bet neįmanoma nustatyti skirtumo" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm išsaugojo %s kaip %s.\n" +"Pateikiamos pirmosios 25 skirtumų eilutės:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm sukūrė %s kaip %s, bet neįmanoma nustatyti skirtumo" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm sukūrė %s kaip %s.\n" +"Pateikiamos pirmosios 25 skirtumų eilutės:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Papildoma rpm išvestis" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "padaryta %s atsarginė kopija" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Parašas geras" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Nežinomo tipo parašas" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Parašas nepatikrinamas. " + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Parašas geras, bet raktas nepatikimas" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Paašo viešasis raktas neprieinamas" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Nėra rinkmenos arba negalima patikrinti parašo" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Rinkmena nepasirašyta" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Abejotinas tipas „%s“, skirtas %u bitų kontrolinei santraukai „%s“" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Nepavyksta atverti pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Nepavyksta atverti kanalo (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Netinkama LDAP URL užklausos eilutė" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Netinkamas LDAP URL užklausos parametras „%s“" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Nepavyksta klonuoti Url objekto" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Netinkama tuščio URL objekto nuoroda" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Nepavyksta išnagrinėti Url komponentų" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Istorija:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url schema neleidžia %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Netinkamas %s komponentas „%s“" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Netinkamas %s komponentas" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Užklausos eilutės nagrinėjimas nepalaikomas šiam URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url schema yra reikalingas komponentas" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Netinkama Url schema „%s“" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url schema neleidžia naudotojo vardo" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url schema neleidžia slaptažodžio" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url schemai reikia kompiuterio komponento" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url schema neleidžia kompiuterio komponento" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Netinkamas kompiuterio komponentas „%s“." + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url schema neleidžia prievado" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Netinkamas prievado komponentas „%s“" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url schema reikalauja kelio pavadinimo" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Santykinis kelias neleidžiamas, jei naudojamas tapatybės nustatymas" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Komanda baigta būsenoje %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Komanda nutraukta naudojant signalą %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Komanda pasibaigė su nežinoma klaida." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Nepavyksta keisti pakeisti aplanko į „%s“ (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Nepavyksta įvykdyti „%s“ (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Nepavyko įvykdyti „%s“ (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Nepavyko įvykdyti „%s“, netikėta klaida." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Nepavyko prijungti %s prie %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Nepavyko atjungti %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Netinkamas rinkmenos pavadinimas: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Laikmena nebuvo atidaryta, kai bandyta atlikti veiksmą „%s“." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Rinkmena „%s“ nerasta laikmenoje „%s“" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Nepavyksta įrašyti rinkmenos „%s“." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Laikmena neįdėta" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Netinkama laikmenos prijungimo vieta" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "„%s“ parsiuntimo (curl) iniciacijuoti nepavyko.." + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Sistemos išimtis „%s“ laikmenoje „%s“." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Kelias „%s“ laikmenoje „%s“ nėra rinkmena." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Kelias „%s“ laikmenoje „%s“ nėra katalogas." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Blogai suformuluotas URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Tuščias pagrindinio kompiuterio vardas URL adrese" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "URL adrese tuščia rinkmenų sistema" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "URL adrese tuščia paskirtis" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Nepalaikoma URL schema „%s“." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Laikmena nepalaiko šios operacijos" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"„%s“ parsiuntimo (curl) klaida:\n" +"Klaidos kodas: %s\n" +"Klaidos pranešimas: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Laikmenos šaltinis „%s“ neturi norimos laikmenos" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Laikmeną „%s“ naudoja kita programa" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Nepavyksta išmesti jokios laikmenos" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Nepavyksta išmesti laikmenos „%s“" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Priėjimas prie „%s“ uždraustas." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Per ilgai jungiamasi prie „%s“." + +#: zypp-media/mediaexception.cc:197 +#, fuzzy, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Parsisiųstų duomenų dydis viršijo manytą rinkmenos dydį „%s“ iš „%s“." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Vieta „%s“ laikinai nepasiekiama." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" SSL liudijimo problema, patikrinkite liudijimų įstaigos tvarkingumą „%s“." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Nėra laisvų išteklių pridėtoje laikmenoje." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Nepalaikomas HTTP tapatybės nustatymo būdas „%s“" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Klaida su curl parsisiunčiant „%s“:\n" +"Klaidos kodas: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Klaida su curl parsisiunčiant „%s“:\n" +"Nepavyko gauti HTTP atsako\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Taip" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ne" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Pastaba:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Įspėjimas:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Klaida:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "atlikta" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "dėmesio" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "klaida" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Įspėjimas: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Gaunama:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "paleidžiama" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "nerasta" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Čia pagalba neprieinama." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "šiaip parinkčiai paaiškinimo nėra" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "rodyti visas parinktis" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "taip" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ne" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "" +#~ "%s nepriklauso platinamojo paketo naujovinimo (distupgrade) saugyklai" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s yra kitos architektūros" + +#~ msgid "problem with installed package %s" +#~ msgstr "problema su įdiegtu paketu %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "niekas nepateikia reikalaujamo %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Ar įgalinote visas reikiamas saugyklas?" + +#~ msgid "package %s does not exist" +#~ msgstr "paketo %s nėra" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s pateikia sistema, jo negalima pašalinti" + +#~ msgid "%s is not installable" +#~ msgstr "%s neįdiegiamas" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "niekas nepateikia %s, kurio reikalauja %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "negalima įdiegti ir %s, ir %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s konfliktuoja su %s, kurį pateikia %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s pakeičia %s, kurį pateikė %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "įdiegtas %s pakeičia %s, kurį pateikė %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "sprendinys %s konfliktuoja su %s, kurį pats siūlo" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s reikalauja „%s“, bet reikalavimo negalima išpildyti" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "nedrausti pašalinti %s" + +#~ msgid "do not install %s" +#~ msgstr "neįdiegti %s" + +#~ msgid "keep %s" +#~ msgstr "išlaikyti %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "nedrausti įdiegti %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "neprašyti įdiegti sprendinių, kuriuos siūlo %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "neprašyti pašalinti visų sprendinių, kuriuos siūlo %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "neįdiegti pačios naujausios %s versijos" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "išlaikyti %s, nors yra kitos architektūros" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "įdiegti %s, nors yra kitos architektūros" + +#~ msgid "keep obsolete %s" +#~ msgstr "išlaikyti pasenusį %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "įdiegti %s iš neįtrauktos saugyklos" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "pasendinti nuo %s iki %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "pakeisti architektūrą iš %s į %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "įdiegti %s (keičiant gamintoją)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "%s pakeisti į %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "pašalinti %s " + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Nepavyksta atverti užrakintos rinkmenos: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Šį veiksmą jau paleido kita programa." + +#~ msgid "Hal Exception" +#~ msgstr "Hal išimtis" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Atleiskite, ši libzypp versija sukompiliuota su HAL palaikymu." + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Nepavyksta sukurti dbus ryšio" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Tai ne CD nuskaitymo įrenginys" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Nepavyko įkelti viešojo rakto iš rinkmenos %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Nepavyko pašalinti viešojo rakto %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Nepavyko rasti ciklinio įrenginio , prie kurio prijungtume atvaizdį iš " +#~ "„%s“" + +#~ msgid "do not keep %s installed" +#~ msgstr "nesistengti išlaikyti įdiegto %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "Nepavyksta sukurti viešojo rakto %s iš %s raktinės į rinkmeną %s" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Parsiuntimo pertrūkis ties %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Parsiuntimą nutraukė naudotojas" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Nepavyko parsiųsti %s iš %s" diff --git a/po/mk.po b/po/mk.po new file mode 100644 index 0000000..1725648 --- /dev/null +++ b/po/mk.po @@ -0,0 +1,5586 @@ +# Macedonian message file for YaST2 (@memory@). +# Copyright (C) 2006 SUSE Linux Products GmbH. +# Зоран Димовски +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2023-05-29 06:14+0000\n" +"Last-Translator: Kristijan Fremen Velkovski \n" +"Language-Team: Macedonian \n" +"Language: mk\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: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Непозната држава: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Без код" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Андора" + +# US +# fuzzy +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Соединети Американски Држави" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Афганистан" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Антигва и Барбуда" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Ангила" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Албанија" + +# AM +# fuzzy +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Арменија" + +# AN +# fuzzy +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Холандски Антили" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Ангола" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Антарктика" + +# AR +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Аргентина" + +# AS +# fuzzy +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Америчка Самоа" + +# AT +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Австрија" + +# AU +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Австралија" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Аруба" + +# FO +# fuzzy +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Оландски Острови" + +# AZ +# fuzzy +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Српски" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Босна и Херцеговина" + +# BB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Барбадос" + +# BD +# fuzzy +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Англиска" + +# BE +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Белгија" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Буркина Фасо" + +# BG +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Бугарија" + +# BH +# fuzzy +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Бразил" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Бурунди" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Бенин" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Бермуда" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Брунеј" + +# BO +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Боливија" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Бразил" + +# BS +# fuzzy +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Панама" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Бутан" + +# FO +# fuzzy +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Остров Буве" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Боцвана" + +# BY +# fuzzy +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Бретонски" + +# BZ +# fuzzy +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Белгија" + +# CA +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Канада" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Кокосови Острови" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Конго" + +# CF +# fuzzy +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Доминиканска Република" + +# CH +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Швајцарија" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Брег на Слоновата Коска" + +# FO +# fuzzy +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Кукови Острови" + +# CL +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Чиле" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Камерун" + +# CN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Кина" + +# CO +# fuzzy +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Колумбија" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Коста Рика" + +# CU +# fuzzy +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Колумбија" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Зелен ’Рт" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Божиќен Остров" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Кипар" + +# CZ +# fuzzy +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Доминиканска Република" + +# DE +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Германија" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Џибути" + +# DK +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Данска" + +# DM +# fuzzy +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Романија" + +# DO +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Доминиканска Република" + +# DZ +# fuzzy +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Бугарија" + +# EC +# fuzzy +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Еквадор" + +# EE +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Естонија" + +# EG +# fuzzy +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Енергија" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Западна Сахара" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Еритреја" + +# ES +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Шпанија" + +# ET +# fuzzy +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Естонија" + +# FI +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Финска" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Фиџи" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Фолкландските Острови (Малвини)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Сојузни Држави на Микронезија" + +# FO +# fuzzy +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Ирска" + +# FR +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Франција" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Метрополитна Франција" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Габон" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Обединето Кралство" + +# GD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Гренада" + +# GE +# fuzzy +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Србија" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Француска Гвајана" + +# DE +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Гернзи" + +# GH +# fuzzy +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Кина" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Гибралтар" + +# GL +# fuzzy +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Гренада" + +# GM +# fuzzy +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Јамајка" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Гвинеја" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Гваделуп" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Екваторска Гвинеја" + +# GR +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Грција" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Јужна Џорџија и Јужни Сендвички Острови" + +# GT +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Гватемала" + +# GU +# fuzzy +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Гватемала" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Гвинеја-Бисао" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Гвајана" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Хонгконг" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Остров Херд и Острови МекДоналд" + +# HN +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Хондурас" + +# HR +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Хрватска" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Хаити" + +# HU +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Унгарија" + +# ID +# fuzzy +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Икони" + +# IE +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ирска" + +# IL +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Израел" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Островот Ман" + +# IN +# fuzzy +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Икони" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Британска Индоокеанска Територија" + +# IQ +# fuzzy +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Израел" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Иран" + +# IS +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Исланд" + +# IT +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Италија" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Џерси" + +# JM +# fuzzy +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Јамајка" + +# JO +# fuzzy +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Корејски" + +# JP +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Јапонија" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Кенија" + +# KZ +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Киргистан" + +# KH +# fuzzy +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Камбодија" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Кирибати" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Комори" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Свети Кристофер и Невис" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Северна Кореја" + +# ZA +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Јужна Кореја" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Кувајт" + +# FO +# fuzzy +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Кајмански Острови" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Тајван" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Лаоска Народна Демократска Република" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Либан" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Света Луција" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Лихтенштајн" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Шри Ланка" + +# LR +# fuzzy +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Србија" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Лесото" + +# LT +# fuzzy +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Литвански" + +# LU +# fuzzy +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Луксембург" + +# LV +# fuzzy +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Хрватска" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Либија" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Мароко" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Монако" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Молдавија" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Црна Гора" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Свети Мартин" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Мадагаскар" + +# FO +# fuzzy +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Маршалски Острови" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Македонија" + +# ML +# fuzzy +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "KStep" + +# MM +# fuzzy +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Панама" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Монголија" + +# MO +# fuzzy +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "KStep" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Северните Маријански Острови" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Мартиник" + +# MR +# fuzzy +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Литвански" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Монтсерат" + +# MT +# fuzzy +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "KStep" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Литвански" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "KStep" + +# MW +# fuzzy +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "KStep" + +# MX +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Мексико" + +# MY +# fuzzy +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "KStep" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Мозамбик" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Намибија" + +# NC +# fuzzy +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Македонија" + +# NG +# fuzzy +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Нигер" + +# FO +# fuzzy +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Норфолшки Остров" + +# NG +# fuzzy +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Србија" + +# NI +# fuzzy +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Парагвај" + +# NL +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Холандија" + +# NO +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Норвешка" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Непал" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Науру" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Ниуе" + +# NZ +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Нов Зеланд" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Оман" + +# PA +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Панама" + +# PE +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Перу" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Француска Полинезија" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Папуа Нова Гвинеја" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Филипини" + +# TJ +# fuzzy +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Пакистан" + +# PL +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Полска" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +# PT +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Португалија" + +# PW +# fuzzy +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Палау" + +# PY +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Парагвај" + +# QA +# fuzzy +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "KStep" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "" + +# RO +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Романија" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Србија" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +# RW +# fuzzy +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Канада" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "" + +# FO +# fuzzy +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Соломонови Острови" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +# SD +# fuzzy +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Звук" + +# SE +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Шведска" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +# SI +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Словенија" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +# SK +# fuzzy +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Словачки" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +# SO +# fuzzy +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Романија" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +# SV +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Ел Салвадор" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +# SZ +# fuzzy +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Тајланд" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +# TD +# fuzzy +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Кина" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +# TH +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Тајланд" + +# TJ +# fuzzy +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Тајван" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +# TJ +# fuzzy +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Туркменистан" + +# TN +# fuzzy +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Русија" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +# TR +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Турција" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Тринидад и Тобаго" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "" + +# TW +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Тајван" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +# UA +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Украина" + +# UG +# fuzzy +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Канада" + +# UM +# fuzzy +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Соединетите Американски Држави" + +# US +# fuzzy +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Соединетите Американски Држави" + +# UY +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Уругвај" + +# TJ +# fuzzy +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Узбекистан" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +# VE +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Венецуела" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Британски Девствени Острови" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Американски Девствени Острови" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +# ZA +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Јужна Африка" + +# ZM +# fuzzy +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Јамајка" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Не успеа да се увезе клучот." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Не успеа да се избрише клучот." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Акинески" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Африкански" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Албански" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +# AU +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Алгонкиски јазици" + +# ZA +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Јужен Алтај" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +# AU +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Апачи јазици" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Арапски" + +# JM +# fuzzy +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Арамејски" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +# AM +# fuzzy +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Ерменски" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Араукански" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +# AU +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Атапаскански јазици" + +# AU +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Австралиски јазици" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +# AZ +# fuzzy +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Азербејџански" + +# RW +# fuzzy +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Банда" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +#, fuzzy +msgid "Balinese" +msgstr "Кинески" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Баскиски" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +# BY +# fuzzy +#. language code: bel be +#: zypp/LanguageCode.cc:259 +#, fuzzy +msgid "Belarusian" +msgstr "Бретонски" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +#, fuzzy +msgid "Bosnian" +msgstr "Естонски" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Бретонски" + +# ID +# fuzzy +#. language code: btk +#: zypp/LanguageCode.cc:287 +#, fuzzy +msgid "Batak (Indonesia)" +msgstr "Икони" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +#, fuzzy +msgid "Buginese" +msgstr "Кинески" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Бугарски" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Кинески" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +# AU +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "Австралија" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +#, fuzzy +msgid "Cornish" +msgstr "Дански" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Чешки" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Дански" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +#, fuzzy +msgid "Lower Sorbian" +msgstr "Српски" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +#, fuzzy +msgid "English" +msgstr "Полски" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Есперанто" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Естонски" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +# FO +# fuzzy +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +#, fuzzy +msgid "Faroese" +msgstr "Ирска" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Фински" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Француски" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +# GU +# fuzzy +#. language code: gaa +#: zypp/LanguageCode.cc:459 +#, fuzzy +msgid "Ga" +msgstr "Гватемала" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +# GE +# fuzzy +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +#, fuzzy +msgid "Georgian" +msgstr "Србија" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Германски" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Ирски" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "Хрватски" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Еврејски" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +#, fuzzy +msgid "Upper Sorbian" +msgstr "Српски" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Унгарски" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Исландски" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +# LT +# fuzzy +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "Литвански" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +# ID +# fuzzy +#. language code: ind id +#: zypp/LanguageCode.cc:565 +#, fuzzy +msgid "Indonesian" +msgstr "Икони" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +# AU +#. language code: iro +#: zypp/LanguageCode.cc:575 +#, fuzzy +msgid "Iroquoian Languages" +msgstr "Австралија" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Италијански" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +#, fuzzy +msgid "Javanese" +msgstr "Јапонски" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Јапонски" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +#, fuzzy +msgid "Judeo-Arabic" +msgstr "Арапски" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +# CA +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +#, fuzzy +msgid "Kannada" +msgstr "Канада" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +#, fuzzy +msgid "Kazakh" +msgstr "Тајван" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +#, fuzzy +msgid "Khotanese" +msgstr "Кинески" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Корејски" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "" + +# LV +# fuzzy +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +#, fuzzy +msgid "Latvian" +msgstr "Хрватска" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Литвански" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +# LU +# fuzzy +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "Луксембург" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +# RW +# fuzzy +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +#, fuzzy +msgid "Ganda" +msgstr "Канада" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "Таи" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Македонски" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +# MY +# fuzzy +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +#, fuzzy +msgid "Malayalam" +msgstr "KStep" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Маорски" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +# MY +# fuzzy +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "KStep" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +# RW +# fuzzy +#. language code: mdr +#: zypp/LanguageCode.cc:729 +#, fuzzy +msgid "Mandar" +msgstr "Канада" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +# AU +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "Австралија" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +# MY +# fuzzy +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "KStep" + +# MT +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +#, fuzzy +msgid "Maltese" +msgstr "KStep" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +# AU +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "Австралија" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +# AU +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "Австралија" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +# AU +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "Австралија" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "Германски" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +# NO +#. language code: nor no +#: zypp/LanguageCode.cc:811 +#, fuzzy +msgid "Norwegian" +msgstr "Норвешка" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "" + +# AU +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "Австралија" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +# AU +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "Австралија" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +# PW +# fuzzy +#. language code: pau +#: zypp/LanguageCode.cc:857 +#, fuzzy +msgid "Palauan" +msgstr "Парагвај" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Полски" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Португалски" + +# AU +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "Австралија" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +# JP +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "Јапонија" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +# RO +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "Романија" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Романски" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Руски" + +# RW +# fuzzy +#. language code: sad +#: zypp/LanguageCode.cc:905 +#, fuzzy +msgid "Sandawe" +msgstr "Канада" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +# AU +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "Австралија" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Српски" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Хрватски" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +# AU +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Австралија" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Словачки" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Словенечки" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +# SO +# fuzzy +#. language code: som so +#: zypp/LanguageCode.cc:983 +#, fuzzy +msgid "Somali" +msgstr "Романија" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +#, fuzzy +msgid "Spanish" +msgstr "Дански" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +#, fuzzy +msgid "Sardinian" +msgstr "Македонски" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Шведски" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +#, fuzzy +msgid "Tahitian" +msgstr "Хрватски" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Тамилски" + +# QA +# fuzzy +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "KStep" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +# TJ +# fuzzy +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +#, fuzzy +msgid "Tajik" +msgstr "Тајван" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Таи" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "" + +# TR +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "Турција" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +# AU +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "Австралија" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Турски" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +# UA +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +#, fuzzy +msgid "Ukrainian" +msgstr "Украина" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +# AU +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "Австралија" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "" + +# AU +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "Австралија" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Валонски" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +# AU +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "Австралија" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Неможеше да се створи %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Неможеше да се кешира складиштето (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Couldn't open file: %s." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Неможеше да се прочита директориумот '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Неможеше да се избрише '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Фајл %1%\n" +" од пакет\n" +" %2%\n" +" е во конфликт со фајлот\n" +" %3%\n" +" од пакет\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Неможе да се создаде sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "скрши %s со игнорирање некои од неговите зависности" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "генерално игнорирај некои зависности" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"инсталираниот %1% не припаѓа во distupgrade складижте и мора да се замени" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "инсталираниот %1% има инфериорна архитектура" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "проблем со инсталираниот %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "спротивставени барања" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "некои проблеми со зависности" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "ништо не го поддржува бараниот '%1%'" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Дали ги вклучивте сите потребни складишта?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "бараниот пакет %1% не постои" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " егзекуцијата не успеа" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Неможеше да се chdir-а во '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Неможеше да се монтира %s во %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Неможеше да се демонтира %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Couldn't open file: %s." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "не е конектирано" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." + +# CL +#, fuzzy +#~ msgid "Child of" +#~ msgstr "Чиле" + +# CF +# fuzzy +#, fuzzy +#~ msgid "Centruual African Republic" +#~ msgstr "Доминиканска Република" diff --git a/po/mr.po b/po/mr.po new file mode 100644 index 0000000..a33dfe7 --- /dev/null +++ b/po/mr.po @@ -0,0 +1,5934 @@ +msgid "" +msgstr "" +"Project-Id-Version: Check hardware-2.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2006-11-13 12:55+0530\n" +"Last-Translator: Priyavert Sharma \n" +"Language-Team: AgreeYa Solutions \n" +"Language: \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: KBabel 1.10.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "अज्ञात देश:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "कोड नाही" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "अंडोरा" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "संयुक्त अरब अमिराती" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "अफगाणिस्तान" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "ऑन्टिग्वा व बर्बुडा" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "अंग्विला" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "अल्बेनिया" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "आर्मेनिया" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "नेदरलॅन्ड्स अन्टिलेस" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "अंगोला" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "अंटार्क्टिका" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "अर्जेंटिना" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "अमेरिकन सॅमोआ" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "ऑस्ट्रिया" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "आस्ट्रेलिया" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "अरूबा" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "अलॅन्ड बेटे" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "अझरबैजान" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "बोस्निया व हर्जेगोव्हिना" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "बारबॅडॉस" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "बांग्लादेश" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "बेल्जियम" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "बर्किना फासो" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "बल्गेरिया" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "बहारिन" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "बुरूंडी" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "बेनिन" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "बरमुडा" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "ब्रुनेई दारूसलाम" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "बोलिव्हिया" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "ब्राझील" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "बहामास" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "भूतान" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "बोव्हेच बेट" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "बोटस्वाना" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "बेलारूस" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "बेलिझे" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "कॅनडा" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "कॉकस (कीलींग) बेटे" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "काँगो" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "मध्य आफ्रिकी प्रजासत्ताक" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "स्वित्झर्लंड" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "कोट डी आयव्हरी" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "कूक बेटे" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "चिली" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "कॅमेरून" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "चीन" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "कोलंबिया" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "कोस्टा रिका" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "क्युबा" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "केप व्हेर्डे" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "ख्रिसमस बेट" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "सायप्रस" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "चेक प्रजासत्ताक" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "जर्मनी" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "दिजबौती" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "डेनमार्क" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "डॉमिनिका" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "डॉमिनिकन प्रजासत्ताक" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "अल्जेरिया" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "इक्वेडोर" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "एस्टोनिया" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "ईजिप्त" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "पश्चिम सहारा" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "एरिट्रिआ" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "स्पेन" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "इथिओपिया" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "फिनलँड" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "फिजी" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "फाल्कलॅन्ड बेटे (माल्व्हिनास)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "मिक्रोनेशिया फेडरेटेड स्टेट्स" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "फरोई बेटे" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "फ्रान्स" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "मेट्रॉपॉलिटन फ्रान्स" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "गॅबॉन" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr ".युनायटेड किंगडम" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "ग्रेनाडा" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "जॉर्जिया" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "फ्रेच गुआना" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "जर्मनी" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "घाना" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "जिब्राल्टर" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "ग्रीनलॅन्ड" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "गॅम्बिया" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "ग्विनिआ" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "ग्वाडेलोप" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "इक्वेटोरियल गुनिआ" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "ग्रीस" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "दक्षिण जॉर्जिया व दक्षिण सॅन्डविच बेटे" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "ग्वाटेमाला" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "ग्वॅम" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "ग्विनिआ-बिसाऊ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "गयाना" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "हाँगकाँग" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "हर्ड बेटे व मॅकडॉनल्ड बेटे" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "होंडुरास" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "क्रोएशिया" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "हैती" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "हंगेरी" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "इंडोनेशिया" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "आयर्लंड" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "इस्रेल" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "भारत" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "ब्रिटिश हिंदी महासागर प्रदेश" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "इराक" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "इराण" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "आइसलॅन्ड" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "ईटाली" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "जमैका" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "जॉर्डन" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "जपान" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "केनिया" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "किरगिझस्तान" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "कंबोडिया" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "किरीबती" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "कॉमोरोस" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "सेंट किट्स व नेव्हिस" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "उत्तर कोरिया" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "दक्षिण कोरिया" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "कुवैत" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "केमन बेटे" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "कझाकस्तान" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "लाओ पीपल्स डेमोक्रॅटिक रिपल्बिक" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "लेबनॉन" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "सेंट ल्युसिया" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "लाएचटेन्स्टिन" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "श्रीलंका" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "लायबेरिया" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "लेसोथो" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "लिथुएनिया" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "लक्झेमबर्ग" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "लॅटव्हिया" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "लिबिया" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "मोरोक्को" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "मोनॅको" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "मॉल्दोव्हा" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "मोंगो" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "सॅन मारिनो" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "मादागास्कर" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "मार्शल बेटे" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "मासेडोनिया" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "माली" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "म्यानमार" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "मंगोलिया" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "मकाओ" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "उत्तरी मेरियाना बेटे" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "मार्टिनिक" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "मॉरिटॅनिया" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "माँतेसेरत" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "माल्टा" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "मॉरिशस" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "मालदीव्हज" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "मालावी" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "मेक्सिको" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "मलेशिया" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "मोझाम्बिक" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "नामिबिया" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "न्यू कॅलेडोनिया" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "नायजेर" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "नॉरफॉक बेटे" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "नायजेरिया" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "निकारागुआ" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "नेदरलॅन्डस" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "नॉर्वे" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "नेपाळ" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "नौरू" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "न्यूए" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "न्यूझीलंड" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "ओमान" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "पनामा" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "पेरू" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "फ्रेंच पॉलिनेसिया" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "पापुआ न्यू जिनिव्हा" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "फिलीपीन्स" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "पाकिस्तान" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "पोलंड" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "सेंट पिअर व मिक्वेलॉन" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "पिटकैर्न" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "प्युर्टो रिको" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "पॅलेस्टिनी भूप्रदेश" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "पोर्तुगाल" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "पलाऊ" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "पॅरॅग्वे" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "कतार" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "रीयुनियन" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "रूमेनिया" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "सर्बियन" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "रशियन फेडरेशन" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "रवांडा" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "सौदी अरबस्तान" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "सॉलोमन बेटे" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "सेशेल्स" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "सुदान" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "स्वीडन" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "सिंगापुर" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "सेंट हेलेना" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "स्लोव्हेनिया" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "स्वॅलबार्ड व जन मायेन" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "स्लोव्हाकिया" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "सिएरा लिओन" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "सॅन मारिनो" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "सेनेगल" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "सोमालिया" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "सुरीनाम" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "साओ टोम व प्रिन्सिप" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "एल सॅल्व्हेडोर" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "सायरिया" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "स्वाझिलॅन्ड" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "टर्क्स व कैकॉस बेटे" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "चॅड" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "फ्रेंच दक्षिणी भूप्रदेश" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "टोगो" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "थायलंड" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "ताजिकीस्तान" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "टोकेलाऊ" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "तुर्कमेनिस्तान" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ट्युनिशिया" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "टोंगा" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "पूर्व तिमोर" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "तुर्कस्तान" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "त्रिनिदाद व टोबॅगो" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "तुवालू" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "तैवान" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "टांझानिया" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "युक्रेन" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "युगांडा" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "अमेरिकेतील छोटी बेटे" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "अमेरिका" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "ऊरुग्वे" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "उझबेकिस्तान" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "होली सी (व्हॅटिकन सिटी देश)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "सेंट विन्सेन्ट व ग्रेनाडिन्स" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "व्हेनेझुएला" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "ब्रिटिश व्हर्जिन बेटे" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "व्हर्जिन आयलंड्स, अमेरिका" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "व्हिएटनाम" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "वानुआतू" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "वॉलिस व फुतुना" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "सॅमोआ" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "येमेन" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "मायोटे" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "दक्षिण आफ्रिका" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "झांबिया" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "झिंबाब्बे" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s :%s ला बाजूला टाकते" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "VM सुरू करण्यात अयशस्वी." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "VM सुरू करण्यात अयशस्वी." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "नोंद आढळली नाही" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "अज्ञात भाषा" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "अफार" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "अबखॅजियॅन" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "अचाईनीज" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "अकोली" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "अडँग्मे" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "अडायघे" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "आफ्रो-एशियाटिक (अन्य)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "आफ्रिहिली" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "आफ्रिकान्स" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "ऐनू" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "अकान" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "अक्कादियॅन" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "अल्बेनियन" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "अलौत" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "अल्गोन्क्वियन भाषा" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "दक्षिण अल्तई" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "अम्हॅरिक" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "इंग्रजी जुनी (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "अपाची भाषा" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "अरेबिक" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "अरॅमॅइक" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "अरॅगोनीज" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "अर्मेनियन" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "अरौकॅनियन" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "अरापाहो" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "आर्टिफिशियल (अन्य)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "अरावाक" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "असमी" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "अस्टुरियन" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "अथापास्कन भाषा" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "ऑस्ट्रेलियन भाषा" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "अवॅरिक" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "अव्हेस्टन" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "अवधी" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "ऐमारा" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "अझरबैजानी" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "बांदा" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "बामिलिक भाषा" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "बशकीर" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "बलुची" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "बाम्बारा" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "बालीनीज" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "बास्क" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "बासा" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "बाल्टिक (अन्य)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "बेजा" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "बेलारूसियन" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "बम्बा" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "बंगाली" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "बर्बर (अन्य)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "भोजपुरी" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "बिहारी" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "बिकोल" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "बिनी" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "बिस्लामा" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "सिकसिका" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "बांतू (अन्य)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "बोस्नीयन" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "ब्रज" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "ब्रेटॉन" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "बाटक (इंडोनेशिया)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "बरियत" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "बगिनीज" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "बल्गेरियन" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "बर्मीज" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "ब्लिन" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "कॅडो" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "मध्य अमेरिकन इंडियन (अन्य)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "कॅरीब" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "कॅटलॅन" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "कॉकेशियन (अन्य)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "सेबुआनो" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "सेल्टिक (अन्य)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "चॅमोरो" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "चीबचा" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "चेचेन" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "चगतई" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "चीनी" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "चुकीज" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "मारी" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "चीनूक जारगॉन" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "चोकटा" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "चिपेव्यान" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "चेरोकी" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "चर्च स्लाविक" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "चुवाश" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "चेयेनी" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "चॅमिक भाषा" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "कॉप्टिक" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "कोर्निश" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "कोर्सिकन" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "क्रेओलेस व पिडगिन्स, इंग्रजी वर आधारित (अन्य)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "क्रेओलेस व पिडगिन्स, फ्रेंचवर आधारित (अन्य)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "क्रेओलेस व पिडगिन्स, पोर्तुगीजवर आधारित (अन्य)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "क्री" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "क्रिमियन टाटार" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "क्रेओलेस व पिडगिन्स (अन्य)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "काशुबियन" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "कुशिटीक (अन्य)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "चेक" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "डाकोटा" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "डॅनिश" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "डार्गवा" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "डायाक" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "डेलावेअर" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "स्लाव (अथॅपास्कन)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "डोग्रीब" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "डिनका" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "दिवेही" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "डोगरी" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "द्रविडियन (अन्य)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "लोअर सर्बियन" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "दुआला" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "डच, मध्य (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "डच" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ड्यूला" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "झोंगखा" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "एफिक" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "इजिप्शियन (प्राचीन)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "एकाजुक" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "इलॅमाइट" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "इंग्रजी" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "इंग्रजी, मध्य (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "एस्पेरॅन्टो" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "एस्टोनियन" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "इवे" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "इवोंडो" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "फँग" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "फरोसी" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "फान्ती" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "फिजियन" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "फिलिपिनो" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "फिनिश" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "फिनो-उग्रीयन (अन्य)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "फॉन" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "फ्रेंच" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "फ्रेंच, मध्य (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "फ्रेंच, जुनी(842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "फ्रिसीयन" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "फुलाह" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "फ्रुलियन" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "गा" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "गायो" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "ग्बाया" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "जर्मनिक (अन्य)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "ज़ॉर्जियन" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "जर्मन" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "गीझ" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "गिल्बर्टीज" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "गेलिक" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "आयरिश" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "गॅलीसियन" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "मँक्स" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "जर्मन , मध्यम जास्त (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "जर्मन, जुनी जास्त (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "गोंडी" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "गोरोंटॅलो" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "गोथिक" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "ग्रेबो" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "ग्रीक, प्राचीन (1453 पर्यंत)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "ग्रीक, आधुनिक (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "गुरानी" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "गुजराती" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "ग्विच’इन" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "हैदा" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "हैतियन" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "हौसा" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "हवाईयन" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "हिब्रु" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "हरेरो" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "हिलीगेनॉन" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "हिमाचली" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "हिन्दी" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "हित्तिते" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "ह्माँग" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "हिरी मोतू" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "अप्पर सॉर्बियन" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "हंगेरियन" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "हुपा" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "ईबान" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "इग्बो" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "आईस्लॅन्डिक" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "इडो" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "सिचुआन यी" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ईजो" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "इनुक्तितूत" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "इन्टरलिंग" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "इलोको" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "इन्टरलिंगुआ (आंतरराष्ट्रीय ऑक्सिलरी भाषा संघटना" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "इंडिक (अन्य)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "इंडोनेशियन" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "इंडो-युरोपियन (अन्य)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "इंगुश" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "इनुपिआक" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "इराणीयन (अन्य)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "इरोकोईयन भाषा" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "ईटालियन" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "जावानीज" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "लॉज्बन" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "जपानी" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "ज्युडेओ-पर्शियन" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "ज्युडेओ-अरेबिक" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "कारा-कल्पक" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "काबाईल" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "काचीन" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "कलालिसट" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "कांबा" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "कानाडी" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "कारेन" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "काश्मिरी" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "कानुरी" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "कावी" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "कझाक" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "कबर्डियन" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "खासी" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "खोईसन (अन्य)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "खमेर" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "खोटानीज" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "किकूयू" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "किन्यारवंडा" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "किरगीझ" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "किम्बुन्डू" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "कोकणी" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "कोमी" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "काँगो" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "कोरियन" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "कोस्रीयन" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "क्पेल्ले" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "कराचाय-बल्कर" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "क्रू" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "कुरुख" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "क्वॅन्यॅमा" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "कुम्यक" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "कुर्दिश" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "कुतेनाय" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "लॅडिनो" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "लाहंदा" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "लांबा" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "लाओ" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "लॅटिन" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "लॅटव्हियन" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "लेझगियान" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "लिंबुर्गन" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "लिंगाला" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "लिथुएनियन" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "मोंगो" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "लोझी" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "लक्झेम्बर्गिश" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "लुबा-लुलुआ" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "लुबा-कटंगा" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "गांडा" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "लुईझेनो" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "लुंडा" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "लुओ (केनिया व तांझानिया)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "लुशाई" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "मेसेडोनियन" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "मदुरीज" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "मगही" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "मार्शलीज" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "मैथिली" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "मकासार" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "मल्याळम" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "मन्डिंगो" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "माओरी" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "ऑस्ट्रोनेशियन (अन्य)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "मराठी" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "मसई" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "मलय" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "मोक्षा" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "मंदार" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "मेंडे" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "आयरिश, मध्य (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "मि’क्माक" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "मिनँगकाबाऊ" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "किरकोळ अन्य भाषा" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "मॉन-खमेर (अन्य)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "मलागासी" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "माल्टीज" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "मांचू" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "मणिपुरी" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "मोनोबो भाषा" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "मोहॉक" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "मॉल्देव्हियन" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "मंगोलियन" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "मोस्सी" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "अनेक भाषा" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "मुंडा भाषा" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "क्रीक" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "मिरॅन्डिस" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "मारवाडी" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "मायन भाषा" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "एरझ्या" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "नाहुआटल" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "उत्तर अमेरिकी भारतीय" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "नेपोलिटन" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "नाव्हाजो" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "न्डेबेले, दक्षिण" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "न्डेबेले उत्तर" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "न्डोंगा" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "लो जर्मन" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "नेपाळी" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "नेपाल भासा" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "निअस" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "नायजेर-कोर्डोफॅनियन (अन्य)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "नियुईन" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "नॉर्वेजियन न्योर्स्क" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "नॉर्वेजियन बोकमल" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "नोगई" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "नॉर्से, जुनी" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "नॉर्वेजियन" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "उत्तरी सोथो" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "नुबियन भाषा" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "क्लासिकल नेवाडी" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "चिचेवा" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "न्याम्वेझी" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "न्यान्कोल" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "न्योरो" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "न्झिमा" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "ऑसिटन (1500 नंतर)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "ऑजिब्वा" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "उडिया" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "ओरोमो" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "ओसाज" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "ऑसेटियन" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "टर्किश, ओटोमन (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "ऑक्टोमियन भाषा" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "पापुआन (अन्य)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "पांगेसिनन" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "पल्हवी" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "पम्पॅन्गा" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "पंजाबी" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "पापिअमेन्टो" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "पलौअन" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "पर्शियन, जुनी (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "पर्शियन" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "फिलीपिनी (अन्य)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "फोएनिशियन" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "पाली" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "पोलिश" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "पोहमपेइयन" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "पोर्तुगीज" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "प्राकृत भाषा" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "प्रॉव्हेन्कल, जुनी (1500 " + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "पुश्तो" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "क्वेचुआ" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "राजस्थानी" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "रापानुई" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "रारोटोंगन" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "रोमन्स (अन्य)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "राएटो-रोमन्स" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "रूमेनी" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "रुमेनियन" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "रूंदी" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "रशियन" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "सॅन्डावे" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "सांगो" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "याकुत" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "दक्षिण अमेरिकन भारतीय (अन्य)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "सॉलिशन भाषा" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "समरितान भाषा" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "संस्कृत" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "सासक" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "संताली" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "सर्बियन" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "सिसीलियन" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "स्कॉट्स" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "क्रोएशियन" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "सेल्कप" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "सेमिटिक (अन्य)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "आयरिश, जुनी (900 पर्यंत)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "खुणांची भाषा" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "शान" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "सिडॅमो" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "सिंहला" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "सिओयुअन भाषा" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "सिनो-तिबेटन (अन्य)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "स्लेव्हिक (अन्य)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "स्लोव्हाक" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "स्लोव्हेनियन" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "दक्षिण सॅमी" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "उत्तरी सॅमी" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "सॅमी भाषा (अन्य)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "लुले सॅमी" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "इनारी सॅमी" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "सॅमोअन" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "स्कॉल्ट सॅमी" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "शोना" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "सिंधी" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "सोनिंके" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "सॉग्डियन" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "सोमाली" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "साँघई" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "सोथो, दक्षिणी" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "स्पॅनिश" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "सार्डिनियन" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "सेरेर" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "निलो-सहारन (अन्य)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "स्वाती" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "सुकुमा" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "सुदानीज" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "सुसु" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "सुमेरियन" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "स्वाहिली" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "स्वीडिश" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "सायरिअक" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "ताहिशियन" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "ताई (अन्य)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "तामिल" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "तातार" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "तेलगू" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "टिम्ने" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "तेरेनो" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "टेटम" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "ताजिक" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "तागालॉग" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "थाई" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "तिबेटियन" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "तिग्री" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "तिग्रीन्या" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "तिव्ह" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "क्लिंगॉन" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "त्लिंगिट" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "तामाशेक" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "टोंगा (न्यासा)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "टोंगा (टोंगा बेटे)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "टॉक पिसीन" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "त्सिम्सीयॅन" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "त्स्वाना" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "त्सोंगा" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "तुर्कमन" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "टुंबुका" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "तुपी भाषा" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "टर्किश" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "अल्ताईक (अन्य)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "त्वि" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "तुव्हिनियन" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "उडमर्ट" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "युगारिटिक" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "युईघर" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "युक्रेनियन" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "युबुंडु" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "निश्चित केलेली नाही" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "उर्दू" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "उझबेक" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "वाई" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "वेंदा" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "व्हिएतनामीज" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "व्होलॅपुक" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "व्होटिक" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "वाकाशन भाषा" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "वालॅमो" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "वॅरे" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "वाशो" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "वेल्श" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "सर्बियन भाषा" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "वॅलून" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "वोलोफ" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "कल्माइक" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "क्झोसा" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "याओ" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "यापीज" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "यिदिश" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "योरूबा" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "युपिक भाषा" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "झापोटेक" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "झेनागा" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "झुएंग" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "झांदे" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "झुलू" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "झुनी" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1' अस्तित्वात नाही." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1' अस्तित्वात नाही." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "अनोळखी" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "डिस्क अस्तित्वात नाही" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "अज्ञात आज्ञा" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "अवैध Url स्कीम %s" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "डिरेक्टर %1: %2 निर्माण करता आली नाही." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr " डेस्कटॉप आयटेम'%s' उघडू शकत नाही" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "पाठवल्याच्या फाईलचे अवैध नांव" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "फाईलरायटिंगसाठी उघडू शकत नाही." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "फ्लॉपी डिस्कवरुन एरर वाचत आहे." + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "रिसोर्सेस जतन करत आहे" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr " डेस्कटॉप आयटेम'%s' उघडू शकत नाही" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr " VM चे नाव आकड्याने सुरू होता कामा नये. " + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr " VM चे नाव आकड्याने सुरू होता कामा नये. " + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "चालू ठेवायचे?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"पॅकेज %s एकत्रित तपासणीत अयशस्वी. आपल्याला ते पुन्हा डाऊनलोड करण्याचा प्रयत्न करायचाआहे?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"पॅकेज %s एकत्रित तपासणीत अयशस्वी. आपल्याला ते पुन्हा डाऊनलोड करण्याचा प्रयत्न करायचाआहे?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm चेक अयशस्वी" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm अयशस्वी" + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "बदल वैशिष्ट्ये दाखवाला रिसोर्स प्रकार VAR1 समर्थन देत नाही feature" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "%s वरून %s पुरवू शकत नाही" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "भांडारात फाईल %1 आढळली नाही" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "फाईल निर्माण करु शकत नाही" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "या गरजेकडे येथेच दुर्लक्ष करा" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "या गरजेकडे येथेच दुर्लक्ष करा" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "यांच्याशी कनेक्शनची रिक्वेस्ट :" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "अवलंबून असण्याच्या (डिपेन्डन्सी) समस्येमुळे %s स्थापित करु शकत नाही" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "कोणतीही गोष्ट %s पुरवत नाही" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "%s चे स्थापित करता येण्याजोगे प्रदाता नाहीत" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "%s चे स्थापित करता येण्याजोगे प्रदाता नाहीत" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "विनंती आधीपासूनच आहे." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "निर्देशानुसार स्थापना मधेच सोडली" + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "अमलात आणा" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "की च्या सांकेतिकीकरणादरम्यान चूक आली" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "अयशस्वी" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s साठी बदललेल्या आकृतीबंध फाईल्स" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm ने %s हे %s म्हणन जतन केले, परंतु फरक सांगणे अशक्य" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "rpm ने %s हे %s म्हणून जतन केले/nफरकाच्या या पहिल्या 25 ओळी\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm ने %s हे %s म्हणून जतन केले फरकाच्या या पहिल्या" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "rpm ने %s हे %s म्हणून जतन केले/nफरकाच्या या पहिल्या 25 ओळी\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "अतिरिक्त rpm आऊटपुट" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "बॅकअप %s निर्माण केले" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "नोंद आढळली नाही" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "नोंद आढळली नाही" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "नोंद आढळली नाही" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "फाईल उघडता येत नाही %1." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "फाईल उघडता येत नाही %1." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "अवैध LDAP URL क्वेरी स्ट्रिंग" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "अवैध LDAP URL क्वेरी पॅरामीटर %s" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Url ऑब्जेक्ट क्लोन करण्यात असमर्थ" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "अवैध रिक्त Url ऑब्जेक्ट संदर्भ" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Url भागांचा संबंध जोडण्यात असमर्थ" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url स्कीम %sला अनुमती देत नाही" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "अवैध %s कॉम्पोनन्ट %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "अवैध %s कॉम्पोनन्ट" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "या URL साठी क्वेरी स्ट्रिंग पार्सिंगचे समर्थन नाही" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL स्कीम हा एक आवश्यक भाग आहे" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "अवैध Url स्कीम %s" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url स्कीम उपभोक्त्याच्या नावाला अनुमती देत नाही" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url स्कीम पासवर्डला अनुमती देत नाही" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url स्कीमला मुख्य भागाची गरज असते" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url स्कीम मुख्य भागाला अनुमती देत नाही" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "अवैध मुख्य भाग %s" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url स्कीम पोर्टला अनुमती देत नाही" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "अवैध पोर्ट भाग %s" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url स्कीमला पाथच्या नावाची गरज असते" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "अथॉरिटी उपस्थित असेल तर सापेक्ष पाथला अनुमती नाही" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "एनकोडेड स्ट्रिंगमधे NUL बाईटचा समावेश आहे" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "अवैध पॅरामीटर अरे स्प्लिट सेपरेटर कॅरॅक्टर" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "अवैध पॅरामीटर मॅप स्प्लिट सेपरेटर कॅरॅक्टर" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "अवैध पॅरामीटर अरे जॉईन सेपरेटर कॅरॅक्टर " + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr " कनेक्ट करतांना आदेश वापरला " + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "%s आढळत नाही." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "%s आढळत नाही." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr " %s - %s उघडणे अशक्य\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "मॉड्युल लोड करण्यात अपयश \"%s\"." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "भांडारात फाईल %1 आढळली नाही" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "फाईल %1 लिहिता येत नाही." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 ही डिरेक्टरी नाही." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "रिक्त CA नांव." + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "अवैध URL योजना '%1'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr " डेस्कटॉप आयटेम'%s' उघडू शकत नाही" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "परवानगी नाकारली" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "होय" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "नाही" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "सावधान" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "त्रुटी" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "केले" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "चूक" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "सावधान" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "सुरु करत आहे..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "सापडले नाही" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "योय" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "नाहीं" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s %s पुरवते, परंतु त्याचे दुसरे स्थापत्य आहे." + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "पॅकेजेस अस्थापित करण्याचा आदेश" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "कोणतीही गोष्ट %s पुरवत नाही" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "डिस्क अस्तित्वात नाही" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s ला कुलुप आहे व अस्थापित होऊ शकत नाही" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "स्थापित नसलेली" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s ला %s ची गरज आहे" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s स्थापित करु शकत नाही" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s चे %s शी पटत नाही" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s %s ला बाजूला टाकते" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s %s ला बाजूला टाकते" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s चे %s शी पटत नाही" + +#~ msgid "do not install %s" +#~ msgstr "%s स्थापित करु नका" + +#~ msgid "keep %s" +#~ msgstr "%s ठेवा" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "%s स्थापित करु नका" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "%s चे स्थापित करता येण्याजोगे प्रदाता नाहीत" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "संबंधित रिझॉल्व्हेबल्स स्थापित किंवा पुसून टाकू नका" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s %s पुरवते, परंतु त्याचे दुसरे स्थापत्य आहे." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "%s स्थापित करा, जरी ते स्थापत्य बदलत असेल" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s %s ला बाजूला टाकते" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "% वरून % डाऊनलोड करत आहे" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "स्थापना (इन्स्टॉलेशन)" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "फाईल उघडता येत नाही %1." + +#~ msgid "Hal Exception" +#~ msgstr "Hal अपवाद" + +#~ msgid "HalContext not connected" +#~ msgstr "हॅलकॉन्टेक्स्ट कनेक्ट केलेले नाही" + +#~ msgid "HalDrive not initialized" +#~ msgstr "हॅलड्राईव्हची सुरुवात नाही" + +#~ msgid "HalVolume not initialized" +#~ msgstr "हॅलव्हाल्यूमची सुरुवात नाही" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "डीबस कनेक्शन निर्माण करणे अशक्य" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: लिभाल कॉन्टेक्स निर्माण करु शकत नाही" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr " libhal_set_dbus_connection: डीबस कनेक्शन निश्चित करू शकत नाही" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "HAL कॉन्टेक्स्ट चा प्रारंभ अशक्य – हाल्ड चालू नाही?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "CDROM ड्राईव्ह नाही" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "म्युटेक्स अट्रिब्यूट्स सुरू करू शकत नाही" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "रीकर्सिव्ह म्यूटेक्स अट्रिब्यूट स्थापित करु शकत नाही" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "रीकर्सिव्ह म्युटेक्स सुरू करू शकत नाही " + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "म्युटेक्स लॉक मिळवू शकत नाही" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "म्युटेक्स लॉक उघडू शकत नाही" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "सार्वजनिक की मिळवणे अशक्य" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "स्थापित नसलेली" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr " %s - %s उघडणे अशक्य\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "सर्बिया व माँटेनेग्रो" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "अज्ञात सूची पर्याय" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "निर्भरता रिझॉल्व करु शकलो नाही" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाईल %s मधे चेकसम नाही.\n" +#~ "तरीही फाईल वापरायची?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s फाईल पुढील की बरोबर सचोटी:\n" +#~ "%s|%s|%s\n" +#~ "तपासात अयशस्वी तरीही फाईल वापरायची?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाईल %s मधे अवैध चेकसम.\n" +#~ "अपेक्षित %s,आढळले %s\n" +#~ "तरीही फाईल वापरायची?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाईल %s मधे अज्ञात चेकसम. %s.\n" +#~ "तरीही फाईल वापरायची?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "फाईल %s वर स्वाक्षरी नाही\n" +#~ "तरीही वापरायची?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "फाईल %s वर अज्ञात की ची स्वाक्षरी:\n" +#~ "%s|%s|%s\n" +#~ "तरीही फाईल वापरायची?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "अविश्वासू की आढळली:\n" +#~ "%s|%s|%s\n" +#~ "की वर विश्वास ठेवायचा?" + +#~ msgid "%s remove failed" +#~ msgstr "%s काढून टाकणे अयशस्वी" + +#~ msgid "rpm output:" +#~ msgstr "rpm आऊटपुट" + +#~ msgid "%s install failed" +#~ msgstr "%s स्थापना अयशस्वी" + +#~ msgid "%s installed ok" +#~ msgstr "%s स्थापना ठीक आहे" + +#~ msgid "%s remove ok" +#~ msgstr "%s टाकणे ठीक आहे" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "%s ही डिपेन्डन्सी पुरवते, परंतु ते स्थापित आयटेमचे स्थापत्य बदलेल" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "%s ही डिपेन्डन्सी पुरवते, परंतु ते स्थापित आयटेमचे स्थापत्य बदलेल" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "संबंधित रिझॉल्व्हेबल्स स्थापित किंवा पुसून टाकू नका" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "%s याआधीच स्थापनेसाठी सज्ज असल्याकडे दुर्लक्ष करा" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr " %s मधील %s ऑब्सोलीटकडे दुर्लक्ष करा" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%s चा हा विवाद विसरून जा" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "या गरजेकडे येथेच दुर्लक्ष करा" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "%s स्थापित करा, जरी ते स्थापत्य बदलत असेल" + +#~ msgid "Install missing resolvables" +#~ msgstr "गायब रिझॉल्व्हेबल्स स्थापित करा" + +#~ msgid "Keep resolvables" +#~ msgstr "रिझॉल्व्हेबल्स ठेवा" + +#~ msgid "Unlock these resolvables" +#~ msgstr "ही रिझॉल्व्हेबल्स अनलॉक करा" + +#~ msgid "delete %s" +#~ msgstr "%s पुसून टाका" + +#~ msgid "install %s" +#~ msgstr "%s स्थापित करा" + +#~ msgid "unlock %s" +#~ msgstr "%s अनलॉक करा" + +#~ msgid "unlock all resolvables" +#~ msgstr "सर्व रिझॉल्व्हेबल्स अनलॉक करा" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "फाईल उघडता येत नाही %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "एरर सेक्टर %u वाचत आहे." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "या URL साठी पाथ पॅरामीटर पार्सिंगचे समर्थन नाही" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "या URL साठी पाथ पॅरामीटर पार्सिंगचे समर्थन नाही" + +#~ msgid "Software management is already running." +#~ msgstr "सॉफ्टवेअर व्यवस्थापन आधीच चालू आहे" + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s च्या जागी %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s च्या जागी %s " + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "ही रिझॉल्व्हेबल्स प्रणालीतून पुसून टाकली जातील" + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s अस्थापित होणार नाही कारण ते अजून आवश्यक आहे" + +#~ msgid "Invalid information" +#~ msgstr "अवैध माहिती" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "इतर रिझॉल्व्हेबल्सना %s ची गरज आहे" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "%s ला %s ची गरज आहे:/n" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s चे अन्य रिझॉल्व्हेल्बशी पटत नाही" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s चे\n" +#~ "%s शी पटत नाही:" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s अन्य रिझॉल्व्हेबल्सना बाजूला टाकते" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "ही रिझॉल्व्हेबल्स प्रणालीतून पुसून टाकली जातील" + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s इतर रिझॉल्व्हेबल्सवर अवलंबून" + +#~ msgid "%s depends on %s" +#~ msgstr "%s %s वर अवलंबून" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s :%s वर अवलंबून" + +#~ msgid "Child of" +#~ msgstr "चाईल्ड ऑफ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "असे कोणतेही साधन उपलब्ध नाही जे या गरजेला समर्थन देते." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "येऊ घातलेल्या समस्या, ज्या या रिझोल्यूशनच्या वर/खाली नमूद केल्या आहेत, त्यासर्व अवलंबून " +#~ "गोष्टी सोडवणार नाहीत" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%s स्थापित करु शकत नाही कारण त्यांचे %s शी पटत नाही" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s स्थापित नाही व त्यावर स्थापित न करता येणारा अशी खूण आहे" + +#, fuzzy +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "च्या गरजा पूर्ण न होणार्या" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%sच्या गरजा पूर्ण न होणार्या आहेत" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s मधे गायब डिपेन्डन्सीज आहेत." + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "गायब डिपेन्डन्सीडमुळे %s स्थापित करु शकत नाही" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s %s च्या डिपेन्डन्सीज पूर्ण करते, परंतु आपल्या प्रणालीवर ठेवण्यात येईल" + +#~ msgid "No need to install %s" +#~ msgstr "%s स्थापित करण्याची गरज नाही" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "%s च्या डिपेन्डन्सीज पूर्ण करण्यासाठी %s स्थापित करू शकत नाही" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "%s च्या डिपेन्डन्सीज पूर्ण करण्यासाठी %s स्थापित करू शकत नाही" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s अस्थापित होणार नाही कारण ते अजून आवश्यक आहे" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s %s ला बाजूला टाकते, परंतु %s पुसता येत नाही कारण ते लॉक्ड आहे" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "%s स्थापित करता येऊ शकत नाही कारण ते विवादास्पद आहे" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s स्थापित करता येण्यासारखे नाही कारण त्याचे %s शी पटत नाही" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "%s चे अपग्रेडिंग करतांना %s साठी %s ची गरज" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s गरज %s चुकवत आहे" + +#~ msgid ", Action: " +#~ msgstr "कृती" + +#~ msgid ", Trigger: " +#~ msgstr "ट्रिगर" + +#~ msgid "package" +#~ msgstr "पॅकेज" + +#~ msgid "selection" +#~ msgstr "निवड" + +#~ msgid "pattern" +#~ msgstr "नमुना" + +#~ msgid "product" +#~ msgstr "उत्पादन" + +#~ msgid "patch" +#~ msgstr "पॅच" + +#~ msgid "script" +#~ msgstr "स्क्रिप्ट" + +#~ msgid "message" +#~ msgstr "संदेश" + +#~ msgid "atom" +#~ msgstr "अणू (अटम)" + +#~ msgid "system" +#~ msgstr "प्रणाली" + +#~ msgid "Resolvable" +#~ msgstr "रिझॉल्व्हेबल" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "हा रिझोल्यूशनचा प्रयत्न अवैध असल्याची खूण करत आहे" + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "रिझ़ॉल्व्हेबल %s स्थापित करण्यासारखा नसल्याची खूण करत आहे" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "%s स्थापित होणार आहे, परंतु डिपेन्डन्सी समस्यांमुळे हे शक्य नाही" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "%s स्थापित करु शकत नाही कारण आधीच त्यावर अस्थापित करण्याची गरज असल्याची खूण केलेली " +#~ "आहे" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "%s स्थापित करु शकत नाही, कारण ते या प्रणालीला लागू होत नाही" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "%s स्थापित करु शकत नाही, कारण आधीच त्यावर अस्थापित करण्याची गरज असल्याची खूण " +#~ "केलेली आहे " + +#~ msgid "This would invalidate %s." +#~ msgstr "हे %s अवैध करेल" + +#~ msgid "Establishing %s" +#~ msgstr "%s प्रस्थापित करत आहे" + +#~ msgid "Installing %s" +#~ msgstr "%s स्थापित करत आहे" + +#~ msgid "Updating %s to %s" +#~ msgstr "%s ते %s अपडेट करत आहे" + +#, fuzzy +#~ msgid "Skipping %s: already installed" +#~ msgstr "%s वगळत आहेः %s याआधीच स्थापित आहे" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "%s चे पर्यायी स्थापित प्रदाता नाहीत" + +#~ msgid "for %s" +#~ msgstr "%s करिता" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "%s काढून टाकणे शक्य नसल्याचे टाळण्यासाठी %sला अपग्रेड करा" + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s %s पुरवते, परंतु ते अस्थापित होणार आहे." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s %s पुरवते, परंतु त्या %s ची दुसरी आवृत्ती आधीच स्थापित आहे." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s %s पुरवते, परंतु ते स्थापित करण्याजोगे नाही. अधिक माहितीसाठी ते स्वतःहूनच स्थापित " +#~ "करण्याचा प्रयत्न करा" + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s %s पुरवते, परंतु त्याला कुलुप आहे " + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s %s पुरवते, परंतु ते ठेवण्यात येणार आहे." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s %s पुरवते, परंतु त्याचे दुसरे स्थापत्य आहे." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "%s साठी %s ची गरज पूर्ण करु शकत नाही" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "दुसर्या स्थापित होणार्या रिझॉल्व्हेल्बला %s ची गरज आहे, त्यामुळे त्याची लिंक जाणार नाही" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "दुसर्या स्थापित होणार्या रिझॉल्व्हेल्बला %s ची गरज आहे, त्यामुळे त्याची लिंक जाणार नाही" + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "%s (%s) विषयीच्या वादामुळे स्थापित होणारे %s काढून टाकणे आवश्यक आहे" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "%s वरील विवादावरुन %s अस्थापित असल्याची खूण" + +#~ msgid "from %s" +#~ msgstr "%s वरुन" + +#~ msgid " Error!" +#~ msgstr "चूक!" + +#~ msgid " Important!" +#~ msgstr "महत्वाचे!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s वर %s अवलंबून" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s ला %s ची गरज आहे" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s ला %s ची गरज आहे" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s च्या जागी %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s ला %s ची गरज आहे" + +#~ msgid "%s part of %s" +#~ msgstr "%s हा %s चा भाग आहे" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s ला %s ची गरज आहे" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "Url अथॉरिटीचा संबंध सांगणे अशक्य" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "सर्वसाधारणपणे या गरजेकडे दुर्लक्ष करा" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "दुसर्या स्थापित होणार्या रिझॉल्व्हेल्बला %s ची गरज आहे, त्यामुळे त्याची लिंक जाणार नाही" + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "अपडेट स्थापना करण्यासाठी आवश्यक फाईल निर्माण करु शकत नाही" + +#~ msgid "Unable to restore all sources." +#~ msgstr "सर्व स्रोत पुनर्स्थापित करणे अशक्य" + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "किमान एका स्रोताची आधीच नोंदणी आहे, साठवलेले स्रोत पुन्हा साठवता येऊ शकत नाहीत" + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "%s च्या डिपेन्डन्सीज पूर्ण करण्यासाठी %s स्थापित होऊ शकत नाही " + +#~ msgid "%s dependend on %s" +#~ msgstr "%s वर %s अवलंबून" + +#~ msgid "Reading index files" +#~ msgstr "इंडेक्स फाईल्स वाचत आहे" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "स्वाक्षरीची repomd.xml फाईल स्वाक्षरी तपासण्यात अयशस्वी." + +#~ msgid "Reading product from %s" +#~ msgstr "%s वरून प्रॉडक्ट वाचत आहे" + +#~ msgid "Reading filelist from %s" +#~ msgstr "%s वरून फाईलसूची वाचत आहे" + +#~ msgid "Reading packages from %s" +#~ msgstr "%s वरून पॅकेजेस वाचत आहे" + +#~ msgid "Reading selection from %s" +#~ msgstr "%s वरून सिलेक्शन वाचत आहे" + +#~ msgid "Reading pattern from %s" +#~ msgstr "%s वरून नमुना वाचत आहे" + +#~ msgid "Reading patches index %s" +#~ msgstr "%s वरून पॅच वाचत आहे" + +#~ msgid "Reading patch %s" +#~ msgstr "पॅच %s वाचत आहे " + +#~ msgid "The script file failed the checksum test." +#~ msgstr "स्क्रिप्ट फाईल चेकसम टेस्टमधे अयशस्वी." + +#~ msgid "Reading packages file" +#~ msgstr "पॅकेज फाईल वाचत आहे" + +#~ msgid "Reading translation: %s" +#~ msgstr "भाषांतर वाचत आहे: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "पॅकेज %s एकत्रित तपासणीत अयशस्वी. आपणास ते पुन्हा डाऊनलोड करण्याचा प्रयत्न करायचा " +#~ "आहे की स्थापना काढून टाकायची?" + +#~ msgid " miss checksum." +#~ msgstr "मिस चेकसम" + +#~ msgid " fails checksum verification." +#~ msgstr "चेकसम पडताळणी अयशस्वी" + +#~ msgid "Downloading %s" +#~ msgstr "%s डाऊनलोड करत आहे" diff --git a/po/nb.po b/po/nb.po new file mode 100644 index 0000000..0e0ed84 --- /dev/null +++ b/po/nb.po @@ -0,0 +1,5656 @@ +# translation of zypp.po to norsk bokmål +# translation of zypp.po to +# Norwegian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2002 SuSE GmbH. +# Olav Pettershagen , 2006, 2007. +# Rune Nordbøe Skillingstad , 2007. +# Olav Pettershagen , 2008, 2009, 2013. +# Olav P. , 2008. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2022-05-29 21:13+0000\n" +"Last-Translator: Karl Ove Hufthammer \n" +"Language-Team: Norwegian Bokmål \n" +"Language: nb\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: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Ukjent land: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Ingen kode" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "De forente arabiske emirater" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua og Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +# AM +# fuzzy +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Argentina" + +# AN +# fuzzy +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Nederland" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktis" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +# fuzzy +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerika, Nord" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Østerrike" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +# CU +# fuzzy +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Åland" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Aserbadjan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia og Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgia" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasil" + +# BS +# fuzzy +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvetøya" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +# BZ +# fuzzy +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belgia" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosøyene" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +# fuzzy +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Den sentralafrikanske republikken" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Sveits" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Elfenbenskysten" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookøyene" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +# CU +# fuzzy +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kapp Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Christmasøya" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Kypros" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tsjekkia" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Tyskland" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danmark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Den dominikanske republikk" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algerie" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estland" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Vest-Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spania" + +# ET +# fuzzy +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Estonia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandsøyene (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikronesiaføderasjonen" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Færøyene" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Frankrike" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Frankrike (Europa)" + +# GH +# fuzzy +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Storbritannia" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Fransk Guiana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +# fuzzy +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grønland" + +# GM +# fuzzy +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Jamaica" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatorial-Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Hellas" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Sør-Georgia og De sørlige sandwichøyene" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +# GH +# fuzzy +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heardøya og Mcdonaldøyene" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungarn" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isle of Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britisk territorium i Indiahavet" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Israel" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +# KZ +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgisistan" + +# KH +# fuzzy +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodsja" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komorene" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "St. Kitts og Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Nord-Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Sør-Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Caymanøyene" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kasakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "St. Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +# LR +# fuzzy +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litauen" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvia" + +# LR +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libya" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshalløyene" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonia" + +# ML +# fuzzy +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Malta" + +# MM +# fuzzy +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Panama" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Nord-Marianene" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +# MR +# fuzzy +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Lituaisk" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Lituaisk" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Malta" + +# MW +# fuzzy +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malta" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mosambik" + +# GM +# fuzzy +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +# NC +# fuzzy +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Ny-Caledonia" + +# NG +# fuzzy +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolkøyene" + +# NG +# fuzzy +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nederland" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norge" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "New Zealand" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Fransk Polynesia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Ny-Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filippinene" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polen" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre og Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestina" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russland" + +# RW +# fuzzy +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi-Arabia" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomonøyene" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychellene" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Sverige" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "St. Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard og Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +# fuzzy +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome og Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Serbia" + +# SZ +# fuzzy +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Thailand" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- og Caicosøyene" + +# TD +# fuzzy +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tsjad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Sørlige franske territorier" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadsjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Øst-Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Tyrkia" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad og Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +# UG +# fuzzy +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Canada" + +# UM +# fuzzy +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Amerikas forente stater" + +# US +# fuzzy +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Amerikas forente stater" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Usbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikanstaten" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "St. Vincent og Grenadinene" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Jomfruøyene" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Jomfruøyene, USA" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis og Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Sør-Afrika" + +# ZM +# fuzzy +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Jamaica" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Inneholder" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Krever" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Konflikter" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "behold den foreldede pakken %s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Anbefalt" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Forslag" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Forbedringer" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Tillegg" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Forsøkte å importere ikke-eksisterende nøkkel %s til nøkkelring %s" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Kunne ikke importere offentlig nøkkel %1%" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Kunne ikke slette nøkkel." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Signaturfilen %s ikke funnet" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Ukjent språk: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +# AZ +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhasisk" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Akinesisk" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-asiatisk (annet)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikansk" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +# AZ +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akansk" + +# AZ +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadisk" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albansk" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutisk" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonquianske språk" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Sør-altaisk" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharisk" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Engelsk, gammelengelsk (ca. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apache-språk" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabisk" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Arameisk" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonesisk" + +# AM +# fuzzy +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armensk" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucaniansk" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Kunstspråk (annet)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamesisk" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturiansk" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapascanske språk" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australske språk" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarisk" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestasisk" + +# SZ +# fuzzy +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +# MM +# fuzzy +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Aserbadjansk" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke-språk" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkirisk" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinesisk" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskisk" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltisk (annet)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Belarusisk" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengalsk" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber-språk (annet)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (annet)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnisk" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonsk" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginesisk" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarsk" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmesisk" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Mellomamerikansk indiansk (annet)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Karibisk" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalansk" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukasisk (annet)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltisk (annet)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tsjetsjensk" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kinesisk" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook-sjargong" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Kirkeslavisk" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Chamiske språk" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptisk" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Kornisk" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsikansk" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreolsk og pidgin, engelskbasert (annet)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreolsk og pidgin, franskbasert (annet)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreolsk og pidgin, portugisiskbasert (annet)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krim-tatar" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreolsk og pidgin (annet)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kashubiansk" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitisk (annet)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tsjekkisk" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dansk" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slavisk (athapascansk)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidisk (annet)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Sorbiansk, nedre" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Mellomnederlandsk (ca. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nederlandsk" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egyptisk (gammelt)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamitisk" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engelsk" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Engelsk, mellomengelsk (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estisk" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Færøyisk" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fiji" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filippinsk" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finsk" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finsk-ugrisk (annet)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Fransk" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Fransk, mellomfransk (ca. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Fransk, gammelfransk (842-ca. 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisisk" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friuliansk" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +# GH +# fuzzy +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germansk (annet)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgisk" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Tysk" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertesisk" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gælisk" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irsk" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galisisk" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Mansk" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Tysk, mellomhøytysk (ca. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Tysk, gammelhøytysk (ca. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotisk" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Gresk, gammelgresk (til 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Gresk, moderne (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitisk" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiiansk" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebraisk" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittitisk" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hirimotu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Sorbiansk, øvre" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ungarsk" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandsk" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indisk (annet)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesisk" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoeuropeisk (annet)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingusj" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iransk (annet)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokesiske språk" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiensk" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanesisk" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japansk" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeopersisk" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeoarabisk" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmirsk" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kasakstansk" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardiansk" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (annet)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanesisk" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgisisk" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreansk" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraeansk" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdisk" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laotisk" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latin" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvisk" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghiansk" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgansk" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litauisk" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgisk" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +# GH +# fuzzy +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya og Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonsk" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Maduresisk" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallisk" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalamsk" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesisk (annet)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +# MW +# fuzzy +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malayisk" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +# MM +# fuzzy +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irsk, mellomirsk (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Diverse språk" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (annet)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagasisk" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltisk" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo-språk" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldovisk" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolsk" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Flere språk" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda-språk" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandesisk" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Maya-språk" + +# SY +# fuzzy +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Nordamerikansk indiansk" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitansk" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, sør" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, nord" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Lavtysk" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalsk" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepalsk bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-kordofaniansk (annet)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueansk" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norsk nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norsk bokmål" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norrønt, gammelnorrønt" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norsk" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho, nordlig" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubiske språk" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Klassisk Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Oksitansk (etter 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetisk" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Tyrkisk, ottomansk (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomianske språk" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuansk (annet)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinansk" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauansk" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persisk, gammelpersisk (ca. 600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persisk" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filippinsk (annet)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fønisisk" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polsk" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeiansk" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugisisk" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakrit-språk" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provensalsk, gammelprovensalsk (til 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongansk" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romansk (annet)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Retoromansk" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romsk" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumensk" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russisk" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Søramerikansk indiansk (annet)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salisjanske språk" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritansk arameisk" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbisk" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliansk" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Skotsk" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroatisk" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semittisk (annet)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irsk, gammelirsk (til 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Tegnspråk" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouanske språk" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sinotibetansk (annet)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavisk (annet)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakisk" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovensk" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sørsamisk" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Nordsamisk" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Samiske språk (annet)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lulesamisk" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Enaresamisk" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoisk" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skoltesamisk" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdiansk" + +# SO +# fuzzy +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalisk" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, sørlig" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spansk" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinsk" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilosaharansk (annet)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sudanesisk" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerisk" + +# SZ +# fuzzy +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Svensk" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syrisk" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitisk" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (annet)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamilsk" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadsjikisk" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalogsk" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetansk" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +# NG +# fuzzy +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingonsk" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamasjek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tongaøyene)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmensk" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi-språk" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Tyrkisk" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaisk (annet)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuviniansk" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritisk" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighursk" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainsk" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Udefinert" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Usbekistansk" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamesisk" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votisk" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakasjanske språk" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Walisisk" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbianske språk" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Wallonsk" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapesisk" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +# CU +# fuzzy +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupik-språk" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Følgende handlinger vil bli utført:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "(utløper ikke)" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(utløper ikke)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(UTLØPT)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(utløper innen 24 t)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, fuzzy, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(utløper innen 24 t)" +msgstr[1] "(utløper innen 24 t)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "ukjent" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "støttes ikke" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Nivå 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Nivå 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Nivå 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Kundekontrakt kreves" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "ugyldig" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Brukerstøttenivå er ikke angitt" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Produsenten tilbyr ikke støtte." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Problembeskrivelse, dvs. teknisk støtte som er utformet for å gi informasjon " +"om kompatibilitet, installasjonshjelp, brukerstøtte, kontinuerlig " +"vedlikehold og grunnleggende feilsøking. Nivå 1-brukerstøtte omfatter ikke " +"retting av produktfeil." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Problemidentifikasjon, dvs. teknisk støtte som er utformet for å gjenskape " +"kundens problemer, identifisere problemområdet og løse problemer som ikke " +"blir løst med Nivå 1-brukerstøtte." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Problemløsning, dvs. teknisk støtte som er utformet for å løse sammensatte " +"problemer ved hjelp av teknisk ekspertise, og som kan rette produktfeil som " +"er identifisert med Nivå 2-brukerstøtte." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Brukerstøtte krever en tilleggskundekontrakt." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Ukjent brukerstøttevalg. Ingen beskrivelse tilgjengelig" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Systemadministrasjonen er låst av programmet med pid %d (%s).\n" +"Lukk dette programmet før du forsøker igjen." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Ukjent samsvarsmodus '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Ukjent samsvarsmodus '%s' for mønsteret '%s'." + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Ugyldig regulært uttrykk '%s': tilbakemelding 'regcomp' %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ugyldig regulært uttrykk '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autentisering kreves for '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Besøk Novell kundesenter for å kontrollere om din registrering er gyldig og " +"ikke er utløpt." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Installer pakken 'lsof' først." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Kan ikke opprette katalog for metadatamellomlager." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Feil under lesing fra '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Kan ikke opprette %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +#, fuzzy +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Ingen gyldige metadata funnet på spesifisert(e) nettadresse(r)" +msgstr[1] "Ingen gyldige metadata funnet på spesifisert(e) nettadresse(r)" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Kunne ikke mellomlagre pakkebrønn (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Bygger pakkebrønnmellomlager '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Kan ikke opprette mellomlager på %s - skrivebeskyttet." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Pakkebrønntypen er ugyldig" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Legger til pakkebrønn '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Ugyldig pakkebrønnfilnavn på '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Kan ikke åpne filen '%s' for å skrive til den." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Ukjent feil ved lesing fra '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Kunnne ikke lese katalogen: '%s'." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Fjerner pakkebrønnen '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Finner ikke ut hvor pakkebrønnen er lagret." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Kan ikke slette '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Finner ikke ut hvor tjenesten er lagret." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Et pakkebrønnalias kan ikke begynne med punktum." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Tjenestealiaset kan ikke begynne med punktum." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Vil du fortsette?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Nødvendig attributt '%s' mangler." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Én eller begge attributtene '%s' eller '%s' kreves." + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr " kjøring mislyktes" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Det ser ut til at pakken %s har blitt skadet under overføring. Vil du prøve " +"å laste den ned på nytt?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Kunne ikke hente pakken %s. Vil du førsøke å hente den på nytt?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm-kontroll mislyktes." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm mislyktes." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "ressurstypen VAR1 støtter ikke funksjonen 'vis endringer'" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Kan ikke hente filen '%s' i pakkebrønnen '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Ingen nettadresse i pakkebrønn." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Kan ikke opprette sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "ignorer noen avhengigheter selv om %s ikke vil fungere" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "ignorer generelt noen avhengigheter" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "kommandokonflikter" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "en konflikt" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "forespørselen støttes ikke" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "slettede leverandører: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"uinstallerbare nødvendige pakker: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "uinstallerbare nødvendige pakker: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Denne kommandoen vil skade systemet!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorer advarsel om skadet system" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Installasjonen er avbrutt som angitt." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " kjørt" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " kjøring mislyktes" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s allerede kjørt som %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " kjøring ikke utført under avbrudd" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Feil ved sending av melding om oppdatering." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Melding om ny oppdatering" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM mislyktes: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Kunne ikke importere offentlig nøkkel %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Kunne ikke fjerne offentlig nøkkel %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Endrede konfigurasjonsfiler for %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm lagret %s som %s, men det var umulig å finne noen forskjell" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm lagret %s som %s.\n" +"Her er de 25 første avvikende linjene:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm opprettet %s som %s, men det var umulig å finne noen forskjell" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm opprettet %s som %s.\n" +"Her er de 25 første avvikende linjene:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Flere rpm-resultater" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "opprettet sikkerhetskopi %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Signaturfilen %s ikke funnet" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Signaturfilen %s ikke funnet" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Signaturfilen %s ikke funnet" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Fil er usignert" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tvilsom type '%s' for %u byte-kontrollsum '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Kunne ikke åpne pty: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Kan ikke åpne pipe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Ugyldig LDAP URL-spørringsstreng" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Ugyldig LDAP URL-spørringsparameter %s" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Kan ikke klone URL-objekt" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Ugyldig referanse til tomt URL-objekt" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Kan ikke analysere URL-komponenter" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historie:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Adressestrategi tillater ikke %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Ugyldig %s komponent %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Ugyldig %s komponent" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Analyse av spørringsstreng støttes ikke for denne URL-en" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Adressestrategi er en obligatorisk komponent" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Ugyldig adressestrategi %s" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Adressestrategi tillater ikke brukernavn" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Adressestrategi tillater ikke passord" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Adressestrategi krever en vertskomponent" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Adressestrategi tillater ikke en vertskomponent" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Ugyldig vertskomponent %s" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Adressestrategi tillater ikke port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Ugyldig portkomponent %s" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Adressestrategi krever banenavn" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relativ sti ikke tillatt hvis autoritet finnes" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Kodet streng inneholder nullbyte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Ugyldig skilletegn for deling av parametermatrise" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Ugyldig skilletegn for deling av parametertilordning" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Ugyldig skilletegn for sammenføyning av parametermatrise" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Kommandoen ble avsluttet med status %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Kommandoen ble drept av signalet %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Kommandoen ble avsluttet med en ukjent feil." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Kan ikke kjøre chroot til '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Kan ikke kjøre chdir til «%s» (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Kan ikke kjøre chdir til «%s» fra chroot «%s» (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Kan ikke kjøre '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Kan ikke splitte (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Kunne ikke montere %s på %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Kunne ikke avmontere %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Ugyldig filnavn: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Mediet ble ikke åpnet da handlingen ble forsøkt utført '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Filen '%s' ikke funnet på medium '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Kan ikke lagre filen '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Medium ikke tilkoblet" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Ugyldig tilkoblingspunkt for medier" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Initialisering av nedlasting (curl) mislyktes for '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Systemunntak '%s' på mediet '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Stien '%s' på mediet '%s' er ikke en fil." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Stien '%s' på mediet '%s' er ikke en katalog." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Feilformatert URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Vertsnavn mangler i URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Filsystem mangler i URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destinasjon mangler i URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "URI-skjema som ikke støttes i '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Handlingen støttes ikke av mediet" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Nedlastingsfeil (curl) for '%s':\n" +"Feilkode: %s\n" +"Feilmelding: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Feil under definisjon av nedlastingsvalg (curl) for '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Mediekilde '%s' inneholder ikke ønsket medium" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Mediet '%s' benyttes av en annen prosess" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Kan ikke løse ut medium" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Kan ikke løse ut mediet '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Tilgang til '%s' avvist." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Tidsavbrudd under tilgang '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Plasseringen '%s' er midlertidig utilgjengelig." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL-sertifikatproblem, bekreft at CA-sertifikat er OK for '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "HTTP-autentiseringsmetode '%s' er ikke støttet" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ja" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nei" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Advarsel: " + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Feil" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "fullført" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "feil" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Advarsel: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Henter:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "starter" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Ikke funnet" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Ingen tilgjengelig hjelp for denne meldingen." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "ingen tilgjengelig hjelp for dette valget" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ja" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nei" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s tilhører ikke en pakkebrønn for distribusjonsoppgradering" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s har foreldet arkitektur" + +#~ msgid "problem with installed package %s" +#~ msgstr "problem med den installerte pakken %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "ingenting inneholder den nødvendige %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Har du aktivert alle nødvendige pakkebrønner?" + +#~ msgid "package %s does not exist" +#~ msgstr "pakken %s finnes ikke" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s er beskyttet av systemet, og kan ikke slettes." + +#~ msgid "%s is not installable" +#~ msgstr "%s kan ikke installeres" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "ingenting inneholder %s som kreves av %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "kan ikke installere både %s og %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s er i konflikt med %s fra %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s foreldede pakker %s fra %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "installert %s foreldede %s fra %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "løsningen %s er i konflikt med %s som den selv inneholder" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s krever %s, men denne nødvendige filen finnes ikke" + +#~ msgid "do not install %s" +#~ msgstr "Ikke installer %s" + +#~ msgid "keep %s" +#~ msgstr "behold %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "ikke forby installasjon av %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "ikke be om å installere en nødvendig pakke som gir %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "ikke be om å slette alle nødvendige pakker som gir %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "ikke installer nyeste versjon av %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "behold %s selv om arkitekturen er feil" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "installer %s selv om arkitekturen ikke er riktig" + +#~ msgid "keep obsolete %s" +#~ msgstr "behold den foreldede pakken %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "installer %s fra deaktivert pakkebrønn" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "nedgradering av %s til %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "Arkitekturendring fra %s til %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "installer %s (med produsentendring)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "%s erstattes av %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "avinstallasjon av %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Kan ikke åpne låsefil: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Denne handlingen utføres allerede av et annet program." + +#~ msgid "Hal Exception" +#~ msgstr "Hal-unntak" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Beklager, men denne versjonen av libzypp er kompilert uten HAL-støtte." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext ikke tilkoblet" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive ikke initialisert" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume ikke initialisert" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Kan ikke opprette dbus-tilkobling" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Kan ikke opprette libhal-kontekst" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Kan ikke angi dbus-tilkobling" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Kan ikke initialisere HAL-kontekst, kjører ikke hald?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Ikke en CD-ROM-stasjon" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Kan ikke initialisere muteksattributter" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Kan ikke angi rekursive muteksattributter" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Kan ikke initialisere rekursiv muteks" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Kan ikke oppnå mutekslås" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Kan ikke frigi mutekslås" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Kunne ikke importere offentlig nøkkel fra filen %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Kunne ikke fjerne offentlig nøkkel %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Kan ikke finne noen tilgjengelig loop-enhet for å montere diskbildefilen " +#~ "fra '%s'" + +#~ msgid "do not keep %s installed" +#~ msgstr "ikke behold %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Kan ikke opprette den offentlige nøkkelen %s fra %s nøkkelringen for " +#~ "filen %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Initialisering av nedlasting (Metalink curl) mislyktes for '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Nedlastingsfeil (curl) for '%s':\n" +#~ "Feilkode: %s\n" +#~ "Feilmelding: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Nedlasting avbrutt %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Nedlasting avbrutt av bruker" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Det oppstod en feil under definisjon av nedlastingsvalg (metalink curl) " +#~ "for '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Kunne ikke laste ned %s fra %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia og Montenegro" + +#~ msgid "Unknown Distribution" +#~ msgstr "Ukjent distribusjon" + +#~| msgid "Ignore some dependencies of %s" +#~ msgid "ignore some dependencies of %s" +#~ msgstr "ignorer noen avhengigheter for '%s'" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s har ingen kontrollsum.\n" +#~ "Vil du bruke filen likevel?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s bestod ikke integritetskontroll med følgende nøkkel:\n" +#~ "%s|%s|%s\n" +#~ " Vil du bruke filen likevel?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s har en ukjent kontrollsum \n" +#~ ".Forventet %s, men finner %s\n" +#~ " Vil du bruke filen likevel?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s har en ukjent kontrollsum %s.\n" +#~ "Vil du bruke filen likevel?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Filen %s er ikke signert.\n" +#~ "Vil du bruke den likevel?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s er signert med en ukjent nøkkel:\n" +#~ "%s|%s|%s\n" +#~ " Vil du bruke filen likevel?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Upålitelig nøkkel funnet:\n" +#~ "%s|%s|%s\n" +#~ " Skal nøkkelen klareres likevel?" + +#~ msgid "%s remove failed" +#~ msgstr "%s avinstallasjon mislyktes" + +#~ msgid "Invalid user name or password." +#~ msgstr "Ugyldig brukernavn eller passord." + +#~ msgid "rpm output:" +#~ msgstr "rpm-resultat:" diff --git a/po/nl.po b/po/nl.po new file mode 100644 index 0000000..aab5d25 --- /dev/null +++ b/po/nl.po @@ -0,0 +1,5639 @@ +# translation of zypp.nl.po to Dutch +# Dutch message file for YaST 2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999, 2000, 2001 SuSE GmbH. +# +# A.S. Kerkmeester , 1999, 2000, 2001. +# FAX-Translations , 2000. +# Karl Eichwalder , 1999, 2000. +# Martin Lohner , 2000. +# peter@sybex.nl, 2000. +# Rinse de Vries , 2006, 2007, 2008. +# Freek de Kruijf , 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: zypp.nl\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-16 09:47+0000\n" +"Last-Translator: Freek de Kruijf \n" +"Language-Team: Dutch " +"\n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Onbekend land: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Geen code" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Verenigde Arabische Emiraten" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua en Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanië" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenië" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Nederlandse Antillen" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# /usr/lib/YaST2/clients/dialup_dev_cfg.ycp:80 +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarctica" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentinië" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikaans-Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Oostenrijk" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australië" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Åland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbeidzjan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnië en Herzegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "België" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgarije" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrein" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazilië" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahama's" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouveteiland" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Wit-Rusland" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Cocoseilanden" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Centraal Afrikaanse Republiek" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Zwitserland" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Ivoorkust" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookeilanden" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chili" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kameroen" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kaapverdië" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Christmaseiland" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cyprus" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tsjechië" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Duitsland" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Denemarken" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominicaanse Republiek" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algerije" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estland" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypte" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Westelijke Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanje" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Ethiopië" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandeilanden" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federale staten van Micronesia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faeröer" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Frankrijk" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Metropolitaans Frankrijk" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Verenigd Koninkrijk" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgië" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Frans-Guyana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinee" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Equatoriaal-Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Griekenland" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Zuid-Georgia en de Zuidelijke Sandwicheilanden" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinee-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard en McDonaldeilanden" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatië" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haïti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hongarije" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesië" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ierland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israël" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Man (eiland)" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Brits Indische Oceaanterritorium" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "IJsland" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italië" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordanië" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgizië" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodja" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comoren" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts en Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Noord-Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Zuid-Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Koeweit" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kaaimaneilanden" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazachstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Democratische Volksrepubliek Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Sint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litouwen" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letland" + +# ../../db/printers.ycp.noloc:1400 +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libië" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavië" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Sint-Maarten" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshalleilanden" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonië" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolië" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macau" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Noordelijke Marianen" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritanië" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Malediven" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Maleisië" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibië" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nieuw-Caledonië" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk (eiland)" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nederland" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noorwegen" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nieuw-Zeeland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Frans-Polynesië" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papoea-Nieuw-Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipijnen" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polen" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint-Pierre en Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestijns Gebied" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Roemenië" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Servië" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russische Federatie" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saoedi-Arabië" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salomonseilanden" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychellen" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Soedan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Zweden" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sint-Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenië" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard en Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slowakije" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalië" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome en Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syrië" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- en Caicoseilanden" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tsjaad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Frans Zuidelijke Gebieden" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadzjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunesië" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Oost-Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkije" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad en Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Oekraïne" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Oeganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Kleine afgelegen eilanden van de Verenigde Staten" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Verenigde Staten" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Oezbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Staat Vaticaanstad" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Sint Vincent en de Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britse Maagdeneilanden" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Maagdeneilanden, V.S." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# /usr/lib/YaST2/clients/dialup_dev_cfg.ycp:82 +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis en Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Zuid-Afrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Levert" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Vereisten" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Vereist" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "In conflict met" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Verouderde onderdelen" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Beveelt aan" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Suggereert" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Verbetert" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Vult aan" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" +"Er is een poging gedaan om een niet-bestaande sleutel, ‘%s’, te importeren " +"in sleutelbos %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Het importeren is mislukt." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Het verwijderen is mislukt." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Het ondertekeningbestand, ‘%s’, is niet aangetroffen" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Onbekende taal: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar, Hamitisch" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abchazisch" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinees" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acholi" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adygees" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Aziatisch (overig)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Aino" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akaans" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadiaans" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanees" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleuts" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonquian-talen" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Zuid-Altai" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amhaars, Amharisch" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Engels, Oud (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apache-talen" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabisch" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramees" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonees" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armeens" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucaniaans" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Kunstmatig (overig)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamees, Assami" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturisch" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapascan-talen" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australische talen" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avaars, Awari" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestisch" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azeri, Azerbeidzjaans" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke-talen" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Basjkiers, Basjkirisch" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Balutsji, Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinees" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskisch" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Balinees" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltisch (overig)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Wit-Russisch" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengaals" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berbers (overig)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (overig)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnisch" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretons, Bretoens" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesië)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Boeriaats" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginees" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgaars" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmees" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Centraal-Amerikaans Indiaans (overig)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Caraïbisch" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalaans" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukasisch (overig)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltisch (overig)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Tsjibtsja" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tsjetsjeens" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinees" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook-jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyaans" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Kerkslavisch" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Tsjoevasjisch" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Chamische talen" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptisch" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornish" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corsicaans" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creools en Pidgin, op basis van Engels (overig)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creools en Pidgin, op basis van Frans (overig)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creools en Pidgin, op basis van Portugees (overig)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +# /usr/lib/YaST2/clients/lan_dns.ycp:87 +# /usr/lib/YaST2/clients/lan_dns.ycp:87 +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krim-Tataars" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creools en Pidgin (overig)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kasjoebisch" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cusjitisch (overig)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tsjechisch" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Deens" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slavisch (Athapascaans)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidiaans (overig)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Nedersorbisch" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Nederlands, middel (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nederlands" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efikisch" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egyptisch (Oud)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamitisch" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engels" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Engels, Middel (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Ests" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faeröers" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijisch" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipijns" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Fins" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fins-Oegrisch (overig)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Frans" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Frans, Middel (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Frans, Oud (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Fries" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulisch" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germaans (overig)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgisch" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Duits" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertees" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Iers" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galicisch" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Duits, Middel Hoog (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Duits, Oud Hoog (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gothisch" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grieks, Oud (tot 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grieks, Modern (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haïtiaans" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiiaans" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebreeuws" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligainoons" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himatsjali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittitisch" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Oppersorbisch" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Hongaars" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Ibaans" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "IJslands" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sitsjuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indisch (overig)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesisch" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-Europees (overig)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingoesjetisch" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiak" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraans (overig)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Iroquoian-talen" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiaans" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javaans" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojbaans" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japans" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeo-Perzisch" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeo-Arabisch" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Katsjin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Groenlands" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada, Kanara, Kanarees" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kasjmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazachs" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardisch, Tsjerkessisch" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisaans (overig)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanees" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Gikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgizisch" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Congo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreaans" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraeaans" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karatsjay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Koerdisch" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenaïsch" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laotiaans" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latijn" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Lets" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghiaans" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgs" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litouws" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgs" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenia en Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedonisch" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurees" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahisch" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallees" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesisch (overig)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Maleis" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksja" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandars" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Iers, Middel (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Diverse talen" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (overig)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Plateaumalagasi" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltees" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo-talen" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavisch" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongools" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossisch" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Meerdere talen" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda-talen" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandees" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Maya-talen" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Noord-Amerikaans Indiaans" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitaans" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, Zuid" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, Noord" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Zuid-Duits" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalees" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Niaas" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofaniaans (overig)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueaans" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Noors Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Nynorsk en Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Noors, Oud" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Noors" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Noord-Sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubische talen" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Klassiek Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankools" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitaans (na 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osaags" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetisch, Osseets" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turks, Ottomaans (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Otomi-talen" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuaans (overig)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinaans" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pehlevi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Punjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauaans" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Perzisch, Oud (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Perzisch" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipijns (overig)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Foenisisch" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Pools" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeiaans" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugees" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakrit-talen" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provençaals, oud (tot 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Poesjto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongaans" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romaans (overig)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Retoromaans" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Roma" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Roemeens" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russisch" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Jakoets" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Zuid-Amerikaans Indiaans (overig)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salishan-talen" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritaans Aramees" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskriet" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasaaks" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Servisch" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliaans" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Schots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroatisch" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Sulkoeps" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitisch (overig)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Iers, Oud (tot 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Gebarentalen" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Sjaans" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singalees" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouaanse talen" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetaans (overig)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavisch (overig)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slowaaks" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Sloveens" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Zuid-Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Noord-Sami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Sami-talen (overig)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoaans" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdiaans" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalisch" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhaïsch" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Zuid-Sothaans" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spaans" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardinisch" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Saharaans (overig)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Soendanees" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerisch" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Zweeds" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syrisch" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitisch" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (overig)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tataars" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadzjieks" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetaans" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamasjek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tonga-eilanden)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimsjiaans" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmeens" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupi-talen" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turks" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaïsch (overig)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuviniaans" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurts" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritisch" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Oeigoers, Oejgoers" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Oekraïens" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Onbepaald" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Oezbeeks" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamees" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votisch" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakashan-talen" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Wasjo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Welsh" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbische talen" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Waals" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapees" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jiddisch" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupik-talen" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "De volgende acties worden uitgevoerd:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "vervalt niet" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "vervallen op %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "vervalt op %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(vervalt niet)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(VERVALLEN)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(vervalt binnen 24 uur)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(vervalt binnen %d dag)" +msgstr[1] "(vervalt binnen %d dagen)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "onbekend" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "niet ondersteund" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Niveau 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Niveau 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Niveau 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Aanvullend gebruikerscontract noodzakelijk" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Gestopt en opgevolgd door een ander pakket" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "ongeldig" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Het ondersteuningsniveau is niet gedefinieerd" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "De verkoper levert geen ondersteuning." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Probleembepaling, wat technische ondersteuning betekent die is ontworpen " +"voor het leveren van informatie over compatibiliteit, hulp bij installatie, " +"ondersteuning bij gebruik, constant onderhoud en algemene " +"probleemoplossing.. Niveau 1 ondersteuning is niet bedoeld om fouten in " +"producten te verbeteren." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Probleemisolatie, wat technische ondersteuning betekent voor reproduceren " +"van problemen bij klanten, probleemgebieden bepalen en oplossingen leveren " +"voor problemen die niet opgelost worden door Niveau 1 ondersteuning." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Probleemoplossing, wat technische ondersteuning betekent voor het oplossen " +"van complexe problemen door engineering in te schakelen bij het oplossen van " +"productfouten die geïdentificeerd zijn in Niveau 2 ondersteuning." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" +"Een aanvullend gebruikerscontract is noodzakelijk voor het verkrijgen van " +"ondersteuning." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"Het pakket is gestopt en is opgevolgd door een nieuw pakket met een andere " +"naam." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Onbekende ondersteuningsoptie. Beschrijving niet beschikbaar" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Systeembeheer is geblokkeerd door de toepassing met pid %d (%s).\n" +"Sluit deze toepassing voordat u het opnieuw probeert." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Onbekende overeenkomstmodus '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Onbekende overeenkomstmodus '%s' voor patroon '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Ongeldige reguliere expressie '%s': regcomp heeft %d geretourneerd" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ongeldige reguliere expressie '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Authenticatie vereist voor '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Zal het opnieuw proberen..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Opgegeven na %1% pogingen." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Het SUSE Customer Center bezoeken om te controleren of uw registratie geldig " +"is en niet is verlopen." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Ga naar het Novell Customer Center om te controleren of uw registratie " +"geldig is en niet is verlopen." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Aanknooppunt aanmaken: Kan geen beschrijfbare map vinden om een aanknooppunt " +"aan te maken" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Eerst pakket 'lsof' installeren." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Kan map voor metadata-cache niet aanmaken." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Fout bij het lezen van '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Kan %s niet aanmaken" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Geen geldige metagegevens op de gespecificeerde URL gevonden" +msgstr[1] "Geen geldige metagegevens op de gespecificeerde URL's gevonden" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" +"In cache opslaan van opslagruimte is mislukt ( starten van repo2solv lukt " +"niet )." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Kan opslagruimte (%d) niet opslaan in de cache." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Cache van opslagruimte '%s' wordt gebouwd" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Kan cache in %s niet aanmaken - geen toegangsrechten." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "Opslagruimte %1% opslaan in cache is mislukt" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Niet behandeld type opslagruimte" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Bezig met toevoegen van installatiebron ‘%s’…" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Ongeldige naam van installatiebronbestand bij ‘%s’" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Kan bestand '%s' niet openen voor schrijven." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Onbekende fout bij lezen van '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Kan map '%1%' van opslagruimte niet lezen: Toegang geweigerd" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Het lezen van map '%s' is mislukt" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Kan opslagruimtebestand '%1%' niet lezen: Toegang geweigerd" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "Metagegevens worden opgeschoond" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "Pakketten worden opgeschoond" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "Mappen voor cache worden opgeschoond" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "Map %1% wordt opgeschoond" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "Cache wordt opgeschoond" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "Uit cache laden" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Bezig met verwijderen van installatiebron ‘%s’…" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Kan niet achterhalen waar opslagruimte is opgeslagen." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "‘%s’ kan niet worden verwijderd" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "Opslagruimte wijzigen" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "Opslagruimte wordt ververst: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Kan er niet achter komen waar de service is opgeslagen." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Onbekende service '%1%': Verweesde opslagruimte '%2%' verwijderen" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "De alias van een opslagruimte mag niet met een punt (.) beginnen." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "De alias van een service mag niet met een punt (.) beginnen." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Geen samenvatting voor bestand %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Onbekende samenvatting %s voor bestand %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Verificatie van samenvatting is mislukt voor bestand '%s'" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Bestand '%s' is ondertekend, doorgaan?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Bestand '%s' uit opslagruimte '%s' is niet ondertekend, doorgaan?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Wilt u de sleutel afwijzen, tijdelijk vertrouwen of altijd vertrouwen?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Sleutelnaam: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +"Ontvangen %1% nieuwe sleutel voor ondertekening van pakketten uit " +"opslagruimte \"%2%\":" +msgstr[1] "" +"Ontvangen %1% nieuwe sleutels voor ondertekening van pakketten uit " +"opslagruimte \"%2%\":" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Verificatie van ondertekening is mislukt voor bestand '%1%'." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"Verificatie van ondertekening is mislukt voor bestand '%1%' uit opslagruimte " +"'%2%'." + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Wilt u doorgaan?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Bestand '%s' is ondertekend met een onbekende sleutel '%s'. Doorgaan?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Bestand '%s' uit opslagruimte '%s' is ondertekend met een onbekende sleutel " +"'%s'. Doorgaan?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Opslagruimte %1% definieert geen extra URL's met 'gpgkey='." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Bezig met zoeken naar gpg-sleutel-id ‘%1%’ in %2%-installatiebron…" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Bezig met zoeken naar gpg-sleutel-id ‘%1%’ in %2%-cache…" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Vereist attribuut '%s' ontbreekt." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Een of beide kenmerken van '%s' of '%s' zijn vereist." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Verificatie van de ondertekening is mislukt" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Het pakket, ‘%s’, lijkt beschadigd te zijn tijdens de overdracht. Wilt u het " +"opnieuw ophalen?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Het pakket, ‘%s’, is niet aangetroffen. Wilt u het opnieuw ophalen?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "controle van applydeltarpm is mislukt." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm mislukt." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Service-plug-in ondersteunt geen wijzigen van een attribuut." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Kan bestand '%s' niet leveren uit opslagruimte '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Geen URL in opslagruimte." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "Verwacht medium %1%/%2% geïdentificeerd door bestand '%3%' met inhoud:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Het bestand ‘%1%’\n" +" in het pakket\n" +" %2%\n" +" botst met een bestand in het pakket\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Het bestand ‘%1%’\n" +" in het pakket\n" +" %2%\n" +" botst met een geïnstalleerd bestand van\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Het bestand ‘%1%’\n" +" van de installatie van\n" +" %2%\n" +" botst met een bestand van het pakket\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Het bestand ‘%1%’\n" +" van de installatie van\n" +" %2%\n" +" botst met een bestand van de installatie van\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Het bestand ‘%1%’\n" +" in het pakket\n" +" %2%\n" +" botst met het bestand\n" +" %3%\n" +" in het pakket\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Het bestand ‘%1%’\n" +" in het pakket\n" +" %2%\n" +" botst met het bestand\n" +" %3%\n" +" van de installatie van\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Het bestand ‘%1%’\n" +" van de installatie van\n" +" %2%\n" +" botst met het bestand\n" +" %3%\n" +" in het pakket\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Het bestand ‘%1%’\n" +" van de installatie van\n" +" %2%\n" +" botst met het bestand\n" +" %3%\n" +" van de installatie van\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Kan sat-pool niet maken." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "doorbreek ‘%s’ door enkele afhankelijkheden te negeren" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "negeer normaliter enige afhankelijkheden" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"de geïnstalleerde %1% behoort niet tot een opslagruimte voor een " +"opwaardering van de distributie en moet vervangen worden" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" +"de te installeren %1% behoort niet tot een opslagruimte voor opwaarderen van " +"een distributie" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "de geïnstalleerde %1% heeft een inferieure architectuur" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "de te installeren %1% heeft een inferieure architectuur" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "er is een probleem met het geïnstalleerde pakket ‘%1%’" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "conflicterende verzoeken" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "een afhankelijkheidsprobleem" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "niets levert de gevraagde ‘%1%’" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Zijn alle vereiste installatiebronnen ingeschakeld?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "het gevraagde pakket, ‘%1%’, bestaat niet" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "niet-ondersteund verzoek" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' wordt geleverd door het systeem en kan niet gewist worden" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% is niet te installeren" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" +"er is geen pakket dat ‘%1%’ levert, benodigd door het geïnstalleerde %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" +"er is geen pakket dat ‘%1%’ levert, benodigd door het te installeren %2%" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "zowel %1% als %2% kunnen niet worden geïnstalleerd" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"het geïnstalleerde %1% botst met ‘%2%’, zoals geleverd door het " +"geïnstalleerde %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"het geïnstalleerde %1% botst met ‘%2%’, zoals geleverd door het te " +"installeren %3%" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"het te installeren %1% botst met ‘%2%’, zoals geleverd door het " +"geïnstalleerde %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"het te installeren %1% botst met ‘%2%’, zoals geleverd door het te " +"installeren %3%" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"het geïnstalleerde %1% markeert ‘%2%’, geleverd door het geïnstalleerde %3%, " +"als verouderd" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"het geïnstalleerde %1% markeert ‘%2%’, geleverd door het te installeren %3%, " +"als verouderd" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"het te installeren %1% markeert ‘%2%’, geleverd door het geïnstalleerde %3%, " +"als verouderd" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"het te installeren %1% markeert ‘%2%’, geleverd door het te installeren %3%, " +"als verouderd" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "het geïnstalleerde %1% botst met ‘%2%’ dat zichzelf aanlevert" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "het te installeren %1% botst met ‘%2%’ dat zichzelf aanlevert" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"het geïnstalleerde %1% vereist ‘%2%’, maar deze vereiste kan niet geleverd " +"worden" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"het te installeren %1% vereist ‘%2%’, maar deze vereiste kan niet geleverd " +"worden" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "verwijderde diensten: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"niet-installeerbare diensten: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "niet-installeerbare diensten: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% is nog niet volledig geïntegreerd in %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Normaliter is het het beste als u de PTF wilt behouden en kiest om de " +"patches voor onderhoud niet te installeren." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Het geïnstalleerde %1% in deze context zal de meegenomen PTF-pakketten ook " +"verwijderen (niet vervangen)." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"De PTF zou verwijderd moeten worden door '%1%' aan te roepen. Dit zal de " +"meegenomen PTF-pakketten bijwerken in plaats van ze te verwijderen." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "U wilt typisch de PTF behouden of kies om de actie te annuleren." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "De geïnstalleerde %1% blokkeert de gewenste actie." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" +"U wilt typisch de PTF behouden en er voor kiezen de actie te annuleren." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "vergrendeling opheffen om verwijdering van %1% toe te staan" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "%1% niet installeren" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "%1% behouden" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "vergrendeling opheffen om installatie van %1% toe te staan" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Dit verzoek zal het systeem laten crashen!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "negeer de waarschuwing voor een gebroken systeem" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "niet vragen om een oplosbare te installeren die %1% levert" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "niet vragen om alle oplosbaren te verwijderen die %1% levert" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "recentste versie van %1% niet installeren" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "%1% behouden, ondanks de inferieure architectuur" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "%1% installeren, ondanks de inferieure architectuur" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "behoud het verouderde pakket ‘%1%’" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "%1% installeren uit genegeerde installatiebron" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "%1% installeren, hoewel het is ingetrokken" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "toestaan de PTF %1% te installeren" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "%1% installeren hoewel het op de zwarte lijst staat" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "%1% afwaarderen naar %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "architectuur van %1% wijzigen naar %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"%1% installeren (met leverancierswijziging)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"installeer %1% van leverancier %2%\n" +" ter vervanging van %3% van leverancier %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "%1% vervangen door %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "verwijder ‘%1%’" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Scripts voor post-transaction uitvoeren" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Script %1% wordt uitgevoerd" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Uitvoer van script %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "De installatie is op verzoek afgebroken." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " uitgevoerd" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " het uitvoeren is mislukt" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s is al uitgevoerd als %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " uitvoeren is overgeslagen tijdens afbreken" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Het bijwerkbericht kan niet worden verstuurd." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nieuw updatebericht" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Ontvangen signaal :\"%1% (%2%)\", om de consistentie van het systeem te " +"verzekeren is het niet mogelijk om een actieve rpm-transactie te annuleren." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" +"Het uitvoeren van de overdracht is vanwege de volgende problemen mislukt:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM is mislukt: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Het importeren van de publieke sleutel %1% is mislukt" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Het verwijderen van de publieke sleutel %1% is mislukt" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "De pakketkop is niet ondertekend!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "De pakketinhoud is niet ondertekend!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Configuratiebestanden gewijzigd voor %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm heeft %s opgeslagen als %s, maar het was niet mogelijk om het verschil " +"te bepalen" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm sloeg %s op als %s.\n" +"Dit zijn de eerste 25 regels die verschillend zijn:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm maakte %s aan als %s, maar het was niet mogelijk om het verschil te " +"achterhalen" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm maakt %s aan als %s.\n" +"Dit zijn de eerste 25 regels die verschillen:\n" + +# /usr/lib/YaST2/clients/lan_inetd_custom.ycp:162 +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Aanvullende rpm-uitvoer" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "reservekopie %s aangemaakt" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "De ondertekening is in orde" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Onbekend type ondertekening" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Ondertekening klopt niet" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Ondertekening is OK, maar sleutel kan niet worden vertrouwd" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Handtekeningen van publieke sleutel zijn niet beschikbaar" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Bestand bestaat niet of ondertekening kan niet gecontroleerd worden" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Bestand heeft geen ondertekening" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Twijfelachtig type '%s' voor %u bytes controlesom '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Kan pty (%s) niet openen." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Kan pipe (%s) niet openen." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Ongeldige LDAP-URL-querytekenreeks" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Ongeldige LDAP-URL-queryparameter '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Kan URL-object niet klonen" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Ongeldige lege URL-objectverwijzing" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Kan URL-componenten niet analyseren" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Geschiedenis:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "%s is niet toegestaan in URL-schema" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Ongeldige %s-component '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Ongeldige %s-component" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Parseren van queryreeks wordt niet ondersteund voor deze URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL-schema is een vereiste component" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Ongeldig URL-schema '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Gebruikersnaam is niet toegestaan in URL-schema" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Wachtwoord is niet toegestaan in URL-schema" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "URL-schema vereist hostcomponent" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Hostcomponent is niet toegestaan in URL-schema" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Ongeldige hostcomponent '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Poort is niet toegestaan in URL-schema" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Ongeldige poortcomponent '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "URL-schema vereist padnaam" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relatief pad is niet toegestaan als authority bestaat" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Gecodeerde reeks bevat een NUL byte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Ongeldig scheidingsteken voor splitsen parametermatrix" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Ongeldig scheidingsteken voor splitsen parametertoewijzing" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Ongeldig scheidingsteken voor samenvoegen parametermatrix" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "De opdracht is beëindigd met status %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "De opdracht is afgebroken door signaal %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "De opdracht is beëindigd met een onbekende foutmelding." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Ongeldige afsplits argumenten gegeven." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Pipe voor besturing maken lukt niet." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Kan geen chroot doen naar '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Kan geen chdir doen naar '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Kan geen chdir naar '%s' doen binnen chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Kan '%s' niet uitvoeren (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Kan geen fork (%s) uitvoeren." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Kan '%s' niet uitvoeren, chdir is mislukt (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "'%s' uitvoeren lukt niet, chroot is mislukt (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "'%s' uitvoeren lukt niet, exec is mislukt (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "'%s' uitvoeren lukt niet, onverwachte fout." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Kan %s niet koppelen aan %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Ontkoppelen van %s is mislukt" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Onjuiste bestandsnaam: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Medium kan niet worden geopend wanneer '%s' wordt uitgevoerd." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Bestand '%s' niet gevonden op medium '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Kan niet naar bestand '%s' schrijven." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Medium is niet gekoppeld" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Beschadigd koppelpunt van medium" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Initialiseren van downloaden (curl) is mislukt voor '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Systeemuitzondering '%s' op medium '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Pad '%s' op medium '%s' is geen bestand." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Pad '%s' op medium '%s' is geen map." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Onjuiste URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Lege hostnaam in URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Leeg bestandssysteem in URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Lege bestemming in URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Niet-ondersteund URI-schema in '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Bewerking niet ondersteund door medium" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Fout bij downloaden (curl) '%s':\n" +"Foutcode: %s\n" +"Foutbericht: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Fout bij het instellen downloadopties (curl) voor '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Mediumbron '%s' bevat niet het gewenste medium" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Medium '%s' wordt door een andere instantie gebruikt" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Kan geen media uitwerpen" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Kan medium '%s' niet uitwerpen" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Toegang tot '%s' geweigerd." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Time-out overschreden bij toegang tot '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"Gedownloade gegevens overtreffen de verwachte bestandsgrootte '%s' van '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Locatie '%s' is tijdelijk niet toegankelijk." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL-certificaatprobleem, controleer of de CA-cert OK is voor '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Geen vrije hulpbronnen om medium aan te koppelen." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Niet-ondersteunde HTTP-authenticatiemethode '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Fout bij download (curl) voor '%s':\n" +"Foutcode: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Fout bij downloaden (curl) voor '%s':\n" +"Kan HTTP-respons niet ophalen\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ja" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nee" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Opmerking:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Waarschuwing:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Foutmelding:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "gereed" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "attentie" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "foutmelding" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Waarschuwing: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Bezig met ophalen van:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "bezig met starten" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "niet gevonden" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Geen hulp beschikbaar voor deze prompt." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "geen hulp beschikbaar voor deze optie" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "alle opties tonen" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ja" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nee" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Bezig met uitvoeren van %%posttrans-script ‘%1%’…" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "De %posttrans-scripts zijn uitgevoerd" + +#~ msgid "Package is not signed!" +#~ msgstr "Pakket is niet ondertekend!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s behoort niet tot een opslagruimte voor distributie-upgrade" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s heeft een slechtere architectuur" + +#~ msgid "problem with installed package %s" +#~ msgstr "probleem met geïnstalleerd pakket %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "Niets levert het gevraagde %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Hebt u alle vereiste opslagruimtes ingeschakeld?" + +#~ msgid "package %s does not exist" +#~ msgstr "pakket %s bestaat niet" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s wordt door het systeem geleverd en kan niet gewist worden" + +#~ msgid "%s is not installable" +#~ msgstr "%s is niet geïnstalleerd" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "niets levert %s nodig door %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "kan %s en %s niet beide installeren" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s is in conflict met %s die geleverd is door %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s maakt %s verouderd en is geleverd door %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "geïnstalleerd %s maakt %s verouderd en is geleverd door %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "oplosser %s is in conflict met %s die geleverd is door zichzelf" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s vereist %s, maar aan deze eis kan niet voldaan worden" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "verwijder de vergrendeling om de verwijdering van %s toe te staan" + +#~ msgid "do not install %s" +#~ msgstr "%s niet installeren" + +#~ msgid "keep %s" +#~ msgstr "%s behouden" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "verwijder de vergrendeling om de installatie van %s toe te staan" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "vraag niet om een oplossingspakket die %s levert te installeren" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "" +#~ "vraag niet om alle oplossingspakketten die %s leveren te verwijderen" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "installeer de meest recente versie van %s niet" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s behouden ondanks de slechtere architectuur" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "%s installeren ondanks de slechtere architectuur" + +#~ msgid "keep obsolete %s" +#~ msgstr "verouderde %s handhaven" + +#~ msgid "install %s from excluded repository" +#~ msgstr "%s installeren uit een uitgesloten opslagruimte" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "downgrade %s tot %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "architectuurverandering van %s naar %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "%s installeren (met wijziging van leverancier)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "vervanging van %s door %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "verwijderen van %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Kan het blokkeringsbestand niet openen: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Deze actie is al bezig vanuit een ander programma." + +#~ msgid "Hal Exception" +#~ msgstr "Hal-uitzondering" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Helaas, deze versie van libzypp is gebouwd zonder HAL-ondersteuning." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext is niet verbonden" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive is niet geïnitialiseerd" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume is niet geïnitialiseerd" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Kan de dbus-verbinding niet maken" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Kan libhal-context niet maken" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Kan dbus-verbinding niet instellen" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Kan HAL-context niet initialiseren, is hald niet actief?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Geen cd-rom-station" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Kan mutex-kenmerk niet initialiseren" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Kan recursief mutex-kenmerk niet instellen" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Kan recursieve mutex niet initialiseren" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Kan mutex-vergrendeling niet verkrijgen" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Kan mutex-vergrendeling niet ontgrendelen" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Importeren van publieke sleutel uit bestand %s is mislukt: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Verwijderen van publieke sleutel %s is mislukt: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Kan geen beschikbaar lusapparaat vinden voor het koppelen van het " +#~ "imagebestand van '%s'" + +#~ msgid "do not keep %s installed" +#~ msgstr "houd %s niet geïnstalleerd" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Kan geen publieke sleutel %s uit %s sleutelring aanmaken naar bestand %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Download (Metalink curl) initialisatie mislukt voor '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Download (metalink curl) fout voor '%s':\n" +#~ "Foutcode: %s\n" +#~ "Foutboodschap: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Download onderbroken bij %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Download onderbroken door gebruiker" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "Fout bij het instellen downloadopties (metalink curl) voor '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Downloaden van %s op %s is mislukt" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Servië en Montenegro" + +#~ msgid "Unknown Distribution" +#~ msgstr "Onbekende distributie" + +#~ msgid "ignore some dependencies of %s" +#~ msgstr "negeer enige afhankelijkheden van %s" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Bestand %s bevat geen checksum.\n" +#~ "Wilt u het toch gebruiken?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Bestand %s voldoet niet aan integriteitscontrole door de volgende " +#~ "sleutel:\n" +#~ "%s|%s|%s\n" +#~ " Wilt u het bestand toch gebruiken?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Bestand %s heeft een ongeldige checksum.\n" +#~ "%s verwacht, %s gevonden\n" +#~ "Wilt u het toch gebruiken?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Bestand %s heeft een onbekende checksum.%sWilt u het toch gebruiken?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Bestand %s is niet ondertekend.\n" +#~ "Wilt u het toch gebruiken?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Bestand %s is ondertekend met een onbekende sleutel:\n" +#~ "%s|%s|%s\n" +#~ " Wilt u het bestand toch gebruiken?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Niet-vertrouwde sleutel gevonden:\n" +#~ "%s|%s|%s\n" +#~ " Sleutel vertrouwen?" diff --git a/po/nn.po b/po/nn.po new file mode 100644 index 0000000..756152a --- /dev/null +++ b/po/nn.po @@ -0,0 +1,5270 @@ +# @TITLE@ +# Copyright (C) 2011, SUSE Linux GmbH, Nuremberg +# This file is distributed under the same license as @PACKAGE@ package. FIRST +# Karl Ove Hufthammer , 2015, 2017. +msgid "" +msgstr "" +"Project-Id-Version: @PACKAGE@\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2022-05-29 21:13+0000\n" +"Last-Translator: Karl Ove Hufthammer \n" +"Language-Team: Norwegian Nynorsk \n" +"Language: nn\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Ukjent land: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Ingen kode" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Dei sameinte arabiske emirata" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua og Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Dei nederlandske Antillane" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktika" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikansk Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austerrike" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Aserbajdsjan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia-Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgia" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvetøya" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosøyane" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo-Brazzaville" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Den sentralafrikanske republikken" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Sveits" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Elfenbeinskysten" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookøyane" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kapp Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Christmasøya" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Kypros" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tsjekkia" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Tyskland" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danmark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Den dominikanske republikken" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algerie" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estland" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Vest-Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spania" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandsøyane" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikronesiaføderasjonen" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Færøyane" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Frankrike" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Storbritannia" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Fransk Guyana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grønland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatorial-Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Hellas" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungarn" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Det britiske territoriet i Indiahavet" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgisistan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodsja" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komorane" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "St. Kitts og Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Caymanøyane" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kasakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "St. Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litauen" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marokko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshalløyane" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Nord-Marianane" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldivane" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mosambik" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Ny-Caledonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolkøya" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nederland" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noreg" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Naurisk" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "New Zealand" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Fransk Polynesia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Ny-Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filippinane" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polen" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint-Pierre-et-Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugual" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russland" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi-Arabia" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salomonøyane" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychellane" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Sverige" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "St. Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard og Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé og Príncipe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- og Caicosøyane" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tsjad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Dei franske sørterritoria" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadsjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Tyrkia" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad og Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "USAs ytre småøyar" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "USA" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Usbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikanstaten" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Jomfruøyane (Storbritannia)" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Jomfruøyane (USA)" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Sør-Afrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Krev" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Ukjent språk: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhasisk" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Acehnesisk" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adygeisk" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afroasiatiske (andre)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadisk" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albansk" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutisk" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharisk" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabisk" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonsk" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armensk" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Kunstspråk (andre)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assami" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturleonesisk" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarisk" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestisk" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Avadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Aserbajdsjansk" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Basjkirsk" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Balutsji" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskisk" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltisk (andre)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Belarusisk" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berbisk (andre)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (andre)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnisk" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonsk" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarsk" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmesisk" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalansk" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukasisk (andre)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltisk (andre)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tsjetsjensk" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kinesisk" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Kyrkjeslavisk" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Tsjuvasjisk" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptisk" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Kornisk" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsikansk" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tsjekkisk" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dansk" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidisk" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Lågsorbisk" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nederlandsk" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engelsk" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estisk" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Færøysk" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijiansk" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finsk" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finsk-ugrisk" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Fransk" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulfulde" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germansk (andre)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgisk" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Tysk" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Kiribatisk" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gælisk" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irsk" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galisisk" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotisk" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Gammalgresk (fram til 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitisk" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebraisk" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hettittisk" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Høgsorbisk" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ungarsk" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Ibo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandsk" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuittisk" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesisk" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoeuropeisk" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiak" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiensk" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanesisk" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japansk" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Grønlandsk" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kasjmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kasakhisk" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgisisk" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreansk" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdisk" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laotisk" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latin" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvisk" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litauisk" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxembourgsk" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya og Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonsk" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallesisk" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malayisk" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Gassisk" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltesisk" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Mandsju" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Rumensk (utdatert)" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolsk" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitansk" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Lågtysk" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norsk (nynorsk)" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norrønt" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norsk" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Nordsotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Oksitansk (etter 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetisk" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persisk" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fønikisk" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polsk" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Ponapisk" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugisisk" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pashto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romansk (andre)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumensk" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russisk" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbisk" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliansk" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroatisk" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkupisk" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semittisk (andre)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Gammalirsk (fram til 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Teiknspråk" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singalesisk" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-tibetansk (andre)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavisk (andre)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakisk" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovensk" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sørsamisk" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Nordsamisk" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lulesamisk" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Enaresamisk" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoansk" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skoltesamisk" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sørsotho" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spansk" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardisk" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanesisk" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumerisk" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Svensk" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitisk" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (andre)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatarisk" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadsjikisk" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetansk" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigré" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinja" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tongansk" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Setswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmensk" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Tyrkisk" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaisk (andre)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uigurisk" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainsk" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Usbekisk" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamesisk" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Walisisk" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Vallonsk" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapesisk" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jiddisch" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Joruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Desse handlingane vert utførte:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Ukjend samsvarsmodus «%s»" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Ukjend samsvarsmodus «%s» for mønsteret '%s'." + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Installer pakken «lsof» først." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Byggjer mellomlager for pakkebrønnen «%s»" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Fjernar pakkebrønnen «%s»" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Vil du halda fram?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Fila %1%\n" +" frå pakken\n" +" %2%\n" +" er i konflikt med fil frå pakken\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Fila %1%\n" +" frå pakken\n" +" %2%\n" +" er i konflikt med fil frå installeringa av\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Fila %1%\n" +" frå installeringa av\n" +" %2%\n" +" er i konflikt med fil frå pakken\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Fila %1%\n" +" frå installeringa av\n" +" %2%\n" +" er i konflikt med fil frå installering av\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Fila %1%\n" +" frå pakken\n" +" %2%\n" +" er i konflikt med fila\n" +" %3%\n" +" frå pakken\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Fila %1%\n" +" frå pakken\n" +" %2%\n" +" er i konflikt med fila\n" +" %3%\n" +" frå installeringa av\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Fila %1%\n" +" frå installeringa av\n" +" %2%\n" +" er i konflikt med fila\n" +" %3%\n" +" frå pakken\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Fila %1%\n" +" frå installeringa av\n" +" %2%\n" +" er i konflikt med fila\n" +" %3%\n" +" frå installeringa av\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Denne kommandoen vil skada systemet!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr "" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Melding om ny oppdatering" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Fann ikkje fila «%s» på mediet «%s»" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Ugyldig URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ja" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nei" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Åtvaring: " + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Feil" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "fullført" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "feil" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Åtvaring: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Hentar:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "startar" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Fann ikkje" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Det finst ikkje noko hjelp tilgjengeleg for denne meldinga." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "finst ikkje hjelp for denne meldinga" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "vis alle val" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ja" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nei" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s er i konflikt med %s frå %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "løysbare %s konfliktar med %s tilgjengeleg frå seg sjølv" + +#~ msgid "Hal Exception" +#~ msgstr "Hal-unntak" diff --git a/po/pa.po b/po/pa.po new file mode 100644 index 0000000..4d003ed --- /dev/null +++ b/po/pa.po @@ -0,0 +1,5954 @@ +# translation of zypp.pa.po to Panjabi +# Punjabi message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Jaswinder Singh Phulewala +# Kanwaljeet Singh Brar +# +# A S Alam , 2007. +msgid "" +msgstr "" +"Project-Id-Version: zypp.pa\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2007-08-23 19:28+0530\n" +"Last-Translator: A S Alam \n" +"Language-Team: Panjabi \n" +"Language: \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: KBabel 1.11.4\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "ਅਣਜਾਣ ਦੇਸ਼: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "ਕੋਡ ਨਹੀਂ" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "ਆਂਡੋਰਾ" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "ਸੰਯੁਕਤ ਅਰਬ ਅਮੀਰਾਤ" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "ਅਫਗਾਨਿਸਤਾਨ" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "ਐਟੀਗੁਆ ਅਤੇ ਬਾਰਮੁਦਾ" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "ਅੰਗੂਲੀਆਂ" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "ਅਲਬੀਨਾ" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "ਅਮਰੀਨੀਅਨ" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "ਨੀਂਦਰਲੈਂਡ ਐਂਟੀਲਸ" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "ਅੰਗੋਲਾ" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "ਐਟਰਾਟਿਕਾ" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "ਅਰਜਨਟੀਨਾ" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "ਅਮਰੀਕੀ ਸਮੋਨਾ" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "ਆਸਟਰੀਆ" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "ਅਸਟਰੇਲੀਆ" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "ਅਰੂਬਾ" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "ਅਲੈਂਡ ਟਾਪੂ" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "ਅਜ਼ਰਬਾਈਜ਼ਾਨ" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "ਬੋਸੀਨਾ ਅਤੇ ਹਰਜ਼ੀਗੋਵੀਨਾ" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "ਬਾਰਬਾਡਾਸ" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "ਬੰਗਲਾਦੇਸ਼" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "ਬੈਲਜੀਅਮ" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "ਬੂਪਕੀਨਾ ਫਾਸੋ" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "ਬੁਲਗਾਰੀਆ" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "ਬਹਿਰਾਨ" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "ਬੁਰੁਡੀ" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "ਬੀਨੀਨ" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "ਬਾਰਾਮੂਡਾ" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "ਬਰੂਨਈ ਡੇਰੂਸਲਾਮ" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "ਬੋਲੋਵੀਆ" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "ਬਰਾਜ਼ੀਲ" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "ਬਾਹਾਮਾਸ" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "ਭੁਟਾਨ" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "ਬੁਉਵੀਟ ਟਾਪੂ" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "ਬੂਟਸਵਾਨਾ" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "ਬੇਲਾਰੂਸ" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "ਬਿਲੀਜ਼ੀ" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "ਕੇਨੈਡਾ" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "ਕੋਕੋਸ (ਕਿੱਲਿੰਗ) ਟਾਪੂ" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "ਕਾਂਗੋ" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "ਕੇਂਦਰੀ ਅਫ਼ਰੀਕੀ ਰਿਪਬਲਿਕ" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "ਸਵਿਟਜ਼ਰਲੈਂਡ" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "ਕੋਟੀ ਡੀਵੋਈਰੀ" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "ਕੁੱਕ ਟਾਪੂ" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "ਚਿੱਲੀ" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "ਕੈਮਰੂਨ" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "ਚੀਨ" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "ਕੋਲੰਬੀਆ" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "ਕਾਸਟ ਰੀਕਾ" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "ਕਿਊਬਾ" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "ਕੇਪ ਵਾਰਡੀ" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "ਕਰਿਸਮਿਸ ਟਾਪੂ" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "ਕਿਊਰੂਸ" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "ਚੈੱਕ ਗਣਰਾਜ" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "ਜਰਮਨੀ" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "ਡਜੀਬੂਟੀ" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "ਡੈਨਮਾਰਕ" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "ਡੋਮੀਨੀਆ" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "ਡੋਮੀਨੀਆਨ ਗਣਰਾਜ਼" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "ਅਲਜੀਰੀਆ" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "ਏਕਵੇਡਰ" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "ਈਸਟੋਨੀਆ" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "ਮਿਸਰ" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "ਦੱਖਣੀ ਸਹਾਰਾ" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "ਈਰਟੀਰਆ" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "ਸਪੇਨ" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "ਈਥੋਪੀਆ" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "ਫਿਨਲੈਂਡ" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "ਫਿਜ਼ੀ" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "ਫਾਕਲੈਂਡ ਟਾਪੂ (ਮਾਲਵੀਨਸ)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "ਮਾਈਕਰੋਨਸੀਆ ਦੇ ਸੰਘੀ ਰਾਜ" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "ਫਾਰੀਓ ਟਾਪੂ" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "ਫਰਾਂਸ" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "ਮੈਟਰੋਪਲੋਟਨ ਫਰਾਂਸ" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "ਗਾਬੋਨ" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "ਬਰਤਾਨੀਆ" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "ਗਰੀਨਾਡਾਆ" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "ਜਾਰਜੀਆ" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "ਫਰੈਂਚ ਗੁਆਨਾ" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "ਜਰਮਨੀ" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "ਗਾਨਾ" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "ਗੀਬਰਾਲਟਰ" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "ਗਰੀਨਲੈਂਡ" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "ਗਾਬੀਆ" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "ਗੁਈਨਾ" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "ਗੁਆਡੀਲੂਪੀ" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "ਭੂ-ਖੰਡੀ ਗੁਆਨਾ" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "ਗਰੀਸ" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "ਦੱਖਣੀ ਜਾਰਜੀਆ ਅਤੇ ਦੱਖਣੀ" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "ਗੁਆਟੇਮਾਲਾ" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "ਗੁਆਮ" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "ਗੂਈਨੀਆ" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "ਗੁਆਨਾ" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "ਹਾਂਗਕਾਂਗ" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "ਹਾਰਟਡ ਟਾਪੂ ਅਤੇ ਮੈਕਡਾਨਲਡ ਟਾਪੂ" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "ਹਾਨਡੂਰਸ" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "ਕਰੋਟੀਆ" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "ਹਾਈਟੀ" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "ਹੰਗਰੀ" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "ਇੰਡੋਨੇਸੀਆ" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "ਆਈਰਲੈਂਡ" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "ਇਜ਼ਰਾਈਲ" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "ਭਾਰਤ" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "ਬਰਤਾਨੀਵੀ ਭਾਰਤੀ ਮਹਾਂ-ਸਾਗਰ ਖੇਤਰ" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "ਇਰਾਕ" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "ਈਰਾਨ" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "ਆਈਸਲੈਂਡ" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "ਇਟਲੀ" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "ਜੈਮਾਈਕਾ" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "ਜਾਰਡਨ" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "ਜਾਪਾਨ" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "ਕੀਨੀਆ" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "ਕਿਰਗਸਤਾਨ" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "ਕੰਬੋਡੀਆ" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "ਕੀਰੀਬਾਟੀ" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "ਕੋਮੋਰੋਸ" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "ਸੇਂਟ ਕਿਟੱਸ ਅਤੇ ਨੀਵਿਸ" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "ਉੱਤਰੀ ਕੋਰੀਆ" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "ਦੱਖਣੀ ਕੋਰੀਆ" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "ਕੁਵੈਤ" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "ਕਾਯਮਾਨ ਟਾਪੂ" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "ਕਜ਼ਾਕਸਤਾਨ" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "ਲਿਓ ਲੋਕਤੰਤਰ" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "ਲੀਬਨਾਨ" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "ਸੇਂਟ ਲੂਸੀਆ" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "ਲੀਚਟੀਨੀਆ" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "ਸ਼ਰੀਲੰਕਾ" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "ਲੀਬਰੀਆ" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "ਲੀਸੋਥੋ" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "ਲੀਥੂਨੀਆ" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "ਲ਼ਕਸ਼ਬਰਗ" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "ਲਾਟੀਵਾਆ" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "ਲੀਬੀਆ" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "ਮੋਰੋਸ਼ਸ" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "ਮੋਨਸ਼ੀਆ" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "ਮੋਲਡੋਵਾ" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "ਮੋਨਗੋ" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "ਸੇਂਟ ਮਾਰੀਓ" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "ਮੈਡਾਗਾਸਕਰ" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "ਮਾਰਸ਼ਲ ਟਾਪੂ" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "ਮੈਕਡੋਨੀਆ" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "ਮਾਲੀ" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "ਮਿਆਂਮਾਰ" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "ਮੰਗੋਲੀਆ" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "ਮੈਕਸੀਕੋ" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "ਉੱਤਰੀ ਮਾਰੀਨਾ ਟਾਪੂ" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "ਮਾਰਟੀਨਿਉ" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "ਮਾਉਰੀਟਨੀਆ" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "ਮੋਨਟਸ਼ਟੀਟ" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "ਮਾਲਟਾ" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "ਮਾਉਰੀਟੀਸ" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "ਮਾਲਦੀਵ" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "ਮਾਲਾਵੀ" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "ਮੈਕਸੀਕੋ" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "ਮਲੇਸ਼ੀਆ" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "ਮੋਜਾਬਕਿਉ" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "ਨਾਮੀਬੀਆ" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "ਨਿਊ ਕਾਲੀਡੋਨੀਆ" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "ਨੀਗਰ" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "ਨੋਰਫੋਕ ਟਾਪੂ" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "ਨਜੀਰੀਆ" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "ਨਿਕਾਰਗੁਆ" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "ਨੀਂਦਰਲੈਂਡ" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "ਨਾਰਵੇ" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "ਨੇਪਾਲ" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "ਨੀਓਰੂ" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "ਨਿਉ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "ਨਿਊਜ਼ੀਲੈਂਡ" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "ਓਮਾਨ" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "ਪੈਨਾਮਾ" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "ਪੇਰੂ" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "ਫਰੈਂਚ ਪੋਲੀਸੀਨੀਆ" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "ਪੋਪ ਨਿਉ ਗੁਆਨਾ" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "ਫਿਲਿਪੀਨੀਜ਼" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "ਪਾਕਿਸਤਾਨ" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "ਪੋਲੈਂਡ" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "ਸੇਂਟ ਪੀਇੱਰ ਅਤੇ ਮੀਕਿਉਨੋਲ" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "ਪਿਟਸਾਰਨ" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "ਪੁਈਰਟੋ ਰੀਸੋ" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "ਫਿਲਸਤੀਨ ਰਾਜ" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "ਪੁਰਤਗਾਲ" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "ਪਾਲਾਊ" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "ਪੇਰੂਗਵੇ" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "ਕਤਰ" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "ਰੀਯੁਨੀਅਨ" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "ਰੋਮਾਨੀਆ" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "ਸਰਬੀਅਨ" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "ਰੂਸੀ ਸੰਘ" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "ਰਵਾਂਡਾ" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "ਸਾਊਦੀ ਅਰਬ" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "ਸੋਲੋਮੋਨ ਟਾਪੂ" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "ਸੀਯਚੀਲੱਸ" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "ਸੂਡਾਨ" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "ਸਵੀਡਨ" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "ਸਿੰਘਾਪੁਰ" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "ਸੇਂਟ ਹੀਲੀਆ" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "ਸਲੋਵੀਨੀਆ" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "ਸਵਾਲਬਾਰਡ ਅਤੇ ਜਾਨ ਮਾਯਾਨ" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "ਸਲੋਵਾਕੀਆ" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "ਲਿੱਰ ਲੀਓਨ" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "ਸੇਂਟ ਮਾਰੀਓ" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "ਸੈਨੇਗਾਲ" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "ਸੋਮਾਲੀਆ" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "ਸੁਰੀਨੇਮ" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "ਸਾਓ ਟੋਮੀ ਅਤੇ ਪਰਿਸਪੀ" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "ਈਲ ਸਾਲੇਵਡੋਰ" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "ਸੀਰੀਆ" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "ਸਵਾਜੀਲੈਂਡ" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "ਤੁਰਕ ਅਤੇ ਸਾਈਸੋਸ ਟਾਪੂ" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "ਚੱਡ" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "ਫਰੈਂਚ ਦੱਖਣੀ ਖੇਤਰ" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "ਟਾਂਗੋ" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "ਥਾਈਲੈਂਡ" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "ਤਜ਼ਾਕਸਤਾਨ" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "ਤੁਕੀਲਾਓ" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "ਤੁਰਕਮੇਨਸਤਾਨ" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ਟੁਨੀਸ਼ੀਆ" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "ਤਾਂਗਾ" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "ਪੂਰਬੀ ਤੇਮੂਰ" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "ਤੁਰਕੀ" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ਟਰੀਨੀਡ ਅਤੇ ਤੋਬਾਗੋ" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "ਤੁਵਾਲੂ" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "ਤਾਈਵਾਨ" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "ਤਾਂਜੀਨੀਆ" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "ਯੂਕਰੇਨ" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "ਉਜਾਂਡਾ" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "ਸੰਯੁਕਤ ਰਾਜ ਮੀਨੋਰ ਆਉਟਲੇ ਟਾਪੂ" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "ਸੰਯੁਕਤ ਰਾਜ" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "ਉਰੂਗਵੇ" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "ਉਜ਼ੇਬਕਸਤਾਨ" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "ਹੋਲੀ ਸੀ (ਵਾਟੀਕਾਨ ਸਿਟੀ ਸਟੇਟ)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "ਸੇਂਟ ਵੀਨਸੈਂਟ ਅਤੇ ਗਰੀਨਡੀਨ" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "ਵੈਨੂਜੇਏਲਾ" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "ਬਰਤਾਨਵੀਂ ਵਰਜੀਨੀਆ ਟਾਪੂ" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "ਵੀਰਜੀਨ ਟਾਪੂ, ਅਮਰੀਕਾ" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "ਵੀਅਤਨਾਮ" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "ਵਾਂਉਤੁ" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "ਵਾਲਿਸ ਅਤੇ ਫੁਟੁਨਾ" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "ਸਾਮੀਆ" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "ਯਮਨ" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "ਮਿਯੋਟੀ" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "ਦੱਖਣੀ ਅਫਰੀਕਾ" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "ਜੈਂਬੀਆ" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "ਜਿੰਬਾਬਾਵੇ" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "ਪਰੋਵਾਇਡ" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "ਲੋੜੀਦਾ" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "ਅਪਵਾਦ" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "ਬਰਤਰਫ਼" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "ਸਿਫਾਰਸ਼ੀ" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "ਸੁਝਾਅ" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "ਇੰਹੈਂਸ" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "ਸਪਲੀਮੈਂਟ" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "VM ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਫੇਲ੍ਹ ਹੈ।" + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "VM ਸ਼ੁਰੂ ਕਰਨ ਲਈ ਫੇਲ੍ਹ ਹੈ।" + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "ਸੋਰਸ ਪੈਕੇਜ '%s' ਨਹੀਂ ਲੱਭਿਆ।" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "ਅਣਜਾਣ ਭਾਸ਼ਾ: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "ਅਫ਼ਰ" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "ਅਬਖਾਜ਼ੀਨਾ" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "ਅਚੀਨੀਜ਼" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "ਅਕੋਲੀ" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "ਅਡਾਨਗਮੀ" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "ਅਡਯਘੀ" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "ਅਫਰੋ-ਏਸ਼ੀਆਟਿਕ (ਹੋਰ)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "ਅਫਰੀਹੀਲੀ" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "ਅਫਰੀਕੀ" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "ਈਨੂ" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "ਅਕਾਨ" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "ਅੱਕਾਡਿਨ" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "ਅਲਬੀਅਨ" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "ਅਲਿਉਟ" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "ਅਲਗੁਨਕਿਉਨ ਭਾਸ਼ਾਵਾਂ" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "ਦੱਖਣੀ ਅਥਟਾਈ" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "ਅਮਹਾਰਿਕ" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "ਅੰਗਰੇਜ਼ੀ, ਪੁਰਾਣੀ (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "ਆਪਚੇਂ ਭਾਸ਼ਾਵਾਂ" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "ਅਰਬੀ" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "ਅਰਾਮਿਕ" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "ਅਰਾਗੋਨੀਸੀ" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "ਅਰਮੀਨੀਅਨ" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "ਅਰਾਉਕਾਨੀਆ" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "ਅਰਾਪਿਹੋ" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "ਆਰਟੀਫਿਸ਼ਲ (ਹੋਰ)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "ਅਰਾਵਾਕ" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "ਅਸਾਮੀ" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "ਆਸਟਰੀਆਈ" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "ਅਥਾਪਾਸਕਾਨ ਭਾਸ਼ਾਵਾਂ" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "ਆਸਟਰੇਲੀਆਈ ਭਾਸ਼ਾਵਾਂ" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "ਅਵਾਰਿਕ" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "ਅਵੀਸਟੀਨ" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "ਅਵਾਥੀ" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "ਅਰਮਾਰਾ" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "ਅਜ਼ਰਬਾਈਜਾਨ" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "ਬਾਂਡਾ" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "ਬਾਕਿਮਲੀਕੀ ਭਾਸ਼ਾਵਾਂ" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "ਬਸ਼ਕੀਰ" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "ਬਲੋਚੀ" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "ਬਾਮਬਾਰਾ" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "ਬਾਲੀਨਸੀ" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "ਬਸਕਿਊ" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "ਬਾਸਾ" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "ਬਲਟਿਕ (ਹੋਰ)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "ਬੀਜਾ" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "ਬੇਲਾਰੂਸੀ" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "ਬੀਮਬਾ" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "ਬੰਗਾਲੀ" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "ਬੀਰਬੀਰ (ਹੋਰ)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "ਭੋਜਪੁਰੀ" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "ਬਿਹਾਰੀ" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "ਬਿਕੋਲ" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "ਬਿਨਿ" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "ਬਿਸਲਮਾ" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "ਸਿਕਸਿਕਾ" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "ਬਾਂਤੁ (ਹੋਰ)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "ਬੋਸਨੀਆ" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "ਬਰਾਜ" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "ਬਰੀਤੋਨ" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "ਬਾਟਾਕ (ਇੰਡੋਨੇਸੀਆ)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "ਬੈਰੁਤ" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "ਬੁਗੀਨੀਆ" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "ਬੁਲਗਾਰੀਅਨ" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "ਬੁਰਮੀਸੀ" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "ਬਲਿਨ" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "ਕੱਡੋ" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "ਕੇਂਦਰੀ ਅਮਰੀਕੀ ਇੰਡੀਅਨ (ਹੋਰ)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "ਕਾਰਿਬ" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "ਕਾਟਾਲੋਨ" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "ਕੂਕੇਸ਼ੀਆਈ (ਹੋਰ)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "ਸੀਬੁਆਂਨੋ" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "ਸੀਲਟਿਕ (ਹੋਰ)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "ਚਾਮੋਰੋ" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "ਚੀਬਚਾ" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "ਚੇਚਨ" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "ਚਾਗਾਤਾਈ" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "ਚੀਨੀ" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "ਚੂਉਕੀਸੀ" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "ਮਾਰੀ" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "ਚੀਨੂਕ ਜਾਰਗਾਨ" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "ਚਾਕਤਾਵ" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "ਚਿਪੀਵਯਾਨ" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "ਚੀਰੋਕੀ" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "ਚਰਚ ਸਲਾਵਿਕ" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "ਚੁਵਸ" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "ਚੀਯੀਨੀ" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "ਚਾਮਿਕ ਭਾਸ਼ਾਵਾਂ" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "ਕੋਪਟੀਕ" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "ਕੋਰਨਿਸ਼" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "ਕੋਰਸਕੇਨ" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "ਕਰੀ" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "ਕਰੀਮਿਕ ਤਰਾਰ" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "ਕਾਸ਼ੁਬਿਨ" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "ਚੈੱਕ" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "ਡਾਕੋਟਾ" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "ਡੈਨਿਸ਼" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "ਡਾਰਗਵਾ" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "ਡਾਯਾਕ" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "ਡੀਲਵਾਰੀ" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "ਸਲਾਵੀ (ਅਥਾਪਾਕਸਕੈਨ)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "ਡਾਗਰਿਬ" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "ਡੀਨਕਾ" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "ਡੀਵਿਹਾ" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "ਡੋਗਰੀ" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "ਦਰਾਵੜੀਅਨ (ਹੋਰ)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "ਲੋਅਰ ਸੋਰਬੀਆਈ" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "ਡੁਆਲਾ" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "ਡੱਚ, ਮਿਡਲ (ca 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "ਡੱਚ" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ਡਯੂਲਾ" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "ਡਜ਼ੋਨਗਖਾ" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "ਈਫਿਕ" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "ਮਿਸਰ (ਪੁਰਾਤਨ)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "ਈਕਾਜੁਕ" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "ਅਲਾਮਿਟੀ" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "ਅੰਗਰੇਜ਼ੀ" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "ਅੰਗਰੇਜ਼ੀ, ਮਿਡਲ (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "ਇਸਪੀਰੋਟੋ" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "ਈਸਟੋਨੀਅਨ" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "ਈਵੀ" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "ਈਵੋਨਡੋ" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "ਫੌਂਗ" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "ਫਾਰੋਸੀ" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "ਫਾਂਟੀ" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "ਫਿਜ਼ੀ" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "ਫਿਲਿਪਿਨੋ" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "ਫੈਨਿਸ਼" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "ਫੋਨ" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "ਫਰੈਂਚ" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "ਫਰੈਂਚ, ਮਿਡਲ (ca. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "ਫਰੈਂਚ, ਪੁਰਾਣੀ (842 ca 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "ਫਾਰਸੀ" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "ਫੂਲਾਹ" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "ਫਰੀਉਲੀਅਨ" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "ਗਾ" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "ਗਾਯੋ" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "ਗਬਾਯਾ" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "ਗਿਰਮਿਕ (ਹੋਰ)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "ਜਾਰਜੀਅਨ" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "ਜਰਮਨ" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "ਗਾਜ਼ਾ" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "ਗਿਲਬਰਿਟਸੀ" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "ਗਾਇਲਿਕ" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "ਆਈਰਸ਼" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "ਗਲੀਸਿਕ" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "ਮੈਂਨਸ" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "ਜਰਮਨ, ਮਿਡਲ ਉੱਚ (ca. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "ਜਰਮਨ, ਪੁਰਾਣਾ ਉੱਚ (ca. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "ਗੋਂਡੀ" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "ਗੋਰੋਨਟਾਲੋ" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "ਗੋਥਿਕ" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "ਗਰੀਬੋ" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "ਗਰੀਕ, ਪੁਰਾਤਨ (1453 ਤੱਕ)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "ਗਰੀਕ, ਮਾਡਰਨ (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "ਗੁਜਰਨੀ" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "ਗੁਜਰਾਤੀ" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "ਗਵਿਚਨਿ" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "ਹਾਈਡਾ" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "ਹਾਈਤਿਨ" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "ਹਾਉਸਾ" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "ਹਾਵਾਈਨ" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "ਹੈਬਰਿਓ" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "ਹੀਰੀਰੋ" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "ਹਿਲਿਗਾਯਨੋਨ" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "ਹਿਮਾਚਲੀ" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "ਹਿੰਦੀ" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "ਹਿੱਟੀਟੀ" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "ਹਮਾਂਗ" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "ਹੀਰੀ ਮੋਟੋ" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "ਅੱਪਰ ਸੋਰਬੀਆਈ" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "ਹੰਗਰੀਅਨ" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "ਉਪਾ" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "ਲਬਾਨ" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "ਲਗਬੋ" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "ਆਈਸਲੈਂਡਿਕ" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ਈਡੋ" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "ਸਿਚੁਨ ਯੀ" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ਈਜੋ" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "ਇਨਕਟੁਟ" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "ਇੰਟਰਲੈਗੁਆ" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "ਲੱਕੋ" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "ਭਾਰਤੀ (ਹੋਰ)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "ਇੰਡੋਨੇਸ਼ੀਅਨ" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "ਇੰਡੋ-ਯੂਰਪੀਆਈ (ਹੋਰ)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "ਈਂਗੁਸ਼" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "ਇਨੁਪਿਓ" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "ਆਈਰਸ਼ (ਹੋਰ)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "ਈਰੋਕਿਉਆਈ ਭਾਸ਼ਾਵਾਂ" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "ਇਤਾਲਵੀ" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "ਜਾਵੀ" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "ਲੋਜਬੀਨ" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "ਜਾਪਾਨੀ" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "ਜੂਡੀਓ-ਪਾਰਸ਼ੀਆਈ" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "ਜੂਡੀਓ-ਅਰਬੀ" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "ਕਾਰਾ-ਕਾਲਪਾਕ" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "ਕਾਬਆਲੇ" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "ਕੋਚੀਨ" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "ਕਾਲਾਲਸੁਟ" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "ਕੰਮਬਾ" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "ਕੰਨੜ" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "ਕੀਰਿਨ" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "ਕਸ਼ਮੀਰੀ" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "ਕਾਨਉਰੀ" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "ਕਵੀ" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "ਕਾਜ਼ਾਖ" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "ਕਾਬਾਰਡੀਆਈ" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "ਖਾਸੀ" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "ਖੋਈਸਾਨ (ਹੋਰ)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "ਖਮੀਰ" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "ਖੋਤਾਨੀਸੀ" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "ਕਿਕੁਯੂ" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "ਕੀਯਾਰਵਾਂਡਾ" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "ਕਿਰਘੀਜ਼" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "ਕਿਮਬੁਡੂ" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "ਕੋਕਨੀ" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "ਕੋਮੀ" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "ਕਾਂਗੋ" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "ਕੋਰੀਆਨ" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "ਕੋਸਰੀਨ" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "ਕਪੀੱਲੀ" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "ਕਾਰਾਚਾਯ-ਬਾਲਕਾਰ" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "ਕਰੁ" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "ਕੁਰੂਖ" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "ਕੂਯਾਮਾ" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "ਕੁਮਯਕ" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "ਕੁਰਦ" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "ਕੁਟੀਨੀ" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ਲਾਡਿਨੋ" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "ਲਾਹਨਡਾ" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "ਲਾਬਾਂ" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "ਲਿਓ" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "ਲੈਟਿਨ" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "ਲਾਵਟੀਅਨ" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "ਲਿਜ਼ਘੀਨ" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "ਲਿਮਬੁਰਗਾਨ" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "ਲਿੰਗਾਲਾ" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "ਲੀਥੂਨੀਅਨ" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "ਮੋਨਗੋ" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "ਲੁਜ਼ੀ" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "ਲ਼ਕਸ਼ਬਰਗਿਸ਼" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "ਲੁਬਾ-ਲੁਲੁਆ" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "ਲੁਬਾ-ਕਾਤਾਂਗਾ" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ਗਾਂਡਾ" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "ਲੁਈਸੀਨੋ" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "ਲੁਆਂਡਾ" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "ਲੁਸ਼ਾਈ" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "ਮੈਕਡੋਨੀਅਨ" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "ਮਾਡੁਰੀਸੀ" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "ਮਾਗਾਹੀ" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "ਮਾਰਸੱਲੀਸੀ" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "ਮੈਥਲੀ" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "ਮਾਕਾਸਾਰ" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "ਮਲਿਆਲਮ" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "ਮਾਂਡੀਂਗੋ" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "ਮੋਰੀ" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "ਮਰਾਠੀ" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "ਮਾਸਾਈ" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "ਮਲਾਇਆ" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "ਮੋਕਸਾ" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "ਮਾਂਡਾਰ" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "ਮੀਂਡੀ" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "ਆਈਰਸ਼, ਮਿਡਲ (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "ਮਿਕਮਾਕਿਉ" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "ਮਿਨਾਂਗਕਾਬਾਉ" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "ਫੁਟਕਲ ਭਾਸ਼ਾਵਾਂ" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "ਮੋਨ-ਖਮੀਰ (ਹੋਰ)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "ਮਾਲਾਗਸੇ" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "ਮਾਲਟਾ" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "ਮਾਂਚੁ" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "ਮਨੀਪੁਰੀ" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "ਮਾਂਨੋਬੋ ਭਾਸ਼ਾਵਾਂ" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "ਮੋਹਾਵਕ" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "ਮੋਲਡੋਵਾ" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "ਮੰਗੋਲੀਅਨ" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "ਮੱਸੀ" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "ਕੋਈ ਭਾਸ਼ਾਵਾਂ" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "ਮਾਂਨਡਾ ਭਾਸ਼ਾਵਾਂ" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "ਕਰੀਕ" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "ਮੀਰਾਂਡੀਸੀ" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "ਮਾਰਵਾਰੀ" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "ਮਾਯਾਨ ਭਾਸ਼ਾਵਾਂ" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "ਈਰਜ਼ਯਾ" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "ਨਾਹੁਆਟਲ" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "ਉੱਤਰੀ ਅਮਰੀਕੀ ਇੰਡੀਅਨ" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "ਨੀਪੋਲੀਤਾਨ" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "ਨਾਵਾਜੋ" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "ਨਡੀਬੀਲੀ, ਦੱਖਣੀ" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "ਨਡੀਬੀਲੀ, ਉੱਤਰੀ" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ਨਡੋਗਾ" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "ਲੋ ਜਰਮਨ" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "ਨੇਪਾਲੀ" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "ਨੇਪਾਲ ਭਾਸ਼ਾ" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "ਨੀਆਸ" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "ਨੀਉਨ" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "ਨਾਰਵੀਅਨ ਨਿਯਰੋਸਕ" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "ਨਾਰਵੀਅਨ ਬੋਕਮਾਲ" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "ਨੋਗਾਈ" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "ਨੋਰਸੀ, ਪੁਰਾਣੀ" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "ਨਾਰਵੀਅਨ" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "ਉੱਤਰੀ ਸੋਥੋ" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "ਨਿਬੀਆਈ ਭਾਸ਼ਾਵਾਂ" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "ਕਲਾਸੀਕਲ ਨੀਵਾਰੀ" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "ਚਿਚੀਵਾ" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "ਨਆਮਵਜ਼ੀ" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "ਨਆਨਕੋਲੀ" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "ਨਆਰੋ" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "ਨਜ਼ੀਮਾ" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "ਉਸਟਾਨ (ਪੋਸਟ 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "ਉਜੀਬਵਾ" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "ਓੜੀਆ" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "ਓਰੋਮਾ" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "ਓਸਾਗੀ" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "ਉੱਸਟੀਨਅਨ" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "ਤੁਰਕ, ਉੱਟੋਮਨ (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "ਓਟਾਮੀਆਈ ਭਾਸ਼ਾਵਾਂ" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "ਪਾਪੁਆਨ (ਹੋਰ)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "ਪਾਂਗਾਸੀਆਈ" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "ਪਾਹਲਵੀ" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "ਪਾਮਪਾਂਗਾ" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "ਪੰਜਾਬੀ" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "ਪਾਡੀਮੀਟਤੋ" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "ਪਾਲਾਉਨ" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "ਪਰਸ਼ੀਆਈ, ਪੁਰਾਣੀ (ca 600-400 BC)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "ਪਰਸੀਆਈ" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "ਫਿਲਿਪੀਨੀ (ਹੋਰ)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "ਫੋਨੋਨੀਸਿਕ" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "ਪਾਲੀ" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "ਪੋਲਿਸ਼" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "ਫੋਹਨਪੀਈ" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "ਪੁਰਤਗਾਲੀ" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "ਪਰਾਕਰਿਟ ਭਾਸ਼ਾਵਾਂ" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "ਪਰੋਵਾਂਕਾਲ, ਪੁਰਾਣੀ (1500 ਤੋਂ)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "ਪੁਸਤੋ" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "ਕਿਉਚੁਆ" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "ਰਾਜਸਥਾਨੀ" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "ਰਾਪਾਨਈ" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "ਰਾਰੋਤੋਨਗੀ" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "ਰੋਮਾਨਿਕ (ਹੋਰ)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "ਰੀਟੋ-ਰੋਮਨੀ" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "ਰੋਮਨੀ" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "ਰੋਮਾਨੀਅਨ" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "ਰੰਡੀ" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "ਰੂਸੀ" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "ਸਾਂਡਾਵੀ" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "ਸਾਂਗੋ" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "ਯਾਕੁਟ" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "ਦੱਖਣੀ ਅਮਰੀਕੀ ਇੰਡੀਅਨ (ਹੋਰ)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "ਸਾਲੀਸ਼ਾਂ ਭਾਸ਼ਾਵਾਂ" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "ਸਾਮਾਰਿਟਿਕ ਅਰਾਮਾਕ" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "ਸੰਸਕਰਿਤ" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "ਸਾਸਾਕ" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "ਸਾਂਤਾਲੀ" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "ਸਰਬੀਅਨ" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "ਸਿਕਿਲਿਆਈ" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "ਸਕੋਟਸ" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "ਕਰੋਆਟੀਅਨ" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "ਸਿਲਕੁਪ" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "ਸਿਮੀਟਿਕ (ਹੋਰ)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "ਆਈਰਸ਼, ਪੁਰਾਣੀ (900 ਤੋਂ)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "ਸਾਇਨ ਭਾਸ਼ਾਵਾਂ" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "ਸ਼ਾਨ" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "ਸੀਡਾਮੋ" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "ਸਿੰਹਾਲਾ" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "ਸੀਉਆਨ ਭਾਸ਼ਾਵਾਂ" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "ਸੀਨੋ-ਤਿੱਬਤ (ਹੋਰ)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "ਸਲਾਵਿਕ (ਹੋਰ)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "ਸਲੋਵਾਕ" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "ਸਲੋਵੀਅਨ" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "ਦੱਖਣੀ ਸਾਮੀ" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "ਉੱਤਰੀ ਸਾਮੀ" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "ਸਾਮੀ ਭਾਸ਼ਾਵਾਂ (ਹੋਰ)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "ਲੁਈ ਸਾਮੀ" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "ਇਨਰੀ ਸਾਮੀ" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "ਸਾਮੋਨੀ" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "ਸਲਾਲਟ ਸਾਮੀ" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "ਸ਼ੋਨਾ" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "ਸਿੰਧੀ" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "ਸੋਨੀਨਕੀ" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "ਸੋਗਡੀਆਈ" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "ਸੋਮਾਲੀ" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "ਸੋਂਘਾਈ" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "ਸੋਥੋ, ਦੱਖਣੀ" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "ਸਪੇਨੀ" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "ਸਾਰਡੀਨੀਅਨ" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "ਸੀਰੀਰ" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "ਨਿਲੋ-ਸਸਾਹਾਰਨ (ਹੋਰ)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "ਸਵਾਤੀ" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "ਸੁਕੁਮਾ" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "ਸੁਡਾਨੀ" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "ਸੁਸੁ" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "ਸੁਮੀਰਿਨ" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "ਸਵਾਹਿਲੀ" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "ਸਵੀਡਿਸ਼" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "ਸਅਰਿਕ" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "ਤਾਹੀਤੀਆਨ" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "ਤਾਈ (ਹੋਰ)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "ਤਾਮਿਲ" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "ਤਤਾਰ" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "ਤੇਲਗੂ" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "ਤਿਮਨੀ" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "ਤਿਰਿਨੋ" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "ਤੋਤੁਮ" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "ਤਾਜ਼ਿਕ" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "ਤਾਗਾਲੋਗ" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "ਥਾਈ" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "ਤਿੱਬਤ" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "ਤੀਗਰਿ" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "ਟੀਗਰੀਨਯਾ" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "ਤੀਵ" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "ਕਲਿੰਗੋਨ" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "ਤਲਿੰਗੀਤ" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "ਤਾਮਾਸਿਕ" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "ਤਾਂਗਾ (ਨਆਸਾ)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "ਤਾਂਗਾ (ਤਾਂਗਾ ਟਾਪੂ)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "ਤੋਕ ਪਿਸ਼ਿਨ" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "ਤਸਾਮਸ਼ਿਨ" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "ਤਸਵਾਕਾ" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "ਤਸਾਂਗੋ" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "ਤੁਰਕ" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "ਤੁਮਬੁਕਾ" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "ਤੁਪਾਈ ਭਾਸ਼ਾਵਾਂ" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "ਤੁਰਕੀ" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "ਅਲਟਿਕ (ਹੋਰ)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "ਤਵੀ" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "ਤੁਵੀਨੀਆਈ" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "ਉਡਮਰਟ" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "ਯਗਾਰਿਟਿਕ" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "ਉਘੋਰ" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "ਯੂਕਰੇਨੀ" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "ਯਮਬੁਡੂ" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "ਅਣ-ਪਛਾਣੀ" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "ਉਰਦੂ" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "ਉਜ਼ੇਬਕ" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "ਵਾਈ" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "ਵਾਂਡਾ" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "ਵੀਅਤਨਾਮੀ" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "ਵੋਲਾਪੁਕ" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "ਵੋਟਿਕ" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "ਵਾਕਾਸ਼ਾਨ ਭਾਸ਼ਾਵਾਂ" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "ਵਾਲਾਮੋ" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "ਵਾਰਾਏ" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "ਵਾਸ਼ੋ" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "ਵਾਲਿਸ਼" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "ਸੋਰਬੀਆਈ ਭਾਸ਼ਾਵਾਂ" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "ਵੱਲੂਨ" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "ਵੋਲੋਫ" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "ਕਾਲਮਯਕ" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "ਯੋਸਾ" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "ਯਾਓ" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "ਯਾਪੀਸੀ" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "ਯੀਡਿੱਸ਼" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "ਯੋਰੁਬਾ" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "ਯੁਪਿਕ ਭਾਸ਼ਾਵਾਂ" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "ਜ਼ਾਪੋਟਿਕ" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "ਜੀਨਾਗਾ" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "ਜ਼ੁਆਂਗ" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "ਜਾਂਡੀ" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "ਜ਼ੂਲੂ" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "ਜੁਨੀ" + +#: zypp/ProblemSolution.cc:134 +#, fuzzy +msgid "Following actions will be done:" +msgstr "ਹੇਠ ਦਿੱਤੇ ਪੈਕੇਜ ਅੱਪਡੇਟ ਕੀਤੇ ਜਾਣਗੇ:\n" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "ਅਣਜਾਣ" + +#: zypp/VendorSupportOptions.cc:17 +#, fuzzy +msgid "unsupported" +msgstr " - ਸਹਾਇਕ ਨਹੀਂ" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "ਡਿਸਕ ਮੌਜੂਦ ਨਹੀਂ ਹੈ।" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "ਅਣਜਾਣ ਕਮਾਂਡ '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "ਫਾਇਲ %2$s ਲਈ ਅਣਜਾਣ ਡਿਜ਼ਟ %1$s" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "ਗਲਤ Url ਸਕੀਮ '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "'%s' ਲਈ ਪਰਮਾਣਿਕਤ ਲੋੜੀਦੀ ਹੈ" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "%1 ਡਾਇਰੈਕਟਰੀ ਬਣਾਈ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ: %2" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, fuzzy, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "ਰਿਪੋਜ਼ਟਰੀ '%s' ਤੋਂ ਮੇਟਾ-ਡਾਟਾ ਪਾਰਸਿੰਗ ਦੌਰਾਨ ਗਲਤੀ:" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "%s ਬਣਾਈ ਨਹੀਂ ਜਾ ਸਕਦੀ: %m\n" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +#, fuzzy +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "بيانات التعريف غير صحيحة لم يتم العثور عليها في المسار(s)" +msgstr[1] "بيانات التعريف غير صحيحة لم يتم العثور عليها في المسار(s)" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "ਪਾਰਸ ਕਰਨ ਦੌਰਾਨ ਫੇਲ੍ਹ: %s।" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "ਰਿਪੋਜ਼ਟਰੀ '%s' ਕੈਚੇ ਬਿਲਡ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +#, fuzzy +msgid "Unhandled repository type" +msgstr "%s ਰਿਪੋਜ਼ਟਰੀ ਲਈ ਅੱਪਲੋਡ ਕੀਤਾ।" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "ਰਿਪੋਜ਼ਟਰੀ '%s' ਸ਼ਾਮਲ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "ਗਲਤ ਐਕਸਪੋਰਟ ਫਾਇਲ ਨਾਂ ਹੈ।" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "ਲਿਖਣ ਲਈ ਫਾਇਲ ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ।" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "ਅਣਜਾਣ ਕਮਾਂਡ '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "ਪਾਰਸ ਕਰਨ ਦੌਰਾਨ ਫੇਲ੍ਹ: %s।" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "ਰਿਪੋਜ਼ਟਰੀ '%s' ਹਟਾਈ ਜਾ ਰਹੀ ਹੈ।" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "ਡੈਸਕਟਾਪ ਆਈਟਮ '%s' ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "VM ਦਾ ਨਾਂ ਇੱਕ ਅੰਕ ਨਾਲ ਸ਼ੁਰੂ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।" + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr "VM ਦਾ ਨਾਂ ਇੱਕ ਅੰਕ ਨਾਲ ਸ਼ੁਰੂ ਨਹੀਂ ਹੋ ਸਕਦਾ ਹੈ।" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "ਜਾਰੀ ਰੱਖਣਾ ਹੈ?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, fuzzy, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "ਲੋੜੀ ਫਾਇਲ ਗੁੰਮ ਹੈ: " + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "ਪੈਕੇਜ %s ਐਂਟੀਗਰੇਟੀ ਚੈਕ ਕਰਨ ਲਈ ਫੇਲ੍ਹ ਹੈ। ਕੀ ਤੁਸੀਂ ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰਨੀ ਚਾਹੁੰਦੇ ਹੋ?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "ਪੈਕੇਜ %s ਐਂਟੀਗਰੇਟੀ ਚੈਕ ਕਰਨ ਲਈ ਫੇਲ੍ਹ ਹੈ। ਕੀ ਤੁਸੀਂ ਮੁੜ-ਕੋਸ਼ਿਸ਼ ਕਰਨੀ ਚਾਹੁੰਦੇ ਹੋ?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm ਚੈੱਕ ਫੇਲ੍ਹ ਹੈ।" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm ਫੇਲ੍ਹ ਹੋਇਆ।" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "ਰਿਪੋਜ਼ਟਰੀ ਤੋਂ ਪਰੋਫਾਇਲ ਲੈਣ ਦੌਰਾਨ ਗਲਤੀ: " + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "ਰਿਪੋਜ਼ਟਰੀ ਵਿੱਚ ਕੋਈ URL ਨਹੀਂ ਹੈ।" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "ਫਾਇਲ ਨਹੀਂ ਬਣਾਈ ਜਾ ਸਕਦੀ ਹੈ।" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "ਆਮ ਤੌਰ ਉੱਤੇ ਇਹ ਲੋੜ ਅਣਡਿੱਠੀ ਕਰੋ" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "ਕੁਨੈਕਸ਼ਨ ਮੰਗ:" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "ਨਿਰਭਰਤਾ ਸਮੱਸਿਆਵਾਂ ਕਰਕੇ %s ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ।" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "%s ਕੋਈ ਨਹੀਂ ਦਿੰਦਾ ਹੈ" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "ਉਪਲੱਬਧ ਪਰੋਫਾਇਲ" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "ਮੰਗ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "ਇੰਸਟਾਲੇਸ਼ਨ ਹਦਾਇਤਾਂ ਮੁਤਾਬਕ ਅਧੂਰੀ ਛੱਡੀ ਗਈ ਹੈ।" + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "ਚਲਾਓ" + +# %s is either BOOTP or DHCP +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI ਚਲਾਉਣਾ ਫੇਲ੍ਹ: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "ਕੁੰਜੀ ਇੰਕ੍ਰਿਪਸ਼ਨ ਦੌਰਾਨ ਗਲਤੀ ਹੈ।" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "ਫੇਲ੍ਹ" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s ਲਈ ਸੰਰਚਨਾ ਫਾਇਲਾਂ ਬਦਲੀਆਂ:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "ਹੋਰ rpm ਆਉਟਪੁੱਟ:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "%s ਦਾ ਬੈਕਅੱਪ ਬਣਿਆ" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "ਫਾਇਲ ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕੀ: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "ਫਾਇਲ %1 ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ।" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "ਗਲਤ LDAP URL ਕਿਊਰੀ ਸਤਰ" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Url ਆਬਜੈਕਟ ਕਲੋਨ ਕਰਨ ਲਈ ਅਸਮਰੱਥ" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "ਗਲਤ ਖਾਲੀ Url ਆਬਜੈਕਟ ਰੈਫਰੈਂਸ" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Url ਭਾਗ ਪਾਰਸ ਕਰਨ ਲਈ ਅਸਮਰੱਥ" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "ਅਤੀਤ:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url ਸਕੀਮ ਲਈ %s ਮਨਜ਼ੂਰ ਨਹੀਂ ਹੈ" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "ਗਲਤ %s ਭਾਗ '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "ਗਲਤ %s ਭਾਗ" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url ਸਕੀਮ ਲਈ ਇੱਕ ਲੋੜੀਦਾ ਭਾਗ ਹੈ" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "ਗਲਤ Url ਸਕੀਮ '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url ਸਕੀਮ ਲਈ ਇੱਕ ਯੂਜ਼ਰ-ਨਾਂ ਮਨਜ਼ੂਰ ਨਹੀਂ ਹੈ" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url ਸਕੀਮ ਲਈ ਇੱਕ ਪਾਸਵਰਪ ਮਨਜ਼ੂਰ ਨਹੀਂ ਹੈ" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url ਲਈ ਇੱਕ ਹੋਸਟ ਭਾਗ ਲੋੜੀਦਾ ਹੈ" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url ਸਕੀਮ ਲਈ ਇੱਕ ਹੋਸਟ ਭਾਗ ਮਨਜ਼ੂਰ ਨਹੀਂ ਹੈ।" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "ਗਲਤ ਹੋਸਟ ਭਾਗ '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url ਸਕੀਮ ਇੱਕ ਪੋਰਟ ਨਹੀਂ ਦਿੰਦੀ ਹੈ।" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "ਗਲਤ ਪੋਰਟ ਭਾਗ '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url ਸਕੀਮ ਲਈ ਮਾਰਗ ਨਾਂ ਲੋੜੀਦਾ ਹੈ" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "ਕੁਨੈਕਟ ਕਰਨ ਦੌਰਾਨ ਚੱਲਦੀ ਕਮਾਂਡ" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "%s ਨਹੀਂ ਲੱਭਿਆ।" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "ਪਾਰਸ ਕਰਨ ਦੌਰਾਨ ਫੇਲ੍ਹ: %s।" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "ਮੋਡੀਊਲ \"%s\" ਲੋਡ ਕਰਨ ਲਈ ਫੇਲ ਹੈ।" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "ਫਾਇਲ %1 ਰਿਪੋਜ਼ਟਰੀ ਵਿੱਚ ਮੌਜੂਦ ਨਹੀਂ ਹੈ।" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "ਫਾਇਲ %1 ਲਿਖੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ।" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 ਡਾਇਰੈਕਟਰੀ ਨਹੀਂ ਹੈ।" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "ਖਾਲੀ CA ਨਾਂ ਹੈ।" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "ਗਲਤ URL ਸਕੀਮ '%1' ਹੈ।" + +#: zypp-media/mediaexception.cc:131 +#, fuzzy +msgid "Operation not supported by medium" +msgstr "ਪਰੋਫਾਇਲ ਵਰਜਨ ਅੱਪਾਰਮੋਰ ਮੋਡੀਊਲ ਵਲੋਂ ਸਹਾਇਕ ਨਹੀਂ ਹੈ\n" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +#, fuzzy +msgid "Cannot eject any media" +msgstr "ਕੋਈ ਸਕੀਮ ਨਹੀਂ ਲੱਭੀ ਹੈ।" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "ਡੈਸਕਟਾਪ ਆਈਟਮ '%s' ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "ਅਧਿਕਾਰ ਪਾਬੰਦੀ ਹੈ" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "ਹਾਂ" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "ਨਹੀਂ" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "ਸਾਵਧਾਨ: " + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "ਗਲਤੀ" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "ਪੂਰਾ" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "ਗਲਤੀ" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "ਸਾਵਧਾਨ: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "ਸ਼ੁਰੂ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "ਨਹੀਂ ਲੱਭਿਆ" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ਹਾਂ" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ਨਹੀਂ" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s %s ਦਿੰਦਾ ਹੈ, ਪਰ ਆਰਕੀਟੈਕਚਰ ਹੋਰ ਹੈ।" + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "ਸੋਰਸ ਪੈਕੇਜ %s-%s ਇੰਸਟਾਲ ਕਰਨ ਦੌਰਾਨ ਸਮੱਸਿਆ:" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "%s ਕੋਈ ਨਹੀਂ ਦਿੰਦਾ ਹੈ" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "ਇੰਸਟਾਲ ਨਹੀਂ ਹਨ" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s %s ਰਾਹੀਂ ਚਾਹੀਦਾ ਹੈ" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s ਦਾ %s ਨਾਲ ਅਪਵਾਦ ਹੈ" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s %s ਰਾਹੀਂ ਚਾਹੀਦਾ ਹੈ" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s %s ਰਾਹੀਂ ਚਾਹੀਦਾ ਹੈ" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s ਦਾ %s ਨਾਲ ਅਪਵਾਦ ਹੈ" + +#~ msgid "do not install %s" +#~ msgstr "%s ਨੂੰ ਨਾ ਹਟਾਓ" + +#~ msgid "keep %s" +#~ msgstr "%s ਰੱਖੋ" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s %s ਦਿੰਦਾ ਹੈ, ਪਰ ਆਰਕੀਟੈਕਚਰ ਹੋਰ ਹੈ।" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s ਹਟਾਓ" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "%s ਨੂੰ %s ਲਈ ਅੱਪਡੇਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" + +# %s is either BOOTP or DHCP +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "%s ਦੀ ਇੰਸਟਾਲੇਸ਼ਨ ਫੇਲ੍ਹ ਹੋਈ:" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "ਫਾਇਲ %1 ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ।" + +#~ msgid "Hal Exception" +#~ msgstr "Hal ਅਪਵਾਦ" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext ਕੁਨੈਕਟਡ ਨਹੀਂ" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive ਸ਼ੁਰੂ ਨਹੀਂ ਹੈ" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume ਸ਼ੁਰੂ ਨਹੀਂ ਕੀਤਾ" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "dbus ਕੁਨੈਕਸ਼ਨ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ" + +#, fuzzy +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_set_dbus_connection: dbus ਕੁਨੈਕਸ਼ਨ ਸੈੱਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: dbus ਕੁਨੈਕਸ਼ਨ ਸੈੱਟ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#~ msgid "Not a CDROM drive" +#~ msgstr "ਇੱਕ CDROM ਡਰਾਇਵ ਨਹੀਂ ਹੈ" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "mutex ਲਾਕ ਲਿਆ ਨਹੀਂ ਜਾ ਸਕਦਾ" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "mutex ਲਾਕ ਰੀਲਿਜ਼ ਨਹੀਂ ਜਾ ਸਕਦਾ" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "ਪਬਲਿਕ ਕੁੰਜੀ ਲੈਣ ਲਈ ਅਸਮਰੱਥ ਹੈ।" + +#, fuzzy +#~ msgid "generally ignore of some dependecies" +#~ msgstr "ਆਮ ਤੌਰ ਉੱਤੇ ਇਹ ਲੋੜ ਅਣਡਿੱਠੀ ਕਰੋ" + +#, fuzzy +#~ msgid "do not forbid installation of %s" +#~ msgstr "%s ਨੂੰ ਨਾ ਹਟਾਓ" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "ਇੰਸਟਾਲ ਨਹੀਂ ਹਨ" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "لا يمكن إنشاء المفتاح العام %s من %s إلى ملف حلقة المفاتيح %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "حاول استيراد مفتاح غير موجود %s إلى حلقة مفاتيح %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "لا يمكن تغيير مجلد العمل '/' داخل استجذار (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "فشل تهيئة تحميل (Metalink curl) '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "تحميل (metalink curl) خطأ '%s':\n" +#~ "رمز الخطأ: %s\n" +#~ "رسالة الخطأ: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "توقف التحميل في %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "توقف التحميل بواسطة المستخدم" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "حدث خطأ أثناء إعداد خيارات التحميل (metalink curl) ل '%s':" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "ਪਾਰਸ ਕਰਨ ਦੌਰਾਨ ਫੇਲ੍ਹ: %s।" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "ਸਰੀਬੀਆ ਅਤੇ ਮਾਂਟੀਂਗਰੋ" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "ਅਣਜਾਣ ਲਿਸਟ ਚੋਣ" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "ਨਿਰਭਰਤਾ ਹੱਲ਼ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕੀ" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "ਫਾਇਲ %s ਲਈ ਚੈਕਸਮ ਨਹੀਂ ਹੈ।\n" +#~ "ਕੀ ਫਾਇਲ ਇੰਝ ਹੀ ਵਰਤਣਾ ਹੈ?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "ਫਾਇਲ %s ਹੇਠ ਦਿੱਤੀ ਕੁੰਜੀ ਨਾਲ ਐਂਟਗਰੇਟੀ ਚੈੱਕ ਲਈ ਫੇਲ੍ਹ ਹੋਈ:\n" +#~ "%s|%s|%s\n" +#~ "ਕੀ ਫਾਇਲ ਵਰਤਣੀ ਹੈ?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "ਫਾਇਲ %s ਦਾ ਚੈਕਸਮ ਗਲਤ ਹੈ।\n" +#~ "%s ਦੀ ਲੋੜ ਸੀ, ਮਿਲਿਆ %s\n" +#~ "ਕੀ ਫਾਇਲ ਇੰਝ ਹੀ ਵਰਤਣੀ ਹੈ?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "ਫਾਇਲ %s ਲਈ ਅਣਜਾਣ ਚੈਕਸਮ %s ਹੈ।\n" +#~ "ਕੀ ਫਾਇਲ ਇੰਝ ਹੀ ਵਰਤਣੀ ਹੈ?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "ਫਾਇਲ %s ਸਾਇਨ ਨਹੀਂ ਹੈ।\n" +#~ "ਕੀ ਇਸ ਨੂੰ ਇੰਝ ਹੀ ਵਰਤਣਾ ਹੈ?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "ਫਾਇਲ %s ਇੱਕ ਅਣਜਾਣੀ ਕੁੰਜੀ ਨਾਲ ਸਾਇਨ ਕੀਤੀ ਗਈ ਹੈ:\n" +#~ "%s|%s|%s\n" +#~ "ਕੀ ਫਾਇਲ ਵਰਤਣੀ ਹੈ?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "ਅਣ-ਟਰਸਟਡ ਕੁੰਜੀ ਲੱਭੀ:\n" +#~ "%s|%s|%s\n" +#~ "ਕੁੰਜੀ ਉੱਤੇ ਭਰੋਸਾ ਕਰਨਾ ਹੈ?" + +#~ msgid "%s remove failed" +#~ msgstr "%s ਹਟਾਉਣਾ ਫੇਲ੍ਹ" + +#~ msgid "Invalid user name or password." +#~ msgstr "ਗਲਤ ਯੂਜ਼ਰ ਨਾਂ ਜਾਂ ਪਾਸਵਰਡ ਹੈ।" + +#~ msgid "rpm output:" +#~ msgstr "rpm ਆਉਟਪੁੱਟ:" + +#~ msgid "%s install failed" +#~ msgstr "%s ਇੰਸਟਾਲ ਫੇਲ੍ਹ ਹੈ" + +#~ msgid "%s installed ok" +#~ msgstr "%s ਇੰਸਟਾਲ ਹੋਇਆ" + +#~ msgid "%s remove ok" +#~ msgstr "%s ਹਟਾਇਆ" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "ਇੰਸਟਾਲ ਕਰਨ ਲਈ ਸੈੱਟ ਕੀਤੇ ਉਸ %s ਨੂੰ ਅਣਡਿੱਠਾ ਕਰੋ" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%s ਦਾ ਇਹ ਅਪਵਾਦ ਅਣਡਿੱਠਾ ਕਰੋ" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "ਇਹ ਲੋੜ ਇੱਥੇ ਹੀ ਅਣਡਿੱਠੀ ਕਰੋ" + +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "%s ਇੰਸਟਾਲ ਕਰੋ, ਭਾਵੇਂ ਇਹ ਵੇਂਡਰ ਬਦਲ ਦੇਵੇਗਾ" + +#~ msgid "Install missing resolvables" +#~ msgstr "ਗੁੰਮ ਹੱਲ-ਯੋਗ ਇੰਸਟਾਲ ਕਰੋ" + +#~ msgid "Keep resolvables" +#~ msgstr "ਹੱਲ-ਯੋਗ ਰੱਖੋ" + +#~ msgid "Unlock these resolvables" +#~ msgstr "ਇਹ ਹੱਲਯੋਗ ਅਣਲਾਕ ਕਰੋ" + +#~ msgid "install %s" +#~ msgstr "%s ਇੰਸਟਾਲ" + +#~ msgid "unlock %s" +#~ msgstr "%s ਅਣਲਾਕ" + +#~ msgid "unlock all resolvables" +#~ msgstr "ਸਭ ਹੱਲਯੋਗ ਅਣਲਾਕ ਕਰੋ" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "ਫਾਇਲ %1 ਖੋਲ੍ਹੀ ਨਹੀਂ ਜਾ ਸਕਦੀ ਹੈ।" + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "ਰਿਪੋਜ਼ਟਰੀ ਤੋਂ ਪੜ੍ਹਨ ਦੌਰਾਨ ਗਲਤੀ:" + +#~ msgid "Software management is already running." +#~ msgstr "ਸਾਫਟਵੇਅਰ ਪਰਬੰਧ ਪਹਿਲਾਂ ਹੀ ਚੱਲ ਰਿਹਾ ਹੈ।" + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s ਨੂੰ %s ਨਾਲ ਬਦਲਿਆ ਜਾਂਦਾ ਹੈ" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s ਨੂੰ %s ਨਾਲ ਬਦਲਿਆ ਗਿਆ" + +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "%s ਨੂੰ ਯੂਜ਼ਰ ਵਲੋਂ ਹਟਾਇਆ ਜਾਵੇਗਾ।\n" + +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s ਨੂੰ ਯੂਜ਼ਰ ਵਲੋਂ ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ।\n" + +#~ msgid "Invalid information" +#~ msgstr "ਗਲਤ ਜਾਣਕਾਰੀ" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s ਲੋੜੀਦਾ ਹੈ:\n" +#~ "%s" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s ਦਾ ਅਪਵਾਦ ਹੈ:\n" +#~ "%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "ਇਹ ਹੱਲ-ਕਰਨ-ਯੋਗ ਸਿਸਟਮ ਤੋਂ ਹਟਾਏ ਜਾਣਗੇ।" + +#~ msgid "%s depends on %s" +#~ msgstr "%s %s ਉੱਤੇ ਨਿਰਭਰ ਹੈ" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s ਨਿਰਭਰ ਹੈ: %s" + +#~ msgid "Child of" +#~ msgstr "ਚਾਈਲਡ" + +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "ਇਹ ਲੋੜ ਨੂੰ ਪੂਰੀ ਕਰਨ ਲਈ ਕੋਈ ਸਰੋਤ ਉਪਲੱਬਧ ਨਹੀਂ ਹੈ।" + +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%s ਨੂੰ ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ, ਕਿਉਂਕਿ ਇਸ ਦਾ %s ਨਾਲ ਅਪਵਾਦ ਹੈ।" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s ਇੰਸਟਾਲ ਨਹੀਂ ਹੈ ਅਤੇ ਅਣ-ਇੰਸਟਾਲਯੋਗ ਮਾਰਕ ਕੀਤਾ ਗਿਆ" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s ਲਈ ਨਿਰਭਰਤਾ ਅਧੂਰੀ ਹੈ" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s ਨੂੰ ਨਿਰਭਰਤਾ ਅਧੂਰੀ ਹੋਣ ਕਰਕੇ ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#~ msgid "No need to install %s" +#~ msgstr "%s ਇੰਸਟਾਲ ਕਰਨ ਦੀ ਲੋੜ ਨਹੀਂ ਹੈ" + +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "%s ਨੂੰ %s ਦੀ ਨਿਰਭਰਤਾ ਪੂਰੀ ਨਾ ਹੋਣ ਕਰਕੇ ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "%s ਨੂੰ %s ਦੀ ਨਿਰਭਰਤਾ ਪੂਰੀ ਨਾ ਹੋਣ ਕਰਕੇ ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ" + +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s ਨੂੰ ਅਣ-ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾਵੇਗਾ, ਕਿਉਂਕਿ ਇਹ ਹਾਲੇ ਵੀ ਲੋੜੀਦਾ ਹੈ" + +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "%s ਨੂੰ ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ, ਕਿਉਂਕਿ ਇਹ ਅਪਵਾਦ ਪੈਦਾ ਕਰਦਾ ਹੈ" + +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s ਲਈ %s ਲੋੜ ਦੀ ਕਮੀ ਹੈ" + +#~ msgid ", Action: " +#~ msgstr ", ਕਾਰਵਾਈ: " + +#~ msgid ", Trigger: " +#~ msgstr ", ਟਿਗਰ: " + +#~ msgid "package" +#~ msgstr "ਪੈਕੇਜ" + +#~ msgid "selection" +#~ msgstr "ਚੋਣ" + +#~ msgid "pattern" +#~ msgstr "ਪੈਟਰਨ" + +#~ msgid "product" +#~ msgstr "ਪਰੋਡੱਕਟ" + +#~ msgid "patch" +#~ msgstr "ਪੈਚ" + +#~ msgid "script" +#~ msgstr "ਸਕ੍ਰਿਪਟ" + +#~ msgid "message" +#~ msgstr "ਸੁਨੇਹਾ" + +#~ msgid "atom" +#~ msgstr "ਐਟਮ" + +#~ msgid "system" +#~ msgstr "ਸਿਸਟਮ" + +#~ msgid "Resolvable" +#~ msgstr "ਹੱਲ-ਯੋਗ" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "ਇਹ ਹੱਲ ਦੀ ਕੋਸ਼ਿਸ਼ ਨੂੰ ਗਲਤ ਮਾਰਕ ਕਰੋ।" + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "ਹੱਲ-ਯੋਗ %s ਨੂੰ ਅਣ-ਇੰਸਟਾਲ ਯੋਗ ਮਾਰਕ ਕਰੋ" + +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "%s ਨੂੰ ਇੰਸਟਾਲ ਕਰਨ ਲਈ ਸ਼ੈਡਿਊਲ ਕੀਤਾ ਗਿਆ ਹੈ, ਪਰ ਨਿਰਭਰਤਾ ਸਮੱਸਿਆ ਕਰਕੇ ਸੰਭਵ ਨਹੀਂ ਹੈ।" + +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "%s ਨੂੰ ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ, ਕਿਉਂਕਿ ਇਹ ਇਸ ਸਿਸਟਮ ਉੱਤੇ ਲਾਗੂ ਨਹੀਂ ਹੁੰਦਾ ਹੈ।" + +#~ msgid "Establishing %s" +#~ msgstr "%s ਤਿਆਰ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" + +#~ msgid "Installing %s" +#~ msgstr "%s ਇੰਸਟਾਲ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "%s ਛੱਡਿਆ ਜਾਂਦਾ ਹੈ: ਪਹਿਲਾਂ ਹੀ ਇੰਸਟਾਲ ਹੈ" + +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "ਇੰਸਟਾਲ %s ਦੇਣ ਵਾਲਾ ਕੋਈ ਬਦਲਵਾਂ ਪਰੋਵਾਈਡਰ ਨਹੀਂ ਹੈ।" + +#~ msgid "for %s" +#~ msgstr "%s ਲਈ" + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s %s ਦਿੰਦਾ ਹੈ, ਪਰ ਅਣ-ਇੰਸਟਾਲ ਕਰਨ ਲਈ ਸ਼ੈਡਿਊਲ ਹੈ।" + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s %s ਦਿੰਦਾ ਹੈ, ਪਰ ਉਸ %s ਦਾ ਹੋਰ ਵਰਜਨ ਪਹਿਲਾਂ ਹੀ ਇੰਸਟਾਲ ਹੈ।" + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s %s ਦਿੰਦਾ ਹੈ, ਪਰ ਅਣ-ਇੰਸਟਾਲ-ਯੋਗ ਹੈ। ਹੋਰ ਜਾਣਕਾਰੀ ਲਈ ਖੁਦ ਹੀ ਇੰਸਟਾਲ ਕਰਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।" + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s %s ਦਿੰਦਾ ਹੈ, ਪਰ ਲਾਕ ਹੈ" + +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s %s ਦਿੰਦਾ ਹੈ, ਪਰ ਵੇਂਡਰ (%s) ਹੋਰ ਹੈ।" + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "%s ਦੀ ਲੋੜ ਨੂੰ %s ਲਈ ਪੂਰਾ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ ਹੈ" + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s ਲਾਕ ਹੈ ਅਤੇ ਅਣ-ਇੰਸਟਾਲ ਨਹੀਂ ਕੀਤਾ ਜਾ ਸਕਦਾ।" + +#~ msgid "from %s" +#~ msgstr "%s ਤੋਂ" + +#~ msgid " Error!" +#~ msgstr " ਗਲਤੀ!" + +#~ msgid " Important!" +#~ msgstr " ਖਾਸ!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s %s ਉੱਤੇ ਨਿਰਭਰ ਹੈ" + +#~ msgid "%s is recommended by %s" +#~ msgstr "%s %s ਵਲੋਂ ਸਿਫਾਰਸ਼ੀ ਹੈ" + +#~ msgid "%s is suggested by %s" +#~ msgstr "%s ਲਈ %s ਵਲੋਂ ਸੁਝਾਅ ਹੈ" + +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s %s ਵਲੋਂ ਇੰਹਾਂਸਡ ਹੈ" + +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s %s ਦਾ ਸਪਲੀਮੈਂਟ ਹੈ" + +#~ msgid "%s part of %s" +#~ msgstr "%s %s ਦਾ ਭਾਗ ਹੈ" + +#~ msgid "Reading '%s' repository cache" +#~ msgstr "'%s' ਰਿਪੋਜ਼ਟਰੀ ਕੈਚੇ ਪੜ੍ਹੀ ਜਾ ਰਹੀ ਹੈ" + +#~ msgid "Cleaning repository '%s' cache" +#~ msgstr "ਰਿਪੋਜ਼ਟਰੀ '%s' ਕੈਚੇ ਸਾਫ਼ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" + +#~ msgid "Reading repository '%s' cache" +#~ msgstr "ਰਿਪੋਜ਼ਟਰੀ '%s' ਕੈਚੇ ਪੜ੍ਹੀ ਜਾ ਰਹੀ ਹੈ" + +#~ msgid "%s will be deleted by another application. (ApplLow/ApplHigh)\n" +#~ msgstr "%s ਨੂੰ ਹੋਰ ਕਾਰਜ ਵਲੋਂ ਹਟਾਇਆ ਜਾਵੇਗਾ। (ApplLow/ApplHigh)\n" + +#~ msgid "Requirememt %s cannot be fulfilled." +#~ msgstr "%s ਲੋੜ ਪੂਰੀ ਨਹੀਂ ਕੀਤੀ ਜਾ ਸਕਦੀ ਹੈ।" + +#~ msgid "Make a solver run with ALL possibilities." +#~ msgstr "ਸੋਲਵਰ ਨੂੰ _ਸਭ_ ਸੰਭਵਾਨਾਵਾਂ ਨਾਲ ਚਲਾਓ" + +#, fuzzy +#~ msgid "Make a solver run with best architecture only." +#~ msgstr "ਸੋਲਵਰ ਨੂੰ _ਸਭ_ ਸੰਭਵਾਨਾਵਾਂ ਨਾਲ ਚਲਾਓ" + +#, fuzzy +#~ msgid "Start the next solver run with doubled timeout." +#~ msgstr "ਸੋਲਵਰ ਨੂੰ _ਸਭ_ ਸੰਭਵਾਨਾਵਾਂ ਨਾਲ ਚਲਾਓ" diff --git a/po/pl.po b/po/pl.po new file mode 100644 index 0000000..b060286 --- /dev/null +++ b/po/pl.po @@ -0,0 +1,5514 @@ +# Copyright (C) 2006 SuSE Linux Products GmbH, Nuernberg +# This file is distributed under the same license as the package. +# +# Mariusz Fik , 2010, 2011, 2012, 2014, 2015. +# Przemyslaw Bojczuk , 2013. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2019-03-14 18:32+0000\n" +"Last-Translator: Ewelina Michalowska \n" +"Language-Team: Polish \n" +"Language: pl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 " +"|| n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.3\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Nieznane państwo: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Bez kodu" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andora" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Zjednoczone Emiraty Arabskie" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua i Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antyle Holenderskie" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktyda" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentyna" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Amerykańskie" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Wyspy Alandzkie" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbejdżan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bośnia i Hercegowina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesz" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgia" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bułgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrajn" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudy" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Boliwia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazylia" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamy" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Wyspa Bouveta" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Białoruś" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Wyspy Kokosowe" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Republika Środkowoafrykańska" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Szwajcaria" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Wybrzeże Kości Słoniowej" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Wyspy Cooka" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Chiny" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kostaryka" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Wyspy Zielonego Przylądka" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Wyspa Bożego Narodzenia" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cypr" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Czechy" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Niemcy" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Dżibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dania" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikana" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algieria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekwador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sahara Zachodnia" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Erytrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Hiszpania" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlandia" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidżi" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandy (Malwiny)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikronezja" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Wyspy Owcze" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francja" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Francja metropolitalna" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Zjednoczone Królestwo" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gruzja" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Gujana Francuska" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grenlandia" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Gwinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Gwadelupa" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Gwinea Równikowa" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grecja" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Georgia Południowa i Sandwich Południowy" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Gwatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Gwinea Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Gujana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Wyspy Heard i McDonalda" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Chorwacja" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Węgry" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonezja" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlandia" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Wyspa Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indie" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Brytyjskie Terytorium Oceanu Indyjskiego" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islandia" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Włochy" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamajka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordania" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonia" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgistan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodża" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komory" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts i Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Korea Północna" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Korea Południowa" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwejt" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kajmany" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazachstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laotańska Republika Ludowo-Demokratyczna" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Liban" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litwa" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Łotwa" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Mołdawia" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Czarnogóra" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint-Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Wyspy Marshalla" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Birma" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Mariany Północne" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martynika" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauretania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Malediwy" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksyk" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malezja" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nowa Kaledonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Holandia" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norwegia" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nowa Zelandia" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinezja Francuska" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua - Nowa Gwinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipiny" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polska" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint-Pierre i Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Portoryko" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Autonomia Palestyńska" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugalia" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paragwaj" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumunia" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Federacja Rosyjska" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arabia Saudyjska" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Wyspy Salomona" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seszele" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Szwecja" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Święta Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Słowenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard i Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Słowacja" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Wyspy Św. Tomasza i Książęca" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Salwador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Suazi" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Wyspy Turks i Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Czad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Francuskie Terytoria Południowe" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tajlandia" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadżykistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunezja" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor Wschodni" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turcja" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trynidad i Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tajwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Dalekie Wyspy Mniejsze Stanów Zjednoczonych" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Stany Zjednoczone Ameryki Północnej" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Urugwaj" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Watykan" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent i Grenadyny" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Wenezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Brytyjskie Wyspy Dziewicze" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Amerykańskie Wyspy Dziewicze" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Wietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Republika Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis i Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Majotta" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Republika Południowej Afryki" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Dostarcza" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Wymagania wstępne" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Wymaga" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Konflikty" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Zastępuje" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Zaleca" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Sugeruje" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Ulepsza" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Uzupełnia" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Próbowano zaimportować nieistniejący klucz %s do bazy kluczy %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Nie udało się zaimportować klucza." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Usunięcie klucza nie powiodło się." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Nie znaleziono pliku sygnatury %s" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Nieznany język: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "abchaski" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "aceh" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "aczoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "adygejski" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "afroazjatyckie (inne)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "akadyjski" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "albański" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "aleucki" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "języki algonkińskie" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "ałtajski południowy" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "amharski" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "staroangielski (ok. 450–1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "języki apaczańskie" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "arabski" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "aramejski" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "aragoński" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "ormiański" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "araukański" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "sztuczne (inne)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "arawakańskie" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "assamski" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "asturyjski" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "języki atapaskańskie" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "języki australijskie" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "awarski" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "awestyjski" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "ajmara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "azerbejdżański" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "języki bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "baszkirski" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "beludżyjski" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "balijski" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "baskijski" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "bałtyckie (inne)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "bedża" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "białoruski" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "bengalski" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "berberskie (inne)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "bhodżpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "biharski" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "bikolskie" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "bantu (inne)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "bośniacki" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "bradż" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "bretoński" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "batackie (Indonezja)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "buriacki" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "bugijski" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "bułgarski" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "birmański" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "kadoskie" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Indian środkowoamerykańskich (inne)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "karaibski" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "kataloński" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "kaukaskie (inne)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "celtyckie (inne)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "czibczańskie" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "czeczeński" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "czagatajski" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "chiński" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "czukocki" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "maryjski" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Dialekt czinucki" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "czipewiański" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "czerokeski" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "starocerkiewnosłowiański" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "czuwaski" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "czejeński" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "języki chamickie" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "koptyjski" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "kornwalijski" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "korsykański" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreolskie i pidżyny oparte na angielskim (inne)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreolskie i pidżyny oparte na francuskim (inne)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreolskie i pidżyny oparte na portugalskim (inne)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "tatarski (krymski)" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreolskie i pidżyny różne (inne)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "kaszubski" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "kuszyckie (inne)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "czeski" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "duński" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "dajackie" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "niewolnicze (atapaskańskie)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "malediwski" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "drawidyjskie (inne)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "łużycki dolny" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "średnioholenderski (ok. 1050–1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "holenderski" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "dzongka" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "egipski (starożytny)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "elamicki" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "angielski" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "średnioangielski (1100–1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "estoński" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "fan" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "farerski" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "fante" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "fidżyjski" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "fiński" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "ugrofińskie (inne)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "francuski" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "średniofrancuski (ok. 1400–1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "starofrancuski (842–ok. 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "fryzyjski" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "fulani" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "friulski" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "germańskie (inne)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "gruziński" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "niemiecki" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "ge'ez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "gilbertański" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "gaelicki (szkocki)" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "irlandzki" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "galicyjski" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "mański" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "średniowysokoniemiecki (ok. 1050–1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "starowysokoniemiecki (ok. 750–1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "gorontalskie" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "gocki" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "grecki, starożytny (do 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "grecki, współczesny (1453–)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "gudżarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "haiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "hausański" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "hawajski" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "hebrajski" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "himaczali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "hetycki" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "hiri motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "łużycki górny" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "węgierski" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "islandzki" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "sichuan yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "interlingwe" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "ilokano" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "interlingua (Międzynarodowe Stowarzyszenie Języka Pomocniczego)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "indyjskie (inne)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "indonezyjski" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "indoeuropejskie (inne)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "inguski" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "inupiak" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "irańskie (inne)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "języki irokeskie" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "włoski" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "jawajski" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "japoński" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "judeo-perski" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "udeo-arabski" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "karakałpacki" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "kabylski" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "kareński" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "kaszmirski" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "kazachski" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "kabardyjski" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "khazi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "khoisan (inne)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "khmerski" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "chotański" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "kinjarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "kirgiski" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "koreański" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "keresański" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "karaczajsko-bałkarski" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "kuruch" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "kwanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "kumycki" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "kurdyjski" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "laotański" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "łaciński" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "łotewski" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "lezgiński" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "limburgan" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "litewski" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "luksemburski" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "luba-lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "luba-katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "luo (Kenia i Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "macedoński" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "madurski" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "marshall" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "makasarski" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "malajalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "maoryjski" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "języki malajo-polinezyjskie (inne)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "masajski" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "malajski" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "mandarski" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "średnioirlandzki (900–1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "micmac" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "języki różne" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "mon-khmerskie (inne)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "malgaski" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "maltański" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "mandżurski" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "języki manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "mołdawski" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "mongolski" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Wielojęzyczność" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "języki munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "mirandyjski" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "języki majskie" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Indian północnoamerykańskich (inne)" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "neapolitański" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "ndebele, południowy" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "ndebele, północny" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "dolny niemiecki" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "nepalski" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "nepalski Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "niger-kordofańskie (inne)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "niueński" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "norweski (nynorsk)" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "norweski (Bokmål)" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "staronordyjski" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "norweski" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "sotho północny" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "języki nubijskie" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "newari klasyczny" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "njamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "njankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "njoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "nzema" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "okcytańskie (po 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "odżibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "orija" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "osetyński" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "turecki, osmańskie (1500–1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "języki otomiańskie" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "papuaskie (inne)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "pahlawi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "pampangan" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "pandżabski" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "palauański" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "staroperski (ok. 600–400 p.n.e.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "perski" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "filipińskie (inne)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "fenicki" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "polski" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "ponapeański" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "portugalski" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakryty" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "staroprowansalski (do 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "pusztu" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "keczua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "radżastani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "rapanuański" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "rarotongański" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "romańskie (inne)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "retoromański" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "cygański / romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "rumuński" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "rosyjski" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "jakucki" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Indian południowoamerykańskich (inne)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "języki saliskie" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "samarytański" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "sanskrycki" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "serbski" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "sycylyjski" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "szkocki" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "chorwacki" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "selkupski" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "semickie (inne)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "staroirlandzki (do 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "języki migowe" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "szan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "syngaleski" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "języki Siuksów" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "chińsko-tybetańskie (inne)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "słowiańskie (inne)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "słowacki" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "słoweński" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "lapoński południowy" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "lapoński północny" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "języki sami (inne)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "lulu sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "inar sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "samoański" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "skolt sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "szona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "sogdyjski" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "somalijski" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "sotho południowy" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "hiszpański" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "sardyńskie" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "nilo-saharyjskie (inne)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "sundajski" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "sumeryjski" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "suahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "szwedzki" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "syryjski" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "tahitański" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "tajskie (inne)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "tamilski" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "tatarski" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "teme" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "tadżycki" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "tajski" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "tybetański" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "klingoński" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "tamaszek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "tongański (Niasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "tangański (wyspy Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "neomelanezyjski" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "turkmeński" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "tubuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "języki tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "turecki" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "języki ałtajskie (inne)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "twi (aszanti)" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "tuwiński" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "udmurcki" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "ugarycki" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "ujgurski" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "ukraiński" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "nieokreślony" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "uzbecki" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "wietnamski" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "volapűk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "wotski" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "języki wakasz" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "walijski" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "języki łużyckie" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "walloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "jao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "japski" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "jidysz" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "joruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "języki yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "zapoteckie" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Wykonane zostaną następujące czynności:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "nie wygasa" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "wygasł: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "wygasa: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(nie wygasa)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(WYGASŁY)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(wygasa w ciągu 24 godzin)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(wygasa w ciągu %d dnia)" +msgstr[1] "(wygasa w ciągu %d dni)" +msgstr[2] "(wygasa w ciągu %d dni)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "nieznany" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "niewspierany" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Poziom 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Poziom 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Poziom 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Wymagana dodatkowa umowa użytkownika" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "nieprawidłowy" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Nieokreślony poziom wsparcia" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Producent nie zapewnia wsparcia." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Określenie problemu oznacza, że pomoc techniczna obejmuje informacje na " +"temat kompatybilności, pomoc w zakresie instalacji, użytkowania i bieżącej " +"konserwacji oraz podstawowego rozwiązywania problemów. Pomoc techniczna na " +"poziomie 1 nie obejmuje naprawy błędów produktu." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Wyizolowanie problemu oznacza, że pomoc techniczna obejmuje odtworzenie " +"problemów użytkownika, oddzielenie ich i dostarczenie rozwiązania problemów " +"nieobjętych pomocą techniczną na poziomie 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Rozwiązywanie problemu: pomoc techniczna obejmuje rozwiązywanie złożonych " +"problemów przy użyciu metod inżynieryjnych w celu naprawy defektów produktów " +"zidentyfikowanych w ramach wsparcia technicznego na poziomie 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" +"Do otrzymania pomocy technicznej wymagana jest dodatkowa umowa użytkownika." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Nieznana opcja wsparcia. Brak opisu" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Zarządzanie systemem jest zablokowane przez program o identyfikatorze pid %d " +"(%s).\n" +"Proszę zamknąć ten program i spróbować ponownie." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Nieznany tryb dopasowania '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Nieznany tryb dopasowania '%s' dla wzorca '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Nieprawidłowe wyrażenie regularne '%s': regcomp zwróciło %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Nieprawidłowe wyrażenie regularne '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Wymagane uwierzytelnienie dla '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Proszę odwiedzić SUSE Customer Center, aby sprawdzić, czy rejestracja jest " +"ważna i czy nie wygasła." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Proszę odwiedzić Centrum obsługi klienta firmy Novell, aby sprawdzić, czy " +"rejestracja jest ważna i czy nie wygasła." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Tworzenie punktu dołączenia: nie można znaleźć katalogu z możliwością zapisu " +"w celu utworzenia punktu dołączenia" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Zainstaluj najpierw pakiet 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Nie można utworzyć katalogu pamięci podręcznej metadanych." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Błąd podczas próby odczytu z '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Nie można utworzyć %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Pod podanym adresem URL nie znaleziono prawidłowych metadanych" +msgstr[1] "Pod podanymi adresami URL nie znaleziono prawidłowych metadanych" +msgstr[2] "Pod podanymi adresami URL nie znaleziono prawidłowych metadanych" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Tworzenie pamięci podręcznej repozytorium nie powiodło się (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Budowanie pamięci podręcznej repozytorium '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Nie można utworzyć pamięci podręcznej w %s - brak uprawnień do zapisu." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Nieobsługiwany typ repozytorium" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Dodawanie repozytorium '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nieprawidłowa nazwa pliku repozytorium pod adresem '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Nie można otworzyć pliku '%s' do zapisu." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Nieznany błąd podczas odczytu z '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Nie można odczytać katalogu repozytorium '%1%': odmowa dostępu" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Odczyt katalogu '%s' nie powiódł się" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Nie można odczytać pliku repozytorium '%1%': odmowa dostępu" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Usuwanie repozytorium '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Nie można określić miejsca przechowywania repozytorium." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Nie można usunąć '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Nie można określić, gdzie jest przechowywana usługa." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Nieznana usługa '%1%': usuwanie osieroconego repozytorium usługi '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Alias repozytorium nie może rozpoczynać się od kropki." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Alias usługi nie może rozpoczynać się od kropki." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Czy kontynuować?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Repozytorium %1% nie definiuje dodatkowych adresów URL 'gpgkey='." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Wyszukiwanie identyfikatora %1% klucza gpg w repozytorium %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Wyszukiwanie identyfikatora %1% klucza gpg w pamięci podręcznej %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Brak wymaganego atrybutu '%s'." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Wymagany jeden lub oba atrybuty '%s' i '%s'." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Weryfikacja podpisu nie powiodła się" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Pakiet %s wygląda na uszkodzony podczas przesyłania. Czy ponowić próbę " +"pobrania?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Nie można dostarczyć pakietu %s. Czy ponowić próbę pobrania?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Sprawdzenie applydeltarpm zakończone niepowodzeniem." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm zakończone niepowodzeniem." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Wtyczka usługi nie obsługuje zmiany atrybutu." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Nie można dostarczyć pliku '%s' z repozytorium '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Brak adresu URL w repozytorium." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Plik %1%\n" +" z pakietu\n" +" %2%\n" +" jest w konflikcie z plikiem z pakietu\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Plik %1%\n" +" z pakietu\n" +" %2%\n" +" jest w konflikcie z plikiem z instalacji\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Plik %1%\n" +" z instalacji\n" +" %2%\n" +" jest w konflikcie z plikiem z pakietu\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Plik %1%\n" +" z instalacji\n" +" %2%\n" +" jest w konflikcie z plikiem z instalacji\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Plik %1%\n" +" z pakietu\n" +" %2%\n" +" jest w konflikcie z plikiem\n" +" %3%\n" +" z pakietu\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Plik %1%\n" +" z pakietu\n" +" %2%\n" +" jest w konflikcie z plikiem\n" +" %3%\n" +" z instalacji\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Plik %1%\n" +" z instalacji\n" +" %2%\n" +" jest w konflikcie z plikiem\n" +" %3%\n" +" z pakietu\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Plik %1%\n" +" z instalacji\n" +" %2%\n" +" jest w konflikcie z plikiem\n" +" %3%\n" +" z instalacji\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Nie można utworzyć sat-pool." + +# break odnosi się do możliwego zepsucia wynikającego ze zignorowania zależności, więc "zainstaluj" wydaje się tu właściwe. Fisiu +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "zainstaluj %s, ignorując niektóre z zależności" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "zazwyczaj ignoruje pewne zależności" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "sprzeczne żądania" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "problem z kilkoma zależnościami" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "nieobsługiwane żądanie" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "usunięci dostawcy: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"dostawcy, których nie można zainstalować: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "dostawcy, których nie można zainstalować: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "To żądanie uszkodzi system!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignoruj ostrzeżenie o uszkodzeniu systemu" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Instalacja przerwana zgodnie z życzeniem." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " wykonano" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " wykonanie nie powiodło się" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s został już wykonany jako %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " nie wykonano w wyniku przerwania" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Błąd podczas wysyłania powiadomienia o aktualizacji." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nowy komunikat o aktualizacji" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Wystąpił błąd RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Nie udało się zaimportować klucza publicznego z pliku %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Usunięcie klucza publicznego nie powiodło się %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Zmienione pliki konfiguracyjne dla %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm zapisał %s jako %s, ale nie można było określić różnicy" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm zapisał %s jako %s.\n" +"Oto pierwszych 25 linii różnicy:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm utworzył %s jako %s, ale nie można było określić różnicy" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm utworzył %s jako %s.\n" +"Oto pierwszych 25 linii różnicy:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Dodatkowe wyjście rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "utworzono zapasowy %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Podpis jest OK" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Nieznany rodzaj podpisu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Nie można sprawdzić podpisu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Podpis jest OK, ale klucz nie jest zaufany" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Klucz publiczny podpisów nie jest dostępny" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Plik nie istnieje lub nie można sprawdzić podpisu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Plik jest niepodpisany" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Niepewny typ '%s' dla %u-bajtowej sumy kontrolnej '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Nie można otworzyć pseudoterminala (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Nie można otworzyć potoku (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Nieprawidłowy ciąg zapytania adresu URL LDAP" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Nieprawidłowy parametr zapytania URL LDAP '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Nie można sklonować obiektu URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Nieprawidłowe odwołanie do pustego obiektu adresu URL" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Analiza komponentów URL nie powiodła się" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historia:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Schemat URL nie zezwala na %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Nieprawidłowe: %s, komponent: '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Komponent — nieprawidłowe: %s" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Analiza zapytania nie jest obsługiwana dla tego adresu URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Schemat URL to wymagany komponent" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Nieprawidłowy schemat URL '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Schemat URL nie zezwala na nazwę użytkownika" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Schemat URL nie zezwala na hasło" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Schemat URL wymaga komponentu hosta" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Schemat URL nie zezwala na komponent hosta" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Nieprawidłowy komponent hosta '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Schemat URL nie zezwala na port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Nieprawidłowy komponent portu '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Schemat URL wymaga nazwy ścieżki" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Względna ścieżka nie jest dozwolona, jeśli usługa istnieje" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Zakodowany łańcuch znaków zawiera bajt NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Nieprawidłowy znak parametru podziału tablicy" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Nieprawidłowy znak parametru podziału mapy" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Nieprawidłowy znak parametru połączenia tablicy" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Polecenie zakończone statusem %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Polecenie zakończone przez sygnał %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Polecenie zakończone nieznanym błędem." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Nie można wykonać polecenia chroot dla '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Nie można wykonać polecenia chdir dla elementu '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" +"Nie można wykonać polecenia chdir dla elementu %s w zmienionym katalogu " +"głównym chroot %s (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Nie można wykonać '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Nie można wykonać fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Montowanie %s w %s zakończone niepowodzeniem" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Odmontowywanie %s zakończone niepowodzeniem" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Błędna nazwa pliku: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Nieotwarty nośnik podczas próby wykonania akcji '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Pliku '%s' nie znaleziono na nośniku '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Nie można zapisać pliku '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Nośnik niedołączony" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Błędny punkt dołączenia nośnika" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Inicjalizacja pobierania (curl) dla '%s' zakończona niepowodzeniem" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Wyjątek systemowy '%s' na nośniku '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Ścieżka '%s' na nośniku '%s' nie prowadzi do pliku." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Ścieżka '%s' na nośniku '%s' nie prowadzi do katalogu." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Błędny adres URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Pusta nazwa hosta w adresie URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Pusty system plików w adresie URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Pusty element docelowy w adresie URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Nieobsługiwany schemat adresu URI w '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operacja nieobsługiwana przez nośnik" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Błąd pobierania (curl) dla '%s':\n" +"Kod błędu: %s\n" +"Komunikat błędu: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Napotkano błąd podczas ustawiania opcji pobierania (curl) dla '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Źródło nośników '%s' nie zawiera żądanego nośnika" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Nośnik '%s' jest używany przez inną instancję" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Nie można wysunąć żadnego nośnika" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Nie można wysunąć nośnika '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Dostęp do '%s' zabroniony." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Przekroczono limit czasu podczas dostępu do '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Pobrane dane przekroczyły oczekiwany rozmiar pliku '%s' z '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Położenie '%s' jest tymczasowo niedostępne." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Problem z certyfikatem SSL; proszę sprawdzić, czy certyfikat CA jest " +"odpowiedni dla \"%s\"." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Nieobsługiwana metoda uwierzytelniania HTTP: '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Tak" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nie" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Informacja:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Ostrzeżenie:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Błąd:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "gotowe" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "błąd" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Ostrzeżenie: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Pobieranie:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "uruchamianie" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "nie znaleziono" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Nie jest dostępna pomoc dla tej wskazówki." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "pomoc nie jest dostępna dla tej opcji" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "wyświetla wszystkie opcje" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "Tak" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "Nie" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Wykonywanie skryptu %%posttrans '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Wykonywanie skryptów %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "Pakiet nie jest podpisany!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s nie należy do repozytorium uaktualniania dystrybucji" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s jest przewidziany dla niższej architektury" + +#~ msgid "problem with installed package %s" +#~ msgstr "problem z zainstalowanym pakietem %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "żaden pakiet nie dostarcza żądanego %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Czy włączono wszystkie wymagane repozytoria?" + +#~ msgid "package %s does not exist" +#~ msgstr "pakiet %s nie istnieje" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "Element %s jest dostarczany przez system i nie można go usunąć" + +#~ msgid "%s is not installable" +#~ msgstr "%s nie można zainstalować" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "żaden pakiet nie dostarcza %s wymaganego przez %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "nie można jednocześnie zainstalować %s i %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s jest w konflikcie z %s dostarczonym przez %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s dezaktualizuje %s, dostarczony przez %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s dezaktualizuje %s, dostarczony przez %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "" +#~ "Element rozwiązywalny %s jest w konflikcie z %s, dostarczonym przez " +#~ "samego siebie" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s wymaga %s, lecz nie można spełnić tego wymagania" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "usuń blokadę, aby umożliwić usunięcie %s" + +#~ msgid "do not install %s" +#~ msgstr "nie instaluj %s" + +#~ msgid "keep %s" +#~ msgstr "zachowaj %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "usuń blokadę, aby umożliwić instalację %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "" +#~ "nie pytaj o instalację wszystkich elementów rozwiązywalnych, " +#~ "dostarczających %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "" +#~ "nie pytaj o usunięcie wszystkich elementów rozwiązywalnych, " +#~ "dostarczających %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "nie instaluj najnowszej wersji %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "zachowaj %s, mimo niższej architektury" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "zainstaluj %s, mimo niższej architektury" + +#~ msgid "keep obsolete %s" +#~ msgstr "zachowaj starszą wersję %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "zainstaluj %s z wyłączonego repozytorium" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "przywróć %s do %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "zmiana architektury z %s na %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "zainstaluj %s (ze zmianą dostawcy)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "zamiana %s na %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "usunięcie %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Nie można otworzyć pliku blokady : %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Inny program wykonuje już tę czynność." + +#~ msgid "Hal Exception" +#~ msgstr "Wyjątek Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Ta wersja libzypp nie zawiera obsługi HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext niepołączony" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive: niezainicjowany" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume: niezainicjowany" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Nie można utworzyć połączenia dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: nie można utworzyć kontekstu libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: nie można ustanowić połączenia dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "Nie można zainicjować kontekstu HAL — demon hald nie jest uruchomiony?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "To nie jest napęd CD-ROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Nie można zainicjować atrybutów muteksu" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Nie można ustawić atrybutu rekurencyjności muteksu" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Nie można zainicjować rekurencyjnego muteksu" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Nie można pobrać blokady muteksu" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Nie można zwolnić blokady muteksu" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Nie udało się zaimportować klucza publicznego z pliku %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Usunięcie klucza publicznego nie powiodło się %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Nie można znaleźć dostępnego urządzenia pętli do zamontowania pliku " +#~ "obrazu z '%s'" + +#~ msgid "do not keep %s installed" +#~ msgstr "nie utrzymuj zainstalowanego %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "Nie można utworzyć klucza publicznego %s z zestawu %s do pliku %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "" +#~ "Inicjalizacja pobierania (Metalink curl) dla '%s' zakończona " +#~ "niepowodzeniem" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Błąd pobierania (metalink curl) dla '%s':\n" +#~ "Kod błędu: %s\n" +#~ "Komunikat błędu: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Przerwano pobieranie na %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Pobieranie przerwane przez użytkownika" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Napotkano błąd podczas ustawiania opcji pobierania (metalink curl) dla " +#~ "'%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Nie udało się pobrać %s z %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia i Czarnogóra" diff --git a/po/pt.po b/po/pt.po new file mode 100644 index 0000000..2e44166 --- /dev/null +++ b/po/pt.po @@ -0,0 +1,6223 @@ +# translation of zypp.pt.po to Portuguese +# PORTUGUESE message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999-2000, 2001 SuSE GmbH. +# +# Bruno David Rodrigues , 2000. +# João Teles , 1999-2000. +# Antonio Cardoso Martins , 2006, 2007, 2008. +# Carlos Gonçalves , 2007. +msgid "" +msgstr "" +"Project-Id-Version: zypp.pt\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2020-12-06 18:26+0000\n" +"Last-Translator: Luís Tiago Favas \n" +"Language-Team: Portuguese \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-Generator: Weblate 3.6.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "País desconhecido: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Sem Código" + +# name for AND +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Emirados Árabes Unidos" + +# name for AFG +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afeganistão" + +# name for ATG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antígua e Barbuda" + +# name for AIA +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguila" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albânia" + +# name for ARM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Arménia" + +# name for ANT +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antilhas Holandesas" + +# name for AGO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# name for ATA +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antárctida" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# name for ASM +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Americana" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Áustria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Austrália" + +# name for ABW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# name for ALA +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Ilhas Aland" + +# name for AZE +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaijão" + +# name for BIH +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bósnia e Herzegovina" + +# name for BRB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Bélgica" + +# name for BFA +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burquina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgária" + +# name for BHR +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Barém" + +# name for BDI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# name for BEN +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benim" + +# name for BMU +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudas" + +# name for BRN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolívia" + +# name for BRA +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasil" + +# name for BHS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Baamas" + +# name for BTN +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Butão" + +# name for BVT +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Ilha Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +# name for BLZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canadá" + +# name for CCK +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Ilhas Cocos" + +# name for COG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +# name for CAF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "República Central Africana" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Suíça" + +# name for CIV +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Costa do Marfim" + +# name for COK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Ilhas Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +# name for CMR +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camarões" + +# name for CHN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colômbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +# name for CUB +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +# name for CPV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cabo Verde" + +# name for CXR +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Ilha Christmas" + +# name for CYP +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Chipre" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "República Checa" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Alemanha" + +# name for DJI +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Jibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dinamarca" + +# name for DMA +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Domínica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "República Dominicana" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algéria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Equador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estónia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipto" + +# name for ESH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sara Ocidental" + +# name for ERI +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritreia" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Espanha" + +# name for ETH +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiópia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlândia" + +# name for FJI +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +# name for FLK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Ilhas Falkland (Malvinas)" + +# official_name for FSM +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Estados Federados da Micronésia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Ilhas Faroé" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "França" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "França Metropolitana" + +# name for GAB +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabão" + +# name for GBR +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Reino Unido" + +# name for GRD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Granada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +# name for GUF +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guiana Francesa" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# name for GHA +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +# name for GIB +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Gronelândia" + +# name for GMB +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gâmbia" + +# name for GIN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guiné" + +# name for GLP +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadalupe" + +# name for GNQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guiné Equatorial" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grécia" + +# name for SGS +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Ilhas Geórgia do Sul e Sandwich do Sul" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +# name for GUM +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# name for GNB +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guiné-Bissau" + +# name for GUY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guiana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +# name for HMD +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Ilhas Heard e McDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croácia" + +# name for HTI +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hungria" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonésia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanda" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Ilha de Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Índia" + +# name for IOT +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Território Britânico do Oceano Índico" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraque" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irão" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islândia" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Itália" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +# name for JAM +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordânia" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japão" + +# name for KEN +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Quénia" + +# name for KGZ +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Quirguizistão" + +# name for KHM +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Camboja" + +# name for KIR +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Quiribati" + +# name for COM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comoros" + +# name for KNA +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "São Cristóvão e Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Coreia do Norte" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Coreia do Sul" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +# name for CYM +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Ilhas Caimão" + +# name for KAZ +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Cazaquistão" + +# name for LAO +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "República Democrática Popular do Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Líbano" + +# name for LCA +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Santa Lúcia" + +# name for LIE +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Listenstaine" + +# name for LKA +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanca" + +# name for LBR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Libéria" + +# name for LSO +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesoto" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituânia" + +# name for LUX +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburgo" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvia" + +# name for LBR +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Líbia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marrocos" + +# name for MCO +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Mónaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldávia" + +# name for SCG +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +# name for SMR +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Coletividade de São Martinho" + +# name for MDG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagáscar" + +# name for MHL +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Ilhas Marshall" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedónia" + +# name for MLI +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# name for MMR +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mianmar" + +# name for MNG +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongólia" + +# name for MAC +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macau" + +# name for MNP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Marianas do Norte" + +# name for MTQ +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinica" + +# name for MRT +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritânia" + +# name for MSR +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Monserrate" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# name for MUS +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Maurícia" + +# name for MDV +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldivas" + +# name for MWI +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malavi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "México" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malásia" + +# name for MOZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Moçambique" + +# name for NAM +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namíbia" + +# name for NCL +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nova Caledónia" + +# name for NER +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Níger" + +# name for NFK +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Ilha Norfolk" + +# name for NGA +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigéria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicarágua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Holanda" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noruega" + +# name for NPL +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +# name for NRU +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# name for NIU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nova Zelândia" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omã" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panamá" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Perú" + +# name for PYF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinésia Francesa" + +# name for PNG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papuásia-Nova Guiné" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipinas" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Paquistão" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polónia" + +# name for SPM +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "São Pedro e Miquelon" + +# name for PCN +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +# official_name for PSE +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Território Palestiniano" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +# name for PLW +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +# name for REU +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunião" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Roménia" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Sérvia" + +# name for RUS +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Federação da Rússia" + +# name for RWA +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arábia Saudíta" + +# name for SLB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Ilhas Salomão" + +# name for SYC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seicheles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudão" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suécia" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapura" + +# name for SHN +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Santa Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Eslovénia" + +# name for SJM +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard e Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Eslováquia" + +# name for SLE +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Serra Leoa" + +# name for SMR +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "São Marino" + +# name for SEN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# name for SOM +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somália" + +# name for SUR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +# name for STP +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé e Príncipe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Síria" + +# name for SWZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Suazilândia" + +# name for TCA +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Ilhas Turcas e Caicos" + +# name for TCD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chade" + +# name for ATF +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Territórios Austrais Franceses" + +# name for TGO +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tailândia" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tajiquistão" + +# name for TKL +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +# name for TKM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turquemenistão" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunísia" + +# name for TON +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor Leste" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turquia" + +# name for TTO +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidade e Tobago" + +# name for TUV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzânia" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ucrânia" + +# name for UGA +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# name for UMI +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Ilhas Menores Distantes dos Estados Unidos" + +# name for USA +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Estados Unidos" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbequistão" + +# name for VAT +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Santa Sé (Estado da Cidade do Vaticano)" + +# name for VCT +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "São Vicente e Granadinas" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# official_name for VGB +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Ilhas Virgens Britânicas" + +# name for VIR +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Ilhas Virgens Americanas, E.U." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietname" + +# name for VUT +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# name for WLF +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis e Futuna" + +# name for WSM +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Iémen" + +# name for MYT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "África do Sul" + +# name for ZMB +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zâmbia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabué" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Providencia" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Pré requer" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Requer" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Conflitua" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Obsoletos" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recomenda" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Sugere" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Melhorar" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Suplementos" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Falha ao importar a chave pública %1%" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Falha ao apagar chave." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Ficheiro de assinatura %s não encontrado" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Idioma desconhecido: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhazião" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinese" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asiático (Outra)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadian" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanês" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Idiomas Algonquianos" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altai do Sul" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amárico" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Inglês Antigo (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Idiomas Apache" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Árabe" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaic" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonese" + +# name for ARM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Arménio" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucanian" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Artificial (Outro)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +# /usr/lib/YaST2/clients/logcontrol.ycp:64 +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamese" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturiano" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Idiomas Athapascan" + +# /usr/lib/YaST2/clients/sw_single.ycp:12 +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Idiomas Australianos" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avaric" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestão" + +# name for SWZ +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +# name for MMR +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbeijão" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +# /usr/lib/YaST2/clients/sw_single.ycp:12 +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Idiomas Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinese" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basco" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Báltico (Outro)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorusso" + +# name for BMU +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber (Outro)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +# name for HTI +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (Outro)" + +# name for BEN +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bósnio" + +# name for BRA +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretão" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonésia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginese" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Búlgaro" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmês" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Índio América Central (Outro)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalão" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucasiano (Outro)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Céltico (Outro)" + +# name for COM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +# name for CHN +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Checheno" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinês" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +# name for MLI +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Jargão Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Church Slavic" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Idiomas Chamic" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Coptic" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornish" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corsicano" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Criolo e Pidgins, Baseados em Inglês (Outros)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Criolo e Pidgins, Baseados em Francês (Outros)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Criolo e Pidgins, Baseados em Português (Outros)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Crimean Tatar" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Criolo e Pidgins (Outros)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kashubian" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitic (Outro)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Checo" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dinamarquês" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidian (Outro)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Baixo-Sórbio" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Holandês, Médio (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Holandês" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +# name for TON +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egípcio (Antigo)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inglês" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Inglês, Médio (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estónio" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faroês" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +# name for FJI +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijiano" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finlandês" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finno-Ugrian (Outro)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francês" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francês, Médio (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francês, Antigo (842-ca.1400)" + +# /usr/lib/YaST2/clients/adsl_custom.ycp:115 +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisão" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +# /usr/lib/YaST2/clients/adsl_custom.ycp:115 +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulian" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +# name for GAB +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germânico (Outros)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgiano" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Alemão" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertês" + +# name for MLI +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaélico" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandês" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galêgo" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Alemão, Médio Alto (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Alemão, Alto Antigo (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gótico" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grêgo, Antigo (até 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grêgo, Moderno (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +# name for HTI +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitiano" + +# /usr/lib/YaST2/clients/remotechooser.ycp:37 +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Havaiano" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebreu" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +# name for HTI +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +# name for HTI +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hittite" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +# name for HTI +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Sórbio Alto" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Húngaro" + +# /usr/lib/YaST2/clients/remotechooser.ycp:37 +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandês" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +# /usr/lib/YaST2/clients/logcontrol.ycp:69 +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indic (Outro)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonês" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-Europeu (Outro)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraniano (Outro)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Idiomas Iroquoians" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiano" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanês" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonês" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeu-Persa" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeu-Arábico" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +# name for KAZ +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (Outro)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Jemer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanês" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +# name for COG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreano" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Curdo" + +# name for KEN +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latim" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letão" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgan" + +# name for AGO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituano" + +# name for COG +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +# name for LUX +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburguês" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +# name for GHA +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenia e Tanzânia)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedónio" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurês" + +# name for MUS +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +# name for MHL +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshalês" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +# name for MDG +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +# name for MLI +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronésio (Outro)" + +# name for MUS +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +# name for MWI +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malaio" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +# name for MMR +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +# According to QIM Screenshot +# -ke- +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandês, Médio (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Idiomas Vários" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (Outro)" + +# name for MDG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagasy" + +# name for MDV +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltês" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +# name for MLI +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Idiomas Manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldávo" + +# name for MNG +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +# /usr/lib/YaST2/clients/sw_single.ycp:12 +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Idiomas Múltiplos" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Idiomas Mundas" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Grêgo" + +# name for MDV +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandês" + +# name for MUS +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Idiomas Mayan" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Índio Norte Americano" + +# name for NPL +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitan" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, Sul" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, Norte" + +# name for TON +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Alemão Baixo" + +# name for NPL +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalês" + +# name for NPL +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanian (Outro)" + +# name for NIU +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Nynorsk Norueguês" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Bokmal Norueguês" + +# name for TON +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norse, Antigo" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norueguês" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho do Norte" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Idiomas Nubian" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari Clássico" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (posto 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turco, Otomano (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Idiomas Otomian" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuan (Outro)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +# name for MLI +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +# name for PLW +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persa, Antigo (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persa" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipino (Outro)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Phoenician" + +# name for MLI +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polaco" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Português" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Idiomas Prakrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provençal, Antigo (até 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +# name for KAZ +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romance (Outro)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Raeto-Romance" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romeno" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romeno" + +# name for REU +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russo" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +# name for WSM +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Índio da América so Sul (Outro)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Idiomas Salishan" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Aramaico Samaritano" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanscrito" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Sérvio" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliano" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Escocês" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croata" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semítico (Outro)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandês, Antigo (até 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Linguagem Gestual" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +# name for WSM +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +# name for AGO +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Idiomas Siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetano (Outro)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Eslavo" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Eslovaco" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Esolveno" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sami Meridional" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Sami Setentrional" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Idiomas Sami (Outros)" + +# name for WSM +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +# name for WSM +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoano" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +# workflow: "Software-Auswahl" +# -ke- +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +# name for SOM +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalês" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, Meridional" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Espanhol" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardiniano" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-Saharan (Outro)" + +# name for HTI +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanese" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumério" + +# name for SWZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Sueco" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siríaco" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Taitiano" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tailandêses (Outros)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tailandês" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetano" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +# name for NGA +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinha" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +# name for SLB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Olhas Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +# /usr/lib/YaST2/clients/adsl_custom.ycp:115 +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +# name for TON +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turcomano" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Idiomas Tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turco" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaico (Outro)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuviniano" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +# name for HTI +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritic" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ucraniano" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +# /usr/lib/YaST2/clients/logcontrol.ycp:69 +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Indeterminado" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbek" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamita" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Idiomas Wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Gaulês" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Idiomas Sórbio" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yiddish" + +# name for ABW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Idiomas Yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +# name for BTN +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +# name for TUV +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "As seguintes acções serão realizadas:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "desconhecido" + +#: zypp/VendorSupportOptions.cc:17 +#, fuzzy +msgid "unsupported" +msgstr " - não suportado" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "O disco não existe." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, fuzzy, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"A gestão do sistema está bloqueada pela aplicação com pid %d. Por favor " +"encerre esta aplicação antes de tentar novamente." + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Comando '%s' desconhecido" + +#: zypp/base/StrMatcher.cc:153 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Digest %s desconhecido para o ficheiro %s." + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Expressão regular inválida '%s': regcomp devolveu %d" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Expressão regular inválida '%s': regcomp devolveu %d" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autenticação requerida para '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "A limpar a cache dos metadados raw de '%s'." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, fuzzy, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Erro ao interpretar a metadata de '%s':" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Não é possível criar %s: %m\n" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +#, fuzzy +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Não foi encontrada uma metadata válida no(s) URL(s) especificado(s)" +msgstr[1] "Não foi encontrada uma metadata válida no(s) URL(s) especificado(s)" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Falha na interpretação de %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "A construir a cache do repositório '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +#, fuzzy +msgid "Unhandled repository type" +msgstr "Repositório activado" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "A Adicionar repositório '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Ficheiro de exportação inválido." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Não é possível abrir ficheiro para escrita." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Comando '%s' desconhecido" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Falha na interpretação de %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "A remover o repositório '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Não é possível ejectar o suporte '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "O nome da MV não pode iniciar com um dígito." + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr "O nome da MV não pode iniciar com um dígito." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +# internal key used: Ok +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Continuar?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, fuzzy, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Está em falta um ficheiro necessário: " + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"O pacote %s falhou a verificação de integridade. Pretende tentar novamente?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"O pacote %s falhou a verificação de integridade. Pretende tentar novamente?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "falhou a verificação applydeltarpm." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "falhou o applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Não é possível fornecer o ficheiro '%s' a partir do repositório '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Nenhum url no repositório." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Não é possível criar o sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "Ignorar de uma forma geral algumas dependências" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "pedidos em conflito" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "Não foi possível instalar %s devido a problemas de dependências" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "fornecedores apagados: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"fornecedores não instaláveis: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "fornecedores não instaláveis: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "A instalação foi interrompida conforme indicado." + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "Executar" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "Falhou a Execução DBI: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "falha no RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Falha ao importar a chave pública %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Falha ao remover a chave pública %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Ficheiros de configuração modificados para %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"o rpm %s foi guardado como %s, mas foi impossível determinar a diferença" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"o rpm %s foi guardado com %s.\n" +"Tem as primeiras 25 linhas diferentes:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "o rpm %s foi criado como %s, mas foi impossível determinar a diferença" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"o rpm %s foi criado com %s.\n" +"Tem as primeiras 25 linhas diferentes:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "Resultado adicional do rpm:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "cópia de segurança %s criada" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tipo '%s' dúbio para soma de verificação de %u byte '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Não foi possível abrir o pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Não é possível abrir o pipe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Cadeia de interrogação URL de LDAP inválida" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Parâmetro '%s' de interrogação URL de LDAP inválido" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Não é possível clonar o objecto Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Referência para objecto Url vazia é inválida" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Não é possível interpretar os componentes Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Histórico:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "O esquema url não permite um %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "componente %s inválido '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Componente %s inválido" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Interpretação da cadeia de interrogação não é suportado para este URL." + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "O esquema de url é um componente requerido" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Esquema de Url inválido '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "O esquema do Url não permite um nome de utilizador" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "O esquema do Url não permite uma palavra passe" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "O esquema de Url requer um componente de computador (host)" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "O esquema do Url não permite um componente de computador (host)" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Componente de computador inválido '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "O esquema de Url não permite um porto" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Componente de porto inválido '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "O esquema de Url requer um nome de caminho" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Caminho relativo não é permitido se a autoridade existe" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "A cadeia codificada contém um byte NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Parâmetro do caracter do separador de dívisão da lista inválido" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Parâmetro do caracter do separador de divisão do mapa inválido" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Parâmetro do caracter do separador de junção da lista inválido" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Comando terminou com estado %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Comando foi morto pelo sinal %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Comando terminou com erro desconhecido." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Não é possível fazer chroot para '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Não foi possível fazer chdir a '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Não foi possível fazer chdir a '%s' dentro de chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Não é possível executar '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Não é possível bifurcar (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Falha ao montar %s em %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Falha ao desmontar %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nome de ficheiro incorrecto: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Ficheiro '%s' não foi encontrado no suporte '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Não é possível escrever o ficheiro '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Mau ponto de ligação com o suporte" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Inicialização da descarga (curl) falhou para '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI mal formado" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nome de computador vazio no URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Sistema de ficheiros vazio no URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destino vazio no URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Esquema de URI não suportado em '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Erro de descarga (curl) para '%s':\n" +"Código do erro: %s\n" +"Mensagem do erro: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Ocorreu um erro durante a definição das opções de descarga (curl) para '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Não é possível ejectar nenhum suporte" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Não é possível ejectar o suporte '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Foi negada a autorização para aceder a '%s'." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, fuzzy, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Tempo limite excedido quando acedia a '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" problema no certificado SSL, verifique se o certificado de CA é OK para " +"'%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Método '%s' de autenticação HTTP não suportado" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Sim" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Não" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Nota:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Aviso:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Erro:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "concluído" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "atenção" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "erro" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Aviso: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "A obter:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "a iniciar" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "não encontrado" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Não existe ajuda disponível para esta mensagem." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "Não existe ajuda disponível para esta opção" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "mostrar todas as opções" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "sim" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "não" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s fornece %s, mas tem outra arquitectura." + +#~ msgid "problem with installed package %s" +#~ msgstr "problema com o pacote %s instalado" + +#~ msgid "nothing provides requested %s" +#~ msgstr "nada fornece %s solicitado" + +#~ msgid "%s is not installable" +#~ msgstr "%s não é instalável" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "nada fornece %s necessário por %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "não é possível instalar tanto %s como %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s conflitua com %s fornecido por %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s torna obsoleto %s fornecido por %s" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s torna obsoleto %s fornecido por %s" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "Resolúvel %s conflitua com %s fornecido por ele próprio" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s requer %s, mas este requisito não pode ser fornecido" + +#~ msgid "do not install %s" +#~ msgstr "não instalar %s" + +#~ msgid "keep %s" +#~ msgstr "manter %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "não perguntar para instalar um resolúvel que fornece %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "não perguntar para apagar todos os resolúveis que fornecem %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "não instalar a versão mais recente de %s" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s fornece %s, mas tem outra arquitectura." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "instalar %s apesar de alterar a arquitectura" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s obsoleto %s" + +#, fuzzy +#~ msgid "install %s from excluded repository" +#~ msgstr "Repositório activado" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "desactualização de %s para %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "alteração de arquitectura de %s para %s" + +#, fuzzy +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "instalar %s (com alteração do vendedor)\n" +#~ " %s\n" +#~ "-->\n" +#~ " %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "substituição de %s por %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "desinstalação de %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Não é possível abrir ficheiro de bloqueio: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Esta acção já está a ser executada por outro programa." + +#~ msgid "Hal Exception" +#~ msgstr "Excepção Hal" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext não ligado" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive não inicializado" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume não inicializado" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Não foi possível criar a ligação dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Não é possível criar o contexto libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Não é possível definir a ligação dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "Não foi possível inicializar o contexto HAL -- o hald não está em " +#~ "execução?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Não é uma unidade de CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Não é possível inicializar os atributos da mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Não é possível definir o atributo da mutex recursiva" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Não é possível inicializar a mutex recursiva" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Não foi possível adquirir o bloqueio da mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Não foi possível libertar o bloqueio da mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Falha ao importar a chave pública do ficheiro %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Falha ao remover a chave pública %s: %s" + +#, fuzzy +#~ msgid "generally ignore of some dependecies" +#~ msgstr "Ignorar de uma forma geral algumas dependências" + +#~ msgid "do not forbid installation of %s" +#~ msgstr "não proibir a instalação de %s" + +#~ msgid "do not keep %s installed" +#~ msgstr "não manter %s instalado" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "توقف التحميل في %d%%" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Não é possível criar a chave pública %s a partir do chaveiro %s para o " +#~ "ficheiro %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "Tentativa de importar uma chave %s não existente no chaveiro %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Não é possível fazer chdir para '/' dentro do chroot (%s)." + +#, fuzzy +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Inicialização da descarga (curl) falhou para '%s'" + +#, fuzzy +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Erro de descarga (curl) para '%s':\n" +#~ "Código do erro: %s\n" +#~ "Mensagem do erro: %s\n" + +#, fuzzy +#~ msgid "Download interrupted by user" +#~ msgstr "A descarregar grupos" + +#, fuzzy +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Ocorreu um erro durante a definição das opções de descarga (curl) para " +#~ "'%s':" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Falha ao montar %s em %s" + +# name for SCG +#~ msgid "Serbia and Montenegro" +#~ msgstr "Sérvia e Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Opção de lista desconhecida" + +#, fuzzy +#~| msgid "Ignore some dependencies of %s" +#~ msgid "ignore some dependencies of %s" +#~ msgstr "Ignorar algumas dependências de %s" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "O ficheiro %s não tem uma soma de verificação.\n" +#~ "Utilizar este ficheiro de qualquer das formas?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "O ficheiro %s falhou a verificação de integridade com a seguinte chave:\n" +#~ "%s|%s|%s\n" +#~ "Utilizar o ficheiro de qualquer das formas?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "O ficheiro %s tem um checksum inválido.\n" +#~ "Esperava-se %s, mas foi encontrado %s\n" +#~ "Utilizar o ficheiro de qualquer das formas?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "O ficheiro %s tem um checksum %s desconhecido.\n" +#~ "Utilizar o ficheiro de qualquer das formas?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "O ficheiro %s não está assinado.\n" +#~ "Utilizá-lo de qualquer das formas?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "O ficheiro %s está assinado com uma chave desconhecida:\n" +#~ "%s|%s|%s\n" +#~ "Utilizar o ficheiro de qualquer das formas?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Foi encontrada uma chave que não é de confiança:\n" +#~ "%s|%s|%s\n" +#~ "Confiar na chave?" + +#~ msgid "%s remove failed" +#~ msgstr "Falha ao remover %s" + +#~ msgid "Invalid user name or password." +#~ msgstr "Nome de utilizador ou palavra passe inválidos." + +#~ msgid "rpm output:" +#~ msgstr "resultado do rpm:" + +#~ msgid "%s install failed" +#~ msgstr "Falhou a instalação de %s" + +#~ msgid "%s installed ok" +#~ msgstr "%s instalado com sucesso" + +#~ msgid "%s remove ok" +#~ msgstr "%s removido com sucesso" diff --git a/po/pt_BR.po b/po/pt_BR.po new file mode 100644 index 0000000..e345115 --- /dev/null +++ b/po/pt_BR.po @@ -0,0 +1,6123 @@ +# translation of zypp.po to Brazilian Portuguese +# Portugese (Brasilian) message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999-2000, 2001 SuSE GmbH. +# +# Karl Eichwalder , 1999. +# Ralf Lanz , 1999. +# Isis Binder , 2008, 2010. +# Luiz Fernando Ranghetti , 2008. +# Luiz Fernando Ranghetti , 2008, 2009, 2012, 2013, 2014, 2015, 2016. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-05-02 00:43+0000\n" +"Last-Translator: Samanta Magalhaes \n" +"Language-Team: Portuguese (Brazil) \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: Weblate 4.9.1\n" +"X-Poedit-Language: Portuguese\n" +"X-Poedit-Country: BRAZIL\n" +"X-Poedit-SourceCharset: utf-8\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "País desconhecido: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Sem código" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Emirados Árabes Unidos" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afeganistão" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antígua e Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguila" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albânia" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armênia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antilhas Holandesas" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antártida" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Americana" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Áustria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Austrália" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Ilhas Åland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaijão" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bósnia e Herzegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Bélgica" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgária" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Barein" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudas" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolívia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Butão" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Ilha Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botsuana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canadá" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Ilhas Cocos (Keeling)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "República Centro-Africana" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Suíça" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Costa do Marfim" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Ilhas Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camarões" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colômbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cabo Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Ilha Christmas" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Chipre" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "República Checa" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Alemanha" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dinamarca" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "República Dominicana" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Argélia" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Equador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estônia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egito" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Saara Ocidental" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritreia" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Espanha" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiópia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlândia" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Ilhas Malvinas (Falkland)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Estados Federados da Micronésia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Ilhas Feroe" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "França" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "França metropolitana" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabão" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Reino Unido" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Granada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Geórgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guiana Francesa" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenlândia" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gâmbia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guiné" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadalupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guiné Equatorial" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grécia" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Ilhas Geórgia do Sul e Sandwich do Sul" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guiné-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guiana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Ilha Heard e Ilhas McDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croácia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hungria" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonésia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanda" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Ilha de Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Índia" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Território Britânico do Oceano Índico" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraque" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irã" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islândia" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Itália" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordânia" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japão" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Quênia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Quirguistão" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Camboja" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comores" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "São Cristóvão e Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Coreia do Norte" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Coreia do Sul" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Ilhas Cayman" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Cazaquistão" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Líbano" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Santa Lúcia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Libéria" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesoto" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituânia" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburgo" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letônia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Líbia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marrocos" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Mônaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldávia" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "São Martinho" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Ilhas Marshall" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedônia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mianmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongólia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macau" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Ilhas Marianas do Norte" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinica" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritânia" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Ilhas Maurício" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldivas" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "México" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malásia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Moçambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namíbia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nova Caledônia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Níger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Ilha Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigéria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicarágua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Holanda" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Noruega" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauruano" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nova Zelândia" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omã" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panamá" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinésia Francesa" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nova Guiné" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipinas" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Paquistão" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polônia" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre e Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Ilhas Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Porto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Território Palestino" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguai" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Catar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Ilha Reunião" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romênia" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Sérvia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Rússia" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arábia Saudita" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Ilhas Salomão" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seicheles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudão" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suécia" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Cingapura" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Santa Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Eslovênia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Ilhas Svalbard e Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Eslováquia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Serra Leoa" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somália" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé e Príncipe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Síria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Suazilândia" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Ilhas Turks e Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chade" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Terras Austrais e Antárticas Francesas" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tailândia" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadjiquistão" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turcomenistão" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunísia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timor-Leste" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turquia" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad e Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvaluano" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzânia" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ucrânia" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Ilhas Menores Distantes dos Estados Unidos" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Estados Unidos" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguai" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbequistão" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Santa Sé (Cidade do Vaticano)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "São Vicente e Granadinas" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Ilhas Virgens Britânicas" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Ilhas Virgens, EUA." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnã" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis e Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Iêmen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "África do Sul" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zâmbia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbábue" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Fornece" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Pré-requisitos" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Requer" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Está em conflito" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Torna obsoleto" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recomenda" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Sugere" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Aprimora" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Complementa" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Tentativa de importar a chave não existente %s para o chaveiro %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Falha ao importar chave." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Falha ao remover chave." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "O arquivo de assinatura %s não foi encontrado" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Idioma desconhecido: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abcásio" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achém" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Circassiano" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-asiático (outros)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Africâner" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Aino" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Acadiano" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanês" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleúte" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Línguas algonquinas" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altaico Meridional" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amárico" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Inglês antigo (aprox. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Línguas apaches" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Árabe" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaico" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonês" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armênio" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucano" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Artificial (outros)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamês" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturiano" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Línguas atapascas" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Línguas australianas" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avárico" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avéstico" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaidjano" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Línguas bamileques" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Balúchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinês" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basco" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Báltico (outros)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Bejanês" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorusso" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berbere (outros)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislamá" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Banto (outros)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bósnio" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Brajavali" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretão" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Bataque (Indonésia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriátio" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginês" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Búlgaro" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birmanês" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Cadoano" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Indígena centro-americano (outros)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Caribe" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalão" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucasiano (outros)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celta (outros)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Checheno" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinês" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Jargão chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Eslavo eclesiástico" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Línguas tchadianas" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Copta" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Córnico" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corso" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Crioulos e pidgins de base inglesa (outros)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Crioulos e pidgins de base francesa (outros)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Crioulos e pidgins de base portuguesa (outros)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tártaro (Crimeia)" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Crioulos e pidgins (outros)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Cassúbio" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cuchita (outros)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Checo" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dacota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dinamarquês" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Daiaque" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Atapasca)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinca" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidiano (outros)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Baixo-sorbiano" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Holandês medieval (aprox. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Holandês" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Diula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efique" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egípcio (Antigo)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamita" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inglês" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Inglês medieval (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estoniano" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Jeje" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Feroês" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijiano" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finlandês" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fino-ugriano (outros)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francês" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francês medieval (aprox. 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francês antigo (aprox. 842-1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frísio" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fula" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulano" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Cua" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaia" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germânico (outros)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgiano" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Alemão" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Ge'ez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertês" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaélico" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandês" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galego" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Alto-alemão medieval (aprox. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Alto-alemão antigo (aprox. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gonde" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gótico" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grego antigo (até 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grego moderno (após 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Guzerate" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitiano" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Haúça" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Havaiano" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebraico" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Hereró" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hitita" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Alto-Sorbiano" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Húngaro" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Ibo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandês" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Yi (Sechuan)" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlíngua" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Ilocano" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" +"Interlíngua (International Auxiliary Language Association, Associação de " +"Línguas Internacionais Auxiliares)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Índico (outros)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonésio" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-europeu (outros)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraniano (outros)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Línguas iroquesas" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiano" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanês" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonês" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judeu-persa" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judeu-arábico" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Groenlandês" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Camba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Canarês" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Caxemira" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Canúri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Cazaque" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Cabardíaco" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (outros)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Cotanês" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Quirguiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Quimbundo" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Concani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Congo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreano" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Cosreano" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Curdo" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laosiano" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latim" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letão" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgano" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituano" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburguês" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Nganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lundês" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Quênia e Tanzânia)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedônio" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurês" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallino" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malaiala" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandinga" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronésio (outros)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marati" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Massai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malaio" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandês medieval (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Línguas diversas" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-khmer (outros)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgaxe" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltês" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Línguas manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldávio" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Vários idiomas" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Línguas mundas" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandês" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Línguas maias" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Indígena norte-americano" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitano" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele do sul" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele do norte" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Baixo-alemão" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalês" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Bhasa (Nepal)" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Nigero-cordofânio (outros)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueano" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Novo norueguês" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Dano-norueguês" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Nórdico antigo" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norueguês" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho (setentrional)" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Línguas núbias" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari clássico" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitano (após 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojíbua" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriá" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osseto" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turco otomano (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Línguas otomianas" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papua (outros)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinano" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pálavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauano" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persa antigo (aprox. 600-400 A.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persa" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipino (outros)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenício" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Páli" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polonês" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pompeano" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Português" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Línguas prácritas" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provençal antigo (até 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Afegão" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quíchua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajastanês" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapa Nui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotonganês" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Latim (outros)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Romanche" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romeno" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Russo" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Iacuto" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Indígena sul-americano (outros)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Línguas salichanas" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Aramaico samaritano" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sânscrito" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Sérvio" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliano" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Escocês" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croata" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semita (outros)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandês antigo (até 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Linguagens de sinais" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Línguas sioux" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-tibetano (outros)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Eslavo (outros)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Eslovaco" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Esloveno" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Lapão Meridional" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Lapão setentrional" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Línguas lapônias (outras)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lapão (Lule)" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Lapão (Inari)" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoano" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Lapão (Skolt)" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Xichonês" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninquê" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdian" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho (Meridional)" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Espanhol" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardo" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-saariano (outros)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Suázi" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanês" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumério" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Suaíli" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Sueco" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siríaco" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Taitiano" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (outros)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tâmil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tártaro" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Temne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tétum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadjique" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalo" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tailandês" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetano" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigré" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrínio" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tuaregue" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonganês (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonganês (Ilhas Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Setswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turcomeno" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Línguas tupis" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turco" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaico (outros)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuviniano" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugarítico" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uigur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ucraniano" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundo" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Indeterminado" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbeque" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamita" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuque" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Vótico" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Línguas wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Galês" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Línguas sorbianas" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Valão" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Iao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapês" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Iídiche" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Iorubá" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Línguas yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapoteca" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zunhi" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "As seguintes ações serão realizadas:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "não expira" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "expirada: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "expira em: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(não expira)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(EXPIRADO)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(expira dentro de 24h)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(expira em %d dia)" +msgstr[1] "(expira em %d dias)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "desconhecido" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "não suportado" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Nível 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Nível 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Nível 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Contrato adicional do consumidor necessário" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Descontinuado e substituído por um pacote diferente" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "inválido" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "O nível de suporte não foi especificado" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "O fornecedor não oferece suporte." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Determinação do problema, que significa suporte técnico feito para fornecer " +"informações de compatibilidade, assistência na instalação, suporte ao uso, " +"manutenção contínua e solução básica de problemas. O Suporte de Nível 1 não " +"corrige defeitos do produto." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Isolamento do problema, que significa suporte técnico feito para duplicar os " +"problemas do cliente, isolar a área do problema e fornecer solução para " +"problemas não resolvidos pelo Suporte de Nível 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Resolução de problema, que significa suporte técnico feito para resolver " +"problemas complexos através de engenharia na resolução de defeitos do " +"produto que foram identificados pelo Suporte de Nível 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" +"Um contrato adicional com o consumidor é necessário para receber suporte." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"O pacote foi descontinuado e substituído por um novo pacote com um nome " +"diferente." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Opção de suporte desconhecida. A descrição não está disponível" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"O gerenciamento do sistema está bloqueado pelo aplicativo com o pid %d " +"(%s).\n" +"Feche esse aplicativo antes de tentar novamente." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Modo de correspondência desconhecido '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Modo de correspondência desconhecido '%s' para o padrão '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Expressão regular inválida '%s': o regcomp retornou %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Expressão regular inválida '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autenticação necessária para '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Será feita nova tentativa..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Desistirá após %1% tentativas." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visite o SUSE Customer Center para verificar se seu registro é válido e não " +"expirou." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Visite o Novell Customer Center para verificar se seu registro é válido e " +"não expirou." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Criar ponto para anexar: Não foi possível localizar um diretório gravável " +"para criar um ponto de anexar" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Instale o pacote ''lsof'' primeiro." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Não foi possível criar o diretório do cache de metadados." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Erro ao tentar ler de '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Não foi possível criar %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Metadados válidos não encontrados na URL especificada" +msgstr[1] "Metadados válidos não encontrados nas URLs especificadas" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Falha ao armazenar .repo (%d) em cache." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Construindo o cache do repositório '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Não foi possível criar o cache em %s - sem permissão de gravação." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Tipo de repositório não identificado" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Adicionando o repositório '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nome de arquivo de repositório inválido em '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Não foi possível abrir o arquivo '%s' para gravação." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Erro desconhecido ao ler de '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" +"Não foi possível ler o diretório de repositório '%1%': Permissão negada" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Falha ao ler o diretório '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Não foi possível ler o arquivo de repositório '%1%': Permissão negada" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Removendo o repositório '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Não foi possível descobrir onde o repositório está armazenado." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Não foi possível remover '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Não foi possível descobrir onde o serviço está armazenado." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Serviço '%1%' desconhecido: removendo o repositório de serviço órfão '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "O apelido do repositório não pode começar com ponto." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "O apelido do serviço não pode começar com ponto." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Nenhum digest para o arquivo %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Digest %s desconhecido para o arquivo %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Falha na verificação do digest para o arquivo '%s'" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "O arquivo '%s' não está assinado. Continuar?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "O arquivo '%s' do repositório '%s' não está assinado. Continuar?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" +"Você deseja rejeitar a chave, confiar nela temporariamente ou confiar nela " +"sempre?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Nome da Chave: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +"%1% chave de assinatura de novo pacote recebida do repositório \"%2%\":" +msgstr[1] "" +"%1% chaves de assinatura de novo pacote recebidas do repositório \"%2%\":" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Falha na verificação de assinatura para o arquivo '%1%'." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"Falha na verificação de assinatura para o arquivo '%1%' do repositório '%2%'." + +# internal key used: Ok +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Continuar?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"O arquivo '%s' está assinado com uma chave desconhecida '%s'. Continuar?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"O arquivo '%s' do repositório '%s' está assinado com uma chave desconhecida " +"'%s'. Continuar?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Repositório 1% não define URLs 'gpgkey' adicionais." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Procurando por ID da chave gpg %1% no repositório %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Procurando por ID da chave gpg 1% no cache %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Atributo necessário '%s' faltando." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Um ou ambos os atributos '%s' ou '%s' são necessários." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Falha na verificação da assinatura" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"O pacote %s parece ter sido corrompido durante a transferência. Deseja " +"tentar obtê-lo novamente?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Falha ao fornecer o pacote %s. Deseja tentar obtê-lo novamente?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Falha na verificação de applydeltarpm." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "Falha no applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "O plug-in de serviço não suporta alterar um atributo." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Não foi possível fornecer o arquivo '%s' a partir do repositório '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Nenhuma URL no repositório." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "Mídia esperada %1%/%2% identificada pelo arquivo '%3%' com o conteúdo:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"O arquivo %1%\n" +" do pacote\n" +" %2%\n" +" conflita com o arquivo do pacote\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"O arquivo %1%\n" +" do pacote\n" +" %2%\n" +" conflita com o arquivo da instalação de\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"O arquivo %1%\n" +" da instalação de\n" +" %2%\n" +" conflita com o arquivo do pacote\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"O arquivo %1%\n" +" da instalação de\n" +" %2%\n" +" conflita com o arquivo da instalação de\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"O arquivo %1%\n" +" do pacote\n" +" %2%\n" +" conflita com o arquivo\n" +" %3%\n" +" do pacote\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"O arquivo %1%\n" +" do pacote\n" +" %2%\n" +" conflita com o arquivo\n" +" %3%\n" +" da instalação de\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"O arquivo %1%\n" +" da instalação de\n" +" %2%\n" +" conflita com o arquivo\n" +" %3%\n" +" do pacote\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"O arquivo %1%\n" +" da instalação de\n" +" %2%\n" +" conflita com o arquivo\n" +" %3%\n" +" da instalação de\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Não foi possível criar o sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "quebrar %s ao ignorar algumas das dependências" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "geralmente ignorar algumas dependências" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"O %1% instalado não pertence a um repositório distupgrade e deve ser " +"substituído" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "o %1% a ser instalado não pertence a um repositório distupgrade" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "o %1% instalado tem uma arquitetura inferior" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "o %1% a ser instalado tem uma arquitetura inferior" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problema com o instalado %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "solicitações conflitantes" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "algum problema de dependência" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "nada fornece o '%1%' solicitado" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Você habilitou todos os repositórios necessários?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "o pacote solicitado %1% não existe" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "solicitação não suportada" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' é fornecido pelo sistema e não pode ser apagado" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% não é instalável" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "nada fornece '%1%' necessário para o %2% instalado" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "nada fornece '%1%' necessário para o %2% instalado" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "não pode instalar %1% e %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"o %1% instalado está em conflito com '%2%' fornecido pelo %3% instalado" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"o %1% instalado está em conflito com o '%2%' fornecido pelo a ser instalado " +"%3%" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"o %1% a ser instalado está em conflito com '%2%' fornecido pelo %3% instalado" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"o %1% a ser instalado está em conflito com '%2%' fornecido pelo a ser " +"instalado %3%" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "o %1% instalado torna obsoleto '%2%' fornecido pelo %3% instalado" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"o %1% instalado torna obsoleto '%2%' fornecido pelo a ser instalado %3%" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"o %1% a ser instalado torna obsoleto '%2%' fornecido pelo %3% instalado" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"o %1% a ser instalado torna obsoleto '%2%' fornecido pelo a ser instalado %3%" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "o %1% instalado está em conflito com o '%2%' fornecido por ele mesmo" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"o %1% a ser instalado está em conflito com o '%2%' fornecido por ele mesmo" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"o %1% instalado requer '%2%', mas este requisito não pode ser fornecido" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"o %1% a ser instalado requer '%2%', mas este requisito não pode ser fornecido" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "fornecedores removidos: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"fornecedores não instaláveis: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "fornecedores não instaláveis: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% ainda não está completamente integrado em %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Normalmente você deseja manter o PTF e escolher não instalar as correções de " +"manutenção." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"A remoção do %1% instalado neste contexto também removerá (não substituirá) " +"os pacotes PTF incluídos." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"O PTF deve ser removido chamando '%1%'. Isso atualizará os pacotes PTF " +"incluídos em vez de removê-los." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Normalmente, convém manter o PTF ou cancelar a ação." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "O %1% instalado bloqueia a ação desejada." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Normalmente, você deseja manter o PTF e optar por cancelar a ação." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "remova o bloqueio para permitir a remoção de %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "não instale %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "manter %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "remova o bloqueio para permitir a instalação de %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Esta solicitação travará o seu sistema!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "igorar o aviso de um sistema travado" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "não peça para instalar um solucionável fornecendo %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "não peça para apagar todos os solucionáveis fornecendo %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "não instale a versão mais recente de %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "mantenha %1% apesar da arquitetura inferior" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "instale %1% apesar da arquitetura inferior" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "mantenha obsoleto %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "instale %1% do repositório excluído" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "instale %1% apesar de ter sido recolhido" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "permitir instalar o PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "instale %1%, embora esteja na lista negra" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "rebaixamento de %1% para %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "mudança de arquitetura de %1% a %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"instalar %1% (com mudança de fornecedor)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"instale% 1% do fornecedor% 2%\n" +" substituindo% 3% do fornecedor% 4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "substituição de %1% por %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "desinstalação de %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Executando scripts de pós-transação" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Executando script %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Saída do script %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "A instalação foi cancelada conforme instruções." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " executado" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " falha na execução" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s já executado como %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " execução ignorada durante o cancelamento" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Erro ao enviar a notificação de mensagem de atualização." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nova mensagem de atualização" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Sinal recebido :\"%1% (%2%)\", para garantir a consistência do sistema não é " +"possível cancelar uma transação RPM em execução." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "A execução da transação falhou devido aos seguintes problemas:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Falha no RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Falha ao importar chave pública %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Falha ao remover chave pública %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "O cabeçalho do pacote não está assinado!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "A carga útil do pacote não está assinada!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Arquivos de configuração alterados para %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "o RPM salvou %s como %s, mas não foi possível determinar a diferença" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"o rpm salvou %s como %s.\n" +"Aqui estão as 25 primeiras linhas de diferença:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "o rpm criou %s como %s, mas não foi possível determinar a diferença" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm criou %s como %s.\n" +"Aqui estão as 25 primeiras linhas de diferença:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Saída adicional do rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "backup %s criado" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "A assinatura está OK" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Tipo de assinatura desconhecido" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Assinatura não verificada" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "A assinatura está OK, mas a chave não é confiável" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Chave pública das assinaturas não disponível" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "O arquivo não existe ou a assinatura não pode ser verificada" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "O arquivo não está assinado" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tipo '%s' duvidoso da soma de verificação de bytes %u ('%s')" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Não foi possível abrir o pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Não foi possível abrir o pipe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "String de consulta de URL de LDAP inválida" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Parâmetro de consulta '%s' de URL de LDAP inválido" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Não foi possível clonar o objeto URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Referência a objeto URL vazio inválida" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Não foi possível analisar os componentes da URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Histórico:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "O esquema de URL não permite %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Componente '%s' inválido %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Componente inválido %s" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "A análise de strings de consulta não é suportada para este URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "O esquema de URL é um componente obrigatório" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Esquema de URL '%s' inválido" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "O esquema de URL não permite nome de usuário" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "O esquema de URL não permite senha" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "O esquema de URL requer um componente de host" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "O esquema de URL não permite componente de host" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Componente de host inválido '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "O esquema de URL não permite porta" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Componente de porta inválido '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "O esquema de URL requer nome de caminho" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Caminho relativo não permitido se existir autoridade" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "A string codificada contém um byte NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Caractere separador de divisão de matriz de parâmetros inválido" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Caractere separador de divisão de mapa de parâmetros inválido" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Caractere separador de integração de matriz de parâmetros inválido" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "O comando encerrou com status %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Comando eliminado pelo sinal %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "O comando encerrou com erro desconhecido." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Argumentos de geração inválidos fornecidos." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Incapaz de criar o tubo de controle." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Não foi possível executar o chroot em '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Não foi possível executar chdir para '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Não foi possível executar chdir para '%s' dentro do chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Não foi possível executar '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Não foi possível dividir (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Impossível executar '%s', chdir falhou (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Impossível executar '%s', chroot falhou (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Impossível executar '%s', exec falhou (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Impossível executar '%s', erro inesperado." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Falha ao montar %s em %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Falha ao desmontar %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nome de arquivo inválido: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Mídia não aberta ao tentar realizar a ação '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Arquivo '%s' não encontrado na mídia '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Não é possível gravar o arquivo '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Mídia não conectada" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Ponto de conexão de mídia inválido" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Falha na inicialização do download (curl) para '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Exceção do sistema '%s' na mídia '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "O caminho '%s' na mídia '%s' não é um arquivo." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "O caminho '%s' na mídia '%s' não é um diretório." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI mal formado" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nome de host vazio no URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Sistema de arquivos vazio no URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destino vazio no URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Esquema de URI não suportado em '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operação não suportada pela mídia" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Erro de download (curl) para '%s':\n" +"Código de erro: %s\n" +"Mensagem de erro: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Erro ao configurar as opções de download (curl) para '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "A mídia fonte '%s' não contém a mídia desejada" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "A mídia '%s' está sendo usada por outra instância" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Não foi possível ejetar qualquer mídia" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Não foi possível ejetar a mídia '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Permissão para acessar '%s' negada." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Tempo de espera excedido ao acessar '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"Os dados transferidos excederam o tamanho esperado do tamanho do arquivo " +"'%s' of '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "O local '%s' está temporariamente inacessível." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Problema no certificado SSL. Verifique se o certificado CA está correto " +"para '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Não há recursos livres disponíveis para anexar a mídia." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Método de autenticação HTTP '%s' não suportado" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Erro de download (curl) para '%s':\n" +"Código do erro: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Erro de download (curl) para '%s':\n" +"Não foi possível obter a resposta HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Sim" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Não" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Nota:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Aviso:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Erro:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "concluído" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "atenção" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "erro" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Aviso: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Baixando:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "iniciando" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "não encontrado" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Nenhuma ajuda disponível para este prompt." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "nenhuma ajuda disponível para esta opção" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "exibe todas as opções" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "sim" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "não" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Executando o script %%posttrans '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Executando scripts %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "O pacote não está assinado!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s não pertence a um repositório de atualização da distribuição" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s tem uma arquitetura inferior" + +#~ msgid "problem with installed package %s" +#~ msgstr "problema com o pacote instalado %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "nada fornece o pacote solicitado %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Você habilitou todos os repositórios solicitados?" + +#~ msgid "package %s does not exist" +#~ msgstr "o pacote %s não existe" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s é fornecido pelo sistema e não pode ser apagado" + +#~ msgid "%s is not installable" +#~ msgstr "%s não pode ser instalado" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "nada fornece %s que é necessário a %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "Não foi possível instalar ambos (%s e %s)" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s conflita com %s, fornecido por %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s torna obsoleto %s, fornecido por %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s instalado torna obsoleto %s fornecido por %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "resolvível %s conflita com %s fornecido por ele mesmo" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s requer %s, mas este requisito não pode ser fornecido" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "remover bloqueio para permitir a remoção de %s" + +#~ msgid "do not install %s" +#~ msgstr "não instalar %s" + +#~ msgid "keep %s" +#~ msgstr "manter %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "remover bloqueio para permitir a instalação de %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "não perguntar ao instalar um resolvível que fornece %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "não perguntar ao remover todos os resolvíveis que fornecem %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "não instalar a versão mais recente de %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "manter %s apesar da arquitetura inferior" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "instalar %s apesar da arquitetura inferior" + +#~ msgid "keep obsolete %s" +#~ msgstr "manter o obsoleto %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "instalar %s do repositório excluído" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "desatualização de %s para %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "alteração de arquitetura de %s para %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "instalar %s (com alteração do fornecedor)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "substituição de %s por %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "desinstalação de %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Não foi possível abrir o arquivo de bloqueio: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Esta ação já está sendo executada por outro programa." + +#~ msgid "Hal Exception" +#~ msgstr "Exceção de Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Desculpe, mas esta versão do libzypp foi compilada sem o suporte ao HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext não conectado" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive não inicializado" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume não inicializado" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Não foi possível criar a conexão com o dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Não foi possível criar o contexto libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "libhal_set_dbus_connection: Não foi possível definir a conexão com dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "Não foi possível inicializar o contexto HAL - o hald não está em execução?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Não é uma unidade de CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Não foi possível inicializar os atributos do mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Não foi possível definir o atributo do mutex recursivo" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Não foi possível inicializar o mutex recursivo" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Não foi possível adquirir o bloqueio mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Não foi possível liberar o bloqueio mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Falha ao importar chave pública do arquivo %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Falha ao remover chave pública %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Não foi possível encontrar um dispositivo loop disponível para montar o " +#~ "arquivo de imagem de '%s'" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "geralmente ignorar algumas das dependências" + +#~ msgid "do not forbid installation of %s" +#~ msgstr "não proibir a instalação de %s" + +#~ msgid "do not keep %s installed" +#~ msgstr "não manter %s instalado" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#~ msgid "%s remove failed" +#~ msgstr "فشلت إزالة %s" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "rpm output:" +#~ msgstr "مخرجات rpm:" + +#~ msgid "%s install failed" +#~ msgstr "فشل تثبيت %s" + +#~ msgid "%s installed ok" +#~ msgstr "تم تثبيت %s بنجاح" + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "عدم تثبيت التبعيات القابلة للتحليل المتعلقة أو حذفها" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "تجاهل أنه تم تعيين %s بالفعل لتثبيته" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "تجاهل %s القديم في %s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "تجاهل تعارض %s هذا" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "تجاهل هذا المتطلب هنا فقط" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "Install missing resolvables" +#~ msgstr "تثبيت التبعيات القابلة للتحليل المفقودة" + +#~ msgid "Keep resolvables" +#~ msgstr "الاحتفاظ بالتبعيات القابلة للتحليل" + +#~ msgid "Unlock these resolvables" +#~ msgstr "إلغاء قفل التبعيات القابلة للتحليل هذه" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#~ msgid "install %s" +#~ msgstr "تثبيت %s" + +#~ msgid "unlock %s" +#~ msgstr "إلغاء قفل %s" + +#~ msgid "unlock all resolvables" +#~ msgstr "إلغاء قفل كافة التبعيات القابلة للتحليل" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "يتعارض %s مع التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s يتعارض مع:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "تعذر تثبيت %s لأنه يتعارض مع %s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "لم يتم تثبيت %s وتم وضع علامة عليه كقابل لإلغاء التثبيت" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#~ msgid "%s has missing dependencies" +#~ msgstr "تم فقد تبعيات %s" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "تعذر تثبيت %s بسبب عدم وجود التبعيات" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#~ msgid "No need to install %s" +#~ msgstr "لا داعي لتثبيت %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s يمكن إلغاء تثبيته لأنه يتعارض مع %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s يفتقد المتطلب %s" + +#~ msgid ", Action: " +#~ msgstr "، الإجراء:" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "patch" +#~ msgstr "التصحيح" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Establishing %s" +#~ msgstr "تأسيس %s" + +#~ msgid "Installing %s" +#~ msgstr "تثبيت %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "تخطي %s: تم التثبيت بالفعل" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "%s مقفل ويتعذر إلغاء تثبيته." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid " Error!" +#~ msgstr "خطأ!" + +#~ msgid " Important!" +#~ msgstr "هام!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "تعذر تحليل سلطة Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "تجاهل هذا المتطلب بصفة عامة" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "Unable to restore all sources." +#~ msgstr "تعذرت استعادة كافة المصادر." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading packages file" +#~ msgstr "قراءة ملف الحزم" + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Downloading %s" +#~ msgstr "إنزال %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Não foi possível criar a chave pública %s do chaveiro %s para o arquivo %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "" +#~ "Tentativa de importar chave não existente %s no gerenciador de chaves %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "" +#~ "Não foi possível alterar o diretório para '/' dentro do chroot (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Falha na inicialização do download (Metalink curl) para '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Erro de download (metalink curl) para '%s':\n" +#~ "Código de erro: %s\n" +#~ "Mensagem de erro: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Download interrompido em %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Download interrompido pelo usuário" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "Erro ao configurar as opções de download (metalink curl) para '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Falha ao baixar %s de %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Sérvia e Montenegro" + +#~ msgid "Unknown Distribution" +#~ msgstr "Distribuição desconhecida" + +#~ msgid "ignore some dependencies of %s" +#~ msgstr "ignorar algumas das dependências de %s" + +#~ msgid "Timeout exceeded when access '%s'." +#~ msgstr "Tempo de espera excedido quando acessando '%s'." diff --git a/po/ro.po b/po/ro.po new file mode 100644 index 0000000..a0d19a8 --- /dev/null +++ b/po/ro.po @@ -0,0 +1,5479 @@ +# Translator(s): +# +# Lucian Oprea +# strainu +# xdaiana +# Laudatti +# turcan +# Alexandru Szasz +# nicubunu +# anonymous +# mazilu59 +# evinteler +# Ursan Marius Bogdan +# +# Reviewer(s): +# +# Lucian Oprea +# xdaiana +# Alexandru Szasz +# strainu +# +# Comunitatea romana openSUSE - www.suseromania.ro +msgid "" +msgstr "" +"Project-Id-Version: OpenSUSE\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2012-11-19 14:59+0200\n" +"Last-Translator: Lucian Oprea \n" +"Language-Team: Romanian \n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"X-Generator: Narro 2.0 on http://tradu.softwareliber.ro\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 < " +"20)) ? 1 : 2;\n" +"X-Generator: Narro 2.0 on http://tradu.softwareliber.ro\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Țară necunoscută: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Fără cod" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Emiratele Arabe Unite" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua și Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antilele Olandeze" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarctica" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samoa Americană" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Insulele Aland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaidjan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia și Herțegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgia" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrein" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermude" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazilia" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Insula Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Insulele Cocos (Keeling)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Republica Centrafricană" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Elveția" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Coasta de Fildeș" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Insulele Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Columbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Capul Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Insulele Christmas" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cipru" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Republica Cehă" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Germania" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danemarca" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Republica Dominicană" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algeria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sahara Occidentală" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritreea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spania" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlanda" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Insulele Falkland (Malvine)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Micronezia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Insulele Feroe" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Franța" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Franța metropolitană" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Anglia" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guiana Franceză" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenlanda" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guineea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadelupa" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guineea Ecuatorială" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grecia" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Georgia de Sud și Insulele Sandwich de Sud" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guineea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Insula Heard și Insulele McDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croația" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungaria" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonezia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlanda" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Insula Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Teritoriul britanic din Oceanul Indian" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islanda" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italia" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Iordania" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonia" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kârgâzstan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodgia" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Insulele Comore" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts și Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Coreea de Nord" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Coreea de Sud" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuweit" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Insulele Cayman" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazahstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Republica Populară Democratică Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Liban" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lituania" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letonia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libia" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroc" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Muntenegru" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Insulele Marshall" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Insulele Mariana de Nord" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinica" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Maurițius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldive" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexic" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaezia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambic" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Noua Caledonie" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Insula Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Olanda" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norvegia" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Noua Zeelandă" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinezia franceză" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Noua Guinee" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipine" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polonia" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre și Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Teritoriile palestiniene" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugalia" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "România" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Federația Rusă" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arabia Saudită" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Insulele Solomon" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suedia" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sfânta Elena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard și Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovacia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome și Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Siria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Insulele Turks și Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Ciad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Teritoriile Franceze Sudice" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tailanda" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Timorul de Est" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turcia" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad și Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ucraina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Insulele minore din afara Statelor Unite" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Statele Unite" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Sfântul Scaun (Vatican)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Sfântul Vincent și Grenadine" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Insulele Virgine Britanice" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Insulele Virgine, S.U.A." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis și Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Africa de Sud" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Oferă" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Necesită" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Conflicte" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "păstrează pachetul vechi %s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Recomandă" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Sugerează" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Îmbunătățește" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Suplimentează" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, fuzzy, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Am încercat să import cheia inexistentă %s în colecția de chei %s" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Importul cheii publice %1% a eșuat" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Ștergerea cheii a eșuat." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Fișierul semnătură %s nu a fost găsit" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Limbă necunoscută: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abhază" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achineză" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adâgă" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asiatică (alta)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadiană" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albaneză" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleută" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Limbi Algonquian" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altai de Sud" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharică" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Engleză veche (cca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Limbi apache" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabă" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramaică" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragoneză" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armeană" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araucaniană" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Artificială (alta)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assameză" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturian" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Limbi athapascane" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Limbi australiene" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avaric" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azeră" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Limbi Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bașkiră" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Balochi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balineză" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Bască" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltică (alta)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorusă" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengaleză" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berberă (alta)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (alta)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosniacă" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonă" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonezia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriată" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginese" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgară" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birmaneză" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Indiană din America Centrala (alta)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalană" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Caucaziană (alta)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celtică (alta)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Cecenă" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chineză" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Chuuk" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Jargon Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Slavonă bisericească" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Ciuvașă" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Limbi chamice" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Coptă" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornică" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corsicană" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creole și pidgin bazate pe engleză (altele)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creole și pidgin bazate pe franceză (altele)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creole și pidgin bazate pe portugheză (altele)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tătară crimeeană" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creole și pidgin (altele)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kașubiană" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cuștică (alta)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Cehă" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Daneză" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidiană (alta)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Sorabă de jos" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Olandeză medievală (cca. 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Olandeză" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha (Bhutan)" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egipteană (antică)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamită" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engleză" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Engleză medievală (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estoniană" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Feroeză" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijiană" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipineză" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finlandeză" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fino-ugrică (alta)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Franceză" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Franceză medievală (cca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Franceză veche (842-cca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Friziană" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friulană" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germanică (alta)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgiană" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Germană" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilberteză" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Galică" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandeză" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galiciană" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Germană medievală (cca. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Germană veche (cca. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotică" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Greacă veche (până la 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Greacă modernă (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitiană" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiiană" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Ebraică" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hitită" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Sorabă de sus" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Maghiară" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandez" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indiană (alta)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indoneziană" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-europeană (alta)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingușă" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iraniană (alta)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Limbi irocheze" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italiană" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javaneză" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japoneză" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Iudeo-persiană" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Iudeo-arabică" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kașmiră" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Cazacă" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisan (alta)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotaneză" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiză" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Komi" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreeană" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosraeană" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karageai-Balkară" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdă" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laoțiană" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latină" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letonă" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezghiană" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgheză" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Lituaniană" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgheză" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya și Tanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedoneană" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurese" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshalleză" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austroneziană (alta)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malaeziană" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandeză medievală (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Diverse limbi" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (alta)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgașă" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Malteză" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Limbi manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldovenească" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolă" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Limbi multiple" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Limbile Munda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandeză" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Limbi maya" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzia" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Indiană din America de Nord" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitană" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele de sud" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele de nord" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Germană de jos" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepaleză" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanian (alta)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueană" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norwegiană Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norwegiană Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Scandinavă veche" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norvegiană" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Sotho de Nord" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Limbi nubiene" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari clasică" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitană (după 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Osetă" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turcă otomană (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Limbi otomiene" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papua (alta)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauană" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Persană veche (cca. 600-400 î.e.n.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persană" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipineză (alta)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Feniciană" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Poloneză" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugheză" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Limbi prakrite" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provensală veche (până la 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romanică (alta)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Retoromană" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Română" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rusă" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakută" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Indiană din America de sud (alta)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Limbi salishan" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Aramaică samariteană" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanscrită" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Sârbă" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Siciliană" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Croată" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitică (alta)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandeză veche (până la 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Limbajul semnelor" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Limbi siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-tibetană (alta)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slavă (alta)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovacă" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenă" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sami sudică" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Sami nordică" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Limbi sami (altele)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Sami lule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Sami inari" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoană" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Sami skolt" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdiană" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho de sud" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spaniolă" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardă" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-sahariană (alta)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sumeriană" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumeriană" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Suedeză" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siriacă" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitiană" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (alta)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tătară" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tailandeză" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetană" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingoniană" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Insulele Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmenă" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Limbi Tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turcă" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaică (alta)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuviniană" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritică" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uigură" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ucrainiană" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Nedeterminată" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbecă" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnameză" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votică" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Limbi wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Galeză" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Limbi sorabe" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Valonă" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmucă" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Idiș" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Limbi yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotecă" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Vor fi efectuate următoarele acțiuni:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "(nu expiră)" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(nu expiră)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(EXPIRAT)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(expiră în 24h)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, fuzzy, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(expiră în 24h)" +msgstr[1] "(expiră în 24h)" +msgstr[2] "(expiră în 24h)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "necunoscut" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nesuportat" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Nivelul 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Nivelul 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Nivelul 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Este necesar un contract client suplimentar" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "invalid" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Nivelul de suport este nespecificat" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Vânzătorul nu oferă suport." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Determinarea problemei, ceea ce înseamnă suport tehnic menit să ofere " +"informații de compatibilitate, asistență la instalare, suport la utilizare, " +"mentenanță curentă și rezolvarea problemelor simple. Suportul de nivel 1 nu " +"este menit să corecteze erori ale produsului." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Izolarea problemei, ceea ce înseamnă suport tehnic menit să reproducă " +"problemele clienților, să izoleze zona cu probleme și să ofere soluții " +"pentru probleme nerezolvate de suportul de nivel 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Rezolvarea problemei, ceea ce înseamnă suport tehnic menit să rezolve " +"problemele complexe prin contribuția specialiștilor la rezolvarea de defecte " +"ale produselor, identificate de suportul de nivel 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" +"Pentru a obține suport tehnic se necesită un contract client suplimentar." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Opțiune de suport necunoscută. Descrierea nu este disponibilă" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Gestiunea sistemului a fost blocată de aplicația cu pid %d (%s).\n" +"Închideți această aplicație înainte de a încerca din nou." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Mod necunoscut '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Mod necunoscut '%s' pentru modelul '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "'%s' este o expresie regulată invalidă: regcomp a întors %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Expresie regulată invalidă '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Pentru '%s' este necesară autentificarea" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Vizitează Centru de Relații cu Clienții Novell pentru a verifica dacă " +"înregistrarea este validă și încă valabilă." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +#, fuzzy +msgid "Please install package 'lsof' first." +msgstr "Curăț cache-ul pachetelor instalate." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Nu se poate crea directorul pentru cache-ul de metadate." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Eroare la încercarea de a citi din '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Nu se poate crea %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +#, fuzzy +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "La URL-ul (URL-urile) specificate nu au fost găsite metadate valide" +msgstr[1] "La URL-ul (URL-urile) specificate nu au fost găsite metadate valide" +msgstr[2] "La URL-ul (URL-urile) specificate nu au fost găsite metadate valide" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Sursa de instalare (%d) nu a putut fi încărcată în cache." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Construirea cache-ului sursei de instalare '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Nu se poate crea memoria cache la %s - lipsește dreptul de scriere." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Tip de sursă de instalare netratat" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Adaug sursa de instalare '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Nume de fișier sursă de instalare invalid la '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Nu se poate deschide fișierul '%s' pentru scriere." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Eroare necunoscută la citirea de la '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Citirea directorului '%s' a eșuat" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Îndepărtez sursa de instalare '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Nu pot determina unde este stocată sursa de instalare." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Nu pot șterge '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Nu pot determina unde este stocat serviciul." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Aliasul sursei de instalare nu poate începe cu punct." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Aliasul serviciului nu poate începe cu punct." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +# continue button label +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Continuați?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Atributul necesar '%s' lipsește." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Unul sau ambele din atributele '%s' și '%s' sunt necesare." + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr " execuție eșuată" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Pachetul %s a fost probabil corupt în timpul transferului. Doriți să " +"repetați descărcarea?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Furnizarea pachetului %s a eșuat. Doriți să încercați să-l obțineți din nou?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "verificarea applydeltarpm a eșuat." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm a eșuat." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "" +"tipul de resursă VAR1 nu suportă funcția de arătare a modificărilor (show " +"changes)" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Nu pot oferi fișierul '%s' din sursa '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Nici un url în sursa de instalare." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Nu pot crea sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "întrerupe pachetul %s ignorând o parte din dependențele lui" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "în general se ignoră unele dependințe" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "cereri ce intră în conflict" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "o problemă de dependențe" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +#, fuzzy +msgid "unsupported request" +msgstr "nesuportat" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "pachete șterse: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"pachete care pot fi dezinstalate: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "furnizori dezinstalabili: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Această cerere vă va afecta sistemul!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignoră avertismentul privitor la stricarea sistemului" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Instalarea a fost anulată la cerere." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " executat" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " execuție eșuată" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, fuzzy, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%1 este deja decriptat!" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " execuție sărită în timpul anulării" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Eroare trimitere notificare mesaj de actualizare." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nou mesaj de actualizare" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM a eșuat:" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Importul cheii publice %1% a eșuat" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Îndepărtarea cheii publice %1% a eșuat" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Fișiere de configurare modificate pentru %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm a salvat %s ca %s, dar nu a putut determina diferențele" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm a salvat %s ca %s.\n" +"Acestea sunt primele 25 de linii diferite:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm a creat %s ca %s, dar nu a putut determina diferențele" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm a creat %s ca %s.\n" +"Acestea sunt primele 25 de linii diferite:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Ieșire rpm suplimentară" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "backup %s creat" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Fișierul semnătură %s nu a fost găsit" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Fișierul semnătură %s nu a fost găsit" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Fișierul semnătură %s nu a fost găsit" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Tip dubios '%s' pentru byte-ul %u, suma de control '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Nu pot deschide pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Nu pot deschide pipe-ul (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Șir de interogare URL LDAP invalid" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Parametru șir de interogare URL LDAP invalid '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Nu pot clona obiectul Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Referință vidă invalidă la obiect Url" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Nu pot parcurge componentele Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Istoric:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Schema url nu permite %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Componentă %s invalidă '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Componentă invalidă %s" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Pentru acest URL nu este suportată parcurgerea unui șir de interogare" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Schema url este o componentă obligatorie" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Schemă ulr invalidă '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Schema url nu permite un nume de utilizator" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Schema url nu permite parolă" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Schema url necesită o componentă gazdă" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Schema url nu permite componentă gazdă" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Componentă gazdă invalidă '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Schema url nu permite port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Componentă port invalidă '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Schema url necesită o cale" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Calea relativă nu este permisă dacă autoritatea există" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Șirul codat conține un byte NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Parametru invalid caracter de separare împărțire matrici" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Parametru de hartă invalid pentru separarea caracterelor" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Parametru invalid caracter de separare uniune matrici" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Comandă finalizată cu starea %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Comanda a fost oprită de semnalul %d(%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Comandă finalizată cu eroare necunoscută." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Nu se poate face chroot la '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Nu se poate face chroot la '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Nu pot efectua chdir spre '/' în chroot (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Nu pot executa '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Nu pot crea un proces nou (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Montarea %s pe %s a eșuat" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Demontarea %s a eșuat" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nume de fișier incorect: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" +"Mediul nu a fost deschis în timp ce se încerca efectuarea acțiunii '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Fișierul '%s' nu a fost găsit pe mediul '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Nu pot scrie fișierul '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Mediu neatașat" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Punct incorect de conectare a mediului" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Inițializarea download-ului (curl) a eșuat pentru '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Excepție sistem '%s' pe mediul '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Calea '%s' de pe mediul '%s' nu este un fișier." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Calea '%s' de pe mediul '%s' nu este un director." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI Invalid" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Nume de gazdă vid în URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Sistem de fișiere vid în URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Destinație vidă în URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Schemă URI nesuportată în '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operația nu este suportată de mediu" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Eroare de descărcare (curl) pentru '%s':\n" +"Cod eroare: %s\n" +"Mesaj eroare: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"A apărut o eroare la setarea opțiunilor de download (curl) pentru '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Sursa '%s' nu conține CD-ul/DVD-ul corect" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Mediul '%s' este utilizat momentan de o altă instanță" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Nu pot ejecta nici un mediu" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Nu pot ejecta mediul '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Accesul la '%s' a fost interzis." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Timp depășit în timpul accesării '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Locația '%s' este temporar inaccesibilă." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +"Problemă de certificat SSL, verificați dacă certificatul autorității de " +"certificare este OK pentru '%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Metodă de autentificare HTTP nesuportată '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Da" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nu" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Avertisment:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Eroare" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "gata" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "eroare" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Avertisment:" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Se descarcă:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "pornesc" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Nu s-a găsit" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Niciun ajutor disponibil pentru acest dialog." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "niciun ajutor disponibil pentru această opțiune" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "da" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nu" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s nu aparține de o sursă de instalare de actualizare distribuție" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s are arhitectură inferioară" + +#~ msgid "problem with installed package %s" +#~ msgstr "problemă cu pachetul instalat %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "nimic nu oferă %s necesar" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Ați activat toate sursele cerute?" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "nu există backup" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s este blocat şi nu poate fi deinstalat." + +#~ msgid "%s is not installable" +#~ msgstr "%s nu este instalabil" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "Nimic nu oferă %s necesar pentru %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "nu pot instala %s și %s împreună" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s intră în conflict cu %s pus la dispoziție de %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s înlocuiește %s oferit de %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "versiuni vechi %s instalate %s furnizate de %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "dependența %s intră în conflict cu %s furnizat de ea însăși" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s necesită %s, dar această cerință nu este îndeplinită" + +#~ msgid "do not install %s" +#~ msgstr "nu instala %s" + +#~ msgid "keep %s" +#~ msgstr "păstrează %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "nu interzice instalarea %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "nu cere instalarea unui pachet ce oferă %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "nu cere stergerea tuturor pachetelor ce oferă %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "nu instala cea mai recentă versiune a %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "păstrează %s chiar dacă arhitectura este inferioară" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "instalează %s chiar dacă arhitectura este inferioară" + +#~ msgid "keep obsolete %s" +#~ msgstr "păstrează pachetul vechi %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "instalează %s de la o sursă de instalare exclusă" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "downgrade %s la %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "modificare de arhitectură a %s în %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "instalează %s (cu modificarea vânzătorului)\n" +#~ " %s\n" +#~ "-->\n" +#~ " %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "înlocuirea %s cu %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "deinstalarea %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Nu pot deschide fișierul zăvor: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Această acțiune este rulată deja de alt program." + +#~ msgid "Hal Exception" +#~ msgstr "Excepție Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Ne pare rău, dar această versiune de libzypp a fost construită fără " +#~ "suport HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext nu este conectat" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive nu este inițializat" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume nu este inițializat" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Nu pot crea conexiunea dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Nu pot crea contextul libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Nu pot seta conexiunea dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "" +#~ "Nu pot inițializa contextul HAL -- este posibil ca hald să nu ruleze?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Nu este o unitate CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Nu pot inițializa atributele mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Nu pot seta atributul mutex recursiv" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Nu pot inițializa mutex-ul recursiv" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Nu pot obține zăvorul mutex-ului" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Nu pot elibera zăvorul mutex-ului" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Importul cheii publice din fișierul %s a eșuat: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Îndepărtarea cheii publice %s a eșuat: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "Nu este disponibil dispozitivul pentru a monta imagine de la '%s'" + +#~ msgid "do not keep %s installed" +#~ msgstr "nu păstra %s instalat" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "Nu pot crea cheia publică %s din keyring-ul %s pe fișierul %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Inițializarea descărcării (metalink curl) a eșuat pentru '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Eroare de descărcare (metalink curl) pentru '%s':\n" +#~ "Cod eroare: %s\n" +#~ "Mesaj eroare: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Descărcare întreruptă la %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Descărcare întreruptă de utilizator" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "A apărut o eroare la setarea opțiunilor de descărcare (metalink curl) " +#~ "pentru '%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "A eșuat descărcarea %s de la %s" diff --git a/po/ru.po b/po/ru.po new file mode 100644 index 0000000..94cf8d9 --- /dev/null +++ b/po/ru.po @@ -0,0 +1,5536 @@ +# Translation of zypp.po to russian +# Copyright (C) 2005, 2006 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999, 2000, 2001 SuSE GmbH. +# +# Aleksey Novodvorksy , 2000. +# Eugene Osintsev , 1999, 2000. +# Aleksey Osipov , 2005, 2006, 2007, 2008. +# Nikolay Derkach , 2007, 2008. +# Alexander Melentiev , 2008, 2009, 2010. +# Alexander Melentiev , 2011, 2012, 2013, 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: zypp.ru\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2022-03-16 00:12+0000\n" +"Last-Translator: Sergey Mashkov \n" +"Language-Team: Russian \n" +"Language: ru\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Неизвестная страна: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Нет кода" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Андорра" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Объединенные Арабские Эмираты" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Афганистан" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Антигуа и Барбадос" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Ангилья" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Албания" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Армения" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Нидерландские Антильские острова" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Ангола" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Антарктида" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Аргентина" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Американское Самоа" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Австрия" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Австралия" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Аруба" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Аландские острова" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Азербайджан" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Босния и Герцеговина" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Барбадос" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Бангладеш" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Бельгия" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Буркина-Фасо" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Болгария" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Бахрейн" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Бурунди" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Бенин" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Бермудские острова" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Бруней-Даруссалам" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Боливия" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Бразилия" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Багамы" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Бутан" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Остров Буве" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Ботсвана" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Беларусь" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Белиз" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Канада" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Кокосовые острова (Килинг)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Конго" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Центральноафриканская Республика" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Швейцария" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Кот-д\"Ивуар" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Острова Кука" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Чили" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Камерун" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Китай" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Колумбия" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Коста-Рика" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Куба" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Кабо-Верде" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Остров Рождества" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Кипр" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Чехия" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Германия" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Джибути" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Дания" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Доминика" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Доминиканская Республика" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Алжир" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Эквадор" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Эстония" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Египет" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Западная Сахара" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Эритрея" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Испания" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Эфиопия" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Финляндия" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Фиджи" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Фолклендские острова (Мальвинские)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Федеративные Штаты Микронезии" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Фарерские острова" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Франция" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Франция" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Габон" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Соединенное Королевство" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Гренада" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Грузия" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Французская Гвинея" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Гернси" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Гана" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Гибралтар" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Гренландия" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Гамбия" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Гвинея" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Гваделупа" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Экваториальная Гвинея" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Греция" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Южная Георгия и Южные Сандвичевы острова" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Гватемала" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Остров Гуам" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Гвинея-Бессау" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Гайяна" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Гонконг" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Остров Херд и острова МакДональда" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Гондурас" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Хорватия" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Гаити" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Венгрия" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Индонезия" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ирландия" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Израиль" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Остров Мэн" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Индия" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Британская территория Индийского океана" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Ирак" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Иран" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Исландия" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Италия" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Джерси" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Ямайка" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Иордан" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Япония" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Кения" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Киргизстан" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Камбоджа" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Кирибати" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Коморские острова" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Сент-Китс и Невис" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Северная Корея" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Южная Корея" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Кувейт" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Каймановы острова" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Казахстан" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Лаосская Народно-Демократическая Республика" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Ливан" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Сент-Люсия" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Лихтенштейн" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Шри-Ланка" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Либерия" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Лесото" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Литва" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Люксембург" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Латвия" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Ливия" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Марокко" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Монако" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Молдова" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Черногория" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Сен-Мартен" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Мадагаскар" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Маршалловы острова" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Македония" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Мали" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Мьянма" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Монголия" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Макао" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Северные Марианские Острова" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Остров Мартиника" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Мавритания" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Монтсеррат" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Мальта" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Маврикий" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Мальдивы" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Малави" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Мексика" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Малайзия" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Мозамбик" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Намибия" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Новая Каледония" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Нигер" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Остров Норфолк" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Нигерия" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Никарагуа" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Нидерланды" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Норвегия" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Непал" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Науру" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Ниуэ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Новая Зеландия" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Оман" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Панама" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Перу" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Французская Полинезия" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Папуа – Новая Гвинея" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Филиппины" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Пакистан" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Польша" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Сен-Пьер и Микелон" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Остров Питкэрн" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Пуэрто-Рико" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Палестина" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Португалия" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Острова Палау" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Парагвай" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Катар" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Реюньон" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Румыния" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Сербия" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Российская Федерация" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Руанда" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Саудовская Аравия" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Соломоновы острова" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Сейшелы" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Судан" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Швеция" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Сингапур" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Остров Святой Елены" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Словения" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Шпицберген и Ян-Майен" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Словакия" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Сьерра-Леоне" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "Сан-Марино" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Сенегал" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Сомали" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Суринам" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Сан-Томе и Принсипи" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Сальвадор" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Сирия" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Свазиленд" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Теркс и Кайкос" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Чад" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Французские Южные территории" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Того" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Таиланд" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Таджикистан" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Токелау" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Туркменистан" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Тунис" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Тонга" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Восточный Тимор" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Турция" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Тринидад и Тобаго" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Тувалу" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Тайвань" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Танзания" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Украина" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Уганда" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Внешние малые острова США" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "США" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Уругвай" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Узбекистан" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Ватикан" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Сент-Винсент и Гренадины" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Венесуэла" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Британские Виргинские острова" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Виргинские острова, США" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Вьетнам" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Вануату" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Уоллис и Футуна" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Острова Самоа" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Йемен" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Майотта" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "ЮАР" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Замбия" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Зимбабве" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Предоставляет" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Предварительно требует" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Требует" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Конфликтует" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Делает устаревшим" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Рекомендует" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Предлагает" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Улучшает" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Дополняет" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Попытка импорта несуществующего ключа %s в хранилище ключей %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Не удалось импортировать ключ %1%." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Не удалось удалить ключ." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Не найден файл подписи %s" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Неизвестный язык: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Афарский" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Абхазский" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Ачехский" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Ачоли" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Адангме" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Адыгейский" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Афро-азиатский (другие)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Африхили" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Африкаанс" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Айнский" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Аканский" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Аккадский" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Албанский" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Алеутский" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Алгонкинские языки" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Южно-алтайский" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Амхарский (амаринья)" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Английский, Старый (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Апачские языки" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Арабский" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Арамейский" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Арагонский" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Армянский" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Арауканский" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Арапахо" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Искусственные (другие)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Аравакские" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Ассамский" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Астурийский" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Атапаскские языки" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Австралийские языки" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Аварский" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Авестийский" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Авадхи" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Аймара" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Азербайджанский" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Банда" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Бамилеке языки" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Башкирский" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Белуджский" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Бамбара" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Балийский" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Баскский" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Баса" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Балтийский (Другие)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Беджа" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Белорусский" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Бемба" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Бенгальский" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Берберские (другие)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Бходжпури" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Бихари" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Бикольский" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Бини" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Бислама" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Сиксика" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Банту (другие)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Боснийский" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Брауи" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Бретонский" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Батакский (Индонезия)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Бурятский" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Бугийский" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Болгарский" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Бирманский" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Блин" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Каддо" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Индейцев Центральной Америки (Другой)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Кариб" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Каталонский" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Кавказские (другие)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Себуанский" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Кельтские (другие)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Чаморро" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Чибча" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Чеченский" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Чагатайский" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Китайский" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Чукотский" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Марийский" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Чинук жаргон" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Чоктав" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Чипевьян" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Чероки" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Церковно-славянский" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Чувашский" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Чейенн" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Чамикские языки" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Коптский" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Корнский" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Корсиканский" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Англо-креольские и пиджины (другие)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Франко-креольские и пиджины (другие)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Португало-креольские и пиджины (другие)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Кри" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Крымско-татарский" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Креольские и пиджины (другие)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Кашубианский" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Кушитские (другие)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Чешский" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Дакота" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Датский" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Даргинский" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Даякский" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Делаварский" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Атапачские языки" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Догриб" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Динка" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Дивехи (Мальдивский)" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Догри" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Дравидийские (другие)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Нижне-лужицкий" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Дуала" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Немецкий, средневековый (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Голландский" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Диула (Дьюла)" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Дзонг-кэ" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Эфик" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Древнеегипетский" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Экаджук" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Эламский" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Английский" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Английский, Средневековый (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Эсперанто" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Эстонский" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Эве" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Эвондо" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Фанг" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Фарерский" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Фанти" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Фиджи" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Филиппинский" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Финский" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Финно-Угрисйкий (другие)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Фон" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Французский" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Среднефранцузский" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Старофранцузский" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Фризский" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Фулах" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Фриулийский" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Га" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Гайо" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Гбайя" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Германские (другие)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Грузинский" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Немецкий" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Геэз" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Гильбертский" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Гаэльский" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Ирландский" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Галисийский" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Мэнский" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Немецкий, средние века (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Немецкий, старый (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Гонди" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Горонтала" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Готский" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Гребо" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Древнегреческий" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Греческий, Современный (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Гуарани" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Гуджарати" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Гвичин" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Хайда" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Гаитянский" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Хауса" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Гавайский" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Иврит" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Гереро" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Хилигайнон" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Химачали" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Хинди" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Хиттит" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Хмонг" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Хири" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Верхне-лужицкий" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Венгерский" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Хупа" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Ибанский" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Игбо" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Исландский" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Идо" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Йи (Сычуань)" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Иджо" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Инуктитут" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Интерлингве" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Илоко" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Интерлингва (Международная Ассоциация Вспомогательного Языка)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Индийские (другие)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Индонезийский" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Индо-Европейский (Другой)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ингушский" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Инупиак" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Иранский (Другой)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Ирокезские языки" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Итальянский" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Яванский" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Ложбан" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Япония" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Еврейско-персидский" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Еврейско-арабский" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Кара-Калпакский" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Кабильский" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Качинский" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Гренландский" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Камба" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Каннада" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Каренский" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Кашмири" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Канури" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Кави" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Казахский" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Кабардинский" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Кхаси" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Койсанские (другие)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Хмерский" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Хотанский" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Кикуйю" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Киньяруанда" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Киргизский (Кыргызский)" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Кимбунду" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Конкани" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Коми" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Конго" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Корейский" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Кусайе" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Кпелле" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Карачаево-балкарский" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Кру" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Курух" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Киньяма" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Кумыкский" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Курдский" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Кутенаи" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ладино" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Лахнда" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Ламба" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Лаосский" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Латинский" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Латышский" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Лезгинский" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Лимбуржский" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Лингала" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Литовский" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Монго" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Лози" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Люксембургский" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Луба-Лулуа" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Луба-Катанга" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ганда" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Луисеньо" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Лунда" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Луо (Кения и Танзания)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Лушаи" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Македонский" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Мадурский" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Магахи" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Маршальский" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Майтхили" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Макассарский" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Малаялам" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Мандинго" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Маори" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Австронезийские (другие)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Маратхи" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Масаи" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Малайский" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Мокшанский" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Мандара" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Менде" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Ирландский, средневековый (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Микмак" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Минангкабау" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Смешанные языки" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Монкхмерские (другие)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Малагасийский" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Мальтийский" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Манчу" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Манипурский" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Манобо языки" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Мохаук" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Молдавский" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Монгольский" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Моси" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Языки разных семей" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Мунда языки" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Крик" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Мирандский" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Марвари" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Майя языки" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Эрзянский" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Науатль" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Северной Америки индейцев" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Неаполитанский" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Навахо" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ндебеле южный" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ндебеле северный" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ндунга" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Нижненемецкий" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Непальский" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Непал-бхаса" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Ниасский" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Нигер-кордофанские (другие)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Ниуэ" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Нюнорск (Новонорвежский)" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Букмоль (Норвежский)" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Ногайский" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Старонорвежский" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Норвежский" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Северный Сото" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Нубийские языки" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Классический неварский" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Чичева" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Ньямвези" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Ньянколе" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Ньоро" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Нзима" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Окситанский (после 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Оджибва" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Ория" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Оромо" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Оседжи" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Осетинский" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Турецкий, Оттоманский (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Отомангские языки" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Папуасские (другие)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Пангасинан" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Пехлевийский" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Пампанга" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Панджаби" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Папьяменто" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Палау" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Персидский, Старый (ca.600-400 до н.э.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Персидский" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Филиппинские (другие)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Финикийский" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Пали" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Польский" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Понпейский" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Португальский" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Языки пракрит" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Провансальский, Старый (до 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Пушту" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Кечуа" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Раджастхани" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Рапануи" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Раротонга" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Романские (другие)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Рето-Романский" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Цыганский" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Румынский" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Рунди" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Русский" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Сандаве" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Санго" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Якутский" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Индейцев Южной Америки (другие)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Салишские языки" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Самаритянский арамейский" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Санскрит" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Сасакский" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Сантали" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Сербский" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Сицилийский" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Шотландский (Гэльский)" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Хорватский" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Селькупский" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Семитские (другие)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Ирландский, Устаревший (до 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Языки жестов" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Шанский" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Сидама" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Сингальский" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Языки Сиу" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Сино-Тибетские (другие)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Славянские (другие)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Словацкий" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Словенский" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Южно-саамский" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Северо-саамский" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Саамские языки (другие)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Люле-саамский" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Инари-саамский" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Самоанский" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Скольт-саамский" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Шона" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Синдхи" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Сонинке" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Согдийский" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Сомали" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Сонгаи" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Сото Южный" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Испанский" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Сардинский" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Серер" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Нило-сахарские (другие)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Свати" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Сукума" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Сунданский" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Сусу" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Шумерский" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Суахили" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Шведский" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Сирийский" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Таитянский" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Тайские (другие)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Тамильский" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Татарский" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Телугу" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Темне" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Терено" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Тетумский" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Таджикский" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Тагальский" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Тайский" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Тибетский" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Тигре" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Тигринья" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Тив" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Клингон" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Тлингит" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Тамашек" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Тонга (Ньяса)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Тонга (Тонга Исландский)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Ток-писин" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Цимшиан" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Тсвана" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Тсонга" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Туркменский" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Тумбука" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Тупи языки" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Турецкий" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Алтайские (другие)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Тви" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Тувинский" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Удмуртский" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Угаритский" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Уйгурский" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Украинский" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Умбунду" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Неопределенный" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Урду" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Узбекский" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Ваи" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Венда" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Вьетнамский" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Волапюк" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Водский" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Вакашские языки" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Воламо" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Варай" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Вашо" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Уэльский" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Лужицкие языки" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Валлонский" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Волоф" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Калмыцкий" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Кхоса" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Яо" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Яп" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Идиш" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Йоруба" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Языки группы Юпик" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Сапотекский" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Зенагский" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Чжуань" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Занди" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Зулусский" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Зунийский" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Будут выполнены следующие действия:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "не истекает" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "истек: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "истекает: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(не истекает)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(ИСТЕК)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(истекает в течение 24 часов)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(истекает через %d день)" +msgstr[1] "(истекает через %d дня)" +msgstr[2] "(истекает через %d дней)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "неизвестно" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "не поддерживается" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Уровень 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Уровень 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Уровень 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Необходимо дополнительное клиентское соглашение" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "неверно" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Уровень поддержки не определен" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Производитель не предоставляет поддержку." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Определение проблемы, т. е. техподдержка должна предоставлять информацию о " +"совместимости, помощь при установке, поддержку использования, обслуживание и " +"базовое выявление неисправностей. Поддержка первого уровня не подразумевает " +"исправление дефектов продукта." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Изоляция проблемы, т. е. техподдержка должна воспроизводить проблему " +"клиента, изолировать проблемную область и предоставлять решения проблем, не " +"решенных поддержкой первого уровня." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Решение проблемы, т. е. техподдержка должна решать сложные проблемы с " +"привлечением инженеров для исправления дефектов продукта, обнаруженных " +"поддержкой второго уровня." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" +"Для получения поддержки необходимо дополнительное клиентское соглашение." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Неизвестный вариант поддержки. Описание недоступно" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Управление системой заблокировано приложением с pid %d (%s).\n" +"Закройте это приложение перед следующей попыткой." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Неизвестный режим сопоставления \"%s\"" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Неизвестный режим сопоставления \"%s\" для шаблона \"%s\"" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Недопустимое регулярное выражение \"%s\": regcomp вернул %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Недопустимое регулярное выражение \"%s\"" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Необходима аутентификация для \"%s\"" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Убедитесь, что ваша регистрация действительна и срок ее действия не истек, в " +"центре SUSE Customer Center." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Посетите Novell Customer Center для проверки срока действия вашей " +"регистрации." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Создание точки присоединения: не могу найти катлог с возможностью записи для " +"создания точки присоединения" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Сначала установите пакет \"lsof\"." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Невозможно создать каталог кэша метаданных." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Ошибка при попытке чтения из \"%s\"" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Не удалось создать %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "По указанному URL-адресу не найдено допустимых метаданных" +msgstr[1] "По указанным URL-адресам не найдено допустимых метаданных" +msgstr[2] "По указанным URL адресам не найдено допустимых метаданных" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Ошибка при кэшировании репозитория (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Сбор кэша репозитория \"%s\"" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Не удалось создать кэш в %s — нет прав на запись." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Необрабатываемый тип репозитория" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Добавление репозитория \"%s\"" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Недопустимое имя файла репозитория в \"%s\"" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Невозможно открыть файл \"%s\" для записи." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Неизвестная ошибка при чтении из \"%s\"" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Невозможно прочитать каталог репозитория \"%1%\": доступ запрещен" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Не удалось прочитать каталог \"%s\"" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Невозможно прочитать файл репозитория \"%1%\": доступ запрещен" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Удаление репозитория \"%s\"" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Невозможно выяснить, где хранится репозиторий." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Не удается удалить \"%s\"" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Невозможно определить, где хранится сервис." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" +"Неизвестный сервис \"%1%\": удаление служебного репозитория \"%2%\" с " +"нарушенными ассоциациями" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Псевдоним репозитория не может начинаться с точки." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Псевдоним сервис не может начинаться с точки." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Продолжить?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Репозиторий %1% не определяет дополнительных URL вида «gpgkey=»." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Поиск ID gpg-ключа %1% в репозитории %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Поиск ID gpg-ключа %1% в кэше %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Необходимый атрибут \"%s\" отсутствует." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Требуются один или оба атрибута \"%s\" или \"%s\"." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Сбой при проверке подписи" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Похоже, что пакет %s поврежден при передаче. Попробовать получить еще раз?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Не удалось предоставить пакет %s. Попробовать получить еще раз?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "сбой при проверке applydeltarpm." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "сбой в applydeltarpm." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Модуль сервиса не поддерживает изменение атрибута." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Невозможно предоставить файл \"%s\" из репозитория \"%s\"" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "В репозитории нет URL-адреса." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" +"Ожидается носитель %1%/%2% идентифицированный в файле '%3%' со следующим " +"содержимым:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом из пакета\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом из пакета\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом из пакета\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом из пакета\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом\n" +" %3%\n" +" из пакета\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом\n" +" %3%\n" +" из пакета\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом\n" +" %3%\n" +" из пакета\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Файл %1%\n" +" из пакета\n" +" %2%\n" +" конфликтует с файлом\n" +" %3%\n" +" из пакета\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Невозможно создать sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "повредить %s, игнорируя некоторые из его зависимостей" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "вообще игнорировать некоторые зависимости" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"установленный пакет %1% не содержится в репозитории обновления и должен быть " +"заменён" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" +"установленный пакет %1% не принадлежит репозиторию обновления дистрибутива" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "установленный %1% имеет низшую архитектуру" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "будет установлен %1% с низшей архитектурой" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "проблема с установленным %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "конфликтующие запросы" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "проблема с некоторыми зависимостями" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "никто не предоставляет запрошенный '%1%'" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Вы включили все необходимые репозитории?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "запрошенный пакет %1% не существует" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "запрос не поддерживается" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1' поставляется как часть системы и не может быть удалён" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% не может быть установлен" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "никто не предоставляет '%1' требуемый для установленного %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "никто не предоставляет '%1%' требуемый для установки %2%" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "невозможно установить оба %1% и %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "установленный %1% конфликтует с '%2%' предоставленным %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "установленный %1% конфликтует с '%2%', требуемым для установки %3%" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"устанавливаемый %1% конфликтует с '%2%' требуемым для установленного %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "устанавливаемый %1% конфликтует с '%2%' требуемым для установки %3%" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "установленный %1% заменяет '%2%', требуемый для установленного %3%" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "установленный %1% заменяет '%2%' требуемый для установки %3%" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "устанавливаемый %1% заменяет '%2%' требуемый для установленного %3%" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "устанавливаемый %1% заменяет %2% требуемый для установленного %3%" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "установленный %1% конфликтует с '%2%' предоставленным самим собой" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "устанавливаемый %1% конфликтует с '%2%', который поставляет сам" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"установленный %1% требует '%2%', но это требование не может быть выполнено" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"устанавливаемый %1% требует '%2%', но это требование не может быть выполнено" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "удаленные поставщики: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"неустанавливаемые поставщики: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "поставщики, не подлежащие установке: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% ещё не полностью интегрирован в %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Скорее всего вы захотите оставить PTF и решите не устанавливать исправления." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Установленный %1% не позволяет выполнить желаемое действие." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Скорее всего вы хотите оставить PTF и решите отменить действие." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "снять блокировку чтобы разрешить удаление %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "не устанавливать %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "оставить %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "снять блокировку чтобы разрешить установку %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Этот запрос повредит вашу систему!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "игнорировать предупреждение о повреждении системы" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "не просить установить решение, которое предоставляет %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "не просить удалять все решения, предоставляющие %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "не устанавливать самую последнюю версию %1" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "оставить %1% не смотря на низшую архитектуру" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "установить %1% не смотря на низшую архитектуру" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "оставить устаревший %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "установить %1% из выключенного репозитория" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "установить %1%, хоть он и был отозван" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "разрешить установку PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "установить %1%, хоть он и в чёрном списке" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "понизить версию %1% до %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "изменить архитектуру %1% на %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"установить %1% (со сменой поставщика)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"установить %1% от поставщика %2%\n" +" заменяющий %3% от поставщика %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "замена %1% на %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "удаление %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Установка прервана согласно указаниям." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " выполнено" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " сбой при выполнении" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s уже выполнен как %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " выполнение пропущено во время прерывания работы" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Ошибка при отправке сообщения об обновлении." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Новое сообщение об обновлении" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Транзакция не удалась из-за следующих проблем:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Сбой RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Не удалось импортировать открытый ключ %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Не удалось удалить открытый ключ %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Заголовок пакета не подписан!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Содержимое пакета на подписано!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Измененные конфигурационные файлы для %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm сохранил %s как %s, но было невозможно определить различия" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm сохранил %s как %s.\n" +"Первые 25 строк различий:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm создал %s как %s, но было невозможно определить различия" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm создал %s как %s.\n" +"Первые 25 строк различий:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Дополнительный вывод rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "создана резервная копия %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Подпись в порядке" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Неизвестный тип подписи" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Подпись не проверена" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Подпись в порядке, но ключ не является доверенным" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Открытый ключ подписей недоступен" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Файл не существует, или невозможно проверить подпись" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Файл не подписан" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Подозрительный тип \"%s\" %u-байтовой контрольной суммы \"%s\"" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Невозможно открыть псевдотерминал (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Невозможно открыть канал (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Недопустимая строка запроса LDAP в URL-адресе" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Недопустимый параметр запроса LDAP в URL-адресе: \"%s\"" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Не удалось создать клон объекта URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Недопустимая ссылка на пустой объект URL" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Не удалось выполнить анализ синтаксиса компонентов URL-адреса" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "История:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Схема URL-адреса не позволяет использовать %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Недопустимый компонент %s: \"%s\"" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Недопустимый компонент %s" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Для данного URL-адреса анализ строки запроса не поддерживается" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Схема URL-адреса является необходимым компонентом" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Недопустимая схема URL-адреса \"%s\"" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Схема URL-адреса не позволяет использовать имя пользователя" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Схема URL-адреса не позволяет использовать пароль" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Схема URL-адреса требует указания компонента хоста" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Схема URL-адреса не позволяет использовать компонент хоста" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Недопустимый компонент хоста \"%s\"" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Схема URL-адреса не позволяет использовать порт" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Недопустимый компонент порта \"%s\"" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Схема URL-адреса требует указания пути" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" +"При наличии компонентов авторизации относительные пути указывать нельзя" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Зашифрованная строка содержит байт со значением NULL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Недопустимый символ разделителя для разбиения массива параметров" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Недопустимый символ разделителя для разбиения отображения параметров" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Недопустимый символ разделителя для объединения массива параметров" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Команда завершилась с кодом %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Команда была прекращена сигналом %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Команда завершилась с неизвестной ошибкой." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Заданы неверные аргументы запуска." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Невозможно создать контролирующий канал." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Невозможно выполнить chroot в \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Невозможно сменить каталог на \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Невозможно сменить каталог на \"%s\" внутри среды chroot \"%s\" (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Невозможно выполнить exec \"%s\" (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Невозможно выполнить fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Невозможно выполнить '%s', chdir не удалась (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Невозможно выполнить '%s', chroot не удалась (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Невозможно выполнить '%s', exec не удался (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Невозможно выполнить '%s': неожиданная ошибка." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Не удалось смонтировать %s в %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Не удалось отмонтировать %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Некорректное имя файла: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "При попытке произведения действия \"%s\" не был открыт носитель." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Файл \"%s\" не найден на носителе \"%s\"" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Невозможно записать файл \"%s\"." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Носитель не присоединен" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Некорректная точка присоединения носителя" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Сбой инициализации загрузки (curl) для \"%s\"" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Системное исключение \"%s\" на носителе \"%s\"." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Путь \"%s\" на носителе \"%s\" не является файлом." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Путь \"%s\" на носителе \"%s\" не является каталогом." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Неправильно сформированный URI-адрес" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Пустое имя хоста в URI-адресе" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Пустая файловая система в URI-адресе" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Пустой пункт назначения в URI-адресе" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Неподдерживаемая схема URI-адреса в \"%s\"." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Операция не поддерживается носителем" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Ошибка загрузки (curl) \"%s\":\n" +"Код ошибки: %s\n" +"Сообщение об ошибке: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "Произошла ошибка при установке параметров загрузки (curl) для \"%s\":" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Источник носителей \"%s\" не содержит желаемого носителя" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Носитель\"%s\" используется другим экземпляром" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Невозможно извлечь ни один носитель" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Невозможно извлечь носитель \"%s\"" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Доступ к \"%s\" запрещен." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Превышено время ожидания при попытке доступа к \"%s\"." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Размер загруженных данных превысил ожидаемый '%s' из '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Расположение \"%s\" временно недоступно." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Проблема с сертификатом SSL, проверьте, все ли в порядке с удостоверяющим " +"центром сертификата \"%s\"." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Неподдерживаемый метод HTTP-аутентификации \"%s\"" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Ошибка скачивания (curl) для '%s':\n" +"Код ошибки: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Ошибка скачивания (curl) для '%s':\n" +"Не могу получить ответ по HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Да" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Нет" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Замечание:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Предупреждение:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Ошибка:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "готово" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "внимание" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "ошибка" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Предупреждение: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Получение:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "запуск" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "не найдено" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Для этого режима справка недоступна." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "для этого параметра справка недоступна" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "выводит все параметры" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "да" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "нет" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Выполнение скрипта %%posttrans \"%1%\"" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Выполнение скриптов %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "Пакет не подписан!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s не принадлежит репозиторию обновления дистрибутива" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s имеет худшую архитектуру" + +#~ msgid "problem with installed package %s" +#~ msgstr "проблема в установленном пакете %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "ничто не предоставляет запрошенный %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Включили ли вы все требуемые репозитории?" + +#~ msgid "package %s does not exist" +#~ msgstr "пакет %s не существует" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s предоставляется системой и не может быть удален" + +#~ msgid "%s is not installable" +#~ msgstr "%s недоступен для установки" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "ничто не предоставляет %s, необходимый для %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "Не удается установить оба %s и %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s конфликтует с %s, который предоставляется %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s делает устаревшим %s, предоставляемый %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "установленный пакет %s делает устаревшим %s, предоставляемый %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "" +#~ "объект разрешения зависимостей %s конфликтует с %s, который " +#~ "предоставляется им самим" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s требует %s, но это требование не может быть удовлетворено" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "удалить блокировку для удаления %s" + +#~ msgid "do not install %s" +#~ msgstr "не устанавливать %s" + +#~ msgid "keep %s" +#~ msgstr "оставить %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "удалить блокировку для установки %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "" +#~ "не просить установить объект разрешения зависимостей, предоставляющий %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "" +#~ "не просить удалить все объекты разрешения зависимостей, предоставляющие %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "не устанавливать самую последнюю версию %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "оставить %s, несмотря на смену архитектуры" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "установить %s, несмотря на смену архитектуры" + +#~ msgid "keep obsolete %s" +#~ msgstr "оставить устаревший %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "установить %s из исключенного репозитория" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "обновить %s до более старой версии %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "изменение архитектуры %s на %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "установить %s (со сменой поставщика)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "замена %s на %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "удаление %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Невозможно открыть файл блокировки: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Это действие уже выполняется другой программой." + +#~ msgid "Hal Exception" +#~ msgstr "Исключение Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Увы, данная версия libzypp была собрана без поддержки HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext не подключен" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive не инициализирован" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume не инициализирован" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Не удалось установить соединение с dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: не удается создать контекст libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: не удалось установить соединение с dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Не удалось инициализировать контекст HAL – не запущен hald?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Не привод CD-ROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Невозможно инициализировать атрибуты взаимного исключения" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Невозможно установить атрибут рекурсивного взаимного исключения" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Не удается инициализировать рекурсивное взаимоисключение" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Не удается получить блокировку взаимоисключения" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Не удается освободить блокировку взаимоисключения" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Не удалось импортировать публичный ключ из файла %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Не удалось удалить публичный ключ %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Невозможно найти доступное loop-устройство для монтирования файла образа " +#~ "из '%s'" + +#~ msgid "generally ignore of some dependecies" +#~ msgstr "игнорировать некоторые зависимости везде" + +#~ msgid "do not keep %s installed" +#~ msgstr "не оставлять установленным %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "Невозможно записать публичный ключ %s из хранилища %s в файл %s" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "Попытка импорта несуществующего ключа %s в хранилище ключей %s" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Невозможно выполнить chdir в '/' внутри среды chroot (%s)." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "Сбой инициализации загрузки (Metalink curl) для '%s'" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Ошибка загрузки (metalink curl) для '%s':\n" +#~ "Код ошибки: %s\n" +#~ "Сообщение об ошибке: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Загрузка прервана на %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "Загрузка прервана пользователем" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Произошла ошибка при установке параметров загрузки (metalink curl) для " +#~ "'%s':" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Не удалось загрузить %s с %s" diff --git a/po/si.po b/po/si.po new file mode 100644 index 0000000..5e37ea8 --- /dev/null +++ b/po/si.po @@ -0,0 +1,5254 @@ +# Sinhala message file for YaST2 (@memory@). +# Copyright (C) 2007 SUSE Linux Products GmbH. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2005-07-29 15:37+0530\n" +"Last-Translator: i18n@suse.de\n" +"Language-Team: Sinhala \n" +"Language: si\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" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +#, fuzzy +msgid "Netherlands Antilles" +msgstr "නෙදර්ලන්තය" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "බෙල්ජියම" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +#, fuzzy +msgid "Switzerland" +msgstr "නෙදර්ලන්තය" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "ජර්මනිය" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "ඩෙන්මාර්කය" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "පින්ලන්තය" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +#, fuzzy +msgid "Faroe Islands" +msgstr "අයර්ලන්තය" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "එක්සත් රාජධානිය" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "ජර්මනිය" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +#, fuzzy +msgid "Greenland" +msgstr "අයර්ලන්තය" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "ග්‍රිසිය" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "හන්ගේරියාව" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "අයර්ලන්තය" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +#, fuzzy +msgid "Iceland" +msgstr "අයර්ලන්තය" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +#, fuzzy +msgid "North Korea" +msgstr "උතුරු අයර්ලන්තය" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "ලක්සන්බර්ග්" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "මෝල්ඩෝව" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +#, fuzzy +msgid "Northern Mariana Islands" +msgstr "උතුරු අයර්ලන්තය" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +#, fuzzy +msgid "Norfolk Island" +msgstr "උතුරු අයර්ලන්තය" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "නෙදර්ලන්තය" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +#, fuzzy +msgid "New Zealand" +msgstr "නෙදර්ලන්තය" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +#, fuzzy +msgid "Poland" +msgstr "පින්ලන්තය" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "පෘතුගාලය" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "රුමෙනියාව" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "ස්ලෝවෙනියාව" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "ස්ලෝවැකියාව" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +#, fuzzy +msgid "Swaziland" +msgstr "පින්ලන්තය" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +#, fuzzy +msgid "Thailand" +msgstr "පින්ලන්තය" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "තුර්කිය" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "යුක්රේනය" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "උතුරු අයර්ලන්තය" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +#, fuzzy +msgid "German" +msgstr "ජර්මනිය" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +#, fuzzy +msgid "Hungarian" +msgstr "හන්ගේරියාව" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +#, fuzzy +msgid "Icelandic" +msgstr "අයර්ලන්තය" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "ලක්සන්බර්ග්" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "මෝල්ඩෝව" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +#, fuzzy +msgid "North American Indian" +msgstr "උතුරු අයර්ලන්තය" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "ජර්මනිය" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +#, fuzzy +msgid "Northern Sotho" +msgstr "උතුරු අයර්ලන්තය" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +#, fuzzy +msgid "Portuguese" +msgstr "පෘතුගාලය" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "රුමෙනියාව" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +#, fuzzy +msgid "Romanian" +msgstr "රුමෙනියාව" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +#, fuzzy +msgid "Slovak" +msgstr "ස්ලෝවැකියාව" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +#, fuzzy +msgid "Slovenian" +msgstr "ස්ලෝවෙනියාව" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +#, fuzzy +msgid "Northern Sami" +msgstr "උතුරු අයර්ලන්තය" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "තුර්කිය" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +#, fuzzy +msgid "Turkish" +msgstr "තුර්කිය" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +#, fuzzy +msgid "Ukrainian" +msgstr "යුක්රේනය" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Couldn't open file: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Couldn't open file: %s." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Couldn't open file: %s." + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Couldn't open file: %s." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." diff --git a/po/sk.po b/po/sk.po new file mode 100644 index 0000000..31ca4b8 --- /dev/null +++ b/po/sk.po @@ -0,0 +1,5505 @@ +# Copyright (C) YEAR SuSE Linux GmbH, Nuernberg +# This file is distributed under the same license as the PACKAGE package. +# Ferdinand Galko , 2015, 2016. +msgid "" +msgstr "" +"Project-Id-Version: libzypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-15 21:47+0000\n" +"Last-Translator: Ferdinand Galko \n" +"Language-Team: Slovak " +"\n" +"Language: sk\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: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Neznáma krajina: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Žiadny kód" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Spojené Arabské Emiráty" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua a Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albánsko" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Arménsko" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Holandské Antily" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktída" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentína" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Americká Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Rakúsko" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Austrália" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Alandské ostrovy" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbajdžan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosna a Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladéš" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgicko" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulharsko" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrajn" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudy" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolívia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazílsky" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamy" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhután" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvetov ostrov" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Bielorusko" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosové (Keeling) ostrovy" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Stredoafrická Republika" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Švajčiarsko" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Pobrežie Slonoviny" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookove ostrovy" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Čile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Čína" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kostarika" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kapverdy" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Vianočne ostrovy" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cyprus" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Česká Republika" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Nemecko" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Džibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Dánsko" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikánska republika" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alžírsko" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvádor" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estónsko" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Západná Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Španielsko" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiópia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Fínsko" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandské ostrovy (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federácia Mikronézskych štátov" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faerské ostrovy" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francúzsko" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Metropolitné Francúzsko" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Spojené kráľovstvo" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Granada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gruzínsko" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Francúzska Guana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltár" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grónsko" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Rovníková Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grécko" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Južná Georgia a Južné Sandwichove ostrovy" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heardov ostrov a Macdonaldové ostrovy" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Chorvátsko" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Maďarsko" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonézia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Írsko" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Ostrov Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britská oblasť Indického oceánu" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irak" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Taliansko" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamajka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordánsko" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonsko" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Keňa" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgizsko" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodža" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komory" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Svätý Kitts a Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Severná Kórea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Južná Kórea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuvajt" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kaimanské ostrovy" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazachstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Ľudová Demokratická Republika Laos" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Svätá Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Lichtenštajnsko" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Srí Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Libéria" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litva" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembursko" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Lotyšsko" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Líbya" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavsko" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Čierna hora" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Svätý Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshallove ostrovy" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedónsko" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mjanmarsko" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolsko" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Severné ostrovy Mariana" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinik" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritánia" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Maurícius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldivy" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malajzia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namíbia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nová Kaledónia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolské ostrovy" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigéria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Holandsko" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Nórsko" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepál" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nový Zéland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Omán" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Francúzska Polynézia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nová Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipíny" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poľsko" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Svätý Pierre a Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairnove ostrovy" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Portoriko" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestínske teritórium" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugalsko" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguaj" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumunsko" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Srbsko" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Ruská Federácia" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudská Arábia" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomon ostrovy" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychely" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudán" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Švédsko" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Svätá Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovinsko" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard a Jan Mayen ostrovy" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovensko" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Maríno" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somálsko" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome a Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Salvádor" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Sýria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swazijsko" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Ostrovy Turks a Caicos" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Čad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Južné Francúzske teritóriá" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thajsko" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkménsko" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisko" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Východný Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turecko" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad a Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tajwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzánia" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrajina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Spojené Štáty Minor Outlying ostrovy" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Spojené Štáty" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguaj" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Mestský Štát Vatikán" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Svätý Vincent a Grenadíny" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britské Panenské ostrovy" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Panenské ostrovy, U.S." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis a Futuna ostrovy" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Južná Afrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Poskytuje" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Predpokladá" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Vyžaduje" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Je v konflikte" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Zastarané" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Odporúča" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Navrhuje" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Zlepšuje" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Doplnky" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Pokus o importovanie neexistujúceho kľúča %s do zväzku kľúčov %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Nepodarilo sa importovať kľúč." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Nepodarilo zmazať kľúč." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Súbor podpisu %s nebol nájdený" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Neznámy jazyk: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afarčina" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abcházčina" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Acehčina" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Ačoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adygčina" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Ázijský (ostatné)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihikli" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikánsky" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadčina" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albánsky" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleuty" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonkské jazyky" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Južný Altai" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharic" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Staroanglický (r. 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apačské jazyky" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabský" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramejčina" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonese" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Arménsky" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araukánčina" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Umelý (ostatné)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawačtina" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamský" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Rakúsky" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athabaské jazyky" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Austrálske jazyky" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarský" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestský jazyk" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymarčina" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Ázerbajdžánsky" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Balúdžtina" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balijčina" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskitský" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltický (ostatné)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Bedža" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bieloruský" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengálsky" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berber (ostatné)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhódžpurčina" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Biharčina" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikolčina" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (ostatné)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosniansky" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Bradžčina" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretónsky" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "(Batak) Indonézia" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buriatčina" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginčina" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulharský" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmese" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Kaddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Stredoamerický Indiánsky (ostatné)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Karibský" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalánsky" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukazský (ostatné)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuánčina" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltský (ostatné)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Čibský" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Čečenský" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Čagatajský" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Čínsky" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Čukský" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Maríjčina" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Činucký žargón" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Čipeva" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Čerokézčina" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Cirkevný slovanský" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Čuvaština" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Čejenský" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Čamaské jazyky" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptčina" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornish" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korzický" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creoles a Pidgins, anglické (ostatné)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creoles a Pidgins, francúzske (ostatné)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creoles a Pidgins, Portugalské (ostatné)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krimský tatársky" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creoles a Pidgins (ostatné)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kašubský" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Cushitic (ostatné)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Český" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakotský" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Dánsky" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Darginčina" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dajačtina" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidian (ostatné)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Dolná lužická srbčina" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Holandský, stredoveký (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Holandský" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Djula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Egyptský (starobylý)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekadžuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamčina" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Anglický" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Anglický stredoveký (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estónsky" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faroese" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fidžský" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipínsky" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Fínsky" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fínsko-uhorský (ostatné)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fončina" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francúzsky" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francúzsky starý (r. 842-1400)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francúzsky stredný (r. 1400-1600)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frízsky" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Frízsky" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaja" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Nemecký (ostatné)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Gruzínsky" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Nemecký" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Ge´ez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Kiribatčina" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaelic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Írsky" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galícijský" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Mančina" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Nemecký (r. 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Nemecký (r. 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotický" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grécky starobylý (do r. 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grécky moderný (od r. 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitian" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Havajský" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebrejský" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligajnončina" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himachálsky" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Chetitčina" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Hornosrbský" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Maďarský" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandský" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Idžo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indický (ostatné)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonézsky" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoeurópsky (ostatné)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Inguština" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iránsky (ostatné)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokézske jazyky" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Taliansky" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Jávsky" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonský" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Židovsko-Perzský" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Židovsko-Arabský" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpačtina" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabylčina" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kačjinčina" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Grónčina" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karenčina" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kašmírsky" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazašský" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardčina" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasijčina" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khojsánske jazyky (iné)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Kotčina" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuju" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgizský" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkánčina" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komijčina" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Konžský" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Kórejský" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kusaie" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukhčina" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuaňama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumytčina" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdský" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladinčina" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahandčina" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latinský" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Lotyšský" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezginčina" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgan" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litovský" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburský" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-luluánčina" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseňo" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Keňa a Tanzánia)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lušáí" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedónsky" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurčina" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahí" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallove ostrovy" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasarčina" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronézsky (ostatné)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malajský" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandarčina" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Írsky stredný (r. 900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mikman" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabaučina" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Rôzne jazyky" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Khmer (ostatné)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagasy" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltézsky" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Mandžuština" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobo jazyky" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldavský" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongolský" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mosi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Viaceré jazyky" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Mundské jazyky" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Muskogi" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Májske jazyky" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Severoamerický Indiánsky" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitan" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele (Južná Afrika)" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele (Zimbabwe)" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Dolnonemčina" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepálsky" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepál Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Nigérisjko-Kordofanský (ostatné)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niueština" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Nórsky Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Nórsky Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogidalčina" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Norse, starý" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Nórsky" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Severné Sotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubijiské jazyky" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Classical Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Ňandža" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Ňamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Ňankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Ňoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (post 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Odžibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromčina" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turecký, Ottoman (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Oto-pameské jazyky" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papujský (ostatné)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlaví" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampangan" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Pandžábčina" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palaučina" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Perzský starý (r. 600-400 p.n.l.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Perzský" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipíny (ostatné)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Péničtina" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pálí" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Poľský" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeičina" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugalský" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakritské jazyky" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provensálsky, starý (do 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Kečuánčina" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Radžastanský" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanujčina" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongčina" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romance (ostatné)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Rétorománčina" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Rómčina" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumunský" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ruský" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Juhoamerický Indiánsky (ostatné)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Sališské jazyky" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritánska aramejčina" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrt" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasačtina" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Srbský" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicílsky" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Chorvátsky" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkupčina" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitský (ostatné)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Írsky starý (do r. 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Znakové jazyky" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Šančina" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouské jazyky" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-tibetský (ostatné)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slovanský (ostatné)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovenský" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovinský" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Južné Sami" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Severné Sami" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Samské jazyky (ostatné)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Inari Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samojčina" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Šona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdčina" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somálsky" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Soto" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Španielsky" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardínsky" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nílsko-Saharský" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundánsky" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumérsky" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Svahilský" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Švédsky" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Sýrčina" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitský" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Tai (ostatné)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamilský" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatársky" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thajský" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetský" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingónsky" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamašek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tongčina (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tongské ostrovy)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshijské jazyky" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Čwančina" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkménsky" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Jazyky tupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turecký" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altajské jazyky" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuviančina" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurtčina" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritčina" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrajinský" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Neurčený" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbecký" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamský" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Vodčina" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakašské jazyky" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamčina" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Welšský" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Srbské jazyky" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmyčtina" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Japčina" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Judejský" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupické jazyky" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotéčtina" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Čuangčina" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Budú vykonané nasledovné akcie:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "nevyprší" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "vypršal: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "vyprší: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(nevyprší)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(VYPRŠANÉ)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(vyprší do 24h)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(vyprší za %d deň)" +msgstr[1] "(vyprší za %d dni)" +msgstr[2] "(vyprší za %d dní)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "neznámy" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nepodporovaný" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Úroveň 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Úroveň 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Úroveň 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Je potrebná ďalšia Zákaznícka Zmluva" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Ukončené a nahradené iným balíkom" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "chybný" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Úroveň podpory nie je určená" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Dodávateľ neposkytuje podporu." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Určenie problému, teda technická podpora zameraná na poskytovanie informácií " +"o kompatibilite, pomoc pri inštalácii, pomoc pri používaní, nepretržitú " +"údržbu a základnú pomoc pri riešení problémov. Podpora Úrovne 1 nie je " +"určená na opravu chýb produktu." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Izolácia problému, teda technická podpora zameraná na reprodukovanie " +"problémov zákazníka, vymedzenie problémovej oblasti a poskytovanie riešenia " +"problémov nevyriešených Podporou Úrovne 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Riešenie problému, teda technická podpora zameraná na riešenie zložitých " +"problémov za pomoci odborníkov pri riešení chýb produktu, ktoré boli " +"identifikované Podporou Úrovne 2." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Pre poskytovanie podpory je potrebná ďalšia zákaznícka zmluva." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "Balík bol ukončený a nahradil ho nový balík s iným názvom." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Neznáma voľba podpory. Popis nie je k dispozícii" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Správa softvéru je uzamknutá inou aplikáciou s pid %d (%s).\n" +"Ukončite najprv túto aplikáciu a skúste znova." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Neznámy režim zhody '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Neznámy režim zhody '%s' pre šablónu '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Neplatný regulárny výraz '%s': regcomp vrátil %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Neplatný regulárny výraz '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "'%s' vyžaduje autentifikáciu" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Skúste to znova..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Vzdanie sa po %1 % pokusoch." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Navštívte SUSE Customer Center, aby ste skontrolovali, či je vaša " +"registrácia platná a ešte nevypršala." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Navštívte Novell Customer Center, aby ste skontrolovali, či je vaša " +"registrácia platná a ešte nevypršala." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Vytvoriť prípojný bod: Nie je možné nájsť zapisovateľný adresár pre " +"vytvorenie prípojného bodu" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Prosím, najskôr nainštalujte balík 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Nie je možné vytvoriť adresár vyrovnávacej pamäte metadát." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Chyba pri čítaní z '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Nie je možné vytvoriť %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Na stanovenej adrese URL sa nenašli platné metadáta" +msgstr[1] "Na stanovených adresách URL sa nenašli platné metadáta" +msgstr[2] "Na stanovených adresách URL sa nenašli platné metadáta" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" +"Nepodarilo sa uložiť repozitár do vyrovnávacej pamäte ( nie je možné spustiť " +"repo2solv )." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Zlyhalo ukladanie do vyrovnávacej pamäti pre repozitár (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Vytváram vyrovnávaciu pamäť repozitára '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" +"Nie je možné vytvoriť vyrovnávaciu pamäť v %s - žiadne práva na zapisovanie." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "Nepodarilo sa uložiť do vyrovnávacej pamäte repozitár %1%" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Nepodporovaný typ repozitára" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Pridávam repozitár '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Neplatný názov súboru repozitára v '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Nemôžem otvoriť súbor '%s' pre zápis." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Neznáma chyba čítania z '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Nie je možné čítať adresár repozitára '%1%': Prístup zamietnutý" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Zlyhalo čítanie adresára '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Nie je možné čítať súbor repozitára '%1%': Prístup zamietnutý" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "Vymazávanie metadát" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "Vymazávanie balíkov" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "Vymazanie adresárov vyrovnávacej pamäte" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "Vymazanie adresára: %1%" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "Vymazávanie vyrovnávacej pamäte" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "Načítavanie z vyrovnávacej pamäte" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Odstraňujem repozitár '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Nie je možné prísť na to, kde je uložený repozitár." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Nie je možné vymazať '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "Úprava repozitára" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "Obnovenie repozitára: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Nie je možné prísť na to, kde je uložená služba." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Neznámá služba '%1%': Odstraňovanie osirelého repozitára služby '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Alias repozitára nemôže začínať bodkou." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Alias služby nemôže začínať bodkou." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Žiadny prehľad pre súbor %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Neznámy prehľad %s pre súbor %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Overenie prehľadu zlyhalo pre súbor '%s'" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Súbor '%s' nie je podpísaný, pokračovať?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Súbor '%s' z repozitára '%s' nie je podpísaný. Pokračovať?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Prajete si tento kľúč odmietnuť, prijať dočasne alebo prijať natrvalo?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Názov kľúča: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "Bol prijatý %1% nový podpisový kľúč balíkov z repozitára \"%2%\":" +msgstr[1] "Boli prijaté %1% nové podpisové kľúče balíkov z repozitára \"%2%\":" +msgstr[2] "" +"Bolo prijatých %1% nových podpisových kľúčov balíkov z repozitára \"%2%\":" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Overenie podpisu súboru '%1%' zlyhalo." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "Overenie podpisu súboru '%1%' z repozitára '%2%' zlyhalo." + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Pokračovať?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Súbor '%s' je podpísaný neznámym kľúčom '%s'. Pokračovať?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Súbor '%s' z repozitára '%s' je podpísaný neznámym kľúčom '%s'. Pokračovať?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Repozitár %1% nedefinuje dodatočné URL 'gpgkey='." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Hľadanie ID gpg kľúča %1% v repozitári %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Hľadanie ID gpg kľúča %1% vo vyrovnávacej pamäti %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Chýba vyžadovaný atribút '%s' ." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Jeden alebo oba z atribútov '%s' alebo '%s' sú vyžadované." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Overenie podpisu zlyhalo" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Balík %s sa počas sťahovania pravdepodobne poškodil. Chcete sa znova pokúsiť " +"o jeho stiahnutie?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Zlyhalo poskytnutie Balíka %s. Chcete sa pokúsiť o znovuzískanie?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Kontrola aplikovania delta rpm zlyhala." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "Aplikovanie delta rpm zlyhalo." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Zásuvný modul služby nepodporuje zmenu atribútu." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Nemôžem poskytnúť súbor '%s' z repozitára '%s'" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Pre tento repozitár nie je definovaná žiadna URL adresa." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "Očakávané médium% 1%/%2% identifikované podľa súboru '%3%' s obsahom:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Súbor %1%\n" +" z balíka\n" +" %2%\n" +" je v konflikte so súborom z balíka\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Súbor %1%\n" +" z balíka\n" +" %2%\n" +" je v konflikte so súborom inštalovaným z\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Súbor %1%\n" +" inštalovaný z\n" +" %2%\n" +" je v konflikte so súborom z balíka\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Súbor %1%\n" +" inštalovaný z\n" +" %2%\n" +" je v konflikte so súborom inštalovaným z\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Súbor %1%\n" +" z balíka\n" +" %2%\n" +" je v konflikte so súborom\n" +" %3%\n" +" z balíka\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Súbor %1%\n" +" z balíka\n" +" %2%\n" +" je v konflikte so súborom\n" +" %3%\n" +" inštalovaným z\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Súbor %1%\n" +" inštalovaný z\n" +" %2%\n" +" je v konflikte so súborom\n" +" %3%\n" +" z balíka\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Súbor %1%\n" +" inštalovaný z\n" +" %2%\n" +" je v konflikte so súborom\n" +" %3%\n" +" inštalovaným z\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Nepodarilo sa vytvoriť sat-pole." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "porušiť %s ignorovaním niektorých závislostí" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "všeobecne ignorovať niektoré závislosti" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"nainštalovaný %1% nepatrí do repozitára zvýšenia verzie distribúcie a musí " +"byť nahradený" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" +"%1%, ktorý sa má inštalovať, nepatrí do repozitára zvýšenia verzie " +"distribúcie" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "nainštalovaný %1% má nižšiu architektúru" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "%1%, ktorý sa má inštalovať, má nižšiu architektúru" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problém s nainštalovaným %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "protichodné požiadavky" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "problém so závislosťami" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "nič neposkytuje požadovaný '%1%'" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Máte povolené všetky požadované repozitáre?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "požadovaný balík %1% neexistuje" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "nepodporovaná požiadavka" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' poskytuje systém a nemôže sa vymazať" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% nie je inštalovateľný" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "nič neposkytuje '%1%', ktorý je potrebný pre nainštalovaný %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" +"nič neposkytuje '%1%', ktorý je potrebný pre %2%, ktorý sa má inštalovať" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "nie je možné nainštalovať obidva %1% aj %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"nainštalovaný %1% je v konflikte s '%2%', ktorý poskytuje nainštalovaný %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"nainštalovaný %1% je v konflikte s '%2%', ktorý poskytuje %3%, ktorý sa má " +"inštalovať" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"%1%, ktorý sa má inštalovať, je v konflikte s '%2%', ktorý poskytuje " +"nainštalovaný %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"%1%, ktorý sa má inštalovať, je v konflikte s '%2%', ktorý poskytuje %3%, " +"ktorý sa má inštalovať" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "nainštalovaný %1% zastaráva '%2%', ktorý poskytuje nainštalovaný %3%" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"nainštalovaný %1% zastaráva '%2%', ktorý poskytuje %3%, ktorý sa má " +"inštalovať" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"%1%, ktorý sa má inštalovať, zastaráva '%2%', ktorý poskytuje nainštalovaný " +"%3%" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"%1%, ktorý sa má inštalovať, zastaráva '%2%', ktorý poskytuje %3%, ktorý sa " +"má inštalovať" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "nainštalovaný %1% je v konflikte s '%2%', ktorý poskytuje sám" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"%1%, ktorý sa má inštalovať, je v konflikte s '%2%', ktorý poskytuje sám" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"nainštalovaný %1% vyžaduje '%2%', ale túto požiadavku nie je možné splniť" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"%1%, ktorý sa má inštalovať, vyžaduje '%2%', ale túto požiadavku nie je " +"možné splniť" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "zmazaný poskytovatelia: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"neinštalovateľní poskytovatelia: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "neinštalovateľní poskytovatelia: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% ešte nie je úplne integrované do %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Zvyčajne chcete zachovať PTF a rozhodnete sa neinštalovať údržbové opravy." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Odstránenie nainštalovaného %1% v tomto kontexte odstráni (nie nahradí!) aj " +"zahrnuté PTF balíky." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"PTF by sa malo odstrániť volaním '%1%'. Tým sa aktualizujú zahrnuté PTF " +"balíky namiesto ich odstránenia." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Zvyčajne si chcete ponechať PTF alebo sa rozhodnúť zrušiť akciu." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Nainštalované %1% blokuje požadovanú akciu." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Zvyčajne chcete zachovať PTF a rozhodnete sa zrušiť akciu." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "odstrániť zámok pre umožnenie odstránenia %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "neinštalovať %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "ponechať %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "odstrániť zámok pre umožnenie inštalácie %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Tento požiadavka poruší váš systém!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorovať varovanie o porušení systému" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "nepožadovať inštaláciu riešenia, ktoré poskytuje %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "nepožadovať zmazanie všetkých riešení, ktoré poskytuje %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "neinštalovať najnovšiu verziu %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "ponechať %1% napriek nižšej architektúre" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "nainštalovať %1% napriek nižšej architektúre" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "ponechať zastaraný %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "inštalovať %1% z vylúčeného repozitára" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "inštalovať %1%, aj keď bol stiahnutý späť" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "umožniť inštaláciu PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "inštalovať %1%, aj keď je nežiadúci" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "znížiť verziu %1% na %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "zmena architektúry %1% na %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"inštalovať %1% (so zmenou dodávateľa)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"inštalovať %1% od dodávateľa %2%\n" +" nahradenie %3% od dodávateľa %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "nahradenie %1% s %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "odinštalovanie %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Spustenie skriptov po transakcii" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Spustenie skriptu %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Výstup skriptu %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Inštalácia bola podľa príkazu zrušená." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " spustený" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " spustenie zlyhalo" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s už spustený ako %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " spustenie odložené kvôli prerušeniu programu" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Chyba zasielania oznámenia o aktualizačnej správe." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nová správa aktualizácie" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Prijatý signál :\"%1% (%2%)\", na zabezpečenie konzistentnosti systému nie " +"je možné zrušiť prebiehajúcu rpm transakciu." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Vykonanie transakcie zlyhalo z dôvodu nasledujúcich problémov:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM zlyhalo: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Nepodarilo sa importovať verejný kľúč %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Nepodarilo zmazať verejný kľúč %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Hlavička balíka nie je podpísaná!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Príloha balíka nie je podpísaná!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Zmenené konfiguračné súbory pre '%s':" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "Balík rpm uložil %s ako %s, ale nebolo možné určiť rozdiel" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"Balík rpm uložil %s ako %s.\n" +"Tu je prvých 25 riadkov rozdielov:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "Balík rpm vytvoril %s as %s, ale nebolo možné určiť rozdiel" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"Balík rpm vytvoril %s as %s.\n" +"Tu je prvých 25 riadkov rozdielov:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Ďalší výstup z rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "Bola vytvorená záloha %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Podpis je v poriadku" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Neznámy typ podpisu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Podpis neoveruje" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Podpis je v poriadku, ale kľúč nie je dôveryhodný" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Verejný kľúč podpisov nie je k dispozícii" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Súbor neexistuje alebo podpis nie je možné overiť" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Súbor je nepodpísaný" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Pochybný typ '%s' pre %u bajtový kontrolný súčet '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Nie je možné otvoriť pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Nie je možné otvoriť rúru (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Neplatný query string v URL pre LDAP" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Neplatný parameter dopytu LDAP URL '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Daný URL objekt nie je možne klonovať" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Neplatný odkaz na prázdny URL objekt" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Nie je možné prečítať zložky URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "História:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Zadaná URL schéma nepovoľuje %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "%s obsahuje neplatnú položku '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "%s obsahuje neplatnú položku" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Query string nie je pre túto URL povolený" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Schéma URL je povinná" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Neplatný názov URL schémy: '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Daná URL schéma nepovoľuje meno používateľa" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Daná URL schéma nepovoľuje heslo" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Daná URL schéma vyžaduje názov hostiteľského počítača (host component)" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" +"Daná URL schéma nepovoľuje názov hostiteľského počítača (host component)" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Neplatný názov počítača '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Daná URL schéma nepovoľuje port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Neplatný port '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Daná URL schéma vyžaduje zadanú cestu" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relatívna cesta nie je povolená v prípade, že je zadaná autorita" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Zakódovaný reťazec obsahuje NUL bajt" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Neplatný oddeľovací znak pre pole parametrov" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Neplatný oddeľovací znak pre mapu parametrov" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Neplatný oddeľovací znak pre spájanie poľa parametrov" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Stav príkazu po skončení je %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Príkaz bol zabitý signálom %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Príkaz skončil s neznámou chybou." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Zadané nesprávne argumenty spawn." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Nie je možné vytvoriť riadiacu rúru." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Nemôžem spraviť chroot do '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Nie je možné vykonať chroot pre '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Nie je možné vykonať chdir pre '%s' vo vnútri chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Nemôžem spustiť '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Nemôžem spraviť rozdelenie programu (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Nemožno vykonať '%s', chdir zlyhal (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Nemožno vykonať '%s', chroot zlyhal (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Nemožno vykonať '%s', exec zlyhal (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Nemožno vykonať '%s', neočakávaná chyba." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Nepodarilo sa pripojiť %s na %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Nepodarilo sa odpojiť %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Nesprávne meno súboru: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Médium sa neotvorilo pri pokuse vykonať '%s'." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Súbor '%s' nebol nájdený na médiu '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Nemôžem zapísať súbor '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Médium nie je pripojené" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Nesprávny prípojný bod média" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Zlyhala inicializácia sťahovania (curl) pre '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Systémová výnimka '%s' na médiu '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Cesta '%s' na médiu '%s' nie je súborom." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Cesta '%s' na médiu '%s' nie je adresárom." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Chybné URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Prázdny názov hostiteľa v URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Prázdny súborový systém v URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Prázdny cieľ v URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Nepodporovaná schéma URI v '%s'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operácie nie je médiom podporovaná" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Chyba sťahovania (curl) pre '%s':\n" +"Kód chyby: %s\n" +"Chybová správa: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Vyskytla sa chyba počas nastavovania možností sťahovania (curl) pre '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Zdroj média '%s' neobsahuje požadované médium" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Médium '%s' už používa iná inštancia" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Nemôžem vysunúť žiadne médium" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Nemôžem vysunúť médium '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Zamietnutý prístup na '%s'." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Vypršal časový limit pri prístupe na '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Stiahnuté dáta prekročili očakávanú veľkosť súboru '%s' z '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Umiestnenie '%s' je dočasne nedostupné." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" problém s certifikátom SSL, skontrolujte či certifikát CA je v poriadku pre " +"'%s'." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Na pripojenie média nie sú k dispozícii žiadne voľné zdroje." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "'%s' nie je podporovaná metóda autentifikácie" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Chyba sťahovania (curl) pre '%s':\n" +"Kód chyby: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Chyba sťahovania (curl) pre '%s':\n" +"Odpoveď HTTP sa nepodarilo načítať\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Áno" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nie" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Poznámka:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Varovanie:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Chyba:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "hotovo" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "pozor" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "chyba" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Pozor: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Sťahuje sa:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "štartovanie" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "nenájdené" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Pre túto výzvu nie je k dispozícii pomocník." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "pre túto voľbu nie je k dispozícii pomocník" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "ukazuje všetky voľby" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "áno" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nie" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Vykonávanie %%posttrans skriptu '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Vykonávanie %p osttrans skriptov" + +#~ msgid "Package is not signed!" +#~ msgstr "Balík nie je podpísaný!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s nepatrí do repozitára zvýšenia verzie distribúcie" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s má nižšiu architektúru" + +#~ msgid "problem with installed package %s" +#~ msgstr "Problém s nainštalovaným balíkom %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "nič neposkytuje požadovaný %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Máte povolené všetky požadované repozitáre?" + +#~ msgid "package %s does not exist" +#~ msgstr "balík %s neexistuje" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s poskytuje systém a nemôže sa vymazať" + +#~ msgid "%s is not installable" +#~ msgstr "%s nie je inštalovateľný" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "nič neposkytuje %s, ktorý je potrebný pre %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "nie je možné nainštalovať obidva %s aj %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s je v konflikte s %s poskytovaným %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s zastaráva %s, ktorý poskytuje %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "nainštalovaný %s zastaráva %s, ktorý poskytuje %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "Riešenie %s je v konflikte s %s, ktorý poskytuje sám" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s vyžaduje %s, ale túto požiadavku nie je možné splniť" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "odstrániť zámok pre umožnenie odstránenia %s" + +#~ msgid "do not install %s" +#~ msgstr "neinštalovať %s" + +#~ msgid "keep %s" +#~ msgstr "ponechať %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "odstrániť zámok pre umožnenie inštalácie %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "nepožadovať inštaláciu riešenia, ktoré poskytuje %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "nepožadovať zmazanie všetkých riešení, ktoré poskytuje %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "neinštalovať najnovšiu verziu %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "ponechať %s napriek nižšej architektúre" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "nainštalovať %s napriek nižšej architektúre" + +#~ msgid "keep obsolete %s" +#~ msgstr "ponechať zastaraný %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "inštalovať %s z vylúčeného repozitára" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "znížiť verziu %s na %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "zmena architektúry %s na %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "inštalovať %s (so zmenou dodávateľa)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "nahradenie %s s %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "odinštalovanie %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Nie je možné otvoriť súbor so zámkom: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Táto akcia je už spustená iným programom." + +#~ msgid "Hal Exception" +#~ msgstr "Výnimka Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Prepáčte, ale táto verzia libzypp bola zostavená bez podpory HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext nie je pripojený" + +#~ msgid "HalDrive not initialized" +#~ msgstr "Jednotka HalDrive nie je inicializovaná" + +#~ msgid "HalVolume not initialized" +#~ msgstr "Jednotka HalVolume nie je inicializovaná" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Nie je možné vytvoriť spojenie pomocou dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Nie je možné vytvoriť libhal context" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: Nie je možné nastaviť spojenie s dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Nie je možné inicializovať HAL kontext -- je spustený hald?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Nie je CDROM mechanika" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Nemôžem inicializovať mutex atribúty" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Nemôžem nastaviť rekurzívny mutex" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Nemôžem inicializovať rekurzívny mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Nepodarilo sa získať mutex zámok" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Nemôžem uvoľniť mutex zámok" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Nepodarilo sa importovať verejný kľúč zo súboru %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Nepodarilo zmazať verejný kľúč %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Nie je možné nájsť dostupné loop zariadenie na pripojenie súboru obrazu z " +#~ "'%s'" diff --git a/po/sl.po b/po/sl.po new file mode 100644 index 0000000..4cec7d0 --- /dev/null +++ b/po/sl.po @@ -0,0 +1,6067 @@ +# Slovenian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2001 SuSE GmbH. +# Janez Krek , 2001. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-15 17:47+0000\n" +"Last-Translator: Jure Repinc \n" +"Language-Team: Slovenian \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=2; plural=(n != 1);\n" +"X-Generator: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Neznana država: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Brez kode" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andora" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Združeni arabski emirati" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigva in Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Angvila" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanija" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenija" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Nizozemski Antili" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktika" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Ameriška Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Avstrija" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Avstralija" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Alandski otoki" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbajdžan" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosna in Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladeš" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgija" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bolgarija" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrajn" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunej" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivija" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazilija" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahami" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Butan" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvetov otok" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botsvana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belorusija" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosovi (Keelingovi) otoki" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Srednjeafriška republika" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Švica" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Slonokoščena obala" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cookovi otoki" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Čile" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kitajska" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbija" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kostarika" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Zelenortski otoki" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Božični otok" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Ciper" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Češka republika" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Nemčija" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Džibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danska" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominika" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikanska republika" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alžirija" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonija" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipt" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Zahodna Sahara" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritreja" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Španija" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopija" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finska" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandski otoki" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Združene države Mikronezije" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Ferski otoki" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francija" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Metropolitanska Francija" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Združeno kraljestvo" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gruzija" + +# Shouldn't this be French Guyane? +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Francoska Gvajana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grenlandija" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambija" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Gvineja" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Gvadelup" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatorialna Gvineja" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grčija" + +# GS +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Južna Georgija in Južni Sandwichevi otoki" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Gvatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Gvam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Gvineja Bissau" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Gvajana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hongkong" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Otok Heard in otočje McDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Hrvaška" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Madžarska" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonezija" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irska" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Otok Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indija" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Britansko ozemlje v Indijskem oceanu" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Islandija" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italija" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamajka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordanija" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonska" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenija" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgizstan" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodža" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komori" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Sveti Krištof in Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Severna Koreja" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Južna Koreja" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuvajt" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Kajmanski otoki" + +# Shouldn't this be "Kazakhstan"? +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazahstan" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Laos, ljudska demokratična republika" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Sveta Lucija" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Lihtenštajn" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Šrilanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberija" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesoto" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litva" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvija" + +# LY +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libija" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavija" + +# CG +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Črna gora" + +# SM +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Sveti Martin" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshallovi otoki" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonija" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Mjanmar" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolija" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Makav" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Severni Marijanski otoki" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinik" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mavretanija" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Monserat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# Shouldn't this be "Mauritius"? +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mavricij" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldivi" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malavi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mehika" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malezija" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibija" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nova Kaledonija" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolški otok" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigerija" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragva" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nizozemska" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norveška" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nova Zelandija" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Francoska Polinezija" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nova Gvineja" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipini" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poljska" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Sveti Peter in Mihael" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairnovi otoki" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Portoriko" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestinsko ozemlje" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugalska" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palav" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paragvaj" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romunija" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Srbija" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Ruska federacija" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudova Arabija" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salomonovi otoki" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Sejšeli" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Švedska" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sveta Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenija" + +# SJ +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard in Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovaška" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalija" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sveti Tomaž in Princ" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Salvador" + +# SY +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Sirija" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Svazi" + +# Perhaps "Turks and Caicos Islands"? +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Otoki Turks in Caicos" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Čad" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Francoska južna ozemlja" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tajska" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistan" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelav" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunizija" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Vzhodni Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turčija" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad in Tobago" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tajvan" + +# TZ +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzanija" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrajina" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Manjši oddaljeni otoki Združenih držav" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Združene države" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Urugvaj" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikanska država (Sveti sedež)" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Sveti Vincencij in Grenadine" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britanski Deviški otoki" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Deviški otoki Združenih držav" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# This should be Wallis, not Wallace +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis in Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Južna Afrika" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambija" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabve" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Ponuja" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Pred-zahteva" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Zahteva" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Spori" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Nadomešča" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Priporoča" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Predlaga" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Izboljša" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Dopolnjuje" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Poskusilo se je uvoziti neobstoječ ključ %s v zbirko ključev %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Uvažanje ključa je spodletelo." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Brisanje ključa je spodletelo." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Podpisna datoteka %s ni bila najdena" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Neznan jezik: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abkhazijski" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Aceščina" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Ačolščina" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Dangmenščina" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adigejščina" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-azijski (drugi)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikanščina" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainujščina" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akanščina" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akadščina" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanščina" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutščina" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonkinski jeziki" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Južnoaltajščina" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharic" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Angleščina, stara (okoli 450–1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apaški jeziki" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabski" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramejščina" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonščina" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armenski" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +#, fuzzy +msgid "Araucanian" +msgstr "Albanščina" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +#, fuzzy +msgid "Arapaho" +msgstr "Grafi" + +#. language code: art +#: zypp/LanguageCode.cc:215 +#, fuzzy +msgid "Artificial (Other)" +msgstr "CA certifikat" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamski" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +#, fuzzy +msgid "Asturian" +msgstr "Avstrija" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +#, fuzzy +msgid "Athapascan Languages" +msgstr "Nastavi jezik" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +#, fuzzy +msgid "Avaric" +msgstr "Amharic" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbaižanščina" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +#, fuzzy +msgid "Banda" +msgstr "Kanada" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +#, fuzzy +msgid "Bamileke Languages" +msgstr "Nastavi jezik" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +#, fuzzy +msgid "Bambara" +msgstr "Samba" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +#, fuzzy +msgid "Balinese" +msgstr "Osnova" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskovščina" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +#, fuzzy +msgid "Basa" +msgstr "Osnova" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Belorusščina" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +#, fuzzy +msgid "Bemba" +msgstr "Bermuda" + +# SN +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +#, fuzzy +msgid "Bini" +msgstr "Hindi" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +# BJ +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosanski" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +#, fuzzy +msgid "Braj" +msgstr "Brazilija" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonščina" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +#, fuzzy +msgid "Batak (Indonesia)" +msgstr "Indonezija" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +#, fuzzy +msgid "Buriat" +msgstr "Bolgarija" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +#, fuzzy +msgid "Buginese" +msgstr "Kitajščina" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarščina" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +#, fuzzy +msgid "Burmese" +msgstr "Vodilo" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +#, fuzzy +msgid "Blin" +msgstr "Belgijska" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +#, fuzzy +msgid "Caddo" +msgstr "Karte" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +#, fuzzy +msgid "Carib" +msgstr "Karte" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalanščina" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +#, fuzzy +msgid "Cebuano" +msgstr "Libanon" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Komorski" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +#, fuzzy +msgid "Chibcha" +msgstr "Kitajska" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Češki" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +#, fuzzy +msgid "Chagatai" +msgstr "Shanghai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kitajščina" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +#, fuzzy +msgid "Chuukese" +msgstr "Kitajščina" + +# ML +#. language code: chm +#: zypp/LanguageCode.cc:329 +#, fuzzy +msgid "Mari" +msgstr "Mali" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +#, fuzzy +msgid "Choctaw" +msgstr "Chroot" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Cerkveno Slovanski" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +#, fuzzy +msgid "Cheyenne" +msgstr "Kanal" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "Jeziki" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +#, fuzzy +msgid "Coptic" +msgstr "Računanje" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Kornščina" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korziški" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +# &A is taken +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +#, fuzzy +msgid "Cree" +msgstr "Kreiraj" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +#, fuzzy +msgid "Crimean Tatar" +msgstr "Čas in datum" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Češka" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +#, fuzzy +msgid "Dakota" +msgstr "Dhaka" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danska" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +#, fuzzy +msgid "Dargwa" +msgstr "Darwin" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +#, fuzzy +msgid "Delaware" +msgstr "Strojna oprema" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +#, fuzzy +msgid "Dinka" +msgstr "Trdi disk" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +#, fuzzy +msgid "Divehi" +msgstr "Gonilnik" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +#, fuzzy +msgid "Dogri" +msgstr "Prijava" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +#, fuzzy +msgid "Lower Sorbian" +msgstr "Varčevanje z energijo" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +#, fuzzy +msgid "Duala" +msgstr "Dakar" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nizozemska" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +#, fuzzy +msgid "Dyula" +msgstr "Dubai" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Angleščina" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonska" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +#, fuzzy +msgid "Ewondo" +msgstr "Konec" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +#, fuzzy +msgid "Fang" +msgstr "Območje" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faerščina" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +#, fuzzy +msgid "Fanti" +msgstr "Atlantik" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijian" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +#, fuzzy +msgid "Filipino" +msgstr "Filipini" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finska" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +#, fuzzy +msgid "Fon" +msgstr "Pisave" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francoska" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frizijski" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +#, fuzzy +msgid "Fulah" +msgstr "Zastavice" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +#, fuzzy +msgid "Friulian" +msgstr "Frizijski" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +#, fuzzy +msgid "Ga" +msgstr "Gaza" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +#, fuzzy +msgid "Gayo" +msgstr "Gabon" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +#, fuzzy +msgid "Gbaya" +msgstr "Gaza" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +#, fuzzy +msgid "Germanic (Other)" +msgstr "Nemška (mrtva tipka)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Gruzijski" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Nemška" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +#, fuzzy +msgid "Geez" +msgstr "Grška" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +#, fuzzy +msgid "Gilbertese" +msgstr "Vietnamski" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +#, fuzzy +msgid "Gaelic" +msgstr "Mali" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irščina" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +#, fuzzy +msgid "Galician" +msgstr "Vatikan" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +#, fuzzy +msgid "Gondi" +msgstr "Zvok" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +#, fuzzy +msgid "Grebo" +msgstr "Skupina" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +#, fuzzy +msgid "Gwich'in" +msgstr "Michigan" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +#, fuzzy +msgid "Haida" +msgstr "Strojna oprema" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "Haiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +#, fuzzy +msgid "Hawaiian" +msgstr "Havaji" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebrejski" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +#, fuzzy +msgid "Hittite" +msgstr "Haiti" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +#, fuzzy +msgid "Hmong" +msgstr "HongKong" + +# HT +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +#, fuzzy +msgid "Hiri Motu" +msgstr "Hiri" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +#, fuzzy +msgid "Upper Sorbian" +msgstr "Srbščina" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Madžarska" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +#, fuzzy +msgid "Hupa" +msgstr "Hausa" + +# IR +#. language code: iba +#: zypp/LanguageCode.cc:541 +#, fuzzy +msgid "Iban" +msgstr "Iran" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +#, fuzzy +msgid "Igbo" +msgstr "Ne upoštevaj" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Islandska" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +#, fuzzy +msgid "Ido" +msgstr "ld" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "Litva" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Medzejični" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +#, fuzzy +msgid "Iloko" +msgstr "Tokijo" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonezijščina" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +#, fuzzy +msgid "Ingush" +msgstr "Angleščina" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italijanska" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanski" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +#, fuzzy +msgid "Lojban" +msgstr "Libanon" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonska" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +#, fuzzy +msgid "Judeo-Persian" +msgstr "Perzijski" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +#, fuzzy +msgid "Judeo-Arabic" +msgstr "Arabski" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +#, fuzzy +msgid "Kabyle" +msgstr "Omogočeno" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +#, fuzzy +msgid "Kachin" +msgstr "Išči v" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +#, fuzzy +msgid "Kamba" +msgstr "Samba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kanada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +#, fuzzy +msgid "Karen" +msgstr "Korejščina" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kašmir" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +#, fuzzy +msgid "Kanuri" +msgstr "Kurdsko" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +#, fuzzy +msgid "Kawi" +msgstr "Darwin" + +# Shouldn't this be "Kazakhstan"? +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazaški" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +#, fuzzy +msgid "Kabardian" +msgstr "Kanada" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +#, fuzzy +msgid "Khasi" +msgstr "Tajski" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +#, fuzzy +msgid "Khotanese" +msgstr "Kitajščina" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +#, fuzzy +msgid "Kimbundu" +msgstr "Vrsta" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +#, fuzzy +msgid "Konkani" +msgstr "Korejščina" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +#, fuzzy +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Korejščina" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +#, fuzzy +msgid "Kosraean" +msgstr "Korejščina" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +#, fuzzy +msgid "Kpelle" +msgstr "Črkovalniki" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +#, fuzzy +msgid "Kurukh" +msgstr "Turška" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +#, fuzzy +msgid "Kumyk" +msgstr "Testni modul" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdsko" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +#, fuzzy +msgid "Kutenai" +msgstr "Kenija" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +#, fuzzy +msgid "Ladino" +msgstr "Radioamaterstvo" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +#, fuzzy +msgid "Lahnda" +msgstr "Pokrajina" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +#, fuzzy +msgid "Lamba" +msgstr "Samba" + +# LA +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +#, fuzzy +msgid "Lao" +msgstr "Laos" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +#, fuzzy +msgid "Latin" +msgstr "Latvijščina" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Latvijščina" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +#, fuzzy +msgid "Lezghian" +msgstr "Belgijska" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "Luksemburg" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +#, fuzzy +msgid "Lingala" +msgstr "Angola" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litvanska" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +#, fuzzy +msgid "Mongo" +msgstr "Kongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +#, fuzzy +msgid "Lozi" +msgstr "Prijava" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "Luksemburg" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +#, fuzzy +msgid "Ganda" +msgstr "Gana" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +#, fuzzy +msgid "Luiseno" +msgstr "Poslušaj na" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +#, fuzzy +msgid "Lunda" +msgstr "Nedelja" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "Tajski" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonščina" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +#, fuzzy +msgid "Madurese" +msgstr "Faerščina" + +# MW +#. language code: mag +#: zypp/LanguageCode.cc:701 +#, fuzzy +msgid "Magahi" +msgstr "Malavi" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +#, fuzzy +msgid "Marshallese" +msgstr "Marshallovi otoki" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +#, fuzzy +msgid "Maithili" +msgstr "Matematika" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +#, fuzzy +msgid "Makasar" +msgstr "Madagaskar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +#, fuzzy +msgid "Malayalam" +msgstr "Malezija" + +#. language code: man +#: zypp/LanguageCode.cc:711 +#, fuzzy +msgid "Mandingo" +msgstr "Opozorilo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +#, fuzzy +msgid "Maori" +msgstr "Glavni" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +#, fuzzy +msgid "Marathi" +msgstr "Matematika" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +#, fuzzy +msgid "Masai" +msgstr "Malavi" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "Malta" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +#, fuzzy +msgid "Mandar" +msgstr "Mjanmar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +#, fuzzy +msgid "Mende" +msgstr "Način" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "Razne nastavitve" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "Managua" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +#, fuzzy +msgid "Maltese" +msgstr "Malta" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +#, fuzzy +msgid "Manchu" +msgstr "Ročno" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "Jeziki" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "Moldavija" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +#, fuzzy +msgid "Mongolian" +msgstr "Mongolija" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +#, fuzzy +msgid "Mossi" +msgstr "Morse" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "&Več ključev" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +#, fuzzy +msgid "Munda languages" +msgstr "Se&kundarni jeziki" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +#, fuzzy +msgid "Creek" +msgstr "Grška" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +#, fuzzy +msgid "Mirandese" +msgstr "Wisconsin" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +#, fuzzy +msgid "Marwari" +msgstr "Strojna oprema" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "Jeziki" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +#, fuzzy +msgid "Nahuatl" +msgstr "Ročno" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +#, fuzzy +msgid "North American Indian" +msgstr "Severna Amerika" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +#, fuzzy +msgid "Ndonga" +msgstr "Tonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "Nemška" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +#, fuzzy +msgid "Nepali" +msgstr "Nepal" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +#, fuzzy +msgid "Nepal Bhasa" +msgstr "Nepal" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +#, fuzzy +msgid "Nias" +msgstr "Vzdevek" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +#, fuzzy +msgid "Niuean" +msgstr "Niue" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +#, fuzzy +msgid "Norwegian Nynorsk" +msgstr "Norveška" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +#, fuzzy +msgid "Norwegian Bokmal" +msgstr "Norveška" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +#, fuzzy +msgid "Nogai" +msgstr "Prijava" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norveščina" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +#, fuzzy +msgid "Northern Sotho" +msgstr "Severna Irska" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "Nastavi jezik" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +#, fuzzy +msgid "Classical Newari" +msgstr "Ime razreda" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +#, fuzzy +msgid "Chichewa" +msgstr "Češki" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +#, fuzzy +msgid "Nyamwezi" +msgstr "Ime" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +#, fuzzy +msgid "Nyoro" +msgstr "Sever" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +#, fuzzy +msgid "Nzima" +msgstr "Lima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +# SY +#. language code: ori or +#: zypp/LanguageCode.cc:833 +#, fuzzy +msgid "Oriya" +msgstr "Sirija" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +#, fuzzy +msgid "Oromo" +msgstr "Korenski uporabnik" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +#, fuzzy +msgid "Osage" +msgstr "shrani" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +#, fuzzy +msgid "Ossetian" +msgstr "Ruska" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "Nastavi jezik" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +#, fuzzy +msgid "Pangasinan" +msgstr "Madžarska" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +#, fuzzy +msgid "Pahlavi" +msgstr "Palau" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +#, fuzzy +msgid "Pampanga" +msgstr "Paragvaj" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +#, fuzzy +msgid "Panjabi" +msgstr "Punjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +#, fuzzy +msgid "Papiamento" +msgstr "Parameter" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +#, fuzzy +msgid "Palauan" +msgstr "Palau" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Perzijski" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +#, fuzzy +msgid "Philippine (Other)" +msgstr "Filipini" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +#, fuzzy +msgid "Phoenician" +msgstr "Slovenščina" + +# ML +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +#, fuzzy +msgid "Pali" +msgstr "Mali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Poljska" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +#, fuzzy +msgid "Pohnpeian" +msgstr "Indonezijščina" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugalska" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "Primarni &Jezik" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +#, fuzzy +msgid "Pushto" +msgstr "Po meri" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +# Shouldn't this be "Kazakhstan"? +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +#, fuzzy +msgid "Rajasthani" +msgstr "Kazahstan" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "Japonska" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +#, fuzzy +msgid "Rarotongan" +msgstr "Preberi usmerjanje" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "Romunija" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romunščina" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +#, fuzzy +msgid "Rundi" +msgstr "Deluje" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ruska" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +#, fuzzy +msgid "Sandawe" +msgstr "Pokrajina" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +#, fuzzy +msgid "Sango" +msgstr "Saigon" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +#, fuzzy +msgid "Yakut" +msgstr "Breakout" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "Nastavi jezik" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +#, fuzzy +msgid "Sanskrit" +msgstr "Začetek" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +#, fuzzy +msgid "Sasak" +msgstr "Samba" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +#, fuzzy +msgid "Santali" +msgstr "Scan postaja" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Srbščina" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +#, fuzzy +msgid "Sicilian" +msgstr "Michigan" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +#, fuzzy +msgid "Scots" +msgstr "Sekunde" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Hrvaška" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +#, fuzzy +msgid "Selkup" +msgstr "Preskoči" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "Jeziki" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +#, fuzzy +msgid "Shan" +msgstr "Shanghai" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +#, fuzzy +msgid "Sidamo" +msgstr "Samoa" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +#, fuzzy +msgid "Sinhala" +msgstr "Zaporedno (serial)" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Nastavi jezik" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovaška" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenščina" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +#, fuzzy +msgid "Northern Sami" +msgstr "Severna Irska" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "Jeziki" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +#, fuzzy +msgid "Lule Sami" +msgstr "Ime modula" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +#, fuzzy +msgid "Samoan" +msgstr "Samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +#, fuzzy +msgid "Shona" +msgstr "Slovenija" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +#, fuzzy +msgid "Sindhi" +msgstr "Hindi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +#, fuzzy +msgid "Soninke" +msgstr "Nadaljuj" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +#, fuzzy +msgid "Sogdian" +msgstr "Prijava" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +#, fuzzy +msgid "Somali" +msgstr "Somalija" + +#. language code: son +#: zypp/LanguageCode.cc:985 +#, fuzzy +msgid "Songhai" +msgstr "Shanghai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Španska" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +#, fuzzy +msgid "Sardinian" +msgstr "Ukrajinska" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +#, fuzzy +msgid "Serer" +msgstr "Strežnik" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +#, fuzzy +msgid "Swati" +msgstr "Začetek" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +#, fuzzy +msgid "Sukuma" +msgstr "Povzetek" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +#, fuzzy +msgid "Sundanese" +msgstr "Sudan" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +#, fuzzy +msgid "Susu" +msgstr "SMVodilo(SMBus)" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +#, fuzzy +msgid "Sumerian" +msgstr "Srbščina" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +#, fuzzy +msgid "Swahili" +msgstr "Svazi" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Švedska" + +# SY +#. language code: syr +#: zypp/LanguageCode.cc:1011 +#, fuzzy +msgid "Syriac" +msgstr "Sirija" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +#, fuzzy +msgid "Tahitian" +msgstr "Tahiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +#, fuzzy +msgid "Tai (Other)" +msgstr "Ostalo" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +#, fuzzy +msgid "Tamil" +msgstr "Družina" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "Katar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +#, fuzzy +msgid "Telugu" +msgstr "Belgija" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +#, fuzzy +msgid "Timne" +msgstr "Čas" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +#, fuzzy +msgid "Tereno" +msgstr "Herero" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +#, fuzzy +msgid "Tetum" +msgstr "Pentium" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +#, fuzzy +msgid "Tajik" +msgstr "Pogovori" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Tajski" + +# TW +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetanski" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +#, fuzzy +msgid "Tigre" +msgstr "prezri" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +#, fuzzy +msgid "Tigrinya" +msgstr "Nigerija" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +#, fuzzy +msgid "Klingon" +msgstr "Saigon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +#, fuzzy +msgid "Tlingit" +msgstr "Dopisni seznami" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +#, fuzzy +msgid "Tamashek" +msgstr "Tashkent" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +#, fuzzy +msgid "Tonga (Tonga Islands)" +msgstr "Solomonovi otoki" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +#, fuzzy +msgid "Tok Pisin" +msgstr "Token Ring" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +#, fuzzy +msgid "Tsimshian" +msgstr "Ruska" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +#, fuzzy +msgid "Tswana" +msgstr "Botsvana" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +#, fuzzy +msgid "Tsonga" +msgstr "Tonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "Turčija" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +#, fuzzy +msgid "Tumbuka" +msgstr "Timbuktu" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "Nastavi jezik" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turška" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +#, fuzzy +msgid "Tuvinian" +msgstr "Tunizija" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +#, fuzzy +msgid "Ugaritic" +msgstr "Haiti" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrajinska" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +#, fuzzy +msgid "Undetermined" +msgstr "Medzejični" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +#, fuzzy +msgid "Uzbek" +msgstr "Uzbekistan" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +#, fuzzy +msgid "Vai" +msgstr "Vi" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +#, fuzzy +msgid "Venda" +msgstr "Proizvajalec" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamski" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +#, fuzzy +msgid "Votic" +msgstr "Vatikan" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "Nastavi jezik" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +#, fuzzy +msgid "Walamo" +msgstr "Palm" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +#, fuzzy +msgid "Waray" +msgstr "Sobota" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +#, fuzzy +msgid "Washo" +msgstr "Welški" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Welški" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +#, fuzzy +msgid "Walloon" +msgstr "vsi" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +#, fuzzy +msgid "Kalmyk" +msgstr "Pogovori" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +#, fuzzy +msgid "Yapese" +msgstr "Japonska" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +#, fuzzy +msgid "Yiddish" +msgstr "Končaj" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +#, fuzzy +msgid "Yoruba" +msgstr "Aruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "Nastavi jezik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +#, fuzzy +msgid "Zenaga" +msgstr "Grenada" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +#, fuzzy +msgid "Zhuang" +msgstr "Spremeni" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +#, fuzzy +msgid "Zande" +msgstr "Območje" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +#, fuzzy +msgid "Zuni" +msgstr "Tunizija" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Izvedena bodo naslednja dejanja:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "ne poteče" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "potekel: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "poteče: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(ne poteče)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(POTEKEL)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(poteče v naslednjih 24 urah)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(poteče čez %d dan)" +msgstr[1] "(poteče čez %d dni)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "neznano" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nepodprto" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "1. stopnja" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "2. stopnja" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "3. stopnja" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Potrebna je dodatna uporabniška pogodba" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Opuščen in nadomeščen z drugim paketom" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "neveljavno" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Stopnja podpore ni določena" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Izdelovalec ne ponuja podpore." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Ugotavljanje težave, kar pomeni tehnično podporo za ponujanje informacij o " +"združljivosti, pomoč pri nameščanju, pomoč pri uporabi, tekoče vzdrževanje " +"in osnovno odpravljanje težav. Prva stopnja podpore ni namenjena " +"odpravljanju napak izdelka." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Osamitev težave, kar pomeni tehnično podporo za podvajanje težav uporabnika, " +"osamitev področja težave in ponujanje rešitev za težave, ki jih ne razreši " +"podpora prve stopnje." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Rešitev težave, kar pomeni tehnično pomoč za odpravljanje kompleksnih težav " +"z vključitvijo inženirjev in odpravo napak izdelka, ki so bile ugotovljene s " +"strani podpore druge stopnje." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Za pridobitev podpore je potrebna dodatna uporabniška pogodba." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"Paket je bil opuščen in je bil nadomeščen z novim paketom z drugim imenom." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Neznana možnost podpore. Opis ni na voljo." + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Sistemsko upravljanje je zaklenil program s PID %d (%s).\n" +"Pred ponovnim poskusom zaprite ta program." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Neznan način ujemanja »%s«" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Neznan način ujemanja »%s« za vzorec »%s«" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Neveljaven regularni izraz »%s«: regcomp je vrnil %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Neveljaven regularni izraz »%s«" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Za »%s« je potrebna overitev" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Poskusilo se bo znova …" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Opuščeno po %1% poskusih." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Obiščite SUSE Customer Center in preverite ali je registracija še veljavna " +"in še ni potekla." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Obiščite Novell Customer Center in preverite ali je registracija še veljavna " +"in še ni potekla." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Ustvarjanje priklopne točke: ni moč najti zapisljive mape za ustvarjanje " +"priklopne točke" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Najprej namestite paket »lsof«." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Ni moč ustvariti mape predpomnilnika metapodatkov." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Napaka pri poskušanju branja iz »%s«" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Ni moč ustvariti %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Na navedenem mestu niso bili najdeni veljavni metapodatki" +msgstr[1] "Na navedenih mestih niso bili najdeni veljavni metapodatki" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "Dodajanje vira v predpomnilnik ni uspelo (ni moč zagnati repo2solv)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Predpomnjenje vira ni uspelo (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Grajenje predpomnilnika vira »%s«" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Predpomnilnika v %s ni moč ustvariti – ni dovoljenja za pisanje." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "Dodajanje vira %1% v predpomnilnik ni uspelo" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Neobravnavana vrsta vira" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Dodajanje vira »%s«" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Neveljavno ime datoteke vira na »%s«" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Datoteke »%s« ni moč odpreti za pisanje." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Neznana napaka pri branju iz »%s«" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Ni moč brati mape vira »%1%«: dovoljenje zavrnjeno" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Branje mape »%s« ni uspelo" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Ni moč brati datoteke vira »%1%«: dovoljenje zavrnjeno" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "Čiščenje metapodatkov" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "Čiščenje paketov" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "Čiščenje map predpomnilnika" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "Čiščenje mape: %1%" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "Čiščenje predpomnilnika" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "Nalaganje iz predpomnilnika" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Odstranjevanje vira »%s«" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Ni moč ugotoviti, kje je vir shranjen." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Ni moč izbrisati »%s«" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "Spreminjanje vira" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "Osveževanje vira: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Ni moč ugotoviti, kje je storitev shranjena." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Neznana storitev »%1%«: odstranjevanje zapuščenega vira storitve »%2%«" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Drugo ime vira se ne more začeti s piko." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Drugo ime storitve se ne more začeti s piko." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Ni izvlečka za datoteko %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Neznan izvleček %s za datoteko %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Potrjevanje z izvlečkom za datoteko »%s« ni uspelo" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Datoteka »%s« ni podpisana. Ali želite nadaljevati?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Datoteka »%s« iz vira »%s« ni podpisana. Ali želite nadaljevati?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Ali želite zavrniti ključ, mu zaupati začasno, ali zaupati vedno?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Ime ključa: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "Prejet %1% nov ključ za podpisovanje paketov iz vira »%2%«:" +msgstr[1] "Prejetih %1% novih ključev za podpisovanje paketov iz vira »%2%«:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Potrjevanje s podpisom za datoteko »%1%« ni uspelo." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "Potrjevanje s podpisom za datoteko »%1%« iz vira »%2%« ni uspelo." + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Ali želite nadaljevati?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Datoteka »%s« je podpisana z neznanim ključem »%s«. Ali želite nadaljevati?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Datoteka »%s« iz vira »%s« je podpisana z neznanim ključem »%s«. Ali želite " +"nadaljevati?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Vir %1% ne določa dodatnih mest »gpgkey=«." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Iskanje ključa GPG z določilnikom %1% v viru %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Iskanje ključa GPG z določilnikom %1% v predpomnilniku %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Zahtevana lastnost »%s« manjka." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Zahtevana je vsaj ena od lastnosti »%s« ali »%s«." + +# %s is either BOOTP or DHCP +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Preverjanje s podpisom ni uspelo" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Videti je, da se je paket %s med prejemanjem pokvaril. Ali želite znova " +"poskusiti s prejemanjem?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Paketa %s ni bilo moč ponuditi. Ali želite znova poskusiti s prejemanjem?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Preverjanje applydeltarpm ni uspelo." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm ni uspel." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Vstavek storitve ne podpira spreminjanja lastnosti." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Ni moč ponuditi datoteke »%s« iz vira »%s«" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "V viru ni nobenega mesta." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "Pričakovan nosilec %1%/%2%, določen z datoteko »%3%« z vsebino:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Datoteka %1%\n" +" iz paketa\n" +" %2%\n" +" je v sporu z datoteko iz paketa\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Datoteka %1%\n" +" Iz paketa\n" +" %2%\n" +" je v sporu z datoteko nameščeno iz\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Datoteka %1%\n" +" nameščena iz\n" +" %2%\n" +" je v sporu z datoteko iz paketa\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Datoteka %1%\n" +" nameščena iz\n" +" %2%\n" +" je v sporu z datoteko nameščeno iz\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Datoteka %1%\n" +" iz paketa\n" +" %2%\n" +" je v sporu z datoteko\n" +" %3%\n" +" iz paketa\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Datoteka %1%\n" +" iz paketa\n" +" %2%\n" +" je v sporu z datoteko\n" +" %3%\n" +" nameščeno iz\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Datoteka %1%\n" +" nameščena iz\n" +" %2%\n" +" je v sporu z datoteko\n" +" %3%\n" +" iz paketa\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Datoteka %1%\n" +" nameščena iz\n" +" %2%\n" +" je v sporu z datoteko\n" +" %3%\n" +" nameščeno iz\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Ni moč ustvariti sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "pokvari %s s prezrtjem nekaterih njegovih odvisnosti" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "splošno prezrtje nekaterih odvisnosti" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"nameščeni %1% ne spada v vir za nadgradnjo distribucije in mora biti " +"nadomeščen" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "%1%, ki bo nameščen, ne spada v vir za nadgradnjo distribucije" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "nameščeni %1% ima starejšo arhitekturo" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "%1%, ki bo nameščen, ima starejšo arhitekturo" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "težava z nameščenim %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "zahteve v sporu" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "neka težava z odvisnostjo" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "nič ne ponuja zahtevanega »%1%«" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Ali ste omogočili vse zahtevane vire?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "zahtevani paket %1% ne obstaja" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "nepodprta zahteva" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "»%1%« ponuja sistema in ga ni mogoče izbrisati" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% ni mogoče namestiti" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "nič ne ponuja »%1%«, ki ga potrebuje nameščeni %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "nič ne ponuja »%1%«, ki ga potrebuje %2%, ki bo nameščen" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "ni mogoče namestiti oba %1% in %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "nameščeni %1% je v sporu z »%2%«, ki ga ponuja nameščeni %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "nameščeni %1% je v sporu z »%2%«, ki ga ponuja %3%, ki bo nameščen" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "%1%, ki bo nameščen, je v sporu z »%2%«, ki ga ponuja nameščeni %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"%1%, ki bo nameščen, je v sporu z »%2%«, ki ga ponuja %3%, ki bo nameščen" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "nameščeni %1% nadomešča »%2%«, ki ga ponuja nameščeni %3%" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "nameščeni %1% nadomešča »%2%«, ki ga ponuja %3%, ki bo nameščen" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "%1%, ki bo nameščen, nadomešča »%2%«, ki ga ponuja nameščeni %3%" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "%1%, ki bo nameščen, nadomešča »%2%«, ki ga ponuja %3%, ki bo nameščen" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "nameščeni %1% je v sporu z »%2%«, ki ga ponuja sam" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "%1%, ki bo nameščen, je v sporu z »%2%«, ki ga ponuja sam" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "nameščeni %1% zahteva »%2%«, vendar te zahteve ni mogoče ponuditi" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"%1%, ki bo nameščen, zahteva »%2%«, vendar te zahteve ni mogoče ponuditi" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "izbrisani ponudniki: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"ponudniki, ki jih ni mogoče namestiti: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "ponudniki, ki jih ni mogoče namestiti: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% še ni povsem integriran v %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Običajno je želeno obdržati PTF in ne namestiti vzdrževalnih popravkov." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Odstranitev nameščenega %1% v tem kontekstu bo odstranila (ne nadomestila!) " +"tudi vsebovane pakete PTF." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"PTF bi morali odstraniti z ukazom »%1%«. To bo posodobilo vsebovane pakete " +"PTF, namesto da bi jih odstranilo." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Običajno je želeno obdržati PTF ali preklicati dejanje." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Nameščeni %1% blokira želeno dejanje." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Običajno je želeno obdržati PTF in preklicati dejanje." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "odstrani zaklep za dovoljenje odstranitve %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "ne namesti %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "obdrži %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "odstrani zaklep za dovoljenje namestitve %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Ta zahteva bo pokvarila sistem!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "prezri opozorilo o pokvaritvi sistema" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "ne vprašaj za namestitev rešitve, ki ponuja %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "ne vprašaj za izbris vseh rešitev, ki ponujajo %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "ne namesti najnovejše različice %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "obdrži %1% kljub starejši arhitekturi" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "namesti %1% kljub starejši arhitekturi" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "obdrži opuščeni %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "namesti %1% iz izločenega vira" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "namesti %1%, čeprav je bil opuščen" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "omogoči nameščanje PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "namesti %1%, čeprav je bil dodan na seznam prepovedanih" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "vrni %1% na starejšo različico %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "spremeni arhitekturo %1% na %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"namesti %1% (s spremembo izdelovalca)\n" +" %2% → %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"namesti %1% izdelovalca %2%,\n" +" ki nadomesti %3% izdelovalca %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "nadomestitev %1% z %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "odstranitev %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Zaganjanje skriptov po transakciji" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Zaganjanje skripta %1%" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "Izhod skripta %1%:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Namestitev je bila prekinjena, kot naročeno." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " izvedeno" + +# %s is either BOOTP or DHCP +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " izvedba ni uspela" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s že izveden kot %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " izvedba preskočena med prekinitvijo" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Napaka pošiljanja obvestila s sporočilom posodobitve." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Sporočilo nove posodobitve" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Prejet signal: »%1% (%2%)«. Zaradi zagotovitve skladnosti sistema ni mogoče " +"preklicati tekoče transakcije RPM." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Izvajanje transakcije ni uspelo zaradi naslednjih težav:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM ni uspel: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Uvažanje javnega ključa %1% ni uspelo" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Odstranjevanje javnega ključa %1% ni uspelo" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Glava paketa ni podpisana!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Vsebina paketa ni podpisana!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Spremenjene nastavitvene datoteke za %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "RPM je %s shranil kot %s, vendar ni bilo moč ugotoviti razlik" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"RPM je %s shranil kot %s.\n" +"Tu je prvih 25 vrstic razlike:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "RPM je %s ustvaril kot %s, vendar ni bilo moč ugotoviti razlik" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"RPM je %s ustvaril kot %s:\n" +"Tu je prvih 25 vrstic razlik:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Dodatni izhod RPM" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "ustvaril varnostno kopijo %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Podpis je v redu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Neznana vrsta podpisa" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Podpis ni potrjen" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Podpis je v redu, vendar ključu ni zaupano" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Javni ključ podpisa ni na voljo" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Datoteka ne obstaja ali pa podpisa ni moč potrditi" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Datoteka ni podpisana" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Dvomljiva vrsta »%s« za %u bajtov nadzorne vsote »%s«" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Ni moč odpreti psevdo-terminala (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Ni moč odpreti cevi (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Neveljaven poizvedovalni niz mesta LDAP" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Neveljavne poizvedovalni parameter »%s« mesta LDAP" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Ni moč podvojiti objekta Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Neveljavna referenca na prazen objekt Url" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Ni moč razčleniti delov Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Zgodovina:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Shema Url ne dovoljuje %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Neveljavna %s komponenta »%s«" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Neveljavna %s komponenta" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Razčlenjevanje poizvedovalnega niza za ta URL ni podprto" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Shema Url je zahtevana komponenta" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Neveljavna shema Url »%s«" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Shema Url ne dovoljuje uporabniškega imena" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Shema Url ne dovoljuje gesla" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Shema Url zahteva komponento gostitelja" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Shema Url ne dovoljuje komponente gostitelja" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Neveljavna komponenta gostitelja »%s«" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Shema Url ne dovoljuje vrat" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Neveljavna komponenta vrat »%s«" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Shema Url zahteva me poti" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Če obstaja avtoriteta, relativna pot ni dovoljena" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Zakodiran niz vsebuje bajt NUL" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Neveljaven znak za razdelitev niza parametrov" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Neveljaven znak za razdelitev preslikave parametrov" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Neveljaven znak za združitev niza parametrov" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Ukaz je končal s stanjem %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Ukaz je bil ubit s signalom %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Ukaz je končal z neznano napako." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Dani neveljavni argumenti ustvaritve." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Ni moč ustvariti nadzorne cevi." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Ni moč izvesti chroot v »%s« (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Ni moč izvesti chdir v »%s« (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Ni moč izvesti chdir v »%s« znotraj chroot »%s« (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Ni moč izvesti »%s« (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Ni moč razvejiti (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Ni moč izvesti »%s«. Ukaz chdir ni uspel (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Ni moč izvesti »%s«. Ukaz chroot ni uspel (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Ni moč izvesti »%s«. Ukaz exec ni uspel (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Ni moč izvesti »%s«. Nepričakovana napaka." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Priklapljanje %s v %s ni uspelo" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Odklapljanje %s ni uspelo" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Slabo ime datoteke: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Nosilec med poskusom izvajanja dejanja »%s« ni bil odprt." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Datoteke »%s« na nosilcu »%s« ni bilo moč najti" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Datoteke »%s« ni moč zapisati." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Nosilec ni priklopljen" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Slaba priklopna točka nosilca" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Pripravljanje prejemanja (curl) ni uspelo za »%s«" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Sistemska izjema »%s« na nosilcu »%s«." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Pot »%s« na nosilcu »%s« ni datoteka." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Pot »%s« na nosilcu »%s« ni mapa." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Napačno oblikovan URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Prazno ime gostitelja v URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Prazen datotečen sistem v URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Prazen cilj v URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Nepodprta shema URI v »%s«." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Nosilec ne podpira dejanja" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Napaka prejemanja (curl) za »%s«\n" +"Koda napake: %s\n" +"Sporočilo napake: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Prišlo je do napake med nastavljanjem možnosti prejemanja (curl) za »%s«:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Vir nosilca »%s« ne vsebuje želenega nosilca" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Nosilec »%s« uporablja drug primerek" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Ni moč izvreči nobenega nosilca" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Ni moč izvreči nosilca »%s«" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Dovoljenje za dostop do »%s« je bilo zavrnjeno." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Med dostopanjem do »%s« je potekel čas." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" +"Prejeti podatki so večji od pričakovane velikosti datoteke »%s« za »%s«." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Mesto »%s« trenutno ni dostopno." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " Težava s potrdilom SSL. Preverite, ali je potrdilo CA za »%s« v redu." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Za priklop nosilca ni na voljo nobenega prostega vira." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Nepodprt način overjanja HTTP »%s«" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Napaka prejemanja (curl) za »%s«:\n" +"Koda napake: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Napaka prejemanja (curl) za »%s«:\n" +"Ni moč dobiti odziva HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Da" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ne" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Opomba:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Opozorilo:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Napaka:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "zaključeno" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "pozor" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "napaka" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Opozorilo: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Prejemanje:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "zaganjanje" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "ni najdeno" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Pomoč za ta poziv ni na voljo." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "pomoč za to možnost ni na voljo" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "prikaže vse možnosti" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "da" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ne" + +#, fuzzy +#~ msgid "Package is not signed!" +#~ msgstr "Paketi za obnovitev" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "Zagonska arhitektura" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Paketi za obnovitev" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "Ta paket ni nameščen in ne bo nameščen." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "Namestitev ni uspela." + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Nameščam na:" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "do not install %s" +#~ msgstr "Nameščam na:" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "Nameščam na:" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "Zbriši %1" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Namestitev" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "Hal Exception" +#~ msgstr "Šifriranje" + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "ni povezave" + +#, fuzzy +#~ msgid "HalDrive not initialized" +#~ msgstr "Ponovno pripravi" + +#, fuzzy +#~ msgid "HalVolume not initialized" +#~ msgstr "Ponovno pripravi" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "povazava kanal-kanal" + +#, fuzzy +#~ msgid "Not a CDROM drive" +#~ msgstr "Ni CD-ROM enot." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "Nameščam na:" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Napaka pri nalaganju modula \"%s\"." + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Srbija in Črna gora" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Neznan monitor:" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "Nezadoščene odvisnosti:" + +#, fuzzy +#~ msgid "%s remove failed" +#~ msgstr "rpm neuspešen." + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "Nepravilno ime naprave." + +#, fuzzy +#~ msgid "rpm output:" +#~ msgstr "" +#~ "\n" +#~ "Izhod ukaza:" + +#, fuzzy +#~ msgid "%s install failed" +#~ msgstr "Namestitev ni uspela." + +#, fuzzy +#~ msgid "%s installed ok" +#~ msgstr "Nameščena verzija" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Imenik %1 je že na seznamu." + +#, fuzzy +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "Ignore this requirement just here" +#~ msgstr "ima nerešene zahteve..." + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Namesti manjkajoče pakete" + +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "Namesti manjkajoče pakete" + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "install %s" +#~ msgstr "Namesti %1" + +#, fuzzy +#~ msgid "unlock %s" +#~ msgstr "Ure" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "Napaka pri branju odseka %u." + +#, fuzzy +#~ msgid "Software management is already running." +#~ msgstr "Storitev za PCMCIA kartice že deluje." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "Potrebno je namestiti %s " + +#, fuzzy +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "Ta paket ni nameščen in ne bo nameščen." + +#, fuzzy +#~ msgid "%s has missing dependencies" +#~ msgstr "Nezadoščene odvisnosti:" + +#, fuzzy +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "Nezadoščene odvisnosti:" + +#, fuzzy +#~ msgid "No need to install %s" +#~ msgstr "potrebno je ponovno namestiti" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "Nezadoščene odvisnosti:" + +#, fuzzy +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%1 je v sporu s/z %2" + +#, fuzzy +#~ msgid ", Action: " +#~ msgstr "Akcija" + +#~ msgid "patch" +#~ msgstr "popravek" + +#, fuzzy +#~ msgid "Establishing %s" +#~ msgstr "Nameščam na:" + +#, fuzzy +#~ msgid "Installing %s" +#~ msgstr "Nameščam na:" + +#, fuzzy +#~ msgid "Skipping %s: already installed" +#~ msgstr "Preverjam že nameščene optične bralnike" + +#, fuzzy +#~ msgid " Error!" +#~ msgstr "Napaka" + +#, fuzzy +#~ msgid " Important!" +#~ msgstr "Uvozi podatke" + +#, fuzzy +#~ msgid "Ignore this requirement generally" +#~ msgstr "ima nerešene zahteve..." + +#, fuzzy +#~ msgid "Reading selection from %s" +#~ msgstr "Napaka pri branju odseka %u." + +#, fuzzy +#~ msgid "Reading patch %s" +#~ msgstr "Skrivanje popravkov" + +#, fuzzy +#~ msgid "Reading translation: %s" +#~ msgstr "Nalaganje nameščenega sistema" + +#, fuzzy +#~ msgid "Downloading %s" +#~ msgstr "Napaka pri nalaganju %1" + +#~ msgid "Ok" +#~ msgstr "OK" + +#, fuzzy +#~ msgid "The package file has incorrect MD5 sum" +#~ msgstr "Paketi za odstranitev" + +#, fuzzy +#~ msgid "The package has no MD5 sum" +#~ msgstr "Paketi za odstranitev" + +#, fuzzy +#~ msgid "The package archive has incorrect MD5 sum" +#~ msgstr "Paketi za odstranitev" + +#~ msgid "Default" +#~ msgstr "Privzeto" + +#, fuzzy +#~ msgid "to be installed (soft)" +#~ msgstr "bo nameščen kot:" + +#, fuzzy +#~ msgid "to be uninstalled" +#~ msgstr "potrebno je ponovno namestiti" diff --git a/po/sr.po b/po/sr.po new file mode 100644 index 0000000..e5e3543 --- /dev/null +++ b/po/sr.po @@ -0,0 +1,5617 @@ +# Serbian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2004 SuSE Linux AG. +# Rade Radenkovic , 2004 +# Bojan Jovanovic , 2004 +# +msgid "" +msgstr "" +"Project-Id-Version: YaST2 (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2004-03-31 11:34+0200\n" +"Last-Translator: Bojan Jovanovic \n" +"Language-Team: Serbian \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=3; plural=n%10==1 && n%100!=11 ? 0 : (n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +# TextEntry label for phone network Areacode (german Vorwahl) +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +#, fuzzy +msgid "No Code" +msgstr "Poz&ivni broj" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Андора" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Ujedinjeni arapski emirati" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Авганистан" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Антигва и Барбуда" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Ангила" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanija" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Јерменија" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Холандски Антили" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Ангола" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Антарктик" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Америчка Самоа" + +# Contry name +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austrija" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australija" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Аруба" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +#, fuzzy +msgid "Aland Islands" +msgstr "Оландска острва" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Азербејџан" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Босна и Херцеговина" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Amerika/Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Бангладеш" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgija" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Буркина Фасо" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bugarska" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Azija/Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Бурунди" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Бенин" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Султанат Брунеи" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivija" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Бразил" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Бахами" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Бутан" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Буве острво" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Bocvana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belorusija" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Белизе" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Кокос (Килинг) острва" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Конго" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "Централна Афричка Република" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Švajcarska" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +#, fuzzy +msgid "Cote D'Ivoire" +msgstr "Обала Слоноваче" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Кукова острва" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Čile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Камерун" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Narodi Republike Kine" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolumbija" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kostarika" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Куба" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Зеленортска острва" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Божићно острво" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Кипар" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Češka Republika" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Nemačka" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Afrika/Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danska" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Amerika/Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikanska Republika" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Alžir" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonija" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egipt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Западна Сахара" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Еритреја" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Španija" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Етиопија" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finska" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidži" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Фокландска острва (Малвини)" + +# official_name for FSM +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Федералне Државе Микронезија" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Farska ostrva" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Francuska" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Габон" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Velika Britanija" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Amerika/Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Jordan" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Француска Гвајана" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Nemačka" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Гана" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Evropa/Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Гамбија" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Гвинеа" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Amerika/Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Екваторијална Гвинеја" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grčka" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Јужна Џорџија и Јужна Сендвич острва" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Gvatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Гвинеа-Бисао" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Гвајана" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Херд острво и Мекдоналд острва" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Hrvatska" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Хаити" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Mađarska" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonezija" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irska" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Izrael" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indija" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Британска Индијска Океанска Територија" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +#, fuzzy +msgid "Iran" +msgstr "Irak" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italija" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Globalno/Jamajka" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Кенија" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Киргизстан" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Камбоџа" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Кирибати" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Комори" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Свети Китс и Невис" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +#, fuzzy +msgid "North Korea" +msgstr "Evropa/Severna-Irska" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +#, fuzzy +msgid "South Korea" +msgstr "Južni Pol" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuvajt" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Кајманска острва" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Казахстан" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Лаошка Народна Демократска Република" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Liban" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Света Луција" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Evropa/Linhenštajn" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Шри Ланка" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Либерија" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Лесото" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litvanija" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Evropa/Luksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Jermenija" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +#, fuzzy +msgid "Libya" +msgstr "Либерија" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Maroko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Evropa/Monako" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Evropa/Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "монго" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "Сан Марино" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Мадагаскар" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Маршалска острва" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonija" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Мали" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Мјанмар" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Монголија" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Azija/Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Северна Маријанска острва" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Amerika/Marinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Мауританија" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Монтсерат" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Маурицијус" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Малдиви" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Малави" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malazija" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Мозамбик" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Намибија" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Нова Каледонија" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Нигер" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Норфолк острво" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Нигерија" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragva" + +# Contry name +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Europa/Holandija" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norveška" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Непал" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Ниуе" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Novi Zeland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Француска Полинезија" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Папуа Нова Гвинеја" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipini" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +# Contry name +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poljska" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Свети Пјер и Микелон" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pacifik/Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Porto Riko" + +# official_name for PSE +#. :PRI:630: +#: zypp/CountryCode.cc:339 +#, fuzzy +msgid "Palestinian Territory" +msgstr "Окупирана Палестинска Територија" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugalija" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paragvaj" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Реунион" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumunija" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "српски" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Руска Федерација" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Руанда" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudijska Arabija" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Соломонска острва" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Сејшели" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Švedska" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Света Хелена" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenija" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Свалбард и Јан Мајен" + +# Contry name +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovačka" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Сијера Леоне" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "Сан Марино" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Сенегал" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Сомалија" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Суринам" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Сао Томе и Принсипе" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +#, fuzzy +msgid "Syria" +msgstr "сиријски" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Свазиланд" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Туркс и Каикос острва" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Чад" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Француске Јужне Територије" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Того" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tajland" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadžikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "токелау" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Туркменистан" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunis" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Тонга" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turska" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Тринидад и Тобаго" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "тувалу" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Тајван" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +#, fuzzy +msgid "Tanzania" +msgstr "Australija/Tasmania" + +# "TW" : _("Taiwan R.O.C."), +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrajina" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Уганда" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Мала Спољашња Острва Сједињених Држава" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Сједињене Државе" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Urugvaj" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Света Столица (Ватикан град-држава)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Свети Винсент и Гренадинци" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venecuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Британска Девичанска Острва" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Девичанска острва, Америчка" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +#, fuzzy +msgid "Vietnam" +msgstr "вијетнамски" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Вануату" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Волис и Футуна" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "SAD/Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Мајоте" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Južna Afrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Замбија" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zibabve" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +# tree node string +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Zahteva" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "Obriši %1" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "афар" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "абкаски" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "акинески" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "аколи" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "адангме" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +#, fuzzy +msgid "Adyghe" +msgstr "адангме" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "афроазијски (остали)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "африхили" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "африканс" + +# entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space +# are allowed, otherwise translartion won't be used +# try to keep short, may be shortened due to bootloader limitations +# entry of bootloader menu - only a-z, A-Z, 0-9, _ and blank space +# are allowed, otherwise translartion won't be used +# try to keep short, may be shortened due to bootloader limitations +#. language code: ain +#: zypp/LanguageCode.cc:179 +#, fuzzy +msgid "Ainu" +msgstr "Linux:" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "акан" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "акадски" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "албански" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "алеут" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +#, fuzzy +msgid "Algonquian Languages" +msgstr "алгонквијски језици" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "јужни сами" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "амхарски" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "енглески, стари (око 450–1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +#, fuzzy +msgid "Apache Languages" +msgstr "језици Апача" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "арапски" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "арамајски" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "арагонски" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "јерменски" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "араукански" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "арапахо" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "вештачки (остали)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "аравак" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "асамешки" + +# Contry name +#. language code: ast +#: zypp/LanguageCode.cc:221 +#, fuzzy +msgid "Asturian" +msgstr "Austrija" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +#, fuzzy +msgid "Athapascan Languages" +msgstr "атапаскански језик" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +#, fuzzy +msgid "Australian Languages" +msgstr "аустралијски језици" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "аварски" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "авестан" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "авади" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "ајмар" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "азербејџански" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "банда" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +#, fuzzy +msgid "Bamileke Languages" +msgstr "бамилеке језици" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "башкир" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "балучи" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "бамбара" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "балинезе" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "баскијски" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "баса" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "балтички (остали)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "беџа" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "белоруски" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "бемба" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "бенгалски" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "бербер (остали)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "бојупи" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "бихари" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "бикол" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "бини" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "бислама" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "сиксика" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "банту (остали)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "бошњачки" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "браџ" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "бретањски" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "батак (Индонезија)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "буријат" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "бугинезе" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "бугарски" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "бурмиски" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +#, fuzzy +msgid "Blin" +msgstr "бини" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "кадо" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "централноамерички индијански (остали)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "карипски" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "каталонски" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "кавкаски (остали)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "цебуано" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "келтски (остали)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "чаморо" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "чибча" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "чеченски" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "чагатај" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kineski" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +#, fuzzy +msgid "Chuukese" +msgstr "чукезе" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "мари" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +#, fuzzy +msgid "Chinook Jargon" +msgstr "чиноок жаргон" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "чоктав" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "чипевјан" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "чироки" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "црквенословенски" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "чуваш" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "чејенски" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "чамски језици" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "коптски" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "корнвалски" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "корзикански" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +#, fuzzy +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "креолски и пиџински (остали)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +#, fuzzy +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "креолски и пиџински (остали)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +#, fuzzy +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "креолски и пиџински (остали)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "кри" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +#, fuzzy +msgid "Creoles and Pidgins (Other)" +msgstr "креолски и пиџински (остали)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +#, fuzzy +msgid "Kashubian" +msgstr "кабардијански" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "кушитски (остали)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Češka" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +#, fuzzy +msgid "Dakota" +msgstr "дакота\t" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danska" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +#, fuzzy +msgid "Dargwa" +msgstr "Darwin" + +#. language code: day +#: zypp/LanguageCode.cc:379 +#, fuzzy +msgid "Dayak" +msgstr "сасак" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "делавер" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "славски (атапаскански)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "догриб" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "динка" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "дивехи" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "догри" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "дравижански (остали)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +#, fuzzy +msgid "Lower Sorbian" +msgstr "Čuvanje Energije" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "дуала" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +#, fuzzy +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "холандски, средњевековни (око 1050—1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Holandija" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "ђула" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "дзонгка" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "ефик" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "египатски (стари)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "екаџук" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "еламит" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "енглески" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "енглески, средњевековни (1100—1500.)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "есперанто" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonski" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "еве" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "евондо" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "фанг" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "фарски" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "фанти" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "фиџијан" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +#, fuzzy +msgid "Filipino" +msgstr "Filipini" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finska" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "фино-угарски (остали)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "фон" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francuska" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "француски, средњевековни (око 1400—1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "француски, стари (842—око 1400.)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "фрижански" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "фула" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "фриулијански" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "га" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "гајо" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "гбаја" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "германски (остали)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "грузијски" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Nemačka" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "гиз" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "жибертески" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +#, fuzzy +msgid "Gaelic" +msgstr "Мали" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "ирски" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +#, fuzzy +msgid "Galician" +msgstr "гвичин" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "са острва Мана" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "немачки, средњевековни горњи (око 1050—1500.)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "немачки, стари горњи (око 750—1050.)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "гонди" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "горонтало" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "готски" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "гребо" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "грчки, стари (до 1453.)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "грчки, савремени (1453.—)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "гуарани" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "гујарати" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +#, fuzzy +msgid "Gwich'in" +msgstr "гвичин" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "хаида" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "Хаити" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "хауса" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "хавајски" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "хебрејски" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "хереро" + +# bug: highlight? +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "хилигајнон" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "химахали" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "хинду" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "хетски" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "хмонг" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +#, fuzzy +msgid "Hiri Motu" +msgstr "хири" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +#, fuzzy +msgid "Upper Sorbian" +msgstr "српски" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Mađarska" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "хупа" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "ибан" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "игбо" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "исландски" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "идо" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "сихуан ји" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "иџо" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "инуктитут" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "интерлингве" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "илоко" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "индијски (остали)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "индонежански" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "индоевропски (остали)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "ингуш" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "инупијак" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "ирански (остали)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +#, fuzzy +msgid "Iroquoian Languages" +msgstr "ироквојански језици" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italija" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "јавански" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +#, fuzzy +msgid "Lojban" +msgstr "Liban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japan" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "јудо-персијски" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "јудо-арапски" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "кара-калпак" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "кабил" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "качин" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +#, fuzzy +msgid "Kalaallisut" +msgstr "гренландски (калалисут)" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "камба" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "канада" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "карен" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "кашмирски" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "канури" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "кави" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "казахстански" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "кабардијански" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +#, fuzzy +msgid "Khasi" +msgstr "кази" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "косијански (остали)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "кмерски" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "котанезе" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "кикују" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "кинјарванда" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "киргишки" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "кимбунду" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "конкани" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "коми" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "конго" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreanski" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "косраенски" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "кпеле" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +#, fuzzy +msgid "Karachay-Balkar" +msgstr "кара-калпак" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "кру" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "курук" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "куанјама" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "кумик" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "курдски" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "кутенај" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ладино" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "ланда" + +# +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "ламбда" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "лао" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "латински" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "летонски" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "лежгијански" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "лимбуржански" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "лингала" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "литвански" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "монго" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "лози" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "луксембуршки" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "луба-лулуа" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "луба-катанга" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "ганда" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Луијсено" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Лунда" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "луо (Кенија и Танзанија)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "лушаји" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "македонски" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "мадурезе" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "магахи" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "маршалски" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "маитхили" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "макасар" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "малајамски" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "мандинго" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "маори" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "аустронежански (остали)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "марати" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "масаи" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "малајски" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +#, fuzzy +msgid "Moksha" +msgstr "мохавк" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "мандарски" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "менде" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "ирски, средњевековни (900-1200.)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +#, fuzzy +msgid "Mi'kmaq" +msgstr "микмак" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "минангкабау" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "разни језици" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "мон-кмер (остали)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "малагаси" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "малтешки" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "манчу" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +#, fuzzy +msgid "Manipuri" +msgstr "канури" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "манобо језици" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "мохавк" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "молдавски" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "монголски" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "моси" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "вишејезички" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "мунда језици" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "крик" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +#, fuzzy +msgid "Mirandese" +msgstr "мадурезе" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "марвари" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "језици маја" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +#, fuzzy +msgid "Erzya" +msgstr "орија" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "нахуатл" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +#, fuzzy +msgid "North American Indian" +msgstr "северноамерички индијански (остали)" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "напуљски" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Globalno/Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "ндебеле, јужни" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "ндебеле, северни" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ндонга" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "Nemačka" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "непалски" + +#. language code: new +#: zypp/LanguageCode.cc:795 +#, fuzzy +msgid "Nepal Bhasa" +msgstr "Непал" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "нијас" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "нигер-кордофански (остали)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "ниујеан" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +#, fuzzy +msgid "Norwegian Nynorsk" +msgstr "норвешки/модерни правопис" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "норвешки/бокмал" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +#, fuzzy +msgid "Nogai" +msgstr "ндонга" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "нордијски, стари" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norveška" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +#, fuzzy +msgid "Northern Sotho" +msgstr "северни сами" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "нубијски језици" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +#, fuzzy +msgid "Classical Newari" +msgstr "Ime klase" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +#, fuzzy +msgid "Chichewa" +msgstr "чибча" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +#, fuzzy +msgid "Nyamwezi" +msgstr "Ime" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "њанкол" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "њоро" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "нзима" + +# ??? +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "окситан (после 1500.)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "оџибва" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "орија" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "оромо" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "осаж" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "осетијан" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "турски, отомански (1500–1928)" + +# ??? +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "отомијански језици" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "папуан (остали)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "пангасинан" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "палави" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "пампања" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "панџаби" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "папијаменто" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "палауан" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "персијски, стари (око 600–400 п.н.е.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "персијски" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "филипински (остали)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "феничански" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "пали" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Poljska" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "понпејан" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugalija" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "пракрит језици" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "провансалски, стари (до 1500.)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "пушто" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "квечуа" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "раџастани" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "рапануји" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "раротонган" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "романски (остали)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "рето-романски" + +# овако каже Мортон-Бенсон, или „језик Рома“ +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "цигански" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +#, fuzzy +msgid "Romanian" +msgstr "Rumunija" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "рунди" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rusija" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "сандаве" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "санго" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "јакут" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "јужноамерички индијански (остали)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "салишан језици" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "самарићански арамајски" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "санскрит" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "сасак" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "сантали" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "српски" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +#, fuzzy +msgid "Sicilian" +msgstr "SAD/Michigan" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "шкотски" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Hrvatski" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "селкуп" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "семитски (остали)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "ирски, стари (до 900.)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "знаковни језици" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "шан" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "сидамо" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +#, fuzzy +msgid "Sinhala" +msgstr "синалезе" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "сијуан језици" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "сино-тибетски (остали)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "словенски (остали)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovačka" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "словеначки" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "јужни сами" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "северни сами" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "сами језици (остали)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "луле сами" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "инари сами" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "самоански" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "сколт сами" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "шона" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "синди" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "сонинке" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "согдијан" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "сомалски" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "сонгхај" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "сото, јужни" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Španija" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "сардинијски" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "серер" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "нило-сахарски (остали)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "свати" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "сукума" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "сунданежански" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "сузу" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "сумерски" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "свахили" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Švedska" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "сиријски" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "тахићански" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "тајландски (остали)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "тамил" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Татарски" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "телугу" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "тимне" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "терено" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "тетум" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "таџик" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "тагалог" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "тајландски" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "тибетски" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "тигар" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "тигрињски" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "тив" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +#, fuzzy +msgid "Klingon" +msgstr "конго" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +#, fuzzy +msgid "Tlingit" +msgstr "тлинклит" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "тамашек" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "тонга (Нијаса)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "тонга (Тонга острва)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "ток писин" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "цимшиан" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "цвана" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "цонга" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "туркменистански" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "тумбука" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "тупи језици" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turska" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "алтајски (остали)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "тви" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "тувинијански" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +#, fuzzy +msgid "Udmurt" +msgstr "урду" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "угарски" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "ујгур" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "украјински" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "умбунду" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "неодређен" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "урду" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "узбекистански" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "ваи" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "венда" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "вијетнамски" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "волапук" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "вотик" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "вакашан језици" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "валамо" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "варај" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "вашо" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "велшки" + +# моравско српски? +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "сорбски језици" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "валун" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "волоф" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +#, fuzzy +msgid "Kalmyk" +msgstr "кумик" + +# не ваља +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "гзоза" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "јао" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "јапески" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "јидишки" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "јоруба" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "јупик језици" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "запотек" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "зенага" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +#, fuzzy +msgid "Zhuang" +msgstr "Бутан" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "занде" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Itd/Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "зуни" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +# summary text heading +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "Paketi za obnavljanje" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +# translators: fallback name for a module at command line +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "nepoznato" + +#: zypp/VendorSupportOptions.cc:17 +#, fuzzy +msgid "unsupported" +msgstr " - није подржано" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +#, fuzzy +msgid "invalid" +msgstr "URL није исправан" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Не могу да отворим '%1'." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Не могу да отворим '%1'." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Не могу да отворим '%1'." + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +# continue button label +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +#, fuzzy +msgid "Continue?" +msgstr "Настави" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "ima neispunjene zahteve..." + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "ima neispunjene zahteve..." + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "Proveravam međuzavisnost..." + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +#, fuzzy +msgid "unsupported request" +msgstr " - није подржано" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "Automatska Instalacija" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +# progress stage +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Snimi konfiguracione fajlove" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +# TextEntry label +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "&Dodatne ipppd opcije" + +# Proposal for backup during update +#: zypp/target/rpm/RpmDb.cc:2230 +#, fuzzy, c-format, boost-format +msgid "created backup %s" +msgstr "Ne pravite sigurnosnu kopiju" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +#, fuzzy +msgid "History:" +msgstr "XF86History" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Наредба која се извршава при повезивању" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Не могу да отворим '%1'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Не могу да отворим '%1'." + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +# summary item: an option is turned on +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "&Da" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "&Ne" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Упозорење" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Greška" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "done" +msgstr "Indonezija" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "Greška" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Упозорење" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Покрећем..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "веза није успостављена" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +# summary item: an option is turned on +#: zypp-tui/output/promptoptions.cc:194 +#, fuzzy +msgid "yes" +msgstr "&Da" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +# summary text heading +#, fuzzy +#~ msgid "Package is not signed!" +#~ msgstr "Paketi za obnavljanje" + +# tree node string +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "Boot arhitektura" + +# summary text heading +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Paketi za obnavljanje" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "Ovaj paket nije i neće biti instaliran." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "Instalacioni proces nije uspešno završen." + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Instaliram na:" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%1 je u konfliktu sa %2" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "do not install %s" +#~ msgstr "Instaliram na:" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "Instaliram na:" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "Obriši %1" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Инсталација" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "веза није успостављена" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "Instaliram na:" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +# name for SCG +#~ msgid "Serbia and Montenegro" +#~ msgstr "Србија и Црна Гора" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "Proveravam međuzavisnost..." + +#, fuzzy +#~ msgid "%s remove failed" +#~ msgstr "rpm greška." + +#, fuzzy +#~ msgid "rpm output:" +#~ msgstr "" +#~ "\n" +#~ "Komandni izlaz:" + +#, fuzzy +#~ msgid "%s install failed" +#~ msgstr "Instalacioni proces nije uspešno završen." + +# PushButton: Allright, really start installation +# PushButton: Allright, really start installation +#, fuzzy +#~ msgid "%s installed ok" +#~ msgstr "&Da, instaliraj" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "%1 je u konfliktu sa %2" + +# error popup message +#, fuzzy +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Direktorijum %1 je već na listi." + +#, fuzzy +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "Ignore this requirement just here" +#~ msgstr "ima neispunjene zahteve..." + +# summary heder +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Instaliranje nedostajućih paketa" + +# summary heder +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "Instaliranje nedostajućih paketa" + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "install %s" +#~ msgstr "Instaliraj %1" + +#, fuzzy +#~ msgid "unlock %s" +#~ msgstr "Satovi" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "Ovaj paket nije i neće biti instaliran." + +#, fuzzy +#~ msgid "%s has missing dependencies" +#~ msgstr "Proveravam međuzavisnost..." + +#, fuzzy +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "Proveravam međuzavisnost..." + +#, fuzzy +#~ msgid "No need to install %s" +#~ msgstr "mora da se reinstalira" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "Proveravam međuzavisnost..." + +#, fuzzy +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%1 je u konfliktu sa %2" + +#, fuzzy +#~ msgid ", Action: " +#~ msgstr "Akcija" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "Establishing %s" +#~ msgstr "Instaliram na:" + +# Frame title for installation target hard disk / partition(s) +#, fuzzy +#~ msgid "Installing %s" +#~ msgstr "Instaliram na:" + +#, fuzzy +#~ msgid "Skipping %s: already installed" +#~ msgstr "Ovaj paket je već instaliran. Obrišite ga." + +#, fuzzy +#~ msgid " Error!" +#~ msgstr "Greška" + +#, fuzzy +#~ msgid " Important!" +#~ msgstr "Unos podataka" + +#, fuzzy +#~ msgid "Ignore this requirement generally" +#~ msgstr "ima neispunjene zahteve..." + +# button for message box with help text +#~ msgid "Ok" +#~ msgstr "U redu" + +# summary text heading +#, fuzzy +#~ msgid "The package file has incorrect MD5 sum" +#~ msgstr "Paketi za obnavljanje" + +# summary text heading +#, fuzzy +#~ msgid "The package archive has incorrect MD5 sum" +#~ msgstr "Paketi za obnavljanje" + +#~ msgid "Default" +#~ msgstr "Podrazumevano" + +#, fuzzy +#~ msgid "installed" +#~ msgstr "Instaliraj" + +#, fuzzy +#~ msgid "to be installed (soft)" +#~ msgstr "mora da se reinstalira" + +#, fuzzy +#~ msgid "to be uninstalled" +#~ msgstr "mora da se reinstalira" diff --git a/po/sv.po b/po/sv.po new file mode 100644 index 0000000..602f84c --- /dev/null +++ b/po/sv.po @@ -0,0 +1,5758 @@ +# translation of zypp.sv.po to Swedish +# translation of zypp.po to +# Swedish message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2001 SuSE GmbH. +# +# Mattias Newzella , 2001. +# Gudmund Areskoug , 2001. +# Mattias Newzella , 2007. +# Jonas Svensson , 2016. +msgid "" +msgstr "" +"Project-Id-Version: zypp.sv\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-07-21 12:47+0000\n" +"Last-Translator: Luna Jernberg \n" +"Language-Team: Swedish \n" +"Language: sv\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.6.2\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Okänt land: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Ingen kod" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Förenade Arabemiraten" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua och Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albanien" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenien" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Nederländska Antillerna" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarktis" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikanska Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Österrike" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australien" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Åland" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbajdzjan" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnien-Hercegovina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgien" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgarien" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brasilien" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvetön" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Vitryssland" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Kokosöarna" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Centralafrikanska republiken" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Schweiz" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Elfenbenskusten" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cooköarna" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Kina" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Kuba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Kap Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Julön" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cypern" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tjeckien" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Tyskland" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danmark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominikanska republiken" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algeriet" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estland" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypten" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Västsahara" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spanien" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopien" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falklandsöarna (Malvinas)" + +# official_name for FSM +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federala staterna Mikronesien" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Färöarna" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Frankrike" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Franska metropolitan" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Storbritannien" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgien" + +# GF +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Franska Guiana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grönland" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatorialguinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grekland" + +# GS +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Sydgeorgien och södra Sandwichöarna" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +# HM +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heardön och McDonaldöarna" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Kroatien" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Ungern" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesien" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Isle of Man" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Indien" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Brittiskt territorium i Indiska Oceanen" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Island" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italien" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordanien" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +# KG +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirgisistan" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kambodja" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comorerna" + +# KN +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Sankt Kitts och Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Nordkorea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Sydkorea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Caymanöarna" + +# KZ +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakstan" + +# CD +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Demokratiska folkrepubliken Lao" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Libanon" + +# LC +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Sankt Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litauen" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Lettland" + +# LR +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libyen" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marocko" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldavien" + +# Libris vill ha det så. +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +# SM +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Saint Martin" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshallöarna" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonien" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongoliet" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Nordmarianerna" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauretanien" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +# MV +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldiverna" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexiko" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Moçambique" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nya Kaledonien" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolköarna" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Nederländerna" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norge" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nya Zeeland" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Franska Polynesien" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Nya Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filippinerna" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polen" + +# PM +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Sankt Pierre och Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +# official_name for PSE +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Ockuperade palestinska territoriet" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Réunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Rumänien" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbien" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Ryska federationen" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudiarabien" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Salomonöarna" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychellerna" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Sverige" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sankt Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenien" + +# SJ +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard och Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakien" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé och Príncipe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +# Libris vill ha det så. +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syrien" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks- och Caicosöarna" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tchad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Franska sydterritorierna" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadzjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisien" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Östtimor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkiet" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad och Tobago" + +# Libris vill ha det så. +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvaluanska" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraina" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "USA:s avlägsna mindre öar" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "USA" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +# VA +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikanstaten" + +# VC +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Sankt Vincent och Grenadinerna" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Brittiska Jungfruöarna" + +# VI +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Jungfruöarna, amerikanska." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# WF +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis och Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Jemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Sydafrika" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Tillhandahåller" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Förutsätter" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Kräver" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "I konflikt" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Gör inaktuellt" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Rekommenderar" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Föreslår" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Utökar" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Kompletterar" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Försökte importera icke existerande nyckel %s till nyckelringen %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Det gick inte att importera nyckeln." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Det gick inte att ta bort nyckeln." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Signaturfilen %s hittas inte" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Okänt språk: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abchaziska" + +# Libris vill ha achinese här. +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinesiska" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adygeiska" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afroasiatiska språk (övriga)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akkadiska" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanska" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutiska" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Algonkinska språk" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Sydaltaiska" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amhariska" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Fornengelska (ca 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Apachiska språk" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabiska" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Arameiska" + +# Libris vill ha "aragonsk spanska" +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonska" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Armeniska" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araukanska" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Konstgjorda språk (övriga)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawakiska" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamesiska" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturiska" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Athapaskiska språk" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Australiska språk" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avariska" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestiska" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerbajdzjanska" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Bamilekespråk" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Basjkiriska" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinesiska" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Baskiska" + +# Libris har med den där parentesen +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Basa (bantuspråk)" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltiska språk (övriga)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beyja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Vitryska" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengaliska" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berberspråk (övriga)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +# Libris har med parentesen +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Edo (bini)" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +# Länge leve Libris! +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Svartfotindianernas språk (siksika)" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantuspråk (övriga)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosniska" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Bretonska" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonesien)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Burjatiska" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Buginesiska" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgariska" + +# Libris vill ha det så. +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmanska" + +# Libris har med parentesen +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Centralamerikanska indianspråk (övriga)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Karibiska" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalanska" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kaukasiska språk (övriga)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Keltiska språk (övriga)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tjetjenska" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Kinesiska" + +# Libris vill ha det så. +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Tjuktjiska" + +# Alternativt tjeremissiska enligt Libris. +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mariska" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Chinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Chopi" + +# Libris vill ha det så. +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Cherokesiska" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Fornkyrkoslaviska" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Tjuvasjiska" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Chamicspråk" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Koptiska" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Korniska" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Korsikanska" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreol- och pidginspråk, baserade på engelska (övriga)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreol- och pidginspråk, baserade på franska (övriga)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreol- och pidginspråk, baserade på portugisiska (övriga)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Krimtatariska" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreol- och pidginspråk (övriga)" + +# Osäker +# Ej verifierat +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kasjubiska" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Kushitiska språk (övriga)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tjeckiska" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danska" + +# Libris vill ha "Darginska (Dargwa)". Jag antar att Dargwa är vanligare. +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dajakiska" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidiska språk (övriga)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Lågsorbiska" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Medelnederländska (ca 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Nederländska" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dyula" + +# Libris vill ha med parentesen. +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Bhutanesiska (Dzongkha)" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Fornegyptiska" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamitiska" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Engelska" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Medelengelska (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estniska" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Färöiska" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +# SAOL vill ha utan d, Libris med d. Jag kör på SAOL:s variant. +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fijianska" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filippinska" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finska" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Finsk-ugriska språk (övriga)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Franska" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Medelfranska (ca 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Fornfranska (842-ca 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frisiska" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulani" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friuliska" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Germanska språk (övriga)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Georgiska" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Tyska" + +# Libris vill ha det så. +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Fornetiopiska (Geez)" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Gilbertesiska" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gaeliska" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Iriska" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galiciska" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Medelhögtyska (ca 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Fornhögtyska (ca 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotiska" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grekiska, klassisk (-1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Nygrekiska (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Guaraní" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwichin" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Haida" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Haitiska" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Haussa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawaiiska" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Hebreiska" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +# Libris vill ha det så. +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Pahari (himachali)" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +# Libris vill ha det så. +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hettitiska språk" + +# Libris vill ha det så. +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmongspråk" + +# Libris vill ha det så. +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hirimotu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Högsorbiska" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Ungerska" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +# Libris vill ha det så. +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Ibo (Igbo)" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Isländsk" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (International Auxiliary Language Association)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indoariska språk (övriga)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonesiska" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indoeuropeiska språk (övriga)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingusj" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iranska språk (övriga)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Irokesiska språk" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Italienska" + +# Libris vill ha det så. +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Javanska" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japanska" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Judepersiska" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Judearabiska" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Karakalpakiska" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabyliska" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Grönländska (Kalaallisut)" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +# Även kanaresiska (äldre form) +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +# Libris vill ha det så. +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Fornjavanska (kawi)" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazakiska" + +# Libris vill ha det så. +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardinska (östtjerkessiska)" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Khoisanspråk (övriga)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Kambodjanska (khmer)" + +# Libris vill ha det så. +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Sakiska (khotanesiska)" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Rwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirgisiska" + +# Libris vill ha det så. +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Mbundu (kimbundu)" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kikongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Koreanska" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kusaie" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpelle" + +# Osäker +# Ej verifierat +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karatjaj-balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Kruspråk" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kurukh" + +# Libris vill ha det så. +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Ovambo (kuanyama)" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurdiska" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenai" + +# Libris vill ha det så. +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Spanjolska (ladino)" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Laotiska" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latin" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Lettiska" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezginska" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limburgiska" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litauiska" + +# Libris vill ha det så. +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Lolo (mongo)" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Luxemburgiska" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Luganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Luo (Kenya och Tanzania)" + +# Libris vill ha det så. +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonska" + +# Libris vill ha det så. +# Även madura. +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurese" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshallesiska" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +# Libris vill ha det så. +# Även malinke. +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mande" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Austronesiska språk (övriga)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Massajiska" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malajiska" + +# Osäker +# Ej verifierat +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Medeliriska (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Mic-mac" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Diverse språk" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-khmerspråk (övriga)" + +# Libris vill ha det så. +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malagasy" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Maltesiska" + +# Även mandju. +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Manobospråk" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldaviska" + +# Libris vill ha det så. +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongoliska språk" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Flera språk" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Mundaspråk" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Muskogee" + +# Libris vill ha det så. +# Även madura. +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandesiska" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Mayaspråk" + +# http://www.geocities.com/forfader/samerna/uraliska.html +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Nordamerikanska indianspråk" + +# Libris vill ha det så. +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Neapolitansk italienska" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele, syd" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele, nord" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Lågtyska" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepali" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Nepalesisk bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-/Kongospråk (övriga)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Nynorska" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Nynorska (Bokmal)" + +# Libris vill ha det så +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogaiska" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Fornisländska" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norska" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Nordsotho" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Nubiska språk" + +# Osäker +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Klassisk newariska" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +# Libris vill ha det så. +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Langue d'oc (1500-)" + +# Libris vill ha det så. +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Odjibwa (chippewa)" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +# Libris vill ha det så. +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetiska" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Ottomanska (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Oto-manguespråk" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papuanska språk (övriga)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangasinan" + +# Libris vill ha det så. +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi (medelpersiska)" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +# Även panjabi. +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Punjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Fornpersiska (ca 600-400 f.Kr.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Persiska" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filippinska språk (övriga)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Feniciska" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polska" + +# Libris vill ha det så. +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Ponape" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portugisiska" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Prakritspråk" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Fornprovensalska (till och med 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pashto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Rarotongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Romanska språk (övriga)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Rätoromanska" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Rumänska" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Ryska" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Jakutiska" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Sydamerikanska indianspråk (övriga)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Salisiska språk" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Samaritanska" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbiska" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilianska" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Skotska" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Kroatiska" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitiska språk (övriga)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Forniriska (-900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Teckenspråk" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidami" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Singalesiska" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Siouxspråk" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sinotibetanska språk (övriga)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Slaviska språk (övriga)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakiska" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovenska" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Sydsamiska" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Nordsamiska" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Samiska språk (övriga)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Lulesamiska" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Enaresamiska" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samoanska" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Skoltsamiska" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdiska" + +# Libris vill ha det så. +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Sotho, syd" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Spanska" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardiska" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-sahariska språk (övriga)" + +# Libris vill ha det så. +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Swazi" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Sukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanesiska" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Sumeriska" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Swahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Svenska" + +# Libris vill ha det så. +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Syriska" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahitiska" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Thaispråk (övriga)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatariska" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telugo" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Temne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadzjikiska" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Thailändska" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetanska" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigré" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinja" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tivi" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingonska" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Tongaöarna)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +# Libris vill ha det så. +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turkmeniska" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Tumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Tupíspråk" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turkiska" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altaiska språk (övriga)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Tuvinska" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Udmurtiska" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ugaritiska" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Uiguriska" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Ukrainska" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Odefinierat språk" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Uzbekiska" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamesiska" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapük" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votiska" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Wakusjiska språk" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +# Libris vill ha det så. +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Kymriska" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Sorbiska språk" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Vallonska" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +# Libris vill ha det så. +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmuckiska" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yap" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Jiddisch" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Yupiska språk" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapotek" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Följande åtgärder kommer att vidtas:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "går inte ut" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "gick ut: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "går ut: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(går inte ut)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(UTGÅNGEN)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(går ut inom 24 timmar)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(går ut om %d dag)" +msgstr[1] "(går ut om %d dagar)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "okänd" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "stöds inte" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Nivå 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Nivå 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Nivå 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Ytterligare kundavtal behövs" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "Utgått och ersatt av ett annat paket" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "ogiltig" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Supportnivån har inte angetts" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Leverantören tillhandahåller inte support." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Problembestämning – innebär teknisk support som ska kunna ge " +"kompatibilitetsinformation, installationshjälp, användningssupport, " +"underhåll och grundläggande felsökning. Support på nivå 1 är inte avsedd att " +"korrigera produktfel." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Problemisolering – innebär teknisk support som ska kunna återskapa " +"kundproblemen, isolera problemområdet och ge lösningar på problem som inte " +"åtgärdas av supporten på nivå 1." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Problemlösning – innebär teknisk support som ska kunna lösa komplexa problem " +"som har identifierats i supporten på nivå 2 med hjälp av tekniker." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Ytterligare ett kundavtal behövs för att kunna ge support." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" +"Paketet har utgått och har ersatts av ett nytt paket med ett annat namn." + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Okänt supportalternativ. Beskrivning är inte tillgänglig" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Systemhanteringen är låst av programmet med pid %d (%s).\n" +"Stäng detta program och försök igen." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Okänt matchningsläge '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Okänt matchningsläge '%s' för mönstret '%s'" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Ogiltigt reguljärt uttryck '%s': regcomp returnerade %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ogiltigt reguljärt uttryck '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Autentisering krävs för '%s'" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "Kommer att försöka igen..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "Ger upp efter %1% försök." + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Besök SUSE kundcenter för att se om din registrering är giltig och inte har " +"slutat gälla." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Besök Novells kundcenter och kontrollera att din registrering är giltig och " +"fortfarande gäller." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "Skapa fästpunkt: hittar ingen skrivbar katalog för att skapa fästpunkt" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Installera paketet 'lsof' först." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Kan inte att skapa cachekatalog för metadata." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Det gick inte att läsa från '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Kan inte skapa %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Giltig metadata hittades inte på specificerad URL" +msgstr[1] "Giltig metadata hittades inte på specificerade URL:er" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" +"Misslyckades att cachelagra lagringsplats ( kunde inte starta repo2solv )." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Misslyckades att cachelagra lagringsplats (%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Cache för lagringsplatsen '%s' byggs" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Kan inte att skapa cache på %s - ingen skrivrättighet." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "Misslyckades att cachelagra lagringsplats %1%" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Kan inte hantera lagringsplatstypen" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Lägger till lagringsplats '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Ogiltigt namn på lagringsplats '%s'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Kan inte skriva till filen '%s'." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Ett okänt fel uppstod vid läsning från '%s'" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Kan inte läsa lagringsplatskatalog '%1%': Åtkomst nekad" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Det gick inte att läsa katalogen '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Kan inte läsa lagringsplatsfilen '%1%': Åtkomst nekad" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "Rensar metadata" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "Rensar paket" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "Rensar cache kataloger" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "Rensar katalog: %1%" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "Rensar cache" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "Laddar från cache" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Lagringsplatsen '%s' tas bort" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Kan inte identifiera var lagringsplatsen finns." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Kan inte radera '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "Modifierar lagringsplats" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "Uppdaterar lagringsplats: " + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Det gick inte att identifiera var tjänsten är lagrad." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Okänd tjänst '%1%': Tar bort övergiven lagringsplats '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Aliaset för en lagringsplats kan inte inledas med en punkt." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Ett alias för en tjänst kan inte inledas med en punkt." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "Ingen sammanfattning för fil %s." + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "Okänd sammanfattning %s för fil %s." + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "Sammanfattningsverifiering misslyckades för fil '%s'" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "Fil '%s' är osignerad, fortsätt?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "Fil '%s' från lagringsplats '%s' är osignerad, fortsätt?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "Vill du avvisa nyckeln, lita på tillfälligt eller alltid lita på?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "Nyckelnamn: %1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "Fick %1% ny paketsigneringsnyckel från lagringsplats \"%2%\":" +msgstr[1] "Fick %1% nya paketsigneringsnycklar från lagringsplatser \"%2%\":" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "Signaturverifiering misslyckades för fil '%1%'." + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" +"Signaturverifiering misslyckades för fil '%1%' från lagringsplats '%2%'." + +# continue button label +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Fortsätt?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "Fil '%s' har signerats med en okänd nyckel '%s'. Fortsätta?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" +"Fil '%s' från lagringsplats '%s' har signerats med en okänd nyckel '%s'. " +"Fortsätt?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Lagringsplatsen %1% definierar inte ytterligare 'gpgkey=' URL." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Söker efter gpg-nyckel med ID %1% i lager %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Söker efter gpg-nyckel med ID %1% i cache %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Det nödvändiga attributet '%s' saknas." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Ett av eller båda attributen '%s' och '%s' krävs." + +# %s is either BOOTP or DHCP +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Signaturen kunde inte verifieras" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Paketet %s verkar ha skadats under överföringen. Vill du försöka överföra " +"det på nytt?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Det gick inte att tillhandahålla paketet %s. Vill du försöka hämta det på " +"nytt?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm-kontrollen misslyckades." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm misslyckades." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Insticksprogrammet för tjänsten har inte stöd för ändring av attribut." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Det går inte att hämta filen %s från lagringsplats %s" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Det finns ingen URL i lagringsplats." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "Förväntat medium %1%/%2% identifierat av filen '%3%' med innehåll:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Fil %1%\n" +" från paketet\n" +" %2%\n" +" står i konflikt med fil från paketet\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Fil %1%\n" +" från paketet\n" +" %2%\n" +" står i konflikt med fil från installationen av\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Fil %1%\n" +" från installationen av\n" +" %2%\n" +" står i konflikt med fil från paketet\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Fil %1%\n" +" från installationen av\n" +" %2%\n" +" står i konflikt med fil från installationen av\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Fil %1%\n" +" från paketet\n" +" %2%\n" +" står i konflikt med fil\n" +" %3%\n" +" från paketet\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Fil %1%\n" +" från paketet\n" +" %2%\n" +" står i konflikt med fil\n" +" %3%\n" +" från installationen av\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Fil %1%\n" +" från installationen av\n" +" %2%\n" +" står i konflikt med fil\n" +" %3%\n" +" från paketet\n" +" %4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Fil %1%\n" +" från installationen av\n" +" %2%\n" +" står i konflikt med fil\n" +" %3%\n" +" från installationen av\n" +" %4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Kan inte skapa sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "bryt %s genom att ignorera vissa beroenden" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "ignorera generellt några beroende" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"det installerade %1% tillhör inte en uppgraderingslagringsplats och måste " +"ersättas" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "det som ska installeras %1% tillhör inte en uppdateringslagringsplats" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "det installerade %1% har sämre arkitektur" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "det som ska installeras %1% har sämre arkitektur" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "problem med den installerade %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "begäranden i konflikt" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "vissa beroendeproblem" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "ingenting tillhandahåller den begärda '%1%'" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Har du aktiverat alla nödvändiga lagringsplatser?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "det begärda paketet %1% finns inte" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "begäran stöds inte" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "'%1%' tillhandahålls av systemet och kan inte raderas" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% är inte installerbar" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "ingenting ger '%1%' som behövs av den installerade %2%" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "ingenting ger '%1%' som behövs för att %2% ska installeras" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "kan inte installera både %1% och %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"den installerade %1% står i konflikt med '%2%' från den installerade %3%" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" +"den installerade %1% står i konflikt med '%2%' från %3% som ska installeras" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" +"den installerade %1% står i konflikt med '%2%' som tillhandahålls av den " +"installerade %3%" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" +"den installerade %1% står i konflikt med '%2%' från %3% tillhandahålls av " +"%3% som ska installeras" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "det installerade %1% har föråldrat '%2%' från den installerade %3%" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"det installerade %1% har föråldrat '%2%' som tillhandahålls av det som ska " +"installeras %3%" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" +"det som ska installeras %1% har föråldrat '%2%' från det installerade %3%" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" +"det som ska installeras %1% har föråldrats '%2%' från det som ska " +"installeras %3%" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"Den installerade %1% står i konflikt med '%2%' som tillhandahålls av sig " +"själv" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" +"Det som ska installeras %1% står i konflikt med '%2%' som tillhandahålls av " +"sig själv" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" +"den installerade %1% kräver '%2%', men detta krav kan inte tillhandahållas" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" +"%1% som ska installeras kräver '%2%', men detta krav kan inte tillhandahållas" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "borttagna leverantörer: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"leverantörer som inte går att installera: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "leverantörer som inte går att installera: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% är ännu inte helt integrerad i %2%." + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" +"Vanligtvis vill du behålla PTF och välja att inte installera " +"underhållspatcharna." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" +"Att ta bort det installerade %1% i detta sammanhang kommer att ta bort (inte " +"ersätta!) De inkluderade PTF-paketen också." + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"PTF bör tas bort genom att kalla \"%1%\". Detta kommer att uppdatera de " +"inkluderade PTF-paketen snarare än att ta bort dem." + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "Vanligtvis vill du behålla PTF eller välja att avbryta åtgärden." + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "Den installerade %1% blockerar önskad åtgärd." + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "Vanligtvis vill du behålla PTF och välja att avbryta åtgärden." + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "ta bort lås för att tillåta borttagning av %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "installera inte %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "behåll %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "ta bort lås för att tillåta installation av %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Denna begäran kommer att knäcka systemet!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ignorera varningen om ett trasigt system" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "be inte om att installera en lösning som ger %1%" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "be inte om att ta bort alla lösningar som ger %1%" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "installera inte senaste versionen av %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "behåll %1% trots den sämre arkitekturen" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "installera %1% trots den sämre arkitekturen" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "behåll föråldrad %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "installera %1% från exkluderad lagringsplats" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "installera %1% fast den har blivit tillbakadragen" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "Tillåt installation av PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "installera %1% fast den har blivit svartlistad" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "nergradering av %1% till %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "arkitekturändring på %1% till %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"installera %1% (med leverantörsändring)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"installera %1% från leverantör %2%\n" +" ersätter %3% från leverantören %4%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "ersättning av %1% med %2%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "avinstallation av %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "Kör efter transaktionsskript" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "Kör %1% skript" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "%1% skriptutdata:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Installationen har avbrutits enligt instruktionerna." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " körd" + +# %s is either BOOTP or DHCP +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " körningen misslyckades" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s redan körd som %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " körningen hoppades över vid avbrottet" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Ett fel inträffade när ett uppdateringsmeddelande skickades." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Nytt uppdateringsmeddelande" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"Mottagen signal:\"%1% (%2%)\", för att säkerställa systemets konsistens är " +"det inte möjligt att avbryta en körande rpm-transaktion." + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "Det gick inte att utföra transaktionen på grund av följande problem:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM misslyckades: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Det gick inte att importera den offentliga nyckeln %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Det gick inte att ta bort den offentliga nyckeln %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "Pakethuvud är inte signerat!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "Paket payload är inte signerad!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Konfigurationsfiler har ändrats för %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "RPM sparade %s som %s, men det gick inte att avgöra skillnaden" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"RPM sparade %s som %s.\n" +"Här visas de första 25 raderna med skillnader:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "RPM skapade %s som %s, men det gick inte att avgöra skillnaden" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"RPM skapade %s som %s.\n" +"Här visas de första 25 raderna med skillnader:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Ytterligare RPM-utdata" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "skapade säkerhetskopian %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "Signaturen är OK" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Okänd signaturtyp" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Signaturen kan inte verifieras" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "Signaturen är OK, men nyckeln är inte betrodd" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Signaturens offentliga nyckel är inte tillgänglig" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Filen finns inte eller signaturen kan inte kontrolleras" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Filen är inte signerad" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Den tvivelaktiga typen '%s' för %u-bytekontrollsumma '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Kan inte öppna pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Det går inte att öppna programkopplingen (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Ogiltig LDAP URL-frågesträng" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Ogiltig LDAP URL-frågeparameter '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Det går inte att klona URL-objektet" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Den tomma URL-objektreferensen är ogiltig" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Det gick inte att analysera URL-komponenterna" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Historik:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "URL-schemat tillåter inte %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "%s-komponenten '%s' är ogiltig" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Ogiltig %s-komponent" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Analysering av frågesträng stöds inte för den här URL-adressen" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL-schemat är en obligatorisk komponent" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "URL-schemat '%s' är ogiltigt" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "URL-schemat tillåter inte något användarnamn" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "URL-schemat tillåter inte något lösenord" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Det måste finnas en värdkomponent i URL-schemat" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Det får inte finnas någon värdkomponent i URL-schemat" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Värdkomponenten '%s' är ogiltig" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "URL-schemat tillåter inte någon port" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Portkomponenten '%s' är ogiltig" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Det måste finnas ett sökvägsnamn för URL-schemat" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Relativa sökvägar tillåts inte om det finns behörighet" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Den kodade strängen innehåller ett NULL-byte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Ogiltigt avgränsningstecken för delning av parametermatris" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Ogiltigt avgränsningstecken för delning av parametermappning" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Ogiltigt avgränsningstecken för koppling av parametermatris" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Kommandot avslutades med statusen %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Kommandot avbröts av signalen %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Kommandot avslutades med ett okänt fel." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "Ogiltigt spawn argument angivet." + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "Kunde inte skapa kontrollrör." + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Kan inte ändra roten (chroot) till '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Kan inte ändra katalogen (chdir) till '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Kan inte ändra katalogen (chdir) till '%s' i chroot '%s' (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Kan inte köra '%s' (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Kan inte dela upp (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "Kan inte köra '%s', chdir misslyckades (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "Kan inte köra '%s', chroot misslyckades (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "Kan inte köra '%s', köra misslyckades (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "Kan inte köra '%s', oväntat fel." + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Misslyckades att montera %s på %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Misslyckades att avmontera %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Ogiltigt filnamn: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Mediet öppnades inte när åtgärden '%s' skulle utföras." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Filen '%s' kunde inte hittas på mediet '%s'" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Kan inte skriva filen '%s'." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Mediet är inte anslutet" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Felaktig anslutningspunkt för media" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Initieringen av hämtningen (curl) misslyckades för '%s'" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Systemundantaget '%s' uppstod för mediet '%s'." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Sökvägen '%s' på mediet '%s' är inte en fil." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Sökvägen '%s' på mediet '%s' är inte en katalog." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Felaktigt format för URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Tomt värdnamn i URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Tomt filsystem i URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Tomt mål i URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "URI-schemat i '%s' stöds inte." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Åtgärden stöds inte av mediet" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Ett hämtningsfel (curl) uppstod för '%s'.\n" +"Felkod: %s\n" +"Felmeddelande: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Ett fel uppstod när alternativ för hämtning (curl) skulle anges för '%s':" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Mediekällan '%s' innehåller inte önskat medium" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Mediet '%s' används av en annan instans" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Kan inte mata ut något medium" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Kan inte mata ut mediet '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Behörighet för åtkomst till '%s' nekad." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Tidsgränsen överskreds vid försök att nå '%s'." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Hämtade data överskred förväntad filstorlek '%s' av '%s'." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Platsen '%s' är för tillfället oåtkomlig." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL-certifikatsproblem, verifiera att CA-certifikatet för '%s' är OK." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "Inga fria resurser tillgängliga för att fästa medium." + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Det finns inte stöd för HTTP-autentiseringsmetoden '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Hämtningen (curl) fel för '%s':\n" +"fel kod: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Nerladdning (curl) fel för '%s':\n" +"Kunde inte hämta HTTP-svar\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ja" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nej" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Notera:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Varning:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Fel:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "klar" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "uppmärksamhet" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "fel" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Varning: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Hämtar:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "startar" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "hittades inte" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Det finns ingen hjälp till meddelandet." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "det finns ingen hjälp till alternativet" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "visar alla alternativ" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ja" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "nej" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Kör %%posttrans-skriptet '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Kör %p 1osttrans-skript" + +#~ msgid "Package is not signed!" +#~ msgstr "Paketet är inte signerat!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s tillhör inte ett distupgrade-förråd" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s innehåller en underordnad arkitektur" + +#~ msgid "problem with installed package %s" +#~ msgstr "problem med det installerade paketet %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "inget tillhandahåller begärda %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Har du aktiverat alla begärda lagringsplatser?" + +#~ msgid "package %s does not exist" +#~ msgstr "paketet %s finns inte" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s kommer från systemet och kan inte tas bort" + +#~ msgid "%s is not installable" +#~ msgstr "%s går inte att installera" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "inget tillhandahåller %s som behövs i %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "kan inte installera både %s och %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s är i konflikt med %s som kommer från %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s gör %s inaktuell som kommer från %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s gör %s som kommer från %s inaktuell" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "lösbara %s är i konflikt med %s som kommer från sig själv" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s behöver %s, men kravet kan inte uppfyllas" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "ta bort lås så att %s kan tas bort" + +#~ msgid "do not install %s" +#~ msgstr "installera inte %s" + +#~ msgid "keep %s" +#~ msgstr "behåll %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "ta bort lås så att %s kan installeras" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "fråga inte om att installera en lösbar med %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "fråga inte om att ta bort alla lösbara med %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "installera inte den senaste versionen av %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "behåll %s trots underordnad arkitektur" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "installera %s trots underordnad arkitektur" + +#~ msgid "keep obsolete %s" +#~ msgstr "behåll föråldrad version av %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "installera %s från undantaget arkiv" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "Nedgradera %s till %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "arkitekturändring av %s till %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "installera %s (med ändrad leverantör)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "ersätt %s med %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "avinstallation av %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Kan inte öppna låsfilen: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Åtgärden körs redan av ett annat program." + +#~ msgid "Hal Exception" +#~ msgstr "Hal-undantag" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Tyvärr är denna version av libzypp byggd utan stöd för HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext har inte anslutits" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive har inte initierats" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume har inte initierats" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Det gick inte att skapa dbus-anslutningen" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: Det gick inte att skapa libhal-kontext" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "libhal_set_dbus_connection: Det gick inte att ange dbus-anslutningen" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Det gick inte att initiera HAL-kontext - hald körs inte?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Inte en cd-rom-enhet" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Det går inte att initiera mutex-attribut" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Det går inte att ange rekursiva mutex-attribut" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Det går inte att initiera rekursivt mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Det går inte att hämta mutex-låset" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Det går inte att släppa mutex-låset" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "" +#~ "Det gick inte att importera den offentliga nyckeln från filen %s: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Det gick inte att ta bort den offentliga nyckeln %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Det gick inte att hitta en tillgänglig loop-enhet för montering av " +#~ "bildfilen från '%s'" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "inte installerad." + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "Kan inte skapa publik nyckel %s från %s nyckelring till filen %s" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Kunde inte öppna %s - %s\n" + +# name for SCG +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbien och Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Okänt alternativ för list" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "det gick inte att lösa beroenden" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s har inte någon kontrollsumma.\n" +#~ "Vill du använda filen ändå?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Integritetskontrollen för filen %s misslyckades med följande nyckel:\n" +#~ "%s|%s|%s\n" +#~ "Vill du använda filen ändå?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s har en ogiltig kontrollsumma.\n" +#~ "%s förväntades, men %s hittades\n" +#~ " Vill du använda filen ändå?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s har en okänd kontrollsumma.%s.\n" +#~ "Vill du använda filen ändå?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Filen %s har inte signerats.\n" +#~ "Vill du använda den ändå?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Filen %s har signerats med en okänd nyckel:\n" +#~ "%s|%s|%s\n" +#~ "Vill du använda filen ändå?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "En osäker nyckel hittades:\n" +#~ "%s|%s|%s\n" +#~ "Vill du lita på nyckeln?" diff --git a/po/ta.po b/po/ta.po new file mode 100644 index 0000000..69135d1 --- /dev/null +++ b/po/ta.po @@ -0,0 +1,5951 @@ +msgid "" +msgstr "" +"Project-Id-Version: NetworkManager-vpnc\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-06-20 12:46+0000\n" +"Last-Translator: Rajasekaran Karunanithi \n" +"Language-Team: Tamil \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: Weblate 5.6\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "அறிந்திராத நாடு:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "குறியீடு இல்லை" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "அன்டோரா" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "ஐக்கிய அரபு நாடுகள்" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "ஆப்கானிஸ்தான்" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "ஆன்டிகுவா மற்றும் பார்புடா" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "அங்வில்லா" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "அல்பேனியா" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "ஆர்மீனியா" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "நெதர்லாந்து அண்டிலிஸ்" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "அங்கோலா" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "அண்டார்டிகா" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "அர்ஜென்டினா" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "அமெரிக்க சமோவா" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "ஆஸ்திரியா" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "ஆஸ்திரேலியா" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "அருபா" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "அலண்ட் தீவுகள்" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "அஜர்பைஜான்" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "பாஸ்னியா மற்றும் ஹெர்சகோவினா" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "பார்படாஸ்" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "பங்களாதேஷ்" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "பெல்ஜியம்" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "பர்கினா ஃபாஸோ" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "பல்கேரியா" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "பஹ்ரைன்" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "புருண்டி" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "பெனின்" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "பெர்முடா" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "புரூனய் தாருசலாம்" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "பொலிவியா" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "பிரேசில்" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "பஹாமாஸ்" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "பூட்டான்" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "பூவெட் தீவு" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "பாட்ஸ்வானா" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "பெலாரஸ்" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "பெலிஸ்" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "கனடா" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "கோகோஸ் (கீலிங்) தீவுகள்" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "காங்கோ" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "மத்திய ஆப்பிரிக்க குடியரசு" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "சுவிட்சர்லாந்து" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "கோடே த’ஐவரி" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "குக் தீவுகள்" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "சிலி" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "கேமரூன்" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "சீனா" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "கொலம்பியா" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "காஸ்டா ரிகா" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "கியூபா" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "கேப் வெர்ட்" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "கிறிஸ்துமஸ் தீவு" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "சைப்ரஸ்" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "செக் குடியரசு" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "ஜெர்மனி" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "ஜிபெளட்டி" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "டென்மார்க்" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "டொமினிகா" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "டொமினிக்கன் குடியரசு" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "அல்ஜீரியா" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "ஈக்வடார்" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "எஸ்டோனியா" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "எகிப்து" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "மேற்கு சஹாரா" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "எரிட்ரியா" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "ஸ்பெயின்" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "எத்தியோப்பியா" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "பின்லாந்து" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "ஃபிஜி" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "ஃபால்க்லாந்து தீவுகள் (மால்வினாஸ்)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "மைக்ரோனேசிய நாடுகளின் கூட்டமைப்பு" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "ஃபாரோ தீவுகள்" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "பிரான்ஸ்" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "பெருநகர பிரான்ஸ்" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "காபோன்" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "ஐக்கிய இராச்சியம்" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "கிரெனடா" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "ஜார்ஜியா" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "பிரஞ்சு கயானா" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "குர்ன்சி" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "கானா" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "ஜிப்ரால்டர்" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "கிரீன்லாந்து" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "காம்பியா" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "கினியா" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "காடேலூப்" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "ஈக்வடோரியல் கினியா" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "கிரீஸ்" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "தென் ஜியார்ஜியா மற்றும் தென் சான்ட்விச் தீவுகள்" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "குவாதமாலா" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "குவாம்" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "கினியா-பிசாவ்" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "கயானா" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "ஹாங் காங்" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "ஹேர்ட் தீவு மற்றும் மெக்டொனால்ட் தீவுகள்" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "ஹோண்டுராஸ்" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "குரோஷியா" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "ஹைட்டி" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "ஹங்கேரி" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "இந்தோனேசியா" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "அயர்லாந்து" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "இஸ்ரேல்" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "மனித தீவு" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "இந்தியா" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "பிரிட்டிஷ் இந்துமாக் கடல் எல்லை" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "ஈராக்" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "ஈரான்" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "ஐஸ்லாந்து" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "இத்தாலி" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "ஜெர்சி" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "ஜமைக்கா" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "ஜோர்டான்" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "ஜப்பான்" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "கென்யா" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "கிர்கிஸ்தான்" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "கம்போடியா" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "கிரிபாட்டி" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "கோமரோஸ்" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "செயின்ட் கிட்ஸ் மற்றும் நெவிஸ்" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "வட கொரியா" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "தென் கொரியா" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "குவைத்" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "கெய்மன் தீவுகள்" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "லாவோ மக்கள் ஜனநாயக குடியரசு" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "லெபனான்" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "செயின்ட் லூசியா" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "லிச்சன்ஸ்டெயின்" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "இலங்கை" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "லைபீரியா" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "லெசோத்தோ" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "லிதுவேனியா" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "லக்சம்பர்க்" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "லாட்வியா" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "லிபியா" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "மொராக்கோ" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "மொனாக்கோ" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "மால்டோவா" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "மாண்டினீக்ரோ" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "சான் மரினோ" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "மடகாஸ்கர்" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "மார்ஷல் தீவுகள்" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "மாசிடோனியா" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "மாலி" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "மியான்மர்" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "மங்கோலியா" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "மக்காவ்" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "வட மாரியானா தீவுகள்" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "மார்டினிக்" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "மொரிட்டானியா" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "மான்ட்செர்ரட்" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "மால்டா" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "மொரிஷியஸ்" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "மாலத்தீவுகள்" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "மலாவி" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "மெக்சிகோ" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "மலேசியா" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "மொசாம்பிக்" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "நமீபியா" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "புதிய கலிடோனியா" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "நைஜர்" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "நார்போக் தீவு" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "நைஜீரியா" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "நிகரகுவா" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "நெதர்லாந்து" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "நார்வே" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "நேபாளம்" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "நவ்ரு" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "நியூ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "¿¢äº¢Ä¡óÐ" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "§º÷Áý" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "ÀÉ¡Á¡" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "¦ÀÕ" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "பிரெஞ்சு பாலினேசியா" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "பாப்புவா நியூ கினியா" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "ஃபிலிப்பைன்ஸ்" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "¾¡öÅ¡ý" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "§À¡Ä¡óÐ" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "செயின்ட் பியரி மற்றும் மிக்வலான்" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "பிட்கெய்ர்ன்" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "பியூர்டோ ரிகோ" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "பாலஸ்தீனிய எல்லை" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "§À¡÷òиø" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Àá̧Å" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Àá̧Å" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Á¡ø¼¡" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "ரீயூனியன்" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Õ§Áɢ¡" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "¦º÷À¢Âý" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "ரஷ்ய கூட்டரசு" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "¸É¼¡" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "சவூதி அரேபியா" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "«Â÷Ä¡óÐ" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "செய்செலஸ்" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "ݼ¡ý" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "ÍÅ£¼ý" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "சிங்கப்பூர்" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "செயின்ட் ஹெலனா" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "ͧġŢɢ¡" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "ஸ்வால்பார்ட் மற்றும் ஜான் மேயன்" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "ͧġš츢Â" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "ஸியரா லியோன்" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "சான் மரினோ" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "செனகல்" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Õ§Áɢ¡" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "¦º÷À¢Â¡" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "சாவோ டோம் மற்றும் பரின்சிபே" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "±ø º¡øÅ§¼¡÷" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "¦º÷À¢Â¡" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "¾¡öÄ¡óÐ" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "டர்க்ஸ் மற்றும் கெய்கோஸ் தீவுகள்" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "º£É¡" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "பிரெஞ்சு தென் எல்லைகள்" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "டோகோ" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "¾¡öÄ¡óÐ" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "¾¡öÅ¡ý" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "டோகேலாவ்" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "¾¡öÅ¡ý" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ú¢Â¡" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "டோங்கா" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "கிழக்கு தைமூர்" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "ÐÕ츢" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ðâɢ¼¡ð & ¦¼¡À¡§¸¡" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Ýæ" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "¾¡öÅ¡ý" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "டான்சானியா" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "¯ì¦Ãöý" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "¸É¼¡" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "³ì¸¢Â «¦ÁÃ¢ì¸ ¿¡Î¸û" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "³ì¸¢Â «¦ÁÃ¢ì¸ ¿¡Î¸û" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "¯Õ̧Å" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "¾¡öÅ¡ý" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "ஹோலி ஸீ (வாடிகன் நகர மாகாணம்)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "¦ºÂ¢ýð Å¢ý¦ºýð & ¸¢¦ÃÉËý¸û" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "¦ÅÉ¢ÍÅÄ¡" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "À¢ýÄ¡óÐ" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "À¢ýÄ¡óÐ" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "வானுவாடூ" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "வாலிஸ் மற்றும் ஃபுடூனா" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "¦¸¡ÄõÀ¢Â¡" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "யேமன்" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "மயோட்" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "¦¾ý ¬ôâ측" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "ƒº¦Áö측" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "ஜிம்பாப்வே" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s %sஐ வழக்கற்றதாக்குகிறது:" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "உள்ளீடு காணப்படவில்லை." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "அறியப்படாத மொழி: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "தொலைதூரம்" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "«º÷¨Àº¡ý" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "º£É" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "அகோலி" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "அடாங்மே" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "அடிகே" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "ஆப்பிரிக்க-ஆசிய (மற்றவை)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "ஆப்ரிஹிலி" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "¬·À⸡ýÍ" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "அய்னு" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "¬·À⸡ýÍ" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "அக்கடியன்" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "«º÷¨Àº¡ý" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "அல்யூட்" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "¦¾ý ¬ôâ측" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "«Ã¡À¢ì" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "ஆங்கிலம், புராதன (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "«Ã¡À¢ì" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "«Ã¡À¢ì" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "அரகோனீஸ்" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "¬÷¦ºƒýÊÉ¡" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Ä¢òЧÅɢ¡" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "அரபாஹோ" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "செயற்கை (மற்றவை)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "அரவாக்" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "அசாமிய" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "¬Íò¾¢Ã¢Â¡" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "«Ã¡À¢ì" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "அவெஸ்டான்" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "அவதி" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "ÀÉ¡Á¡" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "«º÷¨Àº¡É¢" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "¸É¼¡" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "பாமிலேகே மொழிகள்" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "பஷ்கீர்" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "பலுச்சி" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "ƒº¦Áö측" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "º£É" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "À¡ÍìÌ" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "À¡ÍìÌ" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "பால்டிக் (மற்றவை)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "பெஜா" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "¦ÀÄ¡åÍ" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "பெம்பா" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "¦Àøº¢Âõ" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "பெர்பெர் (மற்றவை)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "போஜ்புரி" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "À¢§Ãº¢ø" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "பைகோல்" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "பினி" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "பிஸ்லாமா" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "சிக்சிகா" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "பன்டு (மற்றவை)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "¯Õ§ÁÉ¢Â" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "À¢§Ãº¢ø" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "À¢Ã¢¼¡ý" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "­ó§¾¡É£º¢Â¡" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Àø§¸Ã¢Â¡" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "º£É" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Àø§¸Ã¢Âý" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "பர்மிய" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Àø§¸Ã¢Âý" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "º£É¡" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "மத்திய அமெரிக்க இந்திய (மற்றவை)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Á¡µÃ¢" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "¦¸¼Ä¡ý" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "காகாசியன் (மற்றவை)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "செபுவானோ" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "செல்டிக் (மற்றவை)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "சமாரோ" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "º£É¡" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "¦ºì" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "சகடாய்" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "º£É" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "º£É" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Á¡µÃ¢" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "சினூக் ஜார்கன்" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "சோக்டாவ்" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "சிப்யூயான்" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "செரோக்கீ" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "சர்ச் ஸ்லாவிக்" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "சுவாஷ்" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "செயன்" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "̦á§Åº¢Â¡" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "³Ã¢Í" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "̦á§Åº¢Âý" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "க்ரியோலஸ் மற்றும் பிட்ஜின்ஸ், ஆங்கிலம் சார்ந்தது (மற்றவை)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "க்ரியோலஸ் மற்றும் பிட்ஜின்ஸ், பிரெஞ்சு சார்ந்தது (மற்றவை)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "க்ரியோலஸ் மற்றும் பிட்ஜின்ஸ், போர்த்துக்கீசிய மொழி சார்ந்தது (மற்றவை)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "¸¢§Ãì¸" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "க்ரிமியன் டார்டர்" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "க்ரியோலஸ் மற்றும் பிட்ஜின்ஸ் (மற்றவை)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "கசுபியன்" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "குஷிடிக் (மற்றவை)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "¦ºì" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "டகோடா" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "§¼É¢Í" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "டார்க்வா" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "டாயக்" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "டெலாவேர்" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "ஸ்லேவ் (அதபாஸ்கன்)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "டாக்ரிப்" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Õ§Áɢ¡" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "டிவேஹி" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Á¡µÃ¢" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "திராவிட (மற்றவை)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "¦º÷À¢Âý" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Àá̧Å" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "டச்சு, மத்திய (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "¼îÍ" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "டியூலா" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "ஜாங்கா" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "ஈஃபிக்" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "எகிப்து (புராதன)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "எகாஜக்" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "எலாமைட்" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "§¼É¢Í" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "ஆங்கிலம், மத்திய (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "±ÍÀáý§¼¡" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "±Í§¼¡É¢Â" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "ஈவ்" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "இவான்டோ" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "À¢Ã¡ýÍ" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "«Â÷Ä¡óÐ" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "ஃபன்டி" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "À¢ýÄ¡óÐ" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "ஃபிலிப்பினோ" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "À¢ýÉ¢Í" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "ஃபின்னோ-உக்ரியன் (மற்றவை)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "ஃபான்" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "À¢¦Ãýî " + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "பிரெஞ்சு, மத்திய (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "பிரெஞ்சு, புராதன (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "À¢Ã¡ýÍ" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "ஃப்யூலா" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "À¢ýÄ¡óÐ" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "ÌÅ¡ò¾Á¡Ä¡" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "கயோ" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "º£É¡" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "ஜெர்மானிய (மற்றவை)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "¦º÷À¢Â¡" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "§º÷Áý" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "¸¢§Ãì¸" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Å¢ÂðÉ¡Á¢Â" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Á¡ø¼¡" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "³Ã¢Í" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "­ò¾¡Ä¢Âý" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "மான்க்ஸ்" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "ஜெர்மன், மேல் மத்திய (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "ஜெர்மன், மேல் புராதன (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "­ó¾¢Â¡" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "கோரன்டாலோ" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "கோத்திக்" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "¸¢§Ãì¸" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "கிரேக்கம், புராதன(1453 வரை)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "கிரேக்கம், நவீன (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Àø§¸Ã¢Âý" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "குஜராத்தி" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "க்விச் இன்" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "ஹைடா" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "ÄðÅ¢Âý" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "ஹெளசா" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "ஹவாயன்" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "¸£ôê" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "¸£ôê" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "ஹிலிகைனான்" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "ஹிமாச்சலி" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "­ó¾¢Â¡" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "ஹிடைட்" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "ஹ்மாங்" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "ஹிரி மோட்டு" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "¦º÷À¢Âý" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "«í§¸Ã¢Âý" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "ஹ்யூபா" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "®Ã¡ì" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "இக்போ" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "³ÍÄ¡ó¾¢Â" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "ஐடோ" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Ä¢òЧÅɢ¡" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "ஐஜோ" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "இனக்டிடட்" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "இன்டர்லிங்வே" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "இலோக்கோ" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "இன்டர்லிங்குவா (சர்வதேச துணை மொழி குழுமம்)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "இன்டிக் (மற்றவை)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "­ó§¾¡É£º¢Âý" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "இந்தோ-ஐரோப்பிய (மற்றவை)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "இங்குஷ்" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "­ó¾¢Â¡" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "இரானிய (மற்றவை)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "­ò¾¡Ä¢Âý" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "ÂôÀ¡É¢Â" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "லோஜ்பான்" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "ÂôÀ¡É¢Â" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "­ó§¾¡É£º¢Âý" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "«Ã¡À¢ì" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "கரா-கல்பக்" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "காபைல்" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "À¢§Ãº¢ø" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "கலால்லிசட்" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "ƒº¦Áö측" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "¸É¼¡" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "¦¸¡Ã¢Âý" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "காஷ்மீரி" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Ì÷¾¢Í" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Á¡ø¼¡" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "¾¡öÅ¡ý" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "கபர்டியன்" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "¾¡ö" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "கொய்சான் (மற்றவை)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "க்மர்" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "º£É" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "கிகுயு" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "கின்யர்வாண்டா" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "கிர்கிஸ்" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "கிம்பன்டு" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "¦¸¡Ã¢Âý" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "கோமி" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "காங்கோ" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "¦¸¡Ã¢Âý" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "¦¸¡Ã¢Âý" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "க்பெல்" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "கராச்சய் - பல்கார்" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "க்ரு" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Ì÷¾¢Í" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "ÀÉ¡Á¡" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "குமிக்" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Ì÷¾¢Í" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "குடேனய்" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "ÄðÅ¢Âý" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "¸É¼¡" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "ƒº¦Áö측" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "லாவோ" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "ÄðÅ¢Âý" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "ÄðÅ¢Âý" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "லெஸ்கியன்" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Äìºõ§À¡÷ì" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "லிங்கலா" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "ĢЧÅÉ¢Âý" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "மாங்கோ" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "லோசி" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Äìºõ§À¡÷ì" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "லுபா-லுலுவா" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "லுபா-கடாங்கா" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "º£É¡" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "லூயிசெனோ" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "ݼ¡ý" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "லுவோ (கென்யா மற்றும் டான்சானியா)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "¾¡ö" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Á¡º¢§¼¡É¢Â" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Á¡øËº¢Â" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Á¡ø¼¡" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Á¡øËº¢Â" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Á¡ø¼¡" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Á¡ø¼¡" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Á¡ø¼¡" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "மான்டிங்கோ" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Á¡µÃ¢" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "ஆஸ்ட்ரோனேசியன் (மற்றவை)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Á¡µÃ¢" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Á¡ø¼¡" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Á¡ø¼¡" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "மோக்ஷா" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "ÀÉ¡Á¡" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "மென்டே" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "ஐரிஷ், மத்திய (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "மிக்மாக்" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "மினாங்கபாவ்" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "மான்-க்மர் (மற்றவை)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Á¡ø¼¡" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Á¡øËº¢Â" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "மஞ்சு" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Á¡µÃ¢" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "மொஹாக்" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "ÄðÅ¢Âý" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Á¡º¢§¼¡É¢Â" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Á¡µÃ¢" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "முண்டா மொழிகள்" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "¸¢§Ãì¸" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Á¡º¢§¼¡É¢Â¡" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Á¡µÃ¢" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "எர்சியா" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "நவ்ஹட்ல்" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "வட அமெரிக்க இந்திய" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "நியபாலிட்டன்" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "நவாஜோ" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "ந்டெபில், தெற்கு" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "ந்டெபில், வடக்கு" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "ந்டோங்கா" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "§º÷Áý" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Á¡ø¼¡" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "நேபால் பாசா" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "நியாஸ்" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "நைகர்-கார்டோஃபானியன் (மற்றவை)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "¦º÷À¢Â¡" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "நார்வேஜிய நைநார்ஸ்க்" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "நார்வேஜிய போக்மால்" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "நோகய்" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "நார்ஸ், புராதன" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "¿¡÷§Å" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "வட சோதோ" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "பாரம்பரிய நெவாரி" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "º¢Ä¢" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "நயாம்வேஸி" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "நயான்கோல்" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "நயோரோ" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "நஸீமா" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "ஆக்ஸிடன் (1500க்குப்பின்)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "‍ஓஜிப்வா" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "¦º÷À¢Â¡" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "ஓரோமோ" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "ஓசேஜ்" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "¯Õº¢Â" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "துருக்கி, ஓட்டோமன் (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "பாப்புவன் (மற்றவை)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "«í§¸Ã¢Âý" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Àá̧Å" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Àá̧Å" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "ÀÉ¡Á¡" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "பாப்பியாமென்டோ" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Àá̧Å" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "பாரசீகம், புராதன (ca.600-400 கி.மு.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "¦º÷À¢Âý" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "ஃபிலிப்பைன் (மற்றவை)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "ͧġţɢÂý" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Á¡ø¼¡" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "§À¡Ä¢Í" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "­ó§¾¡É£º¢Âý" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "§À¡÷òÐ츣º¢Â" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "புராவென்கல், புராதன (1500 வரை)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "புஷ்டோ" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "க்வெச்சுவா" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "¾¡öÅ¡ý" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "ºôÀ¡ý" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "ரரோடோங்கன்" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "ரொமான்ஸ் (மற்றவை)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "ரேடோ-ரொமான்ஸ்" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Õ§Áɢ¡" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "¯Õ§ÁÉ¢Â" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "­ó¾¢Â¡" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "¯Õº¢Â" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "¸É¼¡" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "ݼ¡ý" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "யாகுட்" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "பதென் அமெரிக்க இந்திய (மற்றவை)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "சமாரிட்டன் அராமைக்" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "சமஸ்கிருதம்" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "சசாக்" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "சந்தாலி" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "¦º÷À¢Âý" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "சிசிலியன்" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "ஸ்காட்ஸ்" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "̦á§Åº¢Âý" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "செல்கப்" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "செமிடிக் (மற்றவை)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "ஐரிஷ், புராதன (900 வரை)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "சங்கேத மொழிகள்" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "ݼ¡ý" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "சைடாமோ" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "சிங்களம்" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "சீன-திபெத்திய (மற்றவை)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "ஸ்லாவிக் (மற்றவை)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "ͧġšì" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "ͧġţɢÂý" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "தென் சாமி" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "வட சாமி" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "சாமி மொழிகள் (மற்றவை)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "லூலெ சாமி" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "இனாரி சாமி" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "சமோவன்" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "ஸ்கோல்ட் சாமி" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "ͧġŢɢ¡" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "சிந்தி" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "ͧġţɢÂý" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "ݼ¡ý" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Õ§Áɢ¡" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "சோங்காய்" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "சோதோ, தெற்கு" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "ÍÀ¡É¢Â" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Ä¢òЧÅɢ¡" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "செரர்" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "நிலோ-சஹாரன் (மற்றவை)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "ͦÀ¢ý" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "சுகுமா" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "ݼ¡ý" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "சுசு" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "¦º÷À¢Âý" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "¾¡öÄ¡óÐ" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "ÍÅ£ÊÍ" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "¦º÷À¢Â¡" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "¾¡öÅ¡ý" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "தாய் (மற்றவை)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "¾Á¢ú" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Á¡ø¼¡" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "¦Àøº¢Âõ" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "டிம்னே" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "டெரனோ" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "டேடம்" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "¾¡öÅ¡ý" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "டகலோக்" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "¾¡ö" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "¾¡öÅ¡ý" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "டைக்ரே" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "¦º÷À¢Â¡" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "டைவ்" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "க்ளிங்கான்" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "ட்லிங்கிட்" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "டமாஷேக்" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "டோங்கா (நியாஸா)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "டோங்கா (டோங்கா தீவுகள்)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "டோக் பிசின்" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "¯Õº¢Â" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "¾¡öÅ¡ý" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "±Í§¼¡É¢Â¡" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "ÐÕ츢" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "டும்புகா" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "ÐÕ츢Â" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "அல்டெய்க் (மற்றவை)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "ட்வி" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "ú¢Â¡" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "உட்மர்ட்" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "உகாரிடிக்" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "உய்கூர்" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "¯ì¦Ãöý" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "உம்பண்டு" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "தீர்மானிக்க இயலாதவை" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "உருது" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "உஸ்பெக்" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "வாய்" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Vietnam" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Å¢ÂðÉ¡Á¢Â" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "வொலாபக்" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "வால்டிக்" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "வலாமோ" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Àá̧Å" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "§ÅøÍ" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "§ÅøÍ" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "வாலூன்" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "வோலாஃப்" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "கால்மிக்" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "§º¡º¡" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "யாவோ" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "ÂôÀ¡É¢Â" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "யிட்டிஷ்" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "¦¸¡ÄõÀ¢Â¡" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "¬ŠÍò¾¢§ÃĢ¡" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "ஸாபோடெக்" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "¸¢¦Ãɼ¡" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "சுவாங்" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "ஸாண்டே" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Ýæ" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "சுனி" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1' காணப்படவில்லை." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1' காணப்படவில்லை." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "அறியப்படாதது" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "தெரியாத ஆணை " + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "செல்லாத யூஆர்எல் திட்டம் '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "அடைவு %1 உருவாக்க முடியவில்லை: %2." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "டெஸ்க்டாப் பொருளை '%s' திறக்க முடியவில்லை" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, fuzzy, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "மூலங்கள் சேர்க்கப்படுகின்றன" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "செல்லாத ஏற்றுமதி கோப்புபெயர்." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "எழுதுவதற்கு கோப்பைத் திறக்க முடியவில்லை." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "ஃப்ளாப்பி வட்டிலிருந்து படிப்பதில் பிழை" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "மூலங்கள் சேர்க்கப்படுகின்றன" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "டெஸ்க்டாப் பொருளை '%s' திறக்க முடியவில்லை" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "தொடரலாமா?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"நேர்மை சோதனையில் %s பேக்கேஜ் தோல்வியுற்றது. அதனை தகவலிறக்கம் செய்வதற்கு நீங்கள் மீண்டும் " +"முயற்சிக்கப் போகிறீர்களா?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"நேர்மை சோதனையில் %s பேக்கேஜ் தோல்வியுற்றது. அதனை தகவலிறக்கம் செய்வதற்கு நீங்கள் மீண்டும் " +"முயற்சிக்கப் போகிறீர்களா?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "அப்ளைடெல்டாஆர்பிஎம் சோதனை தோல்வியுற்றது" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "அப்ளைடெல்டாஆர்பிஎம் தோல்வியுற்றது." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "VAR1 மூல வகை காட்சி மாற்றங்கள் அம்சத்திற்கு ஆதரவளிப்பதில்லை" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "%sலிருந்து %sஐ அளிக்க இயலாது" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "சேமிப்பிடத்தில் கோப்பு %1 காணப்படவில்லை." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "கோப்பை உருவாக்க முடியவில்லை." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "இத்தேவையை இங்கேயே புறக்கணிக்கவும்" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "இத்தேவையை இங்கேயே புறக்கணிக்கவும்" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "இந்த இணைப்புக்கான கோரிக்கை: " + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "சார்புத்தன்மை பிரச்னைகள் காரணமாக %s ஐ நிறுவ இயலவில்லை" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "%s யாரும் அளிப்பதில்லை" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "%sக்கு நிறுவக்கூடிய அளிப்பவர்கள் இல்லை" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "%sக்கு நிறுவக்கூடிய அளிப்பவர்கள் இல்லை" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "கோரிக்கை ஏற்கனவே உள்ளது." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "குறிப்பிட்டுள்ளபடி நிறுவுதல் இடையில் நிறுத்தப்பட்டது." + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "நிறைவேற்று" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "விசை என்கிரிப்ட் செய்யும்போது பிழை." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "தோல்வியுற்றது" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s:க்காக உள்ளமைத்தல் கோப்புகள் மாற்றப்பட்டுள்ளன" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "%s ஆக ஆர்பிஎம் சேமிக்கப்பட்டுள்ளது, ஆனால் வேறுபாட்டை நிர்ணயிக்க முடியவில்லை" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, fuzzy, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"%s ஆக ஆர்பிஎம் சேமிக்கப்பட்டுள்ளது.\n" +"வேறுபாடுகளின் முதல் 25 வரிகள் இங்குள்ளன:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "%s ஆக ஆர்பிஎம் உருவாf;கப்பட்டுள்ளது, ஆனால் வேறுபாட்டை நிர்ணயிக்க முடியவில்லை" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, fuzzy, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"%s ஆக ஆர்பிஎம் உருவாக்கப்பட்டுள்ளது.\n" +"வேறுபாடுகளின் முதல் 25 வரிகள் இங்குள்ளன:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "கூடுதல் ஆர்பிஎம் அவுட்புட்:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "%s மறுபிரதி உருவாக்கப்பட்டது" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "உள்ளீடு காணப்படவில்லை." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "உள்ளீடு காணப்படவில்லை." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "உள்ளீடு காணப்படவில்லை." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "கோப்பை %1 திறக்க முடியவில்லை." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "செல்லாத எல்டிஏபி யூஆர்எல் வினா வரிசை" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "செல்லாத எல்டிஏபி யூஆர்எல் வினா அளவீடு '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "யூஆர்எல் பொருளின் போலிகையை உருவாக்க இயலவில்லை" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "செல்லாத காலி யூஆர்எல் பொருள் குறிப்புரை" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "யூஆர்எல் உறுப்புகளை விளக்க இயலவில்லை" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "யூஆர்எல் திட்டம் %sக்கு அனுமதிப்பதில்லை" + +#: zypp-core/url/UrlBase.cc:240 +#, fuzzy, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "'%s' செல்லாத உறுப்பு" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "செல்லாத %s உறுப்பு" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "இந்த யூஆர்எல்லுக்கு வினா வரிசை விளக்கம் ஆதரவளிக்கப்படவில்லை" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "யூஆர்எல் திட்டம் ஒரு தேவைப்படும் உறுப்பாகும்" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "செல்லாத யூஆர்எல் திட்டம் '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "யூஆர்எல் திட்டம் பயனாளர் பெயரை அனுமதிப்பதில்லை" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "யூஆர்எல் திட்டம் கடவுச்சொல்லை அனுமதிப்பதில்லை" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "யூஆர்எல் திட்டத்திற்கு ஓர் ஆதார உறுப்பு தேவைப்படுகிறது" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "யூஆர்எல் திட்டம் ஓர் ஆதார உறுப்பை அனுமதிப்பதில்லை" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "செல்லாத ஆதார உறுப்பு'%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "யூஆர்எல் திட்டம் ஒரு முணையத்தை அனுமதிப்பதில்லை" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "செல்லாத முணைய உறுப்பு'%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "யூஆர்எல் திட்டத்திற்கு ஒரு பாதை பெயர் தேவைப்படுகிறது" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "அதிகாரம் இருக்குமானால் தொடர்புப் பாதை ஆதரவளிக்கப்படுவதில்லை" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "குறியீடு செய்யப்பட்ட வரிசை, என்யூஎல் பைட் கொண்டுள்ளது" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "செல்லாத அளவீட்டு அடுக்கு பிளவை பிரிக்கும் வடிவம்" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "செல்லாத அளவீட்டு வரைவு பிளவை பிரிக்கும் வடிவம்" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "செல்லாத அளவீட்டு அடுக்கு இணைப்பை பிரிக்கும் வடிவம்" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "இணைக்கப்படும் பொழுது கட்டளையை செயல்படுத்து" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "%s கண்பிடிக்க முடியவில்லை." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "%s கண்பிடிக்க முடியவில்லை." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "%s - %s திறக்க முடியவில்லை\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "கூறு\"%s\"ஐ ஏற்ற முடியவில்லை" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "சேமிப்பிடத்தில் கோப்பு %1 காணப்படவில்லை." + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "%1 கோப்பில் எழுத முடியவில்லை." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 ஒரு அடைவல்ல." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "சிஏ பெயா காலி செய்." + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "செல்லாத URL திட்டம் '%1'." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "டெஸ்க்டாப் பொருளை '%s' திறக்க முடியவில்லை" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "அனுமதிகள் மறுக்கப்படுகின்றன" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "ஆம்" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "இல்லை" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "எச்சரிக்கை" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "பிழை" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "­ó§¾¡É£º¢Â¡" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "பிழை" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "எச்சரிக்கை" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "ஆரம்பிக்கிறது..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "காணப்படவில்லை " + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ஆம்" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "இல்லை" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s, %sஐ அளிக்கிறது, ஆனால் அதற்கு வேறொரு கட்டமைப்பு உள்ளது." + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "பேக்கேஜ்களின் நிறுவுதலை நீக்குவதற்கான ஆணை" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "%s யாரும் அளிப்பதில்லை" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "சான்றிதழ் %1 இல்லை." + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s பூட்டப்பட்டுள்ளது மற்றும் அதன் நிறுவுதலை நீக்க இயலாது." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "நிறுவப்படவில்லை" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s, %sக்கு தேவைப்படுகிறது" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "%sஐ நிறுவ முடியவில்லை" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s %sஉடன் முரண்படுகிறது" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s %sஐ வழக்கற்றதாக்குகிறது" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s %sஐ வழக்கற்றதாக்குகிறது" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s %sஉடன் முரண்படுகிறது" + +#~ msgid "do not install %s" +#~ msgstr "%sஐ நிறுவ வேண்டாம்" + +#~ msgid "keep %s" +#~ msgstr "%sஐ வைத்துக் கொள்ளவும்" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "%sஐ நிறுவ வேண்டாம்" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "%sக்கு நிறுவக்கூடிய அளிப்பவர்கள் இல்லை" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "தொடர்புள்ள தீர்வுகளை நிறுவவோ அல்லது நீக்கவோ வேண்டாம்" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s, %sஐ அளிக்கிறது, ஆனால் அதற்கு வேறொரு கட்டமைப்பு உள்ளது." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "அது கட்டமைப்பை மாற்றக்கூடுமென்றாலும் %sஐ நிறுவவும்" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s %sஐ வழக்கற்றதாக்குகிறது" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "%sலிருந்து %s தகவலிறக்கம் செய்யப்பட்டது" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "நிறுவுதல்" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "கோப்பை %1 திறக்க முடியவில்லை." + +#~ msgid "Hal Exception" +#~ msgstr "ஹால் விதிவிலக்கு" + +#~ msgid "HalContext not connected" +#~ msgstr "ஹால்கான்டெக்ஸ்ட் இணைக்கப்படவில்லை" + +#~ msgid "HalDrive not initialized" +#~ msgstr "ஹால்டிரைவ் துவக்கப்படவில்லை" + +#~ msgid "HalVolume not initialized" +#~ msgstr "ஹால்வால்யூம் துவக்கப்படவில்லை" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "டிபஸ் இணைப்பை உருவாக்க இயலவில்லை" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: ஆல் லைபால் உள்ளடக்கத்தை உருவாக்க இயலவில்லை" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: ஆல் டிபஸ் இணைப்பை அமைக்க இயலவில்லை" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "HAL உள்ளடக்கத்தை துவக்க இயலவில்லை -- ஹால்ட் இயக்கத்தில் இல்லையா?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "சிடிரோம் டிரைவ் அல்ல" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "மியூடெக்ஸ் பண்புகளை துவக்க இயலாது" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "எதிர்ப்புத்தன்மையுள்ள மியூடெக்ஸ் பண்மப அமைக்க இயலாது" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "எதிர்ப்புத்தன்மையுள்ள மியூடெக்ஸை துவக்க இயலாது" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "மியூடெக்ஸ் பூட்டை பெற இயலாது" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "மியூடெக்ஸ் பூட்டை திறக்க இயலாது" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "பொது விசையை பெற முடியவில்லை." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "நிறுவப்படவில்லை" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "%s - %s திறக்க முடியவில்லை\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "செர்பியா மற்றும் மான்டநெக்ரோ" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "தெரியாத பட்டியல் விருப்பத்தேர்வு" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "சார்புத்தன்மைகளை தீர்க்க முடியவில்லை" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s கோப்பிற்கு செக்சம் இல்லை.\n" +#~ "அவ்வாறிருந்தும் அக்கோப்பை பயன்படுத்தலாமா?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s கோப்பு, பின்வரும் கீயுடன் நேர்மை சோதனையில் தோல்வியுற்றது:\n" +#~ "%s|%s|%s\n" +#~ "அவ்வாறிருந்தும் அக்கோப்பை பயன்படுத்தலாமா?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s கோப்பிற்கு செல்லாத ஒரு செக்சம் உள்ளது.\n" +#~ "எதிர்பார்த்தது %s, கண்டது %s\n" +#~ "அவ்வாறிருந்தும் அக்கோப்பை பயன்படுத்தலாமா?" + +#, fuzzy +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s கோப்பிற்கு அறியப்படாத ஒரு செக்சம் உள்ளது.\n" +#~ "அவ்வாறிருந்தும் அக்கோப்பை பயன்படுத்தலாமா?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "%s கோப்பு கையொப்பமிடப்படவில்லை.\n" +#~ "அவ்வாறிருந்தும் அதனை பயன்படுத்தலாமா?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "%s கோப்பு அறிந்திராத ஒரு கீயினால் கையொப்பமிடப்பட்டுள்ளது:\n" +#~ "%s|%s|%s\n" +#~ "அவ்வாறிருந்தும் அக்கோப்பை பயன்படுத்தலாமா?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "நம்பகத்தன்மையற்ற கீ கண்டுபிடிக்கப்பட்டுள்ளது:\n" +#~ "%s|%s|%s\n" +#~ "கீயை நம்பலாமா?" + +#~ msgid "%s remove failed" +#~ msgstr "%s நீக்குதல் தோல்வியுற்றது" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "கணத்தை மாற்று" + +#~ msgid "rpm output:" +#~ msgstr "ஆர்பிஎம் அவுட்புட்:" + +#~ msgid "%s install failed" +#~ msgstr "%s நிறுவுதல் தோல்வியுற்றது" + +#~ msgid "%s installed ok" +#~ msgstr "%s நிறுவுதல் சரியானது" + +#~ msgid "%s remove ok" +#~ msgstr "%s நீக்குதல் சரியானது" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "" +#~ "இச்சார்புத்தன்மையை %s அளிக்கிறது ஆனால், நிறுவப்பட்டுள்ள பொருளின் கட்டமைப்பை " +#~ "மாற்றிவிடும்" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "" +#~ "இச்சார்புத்தன்மையை %s அளிக்கிறது ஆனால், நிறுவப்பட்டுள்ள பொருளின் கட்டமைப்பை " +#~ "மாற்றிவிடும்" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "தொடர்புள்ள தீர்வுகளை நிறுவவோ அல்லது நீக்கவோ வேண்டாம்" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "‍‍ஏற்கனவே நிறுவுவதற்காக அமைக்கப்பட்டுள்ள %sஐ புறக்கணிக்கவும்" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "%sல் உள்ள வழக்கில் இல்லாத %sஐ புறக்கணிக்கவும்" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%sன் முரண்பாட்டை புறக்கணிக்கவும்" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "இத்தேவையை இங்கேயே புறக்கணிக்கவும்" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "அது கட்டமைப்பை மாற்றக்கூடுமென்றாலும் %sஐ நிறுவவும்" + +#~ msgid "Install missing resolvables" +#~ msgstr "­ò¾¡Ä¢Âý" + +#~ msgid "Keep resolvables" +#~ msgstr "தீர்வுகளை வைத்துக் கொள்ளவும்" + +#~ msgid "Unlock these resolvables" +#~ msgstr "இத்தீர்வுகளைத் திறக்கவும்" + +#~ msgid "delete %s" +#~ msgstr "%s ஐ நீக்கவும்" + +#~ msgid "install %s" +#~ msgstr "%sஐ நிறுவவும்" + +#~ msgid "unlock %s" +#~ msgstr "%sஐ திறக்கவும்" + +#~ msgid "unlock all resolvables" +#~ msgstr "­ò¾¡Ä¢Âý" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "கோப்பை %1 திறக்க முடியவில்லை." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "%u பிரிவை படிப்பதில் பிழை." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "இந்த யூஆர்எல்லுக்கு பாதை அளவீடு விளக்கம் ஆதரவளிக்கப்படவில்லை" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "இந்த யூஆர்எல்லுக்கு பாதை அளவீடு விளக்கம் ஆதரவளிக்கப்படவில்லை" + +#~ msgid "Software management is already running." +#~ msgstr "மென்பொருள் நிர்வாகம் ஏற்கனவே இயக்கத்திலுள்ளது." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s %sஆல் மாற்றியமைக்கப்பட்டது" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s %sஆல் மாற்றியமைக்கப்பட்டது" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "இத்தீர்வுகள் அமைப்பிலிருந்து நீக்கப்படும்" + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "அது இன்னமும் தேவைப்படுவதால், %s நீக்கப்பட மாட்டாது" + +#~ msgid "Invalid information" +#~ msgstr "செல்லாத தகவல்" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "மற்ற தீர்வுகளுக்கு %s தேவைப்படுகிறது" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%sக்கு தேவைப்படுவது:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s மற்ற தீர்வுகளுடன் முரண்படுகிறது" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%sஉடன் முரண்படுவது:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s மற்ற தீர்வுகளை வழக்கற்றதாக்குகிறது" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "இத்தீர்வுகள் அமைப்பிலிருந்து நீக்கப்படும்" + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s மற்ற தீர்வுகளை சார்ந்துள்ளது" + +#~ msgid "%s depends on %s" +#~ msgstr "%s %sஐ சார்ந்துள்ளது" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s %sஐ சார்ந்துள்ளது:" + +#~ msgid "Child of" +#~ msgstr "இதன் உருவாக்கம்" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "இத்தேவையை பூர்த்தி செய்யும் ஆதாரம் எதுவும் இல்லை" + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "இத்தீர்வின் மேலே மற்றும் கீழே விளக்கப்பட்டுள்ள பிரச்னைகள், அனைத்து சார்புத்தன்மைகளையும் " +#~ "தீர்க்கக்கூடியவை அல்ல" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%s ஐ நிறுவ இயலவில்லை ஏனெனில் அது %s உடன் முரண்படுகிறது" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s நிறுவப்படவில்லை மற்றும் அது நிறுவ இயலாததாக குறிக்கப்பட்டுள்ளது" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s தீர்க்கப்படாத தேவைகளைக் கொண்டுள்ளது" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s காணப்படாத சார்புத்தன்மைகளைக் கொண்டுள்ளது" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "காணப்படாத சார்புத்தன்மைகள் %sஐ காரணமாக நிறுவ இயலாது" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s சார்புத்தன்மைகளை %s பூர்த்தி செய்யும் ஆனால் நிறுவுதல் நீக்கப்பட்டுவிடும்" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "%s சார்புத்தன்மைகளை %s பூர்த்தி செய்யும் ஆனால் உங்கள் அமைப்பில் வைக்கப்படும்" + +#~ msgid "No need to install %s" +#~ msgstr "%sஐ நிறுவத் தேவையில்லை" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "%sன் சார்புத்தன்மைகளை பூர்த்தி செய்வதற்கு %sஐ நிறுவ இயலவில்லை" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "%sன் சார்புத்தன்மைகளை பூர்த்தி செய்வதற்கு %sஐ நிறுவ இயலவில்லை" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "அது இன்னமும் தேவைப்படுவதால், %s நீக்கப்பட மாட்டாது" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "" +#~ "%sஐ %s வழக்கற்றதாக்கிவிடும். ஆனால் %sஐ நீக்க முடியாது ஏனெனில் அது பூட்டப்பட்டுள்ளது." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "%sஐ நிறுவ முடியாது ஏனெனில் அது முரணானது" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s உடன் உள்ள முரண்பாடு காரணமாக %sன் நிறுவுதலை நீக்க முடியாது" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "%sஐ புதுப்பிக்கும்போது %sக்காக %s தேவைப்‍படும்போது" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s க்கான தேவையை %s இழந்துள்ளது" + +#~ msgid ", Action: " +#~ msgstr ", செயல்பாடு:" + +#~ msgid ", Trigger: " +#~ msgstr ", தூண்டுதல்:" + +#~ msgid "package" +#~ msgstr "பேக்கேஜ்" + +#~ msgid "selection" +#~ msgstr "தேர்வு" + +#~ msgid "pattern" +#~ msgstr "வடிவம்" + +#~ msgid "product" +#~ msgstr "பொருள்" + +#~ msgid "patch" +#~ msgstr "பாட்ச்" + +#~ msgid "script" +#~ msgstr "உரை" + +#~ msgid "message" +#~ msgstr "தகவல்" + +#~ msgid "atom" +#~ msgstr "அணு" + +#~ msgid "system" +#~ msgstr "சாதனம்" + +#~ msgid "Resolvable" +#~ msgstr "தீர்வு" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "இத்தீர்வு முயற்சி செல்லாததாக குறிக்கப்படுகிறது" + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "இத்தீர்வு %s நிறுவக்கூடியதல்ல என்று குறிக்கப்படுகிறது" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s நிறுவப்படுவதற்காக திட்டமிடப்பட்டுள்ளது, ஆனால் சார்புத்தன்மை பிரச்னைகள் காரணமாக இது " +#~ "சாத்தியமில்லை." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "நிறுவுதல் நீக்கப்பட வேண்டியது என்று ஏற்கனவே குறிக்கப்பட்டிருப்பதால், %sஐ நிறுவஇயலவில்லை" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "இந்த சாதனத்திற்கு பொருந்தாமல் இருப்பதால், %sஐ நிறுவ இயலவில்லை" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "நிறுவுப்பட வேண்டியது என்று ஏற்கனவே குறிக்கப்பட்டிருப்பதால், %s ஐ நிறுவ \n" +#~ "இயலவில்லை" + +#~ msgid "This would invalidate %s." +#~ msgstr "இது, %sஐ செல்லாததாக்கிவிடும்." + +#~ msgid "Establishing %s" +#~ msgstr "%s அமைக்கப்படுகிறது" + +#~ msgid "Installing %s" +#~ msgstr "%s நிறுவப்படுகிறது" + +#~ msgid "Updating %s to %s" +#~ msgstr "%s லிருந்து %sக்கு புதுப்பித்தல்" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "%s விடப்படுகிறது: ஏற்கவே நிறுவப்பட்டுவிட்டது" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "%sக்கான நிறுவப்பட்ட மாற்று அளிப்பவர்கள் இல்லை" + +#~ msgid "for %s" +#~ msgstr "%sக்காக" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "%sக்கு மேம்படுத்திக் கொள்ளவும், %sஐ நீக்குதல் இயலாது" + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s, %sஐ அளிக்கிறது, ஆனால் அது நிறுவுதல் நீக்கப்படுவதற்கு திட்டமிடப்பட்டுள்ளது" + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s, %sஐ அளிக்கிறது, ஆனால், %sன் மற்றொரு வடிவம் ஏற்கனவே நிறுவப்பட்டுவிட்டது" + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s, %sஐ அளிக்கிறது, ஆனால், அதன் நிறுவுதலை நீக்க இயலாது. கூடுதல் விவரங்களுக்கு, " +#~ "அதனைத் தானாகவே நிறுவம முயற்சிக்கவும்." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s, %sஐ அளிக்கிறது, ஆனால் அது பூட்டப்பட்டுள்ளது." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s, %sஐ அளிக்கிறது, ஆனால் அது வைக்கப்படுவதற்கு திட்டமிடப்பட்டுள்ளது." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s, %sஐ அளிக்கிறது, ஆனால் அதற்கு வேறொரு கட்டமைப்பு உள்ளது." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "%s க்கான %sன் தேவையைப் பூர்த்தி செய்ய இயலாது" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "மற்றொரு நிறுவப்பட்டுள்ள தீர்வுக்கு %s தேவைப்படுகிறது, எனவே அதன இணைப்பு நீக்கப்பட " +#~ "மாட்டாது." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "மற்றொரு நிறுவப்பட்டுள்ள தீர்வுக்கு %s தேவைப்படுகிறது, எனவே அதன இணைப்பு நீக்கப்பட " +#~ "மாட்டாது." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "" +#~ "%s (%s) மீதான ஒரு முரண்பாட்டிற்கு, நிறுவப்படப்போகும் %sன் நீக்கம் தேவைப்படுகிறது." + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "%s மீதான ஒரு முரண்பாடு காரணமாக %s நிறுவப்பட முடியாததாக குறிக்கப்பட்டுள்ளது" + +#~ msgid "from %s" +#~ msgstr "%sலிருந்து" + +#~ msgid " Error!" +#~ msgstr "பிழை!" + +#~ msgid " Important!" +#~ msgstr "முக்கியம்!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s, %sஐ சார்ந்துள்ளது" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s, %sக்கு தேவைப்படுகிறது" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s, %sக்கு தேவைப்படுகிறது" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s %sஆல் மாற்றியமைக்கப்பட்டது" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s, %sக்கு தேவைப்படுகிறது" + +#~ msgid "%s part of %s" +#~ msgstr "%s, %sன் ஒரு பகுதியாகும்" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s, %sக்கு தேவைப்படுகிறது" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "யூஆர்எல் அதிகாரத்தை விளக்க இயலவில்லை" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "இத்தேவையை பொதுவாக புறக்கணிக்கவும்" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "மற்றொரு நிறுவப்படப்போகும் தீர்வுக்கு %s தேவைப்படுகிறது, எனவே அதன் இணைப்பு நீக்கப்பட " +#~ "மாட்டாது." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "" +#~ " புதுப்பிக்கப்பட்ட நிறுவுதலை மேற்கொள்வதற்கு தேவைப்படும் கோப்பை உருவாக்க இயலவில்லை." + +#~ msgid "Unable to restore all sources." +#~ msgstr "அனைத்து ஆதாரங்களையும் மீட்க முடியவில்லை" + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "ஒரு ஆதாரமேனும் ஏற்கனவே பதிவு செய்யப்பட்டுள்ளது, சேமிக்கப்பட்ட ஆதாரங்களைமீட்க இயலாது." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "%sன் சார்புத்தன்மைகளை பூர்த்தி செய்வதற்கு %s நிறுவப்படுவதற்கு இயலவில்லை" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s, %sஐ சார்ந்துள்ளது" + +#~ msgid "Reading index files" +#~ msgstr "உள்ளடக்க கோப்புகள் படிக்கப்படுகின்றன" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "கையாப்பமிடப்பட்ட repomd.xml கோப்பு, கையொப்ப சோதனையில் தோல்வியுற்றது." + +#~ msgid "Reading product from %s" +#~ msgstr "%sலிருந்து பொருள் படிக்கப்படுகிறது" + +#~ msgid "Reading filelist from %s" +#~ msgstr "%sலிருந்து கோப்புப்பட்டியல் படிக்கப்படுகிறது" + +#~ msgid "Reading packages from %s" +#~ msgstr "%sலிருந்து பேக்கேஜ்கள் படிக்கப்படுகின்றன" + +#~ msgid "Reading selection from %s" +#~ msgstr "%sலிருந்து தேர்வுகள் படிக்கப்படுகின்றன" + +#~ msgid "Reading pattern from %s" +#~ msgstr "%sலிருந்து வடிவம் படிக்கப்படுகிறது" + +#~ msgid "Reading patches index %s" +#~ msgstr "பாட்ச்களின் உள்ளடக்கம் %s படிக்கப்படுகிறது" + +#~ msgid "Reading patch %s" +#~ msgstr "பாட்ச் %s படிக்கப்படுகிறது" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "சோதனைத் தேர்வில் உரை கோப்பு தோல்வியுற்றது" + +#~ msgid "Reading packages file" +#~ msgstr "பேக்கேஜ்கள் கோப்பு படிக்கப்படுகிறது" + +#~ msgid "Reading translation: %s" +#~ msgstr "மொழிபெயர்ப்பு படிக்கப்படுகிறது: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "நேர்மை சோதனையில் %s பேக்கேஜ் தோல்வியுற்றது. அதனை தகவலிறக்கம் செய்வதற்குநீங்கள் மீண்டும் " +#~ "முயற்சிக்கப் போகிறீர்களா அல்லது நிறுவுதலை நிறுத்திவிடப் போகிறீர்களா?" + +#~ msgid " miss checksum." +#~ msgstr "செக்சம் தவறியது." + +#~ msgid " fails checksum verification." +#~ msgstr "செக்சம் சரிபார்ப்பில் தோல்வியுற்றது." + +#~ msgid "Downloading %s" +#~ msgstr "%s தகவலிறக்கம் செய்யப்படுகிறது" diff --git a/po/th.po b/po/th.po new file mode 100644 index 0000000..a0be730 --- /dev/null +++ b/po/th.po @@ -0,0 +1,5437 @@ +# Thai message file for YaST2 (@memory@). +# Copyright (C) 2008 SUSE Linux Products GmbH. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2008-01-04 08:58+0100\n" +"Last-Translator: i18n@suse.de\n" +"Language-Team: Thai \n" +"Language: th\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" + +#: zypp/CountryCode.cc:50 +#, fuzzy +msgid "Unknown country: " +msgstr "ไม่ทราบประเทศ: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +#, fuzzy +msgid "No Code" +msgstr "ไม่มีรหัส" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "อันดอร์รา" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "สหรัฐอาหรับเอมิเรตส์" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "อัฟกานิสถาน" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "แอนติกาและบาร์บูดา" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "แองกวิลลา" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "แอลเบเนีย" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "อาร์เมเนีย" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "เนเธอร์แลนด์แอนทิลลีส" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "แองโกลา" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "แอนตาร์กติกา" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "อาร์เจนตินา" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "อเมริกันซามัว" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "ออสเตรีย" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "ออสเตรเลีย" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "อรูบา" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "หมู่เกาะเอแลนด์" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "อาเซอร์ไบจาน" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "บอสเนียและเฮอร์เซโกวินา" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "บาร์เบโดส" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "บังกลาเทศ" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "เบลเยียม" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "บูร์กินาฟาโซ" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "บัลแกเรีย" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "บาห์เรน" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "บุรุนดี" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "เบนิน" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "เบอร์มิวดา" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "บรูไนดารุสซาลาม" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "โบลิเวีย" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "บราซิล" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "บาฮามาส" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "ภูฏาน" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "เกาะบูเว" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "บอตสวานา" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "เบลารุส" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "เบลีซ" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "แคนาดา" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "หมู่เกาะโคโคส (คีลิง)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "คองโก" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "สาธารณรัฐแอฟริกากลาง" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "สวิตเซอร์แลนด์" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "โกตดิวัวร์" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "หมู่เกาะคุก" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "ชิลี" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "แคเมอรูน" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "จีน" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "โคลอมเบีย" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "คอสตาริกา" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "คิวบา" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "กาบูเวร์ดี" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "เกาะคริสต์มาส" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "ไซปรัส" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "สาธารณรัฐเช็ก" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "เยอรมนี" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "จิบูตี" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "เดนมาร์ก" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "โดมินิกา" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "สาธารณรัฐโดมินิกัน" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "แอลจีเรีย" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "เอกวาดอร์" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "เอสโตเนีย" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "อียิปต์" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "ซาฮาราตะวันตก" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "เอริเทรีย" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "สเปน" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "เอธิโอเปีย" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "ฟินแลนด์" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "ฟีจี" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "หมู่เกาะฟอล์กแลนด์ (มัลบินัส)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "สหพันธรัฐไมโครนีเซีย" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "หมู่เกาะแฟโร" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "ฝรั่งเศส" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "ฝรั่งเศสแผ่นดินใหญ่" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "กาบอน" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "สหราชอาณาจักร" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "เกรนาดา" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "จอร์เจีย" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "เฟรนช์เกียนา" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "เกิร์นซีย์" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "กานา" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "ยิบรอลตา" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "กรีนแลนด์" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "แกมเบีย" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "กินี" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "กวาเดอลูป" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "อิเควทอเรียลกินี" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "กรีซ" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "เกาะเซาท์จอร์เจียและหมู่เกาะเซาท์แซนด์วิช" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "กัวเตมาลา" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "กวม" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "กินี-บิสเซา" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "กายอานา" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "ฮ่องกง" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "เกาะเฮิร์ดและหมู่เกาะแมกดอนัลด์" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "ฮอนดูรัส" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "โครเอเชีย" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "เฮติ" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "ฮังการี" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "อินโดนีเซีย" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "ไอร์แลนด์" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "อิสราเอล" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "เกาะแมน" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "อินเดีย" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "บริติชอินเดียนโอเชียนเทร์ริทอรี" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "อิรัก" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "อิหร่าน" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "ไอซ์แลนด์" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "อิตาลี" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "เจอร์ซีย์" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "จาเมกา" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "จอร์แดน" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "ญี่ปุ่น" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "เคนยา" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "คีร์กีซน" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "กัมพูชา" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "คิริบาส" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "คอโมโรส" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "เซนต์คิตส์และเนวิส" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "เกาหลีเหนือ" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "เกาหลีใต้" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "คูเวต" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "หมู่เกาะเคย์แมน" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "คาซัคสถาน" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "สาธารณรัฐประชาธิปไตยประชาชนลาว" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "เลบานอน" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "เซนต์ลูเซีย" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "ลิกเตนสไตน์" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "ศรีลังกา" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "ไลบีเรีย" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "เลโซโท" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "ลิทัวเนีย" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "ลักเซมเบิร์ก" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "ลัตเวีย" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "ลิเบีย" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "โมร็อกโก" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "โมนาโค" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "มอลโดวา" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "มอนติเนโกร" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "ซานมาริโน" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "มาดากัสการ์" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "หมู่เกาะมาแชลล์" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "มาซิโดเนีย" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "มาลี" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "พม่า" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "มองโกเลีย" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "มาเก๊า" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "หมู่เกาะมาเรียนาเหนือ" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "มาร์ตินีก" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "มอริเตเนีย" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "มอนต์เซอร์รัต" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "มอลตา" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "มอริเชียส" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "มัลดีฟส์" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "มาลาวี" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "เม็กซิโก" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "มาเลเซีย" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "โมซัมบิก" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "นามิเบีย" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "นิวแคลิโดเนีย" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "ไนเจอร์" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "เกาะนอร์ฟอล์ก" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "ไนจีเรีย" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "นิการากัว" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "เนเธอร์แลนด์" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "นอร์เวย์" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "เนปาล" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "นาอูรู" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "นีอูเอ" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "นิวซีแลนด์" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "โอมาน" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "ปานามา" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "เปรู" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "เฟรนช์โปลินีเซีย" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "ปาปัวนิวกินี" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "ฟิลิปปินส์" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "ปากีสถาน" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "โปแลนด์" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "แซงปีแยร์และมีเกอลง" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "เกาะพิตแคร์น" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "เปอร์โตริโก" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "ดินแดนปาเลสไตน์" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "โปรตุเกส" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "ปาเลา" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "ปารากวัย" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "กาตาร์" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "เรอูนียง" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "โรมาเนีย" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "เซอร์เบีย" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "สหพันธรัฐรัสเซีย" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "รวันดา" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "ซาอุดีอาระเบีย" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "หมู่เกาะโซโลมอน" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "เซเชลส์" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "ซูดาน" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "สวีเดน" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "สิงคโปร์" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "เซนต์เฮเลนา" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "สโลวีเนีย" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "สฟาลบาร์และยานไมเอน" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "สโลวะเกีย" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "เซียร์ราลีโอน" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "ซานมาริโน" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "เซเนกัล" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "โซมาเลีย" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "ซูรินาม" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "เซาตูเมและปรินซีปี" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "เอลซัลวาดอร์" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "ซีเรีย" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "สวาซิแลนด์" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "หมู่เกาะเติกส์และหมู่เกาะเคคอส" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "ชาด" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "เฟรนช์เซาเทิร์นเทร์ริทอรีส์" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "โตโก" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "ไทย" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "ทาจิกิสถาน" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "โตเกเลา" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "เติร์กเมนิสถาน" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "ตูนิเซีย" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "ตองกา" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "ติมอร์ตะวันออก" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "ตุรกี" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "ตรินิแดดและโตเบโก" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "ตูวาลู" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "ไต้หวัน" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "แทนซาเนีย" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "ยูเครน" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "ยูกันดา" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "เกาะเล็กรอบนอกของสหรัฐอเมริกา" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "สหรัฐอเมริกา" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "อุรุกวัย" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "อุซเบกิสถาน" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "สันตะสำนัก (นครรัฐวาติกัน)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "เซนต์วินเซนต์และเกรนาดีนส์" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "เวเนซุเอลา" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "หมู่เกาะบริติชเวอร์จิน" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "หมู่เกาะเวอร์จินของสหรัฐอเมริกา" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "เวียดนาม" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "วานูอาตู" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "วาลลิสและฟุตูนา" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "ซามัว" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "เยเมน" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "มายอต" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "แอฟริกาใต้" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "แซมเบีย" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "ซิมบับเว" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "มอบ" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "สิ่งที่ต้องมีก่อน" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "ต้องการ" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "ขัดแย้ง" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "ล้าสมัย" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "แนะนำ" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "อาจเกี่ยวข้อง" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "ขยาย" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "เสริม" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "พยายามนำเข้ากุญแจ %s ที่ไม่มีอยู่จริงเข้าไปในพวงกุญแจ %s" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "ล้มเหลวในการคืนค่าส่วน MBR ของฮาร์ดดิสก์" + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "ล้มเหลวในการคืนค่าส่วน MBR ของฮาร์ดดิสก์" + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "ไม่พบแฟ้มควบคุม %1 บนสื่อการติดตั้ง" + +#: zypp/LanguageCode.cc:49 +#, fuzzy +msgid "Unknown language: " +msgstr "ภาษาที่ไม่รู้จัก: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "อาฟรีกานส์" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +#, fuzzy +msgid "Albanian" +msgstr "แอลเบเนีย" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "อัลไตใต้" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "อารบิก" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +#, fuzzy +msgid "Aramaic" +msgstr "แอราเมอิก" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +#, fuzzy +msgid "Armenian" +msgstr "อาร์เมเนีย" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +#, fuzzy +msgid "Azerbaijani" +msgstr "อาเซอร์ไบจาน" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +#, fuzzy +msgid "Balinese" +msgstr "บาหลี" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +#, fuzzy +msgid "Belarusian" +msgstr "เบลารุส" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +#, fuzzy +msgid "Bemba" +msgstr "&Membase" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "เบงกาลี" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "บอสเนีย" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +#, fuzzy +msgid "Batak (Indonesia)" +msgstr "อินโดนีเซีย" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "บัลแกเรีย" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "คาตาลัน" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +#, fuzzy +msgid "Chechen" +msgstr "ตรวจสอบ" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +#, fuzzy +msgid "Chinese" +msgstr "จีน" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +#, fuzzy +msgid "Cheyenne" +msgstr "กาแยน" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "เช็ก" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "เดนมาร์ก" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +#, fuzzy +msgid "Delaware" +msgstr "ฮาร์ดแวร์" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +#, fuzzy +msgid "Lower Sorbian" +msgstr "เซอร์เบียต่ำ" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "ดัตช์" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +#, fuzzy +msgid "English" +msgstr "อังกฤษ" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "เอสโตเนีย" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +#, fuzzy +msgid "Faroese" +msgstr "หมู่เกาะแฟโร" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +#, fuzzy +msgid "Fanti" +msgstr "แอตแลนติก" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +#, fuzzy +msgid "Fijian" +msgstr "ฟิจิ" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +#, fuzzy +msgid "Filipino" +msgstr "ฟิลิปปินส์" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "ฟินแลนด์" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "ฝรั่งเศส" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +#, fuzzy +msgid "Ga" +msgstr "กวม" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +#, fuzzy +msgid "Germanic (Other)" +msgstr "เยอรมัน (อื่นๆ)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +#, fuzzy +msgid "Georgian" +msgstr "จอร์เจีย" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "เยอรมัน" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "คุชราต" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "ไฮติ" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "ฮิบรู" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "ฮินดี" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +#, fuzzy +msgid "Upper Sorbian" +msgstr "เซอร์เบียบน" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "ฮังการี" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "ไอซ์แลนด์" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "ลิทัวเนีย" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +#, fuzzy +msgid "Interlingue" +msgstr "เขตภายในเครือข่าย" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "อินโดนีเซีย" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "อิตาลี" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +#, fuzzy +msgid "Javanese" +msgstr "ชวา" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "ญี่ปุ่น" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +#, fuzzy +msgid "Kachin" +msgstr "การาจี" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +#, fuzzy +msgid "Kannada" +msgstr "แคนาดา" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +#, fuzzy +msgid "Kazakh" +msgstr "คาซัคสถาน" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "เขมร" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +#, fuzzy +msgid "Kongo" +msgstr "คองโก" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "เกาหลี" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +#, fuzzy +msgid "Lao" +msgstr "ลาว" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "ละติน" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +#, fuzzy +msgid "Latvian" +msgstr "ลัตเวีย" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "ลักเซมเบิร์ก" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "ลิทัวเนีย" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +#, fuzzy +msgid "Mongo" +msgstr "มองโก" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "ลักเซมเบิร์ก" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +#, fuzzy +msgid "Ganda" +msgstr "กันดา" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +#, fuzzy +msgid "Lunda" +msgstr "ลูนดา" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "มาซิโดเนีย" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +#, fuzzy +msgid "Marshallese" +msgstr "มาร์แชลล์" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +#, fuzzy +msgid "Malayalam" +msgstr "มาลายาลัม" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "มันดิงกา" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "เมารี" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "มราฐี" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "มาเลย์" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "ไอริชกลาง (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "มาดากัสการ์" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +#, fuzzy +msgid "Maltese" +msgstr "มอลตา" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "มอลโดวา" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +#, fuzzy +msgid "Mongolian" +msgstr "มองโกเลีย" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "หลายภาษา" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +#, fuzzy +msgid "Creek" +msgstr "มัสคีกี" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "นาวาโฮ" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +#, fuzzy +msgid "Ndonga" +msgstr "ตองกา" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "เยอรมันต่ำ" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +#, fuzzy +msgid "Nepali" +msgstr "เนปาล" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +#, fuzzy +msgid "Niuean" +msgstr "นีวเว" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +#, fuzzy +msgid "Norwegian Nynorsk" +msgstr "นอร์เวย์นีนอสก์" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +#, fuzzy +msgid "Norwegian Bokmal" +msgstr "นอร์เวย์บุคมอล" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "โนไก" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "นอร์สโบราณ" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "นอร์เวย์" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "โซโทเหนือ" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "เนียมเวซี" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "เนียนโกเล" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "นิโอโร" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "นซิมา" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "อ็อกซิตัน (หลัง 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "โอจิบวา" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "โอดิยา" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "โอโรโม" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +#, fuzzy +msgid "Osage" +msgstr "โอซากี" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "ออสเซเตีย" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "ตุรกีออตโตมัน (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "ปังกาซีนัน" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "ปะห์ลาวี" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "ปัมปังกา" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +#, fuzzy +msgid "Panjabi" +msgstr "ปัญจาบ" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +#, fuzzy +msgid "Palauan" +msgstr "ปาเลา" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "เปอร์เซียโบราณ (ประมาณ 600-400 B.C." + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +#, fuzzy +msgid "Persian" +msgstr "เปอร์เซีย" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +#, fuzzy +msgid "Philippine (Other)" +msgstr "ฟิลิปปินส์ (อื่นๆ)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "โปแลนด์" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "โปรตุเกส" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "ญี่ปุ่น" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "โรมาเนีย" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "โรมาเนีย" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +#, fuzzy +msgid "Rundi" +msgstr "บุรุนดี" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "รัสเซีย" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +#, fuzzy +msgid "Sandawe" +msgstr "รวันด้า" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "เซอร์เบีย" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "โครเอเชีย" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +#, fuzzy +msgid "Shan" +msgstr "เซี่ยงไฮ้" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "สิงหล" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "สโลวะเกีย" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "สโลวีเนีย" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +#, fuzzy +msgid "Lule Sami" +msgstr "ชื่อโมดูล" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +#, fuzzy +msgid "Samoan" +msgstr "ซามัว" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +#, fuzzy +msgid "Somali" +msgstr "โซมาเลีย" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "สเปน" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "สวีเดน" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +#, fuzzy +msgid "Syriac" +msgstr "ซีเรีย" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +#, fuzzy +msgid "Tai (Other)" +msgstr "อื่น ๆ" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "ทมิฬ" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "กาต้าร์" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +#, fuzzy +msgid "Tajik" +msgstr "ทาจีกิสถาน" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "ไทย" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +#, fuzzy +msgid "Tonga (Tonga Islands)" +msgstr "หมู่เกาะโซโลมอน" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +#, fuzzy +msgid "Tswana" +msgstr "บอตสวานา" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +#, fuzzy +msgid "Tsonga" +msgstr "ตองก้า" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "ตุรกี" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "ตุรกี" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "ยูเครน" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +#, fuzzy +msgid "Uzbek" +msgstr "อุซเบกิสถาน" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +#, fuzzy +msgid "Vai" +msgstr "วาติกัน" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +#, fuzzy +msgid "Venda" +msgstr "ผู้ผลิต" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "เวียดนาม" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "เวลส์" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "วัลลูน" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "โคซา" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +#, fuzzy +msgid "Yoruba" +msgstr "โยรูบา" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "ซูลู" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +#, fuzzy +msgid "Following actions will be done:" +msgstr "จะมีการดำเนินการตามขั้นตอนต่อไปนี้:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "ยังไม่มีผู้ใช้" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "ยังไม่มีผู้ใช้" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "ไม่ทราบ" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +#, fuzzy +msgid "invalid" +msgstr "ค่าเวลาใช้งานไม่ได้" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +#, fuzzy +msgid "Unknown support option. Description not available" +msgstr "ไม่มีรายละเอียด" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "โหมดที่ไม่รู้จัก" + +#: zypp/base/StrMatcher.cc:153 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "ไม่ทราบค่าของพารามิเตอร์ %1" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "รูปแบบการค้นหา (RegExp)" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "ไม่สามารถสร้างไดเรกทอรี " + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "ไม่สามารถเปิดใช้งานบริการ '%1' ได้" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "ล้มเหลวในการคืนค่าส่วน MBR ของฮาร์ดดิสก์" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, fuzzy, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "การเพิ่มคลังแพกเกจ %1 ล้มเหลว" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +#, fuzzy +msgid "Unhandled repository type" +msgstr "ชื่อของคลังแพกเกจใช้งานไม่ได้" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, fuzzy, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "กำลังเพิ่มคลังแพกเกจ %1" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "ค่าสำหรับตัวเลือก '%1' ไม่ถูกต้อง: %2" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "ไม่สามารถเปิดแฟ้ม %1 ได้" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "ไม่รู้จักตัวเลือกสำหรับคำสั่ง '%1': %2" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "ไม่สามารถสร้างไดเรกทอรี '%1' ได้" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "กำลังตรวจคลังแพกเกจ " + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "ไม่สามารถเปิดใช้งานบริการ '%1' ได้" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +#, fuzzy +msgid "Can't figure out where the service is stored." +msgstr "ไม่สามารถลบบริการได้ เนื่องจากมันยังไม่ถูกติดตั้ง" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "คลังแพกเกจใช้งานไม่ได้" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "ทำต่อไปหรือไม่ ?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "การสร้างแฟ้มสำรองข้อมูลล้มเหลว" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "แพกเกจ %1 เสียหาย การตรวจสอบความถูกต้องล้มเหลว" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "แพกเกจ %1 เสียหาย การตรวจสอบความถูกต้องล้มเหลว" + +#: zypp/repo/PackageProvider.cc:621 +#, fuzzy +msgid "applydeltarpm check failed." +msgstr "การตรวจความถูกต้องล้มเหลว" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "เลือกคลังแพกเกจ" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "ไม่สามารถสร้างไดเร็กทอรี " + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "การตรวจสอบการขึ้นอยู่แก่กันของระบบ ไม่พบปัญหา" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "การตรวจสอบการขึ้นอยู่แก่กันของระบบ ไม่พบปัญหา" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "การตรวจสอบการขึ้นอยู่แก่กันของระบบ ไม่พบปัญหา" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "อ่านค่าของผู้ให้บริการ" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "เขียนค่าของผู้ให้บริการ" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "เขียนค่าของผู้ให้บริการ" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "รุ่นนี้ถูกติดตั้งไว้บนระบบของคุณ" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +#, fuzzy +msgid "Installation has been aborted as directed." +msgstr "การติดตั้งเสร็จสมบูรณ์เพียงบางส่วนเท่านั้น" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "การสร้างแฟ้มสำรองข้อมูลล้มเหลว" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "จัดเก็บแฟ้มการปรับแต่งค่า" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "ข้อมูล rpm output เพิ่มเติม" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "ลายเซ็นใช้ได้" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "ลายเช็นไม่ได้รับการตรวจสอบ" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "ลายเซ็นใช้ได้ แต่กุญแตไม่สามารถเชื่อถือได้" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "ไม่สามารถเปิด pty (%s) ได้" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "ไม่สามารถเปิด pipe (%s) ได้" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +#, fuzzy +msgid "History:" +msgstr "ประวัติ:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, fuzzy, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "host component '%s' ไม่ถูกต้อง" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, fuzzy, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "port component '%s' ไม่ถูกต้อง" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, fuzzy, c-format, boost-format +msgid "Command exited with status %d." +msgstr "ออกจากคำสั่งด้วยสถานะ %d" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "ไม่สามารถ chdir ไป '%s' (%s) ได้" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "" + +#: zypp-media/mediaexception.cc:48 +#, fuzzy, c-format, boost-format +msgid "Bad file name: %s" +msgstr "ชื่อแฟ้ม: %1" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "ไม่พบแฟ้มควบคุม %1 บนสื่อการติดตั้ง" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "ไม่สามารถเปิดแฟ้ม %1 ได้" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, fuzzy, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "ดาวน์โหลดแฟ้มอิมเมจการติดตั้ง" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, fuzzy, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "เกิดข้อผิดพลาดขึ้นระหว่างทำการสร้างคลังแพกเกจ" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "ไม่สามารถเปิดใช้งานบริการ '%1' ได้" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "ใช่" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "ไม่ใช่" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "แจ้งเตือน: " + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "ผิดพลาด" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "เสร็จแล้ว" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "ผิดพลาด" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "แจ้งเตือน: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "กำลังรับข้อมูล:" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "กำลังเริ่ม" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "ไม่พบ" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "ไม่พบข้อความช่วยเหลือของส่วนนี้" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "ไม่พบข้อความช่วยเหลือของตัวเลือกนี้" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ใช่" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ไม่ใช่" + +#, fuzzy +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "กำลังเรียกใช้คลังแพกเกจสำหรับปรับรุ่นให้ทันสมัย..." + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "สถาปัตยกรรมพื้นฐาน" + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "ผิดพลาด: ไม่สามารถติดตั้งแพกเกจได้" + +#, fuzzy +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "เพิ่มคลังแพกเกจแบบออนไลน์ที่เลือกไว้ทั้งหมด" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "ยังไม่มีบริการ %1 อยู่" + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "ไฟร์วอลล์ยังไม่ถูกติดตั้ง" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "ไม่ต้องติดตั้งตัวจัดการการบูตระบบใด ๆ" + +#, fuzzy +#~ msgid "do not install %s" +#~ msgstr "ไม่ต้องติดตั้ง" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "บันทึกการตั้งค่าการติดตั้ง" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "ลบอัตโนมัติ" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "บันทึกการตั้งค่าการติดตั้ง" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "ไม่สามารถเปิดแฟ้ม %1 ได้" + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "ไม่ได้เชื่อมต่อ" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "ทดสอบการเชื่อมต่ออินเทอร์เน็ต" + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "ไม่ต้องติดตั้ง" + +#, fuzzy +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "ดาวน์โหลดแฟ้มอิมเมจการติดตั้ง" + +#, fuzzy +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "เกิดข้อผิดพลาดขึ้นระหว่างทำการสร้างคลังแพกเกจ" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "ล้มเหลวในการดาวน์โหลดแฟ้ม delta ของแพกเกจ RPM: %1" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "เซอร์เบียและมอนเตเนโกร" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "ผู้รวบรวมเผยแพร่ที่ไม่รู้จัก" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "เพิกเฉยต่อการขึ้นอยู่แก่กันของ %s" + +#, fuzzy +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "แฟ้ม '%1' \n" +#~ "ไม่น่าจะเป็นแฟ้มอิมเมจแบบ ISO \n" +#~ "แน่ใจหรือว่าต้องการจะใช้มันจริง ๆ ? \n" + +#, fuzzy +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "แฟ้ม '%1' \n" +#~ "ไม่น่าจะเป็นแฟ้มอิมเมจแบบ ISO \n" +#~ "แน่ใจหรือว่าต้องการจะใช้มันจริง ๆ ? \n" + +#, fuzzy +#~ msgid "%s remove ok" +#~ msgstr "ลบ % เรียบร้อย" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "ไม่ต้องติดตั้งหรือลบสิ่งที่แก้ไขได้ที่กำลังคำนึงถึง" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "ไม่สามารถเปิดแฟ้ม solv-file:" + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "เกิดข้อผิดพลาดระหว่างเขียนแฟ้ม solv-file: " diff --git a/po/tr.po b/po/tr.po new file mode 100644 index 0000000..28cf313 --- /dev/null +++ b/po/tr.po @@ -0,0 +1,6712 @@ +# Turkish message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 1999, 2000, 2001 SuSE GmbH. +# Görkem Çetin , 1999, 2000. +# Mehmet Mıdık , 2000. +# Metin Oral , 2001. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2018-01-29 14:07+0000\n" +"Last-Translator: Özgür Ateş Fırat \n" +"Language-Team: Turkish \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: Weblate 2.18\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Bilinmeyen ülke:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +#, fuzzy +msgid "No Code" +msgstr "&Kod" + +# AD +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andora" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Birleşik Arap Emirlikleri" + +# AF +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antiga ve Barbuda" + +# AI +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Angula" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Arnavutluk" + +# AM +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Ermenistan" + +# AN +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Hollanda Antilleri" + +# AO +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +# AQ +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antartika" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Arjantin" + +# AS +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Amerikan Samoası" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Avusturya" + +# /usr/lib/YaST2/keyboard_raw.ycp:230 +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Avusturalya" + +# AW +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +# KY +#. :ABW:533: +#: zypp/CountryCode.cc:173 +#, fuzzy +msgid "Aland Islands" +msgstr "Seyman Adaları" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaycan" + +# BA +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosna-Hersek" + +# /usr/lib/YaST2/timezone_raw.ycp:58 +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +# menuentries/menuentry_language.ycp:13 +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladeş" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belçika" + +# BF +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +# /usr/lib/YaST2/keyboard_raw.ycp:570 +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaristan" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahreyn" + +# BI +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +# BJ +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +# /usr/lib/YaST2/keyboard_raw.ycp:79 +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +# BN +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Bruney Darüsselam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivya" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brezilya" + +# BS +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamalar" + +# BT +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bütan" + +# BV +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet Adası" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +# BZ +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Kanada" + +# CC +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Cocos (Keeling) Adaları" + +# CG +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Kongo" + +# CF +#. :COD:180: +#: zypp/CountryCode.cc:197 +#, fuzzy +msgid "Central African Republic" +msgstr "Orta Afrika Cumhuriyeti" + +# /usr/lib/YaST2/keyboard_raw.ycp:169 +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "İsviçre" + +# CI +# fuzzy +#. :CHE:756: +#: zypp/CountryCode.cc:200 +#, fuzzy +msgid "Cote D'Ivoire" +msgstr "Cote d'Ivoire" + +# CK +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cook Adaları" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Şili" + +# CM +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Kamerun" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Çin" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Kolombiya" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Kosta Rika" + +# CU +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Küba" + +# CV +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Verde Burnu" + +# CX +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Christmas Adası" + +# CY +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Kıbrıs" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Çek Cumhuriyeti" + +# /usr/lib/YaST2/keyboard_raw.ycp:79 +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Almanya" + +# /usr/lib/YaST2/timezone_raw.ycp:18 +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Cibuti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Danimarka" + +# /usr/lib/YaST2/timezone_raw.ycp:76 +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominik Cumhuriyeti" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Cezayir" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ekvator" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonya" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Mısır" + +# EH +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Batı Sahra" + +# ER +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritre" + +# /usr/lib/YaST2/keyboard_raw.ycp:200 +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "İspanya" + +# ET +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiyopya" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlandiya" + +# include/nis_server/ui.ycp:45 +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +# FK +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falkland Adaları (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Mikronezya Federal Devletleri" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faroe Adaları" + +# /usr/lib/YaST2/keyboard_raw.ycp:139 +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Fransa" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +# GA +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +# /usr/lib/YaST2/timezone_raw.ycp:390 +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "İngiltere" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Gürcistan" + +# GF +# fuzzy +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Fransız Guyanası" + +# /usr/lib/YaST2/keyboard_raw.ycp:79 +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Almanya" + +# GH +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +# /usr/lib/YaST2/timezone_raw.ycp:384 +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Cebelitarık" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Grönland" + +# GM +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambiya" + +# GN +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Gine" + +# /usr/lib/YaST2/timezone_raw.ycp:85 +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +# GQ +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Ekvatoral Gine" + +# /usr/lib/YaST2/keyboard_raw.ycp:320 +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Yunanistan" + +# GS +# fuzzy +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Güney Gürcistan ve Güney Sandoviç Adası" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +# GW +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Gine-Bissau" + +# GY +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +# HM +# fuzzy +#. :HKG:344: +#: zypp/CountryCode.cc:252 +#, fuzzy +msgid "Heard Island and McDonald Islands" +msgstr "Heard Adası and McDonald Adaları" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Hırvatistan" + +# HT +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +# /usr/lib/YaST2/keyboard_raw.ycp:570 +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Macaristan" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Endonezya" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "İrlanda" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "İsrail" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Man Adası" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Hindistan" + +# IO +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Hint Okyanusu İngiliz Sömürgeleri" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Irak" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "İzlanda" + +# /usr/lib/YaST2/keyboard_raw.ycp:230 +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "İtalya" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Jersey" + +# /usr/lib/YaST2/timezone_raw.ycp:347 +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaika" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Ürdün" + +# /usr/lib/YaST2/keyboard_raw.ycp:700 +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japonya" + +# KE +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +# KG +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kırgızistan" + +# KH +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Kamboçya" + +# KI +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +# KM +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Komoros" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +#, fuzzy +msgid "Saint Kitts and Nevis" +msgstr "Sen Kitts ve Nevis" + +# /usr/lib/YaST2/timezone_raw.ycp:374 +#. :KNA:659: +#: zypp/CountryCode.cc:277 +#, fuzzy +msgid "North Korea" +msgstr "Kuzey İrlanda" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +#, fuzzy +msgid "South Korea" +msgstr "Güney Kutbu" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuveyt" + +# KY +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Seyman Adaları" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakistan" + +# CD +# fuzzy +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +#, fuzzy +msgid "Lao People's Democratic Republic" +msgstr "Lao Halk Cumhuriyeti" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Lübnan" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +#, fuzzy +msgid "Saint Lucia" +msgstr "Sen Lusia" + +# /usr/lib/YaST2/timezone_raw.ycp:407 +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +# LK +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +# LR +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberya" + +# LS +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesoto" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litvanya" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Lüksemburg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letonya" + +# LY +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Liberya" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Fas" + +# /usr/lib/YaST2/timezone_raw.ycp:394 +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monako" + +# /usr/lib/YaST2/timezone_raw.ycp:381 +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +# CG +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "Kongo" + +# SM +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "San Marino" + +# MG +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagaskar" + +# MH +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marşal Adaları" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Makedonya" + +# ML +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +# MM +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Miyanmar" + +# MN +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Moğolistan" + +# /usr/lib/YaST2/timezone_raw.ycp:207 +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +# MP +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Kuzey Meryem Adaları" + +# /usr/lib/YaST2/timezone_raw.ycp:99 +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +# MR +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Moritanya" + +# MS +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Monserat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Mali" + +# MW +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malavi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Meksika" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malezya" + +# MZ +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambik" + +# NA +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibya" + +# NC +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Yeni İskoçya" + +# NE +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Nijer" + +# NF +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk Adası" + +# NG +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nikaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Hollanda" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norveç" + +# NP +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +# NU +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Nie" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Yeni Zelenda" + +# /usr/lib/YaST2/keyboard_raw.ycp:79 +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Umman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +# PF +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Fransız Polinezyası" + +# PG +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua Yeni Gine" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Flipinler" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Polonya" + +# PM +# fuzzy +#. :POL:616: +#: zypp/CountryCode.cc:336 +#, fuzzy +msgid "Saint Pierre and Miquelon" +msgstr "Sen Piyer ve Miquelon" + +# /usr/lib/YaST2/timezone_raw.ycp:456 +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Porto Riko" + +# IO +#. :PRI:630: +#: zypp/CountryCode.cc:339 +#, fuzzy +msgid "Palestinian Territory" +msgstr "Hint Okyanusu İngiliz Sömürgeleri" + +# /usr/lib/YaST2/keyboard_raw.ycp:260 +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portekiz" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +# RE +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romanya" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "Sırpça" + +# RU +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Rusya Federasyonu" + +# RW +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Ruanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Suudi Arabistan" + +# SB +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomon Adaları" + +# SC +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seyşel Adaları" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +# /usr/lib/YaST2/keyboard_raw.ycp:440 +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "İsveç" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapur" + +# SH +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sen Helen" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenya" + +# SJ +# fuzzy +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard ve Jan Mayen Adaları" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakya" + +# SL +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +# SM +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +# SN +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +# SO +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somali" + +# SR +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Surinam" + +# ST +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Surinam" + +# SZ +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +# TC +# fuzzy +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +#, fuzzy +msgid "Turks and Caicos Islands" +msgstr "Turks ve Kaykos Adaları" + +# TD +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Çad" + +# TF +# fuzzy +#. :TCD:148: +#: zypp/CountryCode.cc:370 +#, fuzzy +msgid "French Southern Territories" +msgstr "Fransa'nın Güney Bölgeleri" + +# TG +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Tayland" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tacikistan" + +# TK +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +# TM +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Türkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunus" + +# TO +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +# clients/online_update.ycp:223 +#. :TON:776: +#: zypp/CountryCode.cc:378 +#, fuzzy +msgid "East Timor" +msgstr "Hat süresi" + +# /usr/lib/YaST2/keyboard_raw.ycp:668 +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Türkiye" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad ve Tobako" + +# TV +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Tuvalu" + +# TW +# fuzzy +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Tayland" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +#, fuzzy +msgid "Tanzania" +msgstr "Tazmanya" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukrayna" + +# UG +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +# UM +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "United States Minor Outlying Islands" + +# US +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Birleşik Devletler" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Özbekistan" + +# VA +# fuzzy +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatikan" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +#, fuzzy +msgid "Saint Vincent and the Grenadines" +msgstr "Sen Vinsınt ve Granadalar" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezüella" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Britanya Virjin Adaları" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Virgin Adaları (U.S.)" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +# VU +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +# WF +# fuzzy +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis ve Futuna Adaları" + +# /usr/lib/YaST2/timezone_raw.ycp:481 +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +# YT +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Güney Afrika" + +# ZM +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambiya" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +#, fuzzy +msgid "Prerequires" +msgstr "Öngereklilikler" + +# clients/hwinfo.ycp:54 +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Gerekenler" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Eskitiyor" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "%1% dosyasından genel anahtar alınamadı" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Anahtar silinirken hata meydana geldi." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "%s imza dosyası bulunamadı" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Bilinmeyen dil:" + +# /usr/lib/YaST2/timezone_raw.ycp:31 +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr " Afarca" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abhazya" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +#, fuzzy +msgid "Achinese" +msgstr "Çince" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +#, fuzzy +msgid "Acoli" +msgstr "Sessiz" + +# clients/support_question.ycp:85 +#. language code: ada +#: zypp/LanguageCode.cc:169 +#, fuzzy +msgid "Adangme" +msgstr "Aralık" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adigey " + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Asyatik(Diğer)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikanca" + +# clients/inst_resize_ui.ycp:702 +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Aynu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +#, fuzzy +msgid "Akan" +msgstr "Afrikanca" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Akatça" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Arnavutça" + +# /usr/lib/YaST2/timezone_raw.ycp:472 +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Aleutça" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +#, fuzzy +msgid "Algonquian Languages" +msgstr "Dil yapılandırılıyor..." + +#. language code: alt +#: zypp/LanguageCode.cc:193 +#, fuzzy +msgid "Southern Altai" +msgstr "Güney Afrika" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amharca" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "İngilizce, Eski Çağ (ca. 450-1100)" + +# clients/inst_language.ycp:116 +#. language code: apa +#: zypp/LanguageCode.cc:199 +#, fuzzy +msgid "Apache Languages" +msgstr "Dili ayarla" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arapça" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramice" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonca" + +# AM +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Ermenice" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Araukanya" + +# clients/inst_sw_single.ycp:1462 +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Yapay dil (Diğer)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assam " + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturyanca " + +# clients/inst_language.ycp:116 +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Atabask dilleri" + +# /usr/lib/YaST2/keyboard_raw.ycp:230 +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Avusturalya Dilleri" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarca" + +# /usr/lib/YaST2/timezone_raw.ycp:472 +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestaca " + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Abadhi" + +# MM +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +#, fuzzy +msgid "Aymara" +msgstr "Miyanmar" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azerice" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +#, fuzzy +msgid "Banda" +msgstr "Kanada" + +# clients/inst_language.ycp:116 +#. language code: bai +#: zypp/LanguageCode.cc:239 +#, fuzzy +msgid "Bamileke Languages" +msgstr "Dili ayarla" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Başkurtça" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Beluci " + +# /usr/lib/YaST2/timezone_raw.ycp:481 +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +#, fuzzy +msgid "Bambara" +msgstr "Samba" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +#, fuzzy +msgid "Balinese" +msgstr "Çince" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Bask Dili" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +#, fuzzy +msgid "Basa" +msgstr "Temel" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltık (Diğer)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Beca" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Beyaz Rusça" + +# /usr/lib/YaST2/keyboard_raw.ycp:79 +#. language code: bem +#: zypp/LanguageCode.cc:261 +#, fuzzy +msgid "Bemba" +msgstr "Bermuda" + +# SN +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +#, fuzzy +msgid "Bengali" +msgstr "Senegal" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berberi (Diğer)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri " + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +#, fuzzy +msgid "Bihari" +msgstr "Bahreyn" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +# BJ +#. language code: bin +#: zypp/LanguageCode.cc:273 +#, fuzzy +msgid "Bini" +msgstr "Benin" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantu (Diğer)" + +# BJ +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Boşnakça" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +#, fuzzy +msgid "Braj" +msgstr "Brezilya" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Britanyaca" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +#, fuzzy +msgid "Batak (Indonesia)" +msgstr "Endonezya" + +# /usr/lib/YaST2/keyboard_raw.ycp:570 +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Buryatça" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +#, fuzzy +msgid "Buginese" +msgstr "Çince" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgarca" + +# include/scanner/scanner_functions.ycp:114 +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Burmaca" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. language code: byn +#: zypp/LanguageCode.cc:299 +#, fuzzy +msgid "Blin" +msgstr "Belçikaca" + +# TD +#. language code: cad +#: zypp/LanguageCode.cc:301 +#, fuzzy +msgid "Caddo" +msgstr "Çad" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Merkezi Kızılderili (Diğer)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +#, fuzzy +msgid "Carib" +msgstr "Kart" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Katalanca" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Kafkas (Diğer)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +#, fuzzy +msgid "Cebuano" +msgstr "Lübnan" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Kelt (Diğer)" + +# KM +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +#, fuzzy +msgid "Chamorro" +msgstr "Komoros" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +#, fuzzy +msgid "Chibcha" +msgstr "Çin" + +# clients/hwinfo.ycp:44 clients/hwinfo.ycp:93 +#. language code: che ce +#: zypp/LanguageCode.cc:319 +#, fuzzy +msgid "Chechen" +msgstr "Önbellek" + +# /usr/lib/YaST2/timezone_raw.ycp:240 +#. language code: chg +#: zypp/LanguageCode.cc:321 +#, fuzzy +msgid "Chagatai" +msgstr "Şangay" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Çince" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +#, fuzzy +msgid "Chuukese" +msgstr "Çince" + +# ML +#. language code: chm +#: zypp/LanguageCode.cc:329 +#, fuzzy +msgid "Mari" +msgstr "Mali" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Çinok Jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +#, fuzzy +msgid "Choctaw" +msgstr "Chroot" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Çipevyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Çeroki" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Eski Kilise Slavcası" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Çuvaşça" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +#, fuzzy +msgid "Cheyenne" +msgstr "Kanal" + +# menuentries/menuentry_language.ycp:13 +#. language code: cmc +#: zypp/LanguageCode.cc:345 +#, fuzzy +msgid "Chamic Languages" +msgstr "Diller" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +#, fuzzy +msgid "Coptic" +msgstr "Bilgi işleme" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +#, fuzzy +msgid "Cornish" +msgstr "İrlandaca" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +#, fuzzy +msgid "Corsican" +msgstr "Kosta Rika" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Kreyol ve Pidgin Dilleri, İngilizce Kökenli (Diğer)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Kreyol ve Pidgin Dilleri, Fransızca Kökenli (Diğer)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Kreyol ve Pidgin Dilleri, Portekizce Kökenli (Diğer)" + +# clients/lan_inetd_custom.ycp:762 +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +#, fuzzy +msgid "Cree" +msgstr "Oluştur" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Kırım Tatarları" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Kreyol ve Pidgin Dilleri (Diğer)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Kusitik (Diğer)" + +# /usr/lib/YaST2/keyboard_raw.ycp:500 +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Çekçe" + +# clients/online_update_details.ycp:81 +#. language code: dak +#: zypp/LanguageCode.cc:373 +#, fuzzy +msgid "Dakota" +msgstr "Dhaka" + +# /usr/lib/YaST2/keyboard_raw.ycp:380 +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Danca" + +# include/ui/common_messages.ycp:91 +#. language code: dar +#: zypp/LanguageCode.cc:377 +#, fuzzy +msgid "Dargwa" +msgstr "Darwin" + +# clients/hwinfo.ycp:71 +#. language code: day +#: zypp/LanguageCode.cc:379 +#, fuzzy +msgid "Dayak" +msgstr "Gün:" + +#. language code: del +#: zypp/LanguageCode.cc:381 +#, fuzzy +msgid "Delaware" +msgstr "Donanım" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Tlınçonca" + +# classnames.ycp:163 clients/hwinfo.ycp:70 +#. language code: din +#: zypp/LanguageCode.cc:387 +#, fuzzy +msgid "Dinka" +msgstr "Disk" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +#, fuzzy +msgid "Divehi" +msgstr "Sürücü" + +# include/security/ui.ycp:695 +#. language code: doi +#: zypp/LanguageCode.cc:391 +#, fuzzy +msgid "Dogri" +msgstr "Kullanıcı girişi" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravid (Diğer)" + +# classnames.ycp:98 +#. language code: dsb +#: zypp/LanguageCode.cc:395 +#, fuzzy +msgid "Lower Sorbian" +msgstr "Güç koruma" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +#, fuzzy +msgid "Duala" +msgstr "Palau" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Hollanda, Orta Çağ (ca. 1050-1350)" + +# /usr/lib/YaST2/keyboard_raw.ycp:350 +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Felemenkçe" + +# /usr/lib/YaST2/timezone_raw.ycp:191 +#. language code: dyu +#: zypp/LanguageCode.cc:405 +#, fuzzy +msgid "Dyula" +msgstr "Dubai" + +# TO +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +#, fuzzy +msgid "Dzongkha" +msgstr "Tonga" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Mısır (Antik)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elam " + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "İngilizce" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "İngilizce, Orta Çağ (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonyaca" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewe" + +# clients/inst_custom_part.ycp:2932 +#. language code: ewo +#: zypp/LanguageCode.cc:427 +#, fuzzy +msgid "Ewondo" +msgstr "Bitiş" + +# clients/support_question.ycp:85 +#. language code: fan +#: zypp/LanguageCode.cc:429 +#, fuzzy +msgid "Fang" +msgstr "Aralık" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faroece" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +#, fuzzy +msgid "Fanti" +msgstr "Atlantik" + +# include/nis_server/ui.ycp:45 +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +#, fuzzy +msgid "Fijian" +msgstr "Fiji" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +#, fuzzy +msgid "Filipino" +msgstr "Flipinler" + +# /usr/lib/YaST2/keyboard_raw.ycp:470 +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Fince" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fin-Ugor (Diğer)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +#, fuzzy +msgid "Fon" +msgstr "Yazı tipleri" + +# /usr/lib/YaST2/keyboard_raw.ycp:139 +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Fransızca" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Fransız,Orta Çağ (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Fransız, Eski Çağ (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +#, fuzzy +msgid "Frisian" +msgstr "Dosya sistemi s&ürümü" + +# clients/lan_inetd_custom.ycp:756 +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +#, fuzzy +msgid "Fulah" +msgstr "İşaretler" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +#, fuzzy +msgid "Friulian" +msgstr "Finlandiya" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +#, fuzzy +msgid "Ga" +msgstr "Guam" + +# GA +#. language code: gay +#: zypp/LanguageCode.cc:461 +#, fuzzy +msgid "Gayo" +msgstr "Gabon" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +#, fuzzy +msgid "Gbaya" +msgstr "Gaza" + +# /usr/lib/YaST2/keyboard_raw.ycp:109 +#. language code: gem +#: zypp/LanguageCode.cc:465 +#, fuzzy +msgid "Germanic (Other)" +msgstr "Almanca (ölü tuşlar ile)" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +#, fuzzy +msgid "Georgian" +msgstr "Gürcistan" + +# /usr/lib/YaST2/keyboard_raw.ycp:79 +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Almanca" + +# /usr/lib/YaST2/keyboard_raw.ycp:320 +#. language code: gez +#: zypp/LanguageCode.cc:475 +#, fuzzy +msgid "Geez" +msgstr "Yunanca" + +# src/mozilla_i18n.c:37 +#. language code: gil +#: zypp/LanguageCode.cc:477 +#, fuzzy +msgid "Gilbertese" +msgstr "Vietnamca" + +# ML +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +#, fuzzy +msgid "Gaelic" +msgstr "Mali" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "İrlandaca" + +# /usr/lib/YaST2/timezone_raw.ycp:408 +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +#, fuzzy +msgid "Galician" +msgstr "Vatikan" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +#, fuzzy +msgid "Manx" +msgstr "Man" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +# GA +#. language code: gon +#: zypp/LanguageCode.cc:491 +#, fuzzy +msgid "Gondi" +msgstr "Gabon" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotça" + +# GA +#. language code: grb +#: zypp/LanguageCode.cc:497 +#, fuzzy +msgid "Grebo" +msgstr "Gabon" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Yunan, Antik (1453'e kadar)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Yunan, Modern (1453-)" + +# clients/ui_widgets.ycp:156 +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +#, fuzzy +msgid "Guarani" +msgstr "Paranoya" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +#, fuzzy +msgid "Gujarati" +msgstr "Süre" + +# /usr/lib/YaST2/timezone_raw.ycp:478 +#. language code: gwi +#: zypp/LanguageCode.cc:509 +#, fuzzy +msgid "Gwich'in" +msgstr "Michigan" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +#, fuzzy +msgid "Haida" +msgstr "Donanım" + +# HT +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +#, fuzzy +msgid "Haitian" +msgstr "Haiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +#, fuzzy +msgid "Hausa" +msgstr "Saat" + +# /usr/lib/YaST2/timezone_raw.ycp:476 +#. language code: haw +#: zypp/LanguageCode.cc:517 +#, fuzzy +msgid "Hawaiian" +msgstr "Hawaii" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "İbranice" + +# include/ui/common_messages.ycp:95 +#. language code: her hz +#: zypp/LanguageCode.cc:521 +#, fuzzy +msgid "Herero" +msgstr "hata" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +# /usr/lib/YaST2/timezone_raw.ycp:450 +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +#, fuzzy +msgid "Hindi" +msgstr "Midi" + +# HT +#. language code: hit +#: zypp/LanguageCode.cc:529 +#, fuzzy +msgid "Hittite" +msgstr "Haiti" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +#, fuzzy +msgid "Hmong" +msgstr "Hong Kong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +#, fuzzy +msgid "Upper Sorbian" +msgstr "Sırpça" + +# /usr/lib/YaST2/keyboard_raw.ycp:570 +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Macarca" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupaca" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +#, fuzzy +msgid "Iban" +msgstr "Irak" + +# clients/ui_widgets.ycp:85 +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +#, fuzzy +msgid "Igbo" +msgstr "Görmezden gel" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "İzlandaca" + +# clients/inst_custom_part.ycp:2920 +#. language code: ido io +#: zypp/LanguageCode.cc:549 +#, fuzzy +msgid "Ido" +msgstr "Tanıtıcı" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +#, fuzzy +msgid "Sichuan Yi" +msgstr "Litvanya" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +#, fuzzy +msgid "Inuktitut" +msgstr "Başlangıç" + +# clients/online_update.ycp:45 +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +#, fuzzy +msgid "Interlingue" +msgstr "Devam et" + +# /usr/lib/YaST2/timezone_raw.ycp:236 +#. language code: ilo +#: zypp/LanguageCode.cc:559 +#, fuzzy +msgid "Iloko" +msgstr "Tokyo" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "İnterlingua (Uluslararası Yapay Dil Derneği)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Hint (Diğer)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Endonezyaca" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Hint-Avrupa (Diğer)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +#, fuzzy +msgid "Ingush" +msgstr "İngilizce" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +#, fuzzy +msgid "Inupiaq" +msgstr "Hindistan" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "İrani (Diğer)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +#, fuzzy +msgid "Iroquoian Languages" +msgstr "Dil yapılandırılıyor..." + +# /usr/lib/YaST2/keyboard_raw.ycp:230 +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "İtalyanca" + +# /usr/lib/YaST2/keyboard_raw.ycp:700 +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +#, fuzzy +msgid "Javanese" +msgstr "Japonca" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +#, fuzzy +msgid "Lojban" +msgstr "Lübnan" + +# /usr/lib/YaST2/keyboard_raw.ycp:700 +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Japonca" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +#, fuzzy +msgid "Judeo-Persian" +msgstr "Endonezyaca" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +#, fuzzy +msgid "Judeo-Arabic" +msgstr "Arapça" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-kalpaklar" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +#, fuzzy +msgid "Kabyle" +msgstr "Etkin" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +#, fuzzy +msgid "Kachin" +msgstr "Aranacak yer" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Grönlandca" + +# /usr/lib/YaST2/timezone_raw.ycp:481 +#. language code: kam +#: zypp/LanguageCode.cc:597 +#, fuzzy +msgid "Kamba" +msgstr "Samba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +#, fuzzy +msgid "Kannada" +msgstr "Kanada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +#, fuzzy +msgid "Karen" +msgstr "Kore dili" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Keşmirce" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri " + +# MW +#. language code: kaw +#: zypp/LanguageCode.cc:607 +#, fuzzy +msgid "Kawi" +msgstr "Malavi" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +#, fuzzy +msgid "Kazakh" +msgstr "Kazakistan" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardeyce" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +#, fuzzy +msgid "Khasi" +msgstr "Taylandça" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +# classnames.ycp:73 +#. language code: khm km +#: zypp/LanguageCode.cc:617 +#, fuzzy +msgid "Khmer" +msgstr "Zamanlayıcı" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +#, fuzzy +msgid "Khotanese" +msgstr "Çince" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Ruandaca" + +# clients/inst_sw_single.ycp:1461 +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +#, fuzzy +msgid "Kirghiz" +msgstr "Virgin" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +#, fuzzy +msgid "Kimbundu" +msgstr "Tür" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +#, fuzzy +msgid "Konkani" +msgstr "Kore dili" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +#, fuzzy +msgid "Komi" +msgstr "Alan adı" + +# CG +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +#, fuzzy +msgid "Kongo" +msgstr "Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Kore dili" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +#, fuzzy +msgid "Kosraean" +msgstr "Kore dili" + +# /usr/lib/YaST2/timezone_raw.ycp:242 +#. language code: kpe +#: zypp/LanguageCode.cc:639 +#, fuzzy +msgid "Kpelle" +msgstr "İmla" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karaçay-Balkarca" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +# /usr/lib/YaST2/keyboard_raw.ycp:668 +#. language code: kru +#: zypp/LanguageCode.cc:645 +#, fuzzy +msgid "Kurukh" +msgstr "Türkçe" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +#, fuzzy +msgid "Kuanyama" +msgstr "Panama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +#, fuzzy +msgid "Kumyk" +msgstr "Geçersiz" + +# /usr/lib/YaST2/keyboard_raw.ycp:668 +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +#, fuzzy +msgid "Kurdish" +msgstr "Türkçe" + +# KE +#. language code: kut +#: zypp/LanguageCode.cc:653 +#, fuzzy +msgid "Kutenai" +msgstr "Kenya" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +#, fuzzy +msgid "Ladino" +msgstr "Radyo" + +# UG +#. language code: lah +#: zypp/LanguageCode.cc:657 +#, fuzzy +msgid "Lahnda" +msgstr "Uganda" + +# /usr/lib/YaST2/timezone_raw.ycp:481 +#. language code: lam +#: zypp/LanguageCode.cc:659 +#, fuzzy +msgid "Lamba" +msgstr "Samba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +#, fuzzy +msgid "Lao" +msgstr "Kayıt" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +#, fuzzy +msgid "Latin" +msgstr "Letonyaca" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letonyaca" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. language code: lez +#: zypp/LanguageCode.cc:667 +#, fuzzy +msgid "Lezghian" +msgstr "Belçikaca" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +#, fuzzy +msgid "Limburgan" +msgstr "Lüksemburg" + +# AO +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +#, fuzzy +msgid "Lingala" +msgstr "Angola" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litvanyaca" + +# CG +#. language code: lol +#: zypp/LanguageCode.cc:675 +#, fuzzy +msgid "Mongo" +msgstr "Kongo" + +# include/security/ui.ycp:695 +#. language code: loz +#: zypp/LanguageCode.cc:677 +#, fuzzy +msgid "Lozi" +msgstr "Kullanıcı girişi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +#, fuzzy +msgid "Luxembourgish" +msgstr "Lüksemburg" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +# GH +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +#, fuzzy +msgid "Ganda" +msgstr "Gana" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +#, fuzzy +msgid "Luiseno" +msgstr "Bunları dinle" + +# menuentries/menuentry_sound.ycp:14 +#. language code: lun +#: zypp/LanguageCode.cc:689 +#, fuzzy +msgid "Lunda" +msgstr "Pazar" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +#, fuzzy +msgid "Lushai" +msgstr "Taylandça" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Makedonyaca" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +#, fuzzy +msgid "Madurese" +msgstr "Faroece" + +# MW +#. language code: mag +#: zypp/LanguageCode.cc:701 +#, fuzzy +msgid "Magahi" +msgstr "Malavi" + +# MH +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +#, fuzzy +msgid "Marshallese" +msgstr "Marşal Adaları" + +# ML +#. language code: mai +#: zypp/LanguageCode.cc:705 +#, fuzzy +msgid "Maithili" +msgstr "Mali" + +# MG +#. language code: mak +#: zypp/LanguageCode.cc:707 +#, fuzzy +msgid "Makasar" +msgstr "Madagaskar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +#, fuzzy +msgid "Malayalam" +msgstr "Malezya" + +# include/ui/common_messages.ycp:91 +#. language code: man +#: zypp/LanguageCode.cc:711 +#, fuzzy +msgid "Mandingo" +msgstr "Uyarı" + +# /usr/lib/YaST2/timezone_raw.ycp:207 +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +#, fuzzy +msgid "Maori" +msgstr "Yüksek" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Avustranezya (Diğer)" + +# clients/online_update_details.ycp:88 clients/online_update_select.ycp:112 +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +#, fuzzy +msgid "Marathi" +msgstr "Matematik" + +# MW +#. language code: mas +#: zypp/LanguageCode.cc:721 +#, fuzzy +msgid "Masai" +msgstr "Malavi" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +#, fuzzy +msgid "Malay" +msgstr "Malta" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +# MM +#. language code: mdr +#: zypp/LanguageCode.cc:729 +#, fuzzy +msgid "Mandar" +msgstr "Miyanmar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +#, fuzzy +msgid "Mende" +msgstr "Mod" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "İrlandaca, Orta Çağ (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +# clients/ui_helps.ycp:139 include/security/ui.ycp:624 +#. language code: mis +#: zypp/LanguageCode.cc:739 +#, fuzzy +msgid "Miscellaneous Languages" +msgstr "Diğer ayarlar" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +# MG +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +#, fuzzy +msgid "Malagasy" +msgstr "Madagaskar" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +#, fuzzy +msgid "Maltese" +msgstr "Mali" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +#, fuzzy +msgid "Manchu" +msgstr "Man" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +# menuentries/menuentry_language.ycp:13 +#. language code: mno +#: zypp/LanguageCode.cc:751 +#, fuzzy +msgid "Manobo Languages" +msgstr "Diller" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +# /usr/lib/YaST2/timezone_raw.ycp:381 +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +#, fuzzy +msgid "Moldavian" +msgstr "Moldova" + +# MN +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +#, fuzzy +msgid "Mongolian" +msgstr "Moğolistan" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +#, fuzzy +msgid "Mossi" +msgstr "Mors" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +#, fuzzy +msgid "Multiple Languages" +msgstr "&Çoklu anahtarlar" + +# menuentries/menuentry_language.ycp:13 +#. language code: mun +#: zypp/LanguageCode.cc:763 +#, fuzzy +msgid "Munda languages" +msgstr "Diller" + +# /usr/lib/YaST2/keyboard_raw.ycp:320 +#. language code: mus +#: zypp/LanguageCode.cc:765 +#, fuzzy +msgid "Creek" +msgstr "Yunanca" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +#, fuzzy +msgid "Mirandese" +msgstr "Maine" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +#, fuzzy +msgid "Marwari" +msgstr "Donanım" + +# menuentries/menuentry_language.ycp:13 +#. language code: myn +#: zypp/LanguageCode.cc:771 +#, fuzzy +msgid "Mayan Languages" +msgstr "Diller" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +#, fuzzy +msgid "Nahuatl" +msgstr "El ile" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +#, fuzzy +msgid "North American Indian" +msgstr "Kuzey Amerika" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +# /usr/lib/YaST2/timezone_raw.ycp:356 +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +# TO +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +#, fuzzy +msgid "Ndonga" +msgstr "Tonga" + +# /usr/lib/YaST2/keyboard_raw.ycp:79 +#. language code: nds +#: zypp/LanguageCode.cc:791 +#, fuzzy +msgid "Low German" +msgstr "Almanca" + +# NP +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +#, fuzzy +msgid "Nepali" +msgstr "Nepal" + +# NP +#. language code: new +#: zypp/LanguageCode.cc:795 +#, fuzzy +msgid "Nepal Bhasa" +msgstr "Nepal" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +#, fuzzy +msgid "Nias" +msgstr "Takma ad" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +# NU +#. language code: niu +#: zypp/LanguageCode.cc:801 +#, fuzzy +msgid "Niuean" +msgstr "Nie" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +#, fuzzy +msgid "Norwegian Nynorsk" +msgstr "Norveççe" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +#, fuzzy +msgid "Norwegian Bokmal" +msgstr "Norveççe" + +# TO +#. language code: nog +#: zypp/LanguageCode.cc:807 +#, fuzzy +msgid "Nogai" +msgstr "Tonga" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norveççe" + +# /usr/lib/YaST2/timezone_raw.ycp:374 +#. language code: nso +#: zypp/LanguageCode.cc:813 +#, fuzzy +msgid "Northern Sotho" +msgstr "Kuzey İrlanda" + +# clients/inst_language.ycp:116 +#. language code: nub +#: zypp/LanguageCode.cc:815 +#, fuzzy +msgid "Nubian Languages" +msgstr "Dili ayarla" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +#, fuzzy +msgid "Classical Newari" +msgstr "Sınıf adı" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +#, fuzzy +msgid "Chichewa" +msgstr "Şili" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +#, fuzzy +msgid "Nyamwezi" +msgstr "Ad" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +#, fuzzy +msgid "Nyoro" +msgstr "Kuzey" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +#, fuzzy +msgid "Nzima" +msgstr "Lima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +#, fuzzy +msgid "Oriya" +msgstr "Surinam" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +#, fuzzy +msgid "Oromo" +msgstr "root" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +#, fuzzy +msgid "Osage" +msgstr "kaydet" + +# /usr/lib/YaST2/keyboard_raw.ycp:638 +#. language code: oss os +#: zypp/LanguageCode.cc:839 +#, fuzzy +msgid "Ossetian" +msgstr "Rusça" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +# clients/inst_language.ycp:116 +#. language code: oto +#: zypp/LanguageCode.cc:843 +#, fuzzy +msgid "Otomian Languages" +msgstr "Dili ayarla" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +# /usr/lib/YaST2/keyboard_raw.ycp:570 +#. language code: pag +#: zypp/LanguageCode.cc:847 +#, fuzzy +msgid "Pangasinan" +msgstr "Macarca" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +#, fuzzy +msgid "Pahlavi" +msgstr "Palau" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +#, fuzzy +msgid "Pampanga" +msgstr "Paraguay" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +#, fuzzy +msgid "Panjabi" +msgstr "Panama" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +#, fuzzy +msgid "Papiamento" +msgstr "Parametre" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +#, fuzzy +msgid "Palauan" +msgstr "Palau" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +# clients/inst_sw_single.ycp:1461 +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +#, fuzzy +msgid "Persian" +msgstr "Sürüm" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +#, fuzzy +msgid "Philippine (Other)" +msgstr "Flipinler" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +#, fuzzy +msgid "Phoenician" +msgstr "Slovence" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +#, fuzzy +msgid "Pali" +msgstr "Palm" + +# /usr/lib/YaST2/keyboard_raw.ycp:604 +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Lehçe" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +#, fuzzy +msgid "Pohnpeian" +msgstr "Endonezyaca" + +# /usr/lib/YaST2/keyboard_raw.ycp:260 +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portekizce" + +# clients/inst_language.ycp:116 +#. language code: pra +#: zypp/LanguageCode.cc:877 +#, fuzzy +msgid "Prakrit Languages" +msgstr "Dili ayarla" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +# include/security/ui.ycp:417 +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +#, fuzzy +msgid "Pushto" +msgstr "Özel" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +#, fuzzy +msgid "Rajasthani" +msgstr "Kazakistan" + +# /usr/lib/YaST2/keyboard_raw.ycp:700 +#. language code: rap +#: zypp/LanguageCode.cc:887 +#, fuzzy +msgid "Rapanui" +msgstr "Japonya" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +#, fuzzy +msgid "Rarotongan" +msgstr "Yönlendirme oku" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +#, fuzzy +msgid "Romany" +msgstr "Romanya" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Romence" + +# RE +#. language code: run rn +#: zypp/LanguageCode.cc:901 +#, fuzzy +msgid "Rundi" +msgstr "Reunion" + +# /usr/lib/YaST2/keyboard_raw.ycp:638 +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rusça" + +# include/cups/helps.ycp:578 +#. language code: sad +#: zypp/LanguageCode.cc:905 +#, fuzzy +msgid "Sandawe" +msgstr "Yatay" + +# /usr/lib/YaST2/keyboard_raw.ycp:200 +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +#, fuzzy +msgid "Sango" +msgstr "Saygon" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +#, fuzzy +msgid "Yakut" +msgstr "Breakout" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +# clients/inst_language.ycp:116 +#. language code: sal +#: zypp/LanguageCode.cc:913 +#, fuzzy +msgid "Salishan Languages" +msgstr "Dili ayarla" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +# clients/inst_custom_part.ycp:2930 +#. language code: san sa +#: zypp/LanguageCode.cc:917 +#, fuzzy +msgid "Sanskrit" +msgstr "Başlangıç" + +# /usr/lib/YaST2/timezone_raw.ycp:481 +#. language code: sas +#: zypp/LanguageCode.cc:919 +#, fuzzy +msgid "Sasak" +msgstr "Samoa" + +# /usr/lib/YaST2/timezone_raw.ycp:240 +#. language code: sat +#: zypp/LanguageCode.cc:921 +#, fuzzy +msgid "Santali" +msgstr "Şangay" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Sırpça" + +# /usr/lib/YaST2/timezone_raw.ycp:478 +#. language code: scn +#: zypp/LanguageCode.cc:927 +#, fuzzy +msgid "Sicilian" +msgstr "Michigan" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +#, fuzzy +msgid "Scots" +msgstr "Saniye" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Hırvatça" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +#, fuzzy +msgid "Selkup" +msgstr "Atla" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "İrlandaca, Eski Çağ (900'e kadar)" + +# menuentries/menuentry_language.ycp:13 +#. language code: sgn +#: zypp/LanguageCode.cc:941 +#, fuzzy +msgid "Sign Languages" +msgstr "Diller" + +# GH +#. language code: shn +#: zypp/LanguageCode.cc:943 +#, fuzzy +msgid "Shan" +msgstr "Gana" + +# /usr/lib/YaST2/timezone_raw.ycp:481 +#. language code: sid +#: zypp/LanguageCode.cc:945 +#, fuzzy +msgid "Sidamo" +msgstr "Samoa" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +#, fuzzy +msgid "Sinhala" +msgstr "Seri numara" + +# clients/inst_language.ycp:116 +#. language code: sio +#: zypp/LanguageCode.cc:949 +#, fuzzy +msgid "Siouan Languages" +msgstr "Dili ayarla" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Slovakça" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Slovence" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +# /usr/lib/YaST2/timezone_raw.ycp:374 +#. language code: sme se +#: zypp/LanguageCode.cc:963 +#, fuzzy +msgid "Northern Sami" +msgstr "Kuzey İrlanda" + +# menuentries/menuentry_language.ycp:13 +#. language code: smi +#: zypp/LanguageCode.cc:965 +#, fuzzy +msgid "Sami Languages (Other)" +msgstr "Diller" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +#, fuzzy +msgid "Lule Sami" +msgstr "Modül adı" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +# /usr/lib/YaST2/timezone_raw.ycp:481 +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +#, fuzzy +msgid "Samoan" +msgstr "Samoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +#, fuzzy +msgid "Shona" +msgstr "Slovenya" + +# /usr/lib/YaST2/timezone_raw.ycp:450 +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +#, fuzzy +msgid "Sindhi" +msgstr "Midi" + +# clients/online_update.ycp:45 +#. language code: snk +#: zypp/LanguageCode.cc:979 +#, fuzzy +msgid "Soninke" +msgstr "Devam et" + +# include/security/ui.ycp:695 +#. language code: sog +#: zypp/LanguageCode.cc:981 +#, fuzzy +msgid "Sogdian" +msgstr "Kullanıcı girişi" + +# SO +#. language code: som so +#: zypp/LanguageCode.cc:983 +#, fuzzy +msgid "Somali" +msgstr "Somali" + +# /usr/lib/YaST2/timezone_raw.ycp:240 +#. language code: son +#: zypp/LanguageCode.cc:985 +#, fuzzy +msgid "Songhai" +msgstr "Şangay" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +# /usr/lib/YaST2/keyboard_raw.ycp:200 +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "İspanyolca" + +# MR +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +#, fuzzy +msgid "Sardinian" +msgstr "Moritanya" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +#, fuzzy +msgid "Serer" +msgstr "Sunucu" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +# HT +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +#, fuzzy +msgid "Swati" +msgstr "Haiti" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +#, fuzzy +msgid "Sukuma" +msgstr "Özet" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +#, fuzzy +msgid "Sundanese" +msgstr "Sudan" + +# clients/hwinfo.ycp:43 +#. language code: sus +#: zypp/LanguageCode.cc:1003 +#, fuzzy +msgid "Susu" +msgstr "SMBus" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +#, fuzzy +msgid "Sumerian" +msgstr "Sırpça" + +# SZ +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +#, fuzzy +msgid "Swahili" +msgstr "Swaziland" + +# /usr/lib/YaST2/keyboard_raw.ycp:440 +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "İsveççe" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +#, fuzzy +msgid "Syriac" +msgstr "Surinam" + +# /usr/lib/YaST2/timezone_raw.ycp:461 +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +#, fuzzy +msgid "Tahitian" +msgstr "Tahiti" + +# include/cups/ui.ycp:346 +#. language code: tai +#: zypp/LanguageCode.cc:1015 +#, fuzzy +msgid "Tai (Other)" +msgstr "Diğer" + +# clients/hwinfo.ycp:51 +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +#, fuzzy +msgid "Tamil" +msgstr "Aile" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +#, fuzzy +msgid "Tatar" +msgstr "Katar" + +# /usr/lib/YaST2/keyboard_raw.ycp:410 +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +#, fuzzy +msgid "Telugu" +msgstr "Belçika" + +# classnames.ycp:73 +#. language code: tem +#: zypp/LanguageCode.cc:1023 +#, fuzzy +msgid "Timne" +msgstr "Süre" + +# include/cups/ui.ycp:2582 +#. language code: ter +#: zypp/LanguageCode.cc:1025 +#, fuzzy +msgid "Tereno" +msgstr "Tex bilgisi" + +# classnames.ycp:96 +#. language code: tet +#: zypp/LanguageCode.cc:1027 +#, fuzzy +msgid "Tetum" +msgstr "Pentium" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +#, fuzzy +msgid "Tajik" +msgstr "Taylandça" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Taylandça" + +# TW +# fuzzy +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +#, fuzzy +msgid "Tibetan" +msgstr "Tayland" + +# clients/ui_widgets.ycp:85 +#. language code: tig +#: zypp/LanguageCode.cc:1039 +#, fuzzy +msgid "Tigre" +msgstr "görmezden gel" + +# NG +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +#, fuzzy +msgid "Tigrinya" +msgstr "Nigeria" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +# /usr/lib/YaST2/keyboard_raw.ycp:200 +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +#, fuzzy +msgid "Klingon" +msgstr "Saygon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +#, fuzzy +msgid "Tlingit" +msgstr "Posta listeleri" + +# /usr/lib/YaST2/timezone_raw.ycp:221 +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +#, fuzzy +msgid "Tamashek" +msgstr "Taşkent" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +# SB +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +#, fuzzy +msgid "Tonga (Tonga Islands)" +msgstr "Solomon Adaları" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +#, fuzzy +msgid "Tok Pisin" +msgstr "Token Ring" + +# /usr/lib/YaST2/keyboard_raw.ycp:638 +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +#, fuzzy +msgid "Tsimshian" +msgstr "Rusça" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +#, fuzzy +msgid "Tswana" +msgstr "Botswana" + +# TO +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +#, fuzzy +msgid "Tsonga" +msgstr "Tonga" + +# /usr/lib/YaST2/keyboard_raw.ycp:668 +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +#, fuzzy +msgid "Turkmen" +msgstr "Türkiye" + +# /usr/lib/YaST2/timezone_raw.ycp:48 +#. language code: tum +#: zypp/LanguageCode.cc:1067 +#, fuzzy +msgid "Tumbuka" +msgstr "Timbuktu" + +# clients/inst_language.ycp:116 +#. language code: tup +#: zypp/LanguageCode.cc:1069 +#, fuzzy +msgid "Tupi Languages" +msgstr "Dili ayarla" + +# /usr/lib/YaST2/keyboard_raw.ycp:668 +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Türkçe" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altay(Diğer)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +#, fuzzy +msgid "Tuvinian" +msgstr "Tunus" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +# HT +#. language code: uga +#: zypp/LanguageCode.cc:1083 +#, fuzzy +msgid "Ugaritic" +msgstr "Haiti" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +#, fuzzy +msgid "Ukrainian" +msgstr "Ukrayna" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Belirsiz" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +#, fuzzy +msgid "Uzbek" +msgstr "Özbekistan" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +#, fuzzy +msgid "Vai" +msgstr "Vi" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +#, fuzzy +msgid "Venda" +msgstr "Üretici" + +# src/mozilla_i18n.c:37 +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamca" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +# /usr/lib/YaST2/timezone_raw.ycp:408 +#. language code: vot +#: zypp/LanguageCode.cc:1105 +#, fuzzy +msgid "Votic" +msgstr "Vatikan" + +# clients/inst_language.ycp:116 +#. language code: wak +#: zypp/LanguageCode.cc:1107 +#, fuzzy +msgid "Wakashan Languages" +msgstr "Dili ayarla" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +#, fuzzy +msgid "Walamo" +msgstr "Palm" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +#, fuzzy +msgid "Waray" +msgstr "Cumartesi" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +# clients/inst_mouse.ycp:83 +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +#, fuzzy +msgid "Welsh" +msgstr "Batı" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +#, fuzzy +msgid "Sorbian Languages" +msgstr "Dil yapılandırılıyor..." + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +#, fuzzy +msgid "Walloon" +msgstr "tümü" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +#, fuzzy +msgid "Kalmyk" +msgstr "Konuşma" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +# /usr/lib/YaST2/keyboard_raw.ycp:700 +#. language code: yap +#: zypp/LanguageCode.cc:1131 +#, fuzzy +msgid "Yapese" +msgstr "Japonca" + +# include/nis_server/ui.ycp:45 +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +#, fuzzy +msgid "Yiddish" +msgstr "Sonlandır" + +# AW +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +#, fuzzy +msgid "Yoruba" +msgstr "Aruba" + +# clients/inst_language.ycp:116 +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +#, fuzzy +msgid "Yupik Languages" +msgstr "Dili ayarla" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +#, fuzzy +msgid "Zenaga" +msgstr "Grenada" + +# BT +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +#, fuzzy +msgid "Zhuang" +msgstr "Bütan" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +#, fuzzy +msgid "Zande" +msgstr "Bölge" + +# /usr/lib/YaST2/timezone_raw.ycp:326 +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +#, fuzzy +msgid "Zuni" +msgstr "Tunis" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Aşağıdaki işlemler tamamlanacak:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "(süresi dolmadı)" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(süresi dolmadı)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(SÜRESİ DOLDU)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(24 saat içinde süresi dolacak)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" + +# include/cups/ui.ycp:2577 include/cups/ui.ycp:2598 +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "bilinmeyen" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "desteklenmeyen" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Seviye 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Seviye 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Seviye 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Ek Kullanıcı Sözleşmesi Gerekli" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "geçersiz" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Destek seviyesi belirtilmemiş" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Sağlayıcı destek sağlamıyor." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Destek almak için ek kullanıcı sözleşmesi gerekmektedir." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Bilinmeyen destek seçeneği. Açıklama bulunamadı" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Sistem yönetimi uygulama tarafından pid kullanılarak kilitlendi %d (%s). \n" +"Tekrar denemeden önce bu uygulamayı kapatın." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Geçersiz düzenli ifade '%s': regcomp %d döndürdü" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Geçersiz düzenli ifade '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "'%s' için kimlik doğrulama gerekmektedir" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Kaydınızın geçerli olduğundan ve süresinin dolmadığından emin olmak için en " +"yakın Novell Müşteri Merkezini ziyaret edin." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Metadata önbellek klasörü oluşturulamadı." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "'%s' okunmaya çalışılırken bir hata meydana geldi" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "%s oluşturulamıyor" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %d." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "'%s' depo önbelleği oluşturuluyor" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "%s 'de önbellek oluşturulamıyor - yazma izni yok." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "'%s' depoya ekleniyor" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Geçersiz yetki '{0}'" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "'%s' dosyası açılamıyor." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "'%s' dosyası okunamadı" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "'%s' deposu siliniyor" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Reponun nerede depolandığı belirlenemedi." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "'%s' silinemiyor" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Servesin nerede depolandığı belirlenemedi." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Depo ismi noktayla başlayamaz." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Servis ismi noktayla başlayamaz." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Devam edilsin mi?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Gerekli '%s' niteliği bulunamadı." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "'%s' ya da '%s' niteliklerinden biri yada ikisi birden gerekli." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"%s paketi aktarılırken hasar görmüş olabilir. Kurtarmayı denemek istiyor " +"musunuz?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "%s Paketi bulunamadı. Tekrar aramak ister misiniz?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "'%s' deposundaki '%s' e ulaşılamıyor" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Sat-pool oluşturulamadı." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "şu çözülmemiş gereksinimlere sahip:" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +# clients/inst_sw_single.ycp:742 +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "Yetersiz bağımlılıklar:" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"Yüklenemez sağlayıcılar:" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "Yüklenemez sağlayıcılar:" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Bu istek sisteminizi çökertecek!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Yükleme yönlendirildiği şekilde iptal edildi" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "uygulandı" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr "işletme hatası" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "İptal etme sırasında uygulama es geçildi." + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" +"Güncelleme bilgilendirmesi için mesaj gönderilirken bir hata meydana geldi." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +# clients/online_update_load.ycp:380 +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "İndirme işlemi başarısız oldu:" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "%1% dosyasından genel anahtar alınamadı" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "'%1%' genel anahtarı silinemedi" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +# clients/sw_single.ycp:310 +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, fuzzy, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Yapılandırma dosyalarını kaydet" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Ek rpm çıktısı" + +# clients/inst_sw_backup.ycp:260 +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "%s yedeklemesi oluşturuldu" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Kararsız '%s' türü için %u bayt sğlama toplamı '%s'" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Pty açılamıyor (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Veri yolu açılamıyor (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +#, fuzzy +msgid "Unable to clone Url object" +msgstr "çalışma alanı oluşturulamadı\n" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +#, fuzzy +msgid "Unable to parse Url components" +msgstr "çalışma alanı oluşturulamadı\n" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Tarih:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +# include/nfs/routines.ycp:188 +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Geçersiz %s bileşeni '%s'" + +# include/nfs/routines.ycp:188 +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Geçersiz %s bileşeni" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, fuzzy, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Geçersiz yetki '{0}'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +# include/nfs/routines.ycp:188 +#: zypp-core/url/UrlBase.cc:1127 +#, fuzzy, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Geçersiz özellik '{0}'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +# include/nfs/routines.ycp:188 +#: zypp-core/url/UrlBase.cc:1159 +#, fuzzy, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Geçersiz özellik '{0}'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Kodlanmış dizi bir NUL baytı içerir" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Geçersiz dizi karakteri ayırma parametresi" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Geçersiz dizi karakteri birleştirme parametresi" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Komut %d durumuyla çıkış yaptı." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Komut %d sinyali tarafından durduruldu (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Bağlanıken çalıştırılacak komut" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "'%s' e chroot yapılamıyor (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "'%s' yürütülemedi (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Ayrıştırılamadı (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "%s açılamadı - %s\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Hatalı dosya adı: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "'%s' işlemi gerçekleştirilmeye çalışılırken ortam açılamadı." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "'%s' dosyası '%s' ortamında bulunamadı" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "'%s' dosyası yazılamadı." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Ortam ekli değil" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Hatalı medya bağlantı noktası" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "'%s' için indirme (curl) başlatılamadı" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "'%s' ortamındaki '%s' te sistem isnası meydana geldi." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "'%s' ortamındaki '%s' yolu bir dosya değil." + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Hata: %s temel dizini bir dizin değil, atlanıyor.\n" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "URI de boş alan adı" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "URI de boş dosya sistemi" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "URI de içeriksiz hedef" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +#, fuzzy +msgid "Operation not supported by medium" +msgstr "Profil sürümü Apparmor modülü tarafından desteklenmiyor\n" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"'%s' için indirme(curl) hatası:\n" +"Hata kodu: %s\n" +"Hata raporu: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"'%s' için indirme (curl) ayarları düzenlenirken bir hata meydana geldi:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "'%s' medya kaynağı gerekli ortamı içermiyor." + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "'%s' medyası başka bir oluşum tarafından kullanımda" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Hiçbir sürücü çıkartılamıyor" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "'%s' medyası çıkartılamadı" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "İzin verilmedi\n" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "'%s' konumuna şuan ulaşılamaz. " + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +"SSL sertifikası problemi, CA sertifikasının '%s' için geçerli olduğunu " +"doğrulayın." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Evet" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Hayır" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Not:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Uyarı:" + +# include/ui/common_messages.ycp:95 +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Hata:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "tamamlandı" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +#, fuzzy +msgid "attention" +msgstr "dikkat" + +# include/ui/common_messages.ycp:95 +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "hata" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Uyarı: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Alınıyor:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "başlatılıyor" + +# clients/nis_write.ycp:73 +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "bulunamadı" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "Bu seçenek için yardım mevcut değil" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "tüm seçenekleri göster" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "evet" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "hayır" + +#, fuzzy +#~ msgid "Package is not signed!" +#~ msgstr "Geri yüklenecek paketler" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s dağıtım güncelleme deposuna ait değil." + +# clients/hwinfo.ycp:66 +#~ msgid "%s has inferior architecture" +#~ msgstr "%s alt mimariye sahip" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "İstenen bütün depoları etkinleştirdiğinizden emin misiniz?" + +# clients/online_update_start.ycp:171 +#~ msgid "%s is not installable" +#~ msgstr "%s kurulabilir değil" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#~ msgid "cannot install both %s and %s" +#~ msgstr "%s ve %s in ikisi birden yüklenemez" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s, %s tarafından sağlanan %s ile çakışıyor." + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s %s tarafından sağlanan %s'in süresini bitirdi." + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%1, %2 ile çakışıyor" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s, %s'i gerektiriyor, ama bu gereklilik sağlanamıyor." + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#~ msgid "do not install %s" +#~ msgstr "%s yüklenmedi" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%1 paketini sil" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Kurulum" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Kilitlenmiş dosya açılamıyor: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Bu işlem zaten başka bir program tarafından çalıştırıldı." + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Üzgünüz, libzypp'nin bu versiyonunda HAL desteklenmemektedir." + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "bağlı değil" + +#, fuzzy +#~ msgid "Unable to create dbus connection" +#~ msgstr "çalışma alanı oluşturulamadı\n" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Mutex nitelikleri başlatılamıyor" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Yinelemeli mutex nitelikleri ayarlanamadı." + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Yinelemeli mutex başlatılamıyor" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Mutex kilidine ulaşılamadı." + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Mutex kilidi açılamıyor" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "%s dosyasından genel anahtar alınamadı: %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "'%s' genel anahtarı silinemedi: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr " '%s' deki image dosyasını bağlayacak döngü aracı bulunamadı" + +#, fuzzy +#~ msgid "generally ignore of some dependecies" +#~ msgstr "şu çözülmemiş gereksinimlere sahip:" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#, fuzzy +#~ msgid "do not forbid installation of %s" +#~ msgstr "Kurulan disk:" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#~ msgid "do not keep %s installed" +#~ msgstr "%s i kurulu halde bırakmayın" + +#~ msgid "Tried to import not existant key %s into keyring %s" +#~ msgstr "حاول استيراد مفتاح غير موجود %s إلى حلقة مفاتيح %s" + +#~ msgid "Valid metadata not found at specified URL(s)" +#~ msgstr "بيانات التعريف غير صحيحة لم يتم العثور عليها في المسار(s)" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "خيار list غير معروف" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "لا يحتوي الملف %s على مجموع اختباري.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الملف %s باستخدام المفتاح التالي:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير صالح.\n" +#~ "متوقع %s، تم العثور على %s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "يحتوي الملف %s على مجموع اختباري غير معروف %s.\n" +#~ "هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "لم يتم توقيع الملف %s.\n" +#~ "هل تريد استخدامه على أي حال؟" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "تم توقيع الملف %s باستخدام مفتاح غير معروف:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد استخدام الملف على أي حال؟" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "تم العثور على مفتاح غير موثوق:\n" +#~ "%s|%s|%s\n" +#~ " هل تريد الوثوق بالمفتاح؟" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "كلمة السر CA غير صالحة." + +#~ msgid "%s remove ok" +#~ msgstr "تمت إزالة %s بنجاح" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "يوفر %s هذه التبعية، لكنه سيؤدي إلى تغيير هيكل العنصر المثبَّت" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "قم بتثبيت %s بالرغم من أنه قد يؤدي إلى تغيير الهيكل" + +#~ msgid "delete %s" +#~ msgstr "حذف %s" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "تعذر فتح الملف %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "تعذرت قراءة القطاع %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "تحليل معلمة المسار غير مدعوم لعنوان URL هذا" + +#~ msgid "Software management is already running." +#~ msgstr "إدارة البرامج قيد التشغيل بالفعل." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "لن يتم إلغاء تثبيت %s لأنه لا يزال مطلوبًا" + +#~ msgid "Invalid information" +#~ msgstr "المعلومات غير صالحة" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s مطلوب بواسطة التبعيات القابلة للتحليل الأخرى" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s مطلوب بواسطة\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s يجعل التبعيات القابلة للتحليل الأخرى قديمة" + +#~ msgid "%s obsoletes:%s" +#~ msgstr "%s يجعل العنصر التالي قديمًا:%s" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "سيتم حذف هذه التبعيات القابلة للتحليل من النظام." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s يعتمد على التبعيات القابلة للتحليل الأخرى" + +#~ msgid "%s depends on %s" +#~ msgstr "%s يعتمد على %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s يعتمد على:%s" + +#~ msgid "Child of" +#~ msgstr "عنصر فرعي لـ" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "لا يتوفر أي مورد يدعم هذا المتطلب." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "نتيجة للمشكلات الموضحة أعلاه/أدناه، لن يقوم هذا التحديد بحل كافة التبعيات" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "لم يتم استيفاء متطلبات %s" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم إلغاء تثبيته" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "يستوفي %s تبعيات %s، لكن سيتم الاحتفاظ به في النظام لديك" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s يجعل %s قديمًا. لكن يتعذر حذف %s لأنه مقفل." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "تعذر تثبيت %s لأنه متعارض" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "لطلب %s لـ %s عند تحديث %s" + +#~ msgid ", Trigger: " +#~ msgstr "، تشغيل:" + +#~ msgid "package" +#~ msgstr "الحزمة" + +#~ msgid "selection" +#~ msgstr "التحديد" + +#~ msgid "pattern" +#~ msgstr "النمط" + +#~ msgid "product" +#~ msgstr "المنتج" + +#~ msgid "script" +#~ msgstr "البرنامج النصي" + +#~ msgid "message" +#~ msgstr "الرسالة" + +#~ msgid "atom" +#~ msgstr "الذرة" + +#~ msgid "system" +#~ msgstr "النظام" + +#~ msgid "Resolvable" +#~ msgstr "التبعية القابلة للتحليل" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "تعليم محاولة التحديد هذه كغير صالحة." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "تعليم التبعية القابلة للتحليل %s باعتبارها قابلة لإلغاء التثبيت" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "تمت جدولة %s لتثبيته، لكن لا يمكن القيام بذلك بسبب وجود مشكلات في التبعية." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "تعذر تثبيت %s لأنه تم تعليمه بالفعل على أنه مطلوب إلغاء تثبيته" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "تعذر تثبيت %s لأنه لا ينطبق على هذا النظام." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "تعذر تثبيت %s، لأن %s تم تعليمه بالفعل على أنه مطلوب تثبيته" + +#~ msgid "This would invalidate %s." +#~ msgstr "سيؤدي هذا إلى إلغاء صلاحية %s." + +#~ msgid "Updating %s to %s" +#~ msgstr "تحديث %s إلى %s" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "لا يوجد أي موفرين مثبَّتين بدائل لـ %s" + +#~ msgid "for %s" +#~ msgstr "لـ %s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "لا يمكن التحديث إلى %s لتجنب إزالة %s." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s يوفر %s، لكن تمت جدولته لإلغاء تثبيته." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s يوفر %s، لكن تم تثبيت إصدار آخر لـ %s هذا بالفعل." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s يوفر %s، لكنه قابل لإلغاء التثبيت. حاول تثبيته للحصول على مزيد من " +#~ "التفاصيل." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s يوفر %s، لكنه مقفل." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s يوفر %s، لكن تمت جدولته للاحتفاظ به." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s يوفر %s، لكن له هيكل آخر." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "تعذر استيفاء متطلب %s لـ %s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل مثبَّتة أخرى، لذا لن يتم إلغاء الارتباط." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "يتطلب تعارض %s (%s) إزالة %s المطلوب تثبيته" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "تعليم %s باعتباره قابل لإلغاء التثبيت بسبب وجود تعارضات على %s" + +#~ msgid "from %s" +#~ msgstr "من %s" + +#~ msgid "%s depended on %s" +#~ msgstr "%s اعتمد على %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s تم استبداله بـ %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s جزء من %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "موعد الاستحقاق: %1" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s مطلوب بواسطة %s" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s مطلوب بواسطة تبعية قابلة للتحليل أخرى مطلوب تثبيتها، لذا لن يتم إلغاء " +#~ "الارتباط." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "تعذر إنشاء الملف المطلوب لتنفيذ عملية تثبيت التحديث." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "تم تسجيل مصدر واحد على الأقل، تعذرت استعادة المصادر المخزَّنة." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "تعذر تثبيت %s لاستيفاء تبعيات %s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s اعتمد على %s" + +#~ msgid "Reading index files" +#~ msgstr "قراءة ملفات الفهرس" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "فشل ملف repomd.xml الموقَّع في التحقق من التوقيع." + +#~ msgid "Reading product from %s" +#~ msgstr "قراءة المنتج من %s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "قراءة قائمة الملفات من %s" + +#~ msgid "Reading packages from %s" +#~ msgstr "قراءة الحزم من %s" + +#~ msgid "Reading selection from %s" +#~ msgstr "قراءة التحديد من %s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "قراءة النمط من %s" + +#~ msgid "Reading patches index %s" +#~ msgstr "قراءة فهرس التصحيحات %s" + +#~ msgid "Reading patch %s" +#~ msgstr "قراءة التصحيح %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "فشل ملف البرنامج النصي في اختبار المجموع الاختباري." + +#~ msgid "Reading translation: %s" +#~ msgstr "قراءة الترجمة: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "فشل التحقق من سلامة الحزمة %s. هل تريد إعادة محاولة إنزالها، أو إيقاف " +#~ "التثبيت؟" + +#~ msgid " miss checksum." +#~ msgstr "فقد المجموع الاختباري." + +#~ msgid " fails checksum verification." +#~ msgstr "فشل التحقق من المجموع الاختباري." + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "%s anahtarlığındaki %s genel anahtarı %s dosyasında oluşturulamadı" + +#~ msgid "Can't chdir to '/' inside chroot (%s)." +#~ msgstr "Chroot'un içinde '/' chdir yapılamıyor(%s) ." + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "'%s' için indirme (Metalink curl) başlatılamadı." + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "'%s' için indirme(metalink curl) hatası:\n" +#~ "Hata kodu: %s\n" +#~ "Hata raporu: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "%d%% 'de indirme kesildi" + +#~ msgid "Download interrupted by user" +#~ msgstr "İndirme kullanıcı tarafından iptal edildi" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "'%s' için indirme (metalink curl) ayarları düzenlenirken bir hata " +#~ "meydana geldi:" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "%s den %s indirilirken hata meydana geldi" + +#, fuzzy +#~ msgid "Serbia and Montenegro" +#~ msgstr "Seri kablo bağlantısı" + +# clients/inst_sw_single.ycp:742 +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "Yetersiz bağımlılıklar:" + +#, fuzzy +#~ msgid "%s remove failed" +#~ msgstr "rpm başarısız oldu." + +#, fuzzy +#~ msgid "rpm output:" +#~ msgstr "Program çıktısı:\n" + +# clients/online_update_start.ycp:171 +#, fuzzy +#~ msgid "%s install failed" +#~ msgstr "Kurulum işlemi başarısız oldu." + +#, fuzzy +#~ msgid "%s installed ok" +#~ msgstr "&Evet, kur" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "%1 dizini zaten listede." + +#, fuzzy +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "Ignore this conflict of %s" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "Ignore this requirement just here" +#~ msgstr "şu çözülmemiş gereksinimlere sahip:" + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Eksik paketleri kur" + +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "Eksik paketleri kur" + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "install %s" +#~ msgstr "%1 paketini kur" + +# include/security/ui.ycp:774 +#, fuzzy +#~ msgid "unlock %s" +#~ msgstr "Saatler" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "Bu paket kurulu değildir ve kurulmayacaktır." + +# clients/inst_sw_single.ycp:742 +#, fuzzy +#~ msgid "%s has missing dependencies" +#~ msgstr "Yetersiz bağımlılıklar:" + +# clients/inst_sw_single.ycp:742 +#, fuzzy +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "Yetersiz bağımlılıklar:" + +# clients/online_update_load.ycp:923 +#, fuzzy +#~ msgid "No need to install %s" +#~ msgstr "yeniden kurulmalı" + +# clients/inst_sw_single.ycp:742 +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "Yetersiz bağımlılıklar:" + +#, fuzzy +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%1, %2 ile çakışıyor" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "Paket gereksinimlerini listele" + +#, fuzzy +#~ msgid ", Action: " +#~ msgstr "Hareket" + +# clients/online_update_details.ycp:88 clients/online_update_select.ycp:112 +#~ msgid "patch" +#~ msgstr "yama" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#, fuzzy +#~ msgid "Establishing %s" +#~ msgstr "Kurulan disk:" + +# include/partitioning/auto_part_ui.ycp:200 include/partitioning/auto_part_ui.ycp:249 +#, fuzzy +#~ msgid "Installing %s" +#~ msgstr "Kurulan disk:" + +# include/scanner/scanner_start.ycp:138 +#, fuzzy +#~ msgid "Skipping %s: already installed" +#~ msgstr "Önceden kurulu tarayıcılar kontrol ediliyor" + +#, fuzzy +#~ msgid "%s is locked and cannot be uninstalled." +#~ msgstr "Bu paket kurulu değildir ve kurulmayacaktır." + +# include/ui/common_messages.ycp:95 +#, fuzzy +#~ msgid " Error!" +#~ msgstr "Hata" + +#, fuzzy +#~ msgid " Important!" +#~ msgstr "Dışarıdan veri al" + +#, fuzzy +#~ msgid "Unable to parse Url authority" +#~ msgstr "çalışma alanı oluşturulamadı\n" + +#, fuzzy +#~ msgid "Ignore this requirement generally" +#~ msgstr "şu çözülmemiş gereksinimlere sahip:" + +#, fuzzy +#~ msgid "Unable to restore all sources." +#~ msgstr "çalışma alanı oluşturulamadı\n" + +# +# clients/inst_sw_select.ycp:195 +#, fuzzy +#~ msgid "Reading packages file" +#~ msgstr "{0} dosyasını barındıran paket yok" + +#, fuzzy +#~ msgid "Downloading %s" +#~ msgstr "%1 yüklemesinde bir hata oluştu" + +#~ msgid "Ok" +#~ msgstr "Tamam" + +#, fuzzy +#~ msgid "The package file has incorrect MD5 sum" +#~ msgstr "Geri yüklenecek paketler" + +#, fuzzy +#~ msgid "The package has incorrect signature" +#~ msgstr "Geri yüklenecek paketler" + +#, fuzzy +#~ msgid "The package archive has incorrect MD5 sum" +#~ msgstr "Geri yüklenecek paketler" + +#~ msgid "Default" +#~ msgstr "Öntanımlı" + +# include/scanner/scanner_manual.ycp:82 +#, fuzzy +#~ msgid "to be installed (soft)" +#~ msgstr "şu şekilde yüklenecek:" + +# clients/online_update_load.ycp:923 +#, fuzzy +#~ msgid "to be uninstalled" +#~ msgstr "yeniden kurulmalı" diff --git a/po/uk.po b/po/uk.po new file mode 100644 index 0000000..37e2aab --- /dev/null +++ b/po/uk.po @@ -0,0 +1,5698 @@ +# translation of zypp.po to Ukrainian +# Translation of zypp.uk.po to Ukrainian +# Ukrainian message file for YaST2 (@memory@). +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2005 SUSE Linux Products GmbH. +# +# xxx, 2005. +# Ivan Petrouchtchak , 2006, 2007. +# Yuri Chornoivan , 2008. +# Ivan Petrouchtchak , 2008, 2009. +# Andriy Bandura , 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: zypp.uk\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2021-03-11 21:56+0000\n" +"Last-Translator: Lesath <4lesath@gmail.com>\n" +"Language-Team: Ukrainian \n" +"Language: uk\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" +"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" +"X-Generator: Weblate 3.6.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Невідома країна: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Немає коду" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Андорра" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Об'єднані Арабські Емірати" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Афганістан" + +# AG +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Антигуа і Барбуда" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Ангілья" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Албанія" + +# AM +# fuzzy +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Вірменія" + +# AN +# fuzzy +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Нідерландські Антильські острови" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Ангола" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Антарктика" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Аргентина" + +# AS +# fuzzy +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Американське Самоа" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Австрія" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Австралія" + +# CU +# fuzzy +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Аруба" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Аландські острови" + +# AZ +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Азербайджан" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Боснія і Герцеговина" + +# BB +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Барбадос" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Бангладеш" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Бельгія" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Буркіна-Фасо" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Болгарія" + +# BH +# fuzzy +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Бахрейн" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Бурунді" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Бенін" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Бермуди" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Бруней Даруссалам" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Болівія" + +# BR +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Бразилія" + +# BS +# fuzzy +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Багамські острови" + +# BH +# fuzzy +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Бутан" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Острів Буве" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Ботсвана" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Білорусь" + +# BZ +# fuzzy +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Беліз" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Канада" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Кокосові острови" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Конго" + +# CF +# fuzzy +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Центральноафриканська республіка" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Швейцарія" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Кот д'Івуар" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Острови Кука" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Чилі" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Камерун" + +# CN +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Китай" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Колумбія" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Коста-Рика" + +# CU +# fuzzy +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Куба" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Кабо-Верде" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Різдвяні острови" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Кіпр" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Чехія" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Німеччина" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Джибуті" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Данія" + +# DM +# fuzzy +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Домініка" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Домініканська республіка" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Алжир" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Еквадор" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Естонія" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Єгипет" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Західна Сахара" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Еритрея" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Іспанія" + +# ET +# fuzzy +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Ефіопія" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Фінляндія" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Фіджі" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Фолклендські острови (Мальвінські)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Мікронезія (Федеральні Штати)" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Фарерські острови" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "Франція" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Метропольна Франція" + +# GH +# fuzzy +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Габон" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Сполучене Королівство" + +# GD +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Гренада" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Грузія" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Французька Гвіана" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Гернсі" + +# GH +# fuzzy +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Гана" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Гібралтар" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Гренландія" + +# GM +# fuzzy +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Гамбія" + +# GU +# fuzzy +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Гвінея" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Гваделупа" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Екваторіальна Гвінея" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Греція" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Південна Джорджія і Південні Сандвічеві острови" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Гватемала" + +# GU +# fuzzy +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Гуам" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Гвінея-Бісау" + +# GH +# fuzzy +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Гвіана" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Гонконг" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Хердські і Макдональд острови" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Гондурас" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Хорватія" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Гаїті" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Угорщина" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Індонезія" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ірландія" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Ізраїль" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Острів Мен" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Індія" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Британська Територія в Індійському океані" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Ірак" + +# IR +# fuzzy +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Іран" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Ісландія" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Італія" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Джерсі" + +# JM +# fuzzy +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Ямайка" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Йорданія" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Японія" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Кенія" + +# KZ +# fuzzy +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Киргизстан" + +# KH +# fuzzy +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Камбоджа" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Кірибаті" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Комори" + +# KN +# fuzzy +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Сент Кітс і Невіс" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Північна Корея" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Південна Корея" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Кувейт" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Кайманові острови" + +# KZ +# fuzzy +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Казахстан" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Лаоська Народно-Демократична Республіка" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Ліван" + +# LC +# fuzzy +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Санта Люсія" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Ліхтенштейн" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Шрі-Ланка" + +# LR +# fuzzy +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Ліберія" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Лесото" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Литва" + +# LU +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Люксембург" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Латвія" + +# LR +# fuzzy +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Лівія" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Марокко" + +# MO +# fuzzy +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Монако" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Молдова" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Чорногорія" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Сен-Мартен" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Мадагаскар" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Маршаллові острови" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Північна Македонія" + +# ML +# fuzzy +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Малі" + +# MM +# fuzzy +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "М’янма" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Монголія" + +# MO +# fuzzy +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Аоминь" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Північні Марианські острови" + +# MU +# fuzzy +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Мартиніка" + +# MR +# fuzzy +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Маврітанія" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Монтсеррат" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Мальта" + +# MU +# fuzzy +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Маврікій" + +# MV +# fuzzy +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Мальдіви" + +# MW +# fuzzy +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Малаві" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Мексика" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Малайзія" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Мозамбік" + +# GM +# fuzzy +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Намібія" + +# NC +# fuzzy +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Нова Каледонія" + +# NG +# fuzzy +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Нігер" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Острів Норфолк" + +# NG +# fuzzy +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Нігерія" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Нікарагуа" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Нідерланди" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Норвегія" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Непал" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Науру" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Ніуе" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Нова Зеландія" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Оман" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Панама" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Перу" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Французька Полінезія" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Папуа Нова Гвінея" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Філіппіни" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Пакистан" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Польща" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Сен П'єр і Мікелон" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Піткерн" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Пуерто-Ріко" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Палестинська територія" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Португалія" + +# PW +# fuzzy +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Палау" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Парагвай" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Катар" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Реуніон" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Румунія" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Сербія" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Російська Федерація" + +# RW +# fuzzy +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Руанда" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Саудівська Аравія" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Соломонові острови" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Сейшели" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Судан" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Швеція" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Сингапур" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Острів Святої Олени" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Словенія" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Свальбард і Ян Маєн" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Словаччина" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Сьєра Леон" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "Сан Марино" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Сенегал" + +# SO +# fuzzy +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Сомалі" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Суринам" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Сан Томе і Принсипі" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "Ель Сальвадор" + +# SY +# fuzzy +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Сирія" + +# SZ +# fuzzy +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Есватіні" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Острови Теркс і Кайкос" + +# TD +# fuzzy +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Чад" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Французькі Південні Території" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Того" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Таїланд" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Таджикистан" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Токелау" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Туркменістан" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Туніс" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Тонга" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Східний Тімор" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Туреччина" + +# TT +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Республіка Тринідад та Тобаго" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Тувалу" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Тайвань" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Танзанія" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Україна" + +# UG +# fuzzy +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Уганда" + +# UM +# fuzzy +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Віддалені острови США" + +# US +# fuzzy +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "США" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Уругвай" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Узбекистан" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Святий Престол (Ватикан, місто-держава)" + +# VC +# fuzzy +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Сент Вікент і Гренадіни" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Венесуела" + +# VI +# fuzzy +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Віргінські острови (Британія)" + +# VI +# fuzzy +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Віргінські острови, США" + +# VN +# fuzzy +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "В'єтнам" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Вануату" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Валліс і Футунські острови" + +# KH +# fuzzy +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Самоа" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Ємен" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Майотта" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Південна Африка" + +# ZM +# fuzzy +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Замбія" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Зімбабве" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Ознаки" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "Вимоги" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Вимагає" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Конфліктує" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "Робить застарілим" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Рекомендує" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Пропонує" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Покращує" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Доповнює" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Спроба імпорту неіснуючого ключа %s у сховище ключів %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "Не вдалося імпортувати ключ." + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Не вдалось вилучити ключ." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Файл підпису «%s» не знайдено" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Невідома мова: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Афар" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Абхазька" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Ахінська" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Аколі" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Адангме" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Адиґхе" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Афро-азіатські (інші)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Афрігілі" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Африкаанська" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Аіну" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Акан" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Акадійська" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Албанська" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Алеутська" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Алгонкінські мови" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Південноалтайська" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Амхарська" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Англійська, стара (450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Мови апачі" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Арабська" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Арамейська" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Арагонська" + +# AM +# fuzzy +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Вірменська" + +# AM +# fuzzy +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Арауканська" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Арапахо" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Штучні (інші)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Аравацька" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Ассамська" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Астурійська" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Атапаські мови" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Австралійські мови" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Аварська" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Авестійська" + +# SZ +# fuzzy +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Авадхі" + +# MM +# fuzzy +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Аймарська" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Азербайджанська" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Банда" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Бамілекські мови" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Башкирська" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Балучі" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Бамбара" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Балійська" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Баскська" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Баса" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Балтійські (інші)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Бежа" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Білоруська" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Бемба" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Бенгальська" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Берберські (інші)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Бходжпурі" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Біхарі" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Бікол" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Біні" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Біслама" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Сіксіка" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Банту (інші)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Боснійська" + +# BR +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Брай" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Бретонська" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Батак (Індонезія)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Бурятська" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Бугійська" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Болгарська" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Бірманська" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Блін" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Каддо" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Індіанські центрально-американські (інші)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Карибські мови" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Каталанська" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Кавказькі (інші)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Кебуанська" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Кельтські (інші)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Чаморо" + +# CN +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Чибча" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Чеченська" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Чагатай" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Китайська" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Чуукійська" + +# ML +# fuzzy +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Марі" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Чинукський жаргон" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Чокто" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Чіпев’ян" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Черокі" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Церковнослов'янська" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Чуваська" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Шайєнська" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Чамські мови" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Коптська" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Корнійська" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Корсиканська" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Креольські і піджинські, англійські (інші)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Креольські і піджинські, французькі (інші)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Креольські і піджинські, португальські (інші)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Крі" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Кримськотатарська" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Креольські і піджинські (інші)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Кашубська" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Кушитські (інші)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Чеська" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Дакота" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Данська" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Даргва" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Даяк" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Делавар" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Атапаська" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Догрібська" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Дінка" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Дайвегі" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Догрі" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Дравідські (інші)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Нижня лужицька" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Дуала" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Голландська, середня (1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Голландська" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Діула" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Дзонгка" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Ефік" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Єгипетська (древня)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Екаюк" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Еламська" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Англійська" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Англійська, середньовічна (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Есперанто" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Естонська" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Еве" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Евондо" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Фанг" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Фарерська" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Фанті" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Фіджійська" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Філіппінська" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Фінська" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Фіно-угорські (інші)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Фон" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Французька" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Французька, середньовічна (1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Французька, давня (842 - 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Фризька" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Фула" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Фріулійська" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Га" + +# GH +# fuzzy +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Гайо" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Ґбая" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Германські (інші)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Грузинська" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Німецька" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Ґіз" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Гілбертійська" + +# ML +# fuzzy +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Гаельська" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Ірландська" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Галісійська" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Манкс" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Німецька, середньо-висока (1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Німецька, стара висока (750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Ґонді" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Ґоронтало" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Готська" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Гребо" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Грецька, стародавня (до 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Грецька, сучасна (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Гуарані" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Гуджараті" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Ґвіч’ін" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Хайда" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Гаїтянська" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Хауса" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Гавайська" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Єврейська" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Гереро" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Хілігайнонська" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Гімачалі" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Хінді" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Хетська" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Хмонг" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Хірі Моту" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Верхня лужицька" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Угорська" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Гупа" + +# IR +# fuzzy +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Ібан" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Ігбо" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Ісландська" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ідо" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Сичуаньська Ї" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Іжо" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Інуктитут" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Інтерлінгва" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Ілоко" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Інтерлінгва (Інтернаціональна допоміжна асоціація мови)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Індійські (інші)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Індонезійська" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Індоєвропейські (інші)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Інгуш" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Інупіак" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Іранські (інші)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Ірокезькі мови" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Італійська" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Японська" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Ложбан" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Японська" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Юдейсько-перська" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Юдейсько-арабська" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Каракалпацька" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Кабільська" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Качин" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Калаалісут" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Камба" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Каннадська" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Карен" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Кашмірська" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Канурі" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Каві" + +# KZ +# fuzzy +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Казахська" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Кабардинська" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Хасі" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Койсанські (інші)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Кхмерська" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Хотанська" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Кікуйю" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Кіньяруанда" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Киргизька" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Кімбунду" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Конкані" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Комі" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Конго" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Корейська" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Косраенська" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Кпеле" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Карачаєво-балкарська" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Кру" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Курух" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Куаньяма" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Кумик" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Курдська" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Кутенай" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ладіно" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Лахнда" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Ламба" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Лаоська" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Латинська" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Латвійська" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Лезгінська" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Лімбурганська" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Лінгала" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Литовська" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Монгольська" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Лозі" + +# LU +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Люксембурзька" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Луба-лулуа" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Луба-катанга" + +# GH +# fuzzy +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Ґанда" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Луїсено" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Лунда" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Луо (Кенія і Танзанія)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Лушаї" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Македонська" + +# MV +# fuzzy +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Мадурі" + +# MU +# fuzzy +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Маґахі" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Маршальська" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Маїтхілі" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Макасар" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Малаялам" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Мандінго" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Маорі" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Австронезійські (інші)" + +# MU +# fuzzy +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Маратхі" + +# MW +# fuzzy +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Масаї" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Малайська" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Мокша" + +# MM +# fuzzy +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Мандар" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Менде" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Ірландська, середньовічна (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Мікмак" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Мінангкабау" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Інші мови" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Мон-кхмерські (інші)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Малагасійська" + +# MV +# fuzzy +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Мальтійська" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Манчу" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Маніпурі" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Мови манобо" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Могавк" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Молдовська" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Монгольська" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Моссі" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Декілька мов" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Мови мунда" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Крік" + +# FM +# fuzzy +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Мірандська" + +# MU +# fuzzy +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Марварі" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Мови Майя" + +# SY +# fuzzy +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Ерзія" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Нагуатл" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Індіанська північноамериканська" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Неаполітанська" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Навахо" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ндебеле, південна" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ндебеле, північна" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ндонга" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Нижня німецька" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Непальська" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Непал Вхаза" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Ніас" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Нігеро-кордофанські (інші)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Ніу" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Норвезька (лансмол)" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Норвезька (букмол)" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Ногайська" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Норвезька, давня" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Норвезька" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Північне Сото" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Нубійські мови" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Класичне неварі" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Чичева" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Ньямвезі" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Ньянколе" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Ніоро" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Нзіма" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Провансальська (після 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Ожібва" + +# SY +# fuzzy +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Орійська" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Оромо" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Осаге" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Осетинська" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Турецька, оттоманська (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Отомійські мови" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Папуаські (інші)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Пангасійська" + +# ML +# fuzzy +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Пахлаві" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Пампанга" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Панджабі" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Папіяменто" + +# PW +# fuzzy +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Палау" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Перська, давня (600-400 до н.е.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Перська" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Філіппінські (інші)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Фінікійська" + +# ML +# fuzzy +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Палі" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Польська" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Понпейська" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Португальська" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Пракритські мови" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Провансальська, давня (до 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Пушту" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Кечуа" + +# KZ +# fuzzy +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Раджастані" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Рапануї" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Раротонгська" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Романські (інші)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Ретороманська" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Циганська" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Румунська" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Рунді" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Російська" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Сандаве" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Санго" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Якутська" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Індіанські південноамериканські (інші)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Салішанські мови" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Самарійська арамейська" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Санскрит" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Сасак" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Санталі" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Сербська" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Сицилійська" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Шотландська" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Хорватська" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Селкуп" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Семітські (інші)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Ірландська, давня (до 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Знакові мови" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Шан" + +# KH +# fuzzy +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Сідамо" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Сингальська" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Сіуанські мови" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Сино-тибетські (інші)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Слов'янські (інші)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Словацька" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Словенська" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Південна Самі" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Північна Самі" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Мови Самі (інші)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Луле самі" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Інарі самі" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Самоанська" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Сколт самі" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Шона" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Синдхі" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Сонінке" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Согдійська" + +# SO +# fuzzy +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Сомалійська" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Сонгай" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Сото, південна" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Іспанська" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Сардинська" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Серер" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Ніло-сахарські (інші)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Сваті" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Сукума" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Сунданська" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Сусу" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Шумерська" + +# SZ +# fuzzy +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Суахілі" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Шведська" + +# SY +# fuzzy +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Сирійська" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Таїтянська" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Тайські (інші)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Тамільська" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Татарська" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Телугу" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Тімне" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Терено" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Тетум" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Таджицька" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Тагалог" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Таїландська" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Тибетська" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Тигре" + +# NG +# fuzzy +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Тигринья" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Тів" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Клінгонська" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Тлінгіт" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Тамашек" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Тонга (Ньяса)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Тонга (острови Тонга)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Ток пісін" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Тсимшіан" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Тсвана" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Тсонга" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Туркменська" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Тумбука" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Мови Тупі" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Турецька" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Алтайські (інші)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Тві" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Тувинська" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Удмуртська" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Угарітська" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Уйгурська" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Українська" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Умбунду" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Невизначено" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Урду" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Узбецька" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Ваі" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Венда" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "В'єтнамська" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Волапюк" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Вотік" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Вакашанські мови" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Валамо" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Варай" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Вашо" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Валлійська" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Лужицькі мови" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Валлонська" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Волоф" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Калмицька" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Хоза" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Йао" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Япізька" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Ідиш" + +# CU +# fuzzy +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Йоруба" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Юпікські мови" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Сапотекські мови" + +# GD +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Зенага" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Жуанг" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Занде" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Зулуська" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Зуні" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Буде виконано такі дії:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "(не минає)" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "минув: %1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "минає: %1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(не минає)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(МИНУЛО)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(минуло протягом 24 годин)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(закінчується через %d день)" +msgstr[1] "(закінчується через %d дні)" +msgstr[2] "(закінчується через %d днів)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "невідомий" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "не підтримується" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Рівень 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Рівень 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Рівень 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "Потрібний додатковий контракт клієнта" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "недійсний" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Не вказано рівень підтримки" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Постачальник не надає підтримки." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Визначення проблеми, тобто технічна підтримка, при якій надається інформація " +"про сумісність, допомога при встановленні, підтримка для використання, та " +"вирішення простих проблем. Підтримка 1-го рівня не займається виправленням " +"помилками дефектів продуктів." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"Виокремлення проблеми, тобто технічна підтримка, при якій дублікуються " +"проблеми клієнтів, виокремлюється проблемна ділянка і надається вирішення " +"проблем, які не було виправлено 1-ми рівнем підтримки." + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"Вирішення проблем, тобто технічна підтримка, призначена для вирішення " +"складних проблем, до яких залучають інженерний персонал для вирішення " +"дефектів в продуктах, що їх було знайдено підтримкою 2-го рівня." + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "Для отримання підтримки потрібний додатковий контракт клієнта." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Невідомий параметр підтримки. Немає опису" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"Керування системою заблоковано програмою з pid %d (%s).\n" +"Закрийте цю програму перш ніж спробувати знову." + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Невідомий режим збігу «%s»" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Невідомий режим збігу «%s» для шаблона «%s»" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Некоректний формальний вираз «%s»: regcomp повернула %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Недійсний формальний вираз «%s»" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "Потрібна автентифікація для «%s»" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Відвідайте Центр клієнтів SUSE, щоб перевірити, чи ваша реєстрація дійсна та " +"чи не закінчився термін дії." + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" +"Відвідайте центр покупця Novel для перевірки терміну дії вашої реєстрації." + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" +"Створюємо точку монтування: неможливо знайти директорію з можливістю запису " +"для створення точки монтування" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "Встановіть спершу пакунок 'lsof'." + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Неможливо створити директорію кешу метаданих." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Помилка спроби читання з «%s»" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Неможливо створити %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "У вказаній адресі URL не знайдено чинних метаданих" +msgstr[1] "У вказаних адресах URL не знайдено чинних метаданих" +msgstr[2] "У вказаних адресах URL не знайдено чинних метаданих" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Не вдалось скешувати сховище(%d)." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Створення кешу сховища «%s»" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Не вдалося створити кеш %s - немає прав на запис." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Необроблений тип сховища" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Додавання сховища «%s»" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Не чинна назва файла сховища «%s»" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Неможливо відкрити файл «%s» для запису." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Невідома помилка читання з «%s»" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "Неможливо прочитати директорію сховища '%1%': Доступ заборонено" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Не вдалось прочитати директорію «%s»" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "Неможливо прочитати файл сховища '%1%': Доступ заборонений" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Вилучення сховища «%s»" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Неможливо визначити, де знаходиться сховище." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Неможливо вилучити «%s»" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Неможливо визначити, де знаходиться служба." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "Невідома служба '%1%': видалення сховища служби '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "Псевдонім сховища не може починатися з точки." + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "Псевдонім служби не може починатися з точки." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +# continue button label +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Продовжити?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "Сховище %1% не визначає додаткові мережеві адреси для «gpgkey=»." + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "Пошук ID ключа для gpg %1% у сховищі %2%." + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "Пошук ID ключа для gpg %1% у кеші %2%." + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "Немає потрібного атрибута «%s»." + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Потрібний один або двоє атрибутів «%s» та «'%s»." + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "Невдала перевірка підпису" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Пакунок %s, здається, пошкоджено під час перенесення. Повторити спробу?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "Не вдалося надати пакунок %s. Повторити спробу?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "перевірка applydeltarpm зазнала невдачі." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "застосування дельти rpm зазнало невдачі." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "Модуль служби не підтримує зміну атрибута." + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Неможливо надати файл «%s» зі сховища «%s»" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "В сховищі немає url." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом пакунку\n" +"%3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом пакунку\n" +"%3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом пакунку\n" +"%3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом пакунку\n" +"%3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом\n" +"%3%\n" +" пакунку\n" +"%4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом\n" +"%3%\n" +" пакунку\n" +"%4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом\n" +"%3%\n" +"з пакунку\n" +"%4%" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"Файл %1%\n" +"з пакунку\n" +"%2%\n" +"конфліктує з файлом\n" +"%3%\n" +"з пакунку\n" +"%4%" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Неможливо створити sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "зламати %s, ігноруючи деякі залежності" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "взагалі нехтувати деякими залежностями" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" +"встановлений %1% не належить до оновлюваного сховища та мусить бути замінений" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "%1% який було встановлено не належить до оновлюваного сховища" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "встановлений %1% має неповноцінну архітектуру" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "%1% який було встановлено має неповноцінну архітектуру" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "проблема з встановленим %1%" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "конфлікт запитів" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "якась проблема залежностей" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "ніхто не надає запитуваний «%1%»" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "Ви ввімкнули всі необхідні сховища?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "запитуваний пакунок %1% не існує" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "непідтримуваний запит" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "вилучені залежності: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"залежності без можливості встановлення: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "залежності без можливості встановлення: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Цей запит пошкодить вашу систему!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "ігнорувати попередження про пошкодження системи" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "встановити %1% хоч він і був відкладений" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "дозволити встановити PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "встановити %1% хоч він і був у чорному списку" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Встановлення перервано відповідно до вказівки." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " виконано" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " виконання зазнало невдачі" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s вже виконаний як %s)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " виконання пропущено під час переривання" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Помилка відсилання сповіщення про оновлення." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Нове повідомлення про оновлення" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Помилка RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "Не вдалося імпортувати відкритий ключ %1%" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Не вдалося вилучити відкрити ключ %1%" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Змінено конфігураційні файли для %s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm збережено %s як %s, але було неможливо виявити різницю" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm збережено %s як %s.\n" +"Ось перші 25 рядків розбіжностей:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm створила %s як %s, але було неможливо виявити різницю" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm створили %s як %s.\n" +"Ось перші 25 рядків розбіжностей:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Додатковий вивід rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "створено резервну копію %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "З підписом усе гаразд" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "Невідомий тип підпису" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "Підпис не перевіряється" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "З підписом усе гаразд, але ключ - ненадійний" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "Публічний ключ підписів - недоступний" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "Файл не існує чи підпис не можна перевірити" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "Файл не підписаний" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Сумнівний тип «%s» для %u байтів контрольної суми «%s»" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Не вдалося відкрити pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Неможливо відкрити канал (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Недійсний рядок запиту URL LDAP" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Недійсний параметр запиту «%s» URL LDAP" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Не вдається клонувати об'єкт URL" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Не чинне порожнє посилання до об'єкта URL" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Неможливо розібрати компоненти URL" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Історія:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Схема Url не дозволяє %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Недійсний %s компонент «%s»" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Недійсний компонент %s" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Розбір рядка запиту не підтримується для цього URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Схема URL - це потрібний компонент" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Недійсна схема URL «%s»" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Схема URL не дозволяє імені користувача" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Схема URL не дозволяє пароля" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Схема URL потребує компонент вузла" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Схема URL не дозволяє компонент вузла" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Недійсний компонент вузла «%s»" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Схема URL не дозволяє порт" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Недійсний компонент порту «%s»" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Схема URL потребує назву шляху" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Відносний шлях не дозволяється при існуванні повноваження" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Закодований рядок містить нульовий байт" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Недійсний символ розділення масиву параметрів" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Недійсний символ розділення карти параметрів" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Недійсний символ сполучення масиву параметрів" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Команда завершила роботу зі станом %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Команду було вбито за сигналом %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Команда завершила роботу з невідомою помилкою." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Не вдалося створити chroot для «%s» (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Неможливо змінити директорію на «%s» (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Неможливо зробити chdir «%s» всередині chroot «%s» (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Не вдалося виконати «%s» (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Не вдалося відгалузити (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Не вдалося змонтувати %s у %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Не вдалося відмонтувати %s" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Некоректна назва файла: %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Носій не було відкрито під час спроби виконання дії «%s»." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Файл «%s» не знайдено на носії «%s»" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Неможливо записати у файл «%s»." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Носій не з’єднано" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Некоректна точка з’єднання носія" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "Започаткування завантаження (curl) зазнало невдачі для «%s»" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Системне виключення «%s» на носії «%s»." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Шлях «%s» на носії «%s» не є файлом." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Шлях «%s» на носії «%s» не є директорією." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "Помилковий URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Порожня назва вузла у URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Порожня файлова система за URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Порожнє місце призначення за URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Непідтримувана схема URI у «%s»." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Операція не підтримується носієм" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Помилка завантаження (curl) для «%s»:\n" +"Код помилки: %s\n" +"Повідомлення про помилку: %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Під час встановлення параметрів завантаження (curl) для «%s» сталася помилка:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "Пристрій носія «%s» не містить бажаного носія" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Носій «%s» використовується іншою копією програми" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Не вдається виштовхнути жодного носія" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Не вдається виштовхнути носія «%s»" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Дозвіл на доступ до «%s» заборонено." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "Перевищено час очікування при спробі доступу до «%s»." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "Завантажені дані перевищили очікуваний розмір файлу «%s» у «%s»." + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Адреса «%s» тимчасово недоступна." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" Проблема з сертифікатом SSL, перевірте чи все гаразд з сертифікатом CA для " +"«%s»." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Метод автентифікації HTTP «%s», який не підтримується" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"Помилка (curl) завантаження «%s»:\n" +"Код помилки: %s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"Помилка (curl) завантаження «%s»:\n" +"Не вдається отримати відповідь HTTP\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Так" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Ні" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "Примітка:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "Увага:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "Помилка:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "завершено" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "увага" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "помилка" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "Попередження: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "Отримання:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "запуск" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "не знайдено" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "Для цього запрошення немає довідки." + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "для цього параметра немає довідки" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "показати усі параметри" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "так" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "ні" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "Виконання сценарію %%posttrans '%1%'" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "Виконання сценаріїв %posttrans" + +#~ msgid "Package is not signed!" +#~ msgstr "Пакунок не підписаний!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s не належить до сховища distupgrade (оновлення дистрибутиву)" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s має слабшу архітектуру" + +#~ msgid "problem with installed package %s" +#~ msgstr "проблема з встановленим пакунком %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "жоден з пакунків не надає потрібного %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Чи ви увімкнули всі запитані сховища?" + +#~ msgid "package %s does not exist" +#~ msgstr "пакунок %s не існує" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s надано системою і його неможливо прибрати" + +#~ msgid "%s is not installable" +#~ msgstr "%s не можливо встановити" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "жоден з пакунків не надає %s, потрібного %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "неможливо встановити одночасно %s і %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s конфліктує з %s, що надається %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s робить застарілим %s, що надається %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "встановлений пакунок %s робить застарілим %s, який надається %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "Розв’язок %s конфліктує з %s, що у ньому міститься" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s потребує %s, але цю залежність неможливо вдовольнити" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "усунути блокування, щоб дозволити вилучення %s" + +#~ msgid "do not install %s" +#~ msgstr "не встановлювати %s" + +#~ msgid "keep %s" +#~ msgstr "залишити %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "усунути блокування, щоб дозволити встановлення %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "не питати про встановлення розв’язувача, що надає %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "не питати про вилучення всіх розв’язувачів, що надаються %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "не встановлювати ранішу версію %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "Залишити %s, незважаючи на слабшу архітектуру" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "Встановити %s, незважаючи на те, що це змінить архітектуру" + +#~ msgid "keep obsolete %s" +#~ msgstr "Залишити застарілі %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "Встановити %s з невключеного сховища" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "повернення замість %s %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "зміна архітектури з %s на %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "встановити %s (зі зміною виробника)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "заміна %s на %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "вилучення %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Не вдалося відкрити файл замка: %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Цю дію вже запущено іншою програмою." + +#~ msgid "Hal Exception" +#~ msgstr "Виняток Hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "Вибачте, цю версію libzypp було складено без підтримки HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext не приєднано" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive не започатковано" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume не започатковано" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Неможливо створити з'єднання з dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new: неможливо створити контекст libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: неможливо встановити з'єднання з dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Неможливо започаткувати контекст HAL context -- не запущено hald?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Не привід CD-ROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Неможливо започаткувати атрибути mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Неможливо встановити рекурсивний атрибут mutex" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Неможливо започаткувати рекурсивний mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Неможливо отримати блокування mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Неможливо відпустити блокування mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "Не вдалося імпортувати відкритий ключ з файла %s: %s" + +# ############################################################################### +# Old yast2-agents.po +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Не вдалося вилучити відкрити ключ %s: %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Неможливо знайти наявний пристрій для монтування штампа файла з «%s»" + +#~ msgid "do not keep %s installed" +#~ msgstr "не залишати встановленим %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Не вдалося створити відкритий ключ %s зі списку ключів %s до файл %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "" +#~ "Започаткування завантаження (Metalink curl) зазнало невдачі для «%s»" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Помилка завантаження (metalink curl) для «%s»:\n" +#~ "Код помилки: %s\n" +#~ "Повідомлення про помилку: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "Звантаження перервано на %d%%" + +#, fuzzy +#~ msgid "Download interrupted by user" +#~ msgstr "Звантаження перервано на %d%%" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Під час встановлення параметрів завантаження (metalink curl) для «%s» " +#~ "сталася помилка:" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "Не вдалося звантажити %s з %s" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Сербія і Чорногорія" diff --git a/po/vi.po b/po/vi.po new file mode 100644 index 0000000..995e369 --- /dev/null +++ b/po/vi.po @@ -0,0 +1,5233 @@ +# Vietnamese translation for YaST2 (@memory@). +# Copyright © 2006 SUSE Linux Products GmbH. +# Copyright © 2005, 2006 Gnome i18n Project for Vietnamese. +# Phan Vĩnh Thịnh , 2006. +# Clytie Siddall , 2005, 2006. +# +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2016-08-25 08:06+0000\n" +"Last-Translator: Hoàng Phạm \n" +"Language-Team: Vietnamese \n" +"Language: vi\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: Weblate 2.6\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Cần" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Xung đột" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Failed to parse: %s." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Lỗi khi đọc từ '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Không thể tạo %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Đang thêm kho '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Không thể mở tập tin '%s' để ghi." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Đang xoá kho '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Không thể xác định nơi chứa kho phần mềm." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Không thể xoá '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Đã huỷ cài đặt theo yêu cầu." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Thông báo cập nhật mới" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "Lỗi RPM: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Lệnh thực hiện khi kết nối" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Failed to parse: %s." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Couldn't open file: %s." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Couldn't open file: %s." + +#, fuzzy +#~ msgid "HalContext not connected" +#~ msgstr "chưa kết nối" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Không phải ổ đĩa CDROM" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Failed to parse: %s." + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Couldn't open file: %s." diff --git a/po/wa.po b/po/wa.po new file mode 100644 index 0000000..a358dd6 --- /dev/null +++ b/po/wa.po @@ -0,0 +1,5724 @@ +# Translation into the walloon language. +# Copyright (C) 2007 SUSE Linux Products GmbH. +# +# Pablo Saratxaga , 2001, 2004. +# Jean Cayron , 2007, 2010, 2011, 2012. +msgid "" +msgstr "" +"Project-Id-Version: lcn memory\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2012-08-24 14:42+0200\n" +"Last-Translator: Jean Cayron \n" +"Language-Team: Walloon \n" +"Language: wa\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.4\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Payis nén cnoxhou : " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Pont d' côde" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andore" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Emirats Arabes Unis" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afganistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua eyet Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguila" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albaneye" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Årmeneye" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Antiyes neyerlandesses" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antartike" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Årdjintene" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "Samowa amerikinne" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Otriche" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Ostraleye" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Arouba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Iyes Aland" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaydjan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosneye" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Bårbades" + +# +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Beljike" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Bourkina Fasso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgåreye" + +# +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bareyn" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Bouroundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermudes" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Boliveye" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Braezi" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Boutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Iye Bouvet" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Boswana" + +# +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belaruss" + +# +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Iyes Cocos (Keeling)" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo-Brazza" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Cintrafrike" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Swisse" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Coisse d' Ivwere" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Iyes Cook" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Tchili" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Camrone" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "Chine" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombeye" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cap Vert" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Iye Christmas" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Chipe" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Tchekeye" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Almagne" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Daenmåtche" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominike" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Republike Dominikinne" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Aldjereye" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecwåteur" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estoneye" + +# +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Edjipe" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Sara Coûtchantrece" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrêye" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Espagne" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Etiopeye" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finlande" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fidji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Iyes Malouwines (Falkland)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Estats Federé d' Microneseye" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Iyes Faeroyé" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "France" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "France Metropolitinne" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "Grande-Burtaegne" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenåde" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Djeyordjeye" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "Guyane francesse" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "Guernsey" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Gana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Djibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Groenlande" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambeye" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinêye" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Gwadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Guinêye Ecwåtoriåle" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Grece" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "Djeyordjeye do sud eyet Iyes Sandwich do sud" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Gwatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Gwam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinêye-Bissaw" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Iyes Heard eyet Iyes MacDonald" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Crowåceye" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Hayiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hongreye" + +# +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonezeye" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Irlande" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israyel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "Iye di Man" + +# +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "Inde" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "Teritweres britanikes di l' Oceyan Indyin" + +# +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Irak" + +# +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Izlande" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Itåleye" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "Djerzey" + +# +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Djamayike" + +# +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Djordaneye" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Djapon" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenia" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kirguiztan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodje" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comores" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Sint Kitts et Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "Corêye (bijhrece)" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "Corêye (nonnrece)" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuweyt" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Iyes Cayman" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazaxhtan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Republike Democratike då Peupe Lawo (Lawos)" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Liban" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Sinte Luceye" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Lîchtensteyn" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lessoto" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Litwaneye" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Lussimbork" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Letoneye" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libeye" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Marok" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "Montenegro" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "Sint Martin" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Iyes Marshall" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedoneye" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Birmaneye" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongoleye" + +# +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Iyes Marianes bijhreces" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinike" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Moritanreye" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Male" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Iye Môrice" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldives" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mecsike" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaizeye" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambike" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibeye" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "Nouve Caledoneye" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Nidjer" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Iye Norfolk" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nidjeria" + +# +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragwa" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Bas Payis" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norvedje" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nawouryin" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niuwé" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "Nouve Zelande" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +# +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Perou" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "Polinezeye francesse" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papouwazeye Nouve Guinêye" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Filipenes" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Pologne" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Sint Pire et Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Porto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestene" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +# +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palawou" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paragway" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Katar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reyunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Roumaneye" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "Serbeye" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Rûsseye" + +# +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Arabeye Sawoudite" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Iyes Solomon" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seycheles" + +# +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Soudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Suwede" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapour" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Sinte Helene" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Esloveneye" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Iyes Svalbard eyet Jan Mayen" + +# +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Eslovakeye" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Siera Leyone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "Sint Marin" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegål" + +# +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somaleye" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "São Tomé et Prince" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Sireye" + +# +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Suwazilande" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Iyes Turks eyet Caicos" + +# +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Tchad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "Payis francès nonnrece" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Taylande" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tadjikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turcmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunizeye" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "Levant Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkeye" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinité et Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "Touvalou" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzaneye" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Oucrinne" + +# +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Ouganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "Iyes mineures des Estats Unis" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "Estats Unis" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Ourougway" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Ouzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Vatican" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Sint Vincint et les Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezwela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "Iyes Viedjes Britanikes" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Iyes Viedjes etazunyinnes" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanouatou" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis et Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samowa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayote" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "Nonne Afrike" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambeye" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwè" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "Dene" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "Dimande" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "Afrontmints" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "wårder l' forpassé %s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "Ricmande" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "Propoze" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "Amidrêye" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "Rawetes" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, fuzzy, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "Dj' a sayî d' abaguer l' clé %s nén egzistante e l' anea d' clés %s" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "L' abagaedje del clé publike %1% a fwait berwete" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "Li disfaçaedje del clé a fwait berwete." + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Sinateure di fitchî %s nén trovêye" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Lingaedje nén cnoxhou : " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Abxhaze" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Achinwès" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Afro-Aziyatike (ôtes)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "Afrikaans" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Aynou" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Acanyin" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Acadyin" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Albanès" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Alewoute" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Lingaedjes algonkyins" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Altay nonnrece" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Amarike" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "Inglès, Vî inglès (450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Lingaedjes apaches" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Arabe" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Aramayike" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Aragonès" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Årmenyin" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Arawoucan" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Constrût (ôtes)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Assamès" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Asturyin" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Lingaedjes atapascans" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Lingaedjes ostralyins" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Avarike" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Awadi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Azeri" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "Banda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Lingaedjes bamilekes" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "Baloutchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "Balinès" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Basse" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "Bassa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Baltike (ôtes)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "Bedja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "Bielorûsse" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Berbere (ôtes)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Bantou (ôtes)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "Bosnyin" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "Burton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "Batak (Indonezeye)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "Bouriate" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "Budjinès" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "Bulgåre" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "Birman" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Amerindyin di l' Amerike cintråle (ôtes)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "Carayibe" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "Catalan" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Cocåzyin (ôtes)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "Cebwano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Celtike (ôtes)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "Tchamoro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "Tchibtcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "Tchetchene" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "Tchagatay" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "Chinwès" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "Tchouwoukès" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Djårgon Tchinouk" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "Tchoctåw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "Tchipewa" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "Tcherokî" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "Eslavonike d' eglijhe" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "Tchouvache" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "Tcheyinne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Lingaedjes xhamitikes" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "Coptike" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "Cornike" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "Corse" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Creyoles et pidjines, båzé so l' inglès (ôtes)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Creyoles et pidjines, båzé sol francès (ôtes)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Creyoles et pidjines, båzé sol portuguès (ôtes)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "Crî" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Tatar crimeyin" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Creyoles et pidjines (ôtes)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "Kachubian" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Couchitike (ôtes)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "Tcheke" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "Daenwès" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Dravidyin (ôtes)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "Bas serbe" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "Douwala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "Neyerlandès, Moyén neyerlandès (åtoû di 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "Neyerlandès" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "Dioula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "Boutanès" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "Edjipcyin (ancyin)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Ekadjouk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "Inglès" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "Inglès, Moyén inglès (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Estonyin" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Ewè" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "Faeroyès" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "Fidjyin" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "Filipenes" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "Finwès" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Fino-ougryin (ôtes)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "Francès" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "Francès, Moyén francès (åtoû d' 1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "Francès, Vî francès (842-1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "Frizon" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "Friyoulan" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "Tîxhon (ôtes)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "Djeyordjyin" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "Almand" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "Gehez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "Djilbertyin" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "Gayelic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Irlandès" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "Galicyin" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "Gayel di l' iye di Man" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "Almand, Moyén hôt almand (åtoû di 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "Almand, Vî hôt almand (åtoû di 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "Gotike" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "Grek, Ancyin grek (disk' a 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "Grek, Modiene (dispoy 1453)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "Gwarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "Goudjarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "Hayida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "Hayicyin" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "Hawssa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "Hawayin" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "Ebreu" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "Himatchali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "Hitite" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "Hôt serbe" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "Hongrwès" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Izlandès" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "Yi sitchouwanès" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Interlingua (Soce do lingaedje ogziliaire internacionå)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Indyin (ôtes)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Indonezyin" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Indo-uropeyin (ôtes)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Ingouche" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Inyupiak" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Iranyin (ôtes)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Lingaedjes irocwès" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "Itålyin" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "Djavanès" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "Djaponès" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "Djudeyo-farsi" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Djudeyo-arabe" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "Kabile" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "Katchin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "Kazaxh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "Kabardyin" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "Koysan (ôtes)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "Xhmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "Khotanès" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "Kikouyou" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "Kirguize" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "Kimboundou" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "Kicongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "Coreyin" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "Kosrayin" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "Kpellè" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "Karatchay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "Krou" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "Kuruxh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "Kwanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "Kurde" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "Kutenay" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "Lawocyin" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "Latén" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "Letonyin" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "Lezguyin" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "Limbordjwès" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "Litwanyin" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "Lussimbordjès" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "Louba-Loulouwa" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "Louba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "Louganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "Lounda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "Louwo (Kenia et Tanzaneye)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "Louchay" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "Macedonyin" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "Madurès" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "Marshalès" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "Makazar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "Mawori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Ostronezyin (ôtes)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "Marati" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "Massay" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "Malay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Irlandès, Moyén irlandès (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "Micmak" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Ôtes lingaedjes" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "Mon-Xhmer (ôtes)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "Malgache" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "Malès" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "Mantchou" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Lingaedjes manobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "Mohåwk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "Moldåve" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "Mongol" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Multipes lingaedjes" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Lingaedjes mounda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "Crîk" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "Mirandès" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Lingaedjes maya" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "Amerindyins d' Amerike bijhrece (ôtes)" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "Napolitin" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navaxho" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "Ndebele (Nonnrece)" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "Ndebele (Bijhrece)" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "Ndonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "Bas almand" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "Nepalès" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "Bhasa nepalès" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "Niger-Kordofanyin (ôtes)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "Niuweyin" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "Norvedjyin Ninorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "Norvedjyin Bokmål" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "Nogay" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "Vî norvedjyin" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "Norvedjyin" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "Soto bijhrece" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Lingaedjes noubyins" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "Newari classike" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "Tchitchewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "Nyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "Nzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Occitan (après 1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Odjibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Ozaedje" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Ossetyin" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "Turk otoman (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Lingaedjes otomans" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "Papouwazyin (ôtes)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "Pangazinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "Pandjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "Palawouwin" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "Farsi, Vî farsi (åtoû di 600-400 divant J.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "Farsi" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Filipin (ôtes)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "Fenicyin" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "Pâli" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "Polonès" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "Pohnpeyin" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "Portuguès" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Lingaedjes prakrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "Provincå, Vî provincå (djusk' a 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Pashto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "Ketchwa" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "Radjastani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "Rapanwi" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "Raratongyin (Iye di Påke)" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "Roman (ôtes)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "Romantche" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "Romani" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "Roumanyin" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "Kiroundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "Rûsse" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "Yakout" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "Amerindyins d' Amerike nonnrece (ôtes)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Lingaedjes salichans" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Arameyin samaritin" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "Serbe" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "Sicilyin" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "Crowåte" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "Semitike (ôtes)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Irlandès, Vî irlandès (divant 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Lingaedjes des sines" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "Chan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Lingaedjes siwous" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "Sino-Tibetin (ôtes)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Eslåve (ôtes)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "Eslovake" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "Eslovenyin" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "Såmi nonnrece" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "Såmi bijhrece" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Lingaedjes såmi (ôtes)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "Såmi Lule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "Såmi Inari" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "Samowan" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "Såmi Skolt" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "Shona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "Sindi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "Sogdyin" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "Somalyin" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "Songhay" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "Soto nonnrece" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "Espagnol" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "Sardegnyin" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "Nilo-saryin (ôtes)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "Suwati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "Soukouma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "Sundanès" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "Sousou" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "Soumeryin" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "Suwahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "Suwedwès" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "Siriake" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "Tahityin" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Taylandès (ôtes)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "Tamoul" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Tatår" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "Telougou" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "Tetoum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "Tadjik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "Taylandès" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "Tibetin" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "Tigré" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "Tonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "Tonga (Iyes Tonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "Tsimchyin" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "Tswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "Tsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "Turcmene" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "Toumbouka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Lingaedjes toupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "Turk" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Altayike (ôtes)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "Twi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "Touvinyin" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Oudmourt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Ougaritike" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Ouygour" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Oucrinnyin" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Oumboundou" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Nén cnoxhou" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Ourdou" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Ouzbeke" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "Vay" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "Venda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "Vietnamyin" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "Volapouk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Lingaedjes wakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "Walès" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Lingaedjes sorbyin" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "Walon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "Kalmike" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "Xhossa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "Yawo" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "Yidish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "Yorouba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Lingaedjes youpik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "Zapoteke" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "Zandè" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "Zoulou" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "Zouni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "Dji va fé les faitindjes shuvants :" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "(n' espire nén)" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(n' espire nén)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(ESPIRÉ)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(espire divant 24 e)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, fuzzy, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(espire divant 24 e)" +msgstr[1] "(espire divant 24 e)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "nén cnoxhou" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "nén sopoirté" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "Livea 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "Livea 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "Livea 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "I fåt èn ôte Contrat cliyint" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "nén valåbe" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "Li livea do sopoirt n' est nén specifyî" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "Li vindeu n' dene pont d' sopoirt." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"Trovaedje do problinme, ça vout dire on sopoirt tecnike atuzlé po dner des " +"informåcions sol copatibilité, aidance a l' astalaedje, sopoirt po l' " +"eployaedje, mintnance normåle eyet rujhes di båze. Li sopoirt di livea 1 n' " +"est nén fwait po coridjî les arokes des sacwès nén bén fwaites e prodût." + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "I fåt èn ôte contrat cliyint pos awè on sopoirt." + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "Tchuze di sopoirt nén cnoxhowe. I gn a pont d' discrijhaedje" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Môde di corespondaedje \"%s\" nén cnoxhou" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "Môde di corespondaedje \"%s\" pol modele \"%s\" nén cnoxhou" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "Erîlêye ratourneure « %s » nén valåbe : regcomp a rtourné %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Erîlêye ratourneure « %s » nén valåbe" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "I s' fåt otintifyî po « %s »" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "Dji n' sai ahiver l' ridant muchete des meta-dnêyes." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "Åk n' a nén stî come dji sayive di lére a pårti di « %s »" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "Dji n' sai ahiver %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +#, fuzzy +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "Dji n' a trové nole meta-dnêye valåbe al/ås URL sipeciftî(s)" +msgstr[1] "Dji n' a trové nole meta-dnêye valåbe al/ås URL sipeciftî(s)" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Li metaedje e muchete do depot (%d) a fwait berwete." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "Dji basti l' muchete do depot « %s »" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "Dji n' sai ahiver l' muchete a %s - pont d' droet di scrijhaedje." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "Dji n' sai nén apougnî cisse sôre di depot la" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "Dji radjoute li depot « %s »" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "No do fitchî do depot so « %s » nén valåbe" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Dji n' sai nén drovi l' fitchî « %s » pol sicrire." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Åk di nén cnoxhou n' a nén stî come dji léjheu a pårti d' \"%s\"" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Li léjhaedje do ridant « %s » a fwait berwete." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "Dji n' sai nén trover ewou ç' kel depot est wårdé." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Dji n' sai disfacer « %s »" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "Dji n' sai nén trover ewou ç' kel siervice est wårdé." + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "On no metou di siervice ni s' pout cominçî avou on pont." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +#, fuzzy +msgid "Continue?" +msgstr "&Continouwer" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "Dj' a dandjî d' onk ou amdedeus atributs « %s » ou « %s »." + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr " a fwait berwete a l' enondaedje" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Li pacaedje %s shonne awè stî crombyî sol tins do berwetaedje. Voloz rsayî " +"l' rischoyaedje ?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"L' ahessaedje do pacaedje %s a fwait berwete. Voloz vs rissayî l' " +"rischoyaedje?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "li verifiaedje d' applydeltarpm a fwait berwete." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm a fwait berwete." + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Dji n' sai diner l' fitchî « %s » do depot « %s »" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "Pont d' url e depot" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "Dji n' sai ahiver sat-pool." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "sketer %s e passant houte sacwantes di ses aloyances" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "sketer %s e passant houte sacwantes di ses aloyances" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "dimandes d' afrontmints" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "gn des des problinmes d' aloyances" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +#, fuzzy +msgid "unsupported request" +msgstr "nén sopoirté" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "ahesseus disfacé : " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"ahesseus nén astalåves : " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "ahesseus nén astalåves : " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "Cisse dimande ci va scheter vosse sistinme !" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "passer houte l' adviertixhmint d' on sketé sistinme" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "L' astalaedje a stî abandné come dimandé." + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " enondé" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " a fwait berwete a l' enondaedje" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " a passé l' enondaedje cwand il abandnéve" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "Åk n' a nén stî come dji meteu a djoû l' notifiaedje do messaedje." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "Novea messaedje di metaedje a djoû" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM a fwait berwete :" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "L' abagaedje del clé publike %1% a fwait berwete" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "Li oistaedje del clé publike %1% a fwait berwete" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Les fitchîs d' apontiaedje po %s ont stî candjîs :" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm a schapé %s come %s mins ça n' a nén stî possibe di trover l' diferince" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm a schapé %s come %s/\n" +"Vos avoz droci les 25 prumirès royes di diferince :\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" +"rpm a ahivé %s come %s mins ça n' a nén stî possibe di trover l' diferince" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm a ahivé %s come %s/\n" +"Vos avoz droci les 25 prumirès royes di diferince :\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "Ôtès rexhowes di rpm" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "copeye di såvrité di %s ahivêye" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Sinateure di fitchî %s nén trovêye" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Sinateure di fitchî %s nén trovêye" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Sinateure di fitchî %s nén trovêye" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "Crombe sôre « %s » po l' octet %u del some di controle « %s »" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Dji n' sai drovi pty (%s)." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Dji n' sai drovi l' pupe (%s)." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Tchinne di cweraedje di l' IRL LDAP nén valåbe" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Paramete cweraedje di l' URL LDAP nén valåbe « %s »" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Dji n' sai clôner l' objet Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Vude referince d' objet di l' Url nén valåbe" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Dji n' sai analijhî les componints di l' Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "Istwere :" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "L' arindjmint di l' Url ni permet pont d' %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Componrint %s nén valåbe « %s »" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Componint %s nén valåbe" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "L' arindjmint di l' URL est on componint reki" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Arindjmint di l' URL nén valåbe « %s »" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "L' arindjmint di l' Url ni permet pont d' no d' uzeu" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "L' arindjmint di l' Url ni permete pont d' sicret" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "I fåt on lodjoe e l' arindjmint di l' URL" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "L' arindjmint URL ni permete nén d' awè on componint lodjoe" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Componint do lodjoe nén valåbe « %s »" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "L' arindjmint di l' Url ni permet pont d' pôrt" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Componint do pôrt « %s » Nén valåbe" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "I fåt on no di tchmin e l' arindjmint di l' URL" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "I gn a èn octet NUL el tchinne ecôdêye." + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "Li comande a moussî foû avou l' sitatut %d." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "Li comande a stî touwêye på signå %d (%s)." + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "Li comande a moussî foû avou ene aroke nén cnoxhowe." + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "Dji n' sai fé chroot a « %s » (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Dji n' sai fé chroot a « %s » (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "Dji n' sai fé chdir a « / » divins chroot (%s)." + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "Dji n' sai enonder « %s » (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Dji n' sai fé on fork (%s)." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Li montaedje di %s dins %s a fwait berwete" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Li dismontaedje di %s a fwait berwete" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "Mwais no d' fitchî : %s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "Media nén drovou cwand dj' a sayî d' fé l' faitindje « %s »." + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Fitchî « %s » nén trové sol media « %s »" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Dji n' sai scrire li fitchî « %s »." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "Media nén ataetchî" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "Mwais pont d' ataetche do media" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "L' inicialijhaedje di l' aberwetaedje (curl) a fwait berwete po « %s »" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "Foû rîle sistinme « %s » sol media « %s »." + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "Li tchmin « %s » sol media « %s » n' est nén on fitchî." + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "Li tchmin « %s » sol media « %s » n' est nén on ridant." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "URI må fwaite" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "Vude no do lodjoe e l' URI" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "Vude sistinme di fitchî e l' URI" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "Vude såme e l' URI" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Arindjmint d' URI nén sopoirté dins \"%s\"." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "Operåcion nén sopoirtêye på media" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"Aroke d' aberwetaedje (curl) po « %s » :\n" +"Côde di l' aroke : %s\n" +"Messaedje d' aroke : %s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" +"Åk n' a nén stî come dji definixheu les tchuzes d' aberwetaedje (curl) po « " +"%s » :" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "I gn a nén e media sourdant « %s » li media volou" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "Li media « %s » est eployî pa-z ene ôte instance" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "Dji n' sai fé rexhe nou media" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Dji n' sai fé rexhe li media « %s »" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Droet di moussî e « %s » rifuzé." + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "L' astådje a stî trop longue po moussî e \"%s\"." + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "Dji n' sai moussî e l' eplaeçmint « %s » pol moumint." + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" +" : rujhe di l' acertineure SSL, waitîz k' l' acert. di l' OA est boune po « " +"%s »." + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "Metôde d' otintifiaedje HTTP \"%s\" nén sopoirtêye" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Oyi" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Nonna" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Adviertixhmint" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Aroke" + +# +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "done" +msgstr "Indonezeye" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "error" +msgstr "Aroke" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Adviertixhmint" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +#, fuzzy +msgid "Retrieving:" +msgstr "Oistaedje" + +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Dj' enonde..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Rén trové" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "Oyi" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "Nonna" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "" +#~ "%s ni fwait nén pårteye d' on depot d' metaedje a djoû del distribucion" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s a ene årtchitecteure pus basse" + +#~ msgid "problem with installed package %s" +#~ msgstr "problinme avou l' pacaedje d' astalé %s" + +#~ msgid "nothing provides requested %s" +#~ msgstr "rén n' dene li %s dimandé" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "Avoz metou en alaedje tos les depots dmandés ?" + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "Çou paket n' est nén astalé et n' serè nén astalé." + +#~ msgid "%s is not installable" +#~ msgstr "%s n' est nén astalåve" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "rén n' dene %s k' a dandjî %s" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "Dji n' sai nén astaler ambedeus %s eyet %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s s' afronte avou %s ahessî pa %s" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s rind trop vîs %s ahessî pa %s" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "astalé %s trop vîs %s dinés pa %s" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s afrontmints rezoudåves avou %s ahessî pa lyi minme" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s a dandjî d' %s mins cisse dimande ni sait nén esse ahesseye" + +#~ msgid "do not install %s" +#~ msgstr "èn nén astaler %s" + +#~ msgid "keep %s" +#~ msgstr "wårder %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "èn nén espaitchî l' astalaedje di %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "èn nén dmander d' astaler on rezoudaedje dinant %s" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "èn nén dmander d' disfacer tos les rezoudaedjes dinant %s" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "èn nén astaler l' pus nouve modêye di %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "wårder %s mågré k' il est d' ene pus basse årtchitecteure" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "astaler %s mågré k' il est d' ene pus basse årtchitecteure" + +#~ msgid "keep obsolete %s" +#~ msgstr "wårder l' forpassé %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "astaler %s a pårti do depot schovté evoye" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "dismete a djoû di %s a %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "candjmint d' årtchitecteure di %s a %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "astaler %s (avou candjmint d' vindeu)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "replaeçmint di %s avou %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "disastalaedje di %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "Dji n' sai nén drovi l' fitchî d' eclawaedje : %s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "Ci faitindje ci est dedja enondé pa èn ôte programe." + +#~ msgid "Hal Exception" +#~ msgstr "Foû-rîle di hal" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "" +#~ "Dji rgrete mins cisse modêye ci di libzypp a stî basteye sins sopoirt po " +#~ "HAL." + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext nén raloyî" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive nén inicialijhî" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume nén inicialijhî" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Dji n' sai ahiver l' raloyaedje dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new : Dji n' sai ahiver l' contecse libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection : Dji n' sai defini l' raloyaedje dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Dji n' sai inicialijhî l' contecse HAL -- hald nén ovrant ?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Nén on léjheu d' plake CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Dji n' sai inicialijhî les atributs mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Dji n' sai defini l' atribut mutex recursif" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Dji n' sai inicialijhî l' mutex recursif" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Dji n' sai acweri l' eclawaedje mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Dji n' sai dislaxhî l' eclawaedje mutex" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "L' abagaedje del clé publike do fitchî %s a fwait berwete : %s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Li oistaedje del clé publike %s a fwait berwete : %s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "" +#~ "Dji n' sai trover l' éndjin loop k' i gn a po monter l' imådje a pårti d' " +#~ "« %s »" + +#~ msgid "do not keep %s installed" +#~ msgstr "èn nén wårder %s astalé" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "" +#~ "Dji n' sai askepyî l' clé publike %s di l' anea des clés %s e fitchî %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "" +#~ "L' inicialijhaedje di l' aberwetaedje (Metalink curl) a fwait berwete po " +#~ "« %s »" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "Aroke d' aberwetaedje (metalink curl) po « %s » :\n" +#~ "Côde di l' aroke : %s\n" +#~ "Messaedje d' aroke : %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "L' aberwetaedje s' a aresté a %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "L' aberwetaedje a stî aresté pa l' uzeu" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "" +#~ "Åk n' a nén stî come dji definixheu les tchuzes d' aberwetaedje (curl) po " +#~ "« %s » :" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "L' aberwetaedje di %s a pårti di %s a fwait berwete" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbeye et Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Djin nén cnoxhowe" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "L' operåcion d' siervice ni covént nén." + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Coridjaedjes di radjoutés" + +#, fuzzy +#~ msgid "Install missing resolvables" +#~ msgstr "Afrontmint etur les coridjaedjes" + +#, fuzzy +#~ msgid "Keep resolvables" +#~ msgstr "Coridjaedjes ki dj' vos propôze" + +#, fuzzy +#~ msgid "Unlock these resolvables" +#~ msgstr "Coridjaedjes d' amidrés" + +#, fuzzy +#~ msgid "delete %s" +#~ msgstr "Dis&facer" + +#, fuzzy +#~ msgid "unlock all resolvables" +#~ msgstr "Afrontmint etur les coridjaedjes" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "" +#~ "Dji n' pout nén drovi l' fitchî d' son:\n" +#~ "%1" + +#, fuzzy +#~ msgid "Software management is already running." +#~ msgstr "Meteu a djoû d' programe - ZMD n' est nén enondé" + +#, fuzzy +#~ msgid "Invalid information" +#~ msgstr "&Informåcion" + +#, fuzzy +#~ msgid "%s is needed by other resolvables" +#~ msgstr "Coridjaedjes ricomandés" + +#, fuzzy +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "Afrontmint etur les coridjaedjes" + +#, fuzzy +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "afrontmint avou..." + +#, fuzzy +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "Coridjaedjes di radjoutés" + +#, fuzzy +#~ msgid "%s depends on other resolvables" +#~ msgstr "Coridjaedjes ricomandés" + +#, fuzzy +#~ msgid "Child of" +#~ msgstr "Tchili" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "Gn a pont d' eterface uzeu po ç' module." + +#, fuzzy +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "Çou paket n' est nén astalé et n' serè nén astalé." + +#, fuzzy +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "a des dmandes nén rezoudowes..." + +#, fuzzy +#~ msgid "No need to install %s" +#~ msgstr "Copyî les fitchîs sol sistinme d' astalé" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "a des dmandes nén rezoudowes..." + +#, fuzzy +#~ msgid ", Action: " +#~ msgstr "&Accions" + +#, fuzzy +#~ msgid "selection" +#~ msgstr "Tchuze" + +#, fuzzy +#~ msgid "pattern" +#~ msgstr "Modeles" + +#, fuzzy +#~ msgid "product" +#~ msgstr "prodûts" + +#, fuzzy +#~ msgid "patch" +#~ msgstr "coridjaedjes" + +#, fuzzy +#~ msgid "script" +#~ msgstr "Scripe" + +#, fuzzy +#~ msgid "message" +#~ msgstr "Messaedjes" + +#, fuzzy +#~ msgid "Resolvable" +#~ msgstr "Coridjaedjes di dnés." + +#, fuzzy +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "Coridjaedjes ki dvèt esse astalés" + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "Coridjaedjes ki dj' a dandjî dvant l' astalaedje" + +#, fuzzy +#~ msgid "Installing %s" +#~ msgstr "Astalaedje" + +#, fuzzy +#~ msgid " Error!" +#~ msgstr "Aroke" + +#, fuzzy +#~ msgid " Important!" +#~ msgstr "Abe&rweter" + +#, fuzzy +#~ msgid "Reading index files" +#~ msgstr "Dji lé l' lisse des modules..." + +#, fuzzy +#~ msgid "Reading product from %s" +#~ msgstr "Dji schape l' informåcion sol prodût..." + +#, fuzzy +#~ msgid "Reading filelist from %s" +#~ msgstr "Aroke e scrijhant l' lisse des pakets a pårti d' %1" + +#, fuzzy +#~ msgid "Reading packages from %s" +#~ msgstr "Aroke e scrijhant l' lisse des pakets a pårti d' %1" + +#, fuzzy +#~ msgid "Reading pattern from %s" +#~ msgstr "Modeles k' on -z a dandjî" + +#, fuzzy +#~ msgid "The script file failed the checksum test." +#~ msgstr "Ci fitchî la n' egzistêye nén." + +#, fuzzy +#~ msgid "Reading packages file" +#~ msgstr "L' astalaedje des pakets dmandés n' a nén stî." + +#, fuzzy +#~ msgid "Downloading %s" +#~ msgstr "A&berweter" + +#, fuzzy +#~ msgid "Apache languages" +#~ msgstr "Lingaedjes apaches" + +#, fuzzy +#~ msgid "Athapascan languages" +#~ msgstr "Lingaedjes atapascans" + +#, fuzzy +#~ msgid "Australian languages" +#~ msgstr "Lingaedjes ostralyins" + +#, fuzzy +#~ msgid "Bamileke languages" +#~ msgstr "Lingaedjes bamilekes" + +#, fuzzy +#~ msgid "Chinook jargon" +#~ msgstr "Djårgon Tchinouk" + +#, fuzzy +#~ msgid "Creoles and pidgins, English based (Other)" +#~ msgstr "Creyoles et pidjines, båzé sol inglès (ôtes)" + +#, fuzzy +#~ msgid "Creoles and pidgins, French-based (Other)" +#~ msgstr "Creyoles et pidjines, båzé sol francès (ôtes)" + +#, fuzzy +#~ msgid "Creoles and pidgins, Portuguese-based (Other)" +#~ msgstr "Creyoles et pidjines, båzé sol portuguès (ôtes)" + +#, fuzzy +#~ msgid "Iroquoian languages" +#~ msgstr "Lingaedjes irocwès" + +#, fuzzy +#~ msgid "Manobo languages" +#~ msgstr "Lingaedjes manobo" + +#, fuzzy +#~ msgid "Otomian languages" +#~ msgstr "Lingaedjes otomans" + +#, fuzzy +#~ msgid "Prakrit languages" +#~ msgstr "Lingaedjes prakrit" + +#, fuzzy +#~ msgid "Salishan languages" +#~ msgstr "Lingaedjes salichans" + +#, fuzzy +#~ msgid "Siouan languages" +#~ msgstr "Lingaedjes siwous" + +#, fuzzy +#~ msgid "Tupi languages" +#~ msgstr "Lingaedjes toupi" + +#, fuzzy +#~ msgid "Wakashan languages" +#~ msgstr "Lingaedjes wakashan" + +#, fuzzy +#~ msgid "Sorbian languages" +#~ msgstr "Lingaedjes sorbyin" + +#, fuzzy +#~ msgid "Centruual African Republic" +#~ msgstr "Cintrafrike" diff --git a/po/xh.po b/po/xh.po new file mode 100644 index 0000000..cb1e754 --- /dev/null +++ b/po/xh.po @@ -0,0 +1,5969 @@ +# Copyright (C) 2006 SuSE Linux Products GmbH, Nuernberg +# This file is distributed under the same license as the package. +# +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2006-11-03 12:03\n" +"Last-Translator: Novell Language \n" +"Language-Team: Novell Language \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Ilizwe elingaziwa:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Akukho Khowudi" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "i-Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "Ii-Arab Emirates Ezimanyeneyo" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "i-Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "i-Antigua ne-Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "i-Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "i-Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "i-Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "i-Netherlands Antilles" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "i-Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "i-Antarctica" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "i-Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "i-American Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "i-Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "i-Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "i-Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "i-Aland Islands" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "i-Azerbaijan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "i-Bosnia ne-Herzegowina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "i-Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "i-Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "i-Belgium" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "i-Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "i-Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "i-Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "i-Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "i-Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "i-Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "i-Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "i-Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "i-Brazil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "i-Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "i-Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "i-Bouvet Island" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "i-Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "i-Belarus" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "i-Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "i-Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "i-Cocos (Keeling) Islands" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "i-Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Iriphabliki yaseAfrika Esembindini " + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "i-Switzerland" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "i-Cote D'Ivoire" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "i-Cook Islands" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "i-Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "i-Cameroon" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "i-China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "i-Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "i-Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "i-Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "i-Cape Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "i-Christmas Island" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "i-Cyprus" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "i-Czech Republic" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "EJamani" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "i-Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "i-Denmark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "i-Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "i-Dominican Republic" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "i-Algeria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "i-Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "i-Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "iYiphutha" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "i-Western Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "i-Ertrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "i-Spain" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "i-Ethiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "i-Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "i-Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "i-Falkland Islands (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "i-Federated States of Micronesia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "i-Faroe Islands" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "i-France" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "i-Metropolitan France" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "i-Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "i-United Kingdom" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "i-Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "i-Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "i-French Guiana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "EJamani" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "i-Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "i-Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "i-Greenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "i-Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "i-Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "i-Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "i-Equatorial Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "i-Greece" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "i-South Georgia ne-South Sandwich Islands" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "i-Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "i-Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "i-Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "i-Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "i-Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "i-Heard Island ne-McDonald Islands" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "i-Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "i-Croatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "i-Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "i-Hungary" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "i-Indonesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "i-Ireland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "i-Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "i-Indiya" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "i-British Indian Ocean Territory" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "i-Iraq" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "i-Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "i-Iceland" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "i-Italy" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "i-Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "i-Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "iJapani" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "i-Kenya" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "i-Kyrgyzstan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "i-Cambodia" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "i-Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "i-Comoros" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "i-Saint Kitts neNevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "i-North Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "i-South Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "i-Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "i-Cayman Islands" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "i-Kazakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "i-Lao People's Democratic Republic" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "i-Lebanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "i-Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "i-Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "i-Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "i-Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "i-Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "i-Lithuania" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "i-Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "i-Latvia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "i-Libya" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "i-Morocco" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "i-Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "i-Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "isi-Mongo" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "i-San Marino" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "i-Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "i-Marshall Islands" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "i-Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "i-Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "i-Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "i-Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "i-Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "i-Northern Mariana Islands" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "i-Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "i-Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "i-Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "i-Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "i-Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "i-Maldives" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "i-Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "i-Mexico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "i-Malaysia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "i-Mozambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "i-Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "i-New Caledonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "i-Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "i-Norfolk Island" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "i-Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "i-Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "i-Netherlands" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "i-Norway" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "i-Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "i-Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "i-Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "i-New Zealand" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "i-Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "i-Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "i-Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "i-French Polynesia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "i-Papua New Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "i-Philippines" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "i-Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "i-Poland" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "i-Saint Pierre ne-Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "i-Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "i-Puerto-Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "i-Palestinian Territory" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "i-Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "i-Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "i-Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "i-Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "i-Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "i-Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "isi-Serbian" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "i-Russian Federation" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "i-Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "i-Saudi Arabia" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "i-Solomon Islands" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "i-Seychelles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "i-Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "i-Sweden" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "i-Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "i-Saint Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "i-Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "i-Svalbard ne-Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "i-Slovakia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "i-Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "i-San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "i-Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "i-Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "i-Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "i-Sao Tome ne-Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "i-El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "i-Syria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "i-Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "i-Turks ne-Caicos Islands" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "i-Chad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "i-French Southern Territories" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "i-Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "i-Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "i-Tajikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "isi-Tokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "i-Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "i-Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "i-Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "i-East Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "i-Turkey" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "i-Trinidad ne-Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "isi-Tuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "i-Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "i-Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "i-Ukraine" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "i-Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "i-United States Minor Outlying Islands" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "i-United States" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "i-Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "i-Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "i-Holy See (Vatican City State)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "i-Saint Vincent ne-Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "i-Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "i-British Virgin Islands" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "i-Virgin Islands, U.S." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "i-Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "i-Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "i-Wallis ne-Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "i-Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "i-Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "i-Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "uMzantsi Afrika" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "i-Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "i-Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s ziphelelwe lixehsa:%s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Isilele ukuqalisa i-VM." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Isilele ukuqalisa i-VM." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Ukungenisa akufunyenwanga." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Ulwimi Olungaziwayo:" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Isi-Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Isi-Abkhazian" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "isi-Achinese" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "isi-Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "isi-Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "isi-Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "isi-Afro-Asiatic (Esinye)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "isi-Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "isiBhulu" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "isi-Ainu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "isi-Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "isi-Akkadian" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "isi-Albanian" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "isi-Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "isi-Algonquian Languages" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "isi-Southern Altai" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "isi-Amharic" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "isiNgesi, Sakudala (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Iilwimi ze-Apache" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "isi-Arabic" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "isi-Aramaic" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "isi-Aragonese" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "isi-Armenian" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "isi-Araucanian" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "isi-Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "isi-Artificial (Esinye)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "isi-Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "isi-Assamese" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "isi-Asturian" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Iilwimi ze-Athapascan" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Iilwimi zase-Australia" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "isi-Avaric" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "isi-Avestan" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "isi-Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "isi-Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "isi-Azerbaijani" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "isiBanda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Iilwimi ze-Bamileke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "isi-Bashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "isi-Baluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "isi-Bambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "isi-Balinese" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "Isi-Basque" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "isi-Basa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "isi-Baltic (Esinye)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "isi-Beja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "isi-Belarusian" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "isi-Bemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "isi-Bengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "isi-Berber (Esinye)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "isi-Bhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "isi-Bihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "isi-Bikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "isi-Bini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "isi-Bislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "isi-Siksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "isiBantu (Esinye)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "isi-Bosnian" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "isi-Braj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "isi-Breton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "isi-Batak (Indonesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "isi-Buriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "isi-Buginese" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "isi-Bulgarian" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "isi-Burmese" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "isi-Blin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "isi-Caddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "isi-Central American Indian (Esinye)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "isi-Carib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "isi-Catalan" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "isi-Caucasian (Esinye)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "isi-Cebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "isi-Celtic (Esinye)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "isi-Chamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "isi-Chibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "isi-Chechen" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "isi-Chagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "isiTshayina" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "isi-Chuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "isi-Mari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "isi-Chinook Jargon" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "isi-Choctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "isi-Chipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "isi-Cherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "isi-Church Slavic" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "isi-Chuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "isi-Cheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Iilwimi ze-Chamic" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "isi-Coptic" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "isi-Cornish" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "isi-Corsican" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "Ii-Creoles nee-Pidgins, Ezisekwe esiNgesini (Nakwezinye)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "Ii-Creoles nee-Pidgins, Ezisekwe kwisiFrentshi (Nakwezinye)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "Ii-Creoles nee-Pidgins, Ezisekwe kwisiPhuthukezi (Nakwezinye)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "isi-Cree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "isi-Crimean Tatar" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Ii-Creoles nee-Pidgins (Ezinye)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "isi-Kashubian" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "isi-Cushitic (Ezinye)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "isi-Czech" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "isi-Dakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "isi-Danish" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "isi-Dargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "isi-Dayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "isi-Delaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "isi-Slave (Athapascan)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "isi-Dogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "isi-Dinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "isi-Divehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "isi-Dogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "isi-Dravidian (Esinye)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "i-Lower Sorbian" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "isi-Duala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "isi-Datshi, Esiphakathi (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "isiDatshi" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "isi-Dyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "isi-Dzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "isi-Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "isiYiphutha (Samandulo)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "isi-Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "isi-Elamite" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "isiNgesi" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "isiNgesi, Esiphakathi (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "isi-Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "isi-Estonian" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "isi-Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "isi-Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "isi-Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "isi-Faroese" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "isi-Fanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "isi-Fijian" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "isi-Filipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "isiFinnish" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "isi-Finno-Ugrian (Esinye)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "isi-Fon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "isiFrentshi" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "isiFrentshi, Esiphakathi (ca.1050-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "isiNgesi, Sakudala (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "isi-Frisian" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "isi-Fulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "isi-Friulian" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "isi-Ga" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "isi-Gayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "isi-Gbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "isi-Jamani (Ezinye)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "isi-Georgian" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "isiJamani" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "isi-Geez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "isi-Gilbertese" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "isi-Gaelic" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "isi-Irish" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "isi-Galician" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "isi-Manx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "isiJamani, Esiphakathi Phezulu(ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "isiJamani, Sakudala Phezulu (ca.750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "isi-Gondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "isi-Gorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "isi-Gothic" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "isi-Grebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "isi-Grike, Samandulo (ukuya ku-1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "isiGrike, Sanamhla (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "isi-Guarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "isi-Gujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "isi-Gwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "isi-Haida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "isi-Haitian" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "isi-Hausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "isi-Hawaiian" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "isiHebheru" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "isi-Herero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "isi-Hiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "isi-Himachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "isi-Hindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "isi-Hittite" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "isi-Hmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "isi-Hiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "isi-Sorbian Sangasentla" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "isi-Hungarian" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "isi-Hupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "isi-Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "isi-Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "isi-Icelandic" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "isi-Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "isi-Sichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "isi-Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "isi-Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "isi-Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "isi-Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "i-Interlingua (Umbutho Wehlabathi Wokuncedisa Ngeelwimi)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "isi-Artificial (Esinye)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "isi-Indonesian" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "isi-Indo-European (Esinye)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "isi-Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "isi-Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "isi-Iranian (Esinye)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Iilwimi ze-Iroquoian" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "isiTaliyane" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "isi-Javanese" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "isi-Lojban" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "isiJapani" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "isi-Judeo-Persian" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "isi-Judeo-Arabic" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "isi-Kara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "isi-Kabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "isi-Kachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "isi-Kalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "isi-Kamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "isi-Kannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "isi-Karen" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "isi-Kashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "isi-Kanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "isi-Kawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "isi-Kazakh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "isi-Kabardian" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "isi-Khasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "isi-Khoisan (Esinye)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "isi-Khmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "isi-Khotanese" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "isi-Kikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "isi-Kinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "isi-Kirghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "isi-Kimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "isi-Konkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "isi-Komi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "isi-Kongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "isi-Korean" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "isi-Kosraean" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "isi-Kpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "isi-Karachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "isi-Kru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "isi-Kurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "isi-Kuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "isi-Kumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "isi-Kurdish" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "isi-Kutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "isi-Ladino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "isi-Lahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "isi-Lamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "isi-Lao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "isi-Latin" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "isi-Latvian" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "isi-Lezghian" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "isi-Limburgan" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "isi-Lingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "isi-Lithuanian" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "isi-Mongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "isi-Lozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "isi-Luxembourgish" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "isi-Luba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "isi-Luba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "isi-Ganda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "isi-Luiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "isi-Lunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "isi-Luo (eKenya naseTanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "isi-Lushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "isi-Macedonian" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "isi-Madurese" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "isi-Magahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "isi-Marshallese" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "isi-Maithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "isi-Makasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "isi-Malayalam" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "isi-Mandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "isi-Maori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "isi-Austronesian (Esinye)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "isi-Marathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "isi-Masai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "isi-Malay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "isi-Moksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "isi-Mandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "isi-Mende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "isi-Irish, Esiphakathi (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "isi-Mi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "isi-Minangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Iilwimi Eziyintlaninge" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "isi-Mon-Khmer (Esinye)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "isi-Malagasy" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "isi-Maltese" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "isi-Manchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "isi-Manipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Iilwimi zesiManobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "isi-Mohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "isi-Moldavian" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "isi-Mongolian" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "isi-Mossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Iilwimi Ezininzi" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Iilwimi zesiMunda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "isi-Creek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "isi-Mirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "isi-Marwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Iilwimi zesi-Mayan" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "isi-Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "isi-Nahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "isi-American Indian saseMantla" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "isi-Neapolitan" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "i-Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "isiNdebele, saseMzantsi" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "isiNdebele, saseMantla" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "isiNdonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "isiJamani saseZantsi" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "isi-Nepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "isi-Nepal Bhasa" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "isi-Nias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "isi-Niger-Kordofanian (Ezinye)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "isi-Niuean" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "isi-Norwegian Nynorsk" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "isi-Norwegian Bokmal" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "isi-Nogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "isi-Norse, Sakudala" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "isi-Norwegian" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "isiSuthu saseLebowa" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Iilwimi zesiNubian" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "isi-Classical Newari" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "isi-Chichewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "isi-Nyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "isi-Nyankole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "isiNyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "isiNzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "isi-Occitan (emva kwe-1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "isi-Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "isi-Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "isi-Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "isi-Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "isi-Ossetian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "isi-Turkish, Ottoman (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Iilwimi zesi-Otomian" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "isi-Papuan (Esinye)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "isi-Pangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "isi-Pahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "isi-Pampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "isi-Panjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "isi-Papiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "isi-Palauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "isi-Persian, Sakudala (ca.600-400 B.C)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "isi-Persian" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "isi-Philippine (Esinye)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "isi-Phoenician" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "isiPali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "isi-Polish" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "isi-Pohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "isiPhuthukezi" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Iilwimi zesi-Prakrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "isi-Provencal, Sakudala (ukuya kwi-1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "Isi-Pushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "isi-Quechua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "isi-Rajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "isi-Rapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "isi-Ratongan" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "isi-Romance (Ezinye)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "isi-Raeto-Romance" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "isi-Romany" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "isi-Romanian" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "isi-Rundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "isiRashiya" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "isi-Sandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "isi-Sango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "isi-Yakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "isi-South American Indian (Ezinye)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Iilwimi zesi-Salishan " + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "isi-Samaritan Aramaic" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "isi-Sanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "isi-Sasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "isi-Santali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "isi-Serbian" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "isi-Sicilian" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "isi-Scots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "isi-Croatian" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "isi-Selkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "isi-Semitic (Ezinye)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "isi-Irish, Sakudala (ukuya ku-900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Iilwimi zeMiqondiso" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "isi-Shan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "isi-Sidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "isi-Sinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Iilwimi zesi-Siouan" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "isi-Sino-Tibetan (Ezinye)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "isi-Slavic (Esinye)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "isi-Slovak" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "isi-Slovenian" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "isi-Sami esiseMzantsi" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "isi-Sami esiseMantla" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Iilwimi zesi-Sami (Ezinye)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "isi-Lule Sami" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "isi-Inari Sami" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "isi-Samoan" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "isi-Skolt Sami" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "isiShona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "isi-Sindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "isi-Soninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "isi-Sogdian" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "isi-Somali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "isi-Songhai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "isiSuthu, saseMzantsi" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "isi-Spanish" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "isi-Sardinian" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "isi-Serer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "isi-Nilo-Saharan (Ezinye)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "isiSwati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "isiSukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "isi-Sundanese" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "isi-Susu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "isi-Sumerian" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "isiSwahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "isi-Swedish" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "isi-Syriac" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "isi-Tahitian" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "isi-Tai (Esinye)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "isi-Tamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "isi-Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "isiTelegu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "isi-Timne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "isi-Tereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "isi-Tetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "isi-Tajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "isi-Tagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "isi-Thai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "isi-Tibetan" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "isi-Tigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "isi-Tigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "isi-Tiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "isi-Klingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "isi-Tlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "isi-Tamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "isiTonga (Nyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "isi-Tonga (Tonga Islands)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "isi-Tok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "isi-Tsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "isiTswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "isiTsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "isi-Turkmen" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "isiTumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Iilwimi zesiTupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "isi-Turkish" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "isi-Altaic (Esinye)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "isiTwi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "isi-Tuvinian" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "isi-Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "isi-Ugaritic" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "isi-Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "isi-Ukrainian" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "isi-Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Akuqondwanga" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "isi-Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "isi-Uzbek" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "isi-Vai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "isiVenda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "isi-Vietnamese" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "isi-Volapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "isi-Votic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Iilwimi zesiWakashan" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "isi-Walamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "isi-Waray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "isi-Washo" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "isi-Welsh" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Iilwimi zesi-Sorbian" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "isi-Walloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "isi-Wolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "isi-Kalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "isiXhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "isi-Yao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "isi-Yapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "isi-Yiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "isiYoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Iilwimi zesi-Yupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "isi-Zapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "isi-Zenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "isi-Zhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "isi-Zande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "IsiZulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "isiZuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'%1ayikho kwayona." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'%1ayikho kwayona." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "akwaziwa" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "Idiski ayikho." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Umyalelo ongaziwa" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Ulungiselelo olusebenzisekayo lwe-Url '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "Akakwazi kudaleka uvimba weefayili %1: %2." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Ayikwazi kuvuleka into yolwazi olusesikrinini '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Igama lefayili elithathwa ngaphandle elingasebenzisekiyo." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Ayikwazi kuvula ifayili ukuze kubhalwe." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Imposiso xa kufundwa kwidiski ye-floppy." + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Ibuyisela oovimba" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Ayikwazi kuvuleka into yolwazi olusesikrinini '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "Igama le-VM alikwazi kuqalisa ngomvo." + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr "Igama le-VM alikwazi kuqalisa ngomvo." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +# continue button label +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Qhubeka?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Umbekelo%s usilele ukukhangela imfezekiso. Ingaba usafuna ukuzama kwakhona " +"ukuyikhuphela?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Umbekelo%s usilele ukukhangela imfezekiso. Ingaba usafuna ukuzama kwakhona " +"ukuyikhuphela?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "kusilele ukukhangela ukusetyenziswa kwe-deltarpm. " + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "kusilele ukusetyenziswa kwe-deltarpm." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "uhlobo lukavimba we-VAR1 aluluxhasi uphawu lokubonisa utshintsho" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Ayikwazi kubonelela%s ukusuka ku%s" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "Ifayili %1 ayifunyenwanga elugcinweni." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "Ayikwazi kudaleka ifayili." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "Suhoya le mfuneko apha nje" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "Suhoya le mfuneko apha nje" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "Uqhagamshelo lucela uku:" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "Ayikwazi kuhlohla%s ngenxa yeengxaki zoxhomekeko" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "Akukho nanye ebonelela ngo%s " + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "Akukho baboneleli bahlohliweyo baka%s" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "Akukho baboneleli bahlohliweyo baka%s" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "Isicelo sesikhona kakade." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Ukuhlohla kuye kwalahlwa njengoko bekuyalelwe." + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "Phumeza" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "Imposiso ngethuba loguqulelo oluntsonkothileyo lweqhosha." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "isilele" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Iifayili zobumbeko ezitshintshileyo zika%s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "i-rpm igcine %s njenge %s kodwa kwakungenzeki ukumisela umahluko" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"i-rpm igcinwe %s njenge %s.\n" +"Nantsi imigca eyi-25 yokuqala yomahluko:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "i-rpm idalwe %s njenge %s kodwa kwakungenzeki ukumisela umahluko" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"i-rpm idalwe %s njenge %s.\n" +"Nantsi imigca eyi-25 yokuqala yomahluko:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "Isivelisi se-rpm Esongezelelweyo:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "idale ugcino olukhuselekileyo %s " + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Ukungenisa akufunyenwanga." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Ukungenisa akufunyenwanga." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Ukungenisa akufunyenwanga." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Ayikwazi kuvuleka ifayili %1." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Umtya wokubuzisa we-LDAP URL ongasebenzisekiyo" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Umtya wokubuzisa we-LDAP URL ongasebenzisekiyo '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Akukwazeki ukufanisa into ye-Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Isalathi sento ye-Url elikhamte nengasebenzisekiyo" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Akukwazeki ukwahlula iinxalenye ze-Url" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Ulungiselelo lwe-Url aluyivumeli i-%s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Ayisebenziseki %s inxalenye '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Ayisebenziseki %s inxalenye" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Ukwahlulwa komtya wokubuzisa awuxhaswa malunga nale-URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Ulungiselelo lwe-Url yinxalenye efunekayo" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Ulungiselelo olusebenzisekayo lwe-Url '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Ulungiselelo lwe-Url akulivumeli igama lomsebenzisi" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Ulungiselelo lwe-Url awulivumeli igama lokugqithisa" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Ulungiselelo lwe-Url lufuna inxalenye yomamkeli" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Ulungiselelo lwe-Url awuyivumeli inxalenye yomamkeli" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Ayisebenziseki inxalenye yomamkeli ye-'%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Ulungiselelo lwe-Url awusivumeli isiqhagamshelanisi" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Ayisebenziseki inxalenye yesiqhagamshelanisi se-'%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Ulungiselelo lwe-Url lufuna igama lendlela yothungelwano" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Indlela yothungelwano ethelekisekayo ayivunyelwa xa lukhona ugunyaziso" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Umtya ofakwe iikhowudi uqhulethe i-byte ENGENANTO" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" +"Uphawu oluthatha isithuba somhlukanisi oqhekezayo woludwe lomda wenkcazelo " +"engasebenzisekiyo" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" +"Uphawu oluthatha isithuba somhlukanisi oqhekezayo woludwe lomda wenkcazelo " +"ongasebenzisekiyo" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" +"Uphawu oluthatha isithuba somhlukanisi ohlanganisayo woludwe lomda " +"wenkcazelo engasebenzisekiyo" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Umyalelo okhutshwa xa kudityaniswa" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Ayikwazi kufumana %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Ayikwazi kufumana %s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Ayikwazanga kuvuleka i-%s - %s\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Kusilele ukulayishwa kwemodyulei \"%s\"." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Ifayili %1 ayifunyenwanga elugcinweni." + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Akukwazi kubhaleka ukuphawuleka kwefayili %1." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "%1 asingovimba weefayili." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "Igama le-CA elikhamte." + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Isicwangciso se-Url asisebenziseki '%1'" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Ayikwazi kuvuleka into yolwazi olusesikrinini '%s'" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Iimvume zaliwe" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "Ewe" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "Hayi" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Isilumkiso" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Imposiso" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "igqibile" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "impazamo" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Isilumkiso" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Kuyaqaliswa..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Ayifunyanwanga" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "ewe" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "hayi" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s ibonelela%s, kodwa inenye inzululwazi ngokwakha." + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "umyalelo wokuyeka ukuhlohla imibekelelo" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "Akukho nanye ebonelela ngo%s " + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Idiski ayikho." + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s itshixiwe kwaye ayikwazi kungahlohlwa." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "ayihlohlwanga" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s ifunwa ngu %s" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Ayikwazi kuhlohla%s " + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s iimpixano ne %s" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s ziphelelwe lixehsa %s" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s ziphelelwe lixehsa %s" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s iimpixano ne %s" + +#~ msgid "do not install %s" +#~ msgstr "ungahlohli %s" + +#~ msgid "keep %s" +#~ msgstr "Gcina%s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "ungahlohli %s" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "Akukho baboneleli bahlohliweyo baka%s" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "Ungahlohli okanye cima izicombululi ezinxulumeneyo" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s ibonelela%s, kodwa inenye inzululwazi ngokwakha." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "Hlohla%s nangona kuza kutshintsha inzululwazi yokwakha" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s ziphelelwe lixehsa %s" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "Ikhuphele%s ukusuka ku%s" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Ukuhlohla" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Ayikwazi kuvuleka ifayili %1." + +#~ msgid "Hal Exception" +#~ msgstr "Isinxaxhi se-Hal" + +#~ msgid "HalContext not connected" +#~ msgstr "Imeko ye-Hal ayiqhagamshelwanga" + +#~ msgid "HalDrive not initialized" +#~ msgstr "Isixhobo se-Hal asindululwanga" + +#~ msgid "HalVolume not initialized" +#~ msgstr "Isixa se-Hal asindululwanga" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Ayikwazi kudala uqhagamshelo lwe-dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "i-libhal_ctx_entsha: Ayikwazu kudala imeko ye-libhal" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "" +#~ "i-libhal_imisela_uqhagamshelo_lwe-dbus: Ayikwazi kumesela uqhagamshelo " +#~ "lwe-dbus " + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Ayikwazi kundulula imeko ye-HAL--i-hald ayiqhubi?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Akukho sixhobo se-CDROM" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Ayikwazi kundulula ukwabela i-mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Ayikwazi kumisela ulwabelo lokugoba i-mutex " + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Ayikwazi kundulula i-mutex yokugoba" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Ayikwazi kufumana isitshixo se-mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Ayikwazi kukhulula isitshixo se-mutex" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Akukwazeki ukufumana iqhosha likawonkewonke." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "ayihlohlwanga" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Ayikwazanga kuvuleka i-%s - %s\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "i-Serbia ne-Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Isikhethwa soluhlu esingaziwa" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "ayikwazi kusombulula izixhomekeki" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayili%s ayinayo inxenye yokukhangela.\n" +#~ "Sebenzisa ifayili nakanjani?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayili%s isilele ukukhangela imfezeko ngeqhosha elilandelayo:\n" +#~ "%s|%s|%s\n" +#~ " Sebenzisa ifayili nalanjani?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayili%s inenxenye yokukhangela engasebenzi.\n" +#~ "Ilindeleke%s, ifunyenwe%s\n" +#~ " Sebenzisa ifayili nakanjani?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayili%s inenxenye yokukhangela engaziwa%s .\n" +#~ "Sebenzisa ifayili nakanjani?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Ifayili %s ayisayinwanga.\n" +#~ "Yisebenzise nakanjani?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayili%s isayinwe ngeqhosha elingaziwa:\n" +#~ "%s|%s|%s\n" +#~ " Sebenzise ifayili nakanjani?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Kufunyenwe iqhosha elingathenjwanga:\n" +#~ "%s|%s|%s\n" +#~ " Themba Iqhosha?" + +#~ msgid "%s remove failed" +#~ msgstr "%s ukushenxisa kusilele" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "Guqula igama lokugqithisa lakho" + +#~ msgid "rpm output:" +#~ msgstr "isivelisi se-rpm:" + +#~ msgid "%s install failed" +#~ msgstr "%s ukuhlohla kusilele" + +#~ msgid "%s installed ok" +#~ msgstr "%s ukuhlohla kulungile" + +#~ msgid "%s remove ok" +#~ msgstr "%s ukushenxisa kulungile" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "" +#~ "%s ibonelela esi sixhomekeki kodwa kuza kutshintsha inzululwazi yokwakha " +#~ "into ehlohliweyo" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "" +#~ "%s ibonelela esi sixhomekeki kodwa kuza kutshintsha inzululwazi yokwakha " +#~ "into ehlohliweyo" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Ungahlohli okanye cima izicombululi ezinxulumeneyo" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Suhoya ukuba%s sele imiselwe ukuhlohla" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "Suhoya ukuphelelwa%s lixesha kwi%s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "Suhoya le mpixano ka%s " + +#~ msgid "Ignore this requirement just here" +#~ msgstr "Suhoya le mfuneko apha nje" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "Hlohla%s nangona kuza kutshintsha inzululwazi yokwakha" + +#~ msgid "Install missing resolvables" +#~ msgstr "Hlohla izicombululi ezilahlekileyo" + +#~ msgid "Keep resolvables" +#~ msgstr "Gcina iziconjululwa" + +#~ msgid "Unlock these resolvables" +#~ msgstr "Vula ezi zicombululi" + +#~ msgid "delete %s" +#~ msgstr "Cima %s" + +#~ msgid "install %s" +#~ msgstr "hlohla%s" + +#~ msgid "unlock %s" +#~ msgstr "vula%s" + +#~ msgid "unlock all resolvables" +#~ msgstr "vula zonke izicombululi" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Ayikwazi kuvuleka ifayili %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "Icandelo lokufunda imposiso %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "" +#~ "Ukwahlula umda wenkcazelo yendlela yothungelwano awuxhaswa malunga nale-" +#~ "URL" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "" +#~ "Ukwahlula umda wenkcazelo yendlela yothungelwano awuxhaswa malunga ne-URL" + +#~ msgid "Software management is already running." +#~ msgstr "Ukulawulwa kwe-software sele kuqhuba." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s ibuyiselwe ngo %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s ibuyiselwe ngo %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "Ezi ziconjululwa ziza kucinywa kwisixokelelwano." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s ayizukuhlohlwa kuba isafuneka" + +#~ msgid "Invalid information" +#~ msgstr "Ulwazi olungasebenzi" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s iyafunwa zezinye iziconjululwa" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s ifunwa ngu:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s iimpixano nezinye iziconjululwa" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s iimpixano ne:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s yenza ezinye iziconjululwa ziphelelwe lixesha" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "Ezi ziconjululwa ziza kucinywa kwisixokelelwano." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s ixhomekeke kwezinye iziconjululwa" + +#~ msgid "%s depends on %s" +#~ msgstr "%s ixhomekeke kwi %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s ixhomekeke kwi:%s" + +#~ msgid "Child of" +#~ msgstr "Umntwana ka" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "Akukho vimba ufumanekayo oxhasa le mfuneko." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "Ngenxa yeengxaki ezichazwe ngentla/ngezantsi kwesi sigqibo " +#~ "akuyikusombulula zonke izixhomekeki." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "Ayikwazi kuhlohla u%s kuba kuyaphixana ne%s " + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s ayihlohlwanga kwaye iphawulwe njengengahlohleki" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s inemfuneko ezingazalisekiswanga" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s inezixhomekeki ezilahlekileyo" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s ayikwazi kuhlohla ngenxa yezixhomekeki ezilahlekikeyo" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s zalisekisa izixhomekeki zika%s kodwa aziyi kuhlohlwa" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "" +#~ "%s zaliseka izixhomekeki zika%s kodwa ziza kugcinwa kwisixokelelwano sakho" + +#~ msgid "No need to install %s" +#~ msgstr "Akukho mfuno yokuhlohla%s " + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "Ayikwazi kuhlohla%s ukuzalisekisa izixhomekeki zika%s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "Ayikwazi kuhlohla%s ukuzalisekisa izixhomekeki zika%s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s ayizukuhlohlwa kuba isafuneka" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "%s ziphelelwe lixehsa%s . Kodwa%s ayikwazi kucima kuba itshixiwe." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "Ayikwazi kuhlohla u%s kuba kuyaphixana " + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s ayihlohleki ngenxa yeempixano ne %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "ukufuna%s ka%s xa ihlaziya%s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s ilahlekelwe yimfuneko %s" + +#~ msgid ", Action: " +#~ msgstr ", Isenzo:" + +#~ msgid ", Trigger: " +#~ msgstr ", Inkcukumiso:" + +#~ msgid "package" +#~ msgstr "umbekelo" + +#~ msgid "selection" +#~ msgstr "ukukhetha" + +#~ msgid "pattern" +#~ msgstr "indlela yenkqubo" + +#~ msgid "product" +#~ msgstr "imveliso" + +#~ msgid "patch" +#~ msgstr "lungisa" + +#~ msgid "script" +#~ msgstr "iskripti" + +#~ msgid "message" +#~ msgstr "umyalezo" + +#~ msgid "atom" +#~ msgstr "iatom" + +#~ msgid "system" +#~ msgstr "isixokelelwano" + +#~ msgid "Resolvable" +#~ msgstr "Isiconjululwa" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "Ukuphawu le nzame yesigqibo akusebenzi." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "Ukuphawula ukuconjululwa%s njengesingahlohleki" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s uludwe lwenkqubo ukuba lihlohlwe, kodwa oku akwenzeki ngenxa yeengxaki " +#~ "zesixhomekeki." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "" +#~ "Ayikwazi kuhlohla%s ukusukela oko kuba sele iphawulwe njengefuna ukuba " +#~ "ihlohlwe" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "" +#~ "Ayikwazi kuhlohla%s ukusukela oko ingabhekiseli kwesi sixokelelwano." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "Ayikwazi kuhlohla%s ukusukela oko%s kuba sele iphawulwe njengefuna ukuba " +#~ "ihlohlwe" + +#~ msgid "This would invalidate %s." +#~ msgstr "Oku kuza kubhangisa%s." + +#~ msgid "Establishing %s" +#~ msgstr "Imisela%s" + +#~ msgid "Installing %s" +#~ msgstr "Ihlohla %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "Ihlaziya%s ukuya ku%s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "Itsiba%s: sele ihlohliwe" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "Akukho baboneleli bachaseneyo bahlohliweyo baka%s" + +#~ msgid "for %s" +#~ msgstr "ka%s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "Hlaziya ukuya ku%s ukunqanda ukushenxiswa kuka%s akwenzeki." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s ibonelela%s, kodwa yenzelwe uludwe lwenkqubo ukuba ihlohlwe." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "%s ibonelela%s, kodwa enye inguqulelo yoko%s sele ihlohliwe." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s ibonelela%s, kodwa ayihlohleki. Zama ukuyihlohla ngokunokwayo " +#~ "ngeenkcukacha ezithe vetshe." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s ibonelela%s, kodwa itshixiwe." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s ibonelela%s, kodwa yenzelwe uludwe lwenkqubo ukuba igcinwe." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s ibonelela%s, kodwa inenye inzululwazi ngokwakha." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "Ayikwazi kwanelisa imfuneko%s ka%s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s iyafunwa zezinye ukuba ihlohle izicombululi, ayizukwazi ukwenziwa " +#~ "inganxulumani." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s iyafunwa zezinye ukuba ihlohle izicombululi, ayizukwazi ukwenziwa " +#~ "inganxulumani." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "Impixano ngaphezu%s (%s) ifuna ukushenxiswa ukuba kuhlohlwe%s" + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "Ukuphawula%s njengengahlohleki ngenxa yeempixano ezingaphezu kuka%s" + +#~ msgid "from %s" +#~ msgstr "Ukusuka ku%s" + +#~ msgid " Error!" +#~ msgstr "Imposiso!" + +#~ msgid " Important!" +#~ msgstr "Ibalulekile!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s ixhomekeke kwi %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s ifunwa ngu %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s ifunwa ngu %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s ibuyiselwe ngo %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s ifunwa ngu %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s inxenye ka %s" + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s ifunwa ngu %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "Akukwazeki ukwahlula ugunyaziso lwe-Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "Suhoya le mfuneko jikelele" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s iyafunwa zezinye ukuba ihlohle izicombululi, ayisoze inganxulumani." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "Ayikwazi kudala ifayili efunelwa ukwenza ukuhlohlwa kohlaziyo." + +#~ msgid "Unable to restore all sources." +#~ msgstr "Ayikwazi kugcina bonke oovimba." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "Uvimba nje omnye sele ebhalisiwe, oovimba abagciniweyo abanako ukugcinwa " +#~ "kwakhona." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "Ayikwazi kuhlohla%s ukuzalisekisa izixhomekeki zika%s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s ixhomekeke kwi %s" + +#~ msgid "Reading index files" +#~ msgstr "Ifunda iifayili zokwalathisa" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "Ifayili ye-xml repomd esayiniweyo isilele usayino lokukhangela." + +#~ msgid "Reading product from %s" +#~ msgstr "Ifunda imveliso ukusuka ku%s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "Ifunda uluhlu lwefayili ukusuka ku%s" + +#~ msgid "Reading packages from %s" +#~ msgstr "Ifunda imibekelo ukusuka ku%s" + +#~ msgid "Reading selection from %s" +#~ msgstr "Ifunda ukukhetha ukusuka ku%s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "Ifunda indlela yenkqubo ukusuka ku%s" + +#~ msgid "Reading patches index %s" +#~ msgstr "Ifunda iindawana zokwalathisa%s" + +#~ msgid "Reading patch %s" +#~ msgstr "Ifunda indawana%s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "Ifayili yesikripti isilele uvavanyo lwe-checksum. " + +#~ msgid "Reading packages file" +#~ msgstr "Ifunda ifayili yemibekelo" + +#~ msgid "Reading translation: %s" +#~ msgstr "Ifunda uguqulelo: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "Umbekelo%s usilele ukukhangela imfezekiso. Ingaba usafuna ukuzama " +#~ "kwakhona ukuyikhuphela, okanye lahla ukuhlohla?" + +#~ msgid " miss checksum." +#~ msgstr "ilahlekelwe kukukhangela inxenye." + +#~ msgid " fails checksum verification." +#~ msgstr "isilele ukuqinisekisa ukukhangela inxenye." + +#~ msgid "Downloading %s" +#~ msgstr "Ikhuphela u%s" diff --git a/po/zh_CN.po b/po/zh_CN.po new file mode 100644 index 0000000..2ab3ba9 --- /dev/null +++ b/po/zh_CN.po @@ -0,0 +1,5489 @@ +# Chinese message file for YaST2 (@memory@) +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2001 SuSE GmbH. +# +# +# Thruth Wang , 2007, 2008, 2009, 2012, 2013. +# marguerite , 2013. +# 玛格丽特 · 苏 , 2013, 2014, 2015. +msgid "" +msgstr "" +"Project-Id-Version: YaST (@memory@)\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-04-30 05:43+0000\n" +"Last-Translator: Grace Yu \n" +"Language-Team: Chinese (China) \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-Generator: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "未知国家或地区: " + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "无代码" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "安道尔共和国" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "阿拉伯联合酋长国" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "阿富汗" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "安提瓜岛和巴布达岛" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "安圭拉岛" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "阿尔巴尼亚" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "亚美尼亚" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "荷属安的列斯" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "安哥拉" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "南极洲" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "阿根廷" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "美属萨摩亚" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "奥地利" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "澳大利亚" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "阿鲁巴岛" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "奥兰群岛" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "阿塞拜疆" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "波斯尼亚和黑塞哥维那" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "巴巴多斯岛" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "孟加拉国" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "比利时" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "布基纳法索" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "保加利亚" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "巴林" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "布隆迪" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "贝宁湾" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "百慕大群岛" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "文莱达鲁萨兰国" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "玻利维亚" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "巴西" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "巴哈马群岛" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "不丹" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "布维岛" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "博茨瓦纳" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "白俄罗斯" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "伯利兹城" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "加拿大" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "科科斯(基林)群岛" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "刚果" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "中非共和国" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "瑞士" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "科特迪瓦共和国" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "库克群岛" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "智利" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "喀麦隆" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "中国" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "哥伦比亚" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "哥斯达黎加" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "古巴" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "佛得角" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "圣诞岛" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "塞浦路斯" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "捷克共和国" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "德国" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "吉布提" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "丹麦" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "多米尼加" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "多米尼加共和国" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "阿尔及利亚" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "厄瓜多尔" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "爱沙尼亚" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "埃及" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "西撒哈拉" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "厄立特里亚" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "西班牙" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "埃塞俄比亚" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "芬兰" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "斐济" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "福克兰群岛(马尔维纳斯群岛)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "密克罗尼西亚联邦" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "法罗群岛" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "法国" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "法属美特罗波利坦" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "加蓬" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "英国" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "格林纳达" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "乔治亚州" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "法属圭亚那" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "格恩西" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "加纳" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "直布罗陀" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "格陵兰" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "冈比亚" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "几内亚" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "瓜德罗普岛" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "赤道几内亚" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "希腊" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "南乔治亚岛和南三维治群岛" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "危地马拉" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "关岛" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "几内亚比绍共和国" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "圭亚那" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "中国香港特别行政区" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "赫德岛和麦克唐纳岛" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "洪都拉斯" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "克罗地亚" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "海地" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "匈牙利" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "印度尼西亚" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "爱尔兰" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "以色列" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "马恩岛" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "印度" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "英属印度洋领地" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "伊拉克" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "伊朗" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "冰岛" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "意大利" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "泽西岛" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "牙买加" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "约旦" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "日本" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "肯尼亚" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "吉尔吉斯斯坦" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "柬埔寨" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "基里巴斯" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "科摩罗" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "圣基茨和尼维斯" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "北朝鲜" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "南韩" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "科威特" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "开曼群岛" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "哈萨克斯坦" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "老挝人民民主共和国" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "黎巴嫩" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "圣卢西亚岛" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "列支敦士登" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "斯里兰卡" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "利比里亚" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "莱索托" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "立陶宛" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "卢森堡公国" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "拉脱维亚" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "利比亚" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "摩洛哥" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "摩纳哥" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "摩尔多瓦" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "黑山" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "圣马丁" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "马达加斯加岛" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "马绍尔群岛" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "马其顿王国" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "马里" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "缅甸" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "蒙古" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "中国澳门行政特区" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "北马里亚纳群岛" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "马提尼克岛" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "毛利塔尼亚" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "蒙特塞拉特岛" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "马耳他" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "毛里求斯" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "马尔代夫" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "马拉维" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "墨西哥" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "马来群岛" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "莫桑比克" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "纳米比亚" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "新喀里多尼亚" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "尼日尔" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "诺福克岛" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "尼日利亚" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "尼加拉瓜" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "荷兰" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "挪威" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "尼泊尔" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "瑙鲁语" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "纽埃岛" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "新西兰" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "阿曼" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "巴拿马" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "秘鲁" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "法属波利尼西亚" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "巴布亚新几内亚" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "菲律宾共和国" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "巴基斯坦" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "波兰" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "圣皮埃尔和密克隆" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "皮特克恩岛" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "波多黎各" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "巴基斯坦领土" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "葡萄牙" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "帕劳群岛" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "巴拉圭" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "卡塔尔" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "留尼旺" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "罗马尼亚" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "塞尔维亚" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "俄联邦" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "卢旺达" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "沙特阿拉伯" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "所罗门群岛" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "塞舌尔" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "苏丹" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "瑞典" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "新加坡" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "圣赫勒拿" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "斯洛文尼亚" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "斯瓦尔巴岛和扬马延岛" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "斯洛伐克" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "塞拉利昂" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "圣马力诺" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "塞内加尔" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "索马里" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "苏里南" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "圣多美和普林西比" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "萨尔瓦多" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "叙利亚共和国" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "斯威士兰" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "特克斯和凯科斯群岛" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "乍得湖" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "法属南部领土" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "多哥" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "泰国" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "塔吉克斯坦" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "托克劳语" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "土库曼斯坦" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "突尼斯" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "汤加" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "东帝汶" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "土耳其" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "特立尼达和多巴哥" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "图瓦卢语" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "台湾" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "坦桑尼亚" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "乌克兰" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "乌干达" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "美国本土外小岛屿" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "美国" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "乌拉圭" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "乌兹别克斯坦" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "梵蒂冈(梵蒂冈城国)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "圣文森特和格林纳丁斯" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "委内瑞拉" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "英属维尔京群岛" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "美属维尔京群岛" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "越南" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "瓦努阿图" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "瓦利斯和富图纳" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "萨摩亚群岛" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "也门" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "马约特岛" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "南非" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "赞比亚" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "津巴布韦" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "提供" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "前提" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "需要" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "冲突" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "淘汰" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "推荐" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "建议" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "增强" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "补充" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "尝试导入尚不存在的密钥 %s 到密钥环 %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "导入密钥失败。" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "删除密钥失败。" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "未找到签名文件 %s" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "未知语言: " + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "阿法尔语" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "阿布哈兹语" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "亚齐语" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "阿乔利方言" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "阿当梅语" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "阿地盖语" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "亚非诸语言(其它)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "阿弗里希利语" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "南非荷兰语" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "阿伊努语" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "阿坎语" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "阿卡德语" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "阿尔巴尼亚语" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "阿留申语" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "阿冈昆语" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "南阿尔泰语" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "阿姆哈拉语" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "古代英语(约 450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "阿帕切语" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "阿拉伯语" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "亚拉姆语" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "阿拉贡语" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "亚美尼亚语" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "阿劳干语" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "阿拉帕霍语" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "人工语言(其它)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "阿拉瓦克语" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "阿萨姆语" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "阿斯图里亚斯语" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "阿撒巴斯卡语" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "澳洲语" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "阿法语" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "阿维斯陀语" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "阿瓦乔语" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "艾马拉语" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "阿塞拜疆语" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "班达语" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "巴米累克语" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "巴什基尔语" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "俾路支语" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "班巴拉语" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "巴厘语" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "巴斯克语" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "巴萨语" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "波罗的海诸语言(其它)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "别札语" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "白俄罗斯语" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "别姆巴语" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "孟加拉语" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "柏柏尔语(其它)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "博杰普尔语" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "比哈里语" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "比口语" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "比尼语" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "比利兹语" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "西克西卡语" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "班图语(其它)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "波斯尼亚语" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "布拉杰语" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "布里多尼语" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "巴塔克语(印度尼西亚)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "布利亚特语" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "布吉语" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "保加利亚语" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "缅甸语" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "布林语" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "卡多语" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "中美洲印第安语(其它)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "加勒比语" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "加泰罗尼亚语" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "高加索语(其它)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "宿务语" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "塞尔特语(其它)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "查莫罗语" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "契布卡语" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "车臣语" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "查加语" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "中文" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "楚克语" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "马里语" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "契努克语" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "乔克托语" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "奇帕维安语" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "彻罗基语" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "宗教斯拉夫语" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "楚瓦什语" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "夏延语" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "查米克语" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "科普特语" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "凯尔特语" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "科西嘉语" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "基于英语的克里奥尔语和皮钦语(其它)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "基于法语的克里奥尔语和皮钦语(其它)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "基于葡萄牙语的克里奥尔语和皮钦语(其它)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "克里族语" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "克里米亚鞑靼语" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "克里奥尔语和皮钦语(其它)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "卡舒比语" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "库希特语(其它)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "捷克语" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "达科他语" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "丹麦语" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "特拉华语" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "达雅语" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "特拉瓦印第安人语" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "阿萨巴斯卡奴隶语" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "多格里布语" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "丁卡语" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "迪蔚希语" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "多格来语" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "达罗毗荼语(其它)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "下索布语" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "都阿拉语" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "中古荷兰语(约 1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "荷兰语" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "迪尤拉语" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "不丹语" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "艾非克语" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "古埃及语" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "艾卡朱克语" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "艾拉米特语" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "英语" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "中古英语 (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "世界语" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "爱沙尼亚语" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "幽语" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "埃翁多语" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "芳语" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "法罗语" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "芳蒂语" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "斐济语" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "菲律宾语" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "芬兰语" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "芬兰乌戈尔语(其它)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "丰语" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "法语" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "中古法语(约 1050-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "古法语(842-约 1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "弗里西语" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "富拉语" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "弗留利语" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "加语" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "卡约语" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "巴亚语" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "日尔曼语(其它)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "乔治亚语" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "德语" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "吉兹语" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "吉尔伯特语" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "盖尔语" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "爱尔兰语" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "加利西亚语" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "马恩岛语" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "中古高地德语(约 1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "古高地德语(约 750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "贡德语" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "哥伦打洛语" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "哥特语" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "格列博语" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "古希腊语(1453 以前)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "现代希腊语 (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "瓜拉尼语" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "印度古哈拉地语" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "库臣语" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "海达语" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "海地语" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "豪撒语" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "夏威夷语" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "希伯来语" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "赫雷罗语" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "希利盖农语" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "喜马偕尔语" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "北印度语" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "赫梯语" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "蒙(苗)语" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "希里莫图语" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "高地索布语" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "匈牙利语" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "胡帕语" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "伊班语" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "伊博语" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "冰岛语" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "伊多语" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "四川彝语" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "伊乔语" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "伊努伊特语" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "国际语" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "伊洛卡诺语" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "国际语(国际辅助语协会)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "印度语(其它)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "印度尼西亚语" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "印欧诸语言(其它)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "英古什语" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "依努皮亚语" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "伊朗语(其它)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "易洛魁语" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "意大利语" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "爪哇语" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "逻辑语" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "日语" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "犹太-波斯语" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "犹太-阿拉伯语" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "卡拉卡尔帕克语" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "卡比尔语" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "克钦语" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "格陵兰语" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "坎巴语" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "加拿大语" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "克伦语" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "克什米尔语" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "卡努里语" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "卡威语" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "哈萨克语" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "卡巴尔德语" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "卡西语" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "科伊桑语(其它)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "高棉语" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "和阗(和田)语" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "基库尤语" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "加泰隆语" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "吉尔吉斯语" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "金本杜语" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "孔卡尼语" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "科米语" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "刚果语" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "韩语" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "科斯拉伊语" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "克佩勒语" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "卡拉恰伊-巴尔卡尔语" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "克鲁语" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "库卢克语" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "宽亚玛语" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "库密克语" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "库尔德语" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "库特内语" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "拉迪诺语" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "拉亨达语" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "兰巴语" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "老挝语" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "拉丁语" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "拉脱维亚语" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "列兹金语" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "林堡干语" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "林加拉语" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "立陶宛语" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "蒙古语" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "洛齐语" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "卢森堡语" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "卢巴-卢拉语" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "卢巴-加丹加语" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "干达语" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "卢伊塞诺语" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "隆达语" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "卢奥语(肯尼亚和坦桑尼亚)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "卢萨语" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "马其顿语" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "马都拉语" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "马加赫语" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "马绍尔语" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "米德勒语" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "望加锡语" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "马拉雅拉姆语" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "曼丁哥语" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "毛利语" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "南岛语(其它)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "马拉地语" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "马萨伊语" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "马来语" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "莫克沙语" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "曼达语" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "门德语" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "中古爱尔兰语 (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "密克马克语" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "米南卡保语" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "杂语" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "孟高棉语(其它)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "马达加斯加语" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "马耳他语" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "满语" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "曼尼普尔语" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "马诺博诸语言" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "莫霍克语" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "摩尔达维亚语" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "蒙古语" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "莫西语" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "多语种" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "蒙达诸语言" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "克里克语" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "米兰德语" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "马尔瓦利语" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "玛雅诸语言" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "厄尔兹亚语" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "纳瓦特尔语" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "北美印第安语" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "那不勒斯语" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "纳瓦霍语" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "南部恩德贝勒语" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "北部恩德贝勒语" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "恩敦加语" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "低地德语" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "尼泊尔语" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "尼泊尔 Bhasa 语" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "尼亚斯语" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "尼日尔-科尔多凡语(其它)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "纽埃语" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "挪威 Nynorsk 语" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "挪威布克摩尔语" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "诺盖语" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "古诺尔斯语" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "挪威语" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "北梭托语" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "努比亚诸语言" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "古典尼瓦尔语" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "齐切瓦语" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "尼扬韦齐语" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "尼扬科勒语" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "尼奥罗语" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "恩济马语" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "欧西坦语(1500 后)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "奥吉布瓦语" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "奥里亚语" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "奥罗莫语" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "奥萨格语" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "奥塞梯语" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "土耳其语,古奥斯曼 (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "奥托米诸语言" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "巴布亚语(其它)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "邦阿西楠语" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "钵罗钵语" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "邦板牙语" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "旁遮普语" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "帕皮亚门托语" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "帕劳语" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "古波斯语(约公元前 600-400)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "波斯语" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "菲律宾语(其它)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "腓尼基语" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "巴利语" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "波兰语" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "波纳佩语" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "葡萄牙语" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "古印度方言" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "古普罗旺斯语(1500 以前)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "普什图语" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "盖丘亚语" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "拉贾斯坦语" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "拉帕努伊语" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "拉罗汤加语" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "罗曼语 (其它)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "罗曼语" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "吉普赛语" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "罗马尼亚语" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "隆迪语" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "俄语" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "桑达韦语" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "桑戈语" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "雅库特语" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "南美洲印第安语(其它)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "萨利什诸语言" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "萨马利亚阿拉米语" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "梵语" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "萨萨克语" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "桑塔利语" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "塞尔维亚语" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "西西里岛语" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "苏格兰语" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "克罗地亚语" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "塞尔库普语" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "闪米特语(其它)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "古爱尔兰语(900 以前)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "手语" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "掸语" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "锡达莫语" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "僧伽罗语" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "苏语诸语言" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "汉藏诸语言(其它)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "斯拉夫语(其它)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "斯洛伐克语" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "斯洛文尼亚语" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "南萨摩斯语" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "北萨摩斯语" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "萨米诸语言(其它)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "鲁乐萨摩斯语" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "伊纳里萨摩斯语" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "萨摩亚语" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "斯考特萨摩斯语" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "修纳语" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "信德语" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "索宁克语" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "粟特语" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "索马里语" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "桑海语" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "南部索托语" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "西班牙语" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "撒丁语" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "塞雷尔语" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "尼罗-撒哈拉语(其它)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "斯瓦特语" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "苏库马语" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "巽他语" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "苏苏语" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "苏美尔语" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "斯瓦希里语" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "瑞典语" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "古叙利亚语" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "塔希提语" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "傣语(其它)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "泰米尔语" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "鞑靼语" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "泰卢固语" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "滕内语" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "特列纳语" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "特塔姆语" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "塔吉克语" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "塔加路语" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "泰国语" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "藏语" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "提格雷语" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "提格里尼亚语" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "蒂夫语" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "克林贡" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "特林吉特语" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "塔马奇克语" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "汤加语(尼亚萨)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "汤加语(汤加岛)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "托克皮辛语" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "钦西安语" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "茨瓦纳语" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "聪加语" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "土库曼语" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "奇图姆布卡语" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "图皮诸语言" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "土耳其语" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "阿尔泰语(其它)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "契维语" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "图瓦语" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "乌德穆尔特语" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "乌加里特语" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "维吾尔语" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "乌克兰语" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "翁本杜语" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "未确定的语种" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "乌尔都语" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "乌兹别克斯坦语" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "瓦伊语" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "文达语" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "越南语" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "沃拉普克语" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "沃提克语" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "瓦卡希语组" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "瓦拉莫语" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "瓦赖语" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "瓦肖语" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "威尔士语" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "索布诸语言" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "瓦龙语" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "沃洛夫语" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "卡尔梅克语" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "科萨语" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "瑶语" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "雅浦语" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "依地语" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "约鲁巴语" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "尤皮克诸语言" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "萨波特克语" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "哲纳加语" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "壮语" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "赞德语" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "祖鲁语" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "祖尼语" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "将执行以下动作:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "永不过期" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "过期日期:%1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "过期日期:%1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(永不过期)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(已过期)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(24 小时内过期)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(%d 天后过期)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "未知" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "不支持" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "级别 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "级别 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "级别 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "需要额外的客户合同" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "已停产且已被其他软件包替代" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "无效" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "支持级别未指定" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "厂商不提供支持。" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"问题判定,该技术支持设计用于提供兼容性信息、安装辅助、使用帮助、持续维护和基" +"础甄错。一级支持并不意在修正产品缺陷错误。" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"问题隔离,该技术支持设计用于重现客户问题、孤立问题领域并提供一级支持不能解决" +"的问题的解决方案。" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"问题解决,该技术支持设计用来解决复杂的问题,通过工程解决二级支持中确认的产品" +"缺陷。" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "签署一份额外的客户合同后才能获得支持。" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "该软件包已停产且已被一个使用其他名称的新软件包替代。" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "未知支持选项。描述不可用" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"系统管理被进程编号为 %d 的应用程序 %s 锁定。\n" +"请关闭此应用程序再试。" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "未知匹配模式 '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "未知匹配模式 '%s'(对于软件集 '%s')" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "无效的正则表达式 '%s':regcomp 返回 %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "无效的正则表达式 '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "'%s' 需要认证" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "将重试..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "已尝试 %1% 次,将放弃。" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "访问 SUSE 客户中心检查您的注册是否有效且未过期。" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "访问 Novell 客户中心检查您的注册是否有效并尚未过期。" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "创建挂接点:找不到可用于创建挂接点的可写目录" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "请先安装 'lsof' 软件包。" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "无法创建元数据缓存文件夹。" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "试图读取 '%s' 出错" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "无法创建 %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "在指定 URL 未找到有效元数据" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "缓存软件源 (%d) 失败。" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "正在构建软件源 '%s' 的缓存" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "无法在 %s 创建缓存 - 无写入权限。" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "未处理的软件源类型" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "正在添加软件源 '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "'%s' 处的源文件名无效" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "无法打开 '%s' 文件进行写入。" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "读取 '%s' 遇到未知错误" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "无法读取源文件夹 '%1%':权限被拒" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "读取文件夹 '%s' 失败" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "无法读取源文件 '%1%':权限被拒" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "正在移除软件源 '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "不确定软件源的存储位置。" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "无法删除 '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "不确定服务的储存位置。" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "未知服务 '%1%':正在移除孤立的服务软件源 '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "软件源别名不能以点开头。" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "服务别名不能以点开头。" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "文件 %s 没有摘要。" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "摘要 %s 未知(文件 %s)。" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "文件 '%s' 的摘要验证失败" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "文件 '%s' 未签名,要继续吗?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "文件 '%s'(来自储存库 '%s')未签名,要继续吗?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "要拒绝密钥、暂时信任还是始终信任密钥?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "密钥名称:%1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "从储存库 \"%2%\" 收到 %1% 个新的套件签名密钥:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "文件 '%1%' 的签名验证失败。" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "对储存库 '%2%' 中的文件 '%1%' 的签名验证失败。" + +# internal key used: Ok +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "继续吗?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "文件 '%s' 是使用未知密钥 '%s' 签名的。要继续吗?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "文件 '%s'(来自储存库 '%s')是使用未知密钥 '%s' 签名的。要继续吗?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "软件源 %1% 并未定义额外的 'gpgkey=' URL。" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "正在软件源 %2% 中查找 GPG 密钥 ID %1%。" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "正在缓存 %2% 中查找 GPG 密钥 ID %1%。" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "缺失所需属性 '%s' 。" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "需要 '%s' 或 '%s' 属性中的一项或两项。" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "签名校验失败" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "软件包 %s 似乎在传输时损坏了。您想要重试检索吗?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "未能提供软件包 %s。您想要重试检索吗?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "Applydeltarpm 检查已失败。" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "Applydeltarpm 已失败。" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "服务插件不支持修改属性。" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "无法提供文件 '%s',软件源 '%s' 中找不到该文件" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "软件源中没有 url。" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "由'%3%' 文件标识的预期介质 %1%/%2% 内容为:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"来自软件包 %2%\n" +" 的文件\n" +" %1%\n" +" 与来自软件包 %3%\n" +" 的文件冲突" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"来自软件包 %2%\n" +" 的文件\n" +" %1%\n" +" 与安装自 %3%\n" +" 的文件冲突" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"安装自 %2%\n" +" 的文件\n" +" %1%\n" +" 与来自软件包 %3%\n" +" 的文件冲突" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"安装自 %2%\n" +" 的文件\n" +" %1%\n" +" 与安装自 %3%\n" +" 的文件冲突" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"来自软件包\n" +" %2%\n" +" 的文件 %1%\n" +" 与来自软件包\n" +" %4%\n" +" 的文件\n" +" %3% 冲突" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"来自软件包\n" +" %2%\n" +" 的文件 %1%\n" +" 与安装自\n" +" %4%\n" +" 的文件\n" +" %3% 冲突" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"安装自\n" +" %2%\n" +" 的文件 %1%\n" +" 与来自软件包\n" +" %4%\n" +" 的文件\n" +" %3% 冲突" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"安装自\n" +" %2%\n" +" 的文件 %1%\n" +" 与安装自\n" +" %4%\n" +" 的文件\n" +" %3% 冲突" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "无法创建 sat-pool。" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "通过忽略一些依赖关系来断开 %s" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "通常忽略一些依赖关系" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "安装的 %1% 不属于发行版升级源,必须替换" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "要安装的 %1% 不属于发行版升级源" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "安装的 %1% 的架构较低" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "要安装的 %1% 的架构较低" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "安装的 %1% 有问题" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "冲突的请求" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "一些依赖性问题" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "没有软件源能提供所请求的 \"%1%\"" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "您是否启用了全部所需的软件源?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "请求的软件包 %1% 不存在" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "不支持的请求" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "\"%1%\" 由系统提供,无法擦除" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% 不可安装" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "没有软件源能提供安装的 %2% 所需的 \"%1%\"" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "没有软件源能提供要安装的 %2% 所需的 \"%1%\"" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "无法同时安装 %1% 和 %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "安装的 %1% 与安装的 %3% 所提供的 \"%2%\" 冲突" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "安装的 %1% 与要安装的 %3% 所提供的 \"%2%\" 冲突" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "要安装的 %1% 与安装的 %3% 所提供的 \"%2%\" 冲突" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "要安装的 %1% 与要安装的 %3% 所提供的 \"%2%\" 冲突" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "安装的 %1% 会淘汰安装的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "安装的 %1% 会淘汰要安装的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "要安装的 %1% 会淘汰安装的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "要安装的 %1% 会淘汰要安装的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "安装的 %1% 与其自身所提供的 \"%2%\" 冲突" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "要安装的 %1% 与其自身所提供的 \"%2%\" 冲突" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "安装的 %1% 需要 \"%2%\",但无法满足此要求" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "要安装的 %1% 需要 \"%2%\",但无法满足此要求" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "已删除提供者: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"无法安装的提供者: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "无法安装的提供者: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% 尚未完全集成到 %2% 中。" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "通常情况下,您需要保留 PTF 并选择不安装维护补丁。" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "移除此环境中安装的 %1% 还会移除(而不是替换)包含的 PTF 软件包。" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"应通过调用 \"%1%\" 来移除 PTF。这样将会更新包含的 PTF 软件包,而不会将其移" +"除。" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "通常,您需要保留 PTF 并选择取消该操作。" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "已安装的 %1% 阻碍了期望进行的操作。" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "通常来说您会想要保留该暂时性修复并选择取消该操作。" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "移除锁定以允许移除 %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "不安装 %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "保留 %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "移除锁定以允许安装 %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "此请求将破坏您的系统!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "忽略损坏系统的警告" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "不询问就安装提供 %1% 的一个解析项" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "不询问就删除提供 %1% 的所有解析项" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "不安装最新版本的 %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "即使架构较低,仍保留 %1%" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "即使架构较低,仍安装 %1%" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "保留淘汰的 %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "安装来自排除的软件源的 %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "尽管 %1% 已被维护团队撤回,仍予以安装" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "允许安装暂时性修复 %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "尽管 %1% 已列入黑名单,仍予以安装" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "将 %1% 降级到 %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "架构从 %1% 变为 %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"安装 %1%(并更改厂商)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"由供应商 %2% 安装 %1% 代替\n" +"由供应商 %4% 安装 %3%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "将 %1% 用 %2% 取代" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "卸载 %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "运行事务后脚本" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "正在运行 %1% 脚本" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "%1% 脚本输出:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "安装已按指示中止。" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " 已执行" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " 执行失败" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s 早已作为 %s 执行了)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " 中止时跳过执行" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "发送更新消息通知出错。" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "新更新消息" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" +"接收到信号:\"%1% (%2%)\",为了确保系统一致性,无法取消正在运行的 RPM 事务。" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "由于以下问题执行操作失败:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM 失败: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "从文件 %1% 中导入公钥失败" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "移除公钥 %1% 失败" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "软件包包头未签名!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "软件包数据体未签名!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s 配置文件有变化:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm 已将 %s 另存为 %s,但是无法确定两者的差异" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm 已将 %s 另存为 %s。\n" +"以下是前 25 行差异:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm 已将 %s 创建为 %s,但是无法确定两者的差异" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm 已将 %s 创建为 %s。\n" +"以下是前 25 行差异:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "额外的 RPM 输出" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "已创建备份 %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "签名正确" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "未知签名类型" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "无法校验签名" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "签名正确,但密钥是非受信的" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "签名公钥不可用" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "文件不存在或无法检查其签名" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "未签署文件" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "“%s”对 %u 属于错误类型,字节校验和“%s”" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "无法打开 pty (%s)。" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "无法打开管道 (%s)。" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "无效的 LDAP URL 查询字符串" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "无效的 LDAP URL 查询参数 '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "无法克隆 URL 对象" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "无效的空 URL 对象引用" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "无法解析 URL 组件" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "历史:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "URL 方案不允许使用 %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "无效的 %s 组件 '%s'" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "无效的 %s 组件" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "不支持解析此 URL 的查询字符串" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "URL 方案是一个必需组件" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "无效的 URL 方案 '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "URL 方案不允许使用用户名" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "URL 方案不允许使用密码" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "URL 方案要求有主机组件" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "URL 方案不允许使用主机组件" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "无效的主机组件 '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "URL 方案不允许使用端口" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "无效的端口组件 '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "URL 方案要求有路径名" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "若存在认证则不允许相对路径" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "编码的字符串包含了一个 NUL 字节" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "无效的参数数组分割的分隔符" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "无效的参数映射分割的分隔符" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "无效的参数数组合并的分隔符" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "命令退出,状态 %d。" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "命令已被信号 %d (%s) 杀死。" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "命令退出,未知错误。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "子参数无效。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "无法创建控制管道。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "无法 chroot 到 '%s' (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "无法 chdir 到 '%s' (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "无法 chdir 到 %s,它在 chroot %s (%s) 中。" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "无法执行 '%s' (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "无法派生 (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "无法执行 '%s',chdir 失败 (%s) 。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "无法执行 \"%s\",chroot 失败 (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "无法执行 '%s',执行失败 (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "无法执行 '%s',意外错误。" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "未能把 %s 挂载到 %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "卸载 %s 失败" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "文件名错误:%s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "当试图执行动作 '%s' 时,介质没有打开。" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "文件 '%s' 未在介质 '%s' 上找到" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "无法写入文件 '%s'。" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "介质未挂载" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "介质挂载点错误" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "下载(curl) '%s' 时初始化失败" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "系统例外 '%s'(发生于介质 '%s' 上)。" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "路径 '%s'(介质 '%s' 上)并不是一个文件。" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "路径 '%s'(介质 '%s' 上)并不是一个文件夹。" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "异常的 URI" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "URI 中主机名为空" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "URI 中文件系统为空" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "URI 中目标为空" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "不支持 '%s' 中的 URI 方案。" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "介质不支持此操作" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"下载 (curl) '%s' 出错:\n" +"错误代码:%s\n" +"错误消息:%s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "为 '%s' 设置下载 (curl) 选项时出错:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "介质来源 '%s' 不包含期望的介质" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "介质 '%s' 正被另一个实例使用" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "无法弹出任何介质" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "无法弹出介质 '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "访问 '%s' 的准入请求被拒绝。" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "访问 '%s' 时超时。" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "下载到的数据超出了预期文件大小 '%s'/'%s'。" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "位置 '%s' 暂时无法访问。" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL 证书问题,请校验 '%s' 的 CA 证书。" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "没有可供挂接媒体的免费资源。" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "不支持 HTTP 认证方法 '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"下载 (curl) \"%s\" 时发生错误:\n" +"错误代码:%s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"下载 (curl) \"%s\" 时发生错误:\n" +"无法检索 HTTP 响应\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "是" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "否" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "备注:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "警告:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "错误:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "完毕" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "注意" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "错误" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "警告: " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "正在检索:" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "正在启动" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "未找到" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "此提示无可用帮助。" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "此选项无可用帮助" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "显示全部选项" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "是" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "否" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "正在执行 %%posttrans 脚本“%1%”" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "正在执行 %p osttrans 脚本" + +#~ msgid "Package is not signed!" +#~ msgstr "未签署包!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s 不属于发行版升级源" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s 架构不对应" + +#~ msgid "problem with installed package %s" +#~ msgstr "已安装的 %s 软件包有问题" + +#~ msgid "nothing provides requested %s" +#~ msgstr "没有什么能提供所需的 %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "您启用了全部请求的软件源了吗?" + +#~ msgid "package %s does not exist" +#~ msgstr "软件包 %s 不存在" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s 由系统提供,无法擦除" + +#~ msgid "%s is not installable" +#~ msgstr "%s 不可安装" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "没有什么能提供 %s,而它为 %s 所需" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "无法同时安装 %s 和 %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s 与 %s 冲突,后者由 %s 提供" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s 淘汰了 %s,后者由 %s 提供" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "已安装的 %s 淘汰了 %s,后者由 %s 提供" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "可解析项 %s 与自身提供的 %s 冲突" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s 需要 %s,但无法满足此需求" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "移除锁定以允许移除 %s" + +#~ msgid "do not install %s" +#~ msgstr "不安装 %s" + +#~ msgid "keep %s" +#~ msgstr "保留 %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "移除锁定以允许安装 %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "不询问就安装一个提供 %s 的解析项" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "不询问就删除全部提供 %s 的解析项" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "不安装最新版本的 %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "保留 %s,即使架构不对应" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "尽管架构不对应仍安装 %s" + +#~ msgid "keep obsolete %s" +#~ msgstr "保留已淘汰的 %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "从排除的软件源安装 %s" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "降级 %s 到 %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "架构从 %s 变更到 %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "安装 %s(包括厂商变更)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "将 %s 用 %s 取代" + +#~ msgid "deinstallation of %s" +#~ msgstr "卸载 %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "无法打开锁定文件:%s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "此动作正在由另一个程序运行着。" + +#~ msgid "Hal Exception" +#~ msgstr "Hal 例外" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "对不起,本版 libzypp 没有编译 HAL 支持。" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext 未连接" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive 未初始化" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume 未初始化" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "无法创建 dbus 连接" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new:无法创建 libhal 环境" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection:无法设置 dbus 连接" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "无法初始化 HAL 环境 - hald 未运行?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "不是 CDROM 驱动器" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "无法初始化 mutex 属性" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "无法设置递归的 mutex 属性" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "无法初始化递归的 mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "无法获取 mutex 锁定" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "无法释放 mutex 锁定" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "从文件 %s 中导入公钥失败:%s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "移除公钥 %s 失败:%s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "找不到可用 loop 设备以挂载来自 '%s' 的映像文件" + +#~ msgid "do not keep %s installed" +#~ msgstr "不保留 %s" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "无法创建公共密钥 %s, 该密钥来自 %s 钥匙环,准备创建到 %s 文件" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "下载 (Metalink curl) '%s' 时初始化失败" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "下载 (metalink curl) '%s' 出错:\n" +#~ "错误代码:%s\n" +#~ "错误消息:%s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "下载在 %d%% 中断" + +#~ msgid "Download interrupted by user" +#~ msgstr "下载被用户中断" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "为 '%s' 设置下载 (metalink curl) 选项时出错:" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "下载 %s 从 %s 时失败" diff --git a/po/zh_TW.po b/po/zh_TW.po new file mode 100644 index 0000000..633a7a6 --- /dev/null +++ b/po/zh_TW.po @@ -0,0 +1,5484 @@ +# translation of zypp.po to Chinese Traditional +# Chinese message file for YaST2 (@memory@). -*- coding: utf-8 -*- +# Copyright (C) 2005 SUSE Linux Products GmbH. +# Copyright (C) 2002 SuSE Linux AG. +# Copyright (C) 2001 SuSE GmbH. +# swyear , 2008, 2009, 2011. +# Ray Chen , 2012. +# Ramax Lo , 2014. +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2024-04-30 05:43+0000\n" +"Last-Translator: Grace Yu \n" +"Language-Team: Chinese (Taiwan) \n" +"Language: zh_TW\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=1; plural=0;\n" +"X-Generator: Weblate 4.9.1\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "未知國家:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "沒有程式碼" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "安道爾" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "阿拉伯聯合大公國" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "阿富汗" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "安地卡及巴布達" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "安圭拉島" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "阿爾巴尼亞" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "亞美尼亞" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "荷屬安第列斯群島" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "安哥拉" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "南極洲" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "阿根廷" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "美屬薩摩亞" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "奧地利" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "澳大利亞" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "阿魯巴" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "愛蘭群島" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "亞塞拜然" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "波士尼亞與赫塞哥維納" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "巴貝多" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "孟加拉共和國" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "比利時" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "布基那法索" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "保加利亞" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "巴林" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "蒲隆地" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "貝南" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "百慕達" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "汶萊" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "玻利維亞" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "巴西" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "巴哈馬" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "不丹" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "布維特島" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "波紮那" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "白俄羅斯" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "貝里斯" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "加拿大" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "科科斯群島" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "剛果" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "中非共和國" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "瑞士" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "象牙海岸" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "庫克群島" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "智利" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "喀麥隆" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "中國" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "哥倫比亞" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "哥斯大黎加" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "古巴" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "維德角" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "聖誕島" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "塞普勒斯" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "捷克共和國" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "德國" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "吉布地" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "丹麥" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "多米尼克" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "多明尼加共和國" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "阿爾及利亞" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "厄瓜多爾" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "愛沙尼亞" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "埃及" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "西撒哈拉" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "厄立特里亞" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "西班牙" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "衣索比亞" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "芬蘭" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "斐濟" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "英屬福克蘭群島 (馬爾維納斯群島)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "密克羅尼西亞聯邦" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "法羅群島" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "法國" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "法屬美特羅波利坦" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "加彭" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "英國" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "格瑞納達" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "喬治亞" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "法屬圭亞納" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "格恩西" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "迦納" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "直布羅陀" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "格林蘭島" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "甘比亞" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "幾內亞" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "哥德洛普島 (法屬)" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "赤道幾內亞" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "希臘" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "南喬治亞及南三明治群島" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "瓜地馬拉" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "關島" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "幾內亞比紹" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "蓋亞那" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "香港" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "赫德及麥當勞群島" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "宏都拉斯" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "克羅埃西亞共和國" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "海地" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "匈牙利" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "印尼" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "愛爾蘭" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "以色列" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "馬恩島" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "印度" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "英屬印度洋領土" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "伊拉克" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "伊朗" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "冰島" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "義大利" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "澤西" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "牙買加" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "約旦" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "日本" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "肯亞" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "吉爾吉斯" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "柬埔寨" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "吉里巴斯共和國" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "葛摩" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "聖克里斯多福及尼維斯" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "北韓" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "南韓" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "科威特" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "開曼群島" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "哈薩克" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "寮人民民主共和國" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "黎巴嫩" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "聖露西亞" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "列支敦斯登" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "斯里蘭卡" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "賴比瑞亞" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "賴索托" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "立陶宛" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "盧森堡" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "拉脫維亞" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "利比亞" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "摩洛哥" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "摩納哥" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "摩爾多瓦" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "芒特尼格羅共和國" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "聖馬丁" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "馬達加斯加" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "馬紹爾群島" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "馬其頓" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "馬利" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "緬甸" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "蒙古" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "澳門" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "北馬里安納群島" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "馬丁尼克" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "茅利塔尼亞" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "蒙特色拉特島" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "馬爾他" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "模里西斯" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "馬爾地夫" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "馬拉威" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "墨西哥" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "馬來西亞" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "莫三比克" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "那米比亞" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "新喀里多尼亞群島" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "尼日" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "諾福克島" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "奈及利亞" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "尼加拉瓜" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "荷蘭" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "挪威" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "尼泊爾" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "諾魯" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "紐威島" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "紐西蘭" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "阿曼" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "巴拿馬" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "祕魯" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "法屬波里尼西亞" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "巴布亞新幾內亞" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "菲律賓" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "巴基斯坦" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "波蘭" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "聖匹島" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "皮特康" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "波多黎各" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "巴勒斯坦領土" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "葡萄牙" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "帛琉" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "巴拉圭" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "卡達" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "留尼旺島" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "羅馬尼亞" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "塞爾維亞" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "俄羅斯聯邦" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "盧安達" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "沙烏地阿拉伯" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "所羅門群島" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "塞席爾群島" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "蘇丹" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "瑞典" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "新加坡" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "聖赫勒拿島" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "斯洛維尼亞共和國" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "冷岸及央棉群島" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "斯洛伐克" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "獅子山" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "聖馬力諾" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "塞內加爾" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "索馬利亞" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "蘇利南" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "聖多美普林西比" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "薩爾瓦多" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "敘利亞" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "史瓦濟蘭" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "土克斯及開科斯群島" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "查德" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "法國南方領土" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "多哥" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "泰國" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "塔吉克" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "托克勞群島" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "土庫曼" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "突尼西亞" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "東加" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "東帝汶" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "土耳其" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "千里達托貝哥" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "吐瓦魯" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "台灣" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "坦尚尼亞" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "烏克蘭" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "烏干達" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "美國外島" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "美國" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "烏拉圭" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "烏茲別克" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "羅馬教庭 (梵蒂岡)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "聖文森及格瑞那丁" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "委內瑞拉" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "英屬維爾京群島" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "美屬維爾京群島" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "越南" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "萬那杜" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "瓦利斯及福杜納群島" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "薩摩亞" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "葉門" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "馬約特島" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "南非" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "尚比亞" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "辛巴威" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "提供" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "先決條件" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "需要" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "衝突" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "汰換" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "建議" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "推薦" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "增強" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "補充" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "嘗試將不存在的金鑰 %s 匯入金鑰圈 %s" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "輸入金鑰失敗。" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "刪除金鑰失敗。" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "找不到簽章檔 %s" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "未知的語言:" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "阿法爾語" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "阿布哈西亞語" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "亞齊語" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "阿科利語" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "阿當梅語" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "阿迪格語" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "非洲-亞洲 (其他)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "阿弗裡希利語" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "南非荷蘭語" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "艾奴語" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "阿坎語" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "阿卡德語" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "阿爾巴尼亞語" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "阿留申語" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "亞爾岡京語言" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "南方阿爾泰語" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "阿姆哈拉語" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "英語,舊 (大約450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "阿帕契語" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "阿拉伯語" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "阿拉姆語" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "阿拉貢語" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "亞美尼亞語" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "阿勞坎語" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "阿拉帕霍語" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "人為的 (其他)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "阿拉瓦克語" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "阿薩姆語" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "阿斯圖里亞語" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "阿薩巴斯卡語" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "澳大利亞語" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "阿瓦爾語" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "阿維斯陀語" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "阿沃提語" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "艾馬拉語" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "亞塞拜然語" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "班達語" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "巴米累克語" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "巴什克爾語" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "巴路奇語" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "班巴拉語" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "巴里語" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "巴斯克語" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "巴沙語" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "波羅的語 (其他)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "白廈語" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "白俄羅斯語" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "曼巴語" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "孟加拉語" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "柏柏爾語 (其他)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "波布里語" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "比哈爾語" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "比口語" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "比尼語" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "比斯拉馬語" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "西克西卡" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "班圖語 (其他)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "波士尼亞語" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "布拉吉語" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "不列塔尼語" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "巴塔克語 (印尼)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "白雅特語" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "布吉斯語" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "保加利亞語" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "緬甸語" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "伯林語" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "凱多語" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "中美洲印地安 (其他)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "加勒比語" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "嘉泰羅尼亞語" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "高加索語 (其他)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "宿霧語" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "賽爾特語 (其他)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "查摩洛語" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "奇布查語" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "車臣語" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "察合臺語" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "中文" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "夏克島語" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "麻里語" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "契奴克語" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "喬克托語" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "奇帕維安語" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "卻洛奇文" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "教會斯拉夫語" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "楚瓦士語" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "薜安語" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "占米克語" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "科普特語" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "康瓦耳語" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "科西嘉語" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "克瑞奧里語與皮欽語,英國型 (其他)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "克瑞奧里語與皮欽語,法國型 (其他)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "克瑞奧里語與皮欽語,葡萄牙型 (其他)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "克里語" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "克裡米亞韃靼語" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "克瑞奧里語與皮欽語 (其他)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "卡舒布語" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "庫希迪克語 (其他)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "捷克語" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "達科他語" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "丹麥語" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "達爾格瓦語" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "達雅克語" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "德拉瓦語" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "斯拉夫語 (阿薩巴斯卡)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "多格里布語" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "丁卡語" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "迪韋西語" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "多格里語" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "達羅毗荼語 (其他)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "下文德語" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "杜阿拉語" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "荷蘭語,中古世紀 (大約1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "荷蘭語" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "迪尤拉語" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "宗卡語" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "艾非克語" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "埃及語 (古代)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "艾卡朱克語" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "艾拉米特語" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "英語" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "英文,中古世紀 (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "世界語" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "愛沙尼亞語" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "埃維語" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "埃翁多語" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "芳族語" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "法羅語" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "芳蒂語" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "斐濟語" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "菲律賓語" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "芬蘭語" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "芬匈語 (其他)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "豐語" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "法語" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "法語,中古世紀 (大約1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "法語,舊 (842-大約1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "弗利然語" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "富拉語" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "弗留利語" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "咖語" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "咖幼語" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "格巴亞語" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "日耳曼語 (其他)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "喬治亞文" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "德語" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "吉茲語" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "吉伯特語" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "蓋爾語" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "愛爾蘭語" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "加利西亞語" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "曼島語" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "德語,中古世紀 (大約1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "德語,古代 (大約750-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "岡德語" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "哥倫打洛語" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "哥德語" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "格列博語" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "希臘語,古代 (至 1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "希臘語,現代 (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "瓜拉尼語" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "古吉拉特文" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "哥威迅語" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "海達語" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "海提語" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "豪薩語" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "夏威夷語" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "希伯來文" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "赫雷羅語" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "希利蓋農語" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "赫馬查理語" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "北印度語" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "西台語" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "赫蒙語" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "希裡莫圖語" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "高地索布語" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "匈牙利語" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "胡帕語" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "伊班語" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "伊博語" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "冰島語" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "伊多語" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "西川易語" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "伊喬語" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "伊奴伊特語" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "人工國際語" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "伊洛幹諾語" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "英特林瓜語 (國際輔助語)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "印度語 (其他)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "印尼語" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "印歐語 (其他)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "印古什語" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "因努皮雅克語" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "伊朗語 (其他)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "伊洛古歐安語" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "義大利語" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "爪哇語" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "邏輯語" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "日語" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "猶太-波斯語" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "猶太-阿拉伯語" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "卡拉卡爾帕克語" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "卡拜爾語" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "卡欽語" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "卡拉利蘇特語" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "卡姆帕語" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "坎那達文" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "克倫語" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "喀什米爾語" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "卡努里語" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "卡威語" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "哈薩克語" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "卡巴爾達語" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "卡西語" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "科依桑語 (其他)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "高棉文" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "和闐語" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "吉庫猶語" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "金雅爾王達語" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "吉爾吉斯語" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "金本杜語" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "剛卡尼語" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "科密語" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "剛果語" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "韓語" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "科西嘉語" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "克帕勒語" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "卡拉契巴卡語" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "克魯語" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "庫魯科語" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "夸尼雅馬語" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "庫密克語" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "庫德語" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "庫特內語" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "拉第諾語" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "拉亨達語" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "蘭姆巴語" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "寮文" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "拉丁文" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "拉脫維亞語" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "雷格西安語" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "林柏格安語" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "林加拉語" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "立陶宛語" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "蒙古語" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "羅利語" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "盧森堡語" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "盧巴盧路拉語" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "盧巴卡丹咖語" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "干達語" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "盧伊塞諾語" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "隆達語" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "盧奧語 (肯亞與坦桑尼亞)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "盧夏語" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "馬其頓語" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "馬都拉語" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "馬加伊語" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "馬紹爾語" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "彌濕羅語" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "滿加撒語" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "馬來亞拉姆文" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "曼丁果語" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "毛利語" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "南島語系 (其他)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "馬拉地語" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "馬塞語" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "馬來語" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "莫克夏語" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "門德語" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "門迪語" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "愛爾蘭語,中古世紀 (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "密克馬克語" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "米南卡保語" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "其他語言" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "孟-高棉語 (其他)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "馬拉加西語" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "馬爾他語" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "滿族語" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "曼利普裏語" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "馬諾伯語" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "摩哈克語" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "摩爾達維亞語" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "蒙古文" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "莫西語" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "多重語言" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "蒙達語" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "克里克語" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "米蘭德斯語" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "馬爾瓦爾語" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "瑪雅語" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "愛斯亞語" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "那瓦特語" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "北美印地安" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "紐波利頓語" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "納瓦伙語" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "南恩德貝勒語" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "北恩德貝勒語" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "恩敦加語" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "低地德語" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "尼泊爾語" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "尼伯爾跋娑語" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "尼亞斯語" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "尼日-科爾多凡語 (其他)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "紐埃語" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "挪威耐諾斯克語" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "挪威巴克摩語" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "諾蓋語" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "古諾爾斯語" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "挪威語" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "北索索語" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "努比亞語" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "尼瓦爾語" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "齊切瓦語" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "尼揚韋齊語" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "尼揚科萊語" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "尼奧羅語" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "恩濟馬語" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "奧克騰語 (1500 之後)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "奧吉布瓦語" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "歐利亞文" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "歐羅摩語" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "歐塞奇語" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "奧塞梯語" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "土耳其,鄂圖曼 (1500-1928)" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "鄂圖曼語" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "巴布亞語 (其他)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "邦卡西南語" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "巴勒維語" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "邦幫咖語" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "旁遮普語" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "帕皮阿門托語" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "帛琉語" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "古波斯語 (大約西元前 600-400)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "波斯語" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "菲律賓語 (其他)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "腓尼基語" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "巴利語" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "波蘭語" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "波那貝語" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "葡萄牙語" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "普拉克里特語" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "古普羅凡斯語 (至 1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "普什圖語" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "蓋楚瓦語" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "拉賈斯坦語" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "拉巴怒伊語" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "拉羅通加語" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "羅曼語 (其他)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "里托羅曼語" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "羅曼尼語" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "羅馬尼亞語" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "隆迪語" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "俄語" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "桑達韋語" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "桑戈語" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "雅庫特語" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "南美洲印地安 (其他)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "薩利什語" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "薩瑪利亞語" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "梵語" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "沙沙克語" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "山塔利語" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "塞爾維亞語" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "西西里語" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "蘇格蘭語" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "克羅埃西亞語" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "瑟爾卡普語" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "閃語 (其他)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "古愛爾蘭語 (至 900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "符號語言" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "撣語" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "希達摩語" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "錫蘭文" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "蘇語語系" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "漢藏語 (其他)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "斯拉夫語 (其他)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "斯洛伐克語" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "斯洛維尼亞語" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "南薩米語" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "北薩米語" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "薩米語 (其他)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "魯爾薩米語" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "伊納里薩米語" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "薩摩亞語" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "斯克特薩米語" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "紹納語" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "信德語" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "索寧克語" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "粟特語" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "索馬利語" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "桑海語" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "南索索語" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "西班牙語" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "薩丁尼亞語" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "塞雷爾語" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "尼羅--撒哈拉語 (其他)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "斯瓦特語" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "蘇庫馬語" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "巽他語" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "蘇蘇語" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "蘇美語" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "斯華西里語" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "瑞典語" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "敘利亞文" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "塔希提語" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "泰語 (其他)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "坦米爾文" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "韃靼語" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "特拉古文" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "堤姆奈語" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "特崙諾語" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "德頓語" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "塔吉克語" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "塔加拉族語" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "泰文" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "西藏文" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "泰格瑞語" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "提格利尼亞語" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "提夫語" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "克林貢語" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "特林吉特語" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "泰瑪歇克語" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "東加語 (尼亞沙)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "東加語 (東加群島)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "托比辛語" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "欽西安語" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "班圖語" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "聰加語" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "土庫曼語" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "通布卡語" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "圖皮語" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "土耳其語" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "阿爾泰語 (其他)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "契維語" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "圖瓦尼安語" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "烏德穆爾特語" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "烏嘎利特語" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "維吾爾語" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "烏克蘭語" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "姆崩杜語" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "未確定的" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "烏都語" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "烏茲別克語" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "埃語" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "溫達語" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "越南語" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "沃拉普克語" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "沃提克語" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "瓦卡時語" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "瓦拉莫語" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "瓦瑞語" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "瓦紹語" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "威爾斯語" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "索布語" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "瓦隆語" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "沃洛夫語" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "卡爾梅克語" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "科薩語" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "瑤語" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "雅蒲語" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "意第緒語" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "優魯巴語" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "尤皮克語" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "薩波特克語" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "澤納加語" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "壯語" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "贊德語" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "祖魯語" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "祖尼語" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "將執行以下操作:" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "不過期" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "過期日期:%1%" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "過期日期:%1%" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "(未過期)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "(已過期)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "(在 24 小時內過期)" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "(在 %d 天內過期)" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "不明的" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "不支援" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "層級 1" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "層級 2" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "層級 3" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "需要額外的使用者授權" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "已停產且已被另一個套件取代" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "不適用" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "支援的等級未指定" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "此廠商不提供支援。" + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" +"問題判斷,意指提供相依性資訊、安裝協助、用法支援、持續維護及基本錯誤排除的技" +"術支援。層級 1 支援並不提供產品缺失錯誤的更正。" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" +"問題隔離,意指複製客戶問題、隔離問題區域並提供層級 1 支援無法解決的方案的技術" +"支援。" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" +"問題解決,意指透過工程方法解決層級 2 支援所確認的產品缺陷來解決複雜問題的技術" +"支援。" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "要取得支援,需要額外的使用者授權。" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "該套件已停產,一個使用其他名稱的新套件已將其取代。" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "未知的支援選項。 描述不適用" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" +"系統管理已被 pid 為 %d (%s) 的應用程式鎖定。\n" +"請關閉此應用程式,然後重試。" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "未知的符合模式 '%s'" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "未知的符合模式 '%s' (針對樣式 '%s')" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "無效的正規表示法 '%s'︰regcomp 傳回 %d" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "無效的正規表示法 '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "%s 需要驗證" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "將重試..." + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "已嘗試 %1% 次,即將放棄。" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "造訪 SUSE Customer Center 以檢查您的註冊是否有效以及是否過期。" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "請造訪 Novell Customer Center,檢查您的註冊是否有效且是否未過期。" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "建立裝載點:無法找到可寫入的目錄以建立裝載點" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "請先安裝套件 'lsof'。" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "無法建立中繼資料快取目錄。" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "嘗試自 '%s' 讀取時發生錯誤" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "無法建立 %s" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "在指定的 URL 中找不到有效的中繼資訊" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "快取套件庫失敗 (%d)。" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "正在建立套件庫 '%s' 的快取" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "無法在 %s 建立快取 - 無寫入權限。" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "無法處理的套件庫類型" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "正在新增套件庫 '%s'" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "'%s' 處的套件庫檔案名稱無效" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "無法開啟檔案 '%s' 來寫入。" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "由 '%s' 讀取時發生未知錯誤" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "無法讀取套件庫目錄 '%1%'︰權限遭拒" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "無法讀取目錄 '%s'" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "無法讀取套件庫檔案 '%1%'︰權限遭拒" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "正在移除套件庫 '%s'" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "無法找到套件庫儲存的位置。" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "無法刪除 '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "無法找到服務儲存的位置。" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "未知的服務 '%1%':正在移除落單的服務儲存庫 '%2%'" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "套件庫別名不能以點開始。" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "服務的別名不能以點開始。" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "檔案 %s 無摘要。" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "未知摘要 %s (檔案 %s)。" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "檔案 '%s' 的摘要驗證失敗" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "檔案 '%s' 未經簽署,要繼續嗎?" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "檔案 '%s' (來自儲存庫 '%s') 未經簽署,要繼續嗎?" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "您想要拒絕該金鑰、暫時信任還是永遠信任該金鑰?" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "金鑰名稱:%1%" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "從儲存庫 \"%2%\" 中收到 %1% 個新的套件簽署金鑰:" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "檔案 '%1%' 的簽名驗證失敗。" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "對儲存庫 '%2%' 中的檔案 '%1%' 的簽名驗證失敗。" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "要繼續嗎?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "檔案 '%s' 經未知金鑰 '%s' 簽署。要繼續嗎?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "檔案 '%s' (來自儲存庫 '%s') 經未知金鑰 '%s' 簽署。要繼續嗎?" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "套件庫 %1% 未定義額外的 'gpgkey=' URL。" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "尋找套件庫 %2% 中的 gpg 金鑰 ID %1%。" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "尋找快取 %2% 中的 gpg 金鑰 ID %1%。" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "需要的屬性 '%s' 遺失。" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "需要 '%s' 及 '%s' 屬性或兩者之一。" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "簽章驗證失敗" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "套件 %s 可能在傳輸期間已毀損。是否要重試取回操作?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "無法提供套件 %s。是否要重試取回操作?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "applydeltarpm 檢查失敗。" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "applydeltarpm 失敗。" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "服務外掛不支援屬性的修改。" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "檔案 '%s' 無法由套件庫 '%s' 提供" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "套件庫中沒有 url。" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "檔案 \"%3%\" 所識別的媒體 %1%/%2% 內容應為:" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"檔案 %1%\n" +" (來自以下套件\n" +" %2%)\n" +" 與來自下列套件的檔案相衝突\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"檔案 %1%\n" +" (來自以下套件\n" +" %2%)\n" +" 與來自下列安裝的檔案相衝突\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" +"檔案 %1%\n" +" (來自以下安裝\n" +" %2%)\n" +" 與來自下列套件的檔案相衝突\n" +" %3%" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" +"檔案 %1%\n" +" (來自以下安裝\n" +" %2%)\n" +" 與來自下列安裝的檔案相衝突\n" +" %3%" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"檔案 %1%\n" +" (來自以下套件\n" +" %2%)\n" +" 與下列檔案相衝突\n" +" %3%\n" +" (來自以下套件\n" +" %4%)" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"檔案 %1%\n" +" (來自以下套件\n" +" %2%)\n" +" 與下列檔案相衝突\n" +" %3%\n" +" (來自以下安裝\n" +" %4%)" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" +"檔案 %1%\n" +" (來自以下安裝\n" +" %2%)\n" +" 與下列檔案發生衝突\n" +" %3%\n" +" (來自以下套件\n" +" %4%)" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" +"檔案 %1%\n" +" (來自以下的安裝\n" +" %2%)\n" +" 與下列檔案發生衝突\n" +" %3%\n" +" (來自以下的安裝\n" +" %4%)" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "無法建立 sat-pool。" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "藉由忽略它的某些相依性以破壞 %s" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "一般忽略某些相依性" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "安裝的 %1% 不屬於版本升級套件庫,必須將其取代" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "要安裝的 %1% 不屬於版本升級套件庫" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "安裝的 %1% 的架構較低" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "要安裝的 %1% 的架構較低" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "安裝的 %1% 有問題" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "衝突的要求" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "一些相依性問題" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "沒有套件庫能提供所申請的 \"%1%\"" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "您是否啟用了全部所需的套件庫?" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "申請的套件 %1% 不存在" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "不支援的要求" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "\"%1%\" 由系統提供,無法去除" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "%1% 不可安裝" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "沒有套件庫能提供安裝的 %2% 所需的 \"%1%\"" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "沒有套件庫能提供要安裝的 %2% 所需的 \"%1%\"" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "無法同時安裝 %1% 和 %2%" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "安裝的 %1% 與安裝的 %3% 所提供的 \"%2%\" 衝突" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "安裝的 %1% 與要安裝的 %3% 所提供的 \"%2%\" 衝突" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "要安裝的 %1% 與安裝的 %3% 所提供的 \"%2%\" 衝突" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "要安裝的 %1% 與要安裝的 %3% 所提供的 \"%2%\" 衝突" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "安裝的 %1% 會汰換安裝的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "安裝的 %1% 會汰換要安裝的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "要安裝的 %1% 會汰換安裝的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "要安裝的 %1% 會汰換要安裝的 %3% 所提供的 \"%2%\"" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "安裝的 %1% 與其自身所提供的 \"%2%\" 衝突" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "要安裝的 %1% 與其自身所提供的 \"%2%\" 衝突" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "安裝的 %1% 需要 \"%2%\",但無法符合此要求" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "要安裝的 %1% 需要 \"%2%\",但無法符合此要求" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "已刪除的提供者: " + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" +"\n" +"無法安裝的提供者: " + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "無法安裝的提供者: " + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "%1% 尚未完全整合到 %2% 中。" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "通常情況下,您需要保留 PTF 並選擇不安裝維護修補程式。" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "移除此網路位置中安裝的 %1% 還會移除 (而不是取代) 包含的 PTF 套件。" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" +"應透過呼叫 \"%1%\" 來移除 PTF。這樣將會更新包含的 PTF 套件,而不會將其移除。" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "通常,您需要保留 PTF 並選擇取消該動作。" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "安裝的 %1% 封鎖了所需的動作。" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "通常情況下,您需要保留 PTF 並選擇取消動作。" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "移除鎖定以允許移除 %1%" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "不安裝 %1%" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "保留 %1%" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "移除鎖定以允許安裝 %1%" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "此要求將會破壞您的系統!" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "忽略損毀系統的警告" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "不詢問即安裝提供 %1% 的解決方案" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "不詢問即刪除提供 %1% 的所有解決方案" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "不安裝最新版本的 %1%" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "即使架構較低,仍保留 %1%" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "即使架構較低,仍安裝 %1%" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "保留汰換的 %1%" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "安裝來自已排除套件庫的 %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "儘管 %1% 已收回,仍予以安裝" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "允許安裝 PTF %1%" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "儘管 %1% 已列入黑名單,仍予以安裝" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "將 %1% 降級到 %2%" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "架構從 %1% 變更為 %2%" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" +"安裝 %1% (並變更廠商)\n" +" %2% --> %3%" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" +"安裝來自廠商 %2% 的 %1%\n" +" 取代廠商 %4% 的 %3%" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "以 %2% 取代 %1%" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "解除安裝 %1%" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "執行交易後程序檔" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "正在執行 %1% 程序檔" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "%1% 程序檔輸出:" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "安裝已如指示中止。" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr " 已執行" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr " 執行失敗" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "%s 已作為 %s 執行)" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr " 中止時跳過執行" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "發送更新訊息提醒失敗。" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "新的更新提醒" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "接收到訊號:\"%1% (%2%)\",為確保系統一致性,無法取消執行中 RPM 交易。" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "由於出現以下問題,執行交易失敗:" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "RPM 失敗: " + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "從檔案 %1% 輸入公用金鑰失敗" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "移除公用金鑰 %1% 失敗" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "未簽署套件標頭!" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "未簽署套件封包內容!" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "%s 的已變更組態檔:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "rpm 已將 %s 儲存為 %s,但看不出差異" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm 已將 %s 儲存為 %s。\n" +"這是前 25 行差異:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "rpm 已將 %s 建立為 %s,但看不出差異" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"rpm 已將 %s 建立為 %s。\n" +"這是前 25 行差異:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "其他 rpm 輸出" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "已建立備份 %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "簽章驗證正確" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "未知的簽章類型" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "簽章無法驗證" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "簽章驗證正確,然而金鑰是不被信任的" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "簽章用的公開金鑰不存在" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "檔案不存在或是簽章無法驗證" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "檔案未簽章" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "可疑的類型 '%s' (%u 位元組檢查總數 '%s')" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "無法開啟 pty (%s)。" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "無法開啟管線 (%s)。" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "無效的 LDAP URL 查詢字串" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "無效的 LDAP URL 查詢參數「%s」" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "無法複製 Url 物件" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "無效的空白 Url 物件參照" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "無法剖析 Url 元件" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "歷史記錄:" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Url 規劃不允許 %s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "無效的 %s 元件「%s」" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "無效的 %s 元件" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "æ­¤ URL 不支援查詢字串剖析" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Url 規劃為必要元件" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "無效的 Url 規劃「%s」" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Url 規劃不允許使用者名稱" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Url 規劃不允許密碼" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Url 規劃中必須要有主機元件" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Url 規劃不允許主機元件" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "無效的主機元件「%s」" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Url 規劃不允許連接埠" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "無效的連接埠元件 '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Url 規劃必須要有路徑名稱" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "如果授權存在,則不允許相對路徑" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "編碼字串包含 NUL 位元組" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "無效的參數陣列分割分隔符號字元" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "無效的參數映射分割分隔符號字元" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "無效的參數陣列加入分隔符號字元" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "指令跳出,狀態 %d。" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "指令被信號 %d (%s) 中止。" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "因未知錯誤指令跳出。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "指定了無效的衍生引數。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "無法建立控制管線。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "無法 chroot 到 '%s' (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "無法切換目錄到 '%s' (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "無法切換目錄到 '%s' (在 chroot '%s' 中) (%s)。" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "無法執行 '%s' (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "無法 fork (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "無法執行 \"%s\",chdir 失敗 (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "無法執行 \"%s\",chroot 失敗 (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "無法執行 \"%s\",exec 失敗 (%s)。" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "無法執行 \"%s\",發生非預期的錯誤。" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "無法將 %s 載掛到 %s" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "卸載 %s 失敗" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "無效的檔案名稱︰%s" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "嘗試執行動作 '%s' 時未開啟媒體。" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "檔案 '%s' 無法在媒體 '%s' 中找到" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "無法寫入檔案 '%s'。" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "媒體未加入" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "無效的媒體附載點" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "'%s' 下載 (curl) 初始化失敗" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "發生系統例外 '%s' (在媒體 '%s' 上)。" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "路徑「%s」(媒體「%s」上) 不是檔案。" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "路徑 '%s' (媒體 '%s' 上) 不是目錄。" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "格式錯誤的位址" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "位址中的主機名稱為空" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "位址中的檔案系統為空" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "位址中的目標為空" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "'%s' 中存在不受支援的位址規劃。" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "媒體不支援此操作" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" +"'%s' 下載 (curl) 錯誤:\n" +"錯誤碼:%s\n" +"錯誤訊息:%s\n" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "為 '%s' 設定下載 (curl) 選項時發生錯誤:" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "媒體來源 '%s' 不包含所需的媒體" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "媒體 '%s' 正被其他例項使用" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "無法退出任何媒體" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "無法退出媒體 '%s'" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "存取 '%s' 的權限被拒絕。" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "存取 '%s' 時超出限定時間。" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "下載到的資料超出了預期檔案大小 %s/%s。" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "位置 '%s' 暫時無法存取。" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr " SSL 憑證問題,驗證 '%s' 的 CA 憑證是否正確。" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "沒有可供連接媒體的免費資源。" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "不支援的 HTTP 驗證方式 '%s'" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" +"下載 (curl) \"%s\" 時發生錯誤:\n" +"錯誤代碼:%s\n" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" +"下載 (curl) \"%s\" 時發生錯誤:\n" +"無法擷取 HTTP 回應\n" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "是" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "否" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "注意:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "警告:" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "錯誤:" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "完成" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "注意" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "錯誤" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "警告︰ " + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "正在取回︰" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "正在啟動" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "找不到" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "此提示沒有可用說明。" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "此選項沒有說明訊息" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "顯示所有選項" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "是" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "否" + +#, boost-format +#~ msgid "Executing %%posttrans script '%1%'" +#~ msgstr "正在執行 %%posttrans 程序檔「%1%」" + +#, c-format, boost-format +#~ msgid "Executing %posttrans scripts" +#~ msgstr "正在執行 %p osttrans 程序檔" + +#~ msgid "Package is not signed!" +#~ msgstr "套件未簽章!" + +#~ msgid "%s does not belong to a distupgrade repository" +#~ msgstr "%s 不屬於版本升級套件庫" + +#~ msgid "%s has inferior architecture" +#~ msgstr "%s 有次要架構" + +#~ msgid "problem with installed package %s" +#~ msgstr "已安裝的套件 %s 發生問題" + +#~ msgid "nothing provides requested %s" +#~ msgstr "無法提供所需的 %s" + +#~ msgid "Have you enabled all requested repositories?" +#~ msgstr "是否已啟用所有需要的套件庫?" + +#~ msgid "package %s does not exist" +#~ msgstr "套件 %s 不存在" + +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s 由系統提供,無法清除" + +#~ msgid "%s is not installable" +#~ msgstr "%s 無法安裝" + +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "無法提供 %s (%s 需要此項目)" + +#~ msgid "cannot install both %s and %s" +#~ msgstr "無法同時安裝 %s 和 %s" + +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s 與 %s 衝突 (由 %s 提供)" + +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s 汰換 %s (由 %s 提供)" + +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "安裝的 %s 會汰換 %s (由 %s 提供)" + +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "解決方案 %s 與 %s 衝突 (由其自己提供)" + +#~ msgid "%s requires %s, but this requirement cannot be provided" +#~ msgstr "%s 需要 %s,但無法提供此需求" + +#~ msgid "remove lock to allow removal of %s" +#~ msgstr "解除鎖定以允許移除 %s" + +#~ msgid "do not install %s" +#~ msgstr "請勿安裝 %s" + +#~ msgid "keep %s" +#~ msgstr "保留 %s" + +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "解除鎖定以允許安裝 %s" + +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "請勿要求安裝提供 %s 的解決方案" + +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "請勿要求刪除所有提供 %s 的解決方案" + +#~ msgid "do not install most recent version of %s" +#~ msgstr "請勿安裝最新版本的 %s" + +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "保留 %s,忽略次要架構" + +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "安裝 %s,忽略次要架構" + +#~ msgid "keep obsolete %s" +#~ msgstr "保留過時的 %s" + +#~ msgid "install %s from excluded repository" +#~ msgstr "自排除的套件庫中安裝 %s" + +#~ msgid "downgrade of %s to %s" +#~ msgstr "降級 %s 到 %s" + +#~ msgid "architecture change of %s to %s" +#~ msgstr "架構由 %s 變更為 %s" + +#~ msgid "" +#~ "install %s (with vendor change)\n" +#~ " %s --> %s" +#~ msgstr "" +#~ "安裝 %s (並變更廠商)\n" +#~ " %s --> %s" + +#~ msgid "replacement of %s with %s" +#~ msgstr "將 %s 取代為 %s" + +#~ msgid "deinstallation of %s" +#~ msgstr "反安裝 %s" + +#~ msgid "Can't open lock file: %s" +#~ msgstr "無法開啟鎖定檔案:%s" + +#~ msgid "This action is being run by another program already." +#~ msgstr "此行動已被其他程式執行。" + +#~ msgid "Hal Exception" +#~ msgstr "Hal 例外" + +#~ msgid "Sorry, but this version of libzypp was built without HAL support." +#~ msgstr "抱歉,此版本的 libzypp 不支援 HAL。" + +#~ msgid "HalContext not connected" +#~ msgstr "HalContext 未連接" + +#~ msgid "HalDrive not initialized" +#~ msgstr "HalDrive 未初始化" + +#~ msgid "HalVolume not initialized" +#~ msgstr "HalVolume 未初始化" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "無法建立 dbus 連接" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "libhal_ctx_new:無法建立 libhal 網路位置" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "libhal_set_dbus_connection: 無法設定 dbus 連接" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "無法初始化 HAL 網路位置 -- hald 尚未執行嗎?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "不是光碟機" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "無法初始化 mutex 屬性" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "無法設定遞迴 mutex 屬性" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "無法初始化遞迴 mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "無法取得 mutex 鎖定" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "無法釋放 mutex 鎖定" + +#~ msgid "Failed to import public key from file %s: %s" +#~ msgstr "從檔案 %s 輸入公用金鑰失敗:%s" + +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "移除公用金鑰 %s 失敗:%s" + +#~ msgid "Cannot find available loop device to mount the image file from '%s'" +#~ msgstr "無法找到可用的 loop 裝置來掛載 '%s' 中的影像檔" + +#~ msgid "Cannot create public key %s from %s keyring to file %s" +#~ msgstr "無法建立公開金鑰 %s 從 %s 鑰匙圈到檔案 %s" + +#~ msgid "Download (Metalink curl) initialization failed for '%s'" +#~ msgstr "'%s' 下載 (Metalink curl) 初始化失敗" + +#~ msgid "" +#~ "Download (metalink curl) error for '%s':\n" +#~ "Error code: %s\n" +#~ "Error message: %s\n" +#~ msgstr "" +#~ "'%s' 下載 (Metalink curl) 錯誤:\n" +#~ "錯誤碼: %s\n" +#~ "錯誤訊息: %s\n" + +#~ msgid "Download interrupted at %d%%" +#~ msgstr "下載中斷在 %d%%" + +#~ msgid "Download interrupted by user" +#~ msgstr "使用者中斷下載" + +#~ msgid "" +#~ "Error occurred while setting download (metalink curl) options for '%s':" +#~ msgstr "為 '%s' 設定下載(metalink curl)參數時發生錯誤:" + +#~ msgid "Failed to download %s from %s" +#~ msgstr "下載 %s 從 %s 失敗" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "塞爾維亞和芒特尼格羅共和國" diff --git a/po/zu.po b/po/zu.po new file mode 100644 index 0000000..9d4062e --- /dev/null +++ b/po/zu.po @@ -0,0 +1,5964 @@ +# Copyright (C) 2006 SuSE Linux Products GmbH, Nuernberg +# This file is distributed under the same license as the package. +# +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: 2006-11-03 12:03\n" +"Last-Translator: Novell Language \n" +"Language-Team: Novell Language \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "Izwe elingaziwa:" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "Ayikho Ikhodi" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "Andorra" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "United Arab Emirates" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "Afghanistan" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "Antigua and Barbuda" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "Anguilla" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "Albania" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "Armenia" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "Netherlands Antilles" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "Angola" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "Antarctica" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "Argentina" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "American Samoa" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "Austria" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "Australia" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "Aruba" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "Aland Islands" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "Azerbaijan" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "Bosnia ne-Herzegowina" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "Barbados" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "Bangladesh" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "Belgium" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "Burkina Faso" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "Bulgaria" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "Bahrain" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "Burundi" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "Benin" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "Bermuda" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "Brunei Darussalam" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "Bolivia" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "Brazil" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "Bahamas" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "Bhutan" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "Bouvet Island" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "Botswana" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "Belarus" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "Belize" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "Canada" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "Cocos (Keeling) Islands" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "Congo" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "Centruual African Republic" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "Switzerland" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "Cote D'Ivoire" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "Cook Islands" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "Chile" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "Cameroon" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "China" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "Colombia" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "Costa Rica" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "Cuba" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "Cape Verde" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "Christmas Island" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "Cyprus" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "Czech Republic" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "Germany" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "Djibouti" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "Denmark" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "Dominica" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "Dominican Republic" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "Algeria" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "Ecuador" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "Estonia" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "Egypt" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "Western Sahara" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "Eritrea" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "Spain" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "Ethiopia" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "Finland" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "Fiji" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "Falkland Islands (Malvinas)" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "Federated States of Micronesia" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "Faroe Islands" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "France" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "Metropolitan France" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "Gabon" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "United Kingdom" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "Grenada" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "Georgia" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "French Guiana" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +#, fuzzy +msgid "Guernsey" +msgstr "Germany" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "Ghana" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "Gibraltar" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "Greenland" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "Gambia" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "Guinea" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "Guadeloupe" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "Equatorial Guinea" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "Greece" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "South Georgia kanye ne-South Sandwich Islands" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "Guatemala" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "Guam" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "Guinea-Bissau" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "Guyana" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "Hong Kong" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "Heard Island kanye ne-McDonald Islands" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "Honduras" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "Croatia" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "Haiti" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "Hungary" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "Indonesia" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "Ireland" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "Israel" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "India" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "British Indian Ocean Territory" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "Iraq" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "Iran" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "Iceland" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "Italy" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "Jamaica" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "Jordan" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "Japan" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "Kenya" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "Kyrgyzstan" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "Cambodia" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "Kiribati" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "Comoros" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "Saint Kitts ne-Nevis" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "North Korea" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "South Korea" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "Kuwait" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "Cayman Islands" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "Kazakhstan" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "Lao People's Democratic Republic" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "Lebanon" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "Saint Lucia" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "Liechtenstein" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "Sri Lanka" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "Liberia" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "Lesotho" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "Lithuania" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "Luxembourg" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "Latvia" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "Libya" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "Morocco" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "Monaco" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "Moldova" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +#, fuzzy +msgid "Montenegro" +msgstr "IsiMongo" + +#: zypp/CountryCode.cc:297 +#, fuzzy +msgid "Saint Martin" +msgstr "San Marino" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "Madagascar" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "Marshall Islands" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "Macedonia" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "Mali" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "Myanmar" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "Mongolia" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "Macao" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "Northern Mariana Islands" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "Martinique" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "Mauritania" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "Montserrat" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "Malta" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "Mauritius" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "Maldives" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "Malawi" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "Mexico" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "Malaysia" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "Mozambique" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "Namibia" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "New Caledonia" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "Niger" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "Norfolk Island" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "Nigeria" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "Nicaragua" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "Netherlands" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "Norway" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "Nepal" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "Nauru" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "Niue" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "New Zealand" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "Oman" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "Panama" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "Peru" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "French Polynesia" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "Papua New Guinea" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "Philippines" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "Pakistan" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "Poland" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "Saint Pierre ne-Miquelon" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "Pitcairn" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "Puerto Rico" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "Palestinian Territory" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "Portugal" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "Palau" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "Paraguay" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "Qatar" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "Reunion" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "Romania" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +#, fuzzy +msgid "Serbia" +msgstr "IsiSerbia" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "Russian Federation" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "Rwanda" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "Saudi Arabia" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "Solomon Islands" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "Seychelles" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "Sudan" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "Sweden" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "Singapore" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "Saint Helena" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "Slovenia" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "Svalbard ne-Jan Mayen" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "Slovakia" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "Sierra Leone" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "San Marino" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "Senegal" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "Somalia" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "Suriname" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "Sao Tome ne-Principe" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "El Salvador" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "Syria" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "Swaziland" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "Turks ne-Caicos Islands" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "Chad" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "French Southern Territories" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "Togo" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "Thailand" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "Tajikistan" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "IsiTokelau" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "Turkmenistan" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "Tunisia" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "Tonga" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "East Timor" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "Turkey" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "Trinidad ne-Tobago" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "IsiTuvalu" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "Taiwan" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "Tanzania" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "Ukraine" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "Uganda" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "United States Minor Outlying Islands" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "United States" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "Uruguay" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "Uzbekistan" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "Holy See (Vatican City State)" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "Saint Vincent and the Grenadines" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "Venezuela" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "British Virgin Islands" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "Virgin Islands, U.S." + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "Vietnam" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "Vanuatu" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "Wallis ne-Futuna" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "Samoa" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "Yemen" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "Mayotte" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "South Africa" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "Zambia" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "Zimbabwe" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +#, fuzzy +msgid "Obsoletes" +msgstr "%s yenza zingasebenzi:%s" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +#, fuzzy +msgid "Failed to import key." +msgstr "Ayikwazanga ukuqala i-VM." + +#: zypp/KeyRing.cc:414 +#, fuzzy +msgid "Failed to delete key." +msgstr "Ayikwazanga ukuqala i-VM." + +#: zypp/KeyRing.cc:420 +#, fuzzy, c-format, boost-format +msgid "Signature file %s not found" +msgstr "Into ayitholakali." + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "Ulimi olungaziwa:" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "Isi-Afar" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "Isi-Abkhazia" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "Isi-Achinese" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "Isi-Acoli" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "Isi-Adangme" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "Isi-Adyghe" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "Isi-Asia Esiyisi-Afro (Esinye)" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "Isi-Afrihili" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "IsiBhunu" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "Isi-Anu" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "Isi-Akan" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "Isi-Akkad" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "Isi-Albania" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "Isi-Aleut" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "Izilimi Zama-Algonquia" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "Isi-Altai SaseNingizimu" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "Isi-Amhari" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "IsiNgisi, Esidala (ca.450-1100)" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "Izilimi Zama-Apache" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "Isi-Arabhu" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "Isi-Aramu" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "Isi-Aragoni" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "Isi-Armenia" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "Isi-Araucania" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "Isi-Arapaho" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "Isi-Artificial (Esinye)" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "Isi-Arawak" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "Isi-Assame" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "Isi-Asturia" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "Izilimi Zama-Athapasca" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "Izilimi Zase-Australia" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "Isi-Avari" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "Isi-Avesta" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "Isi-Awadhi" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "Isi-Aymara" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "Isi-Azerbaijani" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "IsiBanda" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "Izilimi ZamaBalimeke" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "IsiBashkir" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "IsiBaluchi" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "IsiBambara" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "IsiBaline" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "IsiBasque" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "IsiBasa" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "Isi-Baltic (Esinye)" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "IsiBeja" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "IsiBelarusia" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "IsiBemba" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "IsiBengali" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "Isi-Barber (Esinye)" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "IsiBhojpuri" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "IsiBihari" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "IsiBikol" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "IsiBini" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "IsiBislama" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "IsiSiksika" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "Izilimi Zabomdabu (Ezinye)" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "IsiBosnia" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "IsiBraj" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "IsiBreton" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "IsiBatak (Indonesia)" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "IsiBuriat" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "IsiBuginese" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "IsiBulgaria" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "IsiBurmese" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "IsiBlin" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "IsiCaddo" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "Isindiya SaseMelika Ephakathi (Esinye)" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "IsiCarib" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "IsiCatal" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "Isi-Caucasia (Esinye)" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "IsiCebuano" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "Isi-Celt (Esinye)" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "IsiChamorro" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "IsiChibcha" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "IsiChechen" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "IsiChagatai" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "IsiShayina" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "IsiChuukese" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "IsiMari" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "Ingxubevange YesiChinook" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "IsiChoctaw" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "IsiChipewyan" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "IsiCherokee" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "IsiSlav SaseSontweni" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "IsiChuvash" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "IsiCheyenne" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "Izilimi ZamaChami" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "IsiCopt" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "IsiCorni" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "IsiCorsic" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "AmaCreoles namaPidgin, Ezisekelwe EsiNgisini (Ezinye)" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "AmaCreoles namaPidgin, Ezisekelwe EsiFulentshini (Ezinye)" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "AmaCreoles namaPidgin, Ezisekelwe EsiPutukezini (Ezinye)" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "IsiCree" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "Isi-Tatar SaseCrimea" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "Ama-Creole namaPidgin (Ezinye)" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "IsiKashubi" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "Isi-Cushiti (Esinye)" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "IsiCzech" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "IsiDakota" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "IsiDanishi" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "IsiDargwa" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "IsiDayak" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "IsiDelaware" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "IsiSlave (Sesi-Athapasca)" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "IsiDogrib" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "IsiDinka" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "IsiDivehi" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "IsiDogri" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "Isi-Dravid (Esinye)" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "IsiSorbia Sangezansi" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "IsiDuala" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "IsiDashi, Maphakathi (ca.1050-1350)" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "IsiDashi" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "IsiDyula" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "IsiDzongkha" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "Isi-Efik" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "IsiGibhithe (Sasendulo)" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "Isi-Ekajuk" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "Isi-Elami" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "IsiNgisi" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "IsiNgisi, Maphakathi (1100-1500)" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "Isi-Esperanto" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "Isi-Estonia" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "Isi-Ewe" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "Isi-Ewondo" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "Isi-Fang" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "IsiFaroese" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "IsiFanti" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "IsiFiji" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "IsiFilipino" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "IsiFinishi" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "Isi-Ugrio SesiFinno (Esinye)" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "IsiFon" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "IsiFulentshi" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "IsiFulentshi, Maphakathi (ca.1400-1600)" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "IsiFulentshi, Esidala (842-ca.1400)" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "IsiFrisia" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "IsiFulah" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "IsiFriulia" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "IsiGa" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "IsiGayo" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "IsiGbaya" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "IsiJalimane (Esinye)" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "IsiGeorgia" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "IsiJalimane" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "IsiGeez" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "IsiGilbertese" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "IsiGaeli" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "Isi-Irish" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "IsiGalicia" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "IsiManx" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "IsiJalimane, Esiphezulu Maphakathi (ca.1050-1500)" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "IsiJalimane, Esiphezulu Sakudala (ca.1050-1050)" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "IsiGondi" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "IsiGorontalo" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "IsiGothic" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "IsiGrebo" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "IsiGriki, Sasendulo (kuya ku-1453)" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "IsiGriki, Sesimanje (1453-)" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "IsiGuarani" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "IsiGujarati" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "IsiGwich'in" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "IsiHaida" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "IsiHaiti" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "IsiHausa" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "IsiHawaii" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "IsiHebheru" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "IsiHerero" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "IsiHiligaynon" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "IsiHimachali" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "IsiHindi" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "IsiHeti" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "IsiHmong" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "IsiHiri Motu" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "IsiSorbia Sangenhla" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "IsiHungary" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "IsiHupa" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "Isi-Iban" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "Isi-Igbo" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "Isi-Iceland" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "Isi-Ido" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "IsiSichuan Yi" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "Isi-Ijo" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "Isi-Inuktitut" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "Isi-Interlingue" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "Isi-Iloko" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "Isi-Interlingua (Inhlangano Yomhlaba Wonke Esiza Ngezilimi)" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "Isi-Indi (Esinye)" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "Isi-Indonesia" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "Isi-Indo-Europe (Esinye)" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "Isi-Ingush" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "Isi-Inupiaq" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "Isi-Irani (Esinye)" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "Izilimi Zase-Iraqi" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "IsiNtaliyane" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "IsiJavani" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "IsiLobja" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "AmaJapane" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "IsiPheresiya EsiyisiJuda" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "Isi-Arabhu EsiyisiJuda" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "IsiKara-Kalpak" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "IsiKabyle" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "IsiKachin" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "IsiKalaallisut" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "IsiKamba" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "IsiKannada" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "IsiKaren" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "IsiKashmiri" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "IsiKanuri" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "IsiKawi" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "IsiKazakh" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "IsiKabard" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "IsiKhasi" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "IsiKhoisan (Esinye)" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "IsiKhmer" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "IsiKhotanese" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "IsiKikuyu" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "IsiKinyarwanda" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "IsiKrghiz" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "IsiKimbundu" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "IsiKonkani" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "IsiKomi" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "IsiKongo" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "IsiKoriya" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "IsiKosrae" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "IsiKpelle" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "IsiKarachay-Balkar" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "IsiKru" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "IsiKurukh" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "IsiKuanyama" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "IsiKumyk" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "IsiKurdu" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "IsiKutenai" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "IsiLadino" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "IsiLahnda" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "IsiLamba" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "IsiLao" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "IsiLatini" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "IsiLatvia" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "IsiLezghia" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "IsiLimburg" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "IsiLingala" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "IsiLithania" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "IsiMongo" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "IsiLozi" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "IsiLuxembourg" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "IsiLuba-Lulua" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "IsiLuba-Katanga" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "IsiGanda" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "IsiLuiseno" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "IsiLunda" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "IsiLuo (Ekenya naseTanzania)" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "IsiLushai" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "IsiMacedonia" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "IsiMadurese" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "IsiMagahi" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "IsiMarshall" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "IsiMaithili" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "IsiMakasar" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "IsiMalayal" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "IsiMandingo" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "IsiMaori" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "Isi-Austronesia (Esinye)" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "IsiMarathi" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "IsiMasai" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "IsiMalay" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "IsiMoksha" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "IsiMandar" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "IsiMende" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "Isi-Irish, Maphakathi (900-1200)" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "IsiMi'kmaq" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "IsiMinangkabau" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "Izilimi Eziyingxubevange" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "IsiMon-Khmer (Ezinye)" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "IsiMalagasy" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "IsiMaltese" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "IsiManchu" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "IsiManipuri" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "Izilimi ZaManobo" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "IsiMohawk" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "IsiMoldavia" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "IsiMongolia" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "IsiMossi" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "Izilimi Eziningi" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "Izilimi ZamaMunda" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "IsiCreek" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "IsiMirandese" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "IsiMarwari" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "Izilimi ZamaMaya" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "Isi-Erzya" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "IsiNahuatl" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "IsiNdiya SaseNyakatho Melika" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "IsiNeapoli" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "Navajo" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "IsiNdebele, saseNingizimu" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "IsiNdebele, saseNyakatho" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "IsiNdonga" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "IsiJalimane Esiphansi" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "IsiNepali" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "IsiNepali Bhasha" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "IsiNias" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "IsiNiger-Kordofanian (Esinye)" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "IsNiue" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "IsiNynorsk SaseNorway" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "IsiBokmal SaseNorway" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "IsiNogai" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "IsiNorse, Esidala" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "IsiNorway" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "IsiSuthu SaseNyakatho (isiPedi)" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "Izilimi zamaNubi" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "IsiNewari Sendabuko" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "IsiChewa" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "IsiNyamwezi" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "IsiNyakole" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "IsiNyoro" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "IsiNzima" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "Isi-Occitan (sangemva kuka-1500)" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "Isi-Ojibwa" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "Isi-Oriya" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "Isi-Oromo" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "Isi-Osage" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "Isi-Ossetian" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "IsiTurkey, Isi-Ottoman (1500-1928" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "Izilimi Zama-Otomia" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "IsiPapua (Esinye)" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "IsiPangasinan" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "IsiPahlavi" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "IsiPampanga" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "IsiPanjabi" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "IsiPapiamento" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "IsiPalauan" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "IsiPeresiya, Esidala (ca.600-400 B.C.)" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "IsiPeresiya" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "Isi-Philippine (Esinye)" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "IsiPhoenicia" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "IsiPali" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "IsiPolishi" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "IsiPohnpeian" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "IsiPutukezi" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "Izilimi ZesiPrakrit" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "IsiProvencal, Esidala (ukuya ku-1500)" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "IsiPushto" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "IsiQuenchua" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "IsiRajasthani" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "IsiRapanui" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "IsiRarotonga" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "IsiRomance (Esinye)" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "IsiRaeto-Romance" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "IsiRomany" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "IsiRomania" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "IsiRundi" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "IsiRashiya" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "IsiSandawe" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "IsiSango" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "IsiYakut" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "IsiNdiya SaseMelika EseNingizimu (Esinye)" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "Izilimi ZesiSalisha" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "Isi-Aramu SaseSamariya" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "IsiSanskrit" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "IsiSasak" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "IsiSantali" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "IsiSerbia" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "IsiSicilia" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "IsiScots" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "IsiCroatia" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "IsiSelkup" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "IsiSemi (Esinye)" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "Isi-Irish, Esidala (ukuya ku-900)" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "Izilimi Zezandla" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "IsiShan" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "IsiSidamo" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "IsiSinhala" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "Izilimi ZaseSioua" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "IsiTibeti SamaSino (Esinye)" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "Isi-Slavic (Esinye)" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "IsiSlovak" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "IsiSlovenia" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "IsiSami SaseNingizimu" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "IsiSami SaseNyakatho" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "Izilimi ZamaSami (Esinye)" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "IsiSami SamaLule" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "IsiSami Sama-Inari" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "IsiSamoa" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "IsiSami SamaSkolt" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "IsiShona" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "IsiSindhi" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "IsiSoninke" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "IsiSogdia" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "IsiSomali" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "IsiSonghai" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "IsiSuthu, SaseNingizimu" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "ISipanishi" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "IsiSardinia" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "IsiSerer" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "IsiSahara EsiyisiNilo (Esinye)" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "IsiSwati" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "IsiSukuma" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "IsiSundanese" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "IsiSusu" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "IsiSumeri" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "IsiSwahili" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "IsiSwidi" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "IsiSyria" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "IsiTahiti" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "Isi-Tai (Esinye)" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "IsiTamil" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "Isi-Tatar" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "IsiTelugu" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "IsiTimne" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "IsiTereno" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "IsiTetum" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "IsiTajik" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "IsiTagalog" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "IsiThai" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "IsiTibet" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "IsiTigre" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "IsiTigrinya" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "IsiTiv" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "IsiKlingon" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "IsiTlingit" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "IsiTamashek" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "IsiTonga (SamaNyasa)" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "IsTonga (Eziqingini ZamaTonga)" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "IsiTok Pisin" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "IsiTsimshian" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "IsiTswana" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "IsiTsonga" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "IsiTurkment" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "IsiTumbuka" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "Izilimi ZamaTupi" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "IsiTurkey" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "Isi-Atlaic (Esinye)" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "IsiTwi" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "IsiTuvinia" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "Isi-Udmurt" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "Isi-Ugaritic" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "Isi-Uighur" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "Isi-Ukrania" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "Isi-Umbundu" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "Olunganqunyiwe" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "Isi-Urdu" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "Isi-Uzbek" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "IsiVai" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "IsiVenda" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "IsiVietnam" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "IsiVolapuk" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "IsiVotic" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "Izilimi ZamaWakasha" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "IsiWalamo" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "IsiWaray" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "IsiWasho" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "IsiWelsh" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "Izilimi ZamaSorbia" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "IsiWalloon" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "IsiWolof" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "IsiKalmyk" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "IsiXhosa" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "IsiYao" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "IsiYapese" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "IsiYiddish" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "IsiYoruba" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "Izilimi ZamaYupik" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "IsiZapotec" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "IsiZenaga" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "IsiZhuang" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "IsiZande" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "IsiZulu" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "IsiZuni" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +#, fuzzy +msgid "does not expire" +msgstr "'I-o%1' ayitholakali." + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +#, fuzzy +msgid "(does not expire)" +msgstr "'I-o%1' ayitholakali." + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "akwaziwa" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +#, fuzzy +msgid "The vendor does not provide support." +msgstr "Idiski ayikho." + +#: zypp/VendorSupportOptions.cc:47 +msgid "" +"Problem determination, which means technical support designed to provide " +"compatibility information, installation assistance, usage support, on-going " +"maintenance and basic troubleshooting. Level 1 Support is not intended to " +"correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "" +"Problem isolation, which means technical support designed to duplicate " +"customer problems, isolate problem area and provide resolution for problems " +"not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "" +"Problem resolution, which means technical support designed to resolve " +"complex problems by engaging engineering in resolution of product defects " +"which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "" +"The package was discontinued and has been superseded by a new package with a " +"different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, fuzzy, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "Ikhomandi engaziwa" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, fuzzy, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "Uhlelo lwe-Url olungekho emthethweni '%s'" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "" +"Visit the SUSE Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "" +"Visit the Novell Customer Center to check whether your registration is valid " +"and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "" +"Create attach point: Can't find a writable directory to create an attach " +"point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +#, fuzzy +msgid "Can't create metadata cache directory." +msgstr "Ayikwazi ukwakha i-directory '%1'. %2." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, fuzzy, c-format, boost-format +msgid "Can't create %s" +msgstr "Ayikwazi ukuvula into esesendlalelweni (desktop) '%s'" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, fuzzy, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "Failed to parse: %s." + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, fuzzy, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "Igama lefayela yokuthekelisa engekho emthethweni." + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, fuzzy, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "Ayikwazi ukuvula ifayela ukuze ibhale." + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, fuzzy, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "Kwenzeke iphutha lapho ifunda iflophi diski." + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, fuzzy, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "Failed to parse: %s." + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, fuzzy, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "Ukubuyisela imithombo yokwaziswa" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, fuzzy, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "Ayikwazi ukuvula into esesendlalelweni (desktop) '%s'" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +#, fuzzy +msgid "Repository alias cannot start with dot." +msgstr "Igama le-VM alikwazi ukuqala ngenombolo." + +#: zypp/ng/repomanager.h:77 +#, fuzzy +msgid "Service alias cannot start with dot." +msgstr "Igama le-VM alikwazi ukuqala ngenombolo." + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "Qhubeka?" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "" +"File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +#, fuzzy +msgid "Signature verification failed" +msgstr "DBI Execution failed: %s" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, fuzzy, c-format, boost-format +msgid "" +"Package %s seems to be corrupted during transfer. Do you want to retry " +"retrieval?" +msgstr "" +"Iphakheji %s ihlulekile lapho ihlolwa ukuthembeka. Ufuna ukuphinde uzame " +"ukuyilanda futhi?" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, fuzzy, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" +"Iphakheji %s ihlulekile lapho ihlolwa ukuthembeka. Ufuna ukuphinde uzame " +"ukuyilanda futhi?" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "ukuhlola i-applydeltarpm kuhlulekile." + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "i-applydeltarpm ihlulekile." + +#: zypp/repo/RepoException.cc:129 +#, fuzzy +msgid "Service plugin does not support changing an attribute." +msgstr "" +"uhlobo lomthombo wokwaziswa we-VAR1 alulusekeli uhlelo lokuboniswa " +"kwezinguquko" + +#: zypp/repo/RepoProvideFile.cc:260 +#, fuzzy, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "Ayikwazi ukuhlinzeka nge-%s kwi-%s" + +#: zypp/repo/RepoProvideFile.cc:266 +#, fuzzy +msgid "No url in repository." +msgstr "Ifayela %1 ayitholakali enqolobaneni yamafayela." + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +#, fuzzy +msgid "Can not create sat-pool." +msgstr "Ayikwazi ukwakha ifayela." + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, fuzzy, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "Sishaye indiva lesi sidingo lapha nje kuphela" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +#, fuzzy +msgid "generally ignore of some dependencies" +msgstr "Sishaye indiva lesi sidingo lapha nje kuphela" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "" +"the installed %1% does not belong to a distupgrade repository and must be " +"replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +#, fuzzy +msgid "conflicting requests" +msgstr "Isicelo Sokuxhuma kwi-:" + +#: zypp/solver/detail/SATResolver.cc:1177 +#, fuzzy +msgid "some dependency problem" +msgstr "Ayikwazi ukufaka %s ngenxa yezinkinga zohlelo oluncike kwezinye" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "" +"the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "" +"the to be installed %1% conflicts with '%2%' provided by the to be installed " +"%3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "" +"the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "" +"the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "" +"the to be installed %1% requires '%2%', but this requirement cannot be " +"provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +#, fuzzy +msgid "deleted providers: " +msgstr "Akukho okunikeza %s" + +#: zypp/solver/detail/SATResolver.cc:1285 +#, fuzzy +msgid "" +"\n" +"not installable providers: " +msgstr "Abekho abanye abaphakeli abafakiwe be-%s" + +#: zypp/solver/detail/SATResolver.cc:1287 +#, fuzzy +msgid "not installable providers: " +msgstr "Abekho abanye abaphakeli abafakiwe be-%s" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "" +"Typically you want to keep the PTF and choose to not install the maintenance " +"patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "" +"Removing the installed %1% in this context will remove (not replace!) the " +"included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "" +"The PTF should be removed by calling '%1%'. This will update the included " +"PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +#, fuzzy +msgid "This request will break your system!" +msgstr "Isicelo sesikhona kakade." + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "Ukufaka kuyekiwe njengoba kunikezwe isiqondiso." + +#: zypp/target/TargetImpl.cc:462 +#, fuzzy +msgid " executed" +msgstr "Qalisa" + +#: zypp/target/TargetImpl.cc:484 +#, fuzzy +msgid " execution failed" +msgstr "DBI Execution failed: %s" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +#, fuzzy +msgid "Error sending update message notification." +msgstr "Kwenzeke iphutha ngesikhathi kufakwa amakhodi okuphepha." + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "" +"Received signal :\"%1% (%2%)\", to ensure the consistency of the system it " +"is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +#, fuzzy +msgid "RPM failed: " +msgstr "ayiphumelelanga" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "Amafayela okuhlela ashintshile e-%s:" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, fuzzy, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "I-rpm igcine %s njenge-%s kodwa bekungenakwenzeka ukubona umehluko" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"I-rpm igcine i-%s njenge-%s.\n" +"Nansi imigqa yokuqala engu-25 yomehluko:\n" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, fuzzy, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "I-rpm yakhe %s njenge-%s kodwa bekungenakwenzeka ukubona umehluko" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" +"I-rpm yakhe i-%s njenge-%s.\n" +"Nansi imigqa yokuqala engu-25 yomehluko:\n" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +#, fuzzy +msgid "Additional rpm output" +msgstr "Okunye okukhishiwe kwe-rpm:" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "yakhe i-backup %s" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +#, fuzzy +msgid "Signature is OK" +msgstr "Into ayitholakali." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +#, fuzzy +msgid "Signature does not verify" +msgstr "Into ayitholakali." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +#, fuzzy +msgid "Signature is OK, but key is not trusted" +msgstr "Into ayitholakali." + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, fuzzy, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "Couldn't open file: %s." + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, fuzzy, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "Ayikwazi ukuvula ifayela %1." + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "Uhlu lombuzo lwe-LDAP URL olunganembile" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "Ipharamitha yombuzo ye-LDAP URL enganembile '%s'" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "Ayikwazi ukukopisha into ye-Url" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "Into engenalutho ye-Url okubhekiselwe kuyo ayinembile" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "Ayikwazi ukucaza izingxenyana ze-Url" + +#: zypp-core/base/Exception.cc:186 +#, fuzzy +msgid "History:" +msgstr "Linganisa Umlando" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "Uhlelo lwe-URL aluyivumeli i-%s" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "Ingxenyana '%s' engekho emthethweni %s" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "Ingxenyana engekho emthethweni %s" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "Ukucazwa kohlu lwemibuzo akusekelwa kule-URL" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "Uhlelo lwe-Url luyingxenyana edingekayo" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "Uhlelo lwe-Url olungekho emthethweni '%s'" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "Uhlelo lwe-URL alulivumeli igama lomsebenzisi" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "Uhlelo lwe-URL aluyivumeli iphasiwedi" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "Uhlelo lwe-Url ludinga ingxenyana yesiphakeli" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "Uhlelo lwe-URL aluyivumeli ingxenyana yesiphakeli" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "Ingxenyana engekho emthethweni '%s'" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "Uhlelo lwe-URL aluyivumeli iphasiwedi" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "Ingxenyana engekho emthethweni '%s'" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "Uhlelo lwe-Url ludinga igama lomgudu" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "Umgudu ongaphelele awuvunyelwe uma kunegunya" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "Uhlu olufakwe amakhodi okuphepha lune-NUL byte" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "Iqoqo lepharamitha elinganembile lihlakaza uhlamvu oluhlukanisayo" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "Ibalazwe lepharamitha elinganembile lihlakaza uhlamvu oluhlukanisayo" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "Iqoqo lepharamitha elinganembile lihlanganisa uhlamvu oluhlukanisayo" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +#, fuzzy +msgid "Command exited with unknown error." +msgstr "Ikhomandi ekhishwa lapho ixhumeka" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, fuzzy, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "Ayiyitholi i-%s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, fuzzy, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "Ayiyitholi i-%s." + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, fuzzy, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "Ayikwazi ukuvula %s - %s\n" + +#: zypp-media/mediaexception.cc:43 +#, fuzzy, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "Ihlulekile ukufaka imoduli \"%s\"." + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, fuzzy, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "Ifayela %1 ayitholakali enqolobaneni yamafayela." + +#: zypp-media/mediaexception.cc:63 +#, fuzzy, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "Ayikwazi ukubhala efayeleni %1." + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, fuzzy, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "I-%1 ayiyona i-directory." + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +#, fuzzy +msgid "Empty host name in URI" +msgstr "Igama le-CA elingenalutho" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, fuzzy, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "Uhlelo '%1' lwe-URL engekho emthethweni." + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, fuzzy, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "Ayikwazi ukuvula into esesendlalelweni (desktop) '%s'" + +#: zypp-media/mediaexception.cc:181 +#, fuzzy, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "Izimvume zinqatshiwe" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "&Yebo" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "&Cha" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +#, fuzzy +msgid "Warning:" +msgstr "Isexwayiso" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +#, fuzzy +msgid "Error:" +msgstr "Iphutha" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "kwenziwe" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "iphutha" + +#: zypp-tui/output/OutNormal.cc:90 +#, fuzzy +msgid "Warning: " +msgstr "Isexwayiso" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +# window title for kernel loading (see txt_load_kernel) +#: zypp-tui/output/OutNormal.cc:261 +#, fuzzy +msgid "starting" +msgstr "Iyaqalisa..." + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +#, fuzzy +msgid "not found" +msgstr "Akutholakalanga" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "yebo" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "cha" + +#, fuzzy +#~ msgid "%s has inferior architecture" +#~ msgstr "%s ihlinzeka nge-%s, kodwa inobunye ubuciko bomklamo." + +#, fuzzy +#~ msgid "problem with installed package %s" +#~ msgstr "ikhomandi yokukhipha amaphakheji" + +#, fuzzy +#~ msgid "nothing provides requested %s" +#~ msgstr "Akukho okunikeza %s" + +#, fuzzy +#~ msgid "package %s does not exist" +#~ msgstr "Idiski ayikho." + +#, fuzzy +#~ msgid "%s is provided by the system and cannot be erased" +#~ msgstr "%s ihluthulelwe futhi ngeke ikwazi ukukhipheka." + +#, fuzzy +#~ msgid "%s is not installable" +#~ msgstr "alufakiwe" + +#, fuzzy +#~ msgid "nothing provides %s needed by %s" +#~ msgstr "%s idingwa yi- %s" + +#, fuzzy +#~ msgid "cannot install both %s and %s" +#~ msgstr "Ayikwazi ukufaka %s" + +#, fuzzy +#~ msgid "%s conflicts with %s provided by %s" +#~ msgstr "%s ixabana ne- %s" + +#, fuzzy +#~ msgid "%s obsoletes %s provided by %s" +#~ msgstr "%s yenza zingasebenzi %s" + +#, fuzzy +#~ msgid "installed %s obsoletes %s provided by %s" +#~ msgstr "%s yenza zingasebenzi %s" + +#, fuzzy +#~ msgid "solvable %s conflicts with %s provided by itself" +#~ msgstr "%s ixabana ne- %s" + +#~ msgid "do not install %s" +#~ msgstr "ungafaki %s" + +#~ msgid "keep %s" +#~ msgstr "Gcina %s" + +#, fuzzy +#~ msgid "remove lock to allow installation of %s" +#~ msgstr "ungafaki %s" + +#, fuzzy +#~ msgid "do not ask to install a solvable providing %s" +#~ msgstr "Abekho abanye abaphakeli abafakiwe be-%s" + +#, fuzzy +#~ msgid "do not ask to delete all solvables providing %s" +#~ msgstr "Ungafaki noma ususe maqondana nezixazululi" + +#, fuzzy +#~ msgid "keep %s despite the inferior architecture" +#~ msgstr "%s ihlinzeka nge-%s, kodwa inobunye ubuciko bomklamo." + +#, fuzzy +#~ msgid "install %s despite the inferior architecture" +#~ msgstr "Faka %s nakuba izoshintsha ubuciko bomklamo" + +#, fuzzy +#~ msgid "keep obsolete %s" +#~ msgstr "%s yenza zingasebenzi %s" + +#, fuzzy +#~ msgid "downgrade of %s to %s" +#~ msgstr "Ilande %s kwi-%s" + +#, fuzzy +#~ msgid "deinstallation of %s" +#~ msgstr "Ukufaka uhlelo" + +#, fuzzy +#~ msgid "Can't open lock file: %s" +#~ msgstr "Ayikwazi ukuvula ifayela %1." + +#~ msgid "Hal Exception" +#~ msgstr "I-Hal Exception" + +#~ msgid "HalContext not connected" +#~ msgstr "I-HalContext ayixhumekile" + +#~ msgid "HalDrive not initialized" +#~ msgstr "I-HalDrive ayizange ilungiselelwe ukuqalisa" + +#~ msgid "HalVolume not initialized" +#~ msgstr "I-HalVolume ayizange ilungiselelwe ukuqalisa" + +#~ msgid "Unable to create dbus connection" +#~ msgstr "Ayikwazanga ukwakha ukuxhumana nge-dbus" + +#~ msgid "libhal_ctx_new: Can't create libhal context" +#~ msgstr "I-libhal_ctx_new: Ayikwazi ukwakha i-libhal context" + +#~ msgid "libhal_set_dbus_connection: Can't set dbus connection" +#~ msgstr "I-libhal_set_dbus_connection: Ayikwazi ukwakha ukuxhumana kwe-dbus" + +#~ msgid "Unable to initalize HAL context -- hald not running?" +#~ msgstr "Ayikwazi ukuqalisa i-HAL context --i-hald ayisebenzi?" + +#~ msgid "Not a CDROM drive" +#~ msgstr "Akuyona i-CDROM drive" + +#~ msgid "Can't initialize mutex attributes" +#~ msgstr "Ayikwazi ukulungela ukuqalisa ama-attribute e-mutex" + +#~ msgid "Can't set recursive mutex attribute" +#~ msgstr "Ayikwazi ukusetha ama-attribute e-mutex" + +#~ msgid "Can't initialize recursive mutex" +#~ msgstr "Ayikwazi ukulungiselela ukuqalisa i-recursive mutex" + +#~ msgid "Can't acquire the mutex lock" +#~ msgstr "Ayikwazi ukuthola isihluthulelo se-mutex" + +#~ msgid "Can't release the mutex lock" +#~ msgstr "Ayikwazi ukukhulula isihluthulelo se-mutex" + +#, fuzzy +#~ msgid "Failed to remove public key %s: %s" +#~ msgstr "Ayikwazi ukuthola isikhiye sikawonk’ uwonke." + +#, fuzzy +#~ msgid "do not keep %s installed" +#~ msgstr "alufakiwe" + +#, fuzzy +#~ msgid "Failed to download %s from %s" +#~ msgstr "Ayikwazi ukuvula %s - %s\n" + +#~ msgid "Serbia and Montenegro" +#~ msgstr "Serbia ne-Montenegro" + +#, fuzzy +#~ msgid "Unknown Distribution" +#~ msgstr "Uhlu olungaziwa okukhethwa kulo" + +#, fuzzy +#~ msgid "ignore some dependencies of %s" +#~ msgstr "ayikwazanga ukuxazulula izinhlelo ezincike kwezinye" + +#~ msgid "" +#~ "File %s does not have a checksum.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayela %s ayinayo i-checksum.\n" +#~ "Nokho yisebenzise ifayela?" + +#~ msgid "" +#~ "File %s failed integrity check with the folowing key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayela %s yehlulekile ekuhlolweni kokwethembeka ngesikhiye " +#~ "esilandelayo:\n" +#~ "%s|%s|%s\n" +#~ " Nokho yisebenzise ifayela?" + +#~ msgid "" +#~ "File %s has an invalid checksum.\n" +#~ "Expected %s, found %s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayela %s ine-checksum engasebenzi.\n" +#~ "Bekulindeleke %s, kwatholakala %s\n" +#~ " Nokho yisebenzise ifayela?" + +#~ msgid "" +#~ "File %s has an unknown checksum %s.\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayela %s ine-checksum engaziwa %s.\n" +#~ "Nokho yisebenzise ifayela?" + +#~ msgid "" +#~ "File %s is not signed.\n" +#~ "Use it anyway?" +#~ msgstr "" +#~ "Ifayela %s ayisayiniwe.\n" +#~ "Nokho yisebenzise?" + +#~ msgid "" +#~ "File %s is signed with an unknown key:\n" +#~ "%s|%s|%s\n" +#~ "Use the file anyway?" +#~ msgstr "" +#~ "Ifayela %s isayinwe ngesikhiye esingaziwa:\n" +#~ "%s|%s|%s\n" +#~ " Nokho yisebenzise ifayela?" + +#~ msgid "" +#~ "Untrusted key found:\n" +#~ "%s|%s|%s\n" +#~ "Trust key?" +#~ msgstr "" +#~ "Isikhiye esingenakwethenjwa sitholakele:\n" +#~ "%s|%s|%s\n" +#~ " Sethembe isikhiye?" + +#~ msgid "%s remove failed" +#~ msgstr "Ukususa i-%s akuphumelelanga" + +#, fuzzy +#~ msgid "Invalid user name or password." +#~ msgstr "Iphasiwedi ye-CA engekho emthethweni." + +#~ msgid "rpm output:" +#~ msgstr "okukhishiwe kwe-rpm:" + +#~ msgid "%s install failed" +#~ msgstr "ukufakwa kwe-%s akuphumelelanga" + +#~ msgid "%s installed ok" +#~ msgstr "%s efakiwe ilungile" + +#~ msgid "%s remove ok" +#~ msgstr "ukususa i-%s kuphumelele" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the architecture of the " +#~ "installed item" +#~ msgstr "" +#~ "%s ihlinzeka ngalolu hlelo okuncikwe kulo kodwa ingabushintsha ubuciko " +#~ "bomklamo bento efakiwe" + +#, fuzzy +#~ msgid "" +#~ "%s provides this dependency, but would change the vendor of the installed " +#~ "item" +#~ msgstr "" +#~ "%s ihlinzeka ngalolu hlelo okuncikwe kulo kodwa ingabushintsha ubuciko " +#~ "bomklamo bento efakiwe" + +#, fuzzy +#~ msgid "Do not install or delete the resolvables concerned" +#~ msgstr "Ungafaki noma ususe maqondana nezixazululi" + +#~ msgid "Ignore that %s is already set to install" +#~ msgstr "Kushaye indiva ukuthi i-%s isisethelwe ukufakwa kakade" + +#~ msgid "Ignore the obsolete %s in %s" +#~ msgstr "Ishaye indiva into engasebenzi i-%s e-%s" + +#~ msgid "Ignore this conflict of %s" +#~ msgstr "Kushaye indiva lokhu kuxabana kwe-%s" + +#~ msgid "Ignore this requirement just here" +#~ msgstr "Sishaye indiva lesi sidingo lapha nje kuphela" + +#, fuzzy +#~ msgid "Install %s although it would change the vendor" +#~ msgstr "Faka %s nakuba izoshintsha ubuciko bomklamo" + +#~ msgid "Install missing resolvables" +#~ msgstr "Faka izixazululi ezilahlekile" + +#~ msgid "Keep resolvables" +#~ msgstr "Gcina Izixazululi" + +#~ msgid "Unlock these resolvables" +#~ msgstr "Vula izihluthulelo zalezi zixazululi" + +#~ msgid "delete %s" +#~ msgstr "Susa %s" + +#~ msgid "install %s" +#~ msgstr "faka %s" + +#~ msgid "unlock %s" +#~ msgstr "vula isihluthulelo se-%s" + +#~ msgid "unlock all resolvables" +#~ msgstr "Vula izihluthulelo zezixazululi" + +#, fuzzy +#~ msgid "Can't open solv-file: " +#~ msgstr "Ayikwazi ukuvula ifayela %1." + +#, fuzzy +#~ msgid "Error reading solv-file: " +#~ msgstr "Kwenzeke iphutha ifunda i-sector %u." + +#~ msgid "Path Parameter parsing not supported for this URL" +#~ msgstr "Ukucazwa kwepharamitha yomgudu akusekelwa kule-URL" + +#~ msgid "Path parameter parsing not supported for this URL" +#~ msgstr "Ukucazwa kwepharamitha yomgudu akusekelwa kule-URL" + +#~ msgid "Software management is already running." +#~ msgstr "Ukulawulwa kwe-software sekuyasebenza kakade." + +#~ msgid "%s is replaced by %s" +#~ msgstr "%s ithathelwa indawo yi- %s" + +#~ msgid "%s replaced by %s" +#~ msgstr "%s ingenelwe esikhundleni yi- %s" + +#, fuzzy +#~ msgid "%s will be deleted by the user.\n" +#~ msgstr "" +#~ "\n" +#~ "Lezi zixazululi zizosulwa kwisistimu." + +#, fuzzy +#~ msgid "%s will be installed by the user.\n" +#~ msgstr "%s ayinakukhishwa ngoba isadingeka namanje" + +#~ msgid "Invalid information" +#~ msgstr "ukwaziswa okungasebenzi" + +#~ msgid "%s is needed by other resolvables" +#~ msgstr "%s idingwa ezinye izixazululi" + +#~ msgid "" +#~ "%s is needed by:\n" +#~ "%s" +#~ msgstr "" +#~ "%s idingwa yi-:\n" +#~ "%s" + +#~ msgid "%s conflicts with other resolvables" +#~ msgstr "%s ixabana nezinye izixazululi" + +#~ msgid "" +#~ "%s conflicts with:\n" +#~ "%s" +#~ msgstr "" +#~ "%s ixabana ne-:\n" +#~ "%s" + +#~ msgid "%s obsoletes other resolvables" +#~ msgstr "%s yenza ezinye izixazululi zingasebenzi" + +#~ msgid "" +#~ "\n" +#~ "These resolvables will be deleted from the system." +#~ msgstr "" +#~ "\n" +#~ "Lezi zixazululi zizosulwa kwisistimu." + +#~ msgid "%s depends on other resolvables" +#~ msgstr "%s yenzike kwezinye izixazululi" + +#~ msgid "%s depends on %s" +#~ msgstr "%s yencike kwi- %s" + +#~ msgid "%s depends on:%s" +#~ msgstr "%s yencike kwi-:%s" + +#~ msgid "Child of" +#~ msgstr "Ingane ka-" + +#, fuzzy +#~ msgid "" +#~ "\n" +#~ "There is no resource available which supports this requirement." +#~ msgstr "" +#~ "\n" +#~ "Awukho umthombo otholakalayo osekela lemfuneko." + +#, fuzzy +#~ msgid "" +#~ "Due to the problems described above/below, this resolution will not solve " +#~ "all dependencies" +#~ msgstr "" +#~ "Izinkinga ezidlulelwe yisikhathi ezichazwe ngenhla/ngezansi kwalokhu " +#~ "ngeke zixazulule zonke izinhlelo okuncikwe kuzo." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting with %s" +#~ msgstr "Ayikwazi ukufaka %s ngoba ixabana ne-%s" + +#~ msgid "%s is not installed and has been marked as uninstallable" +#~ msgstr "%s ayifakwanga futhi iye yaphawulwa njengengafakeki" + +#~ msgid "%s has unfulfilled requirements" +#~ msgstr "%s inezimfuneko ezingagcwalisiwe" + +#~ msgid "%s has missing dependencies" +#~ msgstr "%s inezinhlelo encike kuzo ezilahlekile" + +#~ msgid "%s cannot be installed due to missing dependencies" +#~ msgstr "%s ayikwazi ukufkwa ngenxa yezinhlelo encike kuzo ezilahlekile" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be uninstalled" +#~ msgstr "%s igcwalisa izinhlelo okuncikwe kuzo ze-%s kodwa izokhishwa" + +#, fuzzy +#~ msgid "%s fulfills dependencies of %s but will be kept on your system" +#~ msgstr "" +#~ "%s igcwalisa izinhlelo okuncikwe kuzo ze-%s kodwa izogcinwa kwisistimu " +#~ "yakho" + +#~ msgid "No need to install %s" +#~ msgstr "Asikho isidingo sokuyifaka %s" + +#, fuzzy +#~ msgid "Cannot install %s to fulfill the dependencies of %s" +#~ msgstr "Ayikwazi ukufaka %s ukuze igcwalise izinhlelo okuncikwe kuzo ze-%s" + +#~ msgid "Cannot install %s to fulfil the dependencies of %s" +#~ msgstr "Ayikwazi ukufaka %s ukuze igcwalise izinhlelo okuncikwe kuzo ze-%s" + +#, fuzzy +#~ msgid "%s will not be uninstalled, because it is still required" +#~ msgstr "%s ayinakukhishwa ngoba isadingeka namanje" + +#, fuzzy +#~ msgid "%s obsoletes %s. But %s cannot be deleted, because it is locked." +#~ msgstr "" +#~ "%s yenza ingasebenzi i-%s. Kodwa %s ayikwazi ukususwa ngoba ihluthulelwe." + +#, fuzzy +#~ msgid "Cannot install %s, because it is conflicting" +#~ msgstr "Ayikwazi ukufaka %s ngoba iyaxabana" + +#~ msgid "%s is uninstallable due to conflicts with %s" +#~ msgstr "%s ayifakeki ngenxa yokuxabana ne- %s" + +#~ msgid "for requiring %s for %s when upgrading %s" +#~ msgstr "ngokudinga i-%s ye-%s lapho kuvuselelwa uhlelo %s" + +#, fuzzy +#~ msgid "%s is lacking the requirement %s" +#~ msgstr "%s ilahlekelwe into edingekayo %s" + +#~ msgid ", Action: " +#~ msgstr ", Isinyathelo:" + +#~ msgid ", Trigger: " +#~ msgstr ", Qalisa:" + +#~ msgid "package" +#~ msgstr "iphakheji" + +#~ msgid "selection" +#~ msgstr "okukhethiwe" + +#~ msgid "pattern" +#~ msgstr "iphethini" + +#~ msgid "product" +#~ msgstr "umkhiqizo" + +#~ msgid "patch" +#~ msgstr "isichibiyelo" + +#~ msgid "script" +#~ msgstr "I-script" + +#~ msgid "message" +#~ msgstr "umyalezo" + +#~ msgid "atom" +#~ msgstr "i-athomu" + +#~ msgid "system" +#~ msgstr "isistimu" + +#~ msgid "Resolvable" +#~ msgstr "Isixazululi" + +#~ msgid "Marking this resolution attempt as invalid." +#~ msgstr "Ukuphawula lomzamo we-resolution akusebenzi." + +#~ msgid "Marking resolvable %s as uninstallable" +#~ msgstr "Ukuphawula isixazululi %s njengesingafakeki" + +#, fuzzy +#~ msgid "" +#~ "%s is scheduled to be installed, but this is impossible due to dependency " +#~ "problems." +#~ msgstr "" +#~ "%s ihlelelwe ukuba ifakwe, kodwa lokhu akunakwenzeka ngenxa yezinkinga " +#~ "zezinhlelo okuncikwe kuzo." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s since it is already marked as needed to be uninstalled" +#~ msgstr "Ayikwazi ukufaka i-%s njengoba isiphawulwe ukuthi idinga ukukhiswa" + +#, fuzzy +#~ msgid "Can't install %s, because it does not apply to this system." +#~ msgstr "" +#~ "Ayikwazi ukufaka i-%s njengoba ingakwazi ukuyisebenzisa kule sistimu." + +#, fuzzy +#~ msgid "" +#~ "Can't install %s, because %s is already marked as needed to for " +#~ "installation" +#~ msgstr "" +#~ "Ayikwazi ukufaka i-%s njengoba %s isiphawulwe ukuthi idinga ukukhiswa" + +#~ msgid "This would invalidate %s." +#~ msgstr "Lokhu kuzokwenza i-%s ingasebenzi." + +#~ msgid "Establishing %s" +#~ msgstr "Imisa %s" + +#~ msgid "Installing %s" +#~ msgstr "Ifaka %s" + +#~ msgid "Updating %s to %s" +#~ msgstr "Ivuselela %s kwi-%s" + +#~ msgid "Skipping %s: already installed" +#~ msgstr "Yeqa %s: isifakiwe kakade" + +#, fuzzy +#~ msgid "There are no alternative providers of %s installed" +#~ msgstr "Abekho abanye abaphakeli abafakiwe be-%s" + +#~ msgid "for %s" +#~ msgstr "nge-%s" + +#, fuzzy +#~ msgid "Upgrading to %s to avoid removing %s is not possible." +#~ msgstr "Ukuvuselela kwi-%s ukuze ugweme ukususa %s akunakwenzeka." + +#~ msgid "%s provides %s, but is scheduled to be uninstalled." +#~ msgstr "%s ihlinzeka nge-%s, kodwa ihlelelwe ukuba ikhishwe." + +#~ msgid "%s provides %s, but another version of that %s is already installed." +#~ msgstr "" +#~ "%s ihlinzeka nge-%s, kodwa olunye uhlelo lwale-%s selufakiwe kakade." + +#~ msgid "" +#~ "%s provides %s, but it is uninstallable. Try installing it on its own " +#~ "for more details." +#~ msgstr "" +#~ "%s ihlinzeka nge-%s, kodwa ayikhipheki. Zama ukuyifaka yodwa ukuze " +#~ "uthole imininingwane eyengeziwe." + +#~ msgid "%s provides %s, but it is locked." +#~ msgstr "%s ihlinzeka nge-%s, kodwa ihluthulelwe." + +#~ msgid "%s provides %s, but is scheduled to be kept." +#~ msgstr "%s ihlinzeka nge-%s, kodwa ihlelelwe ukuba igcinwe." + +#, fuzzy +#~ msgid "%s provides %s, but has another vendor (%s)." +#~ msgstr "%s ihlinzeka nge-%s, kodwa inobunye ubuciko bomklamo." + +#~ msgid "Can't satisfy requirement %s for %s" +#~ msgstr "Ayikwazi ukwanelisa isidingo se-%s ye-%s" + +#, fuzzy +#~ msgid "" +#~ "%s is required by another resolvable selected for installation, so it " +#~ "won't be unlinked." +#~ msgstr "" +#~ "%s idingwa ngesinye isixazululi esifakiwe, ngakho ngeke ingalinkeki." + +#, fuzzy +#~ msgid "" +#~ "%s is required by another installed resolvable, so it won't be unlinked." +#~ msgstr "" +#~ "%s idingwa ngesinye isixazululi esifakiwe, ngakho ngeke ingalinkeki." + +#, fuzzy +#~ msgid "" +#~ "A conflict over %s (%s) requires the removal of %s which is scheduled for " +#~ "installation" +#~ msgstr "Ingxabano nge-%s (%s) idinga ukususwa kwe-%s ezofakwa " + +#~ msgid "Marking %s as uninstallable due to conflicts over %s" +#~ msgstr "Ukuphawula i-%s njengengafakeki ngenxa yezingxabano nge-%s" + +#~ msgid "from %s" +#~ msgstr "ivela %s" + +#~ msgid " Error!" +#~ msgstr "Iphutha!" + +#~ msgid " Important!" +#~ msgstr "Kubalulekile!" + +#~ msgid "%s depended on %s" +#~ msgstr "%s yencike kwi- %s" + +#, fuzzy +#~ msgid "%s is recommended by %s" +#~ msgstr "%s idingwa yi- %s" + +#, fuzzy +#~ msgid "%s is suggested by %s" +#~ msgstr "%s idingwa yi- %s" + +#, fuzzy +#~ msgid "%s is enhanced by %s" +#~ msgstr "%s ithathelwa indawo yi- %s" + +#, fuzzy +#~ msgid "%s is supplemented by %s" +#~ msgstr "%s idingwa yi- %s" + +#~ msgid "%s part of %s" +#~ msgstr "%s ingxenye ye- %s" + +#, fuzzy +#~ msgid "Double timeout" +#~ msgstr "Ukuchofoza Kabili Kuphelelwe Isikhathi " + +#, fuzzy +#~ msgid "%s is freshened by %s" +#~ msgstr "%s idingwa yi- %s" + +#~ msgid "Unable to parse Url authority" +#~ msgstr "Ayikwazi ukucaza igunya le-Url" + +#~ msgid "Ignore this requirement generally" +#~ msgstr "Sishaye indiva lesi sidingo kaningi" + +#~ msgid "" +#~ "%s is required by other to-be-installed resolvable, so it won't be " +#~ "unlinked." +#~ msgstr "" +#~ "%s idingwa ngesinye isixazululi esizofakwa, ngakho ngeke ingalinkeki." + +#~ msgid "Cannot create a file needed to perform update installation." +#~ msgstr "" +#~ "Ayikwazi ukwakha ifayela edingekayo ukuze ifake uhlelo lokuvuselela." + +#~ msgid "Unable to restore all sources." +#~ msgstr "Ayikwazi ukubuyisela yonke imithombo." + +#~ msgid "" +#~ "At least one source already registered, stored sources cannot be restored." +#~ msgstr "" +#~ "Okungenani umthombo owodwa usubhalisiwe kakade, imithombo egciniwe " +#~ "ayinakubuyiselwa." + +#~ msgid "Cannot be install %s to fulfil the dependencies of %s" +#~ msgstr "Ayikwazi ukufaka %s ukze igcwalise izinhlelo okuncikwe kuzo ze%s" + +#~ msgid "%s dependend on %s" +#~ msgstr "%s ibincike kwi- %s" + +#~ msgid "Reading index files" +#~ msgstr "Ifuna amafayela e-index" + +#~ msgid "The signed repomd.xml file failed the signature check." +#~ msgstr "Ifayela ye-repomd.xml esayiniwe ihlulekile lapho ihlolwa isignisha." + +#~ msgid "Reading product from %s" +#~ msgstr "Ifunda umkhiqizo ovela kwi-%s" + +#~ msgid "Reading filelist from %s" +#~ msgstr "Ifunda uhlu lwamafayela oluvela kwi-%s" + +#~ msgid "Reading packages from %s" +#~ msgstr "Ifunda amaphakheji avela kwi-%s" + +#~ msgid "Reading selection from %s" +#~ msgstr "Ifunda okukhethiwe okuvela kwi-%s" + +#~ msgid "Reading pattern from %s" +#~ msgstr "Ifunda iphethini evela kwi-%s" + +#~ msgid "Reading patches index %s" +#~ msgstr "Ifunda i-index %s yezichibiyelo" + +#~ msgid "Reading patch %s" +#~ msgstr "Ifunda isichibiyelo %s" + +#~ msgid "The script file failed the checksum test." +#~ msgstr "I-script sihlulekile lapho kwenziwa ukuhlolwa kwe-checksum." + +#~ msgid "Reading packages file" +#~ msgstr "Ifunda ifayela yamaphakheji" + +#~ msgid "Reading translation: %s" +#~ msgstr "Ifunda inkumusho: %s" + +#, fuzzy +#~ msgid "" +#~ "Package %s fails integrity check. Do you want to retry, or abort " +#~ "installation?" +#~ msgstr "" +#~ "Iphakheji %s ihlulekile lapho ihlolwa ukuthembeka. Ufuna ukuphinde uzame " +#~ "ukuyilanda futhi, noma uyeke ukufaka uhlelo?" + +#~ msgid " miss checksum." +#~ msgstr "yeqe i-checksum." + +#~ msgid " fails checksum verification." +#~ msgstr "ihlulekile lapho kufakazelwa i-checksum." + +#~ msgid "Downloading %s" +#~ msgstr "Ilanda i-%s" diff --git a/po/zypp.pot b/po/zypp.pot new file mode 100644 index 0000000..8ac85ed --- /dev/null +++ b/po/zypp.pot @@ -0,0 +1,5171 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR SuSE Linux GmbH, Nuernberg +# This file is distributed under the same license as the zypp package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: zypp\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2024-07-15 16:12+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=CHARSET\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" + +#: zypp/CountryCode.cc:50 +msgid "Unknown country: " +msgstr "" + +#. Defined CountryCode constants +#. Defined LanguageCode constants +#: zypp/CountryCode.cc:149 zypp/LanguageCode.cc:148 +msgid "No Code" +msgstr "" + +#: zypp/CountryCode.cc:158 +msgid "Andorra" +msgstr "" + +#. :AND:020: +#: zypp/CountryCode.cc:159 +msgid "United Arab Emirates" +msgstr "" + +#. :ARE:784: +#: zypp/CountryCode.cc:160 +msgid "Afghanistan" +msgstr "" + +#. :AFG:004: +#: zypp/CountryCode.cc:161 +msgid "Antigua and Barbuda" +msgstr "" + +#. :ATG:028: +#: zypp/CountryCode.cc:162 +msgid "Anguilla" +msgstr "" + +#. :AIA:660: +#: zypp/CountryCode.cc:163 +msgid "Albania" +msgstr "" + +#. :ALB:008: +#: zypp/CountryCode.cc:164 +msgid "Armenia" +msgstr "" + +#. :ARM:051: +#: zypp/CountryCode.cc:165 +msgid "Netherlands Antilles" +msgstr "" + +#. :ANT:530: +#: zypp/CountryCode.cc:166 +msgid "Angola" +msgstr "" + +#. :AGO:024: +#: zypp/CountryCode.cc:167 +msgid "Antarctica" +msgstr "" + +#. :ATA:010: +#: zypp/CountryCode.cc:168 +msgid "Argentina" +msgstr "" + +#. :ARG:032: +#: zypp/CountryCode.cc:169 +msgid "American Samoa" +msgstr "" + +#. :ASM:016: +#: zypp/CountryCode.cc:170 +msgid "Austria" +msgstr "" + +#. :AUT:040: +#: zypp/CountryCode.cc:171 +msgid "Australia" +msgstr "" + +#. :AUS:036: +#: zypp/CountryCode.cc:172 +msgid "Aruba" +msgstr "" + +#. :ABW:533: +#: zypp/CountryCode.cc:173 +msgid "Aland Islands" +msgstr "" + +#. :ALA:248: +#: zypp/CountryCode.cc:174 +msgid "Azerbaijan" +msgstr "" + +#. :AZE:031: +#: zypp/CountryCode.cc:175 +msgid "Bosnia and Herzegovina" +msgstr "" + +#. :BIH:070: +#: zypp/CountryCode.cc:176 +msgid "Barbados" +msgstr "" + +#. :BRB:052: +#: zypp/CountryCode.cc:177 +msgid "Bangladesh" +msgstr "" + +#. :BGD:050: +#: zypp/CountryCode.cc:178 +msgid "Belgium" +msgstr "" + +#. :BEL:056: +#: zypp/CountryCode.cc:179 +msgid "Burkina Faso" +msgstr "" + +#. :BFA:854: +#: zypp/CountryCode.cc:180 +msgid "Bulgaria" +msgstr "" + +#. :BGR:100: +#: zypp/CountryCode.cc:181 +msgid "Bahrain" +msgstr "" + +#. :BHR:048: +#: zypp/CountryCode.cc:182 +msgid "Burundi" +msgstr "" + +#. :BDI:108: +#: zypp/CountryCode.cc:183 +msgid "Benin" +msgstr "" + +#. :BEN:204: +#: zypp/CountryCode.cc:184 +msgid "Bermuda" +msgstr "" + +#. :BMU:060: +#: zypp/CountryCode.cc:185 +msgid "Brunei Darussalam" +msgstr "" + +#. :BRN:096: +#: zypp/CountryCode.cc:186 +msgid "Bolivia" +msgstr "" + +#. :BOL:068: +#: zypp/CountryCode.cc:187 +msgid "Brazil" +msgstr "" + +#. :BRA:076: +#: zypp/CountryCode.cc:188 +msgid "Bahamas" +msgstr "" + +#. :BHS:044: +#: zypp/CountryCode.cc:189 +msgid "Bhutan" +msgstr "" + +#. :BTN:064: +#: zypp/CountryCode.cc:190 +msgid "Bouvet Island" +msgstr "" + +#. :BVT:074: +#: zypp/CountryCode.cc:191 +msgid "Botswana" +msgstr "" + +#. :BWA:072: +#: zypp/CountryCode.cc:192 +msgid "Belarus" +msgstr "" + +#. :BLR:112: +#: zypp/CountryCode.cc:193 +msgid "Belize" +msgstr "" + +#. :BLZ:084: +#: zypp/CountryCode.cc:194 +msgid "Canada" +msgstr "" + +#. :CAN:124: +#: zypp/CountryCode.cc:195 +msgid "Cocos (Keeling) Islands" +msgstr "" + +#. :CCK:166: +#. :CAF:140: +#: zypp/CountryCode.cc:196 zypp/CountryCode.cc:198 +msgid "Congo" +msgstr "" + +#. :COD:180: +#: zypp/CountryCode.cc:197 +msgid "Central African Republic" +msgstr "" + +#. :COG:178: +#: zypp/CountryCode.cc:199 +msgid "Switzerland" +msgstr "" + +#. :CHE:756: +#: zypp/CountryCode.cc:200 +msgid "Cote D'Ivoire" +msgstr "" + +#. :CIV:384: +#: zypp/CountryCode.cc:201 +msgid "Cook Islands" +msgstr "" + +#. :COK:184: +#: zypp/CountryCode.cc:202 +msgid "Chile" +msgstr "" + +#. :CHL:152: +#: zypp/CountryCode.cc:203 +msgid "Cameroon" +msgstr "" + +#. :CMR:120: +#: zypp/CountryCode.cc:204 +msgid "China" +msgstr "" + +#. :CHN:156: +#: zypp/CountryCode.cc:205 +msgid "Colombia" +msgstr "" + +#. :COL:170: +#: zypp/CountryCode.cc:206 +msgid "Costa Rica" +msgstr "" + +#. :CRI:188: +#: zypp/CountryCode.cc:207 +msgid "Cuba" +msgstr "" + +#. :CUB:192: +#: zypp/CountryCode.cc:208 +msgid "Cape Verde" +msgstr "" + +#. :CPV:132: +#: zypp/CountryCode.cc:209 +msgid "Christmas Island" +msgstr "" + +#. :CXR:162: +#: zypp/CountryCode.cc:210 +msgid "Cyprus" +msgstr "" + +#. :CYP:196: +#: zypp/CountryCode.cc:211 +msgid "Czech Republic" +msgstr "" + +#. :CZE:203: +#: zypp/CountryCode.cc:212 +msgid "Germany" +msgstr "" + +#. :DEU:276: +#: zypp/CountryCode.cc:213 +msgid "Djibouti" +msgstr "" + +#. :DJI:262: +#: zypp/CountryCode.cc:214 +msgid "Denmark" +msgstr "" + +#. :DNK:208: +#: zypp/CountryCode.cc:215 +msgid "Dominica" +msgstr "" + +#. :DMA:212: +#: zypp/CountryCode.cc:216 +msgid "Dominican Republic" +msgstr "" + +#. :DOM:214: +#: zypp/CountryCode.cc:217 +msgid "Algeria" +msgstr "" + +#. :DZA:012: +#: zypp/CountryCode.cc:218 +msgid "Ecuador" +msgstr "" + +#. :ECU:218: +#: zypp/CountryCode.cc:219 +msgid "Estonia" +msgstr "" + +#. :EST:233: +#: zypp/CountryCode.cc:220 +msgid "Egypt" +msgstr "" + +#. :EGY:818: +#: zypp/CountryCode.cc:221 +msgid "Western Sahara" +msgstr "" + +#. :ESH:732: +#: zypp/CountryCode.cc:222 +msgid "Eritrea" +msgstr "" + +#. :ERI:232: +#: zypp/CountryCode.cc:223 +msgid "Spain" +msgstr "" + +#. :ESP:724: +#: zypp/CountryCode.cc:224 +msgid "Ethiopia" +msgstr "" + +#. :ETH:231: +#: zypp/CountryCode.cc:225 +msgid "Finland" +msgstr "" + +#. :FIN:246: +#: zypp/CountryCode.cc:226 +msgid "Fiji" +msgstr "" + +#. :FJI:242: +#: zypp/CountryCode.cc:227 +msgid "Falkland Islands (Malvinas)" +msgstr "" + +#. :FLK:238: +#: zypp/CountryCode.cc:228 +msgid "Federated States of Micronesia" +msgstr "" + +#. :FSM:583: +#: zypp/CountryCode.cc:229 +msgid "Faroe Islands" +msgstr "" + +#. :FRO:234: +#: zypp/CountryCode.cc:230 +msgid "France" +msgstr "" + +#. :FRA:250: +#: zypp/CountryCode.cc:231 +msgid "Metropolitan France" +msgstr "" + +#. :FXX:249: +#: zypp/CountryCode.cc:232 +msgid "Gabon" +msgstr "" + +#. :GAB:266: +#: zypp/CountryCode.cc:233 +msgid "United Kingdom" +msgstr "" + +#. :GBR:826: +#: zypp/CountryCode.cc:234 +msgid "Grenada" +msgstr "" + +#. :GRD:308: +#: zypp/CountryCode.cc:235 +msgid "Georgia" +msgstr "" + +#. :GEO:268: +#: zypp/CountryCode.cc:236 +msgid "French Guiana" +msgstr "" + +#. :GUF:254: +#: zypp/CountryCode.cc:237 +msgid "Guernsey" +msgstr "" + +#: zypp/CountryCode.cc:238 +msgid "Ghana" +msgstr "" + +#. :GHA:288: +#: zypp/CountryCode.cc:239 +msgid "Gibraltar" +msgstr "" + +#. :GIB:292: +#: zypp/CountryCode.cc:240 +msgid "Greenland" +msgstr "" + +#. :GRL:304: +#: zypp/CountryCode.cc:241 +msgid "Gambia" +msgstr "" + +#. :GMB:270: +#: zypp/CountryCode.cc:242 +msgid "Guinea" +msgstr "" + +#. :GIN:324: +#: zypp/CountryCode.cc:243 +msgid "Guadeloupe" +msgstr "" + +#. :GLP:312: +#: zypp/CountryCode.cc:244 +msgid "Equatorial Guinea" +msgstr "" + +#. :GNQ:226: +#: zypp/CountryCode.cc:245 +msgid "Greece" +msgstr "" + +#. :GRC:300: +#: zypp/CountryCode.cc:246 +msgid "South Georgia and the South Sandwich Islands" +msgstr "" + +#. :SGS:239: +#: zypp/CountryCode.cc:247 +msgid "Guatemala" +msgstr "" + +#. :GTM:320: +#: zypp/CountryCode.cc:248 +msgid "Guam" +msgstr "" + +#. :GUM:316: +#: zypp/CountryCode.cc:249 +msgid "Guinea-Bissau" +msgstr "" + +#. :GNB:624: +#: zypp/CountryCode.cc:250 +msgid "Guyana" +msgstr "" + +#. :GUY:328: +#: zypp/CountryCode.cc:251 +msgid "Hong Kong" +msgstr "" + +#. :HKG:344: +#: zypp/CountryCode.cc:252 +msgid "Heard Island and McDonald Islands" +msgstr "" + +#. :HMD:334: +#: zypp/CountryCode.cc:253 +msgid "Honduras" +msgstr "" + +#. :HND:340: +#: zypp/CountryCode.cc:254 +msgid "Croatia" +msgstr "" + +#. :HRV:191: +#: zypp/CountryCode.cc:255 +msgid "Haiti" +msgstr "" + +#. :HTI:332: +#: zypp/CountryCode.cc:256 +msgid "Hungary" +msgstr "" + +#. :HUN:348: +#: zypp/CountryCode.cc:257 +msgid "Indonesia" +msgstr "" + +#. :IDN:360: +#: zypp/CountryCode.cc:258 +msgid "Ireland" +msgstr "" + +#. :IRL:372: +#: zypp/CountryCode.cc:259 +msgid "Israel" +msgstr "" + +#. :ISR:376: +#: zypp/CountryCode.cc:260 +msgid "Isle of Man" +msgstr "" + +#: zypp/CountryCode.cc:261 +msgid "India" +msgstr "" + +#. :IND:356: +#: zypp/CountryCode.cc:262 +msgid "British Indian Ocean Territory" +msgstr "" + +#. :IOT:086: +#: zypp/CountryCode.cc:263 +msgid "Iraq" +msgstr "" + +#. :IRQ:368: +#: zypp/CountryCode.cc:264 +msgid "Iran" +msgstr "" + +#. :IRN:364: +#: zypp/CountryCode.cc:265 +msgid "Iceland" +msgstr "" + +#. :ISL:352: +#: zypp/CountryCode.cc:266 +msgid "Italy" +msgstr "" + +#. :ITA:380: +#: zypp/CountryCode.cc:267 +msgid "Jersey" +msgstr "" + +#: zypp/CountryCode.cc:268 +msgid "Jamaica" +msgstr "" + +#. :JAM:388: +#: zypp/CountryCode.cc:269 +msgid "Jordan" +msgstr "" + +#. :JOR:400: +#: zypp/CountryCode.cc:270 +msgid "Japan" +msgstr "" + +#. :JPN:392: +#: zypp/CountryCode.cc:271 +msgid "Kenya" +msgstr "" + +#. :KEN:404: +#: zypp/CountryCode.cc:272 +msgid "Kyrgyzstan" +msgstr "" + +#. :KGZ:417: +#: zypp/CountryCode.cc:273 +msgid "Cambodia" +msgstr "" + +#. :KHM:116: +#: zypp/CountryCode.cc:274 +msgid "Kiribati" +msgstr "" + +#. :KIR:296: +#: zypp/CountryCode.cc:275 +msgid "Comoros" +msgstr "" + +#. :COM:174: +#: zypp/CountryCode.cc:276 +msgid "Saint Kitts and Nevis" +msgstr "" + +#. :KNA:659: +#: zypp/CountryCode.cc:277 +msgid "North Korea" +msgstr "" + +#. :PRK:408: +#: zypp/CountryCode.cc:278 +msgid "South Korea" +msgstr "" + +#. :KOR:410: +#: zypp/CountryCode.cc:279 +msgid "Kuwait" +msgstr "" + +#. :KWT:414: +#: zypp/CountryCode.cc:280 +msgid "Cayman Islands" +msgstr "" + +#. :CYM:136: +#: zypp/CountryCode.cc:281 +msgid "Kazakhstan" +msgstr "" + +#. :KAZ:398: +#: zypp/CountryCode.cc:282 +msgid "Lao People's Democratic Republic" +msgstr "" + +#. :LAO:418: +#: zypp/CountryCode.cc:283 +msgid "Lebanon" +msgstr "" + +#. :LBN:422: +#: zypp/CountryCode.cc:284 +msgid "Saint Lucia" +msgstr "" + +#. :LCA:662: +#: zypp/CountryCode.cc:285 +msgid "Liechtenstein" +msgstr "" + +#. :LIE:438: +#: zypp/CountryCode.cc:286 +msgid "Sri Lanka" +msgstr "" + +#. :LKA:144: +#: zypp/CountryCode.cc:287 +msgid "Liberia" +msgstr "" + +#. :LBR:430: +#: zypp/CountryCode.cc:288 +msgid "Lesotho" +msgstr "" + +#. :LSO:426: +#: zypp/CountryCode.cc:289 +msgid "Lithuania" +msgstr "" + +#. :LTU:440: +#: zypp/CountryCode.cc:290 +msgid "Luxembourg" +msgstr "" + +#. :LUX:442: +#: zypp/CountryCode.cc:291 +msgid "Latvia" +msgstr "" + +#. :LVA:428: +#: zypp/CountryCode.cc:292 +msgid "Libya" +msgstr "" + +#. :LBY:434: +#: zypp/CountryCode.cc:293 +msgid "Morocco" +msgstr "" + +#. :MAR:504: +#: zypp/CountryCode.cc:294 +msgid "Monaco" +msgstr "" + +#. :MCO:492: +#: zypp/CountryCode.cc:295 +msgid "Moldova" +msgstr "" + +#. :MDA:498: +#: zypp/CountryCode.cc:296 +msgid "Montenegro" +msgstr "" + +#: zypp/CountryCode.cc:297 +msgid "Saint Martin" +msgstr "" + +#: zypp/CountryCode.cc:298 +msgid "Madagascar" +msgstr "" + +#. :MDG:450: +#: zypp/CountryCode.cc:299 +msgid "Marshall Islands" +msgstr "" + +#. :MHL:584: +#: zypp/CountryCode.cc:300 +msgid "Macedonia" +msgstr "" + +#. :MKD:807: +#: zypp/CountryCode.cc:301 +msgid "Mali" +msgstr "" + +#. :MLI:466: +#: zypp/CountryCode.cc:302 +msgid "Myanmar" +msgstr "" + +#. :MMR:104: +#: zypp/CountryCode.cc:303 +msgid "Mongolia" +msgstr "" + +#. :MNG:496: +#: zypp/CountryCode.cc:304 +msgid "Macao" +msgstr "" + +#. :MAC:446: +#: zypp/CountryCode.cc:305 +msgid "Northern Mariana Islands" +msgstr "" + +#. :MNP:580: +#: zypp/CountryCode.cc:306 +msgid "Martinique" +msgstr "" + +#. :MTQ:474: +#: zypp/CountryCode.cc:307 +msgid "Mauritania" +msgstr "" + +#. :MRT:478: +#: zypp/CountryCode.cc:308 +msgid "Montserrat" +msgstr "" + +#. :MSR:500: +#: zypp/CountryCode.cc:309 +msgid "Malta" +msgstr "" + +#. :MLT:470: +#: zypp/CountryCode.cc:310 +msgid "Mauritius" +msgstr "" + +#. :MUS:480: +#: zypp/CountryCode.cc:311 +msgid "Maldives" +msgstr "" + +#. :MDV:462: +#: zypp/CountryCode.cc:312 +msgid "Malawi" +msgstr "" + +#. :MWI:454: +#: zypp/CountryCode.cc:313 +msgid "Mexico" +msgstr "" + +#. :MEX:484: +#: zypp/CountryCode.cc:314 +msgid "Malaysia" +msgstr "" + +#. :MYS:458: +#: zypp/CountryCode.cc:315 +msgid "Mozambique" +msgstr "" + +#. :MOZ:508: +#: zypp/CountryCode.cc:316 +msgid "Namibia" +msgstr "" + +#. :NAM:516: +#: zypp/CountryCode.cc:317 +msgid "New Caledonia" +msgstr "" + +#. :NCL:540: +#: zypp/CountryCode.cc:318 +msgid "Niger" +msgstr "" + +#. :NER:562: +#: zypp/CountryCode.cc:319 +msgid "Norfolk Island" +msgstr "" + +#. :NFK:574: +#: zypp/CountryCode.cc:320 +msgid "Nigeria" +msgstr "" + +#. :NGA:566: +#: zypp/CountryCode.cc:321 +msgid "Nicaragua" +msgstr "" + +#. :NIC:558: +#: zypp/CountryCode.cc:322 +msgid "Netherlands" +msgstr "" + +#. :NLD:528: +#: zypp/CountryCode.cc:323 +msgid "Norway" +msgstr "" + +#. :NOR:578: +#: zypp/CountryCode.cc:324 +msgid "Nepal" +msgstr "" + +#. :NPL:524: +#. language code: nau na +#: zypp/CountryCode.cc:325 zypp/LanguageCode.cc:781 +msgid "Nauru" +msgstr "" + +#. :NRU:520: +#: zypp/CountryCode.cc:326 +msgid "Niue" +msgstr "" + +#. :NIU:570: +#: zypp/CountryCode.cc:327 +msgid "New Zealand" +msgstr "" + +#. :NZL:554: +#: zypp/CountryCode.cc:328 +msgid "Oman" +msgstr "" + +#. :OMN:512: +#: zypp/CountryCode.cc:329 +msgid "Panama" +msgstr "" + +#. :PAN:591: +#: zypp/CountryCode.cc:330 +msgid "Peru" +msgstr "" + +#. :PER:604: +#: zypp/CountryCode.cc:331 +msgid "French Polynesia" +msgstr "" + +#. :PYF:258: +#: zypp/CountryCode.cc:332 +msgid "Papua New Guinea" +msgstr "" + +#. :PNG:598: +#: zypp/CountryCode.cc:333 +msgid "Philippines" +msgstr "" + +#. :PHL:608: +#: zypp/CountryCode.cc:334 +msgid "Pakistan" +msgstr "" + +#. :PAK:586: +#: zypp/CountryCode.cc:335 +msgid "Poland" +msgstr "" + +#. :POL:616: +#: zypp/CountryCode.cc:336 +msgid "Saint Pierre and Miquelon" +msgstr "" + +#. :SPM:666: +#: zypp/CountryCode.cc:337 +msgid "Pitcairn" +msgstr "" + +#. :PCN:612: +#: zypp/CountryCode.cc:338 +msgid "Puerto Rico" +msgstr "" + +#. :PRI:630: +#: zypp/CountryCode.cc:339 +msgid "Palestinian Territory" +msgstr "" + +#. :PSE:275: +#: zypp/CountryCode.cc:340 +msgid "Portugal" +msgstr "" + +#. :PRT:620: +#: zypp/CountryCode.cc:341 +msgid "Palau" +msgstr "" + +#. :PLW:585: +#: zypp/CountryCode.cc:342 +msgid "Paraguay" +msgstr "" + +#. :PRY:600: +#: zypp/CountryCode.cc:343 +msgid "Qatar" +msgstr "" + +#. :QAT:634: +#: zypp/CountryCode.cc:344 +msgid "Reunion" +msgstr "" + +#. :REU:638: +#: zypp/CountryCode.cc:345 +msgid "Romania" +msgstr "" + +#. :ROU:642: +#: zypp/CountryCode.cc:346 +msgid "Serbia" +msgstr "" + +#: zypp/CountryCode.cc:347 +msgid "Russian Federation" +msgstr "" + +#. :RUS:643: +#: zypp/CountryCode.cc:348 +msgid "Rwanda" +msgstr "" + +#. :RWA:646: +#: zypp/CountryCode.cc:349 +msgid "Saudi Arabia" +msgstr "" + +#. :SAU:682: +#: zypp/CountryCode.cc:350 +msgid "Solomon Islands" +msgstr "" + +#. :SLB:090: +#: zypp/CountryCode.cc:351 +msgid "Seychelles" +msgstr "" + +#. :SYC:690: +#: zypp/CountryCode.cc:352 +msgid "Sudan" +msgstr "" + +#. :SDN:736: +#: zypp/CountryCode.cc:353 +msgid "Sweden" +msgstr "" + +#. :SWE:752: +#: zypp/CountryCode.cc:354 +msgid "Singapore" +msgstr "" + +#. :SGP:702: +#: zypp/CountryCode.cc:355 +msgid "Saint Helena" +msgstr "" + +#. :SHN:654: +#: zypp/CountryCode.cc:356 +msgid "Slovenia" +msgstr "" + +#. :SVN:705: +#: zypp/CountryCode.cc:357 +msgid "Svalbard and Jan Mayen" +msgstr "" + +#. :SJM:744: +#: zypp/CountryCode.cc:358 +msgid "Slovakia" +msgstr "" + +#. :SVK:703: +#: zypp/CountryCode.cc:359 +msgid "Sierra Leone" +msgstr "" + +#. :SLE:694: +#: zypp/CountryCode.cc:360 +msgid "San Marino" +msgstr "" + +#. :SMR:674: +#: zypp/CountryCode.cc:361 +msgid "Senegal" +msgstr "" + +#. :SEN:686: +#: zypp/CountryCode.cc:362 +msgid "Somalia" +msgstr "" + +#. :SOM:706: +#: zypp/CountryCode.cc:363 +msgid "Suriname" +msgstr "" + +#. :SUR:740: +#: zypp/CountryCode.cc:364 +msgid "Sao Tome and Principe" +msgstr "" + +#. :STP:678: +#: zypp/CountryCode.cc:365 +msgid "El Salvador" +msgstr "" + +#. :SLV:222: +#: zypp/CountryCode.cc:366 +msgid "Syria" +msgstr "" + +#. :SYR:760: +#: zypp/CountryCode.cc:367 +msgid "Swaziland" +msgstr "" + +#. :SWZ:748: +#: zypp/CountryCode.cc:368 +msgid "Turks and Caicos Islands" +msgstr "" + +#. :TCA:796: +#: zypp/CountryCode.cc:369 +msgid "Chad" +msgstr "" + +#. :TCD:148: +#: zypp/CountryCode.cc:370 +msgid "French Southern Territories" +msgstr "" + +#. :ATF:260: +#: zypp/CountryCode.cc:371 +msgid "Togo" +msgstr "" + +#. :TGO:768: +#: zypp/CountryCode.cc:372 +msgid "Thailand" +msgstr "" + +#. :THA:764: +#: zypp/CountryCode.cc:373 +msgid "Tajikistan" +msgstr "" + +#. :TJK:762: +#. language code: tkl +#: zypp/CountryCode.cc:374 zypp/LanguageCode.cc:1045 +msgid "Tokelau" +msgstr "" + +#. :TKL:772: +#: zypp/CountryCode.cc:375 +msgid "Turkmenistan" +msgstr "" + +#. :TKM:795: +#: zypp/CountryCode.cc:376 +msgid "Tunisia" +msgstr "" + +#. :TUN:788: +#: zypp/CountryCode.cc:377 +msgid "Tonga" +msgstr "" + +#. :TON:776: +#: zypp/CountryCode.cc:378 +msgid "East Timor" +msgstr "" + +#. :TLS:626: +#: zypp/CountryCode.cc:379 +msgid "Turkey" +msgstr "" + +#. :TUR:792: +#: zypp/CountryCode.cc:380 +msgid "Trinidad and Tobago" +msgstr "" + +#. :TTO:780: +#. language code: tvl +#: zypp/CountryCode.cc:381 zypp/LanguageCode.cc:1075 +msgid "Tuvalu" +msgstr "" + +#. :TUV:798: +#: zypp/CountryCode.cc:382 +msgid "Taiwan" +msgstr "" + +#. :TWN:158: +#: zypp/CountryCode.cc:383 +msgid "Tanzania" +msgstr "" + +#. :TZA:834: +#: zypp/CountryCode.cc:384 +msgid "Ukraine" +msgstr "" + +#. :UKR:804: +#: zypp/CountryCode.cc:385 +msgid "Uganda" +msgstr "" + +#. :UGA:800: +#: zypp/CountryCode.cc:386 +msgid "United States Minor Outlying Islands" +msgstr "" + +#. :UMI:581: +#: zypp/CountryCode.cc:387 +msgid "United States" +msgstr "" + +#. :USA:840: +#: zypp/CountryCode.cc:388 +msgid "Uruguay" +msgstr "" + +#. :URY:858: +#: zypp/CountryCode.cc:389 +msgid "Uzbekistan" +msgstr "" + +#. :UZB:860: +#: zypp/CountryCode.cc:390 +msgid "Holy See (Vatican City State)" +msgstr "" + +#. :VAT:336: +#: zypp/CountryCode.cc:391 +msgid "Saint Vincent and the Grenadines" +msgstr "" + +#. :VCT:670: +#: zypp/CountryCode.cc:392 +msgid "Venezuela" +msgstr "" + +#. :VEN:862: +#: zypp/CountryCode.cc:393 +msgid "British Virgin Islands" +msgstr "" + +#. :VGB:092: +#: zypp/CountryCode.cc:394 +msgid "Virgin Islands, U.S." +msgstr "" + +#. :VIR:850: +#: zypp/CountryCode.cc:395 +msgid "Vietnam" +msgstr "" + +#. :VNM:704: +#: zypp/CountryCode.cc:396 +msgid "Vanuatu" +msgstr "" + +#. :VUT:548: +#: zypp/CountryCode.cc:397 +msgid "Wallis and Futuna" +msgstr "" + +#. :WLF:876: +#: zypp/CountryCode.cc:398 +msgid "Samoa" +msgstr "" + +#. :WSM:882: +#: zypp/CountryCode.cc:399 +msgid "Yemen" +msgstr "" + +#. :YEM:887: +#: zypp/CountryCode.cc:400 +msgid "Mayotte" +msgstr "" + +#. :MYT:175: +#: zypp/CountryCode.cc:401 +msgid "South Africa" +msgstr "" + +#. :ZAF:710: +#: zypp/CountryCode.cc:402 +msgid "Zambia" +msgstr "" + +#. :ZMB:894: +#: zypp/CountryCode.cc:403 +msgid "Zimbabwe" +msgstr "" + +#: zypp/Dep.cc:96 +msgid "Provides" +msgstr "" + +#: zypp/Dep.cc:97 +msgid "Prerequires" +msgstr "" + +#: zypp/Dep.cc:98 +msgid "Requires" +msgstr "" + +#: zypp/Dep.cc:99 +msgid "Conflicts" +msgstr "" + +#: zypp/Dep.cc:100 +msgid "Obsoletes" +msgstr "" + +#: zypp/Dep.cc:101 +msgid "Recommends" +msgstr "" + +#: zypp/Dep.cc:102 +msgid "Suggests" +msgstr "" + +#: zypp/Dep.cc:103 +msgid "Enhances" +msgstr "" + +#: zypp/Dep.cc:104 +msgid "Supplements" +msgstr "" + +#. TranslatorExplanation first %s is key name, second is keyring name +#: zypp/KeyRing.cc:401 +#, c-format, boost-format +msgid "Tried to import not existent key %s into keyring %s" +msgstr "" + +#: zypp/KeyRing.cc:407 +msgid "Failed to import key." +msgstr "" + +#: zypp/KeyRing.cc:414 +msgid "Failed to delete key." +msgstr "" + +#: zypp/KeyRing.cc:420 +#, c-format, boost-format +msgid "Signature file %s not found" +msgstr "" + +#: zypp/LanguageCode.cc:49 +msgid "Unknown language: " +msgstr "" + +#. language code: aar aa +#: zypp/LanguageCode.cc:161 +msgid "Afar" +msgstr "" + +#. language code: abk ab +#: zypp/LanguageCode.cc:163 +msgid "Abkhazian" +msgstr "" + +#. language code: ace +#: zypp/LanguageCode.cc:165 +msgid "Achinese" +msgstr "" + +#. language code: ach +#: zypp/LanguageCode.cc:167 +msgid "Acoli" +msgstr "" + +#. language code: ada +#: zypp/LanguageCode.cc:169 +msgid "Adangme" +msgstr "" + +#. language code: ady +#: zypp/LanguageCode.cc:171 +msgid "Adyghe" +msgstr "" + +#. language code: afa +#: zypp/LanguageCode.cc:173 +msgid "Afro-Asiatic (Other)" +msgstr "" + +#. language code: afh +#: zypp/LanguageCode.cc:175 +msgid "Afrihili" +msgstr "" + +#. language code: afr af +#: zypp/LanguageCode.cc:177 +msgid "Afrikaans" +msgstr "" + +#. language code: ain +#: zypp/LanguageCode.cc:179 +msgid "Ainu" +msgstr "" + +#. language code: aka ak +#: zypp/LanguageCode.cc:181 +msgid "Akan" +msgstr "" + +#. language code: akk +#: zypp/LanguageCode.cc:183 +msgid "Akkadian" +msgstr "" + +#. language code: alb sqi sq +#: zypp/LanguageCode.cc:185 zypp/LanguageCode.cc:187 +msgid "Albanian" +msgstr "" + +#. language code: ale +#: zypp/LanguageCode.cc:189 +msgid "Aleut" +msgstr "" + +#. language code: alg +#: zypp/LanguageCode.cc:191 +msgid "Algonquian Languages" +msgstr "" + +#. language code: alt +#: zypp/LanguageCode.cc:193 +msgid "Southern Altai" +msgstr "" + +#. language code: amh am +#: zypp/LanguageCode.cc:195 +msgid "Amharic" +msgstr "" + +#. language code: ang +#: zypp/LanguageCode.cc:197 +msgid "English, Old (ca.450-1100)" +msgstr "" + +#. language code: apa +#: zypp/LanguageCode.cc:199 +msgid "Apache Languages" +msgstr "" + +#. language code: ara ar +#: zypp/LanguageCode.cc:201 +msgid "Arabic" +msgstr "" + +#. language code: arc +#: zypp/LanguageCode.cc:203 +msgid "Aramaic" +msgstr "" + +#. language code: arg an +#: zypp/LanguageCode.cc:205 +msgid "Aragonese" +msgstr "" + +#. language code: arm hye hy +#: zypp/LanguageCode.cc:207 zypp/LanguageCode.cc:209 +msgid "Armenian" +msgstr "" + +#. language code: arn +#: zypp/LanguageCode.cc:211 +msgid "Araucanian" +msgstr "" + +#. language code: arp +#: zypp/LanguageCode.cc:213 +msgid "Arapaho" +msgstr "" + +#. language code: art +#: zypp/LanguageCode.cc:215 +msgid "Artificial (Other)" +msgstr "" + +#. language code: arw +#: zypp/LanguageCode.cc:217 +msgid "Arawak" +msgstr "" + +#. language code: asm as +#: zypp/LanguageCode.cc:219 +msgid "Assamese" +msgstr "" + +#. language code: ast +#: zypp/LanguageCode.cc:221 +msgid "Asturian" +msgstr "" + +#. language code: ath +#: zypp/LanguageCode.cc:223 +msgid "Athapascan Languages" +msgstr "" + +#. language code: aus +#: zypp/LanguageCode.cc:225 +msgid "Australian Languages" +msgstr "" + +#. language code: ava av +#: zypp/LanguageCode.cc:227 +msgid "Avaric" +msgstr "" + +#. language code: ave ae +#: zypp/LanguageCode.cc:229 +msgid "Avestan" +msgstr "" + +#. language code: awa +#: zypp/LanguageCode.cc:231 +msgid "Awadhi" +msgstr "" + +#. language code: aym ay +#: zypp/LanguageCode.cc:233 +msgid "Aymara" +msgstr "" + +#. language code: aze az +#: zypp/LanguageCode.cc:235 +msgid "Azerbaijani" +msgstr "" + +#. language code: bad +#: zypp/LanguageCode.cc:237 +msgid "Banda" +msgstr "" + +#. language code: bai +#: zypp/LanguageCode.cc:239 +msgid "Bamileke Languages" +msgstr "" + +#. language code: bak ba +#: zypp/LanguageCode.cc:241 +msgid "Bashkir" +msgstr "" + +#. language code: bal +#: zypp/LanguageCode.cc:243 +msgid "Baluchi" +msgstr "" + +#. language code: bam bm +#: zypp/LanguageCode.cc:245 +msgid "Bambara" +msgstr "" + +#. language code: ban +#: zypp/LanguageCode.cc:247 +msgid "Balinese" +msgstr "" + +#. language code: baq eus eu +#: zypp/LanguageCode.cc:249 zypp/LanguageCode.cc:251 +msgid "Basque" +msgstr "" + +#. language code: bas +#: zypp/LanguageCode.cc:253 +msgid "Basa" +msgstr "" + +#. language code: bat +#: zypp/LanguageCode.cc:255 +msgid "Baltic (Other)" +msgstr "" + +#. language code: bej +#: zypp/LanguageCode.cc:257 +msgid "Beja" +msgstr "" + +#. language code: bel be +#: zypp/LanguageCode.cc:259 +msgid "Belarusian" +msgstr "" + +#. language code: bem +#: zypp/LanguageCode.cc:261 +msgid "Bemba" +msgstr "" + +#. language code: ben bn +#: zypp/LanguageCode.cc:263 +msgid "Bengali" +msgstr "" + +#. language code: ber +#: zypp/LanguageCode.cc:265 +msgid "Berber (Other)" +msgstr "" + +#. language code: bho +#: zypp/LanguageCode.cc:267 +msgid "Bhojpuri" +msgstr "" + +#. language code: bih bh +#: zypp/LanguageCode.cc:269 +msgid "Bihari" +msgstr "" + +#. language code: bik +#: zypp/LanguageCode.cc:271 +msgid "Bikol" +msgstr "" + +#. language code: bin +#: zypp/LanguageCode.cc:273 +msgid "Bini" +msgstr "" + +#. language code: bis bi +#: zypp/LanguageCode.cc:275 +msgid "Bislama" +msgstr "" + +#. language code: bla +#: zypp/LanguageCode.cc:277 +msgid "Siksika" +msgstr "" + +#. language code: bnt +#: zypp/LanguageCode.cc:279 +msgid "Bantu (Other)" +msgstr "" + +#. language code: bos bs +#: zypp/LanguageCode.cc:281 +msgid "Bosnian" +msgstr "" + +#. language code: bra +#: zypp/LanguageCode.cc:283 +msgid "Braj" +msgstr "" + +#. language code: bre br +#: zypp/LanguageCode.cc:285 +msgid "Breton" +msgstr "" + +#. language code: btk +#: zypp/LanguageCode.cc:287 +msgid "Batak (Indonesia)" +msgstr "" + +#. language code: bua +#: zypp/LanguageCode.cc:289 +msgid "Buriat" +msgstr "" + +#. language code: bug +#: zypp/LanguageCode.cc:291 +msgid "Buginese" +msgstr "" + +#. language code: bul bg +#: zypp/LanguageCode.cc:293 +msgid "Bulgarian" +msgstr "" + +#. language code: bur mya my +#: zypp/LanguageCode.cc:295 zypp/LanguageCode.cc:297 +msgid "Burmese" +msgstr "" + +#. language code: byn +#: zypp/LanguageCode.cc:299 +msgid "Blin" +msgstr "" + +#. language code: cad +#: zypp/LanguageCode.cc:301 +msgid "Caddo" +msgstr "" + +#. language code: cai +#: zypp/LanguageCode.cc:303 +msgid "Central American Indian (Other)" +msgstr "" + +#. language code: car +#: zypp/LanguageCode.cc:305 +msgid "Carib" +msgstr "" + +#. language code: cat ca +#: zypp/LanguageCode.cc:307 +msgid "Catalan" +msgstr "" + +#. language code: cau +#: zypp/LanguageCode.cc:309 +msgid "Caucasian (Other)" +msgstr "" + +#. language code: ceb +#: zypp/LanguageCode.cc:311 +msgid "Cebuano" +msgstr "" + +#. language code: cel +#: zypp/LanguageCode.cc:313 +msgid "Celtic (Other)" +msgstr "" + +#. language code: cha ch +#: zypp/LanguageCode.cc:315 +msgid "Chamorro" +msgstr "" + +#. language code: chb +#: zypp/LanguageCode.cc:317 +msgid "Chibcha" +msgstr "" + +#. language code: che ce +#: zypp/LanguageCode.cc:319 +msgid "Chechen" +msgstr "" + +#. language code: chg +#: zypp/LanguageCode.cc:321 +msgid "Chagatai" +msgstr "" + +#. language code: chi zho zh +#: zypp/LanguageCode.cc:323 zypp/LanguageCode.cc:325 +msgid "Chinese" +msgstr "" + +#. language code: chk +#: zypp/LanguageCode.cc:327 +msgid "Chuukese" +msgstr "" + +#. language code: chm +#: zypp/LanguageCode.cc:329 +msgid "Mari" +msgstr "" + +#. language code: chn +#: zypp/LanguageCode.cc:331 +msgid "Chinook Jargon" +msgstr "" + +#. language code: cho +#: zypp/LanguageCode.cc:333 +msgid "Choctaw" +msgstr "" + +#. language code: chp +#: zypp/LanguageCode.cc:335 +msgid "Chipewyan" +msgstr "" + +#. language code: chr +#: zypp/LanguageCode.cc:337 +msgid "Cherokee" +msgstr "" + +#. language code: chu cu +#: zypp/LanguageCode.cc:339 +msgid "Church Slavic" +msgstr "" + +#. language code: chv cv +#: zypp/LanguageCode.cc:341 +msgid "Chuvash" +msgstr "" + +#. language code: chy +#: zypp/LanguageCode.cc:343 +msgid "Cheyenne" +msgstr "" + +#. language code: cmc +#: zypp/LanguageCode.cc:345 +msgid "Chamic Languages" +msgstr "" + +#. language code: cop +#: zypp/LanguageCode.cc:347 +msgid "Coptic" +msgstr "" + +#. language code: cor kw +#: zypp/LanguageCode.cc:349 +msgid "Cornish" +msgstr "" + +#. language code: cos co +#: zypp/LanguageCode.cc:351 +msgid "Corsican" +msgstr "" + +#. language code: cpe +#: zypp/LanguageCode.cc:353 +msgid "Creoles and Pidgins, English-Based (Other)" +msgstr "" + +#. language code: cpf +#: zypp/LanguageCode.cc:355 +msgid "Creoles and Pidgins, French-Based (Other)" +msgstr "" + +#. language code: cpp +#: zypp/LanguageCode.cc:357 +msgid "Creoles and Pidgins, Portuguese-Based (Other)" +msgstr "" + +#. language code: cre cr +#: zypp/LanguageCode.cc:359 +msgid "Cree" +msgstr "" + +#. language code: crh +#: zypp/LanguageCode.cc:361 +msgid "Crimean Tatar" +msgstr "" + +#. language code: crp +#: zypp/LanguageCode.cc:363 +msgid "Creoles and Pidgins (Other)" +msgstr "" + +#. language code: csb +#: zypp/LanguageCode.cc:365 +msgid "Kashubian" +msgstr "" + +#. language code: cus +#: zypp/LanguageCode.cc:367 +msgid "Cushitic (Other)" +msgstr "" + +#. language code: cze ces cs +#: zypp/LanguageCode.cc:369 zypp/LanguageCode.cc:371 +msgid "Czech" +msgstr "" + +#. language code: dak +#: zypp/LanguageCode.cc:373 +msgid "Dakota" +msgstr "" + +#. language code: dan da +#: zypp/LanguageCode.cc:375 +msgid "Danish" +msgstr "" + +#. language code: dar +#: zypp/LanguageCode.cc:377 +msgid "Dargwa" +msgstr "" + +#. language code: day +#: zypp/LanguageCode.cc:379 +msgid "Dayak" +msgstr "" + +#. language code: del +#: zypp/LanguageCode.cc:381 +msgid "Delaware" +msgstr "" + +#. language code: den +#: zypp/LanguageCode.cc:383 +msgid "Slave (Athapascan)" +msgstr "" + +#. language code: dgr +#: zypp/LanguageCode.cc:385 +msgid "Dogrib" +msgstr "" + +#. language code: din +#: zypp/LanguageCode.cc:387 +msgid "Dinka" +msgstr "" + +#. language code: div dv +#: zypp/LanguageCode.cc:389 +msgid "Divehi" +msgstr "" + +#. language code: doi +#: zypp/LanguageCode.cc:391 +msgid "Dogri" +msgstr "" + +#. language code: dra +#: zypp/LanguageCode.cc:393 +msgid "Dravidian (Other)" +msgstr "" + +#. language code: dsb +#: zypp/LanguageCode.cc:395 +msgid "Lower Sorbian" +msgstr "" + +#. language code: dua +#: zypp/LanguageCode.cc:397 +msgid "Duala" +msgstr "" + +#. language code: dum +#: zypp/LanguageCode.cc:399 +msgid "Dutch, Middle (ca.1050-1350)" +msgstr "" + +#. language code: dut nld nl +#: zypp/LanguageCode.cc:401 zypp/LanguageCode.cc:403 +msgid "Dutch" +msgstr "" + +#. language code: dyu +#: zypp/LanguageCode.cc:405 +msgid "Dyula" +msgstr "" + +#. language code: dzo dz +#: zypp/LanguageCode.cc:407 +msgid "Dzongkha" +msgstr "" + +#. language code: efi +#: zypp/LanguageCode.cc:409 +msgid "Efik" +msgstr "" + +#. language code: egy +#: zypp/LanguageCode.cc:411 +msgid "Egyptian (Ancient)" +msgstr "" + +#. language code: eka +#: zypp/LanguageCode.cc:413 +msgid "Ekajuk" +msgstr "" + +#. language code: elx +#: zypp/LanguageCode.cc:415 +msgid "Elamite" +msgstr "" + +#. language code: eng en +#: zypp/LanguageCode.cc:417 +msgid "English" +msgstr "" + +#. language code: enm +#: zypp/LanguageCode.cc:419 +msgid "English, Middle (1100-1500)" +msgstr "" + +#. language code: epo eo +#: zypp/LanguageCode.cc:421 +msgid "Esperanto" +msgstr "" + +#. language code: est et +#: zypp/LanguageCode.cc:423 +msgid "Estonian" +msgstr "" + +#. language code: ewe ee +#: zypp/LanguageCode.cc:425 +msgid "Ewe" +msgstr "" + +#. language code: ewo +#: zypp/LanguageCode.cc:427 +msgid "Ewondo" +msgstr "" + +#. language code: fan +#: zypp/LanguageCode.cc:429 +msgid "Fang" +msgstr "" + +#. language code: fao fo +#: zypp/LanguageCode.cc:431 +msgid "Faroese" +msgstr "" + +#. language code: fat +#: zypp/LanguageCode.cc:433 +msgid "Fanti" +msgstr "" + +#. language code: fij fj +#: zypp/LanguageCode.cc:435 +msgid "Fijian" +msgstr "" + +#. language code: fil +#: zypp/LanguageCode.cc:437 +msgid "Filipino" +msgstr "" + +#. language code: fin fi +#: zypp/LanguageCode.cc:439 +msgid "Finnish" +msgstr "" + +#. language code: fiu +#: zypp/LanguageCode.cc:441 +msgid "Finno-Ugrian (Other)" +msgstr "" + +#. language code: fon +#: zypp/LanguageCode.cc:443 +msgid "Fon" +msgstr "" + +#. language code: fre fra fr +#: zypp/LanguageCode.cc:445 zypp/LanguageCode.cc:447 +msgid "French" +msgstr "" + +#. language code: frm +#: zypp/LanguageCode.cc:449 +msgid "French, Middle (ca.1400-1600)" +msgstr "" + +#. language code: fro +#: zypp/LanguageCode.cc:451 +msgid "French, Old (842-ca.1400)" +msgstr "" + +#. language code: fry fy +#: zypp/LanguageCode.cc:453 +msgid "Frisian" +msgstr "" + +#. language code: ful ff +#: zypp/LanguageCode.cc:455 +msgid "Fulah" +msgstr "" + +#. language code: fur +#: zypp/LanguageCode.cc:457 +msgid "Friulian" +msgstr "" + +#. language code: gaa +#: zypp/LanguageCode.cc:459 +msgid "Ga" +msgstr "" + +#. language code: gay +#: zypp/LanguageCode.cc:461 +msgid "Gayo" +msgstr "" + +#. language code: gba +#: zypp/LanguageCode.cc:463 +msgid "Gbaya" +msgstr "" + +#. language code: gem +#: zypp/LanguageCode.cc:465 +msgid "Germanic (Other)" +msgstr "" + +#. language code: geo kat ka +#: zypp/LanguageCode.cc:467 zypp/LanguageCode.cc:469 +msgid "Georgian" +msgstr "" + +#. language code: ger deu de +#: zypp/LanguageCode.cc:471 zypp/LanguageCode.cc:473 +msgid "German" +msgstr "" + +#. language code: gez +#: zypp/LanguageCode.cc:475 +msgid "Geez" +msgstr "" + +#. language code: gil +#: zypp/LanguageCode.cc:477 +msgid "Gilbertese" +msgstr "" + +#. language code: gla gd +#: zypp/LanguageCode.cc:479 +msgid "Gaelic" +msgstr "" + +#. language code: gle ga +#: zypp/LanguageCode.cc:481 +msgid "Irish" +msgstr "" + +#. language code: glg gl +#: zypp/LanguageCode.cc:483 +msgid "Galician" +msgstr "" + +#. language code: glv gv +#: zypp/LanguageCode.cc:485 +msgid "Manx" +msgstr "" + +#. language code: gmh +#: zypp/LanguageCode.cc:487 +msgid "German, Middle High (ca.1050-1500)" +msgstr "" + +#. language code: goh +#: zypp/LanguageCode.cc:489 +msgid "German, Old High (ca.750-1050)" +msgstr "" + +#. language code: gon +#: zypp/LanguageCode.cc:491 +msgid "Gondi" +msgstr "" + +#. language code: gor +#: zypp/LanguageCode.cc:493 +msgid "Gorontalo" +msgstr "" + +#. language code: got +#: zypp/LanguageCode.cc:495 +msgid "Gothic" +msgstr "" + +#. language code: grb +#: zypp/LanguageCode.cc:497 +msgid "Grebo" +msgstr "" + +#. language code: grc +#: zypp/LanguageCode.cc:499 +msgid "Greek, Ancient (to 1453)" +msgstr "" + +#. language code: gre ell el +#: zypp/LanguageCode.cc:501 zypp/LanguageCode.cc:503 +msgid "Greek, Modern (1453-)" +msgstr "" + +#. language code: grn gn +#: zypp/LanguageCode.cc:505 +msgid "Guarani" +msgstr "" + +#. language code: guj gu +#: zypp/LanguageCode.cc:507 +msgid "Gujarati" +msgstr "" + +#. language code: gwi +#: zypp/LanguageCode.cc:509 +msgid "Gwich'in" +msgstr "" + +#. language code: hai +#: zypp/LanguageCode.cc:511 +msgid "Haida" +msgstr "" + +#. language code: hat ht +#: zypp/LanguageCode.cc:513 +msgid "Haitian" +msgstr "" + +#. language code: hau ha +#: zypp/LanguageCode.cc:515 +msgid "Hausa" +msgstr "" + +#. language code: haw +#: zypp/LanguageCode.cc:517 +msgid "Hawaiian" +msgstr "" + +#. language code: heb he +#: zypp/LanguageCode.cc:519 +msgid "Hebrew" +msgstr "" + +#. language code: her hz +#: zypp/LanguageCode.cc:521 +msgid "Herero" +msgstr "" + +#. language code: hil +#: zypp/LanguageCode.cc:523 +msgid "Hiligaynon" +msgstr "" + +#. language code: him +#: zypp/LanguageCode.cc:525 +msgid "Himachali" +msgstr "" + +#. language code: hin hi +#: zypp/LanguageCode.cc:527 +msgid "Hindi" +msgstr "" + +#. language code: hit +#: zypp/LanguageCode.cc:529 +msgid "Hittite" +msgstr "" + +#. language code: hmn +#: zypp/LanguageCode.cc:531 +msgid "Hmong" +msgstr "" + +#. language code: hmo ho +#: zypp/LanguageCode.cc:533 +msgid "Hiri Motu" +msgstr "" + +#. language code: hsb +#: zypp/LanguageCode.cc:535 +msgid "Upper Sorbian" +msgstr "" + +#. language code: hun hu +#: zypp/LanguageCode.cc:537 +msgid "Hungarian" +msgstr "" + +#. language code: hup +#: zypp/LanguageCode.cc:539 +msgid "Hupa" +msgstr "" + +#. language code: iba +#: zypp/LanguageCode.cc:541 +msgid "Iban" +msgstr "" + +#. language code: ibo ig +#: zypp/LanguageCode.cc:543 +msgid "Igbo" +msgstr "" + +#. language code: ice isl is +#: zypp/LanguageCode.cc:545 zypp/LanguageCode.cc:547 +msgid "Icelandic" +msgstr "" + +#. language code: ido io +#: zypp/LanguageCode.cc:549 +msgid "Ido" +msgstr "" + +#. language code: iii ii +#: zypp/LanguageCode.cc:551 +msgid "Sichuan Yi" +msgstr "" + +#. language code: ijo +#: zypp/LanguageCode.cc:553 +msgid "Ijo" +msgstr "" + +#. language code: iku iu +#: zypp/LanguageCode.cc:555 +msgid "Inuktitut" +msgstr "" + +#. language code: ile ie +#: zypp/LanguageCode.cc:557 +msgid "Interlingue" +msgstr "" + +#. language code: ilo +#: zypp/LanguageCode.cc:559 +msgid "Iloko" +msgstr "" + +#. language code: ina ia +#: zypp/LanguageCode.cc:561 +msgid "Interlingua (International Auxiliary Language Association)" +msgstr "" + +#. language code: inc +#: zypp/LanguageCode.cc:563 +msgid "Indic (Other)" +msgstr "" + +#. language code: ind id +#: zypp/LanguageCode.cc:565 +msgid "Indonesian" +msgstr "" + +#. language code: ine +#: zypp/LanguageCode.cc:567 +msgid "Indo-European (Other)" +msgstr "" + +#. language code: inh +#: zypp/LanguageCode.cc:569 +msgid "Ingush" +msgstr "" + +#. language code: ipk ik +#: zypp/LanguageCode.cc:571 +msgid "Inupiaq" +msgstr "" + +#. language code: ira +#: zypp/LanguageCode.cc:573 +msgid "Iranian (Other)" +msgstr "" + +#. language code: iro +#: zypp/LanguageCode.cc:575 +msgid "Iroquoian Languages" +msgstr "" + +#. language code: ita it +#: zypp/LanguageCode.cc:577 +msgid "Italian" +msgstr "" + +#. language code: jav jv +#: zypp/LanguageCode.cc:579 +msgid "Javanese" +msgstr "" + +#. language code: jbo +#: zypp/LanguageCode.cc:581 +msgid "Lojban" +msgstr "" + +#. language code: jpn ja +#: zypp/LanguageCode.cc:583 +msgid "Japanese" +msgstr "" + +#. language code: jpr +#: zypp/LanguageCode.cc:585 +msgid "Judeo-Persian" +msgstr "" + +#. language code: jrb +#: zypp/LanguageCode.cc:587 +msgid "Judeo-Arabic" +msgstr "" + +#. language code: kaa +#: zypp/LanguageCode.cc:589 +msgid "Kara-Kalpak" +msgstr "" + +#. language code: kab +#: zypp/LanguageCode.cc:591 +msgid "Kabyle" +msgstr "" + +#. language code: kac +#: zypp/LanguageCode.cc:593 +msgid "Kachin" +msgstr "" + +#. language code: kal kl +#: zypp/LanguageCode.cc:595 +msgid "Kalaallisut" +msgstr "" + +#. language code: kam +#: zypp/LanguageCode.cc:597 +msgid "Kamba" +msgstr "" + +#. language code: kan kn +#: zypp/LanguageCode.cc:599 +msgid "Kannada" +msgstr "" + +#. language code: kar +#: zypp/LanguageCode.cc:601 +msgid "Karen" +msgstr "" + +#. language code: kas ks +#: zypp/LanguageCode.cc:603 +msgid "Kashmiri" +msgstr "" + +#. language code: kau kr +#: zypp/LanguageCode.cc:605 +msgid "Kanuri" +msgstr "" + +#. language code: kaw +#: zypp/LanguageCode.cc:607 +msgid "Kawi" +msgstr "" + +#. language code: kaz kk +#: zypp/LanguageCode.cc:609 +msgid "Kazakh" +msgstr "" + +#. language code: kbd +#: zypp/LanguageCode.cc:611 +msgid "Kabardian" +msgstr "" + +#. language code: kha +#: zypp/LanguageCode.cc:613 +msgid "Khasi" +msgstr "" + +#. language code: khi +#: zypp/LanguageCode.cc:615 +msgid "Khoisan (Other)" +msgstr "" + +#. language code: khm km +#: zypp/LanguageCode.cc:617 +msgid "Khmer" +msgstr "" + +#. language code: kho +#: zypp/LanguageCode.cc:619 +msgid "Khotanese" +msgstr "" + +#. language code: kik ki +#: zypp/LanguageCode.cc:621 +msgid "Kikuyu" +msgstr "" + +#. language code: kin rw +#: zypp/LanguageCode.cc:623 +msgid "Kinyarwanda" +msgstr "" + +#. language code: kir ky +#: zypp/LanguageCode.cc:625 +msgid "Kirghiz" +msgstr "" + +#. language code: kmb +#: zypp/LanguageCode.cc:627 +msgid "Kimbundu" +msgstr "" + +#. language code: kok +#: zypp/LanguageCode.cc:629 +msgid "Konkani" +msgstr "" + +#. language code: kom kv +#: zypp/LanguageCode.cc:631 +msgid "Komi" +msgstr "" + +#. language code: kon kg +#: zypp/LanguageCode.cc:633 +msgid "Kongo" +msgstr "" + +#. language code: kor ko +#: zypp/LanguageCode.cc:635 +msgid "Korean" +msgstr "" + +#. language code: kos +#: zypp/LanguageCode.cc:637 +msgid "Kosraean" +msgstr "" + +#. language code: kpe +#: zypp/LanguageCode.cc:639 +msgid "Kpelle" +msgstr "" + +#. language code: krc +#: zypp/LanguageCode.cc:641 +msgid "Karachay-Balkar" +msgstr "" + +#. language code: kro +#: zypp/LanguageCode.cc:643 +msgid "Kru" +msgstr "" + +#. language code: kru +#: zypp/LanguageCode.cc:645 +msgid "Kurukh" +msgstr "" + +#. language code: kua kj +#: zypp/LanguageCode.cc:647 +msgid "Kuanyama" +msgstr "" + +#. language code: kum +#: zypp/LanguageCode.cc:649 +msgid "Kumyk" +msgstr "" + +#. language code: kur ku +#: zypp/LanguageCode.cc:651 +msgid "Kurdish" +msgstr "" + +#. language code: kut +#: zypp/LanguageCode.cc:653 +msgid "Kutenai" +msgstr "" + +#. language code: lad +#: zypp/LanguageCode.cc:655 +msgid "Ladino" +msgstr "" + +#. language code: lah +#: zypp/LanguageCode.cc:657 +msgid "Lahnda" +msgstr "" + +#. language code: lam +#: zypp/LanguageCode.cc:659 +msgid "Lamba" +msgstr "" + +#. language code: lao lo +#: zypp/LanguageCode.cc:661 +msgid "Lao" +msgstr "" + +#. language code: lat la +#: zypp/LanguageCode.cc:663 +msgid "Latin" +msgstr "" + +#. language code: lav lv +#: zypp/LanguageCode.cc:665 +msgid "Latvian" +msgstr "" + +#. language code: lez +#: zypp/LanguageCode.cc:667 +msgid "Lezghian" +msgstr "" + +#. language code: lim li +#: zypp/LanguageCode.cc:669 +msgid "Limburgan" +msgstr "" + +#. language code: lin ln +#: zypp/LanguageCode.cc:671 +msgid "Lingala" +msgstr "" + +#. language code: lit lt +#: zypp/LanguageCode.cc:673 +msgid "Lithuanian" +msgstr "" + +#. language code: lol +#: zypp/LanguageCode.cc:675 +msgid "Mongo" +msgstr "" + +#. language code: loz +#: zypp/LanguageCode.cc:677 +msgid "Lozi" +msgstr "" + +#. language code: ltz lb +#: zypp/LanguageCode.cc:679 +msgid "Luxembourgish" +msgstr "" + +#. language code: lua +#: zypp/LanguageCode.cc:681 +msgid "Luba-Lulua" +msgstr "" + +#. language code: lub lu +#: zypp/LanguageCode.cc:683 +msgid "Luba-Katanga" +msgstr "" + +#. language code: lug lg +#: zypp/LanguageCode.cc:685 +msgid "Ganda" +msgstr "" + +#. language code: lui +#: zypp/LanguageCode.cc:687 +msgid "Luiseno" +msgstr "" + +#. language code: lun +#: zypp/LanguageCode.cc:689 +msgid "Lunda" +msgstr "" + +#. language code: luo +#: zypp/LanguageCode.cc:691 +msgid "Luo (Kenya and Tanzania)" +msgstr "" + +#. language code: lus +#: zypp/LanguageCode.cc:693 +msgid "Lushai" +msgstr "" + +#. language code: mac mkd mk +#: zypp/LanguageCode.cc:695 zypp/LanguageCode.cc:697 +msgid "Macedonian" +msgstr "" + +#. language code: mad +#: zypp/LanguageCode.cc:699 +msgid "Madurese" +msgstr "" + +#. language code: mag +#: zypp/LanguageCode.cc:701 +msgid "Magahi" +msgstr "" + +#. language code: mah mh +#: zypp/LanguageCode.cc:703 +msgid "Marshallese" +msgstr "" + +#. language code: mai +#: zypp/LanguageCode.cc:705 +msgid "Maithili" +msgstr "" + +#. language code: mak +#: zypp/LanguageCode.cc:707 +msgid "Makasar" +msgstr "" + +#. language code: mal ml +#: zypp/LanguageCode.cc:709 +msgid "Malayalam" +msgstr "" + +#. language code: man +#: zypp/LanguageCode.cc:711 +msgid "Mandingo" +msgstr "" + +#. language code: mao mri mi +#: zypp/LanguageCode.cc:713 zypp/LanguageCode.cc:715 +msgid "Maori" +msgstr "" + +#. language code: map +#: zypp/LanguageCode.cc:717 +msgid "Austronesian (Other)" +msgstr "" + +#. language code: mar mr +#: zypp/LanguageCode.cc:719 +msgid "Marathi" +msgstr "" + +#. language code: mas +#: zypp/LanguageCode.cc:721 +msgid "Masai" +msgstr "" + +#. language code: may msa ms +#: zypp/LanguageCode.cc:723 zypp/LanguageCode.cc:725 +msgid "Malay" +msgstr "" + +#. language code: mdf +#: zypp/LanguageCode.cc:727 +msgid "Moksha" +msgstr "" + +#. language code: mdr +#: zypp/LanguageCode.cc:729 +msgid "Mandar" +msgstr "" + +#. language code: men +#: zypp/LanguageCode.cc:731 +msgid "Mende" +msgstr "" + +#. language code: mga +#: zypp/LanguageCode.cc:733 +msgid "Irish, Middle (900-1200)" +msgstr "" + +#. language code: mic +#: zypp/LanguageCode.cc:735 +msgid "Mi'kmaq" +msgstr "" + +#. language code: min +#: zypp/LanguageCode.cc:737 +msgid "Minangkabau" +msgstr "" + +#. language code: mis +#: zypp/LanguageCode.cc:739 +msgid "Miscellaneous Languages" +msgstr "" + +#. language code: mkh +#: zypp/LanguageCode.cc:741 +msgid "Mon-Khmer (Other)" +msgstr "" + +#. language code: mlg mg +#: zypp/LanguageCode.cc:743 +msgid "Malagasy" +msgstr "" + +#. language code: mlt mt +#: zypp/LanguageCode.cc:745 +msgid "Maltese" +msgstr "" + +#. language code: mnc +#: zypp/LanguageCode.cc:747 +msgid "Manchu" +msgstr "" + +#. language code: mni +#: zypp/LanguageCode.cc:749 +msgid "Manipuri" +msgstr "" + +#. language code: mno +#: zypp/LanguageCode.cc:751 +msgid "Manobo Languages" +msgstr "" + +#. language code: moh +#: zypp/LanguageCode.cc:753 +msgid "Mohawk" +msgstr "" + +#. language code: mol mo +#: zypp/LanguageCode.cc:755 +msgid "Moldavian" +msgstr "" + +#. language code: mon mn +#: zypp/LanguageCode.cc:757 +msgid "Mongolian" +msgstr "" + +#. language code: mos +#: zypp/LanguageCode.cc:759 +msgid "Mossi" +msgstr "" + +#. language code: mul +#: zypp/LanguageCode.cc:761 +msgid "Multiple Languages" +msgstr "" + +#. language code: mun +#: zypp/LanguageCode.cc:763 +msgid "Munda languages" +msgstr "" + +#. language code: mus +#: zypp/LanguageCode.cc:765 +msgid "Creek" +msgstr "" + +#. language code: mwl +#: zypp/LanguageCode.cc:767 +msgid "Mirandese" +msgstr "" + +#. language code: mwr +#: zypp/LanguageCode.cc:769 +msgid "Marwari" +msgstr "" + +#. language code: myn +#: zypp/LanguageCode.cc:771 +msgid "Mayan Languages" +msgstr "" + +#. language code: myv +#: zypp/LanguageCode.cc:773 +msgid "Erzya" +msgstr "" + +#. language code: nah +#: zypp/LanguageCode.cc:775 +msgid "Nahuatl" +msgstr "" + +#. language code: nai +#: zypp/LanguageCode.cc:777 +msgid "North American Indian" +msgstr "" + +#. language code: nap +#: zypp/LanguageCode.cc:779 +msgid "Neapolitan" +msgstr "" + +#. language code: nav nv +#: zypp/LanguageCode.cc:783 +msgid "Navajo" +msgstr "" + +#. language code: nbl nr +#: zypp/LanguageCode.cc:785 +msgid "Ndebele, South" +msgstr "" + +#. language code: nde nd +#: zypp/LanguageCode.cc:787 +msgid "Ndebele, North" +msgstr "" + +#. language code: ndo ng +#: zypp/LanguageCode.cc:789 +msgid "Ndonga" +msgstr "" + +#. language code: nds +#: zypp/LanguageCode.cc:791 +msgid "Low German" +msgstr "" + +#. language code: nep ne +#: zypp/LanguageCode.cc:793 +msgid "Nepali" +msgstr "" + +#. language code: new +#: zypp/LanguageCode.cc:795 +msgid "Nepal Bhasa" +msgstr "" + +#. language code: nia +#: zypp/LanguageCode.cc:797 +msgid "Nias" +msgstr "" + +#. language code: nic +#: zypp/LanguageCode.cc:799 +msgid "Niger-Kordofanian (Other)" +msgstr "" + +#. language code: niu +#: zypp/LanguageCode.cc:801 +msgid "Niuean" +msgstr "" + +#. language code: nno nn +#: zypp/LanguageCode.cc:803 +msgid "Norwegian Nynorsk" +msgstr "" + +#. language code: nob nb +#: zypp/LanguageCode.cc:805 +msgid "Norwegian Bokmal" +msgstr "" + +#. language code: nog +#: zypp/LanguageCode.cc:807 +msgid "Nogai" +msgstr "" + +#. language code: non +#: zypp/LanguageCode.cc:809 +msgid "Norse, Old" +msgstr "" + +#. language code: nor no +#: zypp/LanguageCode.cc:811 +msgid "Norwegian" +msgstr "" + +#. language code: nso +#: zypp/LanguageCode.cc:813 +msgid "Northern Sotho" +msgstr "" + +#. language code: nub +#: zypp/LanguageCode.cc:815 +msgid "Nubian Languages" +msgstr "" + +#. language code: nwc +#: zypp/LanguageCode.cc:817 +msgid "Classical Newari" +msgstr "" + +#. language code: nya ny +#: zypp/LanguageCode.cc:819 +msgid "Chichewa" +msgstr "" + +#. language code: nym +#: zypp/LanguageCode.cc:821 +msgid "Nyamwezi" +msgstr "" + +#. language code: nyn +#: zypp/LanguageCode.cc:823 +msgid "Nyankole" +msgstr "" + +#. language code: nyo +#: zypp/LanguageCode.cc:825 +msgid "Nyoro" +msgstr "" + +#. language code: nzi +#: zypp/LanguageCode.cc:827 +msgid "Nzima" +msgstr "" + +#. language code: oci oc +#: zypp/LanguageCode.cc:829 +msgid "Occitan (post 1500)" +msgstr "" + +#. language code: oji oj +#: zypp/LanguageCode.cc:831 +msgid "Ojibwa" +msgstr "" + +#. language code: ori or +#: zypp/LanguageCode.cc:833 +msgid "Oriya" +msgstr "" + +#. language code: orm om +#: zypp/LanguageCode.cc:835 +msgid "Oromo" +msgstr "" + +#. language code: osa +#: zypp/LanguageCode.cc:837 +msgid "Osage" +msgstr "" + +#. language code: oss os +#: zypp/LanguageCode.cc:839 +msgid "Ossetian" +msgstr "" + +#. language code: ota +#: zypp/LanguageCode.cc:841 +msgid "Turkish, Ottoman (1500-1928)" +msgstr "" + +#. language code: oto +#: zypp/LanguageCode.cc:843 +msgid "Otomian Languages" +msgstr "" + +#. language code: paa +#: zypp/LanguageCode.cc:845 +msgid "Papuan (Other)" +msgstr "" + +#. language code: pag +#: zypp/LanguageCode.cc:847 +msgid "Pangasinan" +msgstr "" + +#. language code: pal +#: zypp/LanguageCode.cc:849 +msgid "Pahlavi" +msgstr "" + +#. language code: pam +#: zypp/LanguageCode.cc:851 +msgid "Pampanga" +msgstr "" + +#. language code: pan pa +#: zypp/LanguageCode.cc:853 +msgid "Panjabi" +msgstr "" + +#. language code: pap +#: zypp/LanguageCode.cc:855 +msgid "Papiamento" +msgstr "" + +#. language code: pau +#: zypp/LanguageCode.cc:857 +msgid "Palauan" +msgstr "" + +#. language code: peo +#: zypp/LanguageCode.cc:859 +msgid "Persian, Old (ca.600-400 B.C.)" +msgstr "" + +#. language code: per fas fa +#: zypp/LanguageCode.cc:861 zypp/LanguageCode.cc:863 +msgid "Persian" +msgstr "" + +#. language code: phi +#: zypp/LanguageCode.cc:865 +msgid "Philippine (Other)" +msgstr "" + +#. language code: phn +#: zypp/LanguageCode.cc:867 +msgid "Phoenician" +msgstr "" + +#. language code: pli pi +#: zypp/LanguageCode.cc:869 +msgid "Pali" +msgstr "" + +#. language code: pol pl +#: zypp/LanguageCode.cc:871 +msgid "Polish" +msgstr "" + +#. language code: pon +#: zypp/LanguageCode.cc:873 +msgid "Pohnpeian" +msgstr "" + +#. language code: por pt +#: zypp/LanguageCode.cc:875 +msgid "Portuguese" +msgstr "" + +#. language code: pra +#: zypp/LanguageCode.cc:877 +msgid "Prakrit Languages" +msgstr "" + +#. language code: pro +#: zypp/LanguageCode.cc:879 +msgid "Provencal, Old (to 1500)" +msgstr "" + +#. language code: pus ps +#: zypp/LanguageCode.cc:881 +msgid "Pushto" +msgstr "" + +#. language code: que qu +#: zypp/LanguageCode.cc:883 +msgid "Quechua" +msgstr "" + +#. language code: raj +#: zypp/LanguageCode.cc:885 +msgid "Rajasthani" +msgstr "" + +#. language code: rap +#: zypp/LanguageCode.cc:887 +msgid "Rapanui" +msgstr "" + +#. language code: rar +#: zypp/LanguageCode.cc:889 +msgid "Rarotongan" +msgstr "" + +#. language code: roa +#: zypp/LanguageCode.cc:891 +msgid "Romance (Other)" +msgstr "" + +#. language code: roh rm +#: zypp/LanguageCode.cc:893 +msgid "Raeto-Romance" +msgstr "" + +#. language code: rom +#: zypp/LanguageCode.cc:895 +msgid "Romany" +msgstr "" + +#. language code: rum ron ro +#: zypp/LanguageCode.cc:897 zypp/LanguageCode.cc:899 +msgid "Romanian" +msgstr "" + +#. language code: run rn +#: zypp/LanguageCode.cc:901 +msgid "Rundi" +msgstr "" + +#. language code: rus ru +#: zypp/LanguageCode.cc:903 +msgid "Russian" +msgstr "" + +#. language code: sad +#: zypp/LanguageCode.cc:905 +msgid "Sandawe" +msgstr "" + +#. language code: sag sg +#: zypp/LanguageCode.cc:907 +msgid "Sango" +msgstr "" + +#. language code: sah +#: zypp/LanguageCode.cc:909 +msgid "Yakut" +msgstr "" + +#. language code: sai +#: zypp/LanguageCode.cc:911 +msgid "South American Indian (Other)" +msgstr "" + +#. language code: sal +#: zypp/LanguageCode.cc:913 +msgid "Salishan Languages" +msgstr "" + +#. language code: sam +#: zypp/LanguageCode.cc:915 +msgid "Samaritan Aramaic" +msgstr "" + +#. language code: san sa +#: zypp/LanguageCode.cc:917 +msgid "Sanskrit" +msgstr "" + +#. language code: sas +#: zypp/LanguageCode.cc:919 +msgid "Sasak" +msgstr "" + +#. language code: sat +#: zypp/LanguageCode.cc:921 +msgid "Santali" +msgstr "" + +#. language code: scc srp sr +#: zypp/LanguageCode.cc:923 zypp/LanguageCode.cc:925 +msgid "Serbian" +msgstr "" + +#. language code: scn +#: zypp/LanguageCode.cc:927 +msgid "Sicilian" +msgstr "" + +#. language code: sco +#: zypp/LanguageCode.cc:929 +msgid "Scots" +msgstr "" + +#. language code: scr hrv hr +#: zypp/LanguageCode.cc:931 zypp/LanguageCode.cc:933 +msgid "Croatian" +msgstr "" + +#. language code: sel +#: zypp/LanguageCode.cc:935 +msgid "Selkup" +msgstr "" + +#. language code: sem +#: zypp/LanguageCode.cc:937 +msgid "Semitic (Other)" +msgstr "" + +#. language code: sga +#: zypp/LanguageCode.cc:939 +msgid "Irish, Old (to 900)" +msgstr "" + +#. language code: sgn +#: zypp/LanguageCode.cc:941 +msgid "Sign Languages" +msgstr "" + +#. language code: shn +#: zypp/LanguageCode.cc:943 +msgid "Shan" +msgstr "" + +#. language code: sid +#: zypp/LanguageCode.cc:945 +msgid "Sidamo" +msgstr "" + +#. language code: sin si +#: zypp/LanguageCode.cc:947 +msgid "Sinhala" +msgstr "" + +#. language code: sio +#: zypp/LanguageCode.cc:949 +msgid "Siouan Languages" +msgstr "" + +#. language code: sit +#: zypp/LanguageCode.cc:951 +msgid "Sino-Tibetan (Other)" +msgstr "" + +#. language code: sla +#: zypp/LanguageCode.cc:953 +msgid "Slavic (Other)" +msgstr "" + +#. language code: slo slk sk +#: zypp/LanguageCode.cc:955 zypp/LanguageCode.cc:957 +msgid "Slovak" +msgstr "" + +#. language code: slv sl +#: zypp/LanguageCode.cc:959 +msgid "Slovenian" +msgstr "" + +#. language code: sma +#: zypp/LanguageCode.cc:961 +msgid "Southern Sami" +msgstr "" + +#. language code: sme se +#: zypp/LanguageCode.cc:963 +msgid "Northern Sami" +msgstr "" + +#. language code: smi +#: zypp/LanguageCode.cc:965 +msgid "Sami Languages (Other)" +msgstr "" + +#. language code: smj +#: zypp/LanguageCode.cc:967 +msgid "Lule Sami" +msgstr "" + +#. language code: smn +#: zypp/LanguageCode.cc:969 +msgid "Inari Sami" +msgstr "" + +#. language code: smo sm +#: zypp/LanguageCode.cc:971 +msgid "Samoan" +msgstr "" + +#. language code: sms +#: zypp/LanguageCode.cc:973 +msgid "Skolt Sami" +msgstr "" + +#. language code: sna sn +#: zypp/LanguageCode.cc:975 +msgid "Shona" +msgstr "" + +#. language code: snd sd +#: zypp/LanguageCode.cc:977 +msgid "Sindhi" +msgstr "" + +#. language code: snk +#: zypp/LanguageCode.cc:979 +msgid "Soninke" +msgstr "" + +#. language code: sog +#: zypp/LanguageCode.cc:981 +msgid "Sogdian" +msgstr "" + +#. language code: som so +#: zypp/LanguageCode.cc:983 +msgid "Somali" +msgstr "" + +#. language code: son +#: zypp/LanguageCode.cc:985 +msgid "Songhai" +msgstr "" + +#. language code: sot st +#: zypp/LanguageCode.cc:987 +msgid "Sotho, Southern" +msgstr "" + +#. language code: spa es +#: zypp/LanguageCode.cc:989 +msgid "Spanish" +msgstr "" + +#. language code: srd sc +#: zypp/LanguageCode.cc:991 +msgid "Sardinian" +msgstr "" + +#. language code: srr +#: zypp/LanguageCode.cc:993 +msgid "Serer" +msgstr "" + +#. language code: ssa +#: zypp/LanguageCode.cc:995 +msgid "Nilo-Saharan (Other)" +msgstr "" + +#. language code: ssw ss +#: zypp/LanguageCode.cc:997 +msgid "Swati" +msgstr "" + +#. language code: suk +#: zypp/LanguageCode.cc:999 +msgid "Sukuma" +msgstr "" + +#. language code: sun su +#: zypp/LanguageCode.cc:1001 +msgid "Sundanese" +msgstr "" + +#. language code: sus +#: zypp/LanguageCode.cc:1003 +msgid "Susu" +msgstr "" + +#. language code: sux +#: zypp/LanguageCode.cc:1005 +msgid "Sumerian" +msgstr "" + +#. language code: swa sw +#: zypp/LanguageCode.cc:1007 +msgid "Swahili" +msgstr "" + +#. language code: swe sv +#: zypp/LanguageCode.cc:1009 +msgid "Swedish" +msgstr "" + +#. language code: syr +#: zypp/LanguageCode.cc:1011 +msgid "Syriac" +msgstr "" + +#. language code: tah ty +#: zypp/LanguageCode.cc:1013 +msgid "Tahitian" +msgstr "" + +#. language code: tai +#: zypp/LanguageCode.cc:1015 +msgid "Tai (Other)" +msgstr "" + +#. language code: tam ta +#: zypp/LanguageCode.cc:1017 +msgid "Tamil" +msgstr "" + +#. language code: tat tt +#: zypp/LanguageCode.cc:1019 +msgid "Tatar" +msgstr "" + +#. language code: tel te +#: zypp/LanguageCode.cc:1021 +msgid "Telugu" +msgstr "" + +#. language code: tem +#: zypp/LanguageCode.cc:1023 +msgid "Timne" +msgstr "" + +#. language code: ter +#: zypp/LanguageCode.cc:1025 +msgid "Tereno" +msgstr "" + +#. language code: tet +#: zypp/LanguageCode.cc:1027 +msgid "Tetum" +msgstr "" + +#. language code: tgk tg +#: zypp/LanguageCode.cc:1029 +msgid "Tajik" +msgstr "" + +#. language code: tgl tl +#: zypp/LanguageCode.cc:1031 +msgid "Tagalog" +msgstr "" + +#. language code: tha th +#: zypp/LanguageCode.cc:1033 +msgid "Thai" +msgstr "" + +#. language code: tib bod bo +#: zypp/LanguageCode.cc:1035 zypp/LanguageCode.cc:1037 +msgid "Tibetan" +msgstr "" + +#. language code: tig +#: zypp/LanguageCode.cc:1039 +msgid "Tigre" +msgstr "" + +#. language code: tir ti +#: zypp/LanguageCode.cc:1041 +msgid "Tigrinya" +msgstr "" + +#. language code: tiv +#: zypp/LanguageCode.cc:1043 +msgid "Tiv" +msgstr "" + +#. language code: tlh +#: zypp/LanguageCode.cc:1047 +msgid "Klingon" +msgstr "" + +#. language code: tli +#: zypp/LanguageCode.cc:1049 +msgid "Tlingit" +msgstr "" + +#. language code: tmh +#: zypp/LanguageCode.cc:1051 +msgid "Tamashek" +msgstr "" + +#. language code: tog +#: zypp/LanguageCode.cc:1053 +msgid "Tonga (Nyasa)" +msgstr "" + +#. language code: ton to +#: zypp/LanguageCode.cc:1055 +msgid "Tonga (Tonga Islands)" +msgstr "" + +#. language code: tpi +#: zypp/LanguageCode.cc:1057 +msgid "Tok Pisin" +msgstr "" + +#. language code: tsi +#: zypp/LanguageCode.cc:1059 +msgid "Tsimshian" +msgstr "" + +#. language code: tsn tn +#: zypp/LanguageCode.cc:1061 +msgid "Tswana" +msgstr "" + +#. language code: tso ts +#: zypp/LanguageCode.cc:1063 +msgid "Tsonga" +msgstr "" + +#. language code: tuk tk +#: zypp/LanguageCode.cc:1065 +msgid "Turkmen" +msgstr "" + +#. language code: tum +#: zypp/LanguageCode.cc:1067 +msgid "Tumbuka" +msgstr "" + +#. language code: tup +#: zypp/LanguageCode.cc:1069 +msgid "Tupi Languages" +msgstr "" + +#. language code: tur tr +#: zypp/LanguageCode.cc:1071 +msgid "Turkish" +msgstr "" + +#. language code: tut +#: zypp/LanguageCode.cc:1073 +msgid "Altaic (Other)" +msgstr "" + +#. language code: twi tw +#: zypp/LanguageCode.cc:1077 +msgid "Twi" +msgstr "" + +#. language code: tyv +#: zypp/LanguageCode.cc:1079 +msgid "Tuvinian" +msgstr "" + +#. language code: udm +#: zypp/LanguageCode.cc:1081 +msgid "Udmurt" +msgstr "" + +#. language code: uga +#: zypp/LanguageCode.cc:1083 +msgid "Ugaritic" +msgstr "" + +#. language code: uig ug +#: zypp/LanguageCode.cc:1085 +msgid "Uighur" +msgstr "" + +#. language code: ukr uk +#: zypp/LanguageCode.cc:1087 +msgid "Ukrainian" +msgstr "" + +#. language code: umb +#: zypp/LanguageCode.cc:1089 +msgid "Umbundu" +msgstr "" + +#. language code: und +#: zypp/LanguageCode.cc:1091 +msgid "Undetermined" +msgstr "" + +#. language code: urd ur +#: zypp/LanguageCode.cc:1093 +msgid "Urdu" +msgstr "" + +#. language code: uzb uz +#: zypp/LanguageCode.cc:1095 +msgid "Uzbek" +msgstr "" + +#. language code: vai +#: zypp/LanguageCode.cc:1097 +msgid "Vai" +msgstr "" + +#. language code: ven ve +#: zypp/LanguageCode.cc:1099 +msgid "Venda" +msgstr "" + +#. language code: vie vi +#: zypp/LanguageCode.cc:1101 +msgid "Vietnamese" +msgstr "" + +#. language code: vol vo +#: zypp/LanguageCode.cc:1103 +msgid "Volapuk" +msgstr "" + +#. language code: vot +#: zypp/LanguageCode.cc:1105 +msgid "Votic" +msgstr "" + +#. language code: wak +#: zypp/LanguageCode.cc:1107 +msgid "Wakashan Languages" +msgstr "" + +#. language code: wal +#: zypp/LanguageCode.cc:1109 +msgid "Walamo" +msgstr "" + +#. language code: war +#: zypp/LanguageCode.cc:1111 +msgid "Waray" +msgstr "" + +#. language code: was +#: zypp/LanguageCode.cc:1113 +msgid "Washo" +msgstr "" + +#. language code: wel cym cy +#: zypp/LanguageCode.cc:1115 zypp/LanguageCode.cc:1117 +msgid "Welsh" +msgstr "" + +#. language code: wen +#: zypp/LanguageCode.cc:1119 +msgid "Sorbian Languages" +msgstr "" + +#. language code: wln wa +#: zypp/LanguageCode.cc:1121 +msgid "Walloon" +msgstr "" + +#. language code: wol wo +#: zypp/LanguageCode.cc:1123 +msgid "Wolof" +msgstr "" + +#. language code: xal +#: zypp/LanguageCode.cc:1125 +msgid "Kalmyk" +msgstr "" + +#. language code: xho xh +#: zypp/LanguageCode.cc:1127 +msgid "Xhosa" +msgstr "" + +#. language code: yao +#: zypp/LanguageCode.cc:1129 +msgid "Yao" +msgstr "" + +#. language code: yap +#: zypp/LanguageCode.cc:1131 +msgid "Yapese" +msgstr "" + +#. language code: yid yi +#: zypp/LanguageCode.cc:1133 +msgid "Yiddish" +msgstr "" + +#. language code: yor yo +#: zypp/LanguageCode.cc:1135 +msgid "Yoruba" +msgstr "" + +#. language code: ypk +#: zypp/LanguageCode.cc:1137 +msgid "Yupik Languages" +msgstr "" + +#. language code: zap +#: zypp/LanguageCode.cc:1139 +msgid "Zapotec" +msgstr "" + +#. language code: zen +#: zypp/LanguageCode.cc:1141 +msgid "Zenaga" +msgstr "" + +#. language code: zha za +#: zypp/LanguageCode.cc:1143 +msgid "Zhuang" +msgstr "" + +#. language code: znd +#: zypp/LanguageCode.cc:1145 +msgid "Zande" +msgstr "" + +#. language code: zul zu +#: zypp/LanguageCode.cc:1147 +msgid "Zulu" +msgstr "" + +#. language code: zun +#: zypp/LanguageCode.cc:1149 +msgid "Zuni" +msgstr "" + +#: zypp/ProblemSolution.cc:134 +msgid "Following actions will be done:" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:65 +msgid "does not expire" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" +#: zypp/PublicKey.cc:70 +#, boost-format +msgid "expired: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" +#: zypp/PublicKey.cc:75 +#, boost-format +msgid "expires: %1%" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:84 +msgid "(does not expire)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:93 +msgid "(EXPIRED)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:97 +msgid "(expires within 24h)" +msgstr "" + +#. translators: an annotation to a gpg keys expiry date +#: zypp/PublicKey.cc:101 +#, c-format, boost-format +msgid "(expires in %d day)" +msgid_plural "(expires in %d days)" +msgstr[0] "" +msgstr[1] "" + +#: zypp/VendorSupportOptions.cc:14 +msgid "unknown" +msgstr "" + +#: zypp/VendorSupportOptions.cc:17 +msgid "unsupported" +msgstr "" + +#: zypp/VendorSupportOptions.cc:20 +msgid "Level 1" +msgstr "" + +#: zypp/VendorSupportOptions.cc:23 +msgid "Level 2" +msgstr "" + +#: zypp/VendorSupportOptions.cc:26 +msgid "Level 3" +msgstr "" + +#: zypp/VendorSupportOptions.cc:29 +msgid "Additional Customer Contract Necessary" +msgstr "" + +#: zypp/VendorSupportOptions.cc:31 +msgid "Discontinued and superseded by a different package" +msgstr "" + +#: zypp/VendorSupportOptions.cc:33 +msgid "invalid" +msgstr "" + +#: zypp/VendorSupportOptions.cc:41 +msgid "The level of support is unspecified" +msgstr "" + +#: zypp/VendorSupportOptions.cc:44 +msgid "The vendor does not provide support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:47 +msgid "Problem determination, which means technical support designed to provide compatibility information, installation assistance, usage support, on-going maintenance and basic troubleshooting. Level 1 Support is not intended to correct product defect errors." +msgstr "" + +#: zypp/VendorSupportOptions.cc:50 +msgid "Problem isolation, which means technical support designed to duplicate customer problems, isolate problem area and provide resolution for problems not resolved by Level 1 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:53 +msgid "Problem resolution, which means technical support designed to resolve complex problems by engaging engineering in resolution of product defects which have been identified by Level 2 Support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:56 +msgid "An additional customer contract is necessary for getting support." +msgstr "" + +#: zypp/VendorSupportOptions.cc:58 +msgid "The package was discontinued and has been superseded by a new package with a different name." +msgstr "" + +#: zypp/VendorSupportOptions.cc:60 +msgid "Unknown support option. Description not available" +msgstr "" + +#: zypp/ZYppFactory.cc:379 +#, c-format, boost-format +msgid "" +"System management is locked by the application with pid %d (%s).\n" +"Close this application before trying again." +msgstr "" + +#: zypp/base/StrMatcher.cc:152 +#, c-format, boost-format +msgid "Unknown match mode '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:153 +#, c-format, boost-format +msgid "Unknown match mode '%s' for pattern '%s'" +msgstr "" + +#: zypp/base/StrMatcher.cc:157 +#, c-format, boost-format +msgid "Invalid regular expression '%s': regcomp returned %d" +msgstr "" + +#: zypp/base/StrMatcher.cc:158 +#, c-format, boost-format +msgid "Invalid regular expression '%s'" +msgstr "" + +#. !\todo add comma to the message for the next release +#: zypp/media/MediaCIFS.cc:427 zypp/media/MediaCurl.cc:1514 +#: zypp/media/MediaNetwork.cc:314 +#, c-format, boost-format +msgid "Authentication required for '%s'" +msgstr "" + +#. just report (NO_ERROR); no interactive request to the user +#: zypp/media/MediaCurl.cc:789 +msgid "Will try again..." +msgstr "" + +#: zypp/media/MediaCurl.cc:792 +#, boost-format +msgid "Giving up after %1% attempts." +msgstr "" + +#: zypp/media/MediaCurl.cc:907 zypp-curl/ng/network/networkrequesterror.cc:127 +msgid "Visit the SUSE Customer Center to check whether your registration is valid and has not expired." +msgstr "" + +#: zypp/media/MediaCurl.cc:909 zypp-curl/ng/network/networkrequesterror.cc:129 +msgid "Visit the Novell Customer Center to check whether your registration is valid and has not expired." +msgstr "" + +#: zypp/media/MediaHandler.cc:339 +msgid "Create attach point: Can't find a writable directory to create an attach point" +msgstr "" + +#: zypp/misc/CheckAccessDeleted.cc:472 +msgid "Please install package 'lsof' first." +msgstr "" + +#: zypp/ng/repo/refresh.cc:42 +msgid "Can't create metadata cache directory." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:81 +#: zypp/ng/repo/workflows/serviceswf.cc:283 +#, c-format, boost-format +msgid "Error trying to read from '%s'" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:432 +#: zypp/ng/repo/workflows/repomanagerwf.cc:655 +#: zypp/ng/repo/workflows/repomanagerwf.cc:724 +#, c-format, boost-format +msgid "Can't create %s" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:487 +msgid "Valid metadata not found at specified URL" +msgid_plural "Valid metadata not found at specified URLs" +msgstr[0] "" +msgstr[1] "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:568 +msgid "Failed to cache repo ( unable to start repo2solv )." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:586 +#: zypp/ng/repo/workflows/repomanagerwf.cc:615 +#, c-format, boost-format +msgid "Failed to cache repo (%d)." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:643 +#, c-format, boost-format +msgid "Building repository '%s' cache" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:730 +#, c-format, boost-format +msgid "Can't create cache at %s - no writing permissions." +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:785 +#, boost-format +msgid "Failed to cache repo %1%" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:802 +msgid "Unhandled repository type" +msgstr "" + +#: zypp/ng/repo/workflows/repomanagerwf.cc:878 +#, c-format, boost-format +msgid "Adding repository '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/repomanagerwf.cc:973 +#, c-format, boost-format +msgid "Invalid repo file name at '%s'" +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repo/workflows/repomanagerwf.cc:989 zypp/ng/repomanager.cc:589 +#: zypp/ng/repomanager.cc:667 zypp/ng/repomanager.cc:739 +#: zypp/ng/repomanager.cc:1097 zypp/ng/repomanager.cc:1223 +#, c-format, boost-format +msgid "Can't open file '%s' for writing." +msgstr "" + +#. TranslatorExplanation '%s' is an URL +#: zypp/ng/repo/workflows/serviceswf.cc:290 +#: zypp/ng/repo/workflows/serviceswf.cc:296 +#, c-format, boost-format +msgid "Unknown error reading from '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:196 +#, boost-format +msgid "Cannot read repo directory '%1%': Permission denied" +msgstr "" + +#. TranslatorExplanation '%s' is a pathname +#: zypp/ng/repomanager.cc:204 zypp/ng/repomanager.cc:468 +#: zypp/ng/repomanager.cc:1329 zypp/repo/PluginServices.cc:49 +#, c-format, boost-format +msgid "Failed to read directory '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:214 +#, boost-format +msgid "Cannot read repo file '%1%': Permission denied" +msgstr "" + +#: zypp/ng/repomanager.cc:383 +msgid "Cleaning metadata" +msgstr "" + +#: zypp/ng/repomanager.cc:401 +msgid "Cleaning packages" +msgstr "" + +#: zypp/ng/repomanager.cc:453 +msgid "Cleaning up cache dirs" +msgstr "" + +#: zypp/ng/repomanager.cc:473 +#, boost-format +msgid "Cleaning up directory: %1%" +msgstr "" + +#: zypp/ng/repomanager.cc:503 +msgid "Cleaning cache" +msgstr "" + +#: zypp/ng/repomanager.cc:524 +msgid "Loading from cache" +msgstr "" + +#: zypp/ng/repomanager.cc:615 +#, c-format, boost-format +msgid "Removing repository '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:635 zypp/ng/repomanager.cc:719 +msgid "Can't figure out where the repo is stored." +msgstr "" + +#. TranslatorExplanation '%s' is a filename +#: zypp/ng/repomanager.cc:649 zypp/ng/repomanager.cc:1085 +#, c-format, boost-format +msgid "Can't delete '%s'" +msgstr "" + +#: zypp/ng/repomanager.cc:705 +msgid "Modifying repository" +msgstr "" + +#: zypp/ng/repomanager.cc:892 +msgid "Refreshing Repository: " +msgstr "" + +#: zypp/ng/repomanager.cc:1073 zypp/ng/repomanager.cc:1145 +msgid "Can't figure out where the service is stored." +msgstr "" + +#. translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. +#. %1% = service name +#. %2% = repository name +#: zypp/ng/repomanager.cc:1433 +#, boost-format +msgid "Unknown service '%1%': Removing orphaned service repository '%2%'" +msgstr "" + +#: zypp/ng/repomanager.h:65 +msgid "Repository alias cannot start with dot." +msgstr "" + +#: zypp/ng/repomanager.h:77 +msgid "Service alias cannot start with dot." +msgstr "" + +#: zypp/ng/reporthelper.cc:26 +#, c-format, boost-format +msgid "No digest for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:39 +#, c-format, boost-format +msgid "Unknown digest %s for file %s." +msgstr "" + +#: zypp/ng/reporthelper.cc:52 +#, c-format, boost-format +msgid "Digest verification failed for file '%s'" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:69 +#, c-format, boost-format +msgid "File '%s' is unsigned, continue?" +msgstr "" + +#. TranslatorExplanation: speaking of a file +#: zypp/ng/reporthelper.cc:73 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is unsigned, continue?" +msgstr "" + +#: zypp/ng/reporthelper.cc:90 +msgid "Do you want to reject the key, trust temporarily, or trust always?" +msgstr "" + +#: zypp/ng/reporthelper.cc:116 +#, boost-format +msgid "Key Name: %1%" +msgstr "" + +#: zypp/ng/reporthelper.cc:128 +#, boost-format +msgid "Received %1% new package signing key from repository \"%2%\":" +msgid_plural "Received %1% new package signing keys from repository \"%2%\":" +msgstr[0] "" +msgstr[1] "" + +#. translator: %1% is a file name +#: zypp/ng/reporthelper.cc:144 +#, boost-format +msgid "Signature verification failed for file '%1%'." +msgstr "" + +#. translator: %1% is a file name, %2% a repositories na me +#: zypp/ng/reporthelper.cc:147 +#, boost-format +msgid "Signature verification failed for file '%1%' from repository '%2%'." +msgstr "" + +#. @TODO use a centralized Continue string! +#: zypp/ng/reporthelper.cc:150 zypp-tui/output/Out.cc:32 +msgid "Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:168 +#, c-format, boost-format +msgid "File '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translators: the last %s is gpg key ID +#: zypp/ng/reporthelper.cc:172 +#, c-format, boost-format +msgid "File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?" +msgstr "" + +#. translator: %1% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:78 +#, boost-format +msgid "Repository %1% does not define additional 'gpgkey=' URLs." +msgstr "" + +#. no key in the cache is what we are looking for, lets download +#. all keys specified in gpgkey= entries +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a repositories name +#: zypp/ng/workflows/repoinfowf.cc:87 +#, boost-format +msgid "Looking for gpg key ID %1% in repository %2%." +msgstr "" + +#. translator: %1% is a gpg key ID like 3DBDC284 +#. %2% is a cache directories path +#: zypp/ng/workflows/repoinfowf.cc:134 +#, boost-format +msgid "Looking for gpg key ID %1% in cache %2%." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:198 +#, c-format, boost-format +msgid "Required attribute '%s' is missing." +msgstr "" + +#: zypp/parser/RepoindexFileReader.cc:210 +#, c-format, boost-format +msgid "One or both of '%s' or '%s' attributes is required." +msgstr "" + +#: zypp/repo/PackageProvider.cc:343 +msgid "Signature verification failed" +msgstr "" + +#. TranslatorExplanation %s = package being checked for integrity +#: zypp/repo/PackageProvider.cc:474 +#, c-format, boost-format +msgid "Package %s seems to be corrupted during transfer. Do you want to retry retrieval?" +msgstr "" + +#. TranslatorExplanation %s = name of the package being processed. +#: zypp/repo/PackageProvider.cc:498 +#, c-format, boost-format +msgid "Failed to provide Package %s. Do you want to retry retrieval?" +msgstr "" + +#: zypp/repo/PackageProvider.cc:621 +msgid "applydeltarpm check failed." +msgstr "" + +#: zypp/repo/PackageProvider.cc:632 +msgid "applydeltarpm failed." +msgstr "" + +#: zypp/repo/RepoException.cc:129 +msgid "Service plugin does not support changing an attribute." +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:260 +#, c-format, boost-format +msgid "Can't provide file '%s' from repository '%s'" +msgstr "" + +#: zypp/repo/RepoProvideFile.cc:266 +msgid "No url in repository." +msgstr "" + +#. Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. +#: zypp/repo/SUSEMediaVerifier.cc:104 zypp-media/ng/mediaverifier.cc:109 +#, boost-format +msgid "Expected medium %1%/%2% identified by file '%3%' with content:" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:34 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:40 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:47 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from package\n" +" %3%" +msgstr "" + +#. TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) +#: zypp/sat/FileConflicts.cc:53 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file from install of\n" +" %3%" +msgstr "" + +#. [lhs][rhs] 0 = installed; 1 = to be installed +#. TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) +#: zypp/sat/FileConflicts.cc:68 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:76 +#, boost-format +msgid "" +"File %1%\n" +" from package\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:85 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from package\n" +" %4%" +msgstr "" + +#. TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) +#: zypp/sat/FileConflicts.cc:93 +#, boost-format +msgid "" +"File %1%\n" +" from install of\n" +" %2%\n" +" conflicts with file\n" +" %3%\n" +" from install of\n" +" %4%" +msgstr "" + +#: zypp/sat/detail/PoolImpl.cc:201 +msgid "Can not create sat-pool." +msgstr "" + +#. TranslatorExplanation %s = name of package, patch, selection ... +#: zypp/solver/detail/ProblemSolutionIgnore.cc:42 +#, c-format, boost-format +msgid "break %s by ignoring some of its dependencies" +msgstr "" + +#: zypp/solver/detail/ProblemSolutionIgnore.cc:48 +msgid "generally ignore of some dependencies" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1160 +#, boost-format +msgid "the installed %1% does not belong to a distupgrade repository and must be replaced" +msgstr "" + +#. just in case +#: zypp/solver/detail/SATResolver.cc:1162 +#, boost-format +msgid "the to be installed %1% does not belong to a distupgrade repository" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1166 +#, boost-format +msgid "the installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1168 +#, boost-format +msgid "the to be installed %1% has inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1171 +#, boost-format +msgid "problem with the installed %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1174 +msgid "conflicting requests" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1177 +msgid "some dependency problem" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1180 +#, boost-format +msgid "nothing provides the requested '%1%'" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1181 +#: zypp/solver/detail/SATResolver.cc:1185 +msgid "Have you enabled all the required repositories?" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1184 +#, boost-format +msgid "the requested package %1% does not exist" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1188 +msgid "unsupported request" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1191 +#, boost-format +msgid "'%1%' is provided by the system and cannot be erased" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1194 +#, boost-format +msgid "%1% is not installable" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1199 +#, boost-format +msgid "nothing provides '%1%' needed by the installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1201 +#, boost-format +msgid "nothing provides '%1%' needed by the to be installed %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1204 +#, boost-format +msgid "cannot install both %1% and %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1209 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1211 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1215 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1217 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1224 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1226 +#, boost-format +msgid "the installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1230 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1232 +#, boost-format +msgid "the to be installed %1% obsoletes '%2%' provided by the to be installed %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1237 +#, boost-format +msgid "the installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1239 +#, boost-format +msgid "the to be installed %1% conflicts with '%2%' provided by itself" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1271 +#, boost-format +msgid "the installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1273 +#, boost-format +msgid "the to be installed %1% requires '%2%', but this requirement cannot be provided" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1275 +msgid "deleted providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1285 +msgid "" +"\n" +"not installable providers: " +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1287 +msgid "not installable providers: " +msgstr "" + +#. translator: %1% is the name of a PTF, %2% the name of a patch. +#: zypp/solver/detail/SATResolver.cc:1324 +#, boost-format +msgid "%1% is not yet fully integrated into %2%." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1325 +msgid "Typically you want to keep the PTF and choose to not install the maintenance patches." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1333 +#, boost-format +msgid "Removing the installed %1% in this context will remove (not replace!) the included PTF-packages too." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1334 +#, boost-format +msgid "The PTF should be removed by calling '%1%'. This will update the included PTF-packages rather than removing them." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1335 +msgid "Typically you want to keep the PTF or choose to cancel the action." +msgstr "" + +#. translator: %1% is the name of a PTF. +#: zypp/solver/detail/SATResolver.cc:1340 +#, boost-format +msgid "The installed %1% blocks the desired action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1341 +msgid "Typically you want to keep the PTF and choose to cancel the action." +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1398 +#, boost-format +msgid "remove lock to allow removal of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1405 +#: zypp/solver/detail/SATResolver.cc:1443 +#, boost-format +msgid "do not install %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1422 +#: zypp/solver/detail/SATResolver.cc:1464 +#, boost-format +msgid "keep %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1427 +#, boost-format +msgid "remove lock to allow installation of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1478 +#: zypp/solver/detail/SATResolver.cc:1499 +msgid "This request will break your system!" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1479 +#: zypp/solver/detail/SATResolver.cc:1500 +msgid "ignore the warning of a broken system" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1484 +#, boost-format +msgid "do not ask to install a solvable providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1506 +#, boost-format +msgid "do not ask to delete all solvables providing %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1519 +#, boost-format +msgid "do not install most recent version of %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1540 +#, boost-format +msgid "keep %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1545 +#, boost-format +msgid "install %1% despite the inferior architecture" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1554 +#, boost-format +msgid "keep obsolete %1%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1559 +#, boost-format +msgid "install %1% from excluded repository" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1573 +#, boost-format +msgid "install %1% although it has been retracted" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1576 +#, boost-format +msgid "allow installing the PTF %1%" +msgstr "" + +#. translator: %1% is a package name +#: zypp/solver/detail/SATResolver.cc:1579 +#, boost-format +msgid "install %1% although it is blacklisted" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1599 +#, boost-format +msgid "downgrade of %1% to %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1606 +#, boost-format +msgid "architecture change of %1% to %2%" +msgstr "" + +#. FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. +#: zypp/solver/detail/SATResolver.cc:1617 +#, boost-format +msgid "" +"install %1% (with vendor change)\n" +" %2% --> %3%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1622 +#, boost-format +msgid "" +"install %1% from vendor %2%\n" +" replacing %3% from vendor %4%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1631 +#, boost-format +msgid "replacement of %1% with %2%" +msgstr "" + +#: zypp/solver/detail/SATResolver.cc:1642 +#, boost-format +msgid "deinstallation of %1%" +msgstr "" + +#. Translator: progress bar label +#: zypp/target/RpmPostTransCollector.cc:200 +msgid "Running post-transaction scripts" +msgstr "" + +#. Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:202 +#, boost-format +msgid "Running %1% script" +msgstr "" + +#. Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' +#: zypp/target/RpmPostTransCollector.cc:204 +#, boost-format +msgid "%1% script output:" +msgstr "" + +#: zypp/target/TargetException.cc:27 +msgid "Installation has been aborted as directed." +msgstr "" + +#: zypp/target/TargetImpl.cc:462 +msgid " executed" +msgstr "" + +#: zypp/target/TargetImpl.cc:484 +msgid " execution failed" +msgstr "" + +#. translators: We may find the same script content in files with different names. +#. Only the first occurence is executed, subsequent ones are skipped. It's a one-line +#. message for a log file. Preferably start translation with "%s" +#: zypp/target/TargetImpl.cc:601 +#, c-format, boost-format +msgid "%s already executed as %s)" +msgstr "" + +#: zypp/target/TargetImpl.cc:611 +msgid " execution skipped while aborting" +msgstr "" + +#: zypp/target/TargetImpl.cc:666 zypp/target/TargetImpl.cc:686 +#: zypp/target/TargetImpl.cc:714 zypp/target/TargetImpl.cc:751 +#: zypp/target/TargetImpl.cc:759 +msgid "Error sending update message notification." +msgstr "" + +#: zypp/target/TargetImpl.cc:810 +msgid "New update message" +msgstr "" + +#. translator: %1% is the received unix signal name, %2% is the numerical value of the received signal +#: zypp/target/TargetImpl.cc:2114 +#, boost-format +msgid "Received signal :\"%1% (%2%)\", to ensure the consistency of the system it is not possible to cancel a running rpm transaction." +msgstr "" + +#: zypp/target/TargetImpl.cc:2722 +msgid "Executing the transaction failed because of the following problems:" +msgstr "" + +#. TranslatorExplanation after semicolon is error message +#. TranslatorExplanation the colon is followed by an error message +#: zypp/target/rpm/RpmDb.cc:474 zypp/target/rpm/RpmDb.cc:1843 +#: zypp/target/rpm/RpmDb.cc:2016 +msgid "RPM failed: " +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:799 +#, boost-format +msgid "Failed to import public key %1%" +msgstr "" + +#. Translator: %1% is a gpg public key +#: zypp/target/rpm/RpmDb.cc:866 +#, boost-format +msgid "Failed to remove public key %1%" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1282 +msgid "Package header is not signed!" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:1284 +msgid "Package payload is not signed!" +msgstr "" + +#. Translator: %s = name of an rpm package. A list of diffs follows +#. this message. +#: zypp/target/rpm/RpmDb.cc:1621 +#, c-format, boost-format +msgid "Changed configuration files for %s:" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1824 +#, c-format, boost-format +msgid "rpm saved %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1826 +#, c-format, boost-format +msgid "" +"rpm saved %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1829 +#, c-format, boost-format +msgid "rpm created %s as %s, but it was impossible to determine the difference" +msgstr "" + +#. %s = filenames +#: zypp/target/rpm/RpmDb.cc:1831 +#, c-format, boost-format +msgid "" +"rpm created %s as %s.\n" +"Here are the first 25 lines of difference:\n" +msgstr "" + +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#. report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) +#. TranslatorExplanation Text is followed by a ':' and the actual output. +#: zypp/target/rpm/RpmDb.cc:1859 zypp/target/rpm/RpmDb.cc:2032 +msgid "Additional rpm output" +msgstr "" + +#: zypp/target/rpm/RpmDb.cc:2230 +#, c-format, boost-format +msgid "created backup %s" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2251 +msgid "Signature is OK" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2253 +msgid "Unknown type of signature" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2255 +msgid "Signature does not verify" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2257 +msgid "Signature is OK, but key is not trusted" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2259 +msgid "Signatures public key is not available" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2261 +msgid "File does not exist or signature can't be checked" +msgstr "" + +#. translators: possible rpm package signature check result [brief] +#: zypp/target/rpm/RpmDb.cc:2263 +msgid "File is unsigned" +msgstr "" + +#. dubious: Throw on malformed known types, otherwise log a warning. +#: zypp-core/CheckSum.cc:136 +#, c-format, boost-format +msgid "Dubious type '%s' for %u byte checksum '%s'" +msgstr "" + +#: zypp-core/ExternalProgram.cc:245 +#, c-format, boost-format +msgid "Can't open pty (%s)." +msgstr "" + +#: zypp-core/ExternalProgram.cc:264 zypp-core/ExternalProgram.cc:281 +#, c-format, boost-format +msgid "Can't open pipe (%s)." +msgstr "" + +#: zypp-core/Url.cc:118 +msgid "Invalid LDAP URL query string" +msgstr "" + +#: zypp-core/Url.cc:157 +#, c-format, boost-format +msgid "Invalid LDAP URL query parameter '%s'" +msgstr "" + +#: zypp-core/Url.cc:305 +msgid "Unable to clone Url object" +msgstr "" + +#: zypp-core/Url.cc:318 +msgid "Invalid empty Url object reference" +msgstr "" + +#: zypp-core/Url.cc:331 zypp-core/Url.cc:345 +msgid "Unable to parse Url components" +msgstr "" + +#: zypp-core/base/Exception.cc:186 +msgid "History:" +msgstr "" + +#: zypp-core/url/UrlBase.cc:221 +#, c-format, boost-format +msgid "Url scheme does not allow a %s" +msgstr "" + +#: zypp-core/url/UrlBase.cc:240 +#, c-format, boost-format +msgid "Invalid %s component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:247 +#, c-format, boost-format +msgid "Invalid %s component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:864 zypp-core/url/UrlBase.cc:1309 +msgid "Query string parsing not supported for this URL" +msgstr "" + +#: zypp-core/url/UrlBase.cc:902 +msgid "Url scheme is a required component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:908 +#, c-format, boost-format +msgid "Invalid Url scheme '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1027 +msgid "Url scheme does not allow a username" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1061 +msgid "Url scheme does not allow a password" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1090 +msgid "Url scheme requires a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1100 +msgid "Url scheme does not allow a host component" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1127 +#, c-format, boost-format +msgid "Invalid host component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1148 +msgid "Url scheme does not allow a port" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1159 +#, c-format, boost-format +msgid "Invalid port component '%s'" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1176 +msgid "Url scheme requires path name" +msgstr "" + +#: zypp-core/url/UrlBase.cc:1197 zypp-core/url/UrlBase.cc:1211 +msgid "Relative path not allowed if authority exists" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:111 +msgid "Encoded string contains a NUL byte" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:173 +msgid "Invalid parameter array split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:213 +msgid "Invalid parameter map split separator character" +msgstr "" + +#: zypp-core/url/UrlUtils.cc:283 +msgid "Invalid parameter array join separator character" +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:183 +#, c-format, boost-format +msgid "Command exited with status %d." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:204 +#, c-format, boost-format +msgid "Command was killed by signal %d (%s)." +msgstr "" + +#: zypp-core/zyppng/io/abstractspawnengine.cc:209 +msgid "Command exited with unknown error." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:243 +#: zypp-core/zyppng/io/forkspawnengine.cc:486 +msgid "Invalid spawn arguments given." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:299 +msgid "Unable to create control pipe." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:366 +#, c-format, boost-format +msgid "Can't chroot to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:376 +#, c-format, boost-format +msgid "Can't chdir to '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:377 +#, c-format, boost-format +msgid "Can't chdir to '%s' inside chroot '%s' (%s)." +msgstr "" + +#. don't want to get here +#: zypp-core/zyppng/io/forkspawnengine.cc:406 +#, c-format, boost-format +msgid "Can't exec '%s' (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:413 +#: zypp-core/zyppng/io/forkspawnengine.cc:567 +#, c-format, boost-format +msgid "Can't fork (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:432 +#, c-format, boost-format +msgid "Can't exec '%s', chdir failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:435 +#, c-format, boost-format +msgid "Can't exec '%s', chroot failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:438 +#, c-format, boost-format +msgid "Can't exec '%s', exec failed (%s)." +msgstr "" + +#: zypp-core/zyppng/io/forkspawnengine.cc:442 +#, c-format, boost-format +msgid "Can't exec '%s', unexpected error." +msgstr "" + +#: zypp-media/mediaexception.cc:33 +#, c-format, boost-format +msgid "Failed to mount %s on %s" +msgstr "" + +#: zypp-media/mediaexception.cc:43 +#, c-format, boost-format +msgid "Failed to unmount %s" +msgstr "" + +#: zypp-media/mediaexception.cc:48 +#, c-format, boost-format +msgid "Bad file name: %s" +msgstr "" + +#: zypp-media/mediaexception.cc:53 +#, c-format, boost-format +msgid "Medium not opened when trying to perform action '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:58 +#: zypp-curl/ng/network/networkrequesterror.cc:138 +#, c-format, boost-format +msgid "File '%s' not found on medium '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:63 +#, c-format, boost-format +msgid "Cannot write file '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:68 +msgid "Medium not attached" +msgstr "" + +#: zypp-media/mediaexception.cc:73 +msgid "Bad media attach point" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:79 +#, c-format, boost-format +msgid "Download (curl) initialization failed for '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:84 +#, c-format, boost-format +msgid "System exception '%s' on medium '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:89 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a file." +msgstr "" + +#: zypp-media/mediaexception.cc:94 +#, c-format, boost-format +msgid "Path '%s' on medium '%s' is not a directory." +msgstr "" + +#: zypp-media/mediaexception.cc:101 +msgid "Malformed URI" +msgstr "" + +#: zypp-media/mediaexception.cc:111 +msgid "Empty host name in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:116 +msgid "Empty filesystem in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:121 +msgid "Empty destination in URI" +msgstr "" + +#: zypp-media/mediaexception.cc:126 +#, c-format, boost-format +msgid "Unsupported URI scheme in '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:131 +msgid "Operation not supported by medium" +msgstr "" + +#: zypp-media/mediaexception.cc:138 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +"Error message: %s\n" +msgstr "" + +#. TranslatorExplanation: curl is the name of a library, don't translate +#: zypp-media/mediaexception.cc:146 +#, c-format, boost-format +msgid "Error occurred while setting download (curl) options for '%s':" +msgstr "" + +#: zypp-media/mediaexception.cc:153 +#, c-format, boost-format +msgid "Media source '%s' does not contain the desired medium" +msgstr "" + +#: zypp-media/mediaexception.cc:158 +#, c-format, boost-format +msgid "Medium '%s' is in use by another instance" +msgstr "" + +#: zypp-media/mediaexception.cc:164 +msgid "Cannot eject any media" +msgstr "" + +#: zypp-media/mediaexception.cc:166 +#, c-format, boost-format +msgid "Cannot eject media '%s'" +msgstr "" + +#: zypp-media/mediaexception.cc:181 +#, c-format, boost-format +msgid "Permission to access '%s' denied." +msgstr "" + +#: zypp-media/mediaexception.cc:189 +#: zypp-curl/ng/network/networkrequesterror.cc:122 +#, c-format, boost-format +msgid "Timeout exceeded when accessing '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:197 +#, c-format, boost-format +msgid "Downloaded data exceeded the expected filesize '%s' of '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:205 +#: zypp-curl/ng/network/networkrequesterror.cc:118 +#, c-format, boost-format +msgid "Location '%s' is temporarily unaccessible." +msgstr "" + +#: zypp-media/mediaexception.cc:213 +#, c-format, boost-format +msgid " SSL certificate problem, verify that the CA cert is OK for '%s'." +msgstr "" + +#: zypp-media/mediaexception.cc:220 +msgid "No free ressources available to attach medium." +msgstr "" + +#: zypp-curl/auth/curlauthdata.cc:97 +#, c-format, boost-format +msgid "Unsupported HTTP authentication method '%s'" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:143 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Error code: %s\n" +msgstr "" + +#: zypp-curl/ng/network/networkrequesterror.cc:149 +#, c-format, boost-format +msgid "" +"Download (curl) error for '%s':\n" +"Unable to retrieve HTTP response\n" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "Yes" +msgstr "" + +#: zypp-tui/Table.cc:32 +msgid "No" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:26 +msgid "Note:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:28 +msgid "Warning:" +msgstr "" + +#. translator: usually followed by a ' ' and some explanatory text +#: zypp-tui/output/Out.cc:30 +msgid "Error:" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ............[done] +#. Translator: download progress bar result: ".............[done]" +#: zypp-tui/output/Out.cc:141 zypp-tui/output/OutNormal.cc:341 +#: zypp-tui/output/OutNormal.cc:344 +msgid "done" +msgstr "" + +#. translator: Shown as result tag in a progress bar: .......[attention] +#: zypp-tui/output/Out.cc:143 +msgid "attention" +msgstr "" + +#. translator: Shown as result tag in a progress bar: ...........[error] +#. Translator: download progress bar result: "............[error]" +#: zypp-tui/output/Out.cc:145 zypp-tui/output/OutNormal.cc:338 +#: zypp-tui/output/OutNormal.cc:344 +msgid "error" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:90 +msgid "Warning: " +msgstr "" + +#: zypp-tui/output/OutNormal.cc:254 zypp-tui/output/OutNormal.cc:288 +#: zypp-tui/output/OutNormal.cc:326 +msgid "Retrieving:" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:261 +msgid "starting" +msgstr "" + +#. Translator: download progress bar result: "........[not found]" +#: zypp-tui/output/OutNormal.cc:335 zypp-tui/output/OutNormal.cc:344 +msgid "not found" +msgstr "" + +#: zypp-tui/output/OutNormal.cc:421 +msgid "No help available for this prompt." +msgstr "" + +#: zypp-tui/output/OutNormal.cc:438 +msgid "no help available for this option" +msgstr "" + +#. translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" +#: zypp-tui/output/promptoptions.cc:85 +msgid "shows all options" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "yes" +msgstr "" + +#: zypp-tui/output/promptoptions.cc:194 +msgid "no" +msgstr "" diff --git a/shared/CMakeLists.txt b/shared/CMakeLists.txt new file mode 100644 index 0000000..3ad7078 --- /dev/null +++ b/shared/CMakeLists.txt @@ -0,0 +1,14 @@ +# This subproject contains small shared object libraries +# usually used in libzypp and workers, or for tests. + +# rpm protocol definition, could be moved to a zypp-rpm lib some day +# if more than one class is required to be shared between libzypp and zypp-rpm +ADD_LIBRARY( commit-proto-obj OBJECT commit/CommitMessages.h commit/CommitMessages.cc ) +target_link_libraries( commit-proto-obj PRIVATE zypp_lib_compiler_flags ) + +# tvm protocol lib +ADD_LIBRARY( tvm-protocol-obj OBJECT tvm/tvmsettings.h tvm/tvmsettings.cc ) +target_link_libraries( tvm-protocol-obj PRIVATE zypp_lib_compiler_flags ) + + + diff --git a/shared/commit/CommitMessages.cc b/shared/commit/CommitMessages.cc new file mode 100644 index 0000000..21878cb --- /dev/null +++ b/shared/commit/CommitMessages.cc @@ -0,0 +1,463 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "CommitMessages.h" + +#include +#include +#include +#include +#include + +namespace zypp::proto::target +{ + namespace { + // Serializes a field of type T into the ByteArray buffer, appending a \0 to terminate the field + template + void serializeStepField ( ByteArray &data, const T&field ) { + if constexpr ( std::is_same_v ) { + if ( field ) { + data.push_back ('1'); + data.push_back ('\0'); + } else { + data.push_back ('0'); + data.push_back ('\0'); + } + } else if constexpr ( std::is_same_v ) { + data.insert(data.end(), field.begin(), field.end() ); + data.push_back ('\0'); + } else { + // numbers, convert to string and recursively call again + serializeStepField (data, str::numstring (field) ); + } + } + + // fetches a terminated string from the iterator, requires the terminator to come up before hitting the \a end + std::string fetchTerminatedField ( ByteArray::const_iterator &i, ByteArray::const_iterator end, const char term = '\0' ){ + std::string fData; + fData.reserve(512); + while ( true ) { + if ( i == end ) + ZYPP_THROW( zypp::PluginFrameException("Unexpected end of field in transaction step") ); + if ( *i == term ) { + i++; // consume the terminator + break; + } + fData.push_back( *i ); + i++; + } + + fData.shrink_to_fit(); + return fData; + }; + + template + using has_stepid = decltype(std::declval().stepId); + + template + zyppng::expected makeTrivialMessage( const std::string &command, const T& msg ) { + + PluginFrame f(command); + if constexpr ( std::is_detected_v ) + f.addHeader ("stepId", asString (msg.stepId) ); + return zyppng::expected::success ( std::move(f) ); + } + + template + zyppng::expected parseTrivialMessage( const PluginFrame &msg ) { + try { + T c; + if ( msg.command() != T::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException( str::Str()<<"Message is not a " << T::typeName ) ) ); + + if constexpr ( std::is_detected_v ) { + zyppng::rpc::parseHeaderIntoField ( msg, "stepId", c.stepId ); + } + + return zyppng::expected::success(c); + + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + } + +#define IMPL_TRIVIAL_MESSAGE( Type ) \ + zyppng::expected Type::toStompMessage() const \ + { \ + return makeTrivialMessage( #Type, *this ); \ + } \ + \ + zyppng::expected Type::fromStompMessage(const PluginFrame &msg) \ + { \ + return parseTrivialMessage( msg ); \ + } + + zyppng::expected Commit::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("flags", asString (flags) ); + f.addHeader ("arch", arch ); + f.addHeader ("root", root ); + f.addHeader ("dbPath", dbPath ); + f.addHeader ("lockFilePath", lockFilePath ); + f.addHeader ("ignoreArch", ignoreArch ? "1" : "0" ); + + ByteArray &body = f.bodyRef(); + for ( const auto &step : transactionSteps ) { + if ( std::holds_alternative(step) ) { + const InstallStep &value = std::get(step); + body.push_back( InstallStepType ); + serializeStepField( body, value.stepId ); + serializeStepField( body, value.pathname ); + serializeStepField( body, value.multiversion ); + + } else if ( std::holds_alternative(step) ) { + const RemoveStep &value = std::get(step); + body.push_back( RemoveStepType ); + serializeStepField( body, value.stepId ); + serializeStepField( body, value.name ); + serializeStepField( body, value.version ); + serializeStepField( body, value.release ); + serializeStepField( body, value.arch ); + } else { + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Unknown Step type in message") ) ); + } + } + body.shrink_to_fit(); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected Commit::fromStompMessage( const zypp::PluginFrame &msg ) + { + try { + Commit c; + + if ( msg.command() != Commit::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a Commit") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "flags", c.flags ); + zyppng::rpc::parseHeaderIntoField ( msg, "arch", c.arch ); + zyppng::rpc::parseHeaderIntoField ( msg, "root", c.root ); + zyppng::rpc::parseHeaderIntoField ( msg, "dbPath", c.dbPath ); + zyppng::rpc::parseHeaderIntoField ( msg, "lockFilePath", c.lockFilePath ); + zyppng::rpc::parseHeaderIntoField ( msg, "ignoreArch", c.ignoreArch ); + + // we got the fields, lets parse the steps + // steps are serialized into a very simple form, starting with one byte that tells us what step type we look at + // + enum ParseState { + ReadingStepType, + Reading + }; + + const auto &data = msg.body (); + for ( auto i = data.begin(); i != data.end(); ) { + uint8_t stepType = *i; + i++; + + if ( i == data.end() ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Invalid data in commit message") ) ); + + switch ( stepType ) { + case InstallStepType: { + InstallStep s; + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.stepId ); + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.pathname ); + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.multiversion ); + c.transactionSteps.push_back(s); + break; + } + case RemoveStepType: { + RemoveStep s; + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.stepId ); + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.name ); + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.version ); + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.release ); + zyppng::rpc::parseDataIntoField( fetchTerminatedField(i, data.end() ), s.arch ); + c.transactionSteps.push_back(s); + break; + } + default: + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Invalid step type in commit message") ) ); + } + } + + return zyppng::expected::success ( std::move(c) ); + + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected TransactionError::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + ByteArray &body = f.bodyRef(); + for ( const auto &err : problems ) { + serializeStepField ( body, err ); + } + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected TransactionError::fromStompMessage(const PluginFrame &msg) + { + try { + TransactionError c; + if ( msg.command() != TransactionError::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a TransactionError") ) ); + + const auto &data = msg.body (); + for ( auto i = data.begin(); i != data.end(); ) { + c.problems.push_back( fetchTerminatedField( i, data.end() ) ); + } + + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected RpmLog::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("level", asString (level) ); + f.setBody( line ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected RpmLog::fromStompMessage(const PluginFrame &msg) + { + try { + RpmLog c; + if ( msg.command() != RpmLog::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a RpmLog") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "level", c.level ); + c.line = msg.body().asString(); + + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + IMPL_TRIVIAL_MESSAGE(PackageBegin) + IMPL_TRIVIAL_MESSAGE(PackageFinished) + IMPL_TRIVIAL_MESSAGE(PackageError) + + zyppng::expected PackageProgress::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("stepId", asString (stepId) ); + f.addHeader ("amount", asString (amount) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected PackageProgress::fromStompMessage(const PluginFrame &msg) + { + try { + PackageProgress c; + if ( msg.command() != PackageProgress::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a PackageProgress") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "stepId", c.stepId ); + zyppng::rpc::parseHeaderIntoField ( msg, "amount", c.amount ); + + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected CleanupBegin::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("nvra", asString (nvra) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected CleanupBegin::fromStompMessage(const PluginFrame &msg) + { + try { + CleanupBegin c; + if ( msg.command() != CleanupBegin::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a CleanupBegin") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "nvra", c.nvra ); + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected CleanupFinished::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("nvra", asString (nvra) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected CleanupFinished::fromStompMessage(const PluginFrame &msg) + { + try { + CleanupFinished c; + if ( msg.command() != CleanupFinished::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a CleanupFinished") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "nvra", c.nvra ); + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected CleanupProgress::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("nvra", asString (nvra) ); + f.addHeader ("amount", asString (amount) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected CleanupProgress::fromStompMessage(const PluginFrame &msg) + { + try { + CleanupProgress c; + if ( msg.command() != CleanupProgress::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a CleanupProgress") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "nvra", c.nvra ); + zyppng::rpc::parseHeaderIntoField ( msg, "amount", c.amount ); + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected ScriptBegin::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("stepId" , asString (stepId) ); + f.addHeader ("scriptType" , asString (scriptType) ); + f.addHeader ("scriptPackage", asString (scriptPackage) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected ScriptBegin::fromStompMessage(const PluginFrame &msg) + { + try { + ScriptBegin c; + if ( msg.command() != ScriptBegin::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a ScriptBegin") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "stepId" , c.stepId ); + zyppng::rpc::parseHeaderIntoField ( msg, "scriptType" , c.scriptType ); + zyppng::rpc::parseHeaderIntoField ( msg, "scriptPackage" , c.scriptPackage ); + + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + IMPL_TRIVIAL_MESSAGE(ScriptFinished) + + zyppng::expected ScriptError::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("stepId" , asString (stepId) ); + f.addHeader ("fatal" , asString (fatal) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected ScriptError::fromStompMessage(const PluginFrame &msg) + { + try { + ScriptError c; + if ( msg.command() != ScriptError::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a ScriptError") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "stepId" , c.stepId ); + zyppng::rpc::parseHeaderIntoField ( msg, "fatal" , c.fatal ); + + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected TransBegin::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("name" , asString (name) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected TransBegin::fromStompMessage(const PluginFrame &msg) + { + try { + TransBegin c; + if ( msg.command() != TransBegin::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a TransBegin") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "name" , c.name ); + + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + IMPL_TRIVIAL_MESSAGE( TransFinished ); + + zyppng::expected TransProgress::toStompMessage() const + { + PluginFrame f = zyppng::rpc::prepareFrame(); + f.addHeader ("amount", asString (amount) ); + return zyppng::expected::success ( std::move(f) ); + } + + zyppng::expected TransProgress::fromStompMessage(const PluginFrame &msg) + { + try { + TransProgress c; + if ( msg.command() != TransProgress::typeName ) + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::PluginFrameException("Message is not a TransProgress") ) ); + + zyppng::rpc::parseHeaderIntoField ( msg, "amount", c.amount ); + + return zyppng::expected::success( std::move(c) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + +} diff --git a/shared/commit/CommitMessages.h b/shared/commit/CommitMessages.h new file mode 100644 index 0000000..baf4bd2 --- /dev/null +++ b/shared/commit/CommitMessages.h @@ -0,0 +1,212 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_SHARED_COMMIT_COMMITMESSAGE_H_INCLUDED +#define ZYPP_SHARED_COMMIT_COMMITMESSAGE_H_INCLUDED + +#include +#include + +#include +#include +#include +#include + +/*! + * This file specifies all messages that are sent between TargetImpl and the zypp-rpm + * backend binary. The communication protocol uses our implementation of the + * STOMP protocol mesage format. \sa zypp::PluginFrame + */ +namespace zypp::proto::target +{ + + // transaction steps are sent as part of the Commit Message + // serialized to 0x0\stepId\0pathName\0multiversion\0 + struct InstallStep { + uint32_t stepId; + std::string pathname; + bool multiversion; + }; + + // serialized to 0x1stepId\0name\0version\0release\0arch\0 + struct RemoveStep { + uint32_t stepId; + std::string name; + std::string version; + std::string release; + std::string arch ; + }; + + using TransactionStep = std::variant; + + // first message that is sent to zypp-rpm + // to setup the commit basics. + struct Commit + { + Commit() = default; + Commit(const Commit &) = default; + Commit(Commit &&) = default; + Commit &operator=(const Commit &) = default; + Commit &operator=(Commit &&) = default; + + static constexpr std::string_view typeName = "Commit"; + enum StepTypes : uint8_t { + InstallStepType, + RemoveStepType + }; + + uint32_t flags; + std::string arch; + std::string root; + std::string dbPath; + std::string lockFilePath; + bool ignoreArch; + std::vector transactionSteps; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + + // message written to zypper when the transaction has failed + struct TransactionError { + static constexpr std::string_view typeName = "TransactionError"; + std::vector problems; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + // message written to the rpm log including the level + struct RpmLog { + static constexpr std::string_view typeName = "RpmLog"; + uint32_t level; + std::string line; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + + }; + + // Per package information which directly correspond to a TransactionStep !!!! + struct PackageBegin { + static constexpr std::string_view typeName = "PackageBegin"; + uint32_t stepId; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct PackageFinished { + static constexpr std::string_view typeName = "PackageFinished"; + uint32_t stepId; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct PackageError { + static constexpr std::string_view typeName = "PackageError"; + uint32_t stepId; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct PackageProgress { + static constexpr std::string_view typeName = "PackageProgress"; + uint32_t stepId; + uint32_t amount; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + // Progress for cleaning up old versions of packages + // which have NO corresponding TransactionStep + struct CleanupBegin { + static constexpr std::string_view typeName = "CleanupBegin"; + std::string nvra; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct CleanupFinished { + static constexpr std::string_view typeName = "CleanupFinished"; + std::string nvra; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct CleanupProgress { + static constexpr std::string_view typeName = "CleanupProgress"; + std::string nvra; + uint32_t amount; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + // per script info, for each of those the stepId can be -1 or point + // to a valid step in the transaction set. + struct ScriptBegin { + static constexpr std::string_view typeName = "ScriptBegin"; + int32_t stepId; + std::string scriptType; + std::string scriptPackage; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct ScriptFinished { + static constexpr std::string_view typeName = "ScriptFinished"; + int32_t stepId; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct ScriptError { + static constexpr std::string_view typeName = "ScriptError"; + int32_t stepId; + bool fatal; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + // Generic Transactionstep report, we use it for preparing and verifying progress + struct TransBegin { + static constexpr std::string_view typeName = "TransBegin"; + std::string name; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct TransFinished { + static constexpr std::string_view typeName = "TransFinished"; + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + struct TransProgress { + static constexpr std::string_view typeName = "TransProgress"; + uint32_t amount; + + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + +} + +#endif // ZYPP_SHARED_COMMIT_COMMITMESSAGE_H_INCLUDED diff --git a/shared/tvm/tvmsettings.cc b/shared/tvm/tvmsettings.cc new file mode 100644 index 0000000..ea80046 --- /dev/null +++ b/shared/tvm/tvmsettings.cc @@ -0,0 +1 @@ +#include "tvmsettings.h" diff --git a/shared/tvm/tvmsettings.h b/shared/tvm/tvmsettings.h new file mode 100644 index 0000000..7a86f97 --- /dev/null +++ b/shared/tvm/tvmsettings.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_SHARED_TVM_TVMSETTINGS_H_INCLUDED +#define ZYPP_SHARED_TVM_TVMSETTINGS_H_INCLUDED + +#include +#include +#include + +namespace zypp::test { + + struct TVMSettings + { + struct Device { + std::string name; // the device name + std::string insertedPath; // the path what is currently inserted into the device + }; + std::vector devices; + }; +} + +namespace YAML { + template<> + struct convert { + static Node encode(const zypp::test::TVMSettings& rhs) { + Node node; + node["devices"] = rhs.devices; + return node; + } + + static bool decode(const Node& node, zypp::test::TVMSettings& rhs) { + if(!node.IsMap() || !node["devices"] ) { + return false; + } + + rhs.devices = node["devices"].as>(); + return true; + } + }; + + template<> + struct convert { + static Node encode(const zypp::test::TVMSettings::Device& rhs) { + Node node; + node["name"] = rhs.name; + node["insertedPath"] = rhs.insertedPath; + return node; + } + + static bool decode(const Node& node, zypp::test::TVMSettings::Device& rhs) { + if(!node.IsMap() || !node["name"] || !node["insertedPath"] ) { + return false; + } + + rhs.name = node["name"].as(); + rhs.insertedPath = node["insertedPath"].as(); + return true; + } + }; +} + + +#endif diff --git a/systemCheck b/systemCheck new file mode 100644 index 0000000..4cb60e2 --- /dev/null +++ b/systemCheck @@ -0,0 +1,13 @@ +## +## This file contains requirements/conflicts which fulfill the +## needs of a running system. +## For example the system would be broken if not glibc or kernel is +## installed. +## So the user will be informed if these packages will be deleted. +## +## format: Each line represents one dependency: +## e.g. +## requires:kernel +## requires:glibc + +requires:glibc diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 0000000..6cc4b9f --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,20 @@ + +ADD_DEFINITIONS( -DTESTS_SRC_DIR="${CMAKE_CURRENT_SOURCE_DIR}" -DTESTS_BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}" ) + +IF( NOT DISABLE_MEDIABACKEND_TESTS ) +ADD_SUBDIRECTORY(lib) +ENDIF() + +ENABLE_TESTING() +INCLUDE_DIRECTORIES( ${LIBZYPP_SOURCE_DIR}/tests/lib ) + +ADD_SUBDIRECTORY( media ) +ADD_SUBDIRECTORY( zypp ) +ADD_SUBDIRECTORY( parser ) +ADD_SUBDIRECTORY( repo ) +ADD_SUBDIRECTORY( sat ) +ADD_SUBDIRECTORY( zyppng ) + +ADD_CUSTOM_TARGET( ctest + COMMAND ctest -VV -a +) diff --git a/tests/README b/tests/README new file mode 100644 index 0000000..38a246b --- /dev/null +++ b/tests/README @@ -0,0 +1,29 @@ + +You can find here unit tests for lot of zypp classes. + +run +ctest . + +or the binary itself to run just one test + + +Note on libboost_unit_test_framework.so.1.38.0 +---------------------------------------------- + +When you run the tests manually, some of the testcases here may fail +with an error message like: + + unknown location(0): \ + fatal error in "keyring_test": \ + child has exited; pid: 7222; uid: 216; exit value: 2 + +This happens because the boost test framework we use monitors the +return code of child processes. This monitoring should be turned off. + +You can do this either via a commandfline option: + + ./KeyRing_test --catch_system_errors=no + +Or via an environment variable: + + BOOST_TEST_CATCH_SYSTEM_ERRORS=no ./KeyRing_test diff --git a/tests/data/11.0-update/repodata/deltainfo.xml.gz b/tests/data/11.0-update/repodata/deltainfo.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..61e6b405f111b2572bc11daaff87465fcc905b43 GIT binary patch literal 206608 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 Nrqt9ujtvfvV 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�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 z zX?m{t=X~fpal1`wtVmWpSXy2fExC-SIP4U?(a;Q6g(url*qqh&3MxNFzJM&XfV`=d zEvoY0nUj*OjReFd`SiPdROUZeN==?&1IJogC$X!5x(z zpUgp^?$bCu*~nXc?7>TIv&}JKiv1vMa>-E)9<>Ef8C^M*QyX^d`~>6J5XhtkuSX7m&LL;?U;aN=1*UN5(5w+$pEZ^Z_% zKCuC)S3b&geF3oEDTc=nB4=V}>apb?%?TCoV?qzNH0|209F)H63GW*3MOHNyKAM^} zhLw^lW5aya?|_*Hb3Fj72t7)OR=h5xZ_Y7`T$?bK?gv|psuJ~c)gRs5DDFW&+Fa4} z`8z6yxvq~qIc`OBhT$peoB(HSX3%i+BZI7b?CJhbq989~6C#ng9&vEEwP4gPj((>= zuWydlaRLyJ_H_1v@W}FA zv_p`x^4;L@<}h6fh1FTKq3doAT zb3qwUCmVFF0uSyg59OHvOD0hnQ6#fD`v=@BmqRpC2U}5iLwd>~qJZ>Fgp3>l%3$;< z>yTo9G-Z2#2qtl{tPt)kFlggA{#shy-xS{NK2et@-t-`>Toyr#;F)jPf}9jYL1i71 zcK%Em-u8c=>n>e@RtZylXfI|ryjwrN=8M{d@!SnZ^*^(skqg|HsOE-y=g!UE1;r7P zPF2VUVn|jC!l_bp!;`81nnXc0$E55gCQ~nficHdvN2O5=6uEiZ`n?BBUh-c_y3Wg0 zD=RbAyDe?b|J%Pg35!9nr|*9Z_caYKVm@{OXxJ~Qpn$X@?<9Qx+lnWSFyqUjeSa@N zoeG~r^g}5BHT4h?z6Z8P*MFOu&MO=aq5Q9;%J3)J3U(2mN^|LX8|e3;+*?o>|1;d} zw-cmi0cf~2$WM4#d43qUwZQ)teyPv_$yU(UJ`mz2z5~W{sLKa=ja<=rYXfG*IY$Qe z!hQ=m9{E2qYQ@2R$zs}meLhqR?LvJt8Tdi-pCsxo#Q96@wjwP=_}Wo#-buX_VGiU` zTmtYEVk5*!a^_sxLGZQ$oa_QTAe_Z5)!X<={7h4DVj6zo�qpaR<6M{!>0#lo*Tr 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

Iy6HlOduu3oEG*@cjJ6>ZJk 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

j=2+520UXs=wLh0l&|4|bPW~b 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

TYyamR}^4$hi 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

T&b`=n00;13^fg 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 KjFXMtWsm@J$Bo + + + + c1d8b4a70e4e2ed3cf5d68d27319974cc023cf03 + 1224755528 + 5c8a77e4e4f57070709f995d2d2ebee13b052ded + + + + 630e1f5bc7d12bc26b571e35380191835bf9e5e7 + 1224755531 + 726ac5ccf337abfa42bd6a76d032c3ed7a923ea8 + + + + 958ea074b3c3ff7c57112e292ff1bceb07c6d682 + 1224755535 + 4a44c8ef91cefaaaf31070d5556ca94b27525dc9 + + + + 7949794d363b7a84c2e9168649613bdcdf9b2b91 + 1224755535 + f26bbdd272a1f51f750b76b67bee6f178e9645e0 + + + + da21499c94aef90694c8e9d94eec39ab3891cbc8 + 1224755535 + 7314b359cc9b5c68f22cbe7df2e8cfb964224593 + + diff --git a/tests/data/11.0-update/repodata/repomd.xml.asc b/tests/data/11.0-update/repodata/repomd.xml.asc new file mode 100644 index 0000000..768a149 --- /dev/null +++ b/tests/data/11.0-update/repodata/repomd.xml.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBJAElRqE7a6JyACsoRAugdAKCImJX9Aop0Z5ngfpYz1Z6ec4637QCg +kDTnvGTdR3QFlYLXDEnK2UpM3hs= +=QwmG +-----END PGP SIGNATURE----- diff --git a/tests/data/11.0-update/repodata/repomd.xml.key b/tests/data/11.0-update/repodata/repomd.xml.key new file mode 100644 index 0000000..daeef8a --- /dev/null +++ b/tests/data/11.0-update/repodata/repomd.xml.key @@ -0,0 +1,37 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +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 +=mY6G +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/11.0-update/repodata/updateinfo.xml.gz b/tests/data/11.0-update/repodata/updateinfo.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..11608e4a22b811f7d1fb5dd48ba3351112217ae5 GIT binary patch literal 62833 zcmV);K!(2`iwFQuNdQRz1H4^Zmz+3~e$QW_tvP4M-ea=3Uux~{b^9{y(`|Qe+ub{F zJ_1B0QzT-5taAC+Z%9BUkdUq_1@?=xKni`*7Yc8<8p{P@G_`M!v0%_;(^^XkRLwyuk-%gdbKuq<0ge0N#U=$dZW<&M=9 zlG4j+U$M(3Tbd{Q0)+gBrv3i%)2pA~eR%sDN#hq6)N{!q~yC77dx8fwH9$+#{VPAT*vULzAG3cWYNA%>${6% z1uYkV5b`{YfB3@7jrPSbw13{@(eq1qB3{&Kov|O@@3T5BGDiLhiO9`9%UMaoG)wCg z8lhwbFKZT)@Q$RfS;F#)J-=*n3K=EK7_Hb3ykPmqKR>=92DIz*%kHr(zpC~iK-3Fb z-83xM(rwGUxNHR^tOOcZCI0L`AY1s^w0{Kzg!|3cG|T9^$3(T|x1Zs~I@+W^LMvOI zZ5jTBZ1C>4#QNd_QjvVW3t34HZ)D4La$7u?LqN}CRz+o6)X=0qeA=cJX&Fk=FVH-@ zuJOk0)^E5~*Kk)WjlBBnjb`e)ubGys6OH`w=ELhZe~>p{YDfWvkS(JH3HJ%0AW+jX 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 literal 0 HcmV?d00001 diff --git a/tests/data/Mirrorlist/remote-site/metalink.xml b/tests/data/Mirrorlist/remote-site/metalink.xml new file mode 100644 index 0000000..5df588b --- /dev/null +++ b/tests/data/Mirrorlist/remote-site/metalink.xml @@ -0,0 +1,34 @@ + + + + + 1288734483 + 4834 + + 8fd7745c38277ac8b5618107edb72b7e + de06c2b34f5b13fe6029da59475359675931eb9d + d6f8135c9d5ac370fafd258c89cfb574989cd8557044d9551eefd1aaf2c54c48 + f43d747fa0134e9990297f98771f74a7a449f1b5a53a6936949af5e0b51f3b3834b69af3e25ae4dd7c97415d5570abb5c0a4588ddfae673228f46a83f200b5cd + + + + 1288642986 + 4834 + + bd32127a8b2ae7a370be3dbf876afbc7 + b4b9ea2494aefd82ff08915c28f6548a31625744 + b0d8ae9c43bfd06829092273b409cb0f6e2b581fafd370f11752842c0cd0c2c6 + 78d2eff26e6a12bb1b1bbc78956f548734e921335943afabcfbf4f3ba6d164e8820eb2e685fad78088d2b42b7ec75fe4bde8ad6f5d7e9cf44e70837ce23fb758 + + + + + http://ftp-stud.hs-esslingen.de/pub/fedora/linux/updates/13/x86_64/repodata/repomd.xml + ftp://ftp-stud.hs-esslingen.de/pub/fedora/linux/updates/13/x86_64/repodata/repomd.xml + rsync://ftp-stud.hs-esslingen.de/fedora/linux/updates/13/x86_64/repodata/repomd.xml + http://mirror.eurid.eu/fedora/linux/updates/13/x86_64/repodata/repomd.xml + ftp://mirror.eurid.eu/fedora/linux/updates/13/x86_64/repodata/repomd.xml + + + + diff --git a/tests/data/Mirrorlist/remote-site/mirrors.txt b/tests/data/Mirrorlist/remote-site/mirrors.txt new file mode 100644 index 0000000..20a2168 --- /dev/null +++ b/tests/data/Mirrorlist/remote-site/mirrors.txt @@ -0,0 +1,5 @@ +http://ftp-stud.hs-esslingen.de/pub/fedora/linux/updates/13/x86_64/repodata/repomd.xml +ftp://ftp-stud.hs-esslingen.de/pub/fedora/linux/updates/13/x86_64/repodata/repomd.xml +rsync://ftp-stud.hs-esslingen.de/fedora/linux/updates/13/x86_64/repodata/repomd.xml +http://mirror.eurid.eu/fedora/linux/updates/13/x86_64/repodata/repomd.xml +ftp://mirror.eurid.eu/fedora/linux/updates/13/x86_64/repodata/repomd.xml diff --git a/tests/data/OBS_zypp_svn-11.1/repodata/primary.xml.gz b/tests/data/OBS_zypp_svn-11.1/repodata/primary.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..ce990f8c5f6de059524f5bd358349cc15ccf79af GIT binary patch literal 9633 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 X{^4bBsB&r6@9h5rLOt=?aAyGk?Xbt? literal 0 HcmV?d00001 diff --git a/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml b/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml new file mode 100644 index 0000000..1bde3d3 --- /dev/null +++ b/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml @@ -0,0 +1,21 @@ + + + + + 734543b9cb748334925d6fac1a1f2f3f5b5dffd1 + 1223586019 + 97bd7432a1c6b1b44b9ca1f52b9a18979c72a9ba + + + + 722956718221845366d4572fe5649a268cb93920 + 1223586019 + e9edadbe3063f4ae8c97667f67d31a192eadc427 + + + + f586852ceffd230cd6e7b15a880494a9e2f7a8a5 + 1223586019 + c9e4113751d71ea413fe4564f1f0e94e2cda9bec + + diff --git a/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.asc b/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.asc new file mode 100644 index 0000000..96a9d37 --- /dev/null +++ b/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBI7nDkyW8T9xlZ+8sRAolAAKCgHtH/tQVLIIM1k3SAo8EMMSe+7QCg +ylO1hOqgWrRGrF+JovkE7akc4XI= +=XnSD +-----END PGP SIGNATURE----- diff --git a/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.key b/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.key new file mode 100644 index 0000000..620e3a1 --- /dev/null +++ b/tests/data/OBS_zypp_svn-11.1/repodata/repomd.xml.key @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQGiBEeWW2sRBAC6p0M82A5kapMTPpn9MQ0w++cEHC4cKRGKe4ysJiGEOKcl8wmE +buiiYOZKLvuFoyPDyyB/KPQ56nE/sEwJAsssXpMJ3EeSF5Px2qresY7Ralowozc5 +8WF2Btq90RNqIhfjAEpTmiDpn9g7fIn9YAzwh6md2i7BemKBEfNkVrVYNwCgy5bg +9fSyOa4mr7HldiIAdNsPFLsD/0e8GhiSxD8xV3o7dchf8jMEgAv7gAbP1lGsbZQG +dSsyODycr0PabGY3XVkNBb6NPdEcm63crsKeVltG455NL4WgkULaJDnDNtU1SGui +AlAqEjXXR9dOCgVMs7lfpaF55cerUwGjGGMnZpGbzVClHZubwZrWV9h7O+9ln7Lu +/W3mBACKfr68onKxCxmFEadAYEXtnJ/9Yk58rsD2V05rV+1SYCrybOTM/Hhjt5PZ +WwXyfCwla43ljVGdIO2Rde8o6UIzbM49F04OC97HMzyGyUd2EiXfDtF4j5y+caoq +9mZaXl2hiu4YSjNGEFGBelOS1YwBefnytgFV9nyWU+9E1iqDjLQyenlwcDpzdm4g +T0JTIFByb2plY3QgPHp5cHA6c3ZuQGJ1aWxkLm9wZW5zdXNlLm9yZz6IZgQTEQIA +JgUCR5ZbawIbAwUJBB6wAAYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEMlvE/cZ +WfvLxR0AnRRinTmsd2B7Db6eruYX40smjwnrAJ4iIFZQXD/qMEGsSr0GfCgvhmGe +94hGBBMRAgAGBQJHlltrAAoJEDswEbdrnWUjQqAAn1QYRSp5S0NrCknsvvWbGmhI +jR0SAKCwuY8a+dKLOdrhV+520EhUsYU6+Q== +=7eFk +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/PoolReuseIds/SeqA/SEQA.repo b/tests/data/PoolReuseIds/SeqA/SEQA.repo new file mode 100644 index 0000000..c6f0c50 --- /dev/null +++ b/tests/data/PoolReuseIds/SeqA/SEQA.repo @@ -0,0 +1,28 @@ +=Ver: 3.0 +=Pkg: package 4 1 x86_64 ++Prv: +package = 4-1 +-Prv: +=Vnd: unkown +=Pkg: patch:patch 4 1 x86_64 ++Prv: +patch:patch = 4-1 +-Prv: +=Vnd: unkown +=Pkg: pattern:pattern 4 1 x86_64 ++Prv: +pattern:pattern = 4-1 +-Prv: +=Vnd: unkown +=Pkg: product:product 4 1 x86_64 ++Prv: +product:product = 4-1 +-Prv: +=Vnd: unkown +=Pkg: srcpackage 4 1 src +=Vnd: unkown +=Pkg: application:application 4 1 x86_64 ++Prv: +application:application = 4-1 +-Prv: +=Vnd: unkown diff --git a/tests/data/PoolReuseIds/SeqA/zypp-control.yaml b/tests/data/PoolReuseIds/SeqA/zypp-control.yaml new file mode 100644 index 0000000..ea915c8 --- /dev/null +++ b/tests/data/PoolReuseIds/SeqA/zypp-control.yaml @@ -0,0 +1,35 @@ +version: 1.0 +setup: + channels: + - alias: SEQA + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: SEQA.repo + arch: x86_64 + locales: + [] + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/data/PoolReuseIds/SeqB/SeqB.repo b/tests/data/PoolReuseIds/SeqB/SeqB.repo new file mode 100644 index 0000000..b3df6e3 --- /dev/null +++ b/tests/data/PoolReuseIds/SeqB/SeqB.repo @@ -0,0 +1,28 @@ +=Ver: 3.0 +=Pkg: application:application 4 1 x86_64 ++Prv: +application:application = 4-1 +-Prv: +=Vnd: unkown +=Pkg: package 4 1 x86_64 ++Prv: +package = 4-1 +-Prv: +=Vnd: unkown +=Pkg: patch:patch 4 1 x86_64 ++Prv: +patch:patch = 4-1 +-Prv: +=Vnd: unkown +=Pkg: pattern:pattern 4 1 x86_64 ++Prv: +pattern:pattern = 4-1 +-Prv: +=Vnd: unkown +=Pkg: product:product 4 1 x86_64 ++Prv: +product:product = 4-1 +-Prv: +=Vnd: unkown +=Pkg: srcpackage 4 1 src +=Vnd: unkown diff --git a/tests/data/PoolReuseIds/SeqB/zypp-control.yaml b/tests/data/PoolReuseIds/SeqB/zypp-control.yaml new file mode 100644 index 0000000..ea9d612 --- /dev/null +++ b/tests/data/PoolReuseIds/SeqB/zypp-control.yaml @@ -0,0 +1,35 @@ +version: 1.0 +setup: + channels: + - alias: SeqB + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: SeqB.repo + arch: x86_64 + locales: + [] + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/data/TCNamespaceRecommends/@System.repo b/tests/data/TCNamespaceRecommends/@System.repo new file mode 100644 index 0000000..039aa698 --- /dev/null +++ b/tests/data/TCNamespaceRecommends/@System.repo @@ -0,0 +1,21 @@ +=Ver: 3.0 +=Pkg: aspell 0 0 x86_64 ++Prv: +aspell = 0-0 +-Prv: ++Rec: +aspell-en +recommended-pkg +-Rec: +=Pkg: aspell-en 0 0 x86_64 ++Prv: +locale(aspell:en) +aspell-en = 0-0 +-Prv: ++Sup: +aspell & namespace:language(en) +-Sup: +=Pkg: glibc 0 0 x86_64 ++Prv: +glibc = 0-0 +-Prv: diff --git a/tests/data/TCNamespaceRecommends/update.repo b/tests/data/TCNamespaceRecommends/update.repo new file mode 100644 index 0000000..c37864d --- /dev/null +++ b/tests/data/TCNamespaceRecommends/update.repo @@ -0,0 +1,37 @@ +=Ver: 3.0 +=Pkg: aspell 1 1 x86_64 ++Prv: +aspell = 1-1 +-Prv: ++Rec: +aspell-en +recommended-pkg +-Rec: +=Pkg: aspell-en 1 1 x86_64 ++Prv: +locale(aspell:en) +aspell-en = 1-1 +-Prv: ++Sup: +aspell & namespace:language(en) +-Sup: +=Pkg: aspell-de 1 1 x86_64 ++Prv: +locale(aspell:de) +aspell-de = 1-1 +-Prv: ++Sup: +aspell & namespace:language(de) +-Sup: +=Pkg: aspell-fr 1 1 x86_64 ++Prv: +locale(aspell:fr) +aspell-fr = 1-1 +-Prv: ++Sup: +aspell & namespace:language(fr) +-Sup: +=Pkg: recommended-pkg 1 1 x86_64 ++Prv: +recommended-pkg = 1-1 +-Prv: diff --git a/tests/data/TCNamespaceRecommends/zypp-control.yaml b/tests/data/TCNamespaceRecommends/zypp-control.yaml new file mode 100644 index 0000000..3cdddcc --- /dev/null +++ b/tests/data/TCNamespaceRecommends/zypp-control.yaml @@ -0,0 +1,46 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + - alias: update + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: update.repo + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/data/TCSelectable/@System.repo b/tests/data/TCSelectable/@System.repo new file mode 100644 index 0000000..c3b8608 --- /dev/null +++ b/tests/data/TCSelectable/@System.repo @@ -0,0 +1,27 @@ +=Ver: 3.0 +=Pkg: candidate 1 1 i586 ++Prv: +candidate = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: candidatenoarch 1 1 i586 ++Prv: +candidatenoarch = 1-1 +-Prv: +=Vnd: unknown +=Pkg: installed_only 1 1 i586 ++Prv: +installed_only = 1-1 +-Prv: +=Pkg: installed_only 1 0 i586 ++Prv: +installed_only = 1-0 +-Prv: +=Pkg: installed_and_available 1 1 i586 ++Prv: +installed_and_available = 1-1 +-Prv: +=Pkg: installed_and_available 1 0 i586 ++Prv: +installed_and_available = 1-0 +-Prv: diff --git a/tests/data/TCSelectable/RepoHIGH.repo b/tests/data/TCSelectable/RepoHIGH.repo new file mode 100644 index 0000000..a052888 --- /dev/null +++ b/tests/data/TCSelectable/RepoHIGH.repo @@ -0,0 +1,31 @@ +=Ver: 3.0 +=Pkg: candidate 4 1 x86_64 ++Prv: +candidate = 4-1 +-Prv: +=Vnd: unkown +=Pkg: candidate 4 1 i586 ++Prv: +candidate = 4-1 +-Prv: +=Vnd: unknown +=Pkg: candidatenoarch 5 1 noarch ++Prv: +candidatenoarch = 5-1 +-Prv: +=Vnd: unknown +=Pkg: candidatenoarch 4 1 x86_64 ++Prv: +candidatenoarch = 4-1 +-Prv: +=Vnd: unknown +=Pkg: candidatenoarch 4 1 i586 ++Prv: +candidatenoarch = 4-1 +-Prv: +=Vnd: unknown +=Pkg: candidatenoarch 4 1 noarch ++Prv: +candidatenoarch = 4-1 +-Prv: +=Vnd: unknown diff --git a/tests/data/TCSelectable/RepoLOW.repo b/tests/data/TCSelectable/RepoLOW.repo new file mode 100644 index 0000000..ca88740 --- /dev/null +++ b/tests/data/TCSelectable/RepoLOW.repo @@ -0,0 +1,35 @@ +=Ver: 3.0 +=Pkg: candidate 2 1 x86_64 ++Prv: +candidate = 2-1 +-Prv: +=Vnd: openSUSE +=Pkg: candidate 2 1 i586 ++Prv: +candidate = 2-1 +-Prv: +=Vnd: openSUSE +=Pkg: installed_and_available 1 1 i586 ++Prv: +installed_and_available = 1-1 +-Prv: +=Pkg: installed_and_available 2 1 i586 ++Prv: +installed_and_available = 2-1 +-Prv: +=Pkg: installed_and_available 3 1 i586 ++Prv: +installed_and_available = 3-1 +-Prv: +=Pkg: available_only 1 1 i586 ++Prv: +available_only = 1-1 +-Prv: +=Pkg: available_only 2 1 i586 ++Prv: +available_only = 2-1 +-Prv: +=Pkg: available_only 3 1 i586 ++Prv: +available_only = 3-1 +-Prv: diff --git a/tests/data/TCSelectable/RepoMID.repo b/tests/data/TCSelectable/RepoMID.repo new file mode 100644 index 0000000..3421e51 --- /dev/null +++ b/tests/data/TCSelectable/RepoMID.repo @@ -0,0 +1,31 @@ +=Ver: 3.0 +=Pkg: candidate 0 1 x86_64 ++Prv: +candidate = 0-1 +-Prv: +=Vnd: openSUSE +=Pkg: candidate 0 1 i586 ++Prv: +candidate = 0-1 +-Prv: +=Vnd: openSUSE +=Pkg: candidatenoarch 0 2 noarch ++Prv: +candidatenoarch = 0-2 +-Prv: +=Vnd: openSUSE +=Pkg: candidatenoarch 0 1 x86_64 ++Prv: +candidatenoarch = 0-1 +-Prv: +=Vnd: openSUSE +=Pkg: candidatenoarch 0 1 i586 ++Prv: +candidatenoarch = 0-1 +-Prv: +=Vnd: openSUSE +=Pkg: candidatenoarch 0 1 noarch ++Prv: +candidatenoarch = 0-1 +-Prv: +=Vnd: openSUSE diff --git a/tests/data/TCSelectable/RepoSRC.repo b/tests/data/TCSelectable/RepoSRC.repo new file mode 100644 index 0000000..6ae66c9 --- /dev/null +++ b/tests/data/TCSelectable/RepoSRC.repo @@ -0,0 +1,13 @@ +=Ver: 3.0 +=Pkg: candidate 0 1 src +=Vnd: openSUSE +=Pkg: candidate 0 1 src +=Vnd: openSUSE +=Pkg: candidatenoarch 0 2 src +=Vnd: openSUSE +=Pkg: candidatenoarch 0 1 src +=Vnd: openSUSE +=Pkg: candidatenoarch 0 1 src +=Vnd: openSUSE +=Pkg: candidatenoarch 0 1 src +=Vnd: openSUSE diff --git a/tests/data/TCSelectable/zypp-control.yaml b/tests/data/TCSelectable/zypp-control.yaml new file mode 100644 index 0000000..1dd8ed1 --- /dev/null +++ b/tests/data/TCSelectable/zypp-control.yaml @@ -0,0 +1,70 @@ +version: 1.0 +setup: + channels: + - alias: RepoHIGH + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 10 + file: RepoHIGH.repo + - alias: RepoLOW + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: RepoLOW.repo + - alias: RepoMID + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 50 + file: RepoMID.repo + - alias: RepoSRC + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: RepoSRC.repo + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/data/TCWhatObsoletes/@System.repo b/tests/data/TCWhatObsoletes/@System.repo new file mode 100644 index 0000000..e5b2fc2 --- /dev/null +++ b/tests/data/TCWhatObsoletes/@System.repo @@ -0,0 +1,26 @@ +=Ver: 3.0 +=Pkg: test1 1 1 i586 ++Prv: +test1 = 1-1 +-Prv: ++Obs: +goaway < 2-1 +-Obs: +=Pkg: goaway 1 1 i586 ++Prv: +goaway = 1-1 +-Prv: +=Pkg: goaway 2 1 i586 ++Prv: +goaway = 2-1 +-Prv: +=Pkg: meetoo 1 1 i586 ++Prv: +goaway = 1-1 +meetoo = 1-1 +-Prv: +=Pkg: meetoo 2 1 i586 ++Prv: +goaway = 2-1 +meetoo = 2-1 +-Prv: diff --git a/tests/data/TCWhatObsoletes/zypp-control.yaml b/tests/data/TCWhatObsoletes/zypp-control.yaml new file mode 100644 index 0000000..c3c7e35 --- /dev/null +++ b/tests/data/TCWhatObsoletes/zypp-control.yaml @@ -0,0 +1,36 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: i686 + locales: + - fate: "" + name: en_US + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/data/TCdup/@System.repo b/tests/data/TCdup/@System.repo new file mode 100644 index 0000000..4d0919b --- /dev/null +++ b/tests/data/TCdup/@System.repo @@ -0,0 +1,31 @@ +=Ver: 3.0 +=Pkg: product:Product 1 1 i586 ++Prv: +product:Product = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: release-package 1 1 i586 ++Prv: +product() +product(Product) = 1-1 +release-package = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: glibc 1 1 i586 ++Req: +dropped_required +-Req: ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: dropped_required 1 1 i586 ++Prv: +dropped_required = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: dropped 1 1 i586 ++Prv: +dropped = 1-1 +-Prv: +=Vnd: openSUSE diff --git a/tests/data/TCdup/update.repo b/tests/data/TCdup/update.repo new file mode 100644 index 0000000..62bb3d7 --- /dev/null +++ b/tests/data/TCdup/update.repo @@ -0,0 +1,20 @@ +=Ver: 3.0 +=Pkg: product:Product 2 1 i586 ++Prv: +product:Product = 2-1 +-Prv: +=Vnd: openSUSE +=Pkg: release-package 2 1 i586 ++Prv: +product() +product(Product) = 2-1 +weakremover(dropped_required) +weakremover(dropped) +release-package = 2-1 +-Prv: +=Vnd: openSUSE +=Pkg: package 2 1 i586 ++Prv: +package = 2-1 +-Prv: +=Vnd: openSUSE diff --git a/tests/data/TCdup/zypp-control.yaml b/tests/data/TCdup/zypp-control.yaml new file mode 100644 index 0000000..c372e76 --- /dev/null +++ b/tests/data/TCdup/zypp-control.yaml @@ -0,0 +1,46 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + - alias: update + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 10 + file: update.repo + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/data/dummywebroot/Readme b/tests/data/dummywebroot/Readme new file mode 100644 index 0000000..19b536f --- /dev/null +++ b/tests/data/dummywebroot/Readme @@ -0,0 +1,3 @@ +This is just a dummy directory for all tests +that start a WebServer but do not really need a root +directory to provide any content diff --git a/tests/data/lighttpdconf/conf.d/access_log.conf b/tests/data/lighttpdconf/conf.d/access_log.conf new file mode 100644 index 0000000..879945c --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/access_log.conf @@ -0,0 +1,27 @@ +####################################################################### +## +## Corresponding documentation: +## +## https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModAccesslog +## +server.modules += ( "mod_accesslog" ) + +## +## Default access log. +## +accesslog.filename = log_root + "/access.log" + +## +## The default format produces CLF compatible output. +## For available parameters see access.txt +## +#accesslog.format = "%h %l %u %t \"%r\" %b %>s \"%{User-Agent}i\" \"%{Referer}i\"" + +## +## If you want to log to syslog you have to unset the +## accesslog.use-syslog setting and uncomment the next line. +## +#accesslog.use-syslog = "enable" + +# +####################################################################### diff --git a/tests/data/lighttpdconf/conf.d/auth.conf b/tests/data/lighttpdconf/conf.d/auth.conf new file mode 100644 index 0000000..5fa9b74 --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/auth.conf @@ -0,0 +1,27 @@ +####################################################################### +## +## Authentication Module +## ----------------------- +## +## See https://redmine.lighttpd.net/projects/lighttpd/wiki/docs_modauth +## for more info. +## + +#auth.backend = "plain" +#auth.backend.plain.userfile = "/etc/lighttpd/lighttpd.user" +#auth.backend.plain.groupfile = "/etc/lighttpd/lighttpd.group" + +#auth.backend.ldap.hostname = "localhost" +#auth.backend.ldap.base-dn = "dc=my-domain,dc=com" +#auth.backend.ldap.filter = "(uid=$)" + +#auth.require = ( "/server-status" => +# ( +# "method" => "digest", +# "realm" => "Server Status", +# "require" => "valid-user" +# ), +# ) + +## +####################################################################### diff --git a/tests/data/lighttpdconf/conf.d/compress.conf b/tests/data/lighttpdconf/conf.d/compress.conf new file mode 100644 index 0000000..e0667b6 --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/compress.conf @@ -0,0 +1,31 @@ +####################################################################### +## +## Output Compression +## -------------------- +## +## See https://redmine.lighttpd.net/projects/lighttpd/wiki/docs_modcompress +## +server.modules += ( "mod_compress" ) + +## +## where should the compressed files be cached? +## see the base config for the declaration of the variable. +## +## This directory should be changed per vhost otherwise you can +## run into trouble with overlapping filenames +## +compress.cache-dir = cache_dir + "/compress" + +## +## FileTypes to compress. +## +compress.filetype = ("text/plain", "text/html") + +## +## Maximum filesize that will be compressed. +## Default is 0, which means unlimited file size. +## +#compress.max-filesize = 0 + +## +####################################################################### diff --git a/tests/data/lighttpdconf/conf.d/debug.conf b/tests/data/lighttpdconf/conf.d/debug.conf new file mode 100644 index 0000000..cd62f9b --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/debug.conf @@ -0,0 +1,49 @@ +####################################################################### +## +## Debug options +## --------------- +## +## See https://redmine.lighttpd.net/projects/lighttpd/wiki/DebugVariables +## +## Enable those options for debugging the behavior +## +## The settings can be set per location/vhost. +## + +## +## log-request-handling allows you to track the request +## handing inside lighttpd. +## +debug.log-request-handling = "enable" + +## +## log all request headers. +## +debug.log-request-header = "enable" + +## +## similar to log-request-header. +## but only logs if we encountered an error. +## (return codes 400 and 5xx) +## +debug.log-request-header-on-error = "enable" + +## +## log the header we send out to the client. +## +debug.log-response-header = "enable" + +## +## log if a file wasnt found in the error log. +## +debug.log-file-not-found = "enable" + +## +## debug conditionals handling +## +debug.log-condition-handling = "enable" + +# +####################################################################### + + diff --git a/tests/data/lighttpdconf/conf.d/dirlisting.conf b/tests/data/lighttpdconf/conf.d/dirlisting.conf new file mode 100644 index 0000000..e2a0d15 --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/dirlisting.conf @@ -0,0 +1,55 @@ +####################################################################### +## +## Dirlisting Module +## ------------------- +## +## See https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModDirlisting +## + +## +## Enabled Directory listing +## +dir-listing.activate = "disable" + +## +## Hide dot files from the listing? +## By default they are listed. +## +dir-listing.hide-dotfiles = "disable" + +## +## list of regular expressions. Files that match any of the specified +## regular expressions will be excluded from directory listings. +## +dir-listing.exclude = ( "~$" ) + +## +## set a encoding for the generated directory listing +## +## If you file-system is not using ASCII you have to set the encoding of +## the filenames as they are put into the HTML listing AS IS (with XML +## encoding) +## +dir-listing.encoding = "UTF-8" + +## +## Specify the url to an optional CSS file. +## +#dir-listing.external-css = "/dirindex.css" + +## +## Include HEADER.txt files above the directory listing. +## You can disable showing the HEADER.txt in the listing. +## +dir-listing.hide-header-file = "disable" +dir-listing.show-header = "disable" + +## +## Include README.txt files above the directory listing. +## You can disable showing the README.txt in the listing. +## +dir-listing.hide-readme-file = "disable" +dir-listing.show-readme = "disable" + +## +####################################################################### diff --git a/tests/data/lighttpdconf/conf.d/expire.conf b/tests/data/lighttpdconf/conf.d/expire.conf new file mode 100644 index 0000000..a283781 --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/expire.conf @@ -0,0 +1,22 @@ +####################################################################### +## +## Expire Module +## --------------- +## +## See https://redmine.lighttpd.net/projects/lighttpd/wiki/docs_modexpire +## +server.modules += ( "mod_expire" ) + +## +## assignes a expiration to all files below the specified path. The +## specification of the time is made up of: +## +## +## +#expire.url = ( +# "/buggy/" => "access 2 hours", +# "/images/" => "access plus 1 seconds 2 minutes" +#) + +## +####################################################################### diff --git a/tests/data/lighttpdconf/conf.d/fastcgi.conf b/tests/data/lighttpdconf/conf.d/fastcgi.conf new file mode 100644 index 0000000..192f07b --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/fastcgi.conf @@ -0,0 +1,20 @@ +####################################################################### +## +## FastCGI Module +## --------------- +## +## See https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_ModFastCGI +## +server.modules += ( "mod_fastcgi" ) + +fastcgi.server = ( + "/handler/" => + (( "socket" => env.ZYPP_TEST_SOCKPATH, + "check-local" => "disable", + "docroot" => "/" # remote server may use + # its own docroot + )) +) + +## +####################################################################### diff --git a/tests/data/lighttpdconf/conf.d/maybessl.sh b/tests/data/lighttpdconf/conf.d/maybessl.sh new file mode 100755 index 0000000..e130b03 --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/maybessl.sh @@ -0,0 +1,7 @@ +#!/usr/bin/sh + +if [ "${ZYPP_TEST_USE_SSL}" == "1" ]; then + echo 'server.modules += ( "mod_openssl" )' + echo 'ssl.engine = "enable"' + echo 'ssl.pemfile = ssl_dir + "/server.pem"' +fi diff --git a/tests/data/lighttpdconf/conf.d/mime.conf b/tests/data/lighttpdconf/conf.d/mime.conf new file mode 100644 index 0000000..063bdd6 --- /dev/null +++ b/tests/data/lighttpdconf/conf.d/mime.conf @@ -0,0 +1,594 @@ +# created by create-mime.conf.pl + +####################################################################### +## +## MimeType handling +## ------------------- +## +## https://redmine.lighttpd.net/projects/lighttpd/wiki/Mimetype_assignDetails + +## +## mimetype.xattr-name +## Set the extended file attribute name used to obtain mime type +## (must also set mimetype.use-xattr = "enable") +## +## Default value is "Content-Type" +## +## freedesktop.org Shared MIME-info Database specification suggests +## user-defined value ("user.mime_type") as name for extended file attribute +#mimetype.xattr-name = "user.mime_type" + +## +## Use extended attribute named in mimetype.xattr-name (default "Content-Type") +## to obtain mime type if possible +## +## Disabled by default +## +#mimetype.use-xattr = "enable" + +## +## mimetype ("Content-Type" HTTP header) mapping for static file handling +## +## The first matching suffix is used. If no mapping is found +## 'application/octet-stream' is used, and caching (etag/last-modified handling) +## is disabled to prevent clients from caching "unknown" mime types. +## +## Therefore the last mapping is: +## "" => "application/octet-stream" +## This matches all extensions and acts as default mime type, and enables +## caching for those. +mimetype.assign = ( + ".pcf.Z" => "application/x-font-pcf", + ".tar.bz2" => "application/x-gtar-compressed", + ".tar.gz" => "application/x-gtar-compressed", + ".ez" => "application/andrew-inset", + ".anx" => "application/annodex", + ".atom" => "application/atom+xml", + ".atomcat" => "application/atomcat+xml", + ".atomsrv" => "application/atomserv+xml", + ".lin" => "application/bbolin", + ".cu" => "application/cu-seeme", + ".davmount" => "application/davmount+xml", + ".dcm" => "application/dicom", + ".tsp" => "application/dsptype", + ".es" => "application/ecmascript", + ".otf" => "application/font-sfnt", + ".ttf" => "application/font-sfnt", + ".pfr" => "application/font-tdpfr", + ".woff" => "application/font-woff", + ".spl" => "application/futuresplash", + ".gz" => "application/gzip", + ".hta" => "application/hta", + ".jar" => "application/java-archive", + ".ser" => "application/java-serialized-object", + ".class" => "application/java-vm", + ".js" => "application/javascript", + ".json" => "application/json", + ".m3g" => "application/m3g", + ".hqx" => "application/mac-binhex40", + ".cpt" => "application/mac-compactpro", + ".nb" => "application/mathematica", + ".nbp" => "application/mathematica", + ".mbox" => "application/mbox", + ".mdb" => "application/msaccess", + ".doc" => "application/msword", + ".dot" => "application/msword", + ".mxf" => "application/mxf", + ".asn" => "application/octet-stream", + ".bin" => "application/octet-stream", + ".deploy" => "application/octet-stream", + ".ent" => "application/octet-stream", + ".msp" => "application/octet-stream", + ".msu" => "application/octet-stream", + ".oda" => "application/oda", + ".opf" => "application/oebps-package+xml", + ".ogx" => "application/ogg", + ".one" => "application/onenote", + ".onepkg" => "application/onenote", + ".onetmp" => "application/onenote", + ".onetoc2" => "application/onenote", + ".pdf" => "application/pdf", + ".pgp" => "application/pgp-encrypted", + ".key" => "application/pgp-keys", + ".sig" => "application/pgp-signature", + ".prf" => "application/pics-rules", + ".ai" => "application/postscript", + ".eps" => "application/postscript", + ".eps2" => "application/postscript", + ".eps3" => "application/postscript", + ".epsf" => "application/postscript", + ".epsi" => "application/postscript", + ".ps" => "application/postscript", + ".rar" => "application/rar", + ".rdf" => "application/rdf+xml", + ".rtf" => "application/rtf", + ".stl" => "application/sla", + ".smi" => "application/smil+xml", + ".smil" => "application/smil+xml", + ".xht" => "application/xhtml+xml", + ".xhtml" => "application/xhtml+xml", + ".xml" => "application/xml", + ".xsd" => "application/xml", + ".dtd" => "application/xml-dtd", + ".xsl" => "application/xslt+xml", + ".xslt" => "application/xslt+xml", + ".xspf" => "application/xspf+xml", + ".zip" => "application/zip", + ".apk" => "application/vnd.android.package-archive", + ".cdy" => "application/vnd.cinderella", + ".ddeb" => "application/vnd.debian.binary-package", + ".deb" => "application/vnd.debian.binary-package", + ".udeb" => "application/vnd.debian.binary-package", + ".sfd" => "application/vnd.font-fontforge-sfd", + ".kml" => "application/vnd.google-earth.kml+xml", + ".kmz" => "application/vnd.google-earth.kmz", + ".xul" => "application/vnd.mozilla.xul+xml", + ".xlb" => "application/vnd.ms-excel", + ".xls" => "application/vnd.ms-excel", + ".xlt" => "application/vnd.ms-excel", + ".xlam" => "application/vnd.ms-excel.addin.macroEnabled.12", + ".xlsb" => "application/vnd.ms-excel.sheet.binary.macroEnabled.12", + ".xlsm" => "application/vnd.ms-excel.sheet.macroEnabled.12", + ".xltm" => "application/vnd.ms-excel.template.macroEnabled.12", + ".eot" => "application/vnd.ms-fontobject", + ".thmx" => "application/vnd.ms-officetheme", + ".cat" => "application/vnd.ms-pki.seccat", + ".pps" => "application/vnd.ms-powerpoint", + ".ppt" => "application/vnd.ms-powerpoint", + ".ppam" => "application/vnd.ms-powerpoint.addin.macroEnabled.12", + ".pptm" => "application/vnd.ms-powerpoint.presentation.macroEnabled.12", + ".sldm" => "application/vnd.ms-powerpoint.slide.macroEnabled.12", + ".ppsm" => "application/vnd.ms-powerpoint.slideshow.macroEnabled.12", + ".potm" => "application/vnd.ms-powerpoint.template.macroEnabled.12", + ".docm" => "application/vnd.ms-word.document.macroEnabled.12", + ".dotm" => "application/vnd.ms-word.template.macroEnabled.12", + ".odc" => "application/vnd.oasis.opendocument.chart", + ".odb" => "application/vnd.oasis.opendocument.database", + ".odf" => "application/vnd.oasis.opendocument.formula", + ".odg" => "application/vnd.oasis.opendocument.graphics", + ".otg" => "application/vnd.oasis.opendocument.graphics-template", + ".odi" => "application/vnd.oasis.opendocument.image", + ".odp" => "application/vnd.oasis.opendocument.presentation", + ".otp" => "application/vnd.oasis.opendocument.presentation-template", + ".ods" => "application/vnd.oasis.opendocument.spreadsheet", + ".ots" => "application/vnd.oasis.opendocument.spreadsheet-template", + ".odt" => "application/vnd.oasis.opendocument.text", + ".odm" => "application/vnd.oasis.opendocument.text-master", + ".ott" => "application/vnd.oasis.opendocument.text-template", + ".oth" => "application/vnd.oasis.opendocument.text-web", + ".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation", + ".sldx" => "application/vnd.openxmlformats-officedocument.presentationml.slide", + ".ppsx" => "application/vnd.openxmlformats-officedocument.presentationml.slideshow", + ".potx" => "application/vnd.openxmlformats-officedocument.presentationml.template", + ".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + ".xltx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.template", + ".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + ".dotx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.template", + ".cod" => "application/vnd.rim.cod", + ".mmf" => "application/vnd.smaf", + ".sdc" => "application/vnd.stardivision.calc", + ".sds" => "application/vnd.stardivision.chart", + ".sda" => "application/vnd.stardivision.draw", + ".sdd" => "application/vnd.stardivision.impress", + ".sdf" => "application/vnd.stardivision.math", + ".sdw" => "application/vnd.stardivision.writer", + ".sgl" => "application/vnd.stardivision.writer-global", + ".sxc" => "application/vnd.sun.xml.calc", + ".stc" => "application/vnd.sun.xml.calc.template", + ".sxd" => "application/vnd.sun.xml.draw", + ".std" => "application/vnd.sun.xml.draw.template", + ".sxi" => "application/vnd.sun.xml.impress", + ".sti" => "application/vnd.sun.xml.impress.template", + ".sxm" => "application/vnd.sun.xml.math", + ".sxw" => "application/vnd.sun.xml.writer", + ".sxg" => "application/vnd.sun.xml.writer.global", + ".stw" => "application/vnd.sun.xml.writer.template", + ".sis" => "application/vnd.symbian.install", + ".cap" => "application/vnd.tcpdump.pcap", + ".pcap" => "application/vnd.tcpdump.pcap", + ".vsd" => "application/vnd.visio", + ".vss" => "application/vnd.visio", + ".vst" => "application/vnd.visio", + ".vsw" => "application/vnd.visio", + ".wbxml" => "application/vnd.wap.wbxml", + ".wmlc" => "application/vnd.wap.wmlc", + ".wmlsc" => "application/vnd.wap.wmlscriptc", + ".wpd" => "application/vnd.wordperfect", + ".wp5" => "application/vnd.wordperfect5.1", + ".wk" => "application/x-123", + ".7z" => "application/x-7z-compressed", + ".abw" => "application/x-abiword", + ".dmg" => "application/x-apple-diskimage", + ".bcpio" => "application/x-bcpio", + ".torrent" => "application/x-bittorrent", + ".bz2" => "application/x-bzip", + ".cab" => "application/x-cab", + ".cbr" => "application/x-cbr", + ".cbz" => "application/x-cbz", + ".cda" => "application/x-cdf", + ".cdf" => "application/x-cdf", + ".vcd" => "application/x-cdlink", + ".pgn" => "application/x-chess-pgn", + ".mph" => "application/x-comsol", + ".cpio" => "application/x-cpio", + ".dcr" => "application/x-director", + ".dir" => "application/x-director", + ".dxr" => "application/x-director", + ".dms" => "application/x-dms", + ".wad" => "application/x-doom", + ".dvi" => "application/x-dvi", + ".gsf" => "application/x-font", + ".pfa" => "application/x-font", + ".pfb" => "application/x-font", + ".pcf" => "application/x-font-pcf", + ".mm" => "application/x-freemind", + ".gan" => "application/x-ganttproject", + ".gnumeric" => "application/x-gnumeric", + ".sgf" => "application/x-go-sgf", + ".gcf" => "application/x-graphing-calculator", + ".gtar" => "application/x-gtar", + ".taz" => "application/x-gtar-compressed", + ".tbz" => "application/x-gtar-compressed", + ".tgz" => "application/x-gtar-compressed", + ".hdf" => "application/x-hdf", + ".hwp" => "application/x-hwp", + ".ica" => "application/x-ica", + ".info" => "application/x-info", + ".ins" => "application/x-internet-signup", + ".isp" => "application/x-internet-signup", + ".iii" => "application/x-iphone", + ".iso" => "application/x-iso9660-image", + ".jam" => "application/x-jam", + ".jnlp" => "application/x-java-jnlp-file", + ".jmz" => "application/x-jmol", + ".chrt" => "application/x-kchart", + ".kil" => "application/x-killustrator", + ".skd" => "application/x-koan", + ".skm" => "application/x-koan", + ".skp" => "application/x-koan", + ".skt" => "application/x-koan", + ".kpr" => "application/x-kpresenter", + ".kpt" => "application/x-kpresenter", + ".ksp" => "application/x-kspread", + ".kwd" => "application/x-kword", + ".kwt" => "application/x-kword", + ".latex" => "application/x-latex", + ".lha" => "application/x-lha", + ".lyx" => "application/x-lyx", + ".lzh" => "application/x-lzh", + ".lzx" => "application/x-lzx", + ".book" => "application/x-maker", + ".fb" => "application/x-maker", + ".fbdoc" => "application/x-maker", + ".fm" => "application/x-maker", + ".frame" => "application/x-maker", + ".frm" => "application/x-maker", + ".maker" => "application/x-maker", + ".mif" => "application/x-mif", + ".m3u8" => "application/x-mpegURL", + ".application" => "application/x-ms-application", + ".manifest" => "application/x-ms-manifest", + ".wmd" => "application/x-ms-wmd", + ".wmz" => "application/x-ms-wmz", + ".bat" => "application/x-msdos-program", + ".com" => "application/x-msdos-program", + ".dll" => "application/x-msdos-program", + ".exe" => "application/x-msdos-program", + ".msi" => "application/x-msi", + ".nc" => "application/x-netcdf", + ".pac" => "application/x-ns-proxy-autoconfig", + ".nwc" => "application/x-nwc", + ".o" => "application/x-object", + ".oza" => "application/x-oz-application", + ".p7r" => "application/x-pkcs7-certreqresp", + ".crl" => "application/x-pkcs7-crl", + ".pyc" => "application/x-python-code", + ".pyo" => "application/x-python-code", + ".qgs" => "application/x-qgis", + ".shp" => "application/x-qgis", + ".shx" => "application/x-qgis", + ".qtl" => "application/x-quicktimeplayer", + ".rdp" => "application/x-rdp", + ".rpm" => "application/x-redhat-package-manager", + ".rss" => "application/x-rss+xml", + ".rb" => "application/x-ruby", + ".sce" => "application/x-scilab", + ".sci" => "application/x-scilab", + ".xcos" => "application/x-scilab-xcos", + ".shar" => "application/x-shar", + ".swf" => "application/x-shockwave-flash", + ".swfl" => "application/x-shockwave-flash", + ".scr" => "application/x-silverlight", + ".sql" => "application/x-sql", + ".sit" => "application/x-stuffit", + ".sitx" => "application/x-stuffit", + ".sv4cpio" => "application/x-sv4cpio", + ".sv4crc" => "application/x-sv4crc", + ".tar" => "application/x-tar", + ".gf" => "application/x-tex-gf", + ".pk" => "application/x-tex-pk", + ".texi" => "application/x-texinfo", + ".texinfo" => "application/x-texinfo", + ".roff" => "application/x-troff", + ".t" => "application/x-troff", + ".tr" => "application/x-troff", + ".man" => "application/x-troff-man", + ".me" => "application/x-troff-me", + ".ms" => "application/x-troff-ms", + ".ustar" => "application/x-ustar", + ".src" => "application/x-wais-source", + ".wz" => "application/x-wingz", + ".crt" => "application/x-x509-ca-cert", + ".xcf" => "application/x-xcf", + ".fig" => "application/x-xfig", + ".xpi" => "application/x-xpinstall", + ".xz" => "application/x-xz", + ".amr" => "audio/amr", + ".awb" => "audio/amr-wb", + ".axa" => "audio/annodex", + ".au" => "audio/basic", + ".snd" => "audio/basic", + ".csd" => "audio/csound", + ".orc" => "audio/csound", + ".sco" => "audio/csound", + ".flac" => "audio/flac", + ".kar" => "audio/midi", + ".mid" => "audio/midi", + ".midi" => "audio/midi", + ".m4a" => "audio/mpeg", + ".mp2" => "audio/mpeg", + ".mp3" => "audio/mpeg", + ".mpega" => "audio/mpeg", + ".mpga" => "audio/mpeg", + ".m3u" => "audio/mpegurl", + ".oga" => "audio/ogg", + ".ogg" => "audio/ogg", + ".opus" => "audio/ogg", + ".spx" => "audio/ogg", + ".sid" => "audio/prs.sid", + ".aif" => "audio/x-aiff", + ".aifc" => "audio/x-aiff", + ".aiff" => "audio/x-aiff", + ".gsm" => "audio/x-gsm", + ".wax" => "audio/x-ms-wax", + ".wma" => "audio/x-ms-wma", + ".ra" => "audio/x-realaudio", + ".ram" => "audio/x-realaudio", + ".rm" => "audio/x-realaudio", + ".pls" => "audio/x-scpls", + ".sd2" => "audio/x-sd2", + ".wav" => "audio/x-wav", + ".alc" => "chemical/x-alchemy", + ".cac" => "chemical/x-cache", + ".cache" => "chemical/x-cache", + ".csf" => "chemical/x-cache-csf", + ".cascii" => "chemical/x-cactvs-binary", + ".cbin" => "chemical/x-cactvs-binary", + ".ctab" => "chemical/x-cactvs-binary", + ".cdx" => "chemical/x-cdx", + ".cer" => "chemical/x-cerius", + ".c3d" => "chemical/x-chem3d", + ".chm" => "chemical/x-chemdraw", + ".cif" => "chemical/x-cif", + ".cmdf" => "chemical/x-cmdf", + ".cml" => "chemical/x-cml", + ".cpa" => "chemical/x-compass", + ".bsd" => "chemical/x-crossfire", + ".csm" => "chemical/x-csml", + ".csml" => "chemical/x-csml", + ".ctx" => "chemical/x-ctx", + ".cef" => "chemical/x-cxf", + ".cxf" => "chemical/x-cxf", + ".emb" => "chemical/x-embl-dl-nucleotide", + ".embl" => "chemical/x-embl-dl-nucleotide", + ".spc" => "chemical/x-galactic-spc", + ".gam" => "chemical/x-gamess-input", + ".gamin" => "chemical/x-gamess-input", + ".inp" => "chemical/x-gamess-input", + ".fch" => "chemical/x-gaussian-checkpoint", + ".fchk" => "chemical/x-gaussian-checkpoint", + ".cub" => "chemical/x-gaussian-cube", + ".gau" => "chemical/x-gaussian-input", + ".gjc" => "chemical/x-gaussian-input", + ".gjf" => "chemical/x-gaussian-input", + ".gal" => "chemical/x-gaussian-log", + ".gcg" => "chemical/x-gcg8-sequence", + ".gen" => "chemical/x-genbank", + ".hin" => "chemical/x-hin", + ".ist" => "chemical/x-isostar", + ".istr" => "chemical/x-isostar", + ".dx" => "chemical/x-jcamp-dx", + ".jdx" => "chemical/x-jcamp-dx", + ".kin" => "chemical/x-kinemage", + ".mcm" => "chemical/x-macmolecule", + ".mmd" => "chemical/x-macromodel-input", + ".mmod" => "chemical/x-macromodel-input", + ".mol" => "chemical/x-mdl-molfile", + ".rd" => "chemical/x-mdl-rdfile", + ".rxn" => "chemical/x-mdl-rxnfile", + ".sd" => "chemical/x-mdl-sdfile", + ".tgf" => "chemical/x-mdl-tgf", + ".mcif" => "chemical/x-mmcif", + ".mol2" => "chemical/x-mol2", + ".b" => "chemical/x-molconn-Z", + ".gpt" => "chemical/x-mopac-graph", + ".mop" => "chemical/x-mopac-input", + ".mopcrt" => "chemical/x-mopac-input", + ".mpc" => "chemical/x-mopac-input", + ".zmt" => "chemical/x-mopac-input", + ".moo" => "chemical/x-mopac-out", + ".mvb" => "chemical/x-mopac-vib", + ".prt" => "chemical/x-ncbi-asn1-ascii", + ".aso" => "chemical/x-ncbi-asn1-binary", + ".val" => "chemical/x-ncbi-asn1-binary", + ".pdb" => "chemical/x-pdb", + ".ros" => "chemical/x-rosdal", + ".sw" => "chemical/x-swissprot", + ".vms" => "chemical/x-vamas-iso14976", + ".vmd" => "chemical/x-vmd", + ".xtel" => "chemical/x-xtel", + ".xyz" => "chemical/x-xyz", + ".gif" => "image/gif", + ".ief" => "image/ief", + ".jp2" => "image/jp2", + ".jpg2" => "image/jp2", + ".jpe" => "image/jpeg", + ".jpeg" => "image/jpeg", + ".jpg" => "image/jpeg", + ".jpm" => "image/jpm", + ".jpf" => "image/jpx", + ".jpx" => "image/jpx", + ".pcx" => "image/pcx", + ".png" => "image/png", + ".svg" => "image/svg+xml", + ".svgz" => "image/svg+xml", + ".tif" => "image/tiff", + ".tiff" => "image/tiff", + ".djv" => "image/vnd.djvu", + ".djvu" => "image/vnd.djvu", + ".ico" => "image/vnd.microsoft.icon", + ".wbmp" => "image/vnd.wap.wbmp", + ".cr2" => "image/x-canon-cr2", + ".crw" => "image/x-canon-crw", + ".ras" => "image/x-cmu-raster", + ".cdr" => "image/x-coreldraw", + ".pat" => "image/x-coreldrawpattern", + ".cdt" => "image/x-coreldrawtemplate", + ".erf" => "image/x-epson-erf", + ".art" => "image/x-jg", + ".jng" => "image/x-jng", + ".bmp" => "image/x-ms-bmp", + ".nef" => "image/x-nikon-nef", + ".orf" => "image/x-olympus-orf", + ".psd" => "image/x-photoshop", + ".pnm" => "image/x-portable-anymap", + ".pbm" => "image/x-portable-bitmap", + ".pgm" => "image/x-portable-graymap", + ".ppm" => "image/x-portable-pixmap", + ".rgb" => "image/x-rgb", + ".xbm" => "image/x-xbitmap", + ".xpm" => "image/x-xpixmap", + ".xwd" => "image/x-xwindowdump", + ".eml" => "message/rfc822", + ".iges" => "model/iges", + ".igs" => "model/iges", + ".mesh" => "model/mesh", + ".msh" => "model/mesh", + ".silo" => "model/mesh", + ".vrml" => "model/vrml", + ".wrl" => "model/vrml", + ".x3db" => "model/x3d+binary", + ".x3dv" => "model/x3d+vrml", + ".x3d" => "model/x3d+xml", + ".appcache" => "text/cache-manifest", + ".ics" => "text/calendar", + ".icz" => "text/calendar", + ".css" => "text/css; charset=utf-8", + ".csv" => "text/csv; charset=utf-8", + ".323" => "text/h323", + ".htm" => "text/html", + ".html" => "text/html", + ".shtml" => "text/html", + ".uls" => "text/iuls", + ".markdown" => "text/markdown; charset=utf-8", + ".md" => "text/markdown; charset=utf-8", + ".mml" => "text/mathml", + ".asc" => "text/plain; charset=utf-8", + ".brf" => "text/plain; charset=utf-8", + ".conf" => "text/plain; charset=utf-8", + ".log" => "text/plain; charset=utf-8", + ".pot" => "text/plain; charset=utf-8", + ".spec" => "text/plain; charset=utf-8", + ".srt" => "text/plain; charset=utf-8", + ".text" => "text/plain; charset=utf-8", + ".txt" => "text/plain; charset=utf-8", + ".rtx" => "text/richtext", + ".sct" => "text/scriptlet", + ".wsc" => "text/scriptlet", + ".tsv" => "text/tab-separated-values", + ".tm" => "text/texmacs", + ".ttl" => "text/turtle", + ".vcard" => "text/vcard", + ".vcf" => "text/vcard", + ".jad" => "text/vnd.sun.j2me.app-descriptor", + ".wml" => "text/vnd.wap.wml", + ".wmls" => "text/vnd.wap.wmlscript", + ".bib" => "text/x-bibtex; charset=utf-8", + ".boo" => "text/x-boo; charset=utf-8", + ".h++" => "text/x-c++hdr; charset=utf-8", + ".hh" => "text/x-c++hdr; charset=utf-8", + ".hpp" => "text/x-c++hdr; charset=utf-8", + ".hxx" => "text/x-c++hdr; charset=utf-8", + ".c++" => "text/x-c++src; charset=utf-8", + ".cc" => "text/x-c++src; charset=utf-8", + ".cpp" => "text/x-c++src; charset=utf-8", + ".cxx" => "text/x-c++src; charset=utf-8", + ".h" => "text/x-chdr; charset=utf-8", + ".htc" => "text/x-component", + ".csh" => "text/x-csh; charset=utf-8", + ".c" => "text/x-csrc; charset=utf-8", + ".diff" => "text/x-diff; charset=utf-8", + ".patch" => "text/x-diff; charset=utf-8", + ".d" => "text/x-dsrc; charset=utf-8", + ".hs" => "text/x-haskell; charset=utf-8", + ".java" => "text/x-java; charset=utf-8", + ".ly" => "text/x-lilypond; charset=utf-8", + ".lhs" => "text/x-literate-haskell; charset=utf-8", + ".moc" => "text/x-moc; charset=utf-8", + ".p" => "text/x-pascal; charset=utf-8", + ".pas" => "text/x-pascal; charset=utf-8", + ".gcd" => "text/x-pcs-gcd", + ".pl" => "text/x-perl; charset=utf-8", + ".pm" => "text/x-perl; charset=utf-8", + ".py" => "text/x-python; charset=utf-8", + ".scala" => "text/x-scala; charset=utf-8", + ".etx" => "text/x-setext", + ".sfv" => "text/x-sfv", + ".sh" => "text/x-sh; charset=utf-8", + ".tcl" => "text/x-tcl; charset=utf-8", + ".tk" => "text/x-tcl; charset=utf-8", + ".cls" => "text/x-tex; charset=utf-8", + ".ltx" => "text/x-tex; charset=utf-8", + ".sty" => "text/x-tex; charset=utf-8", + ".tex" => "text/x-tex; charset=utf-8", + ".vcs" => "text/x-vcalendar", + ".3gp" => "video/3gpp", + ".ts" => "video/MP2T", + ".axv" => "video/annodex", + ".dl" => "video/dl", + ".dif" => "video/dv", + ".dv" => "video/dv", + ".fli" => "video/fli", + ".gl" => "video/gl", + ".mp4" => "video/mp4", + ".mpe" => "video/mpeg", + ".mpeg" => "video/mpeg", + ".mpg" => "video/mpeg", + ".ogv" => "video/ogg", + ".mov" => "video/quicktime", + ".qt" => "video/quicktime", + ".webm" => "video/webm", + ".mxu" => "video/vnd.mpegurl", + ".flv" => "video/x-flv", + ".lsf" => "video/x-la-asf", + ".lsx" => "video/x-la-asf", + ".mkv" => "video/x-matroska", + ".mpv" => "video/x-matroska", + ".mng" => "video/x-mng", + ".asf" => "video/x-ms-asf", + ".asx" => "video/x-ms-asf", + ".wm" => "video/x-ms-wm", + ".wmv" => "video/x-ms-wmv", + ".wmx" => "video/x-ms-wmx", + ".wvx" => "video/x-ms-wvx", + ".avi" => "video/x-msvideo", + ".movie" => "video/x-sgi-movie", + ".ice" => "x-conference/x-cooltalk", + ".sisx" => "x-epoc/x-sisx-app", + ".vrm" => "x-world/x-vrml", + "README" => "text/plain; charset=utf-8", + "Makefile" => "text/x-makefile; charset=utf-8", + + # enable caching for unknown mime types: + "" => "application/octet-stream" +) diff --git a/tests/data/lighttpdconf/lighttpd.conf b/tests/data/lighttpdconf/lighttpd.conf new file mode 100644 index 0000000..632a1dc --- /dev/null +++ b/tests/data/lighttpdconf/lighttpd.conf @@ -0,0 +1,448 @@ +var.root_path = env.ZYPP_TEST_SRVROOT +var.log_root = root_path + "/log" +var.state_dir = root_path + "/state" +var.home_dir = root_path + "/home" +var.conf_dir = env.ZYPP_TEST_SRVCONF +var.ssl_dir = env.ZYPP_SSL_CONFDIR + +## +## Cache for mod_compress +## +## used in: +## conf.d/compress.conf +## +var.cache_dir = root_path + "/cache" + +## +####################################################################### + +####################################################################### +## +## Load the modules. +server.modules = ( + "mod_access", + # "mod_alias", + # "mod_auth", + # "mod_authn_file", + # "mod_evasive", + # "mod_redirect", + # "mod_rewrite", + # "mod_setenv", + # "mod_usertrack", +) + +include "conf.d/fastcgi.conf" + +## +####################################################################### + +####################################################################### +## +## Basic Configuration +## --------------------- +## +server.port = env.ZYPP_TEST_PORT + +## +## Use IPv6? +## +server.use-ipv6 = "enable" + +## +## bind to a specific IP +## +server.bind = "127.0.0.1" + +## +## Run as a different username/groupname. +## This requires root permissions during startup. +## +#server.username = "lighttpd" +#server.groupname = "lighttpd" + +## +## enable core files. +## +#server.core-files = "disable" + +## +## Document root +## +server.document-root = env.ZYPP_TEST_DOCROOT + +## +## The value for the "Server:" response field. +## +## It would be nice to keep it at "lighttpd". +## +#server.tag = "lighttpd" + +## +## store a pid file +## +server.pid-file = state_dir + "/lighttpd.pid" + +## +####################################################################### + +####################################################################### +## +## Logging Options +## ------------------ +## +## all logging options can be overwritten per vhost. +## +## Path to the error log file +## +server.errorlog = log_root + "/error.log" + +## +## If you want to log to syslog you have to unset the +## server.errorlog setting and uncomment the next line. +## +#server.errorlog-use-syslog = "enable" + +## +## Access log config +## +include "conf.d/access_log.conf" + +## +## The debug options are moved into their own file. +## see conf.d/debug.conf for various options for request debugging. +## +#include "conf.d/debug.conf" + +## +####################################################################### + +####################################################################### +## +## Tuning/Performance +## -------------------- +## +## corresponding documentation: +## https://redmine.lighttpd.net/projects/lighttpd/wiki/Docs_Performance +## +## set the event-handler (read the performance section in the manual) +## +## possible options on linux are: +## +## select +## poll +## linux-sysepoll +## +## linux-sysepoll is recommended on kernel 2.6. +## +server.event-handler = "linux-sysepoll" + +## +## The basic network interface for all platforms at the syscalls read() +## and write(). Every modern OS provides its own syscall to help network +## servers transfer files as fast as possible +## +## sendfile - is recommended for small files. +## writev - is recommended for sending many large files +## +server.network-backend = "sendfile" + +## +## As lighttpd is a single-threaded server, its main resource limit is +## the number of file descriptors, which is set to 1024 by default (on +## most systems). +## +## If you are running a high-traffic site you might want to increase this +## limit by setting server.max-fds. +## +## Changing this setting requires root permissions on startup. see +## server.username/server.groupname. +## +## By default lighttpd would not change the operation system default. +## But setting it to 2048 is a better default for busy servers. +## +server.max-fds = 2048 + +## +## listen-backlog is the size of the listen() backlog queue requested when +## the lighttpd server ask the kernel to listen() on the provided network +## address. Clients attempting to connect() to the server enter the listen() +## backlog queue and wait for the lighttpd server to accept() the connection. +## +## The out-of-box default on many operating systems is 128 and is identified +## as SOMAXCONN. This can be tuned on many operating systems. (On Linux, +## cat /proc/sys/net/core/somaxconn) Requesting a size larger than operating +## system limit will be silently reduced to the limit by the operating system. +## +## When there are too many connection attempts waiting for the server to +## accept() new connections, the listen backlog queue fills and the kernel +## rejects additional connection attempts. This can be useful as an +## indication to an upstream load balancer that the server is busy, and +## possibly overloaded. In that case, configure a smaller limit for +## server.listen-backlog. On the other hand, configure a larger limit to be +## able to handle bursts of new connections, but only do so up to an amount +## that the server can keep up with responding in a reasonable amount of +## time. Otherwise, clients may abandon the connection attempts and the +## server will waste resources servicing abandoned connections. +## +## It is best to leave this setting at its default unless you have modelled +## your traffic and tested that changing this benefits your traffic patterns. +## +## Default: 1024 +## +#server.listen-backlog = 128 + +## +## Stat() call caching. +## +## lighttpd can utilize FAM/Gamin to cache stat call. +## +## possible values are: +## disable, simple or fam. +## +#server.stat-cache-engine = "simple" + +## +## Fine tuning for the request handling +## +## max-connections == max-fds/2 (maybe /3) +## means the other file handles are used for fastcgi/files +## +server.max-connections = 1024 + +## +## How many seconds to keep a keep-alive connection open, +## until we consider it idle. +## +## Default: 5 +## +#server.max-keep-alive-idle = 5 + +## +## How many keep-alive requests until closing the connection. +## +## Default: 16 +## +#server.max-keep-alive-requests = 16 + +## +## Maximum size of a request in kilobytes. +## By default it is unlimited (0). +## +## Uploads to your server cant be larger than this value. +## +#server.max-request-size = 0 + +## +## Time to read from a socket before we consider it idle. +## +## Default: 60 +## +#server.max-read-idle = 60 + +## +## Time to write to a socket before we consider it idle. +## +## Default: 360 +## +#server.max-write-idle = 360 + +## +## Traffic Shaping +## ----------------- +## +## see /usr/share/doc/lighttpd/traffic-shaping.txt +## +## Values are in kilobyte per second. +## +## Keep in mind that a limit below 32kB/s might actually limit the +## traffic to 32kB/s. This is caused by the size of the TCP send +## buffer. +## +## per server: +## +#server.kbytes-per-second = 128 + +## +## per connection: +## +#connection.kbytes-per-second = 32 + +## +####################################################################### + +####################################################################### +## +## Filename/File handling +## ------------------------ + +## +## files to check for if .../ is requested +## index-file.names = ( "index.php", "index.rb", "index.html", +## "index.htm", "default.htm" ) +## +index-file.names += ( + "index.xhtml", "index.html", "index.htm", "default.htm", "index.php" +) + +## +## deny access the file-extensions +## +## ~ is for backupfiles from vi, emacs, joe, ... +## .inc is often used for code includes which should in general not be part +## of the document-root +url.access-deny = ( "~", ".inc" ) + +## +## disable range requests for pdf files +## workaround for a bug in the Acrobat Reader plugin. +## +$HTTP["url"] =~ "\.pdf$" { + server.range-requests = "disable" +} + +## +## url handling modules (rewrite, redirect) +## +#url.rewrite = ( "^/$" => "/server-status" ) +#url.redirect = ( "^/wishlist/(.+)" => "http://www.example.com/$1" ) + +## +## both rewrite/redirect support back reference to regex conditional using %n +## +#$HTTP["host"] =~ "^www\.(.*)" { +# url.redirect = ( "^/(.*)" => "http://%1/$1" ) +#} + +## +## which extensions should not be handle via static-file transfer +## +## .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi +## +static-file.exclude-extensions = ( ".php", ".pl", ".fcgi", ".scgi" ) + +## +## error-handler for all status 400-599 +## +#server.error-handler = "/error-handler.html" +#server.error-handler = "/error-handler.php" + +## +## error-handler for status 404 +## +#server.error-handler-404 = "/error-handler.html" +#server.error-handler-404 = "/error-handler.php" + +## +## Format: .html +## -> ..../status-404.html for 'File not found' +## +#server.errorfile-prefix = "/srv/www/htdocs/errors/status-" + +## +## mimetype mapping +## +include "conf.d/mime.conf" + +## +## directory listing configuration +## +include "conf.d/dirlisting.conf" + +## +## Should lighttpd follow symlinks? +## +server.follow-symlink = "enable" + +## +## force all filenames to be lowercase? +## +#server.force-lowercase-filenames = "disable" + +## +## defaults to /var/tmp as we assume it is a local harddisk +## +server.upload-dirs = ( root_path+"/upload" ) + +## +####################################################################### + + +####################################################################### +## +## SSL Support +## ------------- +## +## To enable SSL for the whole server you have to provide a valid +## certificate and have to enable the SSL engine.:: +## +## ssl.engine = "enable" +## ssl.pemfile = "/path/to/server.pem" +## +## The HTTPS protocol does not allow you to use name-based virtual +## hosting with SSL. If you want to run multiple SSL servers with +## one lighttpd instance you must use IP-based virtual hosting: :: +## +## Mitigate CVE-2009-3555 by disabling client triggered renegotation +## This is enabled by default. +## +## IMPORTANT: this setting can only be used in the global scope. +## It does *not* work inside conditionals +## +# ssl.disable-client-renegotiation = "enable" +## +## $SERVER["socket"] == "10.0.0.1:443" { +## ssl.engine = "enable" +## ssl.pemfile = "/etc/ssl/private/www.example.com.pem" +## # +## # (Following SSL/TLS Deployment Best Practices 1.3 / 17 September 2013 from: +## # https://www.ssllabs.com/projects/best-practices/index.html) +## # - BEAST is considered mitigaed on client side now, and new weaknesses have been found in RC4, +## # so it is strongly advised to disable RC4 ciphers (HIGH doesn't include RC4) +## # - It is recommended to disable 3DES too (although disabling RC4 and 3DES breaks IE6+8 on Windows XP, +## # so you might want to support 3DES for now - just remove the '!3DES' parts below). +## # - The examples below prefer ciphersuites with "Forward Secrecy" (and ECDHE over DHE (alias EDH)), remove '+kEDH +kRSA' +## # if you don't want that. +## # - SRP and PSK are not supported anyway, excluding those ('!kSRP !kPSK') just keeps the list smaller (easier to review) +## # Check your cipher list with: openssl ciphers -v '...' (use single quotes as your shell won't like ! in double quotes) +## # +## # If you know you have RSA keys (standard), you can use: +## ssl.cipher-list = "aRSA+HIGH !3DES +kEDH +kRSA !kSRP !kPSK" +## # The more generic version (without the restriction to RSA keys) is +## # ssl.cipher-list = "HIGH !aNULL !3DES +kEDH +kRSA !kSRP !kPSK" +## # +## # Make the server prefer the order of the server side cipher suite instead of the client suite. +## # This option is enabled by default, but only used if ssl.cipher-list is set. +## # +## # ssl.honor-cipher-order = "enable" +## # +## server.name = "www.example.com" +## +## server.document-root = "/srv/www/vhosts/example.com/www/" +## } +## + +include_shell "/usr/bin/sh "+ conf_dir + "/conf.d/maybessl.sh" +#ssl.engine = "enable" +#ssl.pemfile = conf_dir + "/ssl/server.pem" + +## If you have a .crt and a .key file, cat them together into a +## single PEM file: +## $ cat /etc/ssl/private/lighttpd.key /etc/ssl/certs/lighttpd.crt \ +## > /etc/ssl/private/lighttpd.pem +## +#ssl.pemfile = "/etc/ssl/private/lighttpd.pem" + +## +## optionally pass the CA certificate here. +## +## +#ssl.ca-file = "" + +## +## and the CRL revocation list here. +## +## +#ssl.ca-crl-file = "" + +## +####################################################################### diff --git a/tests/data/nginxconf/mime.types b/tests/data/nginxconf/mime.types new file mode 100644 index 0000000..8a2348a --- /dev/null +++ b/tests/data/nginxconf/mime.types @@ -0,0 +1,95 @@ + +types { + text/html html htm shtml; + text/css css; + text/xml xml; + image/gif gif; + image/jpeg jpeg jpg; + application/javascript js; + application/atom+xml atom; + application/rss+xml rss; + + text/mathml mml; + text/plain txt; + text/vnd.sun.j2me.app-descriptor jad; + text/vnd.wap.wml wml; + text/x-component htc; + + image/png png; + image/svg+xml svg svgz; + image/tiff tif tiff; + image/vnd.wap.wbmp wbmp; + image/webp webp; + image/x-icon ico; + image/x-jng jng; + image/x-ms-bmp bmp; + + application/font-woff woff; + application/java-archive jar war ear; + application/json json; + application/mac-binhex40 hqx; + application/msword doc; + application/pdf pdf; + application/postscript ps eps ai; + application/rtf rtf; + application/vnd.apple.mpegurl m3u8; + application/vnd.google-earth.kml+xml kml; + application/vnd.google-earth.kmz kmz; + application/vnd.ms-excel xls; + application/vnd.ms-fontobject eot; + application/vnd.ms-powerpoint ppt; + application/vnd.oasis.opendocument.graphics odg; + application/vnd.oasis.opendocument.presentation odp; + application/vnd.oasis.opendocument.spreadsheet ods; + application/vnd.oasis.opendocument.text odt; + application/vnd.openxmlformats-officedocument.presentationml.presentation + pptx; + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet + xlsx; + application/vnd.openxmlformats-officedocument.wordprocessingml.document + docx; + application/vnd.wap.wmlc wmlc; + application/x-7z-compressed 7z; + application/x-cocoa cco; + application/x-java-archive-diff jardiff; + application/x-java-jnlp-file jnlp; + application/x-makeself run; + application/x-perl pl pm; + application/x-pilot prc pdb; + application/x-rar-compressed rar; + application/x-redhat-package-manager rpm; + application/x-sea sea; + application/x-shockwave-flash swf; + application/x-stuffit sit; + application/x-tcl tcl tk; + application/x-x509-ca-cert der pem crt; + application/x-xpinstall xpi; + application/xhtml+xml xhtml; + application/xspf+xml xspf; + application/zip zip; + + application/octet-stream bin exe dll; + application/octet-stream deb; + application/octet-stream dmg; + application/octet-stream iso img; + application/octet-stream msi msp msm; + + audio/midi mid midi kar; + audio/mpeg mp3; + audio/ogg ogg; + audio/x-m4a m4a; + audio/x-realaudio ra; + + video/3gpp 3gpp 3gp; + video/mp2t ts; + video/mp4 mp4; + video/mpeg mpeg mpg; + video/quicktime mov; + video/webm webm; + video/x-flv flv; + video/x-m4v m4v; + video/x-mng mng; + video/x-ms-asf asx asf; + video/x-ms-wmv wmv; + video/x-msvideo avi; +} diff --git a/tests/data/nginxconf/nginx.conf b/tests/data/nginxconf/nginx.conf new file mode 100644 index 0000000..2c14d76 --- /dev/null +++ b/tests/data/nginxconf/nginx.conf @@ -0,0 +1,104 @@ +daemon off; +worker_processes 1; + +error_log log/error.log; +pid server.pid; + +include user.conf; + +events { + worker_connections 1024; + use epoll; +} + + +http { + include mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + + client_body_temp_path temp 1 2; + proxy_temp_path temp 1 2; + fastcgi_temp_path temp 1 2; + uwsgi_temp_path temp 1 2; + scgi_temp_path temp 1 2; + + access_log log/access.log main; + + sendfile on; + #tcp_nopush on; + + #keepalive_timeout 0; + keepalive_timeout 65; + + #gzip on; + + max_ranges 128; + + server { + include port.conf; + server_name localhost; + + include ssl.conf; + + #charset koi8-r; + + #access_log /var/log/nginx/host.access.log main; + + location / { + include srvroot.conf; + index index.html index.htm; + } + + location /handler { + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + fastcgi_param QUERY_STRING $query_string; + fastcgi_param REQUEST_METHOD $request_method; + fastcgi_param CONTENT_TYPE $content_type; + fastcgi_param CONTENT_LENGTH $content_length; + + fastcgi_param SCRIPT_NAME $fastcgi_script_name; + fastcgi_param REQUEST_URI $request_uri; + fastcgi_param DOCUMENT_URI $document_uri; + fastcgi_param DOCUMENT_ROOT $document_root; + fastcgi_param SERVER_PROTOCOL $server_protocol; + fastcgi_param REQUEST_SCHEME $scheme; + fastcgi_param HTTPS $https if_not_empty; + fastcgi_param HTTP_AUTHORIZATION $http_authorization; + + fastcgi_param GATEWAY_INTERFACE CGI/1.1; + fastcgi_param SERVER_SOFTWARE nginx/$nginx_version; + + fastcgi_param REMOTE_ADDR $remote_addr; + fastcgi_param REMOTE_PORT $remote_port; + fastcgi_param SERVER_ADDR $server_addr; + fastcgi_param SERVER_PORT $server_port; + fastcgi_param SERVER_NAME $server_name; + + fastcgi_intercept_errors off; + fastcgi_pass_header "Status"; + fastcgi_pass_header "Status-Code"; + include fcgisock.conf; + } + + #error_page 404 /404.html; + + # redirect server error pages to the static page /50x.html + # + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /srv/www/htdocs/; + } + + # deny access to .htaccess files, if Apache's document root + # concurs with nginx's one + # + location ~ /\.ht { + deny all; + } + } +} diff --git a/tests/data/nginxconf/nossl.conf b/tests/data/nginxconf/nossl.conf new file mode 100644 index 0000000..e69de29 diff --git a/tests/data/nginxconf/ssl.conf b/tests/data/nginxconf/ssl.conf new file mode 100644 index 0000000..e7faf4a --- /dev/null +++ b/tests/data/nginxconf/ssl.conf @@ -0,0 +1,2 @@ +ssl_certificate cert.pem; +ssl_certificate_key cert.key; diff --git a/tests/data/obs_virtualbox_11_1/repodata/primary.xml.gz b/tests/data/obs_virtualbox_11_1/repodata/primary.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..855e00abbf3fb9c74ba2f2ae67ede50de092b144 GIT binary patch literal 17674 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 literal 0 HcmV?d00001 diff --git a/tests/data/obs_virtualbox_11_1/repodata/repomd.xml b/tests/data/obs_virtualbox_11_1/repodata/repomd.xml new file mode 100644 index 0000000..7f971ad --- /dev/null +++ b/tests/data/obs_virtualbox_11_1/repodata/repomd.xml @@ -0,0 +1,21 @@ + + + + + 580103a6b945e1830565121199acbdad45437c7f + 1223588080 + 2d2604f11a697bc443b3c9999d630897138168ad + + + + e8696a3badb8419500de7e1618585d6272912a99 + 1223588080 + 91d3e517317bcd686a5ec1e88abd63b6fb7619da + + + + fc0f951db57c5b767887190bf99e479692b1c407 + 1223588080 + a0015ff42e9822c16990b23a9cb08e026b4afdf9 + + diff --git a/tests/data/obs_virtualbox_11_1/repodata/repomd.xml.asc b/tests/data/obs_virtualbox_11_1/repodata/repomd.xml.asc new file mode 100644 index 0000000..857cd5e --- /dev/null +++ b/tests/data/obs_virtualbox_11_1/repodata/repomd.xml.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBI7njy+FLjwVdyGmYRAh6pAJ4zinB1Qa04keOTZET1/KTWRQcdqACf +WulP6OHLt3n1fuHPRQRYUmUgeaU= +=GveQ +-----END PGP SIGNATURE----- diff --git a/tests/data/obs_virtualbox_11_1/repodata/repomd.xml.key b/tests/data/obs_virtualbox_11_1/repodata/repomd.xml.key new file mode 100644 index 0000000..a79e313 --- /dev/null +++ b/tests/data/obs_virtualbox_11_1/repodata/repomd.xml.key @@ -0,0 +1,20 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQGiBEeWVjIRBACUzcPOeJfTB0/AbBdlmZqfGca/YwPdg7PXB1zBkfuH/YSDDgTo +4BesZigfcgIyO+3KCyPZ0P+5pO3RIdmIyMGndhKsSTb+sX0utPYvsJlMDmo2lHm3 +i26st2DZLESKOtfpeyeXrZHTL1loAyUy0IHpTD6pmtgnBLr7SNkcGb2oJwCgxMvG +ArBVVG5+R6r8gXJ5NxAH+rUEAIOYuwl8RwmFHvVMg/swDl+YTXqhM7BOyieY4HzR +hhm+OKOkMFqSMudReHvX+jwtpUduN8GiTZq0QaWTF1WUZLQhn+Q+4oRjOWnIKiwl +RRQisrn4cVJtzLQojCh6JBcIobNCexAUCMMoC0dGB5LGxfx8eKKuytzPooMYpfzV +78QmA/49WMDc5wLyobhchFzm4cQmk7SYGaTFbAnkF6IBgIEOfQGkQCSMcKlLNYfB +kgJr8FMeakkeExrXKsvmL5U8stwtLgRqYhBYgEE/1ZS2MGDLB0nzaEVfovvTYn6B +n4o34KE/l6RaXUsxcyL0sbZ6BOG1MgKWLjlKkn9xI77m9jR5HbRUVmlydHVhbGl6 +YXRpb246VmlydHVhbEJveCBPQlMgUHJvamVjdCA8VmlydHVhbGl6YXRpb246Vmly +dHVhbEJveEBidWlsZC5vcGVuc3VzZS5vcmc+iGYEExECACYFAkeWVjICGwMFCQQe +sAAGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRD4UuPBV3IaZrrMAJ0aJsQOUt+s +efyWCGh3MefGjBEUFACdEixxBrtbVss3yILYjJbzlUwhp1GIRgQTEQIABgUCR5ZW +MgAKCRA7MBG3a51lI3O8AJ9vv441rs2ZR8pHL2EEmvegbAMPTwCeJJUbs14J5Wlr +zqyZAhXnXWJnldY= +=elkz +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/content b/tests/data/openSUSE-11.1/content new file mode 100644 index 0000000..4c30fcf --- /dev/null +++ b/tests/data/openSUSE-11.1/content @@ -0,0 +1,122 @@ +CONTENTSTYLE 11 +NAME openSUSE +LABEL The openSUSE Distribution +VENDOR SUSE LINUX Products GmbH, Nuernberg, Germany +RELNOTESURL http://www.suse.com/relnotes/i386/openSUSE/11.0.42/release-notes-openSUSE.rpm +DESCRDIR suse/setup/descr +REFERENCES openSUSE-release EQ 11.1 +LINGUAS cs da de en en_GB en_US es fi fr hu it ja nb nl pl pt pt_BR ru sv zh zh_CN zh_TW +BASEARCHS x86_64 +FLAVOR dvd +DISTRIBUTION openSUSE +DATADIR suse +VERSION 11.1 +META SHA1 02f22523c8302dbd4838618b746cf8a348e39a53 dvd-11.1-46.1.x86_64.pat.gz +META SHA1 cc02920ad0f2270663a04861bc44c7fd480f1e9f non_oss-11.1-46.1.x86_64.pat.gz +META SHA1 d8e90da75261b09757c10d90055aba27c36c2571 packages.cs.gz +META SHA1 1bfeb67fbb2e77f1309bd105d209549370d63184 packages.DU.gz +META SHA1 2db9160217ca686f78a3e86de3de38955ad9fe3f packages.en.gz +META SHA1 f4671fc99244c27e2a467a9bd11aa43a5fbe96b8 packages.gz +META SHA1 73615d8e511ea4ad14bce617bfe18ea5de65395e patterns +#HASH SHA1 cd4e142d292e299488a482144f38f9f8d4d61f01 license.tar.gz +HASH SHA1 7bd21d938f9fec0ec764ac4d46d80417baf5c94e control.xml +HASH SHA1 e1499f54fba10d11ce6b6f0fc9c57c6a2ad49f83 media.1/info.txt +HASH SHA1 d423ad41e93a51195a6264961e4a074c6d89359d boot/x86_64/bind +HASH SHA1 635492857403d315c613579760694919d252fa68 boot/x86_64/branding +HASH SHA1 6c661d6cf1db68da6498bcf179fb52dbec907563 boot/x86_64/common +HASH SHA1 7cb8e2739b4751daed7c6f6e7cc20b5021346885 boot/x86_64/config +HASH SHA1 7eebc04d8999af9a5b2fdcb75c6ad2e9cd46ef24 boot/x86_64/cracklib-dict-full.rpm +HASH SHA1 50067c10711281342e1b73bdb02b49a95ea626d0 boot/x86_64/directory.yast +HASH SHA1 93d86eaadeedbf29cf4028f6b965cd513fb4b392 boot/x86_64/efi +HASH SHA1 c9216fb7114ce0f23a0c0650b91d4efd5785dd57 boot/x86_64/fonts-arabic.rpm +HASH SHA1 d4cde75eaf078dcf5a9be04f5cb6427fc5c0a4d2 boot/x86_64/fonts-thai.rpm +HASH SHA1 c82ef5b36dda514d8239a0c234f50a5201cf2f1c boot/x86_64/gdb +HASH SHA1 44bed8ec07474e7703fa7915909eccf76a624b68 boot/x86_64/indic-fonts.rpm +HASH SHA1 e3005c6ffc8600dc1e5c42b3a1d94ce3e32562d5 boot/x86_64/KhmerOS-fonts.rpm +HASH SHA1 e9c779539f1b3f56a96337f262b2bc548e6b223e boot/x86_64/LIESMICH +HASH SHA1 abdf17a0246be709efbcc7c0e0a68f8ad797a754 boot/x86_64/LIESMICH.DOS +HASH SHA1 b5a21e780bdad707a989754f0fda867b60bf398e boot/x86_64/lklug.rpm +HASH SHA1 c4dca65aa97554bc45885b22ef4af24ad5177c75 boot/x86_64/mkbootdisk +HASH SHA1 635492857403d315c613579760694919d252fa68 boot/x86_64/openSUSE +HASH SHA1 ae44557c57285f0866be41334fdaa20312ccdeab boot/x86_64/README +HASH SHA1 4a71ee6114eccfb88582dc5422020cbc5a2639dd boot/x86_64/README.DOS +HASH SHA1 b82adaf3be49972e7241ade027a6a26139cc632c boot/x86_64/rescue +HASH SHA1 3810d9544827f1d42708f39427e0a48e9e086ea1 boot/x86_64/root +HASH SHA1 415f125a4ee1e5a42dc65399b31526110bce3dc1 boot/x86_64/rpmlist +HASH SHA1 bd61c88b73894e8106bda37d8190427a910d3ca2 boot/x86_64/sax2 +HASH SHA1 df10e84db8c57c00aac85e2e6a6cc5e359c27d8f boot/x86_64/unfonts.rpm +HASH SHA1 1239df7c815fa8e121aed8c0dcef1afe45579611 boot/x86_64/yast2-trans-af.rpm +HASH SHA1 b12865177ac3be4741dfb4aae42b39398128314f boot/x86_64/yast2-trans-ar.rpm +HASH SHA1 a35e306a95f4dd292baab41c280cb25f49e9a90f boot/x86_64/yast2-trans-bg.rpm +HASH SHA1 b6eeb78c8462f7d5a26e863f1e4b60740b3379eb boot/x86_64/yast2-trans-bn.rpm +HASH SHA1 b3f6d1ff28da9b19e42a0376a44eaa047d538ebc boot/x86_64/yast2-trans-bs.rpm +HASH SHA1 e95f0a401ac1b94f463d3c47bb1fbde091644dbb boot/x86_64/yast2-trans-ca.rpm +HASH SHA1 6a2c8a3bad0ecc2d18c000d6c1ce0b3af2e0e208 boot/x86_64/yast2-trans-cs.rpm +HASH SHA1 11486ac6c36f4d5a4272bc1c712c30dc8f2c7828 boot/x86_64/yast2-trans-cy.rpm +HASH SHA1 9f15697ae01461959861b33ca46a04587b8f428e boot/x86_64/yast2-trans-da.rpm +HASH SHA1 4a15f3271782059ad77d0b2027685e86d26f0b00 boot/x86_64/yast2-trans-de.rpm +HASH SHA1 1667a7ab28bcc171234c960dab46fef1871d4d69 boot/x86_64/yast2-trans-el.rpm +HASH SHA1 70dab8364af972d42cb21879eac56eaf9b1b2b19 boot/x86_64/yast2-trans-en_GB.rpm +HASH SHA1 29b416da00c34a2bced9438f0ce4e4eeb92b94e6 boot/x86_64/yast2-trans-en_US.rpm +HASH SHA1 46c97123053954623de74f2f88eaabe9bc7a330d boot/x86_64/yast2-trans-es.rpm +HASH SHA1 ab897d8d470485f1ede2ed378502faa5ddc699cc boot/x86_64/yast2-trans-et.rpm +HASH SHA1 f0fba8ba6a39e4ff54e55d0f5afe52102d7f6cb3 boot/x86_64/yast2-trans-fa.rpm +HASH SHA1 83c25237432beb7fcb31ef4242d692ab8683cf2a boot/x86_64/yast2-trans-fi.rpm +HASH SHA1 54d0a51ca313a293afa71837f06570933a811123 boot/x86_64/yast2-trans-fr.rpm +HASH SHA1 199ce417e36c36384709f5870a9227bdbeb69300 boot/x86_64/yast2-trans-gl.rpm +HASH SHA1 3adf1af8f9a806101ec2ec30fd30e3b6f36c5754 boot/x86_64/yast2-trans-gu.rpm +HASH SHA1 4b7f87ba2f9c0305b50ccd05993223319bd98699 boot/x86_64/yast2-trans-hi.rpm +HASH SHA1 64573b85a3635dd438ea3a20948b50e7feff1e1f boot/x86_64/yast2-trans-hr.rpm +HASH SHA1 6450a7cd2061f5399816b521248ad4f96d1401c0 boot/x86_64/yast2-trans-hu.rpm +HASH SHA1 cd7a63bda7472183da33cb778e3ad403152663e2 boot/x86_64/yast2-trans-id.rpm +HASH SHA1 8db427cb2eb69348042ea94e2523c0e626431894 boot/x86_64/yast2-trans-it.rpm +HASH SHA1 3c273d19b4c6ac6d3209fe35109595034fb2bbf5 boot/x86_64/yast2-trans-ja.rpm +HASH SHA1 4a14bf1c880b63ebc4ae0746c89519f7b8a41cd5 boot/x86_64/yast2-trans-jv.rpm +HASH SHA1 f47f6a81e05c38fc77a37226dabe038d64b3b4cd boot/x86_64/yast2-trans-ka.rpm +HASH SHA1 397dcfbe3dc3f54b0ede510105d474360d986930 boot/x86_64/yast2-trans-km.rpm +HASH SHA1 666f733888966efd0490fbb3e41f1ede9f14f1ca boot/x86_64/yast2-trans-ko.rpm +HASH SHA1 417c70401e18d2f948e5f4e87db1396dd6d886c9 boot/x86_64/yast2-trans-lo.rpm +HASH SHA1 f7856142994f69c5d6fe3c7a78fc1ad708fecb55 boot/x86_64/yast2-trans-lt.rpm +HASH SHA1 58beaecdacfda372a34454f738a0f8ec80aecfb2 boot/x86_64/yast2-trans-mk.rpm +HASH SHA1 c48d3d055928c8bd2fc1ec3040f102fe0f387990 boot/x86_64/yast2-trans-mr.rpm +HASH SHA1 890a914b0ad6a29143e61deb161eff3556b72a44 boot/x86_64/yast2-trans-nb.rpm +HASH SHA1 11a8297890053f5cca3674953805284d88b1ad79 boot/x86_64/yast2-trans-nl.rpm +HASH SHA1 fa28c6c056018f95e008e8dc586f0e0b370428c1 boot/x86_64/yast2-trans-pa.rpm +HASH SHA1 7751c37d3d772ff1b85a3a890d95779703980419 boot/x86_64/yast2-trans-pl.rpm +HASH SHA1 b8462077cb347654ad110e7a5eceb5510b785ba1 boot/x86_64/yast2-trans-pt_BR.rpm +HASH SHA1 97f44a1d7e04f9d08d2ce6fdd83398d7aa0643ba boot/x86_64/yast2-trans-pt.rpm +HASH SHA1 570ccf8610302ee61731f50604a0d74405c36640 boot/x86_64/yast2-trans-ro.rpm +HASH SHA1 74822dc08976c91840e90624d369da07c035b69a boot/x86_64/yast2-trans-ru.rpm +HASH SHA1 133235b1cb582ecb94c2f1da2b42f2bf7ad555dd boot/x86_64/yast2-trans-si.rpm +HASH SHA1 a49abc3f07422c8b7356633d4293de4f477d2d8a boot/x86_64/yast2-trans-sk.rpm +HASH SHA1 2cc14382b7bda0846d529580fc168e76d02eade2 boot/x86_64/yast2-trans-sl.rpm +HASH SHA1 6728cda67fd1c92d4b34f8a75752e98145916e4f boot/x86_64/yast2-trans-sr.rpm +HASH SHA1 fc9387bfec45138cbcc10d112a4160e93548dce9 boot/x86_64/yast2-trans-sv.rpm +HASH SHA1 3a6f6bf53ab8dfe8c268dbf25f7aae869dfa8623 boot/x86_64/yast2-trans-ta.rpm +HASH SHA1 755b0d4289a35a84bdc643112c09f102e5aecee6 boot/x86_64/yast2-trans-th.rpm +HASH SHA1 c4e460be4ead26938872f5ee56f05fd527af31c8 boot/x86_64/yast2-trans-tr.rpm +HASH SHA1 5df0e280b9d3f071cf72158d4a482e443fc98c51 boot/x86_64/yast2-trans-uk.rpm +HASH SHA1 e4c77981b4ab02c963536ab6afd3cfe226fd6a3d boot/x86_64/yast2-trans-vi.rpm +HASH SHA1 dcd414589be7e8d1d837d49d35614845f986a59e boot/x86_64/yast2-trans-wa.rpm +HASH SHA1 2f76618d24c00b3fd4cbf8fdd4a56d34dc19867e boot/x86_64/yast2-trans-xh.rpm +HASH SHA1 3e6ac86cc533dae2053c06dca92918444e4c9361 boot/x86_64/yast2-trans-zh_CN.rpm +HASH SHA1 ad9e32afe651712cd384c8e20d17de18d6a86ae4 boot/x86_64/yast2-trans-zh_TW.rpm +HASH SHA1 a1aaa5991b25744683a761b936067ba279be608e boot/x86_64/yast2-trans-zu.rpm +HASH SHA1 219014df667b51f44d62b22979993c6914aab3ce boot/x86_64/loader/linux +HASH SHA1 266979798cb8924da5078fce8f1c41db54e21032 boot/x86_64/loader/initrd +HASH SHA1 1ee4dd576e7aef8b10e01cf64b70e548175f9f40 boot/x86_64/loader/08000600.spl +HASH SHA1 f93b778b469797d3547ce21dd67d31aeeefa412b boot/x86_64/loader/10240600.spl +HASH SHA1 8a33d7e0f2f1c1933261e1747ea9592991b6d305 boot/x86_64/loader/10240768.spl +HASH SHA1 8f51f64ddfcbe6b3261bd329a65bd8f75ddbd779 boot/x86_64/loader/12800800.spl +HASH SHA1 de76d38637bf6a520972ba22125023fb5e9005d2 boot/x86_64/loader/12801024.spl +HASH SHA1 db7c22e91260da6c5c86587a477b277a2921fcc3 boot/x86_64/loader/14001050.spl +HASH SHA1 a5985dc49d457ef58127b288cf3e20c4fbdb5a55 boot/x86_64/loader/16001200.spl +HASH SHA1 495cee4703eaea74c31fca705a4cdbb8825c9f8d boot/x86_64/loader/16801050.spl +HASH SHA1 01aaf0d2aa576c4bdd0fd2638baeeb6e788e902b boot/x86_64/loader/19201200.spl +KEY SHA1 17162a96933229a9771ee10c0976bdc047a2f53d gpg-pubkey-0dfb3188-41ed929b.asc +KEY SHA1 f6accbb18d705bfc104c893cf7dfca1247a33f3c gpg-pubkey-307e3d54-481f30aa.asc +KEY SHA1 47f6492d127ae9f6aac353a2dd23752fc0ed4f8d gpg-pubkey-3d25d3d9-36e12d04.asc +KEY SHA1 2288e5849740566e4fb65b7c9dc0c7e4f43b1039 gpg-pubkey-56b4177a-47965b33.asc +KEY SHA1 89d4bcd20a281553fd1d4ec1708603ebf88f1a59 gpg-pubkey-7e2e3b05-4816488f.asc +KEY SHA1 06ff5171362496c0db84beeccd29967f580350b2 gpg-pubkey-9c800aca-481f343a.asc +KEY SHA1 04544096c5c3b0ed7b01a83d79e048307c2af919 gpg-pubkey-a1912208-446a0899.asc diff --git a/tests/data/openSUSE-11.1/gpg-pubkey-0dfb3188-41ed929b.asc b/tests/data/openSUSE-11.1/gpg-pubkey-0dfb3188-41ed929b.asc new file mode 100644 index 0000000..ac75d62 --- /dev/null +++ b/tests/data/openSUSE-11.1/gpg-pubkey-0dfb3188-41ed929b.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +mQGiBEHtkpsRBACRHiXh3olS++6/Mp9N7ByGMmjaaE+Y8cJQLUPG1myrbW5aogIP +0WenayhGbbgOHNWgd5dQ8KQpYYFoQuUHjFYzj5MvgrdOENOvD7ZNJ6+EmbkNh5cV +zUYfNG9jdiGweZkyA1sh8DYS0JiUmQ4CzaBD/DotB/dCmDcyuNQFiw4qKwCglQah +ATyueBRsOiXl0NIs1uB6dkkD/1A2YmQ6te1q38a1J+a8os6bDlMZhVnkZdhJdw6x +eBwUb9XS0n7hyt/AKCcBnrDEUQJuhBMNgzctJvbuMv27yRMANAXZDQkp0ip/yHLJ +PhUdSNTTRHOL9bV3t+JuZ9xmuclprwyrrJYUkEESXNc0tkuczHBP2c/RqA3OxYHt +hrHLA/9Pqe2gEleeo8l26u/uFXs2dtwjh8EZmdhHoqGcOlpYR4DyAg2D+jYfh3RI +oPzIwRlHVUR1ii5h8iPi98BVuEvukwfbbQ1K22Jwzxt6w3ihCXBKWKbeC3ElIMfA +hVMchLFUbTAw+yodO/u3NHxKQ34+ginid9dVyxV5T0gpDEEHObQrT3BlbiBFbnRl +cnByaXNlIFNlcnZlciA8c3VwcG9ydEBub3ZlbGwuY29tPoheBBMRAgAeBQJB7ZKb +AhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEHPSXWMN+zGID4oAoJPTGZbZApW+ +tuU422mHYGwoqgjrAJ9fhzRhRbV3YsOxKUomNeuIfmWGXA== +=Qv5+ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/gpg-pubkey-307e3d54-481f30aa.asc b/tests/data/openSUSE-11.1/gpg-pubkey-307e3d54-481f30aa.asc new file mode 100644 index 0000000..57a9078 --- /dev/null +++ b/tests/data/openSUSE-11.1/gpg-pubkey-307e3d54-481f30aa.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +mIsERCAdXQEEAL7MrBTz+3SBWpCm2ae2yaDqV3ezQcs2JlvqidJVhsZqQe9/jkxi +KTEQW5+TXF/+BlQSiebunRI7oo3+9U8GyRCgs1sf+yRQWMLzZqRaarzRhw9w+Ihl +edtqYl6/U2JZCb8Adp6d7RzlRliJdJ/VtsfXj2ef7Dwu7elOVSsmaBdtAAYptChT +dVNFIFBhY2thZ2UgU2lnbmluZyBLZXkgPGJ1aWxkQHN1c2UuZGU+iLgEEwECACIC +GwMECwcDAgMVAgMDFgIBAh4BAheABQJIHzCqBQkHwXpNAAoJEOOlw2Awfj1UvWgE +AIRoxE8S6jQB7S43SVcX06FHJeUJ/m+1ErIj9LwJTYrR/8qsDjTgrttgb+nBHkIj +NhCCLAuR8sWj3CxsUMH2fayryNnwZEWGqnzo7Jtt4R1Ur3h5pHYonFjfoJyFUZjJ +7Mhw7/TuOWx20FrzqBi8tbHx8pd7Fa5lCUgopVtMh6GR +=R56j +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/gpg-pubkey-3d25d3d9-36e12d04.asc b/tests/data/openSUSE-11.1/gpg-pubkey-3d25d3d9-36e12d04.asc new file mode 100644 index 0000000..80380d2 --- /dev/null +++ b/tests/data/openSUSE-11.1/gpg-pubkey-3d25d3d9-36e12d04.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +mQENAzbhLQQAAAEIAKAkXHe0lWRBXLpn38hMHy03F0I4Sszmoc8aaKJrhfhyMlOA +BqvklPLE2f9UrI4Xc860gH79ZREwAgPt0pi6+SleNFLNcNFAuuHMLQOOsaMFatbz +JR9i4m/lf6q929YROu5zB48rBAlcfTm+IBbijaEdnqpwGib45wE/Cfy6FAttBHQh +1Kp+r/jPbf1mYAvljUfHKuvbg8t2EIQz/5yGp+n5trn9pElfQO2cRBq8LFpf1l+U +P7EKjFmlOq+Gs/fF98/dP3DfniSd78LQPq5vp8RL8nr/o2i7jkAQ33m4f1wOBWd+ +cZovrKXYlXiR+Bf7m2hpZo+/sAzhd7LmAD0l09kABRG0JVN1U0UgU2VjdXJpdHkg +VGVhbSA8c2VjdXJpdHlAc3VzZS5kZT6JARUDBRA24S1H5Fiyh7HKPEUBAVcOB/9b +yHYji1/+4Xc2GhvXK0FSJN0MGgeXgW47yxDL7gmR4mNgjlIOUHZj0PEpVjWepOJ7 +tQS3L9oP6cpj1Fj/XxuLbkp5VCQ61hpt54coQAvYrnT9rtWEGN+xmwejT1WmYmDJ +xG+EGBXKr+XP69oIUl1E2JO3rXeklulgjqRKos4cdXKgyjWZ7CP9V9daRXDtje63 +Om8gwSdU/nCvhdRIWp/Vwbf7Ia8iZr9OJ5YuQl0DBG4qmGDDrvImgPAFkYFzwlqo +choXFQ9y0YVCV41DnR+GYhwl2qBd81T8aXhihEGPIgaw3g8gd8B5o6mPVgl+nJqI +BkEYGBusiag2pS6qwznZiQEVAwUQNuEtBHey5gA9JdPZAQFtOAf+KVh939b0J94u +v/kpg4xs1LthlhquhbHcKNoVTNspugiC3qMPyvSX4XcBr2PC0cVkS4Z9PY9iCfT+ +x9WM96g39dAF+le2CCx7XISk9XXJ4ApEy5g4AuK7NYgAJd39PPbERgWnxjxir9g0 +Ix30dS30bW39D+3NPU5Ho9TD/B7UDFvYT5AWHl3MGwo3a1RhTs6sfgL7yQ3U+mvq +MkTExZb5mfN1FeaYKMopoI4VpzNVeGxQWIz67VjJHVyUlF20ekOz4kWVgsxkc8G2 +saqZd6yv2EwqYTi8BDAduweP33KrQc4KDDommQNDOXxaKOeCoESIdM4p7Esdjq1o +L0oixF12CohGBBARAgAGBQI7HmHDAAoJEJ5A4xAACqukTlQAoI4QzP9yjPohY7OU +F7J3eKBTzp25AJ42BmtSd3pvm5ldmognWF3Trhp+GYkAlQMFEDe3O8IWkDf+zvyS +FQEBAfkD/3GG5UgJj18UhYmh1gfjIlDcPAeqMwSytEHDENmHC+vlZQ/p0mT9tPiW +tp34io54mwr+bLPN8l6B5GJNkbGvH6M+mO7R8Lj4nHL6pyAv3PQr83WyLHcaX7It +Klj371/4yzKV6qpz43SGRK4MacLo2rNZ/dNej7lwPCtzCcFYwqkiiEYEEBECAAYF +AjoaQqQACgkQx1KqMrDf94ArewCfWnTUDG5gNYkmHG4bYL8fQcizyA4An2eVo/n+ +3J2KRWSOhpAMsnMxtPbB +=Ay23 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/gpg-pubkey-56b4177a-47965b33.asc b/tests/data/openSUSE-11.1/gpg-pubkey-56b4177a-47965b33.asc new file mode 100644 index 0000000..f0bb55a --- /dev/null +++ b/tests/data/openSUSE-11.1/gpg-pubkey-56b4177a-47965b33.asc @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +mQGiBEeWWzMRBADU8l2IckSzgdUS1dn0WMM7wXK4seoFsHHQw/0unHCQCxpyDMnn +TKV86p5KTbR1FDdeaZlY0yCV+IGsiIxLyuUdJn8vuA5gA5ZkUr89/HtWaeZVl77J +HIQxvhDRBWCOO4QNtrZYWvGbvl83wl/zOfdLEs8IGElt0LgfohyTA1qfrwCg/Hac +tDDscXsPlo5Jek/+3RHVeD0D/30riCpfpLJOmhraLg1EbWsE0mN9IQsl+WDPdoYo +bB76z6eH3e38618WzP/LTG4WuVbwpSSqmXyfdVpXxWzESfT8q0B8CGpHf/Sa/T/L +emohmRnLvkf/tAfxFmDMm1jOewJIE9S35jANGHVJcxmfRNpPWC7uHnqjopnsmDkL +kMEdBAC6YcpDOcMJZ9sJbt/JNZBaoT5CltgMDlSN50t2v/J5em8qMLqCSNF5UJyd +LFnePHTHy6gVjWbqcC0ncFzOqM1y644Up7BoKSAr1hRTl6Mw9S3UfZZZ0al3JtWt +8y0eFIW3QP66w1AL0LO2bZMBuOvhb63DXv5iHorcxk0yIFbbybRCb3BlblNVU0U6 +RmFjdG9yeSBPQlMgUHJvamVjdCA8b3BlblNVU0U6RmFjdG9yeUBidWlsZC5vcGVu +c3VzZS5vcmc+iGYEExECACYFAkeWWzMCGwMFCQQesAAGCwkIBwMCBBUCCAMEFgID +AQIeAQIXgAAKCRAcchwkVrQXevBsAKCOeScnlH2fWVBJGHTOVJ3M4yBqDACbBeNk +PuWo05AOQ3M1dLE1hkN36G+IRgQTEQIABgUCR5ZbMwAKCRA7MBG3a51lI7PfAKCc +9ZtKfI5G/g66V7pSMXh9gi+ykgCgivPfGMDh9HIROwBIudo2qGImOqI= +=htdw +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/gpg-pubkey-7e2e3b05-4816488f.asc b/tests/data/openSUSE-11.1/gpg-pubkey-7e2e3b05-4816488f.asc new file mode 100644 index 0000000..74ff59e --- /dev/null +++ b/tests/data/openSUSE-11.1/gpg-pubkey-7e2e3b05-4816488f.asc @@ -0,0 +1,20 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +mQGiBER0iroRBADfqUeJmPCXqPJFnf3CVKy40dL1F+gfvP+JHN7/uu4c9+oCYjI1 +uAE8iGTm/Twb/Zzbs4dt0iWjhNFXbRi42rMww4d/8QcPYZ21WSehh+fv8nCjt2sw +LeC87ar2SR8OTpJBK0fQlcd4e6H5GMntfI6SYEUOPd8m/eQ+4+1AxpUUpwCgswaF +13fePZGI//pDn5tGjbvmaP8D/R3qum/I+oDS8lbFeeDS10GkEkwTYec13gdfsq6I +yzIj7VBsC+rGfbipv+VGR61Q4d19pOHKLDekr9OG+3G4ZcYM4NQvQZR+QIlp3xWu +nBmYD1LRkHLVj+Z4DGQhjjOffkPSuacKPymMaZ/aRiLgTIAo97W2YPhutscXrLSG +2Y+BA/4jsyaDb7kbW4wc8RtPIcuFEheVqgBeRakP9Uj47kBMBEpPtI/mIdY5liKk +ztKnuQG6ROYLNV/PW0ZbE1uT64C710weh4cB3PnZLV5P10deDLBjHk8MJQGCTSDD +JYvhutUzQfshAU6j2kErGvKdZxWGezab34vFyMP2oLGqswPAJrRQTm92ZWxsIFBy +b3ZvIEJ1aWxkIChDb250YWN0IHNlY3VyaXR5QG5vdmVsbC5jb20pIDxub3ZlbGwt +cHJvdm8tYnVpbGRAbm92ZWxsLmNvbT6IZgQTEQIAJgIbAwYLCQgHAwIEFQIIAwQW +AgMBAh4BAheABQJIFkiPBQkHhmvVAAoJEBTCi8l+LjsFn4QAn2wgOHudNubNZvTz +NdaYJKJ0m2qnAJ9hd0nQBhn28H4Ii4a4h7kpGWRxN4hGBBMRAgAGBQJEexD/AAoJ +EKhO2uicgArKFLwAn0B+g2mJ5n8LrBziTQ5SjnSPyDBXAJwJoYTta5Sfw/3vVGpU +fJAKVDoB9w== +=MWDN +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/gpg-pubkey-9c800aca-481f343a.asc b/tests/data/openSUSE-11.1/gpg-pubkey-9c800aca-481f343a.asc new file mode 100644 index 0000000..daeef8a --- /dev/null +++ b/tests/data/openSUSE-11.1/gpg-pubkey-9c800aca-481f343a.asc @@ -0,0 +1,37 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +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 +=mY6G +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/gpg-pubkey-a1912208-446a0899.asc b/tests/data/openSUSE-11.1/gpg-pubkey-a1912208-446a0899.asc new file mode 100644 index 0000000..8467c19 --- /dev/null +++ b/tests/data/openSUSE-11.1/gpg-pubkey-a1912208-446a0899.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +mQILBERqCJkBEACdqhZWdAbUHLIumXMEgv+GFjr1ZzVHgynnFOzztU/8sxZNa9cm +YV4HZpVfjMr7fos3ArzyiPPt/336cf7w9p79/ZS4rHSNPDMlPCtXYvFxUbvU0/GY +q4jwcBsrJ0xaJ9CP5bWyAgVKOb7Y6k0ktaLjRR+tDfMsHA4H0ClMoRr6ATw8NL0e +VCfAHuzqCKvX1If8ng+wTivtAhKvz/WwQiELNELmPfc5tZHOw8NgP/r0Pze18Hn2 +dlAHu0WpC7uoR00vscsMIJiJJPcsxbL1F1eADKnk+wEy8Go+EJeJ5i0WoFbqD52q +Lv/C/oY6NVtVY0MBwtn+oQNSnQ4JBsB/Akdt53LAi0ZtNQxMyUW+76R8FCOmVCV8 +WGiF5CPRP0yvG80AMBjBjKjHb/v8ov5MnIyFimzAHS1gQcUNxTEYA/5eFwoYcGcK +weGq9FUjPTzLQAgvp7XmOzHpSAfJ7qysxFTepNsSZZhgizJyInrdQldr+GYcUNqB +krD9MWmFop975OxhCTEnNv/HcE79r8WD26HzDFYxTiTJbr0pU/ivBzo+rjq+YG2V +stJk+udVYmZTnC4LmXus8JiNuqBXbxNscwCBpcJ8YcfCV6uh+7E0XfXZsgVUFLp1 +NF+ylYRGTycOlWoZODrnJevZW7N9O3bWRx/G2P4bJD07LsDLe4i5hymf5QAGKbRQ +Tm92ZWxsIFByb3ZvIEJ1aWxkIChDb250YWN0IHNlY3VyaXR5QG5vdmVsbC5jb20p +IDxub3ZlbGwtcHJvdm8tYnVpbGRAbm92ZWxsLmNvbT6JAjMEEwECAB0FAkRqCJkG +CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRBHijLooZEiCKSFD/93vZHCAMLEfksU +KnvXl08bv1rfuamuyJnE3ANRE5RDyypriHMCnkVxazvQ2WI4W4UEjluL9+SzZwtV +ZvKVoAr31614nSyWwv2YnJTHfjMG+xRlkolZMnuIiB9PcCBo9+GPU0ABuzo4pEJW +NIRoSS1NFbAZBhtUnY0cN+trM5QObLl7xXTavLyGk//blkk57fov7GXsQJlZUig0 +l2yt5XNyGpLUnTMDumHh8b389quF+0+ZfdwOy7A768xjipAZiTvIujBrEv51wrxh +0HBT0VGA0MhD9t0B+Ce4BM9P/iVMO00naaOp6PqMfPPKxQQqer8qy1i6UWBx95SY +mKZBIvOm2d9PezDxkckCu61r6krx1iKnT1wdprCAkIYwALK118SpbxuyGW0bhRHc +wsc/akzWH72fS0Xu49mvL4k4A2U9asdeQid3dMgbtm5mSWof0yiU/G4YNn0yeXoY +oG1VbCAqQbFX1Rvd6GITJVqI+ekW/uMA9BP78dF8wBeG0+QmpQnSf+eOsxB/RT8o +Kb4hHY+29MUlg+i9ceVt7hoKr03J/uIG5TXFXRYLaI0iAFVlKfWxpqDfS2XA4+dD +VYt+5RDgBcnxDaTB4FE9GqcYScNfe7+NFtL0p0wOPftbmgZzGjucTmrD8mDUNdqA +xGK7vlk4GATSfOQlq7G6LXW6RYnInohGBBMRAgAGBQJEazMlAAoJEKhO2uicgArK +2vMAn0TbVDESEVKVuFZStrfIzOvJQrR9AJsH733Ju1kE99GFrdfCeGqpckmNhg== +=E+qN +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/media.1/media b/tests/data/openSUSE-11.1/media.1/media new file mode 100644 index 0000000..e9c8128 --- /dev/null +++ b/tests/data/openSUSE-11.1/media.1/media @@ -0,0 +1,3 @@ +SuSE Linux Products GmbH +20080918201559 +1 diff --git a/tests/data/openSUSE-11.1/media.1/products b/tests/data/openSUSE-11.1/media.1/products new file mode 100644 index 0000000..ec71eef --- /dev/null +++ b/tests/data/openSUSE-11.1/media.1/products @@ -0,0 +1 @@ +/ openSUSE-dvd-11.1 diff --git a/tests/data/openSUSE-11.1/media.1/products.asc b/tests/data/openSUSE-11.1/media.1/products.asc new file mode 100644 index 0000000..0de16cd --- /dev/null +++ b/tests/data/openSUSE-11.1/media.1/products.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBI0qRLHHIcJFa0F3oRAm+dAKCLULReuAU6ZgUPJaYRwKuU9tqFfgCg +mqQniBKmBYN23YM/PTIUhH7yP1g= +=2Ub2 +-----END PGP SIGNATURE----- diff --git a/tests/data/openSUSE-11.1/media.1/products.key b/tests/data/openSUSE-11.1/media.1/products.key new file mode 100644 index 0000000..f0bb55a --- /dev/null +++ b/tests/data/openSUSE-11.1/media.1/products.key @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +mQGiBEeWWzMRBADU8l2IckSzgdUS1dn0WMM7wXK4seoFsHHQw/0unHCQCxpyDMnn +TKV86p5KTbR1FDdeaZlY0yCV+IGsiIxLyuUdJn8vuA5gA5ZkUr89/HtWaeZVl77J +HIQxvhDRBWCOO4QNtrZYWvGbvl83wl/zOfdLEs8IGElt0LgfohyTA1qfrwCg/Hac +tDDscXsPlo5Jek/+3RHVeD0D/30riCpfpLJOmhraLg1EbWsE0mN9IQsl+WDPdoYo +bB76z6eH3e38618WzP/LTG4WuVbwpSSqmXyfdVpXxWzESfT8q0B8CGpHf/Sa/T/L +emohmRnLvkf/tAfxFmDMm1jOewJIE9S35jANGHVJcxmfRNpPWC7uHnqjopnsmDkL +kMEdBAC6YcpDOcMJZ9sJbt/JNZBaoT5CltgMDlSN50t2v/J5em8qMLqCSNF5UJyd +LFnePHTHy6gVjWbqcC0ncFzOqM1y644Up7BoKSAr1hRTl6Mw9S3UfZZZ0al3JtWt +8y0eFIW3QP66w1AL0LO2bZMBuOvhb63DXv5iHorcxk0yIFbbybRCb3BlblNVU0U6 +RmFjdG9yeSBPQlMgUHJvamVjdCA8b3BlblNVU0U6RmFjdG9yeUBidWlsZC5vcGVu +c3VzZS5vcmc+iGYEExECACYFAkeWWzMCGwMFCQQesAAGCwkIBwMCBBUCCAMEFgID +AQIeAQIXgAAKCRAcchwkVrQXevBsAKCOeScnlH2fWVBJGHTOVJ3M4yBqDACbBeNk +PuWo05AOQ3M1dLE1hkN36G+IRgQTEQIABgUCR5ZbMwAKCRA7MBG3a51lI7PfAKCc +9ZtKfI5G/g66V7pSMXh9gi+ykgCgivPfGMDh9HIROwBIudo2qGImOqI= +=htdw +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/data/openSUSE-11.1/suse/setup/descr/dvd-11.1-46.1.x86_64.pat.gz b/tests/data/openSUSE-11.1/suse/setup/descr/dvd-11.1-46.1.x86_64.pat.gz new file mode 100644 index 0000000000000000000000000000000000000000..5082f149fd75f59fa1e43da60c7df17fd7eaeda0 GIT binary patch literal 155178 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 N*^6TGK5B^gkm-@`V8vh2P5ITs%?m4$u?9k!<>w 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 z�^Wp${7Qd0hS0qaCE*qOPFU>fyP)54Rj}9-N+ecwpw?=escH(WbMHrY=1EeCFx9 z)h|^;sUzAK2lObcMmVB@QCL$IF(sRBl9b1hd~&svIIbOF6G za;N#z*H5tpWo^AlRz^VkRU7}B{$nVs*jHg9WL<`$XQ4yyqx$4Dyt@t(XYpaS*y%eb zq1{=k;t4fa6l(b9H9zehYw-?+?r0cwZXWbTnJ@v<;nv4x;DV^5T75#@mY@?PQn;E( z!6{bCDAsr*3A$g_-Dg+d#b**^zdIMHmeY54-rWRQpUSy}gioP=_PK=2_tmJ{m0|3( z>8v||Ad5U{`kM^M%)5KDy3+oX};lHkI)oX_`s`2~hX8KZ?{ZT5+ zfDL;WSXzcM=?|pW(W5KyOuQ4yBM<2D0JL1@_(V(4q8DhXS?I4N=PJ*pQV6^Gm>MDZ zs#P8I$3E0SP(vTOAY;0uhR2veGg-}DFnZ3T%cmA67@!Ir4;oX zW`VMMH77|hJjx`{%_OvP@sNpxu+3)|mNGBm1IUV{7jK?3dh=Ylro=KMPPuvCK!G$`?y@oDiAIz@m<^EYrp6W!iD~V9f`y%Bbt9=wLd&o8Ocu z@{UDu^Xckb*u|aPY5@L^H}}mr;R2rLH^B2z3V@Pf#J-Oh2XD zIz5Nzm(iL8uH%Q$k_Ss2nBR;58v8dU3+pFx2i0$Lsix-EafF|9m9r@O{(LOWL)kg` zOX?ull^VGotRG`28_Z6U;@~K01P;tipTHkeC;r>%7oOr(8l3^5tUcm>&6Mf`zBt21 z_zCaLn6rh~XZG!SxNqj+o~@52kN#@j>djt|Mxpf-uguui>@T2;81ZsnQq7am+$9;w zrtxbo--@K;LZh(5!r2L)?|0bN@BfGCAo9%UFQtQU7a)1R#Ko9a6x8t$w72(6>la9K zFoQM7PF;e()A-B!J&%12CQ=iVS!?cBQNUMPPETO&U!*3U#`8XV>Hw(hnzj-y-Q7Uw zKYa$1QM94ydG*Dl!S@bsxVP^-i<$gncVBY#?mK_)>n)4F{K6t9b7T{0>=8uyrROEa zk0l#kt4dg?f$58!Rund3FE9{&j~c*#s(oVbVR}1?Jfi}^SP_~qREbcSdz)>6$TVIPk?rR3IELlxTbyWR2TH(SclJ%}I z+pTNr7AVwqf#Xbl4?T#102*e=c&pt#6r)gdUTI!UlfmVv>f?lv@El31GZ7YyHkS44nc|sOKxnuyw>3-)(6!-hpc10JqX29r!=%R==5 zt=!u;Gk^Kg{r6AIe=%*UJ>)*R|M5x8R4R}E>>g|eE?q21npxWqU1#GBC#e^ZPNaiAn2-cOzSNIE3mu?-S2cfTE>XX}> zk+xbDC>L&BLe+;*pfGo3XCWEYCD(7Sr)o}++cHr-)z*&=1?qu1p^N7rZ<2TPc)lk1 z*b@E8FFBG0J<2QMZb++pEJQ+=zawJNtpu)l$h6&eGgvH1&IuZH2@WNrfcDY-C{&6^ z5j(cLP|q821E9^R3$Jz$ji+h%kX^a*YM21~7r=<%0B0?y{#+#WEp^YLa#81*{D>r{ zZ^4iB@!pFcdwMDLrKX}~qI;zY@8fhOq;vr`6%ND+7=UuE3(RIMiCS(WYC7T|g+JXR zC5o0e!o&cfKwiIxLm71`&|CVOlh`N2=SKYT*v z%YJ@~V&7%>K|H|+-|xHf{l4`J-lCw#UqpAanbOy5iJWJV49h}J&wA*0rbJ1sTzj0c zwvN+Urpx*H+AQi?PRw#vsi?()xmSgLKD+M0S4SW2`%u&0;I)wrTNkIs;gm2-oEs-d zp>y+$q0oUxI0T!1IF6JFhyf(v6*HhhD0umquHhk)$jYQ0H*StMgB!bT8lKnVEDQq= zPG2}h9dVBYsBvo3`EbS$ZMe0wntl#>Bjjs7X7tLY_u*gY5wRaxPzi(zo}nlk!)G|y zsg;zD>4L8`$t|Ri?s;)t9s!09h_RyIkd(QDbSQfrp@BKfo|&5FFtMhmErks}mg#&B zE5*$&c9-S5BU`HSLBH<8FSYco)%gmtNu30p5S0lFqN1jUk8e2cOaK{k#{_*vE?HCk zpk+%u;SGhTZ zPUW+3>xHA+H932&8LkAv9>997`EI?u8#ztTUR1uoe^)@LMvctXyIbyDWH$szKCoZw z0G{5iEs`n=UA(w+9csG-0s*~fR{>GYBrlvt$szZS_64Ty#~p?7x_J;JsKl+i`rQwq z4C)@MksOnDqIf8iB8)TP2GPxHAOc*4Wdq^@ZYFeFcCb^6I=(Dt(+eSysR!LdjfRU< zCUINL?uo05NI~SLObT!r;nIZwF9p&9A^=)TT2(`P>H5V^H778>VovVv#KE~Blt)nN zv|W9qW}+Z;v9X2eybAwf1wGuO8MA_=^6#pd>8&7w;pM8Jt?Ta}KY0Jc4fDGXGf_{a z(+v<{7<4VsPkT1Zf4He1T@f@f|K+Dp6|eu3gD6K{Jf?%=r4dF9p&xkDxiaL3#IaUt?RKRWyNI<7Rcf82(s0L`l}4>r zY2bmdmR&l8WDGjOVKeqSh-z@&R01zS1Jh~n0^fRgk643i&tAfl5Z0ew8 z{oFi}_4J__|#v3B@lO-7m$>qtCyL=jw5;%7}Li;VRp($p$5 zQrKD(Y8Y5?>LLri&Y!eCwq#^Bwi1PBEiGmfj1vDP)~4_|CgVo&bt<0tYUPh=&5Ci+ zrmnDNpJ|;D>a_>zqJg?-pf2kBdd(soc;P!12VN>!T)Qc|ZL^3=HpRO&eO{@_-K4Qz zpy}({OzyUf^^(jY?#AS<#5`8q7*&tF`C`5B(&L^>+4YwGZnZpFs2J7#vg<1S+*0ZH z+DYNIiM~?BHIqf&E-79rDZ5MZRD!=?O}}X97p;L`I`E6$)Kj@X^4~7#i#9?}^AgE3 z74Sv>#-|+aMX$OK|5>#ApRrIc+9y0-pcievpRF)2+Lsk?r~Jc)c;Od9e#v_&zf_bL z9QY^nfkkuoTSs`w^E3s&|1!~C7=7v|wu|i!${?&uA7NdzIsA2Fy66r6x)EKB zmY?Y>Ed9rG(Z1;^M|06?{zYQB==DE)S6TXqC=wk^3pQnx{5HP zPYg_-?g%hEh5d|b)seKNJ;grzEhDGU69q;o+*PS^6q!9xlotBM{8!OWkfHb`7xb!I zO)_+Q#h#mm>j}@QYC+z{cnqzAy2)X?U$U$pg#uku>g#%md4oc~l3~F5#?tQm{q3A*hNwY8n-I%CFH*z^HrzEvZDth!#Tw^Beasi_5wWMhvq zj$Y3%*AD2V_}=A1Wzi7mGym8+0;mLvt!X}nfK)f=?E`J+v@*rqWGLb#6{;uYiiB^OMZX<2yq^x)iB}Q_I^U}mjk|q zN`EO_*NW3(>+qUvesK_NJ8DI>D9bZ5{i3ZJ%IY$X2n(rdo*t-L0+M2rP?v16#DPB+ z`(gHdN3w&9M?0|!D2!FW%Zzn|bm^A=-p-APrC$1WVT4l|SEse0k~R%bJVQZR85;BJ z4KJ;DYujEetqkL}qKc1&eU_6{lF+R+@qI3H!Y?$whCf-ojepiw(t6aYq(1x*aj4TK zoN@54-)g|WsXG*Sl{84GYF@;L?yzQ6#qA(#7#@LEHDELL(Lq=Z;uo8F;aZ1H5qqHZA#8?KC1R}z17%z> zqJA;o>RFjwvo)k1glRIaCuzmJR`t}V2v?Z=4eLz)rqw2%q$#tX?};xzU0;Q&Gq@J{ z6Rkq=akLi2gIbY1rK5g6lfdejH#7iN2f*q8SnUf~{dd?cc2xE6z($<1@lGcdpbBpj zn%d!?AW&3Dx7kf&a)0nClr*qYYd3Si>6m;6=I-A-Z^$nqrr3jp;8NK(ZVGHT50qkB zpVrc{u2D8Bi$_RJ!Sp>UyjkI;5BFRwfTcID`l0WpaF79iS%#THXDoOrPH2ho^f_@a z_vm99Pb2pnI{*If|6Y!h%Hb*jNki9p1HrgZ47R!B)Doaw_c5;EYWWJ*fKwa|1)IXt zP=ChMr&$w|7%~e)k)3x=8?Y(PxCJx4fBy7O2PT;+zfa&)p`~MN&w*@!o{O4pt$XZ= zU{iM(t0XJPCYf$37cfr(nj%IDpYMhoG*$j=7Q{($)HE;WI?(uw8AYGFz2Vj=sOkzC zM<0ix(2GR^q6_x>$&HjEi(_u;3$hRXMtDZKFgN}6 z-1M2bsgF6}Y5GU`M}si2B8RmYU*Lh;YQK|s zamR~$IRk%5Id*8{y|86mw9>6B$(*j9)+>Gzy@QfV;HKW%Wn^FpCrMC!<@GnJ%hfT* z692Sj8s&pt&l0 zNZag3qt5?wlU4T6;<bR0LeYsNsx=X!W)I^@C-GX^!w7#!{rWijHCC^$Wxv*n)+Pwd z#u97gYFyh2&_ELxq*%KYfh(4et*HJEz0|CGKqp{)U#x_ktdd48SgC&yf2(f2<%d-! zK_oI&JSSc-Oluu~KyP3_)cpqSie)tB&nCc)Z0=(M-11c`!2MDm05=M;efSB{Ne*vO zOs~Ly8Oaf@IV9l`zBer7N6%73sF12iQ89}MQXyF*ONBf}oQlbU?v!RAp(@V>a#hR( zqGcvB(v?pW1WZpi$e75$4W|8MB+W>fSf)P;@@AwVkuws2)alPa=W>sUQC?pIf&}W1 zNC@?3P7aME>4BeU;q^BPrJrmdf6Qfo90TVkL#8mNs1 zYNNi?M*qiMy=Jl2`1nr2^HJlCWW$Mari!|>WI3+GgvP~%?bR%mTVH;q=uc*U$#ZWQ`9;m41ssbim?EFl*)AjD*C zda0(jNq+w6ZL_&2)?%So9*lHQP-dYL3zBY~rFaBvC@fJFC;=WXk@KFT6wLqwLSvK~ z-htbbx3@vVSID)`1s(_C_WJz5E%M61QyIP|SEjYPXQ25g5yXE9y3E%?Bw#wW+OV3c?b{olv4e>IGh#f(=!vIzdth z{yqcW%wjHh{u65Ss5d_4@KK0lpam+x)*7n6eT3yPocC0Fx3 znI6#L)t*q}MHecL|9JS={PEA`rZ3<7dds~{A8OV8x*Eh%UY>H{mCY2kVJn4d*uy@j z*bg4UVgEWxU(Z55AG2jDP5O`r-yDAM$)?5VF_$G!X6i;bh5fGEYl70$mQ9*C00BawMiQSd@UKK0T2#+Vdaj}>3ebP0m zoclaZH#iQG+VeeNKoyUoRHrKH04h)M$2W!=b(Vxb`2S}tV1m-NE_t@pvlQTfuB9pl z8ZU^@SX7-F5HKKPK+L?Dmt!8xfm6y2=NIK?wNs5?w@Um`^cm&$~|;kX^TB<&i9Gx{aUH7m8$Pp)B>BSt|7 z*ofWzfJCvo+w)$8$RW^aW85xF4?@^9hEli;-Pwd;#x)N?_R%X*VbgxQclhA^=bx5o zuUU~@`f&|qj&J_)@9TeBzYRkZQ2AbZZYDa)#_pe+vFf@1>&jNW4aN^(fpatW)^8~` zQ+nOz4^rigfGKI8SU3Xqi2hlaKOgqoZZ@hzepn|FkZCC}!ZpjRMX|?GC0UtKK%D|n zSjY@LG(>3@)BU8%RQH9fc1(6Eg>;O|;x^2_kj6)JU8IetBhZsvD!HJMX-PH&O(&?y z2mW$myxlgcg|zX^H`7L7P8XLuYPv0(Pj=5=!JY(w!J(Ao<{~aBja^_GZ`7yEoGE=H?<@hTT1BA zOX5bTE%h5|wHDe}BenKB^)TUPOg&Xwhj_pq&Ldo<0I+x8gX8iv{VNn*u(wt-qbRA* zV$Z`_*kqRDO0AX43Hdf=$uu~lx+K`=Xw{FWbvQL0pAuSL8mQLmT9 zO8@nypG-tSqkAyuo>8hU=nFFsPP7q3G=FaD90}te-aE4Y$LXuO>T4It!IKm-P(u5; z*o91JJ}*U3A)0R2gxG6JRrYXZ?}O7b&d;+aAH4Ua(wOm~h-fTo{%EAB&D2DqKq$J7 zxWCMS(eM&oe>O{^(mCc$^;;61c2MdSlxL&@?KNy|l*Vujmby}*K?b+|Ty0DnNBC8C zVPXm2Hy1Rpl^C7sG>cKC6lm1C&u1{slqSu-sI|bwtg5TPE8d+EP2Jsj_ftc?c5m;t z`S%Xa?>;>Lo|;$=`~Ps|5@yRhu5hEH3^pyN(c+w2@uyc-5iYvot<`b|3Vj=8!dGIR zzH61HjlE6<676N&zL-VOJY-glOiyHHtlg^KE^XHxx30lPU3cpOY}RuKMZ# z96rW24P9L6r+A#W;7qbo<5))N<0x&EKBMXzAA-A;^_6G0`PNnHxz%iwQmbA{rImV) zYW69w9VJ0_^BSDvfu^csl_T7UwKt9ZO}e_eq(W3z-3?XW{nX6#RMse;0nHN%c0y7F zUAx!UK4-Nlmm;zy-1?M<;1RaL=zvoDu`!6XMdG`@()=0gBpvlaG4@CXSf&>i7ExP# zp8`Cvew{oh<=<+e0or6Jji0$LJUx@hL1{jVYOc1dzFCy6PoEuE%j(GQu8kDFEl&;D z>m-xQ8aN@K9CUYpA1|qbp$23{K6sCcNaCPt1i4(@J;us%nzh7f0*`_2>^xk%sSC2U z6FDqCSnAiB-6KxYJ$CcUr~|)3RS5>Nh&mYlaKwQ`knx=kNcir}gBT;ddo1;rI;*4X z#x|7heFtcC>SASTeUvoKf+V7YuQ-}$N9ahX(>;hyVk}11R)@D>Q9X)493oUYDiBi- z7Z>MaqBdo%7!TbRbox)wvh#|emH;*igQW$|?{K7kPpcM2!w;Re+?MC8CbSDO-&*~9 zhn6xzVN2PtHhgTu)Kem$)bdi^rzWaw(w3Vv{gA_^Zc6tb8nH*gD_XF8fyMwMP8!Z7 z&PXR>8;jMB0nB0^Bw-k%PKI?J0kR&ox?cgSV-?_)i-UUA?kjGhNJpQ)M{s#I0R$h zrxb5KUE(0l=p(j)1@or#POn2!NTmpaR{?tTno+mfGAoUkfRSoQZSpgFwL z#@fM4KBBz<7ao^5V)5TUSn@1<{Ux## zxW2@J(OXCAeD-B9*|LvV?yTtcWg5Ecw>Q9llVqPD-kZj6gSSuII!}MeXyFRBcO55( z#|1jY*T)ikVLeUeIq1bCIVGfyEfI4K>x8EB91aSUy^7ybVr4Mce2=;L3Z@fsBtbLuikS=t zL+*zle)63phPNHXD8Rc8>TTM{VcmY2*Umm|G#j_UsoM@dkmZOihEzfZlQY}TpPN!VH1wIS@2EeU@9Dv3;;{JT%K%wE3K1n zsclISKlt#6YkPQ^sVQs-`m=75!9&oO>CJP~ z2gwZV%>0Mjpw|26U@XqeO+v>%nw#1@H?8Df}q;*t??c0UMnvD*O;8t31=fzijM8DV3lK4op`w7|SvEQ5c65T)Z{r-(2 z`XDs^2{gG;e8Wy!6l_WDrxYl0Nm%@`S=vo+LS0)}^RSi5Z2fTc^hd?GF6P0m57C=5 z41|?_u~O*Z`R8*-AD-XwXveOfXHN>_!9sY$3$qXYe(~YH^$)geda&gXJ1MaGN0Von zb>YLEvryc5c=_z3PYyqtIf-tiAIu!0Dz-kFJW6h+4}A1+!?s*Y%;XUMdvJ!uL_Dzf z=QHQ9(3t~EXdba0pfL~seg(RPMIL-G^Wez#ho3`ppPzm3)y%`aR~{VP>pVEK?$PdD z@aDr$kIHI}@E%)?8CNOS(cBKa4Sa2i=8MF-FhIJ`vqJ~55&5&88tQ~i#W5&R zX(lO!KGwtTmnD!Oa!erNu})yomR}DPD2R1IS%d}QxCGwB6TqOyaKR-`()JQyi&G65 zw7RL0%!#tSY){}lUS@ddDM(coU~-6}n*9u?M@H}h9Y^W7*MJWBUOhFfIhC~RLbn*F ztfXb&#wS2b_SA5O1Si5Dl$U8Rq2QQ58ZdboM#^UxAG|w3rldNCiv7i2qEM8$1)EXR zw34eOo&Gr!1jV~&;&CUdL#Z3P+h||e3(6s4474?%Nb)A`sGQ`U)U9)OuAn{gS#tT#tX;R^Ig8Slx72Y~Q{UY3!v)#~mc-Sd6{L;01&@T>Nm%a~B<}9c9yE?^1DthOV`xIo*ZAF?YK_D1i(~|p-xJDG zT`czJ#9BxD^eXO)yF2f0r+onlupBodX>sm;iVOV;`G!L)ygR4p7Qi*=tJ)UKB%PKW zF4-&e<>&64zdH@9^Q71a)H=p@I4jN9sS<4`pv4j^bNV^C7p`I21@`F|$oBmT`y9S8 zSbrf42o|*qRbjhg@hh5|w~PPr_%$?XfA8?Ub(25LUcR^Y5;t<+_Q8+GkN?+|O*rQN zb!D@(kU&Fq3aUG|Zi?pPhuKT>$G^C@=>ojVAQE1~2UGWUocymVTYtFx<^0JF^T(%u zxP0{9_Ve@Wzx-i#-4C?|pjy$LqU(xN_j9bsw{C%zwCT{=`Le zH}}~LGr+ih@ZRJJEWYgwuG0CvC+9z3*UJo_8`N*vac}(=tn|o!Zdt!=JERM84D~C+ zuaCF>bYR!~{{7JU{llm3pSgVh+$o~LvIu@Z#s8Hs6#Hmi^#{}UcFf*C_tpLFhwp7V zfB)MPKkd2v+4&DQ&2Kt+|NQA6FP!*c_85E-e%}1%jaXvp%ukd1 z?w|V*3b8Kpox~ zcvC?e)haSd%nzk1T=I2yI>EN@eRoD5$Giq&(+CDgk z#|P%t19R(vx%EGixivYa%h_9t-7FUS@BXr4`KsS5i|XZ!ZN0ghg%U0nBHL?g=qHvEv_~zQ5%=h4%&O+r<=b0fQH5Je5&(o5XBe{!2188QeH2D5}_ehm%9sNRiXmm?IQmqSbJRhs#=gI9O`rfU|0 z<@QSVSPLCT7_YlUy1~AKZp5Et0TDGiW4x%$x3lEtRMv2stQX`C+$@@!>yCA(dj^T2Sa*XgiRS^zulH_y&&4_AinpK9ZK)g6+52BHcmO%X12Kf6wvxt2-o} z0*MF9fW%|Q2HA7`r>#m(5EWTX!Cj3G9T|xPX$3((h(N{;DKT`Nw}DH-YL+_qFI4F_ zM$$14|JBIE@)|ma(IjLzDmvq^AG^oUgxhI4?VG#1$C5N_XYde(0b0oDeYo1-dX4qS&?*)uDd% zRVjFx2o>Xnp)9kKD1=>s20YW5pQve1E^+}z}iBqOI9Mk zGBiuiU&&bcQsG1=D_ZrHWL&(c&$LDUMz3GOO4sQ1?RB>&p?lM}PV@dMBV^NRnh#a6 z!;7)eeFmoV@l0S1PKivPRHt7JqzNL6G=Uw7w6Dd3D}XH(%L5GW&hUu3tXX^q_Z4iY zpnELzTyD@T&1Y3z@;h{+(&aG3t}{|#$eP_l<7oKlsSf`OJmQ5pLCI2gsl)cVZi(6_ z?V|eObUp-BgWH?tI+6J!XcC4c5={4+iT^}qpLt#qj>MXNTo?wS&%wZU4=06}g6@$9 zs+sw8z+u4VBO!4HI|2cH#_|Fjr2W{cWMqB8Lv3mQDerp2SdP@5a%jbL$I z=^o~rW5R`fjZO0HK{kz=QKf2-jf~B@P)>mvX#T4nJbwQMgUVWPQ71lG6@Ehogv_Vg z8S?d3)}c?B&7N)?_|s>5(BN>>5%E3Oo&}pdlyB&Vw6WSnmSel+Vqk`Li&_n~PHxwX z!M2-yuv)n3#%%8i%e-s!mhL@QnHQR$vqx0kZzwCd=*V7b>L|vv+Huw<>h){irCD}i z#lP!s41bT7Sr2y|CJV6HhoA2%cH!d8!}kv9W?cuI2RpXPPCuS?R?`qhpM;+ee7sv2 z!Xf4nKaUnx&1fiKq68c!6voMDP-pBHYZ)ae3a4st4ryKg6Fjk#QgyRW9zTlfsnhU4 zKJkG`rw*i%*KoszgPuVPB8uc%EZ*(p>S7-0m}j|-$@FP|~Ms3v^_?*8HqPp7TzUx4!-K?+*T5d>LRvN2b0zf~{_# zua+$y?)QtYi!YgS*a+aw^uvEw-zn3ecLrCc|aWv_|#u?L{8qM+Apkj|7iPEUv2=CW&QlwEHBsPdT`VjDxgqz>iqWL5&}g z$PYjn!$T7=fqkIxK--5&YXr8I(O$Z8rNv;FbkkUOMM&CxC+iwFc?fr z#NjBkYs~MmC|KMYNL-W%2n=J^G|)C-VFZO$bu28lLt#&B++u+l?_79Xa1Uxd59NoBqldEVZ`_b*-7tL$aL!DIr}J7&?517mfIjQgjr-9LGd z6_`J^YyN|s!q|gtkNFQyU~jH%V43$XeD=fad#pHCwq^GdSyCuJjA4?zLs98a6^=ia zRoZTgC2==tnubf17Ga2ZNu^bnwiLg%t8XADXsBpVFbL4&u|tB@+eIr{=g4=2jl|2?oi!?5H9BNl!O%&Kn{`Iz~w2DLH0_2+{%(d8+hOf>PhO3 zMPphBC^=SareBtW#r2xGd^MP)%-lyuDzXB|p`CNcbaXu>G2UqQ&aASlkQ?HN7?$oC zxg$`KiK9{vx`!GdX4Y{z~8nIDn8C$x!H7PgyX5;Pk+!M)lZO@}_=kK?-k&fm9x-v2BE6P8Cj4QaG3!-%`Z#0TQeo!_Q zYr2Pg*wk*C)uD)+B;6}eUR1ygqGC718)F$lpII{6Jrs|USE5$;kY-w;`7WTg@TPs> zM{)OvGMRYOAG-Nbr+X|VTn2VN2DM5igfBC)hY)@_eBNchfwj14r0gN?Z8q0`V3)Fw`1$0HN4vK__;9Zv4iC5N zefZv?N9(oVRjb^F7n9;*h*1hBVV|Y!BQOXYE|>dYnBmw5@)d-6S zeO(ud&3T_nG~)W+kx(;VY6vi;gJagVh$;V#;SX4EBc88gOmC#uga$!0nnC<76KSKYsd?{ zQPc+lg={wEB~HTz;ngr5=^hGF=9&dB2jc1L8srRtkBKbl9!e(yzc%8Lp&j>o=5Y#G zRJE@ef&Rh&(LIo0%-EvhofhkqRI@<@JYY18a0@y259!`ltqJ?h;?L`&+v{)7Ao0W) zQ&*X`nY*7ljqa<+C)Z|0a8GLl7l^G!a2*O%Wm>7CXDw2Wa|cA zT(#YIGY`+N?xoZZR8vNjsqP^-5*+S&3eJoG&J1@n3SGbHl5s}y0O3A+pkKJWP%G;M zSu^t!-*v_VpScl&Gb%w3K5g;~;Fk<>y=3r+i_OiA7(-MLQ z<%bz+Q{&hg&Qerxo>74k9n^I;yGP(DX!+chwtJ@I1~z9c|C)K|YpHwK@zs2Yna&+~ zOK1vOQIMi*l^SfSH07>US_r=qqM3FNSoDlPT)RHM>B!vVH*?b;q4STaQ{?$$c5dq9 z`47LHn_5>qK2fJfC+ngdlUP-JpCFsfT^&g7y2p{cli2b-$d>aT=Y`d?bXf5?$F^e@ z)txr1(>zPa&`QkWS_F^c-MuPamtV48>iD3xGNs$Yy$48T1&qSASq!9fVixsUk3Km1 zXvbknX8gm0{U;wyuY0&}MsX4tmFdy$9S`??*{>GPq7O34eefaCx{tIJwZxn)x!k+$R_X?sxALG{NM-yNA` zIwYaPnIgRm)2QI{Ua3AY)J{G5qLWm3zfjN|&$CKB^(sBNCuhQ`XE(3hSP%P}?x@4B zc04g&cheA6A@Kb^;_+iPZ3vNQAWo5_2uPCG0!e1~i(7&RBNaj`^HZY9wJ2q7|JYHG zO7fLgR#@v#CGA%Y<=D9;)Ly51kRJj)8qBE{jv#W~s~AG~m)&VRZ9a zl6GK}$Y4Ce2&a-+Yet{kH6&dS`cN=Ff{cvf+y`2}~ zg!yUr%>3+E^Vc@bANp*5>-wGng4SW}l3V5t9D4t!$t^!z-OJc!x)}NGkB3h|b*up_ z_T{Gxc`ty}wSTF&ZD2KEsWOoA9VXfv_})8FJFO&R@3hQ{&T*c)?$U|Gej1r;|<%ccaK(qBS?Vo=A1nj-oTP$1_pr}?u(r~G{hUO83&x1> z;3OHTuvjVx3Dx2#tfX#S8EbfHMT93|bqz(pk+uUj8L1A%E(JQN3ZT~j^4%bDtL-3b zK({JM8oM>Gk^zf{P;xq)R9|e+xK!#Mh97UYV9?qyrszX_IANFY@-1rPR;fqHaKdhD zHr%mhrBNSh!DqpVvo@{r)2RZC)ljV(L^T)2tAQf`|2CGvKds7$8&pQ>xSlHhF!r-v z!F%Kw_XQE{TD$!M{0_6VRX1&6%oi9swC$*3f2y^p?o~oBt-0_y!*X`vr(bWm?Mj%` z>hzs#+HizwI`q!V)7aP8pP*f7*L?QP?OFo;#(-As7W>GS53_=;zEevBNacgm#`PYz zYjm*{{h<&0YcUs^#YGZV+HI(|4GXv(dqL#ZE3rp?k3GCs10xN|9!z>QL|U(=GHJEn zVNE2B7x}LsNot8-Niq=plPvN6>NW6qi7PnRa7@Ak*S$^!@4&Sy8J;(oIp$*%Ny6{e zcKlXlErxQx#q(<~<9C7nA`z(6e3*<@ z1oL0Xk|7a>YP_9Nl;28HgPl=FiqJm?J1v!16izQJ zpl~v3=|kHjC?;=^=qCTosHeDBOEgrJaz)rBMo;;JK~;Gg&{pvaD6F`%i*#0mNK({R zro`eM8|4)p8Zsg+Nh-{rIV~1Xf+CA&q|5v_Zano9XtaFblv>4jLV7KpIMtSqdQsXx zLgj{ZT#g%1bFo1bP1iJiK-tBMg1*a8QZm*R5McfbDZbcUI^7rJ+=KdyS<&deh^a8JHam%nk--2mcey4#>Gf!i|LoW(Nba zgMrz>!0cdPb}%qI7?>Rl%nk--2LrQ%f!V>p>|kJaFfcn9m>v8hm>rO6E2jcu>MmWA zCRJ(N(=e*P)5=hdv=O!OT7WurV4o1Zulu#MI-CUoQ+J>?gWV=(&-IuBZ=#lBSr+r)mj_* zHubBDj?>rTb2jYO(k%Ak>Z(;MphV3JqDH0FPOBuXqt(D#rZ`&T#jU@3Zv8Ll672Ob ztF&WMM8{E$)aLjDwNVuwo)o%^L2PQ31Qqv5E%v;y0{u=f#CuRlM%ctHJP+AklR)2BJ!J7 z*Ho<Ech}tdxzkjfI+6C@lDvR+{04)auao7D^V}nRO4bOiyrMgpWeyM_r z#QSRd=bwojs8o|Eh;$+i;z1G!sg#x)I2*B$YBx>4#|ek_h~z^(G9n_>a7apoK1k_y z8Cekzg1CrhL1Lt~P9ron%`_)E@<}$s2#|bWWJsvn0%^K{d!GN2b^=OwrxPiWBwIj& zC3M6{wxo7j5-*|rR(frXcqyg1PQpZmoPLQ#V?Js`O^&r_Vy&qXW@JwE7>J$r-Ckfm zFv2Igs*yi2!AJx}GeinS**rm1ebFXI5y#(30oa>Dq6T{4lYQWmec+S*AIT?sI4pxw za0cZy*vE3`As)|mEl4;QNfbP7Y*(eyTODOXk?!VM>F}URBMCO_3LrDSp4iI?`$xAY zZ*L@rs+(_JHB@wk&gQ+XyK!yA@8Aj(in-TZ^g5}%g8Ofc@1dh7>BiIQP<_~kx{%Aa zdr_~uDG2dRS83&5>mD2pn#K+lUegO5r)`^0WUkS7%uTTf#NW#8`*_~aPY^h_pY3m@ zczd*U>%-5l@ZG9(Z7+`pn)`F5V1r&VH*-p@_Ob^DU06@_VP$*sTLB22Ha2R(n>la* z&F+~oyX*4TQ0w8xViqkP%iZ|hOieS}mTJY4^Cf*_Ds|ZE?j_r*#f_O;wFOt?cV}1& z=pD#VY~9?wBMq(Ay>GVPJGe>iNKKz5_sgfb&qu(6vboQ{K`+Wn=@+e3*vg7L~;TeE73vwG#rj_bVj+G^&u zwHXEDHno?SW{TX(-FuHj2zQaK8PxqHj(pP%xz}&hgJ8x8i#g~HJFp~TPliPIoHo6Z zI*HqAc^Fl+)BP%LE_E27>W9rBL!YBD_OnVItz!IE=xSATH9+TsHbq+Ahxlr@HRLYA zn#dJ5ey&Dy(3SQQ)T_A^p)hn_;hm(Ir*DkJUdwsQOD8bwX~B6nX0yt?kSaHPk~7>|UUbnSW zd?nN!Uk*AwtF13Xn7pn1RBgh$ z=b$ea;r&zaA*Z40tH?4s^u^@Fdovc~dPpdxjV=1@hN3XMC9271ei;;e`KijB z^x9SDSQw(TN`Kre(8!W1Mqzs)KPT-dY;3rUI&_F+V*zvGaF z^$Bm^i6UX+`tTasQsXSo(1|Ha0BVM=9bNQ^4L@6%k2@QN$_1&5d}&AcBMQ8Z&s4Zb zazc-aHNB(>`x(tMq(W7ZsU_&&8|l)q@*IFMj{`}lzNm5Z(GPc)qPOfQuKOX-stoE$ zpc+_rt?oB1@~NG8Zno5Ug~gMs;ZR|9(wVn5*g&+^Xd5cr<<2m2Ii_c9XULyOBRqXz zSlkKte-y&pjSv%rKBm#>`jO7fkDO$pd$5Hbx6d@t$2Y2b&rfvEC#+WGUK?hydwyt0 z7D!XoIs9h*I16yrV8Y<@C(`Z}tFm}C^JyK?o+FRfQPTEP@~n#~K5BI%wa)9AY`3n7<#=cYfMn?6Q*<1@q+eysVW{>sKM<{Vlp_to% zWQ%uZgvNXw%H~+bPHJ*DRs9hu``LHzpma7oGnDd)sBj(sDwOVLtUk5H$4u!C#F^i4 z?aP_Iepf-=zf<@(zaT%1xGr3<)GnmY;Ib`K=VRdqQ@hx4gv|+QM(P^Yh8w4?kb$JeWB|`uwerCXYV+^h4+2zD?+x8;U&ma@Kix z`Rt=l4nLYX2`xDf&aZ=Cyml&k;G>@}TtO3oQzx-&4?n+39oe)CtNHo#R;Q<*Zi973 zN8P~p0*?&GHD{ec*gZDZnOVmoha+qTV} zZ-4*MuD_~}x}K9hd8)ea>sl+x?Gn6m;bz1TcH8iRC0kyOAjcD<^%ymd7FM!>@=LRR zIutmNzHfFEwcS3FP@Q?eaR)LxTyVgJocBti1BwsNh8yL}Jls`Tsbe>$)mG6hQ!|`h z>LdUM&s*X`nO6=~lJR5)@@83=QO7JgQX&wDB`6<2dD~@xOC&{CK<|Pdg55QN#Y>r> zoXMm^x*w)_MB1@qyG~z3eZ44?zQ|bvquT@T$DR~+VKYbCf0N#o;ca7QY%#ab;pEm8 zbjNgxNYl^lmbhx3O**_W^W?Qr++3FZ*)Cafri|{k&F-!MK%w4vWEc~Ae4#f;5L8-ZtEjwSoh^K^u|1fzCqH9X5MpNZ4X;W zcTJtY>ZoC6*i2_EGDtba1j}jGOg}{j6We+UixXkEUBoj}cBPI+4JL)GaZiwgg$o5RTo-r?zd)s-8#Unw_3;Xli z$J>2x^0;(5hV8*o%fFtML&_&yQLqbc&o6Q2sZO`&hcUT;Q7qok9{q9K3nY*8FNaOf zB@E}sE;ICY65*U4iVi?fAq>aH%!!o0=g3H`U_{V zL@UxDP=tZcYKSiL%oVsHm052)1e^AWmhlhYrDo%g4(=wWV<{)k)q*QPd8p>|DAhlq ziUHK%SWu?7Y@`*&mKMT*x?n@_AT2Z@8-4E2<)WEf6G6z2aXOEq4;_2r2zzI9U>miDfEYe zt-=Kj{9=8xDXb5T9PZt6=Dr2ix;}RwNIzEpV-}PCR`~N* zyPLlD)nLAJM+){tQ6u2ZPb(z`@x z=J<4lZbC}c>mNJLGy-d?PEom*+Owx7Z&`PB)h-@wkS93VCInr(tU-fNu0YWH&0 z#_snR^?scf&q9B-dAS*ZWleQb^2wUg-K>`@Mw64;Hm(1r#_D6()QYE{EQXpgE>{hvL zc?|v>Q8-Rvx3fB`emkOV6J`H~=ff-gx`xNJbddZ&@l4v3Rj9aj!H;4?pYkE+F8e97 zp^Upt3f6-ETq*3)>D-@YA^7FHD8(EUp|};mmZpM(IuWa`1|DbZa103hFDo zY(dkY;=vc5W(P!GkyOCIArqTb2ss%RQ4Y}c`vsi3JQq8lqBy}gDUf=X~2H=rWzt>$y2xJiAW%yWc)%HXJC z*3@*aLdXZ=?V{z7n16hEc{yHRHx3-oQ7fMRjOdE~LqvUq{^RQ%2W@R&9sOGYk}PV0 zq#6Yp$3yClW$whgAFkTCa_~L%(1%*tKi}sdLsLE`2ZBNXQGj3y*VA1;Osr4PR#93C z3<1V6n!YQFOS)kJW5A%z-~sCv-l`DlqJ0WK?X5A%7X%kMYnpm4}^q%@eY=FZn!)sNF^VI zc@=yxEo4B8>mZqGl}MjYC=Ax(xu)pIk7~r^rA#h(DJPZVtkGeGN`N7*5Lilo`0`^| zdo?a^$*#k%iNbJj1d=DwZ=*5cTi+RQC6gA5;Hn(THPXb{|9PB7TCyPcsQx?ZlihPG zP`y%0tEMVu5B#p5w;X*i7Z`W3OQ|JE^_}tuGvcF zd*gi#xoZ=m*9gzYfu)cW;*K9Ow!4*o;CQD+SoJMEJU4d^d}Itr6N``r#Ms2Y3N}6k zxSm;1?f-6?fol>K0+6I1kWH_T780=c2zo8}#4Cf-u_sd>S(O!9FM?v^{wuUyn^-Na%gI!+>PrL5*}vz$;aR)AxrV!MESDp zWdSxG#p3kEximAZkEmGix?~Ur6vYqaJoOr2pzLSye&-7zb&H*=MYuD!p@prvE4bRd zYE~sm9XqRmr3^z&gR$%9gdRbyBO@DCSNX`LCxOT1*`@FG>~~Z2ygE1*sP75CT$Y@t z-KHUIk5V~1HCVRzwy$!BwH;wzJ2A)f4~?N~G@;PiM^wbGRKA|Pf6jlzPIQk$2YJ+9l5(eH^S+tC6$Qpcq1i?=5!RbVWWhKs z-FMS3RAFTQ!6g-lF`k(2qVt_kTaI!?Z~SC!@aXbqLT7~e(naZ*c}ytVfD(TuoPex* z5?9LNfUOf??@#3n@`a%|W$d{(>_D)0hVs4fRzE z_w zPCnA7(LKaSl2d=sQf~eH%JzWUEFB!XDyU7cXdRwuWQO8DvIlh(ZVE}q#aQyoTh=_Qua^6I{*X%4~F= zy}9(5%Pe}x)2EGjE6={(R;%im2 znsDC{mBJbzuu(UDuTM)G5qj^ zzsYNJ$@bXjmh4lc-;2BmAbc<{@yG5&77~hpi=Gp1Hu&W&Ar>Z?14iHNz`N*^c9s^wGibvq?k~V(QzA?=qVf1lSKD%I5;AWXc z`Q0*OBF9{Zckl{sLzJ~b&oTc)(0V|hc&yBFCrOSab6VH@tH0(q6=Vl5@ZoJGe-!em zvHN~|ghlZr#0on+7z|oYj%8(ql7q9q2WuU8Q%U&zD~$u#${(7-nqfUe*GL^e{~Z}o ze|++LO~}LHl5?wygk$JX_{xu1k@ZM_0VRv{okN2NswzGcl}m!8>EVu;CUuDBhAf2b z78U%?hFa_W`{@OrCQ?*fGAn_8*jHR)+k_K_!2v17c*#X=7FGVB73#0BPdt&o<$ZvN zH5!dTmlO0>X%du0W;2GQyKnK*U%73Yh_XBRx4j_CmE z*t?U4Jz|Jtzomu42R;}`dol40C&(Y>Wt&X^4AO%u0rPqdy<}J8P59%S6+&=%03#b> z$=5NovW<9dg{aBLnqW3|xH5=?C80drKzRTs8)B(rBpW>lqi>IBGBcZv-v`O)?=tAh zm;t5nX|0r9&di(sGeve*(9(k+g&JFrveb;K6tu+Znp(1WiasP}f@yMbN?KZt?jMiK zOSbXvro9l~qC+)o^U#3X1S?-|T`5b=%0&xRf4ORd=$JRf1?*o>1`{&=_qa%Yl`b4E zG`7*ZtMi=DG$M81w&-9=#Ye+Uv<3F#DOz*=y{IPwbmdjfT|gQsWvUh(O{q9)f`2WH zeKii1;%TH%TW>W`Vbz!5#cXwIss?YM**MBz!ECEF@gkSLz&(5U!3rsmNxUk7zF&qz z#76m5{S6nxS76`P5-b`6jjipPV}rpF)syTq7?x1|hEfLo=H8H*h|N<*Dc5V4R77oc z9GIVgt9cw2@zwKScYBxf?MJ88^IwC{l{T8wDu0(zzOE$`bsR#YQ8mho_1HJvZ97hm z^&+-9npi^`eMTZ6RcgRuRh!)QsyCjbYb^JqtT`79=6D)iz4YFH|91%_9)Eixhu#S=CoC{6)Z=;s~xDs zuxDKSyd{RqVGN}5$^;mh5hA%(5e==s$7nnLpyMQZni(AmlM}DSBCkO=X*OvhkRMEH zh9u7BV(cUkhPxvB--!`&E7K2r&yV+P(YP>A9`(7`_%P3Bf!x2H*pLli8o{|u#n7>*ioHW{Vc|&dKIcYzIuN)mOJtAn?8N7S0LBK?Qu+He4 zW>Y$Zf_wK3yzWQGnTs7d*q9efwZ0f!RQIthc2U^}t)lEA`g zU-Y@(z}O7KwlG~d_p#A!&|8Qi+8V^(&uK?aWq=h-RVSmJZiY?F*5}LZk%V|%ZFya0 zE_=UwF=t5E$D-FqGuY^Zuh)42pXM;GlQ)awe|h8rvp0z?f6ICM1FeSBI03$}e2{?? z4w@XZyE?(M;2-R76QPN6tJ~I8;BT#U)n1HJL?GdoXM5F|e%gZq!0#+wxtz6l7*{IVM+$czFq={@s5BLbdjrFq@> zyJi#nfa3umo}M83udUGUkI~^9H7eb2;+|qmq28i*(@J**-6TGtdB1M@ib@mGfb>Cp zjWgQm_V=#VtEQP6t8h(D#=rp~j2EElJ&*@<0zwE*^=Snh)J`mZLs%NBJq61NVotf= z6jp%bL(>EgXAFYLP%9|6FL}XqWo8*`|A8zq6|1BIzQ74$P{a7)HDq$IOU@~uU0svA z`s=3AlJtquAcGnh9;8?51UH52KC>W>r&O0EMj8=?By5DaSByk{Q=BC*@*$nari7Vw z`7K0{$hr2F1WP28&;%s#(iH;WSpJ@x>Rs$Z63-3aPa~9}hvFFd_QK$VC1k|j@E2Gw zSWWe`PnGU8ByQP}j>(CIt}yJ=*c|vVI?EO@Mc-~qol(oeB4(W#f{zbL8xLXL7mkae z?6r3clya|xg-jf8beztH;%4T&FYX561pK*-$hs~o<1?o|+Br`yoft_Wxw+zOjuLOI z_JUAcWXwa8t(?SV(w_GVpd&Y`?X1KZzxZ?zX%mPTZrUaG8h?s!!divU?I%C=o3K`W zM@9#mnQ|>*R4U;r!pGCQaU!8=OLxR5Y_*W5;KgJ_=KUf$+0?eGJnm43*=0HE(%TdI zFPio;M=-n*5w(DjghH5uFZH)f82cMjH zd)ElB)*G+p0pJg_?Q1;=;aSfBa=YcRs-(Rn5p{EobmvYPku<{RD{McMDJ;#j*;pBu(`qx{>JcZ3(-|(vDPHrLHv1fP^Z1_}w4XQBy_;{>&X&$KcPHEEwft_}SYK$$|`iCxR;S>#Z0LUw>%BjQS_wFNH*s(m>- zu)y;>{2VG*LD%Uulr9p|s1?t9udE>`G^zJdxkoJK+SXs+9ncELxXv*Y(T^Qt?H*dX^dAN$j4JuSEC=aZ!MwEEp@^TzXv*;93xJ% z-#{|N`p&L@D(w0cZ3f`nq@{*Q#>_5qqHTaEqqp9yuR()_0ELLr%2wCqm|5s$hb*Op zL6g1n-_c3#_t@M$cCn==blGz(6_G=j8VT_qNgVrSAuVS!U9D!$Ll1=i>2(HWN0DzkHWxTSAm5;S$p%jEFr-tt*`;KYl9$w#&P6A%8Wt;;9@Oxap&u$6mzdygiaQs7FEtXH;leVY)>b$=8t7SdY z5b-_1dp!5T#*YKA9MV~?3Ecc#?Z&^}^%S~J;^ccAvej8oKTNDxn5cd@9jEVtC0#A1+ zoHxF=uO@S=$ciio0Cf&IGijGAPp=gjD-uk)jy(X8&OXuU_T+{*pnAZzOF7KX$a&?{ z_Gnqp*iUy_QKW1e6Bh?3Dl`nFX6|mEGcr#|wcwwehpgE~votNY2<9i4bEqeq4<-B| zDzu)g3*b+4wy=YPq8zD$!910r*eaaT!9>o!)OSJgRvcxqm<*kfDa9$iO7U-~bC;Id?kJcSs79b+Gh|79$(wC`G)4h$X^w1}bx zTfVx1ns9;5Ho4>_K6HYWiImrU1`ddt-=Q)^pfb&N%(GJnW^QGfz>Wnb@W4DhW9G_w zfx+dd{~8_nbr+PlXlP`BNXJbGcQ0k!U@Li7Nfv#FM#jwF$2wsKN@X0Sp^S)beJ>_S zoy43oZ*}w#A&0>-hM^)okBhyUttK@|G>$8VCYOMj8~I~H>wb@ zNmF-Uk70Tm+=#Af*~&(eyTaGmSt^M+#NgZ{F3BTmvv8u+8R%~aUez?{`!Q2}E`4i) zxUB5Dccyr9St*<68Z9fN$hQ zg33Ad%X2%IdbaQrd0$mAxeHscy4VbyG#^?-#?=ERp$MH7Av^5$ydE?dy2o55u7b?9 z401EYwJ;x*aS!a$m6SQc1#eKpTazVdp8tk>0NSBs>35iF$Yb{Md2oMx@QVv?jNfE! z(wGCTX(n~_TUzmmZG->JllxTX)DUM)xmT44b;W`V3g@M*Z?eXepmAzLll*wAJUW|1 zAyk(18N+njQqtTh{tyC^MVZCe@4bdaR1a^Dopp9O6aga&g%A73w~d2|jRjb0H*$g2 zp5u$IjL!p{%k%f;t*qhre@YLdBFlOR!UX|UPmdFn zabRDQr$Hr>0RY%1`37WRF{fM=1!lurvrO=#&+BKqBExsKCL{)iDnE^p9hc0nGp+KZ zrr)L@fSW>H@Sx|bH;<>k_xAUTdDFNWd%Pc>cgINt{Je~>H}{(7QSVD>63d6@4es)w zx(yMQsr_|^^Ho(ltmWJ#xAcWLljS(q7nWguYJyF{syaEFF@8aGf-?{mT=m$dATl>lT)0kphicO51k>2 zO24Yh(rf3a0W$^;SOem;v(*jq<}|m}iQ-nf@N@94Qg*qr6+F=myt%1PTV;R{aHGI! z?#PQYFsiTH8Un`!=f_UFd4m5d2WX83n?6?YBwcF8uy*)1{sL^}b zMIQR8#0Us%a%Z(F4e4 zZy2{4%)rcx63Ci&cLPk|3vedzbMbXOb+_cTvRa918n_RZGGjP@`SQNPF~0g~VV3$3 zWBC3Q#X5Kx=yt#Z2YNzw-LMrL!pH?GdeA_(hG*&*m+y~8g#FVT;gov32 z2UmgS{sGrKb$3M&mG)mkCszvk=cJgt*&>1;m`LdApzv zk1LpH{wNHY&|Bd}Br3KH#}!;Q;02QFsfC74IpSXt6Ah-rt~h(x>L=uW=-aRyZ>d(e zSOvQ}zONJ&uvC*z2Ufm0d(cOu`hjNb_2Ljc%pCXnuh)8UEXF3BEyO$!UxL=y!!CWD zjXOQwzio?5gkb8+@5YJ{Q|WN> zQa#e>9aw9Kr#981kQ;q*VTU+H zj|?b9BmYXpQP^1dlXvsSr#K!r6=X=SD1>Y|<&3K%Q7?GJiJ`R(!x6Ks6)9K zn&+f(d8-79@nlKqEf;=f#u6Qn2UfWgdFsyxL_6+JH%@F80M8p}cqQ6_iQ826)H!rS zMqR|k%tv!tTA)pz#JTnJ)UB;n75(WJ`rA7*JG&uD4Cimqf>S5Jb2OQF1g&LLab@kE+CT)X+b7{$3qR+ifwIG`=WZ`_C8 zz}&WwU`8f80`kC_xg*Tf|GBzIo3g$$ETsx$Snb5Ez)5GVf<^nD%JkB=3pIsr^5U|x zA298O3U^QoR!nycqaW3rws#5_)g{$@{O`e3UDOO?2Rr<4^(Th-Bq3WBFjG`j_&>b( z%SmJV%r>>s45ZS`T6t?kTd142)~ZotQ_2ZMiTa0>8zRHF<(ZT49tR6x2p_TFM>?D^ zkqe>D^6h)4&+FL~k-o!bc{Vw2|pvT-=0v<1OEm-J)eq zO3%-$Mx!t#w>72TIaqK1%Rgu~`KqLPaqxTJC7|z`79GoLR+u9Au0lm`QtR9H_AC7= zxgv`YGWKAQGGQMH1^hLct_-iS-RVb`?}EOtXej`56%%C+AY;cbkSQb`4ZOetqsGc? zM%1woB=xrznkjoypk_4&Pi^t4HC2!AavcE z@1{SK#d1(pfqd@mTmTR#|LdUZrr9wHY_50*# z{FSy4k@<*pE$s92iM{@)U9iw42@_`7PVUNF#eoe>KWQ$)x*9%W)@c> zfHFFfAUgHR6$0lR-`0a!rwA_<*5Bh7J6{Ik4R&9Arx9^UA)1FV)AWrix1`%Vj^jV~ zVzg+aw0O~aELV(ng8>{}Yw0{=T4ZF7LN1B~6XO;ejgix+wp!ygd z8*U(v1{NLi>bZ)c1cMo^*V`F&(<+e-_t@6!L%GN7n~6Pbq-TaqK3w^+1LU1t>wJG| zK!aF^x6cS&0zdMPo9@L0d8zNGUWw0*5WihAFcG#hI@`X(=5^qB&#wi?&syjQzWr$% zj)zt#Jv1%J56UXmxubgO>`3#^VMp$tJo)}_pCTkL`>#P-(6^T?-!ZaO@V6ZeH8D5# zllCg=88kHuCa#+>Z1+5EuMTJ!Xn6T8=XspC+n8n={xUQZ11*Pn%eg0-tMoM3nrc`N zTaufXyo%+BK-eZJV&E=CScyW7ri9m&f+{7vv9m`9U7E)1AtlA?UG!+0rmCFyTb#&W zDQ}9YDtf)?jcC5iLMe(!r?u2B0=6MBt$SiI&~x3H>Pme1j!dC=;TEveHa%N{GNYL| z3pYoe#R1#eP=BgmGy4k4OHLFRonI$tEBBgGEcq%Tpd1?72_k;f4cfMlurZjd1zv^< zgrs5C{F6*6GQwZPR2m=fEVJ0$ScSRuWFQMHQ*0}-qel&AOXr46i~1qK5$g#ilt1#+ zTR|(VBj$ypwGT@tsQQAVaU}3G?tg9u6F3#k5;HJ9MVlI--#gFs>3uT|$J-veuNy{9 zc*cxqoYPX>WfNASN;!1848fom3TwDh+Am}lED`ms;7(UDvnaj>#R-ezGaT+6dtsNf zhkSM(1gC24019f!nNj+_gAM)Q2QeX^q&O&8Xh{;fPB1;c1+5=W6ZOg2?nTA@RYe|Yjl}|s6LoN1W zfiw@y3>QA_ON9j442tKv++(zw%CvqS99Zw7IHo{;xsI986fzV)_oNyrKzTVgtcZh7iPbt}czXVXv zE!0^i_XAW(Z;Vm|j^Ndm$_~O8v#7>dW3{{ZeNV9Q=3{m5?{9(7g%D3L(Gi?6qw+y6 zs@U)k>deXS_g7_uMYKr6i`GuWVqdBFdi3IV$CtO9p~EU{eQHUeLd2utZeP65bB%;MrkkkPQWyPlcEJ4{FR#q=t$MMTW|athhY4lp5%}>QYSf{V>R8dUxZhqWnZ^ zagy^Ic{;zTv*nO*NPUmfi4v?0B1F;6 zqD9R!aJ@)LrU;Y%HZB(K#i|$_uaf8LOz~oYVFnE-tJq=kkePPylZNI8H&L4&V^z%| zU$9b*iJ@XNkS8@taz_&-DJ0U(|JGW2wKAHO4a6Q@6?c`pKpSj4 zl&78g_o;>s>2q)0C43EEh4>>q0ig*FK?HqZ}YtQE%8AcFn>Y`;h}2`jqk2bUbw z+4gtdAiE9gy<-IIzccPx(FA09TBQ-uYTAUs1rH`l?}bRAQXt2bu8jRQ*sTsx9VUy< zK7$!?K3VonI%kOrRLo61t90AAN<+Wt%j2NaR0Jzg$ezJLD^=*twMKTTNSP~F@lQ`5 zFvEf+LC^qc5&rL*?$jL-+IfQ~afCAoFS_m^JtjhDz(Yw=;2@p;7+ zv>U1I_*cjSwPtIgk+g)jq3vh7%RYWntoE$9G6KEjwx+vdh41!tVPXXbN`-#??*7ag zMjhjdP_jufDS2OW-%hY7?#+`(+E0lMG>5;YM5r$Ncujo#uoU)gdI$Lvr|uLn?%Z5O zcM{dz?Nl4t?SCIGwF+LlhyNN09WU;yp4^9K=!Gf-<&%d>1YrX>h!56Kk>e?)o^xaj zS`!xI?OTy4HV@cPVQ=e++f=1ayth$v&Pmv|6AQz98={e3KZ4g$%x7;Y9Q>}?ND`}4 z+s;-?U~7>X_hvicX{P+0sl7~0U%_XM1Ts0fA>(P((cTh1_KSr6|9o18y>C__O-vPCJG*DH=zDL#*68$*+>39@(T`1_ac~rO)!oN}8 z4H$MXh!SQy>!0$EX-N)Qk^EK*R1^SQF3SL-;Rf;pFj*0UakUBwxVbaXe*_0~q|A(u(D#hu0|eYC?$- z$75+m@L*cd718R|y*Jd5(d^pi01>dhIXwKhib1RS%1w@XlgWLp?#2N8r2l1yKeSjz zb}p+hy{(6T#%ZM)5WVXx4;UcZI(~a)#-H$R^pcvJG8>q15me$pOF-kvJ~kQgt@azt za!?p|mLvj``5)nVu@s+!%s=nEGiHsN&?@tMbKwTqE~CnGj7!qb`tjU=E%O~S2sR4%P)YOz~zRc-*d4T7~lKeyHDQlrLF5{o8k={W1u=Y zQMrsc;koe^cYiPGWNI#~PG9L@F0PtY$-aG)q3$%ufjIVTug3lGpS*k*g8UU-M8%Le zQPl6~7(r^{BavoAgP&i(3blo8Wioeyjr%6b1sg-?Ym9xKzI`GXNUe|L*WQz#n=u|o z-(KA~0y6M%>4RQhacOy`3tdRr|2;htGeF1#-P0M8G(Y(mURxnSo8Ai^~Z zV6u4~sfdshQa-(c*rdxv1uWwn4=gqh4HR=oyd!Z%cRNjm#l0S!67frVP_>o=rGf=TABgr%-wcfO zBrYl*nf=%Tco%=zJHT}Im6aQTB%Dc#DSGQ6O3q2A21!kS3vso>N;E7Sa?Uk?BlMZ^ z@^g~vHG9^4h!D&m#_aWX(^!D!S*(N&`eF+TfSi~Cee!n9AY>r*0Io0>6SI+Z{vJJS zPM~yWEqgQ^@Rr@Rr&_i}tAYoo+ju!UMC+wdg|KQEYtJ$@<&_!rj|HMNm^|@?%;mtrzA&CK+Qh@WALpkF z=il3K=dhgi?VEsLuc>$fQ2hEZB@yeg!q(S%2-d~>`RM-M(7VeS4><04MSTZ$bm7wq z;~9ZAgPhhG$>y^evWH+pJsIivG^w7U`}i=iHb*ZSaB-oX`wAzo`D&QP9EHtx=XW33 z6?-oh>9Uro@ErM3;+JQvrf;TA`ab%SG_ZX~S@PHHBSO{0^8yg22(Xsed%$o?y6 z$}ooh_o9FEPeG_D8k1KA0}3EDq|H#>3lrS@Fm00-u{d|jzZo!F!h04L!#&3Y7$&qf zNtj6F@P*3Oz-9_%qpM3cg8~$yYP?FM`s!E5PVud|<#xb-N#4=cGudSms`Q9`WL~?k z5u<|~X$PAc;+YVTiwzkQ9-GayYYkMrYgP3ceS zy{?pe^Db&_)2IE89UM4km!U^*n!mH$BY-(2`v_w9d%wR(PSP zMge{4zdwcP)p)V8$RPdg$$fpDKoe8V3Cqjzd09n@67}78AHLtu+U_@gIbr-26caz# zy6C)TVkb)L)KVnrkL?!&%}V#{?ashk4-9OU#ywV8sskXBi?OhZrjd0p73>6k8GZNW z>x%KDU3l}pt4EUA5VFDJj4SKocJMcRJ=*b8NNo}xeDMwj0bTR^vfzJ7eK~6{_P8-I z%i`G)ZznOE9PHfPLZ7gse#JPZ5y#A2y6b!08@reiJUxB){y_G=r+eokeW34G*<%5q zZX7^n?10|c9|z_?x1E7@aRbh&k^3kyW&WZZvj%k8f_F_GS04Iv_=_9FFo`D=QX+@$ z@R23(4IogJYQN;xQcJhzjZYh6+x98rPz2{z{$k{l&OHE$|{LFMY7t~GD51|t4P#S6T?R1G5u=p1bD&TV&l>cj`XW$ETCrmeBk-db# zPTMgU15_wEjg0+Y4;pTLc;DqAo)J(4EMWpLDYL&Qc>D+uGL|4Qh@|oV+4R7Umz3|k z0*mLR`c=rwm9O5;u>)sE)~RZx_EDR$u+gk;!5H>#g~BnxWg#h1zcgcK?`EE0_<^!d z%J+w*7xO7D<>542s7+_dRJ8rlYBU)m|~lMn5_Ptg#RLwkMj8$e|MEw!4DOoKE{jhAB@YTuah|E4u3j8FLT1>(Wyt z_uBZ!5VBG(GwYDIm~Dr*XO*f+h~dQD(IZyMRa#@^K7H6x$#i_Lqlv92&Lu#O`|57+ z`F)!tV+ZB#!Q=GZ=b9zz2s!z1_qZX>RGvS*O}`^Ckk1|k&YY>6Z&HNLw3H4feiM3i z`Z}oBl-F^r71j_(WFzFsdCkKTT;?Yu)MOT>Jt0riIVihq_j~1R+<+e9%C6h}`%D6T z~eR0G`*N-yDdBLnr7^S}7cxnPx&Z18KK7 z>~vRMNj`EBm5^Mxww$3D(8;u^&p1RB#vVBBiX^44VuYp;*;%DKwVi>G#5b*tcM~^CQK{{SP4YjbH_|>zBmIk{XYNAr zY$(%5nZnn0zCLLiMe!)GpBzl<#MJ$jdH!cUR*!0CXy|J{sTi>A2dDXMNVimsqmrIb zLlZ%Wdx-@^sztJ;9d)bs*DY*8XsUG-@(499{S92wareLW|YDb#=D z&_F65P(E*-cGs9oYVrG7y#I&LO0dQ3XFbJ zOYr1BT~$>b(~9X%EL%uf%G{+CB$t0ZzFc^)gPwZy`T>QNGo%5ERM3VhRBA6S7EP0>j#V#;ddgPw zL~Q9A^YoakhlhJ&RtVA(LwpK^jVTBMV!o3R0`B=j@(N?4Pyf<^Sw$q@0in2Ouf6xn z93Bm_2$ftFlf+y|xLvRBM<}_3WrsD$$93A${fo%(ZV3#LqIoN~9_W|nvVEn}GW=0z zOj%Cq53)WN$E|*0THB0u6EQ=gW#2L$D4W<9a)BW#hkfA!9?TR7F#^8P$Zr9rh%{QT zzqO7IW|MG?1dNk>RJ6$JZ_Y6EOdOy1-PjE}4;!f74n};Ch5ms6DgL+iyrR+e;m=4o zACst7&MgTdI*w9z#BA@Duh~t8Fc{+8jG&9-edog%UsxYt1q7M=#hfMnz@6Jp$6@hS z0O?)mTE)+i3g?x{e!;P3n?jB=xLhD{vHFWJe9#C4@yUq*O5MP!UY`RahbL`k8g0j^ zWy>e;Hn~>sa^@GfOMuj+Zir^vPf(CHq;0Yfw)QW=uEvg{Xk94VMSy8dQsh`~L-gh= zpy~XXzY{e2Fm4!OOW^CYt1HdgA5aG;fWO7oV>hngMgQIUMKigxPlt#<&x!pQIm@3t zb2)(dH&O}v1%bF&SO2H1aWUU|3blt-Hm}gFd zF#b+ypf7jXm*W96P{f3Yx%Dt|YTAT)ueQx1j-y{s!vPs6v+sWq4TDjLeP6cQVK;iA zU}>3syhuJs5i-pqg}cN3r37_%s~|mxjN+|>-Qq+FVBnK^j)BzsBCtO;L(yr^16Et* zW22_>4PcCMJNQ(QBM-{G^?;>{`yIzdr&< zgHlJrLY{4pT7>SbVSZhZHSdsBuIpyL(BGXfhG27rVkfx6dlaoaCoMD$ zv3e-S+iZt~KqZ>9K=TQ>LPkB6y|5OWY%O-5?)+iGju2(%RCymg8ufi&$xpn9< zrJ6x^mI)*UkM%F{06m%Tr-Oy9^Z|8ufU`k4U$mm`QFB2jF4+~r@lC=lsI@&F)nJIX z6~G3?}0uVD3{TkhA54p|91%2oy@+y1=t#^xg{mmuYGZTM;OGfZ^b+fI?n~{?o z1uhxZ%~OvC-CHvm4B=>1ETVD>p4t#Jk(G=$55c!T)pM;OCqg|f@ZN4co}X+sv&)yN5Pv=lM{VL|A7nfhqdhG}G!D90{^cE=q4K zl8mzk@uFw#k&V5srpWd@EJkMVWrmR2hmQ4^+MN2@oHQMVVfW~us_p?76aqe;FT?xG z{vuxnPrnlkzILhcWuFDIkSaQ0^rmWhfR1C8BX7SNZ|`4|)*Y?cDv!60TrSKTRLnvA zurxir0ra=N2p#_f${_iKj^ylRTN0wfZs@TI?lmq*dSAlhkD0faYRBq;scOKEz=G$^ zP*F?)w=dzfU)_tnl>~NzhVtm}okd3?;`!(ehN6k=N8}g@*k+PDZPvEACbTUnVCCEW ztt}wDZvMycHydX7({!P$np7?JeG66$j7n*@;pA#(w5t^d{(r=Q+9eLoEo-FLb`Ezp zy_0y6rysS`>}n)VK%4bFaC7^|XE0LK@Z-bKl&-1fYt;UUZ-me+x~(GVzRsDiy71bV zSCDbsHTqh`oUFSNL~hL|{Rl)XV7`BftuT1!n-R<6Pk%~m#)XCbZa%-NNvqEGZUfct z@o_bu&BsR}C`@ldN2eM*Hd=1#px-7H!q#SAamP#ePeOq|CphV??GZoMd_GRw{cx#g zda^jyWCj#4xR?rf-0P=|z4MH82uCMJ5(}@XMUt-Wt`Y@=w)4?HQnDS7B_%L>S1^jE z+Ka!gwqRPJMLziZjY-KNnb#pSd906j{|{Z~6rEYXq}|xIZFFqgwr$(CjZVk5?c|M} zbdrv3+nCHZ^Z$2qSF6@Jcjw})s$KiRyR(c)gIP_A(MPL*!bwdmWgZadYnFTM!E87) zlOnHBcQ~gO8=ymJ+G^_k7%sceb%a)qWfd zM>N(3?ci(!cXnxzG}9f~Ch1#Z1MR^~z?wr;&d8eflaE6`R2D@A$la{AuzH z8l;3FGwjfZ3zg1ems~}APLs16O^5T%p*7M|`Ba&PRasXQ_E|)N{z2>kHwZCCR|+(P z9~8(KNDvMv5*UaHhzJ5`2q+K>2*3(yAWrj~D&Ri)`)spd*~vEvXxB>51HA{?v);k_eLjrPi|b1>wwZ`L1yZ-#Jq z91s6BN1MPUk!JPl@F9;sNOP0pMMto{?G@^fKoZaLZF4r1`Rd;4V*HM(Bywwwif> zp$#x$D$ubMoovv+f>DsbZV=UMu^lD`J==;u=@(=9-ZIN=f)VUPgYS=_fQ)M1h14GiNO}C=I^B=s*I$lq*B;vlSfA`9H z>obK(N{F0d(*ndcfXDqtpyc}4uqu(3SCqPWK4r|_X14JJHI7=1lI!lev5vnGFj%kf z?**^{ey^@H6TUu(`Ghz4K4A$(*(YricI^X+gl|TFAMa6i`kWNRys&Q+N)rl{wH(t6 z!{m}mmWhvUC8R>L-gB}w$3~zvIk#~H7RFj5!vZL~$|mcHi|cU6@fs05Cv_Vqo>F{V z=S_w5ac=@t2JvI$NO*e{xcXXGd}{?NvvrS4L|OtSLPh*Y)1)F_@y*bYmrBQFqMq#j ziO927(L_eK_GnVjSITKoP@Q!(QPEQONLa;(Juy6oI`g8RNVV_f1%rXaiC~n(;yTyaw%A;`sif$HNy-tJJ&)gg(GP3 z-(sctco;v=2zx^(anoz{qo|b8VgxNX=GNJ~knwC~B+t_DeksvB7^ZMUY_y;Ktn3}L z^eJJOW7n1J-i5#x#vRv=zC7nj6mY~&BX@11WRX*xTz|$?Y5jzSU0yF!4j1t6K^juL z9%Ru4koW?zvG2KVNLkLzHX(R3-)DEHjl+_{2@JVMmG#nPpDTgp(cuhuRGxcf>|S*7Vk7q zrNdsb`&E%`So*Y@3fM2%o+_=kr8{&9O{V9X?j{octI@jYLOdf3taFyZ0^oPK;~ zwo(K{FD~QH^kaDit~H#z*MfjpW)B9&V+;g^aO`J6gj_Lxi%PpcyQznC4T|DxcJSE9 z*;T@0R0g%*bX$`zCBpj0#9NQekMD6;1t4%#8rC%RvJ_gM+hXiB3BuBRuB>bH1vOrA zJkK;^Faf$t-qZ~wtR}o}U??x4^KUF;_rxY3eriAWT$u#b7n%vn1gn38^ueV8F0PVJOX z`f(H*tQ5uX2%BTfnZVEUasQjv>qHniJ~B=pxnEPSRTd4{$khc3@Ow_x+lV^bsDKe~Vi6XpuFoG|y4n>2M!zzBmvOK~U;3n8jUBDX;5rWsnL)uCl z$>9uXA6m@fQA@FGiA5x$KMjL&&U1LYxSoeRI@1!kfH_qA1R zfV*!<8f88h6{nmOB!V5#MS?twaK>;VriE_N+<6w0sc}@w6J3fYq)+eHt}k(x)`4Kr zlB@-HI*WOF3e1P2S;q}-#8@JtO1vf5?#s&ziMG9$`!E3(PjB*9I$Y;zt4DQ zhWmEsD-e#vnhtCH>y7hEeNIRqgzJi;q!bLx&^Jy4wus33MHU#?W>Up-Aiy2b_@fg^ z{$;T$?j{(9)e~F8_>9da5Y(0TRl=W}|sDlWZ2CEPCW*B5Z~(_lR@`VV?`GFu7??18q{e2_%zoA6TjQ=B*f(}xm(!xXeAAO#2m*Q`#WopMJ=8;&q@S*_%G8~pW8rTK69JW-nR#P z_La1AuTy@=>nnIcfS9}3n7?VnX8=c4aMO2~X!@PsmB63>-SX(5=-GqsM{LIU1hYF= zieHo{Va1BWH6HgEB{L+QkEaQTX^o0WgR)B&y6WWH^Ejs)%uCXUN$GD--7-vcl=+NW zJg_OFVafz@D<17S1%eka8JQc*x8mwmM8fXK=crWz^FBtefq~mjFs#i0e^6B4E!8tA zturOSn9Tq_OHS~zw<$$Q7>U_LT}-Do0GK=yOjN^SZ}Wj0AC9w;WB_ZqS=FDgEst!~ z^HkKugdQtkEbyA|PwL_Qxb`|2zt(jP6qXoH8W*GdWgq;!0VD!(JG2792DX7X6b*UI~(_;8< z#k3Y=^)k{ETUIbwV0q#xB4M3p;S?)i=G>$vF19)V3Fk4Rs=ZcEfipDLNALbmDYg6s*O*x-_*{@VSa_(M=@ zQJi!uue;#fS0)dP^YwUHUiJm3!g{}C2^quWcju@I*Y<1NpB3R^(S^l#m0_QX+}ecz zH}*$Xn?s-!j7|k5?1oSosw^@qI^?7B6}`4Ye>AOw5)O6`x>h*w1f8TCW_DS@DLR{7 zk#A6JH96;xO66zd2$A)%d&MM9Q?_sJ?F&@w?eESz#y6QCToH=A7hDn=m!n4SPqOd> zSRnjzIMJVrJlxgHyUJM-LK|*h0}A3VKZOht1-8ZP`mN5ozuGu#6|v-D8r~N(_O!I; z$W2L3dZ1I7a5UU^_P&}D*-ZxJsHTY=)g}uretvb*C2f{A{>F^1$p?6NqVlXLD6h30 zND@S6V_5hTj&_S2>Hg_`ze@zKF)14p<(z>=y#qR;4(<-*CxM98m_VnRC>~Q@1U=QU zj(C%9hf?ZN_hO)Pw1UQXfgTJvXfYwh+e`8IHUE=Y#EZeuNR-~*OqscI72{!*QJI}_ zG$#>^_KF#d*M`h*T^452!D8bt3Vqe?YP5sgj;_A+k!y3W(Km;UCpC@%L{<>}+QYMZ z_*%oGrRViE8mvZA-YmP52>Wu&F_A8u%3$g4@*v)l#Qs{RjaKS}rfSn3zi)xlIfTFv zsD~j$3)-j3rU^8K`Nm8Lpm`HyJY>8-nt*&?9pd;*U%vr}D*(zxJj#qz^g6qMjqoD0 zBu?Mt$!I$VQtfGm-9MQqrGkhSSr=7QK;SKmQ0;#3q!gDGW*Nae;e;1$jAcfV2>xfH zI#{}!$My55Rlb4#cz?7^2omjO2wx-$BM)b8Y4GUUq)y2*?>z~n6Pvjc968Xa-p)bB zg`N3-BwK|Gd^A9=jP z{aB{{s>f?2x2nUOu`UJ+%;x&uY-PaQ=oXv;JAqkKZ2kW8XsSBRO#*4XY*Qgxh`nQF z!P-mSY6NKpMCqgnoLgtKUz9s{OkIr1+-cx3+d$o{Wq{pYrqt=EY=czZA?2N20Rvg` z>uqfnN}`V!U+)jKx__DGMg5Bx7ip(TpzvxG+jp)ulx`pgGbfsKsOu#xgQN}}1-3KX zDE`qCuH4l9TEFM%wrxL`&n^ddMVQfS@%+kb z1iP23xzp?3jhD@WoNd1j`L5!U0E$(ShEV6eG}&;K{6b>y0spYLKOP!dBp?0kY;jpn zm)^~vmF9rr=QwHt#)67fN+)b$i-gquZMKW)^2QttieQI)U2D9k>t3ds0n6kfaQ!FK z8BWRO0aj4!lDWN%*g|io%dtLAhvttcODbkTx{)pH%%#tmZJ_Oulzc)5*_TtvMVtkE z`PyJaAYf>t1XhxUb(?`yX6SBgGxo$Yg-r$kclMcQV<$j<)8U0^4^-+oq+cYK#`@;j z&U0~+07(fk5~F)Fh()iPVDL5Y2~`WyCXo5!yCJgYlydBXCmyW!lj1OOaw(?mwnd)b z<16Sa8lU*$nu=x*(E;;s|6B)q`M-s9j6WZhvQNw9cC?)X@e$;0zbt(sa!kqjee4g^ zxTI`P$qoK61XF>p|DPdvuERfzL$3MTo=7cpi3FG@uoxO{p)Cd)$oEZce0=w7DlWEg5Qp106*2`yZHqJGIWjpWj7nUj2C2;zZun3IRfRV5$Jwv$Lx__1M4sGw>%FGINqYBJb?A`V7Z0uaU`#I?jl*h>jL+P(uU zZ?(kXZBm@O@HNr|3;0J`zY&6hQjO*`0!=_BDW7}j(fA7U zE?*aNv~a^0KH)g~;wQPm-noaEf^*;WRdN~jy*$C>>H^)P0b;cb8NE!dB;^23ZRdE6 z(~#N$$U^}Le{=zenWY$nC=c!Ew`|^OXNS@8cSwrsy6?BIqquuQhhbEYw~$v67D-HR zL27}kEnxDi%gi66TkE@z`RgQD`9UD6a}~gBxv&V|R5eZ~%qpAO@gN}}aYifPvpk&P zku;0}$Q$iYc_t0FZXGE>;7OeK<=w9zzmMB{{$D%&$*EbOAskXHaPX}F%7A58OX>Q} z7Ba{%&^Q(mHYk}%pebBpEO0WDATxyI$bXuB;K@S9Eoj|tgi_#WfacqmeHoMyP5p%M zZVr7fa8v7t{VY`+|0+HF+hF%$opZ#ZA`IzDQ$PdH$XAVW@YQM?UpAwG$V(CWZXOQO zY(ZwZubJI3#|_tF+sb!nqLhMw2;<^sKZV~L=7d7JV;OC!tmon`YMDh-p6%PiwsvWz z=w$1J*4+&?eNwNAVs<+M2!rv}C|CJ0hnNL?EVQm?nD5c<#mR_yS8*Z#D$7Yvf|Ae%7 z75LA~ul>UO@e=30z|y@?#1h~g*-D~E1CpTp$(DWLhp98sw!dEvJ~01w#CXt6tos{V z@{=7MrEFcq3%e3rZhbj=qkLVwy*{W-A1APm4Y!;9$Q->#V{KQp=XpQJ(ohDZPhXr% zQlpd0N$Mo~=vRVwEE$s4eb8p$^^8sbB?e!cUX*qC4n zQwd|8+EO&3BAt2wz>{ zCkADJ)%d%F9SI2AQBqux^u~ZoZ+cKahW^wE?@;O}+xEJ+in z+GO)Se2~QPAMhHLTPv$a-1!bbhq?bjxRbHxr#cwRN6+emT}4^|wH-V9D-$Sy5`<>V5GYeAsIX)W*+l=v}!ZDo7-*Dd?dvAQ==+w7L;6PLW9VkX_6E zJ;og9Av8f`NF|0%B8IIhA)OOuMGl8z^vpsm^ZbNG5yKQ~$E`Yp8jRIce zox2o}In`>?D_Raye30!Omx79CWA8RC6%7$$^*g&-@&UF<-#Pz}6eUjd$&(X+EI6BW z=dsCM|FUUO3txN{iOe;d45za}qHi15O#c1o>Z)NTj;~@nC@Y<_rX0Z(E}8{h7;W%M ziUlcLH#3SNb+CJ8ND?T*cdtKqYFQk=Tw?R(ilAxN>4H}9Dx7UC^r{S?rKqr)(Ql-l zZ|sVD#h~ejUeG@84MI2sr4%ch4Y>N}*3Ec>ORDb& ztqRHJnop%ag<;6=kJ}CT2oITbCc7!~A%4=lgSv!%g@ohkl@NF+n%kTbOG%wbbbiSD zG$7c9hv-Q_d9y<~XYdi*eoF6@buvr|R|w|MaWJ1l`R@XR(8i5RDA^fru;hdT=pUyS zPB@ItN!Ln@iWjOQ=hMv(!GLQu_{Z3pPdOk_l?kHf4r&@NXg+#x#cl_Pyix+%JxUxP zA&iTQdDlR8zCNjs^S-4xC{9LgSZK^@NZeAybfSgP@9CYJEd~Munk=UzncV zKxKbNESb*jP%IzUiwn%#T$2!fyS9x2Nx#~o&J(@qxq*G8j5hQ9f+EaOL^q5d{1Ugy z>VKY@7e6N_)KNLwU@U8tvjYpXWkzUg+;Qh~Tj>EsICa(OwcMmsFM zPZCswY~x*V593#NPP7G7G8VwuRgFqtz+grgU13i@y;C*Pfa#WbdPQBsCm_rG5nIp? zm>+yoKI8zkhQqr%m~$RJb{8e2^T1t&lz_?rM$9dZtaROIg-z3*b?&uiL@lieE9Xt5 zd0C-zR;;v@*i$dgi%s~~qgbu48LsRX1LcS$F6JA0cpQ$luDmfmifUTJ5enc4sTk^s;IfN{esz4MgO+;}M*Y6Yp)T#ht z%xEhw04}T_AkPUN*k(x3!JU;(XFTP5jv@=+q;|gsW>(efY2&4RGN8G~8lZHaeFe;4 zXFY4)Y~B^2bMwySV22Bl__&m*3;LvgbrTfihtzq42uA{E_N=*fMgTqPkgE++Rl$Ui z%CS2HH&joKaTMc_mtLTdkVQH_q-^mDwwwpF+UYfc{7-(96{PdrXmFZt6|!I*H|(pxE}dVJ<{l$z_2`5l^b%2lX(Ef z{y$B&4H|~xLFzBs7AK&T8TWxroMR@1++uq26rhdJwy%pM23kj3;_4mdp@#VS;I)!kG0x092jW%;Jz^_nL&42ymG<$0Rr0kqmt18WNO7d_QOxb0Dm ze9dWX?{JIL*%fpT_@A$fFT(iB6qslGuzn&Ce;8Yp^(pu}d7T26BIv7TOV`v_P71IO zAM{X=igj}3ppd88U>oM3cv<>1c_|tPt|5B370jNL_Kd1Ao8n+^#s~5!ers9CTFq{+ zItesJn_ePOW{VL zmPWmqe_80Q47bmgX69Uw$pvTgX?;?E0J(hC1Jfi9v5EKaQbSFjP@F-L=c45eQJtX6 z;s61i?VqcV+jl)MwWZ8+LkHan2Ja5D@>{^X7=k^ z{*v0DT2#0A0T{&J4e)HM;|z3p{9zrsUB6~E3_p=}O$X-U z2be4uh}^?865{w-Za>+X}9zg+F za*Z-iaIPc4C8C(m&)=S>+@{TwA0R9awgfF3rbHXYr5_k-3F9?U zYe;GF?5Wy$4%xIfFtn{k;xPjB=CAkSv8p>{!U*A28;H5obE~GOBwW5M=MUj~?eoIF zuSKAeVCvl&!?%2u`=gE|vhgdRgXAn?mTH)Y*UJ1meM(6`4e^aF;2dJ9NT2!1NtJ8@ zKa50dX&)6j1|>+{w^ufSn9r0=p3eYDE!7!q0R8gzr(O0`Jo#~BJEj&iTSRiYkq=H> zrMNL4nJ6cp7olfPK6ii{a+Wh&kT3}a222R6{CKn6JH!U&pX^3eHc+b{8A@iP&yty79q(HaQA>z2vPm|e&3{kh{XEi8oK9zvSQ>3kRf|4wUSTK zXM>6lJXx)H#TNdzgpX8K^mWIMfGpP%Wykq7yDZ*5xu za^#?hdIjjiF1NV;%YY6?|HHvlwhyXdtk)kA&RK9!*#$n{oFah;*bhjw?WXYDvnU1) zl>J zdC=0uGsq=*b5zLA6($4`pY=ut1YNBwCwjKN&$dTvdp(4iz$z_VAJ?C|B~?Be;tapG zK9gZbW!h#LW@M{<15mc;*%9bxE=)KdO5Qy(X7mDwEP4|8-!2AL7L2GKJ{I~5EZVLZ zIhcr!v=z4&7JEyA1}qRq=5wZmeuXkz_Pt;9!^;+^^LBB+U!1KDhnKs*R*7g{PW#Y4 zQxK!xJ4TNc`54g0!5Qn6hac{HU|0~ciu@YS{qFugFR2i@)u$&s@pHeOXo?A0A=_$L zpJTGcdN>&Av3RBk`0`Kv?WzU~wV2zX2bG{rpkYT@wD$nf|&R$N25 zs&_6JE!F69)id*f=xO0(@7V=I(C769>*eq9OYmlbGd0V~?V8yWY(4Gk?b zQaqIkQM86LHw4&aO7ZgAtCB|Ktem!|#1)EPXh7jM{2Ps1`2!lif-4%oVl{_6>Ho(r z*^WS2aO*Hf+0wjFF0gq(d21E=)G~^EeB7XV<0o7oDfpqsS7`j3) z8i|c;+=fI9AsYEvN-TVVL2^KjL|jLJ=&YZQ$~hO}KUz;vht$;o`~m@L9IHeO$;l6l zjJMy1Ha$;^ce`C=OM^fR;!V{Tu+x|v4|u6zBBE0pwh@fyDP+TiyKSLPlq3ve?~mDN zDD8vTi1-}Y=f8;C;g>Dj6#%&b*aHh__a|W7?6dec{?x8J5t|_XnSq4vKf_t>K*Hhx zyIp?QpSQkYpMz*2dI9d;+8YtbTel?$*ZrZ7Km<>?us8MJj6eyq+`=H9n%~ixQ66h+ z)WCW*i<)nJx31DV@gc~@4KaIR=$q0y1!o%FAio1Z7wI}K_%1gOx>P)m$GN~gX&{F6 zgs8r+&fKjLV6p2uiAqVDSMDGbhSoDFja@52UpH-+>?eJIqe+9d)lcuDy>_s{8S1|5 z5o!7O*^rC=h8O$`n!aeDCjSFYJ#23QuZ9v>Gk97(m<*$zV(zB-l{vJ9KNsz$r#4QK>CEx(j`HEL0G9oa(GYK;W~+Unhvnw|mV0Ndvq;lcskI z6(EFHn735ecHDG%{ar$Tu8Mc&tz*IF>M=0;Ba49l+>|H(3ogLJGe7n>7l04M4f*KG zc?fr7@v`gY-aF-3U(8sJ(Ihu2@p8>V;l}Or04BtuZ9H6}i#$MWRuQ$i)V+>Oc8Aej zjj51wsg7!+zYHH6b?IY>bqkNgZ!LW3?s=>sqrEWt{fc?H>Jh!hk}WdHr#)d`2Y1|< z2*LFe3;r>^xMEV1NtQu3g&p638BQb)I!{{TWz;%${3nU8 z-v|DYOL&IBV_fB+dtBwHZ`_69Ur0U5PaxzCrD)dL5Y0TIh|Lm`5Xd!*9R`tLX8#hU zY_E|L+Cz%z*?a$tjcPwsl3`%28ytXMGT%vEu`!2Ta_%KP;R6;*`6R!>b0j~OxhXx! zbBUfPcGnZ!sRqba`G@ly+nA^6FSP0=AGhCdF?o2}9OvlqTwx(M2ZgFQEn!}}Qfz^c zzg`_&Ebe<#$aN|H*8Db{8&VNIRDllk7x;q6IFhdw7y*D+R=}4ZC&S9>1Ng)uk8@DK z4jM^h6)m=@p-pAMoH5WXdR`(>_PbfVJiPWAqwD78rz^sbdh;mW!$QZ{Z zj>=4n?*X0qjPWw1PyWQ^7UGHtAX4fuG7Qq-#DK->>`Sw(PBJL$?cDcd>J~JlM&W+^ zcmWS^Pv-;({*i-xIc1i#dE!1r(BNojj$O!7fR5CAiCmKA;?=8dkC~S)!fO4} zsofUDL;4k*B-(n{oJY=_QC!^6uf!W-Xd`9(f(=UE384v=V%x>jo3d%3 zhVn@{qF*C1m^9^KPW8u4aZBTqRsV1xG9{aR4cn-hcOWeuOJ#7W4P)dCws!^~DM*LJ zhM4+_+D1>jg5jQT;^rM0ep6*DO2d^BT)0O^3O(WvJ71TJR%wj}y@2?=f}7)ZXbVo| z(oH0uQ|iZ_Vni9P9T9;iAM@iIkJM3f_R9)f`f!`p*UG2VDB;;Irdykfj~g*CA;^3z zq18&$3pI^XPjk=U4$JCdQB>u&cQ8)^%*YYNtl=R5ss0Jzmt@UFj<`!V{oKp=pM|jB z9~&7m#|r(&)JLel>`SneUe;ArV0zdij6|b%jw@Yx#=3O0s6fp*j5@P@TaoxKs;@qX zykV4@&=R#*pSgu`$;|3ja@|;n@FJGxHlyV}J`{ujlF!7#Wk;=_kSTuO(r4|?7fA?N zois4$_(EF$zEc}>ggYqHe5qn0lGuyr^QbQ-)b6BXjF>pfH#ZK$gmj?ATBSS6K3x*m zCu<1}L@MPnG3BYbtveO6 zR!{`7nyguTMvbu+c<;}~nxgiI4aTM3OZE!yq9Hd(8vQKOXOV^O$%K|an8Mn{`eSTI z&llwFQfK~z;o4c1YvWX=hgX&qSpTQwkPvx9fvGeo%=3nRTzp%jjwSL=-Lr1$d5~fV zhxPLXe^xlZm5U{?Hkwl8<2_+KVuA3Nio$t=)y|B>@6@8tqV_&1D`jLB8>N|+^YD`G zNM{>HjHBJwZ@Houdwi;7bD-8>`)>DcGv}Dpmp@+~z;I8x2P1nu;uVS^%c`wk5AD4o z|3&bre%6_>wEX!t(Wy~Xt=6BlJ zYsXM_z8+ec&`eNi9Xg7$q!vi_mt751IX;xe5#KHE%JF*B!}MeU;otbH{ZAZ1vjnfJ zw^>`tfWdE!;F31rHo=Vw%nKA~5)mf4*QIO?Rx5l(yTB|+-k-^TTQ{sJ8QayVL&Ew- zZ1Apzaw!|4SA~7`0 zQil$~D}~@RMP3NKqeebZq{`)I1Ls1s{`qL5L)a*p&0N$}Xz@hy&cor7i8%a!_Uobw3DZm`tOa4K9^x@({BLk6FW+im&#$$>sc{ygC!T1LBD)9tXLw zlSRl^A*~C{A%Y+Mu6gP!Kl-w}d`(uFmwQUpcI@m7G5$qKFb_%mt>A5!R^Ua^YTT;ok5UzWF0P6Vo)4`na&6_( z?2f-vw3glFJl9R6Oc%kIkZ)P}pCN)4n>etzD~w*j!RD{J1yuW~T_5)=6nKrO51v`X%72QEL%nwM}p4PL2j#8|kWr01JT4o*A`IjhIi3S~FlNRfD!X%puA9B}TV zueGt8_27Z)R(Ov26;2U(8yspN|53Lu!BJp{7>e))ln8lBKm%$tOHewi!@$ zOftwhzx%8&XRKS5a}c$7P&IaNuQ2r?IFA*%vfuPsjQ{3(vXq*oKkXpr>ob1G>B}gD zngyxJ$6Xbrf}WlkL1hEZDEjO``_p|XC|Bw+Z#`$@da4dFTIh0{-d8bZoi-BrC>R$+ z8iyLyMmW(0qeQ&nS>_SRfa)Zh>coO4aQy;)3>!ULp!ooGaU~iyft~`FJm(>SuKUNQ z^k0~iTzYfvwtaOjfe+Kfp+ukY3B<1gON2XbPZlRcAylfkXGEMztHkJpES1XgrXsSx z)=Ee8k@{yE&?ot1+fJ)8szazY6RAh&zh$=2=U|n_^7IfQVdXxo14$?^`|~Ml!z{O? z1s~hN;i3mC;VL2KPm4P4hv{tN+c~&$)R!l{`c?F*K=+?awIqLS?G+0?_MR&q(4duD z3n}^QHGkpbASu64vqMDsE(}*E;Kdq%6GAkqS1pR=aZL&E>F_(5K7el|BOSr{%zsh> z>M{9F1DtnmV;@a#Ztb*_{t<5b-H}sV_&5VOEg;KgB^wRv2lz@rDu{GqllA;or@*tw)1@`^_{-e%DjIdd38seNFkBi1rw9LTH{!;x%_NPtFIZyjW20lP>g89~FSvHg z4=RHiBi$x@{zt(Ou`jLRM<2LCN;bCq^t+#oT<`}CS>Nz52*qDgY?uNN%AO_jEEuA$V z&jNqP0td$ee;2O{I6i&7weQP`vEH!WqS+Y)lkBXwUeiz<=s0_d`${1RFqbZc4?EGw zW&j$wiNGgf)P6eDx6>a;Myca8hzbukSJzA7>zFSH@Y43V?~kL;NGoN<7?lj;U`EFI z)(8!opW~hfKG|>$2=0MEiBK`O7o<01DCE75-gWY^jS4Y3BAkFQ*aP^n69JFCXEHaF zF{qlrHsQqt&K&&ObBk5BhGNcIF$6*M9kP^(zOoarl$$;bpn?7ksm#8`=lv3DWJe&e z=cejR6It3ZrbP&+FBS~E{sv~g95W2nofz9^KnmisPVUGj>*-gWd;?CQi7?u78u`^Y zdc2U}9xU&#M*wk6<14fAMBv~1e!I0kEJ07w$0+sP`m{Zw(nbF?N@*?TppYl24q4r*k$eaBpiz$( z8-EX)o2wO61`0QkzZS+_LPni{D5{lDR8KIl(7MdlE-^gqKXLn7x*3CEMCm>bH~k&m zeOkL+rM!n^d}H%Tx$K7^4~GJ*N5h1O0Cd?P`tk@Bv-lF@LKJ6)g3Sf_PIY_VLL?%^ z|3xmi^P=zDZU_I>XrNKv#9dAZ&tP)2pfP6(M-;QvT*_had|cs@ zSp1r_QT|$FP7hGCi^kado3CU=++*7FX}UaR}Hu;H+*+!mM#f%IsQ|wmPNo3F>kHavalEA@;CnvD+%XA zU;4=YPx8+fFQuN&=DfN`^Af&5U1td8pi&DyVPtAzC|1&Hz3NM_iM|S)ZPB@~?j`s{|&zM5`oV3wG)JXztsZ?6HH2L7D*1zZz1}OIh z0r=lk6(ji|zcsOYrHD-I&0c_*7VOo)@0JjcpOeQBFI=x9Tp-cQOe?;3kSko#$3`-m z7{qI95;o@5hzdR2i*1BN2~G463j+#Gsob-6c?Cv+row(7ris9C@*ECa* ziRozRMQ(`{z|B(%@v$V;9!y}3Tk=OgiQ}v0W=F)OY zS-kI-oi7l&BqtJlN7}_jy`+GBSDV;S`Q>bk8V3!VrcOd=6F8|HkE`?q*jfWVCg`?X zgt=tSLyt5|P4VXKy})0?0%89rwZgf9`2qc+mllvA`qIrq3)mhsQNX0QQ$?Ty+oCQY z4LsNKmn{ri5`SVqeg388vU4^z^1A|aRD5}KRI-lIYL24ZB^}QJMN{=J8Cg||@HZAF z!)bIWhvGRp!%E+HRCHojCR1RaV2KHY<2U>Mvc3fKt$P?Zo8&B2=dGQ|NE94u&d8O6 zOJfyFj=#6tR7_2NjWB+xnq+US&@Cc!m7+;^|NR)HgXN8mp2;iHpZX^+kmb-HYFCju zQ9G2$fIB8AgVjV@G?#9&>N%c|kNwrvdHbxV^cKJQ(A(}G!PmkDF>3KIS_w`veGHRa z*z{pgZe{jh1Nz($NyhTBj0aN9%KbhbrGuADAEBO8o^?`~2XwC`dZMjxVuHeHh)}4m zt|7ICKxkYhVIaUi?TZLgmyg2`j&86KAGN@m9(&P$^r4Q4B8$>!5vHYZULq=}HlAQ* z8c|0WJ0AzU#2Aa|#tEZ!&Qem7$*x6i}66 z`N}oBO!n45Cg#PdKmekCLWtZyZexEXG)e}jQP8mzaA#WTN-?{@CP4e zEK%vF z{<{VVOxJ=mOgM&ttOAj#&s>QYxXq^*#$75)1{U@9l!Yl=S)Ab#sH6b<{Q@9Vl ze*Xsb3f$V(+U1lmJPbL1PnA*}h=JKFC(w!b{-h==%lP4msayC3@_f}H@wdJN;2z)g zMxTTidCa&1eytxAaiw{)5exn2uTnoqZ|*dhdE?mq92MlY<#gM7#qkZjsTBw2s(sye|zZZoH_9>XvEu>sN5jLwm!0d=*7M+iw==|Ni?)uM4deO1BCtLF;^V_6oi!(ji zUj$`tv{#}l$R7KWa1Z)zEj*79{gtrIF&a?(c1ft4Y$6poHgTIC5gETcbZ~T7ONh#N z-Gc>fxN|9RlXpNP$fTc^!PQdFR;moh`HwzJTd5G*+HHbaS2@Y-Hx<`huuf||pLok@ z*kryBPr?>k3P-E+~#_JuduwihwbWlA+<~G4yu&Vx)&`+VAvdR#1Kj|ux{8Cy*Nd0T&)F}{A zn!+z@)&(QrWHseZv)Xv0NrHW3qm|D>Tp0sYkh6OrBRx%wp9x4*uzb;y*l6Ce@-onM zPia_$16Sd)+8!{Ovj8J%PTRh%%$pc~ZVoj;{vDKxY0-sH6*swash2^aJL|#|ZPwCa z-yE$@31!+iT$x+(5cnNto|Wg4MA&DC|Dx+0n*@uNHe2YjZQHhO+qP}nwrzJ+b=kIU z+t$>5?|hk=n1~ZQ@)w-Qojcch4vUZ68ND9g#>ULlQ27^q7`<-BF8iu)Ka6qR^2^Lb z({-+c}s^mFxS`zE3i7hF`d{rAshpZ}c?`|5E7m_3V z^KEe4Y*P2rG>%WR$VJuN!^-!S`Ypu-Vrp@vS%jtS{*a*~MdjrHwC%OzJS1Qyy1}@k zj73DqH$mQF_KGAbXpHkaM`^|?#bZ!i$4Z9d^v;La$V%^-%5-nPvXjldzLY(O{k}T2 z&~C+)60+M>V3HFg3MIHNdtbf)VU*P4Ty(8GO!tPH_4g$WZVZS0)LKTLmD&`5$|n`P z+`sy4{(SBC%slsjGz&+GOm*;v1_8!(vp<)`{jwFjEHGj$(;1-CnV;LtQ*P@ikqPI% zDe4Ph6UJLHcZ2VB9I7P{L96siOps}!G-v078B0=n+!=hCJkFwSxqfccS2`y9^i51D zOAKtrRB1(2`?|I!hwsgZXWcz0On?A-btnQ?PQBADLg-lohGWB^sHDik$WI zET&zZvCf6bQySb=&{7C)u^mYXXEN=TYP-HoU`n1C^i)pJ7XbkGHnj-q@B9r!fej;OpHV5;Dp`#XsO9{5$hDkSkzjpj7@6ba?WB(M( zJl3$($kALdx)d?#KE0*q`@KW09vSYa%Sarcs+1poUjF+hzG7cjJwwH=pzCqh7~MMVlIh|C`SmQMLj?`aY{F-O@PJQ_ z#4na6u#Rz{Zy2=MhEY7?fYFw|ffGN=uF&eU(aSKne1fAkf9g}?Ipz`H zu(4E6!OWi|(B8RIpNUg*OZVY4=5CihhJ@nE z>1V>(kRyd8T67l}y*nAtb&x7BEms2Q9ip}fve=SJB?G0erJFX~b8!F5b->?OMiw<8 zb4YTFX4lA~{=G-JJ8S=HT8F%5YGQS#`3-f$U>#8uS&g)17fijg2yKCfk77#iY*JsH z=4up$K-Wsy`=PCrstrV2AmWT2Y}%19#HF;21{+PE$M#pK@s4s<70@d!0OCu`0Tb+m;8$UGpWq}9_fo1&5qC4IgMtATY zBKr|d6XejoS~IoCfepbA{z!i(mfyJ5j9=A-zb>Z5nAe5yXBZB$iFmHf9mB9;Jm^8u zH*?=!fv4KcE`rMZKgVNazC==~7Kpq|(LP07ITe zuK~h1$=@P;lIfsjO~?jb;hS5et9`r>3Qq%Wh-Hm?Kpaaf#_F@Srn~1Whk~wn=6QIE z3ql~?#S3Nj{zoUR$noPBfN!qhINjrdOH?PutCi6Q7pEo|xsqWui6WEbDn}?x&N56f zfE|+E;sa_-dPjolU4_t*Q;b;{qms2uM(QbFjr6QjVW!j*==0E~3)vY%4U|#G9<`b7 z%|}YhbQ6C$URkHQOw+5H8ZfR%Kdpy5EQY5Cx=3MnF0*R@fy~^u!vka{?L_<6LVCUB zABl2s9%5ZHZ|z)TM#cKh4d)j1RCL&(!&lK)WFrSW+|_s!tk|S+6=cFlPd~(H?s0a1 zT^ZHT^A*5QNjhe^4^U?SZYr%ncB(pb;R|4-2l;V`?`;JB z74A_dt_dTAs)gDQ(2h7;wI}K0Qoi!8ItMwGcOY!l=vewWEL#wjwGE|}R~UJ5mcD6N zs4=a(?fVvPhS5~_RJ~6-J%1p*ME>S_?)+K)Srt_0qsVJPUYQZEpLby)*cjAeA<%t` z7i@`KphC31PfDQqsgN~q5hmFC?1+xf+N@*sz=+`dq5a7J{1D%Lb4!?fxN$VJy9Y?< z+~Y;~t}6+0$2hmcYTxh-Z^13B2{XSSSpPrDAG$|)i^r6zRCCM7mArNC+i$#``NiK> zeAkHAJ(?G@bO{P#d82@mOj%?g3#M9c0NJ*D0K8u7)=1VOR1;`z{jYemb#^=(`r#G1 zhmHA4sH=_ni<3adCjN6E=Jv(4tA9y`u@twPw?{A-f40dUVajU~DJ}B9+b&x$*I8$J zTO54K$y4Wp2aNpD_N6=Ajx3DQVh^WJ=6mL9FjSDvuIH~q=C9lYaphTZ8l-XL_!rmK14qtLJw{~zOl~_Z{PN>! zTnPOfU0eij5J$^?#g6>b<9Q%P6jAuDJXqQ%-cn=QWCIR|KVBF>(jsGtg>i&6WR!eL z`5G<`90r4(*1s@mHy1(fB;tS_V;^dfWY=Z;9D%O1ywfz0VdzY03Ne^ySt>Gcv}_#= zDg76tl^pFPD@!uqh71}p)Ae+%G)MPkDG4RiV2qUtWXy_iG1Wm~3dnZp5*3{P3AGU^ z^mpb(28K@-Dk~EJTaCRbx~=B3#TLZI@??9ym{|^myUfVf*oc7qtO~=p0XnOaLUJzG`{@Lu+-ios=$v!8KmMLC8&UMb9pw9dq;keY7-xI zKbqa`{?+F-g<1tvCcUo#iq`-Jh3X_E6gwgP^z^K{!A8{%5z#(U6*o zNxNXgx(BW?F5WzGa<_UJ1zd{NFR1lw1|Aray&QMu2X{2p!g<36rB=^Kk!v2H#IRjx*J@#)}Q5(KXC@Sh?`Pk z6epwp;{F{`kZuv)Btm@IcyD`~8WpIo4$teuHCvBnFCZ02?jzT3UtwfKCdXdDA}qJQ z>JML&n?%^+Gd>4gdgs4stDT=;i?j(tK&=B3>)*ECe9du<#?bOWQ3Mr~@}S%O;Fb+t zJge8@%>s<7)}=cVpixmj6(5fDZw<1k#uuUDEB+WLq7~pt6WiLEI+-bwLBRy2gZ0d| zq}Tz1ys?sVR?^9mEpZ#alUwmwzQ8fUdYMV}cuTvt!Fvgruz2a0^;H#_sQftrC!YSF zM!qjFrWsM$QO0Z64Ui?(Z0>+Hyz}~fcLeJhe6U~vKRNRONc<<@{WVzWhNIw;`a76- z7q&=&_Qd=HoRPYrFWJ=u<}pVL0~o}WiSOOd#llRQA@kHCA>KId%)ffJ(vL&<3SPBX zBR(jL9T4z!ixQd};U;}WY7|}gxa~D&|9HC@A8ArgPb$SI+GYeM@11OwTa|DK9v1!S<$Oer#3B|- zXrfqh>>OlyU5ri{Nq;!p(#cwU9c~wg(^~m6Q~&W|n6rs6sDwcJ$JHgaSwzG7=t`Aj zf5$p>2tQl@$=NQCgUJ~wT}gb^EerE&45lB#m(EcAy z;MZks8CMH59%Qf?z2=gOV;U+9d_O`m6IJ(2Fas`NFK%1nbE_M$(+Hvw;f{Y)l0((;S zqMyO8Dhs8`Db^ZCKzXruRjHD{?G%)}l{iQz4-b!wfuI$REhF^d5SCyGpSCdm_p}+7 zY5mH-`c^aPn4&8BtWp^h0skzkjQCnAZLbM;=fzjYA&I7e$u5GXFZm@3tXnH`nUjq| zHzGcF@R-%uLsC^}Wz=K8J9t0J8S1oGfeE5C&ekLupxC9OfzjT=$V~z}?H88N1V(pf z;<|9OR2=KR<&sKflw=ExcA6QX4Qz-qE%lbF>bV<#cw{Mc!C}AjeV_bvkhAvWRHloa zweim{gC(t_P^%4MQ(mcnDZg>KY0%6X?|Rm~)CC4?M%z`yo-+3Az?K0`;Tl$ccmFoB~bSYn?B%kg;@ zp#>S1T0+Sz8A(408ahfy;%3RW1_g%>OHcA?a`E9yuAbXK@5p6rrJ;l{t9IpNsd%QI2?z`*$9n?L1Ik;m)=3RvIuns zpySU*feFFI^G77BWcn|c?mWJ0ud*$t0K2EOV9J|>Zk+ZaA(PyA5vjANx+Krc%8He} zk@-x~R04ZXT+}K~o369nyJS2Z0vgH6EelBjgIo(7i6vF`w_MUU@w_bA zNWJVhdOpJiW?@lUVhhL6Lf%^xJ+D;yZzIGt;(P}10CF9C3YANcRoOAlyv5@c;(O7c zU>UoIMoy-icp1bW2Un#nA;-0;KeU`IVe!++d&y2Y`!jRK-Iaw|9*jSw)x^pIi77y1 zl9F~=93d{2lK5}Q68@=icISA@6{jA|XN%{X!>q%@?gGTkOzr`IQVrQX7O9yEmT9oq zIf9;tlOh+9U65-(PdCrzrl)J?2ln<{$>Sn&bjpDVFf-26)qM0+Vh#suQ6%FqRCC;s{DgRx$^zwr&Twiuk0; zTVW_h5Ep;Q0Nm4j>_t09$9Mu8Lf}l-8Akr`K#T#nS5O^VjN_bQ-s3J1%+4=k)t9zv z_?6x?)69UTE9#T^r&kiJO6raCB1>HfY6sPw59lHrlwz%Fa zS>iL7+b*uCIeQCq@rNRREW895c^RMsmBVQwjjw>SFFjGhej3PxdwLd}>7r|lR56oc zB8jF{rMIAqO^zi1Arj=sVN~NUWnzi2at}2(CXk5#ht`cGBfSNlY2<-h4a0`we~vXE zp!*h0uid3dAMsb9POvtjM6AX#u%g!jDT{1P>1OA0&$#LR53H+VUp)-MTbF2NCEOG< z_M65yyrvKWXza5@s)aqZ$vyfICyF2hl>=x3Q zVo0+hASHYtIK(x1VfB4?5tq?a<`xIA^-8oAeG>gSV;mP3q{DkxWRP+zvq{{6XrLN< z-J7tJ-5^O4G*wir74)@I^9fpHe(5lpJkLW4>+6>OBa9lJ@aiD7H~3m;Jrb8s6=Z`j zxA~`>ls!AOP`g@O-bP0EKh19gVy6uU(s6QVX{Tcz?b}_9k5l8bhvTzqkM$aux)`6X zCby5{y|YPgU{pawR6<0rPPeb)yNBx$6INuk0#jB>CwVY4bZ<$CCRl5z7XR?0KYGX%%yXl-w`0i*&BDySW=(1~xZ1{X`iN(LGPwX6J0OJ4|@~(OHkl>(3gI)kFWdJD!X>P$I_pZ zwfW~`3`vWoGTH^ECmlnfPF^cXetf%^Z%4suBuSuOO{_t)JqvfEXp;%&f`_i%Gcjfq zn0G%(&Dd|!*SpchH_ZFz)(LFwwZF_~;`1vrn&Ml3X9(23v4R1;0tCeKk2;(j-SnFe z%HwC{|$Ue|Z~)*jl ztG@lUu#W0{DoyOll+7Ac$Oyni2*k7f?34YkK&v)s9>vp(r;q9@ACj9r^SN`iRX}6q zP-H9V$$qk&L|O|A(et>rQJC3$RfdgxltXnfbVC1QRR}_?9ad9h_y{|PihG_@Xg$PP z_#Au*v4)6&4ZSjk5~2i`1FD?{gCqEIjx)K0V7a{WKv@7z0d82m0*Tx{(m*p(B!5;y zl|O$3kjw9Dt+(~n+@uBFpbidMFn;^6tK$RU0VH_Vhd=PMp_U5<1}tTuqA!s81C8DQ zHZRNboAdqmxZLX^=hG!vQc&eT+U+Efp!djy8fE@#M+(P?_BIy29%OBpw+b4ZBXDsH zCxD)RzFSkTlgI$uI|?j(dzzgG1Y2AGasgG!rJ1%Wf=IEIL!|@w;I3on@|x4cQNs?|2(zCzO;sq|}hk~3gLt}{3 zClA7S9@0KXU_aH%O?>=Km>I0Y@2Xa@n=D$RD@kWz=gk-Uqn2SAXRmXmTD9{G^!HW( zV^-@h;eTjbG+l@-o8>U!XcqIo0H%>uG;R60gKXg1d?;V>_{qJfaucUuy7_g=e6 zGM}8*$li;tZWI;ZI#UtKKd`TkA$Ive^cJwC`Upy5B2N4IMfW{mu^RLqOow5Dym74( zYTeFC&0BvFo zf2;*HouW0R1>G*`yyRZB1&}O8{l0SM>R|XWQf2CJc>-j0dHkGxJ>0@OdH8v{KA(LR zRfV}3>6M2xBe~^KbFWTPg>`?v)zYce;fVV!t>*@qB`wU5x*4UthHVAF4aD}PZT|bY z{C+#x!7*BvSpovKnJ>H2>~eIwT2#2}3zCDQ;cokR`n`{Jwg`Etg~j%ckn##tx0Nk; zq^8ZRe}&W zP`yMnWusU_c|8LAHWNtx{Hk85-MD1On2CDZ$(iv$+LQ^0{C6OQy+*hAYZE}lC}3pg{5jCF zIqs+TCKM(kaI+q90~k;)qGEn6U`p9Wy_gWv*itN3^?4$!{cLm5#1u)d1ltYytbQ@$ zrfRXRqE6Aws=?a4#RMFS_e2wLvh!JMvPZRCA;2?i$`8>lRVm<^wg{v~ya2o=`;-vL zL9FBt$*N7Hs4vY<EJYX{1S?E9?5KnuEO8yhK2zxT(0=d^n~hlR$>k z$cr#y_3;l$XdFWddYbEf)P8uOjOoBNCEF9l6CA>LzE%xlZW=3m*?uyWR|f~~E1gD3 zDm_cdr$OH^FBXm-An|FazXJ&@qq_FhkOF$y#4E;Pm6@@?fwQ%N(o;c1584uh{QA!N znEfdD>--IDN+j}Mon_j@y|zx-ojy+0j={*`=P+COc$7Y{Ntm1E5aN0j(TFzy+{pZI z6cfDtxGc5oCc{i?tgOQ^t%Jb+Q~?gTr|G@nkV<|DQ5^GdLO<&8wD!9HeW9m#@S$D zp|Uf+^P3lQpW_BlZn1FdgZ!D!#T<^e!S0=}`kiS$wC{G1h%q~gHRJERd=1?WBX`8SDyH8iURT6pe5VZX&-Nmr?)Zb6dCkhiS+=rpg;=oj= zM4C zIpvvkBgSDyd)Ih9Xj0~P7rxZx{s#>@JzRI=(Dyz<2cRvwpY0AN`iOY?Uk>@sO8Q|Q zn#hR`&Yji@Gc~?`v*^FWvx^(8}0~(eqiq@cv*QPaarZtq!gp z7S{~iv>u`_fm`0@MwjOibj}}~{+}VQ;ei}rzU++wnf3Xj-p&u({Sy7ee-%}eTmGCj z_uKL{o0GNOVvFv{UUud*XCqHp>HRUa8}mG3xg1Jhu=*Mv9S%wOd??Vd_Pc$<4W39g_?Y`gV!RC5{RN;6hS7bRpR>|<0f}O< z_xDf~tiPr%mz%}2aN-Caw-O9@qf^oV;A(mEpYcjYgN6l-iL$TBi;IOu>i!~0>>f(w52j` zg(3~;W|&ia5KvxstQST~WPg{lax+s1)SnrW23hz6nUJR^oe`gF1L2n#c2Qa5X>S&$ z_Kt!8uEpni@PQ}dVInd;0ptLVC%Gi6g3|~z5{V^j5zZlyu`>}VFJj(&cWPf_94__< zHngzaEHFlPuiv>W9-u|#rN-v}_5=dBXE}Lt0@yNsAqlQ#14I(rwr130q+y~3ya{V* z#2S!hvdx-}bGbDog{{@)hL|#5 zSI1c$S$FTY!fT>9{7YO7lJ|3wiqrG4g?dN{8*#t%X7{BULm;OqUjZ9K|HWdeB==Z! z8Uaa2#l+@}3|zN<@Ge+IRmY$1Jdbc%fE`YM4H@V-6l&?Nu^S|f3TklA1j#Mdawjd?k*Vzc6Qw~%5bn;JVj2x#Ta$3WUb5DXQY-y*j zjaHau%-H_ja%sR1qL3PuE1YN~g%+S$Y&3*GeYj=hZge4*z2O?bn8qYFpoGcSJE3DkjFmg5nN*lL} z|GQkkGIqD@D^ISP^#U^n49$OJI8S3ULysl>8BG1-I@sDqv!^lzTvv7Y^QQb< zQ?$b|CGUTLZb*X~x26G?8Lc7)bLHVn#Z9QLkg119HM ze*|^4xSuzoWo=83!|AA}^N;>_M6!-dl3KrdOZlxOgF^`?L8pq3X7Du-8Cebdp4_+O zcr@y9X!icb8ufoal&wCw%&Ej+uVM4d(p?`)3Fkk`%Sg{9179jSbR{sq%bT3JL*-J|-*~2OqZbrw%gq-X^D@B5-r^ zuNs9~sh8G+yXy&nn{3Z^*;o=o+e)Dl0&`^IomeLnT}YRozN=}16Mis~)Ml-)Ng58Q zczOL!mJ^mY@rB=rq!w+Q&C;OmV-!@R<#%ECNbN3`EgtbTm9EzHm1>u{+r4xVNN%Tc6wwz2Lfzi` z)T%Y;$yV(MYi?3J4epz#204}_*`Ll%03$#} z5Q=!WM5UR_Q6wZ6qd0iZLxfY_69$7>UGf8wD^tjwD^t8O=nj~xu*$n^zu1cOzAg+_ zpMVNYy2R!G>W-gk(h!~d1}UUMeb`_bH8ZGU8GTiw|K^OVIiQ+mQ!sq{prsnnl_yH{ zqkHA>U@h8wHhLO$<38T26MJG?P}~vyG_+>Jm$s@_cl?t~70y2XdF<=B`8ql5RD>LB zKw}_n2&zTh*b-bDz#nZkZPHhM7^pTs}{h~Ox^EL(?Iqt4FNVF*zhl5{r3y6@V5TorbT@et%&n*%XL1QM% z%|SeGP%;3NIeQhAgT6NXez(5*-pt^X{g$}!Z`^zg!T^ZgGh2&x0NWle4jP(wauWZL z#ZM7Ji8Xf+DyzWd5LAR=;gU2+l`gY9K!**NF1M03J~Lo1xoctK(JT@ayO>$ zsk428dx5D}TW2`3B8;Rh%b)8=&@et!@SvVu^5M)Rni|gy@nZx&1JC(ioxJn3BL9UB zYZ*Z^t>$#ZwvgQK7NpncBSUr(zq_yN$@=v`l@oAPSnMI_5TEbGPvc9?i~{yp_s*Bv zW2?!5WUS7IcHPaJX`S1O*H^FEUG2d(9ac?7>SAWbwF6%b*fS7@TK)bKAfSyNRNHx;)j`rV6>7^a2>cjYaexa#rhPZJXp$Yphz zkl`P!r}fiR_*_Gs*D82b^!?5I;uU0}AmWVOA$}i*Mvl=&7KI#RKX*D*UFxucWzfE2 zWF~!y#_^YlCd{fqugdKEEqT!83Z-LJZpGnKxrFS*V&!#a2Ygh8zfX&-^1B+hE~F)v zIACHg`MQ$$B7s-A;YE;kup_W$>4UG*JX9mwX9r$FO4^U+);J#_`2idbNKyi3FX2Jx z%fC8tB(~>|p>KDZ!c-U%LxR3%LW-#2Tt@+e%Pa(= z71kPVE#APBsKGrJ80w`8j^PVr{ zGlU-%YD4E9Z{@_FE4yq}OZXpBUY{hRzj^bpcdA18S12{`b7`DdgBy08tDpi(bNL|s z$=U}SoQR;nD2h@^1^GwjlKYCR418$8w#KgN$aSRAw*9B1(ccMilo@!T(S;#)p`N-F z^Wx-Ush#oy?VDFwlM7kl)8M}O)Bcu5!|X3| z4vnYfh`z9uu;EP+vuH)x7^b{t$55tpN5}E7Vjhhr<@4c2^AL!O+%GYuRN+;q*~Ex= zPWTyc%mcfy6W*|nkcZK>2;`%RUS9l?S~Hf3qMFc$YYCANTE!kx$N6!zK=J*^JO}vF z%*Y+sVoI4wy=sSNb*h9ke#h&1!g8ApdO*^7`u#`~{BoPUC9c&#q{0R=?FFDhU3%T8 z#=yQMJzJyeIIN?}6XpZSJQ}GnQ7`N<)!WU|lA0)r_MT+#>kQxEIJXoJ$VCB1#COXd zq@}+u^R04~qE(5!4C+5TMtR2C=@b7*_J;6Rqg2^O^y${I*SR|zOs#R(|A}FHSQ(i- zKvA>*^FS{ew5EnMEiv3xkNjvvZ=z4VAnN!P5Gc)QejC39fHx7E7I*r4oO0xN7ZGpK zNq`x6z-4%SKEPkK*d=wC#c*OX|KjmOtrr*4q!UJngyiLStN7jHIWpv6!)pe#b(bphoaU5l2Cj?z_z=@=S7Tyn! z6`G=nD>TALX$}VJw}5uc`*urb?AO`G@s-2kRz1e4g2Jl2qqR&Rs)Uee1@(spvKwsy!n(zCEARmZhkun6M~UC@9+%uN zmYB?+#O?`-FuE-Lrd>!UFbHD8MWN-Q!->F%ja-UYaOo^#(Y27;+UlL|;C6TVxEFgG zLbtB;87-|5z$3Cup>ri6-MU*DzOAh*KpRhW8*|kUrxO&iuCSVjH{`E%Ocu2IqMLyZ z7L8kF@dZn@(EB+*?#7^2ov>sFWox+8n4w*%x)yBu)l``~XoY7%J(wQ8?|tLwf*ev^ z>vednOgOjK;(3HQr{mY7bU@kxe3(bP`(=P4i4Li;WRB`xK$FF=JBlH#rQZol6WS#! zaY8m?%aPOdTcpsCSvw}lZd*q#MLo|8SK*?wZ&^Ov3;*21&_B_3v&GQM5J@k9FEIBr z|NqLLJS+p{YMl|n2VfgoyTRW?B-%RF)m|a_F$x7bRhs8YHm$GdvrlN(gq<#A#czX_ zgm$#808N+;G0e{MS|U&DE_sO`Ck;x>0zNsI6=o&oDP$R@p*XA3-8nfEs-Zj))8FK> zQEPQd?7s%qR_KwU%?7LEY=M1xfBsNDF;mhGz_mTzyfQ(FaIm1lyF(~l|_A*V+9>vW3*!_Y&u=+X}pAidh? zS95+Ee7R0$fD3Lh{j^y&N7h%2mQ}`9~)MBrPdf5Zgzfd z&)A&PDTU3;^3~Pr4xAcWsN}MPpI3S zi0O+B0mF-v{(f(0Xp+Nhr(K}nrT0`KTo#nl8})kUNR~0@f8q?+=%`K(^30zr=d)|g z9ZejOOsq&dBRcgAr0K9V4Uv@?)x;x2B3mv=6udft2>x)8gp4y`&;BHV&LNoWv@rTn1Fh_dTr+>3__h(qSP_ z_N`DfPv2GdTZEVIzN*QWYHD#2aUipc+9cZwJVGyE22$P;0?7wW)d z#xqs;q?tORLzg+3A~ftEO|>;VBTfBIsArBMk?XWHGp7C`V9*1S$O|IiC9b*?iY=6h z#=HhOf-1kx3TZ)a0r!tt6Cf{&1FGK`Pt)J#LDBQ8?zFt~*#7rt-RozVXZB!(6-;qe z^P0R7-o;Eb9}YzA<7lbV#B<9)ziO7#jI+EeV=FNaVAOj9@D0UN6rqxN;~r5F4Zh=a zO(*r>Jr;`dtEi~J=vW8ER>?7WJNDk20d(_`q&ys>RUZ0Im5IflfEe-C3tsu;pjbsu z1qXDR@747ke<&SnJF8e6P*1Vb!*wJrCA*}fGsxnyi>vd~+u7sAwkNU+gCuG6Lx)uf z9fqAAsx+?&2Z3JCzK|P)foPjlw3E=GfPd%G2gR#wBK&4BQ9hwH%Qj8jK6A%YFY3N~ zi!Hah*H6`8Etcmi@XWP0%OX3r4L~1v!ipXvE;bbnC|wq$X&^C2L=YcGTMp>@Bwt_} zS#$Q=`fG3b4n_XjwRXl@kFSfRIZ^Zm3e4?zT6qTV?RqmPXHP0os(-|P3TWo4F_Ga2 zX5{jjo&h3>INb-%*>E84wWb(~GcKwNiiN+-J6*VLm;m+G=!lN_99am5PQIc8vf0C%RKTLA!pnzZHVrPCCwXym}g zj|vZ+ry#9)el5yjGq2rt8x3bBGS+O;yIVLNO1^o{2rLIw4NrLHOS#Yxk=8qF+nqlm z#111XD2wP8i3aSSTb(Vnev3hn>k}7YAIyvqH_(o5*`I;*fK~smJSfW78->SebkOEq z0+L=0;V>xo`g#s|BBZ;YpoS7^lp8JF&@q7i%zi7#$|(lt!~{?*pr?C@4>6rk>jtdLM%)|E zz)V#Wbe{q6!z~a|2=aL4RjD}XqOE5J#cq7iIAG_~CjctQ`a(w}G( z4;UMhP5LkxD-?RLKDjIa_H|eg-h7F#-K+-wTedC**TG#8M;$2_e?0}7GGDwVpnlrm zd!0(1##B*t2m^ov&``*eqyNis;@DwY!<;4pPJD=(=p)!L1|6jIMH%~g zfa^ES`=J0>Jf0KrsjQY$8d+uo0 zG}$eW>%m{;dYPTPl&ZR!l}4ZZrlFyQMRygf-JpfJ#>qA4Jg?5aNUd0sKB1tNim`Do zj1`1M;2jIfNpqQ>$shW+-?*-Yz~^DcKDiIOcIczE_z;0z^bUsr+(ejEqL+v-YZ0GI zh2Ef&li4E}LpfTY`*Tz1M=HQm;a@vd{!4rD)G5@j?m%+381p7ktxAb10yELj426Z# ztak!!8Bw)Sw700%T{w+nbn6)6??JuS2MqZx5UtB6GbiW}yrwSdR}M{3IG~0pD+j>Q zG408~3qspnF=#Ays7u#)f5-P?6tHD(=$UM2U&H2Q?b;SgTGLGp=sjhL`ey{pUeGI& z-xeIFCM7`2>}j!Vzl)y|u;3+d;_f|7fnu!_8OE3RXxg786-rBmG+4MHD{dPpxE$r$ z=@YHn!}w1oeXXv@xd;o&v{V3-bbxRP)q}6MTFXF>_7* zbv4yloftA#_>G7^!V4U8qmOJteiVMDy?)d{5YN3`_UNT>Rm@z(7{Uy%ava~|t~f;i zz-pkq7^&D0;;3qf9}3D`)7N9jojWL*Uk-QTl-9u0rZh+aD0Acj9TfJJRh676CsFdu zl+(qQ7ojed^S|Wgx{V3_Q^*h_V3w?#$MP8GDXcQUm%mjpsgeYdtcp!`83O{{8=yix zMIl87Pg-tu{IaC8k;QoUDgf=mpf5aC+wG@o3^Mvms+_Nzr|ro*XLL6P+&IpG91(uU(nLym1vB0ojFqq-?FCkj&H+|GW_$nOGZr()l z8bAt^0dGB2a#5+pv~?y^*6}3X5)1h;>ssNPf_9}QOBp|z2LN}gbmkb2W0<^jdUf}` z_hW^AOF4lQi!tf{0Gg%#QwGcw0BBo@lSvF8v#EgHJ|NS9(VyWak?sy0n1N)!~Vj2wksfPBZ$zqW!km5UvLt0~s^WowV zwU-5rXR#BynttKob98zcX7v2ZYcIlN+hH1j1yCv3FIoV-1ii&un#?Hf)Soc+n9Nv# z(5eS7Updn|4)LRBbv_?efVPwdHk0|b4mjpIvmH!5Pw!MuLMz*EpJ1AUXxsNr)SzKqTYBH-*ljYXp%IKCCk?Zc@%zfmacSzsf6E|h4c~d;*=(0*+Ho|-`*sr)0 zEjF6XENwTYl338nw0e>iVEj1u34n}9MSf6qBq6C*(G4`!>5MgwO-5^SU$;(C-(=Aa z{3~78MA-%Oa?$0TXvlBpIyVYj13|(vN1>Lx2xXxqYNL?AN_sk4xt%p9T{g;xohQ`|RV^vtOELTs4I)E8K{#xmazT`fu8E{7{g1yAF@6lh$ z(GIdFBar6)?`wuNb~B)}?nVgEA9CMQtr`qAE0a&vjbEqslveI}v{6f|mb(fdgU&D8%G78LqN{<+L-S zYB%?TyP`-1$4Ue@>K{R$*3R>`gw{qmSH zo$)KTY#iclc<*Z%?Ts$cl`)jnw^|%eiMUL-;x~BdhX4qZLVD9oDQ5|<6xlM{;eUu$ zDftABP)YJfL*l{`@riTHF{CpG%}2>h(0U@dc};|7R#H*KDPx4V>~UyeN0=s??4I46 z-ZUVX9ypZH$*GOFAonaaV*U|BH39*hbHqT>bl;h;a+L%jUx?TRV7?H`vqnAPV)LVP zYZ1t&M748;JUk!82)dbZmRle3=#{pwVW1pU!%s2cLyz&X51F{bKKL~0$iYaPYEV5D z*6G9641A?~nu!d}_A*Dam;#W*w!d1*Wiu@rNu^~uLQns}(PjpWgHum`X$j(^RPL%}m_qf^VLw>oJK=8n?7ILHpsfE!(7$!Jp=Z`rpUjFC5?B`w2z!GEexkvX zoT}cj*i&)VOgev){ zqh$An3%>y4bWVq*FA)llu*FZ4S6H6Ze9wPk#^kaxQwcXm6>4po0K!p$d>*!Bvynsl zhr3+zZ-Ewlw3T!GK?9*#JTRiVP*GcAk|*tSe@6gP*)QZPKB4e=U(Xv@?%jti^79$! zmE8sKfL=!WZo`o>k~$N|w0kNPhs121GW`>)XSK9{>}83{LPEVwx*-PaS8SE410U5_ z;u%3DnjWp4Z?K-Z`aC{>Jo`z;!Or8~JVVD-p*GE@x>9C8bNJ#<>^^n@IOXiGvo8@e zd2w>kD@4&cxo73zPk>@SOkFsV#aMSLV3ugXT+VbHMSQ#Xpdxcyp_<&EXJNV^G@E|$ zc&cRD!wevEUw|9J7`iwxOKet(P(E4M{7LE3xqfT2m1eSzIm$fN<>_D9*nnFm`dKYj zDKT6dqV9tIUHFlSd7HWK@w>Ro(1SZr3KH<$zc)h3wcJivE>vrQp@7vh-d|YDRzl6r ztgadm6J z_+Ny5Q;aA;muB0xZQHhO+tzK{HgB7^ZQHhO+wST7v-`4}$s{LLNj+8S>C|^VxQJm+ z0liMpg;SUdzQXUVpX_5dg9}i+p7kBu`#m6G?4#D1?R(j>y@C~_4XvvR>m{{QM)6`D zL@0Zcz9mzddhajRE8MjWN=AR1DZeor_NQge948neqq8~w|I2qvZ-^w1BDeq3MuhhY z=gJ#TBagyMG0viu&AHL`BeYpX##Fmvq!k#n-`eRl_+K)s^VxzA-$@yqu9(1@4Z#Aop_BGJkC;q(w{Ko`?)x;n5Jt=>puU(bqHxjbkWk zLn$066dWrov{#x)5K<|a8o5GWqO-7J2Vm1Y8Dk9$2sGiTZgdc=Shj*Ac`+6c_Q2e5 zbme|O39-8PjeT}*V*Vb7C?GDmUQXT)`H=near6kbBqphI*WKsk=1Wus6|W87Fby-YmqnzBYF-TWH-I7#APFhS$w+BlRWh^es zpc&TTjJQ_c0rxU-X|92?@ENX1a`1m$3*_SRS($3kqU}Upiw&E^psYSauo1$v8n?oA z77K6Ek`gRU^prKu1>41}tZqGl_Z!Ik)kREs0cv~{fo}bi^bS*GY8KrjeYxR6BNfB1 zw$;k}TcC$Jmomp*LE8h~lEmxYuI#aeB5EM!3+bC?I|23e3(lbd+e8!*zg3DaWa)uM+T_q(<2-; z7oqbaMRWW9lz@!!*L5=BC14Jw>)44`A;SATf57z$#RsGL{hNr)|KRp$2oD(59dYue z9%1xCyBG}hR~hyyvG-(5k24<{T~|_u04-mj)>d9=7W;5BlN*=t#WDUmsOFGy{QMB% z8bPGOLF5Dg>(0h|fBtO4*!Ao2cD|V=e4ojOW^DIcxopZ7FZHoJ?$Cie{27DBC1-sp zTO~i~_Fjrm{APDv>CV7MOxSZY&MJ(#d}eb-RIs$2y? zn2Vfx>_Dt*CCYWjLr&6{Gmfyfi$XZXDE3Z|WKiATPdXx>VEl~3Fw%=J?!<5eDZh|N zvFYa7m^0*RWh6Tjrus<3@W^`ddOt>-=<13BX?hQZRB5=ItvuUg?^s=)rH4g*{Pv~}UL0wqZ&G@P~es8UR#;fGyDAbxD+=itxB&#V)g+}|F#A&wKfIvH;$25>p(v;`OZ=a0q$ zI8w|t_Ichgsq{!`N}#yw!Se1#y#u*kt(+4O(R3$2S)Dk!1@qJ|(eIy3ri5(!FG@F1 zB<1_!-s8GgmsS5l#B`S_wX8)rjM8uzJ)QI5v({7WkrWs9DWWjH=HDlYqo;T5U}m+? zIyS7U{Vo>SB8T7KQcIujp^UDYYkxf);>Yk=H=`kxVpRZd@1R)ElGF3`DG{Khis%jF z=xGWI*EdqJcAhLfVzKjc&sS>c`gqr_GD*UvBLdM}7ms7+pV!ZsTVp*U&>zd2vHB?!*kNX1LLXOe|ao(Gi_E921 z0Y~UQzl*(BU=25JSv!k86H@TkLvftq0aK5**7xRZ&OFO@p#qVnb7rfg*n0;z7N z9p#PG?AV%WwUE&9yiy?Hl)*i$mP#}kMR;Xr^qMh}=n}y++4yaeHMkX%p?~cIHlS)1Vj$B&$BFSg!(~i{=)f^sY+x~ zfvr(byn_%=ee9mjq3MP{T}aC4Hsc2|k1xgsYUfb0B=IpWHn17y|EfWFRlxH^5iQB3s z()_QuaSWqC`YUNwWS^Ei6}S$;f$`4Fgb|V?N-{=K@}4avIv>^hAD2-=L&ut{cbmps(C+9J-h>g7@_Rw45`hz&BwIG5Un zYIN<~)v!EkLwuhNS6uC8fs8jhYIrZqVG~Cjbtb{Dxg*&KPr!L8IHKmAi(_tygeY3c z*)+Y^L9-jLI?R7ewIZJLcU5m^*?p{Qi7ugy1-??S9_oiyDsbu&Rh%?BsNy}mJv4A; z!=y3hylhNYu(DU%ctXSr*QZ0Pql1!rNVH7l0hBosJ=8fygT-@6G69&>`i=m_? zk~*ZaMuAd-ZRt_6QhtNW?ct%kXkgJu%_Qy$-8y=K8Qgg?*dv*D2aAJ9ohs-om$K=% z*KE>W=-3Hmu30mA=u*|h>!MSgVnyW^_&7+i#V}&p%HkD;%u8c!=N3G5I0Ss!x_u*a z%yw)NXz=J=xPG= zgz4Xua7Tx4TbCTTPYo;XXZPWSx4kPidFrY{`9U|TZQyM2M19$I->PChRD$-Il$=e_ z(AhW|#Nazs6Zu0)@7X7;8nk2Rn71rV^v@gJH4Zy*Hj3dGs*9fiO@~wq5iy}{mx~K7 zPAJ>*Q*I)!R8%}Xw#}PPP(sO}RoRfFHPm%Fa4Fzv&J@wJzzXO2wJS|U?r z69;uXMP?x34bU9kNRbH0Et#^<_L4N_8p9w3i^WDf*|cK@j&aTCD%OGgPI89b-Y38Dn>X@Sg5uIG z9eR~sRTDxzqbD=#a?9i75gNasF$dp#&I3>SDhQYy9NbD1kQ^w6>^j7CiK0#B;xOkD zYk^&-P8ghl41DF(Ibq}lddLLkOa;a#WPNUg%cPO+AzTtq%8nU(-z~pOi zc@Z$|IS_bPZTcaKJ@tpJX~i>dffgv>dl%ET_LB>E0A>SLhc#NLN+cgRP)Ok$&tgC> z>+CSE2wV$_n932$FwB7m?=2AFU-v-O^ujntXwxC*XE?YrTq!(A%tWB)~NsC5T@}1ltEYyd7RB`VD5@dW~Qo02R=yGX#q_kD+g?$0C4h4?UOe zF&0P#=`#K;tO{}J968PbYjpx2pew!M9+0(346kk}){P*tbWscpQEl%vFH708_O0K! z2Q*6qr;KZr7^#f%USX>+Arbfx_-Y*K`TP9w=rM+OQ!x3#Fdv3CJ`Cz`i$GUAne&14 z>2&<(6|mJ!vx7rn&QP#23nklykX|GqPI1`FZj-k6T!THkcs$!G*gUWoaLn#4JAA`? z+U}1Aw+m8K!QB4q?bA>Uc$U7vQ4mO1xP!F|@fFw-LQMU3e}J5{O|r|3HIwo>GGhT` z2A(0sm7Dl!23~kQ#8y1qU&bgidczz9hJP`0r#yTv?jyC{lP-4VIt0mA$>#n_3KVl= ztk0&KfzVHxwI7;t%Y#+{Vt!)x$uvCb5m+i}czgopfj}7|hN}U(dM<;Ue0vNs!&eVS z8vWHLv?Pk?n&#X>V1xhOJe4%^le{y7vO;DL*7D)Rq-+`6H~(7xYHX#7@X|q%pKV?{ z7IkxIXPPlW7+?ZxH&_s1UBartu|l$gm{uczki}JVrVb=$D(mRO!blrwk0xt1SOS z!C@;Ge_R$pE(Y}ygO;R^6#8^qA#Cp!{QiwC_Xvbd{gyOy!eW{S`hh`nYqDp}VM4<+ z0!K~-p#Rv{xv%?Z@qkw1n{C0K`Pi_=eelGezo>1SM5FDVrJV-V$JXLJb+!ef(vq-i zi8n^;j8M*K8iq{&~3ZH7kWrq2RMm>IyISCuH_=X<|{CD9zP&GPN`yxjvi#M=Wk zpjUcBE*8EO3`HbC`xsH@!Q!nGz9U=7d*pBQY9yKAJ=XaQ-Fx$C=RgXMoKft-B%2G= z0n)y#gf8w!!w(%_40DIh!y4Q)2H*QTl*~p2OevT)e=YxAvOdE1vvltr^`-Z!+L#mu z7j!!sukcW~Ue9Nispi1kq13GXO{Y+MULw?Lf!q?S|H1;(47PG1kEt82=aDoTii*pp zZ|K5B6Cux*eC-|!jv^m)#ek^XgPNBDq7DZ^TRPXkwWIHqUjYR4pSS|xG!e`;)MNQa z!>Wy>*{osNI(VtE`oJnSKTZ~~9Y9ClOmfN(KgFYO5;ID3M3Qp*+1oX~Yw8v%1zzTV z1+VsAqZTJ)lZ#vas9(LUv6IoG%Ijuq?oc)FSIkr!URoLiezuc8-WyS6Jd#_LTk$Bb z1{SOGF0b}}LiJ^QYgqh4k<3sSP>ZyCkrrpO!$G5$TMhH5++gjF!tGwhL=bMfu^5M z%adwf=l=%9NsAA7642n!X-*w`{k!+R zG)tY2pR?0V1^4iE-B=g&*X_l}5H#)ZwZ_iFn4|l03%4gCF~lWr`UbD3x&2%J^^mIZ zP5>X1eOKK|KOjU4I7^?*04 zoa}3+rOK^+uAt7zP#yH>)_8(AQ1lqvBG9%wPp;2?*@2gd6DsCDQF`1LQMqWu>GCug z(sr0u49@s5EjsYS9kuzV@&Y`LEGpLamq#X$;p+|e9YsQA>X|J*fOtE|PasM1iCdvCQKUDzJR+)LI1OAY4}Y@dTvAlduLJr5B` z>%x;|O?!N;HC9R#1O7D2p9JA{u~3%JCMlw@b$t;mI|KvRx5QsgX?r!3qNeEXc%|u% z?9{*m9YMCJGX)+y+Er)3@!p2m_BqCtq>@%mUm%S0yGK7m<=N%eIwOz$?(bw*+&8 zgk)Ue)MS$dQuQ71ZSvk!&c)6%RnXg<(jDZ5XNHW!PBQ$q;n<8Kbp%>wbMe-jk`W=I(DB2eeo z?im3J4f9Gxsqth3R97v^Och#?Qh$vieiEN1XK;kEZ7KSP|b8KoUOHwh=0*8$91gyObjP{u3NHJG-9boJgIM|bUCuLS|-yuZ=bk7mnL zDdu=J$bLss?h+t3QN|S>N2}w>hV4OGKrGjXQZ7zMmT=YI>`UWvqst1 z`cwO{cxN3VFU!zre^}eC8tCYKkMBpuVTT^%_1-@@KL_DQ)A;n>Yg#07UKAiE(>1>3 z!BxRp-&}NfZB-95J3sSrU!lGb#ys?+H5y*i3X9_k0nAELzTm;N+)rgJhBn3LFz%;nRgTvl$mKkw23y`Dey zoj;B@q|l?>qIN;c+R1Kia(Q;OJ0%*vUJZe7z?X0e<`HuXo41ryUu|jtw0_qtF`k0L z;dC1lhv8H8*yD1E7FM66v@y3Rboru%>ScHN>vA%^ZK*434~WMDh?D)^ZF_0`WdJV0E0jpG)4VMiA?thwhRt1=c=Jx<@J*+~J@^O23E zxq+kJ)vCVTi52fXk%Oa;PN6Ucc4bwMW0EMuRu^-p%?YoJRN4P6`FrU7b4Q;THYAxR z8uZKKkQ~e1@R02N*xra;F^TI3?1d>g+y9Wk;InGEGAqJY`-kBS%?1&+NYS!y>bnbq zR}Gpg>PMM2Z%<5=AREx>NRK-CbLOFDZ=)(BPo;5nrc&F0UqIEdeNFzk1Sc{&lDq!X z5qng7(pALo>G+E6dxEYzRH=EOp{)3n{GoerWxpUCj^8!9fgQ`W#ybGmW?VGk!?oCI z*1fkM>)!<+_0pU_d}X@DTA`|zb*GM&X#|pK6=_ZcYAN+F=L*WgxirtNb$r_V`+m>C z69sy2dGb$D6D4|))#)fz+#6KNghMu!--hU&c_)=JsP|C`K1Ji#m`|{NV|bK1YMBRf z*MI7(r*F!|i7{3QB|PR-I1y-5cXhC%Nl&30VfAe_=+&4VfPe_77|}kB-ov)!kb-7K z=+o2kV9)HAoA&6thNJN5o1*Tsy(_aw&~|bFDzR|!i{0Bp0hn`H)U$R>t)`*(3@zAR z=R({2FnfJuMTK=|blp!~KC+|#>h@RL)a@`e;YW^M+>%eC>Taq(;g~jV0$7C+=4;z| zKr#ww?|1M&GpD!AsDso^@wfO~wnsW*O2a$I&b;@exylS;Ka*T~ol;}j!HmT>xAu-s z3MV@Ld>H>|FXM97Fp%>SP6wWy1Y0vRrEPi)%eS0K?V?h~7v2`AZo?`q^u7sad(No# z5R+w)RfhUIXE#8%1Xlv}V*$&EugbS~UTMZ&5ckrx|A&wEFgLfV`@D5uiIGFyF_sgA zhGF1U=03!y?bqt+4XUsRNAbEMZ!cR#fmgTj{}9sZsVgBEU6h;(;t^sXOX`Ev5;wWHK)ux zY%D9>v$NoHug#t@K;`{T-z-oo<{4?oPwSXD{}2D{Z!$bFE5Um@s?TKln|B19W-Ar} z*IDV-w>tpas@2@rHClUqOg#UZ&w8?Y+X1$y4e?G_jCF$Xt{@@!><&Ec#5|r~ZT`wF zhF4Q{>EFuj7M>ZJU022A`)2zT`wY!jOT&;O(8@Z2Kayje7hz(j9TwHBl{3QF$(;K> z`>+%8@8pI6t-zwxx35 zqi^w8I7U;anITY2f<_1wX+M9qLhz>-mjI9!=L`Lq=H+;*iUjjdn4<_No61(ZM_T6w z=ML`cHlhTe9Q>9}K;&Xk!b&A}s;9KvP;c}D0xVf{okV(wQN zNo8T7*N|s!2}mk=4W6;mI!JeXqXhKLzrvWzIT{4bxamfo!WP55LX(CvexQ0NqNC%U{OGp~Z=FuT$E)`mS? zv>S||m^nuY6^tH(GQiiTb+^oLoW02CZU#Dtt_?CO=p6Moo|)H++|027p&(kQaFs~V z%v{pUbM+GK{5&5ffbF5`2DUNn^&);dCMdap)}DeF3!L;8nq#83A60Y`j}6afY3Am+ zO*iI4#pvv6cMomA*wSh2aCEld=iNNshQ@pDQbk7Lp3X+WFRPn@zGQ6g(;ZOQO+3Q% zi{q*s9j5}+uSZ%<3_1(^F9TXrp=)O#AzvKhsLX(AaA!G%8zEm$QezaCeka*{69KGq z?3Dxir_c(u5&~&d;(i<^puQTlRf+nvn$8rL}=9v5cckLva1L!nS&H&(_Nf^1pTp2sB z&a{KIf*>t`NFo&4FbhYeSGTP#3m2Vm!>(RbHvy%Mb`v}rf?D1M21aci^+iM6nB4lLW&84m@#)$PCK3}=+GiJSB;0tYdC`SED_;8iiH?)l}o zT4ndguspUJknazt%i)Hj4(!rcTRHkpo{qma=zB-6L?)h&hYTj3jGm6*GZ0M{Hv`?f z_aa=%kC2Q;?gM*;2X3Rv4%VkN{>jo^`q6Y(y`;#I3>N3_0S-U^z%yOQ5T=4H8ivQzgtNGuq<6Jl z|L)BaV5Bht#VaCys;c-eq|n?uF5*&`4{H_VX0!+OYJBORCS4E~2bAa`VF%9D%-fvc%dps) zX#=*!aE3w$uUm$|2gyl4FoWFwx2#E-ffs!z>yC@|L*(5f zukv;g$RdyOLD~+`Di87<#?M2LmkW25#f`hpsPxUD@(HR|ALz=<2l1m9hD6R`i5PKm zie&&I`2b$KjN|6@IG#7`VMTZjVw5P&xd%7_sd@e-%Y?lv9hL4!bW{Ssyh(f!C|Yz= zC=N7d_KSgLui(e^3i+GPwZN~aDnlXy~n(cM_q4>E|IytA-M;KB7I*z?3njPYPXV&##L>{VG6I4L*3?^0$- zK$_V*&EUZW9U3^lfmc)uAKl$AZDpxK-0MgBBqn-{lruogffSD;FC#Syu4A;A7OOTw znwk@ik!PENC`QZugZmu7vl@?J*I)r>)FxW*VP0&xPm4DWUW|l1u@y-c@+g1~3Ax|4 z*)up`R!lLW%N@~m-AI+NtN*Mk@{|uj6e!FDfn??!_x!I6h}UwF(D<}a;ifYCF%Jbn z6vwT0PNj*2S$?EvU}F^K;eG8sO=1hL>+b&ID5i~{@<}S86@Cy& z-WI1#Y9(FdbolYE)Oe!EyXlCyv~D;-@okZ{{0|^Mf&7O={UOfQ)sw}6pC4PZ%i|Q+ zL7GgJ+*wfCsQXnX(IXYeB?aj1@p-99)kadZGgS~dd6B42M^+-%i9{(@x(}at$dVK0 z^8J0w2KHf%j3r(nlGvg4N21;YXZ;rTLVIV_;6uhrngPcRp75oV@AokPryzgJ?E<>3 zt@R#=(@4*5o!ZekE^N5#``yyQgnh2&Dp4A)Az~4-#>lyZq}@a=+;~m z0!0OALp?5&?no#I=ks`1U-99;JPUYF1yLJ!vfQ{zK2;69{tD-}Hmh|oOS~dp#$Et( znUnhq2QTFJWEDW!!+j`FGOoXcK##u3KQh{A3CTc`k5Pm;z&X~-3XDoNddyWgVxrDK zY1mBwT7OH4OR68>C$PVm_xJH=c`!LR7eLi4f81SB9(L(pOcDju@aD}OUv^3Y>GvAk z7iLO;(jC<>!5WL{Kcx@-?-^7Z3GCjYur#ye?t|d>a)}j_BFkMhXbV=&TSWcr#+K{$ z`Z3VuEHf>*o9}h72v1fTM(qg=8{&V6rWL-|I;ZKBrot%OvPY*>`=Bup@xG(x7k(}= zz);emzMASB`~&FzV4O`6xOb3BHIaOyPF*-HFouEPEKBSf zt~1={XOUG=YdEX&^k5Hg(C4pGrAA(Vhl1v3rf-@`V>i1DRJA{@33@kKwy6$5_|ba0 zoJ3+9j;TrcAYwr$Se(6;U;CqkzQ+n21p68dI&fa)Dj2<)*PYTR$(B>1MngTgJTBLG z)k(RiJ99Y~rLDhzG(3UdrElrk`hCqC_5&lsLgc zOcnG&UUqhuflM*9TXqGQOVQMiiD%haB?>#|ELO7L|a-XzG0qWT@lEM1D8<= zGz$`Zazo5_)#rq&bAXl_#szqclE;8XM$t2R1Ixp5-!F-2OUj9(>styPZbn{KZk4*{ zPG@F5^u9&|6Px_V_{uCQ>>dyP^lQQeL#QQMH#b|i_&D$;uWZl7^iPPa>aT1^g_f*T zBTFRUy;mdo4wAn2)0pm9yI*g-Px%2(JC+u-Gkj7JuX5H6*7ZUK;iEoNGAHfW?bW<- zYaM27sF4__0+x`s>2?WLi$vrA455>ffpj#_Mf_Cm-6HZypWz;eag-l@iI-bXJ_w(mv-_)CO7P8+qkE0NS6ur)IP2|4U50n@} zVd|w!qp2%X`>{Ktmx_zQeTDf%n!dLym=?}V5G|hmW;%bZ<37bsgiSNNoy<=7gEg@e zEsLkIi4x0ul;hlK3NrSI`BKW$RL04l>AM=85Bl04&zCsA@XMZYSdG6vYN|Dul594r zHQL>C;Na$fEBrVOA@wo;LVTGi;Ek{l@7}AvKoMldlXq8UMV7*TXi5z@oqJSiRj#aD%XYJ31xb@P0b6$JgY-j^-)lOWEu`O54o zqqhd1R0pWr@~jL<;giGEy$=M@^b7K18R-pskJuS6=hJD}UWp(}{9j4P17E3r_fTX( zHn7ql8U-1sJ5|{j{fT?)us1*^t(o7acw1`te5cj)<^1a2lq=ptuQXn07QA;EC~88c z8~YK}=ddv7g=bA3TK+)uelZ1?HLU>U4$;SJlmVvi_+$M~bSw@&q2eW)S8WB2?6R&r z8MbD}#WeIu5rfQT%Hht(O3g*P#alW}T|-rR21A#y1=_33rsVn8fU9^2VmSgjZai;e za#du>btW=HAV$xf3#wp~#c;o8bT>j+jw#${mp*NJSg2OVCSQ59?m|0B9LY_lb^oxH z(S_oMeqT+BC@jg{vGeg;Mq`c?@s@E1?JQ~fstHxRx14j{i zGd)5vs#6a)q6}|qGJ?-BtNH1agVJizSE=DK(^fS;!jg)+;1%ZivGr({o#2_?bm-fy zU(MoRR~KW%8=3H%c7})J~7WLtfB`Oh@1-nP)rcmKsxn(sYuedo| z@zD-Ni5plC1Me4Eqm9;@e?G+M(oHmRQdQJ#~)otSx`3*m~i7mqFFupa|OrARR93r&%^o#;-PM6L)x zHae=8dIUS0lp^=k&F0hdJsQYUw;iiD@#@gk2nd=X>pt%`&OdE=42_99*8!?4~_y9%Ay5$=uRYTuZ?Ac^S_)~{U zjw+11VUd%g=GpJ?=>`+_&1Z``fCpKvonmZEQQmsoYLU6z$rt7&+tmzFmsj3g%zm@Z z;_O32;o+Lfh3wnok8ZnH<$a|Qt|%_Pi|VE$Z;APV^n@;Dr8Rj$B>uMIPD%PM=eXN` zSZfLHA~7uYI)hPg`Gdj|6DO~3{?m>ge}1E#Z-FzbC&-Ggij2&P9J(y^JN9F^klFyo z)TNnHnjHV`NfD@GrqrNm`gC{{{ep^HmP-&1IWBpNB=IZikKGr?!|h1M8@{<3swpLv zvxIu4TZsbo=<>An6H#V!OhX@5<;G1;tPi$&X(^@F(7oL&KQX^7oy}BBOG$~I?2ck* zt_-lFXvv1qVU9|s$z$HyAgL3mW6-xnzduVt^cIqSXClTa0z-uVZJnN*v|W zQEsVGq@xPpyOO~6@LyW@Gv~cb4usTbU6Pge+<{e#zfNi(L_t5p=Qos%Xc%Y*aa4PYYS0&k)Xt) z)b``83$AdUsv}dsRO1;8TFe*Bvmx(X(vLaqxI_p))xz%>$;V*X1(kXav-mfCd49W1 zyI#GFLp%~95V{f^e#8jFyD-(aAQWmAihYK0Vo?}wjyOR)!i@nFfgzjVe$kR#g{by6 z|M#%2Qkdzx2uQ~Xo>Fl^|{u9}R`OMm8E zI4fVxs-w!_=km5`8eU4>!^W6VKH`|R3tlDz*57GGYI#_a*k^AeZ0`?l*tT7L&uOt> z^%a21s@lrrY!b@Ir zP%rXrQRm!*U-Ox0rW&7+hBpW{oX>R>-J(q8>gD~Y6JYTUD9!hygXFa2(CJk<$?=9p z+T}17V6@EQXbUn}xoR`ryIDT&FN71Ks2+E|j@Ype$O$$c{+WIX%lJnzSKPo>G!hOVK@2@X!Gnb!TXJnvPz_|#8Z*G4yg zu!&!STDj1jq1y|jc6Gok(a`!Oom6E!`17kK=nn)%?H>)|IwWA;_*;gh?!AbrCNS1T zjI1&=0)72CAq>?GA&J3p+KQyHib|-uQe>kv{ZM`0Xo^%THYua}O?V1nET_44>92qO z+nADVXi_gLHlV&LOnFakOaBOExzf-Sjc=Ym`cL%|Oy$ zaZaA30t+j-l$!0&G1P|0&t`#6ZS@5?qUCNQa;L&YyKVAHGArZgOMxq6S1^a%7^Buf zQ0ifuKG7IpLvv7dyH(E9#&9X)JEVxLOe+yk-!^Z(lN4r>8zP8B7KOu2dVot4TECm7 z_-NPkc!*{~D6W5tF`}S(>_EpfDyjY<#U#}MjHx~*=L87VKU{eXIN-%gT0aa{!WrrAr<{n15Evg2q!LL2Il5;C6#(>U~Roh+o0%g`P(OUb-H{UwUFo5$n>B@V~oY~UyxA5WIxm&yWju*O+T$BZP65D!3x7TRJ zsp!xfyLaBqfOS`^0{AHuRQ(n2g#a?)fYX-VT+QrwbkvxI5!Af;09RW-W_$q4)BCRi z&s)t>2q@D6^Dn~I)av8Iorm}$nD~KuwfJq2R(1fp~X|m9S(PTXblZk z|7`XD?0SAc97Z}7E8v!A0K@G28J$1tA%!5j`;M{U9;omA{lNivPCK|QPu8LNe(4z8 zf6Fu#=fMLPT13N!8+(ie6D29jPYAZhOJ+yL`ZH;;`b3p`A-3e?>3xH@(=qb$ZF}40 zu{B6*jRd6edjN9}G}^N75tR?T$7Zw1CS~AsJ1i3G>BMr;Qt8?l+#3!qUTx z&hxG%xUPT+Xx*Koj9qOtIx8{+xII&AM+}il7Fo*k8#U7o!ykLW1?XeH!mQIx#Ve#K z;G`7)YMw1>Pq0`}lF1M>S6I_OVklqP3fHCq2B~RyIEKYqCLAaYf?u*4!_v0cvq3WiFy38BD{pHUR_WT9G;fRoaF9Zlhz;Gz`N^9V( zWBBe%BBuqJ=23%tTuA#msowEr;~f?^Mv-YZmi7&jMqJD(f(+jTjdmOyRkZFGjwN|+ zdT2)PhV#9|4U#0+sw9x!`}h;;i@C2TS>mKn zAViH0=*otox&}^n{1$z0dW}@r>d9sSFfR&baA>7^G}_z>>duUwBK0agKFOwpeu45m zya+^P93T_oZ}2WW%f(mBL{ib?e%qXALmRtxQ}kA~fDTP2CXG!;hzp+Isg<0X(n+Yz z2sCKPM~7G0(F1hy(upX3!fm?TAs1YMO(`cU_HAU9e!pFfrqs|>D1l`B!!wjE(Zcm8+Rm+Zzw+B~ub$ExLYV)31 zL|~R3ChXtE#6Hge1>F==40@>EKl804EJLc;e{ckEdHCSUkLdr5=y^LTBrro;ECD3> zmN~&3%sXJW5RRuxu}9&UY5UX(Rh01ivblM%6k$}agG#zpYD7AI2#pE%gRT5Ep>Z3! z9^TS5i`-XVJ5-W5Mlt-Wezp|_34KFthD2AS#)+h~jfId!Hg{^5#gaa+VbUy3S1e-n zU_(ytP{P7bH#UPZC&y(FW7l}37Zc|%7&*G*jt*CHo0h)&;Fw>k(rT)XBd$=XZ}0c6LQu8V1vZ_5YX`GIcr=Bs%tv`D)W@#v z_ime@Gs;W1PO)Los4&E0tavw+bRdG!p!+m@sOGW3QRTiYUj-z)YOrQViqd7>xqjip zyewbp*UGo<6_x;}s_H^(yy9OUad8_}H>4OC)wugeRnRU^W{YRTG1kn$utfEv8rD8~ z9a2>HtEf{CsBl_Dbv9-k8=yAx54;ir9o>VOZDRy8f|L9U8!4wW3Hc^H38M-+6_+lZ zXcqAv;w;LllEqj94Yj%DwC+Acbb6b8x+>>lL(bKVjB6boTXoy_*Zd8%NxG9)AX6Gpip z6$n)_AL=jBNW6o+3rSNJccF(g@}%9JZJ4hza|$eK{X8)O9?_sj7AVotsC^P9aVyAr z_Lavp3Y0NTAP6d2%quB=#@IFsuy|!TX2yGdHoIA50rF{@<--NMUA8e!l12#gu*r`A;8lL&e#0=#Qe-(Uc!I?}+8RJ6`WT=19p{o&Z zkfEn=GJmZI3fETUUKLvH3QU>1OrD#_xOmhkgRYF+CVAYh0bzy1u=tW}{Cf2!qA_KW z{x27qT1$IF7oC!BhQfFyOX;i18#TVWYQ>>ydxq-KGyzcxggcz$WKDV%Ap>9v6Rzfx zoIT_t^fDot{|he#@3Q`&Mbxq9@wB{QT85ee%^A*IR`a@*8;;_-%Y$WvacqS;+1a%v zEv{ZcAr$D+A>dDD4kvh1*2B4J`#;J%s?d;W!}<2)>kp^>d3yFV7Kw(l>o@w0X7Ur0U}XXvkLLU*|FgphQ^k_jXG)K0NT_CKJCxzIDa(sCH5 z4{DTBjIF`&!2yV+l9=KS#&`k4!jeYSVYZTZJz4UDcS7RyYGe^>Aw9WeqWx^7h z`F-x4ii~q9!d|BgE2tcRAj2%w3Kq>G=rN?B%BW*_$%Fp7&~RRH$U>#9798v}OJs&_ z!i3!oB3xvb-58ZpI>o`NHbTuscViQ^^za!uJ^dd~ls+R_>LCnCDX3)1O4Q^}mopF) zD9|ydnQeb3cJmtBX}n<*VauiFY$z5j&;V;&;eWNs2!J&qm#w%s4yA&b?;9n%lUr4Y#&@3B3XUc8L&TwXj5~dbOgjn2 zrrnfcm${hTR|q&R1eVHUrp7_$cPK5FRDG@Ec~{e(Wc+j{$sb@x?h zcF{?;@a=E)6bs)r+9XAvbiFdCi2q%_B(bD9Tygg%Y0^Qib?(7c>HL0IqGDyM)}mr| zMf}3_O|Cgb*ESX4mmlFD!NYZTxu2t`T(CiV99Ao>&qcmKZZEnWGy`&GYm6e89t8xY zfHFBZVeex%?KUymC;n0M#=#Vv)}wd$FUHO(I1}c1+p*1!^~AQbv2EKnH`&;>ZQHhO z+qU!H_uxDJeN|KUN!J|BR87}(_kHCrnQ$M<65!PLhE}a<`aHTpc3GPHm1{{sre^x)b{Xcg9?M{ke4<1QC9-=H&}y(TsNWVy7WQSW zBmIa(NdlEAeai$)28Z&QPyD@T`u62RdW6&{WSO8Y-|G z)wn`kZ|=-twl_H(5rSJKz8?oL_p&MfdV-{TF`!?pywhT)2aPO$Ko0l_^KrK03$@AL zap0*p>QDPC$otim(W|5}561Z}2eZmQyjLMvckpc#g;;HmhrKr;@wq*5W$y>{TRMJHT!$9wLp?C7U?_7 zPYPk8>e0DQV(I@EIg1OWR>)k?-m3}*-zBU;9>N}^ zVl{%uzmKd={82BdW(>y)L*CoLjeAh-)VNs#S%m5`rw_O{{#aN_<6BgNeM#>=@F24k zo`0A{f}eu z7GCAf!$|Rg!EE8R`d~tPg~h(mF(Trk$urqfyMcp5QSH`>o=U;>NEt4)Wo<>^X8~}v z6p?X}F2M$SU@=AO4il80V=hY|7ZVL$|AOpj2%3KaeGPNjg}El&dk8ub5SG%-Ij)}O zIvDv&sCxr={zR=yi*uM)tagU1j$ar$eV*;nJugH86gZ&Zae}#FUpenP5-8*HQDv{1 zSHQCDpJ5GB(`V^EMUQ2i00f*EmqZnWz@;dN@~{oH0@1k{(#nu`P=fDGp_u&7yJo%V zL2|cUzIQPs9b}^fc(4sgYH^@>xvbgnOtW-`c<~&OBD}8x@-E)vLErt!LJ^UfC>mdY zzRwPgoD=>bB3^@z%9;H<@G7|2iC^Gi;O))WYZR>fK?uCBQ#M3G#gGF?B&__=moZeC zCC0`C(0ADkDlWz$7~5yStXmfik)5OCB+^;9gzbUX!Avs_J;GkLy}iXELz)X^gF*yi zcJ?EAX94nAnT)Oo^nDD3)S_sHh@O0>#L2t52)iO74VGUWmXl$?TQi_0>?W2VlvL+( zqEK{u>R|ZOw2Wc7xCtFXWzI^#r)JqVD*DlCuSjmHGYqqL;qE*-PHteGU^ryXf@ORw zG2V*UjoMaFn#fMJy*mh-g)bLMD(;;=u-Vmp8@RTwCjZz~@d)h8)U-OM1t%hv$cQ0p z4)&E;bslhi2z!l=wd#&C`T?UI`+ih7nvD$@?)gznsfH?u7_#_k74QQXV9A;&Uu=dI zwS9g=70GOo?9+0qlXn8fkZVKFeTNEPkvj$dZ0fOXtXTva;hjd`ON^`rc52{bDx+|{ zJbysi9BiwI=pSF#PvLkU>}_6G*GG}_B<*yuwqJqq`8s^g_t$UJp6b$?;tobB{4a?I zZaqa0FpimddK}Il7mg<4eG2=y3m;;4Lwvuy<^N2q`x#*8Nw z)eGG2pTJMy6{-p{e%Z+7=#Pt0em3zFx*6 zoRKxD*PS@)Lgy!G%9}{W#UQpA1!U{~`sNkMT&9W!7YnB=ixLDbflGFs4Lj<_89+Mu7A>gI7bvO0HaZn6jZj$htgo&C?p3#3M6O%eaJUcsyEx7t_gq)Le7HkMaR13mT3 zccgaI`^7(@uzYJ~^R~L)t^dqw+Q>5@01ws(wff~kiWmpHIueRl7EY+TJ~=#mN_H7!aaB{M#rz<{&|sOH zh}~0`5tK}VrnXr)SN?eCwR@B0jl}+($yTN5BR}lH^#-%8c*s{`HF3Dr@!*bj&4WZQ zE|yEkspt6z#sS-qZDgfr#V)S3Ei4*mqJ#Pq5xV~2l|v}@;lyj}@{TA{-sJa=(c>wo z=o1YTW}bO3MQ5WpeV$NUXLP~u-^MW^=+#cJwlR!-JqYmJ->(1^D(GWUQQ+EHfAAifSodH%Qs?Rvg2{I;S#dxmQ<`}4Wb z`OyO)V!RJ;0kR@^=6DIbVQ~@8Zo9#Oh{LzYKeMOZBOWq;&kGYd=0}g|Mq6VgvPIuG zqMXLVYD-xW!^)K__C%SY?Rn4s0guavK5)o;&~x`6q!KPd=<~TX+RAe1c(wJqTYcVN z7luIn+bzAV4ZMAvoqW#MK8K=aZmM$p$<5eK2>5z9=yf5ZoQ*!;hwlumflKQb1D_g3 zEY{3=rCM=&7B?Td+<(?S6MflMZnD-he?wMzvhj6z=)*l;n!%oANBt0LiBGD_VaDY5 zcv}M}ew?J-*hTAT^tf7lErNg2-A7MgWVcsIkS_JY`CD>5EV8vNU%yT&@s)#@CCIwx zk((V+Z_s){=@KR~MG2FN9ENpa; zpTZzbN+H`T%;_U|dCbtR7gb|ZVfm<0R&q2|XQJNa;ah6cs(CNG2_3P<+BDs8Z4<4i z8X=38|C>CEHz&~@+6Ul(K!AX*&*s#^H)I)|LT?pjxpM~EXO7KMp(!4C7NLN0DKkwL zOYzibq^GJ3Q-n(aKt}c=m21-emf#=MYMj;R6D6WVEe^+RRm+}??3J>L^`$RCmVHE>LCUiJZ|O+E!sX(9Dg% z<&`$H19vlGw@xKa=kTLV(Ga=Z^v9JkS0#FvHw0;_`yl~)1hvxsyv7U+W%H) z9VQpUn)imtdnRv`yjZ%}?nP?&laoAJ^>xY-nwtR#y^dAOij(?=lsLCbHv7#s-Y|(= zmn{9W;Vpo(`91DsRX4gcV-2kl@6zobcu7n<)}pYBuC9mn2Ch5cq#>XTtuBI^!_cwx zk$2r0#XRjOQ;KoEK&PYuLbEVe1wiHh_r(aW{zYx=NJsithHktI`s^=7Q7KX`TX59t zH6g)%-aXy&3CQaB2GP6QHj>UwST%K_aqZgg6-n$G_`f|4j>l{LX7drn+O|FMQ#+?8 zmJ4lNMks!67uZ9IM_Ic3w@78~w&$<#oW*5-| znkhcOXG<&Kqi&EQ&2z=y7cvrGt`s>h-5w}gYZP~x z=+1Y%2D^UjIBsHUfaWeA(W1-H79=u%H}Qof&=tcg&&aKmiVAGs?R$EM)l=_q)H`$2?bP+)#h` zxfm)|p3wiTkhI}*=Dl$tq_3nBF^W4SV4tSnx~ewrnnIq`yu|z2>+7jZdpi1nzb$MX z3NfQ~b16Z?c9Ni=wC4@a3ENMBIUg>Qqt_;Wl$7Pr(&})2`EozP4w0pV)ibA{jGx31 zz&d}O5gJuJZ^-*&eC;d$eN#@trv{eO=PE4LwT&bSR~c=8T+|6kW`B=yRR zJe$9cQD`0=OgVZ$meum3Agp>Bc_}XYLDPa+z4M;R5yL3tt$YoEwI$N$c4y1Ju(iKBgL?tn2_?k1 zy}dBSKV?Q&LVf%92y7j=wpuOaLMcdH6WxZKsZX~{wa9k z-4HNT54s_X_P`ygfnbDm@edq)TV6ib9L^UeojCB9%MDJ}i15Los4)&)e^cPPCwKtk zOAulZo$|s#wpRxtk?DVQ6e>+v@sQE;-nf5uj%K5W*^DoTqvGbgf2#K(Qv$F?(jQH1L6UOzEw)sHsUia>S)lSOJ ztWVFaqio0N!@omk#O}a7VCHW`LeIFym(Ik`9oWzpDda%6Wi!&v7V}pr1?KzZ$<1eW zOW3dJJ^Jp~_b9#2uWS14!>OU;E56?!<16m{9w#qyf)bVxiI_ryuG{m zyt^C&(PifS>|;BkWTOI@4hV_@yRB&?Ujw%YC`U|KQgFyNgJ=8n!&Fh8hTnr(!yjYf z54o09;d#VB*?y6H6yMw)K0RGu@lxE4+;k5)(0{~@_Z*d7!+)@jmt2z6kYztX1~Z9x z4|MjKy;SkuI8Lu941VvfVD)&N+z+b|(ZxUSL+a(PdyTIp}M9~Mw_Ol{xS_+GcUe|x`V5On_>O)Cjpj|8t-Ga~j}Nxm=3{XBXf%sG>KzqoU_lT%JA zeW*Xq`XfM$nLm}zk3sE;rO0Gc+N9!& zRAge>i|XsO7^Pk@HK5r@LuuDFgWYI*C2vpGvG|q<5FHYkfv^K#+2ksgb%JV{303&V z`dfEvz_rjK>^vQKqp=i;n&e#&{KmzSK^Pb!vz71)&_4dvJM}MHL=OdHO=)zfnqIr} z>7~cGeCxFI6lF<$_F_|t8-DLtG$;%w)H;C_Sj3PZ6Y|vNik#q~kC4ako3)2z$~SD9 zHPCH7g;PG=)Y`U@vHs?Jny&X+-fQFGN)gI@)jS*3A6G8R-Dpm?RJ7%L z&2QZ}WJWFNf7gfTV-pKCqo=znTi4d0)?T-{nZy`jiG0>Xh<}RwUHmP z3Oyp_kBgAG8uWVh@b6bS7&u7}f5P|K;?}6*Y*vR24epHnZr%5CdEcT1AsbB2 z=zz1|f+UmeKY7LpT!y3u=u@pq~K; z)I5gJ%XSCU90pk{6AZL*_!m$AAc6-un~g7xZQp_<`&lcvM8*fyef`kEeI1oIXSmpW za6y#E=0CYYjV{UC5#z84ToC==;?uF$IFf5F)EZt(8BoECktfI&;2$OD6?M88DhoeX z7K7--<^C=)kU@a%cpm-=C1)RJg9TiIY>)k)yodTOj6{*}hULjDk3kVf5zhaAh#g}n zT8H^n6||Vm=7UCbYKn@He(^6@yUAF*&BW2BNt#&W(}TCW5Tp7ZrpP@1 z6j_GAF$i3C47v($ zEZaWlBuyeVJlc+L{X6V79(StSK8|I6Y%+8SF1^ei8K z%H``uk2A1!e0@&r;I=!*SWj#3uAEx@X_Kj%nKr;J-vI=~kp$qSzh4?b$CA+|Q#^1A zopF2P-UX;1E%QKW_9qQuH=&#HP_oLJ;B3(4XIkl;GTXGR3+k-}n^OglNgoNwOmHuA zE4X|8{xT|c&j%sA`hvr&{`QP7qgEhK@4a0zA;U1d@Zm<&R<_)qS8P)F!{5gx>Os0R znZU2)3MiU%15`!30xte^kO<^F##>USF-9>k!{+&d15B;7BUnGnF28|1Vs9Vgs^rckNMcp_{N{sx}O~asg#MidehRe>toS_+;YNop5xE~6) z4kDBf<&4ueZSId*HFgI$#+^#`gGjMe0j)WH1iM}rq#Y19m0CKcn0RI4QuTmJF7Hs-F(ZUEO)E64MmR{75+y343s5~ldRFwm% zR3^eeTceyDrlBQVF6*jZ;E={JTPee>*MwGf*Wi`ENBI)z#b$C+dhDaE7WBrmXG@G? znBmyWGje{R-JKkv4w*CXN7J_0znC=!Ax|OA8sf~LA^z|!oFZ5-OneWdmD*m7p<(VS z&T8F2zD)3Xn|eQTKVl!`n#CtQ7FRsmM1+)~0Y5e?i=C?N5^ND<5%xlh#h+M>0g3uo ziipx)YCUtKk)?1(s5)zkFvST^7@L|FZbtlwryOUE)T*Cv9=@QI0P?WHMjmoY5<$XG4|RYzd7cJ*>W~etQWvNzs`Z$DE`sr@k#s>7n`uC2Xr}9IBKR<*Plc<( z1f*$UT>*dH!F(z-vj7;QDPLnY6{;d==4-vJOKH$_f6;QPI!O8<%3LTK1pAQxhagP^ zMo(HRn!_axWfZS^VN;~k`h7kEwlj7>LA@uwx=&-E{o@lGx1hx@h-GqL&BFC`=k2Q%ZENxNKY&-bZKE4IU z;pTCXmdQY3_3}APV5K@|N>jgQRxjS>Dc2uQp9hNzd~-+IczIg|nbk&>3^C(%CS$z= zxud>u8Sn}!A<7D}K6owGTf%rUgZDH4X&Ih zPUb?16+!qE_T=Yl&8q;P3Wxw@mC{n(uy&BJbGqOMzw#zkb)vyjTRu;T;31nPKrs`| zoiWL|l-0I{4YCzDGz8_TqwE9OTjFrt<%H+tr!$e_>p#aU5PLL0a`|TB7TP%eO`PGC zaZB4}F)7Hz?0!2(c*TWalQFKloPRW<=J|vbxD5YHxL+9({S>U2;qFB$583ctdKsD=%Gw;=VoM?PLMWrBn)ggRNVl*yfjq_F}hqQ6)z0!RFY8wtJX;#hi zQFNZMe#TT7llk$@!7tR=M<8F&DsGZP4da82LDntm;JlD z*rH~frUMJ%p>-=Y`u)&w`dj~yE+kY?X!El}m*kQ97f=O)#)s--So(EkO_!IUHp#{6 z$_}mWSk>4gU4vFqJw!@2MfYFX-HtrFaqLzVeo&&eqtvtzAaD`yj)WSRcfLENnu-(= zfl1?Y$tdTP+{u<$o^hh1F7f#7dY&SZoy&Mu&3{Lu-E^DdD%;xae?=YF&E0#h-+Rkr zUZY$i9tG9y=cGR`BIU7idf7hd^nW!sb^}OCITl6H&p?L{2OJ`aNFn>u#fzLInXA}* zT+;RW7bPFH@{*}Ju8p1L1u*5=dWbO4XfMm}+!m%K`g@N;!J%NZ3el_8l5i%k`~#cB zcbkgT@#>PwD>A=y#-UG?81hsQ5UEAhN(a&nEhuTZ{1=x!GR%x$3~FT5?pRDP!53FH zK<`8RY5eEpCYqs{?(g$%ZY}o|xP*ZG+9p^~$hu~OY@dT1xYVBY^{95VG)?^ zIl8R@9gN^d=2UFML+$Y4HVw&3OcVz}e6=mULT;BN%o24avxJOJ()2Xzy%hCqiPOIf z?hASy38vf^7a$T#5Xvcjk7mn&qBUFRA-V#i%@$(fn@rRPqb7%tAM#^i)zl3XG;83c z%sP9>{E=gGlZ&2)xKG$90re5B2DW{{U$c@`$ID16H&FODtK!Pi;U$BFzo5AsYL~Ok z4ShEFmR8C-l%dYW4XqbvT4V$mAt!G+X}o6Gj3{yLlO7uG$I6p;IU8+XT;0KuurHRC8{w`W!o)5InPOT52t5SA}_Mg`)*6JJd`p~D-Hwi z8J!U{23@nryS6VJho-bg!k@a{!j+u9>9RMYX!}cGv=B~_jkG;IJ|%dTM9)3!{<6Au zSsh4ZHa2Fn8MaozJ20GgFrEC5E_A7L^d9iKVvFj$Q#TBRm8_F`P@l})DpN+EsdJ1w zVKxT~{(I>mo~*({uTjsg!v-X$)eoML;9)} zU8yOF&MN``*Ll$cWv~>P$lhJ6kE`Y;WgWtOpuWffv?*1{(4oSS#LSSQ)bEWp;bz%3 zNa9CBm79dW?~j|9O0&K7CuVzNa}~Vo1HF49oKmuS|1jRD;YA~Csvoj5(F1ClDRCfv z=6y-DuZ_7PDRLpI%s0tWzqo0LM&C{WuQ|6&zN8BaXRrn}wUhI_&FjovUXEVpaq^S> zmLrMD%}U{Bat5^Wngi;X7BY5jH(`0O82Miu4bJz81D(Ur`;`DyUd0D-U!dPaPo9kS-zD{gg&-k zr3NFE?E2$;ye0LE_!P-KZI0U2NyJo?ztCm})ha@yC z*OB4cm^97_DW3!QY9b28kxMF1a0LBO)5;C?k4t_;T;i+t@ELAoTJ0DL5&$m24dnx1 zY!q2aRL2U8U`?p4K`9d~_Yi3s)DNi-mzF3K$BgpHDl;ZbRrB`HQl9x|2u8Ch*acHT z(t7FqRmDSjOX})EE4`-6`*RiD_4=`rCbWu{=E)*mt2D34aVEG~h9-&ls=VfFOSN$f z*CDzPVmM?e$j^kYgHX^a&QX*vM6aD?yrH{TBMGJLimr z*@aAxyYX^KmH<xR@)PJ?7CF`XM4)C!p4tlHpP#TA^YGHA^NdV!weSV*|Aer}Q|y zZd%Pup=)`!7ETsHB(S)vv9P?v2BW{ObhVWdgf;+-BPucwO z&Bb}04L^6cNDmoYb@h6|b6%w*13@ZenWS!@$vTsBhtU&! zJMi4kR)kZnQ(l=r5-&A;@My&!U|?6Q*OE2q&y$2t>FeD6@f~b5_&1|mCnp&w1kPRW z{TH_$uCrgFe6#(KGx2e-I8he)%yB4*xoos;UO+I5WxswyPJzoap)M0@M{;KcsKBvcbe?JS z5(Qb%PRo>OW?g;3IZ70L`3QOIR&qy>RCXT&MN#l3a|41j9wcR(4)9hpzxgOA`U$f3 z?F?*brTn8dqcoKS2rrNp1;FD2#T;z`0eqLdykf9|R}_|Tf`#Qsyx9?#om&yfRIaRc z8Fb*k$~K-9c&RM-xU~yNS%bJ7hK>6=QzBr1=@#<^@mvp6=jR#}xll!xMc(0VV|qqrRAd0d^Bwm{OSW@BGPAk(46>TFi$c1xn|!+g1{cX7#S zo{kMi9^_YhF-eTL5=ma~gj-kbyXdg|y;Gxfh@pEQNVS4jSJCtEAzAAh?}B+Xma0x? z@Dw&-3H*(TFK_s}1?+lPVgjfx`TvrByT;z*ydf`3#1)P+&?H*m!A4%F<#u|qM%&Y> zzrf-*3<6IB%|(9RX)=a7My-HHu<9$U_9}%1hZI!$=`4q4<$QgrWm>fVRTx60dWPH% zmi_A3QiMJ~8~!)5rwlA;c)FnNHua6$bbv>}tj`0_yp-@rvzliQ!LuPBh5>AKbv*oW z6B{PKlEU?In>hUOPQ!sCZ+1>fHB&3J;YR8_~<2&id^HlGP+olwO~RJaAcLG76V{lpnd zfj4VXot(Kkeg>dck)LC@%35E5LX)}X_u?!%8Lp~c{p9SbriY1v!#nQ}9P^ipU-&Wi zvJ9dY|1|FjxKdWX&NqRwjRkdC-#?X@68u7Lx0n03hRdnkoW*HNur-Eso&vF*&iV@Rj2Un-bL1YSn#Vl4Zb|X&~|X zi>Y=DvV)riN-hL%-6Pb{uhqJPlc$09mPHr5T@QQw{5Zq41Pd-ozuOo>W?`mNL%EMF zAZ%5aM4bf{6K|n(kvRY=d%Bj3mBQ2|`V6;xp|W~`HQ-n)WpZ80g+!h0A$h9Pgt-oz zjmEsWe8O5qZ2(Gja#eB(4nlNR3T!I89G%&`d2J>`;Ni*2l-V+Dl>_-@1PfTs{Be8Y z(}Cy`IW|yqDBDBMp>Yg}Gnh@}n`{m8#a{Kxvm^zip}Z*3Yl}wMk%J^)Xk&0`2)8Wm z@txPQ<(D{S{H07p z%5W`CmAM3^vV0Xt$EZwD6q5iIi4yKA@s*0E{8jGK7`s%|l1JjcH2_T#_&$__>NpXb zBYb)PdSecG4`<)x`|~&4RMm?>sAWq$EBWqHu-<4Tz@%(ombkMkh*65f zqJpz244%~r6EVq$t9<7r048?i06KXjhm#{F#2HFAz2DChi&0vKoR81{`H)%Q<*+^+ z`1Nqq0oxH-ME_scej?a2G)UivF~8p@7$xwNR4mr691`iJ-1u94rU2JL`k!j^jl{_| z5nm9MSypylFr>s85ZqL_3w;4fH4bC>U}z3=aXi6G2Y)bR7?2Q@@LV9YagCX$!4QL8 zLF8G&;P^q`U`Lchdm#aXTp{HBWj~%mV5Fj1Oa@_Zj9n=#St9X#sMKCz0hxZ(pxbyU z9%vOb0|@m*BG6`vQVPJ3u?UhVh<3k-#{!<&CXOF8qgh-4r(9LxGO<~OB_O9c^oVc~ zqmH%d$`)EY>5dZ4aso={nJKg!V>VCpfAG&*`F@#KY$H@2xk?C!M2KpCbW`g zNv#whudNi=i`7Udc8TzvNjHGVXElc^Vuc1PWt9L?wNk`tUCwm~t&&jU*GjnNHhuVY z%Jz@hn?Z1S!Q#Jn4hAu-f`%GjG3TOhn?AYMb_Qkorzj4&yrLglpIu_{WJh&ZhgOr= zj#+$ghV~S0ED2qTtRKtSrfmecTlCZgovF8*l4*^ts5FR%IN-<97!@oNJugew7|6dN zU;i#|lna|9q10FlL!N^>d?2WSWNwg_n~X7dUVYCd-*b_U8JKK3mr2|~G|=orLz%sv zc@&IkI+y)Z5JCkgS|t&JTNVj**9cu|)sT76cNCgf42Y~0C9!f2XB`%mUjy7F)iHb= zxix;0Xd>RX*94vLwH^k=Qx*(8ajlRrS3_R=Dpa;B*_UI20g`K?)|Z=FP^D-&cP4%i zXqI?Xf0hXi&4m3|M=XtgVw|R1=&8VN)RkM-voE zsU{ebCT%v(d1JKx^8VT>BXrwwAlj|wJou+35*U!UA|2XA;?fTk0FYmnf3Oo|Kt#GJ+v;(D) z+H#pF+Te(CwZV{7>9Q;8e*rV98Gy5_Sm+EBgA1JOD+tbj6GaYfMl(3ytv<9@@`A=s z7a*n5;lqa0LKo6y!1nizn zPB8zV5Cs`1)9&#4c#T7)nfN*ER{m1NM-V^~42QENKm{yYr&)O5_g*vd#f~@<5v?U?|KRV>{ zGQFTc6y31$rZQNmAdtfe>NF*PWQv24kaTtTpk7lv5^@#I4s5ap3B-T!Ul;d7F+z0; zlw+Uic$dPypnIzSgtk+|2AE3Y&Q}G=@}FRcrgAFGN}QhdL#3dY#4f-F>}Jpp;OYMY z97B+ZP~iZkVkNkSX9svqr9QL^*71Cw8VFvpVqyNOv?Xqv@!~0&`s< z#<9u|Nm|GOy;%_ei@XXY6dmfVs8fS$=Rra&M>Q_OxdBfz2{VAFdK-YT^nK#|S^~v* zuMi-BQ7wsLd{hfS?%PZTgid-$gpX>c8pjnFGY^jL8ecC82gg^-L_!Vpg+7(3R-=boYT*|!p#r&lDg1ZCDhwWkLJ zkzgPvYP4;jGaI*>N(_>gZpuVJF`3cw4C*w8#@cTZ4^(TbLy^<*Q0TOU)^3ioCDOwG zs}RqeGhamOa)f<&FoJA$z?8&YU}DAA6m<9@7bY_QLhjS)ztyK!hHMK#o@plncS0%n zePJ3iX%h)`YO|s}nu>PDL6%W&W`3qz>;iJ8X_^6;?3-kRPW5|ghL%jfx5Y_e-YB#$ zvfdv4lDw{aT8hK0(KH#;L>d`S|bZ{-A}m6FLnXADL2S~IIAsirE^wU;MuiS zTVzT9zWJMtlVKCjXvVeynAKV5A=j|Uh^yG#Xp|ku+O*Em&q%Q_H$|=5+O|&Ut&Q6l z2A^i5q?Igfn)plbI8147{|_|t4sLNg|6jeRwXrMYDD-Zo-G+B80ifz;Nl7N)yc>_jB z_vx+*AUjxp#`sRtrCsH&;+5?~v>!SUR-LOGonecJbk+RX&I}}Vo3s1Z5H|0Y96N+b z^pN2m=5?v;E<9?4i$(JAx=DhDU9O+yk6%X<-Ljzh?tHdBkXOVl<(5MC8@DmJIN6qO zv!}7v`R^J2=Omqu-z}kBv|@vcL7ZpRu?hE`EPCTZ!iKJUJmY>-H+2n{N=e|7zKJxPXJ z4$g(%5LLUTiq7nr6{_3H2z?d704MVI6H_bE+LSi=S%PYHaC5o zdweZO`xaaHz?XSI)Om=EZm|?V#t_>QV84k;-&VVn>Y?P002ol|x|l-cn7(a}_ulv4 z@83Ti1trZLWh{^H-cKbV6K@6NtR1x-aVGPWo5L}Zv=?zwa}rzD>QZ`6l_~zqd#aRw z7V~0{3MSN2?2NLg$rYcfGSxZ9;^Qgi`Ci^%(Xr}IX2Kj|KTcj?ZfO-*T!3!GYVmGy z_iSw3X0Z+!{hqvBC~=07Vs5H~rpAJ8L}(PUh6vqm>Z#F7Hb3X-{RxF2Uuhs(wP4zk zNl}GjfSL6`@w?lckM?@!@$|1ZmghALP2na{Yj*y=GS2j;w!6g5uDWGWxMno)`G{}p zhm7ot`*yj5CKsr#1xJaaZ&54ZGCe~c(T!B}x55$52ORZG9SG`L`UZ(&*nDe`M5wde zKj&EHZQZt8_rO9BUa}~BX&kM^b-BF=Na>TSJG|r8a1J;T<2?8$*oe^S;%TenadmS! z>$}|cpYJ}N@1Ef7NZaDBjVLliLtu12y>4RlHTMpg#ZHkw?lKGsjw=aslD6V!pAd#) zLJApK?c|vm4a^`++hk>Jb2$vWUqpRR!KSG5+<(x0n+`tg==!Zyp$V&kde*mCKDY^X zpPc39WOXW$6|~2Wc%EMfB$Av)UY&$a{X6t*cNXsi;oi}LvkIg;)=#1`pq`$6&fLPk zEd$+lV&UG+h<^xfeGuCj)sM>D5!rj7?0GKP-cy->IuI^5VXLDCD8ys1QGoSmcJ$65 zlRFV`-BCFl5C(zbV(}Oa@xSw&Q(JtU;a^?!-}pYa=@sc`8s_B%PcIkEr=ffV*LuAW z-lb2-w#aHN0{u}Zk_kW6TDg;1qP1#7ran+bZ`%l+j6>( zghx->co#t@4>w@$<8-PA+=C%p+JhwJTQ1X2R4@G_BxpMP`5ZU-;5IO_dBAR&l6NwN zN9ZFFD?@dg=txH@+7J}5mSC6wFBtg68cWBSF(XH+&;sYls12S4;k)G26huizJ|Met zD;6yDfk~~LD<(s;hTP5Lejx<0ET*v>xxBWggPppS(MuQnT?|s7>^F41(`(JUOA}L+ z^vy`Xms)T$m;#x0eyzvK3LZHJp0ynaf}0ZoyU|3~Esb?8=PDOnj^w`4$LP*nhxFSIX;(@`iN$MP`R^4b2B4s5We2C+cZ!S?%`D zLV`ljRn3qz(MJT#YnE^pg|;bGyG-{eLTnAt9}s{IGPStg?GN{E2ZWXf_KH3*Mz=q1 z?M=?O!1&Sh0>D=Wd|sJ>tmx5J-71SFYMr(E-Xf+d)xIN{kvmT!1%j831_PU-+M)ZV zFjRv{gVLC3b^RY{=M>{h)MfF$t$*9LZQFL=wryLt&D-wVwr$(CZQJ&ACg0O!9wwQm zI;l!3mDIyId+)W@4@JdQD4~s^%|1m__rC6Wg`yw#Aj-W%N=(5C(ke9`_HF5>1ZiU2MZ!CX!ax7=gvEI@rWB)0ii(c#AWD^CKr z4q(z+?#Lz^GE<7TPXAvB#D#jdUl?FH9LdSuS|t-n#%FT1#DmjzO0x;TtI+r^01S?L zB3#XRnrIVNdec@bRfbLWwec;a&Lg2kP6KLyvQu*>xWjRiSA8RQk{|plzWe4h0s)MO z74F=+tjxpG_?LA2eot*qJ=QNNBUU^qQuMQ0BSxGW(ghNA`vX-#bS2!MdM;;Y zmz%G%nUAxXi?bfJau79DfL%4*mIm%xGnccE%gy}b?bjo+8sXtkuhuznemMww_Qtoh zi@v3czM+dfP=M95c$ThTXtf%kx(aS`hsg9MVzD=(To_#qfX0ZK#M#c}3|Efv1~CsK zr|6>a&YRhKR)61!Sb8H$}Ktepay2FSNHICplkRzde<! zkiXI^dOq)%pb(Q3iX=Uhb>^v@D01(dTwOo2*eoe$JCDdVB6v})q57=2Ap2*FObIhu zfEaN~xWh+t$<865eru3;jcff(L$EP)iTT@+9WF-m`=(71Lf&`pb^uZFu^2`4T#zCj zy>HD)22?{wT!ga@_5$qH^!B^wJf_xX_{#JX?_$En+qK`*)%7;#Go-N~SFBjLdITqTKoB1M-li$)@jb&C-ERPdx z)BKI|KXdC!?`+qVW!krT3B-N0%8p`v$f=QSg^8W~Q%UINT?~$%u?%+><`GA|o;-Vh zIQR&JE|A9S8uM}a-6xg)9N3*go_KVI)NxFir@ zv?io{Iei=D5!{LALzMIAGz7RB$q{b_e|T+w9sfg32!zm1*Jj$JI-MstXudldne4`# z>h&k()VafrsXQ(V z+u~AOK95^Xy z7%O~-N%Yk)bo5m)n$!UOWXGrm3~1|jN2gct0T=-un<`bfemb)mL$9>N-9yd|!Cu`n zx`Q3=D$X$=yt%!-+u2rmNIa%_u;`pe|3;^t-kcgN2QSoJ>ZiLLb(cEV+p4sAt%b%N9OW47)&K5JQPyPeGk=#s<9 zz)cU515NohT#MTm}?*KUOr#<+JM>DLC6|&5gq(?j$QQb zx73zjMb+p!Z+X%{%>-AmFQ-){4e?dM7dge_!-v89ha>1zV8l)y{IGPszQ>LwMp#f zv62UoRMDiYJvC&ahp}0UxfO6{*7_#+%aq6Mf1r=leM3HVvXw%UPpzl0VQsycTzpQk zAQN{(@o8xVETo4M&YVvFH9F%2)W;s-nG%bVQ!+o+rS`n?eWvhimaY1hax;#^!kxSQ z&`3vV!Iz=WNC!HkwRyhEjO4<-2M^2mrla($!qS`5nuXBS;la{4@bV)Q;u}0GIt%cE zyjj)02bbD8WZkpkU7UxsA{TuGqNfr<=nb)WDk~|je6V|$@<~u^_s(-Yr~bZCO=@{7 zP>;_m!o4xUEn2$%;$v;Vy1P0GXHJgcPHr&KjB-9=``Oma&0TJ=sB*!NR}lZ6kXc=h z%r5%php0j$>%~cxUwgAWBPKT|0G(Oos#=!DTNZN6ZO4c_>}?zk6i!k*eb~d73001F zfh^U}8)*rHXm{pizV52|GFT15a#!pyW znTlEwg#Q^stFISK1*|q|KO<=Wm9z3LBAj)sd-bE_iJq@u$l_rO>XW!-l%4Nqmx*)8 zDP#(wX4AxBTe^VaQmNW&xntaOuAOdt?KuEQj;bTwWbB>55I{hKjYw zyiC8w1S{)%O$n2)6istj=)B(*@C2wB2H6m3Sh{??z>r7A`poYEq` ziTpYN^SuHjRF&MN?+>%{V}7s4#)f~&LnJO0D3T7{GY=KMl5BzJ8n=5oMN~2k|4Lz8 zF7p)Vzuwq?1IBY2aiFyfJbSutRl4XaAwConsy!7os8;mse0%N0H0T|d?edzx5uK|~ z-U}){ZOV1m%a)tY9$%^YpSRz-!qrmmO%|)D_Qxr8OuF!O4$Gu`B!kPxUOpEpseCn8 zp&a%Gqt@Tv&_y=sNnx%Grv$n!i-ozJeR8S0d}~Kb@=Vnl4$YSIoZs zJk?%pX&b6uG`E!w!!>;U`c#@ONEa)awj(IDY7@U7xl|WRu5%3*nZ5}=%V>_fwcDwz zJT*4U#$NW)R8o({m&?cgy*{)sx;lMcA=|csD|>%_6Bbfgc-e#98@QbejU3QAm%SpKUBDRv% zO8DsrCo^G)lm>U{q_C%!OYOH&gF>zf1XEY2GwzVU*!II+#4VKhjshJbzSZMnT zQ#&ZcD+=w8oi1^^bPFusT4F8NpCBXZpzz`3HsY45JLE3IA9zbAC!sO?x>p@h^Q}?t z2mlpETrY!jCnPa&l6XE60Xyj=a0V%i*bKB{o~~L)W94-W>~Uj_y1*+e2?J?9d-KV$ zFxiH5k1ALz4~^DQ^IYB*_IGufyAPm(uq)IFX3NdyLPxh`}#pVk4T$&8j zqvAc+a)m&S)~Rm!^(fG*Tu;{Jxlq`}W!tx?7HW$CW#2TORd6_fLyJsizIf9ZObyVM z!zm7X6`!A%ntp>*jrQVGFK%(rp;RZ#dsVq7dk?bvIi0j>1swC{!phPELfRH3HZx#S zw})3Gq|$ZbB}sg9zBL?s0;il6C_Pn5^-BM?B6y(G_0c5%N~>GoR)r zRPaElVKk0_52_p?DNhn{YZJJ_o)Y>z(A$hL+)REDAHyb71>Hah*?K z+%Ikiaug~Hr-h^E`h$wJ^O@ldM@Odf2ODVIH1*agSB(_ zBeSfO{H#7$T1rzlM2mNK;GWn@(uYBTrmhIL4=1C=&(&C-s86>`RoX%H#gvL)m8~-n zZAd;zv&)T%XmLflhHgA7Oga&cbR(!G@M{^f2s z3Z#RyCCBkR*750!1DyGhMWq!LVW38vEZ2~PX@P;!s^_69b#+VnQ6tr@OQa0DJYRe2 zm^aVIgahc-%a#JA23==eNX~oIkulkt#znuQb$LtL;`WW-CJxsSDDpT#WS!1#`Ucf< zz-0Pr>H~#VGW_L4c*Ad(+CD}dL*Bcr(9`Q}0j*t8Z!@zt3+VhDWw=Z=z&o@s;6SU! z7ITnfNX7Ky`?O`{GZD1sDqJ2n>eWo*%{8f^HP+0;j;%?DRjSGM<$>8ugrRbV0P${a zC$!HQyp&apbkl^W_4)10&1dak8EUhd3H&q2Q%%-W5LJlLATF|0*f3QqK($c|j1X5s z9mF{vk#6oz5Lva>*q*A7W~=cQR@T~wr?Hhg4sWq-Cbtxx<}Bd6ozU+J{J*TDkrLuWjXp#cz+Zi%9cy(`*Ur7bd&;!XyV_4BR&L-=G&wgP>tK3R~Sk!NE5qACq0_=&7R-Ui|DL6Mix(gU+ z*U3?pTvT_DR`ea0eO~{V$pA31#UgJ0TR1yqbJTmqNhc#$$p-Vu&~6m@ZW&e?HjJ&N z^-*z#_~Sg!10Y^>Zd)qexjvw@u?LO`{^I5J{Hm|3vJ`Zm;;J_``d7Bj#L!()wp$VRZ-Z@PerY3vn z^>t!m5+ibofq2NYoe9v?7iK|XI$71em9Oq9B03Z#%E&A;V4^so@W00MB!_lYD_gpT zEWpi6OD4@Ot2R2WTFIHE@>c6f~KS$TU~k32+qd8OJY*7t1`a2Wou(PA@ZqJnsAmUWTt zMwU8pAbh5QYQ` zmmksW`BH@r>{@-$gmHq)*swlb;mx?XGmAIK&N{OsrFJ2~el4PT2NU~F#rX0#1bd~! z$oPo3bNGM$*k0YX8j0{r_8sOABZtYy+6ayYBz_N=&+uzZgWJxqaBPl3zFK6CDNG^6sL_fqRH{Q0wgZ<; z?#&UuU+a6<%ZD0qdIg*33*mqcMqb%5*xI8E`blGC;_%c->{;ZrFb7R%Cy}4^(fMSa zl_ww@dBfATJzR}N6KkeDW7x(2SgIS;RQ;urdG}j>eV}rh=4Z1LtzGOGY#+T4vt9Rq z51PO*^QcFq@TU3wcV}&<=?@59#6)lN)8z3vz}8N?!!UzNU|`<=T)r4yD1yHS%`Q^5 z8owoYbOAGvPQ^HsJ)n(DZ!Q#qCcdRN3>v3bIhOp~dB=My7E}Pid$l(7SR&Qbacll6 z)M(7-6}6^Hlk>)F9vvGmloeW6n?ru3c>IE_AI3ne8EOk;j1S2Y!U#cUW>2a&*+ykd z;U3oK8ox3KFn8q@fA@yuk{$$Q#`S{-i7rZ_^lBY}SW;SRR* z5v-TSIb~7}XB#ph-9^d|&7DjPOsKBVz+b+(e3d3q>>oqYIosOj_oQjm`j z;f6?m2=zCSu}<2PmT=fg_04_IL0jQqYp;)H_ucxGeQ*SNkSv4F_b)Ext76eB3T|zM zl&}Msgbv8c$3;WC8|eWYvS(=2ISR8$RSl?b_JK-$b}jp^h~$64l2h_j&)c!f9*s1G zzxYdkBb9l1!zB!5mA*I4RQ=Q2VG*xKnG%CG=U9u&Vy;iPzb=RTz2!3)i)dM8vDJ8B zSTRMuTp)y3$sffyl!J6lIut%)x)Lsju}n7Y(zAXxU*+EGeFP2l>0|lZwlI+2%V$5I z8yi}DS-f}|Zd(kjBPC&VP;NMZ29G-~>75O^)u??lb801xK}}$EUV?=iOLGWmiPx>h&%& z@d4bXcBZ2X`B?5AvX$s2Sj&gTMYlBXOaHm_v>6rBU%7J~Hh1u}8Lx`*kSJ{GN7|r# z4dwJ*cJ9J@>3HYTO_Hb#b#d3UZQtKhT~`^rpiHXIdOYtY-=BAtmYcBF zB*XI5#~t-4kTwTh8PUH+?9YITp^@10>@va~A#PQ(Wm(CI+V`*AL)xOyJ(w@`5vv9b z(x-TeAh0F}X$hZ(t1H?kc_s-ejJtdJ)X6Z|?^|spQzhrwI@_&u&f4KJGN6%SQuQo) zD@wk)%9}4ipg%kJu^+UOF}jA^I2(i`PLmFf%ER?-L9d#g;uDQEPT-aU`2`gje%jW| z#7NYlaX|u7zko%X^Y;rMGxmIM61XG06f|hZe8Q$0S1yYV{1i|#=q4zef&yIWH4+sa zfb0u4QgK8J0R%(oCBHdQYwiW%%g$yk?XsYLY&`bWqt9YRSmlP(u3Zn&62%Tb z11Ib4r03+uoM>#GRG#NIwTgRcUy$n?G1^_KlofT>D00+zxVxWEsJOh>|E4QtH|{Kd zkotHhIEA$qieN)9&Z)et>2u16;7bR*`A<0|22|AC%#2;-p@BsZ^R@2`BZVpT~le-61S{f zA|-;(bGI;as7QNK=Eh2oo|as$`m!U1kGX$??B41^v*a|EweBY-K$n7*o?ID%%4qQShTtjULt)k#2+@zuu!X}jUmxQHwmxXdO z_xL2V&nPV?)`}v%Z73?33iY-Ym0;W}L(R!q0~KsFLC`@K;Cz^2DIz%Y-{GG?^5W5EAbX}LFj&{h6;CC&lpM2)rqJZmC$!f|Cn$R&(&<;KT!^= zjx(O3h-@ntiQS8uh4z7@%~3vt3(i$51-_@p3>w*OtrA8T{U}|Rv0SinYju6iZ^PtS zD2&-vg58W2NykpGcng?K?Vye5^JfEgLvjWB1#fOWTe;dPo0+U?dRG=d3i^Dg#;$z? z{#Wjj5~2(CaRmlzY+UW)OC-_0`iL7N{JdOW!lgIlb-AQ+<0_n7%lYYiIGlkI{2Z}? zxcaOu!Y9mGICT|a&W{#@&_@8<6cwTd|2N!_)aq?GLT)GUh3KDiSwPg{-5>Lt1=C_F zlanmRws!r>8T;8Y_MyYL>&LM;%3(QxvAyNWrcb0%AvXkdO)Tvwm;*cd;s;2OZLNsw zf=TBzu)5EfV6-B>h}jSdE1HSd*R5n+#d!8=BCyH22XjEDe2gWB;-X zLDCY#UlY?~GGKx>3%~x?3Ze6Qm+&{K-nn|4*zrz;bTS^CKBc?9E$wDcCj{y};xx>F zMx(5U`$zz4c$d^JY+Dlx;NX`dMh%O!<_Y4DAi=iX96K=le7BIhq^3(U?flno^X&pt zZ39c2`nZw}Q&x?WWIu`){ygONbmt6u9Q2JL(3*g@ryBh95xDQ%qIPvY6ixxJiuV~2 zihplm??~;!sIlpcw^#V{(g>M}b5wyR=*|H^lv>eHC9hb2sBQF(oxfN+Z_!#+XQD8e z-m}nUIPszd@T3-n*0)XDm#mYyR^8W;rTG@kW;7ZJ2Ik?`9eK(<&>17CiqN~l*}C=8R~?U@0e2*n}jV(5a9 z8HNR^IT_$0x60^2n<(4x*Z2UJ$N2uvlp|GXWeh$OWjqB}fQc1-uE(>dX&7`O9UA5! zuxu5t{qI@)dYuk`jW?$=NV9tA>)eyQ8d95WrD}B_3#NdT8v+bISz`+vvZ-tBSNW3d zpGHSUKU5eL17Q&ArXr-jZt6OMkttt2HY>F%kouVF&9qbn=o8X zB2bW&Y)0W$FbgPxW@KLFH;rXTMhW_4RY_0U{MZk(DnxxoJ|vtaX7&%m^llJ znLWo!PoOBy6iZMhToY6QSP3ed8PRZ+7FfIKF>ffW(ni&X2C<^Zrv0Ku5Vg3+>91<+Dk*W|2tUyGDI5QBgdI0q1h zfPAQoA1ukuZ&=OUrLmWE?JUB5@D_8WKRw$SUHK{%R-aGd^Gf%?$p&dPEMdWR0l}QQ zOK}I--lvld!C_IqtC5NQNYCo;VG&q5M;e9tT-lBdROD_=c=9qX>y3UxI(}kzz`T*2 zI&}cVO=^1>YXYuCS(IV7$~~xoEy2XvuLBNB)~Xf-%9*jx?1PQ%re5miass&IwH8k_ zQQ6O+JCG2m9GsTwbLNO7xZOdx&mwH58>Q5B25Em;v6<-)JVTA6lI-%4pBa_VnX6?( zU$19W5UEK0){7Lq&MGoN&*Ja_T?NB@WyV_GU+S8Dzcy5OOIawMh!)Yx#z0tkX*>68&|k3N8wb}gjrkN7w~?QS5Rfjq zCIEbga58xHxS1Sb|0NBkobxp*b_=Tl-Mb%fRP@aYV9Dfm{?T(v3yTn!+u2AIkh z7Jw0Y4OM#wu))z+Mac{M%O3%jx;tnH+<&AKaE2h@bQPQU9-apJEsI1$BT3b8aN$jv1Hx~{m&I&%v0}#mM2aV5kFALfKU&4m`ouko*iuAs%o{+sR}rqytb#f<6?~q>CVo;{seDb zXA+;h$e8<#FIx-an>{IR>6Lt;n+gVE4lz^EeH_h|Itoa+kB{5d;NfGjrsXfCH+c~q zgm=V3eu*zfc_$DEmvDPk6jp)OnKM}s{<^!=bDbnLt{oEqQfR47eqI%G-XHU0i}8v_ zjG~m4VK2btRdhJoHj*q(5csXxMH=F6OvEAY=y>W(`wqtH7o61-mbge1mNxQy4ILhG zrWXt?lbpIb7^b;G65{;K{=mJp*bobJoT#AW^OxeHsX3%39#eYU{6m^}>7?1fv%2xn z*iwWhewRRL@o7XxE+3w!9Qdq-Sr8!L{sD2gh8CH4y}Zn1!QgD3@y|~GL6ft0tiVl? z4xYdlH<2p7Af{1WqKa&h<)8Co~}VP`X|`ezjqPaNxFg&|Q)!*ayQ z+#liT`T-tGSWNSbqWX5R@KL|d++k8CVs*YTa&+Q9Ia{h$S*Zk=ku$$vLFo$I`sspq zM576%H@{`W>ao&nHV+*W8UhkL_$;&=`qyxJyVIM&F_19dP8S@`S6^Vwu{*#B6Jm7g zo2E8axLEaVbh>L@eEvAyBm_tCu}yi#Z=K(a9D$iXz4}*9A2E4}b%}*M{=PE?UMzXl z6+Vx^hTA9?IRWO5jK|VVL}l%8X;*ZWm^EWhfQ!$g@}bW<(UNH`v3Wk^Y&{%9mENKZ zu{DbvzRQ$ZA74Xo<1AQ-LLuv!d3sA-(~S#C7--vCzAeQpc??!D#xX1L(%1@F`@~Mt z?(SEL82CNyWDhBMVm~ZiNvkz+>iMtd=fKva=MO8R7Tkt`T2aGwPpk~|5)zPnDuW;+ zUMW=BihKS^j(VhB4ecPhp|nD}Li4@t9bRX5-{6F~mENKftT(9J-CX8+ zx!I|re$y_OeaQ)b#7L#kxegtnP`qPEf1nonYXyF(nzSvZ27{fJ?(?*PmWW!lJJg? z_B2!9JAn&M7&(2Hl0Y|AK~^2>V4QOmL^~BkAKx(DT1XvC3g8)_sysaTt9hW`C>OV& z$UlVANQG;?7U_(pk=j|o+XVU$g^%emL95{wf~PQd4^nv9)xZmDKUK>w4I0-Z9;aHH z{jg;g?zb3gcMr*`QTdhSNZB->^m+(X<~%g z2F)I0$|{}sIX91DFa1iHc=r)++4*}8zs}rKp^7&P5JF*t4dCt0d6-ef%X9k7rYanc z)iaJIFU#b?nOb`Cg4xuxLNWvoMH-Gz4KDvMPt^FT1$ks*x@TsL98JE}PoY22r@?{b z?#^38tr8|LiWr4!+L4CdHHVZ0IBq1t7$`jBcre!gVDj*s=G}U3E;tT-aI|rRWZTH( zM8)bggJVuN;nHN1TzGQb*!OQpI{V8Z(x_^l{NM8hw4lF=b^X+U5la`5N4V4mp#g$V zyj2UryWhTniV~BPrd9LTq7eG%Ii9??V__YE9o19{Y1L| z1Q&B^PjxOlKK?B*=F>2@CAM@snja$D`i+H4xbQXn)s&|zxBXpAY#OZr$eD-9j~PV- zv=*w90B|Qr!rC`S>K0`)ok0}~*{cF)d>AOFI^Ka(2-Bgtor!;mHzTh28-DjD3+A`x zRDkJMIs6$RgL`&UXGjmhsA45=7tm+3d+-l}4R71^TdWE1y4RnBw{JQi$D0!>^LSM` z46vhp_QPZy^&_|m41+-lu;aJYjlQ(w4>5iU6wS!TA}FCcupN&a zL`Hp$hU;ptQHMw%40^mArc=tywPl*mA9-5B34$kE!l_ps;*f?hVX6$4k=j2;lh0>X z>${}I&RZ7UWN?MwXE5felQ2?KhHjNt;5-=x1sQMlgWZ8Q6L)VD9NIe3WhZ4zS=KR> z(trIt;1gYtQ(bTh(7RF+jAS3q!6PfFLh>~fw!@$wS(U$~C_v!h(ih-(uEZJBmo>PE zTJ@`*fxr9V)@4Hpb=#!805RSWo)w9`9?^`6Sw=zxahH|eSt*>31XaYN z2X*hEsU8#|PQUFE%cD(KMd^4jEq6PZx;Ogje|~&5e!j2V51kZ7MdZt0`P8|ZxnAC= zi2dPWXsWeONPo2u{XG82Ep9Ge=6`jx*=i*mYllVSwlLtfW*>PR^;C5IvwAk>pc`)X&;a`^mhb+)#e*%gx98^-Al??E=DtF8%vQjj=sT| zzP}kt;^2?rXDyLyfxsZ)dT6P&sE_r_&ECO^UkEo37BF)NouxN=rhO~5A0L!6w*COk z!ETB>w-sjKi{dWk(f|DJ%IdgUbK~cZCB?G#5cX_6l!z*wG1QBWc@V2|U=~zWi$$Dm zb(bF9sVfB4>(<|xK|FX(ODUhH*MWS?_ZMy(Gp8_~jwy8EW4JZsm8*&g5u3j`ZC}9t ze8MePFB+{7ztv>gLn~I1Lr5Q_4mjO=?aJo@X)%lcQ~A)P>8)1l%uzTUbqR@9>Pv@a z2={2rjVcvCR=}M&W#ank3C8n%FYyD!6T%NhZPEC)Z7wdaTu1-b&Ml5^fjOU`Sk|fM4~l~L z74(tPB`BY3J>2>mMPnv8nVK}9O8XGx$D&oa0b?dTCMLvK)GN9Hjg<|mAy2{>N0`-5Ucq>SB4=2V=*Chgd36SQnr6(BZHZ39OK|# z9)0ZW;IqvLKrIrW@4Y(+3FbF4INVWyw4`I*G-!SNj}P!R~lt* zNu0J8R`kCwzxigu|Mw^V|GU2SBFO&a5SqREDD?1#h8S?a_Ffk4e8_Szpca)Xj-(9~ z1L>Rt3o4l)z%DSHY7FkrNSCk0z`Bu-q+Ad>2x>k#)T%t(F~dT3{!+KL>G?U{dN$*U z&?p<=Cf(=#p*sT;)H|E3wfpv3X$XFE0&J0lxcQv3z#Z@UMQ*zAUkfQs>W6~6#!5aX zoY#m!KOSI>P7v*)S@)fWg(r4{G##ta8`gdc-}074(nL;I``q(H!V8{f#oSBgDXkz# z8yK7CoQ7pe=>E>ca0VVE48dI0@JpaE{`P8+S*!c@^38+jy6y(fNMY zhiTVvNZy&V!C%}$MZG|`++$U)BU!l8PuGD0`(WOHqCKOgYHMW4)^q8cQCh_50iFmS zZNi-%TfV?Z{y(0o8&&JJ6O|pgCk4?Nl_f1#<4`DU44s*Cy}lT8D>^?ej#g>(&|wPTQspqAM6=Td!h=E42keWn61T>RJ1+@G6Jry zQ<-wztTM+Uzj1_5LepVH%aiP4a@(hd&(-5CHQ9^^J^;u3x6xfu;6R8LLj3G^liPLe z7YgUcQJY-*jtG>5Q0*fi!d(8q-Q7Z$bH?8sSXJos&Y%<2kjGlrFLwjdn-BqWehJA$*l)Gxu3^NoSws=vuUZluH634%K8tzMr+rs~Fy5e#KQA@ywz9Yy-_Dgwfz zVq-KKS4REp9?$Q}X4puHvwn8++wpRCl4u@MI+38uo5@3NYLFIw-Gaw?YUB;v`g$)weKa2%hE{f=To+?~I1~j0tfDo}v7z#S09fL%;@Pe5=L!Y)HR_2MCA4SD z)QJNaDMD6;(=OF5Hj080^t{voOJZ@0rihNeB%EhmrYcaRD(T6&GX&!$@o#^(H{{3^ zaNN`Wv2+-)<*Cm83>^Si%1dd@o<i0*3cKk9$dGson#(zhX>Ra}Zk%5A3=p;hsnCT^a)NsbWwx6o5IK$7!y3eam znlEe_OLZ=!>fVpSFT<&=(lynqx3w!%vr|3(9_BpGirGdC0^?AL&RHVT z^C8yK_EIFD@U$eDV37x2$BC6;wf1YtccT8!AY%6aLFlMW|zb{5H_|IDXbK3$`~!6`C2N* zSjKIy2?iy&A&#rP^(EGJSn?X>#s|!$Hxq(StH{he8@M=ask8I`0i4Uu78K;brD=QU zvIt)OdwH98Eb34cQp@i3oa8G868y?yF~IDm+l-t_nW{l7h$%pGoIz!5k|!3%DzAcD z1OM>14PU)ZDH~?*!KBP*iL)lGgQDzSMY>2L73a*3Y|#_b<9^QX>ptESw$FHF;NKfx z?zH-f00Ro3$9p>19p-%}ek+AaSrtFa3t45%EU5Al212N-;f(O?5+>@fZ3NpR(lZ)h zg%rT(=Nr4)Xjc0fp|Lur_{9y?I>kahuXM1t@FC* zW1$lXkHgKko25jpaSRxDD_PKcT1~9Ve`vY&>Ot3Xvf0p;vwHwRi~+tPgMS0LrHgwd zIULeL1XT`(C5^f=1Lel;_I^ug<=a?-D4N`0-k5#FxeQq8u@rqSA788S@Y`*+mc@Kz zuh#T$*jDoUMkIKd33Ure9nOt=;X0&>4v#N07L_eX!f`X|$~J|GStHKPS%y3e;}Qi7TqGnQrOw>Iq{yG@5ypD4Sz(^C=^zr79so^@-qK93`jwGvb zDJPIQ3_8(VXA#G}R;$@|M-D&1S6bIX3ZjwL5r%<4%RN(E`e#j^YPcRv;rlfhobjGgbfQL+6^r~@$yjtGVf5sZ>( z6n~OKcNN|oNgfdp4I^-f@Ijn@!-xncQ}dU-dQaovk8z~oyHnM z?AlucwK4eLrsdPm4#UUv*xX_oYTl&Kwg-kk;!0xW+9DOXvcrX5IA^f%#Dc|dcK!M! zYL^SukDM)QpaCZH*9T3d#g?r^MPVnh$HfiKtrxSq4XWg7*P^NRT1LAzq8KwH5<9Bg zM~S+N&WkE?wLf=&G;y8BnyVma zg7|`yrScX_dJ~(;T~L5TnNpW0{-weFx_M|35MVWXMw;anlShlD(!;xlFfD|pxHitd3mc=~$EP z&FhrSWlHiA>uE295$RxiXT_~|;S3ZAtIz^ZT)2#0v`6WD2tJ6Kxe;(fZmi;G+77s1 zF2jx$0)uen&#zee(Y>as;THsr4mHvhp8Ezbk_k0|7KCkBFyJ`17rsVgUWjzkgwQ6= zWrZVF6k>`!`U%C{b6=U@l_!*tcjV;cF6ILp0Wwcqc=X^PuCB{4U{CtkVA`LtAE4u4 z26z;X2duz&>~Yi{^s}OU~Aac19c^?fom_Z^$6r4O11w5SI6)_bRO*rX9S# zF9Sz}c!5{k)%MH|II1o6uP=$4Ra-xnme&V5p*r`Wnn`A8NODG0*tqB8^~T*WC$M@& zdCZjx3WvmlypY4j02=$}^!wNNpG_oMWwgJ(p7as7OKzd3)dT9Cv{$ zxR8ouBMd8CIW5jCBtv&1gO83C3_=hE$S)BFFBb5&f{dlo>uR#8Yp0Z3z)_4yLOCR4 zX~XPZ{^N!CS`}H++!ho$IIqIvaplsoYnUf-tBBlu@an z^0g1R`s2v~5wUc{c{h)F+DT6}9q9LE@(LG+UJO)t$=%~Yw{}}^Ued<9iF4~)%s(xF zjqJg`4*llqz))!PW%L*WoVy3z9Zz_lZoLn_uj0^b{J|b0mXsDrq7sRd-n^bd*gAfgX*# z1K~uE#sk-kY;hRL%&jeok6_EA_Kpc) za&>WyiQCu?QqcY~ev+dYY0pMjYQ<|nf}q7uA-sijzH+vA+A?b$KK&5;ZH_Sb>Z6pW5Pv{osfyKw#&jRrUoscndo!vziE^m5yswszGF zf&Lr$H#{rm<)oLa9Qp2n@tiLfr{MT_7xs0i;miD&td3c735K3PD30}?tapEe_LX|4 zhkM{nCowgT1-IL9TAcWk@n^x)WBbWO_7ddzxh}FUrS;P){m%IbGSw|0qe=wwh&`xg zkDgu1vDgZZT%^h3lQ#DkM~w|@MG!fr7j$)9uZo&kSbyJWR2DzT!Oo`KTm4`C^o%pB zn=|y-^KrA7;U88zW0fI%Z9wF0N_%S@*jT*6C4Eidi8PmnQzLHwgk&jbz@km8oOQK# zdmtKK4NwMug(nF`8XFw7-6uhL3wmuY2H?ff1mN(y;KGK@d}&cpS-N1e2oRE?U=2qZ zsbhgRDfo?0t$oipf&1tUm8ACNChgZhF#dbE!?6ls)WQQRIRUvzqfW9KG|^JFLW=3G zAy_;4Spo9e^#C5<#0y}%6%uV+S1~E z*jyLK)7Dc)LK>>T@%`RS{gkr0*;$$BKi9KH8Vr!d*Xd~H`k{#(Z)bihP$9tiLxdnQ zD)4!$TOeI+uF#7xzpBD~5#&xR@b5%aX9g{4ui9M9#LQ{4PJf(ND_3C!;KNXzFvQ9| zAa)=m8KKBtKpK98j#B)7>-Esl43j}nsacZI2rRD=0&v5e`L$a~HqK3~#kJ-9p-dPG zsr3A8%3KcCgRX|Jx4jgvDgSbeaP5$#DF@R^VW~L6vQJSpP#sEFRYBHbs7jls+A1Me z3jqbKy@e)UYhiH;K9Nk8#hka{AtvWlGd3Pz_*XSzLg3`D4!tv6cVt@!b!N}!lZLo& zAr@JT$(Ut2AaH&Y(d{GHhLG+xDiP%%)slG`FNeF4O6sYK9pJX(w)FuDvL1!S^hGqu z80VAXnX<~b^A&y~DvE^A-*rv^iHE9FG*d_qVXoP&jAb+IlP*YRZLVFPE7JgsqW_?B z@cc)T(Nc^L_Jgm$jSwwBN5$pC^?K!-K^YZ8_i;txi8Wvn~2#foXYJ zwltVU#nLj)+|uBo&?u(0S(+<2tyw(?#K10`uYmO)lIXtzZx@j0C8v}#=MtSw9J`8Q zD-5I|SgZWi#)U&10@~K2Tg%uZ7SuviIRz@6T;ToNmUldxmaOy>b_iUTqWJTLQ5kd(-FL2R+w3=x@&8x~+A#gqr4Q8?~K zm_KhS!2i|84fLXBV?G9BflxqAa$i$-dH`yd@aM0S?Tirnm$3wq^!KCL4ee>0QA}l~ zz1 z$3_uCJLnHG6?S6KYgkrceJbyuZ5Du>x+>n}fLH=S}-|qclef}82>h4|SKIAZA*ALI$yMBTVG!L&`|L(wh zWz1@vfrj2i_@h^CY}F^=YSQTNwYExN@a{oj!l2({qEFmdp7hP7(3;q50>?Z&zj2hn zFlmSk=u2grc(gSA_|n?Ou`gYmc03TIMI5t!(1J5ckvigTL@@TC)pC<)ur>{o|q9mQ}L{#t|&G&Xh)!jDejKoELuz2j6a z3B;Wgbd3U4+=Q)&UH7`9QBwxlYP+`Ln_9hd1U1bP259A*%R<+EorRa_GFe9I!5I(j zn$T^cPMX%72{Yux^AbXYkOq=If>_1S`2IUMskuLYT_mtgIWMd!uQ?(_zPCw-dp@^^d53Zgu z#jmk=L!wRA$$qyNVa)FzUDM63EMv24v)JsH$4t4cL=Q_*D&@(-f1wnxS+f`WUGb;V zPcXi70@rw@T}`!46$+lM2$CVLV7}#aMzA z;Qr!ziq0@KS5+g3+llj=+Au*=epYq%9F}G5>|VQ5brr`!7A3y32b2`URY4w4&YCxS zVYLNE@VMGkOV_%g>(|1>RRK~qu==!_B$@lk6l#;M^Q~#y?`8-v3V&OrH*}n9hgoOY z5a1d}dd~60DrZO0)55uMru=>oxtHlw;AbTxwx`YjNzS^~q_eo){xM?gHn#%&FqAFT zfGfc6m%kWq1ww+nx&24bL4kW^@)l`|$#EE?Sn(OFOmiEnnCHtZ5u8VrA*mGLTsG&C z+13UBk+@zZTu4+CFA~2cN0P6Sd@28lf;(BgR6NQmB~E3PD1N0%O>{BhUGnQ{ZT+2j zK4#B^&CTq(0#CE6P0nU@)ZkO1TyeSF-1aTwUfI)v*ICnO;h2^4z499r_ZxEy^T07T zFee;)1M$Q1J0w>ea|iIoakb1L%kMxwSzar+W%&)vGt280=Nxkj^3O5Vooacd;H6`3 zK#p2o&3v`I-r}z1w-JvmueLbtnA@1&j=90)x|`hA8MAUV2QI%y@Zs?{jQJSi$>r68 zGmp7}`E&UVl1q=dqcu6E5;*ox*LeR%QU})Z)Q11mhX2%t|I~)BZTPPeS(uQvC!>gM zNJ7v~M45#~V#wn{^Ft-9`e8X#UhYM3g7bl<(0i7k29j}oSNnBQZ6WN ztdU*X17$O~5w=QdZuT-76EP?)X^-X%Zl&->q|#P%tAg2Xi^wC|4kzM&KD(wllx6J7 z!;3s`c$ByhM(kP7!;I)zFW`*0ZAqI0jtDF>7vKntvCC_u9Dk(XF;WghQjP*vL?uxM zl4j!MVcK=X4OEghe{2F)LM8x=t6w$PmI=Gj#s~Xg{vVrzTk)y*NDcW((SW`hApD__iq`TS+Tw{2v%>qfd zxK-+4_^UaGAV|g6e600_;j?_@Hf&n>~V_FE$Y!hUNN9;sfMw6xnAy(ly2 zh;&#h(vkH;SMGmy!uD0e6qg@L^09A>Nng9E*>>||3y&_ZX%97%l+cj*q0>3do^*oP zrg54?cvqSv1x+!Al5j}bMY>+mu4i%)N-84V&7eFKlRerisDdUShR2z@(cy4rIGSCA z9V<4_ox|hFhjcpAf-jBEz~yUZj}4IvbE6i4{4B>ZrU>_E-%)dIkqS|v-N|0NIfs$Q zUMIm#I@#MDWRywCd**rB$D*Uyb5Z6s`+kiUc+ecJ%2<9s^ZdAv`OV;Y1D02Pl*>o# zIf@9M@>6eTh>0!Z(N|g6z;OCD_QKq}Eph|w4tpZTvfvs9ZFz&F=fwfYRaxS-{T2dK z!f~pOZ7H`3CIm${uy@H-3q7}PzwO;V05k;&%!ONDfn0)aTPxDJi#@}xG7X{%x_gn3 z6>iVmK8WxMGXjkP@fj}A^UITr(4h&Wur@%@q|tmUg%{!63!;cG zb-072>1aL;T|QsCl3wOjG5Z~Py!7Dk+z*DBB{K>)O@JU^c>t$1`P+_ds-LIK(*124;Y_ zX|nE-<<|v0D5KHe?)!iNGVOr-^D!6 zT)FM5B@;~(I~mVQU^L47xL`ya%!QH^Gf1#@8*`VzZ6M_H$Ho3ahj`zQ;Oi{ZBd^ zq**KRszX8*PO|PWnDo)jx(78a3W3hLqszOe2JO)Aat>Ew6zG^Gc&^JgYZs;xWpdQ% z2GuYX)Tr(caSNsB%8lEZSuc?}r?*v!mlidTjrWu4=-d`x5jz-sS(x$%sA}5g-8sMx zTNt{!=3$0CnfFaZy{>W`tBFP|glSk0caCV8fwD=Cks4fnTga_pcD8wcIl_}8I5rTr z$$^K-sM|>sNRWahzIhtIvyl@!N-_}g2Oh+a!ARVFlud7$e6!@&U7|#NDye{u-`z*i z(w8U^=uw1UREaTjeqIE>wW0*4qu*RAaphtXh}}0um$9J32dD3!IQZT4sr9Ah`};5& zRzLmV;1z7(;PiJVrVCzK4kxT%XeX>{((Z&q@rUE&D+o}5Ih&Oa7S~qlJu+`gqjK91 zCu8CMLlLlh=yW3dHYGHkc;KU?rE5i*ZVP=`r5RW#VEV3E%N{ zBodV9gL~Kyx>J6XS)r`d0^=3ukr4lsi@Ex9PCdBUwt89!B z=W3zj3v^mABfy9uM@-e>G+Q3VfTN9z<}q?^=@eixT1P;UX{90$DD@P?c0Hc`u zz35y*Xsxhwi19=RZ3O2s5qm}EmVAs1AH~>Ial^1#C`evjHWp-*9!)Z;tIiO#5>l0& zg<+Ql_WZpXNwQW*EB1TmzEdX-j;Jt`zTerK%P&T2Fdoe@zAOcJNGKtDiz2b2o6EN- z(JJZ^XCUD&<#B>E=~(st30wSUMexx!%S zLlHwA&a|t$MYb_u1b*bCQ0|mtNZ5l0X+qtEE2p@m&XVgTsU}botBTiouJ@TrOJVu| z$!CS)Pni@7J>?}OCoQ^xVhbUuKpsmJlTX^of>QD~K^LY5&-8Y3pd4|Xgvmq*F@wnF z6_P+{MR(9f(+v?XwdNwbu*pM&No}Q~h0IWC($pZrK+BJM1c=^C-89*cUE0c52}8$B zfA%xKgkl_acb|zr>g~q_4xFfR8P_;JbrKH z(aHsfCX(q(K;&gW8>xZPv5R%NbdL0Rvln&RVGX7aAte*B89De_F*i4O6`S?obetpzYEgzDR_loNh3? zRCFWBE$Y0s(A^w@7d}CgIRznR`IJ0w4TCtzENCU?T9%@`Ogxs8rKzw)o;EazF3q5E z*3b-HXCN!#drAWc4Bl9mgN9cJqDt%1IG>E+e)zmrC4ThH5_}rQwC1vtA?D%@q2kov zxcQN!DKzMuWnZ6OfBWll2tIgn{&%K8@!-RS+{0VZ6>i_IbcGS-d8+`; zjTpmBrK#%0S$80=>R~sSLL5E5Z2H|Af^=4D0UQ%aqT&hxd*+)(-I_0cMm4`9exk>} z{D}cG;&)u_b<-fVuZ(PFae$zwEpe5^5yqnQIv4=qDpUEiL}kaXwn$qkFC}~*etu;# zjBBWGlVz<&z6e24!>+n$Xn|4`^ymS2_z@Bv{a2Qke!^3=LQpgLJHNQG{duQ@tN zs@r5?*N@Y>`UDWnWP{c)V2W4S>pktrikRinNf?V>N6lN1$w3O!Y8qnP3S#VVQ7h<9 z2HhmJOL02wl6H{!VvJ#ppgbx28P{_U!+y*aWVyyDFiFornFp!Cgh4saONkVf)* z(q1i*KmGQkZ@0`v0({Vk->BY+`pQbR8_-GE?_~+^5%tSn@pw^5L8_`s2+DD(`5KvA z$k<$6-dyWW%Bg^DmtrV~8eiBoDmYmb^`b27_*ql-xe3A&eOp*n8!3IW7uF`Aquq&g zGMacfNd1ZM*$Ae(7Doy6r-Khnz!cy=L^^6TyZTXI*vx@UlX-kK zT&_qnI=e!!JF8GKJ-aY716>OY&@Pv3&??Q*1FK4~M7yvT+plvBGcif4WKY}v7-o{W zH3h8FE-@IURgq(x#Rcamcd$@-h)|xA`7;J6@5Sz89DYC}}S*~4R zFkVN61s|M4&vmk2NzWDQ&0jlqdx0TaFW5X;D~5QR*UYG`B4pQjLd8tGNKfp@?HmKQ zzujWv_V6JymsZ+LMa2VS7r&6b%kS4rUbaE3UR>bv(7zDexX>(#0OEJcj9^7^Kt9Yu zfw)qlfiVXKC}c}a5M?AR$cIQ+Fn^=qFpeS!@nPI8EJVmw`>OwzKq1ZLQminp3&Mp< z#4yXuVIXlsetl8s$St9~=<#FO;I|@whzWjUs{Ygv|I`rw)DZsA%{_pRp4>jwo<(3X!w2fckG)4XRv(|d z@c4_>oC&=a!qKCR$gVIlW?&8toBR?qJ6P*O8P4?_22`I}K{~=Jz@g}?(wq4bQw?Q6 zI7j}@vs8LQThVv;tuV+2YVHTSV{=+MJnD&9A!7Nng1%rwH*O5g8;b_?ldz#N6%B>& z6f+9hw(^(an{#s0o#jmjTaGmBIU9Lc*hGefoZiWSei(Ik$$INGmGMTu+q8_YFCKjO zr?($09A3Zr-uk<57med|!>8+~Ke~7AE2nW>S_Bfk&7RyA?q}j@I8NcB&xB>bWeKNl z?I22m@jRIPRk}>{WGf-&nkt0y#P8X9teoq6qpprh@zJKmCe#3E28^3M4w@xsc5e&2rVi<1#R|~`I zqkFotf4l77y9ALPolP@EHLO=9&-#nk* zysTZcn9=lPd{>l}8o$jA!&w~tzO(~718z!;-!kzclO#^E*qf5paJL=YjH8)z+rf2s zO`fe;2@L-VR&hyzID`e%we$n}*hcL@G=P)n&6Irt@v9Gw!wrIjGe%l9!`Yg`$J_04HQwhYE>6_vJ7wB?i-@@$jCrdH5WgXj-7d%CQb z%F3DbZPTx|Pdaq3Tr?HNsP@;IH4L)tHiGOYYTMGfr5|SC%D3aRa*YS($v3nGQ`aU| zD5n9*VJI@~6l2xhV=QHx+9I}MocNm=AIfb7IV*$G**c6mdCNet(ekZO+z^(=_5T5c KUe*im7YhKtMgy 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 literal 0 HcmV?d00001 diff --git a/tests/data/openSUSE-11.1/suse/setup/descr/packages.DU.gz b/tests/data/openSUSE-11.1/suse/setup/descr/packages.DU.gz new file mode 100644 index 0000000000000000000000000000000000000000..7e1c24005cbf950283f392cce80ba2f84a7be606 GIT binary patch literal 147899 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℞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 J5M-#53;;Z)a43IIhpw!7n`$7>~)NT5)t%dQLH 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 -W>%DYk_-YD{YWN>q%OHq-jqez1!{o!J9B>Xw@ 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

8L z%)3~{&S(qI_ct)=Q$4Kkb^FhJh+mN zb44FU*2J7Jy%&o`HJi+D_4cx*ewO`}UV+nYdJE^AwKg z)qnMD)FC0P3^sauH7Bv;a6fabkm&9!Qr-pet$}A4`^fgnC_!#r!^s=SNEyZL++y4 zi|0S)X{Uywh^X~C?BC3#Y##Ox?R1}QT)TS)vG1OMe}MfdK>x&tIUDKFG3^5YSw1}z zR|E4!-3IgT9bMu3hRr+*y#SN=omMMo)yu}X(7{@{y|olz>f-gqnf2Y`ki0M`RTAQU8$e+rI^XC|P+8vZ2A$a!L8^qxRND`rELGKP$aG2&hrM=(jzkxgP4 znX!944o}mdX+h&QMfp;#`h-io;=0 z3*~os{iWRm;jBE#SkWWZk8sE(7JM#bSA76&MhIS)+!3pI!agk$?=4L#1EzHFZ6M$3 zkiW?3<(=kXR}H2dG~D$@@~vL(O!;sH@;-Lx{vEJtMIOZRpe%j=c`W=@mdxh20+9Cm zoSV42VxN^U7B;KIVcccRUz06}kJ91l$tWA~=PKI`c5)+D(C?7C&2$_HabE#zb=LNq zBJL+Zk}a4V<1i-a(!dY9CZ0H<&0#oCmBxm#HA+ZkqG3bq!p3>J9@#z{7viwXCfrVp zQ)ita8isbmY`C|a4R?Mv25M$DP6K2gBoR&PVTvGfy6mX1bsdawkW`x+x~JU}AcKa1 zLCa{R!)c^5FL;Ouj=8Ebszo#QAji7jkv&L=!7=emX|W_Go~zy|CSGdXyQ`evdB@v+ z1vHYK8Tb3;X&sJiVvoH{0$__chdnDJl=xqxYRw`gh$?EjCU07SZ`wiZL&{Pvoauuu zJ5+L}2&%NUxn5?AknbKu8vC0GEORUbv5mK=gqgEUY2@9iKN~39esk;|pCA9g1F&wC z@Uv!r{ohh@iQHFRup311;P{#KR21)+hI^0z)$+{dbU6(AK}H;Ik9|&$7sj7~U{FVp zlZ{u20RQpwkWjg_>Ywsu?{mZ5JAVC|{{7UTc{|uUZMdgr4MqV${vUz)@?4jLPVE32 zMNUybqstH&lAc#aBAz2~upbYm96V(_EM2(q7TG3?>0G`j4&k~J5D!;hzs6DE?)vhe zMgPW0M5oN4WY6a@-hBw@ov4G$>u%EV|EbkYz3!;u75EPKIoh1?bJ^|U&-OpHOp1$I zL6fEEL&Ps%LqYEA6icYSM_$cgN@`KjEJSa z(9DfG@~Jf#b!P^0Hb4%XF&~3jr^WeEe66a4zKCgMebm`k!HiOX)@f;2xeCqKTSeFC zse6)la84@DJf~XbZ?&ZnXMq|3n-96UTGVxbUkLbIH}>)exRzjl@zO^W&U5Gtz3rFt zcRAjMtV39UDJq+kTd@~9!7k^t1f@7>BpI;3vWiot?t?!u9g7j&qd9tyPTm4tVqx79 z?>5m+@iO3w)TA)0)HGbcMl#}-$xZRL%p`c9xduOWirf**B_wd#atL>=nz-j5RP(|Nc&tDE7b~U%NT6j0wx!u|LKDXb> z+*;SD75jFcoYlFVpZOc-wybjZxvjkJ``j*_TOd8Z@OEIsnGxteA?CD=I2l31Wyu$l zZ+N*>Bnnd=M*SKqGY%vWHyw;@&S~tPx2)`BxUmYZFaVxg? zu@*edgoUtR!0E*RVAx{|PBV@qTbaY(1melQrh#w}M(9}@Fe+z089$2iJhGWBm4Q>|HTF6=FTVc6^*TTzL zcBXhyP2DTWVKI}#tjJa7{58%krk4pVE(vQOKya=t$`H@43XE&T(bq_rE~BbPTjP0= z440LSRl3=6))41JN-({sjIRRz;TJ|jE#LtOZU2~2-a2|_mMp9&JAy<-%gyp)A$|Sl z%Ft7XnZVrJOr6Sg)r?c_q{4Jo!!z#_^F0ayRz!^;m`S&~(|&}E>Q)yg&T8*S^60+T z(bqszIsbChBKE0Bc*wjf<&E=B6kI=05Xxd=)XzKwIy`^wZO%Fc8QyQ$0dJu=hdHs} z^V|S$5xI032BFHLWz@XnnhSuo2BRV80(2_yy>M&EB-bCaOnbL4uhNw}JOG|J6(iqC zCLGl2Uf7I{Q9R*~kygN>;Wq0w=MtiOsxyzSW#QOi#3@P2&B6UP?w?mVr_>n(KQ6$U zG1)lm>NN4S0yd^b{w-29y!8<8NCeu85aF~t7^@Z=$VNJ==w**-$-c+QwVS9b9ku8M zBQ+5??FY;|Eo7SbS8Q(Cn)TikUJ17@z>%{m<&7--xH|Rptim4sYEnkKPY~N`j4#Fy z3LD&9BItY_(}~HZZw5Z+Eee)}`K9|k{gw--!qQ0veJGHOf>;aSaDwi}?pKWaNZYbZ z<6U`~alcZ$EK@n_=L@n{8xJUBsmS~eVot*s57KL5087}xgAQz zP~d`iTRU^kyJvRF<_^v`<-F1<*=%Q1BF(8e_&gdLo5U+?gx^&^LshNC%1U`sY3Pa3 zTCl>c{6US(540lcPet6+EFRK)Ji&{fzzHsiiOKYkk&5V!S8C?jA+gS^d6H*e-CgB}kF###?hgF$y_YW#BRgwj$EeH6bx%JY6w9Rm zPb-=!mjnX=`esIEc*kFW#L_iOp}uai*kTKocyzW8qMcwd$s}D^- zCeM``AYPL0QQO2Y$9pr7=2~+ItV!;)@_a9LkKoB)x>{25O8vvbQyxb43yeSG79qx@azP zuFqNH1pG!mI~8=oZp`*`R-#m#CUvjJ7IL@&v%hMekJ13wl)@bbzAmsek6^L}0qB@S z#13aBHhxbg!Jg!%)vge61S*gSF^)O!uz^5l-(aK-=RI3y0WOHmvO7sAr=QvvX@Qu` z8Il8mOlDid+mD}44hz!*zYAsQZ?kw9rUqC!_Pr`WW@l*jWBv^QRTHE*x2vEG^LYFJ*j!>;qbCLwW@zD!;g>0@ z-d-M=q;k>Hmy4@t_lAq(&ymiyv$NgoO}aUQwry-8*m^c!a-mXZ6wWSho?eiQSjo!Q z^++SL%6<|nzYDKIEJ43U&)RFMKy*N@lV)eyG`X(pjiDFCYdYQ0&i3_n5j({Up=gBD zfs}lOLyiT#%>kW78(E-xTID+RlM_JhY=^q9x>NJ!nFUJY-N*hv^;l0-4r4x%W&QmkLJ*F4WT5Gw_n zBB1a=4yxEK^2@O&1k&)ZV#1ZQi|L<=ew+~R@_Hkul56OnY0ZwIc>*sl6(BM!P8Fv! zIpdUsyvqyznQe>)54n@j>L!w;8tGaa)*=KZB3+e)wPjMuRsQ=5c=!8pcgQ{1RUP^` zn+5U>0EBq?Q3rSX^3Chew<or8z4A;q(kP{RZoifUn4mynH2x{G8t_X%|4H#Q4!8=O|rL4{{8JNu^hSUmaMQ(AC7;x{{j<$*KvkRMdg0P zjf(BkHZ4IwW!P3@W?7wmY*U@%k4AsPH*u4IEVZz=Mf8pJsuKSS@A%_WPS#h{E|!bA zE1)ZtGx!^xdk&+65hg8M&z4O55d_21EG+SNR#LOu>697r8B=xTLa5}7HYth9rYnod zrjU^IuxQu)ORjS|7K|WZavjj`E>4f|P4*Jvbym+q*REHTma*%TNb9Ox_ zSpi&)GKXRFkvc)(h|{|JLq!Ck5m~@&3Cy?W_xzk24qm`zzsETMUdBKxK&uR5IipK4jQV57A~Xvd8-fMVF6QJd5c_FY}u z034eQu#a*$L3Cu3P9~xpf$FE~+l9x-{apACRcj&S!O!WIo2h=E9ZsyJm=3tJgXUg? z{~R^kqrDH!&29Pnvf&=L_dgUqhz{en_h<_XWVwkxAweb2#**{5baJATMF(8$j7BKg z7HQu(M^RUe(_FxDDnChMs}?-Kk6>+%-E#yN1^|G=-v=9;kyXP5M*imZ&a8pv!r0hN zj*&g2-m0ZA**6I^Xe!b{H3x}x&aUPVn?|Hn-VEIev00~&WizNp{bM*Aht<+ zt}Abgx^Y5mmSc)de!KE8v3bJZ$B8(K9@w-cYr}LPJSQEj7md{*jo{9vN@ZcT#3X!t zbaaHtBe98T!L4%mPF)-9u5rmPbXQ>?4&tt3cXMNdh`lNjX`ew^U&q((Zl@PtmlKR1 z4+gYr&J~;$cDwYsMPjShog^kM_W^5wK}nXZgF61mAf8|Ye=?4eD;LOO00xd{n1dy$ zsDijTnK`GrgfMBpG139aW#hT~a{HyX^K$ln_NnIo>mH~O;%({KMYWCd!R$UMRM8?i zu_jz4ogg#dO0>>W;|$GC&)fiKEz@R?nH7s;U(zXvmQM2KxJbYNEjJ_%WZ)|zFwoe+ z!t~6ZyH{>eVpoGo_^4C*_*pTc7N23gVBIeRv2yqgqxY{j!^|MSb+8w+->c0KAuPeT zBN5rMfx&o^w8gXw4O=cfnX*AWNTlIv_As*`Q$b=q)rB+>+Lb0z-r0v>2Cby^C+Z=!m&}A zdz!VuNFz^>bIK+NJ{0-w9XJyAXw*JZEhR`GHEp0L@{6nZ*2JT1@O544b8!_^q@A4S`d%I4a=hOy&LW&2=n;txu-fAs_d)OxbjBwmF-ML z^CkFy;(kmL(|i|CflQLI3D4qt;I~7#lN_kgxJGoJp3YI`vnDP!&T+(iR&=F@x{Eq; zWj@c9FKk|F8Wm`fyCc8TO4TSG!nT%`rC%r7PlBQQR{IPhBc*%tv_+?TuZq)RF=FVI zm2M}aaIP0j5xUwA^t4j48{)wn(%3~VD8qT2aw11JJoM>?@}I{d9Q^!3B; z(|pV{^_4LVFF%)$iXvxW-VaJ_MtfkJv$*QZBd!1Z=QgCP+L0|6Iq7F{k1IytR80fY z$CW3|qO$|%#@tH#esKJ*4-Ri2Pg~}1dY>cYZi3181Ls#da301ldqF~1{_Ex3^0g`O zyWy4dc=pnDr_^=XPDOTf-WWbBg*8z&sbvJ9q8yLwnsOI9dY`y1!nWDanvmHy=whuTs%8vbKNx;c$I* zTsD_<=3h59d5}aqUb>(~oPCg;y?kPUj3Un&?Md*41)!^!yop1TD&TST9&o=M<7(*6 zIGEY6l{)$y=U!ry6xp~S*%-UE|W8krvegXo|$Yk@chP&OOHxudE zE16%MWHyY9<~i?jBw9y@@x*;fhtbn8=se~6zXHMGWU-XgJhGZ!gdu3%|H7=lTWz8F zMY?i7E!e)reln}OOytFOV(tn0z2_r*kO1vN{B)Jq%g;sd3P5K` z_ZjRZI`rXqULtFnRd%BfOS+)q!l`jqPmO!qsd1J}&96h(az z@3{>|=5SU7A}^q9?ffYbp$9S2+WCR_O1n{t8(2Or!ic#^{335z#T^WK&+TTXIOxEo zdmMIY^LUsJ3s(m^|!pum)rf>)i;-Ov@x+j0UG zqpdOc?_{8(;x;`|QRXoI3wNiIjDRdA<0Omv5(BnYJ|V7PSA(Y4!OG!L2bgC zcS>{ArMfHwVXMElyMu`WmN5UVm*GTK2kfRtpXSh(knPoHD7Hb2DVDGE$bBAey>B&1 z-(m9$i5F0A?Dq3fXCA=m@SS@|5&*Fjp!?O3jrnKBg*tSf{4I{3xPQwBk-Pgfj+cQ2 zdL@LE0SlZhr|Bq!$6=C9hw&8^!h>!L-s&WyCx(`Xf$qod2NF@kFs4G0e46iGocHau zz+Zr2c$5U)+SPtncjen$Q(W|~wE6nJLV6cX-&-o^)GylZYj|z#_M+b0yWVKHN4?kL zMz`C?*Wui2aQU!zkD3?eTN*@Du=qaE7Gg)J!MLTagUUOA!*>XIahEz7wg$b#_k0?S z*N?A?g@{5IYD$yp?$Twu^_8wDLSN?#X`<z}#NS*ZJ|7VqXR{Ik-WmY2Ys?7L45YGv(3w;U1Pi?|~=X({? zE_oA#a4Vv95asiY{Pf?Gh(y6CLJn>!78-)`R{z0A}?N$rV)phn@@9Hw?!`k zEm?sw`LLi(qQDpMU^JIa<_dhEC58;ZJwTQ2M)a*a_qH>*K*!mD8|lc0xrStO5&Km+ zij8$j?ZDr|)6EP?4}+nX<;_v9ftnl@OxaGskxC+HyokgT-5Tq@qBZa7besg#M7P|^ zw!&NZ>q+2Dk`3lMZHu)LUdid7l2KY`3g>YL7{>7w`KIE|+>p-W5XT{-cyj#yn4|Y6 zNu^9%Q`5}dUMu8<+D-L5^P)bme>%yoyD9#(U@+9x0_++Bm1mOZukNmW;K_p)E3a@K z_L8CoG^7Ism)4MzTBd5A*|f795ddk*6zH2zbHy&=q;rYbg*OljAR_H%GfMi?uj*GGO4l3GFV}GFW}3M@}=b$u8jAdcPywaZ`*xEGVrtQ#ketN zDuJ)=Y(ArXuFU?#V=2+MC0qkX0VDTRb-QbutHxIqv))(4tQyn!5UWAy+q>H{pJq7A zYUcA0DitbJq1EOrkkWTrF|GE4>>}pmWA2W(L5yT`4s)vARY3Y{zEKSI@j>9oC1=(J z93XqTBwNv1Jt0!z`zKJ!3@37&{fQy&5Sz+cG_irGIdh`%#8zZ9qXxr z9j^xC%{ug{v`0TflKla-77r08R*Di zSS`jrpyiW?bkJ!eit3Jl-xL~Dskksj$Spfx-EErO zS#-0DZusYGA+|D_zx_M+Q+r=9`0(uFfq}&${@;xEe zw>!bdQ0pZnZK|cVN|9?R#h+F>^617grIOy|`2I^S?#Fb_W}M{&_}g^Tn~4Q_jf9SS zblf)EV-odWb7@QgXDONL6bQ3z9Dk{xQ|?77oTh=D#r^UXEZ-J&(y`>_X83Ak9*Y>2 zvy@Xg=YiE~I+`H`Ne)g^tX!N_fU;bG+u2|hq5x?Yz3L7$peupLOXC3=yJTwa$Fcu} zPopOtMW5&z>!)=UsWilrmahS;$mb z_G1PtP2IH;=f4)*bGUERtm_SayI*QVgUC6MerCB%e4dUqaAbkCn${mXJ2Nwzi$jw_xbI@_$1`U?p0s!JMe8+aE}q{K~7Qdae#+7aOZf`|($ zE+oNOTR%pR&gj^0ZD)E0ZQY|f{a(GkwcO(ZfRIG0c4gLPm8A#-JUl$ymoHz}Z%M^u zIv53Ca>(Ln1Emd?xl4lzn(^OWis@ZU^R6l=v-@0QYsv+WOHpfE_Dba7nVw=F#Uujb zV{e+lf7;D&8)J^5S>hfO2~OaW08DJs8_L(Z)j>oOCg+&v?5Pj$(;jgr2-o@b3qI{bJ5OusrQ`1>D(>I|8AOfTgR_$=R%zGU( z!Lg%`j;CW~tnoDUbwmXtTd;)($nSMc9CX#Un@@%`^PG>w*hVQpFZjSA6_lO}zxYr3 z4*L;GBttX%`ln`6vRh>y&y}DAGP8_}JvcV~lwncnt)R@JR8a+3Y^tqzZXW`J zkz|=m6NTXYnoS%tG42&R z5y6cvHJ9I@9Tw3J130w2)U87GmQl%DG}aZ+^@^ufy|-Z1JNE8zIAv&SeK%EgWgiZu zA#Ffq@TT0tokFT4>z0cT^`$UpF~hcvRK}%XR^XV=;Lh@!v~|p9cOB)!U{6A_9f3VT z<}8#GgLY0o7_G-@P|`@~~3@seub9Nc9C`l!9GPhcxYAUV*Ht|Tk{!9;!&C8}sN4SUztl+P_jqQhkxJ>FauSk{8-6(t8=xl*WG}2rU1j>t(TQ?HwD&mYW zAXzNYhhiMhJC*W)q!`JvmvQjpNEBk*c;n$6r+rAN=D+~VuZ1eAu}wo?>aU<0MY{x` zacdoiob5etvTyWDlKHqOroX&=d3$^7)jvSMe7Ry#NirWQM304u1TxX9(b?Y)Bz=$A zGTP{0Joih8f|9$p`11o-zdJx(0$PJEU}pNC`bS{0?#7O{xjlcJn(}mLvtLiZ6(;uU zWmC-EvJ6~Rnff7Ftj0&fpk&4!cKfxay>S14vz*bvk)ewG8`P&+u(uz+Jp6nJ{~#B8 zYuxyd{z;|skGaI3vDPHn}km!NatJv3ER|GSs|tu z{=KYgw6PC0VF{iULv&&b6o-+LS$Jtw!IQf>Qp&)5 zwzG2D|5zKL9X934-ZVApN;4IR%fg*stzseD$9fkk@rT(|5S;ihh@DPBt`cVQgXLgdxt>YjlSWe^5ug-*tZ+8)Tq zI!x(7^8S{aA5SZPFVhH|Y{z@$Zj)BAF{e>%9lComkNdQ@CpaWoL_NBjMk$x>nM96F$Mv%klX(?;V2v6M3q(oNAJs!GQ*Wf776(v{x`Q&HzBfH$`ftUd@OD{vXS0;{emOD* zG3-jz4Qyxt_;H{6YzrWp-d)u}%sZ5xPTRtE1H&DvI*T-+atR!3h$B_WOk1RqXaZ6v z=!(N}M0mHhGST`Pf@5gwT-DEA72Bfxbij6fhRNN%9>~WYTd8k7KYn7#D?9ZfBCMGI z2gC$>|91%r)lH8bHJu{EyDr4DZamBXj{L!OcVlB7kM58fa8YV|s@}jFiSeJ)hHOv^ zzPdE_YieXfq*J2jnZGY6&X@~R@aJg8|Al!It$Ui20TQkBKr zy&+zimbt?@D|GygDhoavy4k>;mjgB*SHi^6!TFx}kmhXWjvWDs|A z-FrJHSMPzK7#u@n)p$xL2nWS+Oij~T!5uZr9)eZr1qa(l3k=O)QaE~%#FRNx_ z-R^bHA9~7FhXABnOe?*_;P^ZOuE_ z+kauRbWyodvQ)TgCs%8;_RzY&G8aX#3In#vpLP40`fk8IaU;$PBb^?_Adg8A;6NRk z#l~AT<#+@xWkm#EPC61`xm`f4)%s8;t zHkMm&nh3iG%nuGlB{21s`=aw!^Bx*Co@kDHvZk-9nke@qoW&>?sq|#4!8^;MluVlf zexD+D>+?{%znS^B)@3>@yRjzWXeOai#MdAi8@Z*f?(DhMXq$!uaZqa~M6p9DbSckH zO+8cjCRNdic2HVXG2d3fjUr8Oq(vTQ>z{*^3?Uld*O7@S5R+e3n{|~Og$Ut84{kL; zRQtF1+Y9sXN#``vfJuOFp-~Uxda&P~tIbe_C12eGTPyG6OFGl57_x)?$FpfEg;f=fT#@n6~ZQ&GcS0Xuh=mi`8 zDBKk;-nB{=qYbTQq#bezYm&zu0u-IZk7w9Tb z)xq`DT*rPr8tDMyzNrdrM_70E5&j!FU5&n2HjCg_I;9E5D4GCuGJm;Pg};?jKw8~8410jd{lc!PY? zi%~zqe_{k7FFp+fSuZ<^=={xG=x3D5825f#_85;cR2OSi9^u}I25s^v-x1-T-_PzBB*3upVLyAA#A+E%$7r@JBP#Y zu4`hgG(I<4S;MvEpyG;jHn!F~>+9<>jFkc5xk^a}8HI6*IKL#lrL(w~=94XN>sAkl z$ev7Kg0B8Bi;*2QA6znj^!kkT1 zMRT)xt5$z%**#`&*ftGLga|kUTya@@&S;cCS6{46%0MFV zFJ>%JnrIx@LB*=0nEtwToS7j*p*A_!jJK9YYgIM`vpXgSklzK2#D^8Eib1BGmZj4S zd)ahK)Y+PX1-YQOO>JydD{zQZS_$6;y^`8U6jmj_GMD4MMNCv{aZYh{j+ewUUmBi~ zzpNJ-E{I{7@zL7Y-7E7nvm`CtcVR>_ZuV$0^GSZy$WwK97EF2v7J>KxjV!^)9c(kG zAd2}K%S{RnN*2IyO~SWz*Q5=k?5jL@iLh6DFA2P5wVvIhy3d@ZAC-;3fFb0KCG@pm zD>m!nrVpVxLu5J9IEJC6F*7h`)#(sBmT04l*d#$6a1um0wMJHyPipkJ63CBzG42%y z0T2N^cK(BjyX~=%vc0vi05B9^mPrxDb>T?^lh9Q6--new=kUF(jHCq<6&98IfJIrj zz>G%%#o&F{U^ke93QOoz=g#JaD{=0!(d%5}+=RwgwWodoG6SOI04y+bj0;s^!_bDu z>LQDVuYg(bf|)C@(oDz7{yr_Es0*+GI*yVOS2Bg@9Q!*bC}d_R9YY;KsG@Y_4p!Cx zW^k~R231+9xr4B*1v1)cBiMO{CaOmqkpxt<88fJ z5BGT0bQ29# z;3m0=eByq9wsdgVz5ICIKvK#j9Ex4ZnaKjuat*34n~V@4ISr>AzvbPkn~vkDaOiUY zV?dn0AIF;Z!JMdLecIUKs zGj|vF&^|7DF&6eI=9p@_7FY50^D6#fRxt|{JSm$<^WJ{ry`JN-Uoays=8VsT!!Vz8 z_loXEF29B(KFe7z5BENrIK#YdAE3P|x(xoZMonI@VkOcAr{*Y_t66Y>($914i>Qw2 z_j&d`>lx)Cj61ep~Ch6yN44}BBYJX7eVhMnj#$^UNuLe8ia@?63RZu*5#MIf zO~pCl2Z7q8{fX-&#s{S8JEx-jiHWGfKpt|o6p2MY*ZDv)3$;Soi2r-I4m1h||Efq- z$_jTaVy4uwo81+(5r`o#B;hkCL7YIZ8M|v$=t76aRd7N}p-19WdC@?2Jois&+Y<%V zcf4rgY$^}~!jzgl{^y>w5lmhHB804^SvU%jTVdz>#iQwoBvK6! zzipzOEn+Wo6jYgm&(mx==E#a>!gJf4{cVjq0Kn|)gftfZTZNcxkfx4oz;rka{SaBG zc6nIl+j#39>p@nsA!6h0+t=Vqd{8hc=0VCZc{4$gIw2vfgwjNF ziLH?iiRfw@MBfjQiP@=)h#!d4yCBQ3fM=dWMbm^^T-jignX~p`@3epQ!kS!_B%?ks zAByJ#QM1%~1o0atQyR;!pU(F_RMWwRi-ve?W63!S>cJeTFfsWwP0%9G{m2x9H?Y_q zsLuBb9e!$}W-3-4dD%7Lfc!d~*iCN^ixC&%9jX}UJ9TC?YlD~Ckrd{X%bfW2YU zf2v8KX0A`2(|KsKZ|ffcXz5tp04=3MKx7Ju{$v(KqL;)7#AwO5X%t%6F^7>c4PmiS zu)#}e6#{h(@ro-L2GK-b_QIUxhrH+}G&!E~z3ZvF_LuTHL=tvh!ul&)l-Q9fX@mB% zz)OmPPa(FUx@+%Gul7D2ygPOGCSj(Yuv0ailk22p?YOVDysdeB)r1)06`-$Q+$8B3 ziS~5}BF30Iu)k#`rx!z+f=Go*$U%VkAVKKjq<$GTk-5)&7dXZpF1?+J7^1?+CLJ+a zfUC1C%_@Tp4vbunDz_--&EyaUC6XN5NJWMit;2oTc(<143x<@?#>WXX0`#ubSSL>p zk5;PM8LiZ{BpM;G3OL?CoU_496k5;V^y#f*WHWT?) z&8&s0B1q3+@^inN{M?%UoQnM1?i4%$pd(NG??HjaFNM-B-i8Zr z>|6lbPYB3&O|zd|qsqv%vw@_7zWkJPt_S~q%gah)%0%m_(S#8#T17F5z8rvMkV+l0 zK{((nF9tdQ5utrzJ2YMn$=c>{(e}V(sT-Dg$7Xfc$%o3#rg0@Ri9()6K{L3jcGDRV zoQKYGRXq%&g-fOav^B$oI|5i@^StT7kO^7YWk?klDto1xP;G)-4h_ zNBbtX%G)b?a41`>N=ucU{*`3iA?=AT!ohSD6i;{~i0G1Fftcxyh4o(^Y+?A)WBE zM)tJHP;;u#84%hiFKC0rI_nO&pwFuM!aaj{BW3ejtB zGg;7C_=~&o=FKM132=ie*fBh3kDvR@FLQ|%LaGl<{`w}JN%LS7d+tGmJZvMb?iD1Q zxtp)n*O`{wpANVmx&Bil_eYYwOr{r3aJB`((%CIiK;?5{p$*(YAS%b-OL!jV3?uM# zKr;`0CQ5IUyiPGxVJ6V^0!5!Of;$_Bkd4aMrs>qp(%T%7Is;nYlz~o+?GDmz6v+tS zhh2r|j$E?$#LzR8RgyAuiM}1s2!l5I-eVVnq(4$o-8Zxdn;RSM+Z}IbJ`fIck2InH zku4!x34^M}z(G4O#-;{cwCwc<-S_es8`B`&<#l(7>25A2#&qXYk`(e5#I#2;bRHr? z2>HMyqm(h7!hxQmijys?(@xxTI5tIzSld7Zs1Wg_9#4UxCR`pM&jq1|T}p*1q|k9t zUqtyJCV2lF$B*%rmqi*^3F+-ODpWpsJVKTqsaV~B3vVw2$3iY(M%&>^P|WS*(@p&2 zXa3P(i&Tvb z50f}J<7To$kdJq_$B~3&>$kxJcY->8BvGf+ zaT5Tw%*TV7+!)633~2cU3F5U6?Fcb)L2mj6#D8B6SY5o-L7D`q>5b*@lL*$5S>txP z5=_F$*jx&(RpZBZX+XlToC)wtp{ytzoBHv}V1q6iR;*|0_~TN?V<~~{Fq>>Y+IYL* zXFX^gq8(1e?;2At-`iUA##+v{;3H@jjNo5 z4wQSMdD;>~*OuaQ%j7d0_5(VCN#16rzR5In(Qng$8K{(8wC|^AR|J{j(N62R%57BrpMyNO}n6s8yc?*g0ihbeKwYhFFO12<0p~Zi|JB zFotKiMw_&9W`&GlEyZ)gmjSO~Xg8ZLZ?;~nd?9!3>a6eFY`mzdqL@?}9u3T52-PB1 zG@BMFThV4N*FNpu60Np?I~=wMBi1I6pfYZUW(~|`I?Qg;h!k?ItvAC){#cpPVeO*I zbnF0!#ApU~8jHsK+j-&LS8%B^*wvj@&Ma_0Nb$Kb2`LHSz3HIKwd2@+n(1`tU*DlB z5u!8bSFL81#if+naC8)4>m+RGY`Nf<0)rvib!y= z*vPN6>Jq=qfzZ6sVy$e>0)u$c!gD+d%^9MpAzm|PZczn{3z3PEm?quEC8M5vrLNEf z@4`jeQE{bb_Ee)>q>6@a-*b-=618(u?NHu2%k^T*LsI*>jxG`PJNga&pBy%o#io$a z&Q!^D+6OvW(jX0hv0?)82J~&Q4T|GdP0DDv*y3FpjaYyn2ERMzFN=*XR2jjE*eBrz zL!Q$2cB>!8r5e6?%d0k@dDSzodgfKnyy{=itHOKYOs~CH?#@C*B+$&s8SO^K43MCO zm=;VzlTE$9%8es^i6PD0xukiup8)*4&L8fl249`I*d7?;` z$tUNnE~Cn^S4|JbzRmSmIqUl^1ANVTNqY0ts@<|kf)@+ZDrPh9+Ub~#Z6IlAfx&2v z)(#H(=P%mpCiu2IG1aYXGnB?FUi?4HFhO-CAZM-p9bb9_QnjM4;mV*;6I87Vw%C6N zCy^?1ca8S5zGF&mP>QsF(qwgqTnnX(RVUr7%XV9tsaJ27D6_cbSjwl=2Zb1WrH7Rf z_TSP0(mhT4Uuu|lR6I#teV-B+zn*GT)*QJh>e&uw2vb7RV0f<){^4>A2~5CR1p&MO ziJFQ@s2G>=Ac1-HW@?fbZxvU-NwN~r8So*f3>xz)PTMA68&Unh%RO;@q$=K%_)dkO zEHhayAoDL1((hRt*+fj-_Ui?l663lTx01XFg2gzBGB>qQ z^BUATCw-w&8`t*F%1HijSGQwZUyVh`C>@R1(Nv^P!zjlo6g08yK4#mU@{2mH-Z%9| z-8Hrril{o#vq6fIRsw}!g!>sDw(1!Bf?ORH18B-U_Yb7xq7Nrp?|S?+;M;myDpjzW z{PpL_|1X<->(6kin41L@gF1k>eZGd$KI1_kn4}|)BNGw? z(U#7?kVZBqqIqsJUczY|$HO#=1Qp1-EPipE|0|1pueSLQC!F~RxF3(QDWVxuk_Cti z6OQOZ<*P|v3ND}PQ-gdOp;T#EI056g1a1J_PGl%&ei|W~o<4E6LFsDh3UF4Ynj!vV zt^oKW!if~$VGP?y6ac>n_2|bW(Ys+4i|t;gq&G|u26HhRJ zcrpx0HHaq(y+VBBCIH$=A~#9L<sBV7I*IS zHsG{=ekQ4MS&S#-`tP(TY6BBOe>XR`?Wdhr7zcgYdSkEcY;4LWc&qbqIdt;~aq{p> zx-yHXQcM3J2f1{)@htJ3Liuh11*U)@3CSKsS|TC|9Hpd7+ym|^c^=BdOfD+)&_5Wn zQ%)JLM3~ME27l`l&q(o~ibHp{3SDh4ORyrB>0kg#+Ex6$$0_PVb=N4Wn$pAEi-=S% zch|?4UNXCzuM2zbxu@eq70pY^f3K5!*pq_mxUNcq7RQ-N{_(%2v?nhBc^bI8Q~uin zUS%^I;M$5 z=z%Kl41Cp%9=j)Fbsw7VGX!nyjm9d})3lVBf-{w6Gvd;p(-{pa?&YJfRkMBKzSoFf z01um(Prd1QM#H{QUJ{vxbXq7n@6UBUF+n2sQojH{-HmhnZPmn;Ruk>MQ^bUIRA0ED z=bD%Yw#OaOiAF@ZtNCxQAfA(#Ex>qcbXg9tK+|#7OZ}lYFg26wnZ-J~S2{aahFC5Y z>R$9?RAA=s7;?rG)dzQAjUbEjHUU+wq8Wf8Cnhu_!X9~7>H&bpcC)lQmd~w%!=~A} ze?qFu7|rm#M|+sg@cMl&5ea&M&I{8k*_IQN)#Il{;qI%9$T4nQIY()d z%*5L=X8C&^Pu*QwnRwcpf|$KQ?AK4bO0&UrnkC2pPa^pGcMCnzy+j4dn-pU&*Ve?E zK`J=R^mNLY`|_bR{HGph5|zL7RC^#I-`@FMLHX59j~(wcOx;cIt^0b%+gJ!!-KWQt zQ$AYv7~CFvSI%PVRKgL>ov?H_tzq>=WwoIATzJ=%2yE%a$kA}Bh=8Bt;%7u97HVo> zNh}hZ?b>q>@HA6e$7U*_$W-P?hCLiwXu{bdnH>P2bnRyoBhR6zt@4JFu_>KSBZPP^ z6f&e1aR-p4V}wQtj6cpwoG~4j1OkLl;!tro;M>G13lbc%^%(@Us&ruoWCACxlqMiI z?9l=8>I72~t5Je7K|D7Mb)y&rXKp^F*gS{9n>j@%c3pnXc!EVLwlSl~%tA?mg*o@! zeJvS=7?pM^95n-V$Gw?c$e)8Up8i}%(U{*P^2Uq>;)>Hu*5{xd>k)#(43Vt{z)Q0K z>yg>CO~(wI-E~;#PBT-iJq#=njPqZ$oBZmnJZsx$mp!+Lv2+pnN-QVxM(NGtnZ|VL zZj&Ogwe4-LZ!JdW7|jP;?Sfd9#iwhA=qzusDn1rS83zY|VTd0eT{E3-Z(-=(*53eB zy8d=!XA!5=K5FUMA-~L<$gay=VyUK$JKR=%T9eW7+s1~CXn#VC(6k%^ijnn@^>qY< zZ!N*tVdjg%x(I65*6ZOOTztaal?TMWSt^lvX6GBeEx4o;c#I?aT-2;F>xVLs#_hr) zDeJ4Y8DHTnAcpl3u#?uJ?b+=<}5YRMyfQ3JHe9{oGN+#r`na16V4~UYcYBhTt`&i6*Haw5ADVKNPrka}JxAemoC09hhxb z&-nK9jQ^8o98c)-v+S&Id9M~QBh4Fh4+JS;G#4lQ*hzQIq&ttFbr-X4801%{-C{wH zN@Bx5Xzp?d+z&H}KK~pnr&+iA?>o5}=bWkP%P!f3UG}n5S*g?cQxuX;XtA=)h!`yAY1&`DwCb=;w z$W9*Nn!tL(D>2nosVtriE)a9Mcg|`cNJ2m$f!fcyc1X&eegD>kp|%74LzBg%BSKY2 zGJ??u7mg%-daS0?nPaPh(V$mjM@H^nqA)7cCzK4zXn5P4{j)uv1Al-~hj3Pt=x|Kz!AK(+k|X1^WR z{2+C576UK;#6gby7yrjG-8KfUk6JX|n> z;_3h-WxQCkg(C2}ddQd_;snbcGOZp`W1^VacSbGX0|!lEYH}F5l`Ba%f2wwT!x76EZ%<)|;(?p9{54+^xxJ(!l-4Q-FAu3a%z}T;IitEdbZUQZ zb;SZ4nK?10xz@a_A{_>1buUq7LAkp=*IQ6OB+jTNp(>I?2x$SK;hB)03F#|@MA~sV zm72bP>wo@`ZNGANUU~E38oF>lP2C{w${Xynv{Mt(KFbnPYcsFTqN?{MS{Q-^lF(Gl zq;AVbw<1JI<(zJ;;6ias5lurO5o*{%h?F~Rg-u2SQ-R6Ph*FX;Ypb$@Op93O)^>}( zOgUnSXP~siLd#Yp5LhVMXjXd@40X044CI&<(*y=plYaGJdbKny9Ci((9+bqD@FBo- zh@_ zkZ914%6u|&cXR$b=vlye66T*2-k&wB`v7QR7kp>LqjKwt%)p~$uU_)nVIU3WG8W5Sr4I~H=EGz*% zA~Imfj2sfI3d6t9MMfjfhO}X)^m!Eqp*VWe=_Jf1$iA57J$k`LJ#YA-qtyL4QDd&V z7RZHFeZEsk-rd((!v0vAO+DfK5c$Af>Tu#^x5c=tkZn`fnff)&$E9*V-6Pd~x4aLf zu+x*+3~6Wim=38|$Pw6r2Xju4-8yuyIN#z*C-A2?!KhS{q)DH9U>%9t7TmUwwj*jQ zTi0q6;t#6R(F)W>f~emp`QGj$F94;<)!#XDy9)W@&L3XpL?yklh<(~0-u3j+^HZo% zZp*UmECG*c))qg}iDul-D`m>63pxxJs3CrE6H3M$EAB@EvuUUD3eQ<%l@LUQ^rKJ% zIN=3A_PJY3%*awd8a6itfEqf^!Jq%!agV~`P)8m2IE9nlq^13;Zn&mK6Zq2(2-;d; zQqOMa5O+*5P>Jrti53}KvB3tVX+LTV7>+2u#f&Kb<}o`L3JD7xVj+W+{_F*+LmM=s zk7w#i|JDJlyN0h-`acWv=}QAAhR+=al@V}EYLmeY-!bL8I#`-0HT6w6TL<6}G0|4m zWgtxw6$*8?GP$h17P7x}(i_Y7ni0IGMiL=Zh3n8f_^Er5(u5WN$N!UfObK) zqQN%2EmVeBpSPA?)lh3J^;{ryi_zqoKoehS)x;LUamrh9YTHDdmzrd!* zMBX#vnn0B9_Yd7@3b%DM%}{IX;L}CF?iy8^oca{6yuGv#jp{6TSsJyz&#%tDM^;zO9wbmv`uLX! zqL>8(kC}5phmG|uZ)0Ac`D}RiF)}^(ZF8ICz;xTjHd{UsoG99$j6t&}5YZ}|PMC#m zKSNH{?sbm8=6t+2$EO}r_cP>o2Ee{?cZd4=`iIStRCIoDck&K6kT&Mb$o~ji(tUtp zqo_9O)aW2iR&rPefQ-<;OiG92Le$p_to|2lXj`j(`6@Mw*B#B(s>cicaaPP=%{9x7 z*f^ZuAD6Y&TxD4nP;Czz#a@eVJmntbE{2)f(w#wF0;|Dg<~--9PD>MrjLLkR78X~t z>WXB4=*KMLG$)sR({|x8O{>agW~lsP192DcelmmN>eCMqepO%k4@l|@>l{@tV>r`b zCOrasKuSbP=tC7u^sgj-tcx)gKCjO2Yjv{7C2{X9#J>3@*{dxgR|esfWwk@t0a(@f zba_^(cj!snh#~~_J zvB@yp+uPnkLE*#(G<`OCQtbof;B()W0V6u@Y6)`UuvOAa*Dm!<$ll5W6TmDtzi0-- za%^q|uO`u8%@UflVJ;5Ny7VM2KC4;dU1P=fMdPv9uiOU1X<**30kE!%fLXg)$;|-% zV;wFvr%I=F$i(OVG;hbGa}BY&&!4%-U#>ZVd0D40Lzzywijr$>ahC>RRXxG73Jt@z9hl6gh2e0&jA8J`B`KaslVZra z@jP1uREkyyA;J&Js1VD)mb^|gA?_^#$$wTwY5)U&ZoI$UKJ~mmn#^WdnRmljO#>pf zEu=PVFV=I}OWf1*y$j~F7auR&bEK2?nV~ihQ}iVbzpAZ##H;hf)^!7`!@xaISpvJI zdrs;l&gX=MSSb0ss4UR6z}P*-6}vq@eqxp>PeZP9geP&`$BozP3)66FvAHUwZF%MX zUjNM9yEttM&_;)7H(0=aHegidWMcy4Qz|Fvz-fX#mk8M?45YUd5& z@@+Nd+cWqd?y3oW`g~S#iqEt9BWKkoMjZz`tLC*q(}I&z>wuSg=jVqzZWSE$)hVuF z>C9BEnsKK+v)xbwT5aWQ_ZnD4n6Ym;@Sp@(qZpp*e;PscNXKQ!H6XCBX!{zE4{ zB*~+AG+#M9Jvr)MJ#&`tob^$jt7-VSDL?7=F^SLf{oV8Zb>8wk>pybVrxCnMkDBg_ zv%S*~&$InKvyFc+{Gc`COHyWK&RQ=zuh~I!7Zjop_`82Ex$I!0Dp+IXfC6eJ)0!3$ zsD#RC0PJtfs0r-2*gJ2P!2B0aVW1Kk*#^zo##?t|^Yxb>i&3gq_X(kY=}} zrYkOBl%sAEhyekL$;@Nhx`86L@r7Zdn8br=FYJ1gLJ19fcSU!FNf6a{Ay=Ak8kH|G zdLLGBnIYNWtBl~sM0oRW=knX(-PG)tHnPc>XqYiVV!4v{Lgck4>3_ie$+;hF^=-2s z1ICg?-96Cg&u)LBZ^DVYJE3dMF7`~ogoOR4j8pY!%TAy&w&=WaH`l$Lxt-s@tGFbI z4+804J&hINX71V{f{g{!LccJjbPQf^v-lZD8^ebdP+k^BzDRuiiz7KuwrmRhbaA+szo=_tvMpHB!LaUJsU;5C>TC*Y zrbCA#P0_hL@s^Fh#EuY!ZTUDVPPr1u2OeL&)K@V!0I;EEjSF9Z$cL||5TVY?EHgh} z&~w8nE%q%Pf;K`nQFKETDSvDroeH9=TlWOvcSX^Nc-p5{PooCG?sm~;&ogH&_uo5G6jdx2x9=BnWeFb{fve(}Kh&cBl&Zo8Jk zkhW%{V~`%gY8gzLiUrPQ(E4HSKG1Gu_To5kKN2s=bBlOJ3*%nGvGN2GtLF7iC(m>G zL*{g_LG$)z$K80##jxA*i@|zx5BKX$YjVM@7n<*G%-_;`nvPE?+-YlgaDIgi)Ts7s zJ5{D3d9D;^6O9GI*fKgn;INEZQ7LExghU>3MuVg$Jznq|kTQn3;{wwQS@wtBeWHqU zQy>nX+h;TX%+q3v$PGY6<{(xEi^08BvxPZezOAAOB&{^5P`W(xOiW#bS01D&e>{h9 z%W2%slnxaHMs!JH43n-w%QbC0caKCe0dQ#!4q8hY5;KEhpH6W=E5npgZbEm9w2SfB zdyv6~%{HV(*HC^e&{vbM4`vRcF-SSWJLYb?Y>jJ6X1i-vDjlU#AzSip8e?=YMtOr( z0J0yW@Fry3$$$u>bazv_@VCFIRS7Xh0N4kJA5y?}r-NRi?@EABR=9zCNK?+?RE=_m z7gT(~S3Ry2P$yQsXOIJ$gLfpZb1VtzDA{-ct#B{WcfgS}z0tR5p-l}CsYw&F3RCZn zWGU5%o9JsIg%6=W;nC;xZGKSi)J^KU7urCcF(T)})83JA6S^0O;{hTh|LskJMmJUr zx};|@2xxqbav7>e$Fx885j8`^7!MOcYYNQXZHVmnC|obf8PJk z`~Tl~|JyMA2hRVc0Qumzl!9~vvf#+OXTrk?2Y4td@o|Asq+1osqBFQieC zO7&)LbDZPXeX{`;^eO&zu<+|M**=r)Kbvf)4Cg|G`)12qcQ-fY1s;KWSwfuFJ^Rq_ z&&2yoy#H+C{d=(mmb>Y0yxQ?z&v{V)^J?oQqG}!_-G>`I)9y3v{uj`0B~U*=!OJD; zuhRAR-u6uG&(!|Urgjv?t^5shp&Gw!Y;+}fmov0kAzVV$tp8O(6AWcxDyJY0!$kkO zzeNJJKhU<8l@8zxNOQr#4o&uXu7UDd)FEVm;5BjS2A%@|8m8u!6vg`Od8a(@lz-w* z=}NJoZEwfhTz6l;_O{>518GR$?^zxAi*0g_`heIw%L174-$#Jcl9*-Ak6AMGX87Y{ z=hDw;g*Uuyt~oWAp>at+9fqS2vE3Krlxt7{$-L$6U7!~IZ&QQf0KWu-yTQDdKiVnnk%N=GIRQe3xy=?>}TtEq!qI30lCnchz? z?1&5wN&+-(6ENASx>4>IZ5;}93rf(4{Ss$Uh?YuFX{r}>=tkyECbO!{X%^k%FM^#i zk1Ai`NO4u7#?Ez!8i)|U)PBz052pv4RYFmHj zXF0gJsZ(JpugPzR?+z|H?#0CgzaAIwSXnzhc0bb)COBVrZ^L+6CX?mos%s8b6tCDX zQN~z`R}Ao(3phV|(*?BO82x1P)y^WY;h;nvVtKohOijle`~L|5PRk;74-XHeCL3;A zV^pidFrP+hR`vCws*E$V*kUK2PEFvu1335YBtg}5+fVME5L*Yi9Pa<-2~<{IWTh`# z(u6HkfY6-o<%}>^Ngv6%273cm9Cb!4n5MnmJS-4MWEYUg70mGY$HPx&d)>{Bd;Ib8 z>T>Tx$K5;JGqnkB=%h5DJQYx|02N12S5^hOBPB}Zbl#$fF&*jrw--)HOv=5Y><;n@ z#QQMKK%UAyD|Io^V@3OTH{#EWH$0jYXafC`a{#yhw(hM1+}qok*WEDv2kCT%O=@_; z1<$;I+MK@p=pJQR4N@Hhe>44#bu`T-dlIoRTvQ^;xw7pqsL7K_eTOmEB1Gatz*9`W zIEA=Se0nYtrqUZme6Nb(rir#VM3rCVQxe{pLymK={AmXXS*C7a;NAks=O;BFBK!%l zGk~m~@$fZ<-*M}K2dU;FwJR3$eMxNPgk)Jd0^Qw_d=Mnrr!0xSRwSX}z^ARbLu$tQ zoc;aSM)5Esx->YdSEzO0FGJ42NouS+E=pNx)7R>R`ZnpA&2CUbjL*WNS?bYqiTjci zRA$pu#49>Ms)S*auGWSeWAG}jNamp;!7Sy2CZzMoKAmO>Fvk`!Tm?6Zge#jkV+Qhz z<7^1J+>oSto4~}ygXmBo?SP1{LbbC!*RRA$lOgB-*z#kySqMKI*Gd~2^f_BSnjdC+ zX+R+g@FDQ88t%AeEdrF4vVG%W(tTCCsDe^t!kxKefQw57YM}Z_LRTfRqJtPkZU-_> z6z1flO`FffHL$VH41`7;5}Yh669cb~bD6rpE-=S1p7+9K7vju5l(YVDG?yk_*}gdL zwUt|BM)vGdA_-B~C}ebMBN0q8!EN1@Dz(u}IJ#^2KMj3JQEn!(DrdR{Ju8wYFIT(dToHtz#yb|H6}LC#9xao1TJS zoLqJ@eUEb;-Ku`Y8ZV0{UnOYSsGy3;gdUBHwZAi*IMUc@ydOvI*z zSpQl!>b{BwVdnPfS>uj-x_^$$)TyLIlb()L@UiT%r`(h&)b;Zm~ ziDY3;5H!aKkW!D*_D=PVb#gRsP?m}-YaH%bwJWP!dVie#<9`Pn({3E)KR`yvCj*sr zu^bv%jhkEE+s!3#*wW55?fBIA@bUbpA-&srE2in5wB&=nMh2lZij%OazC!CpJ0Y?e zptUaOx%+Q!v}UR-A^4d&ji?ksJq%A|FaVvOugL?Y;Gy^-1rTDDOHCkdYS>>>v2U#y<9G|DiTeo&-Wz7k>WI!nkPXHBj3ba>jf%|Lr;}#>JuX<$qj6H zz4*uf9ue=$B4p%dK{@G7xS{Mb` zGC#Fm&|2ENT^u$)c~0xs8x@6Y$tsxHRkAe6Xxym;{WA~*QJihPf`q=wI{h_!`J)&1 zh7Z(r*m{?6A>+d%G436jwcvak{OHhhb8Jm-T`BAhALT( z&d=PNP@|&k+DS3N_stjhr7t{#IKi+?e6iSx4FQ%rKTB=BpG>1U;7AzGg%|@+LFiJ; zc4}ATv^Xx_;cy|9Hgeft zK?*;t3&fTf{nj?V#Nk3(?>l6+ORw3OJ})$W+NxHb-S1l4<0r1I_weF+-?_TplI8Up z>)Tk~PGf!b{Q9oW3I78xFymS*U*88nE#$`ULbWirJbtKkIY|^3+JqLexuhx!mhN1d zHBBGZ_}8hE(G7*r!cD6;Y!*|Jg4B}Zq|FE%8Nup;(WDQj8PMq6-NJn8ep;0kcSR37V^7m=%y{6vVL2+FR=g3< z_F?n~m27P-)+Xe)F;2EtEpl@w*JmZ_Xn2C~a$<2=f|Kv388w=w9G>Ge=BiVXm9}6J z49M0Hyjvw%g)qgx$4VeHKSrYhYJ?aE1eVJf0v7zU>GUhS`!b!meUh*8K}jmfIVpWu z^xZ6-^l`VaYIOU-Fu4O@VHjim_X;}rysn@h3WjTR}dMP1U7LbIh{i|)@O(ok;I>}T=G z;vSO_Ouv#uMognZ607NF#8qqRT4WV^jAKkOY(8Z>s(E5XGaYL#MGg(gk_p%l2nWWV zf$=T}k2kQ@O#Q1HcM(K%Y2?V<$wBmRA&jho_M1~G6Zd7AXD@S-1NBS#?WL`C^s+HJ zC(|R669td5N%Gb`(t6^fC{S8FTwcAhan(%mtHTmF09^K(zre*>;|#_gZBo?_M9poQGp^mg7X*$z!n>FPGE%>c z^~Yg`5VCXCaqnV;UV7mm#%7cmjlz3+I6ya{`Qp=j6N&6QP)U(-NF%XK`M6*edav%w z6s3zNT$+3=A9^!IVpwYXwEAn2ms#l^;Pho^*uo$87<1FR0kmtY^??oJJWzlR-SzRO z=lk?#9`X4q)S~ zp5S+-na8OfrAjf}`y?K>@_bWtT z_nl5q$1NcCuzQUwy+E-h?5VOg(Q;UH(@qu`Go4b z>^;={@k2y}A`4uv=OwOlos^<{o-!EietKsH+8=|>^~K}glEln@jc}Sm(uYtPSN)jB z4Y(s9x^q7!a$psQCjOezWX0}oq~bSQuOO@V<#^(aC)HAtBummx>Ry(lE`+32^50%K zy}1c7|QaYjC-Jx8m{e==gp84((gYLpL<1euDEAJ2{#Tl`D z{@e2-l}*Gm^ynoS4sk>xDhY?}_A+nHjE+CWHLHa@`VeA?|N8*nZB!!oC^8Ro!r{;w z8tfAw3Coe0R_&}uxzg-q-B@5^jBa|2Fm%(HPF?#6Oup90l~PX?fD@uTNR?#n zwMsS~r=+vGN1ppnnOYlK@y2`YzTNcZOQxTE_$04CA5sAaZuMisofY!*SPy(&x!{>c zd(u42E7hKZrAz<>hcR*)LvZsZnDmP2;TY8;1a1~2+wtFCK@{358Y%L~uO1^l>*PKp z0uQd^b~=JJdG}$IVDR}Yp37LcOyS6M&;1h;%*HU(;CtQX(d#e@C$yP~FM0^H-&&}J zfQ&PVvF9X(O5MYq@99nnIF}Q#9a}GsWR7oYhOuCFsZ$eR;RM06|Bf@3ZjJ=xyI0j??)Hg7wE)%0&r{&CP)+h~d7{Y=#&( z+KGHt(sgqh*JUda1d?#f7f{E*S}RkY!{?+R#}+Rk%XSQVNyfoa{sOlQ2G)pc_@!1&GLV^ zd%-oW#~GY(`JX_e=5A7B@PoCMNf#BDlrUvRFP0RB2r%vc!|l^f%7|cOu+8qcTB!Ug z>Zf$cchTrcew{>`2au#8n=?>f*;w5QHaq+e_hT4ckUmuWiA!vzA(5~$1*S>!2Te2@ zAH@TbMy09d&!A(OiiO4p#54Rr(==%2b|F$`=hUNIo(5G#X#h zP!F?|TL&x&W^{#)_GwO^k|2#Ej%R62&2bpTCumpSMP0`32-oIXKUnP@#uMbsl@aF* z_~t{97Vb!XL!^nVcklq+qs=r;$Nx0S?~<~hGcYY${)cwKl_us`rMnnH{y9gEMs@E6 z_qW=T*6IcX-t54XQ$kFWJm3#DxrfYokN0hk>AVDNQZn)i0UVRSG2w#}N51j=RiQDq zJ3gKeeOdz)HFM&sLMQIXJb;TwL{+wv6n_xkpTt>NOH?B`nhR1_QNO4jLR;guE);L_ zX&Q>9C=sQP!%maSLT9#$ zZUPl);?Z2wLyA{bK_*{N0D%aCG)~t9ncPkwO;1NPMeI`}mdh`7NGBp14a}t;cKeM4 z$UG&aHKsE$;5A?OGJj*+eY-s$(y(V(Th|0NR5>n}d#8t0qFPY<>!kDcZz`AN$S})gf$3 zv3W_(AV4`KePaSztXa4n=3;77*eVKDD7GWbOmbqz@)x^?abJapf&R?EgoW7mXPNn` zRfWyALqx3v(pC)Z7Y@VDkYuh_~4f%mldtGq(B1>b4g~uu{t}->@ z04~y2X{xMbtb<6;Rzx@IFuA8aQIgy`h7a=5be7~K;Qbw;Lp$!6xP_9Z(x2*m6Er!<$&2 z^m!c!ZL?_28;MryRF9~VX1n;s=UQV`zB7-WXkUq@Lp@169)?>-AOtRPA&EQ@>y1sT z;+zdg638oC^!|I*;@C7Nlceo7leGE$*efgSeE;Les|#ZT=lQGx5!iy2PhjP%rf>yE z&%-!PdNgoAOz2q-_Ue_BM^kc|Zi3S!|88Qos1}%mZhjI z7q*Mq7=&p<8&@irav?7c>Op68^u0VgeqrtKrf{wY$uT;)rU_0UsJH_JO7>8> zF!#zLhrsNq$Jen;^Iyz-+SSf}cFzl)bV-n-)1F;gjm1x}W& zn$?Nw2U_jK3f2ag*xEHaI>$*frZ23&*YG^;mG|Izh&T z`;fv;v>lN!7p|l|#%g$12JBA==u2;0#)A^F9B}3v7%fH~*o$b(0eOY<)cKmH>TA6y z^SvPS^mG_`{@7aPVuox9^u*oeFCKsCRS{wnn7q3hsR+cwpCm8PN#>^<|7cPO=E(o_ zeD8uM^y1^imi7C7F%J9-QWjMfMh1Mful+KE0UHJ9NC&a3+&n{Ku-YBwwIf+n5d4DO z&}EkZTR^10p;<3lYV*Wt`-yquiL@sI66Eij6eHgN{SjSZJ_0vj(aIHDQww z(J{<80Se*9%nOH=(-NNRuz*Sf`mnEr^jkltCi*@)zDv(rrir64cN94>lV zgjMOlPhYy#MzNps2eU5he29ISYPcPVe56xJ2TT1}s2=R@99my`velb0P)u(n=yQ z9kWExj_)x_F{sFPiVmgg)59}+bURhiJ>+5~9N6ebiq4%uMyD&nEB-1Xiej!wL^pYDb4`nFMw%zA=$+gE!9C?8KTO@liQJQRlT}X z*Vsimve`5+O3H&0)1NZID z%MVvos&BIb?}N+{B`>qky#e>qniO65clcV5wuV3PlIZbdl?{Sc4Z=6xX1iYA_Wa3x zh)|tyfZ#P!xWr#TANNUIniv(xk`{Gt=&Er~R^Kz=dm1K@IAov(x`Tf*s)RvTXasgP zkQQvLC8ArB2`GgYO69hx4jiMpRVEh{Ct(I9k7w(#E?8zNr$o3VGRsySSAr%sg}RyJ zG}@iY1uv5eh&UO94WB1`u=V#wt(fgHD_VEs&KL_w$|F==lvJ%)n{PW1>cxAZR3F|&4`6Ikr}8vml2&j z=PxGqn7y{cGFynL4-@CXAkdq^%gdv^!}BArU-pky`NC8*9g~_}+;b>qc0GxEv3#Q= zByUC+pqgdhA1evkjQK(@kIQW64KtNYjNsNVQdQl?slUA2_q3J}XZoQYu$S0e@XUoC zOjC3kaCLB-!pd1y2}cs>d!hoUdb`(oPgIl<4z=n5@6rgO>K8>KQNd#w^Oc3hk0zbq z&)KaBAAL<4*VfK_tl>fB6UF|zYCziMf=EHDe)#9hFE9Um342EsPxJlvJ+Q{4IcI5a zIP6E{94?i=G(_a7J^mIYLq#rl0uKr?m zO0X4s4{J4?7Oq?i#9?|7ofG;xlJ_0#4F)F+QbGRW->c%owi?w?uwZ$k(L*E&5d7(w z&9M#Xr9(GsBXLT?le>mb=9O83TCwA}(WDo?h2H- z51LxASeNPx-l#Av_}%+lRSOZ8dXK?mao)d8OO6WN{&pE-DVH{ z&MON~7A%aM)y8@o2W$QQW+Oljs{7{6Ywy(@8bH4S_<}CLh@nRu5798mSRJ;*SRRZ7 z#`=#0PJ9iM?Ur^TUTBvXXOASJ*h5{vr$OgvTGAStV@^KAkdM?oHR0`+b2OUq=r+X* z>#NngDaE>UQcV8bt{%e(!X#`Uf?blX45~q^S|M8|J}4NX%E#l8(rX!deemVXwl*o4 zg7RuBKqG!nabOY4K{e5?6siEEP}h~VketJ+|GL7oFeZl)O}X#6ij7TxWk&XR(nN45 z?Su2MJd&2~`<_TzG=J;}PY=5T9gV^=X5glE;K^;wOS}7MfpF>5LsBh*Aky>su@~-I8!*AO*yg%?&umIwe|@()gvJ2WNAXp=)EPf9W2IUya0X2IGY^~74y?F zVpkb76$GR+LUAEZSpM%}e~~i9}Ka?D|B$8yh>`=0f(e z#hgHVKR0G6*@Q(@&PbYMT7A3qq@fA9L=MyqOQ12|xdsd)lY{CW9Cj~1o_EB`K4Xs$ z2_0&xIXdyzy}yFa{tCcb`sIaD{CLm+_GGBXCK*lC5Ja2Li+Y~0dOnrjnDO`Q_QnTcDQ8p;!lQ(;vO12Xik zGRU_`=$8+@XJS`jcN%Bk7ctM?Sx!AUPVZ!+hq1elM%3MP7!TTQk1|?@KFzb5#ZVY`b)NN# z@hr=^+=I<31PK)YOC}PUc)5J+g<3yRtmbuuf$TvlI>nD79LfeY6!KLOlXJ8mxS5%D zZiP;h@W*-E#vvns*{$Z#%8*Gkuy9cv&j(h<7TDa0X`8Q9OrHtT-5m_myY`PyrOzjk z9W4|h=;lRz-zm+gA zk92e(XcbP)+Z^XCyp#2}h9AW{fIp98A3n6V(9Hsk9#7+Ndj z3OE9-StZ2h{JaX&qB7yEl1$UsJyZTTy$$_)cbCL*MJH%)oEBWcYOIGLo6r8~DvY=JvyWdxaPCdp^*I82f-A4@pCd2ojVZ&wkk^L1i%R}!o9 zFDF*XPe*nTGOae>dK>fks)=={(F~?}A&K#8Mf_sHO?PB_tNe6wr_f;Qex^vSb|9u` z8C)ZDy>{nmF|4^XCD(7@|yIyX;GQ{&1D{dakm`q$DPu z=b^hB7uiz-!*n`&7-IWq#S#WOA5cp@)P%1JA-05^*6ks*rf>95S`tc^abTn@n|0Y~f zy6?LzU9EsDEU-y52^n!HPm&9+p)h`O}p0r1(m9z5{Uc3{XGZK4; z#Jg!ZmC#fGw4(JDiN)0JMt84L#$0+Ng@ncYI(*v#e;cu!X$`>0h@_bxw`xtvWy#V# zAh|5|^Iek6lG~s9My=OaU|_3X<1u4@{D4#JlpUZ&?7Us56TIhsgkKK%Yeb7(QWiCl zLw}Y)!$oX@Ng=4XZJL|hOY??YVgLxyT=cb!beH{{rpu!0a_#D>|H6c+Id!^DGyPH$ zC|TM@jT$L%lfs{CAG^kg2BDN%9q1RWhnuXNYGAh3SpXz9psUNytAxmKILSuN?nflZOH6UVS9(FHyQ#hUq`I24Y@iGGmHT?3!0OQ* zvLMApdsQNo4UXJI7hO>>KA7nJs@AIIBuA#xMq%U90I%67m@u(fjYY{Hwe6dQRc8Th z9Yq@Z^U<)3jgWF-K00rrujCbmK?U%O#KL$1kM37BDF<|9!%0T8bbZ|`BVs6?poUh& zgxG=;mEDJEGvW`um>tg(4c~PG;4Z`o0z(W}6~KpH1vU2A6}t&htn5LB)yQZ@g0csz zSs1yumEUE{miTJQJ5zFn0W5%JsVhAvfg_cFc;>6SZQdP+>|GolOX6W=hLLzFhD>c{ z3a9~`OER1ejUW#TV{S<~RK$ix5fgA47{1l1`qDJaU&?g6T(R<~o|dtrYUAzOSKZC^ z^)2@#noY;<|Al0lQO7+yJMfw*1@ALm+|yAW0|_?%+ob;58^z7SRo^af{+cGLK;;#- zz0*7dL^|1^+3ZQ=@His|-}+rAsNC`Bp{7yE%U=(4YcbgLv;yTZw0urmy8{;@3egy` zZ_l6~@2BZRipf?aZXaUGuQGZ-oCam2GCrEpgyZSfOkrd>UVh=EP7*2|zx5o8vW$v9 zFASXOm;?Se4?0jdd82TsT|vI~+UQ)BvJ(IUn7F=-Gwnp#x+0u6HCiPjtDr| z^&|X!sL@qQ6HOep;J=HlXiK?Qq@NB9NNqu%Tdm}EGeJV&Tdqn5$9!L=bSOzSZpaXj zi=FdH&@Xhz31Qb^94mjZcT1CUQy(bTdqB%^cXQxeFLcZPwfz#aAG^DdA$m3tid38+ zOqmt9Yf(60xTV(ge)~e1^@$`-4|#f3Cx;4o)(2xX1+D>|gFt#%80WEuX~<`VN_GFU zl%OtmcWACJ-f@|dtU96_(wTxElD{pPS4ffWg@OTV_ZnZ8w7GyuT;Bj&WA}QREqPc; zHv&Qz>qC1oVsGx&+n!GwCLV-}9kGphu<0I}ronhT8U_aGREhxXXPS2CZk!3G&f>H8 z6bZCApI9rzmqoHTXI5gyssJ)@NGt>50!_@4SvgZ#HnT{%k;dP}M*Bpl!0&TU%5ba` zT@D%Ah_5XpU;rqbX~{&3@OQD%xhe{_gK+j-v1A_{6$QjAQf<}!eHzj6ruoXUl^qT< z+SRls0lNu^SV(~S{%y;xNTf%O95iOYTJKKreM!4R;xu1E!5SxGPL?#Wl}-Oz`arM1HjZ}lrjsyJ?$zGO$9J?8YLt$RNHWU2>*;?~(?MMmL(W2;3i{&F z1Hz5o2<1*Zl>tsB4;#%Hlx-G(#VT)%4?TZI)XFeS6`~ihv}?sFob(Go-*V)&_&I;? z0hZS*Zxkn&$-w}OF!zcmH3dX9AdQt*$k!h6OyW@$M)jYL={?7!Ld7BCIn+Q!q!_m3 zw?Ca|B+n-_R)ks5sXajuDe(p9pFL!@g%`5;_*{Nu_0Y z+g|RI$eed|UQ3l=r~mkW19}aQ`^W#?-f=xp%~)r{-biNY1K39@tJ2qAFew47GOi`DX2v(R{al4a z$L?NI{2%`hqHYD5RQgv+ECB_^qJ1@2_huI=`_6|mW6`k!O+WWU!NiGl9qEx z=U^7#op*2K(t`5%r@xf6Kl-yQMQMtRSfHXdJTwxmlhiAf*@mA^?M6uykQOI7wpF4Q zH|!Vi$Rhuqqx+kA%QuN)-!BM!Rd{=<^1#@Dw%U8W; zVo5B1ouE|MLSKzClw+*|L1?VX3)Z37roXuyjNHJdmnOYs`B*p+49BY!$tsYm)SULF z9pwklcFTycFxd|o5tj7yeKv(<9X$QL<`O@*{?O5JPo9oB`_R^RE$yS0^XX%rLcIQQ zwxYp*jj2d1MFO1n6jKq*J5u830sD~Kv=2GY_MvC{(6fE$**^4aA9}VAJ==$#?L(HG zKHG<$?L+^)>_c20$zAt0UJE+zTvrMqcr*cT<*w# z*jYdqMgy2b330N||j#;_QfJy7VQ`wDve7NdeN?dRYS$A)|jg5r@B9eCqv4|QH%@iu5!vq;z?c$HY zas!w^zR|s0NvjG6u4{Is?r%dxchz{>gPD`&T_5QulJNCqjLbPS14-JN8-Fi3^2;6S z+lJN5R{U_9;|#>=+#F-)>#yWAny;<{K?2|e00(6T9cZAFgbqO(?$biH?xv~`5FvMm z)@P1GpnmiPv1EGUl>ls28+@uP#y=VXXKE@9n;`tW85vtk5S}a)zU-np64x&?B#aU( zLJbw=-bma%HVS$-F~5MRVGJl~4QL=+F|m=UC$D7E0BuPrWb9>W>S~_!V?iQ9ZC`bw^tQ_dAuAf=yp(i8s=>V(w)9d(jdEF< z8ZACd9O?F@{PD(1p2}0&c&<#gnP~H5$CgwB_;fK>>CKGXG+j9&Vouc~U)m3gqso<( zL9fPStG60JImcFxE)9|zC!?AtF7NCm!)AK}Wl^+IN!Q^_R*(&TG}c6Uw)Fft%z?~* z@aI1-nYi1b(@Ol{OU->}i@GxOlxZQe-JC0jHm$+Dqmh_SNP&et)W-W(3BOW=1ayF7 zq08`DB%tKE=b&^a2dBGThW@W=$)bq;Fw_>y56W}nW>Y>;jwL_>`e}v&D5>D>`8Y$^ z_y($I)W3i^Kg?bZ@sb)tWCld{qbKM-?wSQv!6`*lKYrm>RiN!7JrWSQcXr@x9?qSr zG6KIcSZxL~tE4nXF2fT_BtPD-3fAYoa?=;rPR<*6f~^Wl&6HezDD!mA%vo!M3Ue|p zvH1YCxmq`cLlfB;!lFn`1eC7XWFXdVV0erH=-zk}2&P)xTy(kpx?`i5i zF@-m7M_naThzfj0a*P`jyL1!LGpZ;C`>>U{7KH2yx!=wvj)u z!#Im?7a^-5$$_p-H4o64kQaqJFFf1ck4^hFShQG1#8aS={!k#dxabmj379V1gBC>Ji27v*q>M3b9PMODM9 z=!HRoWj?OiYvHiRtL?3D>jGn}zAy?i%X)BAzz3TZp&!95J5^J7W!X`Ey!W5D_lmcp z9Gf5^`ogXtNU=p-c0-DSeEeC!R#wmi#EZO_gn8kO(wnDIfpJr=q=k3vX>NEb58Sj*6qgH4Go&tT`Io4+(;Vq%_VU=LjP8#E#At}8!k{#qlvnmg@C zL{RysFZWOZ*!DG$K{x4ddxaUkd=C|zWf{)tgfS5ShYDq{%$gqC+U&t~?(Ge@){HAz`m=&;)H-(=M$efQ^@D-OzQBJ5a`B?KWfAnI$U1xe1R}=_z?9uoWn|k z2zV*x3ez*RyFFN_l?_ZXbGAym$S`#e3J|HhNXQ{2o zV{U)3nv1&!9~fAwCdDOCy{URCASPbV#voZre)UYr&y@U!q+}Z)^Z-v@6(Dr}l>njd zqHZS4SSuU(V~E@_MDAK54~LHs0C z$L_kf<87|5Z?A8y!>;wld-H03-B>A*Vzc2rz2+6&$6+Z)amfz3`8xDghTfBc@a?+` zd$(@h-6-R}5{5d=Qn!Ef{&as2K_Xdirbr4;y>JlME|D*L{dcE--TShKIy!2MsKZ^x z6zpA3>z0q6H)uw%LciJE@pk4?)*F*B2kqXdO?|xI*TSa$UIGM4YJY<0Dz?|GYHw<9 zVOsj&NX@B2Wt>J4dR7tY;?$tF&qw{e<}J=oH#%3t!A~n@`9z~o)2A89quDqG7@@n% z*SzL6E^Sjrx}?vZ^1Z?1lctA3iR#lE-uAk?z3J`DnO0A^V8D>`XIZk17{}VByQET@ z>_+Jxv#t}?~V6%oj%O#O0;m@ zW2q#-6>g;hDT=rvtjfLAK(zp^v<1$pYbGIjzcM!%fiV3wY{V$BP)Lne`fNMH+?xXE zTv*V+8DKdQbCy~FJg#oY5y&jiTpe7zJiTCjI(ODAuj`-DHCn%m3!vgBi2&>5utn8F zHILU)j8+uz=J2YjwMk&Bv*)G=35V{tYNr1T`$-fsj-OCEao*GoE3-W#gb&~i$YP0! ziyRg#QN_M!@aecLP$V9nGt$>}$6dR7!O*`iM@gBp9*&ytd!6 zy@J2JK^hO#%p+Pr4TcI{;;~z7Sln)*5Ic}g*WWG_qdp9CAKb+~Hsz5yCJdHwckS@_ z>V@Y*$H!M+WP2UJBx@Troi#Ny4AyY|Vb1)+!lY&O55m}B4t1*9Ffch* zs56nibC5+~vNGT|Ah|J2*Yz0GZRi_Xub#$jSPhg!r_QB&Nj*|ZWXzS#0Mtb>^2 zqgJ8Q0hhmPy4DRoptyjjC!Rm27AM3#aa{du{Qb7fvN?ew(VuNk4g;dbY83jFzS;B< zac$^IBPP8DVt%NMT4a?%IykLjuBJKli{lTz0la-tS+{+GYh{UP*nq^XUTKxA4m4Ik zax28O#Qe8M`qNn5)*Dp7zS7+NYf8!hHoLjdYWakPua=#8L3&Uz;zp=3OI4$1$(Cn^5L5wMBe_7GIZ)&-_TK(%{Jl-wBOXj0gv6}_ z$0i`teSD1MnwrofUsmJrSmF!J`t zMr_D&pc=gAIpV1!@@$PkE@@JNObNC{Hs-ee*ev4aHq}j^|Dj7#61ZXMlf3TrczDV$WTBcOh?p zz=R7D0XU%1*CHMjnzzCWw_8^%q#Isut|PUcsDJJC#`-~rzT=IJqt#z0G*XY$Og(DMuqblIWmcn2Q(g&#zo6LjN=M6DFO#Xnz{J`t? zr(L!<6}@a4K2dW{0vu2|X;IsB4iej)FXZy!6SwMik4^d9Ha^6%bI{(yi*cv2k%=j) zLt)tRAT_L~79aW9#`JQ&uvWN4aY>8*{K<+9*a4Zf01 z##kj9%~wHAzfyMUSHMt;(V49m1NwJa$*40=3}N~y14BeF zzA9juCtANx6^1ZXS%tz(y*o8&SA|nyE5-Tp7o)>5jT+5LaZCW$s^SL_C4Nk-D1poK z@9f|-tSM8l3VdWTU#A12Y+B!eMhh`@vpR@hMVRpZgg11mrsXuiTh*Rt*yP~Ha5bBs z6Gmf&y_aYhvY#5F#!pT=2&U?hHA{%KkgM-JQ~Zymc$fr$sIjrWy^w&=ACqAJ36}q6 zw$a)_go;!zDvJa6!D@P?6>xxoRI0X$0iPI)(7y(~Tw1MhRH>26S~BabQ%P$QYx)AT zA$|?kO-KMsVAHdt8#&w%^v@T`cAOxcigum7tVXtz%fWXVDrizv4Ghn9!TC(>+zWNb z`<9qT($m_D1`%R0P51;j&QXpGu-#jlZ~D+H6Mt0uHDRacU=($WVj8je)Kh-^q&yzX zX%!G>XLfx)#Nv5oA2YMX1nLVbF(!-o-{?eD3hwV#g9uHOID!Bi(Hy)JFlpAaojg#P5G7skK!=RZ5OIg*{Eb%IZ^ zdPwftrw^yUtz|D>bQ~EReU|Z6)z9gQxhcoT4_73UtaseEJM3J2`$qC)%z17s`9le~ zw_-+SON+zCTcq~zr@?O>*6B86jpOcIwMj_gnuV50Jm*vhHPRV0x z-41`UyRz;^3U#zRnbO{7%K9dqm!&IosC;DMz%bLuin>i**iA{nQZ_r6cD1ptH*8q) zll7i(HdgMaDn2cmH+ez7Mm`dYTS81?9Ww%z>Cc4rVQ2`j=W$jnL(WrDp^a>sXoelC zJ3;dm4CTFsE%*W}4|w|tzD|4c=V{_fwG0)vl{KA5F?(LqKjNC&K-{JK^ieo{-g3RG zY#{Zu@cBA!1K6>(3XbS6jXV`$SIdzd>zLW>HHUwcjrO!ejIf_MBD~2^AAVc;+gJRi|m%S?rpl8uino4 zWyB0?fFE+`T&x#ZD{X&DqC_2^Y+Bp&DC-?B>N2%%ZtjrSZZ^i61XFq;wwl%ja-oz9 zkYJ;SpNZHN2WN@KW{6BxPe33Xm!-6__aq0*!EHW%?4lT>BwC3Ja zfH+oe7la`sX%swqc1dtoQCYBLzm6cZ&AAi2YGJ(pFdZPOtLBL`c@RDK&S=nkXP>UB z3X|5U^!OfDygLVdx%&(@vYTHI@L{8;!i?)>}ln#J)VFLz_ zvT)+QONWetN#gOOr^o!QwhdimYNAN#zbKO=C0gH|%7xxkEQKe5B1~ z+EsW%XWYF^*a32?B*c7MJF!|=mD`3-;xXD1xYGx_MS^(m)(>AXdSVsY8YmDVXm{zBzaUn z)6Md+^E0j|brZ*D(;7FCk3S=x6im2G{!gnyx)Ia;k=nh#)=@CHhDUK1Dq+$KXx>6k zsj|XvLjXnYo&kjPB-0~0C6Fi)0f=<5u>dUonj&^Mc0Xa;6UUuim-sZ-{t1LQ!d6{> zv;KOM3s}x)6H*Jt%=Jk=LL`4=vU6^IfJ{%`H$&M;?y!fPvPDNC13_+#+iTo@ZUmK(bQ~v1Ti2GqbCPV8G-E zhDZnAC4`aln^fuWqHv4_s|s&`i$wA~f;EmfH}m|$go4=Pq`5Ukf`#~fE9ML?7?3WCygIz#!%2{wmB&BG>a<{*-eOCKg9|O)`<;F@@@}#ZsTkCE$nuitrR$NwFqZe)2;+pU< zt2MUC=5=iK;-iMoJO6p-H+TLI*{xqYrJncf^PYX)v;XQn3#sqJZ|=JH8pcKXXNe|H zzwb4mJUJf~N#YXA(XJ6?+N-(toK$WURHMpDN;1GnesejYIgQfM%=wU>ORA}dA3|%D zy(_xbmrb|)R;32m2V?*qDY9_Nv}k|HIs2L8ntchZK$#bt{`%X-1`UQ==8|x`^J)U4 zv5uV}R8hB_O2(}Lg(}z}JkT&5n>?dMek10hwUdjp7tW&5h+pQ;%s^F&WreJDtOf`w zI;JJRcX#cry&+%j4srRZb{x*h+VHkK;?i4N8{VtA;Df8I)JPB$ci2%v{GhhvG+hIL zoUs@J?YnYs4rwf`@b?~!{j?*iqIkXr0ohb8+<7>#ul zyH$SrbUY&xh`d+_UQu@AQYS<Ipap=52xXyyd;7g;%TLRgo7{$QQ=|Td+Tnld-GW??87)+ zIKlVB!_eJ}Ml^H9I9|4?t5aWO7iHT5^`ZqnieG>Fl!OTCbo$1DMV^m$v05=-M0Pb-SWg2k=Ki6K7jvJ(!p*ao3F`#Az9Zr1? zN=9~qV+J6k&@<@q(=e-5o(e7ar~R-?GhU;DT3w^dOW~jcl+j8_wEqcrLsTNU`2x~B zkxgi0W#DPbAoeK(lEk-gI0Te7B7R=lN|iyGv3tZKuG$CbjeA1$JVM=@-5|Z`vHQvQ zZgqH1@5&faVe}L#CG~UDqyM`*JKn1~2G%b)cl}C0Z&?mLW)E;7kqZJ~ItTK5%zd)j zh+l{G4V)<=T?!($(cvoj8IVChlM-MU^Q#G~CT%AU?`iSV!LZDc4!~iCxk@;*j{6IX zsw)OU3{uHV$+RgE0k|*Pbq~vgH1wC3M|+3oM^&_koM@oPpJckaKuot_-Ioq44fMKQl+2nemWSe^vj==p!5>n z*Az;=uT|;pj_g&>udk|t&m0!3f5c?eRhYkjPKXJ#w9iKM+txFFKX2a6r?hDXc6Lv zz;3F;JX%Gs+^-b9dMvdSn}LqgydeT_Eebgz;)+Gk$fT%fmo6S0wr$yJi$_%EzJG6_ z5oX0rHkEC7+jH_F=Q`z61n)DDN(+0C!BUPt^^cH4Ue+yb&YsWJZzQ+V;2ubve=*L| zawMSR6TDJHTFp?EQQ@wgA!N;!tH69~jG)nlwKXH)z7kDow~D}zG4W5<=ImITa|(MW zA_DErBFcG(3QK6uU+c-tr zxfI`#Vz&b#arjNJMDI^Owz!E%2cjqlGpdUIKrrBE^O?0U<&7L+yScdY+}1>>LAQuc zU|^ZF+vPtfRP!J8WbD#Ef1401`H$~d6SEq2_&j6oJes(`{{w_i$aTO)m%e$e9k*N&Gmg=_p)c>G~ywYsw?k46_{eZ_3#m#NJ z$?1NZ2%elzojtY2y3ciOtmDsL&TR^q!SAxiGJatKxCyfY9!6WwOuSJo@UA7PWQg}S zT{MA6IgQI&ieftA*~p(3Ec4?2W)_N$-v6^80$HZ?%ne*=c|Ihaaz%gx{a)cU0mpb)zh~gzC3-wx}#$9yl8)* zMZ4qj2gGqV|F*vUw~Y5 zLv*vn>JYZu=%mrX(O?qo|I^mVXK}FmyHk>Z%j88PB9He zfEt|Y)uq}azb2cL2QXN0>cZ*f0Yl&bM*rx7JL7GH^(SuvK|7H!c~k4Dr;hx`JO-RrX14Oc^Yy z(b1ORaUhpri|Y(8fxxOmPENMmwPSVn0y!*58_tcnug*p$(XLj`Z0^p;ww{Abr0z_9 zj!ock3=(+Pot7D(u-uFNbK3}{OltIm5ua^NuW%LyYfi!`iW_hgN9>{ZMk$n`x)aa3 z4eVhbzqJC}d61pc#%PX5r0vftPuN#6nosb`hf*J7cLWFTh;+Xs)LvZrPw|zHRHQ~} zSL&W{4T%l+l{a5#>x5g8?o4X|TXzdU9PerxOl!8f=1|~D5qR*9m_dpatL zQRAi&DAfd6lIx*b8H!=-7g?z}>4ps$Ky3*C(QQy$B)177=>RI&uHx^#e4>eyHn72g z`4YLmDr8W=PhenRqTUE%zK4(mkE8 z=x;J%tDn0&#>XJ*ah8!P2W6Jj*bDDf$XJG#$Zv^YX2IVc9S~Lc!v$^qONBaaC^(P5 zJ^gpQafGOyCt+=k5WBVItp+@}vz zA`+yGBM^PTtVtP5s2X6VY0R*(a$=FnBA}}OT1L%AE2S-B z3M5ew9U@%}e|ijhS|UP5KPeRqi|8}p$PR;@Lb2JLUrDhr)6)5-{>`FE+cxs+M%JWJ zg^E>=VxWtQZ}3!8qqU8?PDvCCP;&hp@qBl05Fj^8HhUO=4ldF#OAEO*%;{dhLMfQ{h$3-Su%!0O zoS`X&kA2Y!S!5s%tY9DfD)-fjm5gP(jLYNsz#=6S%4K2+VRdDI@bNX4) z9ofis{0{cYj{B<~4(S+9a^wR@U+2VO=s$m);K7m{wiiVy3PJQ~Gq@*VG@xxmcVCf+ za-4;9Ohp}&V}0&_Kv7MbS}?_~InJm>2M98>T%U<~DInp=INlQ{w69lb^Bp=kNhjJ@ zSpn3nP9ss_gBr)Umn4PA{fmNk;}QXwg4J)=rlR(mo@in-F}>_UxAF$&Ymex_JNS5R z7_&|i;!+1V$P3e%S^a)GP-aCBfc}pKu+Jkx4HUimK^lz=864fv%bufJDUJ>Pt8or- zxu;|V)US%a3oDrcK^3G#?d3ynpwN!bnJ6!x%*A<11oHSnF0dT(xVrm$0FUdN9zABi zDvz+`Zf%ngvZSz(v6?{yIbco^*1*gxcxBU=qZcyWHA55RMd=@I`|i#w1Ry|^HWDn| zgHj~T7G9qD9$ojGHTp!n{+IP&Yw+q#@Oo!B7!0@loi|&r2d{^(w*0rlH~#voS6#aO zg~-lJ2l*Av`{dxjEwqXs9X3pl-`=Wc(AyHn?c0r=#bn?sfgfy)&XpUDZGB}NRjXyK z2%$UM*#UsBSu}pi>pX!F{*`O+nAykSX)MYu=+XmtSu0HO)l+Q~H7t0@K^39nFy1~L zA@u%s%e(ekZdCUI%;hK32C4un)U<<@3 zZ8F8zMWxA`@xgPYG&m-H|Vk4^>sqw zcQFd9y{USG8gO(O-MDK+_b-0T>;3z^*eJYSe5pA@^RGnY?*5FFFGS{@&X;oY{jU-n zwuw8iJv58K;rW7y!?@)Rj@ZZNmdHB+w)3kiwOEIIVQ2W&R5vUG=)7BJh^@GZKHdnr z16O>49j_a~yy=MBQB=LW?bUqZtMf#EZ9OfK^13cLTljj-A1dSB!9kaor)w~LpEOeN z%Wvcs80*KuwZVZ|E*Cw>=bAU#ck)_SIi$%+`3mgf60Bekmrhl*b}(~402=2s@ja$l zn(0@<>&_Q4iU z8r8zF`Yq#|KYZqn8r4!B1_E6JUBEpy49${(%zek5ihVOm(}`o5o>>=jMA22Ozlb@uzvU%60hxhfLEybC_u|+?0Y{ zo9=6Gdzq95`}C%F=N_71jdr>7LtCJr75aH{z*TGOIO{fsrLAgUD>*j-8LJ06_JKCx zdj(f}r*2Z;y@0uqje+j&c-o3pe$oV0$&Y55maOITG!5(2!{yX;x&nuy4M^Ll3;x4# zF1{(jFkj_s|7TAkb^g#4KBO@|hV~wq(ncwh*29Rg&Qq)N0JZ*$rmhQ^jkK-?y6BNh z+#_jH&D_Dq562Jf&1RpbG>1Wim%5z>*n>Ob5@&{v*uIBUjlhDt^Y9wGSppcU(k^yq zb4AWZT1&1uMJ>18EUxoWoxuCFGr+uOyME(0J2UDIzR#c0xbG>0k7Ep#>oe2FO1w*dAEgj1GCuyu{lqREH zw92}VM&}&8lrUmQ>lqH7TE(>qN-;v($saE(BYpq0;20(b1oux_9zh+cjqP~? zJWrDp5@NvHLQH>j-%5`5z&*Tw<T0zPzcC6PdQwN_(ldW=7mOj zIL!16mA}r2l6NC@yVxd--S@PI0*DP0`LNLFeMy__U0zZP`n2%#xs)Aq&vlsRoRJrs zPYX>i=+}KBdu}z54@(*e2>n=_=sL*W=#wlo)12hD&@XTi z-2PY(XzgBOuq>|7a2e*;;wO#g0m6K<;rH$7Y$4|!< z-1-ix!bMeOL}H^;?h+fYK$%QDX)x6pw?Ix}$kdcp9v7O;<^C`?iFPE(USokD_J$hdzXhrW?SKh{xr z$KW{CO(z;@8`Sdv6|=)^qIx^`_0J1>IVCVgM_uwT_g z(TVTV>Br3`%8U71Z$gJHkbAn(wU>vs5?-P>GG?EY&w!R0aQWBSU=eDdftpakCXB*( zTIW47MCSnl66Ga)^Kr2m;t2Ou8HMOe;t6}GpV>`^U9O7KXl;as<1!j#oIy<6C5yv} zUKnC6U+78h)@4qU(vP%X(yOc3i|^Wv|5^gKfm+}5hu*yo?$bnjaqOdKPnodBkGDi) zRSB2WlyI3Jf`}wnnmU(dnyR8*vGr12EBBJtJPR@NSZnhU0hMLkh@`ZU!|wpL10+yt zOCL$3o%Lwr>EdaLK!Gt9zGcmQ?ktAR3=Yac$2Etom}UheImaWd#`M_xDCI5mz;XvBy)toL_W6X=K$pv&c*g!QQ8x-8V@>f{TO@l-r@IrBmz&RP&M z+-kiMAMCzMgHg^DpU~Ga+T}iS0isB8dat|IufBgloNn>L0Kt${bCbF!VfK&zB?|OC ziUXNzqcBr^iFzBwcYqO~eolhuF!d)dp0MamE7Ovdf56HVd|$9^@c1y>&!h&h#N4&G4RQ%I_hkKBHKQ>LoDoD1{yz;fcw?^;m4;nCwv!aQZ;8YjiRakmze ziJEy{EYEUU*dap-GbT>8s&!{3K}>gJSn@ayutL57A28t3tYrX?=IyIj>rRb0_yMu_19%DgVL3u|c_PKva%VZP~XW&v{eouvihQRCDRGb8m7$ohg-fT1qGL?r7 z5H7CLyr1cNHG#~Izde8K*(!%Zz-8nf!4_E1gZOW+Akj20lX;;`RE3Om1+X-((s$GQ zd(sfGFTL)e2L^awl6Js?DSzsvL8!;{V4^_%q`WoYc;6M>tW3B#-a63Ow%#nbP3jcv z4}zp$1-07<;$}$kcKT(T~+U7>5C1JL~${6V{}eB z8XZewb8b830Og?k!jZCpCgZyix@ThfO6bdUsvgD4&pA8WU7My|eDHMi!Xi-6k`uU$jQ*4`}U12R!KZvAmQ36(l0ja9)4#3lS40KfQF z-8>PchNi;m4iA#a1KI=K`d!Kc+CO@jcMLVO?QM8V)SHt^Ki@~Ivvib7$jarX{f>Kf zdiGJ$!v4}fJN@wKH_Ic1-=$SJqL#1&Jjvh-S$LhtJGW%u-2qBI6FGHJ`k@aH#s^-- zzG>ACh>OZ%ckd6@QVOGf>Klr=MKamzh0)cQoKG&R*QmGH2LJ*H;x@3c%X?OB5| zSv!NO0D`*o5-$Z84sP}6phr13@X6{=99hPpAfv1tpbP`)+rTKFml9&QSDjg!CH=q%zu69$aZ zK=nfW3{b^ccTS1H(J|D-HTs_Wo-oz-T{%v=B%S2uWe{lehkKK;zH0>QEdv7I7ZKv9 z8Bcifj&3tTIrfJwM#e`O{C1{Fd@_@B&*1g7<21v9#iWo!nJ^9@vh)v5PwUVwmAyNU6=2*IAKGE{l5`7|A#%UwPTF^Vr|FFR}E%QnDojFwshtn zILGL|?>fiO{?TJh^Fpxvx?B#ZDll6Qx|&4mzp3u*mpu0nvgD z%Vs;aW7cim3;NiXkF8vzhfBdSTRYTc!A2S$dQU~Hmo1pF&j6*L#VIIuSFU-DYrWVX zdwCMp$WtMSbh`U7LV+znp22661@7*YfAB`;LT{W#Rh6$3QoS)-?+{?OJCbib4fwCB zSwKpp(NgaPr}k)94QC zd<+RRZ?MgF5{N>eE!>TCt}@sh(jGI$3A3dQD?RZS=fN_EOXh+b(DMPRnPv=efOD0P z8I$f;)ee=n`IKvKT*Rhw1IHBO`!lirU}8<%a6%2v?i?X^YNah9GPkI{gPFCk zIR;cX&@u>4#S+sR7n4H0iEt>wnhyL`++zSVBi^3=FXNHFR5^9*$h>#{X3+=F9+`ptoHKF{-ynCBQCt!NE6^%;BBpc;Xb)H6b|cuM2ulwy#B^sWgmiA04&M{sLoMhW5=Wt0~q zF;mm1e1LKz)tGY^xB{!GW~ve-35JY?EHPP969M6zZ0SjluuM$|q@opwuFxT~_GE^SGv3Sm?2o zs;x4pn_V;{G$$*Q<&Tz9U8;7rTUic{lUzqb&t=1)Dd#KQGlM9TGDlgOh(zs#MR1c# z!;+)CwFrgUw9#C?p{izG7jUq6VD5=7;8jJ5u43xhJcO6ia_|ygUh?B#!qzVKBd*O% zdb>Be=e7I#y{up_-W-Zd%w^09Q+C#K_aesplS;_Qh)IFc+n8c~7oya0B5o!L$Qz*Q zhsKO27W&jo_6qLUpQ4CE=DrW(fie)*A}*h!^lomvJ7tE-(khvxa@SbhChlHL#8@GN zBh+vYQoG#qUS&~N(68mHZ79)tT15f?{#ONWrAkemV=P+|4kL)Q!8Jse$$zt#Bon znT#9S)BBk&btZR(sE4snn{p(+0EK+m{W6)zaQd1Hz!D2FLl!W1x?*v)xde2W`zd3d zE83lfHlfn|>;p9>9%QCe11u~w&;AlJIybUO6M6c3P3(srSe3-cwcPmEK{!gFS{;mM z2EF?zKmsthmDO2tx{xKecGe8KI4aGCrvG1oHIUvlT=<7bn?24sDR^ff#>l1VkSA~M>`dGpbSWin8iNxGr!;vUY3kee+yfKwWzm{FY8 z6Z_Il7bL!a07Ck)E{ID{_`+u*xe4Txa5_zIZ0bhHg{kvdF*a#8Q%NJjI;DpGe@%UX zbPsiaco=yNMZyHlfSC&`RLRr>hA}p>` z@@uN-7>Mhq-4a*RIr6*xNrSPy4>Ny^9h#V-B7Kr*!hIj9viZ{Q(?O*2CTBRKK`J8m zdl^T`I0x^`6zSULt=>a5ci+z15Md&TklvvX+N?7cYqol(k$ILFqMzYA?bJ}mVYLtF z8gbIZa-R{sFu*Z%Y3O$^V5V>uPAogVBB}3;DDCezL?V3UG#SybOI=L#ARQZ?|0{{) zGz$L^zQMrqC%P~(@BTSNWs!3gSn@sP_#wj$-e0S%kU|5>tj~LJ7h}P(BgqlSC6{bB zCus&?0y^66!_h<=zExEs@M+ST42Ps@YJ@`T2Ld3Rg zW8!|8jWRRS=d1>P{FyqBmOjgV_f>PteGKgSjY$wdDE>$J`GmRqrAOb9+GLJQ`u##_ z!@6-?U2uq}Ijl9E!?=_fZZACWLKV48(q2BerXvt+K{A-k$Vn6fOCX*g&)&<55~WNc z<=@W|%a!a&0aDOKCA?g!0@ZtsIP)2LE=d5FL^N3tns?=$d#NF`>9FGcBx8|ycNtz! znrGf+nAe+ID2-Mltg3Kuk$Bi9S!<=`Fhq$3x=e2)v!gE5fDV>E(MWMeB2)dQfW?5O zVjckDj4nmW9HME)D^Hi=itUZf-s*$3+Jn9-N=jGD$h6FqKa-PBSX`#U5ribtm*g&$ zr3|3~7p9qp1Yjq9RETL#Lw`c^r|Lb^hjrD=CQb{GYG@hy2T4^Xr8>5a8X_zHKg6MidJb%nLf>`62;h&YB* zA(cf+jSC%V5_VA5MxddR)D4IHECq0U4V!T19xu7Z9(~fbc zjZ7LWQqyL2-%!XdkM<7FkD%0IzM!ez3MQm>Z0tEAgN;I)bC~czOdC)WRgImEdC@hv zzEc|uPOjdIT?eJ*Yt$>Fa#x9;q?)D~n?)K~{Z6LYHpI!+OZN%QJuQPiEV_933bL%4ba_6PP0k*E zZq7<81G(K6ue;FR=AfONUR985W)dBPV)UfhVg67iVd@@01)$T;-MuD_G)#MbdiS&p zbDAC>)n^}`K`u@^vUB%`+q1xjP=ZA3@|y|?@EBqehhtP3(NlmdlG?s9s{MDcR5$sG zm3oN4X|sMSea|4=^ECiSM_;XJ>-%;!U^5E!vHn(Uu~RSK~+eHM*V3S zH7aNL0CW>rwy^j)p93>NcUKdGD+(4u%djVTF#Ll!S(ZRWN=6#79spm4MU%IXA~a0P zWZss{lr<{D-}6Fu^PA)moT6VH@!!fY9=Kx#-}v1hiPs^>Y7;@?8ynu+xp@3v)f8qb z?H+~<7K51a{VcuBO&w?k5O_%v+Mn&Fk^cC!lYUJV|;heL( zYicQFS1j!hW^9$*&w%EKvy*E&)%|fwm`5rkkHO&r9^%)TsN_0qH1$Z0nPDFQJ;`on zI?B@tj?FRw2#>-hjB09&p(Xx*BjEf_?i=0yW(EQCZP#3-lA0J1Dr+q4h2n=j zygICt4bRUU18$brK2}p#NgmiSV9ipXM-|SvU}q)&=rQIu`z!f-7f@0`5qR!LR{M-= zo~ER(Db3*l4qn58tTkQ(7;Eiv)Jav}x>gpsy3mErq{{mRM>{+fr8H5#)EFNmDHnR%nL`Z>&FEP_FWi6{n` zLgf?il-pLPwjz#W!K_vg<7FCT;V5;_)0skTB>vVjK>CAP0QroZSoj)zJQBex#b|W8Hm4 zV(FVDF;izp?o~Ok;WI~fMOL!lXh@|Q8ugW?LLgPBQlmbNU4Mp>st?|^y^GTq2Dr?0 zK@*YF7S9E2Iw|3o!{-CXaywYWY=I@I8EY!+74^`x9a`S*opg()sRU6^4VH@Y2-oWP z8_|1&{pU^#5d$!WpD&3&)2opLuA&ZuXEpHv*h12L0L&&}g*eVdMzj(qw$R6^PEO9; zwX5?NZgak9k~p=UCJh6GO%t^jVL>r(ZsWa{PQXfupU#ZWdP*#n1pWwLd;ITQU6uD? zG~)F0_Te6DvRHsk<=u#^KZ>;+^P7&+44$N5 zXLSEug&O#}t}SLwfjWt! zUN{N8Vc04jk&*^Lgd3I9GVcX?0Kv6-%+iw6b8qz3?bzf46&q;1O<$9QgD5fh|He8( zI{2;m)C)7^l@s+O;C}3ts=)g49rIsWV7*g!-kB=|UO#`KI+D94#($OIAIcX;-(at&Mzim`yI8hSsI;-uI5#_wMt)f8O`M$9+$)^3bk7Y$3E+)5XC9 zrzZ)a)$zG{>l-XBHID&jpCG4qy$PQ;!t+M>CvSwRG;5_ZY%eK)^{g}eo9hhVg>O(g z5C)g!0IPke)mWE(T;ph)!lZ{)-0?-zu+jXX9at2nwEM*Irbv{??PF^B3i1H}{SvLR zh;jWY==NVES;XFRV9Br3z8(_;ajKuJ!TsW6|MWLk3QJVX7Iir!oP$_ulGd_~iX5;J zfOJZAj%t8UFdfl^n~i6tePaRe{(0X2N%L+6{^jJpsuK0raI&u2<76*HC5TtmrK|D- zlC@Y$@tek^I+XzM^!NN4mHqp?Zn*I#Vc7bIR<^Rk_t|hLr_#?+io(@Df3=bkcU`|7 zdp0Fuk2^4k`85sSrZNo2TbL$8WS95>vQ6~2$R3vfGoP`A{QHnAn zNiCTkqt%V(2!BLqNU$zr&D+vO5=-bHI4-jBh$2C9{1~oD2$cvWcXJVRD?#bYEJMC~ zDbDQOn7{kIGFNr{kB!ub@*?4qko?`#^1U~T@9MUk;rl^HOidG=@TVT_cdzsVbwdPS z8{u@8x))_Mnb7M{Yh;#Ad#DMZlAi6S*)&XhK^g>k{o3cWxl&TM zGwn|#G5MQqe4NUtP&pFY3`}=-6v?L^YQb>CMmI}U(A@n&K!Pi(f$bIn{`QDw(;}TO zZGDE6_RJKu_9Fh)8zh6G!kmAnCD#!+0f;lZ3^j@}?2d1;x(e1)PMycZ;e>HB49=GOTo5Ti<2(XUdxTRt?(%Ld9 z=OWE$pnCMACV^E#hU*A%-h#6u(gvF;Xxu*WOS+DPM^XS6 z-nBIoGN&d`h)WXl1JqOvAeMxBZko9at4+hg6d`uDir)er2}(!VSqxGwwl9Q8B_#R~ zTOZQ{=={k|l__Uvk12W!owy5qNjPmz#7ES{!Nc#;TapGd&d5ZCVa}AK7X=DCJp>`_ zNcs)x6cK}?gy45yWxx($jd*~V#A@`8eIkctNgYn)veA@DHk%!?z)C?SpQh$C1&x#Z zM`r~QFBEVQ?KDZmb5wfylN=<( zJ#6uH%VW0YYb-wVm}egI%wwK;%oBKw*rOhnV?@sBewAbVj+xB&^O!{@Gx}#SnQD8q zIgL}@G0zVE$b9CT7)?FZF+#gqjOHm^#s!z@GMjO}o6X3ez-ioy(>UMFX%?Q?amF0R z^B891Hkgg``)4)nvK$gznj*pfF=PYh3u(IJ%&~ddr#E6O|vLSbiuXU9=i&07{fP&($UB+ znp3Jz&yT8=kieTdXZhqDxAJrwt5a!PnB1u>x2Xyh=4}j%?MOGGJ)Lvlvrfxw3Ybo| z!_hkduq;CMiSR~u4MSN~suq!5z>}n@3V@v9?hf_!^^eFI!wiY};oIhk%?kU*tnlA$ zuBKJVH8#_Dn-3s3pI^-BB6Zl7sblLicrd;9xTLd8l7w=1jWb70;O;O=rO7m<%d6h_ zD$NA0?1aul;GM!wIMTg)eUp1R@!uzLvUpm*@3QQxf4}#gE3dbFtycwf%!P4ONKVTq z>rvqyc24EkaQ-;c`XDhqPw4keD0m}svR}Kew!Mv=ISJ!~E&!O&k~H9@>F)DEJ{Ku) zLd^{W7vz(~++L|J5;1ez$XV*R=>PyNT>y6gI$Q7^5U^9YtY#bm`QL6Z=C8dnrsbK1!O0%%c zEh@5fAM>^O-Z@?JSZ5L7K+Qmg=4;Q-W~dqcG>2u9PQs8>@K@gED|d5y-q-PgepUiW zO+x++e9`SXkEVlg4radE&lZ@cOjx|N^*EL3*(aG5xC_p7OqwM~8MrZb9uUKW1{5Dx zg@3RLyo{kp9WFiqeMi^`m+KamW8`TBg*`~v@5<2_u;np(X?BV0jFG=u-uY1WYBhzi zoyEl-N1nUO7d*Zo?LGhAk|)5pGa8mc7J%w;s(3lQCT=r%%A%2+2$cbTTapvEytnMH zn$LSY0A{ssZ2_O8FvLZ3X1yyxll~Fii#)!6KkbFAq z%KobJ$%(6spv5!dBj8I^ zqxwK(%E0n$z(`clqyHLVHBorO$w^sBGq#)ZSJXhKug!cPf2>g%fvBHOwSo=+YIO)Z zLH(plnw*(?Lg#7Bh{B|U<4Wa7j$05wk=b*ciG8nZBkuYW4v{|uvvAD4Cee42tF z_)jn7@CVRT9a(d)_`ITNr)lhu({wO<0q7KbFzVX)TXK<@V&10#C}x5`y=yfp4GsSo zjwhfh53;=nU{#tud>6V(>&7RIe-M?rNCAVn?ri`=V{^xQGpFARzuT``_6=uQ8KGuT z*#LLLfjAw3bQ%-~)ejv>i{-C%_q6Xri#c1#n+PrfV*zWypjMT=j<3~78jWOK5X1+C zQ>)CK$_(D6ULr1gG}cuVy!67>6)6YvQy&*vZ}F2;C9_~f^c?`yl5)kNcEsT`@c=g9 zT^%s`5gq1qw$^)iA8B(yhEIK+DI^mTZRb7t(+rLpp>#@7fCmL?G++xWogqnT}xvMg&#e2`$j?573u!~q@h(X3ZwdgvvQO@aikDfOEi_Q>L4PK;M&DEAjQ!Y(nM5sDnE@Wa88AAvvqf&4jJ!bL2aAM zXyT2=3V213Rm}KeT7L6k>`5@439pkwcx9hXGX;MRudN0(%bR@we2^0px(2hlN>gY! z&ZrT9ZW=f@GRV50Rp!MD_mcM5jaD4Qnf1mfsDP){)Xls3*^Z%NkB zbVSm>)E!^!-R0XPiB%MRf^tANse2M;iZtGPcXuRLypg%m4ln$m28!g%7y~43qnf7A zO4U5c=oOd<_4R0br{}lB{@d( z#N`U&$>Yk63=G8Ab2%qRux+5FcmlPHJ2a%%I`O6jf5`jopmD=q`-Vn%ZmdySF3e-@ z<*0ID(izow3hBc*|N8wiV_k2IW|hzETKVa~MWi*@D=oVD*m9daZ2|?Wn+AvA`qzsH zbss|GCPiHUwgn>28|V9+@@RCk%7BGy2UYKE97t?m>;}MgH(PwZFM|o`Ij2eGF=j&* zE1T^bYb1`MKIUr>#RPTm96w^%4srLAqRBX~ZvTAW8rD|E8`EJ#hvEKpneiz{8+mZO z{q}7yFG@Iuy(lcJ^Y9`}3nGN*nuZF6Ur%uXXSFvq{9`ZA)zB8W*;OO{@aD~r0Fi62 zsch*77IxK!u6p?XOxvwtGRa;rrJE`ksmk-RsQY+Q}J#-(WUrrG&ggH*Y@|&db6X)5Pa+Yr@d4;&8_-`!wha2(r=e& zhX^m zE#tajd`sH-sMuOSne|}i6^&Smwq|a6n>eKYAZKh3$D$dbMtWQ(K*}~_IJe2xoORr? z^>Wz_p0pbCk~W55Bb;2Eb>zpNbJw%;Vq|*8_z^400JeEsz}R72beyVF$>^@ouzt?v zadnyE$_*L%t0RrRCGDn}X0{~D>|2eVOLJxBpY;uD=8vHD*7>l6;#c`|+lX!r&#w2w z^CGRgx0McQ_6TFk3+ly>+5gRRVab%NIv0YLJo_C7g1zyFjK4}m+T8Zm-38y=Vp7pO zXENjehK3KzzlhI#uT3IdJdsZg9ps6xnzHY4o!;-wqW{WPMDHM$QwIiBCD(TdeT>th zmR9gm%cpgD%TcjXi{a59B0y&h&x zyMKc}G)?n797q~DVmuOV#diw=5iHX-*tg^8kP8Y__UQuIwm5V{Xth!akWiC%@& z_bx?cX(W)t;WmaJtLWuWgP(%i#`8R4du%Q2Z_I_-obc}tYAs*!qtpQ5;-?-h@6Gz6 zJuw}bLCrbGE36;6t@4RK?fq%uQD?9^))qik^;&;1|wdqI@hcTk? zsXWnoino$Zghz3qK_}OKhUfzURX`;M<1&F0pNrE3N~0W;@#E(tCos%;9>yUGZ4{}K z=i@Ft7-eayj@zPv6yabaTF61{Drr?yydeRDrQU~Wv95S}rZOXf(WU6eX`^OIDx{d_ zh54N=Oj|a7UYOs_!c1w_o|onKxGc}i?Dw`fq_UxG=(e{cDWtY%A)vTc?Z0ZuY6kE% zkS5K_nexch9i&CtoI3ZG)XDVLn(jQT?#y%~QYsSroW8mphWVIuj)akDG*2jtlBd4@ zaxQDw?yEKfx@)=Cjwmu#d|IUr>`lT<0rsXuk?>vB9n;4m>;ah5%l*(Br;{>JA$+UX z)9(rc;NW2z?7LaO$Sd9$AA0_b#6=E0uY5qZW#1p)ssZp<@V6J{xk^01_;Hft#4D4K zl!mMTeo=*OVq%o9Johs~h5-q!_)>AxMz~Q^-OFiCG$}A1t;^b8F4655s4fn87>R$| z%Zf5f>zYM-QJ`W)z4G;5Qu>khOB#%dz4*=yqJ&F3bq{n-JLpmcB<-W@Rz6OryRK;MXbV+gh5KPP;;oX5CfBel4ETZn{Jd&PeAu?l>Z`@JE|(bMsaClfw$cv`E;l<}X3e=ngO#{9Pz483xoJY_~gN^ml| zO;h*sFQ439|2CVIJw;RGO%y5RAe2ef64l(#)L74`VT8Z)(b`{${G2xpHk(VBNxSzY zfeOuAE=l`PgA71NyZ%T%^@gOeC->TuFv+l(yUoV5?k>c%nucjGLjYoqRKi{22L+L@ zrb)Y909QJv$7}J42Jxup=OeGYB^H`RDQWbo)%LRnVh|=nE_n7r?{=$MU+XJ@t)%Pk zAp%NcoA0K98uk)>mwGyHHhI5ybhdwX`r(8ImQ8y3C~U-npn9QXdeg7;rKkM3F@jJR zh}5ugszKbliEh(|W$RozB!^Lu84o zid?_Na(#4pc#3Hsp}ZcdHsw9}<7H)}@8`lw_K9bfcp!Zl^yo!`R^Sz*NnK?rmXJ8i z;=>BSkD~scy1!2mEvEU(GQvE%p!#yH#8%Hzc0phdK4WkB}TB(9=++baDIur{g

G->H=*N{nSONb<>9wS>Pb7C^Rx;G^p5bScS|%;#zCVb z1R&@eLIqe$_dmOEQF%?L{PLBBJbipcdMNF%hYc zj>5P{|4r#j(`7|``y`D5B8(9pWzC9J`+he!pJ<-$ zb=2(c+X6Nh!uV9?6EAP1OnpxR0VDbyg^;^AMQwMYYvZG7!1BZwO=Ltr%U3%0gFEDw zg)QGRp9MS2Kc-oBdtn?L0{`dF96R1tp zOK1jkB?6oi3((iV*C%dx%h5?-J^0d75wU={dDsF3Jwy4y-PnBU*$>S`jjup{ng*Zg zDRfY(Yx+tZ-pJS94J5v-EJjf4ni+4tok9cx_vq)C1j7Lxaq~$V5}G9k z?@ehbn|&hR?sFPNJn8XG+PhaH6%a$20uI5hGpE}f&_Oh2*6W*3J$*MNhU@v%ZQHZ$@c{Ksfuz+jIDJ|EDd&6aBnJ30_sp2f7$0oo?;}2;z2*4hKw>vRlMtVV^ zi9rzGj=4;(ZZ-d+#u4-wT8v&k7&Lz`ig8FZ{)JwwK@f%`NA?*dLB+DbT+G!mH-W}vsS^KbL8(t>V~!t zXT}l}l@IjnJf(KDImYHhK8L^xc13H?42{m5O!b0rQYXSL<|jR{C?A9)_e(IK95hSB z(%!cQ4fUPp9($nI0n|VI5ly-*R72_cfK%yM7c`GVeo0BJVxVRSN@)Z^ry{WsQN<;c z+T>O~^+*K1!QzG)m*1{-;)k^OtESUJ{`THseh*sn`vF;g$21Y54J2_k>}5&hL2WCG z$eWsHFD*E<0K}>WQR?=INfmd*7$7y$g^K6FJ=Sde^;$_6w0Y^M)eL2t<8Ln=$>Qo>^@7C?&aMOrJ&>@(@$V_H|O6ZCOSI9Jus{HeI~w!Do^B(lVvJPr`PJy^p^=KMK7dgmgI#tK-vFlkOK~ zbPv-7algDSEA6L}A1#vRAhS0ydUn83)5x(z^fn!Bq)h56p}=a}{X&xniPGr1S)6aZ zr9LAh{HVs9b7tT{%4QB~=F6wveVP`xdeF$`^HbuyhaSR0Z#Zxx4`{EEUVfW3k^;ZE z(v~zP^#&p@Jrm4|^r~J$SH=q1C`|Wz5G5LR(XZ}5SHBc zw3-2CA;;HV9t^9c{obTU#xf$x!@MEgk_60N(cp8mnDEzL5HFHoSL{Gy!ae!Zs3(7e zv?^U99f{s9r>}D?vwyEA8hB=>c_AXPxgaJ&Hr09YxbOzeL`oDmV)ONGOeB!vkRJ{q z)ZK&)*&o*3OIj#nZOQoKVu80+S(*6pf(iNi3&cZt%C~D+YP6Ct3px{vj;*E10a1 zJw_rkN;d5lg?#GiB1sEPhq&FGS0#^&^xLy?LK-9SWct%OZcUT-Wt!6@GI)1Ll4UUu zQZLOO?B-Jhkv@`u0XPjtPE3y#?Js&4)LELovDv8Wy}09f#&y3g-Af$Um7@$jVDk}i zl#l>13RhUK|EC<&%~ zXth?wQqs-eA4iFso;c(%=_09?#{AaX*l;%%;wKlQz|X0DtDfBakGz%*I6x9JkW7@V z0@UNP_)=>=81sxjEI=Rr8piR=eV^$uTMy~W6HV#SrF_v@6Z=BupAvg$01sdw8 z_PBndUH;qszbpnrDP|X1p2(-(qG4}eMT#UW6@_%#=fvGbF(=8`UMDfIx=wlnt;dfb zeXQ+VNYsA~={&Fe?_uRzNfFaHf0L$`CJroHd`_eut;G|HJ@gtdM z0i*`_e>sdU3w>}Ya4fB(!nhF9-)MM^^lIim6_&3qFbc$TL9eT8VO|CN%Gou%oZ8iwf* zd4ErJAezCNGEvnwM@BE^khUFhHjnE}Zu>yD?VcTX`n2^^?OHTJ@B$2B-(SYS6Lv~xDZ7w-Wbx_Sk73WoZBkvcSV;sr(|PBTg&D907$mQ z4@q-udfYC=Tf2SLQf#Vt_gQ()yj3c8Vz9~R?nhP zNnCpOz-?K0glsg;F-tcLbO#63wDm403|@9dbj&eXPy$1^)VgP0_lc*yS8%|c8YjC6 zKx4Zi_rp}w4(u87-)?Byy?qD=IGA^LgGl&o>C0dUwG05St*Fyzo+R%3wBXatF}`^t z{?A}IzOX|z3Ur(ffzm9L zP8_QY|0FHkh^fU41C--46$I^7BifmCz^DKX(Sxa#*@}-#+P{#aW&CbJm>`su02}KG zb$5yEX^`GtQMEx>!0&I^A=1R);v3wiUH2+1DmEPgY<+3&&>NY1bYSr$7=g=1Hc=y0 zk4e639t&IUE>5Dm=o^0Aa9X$AZDYD}t+gw8!~k1Bq`#W$-2SxJ38PfV^fq6++ur8O zTcJnJR1}|a$p!Yjb|s<2g|c|x4L=}#@xNn^N~9+) ze>&%Dh8krhiul7b;XdjxTDT*zcVtmjre1RCw{kb`Npa)-^+SrrA$EukB}vN+tZp3;Lv)9Yan13 zw(v6)Gn*U(c`ojAM%J{7<@UHu&V-Bv;l3}CDF)VcVL-%9PKU+hw%TYT0Mw=l)o=JE z7AOWm^*LV+Pl>?DBG;iz_%?b`23b^UxbPX&UOeBAA#3oKK=19KGYzP|oNL zV-bxecog(VGm=BGq}9MQ73>~+_m~M^5 zHOK!wmwvetA0738=eAl~0d&(XK?$N~a702K#X_65L)-YBg!O-ileG2}U4$xr zh?3l{=MjsobNkcYNZ{Q2ij7wr65?Xr3#lXp0S(1vICdExi))CE)ta~djLew@h*Ho<$ki>9kC^C{VNe zZem#BhE<;6JBK9Ebma|PE|A=#IlO|fR43`*{_m1hhD*&%KNsryeVV^RYG)9QTD}5H zKDCc*I;3v7JL5~_;OWALmXy|6&o{tOmZG76TZ)u0cAQY5fIlrV7Bk)lG~N*C5`qnq z4H%g~CCDJZJ?a1UtpDTx?|kuafe1-{^^v|Pay+{(Qy|Ms65+V~+w@{?;E zOez^n`9hsYdl4$Cbw3@Got2y3@tbc0!4E7(t)ya=vBrE3Lu~q8GL!)oP{@U+GAkqf zo)g$WQ`qLQS(WQ{&ShD(WJu|bS<|jg^bonJsBek{hnkm&i3P*Ef>}b?9eY$b(H2SF zN8nhXN2-dqc;^t{y`w3oBQ^O->kGb)Q?U&`-Huat61r~6vB&#~s4of|o!^;XnbHsnU^r^i)VggYs z;k%?-gh{6mfk=Pt1eOF~nYs#Tzu7Q_!C*A$UQNjhA!Xp;^RlXqqt?MG=r{!vuHNm4UJ|EjK3tKmKK2>L~T4~4{w8toMAw4Perb|r&Sr?KC22DP2B;#qy#oa&jxh=`2)~pZ%1WQQRq{l(934IH>2&hrk#HfrtnQH*;`t$3=_L$sIzyCR{4Y$TpR+3 zTLI!^+KoZHFBrUFp&qH(6q0Et!`F#?8>H9Tay~Y_c^@d_hj1L+19v}e1(Mzup!PAG z2=@o2IlvHAhz#C|>CfWgW%OPWDnn}EWwiPB)!5e-1l(e zK9VA4m)ayi|1>X?TZp28Gn%M^@qATPOfl2RIwE5kn7`2|^rD($#WKmvtJO?04Oi5M zFej@I0FhJk$#4}_$-Ef0iDhVdlXN8U9D?}+UvKA2fS@_`s5>%986Pwcmp;!Z#5`QJ z%H9Q0c~5wx2U0Y&s248rMfevwV)sE<%m;jU30nz~>`5>PlCq4wJhiUJ4j3?hlc0G& zt*7@rfiOSNEt0G8OsLAc*`L|MN}`gZoO&7C!vn{;zug#NU^Y;vw*?ccaGMMy_<*{JsaH#)CkO z?~iwVKcN46uZE|q{@pXj8~Xn$(}nMUxZNVRJ*nkaqhd?ijAPQRH}^3!zlM2 z<37!D9f%)LxmeIZ{je3o7pRJP;!pB4N$vX}=+<(S(=hy1`5&M-QCsF}IvwC2Y?Cc};Z~xH zMfAi2mW2ssr^~zK>_!pNl_#ODNNV_sgN0(b&~DX}7k)d7oR|Nr_3~dY|Ml|!S6Tk8 zr0Cmr|3~Fk{0?)X?SJ=K6ZXG{t&RGw^&0u7TO+Bze1+@=L1++94D6WOf#YsPgrl+_ zwK-C)9KrOv+Z_?pbpO4PpJM7R{%f|!C1R)nww*wW$gBK&f>MN^KXS)&>k)h}wH1 z)Ea;ANqVJ0vliWC9nqsvuIB(X2}TOEVGD_1Ph6ujJ?!&fxi4g{-xj&{O%H*;P-0f# z(517HFa9VYH+;fQwMv99_2-D>ZyzCjG)1tKYps{I@+uxC3ef}H$43{ZCoQFzT1e}E zywcp01EG*9o^vMQ^e37AF}NYL3nw9XT{k`8%x%7T<85v)1}oKUN*66QB^GCU;K<|` z`N{wfG^dZ_OwsHPICZ4x!nH33LFi5s446AjWh~o55@#i?Gy(yg#)9Om1$r_`NcjRY z0w8s*_=wJQl|Zq>iw}S5Z*}bqntV(nNGs8E_U1;fVaX(dfw5!JGNAEJ4Pq>hwMhi( z@Kp7j!`92FFeuz8o%KzVrD>8CMM_j*bBS`Tf|gq2P#>nV_KkStkh@v>qlv9A4Botp zm)qjmhM+~GkR5(G?!N9-sB9c0>fFl})1pbRr04F=!Z57oUJ_jg7hA(DbSrk&Db*2 z7y@R@G?|$ErCCV#%+e|f9He1kqBLE07dgr&u3T)bk&0KmfIA?h2VzVknyd~p8w+a5{I zjf1^y$GHGNnrUhikjwGY*nmnkq%O`Br*^wnDylR)*G^A*?r-u3Q{aSt{@xQV1L+MN z*mM%Zalq&yw5u3?Q{DZgBlGh)f|zzoL<=G-#-el-ZLo@ z-)V-BV5GGZ^Yl1RBV<=SJ2{h&&pi`BMO7ngs~x=6BSnM(HN_>01?i{RT<&;JcTA~# z2;W)H{dDrqcDz?dAi<|qn_q>dR|z-Y(7$n5__U{1qmg$@fN0N!UxKzlF|Oq%({J99 zcj`g>0u1cgXEmp_AawRdoYfujtIks@a}eg!;(?uk5Wa)CDw>A0U+j>EEOp=IL5Tg> z%#w)$l7SuE3F#qeiRqkY@nXYlIOMOMdq`8{I-M=8CviW37CoY+wxrDGly=+WiJDTc zu_p*laywm2H6VuWpJ}i}ABR_n-s-tr7kiUCbBlA_JsTZV4XGEAz%X6%^j0JkS2?VO z4vDNWXFfDry?YX3Lif6UWgfn2+;q)!AOcSBF&ty-JLxV zpZpp$8MhV}$VpXRBXcW467o4F^QR%J!BmcRN%rQOS8sw`y*k9T2k+Sxa^c!@fdj2b z%ngf@x~O9RfBW~(&=ah*B9S;6^{Bfp^lz^I&N3=DkGw&l-Fol+^RKqn9xXfC3?{&+ zP*HfzU1&O)HnGV49HzysE!oX!vr1_}C+e2Py30YW=bn2Jj*a-Zb-?#>#0h^%P>FQ+ zFtojPpc1s;s}A9!4oEtmo^+q`H9~NIn7d!AX@My{qW4Q~o3p3ro5cNw*%#=Wt&tN^ zt)@I5Sd9*J9QMa)@B}}vJi;npw<UARI9)Tgm5A zVxO8+B9^NuAbt&>nSsM9+?MLYmG~*}stsZ#k9k(;DoE`W1~lOH^qi6A;NT|Fij34D z5>06inVe61o{q%Q`ygP3@EBZX~Kdnkm)dJ?%D{u2w@{BJ6e#1KFiJC)n0GtOFnuI~j+s7SAb#ZcDdmXHD zUdJxjV@mP0w@ya|@W+Yx0S1{jM-~iDCCa)1{JZDw*V(~k^H5W@Q=iw$c`udkX@w^APyGX&xCW0Nv~;*7u$OStzgong{j^8gHxGr`^7d$d2pU)Yr@e(#SZ%Ul zP4a83xFhV{DgU9>O7n5J<(RL}`EXmD61IdPBgAo4Bwl^7;zD8I-ggl(?G^wop`o9r z73l_mF=hlPOcG5N6_1NODlirh8C<{tP~XvTxF%+x6C~{-W0x42Zk&G(nJ`zrFJ@sa zpiE_)8~vw0aU&j=%lGKvVtdMc;r-0mbBhRDw1(J`hC^XYOdB`R2ZjnZ!B3`t@qTsI zWV7T7v3DTU;l!&$1$Z#6_SN@IWjBI{@YZra=_FYx?naBpHDsDqQKlhR>p%#&>*k)z zeRf8ha-T*6ka8!fv4jC1Q$L-5`jXIa%gJVtlF21zrp(2r6AW44jdrK4PN;J|S0cr< zY%XIWAO({_7fT6Rz%B^0?M(Tq3T{(H7WLjI&H;;ned|P6qHM^W57ITvEst$08^9!8 zChn`(ue_Iwk?=UqyTA(Gr~V|H25Iy(?nO!cNE$dR4i}7OY6K3~Cn6_?J46ly8J3nK z+;BF?)y#NHu$2@%E#atj&-NXTci}|MAS|Xh4EB}rPm@9sV@Ij)gcrd86$J`Mi~$*6 z_|>sOfiw|XEMpVI+G{^lEE@JF6i_Nin7-e=a5uL$HeYXSZ}ptdIxKYl{=DaYyuiPV z1$*}X92D?fitEQA~J6`*vRO0ln-T?8z@kjQHs|32l(Ha;JKZ zZ9EW+VIxRzp)lYd`a3DO(cA&fNQR6nLGt4>`_6M#5y__27<+mg2Bo`G_>+V_42lp* zMM%u?!$yx2`{_u9n2kF_d}FkS@Vkcq8;x*^DW~2{!8(#x6G@_a^ze;EFL>*2z4Bf! zIFU(5Iy-c?8Ye8i*^s)T@{I;SUG@|I_!Hc5hi8YKD7Ig4<@~hg(6jmstZewT(fPyl zyH&wfbl^9{OymriY2E3wDX>zqaVtSpla+Ynx!+VYA~Q3fLJ3_Oj5lBK{{6IGiZy%N zU!$Ae{=7KLjZTYWwHiM15N1(_u=SlP=I(BD{(&y*^zEr4Wrs^Wqdq%*X8=g7`r8Jl zgc{X8OX0d;*%)A?P6Ww9P~jvTPx=ubHtxe~oLaCS$GDM=*QNQ4=Q6b`K8RDBwCx30 z9vaRzKzK{v4od+Bm$xJti8D7F$tW5FW|V;{BK6M6HD}h9^0FqVNBl+3o~EtW$Z=tA zw?|V_zvz@5f?KxxXzeP8H4|KAkYx^3iW%fb71JIX3h{!Nr-GktWQPmy`;1-36F$u< za|Qy%b9tng|CU5K0*a`HnIij=7X2vvZlb1IE+o?!hcWq3zsm{>;6oxCri8=4dFKs= zBsNE(RhiKvo?R_`M(|~~FpYDy@$*HnkCP${7?_a)yll zQuGO<9zsSI+LBHPh6%<4E&ytAlB`6Yet-Vn-Jzx0r9^W3v@_6T2gtlRW|6_$^j?_t zwlUk@;v_xK@6|tU{^DMeX)xTNC!!i!+)~kDJUjwGZlLQ0--M<2-Cc|!+{rLCsEb2E^Bjwp(db%m4zbALfV`w}{M@)(4#y21&X@B&rzq3hfUK6OpGG7b>cvjxxLw8^o+wtF z1lfrgfOYXc6rglQ)bF<4KGg*EjZ)|Y?DqP6@{8k4$};<9V?zeT6X5I-3_AqSZooOQ zK@(4Y-rBHk%WRT44q(#efbUEg!`GB?`+YQ`Z=Sn+iJbds$q*IgHM5XIN1!XCK>_U` z$s6rJT-1O2e4!6LE+ln{lqroS127$4sTMG|KE<;#~X z0=5az=#Hv!>h5IteDiS{#t9!pNfJ9Mib&n3ZAb(AWg_LiDeP(Po(h2(F}ob%!(bSW zM`_xMTi;{9=7Hy)Y8tSeVN8DpS7lqx!+FP1NQ+`;IH5oEFdUqLo(*5yan=G9fN_ye zRCGvp!Rp23Ag<_reNVR}^F_t^?H{U? zEHBRJFT*i#2D&_NpGZC3C4-0_mPT5s0VxAs6{cR2w&5_Y-M`EeM!%7-gE+iad5fM7 zcJ;jK)4vUJgMy$xVBzWYxIrr=Ss_2Z8GlwwoX0^RinWtp>!% zjsnBT%a>a>;6E9fn`ZK9ihb~0_MLX%9^L-TLLp~W4!<>a$U;A_`FyO;1S+sAWNlK! z0rc}NCWGC~?B*=ntS?RB&E0Ip%v&)e#ou?IorXcef_Pt45S>4FWow*m$32Op2au?2 z`-uDosb(QrS59r9n5VeDfv(LI&NLb)<*Jae2-%S&CR6uwH4H&Amh<01m|b0kj9HOg z)leQEafC~TIgXklfcNYqKqxAjD^DF*lO*0A-tG19{*w$ZG8V4FYoz+X{k83FF1WuA zQNje|nxlB39H?DfT{b@st`Ps8A6egQ(MqgqrS7qcuSof3`;FTI2ta1bO47ibhHBuq z^;ij)pJ;yoD146Nm=zu?68wRCkPfF%2!kvDfD8^{eO;z47#WL=CG04gKMZWYwD^Z( z;CdaB5N1J5d-s40d8Zz1v{8>`; zL#X3EctFSQSJDHg+0~MQhiOixIc@N1FsZOzj$?l|n5B6Xa4KC{{*Y>htR~SVcc`XJmgTXYWsT}+%}=c!R-LJbe$t7iu%Z~JzE?TBDS6s|IkT+ zq#7Z*hRrrKdy06#D=XZYAte;J3svWu7z< zUR;YPZ$BYJR2QXGZ1}Nebm1rW*@W~nKEH?7@IO)D4+ag{=qJmbv{IW>Y+a3`6hI{A zKR{Q8Nj%8?BKBy%@?w7+B3V_L*sD6CAx3l%=sL52!;(fvw91^1TD7 z_k>Xf7_9rs+kUaV4L|W>>V%+DBLZxgemCQx6&Ugu8r33_2bl)jMMj0nGK7pFnneE@VYL6R%NLIfo3-UF5_gJ(mRs&kzYB zY3}jdvoK?ta?na}&O(&VOn82P{9k(>RG;zJZrwYD&wiR^WPe7%&iFi!^m%4{l$M ztbm23z>jZ@)N3@y@l6t<0hDy_%28lo?oUw&l0)_u%BKNsA5R_z365DY7E1zT=+*~C z$DsV9o0*PA%k@#c9I|$>0;tSz46mJ`G6utc;)AWCA(j zqAkxjHAwt*%b5sb&poBs{z2bjW?v3do_KH>eE~qx0M5=I7UZX;nNK z;}`Ffe4PH<&gG>)@bU49yFoQ{UmyZu^VN$*kW^05!EiFz#~wIE5L?$mT=?Q1e*R)& zIb(>1Aqw$75tkHdCLg^3AO+e$i}2XWk$scc%ZGfC z{vI}!Pjr-FuhKauy*UAhq)3(3$yG>Ng=Bb`7j3niC7x{m9!So5QRFe7;>%9NsubVFrOiHFJaN{-?$y>P`HM@Tb;34E0O7=U=ecAwO z7Qn-EQ=thYt#4zzqIS}J;|CEpDs7vj`XJ%N5pFT@PIF|b+$`!-C%Vg$g@r{OumvZ2 zkUFFUmuwZWFr`*ReKgZ807_@IKC|1|jgOI$j7E1^(Uzr#DLc$fRXQpR@R9|B;t=+N z&Gdel7%zMqx6X;Rvi3V?xgdVgX1&(+JT7=(sFlaI5Zzu-SjPt z-3v93(IGoCk{G3Y86ZbCO1+^)REI18(@RRbB?xhHxiA3zsme)+)a(2&YNByGJ*1v@ zPjOrmg0Bk~6|N0pzP4zd9((SIp1?U0(Vvy4ksMS04*2$HiI1M!Hh~H`?85WkOm1U8m)8ASk`sR6iwAqA+UL& z52^M@>k;)~fzus)ZijXxmst1iCsJFG8TIpgbMwuBtbSU%hDRf&`O*+{eCAXecaMhr z62MwR{xHb-vNsIN5v}2A^V+)zzMyR%;Ux$tN*6)=f2|_)-YKnMG~trJ4r2cLG#5}u zW}3ssMsohV7MyFrxfYyj!MPTks|BZJ;9aJ2{L+FDIp3)Qty{Z|vJCIp4oeoMM8q9fFDak-pj{DI@-E>Y?(h|*P( zl;zG35~Ll$*L#3mbwsXucZf=Nm8f*?B`PHc8_~aOiMf`TzaNQtr?BE=O6sno3b9Jk zaVnk+z6VK*w)J-*c<+|0TuLPkx&STdd8s(T#w!@px3iRXbA;7gAu%nVD&(eJd9i$K zXsmy{u)g7$e7P3cYmvPc*=v!#7TLd7k-g{>U2EBEk-Zk#YmvPc*}q4TJxb0z1%j&kQ?sJCEKSW~x^PLB-5a`ZRjst6fzCIOPOZ2rwUrY2G z61|G}B=RkZ@9j4?(+?Yw3_;%pVL)=y8Sa);Q4x)T)>DJSJnC+e(kzdDaZYrS03Ylu z)kwu=Xu@UE>Xx#P?xA@C;pP|IFPksj&9~mqiz%`O-2|YK?`dk3{deF?O92yI`I9q+ zwB2MBj;p+#Gux`0w>SYgKscN(MRRY%7SZnFn@VW!v3EKpo{%X6?kb61ahi~v=ewwf zBPy9@tAzVen5Xk<8oI|*eVx*@&C)RORjvmiUuY)og_?p@XSX2HxYf)&-F3A)~mi4ydDTeuoZ+%i-~RYFikKO7Xns(7wy#p$+w# z0FojNeN5#n{c|B$?zAJPV<53J)`2aG2RcO*1`O6a17n;n<#jAwC7_2v+5zxk!E#-R z-+iXiD5c%NCs`WNCQieRE8Y-S24$Gkh*Q6&MWtwNr<&0TN66t;5efcU?#PCrswru6 zAe^RF#Mss73iOo$Nk{FC@+VFV$%|e#JC-Cx^PLY$iDzjZiddTQ_&6Dbs$;gf;YrT zNyB>^4&Wj^UCn;@)9U@TQwd+ha}&^q+$Qo)pV<%)#9Z zq+%(^ilU)InSlO+I@6Psh9XfXLY2G&6jf5ey5(eZ zJx!@YQ`@&yRxNbyuWC*uITgMhsSMw{#Ykp`G&|2p%owH!peEC$Zm~~*$|XY>+;OH@ zTJqPYqmn>i(x&zjh$P+=Bkm^est?%loTWRS`+yzKdGL-0)dQQ_=JRFy9t-Jz$_;Nx z8qwYR&ep>=o`>u?58HA6OSYT)>@}?!x%QSR7K?%GK1+C%Q%JXUQR zckdSW*eUMXB<|iG?%WxE=$>FAAnToBku`R`Gpu)p_0F)~8P+?)zueAXalmi48CnVD zZJ4q~h{E7F{Bm3~89y@Xyw{|h_Z+|Nd~ao?w~@#NtX{Iy#n;Z5fF^rAnRfje_Ow_8 zMvL?BIKg3SC^T|m*=j2ZJJ9M{c2^yzUBN^XMotVJCJ8puvjR;*2R7fx;y}9U#w!5e z5I^vV!qc|T2RaP9Bz?{e=ix&(O!ts>8t17SCOZ$Eg$;8p)Yn3NEz}<<)P=3GA6Iz} z5XTqZt8H%+Xx&>2D1D{?i=cf);@y46w_2D!^Se-9qmb0xtAzt~@xB|GBb}ZRv_98# zr4i5&s>lg)#iw^xm;p_ME?K%qKDQfbX7&`Nmc}P>$B`P9U6yViO5Mm z!ZDVik-izAZp>_H`^(>d+s6?s!%e}k-hS(CFPzo_ zZuaoRePtg$3H>I}ytc4jDBNWLW>wD{~#gE4{Q15BUA;t=XI_@6UOM%TP8_{MI4u+wpCzYp*r^x+D z8AqVo*xL5qg3@(sxtHhY;`GGQeaSqcY1|Ad|7_Tw$CGlVnR$z^)?vgY zYs-{upq$f2udD+>;#y$J*{+cGtTzHAUgK5y=I0eVMeFdIG=*I%;R8)xS$QOK7!}B6mh5D2f zcJpEwt>>a2l?)wzM(X_ab&9A*%~uBB!#Gq4hoc$dw$LY4-JkL}nK629-Y%i>*`p^F zW&XGSCkD^nWr+X`vkZ>Y7xvm@jniL6;Z>Oz!%`Rt*Ga9@5NeI+}!KPS2_k)4L0m9fN$SsLvwDX&%y{nq1Z9d@`hVc{)>%Te z8eylufWjYug=)uS#Jy1{2MY|0y0p92uZvmhC{e+`LcO*kq$#7Ceh}= zj?yB`OS;tT=^&ejH=nok$4{y_=BTf2rsCLIqEemvWhS+24|?C~wnJtEtYt;nL*x;PI`jY!bY)I&Htneo09BD)Ub0k zsp#2$nrC4;2+|;EWv`uv`84GuQ=eX%ro!ajI?rJhMv z`gy8?_5n%|xChk~Z(0WUJ0O{!l4x%_gU^*tXcxhdW%%Yr{B1ByhK=%lq)AgJ+3{6H zAo?U_gsg^$8hVvKonNP%W<$~uOUT$4-fPZM@HTJfXhwL>+1{Qhy^jR8J1n6a#eczC zt}k+6Ix>^^H&JnHYXVD;W{&Vk=g<08M#~REvJgqj>9)#=HS3kK+dyC#!uVEYWLS|# zS$M2Oa;^^82U%K6y|jd#Ay}w_kYrKCZlpS`Dvbp}tAEwxdXbM(PFZiVTX4Q4M#kx_Y zt$v~It2Dx-zFAr4hnqL!-nb%ZhI^zZBn1f+is*jYRn-(5`%EK0xhl;Ahs>3Vq?DYg z&Uo-U6|gk5#puVp5>hnkc0M?um!Wd>m5Cuu+aerh15ldw?MYQqZHbH*|6m_h_XdX8 zH)NEmG>r31*+y-li8j<+jf;BRFy>_JQVUI6p{`_*kYo+{J*F*V&M#L)T4%StTG4(t zJPn&bRZ9N)IF$r(RH|9yk$NCxxmxgJPLalUTW2*xRu_|$c20-4Rp?8jn(ZI-KYu#y z))bCOWi^dcwuJ2mzEg9zbD{{J*!xf=aLmrjx1IrJg}G|PZ;{5DjDJ46XZlliPH1Lo zlo{f~o~LQcxFfWG((urG*rm+0d77D5eGP^_&)wyU=`nfw9jSCYBr_TlP3tr$I6lne z(u0LA;Vd~ef!dM-wq{r`9qgEd)Jht#vYbGxI?QPnz%rHZV|-oag@3#p7PE@gt1WNa zWgV*{guRcXc36Y3%XkJ2=;7wopL*^%z=>Qb$8s)*={?2ZGVjnAHK)|eUxsxyK5OAv zl1|gOvCpnZg_R%|ewUWU_`lf$19Jw+Q&*T>Ict;Nly+<~DL~}xLS$YU+IHT;Bq{Wk zs2x1lbDIa4MwzpvKgneB^RxgOgDT+-a=MBf+e2h_)+x5a8_q|WqLCKeSEYyboL%%k z$42(tLkx%wPi;O`p>-YdS6YHsiZ(O%*;nZ$$Bwwfc#7wvV1`gy$*tK{R6~36_xuM8 zG~oZ2jxqWZ1%ewG|4j`mXRQgNvTeUvPb^RP5mR=ovT*sU?7Qc@(!n-en3T7DvhETH z+ca+(&UKYiqkX4(_{AqvSHdA(V_Of;8)rDTR*&T*o+*yv;<@74VL@gKX zLX2w#@r9{|#uam#a^KyFwJzbIXjp~oXa_PiS-il_VFLEp&79^d_L#$pT7O0ICCvZ! ze?&O5-5JXzZye?dSGv}li561hacI-CV|*c-B?{pXG%GpDP`_OFmU_(9CR-r+CuR%$ciMW%bZdQ2U*9X1i-*uu+JC4VS5q@{c3dTbv& zwgxWb*1=tR)Yjbp!1K1&jZbKO2BML9S545!NfbpD&U(2+Xn$ce*(8$(ldMz?Wdg6fDbBj4Q5xU27zeKnO+ zo90#rx57!0SXOvQt)d!_h1NdTWLo)J80uG`&RucXH3u8Wkul8|zwl;29%4tXc(I>g z7knT2+JswD_rLUTI{S9vc=iluI@JE(M%YHAtg#mRG-NfxRn{)2Z3Pu{Ia!Xu;i5=#elh5?*C)rfqrPG8M(Qn z&z49|d-sE+W_{D6+YGbU7@%7>&_+Lgp{?}GFr+>#)2d)u8Ih2K>#=sN;VtSgVfez zbq*SlcV;w(wkK>hL4*r@UmPCWoNt;8*;Nwt*D!YXXq zBT+6i+?|Nm%5l0aVKUV)*K_w*g`;gLg$5m^2tUTgKc2|P0SSOS{O%zND7m(0WwCog z+k%M(qt+q$DAzh^>k$W+RX);DP(qCeE(i2~FHwQ=rsbp^P&7r}k}8T2pe|{lqEHPo zg;cpD_2>m7Z=7B=sY7QZU41AqKOjnujz~zNS$WGl)%ml@6}eSOrt% zWe8BR2X%Ol3#4D63rqem@aN;CDxRjoV8R%=wVv4PiTzJBv1uFy)bJH4K~S(3PYIe5 zK^`Jk^=7QnQpfSldpUqp=h57qCOF(vg#)OEey7y)`Vo)!hhDkc-fK28UcXvYsm^4| zV&`L}`7ABUb3YHWQj`v>P<MMV5eSLrKj;h2rF?^-y zb%&(znK4*iU`0ReM*6!z93u->0-EVk)Cq=p!VC2g#>8%?f4VobR80S5uQjR!Jo%sK ztwTCiGtx%LUcCYrB(q}5$GsmSQCY$47 z8??cunbn+FUS>IBw0Z(Gkj=53_uRZ1&iUvqqm9LL{%o;h?4E=sSzH4+xElZMf*-I< zQ_nr-^FD{q`xsKwwpdVUV$P1Ur-25nze(k!XZ3Y5K?q}js0utAg|u3k*oNKcG)*I& zD3y~MKpzLGui26J*cmbdh6n9#o8mdybUH~WC z#1jD;BrrY|3FbJ_ai*jGU&1S#vGbL`{QR@$d?Ql=;3Q<{6l_EEBn*(J1|rVH0m(@v zY0^ZLw{nfW@pTUbB6P!4>&yba6o4lowUTtUNhlFqB1M!B=T9T&j6=sk^x{g(g{+f) zlvWuj{$Ui&|7{1|IG`TNJQaFzSU$~WbsUykFJ8QP@n-9d`*zX2b0EQ# ztQC{3U}DLRR36MoP?Mzzt-1|gf3#~-dMCDw8Wspplh{QyH?a>YjCrCNlacMcD{Yen zkdzx@tT7{CI);+lR+#X33G@OWz5GO->A84x$-cBQbt(=Q#!;L*B#BFl9Xcpvysi3~ z1VE6+x_`_~`f|P}_+%VK%B36|>0K8NldLLxB<2m6%rHv*>GPYl1B=Xa4TKsn4@{5} znIL2FsZ&*T=SlRc+{@R^bgokrsHc?a6nW8>sf|4Ka+0Ujc;X)P_r9F-aQ#Q6b7q~f zEkX!ol9sg9au6%5YNnkjOu(E+CWwKw>pXygqiGW0ND+5FBa5G`3R32iGOsu~ex~Nn z1;2eDx%0eLW7fsF4 zjF&@S2cv4Jaxa)ZW&Jg%9yeFv%k?T;ufp{z{CliIYj@sbFEl_AjW)#?7rQ6F??tzI z&GjC-;O<;+vLeIMxyM>7Qclj&!HQLf398KRG$$999kqyg;(m9_uV)7^n!6fH5Pb(1 zHx&ST8~T9ZTP5EjPAkyCVAhz&uyqSJUc=wg6Hp}dH(Yi@@s?xUZmiyajm4X(2syqS zxO>C5fcqXLbm=@E}}v+RVl2NC5CCtx7XEJIRpVIhugRxLrqn1+QGk4HGH zilM{CoDDmmYgt&(a$O64~zahRmp1cZIabt2hOMWitz41+pCLIh)#Fnyn`+3D2m zM-{*p3kg@m6dTd6j0mc7(pvdo&elZ&iYDB+Cc`{FLo6HT{S<;C`tkia2R5iuA(YK# z93he+6d86Es-|sn9AWbH>Zfp)9z#4gO|WN+z6C0y(Gf&1_&jVdkvpVKLbIsXF}+gL zSFLPC^UAbc#Y1Do^OoJC8ASD4{3+V_XupHtHaE<|o82nlwQa90J$2LD+Sv477<{U& zK92`;vUQMXWe+e(-{v^f1z4UxcT84SYpm^=tawG59K~tKDIlX}&J~=Zc&-8E$LGA9 zc>d+!Y~%Rs>LnP_RN$+EHhG>ceff-6rcDlCB$J+s{sgbbPi|J|DoFba{kGC8P4nn; zihNe%l2%DRpxVEC#pK^D989iffCHIMsPQ{$D4zxeiMV=WI;>KEQYEzOkenLRPz@5l zP+k>QtplkelFhVlP4H(xlTebhT7V}N{AYjR9qF3>okXQS@RJ680fiXLl-50D;=I3? zBfmL{hu!9!Q&WBoQQHAh6L%)6xD0Mo_3T`84Clt~my4rMpU)qifm4rYUr7Cy3X^^L zxjozCEKM+5jL_JZv172u`nM)1)#Rcy0;!WvLetcd!ho4waamuC;V zogt)>`csG}L19C>3u7ZoOq4Q9>sgW}c2e~f)ad6oq!vOIXc>`icw6c7i%%bqFOFLD z?YwV8gEOt{fEzlhm?wUoCMjsLP#8Kr6V?D=|@|NUlpvjHrd z=%4oAv-da(aX4Zowfosl8aWuZa~_53`Gok161-<2hrRF?0%fXp{GMS8K|Zsc#m?ef zT+f96>X|Sqpy(9kb)y8IKssW6<N@7WJvyCZuzJGq)(3Td`tfF+kd_4Zmv33cmPk%NKXBb_1kPE}}Ip5PHHhYFGWyv^0^H08}1Xu@Zpj-B8%J3g5# z7Pv?3%!asZ4$zwpYxdY@436|&L02V1W%}1?pzRpds2x*MhgF^LjjocF!iVn$hM|sR za?GNv8@|Yya9M%kfHZf2#U(4PI+B}I_Cu29If=4*_6(-D0txyA(4+~q3L*Ayyq|Az zPn?ltI;+8L&jGDan;GxbcZ|$=Ix3;mv?lnGo<+JW`yBU>2iBgA)z~J8)!7h)j^_;cEs`kaK_#KzT_WM)|&ogM#rZn~q3Wu_d9 zZ}HP4`-!V&E@oa7EOP1>ABI7gYhxrbB{Z8_?7pit5c4X}OzeNK@X(vD`dr?Gg?{IC z&UZh)v!i9-gW9OV^e0+Ue;nZ}K3Z`Jomu}@=woBT8MrQ$xxjX_UMRNzdGkeg(d;+ zOv*C*Wn*KKg~{}i1mpq^%7){#Lb;#;+8Ct`mWLY%3IFafD&z_$HC)E$;3L-HM`53_ zSD5dEN!BQue-7b)4(GJ9?iBpjn}dM9Rm8BY{OY;ibVR%5PQVwu8NPK&?yD*a$D#XK zjY+ahRIJ={57Zy_tLICJ&Rx5tF(>ezGX9cDYg9Q@rPGvpv6blfjdsMuM3e7NDl&-Q z!K@hOX*!jQ$T2$AVPQbZq$dv3G#H!P8lJueLs`>sYB6B~Km&0aNxVyQc+8UqgJ}IRm8!FFNK9OuHQyVEy@2N=}PwOIx z!TXd;BY>m^7xA=^ual7GSf<^Nn6`o%<(|`8`do2#pnQ)ZUD@j$%;ic+s-JtH|9|$b zrMYb+NuL+L0x=sgZSRn<_41>K2TGJ=$(Gy-Nw&M^Rs@P9BoIL3Axb*zf7#<6_O$0c zb?pDz{4%TXl0Ny7*9z7HU#sQk-s}Cf?FjU)< z+K%rl<=axt3_d4tLMEne-dei> zB>z{h5 zeFvpMU3(E0aBcl`deoEpL?G`~fPv=qJqxQy`)DnFVB74@Zc<{YH9KGo6Ktz14+Gmd zg8sZTead?(`9Wn^kb$)x4=akY$Py~FQa4{ip@_&H@9@ForJQgL+q}9XC*uWR@|>Prx@W1A6k^r z986!;bz|_u1W*{T3aq9{N&&5-$Ln}|9g7dNSAT8|KK!G5$d~$vYj7$Q^EyOKOdlhf zIn)x<=$?7VrR87OWqS_tA^n78i;Pa-e){+m^rhwU)JVVm`y9RpN5B1BejEMvpR^$J z`7>2KciR;{l??il&hu-;z@?Uk7}7o+N?Nv!%JDbEqW)ie=z{&HOkS`~cuwUm+C~Q1 zw!sya3YpQs84dgKoEU9GOILZeRX$A4Q}N?wH<5x;Vbj~>RxnK zG1#!Ls`Zg?r}j1~%K7$^fxvFyNKYmLmagVQ9ZxeapN3Cc?BzT92G97R&k=QAhzpA_#NJayIT0$WF;E8N40!-1p`%n&y$mN#El7iIlTY(kW52se=f zD}s%yU0e0rGwKZJy+Gaq7~n zCE_qPByvH(KVAwYXq`@>;j4(dPP1lK0X5Wv%a-nak}q%Fy=VgS&tRhYVAzB*|6nq; ze$Zj$4lXb0r)@8^8~6iS-Q9sX^Kix~3ZOSbWN=Yx+NU6d-ag3IQI)$NkZ59{E)koC zV{hW^eX^=~6#NuLygptL`R+h{zd)l0H+(z4*9P~yCIUPXi`>%PiWWRo<$_Dv7D3A>2Oh!lpZy5`eA_uqCyx4 zO!hR%hI1Wp3v0*A(0vEwEZPQX zmfgP3(dLnbj5d}CM4MJiah(XzOcRG>r&zK<2;g*XE9caXZeGskVzHvB)hO#@$IOD7 zjgr#_LqOze-t`~|P3i-Bbx04OKy66GhJc6}SV%c<#P7U-XD$17^Bv0)jKz!QbR{rZ)DsC(F{=Vki2krh((^PjWES zC1$HKbKpoPX+m4|^F$ZC>yN-t__!)#J)R#;%DzU{4LAqCMZS{Ft}{P0AG={LS+a;s zMg}z3D0V(d?;8@XYBOE}F*ZYHQ;3~VKo$A^vX!pT=?t5o64vH{Po16I&m@l(I2Y}~ zZrk@qNk&}>%#Jfmd|H~pJ$$Ha=k1b5%n}Q&}<*8C**z)mH z=V^Olhxg6G1EmKiTzcCPLyygU>-KA9pQ?}TNbIX@{`d8N+m_x0qmg&ojn@D7feJ|8 zBgxcz1DBevJN9U|zg-4lg1jH&u|S|FQNsXjybh_H;&Rhwxmu_a?_KM<#j;bfaLg8} z4qRB!-gIsaRP1?kwQRR|pu@|=9nA1E^b>&jl)0yKU#0pfmU`-y#hiDBP}9Bj(oElz zks@R)gp%u4RKbqHX(Sl^|+S^TuTH*15T3$XyAF!iSKqt+-;Az zQ5&c+4V_bs`Tnxeb{`sTjJ3mqy>zHMgS_7z-qymc0>El>Y7oYV74PkmQx=Fd00CMU zpYKN)5q#6`&_xIDOQunKu>1WZJo@=QdiY(KLzg$yba7bRWd?Uh!>LH4!48V$yr4@R zj!?&gllff4y#~{*6k#=vOT|U*BP>ShoA$}Sx>DxKe3sZ&?V1JtO6t%`9d zLC4Khj#c%64S~*`qEa7Ki1)eV{$VeCe%}jz59hM> z*5Je%uP6+-@x9u><}ezJ*hDd_=pI5kW*Le7x3vk2YVKSGCsb1j6rm+8r!5ADuHd5I zfTIzY!p0R@yed%l6ePz^iN5*7Wm^nCDGCyfsqMLYpvozyEi8&5(M&U{b{4zafe)G< zT+oT)WUsqypuF4rvdGq*Wb8ryf-iJMWfh;tELc_ z*)7*j+N{VKu|e~MsQr|Lv&La)r`)Do z53C}A$l-_FW}Rv%bsM(r+y-?LktU9DKV-F76-vH@c#d=&!`byD0ZM5mSwU~Fa{p#l z{3@oTmy8WS%gD1Jq0^^qiYACje(9~fcDL5Ot&Sz*RI8|ejwFn=Z~hMT`yvdevpzvB zSB*RB2@>5_c9*#%twLtJBz?B_ye=|2`6Rb_Y{2?;%q+(~TV!g&se9SqlmVb>mL;o# zNg$~jW_>Y#le}VEDNPvP&f&QipTkz>W)PPK)xfCjK@jWvfzOn;uZd6X=c zj2vr+zW`nqy5V3k)Ytu#PLl>ItGEarVNSs8k8B8ZplO}gZ zjODw{1?2GPxMuy&V4~dn`PAlOyIVRAN=yUdhx`TZpOI67#^`Pp>}znKqKU8qcDXlM zRbpBwa+YprILgdjd({U@&Lm2h)%2OT(OKe_$~DoKozFPJMpCuNaSME-(avf+cYT+sb7PmLyk8KN^xTc> z4ZgN{y-7H^WSiIOYge#e^|h~gl|mBeAQF!k zW3YYLd#hUIf8_HfEs0_(N@$$n(-FqEY@CR1hhfx+{yI$pcPE)bA3w;Z`f1-4Gm1ZpHPqf>N9h#Vfj8zh`!^x5ZgHX7_rD|;eyIJK`(9;9e#<3rFf9E% zkdQf}tBZwiC-;1+{n)b*s}dtOyMr_S9mc>7RE^IKi8q~R`YMbQcc2S7YB%aVqQy=S zjZ)9`BIFRkQWv(@vT&Nv3OiS~A=Q)xax{$c&@1!Q8)qgYFw;|TlfWHJiClwWG!JVl z6TM2OGxuE*1%Rj4kRWhn7&YABjuNn<5$zH<_h^sWc1=6h?Km_DEoTMvd%5%iQTN8W z2w7;@2pW{2 zN)mI45)*_j#henPKK9J*;Vcc=#+W8WPF-55U`_7q4+%RA^2t!&=p<&-Q{7di-`}H& ziJ{7KMt6)#UuQ#b3kIdE%kFtb!b2=2NG9T6&QL;=v<}$JjjEX%ScnCjE)11FuREkN z)2JDj*p`D~d>!}i+BNqxMJo}J{FDYgn@rrnX99sE)H)790gj&j{@G#vS+g9$g)P~dNmE21&L)+;EwNTHtbTMh!ir2Ru9B;=t zGa=jzZp_#m#=wr8OfR@|ycvQ91&)R$`-2D`(vuU54ie~sXr)FGkWQ?^`15AG3|g=k zvrMF8j#KUU#9?Q`$*th}vxG=&P{x4@i(8RJ*4MT+-@aNWsYR36k}n{)c!G{_+EUcVvStNIxXjS%2_ibEWie_DrWh^_%ZbRVd2Q0 z(@b$1{FpJVn#8egBXMiEFBK*66iE+EgVwz33N43242Vn9CJ#`YzB1_1H$3@;-AI&l zMNv-0wSg0|019|d9$`FQwqEDqJOt`N7xwl+L^%b75{{I~_;8rnD^H*6>y`Fk=>WQY z>(RpWSbgR1HGowA|N00L2lu}=evL2dyR;RO;s;+HyN45O-rH^8Z?wS%5hC;T@vixC zjVHbu=X=Mw)m32OKhm40$T1uOZ`DN7Ci{`$ke6xn~l1FiL{TSw)I;ptm?cj1$=d_|afFBDJ24AY%#7 zz;Zb3Qw>c9$uF`_L&oJmdZ~nkIo6PQw#^N=4q(WYW6=r#Gk|kLpq3H*+6r~u60MG#6urp>ClMP5of;*%=3>9*5>f?O>`@e{O`n$oT2&s?FgTKZmDRcfk_iJBp1SqIEqCgw=;=2bPGB8DpqK(A3GTxg!RUupnvsW+%|^Bnt~!8jRr z3q>4k;lInE)*fVh{^ZofVH_4$Vd7&$_R`yOx3;|Xjt{1tT|}WFn1u0Y?YR|@6vxy7 z?w{!5bC?x?z8z7GNu;a!SHGso?u=8TeYlzEgtiCCG={gWow80dtN=4PLY^CgQou$M zY+WSyTv#bX7MKS4ra{l_%EY;Ta!FEPZa%ke%46dUTA`F6LS90@oLv7}>ev@P2z*;N zk>$_ss@O%CBTni)`}yAKv0L1v;$_Ilz3hQ#x87l^Z-Jp(;cPWAZ2>)$QH!U55Tm|` z9avqg?=UL{tg)rpJ2`#WPxp6qkJBeLLDLvfCa(roQVaRKwD3l(fNmCSw;Gqa&&_yp zib@Ho#)j~PE@)pzY$7z;3uU|^%~vgRWdsHuTu|pUDN_8@yz0>;f5`($^uGDZ-FST` zOX#63@R@h0?qLKxcH>iPVo58yHbqUuIhPNc<#Pv^wZb!mVUcgl!JdFMtM2*{b9D|e(}w@U0QXnaSS z=n9Uoxb(MiNHdW{%n^`B8rqYH#4q8Snn-G7aU~5y8)Zp84lP_Glr80L)y^n!_ogat z=;!wV_+ZYpfkM=Pqb#GqtV=gUh6k7c@zg>#j=<0lIO|p8>PN*?dQg&>BQ=Q+{9#NS zeJ-^nW1vcg7NGJ-mGFrDpi&}ST5;s!4NNFH8{b%J%-j#jmCB50na~h$hNQbG-`f)!Lv*?rW%O{DdyW(#Ldgu8yYVFO8XSjNULq z`Ac~j&S>oEYcEyUv7LR?!9-6uVbFrOnCYhNfHpPfDpOu7^NLkps^+{RD=x6&0xK@?J-GlKW>4k=dt6Dy z0<6+TF4r$>&wuw6;ac-LiU&H&n{g5#YAA6Ric@AKPRXeyR!n2XG*(RG55hDi;q<92 zW1p&cKy<*Z36TjPq<^N99ts1*jka;``J6Uu`1L&R`MpAhv*H&kezD>ge;9r-rAhi! zhQVs$!{d{?Vn%hxumY%%^mUsn-LBhPQ6w!ZVsquYzDt()GuyY~8}x88+~fv40*U3}CF%Y|UDaL-h9`$OKk4I8s* zDzhX(7FcG7w-w>U9b`Ej4wHOxj~8#G=W}BFcxS)dY9Vmt>xbhZZ>=mW<;>Sb0hjCgKeMu0x{_^E(@8v6m zimbhS>AiV<$37{!04tzh!?&phcs4fD!M98BJ8DqhW}2{z z0eT=O&s}1!*7$2(5N+-PPA+DxJ9tu{Q6t}?-AJmhMs9GM0UU6vHof?gkdh2pL^9+_ z+XuSCV8JK9gO!87zK@U20*1(3?}CYqjN7Rc5dy8VGMb+KrR}529b1)eW^we86m?QY z?W_?dnV3_iB%XXaK7#Mx&wC$fpsr})h$WTTW4|#?fAm zONadTY0y(CGMwslBCS_gTh_ge&O*2yTp=Y(fB+G+cPY3OTU^TMh zidsi(xIII{)YW!}VuHHb^i3L3Zue}@LZaGk0_LX#Qsl+i8$JJF+mWl#Wt!Kqo;PZ-Hq=82 zQRY6nRDo$4N37-1f$m|B!lYDE!Rb<+H>cNIBx`fwx&_FTXTbd}Jgo_T7%<9UP}~|j z$BRT4zqbU4wHdmD195e_Vy4IHuoxr64#p6DZAYVGP)l~>V?eClmi_Ap(KGzD4Gx(b z2M&CSi2RbQ>61*)2W1W{;-qX-Kt%ig&FefpTz)R}OZ9rkIBMD`49jRad!lrIroGTI-c-trveF~^6wL{8`jI!3Azq6zSu8uFB(nwnfHUqD12lwI%rA=fihtrrC zJEuGmQ3n$?x3K+e;0^;Eoe_x$@O)h`dsvMNR9TvGYQDx=q0CfZx_a{hR$B>jt}6SZ z-XL!jmhd-9`pBE%Bx5|&hm#A7^5ykNFOB=@EHS9DZx7!~Ju6#WGkq_?@ZOii-Pgf& zK&POHM4&xMKVz;o3O}97K_t&x+gn?$7i#H?Iw&;93xcYZtD6~}GTKW?zfP%z{RYM})NCEtFH@T5hQSFoU-uudYqn|2^l7{F zgV4`55caGe2x9+pwe?~je-_5>y+&X*Y`!b^&>wPpLg*xejPp+}$Z%UbiZXn*E^{8> zQE8@7V@leRgWv~ zAf`W-j;DsW!Vs0ZVYXz=lD0%&o<>)pds!|J?(Pb&~?USm#No*tgOJC(cRGz6O< zb!l~?6%E=`QzkHstDVb}L-p$X){v}tA_>eb zWjZAEPn~lNQRninIQ$@v(TprRPwArlwRN*Sc0D^;CFV}Fs&9FO<&#W~46>o9ynAIwgEn<3KU5XLO@< z`|bka+#?2ZFvsYsnp#q;%4xNPBXi(8zW89a6x2f#Mp}w}RN=I2Nm^)6vueyud<9f0 zZeF)}up98&x&mqB0{kMjk`J+oH`{%)Jdecbu&s7lw*X5I$vEmGQ@EkJ-~u%{#~%^f zePXE>JD10Jfl*6v=2|165#i!|kBM;R9q4`MM}u1HJP1s{i=%76%$Xh(HwG)KY1t~3 z?s=>EqV*s4w8a@BCfkT>{q9KIf;zWW*iDdD>8} z_f(l@PIs6|eg<155{(c=%zG6QfSDgmxZ8Sid^C?!X1*q-NkNYfaGQ4)zfi03+P1XsJ>69IlE=SmX$4- zmi8EAkN8!U6)&EH7jl*p%QbrGIYbXOaA>lpI48iK61M3k-x}>a-yH{XAYpwo_NGNIyLc>`|$|kofJ(nlzea5Wdkot;SvQo zxx2b~h1Kgw!Ht;UeFO^dgm(|$pEi_mxQD{PBs^tVnOHxc3N~WF92CDeXR@4xVJe49&w2bj6+5dRZcudkGn))yiicd2P;|C04XqL6{-^ z4RhvXudyH(-d%E`Rtugwl+mB0c@DB$Y_S)+TT8vzZ!OlayVS&w&-NB;_+iV8W_P(L zU0JGo@d>>jwwG^swp7E;-r^0<&_uVG$7DVp|G2w@F|EGtE?nK)Tl~6T`+CAR^V)@2 zi%qHkJ*eNb9=xUX;9H$;HYByUuc=w!Hb;j)5fzm` z7E||-P1iU*%yEx%!Un zT|6tN&^NrB>a)7RRwxGQI8DdFlZD*NHT&xthcqqrc{z?$H^>7Mdn0i{uL18i%5)K% z2%Pgc7$CZ+oJF~f9(zywAO{S+3yQoPmy^JRYvnlO&SMjfb(Qua#D#z?MFM`9dgPp% zh;%Q3vUsrVOQTO#uix5Md;7~wo&1UzZ|1s1nn4-74<>vf(HYL>#-=qt8tR8I6}$tv z#T*{&8{JO#xZ5$wo$xmcwQGRMGe=4!kOo4Xf@&tnro|g_D176qo2;P7p94ac}3Mm0$6aQwO z)qy22#HUuVi^}3-qsLCB(_|P&`3PvHQc8}}z{*gx#u<;yyndgnsZQ}eA5b)&Lwl@p zjm@FF0@dM@rWv0}@JXn=9Y&;Q$%ig|pd-Enhjs%mvNXS|r)2}f_G3Wi_fe@wnG5E5 zsnfwgy(x79nh;v9Hb{fhkpoOyhA1L&{&GUGWskWRb%_Vz>AJYCsWDBVtJjIW!z`$NB=4NF`CT4; z7l#!naaXwFRXMR&xHjuK_DqP3?N$%y9Qg>IhlZ>*NsrFwx%d{%49L4lZA>Fhw`M=E zkeC^vtv5Xb^lJ|Wiv_470J@YT_;6-9pISJ9~tF;RI$5Okyv#tQ0 z*nz{_JQ;Q?)WWJn%|z&s)-eoY6jQ4HMr`F2iG#- zRlPB7+%@KE^_VYMuefb3I1)*0MyCD;-46hUF^xd{K2`@M{m_mk+JWhAI#(j*D;M99 zx#58mWs85&+H)%5%NL(nUH2@)Z+P*Ap8*@aYT+I8)d$X{RQ-)ExGRqOKL*|utup!B z9^}`4cujVWjj-Xc{tL1lhNHPUz&GD~Yg4BHV`J}p6(n?oKkPFY;V9_0r~M#btmjRN zHwRJ+e{NsrKo;91VpoI!K+ySWDL9eK4-^Aa`4`JUbyr;^?lW+lNT^jJ;eCNfs4o$T zm%sjRMoLIv+F>#wJbp+Aj-=h!bnrG5gi4u$iR;S z_bT`c98 zsUF6Wj{QE~0Bn+8B9k>LlVOm_k!(lp`a4T-@2}i-<6Jpep0MhUTT{Bu4f*STPjoR- zZ-4!-{B!*4{~#z9Kg8|fobH~cWcT}{4dP$q@sLfq?!4JC*B>a2w)$^>CnW_Ers@)| z(umb`n6@X`&`0_OgmS3;XoEBqnXTj=)$v}>HdG(OHR=Nqm1)M@+$K9kT$XTdahy13 zCun96wsU}rq#jJ8R8B`v1ggMW$~g#}=2Nl_P$=_)Kdtg5oO?=&FP%WWO_i9uA=yxg z)hoGIRE|E8d7P-%h_zPr{|<$IBtW5%P*sp10Xk>EhOKpv6V06@&o6}RQ`>c1{YCU zWa=f|9qCyVex?Iw5bANepKtB@!EnSZ22&GJ`Y}%XpQA~nv(Jd=GzH!r9-n^f9RFuK z3jFEJ71(r2v!Wc9n#safO{=@*!BgvM`1Y3}D9-4gAVuiwVLZ`MABYGFTz}w%+3LU1#aJP$ywyG3*VpPGp9M*K5{~?Eq$mC)Fa3OD>ouRQ zch_~N8~N*O_20hr+GTY7VQOdyOHJA^&+xfDphY#E_&PUGZ1tLFMcXVnz{_Gk5$8}=*uV2dy|T;)6dF8*H%tv>HDMZmcYy*OQfmc0sN z2Wt`XR|Kx-D&xIyS3@OJBSvlk$! zU`@@Qjhe8r#M7YQC>e>PpK*8+r*Iwr`OmJ=s=*@lOgN0dhXaEs1dRJ)|7r51(+1Z= z;!lQII-}#zJVjW8H=r{WqL6dT55}ZI2(bYAr=D1Xk|@OMIi}K(q+VbB6q%9yhX-ay z0Gvylw29b?YQW{Qzyduab2~E14vkmuv>h5XLmXHG(bbZ<#esktsYg+6GW?i&t77rR zT=(<{@ftJs*Xu!))KkaS9;Xd<69^Q-w>n9X8#Iw0{Ye<}FKv3zI<>4XkXh#?LT5OZ z``{D(;HU0~woZn$?`+76Lb7k9e&_igQvZk4|8At-5P{t-`>zB`sN%gmR)-fIb+W)U z!)b8ES6K(EGBXUO(ZKa%k?p3!=a2+p?TUL5t&&>bZL zT2j<>$jQ4VYab!kkkgUoQh`^y<@f}bNil=}yZ>a3oOH%xtqycVf7;0Iy#)khd7?&4 zGL`;Je^=f3KymmKTnEjqpZ9)lHHYCRlaqskC?m$~?E?&RK{{SvnC<5hb3M^cAu#vq z@$2>YBO_fQ=t(^Je9{B{67e)4284j+G3!U%rsbonUkz0YIR+-mVmULMa5^T zdIGUJ7|544X*p6P8?C212hj0{-am|WD$M-ZUDwph<%Uo8_zZ(&|D+-9C@;buV)vWQM5`!_R|sO}+QB$NDJ?^ZF+@#U@k z_Qab-R2i99_F48^7`+9|v;G}Wc zO1q;I){`kBRx%c;SZmTVo3mwLalJcM!1^|o$x-Kg6=AxQrDqf8*k74j3`>zFXE{6D z#=OIKO!uA;<(=MydRjP?b{U)N2mozX_vDo(`V_8)m*M4wDr>c zrcSAEjebtJojzJQ>u4yd9CO|avWL&*AQzyxEq_bMbeB!|&e1#d`mAeE;pP^4c|AB>xqw>D z=v;VIs_QZ77qU0W*rzdpyTj`W{PK6y$P?in7R(P55L2a2SCuYgXn*f{sT$#gRbUVB_s~#V`HVKDA6w`(`FO@uDFei z|4;IC+yED%{UB{NO>b5eQwzns$#{^<<5*nfrE+{m5NKg_6OP7x*D;rRiQ^SBp>jzY zAFi9TFD*h3+h`~*oi(4D!j=^loaZ?7oJMjL0R|~o+q5?V6LR&tw1Tv;Is#VCLEfW3bVl)`-lTTA1&8>Xm`*x$FazFgFdWWr-E|az z!}l;t`cx4u5c<1t&qJ3B{9|g{e~y*1?CAj#AT;^A3J(^e_CA$_YjqK1oDF;WW9N($ zSP|Vqxq4X^krWcv?o!)oQ%t$3t~o%?sUvLbf95y7{L?a z)!2_2q7mBv;#dHyq)aZs4`V&=r9dww5d|!QI9aHHdKDkjtluqy?5AS#51#F-GV7)4 z*jHVX`7FJ4%+1D1112+>XR*zcXC-pY622`LPFNJS7=A4?u-Pv6s+y1blS>!a9QLT9Kl*_BuCr3trl4j zWuGe3K|WtVz8CaIBpSNsbYN|;#)esS8=daH2fka7jj=@Il(a2B{0)1-yq-4T!VE*6 zrR8u0;CxhNb%k*@0VXd~5DB>I`C!kB1p%gTG0~sG*p9V5*5$-gLwVUFQ@B6|J59*H zoBID={Jr?z9CMH@E(WUsvP>NCC7Z6^U;bj7w8a9j_Q1~K+bf`Y-XuJGcY{GX8(8>K z46`Qk#|Rlf0@51PFYO?= z**lD5VMA#;XG?ROUdgIW!U-Zc8E2R{kZSwtu*Q?!kf9eY06s#plSOVd%2_b37#xB7 z=kTU(bjY{?&aH`sn+Mm@Y(NL5!GPw@V@D|oPv~Zr&q+{rKxzdm`PJdklLl$Acxu~j zz{pAsjX*zb2pFsmGML5uBRyfLjp>`|A$uZ?hL;oU+UT_jn1N-TkrGV9v4JPt$v2q6%GiiRZgHs{XH z;Eb->9_?AZ*j?XR?j8~7q!g86W)|xIQv?F;9^Nir?YG**F+_eV%YC_it=D%jQa{k2 zyC2jkU1w_lj?O|4&M<(jy-!5qN5hgfEqD8j$S85RTT4`DvzW*Av@6W~T$R!XTXgmf z`1 zqC}85XlbVziJ^gX0S@odp&4C^YmM&fM*xa!^5%I&v^jtsXoD{%i=+t6jj$pNVI1~^ z!1C=591bF6L2O{q{AOsVthNwMOt|zYaL?-;!Db8IS|nt}qVEy%7AG7gII~)~(4gZn5h6krvJ^W3@Cl>n3ZAm| zNQ$?YILV$3EBXtHQA>Sbm@X1BA^VpTY38vZJ;0>`MIzYlVK^Ap7E=%|EptU}6RBnX z45qgL;cA?PNTTWa>fo!UTn1VtB7ihy|0+0FL-|r=U#iFY6D>7BO6m39-0MY^W3WIO zFvTJp+AI*+3?i7#)x#GdfB>Koz=mc*FYLgrN$TpeCsUA*fkp$bxluBWThOV9mw>ga^~oqlPk)3cWiF(PL;&$KVdZ^wq+>ZzOYea0qOR1(dP$D#Fla)>i<-m{S%zJJN(UCvqi7iQ@n-aqY zfOi4vgP}pXo7@B*C@d|E5HSpWb<{s{z*PcR_VLOlc-nSRAfUe}N~0Z8;e``*8fl;8 zC{){@e9Q*zkfjTkDgZ?<3L5a6G!H+0QOiGtV|ADmYz+8<;uk@Hq=^gw^##RG1K1Q@ zCO;IPn9mG*-Iah)Bh^D&38b&^i(39ceF(yjHtu>w@vps#MVpGmSWlj9wVuqVGtcSR zUqD%f3s_HREs0(n0Ur3Wn)iv51I%Q@saC}mA##vygMEK~I)5)%!?h$*CM%nmgfirG zqMDq(1{IEoFtsL;+R&<((lj=Kq)xlFY)nWOos><~`G~JbX~U`C=yI48>4bv=Y*#9k zGW&iKfzCP&tU+fO_VXsbsgrj{wn-m=ax+bsY$^37X6y5fjdnr3XGxi8>R4&Tx!cUO zDY`7tIWoZ~20P(=pR5EMYN$vo{Jv4&R~uyzFAHWF5|0~EH|gpQduRiFXYFy)BZi;> zdO&x5#AJ0C+-dV2*P_XcP(gob5Sc+EF^;Q2w}#3i%&K+GtPKGKZWqGd=vM7g&ZQj> zR6N=0g%}VMk0vuPf8yS7`u60i$#8&Hk7RIad&wXsHjd`}HfbVpiC2BozY4zPF%PaM z?v0oVdM8iSa%$%`yxNcOr+wfj-Jo^!=JKmg=V-T!qe(pd-qY6ZtY+k0%mAXaHb=+2 zb&lU3tHUDYO>$6P08K!$zoO<~o>ODY)KclLDOEL>)-n6u3CDE} z(HXDDyUyXJL9%9wM3;Q%m#LbJQNEEaU1JA1KOoW-aVkKkuQb@9%(Sqc-DD$t57WuafO_TZuGm?8De9XsZ3VSK?Wogn z_toatZwg}lp^ip+gJ@57kbhMEHsGXqGeOIKoU`i)NK z)Yh!o@WfVWGo-pDLdp$TuAof9^t#Hb4;>=5CbV-JG7 zOxS@|Z$d!V+T^V`Q%qJ(aL>cc^GFjfy3=BZ?H9YPr?dGFB=Z{0&yg@zG-vV0P#u+g z2mSUcO!Yv=B(t0&zchcMF~23M{V}x1;o$rLIIzO@IDZ0?$9kd%u?giwgv{G1ZK}&@YdpcudiRx%*oO5Eyhsmh0JOXE#yM#h10Pt$y(t^tJ&%)^;1Nu$XNdvucWkRD3 zVHXR!C8(fQSqXfO{C-{q29ZZ1F!^gOKFBUwV8LsrmFhPoT%tk|gr*;NGz zDDR56ClkHm02$v~x`KZclo;H(Nw*+T8~L=eVW{?p=2<&Wd#&`gH)$nl>*K`gaf5Le zJJ1adJ_4*F-MBPf+4S?KX`aSGyW;TR@BoI{u5OQt44LPX)@YjKNwYxaHnfe>uiu=% zJ3QmA@_`>u!M);MM_nNM_{b}?#SF{d48wA0 ze&@`ZMByUZP9~e-0-sauaT_Un&oanadkOWA=y_ifbeY#PnQp=vG9yN4X*_{4l&a z94pH>AL%VrF2r~a60wVTHgJd6&dgQa*ebB^$}tdkb~hMXCJSno)nq-Axh?G)vAxnj zu)}XDtNv)RhMgR|Zg}smj!3Y7b9}Pm2#c72A|wO zH%QV1s-$;Hn*yezbd%E{7BMlMs}w;8vCoX?VVV>$o$c$O+wR?l_kj}~b!mh|^q#Bj z-Dj=mGs^6PxJq7GqG7K{tO-!jPMUO?M~>{GDUuK*F2pKGz;#Ay<2>x~NO>c1b_kld zgn8efIi^-t4E($xqIF7yBu$6{?hnkT_Q=2IwbL8_I><-JU7y{=J6l`Nww~`iQ#)I& z7c&l zd#NXiUM@B%i-C-fLSZ@NS9{4=S_>5&)N`IyxU*JB)Nzx<@9E6OtFfku2se76BDReg z*Holv5e%l*c(;H)q%}dpZuSLOK9NVmG!%9GWf2Ucp$>Rg@AvS$&Hp+b{H0Du>O2kd ztT!aaCuRssx&z&XE`{zm&1wV}QGM4M^5-`EWu_5W?b3+b$q`H(=^LbA=naEzJSA>C zNP*SbP44cK*W9dTWf#ue1#jYJM|>cUQt?)F2mM4?CuHI=E+?tgi+}$ONi%LoFw5%D z+YV^jIP)mvry2XJ<`TMo;gxyqoY9}SA!%i$CI9yso}WY$SS-yDk%Dz@jBpu;wV9ZW zbY(C`#Vjd?Pn#_rQad%Y_x;Dmr%xgRWQfmat$6g(J*4%Ld_*J-PGR<0n0SX7!mKpa zxJnLx;QJ47aEl-};+@P2?#!-WM=xMpbQscoVv*@*YvO|3kOvd*kPJ@twsvh70CR=5;rrTTJf1r~I9rFo? z!z{UTuI=wuJ5!ZLj?2K&)l|+jBGKw_A2)=rj5}q=aUd^aA}SZaW4M(+76aJ#Cl#X= zGjrhIX!gII5B4}mHDeF3r7B?>jyOETcu3&uEgMoN86{mEiz`Z$45;J)AqmzLCY71y zK?%nx-v^Ad;@Pj4R+;?)fQZRb$2cKI9Z1?@HGF`X?dm+I0S?2-ve`W>OH^kSkL9UjfcQSKxK0*e z(R!}3;jV1!k<5!%o%~#!Vl!GI31OJn_-xcLmP2l+5>w)t;0a!aK5%w?c6ETE*&3Kb zlV$TE<~Jg$LLBz8*}a(Cu7|e9j0nsdoBpD#h^jWfdVolxAC!F+%fM3EAioboqsGpH zV5H21v70`%AF`31>OBNkO8rGNz|y@Zzjh(lRp#gyuo1b=MmRs`rqISu!KY8OTcd~r z3ZN%ptFl#|)5&9jpE*06I}c19^vQ02N=P)#sDlrGXhC74~Us9#Jv4izbc~im2?{A~OW@0S1ypK47DQ zr8@Zo@hSgr>Z2!zE5grQu_f0IvFfGY$tIqolacH zlpPdmRJEU{@6LFg==t~Wewh5q=BJ(`irb5b;@RUjsuMv-X0I!2uv&fUNH98kqq4}z z)&j0vTDui1+;Lw{Bs=ph#_jh1dW<&Oq#P_6|nR$>F!UUn<;|BnHISTA-J@eqpr9h_n=E{ijpOO+ zj07gUYf7hK755)>^~Wj6lhn&pt9`#qe_FRew>@Bm_Wjv^n(Hu2pa$M*y?6n7HtV6W zXm^}--k9KXdt6o*S{`}yDH(S)O=vU?)#-FFRr`Z!fgF6_79Z9Pb|m;c%kD07ikju- zIudxEuQ@}r=td86lIT8VxSAz`fI&bztAG~KP-OgHa9g{w>~VvO!Q9`~sG=2yn>2^@ zQ+#xP(xaja6fQXKijVJ^#gE{Iel%gmBb}-1Fdjt~wrc`+zVm_(x15@g_}0rJKyXs6 z$YF>}>RV0emrGmgN&c;qoQ9)t8B6ku9_F8dK(zQ(K16C&6i$}-mN_krTG%vE(d#3W zjSFPRZ3zYskPrw%?InT^<@AG9)T!@(q(2s8_!sqx?sA(J7%ymm#SyZqGyX|xAECC` zIc!-56-YS{*Z9exo@g}jKth3n$oDErO_lwt&<^v&ZCi1ZG8jX~7Y4}q0V4BS>ToJ~ z7c6My08qT_m&-4(l9{;I-kQKj84J?1J^&q+EC8RI?&?HKjpcjM=8@y=c)^9|j7*-6 z!a+a@Fu0$~_cpfcF~X%quAD+g02psRox zMwGb|S`abCGaK{vKa0z`tD2yK@g$#GSx5FJv5JwkFY)|&-KneuN3PAU9lX6CWMac; zne`vew(1Cu6L~qMVPrQlSMBl7#)Ib}`oHQhUgF2wAeaQHToAS0Q9YClS&0qd|RfdF|pA^n3w-@W(5%iro~ zv}_fPvZ1ne*F{>r2h3?QS2e7D@SQ6-8r6ituMCFx{l;|*WUf)EP?=K@y*+-ZD#ZjU z+6k|7zm(tv*3Dz+jT7zk&va;ww8qsVW7;ckzgxFY}OtF^ZQjb~Sxb*XVJ`&>-7p4SG4mI(z|~Y>>K|+-46MCu*X$;K{$zXaDMxHRo0%Cm z?6*P0$l3?K56NVeTuDQ2rlz40`H4Rz5Y=@ufh?#EdJ29q zh)nNr4E^vX^pWVMhRevTa6_FN?_C&J8JY9^O*+uPu}V!20Z1LE@6H}#LMB1!(K*L@ zoWWn6SocfB7{t|C;A)j)6Pl7^Te7ae<}(AU$Rthjq{rBB-+!!b)<3uYZhh={%LNlT zQAYs~CjTH;J5rY|V~nl1+MCtvxL*u-e-s%wC?Z`J&#flxW=0rhjmCTs< zHW2DOLL$3S&`>YafVl36j=(Pk9lZt&)DVJcXPmI+Krmk7sVB(#&I=QW*HyRI%$2N! zzhXpw&>KC(R!aTea(mxx6J-(`DG$NMeW;JTo z?>5YUuft`V>#g~DUTtW95x4{Qb5&Z-Zxa(>mpQ4K6?@oL9NiAwKiZ5|5mFK7W*nuF zpT_9aqA42f!DgI*JeP7`4uR0_+lmLUlz52A?RS?u1(?m#8L~FbOe^h==G?wuhZQ8H zuVTMF#CTXmwak&;xUBXT?3Iq;k(}jRRF~pQY#9iKduG+T$@!5nShn+4hL!~low5(J zD3UEQ9pIz^C!xonX=Wc?Vw2=a_7JY|*$T7#(eVuY94lhVr{BM`bkc%&>B91_&CW1! z`qeo#TBXd!Ilc^oc(da9QAxsK+mO3JlH6J)YlW9K>T1STUZZcgtwUFcn;TEc?cpk)Q zh_f&GMG!6BM4X;Ur#QBnGjOj*KxVIRHwR-^{82 zTj~UHGe)E{<@kjfGFq4i0)yX=B%v2;OL^ZEaZ7y|vdc%pcGiRlTt0LcTP~nAu+4zO zf}^B?%rU4v-GU+ak%>}bzyy|EMvCB+huC|@M)x(e+*B2Z(XeJHo(BXcSs&ko@h+6eWFu^Y0NAr}-xq&>S% z4bG_@7XS!DH~IeX4Eo@Tee(coQ}{pxT&Cs_RAvduf#+SII#NLtqO zl;9I)azz^REX;^%w}|t42u3-NgZ{FSUB5ngY5cfNq`l?+%P@L2s!AI6 zaV5ztR~5b01B|IibEi3cI_olfkqi>cqAJ9O+OjFtV0s*>bMwf^S1%REOnk*Xal}OlZP=U6cZo#2VzMCR`XMs5N0;1b6+!l zYVWvG%AxR7Z3B21nCFp{YHdP(IB_J|4Y2mKX4(Vt!4y)SvZ-hu5!7>ORUCO#y7gW`2n`! zZJ?PCUUJYrn4h5m!QIT^vDH;t9-4K&ur6nVf@US23Tkv5M4sJ_-+%Nan$E&l#18_L zGGm$efGmG9NQ0zO!OjsQjL{A~Fa<@PtIrvk<`5)4aHX)05LCsG_+t$++TMyy%KIgI z7%xS#cSBGXZQKmVb8wtw7FHgTtb!Qwyn^aT1NKKI?&$$WnvIs5A5H^eN9Z<0k&2vn z5e6hb#V{E0PvSCx(^v}grNzRi^CazbB$BcAKonO-G259|9_@wf2W{nVL1X(^g^CTzh#%38BG)CeLq;5VG2zz(z zACb(cN7*CEbjz6%e2*_3COtZ0nOPiox%bpgM^Df4ANlq&DQdM}CaGZL7-(V93J|lA zUYv-V%~W`Pecd_!v9cg{VB}OsN*(K93_GfGly`{WybC~&&S&ugp~)%AjEfGc6ct85 z*6x0HswD?tw<%U-yG>f#J4;W(C0}l`XAbg+E{5_L%MYwopNzM4x;dL9KO1 zf84I++$N}L(dTVu7y4LUqV`~LE=|UDi+hRBfZPu?`{Ee8bpG+;QPp{NwHKTKMoaEI z=UuyLt4bbvNe~8m6)T-Y)doneTHfLNTn-Aa{Sy@GPT>Gum);PSaTuAGBS}D(L_teI6G1(B7#Pj}p)n{F* z;-Tbw?nO!Op=fo+cDpjjCWU)R-+y~K+%vrWlJxp1Jy^^nDFbFQ=%D-psrPE zVSkKzB+O$tP2`M?KPKI51}g-GXp;WMWqjnpv^m{?9>zc0RcfkqGM2=7jJk+edW7i`oloY$QME3f7C^B%zY(M`hL7fr&?)miugP$#1%75j>a5;hsk_SRN? z28`!gts}Ob2XYNHv$NN%_DRIfodp=yYC+dmlDOF&AmS#=CW%Sc6*xVWS9a)ubX9OQ zC@I#Q;?chI2y1*qBA_@3eg@o(TWwTRtP5C&Ro6Maq_@ZeUY(Uu(8N`Yk>r^@KRD4ZCfwFKeBlPIU=JeIp#|}goT3RqQfK~1<2d{Hg~C&sS0PUPuSu>H`M@& zJ(%FryjOg8#js2@07yT3H~rNhIA!Q@W=!cz$Nw7nYV^bs(^*{2)m%!YY^@!L<6zsI zf`dH;J%`x9S_JizzR?{{foPo3!v{KxDSVU1L34Mf8|KTW>a7%`D_SnEo=Fr;z1scq zgK1vouE1I=wNnel3E;e%jAr$)bF-e6+N@-H-2F||TO13rO3aec1udEtmkbS*oY1qWH zNkG7iuo!^sn~fo6{4nG16b^-KXAY|!E?Ri+i8UX5$>_j6!V9&%(qzhrGRwbVk@{N?Mo~xKi}4>v%g;c-*5Sm^LW{c zU)X%e%=Oq6uGP05k?tO-=2bT7Ru@;iU+?#p`i_B6@{NY=MYsCu+q{%EYgadW_LPVP zUPa(6eJLJ-TJJTZunT5&rSDv+7rF@P=%r=Wd;OQ=DzAy)UyKMY z*aOZLc6~g|)YQTd*3$te4-#!se|h33^r2hRjJZn6XCK_p&dh8DXDStQ20L%sBC{qV zhk(u5qQ!N}fB?BTWsW^yQ zG(~uF{vqDe=*O4IF(y(yN#~_GcI0EUg~}VeY!dW15n)t{x|pfTn}-I0^dTIq+=Mkh zl8jOMw9G`7w4uTZeEs=Pos)4l@GHPWx|Zoh{O+Y&9JLhO1-*i| zWMv>V&f0-i+`tvpIJQb}*(=MN<;9JcQYfyM+039|RfRPbX_vSd@Jlo5A9B1??*{-b(m|a5<|&tVFO}X{*imLX9h3+ z?voM~L7o6`XS=oaYd6UCbG7|!E~M(v6xf2KA3sWR3@IF*&Gz1#86~ChNd&OG;wU4Sp;Rn zm@e$w@Dp9?u6#x>A&IpdJ{PK0!*B4VZZ`36R*91Wl_J@q_A2y1ayM}8q#NAz^GUPG z@3LtRc^2F|ZMg~zT}qNOa!>Rfz!o@_i4GaV&X%7P+0f(!XsG%N=Bg~uavO)l)1D?# zRCLw8Kj06uLev=Wm!C-f*v}{YVOGY;a~jcQkbVjw;Lx9TnD-cv1;4+$#plGw&}hJ(&U~nFYdj2YOA%gD4koajER#jH%LF# zST`81w0QH{hCfj z*n{`KLmJ>4#YSVG%$3fvQ6SKuvf{Mi`C2&`1ab95r2zvmXH~8ilV92U<#9jo^&}Ta zuezUjS>%}OHEk^Yg5O9^$Km6>O7q3(PL9jBoum8(oiQ$e!zMrqwZq0w#z_~N^~n&M z1mJ`PW*wcU(?8+Jh)!U#lscHZk{YND9G@o0Qd7>{<_dD_HvjzI|N31R_(jF#e@5?i zVli75`BM-@VoaAG4Kr>s+@&-$iwuIuv8KR*<-Ee8T+w48XoDd6QTQl8eImn6kN_xX z%D;km)8_h7nGYNc4tmMC2^FJR5NXC{Kt2xs#1%P~=trf)F;Dq0h$hl2&TbSDMU2%2 z%1CLdn9_K-99NJM*!4s%V)(B`lcDYgmEcb}zVa$hqXf} zkcvBl1Lip@At$>0qfE)9z@|C}d9Z}_8&aqruHOJoE6253V=fk!t*EB8q~$|fq?&&-+T410?7LyQ)&CUY(@`C0Lj^j?U<4d#Dn zsjFmUQ0*C3U_Ew``&fFQNl@0v0SA^a24|6>j2>fcS<*a;*tKgz`74Xn4 zc>coM(%c|*Em7>xTq!(!2f|-B{T?7c9y^OTe~ArFuw@`aC*Y%y$f@c@u_*`yQI<%= zT$p)gMX1F~gkDv~T<@Jxi}yJ=manH~ZGxJ8eK+?^^7qa?p7{OwX9;ngtcsia2@&AT zLCrkRfWa~QFc0Rt!GRPHwR2{|IOg_Ghr>KSw`Iyw%Qggpbb(_a07{6=2oXJn@Mgg` zxX~mlRZDVkvqWRyBd%8|Inm6c3#$yYC$y#=3oK7qPZ#K{NF`z7T@Zcm*p1reTRy{h zFACHUnC5Igz<}g4IH3XMR-NK=%?GhT%pHK`BRm5}Les)O82`HkQXn(|X4P3KPzkT* z%%l^Ip*O8WBws80OoSMkM(l@Jm{wNX0#Q2bF&Mg;We(W}3J|6hyQfdA+gzasnoyHh zeC3X*=L4_Jf`LVnAK2b7n#sb&r(-swxG_QkBRiTJHM=vdY=YmN<`NA(OE`n zdT37B#1SDvtJ}1-sDkH*!0MnjjXzy^ffCpB067S2lz#OrUmd@cRB`W@A5LfKp~4M@ zi>yK{C9@|NO+N5}EibdrjJ_=Q#glM4q)I6G`KjOfx;~1&Z6Suq6$Z^inM;5eM{9c-tH5BzIYtC@|DP z?#qhpe;#S7@G=dEVh_}QUp{;bwQY?xU48_P-=8g@0q1y(L!FhUI^(i(p39FsddvMY z{l5-=W?At<)2Hu!@_}r(I}vETkSa&9uxuA00 z&623d1B6MtMg;y5r04-WIC#P+uf=Y4Xn(8IF4qO zaY|#5zCGj9_8_A+NQX^U&VKHEU(Y}za;49DKLB_&4@bCwkuF@+z(zSj{pjEE?gGY% zCob}g?Dr4ijyc(n4c52Y><=(c%eTpY^bA!oPL>m_6654Ip_@QmQql{f@UJ+Slw?S} zZQ#7gU4mnIRq@5llu=A#?y~Q$cs28t^p?+-#bT}{L;WoT-|&Y)&FP47GK291YK1zv zW=pMjxIV;e>@5wv`HEpLxz`paP5zDdn)>Q{&9II7;lXHl!kfG~*0cVdXB~(BbExe9 z0cV~wSdRlg)Sm&pymSSB+g6-4=A*6hrB3AJoyg{sdbmN|4r7p59YCB_%Q)HH3o9wk zbr-Hkm6!1ywfTTkTxV?;&GY5uV&*oOpWspkchSDwJXD)zXHjd;L+&AmeRRBfa~%|Z zm>?T0L+G#GRt&PAOF9ksGO;g`ZGe>{{N+ecj#X0~lV zFdLQI(ZRvcq=v}kWdO*P##?&+kB|8kqcHiEF>x9aLJg~0xl`>%6}k}TEP)VV*0$Rg zIGekNQn20{TV#!AvMYUbe0*5q<(qtttW^s93a}@Nc_!1N>M_*6@dj_yhG*2;<%B=v zZkaXfEk|_bcv!ZZe$I2sWk{Keq7kha8i7;AkDiA^gj_T}8|TC=xtN$VoounfET#@h z8uQF&)`U=<6WvMR(+S&*K+T%eFIAN?Y6>2*aL(s%gC1&lX+SrJZ{d4eti?-hLJWjQ zRTi3GD^Aj)$7`wcjP`cZvy1dl8J4T-`LP%U-Q;dH3HZqr!n{;bpx-BHm)4P;N6o@g zQOA$iYB&VOl~$`rr-Pu9_Z00RZJBG%Gdez#a$8F@3fs{HwUS>yHK8gNejVmLaVjA? zP`zmyh#rw8<#EHpXXK&0l8Bk+L)15%GBis(apQDNs_Nw>9;4VOxB+8!)kxUOGt4tf zMA)<3yQK5pJA|*}r-wYY2dr*6*4$FM{XaRH>|1>j}I-Lk@=F}H$+8Np_Rj8qtFR_1r6IjFFzo(#}L zx^55wYk+(;)XPZsR{6*O-fIJ9Az8gP@43kG6JBHRr9E>$zBc&;7`{;2pGO*?7y-kB)avPXlJg5}FgKpm8=q<-|596Tf^6m0vk z(tX^yc&OdhJd4@7e~HkQcu-#3bCY(&jzqH;NIihTp{mS8GIP;T-lPyEBc5m2d2G?2 z1i4KUeRgRA35C*CvAho6T&RsV8QoNy4Rv<(kB0h5cZtpQHspdslcz}nnD=WPji}IN z=XHZ9!3`WLPSd2Ad_WM88*4-TqK8S+0D$RLGASnF-G27==;4;*?a|T|z;CmYTFyUy z?ai!_8f9VHd$7SorFYKUU@i_`FA`i2W;a-rKyPZAWYQHTzeWfP69)!y{Q{tZe00F(?Q;Y}qeDcc4c5rNr}x9S>ymE(fGoewWUcGBJEBaWd&r!hRM<0_jLn^7nJWIlH^n8`uJ*`!&`S0X=ErIZ zOLQ(Ym_hwC2oysFpk>>c2b;H>xVLoHPVR6S8{psfuaB54SY&bc^zqx{D+|^4B?@g! zf~{6$u*wrp@V4I-0hALq*|_Nv!GzCkuShvPgtg46QR=fM(YEJVP=ZiYPqU~D7=yt8 z6x~Ya;!1I%LW^<^k4nj0VZeoG)lz>##LHD|neLj@Qgx8@kw0$M-Xbb-r+YSC=eKh+ z54P~PbU#Lz-DRu)!4}|Hy33g?6$`91=O4nCp()p}{IpDuXmOQ$C)5w$-5P3!zSm^k z+E8=M$tnP`wfMDaIzjI3=6N#fwRL6kyAXjZ6}@I}s7}()q0Rgvcwdu_QuKIM=xEA? zG%KHYHmyuezbudy;sgM=2Wha`Tv3=qPtGrC-kUu8=0f17Z;YFA+H4XV5kLZxge<*b z;1^NFi=2zUCc&}UtlXLWGzyZ5hV6%eeLm>CH$07tt5a$-Ad=g+9DSub?@jJ=L6Vsz zJOju(JgEj}?g4f~b2JH|sam!vc!96#nfZ>A@wkZXaGj2D_vp3o6XXWxR2SmC*c`ixPMF?`E8?Xf8WvZgU0Lt_ifGAmqG>T$IL-zO0&>q5zB{1TWo z9*Y5v0o<#TrE?>`ft z_u0HUyZn0RLF=)FMjp~2ADl#Qm^BD4vLa5mL8NVS*U;H$>UUuAf!j{JH+Ztk__4z3z(OTC#a@uifp40 zjxqIJVq=4VE|=Q`W*Z|o^_94>p?WdylH?F2KdN_^7p#j%l-UEUOq2fhZnEVIbbeS2 z4hsOxSgnG4P*a%EY)^;>i~?)oV;2^hIh&KZ1WfA|0}u0=<`1$No5aobEBwm*n6J2i zwX3W?dFMx(_~bzf+puNn4OHb3v4lCaBiTr-dfs~-amf-()%Jy1y6XMQvuMj3^`mXj z;|8la7x7lQ$Y8_)O{???i9y5(hC?2^2|#g($sRq-+}n&iD`x-Nx(U9L?Q&g7;^X$9 z?go(@Q;xQDdDH2XUA?h!fcBHg;3=BWj1F<&)iML2nE{dGo&kHCA(xZnZcHyLyMCPX z4#7m)BsHuWw!ivi2fp_N-^4&21Q_=T}-K1^<##EjDCrm5D%ug%GjHVVlP{EMiWD>CwkhuVt-g0a#L!x}de zsm6txVb=8N09R_$-Qp+pdic}VY4fZJM+xe}P2e}j(%@~cm!|Ut!O+V!{7uI}ZP&Az9A;Q|U zI{N$H`9#+QW9wAzAsRX*Zi*(mH(YU~F9CQ0G)7$VlCdMB@1rEMi=*~Wg9Lt?9eHkY zeGsh}gy7;ew<}dI>1qB+eF)-_+P|fL+u7~(PBMgi{Sp^>7-cKiOzf$5dB}Op&3ZeN zEs=r3K;adph@}UWB*b(!($U}k2JL)GTSV}MlSqJrbktM$2_Jx7kW_voUSDU~t^YT+ z2S9@ijj3f7u?+x|U=ks7(FER)sM-Hpy^@%W+2A61F%mWjjJR~4nB2(}737n_GO(zk zgUNtfqrVEcwiQL(=oT0UxlO#>tfgSaJ6W3mf5*fR`%_T{OFzNZdZzw&KGm}1a~|hk zzVLz`RTBhYF}2(*5NQlcOUpl^1xvF4q6bZoWMRi53SI+=1S1%4|Ax^vCD~*oCd-^U z=pcng!{Cm6k+~RsDS!Ex>?cO1ZmWeqp~I2wFx}5nX@TEij6)&XI*KaOeE`yl2 zm}%Fqv|A0b+c-Nu*{tnUd(9%$$E&UO!uR9hKXU5;*-#cI6L+I?A@=-QgrJ;cHt!iY z6{J!y$I|$4O{wsm8is>mME?l}jrMS{+OEJ8lQ{lVhCar=`3x9khjrMOL5NIN*%*J@ zc6Cbh_B`klF?bb(blp>%``J)Fw$o3oA`Y7qA{xFPy9#f0)K{;G^Z*+kUt02|4eX^> zdYccM8lqtd5dTvW6Wj5c{m0e*M|^9={H+c3dNOWhrsS2*I0Q7+LrxMl;qUD((UIIW zcNnBt`(Q{{PfQJV@x476PP1^-8Wv6ZPGVa5_J9Ac6gc*8qAW}J{rKAM(aGr%*^Ps| zHW7z9&5^XL%YTz4P)v=f7l!sfW@v&!jKvd5j?X0vD`Zcf>lS5Hn$}tkRJK zjj@F00^;bLFy)b25@JFN!%W3(!gl&0I0e3dgvc31FhJOVdE}H?9p)=Ib}eKlskq0e zOL5TbPMe%AhW(B0b%&?!3xnl5N9GvJUILA6PkN*Jx+mnC5tM3_z??E@Mrajiv-P2! z>%v(fiEePUNfR)*(+!tPXDxKn`Pmy#Q&7kaLomd@0u}rDga|nQ+YhrLeI9oOE@~5v zywaKJOA!imyNhvVZp>j-EkD6OC3KR)u{sI65q2(rYX$VJJs98JPtFZf;;?fPaQ9k! z>N#(rI?GJu4={ zhJ7wOn<{&r$x=4_2KZEAMw=jKWy;f@+I~V}N4fSRc#Bch2VwhO^jA#bkLwYbJl1BwHPW1%{7`MJ_L@Hu(NBkw7Lcw$~kmy5<2rlK0uKZ*&Pf-P(BjAEnDP(KbmQ(m~CoYZ%U%AL^0VBKJJ=CC2DUx z`H|Lq>v?nQMRWU!+TQx{$@3q#o~XZX(bN0QP6EHTErkDUw|4gCmDu9Z!saSFAXG6} zJ6X{kOH?XHx0g-gOxZnHdnlXnHt1#uedo=X+pKX+K=}rD<}PFL^~9OPbf7zR7Br3* zgv$@-bL5V>I1fSfA@ZcNp_he&*iaN>M6Na|?xUtr*Ah2j)+g}2%-%2TipUOxOu}le zN|u{8T`fmaiehwie-KAh^h{NI*6S5g9fJG+B$j~BRgpOtXaIGGB!1)Auy9|1+03Kq zrZgKsnZh8CAh|@dX5Jw<0CY9=aXtUfvM&c$XJzgnH+TGsAZ7Sl5^;k6x%>V7Fvp%|VufWY1@98%a|p26Bwhc1&&N z?ttV*u-aA-F0_{+ukekI{EVo+`P5D_KN2ZdbdAKrJ}$EKahCQT^Nc(`dV6wwcHNPv zZ75a!fEFym+rHc3Z)Q_shTL4vTJOyaPRCuM1MjU3cw?OS)*!rTSq3wsT(sQk)g48X zYQqU|wIWv1v{DC6$#V#ImbnL8 z65Q#MBHOB*OOTIqj;xcnfg4)jw^a4L=B3`UmzM9Nlbgr}1#o(7-^rT(DB;8{UR(i_ zG<(3fq0ItT%fgG|*tctI1TRm+852G;2sw!uMUGiY;wgNHbE*p^R}zSh6A5`WkrjK3 z4DA$qw_y~i&tT3hJ-KWH9n)E?B>euP9^X46v#Yq8pXqlwnic+}Mg!4(lp^U{--Kz- zZXniij914Lthq^WE;}P^6VDsQTWaGGb!O|)rbx&*?_Lp4((s1%9xb)}{*HdH0GEHC zi6Sv>tF?pde!EXw+gmf!WKqcs?nYjUK?g1^LglxrnmU zAz=Gm{(FCICK zH)s65c3zE)hGI4!ND%}Pd)ZJ!M#6`lL(E84*q4AsF7GlKm}X>aj!Y1oSK82RIHD;B zWQv3}+&SA(d7+U3_(09ou~))aGm)m|t%rtAa}x;3bks7>@IvS&N!~C~C|uB+FR1&F zM?+-ojKkh4Cgdayd$g?rKY+qg?FU`?+`b!!9PlEPjG45k3&H*st)q@Vi3$kJEwqvV zDc}Ft8b?_T2)$4$6S{f0(YN*vd zf;!q^+zPwnvN#=jI(xwY9nL@cJKOCZ@rQcc(!EwOy2o*tvJu9BkdjQJo^7}Gwq_4~ zslB&*o5eJsZeYbDLnEh^I0duAmUuBb7z9afz9{LBYaQ*n##SusF_C0ny-EN^Pix~3 zw)y2F(FXffI@GlJ@##$^EP4Nc_Uh>6H$O;zw=X);+-b(I=H*kM9_8^=Za-4 z8f~E_NoXTKr7fdSWksN}A;he&Cq_bOsWwF!t>OKd$uzTKij1-6Foi&oTVqeFE8p92 zL1;lCCsZ&^hzevFwX-Wu9i9m)T^#87A_*tBTUW(X2nS#hS)Jp8d|;g5gPZ~)7ymX?*?G^2#BuCr_i zLrCJxe@Fh=U?81Xav8ei+VuMd2ZaJfkO@BfASdtdXDnH1WhDDIH_ zIHYzm{#!3%i~?_U!6wrbf9oZVbxfz}ycp@*5nZzWNIu_kYGI>pKY7}E z_H<^Wp1n~Wz)kWt6CT*H&G<2!`LSjaH+-83;Wq`UU6K|4vJkM16Pz-1F8*AciL3X1CPyC#@H=hYobm^5On6ErZ#@*tI7K zNoNiO00P{hVBySBj@dJTWLM{NXe18jNiT^uEgVZj zA**6)0(&J?0d_MBWdipsBv4`%m^}1!o~L2AkPyTZ2ETn|e#0rO!L!Wt%A(+S9v@s9 zhB>#U5Gw`IbrNxlxMz}zu#(mGqV{%fW$eeD!RDE zB>_Ahoxw8hoVKLc1zp-1$-?m{sws)i3%V%f1`5-Wx-2BLYF>}@^|Lt%n-;l{IDMK* z`frx7Ao30|#%CtJgtJj1hSB9WbF>DKK?V%bL8Ti)LKAy+R?VDdy;IqT5Cv==*e?w6 zdkfd65MdgH+E3*RaTk*$8MbmgZWUqCYXyEGjM8ZsfwCRxB4S6ip84QIhb+HQI#~a4A!h}M7t)$u~Lq{ap9vkudm;p9lpDM^R}a8Sr3XdKmdw5CE}{7liEJu zm&(K0mtH5n4=<(wIoMKYr0KgTwln)QE8WRX(_jF1mGfjoM>ZSb`Z162l978n`yTje z!8igiwumGh`yI8+Gph1YN8z1}(mCb5N&>p_Q+DG-nUo$5%`?=#A2*cwvBV;5(LJ{X zr_Sg2cY9X&yi8*2aixx6wj@!tdC0yVjOKSNUa*cKpl2KrAsR!jF|IVhn{;7v3SlQ% zBb){qi}MEZN&u*msB2Ls*!PUzZa{CL*2{~mrQXECjndq3Xjcl8(jehTOJau`s?tF) zyjdB9A$G~qwh;JLOPT2&Q*g#*lkx}eFMqII5#05NwNchUVh}f$9WA_|t#9Cns5YoA zbvo|8+Puf2j)^WntN-iPlV9J`W&UCo(dHngb>=82hi&8F(qi`HbFwZsCZevX;;?Hh zXj&#!N>RW%1Lg+6+>0@R(QE~^VNI4N&=})t$KL2o;JLD?x&cuQIGN{O7Qj}LTRX92 zVum`XeA8^N+`iG&aLW#)vS`qY$cVaiI3DAzlSvj!j_)v0r`SNLzU8|tpqqLl?E^&5 zh&Y=r^v0w|!W*tqdhw2g2YL+lqc$$+>Y-b%p^lsQ*r0YN!PUOPyKXk6Px3=6!1^Fc^bL z6?aR{?IL`eJ-5<=cJu4;EXt53Te{tN+h3#f$vxem7H{eVtt;F^f|zl zIZ7%427Egwu%?7X#uDoosy{eby3e-s*RSkts5l~Tdv-y2ih)AgBqIOe%y3UN{T=MF zuGn0msv6nhB*U3V=OuS)QoM5VBkKboCf+h$rCCSe+yE*_N-5+P|nBiXUsU5iun>6%ZGt3g$%f4cgS@K6+>xqW7;I`T)(2n4uKio7B`T5#uxcd3T-FNq%4xkBLzr4PBz^Nc+_%}?2j0qLt zy!v@O#Oje;+C)p85c%-tevq)MOoC~lpJ45!buAabb1QVl$_!+_nfuRCk#)azyS(ch zev?y!b{N+50k_J{`0i_`;k}SV>La45gKsh=hRm9P*9V)GyCDABS%I_AH<%gC4arZ$ z`Q5Dur~f@?V{#YVhp2L0VpNMBd~2;I4Srw)LwWFB8I$ZgXtFbaG+-3i4>AGP9p_7i zFJ(*YqTftLr2%M)ij0{{0f6x;PL{LW&4W!&lni{D5-6abZ7t01>wJ?2Ht|Zy(@Av$ zZ2m(;R{}BrKa?)=TuVUs1CE6Wfha&+FHhW9f=o00AB4xWYS7b7g)MapBcTh0a!_t$t`48q!bd0LgT6L}zCB-p;5cSiCh@|CTPkexC?zr0i_i zD|Qi)y!EX0bViqYDe#hlAX%co&D&}OiHD5<29lD+tsm8YSJ!Dc7%*fNd_H*UCCM20 z4UBfAOHqo$D#f~k&14k*oy!h>usSr+QmsB+i8=*yGXJM}j4X=@b0C$-;C?dMh1I9T|I1ms~@PQywkrVbx{fP#5C?oN@NU ziC`0cYh!1O=yV*Vr|QX*d0XcJ!y`37fX4yfAxA?f%U-5*@ib59GO>{Q(vIYiafN$a zxX*=y8iX0=#~R@3%5Bt8Kc9L*JOGEo);(SG7!fy{Rl12ZnL_>0B|7&LZNmM$$6r=W zGh0NsyOMCxm=iK0xd&0G-iDuUH7u=Tty6rC+ruR1gZTPQ=j!0{e&;bxe9eau%)rwp zvomj@`4>z!D)LlY@cnX*C8OfB^N$NYP*+Ko6Va!y)qFf&#T3W!opj~AIX*m60ufZM zlPF;Y8JELO;ma!s72qTs_J4zsW3omW8;X|; z(0T6;eHCTBo-o*Sod}Ti^7zDX{Mm$o%?h)W` z?ZaxQvMcF!x+@iF<3(;BFsjdYMMkN*l*=W|) z%e5AeL873`qS-t!r_i`;R&k)r@f73C&zBbu0XiryWR+~0JG0T%#>EwW6D+pbBdzO6 zAT2p`4GP$+$plTuyt{YnI;6JE5AVWsXzr9-2mrB zK9?LwCi~Iy34R$R;&v2{V{78EAMcH1lEjduh59qj^<1Rv0o*Io=1aP`=x(2Kmbjx5 zffV#=*Aa(GYc7VV*{@dZ%~WmOtqcT6!$ci)HC*rFQ0)g{)-QU)teuAg2!o|ieW~+& z2z%LS$Ph+E!S)AX1|#n(rt|<=Xa5;Y0%Do=iJ+6n^eG|6GZ~REUV%3P=6s}Y)HysV zgDz1mKqrlgY*pj5lSh!1a74fviIj;?^&Ni|fElCprH#ihOOwpTmRoSAqhT6~C*oxh z3?mZ3*v)vqhv#knw~m%{ttT0Ka(|?6{iwLB3bmp<0BU5KVCJ$SfuD6YgwOXd2?qKT z4d3p!Tac0gZ;^zDAkJEv6I zX}uu9X@~yI#cUiMlX#f{pa})#Mss`e##~mhAQ793=ff|Zvk$+VqN-$UnxyQ-RkGti zqO*{ml0)2@IG`zNC<8XwPpmVcsPh^|4H^PGAs3F$!m9F93;fUha)~ARSs{XXAJ~MD z;04Fd`57D?A0M(svxIOmrcrJi*#XwQz)B<@{LV51RiYUvVPg6rf!ZtPOb%o+p-#M~Q$!b;IgI?QbtBKp zK%B3hyGXIx?P=@9oX}bY#&w8O5u9O|r^mK}T&p^P*`Y5jWPv>#)OroHj3a2v+WBqL z^oenZGghotK)4_wK-(>%se?kG2|I}3Ih^NAg5v;!i46^_So*7GMH5_Kl|(!vD`xse zgvALm=or-SYnFwKTveL-xl8g?0#>~qa3N#XZd79_I3RosnwvE$c_SgxaRe8~VRWYo zzA_?tr|csdsFMN$Qvq? z*FR=34`4`$@;fUX(RhJ-x>ff-L!{OX8S)1%HwI)y}@ zNgm{a$PObb8LCb!<{+pijb;E>u^&fM&!k2kGMcl)3*!iBbb^}l+hQ|*U{4%_Mmx!&#my0f+QbnC^=mfGGTrs>5@x;BTyNxa9NsGjNXj(W?j z9LzvdS1|IWfJxI+HX?6dkotQ*M>@U7bMKRS?8_^0^)KcL(KjsB|~RlU-sQ27|{pu!Mlc z)HfAC(~~<~NIcy(wOy6kdUb6iE8j~@WTeL8pq+YhrOb?lc?-iHF+JyC^qxstkkS+h zf*~igkeT6FCrQC1>m_3BDj*J6k1oL*Bb1y-v)aGKpEl9DWP2fYvGHFxBDMl{ogV(S z<&P_K9>K>|L!GboNA#yP;xA6K!N)AsF*1w~>0Eze4_AC>_lM1H3iVa&_zRT&XOeksXc~wuPtB+HcnatDZgS6T25I++Q9y5RZMSA&gD=mn;cndx(jU#-5iVb(7!BhhgeBA&X3%e_@3ixigF!k6|1t71fgv+}`0-w=aSBK3CY=fdb26#%&*eyf(khRAo7rPLq z^8lgX0j*$+Y&86#UgA0#t6vJWPsF4sf4Rr%IUtPn8vc3L&?pkWbP>baA|e%t)SuLI zPW*w_a%L&(*nuVJEv)PY`NH>R2H6m&_YvF|8}O*1S2t9v^;g;#798ozwnbB&nJA){ z&QAL$I^SQmCu;U!%VX9_A|+e zjcQcd0D(nGw(0Yl$#)ilSS-;Dx53iqhlBUt=WPC`0f4#1uZ6_GyCAwhng9u2nvKYU zHS%O@cC?2alKWPQ9n2f~O#{5UIadH{S|DL}xh4bGNTJlqin}eFF(dQLR{K#kxsW); z!&8_Y1$d*mU_EWa>w`Onrf2nZvzJV!Wmc=3MJ+%@U_|@U8J#M^28px6Q;#lk(E=8P z9*jhcp?GV)G_}vNob@%OlCGN9L`F{Ai!>nNuqU~-phPqJ4O_Z0)XS?~yyVSb;Js&A zaCXSze|&blt8zWaRMY5vEvAdh@WCH29 z*$O{oWzGTP)og`Ogp8M6ujC!UhA+~L#QJFJHH|2aGUuQaR|a08={(ioz!v+7$)LN` z)Pzv+kYu@l2p~gf_{lgkUyQ=+9vgo$W+xVE7asrH&*tD&4%x>A=u=mhCTbcgDs>=0 zIaP?2ymI;*HXB#ZdL2sxw9JMGnC!?@{v*v`iw>9e8R@C2R$&l$hpPK!#<@3KujWax8wslvHlGdaK6fKIU^qY>ol|HOF7hp77;O};YSKg*p46rZ4b)PXd77B@ikpZyhYph@6N*UJdCsgs;xZMt z)ZtVag)uAMVI%N5?=D|5tiLEwYj4kP5g=Xj67QDjF2q;MI1G8n2SX$+XBSYHDdw{| zcuu2$2o_@le;nNZg3E^L#csy22v25VEED1>syK~cR9vFV^4FHIFlb7g1F~Tg)=8R6 zcBYo0dF&HF_fl?M`^-dS4%HD@NroSA*z5vU2oMgzW#D!B9Ns1OZQmb^+EC{~IoQ&9 zUOH^h9LBMFncPO0#zEF!QVwAl1NAcS1uV>o7nQ7mXd}3(c zX1U0SN;$1Gcxsd9C-eiG6B<8iV`5;NfnOMcZo(*nG!#rJgN2b1 z`@&o~H>e|4nOB`QM89ocv@%_DhPgNngHaH7X&@t7R$hsFyMATUF(*ht602<@|8V`9 zSx}Su;0=ml2q&B^<5FU~NKSwyC#{^b8vHs= z&oN?*shGkduVaoi&O|!#Nm>|y4Wbi#ZpXmR&Yo$kX&bBfUb97>`+;aOV@Cv|C}yr& zc$j%3R@(ypGx$Tl4-@-}#X3hAn|gB#q?`SbPO^5=%bWw`*RB(>V{D4wZGoqG(%OD8 ze+wOk`L!ulOC4?>@>!}Bs``7F6pWcT?>at_=Ke?Z-`OrgtR?WfndLPNh^@i<@9N!z ze-b-kPjYF&H!2WmRp-?_t+-n_g)3J=+r$Gw85JP0brB0&4W9!vT?t2FQwcR#Izm(i z^C9ReWZYq~nbGVevW2^Me1%{@T%jvM!G20;f=-LjBsom!Yil51zeOw1sg7vkH?0QQ z%#pf0t^mRPm&qrF)8I{#Nwb*HJr#x8_;>_2oL!YY75_^eAJIEHC$Epy(W`@N_5RJ- z(FqrOdqRxc$>x7~oi|74o%eg{zd`F{*vS8K-XblMrvg<^oEpa7<7ARQ9{IuJY)Gg1 zG5!Ad)%E4YV|v2#@)#T9u7y-^E3rTk%4kq~1KdBT+s=V{e-GCBW~=~#Jckq{**|1w z%>?7y)9@b1IxEVV6p6FAFIGl_2c_Ip&M(_-WQQg*Q<+6-lOqV5AyV(Jn?LitesFo* zd~b4t7`dI=s)Q)Rje~h;N&dot681gDi-LIxy5E4gCJC`jN-V_Cvo-hXXfA%7BV&u$ zy%LOlCAFR0#tj3LEq54Akb2WmKhtspe~6}=<}#Gv(P@zLJvudBfVjQ6V-ly~b4b}J zrpth8WCa|Aen|@U)PtVHCW+zG|C*!JNun5h3ZqE>sD^ny`SI~%`=C{Zv3tCpLYM@Q z#!RnrlPf-HHpmq|9aQY->YWQK@gzK|T%?vvdXw=7h1Ru*GFvD*f`>thwN)< zwRt{Q$%Yo`njLHVVBY4Ml55(9Jh7hH)Z%$J9jmy5__f`yGzO)E6> zS+~iaE!H_F^lVfe#@JzVZeiTQnfY9WfqE0tMR^0Iyi)rlvbFzJj8ko5TtxQzg*Zn9 z3BZ3-?N9M-L8)U-4M6|kfBSxtwj%mAQ}FBQYRzTr*^{cT*c`ciH}TnrYbG_A-P)_k z?8-R0VsXo5{z53!$78S~e3ZN(9*SDY`mbuvc|$vcdeTyJ@bQP@|+!n)1?Kz6AWBJv_6;g+@a&7H4T?Z2EVaS?pl9^SzmT?dst9csiENzk%ddLq>ueV)vH8{+dy_6o=m48%q*OXdZ!h2*g zYdvbHphe=->{gjuy6SEyGsL;_?lqFHjlGBMwI^bnj6T<+K$M0#x-1KdsWKtO4R+b% zs6g>}q&3{IS93{y%-p(sO*i9B>(5*TW}%DH5$sZ7;90OqbGLF9CS1h!p3kfv7JVDg z?FMPy`V2T1Y}Y?W(AhWD{cfm;H`6b@j5bT`L3frmQ?j{v&lA$HK3LmSdI(QK_*28 zR|}sB%loU>ZYh{SL70(vJzH--CQH1Bxy#kQm`(pB@hC9*A~K22+&+mQSr)!{ac^Cb zfEVuw0?eFI<$#6Ai)0`MgZCT>y~u_tanaDg2wz~;WuP3l0IA5-4`3oyv;RX&9e`V4 z#@Mr#HWLwHLa5AV2LI^_viT}Y%3B@L^n8G^35mk?`FqQLZ%>BPEF87+Vbh0`X|DbI zp$d@5Or)}xq)q6%cMRhHlbzP~){A+EZIjFfI z@61s>8j>yIFJUl{U{|7ae&2q*w~6qM_-l!H-)?QU_SE)M`n&afc0*rVy|c^3!1_-_ z+!)UG*k*yZQYjvqVEVf1x?61`s5Idc$+M!la$96XW&}~7QQorE8WqsBP}p{(Qvsvx z?Bs#mUX^SKmgNaSp`xNZf?`MKMph*jEyh&yy{G}A8~kktLZLtXkJ4HR?~l;fE8CMI z9(7?TxzDmiU81xj00``~o`@E7XT}(J1g~Kv3p6F09oQk&DbW@en(cmL8zmgDiNR9? zke?D-Ry3euUlTTlRcb!54PJT88g8{rB@y)dMB5Evcfme1rM@2p7NfkI9le%>H%K|p#>ucZw>_aE4H+S_aG%$%ZkE}NV+;9P_`0#uJKJL*JKv^I4$KSyJtsIPcxNcUj%Nke_sXagq+_L{s4fmKIjZLC&n_5XC zBDzfCYiYXku^e21aRKL*&9>Q80s*xyk;vwct~f6wR?%`ZbcK=IPWk>OF_N zk+2UA2TxhcA){TW9*cPK_nD##=T{bzn2w|4@ z;$&D%yfF+5A*b*H1Th=ddr@Lw@bT-on&VEE4uWwS(8g^jy0bX%ns{-6Q3}j6Se=l2 z3?Mzm?$x4G3Vc1wPwlj}*o%UZylRO5udeAe6O&7+rQYzso%zfrCpf!$|I{k%8+^y( zkRvZZ$PsO20Dr^6U)p3$Cc}Ca4RaDsf`*6jVKBA_cT@KUw}uLN9H^hvznmpKHe3VO zxtuBkHjwfPRfH2veO8PcSQX%k6#*Od@J-wwAW$P{Q|zozRU=%A1~3UlRh%IMsP%R+ zyXj?Rx*Dp}xnS{>$H1}a*pd9<=c{r{& zPDF65&q{Kf>9kO9Mj^3vqp*G39klWwf^D0=+O(K#1W!JO>LArr@MBMJ?d&{#+K$71 zKBcv|PwvbpByto%gW1}9rsf^F50pQJ7h|uMjaFPLvH!2$bk2U}fLFTnjtqZx0YLN5 zV*SdiNvN57#k~H>llN?IZSA(U17HaB^Kz=G(`9tNQ3RQMQ_la>v&~8M#IFE| zH)#>XT>}lITZ8gz8(XIUs)>`XI;Us%TLI%yU#`Q8^*TJrI!K_)((|w)kO8ChHTz4? z`unfUBo{>$Ko5JtEy6bxC95aUD`J3yS2wr z>AN%Mo^O!mYl+i8sLX^qd;G?p_ludd;>M)YG~xYvwwlcxt~MU=Z+Q5K@mU^Ge;#e( z#`K8kW)&X$vNNOV0=7A}AV*3;<39+qqfiFdo@ZZT;$`gOIPH2q+fBTOiJEOf?4&d8 zmYp|SJrmQ7Z6EBMyuun*v_)fpZOS!M4Kr^r&`q);+4Wp!%Z8}it@~{NL;I`SU~hZ9 z4gTY{fm}VSs6pjUsYI65r*HA*Sab!sH5djQvETxL%q7&Axqs*vl6gj)I;~OBK7G|5 z^JI^GlR5i>1GJvG+RTk0{F4w4m-Fo>trv6LW=Br*K>-vCXcQ{o-TItW2U+POqq!Iq z8;swb6`??&Fba|>Vxi3L*=xt3E$jP&P6c1o_20MWvG&6~wbx=e(4EVqIwr6rle^<2Ra{N|L!Ty}Fj+lqsYHg{VtyzWd zf(iNTG*qDK{$%su!t1|yGHlFUCHw5k`SC0C?~gr23Fi}d4t(Hevyz26N|P*WUYVSP zhCICy1>eP-XkkH_xROm|XimJ*3L1W)rC9&#;#jOo(mUxKH`JR>r=dDYL}$!68lSyA z`+1e@s%cH&X`O!}q0oWdB0jUrMsh^J4wAP1ln1?*&WbWb8&Zh61T1@=Bb`TY)TUKH zuJ!xRtm812%UUSe#1 zVqFbfNnJ2Ph4lvEFh_+Uc>_P}N$YUyKx_}^TFc8Q6V^Pz1QM|yfxS4&0Ju8pQPvWl z@-!Ud*bWjMnJ&853Lt>qLcqObFeqXBvEglIf3bD!^Vyh^M1n+EddqNjY08>SgyE^j zMV3|qfNTnx$C}@;^Z4NK&AaPg53UZ5UY*?UtThX|7v#XfTDCpQ6a9u0cOXWuI21=z zt0u2~z0S5ONETT&{7B+H6IfMn z&{7XRvD&&zS=WW$gjift+qpKdL+ot|rvj{seTxK=aG%aPZ(clox}}be-@dst$omo_ z(9L`RdRUiJQP|I*zaczaryJXw%DRP%+dUiHCmgu#CQKms;UU55ICj&?;4G8IM8G7- z0CrnIbc#it$hl zsBa38>=}BG76h}LX=ID|SopBfe)~8w1{K+{Vjk|(;uL9 z3)3h`##P`}-rVfng8&4yp_eWRuw$F*15QF_6xQaf)E4WuQlMG2>+_i`yNSU)DzKRw zkJO`yz7tkLSZzCbkK8)S3m@T#K0+f>fOk>HdcrJj1kMqQo}0K1?h*+ElQ0)mH9(3Q zI5+@kji!>cE|=IKb7sZ}xwTMeLB{hIF^z%f#&8a1&(Izl!WSONhRVvB$;)9wCeVPJ zs&PPfh6olkQ%O2WOr+%v^#LB-mKmso7@~p78U%NfC<$|;-FM}vY0N;Fah_Z25_52L zA;b)`3cs>`qz97N&mvOOcKay_(gD1%Lk`wJe0yF}L%139ELfi_Vmg{~psJhH;HxiL zugbFWR>S?0IjX&AuZhDNk>JzU@9-YTWc-I(mYp`YqnOAWXBP%%Lig-#AXM8bn0P=H zTx9GC1HELX6lpoQ3LIdppglG@g?Le|+mWG=AdW%RMX_{nG@H^UCnHt>NYOG1hweoS z@v>YN#9Nwb(s~KfYza}o%bJCs0^`|hye6II&!8YM$d08&IKnhO7tx9qq&u=OufoBw zdBIX2ap*rfQQE8uxOT~Af((*6L?!^E6}Fk(WUrLOS-`KVm}&x+CZ1-TXRnuAKTy{0 zVy|#5*GfyhqPvCmqG8Kmc>{TK#|+KT>Tp%Qmqc^G#8R#W2_!8q1KJR^>CTx^L#Q;h zVe@AqL6gM@;fx#b4a_aiP#Gmco(%m~vORe5MFCqM3l9^jAFeYF#!w-33tYfV@=j*< zpWU(`WZ@u|Tnx5@PDIO05SF{68Z*~pN$kb#6QC;WZYODcq$opTu!Zr==1Rc!;oIH1 zAZXtwG3d5r#qg!_Vo!)%#&%QucB`jMEX}p|7?W4w=~kizhhudPSB6it!S+Yy6KA_2 z{_EZfs5JjI8cbNf(P9w%*6w^tPWY^nU^Pi%_QAghd$c@=#ABa8Hd~!uT~rxhgM(64 zTMconDq-Mi=h(*5W!AgdDO){}&sfyc1~>*8=K$*vfLX?yQNm=_<-9zv-&~%kBOTvp z+n~os1hp5}AZjniN$Q?e(stHRJyu0JO@@kyMHn!?=49B`z45nN73Tov)@IHVWW6>I zwKh&Kxa8b?mEyeh2h^PZKGVoxt~+er+J4S%V~ZWeBvME~V-KqA%BfwOWxUSJz3;T8ynva%Qzt}@jT2cis^&v^Lbw-2db-UwM(u9 zD3M+T)HOFPl_eU?8dUkn;h^=VOJWDI zQ%=l-L>`o-zrljK!(f+nHokPdtbeLy%~M86Bt{2b#B(sYiyYqh{u8C2(`2|fT$l6c zOFZ7G(gK(FRs|)NRcedgBJb}>q^P@!r>dH-@sH%yPCa+rrJL@#Y_IF-{)W?S8OCM1 z``de3)cwF1Sgh)sSc0D!CegEA@y0U98gGO$F=qViDj4;FumWY?6D*kxo)7%$QnAv) zghW*#i5$rk6+fIZXtv=_GZT)>z!o0eakniHR3eN$%f_;`|!Z0ont#lrxxPEs2XuWv|Ck3f4W6uT&h^1uAIv}2!L&hB zix1{1P2S~aG0o-x52hIL8A&jPUl_w#!IO<D1Q}5pqMwcCkL=>odMS^($^>buXoaC`SIOv$B(a%_WEeAkM;u{?WBtc?yaQtne-mVcmQ+1uWIvDd`0#EIPA+G*|V&Bu$GV$CW7##t5Sh8OGo<0DRC=6j^}|vMlL^CV#fnLA1D>V1{#h{66%9#A2AYydxWn z)~FxQ!epwb0GU{5aXv?S5=g=W_E9e5#i?V*@99L2X*cX=42DO#mrF z5LWQ6Ebu`$aH;<|nXBeuwbTi6Q5T52Z`AsUylTY4BeGq`#wXVuPtHQ)vW?Ydlh0}e zQ^-RgpNd!*s;!1ilK1(rfn)0aF?OXtRr|h<+rE4$H?{Sjz6^V#C!2CdHD%x6fmQR|KILGVro~)0{`nar*%fjPgRV>Tymgs(4-KOYT9~gUJDkp_@v;E<>9vZKDXw+99 z8qXe@MMoxEpP3bB=Cjw#`sA!n&idrY$>|1q5Cz+e+yA7st@dVh3x`}l9hFR2$!gi1 zmFs9^ce*rakR2h59^D7DU0SPTWmw(E^4!f~ZLbX6TN0l)d!$Up(C4H>fY5(F+s&6{sA>uQ6U{<`FN$m}Vc}NbVg%!;teoqF^ddSkrZ>(`={(KoO5}bsprsVKFujkih)J z9{|oPt~`1TfHwYqq$7HhI@MuD1NY_GFs1oK7#(-gywgerNiXb zVz(b7o9I7>Nx|PvBPx3l+?ulZN~Md47I`F3ib%bQi&S9m1kwGcBo?GKa|d1|0!XKR z3dibYFpNU;H9kERv7dkgv?%(JmF} zy$DDV2s=qo}a}SG`L^&M=N!Lsd+C%f8 zdN@*apn2^#+wx|`0Hr~Q|bX`5LPeACiNr;!f z+BL8$_xpejra~^_p8llO#+V7AQ)vR zG?oW*1&_mkmOiDeQKWQ6)rKz*<_aQ>uR2Zj4d^>s)bwD%dq)8gt}Kty7~VUQFKxQK z0Q%S)BG>PxrHweqx61r)<6{!kTD#4E#S$(p@`he>Hn zoMjYi$x-Waplr-Eh&XlWWWMDyujD4-@zN!_!oG;fXYZx^&qwvr=2>~Zo|Le91ufhv zf3`d5TTF?itl$0YsHNM)dw14+h;5Sha;TKIk?!&7)@(A+(>Lr2TM;XdtO+As1n6pq z9%ihBwq^@!i=Y{~31ZHWZdz_;`IHlza(-KgrND+L(?yjpE;055oZSz!Okn-BdE&9L zh&CbJb-djG#cwwe&!V_tTg=VY>yvBMwedI`B&cdH3uuAhMQ8T*CO2dh&$jG}`|iZ| z)p0Qf{H59te7{{}LBELTDBRcIiWh8ey<&f|6?3+mCCgS-oLh#D@yLJUaxSFBv#Fsi zt!2+lrY-UoZ`E5KX6`=iG$k|d6C|U3u`^GqyPv|zj!I3gv1n#Wmi@jQFPi$z`8kbc zGUE^50(+dtQbEz?5k1}elaHuO7yR2+XoYF=i)*Zc{r=qs-P1iy=lI2oRyWA?_HGy0 zs`C!7&NOwDMDRR5=p3D$se?3cs64oX{hp|+O?FWFQgG`Atkl-bj=~T%odKps3`_fd z#s5GewYWOJ%}@0$=NvI9V~`;-%sJy)pA&w@K|@WFXgYuoGZD@pio!`2lofTRY^GJ4 zZA`MVF@J)0@KwPwqL(IcdS9JuRgcxHq!-+fe72wIar;wJ@hA8x&~ft@bnilsX%s6&>4|0_Sn#VG5nyMVG<`SOrp=LMRf4$XA&PQb0ld==1s;R!|N z0MEQ{(K4(c$ghHwGm^j8#Po%UdK;2xPW;^PCT$PmqNL4llip~m4r!vZJOCnpiU(~Z zbG^GSzlX{HwdebKYrO&wxB?KR;v`(J!h@~CFaX=du5erGIdPaTX0>)XShNAlizMO( zNG^KDIXW&S)n)b4f?KUM7r@g2{vNVg)pjPf9m(}!Qf5}&tn&GGR`K8=v3P|>P}@hi z-?c}&-w(K`@FIv4U3|euICOhzpR(>nRe<|YTwN}>|a`be& zan{P|V|$$G7P^u{_wE`VG{>|g7h$3H2gM-q+x&0&?hirO{4|6&&oA7;+fS`2eOTBU zhR{Sd>JQY~sCQemxr1f6-7vh-cBF7+$nc;&2nQOixB*-g)C!fN7Evp zR)2=co=$S;TP9ngwEwm9{&l+dR6Th*d&PHxT)mqpf869s>X7s7p2Yl(J{`i%9czH- zG0Xe7<|_bS6(b^&mQ%AurP(ewYlOM6o{$LV_e$`} zV=PCv_tzVpq07sLc)*EGt&Sni`ozxTL>%i}b7-%k@mb<?`QivegEF8o_&N!6nRuteK!!>ch zrS92utLW1RF;3Jm_tQ<7uaalJ$ASu86qI_~J8I{7Yj4i%H5lf%0sd7-ZaZGX3F|~> zftVFOq#+YM8r!?qXFpTN(P+hlSpqyF+xwyx*{v&ZE#B5!^rQiy{zNdd5O7Xrjr$3% z1C)jb6}`~=@3aYTQ@%HpPC4x~ZO75Zro6^a%v&sCle8Xwk|1`PdD<*Jk_jc8TFcig zTi9?m&7x#LO=H80DV2oYgt}hjP??qY5AP4OE>*BAI@iZ1Z{KpeF*6Zp#E$*y?ATbr z>%Y_PLW=uOD8ti@ZKxx5)=ALYa3YQ(1%eU_@^rT&F=*^KF$T zI;{d89EaIR9lY%gi49eT9BD;YhR<_KbjE4GyWG5&5ep*V322H@=ja8*0mECWh-Jle zy4j$W!Cb>{C_%PqS%Kg#2gUM;b*AZx#BTL4rHYdx>}R zIWqQ56q*V0V}u=`vFdfv;7JdpCB(Aa7P3blBYq+M78s9!BM4>Lv^tEKL-t-8&< zU!NFmYOnRAwX>z3J!|dGMh*w*h+Wu^5BUlPZ|$U|_l~W2QgO9eSfz&K0e07A5a+{c zg(afYrb3NJu9$LGPIKuZT=(?hP{jMrRb`fDMalInl{-qNF8ly4i~a z){=+F)>eytfOeLXB8dP$$4ny4_y}KHBl+4MjPF`HzZW_BcvGOi!Ope#hw7|C*z z5MT8MrmRjm0!9MJ^Q2Jw5q;^dD*X$Bq%VS_f-VAD&^}3celkjyRk_DXL}Pfd zy&&oAIoy|K#Ip+4!yFisxXS#H!RTUgtJ7(KPRCdb=2k(Fg&d|X3TORg` zNT<=X0?Uzk%yqmudfC}&Fp`n$j`Kne&{cHpy_gFs9HG7zJ9rS?OPbczmu9$#b zybNeI)qby!zl+PjSyLV9BI=XK35!}!KF^glQtH((WdBgw+~(7Ql0?PSHHm%^w#|NS zKFt+;sk>pKE{RtS)$5SXm)h?Wam1&&vOj5P)}RH3lk5J+iF}$b2keZ)pf>{X`$%6} zUH;Neh_NNxbtB&)N~*0kG0>vO(Lh7qcXt=5s5wejV{FAqE<%gRitlq4ycZi+8>r* z+H@N4%EnB*G_{}0r@2>LX*z^-_$nJ?vTS3#P1tGX3pV9j z;3K~WqS+t~`#IcZvaCHKVuF3xDl$`SO7nc#JJQ7e@26whk=+GvMWHu8ywVs)nvhI1 zKMFv1j1qNTOnT5U)7qI&3ra%aFHkfj>SRDozLhU?Wj_Rfwt;U3oJZiBF_Us+v+)S87rKZJ1kZ=Ncv54$lY}e*$dk67t8>@7F=&I7jKR4c158>ud5nJ zSXK{d7x?fQHx1XWmkdyOB-@pyl(>9>bq;Ts$Uu6=Y8+DpTKE)hWkh?!30%h@8Po6P zZqVsuV{emj%tahVdjTFvN1`OLBKB+x_6_}zC@?l0^=9Mj3fEK)XuojMzs0|FTtdFf z`ZRN+{H6SiHEp$8o7I-eQLlI{y&*5+I500f>>NL4zgs+QsCRJ)g)hz4^}E-PuMe(_ zErj2b>RVI?CmV<&K6mrh=cYxiATZozB+zC z&VJ4Or3onkj{er+!XFvs7@U8nwIHYE!2OSBK>HcYz20oE)@-Dw;O^H6bJhuS)(LZd zfAoJL0H4X^z9s`}GO#8Ce`zw1ju8dff=|h_`r!v)LN)=1RI;8p59h+o9lyP_=dKz6 zI-|PFMR!-Yww5R}&>WkGKMQD_P9qpwQ7DR7;)cG$Q#npg(PDkLTVgjZR7E%ZKV! zF&NT5-yiVT`A(gtfJsafJ#3QT1Nc2EOV8RPJgdmILpDtVo(B%kp9k(>mmsI>Nto78jBqH@`;2nDy^e#k;diZGkRrkt9~LznU3KI zt@4xB$5zHq+SqiJfkLdtmeWD}39|l}zqft)Ubg%?>?M&7X(@tXOq6PWLbQTN#jmW0 zb;YhovZh`@O~Lrq6Z&3c?M#omy5bfFSw8jED_H!Dq>ahC4SheVC?Kia2<2#&Hr|G# zP4!Y^lK1=gGe1)un(XEg-xU{_(X2-W+F8i6?qU+IscTcNYm3bX4o|O8lT#AwT6W@ZReIErXidG*KDWCs2N4 z{m**^6GI|taDteA!BmRJzH`PB$HH(B!g;LB&_k7`6XTap#ERp+wUhIix}BYzoJg9X zjhA5>d;q!_y*6yoV$s?$dG+s%;P+BKLTWJN*zP4A)cO9 zZVp6JN9u!)pw-AglxX7&bi0=Ytz-~N6eP+W(MfI_F<}vHBS5EXNq5>y(w1+bu|0+-cl=9^=JIzObcR%n{u|h`x$egK(qa$n6 z%iajDHT_KF;Xa-}LDV-MKU-?|X=`WZgd7lwy?Ch%iW@wrmZ2sDrnLnSZnYTv(hUd= zoA4t8hjk$>7{?4isK7~B-X|Uww8hzd*eKd&n(*YTv0tb~ash}xBlm~MlELV~L7C-B z%lJ@vCH${gpx=hUBoG=8yxuG?h~C9vb4V8|G_LogRagtBi?%DWyR}}Chg=aP)!N>D zvW&-_I!|H{Nw~uYuKx?ORh1}3Kt2=mausE0Sz9e>M!XCS`YLq~6u>pUV#3}<#G($> zaT;)h+C8QuMv^(U-|rD6+iCSc@_hCy#6EJbyD9?UolN-PYN|8yx~ zPXt0sVG`HfEVtn)*sy*8&Sl^+y{zmaeqYbNui_ZFTm&G#XC zIMrb)omn;OM_QP@SHy;XLI}z}UDiZL=AE!ox>jR#u6x9XK|s49-Z3Q(XJ|kYPNFDG za!w6I>}oQ>j#%JLHH^7rrXa8k84)0gbRGexr&mEr`AFwVvkRNnC_EbTr*;wpVXze^ zhOO2gwR#Jw3f8M36&#w6#GbT@aa?jImQz1WXz7?w|JdDqM!fB~rF)K7eoOLaz@lhC z1a(L}8GMGa-52d1qA|OnE?eyMNDd*kTHi2?`+nvR+moc#yG@I-&~-R2QsU7^!8Eub z^4M#4X+~1>>n}hB>JhK)W7=?5$6?+MSquTE{|&aiyT;7sf4<)P>%IS8D9d9lIoc zrgVus>0Dl4*$`L9dWx4iV(GZ{2I4o1uJO(zesfa=u0anBl8IsF#w45*#1Iex1p>nH zPKm2#9mWBpv~65oA8b;)#Ek09JGl$TOti;DO}i%i5*WRP!`0FVr!BDc-yLj9lrraO z^DL|=`#p?{44DU%HUWDWOQqL}d)+N^C4Lb2>R^X8yWW_my`Us{wBY!8IT7Sj#zJ|DiaU~gtrqJJZFNEVYWWf7^W6|iwlW=ZseQC*4cBlJ!#ZbDoDc;Ai4{%}Ur8Xd4pt)b5Mc_AHD7 z?XI8CUaD(7;OK^mxMxCuMcsLXL_>OE*jNQ_1=AQvgP}M>xlHTor>m3G%m&n|?$oPj zQqlA(Kcyo7q%Qyczd0$uenj6^ML-=DX-<7QWz7fCru`m27<~H>D9mmZnQ1-8zsnro z>@+#;2(a#ulx$(N-?XCM5_I@+kZVM2mUkz&C3h#X6W5ft^k~MDvu2|-DAe_q8!E^q zGV>=mXt`dQ=)?~Yj1m&`dwHEt7{2uwHzxd z8s}6LB0fcSm;gk8FXa^SjE5ACGlPuVF91~JJRWn4s?c+w;R2BWLlw;wc05`)fDcJ( zP)?*Y_yE6<8_6QjKt;w~6Wnd(C%18wXqY81-(EkT{P_4W{oDH3i*z~ym-cv4bRXZ1 zqsLsc^(mYf|5e72KrSizF;7MnZK~(uMCxd>$tZ{g`hvP`lE}F208kc#3&V&Lo;3Sd z{VQ{};iodWtl zGr${c3~<@o;XloI)^gr0Qj5=RWu`5XBt}721xe!ITs{iJl?(KwKFK$v>HiT#BKauMQVjV`EP6?ZzoC z-JZ3I*y^y-<^sb6IwK-Zt&`#kP7CKr5r^`z6r7qvNsmCaNC5xXYnK%4{#StWJG2+U z?)oBFUj*xmV0{s+FM|J=iy+_WXDhJv`FA-Lwd8K>epCJRj|qb=73mn>ZpO`o!SX8n0uDx`<3VB4wc+5-6|(AJTkt+kQ7B*LS1+0q z+8aAF${6_es*5DcB4`Q@3O`K5eejENT4Ll?)d6M$uT&cg+V!~IO;vjGb*FHzMUG1V z%*Cr{L#5a~r{nqWIT>Fx5z^+S_ka`8k90P)`roasE%kI~mSj{C+gI_uUZQ4Gu%Z`u zyT6&3I#vzkPMQ!CQ2}!!>Pmuxn~Kg;7HHlhUX$^qI-QH(5~q2unJ7X(o5uN2(wjb4 zyYt{{RrTacSK+g}VFpgPUVFtNGk6OO9KbwP`wZaH9?I8>ld~QdK-UR%4F7@9nKK1Q z=OPI1GcCkDz*F=YTMuTF9@+UImg?oZ&I$8wV%m~;26pBXJ-;N+ef`cLZGi1K>>Qh^ zL-IP)f|d|$sc%_qaFHamVDA|djETq2hiOs_7_G{aSP8lS`??_cKvLiCx9}5nu`+eFH%UJkT-1hf(@RA>;6dRhW8m^VlX}}kW} zT_sVN4ZYB`jO<833_vmW))i#@L-G-kH|KzAyUl1)?=vxB)a1kz;9j;kQf+&0CXAN7 zyNnODwc5-eY*Z(an=3+#z1dCTq?;7s>LliINr@cfBV#{YpO-vvW{5t#-flymGf1rP zGXMr8t!TiZUx0sX4dq)qE8-crw#y>w>EV=vq>RPl2S=aK;;t6QD;Dr#Yc1MFP%= zuk(8+{~q*ud%F%!dq#?%S-m5B{iU-R=}UlAYL9t1;IK$;H-Ackx>1o4u^-XnBgU!#(xjy1?8$Dky6xc{VlBnIb;cEZfYRU4?ugCP0JX-rMt2`sn!UHVM~6-wbj zi7-qZfV~RQG2(=N|5g6AyYM*9Y6A7BuBACVY91V()qP!Br8cly+}feUwKL~~DGq;- zB-zv##KUw~E0*MF8er7T|Z(bizOa;%j$J>j9 z+`#3)2@QA`*Hi^!siUb09l|-wV7$@9xZam`lm|)e?h(tgJAc0#5!;=3e^#kn*)m^J z_&)uG=(;TdUfT=2ORo)OI^x7-^N9kb0bvHL0m%5xnq+5gZwQxQFzlF|nfxo>XzPhw8MLCSVAuv2=jXZH`6r6ZRvwmVv+h z?K&JMs?!@5(I>S}EROc|6i{kL7NDOqfblyhA}QQ zBseLXAYnJpU#Q-?URn zGFh1yt8`GSyLjd^^l<}<;+4ZCGT)k7jSeNOyt zPd<&O*}o!*uX&sJX-HDpWisV_4g9Tb^qE~gg$xqJjU`b1%(ZR4${IHSY@DR#l?YWE zq}UBJuYDih00#F`M?u=fnU)W;FRr&S(~W->0c0R)u#*Q9*g9VYVf+cOy7Ij>5BXydjLp>%UKwsJst=TY0D_y|MZI*g4^&t!foI#~`E1%j$ia4a{OT>)L-xpYU2JP@Z(7sA;v(`(ZuPd>Uqu@>hA6Z?| zp^k_$1^oQDhiCPJb*;1eOR1-hY#8iJTxlg5Y&Oo&IHx0*SP{GMSL>thml1XL9X7huvnvN@d;8v_ zB#IljhE^TTM{C?dL@Jp0;MV&N9&o zclRiXZ-ST;)>)K1x-BbEw~OMw9b?xkYg^zv13&?nwWX(ctz1ON=FIuFNP@S*#eJXlhk zfz~c{?-*!i#4mgt>z==?>7l-j)pbi9jFB`8H>Nh9+SpuWSPLhyKGo@`5Ez#O{?MKz z-K3Jdcs7C1^87*9;aL5oW3)x|;$wS|kIGk7vL7u?esrCrvUpKTu)W|q$hoi97 z4=rX#5`n*r!2Rq;1zpi?Kj?%P|0i2AdiLsn`ROXsIh1yb&Q3k&HL?YmSCpW|;@1xFN{79vbI-^jEYSK%Ao=7n76tRMo%zQ(b*X8;1+5+*e}<*OgXY~hY60_)UH&bO zerTc4-2#3=E=z$le-*@8o&s@=P9mPPeXX%)Tl#)HK5rw(t(eWUwcbqY&GglqN#bml zQKqj7vuXVS<7~dqT+(&*Eol62JdT4U$I;|9{jvjjdU0@kVv<~dQ!>YqpCT0tt+G!4 zY^QSJiL|I*GY8WDW1PtGm}Jtu<~DC6;P}6of!u<%qReJs@-@g7*tjwpYS~IxqD$Lc zbQ~*5Qqf?zu))&Smla)`>Dg!)*(xv|mpbrzBA!b76$ak@?%_3faml7<7Cz7ohfhWy zdDC%Dk}lrUOwv%2`#3z#RaUtoO=*`N6=T*N?vMFfo5BBZ)Y3P|UF9L`{1m_1_dx z$!QJUjur$4FK-5(mnlCa(p=J!Ic`EWhXr~K;+rr{V!mEEj}yaxSK6Y2;UH#2AamEi zQl8QMEYFZoNsRmr=_;&K+(|StkZe7&mM(J;xO>ocpMmC_vA1TC3UKhW7|z=Rty(ErsG2Gf=J zy1|%EGVO^pOn|LRU)y)#7-DZJ(!zBhA_+O_ePS4KIuH~2(k@!JIva{OTng(4?0}&T z^=&}%{eCwb3n>obAUMzWv&5CzF6qt2K;^7!N>TnxXgf-(irBk}=8h zH{G_I?)x3iu)8)|tW`;CRnpg-nYGnoeR9?(=Qo_3F>xMzbav^`(EouKoN-^cJR_cK z#u4)po*BYki(_Ju12j4`4BW(Iw0C?DzKl5|Nszgmp@DZv2STtaB7#?hP{bVytmA6CY7>DYTctl z3vXUnJ~Z5;)h|gQDKL_pGq(Q>X9FBxm|0LZ)Xib-I#i;FY?z4cTBWpJLNY;wI7WSiLzs`Pl>>Aq~2# z){t6A%VIuB zf(=tNlICjkYOkg0qT6*=H-2VJTxWUp2E|5xtsx*389QYsF?Fp;t-u3YvUOVIb#8^F zhGBx8^QeOdwNX6s`e`yYknbci+#w@jyeb9ZiSMi9VvO`{YCrH<3D_^9Fz%H%!y$+| z(f-#7-NYJK9dQ#`TmFtw=Z@Pi%#po+>ne_zv}oKj=0e;}%0%X#00EX>n|Qgz?(77&Inrwl>>u8zDfBMpD6 zkOnnF8oU*xVFhhajy5P-<~iz6&8YSTWTMq-ttrKtQk0aUr{f!9mUfV%6dBQoQaqiZ z6m+@{e82f7o?*adtf8}f-9`NklDQ<+lOb{!BF|(qS>2-NIKNfVa5FQxY$`8x)JvkV zx<)GE7!jcyo{DFPFdSz=uSf$otElo(_mZxHIEgKWxu@?n8{9XU`;wJ*EAVVoAGHnfx8F_LHve;2MW`q*nGt- z5LZ2ASh;glsc=xQP;oz^oiK#PYRs*i+$2$9*Q4^5KqcS>JDm$-S*i496*-%mJM*y} zQ+rYLZOBeB$!OwsXzHG9Ex`N$B|dt0)tRv`9jJl$OsS1i`ejqy5;30`^}^ZJm4ukm zcVUf1FX6n34Rh(C;g+Q1il#M|Q(nxCV8SE;=ZdL1CVrUq?|1@M?j~65oD9KG}%rXT2J}+m~y{s5N+n29j#FV^9S<qYVmw|5rr!v7lYLqtFA2NBJ z5%{vo0Sz(YRr;PUFioBYa1*66-H3RkFdgaklTYQ(KPAJM+kx7JJ_l`DIoi2&9EdwB z^+5~Gle6#o0&U4R-11e^7H|CR^~PUs{J-wTH>!`tR`oxb-s9f0A-aXdb8#=l!k5{z zogLegXJMWNQNNOsd8tjC8Y;vZP_b)!#;&a@c5NKVB>t><+gonl{u1N1_w9_^qpmM& z0uJiQ-Xg*6JeYP9Ajr-5WAcw9`=g5?6tB#wn4%^?rd&Z2vYTRYc*HjtSM~J$#YWeJ zO=-v6q8Qum=WfwUs<7w?g$CR!OZxdOhvkSXTJ?UhVzflAd5jS@PkCY$E(G!OQ{B(i zqgqEg=9qE8M~Y2m=!UtTKzx7nY+TXp?QLu3$H$!<XEpt4L3A z*HOWKI4DfOm0XBk%UK)k70C-t_d}Xfll-zYAUZ-{>{j>!;rEN~qf4ER)Mf7itVI-x zwQSVRMpN1_t?>TdU9xFv4A{;x)V%f9S#O=n))90)cBb7^^v|>Bs~pmC~rvz(#RYPv+WKZ(DBkM=KDey(B7SEVuoT4`iuC< z0xjQy7{Z=>{c>F(D_@9}CYF~qEBoN9+qyTdm?-M#qR>0y!8hYld2ZZgxonC5GODis z*ac?p`=L+p`T+k<>sy4fx;t3i=UXd7>#yc+=v51DbttuS3%0gd;uqM9&BZ@h1*)he zN)t@c{j3${KXw7DG{;G4@T%Xg2T*R!{B7tcOX!cK@wYIkw+PSl0 zW^pcD?YfDTtx|j|%8XBfl)*%35pL-G4a7TL7N&aC*w;N1hhiXL_(_A6%}EptgJ=RD z;j4p75kIn3o~N&pco2m&<+OCeR;0r=Elm_9?BjXwsans}m(G--`zz+FLe33swzxym z!e>dmR4U=@EeUtPF4E2eO#$;R&`02SZ7}RbnI$=1R&9fEk;_M0Q{KgZOCy6;_o(-&7 zddg;B@mE>SB9F42r!-QeZh5jKy7!&BhCdQm7rJz(aJGdjGPK6CB$JBA#q~wUC2i5+ zIIGU=j9XvD+gIG1y@+4HF1;Fy9&%7v?mED~x71OQB9UEWyes9UrfJWq@H3lL4G1gj z{2=;vE6JRlT)+GwQ>Y6(La=m$G$|%4*7tQdN-}k+Z_;F{V`{jF5=p)EQg=zFco`-@ z39z^TiR$!*MfAz8W*Xe8O9N)`4OY%wcI)-~6Rw}T%1+}~ zX9KJH0f}e4RQ%&ljsXl^gAT26Q`WdCUw3TQphN4!vpzh(t^OBCr8|#S`Pc!}!XlJSY#^DX>ax)n9gEUQ2h{I3SZfobs;%KOA4EdNdTW84lFs4DBprU%Oqrxat4~Re!M|^e4 zIUyJlBAc1_88+NEElToU#a&T1WsBOjSOU-hjN)LN2ohx`E=H$Urw#nmx#T~WC;X>* zFmU;Td+BtNH@r!RCSXzTjCGnHaZ+C$a9(Guk;%w8<^13_t3tm(Htg-jnK~qb zH!49Ii0lluw}7{O?@%4LO6HuKwR*N*t3U2qIg7-iW3@~|sy6Tya#FSW!_L7t*xrVQ zjYhxor1j$2GA{1eLj4nOH3)A4bx_quGN%6lr>|%06z?t@kBz;13GjXn<=)`Ev{~P` zex-F};Z=I3EzbWU4&rl0uZoIb7!HQbh}ZK7n=`TgHXbo!c)%%M{Gj}d_tJ{U2aP?c zZi3V~UCIs~1yipK%dP4bLaZpgT1E+Ij2yxHy-_oWO*$LwcJw0T+&5ktAZn$T%V0U| zKZpl(glHdp7?Qv{B$?Qk6jhk1|LJ*$K~EQ%$yURTm;5u5dGKr5FO+zf%FJ-0gf2Xg zaK`y*c`<>?j! z)erAzHfWWI0i$IxIu_}S=M$|#IFMF75DXn5N}(s-QM6`AG*lTuH;9Rl<(V=dLm}}i z=9pmUm+uZT)458{9v6vZ4jT8B7R+KKGoCW?lvqs<@dW-L$b~W*ib>0@1RjaO0BE9^ z%u*L)^f;!Cy5i8j?7UR_gSe<;FQ_KbZy&+MBWi_*B#XD*+WJxPL416>yVHcXY^&FB zKW_i1KE`xR9@87q44r&w=ycqDrS?Gu>eRrz4A(}M7bFkRJkT7ELtlY-3>7hJ+orJ( zz=I~4C85XrwA^2f~@I)6P9Z<4}m>z2=V8ql$$uk@Lb z|9W~tryYAD980`DpCXm&c)(}NxbV=S@J)w$+@Z{32zpTh(5)eMk)IMxtmoD<_2+7f zeK8U4`(5YILz*U&?ki77EXR=o)}J}T*}|bS-s4kQi#qhl`+0yL;7P(p6Vl z7q@}h?@stbyPI?~CX*GX#VDk6{UJp#C%hKvTRV%xNwBxKS2lJv1i0g?Vvwl)2|mxi zj){R?H0Le#QxJpF?N73g?Qucl?X`jmb-pf=F&)kGBFX55n2bE6 zJ(k}Wr0m4)oYPYMo!)qR}~iU6Lx@~NF(H z5Dv;W)ZdFBD4|PQ+V1C6eH?avd%p`>8x=`$?YBG{!X*J1ZhCW%^U6 zhxkZu@6**q%mu5*MP*NP=3SH`5ax9l5L0COQ^c#*bSRN3VF+MM=a&K0k z;@BVz!K{zbnju&-1Z#$1%@C{^f;B_1W(fY$3_;@Ws;$=3)|PtqV%CCfHIa0i!O>t+ zz)M(lFxjl1xQg^tJWx84_n587D!fYkicOwgQCB^V1LF~_yR>K;j*w3Gh`NHP53S!> z?v<*>n021bJZVBD2K^qDH!MY9ypc2JK%7@OQrbulXZzQnJKYca>>)XBxSS;d+XZc+ z4VXjWRrvvF6~s{wJKy_i>?i8p&EPm3N@**?ci%;Dcw zBizzJ`!<24#aYeD`m%X9E<5VY#R(VsXEUNpa{029V_S{S`dcB`w6xAu!DYNp^k&6_#irI+}u zQ<|h_&6Den+TGexTf0vip1{zsiTLf+$>WRbE44xW4E+Mu&my8N9o+Ro>Ca=vgUyL8 zhoZ_4+5WicN#ih_ZttoQU3ZVOR%L$e&{<=}*@b9W+fTQsbQ5=D##q+C<=MqIRe?YAS1aFU3kq;!4;RG%<1IoK83a&AZoUKiBA5 zLjk6;KJ6ZD>v*oSPr0+yvp}b|&+_(N8po76Wh!iJKYg<09nzERakeR``$#h3&X@(& z(IBC7G#q1KgCy|{cCI;X5~<|T0&0=~ku)qB#7uTt>I6pKaRF4%qz|DkE7BWIDOOo% zRc>8&fx^>^!-t;5`o24lvjkJ_IYSx?94|w!+fS$TSZTTJ9UNAB}gkx4%ld9LXO zhSCm9H@?n#njh(uCGNw7Mc8{$v1||(!8X$BEeOmyMJH%4oOU`(AffG~lMF8kRz*$f zNmwqZxPdq|u$w|!m8oY6y96ki0f;4WQyeVdqCrQCBoT03x_e=^H3MAM*O`2!xTIQ;V#mCm8NkqNAtLLVN0mL(-m7%Vg$OO9m<=Tr) zRpc0H)m_}gpD3>dvJ=bTCq#Uw^w_@E0z@=q2}-(}vEhXn3rGvxRswILDeeLAzX^M@ z5yy)`hOvo5hs#cw2h0kx2E>R8ad6AM#MR3lS6-#%o}TEg;i#M^m=6}4VeqD~(->fP z6h~X;tt+9_({Q9d=m>+&pzb6la-iF^vFLzMcZs{tYAX9YSFe)W0J_%kkUy-_ortyI zFx7sS_ye`y?V69PDt!pY2q+q3UiNRpaVwWE7AK}_RG)7Vbx)VjVNygKy_Cv>cCJ(U z{~{}u@&DAr01EalEr7bDje)$DpZKB1v-X&uRg;d;@+rD__zHvq~a$Ld|dp zSr1xhBDJ2Y!zc6*oVpvc-0ERa;1_EE)pA{~0q2nKYXL##&NdZuZ| z=9&gv%bq!<#f)K_f_XNXzwv3lXu4h%IUNX@I6WS=@BCO-bCF^xsFP6;^l2%wb|#;z zHm>+1sDye$oQT>F<7dgYIxMxBoIl=vhV1X@`S@s+isbdcU6 z%n63HbfjTRyJ?N(V|y^ZySLtb0iiaEwUS)VYSz}|dQGm^$=P#$mN~p1zO+OY{?nzo9*Hi#4TaDOrcJ@`I z+gnAt)fbWO?$le;>^05)#qoJ+{Ot(m9FO~KO+DAtb4@+h)N@Te7f{c9 z2t)N6t8EQ8wT7Ge%44&}YFi(k_2Ky~hi5dT8Nh+rZf&clyRBzSj|_Y}UR_^asE+aT zr4w>`eZJG$sw8?a?YTn|+|gOeEXXv9;M_;R@=+7bm_CJc;ET%g^N`=d}H5GtJx47qC6&IAdDBRAAC~#19{XM5M{uVQWIJsYkDvsA~M03))-%iY>{}Fv_h+f4bp_@(m!vB zIS(cY!ZCro&QIHS*&f{@Wx!830`U4P4s$V>>f>+}4BK5jjE70zNgX2aTp>LRAlgZi zC1I5KaJoK`%kusksd*Fkn%lpMvX+RL+MA7pIAGdi_5u#+``1UR2lm~e%$as%>)>Z> zOj@c+C2SRY^aN>9lm)%SdZBnUL&+`su$4LEu`P1YG)6=?6KI)HV%eXE!64zqZ z1PURuJr7ja)NiRb#t*1$5Yfu%jp&c~TH#nC_!5;b@wmyyM7tl4#w$}~nF!WHP14^$ zZI~F=A(HVX{U*!9xWqR_u1)nP>iD_t=~Qj_`X*>+bi`Z3bn~9;yI$G9>dMY%Y}xw; zffj$jIEz2ReBbmlfu+LL@#01688LsrNvKWu`%LMSTX#AD7X_1 z*@aFsk)h~ORFhfmF|=FaG3c~xFHb37iTT78m&EW7SEgR=3@rs>rG1dx#!*6NZb3ac z&Zb@AZtjQ1Y{xX0@%*ncvcKSvYV_@0=tZ%xt026JXco!;}D3* zQc?*?UR3Stdp<;$;M~2{dI~vf#!2{<{ETq@+)b_(#Is&FZb}2D<6m5SDG59pCV_f& ztK*L$TS5||=kl#8WQuYsiJQc*BnXX5p-Q3${QcXAqpyD6hUB@kyTElCPVYKuPKp%S zb5_Ng{Rn8lzrTHar~puqSx83-hK5FvK8!UPJm~V=FPmk!~rrPM_v?1u%i?f$+Hq~SG5B@=Iyrl2hCO0slEyNKsB)PNyJ9Lx@ zJHn^UET2Xe<`P_j#CR{Q=0~V#YGp%>xEVX%vMOW7TUZ@9w*xeQb*u(Yvn-0sRyYbe ziw2B-L#KnAP1@=yadRk?!FXq0N<2zG9563ZDY3A#bbNd|=y5Ub5&_@<7qCLc4WAPy zX&4zX;mi*friKY!N5eP7=0G}=Q8X;0i!Oh<33}A!6&O44VmgTjK{OO3hmQe&QU7n9 z|9=z-QL^5t>z(>X*r`xyfuY`crgmFj z)Rn>I%1XsDtH?se1;Hv?McLwbQ}s?aL#z zv$yx8fq$Qh#|C|RwkgmgSWszHmFWaTPh0A5k1QZE}i1l9hPumOrZmtLL?R(PN?yBwGt+|vUXUDthn#wpdDUj$o zM^ZL4ml}Q%XaicL!bB>&3Eh+Q^=6wl0cP1=hc`588xD>VJ1eI59keeXao0g_7$;FO zV4{2$_gZS-?4fpH3f+IoAb34*Ngk4|*~z+qT*KCc`W(?W{3r)x3`JdantB#_0AE0$ zzn$+V!^`0ey?J|h;L+fBnu1UdY^O2@Fel>?BoHg5($+b?*pz+UQudV|L%&QR805D>5PN>e!S?iW?$OMRy=v>5EST3V^&W@<@CwlUD8FeJnZB>P z6|IKzPc>`ue7z(Oz9csIeAzL%55&+tmQ7*VysuccDgwwCE}T^OldW7#iv_Tr?U_r! zI*ah#TD`kCv)pk4=e z{}Yn7>2-d#$#@1StOLN`i?KZ=M+x1UBU;2Ea98+{%X^F(j)e$$z(6u7M~AUjJvDes zqPyh!<1{eDr5Kstx*@RJvPCh*EK$wK7YG&S4ezW*-oW5NlnXJtQj)0++?3_bc3V5@ z^~>`kFNS`Wrpjc38SBZ!-uT4t3~Bl8TEkUa_ev>=HU>-UJlCH4RUC`pi3}N1I5Z3{ z>>PE@8YKV&iFjCE**Beo&IPyX{d{?KrDQ3Y%FwXwrsB6AbdJu>n7su&4+;4vvB9g^ zI5;}lM4m(s`%Y567%=MZ2ZOgY_8Ad z`fNVf*|cbii|)<)nE2NRbbUbA2lT!NH0V9ue*S!yllN_@?d=zHTCcfNb#`*3xYDA) zfn`V0Rbpi@-PLO2=%&`a78AKZb>k&8$?^M!hi*4_#EA@wYn8yEOFYNUPEJnL z_U?;4qsen%)2slZT^zV{)*hQp#v$YHF`Z#pNE}1NH$F=BEuH2^+zFewQmNGjtu>L^QS&5Zs}UY-w;#le_(?3zD*qjIZq z5;891MSmE1RMHd6LWmnT)Oi6CfCS^@#uychZ|R*xc*2F)0mynIBr=EqYFMxw3Nw<5 z={Q4xgE)k(9_uD@hcNJT4gQmpQOm5 zsYe~;3@AiHgS!dQJU#%CGG;NHiy}^gDBw_6qrfwZq;Gn>{>v%BF;zbXl)pc{*Le?u z?Vaa)Fj|T3VK$p}Jru%f09Y@{yOb(7EA;JHj?WTOFz2|xAlShK_;MlW9*`LVi6+HL zxB-mTTw&7aN`+N1>`yn{sg+EVK)B3v4SN@-ao3*B-mX|b?lIyh@4bfXFs_pUfcF;J zm<1(Nm2by*#a?P&l*IKmab*XAdR%1bV>ZJ+_LJUYtLuJTnd--HPY#YRPXwUT)8W|V z)~QSs++a9kDN!kNrNYQ*9aXbRKjG!Ws^H2jaxk^(hXZ!DM$wD^)(=)r6Sao<;?U_BNQR*SM6Kl2yw!a26K@nJw_-2gnIf)AoczsKP%Wm> zVXugE%5%pFLpdL&uqx$t6G~EPtM#`kS3y6;wNX;XIQOWhZ*&-$FcK|JwQ8eo&oFt* zskOvxJ+>h5=;9=Ac)1`1XCq5?OfM`nqdM!0m70cwVQiUXtg3uDXc}#D9-uTA!U#J4 zFPTF4BU90=^1C$1MjY86l{t3SnIWffAmXK0=2%D6*ar=ST11VtdkB;cqDtg1g6W2I zOB@%20TQ#&`WF5E_P5W$VfVh%JzHY4G|qQTY}UkPO>EZ0=4*&e9Eu+j;|V-d&!5b~ z2~=Ef#q2><#BfpZy|JwbaCXKe8B(`j7BAyAj)d7?F+s0Ml#O)8L@SCAg0~<0@)<;? zp9V-ofDhkh@MTmuPr;M_oGF;(JqRgVoJRm2%6qdi?A7%V(#L6*Wxl{#Z(5wU*P9t> zaPT63Flm)m2*N?1fp8R zZB-rQRa{yOjCE}?T{cZgU^P3hxW7ExU)QjkUhDV5@|_c%b=|YE;M@??hKFhm5phj? zty?zS%0H2qZcWkE+rViw;UBR2_Ndeeo)g=(V3`*BV^(6hOy0qt4vx;%#=@38YI#*wrb*Xd%ue5P z4$9;h%O;{?j&tM021M=8&Oyzo6p{u>_#90jph3p^RFTdzZr1`CJeFYSRgOTIm~S~H zw3}0yFt?B|=U+{jW97wuwtIxCSCO^ zA^t_}5Ammca(Q^sd=&u22zZRGWvG*x4PeKR_1Z{`Fb9| zepfPy|LoqZ()lvYZcU{s%D-D=g)hYW0GA=p%Iu{W)ZhO9XYX2<+cvWFe>_G1TYEwx zx>`v}wMB}eWZ9y{5fv+wKT{ylBw^yh!9^1F4*MYc9J>#;=R17?KvJ|kOq|54O2r~b zpwWH$a_-*|E5&v3@D#W(={i&fr^Id;>k4u~Xu<*L!%U|-DJD|sS5#Jd#v;+uyg|UV zy)tLbHc8W!(LKFVU#R+pRGp2ya8K-$JiWUk4wq4nI+et?PUr!bWu1$lCWBOy0~%WZ-atEP9*c?YzHACp6YaxW9?q)@zPTxbMER{(ci#!tLLgPO;P8Ch6&8#Rg16 z_U70F*x3G_o33cp()2u=CUgimLn+RGzNlqbs${w#HwIywL{ih)o(YA9rS$%^OG=0r ziQ}0sTlD|7ED%%oGIM{;ne+YOfjDphn#jnBwYkIlI;W>6pD9Yqwd`$5sxDK9mTQm~ zUwdTmDUNbK$VQ(V;HpszfpU?jq7Idfs5uWkj`HZ7Hv6Hskm>rI3!S{>*xQ;vUwr*( z^+%+w??bzD55%5(xWt?W^`vr}vSA|r`0>(dpqf*}z@A!vzbd-BFnq*DMxvakFP-c5 zt(XU@-jTK$)r>~(DDyVOe>h&N?(Q_^wplR8Ociuepk^YS81Jbk7OXJi z8^kopa>uZ{4Rg~0oD)s-Ik7@I2#!bk8vcxl`p%} zanHT}jvsvBueM82r{!YT_X^w-R@RAU@e_jj*}GPAA9DJ-aXcGm=X(QBD!TDqkS4K8 zN4m)C50`RAJsCCEtK2sjr}YkCwue~~7K|-e7gm(8p=EaBGt|s;aX){jy(JH{6!v_o z|0GU|AoQ!m``u8?@b*8LK%*r6%%beTVEg<-zfEaTBMK(UEJ9H;66i3&+F zb#pIri=Y^ll_vCDnW=k1jX|WAizqF2z)E(9y{7@t)=9ZW)-a@g1&E9lcJ*^cKCK-t zCUj1V$)gT=<_ms-`m*|h?WX&1n&0{&x>h zDKeeDkr~$KYj2<~|7F>vc}(F8aa0D+s`RpjfmgL;sKMElrNkT?L8cOAwO7C#u_`qd zv{OCvJsBbU8^;l18l4r;>$mMo1eWP^ihe>|cY&xZcB@hkf;(D#8`lJP#rc z_fuhXl~7X2ZG5ge0sajM`Fi0qg<3egSMk!07$e zid_6oRP;TR`8jCr0h1GngnKJSy{oy5FHhTj(cu`uFOY=nlPbEfB+q9KYx`VZfmVuR zjb7OTbT9h6_33TLZBu*9=nwvXjD9qq@3I2Fw`v2d`tQ+`yZz7TaV65K+D|I{mSGPu zkXIjdLjL}1XP^R1Hz-|RI2Lccu}o)PG$*}liqEZ#nBTVSA}M@S+MPCcn@DIviLVu9 z_MJBbpmuGx7wc+zUYgd7G&q^&_Y(hFp54roCU|zIo}QuWcY@n0v~EOPs@EE941;n* zsQ0WBD!44%LguDgBAmB$TS(s^8r@IIYT;{MCb;6*re$dgwIOYm z&P`O~4n{NC0t^FyqPIPTazJUqkc2GeJvz_#SL;#b3H4N$bzeo(Wa?_kc(|yCJKHEP zyr*IqAQ>G%N1TV;(HRlUMV?xozRr$;v|vN7!~=_A%AM6)G-P^w;aI7v{ zN-A|}4TN6i<_~U>Z9nr?jxqCpw5l$=O#iny{e^e<&s|av5iYY*i(lzZJmH=e2nJ#BZ;(`M0 z(UmR=1!zR{QX?@rb*VQGe8r!Dj0Qw8-9ekGU`Sts;dL1My;4m3zU15O4}%NQQSIY2 zSi;eoBs9IS6+6n9GeRPsg=!knXO$JEGW3+RpWF+{t5d}mW}A!<=sye)KUKD4A}(ZF zWL_9V*=V{@<`~pojcD>a5((t$(cn?Mm2n!-$`h>6ObSVwgP&}(_Z}n9m!lnV;O_6S zA8dEI`qZzzwvHmRL3es{ok|V8Ruyb;|I-Axpd*u(^Ie$S@%2ZT#Krprb_E%$fg;RP zbdoScP(BBJ(y4^2R$k0JFAlbrd>@lN)^&FF1qQuj@Vlnv*}MUVImHg^RMK9SSkA9k z%c+8N@P^1aQ~9cuCk=^K)*^>-88`siV5s>Abd>7DSZ5?J>t8S#_BWSjp}bYAlR%o# zyO4H`>Srw&cDaKrJl0x97gLY|%+{vjdZgFD?&ICj5Au6kP8Qba`4sDU$7 z)oZwIWFbpPGua#m0fe5uOhfgAYrEs9AZh3hSU_z0qc+N0Q8SpKQ80+g3iXUx*>^0@ zv^eB|GGR0e)U5zvY72#fx2eJEqH}KLP;|~OtYqdY8d#)8VGdndc#Kd!0*@(lA?(DY zEzTDut4lP3932zHzav#HV^om#8FKCNI8kRZE7kZ!d(H7idBNNbZK=>{?NEFL_!wi` zdCkla-1`&Cgbb1EC>_rHHlQwwj|3UFBzWLpd49*yXL$}4EFrE3qBMp?qG!Fv?eAZmX4P_{%mF^b+oub|E`M%0pM-n_Syb(iAl_b$P z3KG_e)RsH-omDY`h+$@Ck-;wt=fwsT@0}5gtdaYj&j$6mh$e@Qj>3pfVWeU zl}OY{{{x&q%{sSAdm#V@~zM zH{CYfc-#I*L)_e6om~vxHpI#0)vfx}zV5iis5^zJ*;lX8i0$e@vZ z%p##~lYo&&^v{0Oa3Xwqh*bMQz6}UKM07$N-0qGzICKwp)<uFWtf35T=5W$g(wI8|lN*2pBWhQ{xh*m%}~vyv3ro{>tL-H~$Zki_@-7_f5^ zhEjTQu^`2C!WS(y?yY5zcw+rmhJXiaLy=wx_#^?#NX+#saI30)UqVb>I`6ll=F`z3 z8ZF0k%XlTKSR#MSY|KZ*6b~WZkw$so9xgfMdPOGZC7{}=at|0O&-|!Lm8fDIRr9bS zjPhmy5;9Hb;E~aM>SaO3`R2i7>inzl;AJsE5HL3y^SbiH1@+(vHmlm&8}QX+iNo7M zt9^{UEWK11^$CbWx+bEM-t^f|Jo2MDd-a4k5pXHl$%GKbeusahnNeM{&Nei{Wk`0# zC8H1QiSOx)y$Y{aU03$j-5-BEqEWE#jGbL<_2ZQ*6_dF0GWZyS2%?Mrj%jfZa~z24 z-vQLyhp$m7)Y?8jL@s?P zQ7U-^C%f`h!Gkdq??V|yeBDP0cG4y85lS-)loli7ghtYi0?3ZgB2{}!kxZX` zjZ=9|rgpu2@JLPKDFc>!~&B^@35FpvrpH_gux>(-9`R zw2^wdhLbh;OI+A$$%pLJ{k!xur_+TAwS}?~I`^ceb(riW+b7rQ*g_MSKlZZ0h-ewR zGBs9WG&YrA%L@QVcDz7}uvbYq%GuiEQ!}7iA!H$z(SrQv!66nEoY=?Ko8zt$SJ}FihFlGt_p; z5Cjv-;FCC}o$C25f9!_&)Xn67I((BIxVByWWTrYOvPW@C-Oe5%7|SRNTBy4~@1VZT z!!kRXUec4a`(qt#Kwq>zQAfsL>oVRl(l{bYj%ZGU_z^HryY8VlTn@6X9R_`4pK9A# z=Sf97C)|!ufzzd+ZGQ-~LP0w`u9b z@9?Yi`ui+MDalHh^+%i1Pwr!46n=@+ZcE(=CIUXGC8W(Uo8&Cti)i*9`o#qq2r7$B!5PlRwdZ<7I}rVnmWLc z7svOECBNUw@&dSfnR_2(m4s-85r6B7^VFkm`nYV-dYI7V)@o|G!?f|>iEZ|+Bmuo_ zj+f2x?9K5Ig^*JY#oqo(P_@+&tng2F8@3X}LGzd1Wi<;Bm!?=zE&0^A)H%FfC*{)3 zEDg}#CTr%*6V%=yVTV22wd!M}Nq}FdU7#Yg(}{HAB(_$9YTi_BM^2N_*Sv4-pq>Fu zKDd`#!PiHN>|deE@7g`o`rIL@0&kAQ!E&Xn-eU0gOGE$Xr;*i^ItJQyv*figRMPsT zJ8g`fj)<$CGNu$oHME;qHtxjSalf8Ht6NmJY?mFL47fr2%4>O#5yK>Dt_cMW}|(Cw_lUoF*f zb&JxFOyQYY{E|t(KrLn!@5Ch-P4RkF#$M|m*(jBAlWFufgMS!{ zRM$$&aR2pLXYbAKkw!q};JILe4#2pKmuZ#mRT;yLUz*hO26_?shfUfW84s+VCJ#22 zuKEbK{{7mP`N4CI7^tbZw{ye_YAUli^;4GAh$QsyAdB!+RfjE$sK|#o+{T>SNa~_W zX-avpT>vdqOsUCO$P_Se7DtIwVexwPz3Biytvg5GsnSJJrI07d(N`b44bi#k|Dz#J zyO-S?y6U~}TwPWkEvsfK68!{UxrPagk~h$cJVBEe(vO=!Cg-Kk7?xI1pXORX=OMfcExv=OrHmB3X zW!rU;ASp9P3XC)7##Ov-1$)Rw0*_NKlAJ7~EdY zWzZ?*)4J#jc7CyuQ-8;pi>fkBC5gu4YA5Vzr!}FG22`M*qjG!9Hzx30$Gnx);=FGX zF~>z%t72pbQs!ToA?A`j^1gJ%K&o&=pn}ZH^dg3wu(xq)E(b&Tw1ScCTdf?l84yUK zuH#@d4aQ@<<2VWc2t-fE@}bxon2bg=A4a=7z-0v}*MT_PT`7H8dU8x+^#_^vPkQ1N z{_1sc66BFLe+@f3iYTlE+9I6OOQmtdmu;yom!%F3 zFyFng#-Vz^`Abzfj6V&<9tVih-0bcxP0I&TArPB7`#<)sZMlsc$-dWDAbKBGjvz~- zBwO}|VuP||OKwZD)>8Ml=cNNIqR29fRh+trqQ7Te_6PO{`o}g;CQujZ)-z&{x_cPW zGa^kC3P=EnL?ZJXGe~c+;H|80|NH%D84rg6sExCd!*qwHgL{`@I?q`Vyx^w~cV6~# zovAATu+U`q{;k>}antJ2F+cR8>GAW`$An?K>?I7x{%3Spp<|L&rE24lUuA6mUMzZ# zD(=~;=3K+O1P7u0p~2tXt^PvO5b;uwR{Yg~KeY_Q7w#S|LG;Uj|Mn+IIl~!A%5FDH za&XfrxW5iJ68#KzM|?Kw4{)AEKynNIs-oek0~NOfV`b_At$ z6pf;S1mp&&QNjBx%2V|=D@RkHK_7NP*=WG|m*%6N7aGt>Sw2?#8GZhF ziq9>{oax}xrTW4H$l;)2bmKHMR22fqeq9L3KTwxj9onDx8t^jb`YJlCdvTRwhP58K z9P2V+o@!Qj`B(YW0N;lsfxBdvvEbQoYX77H4v@M&g1C*QZX8Fau)^7*W}`Px*&=@gxcjaY>n3J;eZqrAxbfsA`SM#DXKFOXnY_)z z+JnHV?AIhCFr@WCHeJ}y%W~ug<0sicaScJd7UMrJ#=rJRU-RI0g;@mhp+6ia(r=GBbK>-~MfcD&eqmVsz$CISK6{esJ^j zF8BTo`&_vJ|BX7H2Se=F{=IYFfG3Z&G3=CC~>l5_pn1bzNMuUfa{Ex3}lNS!RD0z*l%c zo7MmxTS61$%isG;JD&71HELUy>%g6XP_^^(_SV+xtv5YRFTOvChLgk2e^8$oQw3=!hnx=;#Z>}C6Yt}`M=XM2 z_LS)_efYz+KGaA}d*kl_ZR6D)#185`S&hK=MK0k%M%!Uwgy*om@p8h+(fMVSsQ&Q7 zE*DL!e32JsDoYx1&}0GdSxwC%BOu(8Cn9<`6_9#%Ni(QnF?J9i7KcS1i;CRD;T?qJ z1Bd6#@*^dIn}O<{q3Xrl44fAAz4J8bB8|;ttX*|01;>_Z6Qk?G8yCgwzcx4L^SRF* z7?Ltdvxm}K-e>T*pQQ0r?T7f>=Le(N?RfKxbY|%ASeJNEyfY-zTB_W(|qWY`~Pzx?kgMH@0<%sd+|*Nv zfvbR~mil0WT@VjR`?_cGHQVKQIgA7c#9q4FV2!2vJnxeMt6~uEN{MAabSes0v_h+

a$HJ(`Y5XxIR8BTPf*R~=A?Q6Uyu2ha|ENxjpGaKC`oG)nDIs2+c zlCr-H?2?qz0e-1bU>5E!EiZ*Mr(KtQ0APi|*lRbO_Pk*<1TvJ6kCK7ITRd&)RtB=$ z%Uy*N1Y=Er+azz@z7E`-hH&!meq2R~ovE!HAlx19dC6RMhcvIJ6j-EyTkc+aH=k; zkX>T-Uz*U3ZlzUcRU5Mi(wV4`HEWXN({6XFgE9Dofj2S3%mMKifQA?@rhrK&V0;1y zAQoO?$^yJ+Hc&r^jRqH(tm#7wH&16}*o$>@T?=EL5^OtGhpr`3FNZTJDaZ)DwQr$s z<&38UUeakpDa~!LQO!ituJ*B;M!4N**`!aw_>)2Gtq1XsK8V3^(t{8F74viS?g4=k z{3j^hx16tWp@Ajs{3uk-#qotYlVk=P!E6WoJ!do6K6V6!1Gyi&yIa0GDmej#)!>YV zk-g!$2}&Axb{x@n+RVJ7aUUU^1vNO`%r?avW;!goktxD1IyM{4x>*?DMRXwRZoTr0 z8-cu~141-y9N(O89>}5$6e3``*cWP-y6dEcUH4H>X5=v@Bdgpt5<%0X7zAVDC_(41 z(+NmNFsr;-C6?UoMzX{5o&dBm+cmZp5}@GGa*?2XhgaQg+1ZB5MKV<-Wn2x)f&dQ0H$8`$(6-qN`ml1&s^@wWMlO~7y&?k2Ff&5iM_w}$<4cf5QcSxneoN2s~D zt0}(=Nk5`q*79DFyo(;o_^uN>*8AaAo6}$_P_Ee!6sp4-^3;|UI5Ez4Y$M+D5aFg> z#}iiEToEX#S+O&sXkAAWZh2qc$wQJ7+XzRAq1WkRhT!|bZkZ}8Xr$-{xR5K zT^HY|Sy<=qWZ+xLc5j>UBG@$m9LdOZ)`gmw_G z?L!4$O(kjMC>wSv6w9c1_{}d>1xm?oh-jKyo{QyR zGsC&tl}Cf+JWMf%Q<%MA$bQS5!mzLdu%EEccOm1_UitJ-NC5{!$UmY3^56~~z^j}U zflL7AyLURkN9es2VbzAUO(Td*IZIw*G5)imJGFG=+owy<(WQy0ZV+E$1j)}ps{Gz^ zU}tc3G;5Gl-qJ|W*g}O#ukdAs*aSc4)5bG3fG&+CYpDezD$oMq^m;c44{_#|W37J5 zzW(xm@h^W@`(GE?*EH7sAn?a!;fIk^8ATDPD?QVR;M{6cESF)!?8;=n{GHTEL0^0l zp3eI;5LKD`71NV-O|>PiHO^Y&tToPBB_lAk)Jo7^ZZ_^S#pO5j_@KLfcIt~HW2(W=TCv{Dyq5Uj3w@V&new8+G zVsK%F!~qiN?V{iXIMp;a8IB;iqd+=LY40-3b+D=*Q0{ z3IS1rFSiRZ*ufzJ8Vbg*n$h=msnw{a$|AA~YT049R#0mNwN_AT1@#;Xs=7P6$9Vdu zNN<0K)HT1^blSJ`X+52ie31lzR^3*;mvsDJ#%sK=;X6FaM-l1vXu!EaOb2FTebgmY zGS1S(9d_P3M8&3m051|p`BLc`f01WLR0j32aUvzBhRM`Pl13jBQD&Tzgc7u8_F|$H& z7{l1y@Bxyyo!n~>&DS-!Gc})Mk(Hzi-BC4MDlf#K$jJoIwA0YJp3devpHSnIwBSA@ z!;1X*DwTe?U_}cf*x_6zL5u`LFqm@0Szd|kp|p5llB>76#C+EH;t%kpKP0UXSdgI= zOvWzS5+z;aQt_B?+v&Np?Y~(HV|(YysO?*G@B&@>kVt}qoqsJICtbE!3T-VVp{&)c zEz-tN@eYc4$@wXb7Le=??vrnGu|1B|_^%cOSiVzM4m~wvcKd7Gf;wV zGRh}^Tq%!|bP`2&GVi@!*0sm-^YcjhoZd|b5#)x?#%W?)(7`ZG{ZO`A_M1`4o2lb?GH!%VP)Q@=AfkMC^lWERqIu-q-l=1oH}&no@bbr zTCqBTzZ;f1Bb(;JWG2eAI?;m(P>A=*u8I!WGZ&D4SO1-OFW_^C3Gsd?pFER1I7Q+?EO` z-ra{>riq-KbC~NN_g-#A9q%%ND}#P~`SQi;hU9Gu{JS8H$;gi7LqA^RI4k*aR5FP$ z%IS);c!k3>A*(i;x`EpEUoKt1eLQ-nE+nz;F&pWE*Wjj z-v|AG_VqH!=Rm6Q^^*|Bmq#m|MRtejZQX@r6g`)5i&t-=;9qr#jAiH*`*CC2|DryB zI(y-csH+T;SK|87qGE%E#i~1Bk0*RsNkyz6)vw6xgt=4t#sJ%&tlxwj2|6 z@RLgFX#vjKLRP-EoVdqr=_NV;D~;CM+rV=i{PHqE@P-xm>stbMK_AuOVpCn(N1kgJ zxvxPhwSXt2>dp)V1@Oc`G=--h3UnaGdUGRCtY+o*m--W`CT0EkR4!9ZmFG|GZj4FKNPgcEbAQou{BE?Mg6=xm9M|SoMKppP0$%!rl=3XeL@j?+a+y>U3h)a(9LK0AM0g>M(6LvoOH_ z@R&`eyKk_7!{4VvT+Z|TsiR_V-qvIDI~$uKxIx z4WaS92&ddsT0I750f$cb>WIcf4-gH!kknMi>W7j!5CF-1M6xY9>fH+NZJ@#gV?)~s zW<3Y2G$J^uxyb@uqh5LJsHk6~!vY~2Ezv=)3=l%ym;y5fd3*8|!K_mw#sRg^S10Kl zcbXkFWZuc8nmRV-v?&T+p&}=a^QoG`h_seUtcq;58M$P`M`47hS~8_W+>TN|=44xY zxd}28EYydPMHVBa*K!a;yYc(o{Fs;pUq>RQ_L{L`THTIv4n3y6MP%oqFjQct-%w?Fd|G!HDK8+MWC@^=$>sO53hwwzSnDttkn00VVCwp{@bV7Xml2g zeO)yC3I~WCQGX$G%VaTdnfEpRrJqMZUO86}Vsm36wLdApQOEkzeA|zb%-4aRm5wwz z=|azDDJ}B!YYA!w(mbi!m#_UO`byhV?JPVl7gQtzGROXC%pdw;tn)FBgjK04>RQ2J zAIUHe#%Tze5ng-Mt;2_6SO*+3Q^j!Ne26Y9|Ov>~uIMgI0 zfeXoWG*YK@dS!Z8^`mA2p>*&x@DRBD(qvcd`rEQ)Ec;RTcXd`H7*#1c8z@Ic9<>d~1qGmhp7b*3Xh1E*tKaq@44uyL(M}OFO zaBLG^C5uT~@XRuxaqRt?86_TtWv9k^o;@z(WYpX4LTQqSd-r1wI_iarzt|ZDmMb>5 z$TMo=;{5nU!%9dh@LJkaA`Yvqai-!&YWJ$z!$$3oUAK@jJBm2aa9xv9b|h~KYFh|!>`Tf|8~~(g*+?9c?d0P zk;HCh!;qi6j?A12wDM4nNL&+jo~Fs5q|t$@9Q8tPZ}Avw_mm1~24zTVyl?Wc?dC7<5VU!2(XmJje z0}%0AuP`@4KtYSA2*!2^%*sNgC9o{#NGC!jG*0$(x-PSXt7=_S05>)-s^urV9Fjkc z8f;>+gR{%+NU}NS$ynwUR2`DXJ18dDZ(70fMd)}bjV2L0;k~=2lWi1wGdE!@j^~(t z!-mds5nMXM5?u2OgA6G_W5MgY7)g*?RO0k3!x3j~b<~(<7AJjo6gvfR7PQT8YbmUB zJxpi+&)(H7w{0xx>w~A5Jr_&64#ikMPMliR7O7t=mTXCM;^Zm?5LOwOoG5*rl)86XS%=6ZAUt)Cl0bGYKxx&el+JH z))h0Gq-48~Ja#}@@Y;gzm9KETbO|ds26Wy<32JVeHaH^<{~_-6Cgu<6xqQIrXm;e!iuto za8WXpQWETNw>frF4b0>Dvz=s+ZeH35CN#i;NfIc=1ETF)nAqvi(5EijzLd_lNjRP; z>s{D6s&+4Gq_4FpVM8sveRK3iq%VUnd4LCq;Lag>@!qfzwzhCG42sT zsuV%$EN{_f;g19~6^D)3Qdk(Zuz#(SMU_jBhM!8sro52ETV>^x-N?M(C8yLKIb|yG zc}7kxG>aSszS+m(*zNUDXdoa%QZ)*4x*R%F!z;m0-r1;bI-v=|+|NG`9GT!!`jGGZULkaq?=~{1kwJ|NYGhC&gBlt1N64VPt>0}5UFCa?6l$bUBZV3% z)JUO53Ozy!6;Y-ocz&C6RO<5QFbX*(p^R*&HFSwbdR&BEL=U$i0l>WXn1FVT`eO(a z&vbet{&3)P6t@)shcFQw#-0J^M#Wv8U0E;}Awrf>H1eGkb>yIXER5I`sTD|cMBgJb z0b5g$CUc~A8g}R478_A=97i<2kSBrabLWnHJtMYya@>FO`=p=`r+!du;ZIwg9bVC&>%%rF4>!PLQ(UQ;RioD7B%J^J;@cKAF(aN0)W52CdO&ZnZ#V^q zw8m*TYmr9f&&Z;XuA1yG)k-6uqTi3wAe{M-+v#@x)HYKIV~VZEvGlDlV}M5tg%n`ko7XcS0`68@Mr2I4fBt-5B+68 zGJ~eAd`n+1XSBX6PVb|BAA_mTH_)bw4~YYt1_b(deoA}yB!L~jPy6k#yQr=>*wo92 z80a7|^nC571u$U9R&wb3RwEM=6xg5RLU%&bb_?Ua8p^q!((*Z8*p2-M4OEY%>UEI+ zxS)M9aQUd@o!2^yXmQ7Y^!5$x#?%kOf>y>wm`y{y2!|idhC;@dx`fAuMjxa;jij3o zGbdrQ|J#3&jhxdGLvfzDX)h$HLmSU@9ba+7^1M1C@$2f?Mr`YvO#G>AbMOc?OMNH($~X|Iwgvk zwRapvVS=oHL5RuZZ{5Mf?-YTKfTi~DmgKaa6_z#v{D0Ep+-#;&aNvq2(w{wA$eMt{ zHKO)zPF~igE!nBO&|X2RH;^&X_(~>&`@&CF+ijO#%d}qWp}m4#Z*b|Qo|Bv1U~&MZ zC*o|m3w=gb{cJ9lCBy z_zywo({9XXEa^7qran_II?s1jX8MS4Bh|;xge5al9oXH(Pm)HJ6;XaK@PaetpWVz_ za$NiGrwMQYQazmHYCrX(t{+ho*%luymgT$qxgLpZE?9o;XZRHU5v2t_&=x+{17fU? zaL+#L?5W-7cfdZ+aFaS7G0c+de|mLvY{+zgCfMm0%h}0Hanm@2#Z%>RH_qPXI$>v& zsS8`gIc@l8Ymb&?nAt<&prc;#tL4pYNurH{ddo5asBfkrXyEgk8+8~M;CsXbwkD3_ z2W+dW!p~5WX2Inm22u@nDV_1;$?cAkag9S9+nH_ylQHM>I$MZL&gf9Q3@)fo*N8YO zNE0G)#os!>qFr{0Wx|h1{MgeiXF|(lsfW+1YXC`tvvr>eU8*7)Uvb3QFvOfi{?678 zu=IA-_Vdn*m5lVmfBZuo2VqX#KV*ifrzKzYZ6o5izRDRY2u2iZBQKMHHkP=Rsp>{F zsijHgL3@x^Yk={tm~YdNq?aE#4e(Rm69d3k)E`>CB$YHLd5Kc@hIu0_Ku;wfwtvNF@4kwncc?56g$dsPEQ>NRod|7fjQ5S0uH%+cp5@kk)B1$D5x7F<|5)<2; zU3eB%aT7p!O1dOzQp1Vr_2H*Z7yj~b1T%|w9oeqxfI+WHs6^lna*kK-47+VX)NI-_# zyY?um*)D!3?XnLWH;X;hzdE_2bU)- zc``1`Q{HHTNLPi}mmT@-_V#9`fadY=O)*G)Hux7|Ft+v7;Z!?4S0Un7zUXM@Nq{(> zz0M8|`MZ_E?>!7x&VZb_bAJfrD*=(DS>!O?SoP){Eqa**<)-(bhu7nk8X#KuGop`L z?axS{cCs#McTiIv=g_#y-{}FVrF&~Ry-^`HkZslMXlVCo+I=X(;gqBPw>!^>V!NH^ z8v(hmwIA4M?{{g)M)+0P#s#VMx(5B)tD(fD&eMxKPtW*ibAmjuB~Q6}i^SovKcejM z9-mQl9x?dTpOfLhK#-m77x%EtHQ%7Fk51I3pJq5Zs$u(^-wj0G-P;Vwf=HZreqOhH zz+9e0#7D@UKm&7bfCymhMRwJtAsbjce!A(KpD)gF>iv4_t^BglhjpXXfd+ti4jIitoxvl!c&Wc{7~qW;kd806m;~CxYEeHUM*fd zp_e~(q8q_|_?MptzHsi}8bnIkwThvzBTWWw09GZL+j>~o%QKVhf($BLl4Ar5FW%uJ z8-XE;mQwLUS4-yzlK6^WY){?LzpL}7+-m=_cYSs4$qkXY;p@$7>7ZUSxtkc@nRp@e zLzjScx0E1HRmN9R=}&)Y24y`XT|5 zv2WcNE*$Q0vmvZ=WhUH%k!IQaq05Gdj+oEqX4`z;*&$xqTlE6H&lVv+lhn( z@K1LC472j+l~2J*F{EF6W28s*C&*5DLRQy=k7PYJn|KE9;{`QO5ij>tVru+s$!Ex5 zxMWn`h^pL z(7Qb2!);sr*-vF2ZTeckmChhNYaRsp8!|Enf1&9&xD_j=0hq-ZV_-{QI=(I(mNzOE?)o1LH9LlZ zPCjY18R}#9zNVd~Lt>c`DhrdMM%&%?v+p{)->*0=_@LzI8iRvyu z^Abj7Fe&;*fdUQ6$`tn0-d7FRXfHraR9{+UFXH^Sz zApv?)4u~-<7&wRiZ>wjT4TFQyW-EejGA-CK=krCc=PgH0CIo zC-%8t=|2Ptw>|gD5Ct*Ys&y5wV0&^#;2P;S;GP|z-|Ff_5-`Bt`q zQsx_Mp@fluJkv=IRpRJ`Ds356`4XZxmr14jrwZfF95YCi4bNBuPjz1CLgg#I6EKGq*dhPx>1RQzEtTT}K@zqY;tcIWGqL@;&S(>ld*> zUomhjC8VF047pMXzc_nK&8D>eldM+1<1w?7-5|4UhyGK~cRIU!n~&Bl@M8a`Q$7vb zcpl`~qKSb$;|HH)LtilAZg`D*CY>vL%CRmTL8>!#8L{mRH1T9M*F!EzZru~_b`Pm3 ztvx5gf3Z6RzivX8xu$oibDACSIbPiLhqFgBIg!ywZ-*w%DNjDUal^We6NjiP`(Vled zy}%c_$K!jfgY&5OmMe~H&UWZu9}0rwoR<=VchZQ<6jF}*RypuyBL~nCPKTTm6QVgp zzd|%coF2(tF}Zu2jtY;{a7x^Z1b>ot>O7ezoU}d-x-&iYw_=?JkIfj(22nWM8qVe+ zNvUX?-B#PEQoXV-;#b#V;D~s7%00d*k6Mj-ZJ)6=hgo$qf2!qKBh2fd9oo-Aovx?K zYh>VD`nMJocr*t3y5MTpPS8s3MJO0_eDzwZkl>xu;^q#*^V0moJ4*$RjY7!Yy$y2 z*nO2-AbZb_zFp3NqgTF-=CZA>lSo^iyS(90-XMAB7e$nZ#>;OBFLtD1L+3;whTX`+vK&~K zVhNETH)?MVbE?>5WRhw{x{rgZ0|MTapSEhT z?Hf)Q{(x0jDrsgdZtpaUv004GV*DD5vDESJmy7Oc)+TM=A=>AxO!m8MT$jel<~?d% zDq5FoIq-AWrRkRUsCB8#y7ZcLxp7^t4{EK281WiJ&hN0Y2-{Wul2@6Kj(xaH3fkvM zGcTh6%2M`bF+6TP#ThBHyU?wlb-q>fXZO4MVtVPP0l$~V5)miQk{HkmcPsf;%@KJ= zIQ;g3crTm7%9i9LDNRiKp3^Y#&fHd;C>g6~K5a>H12Bky_!p`8+1O!Su9Hc!kR+%w zfFO+L1@Km{pG7khPqx2A5x52Ptz_6nZu-yVZpvM6l7Gzx=k2`Ze^@C;XV0c|lXn&cj<3LA) z6b@vi_UCl18*3WB4#v*Cua>|4cb13h;4L|=W`I#&Z zam?;=d5$%n*#TKqskNPJAu=lr-MEArm(YVCiOK0x>)#9`KlKa(fD;)#SXQya3=9w@e(S3)*a@BDjM*!< zI))jOV`nKk7}u6jsH+Mn!y?O*S@@CDd&NIBpsrxM$aD_g$o`kTYwK#cqz%UcY@`Jb!85jr#COI!zZArF;CACK_nai&~b!$nsu^}mVFHP*kuv0n2lKe?>`0mt%F^TA~PiTazL&h8!4UBvsy^mr%}q%xg|Rt|V3n7-|3jW!`)mVdDt%W`>taR$2}qL% zI6Wyvu$7${CL4Ya<4h67^7O+F?ZpHz*-Pt?9Y7!}87EN3VkC2l%zKO2n~-oECK1Ex zypcms5t+9eb(2a<7iRw>-1EWovh5VJn$Fz1OrN-aAOz6{?Uk-i8G477)%=T4bfJuo zuRgt6UqS0OE|6i+T^7A z#9>~=B0>{IP!ZH=Djcxtk`_n=L)5Sof*|j0l(oe!BJ}OZsIG&xQjJ_g)Oks0%aNRn zh?dD2)JkS2qUUX5+KQzVGl54&l!;P6vZg6gX^>)`wor+Jo{})LqQblY$aPj$wUpmt zX9uP?sA%mBA9?=RxcyWoVah?Kt zf>!{#PK<>>2wf-Z)kI8fRx9>!46I6(@iW)R`uaH#GSyjG4p^bQ%9BUPY%`k{L}s=@i887_66 zgSLRkQaO6!p)v^IlgeV}5H$)(s^qkX&}s3=3t?R?{6LK(vuxb7NxGcuY8`a57J*Zz z9O507bd^mN{X|sL49jvZ+J-Ip1u?2*4$*rsMGGvnc^rN$} zz1?c;WtcjL{Z~Ko7c{1cf%qEdgbMz10A(sj#%f4>s^Un6+24CZwB(+Q)1bK!|e z0<*Z-E0!8koCMY9btXuZ7i1fsZ-GqncG=+f8ihRp90*^FGrIM(mzAh3Yt_>CS9OD> z8Yt3+^A@$79d~1Mre*jR#|%_f=dpE{cwZCKO3iyEO6EUh2-$xu!ktXLk~IR`pe(MY zQF2`;R7z}Rb}-q8B^tBz989#JX$aV?W(~0(SO&=Lot$@^9L*-AZ4k?z@L^}wPjeA9 znBe6FAGOd(Vv5_nOy4aN{AALA&~s$z{=ft_bGb!9Dj!L;c5a}`x-brBxTiqeBjyjR zHG~vREwTSB#VF_R7GhD6Xk+)}=xEK^y=MLK%kGW6As3=1WaKOxr5bdOjcu!#4Dp@i z3qxmn&Dr>{=CroB=*?CW7ln)cGmCL5-9iodtru%HM@AZ6R8?jIF()K1U`7}rab{A* z|KBKtG#PCmMGkT|Z_ao#cvRP%KG@SiC2HbxPfe+JYQhCtcNseSXV-{WfjMcz!RI-C zn5{C?Ag4ed9Ubsoq5}%R!pK=Bt}HSW3uuiA5{U4OoMhs`qkTp^MFOw~hl0cc%^=>oR+zl+q05qfbp-JRAG<{-ykoRgcv zZna!kp1?Pq^WBT@OJPAl9E}K9;kQMP)>y4r%ZV@zD5Y(z@n(H3!h-tj1E`&uPI2Y8 zjtklSnT#+OKV5@;cIYIgAYZHx28F_GZ&%GPor6>7&6luio$8?K_o%b$v|$;BzsLD` zzud;*XY8KCC?)Ygp&tg39qkh57;+CgcE~%&o*h$gq&0%IF+_K0iC02k@bqNcxk8EUUsk z&-0S?k-_Iov`G)$B7reK|-k3e5@-9&-q7YP}ZQ!hgHC*iI5Gxej`=tf27 zz({b!W?MJ-L%M&9H@;H9It6ItP-p*VJNAxKK%`M)Zu6 z{`z_`JnxoChRt-t6Nyh63ERwrO>=1ho;HD+kPJ%6jVDW9)L`8(gN|u(Sdg6kD1atY zeiT%`7y>t_EY`5Rs?3iRoF%Y;IBlP<_I!_Q=pA_49}usUKg~Qv1>1;ye1cfinE=YC2TGkIBqS=i<59+A4XbA3O_36e z^+spi$nIaV_tKPL94hX6#}Gcq2nfpNtmogF!}4`xY-GaKRnp1+OrJFzaSo4@1{i z7F7cEb}sc@NSxcy8%PjHW*FV$z;jh0kvMulL-Usi5os$3)%`}q_%+@`hx zX_Br3%~B_vtYL{>4Y{Oh^Pir@=%)%0CNHt2O0JL@>YEizGe1eYpj5=~LkW?B#$;mx{HzpA^1CDw%?nVgB9WVY(KPid-+O4BIQ z%t(fra>J;C2GfGCF(Zu`R<*A0abxOSYDUgQT+c&6X)h5Chxe%Tp>C+Ks7tz6EaB%W zBQNdUG^2%CcMn|W68EaJ!1)-BMlde3fj78=se0*!&<==lC_KHfxf%+qq42E_1v6+h zQ6t>gao69r*4MY!w>P#3uRe|Cn8EnkWRacD$5xqos-_u2(UV}B#ZTgv%&H=8I27}D@J0F`@m%E=kYjSekIlSDxzWQj-_s>6nKHR@LIsd%Y;48bA`{l1k zC#Q$M935WT^MjAahrig9&(~*rhnF3WKH^Ik*L$ZY`=1VfT`Dpp5B#@pw>D+%-EueG z&EH7QI~(t37vZZx4V8jBl@n7&JwRmQuGl6#u7|-qq$-Jg((Hsg9&fcsC3jwDyHGmT zr2j@~^UX*6`&-JyP*Dd<## zk>LD1Pu3*V zux7f%1k~ijK17^w2sB@%B&a1RV5(dy)z$@j+|nYf1n6vnwLKjHbXBq~PzDC9U!8BY zSIe{gl3SOnFM_hxVI6pn;YzLTS&(gikl%&)FRz~%#9|>Pl5s4oD?wZ$&;R5^rYFGW zxr+%`!;WS07bIcAJw)dtFz9pW=ejXaNy3hU30?}J|1Xh0g3)-oDvOLnn7785i4i7< zbHaPIZ?*B@5?s-E!9@sXl|c}1{zL-}EXppN4f$jm=W!H+^{5Gy7shdfE*u|>NH0-A zth#QroFxbL=rH6~0^N0cN^Mn++(0puw{vy~R^uTe-Qa!#tu}UsEC#y$b#nUF@)Eo%~o!YWl4pXjP8OT$QN^TJJ%~q*i$oYhxFT7cXKf8hjiAS;BR8W(5!fZMdv(}gZ zRqOQO5Y!HX5jhvz>+2I?+ZoI}dHqGYJZ{Xqa2)cdN1~Xz&ab*C zCOkgSgF%(OI_UB0;&`%ViCTxw6O2sLe3izjmg{K zD&9F?(&rMBKzWOF_9Lrus!Jg%$ef^@c8?EwUR9u^j^5``k&=8Nlma?Y0<#3DnqiM7 zoA#|T9%wx9DSBDQ4K+%0bJZ+=vt|jp&rO>__vJGM-22a&Cg9UwG+TbN0vLokQ=HPe z8|DflrnaY?CA4#U69u8>joZq;hew6}3U3+HExc7*MoHaVY;rKkQ=1Fc2U6K(@GLqv zP{#;UI+WLd)fXzsXlP%HnQ~BR!p&Ap?L*W8@WS%u`QpchBD#w6NxF*KV80hOi+9V5 zSGrhT$Up3?g#2nkj?!TdRt-=skrHHM!)?8vc3Z(MM|?|=MPtrW#j5pj2Y%KG&Z?A_ zFN_f#0vfZA$u#j1^6=39OiAWaFOWmLen+v5*YTsNFm1Mw(GnGfR)lY4ST(qD6&+7jJKI<`b+O6 zQVY~%KQnKvWdEniegf+`cL>x8{I1C7gVVspBvl28$R@6l;uk4xzc1qlF~ZeY`bJN@ zyvEaab#ioMlWphL!|ShwcM z#rOlx4#dYm>C@3}o^)Rdq?nwM@|f-kM^|p^PEecFxjwic6ZmTXf*ptOg01;8#W8Mb z80Y5#{$lOheY)U&l?z_Ch~s(=>RclXwIdwmvv5_}bY-&o~R(k+pUNMj z{xF0U1iBnt^CoZ?2zFPtiOqJ&hr8B*|#;FdqLPmSbSO7r6y$e zo(=~v6r6U}r6Ug{03${>3sV)jr@Js%Kv2jTGQdK+JwEj~WuY5@^p$b*d$%yl_MXyc zwSDM^X`uJ23$41){4P|a;RuSPoqsSITOX$L{aKy*3jGonHljj;Zv;Po2CKclmw}S; zILW43|3N&%CiHd5yD5P>Ac1sZ+iw4W*5!M~@e53II-rsF;)L&M|6t8IyVzv%6v6XL zB55K{(|0K{XJhoFA`Vs6MUW}JEWt|R(E~ve@F`@NT(C5?{v}Bwyn62r01(f6ziPh$O(g&R&ozUsqMS#ONgG009WMouPFfK7?Ku z<`h^&^Fi%K9v+{d#qh?i7gDp-XioBQG!VGVVV@a=4V;8@jO%x8On$)~QUp@Kum#!Q zVMJGd(=(Wn1!H*bBI7e*Cf>~<8ed!twtBEp8qgm=?|oR>e3Ak7el@~YBWyLo{)`cJ z7o})0pwqJjTF^8y7Jf!8D373p;TZaZn(Y~{}v;Bc1)*=jIzrH+~v-Mh*T!Qa@Pay(sZTK1JE=?Gn zIU4k91gzxYUWOQ4gC505*ZDkf(QTv<3j^K4z`u8NVLofsMKmHuL;Ei5CJ1iKJWv;j zN?=*ENnyIolaB=Pt(mTI-PxPbgHQRXiRc2_k`arXEWi;08dW(#V>to{S_ljsppt2v z!z}29agMl9zT$;^rIL=QryUiEKM((UQ7?2u_&*;!y8b|BHyHWEy9W~l)HWD+y-dS^ zwL{-&5~jBsQ5f@5P+pKrxxY}!bZaHkC1uJ!!BszfHJKJsfT*G^Wck~khT2+fi|BNj zp2fMoJ~^<0t-_J&cYytfNL#Xb;rMG2I`D||hMxR>5#TmV9x&u3pb+oC193%e)E&9K z(h?1IfOwcI^PL7m^dUFeOF+X}lFyx_PlO#oK@a5SwQ>}Bl-%D> zay&56qqw{mNv-kEklHxPatqttp7F%)I{OrwIE-@M*MfzcGHjGVpZI)HGMqZT8mX>L zsHS_8_>C)@#UZcuF$TTqHiFXo3%M;gM5}Y2U&>&6+)-up7A5t~)kb2(0W4_M7 zAjM2`m52SHfWEFVDi=ASa^y`O(ZQnZIyX_SV)F9u6`9dvXh^!!_0V43+}x}h64Mc> zv35GJjz2;d+f!LL3Nv_5-*n~Jdr$*SSYO&|Shjsjdu!Fo-*PKk3vga5a~=wjteF#i z`FgEPjENJiY38)DsalyEc`|2Pl?GKMD$}2s#*>lp^(e%XAXWG$N{M-uF5RkOpziP} z9{;9NXuQWTlhb~jhbEVkvXDdtW)!7(sH1dfBDy+?)nlT*mDT0J0N^-esw4h$LWJ{JpRN0!^R3t%=goy_m4@%T}K4mtu zn6Idq|C)R5%}gXIi*^-V-96okaF`?nB#?=lnfG}P4b*T5{$yL*iNvnC;k~ditnYx( zT2$Y0YCf*(^K}+-N2AsnAGk`8iaggWlESKmRZ9(05d&0IuOAy=?uqAWPNl;kygfACg?QJ!qkmMU-fTiS!i083^SyjqGEvL zf-DZ3%COPo+w?0$UG>wvk`NK6F)#)7ZIiQ}fNWPA-E{%NyL2V`z zw<+_&{hNO@93^4u+B}s44yI#*;W0 z#%pbac~Ym*FYLNMZ5n`fkdlm4`P5%S8AXat{(S&eXsluwzvkvKHH zL*e~sBq-G9>ymj3L1nt2$jgcHH_W$9UZuHKO9Q{HLLwnSp3^dfkFF`e zlBEaLS~>kINNvJfP}y8FI5+35D-bqv@GKV3V&RB|iK09q7GDq9MdM>e?YE$J*_s(! zNz;@vH2J0CzVjISk&*uS?<cj5I5sC=~)S?RjTXrZtF$s!l53 z42Td@nBip``x9Ahq5~-8PW>ED?O>1^(X3YjxaObcci7@vzJ|-bxY_{*=*No#DF%jW zp%osi9rWa3#SVXQ73o*e(zvMFd*5f}nxEKEWiHUklKDeDs9MwrPAZ~*gLT7ZO31p< z01k9157xE}SToASetTp#DS@0}O=-p;uH3m4)RnPfI8)3Iam1G~*){wC5>C($@9`2q zh7|Rv64S#KA2!5%sog0J)2D{sGxuRL&1@RUTu2Yav$3=FXMUsKZ~a-X?pj3o)iucR z8Zb}|W{Os!kpxU^f1L;N#G1-b*%OP5`29Sq0Y#sY#-|3%!wQ~JjcO||1uq=J8|%^I zGw3$`oQ<<0O7!j_n0B9=Yutv5nkEQncy>})X}2QV)6B>3!n^=rEj{3O&UG7i$o!-3 z^cf|UOB*?oZQI{$28FpP?HGV4H7~SKyap;6n1tEa!QJvW8bwnR2J2X{IACEOV|v^7 zVVmQHobT!k?!T-G#2~fsu$aR!r85ilYPoKV<<8Kvug2YQ&ircliMziMGy69fjITlB z_-7fC`!wmax7h8~`K9;a{oW7QpchBv`a@YOeTg0Lz2L;6pV9pk&|tKdGtF$}4LJ={bY~=%z@5Y7;redI z(cEZeO)MAn`&H>F+SkGuo>5=$-)PET;kjG>NoIj9GX3Kf1@l2~<6{iIWLg*w z#orP(@d&Cfg!bBLyI1Rd-4Asc4g1d&!IXlelVc|FYHI)?k&L;MLP)E)5F{ zUCHtg0cMr!FhNRVG|j00F4phMIZ>mjwtTcPGm6=}(;JcoytsF7d-~AvNsH|^-q^@k zOi9ldV9x_m=Ao$c)R2z({UX0B0qL#*ds8)tg!;o10DD2A63xRk1T4WjP@NJDNI^%b zlXzm?uBKf>M_u);e5k$VLaMQ54XVa>WFE9AC)2fwzr;0Z^Y35RGEYt#*3DhW*C2tzz$UK<6cCSVzuZD#q6cKYc=)V z8j`kT?;fAcrSGD=Kn06pmM)^vmik;SjVQLlu|}LRNU4pGmDdb^Qys`+WciUgKh5IP}jzA=IXNg6{Qq zJm^d%wQ|sf<57am(%a{W@mG9DSvYBLw>zDu`SbL6yeG3}#L*ghBV|?8Y{2>0Q#WkX zU!;B0nGIjQ`mwg@(vnoU$1Ep)rOJtq^1Bia+7WMzJa;sIr);(c9MhrGM04Ta@CUhM-O9y ziqj`Y(L}>V(KAD$uhpYvi>w_w16yjne90P5I~}yQetFe?MSJk8V4Jq!VCUu2w$xb) zV*q>M$GjL^MFpI?{zjEQzM_z`*)Is{Vc8bSER-?_%V0oG zwHDs1&|<=+;?wv}$3SX~vxOJ>#vC8IVIR4fu1si1fWFl3)f<1qY1}i78*j`yC3|<% z(&>B$#5PZK9zqn`iNeqbz?DR~J-R+Am*h%(+>iTTF77TYoQMLF;5rTD*h?I_-F$q1 z@9Xcs&Ir+901nIF-dTo^z+aGB)#k{>qEB(5fX|dyxbzCz=hs{hSf7&Hbz(zH`u3}W+i&x7?0*1LPBG5&p`NT2HGKy# z9$LIAeO{&*`s^Y+&cUy+&cKGndGuSH`rxX&{s<)$pz}Nbh3%xBQa-- zTV#W1@tt!E= zcUs4v$`oNeK-`0BFU|7|(e$Z3JSzP3qqh23!b(_|Ekh0VU6H}97$nWJf z-F(Fe|80h2RL8q|H1>W7c9+!84?6k&&CNSfr3OsGy(DAqDR<5(Jl21NK#l7;e|suj zevR>nvxwLD0BnPgz*hv<{YokzcwJd4q__nRrtr@3sZ-}vWt1hPK9KNK?T86vU4B+l zH$ZgmWp&!8>++$i9F+dXhofU&j4rND-gK7q4snt-4Q3O&waB`ieMFWP?AaH)|b5=Kit6)DB=X(^&lygDf%&KHwe6; ztyImayWzwSqXO2bKa3Xq5sg&hX~R;OhBu};;wZ=x(G2smIG3l~3}|hP zT&fSIB?7`X!0B(#-k<#G94-C=r2!j@$4nz`j*Ea&@e|siTcRBC7Lf0=X#5wNhc8y3 z6V|X63KU{gC2dUmBRSCh)}kv8-S%u)J}tzTQ=NNayBKFK*W)7}0moKJdyO(fZh7xq zDZNXNL!*>%>KOu4pC6gSelr>&&{JfYCE5wwY<< zadwf>QCLK7{Yf2TVUb9M6N{42A`a|ICp5qxg&edV`9br%v!P*kQl%lF@qLI@m56gnOhW zy&<;!_k>rqD3U@2smdMKY|7F4OH9NRwk2Ad}Ek zwn#YPQX+|xK$r5^g<~HT%}nBKptGM0d-GD1)*#J8A#GIA=sqslel!u*($1|a_fl0% z>ZzX?=Xy&^hmG9Q-OPn89}!ZY(Z|?z$oVfw<{~pHYB4BbXXghpz;CZqHO5EI-su)6 z&Fs>vbvnsM64voJt6|R_&nx+%vE&CMl7|@ z3lYkvkoAqXahSvp4}AN+{?_H?B^p$qyqY`6tsJ61jSxA+9uI#69qA5~;_7Er8-&-v z+<%iN1CsU;oix&4mrzYH?b!txj>oD{)H(2M&*W!!Hj0X%s4IjRn+Ly8@CAc3H39KZ zpFbPkAwC688XDG%D4LW^+>M`IT0%3kDp-T~A|?eap;g2`3)O?d**MV6>M)7II;d%K z1?jz<{Jzd;?4zQH;(|`i(qh;xvLpadZe1n8)L_3-SNv<#YsT=LqEJ)5b;B~K)2!*u zwMwD!oM4R^GoJShy=Ry- zpC{~$e-yJV90sP#YsJRwkbP;heIB^S1E(=9?U?N?3EP$Y{ZPXyn?NeAUCf$xTYEfC zi1*i~R&WXz8#DnI915v;@NsJ5LVaJYpQM~Ft@Qxo&BSTEg%4@Z=S>oewJFRo=DL%= zkS^+1pH)<}r^lY!lmeOTrZcCY%GsGcohsErSL5NFzd{DkF$S#BH7Q)2(qu{%91%Lc zIkwyUV$GI;+85A)B-Z4*5mr0)Wl7!jJ(?(6p3aZPD02o*6{jfH_0elmxsc(+1;;uc ztf_70r;dLcWaWSlbPaN)6S@7A7a3^@B*#GO#^);VDwBkDSRmfBf7i!nH%-|?8jL4$ z*4c>q@iTQ~LV8i?@5l6;Q?7#HxIILY^{_6gbwi$IQnB;Cv+FaS`oe6u?VStrUlR}d zOm*VX6Mn*PJdKM^WWfi_d3a zNp0bg>%4~Ex?v)39m!5I6@o0m6<`6}*&t<9tVA2}*VcvaOyMc0O#CBT6G&1vjPB^8 ztkbDXcsexAOR+GdjDj}qlGIQs+NWVTc;7qok6v6|_Rel4m^_;Z zLYnkcwC72CYs1s7H_t3YjG1lQ&$I1$wmr|bKWMfYw*P0^@wXU^FD*d-TtlLj z_hvL+eVr*l*Djd?PHTTJrT~^7#}vT*<}%qASMa9{0;7gEOTU-`bobJ=H%z~)+*|ag zeop;Aj)A1&5bVf8uQ>5buN_Mp3|EQYS3-lQ7j)PWb*a%r?JCbWnw2DxMILw64x0qQ z`DV>(=?uFJ`P!zy?-$6qdf?>X9SCA)Yf%t?-uWTe+gj2E{^Q_h!DEgb%tk(nh>zPZ!cwHEeeV? z-wnc&Q3SOy@1uW$M-@3$R5vHP0VJkwgBHyE8ps2F2{i>o;DB6!27Bf(iMDQY&a z(Bo4=l5pgp@OlD$3Kxq)<34sEY>SabwZQAi>&k-?Xe3{sYM!M)mMGAvxv1;l>Wmpa zwe!HnkvvpQuJrK7kxmgqHQ#{Nh`c+BM*!OiRJA|__AXI%2}#(mCJX1RAp^61yv1eg zI{+M7PGLSgqwQNmqAji|_!DdXve|t=B|GwS4-=-;9MMWZ-I@U>O!*@11@Y3-}2K-z?bOtGd z0eo&Epz+;TQil&cf8ZS{U5db4HO9qCt)22k4%`iiWN|qc3sa%)c%(`s6e4w3^T4%) z&B{C)pNAAFT2<*eaRnYtq~CDYpoow+C4OpfgqvLC9ClA(JF-HeP6i`7@g}E*0s#KKgo(hxls7)|0w^Yx{vyRDOUbI-7=z|-#)SE zVLqMud!&CdjPtS!R#d1KeW}7Re*hCy#`LP7ktZFZsr4`=s=x87r?89kC?0?p9bqK3 z7-f1J7qQ<1eXzg(sl=!JJ$$g7utSn}dIL4H$L^Q-7B4n(OnVE8u~gXp05)@4B2pF3 z@OAM-UL5>)DoUqAe}6LJFH2!Bnh|skhjYTQ21iP(#glp!jPyj!K!A|tvvM*AU_QPs zKK?l^<9uE(i5|efla&0WIqP@7bXwCRg(w9|#w)g*HRw{V8F0jI&~jbO#jdK~ z2c%_#XY%MW<1J8twk$n08WqvVB7o-^Tdnw$KctJw#kwaqR8Jch?o5(`6K%~w6Oq5} z^bzi#~)0TgEq(L+;uP)AwyPGDFmp15)d~=PK(Akr(p0i?k>_w(y6vtGrz! zpTPXkO?upmrO`#j3p&rK7%SGYbFwYaj{$Fcv;dYtBEJ^Nqu)!-;@bd72cW~;uYP#7 zx7GRP>k$u)l*vCSpHEcD%c%aQDtWo&cRy^B`yD`xZSO5FoHv%>>^z5fVV6G4a}-cz zwV6+6=a+t;4r-z_+3i5Mz!j@PLB_M9!B|EUBD=XEKJx^W-2nl+=(Ue8rQ+qX_oCBk z5Nw#z3~k`=7D-k}*FE>9f>@dj<58`7*aZ=%^j}0(_yS!I@OQnPU*)7WUmXcFb+(9g zk!K8T%csyXE6#?a)9WjmE&!vq&aN0`x3-1G<8=|GAVhifvL!IL5|YwNj*A?Mo{8$B zU4gLpNk4$yO%1GOT>#?uaF{CLTFB0_-f_27Sx^)Xakv-?2MIkJvMDfUqgUI zV##C8(2x~hS^T>M8_tAYpdjESb?G8Na(W27jmLRC!UKi$qdP29T6)Tb8pTg4jgfg! z(CSEAP8ts?uFV_&AA4`Q+%}S}i~cS=1&(*zD5*CIYqV@{#SLn*Eo*F1vfXv#Lsu=`0ZK*lt=F@cmA+v)7oNoyP36=*(8aR|9%s5;>du;=#uM8Izn2 zi>}rlE#8f%@A|GzYxK~by#MpJrn2$MLbOrK0BinNySn+4oLHxvcpUfq_nLy5)_%)8 zJVrkhbBi0~OGFHHTNcle!1# zD27j?DXKFEwN8|D0(cqz`CRabC4<+DZkzysiW;SuWDi|kr)f-0CyuVY!|AFF9=$kg zHr|pN?>zTCCzFMm1VF0+gQhFZxWQH$jf6Xm%2qe5<8vcJPyw(oN$w-&M~AcVD7FGl z3X>y?Bd+}@=c0@bAxxdYUj{chWl%dHGAvo$Y$*k ztBS^{lI)`bu zPyC$L!b^rjFR0S!X{s8M3)wkx#obulxR+dYeXYAo130i)MFt~;Q7&G;>Qc#uO;}F3 zgcCz#+M+~NU=A8^N2!RTFXesh5dll2V{_!Gpej`(f}_r_>sA~L(M>R`(K<CLPSo^uVv_scKFwV0SI(TtaqOEz7g>*RUypSy4e9P+95L|&g`|j91Bz|}M*6;cC zFSR1*Bq{@*X*NW-A9Jq*`lpAzVmP8Bpq5Wr&fR4dc%CU%g0Qelf@-fSeupUZJYaCb zb*QiBK#49HbzWOcY3f)h8K~%{0oinTp)+?Ho~?~|l5=?@HPYS2s>Z_$Z8ItAL?aTA zBMv_FdoGziA;0EXEPBm`4?^gxgj2rwNNa#}0)=B*C>r&5*k1wXZu1SJ&r;2z9I?bj z6QX!NkxkB&Agh4FK${Voy16aO+gdxVIl8~1fC@CMx&er3kLd|ga~^aj$+T;-4)OZ^ z3>WaVt)I7eDd)lSuuP)O(C!|7f)NNm- z(Vc$F;8vOhVUSA_omq}3HZ8T|!S^pD)t{A+tJl3P4)CAr;06EMu@?UhlK2vF3SFKc zO@Ri=rlH)6H>|5SxK*(IHn2J^4uT{&YUa0e9w7 z=GZo@uRN~5Dzk)v*7-Niq1#CC)8XAArdSx-X>9DE(5%?0E7rPEFz+;wv1AePZCTpw zQH+$JN=@(=`P#<#Ks*g6I+D~zx^S)_4{{DP4OLV`Ux_O^g^eV}YxPv-mG~w44maTj zu!vu0ivU&*@@Rr+BPb!&ZP{`O6tT1{;X+@)ww@HX_X?bIhNYBwO)4@43z_~do`qSG z1sO9&Z|TpH%a;L5R<8v%L}8h`q$=B9h1=hw19ERz?l3NPbDfEbp4g zM>i7(SJ0TPQ^|(v4USTD2bzzi|{0rc7Mr@APngG0mI|n%z8)h$DKxt{L-E4!> zmy>adFx#B-Zx!&qpuIk-cTMMxV$tq16V|NTe)G^AZ!ax(Ib zSMKWCruS-n-m|K2{K3z27K3njmRc%1o`&WkvQ_B}iE%8M)0pg8($StCY(zsgjzfIj+dJQ5av5?kSq>Q@HM07maTv@=rBnBQWBzjWHHNPxvE-$knkxC{S zHnr+bX)Ay}B|~5~4`vPjIO-3Pb~V-I+3#z{fUhX=H@|o0H8X>RUK_@ zFG9@NuF5AWRx?y8OF(BKH#nCQ()~;_mvU^9OgT0oqt&7~-*8HhxG&!At*&mpahn); zqS>13NK`aabix|Q-8Mr1qe145+1lXHM&t5U;a_(t&6q%;k~7}Q%b0Px?WRFT(`ufW zZ1%-}xuMRNO{5s*^+u4{_@z>nqC)jOPq(5w&SFf$e>q56NZp3^3a42Z`J*&L5CgrE z0L2sx_Ea`wA!?6il0>fkzZ_x5N3iV23`#(wmn@x0Bv~Q3gjgxQ-Vf;zim-E5%j;Tt zDeUz1KV59l`1Ld(MNBP5J1UNVF=lVYRC`o3AkUiwqATa?hQ@ANb!@A8qna2#cog#q zJ`!99C~{gDiKUI@cW9nU(Ut4dM_aOKv^ymODQ4+gadcyA_dr-dK9*>4pg2F@ciXg9 znAQ+rLE>AiM$#$m=FGC4=ZZhb5L#*|8$_Q#1;tUfYv#)-#?e$7>|Y)36aOdiCsOYs zC$V$C

Y?jPVS?cgml7J}pT8MBb+uAphS3`2*OEz+Mng^|2;iA1tSJa-cddQ3JTo zQqV*7EFJfEmz_P%Nb}wOrY*POyZGt?Mcm4>LLMP z6o`^?XYQ9&Yt49LK!r)v2cM>ZU(+`24ks&syE41l`i@rQ2(Q0Xt5&ILs8L};lKQFi z)#>3Ex-SzJ0=R&;Ox%eD0db`k)T z^)QXh*Tp+wk&z;+M(+D476-#{B%gXT8+7bH%@vB+;s6=2Hr&J`OTQ%%6)p%s+)EH|@NrNE_zmiR7`;1h>$yFg8~?w>XW zBam}|x4vtQqlUopi^3@vlztl^<7i#7%{pKsP^@apyeIlN^QLcu_P9INL(29`vlx*; z&luX4zSu@}l#ZSU6Le>0gkzL#*v9@G&`(MDY6#KvLq2l%M-bL9jigt>TvAq zArvnr&v7|sdo-S-JKThi*_rajU*s=U!KX(NrG!sVaPc(hKsZb1^P>DSoj=q0zdW5s zg(Rc}&vq}7;icjNdz_z0JRU`=V1#z|mOQ^ArbiMAS^B=rjYW?n6XIqvcpPwG6;~Ia zI^%+^MHuVR$IApN^82vyOR`ZyAeddayBJqGKRAP#~zdDn9k~- zoOi5}DcmJ?_ja|02I@&SMj#w4u^};<)D1*+`RvA7Hlj~cRV+))dD0lZSP!Q{HwaOe z=Y`3}IIa?Q!N43D6GpsnO^tU}pH`pbeOPYONY(Dn-@D4yL?y#=%DnB?>gGJVa-fBG zMnBtQF~jH@&6|UL1&sk_a!_Gm$Y!5!ptUxcJjpeva|{{Wy?L~Mm1}|aRpYHPc!D3rwXa8 ziEz_U>d+4|6PSP2FP2+p86;bxU@*=!*+kTQ%n;c-wPS*VQQ@Q%8y^$7lI-EF!Rhcs zP&XqSa14Qjgc;9n&(&2Kmug>BdSNXyH~rjQ(Z|(2z*#;@qp!N5M;VMcYmEW9)?jiiFc{D!?R?7Oie^jvOY`p+t!L>SvYmTuEZn*$T`zY1 z!OL33_#54QTqBb@?Fhg}ynS5L6vA3;o^z5E83=^>=!l!0W{$LmCIMT=u#}AebMz2H zfo%i41e;;Fic-VqFH+C!#E{w$KWbF?Dsp#Hzcike{Afn<-5`%^G&e%`tXNWZPZ!-NL9aG=sGg6Py#3%ZF#8-YN{KL;GDu~PndII+l z@TuS2$2)$I4GQ~!&K}s02Swxi2i5GQJo}vC&Y$UUU%J#kgAwFVQ7fY#`PI-Yw~qPi zN6FMwbP!fF9~p*C_lrED;*}y|dms6~R8UnKlW0JbSn2ofK>oCk@#S4sstg1YluD_gDD%U_J?E$n>VmZMUeOiq?$gCL8T;eLGgj7x z<17|RcpnwGd;L`D?=d_%Pa_qZ#rWWt{-`2aaWAp0#zO8NR5Y1HG)rlj#lC(-@49^w zjdbT|>WR-hRk4}04-v$NV|KxGKj!9HHmj(rKCS<_l4rA2O=z59jit6ryaSSLPh`~& zbU@ut?a8o&+vMwF*P-9#Mf5c{Wl#!%Q?(o$iz%q#h7^=a*ysgeWxj zZ|GK@=m)S@zjIH5-5kuMJXC(#{o4(_dra(VLHCk=JRD+A@3|kcG#cq=Dcb-OKmKZn zOrF6~80+sj+m?}?(%?i%XlZy@TT{(3O~;Ddilhk;oHesr4M z#*z81^9yonf>gI%#n^s(S**+^pp6~72Q=5Wer(K}c-G}Z%KVQ|t+@zCF6yVwsqeDpdg*rXoq*{%JHqaCk=b7+V3=8W-c* zZEoM~CsEmWz_%4A<#6HS*EjI<|osOv3C2WXEv?JF-VBN9%D zvHgDj@Q!0UHj#XKK9941slFKI@NfOY&wqPQ_aSj1HGlX;$j}95{e98EVrs>x(#OVJ^k2&4CFOh5Jh-vILcs+M!y|o-CfTU-O?i?63vv0tDB> z^t{XLC*zv4&{;#0k2B6No!vUDk8o+n=h2{oC)m;pPHsmmCN&?tSY~Hq?vNCvW{6Rt zast7`=y?vSHb@rr*<;;v&xUZe%n_jtuS$7S>0x{n)nE*Sz|}Oc~{!nG&kf#_uB6*ZF}u;9ZhYNNb*+6IBY=2 z;9Y}&`xkcy033pGXT(pJ1wf{PpH6nTTDH!tul!%YIVoAr^tDH<*dMbHu}$(mf1WGXN3>uC&Jg0ucFBJmWxjX%Hw5lv6^F>$oPh}G z!4nh6C113|6wwR6Dz$dwTW-5d21&q zBN94j;6K9t#ilA<&DtyYHD@F>)AP8`Si#qhBCDwg~c?l0u^?vsmYJb z)<`7URlJi6W3Hlh7A4OH(?_%#vSMd@Kwo>Qx&=0UXgoZhnZ6npi@tvWS@4V zQH3OQuCb%y);)4OIXpS&?)g)e4i6tZ$E1cmxdx37BMkez?eVJwwfWFsV%vcT`=89zLeDoAC6lNZH%oF!<-_*?49u;V~^qEJkbukF*H+7d}BC!sjP z#cEhJ4LT~pN!b9@3B*v-1F>Pxq=Bz0bdc(M6b=|x7C==d+HaBN_h1hefvL6;fB#CP z9EB|oIg4breNi*XiA-lIrpfZOO#v-z7nJ$T^kM`#BFQ--Ej6JPykx$kBM00iu@H~) zY&cwmi}Bt=#N7~TwC(qv{@7E>D-a1k^ZdZ8blRGC{veM4s(en=90ZxWJ)Fv?UZ@6< zpEmKvATWRSOAh4=u5bBMtJwEWbwEP$DcW|85R%GD{;NTW>LjUUNe<- z;s}(N&^2=}L_$U{3VG_ zFQwQpGm%eVyoSuFQmHh6RD1L&IT{xc-acS| zSq^V+XwCl#_C!-&mkR7_jwYR=#cCiEyhi`w3)>@Mg$uA2sLZA^UU=s*7wAMB<9JI9 z-&rjuHHf&W6E9lm7#a@3u>;jahf|)BQ5nNP*Qf_l)MVr#;iU;NcFgY@*@f=u+lo9w1m37tbbqVuJ>?$$UM7)In{eGPb9oIgf#m;vb-Sa;?PgC-VL&P zO(J#URlY6?bLTY)l(a|E2~qC$zA}U$B|Y2@%u|mzRt`h&`7zMxVw+-AJQ{S4O<)n@gWs-vpHU&ta&Ra( z+jC~kLOksaR#sO%RZ&?_75WwspMnh7qdrN1eBET!ouU5WUeq?+5Zq&>hK$3yP0U>g zk##_asYlb2>Qt2TR(p3lq9?rs!6Ml>%DRX>Q+2M*kN%_@xF6w}0YvQU>t0b2t42jy zSUFOZ=Eps%Cd8?zG3~(Z>vF=MdQ<U}^S=6~7*xzB2=Sk|h#{k|3qXeIS1wp3ZeIC0 z=dZny$^w#ER0Bg)49Q2aif+{iGbf*Vu|j&%kzMKwKcp_~)3isla(NaaMQTo+y{Ssu z_I%dW1!-6NYT#>^peUx(Gl{75t^U}Ha-Vn@zsAfKi}Dd|%yE?xf8=f#YBnKS*z|@Q z>l+Fj5io5Cr=O7H(Tbf_c{#OuX; z^24~-N$^`Buc`F+_A&Isgp;*y0rYxKYHi|o%F*!}=X6mtl zA`%We2~9+vw?KzugBl;w<0N6pfKVL5<45w%hKIAcUz?AZ^|FBTZquLpQIS+du>m+q z>GOb2J4F{saf|bgQ*wXroGU-Q9gDJHg=N)O^FfeVNwPV7>^a*iIAyvGXy6iIa1Z^} zW}zbP9w;8gSdi(dsE|EpE7A~>4f^4B9NW&}iIH6%pO$8V^Q9tEBem?F{kWSWhc=zx zctE!(T}eTO3^Gp&zOWNzGtGV9bjANJ)1?vB{}aCM(0|XX+fD>F{gO&C>KS9LYfwRV z2Z?%cGFLXV++ws_!_*u&yQ{(3F@4DF!oEPcA{q3o4{;_i@a>}7Y@Y|H+DIl0OZH=- zf!!Ay5Fj}0t3*{$E{mJ$wjO&=|E)QNGXvvlXUCkHZ);`wpC2Qh8D%pAZ)?(ocU?H6 zcJg9?PvHN`F+fM3M2aV>@O232mbdDzy_t`jLIJrk*1P-G5LctX^Rbx&#R&nx0q>73$v(Mar(Lo47xz;3KP#biI&E%;6`NnRQb$S~G20Q4U{($?PM2m) zIy$Q!`%K7IkUq5_LcpRqeX5*JA%GfdGv#3#cuW2Fhs)L%K?HMox%P^KFPcQ7I=WZL zo|G0!ct5JafSOJC4VYDiY&5gQ<~82Wd+d3SJ@2vKXOC$P^pTxrfqXl4f@zcV+ifJ=<)ODSgg$Sm z=MD95x1mUW@&m|cYu?(r_lkDY+I*(19rqoqEZXd(eRQlJA?H7%m+nXoC?+Ic*?pud zmbeDga4R(=->Si8Rjpr>hT%84f0Odfyz_(} zv)9v_x5b(9);2c0xo8dcKVqk+4~#6FHwZq_&P5iKvzbqs-E$KaM%uH=XhAI!tRrBq zjZD>I4TCOi5|zu^{U%Pne?>;Bq-}vL@awPeXI>PP-{E10XiKI*&hYxqzhelrPZ{uR z1r>;apZh9@nfo|O)kE}IRzN^#1D>-j8ArmMxzpfpK_g>~ha0qjY`7|+nfYmU2Vj$n zESO-|%B^$NzgX^AoE&x=huOT{3ZEGck;<*)volROjvl1NODM$GdlIFrGy$-WzGK?} z^?WOtEcjEf6Ba0}xpYX4t{x9;MQLHuLY2O|Jt!)Hbex$sl3ZA6JkAggdE#&8*gbH$X%YFTT ztYu2MSJRLWe92N!BGmc(s%X-w0YBHqiwZB8-Dg_^Rmkhm&0$J);t$lO&HNfim1EEh zgf!zP!VjcM+`~fy(x4bgXQ5+mgk%Jld6aN+vjSgxH%Q*$7f-WiA&^ZDfE916aJN>x z)y?_IOF0+edoIU`v7@|1K*654;S}y!8aI>c*-9H&*?tpEwu2(56qfnGZ5KwIA2u%y z_(nGrn1$I+7Cj+N4A(2|kJ9J(Y4;c}A$ zOk9>EQ!31b;+DirygnL>qH*HM<)%j=r@KJ{VyMtWAs)fe=BBC&5HpZ1M4kTD0tWE! z&QiO2AKC7F?2nNmJw=9=ctR_aDmdyzfi*(|paU7HCRzSkyG3((j(fX2*Jg`FUsPKgN{njhM=Y2o`kAL|3A%X^LnaA zVl!R!-gql{unu$Dyyxb}^Mm(v1cxdku4~FyjLz|H0=t@MNqipH6-)LR*{@T{atG(N z0nJdS5gR646({^qj)F;Fl50rgJD(aZ$JTw|@a0)sZV*mEtj3(X8z(T&>`x@drn)lD z8AhkbfcA1%kce!R3}6r6wXb-g%XyNmIIwJUhBt%SWSC7`mZ1BgEr;1I)>jCSl0h-@ zMFL#Rz~H9&DN-XqbZ?Ko_TpIqsmzO`$}5!d#))u@3+xCT0y%&0UCZ}*pSFGpPPK5i z<-4c9_X6az8+h4W)35l8e-kMHCHw-^9PKYpX4|XQuu!DqrhEa@)6u9j3M~b`JNKwGiC6h}a<) z*y9XP-E?vh;^7339m#D&OpF-zEa?rZC>93?!~qNC8dv|B!%fo-F)ao9k%SG?Sq+CQ zq|Tso(qRvVMb=&LkhJ#R7(wkfWOJpP)#jgbBodG`IWBUsOOlJIaQqt*fQ^)d_w@jAC}&x! zomgAFk@kcn>W<)PVNQi9yipq?6TE-n>>G_xlSx(ynyX{iymoAQlr1k2ln8%1c3Dv| z%)Gb!x6R)5=}v-kKvfOF;iX zi=Em%iFt*?%a>nPSFOsM<+e<8HsWOBSWN%L8HK~b_!)o97%Qp(TS;@)qyIVDm&-{= z(UIq#ljtHv_)*Uvh77VceNtpF)TWRN-gxWY+RDn->MBrj*Ei-<5YL65YyL_yUuL4N z{bCM!sZ*i^+fnEGHPw9Wfw%?eVOj{JCJ%|@)bcZ;#tP!T-?~@*pLhCuhld^auz&XY z_2!%ZXSKV!`ac_A*So8)==$rQT{ngc18|&TE4q%x!>G58FZE0h< z*?EQ{1uXJgbh3+Hb{oBx2X4FLuNHOu;A*e?@m&A4-9%MuD{E`?6IIr6X$^}CA_qEx{U8f_-FO?%KD1bb@|!M z!iTR^E8-~~$EImuja*hlB6?gN_Ft{7G?u9`;a8`JduRIxnlOM5dlw~g*>h-2J+;`8 zM*XKT!ugItE*IiabU>Yh*NM)~_yTVb*k2G_f|OcxdEJf`ClcgTRey1Pj@kh(5DN)Q zHdN@#P;kJ%w@QoyqbpirT(V!rIpJX>ict0ne zikL;W^b3tQ&6T|Pix<3bU;M|a7kF75F49o|0xn7-;HIU5O+8yGZoB^`_ zCdTx+;;sHnOZs}{jlj*f$F{#)6%8;MUQt$XaUx0>4zyC{Tjf00+PsjoMyCq$2LL5t zpMBc)&Jx1xxXoqp>t=sjL_BG?06OLh&bABi18r4_r3FO?dHAM->%A;wNV;jI6WK28y1@}np}?i)xX_n|4~{bk;* zcIpG{+=tRbWIq{#?U-rLsS_(o5Z}<;oWjxy;(sl_m=vpG6SB;x(@3}D*@4z>9p(V3 z-*8jSo|#OW9LEklk|0BO8j~Obr55MR2w9M|QtJW;fU2NdjQ%Y+eNm3DJ^Twl2N*Tj zi{ENjKY9!r!2ZOnTb+$YVeS`ETzlSr%n*=P@WgIk2TAWbOB4D2G|gO=0y>09WzAc0 zSMNcW?6}_P!6l6)W!LkA8eXEIg*%~2uz#6!ld{@P?pYXb4W+p=Q-nV!lBNo^yz;KR`FoPE<6qLUK*|Elr(JWP~PdS)9!r z;x&q*YpRomntDH*CY1+z3m_gVmRUv&=|IyA22iE-AFSFRz_+8Q1_`h(LbEvz_D*)h zwxf?c?bGxf5v;@jO1z&93e13`o5g;fA--%{75B>QN2*MSw?Zf*2Yt%-R=KAVmUhS1 zHb$VX=Kl0lDd5)lIR+LC?_e=ath|h%hPb5U5z^Hsa4WEhdpGt%? z9_KR=J`>?ThX~c68bNUm3VbuK@@2Z(*F~(=!@gr-xRK|CeMhrc&>$P3F|H+0ThY?V z{_e6)4@r;QK~|2nSAdX1mD+Eu)rSv%4JPd5sw$YaOkCJQa4LQn);(@J8G!CB*ojT= zqN&WjW1JT2kVT87ZOS-E`UqdmaPUI((-^Q05OSBsWjTHO^5yOAt%ph1vxCK3ZVu=D z)nOCqKGXVOX=0%>1N$-T`c)jkg_ghGqa?vGxXg-iHUV@y{@yF}Ye@HLQ zBh6!_ob#UicRJ-Ba+cLOsdJ7RbHw*e3^ujPoEhQ$N*(9n3I3BDWQ@OFJVIIr_|Z)0 zzbi@o!!FMDZ2w8<>skQSsezP0$smsYH0u&)fgh`1v;C!{+pxnv9|Zr1gW&$W|4B$M z1$x>eBzJm+-wcA-J9rs@R!klT{*_%cD|Wlk<%Xu5_@~q2c&DngrvP)n;_n^L9PMz& zZbctaVW$OpoGZpr=vdlY^VT}9fkp;ibU7A`Xj4?ElM1-pJqZEfF`E8a2A|_Nk-mi~ z3{>09z5%yiPHIhD>E3@Zc``6K6A(_TSe5u0`F?@_%*5m%;}mi0HzY~m#N&h@=}bu2 z%)k#nSZBcwcSPO!92yf;MG3ghI;~-yr8`%{SRm>!QpT|0oD$kS#goNy28hrq+&dmT z1P7k}M&o~$BlA`b7O~*>{l9nm=a`6&d!dr7G%?qoshYmdd;WZq{(VoG`qHUhD%LacM)$r|)Se9lv%+N^ zNa4u=QHUc@N#!!I0=s>$tZb~Ut-ta%*XG^4&g-;7oL3M2oF|;M1WBuDh9vZcw>dl= z1D!AEELB}y;sjVJvfiI1e5n@y8VD&|kGOv7yb(U*iNHxi@}vy7zQUn887ehFYtgU{ z!}pQNq$|bb9jt}!_FFd(?9gf30{%n!5C51=1#Ki$L%)jo&;tlL!iFT#G`rLmvqHRW zU)oo7q#@{wbC32fcP=h}J~_MU9~_)qEm&tk;6Kk)61&?|{P}&>dFqFpY;lzV7hcby zko5Una=#1%Vl#m;%tsuEQ#CVxpO~5i6s-PT;;rzu-7&|?A5u{{a!pL8Ad)$v2herh z`bBdGasDHY&6FK&a@gFm&#^s ztiSa}2%)Rb&`UaBOZTj(t|NE5#Ft(X4n1TV0u4RUhnJ?JyjA|B5a6jd4|wWd;&+=U zh;xWDJPsp*weIq|GNW6uDs_2XqKG4%1+JAN4hSbT&RA$L#=dbZW#iaj8^_u0FzN-! zfRlOt6ELakVKflA9-5d(0J-Y-e-kEGStjiIWuY^0aZz$C(0Sgd_5uc4h0x_B67jK_M}<4WtbTbxUd0 zJ53Ok_kOI9BjKofqVS1zWP8Aj&UECd7HMnXuP;}}l6bK;)mSZ^FlQptI)aYUX3{JQ zm2gm9pR>0%Ie-R4H~_KdhqKct+OLp3W&u-WCKSPJ^2)Z3fA1yo+mkkOd+ECaA~b|} zbioq$>FC$Qur|-F+uzL_3~14+>>-t@-PZQ~<1Cv9Eg(=(j@f1{3+Co?77s_*Xct*Q zEO&*?e4F=j^X>PXnAQ$_bc0+rOWhyKLM3tm=rd$Ao9ZyfxOGZ!U|Nf0oqIF>PoyJV zM>j2|xpu$b@EAgtuJC!inktLHpDIrL#FCPB#y6U^{`o~sDONU$Y=pZG=Ss7*3w!H4 zID$j7WA#FUa8W<8*p1~FC=W$Pf1r2MV4P>E7Kb{H#Nr5efnbZ3tkyexdDf9txIsjA zlo**EDpE*PoLapDz9I@7LHXB~ahBSa5aE*r{K_y_fL>vI7@!J-)(j3@dIYKcF_yHk zm}}3A`7geh+JgVvm$ani_xxzD@BYW8`LJa^tghNmYaO@$66muX_lvi=@`he^kT5bD za=fq36R)wZ%!C*v+CnAmKW^Fe)!SJ7_2Cp&91IY^W8}cd zhD~2j#wrwNMGITV*C5}Q_fX8Cn4$Uh8mb&jza@~%21sJt3<6uUZmH3Vau&4l&z6w; zRmwqkE8c5Bac!+Ws2cgP0C>0X6b%w>%#f+4X}hwD4|h&eVC%A)55^7{WqzzpO~iDC zRiGrFWph_GbrY7&Y0R&~YES66ZO<2IMQmc{BuiNTqKDy_Oo%)dc+eW{2=EXx=sTfA zl_j7_1z9za3}BaM4yiiH9yfqd8$TT%K4w2MR9x_&zZ3 zTHmYR{=?8#TgmVUp|w;DwFba0$hZ8|Ois~z3I<()1}pzP$khE_I&~H;*RLZ~#}I1S z7!2ss{Y@0>JV>!JMgP_$+w4AFFHndf;lZ3F$&|zkyu%A@I>*3;dxlu%bjQuA7m^*< zQj?rct@{1iUcth4o~Z5By|lw=7A^i5+TO+tx6hmfEBWxT)2Qk1rrd0_@dse6?y5Mi z(p2TEuaS22wYTc6ZU9+&9_>;0=K-7%{hCn+6M0^6jhf7eY}wV4=q(lySDWqQfzTM_ z90g+4)UkMWRN;SqIo~@wd4OkQw7C)Y*;d+dn0|7dn6vONaGOl zl}G2Qyv)#UBCEEeiGI%!jZ)%%ZidCL8B~2~7j7#-4_DHqTAG(hQ4JpCWKVf;@A;Ka z@A`a|^S5U8?1|y9BXcG^oNWUYYcy>!^J)rJ;sG*a(n1!aB&kvNhgBRKCj*=Fj9Ij* zWDc^OU#x)USTMGSMAz&o;vmt1*$uU+P&<45(I~aWA3VOc_bi|FV*k+(hQ|}W)rhz? zyMlFAY4@sc07XE$ztdAX0FkCe5cet;lBot$<3Dpfr^DPvYp!!T`T1+}{N07c!R=0o z*dum(9mW}(XS&lYs*}n;sv3N9HIF;%RG5W|_Vfoo&9kyjE&dZ{Z=&6n3N~q!2B_~? z4gbIY_a;}mU`fkAanJwzf5%Z#L@Iy!R9bAg=Lvn#mjV#xfcSt%o?jO3VE9)zqaRRw#O29T-PbAsZCgsxDm^ z#GiQ!7LH$*$O$0v=X0$sQTN$jw?h{KR;Ggib=)WmmiY*gt}KlAE=we&kIM0_4+xX( z#2@tN4CxM3(-Hb28>pOma2gH#m~)_%UwdI*jizHH=M2W*e>&tPT+~)y5gl)M>kmlo zj3S(8obHd#cc?}rgK7gufTM}1e>YK4`N*|vjjpAB11YO~b`_g0J`OLl0f52JR2fa+ z%9F{5o>HDF$6tA@>>Cb;$_uR6b{OZqL6wf8r+I|Kkjw*NTlo4bZ);9dzIS{m*LmCG zto?=I%0xftIoXr^!kja04u6>TEBu~Niw;i8ZtvBZrH;;}sJR!qd}z!0?iXzdVT}ZF zG!dt8V>&inXat`j!a*Db{eaWH&9&pXf6FQkI!9OZ9n9q$y>!gA=gPsd>dPOLYu%QYt+!pyF*oTavhVMhI60bxQet&%J|aj#M3f)CJ;sPDRHe1 zAKf&tFv{sX2}1mnO=sFdB9WIg+h6wIwZfCn`Y+d*p@QeWcEVUB@a)83PmWUBp6(CZ z{LSNUJz(W~!`yDOD0KHcI(k$R{jigJaa&BBR=)egS zA3oM>xgYt&ymOL6n3n9?X?D^aJYii-PABFivt+Y)Z8AURO$>HFd_@CN4Xs5uiI zWRjJqL6sMDW!T*gZn^F#2HXsQ?oHxF71#u&tw!pXG#IyJwFO*9CJ_SybwXmtTgU0v#oxLG2{M}d zkRyY!=@>x%dR(s)F7aWBgGx(J=_?G;3N(7{W zqArX#sYWW+g(>811Iort6!85=B=MSLUu-`?q6GSG?8c`333T6gZ>2@teZKu!W164_ z6k_vJVS*$$#l6#*T)e==GPeIePP7b$Lt;2h$|pb1eyNB(3hXoQMxOQHu*HYkQ|K3$ zVRu9=taxu$5x%(f+Iv0cS_8+nU&|!CzqeYlf(BQFxb;{K#ezLhrB95%Uo1Kh|Gu0{RYG05iTuhNYu=lAz%H1z=CjBm zEw(#F=ot1R=gMM(3C)5wec5orB|phb>R30$uH$^##j-PwkX>|y{Hr75MQI&9&flMN zJqY0!TPAx&N;-tnXkj`IiBd4;EDQt<#=eT(gLr}^-%eC7D7og8;L*NSAzG#SD<9JFZ}G~A=)DdHyle59N- zOKoZr>s2+cv>Ioz&eErOOqM-L>)wNj_!aBbzg4RIZqwrIY=3vJTcyz*J|M{~3HGn@ z)z!5vBKGw;BIh!PE$L{_=2o$%=E^7`s-5!6OwKlP)+u zZLCd*U!?6dtq@bh6`CZInwM&Xh|})NCyLH6-V%eEKwMxq7EU|irF6fAS7+J|T4OS^ z_A3_Y#}nd4XFs~1>6T8Tia7-&w4;Z;WLEqVKkaBj4eqA5;=S5}gZRBH*LkHmGmN(* zALSsSv0$_oaZ&OT8jHnWj}2-`YpO$2+8X5beA87Fhn}86EUpv82=aU>SJ^y{g68ql zg3b)q?)du7qZSmhy)W^|!evK$o6X!BHBf3c%)g+HwD+1;>B65ytl!)%XqbyBU4$Js z&jwXd(#5Mi0}T`l;$Wq;gP_qYk48w}7h9bjD5y?E+H{kn0bK@P3@jXSY*QtAPpM72qT zgIQDJJs4X+Tr6ZV3g`>n)i-pTMJ#NqhHX%Ck0a#^x4N<7)ScAQ6>3^t>8z}*xEymp z6G^?+JfeMblYZtt;E}_Rw%mlSe+Gsj;a!VvpqK&9(^Yz56pj4B3=A~pA!2c=8|1`? z5(CCP(TmIzP)%`IaJ!cJ#KE-b;R?Z#8Lc+lg2QJ53v+zgVx1EmASW(ROs>tj5jLHc zU`8x6_5br2iH~g4B*y~tp@nQg;w7zGj9oXAHDWgzwsa8jNz3R8cm;F(pyzs=*30SE zpK0f;G^?1SteZFx(o{^L#n zoP0BhY+QHO?}u{3-YP|mHiqt@Mx4F=(Ky!$@B+35LzW~`mKYTr&m22roX0a^h8(TE z;rnr{^Ar0z-kZ(ZV0k%Onr0dt*Db_ZZj4Tggbw2fDj0U9YyT1@_mX(`ZRti& z_vR@gh*Z(Ny}f;OYn?YWRUa-%$iUe4-XH2Q8C`&;+}5-_Z@z!T=Id+cMXX89B<2=P zS~KxxbcX4&79N54bO4&uLiaN}S$1K^&e<3$tbEpiKZyjK;QBUC9c`-=BLu8#rR0?)4-46z2YN*GH(!z0OW9UO`w_EF~_6AI>Wr0 zB%B-)F*I>Z7R;KUe(%Jw8qwKZ`dZED_lS|7$+Xp+!LfgvbG+>ZQ7Lik+tVzY_&?_g zilSaYr}1cpbK2y1%)`h%f%^^J4BOZE+ADznl@Lpw)de|go5R~x z=|IsY4#4~j%?M4`GEERPcX_L><)<4;mimaDO_7u=N5Et z-`%A$*pvq*=QwxH48q>A_bL^glg(5vjFToHzDC%#0a;D?1!pS2wWsvG&Tb{tx>Tll zJl5%Q?1-%iAhN04dJSJkcK>WD5E(;yI%6m#+kmu3A6}ppV%A>15HrxjqltYI0>$M; zcePa;zU=KUIH>$s-NkTXp}|8M`TZ8qy0JaJjNL!!GU9UQ*q{g3v-853SRPtbr@g4| zA7W9POZiZK?*>egO&Qw#bPASrGl8X!fgv^mkX@|iN%iz&=zGAx()MV7 z6%v?z=cyfrvb!sofj*p~-k{g(bN#lH1v8s_sY}mov*xy9RbvbEo|WoA<7OiL594iO*36aU%|Nz~fT<$;&TgB}fM>a#zjr;6Wes%6_eGT)0gjjrK) z_Ktb=$zuRE47{A!OL%o{b>5Ql*9tr=2;%^^%4gBU_W8AULiE@VcI`jWs`dS3;2V?h z9OCRf2t*s5AQD=WC$k&TDFj8c5^IHRjC)^Lqa@^V_Gn`OzdXyJNPede&$sShXgDd0 zGi5%r)=gVk4vRB%t2ACZ)hq2b1=3>cbQCbGFly1=2_qi@F3pEbBiAP8d?$NhpPL zvsTJrX7q{4`Z_@d{wezy92~jZH`#TdCcQGIx~B2}-BNQO`Dp|l_XK~bfjh>FWmrGz^N}Bum<#S` zLZ5o$tZet-B+4f^kfI_O8ywFB&w4Q}!o-V=*y`srTSrx1es#BfZ-NiKF)%u+v=(lU zs{ji3y(;%ZhNPyicg;b6?`beVaJ2SMU3~!UnkE=ljPXsOj|nPlG=A=YTi4!MV)Nz$;zw)w76sfyLAoYN!kFd)b2NZ4Uqs^I z22GU&tQ($JJ0@}O;Nsy}_~}*`Sm&kd(%y3aU0WT^(fMO1Lx>a$EV?L`!V;VCpW#LC5&#VNx75GYNH->oYScV?7ENX)-mw0k z+LK;a0ITIf1YUs<xL=oR?(wGQ_3` zQ0TkM^EubmRvey9AQh$7`bD#F1#6xVT2VU^ts29i?-+M6Kc=ZnbxN14?Pr0ebvqsR zWmV)a2T}TxdhWTW0sZJ`M;Z3Dfqzyv8+O@2np)8obm*zu=<=B`L}&*m1M1ONgwE6_ zu|*`)gyO2KO1R|6kc=j~Fgt;F=^XYcyyZzOsk3pJ^ebopQXX{ffqT|>zby0~p*r5j zoIikA;gNjm1+-V_yn32ZB$y7_BI3PrS2woiy<%z+*Bp+!l%q@ZHdvd`(RYe^Xz`d>~c(2D`2GSG>B4~SjTItN|IpT7!()n;+G%L1?*kc#OE`0^3u6|3 zQnS!K@n9nDe(>WcaksxF1Ds}Yj~FVt0U8o~9tCdSb1(c^f_ydGs>plgc$ODc(a0bo zUit@~yC0DVIYS;M{Ov{QO~hAxH!5NpQNy5IK^jlp^P!61JG!kOc=|!FgyIFt&fPdZr4=_g6sHew+M1@GaPK7oqCKh!=cqyG;VrBSR-Nzpddx%(#(vCK!89I zj{NNE^u%?*LqgJ4T50?$e)sT}8`?M`$><7o z<*kl22&_LCEXq#UXoHA7%8iq`Ji5V)%0DO@rvunp-J#pKTU;j#(L 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%0A$ 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 Y?}j7Qy~fAKq#ykM0oEckb$<~V03>9Sr2qf` literal 0 HcmV?d00001 diff --git a/tests/data/openSUSE-11.1/suse/setup/descr/packages.en.gz b/tests/data/openSUSE-11.1/suse/setup/descr/packages.en.gz new file mode 100644 index 0000000000000000000000000000000000000000..8cf954fd3c902cf5b845425eaecdfbe40c610e89 GIT binary patch literal 401472 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 HwD$(~Gz9ObTmYJySYDkq@><(_Dsw#3l2rTE-3 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

9m*YNtreL*ZVqyRU`l^%vdM7 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�H}X?V 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�UN`CXPOr+LAF)B|{5Pd8A5s#C}jI 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

%BT4m$X|P|CQ9-l^i&-yPDw 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�!FZy6A2YJPg3w; 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 #qxB&@}NLxG>DF84@bQ~Ls&o{>)GIVC)t zNb$4n{g03Two?`%yZYfjfBx_9|M>CKA3uKl<70W;u#u0573HJs@tiuMcxMDAE_wVj z5acyH1;9MPr5|7Qq?GhPh5(E^gnXnP7;e$*i5^5JBuD~DwbB9tM{5ietPPXaVJVdo z7~$F(G>A(bzRAbtsq&`LnQub-_wmm$)5&z9XB%VRMh5)+CjANt@AZjM!hjZ^BN-AM zbRUo5%x3HQAb%nTFqjZT5FDADF~r8eJG=mv18qYwNzH1dYf<~9LjWNNs}0snYfGgi zPt^->OpVyR+fYw$zv;XesdD+-mRrA-;~?JspyPlb2Ju9Cvwhr_&P@Gv3&Wn*1pE0* z2R#v`TtTEYV2)d)kYrpF0G(es1mun*C3$VgxqA&B8MUU~tSXp+?FHIPfq~-2D(YIh zC~BB24yq!X<)%`cq}hAD$3|PXkA?54 zKv}>HC;761uKD21m2=NZ7S<*@<=-(+k!03a^`upRbDD9mFS zL*7cxcTpH`+GDX0&M5qfMkfdWCdc_6cRS8XGR4 z!h|EqEN#-&fd33t5BZb^27C&+35B3%XEGF zw%wYaE-v5x^6%e&c>6;iIQ=QC<_KN_?`&}sSjr?os;9OZ&|2`2 z`c;O|2@3&MBUiWnPR#<|lSxX6F}(!R+#9kMV86U^QA6ToAi~m{iUK%8gm9YjXQFSS zld7Sau-ak!T)OO)HekOXf`?^PCWQ9Nq)Zg$66hH!$T@zuYH$OP;>SuvQ$ZrVDFJRM zj!2?e?;+vcmWH8{{Wr-jlFKfNh{StjSEHQ|9k z0hu4@eFiTVMA*g-QBZuWt$4LD z^Q+DJbLH>j$?{)eQa%_}b0i7nln|}FX2u{zw00Cpz-3)4ZnQN(X#28_#mlIGMaIk| zp#RTHGEfK%U2N7(f)2#?U-;>_|N7&XkDuVDdj((3_GI1}YcxJ1Bd}-q-FKFv;eCUL zDnA3WPc8aAWLCa&ORu}d0BpOCBa%9fhGbP+q6#&tu|p`Pa^ z2wp&3GTDS+Qaa>hFw}^&m{5l#x3vJqDMwi-=cQ`++*O|wW}fT%UibAH*m}n7{@o1_ zYT5RE%eYm;xI0@4epIuW;0KM_r{9}6VSRNq%RrOwHE;mZy@p6~l@MGoWf*5-f*~H6 zNT|I_x9ist$V)+MOmb|clGFlhh1AX%qKL8BXvn!i0&D*uP(Bks%p*BmTAY?33yMH~ zwp)LZ)wcV3fz=YgzRB5fh*pkDU>)xN#raMLS)K>8Q7l1PykJOtH6*NtVg8{_!s zt&yh&@)w;TsO6PtkT&cx=q=c=9cy)?L$CqfSzfo3zUwBv2deg4wSKyUmvfByKdE!8 zrLr2(SURl%SV-AG!ML+Tv%juTjDi3-c;kvreBzB}sVH&`Lm{96hzrRLw@yQbxMbdr zmGvvao-M-ux{CW{09RXRT@|7uT3#9qO(5lGc^5A|KuKN9Znt>4>bW*IB_&IbJ~fn8 z9bJVp7Q|bS6Nvd(9Q~>;r~1!-{3BG|^ni^Sy-MqqV?ZH}sJ9x0lbULzA*_W0h#74u z7qu0F=*}2`m!r)YCIApGymgL=~33G1nIyB@O5W?Epv8(mj7{@>ll@K<(+ zzx3=119??-A~6as+}Jl=-#$qY1n5@IRnd|eEFs0&-*wX;zp8w{xScHR^?bToO~2T7 zVHt|tp)AjnGeSy}=&|hsR0Hx$3L8d}Pbh!jQWNCqU5gE{h$~2hv94B(P(%Fc0|7ut zIRS{}NGd=HI;TvHhgOTHy&`-wH_U;>q_{5hy+8f_>xZ4nGTW<#izi-E7MBne7L>mG z!*4%9^eG|fLF>>7mx`NtDZ==fCR1z^75RtjA5Fy)7=!kgY1UpP?K<+^pna{TvspT) zR?D_Z#-MMSx6^s_Ebo}#{+V`cQc8`Ur)`r`Y9bR1+KbDyeU;6(%znSTN!oUqj&~}( z?xyQ>g3GB(+tcJ>$^AZdG*KGb~uC2fC6 zf4|tw(jQ!{Q^r}U**xo5hr%IgpEg;0mbFuES(@x7CVdafsa|It*#tASnx`*wnQ{1X zkStS?iV)}J@?dZDK22VCczx}IjVucztjUazws+@#O4$?mYZ&f2$M zQqk~bs?~MYW3qNe!}I|*NbuX- zWrILQtlASo3An&89K5;k^0y=>k*RASk-$nbAhhz*nIHzN zFjyE@BgS!!pvww*o!>rLB4d`*)m2p8FXULJKaW~d^QJ&$3i0q+-^UMIwI6oGiTPhY z{L;rtkbpu`f5sW`^KnVWMLhdks7u8s`~rq!8O1aV%GTBh>x_0< zDF6Uwo>FaVh%B~}af_+{`(zWr9&x;3w(k_f38SITdSz(%Cp;<7(G&UVedMeP<_RbE zL|ByL6`RQhJepT!!yMoYIN|Qq_TB~L2q8g;ROEED*l)9H+#&pt;?QYkxl_d74oUx( zxV1=d4S<1u;Q<~%K=)ZpdeQTe^Op24_zc8wlegrsFcw~wU=u zgm}4B&RU|Caaxm*;uqQ4n_s3Tp0|XN0%=Ss$Ck?{D~%sPQa>Z{x;;;qRW@ii<$c2| zRpgZs^0icvXaJO5cFg12U?_k)gi8ELHK3}H;71bar6LfFjLX3|pZ+<&GX9;y3kdzP z051qDC2|u?2~>LlUlW9su&UP5I;s(~;cPmCmO$&k)2W_&A_ISv%6=}Yd*p>(k44KP z?>jE3BA46;A_oys;=CLa+;dxkiTI-`A*6I>f>5vC5Qs4yxq2)vW5#d@CLVSaluk`x z=yeT5Y9=rNT-CzWRCoiJNtoIU28aO!QAm-l9S~4u=M%o&Nx<^?K9Yea z!Ay^f0z$w57*ETzX!-w5^0kM|PsW(54`P0@lM;gwNOqXNJAc;`S~@n1J^y(H2(po3 zXyHzM5t0Kd3U$I;9z;nCQ8+e$kwTa`E*XSO8iBl(VyzgY=nRb3Cgp5y)bU%}`B(6< zy!fP@{RcQ8l1COBIlYAL3z6)X)1E^mCtmNNgprYgdZ~@oH28!ryy1O8OD9F8(Y!{M z10aosngQj6j9Vn*diZAq@i}9i#_2LrB&lPj%$Zjf#>qG zW$kS5y6N_&l>2ovTTkcKOx0VDzJ+=FVWw{Vn=E8m8sM>+eZca${oxJXq$EO1bJbH^ z03)P;grI?u2Ri3VckONZkO0w>R;pJO&Y2=lh9*!W>68q`frWyy7Jx8ojl-02czp5F z6Wb`JnoSp*o60{?#dZ?0m98E#*T1#xf7$HTpT6YD8QD95H>0NvH~Bt8yI}o94sM2p zJp-A*I?nN~o#PQJoWyy1*yIWzqiG_@NMyAov2*}|BQ7RL!m&rQn_F~=Yxm<>CwZ8=CJCv5Q_c#@5IK?U(*iFdE^QT)nLN-$DkiNxK3PhKzNe*$c5r!< zamOL7G(-MAq+r2HNa?br9>9xVeCPx*|NC(n1m~-z(tm=OOEHv001^Q;TYgp(M$3L_ z&Xsi%IRKrtoO&IUhRt^*{DmSY-CTUG~DWB0M>^d&n zY3Yl|AMYCu8Kgrv-po4)n)PzPgFBnAFwK}7NUF936&AaYTAWQ7zz~hxV%n^xIvmYf z{6#|Q&I>xB#pK|WOK6}{*isF!;=*tWtX9+^XQJK50HN~PCkKBdv(4Tt)q2-v8I>;J z=#8&4DL;FjJaV)w=@AqaXb+*RyAbR#L|yx%isqTU)4AVulRqe}Q95T2_?;AD5T-uh z0mapp-crOAwVA;r75FR8$AT;|I8&3qOXYj0BGV%|zi4XKfn zmPo@n*A^;ZYbhxQj;R_8BDA2QbDMOZ>i7V3>O#=3ZIW zBin4baHnQ66ls7`prYz%D4+tx6NPYW&E)y*>i=d<*&9e(=MnYqk#YaFiXIZ`lmL!{ zP;dd_P+NftsXSH~a6nirB;v}7bBU`cdlHYSbX9gR-dX8t>z6Ckz3QVjx>5*n;To2h znmx_njh>w%@wC|aU8(b*?lbh$?zk=6zHb?~A{XpPunw}^{mbO*bp3gvjG2an7HYOV z_;$7M82IsjfB5mkA3y*8+sEpMUw;1aw=RuqBxs17ylxc5X+hV*6I4C@1)mAWULl)6 zOaLJx7r@~yds>URC#^=vV2dT7oEuL*(+YW;kyxZ47lc#GA$#?M4z6uM|J_dao)Vo$ zn|sB=DdpOjv)7zxk>9J;XLW7ORyvfWO!5itC$5h8#izZ)AsvdXG;e1@{=ddy_t>;K zsaV_ba|I)j>=$eOlNAJ-0D{8_BnXg^weW_o`1&r9W(8HU){;Yv33k9sWGArK@J(&P zncvzXP~&fw58)+9s*@KUK8+|mUkR6E;IK5?Ucaw&+V_L&gCa0Ou^`o+hSUnw-yydM zCBVxqi~$|DFTK#4>y=&g_7hjY{<`MN0d81Dh&-RCjef-@b#;__}R*C~uO+*ZgJe zd3iyot3}L5H)!=2*HfMUa%k(ZDu5nw|D?OP1tTDzQ8|buZF3>*=g}MOC~qUZU*=vl4`9QKEI^7GxP=+^bg- zv$4MC_9pCZH3%u7No~CBL>7e8=~_TyCG7xoO*pk4M1 z`P0BqIiy5|B5Q{XcxxfxnOSlSBO#&Jfy~`_m)pT}cNmfM@pt?dCh9Rnnj#XFe)dKMe2r0`#9rBW*V#B!` z37M!NFc@iVm8!i|63j3|YHkp93X{(C3RA{F)iC8tl{1I@&U=C@U!b2iuu7D@X)eE( zDLWpj;Jre-O77M)N+ojU|Fd@`y=^4P`tD!BpMO^d|Skh6nRAg#PNlN() zGleE@=Sg$y%K9Auq0`JELck~p7U7^Mri4+j6&%wjkZ7>fQPECOzrkC4mugA6eg@%p zH&^r9Gq1t6?tI7cjmvlakK1GBUmiE>@>P^4)L88K&h3TotGi7LlD?e(cZCS|V?Yy< zFd(SbQVDW z&o$|X?KrNQxaC8`FGa~OEugC7eMlWN((*+Q#vD1!X{2mmt%X!1r$bY2p&Z1w0H7#I z)KqP;eX#c!%`gB`+%Pud_=e|F8acAUfDicaFl17v*=$ObfI;3ZlC45uje>66JZCi6YyyJFl+}-Ax&gdQ! zV<;R3atk4?`T_YrQ!9X$ZE{=CnNGJ8j80sh27&UF#1cXqFd`iGSTpYtb3AGvl?q5x zgs1_>6a^eQjwn3ouQkhG-g?l_ZRs7!m5Bl;mKn&i*MbLs0v|$ZtY%m#KC$!8GL@$U zk02Qv85fla&kfK91~ym@ffLPx1w1%Popb=4)UvE?x^rnrIE!7arf1|{5wbFQ#mlM^ zCwP;knS7dkdIKIF?PW!xw^47IYHC&# z+YDaS4NH|rZd9&(FqkeR1}4B*kpVeHr6S&I$+R~HJ1ejy4osOQmX&TgcP1rj7v6;X z)w1@%im$kos@1gT$hvt(AINoDQ^?d9G~2tfDDG$t?bKG0nXgxwz`xy5epRe{DSnO-b1xL2SSX~;vU-`#H z*mKRw{u$hM&%y112gvBkiWf7gB)f0LEN@qN?kEqH-}J!oxFvgz&cEK9W%X$XN0zsk zjE7U#%Zh``gup{5uenLclp=! zbcxM~eSs)T8C7ap)wEjtJ|*@YGE|$0ePq&Us!-(4c;+O-5c*Zs&7ZZg+WS$$=!dT) z)%!Zn=g~81%O>065MK%jY^f!})3|cu{47a3GLvA)=Q5Cu@gB5-4n%9}qmDitVkipD^N(?&Zc zQxkVYnD*MipA5yr;B7sc+ozk6HJL+jYqwo=u`<#`8VtcM zgcCJIOG~a1q~dIrx(ZFyM4z{xOQTVm8J6-!=kma@2|`6eK+v$e-X-eqSt2OEEb_9oiZd)pWL9>kE<{|B7y@u?=JyYakjV&6 z!1+)^r>LNFM5OCq7{9z@VGG&@vqMjhCQq#^NZ^X1M{7ouP@>d~NHTF(39y%Av^IMf zfP{V|2q~m-*}O2fLMn~H4CDz$S|jjJjZsu9N0eh&dzy}VEzn!d7e3l7euk~QXCr#G zX}v9a-~Y8Mf&XJ93MWn@JNvrNYN-QYa}KLdYJQh;_}!3Ivv(Ne5O-&Mf6R;%w$9L@ z!2sWv(HxS7yEu^~JqNb?c*U65TuoF44uuA}G0lpoCOi)GM1b|ciL~BFkF^xsIYEsI zf(0CfSDq?{;+qBixorHN8T$OD7e5a0pMZQ1?7g>FbLr7|e*)&j30$=r4TqA zNQ#L*{wkW(`%T}_nZ!3Dw^fciYrn;p+r)BQc+@QBzfR2@0;69=}-5p#^-6a zF0e=SJq7C}JSX~#4)tSULuIP2t{ItXO2n@vMJRQ^%q3@X#A!szB`+Z&TP1b4jvgZ&r`K3i+AHf5tlez6FBYd%3v;+4$X z!||)3lpTbrL>i$PAxKW#9<;i>MP=Cl3Xs1cIolk0!HEa|LEE5GmWB4n8|4@$Oi^Y$ zk%R{Se2@E0+vY!_1$uj1SE-=&&x{3{_@zFnC^=?ifx=zhH@7*$0?qHGOLytAUxBYh?`c z!8m?#MN-q^@_AtK`i#F@%pI}+yZ*QD^1jUQep~bWqzD-GPGEuyH9|nOX4|1K*Wp-8 zJ;PE>Oc71bxZ47EKy6TPqnPArVMzxQH4%#1AR^eOiFK)lE6$lA7BNSmit)~*o)Xw#3!J$-5r2bU?z+3zE_HZ7v8^Ly%O) zP)k#$3?vm;%@_gZo#+$*#b$wu%_=6hfZtHW(*L0S>kF zlyio;59ne_ZB&o`qD^6MS{>{jZ=emjU;IP!&5P9YzIF!6rXba69%gCM81R0I3LXl}DFcRD$&%MG#8ta^r6H++de4OXp)ms-SOtkA2JB%N74*c!6 zfBfGc|2y21aQkpug!Os=Qb4W0m8nGWojOy$v4~H_&!xEv{QPe4J1uOe&Uxi48ruNv zk-z`(*WZ8p%l~{7`%f7TWX{B>Prz_xu_p3;P4x3qJ30a<-Kc}*;hGP4a(F0fN(zgX zzI-SO&%j@$FO@Sp-}8X9p+b5jd~g^srws=y!cr=IayV0a0j4wyU{YV)BKuiA*O7=B zijYGhWh_ft5ptz*fr=wL?yac4WDm@TB*GD*;9Z9GkB|gyoZ;*Ofg{#$(>x&epjZ%! zXfnf0AT_N>TJyY3O^O3TK@o|h=7M;Mypu8Vv@XSjRU|kSV8VcVQ08L?v zMH`3c0-zrH&*EH#DPGcd zt!!j}sw4E93|bR|l+_Mlti9pXSu1sP#5fx?^HQ6j;)s>|@BV;r`N^;O&obs(IPsU% zsSy6JTUx&^BPV%G_A~O+G8sHVH6wUp|Fv?qEiMV%8ym1R2rHQi3QJBDVGLYCVO>BB z6C|Y}hQ*-Vr7re-@1`7Yel5ji0*4K!e5iTl*uX$HRDGb5R(1O>AC5w2N{l7`78fl! zneds`oXn^Oo_z^CIzqlAj^^spBORsGlo09&M?@My{sgSeG8;WOT`Dd7I|SJ%I9g9Vy6ffXf)nY91MN3+L4n1#8l@SLn-|5K z%%;YTOYe0&e!UGm_q~aSJGa4nzMOB5e@hJ>8s0rt6dVLUfT4r0p-KZM1`WXvBor+H znN3v`Q!HmHRfu^J@OMh>0Q|WZ79(vnM$B@Ih4%t8=QWKi+Ng+T1iQ%Jic&l8f?FTd z9W3`Cyhqn;+L8ku4t(LN+Z(`L25y;W?DO1rgBa&haFK&pqhAjIEk)|sOi{(v#JtBe z*Jgn}>W`}2DWX2j_zlU`Uj;!x40kBO4g4ubm9j>9DwIrhFQqrqI3XMB@n;-uf|7kA z@_tPR_+x!u>u z`#O(r9@pWES%={Tk9HH>aIlBA4>jJ3gtt+!A5JS=SZ_DIaQ`3cm49^G`RDoe+b_R| z?U&X1Zoa(z<)6Vlu3>C{?sa|79>#|YmO7P~9}1$H+@eElE*J-10-F&;)5^<>CDBgr z*R*DrEVc2$3grn7o_S7aD&e50Q!!GFG$PUwf`*F!XGks+k~?fR422TPiYnZZP}dor zYb91IsCx3LBbN5O)twM(WlvY+3?MoB z5oV}ErWWeE`xc2Ii%nR6PCdiFv#9_3KmNPy4lrU{yIQX7>cA0`zPYJ+b5MNc*$O0B z%N|HI=xm=77S0AN0VU)KGAEkOh{ii>9 zC$Z(~KIFc{bj@`@5v{7k(IeGUR`skNA7ENGK9bQrSE6VD&E#YKM)PW8EKVAcS_+iY z$BXbE#m_#4Ap+J$PL}KF! zSkMabV1#s7GR?uaRIk%jWP%XfFCO;8^?DJNzW-5(DjB85QpqaMg3=K{8gk;W3Yay|G-@s};&ISC8ku88 zA8I#=@o3ZK_zp!&VJ0F>w7@gP6q2Vw=W2Be0s$;fFnG8iC;| ztu?|qAuaI)V`^Y}FOUahGY2}EQbjMta6Knte<(~o9B1(+20JGV`}{jHcexm+FZM4# z3^xfr=S(QAr*B^A&NpA*@757{*4CxLxX6%p9y6p=s%PjU;#AuxQ+e!wfEs73}IT^tfonb@-h z$B2;5ONpE@M&Xoi+1r%eouhWKtAI`8aC>;4kK6g8`Tg)MDfR!H)wjO5odd%Uwc}ux zwv088mJWe6v^X(K4_RYq)e?l{A%0HR7cITHjRT5^nbzV3W%#-it{&#K8IIAOmTTAt zWKzjwDWs7>a%zzXoG3*!r!q#0vB#lV!>v+6-nqy1qOr1?gsrkh2Dvyzc%r>|>5YuT zxX(*5I-nBw<+=Y*nK+4^dzvi`9Hs9{AT+W9bvmY|I-P+%}ee_pj*3nTNJnBAnBY{&AiUw~wH^8!-pmSnYTRplZAY!C#``OZ1OxmcowgGLa5 z1a(%J1Q8Z|4HLezdW$s6t7Vq1KYYzFa0&w#X_@N}W8agn*Gvu6)nm)ha4Tl5>9S?k zhBEK_GKSu5Q-35ZrM9i7X)FSl%U4sPpi0yH3)LY3DB{&dRV!v_u3+U={P|=roa*TC6CuUX4i{ zBnf9vHdNxCk_%4)(b_f+x`^LW+xdF6nwH*frN``ObH~Nv0k}9q|D$7WE@mx{c8KL+ zl9BT^Nw8dSL{F_2HhiZ4dzCe_mfqZn=8m(FD5DeqP=&qy0i?G*1i^^`mKupM^jZu> zoo%*eRPfXp_@oVj`qjTFPORVfq9LdoS+SwFmJ@4=yMJftF;S1q3U4savSK~L@-WE= zCsHKjfq5PXIr ziHCLRtvn#viQz+)t21hZRC>`sJFh?joG2kEA};ZIa3TRwN&#&V0}fk25^rBVO4+wv z>NS7wKY#dX4D)Y)9k;!MFw&^DvBtkdXzd@|zO$dI$i1uB0FfKN;GR)TMRpr&tLwr> z6xYg)^~LQrHDiJHNhixsS?$C$)Gu{1zWpmb)SgB=!LQsrPI|(neDnOI3YvIR_?Nm8NWkM+co}Y=ZUbCgjs~e8{ zXDi5|OqkMu9i0^J$uaW-9}|6p+#0BFm#uDh9ob^5X|%m<8K`u~u=O~v+i`ADrY(}X zZZ}GY6-F@^SoRKU>v=5?vx+3F^TOGy{zOUyPh-#b`8r<{zkaBJjF|e*g|v`Ju1t~u zZjhI^jtL381z@y6kT_)pcjl4yc7CsZ$m?951OLt6s~`V+TgKXd-lpT`;}Z&KsNDiz&~ z+~u|r20+r=oYbEjxr?F_o8NjqGH-uqzN{V8w(jw+Hz!r zTPt-~F>D>fVMj{twxiywtoF3~s-h_$-jU-@=RnbW23yzLG70q$22}qQG5&fBV1~HZYP#Y7HLce+ws5a_CK2!4P;62^tq7ipf)GKDzPHK6WQiQu1K*Y;@j$<@T!D(Z<|; z_|cr%iXY9K>r2mo4JFp)Vt4czQECs(Z+`n3q6;w5+q)XwvjqJI4tH<-gkHD(x7oc3 zMI&Cdzw-@t-P^<&bJ}2&l}XHc2f6J}mWLU}s{KIW0e~SPPuys2AJWt!+0QPPB?Cw& z5=^)VWjzgp0%|U)gBV+?fk;ro5I0mkxhg*=)b3gBpRkHO;cKqF<0)oe;ihGd9-B=t z=qzWx7*S$}F>!=354Ce1ia$ri0g2b~K#V_|dO3&bM#|+#Cg=iE99-8=Cf2xK_?P}~^+rQ`{BlpAL?!a_QRccs@mRc^XYKM{C*DDR7>2i9@zd^Upv0aDn?q!Jmb#AHr@-b2e|xJ={TC_K_Iq()$nkN`o>SYKJsJ%5Kik1x??!8s%cdf1+gVrNY4X~m;EmI% z3_GEI?)Hn;+4XK;sC~`>F$Q}=2#LY5UOV;We&R8c5YtcqmXT0m;4WCU-}|2dv?Sr0 za}B&5s+p$15dTj|(#o(<$}o%_f!KA#_F(m2Xq9gAgX$TW@Nm^IMBf|z3@xOmX2$hD z@R(`(9a9X_Jsmi($uZ*o9(iJaCNRkuF!+jv{49U~dYX&r?peWHnwRuIGC-x0LRw|L zgtrDet`tEME3Et_PndQf#u)#(ThH^vqklQA;L?0peu8i!#?ySbDAG^K z*4=OEuDQ6<<2{Ac`ZD)C5gDuQY7jWyKP5yTRL6PNW)3hDL+8*wsn@jNbQ5;hV@IL; z2K{AlwskUI*VCNCYlb=Y#-4x(-wmy=Dm07Ll54LjX&^Wv7D|B(N&K}}ZCqj;;udKs zFw)-!R)0ZgjUd@G;5;VaTvai+xvItjxXW8NLCsb5s6gYVI0rKrF@zVvS~~FrZT}du zoYx5nWC<3+0qPQ~oHvvt;+R{nBnrYj2oa1G+2^EsS~wGpqMY`zj`~vnUj5saRjmEp zD&lZ^`xs5V-IPrjQXifsA~O9N*m4X(@6yP<>Dq48N=3%rcv~kD=JRe7K3HTj_nO{6 z8o~Lf$bN&4I&soJxruXBW!Y!h@g-yji3<-ht*SPdd9(Z=k1Rm^EN6EXus}pC2*v2c z><+~?D{T|-2J0Z!sGDtqcyOr|OeT^GnsAK?6F^`|sK&}Eg^3pDet2-Vc>6PP#*ZeE zG7ZS#815Ybg%9n^AHApdb~QOhCU9te^T#i5f9m^P#gKQ`_T}=$o-t5{)l*xO=F1>i z+Q>mz2h#3WcUh*ZBAZ(KUT@?RjBkoH-uX*+dV5!+dqDpsU)f5(syjM=zS3E0*VW7L zh5GP6Sg+UZP$!6hIp^H{Q@ZFobj~G!_G2vTw_6_GE#^SM8KVmd5I*%tx&Cm;CjaY3 z*+8Vjkf}sKhXApZXo3;cP-z9cm_X1epve9l<~+IS&axqzi$#4@@6%;VWFvHLd-K(* z3Hv+C$S;#@%OxC7?@mJKT*ORE;8Td#?VX3Bhm%yL(8v)$xjS`%{b?o`mb zDb_gki=mX-x$YIJ>7SEIhu4}DPjB<>+AMxl)}zc96;Zo4oRw4rNX!<3z*FOZ!;^Hr zvE&9J<#1xDlu8nbZ2|}gMO2B?%wdFZNXp|4n0*no^W=fdgh-z4r=@?tB_l%sj`hw- zg9j2Vb7?25cC%El0X805#&a3= zjhp%aTCR;t8-rr7+1BkCTn~mQto>xl;#pAcBuW6$8RJm5o9TQ^Ma?pf+Z$N!jW!|8 z4$nSINmjqetQbQWASf10QUOj&Slo!rl}guHo)`5A^$m8HM9e5jk>m(^@kJ79v9W|{ z=ZvC`YQdC3)||IUJ0C;m)&|W{C6vAu3GfXgXRV9Z)kr7oiyl``nHiCrCasOgy)%6` z{2ts2qB}2nmKZ&Fr&+YdoN>BfLY|r-aJ%u!$-CqgE%#`ECJE<8B zs2sR(;MQQvJo`8%zHa+5WnMg>MZ$>6G}HAFceJOO+eH5=UD?rRJG4eVK}a=IMhwy1 zRr!bYc&sv;Y>SXZr8D7?dGLekL!|L37R)*}zT^f?>P=03y@gTRDpy+D8pICG$<~_M6xCudJy*b!f|-3vH{i|2akoT9nuNecJyTo^O|X!PIZ|m_2Ok zUsqmN_4Jpz>t4I(_t8B5){ynzYvmfi!?N$xw%X@ek3la*%i4#5Yo2N8!V{@uIQz3MUV`?BnTrg)r!V?ZG0S+e+i9}-JdU1ul z5Bs8BxnI>84hGNpgjQWqug-s~q94~U>*bw0Ie}A#8@9sNTZ<$9)BR-Nj(`-!ftj$86nZ=VAP6=NlGqzFY3i z!UyHO7@1+ABOmJPQ(vlP#fEdbKy_aQZ3dh^boB>-iY^F++n4*fL}F2q1PCt>K3^9_ zKq8NyO;sMRLv2*?{$u+25pW560aE0fXeifF5n=aLUE`jkm3rSYf;bNeEEBi9ls$XD zSHbfA&YO5v%+xXv1vifeRLU4)msXg2(SAcI;U%z*azeZ70C26UIIKX zzTPZ+S$TS2lNhVGq(^6; zpZIWfdqp0m{`KSOKgSqfv&4QTMZ})UhE12w=W(TX(+)rOhX(a6l`X3%q;wOpohz>F z^Rvx>i#K_ISBwC`^0Zyet5T=yD$TNB&4seW9;)a|5lc9%7~s?h3INc+D=gL+0jSl% zAqg2ys7AsPuFqY0xsSXX&xtfn^({KTG#gWiG$zr$TCO5qU(abYzOb-3Kv!*W^15DE z2hSo_Y!B?3A1!OR>j{a@z^~hpPfyf2HfpC3wkGxcx2u5MrTeU=~J>P=ciXaDvp!jaF}4e#41 zJ3?!Cia8PQqGNoecHLvD04>ydLwe^=2wpP$qI2B{&Ha7dI}UOcHA=%(h06y1{z}cI zt@_^3JsA}j7{e0}T=tJLxjxJ>wkIl)H+`{75<@8wD$xc3gc-8VVMqW|j%(>uClPvAkr+O! zDUmbiEw8fhZ(7;lti2n(Z7&(Un=!>O}DuWN=U+tha z(sZFrSHsYGmRTLV(=Tn{%_{FGKv(ZQTzYE$Xg8G|w#V+Tj9uk}t&q;j^i+pjZ~vdY zC+ltFNb}vlf{(Mvwp{lyYY&h~b~C|Fk^!6n_D!f$=784T9hm# zu+6GIzV80+GwKa_X8hZ~{r=0}AFMM}oU!k6=#RBzh+@Rj>O+*X&8thO5P~BK!ex25 zgpiZH=UJndj{8OckT@tSKo}*gpj;!Ut<;PNppdcxI{-CvFs(zJN%Zt+`K#l8f>&?A zRH=97LD*Nj{<-E62R`3$y8D>HAKO?UA0(0vvL`^H#%%T$1ML{@Jt@<=`%`(@8xY1F z?jSbO;WLZ`6%&W&lqTW0NFl-Q6dn`mr65#TE&*~#Ig6CBj3~_jkyz665GhBi%6gK@ zt5-g9G(HmWdPL4wm_Nn~;uYGnhl|rL!}6t8<~qpM8q13T#NU0`UH!Rr_0rW63p%eR zPi8$HV~G%raTF;jL^DJr;M4jGR5!V~>oAp+uZs#9ClrVG=rx5LYf6ohngF7e!kj=N zxCcF7SNn@SW#DYT7MjGhX$7GPt?h~GMDx#CwB@)glu3H;es39eo-f&q>M)-8{EAAS zMKEQA#T5*(pzZv)@OS$W05d$Ae!ElOO=D>{_ z_*g=~XMzQ;`6!mTT5h&i;WOUHHw6<=1*I!k_ymh!)q98lhgLYQ97l1{@tA+{E%MEi zs%)__)CGNsYTOIqObrQD>}fT^omvEUAB$>T_)Pg!1K}vMA{YxXlYDZ0M>m2vYBf43 zjj&z`Nt9v2P)3|`hC1x5z+Mt$u(pK1GO8!FE%Ps#nA-5ltxn9XO4G39RP*hik6@43 z?lDwrQ}Z+oYKo~@Ks0J`BEbQg5rNV4Y~OE@B^^8$;7IIhX^UGw#u$9%Rj1`u6?s+Ms{Ce2c2$$&eOgt0 z(KFSlD)`1VDk(UO_4pi48!{R1_65RmT}mKF2{6Q1NwH(r5@xIltji*2wJMxUQ7=jxscwyzk{{@2RoH(^}>4~}%-+$Lb%7yfRR z|MBZj5cOuRJgeY%EYTT$^Oqay3Ie3y9uG*4Jy}K0zMR-eiLWW<_=mYQOY6)qyni+K zgSELCG+h5-(_TX!@bXYfGt&zk#fXObN9KEu~%}yzCITb@JuYvSdKTE)Gq*}B3uwkC=jC) zwYJsL#@Td%90Pz{q_X)Hq5?x|2tn8qj4d;q0cjOb!3tH*g#RUy=U&pDRy30O#FMp) z+|xzlxphlAUm;WBeBK}_ZbziASBGjrNg$o0_l{ZkC355&XXol|K0EF0KezM6d^=3D zx_^3F4QGoq`&@$o*vsaPux1UUso@JyVm_mgOEPUpbCqmN#$8mzGHD@{Ja$HciUXk> zMFvsKKv)vqSWhg*T^Ci0i=Rsh@3GQ!UrnE`>2oBr=&a43v&iV3+70AAVj>Ljw%v22jSN zVo+L4tnoqwh+HF425+0BP2M0hok={GWH1^0U4w=*e ziMzw+Vh~{{pN{N200ibp}(jP0vJA>g|cno|>=mHuf@8%HA5UOw*0&po7pv+z8IYqd?wok<9&GD z=799xmqltUeApR+{z8@D`V*3%r0l+oe$_v=m-&eJ+_BsB>xQkHq0c(3uKKR&u(sYN z5B)T^ZqK!Ay!lfS{qjDj(U}#+ce@2nbI4`&>g&yL*=;bSH}Q_0<<&ynwVlss8zfw} zPTYLl-ClQ=b~o+9^zHoCFWbM@!&5e4QQge{-RY5YxBEo4%kXE{*WLR__dC6Ri__g6 zGBGKo|MVx5P|mv!@9LzidFu()3;;laZYIN@(+YdmYPDVFLsNnRDE65eoJnW6fs8`r z;-EMWl&}D6V{9-voPm&Fip&$~X6K?&?AD18|G{D{F*Q4`ZWalj#0%w^HDV5*xI)`u)D3B^cT15kVlVn0U?yONwYS{VasUOJdOZ=NtOhoA3I* z__A64Wm7!*f8F{v=)m`z{pB?~n9@aM${|Cri^?S&SqqAUvV$lNoR~>5)pV$CgHd<| zEf7;Plda%R1tyG{f=EftopTUCXSB7*5zYmY7GZU0y4$JnI)Tn0h2t?u{{n4?*7q&G zZi&);0(g@^gf{l0j_EMC>bvT)iDp`lpppK}UP>56I87rtAT3HsOzjPqAi>r^V6u^2 z+^n*)$Cy49gd!l7@dg8j4es+v%Fw=MZ0iS_E$F+%!*q z{5bo^aOuh{9pluLaW)HRK_@C4PQ}ayM@y=s7ib1CN!F5C;$ufp?m00*_3)gca3}$B zdZZ&(Ap!x==y~$#l%=}IL`~YJaq%`L5*Dd}^aV2h3Rh}g9*`wI_Q&}qSV4EiW4CZ> zut3{qW;vR5-ACOUyesZ-Kr_WI^=Y;F7@o93=mFnnl60u93uRWrn6OlllzfITf)l$Z z*7vFjE;&J2Q*Jajm~kQ<3pQ(@b1sFoBsyBT^h|LtBJSlZ4(S@uF2?%>;_>;`w&I@mLPfA9_p!Q8AF_ z05#YtM=)a1IFdrJi8`ONi=aS&JX{+seUyr+XpbaE&=AN0=12)?9XEta#V{~VLC>{! z5pPU_(hu1}sqx)Bypy9`R-oJ=l?Ow2$sRQBt8O5$-7c-QU~OPYH8O9;8EB4ljku?Ch8*A_ zK?i$C2E^7!z-J|{I)JAL=FJday3|78@u`LMlRtxggeXo@OX2D0LX@gJg)KFuDKv;oRDT-pNcc_v4#xq}%9rZSwtHsVG z3M|?i#c#EmU;gm(?>}FnmuTozh&HS$E+(jtfBo>|3}-(q)UMVI_h5Km zW(6whl*rZRWHmfP+M`_XVBSE+rpl|$r>hx?!7DVQ0n?HlcZ2fBk=BqyqKQ|M3umYx zK}{CPAb=`ggITU!tku}mMn>A$I0n_7tjeoPaOrw1vtF8I_&RKePS2$7YI=dy z#uxQT5O&keM=P&RS22~Yi;BpdrIOi`DejL-X8&qPe=yGr?*NUxjD8oX@cS}eIxnai zyw1QL3vQ9+++q-<&+qntn9OKUbikAPN&Tmqv zX)WMbDiqIAtcWo{YYvQ;)KSBg!iES3MbPa@&|-){CsXR%Z1J>8KIt*YAzw_e!vPme zF~2=Lug~fR94^J!Qv9sX#!}pC$h7wGsw9i*a;6>)cKA@kex8+u(|eqPlXMwKeOP7R zw5XI#b0_a-6l|bWal-L{Q50rP8<0c{mk9)Ch+xVl8a44wg{Sg9^$JkOwZw=J#R=j; zms7?QjIm?Ha3+kyQaaLd8@Czpn*tMyq@9}j>Yw`GsQeMBr2hBz8a2m6GN^y3_4aac zwJJT(Z&u6Iw#o>Kj}$xi9o-pSd2d&D+mFlJXGa6ASK0dPJxSTPsKX&ixmjLidcVVC zNz%e4JuXkf*^goNx;nHD8AACGaA7A(aV#Y?m%}2T7(%9aYRtWNr z+qyX`Yv4%c9B_xgy+K$h^@A zfbdTQoKnm=M!hCh;hHATGcD!_PJ(0j?7p=Gqb{PAQQW9;7d2De?L;m{4^KPiAMUQp zn<&h7w`M)x&W&2kVpHi4%iY@aBfLGhTl6uYV$u!t_CU@WfD=-cQ!Zvqh>5QBjmz6d zM99EJ93XL#it%DBHAWzaRiYg?&;(6@a-xM)lu~G#qhcxZzvjj&@}m{uq5G*iqsR?AkVVBEy$TQ1z{eulj=WWp4Q z6N;4D-LhYE?U->y zE9;rpzyKvQU=AV^OfQNUX!HEuJARX6SrKCXra64)z4tJ%^s4``ylo#$D#v=heiX<0 zBayS>_+u!_n1FajAtV#y)z#DI?;6GKGbz+W#yA;!+h9huq7D-11$S6rCY=z_NT`%< z`d*(rrRQup{b4Nqys|)Ayqu(Xd2Gp_qe*OY*5%~*k*vJDOdAUaeb+F-2|6KJ15zUO z4WsDu4)*QDHYCkmaucS8FICzDf>mumurVN!2ub0zaY(tKr-M90+aax-aN^k&x1Thh z`=*BFW&q1+{N7LM*)H&@wup0t>J#6aA>y?tuRG7Ud%<_r6(?7`4=Ax;q(mtbl%y#! zH=-Lr6RzuE-S8O&f=@M}gE0$BBR0SYQ^qq5wudzwXex!antRGAl?($B78zE?>0n0J z)k&`brRVJ>4j7U05$A|f`8%?RDvz`@!Ua2s*SFj`pgjQhQQdbV@#tf1aR$aS=zI|^L6R5}1y8zXRDamY4DdCKP>AK99yFBv^ z=FvNlvazw{vA&aftexfboxU$AHOndW0h+*1zy9{ie^*+-um7ACJ9o36T%2#bsDh_u zLf!1sMN|fI?IG56{3&v_|7bI_KCc)I+Qzi!SO0RCwP8+W=1>qbWEmq9^@NYh-8TCB zV=g@miZ2AIDs_q|B~&_%9h4@pFvT5L)G8EPar0o8NfG`-uc@&QVtUJ~s|4wudi?Tc z?WcoN8^2K`M(t@73DFdgETHA;>-ofl?P@e(e+DbimSb= zF89dV)8cAfDjy6>i_^~9>?ema>p+?EkD{nTNkFGH1>MZA%y-|R5;g*oqm~df0wY3+ zz>Fx1F?9lIl4k-s7#oEe#1wuuZ2^xp=KXZT(_fHT6A&z|W>u(HQDQ{CBR9fMVD})J z9%Oij?21#e2BuVEA7>c9iBVb zY%N@(%U^!}y?yjG&B0m@MPGNP`gMs1S8#WEO3?7hDiH9V)f}S1^%mN#a}U7a$re_v z(mS^slb8eCtcKV4>xUnHyzFU1x0^(4r(WFi@&ooR7oUbOwAc5Xx>bwC(j>Gxn-~TB zxup6hQP$4PP^>s$9;iln6(a9!Bm_poHQOikHMi=h2ZyxrAf&Bsv}$qYer5^%fA+4d zxp5;&zw1}van>79*L}>`6JfW#j-K#2-4i?Wq^MKP6-ClK`tYycDgY#L6d)3m)RekA z!VVFIqkzi%GP5e{O9~qt&ijt#yKbe@Z5hK*WLQu^;mCNg_M|Gmr0ish%AH~>CG#0bXXMcNqd7=svktq8Z&GY6I8P7yB@($9Y8_V6g}{AXwS zPq~zz^%QKO5mm|u+8;@*2vxdMotj7ONjUQ1oVXaiiq8b$lwuob*Q@_o&D6Dv7?a>j z{aZVQ%neZ36R8Z0 ze|xI5(v};`EXIN}W{e~7VWNO-xcNjOq)&YB1zPrJw5WnU75sc!+$co30SE=TS%GjW zJZ$|&UDpm-H=TYLF8kNQ2CZ&2{ABER%gOcI^(=I=)%L%Wr3){(dbys~TCUx?M3Yyx zcJ%fp_H1!;eHo`tc83?s`NA#NADca@QeT<}-?`<)e|&vA`7OM|`}wkd_xI|?Z5I1} zyj4s0!p_Z$g)%oq{prTXdGYes-~RLJmml*0Xh&Z0>+3_W_~#Gbe*g0isd%A-vi+%f zBOx<(U=TG4VG?Fg#@Zp{Kyzk&5ZN-HiI+wCQv7hx`$$QRptsTiK`A8&afXOD)@Ta^ zV;bRI*~!QD#{TE0Z(l~`7b!G7vsre22gZILJasdBu@}FtWok6Eejj>Xi=VEN^eP{a zmt`ek$H@vEJ9Tk8sZ$+|hq9TBTV9nndY76s6&%706D~%Uw_nX}7ckbm3GY0WrprVBTY+xz@%j8p$D@Ro*Hk)iy^k-Z8(8Zs|AWZ7+f`nC4oo${L0cT!N<; zpgp|u_pFxfXCh-!GI8okS^{EbZXL(0cr;D51iMyFq@|nRx@j2URsRW57!s{fEG}Dg z=aKogyR>mq@=*|yoD@^6t>P26lXuR<{!~IxwXVarwTb4QK2@ky z0Zfit+1$S^=XPV(lXsK##}~i2b#N?iCbR1oMP!={g8vQSi=SV;sbD*FDvyt-!D0)r zgU=(Hvuj0<@?C#Y)42ix9`1&L0AuL|=8L78%}LDRyo{NesgM?un6_aV_tbdq0A$Kz z0d;WI91aZz3WhcNRQol5U%#9$3!B{B761GC`|mc1-SWS$s}bxr-EYB>>BhKOf+_dD z!sT8Rt46i^eqS=E4)7g&KVI3eUj~Ay=E=;a(oU<^7_+)W)!LmNep6~%EafKX?E^pWC9 z2xeID9f5JQ#<1W1s2AI>u>Bp*`D0D?+-p%H;6I3G%_1g0;!BD8)MR)|NPHyZ?0f-o5{WJqnmBkWgZY>{S80<@~<~Py}p81&G#7GgSWWO z-Eui!CYnk|vS)kVNwIRmQA%vfdrsctW|x4~cJaD6ejex*`!tMUF#Mw+Lqd+Nq*Qy- zuKHTl&D0bj1Cm)Of~Ec4RA3|vNThVY$I=;;V%2s_1GtP>=V6-E+^1VBtt#xy6;NFe*z z;Xjj@aByX{+1A*+c)e<6iaev(rWCJ4XtR~OZ%WC_qvYKy`B?dYx?H#EL@vvPjdRmHXqDr<7F3MA1hu+Sar^K{dw^E>%0=W-)^ZBXS zO$liRMR21=&Y71ybNPOUB`bK1Q+i~9vKj+M3DD9=s};e}DFkt_nNDy-fEP@w&yT>n zfAZjns5{vN2j=>oB>{LLkF_m*tlC;p<3qei$Zd6MtnS+6|E}Nf>+KDXFAqIjyQu0- zO?z7EO$4UR{E}w>^Ih*#^(-Z4Afo~@JaX6I_F=mYra~kOoh!CS04RtTK3HYMth7>C z!Zan+3MrL&GF76Fa7@Yl%(y=zgPEisZHUrd;|>Y$PSd9@5huk=^yt&JS1C>6jKGXa zB*$`auHJ@w$K6@-68tv;KmY+rL9v%&v|*e&fdSCmYsI8PL8G`0e=&h1WQ+?-gK|In z?U45r6Aq-#oC@=n%ebK8>eaZ6e5Tv5=Q4emTrkM(w z&V&fSBd9i13l9K8Hl}f6gP{RO*S&dYBCE%(O?z_T0@TXlZ2sEibS4ku)M0Xo66ZHw z?eUBAoEx!Gp$|JByr~a`Grl{C9ds6{X4Pv)Q2WU4qxa;^_BU0+*VBjwQ*8&@61Q!% zg2Cp&$0lB<-a6bZI@rnvTlrwC7;KfD*5=Pz^A1XrV$n82b!q$hAZZ&uYe3pY(`f~; zAUFU>K)1hT8QKLK0B>>0H$F(-?RUbVWgGySNhFO}vVK0qZ_G=C zJcn@^QG4dC=Yn%UELYAl;iXWrmP1l~{J$p$GNwV9FIh~jp%{?)#5{wVU2h6rkHZ$T zPnXX!ljIO7g#Z!4NG2o;f1To6FAx|6tv+6D@nWDgi&g7EzJGp#69xg2jU|s%t(B%&VKfrFq*+PW@@w21{Xf>Q>Fv^y8l{v8kqPZ&!+$K1^AvvtAasV<1O<#u7~4u5YK; zn@L~uA8V^OtAS@1c=Sz$NO?r0e&UBZ+e3%suz$m9@sI}QwR6{G_}2vEqF;HfR|y|f zFu+76VO&%k3&-;tSN1H7u1K!Q3nR1;)(W7NG1fb*xP^*fpdzz6hnhmC=@yL7ueL=S zmyT1cbDJ!PBbF58IFgkd=W#3#^c-p{U>#{_`3w>f+;U0d75V;|2_Xd(^Neu7N74hl zoBgpSRXxl!FF;fvu8^ZPcm{$XtR%q%ImU4iOr$x}z$@~pvPNFL{GltcuYc|y`!|G% zgYLt+dsHo!IqXV7I2=jjQ%%SF8$G2~bZ`zM7yX^IQSQS+C2lavwHQ;-$Nm)Q-2Mhq5SgEn*(0hp-bj)MNHAlh)KjP^0 zqiL)pQS872 z^>NX@j^&#g;(l_4r>ZMMm7S;%v7#6SV%!AJ?h$vER}>5bX}zVE1I?vY9$Ux+M^b9Q zpd*n&S77iIDS=`di|f!M&>_9u2@OG7R9zdhTnrn!%z= z=`C$UdrVAR2X}Er(*;8iq}FPt!!OH)0+I)>Z@Xi4GV}9?#;J!Z5mbDPt_xW^9Ikuw z?dxCQ6}ZCVF#R#U(DB+3g&@xU&|)*%&RdDcU(Rh1^5(Jcok<-1O)Xb-UuS#gys}>h z>5?;>WjK~j5FS{i>d10CVL%2aqp4!CYt<_!LMj~aI)hw>KgMfTjt6uLD2bS`*m8HpR|Imc z_4BFc-p@h$q(YNgx$)XSf103#bjA9vh=d6!Sw_KF4*K<5H(x4HtQTsxRc#{6RSml^zrH?YVf#Ek;L++;h*!1L zUC7t|Xm@hEe!ThfptE4=JWzjlOgrjqNU8exb-k0lOHV&(sJ527+W5B0MsqZ~LSY^XlE?GR3m34dy5)Is$}C?tz37J0HvN z3E&9_%vh?hd~$qRM=)=bhHgJYLaUuv>?~oQ>fWKTcdF_|M*^Fg%4J$p_vBcQpszs@ z+IfutVVu&}(pER$AfdG=*7nFS!jg_$SGXXDA${|&jQpJo{8pqg+ zTS$l(Mj{BHaDXTs3^v-O(>yste0bilPN8tMK3AtBLt)68@Sj zzWT3=ytrt@Hm9`iv^jf_l&q=YyQ}iu8zok6rNAWPK#W}-s6D2{xNR3x);Q=c)zHxp zR~kT|Fc>RJ<5n$Zu#=El0D#5*T;k0Ul`OV;+t$inEd?F@ds@M0OR+AJLb2B>Iex!i zN)bAyjzZCPOjOwixYMTwI9pz-?g$A=G%pSXERUMNh*i{9V*>+QV{AW-;r_Ay(yDz|2?lt~h)e+2zJsaycSI17VHqRs(U8?BPc!TQ1@y8o0G4Ko zOCmh9hC+Y|R-Qv;CGtQqMp!MkVfTRcV6|+>=ghOw8HJQxJ%&uSDT+s!PTrQlMunh3 z`-u^OBMSu8gk;!yB5ScUR$v4*B!FN6v1AYmfDD(yOXw9v5;f%y*F`UyhKkwc&+v0! zI;~DM@`Zw^EtpBHyl;^_3>3E_If#q_lsFGJWq9oD=VZAs1*7?;>{*HTz#-_QR6s*+ zrN`bQuY(v8MH%%lGCooT+4+(XJW7qK1{+**r_E}0J>4VJ=QISDV^+Ps*B|8;Xcd%U1x^&{KN z%yP1x7&Xm)4c_JJ`DSTc7EW-pRd9`7Z)Vx6ncb|`%a7UXbwCQWw5zOnT3jEgt(nBm z)zq<#6pT^SM2h$_`R-LxDGeBjte{TE;~-*wJ9qi@`X+AEVV5zv0j6e9fz-@#$h6no zGGQVs1ksu@!Kua8s$e>q@!Op+yW18c5$^lw!JS&)6zfYJ%{d-m)MPpDYP_G%Dv|0+ zpS{6i$3Np8xsH&=_v2fgt}eXywcdZ4EZHM^dtzi-i0e6xXe zzeefSLU6i=pD%^ePE&fmMX8&W7RAyB$%*V&P|RNZLxpea;v(&ErOmx^)>OWoX@O`9 zi*}vK_gzVN(2StS-igG>O2u)xD}v)CVi^k0z^NFHYK8Xva>|bsrwZAv;`IcasLc%as)`y*wC~3p~$+>exNPQX?^iB839cPb4)K^Y0IdW- zpkTN`#-&35%Agh+2VCO_p?WZ_3Yp;(Xk0(N`TmEviHS$5Tf=R(^>We)B-vrDJ!J*0 zqYvb#3u9gJJ!t!`bv`!15E;+@-TxMIpNIkNht2LY8Bgj6SgC{>TytIjyWY*0dYq^{ zSzh;n#X9HR7Xx5{vCMmCV#=Pe-pBh6IIrKEbeIB@ zj+%!8l(fTls++O~naL_w5RwrKurpN6+W^vjsN*)6l_rc@&zaK11S6DaVU?xI2r7Zo zNHS;oP#2RCOQ`!o{fdXf;R7{`KQCGyjf$r|Gdn4ez96%9C-nDJkqQeBIF~ya+R^=R zCmF&)S7apUS;Nroemsi@Y%zKa1qCwMfm;T(fO4lj^}#ZL5NIFkS!pGywn7Q3ft13$ z@DSt|Bm&__PaNtLtnjL2hOA(Q13XcQf=k!n(BcC<=Ifn1L*BM`;vHFo!bEisfZ{n1 zVq#!*n)PzLD5^3<{}jJQBbM~mYly62o-qIzR@!l7nX-~{2)s8o)+wOD+QENG#f3=4 z=6COF4h@!gRWe1!289l!Ggguu*A)dKcq{a7dsDWdC~@jZ1!E%!BpjGpy3Tds7lLR6 zAxdu$j0QgE*ci)zbjCP`6+|3KFTIn>0d6fN6kLw0_R%qNN9&p=wSk`^m*u<;es`8! z3MT57L<4uyEmB&&OSM)HS;zm{%OMBFE)3jMR-q|u3F617NvuF zPaGpk{Rlb+CGUz-oxjo`Bq2~Sf^$TJJPjA9GEVEEose^d46)n`X#}I*NG7$14*DQP zTri`cRJa+!*#xDtaPyr32i7rhZK!T~@#3t*qh_8S!OI}Ihj3gl7nm>#>bB zqexh0B$AC#Fk>S2*<-*X6PPTpmqGv|;h^RQD8wA2%8_SMz0R@a@v|5vBm%H&pmX==Zoe1Hg7U$*Jz=vZNC>JWLpAK&BZAeBPhYZ^xJZU z+VNcxmMn!s0JhFDr-FbOs2L0!3;~uJkCoAiNET=Sr>gW+$wDCn?N7aawE`;*H5Be=h}b5IDG>~nwZuCK{R$pB__6hrWbxv=6o)h4=k^Y9RR zE+sPpIHn*)nhJm@09;!PJ&_K3i8q@^4?@1=Sdhj$-ifG(oe4cLyjHr&K8z)hQ#m3+ zQa*^k?#9biT{~Z-qjI?uG-$hlhr9+vb7B$pS^&eHMb;2U9MYIHd5W6ETS z@htp;_M2*kEiYD|S|2u3uA`aQ9{STw*ZnIyCdT}XSRXRqGxUvGujctm)if0RQBSR& zTN|(8QhfQFIy&30vbnT0n~PQ8&9BaU+W^1Jj&EJQnpzrvVRPJev(Fgr0ed(0nq$(6 zy^c3zjbEw1*Kme7q9crhW4s4^+ z@#@~w%U?;@ela8n!kDocEZU($n6K5OAP&T$K-ZL|(jR;Dbj;cC2(n8)&MJAYVDN;dQ1E3bm4SwWGj~^eZd8(dH($@} zH@_G6kN>S!0ke+o^S(ncy1m{37Q8LCn=e$8oURPZ$%ug1)9Vp3yYU6?m0WEwP*i$E zJf?&Yqr=9@Z1|UGM<~%jm@TAd;|e_Doa@NK=UcH&NiaytHSD+%lclw$sjqNEMZDw? zysU${jwoMsx%8anm{Nu)NXT*Rgxn|1BK(0P6ytavCCs%Sa<4EW!8~<_2Bn*8W>72` zORU$y~wQN$6ZSW^#f!swTLu-AIe=gf{fx0TvCxsM$Qm6DHwQb@tDgs^I@#bkXu zp5+yt5?;$>&2dkP%vZxH!weFy6oy^{0i${7ykk&F;GVCRhsxux)YsRV*S~-B?)w|i zE*O>?zXnUwQUsqc!GGWJTsrwbrG*YG2rwkF?S)hkI9@S7RoQ_@<&2y(sBoWF{-h_B zpL0V{W;I{l{MV1~-nGsI%FB8^UF2q72v2v+%$M_-N(}hP{Jw}W?hXX$D1{?6=I2Y3 zT4o%idNy9AhW<}|uqvyGieX? zx3zlzFE+NP-Tu2b`Lz0EwjP>tte|T5)<{rgu z4~_)57OCEGl*H0p!H6Ut0>m5#HvAPm%w7i-z*6TZr+|Ep)QG3-g!(k+Mmx%>euk=B zk)dX$Y`^~0n10TgAK^=HeYKtAr5*31B@M4idB_TR*t&Y&L~mf2)rwr)JTMi%m_9-N z1H!!!vQsjF+VuK#dyRruTiGwH(Vn8~f5XfP*yzb`X4q1_E14?gVo@zvcwZk>z>I|HBq-J%h&Vi`216=N^0X2{vySv_;nL*@9I~N zZXVEU!go}ogU!=6EYwY)Wm2>~Bjw^*wRAEw3bB!3aA4c5yZK~2bvH$XZme{djIc76 zK~1pnT7{h(8YpEjfDu=k8A_QW1UaTTywoJYXOFWzZ#k$qA|(nNW_cCaC9q^N`1UYq zSX+0uVY+Ti7yt;j1)*L#s}@d0s>jCNSi+%alSOfqKu(lSx+B?0BgTk?( zgZM$rJg3@wN&)ap%P&|KhMYVkOYJ19*t{f3+gGH=%}oCcY-jzRE&IMI891YdrZc6p zc@x6Wl~F_iYs+Z7C2K67)WQe=BLq3bXjo=@wM-oxzfV{(XU=OV5U|#HXc#xxG4GTI zHtK3Z#inzc?Dk7?2Ogh8_<&z;(?_z+nV04DXwcmgq=fujb=m3Jgoi=|VM2K7u=;%> zL>a?TT?;DMz&7I5Vs&u+J`qwR*i8&OO+6=Ga2HfShoN@ZaEf9%eF3fZwMo+~ieEC- z_Cp(>zG&}U^ZoDUxyMvv7>?g{RTxr=6Y4J*P%vxLXfIwHTksH zegflGG)299wp~0CPYh%bpup5a>-*j7@~jVp_lIIVuItnhw(%A_tQgW7=wLT-E*Mpq zDJ6jv91BXY;y~|^pqCWaxGxW6r6!Ykx7op?B;|~Je+_2on;Kg-dQ~z~U{}7|L-e*x z6&TNMzj>#oS~cx^+_mrXIHSRy-E-Wa1GNRGrX|}@l4!^PgpealksNm3)mWtJWmS@w z+J6j3256@sGg>l@l~T}SEGZYnG80S-;wY4tXgwSsOxTm3j^JFB{?!tQs{~tYrGcJA z8hYCZ6+s=_Aq`but%{zMOaO#N7!0)r?u$gN3>01$bo1`_w=u6WDH0GFiV?+>Y3(#K z0%OD!rq(!MJa;Y(A;5NRC|`(5wxghH+7~)sByjoVdMWQWS%KZ1sA9rbO*V{5)bJDL z@|iuh?$xBD?cN48DOrb*M3qKFL@e_F`9Sx}z0)z(6W)Y39(x&GNAIFYnc=`XYonhB z6UDJ1414Z9W`=7QlhYUl*Z|eui_WZnXPEQz4?p&0^xZ%E*ZzPoaZ#-k7nkv?CF&ji zvFcAgSybZ_siHgLArG%L{j^b%&m9Lj8Lzs~H+fumWDzVfAa-(W)>f?wcQ@&cjG>sN zN7g2B{i#|FpDsLe{Bf#gWh#7UWOfS^Xx+H{%iGrw-L%4I9~IxTOzfQbpMfzP?mzIf z^(K?`hdvsem55W+b?DQyosb^;82+0aNvxGjp#PXp67T4*e$V=Uoc_mn^}1~6RqUo$ zjXkzx{LWcXbN{XG33wp7jh-7%{;qy>vwg&INwZ)ypG`jfJyB_TdwyF|*3b#Mp(5e0 zR;Wnxt7MxmlJJsK3^|b_2q_W}40Dy=Pkm6U;`7M}2P+dK%LsbmkX4>A9eas!ZxIPL zHB$;Xr2vOgaDpv=o_vW$$mHR=#hDls$&G&JX8vT`%@FJloRLM&$Xj7z;}yXx3>K`zw1o+c#vWD_P5b%H*-rh8U3=>ld;*fe*G$-=huHLW|Vh*+BNg; zx(K+7U>wubzKXc}bpvYqVAhRTCm=#w18l3;y?t$oGkyV(;G=l91IVxvRdJa*Rq_F_ zl|%wAtc2Ejgsc||QUf7JFsu#{ag@hCK5CmR+4}Ko9=e^)r>=LoMwP8EH?Upx;p2RH zTd2_|>4bi9#b595$`?_JX}GTvqia=5uuTlLe(MJ%^5B^3UXix*m8Lq~bH7Xx$QYC( zBx8*AVAZAK@&{!~VNDF=7$`4@Bv5J(tnpq6gAm}#DX6^!^282+Bh-%vZSviw_h1`) zz}9my(mbALQ9wKCRSBT1MfI|`wBk!WD1;2lSP+^H470tTnGeB4K`2m;@U=v-He|B+ zqBoYIAbuQLKsm6AQXq&>5;~+I#!?|98(lc#lgoNc#dDwia5HUJ{OS@XYiDr|`B&rh z^f}onj@VwXN2ieIf{)sav=#J?NXCM$2k0%Y-~RVMe>|YlSRwFD6zPH-g}4=ExgjZQ z5R_<0hbdtrM4=q&*V(L7`jfXbCi82k5`uUg6bmAqGy$0@R*WL+ga<+i7z359Io7#z zI)rNhTNlr^xRXGjV_KpNh*H=0G7h79dOk}sUA3`FewE^DFo^R&knpv!ps(3 zPITsb4){`sWz<`H2X|U<)1BN%Q`#KpHXi!j_Nfma=?+AuUV;;YfQU3QmGK@8+7o4% zSg?ae2oZ(`hJ18^GXY9MD#!>C8Y^gx@r+8$33OOk0f?2cCx_*tt$uazK3p#J)qFEP z3GCY#|Ex+_+MVn^Cj7=boy;$#OwQ$ddXFoFb3VS*o%+*rdK#a?d-ypwh>nW6J!lSN zi{*Ur*_F<{`lg6gGDnCr!UrZ)#3jnp!v~CN&Nwv|7$gu5kS+)n3~MfoM^Xc&4C0Pc z-7%`SfE`5|RcF0H=Fn-5eJ_puHYc~k?VOz@1BUTid7iqL>kyzpi=Yw>EX=yy&-e2j zWm-Us9YoGxiHQsZqrhmGS_F`wJeXP3F|?EC&R0{tRCPN3YMGi$5*l?|L2EGbf4o~S zzP*aME$Y^(nf*$yXEyBB#k1zIf%do6Grqpcin;A$(6FU;YDqmk$`-WjWqK%RaeN6W z;c}qzys#O#5t$f)YjF)p_$hFzeksJj8!e1M7C{mKmkH)Po|Q#uF~QDJhKUzCX#7lEYV!6IHHAI00ouz6Um`iuANDp6-cGsi3mP>(PYvhpSSa&(LW4TeufiVdU9t5v_Rp#$?xa)t; zr)oU=+vumIbN6c5MBg6Zbs?B{0$j^GvMp_?YRZ(0fW{CGED>I>QPq|yX+tno+)U}{ z3=t5<^5Db@gs?)~Ap#I$4lyMZ6$G41ahU-HCzB;(hBT$SByV5?+IC~-9?*OMEqe%e z2s$1Bi+vzF2nG+rzaC~Cf_Dc1T@RcN0k#7WZ9An=4X6YS1fL7g0%&vqjReb$rvR<0 z4^&f_fHjCX9tj$-Wf-b?-qL@J6kR>KM=8`U6&6L0~Tjj{TUdrW2Yx;e*+ zQY#xbZ}Hq1+7g5INztT1$hGNIIAryS-|bBU~^GIqmuKwC(#1UOb8_<#1EZ8>fm*>``19#7RN%D7)#>xbC8 zC+mvsxa?$;Hx&qg(yTbc2{|K6{`v!ubKwQxjH!zy$8l98p_>EbM&A^04q2J^@;m}U<;Q1ZyDxK7P5!f_?IdOx< zpzghBXauK2K#sSI{A#$Mp`?Y|wpggwJerlgT3UNOe4*2Oi&72I+wGk{dyf2Ay(xcH zsJc)My@f#YFyQ(s*d91+a8hR2`gc!Q=w~Hy=*?lY+xZf|^KIt~Ce_VCXHn?&)m+D5 z<|^`7Z^nI-FS>lDinAhA%({=TDV!8XSQLwKgrcg#aAS30?3rs^<|_7*4bol;j-t)x z>U{h~`BKkE5#}4=H-fR$qi`ou@^OUobQHc724fg&J)e*F;&4`t1`x;D3640*PK3l! zZq`>3`26}zt<9_$0bkAHz$_mHj`Vu&88r@`WidMPz!4&H;JI3rMRggQHIK1~5s(8e zs*zzg+h7E^yc+5Auh>F6SgAgnkxobG)j_M=NyicJD3v(`M;vEa8DEYpR}praEtY56 zn8-(asFQkQKobYX#hQm+tX9i7bYUZ(>w(KfM7-3%t1=EO$NDT+)d0n4IVH7x9>%$b*wRjl#Oiz4#zHF#cBYNjKjs4=R~vz5LWL0Da_X7k9x z)d*L!YQ4L278&c6iLAoaX3L9A=GCDMZ-Y=cz2rPHpBog%k)!ZN5g0{rYFDGCjiOvf z_Z{1+;lGx)vg*x}fNrHxs!Kv20 zpIJAtNg(;e^y&$Bp5#AZpgfttpU(bS&-a;|@Sv<~5qekZMQ&N|(9w(SE4ufqZy_~q zFC2EGJ0KRB+73D@k-P(jUuk{fd z?!DhFgN$pjqk&YH>BdiUxERRy!-iYBs6V@REoV=OHO&l4_lCo#{)8}QLXO4{YzcHr z^?jy9PQ<<$*9!N5wai$p8fU-6jAk7_1&6y!4@ zkmq7nt%~x-cn!^JW^bG+QJhffIzTgMCY zT&tDJi}OyKo6glSri_y#&)>cIttBD)j5xTGO1eefYboCvS|IC&lu|fDhyezmoGc!8 zWeB!o3*Pw9SWBmjrILv>byG;3{gN?`u|dKK5Rr-$>Rr9YZ+;~;*!VS-1Y+VMA}4|Z zq9p}F0wH>*b;t1m-UlsCeOjCHmIa@6>8{OxN7YC=#9D)k9E2l@2CTJBrN8StRKlG> zCfpwEIBa4Hti7&wU>Bx@8AO@u2^s9wLdJ}s61gE5$YGXQA~7cIqpP;`diKRz&Ku2d zBlZJ2;vLh#ldHhjU6HuxN7L)*-I3(q=4c*~|BL|auNpCgrMxY99=8hs#}LZj`D4T> zwLn>~HBuvV%C*pn7y_-erc0!~*^co4584bYM^`xRYD1=~vhHWqU_AiQ24yOa5bZIN z)sZ~FPIW;T!D(sj>kgMUtBYc>A1DnPIGi(Ky}MNtks*zU1i+@LwE$>AIMj$q#=bgd z>8A6#s2tn=^$+(4AByKkXcrxC-8@*D;gK1A1e`f9x^aR%B5d(0g-7t*q9Z__53K0{iJeTY#UNgeI`-)Hq+BC$=n$ zKpmK`_B2Gy=*^h#@CwJHb|yp?DLf4|lf2xpi9eKYm2CE~Wm)KHR!^V%`f8h0)n=ljQY{@~nZagC0qy3=-uK>O zoX}nhIVIo(Ny^AXL(KQo*h%9%s)R7hfH1&toMr-0g-OONR}vs$jr&Cb%~g9xZA+k@ zO}5`?cLcgWXW9|v4@W{!CEPFBh zC$Pj&Ocb!f@n1@uIp{M!U~Ql=nqubbeA}!Ovpt;nh^Y8Mrh()G5#)N7LHFn;`O;YQ5cjUZ4fq0j1p8x9>k*5N0uK?F_~D8PjKszuHi z(nY*yjR}yQO0hUUgf%@jFqBavgq?r)HjM653s@vn_>|6ZrA@&`8 z1RV07Xgn)OueTjjg8B&gJs`$DUr5%Cz46$|b_}7QY$T=kKu^3c{^cs20XG^)B-m$l z4c-E!5R*(f+sr#2XvQU!B1{9vs|7~@5BLh!K}a$G8G0us5JFFn{ul%t&~m~N19;;sN%r=w~aYkuV*GH*9(8+ z_SyOJ96hVl$|vTtWwI)YylM*Vf!gZ~=h^M%T*WZq2+^k|u$A1e^X z3{AZ*1G#%mx~`fE+g&qbQrXK3l_x%!zRAYbd-OsDvPeFl1aml!Ug|8ly+x0jx!eRFvOS>$(Emgf&yuPsdvejC5?YGDMnbl@|+kzNTKvJzc zNtc3O7pPVGp}{z8Z1pyVexXuMf$VHn4nNt?Rp3m3BknA&69zB=Vp6J+%sN*0;gG(h zm@lCka71010+No7?cU&78NQ&Fi=Dj&h;)Ue)^lVv;DrHC zl&hJ_|E)?NJbwAfuBt6V1Ze#(H^*Q_fL}kps)I-e0{7@r0e`A>pt1Dl1LaWG++SgV z2iTg!1qot%Y~5bpw1HUdt`8RIZMCk&JlSd!-3}J>Ge3y|K(U%- zH^UhW<`Q32%W|NVEvgC!+Wa^M?e|vo!cm;tLmU3=L2^A9@-jEouyJt?1LE_}Q?pfb zXK4*)ruxfKa^2j|UtSHT@m}>^Zx9Yg?Q@hjTS0`v_6T9vb&&kRDb61(YWC|CfN!($ zf34pnpIxlx`E{RW+)zEMw^_aiuXNeSp>}(t!fjP1e}>ek!}W|kue4LIRP}s=ce?p| zKd~FYpdnGlB$>bYG=R9@J6@YkYOr>_s+cM~&^r5PWCCb7mwiaumjN}Abs+1ua%yg!p0gPJ+Ipjn!BkV4?tGhnO$9Ft}Y!{DkkR49i zuUVqDab$_jAmmv?zD~~mDAlISR4hI1sAQbJp##{;WJrpLS9X;ZZlieUfNui{Kz=t|XI4MTozhA3lem<|q1S9NeQb3)C zXb=!Ol|s9HOKc9%8TVSfJMR_%@+FtXbH8jxl;>Azv)kRUxRyS`JS@DxoAFAqK*P*9-sO7wN7#xlGc2*sD>o4}^ zjd9X-md$K=a10&npRKQiyRxyTUa4xPUl)sNRjS!y75&0jvy}rmB`Nl0uYZa(zpjth z!oZJj|EX3g3Ud=v)IUOIx^U zzpA-3_PRsez4e*yRsJ89ufx5y5u#sSyX)T7@f%(j3F5r3{1^RR=CPr?uU@NWh7TZp zv{$Y_PjKUiZsC5rSw=tIVH9&e+&IEVN7|oNKHANZqxn?jpXysOW2^OXl!SKB=sGyL zzqZvX${ZW`5gfb!s(&q3WtcO1IPcUli1x{elEwK?WvSw<)8LHDxdzAeQokyUvaaXn zNZ#0BA0^{|uiVNNtCA82j}(gu9nb$79y=;{f`GP$F2m zYn~(hmlJCl$2uoh`B|X>Pxb`Ye?;h)IBzA&OF< zC6pHPOe)J1l0pNH3?(*u@;=KS&X6C@kXtxI_UsgKh_v`E=5pPfcuTo_iHRFP4Ym+4zzpLYYG$}X2Kb6WQWB*ZQP>D- zet1N_iAQ9V%71u8zH_h0`>gu3UHq_TWQP%H_EzGuC|9rZ*}&S0AXSI38dK;1me=!r ze9B?0n*%t%E{C3)2-2bM;_x?Su9n8TK@OmdkGR44Csb5CNMl`Ju&iR?&S8T0C9WnZnctS@`sELIo|-5+m@ z^MBiX*~fOx=l!;prziv%zI*2qYB%ph->AF`2WA}SmiW4ujDsQ$Fv`J+lW!7FimP2* zCg-J^&sFJG))Aj007gSe=NPxdNM@Wo%R^_p%|n#1mcXGQsBEOI21j9?Jfky4w6u9X7MvI+ z@P3>xl(e0CuJwWY0fs7uVlJUCnFkS{6soYetWMA=bnAn`iD2RUPdMdVK<=a3p^<{v z3;|(~(9{r;=?qg0b;iuSrLGR%c1*vZfFb-i_;A!7pOyXsnh)F_?Dq{UOC!*LHj}OW znL`-=ze`(RP-N(qDof;I)xP<|`=22?19zv>#H{isYdC+l=~-G9pR4)`yl1GN03TMykY4{&;42vLb}M+j9(cZi{z1^{7(PB2EC z&`Blv7VGP})CX|ljGWS70;4q3NIEMikX;}^a4;y6YAbF%BB^c9{Q4_WQa7b$ z+m^=8covr+v5I7|`KT%u$zoN2KyCJ8f7wF2zw>yTdoWlwb1S=H$)$45m#I^%2g_2MX2C1~)oGPvRCh`0YI^Ah5^ayqS zjs9bw+0PPdb13;QBI22%uolNKE%(h7h=5m}5YWDnNcYw~E3$SYFLZ8~puc4A2TH>o z_YPkd^&UDmc$2bIE-3Oe?#94JZ3U8eYlG@e2^+53k2VOqyt0;dN~4Mqd}{-D(DS0T zm7`if2aXAODU}_D#e$mwK~CV@PN;<$oWuL)Z9nGMd8MB?Z-+zr0t-Vtr)sDKw2r^@7k_qmtBa7OJ*AB^fnxb z)c1Lk(m*gq5*#tuf>08pSSm!41SetahsoRs7}rL#9a=MG*T0A{yGDG|H{$!7+^pZ< z0$a%t6jBwDR6mkqIGh%hb#?=NyaZu+soSn`e0>`gDxNSJg;?@)I2jhEI1v~pl4B}U z7)J3-ehFTzj00jEzWdQj!V%xbg{FIBgv^UP$a6Hd#1r zuU|)1w7B0I`@@HKua{xJ38D)7OIhX3Tc$+>5L`e*5R9+iynXln!$Q(~AHS`P_vIzn z$Y*aV;`{MJ?6-mb?PbG&h#xH{Toie!KAJS!9O(cN8w}0gK;36=>lI#w5^Eb7B8u`mSP2SIH0XPo@8N4%^`a=}~92 zS{E?o4m*OAXbQ0jsWsXVSn7l4QXWpX2@#1gU58;9;DyIZ=11>T@z@Q5L?n$U@lh%w z_>7ed!qg8q@+s^W5TR*^B=cv7$m^#ETJmK#2had}W8kOQmk9eb1uZWMh+S-=;HNT@ ziX>4GA`bF|xr&bV512-T6MgR!Cb0he|AydMHUtzCE+ap@e?t((u+>KCGwcU6Z!Oph zXsTJZ53n)k?E#LMbM=1J6nJRSa6(OmugfH_-tw=iew?MKYH zI{OiGuD)(zF3{DF*mL!C3v<4XeneiRpIhiNb@LUY~IE$hXCrK(p2FrFBoR|td znY9Gp%gk|s_(Co|?~7?v@!VmpHzWeaFRy>TMB{f6kbRj0;W-hloF4nUTD?@vproC>9V3NCgLOoJ)NI2Zo@ur0&>!vN`*-oc8j5V~65r--94+aV*hQ$+3 zm|9>&IJ9i}bz$$&bccUz98k8#Q53{W-uRZ=x@ z38oYCBDT^83VqelsD9JZv8|?_mmYOo}M*BMz%B z@&j0N6T}nEl7{mm=*A<(Z#B`~{>CM}+=+@9yiK|OqRXf#oKf3Zv-sF6z-^GXT^!DfdLmKj^ z^oKd65uR20-K^5H+Kq!*b-$TaH=R?OpgE<3Ii;yTuk@VRp+1>add_%Lf6fR}Kb%!M zno*j~8WT3Nm**&UskPT+1(_~r2=q>CLDPl3LDo2ogCnM+8Ir(Xa*I<*P+XvCu(u6D z?dX3Kx=e&I!!$^BNJAlMg1L-jiUm$p$atEDlKBb7ks9`o99NCjh*T%V#Z`H0Y5y&# z751}2qbG5#{THgOl6<9KXsz0s7ma>bxg~=_Ri^0xM?kp0s;aZ1y_8(#pwe!y%BF2Z zomK56FFrnFD2*4V#rR-LGfkcp$u2hV;CS^m=u2$ee%|fB(f(4fI;CsN)=Y zlU2>Zj`fgS6?t1aGa7fgj#1bz*U%X&qay_!i}PIW7KrzDt3-Jg-;}s2b9J`B9>(`v zW|p4I*;RF;+I@94U%P%io2zfiiu*DvaewY6$?n0w%?jDH@}4650y=Omw=H+&?fF69 z7u6p-d%H0Vg{@(UJ&2=Dp_&NmU$ivIitYXK+9@QbM}UNcmed|lJd3zp2MkfHPb!E{ z776dV*aG`S8yx9IY=|o=5mp?>34!)8%tV3|O(g+gEy4r|B~pSC>O+BEblW!X5AA82 zE3f;gKp16>zDzzJUiNE0et06eeOq@zdub%=XPcidxf+ZXbs+0dKTdV6T{NCDufyz{!3Aj3Y=gpcY+){Z50P7=DDHaNu1 zRCV=($co0T5xmjdxnfI2m@&2vBSyn`iL;a@fkx>^tuB+JfPvIYRUm>S*5@)r`dBbu z`eCeO7^zgGfr`}-hr8l;D^X=-$4T2yuxje~vck(yRA{S^DVqWV;G+l@^2MysfL@6E-JKeOg@E!QRAmv$u##B}l%3lRXVANixqdJ4MEY$OetT8tR6 zZ)CK)cQu8jN)H!0TYLNf9=Cif1pArVSuM%~>ziLI8_ITfHfS{~m()tuV&IJ&7Q^9dZ@&)9n{Ar6$Mg3gy->G?#}05Nti~1A;1%W7-YRHMa>bkGb_}=5 z21iT};FY+#?i~nKnJg{Jv)2i;`1Dgy^-FhU|4yyC=9=$(_&XY>y7^f2LZ(qR_3F2E zx!H;jnn0I)wQr@7F9zDFgBfL6Tf;e#3jGeF`_!-c%-7y3Fid0Dobg#e_hmJ@Rmuh$ z>zCRr?>pRKx7S@d z@>eF%_yO9s*N0MnwnTq|io2oaRc*fO^TG}GjT<&kFJwB6!fGC^s*mkeS#)JUn|m&u z{&|dAzv!_?(|ITG^_Qm=cdsaUEw0X{f@*V2&A4$DGAh}pjmq&{hQYMpkT{gw!cOEW z6U}K0PIFFhCM}t!pOl}r=p>`Z=)QCq-(Hb#bolk1(ier(gyAXjDCt6~=DIB_Pgi3q zf2dH`Nmr>uBcavj>l&4ML}m9jY*cEf?69yl$>lH@cEng+Mc*UyU4vxPQnFL@L9-Rc zZN{H%pjlSarLS2>Om1U8Ts`0|$a~D2Nt4O>W8*IuQA1 ztSJ(Vea8G0MVu;?#3=Q73_E}@6d_Ne0OKH_B4E#E=k!8Oho8Wp;me9inC4ezqC1m> zBL{%0F-WQ_I+6)xi^?$?K@N2oRg&N$s9BAAou#@dALzX{6 zDC!MObQl?6KM2Eh9MENt@S8?7+1lS=9VI1p9qa`Ok}(o0isB&RBubK$`b@|$O%TP* zk42IM2Q!0zPg?(KNLtUPWl3OWchyhwD>KbNM)7J|!lv~(SBw+tIk{qtsAUId3VTBv z99N8#FtVl;ktMF|+L{BK!H}&H3O2+gwn;*Rm?#uTsp2G60;`k+GT}U73=2kq!lB6X znWw%4QieRWOF!pq_=}3{Zko+)p4Uxuuiu!A&G>kwOFZkn`JZLEYcAfYWUr4M9?(io z=aO8~8q3qmZI#iQw*jfMA%vW2;O zo-fRYS<{(g0ug$K2uBR}I)_bwX1C_zZ~CV$ek!+_c!<}gWPRcm7>`$#tnus?INXx6 z7*kkR{D2U)- zxFzw1ZeSECEMoqKx;RdV6k`UpQ>+w6SjXY>xrqE&MM8vuqAaC6ME_1+xSyY$z6RIb z=8E*2Kll&Vq9#h7I zxp$Sjzn1g(4!6WZ+L=LdOQ5s*?=<5~t-1h+A$3}9?TE5Aq@4@q;XI-@8C5xTp8RZX zjb9p1%#*-3`3k6~=^egP19;ngHcl`elE+C``~aU4vZv)&p4D|}Xc9j__pah+S>Qa% zqe?wgXH)R1xhmU7xBCR)F)cqqdStngUvbD6xpX#knm29JH2*Z|SXwVduZG3Q!^6FD zZ$6ro&^k><-BG3WaiOnXL5n{oBwSo;`=0@Z|7?p>NXb>pJ0rpFO?$&-K12z-(Vm{R z>Ijy_jnbAW0}R5YJ!Z?SsdoJ10S2|exWewiW3~CD-W)Km8=;M;4k>$W12{m?C}BhO z0jL$|A<6>t^2P=`E13h>WS@>;bNo8~b~WxafY--QyT8?>ztxTP)77{o)%d5Y!%tWC zPv2}sx*cZhm;$J+F%TP)?Dhe8ef%8F55RVNZ?@z1-fWc#6KjFiblq&Te3YB3+WJvr zyr!B1Jemd#TAkORH4Qi0Big9*opsj8MqrSYKb{E7A05*2$EmnHB-qx&4?g4mVf|B= zvOy?77w`@DYiY+*5rl?zB17#<-4Pu4^j9f-sE` z?CF@)vDj&lGM}cgFN1`K7|T#3EM~%vK_jZw-7b5H`?)7Nf4nEATd#%Pp6W~PNM`fj zhr{T8Q3V8O2D&m1W2WioRYyslp`?C+fb-6U;!%_YG{H=2 z4@?P)RjfT6ML5EoCuutD9$N)0c%wYs>ATfGa=ukR^KAywKCPAV+BWsHJ!SLc8$73F zduKeUxxg8w=6~9^utH5dCz$lV?X%P5&x>mFo956?y&P{seuEXvQ5=S$+f|Wqdgdsb z=>v-x8y!y6q*Ir``zy}0?z?AkMxZoRB0 zDa|otbEVgrf2!XuKIm6Nz`eslb6)Eki}vZI8VRX&gZ=T&J2u|&de)Cwz{r{e7~zmc z3l+JDtkzrM33mPGh8dL0L#{fcn+Y5dG@_eo7I zI6kG*gekmJBi$F;GKQobC`>10g?{X1rI>B}@qv!1;;guOZ4Ps^v>L`R0~PFErFbeD zPVQ4MvP>wUv}XDuZj^yWBbY;UC)f}0|s1g_SsIJbtCaZmp~qM zD)R6|PY5w&DDcOGXyJP&U2*K!5Tz(y2LTP@1twrQVugO0X4ZAIhM%J@KNKNTk|avN zS}jl-DMWA(;+RQ=5hIEuGDrlE1{+^ft4xMtMcF@gn}E-^+)7?= zu6^0LtJ`1cXiKk<3|2nf5kj*YL61WNCKPlRc+-q zuFct-t2nvK+Y|_Z5~Ja8cF2)r|MdreUjPY?rLkp=&JVVR4UhzZMxz_({`CpxdZ$@c z`M$^sSEP;G zmZYQ`YHdk(g}M&~Lj4Nq_UbQu$G7S!d-8u=X)$*7{@1^E%TQ3JPmQ&N;L%v??}(gE z2}F{xn5J}@M~4i z!+BrZPOR8{jd zX|XUJXSy$hvjIrNi5&5*M?n#cHXy09GPN0OyL@>&*ge|zf`Qm?OJBX zN;_!RV1N~MJ@PVE)*Wh-O|Um zPNs`59*P&i@wTWIr1 zSn&}qKWyup0Wfq{xEptBr)76->`b`uzG!a3pJl{%D{IRlaI;q&5(s?-E3bMa*kFau zbA74Y>@J4|rd#8tDFc(DuVFrMJfRQOsCG@e?k`o??Tfpk?OfuIp}eY_5R3Qa^&vB< zLNezSJp`(W1R1BlqZ92#Pg`^?a6E2*F_o|0>;LpsE2)mT7zEUL&&&Wxnh?mGJqcSs z8kLfO7d%WciSbGs0W=}#l;d0j$E#m&f&S8OPb^f zvuC@Vh2dHi-^+TR9rOD})z_0ZdmhPLuS69KZ%s+ko@K6S^U_k^1F;l4kQp6NxB*6(1 zv50x1Vw@1dpXnTJ*lbe!&AH5>SG3MJgZ!o)<`!hO=k&gGPKo|@x!Z)?E*_Cceu25B z9G^n(6v}z`(9)0xA7&|9p(I8pxm8#tG`?)1u0p6%Bu*LBtAk$BkWi+fDn=P*AeI6X zB@oJl5dG29h&<3i5!lpy9rirEXnlW|#Njsud~uGXvrlNg1f0XnnwNPQt*>Q!Oyx&p zO?}A>si-EWR!^FZqai4(^M%o?YCuLgbKK^m_RKqNjT)l(_-s3v;KX^znL zGSoiE#%c6mdoKjHOVo(ONR5Ip#d&xo&fY6%L$}mm=D5n{jM>&kLR`ozwbm z%Bpg$_JP1n_0XWa4%n~yp9$IzINp}p4%2H|xNuj_rB`hRX8sC?{Ndftzr97L3AeL5 z5f>g0MwZw6gmjfr2h35CxD@qGfa>y4Dcs)^Pf}6Zlt|;Xbt`Qp$BjW6FGW`nnY@Jt zq)GG-U#hTBzIbE!h6f0Ti26kX-gNZpFa=8si?M*{n4alF<{%5|FPip$Q13#CHrfsJ z1U<>(5Za8oUV%&fjLVpYuyX-1$t+?RV@@%}Ad4AR+IHt4&T^(C$YYw|{25*LtZ+IL zG4y)OjCN#=-&-1)v2|34o9eLFIz(F~a0J}ZhXuSNJSOjj=Kg`>eb$ z1DqZwAU3(ilM|xX`epSIi?=r5g~?k1l++8g$a9#3l;sdZ2@{U993>1>)yJ$&gag}kc{;3py zxQJ{ukDK2aM9tz8Z$1~Cd5Sc*um8MACyZ(vdWDcy7-4z>uS+gVn>sDk4+-ubfrRVj zLM8xaRGZW()Jq7=Nt`7a0ur#85T<~n9gjZ+&hN#%p`Lwt_!j3hUnM-^42SD!6W=m$ zoBc113=7W@^GfMEGnrd@S0j7jAECCzt`p~;7qT(?#!rJ2>!<&8j?JLMh&%U9?P&a* zfDbpsCRJ06=}8FDrIvE{H|@3_u!eFH1d3)_Br(VdOo<>l#|$V01<&-Fn$wsiQpuPP zo5tVG(aW-x_%vXfr=y3R$&53f)w9sV@EuvJ&2M0KR`8Km^`=)bHA75s1nDqGT z<;oTv;TUg1z$n$L0)Y&l;zy%Olem~BKbj9P?mfX%dC2lu5C$kgEI}#GsL={FlWGf1 zF9#{0PznjCZ{I&1ulWo(_7ybRlggXwC#&vUbwhcnTXiuE>*_yj&RS=fEzGd-%ZiyF zu`=B9?`@vjkj^s(ssz$v1bJy<@E`^~M(^*4hDHT4oyD5vRxn|dogjWqBI+*vRjQ{Z zV!@0wS*|UdOy+Sexk9OcInHCQ^`0~(lv9)=Dsv>|vt>DZ`_3+^=I5_lS?rZ)98wS8 zVSh_*LQluC9t6=|jM#_v@*$_mT{+Z!zFcZ(NxupzR)*MtXgEJ7t(j8W=E!|H+-EYN zH^aw`QF040bE9e&P}0CGK5j8y4orjHjzq^D3yXU_E9yW0yjO}Q(KwmLbngzWU@%_G zy}`E7zmws&&);v~{o@#~|Mi1;qPa{jN-k~^(m!So5gmRb0EXY#`OT%Ow*6Iozvp$+ zUo|p+=zkx!g}B*QrRoWeoOoj-MPwv}Cm|o%2?4n|=oX#u^kFQ_y`yZJXa>fqVYCv* z*F=321L`VbC?(KD@FlVCveRT{-=d(a1<0t@Nf{!LGnOShi!-eQ5TaFANr9BwfP^^` zy>sn1g?$;B&9liSoc0KGBuCDE3F@pPf?q1E_yi22Ud&F8PHG5;2m!wPGYYi^fQt zt{!8F6`jKZ0)e-J_?`Sk3&q^ag|ZY=f29~&F<&GYh+&FTgLMQMBqyX0wr^++>|;v> zkK>#|N;6DS$+5O{aVjz<^b$p(z`06hpz&kV3zq zGU1~EwPz89|0^jL+hQP`T`(e~`te*Tq-h%R}3)mOdj z2#!-=S2CwWy7@J~R)La6KSWuOO0^FZ-xph1-RmW-tU_K*Z~yV@)!X0x`u>;Wr@+DW zYUT!lk>jA;H^A+V08S5N2(lH1aYD%{J|O*TT0P=3>uHQ-oFObTl0Xw-p>6*xPZ{#|^Q(7GKKdZgwgZ?5oyS{G)a57MnY4ReR*{XTR`4iDJ zWvdi1c#1Qgr-proHw`{y4wb|L#vJD<0U6{OL5jr^Ya2sm6d;EI~2ML=RbS9N1eW;(6We#93yH{+dbOUube! zrg+n_Mbxr|6UTLsMb%nyYC^4Tvd;k!?xC4gyH<^f&uDXZy7&af7tqs@G_9$o*U^p2 z_I+qZuS!k84m8DYN9iYBDT`8NpNa{^LB#1v*Rx7q(1^a?ib^V<)2u$4B=s{cXtVH?>tMQsSNOP}e>4snc+=?nCzn~wE}$fq0*QtgVJM^Rf# zIUV(4f&?EHmXrM|7Hf^!6Xq6x&YMZ0pn@2octtQI;FJw3J*o5}1I@vCV*Z5O4{$ED zlvWa=3`3TrF`}GtAXtvH8Y3m(`t32nF6xEFnX+r%#WkLoh0o|veOBW9n4|PF`ejc0 z|C~I6I(~c8ahwTqWr64&TdNBRw!eQgVmapzA=;HzsWv80^$<23s3Wz6Dz?XJ=ms3G z&|V&^u~ql$rAFRWg-{)c<+$)Q)$YzAXaz;fO`oQlJ)!8=)SJp(a&$3wQ(ow6acI2j z7L3#(f74zWEH|H47uyM8rku6ypF%jz5aFV%!e|JHeqt{tuAu5^A^)A7+ycPK4XXvdIl{8`7+1L3YE zbY{ihl=#WP3Xbe`yYd(mfO`|x`De{p?eg;T_T#D#x4lz;Trwf%vVCSh#Lx*~v-Klq zW(Kj*Ob{ESDM`R79-W2QS4OQ_i^ez`!*oR#j^+|cc%H_P2*nbP<3!Mur99OuQGx{% zNt_GB@^n~rUM7U+E3G)s5xaTzVKN>w*fk-IEIat2F@3d53o2@5>p+qw$znUh+^2cE z+c1M>NlE5&W{E$iF3}_*={R%TyQ1+k0`N-AOdazKmXcF;p0v){&1!I&)~gg;!ccr1 z;S6QSI6kE~<`|QlrwL19mBK`&gn&Fr2+Gv6d5oTe3ifIYXRWB+8D{^f=j3*fFNV>6 z(~Wmz$NOSZ?IcW+AR|q=93$YY58W-1+m?VuLO{w^D2~%p;=pt_Xv1GyN_d6R%U}W? zffGbz46_(&bA)D$B)Q^(Wso9*Q=~A66FxXYf2u#7v*3SzQ{%PoDs?PjHkEK>n8Hz@ z&2B{Wkh_~dZFNV#J8TVR?atA5ANoqcRpPxCoFu$67?sBeDYFapE` z&{Yakl$;X7RqXe=g$52Sr8pcT!*C{mp3ga>A^{`?RH!)52vu1EBv$%|jMd=iWMFf2 zkH=;a17Cgmc;Gy*h!Jf!8$M)F+tK5v$ZCDq8n7<+*w@}Ly^cy=dv;anFzfF2x?VTc zx-@{+kJ*3vUzN>vpRAhGM}PfL|KZJr zN6Q(UjJ*)kPP_F@*Rhf5*rfy7|N774$FsLmnUsOp8>DG8mDV*~4w^J1a+(n^G;xge z(~TeK3B2^Low~NM@mjrMmtZfj32Y33r6{ZzOSBycslr&ML_iZ*MHNFprl~+FBPkkU z2fqajt)pEmrUYBam>f!j9CmYis?*w;=sCeyfxCd`*(px{hHLD*{pWA^T?Zb@<^!P% z&25W?yAA)iSh!arT=sO2Gt&sW&A#x!-9|m2aM^Bq4FfFZkpKI)w-BwpzWSnghhQCi zi5^kMnMd?6LO%7e(F2mN>cT3s^dx-aszJ3HX(7n%{LGPtuAyct#l z6Rz%LwB_56O?4-vhx%vkLmv;$*0F9M;&+8t%h0_2WkZnD$( z`^LL&#Iz+gKZ{4XE2Q#H!kb2A8!h86^No8TZ9aBg7o}X^sLjsPPEE%;mxoPL1fHqKY-=o>bJrdCrQEjSy#`m>Hm1=To zp=mcmR+NrVY_+bVALv&rbf0^K`liVJ8|xi6hvCz+6I0UgOzY{NCgi5l{W7KOrj*~C z3Bl`GO);r=_})1J`sg#1u8%e@4{8D_^{9IkQSJ9bb}65>ZVp@jc~XUX$+o1OF+HOHy$Q!W}@>wop%)ynuj&I4Y$MAo?Phqf)$(<-xowjO zbQ|QuTfNJ5tr~;9-V$xZ$p5kTbX{)R+P>#k__2M!gCr!Ny?JQUv?u2zZC9qZ?Yb{n zLJ~7%Y~uo+nda9Y34tvkL2S=Bmnt`n zlayyDO##D%5rJ967>7xg!xZI0U=k9T19sZ#_K#16kK~`J%R?Qj%0DT&wqO5w_x*$R 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 literal 0 HcmV?d00001 diff --git a/tests/data/openSUSE-11.1/suse/setup/descr/patterns b/tests/data/openSUSE-11.1/suse/setup/descr/patterns new file mode 100644 index 0000000..2630225 --- /dev/null +++ b/tests/data/openSUSE-11.1/suse/setup/descr/patterns @@ -0,0 +1,2 @@ +dvd-11.1-46.1.x86_64.pat.gz +non_oss-11.1-46.1.x86_64.pat.gz diff --git a/tests/data/vsftpconf/vsftpd.conf b/tests/data/vsftpconf/vsftpd.conf new file mode 100644 index 0000000..4e9c09a --- /dev/null +++ b/tests/data/vsftpconf/vsftpd.conf @@ -0,0 +1,101 @@ +# See vsftpd.conf.5 for config opts. + +# ################ +# General Settings +# ################ +# +# +run_as_launching_user=YES +listen_port=10000 +background=NO +# Uncomment this to enable any form of FTP write command. +write_enable=NO +# +# Activate directory messages - messages given to remote users when they +# go into a certain directory. +dirmessage_enable=YES +# +# It is recommended that you define on your system a unique user which the +# ftp server can use as a totally isolated and unprivileged user. +# nopriv_user=ftpsecure +# +# You may fully customise the login banner string: +ftpd_banner=Welcome to zypp FTP test service. +# +####################### +# Local FTP user Settings +# ####################### +# +# Uncomment this to allow local users to log in. +local_enable=NO +# +# +# ########################## +# Anonymus FTP user Settings +# ########################## +# +# Allow anonymous FTP? (Beware - allowed by default if you comment this out). +anonymous_enable=YES +# +# The maximum data transfer rate permitted, in bytes per second, for anonymous +# authenticated users. The default is 0 (unlimited). +#anon_max_rate=7200 +# +# Anonymous users will only be allowed to download files which are +# world readable. +anon_world_readable_only=YES +# +# ############ +# Log Settings +# ############ +# +# Log to the syslog daemon instead of using an logfile. +syslog_enable=NO +# +# Enable this to have booth logfiles. Standard xferlog and vsftpd's own style log. +dual_log_enable=NO +# +# ################# +# Transfer Settings +# ################# +# +# By default the server will pretend to allow ASCII mode but in fact ignore +# the request. Turn on the below options to have the server actually do ASCII +# mangling on files when in ASCII mode. +# Beware that on some FTP servers, ASCII support allows a denial of service +# attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd +# predicted this attack and has always been safe, reporting the size of the +# raw file. +# ASCII mangling is a horrible feature of the protocol. +ascii_upload_enable=YES +# +#ascii_download_enable=YES +# +# Set to NO if you want to disallow the PASV method of obtaining a data +# connection. +#pasv_enable=NO +# +# PAM setting. Do NOT change this unless you know what you do! +pam_service_name=vsftpd +# +# When "listen" directive is enabled, vsftpd runs in standalone mode and +# listens on IPv4 sockets. This directive cannot be used in conjunction +# with the listen_ipv6 directive. +listen=YES +# +# This directive enables listening on IPv6 sockets. To listen on IPv4 and IPv6 +# sockets, you must run two copies of vsftpd with two configuration files. +# Make sure, that one of the listen options is commented !! +listen_ipv6=NO +# +# Set "ssl_enable=YES" to enable SSL support and configure the location of +# your local certificate (RSA, DSA, or both). Note that vsftpd won't start +# if either of the "xxx_cert_file" options sets a path that doesn't exist. +ssl_enable=NO +rsa_cert_file= +dsa_cert_file= +# +# Limit passive ports to this range to assis firewalling +pasv_min_port=30000 +pasv_max_port=30100 +# diff --git a/tests/data/webconf/ssl/ca/ca.crt b/tests/data/webconf/ssl/ca/ca.crt new file mode 100644 index 0000000..6edc8a3 --- /dev/null +++ b/tests/data/webconf/ssl/ca/ca.crt @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIJAMhg1/NG0qqgMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV +BAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhPcGVuU1VTRTEU +MBIGA1UECwwLRGV2ZWxvcG1lbnQxFTATBgNVBAMMDDEyNy4wLjAuMSBDQTAgFw0x +OTA1MjIwNTU1MTZaGA8yMTk4MTAyNjA1NTUxNlowYjELMAkGA1UEBhMCREUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAoMCE9wZW5TVVNFMRQwEgYDVQQLDAtE +ZXZlbG9wbWVudDEVMBMGA1UEAwwMMTI3LjAuMC4xIENBMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAtKq0Eq6sbzDfLsiXByFLNYymccotr4T1wYIeYVs6 +kKu6zrT/urvy4Oxv7DqqhmXtyZFE/FuQ9uSN7a+04cJWke18o3u6g/Wj1tuL8fev +zyrMPHqQ0eAsfYXssxmVdWULs3/G8lYCOCUJiuY7c7xAR+MSQ0vaCcwhqi6ObNxi +d6NnYvHNzDy97KBYJUk6L0EVFMsMYgPv9VqpR5vVc/R+DBSDucGAj4DmnFycOlip +eFna3lJr3XvmPrLyyJtS76Rpa51Pzrs/nrYZErAZOjOGL5WQhhl4eMQuKsyN2sK2 +58pFg+euQwjLc6Wxj9dnJ3fWIXURy0ZhJRp8clYpTkShmXwO0IuT3IbZZ2eSSqKH ++HYdeztZcJeQFlY3+VOrTb1KkmOYtOzBOR9aveU5xDJfn/i6NxQKO5dIQP2mpeyf +upH64saSqvh0qcJwwCRIodl+BgpwqJ66nQqiIDIyA5u4zSGCOTfUuYKnD1t36Goj +Ni4S2wyQ05nsknnwdakLJO7k+v9G7HNvLT0uoiySjmb/x7BRD9AQbNYCBfdznWhv +aXdY/RB1gUNUH4Q8PGyDfeYhMZWupnWmBA9oGN+OVT2eYqBlYJ9zNanQAvraeuHp +rJ+cSw1+hg5tqkKqQ4Uf76xkzNPPlygr7X7wQuxDdGtRSZHt6Qj07+s9tqAuii4Z +NUkCAwEAAaNTMFEwHQYDVR0OBBYEFI8d9N4BsjyTRjV6V6q4V5Gj314eMB8GA1Ud +IwQYMBaAFI8d9N4BsjyTRjV6V6q4V5Gj314eMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggIBALBFInsHdwQwHbT4i28LfN3SaCtXO4Slznx8pE8Us8IB +4F2xLry3NGZYO03F+m2E9kTJ4vYmL9o7H6Wc3cVwfp7itCAVP+oSR63YO1nnjJuq +/3KoLVHSC8rjBV7zutrVq4iPgIEFOVLcRf6a985NQeIPxJK1DgxYdTHIawwhhPZB +/T8G//NmPiBDz93OUN0rCsGTmi6DqdcTlY3kzdhTtSKJizUl6jlcs8GDoLHt324C +siKqGzTuRVmatc2fVgGJe3PYuMIvoVsrTAAZL6qlqdpCKljac7yz5q8DvAzXoo3p +40S/py2SQWsQOsSJcEwkg5IE/vgG7PadJ/sAuU6DPH95vQZjWr/pWHR5xG7PGuh2 +8B8322OMmpa8E5DnwUvdy/+JveoNZmD133mWup8WORqiLp7HwxJ6hwPj8IgEkdFn +E9EUsMwgItHD8sOdUTegRm965ysZR3xIkLIjXCTf+vsKz1Pj1YWu7EEqcaAJV6JB +2a+G6VsQrqnlxp76QD6IkUSzdztC8tvLYzwCLzD84vvfuhApo8oFiYsBF0m3Cq1V +fr4gKWZmn84yw4izVz4bXBmoFinmiBF/VwQXZcJjs0Sgea9dsql4FeeUhfK0MAQJ +okZWCL9+DvgLCW5k7q17GtlGUExI3QoWu3n1dxptuA34lj4ybmTHXqn/74jMgnGD +-----END CERTIFICATE----- diff --git a/tests/data/webconf/ssl/ca/ca.key b/tests/data/webconf/ssl/ca/ca.key new file mode 100644 index 0000000..b28c451 --- /dev/null +++ b/tests/data/webconf/ssl/ca/ca.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/tests/data/webconf/ssl/certstore/7dd4d2a5.0 b/tests/data/webconf/ssl/certstore/7dd4d2a5.0 new file mode 120000 index 0000000..e375f5a --- /dev/null +++ b/tests/data/webconf/ssl/certstore/7dd4d2a5.0 @@ -0,0 +1 @@ +ca.pem \ No newline at end of file diff --git a/tests/data/webconf/ssl/certstore/ca.pem b/tests/data/webconf/ssl/certstore/ca.pem new file mode 100644 index 0000000..6edc8a3 --- /dev/null +++ b/tests/data/webconf/ssl/certstore/ca.pem @@ -0,0 +1,32 @@ +-----BEGIN CERTIFICATE----- +MIIFnDCCA4SgAwIBAgIJAMhg1/NG0qqgMA0GCSqGSIb3DQEBCwUAMGIxCzAJBgNV +BAYTAkRFMRMwEQYDVQQIDApTb21lLVN0YXRlMREwDwYDVQQKDAhPcGVuU1VTRTEU +MBIGA1UECwwLRGV2ZWxvcG1lbnQxFTATBgNVBAMMDDEyNy4wLjAuMSBDQTAgFw0x +OTA1MjIwNTU1MTZaGA8yMTk4MTAyNjA1NTUxNlowYjELMAkGA1UEBhMCREUxEzAR +BgNVBAgMClNvbWUtU3RhdGUxETAPBgNVBAoMCE9wZW5TVVNFMRQwEgYDVQQLDAtE +ZXZlbG9wbWVudDEVMBMGA1UEAwwMMTI3LjAuMC4xIENBMIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAtKq0Eq6sbzDfLsiXByFLNYymccotr4T1wYIeYVs6 +kKu6zrT/urvy4Oxv7DqqhmXtyZFE/FuQ9uSN7a+04cJWke18o3u6g/Wj1tuL8fev +zyrMPHqQ0eAsfYXssxmVdWULs3/G8lYCOCUJiuY7c7xAR+MSQ0vaCcwhqi6ObNxi +d6NnYvHNzDy97KBYJUk6L0EVFMsMYgPv9VqpR5vVc/R+DBSDucGAj4DmnFycOlip +eFna3lJr3XvmPrLyyJtS76Rpa51Pzrs/nrYZErAZOjOGL5WQhhl4eMQuKsyN2sK2 +58pFg+euQwjLc6Wxj9dnJ3fWIXURy0ZhJRp8clYpTkShmXwO0IuT3IbZZ2eSSqKH ++HYdeztZcJeQFlY3+VOrTb1KkmOYtOzBOR9aveU5xDJfn/i6NxQKO5dIQP2mpeyf +upH64saSqvh0qcJwwCRIodl+BgpwqJ66nQqiIDIyA5u4zSGCOTfUuYKnD1t36Goj +Ni4S2wyQ05nsknnwdakLJO7k+v9G7HNvLT0uoiySjmb/x7BRD9AQbNYCBfdznWhv +aXdY/RB1gUNUH4Q8PGyDfeYhMZWupnWmBA9oGN+OVT2eYqBlYJ9zNanQAvraeuHp +rJ+cSw1+hg5tqkKqQ4Uf76xkzNPPlygr7X7wQuxDdGtRSZHt6Qj07+s9tqAuii4Z +NUkCAwEAAaNTMFEwHQYDVR0OBBYEFI8d9N4BsjyTRjV6V6q4V5Gj314eMB8GA1Ud +IwQYMBaAFI8d9N4BsjyTRjV6V6q4V5Gj314eMA8GA1UdEwEB/wQFMAMBAf8wDQYJ +KoZIhvcNAQELBQADggIBALBFInsHdwQwHbT4i28LfN3SaCtXO4Slznx8pE8Us8IB +4F2xLry3NGZYO03F+m2E9kTJ4vYmL9o7H6Wc3cVwfp7itCAVP+oSR63YO1nnjJuq +/3KoLVHSC8rjBV7zutrVq4iPgIEFOVLcRf6a985NQeIPxJK1DgxYdTHIawwhhPZB +/T8G//NmPiBDz93OUN0rCsGTmi6DqdcTlY3kzdhTtSKJizUl6jlcs8GDoLHt324C +siKqGzTuRVmatc2fVgGJe3PYuMIvoVsrTAAZL6qlqdpCKljac7yz5q8DvAzXoo3p +40S/py2SQWsQOsSJcEwkg5IE/vgG7PadJ/sAuU6DPH95vQZjWr/pWHR5xG7PGuh2 +8B8322OMmpa8E5DnwUvdy/+JveoNZmD133mWup8WORqiLp7HwxJ6hwPj8IgEkdFn +E9EUsMwgItHD8sOdUTegRm965ysZR3xIkLIjXCTf+vsKz1Pj1YWu7EEqcaAJV6JB +2a+G6VsQrqnlxp76QD6IkUSzdztC8tvLYzwCLzD84vvfuhApo8oFiYsBF0m3Cq1V +fr4gKWZmn84yw4izVz4bXBmoFinmiBF/VwQXZcJjs0Sgea9dsql4FeeUhfK0MAQJ +okZWCL9+DvgLCW5k7q17GtlGUExI3QoWu3n1dxptuA34lj4ybmTHXqn/74jMgnGD +-----END CERTIFICATE----- diff --git a/tests/data/webconf/ssl/openssl.cnf b/tests/data/webconf/ssl/openssl.cnf new file mode 100644 index 0000000..a6c4618 --- /dev/null +++ b/tests/data/webconf/ssl/openssl.cnf @@ -0,0 +1,25 @@ +[req] +distinguished_name = req_distinguished_name +req_extensions = v3_req + +[req_distinguished_name] +countryName = Country Name (2 letter code) +countryName_default = DE +stateOrProvinceName = State or Province Name (full name) +stateOrProvinceName_default = BY +localityName = Locality Name (eg, city) +localityName_default = . +organizationalUnitName = Organizational Unit Name (eg, section) +organizationalUnitName_default = Development +commonName = localhost +commonName_max = 64 + +[ v3_req ] +# Extensions to add to a certificate request +basicConstraints = CA:FALSE +keyUsage = nonRepudiation, digitalSignature, keyEncipherment +subjectAltName = @alt_names + +[alt_names] +DNS.1 = localhost +IP.1 = 127.0.0.1 diff --git a/tests/data/webconf/ssl/server.crt b/tests/data/webconf/ssl/server.crt new file mode 100644 index 0000000..8ed5c98 --- /dev/null +++ b/tests/data/webconf/ssl/server.crt @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFHDCCAwQCAQEwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCREUxEzARBgNV +BAgMClNvbWUtU3RhdGUxETAPBgNVBAoMCE9wZW5TVVNFMRQwEgYDVQQLDAtEZXZl +bG9wbWVudDEVMBMGA1UEAwwMMTI3LjAuMC4xIENBMCAXDTE5MDUyMjA3MTI1MVoY +DzIxOTgxMDI2MDcxMjUxWjBEMQswCQYDVQQGEwJERTELMAkGA1UECAwCQlkxFDAS +BgNVBAsMC0RldmVsb3BtZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnw7WHkHubXhBV9eRQeWk9NDgDdEifF4SP +0cLxnkIIgULs/h5QSHRqIW5iJW9D9/ZLZPPWmrpuyEQMsDttHkHDmNDj/k5xYess +uuD4q+XT/rBgeoq4Q7drhqIKw9Xrv2f7KNiPwrcP0FcEEIrA9rRV2iw6mLjOwZVg +YBtlMXKrMssm4BwwTKUFKx3qWsqNVQAORblCrgP5fIgHmYNrsAaHq+ig0CXiZ4Vr +QsazMcWwClCxsJjlbdyO3OuiN6PMoceJupfcZGr95x/t7YeLu/Jb9dIepFTXmnT6 +hpl4/+YRl8Ch97kgC8X77Zbd+rniBhJ4sJfsL4FIZRzyQ5KPdpIK14oCDEH8Vtkk +fN5FBU0Wc3vrcGLUgS4Vp+98g2ALUilg20CNRaFCSdWTaTLE/eBsqZ/F1Qdrg/Lc +YWB8et9/6lqbRUxqC5rAYYJLAiDmWnIbgSoNBlgLafBmA3rIeRCu5XQEJEhmYTFh +dzAmSgAarrMBFtImx0r2H85v5LriR8FeJGDT7D+4Y0GfxKGhTN7vQ/gEJQ9m+JSu +10mYY/W1lyTuakxsczm/R9g3JkuPJy7gWAPaql6PH4kLlkyguD39lc25wnqpSJuN +n4N0O2igs6k69yKQOsv2124A6C+KDNkPRHM613FOMQWtlFCqd3gxyJVzqzt5ZO+x +Sr14lqA6uwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCKUUNolFpk82x7WsgSHeNO +OEuxgWDezKLJSb2yrJ8Lg4P77DoffRSot7V6ky7gpdSbAlBOVxI/nRvnh1hpjTDg +WtpCJ8MsLkg8Y7desEtMOFNtfm2+LG7QMG2egCOEMT7R4yZmmbXVmksU6GykHwM1 +9w0vJoT4wk6nA/s4SQN+9Wewm/bMfdaRPEq0fzUzZ9Ok/PR/En+gBJj6x9w1CC0x +cv1msWJDf8lWJB4iEARb9vsfkyiD6ydpoDym7ZylIzcW9JklcfJFJS1yBFMYmC39 +bpdZFlFeFAmm3bkqTx7bKaIdMA01zHBupj23xs/AI8aWNxP1sf2tRjBAEBM6AW0V +yIFO9JnQ1meQGGOmBG9NT6xgRkEcTImzqI29ImCI3fSUx7WbvcanNzk24efjwG3c +fSf5E6mrdLg1siyanGXBvWDVj8y9yQYiGo1W6jiZed0VNkDvygVyeNa9qEQPJ1gf +g8LSTtqP9NbetZS5qgxetwIEZVeW3jIH05UiYAN06qvym1Q6fCnLCy+19qncn+n6 +ms464/100vrCPAE1aCPsvPaR9wJ5iS7QsMFykSeL62MHp3Sn9n35aMGgqnYmtp+z +bVelf51ZET3IOgssD4g8L1FCo7l8uAxvHXrTdchlCa6/RaG3EYl9QFQFE3s1mnQ/ +spyL6Rw6a4l2snDGbhmjFA== +-----END CERTIFICATE----- diff --git a/tests/data/webconf/ssl/server.csr b/tests/data/webconf/ssl/server.csr new file mode 100644 index 0000000..8b0460e --- /dev/null +++ b/tests/data/webconf/ssl/server.csr @@ -0,0 +1,28 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIEzjCCArYCAQAwRDELMAkGA1UEBhMCREUxCzAJBgNVBAgMAkJZMRQwEgYDVQQL +DAtEZXZlbG9wbWVudDESMBAGA1UEAwwJbG9jYWxob3N0MIICIjANBgkqhkiG9w0B +AQEFAAOCAg8AMIICCgKCAgEAp8O1h5B7m14QVfXkUHlpPTQ4A3RInxeEj9HC8Z5C +CIFC7P4eUEh0aiFuYiVvQ/f2S2Tz1pq6bshEDLA7bR5Bw5jQ4/5OcWHrLLrg+Kvl +0/6wYHqKuEO3a4aiCsPV679n+yjYj8K3D9BXBBCKwPa0VdosOpi4zsGVYGAbZTFy +qzLLJuAcMEylBSsd6lrKjVUADkW5Qq4D+XyIB5mDa7AGh6vooNAl4meFa0LGszHF +sApQsbCY5W3cjtzrojejzKHHibqX3GRq/ecf7e2Hi7vyW/XSHqRU15p0+oaZeP/m +EZfAofe5IAvF++2W3fq54gYSeLCX7C+BSGUc8kOSj3aSCteKAgxB/FbZJHzeRQVN +FnN763Bi1IEuFafvfINgC1IpYNtAjUWhQknVk2kyxP3gbKmfxdUHa4Py3GFgfHrf +f+pam0VMaguawGGCSwIg5lpyG4EqDQZYC2nwZgN6yHkQruV0BCRIZmExYXcwJkoA +Gq6zARbSJsdK9h/Ob+S64kfBXiRg0+w/uGNBn8ShoUze70P4BCUPZviUrtdJmGP1 +tZck7mpMbHM5v0fYNyZLjycu4FgD2qpejx+JC5ZMoLg9/ZXNucJ6qUibjZ+DdDto +oLOpOvcikDrL9tduAOgvigzZD0RzOtdxTjEFrZRQqnd4MciVc6s7eWTvsUq9eJag +OrsCAwEAAaBFMEMGCSqGSIb3DQEJDjE2MDQwCQYDVR0TBAIwADALBgNVHQ8EBAMC +BeAwGgYDVR0RBBMwEYIJbG9jYWxob3N0hwR/AAABMA0GCSqGSIb3DQEBCwUAA4IC +AQBvf/UZ9eUyzlkSRLT31YiWgYb3bAS4uYQGu4WxHJAD0RI5aV8C/0KOdt5vlxs2 +BjljDUNcs6ccYHRlFvzpita8M+H5fB4nnlRnOezfIid24z6avdxqUr6rUvdf9k0I +WrN/tLA2tWPz4teTx/bHgaiyexyj7EdgA6HqxmDWwoO7OGcrfS0PdMTYNxPi8hL7 +U7Z/ds1n/3JkSClmtaZeNSVhtiHn0dvhGuMeyd21zc3Er5E8KIcQnI7UPo+EbsTj +qgRJaU/r3pNRYuqKJC4lOGO85Xczsc2ufKSofkyKoUIg+B8OV9eMJok6XtmSM0VF +KX4B4qFXyacRvchNIjrHiFxYP8Swj0r9viDjp4SnxRh66uIvMDNuz7ycd5M+oDJf +HsHMzDRD9ORXbLmgNNtP+hwEh60Zb8G5SrI8W4DJ3jowqYl6mGzwefwnxegdccxD +Gz/DFsAD9cV1TBQs+fcOOjPcrCH9jounuAJcbt+CSiRgL3MlwYdA96bbbiqfyCEa +1mqz/qIvP6i7lHe/ydRUgJOuUMmA0/FH9nF21SneQ59NHlXE+dCSIRhPooL9HBqN +61TJ7SdtYrTYtfMz1QPKRRll55IjQEY15+NWhLA/qp8/tDfyuUrBT3W13P6/jLCa +N1xyazyra6L9ussjQkrjtEW2S2hno63iJ+7OdXDCRlu38Q== +-----END CERTIFICATE REQUEST----- diff --git a/tests/data/webconf/ssl/server.key b/tests/data/webconf/ssl/server.key new file mode 100644 index 0000000..b7439ca --- /dev/null +++ b/tests/data/webconf/ssl/server.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAp8O1h5B7m14QVfXkUHlpPTQ4A3RInxeEj9HC8Z5CCIFC7P4e +UEh0aiFuYiVvQ/f2S2Tz1pq6bshEDLA7bR5Bw5jQ4/5OcWHrLLrg+Kvl0/6wYHqK +uEO3a4aiCsPV679n+yjYj8K3D9BXBBCKwPa0VdosOpi4zsGVYGAbZTFyqzLLJuAc +MEylBSsd6lrKjVUADkW5Qq4D+XyIB5mDa7AGh6vooNAl4meFa0LGszHFsApQsbCY +5W3cjtzrojejzKHHibqX3GRq/ecf7e2Hi7vyW/XSHqRU15p0+oaZeP/mEZfAofe5 +IAvF++2W3fq54gYSeLCX7C+BSGUc8kOSj3aSCteKAgxB/FbZJHzeRQVNFnN763Bi +1IEuFafvfINgC1IpYNtAjUWhQknVk2kyxP3gbKmfxdUHa4Py3GFgfHrff+pam0VM +aguawGGCSwIg5lpyG4EqDQZYC2nwZgN6yHkQruV0BCRIZmExYXcwJkoAGq6zARbS +JsdK9h/Ob+S64kfBXiRg0+w/uGNBn8ShoUze70P4BCUPZviUrtdJmGP1tZck7mpM +bHM5v0fYNyZLjycu4FgD2qpejx+JC5ZMoLg9/ZXNucJ6qUibjZ+DdDtooLOpOvci +kDrL9tduAOgvigzZD0RzOtdxTjEFrZRQqnd4MciVc6s7eWTvsUq9eJagOrsCAwEA +AQKCAgEAlaSy1duBBlNfSu3s3AOQZfGgTSR6ar51ljvLIe7ChAeZBQCfVYlrngd4 +CL/Pgdc6sIG6JyEZTxv/5zmDqI+mpaw4GEaM/gIT3nBLoETk2raB6W0lM7vjblxH +SkbpGEJBo/0JPyK2W7rBA3Ul732f2jyj2xjDMFnovnC7vwXefOrv3xtkyYh0YinV +o2ec6Xh6dkCnQd0q2m3EgNLkMThwerBS7q78O/mPPt/vkYPCDIcG95jIqU3XwO86 +mBX9W9iqviXcs9A2x4hUKM0JbREW3ARnisGWlELIOXe6if3o4KR2RYNMdFNMJK4H +NrYg/IXiEBmlSh4Nud/HdCnmH2XqWaMTwMkY6Nwtyaq8XD1pQELFqfTJDgFOjAkI +j1Xu4ivEHpNdEhvfXqYw/+FyqkpJ/UWosBuwqTvcWTX+pa2dGvp5xbfiSfypw8aA +74z07HekeA1NNdjXIlLum+3oe5myzSg/0RFLq5BllzfthCJ2xc0BtMkcGf9as4eb +NUFjhfZAecdN9lA8N8i17jp5NwA85Px1zgY9vBEOiL0SkdfyVazmHlLpyLuqZ1EA +pRunf/utOznGj4bnh/DzgFTLfe8HRs2Sx7j3MnI220fqryKKnyeIdegayHaEmljW +vXrpvGB9VI2qqrVwXIesvRDH80SBHUfI+Y8Z83LfmlayJ+R2QDECggEBANvCkUL0 +hOHYcmkh9A9OGMMcLMCV6TrHxk2wOBxzdVQXStfUCaHLUWgI4sM6rVVbAYrznjCi +rm2068tGlu05oxacT4eakmnERiunnsMR5QYDmEXtw+YKAZICieuiKAMoBrAt7dYB ++ybgdEREK4QKA14ezfrsZpoOHeMAOK4RZ5naMfucZpWCIU2wwmYid8CrxXoE6RDm +tPOG2Jxp1uc4bXCMX9tDsoWdxkZO8l6RaoEeNmK288ngPvaqPgXBLreEdzYAFo/G +HhoXRfB0myvQtO27bG6x5RVOPOMJoU1duJ4ZDuWRnuXmsySn+4Iqgwzwhcgosyuy +4KbHyJlqo7FLBkUCggEBAMNuFnT8kLPrn57spBaP5opT5nlqPAIyBCwLORe/Pjru +gf1P4p734uWRNhS5y32n/WeRq58HrSKwg0eZms7KJWs1UDEYfdqp3moRnTwfWdcI +gSyV/AIOxXCcVSHfbyrY7FXVVYukYl0tqHcD7MKIZAEmofX1+abhYGdFm1QWQMCH +v9PG1B46mV26UHG9zgrCchnrWjoOxyIBu8x8YzEZ0PXxm3AXELw95yQzxLjRT49Q +a9kJs5cF6oZXuZXaY/ywxqYJ9biXXPmOvWKJKdffl67O8cz4xaBQibK78pKZT9VN +vkQ037T9YE4uFOB1QoV+2CYg813lBZs9fkAOtL2uzP8CggEAN6ghTgnLlb9RypqU +y0OGNfPuyZ+t//sUmBxnOZ1sO63igKLtBZMOvQBzHerAd3ui+mQUzlCFSLeneEYa +d14/lbxkz/0v06Wn9+pt5Q2lKU7DxAIhuSMTnr0R3SGmbJY4i2o2cBr0VrZF+/wf +4UL/81ht5nz0x1OH8jPeJwe1a1u9iPHlcTwR3zFDKsbT+XIHg4220Vb8wSiHt6V+ +jfTWksiahlew4PJCgw//hj/h722NbJbVS22FxMb9CkwQ3t2nq39+N09/1C/MwMdn +fUNQb10mayqW0DyOYxnPRl7UIQZLpYyp56Pz/vakViUaJ67K0xSrvAeDqfmzLle5 +uW882QKCAQAz/B+7JMf1JDNEmhwX6FVh7Gl9WJX324gikyWvvG54TKOFV2+n67aO +bG8fWkDX/wy4NRaa6fbTKHLzY9e7NCh5+SeIt8Qam18Phfn2WTyTp658xrTPc1Bv +4RYAOagflK5hMqtbxvFnadLLPd8H7DH14GnqvHCZRJBZSDnGR1kYHcQYOGaKV/od +5Yaqitu5HvotDN7mXLH5yM5E2b2k/QIJuigny+rmt+y5Q5ALvZnVPIZDqIH+JVO6 +QrGaPAqm1/svhay4WoMf2yljgasAwnhdxqypYm9ncqT+R2KCPofu7Iw1Jn9vbIrm +oPlqr6ZvTkt+8PrruhUgs13W+lJ3tnzPAoIBAErt9PSnomzWlTspLi8Ep45K8/nV +6aP3SXJ+EVawhr1EL3YphS+C1FBy5Ki97hrjEBnxyYWyJ6H68SLqe5O3V/lO9XLY +4yD8pY4hMTf+S2czyQZvadaDp5dO0g3f2EpZLZ4JdxHvcN2QJhLCEvV1esad/2hC +xzzk1Dpfcy7d4SjOYmtb4KdPiT1tv3Gr7KO4ntrAdhmvCCpfhSYkSzhhnjd5VYcW +3la9wzuqvst/Ya09oHE27xk9T4a2SJ4JiptwmuxxCDMH2JNCHBtT4Q7c00b+iUx1 +O2+q5IipfhQJBfSAL1d1v2eHfq3aJWCUUnLktpaiacV6kRFcmhPS3UVoxDw= +-----END RSA PRIVATE KEY----- diff --git a/tests/data/webconf/ssl/server.pem b/tests/data/webconf/ssl/server.pem new file mode 100644 index 0000000..570e661 --- /dev/null +++ b/tests/data/webconf/ssl/server.pem @@ -0,0 +1,81 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIFHDCCAwQCAQEwDQYJKoZIhvcNAQELBQAwYjELMAkGA1UEBhMCREUxEzARBgNV +BAgMClNvbWUtU3RhdGUxETAPBgNVBAoMCE9wZW5TVVNFMRQwEgYDVQQLDAtEZXZl +bG9wbWVudDEVMBMGA1UEAwwMMTI3LjAuMC4xIENBMCAXDTE5MDUyMjA3MTI1MVoY +DzIxOTgxMDI2MDcxMjUxWjBEMQswCQYDVQQGEwJERTELMAkGA1UECAwCQlkxFDAS +BgNVBAsMC0RldmVsb3BtZW50MRIwEAYDVQQDDAlsb2NhbGhvc3QwggIiMA0GCSqG +SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnw7WHkHubXhBV9eRQeWk9NDgDdEifF4SP +0cLxnkIIgULs/h5QSHRqIW5iJW9D9/ZLZPPWmrpuyEQMsDttHkHDmNDj/k5xYess +uuD4q+XT/rBgeoq4Q7drhqIKw9Xrv2f7KNiPwrcP0FcEEIrA9rRV2iw6mLjOwZVg +YBtlMXKrMssm4BwwTKUFKx3qWsqNVQAORblCrgP5fIgHmYNrsAaHq+ig0CXiZ4Vr +QsazMcWwClCxsJjlbdyO3OuiN6PMoceJupfcZGr95x/t7YeLu/Jb9dIepFTXmnT6 +hpl4/+YRl8Ch97kgC8X77Zbd+rniBhJ4sJfsL4FIZRzyQ5KPdpIK14oCDEH8Vtkk +fN5FBU0Wc3vrcGLUgS4Vp+98g2ALUilg20CNRaFCSdWTaTLE/eBsqZ/F1Qdrg/Lc +YWB8et9/6lqbRUxqC5rAYYJLAiDmWnIbgSoNBlgLafBmA3rIeRCu5XQEJEhmYTFh +dzAmSgAarrMBFtImx0r2H85v5LriR8FeJGDT7D+4Y0GfxKGhTN7vQ/gEJQ9m+JSu +10mYY/W1lyTuakxsczm/R9g3JkuPJy7gWAPaql6PH4kLlkyguD39lc25wnqpSJuN +n4N0O2igs6k69yKQOsv2124A6C+KDNkPRHM613FOMQWtlFCqd3gxyJVzqzt5ZO+x +Sr14lqA6uwIDAQABMA0GCSqGSIb3DQEBCwUAA4ICAQCKUUNolFpk82x7WsgSHeNO +OEuxgWDezKLJSb2yrJ8Lg4P77DoffRSot7V6ky7gpdSbAlBOVxI/nRvnh1hpjTDg +WtpCJ8MsLkg8Y7desEtMOFNtfm2+LG7QMG2egCOEMT7R4yZmmbXVmksU6GykHwM1 +9w0vJoT4wk6nA/s4SQN+9Wewm/bMfdaRPEq0fzUzZ9Ok/PR/En+gBJj6x9w1CC0x +cv1msWJDf8lWJB4iEARb9vsfkyiD6ydpoDym7ZylIzcW9JklcfJFJS1yBFMYmC39 +bpdZFlFeFAmm3bkqTx7bKaIdMA01zHBupj23xs/AI8aWNxP1sf2tRjBAEBM6AW0V +yIFO9JnQ1meQGGOmBG9NT6xgRkEcTImzqI29ImCI3fSUx7WbvcanNzk24efjwG3c +fSf5E6mrdLg1siyanGXBvWDVj8y9yQYiGo1W6jiZed0VNkDvygVyeNa9qEQPJ1gf +g8LSTtqP9NbetZS5qgxetwIEZVeW3jIH05UiYAN06qvym1Q6fCnLCy+19qncn+n6 +ms464/100vrCPAE1aCPsvPaR9wJ5iS7QsMFykSeL62MHp3Sn9n35aMGgqnYmtp+z +bVelf51ZET3IOgssD4g8L1FCo7l8uAxvHXrTdchlCa6/RaG3EYl9QFQFE3s1mnQ/ +spyL6Rw6a4l2snDGbhmjFA== +-----END CERTIFICATE----- diff --git a/tests/lib/CMakeLists.txt b/tests/lib/CMakeLists.txt new file mode 100644 index 0000000..75c7b13 --- /dev/null +++ b/tests/lib/CMakeLists.txt @@ -0,0 +1,44 @@ +find_program( NGINX nginx ) +find_program( VSFTPD vsftpd ) +find_library( LIBFCGI NAMES fcgi ) +find_library( LIBFCGI++ NAMES fcgi++ ) + +if ( NOT NGINX ) + message( FATAL_ERROR "nginx not found" ) +else() + message ( "Using nginx binary at: ${NGINX}" ) + ADD_DEFINITIONS( -DWEBSRV_BINARY="${NGINX}" ) +endif() + +if ( NOT VSFTPD ) + message( FATAL_ERROR "vsftpd not found" ) +else() + message ( "Using vsftpd binary at: ${VSFTPD}" ) + ADD_DEFINITIONS( -DFTPSRV_BINARY="${VSFTPD}" ) +endif() + +if ( NOT LIBFCGI ) + message( FATAL_ERROR "libfcgi not found" ) +else() + message ( "Using libfcgi library at: ${LIBFCGI}" ) +endif() + +if ( NOT LIBFCGI++ ) + message( FATAL_ERROR "libfcgi++ not found" ) +else() + message ( "Using libfcgi++ library at: ${LIBFCGI++}" ) +endif() + +add_definitions( -DSRCDIR="${CMAKE_CURRENT_SOURCE_DIR}") + +ADD_LIBRARY(zypp_test_utils STATIC + FtpServer.h + FtpServer.cc + TestSetup.h + TestTools.h + WebServer.h + WebServer.cc +) + +target_link_libraries( zypp_test_utils PRIVATE zypp_lib_compiler_flags ) +TARGET_LINK_LIBRARIES( zypp_test_utils PUBLIC ${LIBFCGI} ${LIBFCGI++} pthread ) diff --git a/tests/lib/FtpServer.cc b/tests/lib/FtpServer.cc new file mode 100644 index 0000000..6d10439 --- /dev/null +++ b/tests/lib/FtpServer.cc @@ -0,0 +1,379 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "FtpServer.h" + +#include +#include +#include +#include +#include + +#ifndef TESTS_SRC_DIR +#error "TESTS_SRC_DIR not defined" +#endif + +#ifndef FTPSRV_BINARY +#error "FTPSRV_BINARY not defined" +#endif + +using std::endl; +using namespace zypp; + +namespace { + + /** ExternalProgram extended to kill the child process if the parent thread exits + */ + class ZYPP_LOCAL ExternalTrackedProgram : public ExternalProgram + { + public: + ExternalTrackedProgram (const char *const *argv, const Environment & environment, + Stderr_Disposition stderr_disp = Normal_Stderr, + bool use_pty = false, int stderr_fd = -1, bool default_locale = false, + const Pathname& root = "") : ExternalProgram() + { + start_program( argv, environment, stderr_disp, stderr_fd, default_locale, root.c_str(), false, true ); + } + + }; + + bool checkLocalPort( int portno_r ) + { + bool ret = false; + + AutoDispose sockfd { socket( AF_INET, SOCK_STREAM, 0 ) }; + if ( sockfd < 0 ) { + std::cerr << "ERROR opening socket" << endl; + return ret; + } + sockfd.setDispose( ::close ); + + struct hostent * server = gethostbyname( "127.0.0.1" ); + if ( server == nullptr ) { + std::cerr << "ERROR, no such host 127.0.0.1" << endl; + return ret; + } + + struct sockaddr_in serv_addr; + bzero( &serv_addr, sizeof(serv_addr) ); + serv_addr.sin_family = AF_INET; + bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length ); + serv_addr.sin_port = htons(portno_r); + + return( connect( sockfd, (const sockaddr*)&serv_addr, sizeof(serv_addr) ) == 0 ); + } +} + +class FtpServer::Impl +{ +public: + Impl(const Pathname &root, unsigned int port, bool ssl) + : _docroot(root), _port(port), _stop(false), _stopped(true), _ssl( ssl ) + { + // wake up pipe to interrupt poll() + pipe ( _wakeupPipe ); + fcntl( _wakeupPipe[0], F_SETFL, O_NONBLOCK ); + + MIL << "Working dir is " << _workingDir << endl; + + filesystem::assert_dir( _workingDir / "log" ); + filesystem::assert_dir( _workingDir / "tmp" ); + } + + ~Impl() + { + if ( ! _stopped ) + stop(); + + close (_wakeupPipe[0]); + close (_wakeupPipe[1]); + } + + int port() const + { + return _port; + } + + void worker_thread() + { + + /* + * -o vsftpd_log_file=/var/log/vsftpd.log + * + * ssl_enable=NO + * rsa_cert_file= + * dsa_cert_file= + * listen_port + * + * -o anon_root=/tmp/ftptest + * -o local_root=/tmp/ftptest + * + */ + + ExternalProgram::Environment env; + + const auto confPath = _workingDir.path(); + const auto confFile = confPath/"vsftpd.conf"; + bool canContinue = true; + + { + std::lock_guard lock ( _mut ); + canContinue = ( zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"vsftpconf"/"vsftpd.conf", confFile ) == 0 ); + if ( canContinue && _ssl ) canContinue = zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"webconf"/"ssl"/"server.pem", confPath/"cert.pem") == 0; + if ( canContinue && _ssl ) canContinue = zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"webconf"/"ssl"/"server.key", confPath/"cert.key") == 0; + } + + const std::string logfile = (zypp::str::Format("-vsftpd_log_file=%1%") % (confPath/"logfile")).asString(); + const std::string anonRoot = (zypp::str::Format("-oanon_root=%1%") % _docroot).asString(); + const std::string localRoot = (zypp::str::Format("-olocal_root=%1%") % _docroot).asString(); + const std::string listenPort = (zypp::str::Format("-olisten_port=%1%") % _port).asString(); + + const std::string pemFile = (zypp::str::Format("-orsa_cert_file=%1%") % (confPath/"cert.pem") ).asString (); + const std::string keyFile = (zypp::str::Format("-orsa_private_key_file=%1%") % (confPath/"cert.key") ).asString (); + + std::vector argv = { + FTPSRV_BINARY, + confFile.c_str(), + anonRoot.c_str(), + localRoot.c_str(), + listenPort.c_str(), + }; + + if ( _ssl ) { + argv.push_back ( "-ossl_enable=YES" ); + argv.push_back ( "-oallow_anon_ssl=YES" ); + argv.push_back ( pemFile.c_str() ); + argv.push_back ( keyFile.c_str() ); + } + + argv.push_back(nullptr); + + + if ( !canContinue ) { + _stopped = true; + _cv.notify_all(); + return; + } + + ExternalTrackedProgram prog( argv.data(), env, ExternalProgram::Stderr_To_Stdout, false, -1, true); + prog.setBlocking( false ); + + while(1) { + std::string line = prog.receiveLine(); + if ( line.empty() ) + break; + std::cerr << line << endl; + }; + + // Wait max 10 sec for the socket becoming available + bool isup { checkLocalPort( port() ) }; + if ( !isup ) + { + unsigned i = 0; + do { + std::this_thread::sleep_for( std::chrono::milliseconds(1000) ); + isup = checkLocalPort( port() ); + } while ( !isup && ++i < 10 ); + + if ( !isup && prog.running() ) { + prog.kill( SIGTERM ); + prog.close(); + } + } + + if ( !prog.running() ) { + _stop = true; + _stopped = true; + } else { + _stopped = false; + } + + struct pollfd fds[] { { + _wakeupPipe[0], + POLLIN, + 0 + }, { + fileno( prog.inputFile() ), + POLLIN | POLLHUP | POLLERR, + 0 + } + }; + + bool firstLoop = true; + + while ( 1 ) { + + if ( firstLoop ) { + firstLoop = false; + _cv.notify_all(); + if ( _stopped ) + return; + } + + //listen on a pipe for a wakeup event to stop the worker if required + int ret = zyppng::eintrSafeCall( ::poll, fds, 2, -1 ); + + if ( ret < 0 ) { + std::cerr << "Poll error " << errno << endl; + continue; + } + + if ( fds[0].revents ) { + //clear pipe + char dummy; + while ( read( _wakeupPipe[0], &dummy, 1 ) > 0 ) { continue; } + } + + if ( fds[1].revents ) { + while(1) { + std::string line = prog.receiveLine(); + if ( line.empty() ) + break; + std::cerr << line << endl; + }; + + if ( !prog.running() ) { + std::cerr << "Ftpserver exited too early" << endl; + _stop = true; + _stopped = true; + } + } + + if ( _stop ) + break; + } + + if ( prog.running() ) { + prog.kill( SIGTERM ); + prog.close(); + } + } + + std::string log() const + { + //read logfile + return std::string(); + } + + void stop() + { + MIL << "Waiting for server thread to finish" << endl; + _stop = true; + + //signal the thread to wake up + write( _wakeupPipe[1], "\n", 1); + + _thrd->join(); + MIL << "server thread finished" << endl; + + _thrd.reset(); + _stopped = true; + } + + void start() + { + if ( !filesystem::PathInfo( _docroot ).isExist() ) { + std::cerr << "Invalid docroot" << std::endl; + throw zypp::Exception("Invalid docroot"); + } + + if ( !_stopped ) { + stop(); + } + + _stop = _stopped = false; + + std::unique_lock lock( _mut ); + _thrd.reset( new std::thread( &Impl::worker_thread, this ) ); + _cv.wait(lock); + + if ( _stopped ) { + _thrd->join(); + throw zypp::Exception("Failed to start the ftpserver"); + } + } + + std::mutex _mut; // _thrd; + + unsigned int _port; + int _wakeupPipe[2]; + + std::atomic_bool _stop; + bool _stopped; + bool _ssl; +}; + + +FtpServer::FtpServer(const Pathname &root, unsigned int port, bool useSSL) + : _pimpl(new Impl(root, port, useSSL)) +{ +} + +bool FtpServer::start() +{ + _pimpl->start(); + return !isStopped(); +} + + +std::string FtpServer::log() const +{ + return _pimpl->log(); +} + +bool FtpServer::isStopped() const +{ + return _pimpl->_stopped; +} + +int FtpServer::port() const +{ + return _pimpl->port(); +} + + +Url FtpServer::url() const +{ + Url url; + url.setHost("localhost"); + url.setPort(str::numstring(port())); + url.setScheme("ftp"); + return url; +} + +media::TransferSettings FtpServer::transferSettings() const +{ + media::TransferSettings set; + set.setCertificateAuthoritiesPath(zypp::Pathname(TESTS_SRC_DIR)/"data/webconf/ssl/certstore"); + return set; +} + +void FtpServer::stop() +{ + _pimpl->stop(); +} + +FtpServer::~FtpServer() +{ +} diff --git a/tests/lib/FtpServer.h b/tests/lib/FtpServer.h new file mode 100644 index 0000000..433dc45 --- /dev/null +++ b/tests/lib/FtpServer.h @@ -0,0 +1,86 @@ + +#ifndef ZYPP_TEST_FTPSERVER_H +#define ZYPP_TEST_FTPSERVER_H + +#include +#include +#include +#include + +#include + +/** + * + * Starts a ftp server to simulate remote transfers in + * testcases + * + * \code + * #include "FtpServer.h" + * + * BOOST_AUTO_TEST_CASE(Foo) + * { + * + * FtpServer srv((Pathname(TESTS_SRC_DIR) + "/datadir").c_str() ); + * srv.start(); + * + * MediaSetAccess media( Url("ftp://localhost:9099"), "/" ); + * + * // do something with the url + * + * + * srv.stop(); + * + * \endcode + */ +class FtpServer +{ + public: + + /** + * creates a web server on \ref root and \port + */ + FtpServer(const zypp::Pathname &root, unsigned int port=10001, bool useSSL = false ); + ~FtpServer(); + /** + * Starts the webserver worker thread + * Waits up to 10 seconds and returns whether the port is now active. + */ + bool start(); + + /** + * Stops the worker thread + */ + void stop(); + + /** + * returns the port we are listening to + */ + int port() const; + + /** + * returns the base url where the webserver is listening + */ + zypp::Url url() const; + + /** + * generates required transfer settings + */ + zypp::media::TransferSettings transferSettings () const; + + /** + * shows the log of last run + */ + std::string log() const; + + /** + * Checks if the server was stopped + */ + bool isStopped() const; + + class Impl; +private: + /** Pointer to implementation */ + zypp::RW_pointer _pimpl; +}; + +#endif diff --git a/tests/lib/TestSetup.h b/tests/lib/TestSetup.h new file mode 100644 index 0000000..bf20355 --- /dev/null +++ b/tests/lib/TestSetup.h @@ -0,0 +1,377 @@ +#ifndef INCLUDE_TESTSETUP +#define INCLUDE_TESTSETUP +#include + +#ifndef INCLUDE_TESTSETUP_WITHOUT_BOOST +#include +using boost::unit_test::test_case; +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::cin; +using std::cout; +using std::cerr; +using std::endl; +using std::flush; +using namespace zypp; + +#ifndef BOOST_CHECK_NE +#define BOOST_CHECK_NE( L, R ) BOOST_CHECK( (L) != (R) ) +#endif + +#define LABELED(V) #V << ":\t" << V + +enum TestSetupOptionBits +{ + TSO_CLEANROOT = (1 << 0), // wipe rootdir in ctor + TSO_REPO_DEFAULT_GPG = (1 << 1), // dont turn off gpgcheck in repos +}; +ZYPP_DECLARE_FLAGS_AND_OPERATORS( TestSetupOptions, TestSetupOptionBits ); + +/** Build a test environment below a temp. root directory. + * If a \c rootdir_r was provided to the ctor, this directory + * will be used and it will \b not be removed. + * + * \note The lifetime of this objects is the lifetime of the temp. root directory. + * + * \code + * #include "TestSetup.h" + * + * BOOST_AUTO_TEST_CASE(WhatProvides) + * { + * // enabls loging fot the scope of this block: + * // base::LogControl::TmpLineWriter shutUp( new log::FileLineWriter( "/tmp/YLOG" ) ); + * + * TestSetup test( Arch_x86_64 ); + * // test.loadTarget(); // initialize and load target + * test.loadRepo( TESTS_SRC_DIR"/data/openSUSE-11.1" ); + * + * // Here the pool is ready to be used. + * + * } + * \endcode +*/ +class TestSetup +{ +public: + typedef TestSetupOptions Options; + +public: + struct InitLaterType {}; + static constexpr InitLaterType initLater = InitLaterType(); + + TestSetup( InitLaterType ) + {} + + TestSetup( const Arch & sysarch_r = Arch_empty, const Options & options_r = Options() ) + : _pimpl { new Impl( Pathname(), sysarch_r, options_r ) } + {} + + TestSetup( const Pathname & rootdir_r, const Arch & sysarch_r = Arch_empty, const Options & options_r = Options() ) + : _pimpl { new Impl( rootdir_r, sysarch_r, options_r ) } + {} + + TestSetup( const Pathname & rootdir_r, const Options & options_r ) + : _pimpl { new Impl( rootdir_r, Arch_empty, options_r ) } + {} + + void reset() + { _pimpl.reset(); } + +public: + /** Whether directory \a path_r contains a solver testcase. */ + static bool isTestcase( const Pathname & path_r ) + { + return zypp::misc::testcase::LoadTestcase::None != zypp::misc::testcase::LoadTestcase::testcaseTypeAt( path_r ); + } + + /** Whether directory \a path_r contains a testsetup. */ + static bool isTestSetup( const Pathname & path_r ) + { + return filesystem::PathInfo( path_r / "repos.d" ).isDir() && filesystem::PathInfo( path_r / "raw" ).isDir(); + } + +public: + const Pathname & root() const { return _pimpl->_rootdir; } + + Target & target() { if ( ! getZYpp()->getTarget() ) getZYpp()->initializeTarget( _pimpl->_rootdir ); return *getZYpp()->getTarget(); } + RepoManager repomanager() { return RepoManager( RepoManagerOptions::makeTestSetup( _pimpl->_rootdir ) ); } + ResPool pool() { return ResPool::instance(); } + ResPoolProxy poolProxy() { return pool().proxy(); } + sat::Pool satpool() { return sat::Pool::instance(); } + Resolver & resolver() { return *getZYpp()->resolver(); } + +public: + /** Load target repo. */ + void loadTarget() + { target().load(); } + /** Fake @System repo from url. */ + void loadTargetRepo( const Url & url_r ) + { loadRepo( url_r, sat::Pool::systemRepoAlias() ); } + /** Fake @System repo from Path. */ + void loadTargetRepo( const Pathname & path_r ) + { loadRepo( path_r, sat::Pool::systemRepoAlias() ); } + /** Fake @System repo from helix repo. */ + void loadTargetHelix( const Pathname & path_r ) + { loadHelix( path_r, sat::Pool::systemRepoAlias() ); } + +public: + /** Directly load repoinfo to pool. */ + void loadRepo( RepoInfo nrepo ) + { + RepoManager rmanager( repomanager() ); + if ( rmanager.hasRepo( nrepo ) ) + nrepo.setAlias( RepoManager::makeStupidAlias( nrepo.url() ) ); + rmanager.addRepository( nrepo ); + rmanager.buildCache( nrepo ); + rmanager.loadFromCache( nrepo ); + } + /** Directly load repo from url to pool. */ + void loadRepo( const Url & url_r, const std::string & alias_r = std::string() ) + { + RepoInfo nrepo; + nrepo.setAlias( alias_r.empty() ? url_r.getHost()+":"+Pathname::basename(url_r.getPathName()) : alias_r ); + nrepo.addBaseUrl( url_r ); + if ( ! _pimpl->_options.testFlag( TSO_REPO_DEFAULT_GPG ) ) + nrepo.setGpgCheck( false ); + loadRepo( nrepo ); + } + /** Directly load repo from metadata(dir) or solvfile(file) to pool. + * An empty alias is guessed. + */ + void loadRepo( const Pathname & path_r, const std::string & alias_r = std::string() ) + { + if ( filesystem::PathInfo( path_r ).isDir() ) + { + loadRepo( path_r.asUrl(), alias_r ); + return; + } + // .solv file is loaded directly using a faked RepoInfo + RepoInfo nrepo; + nrepo.setAlias( alias_r.empty() ? path_r.basename() : alias_r ); + satpool().addRepoSolv( path_r, nrepo ); + } + /** Directly load repo from some location (url or absolute(!)path). + * An empty alias is guessed. + */ + void loadRepo( const std::string & loc_r, const std::string & alias_r = std::string() ) + { + if ( *loc_r.c_str() == '/' ) + { + loadRepo( Pathname( loc_r ), alias_r ); + } + else + { + loadRepo( Url( loc_r ), alias_r ); + } + } + /** Directly load repo from some location (url or absolute(!)path). + * An empty alias is guessed. + */ + void loadRepo( const char * loc_r, const std::string & alias_r = std::string() ) + { loadRepo( std::string( loc_r ? loc_r : "" ), alias_r ); } + + /** Directly load a helix repo from some testcase. + ** An empty alias is guessed. + **/ + void loadHelix( const Pathname & path_r, const std::string & alias_r = std::string() ) + { + // .solv file is loaded directly using a faked RepoInfo + RepoInfo nrepo; + nrepo.setAlias( alias_r.empty() ? path_r.basename() : alias_r ); + satpool().addRepoHelix( path_r, nrepo ); + } + + // Load repos included in a solver testcase. + void loadTestcaseRepos( const Pathname & path_r, misc::testcase::LoadTestcase::TestcaseTrials * trialsP_r = nullptr ) + { + zypp::misc::testcase::LoadTestcase loader; + std::string err; + if (!loader.loadTestcaseAt( path_r, &err ) ) { + ZYPP_THROW( Exception(err) ); + } + + const auto &setup = loader.setupInfo(); + auto tempRepoManager = repomanager(); + if ( !setup.applySetup( tempRepoManager ) ) { + ZYPP_THROW( Exception("Failed to apply setup!") ); + } + + { + base::SetTracker localesTracker = setup.localesTracker(); + localesTracker.removed().insert( localesTracker.current().begin(), localesTracker.current().end() ); + satpool().initRequestedLocales( localesTracker.removed() ); + + localesTracker.added().insert( localesTracker.current().begin(), localesTracker.current().end() ); + satpool().setRequestedLocales( localesTracker.added() ); + } + poolProxy(); // prepare + if ( trialsP_r ) + *trialsP_r = loader.trialInfo(); + } + +public: + /** Load all enabled repos in repos.d to pool. */ + void loadRepos() + { + RepoManager repoManager( repomanager() ); + RepoInfoList repos = repoManager.knownRepositories(); + for ( RepoInfoList::iterator it = repos.begin(); it != repos.end(); ++it ) + { + RepoInfo & nrepo( *it ); + USR << nrepo << endl; + + if ( ! nrepo.enabled() ) + continue; + + if ( ! repoManager.isCached( nrepo ) || nrepo.type() == repo::RepoType::RPMPLAINDIR ) + { + if ( repoManager.isCached( nrepo ) ) + { + USR << "cleanCache" << endl; + repoManager.cleanCache( nrepo ); + } + //USR << "refreshMetadata" << endl; + //repoManager.refreshMetadata( nrepo ); + USR << "buildCache" << endl; + repoManager.buildCache( nrepo ); + } + USR << "Create from cache" << endl; + repoManager.loadFromCache( nrepo ); + } + } + +public: + /** Detect and load the system located at \a sysRoot. + * + * \a sysRoot needs to be a directory containing either a SolverTestcase, + * a TestSetup system or a real system. The provided repostitories are + * loaded into the pool (without refresh). + */ + static void LoadSystemAt( const Pathname & sysRoot, const Arch & _testSetupArch_r = Arch_x86_64 ) + { + if ( ! PathInfo( sysRoot ).isDir() ) + ZYPP_THROW( Exception("sysRoot argument needs to be a directory") ); + + if ( TestSetup::isTestcase( sysRoot ) ) + { + USR << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl; + TestSetup test; + test.loadTestcaseRepos( sysRoot ); + } + else if ( TestSetup::isTestSetup( sysRoot ) ) + { + USR << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl; + + TestSetup test( sysRoot, _testSetupArch_r ); + test.loadRepos(); + + Pathname solvCachePath( RepoManagerOptions::makeTestSetup( test.root() ).repoSolvCachePath ); + Pathname fakeTargetSolv( solvCachePath / sat::Pool::systemRepoAlias() / "solv" ); + if ( PathInfo( fakeTargetSolv ).isFile() ) + { + USR << str::form( "*** Fake TestSetup Target from '%s'", fakeTargetSolv.c_str() ) << endl; + test.target(); + test.loadTargetRepo( fakeTargetSolv ); + } + } + else + { + sat::Pool satpool( sat::Pool::instance() ); + // a system + USR << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl; + if ( 1 ) + { + USR << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl; + getZYpp()->initializeTarget( sysRoot ); + getZYpp()->target()->load(); + USR << satpool.systemRepo() << endl; + } + + if ( 1 ) + { + RepoManager repoManager( sysRoot ); + RepoInfoList repos = repoManager.knownRepositories(); + for_( it, repos.begin(), repos.end() ) + { + RepoInfo & nrepo( *it ); + + if ( ! nrepo.enabled() ) + continue; + + if ( ! repoManager.isCached( nrepo ) ) + { + USR << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + + USR << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush; + try + { + repoManager.loadFromCache( nrepo ); + USR << satpool.reposFind( nrepo.alias() ) << endl; + } + catch ( const Exception & exp ) + { + USR << exp.asString() + "\n" + exp.historyAsString() << endl; + USR << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + } + } + } + } + +private: + struct Impl + { + Impl( const Pathname & rootdir_r, const Arch & sysarch_r, const Options & options_r ) + { + _options = options_r; + + if ( rootdir_r.empty() ) + _rootdir = _tmprootdir.path(); + else + { + filesystem::assert_dir( (_rootdir = rootdir_r) ); + if ( _options.testFlag( TSO_CLEANROOT ) ) + filesystem::clean_dir( _rootdir ); + } + + // erase any old pool content... + getZYpp()->finishTarget(); + sat::Pool::instance().reposEraseAll(); + // prepare for the new one... + ZConfig::instance().setRepoManagerRoot( _rootdir ); + + if ( ! sysarch_r.empty() ) + ZConfig::instance().setSystemArchitecture( sysarch_r ); + USR << "CREATED TESTSETUP below " << _rootdir << endl; + } + + ~Impl() + { USR << (_tmprootdir.path() == _rootdir ? "DELETE" : "KEEP") << " TESTSETUP below " << _rootdir << endl; } + + filesystem::TmpDir _tmprootdir; + Pathname _rootdir; + Options _options; + }; + + std::unique_ptr _pimpl; // maybe worth creating RW_pointer traits for it +}; + +#endif //INCLUDE_TESTSETUP diff --git a/tests/lib/TestTools.h b/tests/lib/TestTools.h new file mode 100644 index 0000000..988f290 --- /dev/null +++ b/tests/lib/TestTools.h @@ -0,0 +1,29 @@ +#ifndef TESTTOOLS_H +#define TESTTOOLS_H + +#include +#include + +#include "zypp/Pathname.h" +#include "zypp/PathInfo.h" + +namespace TestTools { + //read all contents of a file into a string) + std::string readFile ( const zypp::Pathname &file ) + { + if ( ! zypp::PathInfo( file ).isFile() ) { + return std::string(); + } + std::ifstream istr( file.asString().c_str() ); + if ( ! istr ) { + return std::string(); + } + + std::string str((std::istreambuf_iterator(istr)), + std::istreambuf_iterator()); + return str; + } +} + + +#endif // TESTTOOLS_H diff --git a/tests/lib/WebServer.cc b/tests/lib/WebServer.cc new file mode 100644 index 0000000..9fed168 --- /dev/null +++ b/tests/lib/WebServer.cc @@ -0,0 +1,590 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "WebServer.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef TESTS_SRC_DIR +#error "TESTS_SRC_DIR not defined" +#endif +#ifndef WEBSRV_BINARY +#error "WEBSRV_BINARY not defined" +#endif + +using std::endl; +using namespace zypp; + +namespace { + + /** ExternalProgram extended to kill the child process if the parent thread exits + */ + class ZYPP_LOCAL ExternalTrackedProgram : public ExternalProgram + { + public: + ExternalTrackedProgram (const char *const *argv, const Environment & environment, + Stderr_Disposition stderr_disp = Normal_Stderr, + bool use_pty = false, int stderr_fd = -1, bool default_locale = false, + const Pathname& root = "") : ExternalProgram() + { + start_program( argv, environment, stderr_disp, stderr_fd, default_locale, root.c_str(), false, true ); + } + + }; + + bool checkLocalPort( int portno_r ) + { + bool ret = false; + + AutoDispose sockfd { socket( AF_INET, SOCK_STREAM, 0 ) }; + if ( sockfd < 0 ) { + std::cerr << "ERROR opening socket" << endl; + return ret; + } + sockfd.setDispose( ::close ); + + struct hostent * server = gethostbyname( "127.0.0.1" ); + if ( server == nullptr ) { + std::cerr << "ERROR, no such host 127.0.0.1" << endl; + return ret; + } + + struct sockaddr_in serv_addr; + bzero( &serv_addr, sizeof(serv_addr) ); + serv_addr.sin_family = AF_INET; + bcopy( server->h_addr, &serv_addr.sin_addr.s_addr, server->h_length ); + serv_addr.sin_port = htons(portno_r); + + return( connect( sockfd, (const sockaddr*)&serv_addr, sizeof(serv_addr) ) == 0 ); + } +} + + +static inline std::string hostname() +{ + static char buf[256]; + std::string result; + if (!::gethostname(buf, 255)) + result += std::string(buf); + else + return "localhost"; + return result; +} + +static inline std::string handlerPrefix() +{ + static std::string pref("/handler/"); + return pref; +} + +WebServer::Request::Request(std::streambuf *rinbuf, std::streambuf *routbuf, std::streambuf *rerrbuf ) + : rin ( rinbuf ) + , rout ( routbuf ) + , rerr ( rerrbuf ) +{ } + +class WebServer::Impl +{ +public: + Impl(const Pathname &root, unsigned int port, bool ssl) + : _docroot(root), _port(port), _stop(false), _stopped(true), _ssl( ssl ) + { + FCGX_Init(); + + // wake up pipe to interrupt poll() + pipe ( _wakeupPipe ); + fcntl( _wakeupPipe[0], F_SETFL, O_NONBLOCK ); + + MIL << "Working dir is " << _workingDir << endl; + + filesystem::assert_dir( _workingDir / "log" ); + filesystem::assert_dir( _workingDir / "tmp" ); +#ifdef HTTP_USE_LIGHTTPD + filesystem::assert_dir( _workingDir / "state" ); + filesystem::assert_dir( _workingDir / "home" ); + filesystem::assert_dir( _workingDir / "cache" ); + filesystem::assert_dir( _workingDir / "upload" ); + filesystem::assert_dir( _workingDir / "sockets" ); +#endif + } + + ~Impl() + { + if ( ! _stopped ) + stop(); + + close (_wakeupPipe[0]); + close (_wakeupPipe[1]); + } + + Pathname socketPath () const { + return ( _workingDir.path() / "fcgi.sock" ); + } + + int port() const + { + return _port; + } + + void worker_thread() + { + AutoDispose sockFD( -1, ::close ); + + ExternalProgram::Environment env; + +#ifdef HTTP_USE_LIGHTTPD + bool canContinue = true; + Pathname confDir = Pathname(TESTS_SRC_DIR) / "data" / "lighttpdconf"; + Pathname sslDir = Pathname(TESTS_SRC_DIR) / "data" / "webconf" / "ssl"; + env["ZYPP_TEST_SRVCONF"] = confDir.asString(); + + std::string confFile = ( confDir / "lighttpd.conf" ).asString(); + + { + std::lock_guard lock ( _mut ); + sockFD.value() = FCGX_OpenSocket( socketPath().c_str(), 128 ); + env["ZYPP_TEST_SRVROOT"] = _workingDir.path().c_str(); + env["ZYPP_TEST_PORT"] = str::numstring( _port ); + env["ZYPP_TEST_DOCROOT"] = _docroot.c_str(); + env["ZYPP_TEST_SOCKPATH"] = socketPath().c_str(); + env["ZYPP_SSL_CONFDIR"] = sslDir.c_str(); + if ( _ssl ) + env["ZYPP_TEST_USE_SSL"] = "1"; + } + + const char* argv[] = + { + "/usr/sbin/lighttpd", + "-D", + "-f", confFile.c_str(), + nullptr + }; +#else + + const auto writeConfFile = []( const Pathname &fileName, const std::string &data ){ + std::ofstream file; + file.open( fileName.c_str() ); + if ( file.fail() ) { + std::cerr << "Failed to create file " << fileName << std::endl; + return false; + } + file << data; + file.close(); + return true; + }; + + const auto confPath = _workingDir.path(); + const auto confFile = confPath/"nginx.conf"; + bool canContinue = true; + + { + std::lock_guard lock ( _mut ); + bool canContinue = ( zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"nginxconf"/"nginx.conf", confFile ) == 0 ); + if ( canContinue ) canContinue = writeConfFile( confPath / "srvroot.conf", str::Format("root %1%;") % _docroot ); + if ( canContinue ) canContinue = writeConfFile( confPath / "fcgisock.conf", str::Format("fastcgi_pass unix:%1%;") % socketPath().c_str() ); + if ( canContinue ) canContinue = writeConfFile( confPath / "user.conf", getuid() != 0 ? "" : "user root;" ); + if ( canContinue ) { + if ( _ssl ) + canContinue = writeConfFile( confPath / "port.conf", str::Format("listen %1% ssl;") % _port ); + else + canContinue = writeConfFile( confPath / "port.conf", str::Format("listen %1%;") % _port ); + } + if ( canContinue ) { + if ( _ssl ) + canContinue = ( zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"nginxconf"/"ssl.conf", confPath/"ssl.conf" ) == 0 ); + else + canContinue = ( zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"nginxconf"/"nossl.conf", confPath/"ssl.conf" ) == 0); + } + if ( canContinue ) canContinue = zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"nginxconf"/"mime.types", confPath/"mime.types") == 0; + if ( canContinue && _ssl ) canContinue = zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"webconf"/"ssl"/"server.pem", confPath/"cert.pem") == 0; + if ( canContinue && _ssl ) canContinue = zypp::filesystem::symlink( Pathname(TESTS_SRC_DIR)/"data"/"webconf"/"ssl"/"server.key", confPath/"cert.key") == 0; + + if ( canContinue ) + sockFD.value() = FCGX_OpenSocket( socketPath().c_str(), 128 ); + } + + const char* argv[] = + { + WEBSRV_BINARY, + "-p", confPath.c_str(), + "-c", confFile.c_str(), + nullptr + }; +#endif + + if ( !canContinue ) { + _stopped = true; + _cv.notify_all(); + return; + } + + ExternalTrackedProgram prog( argv, env, ExternalProgram::Stderr_To_Stdout, false, -1, true); + prog.setBlocking( false ); + + while(1) { + std::string line = prog.receiveLine(); + if ( line.empty() ) + break; + if ( line.find_first_of( "nginx: [alert] could not open error log file:") == 0 ) + continue; + std::cerr << line << endl; + }; + + // Wait max 10 sec for the socket becoming available + bool isup { checkLocalPort( port() ) }; + if ( !isup ) + { + unsigned i = 0; + do { + std::this_thread::sleep_for( std::chrono::milliseconds(1000) ); + isup = checkLocalPort( port() ); + } while ( !isup && ++i < 10 ); + + if ( !isup && prog.running() ) { + prog.kill( SIGTERM ); + prog.close(); + } + } + + if ( !prog.running() ) { + _stop = true; + _stopped = true; + } else { + _stopped = false; + } + + FCGX_Request request; + FCGX_InitRequest(&request, sockFD,0); + AutoDispose guard( &request, std::bind( &FCGX_Free, _1, 0 ) ); + + struct pollfd fds[] { { + _wakeupPipe[0], + POLLIN, + 0 + }, { + sockFD, + POLLIN, + 0 + }, { + fileno( prog.inputFile() ), + POLLIN | POLLHUP | POLLERR, + 0 + } + }; + + bool firstLoop = true; + + while ( 1 ) { + + if ( firstLoop ) { + firstLoop = false; + _cv.notify_all(); + if ( _stopped ) + return; + } + + //there is no way to give a timeout to FCGX_Accept_r, so we poll the socketfd for new + //connections and listen on a pipe for a wakeup event to stop the worker if required + int ret = zyppng::eintrSafeCall( ::poll, fds, 3, -1 ); + + if ( ret < 0 ) { + std::cerr << "Poll error " << errno << endl; + continue; + } + + if ( fds[0].revents ) { + //clear pipe + char dummy; + while ( read( _wakeupPipe[0], &dummy, 1 ) > 0 ) { continue; } + } + + if ( fds[2].revents ) { + while(1) { + std::string line = prog.receiveLine(); + if ( line.empty() ) + break; + std::cerr << line << endl; + }; + + if ( !prog.running() ) { + std::cerr << "Webserver exited too early" << endl; + _stop = true; + _stopped = true; + } + } + + if ( _stop ) + break; + + //no events on the listen socket, repoll + if ( ! ( fds[1].revents & POLLIN ) ) + continue; + + if ( FCGX_Accept_r(&request) == 0 ) { + + fcgi_streambuf cout_fcgi(request.out); + fcgi_streambuf cin_fcgi(request.in); + fcgi_streambuf cerr_fcgi(request.err); + + WebServer::Request req( &cin_fcgi, &cout_fcgi, &cerr_fcgi ); + + int i = 0; + for ( char *env = request.envp[i]; env != nullptr; env = request.envp[++i] ) { + char * eq = strchr( env, '=' ); + if ( !eq ) { + continue; + } + req.params.insert( { std::string( env, eq ), std::string( eq+1 ) } ); + } + + if ( !req.params.count("SCRIPT_NAME") ) { + req.rerr << "Status: 400 Bad Request\r\n" + << "Content-Type: text/html\r\n" + << "\r\n" + << "Invalid request"; + FCGX_Finish_r(&request); + continue; + } + + { + std::lock_guard lock( _mut ); + //remove "/handler/" prefix + std::string key = req.params.at("SCRIPT_NAME").substr( handlerPrefix().length() ); + + const auto &it = _handlers.find( key ); + if ( it == _handlers.end() ) { + if ( !_defaultHandler ) { + _defaultHandler = makeDefaultHandler(); + } + _defaultHandler( req ); + FCGX_Finish_r(&request); + continue; + } + //call the handler + it->second( req ); + FCGX_Finish_r(&request); + } + } + } + + if ( prog.running() ) { + prog.kill( SIGTERM ); + prog.close(); + } + } + + std::string log() const + { + //read logfile + return std::string(); + } + + void stop() + { + MIL << "Waiting for server thread to finish" << endl; + _stop = true; + + //signal the thread to wake up + write( _wakeupPipe[1], "\n", 1); + + _thrd->join(); + MIL << "server thread finished" << endl; + + _thrd.reset(); + _stopped = true; + } + + void start() + { + if ( !filesystem::PathInfo( _docroot ).isExist() ) { + std::cerr << "Invalid docroot" << std::endl; + throw zypp::Exception("Invalid docroot"); + } + + if ( !_stopped ) { + stop(); + } + + MIL << "Using socket " << socketPath() << std::endl; + _stop = _stopped = false; + + std::unique_lock lock( _mut ); + _thrd.reset( new std::thread( &Impl::worker_thread, this ) ); + _cv.wait(lock); + + if ( _stopped ) { + _thrd->join(); + throw zypp::Exception("Failed to start the webserver"); + } + } + + std::mutex _mut; // _thrd; + std::map _handlers; + WebServer::RequestHandler _defaultHandler; + unsigned int _port; + int _wakeupPipe[2]; + + std::atomic_bool _stop; + bool _stopped; + bool _ssl; +}; + + +WebServer::WebServer(const Pathname &root, unsigned int port, bool useSSL) + : _pimpl(new Impl(root, port, useSSL)) +{ +} + +bool WebServer::start() +{ + _pimpl->start(); + return !isStopped(); +} + + +std::string WebServer::log() const +{ + return _pimpl->log(); +} + +bool WebServer::isStopped() const +{ + return _pimpl->_stopped; +} + +void WebServer::addRequestHandler( const std::string &path, RequestHandler &&handler ) +{ + std::lock_guard lock( _pimpl->_mut ); + _pimpl->_handlers[path] = std::move(handler); +} + +void WebServer::setDefaultHandler ( RequestHandler &&handler ) +{ + std::lock_guard lock( _pimpl->_mut ); + _pimpl->_defaultHandler = std::move(handler); +} + +void WebServer::removeRequestHandler(const std::string &path) +{ + std::lock_guard lock( _pimpl->_mut ); + auto it = _pimpl->_handlers.find( path ); + if ( it != _pimpl->_handlers.end() ) + _pimpl->_handlers.erase( it ); +} + +int WebServer::port() const +{ + return _pimpl->port(); +} + + +Url WebServer::url() const +{ + Url url; + url.setHost("localhost"); + url.setPort(str::numstring(port())); + if ( _pimpl->_ssl ) + url.setScheme("https"); + else + url.setScheme("http"); + + return url; +} + +media::TransferSettings WebServer::transferSettings() const +{ + media::TransferSettings set; + set.setCertificateAuthoritiesPath(zypp::Pathname(TESTS_SRC_DIR)/"data/webconf/ssl/certstore"); + return set; +} + +void WebServer::stop() +{ + _pimpl->stop(); +} + +WebServer::RequestHandler WebServer::makeResponse( std::string resp ) { + return [ resp ]( WebServer::Request & req ){ + req.rout << resp; + }; +}; + +WebServer::RequestHandler WebServer::makeDefaultHandler( ) +{ + return []( WebServer::Request & req ){ + req.rerr << "Status: 404 Not Found\r\n" + << "Content-Type: text/html\r\n" + << "\r\n" + << "Request handler was not found"; + }; +} + +WebServer::RequestHandler WebServer::makeResponse( std::string status, std::string content ) { + return makeResponse( status , std::vector(), content ); +}; + +WebServer::RequestHandler WebServer::makeResponse( const std::string &status, const std::vector &headers, const std::string &content ) { + return makeResponse( makeResponseString( status, headers, content ) ); +} + +std::string WebServer::makeResponseString(const std::string &status, const std::vector &headers, const std::string &content) +{ + static const std::string genericResp = "Status: %1%\r\n" + "%2%" + "\r\n" + "%3%"; + bool hasCType = false; + bool hasLType = false; + for( const std::string &hdr : headers ) { + if ( zypp::str::startsWith( hdr, "Content-Type:" ) ) { + hasCType = true; + } + if ( zypp::str::startsWith( hdr, "Content-Length:" ) ) { + hasLType = true; + } + } + + std::string allHeaders; + if ( !hasCType ) + allHeaders += "Content-Type: text/html; charset=utf-8\r\n"; + if ( !hasLType ) + allHeaders += str::Format("Content-Length: %1%\r\n") % content.length(); + allHeaders += zypp::str::join( headers.begin(), headers.end(), "\r\n"); + + return ( zypp::str::Format( genericResp ) % status % allHeaders %content ); +}; + +WebServer::~WebServer() +{ +} diff --git a/tests/lib/WebServer.h b/tests/lib/WebServer.h new file mode 100644 index 0000000..c5c9959 --- /dev/null +++ b/tests/lib/WebServer.h @@ -0,0 +1,150 @@ + +#ifndef ZYPP_TEST_WEBSERVER_H +#define ZYPP_TEST_WEBSERVER_H + +#include +#include +#include +#include + +#include + +/** + * + * Starts a webserver to simulate remote transfers in + * testcases + * \author Duncan Mac-Vicar P. + * + * \code + * #include "WebServer.h" + * + * BOOST_AUTO_TEST_CASE(Foo) + * { + * + * WebServer web((Pathname(TESTS_SRC_DIR) + "/datadir").c_str() ); + * web.start(); + * + * MediaSetAccess media( Url("http://localhost:9099"), "/" ); + * + * // do something with the url + * + * + * web.stop(); + * + * \endcode + */ +class WebServer +{ + public: + + struct Request { + Request ( std::streambuf *rinbuf, + std::streambuf *routbuf, + std::streambuf *rerrbuf ); + std::string path; + std::map< std::string, std::string > params; + std::istream rin; + std::ostream rout; + std::ostream rerr; + }; + + using RequestHandler = std::function; + + /** + * creates a web server on \ref root and \port + */ + WebServer(const zypp::Pathname &root, unsigned int port=10001, bool useSSL = false ); + ~WebServer(); + /** + * Starts the webserver worker thread + * Waits up to 10 seconds and returns whether the port is now active. + */ + bool start(); + + /** + * Stops the worker thread + */ + void stop(); + + /** + * returns the port we are listening to + */ + int port() const; + + /** + * returns the base url where the webserver is listening + */ + zypp::Url url() const; + + /** + * generates required transfer settings + */ + zypp::media::TransferSettings transferSettings () const; + + /** + * shows the log of last run + */ + std::string log() const; + + /** + * Checks if the server was stopped + */ + bool isStopped() const; + + /** + * Sets the request handler callback, if a callback for the path does already exist + * it is replaced, can be called at any time + * + * \note a request handler path is always prefixed with /handler so to call a handler named test, the + * URL is "http://localhost/handler/test" + */ + void addRequestHandler ( const std::string &path, RequestHandler &&handler ); + + /** + * Sets the default request handler callback as a fallback if no specific handler was registered for + * a given path. The path from the HTTP request can be queried as the "REQUEST_URI" param from the \ref Request structure passed to the callback. + * + * \note a request handler path is always prefixed with /handler so to call a handler named test, the + * URL is "http://localhost/handler/test" + */ + void setDefaultHandler ( RequestHandler &&handler ); + + /*! + * Removes a registered request hander, can be called at any time + */ + void removeRequestHandler ( const std::string &path ); + + /*! + * Creates a request handler that simply returns the string in \a resp + */ + static RequestHandler makeResponse(std::string resp); + + /*! + * Creates a request handler that simply returns 404 + */ + static RequestHandler makeDefaultHandler( ); + + /*! + * Creates a request handler that sends a HTTP response with \a status and \a content + * in the respose + */ + static RequestHandler makeResponse(std::string status, std::string content); + + /*! + * Creates a request handler that sends a HTTP response with \a status \a content + * and \a headers in the respose + */ + static RequestHandler makeResponse(const std::string &status, const std::vector &headers, const std::string &content); + + /*! + * Creates the corresponding HTTP response to the given parameters + */ + static std::string makeResponseString ( const std::string &status, const std::vector &headers, const std::string &content ); + + class Impl; +private: + /** Pointer to implementation */ + zypp::RW_pointer _pimpl; +}; + +#endif diff --git a/tests/media/CMakeLists.txt b/tests/media/CMakeLists.txt new file mode 100644 index 0000000..575b879 --- /dev/null +++ b/tests/media/CMakeLists.txt @@ -0,0 +1,3 @@ +ADD_TESTS(CredentialManager CredentialFileReader MediaProducts MetaLinkParser) + +#ADD_TESTS(media1 media2 media3 media4 file_exists throw_if_not_exists) diff --git a/tests/media/CredentialFileReader_test.cc b/tests/media/CredentialFileReader_test.cc new file mode 100644 index 0000000..76c568d --- /dev/null +++ b/tests/media/CredentialFileReader_test.cc @@ -0,0 +1,39 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include + +using std::cout; +using std::endl; +using namespace zypp; +using namespace zypp::media; + +typedef std::set CredentialSet; + +struct CredCollector +{ + bool collect(AuthData_Ptr & cred) + { + cout << "got: " << endl << *cred << endl; + creds.insert(cred); + return true; + } + + CredentialSet creds; +}; + +BOOST_AUTO_TEST_CASE(read_cred) +{ + CredCollector collector; + Pathname credfile = TESTS_SRC_DIR "/media/data/credentials.cat"; + CredentialFileReader reader(credfile, + bind( &CredCollector::collect, &collector, _1 )); + + BOOST_CHECK_EQUAL(collector.creds.size(), 3); +} diff --git a/tests/media/CredentialManager_test.cc b/tests/media/CredentialManager_test.cc new file mode 100644 index 0000000..094c79d --- /dev/null +++ b/tests/media/CredentialManager_test.cc @@ -0,0 +1,113 @@ +#include +#include + +#include +#include +#include +#include + +#include + +using std::cout; +using std::endl; +using namespace zypp; +using namespace zypp::media; + +inline void testGetCreds( CredentialManager & cm_r, const std::string & url_r, + const std::string & user_r = "", + const std::string & pass_r = "" ) +{ + Url url( url_r ); + AuthData_Ptr cred = cm_r.getCred( url ); + //cout << "FOR: " << url << endl; + //cout << "GOT: " << cred << endl; + if ( user_r.empty() && pass_r.empty() ) + { + BOOST_CHECK_EQUAL( cred, AuthData_Ptr() ); + } + else + { + BOOST_CHECK_EQUAL( cred->username(), user_r ); + BOOST_CHECK_EQUAL( cred->password(), pass_r ); + } +} + +BOOST_AUTO_TEST_CASE(read_cred_for_url) +{ + CredManagerOptions opts; + opts.globalCredFilePath = TESTS_SRC_DIR "/media/data/credentials.cat"; + opts.userCredFilePath = Pathname(); + CredentialManager cm( opts ); + + BOOST_CHECK_EQUAL( cm.credsGlobalSize(), 3 ); + + testGetCreds( cm, "https://drink.it/repo/roots", "ginger", "ale" ); + testGetCreds( cm, "ftp://weprovidesoft.fr/download/opensuse/110", "agda", "ichard" ); + testGetCreds( cm, "ftp://magda@weprovidesoft.fr/download/opensuse/110", "magda", "richard" ); + testGetCreds( cm, "ftp://agda@weprovidesoft.fr/download/opensuse/110", "agda", "ichard" ); + testGetCreds( cm, "ftp://unknown@weprovidesoft.fr/download/opensuse/110" ); // NULL + testGetCreds( cm, "http://url.ok/but/not/creds" ); // NULL +} + +struct CredCollector +{ + bool collect(AuthData_Ptr & cred) + { + //cout << "got: " << endl << *cred << endl; + creds.insert(cred); + return true; + } + + CredentialManager::CredentialSet creds; +}; + + +BOOST_AUTO_TEST_CASE(save_creds) +{ + filesystem::TmpDir tmp; + CredManagerOptions opts; + opts.globalCredFilePath = tmp / "fooha"; + CredentialManager cm1(opts); + + AuthData cr1("benson","absolute"); + cr1.setUrl(Url("http://joooha.com")); + + AuthData cr2("pat","vymetheny"); + cr2.setUrl(Url("ftp://filesuck.org")); + + // should create a new file + cm1.saveInGlobal(cr1); + + CredCollector collector; + CredentialFileReader( opts.globalCredFilePath, bind( &CredCollector::collect, &collector, _1 ) ); + BOOST_CHECK_EQUAL( collector.creds.size(), 1 ); + + collector.creds.clear(); + cm1.saveInGlobal(cr2); + CredentialFileReader( opts.globalCredFilePath, bind( &CredCollector::collect, &collector, _1 ) ); + BOOST_CHECK_EQUAL(collector.creds.size(), 2 ); + + collector.creds.clear(); + // save the same creds again + cm1.saveInGlobal(cr2); + CredentialFileReader( opts.globalCredFilePath, bind( &CredCollector::collect, &collector, _1 ) ); + BOOST_CHECK_EQUAL(collector.creds.size(), 2 ); + + // todo check created file permissions +} + +BOOST_AUTO_TEST_CASE(service_base_url) +{ + filesystem::TmpDir tmp; + CredManagerOptions opts; + opts.globalCredFilePath = tmp / "fooha"; + CredentialManager cm( opts ); + + AuthData cred( "benson","absolute" ); + cred.setUrl( Url( "http://joooha.com/service/path" ) ); + cm.addGlobalCred( cred ); + + testGetCreds( cm, "http://joooha.com/service/path/repo/repofoo", "benson", "absolute" ); + testGetCreds( cm, "http://benson@joooha.com/service/path/repo/repofoo", "benson", "absolute" ); + testGetCreds( cm, "http://nobody@joooha.com/service/path/repo/repofoo" ); // NULL +} diff --git a/tests/media/MediaProducts_test.cc b/tests/media/MediaProducts_test.cc new file mode 100644 index 0000000..628bf16 --- /dev/null +++ b/tests/media/MediaProducts_test.cc @@ -0,0 +1,9 @@ +#include +#include + +#include + +BOOST_AUTO_TEST_CASE(compile) +{ + // make sure header compiles +} diff --git a/tests/media/MetaLinkParser_test.cc b/tests/media/MetaLinkParser_test.cc new file mode 100644 index 0000000..703aa70 --- /dev/null +++ b/tests/media/MetaLinkParser_test.cc @@ -0,0 +1,76 @@ +#include +#include +#include + +#include + +using namespace zypp; +using namespace zypp::media; + +BOOST_AUTO_TEST_CASE(parse_metalink) +{ + Pathname meta3file = TESTS_SRC_DIR "/media/data/openSUSE-11.3-NET-i586.iso.metalink"; + Pathname meta4file = TESTS_SRC_DIR "/media/data/openSUSE-11.3-NET-i586.iso.meta4"; + + MetaLinkParser mlp3; + MetaLinkParser mlp4; + + mlp3.parse(meta3file); + MediaBlockList bl3 = mlp3.getBlockList(); + std::vector urls3 = mlp3.getUrls(); + + mlp4.parse(meta4file); + MediaBlockList bl4 = mlp4.getBlockList(); + std::vector urls4 = mlp4.getUrls(); + + + BOOST_CHECK(bl3.asString() == bl4.asString()); + + BOOST_CHECK(urls3.size() == 94); + BOOST_CHECK(urls4.size() == 94); + + BOOST_CHECK(urls3.begin()->asString() == "http://ftp.uni-kl.de/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso"); + BOOST_CHECK(urls4.begin()->asString() == "http://ftp4.gwdg.de/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso"); + + BOOST_CHECK(bl3.getFilesize() == 120285184); + BOOST_CHECK(bl4.getFilesize() == 120285184); + + BOOST_CHECK(bl3.numBlocks() == 459); + BOOST_CHECK(bl4.numBlocks() == 459); +} + +BOOST_AUTO_TEST_CASE(parse_metalink_with_zsync_hash) +{ + Pathname meta4file = TESTS_SRC_DIR "/media/data/other.xml.gz.meta4"; + MetaLinkParser mlp4; + mlp4.parse( meta4file ); + + auto bl = mlp4.getBlockList(); + BOOST_REQUIRE( bl.haveBlocks() ); + BOOST_REQUIRE_EQUAL( bl.numBlocks(), 246 ); + + const auto &rsums = mlp4.getZsyncBlockHashes(); + const auto &csums = mlp4.getSHA1BlockHashes(); + BOOST_REQUIRE_EQUAL( rsums.size(), csums.size() ); + BOOST_REQUIRE_EQUAL( bl.numBlocks(), csums.size() ); + BOOST_REQUIRE_EQUAL( bl.getFilesize(), 16108851 ); + + BOOST_REQUIRE( bl.getFileChecksum() == hexstr2bytes("702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121") ); + BOOST_REQUIRE( rsums.front() == hexstr2bytes("52c0a614") ); + BOOST_REQUIRE( rsums.back() == hexstr2bytes("349ad053") ); + BOOST_REQUIRE( csums.front() == hexstr2bytes("b9f77f48f4a49f3438fc1bb6de90df39657597aa") ); + BOOST_REQUIRE( csums.back() == hexstr2bytes("23788c5daf28813cdc6a14f1f02add712c020fd9") ); + + const auto &mirrors = mlp4.getMirrors(); + BOOST_REQUIRE_EQUAL( mirrors.size(), 103 ); + + const auto &firstMirr = mirrors.front(); + BOOST_REQUIRE_EQUAL( firstMirr.url, zypp::Url("http://ftp.uni-erlangen.de/pub/mirrors/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz")); + BOOST_REQUIRE_EQUAL( firstMirr.priority, 1 ); + BOOST_REQUIRE_EQUAL( firstMirr.maxConnections, 10 ); + + const auto &lastMirr = mirrors.back(); + BOOST_REQUIRE_EQUAL( lastMirr.url, zypp::Url("http://mirror.internode.on.net/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz")); + BOOST_REQUIRE_EQUAL( lastMirr.priority, 103 ); + BOOST_REQUIRE_EQUAL( lastMirr.maxConnections, -1 ); +} diff --git a/tests/media/data/credentials.cat b/tests/media/data/credentials.cat new file mode 100644 index 0000000..85f713c --- /dev/null +++ b/tests/media/data/credentials.cat @@ -0,0 +1,24 @@ +# no 1 +[https://drink.it/repo/roots] +username=ginger +password=ale + +#no 2 +[ftp://weprovidesoft.fr/download/opensuse/110] +username=magda +password=richard + +# no 3 - same urla s 2 but different user (lex less than magda) +[ftp://weprovidesoft.fr/download/opensuse/110] +username=agda +password=ichard + +# fail +[http://url.ok/but/not/creds] +username= +password=any + +# fail +[badurl] +username=foo +password=bar diff --git a/tests/media/data/credentials.d/cred1 b/tests/media/data/credentials.d/cred1 new file mode 100644 index 0000000..24b3dc4 --- /dev/null +++ b/tests/media/data/credentials.d/cred1 @@ -0,0 +1,2 @@ +username=helene +password=elena diff --git a/tests/media/data/openSUSE-11.3-NET-i586.iso.meta4 b/tests/media/data/openSUSE-11.3-NET-i586.iso.meta4 new file mode 100644 index 0000000..3678e76 --- /dev/null +++ b/tests/media/data/openSUSE-11.3-NET-i586.iso.meta4 @@ -0,0 +1,602 @@ + + + MirrorBrain/2.13.2 + http://download.opensuse.org/distribution/openSUSE-current/iso/openSUSE-11.3-NET-i586.iso.meta4 + 2010-10-13T09:39:21Z + + openSUSE + http://download.opensuse.org + + + + 120285184 + + + + + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBMNZQUqE7a6JyACsoRAlr2AJ9o5fkD0DZ2MpyWC0S9EI6c7BXuPQCd +ElMAtuZlO5NgYvG2bQ8xys5iWss= +=WmmH +-----END PGP SIGNATURE----- + + a0dc5f5132b0a26218f533d837d4fc1a + c7827b5a8e62d3971524ba0c438e9574e892103a + 7db356f5e21547e423da0406b7ea36e3c6e4ee62975015294585593d3a2a88c8 + + c5bc4f75f550e44491273720086bf1692c526cbd + bbe1177d325d1310868d34e2350666f9cb119e94 + 2a167f3a34a9a09577365b1015ca23b823f0a80d + 48d2ba5258254dcd4e49140ac7857c9fdb38ab60 + bde60d0206ac5a0198e898553b665f9d9c60babb + 41437180a223068413028fd977ef4ea033bfbfce + 81b7da73641a5e3391210bc9e3de1568a5208836 + 6f9c2895ec0a887fe2dabd521e40918244da0059 + 8bc4a733263a01658a7c58a53fb777b4c8b4ff28 + ed21674a98ba5af37df44fe4ad0e140c82ac8d1e + 3772fed4a8bacd4e20478375c9dc8784f9fef98f + 62f0024c67ff6830a3355b9145f043c4d60b2f13 + d9ac81f6753d14912ec643ad8e2982bd1e128c95 + 4f5369273b928b9aaee69736140b814ee9a228d7 + d6b8bcaf68d07591774302417a3d2b4ee0948e60 + c2a98d8a80ada0b7ecdf214ab6bd3331793cb120 + d0725a3e8f0053cb76c1e4424cb2496092063836 + 50d34d802241b3b52937364a14d369f2644ea4f4 + 553ba2491229a1ccfd23d01e00df4d95e612d442 + 2943c0b02f824925e9b589bf3129f950c1e48e5d + 5d4f21b818057eb23d9aa0e27e8fa5be4c1f3594 + 9630c21e84b85e27f9ee19e59ce1a633621a0b1b + ca3c553ec4b1310c1526b684d14c85640329cd1e + 55bbc2e9d0a627b7481639f4d909118f6b811fc3 + 7843b05f31d95adac6f781f0de8e8af868490a76 + 479d93353bceea8744c7f1b4eac97b277e29ba30 + 28db10a11cf7fc317510230237b76df0dd0dc35c + 128a62f1599591f9d7db1ce53d551a00555af265 + 582ff34a81fe4b3da54defa2b890946f1fce1646 + 03855419b291564e13510d81083d79816179e4f0 + 0e5a6eb83c9f358f4bb1e092f9a3bcef95dd0a41 + f3e6e901bd37e3ec8d405a96128cc85bff450a83 + dee45f794ec0fb5fb5a20826ba2d8d191a567733 + 390c6d1eaf5a28f93d7e8237e3972b9e93fe5cca + 20336a02716605b12e6fafd18855cbae411a09eb + ef22857c452d0043adbc054dd4396c0838426ae2 + 574c3a9f656391757acb83fb5091dabeb78e2418 + 203e818753a68b0bea326ea1428972a92036d9d8 + 5b49222d21afb87a5de922e9c77ca255619d21ad + fdd7b232c5ba5fa75c30f0e628e506725869df25 + 360bb3a824926cb73357b7c587390867e944b28c + c0f194a68b2c1d8693a83ef162ad85f8c0bf93cd + 25079830fe5d0c64d5c8f65c6beb61f2832995c8 + fe5b97a5c807c66833a2f5c45a7c511299c8e7c5 + 64f287d9fc0c64c68c9b9f61711080b4072b11bc + fbd01b40db0d0d73c4346bfa6942cd23666d08d8 + e73a60b7a8efde3d70da2935d85c3ebd6b623651 + 414299b4a2da9b50700d2d7d7721139291acd2b7 + e2c03eac8cbd4ef1a1fde5b60c32f26c6760a32b + a44b4d98688b7dd787ee2c3029229ca3083b2633 + 635ab22c1507403e3ba9481b92c7637ebd58bb2e + bddcde253a718b50ab3e2517cc33938ce54baab4 + bed44cc3cacd658389c4807edead76e71329dea9 + efe42d31f00ced3aea5a9aef9a3820ec20ba9e73 + d1b1f83099c80c9219386b38063588a94385ef5a + 670abebd7cd7a0a62d4aeba3dee78c7512d2ea8c + f483d9fbe3d513be20aef6e8736c5755c9aea29e + 46b4ce6520798c362a16ac3e293cbf94f979603a + 8b5e93ad34582431b3efb89ec10e05ff4257c166 + 06e09067668ff5b9ebda474a71db44c9b8386eee + 395843d5243a235c7803bba79eca803bb9c5c5a7 + 0a2cc9fe1a1a4591110f7235b1b9ca9eb4e59ec7 + fe5ef70a92427bbded4cadcd74f648b7e33807c2 + c743ddce2e930bcdf76db2f08f5a959f6f3cecd9 + d5788b2dca4a6cb5d75cce8316db1e761c914da5 + cf5c83859f55714544e42645db270d237b6d4499 + 497214fef565cfa04c2b8f96704be999b93df93f + 2f4c7da4c7d25e6d8d63a995f5296c8295bc8d01 + 95550875564701777b6e6e02854865c991a121b6 + c378b72cdc37c83d4f713e55915863babf949ba3 + d67e326f31fcb79000e96b3032c1e16183e79d84 + 53b0067cc0e8eb9b856a11af29cf69ededfe4bfd + ebf37f7028112f669d244d55ae0290c003cc9cff + 56e6482f5e0162ee16ee77496e583c9a0d5b0b31 + 772fb29f60ecd14b3c06a317258e86b6802a1310 + b43a919ce9eae4c3f1b18f5d3f61328a9f67d885 + cd93972f4cab7128bfefe836ac5601b2cced8a42 + fe20173622a73d64f586f9594551bd5fe56ef690 + 2f22b34a49fef60f54f8f59789a439bc5232e0ab + cc1e04c724746e6058429c0610dafd639798bfab + 95ba6eba3b22e6b473f7946c8c7aa66da6547ae7 + 2b7e254485c22686e0408ce76fa6b267aadf35ae + e35351bcda5aa019839b328106a60e24db7c5de7 + 47864400bc861e6102bdde3900342ee5ac9dfe51 + f7bfb5331e63b5de7826d0fe5abb0a4e9dffa9b4 + 14cf61a6d461a67f569e0f4b99ebd21ce5925566 + 8a250ac80584f8acaf8af9a4a8d3f9f014999a12 + a5731b1360d3a387576903da16ed50f390f00864 + 7c9a3b9f00754bc4da997730e75ddedbcdde5117 + d3879d057ea46050c6286f6653c2bf86fb8938c3 + a03f375f255e325f6a603934e15769044ecb25db + b8ac8d69c3bc16ad657ea2b4a7eace8ea6c60fd8 + 5c02fbca54bd8a035d59145d6d1be0be96f2197c + d43671790be7f5c39af346c8fd00003c135491a2 + 2381abd10331dfea9f5817487cf74923b040f307 + 734168c76e9770dd3f86338570d3e27ce7223251 + 859bf6ee62f7fcb94f052c594d470a61be63f084 + 98b4178ddd01b7959b0a117ccff0688489b8841d + 954de9ea519a33bb4d32ae89f7cae93821e26c02 + f41f1496594933eb8fb6869bff916d330f1c9152 + d523b3606c19e8a0b161008846dac2d30fd92e4c + 3fdf132ad91dcd4f9b466f304d51067baf2ee976 + 3dbde53bdcd43b022ed4575c40fa65ecd67603d0 + cf977d863575f6f74a228a40e357a70a69700189 + 8c1fe8d6c2bc09f548c2059409d53bdeb5fc7d3f + cbfbcedeea1bfc1be031731f0c6de6b0897c84cc + 0124bed97ba6c2970af5bff8ab82acb8affb4611 + 8cba87ed1e345d2312dd341ce7d1810305ccac41 + 6b6c38964701ba72e7838cea1d91c7ef91ec3f08 + 1f371667f596f11b40a46bcebd0ab6a90be2913d + 708f8af393a828613c45eb5e408c0190b4c95622 + d7682ba55ecd3abe1927b9e462fae1b4e9334800 + 459b073f48c2ba332fc39d3f47bd650a04c511ac + bb5d3039b65b985b375ff77e048fa690eca45cf4 + ec3168ae0982393770fee2b55cef963a8c503644 + 0ba5f37dcd6bd6103203fe230d71ffda56502a88 + 80c37d76da053147a5267d03ee94e89d93fcf074 + db4dccc57e290094edb2c9cc9f134b2e3077d22f + ea5981c1f1fb5c214ba0c9e82ec030c2a1bbf0a3 + f92cf79330387d5b51b8efd6300179e1be15ae01 + 38e0eec3af20d607b15a9a21078373a338c1d4ba + 9ee0001d0ee983caa4e1c469cdf77ed51a0ef9f2 + c5a803fc6dd74028f63573e325d87c19001bea8d + 11992d4f3a304d24962223cb14aeb9c67848e027 + d7bb416faf5485896af7d349982a92cdf98e847d + 632add982c1641009bafe85f691f6f21385cd34b + 04bb6d36962f76334e71f90240d528e8a3ad459b + 32ebc900994d00f4eda332631d687edf7982df0b + a302bf465ac38da7429548b80b288c70fe7f9ed4 + ed87a36bfe5abd2bb0b0a4efb5932bfa425f80a0 + f8c448216f59f523bcf33d2d99dc83e8ec7f46e1 + 82f5ffb770451bfd840d816946d9b59884d41b02 + bd8faa855ca9377f46161b9427027ed8400eff3a + f680d78b7854ac0af443b879a880fe3c22cafbd5 + 5d357bb06899857d3e64468d79eef199882cc3d6 + 4be3cae2cd41742f8f33f80c41797a68b1510fb5 + 6d70253e7e22c6a30570d96b6cfb36772b33354f + ede70be18a4db080c3d046c5fd9f0bc6b625a772 + 14c8f1675f97244b14f12d6b32419a19cf814dbc + 0f9943a582d5d514e9deb1253d4806156ad37c17 + c0086d20b74ae26693716ec7bae9b530237d786b + 356fe043c133aab0a922153f9cef068d90bf3f89 + 0d2420bcd3eabc17c319e73cb1c043fa47f8ac92 + 7b9496187417464ac70e4fa7a63a710eea14202a + fcf3ada8b083d0adffc0c5ecce437aaa483d4109 + 0b14dd454a228bf96d9a177fcc65234db93a740b + a7d2ed2809de3e928913a6a3f8efcf1f06f1f3ab + 9752d14b59c1b60ad957de4982d84e0f3a398bcc + bdba58965077db889544e8bb086ddfa8d4394be2 + 93fa8444acd84d0a5580b553b9eec85a354aa4cb + dcdb227911b0bcd0ed6074711eb9ad6f686aef46 + 6cd9e2121fee8d0c0982d9976fc8b5eec99bed7c + e74ef9311f1a084f8d2625369cbd245872e7c7b5 + d042115bc6a339f1bcd58d526c3617cc125311f3 + fb68189e82b480de37bcb09a2e6ac699d7d81533 + aacecb7a31699743342dce7e031818a809a6ef8a + 431b9fe43c294a313042714f99e9a9ae59663992 + fd84701b8a4453d227dffe54761824c4c690f1a4 + a0d69bdc1b1d99b17e42fe9a0e48918344aa4e4e + 3962f2a34b48853aa3885a25c5282640451b8935 + 66f1df2058e6b061623971b3c25f49a35a856f2e + 06531afe357933551835fd816ce915c9737ae8fd + 3642ad5a2bc42db69d495f0b4f506f5059761b94 + 7756a6cf4264d74e727fc84f377d4a7472f91469 + a13af573eadb2998648ea050c65bcdc78e262ada + 9ed650662bf9b8b236934799554d03b0b6ed64d4 + 404d94a3268699510b0dcddbc826bf724dca6658 + 85043d5ae0586b322f97310bc299aa9007101ee8 + 3c39c196c6ba4d90ba316ce3b451bffcc462a9dc + dbf5c2fcd32b32023a1431960ca8eac207b3e8c7 + b2efc9445d6af07aaa64eb736815c1574abfff32 + 9e7443a1d9daa8c5a8e1db98e68fd839b7dec99e + 92317de0fc58deba956a7c4cf23cd87028362826 + 0e53cb81bda4774c3c5ce8898e2a85d56704fdb6 + d4b76a8dae36403ffb6c9bb93a93115c4fd74f18 + cfc7ff0056327d1eb3c401885e49ee514acb5ea4 + 3e47d6f3d4512b56f8a48e028417da53a8f50163 + fdc51eda2dd4f784e086e05efd50756e0e2e93f1 + 62b0642dd3583e46bc4a4a4e946f9f41a85316c5 + 1d699a2de913e0512b3069a56c634952e206f725 + faa1518829eb7b7bafef580bdc7a375ab67df6c9 + 79a2069008732e01fafdc6bfae5c0d4878191cf8 + cfe4b5a6ac9633bb476be67f9ce7326519498f66 + faaba329d20c0fbd04ced467c68b4b466bdf7674 + 22902be8a6d4dcd61f2d5643093c16d91591453b + 2bf01ec12eec43da8c15e0495a27c8e2e7d17975 + d1341a1129f63c66136d661677f34aca91eab3cf + 057e65f31bf494c532d1299368b273abafcbe24f + 1640f880ba910be403d511f39d7d610a2f5aed92 + 4bbff42ed3ba0e6fb23ffc3170e884c1752b7bb9 + 82ec7855cd32e721445c3ec0f2dfae9814faaaa4 + ee6e7a68f2c5b3cb3ade33066182c3fbc49317e6 + 542684dc2cbc3f02ea57a7e21382ecbb0b977c5d + 9ee8f8ba9a51f1a2ffdeaec56b9f790a8246545f + cd0895b0a6f8c32ddf8e1774be61c2a448e113bc + 4871e467373ed699071396b07774a1591d36a421 + 35b5604b108a59988aca58e6f4773b2f4cd5b88a + 9c58cf38b6958c7e7400d19e8c98db2f5a43325d + 00ee7a8491272475e6ece4cca82b7e9c29f740ba + 6f7350658904cc01c8e9a7aab19a44c8c8f1ca4d + 9b640920de57018780e3919b890d17ef09e8ed8c + 17d551e8c57570bff19fd2fb8220bf101f3bc941 + 52e1f2ed6f21611b2efe4d7ef325aa24840470ad + 863df77cbc0c93c5fc589c0e968ff7222cf2d42e + bfc8699fb1f8ee70c74e8914cd76f29ccf5b814f + a0ab0bccc949c52049273865495dd18b0fd11945 + 548a1690e5ffce54983a40f583f968235e480f45 + 4b88cc0e5d7bd519b6abe5f3ebc13b9c1b166506 + 5106ee73a301a0d38eabf0e71cb0fc9866bb8b69 + 032ce62bad50602863ae3f8409ae8b03a44fb017 + c480c521a00374c0691de62fa415e6854ba3400d + 3f63504eb9fc8fe250f7441699508c4c3704153e + 8ea4edef9512aadc4c20dc54488c1569322cba72 + 69c3be28a635b360687e79a7fbc945bab87f7e19 + 072f4d5484893b8b995e19e31b192f414908ce46 + e938a1c8e19fb02d8a59809005327ce91ea1453a + d30fc4f7643cc522965ee3c496d3d7601e73fb08 + 1ee78d5f582629784ecb286c551fcf3b335e74a8 + 54fb2f5699241e407e272d0e79469216d98e6b91 + e7038177e7399d30956ebe5db5f0b5b4946528ff + 68f175645387cf47fc0eed8a973ac4dab2657908 + 0a2f4c4a6abf92231d2c7f9e1dd8011c908fa356 + 741f332adb152ccb781c732755b551dd7c1481f0 + 0cfdbfaa362a5c4d22a1fe7f31375bf57ac7a1ec + 3102a4d3fe18594ffd62696ba07f8ea9321eb222 + 49abbc86515bfa01e86f62f32a44f5663b3b6f27 + e27321dd4d10129f095a0ab8e748898885869ac7 + a4de9b37ffd591118d31be1602d2f20ac434b1fa + 1fa1da65287c26594d76b478e3f5ffb5e80d61c9 + 6a298213a3bd89bfec478b5f265284cba1f09b3b + 79fbd7d3834ab562828062d21dd3788c04c892a0 + 910b55f1f231d98b29ff9c8dbfe51c188f7edcc7 + 0a242b36214a6f44d6c15c7021b649793e779313 + d639b6a1243d8b0536bc0f4c29bf1abb74aa541f + 97ea28452ee779b1d146f02756f632dbca917a8a + 58ca63e6293b38ed450683c0e2d0d778f6ea2fec + 35989c2ef34043069106d0790f483c88dbe5563a + 110cd1527cdd1ac7283f8299a3b57a2b6edf48ef + a2174fa136d4231799369916f9a07d7c8e02ec47 + 952eb637dbeb2e1366747cfa94cc70ee1e8ed493 + 3646a03568c6b81917fa35fb3733d31f96233f3c + 7ff65f933bb17b5e413a892f81cb3f3c8ef6b9c1 + 06a00a18679a4c1524440c022ae4984fef35b937 + f1a6a85df1c1ad73a4d86df3dfe040ad68cdf89a + b2d0c85ebfac8204670291cfe1267a0bd2053ee1 + bc7fda6813272bf14a66aa38490310ecd33db06c + d518fe952e380e96676fa9d62d00ac328c332a5c + fb2c624674936a90916a3d8385325ef92201d317 + c67d2837b586016e4898c830463383860d265adf + dd6d14ec3bba1d23c7234bb4af3e59462170d675 + a771b7fa4312921ff1c2a19d82a90fa77c05f3e6 + 945d62fd50fa90858a0ef8062a45e719dbe6ee60 + 78ba1b8d5aa6964cb9ffc3632e41806a14427d58 + e7dce40ce18becf249f9638c2ba294cd1805478a + 2c7cad45471143608401188c8dcf155ba7a790a9 + bdab487c1d4c977f5a6a0d1cac8f2d12679f6d86 + d73e478a5e1b09047d8e3911948976f559c7e915 + 90a75eaffe4c4c870d3fa541a554a68d61678f67 + 7b040bfb1fea7283b028eb79341fb1f229f6054d + 780282015861b75321929ec63433bad711b66d66 + 22085d54006694927e943f37bf856053f5ce58b0 + 634f46669410fde9a17d53ac19ee5a7d1d04b1a5 + 69dfd663f066f9674a12685116109098354d25f2 + 21fa816492c37c4927d5ea2a1cfc61ff5c2f847e + 14cdeb8dd583856c9935be5a58e33187ccacbc66 + 71b0c9c229b934f78957235be17e9887405a37d5 + 8d744577eaa8d208f4b258197e01c65ed3b7e999 + c4752ddef02d57f8409bb54053259c358f90e327 + 9f13ac8ed18542369833d5e4c9bad59be5f23db1 + a869be8eb4e553fac5ac25e058d343dffbf601af + 56f40091232d071f7a342efeb178aff27c70c29a + 1a4f6184f9e69117990f5483bf05045ee7e17834 + e7ad705497f2f07a91974729ed986e906861ff81 + 8140bcb9ce68579eb83ac751070d7a08057b3e3c + c463b5925b9f27d7f077bdff813cde19d3c2bf09 + 06e20fe2ee579bdd1e2fdef738485afd6d999418 + 91c259e944216ec83ddb541fbf53bbbd518d927f + 8340d1cade0cc8ae45e8136add447649cd470607 + 8241dbbf5ff5cc381d7d6448f2c1348abec45203 + 594b9ab10319109e782cfc0eaabd038a8e744518 + a7ade46fac338fd08ae322f9575ab95768fd4569 + 0146e3deeba63989108d1bcfcf0231c05d8d7a2e + 07d371120735553c7295a9466ee6fe81ff46fe51 + a7c05b98e519af4a86bd20beb6b964c94d48d0af + 9e894b914ab144217181dbca27f955206b3c37b4 + 2205dd2085dada143b64785b1fd86b0d3a765bab + 086cadf056dd73a5209df85f0ad2d3ccf7d14f7b + ae73594385fb7e5195c9c9dffc8b9dd5545a05a0 + 277ab18f0ff09f3a1a0a8d68715f7eb22eaba249 + f6e148ba5488138825b8e2a8ba88f4cf7a24deef + 76743b6a629f09b4cc06e7f871561ee87e518ebb + 7367aff187fdf6e6d4a70f492e0cd907d3a4ff33 + 19ba943536dcb28b3e815c87f8ad9d910948a975 + 1db42e3489d6db0749401769978b04c05cf0f137 + a3c1099e318a4915204318e5de0a4276afe0ef02 + a7a87a47a61b0d93591c94589d39fd079a206ff3 + a4eb1a071e724dca21ad02c912754edfaee1ab00 + 611664ce7faa6e14fb6a167758a53c52dac1084b + 344dc7036a6e2d0ec784d3f60132046d021a24a4 + 02bf376576b2f7ae650e4d2769cb3caf1764a49f + 35b2549570666e6c1cf7c3dbbf70e482c41d714f + e5fbe9e59d967812a34621a9b104968b0c353df4 + 2b8f1ed1d05393b612a433195f3752f874f8308e + 647719776245276d1948c44b37003d0adc8c53ca + 25c8f2a87b48b1e60700764054ce4aa3e5d14c25 + 271744f02f7b00fae63626940cb06e19c75d590e + cc6ed725952f3d39f570868692e86c0941de1c52 + a081512a675ac3fc30bb21862feb2ab6e8094b55 + d46a5d5044f6025a5188c3e6bdbb9f77ed98b1b1 + 891ed91b426b1c415d613128bc3227a350fadfec + dea127f7c5ac058465f1d0264b27659798780498 + a5a7f6e00c529d1272b071ecbf6bbedbbbebf89a + ed61db99d5a7862a643f684e67770921c03400e1 + b719a8c73ba5daee78c4b5f7de7d7c3055547f12 + b6f33ac83b8a1db1db0246e15b6c1ac564db5a5b + c084dc77d693f6d3b3f72f8196cd3583d60545ca + a09e7af08be0e060d48a863d81eef2fc24456369 + fd15cd7451b4df224b3076462cd3532726ed5700 + 36b5a41a18b7cfdcacbcb0def8957dbbbf443df8 + 1b810d454152f6e07bd161e02b40473bc0bd2efa + eb4a3a814b45d248bf3526fa2bf162c72a7d84be + 65c26fe1a5ca80972835cd3546c2e794deae62cd + ddbbf176a6f2a6b0e856e50cc969bf157f4b8706 + 3712dda5fa2838d14b942e2dd43babd8dbd8fb71 + 2bb88a6732a8257da53fb795e4d2a1dabd44948c + 322e7ced7dded5a26b775ed4dd425009c9cacf1a + fe863b60a63f8b844796455dede6206d057b3f7f + e023d908e76518afe0a73a9284691fc51d362673 + 9c4856b53ea1a6137fda6bbe6ba3f29355412c94 + d733e415454ab0737f61ab6545a97aaa34a10981 + b7aa3fe75fba78e3ef7a83657b0deb6cf563751a + d8226fae4f14c31362aaa403f4d6a8b84b89dfc5 + e8a1cfa1e616e1af2a63ab32845ff719ed98c192 + b28f88b4dbe3017d2194b3614321b0e85b1a817e + a4e6762a5454c1623ab580b1cea66e98d47a1207 + dea8eb3fca200ec89e5ade0833a5954abdb3a38d + 84f62cdaa7d95f934e355abf48af32f8b5aa6a92 + 9763c01fd40bd56ebad6adf07a4e00f670508b3a + 35376a957ac89be433fa6a5af47bbb3a803b8439 + 9fbb9ef79f32e2b7e71cab55991ac6838f3cc727 + d7a088da4afedcf3a6b2bf7b6c0405dee40dc0b1 + c2a87610d343c57b3685843b722ea6839c2482c2 + 6698ac8c767847f828b3027930b3840c6c298da9 + 67f27e3c2aa7dab996b38f0b020e9e3a1ddc1a7a + 5aa3383d759f101865c58ae95a7d28cb4bd90912 + ea7bb4593fa94b3731ffcc0471f23e79487d90be + 587d61a2389f0229988dfa3ba6356d34777f7ad7 + 96067e7f71d24311460e6faa73f43af14e1bd09c + b4ad2b6d784fb0455e0e3ffaf77ec6a5d3835be4 + 3c4a0493d869fb12d84fc84efbdf99d721e32795 + 7ebfd1a18b889c0ead28671811c3bc912accee7b + d279daafeba573f7ecff882f696733eeef1081e2 + ca359bb82bf59c190ba4ec30e4f79e61cedf6216 + 213d1d15b0fdd65965916bae093710822c2f7434 + 20dff502ccf9b1dfae7f8c0b118382fa7c3198ac + 4e0405347af59ede2c53c4c1a527ac46595829c5 + 127a4491a7c2310495b68127e9c6570b66600820 + 494ad84de129e62b21bba071d8051a6238a51a5a + f09c50833a58feb41e33cab11e41df1de8eeedcc + 30a03fe42d2f7336b0ed8648a0db70b1462cb76b + 017b17715d7c6a37e4839dbfd9f6498b3b17826c + a4720889b0785c30cc5b9ae56f404a55170d682a + 5c78a48362ff5a2e28124c9901ac7ef2497fd30a + 39e371cf264039216d190a3b7973f6ea9d745775 + 6894cd074f39c624be1f0efc4a4b273c1a579bd6 + 50c637cb403c92e3f6784162069d2604f1225725 + 128d969bbb6da6a34e838e3d95d68ec5dd294867 + 2114cf6fb464efa725f7fa5b8cfc1caa80e28672 + ca7d1683820bae83b8690f38e5aaf9e1d636abe2 + 3257813fc3444c2e606b7f9969bbf315dd63fa90 + 1597f152441f6b0a3ebdccfe0c8350e2242616d2 + 35a4b71263aeab8206ba33e23c77696cd36b4518 + f6334b906ac6f4e068ca73b39fee2e7b25bf7981 + 8e91d3f29603675132f56aec4fe7ef6d6a63fca4 + 59df53686a09f36836696d627f26f684bc82afd0 + b5fdd020ab89b9eef96fedd11924eab2f33fe1ac + a10410318a1572e3db0cb85b8535493cfe023016 + 51124ed652ab51c6f9562e687b70c89ae504529d + cf873592a2b70ec6033e1165fd67a321003464b9 + d4315f51b5ddc3ec94a0183674dca9a400be10cc + dc2f46596ab80be510e874b19702478a04f4e5c3 + 5b49e74cf77ce61c433a1144e214c3f88910962d + 3ac5906a9f85304d580b71cd9327fd61edeffa44 + 81e74202fd189c83953fab52df68951d8169c459 + bc472cf7d207b3f2c8b5ece2409185091c4fb98a + 278be38283d7cfc425f8d2d3ff878d092d9abc20 + 8c59a07a0f16d2c73b18cf9c094a217ac7549b0f + 717c55da1fa0210d630fd39d903cc9e8d1f819dd + 724c8b2141b7be2ad5d8fe35f90db84e634f3caf + e35c251905928e7cdecab7d5335420866e282099 + e9f39bf25ab70cde0ee6dc97803566fa72ab88f8 + 07e733a23c110efd3f61d00d2bf9a932e5b17b3b + f8c9efd365ea8e16a6bb7960dbf2e8923b6daf38 + 0630f187f5d846a3afaf517d2ffeeb90d48c5af4 + 46d00fc1685b39e7a46899416ff11f793e49c722 + 444b3637266774f24ea0757b29e9f4ba0de3057e + fc726962d0b4f888edab8d6088529b3ae4784d28 + 98a01edc5b8d0f543df51f98b9eb55a755ebe364 + 05aa7ad756232555f12ef6bb8fa8356bffbd435f + d6afccb033d4708a3dccde50bf12183072baf439 + a26c492ac46ccaefe9dc5c7c9400aec8d796e261 + ad068476ecd3b0483b1e15dcbf874286e02707b3 + d3a1206d02257a61dc3afc496d6485c4fec7638a + fe449f8645437f64f33b1f1ca8f0a099cdef3a0f + fd07b0f9ca72b8a0b1ee2b6f919a27caf613fbfd + 3a1a5eed724e229a45512ace76fc2c4cdb4aad2d + 1e018eb2b2c3c53c9a51d8ec518d051113ec6529 + 564393b0a9363665c7362f0a5ac71316f4a9265e + 17a78772871dc7e7e5c978f91f97a9b0660f40ac + 80b40c9929082efca003180e089bbfe5f8082d2e + 0944557d7186e1316b470f41e268b5c4a30ed206 + 944691065bdffa40bf18cfa3da7cbc2f5356ff08 + f85307e1e85f3769ebaf8731b3fbc3400fc08108 + af7354a57bb251dd4bcc0c07cb77993243be5e87 + eff8227e4995441276416cca50fd14fef2ba428c + ec673322ba6bad3b270b19d3ceb05305a6d6af45 + dd59aec11fc5b728aff4998e12f53a1112cfbc31 + 252086811d30ceb5badcaaa69c4cb32e7303b7d2 + 0e00907a75b843cd935ef6a451b3c82af49e3008 + 2a4a79d2c884543a3ba2a73afa47eb9f0bd29698 + 9aa7bafb92bd0e1fa42ca81b34828291174cfa45 + 50a700806286465c356dc6a5aa9d77646be2371f + 0d5c84f521e82a262bc5ad047798096be0ad8217 + f9009d3620cb8bf7e644cb35868b26b1f9f72e93 + 22174bf7c7f885afaced65e3af0453917aecb803 + b4492302cc57880ca4c32471fb531b1ca41eb2a1 + bc9a39507de82e1190121b248e032384d998cac7 + 08aabd9ac83078444ac22dc9dc0936c8455ec6aa + 045c55a19bf74a4c09cc350d912287505f49bcc6 + 57cd4adf110b641b0872349a1905853ce7c3be6f + 73fd179fd5237c71f0d69ebcaaeefddcc7372034 + 02a1892f86b351e7d25c86de00f1976fe4c36726 + b4520a04516e18d6484cbb97d494dc301ac4150a + 5b1ec54158bc5fd716dee1175a5b7a69c4f67f97 + 2508fb878c117c6eaf1adb44f047463d8302bc27 + 1de3dbd76c42457a59daea2ef4f9bfee2677cf08 + 9fc5feaa0027b690edd68f9e184388d586ae3405 + 1fa4c67e95d7a6ac3c626c744e703bcc858968f8 + 138631842aeda8e493affbfb915acf75ea0d1b4b + 300ae5f1277a0374ed60996a6cd166f8ce19cc19 + 4a9578fb889bd57ac08f383c501887c6f6cdaacb + ca33f2402ae60e2ca34a082cb2ff57b251fae0b9 + 797e7fffb8ba0b568c2b32947bd27459e581b931 + e7dd92f6b9fcb9cf6e8a7aababb4fd8d5286438f + 0d86c365f6789a0ed89663c9b4ce2baafe631198 + d13836d6d14856c6322e7a02688191f8e403a003 + f76040312df1f9bffffee5da1f3760bbb078a9d5 + 4c292b1cf4f0d198c7a0c62feaec65a7209af089 + 5705d5b44a8475dc9e930e25c9131860282eacce + 7900c7881264321732e18f13318af526f19a8302 + 652da028e5240027a861cd0089652c9a9dd47735 + 0799bdab13d97e3acac01947e581260d1ff96dcc + 06e826c833a096daa1c4c209f09b8a1bb1bf0e88 + 3f87b9557090c2ad7bb155e5ac2a35d242831f9f + 5c2d2fc46f2b4867843780a9925d90231b80ad2e + 57b5897d995a27a65a80e0a63f0625f6a752c081 + 6dd50b9ba1a288cf2e7765e5dcc5bfd80ba8c92a + 2a35d531b30f15cbf91bcdbb6eb715f1656e5a0a + 69f3e10e839bbe57a61afabbe32f4c7e125e3874 + + + + + + + + + + + + + + http://ftp4.gwdg.de/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp3.gwdg.de/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-kassel.de/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.tu-chemnitz.de/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.rz.uni-wuerzburg.de/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://vesta.informatik.rwth-aachen.de/ftp/pub/comp/Linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-erlangen.de/pub/mirrors/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.halifax.rwth-aachen.de/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-ulm.de/mirrors/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-kl.de/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://widehat.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp5.gwdg.de/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.intergenia.de/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://download.uni-hd.de/ftp/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-bayreuth.de/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.uni-leipzig.de/pub/ftp.opensuse.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.hosteurope.de/mirror/ftp.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-siegen.de/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + + + http://ftp2.nluug.nl/os/Linux/distr/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.sunet.se/pub/Linux/distributions/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.uib.no/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.cc.uoc.gr/mirrors/linux/opensuse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.gui.uva.es/sites/opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.mirrors.proxad.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.gts.lug.ro/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.klid.dk/ftp/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.tugraz.at/mirror/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.sh.cvut.cz/MIRRORS/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.switch.ch/ftp/mirror/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + ftp://ftp.pbone.net/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.isr.ist.utl.pt/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.linux.cz/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.karneval.cz/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.se.eu.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.belnet.be/mirror/ftp.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://anorien.csc.warwick.ac.uk/mirrors/download.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.ovh.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.kreksi.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.leaseweb.com/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.inode.at/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://fr2.rpmfind.net/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.icm.edu.pl/pub/Linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.lagis.at/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + ftp://ftp.man.szczecin.pl/pub/Linux/opensuse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://gd.tuwien.ac.at/opsys/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.nl.eu.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.ynet.sk/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.fsn.hu/pub/linux/distributions/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.funet.fi/pub/mirrors/ftp.opensuse.com/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://www.mirrorservice.org/sites/download.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.mirror.garr.it/mirrors/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.ines.lug.ro/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.esat.net/mirrors/ftp.opensuse.org/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uninett.no/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.bifi.unizar.es/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.heanet.ie/mirrors/ftp.opensuse.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.ntua.gr/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp1.nluug.nl/os/Linux/distr/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.roedu.net/mirrors/opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.novell.hu/pub/mirrors/ftp.opensuse.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.hro.nl/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.estpak.ee/pub/suse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + + + http://mirrors.isu.net.sa/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.umoss.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://fundawang.lcuc.org.cn/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.mirror.aussiehq.net.au/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.riken.jp/Linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.kddilabs.jp/Linux/packages/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.novell.co.jp/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.fcaglp.unlp.edu.ar/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.jaist.ac.jp/pub/Linux/openSUSE/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.cs.utah.edu/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors2.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.its.dal.ca/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.kaist.ac.kr/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.xmission.com/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.idrepo.or.id/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.anl.gov/pub/opensuse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.mirrors.tds.net/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.osuosl.org/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://www.muug.mb.ca/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.rackspace.com/openSUSE/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors1.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://www.gtlib.gatech.edu/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.utexas.edu/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.ussg.iu.edu/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.nyi.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://130.57.19.201/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://distro.ibiblio.org/pub/linux/distributions/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.rit.edu/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.chg.ru/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.nux.ipb.pt/pub/dists/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.internode.on.net/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + + diff --git a/tests/media/data/openSUSE-11.3-NET-i586.iso.metalink b/tests/media/data/openSUSE-11.3-NET-i586.iso.metalink new file mode 100644 index 0000000..a2c1e13 --- /dev/null +++ b/tests/media/data/openSUSE-11.3-NET-i586.iso.metalink @@ -0,0 +1,607 @@ + + + + + openSUSE + http://download.opensuse.org + + + + + 120285184 + + + + + + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBMNZQUqE7a6JyACsoRAlr2AJ9o5fkD0DZ2MpyWC0S9EI6c7BXuPQCd +ElMAtuZlO5NgYvG2bQ8xys5iWss= +=WmmH +-----END PGP SIGNATURE----- + + a0dc5f5132b0a26218f533d837d4fc1a + c7827b5a8e62d3971524ba0c438e9574e892103a + 7db356f5e21547e423da0406b7ea36e3c6e4ee62975015294585593d3a2a88c8 + + c5bc4f75f550e44491273720086bf1692c526cbd + bbe1177d325d1310868d34e2350666f9cb119e94 + 2a167f3a34a9a09577365b1015ca23b823f0a80d + 48d2ba5258254dcd4e49140ac7857c9fdb38ab60 + bde60d0206ac5a0198e898553b665f9d9c60babb + 41437180a223068413028fd977ef4ea033bfbfce + 81b7da73641a5e3391210bc9e3de1568a5208836 + 6f9c2895ec0a887fe2dabd521e40918244da0059 + 8bc4a733263a01658a7c58a53fb777b4c8b4ff28 + ed21674a98ba5af37df44fe4ad0e140c82ac8d1e + 3772fed4a8bacd4e20478375c9dc8784f9fef98f + 62f0024c67ff6830a3355b9145f043c4d60b2f13 + d9ac81f6753d14912ec643ad8e2982bd1e128c95 + 4f5369273b928b9aaee69736140b814ee9a228d7 + d6b8bcaf68d07591774302417a3d2b4ee0948e60 + c2a98d8a80ada0b7ecdf214ab6bd3331793cb120 + d0725a3e8f0053cb76c1e4424cb2496092063836 + 50d34d802241b3b52937364a14d369f2644ea4f4 + 553ba2491229a1ccfd23d01e00df4d95e612d442 + 2943c0b02f824925e9b589bf3129f950c1e48e5d + 5d4f21b818057eb23d9aa0e27e8fa5be4c1f3594 + 9630c21e84b85e27f9ee19e59ce1a633621a0b1b + ca3c553ec4b1310c1526b684d14c85640329cd1e + 55bbc2e9d0a627b7481639f4d909118f6b811fc3 + 7843b05f31d95adac6f781f0de8e8af868490a76 + 479d93353bceea8744c7f1b4eac97b277e29ba30 + 28db10a11cf7fc317510230237b76df0dd0dc35c + 128a62f1599591f9d7db1ce53d551a00555af265 + 582ff34a81fe4b3da54defa2b890946f1fce1646 + 03855419b291564e13510d81083d79816179e4f0 + 0e5a6eb83c9f358f4bb1e092f9a3bcef95dd0a41 + f3e6e901bd37e3ec8d405a96128cc85bff450a83 + dee45f794ec0fb5fb5a20826ba2d8d191a567733 + 390c6d1eaf5a28f93d7e8237e3972b9e93fe5cca + 20336a02716605b12e6fafd18855cbae411a09eb + ef22857c452d0043adbc054dd4396c0838426ae2 + 574c3a9f656391757acb83fb5091dabeb78e2418 + 203e818753a68b0bea326ea1428972a92036d9d8 + 5b49222d21afb87a5de922e9c77ca255619d21ad + fdd7b232c5ba5fa75c30f0e628e506725869df25 + 360bb3a824926cb73357b7c587390867e944b28c + c0f194a68b2c1d8693a83ef162ad85f8c0bf93cd + 25079830fe5d0c64d5c8f65c6beb61f2832995c8 + fe5b97a5c807c66833a2f5c45a7c511299c8e7c5 + 64f287d9fc0c64c68c9b9f61711080b4072b11bc + fbd01b40db0d0d73c4346bfa6942cd23666d08d8 + e73a60b7a8efde3d70da2935d85c3ebd6b623651 + 414299b4a2da9b50700d2d7d7721139291acd2b7 + e2c03eac8cbd4ef1a1fde5b60c32f26c6760a32b + a44b4d98688b7dd787ee2c3029229ca3083b2633 + 635ab22c1507403e3ba9481b92c7637ebd58bb2e + bddcde253a718b50ab3e2517cc33938ce54baab4 + bed44cc3cacd658389c4807edead76e71329dea9 + efe42d31f00ced3aea5a9aef9a3820ec20ba9e73 + d1b1f83099c80c9219386b38063588a94385ef5a + 670abebd7cd7a0a62d4aeba3dee78c7512d2ea8c + f483d9fbe3d513be20aef6e8736c5755c9aea29e + 46b4ce6520798c362a16ac3e293cbf94f979603a + 8b5e93ad34582431b3efb89ec10e05ff4257c166 + 06e09067668ff5b9ebda474a71db44c9b8386eee + 395843d5243a235c7803bba79eca803bb9c5c5a7 + 0a2cc9fe1a1a4591110f7235b1b9ca9eb4e59ec7 + fe5ef70a92427bbded4cadcd74f648b7e33807c2 + c743ddce2e930bcdf76db2f08f5a959f6f3cecd9 + d5788b2dca4a6cb5d75cce8316db1e761c914da5 + cf5c83859f55714544e42645db270d237b6d4499 + 497214fef565cfa04c2b8f96704be999b93df93f + 2f4c7da4c7d25e6d8d63a995f5296c8295bc8d01 + 95550875564701777b6e6e02854865c991a121b6 + c378b72cdc37c83d4f713e55915863babf949ba3 + d67e326f31fcb79000e96b3032c1e16183e79d84 + 53b0067cc0e8eb9b856a11af29cf69ededfe4bfd + ebf37f7028112f669d244d55ae0290c003cc9cff + 56e6482f5e0162ee16ee77496e583c9a0d5b0b31 + 772fb29f60ecd14b3c06a317258e86b6802a1310 + b43a919ce9eae4c3f1b18f5d3f61328a9f67d885 + cd93972f4cab7128bfefe836ac5601b2cced8a42 + fe20173622a73d64f586f9594551bd5fe56ef690 + 2f22b34a49fef60f54f8f59789a439bc5232e0ab + cc1e04c724746e6058429c0610dafd639798bfab + 95ba6eba3b22e6b473f7946c8c7aa66da6547ae7 + 2b7e254485c22686e0408ce76fa6b267aadf35ae + e35351bcda5aa019839b328106a60e24db7c5de7 + 47864400bc861e6102bdde3900342ee5ac9dfe51 + f7bfb5331e63b5de7826d0fe5abb0a4e9dffa9b4 + 14cf61a6d461a67f569e0f4b99ebd21ce5925566 + 8a250ac80584f8acaf8af9a4a8d3f9f014999a12 + a5731b1360d3a387576903da16ed50f390f00864 + 7c9a3b9f00754bc4da997730e75ddedbcdde5117 + d3879d057ea46050c6286f6653c2bf86fb8938c3 + a03f375f255e325f6a603934e15769044ecb25db + b8ac8d69c3bc16ad657ea2b4a7eace8ea6c60fd8 + 5c02fbca54bd8a035d59145d6d1be0be96f2197c + d43671790be7f5c39af346c8fd00003c135491a2 + 2381abd10331dfea9f5817487cf74923b040f307 + 734168c76e9770dd3f86338570d3e27ce7223251 + 859bf6ee62f7fcb94f052c594d470a61be63f084 + 98b4178ddd01b7959b0a117ccff0688489b8841d + 954de9ea519a33bb4d32ae89f7cae93821e26c02 + f41f1496594933eb8fb6869bff916d330f1c9152 + d523b3606c19e8a0b161008846dac2d30fd92e4c + 3fdf132ad91dcd4f9b466f304d51067baf2ee976 + 3dbde53bdcd43b022ed4575c40fa65ecd67603d0 + cf977d863575f6f74a228a40e357a70a69700189 + 8c1fe8d6c2bc09f548c2059409d53bdeb5fc7d3f + cbfbcedeea1bfc1be031731f0c6de6b0897c84cc + 0124bed97ba6c2970af5bff8ab82acb8affb4611 + 8cba87ed1e345d2312dd341ce7d1810305ccac41 + 6b6c38964701ba72e7838cea1d91c7ef91ec3f08 + 1f371667f596f11b40a46bcebd0ab6a90be2913d + 708f8af393a828613c45eb5e408c0190b4c95622 + d7682ba55ecd3abe1927b9e462fae1b4e9334800 + 459b073f48c2ba332fc39d3f47bd650a04c511ac + bb5d3039b65b985b375ff77e048fa690eca45cf4 + ec3168ae0982393770fee2b55cef963a8c503644 + 0ba5f37dcd6bd6103203fe230d71ffda56502a88 + 80c37d76da053147a5267d03ee94e89d93fcf074 + db4dccc57e290094edb2c9cc9f134b2e3077d22f + ea5981c1f1fb5c214ba0c9e82ec030c2a1bbf0a3 + f92cf79330387d5b51b8efd6300179e1be15ae01 + 38e0eec3af20d607b15a9a21078373a338c1d4ba + 9ee0001d0ee983caa4e1c469cdf77ed51a0ef9f2 + c5a803fc6dd74028f63573e325d87c19001bea8d + 11992d4f3a304d24962223cb14aeb9c67848e027 + d7bb416faf5485896af7d349982a92cdf98e847d + 632add982c1641009bafe85f691f6f21385cd34b + 04bb6d36962f76334e71f90240d528e8a3ad459b + 32ebc900994d00f4eda332631d687edf7982df0b + a302bf465ac38da7429548b80b288c70fe7f9ed4 + ed87a36bfe5abd2bb0b0a4efb5932bfa425f80a0 + f8c448216f59f523bcf33d2d99dc83e8ec7f46e1 + 82f5ffb770451bfd840d816946d9b59884d41b02 + bd8faa855ca9377f46161b9427027ed8400eff3a + f680d78b7854ac0af443b879a880fe3c22cafbd5 + 5d357bb06899857d3e64468d79eef199882cc3d6 + 4be3cae2cd41742f8f33f80c41797a68b1510fb5 + 6d70253e7e22c6a30570d96b6cfb36772b33354f + ede70be18a4db080c3d046c5fd9f0bc6b625a772 + 14c8f1675f97244b14f12d6b32419a19cf814dbc + 0f9943a582d5d514e9deb1253d4806156ad37c17 + c0086d20b74ae26693716ec7bae9b530237d786b + 356fe043c133aab0a922153f9cef068d90bf3f89 + 0d2420bcd3eabc17c319e73cb1c043fa47f8ac92 + 7b9496187417464ac70e4fa7a63a710eea14202a + fcf3ada8b083d0adffc0c5ecce437aaa483d4109 + 0b14dd454a228bf96d9a177fcc65234db93a740b + a7d2ed2809de3e928913a6a3f8efcf1f06f1f3ab + 9752d14b59c1b60ad957de4982d84e0f3a398bcc + bdba58965077db889544e8bb086ddfa8d4394be2 + 93fa8444acd84d0a5580b553b9eec85a354aa4cb + dcdb227911b0bcd0ed6074711eb9ad6f686aef46 + 6cd9e2121fee8d0c0982d9976fc8b5eec99bed7c + e74ef9311f1a084f8d2625369cbd245872e7c7b5 + d042115bc6a339f1bcd58d526c3617cc125311f3 + fb68189e82b480de37bcb09a2e6ac699d7d81533 + aacecb7a31699743342dce7e031818a809a6ef8a + 431b9fe43c294a313042714f99e9a9ae59663992 + fd84701b8a4453d227dffe54761824c4c690f1a4 + a0d69bdc1b1d99b17e42fe9a0e48918344aa4e4e + 3962f2a34b48853aa3885a25c5282640451b8935 + 66f1df2058e6b061623971b3c25f49a35a856f2e + 06531afe357933551835fd816ce915c9737ae8fd + 3642ad5a2bc42db69d495f0b4f506f5059761b94 + 7756a6cf4264d74e727fc84f377d4a7472f91469 + a13af573eadb2998648ea050c65bcdc78e262ada + 9ed650662bf9b8b236934799554d03b0b6ed64d4 + 404d94a3268699510b0dcddbc826bf724dca6658 + 85043d5ae0586b322f97310bc299aa9007101ee8 + 3c39c196c6ba4d90ba316ce3b451bffcc462a9dc + dbf5c2fcd32b32023a1431960ca8eac207b3e8c7 + b2efc9445d6af07aaa64eb736815c1574abfff32 + 9e7443a1d9daa8c5a8e1db98e68fd839b7dec99e + 92317de0fc58deba956a7c4cf23cd87028362826 + 0e53cb81bda4774c3c5ce8898e2a85d56704fdb6 + d4b76a8dae36403ffb6c9bb93a93115c4fd74f18 + cfc7ff0056327d1eb3c401885e49ee514acb5ea4 + 3e47d6f3d4512b56f8a48e028417da53a8f50163 + fdc51eda2dd4f784e086e05efd50756e0e2e93f1 + 62b0642dd3583e46bc4a4a4e946f9f41a85316c5 + 1d699a2de913e0512b3069a56c634952e206f725 + faa1518829eb7b7bafef580bdc7a375ab67df6c9 + 79a2069008732e01fafdc6bfae5c0d4878191cf8 + cfe4b5a6ac9633bb476be67f9ce7326519498f66 + faaba329d20c0fbd04ced467c68b4b466bdf7674 + 22902be8a6d4dcd61f2d5643093c16d91591453b + 2bf01ec12eec43da8c15e0495a27c8e2e7d17975 + d1341a1129f63c66136d661677f34aca91eab3cf + 057e65f31bf494c532d1299368b273abafcbe24f + 1640f880ba910be403d511f39d7d610a2f5aed92 + 4bbff42ed3ba0e6fb23ffc3170e884c1752b7bb9 + 82ec7855cd32e721445c3ec0f2dfae9814faaaa4 + ee6e7a68f2c5b3cb3ade33066182c3fbc49317e6 + 542684dc2cbc3f02ea57a7e21382ecbb0b977c5d + 9ee8f8ba9a51f1a2ffdeaec56b9f790a8246545f + cd0895b0a6f8c32ddf8e1774be61c2a448e113bc + 4871e467373ed699071396b07774a1591d36a421 + 35b5604b108a59988aca58e6f4773b2f4cd5b88a + 9c58cf38b6958c7e7400d19e8c98db2f5a43325d + 00ee7a8491272475e6ece4cca82b7e9c29f740ba + 6f7350658904cc01c8e9a7aab19a44c8c8f1ca4d + 9b640920de57018780e3919b890d17ef09e8ed8c + 17d551e8c57570bff19fd2fb8220bf101f3bc941 + 52e1f2ed6f21611b2efe4d7ef325aa24840470ad + 863df77cbc0c93c5fc589c0e968ff7222cf2d42e + bfc8699fb1f8ee70c74e8914cd76f29ccf5b814f + a0ab0bccc949c52049273865495dd18b0fd11945 + 548a1690e5ffce54983a40f583f968235e480f45 + 4b88cc0e5d7bd519b6abe5f3ebc13b9c1b166506 + 5106ee73a301a0d38eabf0e71cb0fc9866bb8b69 + 032ce62bad50602863ae3f8409ae8b03a44fb017 + c480c521a00374c0691de62fa415e6854ba3400d + 3f63504eb9fc8fe250f7441699508c4c3704153e + 8ea4edef9512aadc4c20dc54488c1569322cba72 + 69c3be28a635b360687e79a7fbc945bab87f7e19 + 072f4d5484893b8b995e19e31b192f414908ce46 + e938a1c8e19fb02d8a59809005327ce91ea1453a + d30fc4f7643cc522965ee3c496d3d7601e73fb08 + 1ee78d5f582629784ecb286c551fcf3b335e74a8 + 54fb2f5699241e407e272d0e79469216d98e6b91 + e7038177e7399d30956ebe5db5f0b5b4946528ff + 68f175645387cf47fc0eed8a973ac4dab2657908 + 0a2f4c4a6abf92231d2c7f9e1dd8011c908fa356 + 741f332adb152ccb781c732755b551dd7c1481f0 + 0cfdbfaa362a5c4d22a1fe7f31375bf57ac7a1ec + 3102a4d3fe18594ffd62696ba07f8ea9321eb222 + 49abbc86515bfa01e86f62f32a44f5663b3b6f27 + e27321dd4d10129f095a0ab8e748898885869ac7 + a4de9b37ffd591118d31be1602d2f20ac434b1fa + 1fa1da65287c26594d76b478e3f5ffb5e80d61c9 + 6a298213a3bd89bfec478b5f265284cba1f09b3b + 79fbd7d3834ab562828062d21dd3788c04c892a0 + 910b55f1f231d98b29ff9c8dbfe51c188f7edcc7 + 0a242b36214a6f44d6c15c7021b649793e779313 + d639b6a1243d8b0536bc0f4c29bf1abb74aa541f + 97ea28452ee779b1d146f02756f632dbca917a8a + 58ca63e6293b38ed450683c0e2d0d778f6ea2fec + 35989c2ef34043069106d0790f483c88dbe5563a + 110cd1527cdd1ac7283f8299a3b57a2b6edf48ef + a2174fa136d4231799369916f9a07d7c8e02ec47 + 952eb637dbeb2e1366747cfa94cc70ee1e8ed493 + 3646a03568c6b81917fa35fb3733d31f96233f3c + 7ff65f933bb17b5e413a892f81cb3f3c8ef6b9c1 + 06a00a18679a4c1524440c022ae4984fef35b937 + f1a6a85df1c1ad73a4d86df3dfe040ad68cdf89a + b2d0c85ebfac8204670291cfe1267a0bd2053ee1 + bc7fda6813272bf14a66aa38490310ecd33db06c + d518fe952e380e96676fa9d62d00ac328c332a5c + fb2c624674936a90916a3d8385325ef92201d317 + c67d2837b586016e4898c830463383860d265adf + dd6d14ec3bba1d23c7234bb4af3e59462170d675 + a771b7fa4312921ff1c2a19d82a90fa77c05f3e6 + 945d62fd50fa90858a0ef8062a45e719dbe6ee60 + 78ba1b8d5aa6964cb9ffc3632e41806a14427d58 + e7dce40ce18becf249f9638c2ba294cd1805478a + 2c7cad45471143608401188c8dcf155ba7a790a9 + bdab487c1d4c977f5a6a0d1cac8f2d12679f6d86 + d73e478a5e1b09047d8e3911948976f559c7e915 + 90a75eaffe4c4c870d3fa541a554a68d61678f67 + 7b040bfb1fea7283b028eb79341fb1f229f6054d + 780282015861b75321929ec63433bad711b66d66 + 22085d54006694927e943f37bf856053f5ce58b0 + 634f46669410fde9a17d53ac19ee5a7d1d04b1a5 + 69dfd663f066f9674a12685116109098354d25f2 + 21fa816492c37c4927d5ea2a1cfc61ff5c2f847e + 14cdeb8dd583856c9935be5a58e33187ccacbc66 + 71b0c9c229b934f78957235be17e9887405a37d5 + 8d744577eaa8d208f4b258197e01c65ed3b7e999 + c4752ddef02d57f8409bb54053259c358f90e327 + 9f13ac8ed18542369833d5e4c9bad59be5f23db1 + a869be8eb4e553fac5ac25e058d343dffbf601af + 56f40091232d071f7a342efeb178aff27c70c29a + 1a4f6184f9e69117990f5483bf05045ee7e17834 + e7ad705497f2f07a91974729ed986e906861ff81 + 8140bcb9ce68579eb83ac751070d7a08057b3e3c + c463b5925b9f27d7f077bdff813cde19d3c2bf09 + 06e20fe2ee579bdd1e2fdef738485afd6d999418 + 91c259e944216ec83ddb541fbf53bbbd518d927f + 8340d1cade0cc8ae45e8136add447649cd470607 + 8241dbbf5ff5cc381d7d6448f2c1348abec45203 + 594b9ab10319109e782cfc0eaabd038a8e744518 + a7ade46fac338fd08ae322f9575ab95768fd4569 + 0146e3deeba63989108d1bcfcf0231c05d8d7a2e + 07d371120735553c7295a9466ee6fe81ff46fe51 + a7c05b98e519af4a86bd20beb6b964c94d48d0af + 9e894b914ab144217181dbca27f955206b3c37b4 + 2205dd2085dada143b64785b1fd86b0d3a765bab + 086cadf056dd73a5209df85f0ad2d3ccf7d14f7b + ae73594385fb7e5195c9c9dffc8b9dd5545a05a0 + 277ab18f0ff09f3a1a0a8d68715f7eb22eaba249 + f6e148ba5488138825b8e2a8ba88f4cf7a24deef + 76743b6a629f09b4cc06e7f871561ee87e518ebb + 7367aff187fdf6e6d4a70f492e0cd907d3a4ff33 + 19ba943536dcb28b3e815c87f8ad9d910948a975 + 1db42e3489d6db0749401769978b04c05cf0f137 + a3c1099e318a4915204318e5de0a4276afe0ef02 + a7a87a47a61b0d93591c94589d39fd079a206ff3 + a4eb1a071e724dca21ad02c912754edfaee1ab00 + 611664ce7faa6e14fb6a167758a53c52dac1084b + 344dc7036a6e2d0ec784d3f60132046d021a24a4 + 02bf376576b2f7ae650e4d2769cb3caf1764a49f + 35b2549570666e6c1cf7c3dbbf70e482c41d714f + e5fbe9e59d967812a34621a9b104968b0c353df4 + 2b8f1ed1d05393b612a433195f3752f874f8308e + 647719776245276d1948c44b37003d0adc8c53ca + 25c8f2a87b48b1e60700764054ce4aa3e5d14c25 + 271744f02f7b00fae63626940cb06e19c75d590e + cc6ed725952f3d39f570868692e86c0941de1c52 + a081512a675ac3fc30bb21862feb2ab6e8094b55 + d46a5d5044f6025a5188c3e6bdbb9f77ed98b1b1 + 891ed91b426b1c415d613128bc3227a350fadfec + dea127f7c5ac058465f1d0264b27659798780498 + a5a7f6e00c529d1272b071ecbf6bbedbbbebf89a + ed61db99d5a7862a643f684e67770921c03400e1 + b719a8c73ba5daee78c4b5f7de7d7c3055547f12 + b6f33ac83b8a1db1db0246e15b6c1ac564db5a5b + c084dc77d693f6d3b3f72f8196cd3583d60545ca + a09e7af08be0e060d48a863d81eef2fc24456369 + fd15cd7451b4df224b3076462cd3532726ed5700 + 36b5a41a18b7cfdcacbcb0def8957dbbbf443df8 + 1b810d454152f6e07bd161e02b40473bc0bd2efa + eb4a3a814b45d248bf3526fa2bf162c72a7d84be + 65c26fe1a5ca80972835cd3546c2e794deae62cd + ddbbf176a6f2a6b0e856e50cc969bf157f4b8706 + 3712dda5fa2838d14b942e2dd43babd8dbd8fb71 + 2bb88a6732a8257da53fb795e4d2a1dabd44948c + 322e7ced7dded5a26b775ed4dd425009c9cacf1a + fe863b60a63f8b844796455dede6206d057b3f7f + e023d908e76518afe0a73a9284691fc51d362673 + 9c4856b53ea1a6137fda6bbe6ba3f29355412c94 + d733e415454ab0737f61ab6545a97aaa34a10981 + b7aa3fe75fba78e3ef7a83657b0deb6cf563751a + d8226fae4f14c31362aaa403f4d6a8b84b89dfc5 + e8a1cfa1e616e1af2a63ab32845ff719ed98c192 + b28f88b4dbe3017d2194b3614321b0e85b1a817e + a4e6762a5454c1623ab580b1cea66e98d47a1207 + dea8eb3fca200ec89e5ade0833a5954abdb3a38d + 84f62cdaa7d95f934e355abf48af32f8b5aa6a92 + 9763c01fd40bd56ebad6adf07a4e00f670508b3a + 35376a957ac89be433fa6a5af47bbb3a803b8439 + 9fbb9ef79f32e2b7e71cab55991ac6838f3cc727 + d7a088da4afedcf3a6b2bf7b6c0405dee40dc0b1 + c2a87610d343c57b3685843b722ea6839c2482c2 + 6698ac8c767847f828b3027930b3840c6c298da9 + 67f27e3c2aa7dab996b38f0b020e9e3a1ddc1a7a + 5aa3383d759f101865c58ae95a7d28cb4bd90912 + ea7bb4593fa94b3731ffcc0471f23e79487d90be + 587d61a2389f0229988dfa3ba6356d34777f7ad7 + 96067e7f71d24311460e6faa73f43af14e1bd09c + b4ad2b6d784fb0455e0e3ffaf77ec6a5d3835be4 + 3c4a0493d869fb12d84fc84efbdf99d721e32795 + 7ebfd1a18b889c0ead28671811c3bc912accee7b + d279daafeba573f7ecff882f696733eeef1081e2 + ca359bb82bf59c190ba4ec30e4f79e61cedf6216 + 213d1d15b0fdd65965916bae093710822c2f7434 + 20dff502ccf9b1dfae7f8c0b118382fa7c3198ac + 4e0405347af59ede2c53c4c1a527ac46595829c5 + 127a4491a7c2310495b68127e9c6570b66600820 + 494ad84de129e62b21bba071d8051a6238a51a5a + f09c50833a58feb41e33cab11e41df1de8eeedcc + 30a03fe42d2f7336b0ed8648a0db70b1462cb76b + 017b17715d7c6a37e4839dbfd9f6498b3b17826c + a4720889b0785c30cc5b9ae56f404a55170d682a + 5c78a48362ff5a2e28124c9901ac7ef2497fd30a + 39e371cf264039216d190a3b7973f6ea9d745775 + 6894cd074f39c624be1f0efc4a4b273c1a579bd6 + 50c637cb403c92e3f6784162069d2604f1225725 + 128d969bbb6da6a34e838e3d95d68ec5dd294867 + 2114cf6fb464efa725f7fa5b8cfc1caa80e28672 + ca7d1683820bae83b8690f38e5aaf9e1d636abe2 + 3257813fc3444c2e606b7f9969bbf315dd63fa90 + 1597f152441f6b0a3ebdccfe0c8350e2242616d2 + 35a4b71263aeab8206ba33e23c77696cd36b4518 + f6334b906ac6f4e068ca73b39fee2e7b25bf7981 + 8e91d3f29603675132f56aec4fe7ef6d6a63fca4 + 59df53686a09f36836696d627f26f684bc82afd0 + b5fdd020ab89b9eef96fedd11924eab2f33fe1ac + a10410318a1572e3db0cb85b8535493cfe023016 + 51124ed652ab51c6f9562e687b70c89ae504529d + cf873592a2b70ec6033e1165fd67a321003464b9 + d4315f51b5ddc3ec94a0183674dca9a400be10cc + dc2f46596ab80be510e874b19702478a04f4e5c3 + 5b49e74cf77ce61c433a1144e214c3f88910962d + 3ac5906a9f85304d580b71cd9327fd61edeffa44 + 81e74202fd189c83953fab52df68951d8169c459 + bc472cf7d207b3f2c8b5ece2409185091c4fb98a + 278be38283d7cfc425f8d2d3ff878d092d9abc20 + 8c59a07a0f16d2c73b18cf9c094a217ac7549b0f + 717c55da1fa0210d630fd39d903cc9e8d1f819dd + 724c8b2141b7be2ad5d8fe35f90db84e634f3caf + e35c251905928e7cdecab7d5335420866e282099 + e9f39bf25ab70cde0ee6dc97803566fa72ab88f8 + 07e733a23c110efd3f61d00d2bf9a932e5b17b3b + f8c9efd365ea8e16a6bb7960dbf2e8923b6daf38 + 0630f187f5d846a3afaf517d2ffeeb90d48c5af4 + 46d00fc1685b39e7a46899416ff11f793e49c722 + 444b3637266774f24ea0757b29e9f4ba0de3057e + fc726962d0b4f888edab8d6088529b3ae4784d28 + 98a01edc5b8d0f543df51f98b9eb55a755ebe364 + 05aa7ad756232555f12ef6bb8fa8356bffbd435f + d6afccb033d4708a3dccde50bf12183072baf439 + a26c492ac46ccaefe9dc5c7c9400aec8d796e261 + ad068476ecd3b0483b1e15dcbf874286e02707b3 + d3a1206d02257a61dc3afc496d6485c4fec7638a + fe449f8645437f64f33b1f1ca8f0a099cdef3a0f + fd07b0f9ca72b8a0b1ee2b6f919a27caf613fbfd + 3a1a5eed724e229a45512ace76fc2c4cdb4aad2d + 1e018eb2b2c3c53c9a51d8ec518d051113ec6529 + 564393b0a9363665c7362f0a5ac71316f4a9265e + 17a78772871dc7e7e5c978f91f97a9b0660f40ac + 80b40c9929082efca003180e089bbfe5f8082d2e + 0944557d7186e1316b470f41e268b5c4a30ed206 + 944691065bdffa40bf18cfa3da7cbc2f5356ff08 + f85307e1e85f3769ebaf8731b3fbc3400fc08108 + af7354a57bb251dd4bcc0c07cb77993243be5e87 + eff8227e4995441276416cca50fd14fef2ba428c + ec673322ba6bad3b270b19d3ceb05305a6d6af45 + dd59aec11fc5b728aff4998e12f53a1112cfbc31 + 252086811d30ceb5badcaaa69c4cb32e7303b7d2 + 0e00907a75b843cd935ef6a451b3c82af49e3008 + 2a4a79d2c884543a3ba2a73afa47eb9f0bd29698 + 9aa7bafb92bd0e1fa42ca81b34828291174cfa45 + 50a700806286465c356dc6a5aa9d77646be2371f + 0d5c84f521e82a262bc5ad047798096be0ad8217 + f9009d3620cb8bf7e644cb35868b26b1f9f72e93 + 22174bf7c7f885afaced65e3af0453917aecb803 + b4492302cc57880ca4c32471fb531b1ca41eb2a1 + bc9a39507de82e1190121b248e032384d998cac7 + 08aabd9ac83078444ac22dc9dc0936c8455ec6aa + 045c55a19bf74a4c09cc350d912287505f49bcc6 + 57cd4adf110b641b0872349a1905853ce7c3be6f + 73fd179fd5237c71f0d69ebcaaeefddcc7372034 + 02a1892f86b351e7d25c86de00f1976fe4c36726 + b4520a04516e18d6484cbb97d494dc301ac4150a + 5b1ec54158bc5fd716dee1175a5b7a69c4f67f97 + 2508fb878c117c6eaf1adb44f047463d8302bc27 + 1de3dbd76c42457a59daea2ef4f9bfee2677cf08 + 9fc5feaa0027b690edd68f9e184388d586ae3405 + 1fa4c67e95d7a6ac3c626c744e703bcc858968f8 + 138631842aeda8e493affbfb915acf75ea0d1b4b + 300ae5f1277a0374ed60996a6cd166f8ce19cc19 + 4a9578fb889bd57ac08f383c501887c6f6cdaacb + ca33f2402ae60e2ca34a082cb2ff57b251fae0b9 + 797e7fffb8ba0b568c2b32947bd27459e581b931 + e7dd92f6b9fcb9cf6e8a7aababb4fd8d5286438f + 0d86c365f6789a0ed89663c9b4ce2baafe631198 + d13836d6d14856c6322e7a02688191f8e403a003 + f76040312df1f9bffffee5da1f3760bbb078a9d5 + 4c292b1cf4f0d198c7a0c62feaec65a7209af089 + 5705d5b44a8475dc9e930e25c9131860282eacce + 7900c7881264321732e18f13318af526f19a8302 + 652da028e5240027a861cd0089652c9a9dd47735 + 0799bdab13d97e3acac01947e581260d1ff96dcc + 06e826c833a096daa1c4c209f09b8a1bb1bf0e88 + 3f87b9557090c2ad7bb155e5ac2a35d242831f9f + 5c2d2fc46f2b4867843780a9925d90231b80ad2e + 57b5897d995a27a65a80e0a63f0625f6a752c081 + 6dd50b9ba1a288cf2e7765e5dcc5bfd80ba8c92a + 2a35d531b30f15cbf91bcdbb6eb715f1656e5a0a + 69f3e10e839bbe57a61afabbe32f4c7e125e3874 + + + + + + + + + + + + + + http://ftp.uni-kl.de/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp5.gwdg.de/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-bayreuth.de/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://download.uni-hd.de/ftp/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp4.gwdg.de/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-erlangen.de/pub/mirrors/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.rz.uni-wuerzburg.de/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.uni-leipzig.de/pub/ftp.opensuse.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.halifax.rwth-aachen.de/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp3.gwdg.de/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.intergenia.de/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.tu-chemnitz.de/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-ulm.de/mirrors/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://vesta.informatik.rwth-aachen.de/ftp/pub/comp/Linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-kassel.de/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://widehat.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.hosteurope.de/mirror/ftp.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp-stud.fht-esslingen.de/pub/Mirrors/ftp.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uni-siegen.de/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + + + http://anorien.csc.warwick.ac.uk/mirrors/download.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.esat.net/mirrors/ftp.opensuse.org/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.switch.ch/ftp/mirror/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.gui.uva.es/sites/opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.ines.lug.ro/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://www.mirrorservice.org/sites/download.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.icm.edu.pl/pub/Linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.heanet.ie/mirrors/ftp.opensuse.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.kreksi.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.belnet.be/mirror/ftp.opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.fsn.hu/pub/linux/distributions/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.ynet.sk/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.funet.fi/pub/mirrors/ftp.opensuse.com/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.ovh.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.lagis.at/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.klid.dk/ftp/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + ftp://ftp.pbone.net/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.se.eu.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.sh.cvut.cz/MIRRORS/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.inode.at/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://gd.tuwien.ac.at/opsys/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.mirrors.proxad.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.leaseweb.com/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp2.nluug.nl/os/Linux/distr/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.cc.uoc.gr/mirrors/linux/opensuse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.karneval.cz/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + ftp://ftp.man.szczecin.pl/pub/Linux/opensuse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.tugraz.at/mirror/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.mirror.garr.it/mirrors/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.linux.cz/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.uib.no/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.sunet.se/pub/Linux/distributions/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.gts.lug.ro/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://fr2.rpmfind.net/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.isr.ist.utl.pt/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.bifi.unizar.es/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.uninett.no/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.nl.eu.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp1.nluug.nl/os/Linux/distr/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.novell.hu/pub/mirrors/ftp.opensuse.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.ntua.gr/pub/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.hro.nl/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.roedu.net/mirrors/opensuse.org/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.estpak.ee/pub/suse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + + + http://opensuse.cs.utah.edu/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.kaist.ac.kr/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.its.dal.ca/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.kddilabs.jp/Linux/packages/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.jaist.ac.jp/pub/Linux/openSUSE/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://www.gtlib.gatech.edu/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.idrepo.or.id/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.novell.co.jp/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.riken.jp/Linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://www.muug.mb.ca/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.umoss.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.osuosl.org/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.isu.net.sa/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.fcaglp.unlp.edu.ar/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://opensuse.mirror.aussiehq.net.au/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://suse.mirrors.tds.net/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.anl.gov/pub/opensuse/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors1.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://fundawang.lcuc.org.cn/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.rackspace.com/openSUSE/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors2.kernel.org/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.xmission.com/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.utexas.edu/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://130.57.19.201/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.nyi.net/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.chg.ru/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://distro.ibiblio.org/pub/linux/distributions/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.ussg.iu.edu/linux/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirrors.rit.edu/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://ftp.nux.ipb.pt/pub/dists/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + http://mirror.internode.on.net/pub/opensuse/distribution/11.3/iso/openSUSE-11.3-NET-i586.iso + + + + diff --git a/tests/media/data/other.xml.gz.meta4 b/tests/media/data/other.xml.gz.meta4 new file mode 100644 index 0000000..34baf30 --- /dev/null +++ b/tests/media/data/other.xml.gz.meta4 @@ -0,0 +1,634 @@ + + + MirrorBrain/2.19.0 + http://download.opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz.meta4 + 2020-04-17T10:35:59Z + + openSUSE + http://download.opensuse.org + + + + 16108851 + + + + + b0e3ea6121ce4a0a9efc732fa61498b4 + 9bf6ebc95bbf7776c8ee2a7d0a59ec94ab34953b + 702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121 + + 52c0a614 + 1d1b0484 + a6eedb22 + 774ee5fd + 48b1afe4 + 99676335 + 237f7e44 + 6716b34d + 9de0b6b5 + eeb79c2c + 91a32ff3 + cb7d3528 + 6821642b + 4afbbfeb + 4b3dd85a + 06d847bf + 0d4062b0 + cf9421e9 + ccc6bff3 + d0469103 + 10f29244 + 078e5f5a + fb01f0a1 + a4cb6923 + b08fc953 + 49caabcc + 1793fa09 + b36e811d + b1a3bbe7 + 2956918c + 53523172 + 254f3914 + 7f220a9c + bd30c70f + d8b1add2 + d395e95e + 3e979f77 + 930b076b + 378c8b81 + 30ef4edf + dab0d9fc + 5e391464 + 6ac489c6 + 36fa94f0 + f3063b42 + 9f566ad4 + 6c12a5aa + 1a25ae6b + 5918c9ba + 259ac921 + f4957810 + e6d0f681 + 7bd396e9 + ae538fc9 + f89b0b44 + 03d057ee + ab803b05 + 08b08ed8 + c2917a7d + 863d0b85 + aa1f9d90 + 991afb80 + 4edf38ea + b5e40f1a + d4d4e483 + f65e306b + 7912c783 + f6819c0c + 04e266f2 + 187905a5 + 32711d10 + 86d5f0d4 + 850439c0 + f804e0e4 + ead17338 + 171a26ce + 1140a195 + 40e5ab93 + 1c4141d1 + 65375cd7 + 85dbcc3b + 4e3fe5e3 + b39121ef + ce4798ee + 712af259 + 2ed654bb + 749ed9d5 + 98e286c7 + 6cdc3999 + 1992b5b9 + 14a34c09 + 8f2bdad5 + adde2ef2 + fcda3990 + af59b0b0 + d6b197ea + 48a7fc22 + e6303467 + da1fff7c + ce22618c + c3058796 + 15225499 + 9f1bf1f1 + 380172a2 + a1b44a09 + c9d9f6f1 + a8c78564 + 9cbd2bc3 + 64d0dcec + f465da8f + 6a9d15f0 + 64fdc6da + f3dc5c56 + 11c6fc79 + 08d33205 + 39f3b762 + fbcabbba + 4b549193 + 367aa49b + 0066daf1 + 2c1762d9 + 2e8a4128 + 358b5696 + 101e02b4 + 01b563a3 + af77bfc1 + 1baa1682 + 21170038 + bf1938f8 + fc833941 + 4f4af457 + 2e69237a + 339aa64a + 6fc4603a + 2bd4258e + 2d96b5ca + 5f1f0d5a + 6e96399d + ac0c374c + 3b1b78ef + 13ea3a71 + b7235e19 + 983b7750 + 6346a1cf + 1c4674f2 + 29401c27 + d20d75d9 + 58fe3a80 + 36046fa4 + 30f1bb0a + 0d6bfb04 + ba03494d + ddab80c6 + 3ebe0e52 + 717f3b33 + 4c1d18b4 + 194996e3 + c0a5b547 + 46701b77 + 1fee6657 + 5c0b188e + 36b0b261 + 542d6ecb + 8075ad43 + fec52502 + 58b78958 + 3cb977f5 + d723f5f1 + acce65f2 + b8971b43 + 284701af + 7806f59f + 5d316f76 + 0744df06 + 74a71b65 + af52e37a + 36182408 + dfb2d5e7 + eb1837ae + 06ebb86a + e29d708e + f41ddba4 + 3ca24f76 + 3ec2d12c + a05085e8 + b3901429 + 5c7168b6 + 3b61dd7a + 8ebabd02 + 27c0e98a + 5ace82d6 + 321df0de + 0b8f5b4c + 4bae8466 + 68101f66 + 980da2ba + 81d50c1a + 4e84bd20 + 9b61208a + 205a556b + 057d34ba + 31f20187 + 9e718b2a + d0b8e062 + 0872e972 + b49a2bde + 760271ef + 6f76f48a + 1c611d36 + 064db936 + e7329863 + cbfee98e + f3bcd1ec + 926fbb8f + 8c385a88 + 1b24f948 + d7eb6751 + f4d38846 + a8599d87 + 78b0a47b + 07ae8db1 + f186b800 + b46b9174 + fae79ab0 + 737f9ce2 + 09cd0215 + 115a6c03 + 20a53586 + d54c989a + c80e7714 + 9fb08412 + 765695e9 + f7071fd6 + b0acf700 + 67ee5560 + fe631438 + fb4f23ae + bb560d0b + 60cc375c + 5c02ef6d + 58864bc2 + 232e0528 + 2851bfa6 + 24a78b42 + 54f4fba1 + 349ad053 + + + b9f77f48f4a49f3438fc1bb6de90df39657597aa + eb519d03cea235bd24f57941495cd917f84bd897 + bbc848cfe07fc2588d94115dca1b6933b5b2c3e3 + 8cef145c2e633fe14f29be5692683e55aa70b543 + c508c1c5dfb4684fb20ae91cfe6231fa0e6ba174 + 23ac327f06a38b40f10dc9b8c26f6563820fbaee + ca25b93d0744a27f31b9c50e680fb37fda988f6a + 027e02287e26a679610d4d26f27ae03d0d90480d + 9c63ede3e63de810e41d88b99f4ff29d236d0765 + f5f60eabcdea574a4b25ed7892e5ff893d28e3e6 + cac3ce8115413ad842cde8a8a5b3c376533695d4 + b7ad7d09e62a1a581e58b33467a3afe012c51163 + 898aa214396d911d01e84b06ea7606fb834f6f82 + 664f445146b0548ac6b62400681d0ae651be8d59 + c39c214f2fb452b1be664839df1a371f863970cd + 5cc9e11746124ebf0282c1ea1f18e72cfaf6b60d + b3f7e9b52fe2a3630b9547e495e847ca530e283b + 0ddaaa89b57a47a76cf8e870dd2adf3064c5b7d2 + 6863ae28830c18b39bbe40ccf663f36178dbaabe + c111b32adb590650b10c6131016bd118669fad9c + 8a2941fddacbf7b2a144eb246e761c7c48134fa9 + d222fe76b95e9034275121b86a124977a8a2a0f4 + 7072c00f004d82533321d0c99a6106a089ee4acd + 026ea21296d66729725274dde37fb07b25a6bc90 + a799bb63224e7ae4e2ac48c83548c0e7f4339ed9 + 090f7ed2f2a21712f1297ffbffc7441de521c72c + 28a25cbd545c6b8936a58dbfbc6f3df66b1ff1f2 + 0b2df923da1a425330738bb0690723db59574ed8 + 3787396a99a302e8020a4936484a0548244e4696 + 836809523b244b31a70ecc9b8cfbc92b6189703a + 6d26a0b6abe7961b1013540194dfd1568246e39b + eaa06966730e2960dff6b318739c47f53afb48fc + 25840fe2bf327ce91d8920b595702de770efe901 + 0c5cd1b57bc8d833a0ec6cbcc2e983851672ff8a + 4ab9385e1eea1f6dc45c4ea4cce55bc1689cb162 + 28f0d7c20caefbe1052db07410d6a22465a77768 + 0d52b5cc32cdc5ca3589210240b0e5b7173d71b4 + b6412c472de727869867918d2186effc129334e0 + c193530764f9fc5c2b008ecdc0ed454fd09a2016 + 325e3e4211f9815b4f647c3cef57bccaf3e4bcc1 + e5583176f956725ac4f0d6618a22575dea4996a6 + 03dfdb60cb43e5a55d0c61678ca4698cffb403e4 + 226dc7d7c836d0397d0aa96b2d29706afb1100ae + f1b6075e2f073a270dd22e23afe0f0a68f685cb9 + 56b9d3b2d8b4a574d17d5e063f2a59e3be39c10e + 8ff09431921fa287749cde787c7fe730826593c8 + e24b0cd9b8fe9485d269f46856fc7b67689b8e93 + 33dc95d1b5b070010f08aca43a4496409168fed2 + 6dce6f86912a57890b0c801a39c7bac95ecd4304 + 7d7cc195b098047e04c8e667a5cd91649e50fdee + 3059a0a978572cda808d4ddc402df2b67458733d + d9184e997d4737bf9966b56dbb20b9a5c74f6645 + 64addf29c0b35eac2ce21ae2fe6d8ce232af8ff9 + 2170eb72b643a229e1e33a28e1b7e554398b423d + 4b7bacad11b4762e54cbd412d41ae043b7388706 + 4c5f8f1926419001ff88122a3d426dff0e2fcff5 + ccd0dd77c83da20d7f4ddf13dab89d472f816398 + 5a66f1fdb6189de62f91e3c13b7859434eb2ae10 + 362f956e4061b1d4ae60654c3b59bc18a9aa8b5b + 9712c3dfcea2ff067a4c510fae5dbcc90599ffe6 + 699440f8b691774ec9060caa988d008b79b0b272 + b0638b719cdf6a634516b2cb7ec85e41b866bdbd + 49afa1c7fdae319b4325edba0e19814459bd3d9a + aecf9ee3948c3530122e8839ffb450ebceb4df5b + d9709a7431c3c9c4ec42e76efbbbf7e7a2eb964a + a254ba5f983e12bffba48af2cae35783fbe3da6d + 7a6ff90e51fce74e528ce3968507ebc6000614b5 + 44aea5f544bd0ea25774f392eab846f873e5fff8 + 75d7c5d1e09d73c368248835da602ed9bb785490 + eb8b75f5ad07a6459ad05a9d88e22f529a21944d + 993b71f98128b7f2c929d56b430f5e514b7c457a + 72b582d7cb77f901f86e405c84b3e8eecb2bc22b + 49bff42f3e2eefa5c53c03b698488c903f76fe55 + 248bc7caba7b75ca7edee72e1645e6ee0207b8e2 + 156215ff516ef914f28268b31dd27a360b4797e1 + fe0c489135d495aea711c01d37d31f40d638cea2 + 5697a51c38f075aebea5e0593d48e899e79f5054 + a146d446f52c08a4aa2515a76ac39003f62b588e + 619386f78b66eac122d61c8028a992ca3cdf6eb3 + ec216f4ef6a5983c448d1b63de347a0753b053ed + 83e08e5f9d347d75337d77c01b38cbf8326e3982 + 5c60ba2c86df1b65e41eeff93481b99ee90e7a21 + bed0f7975dbe0abb3e09d76ca239d5a8e8231974 + a245c5324a6ca6626e0903d892712d8cd93cca84 + cdbbc69c35540f4527ab858cb547ea599b5dabc4 + e8bc63208646ff1db2c653a931eca96d3790e56f + 75ce34d9dd80a13d00cc73f30c63dbc242ffe187 + 03a1c7dbd3cd99536600bf19b5275c4c58b82e58 + f0d0d1fc1155a1dcfb804c952166ebdadb30a926 + 31e699f38b24cd4fdd89440904887c0c6490b2b1 + 387c9fde6f3d817da8bfbe791967ac7bed10b0bb + bd18d25208a69f60bc9ed47703b0598d05e88a65 + 88ec754b99b1d1a301665b52d0f5078a8313ced4 + 5c8d406fa3325410513c3f82abb839e68bd8cc5d + 8fb9bbf106b201846af4827ea8f18151d1e54f1a + 4d4a23f492a786868b2a8326108578eb222915c7 + 4c9a257ffd6aaecc8649f9fcd7658dc12886cc45 + 2999f114c2afc1d381b61f393ae9041042ea4c1b + c9f20744675482835bb4e307df78a0eb33ee9597 + 8f5c1d36a94e28b979232e75f5a09895670d43ba + b80f0f22d35d561a6f19ad414583692ad1a6baf7 + d2e607369e972154e5cfb644b6b9065fe0ec8cc7 + f8dfc2d1cb12c28fc393aa01db2fa4b6a473fffb + 0695ec9bea77cdf4cfbbd40024bb23f415a96846 + 4e92c4015ac67f2ece37f29f31fc14ba4b5138fd + 629dc485fee76e0f18dcfad4b1cae81e9d890cc8 + fc14106f32b3ffef1bc04efc9cfd517004a0bccc + 25c13c97f2a16b1fc222ad65a87adf1da03d3f13 + f512eab85491096e799a78a22dbf18cd52314f05 + 12b559864bb0932a3773077a5dab5753479ca4a1 + 7e44c02f91d0e6fe04687e709db3787b370c910a + 9f6f67023a05fd7bfa00bb39faf367ef00303aae + 39c467877e9d220a52d570f303e76344b3a2608d + 174a697aecf5d38b0f114b9bfa372a8f18c42c81 + 9f879aecaf6569cb3cfd164bc44c725ec0c3c100 + a0f37fcf36cc62ec7028b0136a601a9743a11bb6 + 28d780cb009c6ec45f3d96f061d342cfcc39a116 + f91a54e70e648566847152dc6da160a43c354462 + 8f1356a866020fa3403d001b1b9d8704c9ec014d + 72d1935f0dbd5bbb4261d642b5a84c56fde79461 + 0019d698709935d84730ead1e75a88ce34d56047 + 8136920b4ec15543f69841411497930b9a0756ea + 8d8d23fdf4a45991475bea88f8f4ae41313204d8 + 270ee2b97fdf893361fb0d1e6cd2b3dcc2a56cca + a46ed235e4e2350ce55d929437bef2696c73e58f + ffde235c872520ff2a4fb1686612422157b3da4e + 70156892aaa72c869cb4de9f178211acd91386db + 577030eac9eeb0149484d59e4675a0675ec29aba + 51b73a522f31981f46fd9c93088dc649c9e18ded + eb1d66156a4de48f02550198d258c21987272094 + 8bf73b8e4ed442733be764995b19854dad16ad74 + df2aac249fe67e78ed7efc88cf8373ca9664d25f + 2087445ccafa2f380f8fd3083dd371be0c791011 + dd95e88e8eec80074466a5629cc2bf27c0caa405 + df0ae393f8c15b6c79764e0c20c23a63816b265f + 6a3d41b1d89219b8e55f92d0c9e6d7c490ed3a9d + b77f200b3feeac052155676bebd7d79ff7c521b4 + 40a85837934de7349e4b7d499e45c8f0c89f0380 + 86f4ec3d1997356df228c2f8e12f7ec34376dad9 + 18b1eafaa4cbcc5246341f02120ef5a751b2a07a + 4bce3c8d51fd178c83b92856d5a6d91a73b8c270 + 77e395ea41c389823415d295d43654c1ea0a13f8 + 0e5bc24274fcc33dc0bad9e793843ff004d14e6b + 1f8e4e250a637126869934b3be7ea2dd4def9697 + 6c9e951e83951c7189f9a7cae64114f2d068b149 + ee358a80270841ec34573070bc44a9a973e975f7 + 52bd4e79805c4b82c582a0e54a16eb64a41e0265 + beeab96f0955f21d919047b1548cc63dda681e99 + 1a1dcc661db31042e679d8aba08050fe4ac46eb4 + 50bc05e6b0117a66737fe0ed916f7f399fe99e08 + e3324f3cda3c99be671c6fb194b6333f6dc9ebcd + f8a657caa0609cb1735b2f89df79a58085692fbe + 68e81283af7bfa5be9f34c2a20c7e1c176447f47 + c9b06b781e3c1206f98efd4e129d500e84140aac + 5ea9392a721308c336c4947f650ae1d67e0219b2 + ea395621e73a3cdf0c810c9b66fa14db08fb318b + 80c5e69781257a49808d7dd41e8607ae85354230 + 798c5481862e497135160472d11d9588a2d67a14 + 1bcae9f627068040e89bddc27797dd9d9c8db03e + 2b47afadd5782554928703669796bd39239271b2 + 782bcea66a64ace7c2a5a0cef1f9607bd8d27520 + 5cf8116d576d670d6be3a116383cdf7f0d9c8484 + c721d424f73d1dcb1ec1964a7b8274d01932eb6a + 93240a9223131a0179d979f2dce69a3eddffbc02 + 349abb4775ac5696ccee9c69ebcc609701bd58aa + 5add463a4edb0ae91f7ccea535dfb7746d7d6dd9 + b1515c806cf9b3e5d6e4583983469830c4a280d5 + b3673a2dfae021812831b56f0f5b728e9ed18f16 + d8334d5c17258b6ae3b81e465174543d624f3d60 + 9ed0e5219d14aac67748cd5224f6348db4975cfa + 4ae31784ea2ed429d97badf0fcf4c0476629837a + 5fbec5ca9e444ac869e307ad9c202266174aec52 + 9c76b3f2f5fe557e89935e83239c6f077b5a15c0 + 89416abb164886ab6d62a5069f6372dbb1d5aed6 + 4ab5bfc5a77c9bd9a02f4387a2a156ad435ca734 + 5e4f901d92f1a028a8600ae6d1733d1a1447c30f + 002ca76cf81c26feb9e45a0f839c89ba6cbb61ab + 3e200848aaaa4f6c4f47724e81b7ca756c41e843 + e7fe994aa2131b3daff2f55c5b3e655089ff91df + 27147f6cb293f64e7c92dd8ae456ebef7936b40b + 21622d7ef1ca2927d6228f6d22e9a9ad840decf5 + 189e3e39639d1b21268c6f92bfb4c76a6d9d1675 + 94f8084e4d6439d5381fb008061c68831d54eca8 + 468346108131da81828a06effb7105fa9908570f + 6a2c40a1161acb3e3192ba56f114a287d1bd8075 + 8364b1e1722b18c25e013290ac83f2e9826cd0b0 + 085a690dc2f967ebef514b0eedbb65b5acabc6ec + 23c83426d57e5026a649aa567f33424c10ed26a0 + 8e64b4ff663e3f70ea8f78df0fa1f4c8a8fd6964 + 71a4e3c72ee14ebc3790feee49c1f9171b2c3b0b + 07505ef63db167bb46b17ca93f00f358bc0bca70 + 18376e3f57aaef28a167d53da5641aa6c52aba51 + 25f657d2985d243f908db3e10610ebc925a871da + bd1d54dbad5b26d69f0b563f1871790814aae02c + d441456e1f7c43e7aef24a7eaa4a761640e0868e + 9f8e36d32e573dbd34eaaabd5f55c50a81a597cf + 3f79e9a63d018fda063efe1367a1933bfb95cff6 + a3eb8c31e8fef133e1041ddbb645cb18f112c8bf + 00eac6ff6914ae5fefc5d38f62dfb2f702d3438f + 7837845b7cdd1374ad35543094c637b8a61a508d + 9ecb417b572d73a8698e009cbace10d0f49bc1f4 + 58efd0711cdcb0d59bf63ac2cecd8b45b4699f14 + f83e6c8ae5f654a7f62974f8cc48f7874e87608f + fef21cedd6aeecac6c65dcffcb07726cd7491bfc + 6131018fa558299e5df017d50d206e54d12fdac6 + 9ad2d8009f5958ee0714f7104cf73b06340c651e + 99bd899a87a9ae07e50cf0a8eee6b209a5ebce49 + c25f16d3deffb6e9d362f072791ddc994d0d1a70 + 06a3f40e2a1ed91d4d0b6bbd1aadbdbe8dda9b95 + ebd13b83c8a14249ed95fcf6900e5c58de46b881 + 81e55b598eb22532f5b48898f59e1c0a4619c078 + ef81c3884c81def482f667886494d6f93ce52c1e + 555a16832d6b8acb9c8184a5eff52ba082e62000 + 4ac5ad095910ef4148dc526a147edaf38fc894e5 + 78cf92a1f62daf43273e0e5189e4969b3f40c284 + a3b9ee6f0d9e00c5f2b0155f18288ec5656707b8 + f7e7ae7cc6d63c8947aa87a9dc37642c13292401 + 7d6d48f8721f4b3c9b9dedc95ad55b1c6573d71c + db8bfaa26b11df13d8896e14731861fccdc477b1 + 848ed4b02af9b094459def417cc7c11736975d85 + 02d15cb753a295103146621251e51d61dff48351 + 55fd50c584c10365cacaffe437e60b01883687e6 + 52e09e6ea21b615131a55ccc3c3889693d357555 + 51f4a27756d001bc2861e09fa66e1c61e733c96a + d74b8360e3e79fdae041f352dc43b5c47fbe9d6c + b1c9de6514a7b4674aa1d902e4ffcfb5cb3dd653 + 76e85afeca22666bd9fe882baf184ab16bbd42d2 + 654e52677ceb84aea219d4d4fea61e79db34a631 + 7fa1c90807ca53c64553ae9538dc9b3a545538ea + 2158c837a32a3e6deac4458985898be39696cea8 + d6499e8d4d0e6dab8a9acee357312be7fd93c195 + e92698d28f58b976527799619f68c98fd6b1f365 + 5c706b017ed4d74765d3c7015ab76370f961acf9 + f143b67707f982a488d864a2d1e148f07eef1dd0 + 709a783cb5ba13dcc0b309cb12b8a5fc9582d1b7 + 452244a5246739fa8ba424b1b754da9fe5e8f6a4 + b1b3bc21c6054382d40b6309de3f307e03ab8814 + 863a5fcb1f90350550bb366eb2b5d9af4f952beb + fd1100fc41b85a27dd5144a64e9552a09cea327c + 31c2f06b23a797c8252b0efc6cb55e86531582f5 + 91ba8885fd33e935ea57f4936f41cad8afee735c + 9320db884775a370709c7fc6dcb37eca77c46dd4 + e219dc3a4cd44d2785fa6f4c7f930f2eadfb37ff + 2a2ac760f2944c4e1b6ac7d3001ecc09ad49b1bc + 693d0e7a7af313dd849c48222276e25d635512bc + 23788c5daf28813cdc6a14f1f02add712c020fd9 + + + + + + + + + + + http://ftp.uni-erlangen.de/pub/mirrors/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://widehat.opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.uni-bayreuth.de/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.rz.uni-wuerzburg.de/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.tu-chemnitz.de/pub/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + https://ftp.gwdg.de/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.schlundtech.de/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.de.leaseweb.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.braun-software-solutions.de/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror1.hs-esslingen.de/pub/Mirrors/ftp.opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://suse.uni-leipzig.de/pub/ftp.opensuse.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.mirror.iphh.net/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.uni-kl.de/pub/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.tu-ilmenau.de/mirror/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.halifax.rwth-aachen.de/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + + + http://ftp.sh.cvut.cz/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.nic.cz/opensuse/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.hostsuisse.com/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://pkg.adfinis-sygroup.ch/opensuse/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.xgroup.si/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.linux.cz/pub/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.karneval.cz/pub/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.easyname.at/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.dotsrc.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.klid.dk/ftp/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.man.poznan.pl/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp1.nluug.nl/os/Linux/distr/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp2.nluug.nl/os/Linux/distr/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.nl.leaseweb.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.mirror.liteserver.nl/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.belnet.be/mirror/ftp.opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.mirror.garr.it/mirrors/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.pbone.net/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://quantum-mirror.hu/mirrors/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.fsn.hu/pub/linux/distributions/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://fr2.rpmfind.net/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://tux.rainside.sk/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.mirrors.proxad.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.lysator.liu.se/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.icm.edu.pl/pub/Linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.vectranet.pl/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.acc.umu.se/mirror/opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.hro.nl/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.coreix.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.ox.ac.uk/sites/ftp.opensuse.org/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.novell.hu/pub/mirrors/ftp.opensuse.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.koyanet.lv/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.rackspace.co.uk/openSUSE/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.ipacct.com/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.netix.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://www.mirrorservice.org/sites/download.opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.nxthost.com/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.acc.umu.se/mirror/opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.funet.fi/pub/mirrors/ftp.opensuse.com/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.rnl.tecnico.ulisboa.pt/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.library.ucy.ac.cy/linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.yandex.ru/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ams.edge.kernel.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + + + http://opensuse.ucom.am/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://repo.iut.ac.ir/repo/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.dc.uz/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.squ.edu.om/opensuse/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.mirror.liquidtelecom.com/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.its.dal.ca/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.siena.edu/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://nrt.edge.kernel.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://sjc.edge.kernel.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ewr.edge.kernel.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.clarkson.edu/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.math.princeton.edu/pub/opensuse-full/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.c3sl.ufpr.br/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.us.leaseweb.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.vtti.vt.edu/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.csclub.uwaterloo.ca/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.rit.edu/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.lzu.edu.cn/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://plug-mirror.rcac.purdue.edu/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.ucr.ac.cr/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.cedia.org.ec/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.bjtu.edu.cn/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.tuna.tsinghua.edu.cn/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.rackspace.hk/openSUSE/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirrors.ustc.edu.cn/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://espejito.fder.edu.uy/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://www.muug.mb.ca/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.dal10.us.leaseweb.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.datto.com/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.rackspace.com/openSUSE/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.yzu.edu.tw/Linux/openSUSE/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.kaist.ac.kr/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + https://provo-mirror.opensuse.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.cs.utah.edu/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.jaist.ac.jp/pub/Linux/openSUSE/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.kddilabs.jp/Linux/packages/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://ftp.riken.jp/Linux/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.sjc02.svwh.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.sfo12.us.leaseweb.net/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse-mirror-gce-ap.susecloud.net/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse-mirror-gce-us.opensu.se/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://sfo-korg-mirror.kernel.org/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://suse.mobile-central.org/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://opensuse.mirrors.theom.nz/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + http://mirror.internode.on.net/pub/opensuse/update/leap/15.0/oss/repodata/702d2a63e32b11a60ef853247f7901a71d0ec12731003a433dc17d200021a121-other.xml.gz + + diff --git a/tests/media/file_exists_test.cc b/tests/media/file_exists_test.cc new file mode 100644 index 0000000..2a1f3b8 --- /dev/null +++ b/tests/media/file_exists_test.cc @@ -0,0 +1,130 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include "mymediaverifier.h" + +using namespace zypp; +using namespace zypp::media; + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +BOOST_AUTO_TEST_CASE(curl_params_reset) +{ + MediaManager mm; + media::MediaId id; + + Url url("http://ftp.kernel.org/pub/"); + + id = mm.open( url, ""); + mm.attach(id); + + Pathname dest; + Pathname src("/README"); + mm.doesFileExist(id, src); + mm.provideFile(id, src); + dest = mm.localPath(id, src); + BOOST_REQUIRE( PathInfo(dest).size() != 0 ); + mm.provideFile(id, src); + dest = mm.localPath(id, src); + BOOST_REQUIRE( PathInfo(dest).size() != 0 ); + mm.doesFileExist(id, src); + BOOST_REQUIRE( PathInfo(dest).size() != 0 ); + mm.release(id); +} + +BOOST_AUTO_TEST_CASE(http_test) +{ + //MediaVerifierRef verifier( new MyMediaVerifier() ); + MediaManager mm; + media::MediaId id; + + Url url("http://ftp.kernel.org/pub/"); + +// iso_url = "iso:/"; +// iso_url.setQueryParam("iso", "SUSE-10.1-Beta5/SUSE-Linux-10.1-beta5-i386-CD1.iso"); +// iso_url.setQueryParam("url", src_url.asString()); + + id = mm.open( url, ""); + //mm.addVerifier( id, verifier); + mm.attach(id); + BOOST_REQUIRE( mm.doesFileExist(id, Pathname("/README")) ); + BOOST_REQUIRE( ! mm.doesFileExist(id, Pathname("/fakefile")) ); + mm.release(id); +} + +BOOST_AUTO_TEST_CASE(ftp_test) +{ + //MediaVerifierRef verifier( new MyMediaVerifier() ); + MediaManager mm; + media::MediaId id; + + Url url("ftp://ftp.kernel.org/pub/"); + +// iso_url = "iso:/"; +// iso_url.setQueryParam("iso", "SUSE-10.1-Beta5/SUSE-Linux-10.1-beta5-i386-CD1.iso"); +// iso_url.setQueryParam("url", src_url.asString()); + + id = mm.open( url, ""); + //mm.addVerifier( id, verifier); + mm.attach(id); + BOOST_REQUIRE( mm.doesFileExist(id, Pathname("/README")) ); + BOOST_REQUIRE( ! mm.doesFileExist(id, Pathname("/fakefile")) ); + mm.release(id); +} + +BOOST_AUTO_TEST_CASE(isotest) +{ + if ( geteuid() != 0 ) + { + BOOST_WARN( "ISO test requires root permissions! (mount)"); + return; + } + + MediaManager mm; + media::MediaId id; + + //Url url("nfs://dist.suse.de/dist/install/openSUSE-10.2-GM/"); + Url url("dir:/mounts/dist/install/openSUSE-10.2-GM/"); + + Url iso_url("iso:/"); + iso_url.setQueryParam("iso", "openSUSE-10.2-RC5-PromoDVD-i386.iso"); + iso_url.setQueryParam("url", url.asString()); + + id = mm.open( iso_url, ""); + mm.attach(id); + BOOST_REQUIRE( mm.doesFileExist(id, Pathname("/README")) ); + BOOST_REQUIRE( ! mm.doesFileExist(id, Pathname("/fakefile")) ); + mm.release(id); +} + +BOOST_AUTO_TEST_CASE(nfs_tst) +{ + if ( geteuid() != 0 ) + { + BOOST_WARN( "NFS test requires root permissions! (mount)"); + return; + } + + MediaManager mm; + media::MediaId id; + Url url("nfs://dist.suse.de/dist/install"); + + id = mm.open( url, ""); + mm.attach(id); + BOOST_REQUIRE( mm.doesFileExist(id, Pathname("/SLP/openSUSE-10.2-RM/i386/DVD1/README")) ); + BOOST_REQUIRE( ! mm.doesFileExist(id, Pathname("/fakefile")) ); + mm.release(id); + +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/media/media1_test.cc b/tests/media/media1_test.cc new file mode 100644 index 0000000..c1cf86c --- /dev/null +++ b/tests/media/media1_test.cc @@ -0,0 +1,39 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include "mymediaverifier.h" + +using namespace zypp; +using namespace zypp::media; + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +BOOST_AUTO_TEST_CASE(verifier_test) +{ + MediaVerifierRef verifier( + new MyMediaVerifier(/* "SUSE-Linux-CORE-i386 9" */) + ); + MediaManager mm; + media::MediaId id; + + //id = mm.open(zypp::Url("cd:/"), ""); + id = mm.open(zypp::Url("ftp://machcd2/CDs/SLES-10-ISSLE-Beta1a-ppc/CD1"), ""); + mm.addVerifier( id, verifier); + mm.attach(id); + mm.provideFile(id, Pathname("/suse/setup/descr/EXTRA_PROV")); + mm.release(id); + mm.attach(id); + mm.provideFile(id, Pathname("/suse/setup/descr/EXTRA_PROV")); +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/media/media2_test.cc b/tests/media/media2_test.cc new file mode 100644 index 0000000..53db45d --- /dev/null +++ b/tests/media/media2_test.cc @@ -0,0 +1,153 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "mymediaverifier.h" + +#include +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::media; + + +bool do_step = false; +int do_quit = 0; + +void quit(int) +{ + do_quit = 1; +} + +void goon(int) +{ +} + +#define ONE_STEP(MSG) \ +do { \ + DBG << "======================================" << std::endl; \ + DBG << "==>> " << MSG << std::endl; \ + DBG << "======================================" << std::endl; \ + if( do_step) { pause(); if( do_quit) exit(0); } \ +} while(0); + +BOOST_AUTO_TEST_CASE(strange_test) +{ + { + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = goon; + sigaction(SIGINT, &sa, NULL); + sa.sa_handler = quit; + sigaction(SIGTERM, &sa, NULL); + + //if( argc > 1 && std::string(argv[1]) == "-i") + // do_step = true; + } + + MediaVerifierRef verifier( + new MyMediaVerifier(/* "SUSE-Linux-CORE-i386 9" */) + ); + MediaManager mm; + media::MediaId one; + media::MediaId two; + zypp::Url url; + + url = "cd:/"; + + try + { + ONE_STEP("ONE: open " + url.asString()); + one = mm.open(url); + + ONE_STEP("TWO: open " + url.asString()); + two = mm.open(url); + + + ONE_STEP("ONE: add verifier") + mm.addVerifier( one, verifier); + + ONE_STEP("TWO: add verifier") + mm.addVerifier( two, verifier); + + + ONE_STEP("ONE: attach") + mm.attach(one); + + ONE_STEP("ONE: provideFile(/INDEX.gz)") + mm.provideFile(one, Pathname("/INDEX.gz")); + + ONE_STEP("TWO: attach") + mm.attach(two); + + + ONE_STEP("ONE: provideFile(/content)") + mm.provideFile(one, Pathname("/content")); + + ONE_STEP("TWO: provideFile(/INDEX.gz)") + mm.provideFile(two, Pathname("/INDEX.gz")); + + + try + { + ONE_STEP("ONE: release()") + mm.release(one); //! \todo add the device argument once mm.getDevices() is ready + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + ERR << "ONE: HUH? Eject hasn't worked?!" << std::endl; + } + + try { + ONE_STEP("ONE: provideFile(/content)") + mm.provideFile(one, Pathname("/content")); + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + DBG << "ONE: OK, EXPECTED IT (released)" << std::endl; + } + + try { + ONE_STEP("TWO: provideFile(/ls-lR.gz)") + mm.provideFile(two, Pathname("/ls-lR.gz")); + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + DBG << "TWO: OK, EXPECTED IT (released)" << std::endl; + } + + ONE_STEP("TWO: (RE)ATTACH IT") + mm.attach(two); + + ONE_STEP("TWO: provideFile(/INDEX.gz)") + mm.provideFile(two, Pathname("/INDEX.gz")); + + ONE_STEP("CLEANUP") + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + } + catch( ... ) + { + // hmm... + ERR << "Catched *unknown* exception" << std::endl; + } +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/media/media3_test.cc b/tests/media/media3_test.cc new file mode 100644 index 0000000..abccc68 --- /dev/null +++ b/tests/media/media3_test.cc @@ -0,0 +1,159 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "mymediaverifier.h" + +#include +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::media; + +bool do_step = false; +int do_quit = 0; + +void quit(int) +{ + do_quit = 1; +} + +void goon(int) +{ +} + +#define ONE_STEP(MSG) \ +do { \ + DBG << "======================================" << std::endl; \ + DBG << "==>> " << MSG << std::endl; \ + DBG << "======================================" << std::endl; \ + if( do_step) { pause(); if( do_quit) exit(0); } \ +} while(0); + +BOOST_AUTO_TEST_CASE(strange_test) +{ + bool eject_src = false; + bool close_src = false; + { + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = goon; + sigaction(SIGINT, &sa, NULL); + sa.sa_handler = quit; + sigaction(SIGTERM, &sa, NULL); + +// std::cerr << "ARGS=" << argc << std::endl; +// for(int i=1; i < argc; i++) +// { +// if( std::string(argv[i]) == "-i") +// do_step = true; +// else +// if( std::string(argv[i]) == "-e") +// eject_src = true; +// else +// if( std::string(argv[i]) == "-c") +// close_src = true; +// } + } + + MediaVerifierRef verifier( + new MyMediaVerifier(/* "SUSE-Linux-CORE-i386 9" */) + ); + MediaManager mm; + media::MediaId src = 0; + media::MediaId iso; + zypp::Url src_url; + zypp::Url iso_url; + + src_url = "nfs://dist.suse.de/dist/install"; + + iso_url = "iso:/"; + iso_url.setQueryParam("iso", "SUSE-10.1-Beta5/SUSE-Linux-10.1-beta5-i386-CD1.iso"); + iso_url.setQueryParam("url", src_url.asString()); + +/* + iso_url = "iso:/"; + iso_url.setQueryParam("iso", "/space/tmp/iso/SUSE-Linux-10.1-beta7-i386-CD1.iso"); +*/ + + try + { + if( eject_src || close_src) + { + ONE_STEP("SRC: open " + src_url.asString()); + src = mm.open(src_url); + + ONE_STEP("SRC: attach") + mm.attach(src); + } + + ONE_STEP("ISO: open " + iso_url.asString()); + iso = mm.open(iso_url); + + ONE_STEP("ISO: add verifier") + mm.addVerifier(iso, verifier); + + ONE_STEP("ISO: attach") + mm.attach(iso); + + ONE_STEP("provideFile(/INDEX.gz)") + mm.provideFile(iso, Pathname("/INDEX.gz")); + + if( eject_src) + { + try + { + ONE_STEP("SRC: release(ejectDev=\"/dev/device\")") + mm.release(src);//! \todo add the device argument once mm.getDevices() is ready + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + ERR << "ONE: HUH? Eject hasn't worked?!" << std::endl; + } + } + else + if( close_src) + { + try + { + ONE_STEP("SRC: close()") + mm.close(src); + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + ERR << "SRC: HUH? Close hasn't worked?!" << std::endl; + } + } + + ONE_STEP("ISO: RELEASE") + mm.release(iso); + + ONE_STEP("CLEANUP") + } + catch(const MediaException &e) + { + ERR << "Catched media exception..." << std::endl; + ZYPP_CAUGHT(e); + } + catch( ... ) + { + // hmm... + ERR << "Catched *unknown* exception" << std::endl; + } +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/media/media4_test.cc b/tests/media/media4_test.cc new file mode 100644 index 0000000..1ce0dc5 --- /dev/null +++ b/tests/media/media4_test.cc @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; +using namespace zypp; +using namespace zypp::media; + +bool do_step = false; +int do_quit = 0; + +void quit(int) +{ + do_quit = 1; +} + +void goon(int) +{ +} + +#define ONE_STEP(MSG) \ +do { \ + DBG << "======================================" << std::endl; \ + DBG << "==>> " << MSG << std::endl; \ + DBG << "======================================" << std::endl; \ + if( do_step) { pause(); if( do_quit) exit(0); } \ +} while(0); + +BOOST_AUTO_TEST_CASE(strange_test) +{ + { + struct sigaction sa; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sa.sa_handler = goon; + sigaction(SIGINT, &sa, NULL); + sa.sa_handler = quit; + sigaction(SIGTERM, &sa, NULL); + +// if( argc > 1 && std::string(argv[1]) == "-i") +// do_step = true; + } + + MediaManager mm; + media::MediaId id; + zypp::Url url; + Pathname dir("./suse/setup/descr"); + + url = "cd:/"; + + try + { + ONE_STEP("open " + url.asString()); + id = mm.open(url); + + ONE_STEP("attach") + mm.attach(id); + + ONE_STEP("provideDirTree(" + dir.asString() + ")"); + mm.provideDirTree(id, Pathname(dir)); + + ONE_STEP("Create a temporary dir"); + zypp::filesystem::TmpDir temp; + + ONE_STEP("Create a copy of " + dir.asString()); + zypp::filesystem::copy_dir(mm.localPath(id, dir), temp.path()); + + std::string cmd("/bin/ls -lR "); + cmd += temp.path().asString(); + + ONE_STEP("Check the directory copy") + system( cmd.c_str()); + + ONE_STEP("CLEANUP") + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + } + catch( ... ) + { + // hmm... + ERR << "Catched *unknown* exception" << std::endl; + } +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/media/metalink/metalink.dockerfile b/tests/media/metalink/metalink.dockerfile new file mode 100644 index 0000000..2c75150 --- /dev/null +++ b/tests/media/metalink/metalink.dockerfile @@ -0,0 +1,38 @@ +FROM opensuse/leap:15.4 +ENV container docker + +ENV LANG en_US.UTF-8 + +RUN zypper ar -f http://download.opensuse.org/repositories/openSUSE:infrastructure:MirrorCache/15.4 mc +RUN zypper --gpg-auto-import-keys ref + +# install MirrorCache here to fetch all dependencies +RUN zypper -vvv -n install MirrorCache \ + vim postgresql postgresql-server curl sudo git-core wget tar m4 make \ + perl-Digest-MD4 tidy perl-DateTime-HiRes \ + perl-Inline-C gcc # dependencies for hashes calculation + +WORKDIR /opt/project +ENV TZ UTC + +# let pg initialize data dir in cache to save some time on every run +RUN sudo -u postgres /usr/share/postgresql/postgresql-script start && \ + sudo -u postgres createuser mirrorcache && \ + sudo -u postgres createdb mirrorcache && \ + sudo -u postgres /usr/share/postgresql/postgresql-script stop + +COPY testfile /opt/project/testfile + +ENV MIRRORCACHE_ROOT=/opt/project \ + MIRRORCACHE_PERMANENT_JOBS='' \ + MIRRORCACHE_HASHES_QUEUE=default \ + MIRRORCACHE_HASHES_COLLECT=1 + +RUN echo 100 # change this number to invalidate docker cache + +RUN sudo -u postgres /usr/share/postgresql/postgresql-script start && \ + sudo -u mirrorcache -E /usr/share/mirrorcache/script/mirrorcache minion job -e folder_sync -a '["/"]' && \ + sudo -u mirrorcache -E /usr/share/mirrorcache/script/mirrorcache backstage run --oneshot && \ + ( sudo -u mirrorcache -E /usr/share/mirrorcache/script/mirrorcache daemon & ) && \ + sleep 5 && \ + curl -is 127.0.0.1:3000/download/testfile.meta4 diff --git a/tests/media/mymediaverifier.h b/tests/media/mymediaverifier.h new file mode 100644 index 0000000..5f48136 --- /dev/null +++ b/tests/media/mymediaverifier.h @@ -0,0 +1,65 @@ + +#ifndef TEST_MYMEDIAVERIFIER +#define TEST_MYMEDIAVERIFIER + +#include +#include +#include +#include + +using namespace zypp; +using namespace zypp::media; + +/* +** Very basic example verifier. +** +** This one does not know anything about the product, it +** just checks if /media.1 (limited to 1st CD) exists... +*/ +class MyMediaVerifier: public MediaVerifierBase +{ + private: + // std::string _productname; + public: + MyMediaVerifier(/* std::string &productname */) + : MediaVerifierBase() + //, _productname(productname) + {} + + virtual + ~MyMediaVerifier() + {} + + virtual bool + isDesiredMedia(const MediaAccessRef &ref) + { + DBG << "isDesiredMedia(): for media nr 1 " << std::endl; + + if( !ref) + DBG << "isDesiredMedia(): invalid media handle" << std::endl; + + std::list lst; + Pathname dir("/media.1"); + + DBG << "isDesiredMedia(): checking " << dir.asString() << std::endl; + + // check the product e.g. via /media.1/products as well... + try + { + if( ref) + ref->dirInfo(lst, dir, false); + } + catch(const zypp::Exception &e) + { + ZYPP_CAUGHT(e); + } + DBG << "isDesiredMedia(): media " + << (lst.empty() ? "does not contain" : "contains") + << " the " << dir.asString() << " directory." + << std::endl; + + return !lst.empty(); + } +}; + +#endif diff --git a/tests/media/throw_if_not_exists_test.cc b/tests/media/throw_if_not_exists_test.cc new file mode 100644 index 0000000..66bf001 --- /dev/null +++ b/tests/media/throw_if_not_exists_test.cc @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include "mymediaverifier.h" + +using namespace zypp; +using namespace zypp::media; + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +BOOST_AUTO_TEST_CASE(http_test) +{ + //MediaVerifierRef verifier( new MyMediaVerifier() ); + MediaManager mm; + media::MediaId id; + + Url url("http://www.google.com"); + + id = mm.open( url, ""); + //mm.addVerifier( id, verifier); + mm.attach(id); + BOOST_CHECK_THROW( mm.provideFile(id, Pathname("/file-not-exists")), Exception ); + mm.release(id); +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/parser/CMakeLists.txt b/tests/parser/CMakeLists.txt new file mode 100644 index 0000000..ccf3994 --- /dev/null +++ b/tests/parser/CMakeLists.txt @@ -0,0 +1,7 @@ +ADD_SUBDIRECTORY( yum ) +ADD_SUBDIRECTORY( inifile ) + +ADD_TESTS( ProductFileReader ) +ADD_TESTS( RepoFileReader ) +ADD_TESTS( RepoindexFileReader ) +ADD_TESTS( HistoryLogReader ) diff --git a/tests/parser/HistoryLogReader_test.cc b/tests/parser/HistoryLogReader_test.cc new file mode 100644 index 0000000..e0eb53f --- /dev/null +++ b/tests/parser/HistoryLogReader_test.cc @@ -0,0 +1,40 @@ +#include "TestSetup.h" +#include +#include + +using namespace zypp; + +BOOST_AUTO_TEST_CASE(basic) +{ + std::vector history; + parser::HistoryLogReader parser( TESTS_SRC_DIR "/parser/HistoryLogReader_test.dat", + parser::HistoryLogReader::Options(), + [&history]( HistoryLogData::Ptr ptr )->bool { + history.push_back( ptr ); + return true; + } ); + + BOOST_CHECK_EQUAL( parser.ignoreInvalidItems(), false ); + BOOST_CHECK_THROW( parser.readAll(), parser::ParseException ); + + parser.setIgnoreInvalidItems( true ); + BOOST_CHECK_EQUAL( parser.ignoreInvalidItems(), true ); + + history.clear(); + parser.readAll(); + + BOOST_CHECK_EQUAL( history.size(), 9 ); + BOOST_CHECK( dynamic_pointer_cast ( history[0] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[1] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[2] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[3] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[4] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[5] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[6] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[7] ) ); + BOOST_CHECK( dynamic_pointer_cast ( history[8] ) ); + + BOOST_CHECK_EQUAL( (*history[1])[HistoryLogDataInstall::USERDATA_INDEX], "trans|ID" ); // properly (un)escaped? + HistoryLogDataInstall::Ptr p = dynamic_pointer_cast( history[1] ); + BOOST_CHECK_EQUAL( p->userdata(), "trans|ID" ); // properly (un)escaped? +} diff --git a/tests/parser/HistoryLogReader_test.dat b/tests/parser/HistoryLogReader_test.dat new file mode 100644 index 0000000..b8b2deb --- /dev/null +++ b/tests/parser/HistoryLogReader_test.dat @@ -0,0 +1,14 @@ +2009-09-29 07:24:46|radd |InstallationImage|file:/usr/src/packages/BUILD/openSUSE-images-11.2/gnome_cd/home/rpmdir| +2009-09-29 07:25:29|install|update-test-security|0-2.35|noarch|root@opensuse|InstallationImage|d99de2872270cbd436b0c10af85c286a1365a348|trans\|ID +2011-07-18 18:08:09|install|kernel-source|2.6.37.6-0.5.1|noarch||repo-update|7823612d9ca3de086c2cd4dca936f6a3f3e9313d| +# 2009-09-29 07:25:30 filesystem.rpm installed ok +# Additional rpm output: +# +2009-09-29 07:47:59|remove |PolicyKit-doc|0.9-15.20|x86_64|root@opensuse|trans\|ID +2009-09-29 07:47:32|rremove|InstallationImage| +2010-06-01 16:11:17|remove |xchat-python|2.8.6-43.13|x86_64|2848:y2base| +2010-06-01 16:11:17|bad |unknown action field +discard\|one field +discard|to fields but bad date +2015-08-11 18:42:49|command|root@fibonacci|'/Local/ma/zypp/BUILD/zypper/src/zypper' 'in' '-f' 'xteddy'| +2011-07-18 18:08:09|patch|patch-name|2.6.37.6-0.5.1|noarch|repo-update|moderate|security|needed|applied| diff --git a/tests/parser/ProductFileReader_test.cc b/tests/parser/ProductFileReader_test.cc new file mode 100644 index 0000000..568b1d2 --- /dev/null +++ b/tests/parser/ProductFileReader_test.cc @@ -0,0 +1,47 @@ +#include "TestSetup.h" +#include + +//TestSetup test( TestSetup::initLater ); +//struct TestInit { +// TestInit() { +// test = TestSetup( Arch_x86_64 ); +// } +// ~TestInit() { test.reset(); } +//}; +//BOOST_GLOBAL_FIXTURE( TestInit ); + +// Must be the first test! +BOOST_AUTO_TEST_CASE(basic) +{ + parser::ProductFileData data; + BOOST_CHECK( data.empty() ); + + data = parser::ProductFileReader::scanFile( TESTS_SRC_DIR "/parser/ProductFileReader_test.dat" ); + BOOST_REQUIRE( ! data.empty() ); + + BOOST_CHECK_EQUAL( data.vendor(), "Novell" ); + BOOST_CHECK_EQUAL( data.name(), "SUSE_SLES" ); + BOOST_CHECK_EQUAL( data.edition(), "11-0" ); + BOOST_CHECK_EQUAL( data.arch(), Arch_i586 ); + BOOST_CHECK_EQUAL( data.productline(), "" ); + BOOST_CHECK_EQUAL( data.registerTarget(), "sle-11-i586" ); + BOOST_CHECK_EQUAL( data.registerRelease(), "whatever" ); + BOOST_CHECK_EQUAL( data.registerFlavor(), "module" ); + BOOST_CHECK_EQUAL( data.updaterepokey(), "A43242DKD" ); + + BOOST_REQUIRE_EQUAL( data.upgrades().size(), 2 ); + + BOOST_CHECK_EQUAL( data.upgrades()[0].name(), "openSUSE_11.1" ); + BOOST_CHECK_EQUAL( data.upgrades()[0].summary(), "openSUSE 11.1" ); + BOOST_CHECK_EQUAL( data.upgrades()[0].repository(), "http://download.opensuse.org/distribution/openSUSE/11.1" ); + BOOST_CHECK_EQUAL( data.upgrades()[0].product(), "used on entreprise products" ); + BOOST_CHECK_EQUAL( data.upgrades()[0].notify(), true ); + BOOST_CHECK_EQUAL( data.upgrades()[0].status(), "stable" ); + + BOOST_CHECK_EQUAL( data.upgrades()[1].name(), "openSUSE_Factory" ); + BOOST_CHECK_EQUAL( data.upgrades()[1].summary(), "openSUSE Factory" ); + BOOST_CHECK_EQUAL( data.upgrades()[1].repository(), "http://download.opensuse.org/distribution/openSUSE/Factory" ); + BOOST_CHECK_EQUAL( data.upgrades()[1].product(), "" ); + BOOST_CHECK_EQUAL( data.upgrades()[1].notify(), false ); + BOOST_CHECK_EQUAL( data.upgrades()[1].status(), "unstable" ); +} diff --git a/tests/parser/ProductFileReader_test.dat b/tests/parser/ProductFileReader_test.dat new file mode 100644 index 0000000..74d36c0 --- /dev/null +++ b/tests/parser/ProductFileReader_test.dat @@ -0,0 +1,61 @@ + + + Novell + SUSE_SLES + 11 + 0 + i586 + A43242DKD +

SUSE Linux Enterprise Server + +This is the Server product of the SUSE Linux Enterprise edition. It is an alternative product for the Windows Server and other UNIX Operating Systems, providing Server functionality and interoperability with UNIX servers. This is the replacement product intended to sunset SUSE Linux Enterprise Server10 which was introduced in May of 2006 + The SUSE Linux Enterprise Server 11 addresses very large enterprises as well as large enterprises and in some ways also medium, small, government and educational needs for a secure, stable, reliable and high-performance operating system platform. + It is the core and base offering to provide a general-purpose infrastructure solution. This offering is engineered, tested and proven to handle mission-critical workloads in the data center. + Developed and backed by Novell, only SUSE Linux Enterprise Server offers an open, scalable, high-performance data center solution that comes with application security, virtualization and Integrated systems management across a range of hardware architectures. + SUSE Linux Enterprise Server is deployable as a general-purpose server or can be tailored to run a variety of specialized workloads, and it offers seamless interoperability with your existing data center infrastructure. + + + http://www.novell.com/linux/releasenotes/i586/SUSE-SLES/11/release-notes-sles.rpm + + + + + openSUSE_11.1 + openSUSE 11.1 + http://download.opensuse.org/distribution/openSUSE/11.1 + used on entreprise products + true + stable + + + openSUSE_Factory + openSUSE Factory + http://download.opensuse.org/distribution/openSUSE/Factory + no + unstable + + + + + sle-11-i586 + whatever + module + + + + SLES + false + + + + en_US + + suse + suse/setup/descr + + SUSE_SLE + + + + + diff --git a/tests/parser/RepoFileReader_test.cc b/tests/parser/RepoFileReader_test.cc new file mode 100644 index 0000000..6b861d0 --- /dev/null +++ b/tests/parser/RepoFileReader_test.cc @@ -0,0 +1,58 @@ +#include +#include +#include +#include + +#include "TestSetup.h" + +using std::stringstream; +using std::string; +using namespace zypp; + +static std::string suse_repo = "[factory-oss]\n" +"name=factory-oss $releasever - $basearch\n" +"failovermethod=priority\n" +"enabled=1\n" +"gpgcheck=1\n" +"autorefresh=0\n" +"baseurl=http://serv.er/loc1\n" +"baseurl=http://serv.er/loc2\n" +" http://serv.er/loc3 , http://serv.er/loc4 http://serv.er/loc5\n" +"gpgkey=http://serv.er/loc1\n" +"gpgkey=http://serv.er/loc2\n" +" http://serv.er/loc3 , http://serv.er/loc4 http://serv.er/loc5\n" +"mirrorlist=http://serv.er/loc1\n" +"mirrorlist=http://serv.er/loc2\n" +" http://serv.er/loc3 , http://serv.er/loc4 http://serv.er/loc5\n" +"type=NONE\n" +"keeppackages=0\n"; + +struct RepoCollector : private base::NonCopyable +{ + bool collect( const RepoInfo &repo ) + { + repos.push_back(repo); + return true; + } + + RepoInfoList repos; +}; + +// Must be the first test! +BOOST_AUTO_TEST_CASE(read_repo_file) +{ + { + std::stringstream input(suse_repo); + RepoCollector collector; + parser::RepoFileReader parser( input, bind( &RepoCollector::collect, &collector, _1 ) ); + BOOST_CHECK_EQUAL(1, collector.repos.size()); + + const RepoInfo & repo( collector.repos.front() ); + + BOOST_CHECK_EQUAL( 5, repo.baseUrlsSize() ); + BOOST_CHECK_EQUAL( 5, repo.gpgKeyUrlsSize() ); + BOOST_CHECK_EQUAL( Url("http://serv.er/loc1"), repo.url() ); + BOOST_CHECK_EQUAL( Url("http://serv.er/loc1"), repo.gpgKeyUrl() ); + BOOST_CHECK_EQUAL( Url("http://serv.er/loc1"), repo.mirrorListUrl() ); + } +} diff --git a/tests/parser/RepoindexFileReader_test.cc b/tests/parser/RepoindexFileReader_test.cc new file mode 100644 index 0000000..25b68ff --- /dev/null +++ b/tests/parser/RepoindexFileReader_test.cc @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include + +#include "TestSetup.h" + +using std::stringstream; +using std::string; +using namespace zypp; + +static string service = "" + "" + "" + "" + ""; + +struct RepoCollector : private base::NonCopyable +{ + bool collect( const RepoInfo &repo ) + { + repos.push_back(repo); + return true; + } + + RepoInfoList repos; +}; + +// Must be the first test! +BOOST_AUTO_TEST_CASE(read_index_file) +{ + { + stringstream input(service); + RepoCollector collector; + parser::RepoindexFileReader parser( input, bind( &RepoCollector::collect, &collector, _1 ) ); + BOOST_REQUIRE_EQUAL(3, collector.repos.size()); + + RepoInfo repo; + repo = collector.repos.front(); + + BOOST_CHECK_EQUAL("Company's Foo", repo.name()); + BOOST_CHECK_EQUAL("company-foo", repo.alias()); + BOOST_CHECK_EQUAL("sle-11-i386", repo.targetDistribution()); + BOOST_CHECK_EQUAL(20, repo.priority()); + // "Repository is per default disabled" + BOOST_CHECK(!repo.enabled()); + // "Repository autorefresh is per default enabled" + BOOST_CHECK(repo.autorefresh()); + BOOST_CHECK_EQUAL("/repo/products/foo", repo.path()); + + collector.repos.pop_front( ); + repo = collector.repos.front(); + + BOOST_CHECK_EQUAL("company-bar", repo.alias()); + BOOST_CHECK_EQUAL("sle-11-i386", repo.targetDistribution()); + // "Priority should be 99 when not explictly defined" + BOOST_CHECK_EQUAL(99, repo.priority()); + // "Repository is explicitly enabled" + BOOST_CHECK(repo.enabled()); + // "Repository autorefresh is explicitly disabled" + BOOST_CHECK(!repo.autorefresh()); + + + } +} diff --git a/tests/parser/inifile/CMakeLists.txt b/tests/parser/inifile/CMakeLists.txt new file mode 100644 index 0000000..25e1113 --- /dev/null +++ b/tests/parser/inifile/CMakeLists.txt @@ -0,0 +1,2 @@ + +ADD_TESTS(inidict iniparser) \ No newline at end of file diff --git a/tests/parser/inifile/data/1.ini b/tests/parser/inifile/data/1.ini new file mode 100644 index 0000000..b53fd48 --- /dev/null +++ b/tests/parser/inifile/data/1.ini @@ -0,0 +1,54 @@ +[base] +name=CentOS-$releasever - Base +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os +baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/ +gpgcheck=1 +gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 +protect=1 + +#released updates +[update] +name=CentOS-$releasever - Updates +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates +baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/ +gpgcheck=1 +gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 +protect=1 + +#packages used/produced in the build but not released +[addons] +name=CentOS-$releasever - Addons +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=addons +baseurl=http://mirror.centos.org/centos/$releasever/addons/$basearch/ +gpgcheck=1 +gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 +protect=0 + +#additional packages that may be useful +[extras] +name=CentOS-$releasever - Extras +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras +baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/ +gpgcheck=1 +gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 +protect=0 + +#additional packages that extend functionality of existing packages +[centosplus] +name=CentOS-$releasever - Plus +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus +baseurl=http://mirror.centos.org/centos/$releasever/centosplus/$basearch/ +gpgcheck=1 +enabled=0 +gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 +protect=0 + +#contrib - packages by Centos Users +[contrib] +name=CentOS-$releasever - Contrib +mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib +baseurl=http://mirror.centos.org/centos/$releasever/contrib/$basearch/ +gpgcheck=1 +enabled=0 +gpgkey=http://mirror.centos.org/centos/RPM-GPG-KEY-centos4 +protect=0 \ No newline at end of file diff --git a/tests/parser/inifile/data/2.ini b/tests/parser/inifile/data/2.ini new file mode 100644 index 0000000..36d21c8 --- /dev/null +++ b/tests/parser/inifile/data/2.ini @@ -0,0 +1,12 @@ +[base] +name=foo +name= foo +name =foo +name = foo +[equal] +name1==foo +name1= =foo +name2=f=oo +name3=foo= +[te]st] +name=foo diff --git a/tests/parser/inifile/inidict_test.cc b/tests/parser/inifile/inidict_test.cc new file mode 100644 index 0000000..0f67687 --- /dev/null +++ b/tests/parser/inifile/inidict_test.cc @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using std::cout; +using std::endl; +using std::string; +using std::map; +using namespace zypp; +using namespace zypp::parser; +using namespace boost::unit_test; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/parser/inifile/data") + +BOOST_AUTO_TEST_CASE(ini_read) +{ + InputStream is((DATADIR+"/1.ini")); + IniDict dict(is); + + //MIL << dict["homedmacvicar"]["type"] << endl; + + for ( IniDict::section_const_iterator it = dict.sectionsBegin(); it != dict.sectionsEnd(); ++it ) + { + MIL << (*it) << endl; + + for ( IniDict::entry_const_iterator it2 = dict.entriesBegin(*it); it2 != dict.entriesEnd(*it); ++it2 ) + { + MIL << " - " << (*it2).first << " | " << (*it2).second << endl; + } + } + + BOOST_CHECK( dict.hasSection("addons") ); + BOOST_CHECK( !dict.hasSection("uhlala") ); + BOOST_CHECK( dict.hasEntry("contrib", "name") ); + BOOST_CHECK( !dict.hasEntry("foo", "bar") ); +} + +BOOST_AUTO_TEST_CASE(ini_read2) +{ + InputStream is((DATADIR+"/2.ini")); + IniDict dict(is); + + BOOST_CHECK( find( dict.sectionsBegin(), dict.sectionsEnd(), "base" ) != dict.sectionsEnd() ); + //IniDict::entry_const_iterator i = find( dict.entriesBegin("base"), dict.entriesEnd("base"), "name"); + //BOOST_CHECK( i != dict.entriesEnd("base") ); +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/parser/inifile/iniparser_test.cc b/tests/parser/inifile/iniparser_test.cc new file mode 100644 index 0000000..0039478 --- /dev/null +++ b/tests/parser/inifile/iniparser_test.cc @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace zypp::parser; +using namespace boost::unit_test; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/parser/inifile/data") + +class IniTest : public IniParser +{ + virtual void consume( const std::string §ion ) + { + MIL << section << endl; + } + + virtual void consume( const std::string §ion, const std::string &key, const std::string &value ) + { + MIL << "'" << section << "'" << " | " << "'" << key << "'" << " | " << "'" << value << "'" << endl; + if (section == "base" && key == "gpgcheck") + BOOST_CHECK_EQUAL(value, "1"); + } +}; + + +class WithSpacesTest : public IniParser +{ + virtual void consume( const std::string §ion ) + { + MIL << section << endl; + BOOST_CHECK(section == "base" || section == "equal" || section == "te]st"); + } + + virtual void consume( const std::string §ion, const std::string &key, const std::string &value ) + { + MIL << "'" << section << "'" << " | " << "'" << key << "'" << " | " << "'" << value << "'" << endl; + if ( section == "base") + { + if ( key == "name" ) + BOOST_CHECK_EQUAL( value, "foo" ); + } + else if ( section == "equal" ) + { + if ( key == "name1" ) + BOOST_CHECK_EQUAL( value, "=foo" ); + else if ( key == "name2" ) + BOOST_CHECK_EQUAL( value, "f=oo" ); + else if ( key == "name3" ) + BOOST_CHECK_EQUAL( value, "foo=" ); + else + { + cout << "'" << section << "'" << " | " << "'" << key << "'" << " | " << "'" << value << "'" << endl; + BOOST_CHECK_MESSAGE( false, "Unhandled key" ); + } + } + } +}; + +BOOST_AUTO_TEST_CASE(ini_read) +{ + InputStream is((DATADIR+"/1.ini")); + IniTest parser; + parser.parse(is); +} + +BOOST_AUTO_TEST_CASE(ini_spaces_test) +{ + InputStream is((DATADIR+"/2.ini")); + WithSpacesTest parser; + parser.parse(is); +} diff --git a/tests/parser/yum/CMakeLists.txt b/tests/parser/yum/CMakeLists.txt new file mode 100644 index 0000000..2d697c9 --- /dev/null +++ b/tests/parser/yum/CMakeLists.txt @@ -0,0 +1 @@ +ADD_TESTS(RepomdFileReader) diff --git a/tests/parser/yum/RepomdFileReader_test.cc b/tests/parser/yum/RepomdFileReader_test.cc new file mode 100644 index 0000000..5b0eddf --- /dev/null +++ b/tests/parser/yum/RepomdFileReader_test.cc @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using std::cout; +using std::endl; +using namespace zypp; +using namespace boost::unit_test; + +using namespace zypp::parser::yum; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "parser/yum/data") + +class Collector +{ +public: + Collector() + {} + + bool operator()( OnMediaLocation &&loc, const std::string &t ) + { + items.push_back( make_pair( t, std::move(loc) ) ); + return true; + } + + std::vector > items; +}; + +BOOST_AUTO_TEST_CASE(repomd_read) +{ + std::list entries; + if ( filesystem::readdir( entries, DATADIR, false ) != 0 ) + ZYPP_THROW(Exception("failed to read directory")); + + for ( std::list::const_iterator it = entries.begin(); it != entries.end(); ++it ) + { + Pathname file = *it; + if ( ( file.basename().substr(0, 6) == "repomd" ) && (file.extension() == ".xml" ) ) + { + cout << *it << endl; + + Collector collect; + RepomdFileReader r( file, std::ref(collect) ); + if ( file.basename() == "repomd-1.xml" ) { + BOOST_CHECK_EQUAL( r.keywords().size(), 7 ); + auto keyhints = r.keyhints(); + BOOST_CHECK_EQUAL( keyhints.size(), 5 ); + std::map check = { + { "gpg-pubkey-39db7c82-5847eb1f.asc", "FEAB502539D846DB2C0961CA70AF9E8139DB7C82" }, + { "gpg-pubkey-307e3d54-5aaa90a5.asc", "4E98E67519D98DC7362A" }, + { "gpg-pubkey-65176565-59787af5.asc", "637B32FF" }, + { "gpg-pubkey-3dbdc284-is OK", "3dbdc284" }, + { "gpg-pubkey-feab502539d846db2c0961ca70af9e8139db7c82-is OK as well", "feab502539d846db2c0961ca70af9e8139db7c82" }, + { "gpg-pubkey-536X4dd4-X is not a hexdigit", "must not occur" }, + }; + for ( const auto & hint : keyhints ) { + BOOST_CHECK_EQUAL( check[hint.first], hint.second ); + } + } + + std::ifstream ifs( file.extend(".solution").asString().c_str() ); + + unsigned int count = 0; + while ( ifs && !ifs.eof() ) + { + std::string dtype; + getline(ifs, dtype); + if ( dtype.empty() ) + break; + BOOST_REQUIRE( count < collect.items.size() ); + BOOST_CHECK_EQUAL( collect.items[count].first, dtype ); + + std::string checksum_type; + std::string checksum; + getline(ifs, checksum_type); + getline(ifs, checksum); + BOOST_CHECK_EQUAL( collect.items[count].second.checksum(), CheckSum(checksum_type, checksum) ); + + std::string loc; + getline(ifs, loc); + BOOST_CHECK_EQUAL( collect.items[count].second.filename(), Pathname(loc) ); + + count++; + } + BOOST_CHECK_EQUAL( collect.items.size(), count ); + } + } +} + + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/parser/yum/data/repomd-1.xml b/tests/parser/yum/data/repomd-1.xml new file mode 100644 index 0000000..787063a --- /dev/null +++ b/tests/parser/yum/data/repomd-1.xml @@ -0,0 +1,39 @@ + + + 1620840613 + + pool + gpg-pubkey-39db7c82-5847eb1f.asc?fpr=FEAB502539D846DB2C0961CA70AF9E8139DB7C82 + gpg-pubkey-307e3d54-5aaa90a5.asc?fpr=4E98E67519D98DC7362A + gpg-pubkey-65176565-59787af5.asc?fpr=637B32FF + gpg-pubkey-3dbdc284-is OK + gpg-pubkey-feab502539d846db2c0961ca70af9e8139db7c82-is OK as well + gpg-pubkey-536X4dd4-X is not a hexdigit + obsproduct://build.opensuse.org/openSUSE:Leap:15.3/Leap/15.3/x86_64 + openSUSE Leap 15.3 + + + + 63d86413540fbb2647e5b5de556d4e4b53f032d9 + 1176225512 + 63d86413540fbb2647e5b5de556d4e4b53f032d9 + + + + f76cb1f9f1963edc614848944b99e2664eba4b4a + 1176225558 + f9cf4f4520ebe75e4bd66c1572521b414dfea564 + + + + fd1ea55f143820333b702cda4f97b286daf65171 + 1176225549 + 3bfb8413a4698b86f632bb914f6dc8a4e3ac9660 + + + + 689fecabbb0907f51f5bb7211048e091c6f2bc84 + 1176225550 + ce38366eaded03cb8b3fdc64bb31ea5304e9901c + + diff --git a/tests/parser/yum/data/repomd-1.xml.solution b/tests/parser/yum/data/repomd-1.xml.solution new file mode 100644 index 0000000..fbd5911 --- /dev/null +++ b/tests/parser/yum/data/repomd-1.xml.solution @@ -0,0 +1,17 @@ +patches +sha1 +63d86413540fbb2647e5b5de556d4e4b53f032d9 +repodata/patches.xml +other +sha1 +f76cb1f9f1963edc614848944b99e2664eba4b4a +repodata/other.xml.gz +primary +sha1 +fd1ea55f143820333b702cda4f97b286daf65171 +repodata/primary.xml.gz +filelists +sha1 +689fecabbb0907f51f5bb7211048e091c6f2bc84 +repodata/filelists.xml.gz + diff --git a/tests/repo/CMakeLists.txt b/tests/repo/CMakeLists.txt new file mode 100644 index 0000000..69f5011 --- /dev/null +++ b/tests/repo/CMakeLists.txt @@ -0,0 +1,20 @@ +ADD_SUBDIRECTORY( yum ) +ADD_SUBDIRECTORY( susetags ) + +# to find the KeyRingTest receiver +INCLUDE_DIRECTORIES( ${LIBZYPP_SOURCE_DIR}/tests/zypp ) + +ADD_TESTS( + DUdata + ExtendedMetadata + PluginServices + RepoLicense + RepoSigcheck + RepoVariables +) + +IF( NOT DISABLE_MEDIABACKEND_TESTS ) +ADD_TESTS( + MirrorList +) +ENDIF() diff --git a/tests/repo/DUdata_test.cc b/tests/repo/DUdata_test.cc new file mode 100644 index 0000000..8794bf5 --- /dev/null +++ b/tests/repo/DUdata_test.cc @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "KeyRingTestReceiver.h" +#include "TestSetup.h" + +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::repo; +using namespace zypp::filesystem; + +#define TEST_DIR TESTS_SRC_DIR "/repo/susetags/data/dudata" + +PoolItem piFind( const std::string & name_r, const std::string & ver_r, bool installed_r = false ) +{ + PoolQuery q; + q.addDependency( sat::SolvAttr::name, name_r, Rel::EQ, Edition(ver_r) ); + q.setStatusFilterFlags( installed_r ? PoolQuery::INSTALLED_ONLY : PoolQuery::UNINSTALLED_ONLY ); + if ( q.size() != 1 ) + ZYPP_THROW(Exception(q.size()?"Ambiguous!":"Missing!")); + return PoolItem( *q.begin() ); +} + +typedef std::pair ByteSet; +namespace std +{ + inline std::ostream & operator<<( std::ostream & str, const ByteSet & obj ) + { return str << "<" << obj.first << "," << obj.second << ">"; } +} + +inline ByteSet mkByteSet( const DiskUsageCounter::MountPointSet & mps_r ) +{ return ByteSet( mps_r.begin()->commitDiff(), (++mps_r.begin())->commitDiff() ); } + +inline ByteSet mkByteSet( int grow_r , int norm_r ) +{ return ByteSet( ByteCount( grow_r, ByteCount::K ), ByteCount( norm_r, ByteCount::K ) ); } + +inline ByteSet getSize( const DiskUsageCounter & duc_r, const PoolItem & pi_r ) +{ return mkByteSet( duc_r.disk_usage( pi_r ) ); } + +inline ByteSet getSize( const DiskUsageCounter & duc_r, const ResPool & pool_r ) +{ return mkByteSet( duc_r.disk_usage( pool_r ) ); } + +inline void XLOG( const DiskUsageCounter & duc_r, const ResPool & pool_r ) +{ + for( const auto & pi : pool_r ) + { + USR << pi << endl; + } + WAR << duc_r.disk_usage( pool_r ) << endl; +} + +BOOST_AUTO_TEST_CASE(dudata) +{ + //KeyRingTestReceiver rec; + // rec.answerAcceptUnknownKey(true); + //rec.answerAcceptUnsignedFile(true); + // rec.answerImportKey(true); + + Pathname repodir( TEST_DIR ); + TestSetup test( Arch_x86_64 ); + test.loadTargetRepo( repodir/"system" ); + test.loadRepo( repodir/"repo", "repo" ); + + ResPool pool( ResPool::instance() ); + PoolItem ins( piFind( "dutest", "1.0", true ) ); + PoolItem up1( piFind( "dutest", "1.0" ) ); + PoolItem up2( piFind( "dutest", "2.0" ) ); + PoolItem up3( piFind( "dutest", "3.0" ) ); + + DiskUsageCounter duc( { DiskUsageCounter::MountPoint( "/grow", DiskUsageCounter::MountPoint::Hint_growonly ), + DiskUsageCounter::MountPoint( "/norm" ) } ); + //XLOG( duc, pool ); + + BOOST_CHECK_EQUAL( getSize( duc, ins ), mkByteSet( 5, 5 ) ); + BOOST_CHECK_EQUAL( getSize( duc, up1 ), mkByteSet( 15, 15 ) ); + BOOST_CHECK_EQUAL( getSize( duc, up2 ), mkByteSet( 45, 45 ) ); + BOOST_CHECK_EQUAL( getSize( duc, up3 ), mkByteSet( 0, 0 ) ); + + // delete installed size 5 g n + ins.status().setTransact( true, ResStatus::USER ); + BOOST_CHECK_EQUAL( getSize( duc, pool ), mkByteSet( 0, -5 ) ); + ins.status().setTransact( false, ResStatus::USER ); + + // install known DU size 15 g n + up1.status().setTransact( true, ResStatus::USER ); + BOOST_CHECK_EQUAL( getSize( duc, pool ), mkByteSet( 15, 15 ) ); // (multi)install (old stays) + ins.status().setTransact( true, ResStatus::USER ); + BOOST_CHECK_EQUAL( getSize( duc, pool ), mkByteSet( 15, 10 ) ); // update (old goes) + ins.status().setTransact( false, ResStatus::USER ); + up1.status().setTransact( false, ResStatus::USER ); + + // install unknown DU size 0/installed g n + up3.status().setTransact( true, ResStatus::USER ); + BOOST_CHECK_EQUAL( getSize( duc, pool ), mkByteSet( 5, 0 ) ); // (multi)install (n could be 5 too, but satsolver does not know about multinstall) + ins.status().setTransact( true, ResStatus::USER ); + BOOST_CHECK_EQUAL( getSize( duc, pool ), mkByteSet( 5, 0 ) ); // update (old goes) + ins.status().setTransact( false, ResStatus::USER ); + up3.status().setTransact( false, ResStatus::USER ); +} diff --git a/tests/repo/ExtendedMetadata_test.cc b/tests/repo/ExtendedMetadata_test.cc new file mode 100644 index 0000000..b1fff04 --- /dev/null +++ b/tests/repo/ExtendedMetadata_test.cc @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include "KeyRingTestReceiver.h" + +#include "TestSetup.h" + +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::repo; +using namespace zypp::filesystem; + +#define TEST_DIR TESTS_SRC_DIR "/repo/yum/data/extensions" + +BOOST_AUTO_TEST_CASE(extended_metadata) +{ + KeyRingTestReceiver rec; + //rec.answerAcceptUnknownKey(true); + rec.answerAcceptUnsignedFile(true); + + +// rec.answerImportKey(true); + Pathname repodir(TEST_DIR ); + + sat::Pool pool(sat::Pool::instance()); + + TestSetup test( Arch_x86_64 ); + test.loadRepo(repodir.absolutename().asDirUrl(), "updates"); + + Repository repo = pool.reposFind("updates"); + + BOOST_CHECK_EQUAL( repo.generatedTimestamp(), Date(1227279057) ); + BOOST_CHECK_EQUAL( repo.suggestedExpirationTimestamp(), Date(1227279057 + 3600) ); + + // check that the attributes of product compatibility are ok + int count = 0; + std::vector cpeids; + std::vector labels; + + for_( it, + repo.compatibleWithProductBegin(), + repo.compatibleWithProductEnd() ) + { + cpeids.push_back(it.cpeId()); + labels.push_back(it.label()); + count++; + } + + // there were 2 compatible products + BOOST_CHECK_EQUAL( count, 2 ); + BOOST_CHECK_EQUAL( cpeids[0], "cpe:/o:opensuse" ); + BOOST_CHECK_EQUAL( cpeids[1], "cpe:/o:sle" ); + + BOOST_CHECK_EQUAL( labels[0], "openSUSE 11.0" ); + BOOST_CHECK_EQUAL( labels[1], "SLE 11.0" ); + + cpeids.clear(); + labels.clear(); + count = 0; + + for_( it, + repo.updatesProductBegin(), + repo.updatesProductEnd() ) + { + cpeids.push_back(it.cpeId()); + labels.push_back(it.label()); + count++; + } + + // the repo updates one product + BOOST_CHECK_EQUAL( count, 1 ); + BOOST_CHECK_EQUAL( cpeids[0], "cpe:/o:sle" ); + BOOST_CHECK_EQUAL( labels[0], "SLE 11.0" ); + + // because this product updates something, it _is_ an update repo + BOOST_CHECK( repo.isUpdateRepo() ); + + BOOST_CHECK( repo.providesUpdatesFor(CpeId("cpe:/o:sle")) ); + BOOST_CHECK( ! repo.providesUpdatesFor(CpeId("cpe:/o:windows")) ); + // reuse to count solvables + count = 0; + + /** + * Now check for the extended metadata of the packages + */ + for_( it, repo.solvablesBegin(), repo.solvablesEnd() ) + { + sat::Solvable s = *it; + MIL << s << endl; + MIL << s.kind() << endl; + if ( s.ident() == "wt" ) + { + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + BOOST_CHECK(p->maybeUnsupported() ); + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportUnknown ); + + } + else if ( s.ident() == "foobar" ) + { + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportUnsupported ); + BOOST_CHECK(p->maybeUnsupported() ); + } + else if ( s.ident() == "foofoo" ) + { + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + // if it is level 3 support it cant be unsupported + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportLevel3 ); + BOOST_CHECK(! p->maybeUnsupported() ); + } + // superseded chains.... + // oldfoo -> newfoo -> superfoo(L3) + // foomess -> superfoo(L3) + // -> brokenfoo -> foomess(cycle) + // -> notexists + else if ( s.ident() == "oldfoo" ) + { + // oldfoo -> newfoo -> superfoo(L3) + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + // if it is superseeded it counts as maybeUnsuopported + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportSuperseded ); + BOOST_CHECK( p->maybeUnsupported() ); + const auto & supersededBy { p->supersededBy() }; + BOOST_CHECK_EQUAL( supersededBy.size(), 1 ); + BOOST_CHECK_EQUAL( supersededBy[0], "newfoo" ); + const auto & supersededByItems { p->supersededByItems() }; + BOOST_CHECK_EQUAL( supersededByItems.first.size(), 1 ); + BOOST_CHECK_EQUAL( supersededByItems.first[0], "superfoo" ); + BOOST_CHECK_EQUAL( supersededByItems.second.size(), 0 ); + } + else if ( s.ident() == "newfoo" ) + { + // oldfoo -> newfoo -> superfoo(L3) + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + // if it is superseeded it counts as maybeUnsuopported + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportSuperseded ); + BOOST_CHECK( p->maybeUnsupported() ); + const auto & supersededBy { p->supersededBy() }; + BOOST_CHECK_EQUAL( supersededBy.size(), 1 ); + BOOST_CHECK_EQUAL( supersededBy[0], "superfoo" ); + const auto & supersededByItems { p->supersededByItems() }; + BOOST_CHECK_EQUAL( supersededByItems.first.size(), 1 ); + BOOST_CHECK_EQUAL( supersededByItems.first[0], "superfoo" ); + BOOST_CHECK_EQUAL( supersededByItems.second.size(), 0 ); + } + else if ( s.ident() == "superfoo" ) + { + // oldfoo -> newfoo -> superfoo(L3) + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportLevel3 ); + BOOST_CHECK( not p->maybeUnsupported() ); + const auto & supersededBy { p->supersededBy() }; + BOOST_CHECK_EQUAL( supersededBy.size(), 0 ); + const auto & supersededByItems { p->supersededByItems() }; + BOOST_CHECK_EQUAL( supersededByItems.first.size(), 0 ); + BOOST_CHECK_EQUAL( supersededByItems.second.size(), 0 ); + } + else if ( s.ident() == "foomess" ) + { + // foomess -> superfoo(L3) + // -> brokenfoo -> foomess(cycle) + // -> notexists + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + // if it is superseeded it counts as maybeUnsuopported + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportSuperseded ); + BOOST_CHECK( p->maybeUnsupported() ); + const auto & supersededBy { p->supersededBy() }; + BOOST_CHECK_EQUAL( supersededBy.size(), 2 ); + BOOST_CHECK_EQUAL( supersededBy[0], "brokenfoo" ); + BOOST_CHECK_EQUAL( supersededBy[1], "superfoo" ); + const auto & supersededByItems { p->supersededByItems() }; + BOOST_CHECK_EQUAL( supersededByItems.first.size(), 1 ); + BOOST_CHECK_EQUAL( supersededByItems.first[0], "superfoo" ); + BOOST_CHECK_EQUAL( supersededByItems.second.size(), 1 ); + BOOST_CHECK_EQUAL( supersededByItems.second[0], "notexists" ); + } + else if ( s.ident() == "brokenfoo" ) + { + // foomess -> superfoo(L3) + // -> brokenfoo -> foomess(cycle) + // -> notexists + count++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + // if it is superseeded it counts as maybeUnsuopported + BOOST_CHECK_EQUAL(p->vendorSupport(), VendorSupportSuperseded ); + BOOST_CHECK( p->maybeUnsupported() ); + const auto & supersededBy { p->supersededBy() }; + BOOST_CHECK_EQUAL( supersededBy.size(), 2 ); + BOOST_CHECK_EQUAL( supersededBy[0], "foomess" ); + BOOST_CHECK_EQUAL( supersededBy[1], "notexists" ); + const auto & supersededByItems { p->supersededByItems() }; + BOOST_CHECK_EQUAL( supersededByItems.first.size(), 1 ); + BOOST_CHECK_EQUAL( supersededByItems.first[0], "superfoo" ); + BOOST_CHECK_EQUAL( supersededByItems.second.size(), 1 ); + BOOST_CHECK_EQUAL( supersededByItems.second[0], "notexists" ); + } + else + { + BOOST_FAIL(str::form("Repo has package not contemplated in test: %s", s.ident().c_str()).c_str()); + } + + } + + // check that we actually found all testeable + // resolvables + BOOST_CHECK_EQUAL(count, 8); + +} diff --git a/tests/repo/MirrorList_test.cc b/tests/repo/MirrorList_test.cc new file mode 100644 index 0000000..89f8494 --- /dev/null +++ b/tests/repo/MirrorList_test.cc @@ -0,0 +1,33 @@ +#include +#include +#include + +#include "WebServer.h" + +#include + +using namespace zypp; +using namespace zypp::repo; + +BOOST_AUTO_TEST_CASE(get_mirrorlist) +{ + WebServer web((Pathname(TESTS_SRC_DIR) + "/data/Mirrorlist/remote-site").c_str(), 10001); + BOOST_REQUIRE( web.start() ); + + Url weburl1 (web.url()); + Url weburl2 (web.url()); + + weburl1.setPathName("/metalink.xml"); + weburl2.setPathName("/mirrors.txt"); + + RepoMirrorList rml1 (weburl1); + RepoMirrorList rml2 (weburl2); + + BOOST_CHECK(rml1.getUrls().begin()->asString() == "http://ftp-stud.hs-esslingen.de/pub/fedora/linux/updates/13/x86_64/"); + BOOST_CHECK(rml2.getUrls().begin()->asString() == "http://ftp-stud.hs-esslingen.de/pub/fedora/linux/updates/13/x86_64/"); + + BOOST_CHECK(rml1.getUrls().size() == 4); + BOOST_CHECK(rml2.getUrls().size() == 4); + + web.stop(); +} diff --git a/tests/repo/PluginServices_test.cc b/tests/repo/PluginServices_test.cc new file mode 100644 index 0000000..8fdd0c4 --- /dev/null +++ b/tests/repo/PluginServices_test.cc @@ -0,0 +1,52 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace boost::unit_test; +using namespace zypp::repo; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/repo/yum/data") + +class ServiceCollector +{ +public: + typedef std::set ServiceSet; + + ServiceCollector( ServiceSet & services_r ) + : _services( services_r ) + {} + + bool operator()( const ServiceInfo & service_r ) const + { + _services.insert( service_r ); + return true; + } + +private: + ServiceSet & _services; +}; + + +BOOST_AUTO_TEST_CASE(plugin_services) +{ + ServiceCollector::ServiceSet services; + + PluginServices local("/space/tmp/services", ServiceCollector(services)); +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/repo/RepoLicense/repo/repodata/CHECKSUM-license-prod.tar.gz b/tests/repo/RepoLicense/repo/repodata/CHECKSUM-license-prod.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..4cd30b4ec325d0430ad9a9a7bdf2195a8eaac910 GIT binary patch literal 373 zcmV-*0gC<~iwFQiqq1251MSz#Zh}A*24L1c1y3-Z8w|7PzRSJ>(J?X6E&vlBzel63 zVd^a*SnK%~k~k6|08937~L^#X0LtOltP21It-pUx)`hytqb+=r{H!MIZA1DNe7|>G{WTLC}=_(^Q z;J~CWt=g^5`sb2I^b&+7kA5<9i{aCrI?X@xA@?PH=U?;Q&p!!f`6!t@=6_vZ{$0Ci z&QfcPF~%5U Tj4{R-^Ur(%!9LJd04M+ec1Ohq literal 0 HcmV?d00001 diff --git a/tests/repo/RepoLicense/repo/repodata/CHECKSUM-license.tar.gz b/tests/repo/RepoLicense/repo/repodata/CHECKSUM-license.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..be793fe203433bd8511dcf031b9e9b78326778f5 GIT binary patch literal 384 zcmV-`0e}7oHioAg1oXcd)qWdoU3PUmlLDSMi@bP;r zwv|l1VTcvaw=m!_j3NBA)z8PZiQ`T)4KIE^AvDQCCHeYp%ReSEjiypvp$vC<7m8o+KpZ3&#{)u+EFYqV-lJ|c8ks-@R$>ewbSK;{Y z+I1U`&HJ0%o!H&~yp9^!M`RB6|8U#ECH;>DZ1ZpBp#49Br2pq&WN(%(myfjnEgN|_ zklh*akN%f)5m=rQ3h#A0xeLRmJ$17G(f0C>g(L0%G5q%bYgjKkP3?n8`@eachN_D1 zU1+K}ZDOorecc)t^*=hvKRYJv|1l)}@5snozH`o#Px?QZR)?pzzA|-=;nSWv+5gt| e^G~Gxuar_sDW#NBN-3q()jk1Wg6_=#C;$LwBF?`6 literal 0 HcmV?d00001 diff --git a/tests/repo/RepoLicense/repo/repodata/license.de.txt b/tests/repo/RepoLicense/repo/repodata/license.de.txt new file mode 100644 index 0000000..a6f30cf --- /dev/null +++ b/tests/repo/RepoLicense/repo/repodata/license.de.txt @@ -0,0 +1 @@ +license de diff --git a/tests/repo/RepoLicense/repo/repodata/license.fr.txt b/tests/repo/RepoLicense/repo/repodata/license.fr.txt new file mode 100644 index 0000000..763c099 --- /dev/null +++ b/tests/repo/RepoLicense/repo/repodata/license.fr.txt @@ -0,0 +1 @@ +license fr diff --git a/tests/repo/RepoLicense/repo/repodata/license.txt b/tests/repo/RepoLicense/repo/repodata/license.txt new file mode 100644 index 0000000..76478b3 --- /dev/null +++ b/tests/repo/RepoLicense/repo/repodata/license.txt @@ -0,0 +1 @@ +license default diff --git a/tests/repo/RepoLicense/repo/repodata/no-acceptance-needed b/tests/repo/RepoLicense/repo/repodata/no-acceptance-needed new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/RepoLicense/repo/repodata/repomd.xml b/tests/repo/RepoLicense/repo/repodata/repomd.xml new file mode 100644 index 0000000..6678b19 --- /dev/null +++ b/tests/repo/RepoLicense/repo/repodata/repomd.xml @@ -0,0 +1,11 @@ + + + + + 3a4013a12934c55f9a6b0c1b8db2ce6660840b1f7cbee95ec92a50c13c5b9e95 + + + + 3c0371f0a090e0ad6432c705798e7c5617b278e85cf382344e80c4dfaf07cffb + + diff --git a/tests/repo/RepoLicense_test.cc b/tests/repo/RepoLicense_test.cc new file mode 100644 index 0000000..17cad56 --- /dev/null +++ b/tests/repo/RepoLicense_test.cc @@ -0,0 +1,48 @@ +#include + +#include + +#include +#include +#include "TestSetup.h" + +using namespace boost::unit_test; +using namespace zypp; +using std::cout; +using std::endl; + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +const Pathname DATADIR( TESTS_SRC_DIR "/repo/RepoLicense" ); + +/////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(repolicense) +{ + std::string repo( "repo" ); + test.loadRepo( DATADIR/repo, repo ); + ResPool pool( ResPool::instance() ); + const RepoInfo & ri( pool.knownRepositoriesBegin()->info() ); + + std::string prod; // + BOOST_CHECK_EQUAL( ri.hasLicense( prod ), true ); + BOOST_CHECK_EQUAL( ri.needToAcceptLicense( prod ), false ); + BOOST_CHECK_EQUAL( ri.getLicenseLocales( prod ), LocaleSet({ Locale(),Locale("de") }) ); + + prod = "prod"; // + BOOST_CHECK_EQUAL( ri.hasLicense( prod ), true ); + BOOST_CHECK_EQUAL( ri.needToAcceptLicense( prod ), true ); + BOOST_CHECK_EQUAL( ri.getLicenseLocales( prod ), LocaleSet({ Locale(), Locale("de"), Locale("fr") }) ); + + prod = "noprod"; // is not available + BOOST_CHECK_EQUAL( ri.hasLicense( prod ), false ); + BOOST_CHECK_EQUAL( ri.needToAcceptLicense( prod ), false ); + BOOST_CHECK ( ri.getLicenseLocales( prod ).empty() ); +} diff --git a/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml b/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml new file mode 100644 index 0000000..a8265ad --- /dev/null +++ b/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml.asc b/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml.asc new file mode 100644 index 0000000..431df21 --- /dev/null +++ b/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 + +iJwEAAECAAYFAlkxg9AACgkQGg2gkyh1YAPSfAQAlimnC4dx6bCJyJxJb6BjECNA +HQBtDC4MEzQ+hDiXd6YL7wjI3fu3K9sclx2ypFb3vLkK5SHQysStWMmDOEgNA96I +iAuyyDVb3F24OiYOCcTKKViXAFTxykiC9dPFXdmA4vMjqcQYaxIkA17dFYvMjLLQ +5DdgmDuMS+Fv4xVjP8I= +=dzhU +-----END PGP SIGNATURE----- diff --git a/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml.key b/tests/repo/RepoSigcheck/signed_repo/repodata/repomd.xml.key new file mode 100644 index 0000000000000000000000000000000000000000..efe36ade26e1f89473bc161034f8584e403e7a25 GIT binary patch literal 363 zcmV-x0hIojjRaXSfX)E~0P$>FOK9WSZJe_0W!o@1LzFQx*zl^uViR0V$^Rm)A~_GlNWX zZek40a=8pylvHgtQ78vdl`cZv8{S0}Fy}T-G`|>;+*kOAs-CVgqW}>B00FcgdUxdamd0stcg0$DMD&H@_)2MY-Z2Ll2D z1{DYb2?`4Y76JnS0v-VZ7k~f?2@o0$ppz(dU;|291OIl?M5SSjX0ae0o@o*2JlqwM zx)n6rz$43!5aDxw+9<-Ae$hylch`Kl9Fp&hmCZt(pELMmY&%nM4`>_6;D8Fi>-$di zlK&`T3PxX0+Hh_W6=d+>&4%HdVD52a>$2;S-e$lj$wAll!YG@FrIL|4Hu2c`J7M6` J#;6>;I!$b#nvDPe literal 0 HcmV?d00001 diff --git a/tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml b/tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml new file mode 100644 index 0000000..a8265ad --- /dev/null +++ b/tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml.asc b/tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml.asc new file mode 100644 index 0000000..431df21 --- /dev/null +++ b/tests/repo/RepoSigcheck/unknownkey_repo/repodata/repomd.xml.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 + +iJwEAAECAAYFAlkxg9AACgkQGg2gkyh1YAPSfAQAlimnC4dx6bCJyJxJb6BjECNA +HQBtDC4MEzQ+hDiXd6YL7wjI3fu3K9sclx2ypFb3vLkK5SHQysStWMmDOEgNA96I +iAuyyDVb3F24OiYOCcTKKViXAFTxykiC9dPFXdmA4vMjqcQYaxIkA17dFYvMjLLQ +5DdgmDuMS+Fv4xVjP8I= +=dzhU +-----END PGP SIGNATURE----- diff --git a/tests/repo/RepoSigcheck/unsigned_repo/repodata/repomd.xml b/tests/repo/RepoSigcheck/unsigned_repo/repodata/repomd.xml new file mode 100644 index 0000000..a8265ad --- /dev/null +++ b/tests/repo/RepoSigcheck/unsigned_repo/repodata/repomd.xml @@ -0,0 +1,3 @@ + + + diff --git a/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml b/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml new file mode 100644 index 0000000..d06ab40 --- /dev/null +++ b/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml @@ -0,0 +1,4 @@ + + + + diff --git a/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml.asc b/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml.asc new file mode 100644 index 0000000..431df21 --- /dev/null +++ b/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml.asc @@ -0,0 +1,9 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2 + +iJwEAAECAAYFAlkxg9AACgkQGg2gkyh1YAPSfAQAlimnC4dx6bCJyJxJb6BjECNA +HQBtDC4MEzQ+hDiXd6YL7wjI3fu3K9sclx2ypFb3vLkK5SHQysStWMmDOEgNA96I +iAuyyDVb3F24OiYOCcTKKViXAFTxykiC9dPFXdmA4vMjqcQYaxIkA17dFYvMjLLQ +5DdgmDuMS+Fv4xVjP8I= +=dzhU +-----END PGP SIGNATURE----- diff --git a/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml.key b/tests/repo/RepoSigcheck/wrongsig_repo/repodata/repomd.xml.key new file mode 100644 index 0000000000000000000000000000000000000000..efe36ade26e1f89473bc161034f8584e403e7a25 GIT binary patch literal 363 zcmV-x0hIojjRaXSfX)E~0P$>FOK9WSZJe_0W!o@1LzFQx*zl^uViR0V$^Rm)A~_GlNWX zZek40a=8pylvHgtQ78vdl`cZv8{S0}Fy}T-G`|>;+*kOAs-CVgqW}>B00FcgdUxdamd0stcg0$DMD&H@_)2MY-Z2Ll2D z1{DYb2?`4Y76JnS0v-VZ7k~f?2@o0$ppz(dU;|291OIl?M5SSjX0ae0o@o*2JlqwM zx)n6rz$43!5aDxw+9<-Ae$hylch`Kl9Fp&hmCZt(pELMmY&%nM4`>_6;D8Fi>-$di zlK&`T3PxX0+Hh_W6=d+>&4%HdVD52a>$2;S-e$lj$wAll!YG@FrIL|4Hu2c`J7M6` J#;6>;I!$b#nvDPe literal 0 HcmV?d00001 diff --git a/tests/repo/RepoSigcheck_test.cc b/tests/repo/RepoSigcheck_test.cc new file mode 100644 index 0000000..0226f64 --- /dev/null +++ b/tests/repo/RepoSigcheck_test.cc @@ -0,0 +1,375 @@ +#include + +#include + +#include +#include +#include "TestSetup.h" + +using namespace boost::unit_test; +using namespace zypp; +using std::cout; +using std::endl; + +#define TC_VERBOSE 0 + +#define COUT if ( TC_VERBOSE ) std::cout +#define TAG COUT << "*** " << __PRETTY_FUNCTION__ << endl + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64, TSO_REPO_DEFAULT_GPG ); + getZYpp()->keyRing()->allowPreload( false ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); +const Pathname DATADIR( TESTS_SRC_DIR "/repo/RepoSigcheck" ); + +/////////////////////////////////////////////////////////////////// + +struct KeyRingReceiver : public callback::ReceiveReport +{ + typedef callback::ReceiveReport Base; + + KeyRingReceiver() { TAG; connect(); } + ~KeyRingReceiver() { TAG; } + + virtual void reportbegin() { TAG; cblistCheck( __FUNCTION__ ); } + virtual void reportend() { TAG; cblistCheck( __FUNCTION__ ); } + + virtual KeyTrust askUserToAcceptKey( const PublicKey &key, const KeyContext &keycontext = KeyContext() ) + { + TAG; cblistCheck( __FUNCTION__ ); + return Base::askUserToAcceptKey( key , keycontext ); + } + + virtual void infoVerify( const std::string & file_r, const PublicKeyData & keyData_r, const KeyContext &keycontext = KeyContext() ) + { + TAG; cblistCheck( __FUNCTION__ ); + return Base::infoVerify( file_r, keyData_r, keycontext ); + } + + virtual bool askUserToAcceptUnsignedFile( const std::string &file, const KeyContext &keycontext = KeyContext() ) + { + TAG; cblistCheck( __FUNCTION__ ); + return Base::askUserToAcceptUnsignedFile( file, keycontext ); + } + + virtual bool askUserToAcceptUnknownKey( const std::string &file, const std::string &id, const KeyContext &keycontext = KeyContext() ) + { + TAG; cblistCheck( __FUNCTION__ ); + return Base::askUserToAcceptUnknownKey( file, id, keycontext ); + } + + virtual bool askUserToAcceptVerificationFailed( const std::string &file, const PublicKey &key, const KeyContext &keycontext = KeyContext() ) + { + TAG; cblistCheck( __FUNCTION__ ); + return Base::askUserToAcceptVerificationFailed( file, key, keycontext ); + } + +public: + typedef std::list CallbackList; + + void cblistCheck( const std::string & cb_r ) + { + BOOST_CHECK_EQUAL( _cblist.empty(), false ); + if ( !_cblist.empty() ) + { + BOOST_CHECK_EQUAL( _cblist.front(), cb_r ); + _cblist.pop_front(); + } + } + + CallbackList _cblist; // expected callback sequence list + +} krCallback; + +inline std::string chr( const bool & v ) +{ return v ? "1" : "0"; } + +inline std::string chr( const TriBool & v ) +{ + return indeterminate(v) ? "*" : chr( bool(v) ); +} + +/////////////////////////////////////////////////////////////////// +/* + * Check the RepoInfo methods returning which checks to perform + * based on the global (zypp.conf) and local (.repo file) settings. + * + * *** See table in RepoInfo.h:'Repository gpgchecks' + */ +BOOST_AUTO_TEST_CASE(init) +{ + ZConfig & zcfg( ZConfig::instance() ); + + RepoInfo repo; + std::initializer_list tribools( { TriBool(indeterminate), TriBool(true), TriBool(false) } ); + + // global zconfig values... + for ( bool g_GpgCheck : { true, false } ) + { + zcfg.setGpgCheck( g_GpgCheck ); + for ( TriBool g_RepoGpgCheck : tribools ) + { + zcfg.setRepoGpgCheck( g_RepoGpgCheck ); + for ( TriBool g_PkgGpgCheck : tribools ) + { + zcfg.setPkgGpgCheck( g_PkgGpgCheck ); + + // .repo values + for ( TriBool r_GpgCheck : tribools ) + { + repo.setGpgCheck( r_GpgCheck ); + for ( TriBool r_RepoGpgCheck : tribools ) + { + repo.setRepoGpgCheck( r_RepoGpgCheck ); + for ( TriBool r_PkgGpgCheck : tribools ) + { + repo.setPkgGpgCheck( r_PkgGpgCheck ); + + // check the repo methods returning what to do: + bool cfgGpgCheck = indeterminate(r_GpgCheck) ? g_GpgCheck : bool(r_GpgCheck); + TriBool cfgRepoGpgCheck = indeterminate(r_GpgCheck) && indeterminate(r_RepoGpgCheck) ? g_RepoGpgCheck : r_RepoGpgCheck; + TriBool cfgPkgGpgCheck = indeterminate(r_GpgCheck) && indeterminate(r_PkgGpgCheck) ? g_PkgGpgCheck : r_PkgGpgCheck; +#if ( TC_VERBOSE ) + COUT << chr(cfgGpgCheck) << "\t" << chr(cfgRepoGpgCheck) << "\t" << chr(cfgPkgGpgCheck) + << "\t(" << chr(r_GpgCheck) << "," << chr(g_GpgCheck) << ")" + << "\t(" << chr(r_RepoGpgCheck) << "," << chr(g_RepoGpgCheck) << ")" + << "\t(" << chr(r_PkgGpgCheck) << "," << chr(g_PkgGpgCheck) << ")" + << flush; +#endif + + // default gpgCeck follows config + BOOST_CHECK_EQUAL( repo.gpgCheck(), cfgGpgCheck ); + + + // repoGpgCheck follows gpgCeck + // explicitly defined it alters mandatory check + bool willCheckRepo = repo.repoGpgCheck(); + bool mandatoryCheck = repo.repoGpgCheckIsMandatory(); +#if ( TC_VERBOSE ) + COUT << "\t" << ( willCheckRepo ? ( mandatoryCheck ? "!" : "+" ) : "-" ) << flush; +#endif + if ( mandatoryCheck ) // be a subset of willCheckRepo! + BOOST_CHECK_EQUAL( willCheckRepo, mandatoryCheck ); + + if ( cfgGpgCheck ) + { + BOOST_CHECK_EQUAL( willCheckRepo, true ); + BOOST_CHECK_EQUAL( mandatoryCheck, !bool(!cfgRepoGpgCheck) ); // TriBool: !false = true or indeterminate + } + else + { + BOOST_CHECK_EQUAL( willCheckRepo, bool(cfgRepoGpgCheck) ); + BOOST_CHECK_EQUAL( mandatoryCheck, bool(cfgRepoGpgCheck) ); + } + + + // pkgGpgCheck may depend on the repoGpgCheck result + for ( TriBool r_validSignature : tribools ) // indeterminate <==> unsigned repo + { + repo.setValidRepoSignature( r_validSignature ); + + if ( r_validSignature && !willCheckRepo ) + // RepoInfo must invalidate any valid (old) signature as soon as the repo check + // is turned off. This prevents showing 'valid sig' for not yet refreshed repos. + // Instead show 'won't be checked' immediately. + BOOST_CHECK( bool(!repo.validRepoSignature()) ); + else + BOOST_CHECK( sameTriboolState( repo.validRepoSignature(), r_validSignature ) ); + + bool willCheckPkg = repo.pkgGpgCheck(); + bool mandatoryCheck = repo.pkgGpgCheckIsMandatory(); +#if ( TC_VERBOSE ) + COUT << "\t" << chr(r_validSignature) << ( willCheckPkg ? ( mandatoryCheck ? "!" : "+" ) : "-" ) << flush; +#endif + if ( mandatoryCheck ) // be a subset of willCheckPkg! + BOOST_CHECK_EQUAL( willCheckPkg, mandatoryCheck ); + + if ( cfgPkgGpgCheck ) + { + BOOST_CHECK_EQUAL( willCheckPkg, true ); + BOOST_CHECK_EQUAL( mandatoryCheck, true ); + } + else if ( cfgGpgCheck ) + { + if ( r_validSignature ) + { + BOOST_CHECK_EQUAL( willCheckPkg, false ); + BOOST_CHECK_EQUAL( mandatoryCheck, false ); + } + else // TriBool: !true = false or indeterminate/unsigned + { + BOOST_CHECK_EQUAL( willCheckPkg, true ); + BOOST_CHECK_EQUAL( mandatoryCheck, !bool(!cfgPkgGpgCheck) ); // TriBool: !false = true or indeterminate/unsigned + } + } + else + { + BOOST_CHECK_EQUAL( willCheckPkg, false ); + BOOST_CHECK_EQUAL( mandatoryCheck, false ); + } + } +#if ( TC_VERBOSE ) + COUT << endl; +#endif + + } + } + } + } + } + } + // reset to defaults: + zcfg.setGpgCheck ( true ); + zcfg.setRepoGpgCheck ( indeterminate ); + zcfg.setPkgGpgCheck ( indeterminate ); +} + +// RAII: Protect ZConfig value changes from escaping the block scope +struct ZConfigGuard +{ + ZConfigGuard() + : _zcfg( ZConfig::instance() ) + { + _g = _zcfg.gpgCheck(); + _r = _zcfg.repoGpgCheck(); + _p = _zcfg.pkgGpgCheck(); + } + + ~ZConfigGuard() + { + _zcfg.setGpgCheck ( _g ); + _zcfg.setRepoGpgCheck( _r ); + _zcfg.setPkgGpgCheck ( _p ); + } + + ZConfig * operator->() { return &_zcfg; } + + ZConfig & _zcfg; + bool _g; + TriBool _r; + TriBool _p; +}; + + +// RAII: Set and reset KeyRingReceiver callback list and response bits for new testcase +struct KeyRingGuard +{ + KeyRingGuard ( KeyRing::DefaultAccept accept_r = KeyRing::ACCEPT_NOTHING ) + { + KeyRing::setDefaultAccept( accept_r ); + krCallback._cblist.clear(); +#if ( TC_VERBOSE ) + COUT << "================================================================================" << endl; + KeyRing & keyRing( *getZYpp()->keyRing() ); + COUT << "K " << keyRing.publicKeys() << endl; + COUT << "T " << keyRing.trustedPublicKeys() << endl; + COUT << KeyRing::defaultAccept() << endl; + + ZConfig & zcfg( ZConfig::instance() ); + COUT << "ZConf " << chr( zcfg.gpgCheck() ) << chr( zcfg.repoGpgCheck() ) << chr( zcfg.pkgGpgCheck() ) << endl; +#endif + } + + ~KeyRingGuard() + { + BOOST_CHECK_EQUAL( krCallback._cblist.empty(), true ); + KeyRing::setDefaultAccept( KeyRing::ACCEPT_NOTHING ); + krCallback._cblist.clear(); + } +}; + +void testLoadRepo( bool succeed_r, // whether loadRepos should succeed or fail with RepoException + const std::string & repo_r, // name of the test repo to load + KeyRing::DefaultAccept accept_r, // Callback response bits to set (mimics user input) + KeyRingReceiver::CallbackList cblist_r ) // Callback sequence list expected +{ + KeyRingGuard _guard( accept_r ); + krCallback._cblist = std::move(cblist_r); + if ( succeed_r ) + test.loadRepo( DATADIR/repo_r, repo_r ); + else + BOOST_CHECK_THROW( test.loadRepo( DATADIR/repo_r, repo_r ), repo::RepoException ); +} + +// ACCEPT_NOTHING = 0x0000, +// ACCEPT_UNSIGNED_FILE = 0x0001, +// ACCEPT_UNKNOWNKEY = 0x0002, +// TRUST_KEY_TEMPORARILY = 0x0004, +// TRUST_AND_IMPORT_KEY = 0x0008, +// ACCEPT_VERIFICATION_FAILED = 0x0010, + +BOOST_AUTO_TEST_CASE(unsigned_repo) +{ + // askUserToAcceptUnsignedFile actually depends on the gpgcheck settings. + // Mandatory on 'R' cases. Otherwise an unsigend repo is accepted but 'pkggpg on' + // is enforced. + ZConfigGuard zcfg; + zcfg->setRepoGpgCheck( false ); // unsafe + + std::string repo( "unsigned_repo" ); + testLoadRepo( true, repo, KeyRing::ACCEPT_NOTHING, + { } ); + + zcfg->setRepoGpgCheck( indeterminate ); // the default + + testLoadRepo( false, repo, KeyRing::ACCEPT_NOTHING, + { "reportbegin", "askUserToAcceptUnsignedFile", "reportend" } ); + testLoadRepo( true, repo, KeyRing::ACCEPT_UNSIGNED_FILE, + { "reportbegin", "askUserToAcceptUnsignedFile", "reportend" } ); +} + +BOOST_AUTO_TEST_CASE(unknownkey_repo) +{ + std::string repo( "unknownkey_repo" ); + testLoadRepo( false, repo, KeyRing::ACCEPT_NOTHING, + { "reportbegin", "askUserToAcceptUnknownKey", "reportend" } ); + testLoadRepo( true, repo, KeyRing::ACCEPT_UNKNOWNKEY, + { "reportbegin", "askUserToAcceptUnknownKey", "reportend" } ); +} + + +BOOST_AUTO_TEST_CASE(wrongsig_repo) +{ + std::string repo( "wrongsig_repo" ); + // IMPORTED KEYS WILL STAY IN KEYRING! FIXIT if it disturbs subsequent tests + + // 1st testcase with a key, so on the fly check askUserToAcceptKey + // being called unless the key is imported in the trusted ring + testLoadRepo( false, repo, KeyRing::ACCEPT_NOTHING, + { "reportbegin", "askUserToAcceptKey", "reportend" } ); + testLoadRepo( false, repo, KeyRing::TRUST_KEY_TEMPORARILY, + { "reportbegin", "askUserToAcceptKey", "infoVerify", "askUserToAcceptVerificationFailed", "reportend" } ); + testLoadRepo( false, repo, KeyRing::ACCEPT_NOTHING, + { "reportbegin", "askUserToAcceptKey", "reportend" } ); + testLoadRepo( false, repo, KeyRing::TRUST_AND_IMPORT_KEY, + { "reportbegin", "askUserToAcceptKey", "infoVerify", "askUserToAcceptVerificationFailed", "reportend" } ); + + // Now the key is in the trusted ring (no more askUserToAcceptKey) + testLoadRepo( false, repo, KeyRing::ACCEPT_NOTHING, + { "reportbegin", "infoVerify", "askUserToAcceptVerificationFailed", "reportend" } ); + testLoadRepo( true, repo, KeyRing::KeyRing::ACCEPT_VERIFICATION_FAILED, + { "reportbegin", "infoVerify", "askUserToAcceptVerificationFailed", "reportend" } ); +} + +BOOST_AUTO_TEST_CASE(signed_repo) +{ + std::string repo( "signed_repo" ); + testLoadRepo( true, repo, KeyRing::KeyRing::ACCEPT_NOTHING, // relies on wrongsig_repo having accepted the key! (already in trusted ring) + { "reportbegin", "infoVerify", "reportend" } ); +} + + +BOOST_AUTO_TEST_CASE(summary) +{ + KeyRingGuard _guard; + KeyRing & keyRing( *getZYpp()->keyRing() ); + BOOST_CHECK_EQUAL( keyRing.publicKeys().size(), 1 ); + BOOST_CHECK_EQUAL( keyRing.trustedPublicKeys().size(), 1 ); + BOOST_CHECK_EQUAL( KeyRing::defaultAccept(), KeyRing::ACCEPT_NOTHING ); + BOOST_CHECK_EQUAL( test.satpool().repos().size(), 5 ); // +} diff --git a/tests/repo/RepoVariables_test.cc b/tests/repo/RepoVariables_test.cc new file mode 100644 index 0000000..60265a2 --- /dev/null +++ b/tests/repo/RepoVariables_test.cc @@ -0,0 +1,251 @@ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +using std::cout; +using std::endl; +using namespace zypp; +using namespace boost::unit_test; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/repo/yum/data") + +typedef std::list ListType; + +namespace std { + std::ostream & operator<<( std::ostream & str, const ListType & obj ) + { + str << "["; + for ( const auto & el : obj ) + str << " " << el; + return str << " ]"; + } +} + +// A plain functor +struct FncTransformator +{ + std::string operator()( const std::string & value_r ) const + { return "{"+value_r+"}"; } +}; + +BOOST_AUTO_TEST_CASE(value_transform) +{ + using zypp::base::ValueTransform; + using zypp::base::ContainerTransform; + + typedef ValueTransform ReplacedString; + typedef ContainerTransform ReplacedStringList; + + ReplacedString r( "val" ); + BOOST_CHECK_EQUAL( r.raw(), "val" ); + BOOST_CHECK_EQUAL( r.transformed(), "{val}" ); + + r.raw() = "new"; + BOOST_CHECK_EQUAL( r.raw(), "new" ); + BOOST_CHECK_EQUAL( r.transformed(), "{new}" ); + + ReplacedStringList rl; + BOOST_CHECK_EQUAL( rl.empty(), true ); + BOOST_CHECK_EQUAL( rl.size(), 0 ); + BOOST_CHECK_EQUAL( rl.raw(), ListType() ); + BOOST_CHECK_EQUAL( rl.transformed(), ListType() ); + + rl.raw().push_back("a"); + rl.raw().push_back("b"); + rl.raw().push_back("c"); + + BOOST_CHECK_EQUAL( rl.empty(), false ); + BOOST_CHECK_EQUAL( rl.size(), 3 ); + BOOST_CHECK_EQUAL( rl.raw(), ListType({ "a","b","c" }) ); + BOOST_CHECK_EQUAL( rl.transformed(), ListType({ "{a}", "{b}", "{c}" }) ); + + BOOST_CHECK_EQUAL( rl.transformed( rl.rawBegin() ), "{a}" ); +} + +void helperGenRepVarExpandResults() +{ + // Generate test result strings for RepVarExpand: + // ( STRING, REPLACED_all_vars_undef, REPLACED_all_vars_defined ) + // Crefully check whether new stings are correct before + // adding them to the testccse. + std::map vartable; + std::map> result; + bool varsoff = true; + + auto varLookup = [&vartable,&varsoff]( const std::string & name_r )->const std::string * + { + if ( varsoff ) + return nullptr; + std::string & val( vartable[name_r] ); + if ( val.empty() ) + { val = "["+name_r+"]"; } + return &val; + }; + + for ( auto && value : { + "" + , "$" + , "$${}" + , "$_:" + , "$_A:" + , "$_A_:" + , "$_A_B:" + , "${_A_B}" + , "\\${_A_B}" // no escape on level 0 + , "${_A_B\\}" // no close brace + , "${C:-a$Bba}" + , "${C:+a$Bba}" + , "${C:+a${B}ba}" + , "${C:+a\\$Bba}" // escape on level > 0; no var $Bba + , "${C:+a$Bba\\}" // escape on level > 0; no close brace C + , "${C:+a${B}ba}" + , "${C:+a\\${B}ba}" // escape on level > 0; no var ${B} + , "${C:+a${B\\}ba}" // escape on level > 0; no close brace B + , "${C:+a\\${B\\}ba}" + , "__${D:+\\$X--{${E:-==\\$X{o\\}==} }--}__\\${B}${}__" + , "__${D:+\\$X--{${E:-==\\$X{o\\}==}\\}--}__\\${B}${}__" + } ) { + varsoff = true; + result[value].first = repo::RepoVarExpand()( value, varLookup ); + varsoff = false; + result[value].second = repo::RepoVarExpand()( value, varLookup ); + } + + for ( const auto & el : result ) + { +#define CSTR(STR) str::form( "%-40s", str::gsub( "\""+STR+"\"", "\\", "\\\\" ).c_str() ) + cout << "RepVarExpandTest( " << CSTR(el.first) << ", " << CSTR(el.second.first) << ", " << CSTR(el.second.second) << " );" << endl; + } +} + +void RepVarExpandTest( const std::string & string_r, const std::string & allUndef_r, const std::string & allDef_r ) +{ + std::map vartable; + bool varsoff = true; + + auto varLookup = [&vartable,&varsoff]( const std::string & name_r )->const std::string * + { + if ( varsoff ) + return nullptr; + std::string & val( vartable[name_r] ); + if ( val.empty() ) + { val = "["+name_r+"]"; } + return &val; + }; + + varsoff = true; + BOOST_CHECK_EQUAL( repo::RepoVarExpand()( string_r, varLookup ), allUndef_r ); + varsoff = false; + BOOST_CHECK_EQUAL( repo::RepoVarExpand()( string_r, varLookup ), allDef_r ); +} + +BOOST_AUTO_TEST_CASE(RepVarExpand) +{ // ( STRING , REPLACED_all_vars_undef , REPLACED_all_vars_defined ) + RepVarExpandTest( "" , "" , "" ); + RepVarExpandTest( "$" , "$" , "$" ); + RepVarExpandTest( "$${}" , "$${}" , "$${}" ); + RepVarExpandTest( "$_:" , "$_:" , "[_]:" ); + RepVarExpandTest( "$_A:" , "$_A:" , "[_A]:" ); + RepVarExpandTest( "$_A_:" , "$_A_:" , "[_A_]:" ); + RepVarExpandTest( "$_A_B:" , "$_A_B:" , "[_A_B]:" ); + RepVarExpandTest( "${C:+a$Bba\\}" , "${C:+a$Bba\\}" , "${C:+a[Bba]\\}" ); + RepVarExpandTest( "${C:+a$Bba}" , "" , "a[Bba]" ); + RepVarExpandTest( "${C:+a${B\\}ba}" , "${C:+a${B\\}ba}" , "${C:+a${B\\}ba}" ); + RepVarExpandTest( "${C:+a${B}ba}" , "" , "a[B]ba" ); + RepVarExpandTest( "${C:+a\\$Bba}" , "" , "a$Bba" ); + RepVarExpandTest( "${C:+a\\${B\\}ba}" , "" , "a${B}ba" ); + RepVarExpandTest( "${C:+a\\${B}ba}" , "ba}" , "a${Bba}" ); + RepVarExpandTest( "${C:-a$Bba}" , "a$Bba" , "[C]" ); + RepVarExpandTest( "${_A_B\\}" , "${_A_B\\}" , "${_A_B\\}" ); + RepVarExpandTest( "${_A_B}" , "${_A_B}" , "[_A_B]" ); + RepVarExpandTest( "\\${_A_B}" , "\\${_A_B}" , "\\[_A_B]" ); + RepVarExpandTest( "__${D:+\\$X--{${E:-==\\$X{o\\}==} }--}__\\${B}${}__", "__--}__\\${B}${}__" , "__$X--{[E] --}__\\[B]${}__" ); + RepVarExpandTest( "__${D:+\\$X--{${E:-==\\$X{o\\}==}\\}--}__\\${B}${}__", "____\\${B}${}__" , "__$X--{[E]}--__\\[B]${}__" ); +} + +void varInAuthExpect( const Url & url_r, const std::string & expHost_r, const std::string & expPort_r, const std::string & expPath_r, + const std::string & user_r = std::string(), const std::string & pass_r = std::string() ) +{ + BOOST_CHECK_EQUAL( url_r.getHost(), expHost_r ); + BOOST_CHECK_EQUAL( url_r.getPort(), expPort_r ); + BOOST_CHECK_EQUAL( url_r.getPathName(), expPath_r ); + BOOST_CHECK_EQUAL( url_r.getUsername(), user_r ); + BOOST_CHECK_EQUAL( url_r.getPassword(), pass_r ); +} + +BOOST_AUTO_TEST_CASE(replace_text) +{ + /* check RepoVariablesStringReplacer */ + ZConfig::instance().setSystemArchitecture(Arch("i686")); + ::setenv( "ZYPP_REPO_RELEASEVER", "13.2", 1 ); + + repo::RepoVariablesStringReplacer replacer1; + BOOST_CHECK_EQUAL( replacer1(""), "" ); + BOOST_CHECK_EQUAL( replacer1("$"), "$" ); + BOOST_CHECK_EQUAL( replacer1("$arc"), "$arc" ); + BOOST_CHECK_EQUAL( replacer1("$arch"), "i686" ); + + BOOST_CHECK_EQUAL( replacer1("$archit"), "$archit" ); + BOOST_CHECK_EQUAL( replacer1("${rc}it"), "${rc}it" ); + BOOST_CHECK_EQUAL( replacer1("$arch_it"), "$arch_it" ); + + BOOST_CHECK_EQUAL( replacer1("$arch-it"), "i686-it" ); + BOOST_CHECK_EQUAL( replacer1("$arch it"), "i686 it" ); + BOOST_CHECK_EQUAL( replacer1("${arch}it"), "i686it" ); + + BOOST_CHECK_EQUAL( replacer1("${arch}it$archit $arch"), "i686it$archit i686" ); + BOOST_CHECK_EQUAL( replacer1("X${arch}it$archit $arch-it"), "Xi686it$archit i686-it" ); + + BOOST_CHECK_EQUAL( replacer1("${releasever}"), "13.2" ); + BOOST_CHECK_EQUAL( replacer1("${releasever_major}"), "13" ); + BOOST_CHECK_EQUAL( replacer1("${releasever_minor}"), "2" ); + + BOOST_CHECK_EQUAL(replacer1("http://foo/$arch/bar"), "http://foo/i686/bar"); + + /* check RepoVariablesUrlReplacer */ + repo::RepoVariablesUrlReplacer replacer2; + + // first of all url with {} must be accepted: + BOOST_CHECK_NO_THROW( Url("ftp://site.org/${arch}/?arch=${arch}") ); + BOOST_CHECK_NO_THROW( Url("ftp://site.org/${arch:-noarch}/?arch=${arch:-noarch}") ); + BOOST_CHECK_NO_THROW( Url("ftp://site.org/${arch:+somearch}/?arch=${arch:+somearch}") ); + + BOOST_CHECK_EQUAL(replacer2(Url("ftp://user:secret@site.org/$arch/")).asCompleteString(), + "ftp://user:secret@site.org/i686/"); + + BOOST_CHECK_EQUAL(replacer2(Url("http://user:my$arch@site.org/$basearch/")).asCompleteString(), + "http://user:my$arch@site.org/i386/"); + + BOOST_CHECK_EQUAL(replacer2(Url("http://site.org/update/?arch=$arch")).asCompleteString(), + "http://site.org/update/?arch=i686"); + + BOOST_CHECK_EQUAL(replacer2(Url("http://site.org/update/$releasever/?arch=$arch")).asCompleteString(), + "http://site.org/update/13.2/?arch=i686"); + + // - bsc#1067605: Allow VAR in Url authority + // fake some host name via $arch + varInAuthExpect( replacer2(Url("ftp://$arch/path")), "i686", "", "/path" ); + varInAuthExpect( replacer2(Url("ftp://$arch:1234/path")), "i686", "1234", "/path" ); + // don't expand in user/pass! + varInAuthExpect( replacer2(Url("ftp://$arch:$arch@$arch:1234/path")), "i686", "1234", "/path", "$arch", "$arch" ); + // No support for complex vars: + // BOOST_CHECK_NO_THROW( Url("ftp://${arch:-nosite}/path") ); + // BOOST_CHECK_NO_THROW( Url("ftp://${arch:+somesite}/path") ); +} + +BOOST_AUTO_TEST_CASE(uncached) +{ + ::setenv( "ZYPP_REPO_RELEASEVER", "13.2", 1 ); + repo::RepoVariablesStringReplacer replacer1; + BOOST_CHECK_EQUAL( replacer1("${releasever}"), "13.2" ); + ::setenv( "ZYPP_REPO_RELEASEVER", "13.3", 1 ); + BOOST_CHECK_EQUAL( replacer1("${releasever}"), "13.3" ); +} +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/repo/susetags/CMakeLists.txt b/tests/repo/susetags/CMakeLists.txt new file mode 100644 index 0000000..4993c4e --- /dev/null +++ b/tests/repo/susetags/CMakeLists.txt @@ -0,0 +1,2 @@ + +ADD_TESTS(Downloader) \ No newline at end of file diff --git a/tests/repo/susetags/Downloader_test.cc b/tests/repo/susetags/Downloader_test.cc new file mode 100644 index 0000000..c67ea23 --- /dev/null +++ b/tests/repo/susetags/Downloader_test.cc @@ -0,0 +1,165 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tests/zypp/KeyRingTestReceiver.h" + + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace boost::unit_test; +using namespace zypp::repo; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/repo/susetags/data") + +using namespace zyppng::operators; + +BOOST_AUTO_TEST_CASE(susetags_download) +{ + KeyRingTestReceiver keyring_callbacks; + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + + Pathname p = DATADIR + "/stable-x86-subset"; + RepoInfo repoinfo; + repoinfo.setAlias("testrepo"); + repoinfo.setPath("/"); + + filesystem::TmpDir tmp; + Pathname localdir(tmp.path()); + + + auto ctx = zyppng::SyncContext::create (); + auto res = ctx->provider()->attachMedia( p.asDirUrl() , zyppng::ProvideMediaSpec() ) + | and_then( [&]( zyppng::SyncMediaHandle h ){ + auto dlctx = std::make_shared( ctx, repoinfo, localdir ); + return zyppng::SuseTagsWorkflows::download(dlctx, h); + }) + | and_then( [&](zyppng::repo::SyncDownloadContextRef ctx ) { + + MIL << "All files downloaded" << endl; + + const char* files[] = + { + "/suse", + "/suse/setup", + "/suse/setup/descr", + "/suse/setup/descr/kde-10.3-71.noarch.pat", + "/suse/setup/descr/packages", + "/suse/setup/descr/packages.DU", + "/suse/setup/descr/packages.en", + // "/suse/setup/descr/packages.es", + "/suse/setup/descr/patterns", + "/content", + "/gpg-pubkey-7e2e3b05-44748aba.asc", + "/media.1", + // "/media.1/products.asc", + // "/media.1/products.key", + "/media.1/media", + // "/media.1/products", + // "/media.1/info.txt", + // "/media.1/license.zip", + "/gpg-pubkey-a1912208-446a0899.asc", + "/gpg-pubkey-307e3d54-44201d5d.asc", + "/gpg-pubkey-9c800aca-40d8063e.asc", + "/content.asc", + "/content.key", + "/gpg-pubkey-3d25d3d9-36e12d04.asc", + "/gpg-pubkey-0dfb3188-41ed929b.asc", + NULL + }; + + int i=0; + while ( files[i] != NULL ) + { + BOOST_CHECK_MESSAGE( PathInfo(localdir + files[i] ).isExist(), string(files[i]).c_str() ); + i++; + } + + return zyppng::expected::success(); + }); + + BOOST_REQUIRE ( res.is_valid () ); +} + + +BOOST_AUTO_TEST_CASE(susetags_gz_download) +{ + KeyRingTestReceiver keyring_callbacks; + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + + Pathname p = DATADIR + "/stable-x86-subset-gz"; + + RepoInfo repoinfo; + repoinfo.setAlias("testrepo"); + repoinfo.setPath("/"); + filesystem::TmpDir tmp; + + Pathname localdir(tmp.path()); + + auto ctx = zyppng::SyncContext::create (); + auto res = ctx->provider()->attachMedia( p.asDirUrl() , zyppng::ProvideMediaSpec() ) + | and_then( [&]( zyppng::SyncMediaHandle h ){ + auto dlctx = std::make_shared( ctx, repoinfo, localdir ); + return zyppng::SuseTagsWorkflows::download(dlctx, h); + }) + | and_then( [&](zyppng::repo::SyncDownloadContextRef ctx ) { + + const char* files[] = + { + "/suse", + "/suse/setup", + "/suse/setup/descr", + "/suse/setup/descr/kde-10.3-71.noarch.pat.gz", + "/suse/setup/descr/packages.gz", + "/suse/setup/descr/packages.DU.gz", + "/suse/setup/descr/packages.en.gz", + // "/suse/setup/descr/packages.es", + "/suse/setup/descr/patterns.gz", + "/content", + "/gpg-pubkey-7e2e3b05-44748aba.asc", + "/media.1", + // "/media.1/products.asc", + // "/media.1/products.key", + "/media.1/media", + // "/media.1/products", + // "/media.1/info.txt", + // "/license.tar.gz", + // "/control.xml", + // "/installation.xml", + "/gpg-pubkey-a1912208-446a0899.asc", + "/gpg-pubkey-307e3d54-44201d5d.asc", + "/gpg-pubkey-9c800aca-40d8063e.asc", + "/content.asc", + "/content.key", + "/gpg-pubkey-3d25d3d9-36e12d04.asc", + "/gpg-pubkey-0dfb3188-41ed929b.asc", + NULL + }; + + int i=0; + while ( files[i] != NULL ) + { + BOOST_CHECK_MESSAGE( PathInfo(localdir + files[i] ).isExist(), string(files[i]).c_str() ); + i++; + } + + return zyppng::expected::success(); + + }); + + BOOST_REQUIRE ( res.is_valid () ); +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/repo/susetags/data/addon_in_subdir/media.1/build b/tests/repo/susetags/data/addon_in_subdir/media.1/build new file mode 100644 index 0000000..3e09a19 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/media.1/build @@ -0,0 +1 @@ +openSUSE-11.1-Beta5-DVD-i586-Build0128 diff --git a/tests/repo/susetags/data/addon_in_subdir/media.1/directory.yast b/tests/repo/susetags/data/addon_in_subdir/media.1/directory.yast new file mode 100644 index 0000000..d1b27df --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/media.1/directory.yast @@ -0,0 +1,6 @@ +build +info.txt +media +products +products.asc +products.key diff --git a/tests/repo/susetags/data/addon_in_subdir/media.1/media b/tests/repo/susetags/data/addon_in_subdir/media.1/media new file mode 100644 index 0000000..42af4f5 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/media.1/media @@ -0,0 +1,3 @@ +openSUSE +20081112071348 +1 diff --git a/tests/repo/susetags/data/addon_in_subdir/media.1/products b/tests/repo/susetags/data/addon_in_subdir/media.1/products new file mode 100644 index 0000000..bf73ab9 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/media.1/products @@ -0,0 +1 @@ +/ openSUSE 11.1-0 diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/SHA1SUMS b/tests/repo/susetags/data/addon_in_subdir/updates/SHA1SUMS new file mode 100644 index 0000000..308e7d9 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/SHA1SUMS @@ -0,0 +1,2 @@ +33bbc20526153c35d11ce0b1c3d6b7be151b92d9 content +bfc5ac3540529a9a898c3c444096f9bcbb5db780 directory.yast diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/content b/tests/repo/susetags/data/addon_in_subdir/updates/content new file mode 100644 index 0000000..cc17cac --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/content @@ -0,0 +1,19 @@ +CONTENTSTYLE 11 +BASEARCHS i586 +DATADIR suse +DESCRDIR suse/setup/descr +DISTRIBUTION openSUSE +FLAVOR dvd +LABEL openSUSE 11.1 +LINGUAS cs da de en en_GB en_US es fi fr hu it ja nb nl pl pt pt_BR ru sv zh zh_CN zh_TW +NAME openSUSE +REFERENCES openSUSE-release = 11.1 +RELNOTESURL http://www.suse.com/relnotes/i386/openSUSE/11.0.42/release-notes-openSUSE.rpm +REPO_LOCATION http://download.opensuse.org/factory/repo/oss/ +SUMMARY openSUSE +VENDOR openSUSE +VERSION 11.1 +META SHA1 3d0cdf34257cc2c54929bf5414969142cad1d421 packages +META SHA1 2d68731ab2f3c86b81f7672798f871cf96b2d0fc packages.DU +META SHA1 07c36c760ed0c58b58d6d8fcfdd2717df02c4256 packages.en +HASH SHA1 875e73cf2ee139203208c860fbfd7fa5cb291c7e license.tar.gz \ No newline at end of file diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/content.asc b/tests/repo/susetags/data/addon_in_subdir/updates/content.asc new file mode 100644 index 0000000..3df9e35 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/content.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.9 (GNU/Linux) + +iEYEABECAAYFAkktcUUACgkQm+zCtd2wN1ZrDgCdFYz7dG8ui0ueFLOIHYxFgunL +VEYAnjzykFqwVAmYhF/QNbfriOqN5z1B +=4Jf7 +-----END PGP SIGNATURE----- diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/content.key b/tests/repo/susetags/data/addon_in_subdir/updates/content.key new file mode 100644 index 0000000..5c27af8 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/content.key @@ -0,0 +1,439 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +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 +6fh4/BFzYYIFqUADPFzkYKy6U4lls9BNL/Yk0JgEkLbrEayNW6QbM1j/j2wctUrb +aEe6Imncp8VN8DHSjE2tOe1iHIj6G+9rywDXx4kb9hwqcOfpKL/0AoRzle6aTr7K +nCpxBMXCIfQyLKEcJ9wiO3LCwBafJ7fmLJFUnRb4L7ZPg5gMejl0fquMtVKR+CyS +LnhEqDwbrtIR5VOJuZlUFzr77HBL/T7rbxiU3mHONAI8T7dxs2fDv1+ktKeQtlLV +v6DgOc2AaqbvgPO1LEtOdq9fN5aaoAi1EGBDVkIMdWDXdVYY8PnP7GXow2X3G+oM +Ddl8+NpN3g+JAhwEEwECAAYFAkKfCxwACgkQ2MIKCVokV8/xBQ/+MBAGiuwATgRa +lqxdV/PLCDHTaRKAqNf1kMhCMZ99ubECMPzXgI1QQa44AiTNmUUd4RNrBS3gzMjX +nx4oPe6JjXCkP1grnBLMple2NTkaWU0Q/VQkbDxYvZaiPZuz9JTrilU3Z6L8+e6A +zHVAs+EdIeYNxqeTfLUbFj+59AN9eJs7Ud7+uMWGeeDpiZUTcRXm2wdBRzfZi82q +bSLREsIAAvOHr7uB5YarjQOh6lFTT2Jo0GAE3fzVlcSAzS0yV1hD3qtIQH6x7uXr +KTAcTDYQoDJnPIOZSYiz0xbuoAuWISicGXVvlaJ03C5+qgQ9oHRbzALC9SvxPXZe +OC63bjMC7YLXQRzZ+l4wkSjl+d2FfE6koAAC1vTzVx8febJ6eXbNB7mA3sO8gBRG +j7oVzpqY2IAI+UqzyBuKVp7XElOKePK14mw3Dr0Ps/0MC63grWq6kLlAreGZzrS/ +dD/4L1ZgxibFbQXmaElQ+2n7AgNCV7YeESafEPCVV82yScPxC1WlpVBUjqcmn4gc +GBAQ62TBTg/2JL5Z7axiygv7KwDRiAb7lXtBRFidF3dCYOyA696K6CKXioXZwYA3 +XIZXat2A5SfvH6NKVPzcultvqMWtvYceIx9OfiDiTCrInXnixOSn9cJXRk7SeAOo +Q/PHczcYWeAz8kAkUzCYMLQwtusUkkKIRgQTEQIABgUCP52dtgAKCRAhkYDN20Km +DkeUAKCKdRvqJlZLav7J8aZs+VHh45UmIwCgka/3mvy+0u2U8QdfHH9U2H2ndceI +RgQTEQIABgUCQA2AagAKCRAqHoQY2VDGRzkxAJ4kR3qK5sz/RW34GRwgtpvqA3tm +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 +k/oVP1VewlU= +=zobT +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/directory.yast b/tests/repo/susetags/data/addon_in_subdir/updates/directory.yast new file mode 100644 index 0000000..b2c1c89 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/directory.yast @@ -0,0 +1,2 @@ +media.1/ +suse/ diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/license.tar.gz b/tests/repo/susetags/data/addon_in_subdir/updates/license.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5d513d14d3ba6de2dc3e88d54c8b5dedfc2f5a94 GIT binary patch literal 45 vcmb2|=3uxU&gjj+{PrLtF9QR^p#|UlbNS2{0GSZbV9q@2o~$~91_J{C4>k&f literal 0 HcmV?d00001 diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/suse/i586/SHA1SUMS b/tests/repo/susetags/data/addon_in_subdir/updates/suse/i586/SHA1SUMS new file mode 100644 index 0000000..8b8b046 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/suse/i586/SHA1SUMS @@ -0,0 +1 @@ +c8db67006900a7758dda69efee189c5eb39d206c dnsmasq-2.46-1.i586.rpm diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/SHA1SUMS b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/SHA1SUMS new file mode 100644 index 0000000..b5fa0b4 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/SHA1SUMS @@ -0,0 +1,4 @@ +965ba5faeea815d41ba308ffd193b78505b26c1c directory.yast +3d0cdf34257cc2c54929bf5414969142cad1d421 packages +2d68731ab2f3c86b81f7672798f871cf96b2d0fc packages.DU +07c36c760ed0c58b58d6d8fcfdd2717df02c4256 packages.en diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/directory.yast b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/directory.yast new file mode 100644 index 0000000..09276e7 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/directory.yast @@ -0,0 +1,4 @@ +directory.yast +packages +packages.DU +packages.en diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages new file mode 100644 index 0000000..d313420 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages @@ -0,0 +1,63 @@ +=Ver: 2.0 +##---------------------------------------- +=Pkg: dnsmasq 2.46 1 i586 ++Req: +/usr/sbin/useradd +fillup +coreutils +grep +diffutils +insserv +sed +/bin/mkdir +/bin/sh +/bin/sh +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +/bin/sh +libc.so.6 +libc.so.6(GLIBC_2.0) +libc.so.6(GLIBC_2.1) +libc.so.6(GLIBC_2.2) +libc.so.6(GLIBC_2.3) +libc.so.6(GLIBC_2.3.4) +libc.so.6(GLIBC_2.4) +rpmlib(PayloadIsLzma) <= 4.4.2-1 +-Req: ++Prq: +/usr/sbin/useradd +fillup +coreutils +grep +diffutils +insserv +sed +/bin/mkdir +/bin/sh +/bin/sh +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(PayloadIsLzma) <= 4.4.2-1 +-Prq: ++Prv: +dns_daemon +dnsmasq = 2.46-1 +/etc/dnsmasq.conf +/etc/init.d/dnsmasq +/etc/slp.reg.d +/etc/slp.reg.d/dnsmasq.reg +/etc/sysconfig/SuSEfirewall2.d/services/dnsmasq-dhcp +/etc/sysconfig/SuSEfirewall2.d/services/dnsmasq-dns +/usr/sbin/dnsmasq +/usr/sbin/rcdnsmasq +-Prv: +=Grp: Productivity/Networking/DNS/Servers +=Lic: GPL v2 or later +=Src: dnsmasq 2.46 1 src +=Tim: 1226926770 +=Loc: 1 dnsmasq-2.46-1.i586.rpm +=Siz: 290023 826308 diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.DU b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.DU new file mode 100644 index 0000000..054d150 --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.DU @@ -0,0 +1,58 @@ +=Ver: 2.0 +##---------------------------------------- +=Pkg: dnsmasq 2.46 1 i586 ++Dir: +/ 0 840 0 61 +etc/ 19 6 1 4 +etc/init.d/ 3 0 1 0 +etc/slp.reg.d/ 1 0 1 0 +etc/sysconfig/ 0 2 0 2 +etc/sysconfig/SuSEfirewall2.d/ 0 2 0 2 +etc/sysconfig/SuSEfirewall2.d/services/ 2 0 2 0 +usr/ 0 815 0 56 +usr/sbin/ 149 0 1 0 +usr/share/ 0 666 0 55 +usr/share/doc/ 0 476 0 42 +usr/share/doc/packages/ 0 476 0 42 +usr/share/doc/packages/dnsmasq/ 188 288 7 35 +usr/share/doc/packages/dnsmasq/contrib/ 0 288 0 35 +usr/share/doc/packages/dnsmasq/contrib/Solaris10/ 4 0 2 0 +usr/share/doc/packages/dnsmasq/contrib/Suse/ 10 0 5 0 +usr/share/doc/packages/dnsmasq/contrib/dns-loc/ 17 0 2 0 +usr/share/doc/packages/dnsmasq/contrib/dnslist/ 29 0 3 0 +usr/share/doc/packages/dnsmasq/contrib/dnsmasq_MacOSX/ 4 0 3 0 +usr/share/doc/packages/dnsmasq/contrib/dynamic-dnsmasq/ 8 0 1 0 +usr/share/doc/packages/dnsmasq/contrib/openvpn/ 7 0 3 0 +usr/share/doc/packages/dnsmasq/contrib/port-forward/ 4 0 2 0 +usr/share/doc/packages/dnsmasq/contrib/slackware-dnsmasq/ 6 0 5 0 +usr/share/doc/packages/dnsmasq/contrib/try-all-ns/ 4 0 2 0 +usr/share/doc/packages/dnsmasq/contrib/webmin/ 174 0 2 0 +usr/share/doc/packages/dnsmasq/contrib/wrt/ 21 0 5 0 +usr/share/locale/ 0 128 0 10 +usr/share/locale/de/ 0 3 0 1 +usr/share/locale/de/LC_MESSAGES/ 3 0 1 0 +usr/share/locale/es/ 0 23 0 1 +usr/share/locale/es/LC_MESSAGES/ 23 0 1 0 +usr/share/locale/fi/ 0 1 0 1 +usr/share/locale/fi/LC_MESSAGES/ 1 0 1 0 +usr/share/locale/fr/ 0 24 0 1 +usr/share/locale/fr/LC_MESSAGES/ 24 0 1 0 +usr/share/locale/id/ 0 14 0 1 +usr/share/locale/id/LC_MESSAGES/ 14 0 1 0 +usr/share/locale/it/ 0 1 0 1 +usr/share/locale/it/LC_MESSAGES/ 1 0 1 0 +usr/share/locale/nb/ 0 14 0 1 +usr/share/locale/nb/LC_MESSAGES/ 14 0 1 0 +usr/share/locale/pl/ 0 32 0 1 +usr/share/locale/pl/LC_MESSAGES/ 32 0 1 0 +usr/share/locale/pt_BR/ 0 1 0 1 +usr/share/locale/pt_BR/LC_MESSAGES/ 1 0 1 0 +usr/share/locale/ro/ 0 15 0 1 +usr/share/locale/ro/LC_MESSAGES/ 15 0 1 0 +usr/share/man/ 0 62 0 3 +usr/share/man/es/ 0 21 0 1 +usr/share/man/es/man8/ 21 0 1 0 +usr/share/man/fr/ 0 22 0 1 +usr/share/man/fr/man8/ 22 0 1 0 +usr/share/man/man8/ 19 0 1 0 +-Dir: diff --git a/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.en b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.en new file mode 100644 index 0000000..0c7748f --- /dev/null +++ b/tests/repo/susetags/data/addon_in_subdir/updates/suse/setup/descr/packages.en @@ -0,0 +1,20 @@ +=Ver: 2.0 +##---------------------------------------- +=Pkg: dnsmasq 2.46 1 i586 +=Sum: Lightweight, Easy-to-Configure DNS Forwarder and DHCP Server ++Des: +Dnsmasq is a lightweight, easy-to-configure DNS forwarder and DHCP +server. It is designed to provide DNS and, optionally, DHCP, to a small +network. It can serve the names of local machines that are not in the +global DNS. The DHCP server integrates with the DNS server and allows +machines with DHCP-allocated addresses to appear in DNS with names +configured either in each host or in a central configuration file. +Dnsmasq supports static and dynamic DHCP leases and BOOTP for network +booting of diskless machines. + + + +Authors: +-------- + simon@thekelleys.org.uk +-Des: diff --git a/tests/repo/susetags/data/dudata/repo/content b/tests/repo/susetags/data/dudata/repo/content new file mode 100644 index 0000000..f76a96e --- /dev/null +++ b/tests/repo/susetags/data/dudata/repo/content @@ -0,0 +1,2 @@ +META SHA1 b75eeb1b3d231ccb6322c91417050520f992949c packages +META SHA1 cb96552f7a57eb21f3279310c1c339e6b22924d8 packages.DU diff --git a/tests/repo/susetags/data/dudata/repo/media.1/media b/tests/repo/susetags/data/dudata/repo/media.1/media new file mode 100644 index 0000000..d5aa1ef --- /dev/null +++ b/tests/repo/susetags/data/dudata/repo/media.1/media @@ -0,0 +1,3 @@ +SUSE Linux Products GmbH +20070705102239 +1 diff --git a/tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages b/tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages new file mode 100644 index 0000000..0dce8f4 --- /dev/null +++ b/tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages @@ -0,0 +1,8 @@ +=Ver: 2.0 +##---------------------------------------- +=Pkg: dutest 1.0 1 x86_64 +##---------------------------------------- +=Pkg: dutest 2.0 1 x86_64 +##---------------------------------------- +=Pkg: dutest 3.0 1 x86_64 +##---------------------------------------- diff --git a/tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages.DU b/tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages.DU new file mode 100644 index 0000000..0cfa08e --- /dev/null +++ b/tests/repo/susetags/data/dudata/repo/suse/setup/descr/packages.DU @@ -0,0 +1,16 @@ +=Ver: 2.0 +##---------------------------------------- +## / localK subK localF subF +##---------------------------------------- +=Pkg: dutest 1.0 1 x86_64 ++Dir: +/norm 15 0 1 0 +/grow 15 0 1 0 +-Dir: +##---------------------------------------- +=Pkg: dutest 2.0 1 x86_64 ++Dir: +/norm 45 0 1 0 +/grow 45 0 1 0 +-Dir: +##---------------------------------------- diff --git a/tests/repo/susetags/data/dudata/system/content b/tests/repo/susetags/data/dudata/system/content new file mode 100644 index 0000000..07033bc --- /dev/null +++ b/tests/repo/susetags/data/dudata/system/content @@ -0,0 +1,2 @@ +META SHA1 95a347a40f621834a870e10b8914c9442c2dc355 packages +META SHA1 7d11955486b049be5f601b82acc18bfc73c22f39 packages.DU diff --git a/tests/repo/susetags/data/dudata/system/media.1/media b/tests/repo/susetags/data/dudata/system/media.1/media new file mode 100644 index 0000000..d5aa1ef --- /dev/null +++ b/tests/repo/susetags/data/dudata/system/media.1/media @@ -0,0 +1,3 @@ +SUSE Linux Products GmbH +20070705102239 +1 diff --git a/tests/repo/susetags/data/dudata/system/suse/setup/descr/packages b/tests/repo/susetags/data/dudata/system/suse/setup/descr/packages new file mode 100644 index 0000000..350dc7f --- /dev/null +++ b/tests/repo/susetags/data/dudata/system/suse/setup/descr/packages @@ -0,0 +1,4 @@ +=Ver: 2.0 +##---------------------------------------- +=Pkg: dutest 1.0 1 x86_64 +##---------------------------------------- diff --git a/tests/repo/susetags/data/dudata/system/suse/setup/descr/packages.DU b/tests/repo/susetags/data/dudata/system/suse/setup/descr/packages.DU new file mode 100644 index 0000000..c86c52e --- /dev/null +++ b/tests/repo/susetags/data/dudata/system/suse/setup/descr/packages.DU @@ -0,0 +1,10 @@ +=Ver: 2.0 +##---------------------------------------- +## / localK subK localF subF +##---------------------------------------- +=Pkg: dutest 1.0 1 x86_64 ++Dir: +/norm 5 0 1 0 +/grow 5 0 1 0 +-Dir: +##---------------------------------------- diff --git a/tests/repo/susetags/data/shared_attributes/content b/tests/repo/susetags/data/shared_attributes/content new file mode 100644 index 0000000..75955ab --- /dev/null +++ b/tests/repo/susetags/data/shared_attributes/content @@ -0,0 +1,30 @@ +PRODUCT openSUSE-factory +VERSION 10.3 +DISTPRODUCT SuSE-Linux-STABLE-X86 +DISTVERSION 10.2.42-factory +VENDOR SUSE LINUX Products GmbH, Nuernberg, Germany +RELNOTESURL http://www.suse.com/relnotes/i386/openSUSE/FACTORY/release-notes.rpm +ARCH.x86_64 x86_64 i686 i586 i486 i386 noarch +ARCH.i686 i686 i586 i486 i386 noarch +ARCH.i586 i586 i486 i386 noarch +ARCH.i486 i486 i386 noarch +ARCH.i386 i386 noarch +DEFAULTBASE i586 +REQUIRES openSUSE-release = 10.3 pattern:basesystem +PROVIDES product:openSUSE = 10.2.42 +OBSOLETES product:SUSE_LINUX product:openSUSE <= 10.2 +LINGUAS cs da de en en_GB es fi fr hu it ja km nl nb pl pt_BR zh_CN zh_TW +SHORTLABEL FACTORY +LABEL openSUSE FACTORY 10.3 +LABEL.de openSUSE FACTORY 10.3 +EXTRAURLS http://download.opensuse.org/distribution/10.2/repo/oss/ +OPTIONALURLS http://download.opensuse.org/distribution/10.2/repo/non-oss/ http://download.opensuse.org/distribution/10.2/repo/debug/ +DESCRDIR suse/setup/descr +DATADIR suse +FLAGS update +LANGUAGE en_US +META SHA1 cec02abacb62fce2964a787d516879822691be6e packages +META SHA1 2664997a3bae2679cf1395a81d54a7dd4532c276 packages.DU +META SHA1 1c539c3fe4a8ec5fbe96ce3b559fc952124f9acd packages.en + + diff --git a/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages b/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages new file mode 100644 index 0000000..231681b --- /dev/null +++ b/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages @@ -0,0 +1,32 @@ +##---------------------------------------- +=Pkg: foo 1.0 1 i586 +=Cks: SHA1 05f0647241433d01636785fd282cc824a6527269 ++Req: +bar > 1.0 +-Req: +=Grp: Bar +=Lic: BSD License and BSD-like, GNU General Public License (GPL) +=Src: foo 1.0 1 src +=Tim: 1183399094 +=Loc: 1 foo-1.0-1.i586.rpm +=Siz: 16356019 38850584 ++Aut: +Foo Bar +-Aut: +##---------------------------------------- +=Pkg: foo 1.0 1 x86_64 +=Cks: SHA1 05f0647241433d01636785fd282cc824a6527269 ++Req: +bar > 1.0 +-Req: +=Grp: Bar +=Lic: BSD License and BSD-like, GNU General Public License (GPL) +=Src: foo 1.0 1 src +=Tim: 1183399094 +=Loc: 1 foo-1.0-1.x86_64.rpm +=Siz: 16356019 38850584 ++Aut: +Foo Bar +-Aut: +=Shr: foo 1.0 1 i586 + diff --git a/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.DU b/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.DU new file mode 100644 index 0000000..f8a911b --- /dev/null +++ b/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.DU @@ -0,0 +1,7 @@ +##---------------------------------------- +=Pkg: foo 1.0 1 i586 ++Dir: +/ 0 39444 0 3068 +usr/share/ 11 0 1 0 +-Dir: +##---------------------------------------- diff --git a/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.en b/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.en new file mode 100644 index 0000000..5021a00 --- /dev/null +++ b/tests/repo/susetags/data/shared_attributes/suse/setup/descr/packages.en @@ -0,0 +1,7 @@ +##---------------------------------------- +=Pkg: foo 1.0 1 i586 +=Sum: Foo program ++Des: +This is the description +-Des: +##---------------------------------------- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/content b/tests/repo/susetags/data/stable-x86-subset-gz/content new file mode 100644 index 0000000..9bca45d --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/content @@ -0,0 +1,42 @@ +PRODUCT openSUSE-factory +VERSION 10.3 +DISTPRODUCT SuSE-Linux-STABLE-X86 +DISTVERSION 10.2.42-factory +VENDOR SUSE LINUX Products GmbH, Nuernberg, Germany +RELNOTESURL http://www.suse.com/relnotes/i386/openSUSE/FACTORY/release-notes.rpm +ARCH.x86_64 x86_64 i686 i586 i486 i386 noarch +ARCH.i686 i686 i586 i486 i386 noarch +ARCH.i586 i586 i486 i386 noarch +ARCH.i486 i486 i386 noarch +ARCH.i386 i386 noarch +DEFAULTBASE i586 +REQUIRES openSUSE-release = 10.3 pattern:basesystem +PROVIDES product:openSUSE = 10.2.42 +OBSOLETES product:SUSE_LINUX product:openSUSE <= 10.2 +LINGUAS cs da de en en_GB es fi fr hu it ja km nl nb pl pt_BR zh_CN zh_TW +SHORTLABEL FACTORY +LABEL openSUSE FACTORY 10.3 +LABEL.de openSUSE FACTORY 10.3 +EXTRAURLS http://download.opensuse.org/distribution/10.2/repo/oss/ +OPTIONALURLS http://download.opensuse.org/distribution/10.2/repo/non-oss/ http://download.opensuse.org/distribution/10.2/repo/debug/ +DESCRDIR suse/setup/descr +DATADIR suse +FLAGS update +LANGUAGE en_US +META SHA1 3b3a4b0f085dd3605b61cdec06783b6b2a1f1d61 kde-10.3-71.noarch.pat.gz +META SHA1 2c351e103b347ef2984cb2aa638accfeadfaef58 packages.DU.gz +META SHA1 208a6f8e1c96e9ba2ea7c74c05113c11c7378823 packages.en.gz +META SHA1 59d65b8575ba1edde1813fef2e9949ae85f4d4c1 packages.es.gz +META SHA1 061c361edf6157bc4273872055822e9d1766b8c4 packages.gz +META SHA1 8ae8446949182a9908c7d07b7bc58fb718cf3a92 patterns.gz +KEY SHA1 c0354069c10819674da8706822e1d4bd0c1797e9 gpg-pubkey-0dfb3188-41ed929b.asc +KEY SHA1 2e38e503c436c5d002bdc31755c82188044d9d21 gpg-pubkey-307e3d54-44201d5d.asc +KEY SHA1 7025932e6866932f489421990075f3ed312023ea gpg-pubkey-3d25d3d9-36e12d04.asc +KEY SHA1 fd6146cac8c1473c5b52548936de773d5bbd5610 gpg-pubkey-7e2e3b05-44748aba.asc +KEY SHA1 cd7adceba1fe5d7ba27b5749718743192d82f802 gpg-pubkey-9c800aca-40d8063e.asc +KEY SHA1 7535d79e31ef7b4232e5593bb49d9142978b2e95 gpg-pubkey-a1912208-446a0899.asc +HASH SHA1 875e73cf2ee139203208c860fbfd7fa5cb291c7e license.tar.gz +HASH SHA1 4aa8ded6302e6ec85690a51af6044dffe9b21923 control.xml +HASH SHA1 82f1f17ce74f0cd3fca4813c178196b317fc952d installation.xml +HASH SHA1 68d9b548d61e31e82e8834690e884afa27751287 media.1/info.txt + diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/content.asc b/tests/repo/susetags/data/stable-x86-subset-gz/content.asc new file mode 100644 index 0000000000000000000000000000000000000000..63684d6fd357c475e7d6a78c2daa10ac0f599440 GIT binary patch literal 72 zcmV-O0Jr~$Mg#y60ssaD0#v?u9{>so5I?w{Iw!`k + + + + + control + + + true + true + false + never + 95 + true + true + simple + false + true + true + true + true + false + true + false + + + + + /root/ + /root/inst-sys/ + + + + + + false + auto + + + http://download.opensuse.org/YaST/Repos/openSUSE_103_Servers.xml + + + + false + true + 7G + 40 + 5G + 20G + false + false + 15G + 25G + false + + + + false + laptop + ifplugd + + + + language + keyboard + timezone + users + networking + firewall + host + routing + proxy + runlevel + x11 + nis + ldap + printer + add-on + + + + + + + + + + + + installation,demo,autoinstallation + initial + initial + no + + hwinfo + keyboard + mouse + partitions + software + bootloader + timezone + language + runlevel + + + + + + partitions + software_simple + country_simple + + + + + + hwinfo + keyboard + mouse + partitions + software + bootloader + timezone + language + runlevel + + + + + + + + update + initial + normal + no + + update + packages + backup + language + + + + + + update + initial + initial + no + + hwinfo + media + + update + packages + backup + language + keyboard + + + + + + network + continue,normal + yes + + + lan + 20 + + + general + 5 + + + dsl + 30 + + + isdn + 40 + + + modem + 50 + + + remote + 60 + + + firewall + 10 + + + proxy + 70 + + + + + + + hardware + continue + yes + + x11 + printer + sound + tv + bluetooth + + + + + + + + + all + yes + yes + + + installation + initial + + + language + + no + yes + + yes + + true + + + + checkmedia + + + + license + + + + disks_activate + + + + system_analysis + + + + + productsources + yes + + + + add-on + yes + + + + timezone + + yes + + yes + + + + desktop + + + yes + + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + no + + + + finish + no + + + + + + + + all + yes + yes + + + update + initial + + + language + + no + + yes + + true + + + + checkmedia + + + + license + + + + disks_activate + + + + system_analysis + + + + update_partition + + + upgrade_urls + + + + productsources + yes + + + + add-on + yes + + + yes + + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + no + + + + finish + no + + + + + + all + + initial + + repair + + + + info + + + + repair + + + + + + + + all + yes + yes + + initial + + screen_shot + + + no + yes + + language + true + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + yes + + + + + + + + all + yes + yes + + initial + + demo + + + no + + language + true + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + no + + + + + + + continue + update + + all + yes + yes + + + + + rpmcopy + no + no + + + yes + + + + + ask_net_test + no + + + + do_net_test + + + + addon_update_sources + + + + suse_register + + + + ask_online_update + + + + you + + + + restore_settings + + + suseconfig + no + no + + + + release_notes + + + congratulate + + + + + + + continue + installation + + yes + yes + all + + + + yes + + + + + root + no + + + + initialization + no + no + + + + netprobe + no + no + + + + rpmcopy + no + no + + + + hostname + + + + proposal + network + + + + fam + + + + ask_net_test + + + + do_net_test + + + + addon_update_sources + + + + suse_register + + + + ask_online_update + + + + you + + + + extrasources + + + + restore_settings + + + + auth + + + + user + + + suseconfig + no + no + + + + release_notes + + + + proposal + hardware + + + + save_hardware_status + + + congratulate + + + + + + + initial + + autoinstallation + + all + no + no + + + + + autoinit + all + true + + + + autosetup + + + + proposal + initial + no + yes + + + + prepdisk + + + + kickoff + + + + autoimage + + + + rpmcopy + + + + finish + + + + + + + + all + no + no + + continue + autoinstallation + + + + netprobe + + + + autopost + + + + rpmcopy + + + yes + + + + + autoconfigure + + + suseconfig + + + + + diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-0dfb3188-41ed929b.asc b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-0dfb3188-41ed929b.asc new file mode 100644 index 0000000..89fc35c --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-0dfb3188-41ed929b.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQGiBEHtkpsRBACRHiXh3olS++6/Mp9N7ByGMmjaaE+Y8cJQLUPG1myrbW5aogIP +0WenayhGbbgOHNWgd5dQ8KQpYYFoQuUHjFYzj5MvgrdOENOvD7ZNJ6+EmbkNh5cV +zUYfNG9jdiGweZkyA1sh8DYS0JiUmQ4CzaBD/DotB/dCmDcyuNQFiw4qKwCglQah +ATyueBRsOiXl0NIs1uB6dkkD/1A2YmQ6te1q38a1J+a8os6bDlMZhVnkZdhJdw6x +eBwUb9XS0n7hyt/AKCcBnrDEUQJuhBMNgzctJvbuMv27yRMANAXZDQkp0ip/yHLJ +PhUdSNTTRHOL9bV3t+JuZ9xmuclprwyrrJYUkEESXNc0tkuczHBP2c/RqA3OxYHt +hrHLA/9Pqe2gEleeo8l26u/uFXs2dtwjh8EZmdhHoqGcOlpYR4DyAg2D+jYfh3RI +oPzIwRlHVUR1ii5h8iPi98BVuEvukwfbbQ1K22Jwzxt6w3ihCXBKWKbeC3ElIMfA +hVMchLFUbTAw+yodO/u3NHxKQ34+ginid9dVyxV5T0gpDEEHObQrT3BlbiBFbnRl +cnByaXNlIFNlcnZlciA8c3VwcG9ydEBub3ZlbGwuY29tPoheBBMRAgAeBQJB7ZKb +AhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEHPSXWMN+zGID4oAoJPTGZbZApW+ +tuU422mHYGwoqgjrAJ9fhzRhRbV3YsOxKUomNeuIfmWGXA== +=Qv5+ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-307e3d54-44201d5d.asc b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-307e3d54-44201d5d.asc new file mode 100644 index 0000000..2d21c1b --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-307e3d54-44201d5d.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mIsERCAdXQEEAL7MrBTz+3SBWpCm2ae2yaDqV3ezQcs2JlvqidJVhsZqQe9/jkxi +KTEQW5+TXF/+BlQSiebunRI7oo3+9U8GyRCgs1sf+yRQWMLzZqRaarzRhw9w+Ihl +edtqYl6/U2JZCb8Adp6d7RzlRliJdJ/VtsfXj2ef7Dwu7elOVSsmaBdtAAYptChT +dVNFIFBhY2thZ2UgU2lnbmluZyBLZXkgPGJ1aWxkQHN1c2UuZGU+iLgEEwECACIF +AkQgHV0CGwMFCQQ9AoAECwcDAgMVAgMDFgIBAh4BAheAAAoJEOOlw2Awfj1UjUIE +AIf3SLlrfj2RsCDjyYThXen+A/WTYDPbY+NYmmVvFQilHNQY9ZrJ5cNohRQu6hA+ +Sccrf11Uy24tTHWSTzuG9VzFeeIAcIU02XHar0w3QbvTk6IqeG+OZlfOGJj1sdx4 +JKwpwk9mSdrq2ELhrkPZiVWS7RmRkPr2klwYgKGWbmOJ +=ZmDA +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-3d25d3d9-36e12d04.asc b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-3d25d3d9-36e12d04.asc new file mode 100644 index 0000000..894a463 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-3d25d3d9-36e12d04.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQENAzbhLQQAAAEIAKAkXHe0lWRBXLpn38hMHy03F0I4Sszmoc8aaKJrhfhyMlOA +BqvklPLE2f9UrI4Xc860gH79ZREwAgPt0pi6+SleNFLNcNFAuuHMLQOOsaMFatbz +JR9i4m/lf6q929YROu5zB48rBAlcfTm+IBbijaEdnqpwGib45wE/Cfy6FAttBHQh +1Kp+r/jPbf1mYAvljUfHKuvbg8t2EIQz/5yGp+n5trn9pElfQO2cRBq8LFpf1l+U +P7EKjFmlOq+Gs/fF98/dP3DfniSd78LQPq5vp8RL8nr/o2i7jkAQ33m4f1wOBWd+ +cZovrKXYlXiR+Bf7m2hpZo+/sAzhd7LmAD0l09kABRG0JVN1U0UgU2VjdXJpdHkg +VGVhbSA8c2VjdXJpdHlAc3VzZS5kZT6JARUDBRA24S1H5Fiyh7HKPEUBAVcOB/9b +yHYji1/+4Xc2GhvXK0FSJN0MGgeXgW47yxDL7gmR4mNgjlIOUHZj0PEpVjWepOJ7 +tQS3L9oP6cpj1Fj/XxuLbkp5VCQ61hpt54coQAvYrnT9rtWEGN+xmwejT1WmYmDJ +xG+EGBXKr+XP69oIUl1E2JO3rXeklulgjqRKos4cdXKgyjWZ7CP9V9daRXDtje63 +Om8gwSdU/nCvhdRIWp/Vwbf7Ia8iZr9OJ5YuQl0DBG4qmGDDrvImgPAFkYFzwlqo +choXFQ9y0YVCV41DnR+GYhwl2qBd81T8aXhihEGPIgaw3g8gd8B5o6mPVgl+nJqI +BkEYGBusiag2pS6qwznZiQEVAwUQNuEtBHey5gA9JdPZAQFtOAf+KVh939b0J94u +v/kpg4xs1LthlhquhbHcKNoVTNspugiC3qMPyvSX4XcBr2PC0cVkS4Z9PY9iCfT+ +x9WM96g39dAF+le2CCx7XISk9XXJ4ApEy5g4AuK7NYgAJd39PPbERgWnxjxir9g0 +Ix30dS30bW39D+3NPU5Ho9TD/B7UDFvYT5AWHl3MGwo3a1RhTs6sfgL7yQ3U+mvq +MkTExZb5mfN1FeaYKMopoI4VpzNVeGxQWIz67VjJHVyUlF20ekOz4kWVgsxkc8G2 +saqZd6yv2EwqYTi8BDAduweP33KrQc4KDDommQNDOXxaKOeCoESIdM4p7Esdjq1o +L0oixF12CohGBBARAgAGBQI7HmHDAAoJEJ5A4xAACqukTlQAoI4QzP9yjPohY7OU +F7J3eKBTzp25AJ42BmtSd3pvm5ldmognWF3Trhp+GYkAlQMFEDe3O8IWkDf+zvyS +FQEBAfkD/3GG5UgJj18UhYmh1gfjIlDcPAeqMwSytEHDENmHC+vlZQ/p0mT9tPiW +tp34io54mwr+bLPN8l6B5GJNkbGvH6M+mO7R8Lj4nHL6pyAv3PQr83WyLHcaX7It +Klj371/4yzKV6qpz43SGRK4MacLo2rNZ/dNej7lwPCtzCcFYwqkiiEYEEBECAAYF +AjoaQqQACgkQx1KqMrDf94ArewCfWnTUDG5gNYkmHG4bYL8fQcizyA4An2eVo/n+ +3J2KRWSOhpAMsnMxtPbB +=Ay23 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-7e2e3b05-44748aba.asc b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-7e2e3b05-44748aba.asc new file mode 100644 index 0000000..a4be6b8 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-7e2e3b05-44748aba.asc @@ -0,0 +1,20 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQGiBER0iroRBADfqUeJmPCXqPJFnf3CVKy40dL1F+gfvP+JHN7/uu4c9+oCYjI1 +uAE8iGTm/Twb/Zzbs4dt0iWjhNFXbRi42rMww4d/8QcPYZ21WSehh+fv8nCjt2sw +LeC87ar2SR8OTpJBK0fQlcd4e6H5GMntfI6SYEUOPd8m/eQ+4+1AxpUUpwCgswaF +13fePZGI//pDn5tGjbvmaP8D/R3qum/I+oDS8lbFeeDS10GkEkwTYec13gdfsq6I +yzIj7VBsC+rGfbipv+VGR61Q4d19pOHKLDekr9OG+3G4ZcYM4NQvQZR+QIlp3xWu +nBmYD1LRkHLVj+Z4DGQhjjOffkPSuacKPymMaZ/aRiLgTIAo97W2YPhutscXrLSG +2Y+BA/4jsyaDb7kbW4wc8RtPIcuFEheVqgBeRakP9Uj47kBMBEpPtI/mIdY5liKk +ztKnuQG6ROYLNV/PW0ZbE1uT64C710weh4cB3PnZLV5P10deDLBjHk8MJQGCTSDD +JYvhutUzQfshAU6j2kErGvKdZxWGezab34vFyMP2oLGqswPAJrRQTm92ZWxsIFBy +b3ZvIEJ1aWxkIChDb250YWN0IHNlY3VyaXR5QG5vdmVsbC5jb20pIDxub3ZlbGwt +cHJvdm8tYnVpbGRAbm92ZWxsLmNvbT6IZgQTEQIAJgUCRHSKugIbAwUJA8JnAAYL +CQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEBTCi8l+LjsFWEoAn13x+5ObqkW08gYF +YNDlcGPjQuGPAJ9kAQbVUvvh1u9mBgu91cQ9W/TkHYhGBBMRAgAGBQJEexD/AAoJ +EKhO2uicgArKFLwAn0B+g2mJ5n8LrBziTQ5SjnSPyDBXAJwJoYTta5Sfw/3vVGpU +fJAKVDoB9w== +=tJSz +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-9c800aca-40d8063e.asc b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-9c800aca-40d8063e.asc new file mode 100644 index 0000000..67eedcf --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-9c800aca-40d8063e.asc @@ -0,0 +1,37 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +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 +=pJli +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-a1912208-446a0899.asc b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-a1912208-446a0899.asc new file mode 100644 index 0000000..279397c --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/gpg-pubkey-a1912208-446a0899.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQILBERqCJkBEACdqhZWdAbUHLIumXMEgv+GFjr1ZzVHgynnFOzztU/8sxZNa9cm +YV4HZpVfjMr7fos3ArzyiPPt/336cf7w9p79/ZS4rHSNPDMlPCtXYvFxUbvU0/GY +q4jwcBsrJ0xaJ9CP5bWyAgVKOb7Y6k0ktaLjRR+tDfMsHA4H0ClMoRr6ATw8NL0e +VCfAHuzqCKvX1If8ng+wTivtAhKvz/WwQiELNELmPfc5tZHOw8NgP/r0Pze18Hn2 +dlAHu0WpC7uoR00vscsMIJiJJPcsxbL1F1eADKnk+wEy8Go+EJeJ5i0WoFbqD52q +Lv/C/oY6NVtVY0MBwtn+oQNSnQ4JBsB/Akdt53LAi0ZtNQxMyUW+76R8FCOmVCV8 +WGiF5CPRP0yvG80AMBjBjKjHb/v8ov5MnIyFimzAHS1gQcUNxTEYA/5eFwoYcGcK +weGq9FUjPTzLQAgvp7XmOzHpSAfJ7qysxFTepNsSZZhgizJyInrdQldr+GYcUNqB +krD9MWmFop975OxhCTEnNv/HcE79r8WD26HzDFYxTiTJbr0pU/ivBzo+rjq+YG2V +stJk+udVYmZTnC4LmXus8JiNuqBXbxNscwCBpcJ8YcfCV6uh+7E0XfXZsgVUFLp1 +NF+ylYRGTycOlWoZODrnJevZW7N9O3bWRx/G2P4bJD07LsDLe4i5hymf5QAGKbRQ +Tm92ZWxsIFByb3ZvIEJ1aWxkIChDb250YWN0IHNlY3VyaXR5QG5vdmVsbC5jb20p +IDxub3ZlbGwtcHJvdm8tYnVpbGRAbm92ZWxsLmNvbT6JAjMEEwECAB0FAkRqCJkG +CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRBHijLooZEiCKSFD/93vZHCAMLEfksU +KnvXl08bv1rfuamuyJnE3ANRE5RDyypriHMCnkVxazvQ2WI4W4UEjluL9+SzZwtV +ZvKVoAr31614nSyWwv2YnJTHfjMG+xRlkolZMnuIiB9PcCBo9+GPU0ABuzo4pEJW +NIRoSS1NFbAZBhtUnY0cN+trM5QObLl7xXTavLyGk//blkk57fov7GXsQJlZUig0 +l2yt5XNyGpLUnTMDumHh8b389quF+0+ZfdwOy7A768xjipAZiTvIujBrEv51wrxh +0HBT0VGA0MhD9t0B+Ce4BM9P/iVMO00naaOp6PqMfPPKxQQqer8qy1i6UWBx95SY +mKZBIvOm2d9PezDxkckCu61r6krx1iKnT1wdprCAkIYwALK118SpbxuyGW0bhRHc +wsc/akzWH72fS0Xu49mvL4k4A2U9asdeQid3dMgbtm5mSWof0yiU/G4YNn0yeXoY +oG1VbCAqQbFX1Rvd6GITJVqI+ekW/uMA9BP78dF8wBeG0+QmpQnSf+eOsxB/RT8o +Kb4hHY+29MUlg+i9ceVt7hoKr03J/uIG5TXFXRYLaI0iAFVlKfWxpqDfS2XA4+dD +VYt+5RDgBcnxDaTB4FE9GqcYScNfe7+NFtL0p0wOPftbmgZzGjucTmrD8mDUNdqA +xGK7vlk4GATSfOQlq7G6LXW6RYnInohGBBMRAgAGBQJEazMlAAoJEKhO2uicgArK +2vMAn0TbVDESEVKVuFZStrfIzOvJQrR9AJsH733Ju1kE99GFrdfCeGqpckmNhg== +=E+qN +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/installation.xml b/tests/repo/susetags/data/stable-x86-subset-gz/installation.xml new file mode 100644 index 0000000..f71e6b7 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/installation.xml @@ -0,0 +1,109 @@ + + + + control-ISSLE + + false + + + auto + + + true + + + + + + + + + + product + continue,normal + installation + + yast2-issleconfig + + + + + + + no + no + + normal + installation,normal + + + + sw_single + yes + yes + + + + issleconfig + yes + yes + + + + inst_release_notes + yes + yes + + + inst_congratulate + no + yes + + + + + + + + + no + no + + continue,normal + installation,normal,update + + hostname + root + ca_mgm + + + + yast2-issleconfig + + + + + suseconfig + + + + issleconfig + yes + yes + + + + + + + + diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/license.tar.gz b/tests/repo/susetags/data/stable-x86-subset-gz/license.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5d513d14d3ba6de2dc3e88d54c8b5dedfc2f5a94 GIT binary patch literal 45 vcmb2|=3uxU&gjj+{PrLtF9QR^p#|UlbNS2{0GSZbV9q@2o~$~91_J{C4>k&f literal 0 HcmV?d00001 diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/media.1/directory.yast b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/directory.yast new file mode 100644 index 0000000..f4fb49c --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/directory.yast @@ -0,0 +1,6 @@ +info.txt +license.zip +media +products +products.asc +products.key diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/media.1/info.txt b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/info.txt new file mode 100644 index 0000000..d5d1a49 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/info.txt @@ -0,0 +1,38 @@ + + openSUSE FACTORY 10.3-factory + + Attention! You are accessing our BETA Distribution. If you install + any package, note that we can NOT GIVE ANY SUPPORT for your system - + no matter if you update from a previous system or do a complete + new installation. + + Use this BETA distribution at your own risk! We recommend it for + testing, porting and evaluation purposes but not for any critical + production systems. + + If you are curious and would like to help us to find the bugs, you're + very welcome. Please enter bug reports following the instructions + given at http://bugs.opensuse.org . + If you want to talk about this distribution with others, you can + discuss on the mailing list opensuse-factory@opensuse.org. + + Sources for development releases are not distributed via mirrors to + reduce the bandwidth and storage on these mirrors. + + You can always find the latest source at + http://download.opensuse.org/distribution/SL-OSS-factory/ + + In case you need the exact source of this development release you can + find it on: + http://www.novell.com/products/opensuse/source_code.html + + Alternatively, see + http://www.novell.com/products/opensuse/source_code.html or send e-mail + to sourcedvd@suse.de to request the source + for a specific release of openSUSE on DVD. Please note that we will + charge $15 or 15 Euros to cover our costs of distribution. + + Use this distribution at your own risk - and remember to have a + lot of fun! :) + + Your openSUSE Team. diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/media.1/media b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/media new file mode 100644 index 0000000..d5aa1ef --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/media @@ -0,0 +1,3 @@ +SUSE Linux Products GmbH +20070705102239 +1 diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products new file mode 100644 index 0000000..5563ffd --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products @@ -0,0 +1 @@ +/ SuSE-Linux-STABLE-X86 10.3 diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.asc b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.asc new file mode 100644 index 0000000..c6f169d --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBGjNGIqE7a6JyACsoRAoWnAJkB1wTxOQngy5xvjTiUvwWp65wW5wCg +hCbA+jw64zZYCa7IM71hBBynFL4= +=nSHl +-----END PGP SIGNATURE----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.key b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.key new file mode 100644 index 0000000..67eedcf --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset-gz/media.1/products.key @@ -0,0 +1,37 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +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 +=pJli +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/kde-10.3-71.noarch.pat.gz b/tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/kde-10.3-71.noarch.pat.gz new file mode 100644 index 0000000000000000000000000000000000000000..9664f1dbed28d746a726a8d29def72934ba44d30 GIT binary patch literal 4692 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 W8XPK+Jup<`1OEgU220dvCjbEQsv+_K literal 0 HcmV?d00001 diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/packages.DU.gz b/tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/packages.DU.gz new file mode 100644 index 0000000000000000000000000000000000000000..c49020ede5244afad3c622f6764e2f6cab004d7d GIT binary patch literal 4491 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 dGTw$%%&D(K83^@wRXl(}|E7Nj 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 E0O-A<)c^nh literal 0 HcmV?d00001 diff --git a/tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/patterns.gz b/tests/repo/susetags/data/stable-x86-subset-gz/suse/setup/descr/patterns.gz new file mode 100644 index 0000000000000000000000000000000000000000..62e0eb3cfebdb402c1e9e17cd5b6880d756dfb1c GIT binary patch literal 45 zcmb2|=HOUdvM+>znc=jb=T%da3&z(>&99t3?XTl??t-?5&cjDc427NNDkK;f7yyvi B5mf*H literal 0 HcmV?d00001 diff --git a/tests/repo/susetags/data/stable-x86-subset/content b/tests/repo/susetags/data/stable-x86-subset/content new file mode 100644 index 0000000..215791f --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/content @@ -0,0 +1,42 @@ +PRODUCT openSUSE-factory +VERSION 10.3 +DISTPRODUCT SuSE-Linux-STABLE-X86 +DISTVERSION 10.2.42-factory +VENDOR SUSE LINUX Products GmbH, Nuernberg, Germany +RELNOTESURL http://www.suse.com/relnotes/i386/openSUSE/FACTORY/release-notes.rpm +ARCH.x86_64 x86_64 i686 i586 i486 i386 noarch +ARCH.i686 i686 i586 i486 i386 noarch +ARCH.i586 i586 i486 i386 noarch +ARCH.i486 i486 i386 noarch +ARCH.i386 i386 noarch +DEFAULTBASE i586 +REQUIRES openSUSE-release = 10.3 pattern:basesystem +PROVIDES product:openSUSE = 10.2.42 +OBSOLETES product:SUSE_LINUX product:openSUSE <= 10.2 +LINGUAS cs da de en en_GB es fi fr hu it ja km nl nb pl pt_BR zh_CN zh_TW +SHORTLABEL FACTORY +LABEL openSUSE FACTORY 10.3 +LABEL.de openSUSE FACTORY 10.3 +EXTRAURLS http://download.opensuse.org/distribution/10.2/repo/oss/ +OPTIONALURLS http://download.opensuse.org/distribution/10.2/repo/non-oss/ http://download.opensuse.org/distribution/10.2/repo/debug/ +DESCRDIR suse/setup/descr +DATADIR suse +FLAGS update +LANGUAGE en_US +META SHA1 c37f4ba4225650844363711710c3824a58c901dd kde-10.3-71.noarch.pat +META SHA1 80f9bb1f9e95ebcebfd9b22f338f779e204cd50b packages +META SHA1 9c341d93124860f03b001681513ca07b4d0ca873 packages.DU +META SHA1 a48fa507afccbce76b549a07394e41d9813e6b01 packages.en +META SHA1 765900f5513ce6bf496d5006bdff45f805e61997 packages.es +META SHA1 d3c628ac67854629ff98432bebef6c00aad9bb98 patterns +KEY SHA1 c0354069c10819674da8706822e1d4bd0c1797e9 gpg-pubkey-0dfb3188-41ed929b.asc +KEY SHA1 2e38e503c436c5d002bdc31755c82188044d9d21 gpg-pubkey-307e3d54-44201d5d.asc +KEY SHA1 7025932e6866932f489421990075f3ed312023ea gpg-pubkey-3d25d3d9-36e12d04.asc +KEY SHA1 fd6146cac8c1473c5b52548936de773d5bbd5610 gpg-pubkey-7e2e3b05-44748aba.asc +KEY SHA1 cd7adceba1fe5d7ba27b5749718743192d82f802 gpg-pubkey-9c800aca-40d8063e.asc +KEY SHA1 7535d79e31ef7b4232e5593bb49d9142978b2e95 gpg-pubkey-a1912208-446a0899.asc +HASH SHA1 875e73cf2ee139203208c860fbfd7fa5cb291c7e license.tar.gz +HASH SHA1 4aa8ded6302e6ec85690a51af6044dffe9b21923 control.xml +HASH SHA1 82f1f17ce74f0cd3fca4813c178196b317fc952d installation.xml +HASH SHA1 68d9b548d61e31e82e8834690e884afa27751287 media.1/info.txt + diff --git a/tests/repo/susetags/data/stable-x86-subset/content.asc b/tests/repo/susetags/data/stable-x86-subset/content.asc new file mode 100644 index 0000000000000000000000000000000000000000..e02b8bb6203d0f3cdfafc8fa8e5b4d863a15ec83 GIT binary patch literal 72 zcmV-O0Jr~$Mg#y60ssaD0#v?t5C94Z5I?w{Iw!`k + + + + + control + + + true + true + false + never + 95 + true + true + simple + false + true + true + true + true + false + true + false + + + + + /root/ + /root/inst-sys/ + + + + + + false + auto + + + http://download.opensuse.org/YaST/Repos/openSUSE_103_Servers.xml + + + + false + true + 7G + 40 + 5G + 20G + false + false + 15G + 25G + false + + + + false + laptop + ifplugd + + + + language + keyboard + timezone + users + networking + firewall + host + routing + proxy + runlevel + x11 + nis + ldap + printer + add-on + + + + + + + + + + + + installation,demo,autoinstallation + initial + initial + no + + hwinfo + keyboard + mouse + partitions + software + bootloader + timezone + language + runlevel + + + + + + partitions + software_simple + country_simple + + + + + + hwinfo + keyboard + mouse + partitions + software + bootloader + timezone + language + runlevel + + + + + + + + update + initial + normal + no + + update + packages + backup + language + + + + + + update + initial + initial + no + + hwinfo + media + + update + packages + backup + language + keyboard + + + + + + network + continue,normal + yes + + + lan + 20 + + + general + 5 + + + dsl + 30 + + + isdn + 40 + + + modem + 50 + + + remote + 60 + + + firewall + 10 + + + proxy + 70 + + + + + + + hardware + continue + yes + + x11 + printer + sound + tv + bluetooth + + + + + + + + + all + yes + yes + + + installation + initial + + + language + + no + yes + + yes + + true + + + + checkmedia + + + + license + + + + disks_activate + + + + system_analysis + + + + + productsources + yes + + + + add-on + yes + + + + timezone + + yes + + yes + + + + desktop + + + yes + + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + no + + + + finish + no + + + + + + + + all + yes + yes + + + update + initial + + + language + + no + + yes + + true + + + + checkmedia + + + + license + + + + disks_activate + + + + system_analysis + + + + update_partition + + + upgrade_urls + + + + productsources + yes + + + + add-on + yes + + + yes + + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + no + + + + finish + no + + + + + + all + + initial + + repair + + + + info + + + + repair + + + + + + + + all + yes + yes + + initial + + screen_shot + + + no + yes + + language + true + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + yes + + + + + + + + all + yes + yes + + initial + + demo + + + no + + language + true + + + + proposal + initial + + + + do_resize + false + i386,x86_64,ia64 + + + + prepdisk + + + + kickoff + + + + rpmcopy + no + no + + + + + + + continue + update + + all + yes + yes + + + + + rpmcopy + no + no + + + yes + + + + + ask_net_test + no + + + + do_net_test + + + + addon_update_sources + + + + suse_register + + + + ask_online_update + + + + you + + + + restore_settings + + + suseconfig + no + no + + + + release_notes + + + congratulate + + + + + + + continue + installation + + yes + yes + all + + + + yes + + + + + root + no + + + + initialization + no + no + + + + netprobe + no + no + + + + rpmcopy + no + no + + + + hostname + + + + proposal + network + + + + fam + + + + ask_net_test + + + + do_net_test + + + + addon_update_sources + + + + suse_register + + + + ask_online_update + + + + you + + + + extrasources + + + + restore_settings + + + + auth + + + + user + + + suseconfig + no + no + + + + release_notes + + + + proposal + hardware + + + + save_hardware_status + + + congratulate + + + + + + + initial + + autoinstallation + + all + no + no + + + + + autoinit + all + true + + + + autosetup + + + + proposal + initial + no + yes + + + + prepdisk + + + + kickoff + + + + autoimage + + + + rpmcopy + + + + finish + + + + + + + + all + no + no + + continue + autoinstallation + + + + netprobe + + + + autopost + + + + rpmcopy + + + yes + + + + + autoconfigure + + + suseconfig + + + + + diff --git a/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-0dfb3188-41ed929b.asc b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-0dfb3188-41ed929b.asc new file mode 100644 index 0000000..89fc35c --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-0dfb3188-41ed929b.asc @@ -0,0 +1,17 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQGiBEHtkpsRBACRHiXh3olS++6/Mp9N7ByGMmjaaE+Y8cJQLUPG1myrbW5aogIP +0WenayhGbbgOHNWgd5dQ8KQpYYFoQuUHjFYzj5MvgrdOENOvD7ZNJ6+EmbkNh5cV +zUYfNG9jdiGweZkyA1sh8DYS0JiUmQ4CzaBD/DotB/dCmDcyuNQFiw4qKwCglQah +ATyueBRsOiXl0NIs1uB6dkkD/1A2YmQ6te1q38a1J+a8os6bDlMZhVnkZdhJdw6x +eBwUb9XS0n7hyt/AKCcBnrDEUQJuhBMNgzctJvbuMv27yRMANAXZDQkp0ip/yHLJ +PhUdSNTTRHOL9bV3t+JuZ9xmuclprwyrrJYUkEESXNc0tkuczHBP2c/RqA3OxYHt +hrHLA/9Pqe2gEleeo8l26u/uFXs2dtwjh8EZmdhHoqGcOlpYR4DyAg2D+jYfh3RI +oPzIwRlHVUR1ii5h8iPi98BVuEvukwfbbQ1K22Jwzxt6w3ihCXBKWKbeC3ElIMfA +hVMchLFUbTAw+yodO/u3NHxKQ34+ginid9dVyxV5T0gpDEEHObQrT3BlbiBFbnRl +cnByaXNlIFNlcnZlciA8c3VwcG9ydEBub3ZlbGwuY29tPoheBBMRAgAeBQJB7ZKb +AhsDBgsJCAcDAgMVAgMDFgIBAh4BAheAAAoJEHPSXWMN+zGID4oAoJPTGZbZApW+ +tuU422mHYGwoqgjrAJ9fhzRhRbV3YsOxKUomNeuIfmWGXA== +=Qv5+ +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-307e3d54-44201d5d.asc b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-307e3d54-44201d5d.asc new file mode 100644 index 0000000..2d21c1b --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-307e3d54-44201d5d.asc @@ -0,0 +1,13 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mIsERCAdXQEEAL7MrBTz+3SBWpCm2ae2yaDqV3ezQcs2JlvqidJVhsZqQe9/jkxi +KTEQW5+TXF/+BlQSiebunRI7oo3+9U8GyRCgs1sf+yRQWMLzZqRaarzRhw9w+Ihl +edtqYl6/U2JZCb8Adp6d7RzlRliJdJ/VtsfXj2ef7Dwu7elOVSsmaBdtAAYptChT +dVNFIFBhY2thZ2UgU2lnbmluZyBLZXkgPGJ1aWxkQHN1c2UuZGU+iLgEEwECACIF +AkQgHV0CGwMFCQQ9AoAECwcDAgMVAgMDFgIBAh4BAheAAAoJEOOlw2Awfj1UjUIE +AIf3SLlrfj2RsCDjyYThXen+A/WTYDPbY+NYmmVvFQilHNQY9ZrJ5cNohRQu6hA+ +Sccrf11Uy24tTHWSTzuG9VzFeeIAcIU02XHar0w3QbvTk6IqeG+OZlfOGJj1sdx4 +JKwpwk9mSdrq2ELhrkPZiVWS7RmRkPr2klwYgKGWbmOJ +=ZmDA +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-3d25d3d9-36e12d04.asc b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-3d25d3d9-36e12d04.asc new file mode 100644 index 0000000..894a463 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-3d25d3d9-36e12d04.asc @@ -0,0 +1,30 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQENAzbhLQQAAAEIAKAkXHe0lWRBXLpn38hMHy03F0I4Sszmoc8aaKJrhfhyMlOA +BqvklPLE2f9UrI4Xc860gH79ZREwAgPt0pi6+SleNFLNcNFAuuHMLQOOsaMFatbz +JR9i4m/lf6q929YROu5zB48rBAlcfTm+IBbijaEdnqpwGib45wE/Cfy6FAttBHQh +1Kp+r/jPbf1mYAvljUfHKuvbg8t2EIQz/5yGp+n5trn9pElfQO2cRBq8LFpf1l+U +P7EKjFmlOq+Gs/fF98/dP3DfniSd78LQPq5vp8RL8nr/o2i7jkAQ33m4f1wOBWd+ +cZovrKXYlXiR+Bf7m2hpZo+/sAzhd7LmAD0l09kABRG0JVN1U0UgU2VjdXJpdHkg +VGVhbSA8c2VjdXJpdHlAc3VzZS5kZT6JARUDBRA24S1H5Fiyh7HKPEUBAVcOB/9b +yHYji1/+4Xc2GhvXK0FSJN0MGgeXgW47yxDL7gmR4mNgjlIOUHZj0PEpVjWepOJ7 +tQS3L9oP6cpj1Fj/XxuLbkp5VCQ61hpt54coQAvYrnT9rtWEGN+xmwejT1WmYmDJ +xG+EGBXKr+XP69oIUl1E2JO3rXeklulgjqRKos4cdXKgyjWZ7CP9V9daRXDtje63 +Om8gwSdU/nCvhdRIWp/Vwbf7Ia8iZr9OJ5YuQl0DBG4qmGDDrvImgPAFkYFzwlqo +choXFQ9y0YVCV41DnR+GYhwl2qBd81T8aXhihEGPIgaw3g8gd8B5o6mPVgl+nJqI +BkEYGBusiag2pS6qwznZiQEVAwUQNuEtBHey5gA9JdPZAQFtOAf+KVh939b0J94u +v/kpg4xs1LthlhquhbHcKNoVTNspugiC3qMPyvSX4XcBr2PC0cVkS4Z9PY9iCfT+ +x9WM96g39dAF+le2CCx7XISk9XXJ4ApEy5g4AuK7NYgAJd39PPbERgWnxjxir9g0 +Ix30dS30bW39D+3NPU5Ho9TD/B7UDFvYT5AWHl3MGwo3a1RhTs6sfgL7yQ3U+mvq +MkTExZb5mfN1FeaYKMopoI4VpzNVeGxQWIz67VjJHVyUlF20ekOz4kWVgsxkc8G2 +saqZd6yv2EwqYTi8BDAduweP33KrQc4KDDommQNDOXxaKOeCoESIdM4p7Esdjq1o +L0oixF12CohGBBARAgAGBQI7HmHDAAoJEJ5A4xAACqukTlQAoI4QzP9yjPohY7OU +F7J3eKBTzp25AJ42BmtSd3pvm5ldmognWF3Trhp+GYkAlQMFEDe3O8IWkDf+zvyS +FQEBAfkD/3GG5UgJj18UhYmh1gfjIlDcPAeqMwSytEHDENmHC+vlZQ/p0mT9tPiW +tp34io54mwr+bLPN8l6B5GJNkbGvH6M+mO7R8Lj4nHL6pyAv3PQr83WyLHcaX7It +Klj371/4yzKV6qpz43SGRK4MacLo2rNZ/dNej7lwPCtzCcFYwqkiiEYEEBECAAYF +AjoaQqQACgkQx1KqMrDf94ArewCfWnTUDG5gNYkmHG4bYL8fQcizyA4An2eVo/n+ +3J2KRWSOhpAMsnMxtPbB +=Ay23 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-7e2e3b05-44748aba.asc b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-7e2e3b05-44748aba.asc new file mode 100644 index 0000000..a4be6b8 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-7e2e3b05-44748aba.asc @@ -0,0 +1,20 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQGiBER0iroRBADfqUeJmPCXqPJFnf3CVKy40dL1F+gfvP+JHN7/uu4c9+oCYjI1 +uAE8iGTm/Twb/Zzbs4dt0iWjhNFXbRi42rMww4d/8QcPYZ21WSehh+fv8nCjt2sw +LeC87ar2SR8OTpJBK0fQlcd4e6H5GMntfI6SYEUOPd8m/eQ+4+1AxpUUpwCgswaF +13fePZGI//pDn5tGjbvmaP8D/R3qum/I+oDS8lbFeeDS10GkEkwTYec13gdfsq6I +yzIj7VBsC+rGfbipv+VGR61Q4d19pOHKLDekr9OG+3G4ZcYM4NQvQZR+QIlp3xWu +nBmYD1LRkHLVj+Z4DGQhjjOffkPSuacKPymMaZ/aRiLgTIAo97W2YPhutscXrLSG +2Y+BA/4jsyaDb7kbW4wc8RtPIcuFEheVqgBeRakP9Uj47kBMBEpPtI/mIdY5liKk +ztKnuQG6ROYLNV/PW0ZbE1uT64C710weh4cB3PnZLV5P10deDLBjHk8MJQGCTSDD +JYvhutUzQfshAU6j2kErGvKdZxWGezab34vFyMP2oLGqswPAJrRQTm92ZWxsIFBy +b3ZvIEJ1aWxkIChDb250YWN0IHNlY3VyaXR5QG5vdmVsbC5jb20pIDxub3ZlbGwt +cHJvdm8tYnVpbGRAbm92ZWxsLmNvbT6IZgQTEQIAJgUCRHSKugIbAwUJA8JnAAYL +CQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEBTCi8l+LjsFWEoAn13x+5ObqkW08gYF +YNDlcGPjQuGPAJ9kAQbVUvvh1u9mBgu91cQ9W/TkHYhGBBMRAgAGBQJEexD/AAoJ +EKhO2uicgArKFLwAn0B+g2mJ5n8LrBziTQ5SjnSPyDBXAJwJoYTta5Sfw/3vVGpU +fJAKVDoB9w== +=tJSz +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-9c800aca-40d8063e.asc b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-9c800aca-40d8063e.asc new file mode 100644 index 0000000..67eedcf --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-9c800aca-40d8063e.asc @@ -0,0 +1,37 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQGiBDnu9IERBACT8Y35+2vv4MGVKiLEMOl9GdST6MCkYS3yEKeueNWc+z/0Kvff +4JctBsgs47tjmiI9sl0eHjm3gTR8rItXMN6sJEUHWzDP+Y0PFPboMvKx0FXl/A0d +M+HFrruCgBlWt6FA+okRySQiliuI5phwqkXefl9AhkwR8xocQSVCFxcwvwCglVcO +QliHu8jwRQHxlRE0tkwQQI0D+wfQwKdvhDplxHJ5nf7U8c/yE/vdvpN6lF0tmFrK +XBUX+K7u4ifrZlQvj/81M4INjtXreqDiJtr99Rs6xa0ScZqITuZC4CWxJa9GynBE +D3+D2t1V/f8l0smsuYoFOF7Ib49IkTdbtwAThlZp8bEhELBeGaPdNCcmfZ66rKUd +G5sRA/9ovnc1krSQF2+sqB9/o7w5/q2qiyzwOSTnkjtBUVKn4zLUOf6aeBAoV6NM +CC3Kj9aZHfA+ND0ehPaVGJgjaVNFhPi4x0e7BULdvgOoAqajLfvkURHAeSsxXIoE +myW/xC1sBbDkDUIBSx5oej73XCZgnj/inphRqGpsb+1nKFvF+rQoU3VTRSBQYWNr +YWdlIFNpZ25pbmcgS2V5IDxidWlsZEBzdXNlLmRlPohiBBMRAgAiBQJA2AY+AhsD +BQkObd+9BAsHAwIDFQIDAxYCAQIeAQIXgAAKCRCoTtronIAKypCfAJ9RuZ6ZSV7Q +W4pTgTIxQ+ABPp0sIwCffG9bCNnrETPlgOn+dGEkAWegKL+IRgQQEQIABgUCOnBe +UgAKCRCeQOMQAAqrpNzOAKCL512FZvv4VZx94TpbA9lxyoAejACeOO1HIbActAev +k5MUBhNeLZa/qM2JARUDBRA6cGBvd7LmAD0l09kBATWnB/9An5vfiUUE1VQnt+T/ +EYklES3tXXaJJp9pHMa4fzFa8jPVtv5UBHGee3XoUNDVwM2OgSEISZxbzdXGnqIl +cT08TzBUD9i579uifklLsnr35SJDZ6ram51/CWOnnaVhUzneOA9gTPSr+/fT3WeV +nwJiQCQ30kNLWVXWATMnsnT486eAOlT6UNBPYQLpUprF5Yryk23pQUPAgJENDEqe +U6iIO9Ot1ZPtB0lniw+/xCi13D360o1tZDYOp0hHHJN3D3EN8C1yPqZd5CvvznYv +B6bWBIpWcRgdn2DUVMmpU661jwqGlRz1F84JG/xe4jGuzgpJt9IXSzyohEJB6XG5 ++D0BuQINBDnu9JIQCACEkdBN6Mxf5WvqDWkcMRy6wnrd9DYJ8UUTmIT2iQf07tRU +KJJ9v0JXfx2Z4d08IQSMNRaq4VgSe+PdYgIy0fbj23Via5/gO7fJEpD2hd2f+pMn +OWvH2rOOIbeYfuhzAc6BQjAKtmgR0ERUTafTM9Wb6F13CNZZNZfDqnFDP6L12w3z +3F7FFXkz07Rs3AIto1ZfYZd4sCSpMr/0S5nLrHbIvGLp271hhQBeRmmoGEKO2JRe +lGgUJ2CUzOdtwDIKT0LbCpvaP8PVnYF5IFoYJIWRHqlEt5ucTXstZy7vYjL6vTP4 +l5xs+LIOkNmPhqmfsgLzVo0UaLt80hOwc4NvDCOLAAMGB/9g+9V3ORzw4LvO1pwR +YJqfDKUq/EJ0rNMMD4N8RLpZRhKHKJUm9nNHLbksnlZwrbSTM5LpC/U6sheLP+l0 +bLVoq0lmsCcUSyh+mY6PxWirLIWCn/IAZAGnXb6Zd6TtIJlGG6pqUN8QxGJYQnon +l0uTJKHJENbI9sWHQdcTtBMc34gorHFCo1Bcvpnc1LFLrWn7mfoGx6INQjf3HGQp +MXAWuSBQhzkazY6vaWFpa8bBJ+gKbBuySWzNm3rFtT5HRKMWpO+M9bHp4d+puY0L +1YwN1OMatcMMpcWnZpiWiR83oi32+xtWUY2U7Ae38mMag8zFbpeqPQUsDv9V7CAJ +1dbriEwEGBECAAwFAkDYBnoFCQ5t3+gACgkQqE7a6JyACspnpgCfRbYwxT3iq+9l +/PgNTUNTZOlof2oAn25y0eGi0371jap9kOV6uq71sUuO +=pJli +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-a1912208-446a0899.asc b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-a1912208-446a0899.asc new file mode 100644 index 0000000..279397c --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/gpg-pubkey-a1912208-446a0899.asc @@ -0,0 +1,31 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +mQILBERqCJkBEACdqhZWdAbUHLIumXMEgv+GFjr1ZzVHgynnFOzztU/8sxZNa9cm +YV4HZpVfjMr7fos3ArzyiPPt/336cf7w9p79/ZS4rHSNPDMlPCtXYvFxUbvU0/GY +q4jwcBsrJ0xaJ9CP5bWyAgVKOb7Y6k0ktaLjRR+tDfMsHA4H0ClMoRr6ATw8NL0e +VCfAHuzqCKvX1If8ng+wTivtAhKvz/WwQiELNELmPfc5tZHOw8NgP/r0Pze18Hn2 +dlAHu0WpC7uoR00vscsMIJiJJPcsxbL1F1eADKnk+wEy8Go+EJeJ5i0WoFbqD52q +Lv/C/oY6NVtVY0MBwtn+oQNSnQ4JBsB/Akdt53LAi0ZtNQxMyUW+76R8FCOmVCV8 +WGiF5CPRP0yvG80AMBjBjKjHb/v8ov5MnIyFimzAHS1gQcUNxTEYA/5eFwoYcGcK +weGq9FUjPTzLQAgvp7XmOzHpSAfJ7qysxFTepNsSZZhgizJyInrdQldr+GYcUNqB +krD9MWmFop975OxhCTEnNv/HcE79r8WD26HzDFYxTiTJbr0pU/ivBzo+rjq+YG2V +stJk+udVYmZTnC4LmXus8JiNuqBXbxNscwCBpcJ8YcfCV6uh+7E0XfXZsgVUFLp1 +NF+ylYRGTycOlWoZODrnJevZW7N9O3bWRx/G2P4bJD07LsDLe4i5hymf5QAGKbRQ +Tm92ZWxsIFByb3ZvIEJ1aWxkIChDb250YWN0IHNlY3VyaXR5QG5vdmVsbC5jb20p +IDxub3ZlbGwtcHJvdm8tYnVpbGRAbm92ZWxsLmNvbT6JAjMEEwECAB0FAkRqCJkG +CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRBHijLooZEiCKSFD/93vZHCAMLEfksU +KnvXl08bv1rfuamuyJnE3ANRE5RDyypriHMCnkVxazvQ2WI4W4UEjluL9+SzZwtV +ZvKVoAr31614nSyWwv2YnJTHfjMG+xRlkolZMnuIiB9PcCBo9+GPU0ABuzo4pEJW +NIRoSS1NFbAZBhtUnY0cN+trM5QObLl7xXTavLyGk//blkk57fov7GXsQJlZUig0 +l2yt5XNyGpLUnTMDumHh8b389quF+0+ZfdwOy7A768xjipAZiTvIujBrEv51wrxh +0HBT0VGA0MhD9t0B+Ce4BM9P/iVMO00naaOp6PqMfPPKxQQqer8qy1i6UWBx95SY +mKZBIvOm2d9PezDxkckCu61r6krx1iKnT1wdprCAkIYwALK118SpbxuyGW0bhRHc +wsc/akzWH72fS0Xu49mvL4k4A2U9asdeQid3dMgbtm5mSWof0yiU/G4YNn0yeXoY +oG1VbCAqQbFX1Rvd6GITJVqI+ekW/uMA9BP78dF8wBeG0+QmpQnSf+eOsxB/RT8o +Kb4hHY+29MUlg+i9ceVt7hoKr03J/uIG5TXFXRYLaI0iAFVlKfWxpqDfS2XA4+dD +VYt+5RDgBcnxDaTB4FE9GqcYScNfe7+NFtL0p0wOPftbmgZzGjucTmrD8mDUNdqA +xGK7vlk4GATSfOQlq7G6LXW6RYnInohGBBMRAgAGBQJEazMlAAoJEKhO2uicgArK +2vMAn0TbVDESEVKVuFZStrfIzOvJQrR9AJsH733Ju1kE99GFrdfCeGqpckmNhg== +=E+qN +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset/installation.xml b/tests/repo/susetags/data/stable-x86-subset/installation.xml new file mode 100644 index 0000000..f71e6b7 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/installation.xml @@ -0,0 +1,109 @@ + + + + control-ISSLE + + false + + + auto + + + true + + + + + + + + + + product + continue,normal + installation + + yast2-issleconfig + + + + + + + no + no + + normal + installation,normal + + + + sw_single + yes + yes + + + + issleconfig + yes + yes + + + + inst_release_notes + yes + yes + + + inst_congratulate + no + yes + + + + + + + + + no + no + + continue,normal + installation,normal,update + + hostname + root + ca_mgm + + + + yast2-issleconfig + + + + + suseconfig + + + + issleconfig + yes + yes + + + + + + + + diff --git a/tests/repo/susetags/data/stable-x86-subset/license.tar.gz b/tests/repo/susetags/data/stable-x86-subset/license.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..5d513d14d3ba6de2dc3e88d54c8b5dedfc2f5a94 GIT binary patch literal 45 vcmb2|=3uxU&gjj+{PrLtF9QR^p#|UlbNS2{0GSZbV9q@2o~$~91_J{C4>k&f literal 0 HcmV?d00001 diff --git a/tests/repo/susetags/data/stable-x86-subset/media.1/directory.yast b/tests/repo/susetags/data/stable-x86-subset/media.1/directory.yast new file mode 100644 index 0000000..f4fb49c --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/media.1/directory.yast @@ -0,0 +1,6 @@ +info.txt +license.zip +media +products +products.asc +products.key diff --git a/tests/repo/susetags/data/stable-x86-subset/media.1/info.txt b/tests/repo/susetags/data/stable-x86-subset/media.1/info.txt new file mode 100644 index 0000000..d5d1a49 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/media.1/info.txt @@ -0,0 +1,38 @@ + + openSUSE FACTORY 10.3-factory + + Attention! You are accessing our BETA Distribution. If you install + any package, note that we can NOT GIVE ANY SUPPORT for your system - + no matter if you update from a previous system or do a complete + new installation. + + Use this BETA distribution at your own risk! We recommend it for + testing, porting and evaluation purposes but not for any critical + production systems. + + If you are curious and would like to help us to find the bugs, you're + very welcome. Please enter bug reports following the instructions + given at http://bugs.opensuse.org . + If you want to talk about this distribution with others, you can + discuss on the mailing list opensuse-factory@opensuse.org. + + Sources for development releases are not distributed via mirrors to + reduce the bandwidth and storage on these mirrors. + + You can always find the latest source at + http://download.opensuse.org/distribution/SL-OSS-factory/ + + In case you need the exact source of this development release you can + find it on: + http://www.novell.com/products/opensuse/source_code.html + + Alternatively, see + http://www.novell.com/products/opensuse/source_code.html or send e-mail + to sourcedvd@suse.de to request the source + for a specific release of openSUSE on DVD. Please note that we will + charge $15 or 15 Euros to cover our costs of distribution. + + Use this distribution at your own risk - and remember to have a + lot of fun! :) + + Your openSUSE Team. diff --git a/tests/repo/susetags/data/stable-x86-subset/media.1/media b/tests/repo/susetags/data/stable-x86-subset/media.1/media new file mode 100644 index 0000000..d5aa1ef --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/media.1/media @@ -0,0 +1,3 @@ +SUSE Linux Products GmbH +20070705102239 +1 diff --git a/tests/repo/susetags/data/stable-x86-subset/media.1/products b/tests/repo/susetags/data/stable-x86-subset/media.1/products new file mode 100644 index 0000000..5563ffd --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/media.1/products @@ -0,0 +1 @@ +/ SuSE-Linux-STABLE-X86 10.3 diff --git a/tests/repo/susetags/data/stable-x86-subset/media.1/products.asc b/tests/repo/susetags/data/stable-x86-subset/media.1/products.asc new file mode 100644 index 0000000..c6f169d --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/media.1/products.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.0.7 (GNU/Linux) + +iD8DBQBGjNGIqE7a6JyACsoRAoWnAJkB1wTxOQngy5xvjTiUvwWp65wW5wCg +hCbA+jw64zZYCa7IM71hBBynFL4= +=nSHl +-----END PGP SIGNATURE----- diff --git a/tests/repo/susetags/data/stable-x86-subset/media.1/products.key b/tests/repo/susetags/data/stable-x86-subset/media.1/products.key new file mode 100644 index 0000000..67eedcf --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/media.1/products.key @@ -0,0 +1,37 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.4-svn0 (GNU/Linux) + +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 +=pJli +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/kde-10.3-71.noarch.pat b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/kde-10.3-71.noarch.pat new file mode 100644 index 0000000..f3ccf93 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/kde-10.3-71.noarch.pat @@ -0,0 +1,178 @@ +# openSUSE Patterns 10.3-71.i586 -- (c) 2007 SUSE LINUX Products GmbH +# generated on Wed Jul 4 17:31:46 UTC 2007 + +=Ver: 5.0 + +=Pat: kde 10.3 71 i586 + +=Cat.cs: Grafická rozhraní +=Cat.da: Grafiske miljøer +=Cat.de: Grafische Umgebungen +=Cat: Graphical Environments +=Cat.en_GB: Graphical Environments +=Cat.es: Entornos gráficos +=Cat.et: Graafilised keskkonnad +=Cat.fi: Graafinen ympäristö +=Cat.fr: Environnements graphiques +=Cat.hr: Grafičko okruženje +=Cat.hu: Grafikus környezet +=Cat.id: Lingkungan Grafis +=Cat.it: Ambienti grafici +=Cat.ja: グラフィック環境 +=Cat.km: បរិស្ថាន​ក្រាហ្វិក +=Cat.lt: Grafinės aplinkos +=Cat.nb: Grafisk miljø +=Cat.nl: Grafische omgevingen +=Cat.pl: Środowiska graficzne +=Cat.pt_BR: Ambientes Gráficos +=Cat.ru: Графическое окружение +=Cat.sk: Grafické prostredia +=Cat.sv: Grafiska miljöer +=Cat.uk: Графічні середовища +=Cat.zh_CN: 图形环境 +=Cat.zh_TW: 圖形環境 + +=Ico: kde + +=Sum: KDE Desktop Environment +=Sum.bg: KDE Работна среда +=Sum.cs: Prostředí KDE +=Sum.da: KDE skrivebordsmiljø +=Sum.de: KDE Desktop-Umgebung +=Sum.el: ΠΡριβάλλον ΕπιφάνΡιας ΕργασΗας KDE +=Sum.en_GB: KDE Desktop Environment +=Sum.es: Escritorio KDE +=Sum.et: KDE töölaua keskkond +=Sum.fi: KDE-työpöytäympäristö +=Sum.fr: Environnement de bureau KDE +=Sum.hu: KDE asztali környezet +=Sum.it: Ambiente Desktop KDE +=Sum.ja: KDE デスクトップ環境 +=Sum.km: បរិស្ថាន​ផ្ទៃតុ KDE +=Sum.ko: KDE 데스크탑 환경 +=Sum.lt: KDE darbalaukio aplinka +=Sum.nb: Skrivebordsmiljøet KDE +=Sum.nl: KDE Desktop Environment +=Sum.pl: Środowisko graficzne KDE +=Sum.pt_BR: KDE Ambiente de Desktop +=Sum.ru: Рабочая среда KDE +=Sum.sk: Prostredie KDE +=Sum.sl: Namizno okolje KDE +=Sum.sv: Skrivbordsmiljön KDE +=Sum.uk: Стільничне середовище KDE +=Sum.zh_CN: KDE 桌面环境 +=Sum.zh_TW: KDE 桌面環境 + ++Des.bg: +KDE е мощна свободна графична среда за работни станции с Линукс, комбинираща в себе си лекота на употреба, съвременна функционалност и изключителен графичен дизайн с техническото превъзходство операционната система Линукс. +-Des.bg: ++Des.ca: +KDE és un potent entorn gràfic d'escriptori de programari lliure per a les estacions de treball de Linux. Combina la facilitat d'ús, la funcionalitat contemporània i un disseny gràfic excepcional amb la tecnologia del sistema operatiu Linux. +-Des.ca: ++Des.cs: +KDE je svobodné grafické prostředí pro pracovní stanice. Snoubí v sobě uživatelskou přívětivost, moderní funkcionalitu a atraktivní vzhled s linuxovou technologií. +-Des.cs: ++Des.da: +KDE er et stærkt grafisk skrivebordsmiljø til Linux-arbejdsstationer og er fri software. Det er bÃ¥de let at bruge, har mange funktioner og et flot grafisk design med teknologien fra Linux-operativsystemet. +-Des.da: ++Des.de: +KDE ist eine leistungsstarke kostenlose grafische Desktop-Umgebung für Linux-Arbeitsstationen. Das Programm kombiniert Benutzerfreundlichkeit, moderne Funktionsweise und hervorragendes grafisches Design mit der Technologie des Linux-Betriebssystems. +-Des.de: ++Des: +KDE is a powerful free software graphical desktop environment for Linux workstations. It combines ease of use, contemporary functionality, and outstanding graphical design with the technology of the Linux operating system. +-Des: ++Des.en_GB: +KDE is a powerful free software graphical desktop environment for Linux workstations. It combines ease of use, contemporary functionality, and outstanding graphical design with the technology of the Linux operating system. +-Des.en_GB: ++Des.es: +KDE es un potente programa escritorio gráfico gratuito para estaciones de trabajo Linux. Combina la facilidad de uso, funciones contemporáneas y un diseño gráfico insuperable con la tecnología del sistema operativo Linux. +-Des.es: ++Des.fi: +KDE on vaikuttava vapaa työpöytäympäristö Linux-työasemille. Siinä yhdistyy helppokäyttöisyys, käytettävyys ja upea graafinen suunnittelu Linux-käyttöjärjestelmäteknologian kanssa. +-Des.fi: ++Des.fr: +KDE est un environnement de bureau graphique gratuit et puissant pour les stations de travail Linux. Il allie simplicité d'utilisation, fonctionnalités modernes et conception graphique exceptionnelle grâce à la technologie du système d'exploitation Linux. +-Des.fr: ++Des.hr: +KDE je moćno besplatano grafičko okruženje radne povrÅ¡ine za Linux radne stanice. Kombinira lakoću koriÅ¡tenja, svakodnevnu funkcionalnost i izvrstan grafički dizajn zajedno s tehnologijom Linux operativnog sustava. +-Des.hr: ++Des.hu: +A KDE egy nagyteljesítményű, ingyenes, grafikus, asztali környezet Linux munkaállomásokhoz. Az egyszerű használatot, a modern funkcionalitást, valamint a kiemelkedő grafikai kivitelt egyesíti a Linux operációs rendszer technológiai előnyeivel. +-Des.hu: ++Des.id: +KDE merupakan lingkungan desktop grafis free software yang powerful untuk workstation Linux. Ia menggabungkan kemudahan, fungsionalitas kontemporer, dan desain grafis yang hebat dengan teknologi sistem operasi Linux. +-Des.id: ++Des.it: +KDE rappresenta un efficiente ambiente desktop grafico software gratuito per le workstation Linux. Associa facilità d'uso, funzioni aggiornate e ambiente grafico accattivante alla tecnologia del sistema operativo Linux. +-Des.it: ++Des.ja: +KDEは、Linuxワークステーション用の無料で強力なソフトウェアグラフィカルデスクトップ環境です。 使いやすさ、現代の機能性、そして優れたグラフィカルデザインをLinuxオペレーティングシステムの技術と統合します。 +-Des.ja: ++Des.km: +KDE គឺ​ជា​បរិស្ថាន​ផ្ទៃតុ​ក្រាហ្វិក​ឥត​គិត​ថ្លៃ​សម្រាប់​ស្ថានីយ​ការងារ​របស់​លីនុច ។ វា​រួមបញ្ចូល​នូវ​ភាព​ងាយស្រួល​ក្នុងការ​ប្រើប្រាស់ និង​មុខងារ​ដែល​វិវត្ត​តាម​សម័យកាល​ជានិច្ច ជាមួយ​នឹង​បច្ចេកវិជ្ជា​រចនា​ក្រាហ្វិក​គំរូ​តាម​​ប្រព័ន្ធ​ប្រតិបត្តិការ​លីនុច ។ +-Des.km: ++Des.lt: +KDE yra galinga nemokama grafinė darbalaukio aplinka Linux darbo stotims. Ji sujungia lengvą naudojimą, Å¡iuolaikinį funkcionalumą ir puikų grafinį dizainą su Linux operacinės sistemos technologijomis. +-Des.lt: ++Des.nb: +KDE er et effektivt og elegant grafisk skrivebordsmiljø for Linux-arbeidsstasjoner. KDE kombinerer brukervennlighet, avanserte funksjoner og lekker grafisk design med teknologien i Linux-operativsystemet. +-Des.nb: ++Des.nl: +KDE is een krachtige, vrije grafische desktop environment voor Linux-computers. Het combineert eenvoudig gebruik, uitgebreide functionaliteit en een uitstekend grafisch design met de technologie van het Linux-besturingssysteem. +-Des.nl: ++Des.pl: +KDE jest potężnym środowiskiem graficznym dla linuksowych stacji roboczych. Łączy łatwość obsługi, szerokie możliwości i atrakcyjny wygląd z technologiamisystemu operacyjnego Linux. +-Des.pl: ++Des.pt: +O KDE é um ambiente de trabalho gráfico livre e potente, para estações de trabalho Linux. Este combina a facilidade de utilização, funcionalidade contemporânea, e design gráfico de grande destaque, com a tecnologia do sistema operativo Linux. +-Des.pt: ++Des.pt_BR: +O KDE é um poderoso ambiente gráfico de área de trabalho de software gratuito para estações de trabalho Linux. Ele combina a facilidade de uso, a funcionalidade contemporânea e o excelente design gráfico à tecnologia do sistema operacional Linux. +-Des.pt_BR: ++Des.ru: +KDE это мощная бесплатная графическая система для Linux рабочих станций. Она комбинирует легкость в использовании, современную функциональность, превосходный дизайн с технологиями оперативной системы Linux. +-Des.ru: ++Des.sk: +KDE je výkonné grafické prostredie a slobodný softvér, pre linuxové pracovné stanice. Kombinuje jednoduchosž použitia, modernú funkcionalitu a výnimočný grafický dizajn spolu s technológiou operačného systému Linux. +-Des.sk: ++Des.sv: +KDE är en kraftfull fri programvara för grafisk skrivbordsmiljö för Linux-arbetsstationer. Den kombinerar användarvänlighet, moderna funktioner och fantastisk grafisk formgivning med tekniken hos operativsystemet Linux. +-Des.sv: ++Des.uk: +KDE - це потужне графічне середовище для робочих станцій Linux. Воно поєднує простоту використання, модерну функціональність та видатний графічний дизайн з операційною системою Linux. +-Des.uk: ++Des.zh_CN: +KDE 是一个软件图形桌面环境,它用于 Linux 工作站,不但功能强大,而且还可以免费使用。 它将先进的功能、独特的图形设计与 Linux 操作系统的技术相结合,使用方便。 +-Des.zh_CN: ++Des.zh_TW: +KDE 是針對 Linux 工作站所設計、功能強大的免費軟體圖形桌面環境。它將容易使用、現代化功能及傑出的圖形設計等結合到 Linux 作業系統之中。 +-Des.zh_TW: + ++Rec: +kde_internet +multimedia +office +kde_utilities +imaging +games +non_oss +non_oss_java +xgl +-Rec: + ++Req: +kde_basis +-Req: + +=Vis: true + +=Ord: 1520 + ++Prc: +opensuse-quickstart_en +-Prc: ++Psg: +kdeedu3 +kiosktool +-Psg: + diff --git a/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages new file mode 100644 index 0000000..8664af9 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages @@ -0,0 +1,512 @@ +##---------------------------------------- +=Pkg: kdelibs3 3.5.7 24 i586 +=Cks: SHA1 05f0647241433d01636785fd282cc824a6527269 ++Req: +rpmlib(VersionedDependencies) <= 3.0.3-1 +qt3 >= 3.3.8 +openssl +hicolor-icon-theme +sudo +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +/bin/sh +/usr/bin/perl +libDCOP.so.4 +libHalf.so.4 +libICE.so.6 +libIlmImf.so.4 +libSM.so.6 +libX11.so.6 +libXau.so.6 +libXcursor.so.1 +libXext.so.6 +libXfixes.so.3 +libXft.so.2 +libXi.so.6 +libXinerama.so.1 +libXrandr.so.2 +libXrender.so.1 +libacl.so.1 +libacl.so.1(ACL_1.0) +libart_lgpl_2.so.2 +libasound.so.2 +libasound.so.2(ALSA_0.9) +libaspell.so.15 +libattr.so.1 +libattr.so.1(ATTR_1.0) +libbz2.so.1 +libc.so.6 +libc.so.6(GLIBC_2.0) +libc.so.6(GLIBC_2.1) +libc.so.6(GLIBC_2.1.2) +libc.so.6(GLIBC_2.1.3) +libc.so.6(GLIBC_2.2) +libc.so.6(GLIBC_2.3) +libc.so.6(GLIBC_2.3.4) +libc.so.6(GLIBC_2.4) +libcups.so.2 +libdl.so.2 +libdl.so.2(GLIBC_2.0) +libdl.so.2(GLIBC_2.1) +libdns_sd.so.1 +libexpat.so.1 +libfam.so.0 +libfontconfig.so.1 +libfreetype.so.6 +libgcc_s.so.1 +libgcc_s.so.1(GCC_3.0) +libgcc_s.so.1(GLIBC_2.0) +libgssapi_krb5.so.2 +libgssapi_krb5.so.2(gssapi_krb5_2_MIT) +libidn.so.11 +libjasper.so.1 +libjpeg.so.62 +libkabc.so.1 +libkabc_dir.so.1 +libkabc_file.so.1 +libkabc_ldapkio.so.1 +libkatepartinterfaces.so.0 +libkdecore.so.4 +libkdefakes.so.4 +libkdefx.so.4 +libkdeinit_cupsdconf.so +libkdeinit_dcopserver.so +libkdeinit_kaddprinterwizard.so +libkdeinit_kbuildsycoca.so +libkdeinit_kcmshell.so +libkdeinit_kconf_update.so +libkdeinit_kcookiejar.so +libkdeinit_kded.so +libkdeinit_kio_http_cache_cleaner.so +libkdeinit_kio_uiserver.so +libkdeinit_klauncher.so +libkdeinit_knotify.so +libkdemm.so.0 +libkdeprint.so.4 +libkdeprint_management.so.4 +libkdesu.so.4 +libkdeui.so.4 +libkhtml.so.4 +libkio.so.4 +libkjs.so.1 +libkmediaplayer.so.0 +libknewstuff.so.1 +libkntlm.so.0 +libkparts.so.2 +libkresources.so.1 +libkscript.so.0 +libkspell2.so.1 +libktexteditor.so.0 +libkutils.so.1 +libkwalletbackend.so.1 +libkwalletclient.so.1 +libm.so.6 +libm.so.6(GLIBC_2.0) +libnetworkstatus.so.0 +libpcre.so.0 +libpng12.so.0 +libpthread.so.0 +libpthread.so.0(GLIBC_2.0) +libpthread.so.0(GLIBC_2.2) +libqt-mt.so.3 +libresolv.so.2 +libresolv.so.2(GLIBC_2.0) +libresolv.so.2(GLIBC_2.2) +libstdc++.so.6 +libstdc++.so.6(CXXABI_1.3) +libstdc++.so.6(CXXABI_1.3.1) +libstdc++.so.6(GLIBCXX_3.4) +libstdc++.so.6(GLIBCXX_3.4.9) +libtiff.so.3 +libutil.so.1 +libvcard.so.0 +libxcb-xlib.so.0 +libxcb.so.1 +libxml2.so.2 +libxslt.so.1 +libz.so.1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Req: ++Prq: +rpmlib(VersionedDependencies) <= 3.0.3-1 +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Prq: ++Prv: +kups +keramik +kdelibs3-cups +kdelibs3-33addons +kdepim3-networkstatus +kdelibs3_base = 3.3 +cupsdconf.so +dcopserver.so +highcolor.so +highcontrast.so +kabc_dir.so +kabc_file.so +kabc_ldapkio.so +kabcformat_binary.so +kaddprinterwizard.so +kbuildsycoca.so +kbzip2filter.so +kcm_kresources.so +kcmshell.so +kconf_update.so +kcookiejar.so +kded.so +kded_kcookiejar.so +kded_kdeprintd.so +kded_kdetrayproxy.so +kded_kpasswdserver.so +kded_kssld.so +kded_kwalletd.so +kded_networkstatus.so +kded_proxyscout.so +kdeprint_cups.so +kdeprint_ext.so +kdeprint_lpdunix.so +kdeprint_lpr.so +kdeprint_rlpr.so +kdeprint_tool_escputil.so +kdewidgets.so +keramik.so +kfileaudiopreview.so +kgzipfilter.so +khtmlimagepart.so +kimg_dds.so +kimg_eps.so +kimg_exr.so +kimg_hdr.so +kimg_ico.so +kimg_jp2.so +kimg_pcx.so +kimg_psd.so +kimg_rgb.so +kimg_tga.so +kimg_tiff.so +kimg_xcf.so +kimg_xview.so +kio_file.so +kio_ftp.so +kio_ghelp.so +kio_help.so +kio_http.so +kio_http_cache_cleaner.so +kio_metainfo.so +kio_uiserver.so +kjavaappletviewer.so +klauncher.so +knotify.so +kspell_aspell.so +kspell_ispell.so +kstyle_highcontrast_config.so +kstyle_plastik_config.so +ktexteditor_docwordcompletion.so +ktexteditor_insertfile.so +ktexteditor_isearch.so +ktexteditor_kdatatool.so +kthemestyle.so +libDCOP.so.4 +libconnectionmanager.so.0 +libkabc.so.1 +libkabc_dir.so.1 +libkabc_file.so.1 +libkabc_ldapkio.so.1 +libkatepart.so +libkatepartinterfaces.so.0 +libkcertpart.so +libkdecore.so.4 +libkdefakes.so.4 +libkdefx.so.4 +libkdeinit_cupsdconf.so +libkdeinit_dcopserver.so +libkdeinit_kaddprinterwizard.so +libkdeinit_kbuildsycoca.so +libkdeinit_kcmshell.so +libkdeinit_kconf_update.so +libkdeinit_kcookiejar.so +libkdeinit_kded.so +libkdeinit_kio_http_cache_cleaner.so +libkdeinit_kio_uiserver.so +libkdeinit_klauncher.so +libkdeinit_knotify.so +libkdemm.so.0 +libkdeprint.so.4 +libkdeprint_management.so.4 +libkdeprint_management_module.so +libkdesasl.so.1 +libkdesu.so.4 +libkdeui.so.4 +libkdnssd.so.1 +libkhtml.so.4 +libkhtmlpart.so +libkimproxy.so.0 +libkio.so.4 +libkjava.so.1 +libkjs.so.1 +libkmdi.so.1 +libkmdi2.so.1 +libkmediaplayer.so.0 +libkmid.so.0 +libkmultipart.so +libknewstuff.so.1 +libkntlm.so.0 +libkparts.so.2 +libkresources.so.1 +libkscreensaver.so.4 +libkscript.so.0 +libkspell.so.4 +libkspell2.so.1 +libktexteditor.so.0 +libkunittest.so.1 +libkutils.so.1 +libkwalletbackend.so.1 +libkwalletclient.so.1 +libnetworkstatus.so.0 +libshellscript.so +libvcard.so.0 +light.so +plastik.so +kdelibs3 = 3.5.7-24 +-Prv: ++Obs: +kde3-i18n +kups +keramik +kdelibs3-cups +kdelibs3-33addons +kdepim3-networkstatus +-Obs: ++Rec: +ispell +ispell_dictionary +enscript +-Rec: +=Grp: System/GUI/KDE +=Lic: BSD License and BSD-like, GNU General Public License (GPL) +=Src: kdelibs3 3.5.7 24 src +=Tim: 1183399094 +=Loc: 1 kdelibs3-3.5.7-24.i586.rpm +=Siz: 16356019 38850584 ++Aut: +The KDE Team +-Aut: +##---------------------------------------- +=Pkg: kdelibs3-arts 3.5.7 24 i586 +=Cks: SHA1 84d8c8e875395b8caaed90ae40bdfad3fe903eb7 ++Req: +arts >= 1.5.7 +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +libX11.so.6 +libartsflow.so.1 +libartsflow_idl.so.1 +libc.so.6 +libc.so.6(GLIBC_2.0) +libc.so.6(GLIBC_2.1.3) +libc.so.6(GLIBC_2.4) +libkdecore.so.4 +libkdeui.so.4 +libkio.so.4 +libkmedia2_idl.so.1 +libmcop.so.1 +libpthread.so.0 +libpthread.so.0(GLIBC_2.0) +libqt-mt.so.3 +libqtmcop.so.1 +libsoundserver_idl.so.1 +libstdc++.so.6 +libstdc++.so.6(CXXABI_1.3) +libstdc++.so.6(GLIBCXX_3.4) +libstdc++.so.6(GLIBCXX_3.4.9) +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Req: ++Prq: +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Prq: ++Prv: +kdelibs3:/opt/kde3/bin/artsmessage +libartskde.so.1 +kdelibs3-arts = 3.5.7-24 +-Prv: ++Rec: +kdemultimedia3-arts +-Rec: +=Grp: System/GUI/KDE +=Lic: BSD License and BSD-like, GNU General Public License (GPL) +=Src: kdelibs3 3.5.7 24 src +=Tim: 1183399094 +=Loc: 1 kdelibs3-arts-3.5.7-24.i586.rpm +=Siz: 183999 393828 ++Aut: +The KDE Team +-Aut: +##---------------------------------------- +=Pkg: kdelibs3-debuginfo 3.5.7 24 i586 +=Cks: SHA1 0f4c7798729fae70830fd03962dff8cdcadb7bdc ++Req: +kdelibs3 = 3.5.7-24 +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Req: ++Prq: +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Prq: ++Prv: +kdelibs3-debuginfo = 3.5.7-24 +-Prv: +=Grp: Development/Debug +=Lic: BSD License and BSD-like, GNU General Public License (GPL) +=Src: kdelibs3 3.5.7 24 src +=Tim: 1183399094 +=Loc: 1 kdelibs3-debuginfo-3.5.7-24.i586.rpm +=Siz: 44452218 139124954 ++Aut: +The KDE Team +-Aut: +##---------------------------------------- +=Pkg: kdelibs3-devel 3.5.7 24 i586 +=Cks: SHA1 46cfb73e29561af9e5445f6c525821856d067e61 ++Req: +qt3-devel +libvorbis-devel +kdelibs3 = 3.5.7 +autoconf +automake +libxslt-devel +libxml2-devel +libart_lgpl-devel +libjpeg-devel +kdelibs3-doc +libtiff-devel +openssl-devel +unsermake +update-desktop-files +libdrm-devel +dbus-1-qt3-devel +libattr-devel +libacl-devel +avahi-compat-mDNSResponder-devel +libbz2-devel +kdelibs3-arts +fam-devel +pcre-devel +libidn-devel +arts-devel +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +/bin/bash +/bin/sh +/usr/bin/env +/usr/bin/perl +libc.so.6 +libc.so.6(GLIBC_2.0) +libc.so.6(GLIBC_2.1.3) +libc.so.6(GLIBC_2.4) +libkdecore.so.4 +libkio.so.4 +libkunittest.so.1 +libqt-mt.so.3 +libstdc++.so.6 +libstdc++.so.6(CXXABI_1.3) +libstdc++.so.6(GLIBCXX_3.4) +libstdc++.so.6(GLIBCXX_3.4.9) +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Req: ++Prq: +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Prq: ++Prv: +perl(Ast) +perl(Iter) +perl(kalyptusCxxToDcopIDL) +perl(kdocAstUtil) +perl(kdocParseDoc) +perl(kdocUtil) +kdelibs3-devel = 3.5.7-24 +-Prv: +=Grp: System/GUI/KDE +=Lic: BSD License and BSD-like, GNU General Public License (GPL) +=Src: kdelibs3 3.5.7 24 src +=Tim: 1183399094 +=Loc: 1 kdelibs3-devel-3.5.7-24.i586.rpm +=Siz: 1403143 6898685 ++Aut: +The KDE Team +-Aut: +##---------------------------------------- +=Pkg: kdelibs3-doc 3.5.7 24 i586 +=Cks: SHA1 28714c6b0ab4dbed12039d511995d3085721ed4e ++Req: +sgml-skel +libxml2 +/usr/bin/sgml-register-catalog +/usr/bin/xmlcatalog +/usr/bin/edit-xml-catalog +sed +grep +awk +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +libbz2.so.1 +libc.so.6 +libc.so.6(GLIBC_2.0) +libc.so.6(GLIBC_2.1) +libc.so.6(GLIBC_2.4) +libkdecore.so.4 +libkio.so.4 +libqt-mt.so.3 +libstdc++.so.6 +libstdc++.so.6(CXXABI_1.3) +libstdc++.so.6(GLIBCXX_3.4) +libxml2.so.2 +libxslt.so.1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Req: ++Prq: +/usr/bin/sgml-register-catalog +/usr/bin/xmlcatalog +/usr/bin/edit-xml-catalog +sed +grep +awk +/bin/sh +/bin/sh +rpmlib(PayloadFilesHavePrefix) <= 4.0-1 +rpmlib(CompressedFileNames) <= 3.0.4-1 +rpmlib(PayloadIsBzip2) <= 3.0.5-1 +-Prq: ++Prv: +kdelibs3:/opt/kde3/share/apps/ksgmltools2 +kdelibs3_doc +kdelibs3-doc = 3.5.7-24 +-Prv: +=Grp: System/GUI/KDE +=Lic: BSD License and BSD-like, GNU General Public License (GPL) +=Src: kdelibs3 3.5.7 24 src +=Tim: 1183399094 +=Loc: 1 kdelibs3-doc-3.5.7-24.i586.rpm +=Siz: 918394 5908265 ++Aut: +The KDE Team +-Aut: +##---------------------------------------- \ No newline at end of file diff --git a/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.DU b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.DU new file mode 100644 index 0000000..462fb94 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.DU @@ -0,0 +1,498 @@ +##---------------------------------------- +=Pkg: kdelibs3 3.5.7 24 i586 ++Dir: +/ 0 39444 0 3068 +etc/ 1 12 1 1 +etc/xdg/ 0 12 0 1 +etc/xdg/menus/ 12 0 1 0 +opt/ 0 39366 0 3054 +opt/kde3/ 0 39366 0 3054 +opt/kde3/bin/ 1104 0 51 0 +opt/kde3/lib/ 19666 5798 53 152 +opt/kde3/lib/kde3/ 4968 830 138 14 +opt/kde3/lib/kde3/plugins/ 0 830 0 14 +opt/kde3/lib/kde3/plugins/designer/ 108 0 2 0 +opt/kde3/lib/kde3/plugins/styles/ 722 0 12 0 +opt/kde3/share/ 0 12798 0 2798 +opt/kde3/share/applications/ 0 13 0 1 +opt/kde3/share/applications/kde/ 13 0 1 0 +opt/kde3/share/apps/ 0 3902 0 410 +opt/kde3/share/apps/LICENSES/ 57 0 5 0 +opt/kde3/share/apps/kabc/ 229 4 1 1 +opt/kde3/share/apps/kabc/formats/ 4 0 1 0 +opt/kde3/share/apps/katepart/ 11 2194 2 134 +opt/kde3/share/apps/katepart/scripts/ 16 10 5 2 +opt/kde3/share/apps/katepart/scripts/indent/ 10 0 2 0 +opt/kde3/share/apps/katepart/syntax/ 2168 0 127 0 +opt/kde3/share/apps/kcertpart/ 1 0 1 0 +opt/kde3/share/apps/kcm_componentchooser/ 38 0 2 0 +opt/kde3/share/apps/kconf_update/ 8 0 8 0 +opt/kde3/share/apps/kdeprint/ 194 299 13 99 +opt/kde3/share/apps/kdeprint/filters/ 156 0 20 0 +opt/kde3/share/apps/kdeprint/icons/ 0 91 0 55 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/ 0 91 0 55 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/16x16/ 0 20 0 20 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/16x16/actions/ 3 0 3 0 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/16x16/apps/ 17 0 17 0 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/22x22/ 0 32 0 19 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/22x22/actions/ 31 0 18 0 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/22x22/apps/ 1 0 1 0 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/32x32/ 0 26 0 12 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/32x32/actions/ 3 0 1 0 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/32x32/apps/ 23 0 11 0 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/48x48/ 0 6 0 2 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/48x48/apps/ 6 0 2 0 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/64x64/ 0 7 0 2 +opt/kde3/share/apps/kdeprint/icons/crystalsvg/64x64/apps/ 7 0 2 0 +opt/kde3/share/apps/kdeprint/pics/ 25 0 18 0 +opt/kde3/share/apps/kdeprint/plugins/ 25 0 5 0 +opt/kde3/share/apps/kdeprint/tools/ 2 0 1 0 +opt/kde3/share/apps/kdeui/ 0 93 0 26 +opt/kde3/share/apps/kdeui/about/ 45 0 23 0 +opt/kde3/share/apps/kdeui/pics/ 48 0 3 0 +opt/kde3/share/apps/kdewidgets/ 0 60 0 42 +opt/kde3/share/apps/kdewidgets/pics/ 60 0 42 0 +opt/kde3/share/apps/khtml/ 6 50 4 12 +opt/kde3/share/apps/khtml/css/ 9 0 2 0 +opt/kde3/share/apps/khtml/icons/ 0 41 0 10 +opt/kde3/share/apps/khtml/icons/crystalsvg/ 0 41 0 10 +opt/kde3/share/apps/khtml/icons/crystalsvg/128x128/ 0 14 0 1 +opt/kde3/share/apps/khtml/icons/crystalsvg/128x128/actions/ 14 0 1 0 +opt/kde3/share/apps/khtml/icons/crystalsvg/16x16/ 0 4 0 3 +opt/kde3/share/apps/khtml/icons/crystalsvg/16x16/actions/ 4 0 3 0 +opt/kde3/share/apps/khtml/icons/crystalsvg/22x22/ 0 4 0 2 +opt/kde3/share/apps/khtml/icons/crystalsvg/22x22/actions/ 4 0 2 0 +opt/kde3/share/apps/khtml/icons/crystalsvg/32x32/ 0 6 0 2 +opt/kde3/share/apps/khtml/icons/crystalsvg/32x32/actions/ 6 0 2 0 +opt/kde3/share/apps/khtml/icons/crystalsvg/48x48/ 0 5 0 1 +opt/kde3/share/apps/khtml/icons/crystalsvg/48x48/actions/ 5 0 1 0 +opt/kde3/share/apps/khtml/icons/crystalsvg/64x64/ 0 8 0 1 +opt/kde3/share/apps/khtml/icons/crystalsvg/64x64/actions/ 8 0 1 0 +opt/kde3/share/apps/kio_uiserver/ 0 1 0 1 +opt/kde3/share/apps/kio_uiserver/icons/ 0 1 0 1 +opt/kde3/share/apps/kio_uiserver/icons/crystalsvg/ 0 1 0 1 +opt/kde3/share/apps/kio_uiserver/icons/crystalsvg/16x16/ 0 1 0 1 +opt/kde3/share/apps/kio_uiserver/icons/crystalsvg/16x16/apps/ 1 0 1 0 +opt/kde3/share/apps/kjava/ 156 2 3 1 +opt/kde3/share/apps/kjava/icons/ 0 2 0 1 +opt/kde3/share/apps/kjava/icons/crystalsvg/ 0 2 0 1 +opt/kde3/share/apps/kjava/icons/crystalsvg/16x16/ 0 2 0 1 +opt/kde3/share/apps/kjava/icons/crystalsvg/16x16/actions/ 2 0 1 0 +opt/kde3/share/apps/knewstuff/ 1 0 1 0 +opt/kde3/share/apps/knotify/ 119 0 1 0 +opt/kde3/share/apps/kssl/ 159 0 1 0 +opt/kde3/share/apps/kstyle/ 0 183 0 47 +opt/kde3/share/apps/kstyle/pixmaps/ 0 90 0 32 +opt/kde3/share/apps/kstyle/pixmaps/riscos/ 90 0 32 0 +opt/kde3/share/apps/kstyle/themes/ 93 0 15 0 +opt/kde3/share/apps/ktexteditor_docwordcompletion/ 1 0 1 0 +opt/kde3/share/apps/ktexteditor_insertfile/ 1 0 1 0 +opt/kde3/share/apps/ktexteditor_isearch/ 1 0 1 0 +opt/kde3/share/apps/ktexteditor_kdatatool/ 1 0 1 0 +opt/kde3/share/apps/proxyscout/ 33 0 1 0 +opt/kde3/share/autostart/ 7 0 1 0 +opt/kde3/share/config/ 202 18 10 6 +opt/kde3/share/config/colors/ 10 0 4 0 +opt/kde3/share/config/ui/ 8 0 2 0 +opt/kde3/share/emoticons/ 0 79 0 42 +opt/kde3/share/emoticons/Default/ 79 0 42 0 +opt/kde3/share/icons/ 0 6549 0 1906 +opt/kde3/share/icons/crystalsvg/ 8 6480 1 1898 +opt/kde3/share/icons/crystalsvg/128x128/ 0 1622 0 151 +opt/kde3/share/icons/crystalsvg/128x128/actions/ 27 0 3 0 +opt/kde3/share/icons/crystalsvg/128x128/apps/ 33 0 2 0 +opt/kde3/share/icons/crystalsvg/128x128/devices/ 269 0 22 0 +opt/kde3/share/icons/crystalsvg/128x128/filesystems/ 529 0 40 0 +opt/kde3/share/icons/crystalsvg/128x128/mimetypes/ 764 0 84 0 +opt/kde3/share/icons/crystalsvg/16x16/ 0 429 0 408 +opt/kde3/share/icons/crystalsvg/16x16/actions/ 248 0 228 0 +opt/kde3/share/icons/crystalsvg/16x16/apps/ 3 0 2 0 +opt/kde3/share/icons/crystalsvg/16x16/devices/ 47 0 47 0 +opt/kde3/share/icons/crystalsvg/16x16/filesystems/ 45 0 45 0 +opt/kde3/share/icons/crystalsvg/16x16/mimetypes/ 86 0 86 0 +opt/kde3/share/icons/crystalsvg/22x22/ 0 552 0 346 +opt/kde3/share/icons/crystalsvg/22x22/actions/ 316 0 211 0 +opt/kde3/share/icons/crystalsvg/22x22/apps/ 4 0 2 0 +opt/kde3/share/icons/crystalsvg/22x22/devices/ 41 0 23 0 +opt/kde3/share/icons/crystalsvg/22x22/filesystems/ 43 0 23 0 +opt/kde3/share/icons/crystalsvg/22x22/mimetypes/ 148 0 87 0 +opt/kde3/share/icons/crystalsvg/32x32/ 0 782 0 359 +opt/kde3/share/icons/crystalsvg/32x32/actions/ 347 0 181 0 +opt/kde3/share/icons/crystalsvg/32x32/apps/ 5 0 2 0 +opt/kde3/share/icons/crystalsvg/32x32/devices/ 119 0 47 0 +opt/kde3/share/icons/crystalsvg/32x32/filesystems/ 107 0 41 0 +opt/kde3/share/icons/crystalsvg/32x32/mimetypes/ 204 0 88 0 +opt/kde3/share/icons/crystalsvg/48x48/ 0 842 0 223 +opt/kde3/share/icons/crystalsvg/48x48/actions/ 148 0 39 0 +opt/kde3/share/icons/crystalsvg/48x48/apps/ 10 0 2 0 +opt/kde3/share/icons/crystalsvg/48x48/devices/ 185 0 47 0 +opt/kde3/share/icons/crystalsvg/48x48/filesystems/ 188 0 44 0 +opt/kde3/share/icons/crystalsvg/48x48/mimetypes/ 311 0 91 0 +opt/kde3/share/icons/crystalsvg/64x64/ 0 917 0 184 +opt/kde3/share/icons/crystalsvg/64x64/actions/ 21 0 5 0 +opt/kde3/share/icons/crystalsvg/64x64/apps/ 13 0 2 0 +opt/kde3/share/icons/crystalsvg/64x64/devices/ 258 0 47 0 +opt/kde3/share/icons/crystalsvg/64x64/filesystems/ 240 0 40 0 +opt/kde3/share/icons/crystalsvg/64x64/mimetypes/ 385 0 90 0 +opt/kde3/share/icons/crystalsvg/scalable/ 0 1336 0 227 +opt/kde3/share/icons/crystalsvg/scalable/actions/ 304 0 56 0 +opt/kde3/share/icons/crystalsvg/scalable/apps/ 7 0 1 0 +opt/kde3/share/icons/crystalsvg/scalable/devices/ 290 0 47 0 +opt/kde3/share/icons/crystalsvg/scalable/filesystems/ 212 0 44 0 +opt/kde3/share/icons/crystalsvg/scalable/mimetypes/ 523 0 79 0 +opt/kde3/share/icons/hicolor/ 0 61 0 7 +opt/kde3/share/icons/hicolor/128x128/ 0 24 0 1 +opt/kde3/share/icons/hicolor/128x128/apps/ 24 0 1 0 +opt/kde3/share/icons/hicolor/16x16/ 0 1 0 1 +opt/kde3/share/icons/hicolor/16x16/apps/ 1 0 1 0 +opt/kde3/share/icons/hicolor/22x22/ 0 2 0 1 +opt/kde3/share/icons/hicolor/22x22/apps/ 2 0 1 0 +opt/kde3/share/icons/hicolor/32x32/ 0 3 0 1 +opt/kde3/share/icons/hicolor/32x32/apps/ 3 0 1 0 +opt/kde3/share/icons/hicolor/48x48/ 0 5 0 1 +opt/kde3/share/icons/hicolor/48x48/apps/ 5 0 1 0 +opt/kde3/share/icons/hicolor/64x64/ 0 8 0 1 +opt/kde3/share/icons/hicolor/64x64/apps/ 8 0 1 0 +opt/kde3/share/icons/hicolor/scalable/ 0 18 0 1 +opt/kde3/share/icons/hicolor/scalable/apps/ 18 0 1 0 +opt/kde3/share/locale/ 259 0 1 0 +opt/kde3/share/mimelnk/ 42 1290 1 317 +opt/kde3/share/mimelnk/all/ 9 0 2 0 +opt/kde3/share/mimelnk/application/ 761 0 179 0 +opt/kde3/share/mimelnk/audio/ 101 0 27 0 +opt/kde3/share/mimelnk/image/ 144 0 38 0 +opt/kde3/share/mimelnk/inode/ 21 0 6 0 +opt/kde3/share/mimelnk/message/ 9 0 2 0 +opt/kde3/share/mimelnk/model/ 3 0 1 0 +opt/kde3/share/mimelnk/multipart/ 9 0 2 0 +opt/kde3/share/mimelnk/text/ 175 0 41 0 +opt/kde3/share/mimelnk/uri/ 12 0 6 0 +opt/kde3/share/mimelnk/video/ 46 0 13 0 +opt/kde3/share/services/ 226 80 62 12 +opt/kde3/share/services/kded/ 70 0 8 0 +opt/kde3/share/services/kresources/ 3 7 1 3 +opt/kde3/share/services/kresources/kabc/ 7 0 3 0 +opt/kde3/share/servicetypes/ 131 0 29 0 +usr/ 0 65 0 12 +usr/share/ 0 65 0 12 +usr/share/doc/ 0 57 0 6 +usr/share/doc/packages/ 0 57 0 6 +usr/share/doc/packages/kdelibs3/ 57 0 6 0 +usr/share/man/ 0 8 0 6 +usr/share/man/man1/ 4 0 3 0 +usr/share/man/man7/ 3 0 2 0 +usr/share/man/man8/ 1 0 1 0 +-Dir: +##---------------------------------------- +=Pkg: kdelibs3-arts 3.5.7 24 i586 ++Dir: +/ 0 386 0 2 +opt/ 0 386 0 2 +opt/kde3/ 0 386 0 2 +opt/kde3/bin/ 11 0 1 0 +opt/kde3/lib/ 375 0 1 0 +-Dir: +##---------------------------------------- +=Pkg: kdelibs3-debuginfo 3.5.7 24 i586 ++Dir: +/ 0 137630 0 3429 +usr/ 0 137630 0 3429 +usr/lib/ 0 106253 0 186 +usr/lib/debug/ 0 106253 0 186 +usr/lib/debug/opt/ 0 106253 0 186 +usr/lib/debug/opt/kde3/ 0 106253 0 186 +usr/lib/debug/opt/kde3/bin/ 8618 0 56 0 +usr/lib/debug/opt/kde3/lib/ 70633 27002 54 76 +usr/lib/debug/opt/kde3/lib/kde3/ 23702 3300 69 7 +usr/lib/debug/opt/kde3/lib/kde3/plugins/ 0 3300 0 7 +usr/lib/debug/opt/kde3/lib/kde3/plugins/designer/ 317 0 1 0 +usr/lib/debug/opt/kde3/lib/kde3/plugins/styles/ 2983 0 6 0 +usr/src/ 0 31377 0 3243 +usr/src/debug/ 0 31377 0 3243 +usr/src/debug/kdelibs-3.5.7/ 0 31377 0 3243 +usr/src/debug/kdelibs-3.5.7/arts/ 0 273 0 52 +usr/src/debug/kdelibs-3.5.7/arts/kde/ 235 0 45 0 +usr/src/debug/kdelibs-3.5.7/arts/knotify/ 35 0 6 0 +usr/src/debug/kdelibs-3.5.7/arts/message/ 3 0 1 0 +usr/src/debug/kdelibs-3.5.7/dcop/ 285 451 20 44 +usr/src/debug/kdelibs-3.5.7/dcop/KDE-ICE/ 359 0 31 0 +usr/src/debug/kdelibs-3.5.7/dcop/client/ 52 0 7 0 +usr/src/debug/kdelibs-3.5.7/dcop/dcopidl/ 3 0 1 0 +usr/src/debug/kdelibs-3.5.7/dcop/dcopidl2cpp/ 37 0 5 0 +usr/src/debug/kdelibs-3.5.7/dnssd/ 101 0 23 0 +usr/src/debug/kdelibs-3.5.7/interfaces/ 0 437 0 134 +usr/src/debug/kdelibs-3.5.7/interfaces/kimproxy/ 0 63 0 7 +usr/src/debug/kdelibs-3.5.7/interfaces/kimproxy/library/ 63 0 7 0 +usr/src/debug/kdelibs-3.5.7/interfaces/kio/ 2 0 1 0 +usr/src/debug/kdelibs-3.5.7/interfaces/kmediaplayer/ 33 10 8 3 +usr/src/debug/kdelibs-3.5.7/interfaces/kmediaplayer/kfileaudiopreview/ 10 0 3 0 +usr/src/debug/kdelibs-3.5.7/interfaces/kregexpeditor/ 5 0 1 0 +usr/src/debug/kdelibs-3.5.7/interfaces/kscript/ 28 9 6 3 +usr/src/debug/kdelibs-3.5.7/interfaces/kscript/sample/ 9 0 3 0 +usr/src/debug/kdelibs-3.5.7/interfaces/ktexteditor/ 287 0 105 0 +usr/src/debug/kdelibs-3.5.7/kab/ 217 0 9 0 +usr/src/debug/kdelibs-3.5.7/kabc/ 658 383 93 134 +usr/src/debug/kdelibs-3.5.7/kabc/formats/ 8 0 2 0 +usr/src/debug/kdelibs-3.5.7/kabc/plugins/ 0 124 0 21 +usr/src/debug/kdelibs-3.5.7/kabc/plugins/dir/ 25 0 7 0 +usr/src/debug/kdelibs-3.5.7/kabc/plugins/file/ 30 0 7 0 +usr/src/debug/kdelibs-3.5.7/kabc/plugins/ldapkio/ 69 0 7 0 +usr/src/debug/kdelibs-3.5.7/kabc/vcard/ 119 109 36 69 +usr/src/debug/kdelibs-3.5.7/kabc/vcard/include/ 76 33 36 33 +usr/src/debug/kdelibs-3.5.7/kabc/vcard/include/generated/ 33 0 33 0 +usr/src/debug/kdelibs-3.5.7/kabc/vcardparser/ 23 0 6 0 +usr/src/debug/kdelibs-3.5.7/kate/ 0 1740 0 108 +usr/src/debug/kdelibs-3.5.7/kate/interfaces/ 59 0 7 0 +usr/src/debug/kdelibs-3.5.7/kate/part/ 1592 0 89 0 +usr/src/debug/kdelibs-3.5.7/kate/plugins/ 0 89 0 12 +usr/src/debug/kdelibs-3.5.7/kate/plugins/insertfile/ 15 0 3 0 +usr/src/debug/kdelibs-3.5.7/kate/plugins/isearch/ 26 0 3 0 +usr/src/debug/kdelibs-3.5.7/kate/plugins/kdatatool/ 17 0 3 0 +usr/src/debug/kdelibs-3.5.7/kate/plugins/wordcompletion/ 31 0 3 0 +usr/src/debug/kdelibs-3.5.7/kcert/ 34 0 3 0 +usr/src/debug/kdelibs-3.5.7/kcmshell/ 22 0 6 0 +usr/src/debug/kdelibs-3.5.7/kconf_update/ 27 0 3 0 +usr/src/debug/kdelibs-3.5.7/kdecore/ 3210 768 259 50 +usr/src/debug/kdelibs-3.5.7/kdecore/kconfig_compiler/ 51 0 1 0 +usr/src/debug/kdelibs-3.5.7/kdecore/malloc/ 181 0 1 0 +usr/src/debug/kdelibs-3.5.7/kdecore/network/ 446 0 44 0 +usr/src/debug/kdelibs-3.5.7/kdecore/svgicons/ 90 0 4 0 +usr/src/debug/kdelibs-3.5.7/kded/ 218 0 32 0 +usr/src/debug/kdelibs-3.5.7/kdefx/ 337 0 14 0 +usr/src/debug/kdelibs-3.5.7/kdemm/ 78 0 21 0 +usr/src/debug/kdelibs-3.5.7/kdeprint/ 729 1418 126 353 +usr/src/debug/kdelibs-3.5.7/kdeprint/cups/ 337 224 73 58 +usr/src/debug/kdelibs-3.5.7/kdeprint/cups/cupsdconf2/ 224 0 58 0 +usr/src/debug/kdelibs-3.5.7/kdeprint/ext/ 14 0 7 0 +usr/src/debug/kdelibs-3.5.7/kdeprint/lpdunix/ 24 0 7 0 +usr/src/debug/kdelibs-3.5.7/kdeprint/lpr/ 141 0 35 0 +usr/src/debug/kdelibs-3.5.7/kdeprint/management/ 621 0 154 0 +usr/src/debug/kdelibs-3.5.7/kdeprint/rlpr/ 41 0 16 0 +usr/src/debug/kdelibs-3.5.7/kdeprint/tools/ 0 16 0 3 +usr/src/debug/kdelibs-3.5.7/kdeprint/tools/escputil/ 16 0 3 0 +usr/src/debug/kdelibs-3.5.7/kdesu/ 90 0 15 0 +usr/src/debug/kdelibs-3.5.7/kdeui/ 3964 22 362 7 +usr/src/debug/kdelibs-3.5.7/kdeui/kdetrayproxy/ 22 0 7 0 +usr/src/debug/kdelibs-3.5.7/kdewidgets/ 55 0 4 0 +usr/src/debug/kdelibs-3.5.7/kdoctools/ 56 0 8 0 +usr/src/debug/kdelibs-3.5.7/khtml/ 866 4750 44 283 +usr/src/debug/kdelibs-3.5.7/khtml/css/ 530 0 18 0 +usr/src/debug/kdelibs-3.5.7/khtml/dom/ 700 0 53 0 +usr/src/debug/kdelibs-3.5.7/khtml/ecma/ 827 0 48 0 +usr/src/debug/kdelibs-3.5.7/khtml/html/ 492 0 32 0 +usr/src/debug/kdelibs-3.5.7/khtml/java/ 174 0 21 0 +usr/src/debug/kdelibs-3.5.7/khtml/kmultipart/ 31 0 3 0 +usr/src/debug/kdelibs-3.5.7/khtml/misc/ 211 0 23 0 +usr/src/debug/kdelibs-3.5.7/khtml/rendering/ 1307 0 59 0 +usr/src/debug/kdelibs-3.5.7/khtml/xml/ 478 0 26 0 +usr/src/debug/kdelibs-3.5.7/kimgio/ 198 0 17 0 +usr/src/debug/kdelibs-3.5.7/kinit/ 182 0 18 0 +usr/src/debug/kdelibs-3.5.7/kio/ 0 4866 0 488 +usr/src/debug/kdelibs-3.5.7/kio/bookmarks/ 300 0 40 0 +usr/src/debug/kdelibs-3.5.7/kio/httpfilter/ 25 0 3 0 +usr/src/debug/kdelibs-3.5.7/kio/kfile/ 1289 0 124 0 +usr/src/debug/kdelibs-3.5.7/kio/kio/ 2424 0 201 0 +usr/src/debug/kdelibs-3.5.7/kio/kioexec/ 14 0 3 0 +usr/src/debug/kdelibs-3.5.7/kio/kpasswdserver/ 35 0 4 0 +usr/src/debug/kdelibs-3.5.7/kio/kssl/ 354 0 54 0 +usr/src/debug/kdelibs-3.5.7/kio/misc/ 95 326 10 48 +usr/src/debug/kdelibs-3.5.7/kio/misc/kdesasl/ 14 0 2 0 +usr/src/debug/kdelibs-3.5.7/kio/misc/kfile/ 18 0 2 0 +usr/src/debug/kdelibs-3.5.7/kio/misc/kntlm/ 46 0 5 0 +usr/src/debug/kdelibs-3.5.7/kio/misc/kpac/ 63 0 14 0 +usr/src/debug/kdelibs-3.5.7/kio/misc/ksendbugmail/ 27 0 6 0 +usr/src/debug/kdelibs-3.5.7/kio/misc/kssld/ 50 0 4 0 +usr/src/debug/kdelibs-3.5.7/kio/misc/kwalletd/ 108 0 15 0 +usr/src/debug/kdelibs-3.5.7/kio/tests/ 4 0 1 0 +usr/src/debug/kdelibs-3.5.7/kioslave/ 0 500 0 29 +usr/src/debug/kdelibs-3.5.7/kioslave/bzip2/ 8 0 2 0 +usr/src/debug/kdelibs-3.5.7/kioslave/file/ 61 0 3 0 +usr/src/debug/kdelibs-3.5.7/kioslave/ftp/ 94 0 2 0 +usr/src/debug/kdelibs-3.5.7/kioslave/gzip/ 13 0 2 0 +usr/src/debug/kdelibs-3.5.7/kioslave/http/ 204 115 6 12 +usr/src/debug/kdelibs-3.5.7/kioslave/http/kcookiejar/ 115 0 12 0 +usr/src/debug/kdelibs-3.5.7/kioslave/metainfo/ 5 0 2 0 +usr/src/debug/kdelibs-3.5.7/kjs/ 748 0 69 0 +usr/src/debug/kdelibs-3.5.7/kmdi/ 460 138 38 39 +usr/src/debug/kdelibs-3.5.7/kmdi/kmdi/ 116 0 17 0 +usr/src/debug/kdelibs-3.5.7/kmdi/res/ 22 0 22 0 +usr/src/debug/kdelibs-3.5.7/knewstuff/ 182 0 31 0 +usr/src/debug/kdelibs-3.5.7/kparts/ 317 0 37 0 +usr/src/debug/kdelibs-3.5.7/kresources/ 123 0 26 0 +usr/src/debug/kdelibs-3.5.7/kspell2/ 92 275 23 36 +usr/src/debug/kdelibs-3.5.7/kspell2/plugins/ 0 204 0 19 +usr/src/debug/kdelibs-3.5.7/kspell2/plugins/aspell/ 14 0 5 0 +usr/src/debug/kdelibs-3.5.7/kspell2/plugins/ispell/ 190 0 14 0 +usr/src/debug/kdelibs-3.5.7/kspell2/ui/ 71 0 17 0 +usr/src/debug/kdelibs-3.5.7/kstyles/ 0 1078 0 46 +usr/src/debug/kdelibs-3.5.7/kstyles/highcolor/ 69 0 4 0 +usr/src/debug/kdelibs-3.5.7/kstyles/highcontrast/ 60 9 3 3 +usr/src/debug/kdelibs-3.5.7/kstyles/highcontrast/config/ 9 0 3 0 +usr/src/debug/kdelibs-3.5.7/kstyles/keramik/ 436 0 13 0 +usr/src/debug/kdelibs-3.5.7/kstyles/kthemestyle/ 203 0 8 0 +usr/src/debug/kdelibs-3.5.7/kstyles/light/ 112 0 7 0 +usr/src/debug/kdelibs-3.5.7/kstyles/plastik/ 167 18 4 3 +usr/src/debug/kdelibs-3.5.7/kstyles/plastik/config/ 18 0 3 0 +usr/src/debug/kdelibs-3.5.7/kstyles/utils/ 0 4 0 1 +usr/src/debug/kdelibs-3.5.7/kstyles/utils/installtheme/ 4 0 1 0 +usr/src/debug/kdelibs-3.5.7/kunittest/ 61 0 7 0 +usr/src/debug/kdelibs-3.5.7/kutils/ 374 66 42 12 +usr/src/debug/kdelibs-3.5.7/kutils/ksettings/ 66 0 12 0 +usr/src/debug/kdelibs-3.5.7/kwallet/ 0 110 0 18 +usr/src/debug/kdelibs-3.5.7/kwallet/backend/ 68 0 13 0 +usr/src/debug/kdelibs-3.5.7/kwallet/client/ 42 0 5 0 +usr/src/debug/kdelibs-3.5.7/libkmid/ 250 0 32 0 +usr/src/debug/kdelibs-3.5.7/libkscreensaver/ 25 0 5 0 +usr/src/debug/kdelibs-3.5.7/libltdl/ 79 0 2 0 +usr/src/debug/kdelibs-3.5.7/networkstatus/ 63 0 20 0 +usr/src/debug/kdelibs-3.5.7/pics/ 1 0 1 0 +-Dir: +##---------------------------------------- +=Pkg: kdelibs3-devel 3.5.7 24 i586 ++Dir: +/ 0 7141 0 791 +etc/ 0 5 0 1 +etc/opt/ 0 5 0 1 +etc/opt/kde3/ 5 0 1 0 +opt/ 0 7136 0 790 +opt/kde3/ 0 7136 0 790 +opt/kde3/bin/ 130 0 7 0 +opt/kde3/include/ 4111 1867 415 289 +opt/kde3/include/arts/ 59 0 10 0 +opt/kde3/include/dnssd/ 30 0 7 0 +opt/kde3/include/dom/ 420 0 29 0 +opt/kde3/include/kabc/ 202 0 43 0 +opt/kde3/include/kate/ 22 0 2 0 +opt/kde3/include/kdemm/ 26 0 7 0 +opt/kde3/include/kdeprint/ 63 8 14 3 +opt/kde3/include/kdeprint/lpr/ 8 0 3 0 +opt/kde3/include/kdesu/ 25 0 8 0 +opt/kde3/include/khexedit/ 26 0 5 0 +opt/kde3/include/kio/ 332 0 37 0 +opt/kde3/include/kjs/ 120 0 17 0 +opt/kde3/include/kmdi/ 16 0 4 0 +opt/kde3/include/kmediaplayer/ 11 0 3 0 +opt/kde3/include/knewstuff/ 47 0 10 0 +opt/kde3/include/kparts/ 125 0 14 0 +opt/kde3/include/kresources/ 43 0 9 0 +opt/kde3/include/ksettings/ 20 0 4 0 +opt/kde3/include/kspell2/ 32 0 10 0 +opt/kde3/include/ktexteditor/ 97 0 33 0 +opt/kde3/include/kunittest/ 43 0 3 0 +opt/kde3/include/libkmid/ 100 0 17 0 +opt/kde3/lib/ 84 0 43 0 +opt/kde3/share/ 0 944 0 36 +opt/kde3/share/apps/ 0 944 0 36 +opt/kde3/share/apps/dcopidlng/ 82 0 7 0 +opt/kde3/share/apps/kdelibs/ 0 862 0 29 +opt/kde3/share/apps/kdelibs/admin/ 862 0 29 0 +-Dir: +##---------------------------------------- +=Pkg: kdelibs3-doc 3.5.7 24 i586 ++Dir: +/ 0 6378 0 1199 +etc/ 0 1 0 1 +etc/xml/ 1 0 1 0 +opt/ 0 6377 0 1198 +opt/kde3/ 0 6377 0 1198 +opt/kde3/bin/ 43 0 1 0 +opt/kde3/share/ 0 6334 0 1197 +opt/kde3/share/apps/ 0 6003 0 1145 +opt/kde3/share/apps/ksgmltools2/ 0 6003 0 1145 +opt/kde3/share/apps/ksgmltools2/customization/ 66 940 16 487 +opt/kde3/share/apps/ksgmltools2/customization/af/ 7 9 4 9 +opt/kde3/share/apps/ksgmltools2/customization/af/entities/ 9 0 9 0 +opt/kde3/share/apps/ksgmltools2/customization/bg/ 5 0 2 0 +opt/kde3/share/apps/ksgmltools2/customization/ca/ 11 14 4 13 +opt/kde3/share/apps/ksgmltools2/customization/ca/entities/ 14 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/cs/ 7 1 3 1 +opt/kde3/share/apps/ksgmltools2/customization/cs/entities/ 1 0 1 0 +opt/kde3/share/apps/ksgmltools2/customization/da/ 11 14 4 13 +opt/kde3/share/apps/ksgmltools2/customization/da/entities/ 14 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/de/ 11 19 4 14 +opt/kde3/share/apps/ksgmltools2/customization/de/entities/ 19 0 14 0 +opt/kde3/share/apps/ksgmltools2/customization/dtd/ 19 0 4 0 +opt/kde3/share/apps/ksgmltools2/customization/el/ 5 1 2 1 +opt/kde3/share/apps/ksgmltools2/customization/el/entities/ 1 0 1 0 +opt/kde3/share/apps/ksgmltools2/customization/en-GB/ 7 2 3 1 +opt/kde3/share/apps/ksgmltools2/customization/en-GB/entities/ 2 0 1 0 +opt/kde3/share/apps/ksgmltools2/customization/en/ 9 2 4 2 +opt/kde3/share/apps/ksgmltools2/customization/en/entities/ 2 0 2 0 +opt/kde3/share/apps/ksgmltools2/customization/entities/ 76 0 3 0 +opt/kde3/share/apps/ksgmltools2/customization/es/ 10 14 4 13 +opt/kde3/share/apps/ksgmltools2/customization/es/entities/ 14 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/et/ 9 14 4 13 +opt/kde3/share/apps/ksgmltools2/customization/et/entities/ 14 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/fi/ 7 4 4 4 +opt/kde3/share/apps/ksgmltools2/customization/fi/entities/ 4 0 4 0 +opt/kde3/share/apps/ksgmltools2/customization/fo/ 7 14 4 9 +opt/kde3/share/apps/ksgmltools2/customization/fo/entities/ 14 0 9 0 +opt/kde3/share/apps/ksgmltools2/customization/fr/ 51 15 4 13 +opt/kde3/share/apps/ksgmltools2/customization/fr/entities/ 15 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/he/ 8 17 4 12 +opt/kde3/share/apps/ksgmltools2/customization/he/entities/ 17 0 12 0 +opt/kde3/share/apps/ksgmltools2/customization/hu/ 7 6 3 5 +opt/kde3/share/apps/ksgmltools2/customization/hu/entities/ 6 0 5 0 +opt/kde3/share/apps/ksgmltools2/customization/id/ 6 4 3 3 +opt/kde3/share/apps/ksgmltools2/customization/id/entities/ 4 0 3 0 +opt/kde3/share/apps/ksgmltools2/customization/it/ 10 18 4 13 +opt/kde3/share/apps/ksgmltools2/customization/it/entities/ 18 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/ja/ 6 0 3 0 +opt/kde3/share/apps/ksgmltools2/customization/ko/ 6 7 3 7 +opt/kde3/share/apps/ksgmltools2/customization/ko/entities/ 7 0 7 0 +opt/kde3/share/apps/ksgmltools2/customization/lt/ 5 0 2 0 +opt/kde3/share/apps/ksgmltools2/customization/nl/ 23 16 4 13 +opt/kde3/share/apps/ksgmltools2/customization/nl/entities/ 16 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/nn/ 11 14 4 11 +opt/kde3/share/apps/ksgmltools2/customization/nn/entities/ 14 0 11 0 +opt/kde3/share/apps/ksgmltools2/customization/no/ 7 14 4 13 +opt/kde3/share/apps/ksgmltools2/customization/no/entities/ 14 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/obsolete/ 36 0 5 0 +opt/kde3/share/apps/ksgmltools2/customization/pl/ 20 13 4 12 +opt/kde3/share/apps/ksgmltools2/customization/pl/entities/ 13 0 12 0 +opt/kde3/share/apps/ksgmltools2/customization/pt-BR/ 9 14 4 13 +opt/kde3/share/apps/ksgmltools2/customization/pt-BR/entities/ 14 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/pt/ 12 13 5 12 +opt/kde3/share/apps/ksgmltools2/customization/pt/entities/ 13 0 12 0 +opt/kde3/share/apps/ksgmltools2/customization/ro/ 11 14 4 13 +opt/kde3/share/apps/ksgmltools2/customization/ro/entities/ 14 0 13 0 +opt/kde3/share/apps/ksgmltools2/customization/ru/ 9 15 4 11 +opt/kde3/share/apps/ksgmltools2/customization/ru/entities/ 15 0 11 0 +opt/kde3/share/apps/ksgmltools2/customization/sk/ 7 12 3 11 +opt/kde3/share/apps/ksgmltools2/customization/sk/entities/ 12 0 11 0 +opt/kde3/share/apps/ksgmltools2/customization/sl/ 8 12 4 11 +opt/kde3/share/apps/ksgmltools2/customization/sl/entities/ 12 0 11 0 +opt/kde3/share/apps/ksgmltools2/customization/sr/ 40 18 4 12 +opt/kde3/share/apps/ksgmltools2/customization/sr/entities/ 18 0 12 0 +opt/kde3/share/apps/ksgmltools2/customization/sv/ 7 13 4 12 +opt/kde3/share/apps/ksgmltools2/customization/sv/entities/ 13 0 12 0 +opt/kde3/share/apps/ksgmltools2/customization/tr/ 5 13 2 9 +opt/kde3/share/apps/ksgmltools2/customization/tr/entities/ 13 0 9 0 +opt/kde3/share/apps/ksgmltools2/customization/uk/ 9 0 4 0 +opt/kde3/share/apps/ksgmltools2/customization/wa/ 5 0 2 0 +opt/kde3/share/apps/ksgmltools2/customization/xh/ 5 0 2 0 +opt/kde3/share/apps/ksgmltools2/customization/xsl/ 28 0 28 0 +opt/kde3/share/apps/ksgmltools2/customization/xx/ 5 0 2 0 +opt/kde3/share/apps/ksgmltools2/customization/zh-CN/ 7 8 3 5 +opt/kde3/share/apps/ksgmltools2/customization/zh-CN/entities/ 8 0 5 0 +opt/kde3/share/apps/ksgmltools2/customization/zh-TW/ 7 5 3 5 +opt/kde3/share/apps/ksgmltools2/customization/zh-TW/entities/ 5 0 5 0 +opt/kde3/share/apps/ksgmltools2/docbook/ 1 4996 1 641 +opt/kde3/share/apps/ksgmltools2/docbook/xml-dtd-4.1.2/ 311 67 13 19 +opt/kde3/share/apps/ksgmltools2/docbook/xml-dtd-4.1.2/ent/ 67 0 19 0 +opt/kde3/share/apps/ksgmltools2/docbook/xml-dtd-4.2/ 321 0 11 0 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/ 31 4266 6 592 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/common/ 2232 0 60 0 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/html/ 1291 0 58 0 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/images/ 58 31 29 31 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/images/callouts/ 31 0 31 0 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/lib/ 70 0 4 0 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/manpages/ 43 0 7 0 +opt/kde3/share/apps/ksgmltools2/docbook/xsl/params/ 541 0 403 0 +opt/kde3/share/doc/ 0 331 0 52 +opt/kde3/share/doc/HTML/ 0 331 0 52 +opt/kde3/share/doc/HTML/en/ 0 331 0 52 +opt/kde3/share/doc/HTML/en/common/ 320 0 50 0 +opt/kde3/share/doc/HTML/en/kspell/ 11 0 2 0 +-Dir: +##---------------------------------------- \ No newline at end of file diff --git a/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.en b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.en new file mode 100644 index 0000000..d1ece01 --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.en @@ -0,0 +1,47 @@ +##---------------------------------------- +=Pkg: kdelibs3 3.5.7 24 i586 +=Sum: KDE Base Libraries ++Des: + +

This package contains kdelibs, one of the basic packages of the K +Desktop Environment. It contains the necessary libraries for the KDE desktop. +

+This package is absolutely necessary for using KDE. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-arts 3.5.7 24 i586 +=Sum: KDE aRts support ++Des: + +

This package contains bindings and gui elements for using aRts sound daemon. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-debuginfo 3.5.7 24 i586 +=Sum: KDE Base Libraries ++Des: + +

This package contains kdelibs, one of the basic packages of the K +Desktop Environment. It contains the necessary libraries for the KDE desktop. +

+This package is absolutely necessary for using KDE. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-devel 3.5.7 24 i586 +=Sum: KDE Base Package: Build Environment ++Des: + +

This package contains all necessary include files and libraries needed to develop applications that require these. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-doc 3.5.7 24 i586 +=Sum: Documentation for KDE Base Libraries ++Des: + +

This package contains the core environment and templates for the KDE help system. +

+-Des: +##---------------------------------------- diff --git a/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.es b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.es new file mode 100644 index 0000000..570a4df --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/packages.es @@ -0,0 +1,47 @@ +##---------------------------------------- +=Pkg: kdelibs3 3.5.7 24 i586 +=Sum: KDE Base Libraries ++Des: + +

This package contains kdelibs, one of the basic packages of the K +Desktop Environment. It contains the necessary libraries for the KDE desktop. +

+This package is absolutely necessary for using KDE. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-arts 3.5.7 24 i586 +=Sum: KDE aRts support ++Des: + +

This package contains bindings and gui elements for using aRts sound daemon. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-debuginfo 3.5.7 24 i586 +=Sum: KDE Base Libraries ++Des: + +

This package contains kdelibs, one of the basic packages of the K +Desktop Environment. It contains the necessary libraries for the KDE desktop. +

+This package is absolutely necessary for using KDE. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-devel 3.5.7 24 i586 +=Sum: Paquete básico de KDE: entorno de desarrollo ++Des: + +

Este paquete contiene todas las librerías y archivos include necesarios para desarrollar aplicaciones que los requieran. +

+-Des: +##---------------------------------------- +=Pkg: kdelibs3-doc 3.5.7 24 i586 +=Sum: Documentación para las bibliotecas básicas de KDE ++Des: + +

Este paquete contiene el entorno central y las plantillas para el sistema de ayuda de KDE. +

+-Des: +##---------------------------------------- diff --git a/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/patterns b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/patterns new file mode 100644 index 0000000..43d428b --- /dev/null +++ b/tests/repo/susetags/data/stable-x86-subset/suse/setup/descr/patterns @@ -0,0 +1,2 @@ +kde-10.3-71.noarch.pat + diff --git a/tests/repo/yum/CMakeLists.txt b/tests/repo/yum/CMakeLists.txt new file mode 100644 index 0000000..de237c0 --- /dev/null +++ b/tests/repo/yum/CMakeLists.txt @@ -0,0 +1,2 @@ + +ADD_TESTS(YUMDownloader) \ No newline at end of file diff --git a/tests/repo/yum/YUMDownloader_test.cc b/tests/repo/yum/YUMDownloader_test.cc new file mode 100644 index 0000000..b02f478 --- /dev/null +++ b/tests/repo/yum/YUMDownloader_test.cc @@ -0,0 +1,81 @@ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "tests/zypp/KeyRingTestReceiver.h" + +using std::cout; +using std::endl; +using namespace zypp; +using namespace boost::unit_test; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/repo/yum/data") + +using namespace zyppng::operators; + +BOOST_AUTO_TEST_CASE(yum_download) +{ + KeyRingTestReceiver keyring_callbacks; + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + + Pathname p = DATADIR + "/ZCHUNK"; + Url url(p.asDirUrl()); + RepoInfo repoinfo; + repoinfo.setAlias("testrepo"); + repoinfo.setPath("/"); + + filesystem::TmpDir tmp; + Pathname localdir(tmp.path()); + + auto ctx = zyppng::SyncContext::create (); + auto res = ctx->provider()->attachMedia( p.asDirUrl() , zyppng::ProvideMediaSpec() ) + | and_then( [&]( zyppng::SyncMediaHandle h ){ + auto dlctx = std::make_shared( ctx, repoinfo, localdir ); + return zyppng::RpmmdWorkflows::download(dlctx, h); + }) + | and_then( [&](zyppng::repo::SyncDownloadContextRef ctx ) { + +#if defined(LIBSOLVEXT_FEATURE_ZCHUNK_COMPRESSION) + const bool zchunk = true; +#else + const bool zchunk = false; +#endif + std::map files { + { "filelists.xml.gz", false&&!zchunk }, + { "filelists.xml.zck", false&&zchunk }, + { "other.xml.gz", false&&!zchunk }, + { "other.xml.zck", false&&zchunk }, + { "patterns.xml.gz", true }, + { "primary.xml.gz", !zchunk }, + { "primary.xml.zck", zchunk }, + { "repomd.xml", true }, + { "repomd.xml.asc", true }, + { "repomd.xml.key", true }, + }; + + for ( const auto & el : files ) + { + Pathname stem { "/repodata/"+el.first }; + bool downloaded { PathInfo(localdir/stem).isExist() }; + BOOST_CHECK_MESSAGE( downloaded == el.second, std::string(el.second?"missing ":"unexpected ")+stem ); + } + + return zyppng::expected::success(); + + }); + + BOOST_REQUIRE ( res.is_valid () ); + +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/filelists.xml.gz b/tests/repo/yum/data/10.2-updates-subset/repodata/filelists.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..dad0a0ee053949f8e465598391b21c9b7f575ae8 GIT binary patch literal 4344 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 E0YlNCw*UYD literal 0 HcmV?d00001 diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/other.xml.gz b/tests/repo/yum/data/10.2-updates-subset/repodata/other.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..5694694b27d927d3c0d2e83dc44bfb7dc6406869 GIT binary patch literal 20305 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 + + + fetchmsttfonts.sh + Download Microsoft(r) TrueType Core Fonts + Download Microsoft(r) TrueType Core Fonts + For legal reasons we can't include the Microsoft(r) +TrueType Core Fonts in our product. This patch downloads +these fonts and installs them on your system. Please note +that about 4 MByte data are downloaded therefore. License +for the fonts will be installed as +/usr/share/doc/corefonts/EULA.html. + + Aus rechtlichen Gründen können wir leider die TrueType Core +Fonts von Microsoft(r) auf unserem Produkt nicht +mitliefern. Dieser Patch lädt diese Fonts herunter und +installiert diese auf Ihrem System. Beachten Sie bitte, +dass dazu in etwa 4 MByte an Daten heruntergeladen werden. +Die Lizenz für die Fonts wird unter +/usr/share/doc/corefonts/EULA.html abgelegt. + + + + + + optional + +END-USER LICENSE AGREEMENT FOR +MICROSOFT SOFTWARE + +IMPORTANT-READ CAREFULLY: This Microsoft End-User License Agreement ("EULA") is +a legal agreement between you (either an individual or a single entity) and +Microsoft Corporation for the Microsoft software accompanying this EULA, which +includes computer software and may include associated media, printed materials, +and "on-line" or electronic documentation ("SOFTWARE PRODUCT" or "SOFTWARE"). +By exercising your rights to make and use copies of the SOFTWARE PRODUCT, you +agree to be bound by the terms of this EULA. If you do not agree to the terms +of this EULA, you may not use the SOFTWARE PRODUCT. + + +SOFTWARE PRODUCT LICENSE +The SOFTWARE PRODUCT is protected by copyright laws and international copyright +treaties, as well as other intellectual property laws and treaties. The +SOFTWARE PRODUCT is licensed, not sold. + + +1. GRANT OF LICENSE. This EULA grants you the following rights: + + * Installation and Use. You may install and use an unlimited number of copies + of the SOFTWARE PRODUCT. + * Reproduction and Distribution. You may reproduce and distribute an + unlimited number of copies of the SOFTWARE PRODUCT; provided that each copy + shall be a true and complete copy, including all copyright and trademark + notices, and shall be accompanied by a copy of this EULA. Copies of the + SOFTWARE PRODUCT may not be distributed for profit either on a standalone + basis or included as part of your own product. + + +2. DESCRIPTION OF OTHER RIGHTS AND LIMITATIONS. + + * Limitations on Reverse Engineering, Decompilation, and Disassembly. You may + not reverse engineer, decompile, or disassemble the SOFTWARE PRODUCT, + except and only to the extent that such activity is expressly permitted by + applicable law notwithstanding this limitation. + * Restrictions on Alteration. You may not rename, edit or create any + derivative works from the SOFTWARE PRODUCT, other than subsetting when + embedding them in documents. + * Software Transfer. You may permanently transfer all of your rights under + this EULA, provided the recipient agrees to the terms of this EULA. + * Termination. Without prejudice to any other rights, Microsoft may terminate + this EULA if you fail to comply with the terms and conditions of this EULA. + In such event, you must destroy all copies of the SOFTWARE PRODUCT and all + of its component parts. + + +3. COPYRIGHT. All title and copyrights in and to the SOFTWARE PRODUCT +(including but not limited to any images, text, and "applets" incorporated into +the SOFTWARE PRODUCT), the accompanying printed materials, and any copies of +the SOFTWARE PRODUCT are owned by Microsoft or its suppliers. The SOFTWARE +PRODUCT is protected by copyright laws and international treaty provisions. +Therefore, you must treat the SOFTWARE PRODUCT like any other copyrighted +material. + + +4. U.S. GOVERNMENT RESTRICTED RIGHTS. The SOFTWARE PRODUCT and documentation +are provided with RESTRICTED RIGHTS. Use, duplication, or disclosure by the +Government is subject to restrictions as set forth in subparagraph (c)(1)(ii) +of the Rights in Technical Data and Computer Software clause at DFARS +252.227-7013 or subparagraphs (c)(1) and (2) of the Commercial Computer +Software - Restricted Rights at 48 CFR 52.227-19, as applicable. Manufacturer +is Microsoft Corporation/One Microsoft Way/Redmond, WA 98052-6399. + + +LIMITED WARRANTY + +NO WARRANTIES. Microsoft expressly disclaims any warranty for the SOFTWARE +PRODUCT. The SOFTWARE PRODUCT and any related documentation is provided "as is" +without warranty of any kind, either express or implied, including, without +limitation, the implied warranties or merchantability, fitness for a particular +purpose, or noninfringement. The entire risk arising out of use or performance +of the SOFTWARE PRODUCT remains with you. + +NO LIABILITY FOR CONSEQUENTIAL DAMAGES. In no event shall Microsoft or its +suppliers be liable for any damages whatsoever (including, without limitation, +damages for loss of business profits, business interruption, loss of business +information, or any other pecuniary loss) arising out of the use of or +inability to use this Microsoft product, even if Microsoft has been advised of +the possibility of such damages. Because some states/jurisdictions do not allow +the exclusion or limitation of liability for consequential or incidental +damages, the above limitation may not apply to you. + + +MISCELLANEOUS + +If you acquired this product in the United States, this EULA is governed by the +laws of the State of Washington. + +If this product was acquired outside the United States, then local laws may +apply. + +Should you have any questions concerning this EULA, or if you desire to contact +Microsoft for any reason, please contact the Microsoft subsidiary serving your +country, or write: Microsoft Sales Information Center/One Microsoft Way/ +Redmond, WA 98052-6399. + + + + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/patch-flash-player-2359.xml b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-flash-player-2359.xml new file mode 100644 index 0000000..7330ec0 --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-flash-player-2359.xml @@ -0,0 +1,71 @@ + + + + flash-player + flash-player: Security upgrade to 7.0.69 + flash-player: Security Upgrade auf Version 7.0.69 + This security update brings the Adobe Flash Player to +version 7.0.69. It fixes the following security problem: + +CVE-2006-5330: CRLF injection vulnerability in Adobe Flash +Player allows remote attackers to modify HTTP headers of +client requests and conduct HTTP Request Splitting attacks +via CRLF sequences in arguments to the ActionScript +functions (1) XML.addRequestHeader and (2) +XML.contentType. NOTE: the flexibility of the attack varies +depending on the type of web browser being used. + + Dieses Securityupgrade bringt den Adobe Flash Player auf +Version 7.0.69. Dieses Update behebt damit folgendes +Sicherheitsproblem: + +CVE-2006-5330: Ein CRLF Injectionsangriff in Adobe Flash +Player erlaubt entfernten Angreifern die HTTP Header von +Client Anfragen zu verändern und damit HTTP Request +Splitting Angriffe auszuführen. Dies geschieht durch +Einschleusen von CRLF Sequenzen in die ActionScript +Funktionen (1) XML.addRequestHeader und (2) +XML.contentType. Note: Die Flexibilität dieses Angriffs ist +abhängig vom benutzten Webbrowser. + + + + + + security + + + flash-player + i586 + + e0add7ff093ece07c6967f658073bfd74607fb64 + + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/patch-glabels-2348.xml b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-glabels-2348.xml new file mode 100644 index 0000000..1b38be2 --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-glabels-2348.xml @@ -0,0 +1,81 @@ + + + + glabels + If you installed glabels, you should update. + If you installed glabels, you should update. + If you cannot install glabels or experienced problem with +file types (MIME) or you cannot find glabels in the menu, +you should update. + + If you cannot install glabels or experienced problem with +file types (MIME) or you cannot find glabels in the menu, +you should update. + + + + + + recommended + + + glabels + i586 + + 34adf06a0c4873b9d53b4634beb8bee458b45767 + + + glabels + x86_64 + + 40f24dc53e8f800fc1383b0ac1b357a7134f8eea + + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/patch-gv-2350.xml b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-gv-2350.xml new file mode 100644 index 0000000..d96af97 --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-gv-2350.xml @@ -0,0 +1,111 @@ + + + + gv + gv: Additional fix for previous security update + gv: Weiterer Fix für vorheriges Sicherheitsupdate + The previous "gv" update to fix a stack overflow did not +completely fix the problem spotted. An attacker could +still cause the handling to use up all system memory, or +open windows much wider than the X display and crash. Code +execution however was not possible. + + Das vorherige "gv" Update hat zwar den berichteten +Stacküberlauf behoben, es konnte aber immer noch eine +fehlerhaftes PS den Viewer zum Absturz bringen und/oder +den Systemspeicher aufbrauchen. Das Ausführen von Schadcode +war allerdings nicht mehr möglich. + + + + + + security + + + gv + i586 + + ef3e9360d99cd36ba269af1abd2e8ac963c8c838 + + + gv + ppc + + 508bdeacfb23a0a210a27e3ed164f58b5c5c4590 + + + gv + x86_64 + + d1ceecc9b2442fe298040690bf91ae224cc2bfd4 + + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/patch-openssl-2349.xml b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-openssl-2349.xml new file mode 100644 index 0000000..74c74ce --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-openssl-2349.xml @@ -0,0 +1,297 @@ + + + + openssl + Security update for OpenSSL + Sicherheitsupdate für OpenSSL + A previous openssl update (CVE-2006-2940) introduced +another bug that can lead to a crash by providing a large +prime number. An uninitialized pointer is freed during +error handling. This bug allows remote attackers to crash +services that use openssl. + + Ein vorheriges Sicherheitsupdate von OpenSSL +(CVE-2006-2940) hat einen weiteren Fehler verursacht, der +von entfernten Angreifern ausgenutzt werden kann, um +Applikationen, die OpenSSL benutzen, zum Absturz zu bringen. + + + + + + + + + + + security + + + openssl + i586 + + a923a481bc975916121811645c9957303c90172c + + + openssl + ppc + + 3751ba88267a45f6bae72285bc3295f1550ad80e + + + openssl + x86_64 + + 0a6e313ab112570584d82725dbb1fb81862bfdf0 + + + openssl-32bit + x86_64 + + 485659fe4f32303bb951e557367564f920eb1740 + + + openssl-64bit + ppc + + 96d57cc3d4539e0355374526af16c0d4a4919ea6 + + + openssl-devel + i586 + + 9f6a44015ad97680e9f93d0edefa1d533940479c + + + openssl-devel + ppc + + aefc1215e506133131739f86a77eaef17e598dd6 + + + openssl-devel + x86_64 + + 72d8cd8e5273cc13d821e3179b49c1ca1225d471 + + + openssl-devel-32bit + x86_64 + + acbbb17d623d1a509f1811ab75297a6015d4ee8e + + + openssl-devel-64bit + ppc + + e9b398feb88d4fbe24a0a52f20e9d20feb5caf49 + + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/patch-tar-2351.xml b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-tar-2351.xml new file mode 100644 index 0000000..ad3fda4 --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/patch-tar-2351.xml @@ -0,0 +1,114 @@ + + + + tar + tar: Securityupdate to fix symlink traversal + tar: Sicherheitsupdate das behebt ein Symlinkproblem behebt + This security update fixes a directory traversal in tar, +where unpacked symlinks could be followed outside of the +directory where the tar file is unpacked. (CVE-2006-6097) + +This feature was made optional and needs to be enabled with +a commandline option. + + Dieses Sicherheitsupdate behebt ein Problem, wo beim +Entpacken eines TAR Archives dieses durch Symlinks aus dem +aktuellen Verzeichnis ausbrechen konnte. (CVE-2006-6097) + +Das alte obsolete Feature in GNU Tar wurde optional gemacht +und kann für alte TAR Archive mit einer +Kommandozeilenoption angeschaltet werden. + + + + + + security + + + tar + i586 + + 7842746e863cbad136ce916a9720ff5913a5bf66 + + + tar + ppc + + def753a1b7fe65e49653e22ae6d42b329306be53 + + + tar + x86_64 + + 8fe39477a30f01b18d6c1f2b76a61b96f07a8969 + + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/patches.xml b/tests/repo/yum/data/10.2-updates-subset/repodata/patches.xml new file mode 100644 index 0000000..6d66963 --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/patches.xml @@ -0,0 +1,27 @@ + + + + 6b72b4f3617d0d51af28399c0f5e0af401440245 + + + + b02ba598d8ed5f8a31859d3b34e72e1ddecbe894 + + + + 321ee41de68be4e83dfb74559c14300a59b85ccf + + + + ec9e8a3f3ce2588cecd84ab95ec910d41db5d74b + + + + d803372cd5d844ee01ab6fb3d1b4332391fa1206 + + + + c2de5dd35ec2dcccc118d9d7f539e768dfd5ec50 + + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/primary.xml.gz b/tests/repo/yum/data/10.2-updates-subset/repodata/primary.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..d016c87af8d887bca884bfdeb45d3ca48970b81f GIT binary patch literal 11779 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 literal 0 HcmV?d00001 diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml b/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml new file mode 100644 index 0000000..2c7e82c --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml @@ -0,0 +1,27 @@ + + + + + 23ed066c97c23c557121aaf9c57e5f3f429e4a23 + 1176468240 + 23ed066c97c23c557121aaf9c57e5f3f429e4a23 + + + + 7f83e2e248d8966d119471c58ef41e7a065c9e1a + 1176468292 + b2b013f0426018c6cc9dbb30a06fa2bab0aaeea8 + + + + 73588a1c655a58b2251146675ab64cce8cb45a26 + 1176468284 + 68e66f72b932235eeee5d5638d3cba2ec674c208 + + + + 8a7622d1200067c399e483c4ca19fb382ae1f24e + 1176468286 + 0bc279d4c287dfea715805e349744122f412e3a6 + + diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.asc b/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.asc new file mode 100644 index 0000000..db30fb6 --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.9.22 (GNU/Linux) + +iD8DBQBGzqIbm+zCtd2wN1YRAslJAJ9eQ+6wpaKRVkr5nrQ4vij6ge0QpgCfRoT2 +clYiEftDMuaEpZeRaBQodyc= +=I83X +-----END PGP SIGNATURE----- diff --git a/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.key b/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.key new file mode 100644 index 0000000..8e52028 --- /dev/null +++ b/tests/repo/yum/data/10.2-updates-subset/repodata/repomd.xml.key @@ -0,0 +1,24 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.6 (GNU/Linux) + +mQGiBEYjZk4RBACjIOtNaPzvKlC32b8R5TDRB0/FQ0tsMtt5dLwuq2ZYlEbT1YLF +110vZEl5IQAq5ldvD7MdR/6fqdXTdxBeYzZjeIEYbHzg3rN/N/+MkcG4W8IK1H6e +DAbL05HlQ1ueTp0mjgoGLYKt1igQe8h5uA6gEE7dv0tG0NJx2w5Gs2GpmwCgiRiu +s2ev221Pa65IpR1gsYuXLOEEAKJ1Bvjm+BfHJirqoH7iPq5HlABwn+s9sUmf6bjC +kfar/ySAsL0VUhHNCIoHUEZd2imA2ZA0kTBxB+BIX/HMRZzxPZEwYI8Q0UYsTVb/ +gnQt+mWaZs1/2teWR0wnUp+eO5MpOAO9QjFJTdIz0GegsfSOPCo55CUtktr3tJUK +fZ3gA/9mZe+b1Evi1/Us+klnERRKR2jjWXxwuPN6UivJbfXIZjuVUNclAhEqstzp +fnWJ3LhPxj0zJvhp/MnqSTaI6DQbr0f+JvwP+5k/4gbnqm+xxOocyhiVT45zOPAy +UYuG4t0m+9G7Vx6LC9tMukbdfHaRym42yC2s04GW2isKfta1ZbQsWllwcCBUZXN0 +IEtleSBQYWlyIDx6eXBwLWRldmVsQG9wZW5zdXNlLm9yZz6IYAQTEQIAIAUCRiNm +TgIbIwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEJvswrXdsDdWSVAAnjkR2lao +hb2Q4WnxamdHYWSf8ULKAJ4jjfZsFq0vmgPsO/YHaKTJN5sAL7kBDQRGI2ZREAQA +toB5TGT9K7NCv5D5dQw7jVHngnxp3NGTtAhwirYphBWaF2be3UJVTLbUFW14eMnr +VW9PKj/HNVLhQu0C6CaXtXy5LahIls+mFlSKwbiP74cFlNYcj69tzCnaFKgElQPH +cMOc31EgjySYcUIys421MxI++sugW+yHr5ByIsL6vfcAAwUEAILSwmLtD+Pwkues +73DPPyWIM3MA0exO7QmZeFwnbpiZYuZQ3GiPGrbeZVqHWB72dhW8+5ugR9CVQSsL +HC5wHMIQFU8RsiL06gZdIaJNgAr7ajhtUybP0WPVpXkzm5+VB8Che9m0Z0t2tK8Y +0KVapBcr3YDgx89F9VA0yny6q3WiiEkEGBECAAkFAkYjZlECGwwACgkQm+zCtd2w +N1apuACfUR+Daoo3N1fxxDa3A3t4OkAfpQgAn1UEvpQp+/4DnzSbEvwzLeoek3dz +=5nY9 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/repo/yum/data/ZCHUNK/repodata/filelists.xml.gz b/tests/repo/yum/data/ZCHUNK/repodata/filelists.xml.gz new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/yum/data/ZCHUNK/repodata/filelists.xml.zck b/tests/repo/yum/data/ZCHUNK/repodata/filelists.xml.zck new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/yum/data/ZCHUNK/repodata/other.xml.gz b/tests/repo/yum/data/ZCHUNK/repodata/other.xml.gz new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/yum/data/ZCHUNK/repodata/other.xml.zck b/tests/repo/yum/data/ZCHUNK/repodata/other.xml.zck new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/yum/data/ZCHUNK/repodata/patterns.xml.gz b/tests/repo/yum/data/ZCHUNK/repodata/patterns.xml.gz new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/yum/data/ZCHUNK/repodata/primary.xml.gz b/tests/repo/yum/data/ZCHUNK/repodata/primary.xml.gz new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/yum/data/ZCHUNK/repodata/primary.xml.zck b/tests/repo/yum/data/ZCHUNK/repodata/primary.xml.zck new file mode 100644 index 0000000..e69de29 diff --git a/tests/repo/yum/data/ZCHUNK/repodata/repomd.xml b/tests/repo/yum/data/ZCHUNK/repodata/repomd.xml new file mode 100644 index 0000000..deeabc4 --- /dev/null +++ b/tests/repo/yum/data/ZCHUNK/repodata/repomd.xml @@ -0,0 +1,70 @@ + + + 1579611877 + + obsrepository://build.opensuse.org/OBS:Server:Unstable/openSUSE_15.1 + obsbuildid:1547846024 + + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + 0e6e755baf18198ef58bb2f4630911b0628f1439ddbc14f486842a3238dbb99b + + 1579611877 + 1 + 599948 + + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + 35ebf812be754b3b5380fd662ec35d3b00302e2f112d0a339710547c19794505 + + 1579611877 + 1 + 5344403 + + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + 914babd921de65377d9a746df744865dbe6b45e185db011644b955b6e24b5aeb + + 1579611877 + 1 + 1772089 + + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + 0e6e755baf18198ef58bb2f4630911b0628f1439ddbc14f486842a3238dbb99b + dc6c50934d7847077e559d740d5363d2d5885e40a811bfb1c6ec71007a7dc73f + + 1579611877 + 1 + 599948 + 3265 + + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + 35ebf812be754b3b5380fd662ec35d3b00302e2f112d0a339710547c19794505 + 9d33f302afe9a38630b1c6519a8e0c820902c2247447636d89c50f98a6344e38 + + 1579611877 + 1 + 5344403 + 3260 + + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + 914babd921de65377d9a746df744865dbe6b45e185db011644b955b6e24b5aeb + 7ca38348f174e5b9cba5df862b48da22029d10c7288125b59871590706aca580 + + 1579611877 + 1 + 1772089 + 3262 + + + e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + cc15cbebe9bd8360d90384cb4ce2aefd9fdf69940090dd719b2d3908dba79d53 + + 1579611877 + 1 + 1014 + + diff --git a/tests/repo/yum/data/ZCHUNK/repodata/repomd.xml.asc b/tests/repo/yum/data/ZCHUNK/repodata/repomd.xml.asc new file mode 100644 index 0000000000000000000000000000000000000000..d4560ebadaad661ade1834cf3b44095c74a01115 GIT binary patch literal 326 zcmV-M0lEH(0Yd};0SEvs79j-Me@0<8>V^}f)y7$dqcpY;4w~f!0$wSFFb^Dhd2nz* zbY*jNb9HHSWdI5Z5Qd{Pwhs=P<#W#m{0wEanFR6YAnU|XHGC(ni&VB8UF6gq=v;Pq zgw=ISWL7e#+em`Q;`g0@lUEj!ItAKP>o!4+IfR-r%~qMz_6U(#6HLb(n^C3jZ^K~< zP`Gl|U%v_zWVNhj_o<(VgC^Y`Z0v?r-JDQl$2*EA)x)m;eH-IlTYiPuc6Ud%u2Ne$ zd5Etpm!iw;b~Lc&FY>B}(^+z7paf)~gOj+Z+&&5pL*SNVW^Sb;G@8G=Tb+2sVu0UEmji?6_BMmc>9 znIy_*W69Oe)#WNKx1ndRw5)C#H6%g;qtQ&(jg5wv=O>=SrHqQ&_0+r7uPpH6s-g9M zKF4wI#_cBT){!8)#RGY?=rR7{fz4<-Y$&`*AUNHxZ0;IoH7J{4TAwnTX7aI?Sec4W zN~KAjT1Av&o}kihN}mLi)l4Dm1n__vEm+|(LC*g@P(jgNQD#`u!Z`4b$pw^6Y_E&hr_4E5c#g;t2hNQhZy9V=(8wT?p;}%IHHLV3cvy8aDbJwHMT ikBeyD{*J{ullhd3_}*0+Ma6fcW%LgGtqVT20RRB#i;}_s literal 0 HcmV?d00001 diff --git a/tests/repo/yum/data/extensions/repodata/other.xml.gz b/tests/repo/yum/data/extensions/repodata/other.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..0ceffeeb4a6f388fe4668e9699966c4ef52fe4ad GIT binary patch literal 211 zcmV;^04)C>iwFR2dM-%-13iyHZiFxlMfaS-@_v$#Xws-6%&sSB58xplh=72Y(9ZE2 zD%73r|MdTNb9>DbeDn5LQK8Kug{N*!&_T5OCER&lnDx-o*svs*LNwW znD&;W_kbs literal 0 HcmV?d00001 diff --git a/tests/repo/yum/data/extensions/repodata/primary.xml.gz b/tests/repo/yum/data/extensions/repodata/primary.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..7def063329d27d08ba16f533f18d83682be7fb2a GIT binary patch literal 901 zcmV;01A6=)iwFq71o&kD0|4z=U2oeq6n)RH5cssAu)ZbBfuv&Cn!N86eJJ3d|IwPL#5({dkxU9Ds z`TPCNDj{$4tF(faa@tZ0;kC)gu5FuZ$0=pqeX@DC2OD_j%qWMcs!}x>(bu}Eo}7W0 z8E!fQ2YjvWpe$`n=rok==@yQ2df;KHX%uVo2o^lOTJ1xF$@=X1m1U(htsuW|Q)lS( z5vtiPmq8Mz&d}{+6CV~ditRFjoM0p)zU|sEu{4zZBF+G1J79a$RntOdN3oRsR`QH| zeD@d01MX2@L^1bccP(66umYkW@V&(60YE~Ngt{?>)R{94Y4NwB`XT@D-nx~A#%}7& zv3{I`VOlmVR{0;y<9LsoXwYM^oi6i<*L&Hv54KUAW+0T_f?WgB(j$6gD=V;sEOASo z??s6p1nY=cMJG$#ndfcRNq}F$#DbBZVLpM3gh3eiAu=Uv)6%j8KE(WuhfMY)%ex7+ zcEc${sTl36wssmsM(*3y!1l_s`?In80~~=^Y(?9?i!T_yE+vE7K>qumx2f|uaD?1J z&DF@k6xnLkHTiFV;!;fob?b~2N-$%R5pbL^?0lz8n>W%hRmzsyMz%1bkE6#KBe&Rl zyzUMt2ffm?Mr|TFxwa-FOqD6I{bToz!5)&=kaK^@G(5I3rueR_x82dD2%9 zszEYLx#Im^Pv8oL9`3n?a}W3Z6vc;=bG|&f)R|SA&MuZ;o%Sf9R6+I2 zd + + + obsrepository://build.suse.de/SUSE:openSUSE:11:standard + opensuse + i386 + other string + openSUSE 11.0 + SLE 11.0 + SLE 11.0 + + + + 603807e12e7418911fa9f158ef66b9c20f1df567 + 1215823452 + 34cde52910a161664291bd93e8a9cd24f751af6b + + + + 06660c856facf17822102d09d849d42fad79d28e + 1215823453 + fdabcfd9c056109ab25acf0644823bdec94b6cfd + + + + dff5db9c510c177b5ae01ec79f10ac47844e6494 + 1215823454 + c6bd3c6099de74d97ed045163235be10ffa8a85f + + + + + 2950f8a880455d7b7e96d3bddd5859bd4db38524 + 1227279057.0 + b17c055bef95bca397faffdf028cfa91dd1b24bc + + + + + 34599f8eed67ec256299d295617ceaf05ae7ebdd + 1227279057.0 + a3011438085ac55f06c68053201ea3ded17ee85c + + diff --git a/tests/repo/yum/data/extensions/repodata/susedata.xml.gz b/tests/repo/yum/data/extensions/repodata/susedata.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..fea117dcb8e1c968c2e879681e8b30f8d422fbc2 GIT binary patch literal 481 zcmV<70UrJziwFqk3k+re0|331OK+So5XbNPDO{i00}q?!Rl(*~srU9=`7z!_ur|V` zY`%THDYPg_6QU*=f$(Ey{QHkBQ{7z79r_7_ZH%rl31f^v3nLqStnv46UxEVP9Co|P zjus?y40(TTYkYF9{~SeKqsL1q#}-16V{`_`u3nLGCm1m5nP}M&ynliZyK3&DzCAY5 zk4eI)N;65bI9D;_fIbArE zF`NyXS$t8$WXOko!&hV`jc(02AZwJH*Z@^@ zH}j;flJBLUgmRT+g($dSEG{#tpp-z1eV)fM1)}&$mw#TQD}6>+m#pNhSs%d08*PC# zoqTOr|MkHjL4MRQ`Rtz_hrf?bHrj&zJNa9o-!-?x(~Y*kFX`Xqm^`>KHrnb$pTXMq zEcMe7d@wEO?YpzzXp7)K`TtAuhaf +using boost::unit_test::test_case; + +#include +#include +#include +#include "TestSetup.h" +#include +using std::cin; +using std::cout; +using std::cerr; +using std::endl; +using namespace zypp; + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +void testcase_init() +{ + test.loadTestcaseRepos( TESTS_SRC_DIR"/sat/BlacklistedPool" ); +} + +std::string blacktag( const PoolItem & pi_r ) +{ + char buf[6]; + buf[0] = pi_r.isBlacklisted() ? 'B' : ' '; + buf[1] = pi_r.isRetracted() ? 'R' : ' '; + buf[2] = pi_r.isPtf() ? 'P' : ' '; + buf[3] = pi_r.isPtfMaster() ? 'm' : ' '; + buf[4] = pi_r.isPtfPackage() ? 'p' : ' '; + buf[5] = '\0'; + return buf; +} + +std::string blacktag( ui::Selectable::Ptr sel_r ) +{ + char buf[7]; + buf[0] = sel_r->hasBlacklisted() ? 'B' : ' '; + buf[1] = sel_r->hasBlacklistedInstalled() ? 'b' : ' '; + buf[2] = sel_r->hasRetracted() ? 'R' : ' '; + buf[3] = sel_r->hasRetractedInstalled() ? 'r' : ' '; + buf[4] = sel_r->hasPtf() ? 'P' : ' '; + buf[5] = sel_r->hasPtfInstalled() ? 'p' : ' '; + buf[6] = '\0'; + return buf; +} + +BOOST_AUTO_TEST_CASE(BlacklistedPool) +{ + testcase_init(); + ResPoolProxy poolProxy( test.poolProxy() ); + ui::Selectable::Ptr s( poolProxy.lookup( ResKind::package, "package" ) ); + BOOST_REQUIRE( s ); + + //cout << blacktag(s) << endl; + BOOST_CHECK_EQUAL( blacktag(s), "BbRrPp" ); + + std::vector expect = { + "BRPmp" // I__s_(7)package-5-1.x86_64(@System) + ," " // U__s_(2)package-1-1.x86_64(Repo) + ,"BRPmp" // U__s_(6)package-5-1.x86_64(Repo) + ,"B P p" // U__s_(5)package-4-1.x86_64(Repo) + ,"B Pm " // U__s_(4)package-3-1.x86_64(Repo) + ,"BR " // U__s_(3)package-2-1.x86_64(Repo) + }; + unsigned idx = unsigned(-1); + for ( const auto & pi : s->installed() ) { + //cout << blacktag(pi) << " " << pi << endl; + BOOST_CHECK_EQUAL( blacktag(pi), expect[++idx] ); + } + for ( const auto & pi : s->available() ) { + //cout << blacktag(pi) << " " << pi << endl; + BOOST_CHECK_EQUAL( blacktag(pi), expect[++idx] ); + } +} + diff --git a/tests/sat/CMakeLists.txt b/tests/sat/CMakeLists.txt new file mode 100644 index 0000000..0d747c6 --- /dev/null +++ b/tests/sat/CMakeLists.txt @@ -0,0 +1,17 @@ + +# to find the KeyRingTest receiver +INCLUDE_DIRECTORIES( ${LIBZYPP_SOURCE_DIR}/tests/zypp ) + +ADD_TESTS( + Blacklisted + IdString + LookupAttr + Pool + Queue + Map + Solvable + SolvableSpec + SolvParsing + WhatObsoletes + WhatProvides +) diff --git a/tests/sat/IdString_test.cc b/tests/sat/IdString_test.cc new file mode 100644 index 0000000..900ff91 --- /dev/null +++ b/tests/sat/IdString_test.cc @@ -0,0 +1,59 @@ +#include "TestSetup.h" +#include + +BOOST_AUTO_TEST_CASE(idstring) +{ + // id 0 ==> NULL + // id 1 ==> "" + // evaluates id in a boolean context + IdString a0( 0 ); + IdString a1( 1 ); + + BOOST_CHECK_EQUAL( a0.id(), 0 ); + BOOST_CHECK_EQUAL( a1.id(), 1 ); + + BOOST_CHECK( !a0 ); + BOOST_CHECK( a1 ); + + BOOST_CHECK( !(a0 == a1) ); + BOOST_CHECK( (a0 != a1) ); + BOOST_CHECK( (a0 < a1) ); + BOOST_CHECK( (a1 > a0) ); + BOOST_CHECK( !(a0 >= a1) ); + BOOST_CHECK( !(a1 <= a0) ); + + BOOST_CHECK_EQUAL( a0.compare( (const char *)0 ), 0 ); + BOOST_CHECK_EQUAL( a0.compare( "" ), -1 ); + BOOST_CHECK_EQUAL( a0.compare( a1 ), -1 ); + + BOOST_CHECK_EQUAL( a1.compare( (const char *)0 ), 1 ); + BOOST_CHECK_EQUAL( a1.compare( "" ), 0 ); + BOOST_CHECK_EQUAL( a1.compare( a0 ), 1 ); +} + +BOOST_AUTO_TEST_CASE(idstringtype) +{ + sat::SolvAttr a0( sat::SolvAttr::allAttr ); + sat::SolvAttr a1( sat::SolvAttr::noAttr ); + + BOOST_CHECK_EQUAL( a0.id(), 0 ); + BOOST_CHECK_EQUAL( a1.id(), 1 ); + + BOOST_CHECK( !a0 ); + BOOST_CHECK( !a1 ); // evaluates empty string (id 0/1) in a boolean context + + BOOST_CHECK( !(a0 == a1) ); + BOOST_CHECK( (a0 != a1) ); + BOOST_CHECK( (a0 < a1) ); + BOOST_CHECK( (a1 > a0) ); + BOOST_CHECK( !(a0 >= a1) ); + BOOST_CHECK( !(a1 <= a0) ); + + BOOST_CHECK_EQUAL( a0.compare( (const char *)0 ), 0 ); + BOOST_CHECK_EQUAL( a0.compare( "" ), -1 ); + BOOST_CHECK_EQUAL( a0.compare( a1 ), -1 ); + + BOOST_CHECK_EQUAL( a1.compare( (const char *)0 ), 1 ); + BOOST_CHECK_EQUAL( a1.compare( "" ), 0 ); + BOOST_CHECK_EQUAL( a1.compare( a0 ), 1 ); +} diff --git a/tests/sat/LookupAttr_test.cc b/tests/sat/LookupAttr_test.cc new file mode 100644 index 0000000..e534946 --- /dev/null +++ b/tests/sat/LookupAttr_test.cc @@ -0,0 +1,240 @@ +#include "TestSetup.h" +#include +#include +#include + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +// Must be the first test! +BOOST_AUTO_TEST_CASE(bnc_435838) +{ + // empty @system to pool + test.satpool().systemRepo(); + BOOST_REQUIRE( test.satpool().findSystemRepo() ); + + // bnc_435838 crashes if iterating a just created repo. + sat::LookupAttr q( sat::SolvAttr::name ); + for_( it, q.begin(),q.end() ) + ; +} + +BOOST_AUTO_TEST_CASE(LookupAttr_init) +{ + //test.loadTarget(); // initialize and load target + test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1" ); + test.loadRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" ); + test.loadRepo( TESTS_SRC_DIR "/data/11.0-update" ); +} + +BOOST_AUTO_TEST_CASE(LookupAttr_defaultconstructed) +{ + sat::LookupAttr q; + BOOST_CHECK( q.empty() ); + BOOST_CHECK( q.size() == 0 ); + BOOST_CHECK_EQUAL( q.begin(), q.end() ); +} + +BOOST_AUTO_TEST_CASE(LookupAttr_nonexistingattr) +{ + sat::LookupAttr q( sat::SolvAttr("nonexistingattr") ); + BOOST_CHECK( q.empty() ); + BOOST_CHECK( q.size() == 0 ); + BOOST_CHECK_EQUAL( q.begin(), q.end() ); +} + +BOOST_AUTO_TEST_CASE(LookupAttr_existingattr) +{ + sat::LookupAttr q( sat::SolvAttr::name ); + BOOST_CHECK( ! q.empty() ); + BOOST_CHECK( q.size() != 0 ); + BOOST_CHECK_NE( q.begin(), q.end() ); +} + +BOOST_AUTO_TEST_CASE(LookupAttr_existingattr_matcher) +{ + sat::LookupAttr q( sat::SolvAttr::name ); + + BOOST_CHECK_THROW( q.setStrMatcher( StrMatcher("[]ypper",Match::REGEX) ), MatchInvalidRegexException ); + BOOST_CHECK( ! q.strMatcher() ); + BOOST_CHECK_NO_THROW( q.setStrMatcher( StrMatcher("[zZ]ypper",Match::REGEX) ) ); + BOOST_CHECK( q.strMatcher() ); + + BOOST_CHECK_EQUAL( q.size(), 9 ); +} + +BOOST_AUTO_TEST_CASE(LookupAttr_iterate_solvables) +{ + // sat::SolvAttr::name query should visit each solvable once. + // So query size and containersize are to be equal if we query + // pool/repo/solvable. Quick check whether the iterators + // position info matches the result. + + sat::Pool satpool( test.satpool() ); + + { + // iterate all: + sat::LookupAttr q( sat::SolvAttr::name ); + BOOST_CHECK_EQUAL( q.size(), satpool.solvablesSize() ); + // quick test whether iterator positions actually matches the result: + for_( res, q.begin(), q.end() ) + { + BOOST_CHECK_EQUAL( res.inRepo(), res.inSolvable().repository() ); + BOOST_CHECK_EQUAL( res.inSolvAttr(), sat::SolvAttr::name ); + } + } + { + unsigned total = 0; + for_( it, satpool.reposBegin(), satpool.reposEnd() ) + { + // iterate one repo: + sat::LookupAttr q( sat::SolvAttr::name, *it ); + BOOST_CHECK_EQUAL( q.size(), it->solvablesSize() ); + total += q.size(); + // test result actually matches the repo: + for_( res, q.begin(), q.end() ) + { + BOOST_CHECK_EQUAL( res.inRepo(), *it ); + BOOST_CHECK_EQUAL( res.inRepo(), res.inSolvable().repository() ); + BOOST_CHECK_EQUAL( res.inSolvAttr(), sat::SolvAttr::name ); + } + } + BOOST_CHECK_EQUAL( total, satpool.solvablesSize() ); + } + { + unsigned total = 0; + for_( it, satpool.solvablesBegin(), satpool.solvablesEnd() ) + { + // iterate one solvable: + sat::LookupAttr q( sat::SolvAttr::name, *it ); + BOOST_CHECK_EQUAL( q.size(), 1 ); + total += q.size(); + // test result actually matches the solvable: + for_( res, q.begin(), q.end() ) + { + BOOST_CHECK_EQUAL( res.inSolvable(), *it ); + BOOST_CHECK_EQUAL( res.inRepo(), res.inSolvable().repository() ); + BOOST_CHECK_EQUAL( res.inSolvAttr(), sat::SolvAttr::name ); + } + } + BOOST_CHECK_EQUAL( total, satpool.solvablesSize() ); + } +} + +BOOST_AUTO_TEST_CASE(LookupAttr_itetate_all_attributes) +{ + sat::Pool satpool( test.satpool() ); + + // iterate all: + sat::LookupAttr all( sat::SolvAttr::allAttr ); + + { + unsigned total = 0; + for_( it, satpool.reposBegin(), satpool.reposEnd() ) + { + // iterate one repo: + sat::LookupAttr q( sat::SolvAttr::allAttr, *it ); + total += q.size(); + } + BOOST_CHECK_EQUAL( total, all.size() ); + } + { + unsigned total = 0; + for_( it, satpool.solvablesBegin(), satpool.solvablesEnd() ) + { + // iterate one solvable: + sat::LookupAttr q( sat::SolvAttr::allAttr, *it ); + total += q.size(); + } + BOOST_CHECK_EQUAL( total, all.size() ); + } +} + +BOOST_AUTO_TEST_CASE(LookupAttr_solvable_attribute_substructure) +{ + sat::LookupAttr q( sat::SolvAttr::updateReference ); + BOOST_CHECK_EQUAL( q.size(), 303 ); + + for_( res, q.begin(), q.end() ) + { + BOOST_CHECK( ! res.subEmpty() ); + BOOST_CHECK_EQUAL( res.subSize(), 4 ); + + BOOST_CHECK_EQUAL( res.subFind( sat::SolvAttr::allAttr ), res.subBegin() ); + BOOST_CHECK_EQUAL( res.subFind( "" ), res.subBegin() ); + + BOOST_CHECK_EQUAL( res.subFind( sat::SolvAttr::updateReference ), res.subEnd() ); + BOOST_CHECK_EQUAL( res.subFind( "noval" ), res.subEnd() ); + + BOOST_CHECK_NE( res.subFind( sat::SolvAttr::updateReferenceType ), res.subEnd() ); + BOOST_CHECK_NE( res.subFind( sat::SolvAttr::updateReferenceHref ), res.subEnd() ); + BOOST_CHECK_NE( res.subFind( sat::SolvAttr::updateReferenceId ), res.subEnd() ); + BOOST_CHECK_NE( res.subFind( sat::SolvAttr::updateReferenceTitle ), res.subEnd() ); + + BOOST_CHECK_EQUAL( res.subFind( sat::SolvAttr::updateReferenceType ), res.subFind( "type" ) ); + BOOST_CHECK_EQUAL( res.subFind( sat::SolvAttr::updateReferenceHref ), res.subFind( "href" ) ); + BOOST_CHECK_EQUAL( res.subFind( sat::SolvAttr::updateReferenceId ), res.subFind( "id" ) ); + BOOST_CHECK_EQUAL( res.subFind( sat::SolvAttr::updateReferenceTitle ), res.subFind( "title" ) ); + + // repeatedly calling subBegin() is ok: + BOOST_CHECK_EQUAL( res.subFind( sat::SolvAttr::updateReferenceType ).subBegin(), res.subBegin() ); + } + + // search substructure id without parent-structure works for wellknown structures: + q = sat::LookupAttr( sat::SolvAttr::updateReferenceId ); + BOOST_CHECK_EQUAL( q.size(), 303 ); + + // search id in parent-structure: + q = sat::LookupAttr( sat::SolvAttr::updateReferenceId, sat::SolvAttr::updateReference ); + BOOST_CHECK_EQUAL( q.size(), 303 ); + + // search id in any parent-structure: + q = sat::LookupAttr( sat::SolvAttr::updateReferenceId, sat::SolvAttr::allAttr ); + BOOST_CHECK_EQUAL( q.size(), 303 ); + + // search any id in parent-structure: (4 ids per updateReference) + q = sat::LookupAttr( sat::SolvAttr::allAttr, sat::SolvAttr::updateReference ); + BOOST_CHECK_EQUAL( q.size(), 1212 ); + + // search any id in any parent-structure: + // - https://github.com/openSUSE/libsolv/pull/402 added an additional + // flexarray to each of the 2287 entries. This is + // why the total size varies depending on the libsolv version used. + q = sat::LookupAttr( sat::SolvAttr::allAttr, sat::SolvAttr::allAttr ); + auto qs = q.size(); + BOOST_CHECK( qs == 10473 || qs == 12760 ); + // for_(it,q.begin(),q.end()) + // { cout << it << endl;} +} + +BOOST_AUTO_TEST_CASE(LookupAttr_repoattr) +{ + sat::LookupAttr q( sat::SolvAttr::repositoryAddedFileProvides, sat::LookupAttr::REPO_ATTR ); + BOOST_CHECK( ! q.empty() ); + BOOST_CHECK_EQUAL( q.size(), 264 ); + + sat::LookupRepoAttr p( sat::SolvAttr::repositoryAddedFileProvides ); + BOOST_CHECK( ! p.empty() ); + BOOST_REQUIRE_EQUAL( p.size(), q.size() ); + + sat::LookupRepoAttr::iterator pit( p.begin() ); + for_( qit, q.begin(), q.end() ) + { + BOOST_CHECK_EQUAL( qit, pit ); + ++pit; + } +} + +#if 0 +BOOST_AUTO_TEST_CASE(LookupAttr_) +{ + base::LogControl::TmpLineWriter shutUp( new log::FileLineWriter( "/tmp/YLOG" ) ); + MIL << "GO" << endl; +} +#endif diff --git a/tests/sat/Map_test.cc b/tests/sat/Map_test.cc new file mode 100644 index 0000000..35a9272 --- /dev/null +++ b/tests/sat/Map_test.cc @@ -0,0 +1,68 @@ +#include +#include +#include + +#include +#include +#include + + +#define BOOST_TEST_MODULE Map + +using std::endl; +using std::cout; +using namespace zypp; +using namespace boost::unit_test; + + +BOOST_AUTO_TEST_CASE(basic) +{ + sat::Map m; + BOOST_CHECK_EQUAL( m.empty(), true ); + BOOST_CHECK_EQUAL( m.size(), 0 ); + BOOST_CHECK_EQUAL( m.asString(), "" ); + BOOST_CHECK( m == sat::Map() ); + + m.grow( 8 ); + BOOST_CHECK_EQUAL( m.empty(), false ); + BOOST_CHECK_EQUAL( m.size(), 8 ); + BOOST_CHECK_EQUAL( m.asString(), "00000000" ); + BOOST_CHECK( m != sat::Map() ); + + m.grow( 9 ); + BOOST_CHECK_EQUAL( m.empty(), false ); + BOOST_CHECK_EQUAL( m.size(), 16 ); + BOOST_CHECK_EQUAL( m.asString(), "0000000000000000" ); + + m.grow( 0 ); // no shrink! + BOOST_CHECK_EQUAL( m.size(), 16 ); + + m.setAll(); + BOOST_CHECK_EQUAL( m.asString(), "1111111111111111" ); + + m.clear( 0 ); + m.assign( 3, false ); + BOOST_CHECK_EQUAL( m.asString(), "0110111111111111" ); + BOOST_CHECK_EQUAL( m.test( 0 ), false ); + BOOST_CHECK_EQUAL( m.test( 1 ), true ); + + // COW + m.clearAll(); + sat::Map n(m); + BOOST_CHECK_EQUAL( m.asString(), "0000000000000000" ); + BOOST_CHECK_EQUAL( n.asString(), "0000000000000000" ); + BOOST_CHECK_EQUAL( m, n ); + + m.set( 1 ); + BOOST_CHECK_EQUAL( m.asString(), "0100000000000000" ); + BOOST_CHECK_EQUAL( n.asString(), "0000000000000000" ); + BOOST_CHECK( m != n ); + + n.set( 1 ); + BOOST_CHECK_EQUAL( m.asString(), "0100000000000000" ); + BOOST_CHECK_EQUAL( n.asString(), "0100000000000000" ); + BOOST_CHECK( m == n ); + + + BOOST_CHECK_THROW( m.set( 99 ), std::out_of_range ); +} diff --git a/tests/sat/Pool_test.cc b/tests/sat/Pool_test.cc new file mode 100644 index 0000000..018a236 --- /dev/null +++ b/tests/sat/Pool_test.cc @@ -0,0 +1,100 @@ +#include "TestSetup.h" +#include +#include + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +namespace zypp { namespace detail { + /** \relates RepositoryIterator Stream output */ + inline std::ostream & operator<<( std::ostream & str, const RepositoryIterator & obj ) + { + str << "RI["<< *obj <<"]"; + return str; + } +}} + +// Must be the first test! +BOOST_AUTO_TEST_CASE(findSystemRepo) +{ + // On the fly check that findSystemRepo does not + // cause loading the SystemRepo. check 2 times. + BOOST_REQUIRE( ! test.satpool().findSystemRepo() ); + BOOST_REQUIRE( ! test.satpool().findSystemRepo() ); +} + +void checkRepoIter() +{ + sat::Pool satpool( test.satpool() ); + sat::Pool::size_type count = satpool.reposSize(); + for_( it, satpool.reposBegin(), satpool.reposEnd() ) + { + cout << "- " << count << " " << *it << endl; + BOOST_CHECK( *it ); + --count; + } + BOOST_CHECK_EQUAL( count, 0 ); +} + + +BOOST_AUTO_TEST_CASE(repolist) +{ + // libzypp-11: underlying libsolv changed the pools repository + // pointer list. It may now contain emebeded NULLs which have + // to be skipped when iterating the repos. + // + sat::Pool satpool( test.satpool() ); + BOOST_CHECK( satpool.reposEmpty() ); + BOOST_CHECK_EQUAL( satpool.reposSize(), 0 ); + checkRepoIter(); + + // empty @system to pool + test.satpool().systemRepo(); + BOOST_REQUIRE( satpool.findSystemRepo() ); + BOOST_CHECK( !satpool.reposEmpty() ); + BOOST_CHECK_EQUAL( satpool.reposSize(), 1 ); + checkRepoIter(); + + test.loadRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" ); + BOOST_CHECK( !satpool.reposEmpty() ); + BOOST_CHECK_EQUAL( satpool.reposSize(), 2 ); + checkRepoIter(); + + test.loadRepo( TESTS_SRC_DIR "/data/11.0-update" ); + BOOST_CHECK( !satpool.reposEmpty() ); + BOOST_CHECK_EQUAL( satpool.reposSize(), 3 ); + checkRepoIter(); + + satpool.reposErase( ":obs_virtualbox_11_1" ); + BOOST_CHECK( !satpool.reposEmpty() ); + BOOST_CHECK_EQUAL( satpool.reposSize(), 2 ); + checkRepoIter(); + + satpool.reposErase( ":11.0-update" ); + test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1" ); + BOOST_CHECK( !satpool.reposEmpty() ); + BOOST_CHECK_EQUAL( satpool.reposSize(), 2 ); + checkRepoIter(); + + + +/* for_( it, satpool.reposBegin(), satpool.reposEnd() ) + { + cout << "- " << *it << endl; + }*/ + //test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1" ); +} + +#if 0 +BOOST_AUTO_TEST_CASE(LookupAttr_) +{ + base::LogControl::TmpLineWriter shutUp( new log::FileLineWriter( "/tmp/YLOG" ) ); + MIL << "GO" << endl; +} +#endif diff --git a/tests/sat/Queue_test.cc b/tests/sat/Queue_test.cc new file mode 100644 index 0000000..66f5579 --- /dev/null +++ b/tests/sat/Queue_test.cc @@ -0,0 +1,51 @@ +#include +#include +#include + +#include +#include +#include + + +#define BOOST_TEST_MODULE Queue + +using std::endl; +using std::cout; +using namespace zypp; +using namespace boost::unit_test; + + +BOOST_AUTO_TEST_CASE(basic) +{ + sat::Queue m; + BOOST_CHECK_EQUAL( m.empty(), true ); + BOOST_CHECK_EQUAL( m.size(), 0 ); + BOOST_CHECK_EQUAL( m.begin(), m.end() ); + BOOST_CHECK( m == sat::Queue() ); + BOOST_CHECK_EQUAL( m.first(), 0 ); + BOOST_CHECK_EQUAL( m.last(), 0 ); + + m.push( 13 ); + BOOST_CHECK_EQUAL( m.empty(), false ); + BOOST_CHECK_EQUAL( m.size(), 1 ); + BOOST_CHECK( m.begin() != m.end() ); + BOOST_CHECK_EQUAL( m.begin()+1, m.end() ); + + BOOST_CHECK_EQUAL( m.first(), 13 ); + BOOST_CHECK_EQUAL( m.last(), 13 ); + BOOST_CHECK_EQUAL( m.at(0), 13 ); + BOOST_CHECK_THROW( m.at(1), std::out_of_range ); + + BOOST_CHECK( m.contains(13) ); + BOOST_CHECK( !m.contains(14) ); + + BOOST_CHECK_EQUAL( m.find(13), m.begin() ); + BOOST_CHECK_EQUAL( m.find(14), m.end() ); + + m.pushUnique( 13 ); + BOOST_CHECK_EQUAL( m.size(), 1 ); + m.push( 13 ); + BOOST_CHECK_EQUAL( m.size(), 2 ); + m.remove( 13 ); + BOOST_CHECK_EQUAL( m.size(), 0 ); +} diff --git a/tests/sat/SolvParsing_test.cc b/tests/sat/SolvParsing_test.cc new file mode 100644 index 0000000..05e3483 --- /dev/null +++ b/tests/sat/SolvParsing_test.cc @@ -0,0 +1,131 @@ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// allows us to control signature +// callbacks +#include "KeyRingTestReceiver.h" + +#define BOOST_TEST_MODULE ResObject + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace boost::unit_test; + + +/* + * this test test that the attributes + * from the metadata are preserved into + * the final object + * + * so the test covers both libsolv-tools + * right insertion and parsing + * and libzypp ResObject and friends data + * extraction from solv files + */ + + +// init the solv +static void init_pool_yum() +{ + Pathname dir(TESTS_SRC_DIR); + dir += "/repo/yum/data/10.2-updates-subset"; + + ZYpp::Ptr z = getZYpp(); + ZConfig::instance().setSystemArchitecture(Arch("i586")); + + filesystem::TmpDir tmp; + RepoManagerOptions opts = RepoManagerOptions::makeTestSetup(tmp.path()); + RepoManager mgr(opts); + + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + + // disable sgnature checking + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + keyring_callbacks.answerAcceptVerFailed(true); + keyring_callbacks.answerAcceptUnknownKey(true); + + RepoInfo info; + info.setAlias("updates"); + info.addBaseUrl(dir.asUrl()); + mgr.buildCache(info); + mgr.loadFromCache(info); +} + +BOOST_AUTO_TEST_CASE(attributes) +{ + init_pool_yum(); + MIL << sat::Pool::instance(); + Repository r = sat::Pool::instance().reposFind("updates"); + + int c = 0; + + for ( Repository::SolvableIterator it = r.solvablesBegin(); + it != r.solvablesEnd(); + ++it ) + { + sat::Solvable s = *it; + //MIL << s.ident() << endl; + if ( s.ident() == "openssl-devel" ) + { + c++; + Package::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + + //solvable 5 (6): + //name: openssl-devel 0.9.8d-17.2 i586 + BOOST_CHECK_EQUAL(p->name(), "openssl-devel"); + //vendor: SUSE LINUX Products GmbH, Nuernberg, Germany + BOOST_CHECK_EQUAL(p->vendor(), "SUSE LINUX Products GmbH, Nuernberg, Germany"); + //solvable:checksum: 9f6a44015ad97680e9f93d0edefa1d533940479c + BOOST_CHECK_EQUAL(p->checksum(), CheckSum::sha1("9f6a44015ad97680e9f93d0edefa1d533940479c")); + //solvable:summary: + BOOST_CHECK_EQUAL(p->summary(), "Include Files and Libraries mandatory for Development."); + //solvable:description: This package contains all necessary include files and libraries needed + //to develop applications that require these. + BOOST_CHECK_EQUAL(p->description(), "This package contains all necessary include files and libraries needed\nto develop applications that require these."); + //solvable:authors: Mark J. Cox + //Ralf S. Engelschall + //Dr. Stephen + //Ben Laurie + //Bodo Moeller + //Ulf Moeller + //Holger Reif + //Paul C. Sutton + //solvable:packager: http://bugs.opensuse.org + //solvable:url: http://www.openssl.org/ + //solvable:buildtime: 1165493634 + //solvable:installsize: 3845 + BOOST_CHECK_EQUAL(p->installSize(), ByteCount(3937193)); + //solvable:downloadsize: 909 + BOOST_CHECK_EQUAL(p->downloadSize(), ByteCount(930588)); + //solvable:mediadir: rpm/i586 + //solvable:mediafile: openssl-devel-0.9.8d-17.2.i586.rpm + //solvable:license: BSD License and BSD-like, Other License(s), see package + //solvable:group: Development/Libraries/C and C++ + BOOST_CHECK_EQUAL(p->group(), "Development/Libraries/C and C++"); + //solvable:sourcearch: src + //solvable:sourceevr: (void) + //solvable:sourcename: openssl + //solvable:headerend: 34861 + + } + } + + // check that we actually found all testeable + // resolvables + BOOST_CHECK_EQUAL(c, 1); + + +} diff --git a/tests/sat/SolvableSpec_test.cc b/tests/sat/SolvableSpec_test.cc new file mode 100644 index 0000000..eeb6a15 --- /dev/null +++ b/tests/sat/SolvableSpec_test.cc @@ -0,0 +1,112 @@ +#include +#include +#include + +#include +#include +#include "TestSetup.h" + +#define BOOST_CHECK_MODULE SolvableSpec + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace boost::unit_test; + + +BOOST_AUTO_TEST_CASE(parsing) +{ + { + sat::SolvableSpec specs; + // adds no empty values + specs.addIdent ( IdString() ); + specs.addIdent ( IdString( "" ) ); + specs.addProvides( Capability() ); + specs.addProvides( Capability( "" ) ); + BOOST_CHECK( ! specs.containsIdent( IdString() ) ); + BOOST_CHECK( ! specs.containsProvides( Capability() ) ); + BOOST_CHECK( ! specs.containsIdent( IdString( "" ) ) ); + BOOST_CHECK( ! specs.containsProvides( Capability( "" ) ) ); + } + { + sat::SolvableSpec specs; + specs.addIdent ( IdString( "idstr" ) ); + specs.addProvides( Capability( "idcap" ) ); + specs.addProvides( Capability( "idvcap=13" ) ); + specs.addProvides( Capability( "idvwcap = 14" ) ); + BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) ); + } + { + sat::SolvableSpec specs; + specs.parse( "idstr" ); + specs.parse( "provides:idcap" ); + specs.parse( "provides:idvcap=13" ); + specs.parse( "provides:idvwcap = 14" ); + BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) ); + } + { + sat::SolvableSpec specs; + std::stringstream str; + str << "# some comment" << endl; + str << " # maybe indented" << endl; + str << " \t " << endl; // white line + str << " idstr " << endl; + str << " provides:idcap " << endl; + str << " provides:idvcap=13 " << endl; + str << " provides:idvwcap = 14 " << endl; + str << "" << endl; + specs.parseFrom( str ); + BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) ); + } + { + sat::SolvableSpec specs; + specs.splitParseFrom( "idstr provides:idcap provides:idvcap=13 provides:idvwcap\\ =\\ 14 id\\ ws\\ str provides:id\\ ws\\ cap\\ =\\ 99" ); + BOOST_CHECK( specs.containsIdent ( IdString( "idstr" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idcap", "", "" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvcap", "=", "13" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "idvwcap", "=", "14" ) ) ); + BOOST_CHECK( specs.containsIdent ( IdString( "id ws str" ) ) ); + BOOST_CHECK( specs.containsProvides( Capability( "", "id ws cap", "=", "99" ) ) ); + } +} + +BOOST_AUTO_TEST_CASE(eval) +{ + sat::SolvableSpec specs; + specs.parse( "candidate" ); + BOOST_CHECK( !specs.dirty() ); // ident don't + specs.parse( "provides:available_only > 1-1" ); + BOOST_CHECK( specs.dirty() ); // deps do + + TestSetup test( Arch_x86_64 ); + test.loadTestcaseRepos( TESTS_SRC_DIR "/data/TCSelectable" ); + std::set matches {2,3,8,9,14,15,16,17,28}; // matching Solvable IDs in TestcaseRepo (does not match srcpackage:!) + for ( const auto & solv : ResPool::instance() ) + { + //cout << ( specs.contains( solv ) ? "* " : " " ) << solv << endl; + BOOST_CHECK_MESSAGE( specs.contains( solv ) == matches.count( solv.id() ), str::Str() << "Wrong: " << ( specs.contains( solv ) ? "* " : " " ) << solv ); + } + + BOOST_CHECK( !specs.dirty() ); // loop built the cache + specs.parse( "provides:available_only > 1-1" ); + BOOST_CHECK( !specs.dirty() ); // already have this spec, no need to set dirty + + specs.parse( "provides:available_only = 1-1" ); + BOOST_CHECK( specs.dirty() ); // This is a new one, so got dirty + matches.insert( 13 ); + + for ( const auto & solv : ResPool::instance() ) + { + BOOST_CHECK_MESSAGE( specs.contains( solv ) == matches.count( solv.id() ), str::Str() << "Wrong: " << ( specs.contains( solv ) ? "* " : " " ) << solv ); + } +} diff --git a/tests/sat/Solvable_test.cc b/tests/sat/Solvable_test.cc new file mode 100644 index 0000000..f24407a --- /dev/null +++ b/tests/sat/Solvable_test.cc @@ -0,0 +1,215 @@ +#include +#include +#include + +#include +#include +#include +#include +#include "TestSetup.h" + + +#define BOOST_TEST_MODULE Solvable + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace boost::unit_test; + + +struct TestInit { + TestInit() + : _test( Arch_x86_64 ){ + _test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" ); + _test.loadRepo( TESTS_SRC_DIR "/data/11.0-update", "update" ); + } + + TestSetup _test; +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +BOOST_AUTO_TEST_CASE(attributes) +{ + MIL << sat::Pool::instance(); + Repository r = sat::Pool::instance().reposFind("opensuse"); + + int c = 0; + + for ( Repository::SolvableIterator it = r.solvablesBegin(); + it != r.solvablesEnd(); + ++it ) + { + sat::Solvable s = *it; + //MIL << s.ident() << endl; + if ( s.ident() == "pattern:apparmor" ) + { + c++; + + // solvable 21795 (21796): + // name: pattern:apparmor 11.0-67 i586 + // vendor: SUSE LINUX Products GmbH, Nuernberg, Germany + // provides: + // pattern:apparmor = 11.0-67 + // requires: + // pattern:basesystem + // apparmor-parser + // audit + // apparmor-profiles + // recommends: + // yast2-apparmor + // apparmor-utils + // pattern:apparmor_opt + // solvable:category: Base Technologies + // solvable:icon: yast-software + // solvable:summary: Novell AppArmor + // solvable:description: Novell AppArmor is an application security framework that provides mandatory access control for programs. It protects from exploitation of software flaws and compromised systems. It offers an advanced tool set that automates the development of per-program application security without requiring additional knowledge. + // solvable:isvisible: 1 + // solvable:order: 1030 + Pattern::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + BOOST_CHECK_EQUAL(p->name(), "apparmor"); + BOOST_CHECK_EQUAL(p->vendor(), "SUSE LINUX Products GmbH, Nuernberg, Germany"); + BOOST_CHECK_EQUAL(p->category(), "Base Technologies"); + BOOST_CHECK_EQUAL(p->summary(), "Novell AppArmor"); + BOOST_CHECK_EQUAL(p->icon(), "pattern-apparmor"); + BOOST_CHECK_EQUAL(p->userVisible(), true); + BOOST_CHECK_EQUAL(p->isDefault(), false); + } + if ( s.ident() == "pattern:default" ) + { + c++; + Pattern::Ptr p = asKind(makeResObject(s)); + BOOST_CHECK(p); + BOOST_CHECK_EQUAL(p->userVisible(), false); + } + } + + // check that we actually found all testeable + // resolvables + BOOST_CHECK_EQUAL(c, 2); +} + +BOOST_AUTO_TEST_CASE(asStringTest) +{ + BOOST_CHECK_EQUAL( sat::Solvable(0).asString(), "noSolvable" ); + BOOST_CHECK_EQUAL( sat::Solvable(1).asString(), "systemSolvable" ); + BOOST_CHECK_EQUAL( sat::Solvable(2).asString(), "product:openSUSE-11.1.x86_64" ); + BOOST_CHECK_EQUAL( sat::Solvable(3693).asString(), "autoyast2-2.16.19-0.1.src" ); + BOOST_CHECK_EQUAL( sat::Solvable(19222).asString(), "noSolvable" ); +#if 0 + Repository r = sat::Pool::instance().reposFind("update"); + for_( it, r.solvablesBegin(), r.solvablesEnd() ) + { + BOOST_CHECK_EQUAL( (*it).asString(), str::numstring((*it).id()) ); + } +#endif +} + +BOOST_AUTO_TEST_CASE(SplitIdent) +{ + sat::Solvable::SplitIdent split; + BOOST_CHECK_EQUAL( split.ident(), IdString() ); + BOOST_CHECK_EQUAL( split.kind(), ResKind() ); + BOOST_CHECK_EQUAL( split.name(), IdString() ); + + // - kind defaults to package + // - package and srcpackage have NO namespaced ident. + + split = sat::Solvable::SplitIdent( "foo" ); + BOOST_CHECK_EQUAL( split.ident(), "foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::package ); + BOOST_CHECK_EQUAL( split.name(), "foo" ); + + split = sat::Solvable::SplitIdent( "nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::package ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( "package:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::package ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::pattern ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( "srcpackage:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); // !!! + BOOST_CHECK_EQUAL( split.kind(), ResKind::srcpackage ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + // now split from kind,name + // - kind spec in name wins! + + split = sat::Solvable::SplitIdent( ResKind::package, "nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::package ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::pattern, "nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::pattern ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::srcpackage, "nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::srcpackage ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::package, "package:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::package ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::pattern, "package:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::package ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::srcpackage, "package:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::package ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::package, "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::pattern ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::pattern, "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::pattern ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::srcpackage, "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "pattern:nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::pattern ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::package, "srcpackage:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::srcpackage ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::pattern, "srcpackage:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::srcpackage ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + + split = sat::Solvable::SplitIdent( ResKind::srcpackage, "srcpackage:nokind:foo" ); + BOOST_CHECK_EQUAL( split.ident(), "nokind:foo" ); + BOOST_CHECK_EQUAL( split.kind(), ResKind::srcpackage ); + BOOST_CHECK_EQUAL( split.name(), "nokind:foo" ); + +} + +BOOST_AUTO_TEST_CASE(duData) +{ + DiskUsageCounter ducounter( DiskUsageCounter::justRootPartition() ); + + sat::Solvable s = *sat::WhatProvides( Capability("glibc-devel.x86_64 == 2.8.90-2.3") ).begin(); + BOOST_CHECK_EQUAL( (*ducounter.disk_usage( s ).begin()).pkg_size, 30629 ); +} diff --git a/tests/sat/WhatObsoletes_test.cc b/tests/sat/WhatObsoletes_test.cc new file mode 100644 index 0000000..f9dff54 --- /dev/null +++ b/tests/sat/WhatObsoletes_test.cc @@ -0,0 +1,35 @@ +#include "TestSetup.h" +#include + +namespace zypp +{ + namespace sat + { + // Obsoletes may either match against provides, or names. + // Configuration depends on the behaviour of rpm. + extern bool obsoleteUsesProvides; + } +} + +BOOST_AUTO_TEST_CASE(WhatObsoletes) +{ + TestSetup test( Arch_x86_64 ); + test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCWhatObsoletes" ); + + sat::Solvable test1( 2 ); + BOOST_REQUIRE_EQUAL( test1.name(), "test1" ); + + { + sat::obsoleteUsesProvides = true; + sat::WhatObsoletes w( test1 ); + BOOST_REQUIRE( w.size() == 2 ); + // (3)goaway-1-1.i586(@System) + // (5)meetoo-1-1.i586(@System) + } + { + sat::obsoleteUsesProvides = false; + sat::WhatObsoletes w( test1 ); + BOOST_REQUIRE( w.size() == 1 ); + // (3)goaway-1-1.i586(@System) + } +} \ No newline at end of file diff --git a/tests/sat/WhatProvides_test.cc b/tests/sat/WhatProvides_test.cc new file mode 100644 index 0000000..090cfa5 --- /dev/null +++ b/tests/sat/WhatProvides_test.cc @@ -0,0 +1,62 @@ +#include "TestSetup.h" + +BOOST_AUTO_TEST_CASE(WhatProvides) +{ + TestSetup test( Arch_x86_64 ); + test.loadRepo( TESTS_SRC_DIR"/data/openSUSE-11.1" ); + + { + sat::WhatProvides q( Capability("zypper") ); + BOOST_CHECK( ! q.empty() ); + BOOST_CHECK( q.size() == 1 ); + } + + { + sat::WhatProvides q( Capability("zypper.x86_64 == 0.12.5-1.1") ); + BOOST_CHECK( ! q.empty() ); + BOOST_CHECK( q.size() == 1 ); + } + + { + sat::WhatProvides q( Capability("zypper.i586 == 0.12.5-1.1") ); + BOOST_CHECK( q.empty() ); + BOOST_CHECK( q.size() == 0 ); + } + + { + // sat::WhatProvides::const_iterator requires proper + // copyctor and assignment. If they break + sat::WhatProvides q; + BOOST_CHECK( q.begin() == q.begin() ); + BOOST_CHECK( q.begin() == q.end() ); + + q = sat::WhatProvides( Capability("zypper.x86_64 == 0.12.5-1.1") ); + // q no longer empty + BOOST_CHECK( q.begin() == q.begin() ); + BOOST_CHECK( q.begin() != q.end() ); + + sat::WhatProvides::const_iterator a; + BOOST_CHECK( a == q.end() ); + + sat::WhatProvides::const_iterator b( q.begin() ); + BOOST_CHECK( b == q.begin() ); + +// SEC << LABELED(q.begin()) << endl; +// SEC << LABELED(q.end()) << endl; +// SEC << LABELED(a) << endl; +// SEC << LABELED(b) << endl; + + { + a = q.begin(); + BOOST_CHECK( a == q.begin() ); +// SEC << LABELED(a) << endl; +// SEC << LABELED(b) << endl; + + a = b; + BOOST_CHECK( a == b ); +// SEC << LABELED(a) << endl; +// SEC << LABELED(b) << endl; + } + BOOST_CHECK( a == q.begin() ); + } +} diff --git a/tests/zypp/Arch_test.cc b/tests/zypp/Arch_test.cc new file mode 100644 index 0000000..057bb40 --- /dev/null +++ b/tests/zypp/Arch_test.cc @@ -0,0 +1,79 @@ +// Arch.cc +// +// tests for Arch +// + +#include +#include +#include + +#include +#include + +// Boost.Test +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; + +/****************************************************************** +** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +** +** DESCRIPTION : +*/ +BOOST_AUTO_TEST_CASE(arch_test) +{ + ////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////// + BOOST_REQUIRE( Arch() == Arch_noarch ); + BOOST_REQUIRE( Arch("") == Arch_empty ); + BOOST_REQUIRE( ! Arch_noarch.empty() ); + BOOST_REQUIRE( Arch_empty.empty() ); + BOOST_REQUIRE( Arch_noarch.isBuiltIn() ); + BOOST_REQUIRE( ! Arch_empty.isBuiltIn() ); + BOOST_REQUIRE( Arch_empty != Arch_noarch ); + ////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////// + BOOST_CHECK_EQUAL( Arch("i386"), Arch_i386 ); + BOOST_CHECK_EQUAL( Arch("i386").idStr(), "i386" ); + BOOST_CHECK_EQUAL( Arch("i386").asString(), "i386" ); + BOOST_REQUIRE( Arch_i386.isBuiltIn() ); + + BOOST_CHECK_EQUAL( Arch("FOO").idStr(), "FOO" ); + BOOST_CHECK_EQUAL( Arch("FOO").asString(), "FOO" ); + BOOST_REQUIRE( ! Arch("FOO").isBuiltIn() ); + ////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////// + BOOST_REQUIRE( Arch_noarch.compatibleWith( Arch_noarch ) ); + BOOST_REQUIRE( Arch_noarch.compatibleWith( Arch_i386 ) ); + BOOST_REQUIRE( Arch_noarch.compatibleWith( Arch_x86_64 ) ); + + BOOST_REQUIRE( ! Arch_i386.compatibleWith( Arch_noarch ) ); + BOOST_REQUIRE( Arch_i386.compatibleWith( Arch_i386 ) ); + BOOST_REQUIRE( Arch_i386.compatibleWith( Arch_x86_64 ) ); + + BOOST_REQUIRE( ! Arch_x86_64.compatibleWith( Arch_noarch ) ); + BOOST_REQUIRE( ! Arch_x86_64.compatibleWith( Arch_i386 ) ); + BOOST_REQUIRE( Arch_x86_64.compatibleWith( Arch_x86_64 ) ); + BOOST_REQUIRE( Arch_x86_64.compatibleWith( Arch_x86_64_v4 ) ); + ////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////// + BOOST_CHECK_EQUAL( Arch::baseArch( Arch_x86_64_v4 ), Arch_x86_64 ); + BOOST_CHECK_EQUAL( Arch::baseArch( Arch_x86_64 ), Arch_x86_64 ); + BOOST_CHECK_EQUAL( Arch::baseArch( Arch_i686 ), Arch_i386 ); + ////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////// + BOOST_REQUIRE( Arch_i386.compare( Arch_noarch ) > 0 ); + BOOST_REQUIRE( Arch_i386.compare( Arch_i386 ) == 0 ); + BOOST_REQUIRE( Arch_i386.compare( Arch_x86_64 ) < 0 ); +} diff --git a/tests/zypp/CMakeLists.txt b/tests/zypp/CMakeLists.txt new file mode 100644 index 0000000..4824e23 --- /dev/null +++ b/tests/zypp/CMakeLists.txt @@ -0,0 +1,87 @@ +ADD_SUBDIRECTORY(base) + +ADD_TESTS( + Arch + Capabilities + CheckSum + ContentType + CpeId + Date + DrunkenBishop + Dup + Digest + Deltarpm + Edition + ExtendedPool + FileChecker + Flags + GZStream + InstanceId + KeyRing + Locale + Locks + PathInfo + Pathname + PluginFrame + PoolQueryCC + PoolQuery + ProgressData + PtrTypes + PublicKey + PurgeKernels + RWPtr + RepoManager + RepoStatus + ResKind + Resolver + ResStatus + RpmPkgSigCheck + Selectable + SetRelationMixin + SetTracker + StrMatcher + StringV + Target + Url + UserData + Vendor +) + +IF( NOT DISABLE_LIBPROXY ) + FIND_PACKAGE(libproxy) + IF ( NOT LIBPROXY_FOUND ) + MESSAGE( FATAL_ERROR "libproxy not found" ) + ELSE ( NOT LIBPROXY_FOUND ) + + include(CheckSymbolExists) + + # Check for function px_proxy_factory_free_proxies + set( CMAKE_REQUIRED_INCLUDES ${LIBPROXY_INCLUDE_DIRS} ) + set( CMAKE_REQUIRED_LIBRARIES ${LIBPROXY_LIBRARIES} ) + check_symbol_exists(px_proxy_factory_free_proxies "proxy.h" LIBPROXY_HAVE_FREE_PROXIES) + + ADD_TESTS( + Proxy + ) + if(LIBPROXY_HAVE_FREE_PROXIES) + target_compile_definitions( Proxy_test PUBLIC LIBPROXY_HAVE_FREE_PROXIES ) + endif() + target_link_libraries( Proxy_test PUBLIC ${LIBPROXY_LIBRARIES} ) + target_include_directories( Proxy_test PUBLIC ${LIBPROXY_INCLUDE_DIRS} ) + ENDIF( NOT LIBPROXY_FOUND ) +ENDIF() + +IF (ENABLE_ZCHUNK_COMPRESSION) + ADD_TESTS ( + ZChunk + ) +ENDIF(ENABLE_ZCHUNK_COMPRESSION) + +IF( NOT DISABLE_MEDIABACKEND_TESTS ) + ADD_TESTS( + Fetcher + MediaSetAccess + RepoInfo + ) +ENDIF() + diff --git a/tests/zypp/Capabilities_test.cc b/tests/zypp/Capabilities_test.cc new file mode 100644 index 0000000..cc83714 --- /dev/null +++ b/tests/zypp/Capabilities_test.cc @@ -0,0 +1,192 @@ +// Capabilities.cc +// +// tests for Capabilities +// +#include +#include + +// Boost.Test +#include + +#include "TestSetup.h" +#include +#include +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +BOOST_AUTO_TEST_CASE(capabilities_test) +{ + ////////////////////////////////////////////////////////////////////// + // Id 0 and 1 are nor equal, but share the same representation ""/NOCAP + ////////////////////////////////////////////////////////////////////// + + Capability c0( 0 ); // id 0 + Capability c1( 1 ); // id 1 + Capability cD; // default constructed empty + Capability cE( "" ); // empty + + BOOST_CHECK_EQUAL( c0.id(), 0 ); + BOOST_CHECK_EQUAL( c1.id(), 1 ); + BOOST_CHECK_EQUAL( Capability().id(), 1 ); // default constructed empty + BOOST_CHECK_EQUAL( Capability("").id(), 1 ); // empty + + BOOST_CHECK_EQUAL( c0.asString(), "" ); + BOOST_CHECK_EQUAL( c1.asString(), "" ); + + BOOST_CHECK_EQUAL( c0.empty(), true ); + BOOST_CHECK_EQUAL( c1.empty(), true ); + + BOOST_CHECK_EQUAL( c0.detail().kind(), CapDetail::NOCAP ); + BOOST_CHECK_EQUAL( c1.detail().kind(), CapDetail::NOCAP ); + + BOOST_CHECK_EQUAL( ( c0 == c1 ), false ); + BOOST_CHECK_EQUAL( Capability::matches( c0, c1 ), CapMatch::yes ); + + ////////////////////////////////////////////////////////////////////// + // skipping internal marker in Capabilities + ////////////////////////////////////////////////////////////////////// + + Capability r( "req" ); + Capability p( "prereq" ); + + sat::detail::IdType caps[10]; + caps[0] = r.id(); + caps[1] = sat::detail::solvablePrereqMarker; + caps[2] = p.id(); + caps[3] = 0; + + // Capabilities with and without prereq (skip marker in ++) + Capabilities c( caps ); + //cout << c << endl; + BOOST_CHECK_EQUAL( c.size(), 2 ); + Capabilities::const_iterator it( c.begin() ); + BOOST_CHECK_EQUAL( *it, r ); + BOOST_CHECK_EQUAL( it.tagged(), false ); + ++it; + BOOST_CHECK_EQUAL( *it, p ); + BOOST_CHECK_EQUAL( it.tagged(), true ); + + // Capabilities with prereq only (skip marker in ctor) + c = Capabilities( caps+1 ); + //cout << c << endl; + BOOST_CHECK_EQUAL( c.size(), 1 ); + it = c.begin(); + BOOST_CHECK_EQUAL( *it, p ); + BOOST_CHECK_EQUAL( it.tagged(), true ); + + + ////////////////////////////////////////////////////////////////////// + // + ////////////////////////////////////////////////////////////////////// + Capability n( "na.me" ); + Capability na( "na.me.i386" ); + Capability noe( "na.me == 1" ); + Capability naoe( "na.me.i386 == 1" ); + + BOOST_CHECK_EQUAL( n.detail().kind(), CapDetail::NAMED ); + BOOST_CHECK_EQUAL( na.detail().kind(), CapDetail::NAMED ); + BOOST_CHECK_EQUAL( noe.detail().kind(), CapDetail::VERSIONED ); + BOOST_CHECK_EQUAL( naoe.detail().kind(), CapDetail::VERSIONED ); + + BOOST_CHECK_EQUAL( n.detail().hasArch(), false ); + BOOST_CHECK_EQUAL( na.detail().hasArch(), true ); + BOOST_CHECK_EQUAL( noe.detail().hasArch(), false ); + BOOST_CHECK_EQUAL( naoe.detail().hasArch(), true ); + + BOOST_CHECK ( n.detail().arch().empty() ); + BOOST_CHECK_EQUAL( na.detail().arch(), Arch_i386.idStr() ); + BOOST_CHECK ( noe.detail().arch().empty() ); + BOOST_CHECK_EQUAL( naoe.detail().arch(), Arch_i386.idStr() ); + + BOOST_CHECK_EQUAL( Capability( "", "na.me", "", "" ), n ); + BOOST_CHECK_EQUAL( Capability( "i386", "na.me", "", "" ), na ); + BOOST_CHECK_EQUAL( Capability( "", "na.me", "==", "1" ), noe ); + BOOST_CHECK_EQUAL( Capability( "i386", "na.me", "==", "1" ), naoe ); + + // explicit arch + BOOST_CHECK_EQUAL( Capability( Arch_i386, "na.me" ), na ); + BOOST_CHECK_EQUAL( Capability( Arch_i386, "na.me == 1" ), naoe ); +} + +BOOST_AUTO_TEST_CASE(guessPackageSpec) +{ + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "" ), Capability( "", "", "", "" ) ); + + // Remember: 'name OP ver-rel': name may match provides + // 'name-ver-rel': name may match package names only + + // With no libzypp in the pool, no guess should succeed: + BOOST_REQUIRE( sat::WhatProvides(Capability("libzypp")).empty() ); + + // these must be guessed + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2" ), Capability( "", "libzypp-1-2", "", "" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2.i586" ), Capability( "i586", "libzypp-1-2", "", "" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp.i586-1-2" ), Capability( "", "libzypp.i586-1-2", "", "" ) ); + // these are unambiguous + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "patch:swmgmt=12" ), Capability( "", "swmgmt", "=", "12", ResKind::patch ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp=0:1.0.2-2" ), Capability( "", "libzypp", "=", "0:1.0.2-2" ) ); + + // now load some repo providing libzypp and see how the guessing changes: + test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" ); + BOOST_REQUIRE( ! sat::WhatProvides(Capability("libzypp")).empty() ); + + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2" ), Capability( "", "libzypp", "=", "1-2" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-1-2.i586" ), Capability( "i586", "libzypp", "=", "1-2" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp.i586-1-2" ), Capability( "i586", "libzypp", "=", "1-2" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp<=1.0.2-2" ), Capability( "", "libzypp", "<=", "1.0.2-2" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp<=1:1.0.2-2" ), Capability( "", "libzypp", "<=", "1:1.0.2-2" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp-0:1.0.2-2" ), Capability( "", "libzypp", "=", "0:1.0.2-2" ) ); + + // now with yast2-packagemanager which is just a provides. Guess must not lead to libzypp. + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "yast2-packagemanager-1-2" ), Capability( "", "yast2-packagemanager-1-2", "", "" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "yast2-packagemanager-1-2.i586" ), Capability( "i586", "yast2-packagemanager-1-2", "", "" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "yast2-packagemanager.i586-1-2" ), Capability( "", "yast2-packagemanager.i586-1-2","", "" ) ); + // these are unambiguous + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "yast2-packagemanager<=1.0.2-2" ), Capability( "", "yast2-packagemanager", "<=", "1.0.2-2" ) ); + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "yast2-packagemanager<=1:1.0.2-2" ), Capability( "", "yast2-packagemanager", "<=", "1:1.0.2-2" ) ); + + + // Double arch spec: the trailing one succeeds, the other one gets part of the name. + // As "libzypp.i586' is not in the pool, guessing fails. Result is a named cap. + BOOST_CHECK_EQUAL( Capability::guessPackageSpec( "libzypp.i586-1-2.ppc" ), + Capability( "ppc", "libzypp.i586-1-2", "", "" ) ); + + // Now check prepended kind specs. + + Capability cap( "package:libzypp=1-2" ); + BOOST_CHECK_EQUAL( cap, Capability( "", "libzypp", "=", "1-2", ResKind::package ) ); + BOOST_CHECK_EQUAL( cap, Capability( "", "package:libzypp", "=", "1-2" ) ); + BOOST_CHECK_EQUAL( cap, Capability( "", "package:libzypp", "=", "1-2", ResKind::pattern ) ); // known name prefix wins + // 'package:' is the default + BOOST_CHECK_EQUAL( cap, Capability( "libzypp=1-2" ) ); + BOOST_CHECK_EQUAL( cap, Capability( "", "libzypp", "=", "1-2" ) ); + + BOOST_CHECK_EQUAL( cap, Capability::guessPackageSpec( "package:libzypp-1-2" ) ); + BOOST_CHECK_EQUAL( cap, Capability::guessPackageSpec( "package:libzypp=1-2" ) ); + BOOST_CHECK_EQUAL( cap, Capability::guessPackageSpec( "libzypp-1-2" ) ); + BOOST_CHECK_EQUAL( cap, Capability::guessPackageSpec( "libzypp=1-2" ) ); + + + cap = Capability( "pattern:32bit=1-2" ); + BOOST_CHECK_EQUAL( cap, Capability( "", "32bit", "=", "1-2", ResKind::pattern ) ); + BOOST_CHECK_EQUAL( cap, Capability( "", "pattern:32bit", "=", "1-2" ) ); + BOOST_CHECK_EQUAL( cap, Capability( "", "pattern:32bit", "=", "1-2", ResKind::package ) ); // known name prefix wins + + BOOST_CHECK_EQUAL( cap, Capability::guessPackageSpec( "pattern:32bit-1-2" ) ); + BOOST_CHECK_EQUAL( cap, Capability::guessPackageSpec( "pattern:32bit=1-2" ) ); +} + + diff --git a/tests/zypp/CheckSum_test.cc b/tests/zypp/CheckSum_test.cc new file mode 100644 index 0000000..de28a2c --- /dev/null +++ b/tests/zypp/CheckSum_test.cc @@ -0,0 +1,53 @@ +#include +#include +#include + +// Boost.Test +#include + +#include +#include +#include +#include +#include + + +using boost::unit_test::test_case; +using namespace zypp; +using namespace std::string_literals; + +void chksumtest( const std::string & type_r, const std::string & sum_r ) +{ + BOOST_CHECK_EQUAL( type_r, CheckSum( sum_r ).type() ); // autodetect type + BOOST_CHECK_EQUAL( type_r, CheckSum( type_r, sum_r ).type() ); + BOOST_CHECK_EQUAL( sum_r, Digest::digest( type_r, "" ) ); + for ( const std::string & t : { "md5"s, "sha1"s, "sha224"s, "sha256"s, "sha384"s, "sha512"s, } ) + { + if ( t != type_r ) + { + BOOST_CHECK_THROW( CheckSum( t, sum_r ), Exception ); // wrong type/size + } + } +} + +// most frequently you implement test cases as a free functions +BOOST_AUTO_TEST_CASE(checksum_test) +{ + CheckSum e; + BOOST_CHECK( e.empty() ); + BOOST_CHECK( e.type().empty() ); + BOOST_CHECK( e.checksum().empty() ); + // sum for "" + // md5 32 d41d8cd98f00b204e9800998ecf8427e + // 1 40 da39a3ee5e6b4b0d3255bfef95601890afd80709 + // 224 56 d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f + // 256 64 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + // 384 96 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b + // 512 128 cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e + chksumtest( CheckSum::md5Type(), "d41d8cd98f00b204e9800998ecf8427e" ); + chksumtest( CheckSum::sha1Type(), "da39a3ee5e6b4b0d3255bfef95601890afd80709" ); + chksumtest( CheckSum::sha224Type(), "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f" ); + chksumtest( CheckSum::sha256Type(), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" ); + chksumtest( CheckSum::sha384Type(), "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b" ); + chksumtest( CheckSum::sha512Type(), "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e" ); +} diff --git a/tests/zypp/ContentType_test.cc b/tests/zypp/ContentType_test.cc new file mode 100644 index 0000000..fb93b6d --- /dev/null +++ b/tests/zypp/ContentType_test.cc @@ -0,0 +1,66 @@ +#include +#include +#include +#include + +using std::cout; +using std::endl; + +using zypp::ContentType; + +BOOST_AUTO_TEST_CASE(contenttype_default) +{ + ContentType v; + BOOST_CHECK( !v ); + BOOST_CHECK( v.empty() ); + BOOST_CHECK( v.emptyType() ); + BOOST_CHECK( v.emptySubtype() ); + + ContentType w( "/" ); + BOOST_CHECK_EQUAL( v == w, true ); + BOOST_CHECK_EQUAL( v != w, false ); + BOOST_CHECK_EQUAL( v < w, false ); + BOOST_CHECK_EQUAL( v <= w, true ); + BOOST_CHECK_EQUAL( v > w, false ); + BOOST_CHECK_EQUAL( v >= w, true ); + + BOOST_CHECK_EQUAL( v.asString(), "" ); +} + +BOOST_AUTO_TEST_CASE(contenttype_val) +{ + BOOST_CHECK_THROW( ContentType( " " ), std::invalid_argument ); + + BOOST_CHECK_THROW( ContentType( "//" ), std::invalid_argument ); + BOOST_CHECK_THROW( ContentType( "/ " ), std::invalid_argument ); + + BOOST_CHECK_THROW( ContentType( "/", "a" ), std::invalid_argument ); + BOOST_CHECK_THROW( ContentType( "a", "/" ), std::invalid_argument ); + + BOOST_CHECK_THROW( ContentType( " ", "a" ), std::invalid_argument ); + BOOST_CHECK_THROW( ContentType( "a", " " ), std::invalid_argument ); +} + +BOOST_AUTO_TEST_CASE(contenttype_cmp) +{ + std::set c( { + ContentType( "" ), + ContentType( "/" ), // == "" + ContentType( "a" ), + ContentType( "a/" ), // == "a" + ContentType( "/a" ), + ContentType( "" , "a" ), // == "/a" + ContentType( "a/b" ), + ContentType( "b/b" ), + ContentType( "b/c" ) + }); + + std::set::const_iterator i = c.begin(); + BOOST_CHECK_EQUAL( *(i++), ContentType() ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "", "a" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "a", "" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "a", "b" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "b", "b" ) ); + BOOST_CHECK_EQUAL( *(i++), ContentType( "b", "c" ) ); + BOOST_CHECK( i == c.end() ); +} diff --git a/tests/zypp/CpeId_test.cc b/tests/zypp/CpeId_test.cc new file mode 100644 index 0000000..2b5f446 --- /dev/null +++ b/tests/zypp/CpeId_test.cc @@ -0,0 +1,452 @@ +#include +#include +#include + +using std::cout; +using std::endl; + +using zypp::SetCompare; +using zypp::SetRelation; +using zypp::CpeId; +typedef CpeId::Value Value; + +/////////////////////////////////////////////////////////////////// +/// Symmetric attribute compare if wildcards are involved! +/// The specs define any comarison with a wildcarded attribute as +/// target to return \c uncomparable: +/// \code +/// wildcardfree <=> wildcarded ==> uncomparable, +/// wildcarded <=> wildcardfree ==> superset or disjoint +/// \endcode +/// But a symmetric result is much more intuitive: +/// \code +/// wildcardfree <=> wildcarded ==> subset or disjoint +/// wildcarded <=> wildcardfree ==> superset or disjoint +/// \endcode +/////////////////////////////////////////////////////////////////// +#define WFN_STRICT_SPEC 0 + +#define defVALUE(N,S) \ + const std::string N##Str( S ); \ + Value N( N##Str ); + +defVALUE( wildcardfree, "STrv\\*al\\?" ); // '\?' quoted? +const std::string wildcardfreeUri( "STrv%2aal%3f" ); +const std::string wildcardfreeFs( "STrv\\*al\\?" ); + +defVALUE( wildcardfree2, "stRV\\*al\\\\\\?" ); // '\\\?' backslash, quoted? + +defVALUE( wildcarded, "strv\\*AL?" ); // '?' ? +const std::string wildcardedUri( "strv%2aAL%01" ); +const std::string wildcardedFs( "strv\\*AL?" ); + +defVALUE( wildcarded2, "strv\\*AL\\\\?" ); // '\\?' backslash, ? + + + +BOOST_AUTO_TEST_CASE(cpeid_value_ANY) +{ + for ( const auto & c : { Value(), Value(nullptr), Value("*"), Value::ANY } ) + { + BOOST_CHECK( c.isANY() ); + BOOST_CHECK( ! c.isNA() ); + BOOST_CHECK( c.isLogical() ); + BOOST_CHECK( ! c.isString() ); + BOOST_CHECK( c == Value::ANY ); + BOOST_CHECK( c == nullptr ); // ANY + BOOST_CHECK( c != Value::NA ); + BOOST_CHECK( c != wildcardfree ); + BOOST_CHECK( c != wildcarded ); + BOOST_CHECK( ! c.isWildcardfree() ); + BOOST_CHECK( ! c.isWildcarded() ); + BOOST_CHECK_EQUAL( c.asFs(), "*" ); + BOOST_CHECK_EQUAL( c.asUri(), "" ); + BOOST_CHECK_EQUAL( c.asWfn(), "*" ); + BOOST_CHECK_EQUAL( c.asString(), c.asWfn() ); + } +} + +BOOST_AUTO_TEST_CASE(cpeid_value_NA) +{ + for ( const auto & c : { Value(""), Value::NA } ) + { + BOOST_CHECK( ! c.isANY() ); + BOOST_CHECK( c.isNA() ); + BOOST_CHECK( c.isLogical() ); + BOOST_CHECK( ! c.isString() ); + BOOST_CHECK( c != Value::ANY ); + BOOST_CHECK( c == Value::NA ); + BOOST_CHECK( c == std::string() ); // NA + BOOST_CHECK( c == "" ); // NA + BOOST_CHECK( c != wildcardfree ); + BOOST_CHECK( c != wildcarded ); + BOOST_CHECK( ! c.isWildcardfree() ); + BOOST_CHECK( ! c.isWildcarded() ); + BOOST_CHECK_EQUAL( c.asFs(), "-" ); + BOOST_CHECK_EQUAL( c.asUri(), "-" ); + BOOST_CHECK_EQUAL( c.asWfn(), "" ); + BOOST_CHECK_EQUAL( c.asString(), c.asWfn() ); + } +} + +BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcardfree) +{ + for ( const auto & c : { wildcardfree } ) + { + BOOST_CHECK( ! c.isANY() ); + BOOST_CHECK( ! c.isNA() ); + BOOST_CHECK( ! c.isLogical() ); + BOOST_CHECK( c.isString() ); + BOOST_CHECK( c != Value::ANY ); + BOOST_CHECK( c != Value::NA ); + BOOST_CHECK( c == wildcardfree ); + BOOST_CHECK( c == wildcardfreeStr ); + BOOST_CHECK( c == wildcardfreeStr.c_str() ); + BOOST_CHECK( c != wildcarded ); + BOOST_CHECK( c.isWildcardfree() ); + BOOST_CHECK( ! c.isWildcarded() ); + BOOST_CHECK_EQUAL( c.asFs(), wildcardfreeFs ); + BOOST_CHECK_EQUAL( c.asUri(), wildcardfreeUri ); + BOOST_CHECK_EQUAL( c.asWfn(), wildcardfreeStr ); + BOOST_CHECK_EQUAL( c.asString(), c.asWfn() ); + } + + BOOST_CHECK( wildcardfree2 == wildcardfree2 ); + BOOST_CHECK( wildcardfree2 != wildcardfree ); + BOOST_CHECK( wildcardfree2 != wildcarded ); + BOOST_CHECK( wildcardfree2.isWildcardfree() ); + BOOST_CHECK( ! wildcardfree2.isWildcarded() ); +} + +BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcarded) +{ + for ( const auto & c : { wildcarded } ) + { + BOOST_CHECK( ! c.isANY() ); + BOOST_CHECK( ! c.isNA() ); + BOOST_CHECK( ! c.isLogical() ); + BOOST_CHECK( c.isString() ); + BOOST_CHECK( c != Value::ANY ); + BOOST_CHECK( c != Value::NA ); + BOOST_CHECK( c != wildcardfree ); +#if WFN_STRICT_SPEC + BOOST_CHECK( c != wildcarded ); // !!! According to the CPE Name Matching Specification Version 2.3 + // unquoted wildcard characters yield an undefined result (not ==). +#else + BOOST_CHECK( c == wildcarded ); +#endif + BOOST_CHECK( ! c.isWildcardfree() ); + BOOST_CHECK( c.isWildcarded() ); + BOOST_CHECK_EQUAL( c.asFs(), wildcardedFs ); + BOOST_CHECK_EQUAL( c.asUri(), wildcardedUri ); + BOOST_CHECK_EQUAL( c.asWfn(), wildcardedStr ); + BOOST_CHECK_EQUAL( c.asString(), c.asWfn() ); + } + +#if WFN_STRICT_SPEC + BOOST_CHECK( wildcarded2 != wildcarded2 ); // unquoted wildcard characters yield an undefined result (not ==). +#else + BOOST_CHECK( wildcarded2 == wildcarded2 ); +#endif + BOOST_CHECK( wildcarded2 != wildcardfree ); + BOOST_CHECK( wildcarded2 != wildcarded ); + BOOST_CHECK( ! wildcarded2.isWildcardfree() ); + BOOST_CHECK( wildcarded2.isWildcarded() ); + + +} + +BOOST_AUTO_TEST_CASE(cpeid_value_valid) +{ + static const char *const hdig = "0123456789abcdef"; + + for ( char ch = 0; ch < CHAR_MAX; ++ch ) + { + // cout << "==== " << unsigned(ch) << endl; + char qchstr[] = { '\\', ch, '\0' }; + std::string chstr( qchstr+1 ); + char pchstr[] = { '%', hdig[(unsigned char)(ch)/16], hdig[(unsigned char)(ch)%16], '\0' }; + + if ( ch == '\0' ) + { + BOOST_CHECK( Value( chstr ).isNA() ); + BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument ); + BOOST_CHECK( Value( chstr, Value::uriFormat ).isANY() ); + } + else if ( ch <= ' ' || '~' < ch ) + { + BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument ); + BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument ); + BOOST_CHECK_THROW( (Value( chstr, Value::uriFormat )), std::invalid_argument ); + } + else if ( ( '0' <= ch && ch <= '9' ) + || ( 'A' <= ch && ch <= 'Z' ) + || ( 'a' <= ch && ch <= 'z' ) + || ch == '_' ) + { + BOOST_CHECK( Value( chstr ).isString() ); + BOOST_CHECK( Value( chstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() ); + + BOOST_CHECK_THROW( (Value( qchstr )), std::invalid_argument ); + BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() ); + } + else if ( ch == '*' ) + { + BOOST_CHECK( Value( chstr ).isANY() ); + BOOST_CHECK( Value( chstr, Value::fsFormat ).isANY() ); + BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( qchstr ).isString() ); + BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() ); + } + else if ( ch == '?' ) + { + BOOST_CHECK( Value( chstr ).isString() ); + BOOST_CHECK( Value( chstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( chstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( qchstr ).isString() ); + BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() ); + } + else if ( ch == '-' ) + { + BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument ); + BOOST_CHECK( Value( chstr, Value::fsFormat ).isNA() ); + BOOST_CHECK( Value( chstr, Value::uriFormat ).isNA() ); + + BOOST_CHECK_THROW( (Value( qchstr )), std::invalid_argument ); + BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() ); + } + else if ( ch == '\\' ) + { + BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument ); + BOOST_CHECK_THROW( (Value( chstr, Value::fsFormat )), std::invalid_argument ); + BOOST_CHECK( (Value( chstr, Value::uriFormat )).isString() ); + + BOOST_CHECK( Value( qchstr ).isString() ); + BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() ); + } + else + { + BOOST_CHECK_THROW( (Value( chstr )), std::invalid_argument ); + Value f( chstr, Value::fsFormat ); + BOOST_CHECK( f.isString() ); + Value u( chstr, Value::uriFormat ); + BOOST_CHECK( u.isString() ); + + BOOST_CHECK_EQUAL( f.asString(), u.asString() ); + if ( ch == '.' ) + { + BOOST_CHECK_EQUAL( f.asFs(), chstr ); + BOOST_CHECK_EQUAL( f.asUri(), chstr ); + } + else + { + BOOST_CHECK_EQUAL( f.asFs(), qchstr ); + BOOST_CHECK_EQUAL( f.asUri(), pchstr ); + } + + BOOST_CHECK( Value( qchstr ).isString() ); + BOOST_CHECK( Value( qchstr, Value::fsFormat ).isString() ); + BOOST_CHECK( Value( qchstr, Value::uriFormat ).isString() ); + + BOOST_CHECK( Value( pchstr, Value::uriFormat ).isString() ); + } + } + + BOOST_CHECK_THROW( Value( "\\!\\a\\-\\_\\.\\!" ), std::invalid_argument ); + BOOST_CHECK_EQUAL( Value( "\\!\\a\\-\\_\\.\\!", Value::fsFormat ).asFs(), "\\!a-_.\\!" ); +} + +BOOST_AUTO_TEST_CASE(cpeid_type_checks) +{ + for ( const auto & c : { Value::ANY, Value::NA, wildcardfree, wildcarded } ) + { + BOOST_CHECK_EQUAL( c.isANY(), c.type() == Value::Type::ANY ); + BOOST_CHECK_EQUAL( c.isNA(), c.type() == Value::Type::NA ); + BOOST_CHECK_EQUAL( c.isWildcardfree(), c.type() == Value::Type::wildcardfree ); + BOOST_CHECK_EQUAL( c.isWildcarded(), c.type() == Value::Type::wildcarded ); + BOOST_CHECK_EQUAL( c.isLogical(), c.isLogical( c.type() ) ); + BOOST_CHECK_EQUAL( c.isString(), c.isString( c.type() ) ); + BOOST_CHECK_EQUAL( c.isLogical(), ! c.isString() ); + } +} + +BOOST_AUTO_TEST_CASE(cpeid_compare) +{ + BOOST_CHECK( compare( Value::ANY, Value::ANY, SetCompare::equal ) ); + BOOST_CHECK( compare( Value::ANY, Value::NA, SetCompare::properSuperset ) ); + BOOST_CHECK( compare( Value::ANY, wildcardfree, SetCompare::properSuperset ) ); +#if WFN_STRICT_SPEC + BOOST_CHECK( compare( Value::ANY, wildcarded, SetCompare::uncomparable ) ); +#else + BOOST_CHECK( compare( Value::ANY, wildcarded, SetCompare::properSuperset ) ); +#endif + + BOOST_CHECK( compare( Value::NA, Value::ANY, SetCompare::properSubset ) ); + BOOST_CHECK( compare( Value::NA, Value::NA, SetCompare::equal ) ); + BOOST_CHECK( compare( Value::NA, wildcardfree, SetCompare::disjoint ) ); +#if WFN_STRICT_SPEC + BOOST_CHECK( compare( Value::NA, wildcarded, SetCompare::uncomparable ) ); +#else + BOOST_CHECK( compare( Value::NA, wildcarded, SetCompare::disjoint ) ); +#endif + + BOOST_CHECK( compare( wildcardfree, Value::ANY, SetCompare::properSubset ) ); + BOOST_CHECK( compare( wildcardfree, Value::NA, SetCompare::disjoint ) ); + //BOOST_CHECK( compare( wildcardfree, wildcardfree, kNeedsCloserLook, // equal or disjoint + BOOST_CHECK( compare( wildcardfree, wildcardfree, SetCompare::equal ) ); + BOOST_CHECK( compare( wildcardfree, wildcardfree2, SetCompare::disjoint ) ); +#if WFN_STRICT_SPEC + BOOST_CHECK( compare( wildcardfree, wildcarded, SetCompare::uncomparable ) ); +#else + //BOOST_CHECK( compare( wildcardfree, wildcarded, kNeedsCloserLook, // subset or disjoint + BOOST_CHECK( compare( wildcardfree, wildcarded, SetCompare::properSubset ) ); + BOOST_CHECK( compare( wildcardfree, wildcarded2, SetCompare::disjoint ) ); +#endif + + BOOST_CHECK( compare( wildcarded, Value::ANY, SetCompare::properSubset ) ); + BOOST_CHECK( compare( wildcarded, Value::NA, SetCompare::disjoint ) ); + //BOOST_CHECK( compare( wildcarded, wildcardfree, kNeedsCloserLook, // superset or disjoint + BOOST_CHECK( compare( wildcarded, wildcardfree, SetCompare::properSuperset ) ); + BOOST_CHECK( compare( wildcarded, wildcardfree2, SetCompare::disjoint ) ); +#if WFN_STRICT_SPEC + BOOST_CHECK( compare( wildcarded, wildcarded, SetCompare::uncomparable ) ); +#else + //BOOST_CHECK( compare( wildcarded, wildcarded, kNeedsCloserLook, // equal or uncomparable + BOOST_CHECK( compare( wildcarded, wildcarded, SetCompare::equal ) ); + BOOST_CHECK( compare( wildcarded, wildcarded2, SetCompare::uncomparable ) ); +#endif +} + + +BOOST_AUTO_TEST_CASE(cpeid_value_string_wildcard) +{ + for ( const auto & c : { Value( "a" ), Value( "\\*" ), Value( "\\?" ) } ) + { + BOOST_CHECK( c.isWildcardfree() ); + BOOST_CHECK( !c.isWildcarded() ); + } + + for ( const auto & c : { Value( "*\\*" ), Value( "\\**" ), Value( "?" ), Value( "??\\?" ), Value( "\\???" ) } ) + { + BOOST_CHECK( !c.isWildcardfree() ); + BOOST_CHECK( c.isWildcarded() ); + } +} + +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(cpeid_basics) +{ + BOOST_CHECK_THROW( CpeId( "malformed" ), std::invalid_argument ); + CpeId none( "malformed", CpeId::noThrow ); + BOOST_CHECK_EQUAL( CpeId::NoThrowType::lastMalformed, "malformed" ); + CpeId( "", CpeId::noThrow ); + BOOST_CHECK_EQUAL( CpeId::NoThrowType::lastMalformed, "" ); + + for ( const auto & c : { CpeId(), CpeId( nullptr ), CpeId( "" ), CpeId( std::string() ), CpeId( "cpe:2.3:" ), CpeId( "cpe:/" ) } ) + { + BOOST_CHECK( ! c ); // evaluate false in boolean context + BOOST_CHECK_EQUAL( c.asString(), c.asFs() ); + BOOST_CHECK_EQUAL( c.asFs(), "cpe:2.3:*:*:*:*:*:*:*:*:*:*:*" ); + BOOST_CHECK_EQUAL( c.asUri(), "cpe:/" ); + BOOST_CHECK_EQUAL( c.asWfn(), "wfn:[]" ); + BOOST_CHECK_EQUAL( c, none ); // matching!! + } + + for ( const auto & c : { CpeId( "cpe:/o:sle" ), CpeId( "cpe:/o:*" ) } ) + { + BOOST_CHECK( c ); // evaluate true in boolean context + BOOST_CHECK( ! c.asString().empty() );// empty string rep + BOOST_CHECK_EQUAL( c, c ); // matching!! + } +} + +void testStrconv( const std::string & fs, const std::string & uri, const std::string & wfn ) +{ + CpeId fromFS( fs ) ; + CpeId fromURI( uri ); + + BOOST_CHECK_EQUAL( fromFS, fromURI ); + + for ( const auto & c : { fromFS, fromURI } ) + { + BOOST_CHECK_EQUAL( c.asFs(), fs ); + BOOST_CHECK_EQUAL( c.asUri(), uri ); + BOOST_CHECK_EQUAL( c.asWfn(), wfn ); + } +} + +BOOST_AUTO_TEST_CASE(cpeid_strconv) +{ + // colon embedded in product value + testStrconv ( "cpe:2.3:a:opensuse:lib\\:zypp:14.16.0:beta:*:*:*:*:*:-", + "cpe:/a:opensuse:lib%3azypp:14.16.0:beta:~~~~~-", + "wfn:[part=\"a\",vendor=\"opensuse\",product=\"lib\\:zypp\",version=\"14\\.16\\.0\",update=\"beta\",other=NA]" ); + + testStrconv ( "cpe:2.3:a:hp:insight_diagnostics:7.4.0.1570:-:*:*:online:win2003:x64:*", + "cpe:/a:hp:insight_diagnostics:7.4.0.1570:-:~~online~win2003~x64~", + "wfn:[part=\"a\",vendor=\"hp\",product=\"insight_diagnostics\",version=\"7\\.4\\.0\\.1570\",update=NA,sw_edition=\"online\",target_sw=\"win2003\",target_hw=\"x64\"]" ); + + testStrconv ( "cpe:2.3:a:hp:openview_network_manager:7.51:*:*:*:*:linux:*:*", + "cpe:/a:hp:openview_network_manager:7.51::~~~linux~~", + "wfn:[part=\"a\",vendor=\"hp\",product=\"openview_network_manager\",version=\"7\\.51\",target_sw=\"linux\"]" ); + + testStrconv ( "cpe:2.3:a:foo\\\\bar:big\\$money_manager_2010:*:*:*:*:special:ipod_touch:80gb:*", + "cpe:/a:foo%5cbar:big%24money_manager_2010:::~~special~ipod_touch~80gb~", + "wfn:[part=\"a\",vendor=\"foo\\\\bar\",product=\"big\\$money_manager_2010\",sw_edition=\"special\",target_sw=\"ipod_touch\",target_hw=\"80gb\"]" ); + + BOOST_CHECK_THROW( (CpeId( "cpe:/x:" )), std::invalid_argument ); // illegal part 'x' + BOOST_CHECK_THROW( CpeId( "cpe:/a:foo%5cbar:big%24money_2010%07:::~~special~ipod_touch~80gb~" ), std::invalid_argument ); // illegal %07 + BOOST_CHECK_EQUAL( CpeId( "cpe:/a:foo~bar:big%7emoney_2010" ).asUri(), "cpe:/a:foo%7ebar:big%7emoney_2010" ); // unescaped ~ is ok but not preferred +} + +BOOST_AUTO_TEST_CASE(cpeid_matches) +{ + CpeId sle( "cpe:/o:sles" ); + CpeId win( "cpe:/o:windows" ); + CpeId any; + CpeId ons( "cpe:2.3:o:??????s" ); + CpeId oops( "cpe:2.3:o:?????s" ); + + BOOST_CHECK_EQUAL( compare( sle, win ), SetRelation::disjoint ); + + BOOST_CHECK_EQUAL( compare( sle, any ), SetRelation::subset ); + BOOST_CHECK_EQUAL( compare( win, any ), SetRelation::subset ); + + BOOST_CHECK_EQUAL( compare( any, sle ), SetRelation::superset ); + BOOST_CHECK_EQUAL( compare( any, win ), SetRelation::superset ); + +#if WFN_STRICT_SPEC + BOOST_CHECK_EQUAL( compare( sle, ons ), SetRelation::uncomparable ); + BOOST_CHECK_EQUAL( compare( win, ons ), SetRelation::uncomparable ); +#else + BOOST_CHECK_EQUAL( compare( sle, ons ), SetRelation::subset ); + BOOST_CHECK_EQUAL( compare( win, ons ), SetRelation::subset ); +#endif + + BOOST_CHECK_EQUAL( compare( ons, sle ), SetRelation::superset ); + BOOST_CHECK_EQUAL( compare( ons, win ), SetRelation::superset ); + + BOOST_CHECK_EQUAL( compare( oops, sle ), SetRelation::superset ); + BOOST_CHECK_EQUAL( compare( oops, win ), SetRelation::disjoint ); + +} diff --git a/tests/zypp/Date_test.cc b/tests/zypp/Date_test.cc new file mode 100644 index 0000000..657dbb1 --- /dev/null +++ b/tests/zypp/Date_test.cc @@ -0,0 +1,10 @@ +#include + +#include + +BOOST_AUTO_TEST_CASE(date_test) +{ + std::string format = "%Y-%m-%d %H:%M:%S"; + std::string date = "2009-02-14 00:31:30"; + BOOST_CHECK_EQUAL(zypp::Date(date,format).form(format), date); +} diff --git a/tests/zypp/Deltarpm_test.cc b/tests/zypp/Deltarpm_test.cc new file mode 100644 index 0000000..e36c970 --- /dev/null +++ b/tests/zypp/Deltarpm_test.cc @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include "KeyRingTestReceiver.h" + +using boost::unit_test::test_case; + +using std::cout; +using std::endl; +using namespace zypp; +using namespace zypp::repo; +using namespace zypp::filesystem; + +#define TEST_DIR TESTS_SRC_DIR "/zypp/data/Delta" + +BOOST_AUTO_TEST_CASE(delta) +{ + KeyRing::setDefaultAccept( KeyRing::ACCEPT_UNKNOWNKEY | KeyRing::ACCEPT_UNSIGNED_FILE ); + + TmpDir rootdir; + RepoManager rm( RepoManagerOptions::makeTestSetup( rootdir ) ); + + RepoInfo updates; + updates.setAlias("updates"); + updates.addBaseUrl( Pathname(TEST_DIR).asUrl() ); + + try + { + rm.buildCache(updates); + rm.loadFromCache(updates); + } + catch (const Exception & e) + { + BOOST_FAIL( std::string("Problem getting the data: ")+ e.msg()) ; + } + sat::Pool pool(sat::Pool::instance()); + + repo::DeltaCandidates dc(std::list(pool.reposBegin(),pool.reposEnd()), "libzypp"); + + std::list deltas = dc.deltaRpms(0); + for_ (it,deltas.begin(),deltas.end()) + { + BOOST_CHECK(it->name() == "libzypp"); + BOOST_CHECK(it->edition() == Edition("4.21.3-2")); + BOOST_CHECK(it->arch() == "i386"); + BOOST_CHECK(it->baseversion().edition().match(Edition("4.21.3-1")) + ||it->baseversion().edition().match(Edition("4.21.2-3"))); + + cout << it->name() << " - " << it->edition() << " - " << it->arch() + << " base: " << it->baseversion().edition() << endl; + + cout << (it->edition() == "4.21.3-2") << endl; // fine + cout << (it->edition() == Edition("4.21.3-2")) << endl; // fine + cout << (it->edition().match(Edition("4.21.3-2")) == 0) << endl; // match returns -1,0,1 + cout << (it->edition().match("4.21.3-2") == 0) << endl; // match returns -1,0,1 + } +} diff --git a/tests/zypp/Digest_test.cc b/tests/zypp/Digest_test.cc new file mode 100644 index 0000000..528574f --- /dev/null +++ b/tests/zypp/Digest_test.cc @@ -0,0 +1,35 @@ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::filesystem; + +/** + * Test case for + * static std::string digest(const std::string& name, std::istream& is, size_t bufsize = 4096); + */ +BOOST_AUTO_TEST_CASE(digest) +{ + std::string data("I will test the checksum of this"); + std::stringstream str1(data); + std::stringstream str2(data); + std::stringstream str3(data); + + BOOST_CHECK_EQUAL( Digest::digest( "sha1", str1 ), "142df4277c326f3549520478c188cab6e3b5d042" ); + BOOST_CHECK_EQUAL( Digest::digest( "md5", str2 ), "f139a810b84d82d1f29fc53c5e59beae" ); + // FIXME i think it should throw + BOOST_CHECK_EQUAL( Digest::digest( "lalala", str3) , "" ); +} diff --git a/tests/zypp/DrunkenBishop_test.cc b/tests/zypp/DrunkenBishop_test.cc new file mode 100644 index 0000000..85dc92e --- /dev/null +++ b/tests/zypp/DrunkenBishop_test.cc @@ -0,0 +1,90 @@ +#include +#include +#include + +using boost::unit_test::test_case; + +using namespace zypp; +using base::DrunkenBishop; + +BOOST_AUTO_TEST_CASE(drunkenbishop) +{ + { + DrunkenBishop b; + BOOST_CHECK_EQUAL( b.asString(), + "++\n" + "++" ); + } + { + DrunkenBishop b( "94", 0, 0 ); + BOOST_CHECK_EQUAL( b.asString(), + "+-+\n" + "|E|\n" + "+-+" ); + } + { + BOOST_CHECK_THROW( DrunkenBishop( "9g" ), std::invalid_argument ); + } + { + DrunkenBishop b( "" ); + BOOST_CHECK_EQUAL( b.asString(), + "+-----------------+\n" + "| |\n" + "| |\n" + "| |\n" + "| |\n" + "| E |\n" + "| |\n" + "| |\n" + "| |\n" + "| |\n" + "+-----------------+" ); + } + { + DrunkenBishop b( "CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC", "Title" ); + BOOST_CHECK_EQUAL( b.asString(), + "+-----[Title]-----+\n" + "| |\n" + "| |\n" + "| |\n" + "| ^ |\n" + "| E |\n" + "| |\n" + "| |\n" + "| |\n" + "| |\n" + "+---[CCCCCCCC]----+" ); + } + { + DrunkenBishop b( "9c6fb17fa201ad829d808739379a2a51", "very very long Title" ); + BOOST_CHECK_EQUAL( b.asString(), + "+[very very long ]+\n" + "| |\n" + "| |\n" + "| |\n" + "| E+ . o |\n" + "| .= = S o |\n" + "|. * = . + o |\n" + "| .o . + . = |\n" + "|.. . . o. . |\n" + "|o ...o |\n" + "+---[379A2A51]----+" ); + } + { + DrunkenBishop b( "4E98E67519D98DC7362A5990E3A5C360307E3D54" ); + BOOST_CHECK_EQUAL( b.asString(), + "+-------------------+\n" + "| ^. .^E |\n" + "| . .^^: . |\n" + "| ...:^? : |\n" + "| . ?.: i |\n" + "| ^ i : . |\n" + "| : S l . |\n" + "| ^ : . . |\n" + "| . . |\n" + "| |\n" + "| |\n" + "| |\n" + "+----[307E3D54]-----+" ); + } +} diff --git a/tests/zypp/Dup_test.cc b/tests/zypp/Dup_test.cc new file mode 100644 index 0000000..c0d13a3 --- /dev/null +++ b/tests/zypp/Dup_test.cc @@ -0,0 +1,67 @@ +#include "TestSetup.h" +#include +#include +#include +#include + +#define BOOST_TEST_MODULE Dup + +///////////////////////////////////////////////////////////////////////////// + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCdup" ); + dumpRange( USR, test.pool().knownRepositoriesBegin(), + test.pool().knownRepositoriesEnd() ) << endl; + } + ~TestInit() { test.reset(); } +}; + +template +std::ostream & vdumpPoolStats( std::ostream & str, TIterator begin_r, TIterator end_r ) +{ + pool::PoolStats stats; + for_( it, begin_r, end_r ) + { + str << *it << endl; + stats( *it ); + } + return str << stats; +} + +bool upgrade( ) +{ + bool rres = false; + { + rres = getZYpp()->resolver()->doUpgrade(); + } + if ( ! rres ) + { + ERR << "upgrade " << rres << endl; + getZYpp()->resolver()->problems(); + return false; + } + MIL << "upgrade " << rres << endl; + vdumpPoolStats( USR << "Transacting:"<< endl, + make_filter_begin(test.pool()), + make_filter_end(test.pool()) ) << endl; + return true; +} + + +BOOST_GLOBAL_FIXTURE( TestInit ); + +BOOST_AUTO_TEST_CASE( orphaned ) +{ + USR << "pool: " << test.pool() << endl; + BOOST_REQUIRE( upgrade( ) ); + + ResPoolProxy proxy( test.poolProxy() ); + BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "glibc" )->status(), ui::S_KeepInstalled ); + BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "release-package" )->status(), ui::S_AutoUpdate ); + BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "dropped_required" )->status(), ui::S_KeepInstalled ); + BOOST_CHECK_EQUAL( proxy.lookup( ResKind::package, "dropped" )->status(), ui::S_AutoDel ); +} + diff --git a/tests/zypp/Edition_test.cc b/tests/zypp/Edition_test.cc new file mode 100644 index 0000000..0ba662d --- /dev/null +++ b/tests/zypp/Edition_test.cc @@ -0,0 +1,38 @@ +// Edition.cc +// +// tests for Edition +// + +#include +#include + +#include + +using boost::unit_test::test_case; + +using namespace zypp; + +BOOST_AUTO_TEST_CASE(edition) +{ + Edition _ed1 ("1"); + Edition _ed2 ("1.1"); + Edition _ed3 ("1:1"); + Edition _ed4 ("2:1-1"); + + BOOST_CHECK_EQUAL(_ed2.version(), "1.1"); + BOOST_CHECK_EQUAL(_ed2.release(), ""); + BOOST_CHECK_EQUAL(_ed2.epoch(), 0U); + BOOST_CHECK_EQUAL(_ed4.epoch(), 2U); + + BOOST_CHECK_EQUAL(_ed1, Edition ("1", "")); + BOOST_CHECK_EQUAL(_ed2, Edition ("1.1", "")); + BOOST_CHECK_EQUAL(_ed2, Edition ("1_1", "")); // Edition strings may differ in separator (non alphanum) + BOOST_CHECK_EQUAL(_ed2, Edition ("0:1.1")); // epoch 0 is no epoch + BOOST_CHECK_EQUAL(_ed3, Edition ("1", "", "1")); + BOOST_CHECK_EQUAL(_ed3, Edition ("1", "", 1)); + BOOST_CHECK_EQUAL(_ed4, Edition ("1", "1", 2)); + + BOOST_CHECK_EQUAL( Edition::compare("1:1-1","2:1-1"), -1 ); + BOOST_CHECK_EQUAL( Edition::compare("2:1-1","2:1-1"), 0 ); + BOOST_CHECK_EQUAL( Edition::compare("3:1-1","2:1-1"), 1 ); +} diff --git a/tests/zypp/ExtendedPool_test.cc b/tests/zypp/ExtendedPool_test.cc new file mode 100644 index 0000000..7c44549 --- /dev/null +++ b/tests/zypp/ExtendedPool_test.cc @@ -0,0 +1,101 @@ +#include + +#include + +#include "TestSetup.h" +#include + +#include +#include + +using boost::unit_test::test_case; +using std::cin; +using std::cout; +using std::cerr; +using std::endl; +using namespace zypp; + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +void testcase_init() +{ +// cout << "+++[repoinit]=======================" << endl; + test.loadTestcaseRepos( TESTS_SRC_DIR"/data/PoolReuseIds/SeqA" ); +// for ( auto && pi : ResPool::instance() ) +// cout << pi << " " << pi.resolvable() << endl; +// cout << "---[repoinit]=======================" << endl; +} + +void testcase_init2() +{ +// cout << "+++[repoinit2]=======================" << endl; + sat::Pool::instance().reposEraseAll(); + test.loadTestcaseRepos( TESTS_SRC_DIR"/data/PoolReuseIds/SeqB" ); +// for ( auto && pi : ResPool::instance() ) +// cout << pi << " " << pi.resolvable() << endl; +// cout << "---[repoinit2]=======================" << endl; +} + +void checkpi( const PoolItem & pi ) +{ + BOOST_CHECK( pi.resolvable() ); + BOOST_CHECK_EQUAL( pi.id(), pi.resolvable()->id() ); + BOOST_CHECK_EQUAL( bool(asKind( pi.resolvable() )), isKind(pi) ); + BOOST_CHECK_EQUAL( bool(asKind( pi.resolvable() )), isKind(pi) ); + BOOST_CHECK_EQUAL( bool(asKind( pi.resolvable() )), isKind(pi) ); + BOOST_CHECK_EQUAL( bool(asKind( pi.resolvable() )), isKind(pi) ); + BOOST_CHECK_EQUAL( bool(asKind( pi.resolvable() )), isKind(pi) ); + BOOST_CHECK_EQUAL( bool(asKind( pi.resolvable() )), isKind(pi) ); +} + +void repocheck() +{ +// cout << "+++[repocheck]======================" << endl; + for ( auto && pi : ResPool::instance() ) + { +// cout << "??? " << pi << endl; + checkpi( pi ); + } +// cout << "---[repocheck]======================" << endl; +} + +/////////////////////////////////////////////////////////////////// +// Check that after ERASING ALL REPOS and loading a new one, ResPool +// actually creates new PoolItems rather than reusing already existing +// ones. +// +// Adding/removing repos will not reuse poolIDs unless actually all +// repos are removed from the pool. In this case ResPool must invalidate +// ALL existing PoolItems (especially the Resolvable Pointers inside). +// +// SeqA SeqB +// (1)package - (1)application +// (2)pattern - (2)package +// ... ... +// +// The two test repos have Resolvables of different kind in different +// order. If ResPool fails to recreate the PoolItem, we'll experience +// cast errors. PoolItem(1) will claim to be an application, but the +// Resolvable is still the original one created for a package... +/////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(t_1) { + + //will print additional context information on error + BOOST_TEST_CONTEXT("First phase") { + testcase_init(); + repocheck(); + } + + BOOST_TEST_CONTEXT("Second phase") { + testcase_init2(); + repocheck(); + } +} diff --git a/tests/zypp/Fetcher_test.cc b/tests/zypp/Fetcher_test.cc new file mode 100644 index 0000000..5f03d0b --- /dev/null +++ b/tests/zypp/Fetcher_test.cc @@ -0,0 +1,376 @@ +#include "TestSetup.h" + +#include +#include + +#include "WebServer.h" + +#define BOOST_TEST_MODULE fetcher_test + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/data/Fetcher/remote-site") + +BOOST_AUTO_TEST_SUITE( fetcher_test ); + +BOOST_AUTO_TEST_CASE(fetcher_enqueuedir_noindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // Now test that without trusting it, it should throw + // do the test by trusting the SHA1SUMS file signature key + { + filesystem::TmpDir dest; + Fetcher fetcher; + fetcher.enqueueDir(OnMediaLocation("/complexdir"), true); + fetcher.start( dest.path(), media ); + fetcher.reset(); + + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir2").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir2/subdir2-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file2.txt").isExist() ); + } +} + +BOOST_AUTO_TEST_CASE(fetcher_enqueuedir_autoindex_untrustedkey) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key + { + filesystem::TmpDir dest; + + // add the key as untrusted, which is the same as not adding it and + // let autodiscovery to add it + + Fetcher fetcher; + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDir(OnMediaLocation("/complexdir"), true); + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), Exception); + + BOOST_CHECK( ! PathInfo(dest.path() + "/complexdir/subdir2").isExist() ); + BOOST_CHECK( ! PathInfo(dest.path() + "/complexdir/subdir2/subdir2-file1.txt").isExist() ); + BOOST_CHECK( ! PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file1.txt").isExist() ); + BOOST_CHECK( ! PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file2.txt").isExist() ); + + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(fetcher_enqueuedir_autoindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key + { + filesystem::TmpDir dest; + + // add the key as trusted + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/complexdir/subdir1/SHA1SUMS.key"), true); + Fetcher fetcher; + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDir(OnMediaLocation("/complexdir"), true); + fetcher.start( dest.path(), media ); + + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir2").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir2/subdir2-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file2.txt").isExist() ); + + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(fetcher_enqueue_digested_dir_autoindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key but with a broken file + { + filesystem::TmpDir dest; + Fetcher fetcher; + // add the key as trusted + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/complexdir-broken/subdir1/SHA1SUMS.key"), true); + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDigestedDir(OnMediaLocation("/complexdir-broken"), true); + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), FileCheckException); + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(fetcher_enqueuebrokendir_noindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key but with a broken file + { + filesystem::TmpDir dest; + Fetcher fetcher; + // add the key as trusted + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/complexdir-broken/subdir1/SHA1SUMS.key"), true); + fetcher.enqueueDir(OnMediaLocation("/complexdir-broken"), true); + // this should not throw as we provided no indexes and the + // enqueue is not digested + fetcher.start( dest.path(), media ); + fetcher.reset(); + + BOOST_CHECK( PathInfo(dest.path() + "/complexdir-broken/subdir2").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir-broken/subdir2/subdir2-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir-broken/subdir1/subdir1-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir-broken/subdir1/subdir1-file2.txt").isExist() ); + + } +} + +BOOST_AUTO_TEST_CASE(fetcher_enqueuebrokendir_index) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key but with a broken file + { + filesystem::TmpDir dest; + Fetcher fetcher; + // add the key as trusted + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/complexdir-broken/subdir1/SHA1SUMS.key"), true); + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDir(OnMediaLocation("/complexdir-broken"), true); + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), Exception); + fetcher.reset(); + } +} + + +BOOST_AUTO_TEST_CASE(fetcher_enqueue_digesteddir_brokendir_with_index) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key but with a broken file + { + filesystem::TmpDir dest; + Fetcher fetcher; + // add the key as trusted + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/complexdir-broken/subdir1/SHA1SUMS.key"), true); + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDigestedDir(OnMediaLocation("/complexdir-broken"), true); + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), Exception); + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(fetcher_enqueue_digested_broken_with_autoindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key but with a broken file + { + filesystem::TmpDir dest; + Fetcher fetcher; + // add the key as trusted + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/complexdir-broken/subdir1/SHA1SUMS.key"), true); + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDigested(OnMediaLocation("/complexdir-broken/subdir1/subdir1-file2.txt")); + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), Exception); + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(fetcher_enqueue_digested_with_autoindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + // do the test by trusting the SHA1SUMS file signature key with a good file + // checksum in auto discovered index + { + filesystem::TmpDir dest; + Fetcher fetcher; + // add the key as trusted + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/complexdir/subdir1/SHA1SUMS.key"), true); + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDigested(OnMediaLocation("/complexdir/subdir1/subdir1-file1.txt")); + fetcher.start( dest.path(), media ); + fetcher.reset(); + } +} + + +BOOST_AUTO_TEST_CASE(fetcher_enqueuefile_noindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + { + filesystem::TmpDir dest; + Fetcher fetcher; + fetcher.enqueue(OnMediaLocation("/file-1.txt")); + fetcher.start( dest.path(), media ); + BOOST_CHECK( PathInfo(dest.path() + "/file-1.txt").isExist() ); + } + + //MIL << fetcher; +} + +BOOST_AUTO_TEST_CASE(fetcher_simple) +{ + MediaSetAccess media( (DATADIR).asUrl(), "/" ); + Fetcher fetcher; + + { + filesystem::TmpDir dest; + OnMediaLocation loc("/complexdir/subdir1/subdir1-file1.txt"); + loc.setChecksum(CheckSum::sha1("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15")); + fetcher.enqueueDigested(loc); + fetcher.start(dest.path(), media); + fetcher.reset(); + // now we break the checksum and it should fail + loc.setChecksum(CheckSum::sha1("f1d2d2f924e986ac86fdf7b36c94bcdf32beec16")); + fetcher.enqueueDigested(loc); + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), Exception); + fetcher.reset(); + + } +} + +BOOST_AUTO_TEST_CASE(content_index) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + Fetcher fetcher; + + // test transfering one file by setting the index + { + filesystem::TmpDir dest; + OnMediaLocation loc("/contentindex/subdir1/subdir1-file1.txt"); + // trust the key manually + getZYpp()->keyRing()->importKey(PublicKey(DATADIR + "/contentindex/content.key"), true); + fetcher.addIndex(OnMediaLocation("/contentindex/content", 1)); + fetcher.enqueue(loc); + fetcher.start(dest.path(), media); + fetcher.reset(); + BOOST_CHECK( PathInfo(dest.path() + "/contentindex/subdir1/subdir1-file1.txt").isExist() ); + } + +} + +BOOST_AUTO_TEST_CASE(enqueue_broken_content_index) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + Fetcher fetcher; + filesystem::TmpDir dest; + { + OnMediaLocation loc("/contentindex-broken-digest/subdir1/subdir1-file1.txt",1); + // key was already imported as trusted + fetcher.addIndex(OnMediaLocation("/contentindex-broken-digest/content", 1)); + fetcher.enqueue(loc); + fetcher.start(dest.path(), media); + fetcher.reset(); + BOOST_CHECK( PathInfo(dest.path() + "/contentindex-broken-digest/subdir1/subdir1-file1.txt").isExist() ); + + // now retrieve a file that is modified, so the checksum has to fail + loc = OnMediaLocation("/contentindex-broken-digest/subdir1/subdir1-file2.txt",1); + fetcher.addIndex(OnMediaLocation("/contentindex-broken-digest/content", 1)); + fetcher.enqueue(loc); + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), Exception); + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(enqueue_digested_images_file_content_autoindex) +{ + MediaSetAccess media( ( DATADIR + "/images-file").asUrl(), "/" ); + Fetcher fetcher; + filesystem::TmpDir dest; + { + OnMediaLocation loc("/images/images.xml",1); + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDigested(loc); + fetcher.start(dest.path(), media); + fetcher.reset(); + BOOST_CHECK( PathInfo(dest.path() + "/images/images.xml").isExist() ); + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(enqueue_digested_images_file_content_autoindex_unsigned) +{ + MediaSetAccess media( ( DATADIR + "/images-file-unsigned").asUrl(), "/" ); + Fetcher fetcher; + filesystem::TmpDir dest; + { + OnMediaLocation loc("/images/images.xml",1); + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDigested(loc); + // it should throw because unsigned file throws + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), FileCheckException); + fetcher.reset(); + // the target file was NOT transferred + BOOST_CHECK( ! PathInfo(dest.path() + "/images/images.xml").isExist() ); + fetcher.reset(); + } +} + +BOOST_AUTO_TEST_CASE(enqueue_broken_content_noindex) +{ + MediaSetAccess media( ( DATADIR).asUrl(), "/" ); + Fetcher fetcher; + + { + filesystem::TmpDir dest; + OnMediaLocation loc("/contentindex-broken-digest/subdir1/subdir1-file1.txt",1); + // key was already imported as trusted + fetcher.enqueue(loc); + fetcher.start(dest.path(), media); + fetcher.reset(); + // now retrieve a file that is modified, so the checksum has to fail + loc = OnMediaLocation("/contentindex-broken-digest/subdir1/subdir1-file2.txt",1); + fetcher.enqueue(loc); + fetcher.start( dest.path(), media ); + fetcher.reset(); + BOOST_CHECK( PathInfo(dest.path() + "/contentindex-broken-digest/subdir1/subdir1-file2.txt").isExist() ); + + } +} + + +BOOST_AUTO_TEST_CASE(enqueuedir_http) +{ + WebServer web((Pathname(TESTS_SRC_DIR) + "/zypp/data/Fetcher/remote-site").c_str(), 10001); + BOOST_REQUIRE( web.start() ); + + // at this point the key is already trusted + { + MediaSetAccess media( web.url(), "/" ); + Fetcher fetcher; + filesystem::TmpDir dest; + + // auto add the SHA1SUMS + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDir(OnMediaLocation("/complexdir"), true); + fetcher.start( dest.path(), media ); + + fetcher.reset(); + + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir2").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir2/subdir2-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file1.txt").isExist() ); + BOOST_CHECK( PathInfo(dest.path() + "/complexdir/subdir1/subdir1-file2.txt").isExist() ); + } + + // test broken tree + { + MediaSetAccess media( web.url(), "/" ); + Fetcher fetcher; + filesystem::TmpDir dest; + + // auto add the SHA1SUMS + fetcher.setOptions( Fetcher::AutoAddIndexes ); + fetcher.enqueueDir(OnMediaLocation("/complexdir-broken"), true); + // should throw because wrong checksum + BOOST_CHECK_THROW( fetcher.start( dest.path(), media ), FileCheckException); + fetcher.reset(); + + BOOST_CHECK( PathInfo(dest.path() + "/complexdir-broken/subdir2").isExist() ); + + // unprocessed after failure: + BOOST_CHECK( ! PathInfo(dest.path() + "/complexdir-broken/subdir2/subdir2-file1.txt").isExist() ); + + // this one got transferred before the failure, so it is there + BOOST_CHECK( PathInfo(dest.path() + "/complexdir-broken/subdir1/subdir1-file1.txt").isExist() ); + // broken: + BOOST_CHECK( ! PathInfo(dest.path() + "/complexdir-broken/subdir1/subdir1-file2.txt").isExist() ); + + fetcher.reset(); + } + + web.stop(); +} + +BOOST_AUTO_TEST_SUITE_END(); + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/zypp/FileChecker_test.cc b/tests/zypp/FileChecker_test.cc new file mode 100644 index 0000000..3867bcb --- /dev/null +++ b/tests/zypp/FileChecker_test.cc @@ -0,0 +1,89 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include "KeyRingTestReceiver.h" + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::filesystem; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/data/FileChecker") + +BOOST_AUTO_TEST_CASE(keyring_test) +{ + Pathname file( Pathname(DATADIR) + "hello.txt" ); + Pathname file2( Pathname(DATADIR) + "hello2.txt" ); + Pathname pubkey( Pathname(DATADIR) + "hello.txt.key" ); + Pathname signature( Pathname(DATADIR) + "hello.txt.asc" ); + + /** + * 1st scenario, the signature does + * match + */ + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + SignatureFileChecker sigchecker( signature ); + sigchecker.addPublicKey(pubkey); + sigchecker(file); + } + + /** + * second scenario, the signature does not + * match, an exception has to be thrown + */ + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + SignatureFileChecker sigchecker( signature ); + sigchecker.addPublicKey(pubkey); + + BOOST_CHECK_THROW( sigchecker(file2), zypp::Exception ); + + } + +} + +BOOST_AUTO_TEST_CASE(checksum_test) +{ + Pathname file( Pathname(DATADIR) + "hello.txt" ); + Pathname file2( Pathname(DATADIR) + "hello2.txt" ); + Pathname pubkey( Pathname(DATADIR) + "hello.txt.key" ); + Pathname signature( Pathname(DATADIR) + "hello.txt.asc" ); + + /** + * 1st scenario, checksum matches + */ + { + ChecksumFileChecker checker( CheckSum("sha1", "f2105202a0f017ab818b670d04982a89f55f090b") ); + checker(file); + } + + /** + * 1st scenario, checksum does not matches + */ + { + ChecksumFileChecker checker( CheckSum("sha1", "f2105202a0f017ab818b670d04982a89f55f090b") ); + BOOST_CHECK_THROW( checker(file2), zypp::FileCheckException ); + } +} + diff --git a/tests/zypp/Flags_test.cc b/tests/zypp/Flags_test.cc new file mode 100644 index 0000000..91293c6 --- /dev/null +++ b/tests/zypp/Flags_test.cc @@ -0,0 +1,92 @@ +// +// tests for Flags +// +#include +#include +#include +#include + +using boost::unit_test::test_case; +using std::cout; +using std::endl; +using namespace zypp; + +enum class E +{ + _0 = 0, + _1 = 1 << 0, + _2 = 1 << 1, + _3 = _2 | _1, + _4 = 1 << 2, + _5 = _4 | _1, + _8 = 1 << 3, +}; + +ZYPP_DECLARE_FLAGS( TFlags, E ); +ZYPP_DECLARE_OPERATORS_FOR_FLAGS( TFlags ); + +inline std::ostream & operator<<( std::ostream & str, const E & obj ) +{ return str << TFlags(obj); } + +static const TFlags T_6( E::_4 | E::_2 ); +static const TFlags T_7( E::_4 | E::_2 | E::_1 ); + + +BOOST_AUTO_TEST_CASE(flags) +{ + TFlags t0; + BOOST_CHECK_EQUAL( t0, 0 ); + BOOST_CHECK_EQUAL( E::_0, t0 ); + BOOST_CHECK_EQUAL( t0, E::_0 ); + BOOST_CHECK_EQUAL( t0, TFlags(0) ); + BOOST_CHECK_EQUAL( ~t0, ~0 ); + BOOST_CHECK_EQUAL( ~~t0, 0 ); + BOOST_CHECK_EQUAL( ~t0, ~E::_0 ); + BOOST_CHECK_EQUAL( ~~t0, E::_0 ); + + BOOST_CHECK_EQUAL( TFlags::none(), TFlags(0) ); + BOOST_CHECK_EQUAL( TFlags::all(), ~TFlags(0) ); + + TFlags t1( E::_1 ); + BOOST_CHECK_EQUAL( t1, 1 ); + BOOST_CHECK_EQUAL( t1, E::_1 ); + BOOST_CHECK_EQUAL( t1, TFlags(1) ); + + TFlags t; + //t = 1; // must not compile: assign from int_type + t = E::_2; // = enum + BOOST_CHECK_EQUAL( t, E::_2 ); + t = T_6; // = TFlags + BOOST_CHECK_EQUAL( t, T_6 ); + + // enum op enum + t = ~E::_1; BOOST_CHECK_EQUAL( ~t, E::_1 ); + t = E::_1 & E::_2; BOOST_CHECK_EQUAL( t, E::_0 ); + t = E::_1 | E::_2; BOOST_CHECK_EQUAL( t, E::_3 ); + t = E::_1 ^ E::_2; BOOST_CHECK_EQUAL( t, E::_3 ); + + // enum op TFlags + t = E::_2 & T_6; BOOST_CHECK_EQUAL( t, E::_2 ); + t = E::_2 | T_6; BOOST_CHECK_EQUAL( t, T_6 ); + t = E::_2 ^ T_6; BOOST_CHECK_EQUAL( t, E::_4 ); + + // TFlags op enum + t = ~T_7; BOOST_CHECK_EQUAL( ~t, T_7 ); + t = T_7 & E::_2; BOOST_CHECK_EQUAL( t, E::_2 ); + t = T_7 | E::_2; BOOST_CHECK_EQUAL( t, T_7 ); + t = T_7 ^ E::_2; BOOST_CHECK_EQUAL( t, E::_5 ); + + // TFlags op TFlags + t = T_7 & T_6; BOOST_CHECK_EQUAL( t, T_6 ); + t = T_7 | T_6; BOOST_CHECK_EQUAL( t, T_7 ); + t = T_7 ^ T_7; BOOST_CHECK_EQUAL( t, E::_0 ); + + t = E::_3; + BOOST_CHECK( ! t.testFlag( E::_0 ) ); // fails as t != 0 + BOOST_CHECK( t.testFlag( E::_1 ) ); + BOOST_CHECK( t.testFlag( E::_2 ) ); + BOOST_CHECK( t.testFlag( E::_3 ) ); + t.unsetFlag( E::_2 ); BOOST_CHECK( t.testFlag( E::_1 ) ); + t.setFlag( E::_1, false ); BOOST_CHECK( t.testFlag( E::_0 ) ); // succeed as t == 0 + t.setFlag( E::_3, true ); BOOST_CHECK( t.testFlag( E::_3 ) ); +} diff --git a/tests/zypp/GZStream_test.cc b/tests/zypp/GZStream_test.cc new file mode 100644 index 0000000..0f33b88 --- /dev/null +++ b/tests/zypp/GZStream_test.cc @@ -0,0 +1,80 @@ +// Boost.Test +#include + +#include +#include +#include + +BOOST_AUTO_TEST_CASE(gz_simple_read_write) +{ + const zypp::Pathname file = zypp::Pathname(TESTS_BUILD_DIR) / "test.gz"; + const std::string testString("HelloWorld"); + + { + zypp::ofgzstream strOut( file.c_str() ); + BOOST_REQUIRE ( strOut.is_open() ); + BOOST_REQUIRE ( !strOut.fail() ); + BOOST_REQUIRE ( strOut.getbuf().canWrite() ); + BOOST_REQUIRE ( !strOut.getbuf().canRead() ); + strOut << testString; + BOOST_REQUIRE ( !strOut.fail() ); + } + + { + std::string test; + zypp::ifgzstream str( file.c_str() ); + BOOST_REQUIRE ( str.is_open() ); + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE ( !str.getbuf().canWrite() ); + BOOST_REQUIRE ( str.getbuf().canRead() ); + str >> test; + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE_EQUAL( test, testString ); + } + + { + zypp::InputStream iStr( file ); + BOOST_REQUIRE( typeid( iStr.stream() ) == typeid( zypp::ifgzstream& ) ); + } +} + +BOOST_AUTO_TEST_CASE(gz_seek) +{ + const zypp::Pathname file = zypp::Pathname(TESTS_BUILD_DIR) / "testseek.gz"; + const std::string testString("Hello World!\nLet's see if seeking works!"); + + { + zypp::ofgzstream strOut( file.c_str() ); + BOOST_REQUIRE( strOut.is_open() ); + strOut << testString; + } + + //gzseek only supports SEEK_SET (beg) and SEEK_CUR (cur), SEEK_END (end) is not supported + { + std::string test; + zypp::ifgzstream str( file.c_str() ); + str.seekg( 6, std::ios_base::beg ); + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE_EQUAL( str.tellg(), 6 ); + str >> test; + BOOST_REQUIRE_EQUAL( test, "World!" ); + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE_EQUAL( str.tellg(), 12 ); + + str.seekg( 7, std::ios_base::cur ); + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE_EQUAL( str.tellg(), 19 ); + str >> test; + BOOST_REQUIRE_EQUAL( test, "see" ); + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE_EQUAL( str.tellg(), 22 ); + + str.seekg( 0, std::ios_base::beg ); + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE_EQUAL( str.tellg(), 0 ); + str >> test; + BOOST_REQUIRE ( !str.fail() ); + BOOST_REQUIRE_EQUAL( str.tellg(), 5 ); + BOOST_REQUIRE_EQUAL( test, "Hello" ); + } +} diff --git a/tests/zypp/InstanceId_test.cc b/tests/zypp/InstanceId_test.cc new file mode 100644 index 0000000..553d7dc --- /dev/null +++ b/tests/zypp/InstanceId_test.cc @@ -0,0 +1,46 @@ +#include "TestSetup.h" +#include + +#define BOOST_TEST_MODULE InstanceId + +///////////////////////////////////////////////////////////////////////////// +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + + // Abuse;) vbox as System repo: + test.loadTargetRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" ); + test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" ); + test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "zyppsvn" ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); +///////////////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(default_constructed) +{ + InstanceId instanceId; + BOOST_CHECK_EQUAL( instanceId.getNamespace(), std::string() ); + + BOOST_CHECK_EQUAL( instanceId.isSystemId( "System" ), false ); + BOOST_CHECK_EQUAL( instanceId.isSystemId( "@System" ), true ); + + BOOST_CHECK_EQUAL( instanceId(""), PoolItem() ); + BOOST_CHECK_EQUAL( instanceId(PoolItem()), "" ); +} + +BOOST_AUTO_TEST_CASE(convert) +{ + InstanceId instanceId; + instanceId.setNamespace( "SUSE" ); + BOOST_CHECK_EQUAL( instanceId.getNamespace(), "SUSE" ); + + ResPool pool( ResPool::instance() ); + for_( it, pool.begin(), pool.end() ) + { + std::cout << instanceId(*it) << endl; + BOOST_CHECK_EQUAL( instanceId(instanceId(*it)), *it ); + } +} diff --git a/tests/zypp/KeyRingTestReceiver.h b/tests/zypp/KeyRingTestReceiver.h new file mode 100644 index 0000000..17e7572 --- /dev/null +++ b/tests/zypp/KeyRingTestReceiver.h @@ -0,0 +1,142 @@ + +#ifndef ZYPP_KEYRING_TEST_RECEIVER_H +#define ZYPP_KEYRING_TEST_RECEIVER_H + +#include +#include +#include +#include + +/** + * Keyring Callback Receiver with some features + * Allows to simulate and configure user answer + * Can record which callbacks were called + */ +struct KeyRingTestReceiver : public zypp::callback::ReceiveReport +{ + KeyRingTestReceiver() + { + reset(); + connect(); + } + + void reset() + { + _answer_accept_unknown_key = false; + _answer_accept_key = KeyRingReport::KEY_DONT_TRUST; + _answer_ver_failed = false; + _answer_accept_unsigned_file = false; + _asked_user_to_accept_unknown_key = false; + _asked_user_to_accept_key = false; + _asked_user_to_accept_ver_failed = false; + _asked_user_to_accept_unsigned_file = false; + } + + ~KeyRingTestReceiver() + { + disconnect(); + } + + void answerAcceptVerFailed( bool answer ) + { _answer_ver_failed = answer; } + + bool askedAcceptVerFailed() const + { return _asked_user_to_accept_ver_failed; } + + void answerAcceptUnknownKey( bool answer ) + { _answer_accept_unknown_key = answer; } + + bool askedAcceptUnknownKey() const + { return _asked_user_to_accept_unknown_key; } + + void answerAcceptKey( KeyRingReport::KeyTrust answer ) + { _answer_accept_key = answer; } + + bool askedAcceptKey() const + { return _asked_user_to_accept_key; } + + void answerAcceptUnsignedFile( bool answer ) + { _answer_accept_unsigned_file = answer; } + + bool askedAcceptUnsignedFile() const + { return _asked_user_to_accept_unsigned_file; } + + virtual bool askUserToAcceptUnsignedFile( const std::string &file, const zypp::KeyContext &keycontext ) + { + MIL << std::endl; + _asked_user_to_accept_unsigned_file = true; + return _answer_accept_unsigned_file; + } + + virtual bool askUserToAcceptUnknownKey( const std::string &file, const std::string &id, const zypp::KeyContext &keycontext ) + { + MIL << std::endl; + _asked_user_to_accept_unknown_key = true; + return _answer_accept_unknown_key; + } + + virtual KeyRingReport::KeyTrust askUserToAcceptKey( const zypp::PublicKey &key, const zypp::KeyContext &keycontext ) + { + MIL << std::endl; + _asked_user_to_accept_key = true; + return _answer_accept_key; + } + + virtual bool askUserToAcceptVerificationFailed( const std::string &file, const zypp::PublicKey &key, const zypp::KeyContext &keycontext ) + { + MIL << std::endl; + _asked_user_to_accept_ver_failed = true; + return _answer_ver_failed; + } + + // how to answer + bool _answer_accept_unknown_key; + KeyRingReport::KeyTrust _answer_accept_key; + bool _answer_ver_failed; + bool _answer_accept_unsigned_file; + + // we use this variables to check that the + // callbacks were called + bool _asked_user_to_accept_unknown_key; + bool _asked_user_to_accept_key; + bool _asked_user_to_accept_ver_failed; + bool _asked_user_to_accept_unsigned_file; +}; + +/** + * Keyring Signal Receiver with some features + * Allows to simulate and configure user answer + * Can record which callbacks were called + */ +struct KeyRingTestSignalReceiver : zypp::callback::ReceiveReport +{ + KeyRingTestSignalReceiver(/*RpmDb &rpmdb*/) + : _trusted_key_added_called(false) + { + MIL << "KeyRing signals enabled" << std::endl; + connect(); + } + + ~KeyRingTestSignalReceiver() + { + disconnect(); + } + + virtual void trustedKeyAdded( const zypp::PublicKey &key ) + { + MIL << "TEST: trusted key added to zypp Keyring. Synchronizing keys with fake rpm keyring" << std::endl; + _trusted_key_added_called = true; + //std::cout << "trusted key added to zypp Keyring. Synchronizing keys with rpm keyring" << std::endl; + //_rpmdb.importZyppKeyRingTrustedKeys(); + //_rpmdb.exportTrustedKeysInZyppKeyRing(); + } + + virtual void trustedKeyRemoved( const zypp::PublicKey &key ) + { + } + + bool _trusted_key_added_called; + +}; + +#endif diff --git a/tests/zypp/KeyRing_test.cc b/tests/zypp/KeyRing_test.cc new file mode 100644 index 0000000..a0e141c --- /dev/null +++ b/tests/zypp/KeyRing_test.cc @@ -0,0 +1,318 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include "KeyRingTestReceiver.h" +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::filesystem; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/data/KeyRing") + +bool verifyFileSignatureWorkflow( KeyRing_Ptr ring, const Pathname &file, const std::string &filedesc, const Pathname &signature, bool & sigValid_r, const KeyContext &keycontext = KeyContext()) +{ + sigValid_r = false; // just in case.... + keyring::VerifyFileContext context( file, signature ); + context.shortFile( filedesc ); + context.keyContext( keycontext ); + const auto &res = zyppng::KeyRingWorkflow::verifyFileSignature( zyppng::SyncContext::create(), ring, std::move(context) ); + sigValid_r = res.second.fileValidated(); + return res.second.fileAccepted(); +} + +bool verifyFileSignatureWorkflow( KeyRing_Ptr ring, const Pathname &file, const std::string filedesc, const Pathname &signature, const KeyContext &keycontext = KeyContext()) +{ + keyring::VerifyFileContext context( file, signature ); + context.shortFile( filedesc ); + context.keyContext( keycontext ); + const auto &res = zyppng::KeyRingWorkflow::verifyFileSignature( zyppng::SyncContext::create(), ring, std::move(context) ); + return res.second.fileAccepted(); +} + + +BOOST_AUTO_TEST_CASE(keyring_test) +{ + PublicKey key( Pathname(DATADIR) + "public.asc" ); + + /** + * scenario #1 + * import a not trusted key + * ask for accept, answer yes 'temporarily' + */ + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + // base sandbox for playing + TmpDir tmp_dir; + KeyRing_Ptr keyring = new KeyRing( tmp_dir.path() ); + + BOOST_CHECK_EQUAL( keyring->publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring->trustedPublicKeys().size(), (unsigned) 0 ); + + keyring->importKey( key, false ); + + BOOST_CHECK_EQUAL( keyring->publicKeys().size(), (unsigned) 1 ); + BOOST_CHECK_EQUAL( keyring->trustedPublicKeys().size(), (unsigned) 0 ); + + BOOST_CHECK_MESSAGE( keyring->isKeyKnown( key.id() ), "Imported untrusted key should be known"); + BOOST_CHECK_MESSAGE( ! keyring->isKeyTrusted( key.id() ), "Imported untrusted key should be untrusted"); + + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + bool to_continue = verifyFileSignatureWorkflow( keyring, DATADIR + "repomd.xml", "Blah Blah", DATADIR + "repomd.xml.asc"); + + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known"); + BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptKey(), "Verify Signature Workflow with only 1 untrusted key should ask user wether to trust and/or import"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptVerFailed(), "The signature validates"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnsignedFile(), "It is a signed file, so dont ask the opposite"); + + BOOST_CHECK_MESSAGE( to_continue, "We did not import, but we trusted and signature validates."); + } + + /** + * scenario #1.1 + * import a not trusted key + * ask to accept, answer yes 'temporarily' + * vorrupt the file and check + */ + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + // base sandbox for playing + TmpDir tmp_dir; + KeyRing_Ptr keyring = new KeyRing ( tmp_dir.path() ); + + BOOST_CHECK_EQUAL( keyring->publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring->trustedPublicKeys().size(), (unsigned) 0 ); + + keyring->importKey( key, false ); + + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + + // now we will recheck with a corrupted file + bool to_continue = verifyFileSignatureWorkflow( keyring, DATADIR + "repomd.xml.corrupted", "Blah Blah", DATADIR + "repomd.xml.asc"); + + // check wether the user got the right questions + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known"); + BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptKey(), "Verify Signature Workflow with only 1 untrusted key should ask user wether to trust and/or import"); + BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptVerFailed(), "The signature does not validates"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnsignedFile(), "It is a signed file, so dont ask the opposite"); + + BOOST_CHECK_MESSAGE( ! to_continue, "We did not continue with a corrupted file"); + } + + /** + * scenario #1.2 + * import a not trusted key + * ask for trust, answer yes + * ask for import, answer no + * check without signature + */ + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + // base sandbox for playing + TmpDir tmp_dir; + KeyRing_Ptr keyring = new KeyRing ( tmp_dir.path() ); + + keyring->importKey( key, false ); + + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + // now we will recheck with a unsigned file + bool to_continue = verifyFileSignatureWorkflow( keyring, DATADIR + "repomd.xml", "Blah Blah", Pathname() ); + + // check wether the user got the right questions + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptKey(), "No signature, no key to trust"); + BOOST_CHECK_MESSAGE( keyring_callbacks.askedAcceptUnsignedFile(), "Ask the user wether to accept an unsigned file"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptVerFailed(), "There is no signature to verify"); + + BOOST_CHECK_MESSAGE( ! to_continue, "We did not continue with a unsigned file"); + } + + /** scenario #2 + * empty keyring + * should ask for unknown key + * answer no + */ + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + // base sandbox for playing + TmpDir tmp_dir; + KeyRing_Ptr keyring = new KeyRing( tmp_dir.path() ); + + BOOST_CHECK_MESSAGE( ! keyring->isKeyKnown( key.id() ), "empty keyring has not known keys"); + + //keyring_callbacks.answerAcceptUnknownKey(true); + bool to_continue = verifyFileSignatureWorkflow( keyring, DATADIR + "repomd.xml", "Blah Blah", DATADIR + "repomd.xml.asc"); + BOOST_CHECK_MESSAGE(keyring_callbacks.askedAcceptUnknownKey(), "Should ask to accept unknown key, empty keyring"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptKey(), "Unknown key cant be trusted"); + BOOST_CHECK_MESSAGE( ! to_continue, "We answered no to accept unknown key"); + } + + /** scenario #3 + * import trusted key + * should ask nothing + * should emit signal + */ + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + // base sandbox for playing + TmpDir tmp_dir; + KeyRing_Ptr keyring = new KeyRing( tmp_dir.path() ); + + BOOST_CHECK_EQUAL( keyring->publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring->trustedPublicKeys().size(), (unsigned) 0 ); + + keyring->importKey( key, true ); + + BOOST_CHECK_EQUAL( receiver._trusted_key_added_called, true ); + + BOOST_CHECK_EQUAL( keyring->publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring->trustedPublicKeys().size(), (unsigned) 1 ); + + BOOST_CHECK_MESSAGE( keyring->isKeyKnown( key.id() ), "Imported trusted key should be known"); + BOOST_CHECK_MESSAGE( keyring->isKeyTrusted( key.id() ), "Imported trusted key should be trusted"); + + bool to_continue = verifyFileSignatureWorkflow( keyring, DATADIR + "repomd.xml", "Blah Blah", DATADIR + "repomd.xml.asc"); + + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnknownKey(), "Should not ask for unknown key, it was known"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptKey(), "Verify Signature Workflow with only 1 untrusted key should ask user wether to trust and/or import"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptVerFailed(), "The signature validates"); + BOOST_CHECK_MESSAGE( ! keyring_callbacks.askedAcceptUnsignedFile(), "It is a signed file, so dont ask the opposite"); + + BOOST_CHECK_MESSAGE( to_continue, "We did not import, but we trusted and signature validates."); + } + //keyring.importKey( key, true ); + //BOOST_CHECK_EQUAL( receiver._trusted_key_added_called, true ); + //BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), 1 ); + + /* check signature id can be extracted */ + +} + +BOOST_AUTO_TEST_CASE(signature_test) +{ + PublicKey key( DATADIR + "public.asc" ); + + { + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + // base sandbox for playing + TmpDir tmp_dir; + KeyRing keyring( tmp_dir.path() ); + + BOOST_CHECK_EQUAL( keyring.readSignatureKeyId( DATADIR + "repomd.xml.asc" ), "BD61D89BD98821BE" ); + BOOST_CHECK_THROW( keyring.readSignatureKeyId(Pathname()), Exception ); + TmpFile tmp; + BOOST_CHECK_EQUAL( keyring.readSignatureKeyId(tmp.path()), "" ); + + keyring.importKey(key); + + BOOST_CHECK(keyring.verifyFileSignature( DATADIR + "repomd.xml", DATADIR + "repomd.xml.asc")); + BOOST_CHECK( ! keyring.verifyFileSignature( DATADIR + "repomd.xml.corrupted", DATADIR + "repomd.xml.asc")); + } +} + +BOOST_AUTO_TEST_CASE(keyring_import) +{ + // base sandbox for playing + TmpDir tmp_dir; + KeyRing keyring( tmp_dir.path() ); + struct Receiver: public callback::ReceiveReport + { + Receiver() + { connect(); } + + virtual void trustedKeyAdded( const PublicKey & key_r ) + { ++_cbcnt; } + + virtual void trustedKeyRemoved( const PublicKey & key_r ) + { --_cbcnt; } + + unsigned _cbcnt = 0; + } receiver; + + /////////////////////////////////////////////////////////////////// + // Make sure we get a proper callback notification if multiple + // keys are imported at once. + /////////////////////////////////////////////////////////////////// + PublicKey key( DATADIR + "installkey.gpg" ); + BOOST_CHECK_EQUAL( key.hiddenKeys().size(), 2 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), 0 ); + keyring.importKey( key, true ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), 3 ); + BOOST_CHECK_EQUAL( receiver._cbcnt, keyring.trustedPublicKeys().size() ); +} + +BOOST_AUTO_TEST_CASE(keyring_delete) +{ + PublicKey key( Pathname(DATADIR) + "public.asc" ); + /** scenario #3 + * import and delete untrusted key + */ + { + // base sandbox for playing + TmpDir tmp_dir; + KeyRing keyring( tmp_dir.path() ); + + BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 ); + + keyring.importKey( key, false ); + + BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 1 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 ); + + keyring.deleteKey( key.id(), false); + + BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 ); + } + + /** scenario #3.1 + * import and delete trusted key + */ + { + // base sandbox for playing + TmpDir tmp_dir; + KeyRing keyring( tmp_dir.path() ); + + BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 ); + + keyring.importKey( key, true ); + + BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 1 ); + + //try to delete from untrusted keyring + keyring.deleteKey( key.id(), false); + + BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 1 ); + + keyring.deleteKey( key.id(), true); + + BOOST_CHECK_EQUAL( keyring.publicKeys().size(), (unsigned) 0 ); + BOOST_CHECK_EQUAL( keyring.trustedPublicKeys().size(), (unsigned) 0 ); + } +} + diff --git a/tests/zypp/Locale_test.cc b/tests/zypp/Locale_test.cc new file mode 100644 index 0000000..576892a --- /dev/null +++ b/tests/zypp/Locale_test.cc @@ -0,0 +1,173 @@ +#include +#include +#include + +#include + +#define BOOST_TEST_MODULE Locale + +using std::cout; +using std::endl; + +using namespace zypp; +using namespace boost::unit_test; + +BOOST_AUTO_TEST_CASE(static_deps) +{ + setenv( "LANG", "C", 1 ); + + // static vars initialization sequence: Locale depends on LanguageCode + BOOST_CHECK_EQUAL( LanguageCode::enCode.code(), "en" ); + BOOST_CHECK_EQUAL( IdString(Locale::enCode), IdString(LanguageCode::enCode) ); + + // solver communication: Both must lead to the same ID + BOOST_CHECK_EQUAL( Locale::enCode.id(), IdString(LanguageCode::enCode.code()).id() ); +} + +// +// NOTE: In checks testing for empty codes (IdString::Null/IdString::Empty) +// explicitly use the ID, because both share the same string representation. +// +// This way you get "failed [1 != 0]" rather than "failed [ != ]" +// + +BOOST_AUTO_TEST_CASE(no_codes) +{ + // IdString::Null is probably a rare case + BOOST_CHECK_EQUAL( LanguageCode(nullptr).id(), IdString::Null.id() ); + BOOST_CHECK_EQUAL( CountryCode(nullptr).id(), IdString::Null.id() ); + BOOST_CHECK_EQUAL( Locale(nullptr).id(), IdString::Null.id() ); + BOOST_CHECK_EQUAL( Locale(nullptr).language().id(), IdString::Null.id() ); + BOOST_CHECK_EQUAL( Locale(nullptr).country().id(), IdString::Null.id() ); + + // IdString::Null is the ususal noCode + BOOST_CHECK_EQUAL( LanguageCode::noCode.id(), LanguageCode().id() ); + BOOST_CHECK_EQUAL( LanguageCode::noCode.id(), LanguageCode("").id() ); + BOOST_CHECK_EQUAL( LanguageCode::noCode.id(), IdString::Empty.id() ); + + BOOST_CHECK_EQUAL( CountryCode::noCode.id(), CountryCode().id() ); + BOOST_CHECK_EQUAL( CountryCode::noCode.id(), CountryCode("").id() ); + BOOST_CHECK_EQUAL( CountryCode::noCode.id(), IdString::Empty.id() ); + + BOOST_CHECK_EQUAL( Locale::noCode.id(), Locale().id() ); + BOOST_CHECK_EQUAL( Locale::noCode.id(), Locale("").id() ); + BOOST_CHECK_EQUAL( Locale::noCode.id(), IdString::Empty.id() ); + BOOST_CHECK_EQUAL( Locale::noCode.language().id(), LanguageCode::noCode.id() ); + BOOST_CHECK_EQUAL( Locale::noCode.country().id(), CountryCode::noCode.id() ); + + // + const char * nc = "No Code"; + BOOST_CHECK_EQUAL( LanguageCode(nullptr).name(), nc ); + BOOST_CHECK_EQUAL( CountryCode(nullptr).name(), nc ); + BOOST_CHECK_EQUAL( Locale(nullptr).name(), nc ); + + BOOST_CHECK_EQUAL( LanguageCode::noCode.name(), nc ); + BOOST_CHECK_EQUAL( CountryCode::noCode.name(), nc ); + BOOST_CHECK_EQUAL( Locale::noCode.name(), nc ); + +} + +BOOST_AUTO_TEST_CASE(language_code) +{ + // language code: ger deu de, N_( "German" ) + std::string name( "German" ); + for ( const char * s : { "ger", "deu", "de" } ) + { + BOOST_CHECK_EQUAL( LanguageCode(s).code(), s ); + BOOST_CHECK_EQUAL( LanguageCode(s), IdString(s) ); + BOOST_CHECK_EQUAL( LanguageCode(s).id(), IdString(s).id() ); + + BOOST_CHECK_EQUAL( LanguageCode(s).name(), name ); + } + BOOST_CHECK( LanguageCode("de") < LanguageCode("deu") ); + BOOST_CHECK( LanguageCode("deu") < LanguageCode("ger") ); + + BOOST_CHECK_EQUAL( LanguageCode("XX"), IdString("XX") ); +} + +BOOST_AUTO_TEST_CASE(country_code) +{ + // country code: "DE", N_("Germany) + std::string name( "Germany" ); + for ( const char * s : { "DE" } ) + { + BOOST_CHECK_EQUAL( CountryCode(s).code(), s ); + BOOST_CHECK_EQUAL( CountryCode(s), IdString(s) ); + BOOST_CHECK_EQUAL( CountryCode(s).id(), IdString(s).id() ); + + BOOST_CHECK_EQUAL( CountryCode(s).name(), name ); + } + + BOOST_CHECK( CountryCode("AA") < CountryCode("DE") ); + + BOOST_CHECK_EQUAL( CountryCode("XX"), IdString("XX") ); +} + +BOOST_AUTO_TEST_CASE(locale) +{ + // IdString::Null (rare) + { + for ( const Locale & l : { Locale( nullptr ), Locale( LanguageCode(nullptr), CountryCode(nullptr) ) } ) + { + BOOST_CHECK_EQUAL( l.id(), IdString::Null.id() ); + BOOST_CHECK_EQUAL( l.language().id(), IdString::Null.id() ); + BOOST_CHECK_EQUAL( l.country().id(), IdString::Null.id() ); + BOOST_CHECK_EQUAL( bool(l), false ); + BOOST_CHECK_EQUAL( bool(l.language()), false ); + BOOST_CHECK_EQUAL( bool(l.country()), false ); + } + } + // Trailing garbage ([.@].*) is ignored + { + for ( const Locale & l : { Locale(), Locale( "" ), Locale( "@UTF-8" ), Locale( ".UTF-8" ) + , Locale( LanguageCode(), CountryCode(nullptr) ) + , Locale( LanguageCode(nullptr), CountryCode() ) + , Locale( LanguageCode(), CountryCode() ) } ) + { + BOOST_CHECK_EQUAL( l.id(), IdString::Empty.id() ); + BOOST_CHECK_EQUAL( l.language().id(), IdString::Empty.id() ); + BOOST_CHECK_EQUAL( l.country().id(), IdString::Empty.id() ); + BOOST_CHECK_EQUAL( bool(l), false ); + BOOST_CHECK_EQUAL( bool(l.language()), false ); + BOOST_CHECK_EQUAL( bool(l.country()), false ); + } + } + { + for ( const Locale & l : { Locale("de_DE"), Locale( "de_DE@UTF-8" ) + , Locale( LanguageCode("de"), CountryCode("DE") ) } ) + { + BOOST_CHECK_EQUAL( l, IdString("de_DE") ); + BOOST_CHECK_EQUAL( l.language(), IdString("de") ); + BOOST_CHECK_EQUAL( l.country(), IdString("DE") ); + BOOST_CHECK_EQUAL( bool(l), true ); + BOOST_CHECK_EQUAL( bool(l.language()), true ); + BOOST_CHECK_EQUAL( bool(l.country()), true ); + } + } + { + for ( const Locale & l : { Locale("de"), Locale( "de@UTF-8" ) + , Locale( LanguageCode("de") ) } ) + { + BOOST_CHECK_EQUAL( l.id(), l.language().id() ); + BOOST_CHECK_EQUAL( l.country().id(), IdString::Empty.id() ); + BOOST_CHECK_EQUAL( bool(l), true ); + BOOST_CHECK_EQUAL( bool(l.language()), true ); + BOOST_CHECK_EQUAL( bool(l.country()), false ); + } + } +} + +BOOST_AUTO_TEST_CASE(fallback) +{ + { // default fallback... + Locale l( "de_DE" ); + BOOST_CHECK_EQUAL( (l = l.fallback()), "de" ); + BOOST_CHECK_EQUAL( (l = l.fallback()), "en" ); + BOOST_CHECK_EQUAL( (l = l.fallback()), "" ); + } + { // special rules... + Locale l( "pt_BR" ); + BOOST_CHECK_EQUAL( (l = l.fallback()), "en" ); + BOOST_CHECK_EQUAL( (l = l.fallback()), "" ); + } +} diff --git a/tests/zypp/Locks_test.cc b/tests/zypp/Locks_test.cc new file mode 100644 index 0000000..69af3fc --- /dev/null +++ b/tests/zypp/Locks_test.cc @@ -0,0 +1,118 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "TestSetup.h" + +#define BOOST_TEST_MODULE Locks + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace boost::unit_test; + +bool isLocked( const sat::Solvable & solvable ) +{ + zypp::PoolItem pi( zypp::ResPool::instance().find( solvable ) ); + if( pi.status().isLocked() ) + return true; + return false; +} + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + //test.loadTarget(); // initialize and load target + test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" ); + test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "@System" ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +///////////////////////////////////////////////////////////////////////////// +// 0xx basic queries +///////////////////////////////////////////////////////////////////////////// + +// default query + one search string +// q.addString("foo"); +// result: all resolvables having at least one attribute matching foo +BOOST_AUTO_TEST_CASE(locks_1) +{ + cout << "****001****" << endl; + PoolQuery q; + q.addString("zypper"); + Locks::instance().addLock(q); + for_(it,q.begin(),q.end()) + { + BOOST_CHECK(isLocked(*it)); + } + Locks::instance().removeLock(q); //clear before next test +} + +BOOST_AUTO_TEST_CASE(locks_save_load) +{ + cout << "****save/load****" << endl; + Pathname src(TESTS_SRC_DIR); + src += "zypp/data/Locks/locks"; + Locks::instance().readAndApply(src); + PoolQuery q; + q.addString("zypper"); + for_(it,q.begin(),q.end()) + { + BOOST_CHECK(isLocked(*it)); + } +#if 1 + filesystem::TmpFile testfile; + //Pathname testfile(TESTS_SRC_DIR); + // testfile += "/zypp/data/Locks/testlocks"; + Locks::instance().removeLock(q); + Locks::instance().save(testfile); + Locks::instance().readAndApply(testfile); + //now unlocked + for_(it,q.begin(),q.end()) + { + BOOST_CHECK(!isLocked(*it)); + } + BOOST_CHECK(Locks::instance().size()==0); +#endif +} + +BOOST_AUTO_TEST_CASE(locks_save_without_redundancy) +{ + cout << "****save without redundancy****" << endl; + PoolQuery q; + q.addString("zypper"); + Locks& locks = Locks::instance(); + locks.addLock(q); + locks.addLock(q); + locks.merge(); + BOOST_CHECK( locks.size()==1 ); + locks.addLock(q); + locks.merge(); + BOOST_CHECK( locks.size()==1 ); + locks.removeLock(q); + locks.merge(); + BOOST_CHECK( locks.size() == 0 ); +} + +BOOST_AUTO_TEST_CASE( locks_empty ) +{ + cout << "****test and clear empty locks****" << endl; + PoolQuery q; + q.addString("foo-bar-nonexist"); + Locks& locks = Locks::instance(); + locks.addLock(q); + locks.merge(); //only need merge list + BOOST_CHECK( locks.existEmpty() ); + locks.removeEmpty(); + BOOST_CHECK( locks.size() == 0 ); +} diff --git a/tests/zypp/MediaSetAccess_test.cc b/tests/zypp/MediaSetAccess_test.cc new file mode 100644 index 0000000..abdba27 --- /dev/null +++ b/tests/zypp/MediaSetAccess_test.cc @@ -0,0 +1,329 @@ +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "WebServer.h" +#include "FtpServer.h" + +using std::cout; +using std::endl; +using std::string; +using namespace zypp; +using namespace boost::unit_test; +using namespace zypp::filesystem; + +class SimpleVerifier : public media::MediaVerifierBase +{ +public: + + SimpleVerifier( const std::string &id ) + { + _media_id = id; + } + + bool isDesiredMedia(const media::MediaHandler &ref) const override + { + return ref.doesFileExist(Pathname("/x." + _media_id )); + } + +private: + std::string _media_id; +}; + +bool check_file_exists(const Pathname &path) +{ + FILE *file; + + if ((file = fopen(path.asString().c_str(), "r")) == NULL) return false; + + fclose(file); + return true; +} + +/* + * Check how MediaSetAccess::rewriteUrl() works. + */ +BOOST_AUTO_TEST_CASE(msa_url_rewrite) +{ + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("iso:/?iso=/path/to/CD1.iso"), 1).asString(), + Url("iso:/?iso=/path/to/CD1.iso").asString()); + + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("iso:/?iso=/path/to/CD1.iso"), 2).asString(), + Url("iso:/?iso=/path/to/CD2.iso").asString()); + + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("iso:/?iso=/path/to/CD1.iso"), 13).asString(), + Url("iso:/?iso=/path/to/CD13.iso").asString()); + + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("iso:/?iso=/path/to/cd1.iso"), 2).asString(), + Url("iso:/?iso=/path/to/cd2.iso").asString()); + + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("iso:/?iso=/path/to/cd2.iso"), 1).asString(), + Url("iso:/?iso=/path/to/cd1.iso").asString()); + + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("iso:/?iso=/path/to/dvd1.iso"), 2).asString(), + Url("iso:/?iso=/path/to/dvd2.iso").asString()); + + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("dir:/path/to/CD1"), 2).asString(), + Url("dir:/path/to/CD2").asString()); + + // trailing slash check + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("dir:/path/to/CD1/"), 2).asString(), + Url("dir:/path/to/CD2/").asString()); + + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("nfs://nfs-server/exported/path/to/dvd1"), 2).asString(), + Url("nfs://nfs-server/exported/path/to/dvd2").asString()); + + // single media check shouldn't this fail somehow?? + BOOST_CHECK_EQUAL( + MediaSetAccess::rewriteUrl(Url("http://ftp.opensuse.org/pub/opensuse/distribution/SL-OSS-factory/inst-source"), 2).asString(), + Url("http://ftp.opensuse.org/pub/opensuse/distribution/SL-OSS-factory/inst-source").asString()); +} + +#define DATADIR (Pathname(TESTS_SRC_DIR) / "/zypp/data/mediasetaccess") + +/* + * + * test data dir structure: + * + * . + * |-- src1 + * | |-- cd1 + * | | |-- dir + * | | | |-- file1 + * | | | |-- file2 + * | | | `-- subdir + * | | | `-- file + * | | `-- test.txt + * | |-- cd2 + * | | `-- test.txt + * | `-- cd3 + * | `-- test.txt + * `-- src2 + * `-- test.txt + * + */ + +/* + * Provide files from set without verifiers. + */ +BOOST_AUTO_TEST_CASE(msa_provide_files_set) +{ + Url url = (DATADIR + "/src1/cd1").asUrl(); + MediaSetAccess setaccess(url); + + Pathname file1 = setaccess.provideFile("/test.txt", 1); + BOOST_CHECK(check_file_exists(file1) == true); + + Pathname file2 = setaccess.provideFile("/test.txt", 2); + BOOST_CHECK(check_file_exists(file2) == true); + + Pathname file3 = setaccess.provideFile("/test.txt", 3); + BOOST_CHECK(check_file_exists(file3) == true); +} + +/* + * Provide files from set with verifiers. + */ +BOOST_AUTO_TEST_CASE(msa_provide_files_set_verified) +{ + Url url = (DATADIR + "/src1/cd1").asUrl(); + MediaSetAccess setaccess(url); + + setaccess.setVerifier(1, media::MediaVerifierRef(new SimpleVerifier("media1"))); + setaccess.setVerifier(2, media::MediaVerifierRef(new SimpleVerifier("media2"))); + setaccess.setVerifier(3, media::MediaVerifierRef(new SimpleVerifier("media3"))); + + // provide file from media1 + Pathname file1 = setaccess.provideFile("/test.txt", 1); + BOOST_CHECK(check_file_exists(file1) == true); + + // provide file from invalid media + BOOST_CHECK_THROW(setaccess.provideFile("/test.txt", 2), + media::MediaNotDesiredException); + + // provide file from media3 + Pathname file3 = setaccess.provideFile("/test.txt", 3); + BOOST_CHECK(check_file_exists(file3) == true); +} + +/* + * Provide file from single media with verifier. + */ +BOOST_AUTO_TEST_CASE(msa_provide_files_single) +{ + Url url = (DATADIR + "/src2").asUrl(); + MediaSetAccess setaccess(url); + setaccess.setVerifier(1, media::MediaVerifierRef(new SimpleVerifier("media"))); + + // provide file from media + Pathname file = setaccess.provideFile("/test.txt", 1); + BOOST_CHECK(check_file_exists(file) == true); + + // provide non-existent file + // (default answer from callback should be ABORT) + BOOST_CHECK_THROW(setaccess.provideFile("/imnothere", 2), + media::MediaFileNotFoundException); +} + +/* + * Provide directory from src/cd1. + */ +BOOST_AUTO_TEST_CASE(msa_provide_dir) +{ + Url url = (DATADIR + "/src1/cd1").asUrl(); + + MediaSetAccess setaccess(url); + + Pathname dir = setaccess.provideDir("/dir", false, 1); + + Pathname file1 = dir + "/file1"; + BOOST_CHECK(check_file_exists(file1) == true); + + Pathname file2 = dir + "/file2"; + BOOST_CHECK(check_file_exists(file2) == true); + + // provide non-existent dir + // (default answer from callback should be ABORT) + BOOST_CHECK_THROW(setaccess.provideDir("/imnothere", 2), + media::MediaFileNotFoundException); + + // This can't be properly tested with 'dir' schema, probably only curl + // schemas (http, ftp) where download is actually needed. + // Other schemas just get mounted onto a local dir and the whole subtree + // is automatically available that way. + // BOOST_CHECK(check_file_exists(dir + "/subdir/file") == false); + // BOOST_CHECK(check_file_exists(dir + "/subdir") == false); +} + + +/* + * Provide directory from src/cd1 (recursively). + */ +BOOST_AUTO_TEST_CASE(msa_provide_dirtree) +{ + Url url = (DATADIR + "/src1/cd1").asUrl(); + MediaSetAccess setaccess(url); + + Pathname dir = setaccess.provideDir("/dir", true, 1); + + Pathname file1 = dir + "/file1"; + BOOST_CHECK(check_file_exists(file1) == true); + + Pathname file2 = dir + "/file2"; + BOOST_CHECK(check_file_exists(file2) == true); + + Pathname file3 = dir + "/subdir/file"; + BOOST_CHECK(check_file_exists(file3) == true); +} + +/* + * file exists local + */ +BOOST_AUTO_TEST_CASE(msa_file_exist_local) +{ + Url url = (DATADIR + "/src1/cd1").asUrl(); + MediaSetAccess setaccess(url); + + BOOST_CHECK(setaccess.doesFileExist("/test.txt")); + BOOST_CHECK(!setaccess.doesFileExist("/testBADNAME.txt")); +} + +template +void msa_remote_tests_impl() { + Server srv( DATADIR / "/src1/cd1", 10002 ); + BOOST_REQUIRE( srv.start() ); + MediaSetAccess setaccess( srv.url(), "/" ); + + BOOST_CHECK(!setaccess.doesFileExist("/testBADNAME.txt")); + BOOST_CHECK(setaccess.doesFileExist("/test.txt")); + + // check providing a file via http works + Pathname local = setaccess.provideFile("/test.txt"); + BOOST_CHECK(CheckSum::sha1(sha1sum(local)) == CheckSum::sha1("2616e23301d7fcf7ac3324142f8c748cd0b6692b")); + + // providing a file which does not exist should throw + BOOST_CHECK_THROW(setaccess.provideFile("/testBADNAME.txt"), media::MediaFileNotFoundException); + + Pathname fPath; + { + Url url = srv.url(); + url.setPathName("/testBADNAME.txt"); + + // providing a file which does not exist should throw + BOOST_CHECK_THROW(MediaSetAccess::provideFileFromUrl(url), media::MediaFileNotFoundException); + + url.setPathName("/test.txt"); + + //providing a file by static method, file should exist after method call + ManagedFile file = MediaSetAccess::provideFileFromUrl( url ); + fPath = file; + BOOST_CHECK(check_file_exists(fPath) == true); + } + //file should be removed once the ManagedFile goes out of scope + BOOST_CHECK(check_file_exists(fPath) == false); + + BOOST_CHECK(setaccess.doesFileExist("/test-big.txt")); + BOOST_CHECK(setaccess.doesFileExist("dir/test-big.txt")); + + { + // providing a file with wrong filesize should throw + OnMediaLocation locPlain("dir/test-big.txt"); + locPlain.setDownloadSize( zypp::ByteCount(500, zypp::ByteCount::B) ); + BOOST_CHECK_THROW(setaccess.provideFile(locPlain), media::MediaFileSizeExceededException); + + // using the correct file size should NOT throw + locPlain.setDownloadSize( zypp::ByteCount(7135, zypp::ByteCount::B) ); + Pathname file = setaccess.provideFile( locPlain ); + BOOST_CHECK(check_file_exists(file) == true); + } + + { + // test the maximum filesize again with metalink downloads + // providing a file with wrong filesize should throw + OnMediaLocation locMeta("/test-big.txt"); + locMeta.setDownloadSize( zypp::ByteCount(500, zypp::ByteCount::B) ); + BOOST_CHECK_THROW(setaccess.provideFile(locMeta), media::MediaFileSizeExceededException); + + // using the correct file size should NOT throw + locMeta.setDownloadSize( zypp::ByteCount(7135, zypp::ByteCount::B) ); + Pathname file = setaccess.provideFile( locMeta ); + BOOST_CHECK(check_file_exists(file) == true); + } + + srv.stop(); +} + +/* + * file exists remote http + */ +BOOST_AUTO_TEST_CASE(msa_remote_tests_http) +{ + msa_remote_tests_impl(); +} + +/* + * file exists remote ftp + */ +BOOST_AUTO_TEST_CASE(msa_remote_tests_ftp) +{ + msa_remote_tests_impl(); +} + + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/zypp/PathInfo_test.cc b/tests/zypp/PathInfo_test.cc new file mode 100644 index 0000000..c4fa4bb --- /dev/null +++ b/tests/zypp/PathInfo_test.cc @@ -0,0 +1,213 @@ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using std::cout; +using std::endl; +using namespace zypp; +using namespace zypp::filesystem; + +/** + * Test case for + * bool is_checksum( const Pathname & file, const CheckSum &checksum ); + * std::string checksum( const Pathname & file, const std::string &algorithm ); + */ +BOOST_AUTO_TEST_CASE(pathinfo_checksum_test) +{ + const char *buffer = "I will test the checksum of this"; + TmpFile file; + std::ofstream str(file.path().asString().c_str(),std::ofstream::out); + + if (!str.good()) + ZYPP_THROW(Exception("cant open file")); + + str << buffer; + str.flush(); + str.close(); + + CheckSum file_sha1("sha1", "142df4277c326f3549520478c188cab6e3b5d042"); + CheckSum file_md5("md5", "f139a810b84d82d1f29fc53c5e59beae"); + + BOOST_CHECK_EQUAL( checksum( file.path(), "sha1"), "142df4277c326f3549520478c188cab6e3b5d042" ); + BOOST_CHECK_EQUAL( checksum( file.path(), "md5"), "f139a810b84d82d1f29fc53c5e59beae" ); + + BOOST_REQUIRE( is_checksum( file.path(), file_sha1 ) ); + BOOST_REQUIRE( is_checksum( file.path(), file_md5 ) ); +} + +BOOST_AUTO_TEST_CASE(pathinfo_is_exist_test) +{ + TmpDir dir; + Pathname subdir("text with spaces"); + // create a fake file + BOOST_CHECK_EQUAL( filesystem::mkdir(dir.path() + subdir), 0 ); + + Pathname filepath = (dir.path() + subdir+ "filename"); + std::ofstream str(filepath.asString().c_str(),std::ofstream::out); + str << "foo bar" << endl; + str.flush(); + str.close(); + + BOOST_CHECK( PathInfo(filepath).isExist() ); +} + +BOOST_AUTO_TEST_CASE(pathipathinfo_misc_test) +{ + TmpDir dir; + + PathInfo info(dir.path()); + BOOST_CHECK(info.isDir()); +} + +BOOST_AUTO_TEST_CASE(pathinfo_expandlink_test) +{ + TmpDir dir; + + // ---- not a link + + // create a file + Pathname file(dir / "file"); + std::ofstream str(file.asString().c_str(),std::ofstream::out); + str << "foo bar" << endl; + str.flush(); + str.close(); + + // expandlink should return the original Pathname if it does not point to a link + BOOST_CHECK_EQUAL( file, filesystem::expandlink(file) ); + + // ---- valid link + + // create a (relative!) link to that file + Pathname link1(dir / "link1"); + BOOST_CHECK_EQUAL( filesystem::symlink(file.basename(), link1), 0); + + // does the link expand to the file? + BOOST_CHECK_EQUAL( file, filesystem::expandlink(link1) ); + + // ---- broken link + + // create a link to a non-existent file + Pathname brokenlink(dir / "brokenlink"); + Pathname non_existent(dir / "non-existent"); + BOOST_CHECK_EQUAL( filesystem::symlink(non_existent, brokenlink), 0); + PathInfo info(brokenlink, PathInfo::LSTAT); + BOOST_CHECK(info.isLink()); + + // expandlink should return an empty Pathname for a broken link + BOOST_CHECK_EQUAL( Pathname(), filesystem::expandlink(brokenlink) ); + + // ---- cyclic link + + // make the 'non-existent' a link to 'brokenlink' :O) + BOOST_CHECK_EQUAL( filesystem::symlink(brokenlink, non_existent), 0); + // expandlink should return an empty Pathname for such a cyclic link + BOOST_CHECK_EQUAL( Pathname(), filesystem::expandlink(brokenlink) ); + BOOST_CHECK_EQUAL( Pathname(), filesystem::expandlink(non_existent) ); + + cout << brokenlink << " -> " << filesystem::expandlink(brokenlink) << endl; +} + +BOOST_AUTO_TEST_CASE(test_assert_dir_file) +{ + TmpDir root; + + Pathname rfile( root/"file" ); + BOOST_CHECK_EQUAL( filesystem::assert_file( rfile ), 0 ); + BOOST_CHECK( PathInfo(rfile).isFile() ); + + Pathname rdir ( root/"dir" ); + BOOST_CHECK_EQUAL( filesystem::assert_dir ( rdir ), 0 ); + BOOST_CHECK( PathInfo(rdir).isDir() ); + + // empty path + Pathname path; + BOOST_CHECK_EQUAL( filesystem::assert_file( path ), ENOENT ); + BOOST_CHECK_EQUAL( filesystem::assert_dir ( path ), ENOENT ); + + // for dirs: + // existing dir + path = rdir; + BOOST_CHECK_EQUAL( filesystem::assert_dir( path ), 0 ); + BOOST_CHECK( PathInfo(path).isDir() ); + // new dirs + path = rdir/"sub/subsub"; + BOOST_CHECK_EQUAL( filesystem::assert_dir( path ), 0 ); + BOOST_CHECK( PathInfo(path).isDir() ); + // file in path + path = rfile/"sub"; + BOOST_CHECK_EQUAL( filesystem::assert_dir( path ), ENOTDIR ); + BOOST_CHECK( !PathInfo(path).isDir() ); + // path is file + path = rfile; + BOOST_CHECK_EQUAL( filesystem::assert_dir( path ), EEXIST ); + BOOST_CHECK( !PathInfo(path).isDir() ); + + // for files: + // existing file + path = rfile; + BOOST_CHECK_EQUAL( filesystem::assert_file( path ), 0 ); + BOOST_CHECK( PathInfo(path).isFile() ); + // new file + path = rdir/"sub/file"; + BOOST_CHECK_EQUAL( filesystem::assert_file( path ), 0 ); + BOOST_CHECK( PathInfo(path).isFile() ); + // file in path + path = rfile/"sub/file"; + BOOST_CHECK_EQUAL( filesystem::assert_file( path ), ENOTDIR ); + BOOST_CHECK( ! PathInfo(path).isFile() ); + // path is dir + path = rdir; + BOOST_CHECK_EQUAL( filesystem::assert_file( path ), EEXIST ); + BOOST_CHECK( ! PathInfo(path).isFile() ); +} + +BOOST_AUTO_TEST_CASE(test_exchange) +{ + TmpDir root; + Pathname a; + Pathname b; + // paths must not be epmty: + BOOST_CHECK_EQUAL( filesystem::exchange( a, b ), EINVAL ); + a = root/"a/p"; + BOOST_CHECK_EQUAL( filesystem::exchange( a, b ), EINVAL ); + b = root/"b/p"; + BOOST_CHECK_EQUAL( filesystem::exchange( a, b ), 0 ); // ok if both don't exist + + // one path not existing: + filesystem::assert_file( a ); + BOOST_CHECK( PathInfo(a).isFile() ); + BOOST_CHECK( !PathInfo(b).isFile() ); + + BOOST_CHECK_EQUAL( filesystem::exchange( a, b ), 0 ); + BOOST_CHECK( !PathInfo(a).isFile() ); + BOOST_CHECK( PathInfo(b).isFile() ); + + BOOST_CHECK_EQUAL( filesystem::exchange( a, b ), 0 ); + BOOST_CHECK( PathInfo(a).isFile() ); + BOOST_CHECK( !PathInfo(b).isFile() ); + + // both paths exist: + filesystem::assert_dir( b ); + BOOST_CHECK( PathInfo(b).isDir() ); + + BOOST_CHECK_EQUAL( filesystem::exchange( a, b ), 0 ); + BOOST_CHECK( PathInfo(a).isDir() ); + BOOST_CHECK( PathInfo(b).isFile() ); + + BOOST_CHECK_EQUAL( filesystem::exchange( a, b ), 0 ); + BOOST_CHECK( PathInfo(a).isFile() ); + BOOST_CHECK( PathInfo(b).isDir() ); +} diff --git a/tests/zypp/Pathname_test.cc b/tests/zypp/Pathname_test.cc new file mode 100644 index 0000000..ebc13c1 --- /dev/null +++ b/tests/zypp/Pathname_test.cc @@ -0,0 +1,166 @@ +#include +#include + +#include + +#include +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; + +BOOST_AUTO_TEST_CASE(pathname_default_ctor) +{ + Pathname p; + + BOOST_CHECK_EQUAL(p.empty(), true ); + BOOST_CHECK_EQUAL(p.absolute(), false ); + BOOST_CHECK_EQUAL(p.relative(), false ); + BOOST_CHECK_EQUAL(p.dirname(), "" ); + BOOST_CHECK_EQUAL(p.basename(), "" ); + BOOST_CHECK_EQUAL(p.extension(), "" ); + BOOST_CHECK_EQUAL(p.absolutename(), "" ); + BOOST_CHECK_EQUAL(p.relativename(), "" ); +} + +BOOST_AUTO_TEST_CASE(pathname_root) +{ + Pathname p("/"); + + BOOST_CHECK_EQUAL(p.empty(), false ); + BOOST_CHECK_EQUAL(p.absolute(), true ); + BOOST_CHECK_EQUAL(p.relative(), false ); + BOOST_CHECK_EQUAL(p.dirname(), "/" ); + BOOST_CHECK_EQUAL(p.basename(), "/" ); + BOOST_CHECK_EQUAL(p.extension(), "" ); + BOOST_CHECK_EQUAL(p.absolutename(), "/" ); + BOOST_CHECK_EQUAL(p.relativename(), "./" ); +} + +BOOST_AUTO_TEST_CASE(pathname_this) +{ + Pathname p("."); + + BOOST_CHECK_EQUAL(p.empty(), false ); + BOOST_CHECK_EQUAL(p.absolute(), false ); + BOOST_CHECK_EQUAL(p.relative(), true ); + BOOST_CHECK_EQUAL(p.dirname(), "." ); + BOOST_CHECK_EQUAL(p.basename(), "." ); + BOOST_CHECK_EQUAL(p.extension(), "" ); + BOOST_CHECK_EQUAL(p.absolutename(), "/" ); + BOOST_CHECK_EQUAL(p.relativename(), "." ); +} + +BOOST_AUTO_TEST_CASE(pathname_up) +{ + Pathname p(".."); + + BOOST_CHECK_EQUAL(p.empty(), false ); + BOOST_CHECK_EQUAL(p.absolute(), false ); + BOOST_CHECK_EQUAL(p.relative(), true ); + BOOST_CHECK_EQUAL(p.dirname(), "." ); + BOOST_CHECK_EQUAL(p.basename(), ".." ); + BOOST_CHECK_EQUAL(p.extension(), "" ); + BOOST_CHECK_EQUAL(p.absolutename(), "/" ); + BOOST_CHECK_EQUAL(p.relativename(), ".." ); +} + +BOOST_AUTO_TEST_CASE(pathname_abs) +{ + Pathname p("/foo/baa.ka"); + + BOOST_CHECK_EQUAL(p.empty(), false ); + BOOST_CHECK_EQUAL(p.absolute(), true ); + BOOST_CHECK_EQUAL(p.relative(), false ); + BOOST_CHECK_EQUAL(p.dirname(), "/foo" ); + BOOST_CHECK_EQUAL(p.basename(), "baa.ka" ); + BOOST_CHECK_EQUAL(p.extension(), ".ka" ); + BOOST_CHECK_EQUAL(p.absolutename(), "/foo/baa.ka" ); + BOOST_CHECK_EQUAL(p.relativename(), "./foo/baa.ka" ); +} + +BOOST_AUTO_TEST_CASE(pathname_rel) +{ + Pathname p("./foo/./../baa.ka"); + + BOOST_CHECK_EQUAL(p.empty(), false ); + BOOST_CHECK_EQUAL(p.absolute(), false ); + BOOST_CHECK_EQUAL(p.relative(), true ); + BOOST_CHECK_EQUAL(p.dirname(), "." ); + BOOST_CHECK_EQUAL(p.basename(), "baa.ka" ); + BOOST_CHECK_EQUAL(p.extension(), ".ka" ); + BOOST_CHECK_EQUAL(p.absolutename(), "/baa.ka" ); + BOOST_CHECK_EQUAL(p.relativename(), "./baa.ka" ); +} + +BOOST_AUTO_TEST_CASE(pathname_relup) +{ + Pathname p("./../foo/./../baa"); + + BOOST_CHECK_EQUAL(p.empty(), false ); + BOOST_CHECK_EQUAL(p.absolute(), false ); + BOOST_CHECK_EQUAL(p.relative(), true ); + BOOST_CHECK_EQUAL(p.dirname(), ".." ); + BOOST_CHECK_EQUAL(p.basename(), "baa" ); + BOOST_CHECK_EQUAL(p.extension(), "" ); + BOOST_CHECK_EQUAL(p.absolutename(), "/baa" ); + BOOST_CHECK_EQUAL(p.relativename(), "../baa" ); +} + +BOOST_AUTO_TEST_CASE(pathname_strval) +{ + BOOST_CHECK_EQUAL(Pathname("").asString(), "" ); + BOOST_CHECK_EQUAL(Pathname("/////./").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("./").asString(), "." ); + BOOST_CHECK_EQUAL(Pathname("/.").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("./..").asString(), "./.." ); // ? .. + BOOST_CHECK_EQUAL(Pathname("../").asString(), "./.." ); // ? .. + BOOST_CHECK_EQUAL(Pathname(".././..").asString(), "./../.." ); // ? ../.. + + + BOOST_CHECK_EQUAL(Pathname("//baa").asString(), "/baa" ); + BOOST_CHECK_EQUAL(Pathname("/./baa").asString(), "/baa" ); + BOOST_CHECK_EQUAL(Pathname("/baa/..").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/baa/../baa").asString(), "/baa" ); + BOOST_CHECK_EQUAL(Pathname("/./../foo/./../baa").asString(), "/baa" ); + + BOOST_CHECK_EQUAL(Pathname("/").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname(".").asString(), "." ); + BOOST_CHECK_EQUAL(Pathname("..").asString(), "./.." ); + BOOST_CHECK_EQUAL(Pathname("/.").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/..").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/./.").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/./..").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/../.").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/../..").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/././").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/./../").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/.././").asString(), "/" ); + BOOST_CHECK_EQUAL(Pathname("/../../").asString(), "/" ); + + BOOST_CHECK_EQUAL(Pathname("a\\b").asString(), "./a\\b" ); + BOOST_CHECK_EQUAL(Pathname("a/b").asString(), "./a/b" ); + BOOST_CHECK_EQUAL(Pathname("c:a\\b").asString(), "./c:a\\b" ); + BOOST_CHECK_EQUAL(Pathname("c:a/b").asString(), "./c:a/b" ); + BOOST_CHECK_EQUAL(Pathname("cc:a\\b").asString(), "./cc:a\\b" ); + BOOST_CHECK_EQUAL(Pathname("cc:a/b").asString(), "./cc:a/b" ); +} + +BOOST_AUTO_TEST_CASE(pathname_stripprefix) +{ + BOOST_CHECK_EQUAL( Pathname::stripprefix( "", "" ), "" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "", "/" ), "/" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "", "/foo" ), "/foo" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/", "" ), "" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/", "/" ), "/" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/", "/foo" ), "/foo" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/f", "" ), "" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/f", "/" ), "/" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/f", "/foo" ), "/foo" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/foo", "" ), "" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/foo", "/" ), "/" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/foo", "/foo" ), "/" ); + BOOST_CHECK_EQUAL( Pathname::stripprefix( "/foo", "/foo/baa" ), "/baa" ); +} diff --git a/tests/zypp/PluginFrame_test.cc b/tests/zypp/PluginFrame_test.cc new file mode 100644 index 0000000..0e47508 --- /dev/null +++ b/tests/zypp/PluginFrame_test.cc @@ -0,0 +1,188 @@ +#include +#include + +#include +#include + +#include "TestSetup.h" +#include + +BOOST_AUTO_TEST_CASE(InitialSettings) +{ + PluginScript::defaultTimeout( 3 ); +} + +BOOST_AUTO_TEST_CASE(PluginFrameDefaultCtor) +{ + PluginFrame f; + BOOST_CHECK_EQUAL( bool(f), !f.empty() ); + BOOST_CHECK_EQUAL( f.empty(), true ); + BOOST_CHECK_EQUAL( f.command().empty(), true ); + BOOST_CHECK_EQUAL( f.body().empty(), true ); + BOOST_CHECK_EQUAL( f.headerEmpty(), true ); + BOOST_CHECK_EQUAL( (f == f), true ); + BOOST_CHECK_EQUAL( (f != f), false ); +} + +BOOST_AUTO_TEST_CASE(PluginFrameCtorAssign) +{ + PluginFrame f( "command" ); + BOOST_CHECK_EQUAL( bool(f), !f.empty() ); + BOOST_CHECK_EQUAL( f.empty(), false ); + BOOST_CHECK_EQUAL( f.command(), "command" ); + BOOST_CHECK_EQUAL( f.body().empty(), true ); + BOOST_CHECK_EQUAL( f.headerEmpty(), true ); + BOOST_CHECK_EQUAL( (f == f), true ); + BOOST_CHECK_EQUAL( (f != f), false ); + + PluginFrame g( "command", "body" ); + BOOST_CHECK_EQUAL( bool(g), !g.empty() ); + BOOST_CHECK_EQUAL( g.empty(), false ); + BOOST_CHECK_EQUAL( g.command(), "command" ); + BOOST_CHECK_EQUAL( g.body().asString(), "body"); + BOOST_CHECK_EQUAL( g.headerEmpty(), true ); + BOOST_CHECK_EQUAL( (f == g), false ); + BOOST_CHECK_EQUAL( (f != g), true ); + + PluginFrame h( g ); + BOOST_CHECK_EQUAL( (g == h), true ); + + h.addHeader( "" ); // empty KV in header is ok, if you like it + BOOST_CHECK_EQUAL( (g == h), false ); + + h.addHeader({ + { "a", "a1" }, + { "a", "a2" }, + { "b", "b1" }, + { "b", "b2" }, + { "c", "c1" }, + { "c", "c1" } + }); + BOOST_CHECK_EQUAL( h.headerSize(), 7 ); + + h.setHeader( "b", "b" ); // replaces existing 'b:" headers + BOOST_CHECK_EQUAL( h.headerSize(), 6 ); + + // now write and reparse from stream: + std::string data; + { + std::ostringstream datas; + h.writeTo( datas ); + datas.str().swap( data ); + } + std::istringstream datas( data ); + PluginFrame i( datas ); + BOOST_CHECK_EQUAL( (h == i), true ); +} + +void doParse( const std::string & str_r ) +{ + std::string data( str_r ); + data.push_back( '\0' ); + std::istringstream datas( data ); + PluginFrame i( datas ); +} + +BOOST_AUTO_TEST_CASE(PluginFrameExceptipn) +{ + BOOST_CHECK_THROW( PluginFrame( "c\nc" ), PluginFrameException ); + + BOOST_CHECK_THROW( doParse( "c" ), PluginFrameException ); // no NL after command + BOOST_CHECK_THROW( doParse( "c\n" ), PluginFrameException ); // no NL after header + doParse( "c\n\n" ); // valid empy header and body + BOOST_CHECK_THROW( doParse( "c\nh:v\nbody" ), PluginFrameException ); // no NL after header + doParse( "c\nh:v\n\nbody" ); // valid + BOOST_CHECK_THROW( doParse( "c\nhv\n\nbody" ), PluginFrameException ); // no : in header +} + +BOOST_AUTO_TEST_CASE(PluginScriptTest) +{ + PluginScript scr; + BOOST_CHECK_EQUAL( scr.isOpen(), false ); + BOOST_CHECK_EQUAL( scr.getPid(), PluginScript::NotConnected ); + BOOST_CHECK_EQUAL( scr.script(), "" ); + + BOOST_CHECK_THROW( scr.open( "bla" ), PluginScriptException ); // script does not exist + BOOST_CHECK_EQUAL( scr.isOpen(), false ); // stay closed + BOOST_CHECK_EQUAL( scr.getPid(), PluginScript::NotConnected ); + BOOST_CHECK_EQUAL( scr.script(), "" ); + + scr.open( "/bin/cat" ); + BOOST_CHECK_EQUAL( scr.isOpen(), true ); + BOOST_CHECK_EQUAL( (scr.getPid() != PluginScript::NotConnected ), true ); + BOOST_CHECK_EQUAL( scr.script(), "/bin/cat" ); // set after successful open + + BOOST_CHECK_THROW( scr.open( "/bin/ls" ), PluginScriptException ); // already open + BOOST_CHECK_EQUAL( scr.isOpen(), true ); // stay with "/bin/cat" + BOOST_CHECK_EQUAL( (scr.getPid() != PluginScript::NotConnected ), true ); + BOOST_CHECK_EQUAL( scr.script(), "/bin/cat" ); + + PluginFrame f; + scr.send( f ); + PluginFrame r( scr.receive() ); + BOOST_CHECK_EQUAL( f, r ); + + f.setCommand( "CMD" ); + f.addHeader( "a","value" ); + f.setBody( "foo" ); + scr.send( f ); + r = scr.receive(); + BOOST_CHECK_EQUAL( f, r ); + + scr.close(); + BOOST_CHECK_EQUAL( scr.isOpen(), false ); + BOOST_CHECK_EQUAL( scr.getPid(), PluginScript::NotConnected ); + BOOST_CHECK_EQUAL( scr.script(), "/bin/cat" ); // not reset by close, may be reused by open() + + scr.close(); // no exception on dupl. close. +} + +BOOST_AUTO_TEST_CASE(PluginScriptSend) +{ + PluginFrame f( "a" ); + f.setBody( std::string( 1020, '0' ) ); + + PluginScript scr( "/bin/cat" ); + BOOST_CHECK_THROW( scr.send( f ), PluginScriptNotConnected ); + + scr.open(); + BOOST_CHECK_THROW( do { scr.send( f ); } while ( true ), PluginScriptSendTimeout ); + + ::kill( scr.getPid(), SIGKILL); + BOOST_CHECK_THROW( scr.send( f ), PluginScriptDiedUnexpectedly ); +} + +BOOST_AUTO_TEST_CASE(PluginScriptReceive) +{ + PluginFrame f( "a" ); + f.setBody( std::string( 1020, '0' ) ); + + PluginScript scr( "/bin/cat" ); + scr.open(); + BOOST_CHECK_THROW( scr.receive(), PluginScriptReceiveTimeout ); + + ::kill( scr.getPid(), SIGKILL); + BOOST_CHECK_THROW( scr.receive(), PluginScriptDiedUnexpectedly ); +} + +BOOST_AUTO_TEST_CASE(PluginExecutorTest) +{ + PluginExecutor exec; + BOOST_CHECK_EQUAL( (bool)exec, !exec.empty() ); + BOOST_CHECK_EQUAL( exec.empty(), true ); + BOOST_CHECK_EQUAL( exec.size(), 0 ); + + exec.load( "/bin/cat" ); + BOOST_CHECK_EQUAL( (bool)exec, !exec.empty() ); + BOOST_CHECK_EQUAL( exec.empty(), false ); + BOOST_CHECK_EQUAL( exec.size(), 1 ); + + exec.load( "/bin/cat" ); + BOOST_CHECK_EQUAL( exec.size(), 2 ); + + exec.send( PluginFrame( "ACK" ) ); + BOOST_CHECK_EQUAL( exec.size(), 2 ); + + exec.send( PluginFrame( "ERROR" ) ); + BOOST_CHECK_EQUAL( exec.size(), 0 ); // deleted failing scripts +} diff --git a/tests/zypp/PoolQueryCC_test.cc b/tests/zypp/PoolQueryCC_test.cc new file mode 100644 index 0000000..5fa475c --- /dev/null +++ b/tests/zypp/PoolQueryCC_test.cc @@ -0,0 +1,126 @@ +#include "TestSetup.h" +#include +#include + +#include +#include + +#define BOOST_TEST_MODULE PoolQuery_CC + +using boost::unit_test::test_case; +using std::cin; +using std::cout; +using std::cerr; +using std::endl; +using namespace zypp; + +template +std::ostream & nlist( std::ostream & str, const TCont & set_r ) +{ + str << "[" << set_r.size() << "]: "; + for ( const auto & solv : set_r ) + str << " \"" << solv.name() << "\""; + return str << endl; +} + +///////////////////////////////////////////////////////////////////////////// + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + + test.loadTargetHelix( TESTS_SRC_DIR "/zypp/data/PoolQueryCC/rxnames.xml" ); + nlist( cout << "repo ", ResPool::instance() ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +///////////////////////////////////////////////////////////////////////////// +// Basic issue: Multiple match strings are compiled into a singe regex. The +// semantic of the individual match strings must be preserved. I.e. a literal +// "." must become "\.". Globbing patterns must match the whole string, so they +// need to be anchored within the regex. Etc. +///////////////////////////////////////////////////////////////////////////// +static const unsigned qtestSIZEMISS = unsigned(-1); +static const unsigned qtestRXFAIL = unsigned(-2); +static const unsigned qtestRXFAILCOMB = unsigned(-3); + +unsigned qtest( const std::string & pattern_r, Match::Mode mode_r, bool verbose_r = false ) +{ + static constexpr const bool noMatchInvalidRegexException = false; + + typedef std::set Result; + PoolQuery q; + q.addAttribute(sat::SolvAttr::name); + switch ( mode_r ) + { + case Match::STRING: q.setMatchExact(); break; + case Match::SUBSTRING: q.setMatchSubstring(); break; + case Match::OTHER: q.setMatchWord(); break; // OTHER missused for matchWord() + case Match::GLOB: q.setMatchGlob(); break; + case Match::REGEX: q.setMatchRegex(); break; + default: + throw( "unhandled match mode" ); + break; + } + q.addString( pattern_r ); + Result o; + try { + o = Result( q.begin(), q.end() ); // original query + } + catch ( const zypp::MatchInvalidRegexException & excpt ) + { + cout << "Caught: " << excpt << endl; + return qtestRXFAIL; + } + + q.addString( "more" ); + try { + Result r( q.begin(), q.end() ); // compiles into RX (o|more) + + BOOST_CHECK( o == r ); + if ( o != r || verbose_r ) + { + cout << '"' << pattern_r << "\" " << mode_r << endl; + nlist( cout << " o", o ); + nlist( cout << " r", r ); + if ( ! verbose_r ) + return qtestSIZEMISS; + } + } + catch ( const zypp::MatchInvalidRegexException & excpt ) + { + BOOST_CHECK( noMatchInvalidRegexException ); + cout << "Caught: " << excpt << endl; + return qtestRXFAILCOMB; + } + + return o.size(); +} + +inline unsigned qtest( const std::string & pattern_r, bool verbose_r = false ) +{ return qtest( pattern_r, Match::SUBSTRING, verbose_r ); } + +///////////////////////////////////////////////////////////////////////////// +BOOST_AUTO_TEST_CASE(pool_query_init) +{ + // NOTE: qtest( , Match::OTHER ) is missused for matchWord() + BOOST_CHECK_EQUAL( qtest( "?", Match::SUBSTRING ), 1 ); + BOOST_CHECK_EQUAL( qtest( "?", Match::STRING ), 1 ); + BOOST_CHECK_EQUAL( qtest( "?", Match::OTHER ), 0 ); // not word boundary + BOOST_CHECK_EQUAL( qtest( "?", Match::GLOB ), 15 ); + BOOST_CHECK_EQUAL( qtest( "\\?", Match::GLOB ), 1 ); + BOOST_CHECK_EQUAL( qtest( "?", Match::REGEX ), qtestRXFAIL ); + BOOST_CHECK_EQUAL( qtest( "\\?", Match::REGEX ), 1 ); + + BOOST_CHECK_EQUAL( qtest( "A", Match::SUBSTRING ), 4 ); + BOOST_CHECK_EQUAL( qtest( "A", Match::OTHER ), 2 ); + BOOST_CHECK_EQUAL( qtest( "A*", Match::OTHER ), 0 ); + BOOST_CHECK_EQUAL( qtest( "*A", Match::OTHER ), 0 ); + BOOST_CHECK_EQUAL( qtest( "A*", Match::GLOB ), 2 ); + BOOST_CHECK_EQUAL( qtest( "*A", Match::GLOB ), 1 ); +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/tests/zypp/PoolQuery_test.cc b/tests/zypp/PoolQuery_test.cc new file mode 100644 index 0000000..cd8aabf --- /dev/null +++ b/tests/zypp/PoolQuery_test.cc @@ -0,0 +1,989 @@ +#include "TestSetup.h" +#include +#include + +#define BOOST_TEST_MODULE PoolQuery + +///////////////////////////////////////////////////////////////////////////// +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( Arch_x86_64 ); + + // Abuse;) vbox as System repo: + test.loadTargetRepo( TESTS_SRC_DIR "/data/obs_virtualbox_11_1" ); + test.loadRepo( TESTS_SRC_DIR "/data/openSUSE-11.1", "opensuse" ); + test.loadRepo( TESTS_SRC_DIR "/data/OBS_zypp_svn-11.1", "zyppsvn" ); + + dumpRange( USR, test.pool().knownRepositoriesBegin(), + test.pool().knownRepositoriesEnd() ); + USR << "pool: " << test.pool() << endl; + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); +///////////////////////////////////////////////////////////////////////////// + +static std::ofstream devNull; +#define COUT devNull + +struct PrintAndCount +{ + PrintAndCount() : _count(0) {} + + bool operator()( const sat::Solvable & solvable ) + { + zypp::PoolItem pi( zypp::ResPool::instance().find( solvable ) ); + COUT << pi.resolvable() << endl; + ++_count; + return true; + } + + unsigned _count; +}; + +void dumpQ( std::ostream & str, const PoolQuery & q, bool verbose = true ) +{ + q.begin(); + str << q << endl; + unsigned nc = 0; + if ( 1 ) + { + for_( it, q.begin(), q.end() ) + { + ++nc; + if ( verbose ) + str << it << endl; + } + str << "--> MATCHES: " << nc << endl; + } +} + + +#if 0 +BOOST_AUTO_TEST_CASE(pool_query_experiment) +{ + cout << "****experiment****" << endl; + + PoolQuery q; + q.addString("zypper"); + q.addAttribute(sat::SolvAttr::name); + + // should list 1 selectable? + cout << "****selectables****" << endl; + for (PoolQuery::Selectable_iterator it = q.selectableBegin(); + it != q.selectableEnd(); ++it) + { + ui::Selectable::Ptr s = *it; + cout << s->kind() << ":" << s->name() << " hasinstalled: " << s->installedEmpty() << endl; + } + cout << "****solvables****" << endl; + PrintAndCount cb; + std::for_each(q.begin(), q.end(), cb); +} +#endif + +///////////////////////////////////////////////////////////////////////////// +// 0xx basic queries +///////////////////////////////////////////////////////////////////////////// + +// no conditions, default query +// result: all available resolvables +BOOST_AUTO_TEST_CASE(pool_query_000) +{ + cout << "****000****" << endl; + PoolQuery q; + cout << q.size() << endl; + BOOST_CHECK(q.size() == 3811); + + /* dumpsolv repo1.solv repo2.solv repo3.solv | \ + grep '^name:.*\(noarch\|x86_64\|i386\|i586\|i686\|src\)$' | wc -l */ +} + +// default query + one search string +// q.addString("foo"); +// result: all resolvables having at least one attribute matching foo +BOOST_AUTO_TEST_CASE(pool_query_001) +{ + cout << "****001****" << endl; + PoolQuery q; + q.addString("zypper"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 11); +} + +// default query + one attribute + one string +// q.addAttribute(foo, bar); +// should be the same as +// q.addAttribute(foo); q.addString(bar); +// result: resolvables with foo containing bar +BOOST_AUTO_TEST_CASE(pool_query_002) +{ + cout << "****002****" << endl; + PoolQuery q; + q.addString("zypper"); + q.addAttribute(sat::SolvAttr::name); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 5); + + cout << endl; + + PoolQuery q1; + q1.addAttribute(sat::SolvAttr::name, "zypper"); + + BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 5); +} + +// kind filter +BOOST_AUTO_TEST_CASE(pool_query_003) +{ + cout << "****003****" << endl; + PoolQuery q; + q.addString("zypper"); + q.addAttribute(sat::SolvAttr::name); + q.addKind(ResKind::package); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 3); +} + +// match exact +BOOST_AUTO_TEST_CASE(pool_query_004) +{ + cout << "****004****" << endl; + PoolQuery q; + q.addString("vim"); + q.addAttribute(sat::SolvAttr::name); + q.setMatchExact(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1); + + PoolQuery q1; + q1.addString("zypp"); + q1.addAttribute(sat::SolvAttr::name); + q1.setMatchExact(); + + std::for_each(q1.begin(), q1.end(), PrintAndCount()); + BOOST_CHECK(q1.empty()); +} + +// use globs +BOOST_AUTO_TEST_CASE(pool_query_005) +{ + cout << "****005.1****" << endl; + PoolQuery q; + q.addString("z?p*"); + q.addAttribute(sat::SolvAttr::name); + q.setMatchGlob(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6); + + cout << "****005.2****" << endl; + + PoolQuery q1; + q1.addString("*zypp*"); + q1.addAttribute(sat::SolvAttr::name); + q1.setMatchGlob(); + + BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 26); + + cout << "****005.3****" << endl; + + // should be the same as above + PoolQuery q2; + q2.addString("zypp"); + q2.addAttribute(sat::SolvAttr::name); + + BOOST_CHECK(q2.size() == 26); +} + +// use regex +BOOST_AUTO_TEST_CASE(pool_query_006) +{ + cout << "****006.1***" << endl; + + // should be the same as 005 1 + PoolQuery q; + q.addString("^z.p.*"); + q.addAttribute(sat::SolvAttr::name); + q.setMatchRegex(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6); + + cout << "****006.2***" << endl; + + PoolQuery q1; + q1.addString("zypper|smart"); + q1.addAttribute(sat::SolvAttr::name); + q1.setMatchRegex(); + + BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 8); + + cout << "****006.3***" << endl; + + // invalid regex + PoolQuery q2; + q2.addString("zypp\\"); + q2.setMatchRegex(); + BOOST_CHECK_THROW(q2.begin(), Exception); +} + + +// match whole words +BOOST_AUTO_TEST_CASE(pool_query_007) +{ + cout << "****007***" << endl; + + PoolQuery q; + q.addString("zypp"); + q.addAttribute(sat::SolvAttr::name); + q.setMatchWord(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6); +} + +// match by installed status (basically by system vs. repo) +BOOST_AUTO_TEST_CASE(pool_query_050) +{ + cout << "****050****" << endl; + PoolQuery q; + q.addString("yasm"); + q.addAttribute(sat::SolvAttr::name); + q.setMatchExact(); + q.setInstalledOnly(); + + BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 4); + + cout << endl; + + PoolQuery q1; + q1.addString("zypper"); + q1.addAttribute(sat::SolvAttr::name); + q1.setMatchExact(); + q1.setUninstalledOnly(); + BOOST_CHECK_EQUAL(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count, 5); +} + +///////////////////////////////////////////////////////////////////////////// +// 1xx multiple attribute queries +///////////////////////////////////////////////////////////////////////////// + + +BOOST_AUTO_TEST_CASE(pool_query_100) +{ + cout << "****100****" << endl; + PoolQuery q; + /* This string is found sometimes only in only in summary (e.g. pgcalc) + and sometimes only in description (e.g. bc, lftp). We don't have + any package with 'revers' only in package name, but let's ignore this. + I didn't find a string with the same characteristics giving fewer matches + :-/ */ + q.addString("revers"); + q.addAttribute(sat::SolvAttr::name); + q.addAttribute(sat::SolvAttr::summary); + q.addAttribute(sat::SolvAttr::description); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 5); + + cout << endl; + + { + PoolQuery q1; + q1.addAttribute(sat::SolvAttr::name, "zypper"); + BOOST_CHECK_EQUAL(q1.size(),5); + + PoolQuery q2; + q2.addAttribute(sat::SolvAttr::summary,"samba"); + BOOST_CHECK_EQUAL(q2.size(),13); + + // now summary and name in one go: + q1.addAttribute(sat::SolvAttr::summary,"samba"); + BOOST_CHECK_EQUAL(q1.size(),18); + } +} + + +// multi attr (same value) substring matching (case sensitive and insensitive) +BOOST_AUTO_TEST_CASE(pool_query_101) +{ + cout << "****101****" << endl; + + PoolQuery q; + q.addString("RELAX"); + q.addAttribute(sat::SolvAttr::name); + q.addAttribute(sat::SolvAttr::summary); + q.addAttribute(sat::SolvAttr::description); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 7); + + cout << endl; + + PoolQuery q2; + q2.addString("RELAX"); + q2.addAttribute(sat::SolvAttr::name); + q2.addAttribute(sat::SolvAttr::summary); + q2.addAttribute(sat::SolvAttr::description); + q2.setCaseSensitive(); + + BOOST_CHECK(std::for_each(q2.begin(), q2.end(), PrintAndCount())._count == 4); +} + + +// multi attr (same value) glob matching (case sensitive and insensitive) +BOOST_AUTO_TEST_CASE(pool_query_102) +{ + cout << "****102****" << endl; + PoolQuery q; + q.addString("pack*"); + q.addAttribute(sat::SolvAttr::name); + q.addAttribute(sat::SolvAttr::summary); + q.setMatchGlob(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 23); +} + + +// multi attr (same value via addAttribute()) +BOOST_AUTO_TEST_CASE(pool_query_103) +{ + cout << "****103.1****" << endl; + PoolQuery q; + q.addAttribute(sat::SolvAttr::name, "rest"); + q.addAttribute(sat::SolvAttr::summary, "rest"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 14); + + cout << "****103.2****" << endl; + + PoolQuery q1; + q1.addString("rest"); + q1.addAttribute(sat::SolvAttr::name); + q1.addAttribute(sat::SolvAttr::summary); + + BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 14); +// BOOST_CHECK(q1.size() == 42); + + cout << endl; +} + +// multiple attributes, different search strings (one string per attrbute) +BOOST_AUTO_TEST_CASE(pool_query_104) +{ + cout << "****104****" << endl; + PoolQuery q; + q.addAttribute(sat::SolvAttr::name, "zypper"); + q.addAttribute(sat::SolvAttr::summary, "package management"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 8); +} + +// multiple attributes, different search strings (one string per attrbute), regex matching +BOOST_AUTO_TEST_CASE(pool_query_105) +{ + cout << "****105****" << endl; + PoolQuery q; + q.addAttribute(sat::SolvAttr::name, "zy..er"); + q.addAttribute(sat::SolvAttr::summary, "package management"); + q.setMatchRegex(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 8); +} + +///////////////////////////////////////////////////////////////////////////// +// 3xx repo filter queries (addRepo(alias_str)) +///////////////////////////////////////////////////////////////////////////// + +// default query + one attribute(one string) + one repo +BOOST_AUTO_TEST_CASE(pool_query_300) +{ + cout << "****300****" << endl; + PoolQuery q; + q.addAttribute(sat::SolvAttr::name, "zypper"); + q.addRepo("zyppsvn"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 4); +} + +// default query + one repo +BOOST_AUTO_TEST_CASE(pool_query_301) +{ + cout << "****301****" << endl; + PoolQuery q; + q.addRepo("zyppsvn"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 42); +} + +// multiple repos + one attribute +BOOST_AUTO_TEST_CASE(pool_query_302) +{ + cout << "****302****" << endl; + PoolQuery q; + q.addString("zypper"); + q.addAttribute(sat::SolvAttr::name); + q.addRepo("opensuse"); + q.addRepo("zyppsvn"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 5); +} + +///////////////////////////////////////////////////////////////////////////// +// 4xx kind queries (addKind(ResKind)) +///////////////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(pool_query_400) +{ + cout << "****400****" << endl; + PoolQuery q; + q.addString("lamp_server"); + q.addAttribute(sat::SolvAttr::name); + q.addKind(ResKind::pattern); + q.setMatchExact(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1); +} + +// should find packages and patterns +BOOST_AUTO_TEST_CASE(pool_query_401) +{ + cout << "****401****" << endl; + PoolQuery q; + q.addString("mail*"); + q.addAttribute(sat::SolvAttr::name); + q.setMatchGlob(); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 4); +} + + +///////////////////////////////////////////////////////////////////////////// +// 5xx multiple string/attribute queries +///////////////////////////////////////////////////////////////////////////// + +// multiple strings for one attribute +BOOST_AUTO_TEST_CASE(pool_query_500) +{ + cout << "****500.1****" << endl; + PoolQuery q; + q.addString("zypper"); + q.addString("yast2-packager"); + q.addAttribute(sat::SolvAttr::name); + q.setMatchExact(); + // creates: ^(apt|zypper)$ + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 6); + + cout << "****500.2****" << endl; + q.addString("*bzypp"); + q.setMatchGlob(); + // creates: ^(.*zy.p|yast.*package.*|.*bzypp)$ + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 11); + + cout << "****500.3****" << endl; + PoolQuery q1; + q1.addString("^libsm[a-z]*[0-9]$"); + q1.addAttribute(sat::SolvAttr::name, "bzypp$"); + q1.addKind(ResKind::package); + q1.setMatchRegex(); + // creates: (^libsm[a-z]*[0-9]$|bzypp$) + BOOST_CHECK(std::for_each(q1.begin(), q1.end(), PrintAndCount())._count == 5); + + cout << "****500.4****" << endl; + PoolQuery q2; + q2.addString("Thunder"); + q2.addAttribute(sat::SolvAttr::name, "sun"); + q2.addKind(ResKind::package); + q2.addRepo("opensuse"); + q2.setCaseSensitive(); + // creates: (sun|Thunder) + BOOST_CHECK(std::for_each(q2.begin(), q2.end(), PrintAndCount())._count == 3); + + cout << "****500.5****" << endl; + PoolQuery q3; + q3.addString("audio"); + q3.addAttribute(sat::SolvAttr::name, "zip"); + q3.addKind(ResKind::package); + q3.addRepo("opensuse"); + q3.setMatchWord(); + // creates: \b(zip|audio)\b + BOOST_CHECK(std::for_each(q3.begin(), q3.end(), PrintAndCount())._count == 3); +} + +// multiple strings, multiple attributes, same strings +BOOST_AUTO_TEST_CASE(pool_query_501) +{ + cout << "****501****" << endl; + PoolQuery q; + q.addString("Thunder"); + q.addString("storm"); + q.addAttribute(sat::SolvAttr::name); + q.addAttribute(sat::SolvAttr::description); + q.addKind(ResKind::package); + q.addRepo("opensuse"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 14); +} + +// multiple strings, multiple attributes, same strings +BOOST_AUTO_TEST_CASE(pool_query_502) +{ + cout << "****502****" << endl; + PoolQuery q; + q.addString("weather"); + q.addAttribute(sat::SolvAttr::name, "thunder"); + q.addAttribute(sat::SolvAttr::description, "storm"); + q.addKind(ResKind::package); + q.addRepo("opensuse"); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 13); +} + +///////////////////////////////////////////////////////////////////////////// +// 6xx queries with edition +///////////////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(pool_query_X) +{ + cout << "****600.1****" << endl; + PoolQuery q; + q.addAttribute(sat::SolvAttr::name, "zypper"); + q.setMatchExact(); + q.setEdition(Edition("0.12.5"), Rel::GT); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 4); + + cout << "****600.2****" << endl; + q.setEdition(Edition("0.12.5"), Rel::LT); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 0); + + cout << "****600.3****" << endl; + q.setEdition(Edition("0.12.5"), Rel::LE); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1); + + cout << "****600.4****" << endl; + q.setEdition(Edition("0.12.5-5"), Rel::LT); + + BOOST_CHECK(std::for_each(q.begin(), q.end(), PrintAndCount())._count == 1); +} + +BOOST_AUTO_TEST_CASE(pool_query_X1) +{ + cout << "****601.****" << endl; + PoolQuery q; + q.addString("zypper"); + q.addAttribute(sat::SolvAttr::name ); + BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 5); + + q.setEdition(Edition("0.12.8"), Rel::GE); + BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 4); +} + +BOOST_AUTO_TEST_CASE(pool_query_X2) +{ + cout << "****X****" << endl; + PoolQuery q; + q.setMatchGlob(); + q.addString("zypp*"); + q.addAttribute(sat::SolvAttr::name); + + BOOST_CHECK_EQUAL(std::for_each(q.begin(), q.end(), PrintAndCount())._count, 5); +} + + +BOOST_AUTO_TEST_CASE(pool_query_recovery) +{ + Pathname testfile(TESTS_SRC_DIR); + testfile += "/zypp/data/PoolQuery/savedqueries"; + cout << "****recovery****" << endl; + + std::vector queries; + std::insert_iterator > ii( queries,queries.begin()); + readPoolQueriesFromFile(testfile,ii); + BOOST_REQUIRE_MESSAGE(queries.size() == 2, "Bad count of read queries."); + + BOOST_CHECK_EQUAL(queries[0].size(), 8); + + PoolQuery q; + q.addString("ma*"); + q.addRepo("opensuse"); + q.addKind(ResKind::patch); + q.setMatchRegex(); + q.setCaseSensitive(); + q.setUninstalledOnly(); + q.setEdition(Edition("0.8.3"),Rel::NE); + BOOST_CHECK(q == queries[1]); +} + +BOOST_AUTO_TEST_CASE(pool_predicated_matcher) +{ + cout << "****predicated_matcher****" << endl; + { + PoolQuery q; + q.setMatchExact(); + + q.addDependency( sat::SolvAttr::name, "zy*", Rel::ANY, Edition(), Arch_empty ); + BOOST_CHECK_EQUAL( q.size(), 0 ); + + q.addDependency( sat::SolvAttr::name, "zy*", Rel::ANY, Edition(), Arch_empty, Match::GLOB ); + BOOST_CHECK_EQUAL( q.size(), 5 ); // 5 more + + q.addDependency( sat::SolvAttr::name, "^kde.*-zh", Rel::ANY, Edition(), Arch_noarch, Match::REGEX ); + BOOST_CHECK_EQUAL( q.size(), 9 ); // 4 more + + q.addDependency( sat::SolvAttr::name, "kde.*-zh", Rel::ANY, Edition(), Arch_noarch, Match::REGEX ); + BOOST_CHECK_EQUAL( q.size(), 10 ); // 1 more + } +} + +BOOST_AUTO_TEST_CASE(pool_query_serialize) +{ + std::vector queries; + { + PoolQuery q; + q.addString( "ma" ); + q.addAttribute( sat::SolvAttr::name ); + q.addRepo( "factory-nonoss" ); + q.addRepo( "zypp_svn" ); + queries.push_back( q ); + } + { + PoolQuery q; + q.addAttribute( sat::SolvAttr::name, "ma" ); + q.addRepo( "factory-nonoss" ); + q.addRepo( "zypp_svn" ); + queries.push_back( q ); + } + { + PoolQuery q; + q.setMatchExact(); + q.addAttribute( sat::SolvAttr::name, "ma" ); + q.addDependency( sat::SolvAttr::name, "nn", Rel::EQ, Edition("nne-nnr"), Arch_noarch ); + q.addDependency( sat::SolvAttr::name, "nx", Rel::EQ, Edition("nxe-nxr"), Arch_noarch, Match::REGEX ); + q.addDependency( sat::SolvAttr::requires, "rn", Rel::EQ, Edition("rne-rnr"), Arch_noarch ); + q.addDependency( sat::SolvAttr::requires, "rx", Rel::EQ, Edition("rxe-rxr"), Arch_noarch, Match::GLOB ); + queries.push_back( q ); + } + + cout << "****serialize****" << endl; + // filesystem::TmpFile testfile; + Pathname testfile( "/tmp/testfile" ); + writePoolQueriesToFile( testfile, queries.begin(), queries.end() ); + + std::vector recovered; + std::insert_iterator> ii( recovered, recovered.end() ); + readPoolQueriesFromFile( testfile, ii ); + + BOOST_REQUIRE_EQUAL( queries.size(), recovered.size() ); + for ( unsigned i = 0U; i < queries.size(); ++i ) + { + BOOST_CHECK_EQUAL( queries[i], recovered[i] ); + } +} +// test matching +BOOST_AUTO_TEST_CASE(pool_query_equal) +{ + cout << "****equal****" << endl; + std::vector v; + { + PoolQuery q; + v.push_back( q ); + } + { + PoolQuery q; + q.addAttribute( sat::SolvAttr::name, "zypper" ); + q.setMatchExact(); + q.setCaseSensitive(true); + v.push_back( q ); + } + { + PoolQuery q; + q.addAttribute( sat::SolvAttr::name, "libzypp" ); // different + q.setMatchExact(); + q.setCaseSensitive(true); + v.push_back( q ); + } + { + PoolQuery q; + q.addAttribute( sat::SolvAttr::vendor, "zypper" ); // different + q.setMatchExact(); + q.setCaseSensitive(true); + v.push_back( q ); + } + { + PoolQuery q; + q.addAttribute( sat::SolvAttr::name, "zypper" ); + q.setMatchExact(); + q.setCaseSensitive(false); // different + v.push_back( q ); + } + { + PoolQuery q; + q.addAttribute( sat::SolvAttr::name, "zypper" ); + q.setMatchSubstring(); // different + q.setCaseSensitive(true); + v.push_back( q ); + } + { + PoolQuery q; + q.addDependency( sat::SolvAttr::provides, "zypper" ); + v.push_back( q ); + } + { + PoolQuery q; + q.addDependency( sat::SolvAttr::provides, "zypper", Rel::GT, Edition("1.0") ); + v.push_back( q ); + } + { + PoolQuery q; + q.addDependency( sat::SolvAttr::provides, "zypper", Rel::GT, Edition("2.0") ); + v.push_back( q ); + } + + for (size_t li = 0; li < v.size(); ++li) + { + for (size_t ri = 0; ri < v.size(); ++ri) + { + COUT << li << " <> " << ri << endl; + bool equal( v[li] == v[ri] ); + bool nequal( v[li] != v[ri] ); + BOOST_CHECK_EQUAL( equal, li==ri ); + BOOST_CHECK_EQUAL( equal, !nequal ); + } + } +} + +///////////////////////////////////////////////////////////////////////////// +// Dependency Query +///////////////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(addDependency) +{ + { + cout << "****addDependency1****" << endl; + PoolQuery q; + q.setCaseSensitive( false ); + q.setMatchSubstring(); + q.addString( "libzypp" ); + q.addDependency( sat::SolvAttr::provides, "FOO" ); // ! finds 'perl(CPAN::InfoObj)' 'foO' + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 13 ); + } + { + cout << "****addDependency2****" << endl; + PoolQuery q; + q.setCaseSensitive( false ); + q.setMatchSubstring(); + q.addString( "libzypp" ); + q.addDependency( sat::SolvAttr::provides, "FOO", Rel::GT, Edition("5.0") ); + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 7 ); + } + { + cout << "****addDependency2a****" << endl; + PoolQuery q; + q.setCaseSensitive( false ); + q.setMatchSubstring(); + q.addDependency( sat::SolvAttr::provides, "libzypp", Rel::GT, Edition("5.0") ); + q.addAttribute( sat::SolvAttr::arch, Arch_i586.asString() ); // OR with arch i585 + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 66 ); + } + { + cout << "****addDependency2b****" << endl; + PoolQuery q; + q.setCaseSensitive( false ); + q.setMatchSubstring(); + // libzypp provides yast2-packagemanager... + q.addDependency( sat::SolvAttr::provides, "yast2-packagemanager", Rel::GT, Edition("5.0"), Arch_i586 ); // AND with arch i585 + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 2 ); + } + { + cout << "****addDependency2c****" << endl; + PoolQuery q; + q.setCaseSensitive( false ); + q.setMatchSubstring(); + // but no package named yast2-packagemanager + q.addDependency( sat::SolvAttr::name, "yast2-packagemanager", Rel::GT, Edition("5.0"), Arch_i586 ); // AND with arch i585 + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 0 ); + } + { + cout << "****addDependency2d****" << endl; + PoolQuery q; + q.setCaseSensitive( false ); + q.setMatchSubstring(); + // libzypp provides yast2-packagemanager... + q.addDependency( sat::SolvAttr::provides, "yast2-packagemanager", Arch_i586 ); // AND with arch i585 + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 2 ); + } + { + cout << "****addDependency2e****" << endl; + PoolQuery q; + q.setCaseSensitive( false ); + q.setMatchSubstring(); + // but no package named yast2-packagemanager + q.addDependency( sat::SolvAttr::name, "yast2-packagemanager", Arch_i586 ); // AND with arch i585 + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 0 ); + } + + { + cout << "****addDependency3****" << endl; + PoolQuery q; + // includes wine + q.addDependency( sat::SolvAttr::provides, "kernel" ); + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 12 ); + } + { + cout << "****addDependency4****" << endl; + PoolQuery q; + // no wine + q.addDependency( sat::SolvAttr::name, "kernel" ); + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 11 ); + } + { + cout << "****addDependency5****" << endl; + PoolQuery q; + // Capability always matches exact + q.addDependency( sat::SolvAttr::provides, Capability("kernel") ); + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 2 ); + } + { + cout << "****addDependency6****" << endl; + PoolQuery q; + // non dependecy + Capability matches solvable name! + q.addDependency( sat::SolvAttr::summary, Capability("kernel") ); + std::for_each(q.begin(), q.end(), PrintAndCount()); + //dumpQ( std::cout, q ); + BOOST_CHECK_EQUAL( q.size(), 0 ); // non dependecy + } +} + +namespace +{ + std::string q2str( const PoolQuery & q_r ) + { + str::Str s; + q_r.serialize( s.stream() ); + return s; + } + + template + void str2q( const std::string & s_r, OutputIterator out_r ) + { + std::istringstream s( s_r ); + do { + PoolQuery q; + if ( q.recover( s ) ) + *out_r++ = std::move(q); + else + break; + } while ( true ); + } + + typedef std::set Pqs; + + PoolQuery str2q( const std::string & s_r ) + { + Pqs ret; + str2q( s_r, std::insert_iterator( ret, ret.end() ) ); + return *ret.begin(); + } + + + std::string serialized( const std::string & arg_r ) + { return "\n" + arg_r + "\n\n"; } + + template + std::string serialized( const std::string & arg_r, Args... args_r ) + { return "\n" + arg_r + serialized( args_r... ); } + + + void testSerializeAndBack( const PoolQuery & q_r, const PoolQuery & expect_r, bool equal_r = true ) + { + static unsigned i = 0; + + std::string s { q2str( q_r ) }; + PoolQuery q { str2q( s ) }; + BOOST_CHECK_EQUAL( (q == expect_r), equal_r ); + + if ( ++i && (q == expect_r) != equal_r ) + { + cout << "+++" << endl; + cout << q << endl; + cout << "=== " << i << " ^v SerializeAndBack == " << equal_r << endl; + cout << expect_r << endl; + cout << "---" << endl; + } + } +} + +BOOST_AUTO_TEST_CASE(zypperLocksSerialize) +{ + // Fix/cleanup zypper locks (old style, new stule, complex) (bsc#1112911) + // As you may notice: locks (by now) ignore any arch component + cout << "****zypperLocksSerialize****" << endl; + std::string n { "n*" }; + Rel o { Rel::EQ }; + Edition e { "v", "r", 1 }; + Arch a { "a" }; + + { + // old style + // solvable_name: n* + PoolQuery oldq; + oldq.addAttribute( sat::SolvAttr::name, n ); + testSerializeAndBack( oldq, oldq ); + + { // new style + PoolQuery q; + q.addDependency( sat::SolvAttr::name, n, Rel::ANY, Edition(), Arch_empty ); + testSerializeAndBack( q, oldq ); + } + + { // new style + arch rule however stays complex + PoolQuery q; + q.addDependency( sat::SolvAttr::name, n, Rel::ANY, Edition(), a ); + testSerializeAndBack( q, oldq, false ); + testSerializeAndBack( q, q ); + } + } + + { + // old style + // solvable_name: n* + // version: == 1:v-r + PoolQuery oldq; + oldq.addAttribute( sat::SolvAttr::name, n ); + oldq.setEdition( e, o ); + testSerializeAndBack( oldq, oldq ); + + { // new style + PoolQuery q; + q.addDependency( sat::SolvAttr::name, n, o, e, Arch_empty ); + testSerializeAndBack( q, oldq ); + } + + { // new style + arch rule however stays complex + PoolQuery q; + q.addDependency( sat::SolvAttr::name, n, o, e, a ); + testSerializeAndBack( q, oldq, false ); + testSerializeAndBack( q, q ); + } + } +} diff --git a/tests/zypp/ProgressData_test.cc b/tests/zypp/ProgressData_test.cc new file mode 100644 index 0000000..b96cce7 --- /dev/null +++ b/tests/zypp/ProgressData_test.cc @@ -0,0 +1,129 @@ + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +using boost::unit_test::test_case; +using std::cout; +using std::endl; + +using namespace zypp; + +BOOST_AUTO_TEST_CASE(progressdata_test) +{ + { + ProgressData progress(100); + CombinedProgressData sub1rcv(progress, 80); + + ProgressData sub1progress(100); + sub1progress.sendTo(sub1rcv); + + // task 1 goes to 50% + sub1progress.set(50); + // which is 50% of 80% in task 1 + BOOST_CHECK_EQUAL( progress.val(), 40 ); + } + + { + ProgressData progress(40000); + CombinedProgressData sub2rcv(progress, 10000); + + ProgressData sub2progress(500); + sub2progress.sendTo(sub2rcv); + sub2progress.set(250); + + // which is 50% of 80% in task 1 + BOOST_CHECK_EQUAL( progress.val(), 5000 ); + } + + { + ProgressData progress(20000,60000); + CombinedProgressData sub2rcv(progress, 10000); + + ProgressData sub2progress(500); + sub2progress.sendTo(sub2rcv); + sub2progress.set(250); + + // which is 50% of 80% in task 1 + BOOST_CHECK_EQUAL( progress.val(), 25000 ); + } + +} + +// Check expected ProgressReport triggers: +// none | (start progress) progress* (progress end) +struct PReceive : public callback::ReceiveReport +{ + int frame = 0; // 0 -start-> 1(progress) -finish-> 2 + int pings = 0; // count progress triggers + + void reportbegin() override + { + // cout << "REPORT+++" << endl; + frame = pings = 0; + } + + void start( const ProgressData & task ) override + { + // cout << "REPBEG " << task << " " << frame <<":"<< pings << endl; + BOOST_CHECK_EQUAL( frame, 0 ); + BOOST_CHECK_EQUAL( pings, 0 ); + frame = 1; + pings -= 1; // start must be followed by 1 progress + } + + bool progress( const ProgressData & task ) override + { + // cout << "REP... " << task << " " << frame <<":"<< pings << endl; + BOOST_CHECK_EQUAL( frame, 1 ); // progress + pings += 1; + return true; + } + + void finish( const ProgressData & task ) override + { + // cout << "REPEND " << task << " " << frame <<":"<< pings << endl; + BOOST_CHECK_EQUAL( frame, 1 ); + frame = 2; + pings -= 1; // finish must be preceded by 1 progress + } + + void reportend() override + { + // cout << "REPORT--- " << " " << frame <<":"<< pings << endl; + BOOST_CHECK( ( frame == 0 && pings == 0 ) || ( frame == 2 && pings >= 0 ) ); + } +}; + +BOOST_AUTO_TEST_CASE(progress_report) +{ + PReceive preceive; + preceive.connect(); + { + callback::SendReport report; + ProgressData ticks; + ticks.sendTo( ProgressReportAdaptor( report ) ); + ticks.range( 5 ); + } + BOOST_CHECK_EQUAL( preceive.frame, 0 ); // If no value was set no reports were sent. + + { + callback::SendReport report; + ProgressData ticks; + ticks.sendTo( ProgressReportAdaptor( report ) ); + ticks.range( 5 ); + ticks.toMin(); + ticks.set(3); + ticks.toMax(); + } + BOOST_CHECK_EQUAL( preceive.frame, 2 ); // Values were set, so finish was sent. + +} diff --git a/tests/zypp/Proxy_test.cc b/tests/zypp/Proxy_test.cc new file mode 100644 index 0000000..4951170 --- /dev/null +++ b/tests/zypp/Proxy_test.cc @@ -0,0 +1,19 @@ +#include + +#include +#include + +// compile time check that the libproxy API in the distro we are building against +// is actually what we want +BOOST_AUTO_TEST_CASE(proxy_api) +{ + static_assert( std::is_same_v > ); + static_assert( std::is_same_v > ); + static_assert( std::is_same_v > ); +#ifdef LIBPROXY_HAVE_FREE_PROXIES + static_assert( std::is_same_v ); +#endif + + // make sure symbols can be resolved + BOOST_REQUIRE( zypp::media::ProxyInfoLibproxy::isAvailabe() ); +} diff --git a/tests/zypp/PtrTypes_test.cc b/tests/zypp/PtrTypes_test.cc new file mode 100644 index 0000000..dfae8c2 --- /dev/null +++ b/tests/zypp/PtrTypes_test.cc @@ -0,0 +1,152 @@ +#include + +#include + +#include +#include +#include +#include + +#define BOOST_TEST_MODULE PtrTypes + +using std::endl; +using namespace zypp; +using namespace zypp::base; + + +#define TRACE_TAG DBG << this->numericId() << " " << __PRETTY_FUNCTION__ << endl + +/** Logs Ctor, CopyCtor, Assign and Dtor. */ +template + struct Trace : public ProvideNumericId + { + Trace() { TRACE_TAG; } + Trace( const Trace & ) { TRACE_TAG; } + ~Trace() { TRACE_TAG; } + Trace & operator=( const Trace & ) { TRACE_TAG; return *this; } + }; + +/** Data class for shared_ptr */ +struct NonIntrusive : private Trace +{ + using Trace::numericId; +}; + +/** Data class for intrusive_ptr */ +struct Intrusive : public ReferenceCounted, + private Trace +{ + using Trace::numericId; +}; + +namespace zypp +{ + template<> + inline NonIntrusive * rwcowClone( const NonIntrusive * rhs ) + { return new NonIntrusive( *rhs ); } + + template<> + inline Intrusive * rwcowClone( const Intrusive * rhs ) + { return new Intrusive( *rhs ); } + +} + +/****************************************************************** +** +*/ +#define T_NULL assert( !ptr ); assert( ptr == nullptr ) +#define T_NOT_NULL assert( ptr ); assert( ptr != nullptr ) +#define T_UNIQUE assert( ptr.unique() ); assert( ptr.use_count() < 2 ) +#define T_NOT_UNIQUE assert( !ptr.unique() ); assert( ptr.use_count() >= 2 ) +// Also comapre with underlying shared ptr type. +#define T_EQ(a,b) assert( a == b ); assert( a == b.cgetPtr() ); assert( a.cgetPtr() == b ); assert( a.cgetPtr() == b.cgetPtr() ); +#define T_NE(a,b) assert( a != b ); assert( a != b.cgetPtr() ); assert( a.cgetPtr() != b ); assert( a.cgetPtr() != b.cgetPtr() ); + +template + void test() + { + MIL << __PRETTY_FUNCTION__ << std::endl; + // typedefs that should be provided: + typedef typename RW::PtrType Ptr; + typedef typename RW::constPtrType constPtr; + typedef typename Ptr::element_type Ptr_element_type; + typedef typename constPtr::element_type constPtr_element_type; + // initial NULL + RW ptr; + T_NULL; + T_UNIQUE; + T_EQ(ptr,ptr); + // assign + ptr = RW( new Ptr_element_type ); + T_NOT_NULL; + T_UNIQUE; + T_EQ(ptr,ptr); + { + // share + RW ptr2( ptr ); + T_NOT_NULL; + T_NOT_UNIQUE; + T_EQ(ptr,ptr2); + // unshare + ptr2.reset(); + T_NOT_NULL; + T_UNIQUE; + T_NE(ptr,ptr2); + // different impl + ptr2.reset( new Ptr_element_type ); + T_NE(ptr,ptr2); + } + // assign + ptr.reset( 0 ); + T_NULL; + T_UNIQUE; + // nullptr compatible + ptr.reset( nullptr ); + T_NULL; + T_UNIQUE; + ptr = nullptr; + T_NULL; + T_UNIQUE; + ptr = RW( nullptr ); + T_NULL; + T_UNIQUE; + + + } + +template + void cowt() + { + test(); + MIL << __PRETTY_FUNCTION__ << std::endl; + typedef typename RW::PtrType::element_type Ptr_element_type; + // create + RW ptr( new Ptr_element_type ); + unsigned long ptrid = ptr->numericId(); + // share + RW ptr2( ptr ); + // clone aon access + unsigned long ptrid2 = ptr2->numericId(); + assert( ptrid != ptrid2 ); + } + +/****************************************************************** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +*/ +BOOST_AUTO_TEST_CASE(basic_test) +{ + MIL << "===[START]=====" << endl; + test > >(); + test > >(); + test > >(); + test > >(); + + cowt > >(); + cowt > >(); + cowt > >(); + cowt > >(); + + MIL << "===[DONE]=====" << endl; +} diff --git a/tests/zypp/PublicKey_test.cc b/tests/zypp/PublicKey_test.cc new file mode 100644 index 0000000..fc67878 --- /dev/null +++ b/tests/zypp/PublicKey_test.cc @@ -0,0 +1,54 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/data/PublicKey") + +BOOST_AUTO_TEST_CASE(publickey_test) +{ + // test for a empty key + zypp::PublicKey empty_key; + BOOST_REQUIRE( ! empty_key.isValid() ); + + BOOST_CHECK_THROW( zypp::PublicKey("nonexistent"), Exception ); + + zypp::PublicKey k2(DATADIR/"susekey.asc"); + BOOST_CHECK_EQUAL( k2.id(), "A84EDAE89C800ACA" ); + BOOST_CHECK_EQUAL( k2.name(), "SuSE Package Signing Key " ); + BOOST_CHECK_EQUAL( k2.fingerprint(), "79C179B2E1C820C1890F9994A84EDAE89C800ACA" ); + BOOST_CHECK_EQUAL( k2.gpgPubkeyVersion(), "9c800aca" ); + BOOST_CHECK_EQUAL( k2.gpgPubkeyRelease(), "40d8063e" ); + BOOST_CHECK_EQUAL( k2.created(), zypp::Date(1087899198) ); + BOOST_CHECK_EQUAL( k2.expires(), zypp::Date(1214043198) ); +//BOOST_CHECK_EQUAL( k2.daysToLive(), "" ); + BOOST_REQUIRE( k2.path() != Pathname() ); + BOOST_REQUIRE( k2 == k2 ); + + k2 = zypp::PublicKey(DATADIR/"multikey.asc"); + BOOST_CHECK_EQUAL( k2.id(), "27FA41BD8A7C64F9" ); + BOOST_CHECK_EQUAL( k2.name(), "Unsupported " ); + BOOST_CHECK_EQUAL( k2.fingerprint(), "D88811AF6B51852351DF538527FA41BD8A7C64F9" ); + BOOST_CHECK_EQUAL( k2.gpgPubkeyVersion(), "8a7c64f9" ); + BOOST_CHECK_EQUAL( k2.gpgPubkeyRelease(), "4be01af3" ); + BOOST_CHECK_EQUAL( k2.created(), zypp::Date(1272978163) ); + BOOST_CHECK_EQUAL( k2.expires(), zypp::Date(1399122163) ); + + k2 = zypp::PublicKey(DATADIR/"multikey2.asc"); + BOOST_CHECK_EQUAL( k2.hiddenKeys().size(), 8 ); +} + diff --git a/tests/zypp/PurgeKernels_test.cc b/tests/zypp/PurgeKernels_test.cc new file mode 100644 index 0000000..4f6c0a1 --- /dev/null +++ b/tests/zypp/PurgeKernels_test.cc @@ -0,0 +1,396 @@ +#include "TestSetup.h" +#include +#include + +#include + +using namespace zypp; +using namespace boost::unit_test; + +namespace { + // Defines a expected removal of a package and carries the flag if it actually was removed + struct ExpectedRemoval { + ExpectedRemoval( std::string &&name ) : packageNVRA(std::move(name)) {} + std::string packageNVRA; + mutable bool wasRemoved = false; + }; + + bool operator< ( const ExpectedRemoval &a, const ExpectedRemoval &b ) { + return a.packageNVRA < b.packageNVRA; + } +} + +namespace boost { namespace test_tools { namespace tt_detail { +template<> +struct print_log_value< std::set > { +void operator()( std::ostream& ostr, + std::set const& set) +{ + ostr << "{" << std::endl; + for( const auto &elem : set ) ostr << "'" << elem.packageNVRA << "'," << std::endl; + ostr << "}" << std::endl; +} +}; +}}} + +namespace { + std::string makeNVRA( const PoolItem &pck ) { + return pck.name() + "-" + pck.edition().asString() + "." + pck.arch().asString(); + } + + using TestSample = std::tuple< + Pathname, // repoPath + std::string, // uname_r + zypp::Arch, // arch + std::string, // keepSpec + std::set // expectedRems + >; + + std::vector maketestdata() { + return { + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/simple", + "1-3-default", + Arch("x86_64"), + "oldest,running,latest", + { + { "kernel-default-1-2.x86_64" }, + { "kernel-default-devel-1-2.x86_64" }, + { "kernel-default-devel-debuginfo-1-2.x86_64" }, + { "kernel-devel-1-2.noarch" }, + { "kernel-livepatch-default-1-2.x86_64" }, + { "kernel-syms-1-2.x86_64" }, + { "kernel-default-1-4.x86_64" }, + { "kernel-default-devel-1-4.x86_64" }, + { "kernel-default-devel-debuginfo-1-4.x86_64" }, + { "kernel-devel-1-4.noarch" }, + { "kernel-syms-1-4.x86_64" }, + // left over devel packages that need to go away too + { "kernel-devel-1-1.2.noarch" }, + { "kernel-source-1-1.2.noarch" }, + { "kernel-default-devel-1-3.x86_64" }, + { "kernel-default-devel-debuginfo-1-3.x86_64" }, + { "kernel-devel-1-3.noarch" }, + } + }, + //test that keeps only the running kernel + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/simple", + "1-3-default", + Arch("x86_64"), + "running", + { + { "kernel-default-1-1.x86_64" }, + { "kernel-default-devel-1-1.x86_64" }, + { "kernel-default-devel-debuginfo-1-1.x86_64" }, + { "kernel-livepatch-default-1-1.x86_64" }, + { "kernel-devel-1-1.noarch" }, + { "kernel-syms-1-1.x86_64" }, + { "kernel-source-1-1.noarch" }, + { "kernel-default-1-2.x86_64" }, + { "kernel-default-devel-1-2.x86_64" }, + { "kernel-default-devel-debuginfo-1-2.x86_64" }, + { "kernel-devel-1-2.noarch" }, + { "kernel-livepatch-default-1-2.x86_64" }, + { "kernel-syms-1-2.x86_64" }, + { "kernel-default-1-4.x86_64" }, + { "kernel-default-devel-1-4.x86_64" }, + { "kernel-default-devel-debuginfo-1-4.x86_64" }, + { "kernel-devel-1-4.noarch" }, + { "kernel-syms-1-4.x86_64" }, + { "kernel-default-1-5.x86_64" }, + { "kernel-default-devel-1-5.x86_64" }, + { "kernel-default-devel-debuginfo-1-5.x86_64" }, + { "kernel-devel-1-5.noarch" }, + { "kernel-syms-1-5.x86_64" }, + { "dummy-kmp-default-1-0.x86_64" }, + // left over devel packages that need to go away too + { "kernel-devel-1-1.2.noarch" }, + { "kernel-source-1-1.2.noarch" }, + { "kernel-default-devel-1-3.x86_64" }, + { "kernel-devel-1-3.noarch" }, + { "kernel-default-devel-1-3.x86_64" }, + { "kernel-default-devel-debuginfo-1-3.x86_64" }, + } + }, + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/simple", + "1-3-default", + Arch("x86_64"), + "oldest+1,running,latest-1", + { + { "kernel-default-1-1.x86_64" }, + { "kernel-livepatch-default-1-1.x86_64" }, + { "kernel-default-devel-1-1.x86_64" }, + { "kernel-default-devel-debuginfo-1-1.x86_64" }, + { "kernel-devel-1-1.noarch" }, + { "kernel-syms-1-1.x86_64" }, + { "kernel-source-1-1.noarch" }, + { "kernel-default-1-5.x86_64" }, + { "kernel-default-devel-1-5.x86_64" }, + { "kernel-default-devel-debuginfo-1-5.x86_64" }, + { "kernel-devel-1-5.noarch" }, + { "kernel-syms-1-5.x86_64" }, + { "dummy-kmp-default-1-0.x86_64" }, + // left over devel packages that need to go away too + { "kernel-default-devel-1-3.x86_64" }, + { "kernel-default-devel-debuginfo-1-3.x86_64" }, + { "kernel-devel-1-3.noarch" }, + } + }, + TestSample { + //kernel-1-1 has a non kernel package depending on it, it should not be removed + TESTS_SRC_DIR"/zypp/data/PurgeKernels/withdeps", + "1-5-default", + Arch("x86_64"), + "running", + { + { "kernel-default-1-2.x86_64" }, + { "kernel-default-extra-1-2.x86_64" }, + { "kernel-default-devel-1-2.x86_64" }, + { "kernel-default-devel-debuginfo-1-2.x86_64" }, + { "kernel-devel-1-2.noarch" }, + { "kernel-livepatch-default-1-2.x86_64" }, + { "kernel-syms-1-2.x86_64" }, + // the following packages are not held back because they do not fit keep spec and no deps are keeping them + { "kernel-default-devel-1-1.x86_64" }, + { "kernel-default-devel-debuginfo-1-1.x86_64" }, + { "kernel-devel-1-1.noarch" }, + { "kernel-syms-1-1.x86_64" }, + } + }, + TestSample { + //kernel-1-5 provides a symbol for a kmp that has a non kernel package depending on it, it should not be removed + TESTS_SRC_DIR"/zypp/data/PurgeKernels/withdeps", + "1-1-default", + Arch("x86_64"), + "running", + { + { "kernel-default-1-2.x86_64" }, + { "kernel-default-extra-1-2.x86_64" }, + { "kernel-default-devel-1-2.x86_64" }, + { "kernel-default-devel-debuginfo-1-2.x86_64" }, + { "kernel-devel-1-2.noarch" }, + { "kernel-livepatch-default-1-2.x86_64" }, + { "kernel-syms-1-2.x86_64" }, + { "kernel-default-devel-1-5.x86_64" }, + { "kernel-default-devel-debuginfo-1-5.x86_64" }, + { "kernel-devel-1-5.noarch" }, + { "kernel-syms-1-5.x86_64" }, + } + }, + TestSample { + //kernel-1-2 is explicitly in the keep spec, it should not be removed + //kernel-1-5 provides a symbol for a kmp that has a non kernel package depending on it, it should not be removed + TESTS_SRC_DIR"/zypp/data/PurgeKernels/withdeps", + "1-1-default", + Arch("x86_64"), + "running,1-2", + { + { "kernel-default-devel-1-5.x86_64" }, + { "kernel-default-devel-debuginfo-1-5.x86_64" }, + { "kernel-devel-1-5.noarch" }, + { "kernel-syms-1-5.x86_64" }, + } + }, + TestSample { + //kernel-default-1-1.x86_64 is the running kernel it should not be removed, + //in all sets with different arch only the latest should be kept + TESTS_SRC_DIR"/zypp/data/PurgeKernels/arch", + "1-1-default", + Arch("x86_64"), + "latest,running", + { + { "kernel-default-1-1.aarch64" }, + { "kernel-default-1-1.i686" }, + + //{ "kernel-syms-1-1.x86_64" }, + //{ "kernel-default-devel-1-1.x86_64" }, + //{ "kernel-default-devel-debuginfo-1-1.x86_64" }, + + { "kernel-default-1-2.aarch64" }, + { "kernel-default-1-2.i686" }, + { "kernel-default-1-2.x86_64" }, + + { "kernel-default-devel-1-1.aarch64" }, + { "kernel-default-devel-1-1.i686" }, + { "kernel-default-devel-1-2.aarch64" }, + { "kernel-default-devel-1-2.i686" }, + { "kernel-default-devel-1-2.x86_64" }, + + { "kernel-default-devel-debuginfo-1-1.aarch64" }, + { "kernel-default-devel-debuginfo-1-1.i686" }, + { "kernel-default-devel-debuginfo-1-2.aarch64" }, + { "kernel-default-devel-debuginfo-1-2.i686" }, + { "kernel-default-devel-debuginfo-1-2.x86_64" }, + + { "kernel-devel-1-2.noarch" }, + + { "kernel-livepatch-default-1-2.aarch64" }, + { "kernel-livepatch-default-1-2.i686" }, + { "kernel-livepatch-default-1-2.x86_64" }, + + { "kernel-syms-1-1.aarch64" }, + { "kernel-syms-1-1.i686" }, + + { "kernel-syms-1-2.aarch64" }, + { "kernel-syms-1-2.i686" }, + { "kernel-syms-1-2.x86_64" }, + } + }, + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/rebuild", + "1-1-default", + Arch("x86_64"), + "running", + { + { "kernel-source-1-1.noarch" }, + } + }, + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/fancybuildnr", + "5.8.1-3.g846658e-default", + Arch("x86_64"), + "latest,latest-1,running", + { + { "kernel-default-5.7.8-1.1.g8f507a0.x86_64" }, + { "kernel-default-5.7.9-1.1.ga010166.x86_64" }, + { "kernel-default-5.7.10-1.1.g6a1b5cf.x86_64" }, + { "kernel-default-5.7.10-3.1.gd1148b9.x86_64" }, + { "kernel-default-5.7.11-1.1.g5015994.x86_64" }, + { "kernel-default-5.7.12-1.1.g9c98feb.x86_64" }, + { "kernel-default-5.8.0-1.1.gd3bf2d6.x86_64" }, + { "kernel-default-5.8.0-2.1.g9bc0044.x86_64" }, + { "kernel-default-5.8.0-3.1.gd4e7682.x86_64" }, + { "kernel-default-5.8.1-1.1.ge6658c9.x86_64" }, + // those are running, latest and latest-1 , they should stay + //{ "kernel-default-5.8.1-2.1.g553537d.x86_64" }, + //{ "kernel-default-5.8.1-3.1.g846658e.x86_64" }, + } + }, + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/kernel-base", + "5.7.8-3-default", + Arch("x86_64"), + "running", + { + { "kernel-default-base-5.7.8-1.1.1.1.x86_64" }, + { "kernel-default-base-5.7.8-2.1.1.1.x86_64" }, + //{ "kernel-default-base-5.7.8-3.1.1.1.x86_64" }, + { "kernel-default-base-5.8.8-2.1.1.1.x86_64" }, + } + }, + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/kernel-base", + "5.7.8-3-default", + Arch("x86_64"), + "running, 5.7.8-2.1.1", + { + { "kernel-default-base-5.7.8-1.1.1.1.x86_64" }, + { "kernel-default-base-5.8.8-2.1.1.1.x86_64" }, + //{ "kernel-default-base-5.7.8-2.1.1.1.x86_64" }, + //{ "kernel-default-base-5.7.8-3.1.1.1.x86_64" }, + } + }, + // same test set as before, but this time the user took the uname-r kernel output + // we should ignore the -flavor in the end and just use the edition part + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/kernel-base", + "5.7.8-3-default", + Arch("x86_64"), + "running, 5.7.8-2.1.1-default", + { + { "kernel-default-base-5.7.8-1.1.1.1.x86_64" }, + { "kernel-default-base-5.8.8-2.1.1.1.x86_64" }, + //{ "kernel-default-base-5.7.8-2.1.1.1.x86_64" }, + //{ "kernel-default-base-5.7.8-3.1.1.1.x86_64" }, + } + }, + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/flavour", + "1-3-rt", + Arch("x86_64"), + "running", + { + { "kernel-rt-1-1.x86_64" }, + { "kernel-rt-devel-1-1.x86_64" }, + { "kernel-rt-devel-debuginfo-1-1.x86_64" }, + { "kernel-devel-rt-1-1.noarch" }, + { "kernel-syms-rt-1-1.x86_64" }, + { "kernel-source-rt-1-1.noarch" }, + { "kernel-rt-1-2.x86_64" }, + { "kernel-rt-devel-1-2.x86_64" }, + { "kernel-rt-devel-debuginfo-1-2.x86_64" }, + { "kernel-devel-rt-1-2.noarch" }, + { "kernel-syms-rt-1-2.x86_64" }, + { "kernel-rt-1-4.x86_64" }, + { "kernel-rt-devel-1-4.x86_64" }, + { "kernel-rt-devel-debuginfo-1-4.x86_64" }, + { "kernel-devel-rt-1-4.noarch" }, + { "kernel-syms-rt-1-4.x86_64" }, + { "kernel-rt-1-5.x86_64" }, + { "kernel-rt-devel-1-5.x86_64" }, + { "kernel-rt-devel-debuginfo-1-5.x86_64" }, + { "kernel-devel-rt-1-5.noarch" }, + { "kernel-syms-rt-1-5.x86_64" }, + // left over devel packages that need to go away too + { "kernel-devel-rt-1-1.2.noarch" }, + { "kernel-source-rt-1-1.2.noarch" }, + { "kernel-rt-devel-1-3.x86_64" }, + { "kernel-devel-rt-1-3.noarch" }, + { "kernel-rt-devel-1-3.x86_64" }, + { "kernel-rt-devel-debuginfo-1-3.x86_64" }, + } + }, + // rc kernels have a special naming hack because upstream uses characters that are forbidden in rpm versions + TestSample { + TESTS_SRC_DIR"/zypp/data/PurgeKernels/rckrnl", + "5.13.0-rc7-17-default", + Arch("x86_64"), + "running", + { + { "kernel-default-5.13.rc7-16.1.x86_64" }, + { "kernel-default-5.13~rc7-18.1.x86_64" } + } + }, + }; + } +} + +namespace bdata = boost::unit_test::data; + +BOOST_DATA_TEST_CASE(purge_kernels, bdata::make( maketestdata() ), repoPath, uname_r, arch, keepSpec, expectedRems ) +{ + TestSetup test( Arch_x86_64 ); + test.loadTestcaseRepos( repoPath ); + + auto expectedRemovals = expectedRems; + + PurgeKernels krnls; + krnls.setUnameR( uname_r ); + krnls.setKernelArch( arch ); + krnls.setKeepSpec( keepSpec ); + krnls.markObsoleteKernels(); + + auto pool = ResPool::instance(); + BOOST_REQUIRE( pool.resolver().resolvePool() ); + + unsigned removeCount = 0; + const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled ); + for ( auto it = pool.byStatusBegin( toBeUninstalledFilter ); it != pool.byStatusEnd( toBeUninstalledFilter ); it++ ) { + removeCount++; + + std::set::iterator pck = expectedRemovals.find( makeNVRA(*it) ); + BOOST_REQUIRE_MESSAGE( pck != expectedRemovals.end(), std::string("Unexpected package removed: ") + makeNVRA(*it) + (it->status().isByUser() ? " (by user)" : " (autoremoved)") ); + + (*pck).wasRemoved = true; + } + + for ( const auto &rem : expectedRemovals ) { + if (!rem.wasRemoved) + std::cout << std::string( "Expected package removal did not happen for: ") + rem.packageNVRA << std::endl; + //BOOST_REQUIRE_MESSAGE( rem.second, std::string( "Expected package removal did not happen for: ") + rem.first ); + } + + BOOST_REQUIRE_EQUAL( expectedRemovals.size(), removeCount ); +} diff --git a/tests/zypp/RWPtr_test.cc b/tests/zypp/RWPtr_test.cc new file mode 100644 index 0000000..ec11010 --- /dev/null +++ b/tests/zypp/RWPtr_test.cc @@ -0,0 +1,83 @@ +#include + +#include +#include +#include + +#define BOOST_TEST_MODULE RWPtr_test + +struct Foo +{ + int _foo; + + Foo(int foo=0): _foo(foo) + { + std::cerr << "created Foo(" << _foo << ")" << std::endl; + } + ~Foo() + { + std::cerr << "destroy Foo(" << _foo << ")" << std::endl; + } +}; + +#define REF_TEST(ref,msg,exp,res) \ +do { \ + bool unique = exp; \ + std::cerr << msg << std::endl; \ + if( ref) { \ + std::cerr << "ref contains object" << std::endl; \ + } else { \ + std::cerr << "ref contains no object" << std::endl; \ + } \ + std::cerr << "ref counter is " << ref.use_count() << std::endl; \ + if( ref.unique()) { \ + std::cerr << "ref is unique" << std::endl; \ + if( unique) { \ + std::cerr << "EXPECTED" << std::endl; \ + } else { \ + std::cerr << "NOT EXPECTED" << std::endl; \ + res = 1; \ + } \ + } else { \ + std::cerr << "ref is shared" << std::endl; \ + if( !unique) { \ + std::cerr << "EXPECTED" << std::endl; \ + } else { \ + std::cerr << "NOT EXPECTED" << std::endl; \ + res = 1; \ + } \ + } \ + std::cerr << std::endl; \ +} while(0); + +BOOST_AUTO_TEST_CASE(basic_test) +{ + bool skip_reset = false; + int result = 0; + + typedef zypp::RW_pointer FooRef; + + FooRef ref; + REF_TEST(ref,"=== REF(nil)", true, result); + + ref.reset(new Foo(42)); + REF_TEST(ref,"=== REF(object)", true, result); + + { + FooRef ref2(ref); + REF_TEST(ref,"=== REF2(REF)", false, result); + } + + REF_TEST(ref,"=== REF(object), REF2 out of scope now", true, result); + + if( !skip_reset) + { + ref.reset(); + REF_TEST(ref,"=== REF(nil), reset()", true, result); + } + + std::cerr << "RESULT: " + << (result == 0 ? "PASSED" : "FAILED") + << std::endl; +} + diff --git a/tests/zypp/RepoInfo_test.cc b/tests/zypp/RepoInfo_test.cc new file mode 100644 index 0000000..ba66fb6 --- /dev/null +++ b/tests/zypp/RepoInfo_test.cc @@ -0,0 +1,48 @@ + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include "KeyRingTestReceiver.h" + +#include "WebServer.h" + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; +using namespace boost::unit_test::log; + +using namespace zypp; +using namespace zypp::filesystem; +using namespace zypp::repo; + +BOOST_AUTO_TEST_CASE(repoinfo_test) +{ + WebServer web((Pathname(TESTS_SRC_DIR) + "/data/Mirrorlist/remote-site").c_str(), 10001); + BOOST_REQUIRE( web.start() ); + + Url weburl (web.url()); + weburl.setPathName("/metalink.xml"); + + RepoInfo ri; + + ri.setMirrorListUrl(weburl); + + BOOST_CHECK(ri.url().asString() == "http://ftp-stud.hs-esslingen.de/pub/fedora/linux/updates/13/x86_64/"); + + std::ostringstream ostr; + ri.dumpAsIniOn(ostr); + + BOOST_CHECK( ostr.str().find("baseurl=") == std::string::npos ); + + web.stop(); +} diff --git a/tests/zypp/RepoManager_test.cc b/tests/zypp/RepoManager_test.cc new file mode 100644 index 0000000..32343b7 --- /dev/null +++ b/tests/zypp/RepoManager_test.cc @@ -0,0 +1,288 @@ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "TestSetup.h" + +#include + + +#include "KeyRingTestReceiver.h" + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::filesystem; +using namespace zypp::repo; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/data/RepoManager") + +#define REPODATADIR (Pathname(TESTS_SRC_DIR) + "/repo/susetags/data/addon_in_subdir") + +BOOST_AUTO_TEST_CASE(refresh_addon_in_subdir) +{ + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + + // disable sgnature checking + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + keyring_callbacks.answerAcceptVerFailed(true); + keyring_callbacks.answerAcceptUnknownKey(true); + + // make sure we can refresh an addon which is in a subpath in a media url + TestSetup test( Arch_x86_64 ); + RepoInfo info; + info.setBaseUrl( REPODATADIR.asDirUrl() ); + info.setPath("/updates"); + info.setType(RepoType::YAST2); + info.setAlias("boooh"); + + test.loadRepo(info); + + // take care we actually got the data + Repository r( test.satpool().reposFind( "boooh" ) ); + BOOST_REQUIRE( r ); + BOOST_CHECK_EQUAL( r.solvablesSize(), 2 ); + BOOST_CHECK_EQUAL( r.info().type(), repo::RepoType::YAST2 ); + BOOST_CHECK( r.info().hasLicense() ); +} + +BOOST_AUTO_TEST_CASE(pluginservices_test) +{ + TmpDir tmpCachePath; + RepoManagerOptions opts( RepoManagerOptions::makeTestSetup( tmpCachePath ) ) ; + + opts.rootDir = ""; // NOTE: After all paths have been setup correctly, + // we must reset the RepoManager rootDir to prevent the plugin script + // from being executed chrooted (would require UID 0). + + opts.pluginsPath = DATADIR + "/plugin-service-lib-1"; + BOOST_CHECK(PathInfo(opts.pluginsPath / "services/service").isExist()); + + { + RepoManager manager(opts); + BOOST_REQUIRE_EQUAL(1, manager.serviceSize()); + BOOST_CHECK(manager.repoEmpty()); + + ServiceInfo service(*manager.serviceBegin()); + BOOST_CHECK_EQUAL("service", service.alias()); + BOOST_CHECK_EQUAL( (DATADIR / "/plugin-service-lib-1/services/service").asFileUrl(), service.url().asString()); + + // now refresh the service + manager.refreshServices(); + BOOST_CHECK_EQUAL((unsigned) 2, manager.repoSize()); + //std::list infos; + //manager.getRepositoriesInService("test", + // insert_iterator >(infos,infos.begin())); + //BOOST_CHECK_EQUAL(infos.size(), 2); // 2 from new repoindex + } + + // Now simulate the service changed + opts.pluginsPath = DATADIR + "/plugin-service-lib-2"; + { + RepoManager manager(opts); + BOOST_REQUIRE_EQUAL(1, manager.serviceSize()); + + ServiceInfo service(*manager.serviceBegin()); + BOOST_CHECK_EQUAL("service", service.alias()); + BOOST_CHECK_EQUAL( (DATADIR / "/plugin-service-lib-2/services/service").asFileUrl(), service.url().asString()); + // now refresh the service + manager.refreshServices(); + BOOST_CHECK_EQUAL((unsigned) 1, manager.repoSize()); + } +} + +// regression test for services bug +// if you modify a service that you just +// added and saved, the service was not associated with its +// file internally +BOOST_AUTO_TEST_CASE(service_file_link_bug) +{ + TmpDir tmpCachePath; + RepoManagerOptions opts( RepoManagerOptions::makeTestSetup( tmpCachePath ) ) ; + + filesystem::mkdir( opts.knownReposPath ); + filesystem::mkdir( opts.knownServicesPath ); + RepoManager manager(opts); + + //test service + ServiceInfo service("test", DATADIR.asDirUrl() ); + service.setEnabled(true); + + manager.addService(service); + // now internally, service is associated with the file + // where it was saved + + // the following line reset the file association with the bug + manager.modifyService(service.alias(), service); + // and the following modifyService fails because there is no + // association + manager.modifyService(service.alias(), service); +} + +BOOST_AUTO_TEST_CASE(repomanager_test) +{ + TmpDir tmpCachePath; + RepoManagerOptions opts( RepoManagerOptions::makeTestSetup( tmpCachePath ) ) ; + opts.servicesTargetDistro = "sles-10-i586"; // usually determined by the Target + + filesystem::mkdir( opts.knownReposPath ); + filesystem::mkdir( opts.knownServicesPath ); + filesystem::assert_dir( opts.rootDir/"Datadir" ); + + BOOST_CHECK_EQUAL( filesystem::copy_dir_content( DATADIR + "/repos.d", opts.knownReposPath ), 0 ); + BOOST_CHECK_EQUAL( filesystem::copy_dir_content( DATADIR, opts.rootDir/"Datadir" ), 0 ); + + RepoManager manager(opts); + + std::list repos; + repos.insert(repos.end(), manager.repoBegin(), manager.repoEnd()); + BOOST_CHECK_EQUAL(repos.size(), (unsigned) 4); + + // now add a .repo file with 2 repositories in it + manager.addRepositories( (DATADIR / "/proprietary.repo").asFileUrl() ); + + // check it was not overwriten the proprietary.repo file + BOOST_CHECK( PathInfo(opts.knownReposPath + "/proprietary.repo_1").isExist() ); + + // now there should be 6 repos + repos.clear(); + repos.insert(repos.end(), manager.repoBegin(), manager.repoEnd()); + BOOST_CHECK_EQUAL(repos.size(), (unsigned) 6); + + RepoInfo office_dup; + office_dup.setAlias("office"); + BOOST_CHECK_THROW(manager.addRepository(office_dup), RepoAlreadyExistsException); + + // delete the office repo inside the propietary_1.repo + RepoInfo office; + office.setAlias("office"); + manager.removeRepository(office); + // now there should be 5 repos + repos.clear(); + repos.insert(repos.end(), manager.repoBegin(), manager.repoEnd()); + BOOST_CHECK_EQUAL(repos.size(), (unsigned) 5); + // the file still contained one repo, so it should still exists + BOOST_CHECK( PathInfo(opts.knownReposPath + "/proprietary.repo_1").isExist() ); + + // now delete the macromedia one + RepoInfo macromedia; + macromedia.setAlias("macromedia"); + manager.removeRepository(macromedia); + BOOST_CHECK_EQUAL(manager.repoSize(), (unsigned) 4); + // the file should not exist anymore + BOOST_CHECK( ! PathInfo(opts.knownReposPath + "/proprietary.repo_1").isExist() ); + + //test service + + Url urlS( zypp::Pathname("/Datadir").asDirUrl() ); + + ServiceInfo service("test", urlS); + service.setEnabled(true); + + manager.addService(service); + manager.refreshServices(); + BOOST_CHECK_EQUAL(manager.repoSize(), (unsigned) 7); // +3 from repoindex + + //simulate change of repoindex.xml + urlS = ( zypp::Pathname("/Datadir") / "second").asDirUrl(); + + service.setUrl(urlS); + service.setEnabled(true); + + manager.modifyService(service.alias(), service); + manager.refreshServices(); + BOOST_CHECK_EQUAL(manager.repoSize(), (unsigned) 6); // -1 from new repoindex + + std::list infos; + manager.getRepositoriesInService("test", + std::insert_iterator >(infos,infos.begin())); + BOOST_CHECK_EQUAL(infos.size(), 2); // 2 from new repoindex + + + // let test cache creation + + RepoInfo repo; + repo.setAlias("foo"); + //BOOST_CHECK_MESSAGE(0, repourl.asString()); + repo.setBaseUrl( (Pathname(TESTS_SRC_DIR) / "/repo/yum/data/10.2-updates-subset").asDirUrl() ); + + KeyRingTestReceiver keyring_callbacks; + KeyRingTestSignalReceiver receiver; + + // disable sgnature checking + keyring_callbacks.answerAcceptKey(KeyRingReport::KEY_TRUST_TEMPORARILY); + keyring_callbacks.answerAcceptVerFailed(true); + keyring_callbacks.answerAcceptUnknownKey(true); + + // We have no metadata and cache yet + BOOST_CHECK_MESSAGE( !manager.isCached(repo), "Repo should not yet be cached" ); + + // This should download metadata and build the cache + manager.buildCache(repo); + + // Now we have metadata and cache + BOOST_CHECK_MESSAGE( manager.isCached(repo), "Repo should be cached now" ); + + // Metadata are up to date + RepoManager::RefreshCheckStatus ref_stat = manager.checkIfToRefreshMetadata(repo, *repo.baseUrlsBegin()); + SEC << endl << ref_stat << endl; + BOOST_CHECK_MESSAGE( ref_stat== RepoManager::REPO_UP_TO_DATE || ref_stat == RepoManager::REPO_CHECK_DELAYED, "Metadata should be up to date" ); + + // the solv file should exists now + Pathname base = (opts.repoCachePath / "solv" / repo.alias()); + Pathname solvfile = base / "solv"; + Pathname cookiefile = base / "cookie"; + BOOST_CHECK_MESSAGE( PathInfo(solvfile).isExist(), "Solv file is created after caching: " + solvfile.asString()); + BOOST_CHECK_MESSAGE( PathInfo(cookiefile).isExist(), "Cookie file is created after caching: " + cookiefile.asString()); + + MIL << "Repo already in cache, clean cache"<< endl; + manager.cleanCache(repo); + + BOOST_CHECK_MESSAGE( !manager.isCached(repo), + "Repo cache was just deleted, should not be cached now" ); + // now cache should build normally + manager.buildCache(repo); + + manager.loadFromCache(repo); + + if ( manager.isCached(repo ) ) + { + MIL << "Repo already in cache, clean cache"<< endl; + manager.cleanCache(repo); + } + MIL << "Parsing repository metadata..." << endl; + manager.buildCache(repo); + + + // now test that loading twice a repo updates + // it instead of duplicating the solv file + + +} + +BOOST_AUTO_TEST_CASE(repo_seting_test) +{ + RepoInfo repo; + repo.setAlias("foo"); + repo.setBaseUrl(std::string("http://test.org")); + BOOST_CHECK_MESSAGE( !repo.keepPackages(), "keepPackages must default to OFF"); +} + +//! \todo test this +//BOOST_AUTO_TEST_CASE(repo_dont_overwrite_external_settings_test) +//{ +//} diff --git a/tests/zypp/RepoStatus_test.cc b/tests/zypp/RepoStatus_test.cc new file mode 100644 index 0000000..bf98ec3 --- /dev/null +++ b/tests/zypp/RepoStatus_test.cc @@ -0,0 +1,56 @@ + +#include +#include +#include +#include +#include + +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; +using namespace zypp::filesystem; + +BOOST_AUTO_TEST_CASE(repostatus_test) +{ + RepoStatus e; + RepoStatus E { "", 42 }; // empty refers to the checksum only, not to the timestamp! + RepoStatus a { "aa", 0 }; + RepoStatus b { "bb", 1 }; + RepoStatus c { "cc", 2 }; + + BOOST_CHECK_EQUAL( e.empty(), true ); + BOOST_CHECK_EQUAL( e.timestamp(), 0 ); + BOOST_CHECK_EQUAL( (e && e).empty(), true ); + + BOOST_CHECK_EQUAL( E.empty(), true ); + BOOST_CHECK_EQUAL( E.timestamp(), 42 ); + RepoStatus r { E && e }; + BOOST_CHECK_EQUAL( r.empty(), true ); + BOOST_CHECK_EQUAL( r.timestamp(), 42 ); + r = e && E; + BOOST_CHECK_EQUAL( r.empty(), true ); + BOOST_CHECK_EQUAL( r.timestamp(), 42 ); + r = E && E; + BOOST_CHECK_EQUAL( r.empty(), true ); + BOOST_CHECK_EQUAL( r.timestamp(), 42 ); + + + BOOST_CHECK_EQUAL( a.empty(), false ); + BOOST_CHECK_EQUAL( a.timestamp(), 0 ); + + r = e && a; + BOOST_CHECK_EQUAL( r.empty(), false ); + BOOST_CHECK_EQUAL( r.timestamp(), a.timestamp() ); // max timestamp + + r = a && b; + BOOST_CHECK_EQUAL( r, (b && a) ); + BOOST_CHECK_EQUAL( r.timestamp(), b.timestamp() ); // max timestamp + + r = a && b && c; + BOOST_CHECK_EQUAL( r, (a && b) && c ); + BOOST_CHECK_EQUAL( r, a && (b && c) ); + BOOST_CHECK_EQUAL( r.timestamp(), c.timestamp() ); // max timestamp +} diff --git a/tests/zypp/ResKind_test.cc b/tests/zypp/ResKind_test.cc new file mode 100644 index 0000000..4f8f60b --- /dev/null +++ b/tests/zypp/ResKind_test.cc @@ -0,0 +1,32 @@ +#include +#include +#include + +using boost::unit_test::test_case; +using namespace zypp; + +BOOST_AUTO_TEST_CASE(reskind_test) +{ + // Default construced is empty "" + BOOST_CHECK_EQUAL( ResKind(), "" ); + // boolean context + BOOST_CHECK( ! ResKind() ); + BOOST_CHECK( ! ResKind(0) ); // id NULL + BOOST_CHECK( ! ResKind(1) ); // id "" + BOOST_CHECK( ! ResKind("") ); // "" + BOOST_CHECK( ResKind(2) ); + BOOST_CHECK( ResKind("FOO") ); + // Internal representation is lowercased + BOOST_CHECK_EQUAL( ResKind("FOO").asString(), "foo" ); + // Caseinsensitive comparison + BOOST_CHECK_EQUAL( ResKind("FOO"), ResKind("foo") ); + BOOST_CHECK_EQUAL( ResKind("FOO"), std::string("Foo") ); + BOOST_CHECK_EQUAL( ResKind("FOO"), "Foo" ); + BOOST_CHECK_EQUAL( ResKind("FOO"), std::string("foo") ); + BOOST_CHECK_EQUAL( ResKind("FOO"), "foo" ); + BOOST_CHECK_EQUAL( std::string("foo"), ResKind("FOO") ); + BOOST_CHECK_EQUAL( "foo", ResKind("FOO") ); + + BOOST_CHECK_EQUAL( ResKind::compare( "FOO", "foo" ), 0 ); + +} diff --git a/tests/zypp/ResStatus_test.cc b/tests/zypp/ResStatus_test.cc new file mode 100644 index 0000000..00343a1 --- /dev/null +++ b/tests/zypp/ResStatus_test.cc @@ -0,0 +1,243 @@ +#include "TestSetup.h" +#include + +#define BOOST_TEST_MODULE ResStatus + +BOOST_AUTO_TEST_CASE(Default) +{ + { + ResStatus s; + BOOST_CHECK( s.isUninstalled() ); + BOOST_CHECK_EQUAL( s.isInstalled(), ! s.isUninstalled() ); + BOOST_CHECK_EQUAL( s.getTransactValue(), ResStatus::KEEP_STATE ); + BOOST_CHECK_EQUAL( s.getTransactByValue(), ResStatus::SOLVER ); + } + { + ResStatus s( true ); + BOOST_CHECK( s.isInstalled() ); + BOOST_CHECK_EQUAL( s.isInstalled(), ! s.isUninstalled() ); + BOOST_CHECK_EQUAL( s.getTransactValue(), ResStatus::KEEP_STATE ); + BOOST_CHECK_EQUAL( s.getTransactByValue(), ResStatus::SOLVER ); + } +} + +//////////////////////////////////////////////////////////////////////////////// +// tools +//////////////////////////////////////////////////////////////////////////////// +template +inline const Tp & max( const Tp & lhs, const Tp & rhs ) +{ return lhs < rhs ? rhs : lhs; } + +template +inline Tp * begin( Tp (& _array)[N] ) { return _array; } + +template +inline Tp * end( Tp (& _array)[N] ) { return _array + (sizeof(_array)/sizeof(Tp)); } + +ResStatus::TransactByValue transactByValues[] = { + ResStatus::USER, ResStatus::APPL_HIGH, ResStatus::APPL_LOW, ResStatus::SOLVER +}; + +ResStatus::TransactValue transactValues[] = { + ResStatus::TRANSACT, ResStatus::KEEP_STATE, ResStatus::LOCKED +}; + +bool transactTo[] = { + true, false +}; + +// Status transition like setTransact, setLock, setSoftTransact +typedef bool (ResStatus::* Transition)( bool, ResStatus::TransactByValue ); + +// Result evaluation +typedef void (* Evaluate)( ResStatus::TransactValue, ResStatus::TransactByValue, /* fromState, fromBy */ + bool, ResStatus::TransactByValue, /* toState, toBy */ + bool, ResStatus ); /* done, result */ + +// build status and return whether the comination is supported. (e.g currently no LOCKED state below APPL_HIGH) +inline bool initStatus( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy, ResStatus & from ) +{ + from = ResStatus(); + if ( fromState == ResStatus::KEEP_STATE ) + { + from.setSoftLock( fromBy ); + } + else + { + from.setTransactValue( fromState, fromBy ); + if ( fromState == ResStatus::LOCKED && ! from.isLocked() ) + return false; // no lock at this level (by now just USER APPL_HIGH) + } + return true; +} + +void testTable( Transition transition, Evaluate evaluate ) +{ + // Table: For each causer combination (fromBy -> toBy) invoke transition: + // + // bool ok = ResStatus(fromState,fromBy).transition( toState, toBy ) + // + // And evaluate the result. + // + for ( ResStatus::TransactByValue * toBy = begin( transactByValues ); toBy != end( transactByValues ); ++toBy ) + { + for ( ResStatus::TransactByValue * fromBy = begin( transactByValues ); fromBy != end( transactByValues ); ++fromBy ) + { + INT << "=== " << *fromBy << " ==> " << *toBy << " ===" << endl; + for ( ResStatus::TransactValue * fromState = begin( transactValues ); fromState != end( transactValues ); ++fromState ) + { + ResStatus from; + if ( ! initStatus( *fromState, *fromBy, from ) ) + { + //WAR << "Unsupported ResStatus(" << *fromState << "," << *fromBy << ")" << endl; + continue; // Unsupported ResStatus + } + for ( bool * toState = begin( transactTo ); toState != end( transactTo ); ++toState ) + { + ResStatus result( from ); + bool done = (result.*transition)( *toState, *toBy ); + if ( ! done ) + BOOST_CHECK_EQUAL( from, result ); // status stays unchaged on failure! + evaluate( *fromState, *fromBy, *toState, *toBy, done, result ); + } + } + } + } +} + +// BOOST_CHECK_EQUAL or BOOST_REQUIRE_EQUAL +#define X BOOST_CHECK_EQUAL + + +// Transition must succeeds always +#define CHECK_DONE_ALWAYS X( done, true ); if ( ! done ) return + +// Transition succeeds if same or higher TransactByValue +#define CHECK_DONE_IFCAUSER X( done, toBy >= fromBy ); if ( ! done ) return + +// Transition succeeds if a locker (APPL_HIGH or USER) +#define CHECK_DONE_ALWAYS_IFLOCKER X( done, toBy >= ResStatus::APPL_HIGH ); if ( ! done ) return + +// Transition succeeds if a locker (APPL_HIGH or USER) and same or higher TransactByValue +#define CHECK_DONE_IFCAUSER_ISLOCKER X( done, toBy >= max(fromBy,ResStatus::APPL_HIGH) ); if ( ! done ) return + + +// Expected target state after transistion +#define CHECK_STATE(NEW) X( result.getTransactValue(), ResStatus::NEW ) + + +// Transition result: Remember the causer (i.e. may downgrade superior causer of previous state) +#define CHECK_CAUSER_SET X( result.getTransactByValue(), toBy ) + +// Transition result: Remember a superior causer +#define CHECK_CAUSER_RAISED X( result.getTransactByValue(), max(fromBy,toBy) ) + +// Transition result: Causer stays the same +#define CHECK_CAUSER_STAYS X( result.getTransactByValue(), fromBy ) + +// Transition result: Causer reset to least (SOLVER) level. +#define CHECK_CAUSER_TO_SOLVER X( result.getTransactByValue(), ResStatus::SOLVER ) + + +//////////////////////////////////////////////////////////////////////////////// +// test cases (see BOOST_AUTO_TEST_CASE(transition)) +//////////////////////////////////////////////////////////////////////////////// +// All tests below should define 3 checks, abbrev. by defines +// +// CHECK_DONE_*: When does the tranaction succeed? (return if not) +// CHECK_STATE( NEXT ): The state the transition leads to (if successful) +// CHECK_CAUSER_*: Changes to the remembered causer (if successful) +// + +#define DOCHECK( FROMSTATE, TOSTATE, C_DONE, C_STATE, C_CAUSER ) \ + if ( ResStatus::FROMSTATE == fromState && TOSTATE == toState ) { C_DONE; CHECK_STATE( C_STATE ); C_CAUSER; } + +void evaluateSetTransact( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy, + bool toState, ResStatus::TransactByValue toBy, + bool done, ResStatus result ) +{ + ResStatus from; + initStatus( fromState, fromBy, from ); + MIL << from << " =setTransact("<\t" << done << ":" << result << endl; + + DOCHECK( TRANSACT, true, CHECK_DONE_ALWAYS, TRANSACT, CHECK_CAUSER_RAISED ); + DOCHECK( TRANSACT, false, CHECK_DONE_IFCAUSER, KEEP_STATE, CHECK_CAUSER_RAISED ); // from transact into softlock + DOCHECK( KEEP_STATE, true, CHECK_DONE_ALWAYS, TRANSACT, CHECK_CAUSER_SET ); + DOCHECK( KEEP_STATE, false, CHECK_DONE_ALWAYS, KEEP_STATE, CHECK_CAUSER_STAYS ); // keep is not raised to softlock + DOCHECK( LOCKED, true, CHECK_DONE_IFCAUSER, TRANSACT, CHECK_CAUSER_SET ); + DOCHECK( LOCKED, false, CHECK_DONE_ALWAYS, LOCKED, CHECK_CAUSER_STAYS ); +} + +void evaluateSetSoftTransact( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy, + bool toState, ResStatus::TransactByValue toBy, + bool done, ResStatus result ) +{ + ResStatus from; + initStatus( fromState, fromBy, from ); + MIL << from << " =setSoftTransact("<\t" << done << ":" << result << endl; + + DOCHECK( TRANSACT, true, CHECK_DONE_ALWAYS, TRANSACT, CHECK_CAUSER_RAISED ); + DOCHECK( TRANSACT, false, CHECK_DONE_IFCAUSER, KEEP_STATE, CHECK_CAUSER_RAISED ); // from transact into softlock + DOCHECK( KEEP_STATE, true, CHECK_DONE_IFCAUSER, TRANSACT, CHECK_CAUSER_SET ); // leaving KEEP requires sup. causer + DOCHECK( KEEP_STATE, false, CHECK_DONE_ALWAYS, KEEP_STATE, CHECK_CAUSER_STAYS ); // keep is not raised to softlock + DOCHECK( LOCKED, true, CHECK_DONE_IFCAUSER, TRANSACT, CHECK_CAUSER_SET ); + DOCHECK( LOCKED, false, CHECK_DONE_ALWAYS, LOCKED, CHECK_CAUSER_STAYS ); +} + +// Check whether failures are ok and whether success lead to the correct state +void evaluateSetLock( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy, + bool toState, ResStatus::TransactByValue toBy, + bool done, ResStatus result ) +{ + ResStatus from; + initStatus( fromState, fromBy, from ); + MIL << from << " =setLock("<\t" << done << ":" << result << endl; + + DOCHECK( TRANSACT, true, CHECK_DONE_IFCAUSER_ISLOCKER, LOCKED, CHECK_CAUSER_SET ); // transact is 'not locked' + DOCHECK( TRANSACT, false, CHECK_DONE_ALWAYS, TRANSACT, CHECK_CAUSER_STAYS ); + DOCHECK( KEEP_STATE, true, CHECK_DONE_ALWAYS_IFLOCKER, LOCKED, CHECK_CAUSER_SET ); + DOCHECK( KEEP_STATE, false, CHECK_DONE_ALWAYS, KEEP_STATE, CHECK_CAUSER_STAYS ); + DOCHECK( LOCKED, true, CHECK_DONE_ALWAYS, LOCKED, CHECK_CAUSER_RAISED ); + DOCHECK( LOCKED, false, CHECK_DONE_IFCAUSER, KEEP_STATE, CHECK_CAUSER_TO_SOLVER ); +} + +BOOST_AUTO_TEST_CASE(transition) +{ + //base::LogControl::TmpLineWriter shutUp( new log::FileLineWriter( "-" ) ); + MIL << endl; + testTable( &ResStatus::setTransact, &evaluateSetTransact ); + testTable( &ResStatus::setSoftTransact, &evaluateSetSoftTransact ); + testTable( &ResStatus::setLock, &evaluateSetLock ); +} + + +bool WhilePoolItemSameStateIsPrivate( ResStatus ostatus, ResStatus nstatus ) +{ + if ( nstatus == ostatus ) + return true; + // some bits changed... + if ( nstatus.getTransactValue() != ostatus.getTransactValue() + && ( ! nstatus.isBySolver() // ignore solver state changes + // removing a user lock also goes to bySolver + || ostatus.getTransactValue() == ResStatus::LOCKED ) ) + return false; + if ( nstatus.isLicenceConfirmed() != ostatus.isLicenceConfirmed() ) + return false; + return true; +} + +BOOST_AUTO_TEST_CASE(savestate) +{ + ResStatus ostatus; + ResStatus nstatus; + + BOOST_CHECK_EQUAL( WhilePoolItemSameStateIsPrivate( ostatus, nstatus ), true ); + nstatus.setLock( true, ResStatus::USER ); + BOOST_CHECK_EQUAL( WhilePoolItemSameStateIsPrivate( ostatus, nstatus ), false ); + ostatus = nstatus; + nstatus.setLock( false, ResStatus::USER ); + BOOST_CHECK_EQUAL( WhilePoolItemSameStateIsPrivate( ostatus, nstatus ), false ); +} + + + diff --git a/tests/zypp/Resolvable_test.cc b/tests/zypp/Resolvable_test.cc new file mode 100644 index 0000000..157b7b3 --- /dev/null +++ b/tests/zypp/Resolvable_test.cc @@ -0,0 +1,38 @@ + +#include +#include +#include + +// Boost.Test +#include + +#include +#include +#include +#include +#include + +#include "TestSetup.h" + +using boost::unit_test::test_case; +using namespace zypp; + + +BOOST_AUTO_TEST_CASE(resolvable_test) +{ + TestSetup test( Arch_x86_64 ); + // test.loadTarget(); // initialize and load target + test.loadRepo( TESTS_SRC_DIR"/data/openSUSE-11.1" ); + + int pattern_count = 0; + for_( pitem, test.pool().begin(), test.pool().end() ) + { + if ( isKind(pitem->resolvable()) ) + { + //BOOST_CHECK( ! asKind(pitem->resolvable())->contents().empty() ); + MIL << asKind(pitem->resolvable()) << endl; + pattern_count++; + } + } + BOOST_CHECK(pattern_count > 0); +} diff --git a/tests/zypp/Resolver_test.cc b/tests/zypp/Resolver_test.cc new file mode 100644 index 0000000..2898415 --- /dev/null +++ b/tests/zypp/Resolver_test.cc @@ -0,0 +1,100 @@ +#include +#define BOOST_CHECK_MODULE Resolver +using namespace boost::unit_test; + +#include "TestSetup.h" +#include +#include +#include +#include + +static TestSetup test( TestSetup::initLater ); + +struct BAD_TESTCASE {}; + +typedef std::set PoolItemSet; + +constexpr const unsigned onlyRequires = 0x1; +constexpr const unsigned inrMode = 0x2; + +PoolItemSet resolve( unsigned flags_r = 0 ) +{ + test.resolver().setOnlyRequires ( flags_r & onlyRequires ); + test.resolver().setIgnoreAlreadyRecommended( ! ( flags_r & inrMode ) ); + if ( ! test.resolver().resolvePool() ) + throw BAD_TESTCASE(); + + return { make_filter_begin(test.pool()), make_filter_end(test.pool()) }; +} + +inline PoolItem getPi( const std::string & name_r, bool installed_r ) +{ + for ( const auto & pi : test.pool().byName( name_r ) ) + { if ( pi.isSystem() == installed_r ) return pi; } + throw BAD_TESTCASE(); +} +inline PoolItem getIPi( const std::string & name_r ) +{ return getPi( name_r, true ); } +inline PoolItem getAPi( const std::string & name_r ) +{ return getPi( name_r, false ); } + +///////////////////////////////////////////////////////////////////////////// +// Pool content: +PoolItem Ip; // IA: aspell +PoolItem Ap; +PoolItem Ipen; // IA: aspell-en (wanted locale) +PoolItem Apen; +PoolItem Apde; // A: aspell-de (wanted locale) +PoolItem Apfr; // A: aspell-fr (unwanted locale) +PoolItem Aprec; // A: recommended-pkg (by aspell) + +struct TestInit { + TestInit() { + test = TestSetup( ); + + test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCNamespaceRecommends" ); + Ip = getIPi( "aspell" ); + Ap = getAPi( "aspell" ); + Ipen = getIPi( "aspell-en" ); + Apen = getAPi( "aspell-en" ); + Apde = getAPi( "aspell-de" ); + Apfr = getAPi( "aspell-fr" ); + Aprec = getAPi( "recommended-pkg" ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +///////////////////////////////////////////////////////////////////////////// + +inline void BOOST_checkresult( const PoolItemSet & resolved_r, const PoolItemSet & expected_r ) +{ BOOST_CHECK_EQUAL( resolved_r, expected_r ); } + + +BOOST_AUTO_TEST_CASE(install) +{ + Ap.status().setTransact( true, ResStatus::USER ); + // Upadte aspell, add all recommends + BOOST_checkresult( resolve(), { Ap, Ip, Apde, Aprec } ); + Ap.status().setTransact( false, ResStatus::USER ); +} + +BOOST_AUTO_TEST_CASE(installOnlyRequires) +{ + Ap.status().setTransact( true, ResStatus::USER ); + // Upadte aspell, add only namespace recommends + BOOST_checkresult( resolve( onlyRequires ), { Ap, Ip, Apde } ); + Ap.status().setTransact( false, ResStatus::USER ); +} + +BOOST_AUTO_TEST_CASE(inr) +{ + // Fillup all recommends + BOOST_checkresult( resolve( inrMode ), { Apde, Aprec } ); +} + +BOOST_AUTO_TEST_CASE(inrOnlyRequires) +{ + // Fillup only namespace recommends + BOOST_checkresult( resolve( inrMode|onlyRequires ), { Apde } ); +} diff --git a/tests/zypp/RpmPkgSigCheck_test.cc b/tests/zypp/RpmPkgSigCheck_test.cc new file mode 100644 index 0000000..37cff53 --- /dev/null +++ b/tests/zypp/RpmPkgSigCheck_test.cc @@ -0,0 +1,278 @@ +#include "TestSetup.h" + +#include +using target::rpm::RpmDb; + +#define DATADIR (Pathname(TESTS_SRC_DIR) / "/zypp/data/RpmPkgSigCheck") + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( ); + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +/////////////////////////////////////////////////////////////////// +// +// - RpmDb::checkPackage (legacy) and RpmDb::checkPackageSignature are +// expected to produce the same result, except for ... +// +// Result comparison is not very sophisticated. As the detail strings are +// user visible (at least in zypper) we want a notification (breaking testcase) +// if something in the rpm format changes. +// +/////////////////////////////////////////////////////////////////// +namespace +{ + struct CheckResult + { + CheckResult() + {} + + CheckResult( RpmDb::CheckPackageResult && result_r ) + : result { std::move(result_r) } + {} + + CheckResult( RpmDb::CheckPackageResult && result_r, + std::vector> && detail_r ) + : result { std::move(result_r) } + { static_cast>&>(detail) = std::move(detail_r); } + + RpmDb::CheckPackageResult result; + RpmDb::CheckPackageDetail detail; + }; + + bool operator==( const CheckResult & lhs, const CheckResult & rhs ) + { + if ( lhs.result != rhs.result ) + return false; + // protect against reordered details: + + // there seems to be a backporting of how rpm prints the signature check result + // breaking our tests here, instead of checking for exact equality we just require + // that all elements in the lhs exist in the rhs instance. + //if ( lhs.detail.size() != rhs.detail.size() ) + // return false; + + for ( const auto & l : lhs.detail ) + { + if ( std::find( rhs.detail.begin(), rhs.detail.end(), l ) == rhs.detail.end() ) + return false; + } + return true; + } + + std::ostream & operator<<( std::ostream & str, const CheckResult & obj ) + { + str << "R: " << obj.result; + for ( const auto & el : obj.detail ) + str << endl << " " << el.first << " | " << el.second; + return str; + } + + CheckResult gcheckPackage( const Pathname & path_r ) + { + CheckResult res; + res.result = test.target().rpmDb().checkPackage( path_r, res.detail ); +// cout << "==-" << path_r << endl; +// cout << res << endl; + return res; + } + + CheckResult gcheckPackageSignature( const Pathname & path_r ) + { + CheckResult res; + res.result = test.target().rpmDb().checkPackageSignature( path_r, res.detail ); +// cout << "==!" << path_r << endl; +// cout << res << endl; + return res; + } +} // namespace + + +BOOST_AUTO_TEST_CASE(no_pkg) +{ + Pathname rpm { DATADIR/"no.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_ERROR, {/*empty details*/} }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(unsigned_pkg) +{ + Pathname rpm { DATADIR/"unsigned.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + // For unsigned packages the final result differs! + // (but only if the digests are OK) + BOOST_CHECK_EQUAL( cp.result, RpmDb::CHK_OK ); + BOOST_CHECK_EQUAL( cs.result, RpmDb::CHK_NOSIG ); + BOOST_CHECK_EQUAL( cp.detail, cs.detail ); + + CheckResult xpct { RpmDb::CHK_NOSIG, { + { RpmDb::CHK_OK, " Header SHA1 digest: OK" }, + { RpmDb::CHK_OK, " Header SHA256 digest: OK" }, + { RpmDb::CHK_OK, " Payload SHA256 digest: OK" }, + { RpmDb::CHK_OK, " MD5 digest: OK" }, + { RpmDb::CHK_NOSIG, " Package header is not signed!" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(unsigned_broken_pkg) +{ + Pathname rpm { DATADIR/"unsigned_broken.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + // Unsigned, but a broken digest 'superseeds' CHK_NOSIG + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_FAIL, { + { RpmDb::CHK_OK, " Header SHA1 digest: OK" }, + { RpmDb::CHK_OK, " Header SHA256 digest: OK" }, + { RpmDb::CHK_FAIL, " Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" }, + { RpmDb::CHK_FAIL, " MD5 digest: BAD (Expected e3f474f75d2d2b267da4ff80fc071dd7 != cebe1e7d39b4356639a0779aa23f6e27)" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(unsigned_broken_header_pkg) +{ + Pathname rpm { DATADIR/"unsigned_broken_header.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + // Unsigned, but a broken digest 'superseeds' CHK_NOSIG + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_FAIL, { + { RpmDb::CHK_FAIL, " Header SHA1 digest: BAD (Expected d6768447e13388b0c35fb151ebfa8f6646a115e9 != dd761ace671a5eb2669b269faf22a3cd72792138)" }, + { RpmDb::CHK_FAIL, " Header SHA256 digest: BAD (Expected 2ce9f41bc0de68b4cb1aa1e18c1bea43dfaa01299ae61ef3e4466df332c792e5 != 4a9410db7131cead773afe1876f2490023ccc7dc47cbba47807430c53ea9649d)" }, + { RpmDb::CHK_FAIL, " Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" }, + { RpmDb::CHK_FAIL, " MD5 digest: BAD (Expected e3f474f75d2d2b267da4ff80fc071dd7 != 9afd6b52896d23910280ddded1921071)" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(signed_pkg_nokey) +{ + Pathname rpm { DATADIR/"signed.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_NOKEY, { + { RpmDb::CHK_NOKEY, " Header V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: NOKEY" }, + { RpmDb::CHK_OK, " Header SHA1 digest: OK" }, + { RpmDb::CHK_OK, " Header SHA256 digest: OK" }, + { RpmDb::CHK_OK, " Payload SHA256 digest: OK" }, + { RpmDb::CHK_OK, " MD5 digest: OK" }, + { RpmDb::CHK_NOKEY, " V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: NOKEY" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(signed_broken_pkg_nokey) +{ + Pathname rpm { DATADIR/"signed_broken.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_FAIL, { + { RpmDb::CHK_NOKEY, " Header V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: NOKEY" }, + { RpmDb::CHK_OK, " Header SHA1 digest: OK" }, + { RpmDb::CHK_OK, " Header SHA256 digest: OK" }, + { RpmDb::CHK_FAIL, " Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" }, + { RpmDb::CHK_FAIL, " MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 442a473472708c39f3ac2b5eb38b476f)" }, + { RpmDb::CHK_FAIL, " V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: BAD" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(signed_broken_header_pkg_nokey) +{ + Pathname rpm { DATADIR/"signed_broken_header.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_FAIL, { + { RpmDb::CHK_FAIL, " Header V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: BAD" }, + { RpmDb::CHK_FAIL, " Header SHA1 digest: BAD (Expected 9ca2e3aec038e562d33442271ee52c08ded0d637 != 95286fd653f927df0a42746e310861d3f89bb75c)" }, + { RpmDb::CHK_FAIL, " Header SHA256 digest: BAD (Expected e88100656c8e06b6e4bb9155f0dd111ef8042866941f02b623cb46e12a82f732 != 76b343bcb9b8aaf9998fdcf7392e234944a0b078c67667fa0d658208b9a66983)" }, + { RpmDb::CHK_FAIL, " Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" }, + { RpmDb::CHK_FAIL, " MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 81df819a7d94638ff3ffe0bb93a7d177)" }, + { RpmDb::CHK_FAIL, " V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: BAD" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + + +/////////////////////////////////////////////////////////////////// +BOOST_AUTO_TEST_CASE(add_key) +{ + PublicKey key { Pathname(DATADIR)/"signed.key" }; + //cout << key << endl; + test.target().rpmDb().importPubkey( key ); +} +/////////////////////////////////////////////////////////////////// + + +BOOST_AUTO_TEST_CASE(signed_pkg_withkey) +{ + Pathname rpm { DATADIR/"signed.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_OK, { + { RpmDb::CHK_OK, " Header V3 RSA/SHA256 Signature, key ID 3dbdc284: OK" }, + { RpmDb::CHK_OK, " Header SHA1 digest: OK" }, + { RpmDb::CHK_OK, " Header SHA256 digest: OK" }, + { RpmDb::CHK_OK, " Payload SHA256 digest: OK" }, + { RpmDb::CHK_OK, " MD5 digest: OK" }, + { RpmDb::CHK_OK, " V3 RSA/SHA256 Signature, key ID 3dbdc284: OK" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(signed_broken_pkg_withkey) +{ + Pathname rpm { DATADIR/"signed_broken.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_FAIL, { + { RpmDb::CHK_OK, " Header V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: OK" }, + { RpmDb::CHK_OK, " Header SHA1 digest: OK" }, + { RpmDb::CHK_OK, " Header SHA256 digest: OK" }, + { RpmDb::CHK_FAIL, " Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" }, + { RpmDb::CHK_FAIL, " MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 442a473472708c39f3ac2b5eb38b476f)" }, + { RpmDb::CHK_FAIL, " V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: BAD" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} + +BOOST_AUTO_TEST_CASE(signed_broken_header_pkg_withkey) +{ + Pathname rpm { DATADIR/"signed_broken_header.rpm" }; + CheckResult cp { gcheckPackage( rpm ) }; + CheckResult cs { gcheckPackageSignature( rpm ) }; + BOOST_CHECK_EQUAL( cp, cs ); + + CheckResult xpct { RpmDb::CHK_FAIL, { + { RpmDb::CHK_FAIL, " Header V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: BAD" }, + { RpmDb::CHK_FAIL, " Header SHA1 digest: BAD (Expected 9ca2e3aec038e562d33442271ee52c08ded0d637 != 95286fd653f927df0a42746e310861d3f89bb75c)" }, + { RpmDb::CHK_FAIL, " Header SHA256 digest: BAD (Expected e88100656c8e06b6e4bb9155f0dd111ef8042866941f02b623cb46e12a82f732 != 76b343bcb9b8aaf9998fdcf7392e234944a0b078c67667fa0d658208b9a66983)" }, + { RpmDb::CHK_FAIL, " Payload SHA256 digest: BAD (Expected 6632dfb6e78fd3346baa860da339acdedf6f019fb1b5448ba1baa6cef67de795 != 85156c232f4c76273bbbb134d8d869e93bbfc845dd0d79016856e5356dd33727)" }, + { RpmDb::CHK_FAIL, " MD5 digest: BAD (Expected 8e64684e4d5bd90c3c13f76ecbda9ee2 != 81df819a7d94638ff3ffe0bb93a7d177)" }, + { RpmDb::CHK_FAIL, " V3 RSA/SHA256 Signature, key ID b88b2fd43dbdc284: BAD" }, + } }; + BOOST_CHECK_EQUAL( xpct, cs ); +} diff --git a/tests/zypp/Selectable_test.cc b/tests/zypp/Selectable_test.cc new file mode 100644 index 0000000..27e90be --- /dev/null +++ b/tests/zypp/Selectable_test.cc @@ -0,0 +1,354 @@ +#include "TestSetup.h" +#include +#include + +#define BOOST_TEST_MODULE Selectable + +///////////////////////////////////////////////////////////////////////////// + +static TestSetup test( TestSetup::initLater ); +struct TestInit { + TestInit() { + test = TestSetup( ); + + // zypp::base::LogControl::instance().logToStdErr(); + test.loadTestcaseRepos( TESTS_SRC_DIR"/data/TCSelectable" ); + + // dumpRange( USR, test.pool().knownRepositoriesBegin(), + // test.pool().knownRepositoriesEnd() ) << endl; + // USR << "pool: " << test.pool() << endl; + + } + ~TestInit() { test.reset(); } +}; +BOOST_GLOBAL_FIXTURE( TestInit ); + +///////////////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(candiadate) +{ + ResPoolProxy poolProxy( test.poolProxy() ); + ui::Selectable::Ptr s( poolProxy.lookup( ResKind::package, "candidate" ) ); + // (I 1) { + // I__s_(8)candidate-1-1.i586(@System)(openSUSE) + // } (A 6) { + // U__s_(2)candidate-4-1.x86_64(RepoHIGH)(unkown) + // U__s_(3)candidate-4-1.i586(RepoHIGH)(unkown) <- (update) candidate if allowVendorChange + // U__s_(6)candidate-0-1.x86_64(RepoMID)(openSUSE) + // U__s_(7)candidate-0-1.i586(RepoMID)(openSUSE) <- candidate (highest prio matching arch and vendor) + // U__s_(4)candidate-2-1.x86_64(RepoLOW)(openSUSE) + // U__s_(5)candidate-2-1.i586(RepoLOW)(openSUSE) + // } + if ( ZConfig::instance().solver_allowVendorChange() ) + { + BOOST_CHECK_EQUAL( s->candidateObj()->repoInfo().alias(), "RepoHIGH" ); + BOOST_CHECK_EQUAL( s->candidateObj()->edition(), Edition("4-1") ); + BOOST_CHECK_EQUAL( s->candidateObj()->arch(), Arch_i586 ); + // updateCandidate: + BOOST_CHECK_EQUAL( s->updateCandidateObj(), s->candidateObj() ); + } + else + { + BOOST_CHECK_EQUAL( s->candidateObj()->repoInfo().alias(), "RepoMID" ); + BOOST_CHECK_EQUAL( s->candidateObj()->edition(), Edition("0-1") ); + BOOST_CHECK_EQUAL( s->candidateObj()->arch(), Arch_i586 ); + // no updateCandidate due to low version + BOOST_CHECK_EQUAL( s->updateCandidateObj(), PoolItem() ); + } +} + +BOOST_AUTO_TEST_CASE(candiadatenoarch) +{ + ResPoolProxy poolProxy( test.poolProxy() ); + ui::Selectable::Ptr s( poolProxy.lookup( ResKind::package, "candidatenoarch" ) ); +/*[package]candidatenoarch: S_KeepInstalled + (I 1) { + I__s_(17)candidatenoarch-1-1.i586(@System) +} (A 8) { + C U__s_(4)candidatenoarch-5-1.noarch(RepoHIGH) <- candidate (arch/noarch change) + U__s_(5)candidatenoarch-4-1.x86_64(RepoHIGH) + U__s_(6)candidatenoarch-4-1.i586(RepoHIGH) + U__s_(7)candidatenoarch-4-1.noarch(RepoHIGH) + U__s_(12)candidatenoarch-0-2.noarch(RepoMID) + U__s_(13)candidatenoarch-0-1.x86_64(RepoMID) + U__s_(14)candidatenoarch-0-1.i586(RepoMID) + U__s_(15)candidatenoarch-0-1.noarch(RepoMID) +} */ + BOOST_CHECK_EQUAL( s->candidateObj()->repoInfo().alias(), "RepoHIGH" ); + BOOST_CHECK_EQUAL( s->candidateObj()->edition(), Edition("5-1") ); + BOOST_CHECK_EQUAL( s->candidateObj()->arch(), Arch_noarch ); + // no updateCandidate due to low version + BOOST_CHECK_EQUAL( s->updateCandidateObj(), s->candidateObj() ); +} + + +///////////////////////////////////////////////////////////////////////////// +// +// Status change tests +// +///////////////////////////////////////////////////////////////////////////// + +// build ResStatus and return whether the comination is supported. (e.g currently no LOCKED state below APPL_HIGH) +inline bool initStatus( ResStatus::TransactValue fromState, ResStatus::TransactByValue fromBy, ResStatus & from ) +{ + from = ResStatus(); + if ( fromState == ResStatus::KEEP_STATE ) + { + from.setSoftLock( fromBy ); + } + else + { + from.setTransactValue( fromState, fromBy ); + if ( fromState == ResStatus::LOCKED && ! from.isLocked() ) + return false; // no lock at this level (by now just USER APPL_HIGH) + } + return true; +} + +///////////////////////////////////////////////////////////////////////////// +// status verification helper +///////////////////////////////////////////////////////////////////////////// +// enum TransactValue +// { +// KEEP_STATE = bit::RangeValue::value, +// LOCKED = bit::RangeValue::value, // locked, must not transact +// TRANSACT = bit::RangeValue::value // transact according to state +// }; + +template +inline bool _all( TIter begin_r, TIter end_r, ResStatus::TransactValue val_r ) +{ + for_( it, begin_r, end_r ) + { + if ( it->status().getTransactValue() != val_r ) + return false; + } + return true; +} + +template +inline bool _none( TIter begin_r, TIter end_r, ResStatus::TransactValue val_r ) +{ + for_( it, begin_r, end_r ) + { + if ( it->status().getTransactValue() == val_r ) + return false; + } + return true; +} + +template +inline bool _atLeastOne( TIter begin_r, TIter end_r, ResStatus::TransactValue val_r ) +{ return ! _none( begin_r, end_r, val_r ); } + +inline bool _allBySolver( ui::Selectable::Ptr sel ) +{ + for_( it, sel->installedBegin(), sel->installedEnd() ) + { + if ( it->status().transacts() && ! it->status().isBySolver() ) + return false; + } + for_( it, sel->availableBegin(), sel->availableEnd() ) + { + if ( it->status().transacts() && ! it->status().isBySolver() ) + return false; + } + return true; +} + +inline bool _allInstalled( ui::Selectable::Ptr sel, ResStatus::TransactValue val_r ) { return _all( sel->installedBegin(), sel->installedEnd(), val_r ); } +inline bool _noneInstalled( ui::Selectable::Ptr sel, ResStatus::TransactValue val_r ) { return _none( sel->installedBegin(), sel->installedEnd(), val_r ); } +inline bool _atLeastOneInstalled( ui::Selectable::Ptr sel, ResStatus::TransactValue val_r ) { return _atLeastOne( sel->installedBegin(), sel->installedEnd(), val_r ); } + +inline bool _allAvailable( ui::Selectable::Ptr sel, ResStatus::TransactValue val_r ) { return _all( sel->availableBegin(), sel->availableEnd(), val_r ); } +inline bool _noneAvailable( ui::Selectable::Ptr sel, ResStatus::TransactValue val_r ) { return _none( sel->availableBegin(), sel->availableEnd(), val_r ); } +inline bool _atLeastOneAvailable( ui::Selectable::Ptr sel, ResStatus::TransactValue val_r ) { return _atLeastOne( sel->availableBegin(), sel->availableEnd(), val_r ); } + +inline bool _haveInstalled( ui::Selectable::Ptr sel ) { return ! sel->installedEmpty(); } +inline bool _haveAvailable( ui::Selectable::Ptr sel ) { return ! sel->availableEmpty(); } + +inline bool _noInstalled( ui::Selectable::Ptr sel ) { return sel->installedEmpty(); } +inline bool _noAvailable( ui::Selectable::Ptr sel ) { return sel->availableEmpty(); } + +#define allInstalled(V) _allInstalled(sel,ResStatus::V) +#define noneInstalled(V) _noneInstalled(sel,ResStatus::V) +#define atLeastOneInstalled(V) _atLeastOneInstalled(sel,ResStatus::V) + +#define allAvailable(V) _allAvailable(sel,ResStatus::V) +#define noneAvailable(V) _noneAvailable(sel,ResStatus::V) +#define atLeastOneAvailable(V) _atLeastOneAvailable(sel,ResStatus::V) + +#define haveInstalled _haveInstalled(sel) +#define haveAvailable _haveAvailable(sel) +#define noInstalled _noInstalled(sel) +#define noAvailable _noAvailable(sel) + +#define allBySolver _allBySolver(sel) + +// Verify Selectable::status computes the right value. +// +// S_Protected, // Keep this unmodified ( have installedObj && S_Protected ) +// S_Taboo, // Keep this unmodified ( have no installedObj && S_Taboo) +// // requested by user: +// S_Del, // delete installedObj ( clears S_Protected if set ) +// S_Update, // install candidateObj ( have installedObj, clears S_Protected if set ) +// S_Install, // install candidateObj ( have no installedObj, clears S_Taboo if set ) +// // not requested by user: +// S_AutoDel, // delete installedObj +// S_AutoUpdate, // install candidateObj ( have installedObj ) +// S_AutoInstall, // install candidateObj ( have no installedObj ) +// // no modification: +// S_KeepInstalled, // no modification ( have installedObj && !S_Protected, clears S_Protected if set ) +// S_NoInst, // no modification ( have no installedObj && !S_Taboo, clears S_Taboo if set ) +void verifyState( ui::Selectable::Ptr sel ) +{ + ui::Status status( sel->status() ); + SEC << dump(sel) << endl; + switch ( status ) + { + case ui::S_Update: + case ui::S_AutoUpdate: + BOOST_CHECK( haveInstalled ); + BOOST_CHECK( atLeastOneAvailable(TRANSACT) ); + BOOST_CHECK_EQUAL( allBySolver, status==ui::S_AutoUpdate ); + break; + + case ui::S_Del: + case ui::S_AutoDel: + BOOST_CHECK( haveInstalled ); + BOOST_CHECK( noneAvailable(TRANSACT) ); // else would be UPDATE + BOOST_CHECK( atLeastOneInstalled(TRANSACT) ); + BOOST_CHECK_EQUAL( allBySolver, status==ui::S_AutoDel ); + break; + + case ui::S_Protected: + BOOST_CHECK( haveInstalled ); + BOOST_CHECK( noneAvailable(TRANSACT) ); // else would be UPDATE + BOOST_CHECK( noneInstalled(TRANSACT) ); // else would be DEL + BOOST_CHECK( allInstalled(LOCKED) ); // implies noneInstalled(TRANSACT) + break; + + case ui::S_KeepInstalled: + BOOST_CHECK( haveInstalled ); + BOOST_CHECK( noneAvailable(TRANSACT) ); // else would be UPDATE + BOOST_CHECK( noneInstalled(TRANSACT) ); // else would be DEL + BOOST_CHECK( ! allInstalled(LOCKED) ); // else would be PROTECTED + break; + + + case ui::S_Install: + case ui::S_AutoInstall: + BOOST_CHECK( noInstalled ); + BOOST_CHECK( atLeastOneAvailable(TRANSACT) ); + BOOST_CHECK_EQUAL( allBySolver, status==ui::S_AutoInstall ); + break; + + case ui::S_Taboo: + BOOST_CHECK( noInstalled ); + BOOST_CHECK( noneAvailable(TRANSACT) ); // else would be INSTALL + BOOST_CHECK( allAvailable(LOCKED) ); // implies noneAvailable(TRANSACT) + break; + + + case ui::S_NoInst: + BOOST_CHECK( noInstalled ); + BOOST_CHECK( noneAvailable(TRANSACT) ); // else would be INSTALL + BOOST_CHECK( ! allAvailable(LOCKED) ); // else would be TABOO + break; + } +} + +// Create all ResStatus combinations over a Selectables PoolItems +struct StatusCombination +{ + StatusCombination() + {} + StatusCombination( ui::Selectable::Ptr sel_r ) + { + _items.insert( _items.end(), sel_r->installedBegin(), sel_r->installedEnd() ); + _items.insert( _items.end(), sel_r->availableBegin(), sel_r->availableEnd() ); + } + bool next() + { + for (auto i : _items) + { + switch ( i.status().getTransactValue() ) + { + case ResStatus::KEEP_STATE: + i.status().setTransactValue( ResStatus::LOCKED, ResStatus::USER ); + return true; + break; + case ResStatus::LOCKED: + i.status().setTransactValue( ResStatus::TRANSACT, ResStatus::USER ); + return true; + break; + case ResStatus::TRANSACT: + i.status().setTransactValue( ResStatus::KEEP_STATE, ResStatus::USER ); + break; + } + } + return false; // back at the beginning + } + + std::vector _items; +}; + +// Create all ResStatus combinations over the Selectables PoolItems and verify the result. +void testStatusTable( ui::Selectable::Ptr sel ) +{ + StatusCombination comb( sel ); + do { + verifyState( sel ); + } while ( comb.next() ); +} + +BOOST_AUTO_TEST_CASE(status_verify) +{ + // this verifies the Selectables computes ui::Status + ResPoolProxy poolProxy( test.poolProxy() ); + ResPoolProxy::ScopedSaveState saveState( poolProxy ); + { + ui::Selectable::Ptr sel( poolProxy.lookup( ResKind::package, "installed_only" ) ); + BOOST_REQUIRE( !sel->installedEmpty() ); + BOOST_REQUIRE( sel->availableEmpty() ); + BOOST_CHECK_EQUAL( sel->status(), ui::S_KeepInstalled ); + testStatusTable( sel ); + } + { + ui::Selectable::Ptr sel( poolProxy.lookup( ResKind::package, "installed_and_available" ) ); + BOOST_REQUIRE( !sel->installedEmpty() ); + BOOST_REQUIRE( !sel->availableEmpty() ); + BOOST_CHECK_EQUAL( sel->status(), ui::S_KeepInstalled ); + testStatusTable( sel ); + } + { + ui::Selectable::Ptr sel( poolProxy.lookup( ResKind::package, "available_only" ) ); + BOOST_REQUIRE( sel->installedEmpty() ); + BOOST_REQUIRE( !sel->availableEmpty() ); + BOOST_CHECK_EQUAL( sel->status(), ui::S_NoInst ); + testStatusTable( sel ); + } + + // TODO: Test the pickStatus computation (w./w.o. multiinstall) + // TODO: Test status/pickStatus transactions (w./w.o. multiinstall) +} + +///////////////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(pickstatus_cycle) +{ + return; + // TODO: automate it + ResPoolProxy poolProxy( test.poolProxy() ); + ResPoolProxy::ScopedSaveState saveState( poolProxy ); + ui::Selectable::Ptr sel( poolProxy.lookup( ResKind::package, "installed_and_available" ) ); + + USR << dump(sel) << endl; + for ( const PoolItem & pi : sel->picklist() ) + { + (sel->pickInstall( pi, ResStatus::USER ) ? WAR : ERR) << (pi.multiversionInstall() ? "M " : " " ) << pi << endl; + USR << dump(sel) << endl; + } +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/tests/zypp/SetRelationMixin_test.cc b/tests/zypp/SetRelationMixin_test.cc new file mode 100644 index 0000000..189b9df --- /dev/null +++ b/tests/zypp/SetRelationMixin_test.cc @@ -0,0 +1,142 @@ +#include +#include + +using zypp::SetCompare; +using zypp::SetRelation; + +BOOST_AUTO_TEST_CASE(set_compare) +{ + BOOST_CHECK( SetCompare::uncomparable == SetCompare::uncomparable ); + BOOST_CHECK( SetCompare::uncomparable != SetCompare::equal ); + BOOST_CHECK( SetCompare::uncomparable != SetCompare::properSubset ); + BOOST_CHECK( SetCompare::uncomparable != SetCompare::properSuperset ); + BOOST_CHECK( SetCompare::uncomparable != SetCompare::disjoint ); + + BOOST_CHECK( SetCompare::equal != SetCompare::uncomparable ); + BOOST_CHECK( SetCompare::equal == SetCompare::equal ); + BOOST_CHECK( SetCompare::equal != SetCompare::properSubset ); + BOOST_CHECK( SetCompare::equal != SetCompare::properSuperset ); + BOOST_CHECK( SetCompare::equal != SetCompare::disjoint ); + + BOOST_CHECK( SetCompare::properSubset != SetCompare::uncomparable ); + BOOST_CHECK( SetCompare::properSubset != SetCompare::equal ); + BOOST_CHECK( SetCompare::properSubset == SetCompare::properSubset ); + BOOST_CHECK( SetCompare::properSubset != SetCompare::properSuperset ); + BOOST_CHECK( SetCompare::properSubset != SetCompare::disjoint ); + + BOOST_CHECK( SetCompare::properSuperset != SetCompare::uncomparable ); + BOOST_CHECK( SetCompare::properSuperset != SetCompare::equal ); + BOOST_CHECK( SetCompare::properSuperset != SetCompare::properSubset ); + BOOST_CHECK( SetCompare::properSuperset == SetCompare::properSuperset ); + BOOST_CHECK( SetCompare::properSuperset != SetCompare::disjoint ); + + BOOST_CHECK( SetCompare::disjoint != SetCompare::uncomparable ); + BOOST_CHECK( SetCompare::disjoint != SetCompare::equal ); + BOOST_CHECK( SetCompare::disjoint != SetCompare::properSubset ); + BOOST_CHECK( SetCompare::disjoint != SetCompare::properSuperset ); + BOOST_CHECK( SetCompare::disjoint == SetCompare::disjoint ); +} + +BOOST_AUTO_TEST_CASE(set_relation) +{ + BOOST_CHECK( SetRelation::uncomparable == SetRelation::uncomparable ); + BOOST_CHECK( SetRelation::uncomparable != SetRelation::equal ); + BOOST_CHECK( SetRelation::uncomparable != SetRelation::properSubset ); + BOOST_CHECK( SetRelation::uncomparable != SetRelation::properSuperset ); + BOOST_CHECK( SetRelation::uncomparable != SetRelation::disjoint ); + BOOST_CHECK( SetRelation::uncomparable != SetRelation::subset ); + BOOST_CHECK( SetRelation::uncomparable != SetRelation::superset ); + + BOOST_CHECK( SetRelation::equal != SetRelation::uncomparable ); + BOOST_CHECK( SetRelation::equal == SetRelation::equal ); + BOOST_CHECK( SetRelation::equal != SetRelation::properSubset ); + BOOST_CHECK( SetRelation::equal != SetRelation::properSuperset ); + BOOST_CHECK( SetRelation::equal != SetRelation::disjoint ); + BOOST_CHECK( SetRelation::equal != SetRelation::subset ); + BOOST_CHECK( SetRelation::equal != SetRelation::superset ); + + BOOST_CHECK( SetRelation::properSubset != SetRelation::uncomparable ); + BOOST_CHECK( SetRelation::properSubset != SetRelation::equal ); + BOOST_CHECK( SetRelation::properSubset == SetRelation::properSubset ); + BOOST_CHECK( SetRelation::properSubset != SetRelation::properSuperset ); + BOOST_CHECK( SetRelation::properSubset != SetRelation::disjoint ); + BOOST_CHECK( SetRelation::properSubset != SetRelation::subset ); + BOOST_CHECK( SetRelation::properSubset != SetRelation::superset ); + + BOOST_CHECK( SetRelation::properSuperset != SetRelation::uncomparable ); + BOOST_CHECK( SetRelation::properSuperset != SetRelation::equal ); + BOOST_CHECK( SetRelation::properSuperset != SetRelation::properSubset ); + BOOST_CHECK( SetRelation::properSuperset == SetRelation::properSuperset ); + BOOST_CHECK( SetRelation::properSuperset != SetRelation::disjoint ); + BOOST_CHECK( SetRelation::properSuperset != SetRelation::subset ); + BOOST_CHECK( SetRelation::properSuperset != SetRelation::superset ); + + BOOST_CHECK( SetRelation::disjoint != SetRelation::uncomparable ); + BOOST_CHECK( SetRelation::disjoint != SetRelation::equal ); + BOOST_CHECK( SetRelation::disjoint != SetRelation::properSubset ); + BOOST_CHECK( SetRelation::disjoint != SetRelation::properSuperset ); + BOOST_CHECK( SetRelation::disjoint == SetRelation::disjoint ); + BOOST_CHECK( SetRelation::disjoint != SetRelation::subset ); + BOOST_CHECK( SetRelation::disjoint != SetRelation::superset ); + + BOOST_CHECK( SetRelation::subset != SetRelation::uncomparable ); + BOOST_CHECK( SetRelation::subset != SetRelation::equal ); + BOOST_CHECK( SetRelation::subset != SetRelation::properSubset ); + BOOST_CHECK( SetRelation::subset != SetRelation::properSuperset ); + BOOST_CHECK( SetRelation::subset != SetRelation::disjoint ); + BOOST_CHECK( SetRelation::subset == SetRelation::subset ); + BOOST_CHECK( SetRelation::subset != SetRelation::superset ); + + BOOST_CHECK( SetRelation::superset != SetRelation::uncomparable ); + BOOST_CHECK( SetRelation::superset != SetRelation::equal ); + BOOST_CHECK( SetRelation::superset != SetRelation::properSubset ); + BOOST_CHECK( SetRelation::superset != SetRelation::properSuperset ); + BOOST_CHECK( SetRelation::superset != SetRelation::disjoint ); + BOOST_CHECK( SetRelation::superset != SetRelation::subset ); + BOOST_CHECK( SetRelation::superset == SetRelation::superset ); +} + +BOOST_AUTO_TEST_CASE(set_relation_comapre) +{ + BOOST_CHECK( SetRelation::uncomparable == SetCompare::uncomparable ); + BOOST_CHECK( SetRelation::uncomparable != SetCompare::equal ); + BOOST_CHECK( SetRelation::uncomparable != SetCompare::properSubset ); + BOOST_CHECK( SetRelation::uncomparable != SetCompare::properSuperset ); + BOOST_CHECK( SetRelation::uncomparable != SetCompare::disjoint ); + + BOOST_CHECK( SetRelation::equal != SetCompare::uncomparable ); + BOOST_CHECK( SetRelation::equal == SetCompare::equal ); + BOOST_CHECK( SetRelation::equal != SetCompare::properSubset ); + BOOST_CHECK( SetRelation::equal != SetCompare::properSuperset ); + BOOST_CHECK( SetRelation::equal != SetCompare::disjoint ); + + BOOST_CHECK( SetRelation::properSubset != SetCompare::uncomparable ); + BOOST_CHECK( SetRelation::properSubset != SetCompare::equal ); + BOOST_CHECK( SetRelation::properSubset == SetCompare::properSubset ); + BOOST_CHECK( SetRelation::properSubset != SetCompare::properSuperset ); + BOOST_CHECK( SetRelation::properSubset != SetCompare::disjoint ); + + BOOST_CHECK( SetRelation::properSuperset != SetCompare::uncomparable ); + BOOST_CHECK( SetRelation::properSuperset != SetCompare::equal ); + BOOST_CHECK( SetRelation::properSuperset != SetCompare::properSubset ); + BOOST_CHECK( SetRelation::properSuperset == SetCompare::properSuperset ); + BOOST_CHECK( SetRelation::properSuperset != SetCompare::disjoint ); + + BOOST_CHECK( SetRelation::disjoint != SetCompare::uncomparable ); + BOOST_CHECK( SetRelation::disjoint != SetCompare::equal ); + BOOST_CHECK( SetRelation::disjoint != SetCompare::properSubset ); + BOOST_CHECK( SetRelation::disjoint != SetCompare::properSuperset ); + BOOST_CHECK( SetRelation::disjoint == SetCompare::disjoint ); + + BOOST_CHECK( SetRelation::subset != SetCompare::uncomparable ); + BOOST_CHECK( SetRelation::subset == SetCompare::equal ); + BOOST_CHECK( SetRelation::subset == SetCompare::properSubset ); + BOOST_CHECK( SetRelation::subset != SetCompare::properSuperset ); + BOOST_CHECK( SetRelation::subset != SetCompare::disjoint ); + + BOOST_CHECK( SetRelation::superset != SetCompare::uncomparable ); + BOOST_CHECK( SetRelation::superset == SetCompare::equal ); + BOOST_CHECK( SetRelation::superset != SetCompare::properSubset ); + BOOST_CHECK( SetRelation::superset == SetCompare::properSuperset ); + BOOST_CHECK( SetRelation::superset != SetCompare::disjoint ); +} diff --git a/tests/zypp/SetTracker_test.cc b/tests/zypp/SetTracker_test.cc new file mode 100644 index 0000000..75e091d --- /dev/null +++ b/tests/zypp/SetTracker_test.cc @@ -0,0 +1,103 @@ +#include +#include +#include +#include + +typedef std::set SetType; +namespace std +{ + inline ostream & operator<<( ostream & str, const SetType & obj ) + { return zypp::dumpRangeLine( str, obj.begin(), obj.end() ); } +} +typedef zypp::base::SetTracker Tracker; + +std::set s; +std::set s1 ({1}); +std::set s2 ({2}); +std::set s3 ({3}); +std::set s12 ({1,2}); +std::set s13 ({1,3}); +std::set s23 ({2,3}); +std::set s123 ({1,2,3}); + + +BOOST_AUTO_TEST_CASE(basic) +{ + Tracker t; + BOOST_CHECK_EQUAL( t.current(), s ); + BOOST_CHECK_EQUAL( t.added(), s ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.add( 1 ) ); + BOOST_CHECK_EQUAL( t.current(), s1 ); + BOOST_CHECK_EQUAL( t.added(), s1 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( !t.add( 1 ) ); + BOOST_CHECK_EQUAL( t.current(), s1 ); + BOOST_CHECK_EQUAL( t.added(), s1 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.add( 2 ) ); + BOOST_CHECK_EQUAL( t.current(), s12 ); + BOOST_CHECK_EQUAL( t.added(), s12 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.remove( 1 ) ); + BOOST_CHECK_EQUAL( t.current(), s2 ); + BOOST_CHECK_EQUAL( t.added(), s2 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.set( s3 ) ); + BOOST_CHECK_EQUAL( t.current(), s3 ); + BOOST_CHECK_EQUAL( t.added(), s3 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.add( 2 ) ); + BOOST_CHECK_EQUAL( t.current(), s23 ); + BOOST_CHECK_EQUAL( t.added(), s23 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.remove( 2 ) ); + BOOST_CHECK_EQUAL( t.current(), s3 ); + BOOST_CHECK_EQUAL( t.added(), s3 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( ! t.remove( 2 ) ); + BOOST_CHECK_EQUAL( t.current(), s3 ); + BOOST_CHECK_EQUAL( t.added(), s3 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.set( s ) ); + BOOST_CHECK_EQUAL( t.current(), s ); + BOOST_CHECK_EQUAL( t.added(), s ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + //---------------------------------------------------------------------- + + BOOST_CHECK( t.setInitial( s2 ) ); + BOOST_CHECK_EQUAL( t.current(), s2 ); + BOOST_CHECK_EQUAL( t.added(), s ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.set( s13 ) ); + BOOST_CHECK_EQUAL( t.current(), s13 ); + BOOST_CHECK_EQUAL( t.added(), s13 ); + BOOST_CHECK_EQUAL( t.removed(), s2 ); + + BOOST_CHECK( t.set( s123 ) ); + BOOST_CHECK_EQUAL( t.current(), s123 ); + BOOST_CHECK_EQUAL( t.added(), s13 ); + BOOST_CHECK_EQUAL( t.removed(), s ); + + BOOST_CHECK( t.set( s ) ); + BOOST_CHECK_EQUAL( t.current(), s ); + BOOST_CHECK_EQUAL( t.added(), s ); + BOOST_CHECK_EQUAL( t.removed(), s2 ); + + BOOST_CHECK( t.set( s2 ) ); + BOOST_CHECK_EQUAL( t.current(), s2 ); + BOOST_CHECK_EQUAL( t.added(), s ); + BOOST_CHECK_EQUAL( t.removed(), s ); + +} diff --git a/tests/zypp/Signature_test.cc b/tests/zypp/Signature_test.cc new file mode 100644 index 0000000..e95095a --- /dev/null +++ b/tests/zypp/Signature_test.cc @@ -0,0 +1,29 @@ + +#include +#include +#include + +#include +#include +#include + +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; + +using namespace zypp; + + +void signature_test() +{ +} + +test_suite* +init_unit_test_suite( int, char* [] ) +{ + test_suite* test= BOOST_TEST_SUITE( "SignaureTest" ); + test->add( BOOST_TEST_CASE( &signature_test ), 0 /* expected zero error */ ); + return test; +} + diff --git a/tests/zypp/StrMatcher_test.cc b/tests/zypp/StrMatcher_test.cc new file mode 100644 index 0000000..3dddf0c --- /dev/null +++ b/tests/zypp/StrMatcher_test.cc @@ -0,0 +1,210 @@ +#include "TestSetup.h" +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : Matcher +// +/////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(Match_default) +{ + Match m; + BOOST_CHECK( !m ); // eval in boolean context + BOOST_CHECK_EQUAL( m, Match::NOTHING ); + BOOST_CHECK_EQUAL( m.get(), 0 ); + + // set the mode part + BOOST_CHECK_EQUAL( m |= Match::STRING, Match::STRING ); + + m.setModeSubstring(); + BOOST_CHECK_EQUAL( m, Match::SUBSTRING ); + + m.setMode( Match::GLOB ); + BOOST_CHECK_EQUAL( m, Match::GLOB ); + + BOOST_CHECK_EQUAL( m = Match::REGEX, Match::REGEX ); + + BOOST_CHECK( m.isModeRegex() ); + m |= Match::NOCASE | Match::FILES; + BOOST_CHECK_EQUAL( m, Match::REGEX | Match::NOCASE | Match::FILES ); + + BOOST_CHECK( m.testAnyOf( Match::SUBSTRING | Match::NOCASE | Match::FILES ) ); + BOOST_CHECK( !m.test( Match::SUBSTRING | Match::NOCASE | Match::FILES ) ); + BOOST_CHECK( m.test( Match::REGEX | Match::NOCASE | Match::FILES ) ); + BOOST_CHECK( m.test( Match::NOCASE | Match::FILES ) ); + BOOST_CHECK( m != (Match::NOCASE | Match::FILES) ); + BOOST_CHECK_EQUAL( m.flags(),Match::NOCASE | Match::FILES ); + + m -= Match::NOCASE; // remove flags + BOOST_CHECK( m.test( Match::REGEX | Match::FILES ) ); + m -= Match::REGEX; + BOOST_CHECK_EQUAL( m, Match::FILES ); +} + +BOOST_AUTO_TEST_CASE(Match_operator) +{ + // Test whether implicit conversions from enum Match::Mode to + // Matcher work. There must be no difference in using mode and flag + // constants. These tests usually fail at compiletime, if some operator + // overload is missing. + // + // E.G.: + // inline Match operator|( const Match & lhs, const Match & rhs ) + // this does not cover (REGEX|SUBSTRING), because if both arguments + // are enum Mode the compiler might want to use operator|(int,int) + // instead. + + Match m( Match::GLOB ); + m = Match::GLOB; + + m |= Match::GLOB; + m = Match::SUBSTRING | Match::GLOB; + + m -= Match::GLOB; + m = Match::SUBSTRING - Match::GLOB; +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : StrMatcher +// +/////////////////////////////////////////////////////////////////// + +BOOST_AUTO_TEST_CASE(StrMatcher_defaultconstructed) +{ + StrMatcher m; + BOOST_CHECK_EQUAL( m.flags(), Match::NOTHING ); + BOOST_CHECK( !m ); // eval in boolean context + BOOST_CHECK( m.searchstring().empty() ); + BOOST_CHECK_EQUAL( m.flags(), Match() ); + // matches nothing: + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( " " ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( !m( "default" ) ); + + m.setSearchstring( "fau" ); + BOOST_CHECK( m ); // eval in boolean context +} + +BOOST_AUTO_TEST_CASE(StrMatcher_OTHER) +{ + StrMatcher m( "fau", Match::OTHER ); + BOOST_CHECK_THROW( m.compile(), MatchUnknownModeException ); +} + +BOOST_AUTO_TEST_CASE(StrMatcher_STRING) +{ + StrMatcher m( "fau" ); + BOOST_CHECK_EQUAL( m.flags(), Match::STRING ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( !m( "fault" ) ); + BOOST_CHECK( !m( "defau" ) ); + BOOST_CHECK( !m( "default" ) ); +} + +BOOST_AUTO_TEST_CASE(StrMatcher_STRINGSTART) +{ + StrMatcher m( "fau", Match::STRINGSTART ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( m( "fault" ) ); + BOOST_CHECK( !m( "defau" ) ); + BOOST_CHECK( !m( "default" ) ); +} + +BOOST_AUTO_TEST_CASE(StrMatcher_STRINGEND) +{ + StrMatcher m( "fau", Match::STRINGEND ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( !m( "fault" ) ); + BOOST_CHECK( m( "defau" ) ); + BOOST_CHECK( !m( "default" ) ); +} + +BOOST_AUTO_TEST_CASE(StrMatcher_GLOB) +{ + // GLOB must match whole word + StrMatcher m( "f[a]u", Match::GLOB ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( !m( "fault" ) ); + BOOST_CHECK( !m( "defau" ) ); + BOOST_CHECK( !m( "default" ) ); +} + +BOOST_AUTO_TEST_CASE(StrMatcher_REGEX) +{ + // REGEX matches substring (unless anchored) + StrMatcher m( "f[a]u", Match::REGEX ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( m( "fault" ) ); + BOOST_CHECK( m( "defau" ) ); + BOOST_CHECK( m( "default" ) ); + + m.setSearchstring( "^f[a]u" ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( m( "fault" ) ); + BOOST_CHECK( !m( "defau" ) ); + BOOST_CHECK( !m( "default" ) ); + + m.setSearchstring( "f[a]u$" ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( !m( "fault" ) ); + BOOST_CHECK( m( "defau" ) ); + BOOST_CHECK( !m( "default" ) ); + + m.setSearchstring( "^f[a]u$" ); + BOOST_CHECK( !m( "" ) ); + BOOST_CHECK( !m( "a" ) ); + BOOST_CHECK( m( "fau" ) ); + BOOST_CHECK( !m( "fault" ) ); + BOOST_CHECK( !m( "defau" ) ); + BOOST_CHECK( !m( "default" ) ); +} + +BOOST_AUTO_TEST_CASE(StrMatcher_RX) +{ + StrMatcher m( "fau" ); + + BOOST_CHECK( !m.isCompiled() ); + BOOST_CHECK_NO_THROW( m.compile() ); + + m.setSearchstring( "wa[" ); + BOOST_CHECK( !m.isCompiled() ); + m.setFlags( Match::REGEX ); + BOOST_CHECK( !m.isCompiled() ); + BOOST_CHECK_THROW( m.compile(), MatchInvalidRegexException ); + BOOST_CHECK( !m.isCompiled() ); + + m.setSearchstring( "wa[a]" ); + BOOST_CHECK_NO_THROW( m.compile() ); + BOOST_CHECK( m.isCompiled() ); + + BOOST_CHECK( !m( "was" ) ); + BOOST_CHECK( !m( "qwasq" ) ); + BOOST_CHECK( m( "qwaaq" ) ); +} + +#if 0 +BOOST_AUTO_TEST_CASE(StrMatcher_) +{ + base::LogControl::TmpLineWriter shutUp( new log::FileLineWriter( "/tmp/YLOG" ) ); + MIL << "GO" << endl; +} +#endif diff --git a/tests/zypp/StringV_test.cc b/tests/zypp/StringV_test.cc new file mode 100644 index 0000000..511fbb0 --- /dev/null +++ b/tests/zypp/StringV_test.cc @@ -0,0 +1,236 @@ +#include +#include +#include +#include +#include + +using std::cout; +using std::endl; +using namespace zypp::strv; + +namespace tools +{ + // Something convertible to bool + struct False { + operator bool() { return false; } + }; + + template + std::ostream & outsopt( std::ostream & str, const std::optional & v ) + { + str << "{"; + if ( v.has_value() ) + str << v.value(); + else + str << "@"; + return str << "}"; + } + + // CB data tracker + void outs( std::ostream & str, + std::optional w = std::optional(), + std::optional i = std::optional(), + std::optional f = std::optional() ) + { outsopt(str,w); outsopt(str,i); outsopt(str,f) << endl; } + +} // namespace tools + +BOOST_AUTO_TEST_CASE(WordConsumerSignature) +{ + std::string l { "0b2" }; + regex r { "^|b|$" }; + + // Check different CB signatures are correctly overloaded and invoked. + // Trace the CB calls and args passed in one big string and compare it + // with the expected. + // std::ostream & str { cout }; + std::ostringstream str; + // CB returning false + BOOST_CHECK_EQUAL( 2, splitRx( l, r, [&str](std::string_view w, unsigned i, bool f) -> bool { tools::outs(str,w,i,f); return tools::False(); } ) ); + BOOST_CHECK_EQUAL( 2, splitRx( l, r, [&str](std::string_view w, unsigned i) -> bool { tools::outs(str,w,i); return tools::False(); } ) ); + BOOST_CHECK_EQUAL( 2, splitRx( l, r, [&str](std::string_view w) -> bool { tools::outs(str,w); return tools::False(); } ) ); + BOOST_CHECK_EQUAL( 2, splitRx( l, r, [&str]() -> bool { tools::outs(str); return tools::False(); } ) ); + // CB returning true + BOOST_CHECK_EQUAL( 4, splitRx( l, r, [&str](std::string_view w, unsigned i, bool f) -> void { tools::outs(str,w,i,f); } ) ); + BOOST_CHECK_EQUAL( 4, splitRx( l, r, [&str](std::string_view w, unsigned i) -> void { tools::outs(str,w,i); } ) ); + BOOST_CHECK_EQUAL( 4, splitRx( l, r, [&str](std::string_view w) -> void { tools::outs(str,w); } ) ); + BOOST_CHECK_EQUAL( 4, splitRx( l, r, [&str]() -> void { tools::outs(str); } ) ); + // no CB + BOOST_CHECK_EQUAL( 4, splitRx( l, r ) ); + + // Trace: + BOOST_CHECK_EQUAL( str.str(), + "{}{0}{0}\n" // F1 + "{0b2}{1}{1}\n" + "{}{0}{@}\n" // F2 + "{0b2}{1}{@}\n" + "{}{@}{@}\n" // F3 + "{0b2}{@}{@}\n" + "{@}{@}{@}\n" // F4 + "{@}{@}{@}\n" + "{}{0}{0}\n" // T1 + "{0}{1}{0}\n" + "{2}{2}{0}\n" + "{}{3}{1}\n" + "{}{0}{@}\n" // T2 + "{0}{1}{@}\n" + "{2}{2}{@}\n" + "{}{3}{@}\n" + "{}{@}{@}\n" // T3 + "{0}{@}{@}\n" + "{2}{@}{@}\n" + "{}{@}{@}\n" + "{@}{@}{@}\n" // T4 + "{@}{@}{@}\n" + "{@}{@}{@}\n" + "{@}{@}{@}\n" + ); +} + +namespace tools +{ + using zypp::strv::detail::WordConsumer; + + /* Call splitter_r and check whether CB results match word_r. May CB abort at stopAt_r. */ + void checkSplit( std::function splitter_r, const std::initializer_list & words_r, + unsigned stopAt_r = -1U ) + { + //cout << "??? " << words_r.size() << endl; + auto next = words_r.begin(); + unsigned ret = splitter_r( [&]( std::string_view w, unsigned i, bool f )->bool { + //cout << " ["<"< " << ret << endl; + BOOST_CHECK_EQUAL( next, words_r.end() ); + BOOST_CHECK_EQUAL( ret, words_r.size() ); + } + + void expectRx( const std::string & l, const regex & rx, const std::initializer_list & words, unsigned stopAt = -1U ) + { checkSplit( [&](WordConsumer && wc) { return splitRx( l, rx, wc ); }, words, stopAt ); } + + void expectSp( std::string_view l, std::string_view sep, const std::initializer_list & words, unsigned stopAt = -1U ) + { checkSplit( [&](WordConsumer && wc) { return split( l, sep, wc ); }, words, stopAt ); } + + void expectTp( std::string_view l, std::string_view sep, const std::initializer_list & words, unsigned stopAt = -1U ) + { checkSplit( [&](WordConsumer && wc) { return split( l, sep, Trim::trim, wc ); }, words, stopAt ); } +} // namespace tools + + +BOOST_AUTO_TEST_CASE(splitRxResults) +{ + using tools::expectRx ; + + regex rx; // no regex, no match ==> input reported + expectRx( "", rx, {""} ); + expectRx( "0", rx, {"0"} ); + expectRx( "01", rx, {"01"} ); + expectRx( "012", rx, {"012"} ); + + rx = ""; // Empty regex, empty matches + expectRx( "", rx, {"",""} ); + expectRx( "0", rx, {"","0",""} ); + expectRx( "01", rx, {"","0","1",""} ); + expectRx( "012", rx, {"","0","1","2",""} ); + + rx = "x*"; // Empty matches as above + expectRx( "", rx, {"",""} ); + expectRx( "0", rx, {"","0",""} ); + expectRx( "01", rx, {"","0","1",""} ); + expectRx( "012", rx, {"","0","1","2",""} ); + + rx = "1*"; + expectRx( "", rx, {"",""} ); + expectRx( "0", rx, {"","0",""} ); + expectRx( "01", rx, {"","0",""} ); + expectRx( "012", rx, {"","0","2",""} ); + expectRx( "012\n", rx, {"","0","2","\n"} ); // no match behind a trailing NL + expectRx( "012\n\n", rx, {"","0","2","\n","\n"} ); // no match behind a trailing NL + + rx = "^|1|$"; + expectRx( "", rx, {"",""} ); + expectRx( "0", rx, {"","0",""} ); + expectRx( "01", rx, {"","0",""} ); + expectRx( "012", rx, {"","0","2",""} ); + expectRx( "012\n", rx, {"","0","2","\n"} ); // no match behind a trailing NL + expectRx( "012\n\n", rx, {"","0","2","\n","\n"} ); // no match behind a trailing NL +} + +BOOST_AUTO_TEST_CASE(splitResults) +{ + using tools::expectSp; + + std::string sep; // empty sep; split [[:blank:]]+; report not empty words + expectSp( "", sep, {} ); + expectSp( " ", sep, {} ); + expectSp( " ", sep, {} ); + expectSp( " 1 ", sep, {"1"} ); + expectSp( " 1 2 ", sep, {"1","2"} ); + expectSp( " 1 2 ", sep, {"1","2"} ); + expectSp( " 1 2 ", sep, {"1","2"}, 0 ); // CB aborted + expectSp( " 1 2 ", sep, {"1","2"}, 1 ); // CB aborted + + sep = ","; // not empty seps.... + expectSp( "", sep, {""} ); + expectSp( ",", sep, {"",""} ); + expectSp( ",,", sep, {"","",""} ); + expectSp( "1", sep, {"1"} ); + expectSp( ",1,", sep, {"","1",""} ); + expectSp( ",1,2,", sep, {"","1","2",""} ); + expectSp( ",1,,2,", sep, {"","1","","2",""} ); + + expectSp( " ", sep, {" "} ); + expectSp( " , ", sep, {" "," "} ); + expectSp( " , , ", sep, {" "," "," "} ); + expectSp( " 1 ", sep, {" 1 "} ); + expectSp( " , 1 , ", sep, {" "," 1 "," "} ); + expectSp( " , 1 , 2 , ", sep, {" "," 1 "," 2 "," "} ); + expectSp( " , 1 , , 2 , ", sep, {" "," 1 "," "," 2 "," "} ); + expectSp( " , 1 , , 2 , ", sep, {" "," 1 , , 2 , "}, 0 ); // CB aborted + + using tools::expectTp; // trimmed split + expectTp( " ", sep, {""} ); + expectTp( " , ", sep, {"",""} ); + expectTp( " , , ", sep, {"","",""} ); + expectTp( " 1 ", sep, {"1"} ); + expectTp( " , 1 , ", sep, {"","1",""} ); + expectTp( " , 1 , 2 , ", sep, {"","1","2",""} ); + expectTp( " , 1 , , 2 , ", sep, {"","1","","2",""} ); + expectTp( " , 1 , , 2 , ", sep, {"","1 , , 2 ,"}, 0 ); // CB aborted +} + +BOOST_AUTO_TEST_CASE(trimming) +{ + BOOST_CHECK_EQUAL( ltrim(""), "" ); + BOOST_CHECK_EQUAL( ltrim(" "), "" ); + BOOST_CHECK_EQUAL( ltrim("1"), "1" ); + BOOST_CHECK_EQUAL( ltrim(" 1"), "1" ); + BOOST_CHECK_EQUAL( ltrim("1 "), "1 " ); + BOOST_CHECK_EQUAL( ltrim(" 1 "), "1 " ); + + BOOST_CHECK_EQUAL( rtrim(""), "" ); + BOOST_CHECK_EQUAL( rtrim(" "), "" ); + BOOST_CHECK_EQUAL( rtrim("1"), "1" ); + BOOST_CHECK_EQUAL( rtrim(" 1"), " 1" ); + BOOST_CHECK_EQUAL( rtrim("1 "), "1" ); + BOOST_CHECK_EQUAL( rtrim(" 1 "), " 1" ); + + BOOST_CHECK_EQUAL( trim(""), "" ); + BOOST_CHECK_EQUAL( trim(" "), "" ); + BOOST_CHECK_EQUAL( trim("1"), "1" ); + BOOST_CHECK_EQUAL( trim(" 1"), "1" ); + BOOST_CHECK_EQUAL( trim("1 "), "1" ); + BOOST_CHECK_EQUAL( trim(" 1 "), "1" ); + + BOOST_CHECK_EQUAL( ltrim(" 1 "), trim(" 1 ", Trim::left) ); + BOOST_CHECK_EQUAL( rtrim(" 1 "), trim(" 1 ", Trim::right) ); + BOOST_CHECK_EQUAL( trim(" 1 "), trim(" 1 ", Trim::left|Trim::right) ); + + BOOST_CHECK_EQUAL( trim(" \t1\t "), "1" ); + BOOST_CHECK_EQUAL( trim(" \t1\t ", " "), "\t1\t" ); + BOOST_CHECK_EQUAL( trim(" \t1\t ", ""), " \t1\t " ); +} diff --git a/tests/zypp/Target_test.cc b/tests/zypp/Target_test.cc new file mode 100644 index 0000000..3ac9138 --- /dev/null +++ b/tests/zypp/Target_test.cc @@ -0,0 +1,56 @@ +#include +#include +#include +#include + +// Boost.Test +#include + +#include +#include +#include +#include +#include +#include + +using boost::unit_test::test_case; +using namespace zypp; +using namespace zypp::filesystem; + +BOOST_AUTO_TEST_CASE(target_test) +{ + + filesystem::TmpDir tmp; + + ZYpp::Ptr z = getZYpp(); + + // create the products.d directory + assert_dir(tmp.path() / "/etc/products.d" ); + BOOST_CHECK( copy( Pathname(TESTS_SRC_DIR) / "/zypp/data/Target/product.prod", tmp.path() / "/etc/products.d/product.prod") == 0 ); + + // make it the base product + BOOST_CHECK( symlink(tmp.path() / "/etc/products.d/product.prod", tmp.path() / "/etc/products.d/baseproduct" ) == 0 ); + + z->initializeTarget( tmp.path() ); + + // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine) + BOOST_CHECK( ! PathInfo( tmp.path() / "/var/lib/zypp/AnonymousUniqueId").isExist() ); + // create an artificial one + { + Pathname f( tmp.path() / "/var/lib/zypp" ); + filesystem::assert_dir( f ); + std::ofstream o( (f/"AnonymousUniqueId").c_str() ); + o << "AnonymousUniqueId"; + } + BOOST_CHECK( PathInfo( tmp.path() / "/var/lib/zypp/AnonymousUniqueId").isExist() ); + BOOST_CHECK_EQUAL( z->target()->anonymousUniqueId(), "AnonymousUniqueId" ); + + // now check the base product + BOOST_CHECK_EQUAL( z->target()->targetDistribution(), "sle-10-i586"); + BOOST_CHECK_EQUAL( z->target()->targetDistributionRelease(), "special_edition"); + BOOST_CHECK_EQUAL( z->target()->distributionVersion(), "10"); + + Target::DistributionLabel dlabel( z->target()->distributionLabel() ); + BOOST_CHECK_EQUAL( dlabel.summary, "A cool distribution" ); + BOOST_CHECK_EQUAL( dlabel.shortName, "" ); +} diff --git a/tests/zypp/Url_test.cc b/tests/zypp/Url_test.cc new file mode 100644 index 0000000..00ee9eb --- /dev/null +++ b/tests/zypp/Url_test.cc @@ -0,0 +1,318 @@ +/* +** Check if the url by scheme repository works, e.g. +** if there are some initialization order problems +** (ViewOption) causing asString to format its string +** differently than configured. +*/ + +#include +#include + +#include + +#include +#include +#include +#include + +// Boost.Test +#include + +using boost::unit_test::test_case; +using namespace zypp; + +void testUrlAuthority( const Url & url_r, + const std::string & host_r, const std::string & port_r = std::string(), + const std::string & user_r = std::string(), const std::string & pass_r = std::string() ) +{ + BOOST_CHECK_EQUAL( url_r.getUsername(), user_r ); + BOOST_CHECK_EQUAL( url_r.getPassword(), pass_r ); + BOOST_CHECK_EQUAL( url_r.getHost(), host_r ); + BOOST_CHECK_EQUAL( url_r.getPort(), port_r ); +} + + +BOOST_AUTO_TEST_CASE(test_ipv6_url) +{ + std::string str; + zypp::Url url; + + str = "http://[2001:DB8:0:F102::1]/64/sles11/RC1/CD1?device=eth0"; + url = Url( str ); + BOOST_CHECK_EQUAL( str,url.asString() ); + testUrlAuthority( url, "[2001:DB8:0:F102::1]", "", "", "" ); + + // bnc# + str = "http://[2001:DB8:0:F102::1]:8080/64/sles11/RC1/CD1?device=eth0"; + url = Url( str ); + testUrlAuthority( url, "[2001:DB8:0:F102::1]", "8080", "", "" ); + + + str = "http://user:pass@[2001:DB8:0:F102::1]:8080/64/sles11/RC1/CD1?device=eth0"; + url = Url( str ); + testUrlAuthority( url, "[2001:DB8:0:F102::1]", "8080", "user", "pass" ); +} + +BOOST_AUTO_TEST_CASE(test_url1) +{ + std::string str, one, two; + zypp::Url url; + + + // asString & asCompleteString should not print "mailto://" + str = "mailto:feedback@example.com?subject=hello"; + url = str; + BOOST_CHECK_EQUAL( str, url.asString() ); + BOOST_CHECK_EQUAL( str, url.asCompleteString() ); + + // In general, schema without authority allows specifying an empty authority + // though it should not be printed (unless explicitly requested). + BOOST_CHECK_EQUAL( Url("dvd:/srv/ftp").asCompleteString(), "dvd:/srv/ftp" ); + BOOST_CHECK_EQUAL( Url("dvd:/srv/ftp").asString(), "dvd:/srv/ftp" ); + + BOOST_CHECK_EQUAL( Url("dvd:///srv/ftp").asCompleteString(), "dvd:/srv/ftp" ); + BOOST_CHECK_EQUAL( Url("dvd:///srv/ftp").asString(), "dvd:/srv/ftp" ); + + BOOST_CHECK_EQUAL( Url("dvd:///srv/ftp").asString(url::ViewOption::DEFAULTS+url::ViewOption::EMPTY_AUTHORITY), "dvd:///srv/ftp" ); + BOOST_CHECK_EQUAL( Url("dvd:///srv/ftp").asString(url::ViewOption::DEFAULTS-url::ViewOption::EMPTY_AUTHORITY), "dvd:/srv/ftp" ); + + BOOST_CHECK_THROW( Url("dvd://authority/srv/ftp"), url::UrlNotAllowedException ); + + // asString shouldn't print the password, asCompleteString should + // further, the "//" at the begin of the path should become "/%2F" + str = "ftp://user:pass@localhost//srv/ftp"; + one = "ftp://user@localhost/%2Fsrv/ftp"; + two = "ftp://user:pass@localhost/%2Fsrv/ftp"; + url = str; + + BOOST_CHECK_EQUAL( one, url.asString() ); + BOOST_CHECK_EQUAL( two, url.asCompleteString() ); + + // asString shouldn't print the password, asCompleteString should. + // further, the "//" at the begin of the path should be keept. + str = "http://user:pass@localhost//srv/ftp?proxypass=@PROXYPASS@&proxy=proxy.my&proxyuser=@PROXYUSER@&Xproxypass=NOTTHIS&proxypass=@PROXYPASS@&proxypass=@PROXYPASS@"; + one = "http://user@localhost//srv/ftp?proxy=proxy.my&proxyuser=@PROXYUSER@&Xproxypass=NOTTHIS"; + two = str; + url = str; + + BOOST_CHECK_EQUAL( one, url.asString() ); + BOOST_CHECK_EQUAL( two, url.asCompleteString() ); + // hidden proxypass in the query is available when explicitly asked for + BOOST_CHECK_EQUAL( url.getQueryParam( "proxypass" ), "@PROXYPASS@" ); + + // absolute path defaults to 'file://' + str = "/some/local/path"; + BOOST_CHECK_EQUAL( zypp::Url(str).asString(), "file://"+str ); + + str = "file:./srv/ftp"; + BOOST_CHECK_EQUAL( zypp::Url(str).asString(), str ); + + str = "ftp://foo//srv/ftp"; + BOOST_CHECK_EQUAL( zypp::Url(str).asString(), "ftp://foo/%2Fsrv/ftp" ); + + str = "FTP://user@local%68ost/%2f/srv/ftp"; + BOOST_CHECK_EQUAL( zypp::Url(str).asString(), "ftp://user@localhost/%2f/srv/ftp" ); + + str = "http://[::1]/foo/bar"; + BOOST_CHECK_EQUAL( str, zypp::Url(str).asString() ); + + str = "http://:@just-localhost.example.net:8080/"; + BOOST_CHECK_EQUAL( zypp::Url(str).asString(), "http://just-localhost.example.net:8080/" ); + + str = "mailto:feedback@example.com?subject=hello"; + BOOST_CHECK_EQUAL( str, zypp::Url(str).asString() ); + + str = "nfs://nfs-server/foo/bar/trala"; + BOOST_CHECK_EQUAL( str, zypp::Url(str).asString() ); + + str = "ldap://example.net/dc=example,dc=net?cn,sn?sub?(cn=*)#x"; + BOOST_CHECK_THROW( zypp::Url(str).asString(), url::UrlNotAllowedException ); + + str = "ldap://example.net/dc=example,dc=net?cn,sn?sub?(cn=*)"; + BOOST_CHECK_EQUAL( str, zypp::Url(str).asString() ); + + // parseable but invalid, since no host avaliable + str = "ldap:///dc=foo,dc=bar"; + BOOST_CHECK_EQUAL( str, zypp::Url(str).asString()); + BOOST_CHECK( !zypp::Url(str).isValid()); + + // throws: host is mandatory + str = "ftp:///foo/bar"; + BOOST_CHECK_THROW(zypp::Url(str).asString(), url::UrlNotAllowedException ); + + // throws: host is mandatory + str = "http:///%2f/srv/ftp"; + BOOST_CHECK_THROW(zypp::Url(str).asString(), url::UrlNotAllowedException ); + + // OK, host allowed in file-url + str = "file://localhost/some/path"; + BOOST_CHECK_EQUAL( str, zypp::Url(str).asString()); + + // throws: host not allowed + str = "cd://localhost/some/path"; + BOOST_CHECK_THROW(zypp::Url(str).asString(), url::UrlNotAllowedException ); + + // throws: no path (email) + str = "mailto:"; + BOOST_CHECK_THROW(zypp::Url(str).asString(), url::UrlNotAllowedException ); + + // throws: no path + str = "cd:"; + BOOST_CHECK_THROW(zypp::Url(str).asString(), url::UrlNotAllowedException ); + + // OK, valid (no host, path is there) + str = "cd:///some/path"; + BOOST_CHECK( zypp::Url(str).isValid()); +} + +BOOST_AUTO_TEST_CASE(test_url2) +{ + zypp::Url url("http://user:pass@localhost:/path/to;version=1.1?arg=val#frag"); + + BOOST_CHECK_EQUAL( url.asString(), + "http://user@localhost/path/to?arg=val#frag" ); + + BOOST_CHECK_EQUAL( url.asString(zypp::url::ViewOptions() + + zypp::url::ViewOptions::WITH_PASSWORD), + "http://user:pass@localhost/path/to?arg=val#frag"); + + BOOST_CHECK_EQUAL( url.asString(zypp::url::ViewOptions() + + zypp::url::ViewOptions::WITH_PATH_PARAMS), + "http://user@localhost/path/to;version=1.1?arg=val#frag"); + + BOOST_CHECK_EQUAL( url.asCompleteString(), + "http://user:pass@localhost/path/to;version=1.1?arg=val#frag"); +} + +BOOST_AUTO_TEST_CASE(test_url3) +{ + zypp::Url url("http://localhost/path/to#frag"); + std::string key; + std::string val; + + // will be encoded as "hoho=ha%20ha" + key = "hoho"; + val = "ha ha"; + url.setQueryParam(key, val); + BOOST_CHECK_EQUAL( url.asString(), + "http://localhost/path/to?hoho=ha%20ha#frag"); + + // will be encoded as "foo%3Dbar%26key=foo%26bar%3Dvalue" + key = "foo=bar&key"; + val = "foo&bar=value"; + url.setQueryParam(key, val); + BOOST_CHECK_EQUAL( url.asString(), + "http://localhost/path/to?foo%3Dbar%26key=foo%26bar%3Dvalue&hoho=ha%20ha#frag"); + + // will be encoded as "foo%25bar=is%25de%25ad" + key = "foo%bar"; + val = "is%de%ad"; + url.setQueryParam(key, val); + BOOST_CHECK_EQUAL( url.asString(), + "http://localhost/path/to?foo%25bar=is%25de%25ad&foo%3Dbar%26key=foo%26bar%3Dvalue&hoho=ha%20ha#frag"); + + // get encoded query parameters and compare with results: + zypp::url::ParamVec params( url.getQueryStringVec()); + const char * const result[] = { + "foo%25bar=is%25de%25ad", + "foo%3Dbar%26key=foo%26bar%3Dvalue", + "hoho=ha%20ha" + }; + BOOST_CHECK( params.size() == (sizeof(result)/sizeof(result[0]))); + for( size_t i=0; ifirst) + { + BOOST_CHECK_EQUAL( m->second, "cn,sn"); + } + else + if("filter" == m->first) + { + BOOST_CHECK_EQUAL( m->second, "(cn=*)"); + } + else + if("scope" == m->first) + { + BOOST_CHECK_EQUAL( m->second, "sub"); + } + else + { + BOOST_FAIL("Unexpected LDAP query parameter name in the map!"); + } + } + + url.setQueryParam("attrs", "cn,sn,uid"); + url.setQueryParam("filter", "(|(sn=foo)(cn=bar))"); + + BOOST_CHECK_EQUAL(url.getQueryParam("attrs"), "cn,sn,uid"); + BOOST_CHECK_EQUAL(url.getQueryParam("filter"), "(|(sn=foo)(cn=bar))"); + + } + catch(const zypp::url::UrlException &e) + { + ZYPP_CAUGHT(e); + } +} + +BOOST_AUTO_TEST_CASE( test_url5) +{ + std::string str( "file:/some/${var:+path}/${var:-with}/${vars}" ); + BOOST_CHECK_EQUAL( Url(str).asString(), str ); + BOOST_CHECK_EQUAL( Url(zypp::url::encode( str, URL_SAFE_CHARS )).asString(), str ); +} + +BOOST_AUTO_TEST_CASE(plugin_scriptpath) +{ + // plugin script path must not be rewritten + for ( const std::string & t : { "script", "script/", "/script", "/script/", "./script", "./script/" } ) + { + BOOST_CHECK_EQUAL( Url("plugin:"+t).getPathName(), t ); + } + + { // more cosmetic issue, but the RepoVarReplacer should + // not change the string representation (-> "plugin:/script") + Url u( "plugin:script?opt=val" ); + RepoInfo i; + i.setBaseUrl( u ); + BOOST_CHECK_EQUAL( u.asString(), i.url().asString() ); + } + +} + +BOOST_AUTO_TEST_CASE(plugin_querystring_args) +{ + // url querysting options without value must be possible + // e.g. for plugin schema + Url u( "plugin:script?loptv=lvalue&v=optv&lopt=&o" ); + url::ParamMap pm( u.getQueryStringMap() ); + BOOST_CHECK_EQUAL( pm.size(), 4 ); + BOOST_CHECK_EQUAL( pm["loptv"], "lvalue" ); + BOOST_CHECK_EQUAL( pm["v"], "optv" ); + BOOST_CHECK_EQUAL( pm["lopt"], "" ); + BOOST_CHECK_EQUAL( pm["o"], "" ); +} + +// vim: set ts=2 sts=2 sw=2 ai et: diff --git a/tests/zypp/UserData_test.cc b/tests/zypp/UserData_test.cc new file mode 100644 index 0000000..d8522bb --- /dev/null +++ b/tests/zypp/UserData_test.cc @@ -0,0 +1,87 @@ +#include +#include +#include +#include + +using std::cout; +using std::endl; + +using zypp::callback::UserData; +const std::string key( "key" ); + +#define checkIsEmpty(v) \ + BOOST_CHECK( !v ); \ + BOOST_CHECK( v.empty() ); \ + BOOST_CHECK_EQUAL( v.size(), 0 ); \ + BOOST_CHECK_EQUAL( v.haskey( key ), false ); \ + BOOST_CHECK_EQUAL( v.hasvalue( key ), false ); \ + BOOST_CHECK_EQUAL( v.getvalue( key ).empty(), true ); + +#define checkIsNotEmpty(v,s) \ + BOOST_CHECK( v ); \ + BOOST_CHECK( !v.empty() ); \ + if ( s ) \ + { BOOST_CHECK_EQUAL( v.size(), s ); } \ + else \ + { BOOST_CHECK( v.size() ); } \ + BOOST_CHECK_EQUAL( v.haskey( key ), true ); + + +BOOST_AUTO_TEST_CASE(useruata_default) +{ + UserData v; + checkIsEmpty( v ); + + // set key with empty value + v.reset( key ); + checkIsNotEmpty( v, 1 ); + BOOST_CHECK_EQUAL( v.hasvalue( key ), false ); + BOOST_CHECK_EQUAL( v.getvalue( key ).empty(), true ); + + std::string rs; + unsigned ru = 0; + int ri = 0; + char rc = 0; + + // set key with value + v.set( key, 42 ); + BOOST_CHECK_EQUAL( v.hasvalue( key ), true ); + BOOST_CHECK_EQUAL( v.getvalue( key ).empty(), false ); + + // get back data + BOOST_CHECK_EQUAL( v.get( key, rs ), false ); + BOOST_CHECK_EQUAL( v.get( key, ru ), false ); + BOOST_CHECK_EQUAL( v.get( key, ri ), true ); + BOOST_CHECK_EQUAL( v.get( key, rc ), false ); + BOOST_CHECK_EQUAL( ru, 0 ); + BOOST_CHECK_EQUAL( ri, 42 ); + BOOST_CHECK_EQUAL( rc, 0 ); + + v.set( key, 43U ); + BOOST_CHECK_EQUAL( v.get( key, rs ), false ); + BOOST_CHECK_EQUAL( v.get( key, ru ), true ); + BOOST_CHECK_EQUAL( v.get( key, ri ), false ); + BOOST_CHECK_EQUAL( v.get( key, rc ), false ); + BOOST_CHECK_EQUAL( ru, 43 ); + BOOST_CHECK_EQUAL( ri, 42 ); + BOOST_CHECK_EQUAL( rc, 0 ); + + // set key with empty value + v.reset( key ); + BOOST_CHECK_EQUAL( v.hasvalue( key ), false ); + BOOST_CHECK_EQUAL( v.getvalue( key ).empty(), true ); + checkIsNotEmpty( v, 1 ); + + // erase key + v.erase( key ); + BOOST_CHECK_EQUAL( v.hasvalue( key ), false ); + BOOST_CHECK_EQUAL( v.getvalue( key ).empty(), true ); + checkIsEmpty( v ); + + // const may add but not manip non-empty values + const UserData & cv( v ); + BOOST_CHECK_EQUAL( cv.reset( key ), true ); // add new key: ok + BOOST_CHECK_EQUAL( cv.set( key, 42 ), true ); // empty -> non-empty: ok + BOOST_CHECK_EQUAL( cv.set( key, 43 ), false );// change non-empty: not ok + BOOST_CHECK_EQUAL( cv.reset( key ), false ); // change non-empty: not ok +} diff --git a/tests/zypp/Vendor_test.cc b/tests/zypp/Vendor_test.cc new file mode 100644 index 0000000..355ad27 --- /dev/null +++ b/tests/zypp/Vendor_test.cc @@ -0,0 +1,94 @@ + +#include +#include +#include + +// Boost.Test +#include + +#include +#include +#include +#include + +using boost::unit_test::test_case; +using namespace zypp; +using std::cout; +using std::endl; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/data/Vendor") + +BOOST_AUTO_TEST_CASE(vendor_empty) +{ + VendorAttr::noTargetInstance() = VendorAttr(); // suse defaults; no configfiles read + + BOOST_REQUIRE( VendorAttr::instance().equivalent("", "") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("a", "") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("", "a") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("a", "a") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("a", "aa") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("aa", "a") ); + + BOOST_REQUIRE( VendorAttr::instance().equivalent( IdString::Null, IdString::Null ) ); + BOOST_REQUIRE( VendorAttr::instance().equivalent( IdString::Empty, IdString::Null ) ); + BOOST_REQUIRE( VendorAttr::instance().equivalent( IdString::Null, IdString::Empty ) ); + BOOST_REQUIRE( VendorAttr::instance().equivalent( IdString::Empty, IdString::Empty ) ); +} + +BOOST_AUTO_TEST_CASE(vendor_test1) +{ + + VendorAttr::noTargetInstance() = VendorAttr(); // suse defaults; no configfiles read + // bsc#1030686: Remove legacy vendor equivalence between 'suse' and 'opensuse' + // No vendor definition files has been read. So only suse* vendors are + // equivalent + BOOST_REQUIRE( VendorAttr::instance().equivalent("suse", "SuSE as prefix") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("SuSE as prefix", "suse") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("SuSE as prefix","foreign") ); + // bnc#812608: All opensuse projects get their own class (no prefix compare in opensuse namespace) + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse", "SuSE as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse as prefix", "SuSE as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse", "opensuse as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse as prefix", "opensuse but different prefix") ); + + // bsc#1182629: relaxed equivalence just adds suse/opensuse + BOOST_REQUIRE( !VendorAttr::instance().relaxedEquivalent("SuSE as prefix","foreign") ); + BOOST_REQUIRE( VendorAttr::instance().relaxedEquivalent("opensuse", "SuSE as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().relaxedEquivalent("opensuse as prefix", "SuSE as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().relaxedEquivalent("opensuse", "opensuse as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().relaxedEquivalent("opensuse as prefix", "opensuse but different prefix") ); +} + +BOOST_AUTO_TEST_CASE(vendor_test2) +{ + VendorAttr::noTargetInstance() = VendorAttr( DATADIR / "vendors.d" ); + + BOOST_REQUIRE( VendorAttr::instance().equivalent("suse", "suse") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("equal", "equal") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("suse", "SuSE") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse", "SuSE") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("open", "SuSE") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("nothing", "SuSE") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("nvidia", "SuSE") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("nvidia_new_new", "SuSE") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("nvidia", "opensuse") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("ati", "SuSE") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("ati", "nvidia") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("ati_new", "ati") ); +} + +BOOST_AUTO_TEST_CASE(vendor_test3) +{ + VendorAttr::noTargetInstance() = VendorAttr(); // suse defaults; no configfiles read + VendorAttr::noTargetInstance().addVendorList( { "suse", "opensuse", "opensuse too" } ); + + BOOST_REQUIRE( VendorAttr::instance().equivalent("SuSE as prefix", "opensuse") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("SuSE as prefix", "opensuse too") ); + BOOST_REQUIRE( VendorAttr::instance().equivalent("opensuse", "opensuse too") ); + // bnc#812608: All opensuse projects get their own class (no prefix compare in opensuse namespace) + BOOST_REQUIRE( !VendorAttr::instance().equivalent("SuSE as prefix", "opensuse as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("SuSE as prefix", "opensuse too as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse", "opensuse too as prefix") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse as prefix", "opensuse too") ); + BOOST_REQUIRE( !VendorAttr::instance().equivalent("opensuse as prefix", "opensuse too as prefix") ); +} diff --git a/tests/zypp/ZChunk_test.cc b/tests/zypp/ZChunk_test.cc new file mode 100644 index 0000000..7789f82 --- /dev/null +++ b/tests/zypp/ZChunk_test.cc @@ -0,0 +1,33 @@ +// Boost.Test +#include + +#include +#include +#include +#include + +BOOST_AUTO_TEST_CASE(zchunk_simple_read_write) +{ + const zypp::Pathname file = zypp::Pathname(TESTS_BUILD_DIR) / "test.zck"; + const std::string testString("HelloWorld"); + + { + zypp::ofzckstream strOut( file.c_str() ); + BOOST_REQUIRE( strOut.is_open() ); + strOut << testString; + } + + BOOST_REQUIRE_EQUAL( zypp::filesystem::zipType( file ), zypp::filesystem::ZT_ZCHNK ); + + { + std::string test; + zypp::ifzckstream str( file.c_str() ); + str >> test; + BOOST_REQUIRE_EQUAL( test, testString ); + } + + { + zypp::InputStream iStr( file ); + BOOST_REQUIRE( typeid( iStr.stream() ) == typeid( zypp::ifzckstream& ) ); + } +} diff --git a/tests/zypp/base/CMakeLists.txt b/tests/zypp/base/CMakeLists.txt new file mode 100644 index 0000000..adac9eb --- /dev/null +++ b/tests/zypp/base/CMakeLists.txt @@ -0,0 +1,4 @@ +ADD_TESTS(Glob ) +ADD_TESTS(Sysconfig ) +ADD_TESTS(String ) +ADD_TESTS(ExternalProgram ) diff --git a/tests/zypp/base/ExternalProgram_test.cc b/tests/zypp/base/ExternalProgram_test.cc new file mode 100644 index 0000000..7f7789e --- /dev/null +++ b/tests/zypp/base/ExternalProgram_test.cc @@ -0,0 +1,268 @@ +#include "TestSetup.h" +#include "TestTools.h" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#define BOOST_TEST_MODULE ExternalProgram +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/base/data/ExternalProgram") + +using zypp::ExternalProgram; + +BOOST_AUTO_TEST_CASE( Basic ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"Hello\";sleep 1;echo \"I'm the second line\";exit 123;", + nullptr + }; + ExternalProgram proc( argv, ExternalProgram::Normal_Stderr ); + BOOST_CHECK( proc.running() ); + + const auto pid = proc.getpid(); + BOOST_REQUIRE ( pid != -1 ); + std::string line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("Hello\n") ); + line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("I'm the second line\n") ); + int exitCode = proc.close(); + BOOST_REQUIRE( !proc.running() ); + BOOST_REQUIRE_EQUAL( proc.getpid(), -1 ); + BOOST_REQUIRE_EQUAL( exitCode, 123 ); + BOOST_REQUIRE_LT ( ::getpgid( pid ) , 0 ); +} + +BOOST_AUTO_TEST_CASE( StderrToStdout ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"Hello\";sleep 1;echo \"I'm the second line\" >&2;", + nullptr + }; + ExternalProgram proc( argv, ExternalProgram::Stderr_To_Stdout ); + BOOST_CHECK( proc.running() ); + BOOST_REQUIRE ( proc.getpid() != -1 ); + std::string line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("Hello\n") ); + line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("I'm the second line\n") ); + proc.close(); + BOOST_REQUIRE( !proc.running() ); + BOOST_REQUIRE_EQUAL( proc.getpid(), -1 ); +} + +BOOST_AUTO_TEST_CASE( SetEnv ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"${ZYPPENV}\"", + nullptr + }; + ExternalProgram proc( argv, ExternalProgram::Environment{ std::make_pair("ZYPPENV", "Hello from env") }, ExternalProgram::Normal_Stderr ); + std::string line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("Hello from env\n") ); + proc.close(); +} + +// environment of the parent has to be in the child process as well +// some code paths rely on that +BOOST_AUTO_TEST_CASE( ParentEnv ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"${PARENTENV}${ZYPPENV}\"", + nullptr + }; + + setenv( "PARENTENV", "Hello from", 0 ); + + ExternalProgram proc( argv, ExternalProgram::Environment{ std::make_pair("ZYPPENV", " env") }, ExternalProgram::Normal_Stderr ); + std::string line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("Hello from env\n") ); + proc.close(); + + unsetenv( "PARENTENV" ); +} + +// weird feature to redirect stdout and stderr +BOOST_AUTO_TEST_CASE( RedirectStdoutAndStderrWithChdir ) +{ + zypp::filesystem::TmpDir dir; + + const zypp::Pathname stdoutPath( dir.path()/"stdout" ); + const zypp::Pathname stderrPath( dir.path()/"stderr" ); + + const std::string stdoutRedir( zypp::str::form(">%s", stdoutPath.c_str() ) ); + const std::string chDir( zypp::str::form("#%s", dir.path().c_str() ) ); + zypp::AutoFD stdErrRedir( ::open( stderrPath.c_str() , O_CREAT | O_RDWR, 0666 ) ); + + BOOST_REQUIRE( *stdErrRedir != -1 ); + + const char *argv[] = { + chDir.c_str(), + stdoutRedir.c_str(), + "bash", + "-c", + "echo \"Hello on stdout\";echo \"Hello on stderr\" >&2;echo \"Hello on file in chdir\" > chdirfile", + nullptr + }; + + ExternalProgram proc (argv, ExternalProgram::Stderr_To_FileDesc, false, *stdErrRedir ); + + int exitCode = proc.close(); + BOOST_REQUIRE( !proc.running() ); + BOOST_REQUIRE_EQUAL( exitCode, 0 ); + + ::close( *stdErrRedir ); + *stdErrRedir = -1; + + BOOST_REQUIRE_EQUAL( TestTools::readFile( stdoutPath ), "Hello on stdout\n"); + BOOST_REQUIRE_EQUAL( TestTools::readFile( stderrPath ), "Hello on stderr\n"); + BOOST_REQUIRE_EQUAL( TestTools::readFile( dir.path() / "chdirfile" ), "Hello on file in chdir\n"); +} + +BOOST_AUTO_TEST_CASE( LongRunningEcho ) +{ + const auto executable = DATADIR/"echo.sh"; + const char *argv[] = { + executable.c_str(), + nullptr + }; + + ExternalProgram proc (argv, ExternalProgram::Normal_Stderr ); + BOOST_REQUIRE( proc.running() ); + BOOST_REQUIRE( proc.send( "Hello" ) ); + BOOST_REQUIRE( proc.send( " my friend\n" ) ); + BOOST_REQUIRE( proc.send( "How are you today\n" ) ); + BOOST_REQUIRE_EQUAL( proc.receiveLine(), "Hello my friend\n" ); + BOOST_REQUIRE_EQUAL( proc.receiveLine(), "How are you today\n" ); + + BOOST_REQUIRE( proc.running() ); + BOOST_REQUIRE( proc.send( "q\n" ) ); + const auto res = proc.close(); + BOOST_REQUIRE_EQUAL( res, 0 ); +} + +BOOST_AUTO_TEST_CASE( SendSignal ) +{ + const auto executable = DATADIR/"echo.sh"; + const char *argv[] = { + executable.c_str(), + nullptr + }; + + ExternalProgram proc (argv, ExternalProgram::Normal_Stderr ); + BOOST_REQUIRE( proc.running() ); + proc.kill( SIGTERM ); + const auto exitCode = proc.close(); + BOOST_REQUIRE_EQUAL( exitCode, SIGTERM+128 ); +} + +BOOST_AUTO_TEST_CASE( CleanerThread_default ) +{ + pid_t pid = -1; + { + ExternalProgram proc( "bash -c 'sleep 2'", ExternalProgram::Normal_Stderr ); + BOOST_CHECK( proc.running() ); + pid = proc.getpid(); + } + std::this_thread::sleep_for( std::chrono::seconds(4) ); + // check if the process is really gone, can't use waitpid because some ExternalProgram + // implementations do spawn processes from a helper thread which means they are not our direct children + BOOST_CHECK_EQUAL( ::getpgid( pid ), -1 ); + BOOST_CHECK_EQUAL( errno, ESRCH ); +} + +BOOST_AUTO_TEST_CASE( ReadTimeout ) +{ + static const char* argv[] = { "sleep", "2", NULL }; + ExternalProgram prog( argv, ExternalProgram::Discard_Stderr ); + BOOST_CHECK_THROW( prog.receiveLine( 100 ), io::TimeoutException ); + BOOST_CHECK_EQUAL( prog.receiveLine( 3000 ), "" ); + BOOST_CHECK_EQUAL( prog.close(), 0 ); +} + +BOOST_AUTO_TEST_CASE( CloseFDs ) +{ + // simple bash script that counts the number of open fds, 4 is the minimum since ls opens one fd to read the /proc/self/fd + std::string_view script ( "if [ $( ls /proc/self/fd | wc -l ) -gt \"4\" ]; then exit 1; fi; exit 0" ); + + const char *argv[] = { + "bash", + "-c", + script.data(), + nullptr + }; + + // open random fds we definitely can read to get higher nr of fds + zypp::AutoFD testFD( ::open( "/proc/self/fd", O_RDONLY ) ); + zypp::AutoFD testFD2( ::open( "/proc/self/fd", O_RDONLY ) ); + + ExternalProgram proc( argv, ExternalProgram::Discard_Stderr ); + const auto exitCode = proc.close(); + BOOST_REQUIRE_EQUAL( exitCode, 0 ); +} + +BOOST_AUTO_TEST_CASE( WaitForExit ) +{ + ExternalProgram proc( "bash -c 'sleep 2'", ExternalProgram::Normal_Stderr ); + BOOST_CHECK( proc.running() ); + auto start = zyppng::Timer::now(); + BOOST_CHECK( !proc.waitForExit( 500 ) ); + BOOST_REQUIRE_LT( zyppng::Timer::elapsedSince( start), 1000 ); + BOOST_CHECK( proc.waitForExit() ); +} + + +void handler(int signo, siginfo_t *info, void *context) +{ /* do nothing */ } + +BOOST_AUTO_TEST_CASE(readline_sigalrm) +{ + struct sigaction act = { {0} }; + struct sigaction oldAct = { {0} }; + act.sa_flags = SA_SIGINFO; + act.sa_sigaction = &handler; + sigaction(SIGALRM, &act, &oldAct); + + struct itimerval t = { {0} }; + t.it_interval.tv_sec = 42; + t.it_value.tv_sec = 1; + setitimer(ITIMER_REAL, &t, NULL); + + ExternalProgram::Arguments cmd; + cmd.push_back("sh"); + cmd.push_back("-c"); + cmd.push_back("sleep 2; echo license.de.txt"); + + LocaleSet ret; + ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout ); + + std::string received; + for ( std::string output( prog.receiveLine() ); output.length() ; output = prog.receiveLine( ) ) { + received += output; + } + prog.close(); + + BOOST_REQUIRE( !received.empty() ); + BOOST_REQUIRE_EQUAL( received, "license.de.txt\n"); + + // disable timer and handler + sigaction(SIGALRM, &oldAct, NULL); + t.it_interval.tv_sec = 0; + t.it_value.tv_sec = 0; + setitimer(ITIMER_REAL, &t, NULL); + +} diff --git a/tests/zypp/base/Glob_test.cc b/tests/zypp/base/Glob_test.cc new file mode 100644 index 0000000..49e2e5e --- /dev/null +++ b/tests/zypp/base/Glob_test.cc @@ -0,0 +1,59 @@ +#include "TestSetup.h" +#include +#include + +#define BOOST_TEST_MODULE Glob + +static Pathname TEST_ROOT( TESTS_SRC_DIR"/zypp/base/Glob_test.dat" ); + +using filesystem::Glob; + +BOOST_AUTO_TEST_CASE(Glob_default) +{ + // enable loging for the scope of this block: + // base::LogControl::TmpLineWriter shutUp( new log::FileLineWriter( "-" ) ); + Glob q; + BOOST_CHECK( q.empty() ); + BOOST_CHECK( q.size() == 0 ); + BOOST_CHECK_EQUAL( q.begin(), q.end() ); + BOOST_CHECK( q.defaultFlags() == Glob::Flags() ); + + q.add( TEST_ROOT/"file" ); + BOOST_CHECK( ! q.empty() ); + BOOST_CHECK( q.size() == 1 ); + BOOST_CHECK_NE( q.begin(), q.end() ); + BOOST_CHECK_EQUAL( *q.begin(), TEST_ROOT/"file" ); + + q.reset( Glob::kBrace ); + BOOST_CHECK( q.empty() ); + BOOST_CHECK( q.size() == 0 ); + BOOST_CHECK_EQUAL( q.begin(), q.end() ); + BOOST_CHECK( q.defaultFlags() == Glob::kBrace ); + + q.add( TEST_ROOT/"file*" ); + BOOST_CHECK( q.size() == 3 ); + + q.add( TEST_ROOT/"*{.xml,.xml.gz}" ); + BOOST_CHECK( q.size() == 5 ); + + q.clear(); // no flags reset: Glob::kBrace active + BOOST_CHECK( q.size() == 0 ); + + q.add( TEST_ROOT/"*{.xml,.xml.gz}" ); + BOOST_CHECK( q.size() == 2 ); + + q.reset(); // flags reset: Glob::kBrace off + BOOST_CHECK( q.size() == 0 ); + + q.add( TEST_ROOT/"*{.xml,.xml.gz}" ); + BOOST_CHECK( q.size() == 0 ); +} + +BOOST_AUTO_TEST_CASE(Glob_static) +{ + std::set q; + Glob::collect( TEST_ROOT/"*{.xml,.xml.gz}", Glob::kBrace, std::inserter( q, q.begin() ) ); + BOOST_REQUIRE( q.size() == 2 ); + BOOST_CHECK_EQUAL( *q.begin(), TEST_ROOT/"file.xml" ); + BOOST_CHECK_EQUAL( *++q.begin(), TEST_ROOT/"file.xml.gz" ); +} diff --git a/tests/zypp/base/Glob_test.dat/file b/tests/zypp/base/Glob_test.dat/file new file mode 100644 index 0000000..e69de29 diff --git a/tests/zypp/base/Glob_test.dat/file.xml b/tests/zypp/base/Glob_test.dat/file.xml new file mode 100644 index 0000000..e69de29 diff --git a/tests/zypp/base/Glob_test.dat/file.xml.gz b/tests/zypp/base/Glob_test.dat/file.xml.gz new file mode 100644 index 0000000..e69de29 diff --git a/tests/zypp/base/String_test.cc b/tests/zypp/base/String_test.cc new file mode 100644 index 0000000..0a6fb16 --- /dev/null +++ b/tests/zypp/base/String_test.cc @@ -0,0 +1,483 @@ +#include + +#include +#include +#include +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; +using namespace boost::unit_test; + +using namespace zypp; +using namespace zypp::str; + +#define RXspecial "\\^.[$()|*+?{" + +BOOST_AUTO_TEST_CASE(str2rx) +{ + char s[] = "c"; + char x[] = "\\c"; + for ( const char * ch = RXspecial; *ch; ++ch ) + { + s[0] = x[1] = *ch; + BOOST_CHECK_EQUAL( str::rxEscapeStr( s ), x ); + } +} + +BOOST_AUTO_TEST_CASE(glob2rx) +{ + { + char s[] = "c"; + char x[] = "\\c"; + for ( const char * ch = RXspecial; *ch; ++ch ) + { + s[0] = x[1] = *ch; + if ( *ch == '?' ) + BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "." ); + else if ( *ch == '*' ) + BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), ".*" ); + else if ( *ch == '[' ) + BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\[" ); // no closing ] so it is literal + else if ( *ch == '\\' ) + BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), "\\" ); // actually an input error as "\" is not a valid GLOB + else + { + s[0] = x[1] = *ch; + BOOST_CHECK_EQUAL( str::rxEscapeGlob( s ), x ); + } + } + std::string a( str::rxEscapeStr( RXspecial ) ); // all rx/glob special chars are literally (\-escaped) + BOOST_CHECK_EQUAL( str::rxEscapeGlob( a ), a ); // nothing more to escape. + + // character class: contains "][" + BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[][]" ), "[][]" ); + BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^][]" ), "[^][]" ); + BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!][]" ), "[^][]" ); // glob allows ! and ^ to negate a cclass + + // no character class: no closing ']' so take it literally (the ] would be member of the cclass, not the closing ]) + BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[]" ), "\\[]" ); + BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[!]" ), "\\[!]" ); + BOOST_CHECK_EQUAL( str::rxEscapeGlob( "[^]" ), "\\[\\^]" ); + } +} + +BOOST_AUTO_TEST_CASE(gsubTest) +{ + std::string olds = "olds"; + std::string news = "new string"; + + BOOST_CHECK_EQUAL(gsub("test olds string",olds,news), "test new string string"); + BOOST_CHECK_EQUAL(gsub("no string",olds,news),"no string"); + BOOST_CHECK_EQUAL(gsub("oldsolds",olds,news),"new stringnew string"); +} + +BOOST_AUTO_TEST_CASE(replaceAllTest) +{ + std::string olds = "olds"; + std::string news = "new string"; + std::string tests; + + tests = "test olds string"; + replaceAll(tests,olds,news); + BOOST_CHECK_EQUAL(tests, "test new string string"); + + tests = "no string"; + replaceAll(tests,olds,news); + BOOST_CHECK_EQUAL(tests, "no string"); + + tests = "oldsolds"; + replaceAll(tests,olds,news); + BOOST_CHECK_EQUAL(tests, "new stringnew string"); +} + +BOOST_AUTO_TEST_CASE(testsplitEscaped) +{ + std::string s( "simple non-escaped string" ); + std::vector v; + + splitEscaped( s, std::back_inserter(v) ); + BOOST_CHECK_EQUAL( v.size(), 3 ); + BOOST_CHECK_EQUAL( v[0], "simple" ); + BOOST_CHECK_EQUAL( v[1], "non-escaped" ); + BOOST_CHECK_EQUAL( v[2], "string" ); + + v.clear(); + s = std::string( "\"escaped sentence \"" ); + splitEscaped( s, std::back_inserter(v) ); + BOOST_CHECK_EQUAL( v.size(), 1 ); + BOOST_CHECK_EQUAL( v[0], "escaped sentence " ); + + v.clear(); + s = std::string( "\"escaped \\\\sent\\\"ence \\\\\"" ); + splitEscaped( s, std::back_inserter(v) ); + BOOST_CHECK_EQUAL( v.size(), 1 ); + BOOST_CHECK_EQUAL( v[0], "escaped \\sent\"ence \\" ); + + v.clear(); + s = std::string( "escaped sentence\\ with\\ space" ); + splitEscaped( s, std::back_inserter(v) ); + BOOST_CHECK_EQUAL( v.size(), 2 ); + BOOST_CHECK_EQUAL( v[0], "escaped" ); + BOOST_CHECK_EQUAL( v[1], "sentence with space" ); + + // split - join + v.clear(); + s = "some line \"\" foo\\ a foo\\\\ b"; + str::splitEscaped( s, std::back_inserter(v) ); + BOOST_CHECK_EQUAL( v.size(), 6 ); + BOOST_CHECK_EQUAL( v[0], "some" ); + BOOST_CHECK_EQUAL( v[1], "line" ); + BOOST_CHECK_EQUAL( v[2], "" ); + BOOST_CHECK_EQUAL( v[3], "foo a" ); + BOOST_CHECK_EQUAL( v[4], "foo\\" ); + BOOST_CHECK_EQUAL( v[5], "b" ); + BOOST_CHECK_EQUAL( s, str::joinEscaped( v.begin(), v.end() ) ); + + // split - join using alternate sepchar + s = str::joinEscaped( v.begin(), v.end(), 'o' ); + v.clear(); + str::splitEscaped( s, std::back_inserter(v), "o" ); + BOOST_CHECK_EQUAL( v.size(), 6 ); + BOOST_CHECK_EQUAL( v[0], "some" ); + BOOST_CHECK_EQUAL( v[1], "line" ); + BOOST_CHECK_EQUAL( v[2], "" ); + BOOST_CHECK_EQUAL( v[3], "foo a" ); + BOOST_CHECK_EQUAL( v[4], "foo\\" ); + BOOST_CHECK_EQUAL( v[5], "b" ); + BOOST_CHECK_EQUAL( s, str::joinEscaped( v.begin(), v.end(), 'o' ) ); +} + +BOOST_AUTO_TEST_CASE(bnc_909772) +{ + // While \-escaping processes single-quote, double-quote, backslash and sepchar[ ] + // deescaping failed to process the quotes correctly. + std::string s; + std::vector v; + + v.clear(); + v.push_back(""); + v.push_back("'\" \\"); + v.push_back("\\'\\\"\\ \\\\"); + s = str::joinEscaped( v.begin(), v.end() ); + BOOST_CHECK_EQUAL( s, "\"\"" " " "\\'\\\"\\ \\\\" " " "\\\\\\'\\\\\\\"\\\\\\ \\\\\\\\" ); + + s += " "; + s += "'" "\\\\\" \\ \\\\" "'\\ single"; // single quote: all literal, no ' inside + + s += " "; + s += "\"" "\\'\\\" \\ \\\\" "\"\\ double";// double quote: all literal except \\ \" + + v.clear(); + splitEscaped( s, std::back_inserter(v) ); + BOOST_CHECK_EQUAL( v.size(), 5 ); + BOOST_CHECK_EQUAL( v[0], "" ); + BOOST_CHECK_EQUAL( v[1], "'\" \\" ); + BOOST_CHECK_EQUAL( v[2], "\\'\\\"\\ \\\\" ); + BOOST_CHECK_EQUAL( v[3], "\\\\\" \\ \\\\ single" ); + BOOST_CHECK_EQUAL( v[4], "\\'\" \\ \\ double" ); +} + +BOOST_AUTO_TEST_CASE(testsplitEscapedWithEmpty) +{ + std::string s( "simple:non-escaped:string" ); + std::vector v; + + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3); + BOOST_CHECK_EQUAL(v.size(), 3); + + v.clear(); + s = "non-escaped:with::spaces:"; + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 5); + BOOST_CHECK_EQUAL(v.size(), 5); + + v.clear(); + s = "::"; + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 3); + BOOST_CHECK_EQUAL(v.size(), 3); + + v.clear(); + s = ":escaped::with\\:spaces"; + BOOST_CHECK_EQUAL(splitFieldsEscaped(s, std::back_inserter(v)), 4); + BOOST_CHECK_EQUAL(v.size(), 4); +} + +BOOST_AUTO_TEST_CASE(test_escape) +{ + std::string badass = "bad|ass\\|worse"; + std::string escaped = str::escape(badass, '|'); + + BOOST_CHECK_EQUAL( escaped, "bad\\|ass\\\\\\|worse" ); +} + +BOOST_AUTO_TEST_CASE(conversions) +{ + BOOST_CHECK_EQUAL(str::numstring(42), "42"); + BOOST_CHECK_EQUAL(str::numstring(42, 6), " 42"); + BOOST_CHECK_EQUAL(str::numstring(42, -6), "42 "); + + BOOST_CHECK_EQUAL(str::hexstring(42), "0x0000002a"); + BOOST_CHECK_EQUAL(str::hexstring(42, 6), "0x002a"); + BOOST_CHECK_EQUAL(str::hexstring(42, -6), "0x2a "); + + BOOST_CHECK_EQUAL(str::octstring(42), "00052"); + BOOST_CHECK_EQUAL(str::octstring(42, 6), "000052"); + BOOST_CHECK_EQUAL(str::octstring(42, -6), "052 "); + + BOOST_CHECK_EQUAL(str::strtonum("42"), 42); + + BOOST_CHECK_EQUAL(str::toLower("This IS A TeST"), "this is a test"); + BOOST_CHECK_EQUAL(str::toUpper("This IS A TeST"), "THIS IS A TEST"); + BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0); + + BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0); + BOOST_CHECK_EQUAL(str::compareCI("TeST", "test"), 0); +} + +BOOST_AUTO_TEST_CASE(conversions_to_bool) +{ + // true iff true-string {1,on,yes,true} + BOOST_CHECK_EQUAL( str::strToTrue("1"), true ); + BOOST_CHECK_EQUAL( str::strToTrue("42"), true ); + BOOST_CHECK_EQUAL( str::strToTrue("ON"), true ); + BOOST_CHECK_EQUAL( str::strToTrue("YES"), true ); + BOOST_CHECK_EQUAL( str::strToTrue("TRUE"), true ); + BOOST_CHECK_EQUAL( str::strToTrue("0"), false ); + BOOST_CHECK_EQUAL( str::strToTrue("OFF"), false ); + BOOST_CHECK_EQUAL( str::strToTrue("NO"), false ); + BOOST_CHECK_EQUAL( str::strToTrue("FALSE"), false ); + BOOST_CHECK_EQUAL( str::strToTrue(""), false ); + BOOST_CHECK_EQUAL( str::strToTrue("foo"), false ); + + // false iff false-string {0,off,no,false} + BOOST_CHECK_EQUAL( str::strToFalse("1"), true ); + BOOST_CHECK_EQUAL( str::strToFalse("42"), true ); + BOOST_CHECK_EQUAL( str::strToFalse("ON"), true ); + BOOST_CHECK_EQUAL( str::strToFalse("YES"), true ); + BOOST_CHECK_EQUAL( str::strToFalse("TRUE"), true ); + BOOST_CHECK_EQUAL( str::strToFalse("0"), false ); + BOOST_CHECK_EQUAL( str::strToFalse("OFF"), false ); + BOOST_CHECK_EQUAL( str::strToFalse("NO"), false ); + BOOST_CHECK_EQUAL( str::strToFalse("FALSE"), false ); + BOOST_CHECK_EQUAL( str::strToFalse(""), true ); + BOOST_CHECK_EQUAL( str::strToFalse("foo"), true ); + + // true iff true-string + BOOST_CHECK_EQUAL( str::strToBool("TRUE", false), true ); + BOOST_CHECK_EQUAL( str::strToBool("FALSE", false), false ); + BOOST_CHECK_EQUAL( str::strToBool("", false), false ); + BOOST_CHECK_EQUAL( str::strToBool("foo", false), false ); + + // false iff false-string + BOOST_CHECK_EQUAL( str::strToBool("TRUE", true), true ); + BOOST_CHECK_EQUAL( str::strToBool("FALSE", true), false ); + BOOST_CHECK_EQUAL( str::strToBool("", true), true ); + BOOST_CHECK_EQUAL( str::strToBool("foo", true), true ); + + // true/false iff true/false-string, else unchanged + bool ret; + ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("TRUE", ret), true ); + ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("FALSE", ret), false ); + ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("", ret), true ); + ret = true; BOOST_CHECK_EQUAL( str::strToBoolNodefault("foo", ret), true ); + + ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("TRUE", ret), true ); + ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("FALSE", ret), false ); + ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("", ret), false ); + ret = false; BOOST_CHECK_EQUAL( str::strToBoolNodefault("foo", ret), false ); +} + +BOOST_AUTO_TEST_CASE(operations) +{ + BOOST_CHECK_EQUAL(str::ltrim(" \t f \t ffo \t "), "f \t ffo \t "); + BOOST_CHECK_EQUAL(str::rtrim(" \t f \t ffo \t "), " \t f \t ffo"); + BOOST_CHECK_EQUAL(str::trim(" \t f \t ffo \t "), "f \t ffo"); + + // strip first + { + std::string tostrip(" Oh! la la "); + std::string word( str::stripFirstWord(tostrip, true) ); // ltrim first + BOOST_CHECK_EQUAL(word, "Oh!"); + BOOST_CHECK_EQUAL(tostrip, "la la "); + } + { + std::string tostrip(" Oh! la la "); + std::string word( str::stripFirstWord(tostrip, false) ); // no ltrim first + BOOST_CHECK_EQUAL(word, ""); + BOOST_CHECK_EQUAL(tostrip, "Oh! la la "); + } + + // strip last + { + std::string tostrip(" Oh! la la "); + std::string word( str::stripLastWord(tostrip, true) ); // rtrim first + BOOST_CHECK_EQUAL(word, "la"); + BOOST_CHECK_EQUAL(tostrip, " Oh! la"); + } + { + std::string tostrip(" Oh! la la "); + std::string word( str::stripLastWord(tostrip, false) ); // no rtrim first + BOOST_CHECK_EQUAL(word, ""); + BOOST_CHECK_EQUAL(tostrip, " Oh! la la"); + } +} + +BOOST_AUTO_TEST_CASE(prefix_suffix) +{ + BOOST_CHECK( str::hasPrefix("abcXabcYabc", "abcX") ); + BOOST_CHECK( str::hasSuffix("abcXabcYabc", "Yabc") ); + + BOOST_CHECK_EQUAL( str::stripPrefix("abcXabcYabc", "abcX"), "abcYabc" ); + BOOST_CHECK_EQUAL( str::stripSuffix("abcXabcYabc", "Yabc"), "abcXabc" ); + + BOOST_CHECK( ! str::hasPrefix("abcXabcYabc", "ac") ); + BOOST_CHECK( ! str::hasSuffix("abcXabcYabc", "ac") ); + + BOOST_CHECK_EQUAL( str::stripPrefix("abcXabcYabc", "ac"), "abcXabcYabc" ); + BOOST_CHECK_EQUAL( str::stripSuffix("abcXabcYabc", "ac"), "abcXabcYabc" ); + + BOOST_CHECK( str::startsWith("abcXabcYabc", "abc") ); + BOOST_CHECK( str::endsWith("abcXabcYabc", "abc") ); + + BOOST_CHECK( str::contains("abcXabcYabc", "XabcY") ); + BOOST_CHECK( ! str::contains("abcXabcYabc", "xabcy") ); + BOOST_CHECK( str::containsCI("abcXabcYabc", "xabcy") ); + + BOOST_CHECK_EQUAL( str::commonPrefix("", ""), 0 ); + BOOST_CHECK_EQUAL( str::commonPrefix("a", ""), 0 ); + BOOST_CHECK_EQUAL( str::commonPrefix("", "b"), 0 ); + BOOST_CHECK_EQUAL( str::commonPrefix("a", "b"), 0 ); + BOOST_CHECK_EQUAL( str::commonPrefix("c", "c"), 1 ); + BOOST_CHECK_EQUAL( str::commonPrefix("ca", "cb"), 1 ); +} + +BOOST_AUTO_TEST_CASE(hexencode_hexdecode) +{ + std::string o; + o.reserve( 256 ); + for ( unsigned i = 1; i < 256; ++i ) + o += i; + + std::string e( str::hexencode( o ) ); + // encoded contains nothing but [%a-zA-Z0-9] + for ( unsigned i = 0; i < 255; ++i ) + { + char ch = e[i]; + BOOST_CHECK( ch == '%' + || ( 'a' <= ch && ch <= 'z' ) + || ( 'A' <= ch && ch <= 'Z' ) + || ( '0' <= ch && ch <= '9' ) ); + } + + std::string d( str::hexdecode( e ) ); + // decoded equals original + BOOST_CHECK( o == d ); + + // Test %XX is decoded for hexdigits only + const char *const dig = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + for ( const char * d1 = dig; *d1; ++d1 ) + for ( const char * d2 = dig; *d2; ++d2 ) + { + std::string eu( "%" ); + eu += *d1; eu += *d2; + std::string el( str::toLower(eu) ); + + std::string u( str::hexdecode( eu ) ); + std::string l( str::hexdecode( el ) ); + + if ( *d1 <= 'F' && *d2 <= 'F' ) + { + BOOST_CHECK_EQUAL( u, l ); // no matter if upper or lower case hexdigit + BOOST_CHECK_EQUAL( u.size(), 1 ); // size 1 == decoded + } + else + { + BOOST_CHECK_EQUAL( u, eu ); // no hexdigits remain unchanged + BOOST_CHECK_EQUAL( l, el ); + } + } +} + +BOOST_AUTO_TEST_CASE(regex_subst) +{ + const std::string input = "StRi_g: Hello this is a StRiNg with multiple Stri_g mentions to replace StRi_g"; + str::regex rxexpr( "(St[rR]i[nN_]g)" ); + BOOST_REQUIRE_EQUAL( rxexpr.get()->re_nsub, 1 ); + + { + const std::string result = str::regex_substitute( input, rxexpr, "FooBar", true ); + BOOST_REQUIRE_EQUAL( result, "FooBar: Hello this is a FooBar with multiple FooBar mentions to replace FooBar" ); + } + + { + const std::string result = str::regex_substitute( input, rxexpr, "FooBar", false ); + BOOST_REQUIRE_EQUAL( result, "FooBar: Hello this is a StRiNg with multiple Stri_g mentions to replace StRi_g" ); + } + + { + const std::string nomatch = "Text with no match"; + const std::string result = str::regex_substitute( nomatch , rxexpr, "FooBar", false ); + BOOST_REQUIRE_EQUAL( result, nomatch ); + } + + { + const std::string input = "StRi_gString: Hello this is a StRiNg with multiple Stri_g mentions to replace StRi_g"; + str::regex rxexpr( "(^St[rR]i[nN_]g)" ); + const std::string result = str::regex_substitute( input, rxexpr, "FooBar", true ); + BOOST_REQUIRE_EQUAL( result, "FooBarString: Hello this is a StRiNg with multiple Stri_g mentions to replace StRi_g" ); + } + + { + const std::string input = "StRi_gString\n: Hello this is a StRiNg with multiple Stri_g mentions to replace StRi_g"; + str::regex rxexpr( "(String$)", str::regex::match_extended | str::regex::newline ); + const std::string result = str::regex_substitute( input, rxexpr, "FooBar", true ); + BOOST_REQUIRE_EQUAL( result, "StRi_gFooBar\n: Hello this is a StRiNg with multiple Stri_g mentions to replace StRi_g" ); + } + + { + const std::string input = "Hello StRi_gString\n: Hello."; + str::regex rxexpr( "((^: Hello)|(String\n))", str::regex::match_extended); + const std::string result = str::regex_substitute( input, rxexpr, " FooBar", true ); + BOOST_REQUIRE_EQUAL( result, "Hello StRi_g FooBar FooBar." ); + } + + { + const std::string input = "4.12.14-lp151.28.48-default"; + const std::string flavour = str::regex_substitute( input, str::regex( ".*-", str::regex::match_extended ), "", true ); + BOOST_REQUIRE_EQUAL( flavour, "default" ); + std::string version = str::regex_substitute( input, str::regex( "-[^-]*$", str::regex::match_extended ), "", true ); + BOOST_REQUIRE_EQUAL( version, "4.12.14-lp151.28.48" ); + const std::string release = str::regex_substitute( version, str::regex( ".*-", str::regex::match_extended ), "", true ); + BOOST_REQUIRE_EQUAL( release, "lp151.28.48" ); + } + +} + +BOOST_AUTO_TEST_CASE(regex_subst2) +{ + auto gsub = [&]( const std::string & l, const std::string & rx, const std::string & res, bool global = true ) { + BOOST_CHECK_EQUAL( str::regex_substitute( l, rx, "@", global ), res ); + }; + auto fsub = [&]( const std::string & l, const std::string & rx, const std::string & res ) { + gsub( l, rx, res, false ); + }; + + gsub( "123", "a*", "@1@2@3@" ); + fsub( "123", "a*", "@123" ); + + gsub( "123", ".", "@@@" ); + fsub( "123", ".", "@23" ); + + gsub( "123", "1", "@23" ); + gsub( "123", "2", "1@3" ); + gsub( "123", "3", "12@" ); + gsub( "123", "4", "123" ); + + gsub( "123", "^", "@123" ); + gsub( "123\n", "^", "@123\n" ); + gsub( "123\n123", "^", "@123\n@123" ); + + gsub( "123", "$", "123@" ); + gsub( "123\n", "$", "123@\n" ); + gsub( "123\n123", "$", "123@\n123@" ); +} diff --git a/tests/zypp/base/Sysconfig_test.cc b/tests/zypp/base/Sysconfig_test.cc new file mode 100644 index 0000000..f934555 --- /dev/null +++ b/tests/zypp/base/Sysconfig_test.cc @@ -0,0 +1,75 @@ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include + +using boost::unit_test::test_suite; +using boost::unit_test::test_case; +using namespace boost::unit_test; + +using namespace zypp; + +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zypp/base/data/Sysconfig") + +BOOST_AUTO_TEST_CASE(Sysconfig) +{ + Pathname file = DATADIR / "proxy"; + std::map values = zypp::base::sysconfig::read(file); + BOOST_CHECK_EQUAL( values.size(), 6 ); + BOOST_CHECK_EQUAL( values["PROXY_ENABLED"], "no"); + BOOST_CHECK_EQUAL( values["GOPHER_PROXY"], ""); + BOOST_CHECK_EQUAL( values["NO_PROXY"], "localhost, 127.0.0.1"); +} + +BOOST_AUTO_TEST_CASE(SysconfigWrite) +{ + Pathname file = DATADIR / "proxy"; + filesystem::TmpFile tmpf( filesystem::TmpFile::makeSibling( file ) ); + filesystem::copy( file, tmpf.path() ); + + BOOST_REQUIRE_THROW( zypp::base::sysconfig::writeStringVal( "/tmp/wrzlprmpf", "PROXY_ENABLED", "yes", "# fifi\n fofo\n" ), + zypp::Exception ); + BOOST_CHECK( zypp::base::sysconfig::writeStringVal( tmpf.path(), "PROXY_ENABLED", "yes", "# fifi\n fofo\n" ) ); + BOOST_CHECK( !zypp::base::sysconfig::writeStringVal( tmpf.path(), "NEW1","12" ) ); + BOOST_CHECK( zypp::base::sysconfig::writeStringVal( tmpf.path(), "NEW2","13", "# fifi\n# fofo" ) ); + BOOST_CHECK( zypp::base::sysconfig::writeStringVal( tmpf.path(), "NEW3","13\"str\"", "fifi\nffofo" ) ); + + std::ostringstream s; + ExternalProgram( "diff -u " + file.asString() + " " + tmpf.path().asString() + " | tail -n +3" ) >> s; + BOOST_CHECK_EQUAL( s.str(), + "@@ -8,7 +8,7 @@\n" + " # This setting allows to turn the proxy on and off while\n" + " # preserving the particular proxy setup.\n" + " #\n" + "-PROXY_ENABLED=\"no\"\n" + "+PROXY_ENABLED=\"yes\"\n" + " \n" + " ## Type:\tstring\n" + " ## Default:\t\"\"\n" + "@@ -49,3 +49,11 @@\n" + " # Example: NO_PROXY=\"www.me.de, do.main, localhost\"\n" + " #\n" + " NO_PROXY=\"localhost, 127.0.0.1\"\n" + "+\n" + "+# fifi\n" + "+# fofo\n" + "+NEW2=\"13\"\n" + "+\n" + "+# fifi\n" + "+# ffofo\n" + "+NEW3=\"13\\\"str\\\"\"\n" + ); +} + diff --git a/tests/zypp/base/data/ExternalProgram/echo.sh b/tests/zypp/base/data/ExternalProgram/echo.sh new file mode 100755 index 0000000..a4e207b --- /dev/null +++ b/tests/zypp/base/data/ExternalProgram/echo.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +#just read from stdin and write to stdout until we get a single q + +while read -r line +do + if [ "$line" == "q" ] + then + exit 0 + fi + + echo "$line" +done diff --git a/tests/zypp/base/data/Sysconfig/proxy b/tests/zypp/base/data/Sysconfig/proxy new file mode 100644 index 0000000..f3a6b9c --- /dev/null +++ b/tests/zypp/base/data/Sysconfig/proxy @@ -0,0 +1,51 @@ +## Path: Network/Proxy +## Description: +## Type: yesno +## Default: no +## Config: kde,profiles +# +# Enable a generation of the proxy settings to the profile. +# This setting allows to turn the proxy on and off while +# preserving the particular proxy setup. +# +PROXY_ENABLED="no" + +## Type: string +## Default: "" +# +# Some programs (e.g. lynx, arena and wget) support proxies, if set in +# the environment. SuSEconfig can add these environment variables to +# /etc/SuSEconfig/* (sourced by /etc/profile etc.) - +# See http://portal.suse.com/sdb/en/1998/01/lynx_proxy.html for more details. +# Example: HTTP_PROXY="http://proxy.provider.de:3128/" +HTTP_PROXY="" + +## Type: string +## Default: "" +# +# Some programs (e.g. lynx, arena and wget) support proxies, if set in +# the environment. SuSEconfig can add these environment variables to +# /etc/SuSEconfig/* (sourced by /etc/profile etc.) - +# this setting is for https connections +HTTPS_PROXY="" + +## Type: string +## Default: "" +# +# Example: FTP_PROXY="http://proxy.provider.de:3128/" +# +FTP_PROXY="" + +## Type: string +## Default: "" +# +# Example: GOPHER_PROXY="http://proxy.provider.de:3128/" +# +GOPHER_PROXY="" + +## Type: string(localhost) +## Default: localhost +# +# Example: NO_PROXY="www.me.de, do.main, localhost" +# +NO_PROXY="localhost, 127.0.0.1" diff --git a/tests/zypp/data/Delta/repodata/deltainfo.xml b/tests/zypp/data/Delta/repodata/deltainfo.xml new file mode 100644 index 0000000..2909d1b --- /dev/null +++ b/tests/zypp/data/Delta/repodata/deltainfo.xml @@ -0,0 +1,17 @@ + + + + DRPMS/libzypp-4.21.3-1_4.21.3-2.i386.drpm + libzypp-4.21.3-1-d3571f98b048b1a870e40241bb46c67ab4 + 22452 + 8f05394695dee9399c204614e21e5f6848990ab7 + + + DRPMS/libzypp-4.21.2-3_4.21.3-2.i386.drpm + libzypp-4.21.2-3-e82691677eee1e83b4812572c5c9ce8eb + 110362 + 326658fee45c0baec1e70231046dbaf560f941ce + + + + diff --git a/tests/zypp/data/Delta/repodata/primary.xml.gz b/tests/zypp/data/Delta/repodata/primary.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..b41606abd00d5334185957455c5aec6df77752ac GIT binary patch literal 86272 zcmV)BK*PTuiwFRvo-RlL1MFQ}bK5o+e)q4y_@UFzR1yjBnmFD~b7`~dq~6%ccAq>T z07|SWlI6vY^V{}q|JWXoluXGo3Cc=rC(LwQ8~P6JIOpJe5ODCfPxBC6h%^i0=-IwL z*7lKzSj>ZH`fUHh>FbfR|F^@vgSp5lr#VFckFsa`vpi3pOeSFv6`#huI2U8Vi^&2t zVexz(NBeuI{8!36Nt1b}9AH+3vLX{psVKe>VK|1&CkbWebSkbTC2+0S8UwY}ExdnN zrXJLZ{n~-@s|2bcYj;>@eh|^QIHZ)Gc{CFTlk(5SXEbHA!z^V7lk&Gka^1~HBr%&k z+lQ`(6sTR<>!}Ez?VI}kWC>?8!OpW{UYDND=srr$rvZPq|DRVU`-d14-=>;R4cB7W zA+Ba&8w-tN*QdfZ1#yWGwsA07gh^7M3FpD8$ls5_*@4>(4MLvtu?8)A!{#RD?-y)4f zie3lNIr<^YpI(-K|6R_KF&95f^QR^3{r~>UgDC)i7iliS5}L+0V80YFj5OuwBo{&C z1tBk!Ux#rT&=&@xl)-6a6>j~%;(`+0kA}WiH z)9Jxv30cS#X?S=rkv|tHc`z4cC&DDcnuARnCcr-O3aH^C$#PB7m{eKtSuFYwAdc=3 zdw(%v0;C8AId>n)nHyXPnShC-HL?g}Rt?`Q6@IxYCNS40i?uM4^Lb?IV@Mp!C37w5 z$LXBri$5U&K7JAg44N$te?2}z7Z}AUOsia^2b1Q9t0EU7;&EEf**EV#{DF?sm=_G@ z&aZRtx1Z6w0>;}D>GWsxtAH}2t17!%a5cAS8W+jo$yJt%`Q-I1tDsftDzfa@S)ApE zkarM|>v>WMTz|MKl*KT6gzTlY4`zaLk&aSWL;^wor}?ve!*HYmmZN9sc0(J~GO75h z2vU(9Y#X+25N1+~ z8`$S$P_u)Yy-m%+vUb+gtnNsOhMFZtr<#?M{idFkse__zDB8o@Oi?9&jq9V2O&DY6 zhCWWx_#)sP`q&Girr;(-9Op$IW*sn*vkpXdEEApF`eB7qZCG672^OSH*s! z>9lL0=dk?}d48o*(=eWP&M%e(aR;Q};-UkRWb+{Fnt{u9g5R;pooEx8rXo?5DF^AI z4;s{IA2_VW9%yi6MBnDJd9T*OoDU0SiA;)s!O29b+DnnhM|m9gYj`$$KjuBNJW$Z{qoBJEQ1&@ML4;<2TQ z`|;PKH^00%!(;8I-XeN`5weBI*yu0RDY81t-egCg=XB%bGRC<7zN;=U_Odt>d54wU zWWlR!H^|qbE|L*=d)1z1JLzQ3y?&DA&JW~s@TaeOih@fL zjq-WYQw)+ua*GhQ$w4==u3iL8=|Z$%W<@qDF
Jh=P2~C+}Z9fBE)RH%_{|YN&D9 zMMYZ&t)gRgu80ki&Uw;=pF<}oLPOpwXQ?XYu(JY_q$~kr@ApE3eOH8oYu+|zn$Q$} z_?dE#XRuVbD)y2p4El_Q3e8I5OOg7pgu0=y0p#&q0jJPKsZg8e894l*P{7IkT^_eB z)-|N0OA^{ug`Bo&ydX-7ytTQ1(hJ(X^ykq3taVK1!CZ`GAg*max8N4r#uqagD?Pb_ z4Nr7_+t^;m$iTS?KHpaM0yaMnB0uIq+JTG1+uVo+LTF zME(!32`wnt9)e>afmaba{ z!=`CsPdFAIIL7aWW3*gXTjv;U+?-VF9HXf@)*8p?I-0)1F`5`RNUTj9V>R7xvW!*w zx6Ct!LHzlFFpc&~lyzVl2c~gg8V9CvU>Y9|dSDvAJk$8&Pd{3Q7v%j(Iy^SFmL=Ou zj*YElRV5!dySM?CCoCTr$bQlT1G$D77|4Nv92m$OxPgIOA_fL>U?78mf$YW(3}icM zU?6Xx1_p8yZeSp91q}>jUj~webWShs%0Fsjm(;s{-0v%no~s$eGzm7T&jhv%qM14~ zZH|3QcNrBf{9lQFd>-WiScxJ-r*Ryf2e~To_yW2BN$HQJbdVt$!GDX~@+vn3V}d@s zd-KN_oz4UThb}@%ktT5_Q0(uOq+%BP`K6>9;rDzdS_EVMnVvH9A0;0$d#izgv1=NfqfQMB6F^BmE8K;ui;d`7480?<` zEr(qKVOj`OW-ij7OHo=jsB8@_@))LBz)+FEWP#$*ML_pt&EG)HLG|Zj^d?6jjy!>2 z|IHlqLS|a0e57|PUI+jgr zcZE82FmXt8L99`y*f2Cnzcsj1Y-7zOP4X1mhNe4e>}gfikz9@={P?KTItN&I`PJk^ zup$leD-{+s4I*~lmqT6ctQ`=j*w!3lI|5Y(W~*tI#bcvS0Jf%U3OZx>7}fL)Tjn)K=P4PKwdX^IqhkI$JH_pxhMU{U})VYWRKFU>2vM$OC0& zw+9i=1K;nH_5IVpU$O?@3dO8W9m{prsbIa&SSnAwKX*Kk&EKRq^ng5>2jG89=ZVaK z^e8{6wzX1B+g5C=rLr*xGREpTfZB?~ath%dHE&97Rq@M|CVji>b1$v+fKGwbyEpD# z7k|3+KpkgHZkD&{=*M+*U1rG3(-SQrcps`elgKV$%|+I=oR`54HMjytysSk>K(;Qu zHP+w6wzR1U<1(P6fKz~}wj>LtGHlfqR#oZl6>wW5y$=8O%CmwiY?Gdh^#!5rVSImWJW zgS2(c7Sa}*x?!)8wqSd0vO?P0j-hpswy;vyY%!#K54O0NhQUK%Yw?y}cU_GV-YG13 zmw4ozXxYBO$lU}lcfh}H7rER`ymQAy>%g!M4C}zK4h-wSu=ZeBRawX0?Bv(EFIXSr zZG^VCW_XKo9?WINkIKWkMc%X|1x_F?A2fDaVd|LhGv~2^_3=_j~ZO7L<-O&w0vvgbY43F8quRGXe zj$>+uIRvPO0QF-CP!rqk#TUcuH|0BV%>cEfJ1#bx0cwjlx~1~&+iKwTkv;nMwdvw7 z5~j9R{IMZS{h)SWLzsF9Qx9S4Axu4lsfRH25T+i&)T-biOx;In2vZMX>LE-$gsF!x z^$@1seVBSAZ#}+;NVP9)kJ*g7%ptnxP$9qP;c0|e4yMFpOyjQS6JIG(UB#JSLaXIl z6=eui#-N{n-0A@y7?zyEh7M7bMKsA~agJiYj6YWa>}DRkQRrS(Xc^*#{34Kxgy1sB z>!Yif5oS4#Z*ogBu`PUym_#=Wi~F8sdl<}yZi11p)ClUq>_0%Wk6p9ZcZ#Ih*RZ}D zv)}ky(Y4j@`OTv5+2}urZzs7#HwS}182rKDe+7g86|TB=OkLQHXH%0|IyNoN44pZG zVa+pagBXsXbKx28VDlfV%_ol5>+2MTm}}yF`v&S7)C;$oEPRSVDP}J1b8>gZ1)jqDRd? zSm`np$hW)XfpY00BvoPcLF;@*b9o#)7gA$OJz18x2WmE#r_nvAa4-+bQ{b1gfXz_- z4o@cS2h{5_PR~Ik6^JrO&C0{*P#5q%_GESvb`j9h8>un{2Vu2(@^E)`Furc{WZB-; z+CnAvg2+#4mZxAJ3Mdqu4wee&$L3l1w16L(s1D~-si3QVUKH8lq8t_cGMIwVf+ZQE zAHw`;Sf-4lGUe~JZTVrEKP~ZZVa}o71f=fPgK2eET*qT-8@iEAlnWvrCMl{mEjvTRutIJ3i4P_n7^wgG)%N!e#f6QqD=JmJlgtk2Y!g| zTH2Nuq$IHRC{CaBj~d#ku&D_o=qjT7B`^ zRhA1?$8KRXlt;21r|`~r{q|Sq4SmDm-R=hO?4kHC>+YgHXTWx)JXMZ|)km*Zl^`owDg*9P>pRuUNxv#5-w>@G!pZ5Yx5r1%Pum{uyw0U|9VdZ5Dw6fu^va=fy0R^D z*eEIALT7Cci+0JgBFkGJVeZNx4!M`YBxc~}-X$CGGVdV%7Z0+w$4tBA(}ct*GJo0pbu&@t9%>x-FC7}BLeFNw@k-y99w||}?XY;zgh`%cz0+|{eJVWN`eH=`ZRB3Ao8R$ij5u=yHxusgk6+qCh`FG4Hr z*>>xT-hV{1Iz2rCr!F7mX>dWqyM{HF-u>9^VFXMen8|IOYo2CNtb2sJx^23QGTY}i z#lFs{A=F-GIIg=$sw&wssc5AxtQsq)13O2&kh)LmX*p$4dGmLil<&f;T7S=TJCOpY`UD@C)o2)Vo&L(nV;ugW?K z-lD00qbUW6xBvSuD719+PF$7hdNwZvBs3NE*VN1|F-?6{GrNRnx1W6`w!0c)B&NN> zgKBEg#hZ&`q>W%+Kfci7Ng2nO{D+>Ls_0-Zq_E7=zEQ+m`)dawL_)}x58~de)do&; zlhWEnjPDzWj(j`xU2`U6OPAz6%$;DaZn(Cm>AFLiZdp2UiSH0gbHMhQhOj(aUM)44 zyYJH6VW*e5GsxN_0@!MpJIlqrt=(dE4EFBc?47P}c~{e>aU3k(VDVDn#c@8W&Q;!z z*>h|M8?c?zG)=fJvpwIpUEz5ab%aT5gWC)?eU94E)xqq2Yi3W=`k6i3S~Yt{^AS56 zcf6Ui!R)Opk-_%epY0>$?zV4bFb4xT7{ItxWA_!|6qtjF^K@cx&*O%#dA5cfYC4)} zQenED?P}b!2HW>t+CIZJdT#mLwL_Ff)Anr<;9RVZ!R$TmE#G1s2a7jYyxSQ)^_SMS zqw_SESbaJU4a1d|&NHZ?nYMvFOVfRu3$^Qr24nXP89P@ahH3SRZ<^RNSB#zI zS}Qv}Vs&iwHEGbgr*OHw?QAPY(C7j`(?1vJoRRGy#=yi^Kr{!8TKOgw->Ru zyd_RySck32_qjDWmrpi@BQ8L3-R+iCJhsNzT(-B@m1#n_IuV2lDi|fyFg)L7x~91T z_AJ;oJ)im9)57X*qlm6XU(#BQQepqLjRm;pI$3psO#W{hU^BXu*1dZ06N7Rwt!; zK&N07Kncu~CkShrGt$hFW+UBsLdX;C|Lk2!b7MJj{wp0m^@O9lu`fP4eD%p=Um1za zghUs&ASsntHatco!zd)XRA*_>3mFj}(yPR6?H8mrf8{L2?j{QJAm>a&sh zqN}&f)FbSl`O~PCx+bm7_OD>3T#VkPIYV{vV4LmcVR!3z-1%R8Z@sRg(L2NZe46-Q zNDQ}t$6|e?g^<^F3gl1U&yYYTiV(z}f~(%o%&_6(LiAmJbSB`4y09WNF-3=QWP-Md z7Og$d`L7GyJ+-eYrlvDfO{~~su(4Q9aO+lu?yKx@xp>?jcdMs|&J4;RJC!xntRk7A zclk2I@<5x#(ycnf8%;iCR9KTo_P4HGxjy`Z0P>-`8cLuo=S9$;_+qhM%cSlOQ&ItgA>R7Y)kl8Mz0Kyp2@`OT5~pg$^auB!cE{}k4xcu-IKFg7 zM~d32oK^9u#4seJ*Ke}i6ZAH+t|97zy0Rxz%BbqVi}5|xAq(Cy+e|Wc9Fj>J7GcwS z*dqF!QXy5?Yn;M@HPaFn4eqxKUYqpN6M9K0u#mn`T+Ip6%tYrYXnEMJ;8SOgSdC~V z=^_-;Du$_-S>vMh2k2>Kw52MaTC`1Ta!6OAP_!3%#FvZn0k5jquY=Z-yLD z9vm?Q>!Wf*Dt}USW==x&bWiG>$%*R7epSwnsnAK^ce|DNFRKrou_0k9KICfAM~p*w z`9(5^-Lf-sK%w#V|#1ni4*hp176g%Bm2j61*-`qo23G{JIu*Y}-XM?Szb0 zZG+W0jjQ<@@S2uGVi^<#CyVt?-wGLgzk~Y5!f;f?nnMU8bey6xukrWkP)@&erz(-O zHK<&{GH#d3>WPor?eVdvmZ)PLJog-NnW892# z=_*Q-GJu)Voa-?;>sTE8Djzo?LYZF{gj&t78Q*_G*YNpHv<;=Wac{vBiW?GDW;W zk&Ydb&g<>e8#-dhS^L}~$2m{YnI`NO(OqUd~2(_L^av=w5GCcu<=6~4VFt%+9;cMRIhRE4<);UhexHfI<cf@GMJ$lr;-5XTm@>*9-cSE^b#xDg(ohw$qpir$z) z2#kC=Q$to|Di-(HMO&485rX8!V#t3yp z6jl%0ZmP>W$hkoA#bO!@XkA3+7l&;yA@C+Ia`8;ke&+vzTmDFc?A!=qpZTF`HuI<8s$~1je`R8xet@!>1R!>2@8qf<79f^G`m+VF7fx!+c2S7IR@sRo~?miD9U))hQ= zjkZX}VJs{jVN3H41HzT3c21j2#ihVlc*<7a@N!TDBD@`wgAz@gaxZtV-);BZ2%IGf z8lp8-)NwAJB^#=%jiG|7U<`2ba|HO5V1Iciw#UNS{jXKYH1dlob1d>zist|jwRQb0 zOie~Se8oPJn{c}uqVYk8l)4oNB}X7vQj%pJ^XlJtX6qg-WQawJ3q@qKH+IU@w(+|m zp`5Kex`V1nm!VDDLPCFO--v4~6YSDe1&IxtLV{>xi1Q`B-P4>*jFB@ZgH*;!!oCWG z_SdHO9I0_eBP?AArW{P*{NvB|&y!j(l%+Pd$wEk%dP_SJ|5AXlPAE@)df6 zie9HyaFlb6N`PgqP@-#-Y(TK(6f>!ThamlHvQoZvdt&vY@j94R3Cd%260eF!`r%V93B`U!Kx=ihLxYQc$foSYzOo`> zFOFUiN^0i90H1@i-CED+Y=D5Jr0nJ@fWBm#mZn=5QELmtC?qIg=K}lB%l)yNEVJTy zwet+5MBZVHEq*P?#MRTGk6Pjz8SAP`q+N<*Vc8~g@f>@eb@o|_xeUH!fHAMDje2<6 z^z+Lxi!%X6Mn|gRSoRfRRk_=qt>2t&C0D!SWqL4}#L+baoD)-;oR|0164Zq?Hqj#Z^pOK#`A zEKFFruj|_jjfn449JEA0tztxniAC8jNzBE2bTP?eXYjF|5RerZ@`cW6q#k}j5Z5cR zVsS`e48OhzWPj`dZz{rA3;}^s+03Qem%__8%L1P{Mz=;%m~)7gV<{AIXqI!?emBcd z9mM3dO=9NkM1-+{(i0Z9tvhc@#>Sy7z56s_$kENf;asL3l;CYb0ivAMbyK!v-|pCx$0#y z&=_L{{ItqddpEUV0K3M=MJEod$>N$6qBNDmICMS0s>JGmDMky&sx%eJYQ>G$0=LEs z12VFtWL>C}3EfxmrfWr-$=iq?gnim725!Rsv}hBMmVMV-+f;Kz3&4dujMrnFNvIg; z;fVY@>H(u4q{nVh!DONLl;}MM0IEw4aMuo?K9P=<(9XAzGJ}H$p8c zP3_xL&HL)5XQE4XiZY~- z#~=p!${Dz*Ovb_}{K(^2GEfHPmloXa=cn1ULVzke7o(di9&Db`f%i-3K_z$&3AKqO zp=jhBp0y$&u}z2Wp*MWeN*+5{{*jS_pm5EN;hkwe8m;RgD!LgSL<~&z*)jK_=~c+qVTry{Xy~RPD;> z_TAJ&x6H|)C??AzmuUQ4fV6)kTy!Vd;;V|ptq^y@!Wvv`kB?m!rW7lNBU-D1O4?JoIW{&l-OwiZ&Y0oQ%A zeP|QyX{=Gzf1P_FG5s6wctgCw<<(wTcIKw`-{~Uz|998k@BfI4>RUp6wZ!B5JLd4| zP!FHC%$NE9{B^J1sxE`w4)*Kq{ukM_ty|RL`Cds{HLFTD@)-j-z`mN4Nl{1i;!VH{#c)+^Aw$- zPM4m4?!rdP{XdM@3!>UQuv{U+CR{`PKa_) z!9eTNp~VdXlL!iF<+K(uZM6Y^^ zg{RfA2i7fi5Zv#M*Fi_EV~Scap(zekjSd1=M2?}QS!1cjhr96l&jQZ>afA)Qo<5`W zsaJK`9v^@D&&^Vx5oPt{FY=k6{$1Yu)t}D0=5Rl(pS1iu*M~QAJ-wZ4eL2_RJlEeN zL`U!5K(tSQPGEnXCZpbEKY26Hn@9UY+l-z{#*a5YwRu|KEGt_a*1H>@x&4XHvbgtyKYte5 z_2M`I)Dp6eL8x#}{_dF5dD!>s$aB?M*Hc4;5&-WG$eqW&epZ{vws9RAYoo7s=f^Lf z`BpDNLghp5>lipODdzAzukmh5OrBzLEXAwXxM#<&;mhq?`vzv@hrA z$BZotAZKMmRNQWeoP7TN88FBNoT3;@iOGe#Qzw^$Uuj;_?#*TGR74lOxj!#+Ir#M> zW>tgiDiohGI8OQQEZb|{x!FSsb79#aWYJUd_3os@`o3!3}8nOv1q59^eR(WIgaX_Oz6FLJ${Ah-f8 zpKGjZm3)(UcUPNWf(neLDzDfFJ1DPy-K3?gO!BhllCEaf7TnkQ2t)BTDld?vMovpz z&ed;Ot1Yx6jE)M1JkT@i8!TPvO3tm#gjnKs6flI@^}W&-EqW@UQWkR~u%{-GqTh-R z*#TK?f>Nd6{l~DbE9R99y+)2q8KICj<^IF)Z%oLDrda&Fxey{m|PF=fu2 zOP}t#^r`y&ZE|2#jTK|{Lvhz!H8?_WR&gmRkdB?f?h><85i~x7Q-L*r9k2>Zl_Tug zf_2rSBU@o}_tOXOyHN93uojRpVF}+1aHp-`R^!W(gjum_MQ0?VI;YEq{(+*E3lPyt zk{Uu8&cfC>GyxO05LbZ&L~47>%)NR4v4`W;J8=gv+5e*`NYaGpvm}^ld-LqW{AOk~ zD320KNK$Xf_znWm-4o2iB6Kctf>vQ^Tg&+1@#o8zv&6pICGk4Jg|fXVb>8pHLmdJ( zC^;pGyi|himBIIC@O*na>O5%C_ClXO**$%s7^*N4V=1}9pKwn1S`Ia=q!V4S$r*vqI<`AQWt zsqSECnGwQT%#GxGs&SM|=p3H;HaTq|heXLz%jWCm3fHMUxtaP(oucuQiIEryw%ZG` zA0`0{LNL`JTNxr?m(6w(``sLJx!71^DOqyK>Ln)H&IiAH8#A}LKDw9_rBOzZIy93s9ar^aJ@B*b~?rF-M-a8 zby`&?_JWP>v=b|8V}VN|R;|TNGN#mNQD_ZT&Ti;176af z$vK4}{zQI~Oql+;xQIwL#YS<2!OE0RlCX9keOh*=!BInQe6yb};_=Wji9;B&p*$(ELvV?c>++;-^aeBwFNX_J*KD97H|qQ*BomsLVt2o*AE zo5djeUI((F-!HPswJJrWB+jD&)wIeRpjDuWuohzD2aml~5L1x_)kFfVbvmR+oNbO$ znL(U@<0MIBWz%agR?%ai#q1M$Lq=KMoBD2msgn!NwdUqvoG#nhBU4o!Gq@m35KYji zgQV}h?+aIz{j@|4;uysyc@sxR!MLXfx+8&FAY@8rGnbm!pVg>AG&rX{7=`lkmsWtNgr zWdKZ;Jfgb|N zwZtwM2j8YGf+wuEB%v08q%Nqo%T>+ojm;1hFa|MigtkHHd~Z^{smU3{GCM0FqYs*R zw9aA$>z-sKn(QQMNjbxI@v4v0XMvYm1<>j-8F24&UC3iDWWCGBAJrsj3v!Hb15q)`@w)^0E^-6VIMz!^%~ zkwsI>c23saQxQ&Ou%r^n4a8Q_RQ2dS{WgIvuWZnggS%i=(P?nV=4MubXfv^|#_NdN zDaaFUXF)|LQ4VMnXD=~*?JY$85K4Y}mA8AD)GY8PD{Gw3QMI%uZzodTpSLU0t&TG{ zp+lLvs<_czm#2`Xx&H!XUhg+aM6Z0vI<%M3X)x57=0Bni2|~1tP69nQS`ay}e^X49 zoYq1s7RqKc;+_*32u(jjl5%Gp%PbwJWSc7=wBC7cirm$bWaoqLljdRRXqA{AQjv3x z{!uTsPu--j8n+E)YuYwl5C`#?1VMg%bNYIEg|T+trYfU-WHFvKMXOA16=t0Sv!)PBDM$duPWd9kQwCDA zSuj3g(?|CT6mhJ*wYkS_sNc-g{!R4JHwLymR7~A9x%1FFFJmmTJy|(;jk>?`YMOxU ziuDqTNG>0Jdol0{Vv<>PYb$dxIqQquLouq;9UfnewaUEdT(vs!v#Gse4idX<2ck`t zi%c@kG3KVkn@#eBVlD@r`Se538ayj!ux2}2{y8VR=Rt*Rs~kTnokvs2Cs6o(m@zF0 zBG>GSu^7b-T4P2#BUgIGLW^s&mCQ9_PGxYX_fr$^rrgz%P^YJ+ZK;bBw}sprG2DJF zI#bjXYZIaLF`#XQL4#S+qNFKGuoF;Y_EjwPXw}^UEgGWNIusXDXp+4H+sN~j^nx6e zX%OmS#l1gbLCnH`of3E-!emZ_Z< zpNqs+lyVj7K-Kb$yf#;5no@+7 zbQGv|hRavoyDwq?{tRCpCO3j=Xg$t3X{3rY=pt7+w7QDfp^$4e&Gl@1v^PA8i4DJJ zFy@xCJ%cgVZuS|BxqAj<-W=k|!I+{UVs!q-XMZn3XYdZ1XisJx zFfvC89F?TuhEfhxR7(o8WS^UfZ-3>pZX_q~{-X`xZE#yVj4WSh??5l%_37V^=&=_k zC$|Bf2xq&(4Z}%Sq&L_fk)U+`22Rh^?hjx6@8$X7TNz$;_1o7+{F{6V&Q31RE+k}; z2miBt`{O77`{t8Z=lC3f4f0E8I>Q$}fuAS>D2{ zH~S~2cE&sD=tv;j8MC#Ppu53(H-4hN8nr`_SanfEs@c1I_0^E4%hI*7TyGW}Pl zyE)AMr1_G=LpW%Ieg1G|?;54~aQk?L z^=eJ;4sV%vK(xPiCA-@?qsmz&c&Z}e&Le8(J+cI}XI zCHx!U;pS>@zS;)h-K$d>d-=%w-8=qpYfLY8x6gZh(v!K9emvjlncTsfHb`$-4D!u6 z_wDh%mMB#Idm_>3%@Ezpf!!6{qB-mL$NztQsmBM8ubR=Ln`e8Sv!8&R0`})e829cq z|0*AsgB}}NTRtjJOGb;%({$?=Wl;GI`r=@ zWtiXY|8(+C*FVRp+=7t(?l0$We}&ib0Ka;D`1Wx9kAFGHarezMypX~B>gU6^C&#bs z- zr7;C|5t31iS*0T8zdE+$9fO6;@Jv?!$8dfr#e2?Atlw?X-h0kZTdksx`i}c+MGZlx z+hBDUf-#bDFFQb)kqc0D`Rixo{kk*h3%G#yqi%0vxIPI|-A3c@HfVJFzP^3h<98nI ziGF#Buimb1!5%-fmg#TZIlg$at}S`|(E16*ovdGb`_Ss4Cc3;X&LtPRz?Wj9h<|-q z#463Slp%o5+LOU5>5lI#2$;nt=g8iAjLLgVy0=$w{e3R6gDR%X2Ifp|@E!VeJGa+N z$|ZCVAOQ~6hRz^Rxnzjh=ahnsI1F~}&lOa0RPrDbYGxa3Z`0KpzO6d&4r}(+M4jDW z)#ieZIWhX^ITqrg@+hf#fdU{`%^3>GeNe^G9*TK(s{(KZu@Z6=ulWyIr1f;w^jp-Z zwV0VEj%=9?hrt0_2NGef#z+|IlSjGV8eOl`RFCY6ur#~ zqfvIW5p0=C{=}~!(E!qUs3>#X)lDx5Lu;F7XiNVz3Nhk4QLBXS1PFEoO zCSnz*rgR_UtRU>WWgTh}S*3Z*u| zoY4tB-Psk8w8VNLag>aH)Xq)gN`O5WW0k~Urs&c3+$F@27#9}noE)H)fb|h2^D`Y} z>}3*JplaF4lo~Xc3(&I=bCmQZk+^{BMjO25xzfq_2t|Vj7Z*B&8ik> zM(?V9kM+t=kf=;Qo6uhsm*dQoftHnab3}dCXQn++#9l+>inOFzz5m3GL?xgC2 z&*H&SZtZerFlb&tq)SBWvMsR~3J?dM(ri6FdIhBzoosEp!J~(7TN+cgN^^Cl!8{#> zVN*T>MUXWjPCa=JrrDA~L%7^7K{=+HDWR&!X|&y7S|%o-W|JxF=qkI>R)gu@Wo9%5 zU9i!5Gw9JZF|X8|vtyT5s6WWSy@Ts!}1vQLTwJg+y;j7iMbE>li;N@J=VKyvlN9 zui3l7NMnimWh}=^*;(Z1O78EgT|k&i!l!cyArnH5u5)0XNY!9j$|ZX)K{Z5)j)8hn zee*KUqPq+g<|^Ynw1@ z<2*wpv63T4pQOSYJ+okips%0C{3zfXimDwaonM1GXU15b62&F0TVDv$9)_(Z& zG@cowBwJ3#McYQ@>|Em06l~Lo>?)~DP*m)ttj_bOvM-P%=>&-v0ea{2??PjqmPBb= z+tu5UHEXK9mU>o~n8d*sqpa9w;?zrnU6TngHb;tLL}g;6Zamx?%e*NQd+ogODeCV0 zX%T!~G@*7TD{@I(`v8)3gHVjj6x9lMWy%&>=m;Q)QWZ zp<>jwmeMVFvWb3AN?WWA+?pUsa@>E4B`{*^Ee?{>vkXk7IwB0Yfq&(l)>$b@jcQF8 zJ6+oXq^}gogOqrB6XdwPQ1eX~*wj=i*jiFbX*Hs}G$Wl!Rv}S=YOB&|RFiWVVGCX< z;|gT-V29?;^mbX4Nw3AwC`<~y9=Y~Ka;+;Zql>u~)IQY#8t6>pc-u8*l2F2?_PT69 z#AboqQi8$i2&;!Go^;@i6}k5Avs~eW;2dUOQWVM3#AKPMJ%u*rQE|HfN61Gy@Z2H89$6ZGLV(Z!`x zlc;1R)-lKr7hhBFUfKryRH2p`0eD+L)n0|obyg*!3o%&;NjsTHLl0p=BdZkTW-P@D zhg|9th-!u!tH~%?nK3E!@}4&c&sGw9R;r|t0fJ-C)eP*5k#J8^Gao`PnPrRM zR0;;TM2X3mF?8;+FA)q0VvXVmtJt-ydSiom{Xgqb0;M)>$OqoYPk*Mo+GRzYQOwud-y z>_7kUyYF{DU0$@eX4|{dKGItvuo&qT+Y{jyzZSpw#}c)1Z>?WT2#pDL0vhAZeP~SD4vmpn{Y61z{s+zg`IjfB z#^k&He;_dK4RcpM|HV^dW{_W}K7}VY;KjunEGFZ#i(ckOFpR{UwMzsx8k;58#Qef?C;f!G%8z^myb`({Y;~>JeD}(l_bniE~ou+6RpnQ$>)bMg`t>i zy-E#hxa0;?olW}66*Ah+W(4Y-tG*b|`99_J=D7j*o*!7dCqP^?!sIw{+Q%Ekv z(UAhDa@T9jUE@oKuzrTO07(2x9&B>qGEE8HYoRUcM6EL0@Wtch7@tMPxz7S z-i;f1#VJ+B0y&xu#%ifKJ~~h#1GTYsfTK6dP4eOd9InxdQpo9s(i+I-ANJRpANBYp zF12|XmC%E+NGhwm#fUtNn7h_J*FYxNM9!ybQM|)ofySwP0f+qo@2-?qSFadr&4YzD zkFDQwZvcvmPaJa+c$;~H9a)`FQj^XU+JF^j$JsZ&I)|mZz?$1&D$^8_UC0yLy;Aa3 zU1mrgF(`Rfn9#sWwQw#$l2Czzvqr^@Mr5h~PvziZAVWoPgBl$)`S93lbwSNHwjtS8 za{=PP8`r0`jimBqv9cLXi#JCNL^q^m^s<}qcxoCg+{-D1d{RuK+IlL!jvUk3* zT+C{Sn2oEh+YQO4>R3l>5}3LPYOnHI$Szx7#j|4x!K8^(b7uIMy6tYQXtV~_NT8vP z_C!2r$>r)Xorn|KP+bTd%LcP8|9w3Bjq0HXd%TI_cTAG)7q__q2d>j06n4&5qNq5B zGy{KLy5Ha_N?Gm>Q%d}p*OW;>O12Y9vs6=84e2(LuQV@)qvLNMdxn1Fwgiz_YORqS zSQza*UwDUWBnA@t9Vrte_)df~+J1^rS}v!D+`KnF*ftQHiy5V3IL~t|6kHijt^VCM zHmR)r77YH<6aP+yzxY(<$6;D;ONuE`oSP##`D(@|U#MUf_4Z;AS*&`{$QuB1zd=_3 zRiaW%3NB%S4TkEj+?3n5yZ5~#q`eryXmaABd@K|G?aMwdA#bQ4ua3kivjoI$^XXh= zJHh~5fqjjFhWvz^Snb#$#j3DGQCde___mH9*S0{CC=yt8&f#2GNiZi=bvLb}*?8>6wf4VU5Kl zfMNNCTB*c_y;>%vAnO1GSU^BaS#7WZ?IqvselG9#*YA7Q+y>Ve4U@`PA#6c&ePRSJ zW*iL}i9Ah`VL_gYab>@=0js3;3@fdU|+Qc+*j#hfM34DyCY7u;>c(hgFVT;!$hD*c- zNMx%j5U1?xS3q^whJAJehfJ|eoV1PGvbq_Md8q{zBkL5aY7G_^Mkk#=j$@YyCxcjT z*=y}lH-exEcf3eFD-n*ul%2vx#JS}@>g5?SznsCl-nq^t3WmpMTnwphxea-HeXN0B zxLl~o7Q)mtI?(9M<+BZ0CiK)=>?bHk5wZ_6cxts5tO9cOH5p$arkOxk4tJ&Q5kZug zj|?g=4rK<3EOSy6v6|UaFhR4U(dMbXk6oim)QSKF@?nToyvqjExQLG*c}%_66;o?vqB&S08; z?3BC*CLde3S{fyJdTb&WUV}~&Oz9xdEEgZQrl+rM_cp+KtxZIMA2F6$cX5#($u

0i*(j%xOeS=Ap`pO{$Qh(wMn4wy_ajG+g3{G?)N#32k}it@$k{)r%#% zj?Qs0CRrv$OfsT9imvRo6}#bO3P(<2UkqscK5;DBu+4F=t?<5HN;x{bocBWd$Dtqc0HDuQ7~kDQriFXXcUOb}|`lHeoAd z?4(=7c|8Q9oX0_b*~qS6pS(1F+$PfA^8RHQJsVXe4g0u~WR|On-s%CyRHV7n96p_O znY~B`iDgk3U#X%6bjv0!*ieH)v?{d5T)CRWHh54KVqPo_xxA*I3}4nEiFS2djJEmP zfMJ$8Pc5_o-=WFFm=lVL5BvkMBm%4XDNG16o7B0l89%jmTq)&Hc&fGmJdDkf*zC>v zvbg%jEv+#1<+Wd(k!pSfO*8Arw6bh4l_HhgyqMd1w=AB46hHr5aen;94D@~@La1nv zTi^dBUg;mWkkM8%g1{`COjTF8+~Orx<1FJFUEcfv+weBf%m*(yXdlea(174>=J43+ zDlHGqI$v0qvq3?#5>Ev+Iu0VwZpZIG`VviNVJzYY0ZN&%Ong9=KN+M!QmJ6)h!MtU zhaQ-MBG1+5j7)O~5+ArySVst|Vo3b41{rN{#U|zbl0A%PP_;MlAmH2jQA&UnZRi*h56EA zVbpn&_%k!!kigEc%0crMF1zuj-w!{9Kyq%PZR3z?i?tcGJox~0x9X>|j% z{v&)+`8cyi2s45#pPYG;lXYXW3=JA1@di>i9}0xMJNA!AX4IqXkz~5%ObNcnmkyI2 z9kI+T4!qoZYNw;8XZeqOdzloq+Aot-FmepEuxJH{*+?%=#LZ?ZJior~9RFBZkUKDP zsw1V2bufk<)j7&LL~z~(phxGkc!AL56lKOm2UUs+BOq&czdO~E1F+i^tFqlDt?iwq zC*hJWH`y}>c|;dSI4T2W%fNKWyQU&syfdXAW{3=!wS0t&P_S0Auv9#VC8H;bqxnXS zC1T}H*=UO)p81s7ZA0eaq)@kxyas&2Mlj++d?2 zZ%7Ut;@rw9=WKs<=XSRE4W4V}Y2utF5|Gnz7E>-bR@;&#Wr1wy?I%B)u(h0h% zj51DiUaUr^n9LPlFegkhh=P(Fk$N_-7+??3lM2?#ILI~Fa^g7#Y{cPgjwT=6gJ6Jj7Ct`sO9$ZZ?Az zfshxyJ6AW^!za3^6~KdX_Ku1BX*h_9I?oCZ8=U&MMMdk3}$<4t3Ct9bFJ19+s*^IhML*gYgYRt zV&~2R3~RNZ>nlmz><$odlVy{{r0WWtp2{mb^gy~QxEhocYfkZK-+6>JJ|YoN90WfD zZpN)Pswvh5ti!77oLeF$|z{!D#l3i%pM^0jn%-8*A$hmXK2l4qrzIaG9QQ? zGR)4VWS2NMIc>R&S0k5}_HKGJ80E8Bb8fZdv@MKOjyE0K6tic!BtFW$dL>B-YibI@ zF#{6Lh^OEE+TuOXG-xqPw}OFq@q!XUIwi_Avcd?JNn{&$)nj&Y!2&g7cK*GiS6RXT`;k`;DjqwFws8)gi{Tdkpm)XhJsyoD-%cj9W1FWq>LZgyn!5% z(UctXr5?gU!Ew=Hl8*x9ZGM}()XG$av(_hUaiE)O0L30m@M+#FzPn;rrWydGpS_#@ zY7m?<^f)u7^rho}jeIqFVu|T2uI6ekrBb%m4#aV=ZBD_#o`Rl3Y+x;d`bppD4yQmg z&gkI-oy8Qs$>X58yVDKx@R>&5BEg2Fmg%8+U(v{P>Xz@N3M(Hu0TGqJU@L z!7i%YL5^N|s3|gZ@UxV+BLzR}U&6d@F;S8=6}&WTV%j7iU`ALBK=#eX5Ho(5@plS` zLbfx9)eaXey!XVK558pdh>P^4uJy#=;60?btXnUHkNO-$MGcMYJc!kY7VT4Lb@p%Z zr=5{t;xdwe1IiM_h_=cHpN#VCwXS>A(LM zCq&i!q~87|G4n;HE`u=3fN;7$HlOOn-f&7=^%fLlpYet3zh4yoZ8%V`i!38~9no-yVv%1oE zuG9-%gmm=MGHdekSrC{Lwn%iRwY+`ck_nMV_zEGph-U>zBTqfr{xb}9>@$544-PW`JAdY>n>8_xq zF5>p(A6&^VT>Ay;*O|+(rrCYq%h0|4%W;+0MDQ<01Q+Z9=L)+%9%gE4VF>H#fRhJ_ zHmScn@e}&ct!c(wCFQdZ?q_Fawt_R2iaCRwH*JwwlaWKf=4{d8I%PnBT%0n;9k_WDqfxJOvCq8DyT#b_4K>1f@CwyN(21dtRI>pJURam?`ibo%j6gnsh*_s z(i}VTG1@}q4PG`0dYp(bDn(t)ROQV>gFyNa4pwf$njcBVD1BOHB5WXl)Mu`gcwWn1 zi|qVy@_3G;s!b7x;os<)X@A)93NyBRuT9e)5oKWD=y&^4)TL^yUhn0nxIPav;A}l6V?C1g_cRq^e9DxL7aozyB@f zhME@L>GGkz#jp3Hq_{fFHC2hB{`l6 zERwODH&7qUyk{yCPta@*icn%GvK~XznOmATHqI=9vSCaY_HFoyE_GKvqnD7xS`MEJ z)vDn)_)<5U_&2M>Nr6g{Y*Bj^dLX$QxOUPF?)v$p+2nWGw1+$k?wz(=1%@sq$r-sP z`VL?VoXSLpjA3WXPl{}4aso6|{RMMXmS?$*L*i*qlPD^>YTqC5hgl(N4EW1WB!BGZ z6aFwOpXzbIzL#d}?=eHFePmBjQNpow zWpT|heCCcc?oNAUAc`EDdbbj|-xzf=N9qEe2aA49CnM~^``;lA@Qq@lF;M18XW1wa zXi!;k+VFg>91McEdZN;Rfta%@SBuH7?EUh%ANYEb3#3=wPrNL0%=MZ!mVUu+B&Xx> z@m{6*;&dm+<=f6t{({aJ7r!3(fjuh)n`;!UD67&eQ3iaAZU$Fj-0+ z%w0(h)CP`E6J)6=XKr%^xpkX=e(!(%E)4vl;_^SEcRR6|EsOjqh$1nj%a4W`HyQ3y z8k$80LF8Cd;J|WTVNtH=u@JODko+io6retl;U-7`6g1^uLA+^m{iw_b4h9Fk2Kh2Y=#<982`0(&3n=d>BL%=@n-;iije{>H=k?G*wJ#JY0?|ND1tEA{R0I z*P_W#cY{jsCmdgSm8Vezqk)Wvk&=CMjG8mZmvmM5O%6!KoxuU~9F>q0UH;K2ohBr( z&{da)#h8E2lcG2L(Z#s;ZNDY5fqnzDp`pN|o217t_)*a(-9^y#RPmGV9>G8xVsBaC zx*(ZFMCfzvylz+Su*JL#U*e7{Ppu4KV8PI+gBtQgF!=6F3`fB(KUSw4Bs*)$l5|8B zS%wt~rZKSToV`eA4uw7g9$ZM1k}~9pSIJ>xz&2T#VCtt}U5I+S?lleSV);P8|H|*Z z`d0zueUPcNeO)%A2PJ^y?8J6V$~MzNmQM{HEubY~NI}?PMzjN=_u^A&U}dj4D;9g* zd)J6m!W@1Ch#}yth>GESGqj-KT^J;a@1Ap}wtCBEi1l9%+|iz}!}1CHx2Z!qZAht% zkn}DwQ$*T^;iTbETqOo!Pf!>iW}LlM!#pa-Q{M*jKeW_UGBT+43@h?5!;w?9bU>0> zjyuUIrxp(GrEJ*pC+uQ2_rWtgBL+P387$9dcLzpU>?EV4t7(}#jIWGM&XDa7F$;UE z(JyE2jMK^n{@N?TZuy6~9t;G2HP&)gzQt8=QM(Fw=oUPG;caPdkh+#A_GhjX9=-$N zubX}kkROkoMV!CH1}E4ukf9UsQAp%e^`h7m1cE3_Bw{YiJhLLy;w3__Dr2tq&Zx!v z930EnQ?oWf&Az^ydnWmN=N?b|{`|9qxK38Z&HaQ3aOR+9o@c<|n0=TB^WES;iig@c zGhrNa`=`TUo}b$?WvOKw0ztaKF%SSHL}rADo!2HF!^(~bp}C#@)?}afO4x& z@ww)M*dXQ(!158E0VAPl;UA3u-2y2PngFxvtQ4q(S9504iN?^IRw9zGm3<~c3{4~U zLo7@yt8IZO9rhRu-OMtFYy$-d(~8~GC)RDQ&;w1V$t%8c$JFzI*Ji=MBFPVIZy3#F z;o{RVn^D{tA%T${O$~BT0)%w_*(AMBgEA!|>-^{}BQ-rVr)=Vg5TVs=+FDe>^Fv^D zP@Be|uDn2rYkGhjgf&XPdX}$_UrMUD_sb8bv-D8m2E#>GA(oQalZz%F_`sHz*=I&y zmiyvKI2}?Y6#V>Dc$M}act&tnub7J@8EKK|I#iIACs!4XO36QSNr!OHIE}W#q+VeL ze5-Tt`lRF{d2Wr;l)Ki`lbYI1s&A$*tgxACz)Fr_M~9ed63= zpU$B}`fA9~?5o6MgZqtO@(@`3ymV;-gQOMh(j;e-c|(oEl!yv{4Dwz}&6+_yL5#@Q zW|$$-HwU$1H14RufDgnK!|T5(N1=^bX@qm1iU+N zo&ctq9`*voZCKcnhDv&=mXwGC`Y62Z4Rw;ctVLB-J#r8jsG*x(+21Kz3YQHZZ zzJ=Ph#+oia0>|&q7SMomJjS8U%2S&Zc#_%SNm_lgnICx$b63ROA7|q+KHd{|Hj_03IAX z;gzXgfH1P2>TkKXHE7z(`L0I2ubk~})rkgH=0F@rv&uN7F-YH@@o9UIQ5&SgCM#z@ zcfPM@pb@#!XT2W)yqbq2T);>dE^1(-9HD;n?|63sm@g1>Dm z&KmR4R{2sVa`H}O^GQA2pl*jTNURPZ&Z=dc?Cyn?6z94NSES0z_>S6qz$vb?wu|QZ z@^UeA8_Z8|DTBLcUv3_%O|!G8HRmDski$MYUcI>v3O`Jc4VEGFS8po@+0P}N27H;= z7s)oj$`Sr@Bq+zKsSe8Ye~FaVcomMLIG%^Obq5@BU`v>d%I)ajU}#c9Wb!fqu-9sr@Z;dUo#xvQKJ~}== zEb;P9K1bFn1%3tC6U97}=~49<>fd;SH)_K(YVC5uA9A z%tg_NRt$~6sp3b^!y!U08lR1G;+9-YOqx!%SYZ}Z2PKVp<}+(TsLqM*B=G5kZAPGG zP3o7bN*Of;4_P?p^S40{HM}&So5Q#8y)D+_r8Xf3!lNn+&94@nRix8FP|16W z_K>#BHRl-}pGmo`B^rh8Xo6bFub-Mw6$`%(^PV`B5FM!AGz~Lww4Qg;X$Pum!S_(Y8;+S>X!ccmRiGN;8~(*vct%+!fAfc*|_^$iU#Q? z7rZCQ8c`#TR!RPF+%!X2RwBM>>Q(G@;|H7;l?qqLj!=>ZoVw2d)|XQ^=j3BpqKCKu z(((fEGUIMp;n0{{!NQDSGeSlxj5RCsJJTFgSXEC3Xd+!Vh=4Ufz8dOfq-UYqw^WcdlNG5FG+xgTGfd;;><fjmth> zTZsp93XB86y|>e{v&e(@wG^5YLl;EC+SBPGcbr;8oWSk-nmwo@s}E?MB0BTcM-g4y z)$hnxTx$gRKWZhw{ZAig3hfA%&g9kA6;LpVyc|J7Pzo*$bo|z~E3-W+IunXee(|h>{V{GweLJ=ud*&rinhgG=YRd>8e;>2X8La z#+!_8s?CNvJNidM{iM6Z=6V})!J*01BmvC(wT?zq=(6*=L6qPI4i%?qQcOM|2*{1K zp?=ZBBxwM^^eUMY6Y*|8dwcY7%klPT=?dVt*-0(uAHViy)<})AFzr3qV4~7HXKpYT z2d@_it_QOlEJ~m^HBB<<3X@+WgoTL%gE(?X;$NGwqh5*S4r6M`AY__&`HQp8fni%L z_iSry)J73z+S1NVHM$!|>7+-z($AL{Z?BG;2q$k^?&pE#89iJ!(e}#d7+<5~D%c6n z0lUQrD`=V&)E9}#gJYO*nCxx@P<1og29>~bvtLbvL@QD1fV$I)Ugq7~3-t&q`1moe z6JGGB!5HH9TQ7aGiiZIfHYUMVD>7K+i6?m5?}`A*37c%( zbctZX=eAd*oF2kj=F}+lS(9kn^DHPqD5|GfR0fQ}U;v74rE_tmI8mWRIfqB3WUesa zLbPhBKOy4fDz;2_O=_t+NczYhH*0SZmAKPAo38WQxtRxB_*=RkBh2oy)&F1%a4g;B zOqPlTR+{q<;mgpJYgm3-rbo26%Dofnhwp9;HACNPvTkjtIp$;)fY@66S~Z;@_jdC< znf2PbGWlJIz?F(#vo};H>F3a9ei6K{Nk=JqJS%iG@+0NjH# z*leyS%%Laemo)E9o_%v6@Y6TOO*w5giH!�ZBrZ-Z1cssNzM=#b1-)*lbqrOnw># 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%0AH$j)S) zqpr`5sEBE_mU+vfkSKLoH;0F*m9z#y^;EFim2qYhHgg-0)v+~1JBEp9};OU z>Bt;6A)CVjy$113m?kk_ubjt;;lC?wQNeH!Ga`_=YhWqQ=zf-GNT?)6{)TiF)+z2J z8W~8o9$8D5IS5@MDt;ET=_~9pLbh9X*rjm)cqZ*neZ*)}^oQyKoG# zw-jmNIuMbB9Q8gij5r;LiF|1nty`T9MI0`L^#gXmP>1?9Ao+g38xDqn_E+Vv?Eu=D zwtCL?;|$+^?Y5IiK&RCj#zl+=ATZ6)d;0G%NJq(-WcizJ+fDcV4rkb18!gtVq_ryP zYtGEtYOy{!>yz^vPR^J(4?a4(bZF@Rzzfc}FI=7x&o$$Sc?r)9VXwt8vB&`$9U2C1 zVlvu0z6W2%oRK8RT+YzIyDXwSwBU}+ZqjWG{KN=32T7!4{|t0sWzIy}U}-Rg51rrF zSk!*-@#8nTj>m~#M8Wz-UelE|UHQsmv%Zwqhi83we#7D66jyW^@3uI3!`>oa%2{*O zq0WNR5b@cpjFQ;5v@1BZ%WT8m#3MmFDxG#?$PR(q>vOCNzR#D z*k3V>J&tea4U-TF!Y>hOAni%=pC}v!s-tiFv_1`W5=Tfc7_e@qfowfzz2L(o9br$; zys*sYq&7rlo|Ksgv-|mVvXi$ZUUoGWdbX}t{Mp$jHUN*eTn@CLhw zm30~Jz?)E4=7R=-b-y~|E@%3Nle7e5T&uhxh9EqCNG-vJDH=(0HF~wzQgzYoI;$H$ zGbXOHyn2ITBfr)V5Q>bQvXhv))}&V8fi2lOE%G|I!cxO9!OnTq!Gqc;9(nyV85_uV z5*hB0kuYABg7C!m)p0RK`Zl#6_^br%7f~4Z%A4U3M4f2=>x6D%jjN8hiL5PuN*&>` z9;m~V?)ZqvzOM&ez6!&<6({DVqAnE~aW1_fxB&jv>f>8G*S$Q59LD-f@HK}?E~(`T zKZvI7JPrD-II>qX{c=sqlHz)y);{L#;UsDeC-ua0L4-IJv=dA2xgcr}&4bE?pO}=m zhY`&$9aFFpX?N}>KDXJ<-iASb6M*9w(WCk$cz~F#jKg&@;WGF^4*^g`<(*G+P!3PUGej7Uv!GX` zftyuS`KWtIS3#V_7Q@`r_nHmvo6LR5O1l+!wzXb?@3{ijvu*hq_^W_Of9Ya-vXR(#5l1xn1ntz#9q_KO1Htj=hsOBX7A>+(T^_qXt zbJL_tJ|_lc2)Pp(FrLl$G@Za*1ce}e!@&cEX;N&yVit(2o-(Z5IjU4Rs8^`CAJI-2 zLSr@NR!(k`sIco%c}t)Y@PeJrg|Vzudb5h0&CQ+p*p8{aDEc;JrscwmwPmFru?CMHFOzFF@#-f*SUd4vF^w4li(s4!8 z8p|m!=0-4Kl7Mr?R2>sPO#62{0V{VCEOt*J!g?75qpSqFm@Ovg3m1AAOw~R~74-L; z(s-I|Ck?Hq{CiBf-!+If^UjXesDb%|`2wSsNjNqjGw^ccAodw9h8krK#u_*H-V1kS!8D~5p1COTKB!&jVEby zr}<1Y{4ciElf~E-d~l6+|KRFu4zOaGYJc`!^;7MNQj-SEDGgXr-wilfI6N#(3yB- zBa#W%VUUUgt>ydR5SqcPfK1?ZD3~6UTs&!>A3~<@GUxK6Tm@Gb4f&Bc z$(EfLK30v=LA$BDNs(I}Q^U)^H-S@`U>`L~o9qvnyv_)GS>=F+81X87&li{`PXoA# zQkiZtDVa)A7?Lwb}Hmw}(TsjWKot65ah33iGcYT4j98;q-Z`u<|0Yr>|qV{TE5ZTEAx=p|KHbc8|! z?v*9|{FcLV#1*Z2zgRI^BG){|2%D!ou?iQ0`1z^s=ju_dBOPp)YnTe1Y)$MfcIAPDkppcLCNS3dLGBYGjB^89;v*QL zAt02uqyuSW4u;uw2M_3Y=@s*Rp$lm5&NVSZF$euc{A7WaZ$S)UPriP+E|8Tk#7Yy( z%bJya@YQYI8&^yeb#zha9r56saj85v?y_9A#D5u8*MIB+Gxz<_CwP5;f2Z{=LRsA% ztnTxzm7(=lb2s#=1-Cks+PMW=+br=5?8WBdAFKjZ)Doo$rs#gw3iBVkfK?j2a2eM$ z_|Lz@mI{B>Ic=`b=|e7JR&0^Lv;{Q#C(l~jTMO;nSuwLX7p`{Q#L8AFz7=K0Cqc?! zBD4rMbp8h7oh}PgJ!arF(WPY9mg1psHdYbcOkmgf#eoZ(u_)e)I(M*yyr($4om$g%d^qsSK z^@^O2(sB*|1}CY-?twLDl;z$iU*ZXO@Aa!`m9`e3VXjy4&#;OWjrqc}_?KZo|CEbk z&1Vaj=5zM5))$>H9M0z13U+b!gmr%73CokjoHEY_)+{|`v#GpY!W9`><5`kP#pB}oqT`ab=y04>XLiP|uj1`1?#*7rFJPBm zjYSVRC@gm!;NM&7s7R5>E;8Pg@>0{Z=T!Ka&8h~36?T3QeY=%p&Q7jh{*Wou1s)+- zx`ijPf$=L9?Gw6`H3qhb4z=GEL}C z>vma>ThK+GG$%TRS8^173Iq;88q3olsQ%WBl4RmiXQrMsey{1C44OfjCMm?>r)syg z^JH-})HQ~D%$cn-WPBLYpiWRxz1LA;l&J?qpok;BI^~=Y3<;6V%=-)*?wb}Rd9UKG zsGG7yZCfk>XaGiWFir%CG7}f0)2q`4{^?xupUV^e(>xfse8IhRI>{T}Bt#RisCULX z&5t;#uMRk`GuFstt03L&HX+-+9t{@oX6vcWj~liMJYr zH-S2+>LVG`|A5oivvrDhmyO59-n|5PKZkN}@Lt-i?_0mpIVtM>YOfR2akfOSBB+QbqgU@ zlwK{P1T;pD;QijH8N?=?4R$+v5pwPuFAWg2(#vJA9QGf?13E&q4?YY@;2n}o>`RI& z%+&w%yu+ZUi_B!JVaH4U8Oc2Owd@y4yh~+fI8j0u9!NOj{It9nIpGDOTpQ?r2y5YB zK;2?}CJ_)22)B7N?vIzJQ=5c?yTuVYf%XkH8uIdVi-GEgcQhNcO2mNCvKSqUbjI_E z)*u{6s~!l3ju55L6YnTmGb9?SjG!CDM9A_?8IYln_!Vj>n;|Ks<(un6+)w*azT2lgyIPZa~uxBoHoai9s_r- zZnzj+p*~R&l4behW(}Rc9*H+e;k9+k=Q|DP*wI(|%*cN|J)zT%JrRy2UY}2qN_9No zvt?X(=ur5kLp|zVp1Q2bLb&WlS%iLCnT2R zNCE559N}?NAeR=T;fpXX?hFZtrikA)_7TYEB#}3inI7kUq*JQxt0!Aq_Wcc3({T^V zkQG^#*?_UfFbzE}7wxfWwlx_}Jdfs=x|9~I5%N5{u+1jgZ<@C)KPH`ClIQAW8s?v< zJ|`l=lYTpc`YTRL_18s_e^QtK{@)ByxgXKDWyy_1Ay$xJ6wr|;X$KX0@}aGX!XUw4 z1%)X`3WhY7*p)nQjrmJE41!9rQ(RDQsSP^Se%c-;$%xLsi~7B6sRLh+)j1J-);E5n z-_!PlhM-f5E3J#$K<#%Y{Gr`Vx*3zniqm2g z(z*VSBA63ii}bCX#o;8_+uJJ}yBY%A@l`QM)cypY=U+!eQ9K}_{N2wcXb3Us8T2T5 zt2dN#A2hBzb*MuiB;J1P;zPR|4*E$_(J~(5PE^M&bs5lt?RUrYr+t%`3rXS=ZRuAb z9g6+#kp8rxo|&?y6<=$bL_Y-|us=4RsA!iuKb}?KV9@3u7XZ4p6UFCXAhkHMX0xe$r_bcXEhJBvU7;-w&dk!^-(dJCG;k01Syf zh{i!i^TY>5n=kDs?X~={6-@e(TP*bP1I>xnbj8tfC9T_5CSTg4kHNU!;r9WZ4)&%6 zOz4T4_MoY2}wx|KzhV{`}yUt)3D|@L9PI7m)o_9<===&uALsnu?tj5tlOksnbJzq__9!>LTWX)#IYFCpz;k zN)ZV2It+*@GW{vyRqJw;AefI{^e-$A2+SCtmsPnpD^PK45QbpZ$7szEtQmqeL$GED z)(pX#Ay_j6e`$sw@psi$>uGCCJ$o^0!M2)6y3OEdFe%_AtU8!%)=ykTdMX|$9m#vl zR%8`kC4R*wPp_z}9>;<42-aO%Gz~{cr+Y+QLDYxV?=1I9Rb$LL&t{%9p%R0BkIEaC zA~4>_8FL`cs~jn9q=&QpYtWtUhkf>t95-Cf5`pc4Hqi#mq428wfV2wYsE3{Kv6s>R zuUuK)xygiDehE^d3!-yD(f>vn1!=CEl6raBnqKp-&W`u3RthRf&xKcrcYo&iuYB&M zf0hZ&`pxa;_VyklS+!owE6>E6y_2U!52|dRVte*X`p?Zz|!KZW@UZZyc?Gt z_2%M)3;i>kG(@9*r{TQ2GGApv_wi{G`M9V+aQ*2wo(X5(H}kO&ZRtN^KGu7J_JlKM zEu4wJOd!$kJBLYc=?wm+c%O$v;{RP|NYWOr&)ayL!-u!onlp2=pLQA}eUXY|b zgl;J zh+ii~noNKR<2o&jUM9QM)y7-1hzhX1mfHLnEj-y$uRd)e z@HJ68)EYIFwY-;NB_(ks>oPg%t>$9J0bgiKPQ(2#OkG6F@*V(7sS?XD! zQ`={G`!0=RN}VzlHnyKW+42tQN%lC~l+=ABnQ&*!g6e3H&^a28F|a|B_y#-IoHmJ6 z@@N4yNq|TimJDJhJ1unrBk#BXs%O%NP?r_y4W|^VEHv^;np&SY=n2xX+JIj~Y+ylS z|2FhF%zbQDmxo$k0}qpJhTtNMQLfJjz6@^%HDsK_od7~Yz(~CPJV@QTZ)|URl7Y?A z6p}_-${jW9P3s4}%9FH+6;g;Z%&5k2bkt<8Uiy(uy`8Irw@29g#?wN2SwBEX%Gm`r zvG`2T{iX*vbK>BnvY4sKaW}TuFv=>f0oh6XacG5|P7X_=LCiNsN7gXFpoEq3oA+5^PGlg9O zl*|CclDH`j7I4v^qeT*nDViol&Tgf2T_!ZmX_?Xqt}PSVDGU!SJJB_~V#d#*1&5C4 zh;|;$XQNa}!>@qLurj*gY+J1zIL|+sWf*dzK?o6&4>TvuOS%NLdI`FZpigxb6@w(L~lUfUCr3=LW~8Z1#T;WH_;UL0Qld8z1fK4#UR7j#G%7wC(Hw81z7`P zM1?rGv+f?R_RW}T5y1Ekw}`r@OXx5uB92~4k>R|u{dzThKUDC!t zUdvDXP~%y9%+IPxM`-yJUAY&*kXrU5`tw;OkvgGfIE1W+uM7I|Q$S-Pl0{d(+8^n3 z9JGs=o5}^*zYOmhva#azR9O6+zqUaN=;(10Q=4G(3sZWE8Vk0Wm&Au)+0S*vz~CL4 zH8H!rOLb6W?Fbe~Doy*SVm*-#y=MdiI?o|iBXB*_v}1Ek1FmJyoYG>(uuZ`{o6O(% zG+#7buZo-wgiM?s58HQstgE?5u@uzFCGt;X z_N3_2S#K3_*c|FHZM%U}o4=LNz(d+OAE`##*V%`SCx973Z`M|w(p5)1;ZtcUo@+EF@4ZxQAMLs~l0u%+F!#`3W}7~kDn z@4kRg8^u~lu4grCYjV9N*K2aUCf93n{Q%@z=;%C8y*-oIXgO_uD>1yEA^VF8D$?z(BHikXNOyPYt!eg}X8&<$ z_8)@Se)i({JT?AygmaF^eYU2aYwEeCo@?s4rk)F^XFi0XdX3e#hMQW$O?~CDS!1=W z56}AW{FcKr8qy5lz-+g+)zjV9v!zD{z8$ZwFE3Qb`1#TaIlVsLX>C;!J(%{~Aqnp2 zEM*pC8s)(o4{4W2;>FD^O7H_mbA`mIQ_X1Vjz!IlZ$AI4ft9{j%zQrLkTis@G3*$J z$vvCV_0aJ=L#g*v%Agvkrg0vtdpA~KkgNn#t;<4;XfQ?-v^$=a*pNa za*}h}ezlqA?dS{Go^zZrt>1BRPl`9N+}HFSjnN#@@?oj4TJF<1~Gd3nIRizTPiamOQv?$7gUShpa zJer~8mVMaDoblKeIcS=uO+n&b5+_9l*T4v9{B)RN-Z1n}6nMhV00QMcQ<6;hNIk12 z7ucH%_&L2!CQDss`NZ^toMbl;8WW)gZ#ULp;0&2yR3-i|j{EVBuHFfzNiYUcB(gLR zl1Abvz>SQKA^`b$6Pqww<3!UC)l2n-h_+>17aNIdF>3;aklCIGDs1Yv)EnamR5plc z<@84MM|`btED?N(%9nWD!Bv;Z=g0z4C@fdc$0pU|b?d=QFnKeS<)YKVY22A7Q?4`kBB|;p%wt zqVu5dT^Lu0mMn#*|pR~gw~ za7Z+fjWU*#?ahKeKVdbEB|o_L}V$cgd{Jj_VqmF20lm9u1Q~y}H%$$B-={3DI-;RuwWuIhDjs zVptM{#->(F6YeZN$-6KW{_w+}T~=It{0H9W^IKitIV7V$FU8G~nOgK0Z_cD99|N zqXa`kBS;^{nxvo&O$5IeYA{V0pH5Rf%{Dy`n1KHRg7t=<6eP?yMZTv;^l(#cbaL7d z^y|gh%Qu_qvHA!9pf+C8_iU3Jn9vsDh#8XH+5a6n%7h)^(`J@WBMWm0E)S6iIX&pjF@od2Mbffgs!9E8)9=H zoyjN~meEC*Kivd9>hcPV9e6RF#DgFj3X;RefWN5!x6c1RiUe|XKXo1UsEf$nS)?dg z@6`29{UhvDsItkxt-V>qu~?nW1&SVO!~}*%2N&wf;BsZ9VwqKBA>)Ezm93&| zalEO?WfmS0Hw_h^*E1h%5O7BKhF`GjgT(-&efjp~k=ohYd(yzaPsL+{K0VtMXc8=_ zG^)yU0-~oa^|wbB5E*iqV5o>QNl@k>;4ExGnsa~>l4*=#&&h1Y;%+5b!Af6@o;obD zZbF+v?IS3wZ83$jyzs;1zVXLluW(6RSTj2-gCfvSn~3u=WdjfXT^z#ufGERkj^jPsC- z&eVaEj@?u2V^d4GtaHyMYLQJqvTmH)v=9F$P2Ugv13onwxh}~5Pus0kON%&AOpi$% z*qE8>L#P}9%W|oELk@h~I6J)D4xu@@$6P@qJk&YSZk6Ieo-> zFZ`$N1%Ef!1NinmX>E7a_U_hPN|CeUU3E=m9GVnJbe$t98=6ZEzX-GeEmC13mEDBy zN&0%T&6@zTY_G!`8nq1vM~R&k)B6tE7m&E?pf`+@C>bzOK8t%TwQu%NyD)|BKV=ZS zp0^|q$=2*-T|lm3YeIdF=o@~N12Tr9t~yOUi@eVFli}rXhTgnAJn(4nJ552T2etrm zK#jjsnFE-U@dy%#l~QTz9A9k8zHTY|N{^x6EnL4bZ}!DtQ3y~;CL;-jOXnvI6w2MsN*WHR%!}+J0HF>^Xk_TTB8+^X( znA`_q=pM_aux#E}EL#-;&0D*VY-E~do-SkLy%C19OJ_-?J>v+g|sVN|6)$R!=evex08mtD&i^be&M63t%Le}XC_}5E2pfO@MV3fXGAvk zUu$l{+jVLHMrtit@p8i&&wOb*1`bT5yFoQ;P1uQ zo|2=4Zp{%b;t;qie8}ZJMh(Y8ggjs%nUtf$*sGozyd}|Ha{X}{7~)cl%x~Qg*lpRO z7-N>GX5Cm|ZE!)CO+K@@BiO9rgO<`H>exKTA_(GQo`XWMXf8 z;&+C${C2J3s;zsaltdeYrFEWb&;2TnMesz13@IEM1{ZdYI%ka%fPq9jEU)aF&Ozsb zTlIdvyt-1dluTu4*mhI#TMs%%XJ^db0-lG2{FB(=)odIboopgcqKADaDPIhj^@>B; z36Txurz8vdV*SbRp#9N4xVHr7$4*jSzz zpz8yA-vb)-o^C&XzRSt`w$%3ai#e^=+^IS{IZ|9{QQ*L`qv$HJGMMgawQ+QI)!=|U zFAWC3KDSGEba}ODitVV4*%=oR)L0xE8Qg@BM`%}ju9Kz0oYuzdYd2MMF%pt7 zkoK13479rO5}M@reZxbyn>*q}2F0~X;Ls(WV`nEPCu)25#h%gRIk0I~0MRZETsmuy z%_ifJ@%Na{Ff1gFA>tb!rTUgm^CRwrO_H+su=dCo9@&~ zrb!@N=DCKwi_^Gk&t`8|tRMFnag_I7Lv|R~$pFB6i)_q-5~|9#W4vN7H7`oydYibi zgFrnlvh*>VVITWR@3GZ&Kdwym~iZ=CJJsaoUxRsl(|x2M_E(kpYUBWmn}20|^O#@amuN(WIT@)yB$L%Jo7i@^YiS!jKWet-Mh=isn= z-|3z$u~{1DyCybkVzVYTYhv>?#3l~K4~g*vo~h?gX5j=XuD4?LpekaxsQBL4Rs=XZ zd;R^8T-ZgTEmv;niucM@hdtszD@TN@=Tp5u`1%*2VL9tG_^<>3tw7z7dG%}{E z3=^CUg+ca8ev_7b^{i%Uc!FVXFVsmg5$ei0Au9q=E#kJS4)Q84Ee6KAHkmG)rX;YM zombpnp6#z|*iEnXdtv#`iO#z2*;sIHh-t$^wT6heCcf4!8*b&FNKCh;=<03YG#YY` zaGkS??>(;|K)0zQmq6HuizUsT!AU{}`kJb7rKAUtn9GFLRPFn{aa;GsWxV`FG1BU7 z5RW);f23O}K7SkUa5tsvgS0+K>w|QUgT(1qwpveGJ6l_OTf19(YWw-~*7LbkQnU7e zYpNGw>z<6Ut;+;Ab3s91!|u!+jRy(6|MU(b_=l2vjT)tQgvR ztCKQ?X`(tO=VylpYX4)Hwx^o5PVz0>{XSBE1PB#526vvd_GTP&e!}n%Sbcj`>IBb; z?OL!*3;i)Gv0Nta;7n~=f?>Pr$a*SmYQ8CB4abg3a_Gjmy z=2QwvgCu;8CJ@jdV|}Vf=NY$afeao?F!U-%AWY1+oD$m2DNLAK$QSbbS?kHnLH>!A z`&(OEj!>_f1J`7ua-G#sH84xAO;2!5s(E)Ds>c=EQdR{Y0|1cL@>ufLN+w!-sHCI5 z@643$7wh?%nV(58FthWt1!$M&d%LZ@?fJv7oIbUF-v z2}6N~z09EuLB2OZpsar~vn%!qTg^t8m?c;-Pj8d1dX*6WqV|XQ(>}R8ylB1(fMNtZ z#@6x4|ENvqr7j|$Q=ms<;9K>^h2UG=Z#FCQxchuPk6*tlnZ$o~Z&vAinP#`9QWfRj zEwaKF;(dV2kY{D~QVi;ES98gAQF-|PXYX2<+cvWFe>_G1TYEwxqApgFQf*P9C|R~> zaYV(+$PG10!6fF-EC-JIMu?P}qbf3PQ`*(l~ldeN$ za7yfkv92H&geDw-KFoBglVT#3enn-aXDkve%^L(<+beU{Y?Cxy8Qs$>^@XZmNY&ZM z3wOmH$h&nvNy*bz{d9X+;l~&mZs;~G@(Pl z8A@^f^F=MgQYF&`xiJXaB$ArW_Dm==ET#9ST~b24NF2?4*{1)uWr3Kwmzn!(&YbTL z_r<;o&_qT~tj!(X*Eu~s`Akt-u4QjiQgxX+v|NL{_}U|bPjQs{K{oo_09TD#2$YLF z6?Ld=M9q2Vag;~rwAl~6g-qAyTyl>K$pDQO#&nFZGOfSuYss zhca(d{Dh4ZsZkq*j%v3=q1!^YJiSeF#V!;YCzClcrEO!jM+b}mBz&X)GpA##j zgWzbSui?*_sP8=b1Zxt1SHVmrNih_+#Cq?EJ03;q8u#4m@A$z7{%X4fby_ZVeXqbh zVP&0o7C#}VpS^1}_aUdR8^^P8cD^_8q@o+&1!)qibfk;C{%|R0)RR$jy~=%qaa!*H zW_y?=VZqpfbzwyb8(L;3K10ns7x(jb+FNp8OJUEa`cLAd2tvO~yx$GQ3~&E~2{cO5 z&n(Ig47Sf-lxVOr=*^4rOV`$)g<#KERdup`%~cgAakI7w|7entf^3%9o2NYCm}9)V z>lZo%qFNv2v#Sn|O8cnQalZOcCrAvi`^o)r^I*?$_p`>v?f!w|ng>xisvlNYd;g;M zpEE8)4m9!yFI5^ReaJSSi2uo8>rD1fHri(#XSFeZZ65iDlS)1Wce_m`r5^&U?eNKX zo{AmD$k6cdvM078r*n%MmYvROcr>(x-sNAyO)Xa3#$PNFyGk5hhPqoX2fJDZW?=6v zg{sUmN&GLntasKe>-Tg= zAyXSG@*EMNogbI1a_srwW|X#R|n|INvQo*=dg?qp1)_ z_p|mSF6NWpf)F-+`p-y?r`MMb?oa|(CB(z{l!Q0Iy}1d>$56jMee+n3ThBg1Za#F+ zzVPG#De#!_CV%Cf6nc+~7P4=|9*ypYmEqxc(G;i6lOogU8<}B!zV-&{@?Vxsn#UBr z5JzS3tV%Ci7n;$L#coyVL2yTlZzCIhn}icCH#VBGYaUm?==VljN}=H>%32DRWPg9% zBrI7%FM~WMl49R=W0C<%y7TwcS{2%fSTjn&&hsGRa6c7BR|zGR+{Wjs6X4&#L$%3q z(hm7e^rCIU>3HZiI7kyleT#1dQHat;ogiL`C02nVi1}^HE|S7WrQK<>)kH!QN_?#-v+uki0JUqgy;xV%^U}0tq`}EF zznA#e^6X}wG{Lhw_4Eu~zZ2Y6p>-qTQoYt-V;GbhB5yE>ZQiXB1W@E6L%nC6P{C#4 z7BV;065+h1+d}#V(dd3sRtsPAGQkzcHZ4n2s10eebZ(*=cQBgCHeeV46us>!lmki= zh9qP$@6vg`w_1-XPpGH5totgOCR0~S#=}KD+}TEX;XM_@0Lkb8Ito?Wn~LQnsZXo7 z=jD&VWG3mj5JwaG4x(~JL083i=s>>;gFBDzN$|JrkGQtZ@d_?w>ZlA zLwh_9DpkSHF{Y2M_=r?c55@5&cXw@|egu`$-B-knA`f7_5#N*W^-9Un>x8B}7bl6F z#;C}b4*63%rH;|)Xq}c#o+LwYhLcLhQ*Vk!hhufwR#K@;YasM8H-B)8Z2OtFa*Ub( z!&PwN=hr5t}Ft2DuqSYE#MfY~Jy#9kZ;O(Qr6OzUhTY zEbTjKg`rPG<{@X7X$5ay_FotLd_}(mNM55OyzgZrFMO>=JWuXv?G~ZKiD1<4Q5q=p zB0%rtX)($(c&H$?$D&eoLzmo8jLEVHCzG^h@?ey?LQ_izZZll~8icHRY?yf}!E0C{ z94>N5ItB*FnSumGoS^|*8X1bgui32_ewGC`;u=Te;8bdj%pvL!4i(vB%$ert=LhuNY_^GlT6LBHaBJ;u^%0|QGf9QQle=j&&574Z72t>r`s! zwW?r)`=2Jj1s$2RobSTqj;}w$Bre`3uq((|4HRLXqLYLng7P`&lTIaEwew=;d2z6{ zys$RowBMVtVn#txk2q5(IWg4m{ zT-zN-1xZ79zye~^AGJ~5ikiU;jeq(((ggye15&L36jZN|KWaXiK1x4Sxfazj@)J)iKpQVjTz&PhfTBxe@YO@7)j z(QvShG!AYh+M`BSz!|A4oBE)viJTCmunQdhli)<~n~Srv1}6hGME?W+Ii>49;0-#b z>SgB_XRf$~pja71gY(gWpTME=dOg)7y{d#(;}o=M>mk45AG$3Th3U)>9%-N?rg<1J z;Irm3ZYV=Bt#rQt=oIaK&-Yc<@;AIp1KiveR`-vTQuO(WC2c*6%nR5Fi z2*4&VTD2ENx)@;932Oy)9p$bCE#=**r6%7H0dJ=yE0L&^{uelZnBg^k0FaJhksJKr zWwe*Eyf*=YrJr^a{UK zAdm#VQYe8*X=GD->YY*0dO#tx;RGJT-NY151bTn zcaGt33ewz`Ma#v#S4(s@iZE@9chZZSeXj`7xfwi{uh2_xrob&uuLj(JT^3h^fx-gy zvpLPc<=|KmzpFaRkmp|P@HS@|iQau@dQvVC4jDAEk69$tZ4xl@i2m7&8cu{y50Pp= z$hQFjh=@*zgKO=G{R8)4XMMC525d_H5P^Fi&iU2v=e>u*l5jW+T-Kg2gHu)J zY>iA3YiRtAiH&C+I4en^?HQ@0*&Qjj4oQ5Uj{!R;VJM{+7YkBMCw$RX7 zWeB*xHWcZFfKL*zjKo~O0=KH#_a(&CrSpC(YCatuqS10pw~SY!iY4;L%*K2~Oz{BX z9ch&N?!l5%u2*DoUIMC}D))eq^30E_REa9aQ8f=M!YFSRAR*I)4jviJr(PChoNpdX zrp~_#4_+1%1OaoSF|R96Tu={=V6&>Ny#ZfMmN>jEwA#nm%hF4QQJ;V~q-!E7=}n*g z#3MhdvsX`u69Jc!olFQ}?05KAniuf_KT!y42E*X7bSA0)j>{fWa>bkPGwtoEa zkVe72Gj?{d)sI)MR7~Q|%iv=SB8V>fJEp}w%yA&De+N)+AHGJVP;2{aB{iJJd=~(? z!^ZHbvMxCsm~d8L@?dDL%$qjuYMk%d!=N*qUO4Ph#4sxhrHs`Y025sbSgBM*LAODr zX44{wWinSjzkFI?ha#xWslGtu1;d$xOcR(ON#9I#Vlu7LhA3jT3-DaifqH!0X*eH~ zbQln|Z+n{cY6t=a+ntOMkBf9(o;4aU>XB?jMdZ?#5~Y$yaI!036+9R-@jjGM#Mgb4 zU?*MT9-%a|Kxr{DPG}^@QQ#F1I*uY@iIJIqd-s`V>^XJoP&kLYq7m*Ziy*N#j8pNXAuR#>a)Xwck>`_F2 z$??Dc=Ps4{M$*=3i}e5fzadHl(SqM{3T^1&%S8TlCo-FBVACDo(Z1RFad*cHiJyr# z2P^805d&{<5?z$&ucy|i*9%5zf-37(-*XjjPe+*O(njj-8cx>WFL7b3B_Fa=_wUlv zoK6=e)E3G{=-iW<)?u=jY@b}GV+&1S{@BX~Bcf&O%G6ki(b!aeEiV8d+3^A?j%JHT znYQ0QpT7ngMx5O17S-O`}5#L3mOVAd#+kt5qZw8>+AT=*KjXR6Xhm$D%0t7)Z~?Q+6yI|2pWMg9 zDEtzs-Ilr$Oay#VOGukzHpyAO7t!oJ#(_5zM?i{gM}<#kbnZ&LIWJEKlC0=XTC7JS zAINVH?R&b)syEQt@{w49EJDtzrR(-ENGeMWZi$%aPhxk*nYW+ZTz}>adE3^zVm9+c zKM7_@2&*n`#aHgU{Ho2Ld0W-8@I{yYBSD>dE7MsLi6gpj@6|<{UI8}|5uO*EIk3br z@>6Dz;E!mINw#kLu{TP}E?t9x(fs>F+#}|)av|G884?pF+E#8QVwu{(*dgpM-0ko*~GT9shaTjUkeYU%((UL4&smi%5j%M0M{W$t~DRT82V zM*OWS&Qp)N>Ep6Z>tRBdTdS$%4%5biC$`zQk_7a!IbJr$vp2^>6hclp5W9OTLDg1A zu);sxZP-c>2hCr4m(?slT$*A&Avot_|o2;2LPf&YPKr{pCtoy~W_~mxlh&Pa~@-bquuaX31+~sHF8vciI>|9T8VOWlSlGYG^mJY}|>t z<9=Qkp9N#4U3^8VK3{b%|@;NPCW z2ujUlR-O-U1Pa#FsSD-)1L?c!-Zk`CzV-B z9B+|k)#M|c8r5}4*(WU@tdak=gZM7sw3TL%(Q@&tB8ViO5sUs<24m=R`U_Wo(axJm zj36f~NAx{NjGZFQNeSA1V$GEP_%fy6$dtZ$*{k2^#J=p+Z)Zwn67L=YgXaeZa9Y}> z$FX>ObJJI$PjYyA{BbF(U(YR?(GKh7`)kMz3*)x#lu5)c#&agUynyoZllYr>8%(B6 zF5X&6HKzGoZdyYE;rUnnpKluCyi5PQ?H->t1kIfL+Hw8{Tj`T+aUN=xR|+g7+Hzbi z=Y;lSTGs}FNP1ZiF3>g_`5wq;=#;+L5pzVnW$+JUk?LA$8ScM6>+HU19clzr4xS4p z=m3n%c$rq|UX?N2_@zlbZ=e^Ef6%18k@3L#Y4TuW>8g)#>))?!nIAmYh=H1lyE})h zpr$gLQ$J-%jYvZO4zdVORdv|1h>Coe!)?sDjifHBl%|vi+Xc`<#gv+ig-ihhXK|D` z6&9~o-WH4kc7+FOa_a9Gb5T{M zsU*>OTzKEaTAcSyBIdXVYgLR4LCX9qGsIl7N8XpN z7)TY42vm@HnO?+@6ZSSv&E;SypH?ukeXEs&HUk1l)O8$;roniOcN|3l0Dsa_x(Q)=KHi(vxEnt3SxRf6^1L@K>*klOT`0`D@tOQAA-S&=%pG zUMh_vzHCc%!BjvgGp(QtDAL3FJ(SLvBfGUPUq5BQh57D{H4fDS&R?p^Vf<+*b~!+l z=BBl~G%X)Ug+OfTOb(NW|6}jkmfOgY?0bC$qW59t2(lzfvSn{5HYiKByXnsW{B5*&o~hX#LlxB3fB zL&Qr#TJcu{{?sxIU$}d?1ko=8{@b4<asEWupP-Uz(48UT8okW%*d`XY~2!DL%I(bEbn&m+A`-Acup7(T&s4 zP*n&Z`*k5C|3F=Cb!dO$YrxB#>#OLn?!{G#8PwAl*>qt)FUyf1 zjGtr&#We)+T8#g^7}Ekh*z$J)1K4}%zusEjZHj7b+Sh@puUN;TSjs zSjH!MD*kXf%FO7kefzf&s)WPNiP4!m~rM?{5R@&9t^Qx``c=7 z+uyl|M~)Wr0XqZ_T0w#-QURunAX-@DOVoE)Ze#5gNtTwmUaIo^^6-fEK|M7L$Q)6z zLmhw>fcXGkNEimg0+T@VHr)=u0aQp<$(VgNc+O+40Sj)DOO1eY2_^n_j41s!Pw5Po zW0KzRl*DC-qROMO0^aSd1-v=|ms8!dvh4x)qrFytI6JVM5ZLW-scGeAze$Oilt3TI zkdH`)C3VAs)gX=V6B1zD>)0#RDA%k4Nx8p{JMMrgKz<(Cc^hPPS^RK&c%U6KB+E>! zyp3Qs@8_ckO5jQ6)OB&qdTmdu-rk=7W|{q20AJw&ZCV3(Yza+}FMsbZ?Re75+*q1c zx%hxpXc7)Mw%H>n{ZJAPC)CheO-9d>^*$`z=M|8|rGu}*t^;=lLe)vON9UJSqWZ%RyIeG_@lsVr&4L6Zf*XEim8 zjDT=Uo`~q(R6y$4CC#9Q#n?f7SR594EGlvnhj$Q?4;-E|%a4=5HGjLke z_s-L#i!?Tqv3Aw16dYTsO^mJ!Z(J0!|JvM~&*wgOU`Wa+%^pf`d7r`Kev-yhwIAYh zpC627x8uz((wU*dXEEywUYTD8`Jj#+{|ha0oaRpunn897v;lp%UEl2h_oY+;2@0Vx zg__*Y<%83OPg?uo4NpAqEWBB!)Oi1ew_L^*<4ZiARkag|rXI=&&`Ya8D^JPh$t~@? z_6p8J4G!U~y6)?c&J_I5ii(N(*%F=b*dv5LD#|KS2g&t?klnacCwl`RDRnB>3##j9>Td&3SLE7g_l8?twpr#2Clk=_#U?<7 zL27gVtoqNRp#x#Hj3JC`!wsnDB7lCg@Qf^|p&22w-Ingu3k7J{3JB0|WX{(ke5I0@5JnqtO=M>hCBz z@NO>~1EZ08OWSIZfhF%2_7*+dW<3mr3d}le1U}_RGII5^!w-k;HGSt_Y(4+W4so5Z77a2#-oy9daD zX5Oa?^ymX~^qi*YEN`r!C~mJH#QDg9z2@H(Fb5zFwGfo9Nvvs^dxsZ4)OcdmLnv?Q zWH`}@UfYTgw6F1+xKcT;v9x6Y&1`g&aK4~n=j^K*Ny`2*uuD=-2l%B%fmyh_w7eA3 zoOWII0e}?-W3SzC+Vh6d5XewMK1v1-Z}GIHTN%i1FLxDA5R5eeZj-!q`#NxU8p6rL z`*9T|mN(5F0P_Pb77|q(2Ql=25?UAF zPOIp6a5l{a^O$iW#eQ-YM$t4^B1_Gi$w;sel`XC0wNe@2wSIp1Ry9WeH@SmV~-*Udjg$9ObQX*2VR#(jiv z7S!N$GusqznCYt6u# zVqd6T>aLR(cHKuknUTksjI46oNCZujVi1gpqXeD5PA4E8!L0ITl~{7S8_5pKdjinP zY}eRYNPvPz%SD3nk#kcuO?I3qz}g)8p6oOhMwoF3Xt89BSW(y{=nmcS6TXUOx_i1e+%Yz1q`?60(8lLc99Ja8w%%JH zuJ^&KGy%h9xSPP@HaEtz-WvAH-SP5)WHDiT9iispuBQAhB>jkbS<8Dx@-BKTiOeh8mq1-SX(!#%>{D8>X)*n75e51RUJ23Q?_-}tohG%4llDW%jS|vewx$Z z(i(Ae;AL)?U~DyMg%EgFRAJs+)3F(`XnZ`S`Nv>`bzOX;W?`Mbn+18${qBLu_bJw) z`WR)17fL5l=0dCf+l5_GBXae<0dMbUtO2;BzxIbE9gk_7qiL^KGeH}wfT!usdYZ1M z>F;cs=D{{i&|dE@a>m}I54i89_mX#gwZy5-k%-cf8v4JxdT*Tx9w zIA8)!N`l!3Xa+JsZQmPKITq8!$HUA2==D5!6WT$%whtA2HI=Acv}frz;Ki%=5gEwo z4Z9Go#%#e3qHNfyP%NY3;Wxij6(}XUA);w+c`lZN%?#&mR~`+P^DxC6PGRaVHPx25);Md8 zv(`9kjq@98oIKw8`OVL-IX?3BSiSVOmvXr-u~v<`w7G{EDrTqP<zx-5c1Uepozg7ry?{bxA`WZ2a%&Lll#IaCQY%4w zx!JhS6qn!7cj&m5{VL?9_mtPxOnil#d=DlB?qohtzFoiu6ui}jd3qs$-x&>o^2hBftjYoYXa)hW4}E+%9>P`BmD$iNS>x5(h}6w~K-o;8fGxWH^H4 zjsod0rM=5A*WLbrzTGbK12wEFQpVx!5+`Xqq8~q-ChsBE9_`QrG-u(`nz%r}cD7@V7PLEHURlHq{` zIX4;L5?LIyebKS0Q)LHK4fJgKsDSg`+YRc$#LNo8VGLt)!v{#-c5<&lG+)=?&eVL4 zMOKn7bVt>2sk{(_A}13-(@sO@dODlyd_s*+(t`Vt3@h^It5o{of)y={V25*=1Thi} z!C=Y}XL%*EhtlGKNv_`N67yN(i$B1Z{*bgnU_pjfFd4gOOO$kxOT}ZpZKvnXw*O`+ zjP0E(qqc9&!3%WhLm~+dcK)?=oOIb@DYUhegtAt%wn!U8#XBhGCFiF!T0pWpxKF;# z#r8N-gc$ta)vaiu&;(n%EA$-MV^S=S!R z&(9<2b9y%&M35Uk8>fkJK?lP$`On(zidxQ2eMDZ#fJm3T`et%PLvy5)hzy)#IvAA$ zwLcv3hn0DsnuC(2qu6wvR;^dTlBPN4a_Z2Pd!AuhYQ^dV{%%<6jBJ_O>DF zKq1~YWBJt2bd>9<76gD5%713=m-)rJXOc7G)y4)SaTQ()TC+NNpW#lN>?9LMIh(fh zt)G*+3s*e9qikB4cQ2P!&WG&m@R=msQZ;ZLa9b*%cy}LinI>{_&S9>9+IQ1tf4Ou4 z_wneRy7+MROoN5DlaxUMK1kCQZozaOo8$WL!~km>u$B4Pe(aaP==a5RrS4HZHTcM* z+KRSs#>3Ir#Qj0G$|W^TNj7$*ZgVx#k69Y)XBw&M^;lm^JGsek@8#;6w*5~7bE7tl zKk~iL`dg-c+}Vg;bkylyNB#I}XO(M=gJFk9&qONWPfcE=7O^YHb1nxJK zFE#Yf{~V^XYL?J}k-e96)B?QWDHGJK6syj2dSlXZBPk(A? z3s|j6!RKi#qJKmBf0@);cERTnvwgWNmOrp|ktpZ;e8^W-Hbvu^-_|dD_ZD6Hd&fN&zpix@4`dWL-k7r0CA|q5(FhA=AXGEL&UDx6lGr;3a* zW#U{A?hr5Pam-}95`a1%w3!Bfvf&Fl&k^NfK{+x(G=#?YBAjwlY4sSK1spozt0Ni{ zJwP<@LQ+#5s~<|{Kma835y`gbsCO&4w}A>1j16rknDrd6(um-s<|Yetje6y=qoRI| z4hw{Av_uEFGC&A*V+za|x6H+H1y&X>~iwIrNzN7LmR4z(P8YXtrwgHU+QDH8=4CO_<{}9)hM!?bCwj z2aDO*WV14vU%vLE z=qqhcwX^WJTu_k=$Q=8lF@NZXvChXh5>}eI&y?7^fj7}OO+Gbz)v;82s01TG}g(MX-r>6PhW)sLD9gwny& zz(e5nOOsu->u<}JvFu0T-_==-U{nQp91O^$)|{Ycr?xFDaf$$R=~gy)#h=-z>Cze; zjfy&+m=5io1zbc9!^&8^8Nh8Z>Y`;#tg%>gsKvjPOmvBRN1TXUJ4EM5?7zFNL8P38 z#%h9#M>&UqJa{TCNVSvs^)WNWx2Ft31lpW8$f()&chvT>Ub%?kwCJ8|$1D((yPq2c& z>hUn|%b%y7h??!VU!>Gm7FH{n|3orIITY^E9Q|SA!Ldzvl`JM{!86N%#?q`{ph{=48Jy?|JzyD7xJta=OMJHMH0K24MTqNIx=%A(8@zOB5_UB zd737Jl1|fU=pDy&nC1~ZOh+AcdV0tK&K8%0WCv$WZs{QSMQ96N;v-QxFOVnfIsYWy zn^i4tanuXFy~Sg!-BT){8I&Pa)`-tS<1C!;ph`9rwI>~FI9>$Mb{Q=d6FJRhNTCu3 zDNBHf>R}6U-{xbg@|xW-RU&wl=OrJKhfyBDqs2K?4nV|fy~5lG0R=6dA{g5xFe?j{ zmcX){Bb^AD&^X!C>AK7kuBvrS0o>TUsFt7ba!CF(YOsmP4$dyOBgy8RCu5mcP<2Qi z@1U4qzi9=_7op>&G@3;0g!k^6PPS3#&D?~sIG$tn4I4VkMR4g1OK{CE3^JqyjRmjo zVkALoQHj&D3`d-`)lp-bS)BCUQS21NSaI&yeRUuXvM6ecp8|d~=ONY=Gn=GjyN^6}KvsD)oygbfY1*NJ zwzHfVLphcwr_?Fy&l2DmhlhB5o0NACjzARMfZ1tC1h`~Oa^c2W(@V#?OT}G>CnKZF5AA8&bM(m8Y}Bv*g39tFKVQxwJBjkExdhm{6?fN zgD-i22Z-R#A$sxNuokwtzVGe__#PwvhNz!aezI3($&XOroF^Jag??TlA3vh=o@rfz;z9khdg( zR9ynKKPiH|2St$jT_VVCy00so0bkl6b4EoU$94_q*hjx+kYhB|gu{skvrRC0+eYNoBjz@f=At*OgQK zp2S)qtJIRLnnQdRQDDw~jF@sH*gA>jl^`vM=zO%u@~p^G4~VRL@=7hstG^j>0BH8QA?L4Sk{+S~fwrqFf1*GQp83N=!wkwT3WYNXHxQmBYBEy45KoTE~gKSxo> zDG6m{JFTHBJaWKA*hTbk8xjD_dyffd*Qh^+F!4;Mx8e^6K1Xp^0dNQt!C~wfaBfuG z<=K@5a~UFJ8AT)CNl`}*y2rwZO_5rGL`U>JG83>h1!*!vYNug$4sNj#B`0x2^9y+r zs2+Fj*w<5Ht0yPDH$T2Ue#!++Rt1+z&+7G_)PPCE>!~7y=Z<_0A6)1-27Ja6Gxd{9SCgb4h{I5C7UvoxCJ<)qBr=#}} zm;Kcj-B(>8T(Kgd0pM6-^*TAbI6qX#$hbs(M3g93bJ4+@Df(AVQ3`>*(*gL^Jp;)N zOFq9e@+zat6EZ%+U=#`h^eNc{V<#9{+N^EvSd?hOExk!!?e=c*tfWz|Y}CXxN`vNE zOg4}^wSZt(xs?^zb_EQ2Z~#C+zrTLjR+qikZSNOYeV>TkIRoz#*+s8ctiJQTbD{D5R?<`%AUb$R}x^ zw$ugxTmNzH_dmAOYaL}~4D#*-`HQNRg?gl0>P_pACR~0$q~(xgAJv=4GzUkXVK`h+5=#esvm<(k;$YYn778^4y6J?h zz;uDRBu>yWJFon$m*C*mdommP*{nr`(S=$50LGiq0J8BNT}Q$xYLgh{cQA>7otKm| zbVTM4C;3ePPQ%-WhB4SWj5I!AV&;~bHwld_S1tNC$+w?vx76j}y3m&RI)3j1-r+Kg z>=Uo_EnR5QGB_(1M6n$Dxga=`!ApZbjFQnvUi<^i$T2N;($DwbhtqC^t$9WZ$WhDb z&FVB-003*`(>-Lp4Dr>;l??o;I!(j;qwPa)5s=KFX)E8-(~Bvs?~2oVsNct6D)bGs z>Ec7;z@`C#{+*xF-aSrW$M4gAJLt}k7h$5<4aw^V?(14QlCcB%?Fv2u-W_VzsN?;X^EjY&&;$JlGLG% zXR?Z~xM6u-9TWK?ne{`5H!gg*mTpi+K`zj$NruE?CRr8WBI>dOvIoQw{JpzKSgbiY zs=)W2B8T>+zcAULv>^~ZZWeZ}-z@0sQAeE-#mw3}iJ~w;RzN?*Wb(Ief9!XPKu5q* z`wvTUTF(kg8v*`5=}~SrQz6^5lhtd6da38+W;d7|KzE( zYa>P*G1`dHMvOLMv=O6@R0FW)N`sYtD;Up(%hMalHxsMU9OYSGbdKsxk*&KT=PXN4 zJif0V2L2Ab84q>xIwziV3v?d1APhSXW#K!OLuvcPdO|DpGM_G#L))uN;0khuK~hR^ zK2S(<2yqNo6>H=I9HtN{{O+chN?SsYd%cTq-d^gVUrzHh6W-T@iFFAuiK%07PH z#vU~vhS|8Sc8^bbtU!1NCp~1w+fpM+-x)7Tf1!p&$}SmOV5805GUo^;2AXKOmHAo3 zcyzsk-i7V#+B%TDBwqO`DF;M1yC(eMFpR^yO%vfi1ffs6F`u!d+nk&FOugtl-&vaJ zW4?`4A3qb8%t&=$cN0HJ8dX+A`Gdd<&Xj+4Gb_n)eC4cAwt^`#i@@>SV|;ORoRv z)$xfT(;=E*r(Y~*CsV~u;}8~4mB-yUdz_x(!UmoX_iQAu>6mL-8`WpgvtA;i~;((Iu7%KPK^}r(4d1 zmdR3&pHVnjfbzxA9&yP>m%*GAzaoYFe2`SdoS&>VK%`}9F z*$?Ak(oO9h1A7B)%bjAf(G2APcEZ};d9jQa0U}-*=&lQ!+;#-V^ig>PZ|BIAp1fD4 z+p&CEayn5LD-SnKu2m9cMus9vB_6fa-82#t+nil^7FBT_KzT~KBxzEEu{!9%Po2*F z#byLEi+2^-uIqq7uS%#y;0|(*SMChEZ9&v*+Mxwet8fh<)33QanOE~k{DT!EQd&z0 zt)=(=gU?~O__le_yI*S0^-I)(Vwm)2Kb~9E&@^j%RtLmR!w3y%funC&&B71s0uBCU zld%;fgK9!{?@dU}P2>1}?(tr|&NxPAbgRsTC%VpS0a#MMtylC;6q#DHdfj@cnPse* z*`tx3St}B%+|HCJ8eDVSS9w8XwKX(tcfK%{KjgdiD5}{mekbj+4{JAzJ=MFuu*G95 zT2!Rka|mRx?}(@@W&{?6D-eRa1hhBi22HdF&`!M)C(E*wI221-O5jjs(m2n5aZ+tf z7d3+2U(9>za=|^6{u)9Z*g-is#pXUa*`}Ya^JSL$(u12NSw153<5MHNlKaqo8CJy( z)irmh&I2;u?El7q>Hk0iUCaOGp5=iq{a}L#5D#dyd-$q(`PXB4jl}epVmxWsg#4)3c6Omc#I1bM(aw?paXfpS9UAg?ONHMLFkCqUa^lYY0g$f* zM3QEa!*pYHFym;^t0X8ly+=K~8n4s<(ZZh*ebj1yN&>Z$bxFH}nzETg<2rw*`=plc zt>pAZg;+zjWwWE9-KS~yp$G>Pj{4v3JR^$jcAl>V#eu)%UU1StyYH`0OmP-ShuR3ms!@0#GH^Ax-`2m=~29MFJH~w`9lzs4{ZHZ4sp^TlqW$wZapJ1Dk)A-&R z;C)&5K_P{w776*G&?&=l-)Jf5=pA#Vky*W3ym~?}f9gaxg8T3-qpd)^@S%lMCOLCH?O6Gdd1|fV|-`gh0u>(0@mG9f;?3%dmn0q`nn5YzPBaYH&bW zyixZO6FJQ80HPp2{lvccsp=Q&chVU3O=2C$VL&&KFG3y@&kzq0&h$=)<4o<(@lQ7# zYQE^KE8HQ-Dohzxkgr`n-)hdXTF5owe!Ez z%>VzR`L{~Kiq-G#m0W$s_~1{=Q@g4yw{#R=C;^Ibv{ZTMYB_NDeS!jBs5QiyoYI!b zx&C~H!riEotg;!J{v7@yrqYrinkL0)>ieEW|Gt}BxyR(ArfMt z21?>doCLb`+;|dBDIpqWxB;Jul}pEFG{E&m0wQDIx-nch+~amlSm)AAxCbN6viU=o z4G|qNpU=&<`Mk43ytKFM1$xU>$mG_gBjLAW2?^kz?EV>M<wN z(6=HMbM?AnP{p6De;XNKwv43|f+TV${r4mQ49>v8)j1z-+v?ALD)VU5*8;9|2I*Pz zAkg2CkvaGaO~1jdSTYU3EY27MTLRPZb>XnY0sO_7EI}oHC|oL#K-(lI_A_V*r|P*% z9GQOg^C?0SY>AB%ml6JAZq>Ttc*Y4TC!I@ z)Xg@3KD+txu&sXa`$>|w`4GCIFnzt4sn`uIC7EqzyDCT|z!o%Eso~ zno*|R&24YH+1#4Vt=Zg~&FxRSxy=T&;6@pgwrwC1?k+`7*u&d%Yhr+Z&w4%LYSpt? zdf@IiuaDHt)sefum6of0R(wMAbOpmV)qu|mv#Hw%PbbQA_f5o!V>}pmw6Y|26-b)7 z-Fbc5TU(eCsg3VC>L?iwiTuuaG1!;yVK-T?hzrS+d= zwfY^K%uaTT%(5N&Pd(r1?Cz~UTDQQ9y`RqbG;Hm8kYkG`2KI~}e3A`(!GyczHSU>o zuIwqtx^x7o&eUbZw%6Chli5rUxForCPrTbbqNcR=oCyE-xjKOBT3~g?00#(E<(H;l#sTJxS4x|1XBWPLdqFcj0WQ43T}Mewf)QE1btRJa z-;~{FeX#Zss|fzYufOA|sF@G9hXh83tm-g`qlHT(1!m5=h`=Bz$@r3bFR~?*N-6kL zINC>Jd}_epS7p}E(Xo|>{x<`_9^75lS>DYULFLIB^_gDw#@xfcJIIcO{p?7m6 z2#zyeN(|mfBQ8@&Ir`_;mxu-F4{H(s&VBKMWFGTN@N*wXvO^z>5e;qcaH#9d{XI7Y z%*}05(KfrSwo#>eXZblg%d#VXU&nO2?_0bEVTYPdq;eoISQw%7OA5u^GefHkI2}^x5jf<@O7RVke)Q&4LOg z)};4E3kPnRdSbBXWI@@E8v>k0el}6daCdA20X*1!m0KaoYJn2n7Txp9>zF!puN-fM~3mE8`fPcPS%z&d;zK!Oxt!|P?Tc5kU z;Yi*fdFPi!l!wO4ZwW7Uq+vtnL?DLU$iuQ6SeIf6ksvo}Zw_;+bP|Z!XvvKs>N^vl zO;06#Olb8x4}IYUq;X`DYDKz_gQ^1p-j|=YYO(DbP8j}xRah!%W-V^-G>frWjLl;F z8jG>i@gJ6p?rGLKZQmi<=d4WjyR2Q8#>wVwv@R8`%at7Xx$Dw&%iCyODzh%VW?imb zm#c$XYavFw29fhSs4T*EmA~XwCZuB@E|P-wdD6_wD1fq*y;%&Kt*1C6Wp)?3^|Q{m zivH|=S6@so{WReB(pVzmNwx?+}OIJ`nF^b6DDvoFt{OY2R}iCf=FZ zY7-@69hgsBQrrLxA|U=nDtw~maS&~C4$*hB$#H+g12QOk-ln-xwq`BLZlL-G?1{_+LCPpS1lO%GtQautxC3mr zK=J3LL$s zaHiJ=>p zP~#GMv`c7)Zam-+V(>$k=jh#a&h%{WZP6Bc$Tb-2!Njob6V9%Y&n7WBeQN!iVdSTt zK>%BG75E70cB8Rc`^+@ za(b`$r~1?tY!{i%!5i6T)-hJOtjTT8Ny4T(ukGVw~*AjwjzReh_f{_3j_tFgWs>#MQ; z4UYAiU-`*p{SP>npPCOQ^H0>@{B*9rDW4&|j6I8uiKzJn3@&z)TPhLG^ogZJmm!ui z*8S$jZ|lu!yM79I(<$#G&{CNJcQ(GPR%l;8gJ@zHsX&k!iVHJjMGl6D2T}DgFKcc} zVkwNxVFatZ%>5toB3${d&xFpm`OAKaD$ZPbHOlF+J zBEX#(`y`gfy?m6(*y^f)UqeW%K2OZnD4lxg{FeD88V%5-gAR)MEl3{iJXDD%MJx?- zi~9cCw=HRzt@UYYA6&JK>cM~lbqPjv6+KA}_4e&EP-4Y#4PfZUU4`gwo@Y3V01=aO z_pOpLua!{rD#%i%5Uaz;BAZYKU|zy$)z>B`)h7<~Di#r%D1wThPE+B4RhP6tA{e5E zr4R&pZ=fElR3Al<9sQCkWB|5llLsvHV z*BdrB87fC#{}XgE48?)cZt*aNg2o9ted>9d63Lg+#W2@4pSyDIbqY8>KaI^_`WsHCfGs^}-8nr2v*bI~?z$uEde zC3A@0gDF~Ip~Yj5{uM@r4u=3iyN95=C8HmmjqUALV=u$hIqbjsk-wlZO(b8h*Atcc zgEe{$k(aJp7X15_;Qt!Ii)ApU!=FwV1)K{{OcI#I#a^-0km4k$KCd%DqP!s6_uLw>V~?vO15g zyTtpNm{w}uD^W84DMQHqV-fCT>Xob!*al^BHI0(%I-ycxE3<>iJ}l9grRQLx1x-W1 zW;JVw^}sSfZtvv0IA#H!;vO-7V67pfXljZ5XDLQGf42~eibNZ`Cr3wX z&h9nqk6(6g>_R6Not>c>y!R2#GV3D*pdQA*9J@11WNlyLofQo57>H=Jdgy z4k}R-pL=Rby;Bn|(7Mae*+08R#0tzw8xB6t@xyGDnFcup`snC@=Mo)I02W5hGI3>* z;hFW!ir*o+$2?6`Ko-OgjaciUsp3aS)qaq4NjQYC2B?6CoFmI7dV&J5-q0K1sh~k0 z=_dt!B!#E=0UyJ>w6U|pk+CtQ{gY={Fy(!)L|7r=GnhM^dO&M^eSLc54|E(zou}r| zDw3xxOdeX$X}-X7xW&v4l7Sq}Q*4*$IC=z2jozXbMgPYvTl2e;y1Sy(nWmAE-2yI5 zQg~rxHCx4c8JB< zvg~kz+Xl?*xV!C32sN3wh#7`&2*P__zi~*Ta|^9B;`X^3NXU4uvOd!S+fTynT&Tb> zpN@lr4j1KR>af~o0ruL4DY_EqOj)2tIw^*0vU!kTsxQARHA-QYr0Du*Q(=Y9v5JGp z=E4fyKAuh|%I$=dvl2PlvLXZnF~>jNFj$(QMmkM}UVGJ^L+$$W)jMpK+2;z0{Aa2j zq674Igd|wI+3gT!)xC*~5 zdbGxB#ad2;X+SA$V~scKYY`UIXCFZA%yfz?zja*5?$2a|x%lZC?6X5BF$MWzeK05# zW_!D8e(4;XI&Z#&UF%c_Rli4_U8fDpF#J8v&->*z4o~w!y^UF+Sa~yf(G_emI~mOo z+A-IXaT){PV9~*PTh$|~huc%_*h^$s0>}x;vGmYBJoI7h;aI~u2NzV1Co0qz$S@%X z@MLZ!4nl^71XV`o`1ASM;XHs3)kM;tG-O#7_IaL{td9&nXQEAd=q5qe)|iN)#We-% z6nzBxn(HPCEWb#|pqzRUvOfuL#hpB?doekn zAo7RKg{D|tg4qOcVdk#0s9#{7!O%JJ)uY0s5_njQs?|HXa1X#v@8XJ&=9 zKQJv!OawyLV?8GVUBO_-7KnewBc^2HFiL1nRqVq~I)p1;lCl zbhYn$HO$0P4FY{XrTl5;DJs}T z?Bf%}qRs?RK0Q$C93df5$sLa}9&1=N8*hq~V5~Pf>qd6}lD(Iv1mjR~-#dozK}JAO zHfL2|>!6XUEYo*gQqTy5gON6H@U>uInha2JWvVDK5(LD03C$AlQG%V4%253mv@eFr zG|!;joEr=>a@x0eA%P3-7%zB*8H8Ck(|Q=XzOtwisJC;e??U3-hTcGeKr+MV9tWPQ z3W>zg10r`%eW=SJMkEDBJbZn`=Im+Qz)6Q%$K2g=Qw*Y^c79bbl_LLF`yok(-mRah zUS5s;OBFZHqG8Lv%esq&%>k}1_3$R zF;Q#@Ts=(tQ5rtKbN;e&8&l;XvDnY2xZyUn4M>x89cY$1;baX<^lHc@Rh$3xEJi<7 zfG~N9EgiRa35AMPDj~F@Pum>2S&^okhsA^#E0*IH#NJuQ5pI!*x+Az$Ig@CLk~Y(V z&@|+*y;8 z>(1fj?)BA2d%l1E`Saoa)yetiwFY0=z1%N?OYwwo3>2Cf;a^Bf^Kf4HD4Qi+q+^L+HGU@>$ z6L-Zn;c-0-<{?!{UqKU=Z!rWEy zYqas-s&!wX%i4t7i$ChmArr2sqoxUjEqbyhp@ucnB_^OIC-x!YghQbDDkVWJNdZ&k zQmM8s*yENKVI@Fk6Rhp&2%xKyZGkc{VEyWRtG!yD?U&rTTzwIgwGQjRdkj}pMF{1J@C(^XkyB*MHk#!QSbL7Wrbt9`4D2bbWA#tSY&II9eTc=IP3 zXkbxx;cUn!(>RZ#7_3K4pu8}SBXr^TU_^R}3S!lDqvb3)ut$d>w-V^C+f!<*a^wbz zDSa~V8ir^~yk=dQ@_Qpl`NH z^+L`k^nBsXGW^*UEJ!?x?WTg7yc1^AnV7Z41gKi44~L+37>vld*j`_s2;0tJ=E>_X z(&ceu=7r;sKRpt~)OCKJqCi0ae9nYky;Lh#BAX;z%dC{V$GjT3QA# ziTV2GC1KJH`t}(|*>2}EER+J4o-t!MhZ=q|-#6j$fgTL1?A2+@nwzU;`I|LM z(0y*&47x9$Dd66J&NKm^{-W9Pn-#zy)S2Rx*4;2y7%{ay%+A>P&=3O%fuXC>rU6LORed$4MNYKfE} z8yjxx{j}Q(ZaLyxf-D+yo+?(Yk2~xkp z-C4=^HRK!hdYk3?vyI!jn==usIIgeY#?qX9L;l2{E)I`r2-^T$99d%De*gR;g#}ij z?ar0vebvefMu=3Y;~F8*&}ZdX)?1_@Y{s{vkdaNz_>s*=_Ny~!SMnlYDdmlD{AeB5 z_(lpbF1KChH2|!X&S}`|#YB;%5@fv1T+?5AFOgcHCi|IrV;^j4-zN?d?Bb$Vil2S|26tdZ<*RWI- zUqg`dd-6(z&xkM^`GhHOcV>-%E8LqP$Kgp@QHx(*>_0(*IR9R&hrPKvX~MZ=(ab{7 zs)W*17Pm&ZPuMBa`jaqr`*7@w!~z{MKE=8hTz@|KrBUPi zWrianH<*Q%QG5?Ubz$C+c%B6-)3MG1RR2`|81;uCtRT?k;F>pqyFjqJLVh&oJdVZ+ z?$P+y3w+-t*2QGxb~7Pg!^SeujA@FX_jXPPUauELRe{Gi6mMMTMiqS=CGgVm*n`i5 z)~+^H&td&dlyjaBh|j*Q>D&v#F2dr=!Y(x-yZ3ZBfT7^Dvo0NZAORRLx>=a2$UWVK z!2*Ip&X55X+U@bF$0-Zl0Hm*so8P;IS+@6-Myu^ZKTHF?S6yh;h30pmA`M4SB<=iz z(b)Pho$t@;)K}=2xUdlw5_}{0`7>DU{k;s7jK@hf)%p+O88)G>OWsWh)By>k6WezC z2edBVGmc+in$rP|ycZ{YPx}XJ&e_E#lcxxtUlK_ZahkqMkvSWqClzt1sxE>|@ns2C z5|17Tl7LSk!{mZpvH+CrFZwZ!)DYGWIP;Psh$EA`A-*}UR!;h9>L}Zp-;Fv%QM``iQ~_E|2z|&7JKJ z9I+N*5c~Dz$(*g%vg8tc_j?KvaBIWQKzC`v=*-ceUn5{85BD;};2QKOM!L@Dfs1Y< zg;*Hq76$&kqYLv{t1hAuIU3q`VK+f=W9EUnNK^vLqD>0ZWuAN_h;PkwjqA?dj2?W- zPfbJ@(3Xr?W;~Zu|FN|}8r`Khyp|vZ6V9w_B7PiYFk97%k(VH_4Ubt6>JrbRKEl4M?~6^%?rn0 zi_n2boHz93_lp3xVe)_>F9C&k2Ofwka-;6Z?Uj~jr~|~qT$%4Q7@`lk(Ov=?&XRoY zB!$vDAhKxvdu1WRY+koGm=1a%H?NhW$fM-`ev;#Xi5|t}y+~?}e}>e?QI=cS?)Ho) zcGuab(8OVs^S%}=+>~LX4En_9i<05g@zqFmZ9+BOlN@K|Y({UBDAeCmZeyZcNvn1< z`RaPUHw4{Ey0Z>zc1fsGLt7PG4z*iWq+qthd4!B3gttw7uJ`owl)=m|n9>=!kU;-} zU*jqxY8hcN2s7Tb0o?}-B1GuQLvq&1YZ*0SJC!9fuz7i6)U-fI!~~A! z+CI`+G?<;$k}nX*1Ct-AOii^*7mPGac@qbeBo#}*v~e782OXC;9i|>CNm7gx^&~3l zSr%BZ!t9>ISdL~Q>pp=fV&{L+>>EC+;l%IDb>-&h0jid+di1JCe-l00K;@}3uR9yi zo8M1o&Lk+!4c%tHadIE@v@GQbEz-{ohgc<1fb9C@=mBx&cSx6BU-ueS7DA?h8Be^E zC|aJl{*vJIFogzjIgMKV)sUEuNR74Afpz>5y4aq|x>1QLGTiRQzR{oY-*;;_}TAA}uh-A&2=*!n@WnxU6XiYPxl}**k+{lwT+p09E zDp8sK#3YyZlw@SpBNp`tk*M^E9pv$P@xXU3aL}Ek=CA1+FP#B+qhSV=G?uh2_C5;7 z`?1kz!ZMzWjIT!_o&>4FKT%4|t90pB4Fh$DNAdVKl|th^hMAo9<2*FEoRozmDlnrc z#X}vXLle=}QLG*l^(}WtF(V^qH~U&d9NR|+o{w0frQEF0yKX-3^PUuR*Bvyj*WK-@ z2o<l0zsdVI&Bu*TekD|Ht07Ew_y%*>`*ewkKv+ ziXdT$lHBfIJy17WvL#C)s%>q*bQD35goz6m7fRIk?8`pv!+t~m*yhQsDikS;b~oKK zy)%k%m?TsvR3);i@_N$db|SEAZt7lGAJ%t3Xf3MmI5Z#k_4z&vxua2QjSXBS2t}Uj zDw0xF3%iyYq{MhA<|vgKA!AAz4TN?H6s!OXdNxDdKnVd=wv3XYMx{d`7%n=)J`>p= zT`JPfc*_Mk%~-f}qmftr+gTQxo+ZKzp{K|gAif}tL+U)D1XCFnc+5r=i~|41?M)pF zYr&ADhAF=rom4JO=>fAixJ#FocqnbB#@!hYe&T)u^+z^?jTEZNK~~3ub`Al<*2N zT%WlfG#A;uXB=)M)B6|Un>sE?R!_qbzI3t311ny#4#_O71;5xf~9#1AY@b$Mo zlhibgl7#DrYdEUYIs9`#JzN4#GUC)94pA<#t{@hD+s4Wk^6?35IyR=dT2LvpPK-ozK24$d1 zj(HMy8J9{9S);bzaLzJ!x=K_((z%N;F|Lx3->JFZivb-{`up@F&_BAfVmM#dM>Z2r z{x&1G?mc$s+%))@Z!|oojt6j}>fK~0-8eRddgokM3D7GU?TphRjw+_M;D@$}0PP~5 ztE8H@kvk4JL5ruM18(5nYZ9n zrW=a9oG5?8eB0z*nsc=@@Y^aR5@O^zZA19znglG_dXTM^)4zhmCcFie&2 zVLb=WZ1Kz%4qF&6$`fqy^^jdeA49d@g5G6wW^5)+lgiM7xSIi6Z# zkQmYIR|2@^pXPTs;#`W>ksl;j#}aV!q_=l%~?BhTb#J zVKvPh8p&LW9*SjSXX~&0M!(2+?Ls4QnArI`1M)JIsmCqoG5wsCvm#3L=^>bQpId9(hl`pf z2xu5P39NKlk?v{M<9A_R0I-$@_?>g##vLO6XgYmHN#)c=_GH`sHyfgGZAwc66iUqt z%@nVJN`^|pZ0q1@dF+j%r3r;~te73JF^{pl?fbCZ@kY*1b%^^fs~j;1Ej%pdFih#l zLcLqA>tney<=I!`Za6K!8h+yL?^K!n8xZ4bkU0KXNOGSho%R-+y*j`2KD^)i0SELV zMLr(h0)b4zGfg@&$4f1m@TIrU*k~=4)Z@O)CDUi%{Uiql_tt`m%H|)+Ug?YPfS&~; z7X6Iwr+@~dy`0O;R^E`qFhzDoU+$*l3^B7eUsJw@kQ7{fB^3;r7| z`74aO<)360*g}`?mR_CW9eBZf(cAbKqh2y?42NQHqKlh0;gpN1%Jm|`X5r$$QOlMd zkLSn$1_zp%?xUJw&#Kdvn2>R1WYnpF`Z<^bM3heVx4-^3D+&I-;fSu%f0O-3I5q-B ze>4&6(O^EQ{CA}HB+*?ti4m197m16f(L~Hl@}RoPg@P9}IRjO6rE1bGVl`3#GFEk$ zB%g{7xwW^vs6UCT_VzDZ?QIQK*$G}fUCgDa!a{d4KSY38*{e#|t&cVweuGkju^9jn= zXa@)cAYARyelW>P-6e;Vm~v^j)8B`@*)65jy7|I)>5wZ9y$W{yolda5^+b3hNdHr1 z0%{m9T3(u|_;ZBnKm`x?BB~UNMQ2E6FWpnC$?w*Xv?W{jxHYG~i|_&wEQ*=G3~$hn z)N6bhx6lA!7T4iA3?|JZ;FjPjn_DhBU1`|LyLwLy1!Rkse?^ROawWj>{ulV*NaYDz zx8K7Ps|4;$mzsI2=#b=J6E>3%KMlJmXQQx-4f3_CL(yxp9`2`KR&NQ1p!FE4z#I^= z!|V7=>fOofUwGW_13>T^69dDce+CMnHrW&OtUoc)xs=pOqDzfOaW>0rpBKj8@Ev90 zq`lqlbe^uCr|I#Y)S3}{Yv_%XRZ+77=i^M>uwH-R_DyFseEIIj(xzLMq{=<6a^hF2 zocKt;D`B7=@xjPzN7wJveDq~}?Nc?&L;osbCm{02_Q%t26cJ~s`KTu0&NEHdpy@Mn zekiWK588`Xm*NH(UfgLlS+jrj|{zcFGyp zRO{ti))?({(BAsxRr?j4!LNdCI)a0pmrv_bXDO5coP{6rVsI4|FzWgnRl51P@|e`Q zED%#P(fGuY1@%m^shGan!x_Kfk@i@#av!B_&u(b8Ev?1pZd)ZeX}UGb((@lB0LF8p zZOr0C$X_N(mI;U1aDx9@&;#ko2G}ewHa&@3iLk?5j8om#VU`gw%eIuvLMn5x3;w z%=Mw`_K}C_%!H;0(3kqXdgE_6oqMKpV~trSW$$iUI+O39u+0;b2NT71p)fQ8a3zs$ zkEu_}CB70H_v87Oi>C`SC%k~fxK0N-&Ju@jHy=OW`}*gvLm?st;IRDdon`n4`~{&^ zZT4I&+7uTO_)L0*TV6ri{F?g#>r--{{4MY=GY`K^=10q)rS#KOUT1GLwb2F@lRHjS z!%b0IC)Ty3AHT}E{WdSh{s&abDaLs|)Qh#EuI~WGLz`En+hvNO&o08_9Q75}A#7O8 zr!Z%WTXi`p=!pO7a^LX@X%-j9doBMk$?t{;uWD>NO~|e8_p|76^jQ9D6SM?H!=?jq zAtvwKNzQK!MJGL9-^xSiogQ@dUh?POc1JJWvIGxGhhE~dAmS4%3%1@f|Vu!-LzHfN1nWh962{Cm!ly`|19_=|H}sc%c0 z+uW6oF|1g6fXqT<@aw!T1`5iqeChIi)?oNnm8h_HTF0Nt6mC60+@sW9n&%n3=~D;A z3MTD%Qu!B=9JPIYAxQZ`x6b1Gwi*GPt6jzs2{LOU^)j6yomfJ@Tu!AI(Pe=*+44Yl zl2|RJzD}}PT;!P}ULSIHo0fYJveZT;rY6LY-^*)y_zDXDeaJDY<6TXSy&rX&r0G33Y~jdo%ZRzeCP@XrN8mv=$JR7 zi>s42oh7+LjATtZRS)iTNc|>l0&(wJ!^4Tp8*5WUjq3#=CSVB19wy@Hi`sF|bF(9b zvx+7t!6fqN%U+KMcW{IfaRTppkd(?K{g|*DINs1#s^&D^aN>ti0d3SDMiL@R0}2&H zEd)|TBb9hsv6M=~8`B(q6hw*W3iGo#mr-s8v^Pd>sShqo1cYyZ)8C%GKl#f!di(`K z0}d9CD~-4@E&@u$BebMjDmmgUAm3-v_&;eKzF2`ySVLPVkcd&0bTI9Y=~TgknylzH{1!~5-(I; zBVeB{mnIyOXg!6GxzI^Lp1y$Oi{9}$#{nst-YV?Jr>OhKY!B^eozPUC>HF>JdmD33 zH*oMeTU)zZJ6pSm$_QR99ZEM53Xc(qMSZ|=r0(?DWAzyu6i64iU-J%r-_1{}BqRy= zy_0umhX*9<#6@?mXeY^oxSy_T%(|bTqGwcWbET2T(M3i^VHUadC(*p0!}Gx*VNnx| z_*q}fVnz<5hQ`CWfBWvRZSHsKysiS4kLcBNX4+2!l~kOYR?g}_VEJisJQKqqh6RlO z3`zb`?8SdOq9W$06TA#|*lxU}v>vzywu=Vg9-&FEmntUXS_Algr(hv7;1rr5x=OUD zrrH7VDGDo-Xqe@9)>N7z7}k21>G2Gt$vzAelhCDX5pcq(MB*iZEakBY#|{y zqn}Lm<|Qw!L7Im^+K8gjeO$8sXgsW?U0YS|rK*_JQ$I1r^_J!i>$#<;nHyU^JfuFO zkFn{H<6jWWMQT*kVo<`)&JU!3-(IO|jE|hH(=85~*`*7bwMj*PgWxurbdrz6t>fJ~ zR}fn(wPHf*ni|Mk_A6#mq!60P3S$2>3ge;XQUReZl*Ax2Vj{iCIam7N5LPC8#W8dy z^wnD~O*+i6wJ_P-zDr3EwV`)mqT-Z6NZj!tiw%K4uWzn&0wyTn`~U~^4sLaTa*Wm1sshF8p63kg6=*MgFd@;3KP182<0ZEedBE$Ch@}qKfbTOb$NS< z1{F$P%^l=ccF~_k@EqcdhdqL>bO%at_Oq%D!s}q}zsZvUar=lGjr7+gR8uT_HbI8t zu__cz4t2I?^0PY|MMY556#Q^j;djuQQ^3R1{HMP}3|ehTS4d z0s!UKRT4}M_A5=rzec`h49h7JHRW43EQ31Dn%P{d6cWz~_Lxx)&{_QMM(QDQ&^xb5 z)%DLKI-xQ&nU1?EOq)6M0Q++q(ViHhbV5l#yAP2AhJF*LHAGH2#-kZ>ZHZ$lBCY-_ zKm{NCcmMjAolfW9^YCFp1DPcBC7N`n3Fq1e)5JDLv|0+zs`vm+K(fEH8_q|Wfm2`a zw6LKB=FE5muK#>yJf9iQXU6lH@qA`HpBehhFkwDV=o$YgYFjuA%#_#ijaia?>9Bn! z++)INOiN3%y(MP5lD{8nSY_i##l4GB({68%=>&g&ZE^*tFtI@raKWJviU%8~E?lUe ztL2lF!=<$xV62&F#z**&&U`*3v00nM9HXu~@eApqeDzsDMO%7o((vaXL=lgNb#Cr&ul@nB7EGmkp{ZIG1%zR)$um5%53Q(j~w zB@iD2ts9@Kz^hCU)?opE&;DH>pWQTN3u!Q(NUO6E&Esd9$b{sg(BF^gH-}sW!*P3v zAnRdWRO`At%cNrCeP`EaJoSauaN9eV%72YN=rh@gM^D%dD|2VVPJ&Y;u`l+bw?Pw? z^q-34!6poS)4{W{aqP(QplaU4aJS1pdu!jjs=BiDEhxpl*M-Z~PUWHJPqgDb!S zxT`_Zs91Kg8W8smsO_^7?R7@KG3;cCwaz(`6K;r6+NR z3%SzBU~Gc0c!n$j+jYq~%c>_4CuD5pIM}7Waw2Q%<1NO%dh9 zNr+938FwjpZlxB=oBh>BuwXVAZcC6DQaODxXNNT5sp!v>{?>-4U2mOPh#0flwx3tq z^J;ruZGX^eGsrtnoNfQlq~mWvj4y3K|6C-|!h1uFS6`O9L-9C$RdxYYRM)}aDG^`TRLPHlCP}_{Cp$1$34!%7w^w{m*!apBUbWk zoN%z~2xebW%)V5N@R-iqG>YjxOF2R=H3-XkFqo`EsfRd6b`WXs-@kmyw}3%QIY>Bl?Vl6U?Ro@N5k`V;8GVf!4f=3lOSyZ_C8MgbH z-aOM=pbr=wMyMELf|IM*^CEb|$Rk0kmLxTsSLkt*kT@JMD7>FQp2E!{(73}6q}pPn zQ7!O#^1AXM1RBoQP0d&eM2P~Onv=Q?uFkl^r#2o~Kaz*6$(0uVIMN|v$mSc+9+7uP z@d#i$fvOftfxSyqU4j$#tI0x}HF#jwkGD9DeFuO;%OT8%XLNjPNVLU01%G16UkmOOI!a7i0Oc_Es~=wNZFRo+e#E4aH2Ej_^NB2Zq3UnSl9yY4 z_h6IU?*L+KdvAH;ys-t&&U3IAPU*uuM*>w=oAq>de(Cq=qArvsryU9|aK@^XAmdfh zU@W5x;oaO6KJx^W-2nl+=(Ue8CFA9?_oCBk5Nx=l8T!EAEt0GhUH9CF3SwzCj7PPu z!!C$8rT-$T!WWo&fWPbG{3<80`RYiZsk23_i#%g!TW&(ztQZ@PPOqH(io8k1?`S>)N7ZyL;k91qdWbh`6wDkwpKP=b7^Y=LPnQ z&HC2LOaPQbS6S8FwX0PTWszVauPZax^;^^g0RNwe;hgx;-fc3Aa1T-M#6RwK_Ykbq zW?}gkeOn+_pHrA1Ux`Z{gqGHZ$L_}2-j^?$3td#(u)bC53ebr4LgPqUqsL+;t0eMk z0Ua|#>JY;_HkM2#Iq3#|HyI~9HND5DW~UhryJ$u*V|%bv%^D|)=vE5@ z93{)caS)&;URZRwF=-39^S5}aJ)h_`XHS%;OS<(;bZO(oOQ!?5k{=xDIo>o1zTatf z_8POZ)0mwWo!LtGYCtbcB4=}7JlOcZVv^HQ(bd|c<-76p-N4mpjUL*Q_kaG@R5o5& ziZ*H)V9oz(S2ur}6YG={kK>;IUQ24o z8z%suqDCnu*+W;?X&O`0siSM}aJnjkM=#Erjkl!6JI{U3$z-7>0nlo|py^68Zm^X` zW8qGtvegai_}s`4Q~)eYlKY7H(cx@7imiat!sN)}h-*K}xhSJU2vcY9m%&ZWSQLk< z)p>!M%cw;BG^cjdQ@sZxL+~NEF&D^~tDVwNA&3|%rWV7~&RYl_E87(ftz2VOJvNT0sHq8ViJVPk5 zuOl!zASNoQ_@)21kl$a{Y~V3666EFl(N|(!K(~_#f)fom`0B2NSrVIXBtnt62!?G{ zge{_y!u_OXB)1jr3eXsf8~N5O`h*Qqxa(ez7G`73ee?RBRvs$%?k>~u=g*(rU4aF* zI~T72hzzylX>f%35M*1DMZK;8Q5@Dwk_>1yX&tHY-Q_vF9Af%O1QLj? zo-57PN`I$@BB%}8Lsi(bl=X`CCl-(3NH)&0uw|uZZj*%~g9}i^(y*kYBj&KI^GX1u zcp%8c#@Aul{XVT?s^pv~hfaIAEc1gtox`--r+!Xr;U%My7gTBVG*u1Bh3p);=DzB^ zx|dvaW4*ge130i)MFt~;Q7+!R?o!EyO;}F3gcCz#+M+~NU=A8^N2!RTFXesh5dll2 zV{_!Gpej`(f}_r_>sA~L(M>R`(FRF$EW`0r$2KBokuA#Z`b0dD*6X8#BpSw{ZK94Z za99t+Nkf<(f(pV9l4ir*BFl|02Z(8y-6*zAidtO%;!Glvyz*eO?84ol+sZwPp;6y9 zI=3hBZ#1J_zf8I$zR)JcE&FQ2+k6n7+#o&gT%OdnvG#L!WrwbbV3KDkbnxP;L|gMD z3+Zsyc_CT8`IgnIA-Dp0_T902Nc`^ht>5?SUus3rNmK?r(`<-vKjvNs^iL1_#b``N zKrNrLoV&{^@H|tj1Yu#91l4|3{0>p*dBEU=8&F>_fD&CY>b$m?($uk1GEmV?1G4Gx zLTBzYJX;&_B47<60FEPh4|9CE|soTCvqdWbU!L2k2!XTFz7kh-3L8m`*XpUvEAdP89d5!6U=hF0mI16Bbk+p^^nC}L?@ z!iBzoZ9OS&?-e-b3`;5Vnp9*47Bc-^JPWfV3o>Sm-rhr(xHQa-!IfhzHv$%caAmNZ zVEu*G5PON!MI@0$4%5|Rt&AF6k^GW|S>82~k8UOouAnhn$JJn$>v30Ty~0Z5>cS`^ z`4_TrtK3h6(-B-CSE+75WaN!XGk)4@d$oiEGY; z@!HF)s6a*zxkn^q6sW$plgzozDq`n!^r`WiBQ8ao%ZR%xwc9Mos*)8)ZZ!Q15$WG_ zs_1$_L@2fkN>V2pq0OaI80j#@4%;i}0Fbv{#(JTC=GvF?f3&v>FfXZ!U<8%myI~{` zV^t9+$t7cT7a?s3wH}}c{`VjGvygUm$;rrHy>@%+o8Ie# zXTPsG1HPif-~7Sly3v;K#b?U@v;DtjIdx})SP3M6USIb%7A%Cv=ND9f*U%lz=)h|0 zsQ6bP^WORrrUhAC%qC$+dspHU1AyujS9P?ty$CU5yDFcmSj|zXECHQ`+~7h^NcS_z zT*|RYGUeEWj8=={e8VY0;=Xvd*XwP)b(y03@@k^yDMTP2n zo^C~VlEs*W|LGuUA$1$tE1YIw5key=3W3BFPHLCB#bc^?pc)P=uYcT3*-EOJS#P@af_ejbBd#QpD6^w4>q(7-RNU zOtnWv1M<8{Ai8qCZfNYbRmZlfH>!!@gGVu+;A6pcfFh@bkyzSTeuw6%6kWMKeY7Q; zM!QookYbkpB#v%u?H&p%$j1^b4ix9-`)-@o3ey?_EJ%Ed)mS>E-JDsr^IY)<89_@8 zWrOGwsGvCNcFlY_#Uz?ZgM+KXed7Nl{zU3s<|KCRmz-kloH3pu_|EuK-=_u1pUC?Z zL*)N^Ab$Y65!ed?sy^1l>x1RAP7YM(C29coSqgfno|WUl?y9rL8EL+|-?Zgkd2iP4 ziwiqOmZ635VPk`m`|uw2r8uje&6G}qcW!h&=GH?CoKE8b;7lzL*q5!Mh;KAb9E>6k z&_8vQ(3pJ!CC#a?eOxnS`X-KrXnR^SmAXg(7zLuF+*$Y~)mk&&7*Jsn^}(kp;McTG zyTi!};I7QBw!WhkIl}9&)T&i#8fsLSkfeSpeRX>Hh3?CQg#a$#trB-)K|oxo1@-F0 zuqH4KZbtY?i%EL?g^FcQ(DgebzHJGye~K_I?hZ}lkg44ts{X9X!%7L#!gmu)5fl;J zXJJl$yGZN>YcSlw-r&$RT(Va6$xxaSrBqc%Og&5^i*@l%SZ1Wis2SP+b&Qut^22q!3g9W;H~dktxJh*MSW z4)&M%a#KC-iMkzDdFpO+t$iBNun3>#{dt4D;5~O^&D&fU6Z^J~Dq35nSZH7>VtK)( z6HlmaVe%V*LatzYI;@olh5O=|HtP#R%QyO*w)G{=`j|Pr;rcwJ{qUsifhQ?}ewZd9`d99LkK`7~pmd8Uxcng}-yr4IcdGlBVMgJQLHmO-*53I^j$ zlTAd;#|)9ZQ#&R&7!^)RvGFmHE6E<-8k`PK1a&jQ0ml$XNSN{L_FP?+ajEu2r5DyR zbJNe=6@6UY1DxgKH2SJr9?oIAmzW&ZxEeW!4n%Fz(9nam`&+ZebS}>@&kK&W6;dCG zP610Equ4`zV6X>O1pW*%2C>O$U_?*IMVPK!8>b#6_0ye;!^<7G!$q09ox(eMX*i|k{``Uz8mJz+!o8Iw;&oKQ%>Q^E4gRZk+B9F?VnnX0ZqihoT+RH!o>1ZDkwvSDE#(Afj~@vvxo|Dc+^ zlxLqa-1&1I?n{^YXE1^sDr#l)BflD%<<>EOgD9DqiVnhx<|D(f>3)$%RJ>9|Z0{rg zmkO#%V-gK$5-a`Q9mt>dF}}RZN|k{?f}Fuq`5C~$sMo<%r9cVQ58)0&^&GpOky0r& z6lH#xy5}6#L0yn`-YdGo-F>?FrW1eCc*e@QaFWGB3Gbr!=V_#3vlt)z z(jQkuEAAz>)kMhsgNmlph-N7*v)I><=v{X}qLJ<#O+E3Mrz$p+_924!aLg{4?#J9b z%jOkTHK6sMRPt<|sws^#tg+N~iFZJ!m z?;aDoTF||uACE@Z(|hiRERDwcS;{uR#E-ukB9mvZ6vp~{&bDP_=QN4`IN4d@exP6c zaO&4Cr@MxF`5TD3sJ|X8KKS6@(qUj0fghb_w{c{?>->V8njqC}S24EVUKT5}320-- z?g7p9tsfinCZ2Wq5OW7pnrE4=qbPCr)hD00le7^E`x%4PL4QNGsLbI(Ux})Ys$rye=80b**vWlY zT{j=i{h}gTnnY9ow(%4+N_)W;q%-m;_w`P;GD0?_DZ6Ps`-~GYw~tV&(iD4wt8b64 zwpb?Sq)JtQhN(zWw|^Rq5geXTJ;qi*wZ_GycAMLG2T4>m9`J328J0(kX|U&WnqqlE zLU1&rMHvno-)Be+N8Om0y2lqj9dcB445;5gKT1P{k@9Ci5+j?MO6kUuN3^;2kTqV@ z+XdZ*tpjBc&}Bq7j=ha^PK*Jq+l1!l#yp%vG~+S2R(V2qbV?*g|NKqmv7AGQ*{0^I z)O460%(z&gm*&zB{dtCUKAV#4C(i`Gfp)V#mi2=Jz7F)>x&#{lkeT-+#2R~klyC^F z9-D^gjdHyd9LbH-bmHqn@hTnxRhS;Y{lBUFZaWHmq8nM^2)~i{KE-~B7wvp}_UTY` zcPls{%S6+q1taYV9qM|E(gE71PW#FW%ZP+iVr;*kKfL4Ej!h(=Ud-d{U#c&LIsDt; z@bll^(|t%>NX;L95&5i64#&<0cu%waUwS?5=a>uy!GQxvlaV$}v%ZLf78X*>+8mfr zQMkWUB1=$7sU4~X?aAUf`!)ZW!wy@pE#!ec!I6G;N*71Vp8+Li&b_u<_<|wYK9mUDkl(3jGpJPYJ+4^pFP$+_iO}b%N!Bf z@T!zI#lFB+AFJfD*h$O6eadnIPm=?55}B=(eCS(~#gua`mX)IUermeKuZfS4nss*M zTXdzZO>-kobg%v1(ze$g*U{8Qi6n28jH3p04Bj;exPNhX0Kg#_cSihlSpZ}z`1{EY zSIgF!jkW&^I432`nZEXjm0Y{P01`=~xA|ZpK?mX%_f@m4Vg|Km1oc)ta zLnR)_?SixmS#m=5N_MwF5K?)o;v245Ivr=}*z|(im!8x0bPH${Pk;%qjnW^D<2~LE zRdYFc61iiau>3_tSB#%O3Q)+6u{S1T1W^f@0BBd1Yzt-`&;1)CZ^*C1u6x+wugra7-z3#12L&X4 zkY^2$+sCK$LZ$!pzahs$CUCcNm8yOr-<|>%Nb>G5W4~rVp>4VwG|Jxk*5X+yCNMpU zozl;Ng+)^I5uIRJ@;^-GaAKu*r8e zwCXsz(hiKHBA*`l#89R-q_CLfRiMIdH8c5<*&2yNyNY*mVa!$3&a&j$VETwwLssl; z59w<^Rky&V4~>WCll;L>NGvUo3xshiU%Q*HX>#vfL?6J<{#7&BJ2*YFDAZ<017w+1 z%v$rojQG;- zAVW^AJjvpv4s-*kmVEXLqDs05zmScDi2sO#4~M&7;WNO#Futgbjt zMUJ<^AeQ9|0hQ%LMH8*g=cjBJumP^AV|47bAA6#ZJ)C9=&RdA$Kt(2w#JDOMuqzVr zop!`a-Awe`pj26R^eIx9VLc^X26XBRl^H9pf(?RE*FZ^8-reHeV#ee=nXBiHa4(@4zAPe3@WQ4&TuVb zmhJ%~lG6aBC+0%tz&}5hiAb#0 z&eN$L9v#~-6~4T>eAj*B1~N_b`nxKJU4)Z#*_c9D9~~kHI7!sVI@%J$0ZiI+7QVL% z5CbpX(Iox!0(hU_NRaiuN>k!RE+Xa$x8J-P|s-uHw(hnA0sN(T|5xE^!sZQcU-)^y`3CI}AF9+0rL0z408@QU~k0j*VY z>*D@xT!L%MB>+O_MWoTUY(xm^VWoz?_9PTXxL6IVra?y~I4K)~I)NB!dLTCJxis)q zg$`1EkHaCu$^xj$MEfnX{2uJVA~4f7;_qLHl%uf4A!nJ)wl8WXIg#m1#WY!-wke>6 z?Se9&nO=+_M{-$@jv%ueW&-d?fye-N@iB`VL-##811I}46}PMvef+UJGFYv*_E z&>flNN`(%f>uB6XpJDM3y%N_eY!+3#Z(iZYBuU5w33?Ny&nGA+bFLvv5QK*9`e( zuJiiMAft)bj*+)n?b%P;mQG!bm7{SH;q3$Vm*w#GhSvO_U{5sVb*aF<=4jF>TC4^# z!E5v%zOX$KR=5Cbfy!(q^%bd7o-MNLK?5?-1RW5@iikzMFcnQMsg8||JcGuN0_11qfqN=vBQ%lh}F?s^aB zhs?7(m{Yw6^F+dXLr8PrBg+etE{^;(>)#-&*ECW$UghheFn3;)KuLQfof74456wp} zDW?4*jVyMrcKEpT+)pZwkix*-_W4$ugfWa>d*Y^ z%FC*_@90blE~RD9SfKK9QTF0ot6CQepo!Sk`sk>n<1q~-p__b6oNE@ z%=_w_Vo))kAjE&_B8H5&z6sb9N_NFRr+lyIOm!w@CsG+Z2f})sC&m^MKxB6p0 z%6;Nt{2DV`EXqf;F(*|@{E@p|sQHv=VbdGE+IZ!qn``T9-q&>^2}BGx(#sC2blm+g zr>pmr?p9hrKPe{tcpL?o=xN@}&wA+D6s`Ajv{q~j{^-HY7MM>l{`8}1WXVuWx)&Kp zrl8T}@~PJk?%uxHc(eJYJEVT4)TXb?j|6E-Zul zk^~4u-M^G35!?AtW5U@%4r8s6%5%=3QkoDn(F&hmNpdqC=?{*I183)^iy~AD|6n9^ z7M67`ozP@kXm>%6YzC(YE4}~o(4mq*5U-c>$q(aRC&6!lyr$CM+sDuk6HeB;1<>mS zskMnaw%71{J=v$tTUJJdJ>g33$K*7fo2kbJiby!@Bs39u-Vz;-4QhNykCTKY143~K zj~~f58y?Q)er-Nt*2@CUyG?)YM@3Q<#RlLcrO!h;?G#-k#VyV|PRaefbFTdKb|T7x zHI`LhF9tzoCCTRSvFB{7;FRe$pn*$-!9Da>n}v$Fd!Tp}6G5h@qC)nZtw=*iHt2`j zacnz>Cq{O8d|H|b&R2>^jn%4q_Tz4j9NKh#;{n~GbR`89GRQnB_`*(<%{2FY(-r@_ zOqWJf|4;b3L;t;~ZaWd!^h+wmsAr6|u0aLe9VF_($z0jca*NS!4O0u??5+l9$Mhky z3;P1)ie%8U0mPZWz_*KPvwa?*Y9pC2EZL8R26kU=K!D(|uM$;3xh!s~+j{JM{kP^6 z&J2vJogH&({!}Z=|NI#7%qW`~_^BpMc-Mt|z*`x-KU}rG2qKuv%e7Y=e9!uwGT2GnfIZ@{b?C5?ea0w6#f z*sVVYAU)hKN)FP<)hzZKDF3u?0Jv< zK6^}appWb{3*_6W6HJ?=-)v%%Krtop%I+gwvBWi?hFhs2`Bn`!BiB$l1vEguu9;(1cTtp;#hOxlXGG3Ssi@4wXQ|D42P>;{( zccmWp{@djqxAVcOx5uaB5w)9s`!^}y%sWr$F?&6&dt00tZ~fIPZy{QP{g2q`=>sDR z=M92Sv~!UK&&Si_)8n?~iTcE5>}?_ZIzDrs9F z3;f1w{8phK9R+<3VN8hn+fO@_iac9mM?#4lYUX5r8ENGjLQ%BGP zk!My){@xYF4S#ule!dFdhdXh7SP^tUMzc<31U&RrnFm1`LJDb(Wz_PxV(?u!C={>{ zzNFt?8qmm>dZp2CM0o+|Z^5fUUSgL7K`XkSjZo~<26a}d{7?ATQ2&?t&nVWK@U(A_ zfz~#LEk9CTQUy=a;zvQA!4~p!P(lUS+j8GLAZwXY?$s>h17ETfln8Y`zbcw^YQWF6 z@uI>DX7}0FKo#;jbaR+eo%jQ_X*0jZQRNsk10l`$iSPrd68G@XfHWvZ(pl=58zC9N zWgaD*+^oRY{tc3M_{G!gSqNm417OYDD%`C#ueZ54c`4^2e9z@LF?N)f2q@SSH=M#f zOXFs8JzHr5E8B0P$#zf#mBKO~xb4D-^TXz)0pI9`0@DzD=sfgDUWtS^EviTY9tD1! zj~~W1a#nC8Xy(rVU?=yQlZcU7MeJ3fmbrnQM8812d4ovrBqQ-5h5seoBk;WFheY60 z6*ukm@8XO(vSS}d7B#;;k|*s9#s3I6WXv(q2Hjj6?)uguUOVtf#LsCVrNNGMfUP+p$s_4O%i1nM0Q(AzW^9fQieJWJ-m(P~4K3iPuMCQ8Z3Gx!m+9 z2TEGDQ-C1f^?<3otkNpW!q^HQx5>IJmQUyo7 zD6nQ|0CXTD)ile$&Qs1o?bD-vR(N!rdS%sx&u{p&kkKS!11&sQx87{r2Zln%w}D0( zXSZlB&v9>;=Q{13IqLSCx5iKI3+UIS{ug{I$%Ev@GUzKs!cA}t040h0ORkeX-8df2 zi}r{7?tvCTSMT}mi1=C9+Ht7&*6vFp{QJnd)A{gEuS1|7W{p8FC)9{J!K4y|pG*+H zuZ7K{{bgC4anMl-+7Pt#+tX0>>HnuWZC=mRSZt;}@2$6%2OBV_EqZQ#JU@6(M{uYz z;<{#h#poRGCa|lCmc-|AU9n`Jk^MT8EO&5T8`2DQ8nI!*RdK=(JFk*i=`>Im74_8PZ|?bU9D5 z6$e&r&hTbXn+&sQ%Mx@ywB<0{#rg^XQZgt;zDR(}85rC&e~;7{5Z&A3ul;ylKq~X% zsPYPBym2BN;{rQEhd|EX``7Y)(Wh-tf>SNrZTar$@BIMz?1o-;*Yqp?;@?CHKncG9 zHAnl)6S;@(E=dvB>bt3qxZJ4BLq^_Ozvmji2k>;37>VJD*n#z8=L86oE3R}RhJbIaVl#Hm^vitsT96n`zUai zn0y2`S{xcoiXeA|afhkxi=D&$RV@TJE+Tfw1@<@tR5zVmgm^f?V@Gn^5ECPYJxhAS zDvHIy0dc@WxyIFh?r_s|L(EEnek5VTbXLP53#l{coOIZOVUcwgJS6QsgI=@D3z54V{D2Y){~K551IE#_8C z0V<-B8E4Y5l}I*-W;mZ!GFmksvTQhQ*Cn8Tpv6w@p2WPu;pNLOy`EKhv)q=6&PJR} z9E<6{Jfm<}7(e5W8Dm8iU@K|P`t(0X`*Jx6DLV4pa}r&o2tVrkqmV(?W>1O?hT0Tz z!CP;`TVGq->h*wr{~?h(B_*xP)K zcdkC{b=^wt}0v7ovbh3+Hb{oBx2X4FLua|ZF z;A*e?@m&A4-9%OEYwPRu6IIr6X$%|xtK$qN(Wv~HigjH3QNMxrk1q63KAwHp*=^K9 zKREWw-l>^}6}+@}x{B{d_^0<~ZDUR9y8LWr;lo#|74ejgW79OSMlLHN5j`#s2d~%H z8q3s}@T=3qy|euTO&Gw3y^9jL>^U^1o?7fkqyEzv;e5v+mkaSII-t(M>qKW~e1SIz z>@Nr|K}s#Uyly9o6A5yvs=v5CN9_O?h=qg|8!Gf=Bskz-a)w7VL6EQo;XT|w)HjJ% z#jAM8nrgw)b-{B(UQI*%Qh(EaTy;Z-NgNHi&N}lAr)0tADeBG-NkT`Svu-5D$dxK( z4?4BF#Hlv-0YQip=6Y@IX06xT=tnb;b<*B+o&lB=T<8j)5qI6c3HetMkxX|h|t1mSyb1eR+%|Z36reKGdSSt8iCIRLD z@N6^8;0yp0t+x~7&`OzamGfL{^Fq=Zohry50+fJ#_G#NYD+sgWHdn>3oBeGO@ub}X=$I=w z+b+Nlv{faR78D)igOiT4w|}y;Oc8qNCqq>d2RF{Xn;ck5=|Yg`iqO760_Xn3wP2~I2G;>)B=nx{6b#Kk>-GeUKalO-nOBzecuIC3eyhK9_cS4n5 z|6U`Dx=1dZ|0=8v`dX|Oe+DQ85GpEBq>$IGbzZ+I>Z^|64MD%q5S+L}&8la_e1jA` z=MYrsAyz`e(RGAQOg-}Kg`jqdja!(~J?T)R<>mC~9GkHCe*Y}baE4?2+xAt{HPa95i zW8%p`P0z&jk0q|#>3Qw{$ZP-SIf7`d_48=Jp@a>|?m+5L> z7qM0k`;LX-MxGP)9nE4vgKUJxxRyX|MJp%!yQ?}qBt3G6Svk>O0YVN{YQMEsA3ppw zn6Q(ps$kkOabXX^srX@7_qgq30J^teCpNu{rZW4EaaycH7A=;xDdQmNBYZW(;S14E zW57B<$X%I~4x32#nbrqO6HA>L*pFe?ui^+UwEXoR zB?*qfWmZhGDWKc&_gNpQi@So%$WBm2v5z;!qk7h#uT}kSnc5$|6`%gk&*MdO%2!VYRcYm4q z79x6+QG3h-zV)`*<# zS(i8q{8;^(?Jp(Wh8_0#Aoyn-1o!9tPeOVr(9<3vxzj8BW)Q^Q!OH-&V)8ifuk4~( zvD<|%H!|hKKb;oGJ5{AU1(*XCfA4tiXoov?EBc5EJ1x-TTrrM9$I{-qx889LG&1m_ z%ZXq_o1#LURKVr#NeBp!(e%$U_#DTH^es$bpxS2k4Y>VsQfuN$_x^*)lYzmRfN)yH zs>IL8_Y3@ICME|Nr-)m>AxQ!!9w!7z=R(3}27dU#ItzBVBkIoQ(3qeqO2Bp2X$|Wv z-MJdY0#S#NGKK}`l+f-eo-CF#M1)r1-tpieIPmm08vnB#nYU`Vj0L~%|GhIf$3%48 z3zcN0iMjqv)eLmr^XHTFAA6F1_rm;HNLFr-$1ZqG&yR)nVlM#KPDR_(^-Q7vcnbZ- z68srxvAl6NytkWfZ|kkMz7V0up`fn>w)gT=i}hYPq3tt0n`%&^51+ z?eHb{lk*-|~6mum5^fsn%W zi0h}$8{spa2%Iz|Ps)(%D;%nmp;8mH7LDpKd>@%ix>8Ku!CL5U|K#R@9Xf4Wz<((J z;UBY^ppArTJ&c)@=CudiKgM*W+ zCF?8*{O6fUVt0FnKflj9&-{>+E%q32;mraH$$-x#_sb|CHWL`be8hn`RWtMViK$6I z!Rp^7-U@Hq9doSw5fzmq*TiHBBAFw40A1IuUo>|R=Re}uOxe*Uhs`bf9NVLq_0&;- zMd9S*(i(p@n_9!4Et%|tJenduK^}3MBSl{)`dfdD5W4ydy`=NCbkBn^V=GrAS4QkT~yia63) z;95E2fN)adjD-ec>>I~YHi-?kah%m{h>V7d1#%y9CR3iONY%oTh-6r;T$y z$rKnP9Fgy|D_cjlr;#NM3W=$0C~ZinTS}|mX@aP{_hW?|2}j)%g-@&_+XH5FrXx?a zNLvGceYrZ8#EZ45#%k$=ITMlA5pi$@k zDv=97pCO~!Ooutfty6*n(^@3!+?(-#Asy*Dx@j@Xwfp@mk0E5~3SZQ#sj>+Cnc~Dx zEGcPce4|+#oL|(GVr8SqM!4&6t~5)#u(vLPBRDiWRxcz77xfd1-B?b5@=$d22YNRR zCV7@>aj4@+ERKK|2)0B#=v8VL9BiH5eSbH|xAaHya)2@_5j3&yV&7?tg5W z4_oF#uV+84cih2CpwD*PFW%?$yk*x{Z)5Q{ zo)`b$X7S}*f7;G}{EUAlhyP~eV1NJ~BL_w{Z2EdKR-rg6TG&Fq2Km0chhh%J49&OK zP~~9yErDD%KoZ+#5ZI!1ON~~Pv!soGwS+vVQVzOX^WFf8YpeI5YUIZP;N8MgG)S~D zL#Cdl?aC@X+yza6t;=dY7&~B``LQ-N5z`e`fs%Zd&0W>hO;|RkF~1J0J)z^aJzt^~ zv5B3NEMfhN9)@EwA@W$@L2I-lz(dHO?}QRnme>LaMUsMgRKW>=8NNCpqI95OuyXYM zc9I#xMO*nK9=iOD=7iC3d1CP#D7ft7`@q0!eXoA|4?|mRCBq|x)>1Ll8UVW>-||y4 zIYsX&7<2_1to-*NQ}=u6)LFJ%zm8BHL#SnAFrZKOH&LwfAjQfQ{acf4v-@N z2MdxUQxY%m4ll6j90M2b8Dd$`9XG39N_JdJO>#Q5>i27V1q<7GqPAD}(hjFtwD@Ca zdmA&{K693=!1IN}Pe)aNce)~MdzjBIglIO=J+D_ri z_bQlX?qL6@F~NguR5GM{BYl;7Bp$Cw;}G(dN9U@%%+PKktG1(we$Nq&Q{sMZM#Zlg zRDEd|ZYx0#SJI_gnwLpY4IkuWPkC_f`IS%a27HzCw`TS1iQ%v#b0$2TZ37i+G;J~S zY6?~20WxROLKdSWsZsYwRU8{91Do@VS+uHT4zitJtbpcNFt$fT*X$|cAkl%@4YjFI zJA3`nD7D2OJifN~ET8pa|IrVI#}mHQh`2Sof^}AD_iA9%Q#t^VrbQ60m$|H_C!lK0>4`OXI!E5((*}a&qef!el$~hkZIjx$0O;l7q za_w59YpLHr$||2-#b(Qo!^><4VDK|lMpL-*Wb&b}l&8wcR~{?-hQp!q0xPy1#(95O zrQ_&n9^o(~^FY`ZzVX`ITF{j59Usbd-nKYve_^;X(GPk~_9VYB=S*9`AEx~ZzbDk9 zgOjq`dv#{1qjM>0?u9NN+H$`8MO#8xBS9QZ#3|gEj!hRD!DonY5Jy2j;IwZG?Rf6r zvWkPw(G`6MbNNOu9dj-EIzOU-Wy=lE!D`tu5RDyp9Rt&VVP^5g8{$i!7%2E3KW){F zdE>3ugCzcT5%^mY&qxkf_6pR=()f{1lVHx{b8HGdHk&ptbA{j+iezw?w&_Sk4mB+wp08G zgTBfEIPkQU1IG8(20Z9C7tl)1jcW!SIDz8B$C@qoBcGUePI3s-l3hE^PMU)!tc%I% z#Jpsd40%gE)Bpq|2WmZiUpxlhz`PwbXQG2lvhp;j@`A1myW8Py(oSq7ffRQoV}#oZ zI13OnzR2cH*OZE5XQfne3Oj1<4hA1wBnsynrXeH%P2A=z)v2&)i`!~b)79>{oc;<< z^df^NH2f(??)HUu;PJ=)Zd87zNxY~6o1nDSNd1xq z_xsRsb!0!05-ke-l*rz%be`3F zo%#{^tY<~5z3?X&9EBV+_?0vGmi%@~1f+tZE{r#+Mk>~YDdeXHl#QDx;QNnB;x);> z*nWaU3H06AjZOPg=)UiMk`{6I`SxdxX@VM1h|N!h36kIx_fBJS@d6ji*#7@G(J~kg ziQzOUpZq-gr6Tqyu+O|3dDe%+79VO)pQvmp?jN;Z`R4Xy}r>#-V%1$(GUpBR6? zSau-(V>y?qgt~MS`ITR-dv6y3yI|H@%p!}l*zOFWW7vSZMj!C4=3(1DYvb13;qBQE_XHity(lcGU1y*L_06G1GP98{w9nNQT za@^%yE0QhKWC-VQ(57Y3aF3Fwh@0^9v2xNZwW&$0SJk4@YLdk|OP}U3S@tNcdk-e! zSFG3IR;lv4O^frh{oTE8l}2~?fF!dd*uTzuz4a|3_KgK1=Q4*a>1fa9RT2=u}MC9rCTs7#qAmxyH**&>dD=JC^l&J5P>`1;PH78J6*ukgsiRY!Z9&D|O` zP--^Jzo3q^_nKDe!kPUr$<=HR`LA+wfdk2+gm?CCGwMm47SySRY7+XMGEMzhY=nLK6Te{667PeKx zHYmBrk@AIGeYNJ)oz&75YU-_Z*4EZsjya%-q+V+t(Z0D!KXV`O$l*s@ZbH{T1H+K; zu0=Oc%n;{kk6su@V}CdY1C4ozSe)txIq{*yfN@XsBJ%`PGaMG&uBAS4Fl~CcLU3e8 zs|~l{@R`8E9ACCr=R^m{i3=2yYjbXdO{XQ86U$8f|2#qBBil5|vA}$2AzP4mNvjrP z*Ue>(*iD8l9YlQ6GP(j@!5ly6xgMwWa=P{B+BqxDDy*Mv_QlEEJ)mRkue9F};`oKT za+;OS$=|wzgTG!K9Iq~3L0O9YfK5SJNVQu?gtTm}Uva*fbM1jMt=3BH+~Ev%w?lmM zf3I_|s}F+5jz4`HaiMSe+1XoL-jb^SxDx;;-%KJKH{6Z;q1>>yN)e-tp?jziXRm)W z&UFI3fUUuhC5eQONtDFu&m-V2qr3+^6-s-W2eM0l@47lK{T4{U2DWK zDP}6bB{Y-Ne!`6aqJVRky%3q}h24FQoNBo$t2}+c8lr22wSi|zW6x;GjT&m?mByhb zh`7QOQTrsD(jvapu9d}0At}7>JgA#-IR}`%bvZt)(Jm0KYK58;W2EN1BAs0w_Oyrx2HJTMYf>|bxkZ!KOuQMLVY;k^M<6~OfabK&{mf35UD&a6 zHh~H&pLgI-A^|73zRgod+bYEf0qa^RyJbOZJzGv!&N8|}N=NG{-jTOk8xU>}cJ$1$ z*DWtYFZsvqvowP-lZ5?yz+&f7khuo}`m)E~yS!Wn4GwXni^8S#C+1_9TNRC z@MCzd_(-748^j_2Iowa$~2G1I$e$(u{8liHkDhi;p@ompG^fKV@S{D z425JHkoM@q3$#Ma+RGPW26}iju}?yvxV-4Dwrazdz5OKzl^?6S7)~rSct|6^-vU}U zw#S#T`zKvST<#nj^x%4SUKkV0LyPLP7uEekENXKpAIk6D;Ofuy$@0KLKJK+CL%W|& z!Ln{9u+%Xy#6|$Ji`6`-o_-8{4;Wb59__C}0<-TtwZl+$cLg)hhf~yB^m=2V-*&QK zW^*rf>4k09+*Yh=Y=PdhQXQy#x+Un%a=Mt<5W|q;G$(P0gwx+L1Ct=&o~nujm0Yt& zeR1>-)e{*@JtqZmfYjxl_&+Zu6+YCS;Hq)=9o%GbRZFYyiCO%nr@~@xn+M3!fT1Cv zUZtTXcTQ6ew*V2;*epvMC?P3G!ndiJG7Df4g2-U|#{SUg+EVWj@j*QCul@US3^ z1KcW~MH4&V*WL-yV?Wrn|3s@c@ROl$Ou`F@v-cnnZFGW2Xic8XZbYXL6wOMk6}B<% zePNA~kjvSljRE}fEQ2EXojyE&a{ofZNm-mJ^SQNd+RAcRoS|E#@zSYYX}2km7F(yI zfMJDEi|$Ss`4DhvK4coXJ~;`D+sH!pj7gTk)q(4TlZvQ^0%)0TC#sYzJA9Gj9*5$* z3yn25d!E(ElC}LVYPcW}1c{FuaCa7R=6)SqN!y9XyxKE;6)6~V;dcqVw(k7*I6 zUSz~pKd0F`s`B!yyX|{ZeCSVr(NU$faC=+@P`K|^xgRnlHGREn4*GjfgCT;WwSQ{w z5hR{ny6C3b!%Z7aMN=cjh^tb=U@hf)sHJYh$tP->U|2E6H-$bXsIbxaxkGMUduNHw zn-7Q|t>s%3a8m{8nkWflS_sV10LFX~iGv$7RT8jncwX(8#Jz)yhhyQVTU}tCm##~D z%l%Kc$lNN8u_;02Gdhr94X$9tE`k(& z$6mX7d@IHSZtm!XY|kRxan-7Hz&g%(?%D5L{AYDK*tD7z9?nZRtSb8v0%q;42HE?6JPS^&E|BN zc3HM?*u9mGzFcXr57CqsL?Swp!m8yhOj|k085$!_Qriv0B+9h!;f2lm7~_aPIVAmC)`ZqM+oUj?^b@YVcY z#dIQQ$m4B%^~~2k5sQk|Ts`%y>V{eHPdcxxPP(mCwkK5cbaM3Rv_f56bt_Z<^I7zK z7X1s)qJO8OAsCf2cf(s}S!Q!llG)1;n<7A=?=H_5TvuChcs7Allv?W-&B7I|c|vGK z?MT!!hC$yk?qYsSQ<>_NE?L{p0!{07I_}G=$X^bl^d}v!6tZp{y zvV%0WqAlpqQ@7FOGhv9(4o(Ktqpt{^sZU~yNTvzJRaupA$&n!$O?F{+0`JlV>{EEl zlUPz`<1*=2&;X=7=-dPMY~X%b>ODerypK750I|Yj`P2_+uh4n*G^0o`8?i;id+qjK zZ7q7m)F^TiafOkc(zMZN8-Z5lI%uTPFl%MpXE|_+uNmH@vbh_FZy^?8hZ$1wLg#br zhUkd{>ou!tt`uGw{z2U78sVId?x1Fwm*%#hy$s70y%3N@qd)d<0x!6!O5TM}nb+D9 zqi6TQsF>&3{f^n?n5XH@Mctji3rnORcHOasuWX|^G*r{y)I!sR0o@xb zM5O+at-prH6fL#W&{E$AG7y(==2(};Ec{)~L-)jkiM0E{kE6uh{+bMNn#Fx$sOSc0 zNbq?SxC76<@aGBg)oiOG@0XK#UQ|URgNS(PA9(J5L?YxId6@9GAEh@DU-8|jh-pL( zgK`CFJax}UDuVCmwtnF02mKO?7jR!j+?V@}WbZQie$91rvCT5SeO~52=`uqGC>~j6 zIWTMRHz+3MwR$}oaGbhIlPJ>&7Y03Kl(C-iCx>o*M6`9gu1XMG$6vcekb|4yU<2*c zV~iONt+t|Z(;LDX5mNvKDJqv{=2Qd%1d4FvXIG~ut|N}EWu%qslHP+CGFPn&balES z6AETq$Q6nP{lQ>ScEUy*MC?&+oXq9XeO6N^ zoQHgAyX|O(Q`|0_V>T$6)&OoLyOI$uU6wpe|2P8PM4wt^1ms&L;?=L+~gjrts%<1Kiqem`qb zPf>T8%(^Dk8c5`4;^Vyat)I8NXKHz-mWQb2j*hWsN_nP~2Pg%}%htU0H%t+Wa3-ny z;qvm_BnRH#`D8S%?Z{QGL|mE{%WK7jiCq;lth?86`^7NDu1kvx!|sP@Jn6>FRoAhV zv`C9pCyFL4jL+yic-SaBtx(Ep0<&G z^px$p#L(&HpvH;fIqF6wFX3B*PU$aeQ0pKfkc0fJ4zED@i+6kLuX|gP@C?-0T9Gg9mn=XLoap$M=HS$A-80c2Oa!Q`agWU6j*Xa&q<t5@!3?;gC;PEC;-f}{X+o&h1z{+12- z7-0=`b}i&Xw~4`aqcZVl?l~M)tmRJ!q6mP2&6aH7GI58ebgtL2WMCrHww3_p;=2&DM%?imA;k%A|zSlkXsiI+C6_bv8`0ky1c)WW;HzJ#~2Gkum=0ZzE z2jwN5tML3{EUFIe6F-mKeKjW9^k$LVX7pjB0~-LkS4`aV!#&)s=MJ}Xtt9xZ;82R_QL@2ElsQ3PM-Qz=pHNg1GwwDe5^2}evuK4`d*ag^sj+b+sVsGmFq~Bvlylt zdFkwUaCW*w&1`J>UK&JR8cn=$b|bItRymS9hjfY1QU=8Ac8@DKG^O&rkA%)QcOG5v zB@HNO1`DSVv0J-&G#(etQH4W()K7CitLM;!*iaLRn$v=t;={1~9~^4jEO(R*W4~Fe zyFKMc_tZlBQIOG2FZ=5GdY~WtFrnKS(^Jr))R-4}(vNbV`r}*j zI84Wx`#FlIszn{{Hh%ErhklgGkq}M2Dvi4E!%K%%KDM=dr2CI1!OwG;M^1u0pTw0p z;5&kVKlYQLp(p#8O;YzV0+MLE(UPC_$9|keg_jhgz)StYuPKJ#{Orfm#W$xazKPO4 zZM+O_qIFwGe#+9@IpAUEjW>#$89(Zu=P=9?H{~7dU+I@3G(xE~SMT8$^A z-p$*o{?@-Gj=_VYp&bs}>Oc63&apUZwl$+4z@XCk?G*;j)V{GxhgIy~{_uk?N9@nn ziC0w?5_RCgl;*pCrvsr$E!)NHYainMG^S%AnMI?#J0zZnKGsw@D2WTAT^|Qu=gq?t zj-VU;ajELwdprj&nJ(0ixu;*74EyS) zB;lsfhRNzYC`l6d3h{?Ww0%oo`r~TGn~NTQ#i8+peC@a=P zUI?Mwwxj3{0n}VU9>$1{$fiZjRKxovoiomt@a^aUI9xEeM&lzDpx?BJ^j0V?M?q4_ zJV5ypgz}l#+TPo@n_|cEORj|95%$TJD>KK=BfQK>noEWVxLaFWTjnK0=imn#iO)#C z6aDFT*QZFwtXc4Rng6WIEYd;Gd%fmv_1-Kl@nHg%9sY3VO|%IulSAlRX66M?oWf+b zfK{P|RbnL~Vj4;H0rj7k*2-&q|3U$G_g z`3|0pr=EL5H}#Q95I(hi>&GMn^egzEeMsi@cgNtZj-x!Ue&5yX3!p1u=T$ zjV4)FB~51gEcQq4QIsR(Jex*&zW`1ae*I1o&?~89lR4~W&C6e{5jkuu#x@&G%rOnz zL^Jc`Um>chnOC%(_|z6HOPYC!$DArPgQnFF*d^`0KBks(9SOQ&^#@cU?90q3{s_Ej zHxU&!S|zP%)c7u2I)j3&n&D8G5y7#>A5VQ^?!bix{EODCdp{hG9MKK!f7mB+b-&loqKmPb@!r7JdqP%(Y>V7b@ zL?E_?h{eGO1tX_Tq{}8=s%m)T;AnfS;)O%H<2KATR5gr)cvlJBo;8r_)Af(P8>S)8 zd;aFto6W7Y2ck2M7H_GA@X+Neu=uvvBy?^pC@33~XVRNsZuR^*O#=jw2DMe#Qa492 zx0?`L&SmL9q9k)aWGaou#8FK6!|%)}aG?9mENz`L_h@>dc+Vc9e-`_wR~L)f!&%Ypc}nH)-EVR{wTWmyQY(*GTi@ZMf@;AsA*#tOZWQ z+joPd7cAhh>99szS$)gu=z7Gf3xEnA`2u;08(4eVh#KUZ4*vH9J!;Soz2bIgWx)^L zN6$U3-0jJA+`rK%5>K42D1=dR&07aWEhbQ>@!q_05BG^jlhC!c|IA@3C5VMU9s-#a zL2{O$dNDiB1#B~AjehRe?oSN;bGXlw1vJ7LeevAgOeZeEY!`LVq+VC(jZD0?o?#QQ zYCtQLHEz0Tm9W>y;r=qlg{E~kN6PhgkpevY_He`>`T>o}s}fr0r-cO(SxR3`Al`4H z&Lcg{QSpt;(T(lim>wa(dNysuic?mpj_$2kMMZ08QM1LH!eAy6n<6r`AW1?D9^Z!G-6(qt<_^veK7;Fm6{m)@kL=;xf*+fe`;C8)G`+1mBzP z#^yb*6(hJD`RR4!?tvZ~egW?y1m2mGmg->!an4RWVk?*Tn2wF5ohY0WQ5Ys$G++Xd z?ihD;@k-IJKnDSj_(o+MG68=T#xbdX=&+BV;}`B$7oj~L4+kCO(VB9Jm0}W&=!Gsl z=AhMsD`4xNS-^imp|8^DmrA)KKM;=_`Yn~gp~$#`h@i_$$GCP!w7lGJary_cs0y-i z8hus2qC+wR=#o3g^uZEl9PKK*-nQ46h?bKkjb(T48tqKSb-%2wuk~E?&zI~1#@T^g z8u05I{!u7dO5=OS8JxWw9CqBn;7q`127BF=?xFRt!+}@lL6z5Q1rvJagwP8L&JkwM zFNz9>VwyGD!Qn=e!Q+t(HbJ0fr7jVrj`@+ZD!AP*9k+Ye!OC?9OSaKr>F1SuxcA}k zXy@~eyG>_WH1%)&{wVf`-l)2c%A$h5*Y!+W;HMFl$bblvk+A0fJjI9pBpZzqq+JX= zZMgRX`_5nzVHJ+fPS4oHoo4+=c~v)`SJQcAN`CLA#7*_e+uFSE0}LmdLc5FTorl5; z9$Y4gAj@hET{OHB_=c%OYZRqnL>x&)TMltZs95I)WHZS*ZXKONa6sU|em!^|lt=wFV54t+8tb zwN~)dZj^g+xPQn?a#9u1mrM1P2Hp+6?23f;T>nH=EDpwJFNP)KpdgeXka)N;2eN_BzHA> z?y*an3_=%_V15q%xAVYJt&9tX@KmC&Wn9vK{hxdc=OG-z+t+^6iKDE#!9*o#RDOMm zyx2r>?&@?TYu*O2NxgMi`bGA%iTT_zOYV1fuLf;Q=x-`fYH+*{ej*`RbVSam#lHUg zR1#hsTK8@gC_TQ-H6R||JJfKevUcys;=#!=tlpOqTOb(CtS0A&8)Whhhrr9?ryU@5 zXw9s_-w@YNhYusw)+TbW9bBSxw7;HMab#?kiwcK!3HO@Ls$=u97Bz88Gt z6_~)P@Er{;-EN;QAPwk+&RN%NjdLJ9(o;TXm^#m?+n122 z#7U-^MY)iWwt#3t+c`fZ5_+&&x5m-2s2spiq3s@Kj6q4fA+D}jHtSY1CvCl)HQ~ne zuIIY~5FNQ{F+I93@W*9&8!}!7mer)x1!^HXb?4R0#m7=(IA7v?9O4Pgn5~y zDoVk4@rbN#Z>yQyOqTPN6i!ircqZVIj36EX=?}--jP^pt{^v0Eej9y{D&Eik>;H^_ zy%%RmMiP1+0PlpZAOESq_(c#hgYk9^IqMf8ToZwC0uIX_qauylcg`tZ4*=~@)P`J? zhGPn5g;`7*K$!dW#1I_<#=&W#s)+FcLJ|G*pJE|C-rqU@et6wNGLzH+x@#V55EpZI zXN)AT!5NSJxz_lR#7j)@Ou4V%zCP|A)>~|$W{IX^nA?Gbzyz&2rSw9j&dTXI$Cc^) zDZH~3r!=*&mAITtdKI8)ShyIb#aopl|6i#ynv9Th;9Z>qxYN!%*vQmkbIWnE&5bv& z9Y|l zxg&8(%4pPDoeoM~;F9gR{t0lvI;Ff$)~gE_M$b~aKS)~K$G6w}Ta{)AQcynJK?{Ie zj)&f?8q&4<S!<#U|^uF%mt%qaVk_$5lfyz3|}1W3jaGOQs2j~1BzvOcmv3QyL<)QTAs zBh(RXM8~~2-=lwxoF}`LuAGoWO&sE!)Y@6WiXhn~wZ)jjHf4wqHv^*4dKrk~99w^N z$$5BOP2o>}i;H7BrZ1EJ%nzT4!KtU*0PXN%Z9Om6A9b<1Nthx@c#qEV4R3wnF#iCx z9ba1)$SNcd)__LlM3e#Drtbdfz+L&fBDs`A%vFgP!rIxxT{j`wlJwD4BPd_BZ^Z%K zTfxL#p@m;v@Tt+7LAU@)tOaaHvpJ4*CQI-m&@-8t=IKT4bnCKeHc22;?cDg2NOY%Gb!uxDXqHlg ziUvSNH0h#zyl13S_KxF>R*q>-%XZcyPU52w+pdANff!R%%opa|pImcQP?;^+Vk%Aj z98sjI)Buy)$ya|g`udAM>aVf;;L~i`X7u`WwA*g;dD}g2yXS5958HMnkpGa~V128{ z2?E|O`Zj_{PA}gLx*PB1o}Y1A>l%@j1*%aM$67I~jWmXN(XVO-WyBNUhcBgUjWC6B zHK41p|Ld4pfsdD#40Ohq^N#(j(SO(1);8*g2ni5q2zlUqB62~7-Qy^UL^Dya5OJEd zjJw!YAYvF1b~vA{DwtFv+3@;zwtqx9kvi5&hB=m`g_!|4VSIlXDZ?HX-UIES5H-d# z!Z`tL{Htv3G|1<(Qm3tAAcQmQI{5NO0c3ogNtju$5(zN{Vi7XG!+Lia=Alu_NFD~( zSIA;&RNN6Ki59&}69{GK$B>*c%%&hMtXhh%u~ENg;!SY)@(i41mRqj{Xh`UNLvOmc z(i5U5kL7nZ;+eT_keP648=5pCyCMXNXiHCG!L8IW-!ZCAu*ie9NhSEC4e=W@*B&i z18;!PcAL^Zn?%g zqj8!^u87M?UWo&RrW&M%ENIo}&T9ez*q^Zu^@KVWv_xY{YcOY#e*|ZuVq%AG!^AAv zoYe7rmEAao7*7Qyx5FBoTr__-e#&YL-FQdPPED^2%rh&@b?5?LQOJ58$H2EhuV_-! z%++xfx`5bKM^UQ6Rk;8snvq}%M&LVwFc|YOOS?ORy~9IVG#a{GMKGR9rj7<~g}mfm zUB2tS!HJTEl19a;UtFdh{OS+0I4JO8>Ibw0-;ZQR(*>5JVAo-<=Wf0BHr5uTV32QP z3&pLNhUy-!yC(atTp=3LX+>uRW_Oh?n)Qki=LKH1*)oR$l}=Zev*_Kk*avO=ko~m? zJLUaAop9=*S>GY+mC?{!iBcLzx3O}zN2Nj3-DHXiJ3M0n!nW`s)(`0HiM}e~{qP;9 zOiU-IyTW_V;p;f27Mc4nzz4N=9rD5e9pO!5K}2`lRBkPky6?k=>!|0F=IItrU+;)d z%fv4osaA;Pxv1!dNDWD8O0v}T{Uim)g>~=M489AmA9g3Yq{|RNcdW25oaTzzuCG=b z#PskhE2o#|tJs^yB3#VVV3KEWwPDi0b<4}^-~wmtbXUGCtCV_aIqL8^$un*g1Zg$hZtPRm)SHN=bbX~ru)52`dAYSc^< zFK0Qr06g;0pEpOSc`sxaqsy$U%_`DmQ7$b*1xJ#2!SX0L0)FcEi+SjUN#PL{g&dbH8~Q6tzr!d}|VIp}qpzj^YlA5d*=Tzm;z-;1MB>23%3 z(@)}sQSJFifx8E|1-inwkvd@B4+Dw)KZpv>{%goA_oFe1V#q_b9pg`5DK8$zbr&^I z2we{0B#RR&ra#fR+Xx}YS%nPB9&HGmnW&MTsQ;h6Yg=v`NwV+w3WOhKrEU_oEZe?;s`8&U37cXjDwEc-%486oyoAQ zlbvK<0;p<6b!6}Hl_OW*EXWm2usweaOb=IMF5g{B%)38RVoZd}dSiv3&gF|+AoM-1 z+nGlS%|=mzrG4)v&)r!#fS+&86hPgDN`&MzxDgRgSMF?R(!QKQa*byFUI7Uh=2FRn zz|m+kwgPTwm(?FHypc!KHlFIyFBl-rZbQwRdNkPky)Rc^F3F>xY~F-MwKsD4qv(1Jy$wwjpr5f&5zp`EJ*aA zjj^x%7qku5Ils94X~D{4GV>;js`1dZv{Z`gc-S6Dh4SZ~f?27G0g)BxZID(ipQ zUl`T~n?XOLri*;Q+}fwzDcxd2$&rOku-O4YOTs|Ti-_9y^zv(8(84GCe@80VXb!^^ z88Kotx(L$A6n8|c;-dhhjk&ThS2pI##$4H$D;sm=-_Beqr=DNL9APDr&r2sFUoJqt z8b|&@kgXLDu)2~IGfBb7ttw)}IJdVi5oy7AOnM;4LL2GKEP(L%KEe-LaU=UI#O3b_tk39gZO^a3Yh3T>5l&!;An8M|o zhjI{!^KCi#O9yGNU>(MIVNa59Zb5>XwWG(FkK|B#TY=~}dX4!-9s=nn%1I4ddY4C-; z^M0AeOK8?b@r*~v_0EoVcV5@daiFW1kG)RF(FDqaq%wG!afmfJ*7#7_c0Japz2n6 ziyot7&*2DX9<8f8Eqk{IH^Ei^yxr-v?Bg;^KV$#0TIK`I!*`CoyHk~zx&J9= zqg*uYolsu=-WC7t?9@5Y6LLI3o@eBXLP*wcSF)DZ|3F&`YSCX?_Qe~sK<`%4_seV& z(i``$`fc+W_D&=32iZ2pYFqM;6erc-+eoMPshfnuNjiNJyo9Y~7QM7z zzFFpqxTJ*k(E)YN{ccB%7W_u$F5RrK3dSsfj3s2qn?UKg(9Enw&Q zL98%h48TH%cYLthc9c;KZFRDv{q2@zwYeegmDt!_x$j{T3)pO6tf53_*w;rBGIT^i88J*|gAce$dVeC6z{@|av^o*!fTuT-0B=}!A4 znS(Tqvu>TP=EIYojzWLf5CiRDeT2b4 zl`G9=N}S=xt1t5cKo8&2WaGSgyUZx|#lA#}cKdS10VdR-w2kml8&?u_&u3yy+2QIo z9lddQg>Lvr2HVxT6V-?vi#>rura$0OUj@z9MkB2u$PHzXsCi!JlyHYVV1)#W#Ry=N zcMmSK+yH|}IQp5|jB?SZhMnGJ``x?O?=cadqmkM>+ZMK>)a$FT+ykMLr2*V_^_LT9n{hzY6z(<`IjMz!2m{)w4^7XF43P9t%)iPFr6c+F=iY% zOKGRZ!`nVPI+kd2+>cw;BfsV3j#Ao&d-we3hr8A^i3U`ZhD_Vb7cbtuc=PgYQ-Euk zPt8=65)0%~Wu_P})9EB^E7*hTbOKYDtlp}1MoznRF3;(r>)l2%GbfyOpEJzmH!HdO zr6oa2F=o`N6(LakP*|*)P)MLr?)K7oWh|^eVkenzss)RMKcXnvEx3hd!!l8EEF=n&N?#!>)t#_r#&n~`4`C+O_$66$ zIo~Q9L-XD4bwn+#vw!{ahXWo_0608eIPb^=w%;yqkKu?yrR;Zlc25CC^7a8QSe5xe z6K}|VpYSg9OJ*(ReNDIXIQguu0TiIRwN?G3!$Ji$ndL1@&$dn0;+i-DGPFt|>amVj zumJgyHwkMG(WyscaN7{a_JMaZ^CERV&6+0{{%877N280h0IAABQ(AiEf`$Mc*68@BJ_uVcRI#3I8Z_aO+3x z5600A?DHet1LC#Fpubvey2E}ILxbh5H^rgpA)^L`X4+^}N-Hcf;ygETl(N0R7TJp@ zeEP~6`N$}fj2t5mwpOGZM_c91VsQgg?~8+O1ndl~Hb>~wgqBUY$AE68{@GxFFBY?qw`yS~ zLR?q9J#n!kT*vM*^idVl-C!=PEBg^Hv-4XEQ(d+s}Rv z30=jmt0pcgL~eg#Z}e#Fl{x%2ZcrwpkUDRr8}Ngj6YYL{eFajmMBZ*LF>54b)1DZZg;*__t?Jo1_pYWt$^jqA<9d{g!#&)nsylLdOGdce_J-XT! zskn+a2vZ7kzEekGJVPf5P$UO+iUh7u7Kn=~Knl>3 z&^#puiY-4=1@MVhGZAs2TDFq-5w^l^mD6ua-g3||BSLU!PujYJTo7O*p4Wi zFWsnq)e3!@AQ*Y6V4DYdSXHxVMi{eO$vPUR8IF3+$ZEL?$q8Lf2XrjZ&Zpyn9;F_p(5~xp5vjWj=ETnO0*9M-Yk%?7b0! z!`*lq$?=+cR5%;kAJaI<#bJEIzqqmCFFsG9GDT~_42Lk(@4L|*O{)7zB*OyIP-Ir* zmV$F6yDynsNVv%#uC$O_k@NS0Wal_LMG686IDC+G7WVaz()wD!NR}pCRk%C4TLPCp&ls zE?X*KA+Q7b!S(!UT_JjPIP=DwVqdAg1Y>O8a*2h?Y-emb+OWAS={g( z75l`sMMX7lR+!BSvsqy_E6iqv*{m=>dxa5gs2^QnwrG993N_U0iztH0?7aO~TVPnS zZ24eNEh!Rntmb7E2;1W0l_tq0&&m#^+04V6d3ZAqZ|32jFb{XS7ahjk?z~!c|LFwA zWXkE~@HZR|l_m_Ej-W0@40l_T>e!sN4n}A6nuK}R94a`7lRRs?S|9?3(g)HhHx(!{ zaB0Q7cvPBlxe}FIC~in~T+LaVk?h4hYXJ6+G#}oG|-3x>~5HOxdK0ODPu%t1CJObjEyqEU7CgY zv7`Ew!xo}s!84&hm2VG;+{zT|PZlak_ejf4Ac=wixyS%1=uni8EPbkSw?-rO!7IMwL6jlzFwAvttnvSy|;8UWC^SH!?xWI z?}|niQSWoFW%tgzE&Iv~qLOJaebuN2W0KLDO==Itw4l`p6s(@BFK7ubNe_M0dK{QxsMm; zRd}oEl>6jC3`c@Zu{gC$R`|xx@UVSia+*V0|0gZA=BBA;$+tXf{ZKS0(eE&HNFfBNCIbS{L}R(lgNa>#~!mgJ*p zoVT7SG2VE_93b#eGMm#g{2K&Xl;Rn6Ec&$Q6SI}v@+`l5CK_nzyryx{KI@R415@D{ z+A*I!v%f9(w0|4fXVEQWIe5u{@-el~$1F_?y593gF3QAZtSv8b^=FFS% zl}m%Tq^(O%)jx2`In?RnG_8UpMRNRe6xZZ76`lH(H%6pp?qvAlhH;MLz^AhPqrE{0 zOhXnZ-yLAkAHd)+4X{AY8+=K$bC`#`|31p?w7^!)aJop;;?YT@NaGrji@}9}(VbZ1Xs+CM&Hf zj}jU=DdRt6rrujGirMfs*bEu471G{tLW{nl>0|`_P=`-Us82{{x>>ax#4_<$?lhZu z4s(V@9N5%hD}wJ-0Av6GQ*6d2PXdQ>tPKu8c3!WB0~y8btVPCtBQi*vob;ncfic~q zfp@J|n!LbrL(Su7(Ll#2459?P^wWO7Yw3F&Tj!U~sG*thjG6R=4Y|^37eT5OxR3vS&Wda>H04Zx5hTL?t{<6l|u zSlsN9H?j|?^@}*d>D_3+XKYd7B&o7fXvHXV`=s>8ISoL*a)!8a!FL?SPOeO$6NH%^ zqy@+24-guU;G}TqByn{Vx3CY#DLrZ8zk2WbDYmFa0R5+sZtYVmXHh(6VvE8Z&*DZf zKACMkEefY;T=1zScvk2KcdULe?9XWg8kjRL_lilx_9uRDCh7+_Nhi@0gV1X~8F zlMXDQ6r+$8sO&8Ktz_Y?C0chdhiaJT2Sh+N>z6UkYksD=&R_F$ka_bpKS#oVz2-mI z#jW|7$(%FG>H#>L&eUtEz&OzjHO1&SQm%Rpfov!>qjm4ZlujY-P}lrVLh{xXbrP&g z&sy`Ks^Gc9Kwr=#@GeO)yGsyE(Ueq*xo za2C&^&UgIvMBSpz*Sdu3_9m5y&8T>N>J==%TU0+L$s z;w3&WdiGZYl>gkCX;<^ngH>cO2>#sKGUoV|`mu*~##S?9uBCnUUgWfqw6~zF$?@*p z)SrZGoQJV-{S_-4T~gwMG@anGGH*$GhK{#ouy~5y7^A3sWJ&EKw*14Wu8q19+9+f8@CFu*VAZGoOpA54D3kQz7w#^KF->k?K401gSrn+#;Ro72 zRLR>&K9J<9E|erU`)4%vW$EoeEyq3^?Ju&$U!;m4gchtSrSLB+giS?ispDuaFedsm z5oj6B&zueLJY}vfmQzVwI$UEGyh#d`vQ$hBgfd(v3KPYJ|K#0zE&K4-U#WL9`bXB* z2zYBRJK))V-K+eMQXDsWOO)KElhBgXdF|lR-Jr^)T0QKo%gYp?M7}=;u49|;v!Y^2 z;XEoT7=&i1RD%%1y|IcomZeL_M3|zjmMtAv6_(PcDuaoWHrCzeQr+sKEj@#o0e(^^ z{(Bku6OPaqwR-!_yPXvguBCP~?^(C;Y7SzqUFs^pG&AQbx5n~;O@a*?wR*P? z6taMh<&X_tu|0(SK3Ts(e$V6MMismK% zGf&X4ROCKLDj`F&HpryOVYA9rM*la+XB!+kD;kRi=B_5vp?&NBv-fY!ZDU!RFnC?~ z6=-*VZRsr%I{Bzlzd@ZWD=pbfQ_jq)o{nsg1WA}6zyd%?^u)~V{Ejc8BPPC!nTWaR z_%7yZ>W|HO)>?aGgQRGu>8h;vZD&MUB(brvv5)KcJeMUWet@ExdZ7?NafwtAk~xKt zVd~mU`?1Qo;6Ood5ccpG>U-9_W1Ih1L_ONqNOG>>-dbWr9K6bk3y+W&(is35v1dI* zeT(`Gm?vJTf$5vLjzimibK3cjdwU*GnV4|fc^e|BOm@II8EQ)52%@GSJcy4^0RGLZPy+7fe#Vx5faxJF z{{(@ww8m$7Zxkw@&s@f(4pBruMMxf+|2D9qqPGI9h>r)hx5@-yHdg~y6!>p}Vb3(- z%ojMHLUfX~#QdwAEyLF|2&y69-gP_^6@>w%T^nf%2;yO>AW#eZVWs)T&J`^%Fr2vH6q9lvr*{(Isf>#|C#*lfA~iq z=lRDh30u8hFq)OYAU5F^Wf}W7;WSL+6v4`2R4$gei6@zV6Xk#VABBHZ(wBfbFDzO# z5Vp+22ud66Ga7*SeYg3(+kD?`zV9}F-`yse(hkFf8&6*ZFBUYYRHpS+dqvP_M>7Df zGEMoh84N$|>rV7=5lKb5JimEmmj=@>^u|>{DJH+?>|&J#L3{!tO)5LVB3^+Ka&wX! zn>eC-#`i>~Vv@PLNIg#u#O6{X%_N)7N=t?l)M;|i>N11~nyiTKu?)bex+EUJpQW<5 z`z}VTr=;VMU*Eqv_4l9czTjrbm%S%}@2`$DU^7)RMQAc-xS3$-Dgt^P)1L4}8_ZDu zXfoB0$h+xd?rA8q4KKV1)2QI&nvda-5qy2%D#)*`$sBw*U>>Vdk|ckrcMAJUPg9Ee z_%WFDdh%l{E6ecCNeMr{rANG;4LQhh#D7~!*nM(PMK4OKQ8e>uj!iJsM-%Fg7AfJw zJQyfAK^qDFG#YPa695WKa-0;ie1;f!zS073QfLDxH(Np$Y0505=ie97_l5L*A^rA+ zq>u>@9!VyzW%W|RP<~%e#ae0*^qll^K$C>UO`f3*VMKHEhSa9{8HsrgLPuZ2vkD_Qp9DaBQ{Vw=gfezr z?1Y0+4Sk7cQ@Z_P+5=k_=XLv%)h&SjRAT?0l$k9C2h3&#llQ@SN2*?Nza4lTQ$(Cj zq&rFK5?)pC1+$bUw7RphiM$WJ-Y-Z_hXtO73KxI=`DeR(EWVv&qG7X8SDekcM$fm6 zq4J+Dm;7~<(pCZ3`>9E|{{7O+ze(zNbVpC^ZkkNa+FO)=jQkVMRRgW>xK$Pf=Lv1H zY>ScqG}xQ&`3FxIQ&2lFp3r(4!2_*%%gl5qJMPx|Xp)tYLVGAPl5u!-IwZf3!WlWAX)*YjwaAcZog*V&?B zFkmC}eVdPl%HhQ?O$)S;#;N%y>hm*ash*(QbpDigm?8jCAz3X4w?*F@Wef)*Cl35# zQj4C6w4(0e)41Q;^S2hbAh#Wu6WL?JoWyxX6}mZX?_9QhVfpBVsmG>_E{7NZ^bEl8 zxAt7)Cn6;=jgob1ILtFFoyoL|lvDh4l6C!)sApz-K1OC437>tr3^EJG2)NA(liv&a zM4FwU@=l!1hJGhYhf*CVD#Cd}V|mo2+0l|^X4m5BD4zPAF!>av-6#hP5&h7*4HF;& zIkeWyL(mE7pg-yr^rv-KW_OXhS5RM{&;~+s7(FWM$7ze}7|?O+ENifNzezKgZjL@q z#{8)@&1&Z{^4I(egaFL)G-gs|`Xw0X*H+jI=|r5_W&9Scr3Q@VVRsb9{t-NyY0x)6 zEY>f5_{R9CPZ*pJ*gv!#rsM9%mY}E^qU-i3P8hWj$$j*>1ymbH-Vg>5+C~KZ4UC5^ zwx0(1Y?NDoiBuFi@_yl|+VAIAc_diZrahD&%yzrZCAkDBC zPea<39@HKU!bfsz1qovZMr3+9gK|+*>i@pfau3g4p zB3SzjEnZe=7n&~(-a^xE_jhg&w%5Lpzjbrf@ox9F9ad5HjBsm;GLOQEm^G=!Arv9wD`C*B&Q%o79V(>? z-PdPa(Bl9RaGF_kLu>knfE3j}3ABNKv!bcYpYCGc(T(0QZLOn-`gxvMXgp&W;5a1a zJfB2is{Mvw4tT17tzn{#V&O8^aLTw;-O0=^B~eeEU#7DhG}G%XZKO8PE1hQdy!nh< zx{fL(=Y5zA{7wMeG}=u_3?t$Ah}6gBl4p4UZn5czrZXuvtPvI98e1-k-TEq|xf$_p zy`n(Y&;08wl0BkJ-OZ2tSr%Fz!KL> zZLlSEK6K8T0NlWlxwpqOwkzPROi@4x3Is1`1Y{es*J1&SstOpkCsV>isba})6qVz) zy4k<&|J!Z(%YQpfFYf5P1nK79vt>rO%Qopji?&(WL5{^TdNPZXKBI69{GZxyT{y$e z&d5)kd0FR zB2GB&`e>NWT4feGK-pqK>P%tmrhRaPudQNgEV&gvZj9XezJD>BBcOjcECj$E!_dpJ zX`n_~I@yf835zUkp8Y79L@b`dG~1fQldN!zx1A6;E3d;GlJil4Z^4MawTd|hV)U|l zl>*MKre5cDHbLdRohVs2_-ljRm%;7|+FHyCGg;~E6J@DJ68>NTf2;PGZC@fuB3F7_ zfy4XLHHVyV6;3{#jUF1#0PJMvjHjsBx6%X?S>a?VuzV1uBftau4pgv29~BY8UFqkT zsSzQP>C04%x5vd|^(83=X-3-I+$Y&D?k97v8__c(4jD=zAHwb%Q5B1~79{bRFzj1~ z^{--eJPA#LF<9SLMrbKc3Q;C<5BI3_i9X1)O6qIU!)^gZO4F}2eyN3JWWs`NyouPI zB99&=sE@E-GotF^n;0-<+6jL)`4(%YgYNhw#t8x8C}T1pyiJze(gR1ays7L8j%}Ux zi;2ty(;qNz&2o?tBG?CG&BE%yTfvnqc;jZUm5AP0>;>nG1T>j;PWaA;G`?^0Cblr+ zEV`OZPUC7&N@hsG@sWENp*D;9SrOG26%?$8ya=$Dw2QMX0~L|uO` zM;=GFqLA$Kkri%34>xslYSr4TGjS{aIZI)~`xsAJb9~&8Jb|?ReNx1pJ)?gYt#cao z%o`O=;2XpWwZo!7GMJUl+Lz}t;R;)@tQDk{FX0!+;T#54iK(rso;FJL#EHG?7b(*M z(_D;tp<1sHf19E&ksul=5(3-gz_Fs)d#e#>L%)4|Z4-6iFPCH0V&&U|o1vudqK@0>#ohYkJ03?}T7a}uPnbDLHtT+>kFBTw5OeCXsXU%BFMFM}C9XXPkL z(N9h%@!N3!-Xf4vEbn|8MTN8<%1|L35{@*J6q#oh3>qyNu$Y@oj_C32BLdizWB}sA zjAH-LwpBXCq*L&t^Vw7xN;o~CuDA%5hWtk7Ib%wD4j?xVh8xYd#fmku6kw{Kst~WT zhn>FO(v#sOh?2p!+vW5Im2!nJiDWurl>Ty7{E1WoRw`lC0p30A7aXqU^*GpPY5=m=S?}32 zbQRrlC|~x8iPws(7tkaM!k!JJfnP74P9y(3fxR8ByPwDM< znTK|7DUHi-zr7GE*l8v}3=Xeb8RIJNJ@{ad_?1U6k9v9wqRlPIY@rrP0EW=kQP2$y zR{237mSi?9(Ot$GyQ85&k`gEZwS^ZM$T%rZGx+4X-S98K_0)cQ{U`tC^3^Mwaf&G^ zk+!qxHazteeE_|JtOwl=3Vtb!(~!dpdZVakxCF91*Py?({C)*J$-l{GCBiB21winm z(bG6)KxqH!QNu>&KM9@$`~H&`!P938em`t1Y=B%yA+T6DzYKazvoJ2RsmqaJfi1%himFRauL9C?_}ob=$_vi*sD9OqJ%B38Wb^V6Ao8P+lTlH#W>9>=7_@ znY1bA(U6WXj&oM8hDlkmKfpg~ZctFBJ5VKqm!S?=Zng&sKg|nZKiaiQ^0bz_e3~#_ZH0h4^3O4ka;iD3ZaK% z3tRR1iM&N;6NJgtwH)WY5sfaBxNP&J-&$F4n`6))nDO2h&Uk;#jQ7^hczqd(O9-7t z8+RxKqrzM5^)Y9oWw2RZZ(0P0pJ#yC#AF0f5-XsL5Pjh57Qg5{ld?$BV!`^$mgmAc z!`*c=l8K&^mv>g04tve@x#2RqMsz>~%*SYq+$#Cnx+ejE#5Ol#b?jgFuCmz>p{Nov zR*dJ6*5VCv=6P*c)1p}+FTO93?+fJn0;v{=p&oqb2)UH(Ylk||fH?pESk>+RAL?nH4JWp>%${s1* zZ0SKJWt>)XxtK;YI1O4zA(AJIH=LICFtsGn!5==b;nAgMQ!S=5L)ry0Q;ofoHjJR5 zWVx|s7HejsLVS8fj2&QqclSxd=Z;|>X}qb#QuY;NDa_fDHJu5Zyh*mFnLUg8UX%_^ z%nuhwIDe!;OhxdAOH!XhL{k}4lcN(;AH~Cz-iTd=W@upOkUm=<-rn=CXGt#{Nn$T) zt*|!z942FlFQWb!M}9k^9y1xR2$b|sKnmC2AfkoZ*~IdHcn%seZ!y-Im5dv88n!Kz zKccLX3hBT#({cH)Y$VKilaP9X^y%lpiY6lbr)>)%G=;6>EQlQo;it?QI(8U{AdfVU zMPj^+7*^Gx+iw3B=SsivTk2F+EXQu&d`*YaYnpjwmuBL&Sq_MkIKJ$Nnr?$o9;MAR z>qn1Fy&6n|xy5TIEyen8)L^nfZpzGzY7uRfo?X*H+I*nn4k>(SfEwHH%Eej#J0%4}F0| z7~AR$AJA;t*VtO~JbH>inPrnHhh#@#f#h>vbDrXfBm<#d8mN%53y^q2GiB~6FmToU zYC9L-3mcB;C=-i3Uc}8GP;xUI$PE2vOg;#9DqSI#qcz(IPnzSE&D*Jr!9h&LtT*-{ ze5@H~6ZdW4HFEjhLhLoYwUgdQn|7NHU)VgRVM0gWyj4cG)5>)61_6X&dWOKkqj8kB zXchMnn`;ez$dKZ^o<1iTmPy#k!(tLAHp%d6M(=Qqa0|MgO!z}hbP!V{|K2~uga-zr zum8OR@;)uQ#6QX={GkQhz5?v;lF4bC;)p5jC_)-$#NS%T4n@X%PhPD4ylGs-_V!Nj zxBo}@pa0|ji|2nzLWHT%oH^=+L;3;>RDZ@;5J8zQ*79jSo!VMXvN@-Yk>CpFL@A$I zL!dEMz0c2M%j)}xPHsff=lr3SX18E1-Ncna8$FUS_k!KsJ^#gv7r~3COU?`_auH6< zayw2{)aEPAAzfKF%`)ntn^8{V6@4}7+>}J8+ukV43OcRAX+1tYwH%&rDJ~tlgek3SIZfjUU!!{tT0W*RG{fD!AI(f10$|mYG=BF%~P2gqY zh|Pv`$VPr4BU5PB-lur!qr~F=5sg$We{3qPW`Ot%0jPRogKH=^k{5y67&{6^d;P|;Cm&% zlzuqHP1Rr-1tTl!SS*R*-^bz~G8Rp9 zEbQS}ezNcHKV95w95VT;hyR@jBdy55x;YN;%{}rNjHQ=-DF+9z1fDC`u4Q#Zvl~nO}{x~pf=zB ze7>z}g^mz1M-Ok#1LXY?4qu+Qj;v3c4?w`6=(^|XHM$AsrW7g;7B}-Q#K?Sf3uOi)B+>3WXbgm zRuQ=O#OKFOz6lf?O@S4`KegZhgCxAgDxnuW>73Dw&J_EaJ$RZz&7EU`Ahd5#^v1aQ zIHVr#ZEF9gxxq`;Y;buhGtES0Z)bpf08D6ZEVh@7Te3sbD#~S5s@{dhYoxgPPQCgj zBKsn>X!Qi6L&+}mN1WFp*_)5B@)|y^Fin@BKI8GD8ByJD7d{d_OlR3t@+yPeG?}$w zT4w{cpk|~LV@`%1*kocpF{RUFWK}15RtZL;M2ll>`(B?Q#ILFP&p3R<=o7Y zw!w`QOz9n)!Ni;45-jNV&G7qX_m&_bGbGp0DU-(<(^gbQI>W0KAEEgjUG6RvvYu1Z`NrHn;M#dW4A3w`xL0-MZe5^k zmb6cXshmtfNXg6)as4Tp0D8%2E0aRqM0sQ?5jdzURcn;M#d{YwZ~n+YTMv)myE_L= zJuCUcQh4tv>{54G=D(lMXfW>b`K%T8!$~j>X{3`{ zYT=ENBxZ=F4b4f^#}#4RN{ZL-KU~}X6dLskI zYwCxrMO&i__FkhQlk9H8flB($zsuptdfzw8f7_!dvFQ&B8moiT>Bip@n~vgN-Nb1g z4GIoCp;@;7Jb3nS6rdZ}wG@5gTtoy4SGyd8A|VX*API-zWL@MQ>4O6Ao@S-mbxIeL z0jj^yINR6?WGE%Z;?htqKi)KS3sIQb&?3XgpXLyCh@{4h&gur@_IUpUQ8KwNXzNcG zRf&+jE{v8T0Ip?LB?ll0>o(GSk^(t3d5Fqz3xn4% zp_$=|Nh08A>J!2NqP;mTlj}{gg5kLVS}~idTLy0t7dHK$wDC1vii8r{?yhO}&+a1s z=#Ia)3INIlX|hRI!Z5HGfUEQQi$#Ai5QW$RfHqql48OMJ#wEfa?p%forBzGH)SN#f zbovv2VmA;zd6Kv@owGH`JVQ|e(5vh^wAki60Vki&GdN9v!zW@pKD37EY$G5D=^-of zX+ORA-cL*YRFZ5?}VWa~OiV`#^0d~I`|y>epx+Ev|^v}s|zH22b0HgPMH0pRX96i_L2 zT*H^Fz(~H(WqV-|-}i0{`JC(ZM89KP3KCRHd<}eLm15&$Dj8FCogaau;9PP<6K#qP zw#VtTVkFel3Nc?cfJY-04WUsUMc|jQZLV$D?ux^$vkAZbtxgh7B*f#E8iOhF%Dy|M zr|_MDRG2H{Zw8dvv{n)m^>vD<^ep7Cwd~8JouCB!0+{a?WhlN}6R5 zMJ`=#Sb)zfF6eEkO!+Bl^}-3lOg9uCZ)XNRS>?0f;NiI7diegbfL6Z_8O>JzkentW zfW>g;V2-UvllVT$A8mhDU<0@;-x?OeNR=SBq384cx*A!6gSCBuK183$0gt71egH4f zM#I{)hm>)gm^A^Z5%5|0!lghh0fG&Q^XrnV|Ni3IEw#PWRGS0;$w9EU`>>Sl=2|>B zihNbZkgHxELG3YlFrrA;%htbN=iK`Tq}(1X%d+n}m%oT8tIF=Nh?kW>dvCz>q^x!7 z7&#PkEbx6dJ=Ne8Ab8u;EmSmBBz`Yeu!YG4m^RsXn*M3~@||#$9l!s2&rP?>99Tu4 zX2gqNFT_c>yMV%ZR-sd}>Y;kdIGVGRgTx7BGfvBFY7fDa6REc*ZcT)h8Outdg>9{7Df!(T8G|W9^w*a$J)aYm z8LB-B`_mEa0#ax)E4ex=;YAE@fnPZPx1XtR_hZ)eLg+D5rZ4&&B|En1i#(?GVw2|Y zLwtRR_W7$vce0;6ANwy~?jG##`7d^#2TvEooUj1TRR62o<{29T&E)n8V)|%Ba7f=tTuwrowVc%A07y1QKGjElNk=nDgSMC<4HFQ1|J7;(7T<{>HF#Hd%qWp7)S!1DIR zVAH^App}~7(EVUv=~C|OPLmW=?O`1PQl~ih%Sqf!*hpaEA~kam_D*`B-<<)0(o_CL zKDCTRL0!i}G;J|XjgY>BFoPX>c;!E$&LxRzxjlM-!f#|L-tj;LV`$JMnj+6%$ZfGH znBYi-K*t!k4L*%IqJmRMZ2olGn=^83UU&*JL5<>o@u*1+i~Gf5UuAbGEGb1Toze8T z!pYE`K@8Y-#0{*)nxOZ=A0+QiKDK7PyKgaJRKqpX=HUCZ`95vdPMZmxpQ_F7Jwg7) z(*@h^huVB;pEgg!ikqS4AW<+R4IK)F`^MZLR(B4bV!OI=`g?SAPm|fO!opzMQjw}j zTSP$hY)W!oMZ~MRRfi+31d-WeCd322M6>0is>|X4m}IxGHGp=DC5OH>^(Ax0($OX$ z%q+@rc19JhHsdNhM!l0^{#b*cl8mDf#Jv-6(7PP(0FDSbx}X3n4d9jevJq7cWbadUVo(C_M_p0NX zN2eX-NwcR(3ru-5Sp4Yia~T|W375>i?$oV0=gEP0E%gra!8+t z%KWFn?(WkygQ}>fuftD(x|ojkcA>c&`0NeFM@MEUGWGk&{N5v@PVevI^G`WGMX#Aa zS*4+2Bgs;xOZ&9rcbKV64o68KcB$l*j$4k<&MB2BBLx;Rtc#%u*WP-+?RQS)=&P{7 zJ&ovMfOxhJ_)3Ge%y}r_Ruy%cIvFK+%V~fGmg20XzQ$W8a}!V+6>-jxR2*rh3R{*h z=8gB~X*f~v5{Pc#ZrkZc=41VSz+-ti0+wm&Y`G95-3X~v8He3fZDh1`JJ;^$C}yeP zxP6H^X5f~puA`eR+(W1|78xT>jj~xHFC&0>=cgauU*7!Lro)+N~u_Z=fCUJFZRPh~8+ zv1{{Y(b*17@%8DAvXjqlv*4lJ;!$KeWPoD0tinWng1j7a;LSy?Bw(^>q&ll?sE_f)JfYe4b_-u+@=d3)3<@6_- zkHD}zqHSf|LX5zMPR1x5&f>Ibz;X6q4%qYecj@1yp!m}SYPf+hR(IZYOn-!(hih=4 z?b=egy(BO^ZY8}3Dgg?fh_j^BLnb!pkBXH7=atB`D9OGCij`QAgcRz^%7~#BgOLGc4jQs-7 zDo!-(&gabj8ch-`R0cPAm}PwvZ!tG1X%6ma85Uz4ZSoczdy)3#bn3zfVY*=psRs-U zTF|73fR_w@geV!Q^+Pp z1TM)r zVqi|QY#c{EeD4TjTkyY2!5w~=1%L}o7#UfG7-q|7kE=5sA-5kMIuEMv_q^CaW~X4< zk72ORi_)8=4qk<25*LCpc;DEw>G!kVOt`IV0;|dy9&86uYVpAl+yiKH5jOAG4q7TH zukfEQ0AzSHRDFDIXKVg7~oF=2nLJ=i%AXCH(e${`?0ND<{Kcje_XyHywVl-y=#M117PD>v<^zzUb4SB6 z;tU#B!EZ8OszhF?=?<4?+DdN)(nJjQDCEEcc&X{dgw@Fo%EU=Zk5lSG;Im`r^{Pg! zrx#W(G_e`pQI!#a8}AspAs5n&@WnZZEmf*qv7XEWn&`b>r_OF;II?8GtEb3i@1chY?j#<- zNYqY#yfd_twpVyq>s)DNiCcV7P^%Se+6yaCZo51hhfL)(#;LytE8g z9+o)xIYBB_GDq$J%oW=H&dl}8)Ii~v-la7!Y*80|CU4e1nZea3{~h(aag%3tD=vDQ z1v@)KtoRu?R58p8qwKsc5(b!p6LtzKnxYd{4z%g|FRG!z#uob%!nTAA7pUb5I4>Ue z!V>0c1go7mdXuL#kodn_u&nHW-eaZKYZns;uF(9EM;X$=2{d>Z+voO)g*m26M8T5I zvW`382aAc4&XHu8WYGmt8VuXkJkkfXZlP9fDL8Gk9t|* z4=3HxhC?(x6-*6UUWfu-WLtGbaEyS7=2(SbE0|L3|ndYy4J@>Ud`&#RB zLZG36U}_GAj=L7gzyV3jSt`tzn+=}?lQ#bnPm#{~WZ9{;Sj?JF>Rm1o{Ce0_ISdjD z^OwtZQ}JRRdd;`Ae7DIOtVSY-_U}D#`9^|>>PKlz?;ToB#RlVxV8uZ z4j}~yKl;X8hNl~6vmjVJLYhllNY>E8p=%UIld`6u$({*YRN+2KY0p5-6<$WV=mWJa z(Nv2hscJD+=q^qKLFr%`bJb<4TUF<)&|&HivE&5Rc`pVqPc0t6SY!h&wOit**x*ig z*>Ei0obFhwy91aL2ffc|A+DR>jzH=k4ZHNGHO;!&{Wl%==IK12A+?7_pY(u5P=FPq z|H^h;)0dmu{3?I1$spZhX2ap3JX2z&>A}so3b(FJ8>1e$`_Y%oApfBm8y)b5CfBSn20B_Y#=M+?iJM2sAYNUVy&%wD9ax z>Qz_0{#jMxxF0f_jF8Kv-Hq+2O%{K@8&kj7m|DHYhSpS1tf~HQv!Yv zX#sg&G%+yn(L9dJB1#7TMCR0!C?C`7&d*MewMd8e)1_I+UG4xGE6*Q|vALPFS^t%Z z1JViVRLonDYt+z#ge!KrI}N?0VgbScsXG#HeeUCIU^0xhU>Ze6){RtQuI(Wc!@WrW z<5_%$ElXhH;P5>8l@oD3D*_Ddz^ox~3=~hac zJEW|1uufsun5qldC$aX9hWe>B413>TCdXy-CkA=+p9N1=s1fI8FYpmKamz&;CX5aH z$xv9D`u?LX)Pl5pgh;iKJ%n^($K~OnK1g^7?Iz=&+EYbwmTOjW%}=7Id-C*xA5R_V zG+?`7ACK>T$j*+4Hn&IIwr-XsQJ8wvvK%q<4P#xacJP9>_cd~Ir=$jx+IbSqF$zVu z6{W){Dd-s7lpu`9AEb?l=2|@{iS9$7zWDEoQrHSJ{!k-FGhIXj`wC-vR4iZrAp-&9gakTdV;+4(n!RR1^8`~zPBuAKN^h>@K+Y zso3G6E$3|WW~SG!t9KjQgxyA1a&W*}1vJ#MM&au4oD0D(J!zw8!oYgCrg!=0VGySspkm=ZW&)^*5xAdp=5UWIvr-md;T z%I_w8PF^9E_T`f^Mh!S(t(Kw{dfwmjk4meg|ljK+F(0tlFE|B&BC(7;$ zSFK#-Ndd%I1p7+g;oieTz1bD|Bo@pBu(4&E)ta}ROJ@%b`Nm-Md5_aYfS$NRZ1Pbd zAHJ0e$?tzk!$POhF3+h2)1yl2=Xnm?Ulpx+IU|P1N(uE0OOhQ1G+Q*8inf6Z+%7$naZuU&HxUg5Sp*p9Nt%eN+$-~+mmKrWP zhbpHj6ldrP-2~!_AU$x;sP%3vo;JruPx@kS>=_@6%(Kuu#(?v39U|9ez1}RZV&wEe ziVyur?XvkJO=*JUYMzv4h&4p|kY=TE2C_V9&AR_PALXZKBpK7oBmM8W|8hTg@^o?T zYRDi;!vAjAB!HcaH2l*uENLd$;efp5S-PX0F^n{QovVVLSg)zq7rYS`+OIC(e)y%~ zbw0d(*FiV_3msJr98Z1Baek7Hj~~iB7aX^!W-^F@IKwRKnPgpu z6eD`^D8x^#`>fd95^#EP*>uH~e@&Zvg=r4BotE zxE+`*9zCF9My{IGXENo6`-_H-xW92!f`HXjKSsA%atqyVsWZ468Fjz_Bs6F}rcDxO zNNgbygN-6es2r>1o_~m;2R6h^8S3m6%!Lc;u)A>XSME%qgG+l^lKN)>R&Ja=F1+Zz zMoml8%tO|oVDLsQt z4E`S=*%%z5#xjsSO*kHv&p~SZfVdMn&XR68n~-3JudPVFeuH%~LIn9fqTWHk_hQ-8 zz*a%k=VAk2r}-JX)w-T9{2eMQCJ)=JXd^ph?)-%-KrJ*slt(3>K^Qi z?9V`Th@e22Q^6Y2M4)-HM{q>I-h8YHNar_xBvZ9vF#uAli7W198PDsEH}9_A9iM4+f&Xs6!8*yH_s0g2u&yQC$`Y+9n&$*~6R7Zk~ceJnS+oIV7(Y>h8|Zy!ZSR-^Y@rsOj@Pz14NS zNUev5rdk9p6&8O6o)fW+MrAo~vged`Wf2qrV?dn0oT8Rtnx)&NUqal1Xx5esf562OYNIOD)Gy;(QBhr;x0`arC>04gqGL0p@ zh~DMpD)aZM*v24EW3xOTbnTh}wNG#ulW-=p&+%3=dqo>sQI!c7<$Z_uWwFS8b{4#5 zG)D11z`}5nfy3Y^@8WMO@9|&9*+uJSg3yM3!A`UO(8P^1%n|?Egc&;Z`x$eVZQT1L z&XmpL&f7hB9##R$Ynj7C6skJ4`VBpXZ&iL*+X&qNVV(8LS*|)46%Y16_LhO#0|x4- z+<^YfeTAF1=dTcX_T1lpwgO4i%^ArgjhpXqr^;svt-*zw4e6Xmj5dcp_3!vYYgk4T z$QGL$bo3oRd`My(yt_|VBLCYcC^n{wQS9x+?Qra?;fm@~X<*6qv^i+zK)IXyXr zUjRGW{{9LxoK7|_OlQu?sWU)Lj+t7BFf^_x++aMPelMQF^}^?wh|f??sP4$$qB^%X zTwwerXXhQ{1w37~K}hRSV%a}_och0X)DDgkixHDLbZc|o=@m&zp$&g43g@i}48)Tl z`$US<_BVL5&ZPUAR56KKT|PxujFaB6LMOLpi-Y)-S#zR)b-nZUhBH2*!lGbw=N?nY zKHLK*QTj22W97|^#JQvH$5vbhbRvBl?NK_Rb47hieem@83is<$#+`l7tDoCG9P&27 zsfKOn+-C1^5}|l1%iR`bmRUYgE%GotWoV(VhlgP5JsxsIYnX}~MDD#fzw!UG|N5NN z&i@P;=o_YmijY<83ttS0mSPD4of4WnP!W0&{G)!iMCO`7mmXS*Y~)lxx>%uj)Q!oW z^2d?MI|E zu~W)Z59;BX@bI{xN{+)qLwAbNEQIBrq`u8&7vig%m)FN_NOmxHJ$Z?Zy}p5P5H=TD zv4JdIb|gXeCfUnp>$sy3f5vu$8{-C=`;473fVU#d(`Xn2R6R*(L_Va9`hsAbBY26L zrIu`k%pDT+CbP|>@uYJ)m*+p7Hzka>h)Km+(^JPwfu{2IT!-zj#a?pC{2S{b_HA@V z+1(9`<_E!n|8#GEIoz`@xVgpx5ktc~59dbAv-JhjNyEu(dTP0>c_ABfQ)T-zY}-g3 z=L*qT;&gz9oKp7*1{1KwIeNYjej71GsoiP-->o&KNomrF6}MmAGu`YShI;wJ6wR#X zh{G0HZcTm6dc@LW#MHcDPinUt(Qb7Vj*C_?j5in8V7PCdhDpzV8a#oZwkjgJDpXt3 zi!tH_Q+$Y>qKZsnFRVMXTQV>v-P^Ne8-{|8_FEyPfMsXQ2&^(h97fZd8TK?M;6Cy$ z@(6Mw^%Rwf;M^8`D~y-HsX~2sQNgh`J@7>{MPZrs!})f@V|zz;E}`>tn^B6J@+gUJ zLq%{>W3qbCY0xh_?{?mM`@4Hjn|m*x?=}3h%eVgC!PBQG*kDH)V&*wrvTUHZ|Ki#1 z9(sZ;EaLj6NdmLf7Hk-tDBy(1EyTL)%yx?IjzLx4vE#Et55{wMJP8{sm`ZKH*hDsT z$TaSejVOR`4k?ecdu?y)d8vbyfstjF7X~=E@aGYTZ8_SBhh=|vcUMNa3uBJ*x6p~X z_2|ziitCSHwR!aC{Wp)Kb7PoXw_&UgdkD-Hbto^KFYp9EC~A!%VOJc7cvgXZHCoH}8+z@2-w- zNbp5lR?M`MsiaKfAKcD5nE!x5aCZyM{fw+xnT_ zH(|%38anAzlJp#%ru)0J^m;U|GX$7=uVUU78cUpkI!LhumbuQ+ekNEU;+m#uK|O-N z5Dt!uC&+m<5d%Yw7|^JIKOsU0U?!3|<5Vh?fue{adW1H3UOe&&1uwD>Z^2+PjdP`m zrz5p5RA<|ACTW;n10Z#14C31Fa1J58tZ#KYTc8LsNvc3gXy!xo6UikbT~{fvw8mEX9ds~LT~)i@T-&&uSS+Cm0KSyBC)WNd$QM& znz#4uwf6G8&cyR@V;TW-uCBX!P;Pj5`C%xbK@ydTB?(0V$eIdmS8R&eH znM^bT_`na#wt=lQ~sMyB9Z#sb{^Wv|G|0LMuaHQvp!AJ|%$Ll#p$KavVbeX3v49fc3 zzO+mHr9Rp8ZQq@poFaAy;0*h#^b;!NDrIKoT4|9hFfXz)G0kvds|OylqJEQXJ?h?S z8weX!|0|fJSsLH-jiPks>M=*iujy7(<(FW~RMY80p4`Q$>oFqTW0N$ttDc5E)1*DbQWjm=fHW+`x9UZ zUPt*bsbjqa0`s!a&6{>0y_Ddp(`LT67d+j4U`y9>dg>+vW9y=hdVh98dk|~8RZknW z+PzJ{jv+Q%uqC%oec6PmbKEC#Q4LF4C@D_zkQb3Wm2p}ms?cL$C)BtxK3DDSHe8d2 z4jyj-h3RMM7ViuLP-qAciJswTh*4YJGBCR9Vh4BhrmKz9~-%y`4ZBqo8D-qR(Z z`|C_1vyx2M0iuvSWKNJYY$>710SigcjC;&fr-EUgB?%CSwjsawqkG(Yc5>Vtu%K=P z8U*{x3rUOvGJUC~FZU~8V$I&p^7XtqW$AZlmPVZK&CF@7Lcf0-S>qQDP9kaJ$x6qT zv4tMn<5q5P>0i|*CKoCn@4_8hef(+oud@4p*>+|LC+B;}lmX#xchI1J=v@a>`X}w* z(?2EsGr_00FYF7w{{7nYJKBN6PyJ7EmWTdP*pHGjOIw3D0N(e;*^2_I_KZ>07D0M% z9^R8&vWf?GEm9lpmh(l(Vn_5b;E!&g5$DN$W3;g|MC3P5X|{Hd3&nWud%??v&~N0| zxK5W)GN=6hY%(>pv_07VG3cv8!An~9AXEC{O5nm_$aDh_$O>HrAuD7S$XQ z@l4d#xU~3VUO1J63Vx(PEvf+;eKzjk7&xv7h4typdVn)_-zgt z9-Gd5!acN)+|X4)h?gm6)fsp@D&Nf#pRKVv6kHK)san$#@KoLZ6iVnB=fg{s#D?x7tnUJhq*F?wL7Sy3&k?V8OTh% zUdQWYl=3QFkX2R^4|;i2T5ME!pg2EOh_hW%1IAcp-A-P~3ypIg=5ev)U7tP08QXb% z+}sl!T5f6u`4h9+Pb;7+R@wKjPQCrT-6y{d_o$4k$#4B$bP*q0A&p>~eUm}EJ`HKO9EF)8wP4MTev_J z5K5jb%xk&GKqfS>L8ux1b;fC@Vh>%a z$_->L*&S1qveloqUq0P!;LpJ`(kkF68mHME!_;1!ydh=cBpyC(c=)&Z`c3Dw)9}wf zoHkG2HvHFr5mn)`^R9XMzPa}d#9*(D6&lZR96L*G62#szgb>6IQTF9QTF~|Oh>@%&`U|_>ZkuFTEQ@sd>^K+hg z-#{xYK=ak)VUJfeyy%+Q|4YXa8AvTLAw}|-EVcOOBD%r1mVt)VCJ{vSwrDVu1x$W_ zb9MIX#nro$<12rVghPMJ2y>uoRm5%BAN+puD{lT3r3(N5x_iI7_kS}fKX4ZMNbJV$ zzHM?v1$sXS(1?`m4tZ)PNFHTSW?Jh<0e6w$!t1}N)x9a7TI7P zeFMveoqeyKKR2e~MTMv%VIMWQ4#hd?dd&>w5cLQ`fnl{u;&e;{Z?WRI?_Xs(j7gpw z#8P*4!`4`+7n2c=VZB1;L@045wCS2k4EvW%z1UDnn(RZ#Jc)B(bYTTq#4f=gRGN6< zaZby-&W^H|<*u^uA3j6VbCHCfB6^c->>rJXU6N0-XgUq(PjK<>r{MU*HySYd$-*tO zoO)rb^b^Tk;KXEd;Phgrsm@cwAm8|ss zVykm{e0BWZRKZW@d06J!3;gmc+VgozxakzJ$bEck_4wPj8UN<%Y!aQtKz0zI^M#Os zS3u|B{cDtIM!EWonFKMDuom8Y=6K^0ZhmKY4-d@)T*yt~1P>GIjf;x{xFF(EFmOYW zXSX(ll~oU{QmG%2KppiT;m8-7p9UfZC$!oUfg$kZM`3E0ByJ7Z)kkVP9L+Hf1;_zg z7E+`7x{Z>GPqM0cGl^23A!^uwB7kBM0WOvmNRv~M%w+n`z|R%hQ?|Z!@^3$!fLey$ z4-o0}%?&r;hy(-|T?6eZCsF07=;H4}nbT2DjeAS)PhEc0OZmfMJ!Le7bA|q<5j&{S zA88zYqwofvXV=$=-hsFF`HFM7hN%ckFr%5WwU@IQS3xhXD)ulEdp4eRL0LEs%VIX1 z(Sep`V-k>QcF|rs%r_R2`7Lk4H~~)TOSY9Snp;dJorEIj9+pQYKudvirW|e2cZ@Ew zkht#Ze6tZbZjRnU&7Ra;uNWQ25tl40(7_iuKy1ji^qXe2#kWv7KB$aY)WRr8?iebo z*gy=9Vl12rC+0f;R{Sx9rLdcZ`8Vit;AL>+%yOi1A2yl^j&wUmG&-1L$!h!5ja&rt z0nb#UVQ4g8{rmQ60 zH~TiphxC@PZ|pIo@)CkiN8mA~Q1SV|;R;5tey5PU@_DJLyPOTe(pFZ{s%dnXaaOB* zWponkvX`QjNKBu@1trfpJUnHWcO7B8ntvL7VSBxc#t{qZ4+&=nwJecFipLbaC`i&#aX?YuC8-YtTCu=jGELqPEa8BEYWN*I{3 zb$7726nSxWfdpJw`*DDQVZNR6{V3nB>TIf+uq&Pb~G<7-_U30KrIw1xJX97aa*koSqX0wx! zvbWqBHX)SO{47r^P(hEYTQ>#PB1b-e5Yei^Lu`H`UYy-TV&nqHmC77Ju-{EJB_-Edzh-^X-0080jZ6O`Dzjm8CWW6 zPt)7i37~APpjX5Z_d`Hk+Aq+JVei@Qi`IOQ2J_+@q`AT@iNyqD5C0_&v;{rg6firR zMe(Ws{25{qFpK5q*}EN8NomCd<5DAj#r{_zylE!t zG`pi!PWlL}9JK2g_lbXF_+`b6=NQ*>O(0cw8gs{2XD_ojsTgi=@~Vw*CdT@Ulv6+} zpe!}==2dno*ECDnSQ#-x8EX|^XTWEyqB>W?LktNQSx)=l&1jy+qzT|lYaHi!STRxm zkRfCCebnbH6MSiXnx{4iS=>hyK-P5@lnP!?7butH+#!tvDt8x;zR8aYr5^lnb`F9LlN z(rZVvNthOn1=%qM@if9M66s~*-js}hlk9oBW4jh-G+?g{S(l!hFagp{mE;*wLz&@m zG$KE3s@z859TqNN2BDVperaF@0w?-U!<+?u;qhts26B-XiGeY6L!l}fcP8~VIEQxt z04=7F5gBd}uS3TOKOd-$BSwR~v#ue$6p6vGl1nflBfd%2z9fwz(>m&9fC=F3e;Q@* zX3DXEW%l!*JC{HI`9fYh>c;}lEzmIGTw_l>rJ6LB4%qo11|#r=x>H|EZ!?wjI87U} zzA?Lcob4~Ln{w!CP(Z76SG3kH(^nwX+!t<|#k?uk6)pVJ)jgj@nvc_hk@FZuMDq%!d34J* zIUYIY^F;O&tDgK*6;w+7$w_baSCuhKJWFhUUo%ELtaunkSu> z)=s1!+6kNGikFXn;H>yoTGw^CzRvWs+eT@BA+k#g6rq%CSVT`!wW z#kT;B2N*|eKo)DoAs{bEwrSMYK1cMZMGC7}HgQSp)Bp`~-`Z2PT4g0TOp zDqU5`rfh*DiBsONj)2SdudJIn_=OcC4ew%1V^ofC;4Jo>2hS3V5O@Q>Qki(`f`lxc z%1M_4M*QK{2*1mHsU8iPTMl~}lQB~nlzwG9(63wtcNv`4o}f&qaKN3-M+01P3PGpDDLR}N1R>z zZBDxzdT)}555!0LWHIrR^ME*)uJAt;5o{F$&I5Gfn)sbH(+pAbnF!Vd8DEhTbCWI;>e5>sqq`?$F26 z1}$JJ2ppW63&Qw=kV9&|U$K-pES@%YJaQrbJQ1{;OIcSUDBysGP&P}uGodpvY>}Ly zAO!W;CPH^BWmY|oM8Io}f49@+rrkU{2E>(wpDpI0{v362xtDNidE&5fGbE8?t3|OY zP2DXi0UoYh1^LiXSNH*oDu~R}rx_UJz<;ZI5u}%^cc*U}{@MA}`OP`ci1vpY6ZQzJ zE6id{2$C@{%kfXmD8;efub#EmjDmomF>Ms!nJr-8luzHVr#sCvri*}w3pj8GdyBf2 z%9=o~RQg1Xg<>%Tu*Y?PY19h#Fx1NU%NnU46+OTQip=g7ve{aN)Rr;#fVTy}WRZM#&xh@;C{lh9j41{R!6LALbho~G3qjOD9>b6Jq6ZrVDlOxU;xE?ymlNns(N zlE^fnhkQ2q_aqwSS@tO={XsspX!{LFD!vW#{^mmHB?t9%kc)W`>@mCKll>=)E60T> zWYbLyc=M=AsbDKSg$lS$MbER0FFX(QXwN zmOL144;cBoa}T`s{u|n@uxkEgE2OWjs2_yAU^d?VmxiJ;G70K^$YHbAC?p81>$R!Yu!ohx1l9p{<+kFV-zl>*1qX2mfmYm~rRdzz2VH7v=plY|VzfqLzrx zC2dm2X5izODJM_ua(vd_((++3c=}L(vbtlN^X1vX> zsjK0!T7TN`PyhJGhW|r&OPWM`PJ=)v>`gC`;~x-{;CG*Nley3@3VfBxk5oYonmAiT zgky|V6A5_cS!fu?7+Z>_F6WohFXhaf;=o5jKlC z;n(bNrDF{H1$%>duQ11xy#FJda<-~Rv<(Oz1tv-~7-S;#vG11i5zI#9Ruy>0emMx! z-W)P0oJEq$#2c`9Bp#Vq3XYrF^!?>%21kXUT`fll*U#@2ECP!q#9GY)h7HjcFSatH z`PTLAMt6CR=pfs?*0C&mxKF%%dwx@6b@0Lplda0M=DHrcfy%-TxMt!Vg|wDiV;Y8x z1pHtSEAo~i`~LbNNdUgs8b;}Cb2K81g`^Jd3CHkC3Zlz*J6bAUa1?N#=q0ug;0MN4 zWja25lXS}M8f&0%Rzg&Qe->Us*=;MQS)4W*jY}i#zQn^qV%#?jUZJk@}Kus6Co&pJq}mFZ@g&@iO&45{t@Zpe{Fq=qG1$mu3__JDCa(4DxN%h zv4XN~k*lJk*|#^Gm;`apN>H^4QqGrQzc^S~?=Q{$l?1jHwgb))1bWQMPavzfZ;irk z{0$-`F59Qg_cIQU*!2%yEN#mj-UGJ;?(KvGreTf)^D-@W66RIXcT zFZrPl*H#TA!*<1y-$}x`1i~D3`In+q&`-!=;6Z%&T>i5AH<<)UKb*pd@O;^ba4NQg zDt`r&`0DJq4K&T$YStf{lJRm$H5IHo0tD5p!d~>Z9MH4P7_#tk&7w#ictM6^US3hcITL}g1FWH_bWW0HY{`v4r=i@|vd01cWfWbd*z;ovht?FzM0ixHO`nqOJ@ z2P@)qdd!t3+0av*cnfsD9=`uJBAp*JFl--_PlmtF1h18)tOHITI+}FN=c?R>T`8au zEGO=%Szsxh8ZNZLSb09j*2yBl^mDgpY&|Ee(3xlhR)BvHrdc|lAczKRYa}L#DS>HI5$!>GkC4hn}}*;wv@Ifql3BPsdju&VPOP_T2w3G($4|e)ID?`u?Bn z#U1K$PcOZGe~!X8Cc?(G4F6yLqrZjbZU_EjX6UEEi@hf+5J8MRUtCuL1@d#2)1mk?Jjg#sU7SNY&90mZR|KxqvicP}L-E3_ zrBVU_4OD~gB(&Ca{c7EB(c`y`o>a9Arr)oP2;vNnk3iYNKyBK^_mf0=WLJgz1ug6J z;XdM^&nzEXE9WoP%e++k=lXk9U7vBjUx&S`DC>*wokY80oCQVF3ua|7D>j>YSJ|+6 z7L$@y_P|NHzXD{;k#H-3Y6h)j!Rm1V9~>;uR2Qq(*T(H=cD*WvRHa>G`Bx~s0va|Q z4weU=vyi8-E24o7KWc(#)(iXnoW;L}N`7KI1bsV&Dza|hljQvYk&hKco{WKqB_n7WUe>M znL;2W()(UFLJk=Fb_X@iC+pEywr7c`tS4{-h9#MMCR=z5COcs_-PXqIV=8_j+7E!# z)n1>U!^o?h9%t#$A(Yk0E;-P|m^5{_QcVbwh!{|3Ij9Rd zIA3w&?;x*VGvP5<27~7T$389OS|6u?=j3Gn=4m+P82(D{a&~Asi6&f`<6F|&mw_~@ zqaNq@O!(vYurj%ya)5c7!X-7k?94X%OuUA+ZX05y<^CmM~8~}oR|KLUNWcR@{@IvCB_@D#oj5)K+ zZa}}${;gCYmLV;y`n#bFi3!6IRuvCz#om@gAM!f?58L(U1VLZ}IEDEwE*A{`iXsqt z=7H4Z5aI+ttI605Fn>2W7Q#S0OJXxT!Puzc6fhB_T+wbK@yfN(NU-_Fc~rr?2!sM- z_F+3j9nuvRq)%x`)^dLR9qf2Kx+U)|PibAPVw7-2Gqbz0#nuF>m@$AA9m(K2*1!F} zfB1{vaF+I7u#Zi3e?c6vCHyl*Q*sfiEv8aYOUA6dP(!(%3e6-fY*_!ET|E{ErQ%pTSL(8MRxsYVx@oUp14MnTQD#ef|!uOSF~UFa2Q4`ct`Ef^u# zFhJGv+q5$MP4d?^>f)=jlWQDVBsRZzvSbwy<(-#W-^2!liKy(fzs`Ehiz5+f)VV^O zZh9Y8H>wCrmmWf~5=~Ikn#Xt#J_hWJ21gq&!2h^^OzY0w z8cRBR;#xia{0+7y9*yQD$)*^0I&*1jUf7f`7qOmdYIKbi>F|(iLh3`IAZF|CwSh;5 zW0yJXD?oXRkzzS`W5x`#Ay5z-wJHT$m?eFWkvj}9Cmx4<(a-Qs#UaGWE_~`RT+)XY z6AA?aUrBEXA~t_pKa;VJesnwn<=YR~o%2qbA-t!cifH^_s3+XxO0`13Bs~EXIWg zFm9i>LTMkQ4_}{^4gTQ1M#J}&28&Jsjb8Mbx5zXGZ({j!q{2qUncAS`mWflVpj9m% zJM&o1V^kokX&wz?rY_@qCBU`nO|_vgPzUoj+u}%|U4!=o&WH2Bzn-PpCjfqvkd2Su zC>(?4fr(|@4W1mV2*!8|kG~daE?~xsB*Zus;DzEsX0o{VDSVlsBCVnWM4WIV7HnmoBx7ja{O3f_3HXB@Z^l{tW~ElLKgRad4Gi+bQQ&PIXoT%d|KNxS!INLreTcY1MYV(YWq zu-ggPy~qY~Z2$|n61RDVjRS5=f2oHU9SeDjmGGK7JW3fKnPK8~?cw1)|7VP~YolQ2 z$b||^Y|lqfU+F{ZTUb{xOWx`l+Y4Uqa)8@XU=@s@jcVf(qZFOA9z{QNGnFbZsGj;DD8F zHXP((&E_dFM;LfKsD~y5wgMt;1wrQ6= zhBR51gCLD8VRCAiH4lqlF$CxXA07}s4DS-vaE-L6BAbplBRsTIIg|`=L%m$P&BE!L zw-da`&~rNu#w3z?peHeX6CYu-G*%W^MQSjS<$VVl-xH`I+YBcgZ)MX|>EkXk@OH3s zu*3tF2^b5TnIggf>?@2F5)gY`u0um-W0)JsjS*yE`=b5Gp`8{oAKD!a6iq=Y>biye z1Fewv8KT}vRS4&;e3*Zm&F%iUEd*%Kc9$pj5<8@sGX5Z(z+ZlOecW!)za9Gb_!OU6 zxTjB_$yi<{1jh{@rt+=0Ew-sEqgj%^bX zetz@H69-V<_m|mz4P_uAi<)+LCiW3UmdpgW_{QO;k{DSvh+baXQWZKFV~L6C!mOWD zP_3|w2mT7uhBH7}Bx6ny1BDguo53IW{Ygg|D`9l$=W$$)Ag+aXZk2RBH}ylq)}5Eog;nb@t#7 za^Sr)Gq_lg{5>WbsIMHDPGz_yBgt$hgIQuFdp-fgD&g5-gr#R~vg%4H{3G|=H?Zxz zc?Cr+c_Inj7>)@O}Sc$(4b%6Tf1H6xi z9_QCn6aVD@C-qw{pTMZs_)om0Z~w{j_&b~!Rpua0C>{^B#?x)C$|YQ>u@ z&3xK-=uaz-f>|@4&&Kl^GWs@Urs25%qWM#p#C@nGB=aM#YJU+x-SNb0hz|Aot=xs~ z6QN+o=$8UWKV3{Jz&;>PJUq0ITz2*klIWhdtCi34KJzTa9&{R~eu>bAu!e=lb_@ek zEa!`EhBOn@W!!fYOEXqTWY@b#4dwx$?-CiE?Sk-EA(J^S!fjTl5d&e6x%mn;XS?B> z26*-v;=z=IOXFi^MVU#&3tkdxJns%PcM-@0&yHuQ!oMt*Y}46NM9ue6?~D_y0F(R@ zCi*AOR;*B`SWT{XerIA?Hkm^bwXp2;iqj@A7HJ^pq$o%TYxeaPc>O&IL{e%Z9n(2& zo=vv0aKtA`ST^+Fb7{3Twim<;;cKf$V;Rt<78dM1+!&x+I`7XU{t3GD!NHR++1jdD z3uj_n9bdiIaIBh%;qZ{_-}*Bhe#fck6I`c;c^M>;?G>k$S39WaX!mOvI`VMoXUTeE zf{VU5Ikynlh=kU1+l~%zaBM<)P>21TaWJE1(%Xgkge`7r9;9DegFb%V+~L$dJ8rh) zBx8m{Bp@tBLbk(XA|+h;>j4@h2_RpJqFtequ)Cb9_PFl#VYT#@BmbDzKcM5F!j3j3*+~fP2BDU}OwS zWSwW}Yyvw@n0O{7TO8hZeGpC;}8xn`m+rCz+?Iu3e{nDyZL@Y|1h!M z*nftx4FDy%IJC>DH4N_{_c_QaT2btnq@sQWO1)4I^|(__00=a%a#-Usb`IAbD$sMB zO9~N|5ggdRh7Se82k2-PDjnn9YJY?GfOccX11sXC#2tsn$`|C?NKoGKxO89>7n#H=xq|mU|A9>d*WYfM6ha6qVsIjEZ9QyPA|BRc=tE6et@E}sp|UeOrl zu_M}9ix&RLzJb@i!r)b?R|A5#4DxD*Oy&iRuu*0m9A8O4;~D8VV5-lnI#*Y&b)r)%ZCCZt|*NSNz>qVEfM)<%bL|YUi8&7yB>bHA8jbh5E zgCz|fkT%izGRS|G2YMP8-edHr+M`v3Sg`eI(qnh-BWN=T5w3$nZ^C&eq~lTHM5+Q@ zFkZS`ui_}rMwf(S1@X?2)en! z;WWY8nCPg+#40+2`yNU4zcA*qrs!ZGZHnk(`jPsN=?1jTnkF{`OxmP}I#Jm?1@KDP zwHDk(cKWGAS#zPSrzW+Zwf0D$e9e*Gfho~cr#ZKJqu!Mml2yIE&@6=kBkX{&$}?0u z%bxz2xddW?1gxOIFh$p4Hgrev#~8s0X_nFpgK}vCT8z8RCm6a!+-p3?q72`Q1hwg@w1G=pvdjwnRXwvPi>^4nU`ND4de0s|dVLl#b{%e@y zNgbb%BKmO@e-lq?=i>URgEe#z$Ns^~WpMxncCb~nYgP}wZ#r>IyKd+W2N3(`oy(3% zG}+=k-dHI34C=JEJqf58$ckc|uTpXeSNNeM3C=$*l*3FQSEp)V2~)+_M_bF0aWX*~ zl^t?@4z2p*BV;bJv#CFk&#f@N-wS40S%!CE&Ae3pzlq%|B(Oe>9x%hgOP6(?mVi-@v}n zd3W5Fw5i?T`JN_KFS1-y8O?@T5JOg6`E9A{h0Sl0upfXH-Z6CH^7K-1RkuaWVzy4b zEwrT}Qwr%QDW)G3!ZY^Ajtu2>d#l`fyVa> z|D|{XJMOJNiy(QN`tR;UgZD){SZl1bz$mW4Qn(kYx*NXD!SNI-6CR6v#>~sLisPd4 zpIGOLvW`A->wMHOn*2mW!-xYaHv_5b{CL&uK(3yMe?ma&RuKj1=0!IE=}PY~Oa8~J zDtS4zXih?wzyWQ)Q{;B%r?-{fj10luUASNt1#>A;+gyrSSACt}vuFOOB~&=7-6+h5 zhv$6&-*Og`=uhT;T1q4fnL12-4fe|ccA!2}j+iGa*?B5J3Tz5eD20A5{2xknfOETx z=_Qan8pQ-8Z8~dB4h4f?aiBoPO|ugS!Y#MQ;AndCED4d~0$QW<9(lw{9f5~# zHa&U|0@xu#e(lt z9@7Oy+7>aDD|jUMX$+yJqMXb4L^f>1vlIZ%IxrNSb(5incSJd}*^DEqMg>g|IYu0? zeyW)^_q3%>#0+nQ?ihLrtn`5V>HAwSAtKx(foTQE4obcyS*vpHLW_=jq6y7YQh|F+ zVP}a{But(Z(`hE8&rqy^N8~0(N!Bfv31&Z{xmb47_g$wSLBaf)w9q61PDl5yH6DBe z7zhCKAA#aVB9R0z8SzsEgO~<#zXo7hs$j%1B4Tag|zLo z+0`7ys+ywg$Em|C?HLoCk|vqgHiCeO+jGt?x>nL2bt{N?9;3n=tRNK`1fzvPqq$|Z zJNy-Qc%}#K+pU`~{{U~EnLAeiUAahSI0c^pIb@~Fq3+2;4*+@t_v1v~d994}^`rIQ$!i za3Qk!GV5Bx8AWU1m0!nsMrv?44~r2E-w0oWk$i25pYmG-LBSNi=8=^u~dJlqWNP+q_D)33jDkl=@~q=QuxST{fvKRl%J`u^stlYb>N z7_lSbGR~UVbuHjW^-DHjV$rZ^I5QM~4IxIyX@w=AJBMw7CI||z+oTI|aS%sIUpX8@ zA7unHR-{WISnWt?rCxjFVhZXdGeg!`sVW{CLF;)6ZdB z(IFKjeml;}Tu-0L{j>$aDG9s9x0y6=!ZC@E79VMqCaa{{+~zmOZ;m^cq705X?2`Ts zDgRYh#zXNDSvq?y=v5YMv_RHja&VYo)?wDFyA=5 z^d^p)rvUkadFQ#m|K#avU0es0iqi&)@}IL=ClQpOoWX)fUtq|It*iGRwgpoR=e$s$ zle&;IMI^+{=!+uH7SJRFNy53@Uco%-hT{xuL*81LrkimsncQk>!bak8+-rUt30;(`OHS3yI^E0Zqvimp zSlw`861`ZqV!CTH^9_j7&Y)?s%({a6btwme8PfRd#%(sa*;ah6f{i#K^HMRu4!$G3{{StWjjj6S9*2liG>mSfdf1VMb#*D>ug;Iy} z{`4)Vx!P(#PsW@KGtY93=pR4|p~k>JmGmDV!WoV{p(+MAijC`MUCmC@;14&5s;RCP z923tvoiuK19VV3FR^zmlqvQG>!_It*Ub;+& zFf&WOG=2%3Us`268wcMa;r>G!W4bi2!|4kl6ngn$NnWIjQ??+muw!VQUo^XjEuI%D(^^p=cDfLN! zrG1#fd&r*2My)AZ$rDy$l!JkZp%fEE%%l85`e38jVD=QGm&>V-I7y2lFfa8u{~9>! zZ!w@sEwjIxBuTH*+iQ8pbmnh;IPL83e7JeF_sqEXj;paWw~Bkz=74fyl12%yt~YS! z1mYVdf=-O!AiHQXuUx~Qr7?tV-vWUaBu`FwOY@Ae+i9+0H&^?Wy$cDwXjU>Eg*2t& zo}(-@VCT+s1^e#r?3|oWx-dq^9BHD!nL=tT`OQ_5qzkwf3!K*^zQ+c^HSu;py%HwI z_Aw7U(*?4zMoC3~cicI>ysXb_3F2k2-%#gYg^61y!!N1jc~F zH(3nZp!G=AG_32x`=XYEUT5JQ@gOGu^=%2@!v`(pp(M%qnWs}BZwZupQf>Vrl1*B%jgui??FOGXtUd8;b9>RN2+o$I5B+d-ADw7@FNf<+LtB(qd~GniiM)_ z7_eSuz1}Pr7c2uT3}{s&E4gB9m_`|_wpr?#xT5C$Bw_4&)qkq7C+scqWcqVpybj(^T9_<~jUUjMT#M^w3Iz|0Wm@HKuhowhC@)m`)iq zln3JsfCv(!PG8<#A0CqM`C=XNcbaDYS(J|pL_rGe)S8*31rhCCNn1vQ0Y58Te$g=71L9^FvsjyF`YL8 zweSAu1Q(b}7MLK|3~n$V>7+yhImM=a;Oc7O_81Z$HM4U_57ZrXzbiRJPq_x1w0y}d zuv;8n1%+#P!!+Pt-G#lG0kayKrgF{f0{80K%Ox9(Gen1nT6TG;R+X~0783x07!5!O ziaO$$HF@I!?h?tPjFaO&wIN?Fs0+>;)e^wP&ee_2$o@F30a@Gd=25x*ZMp`Pe{R~M z%xC7U319NLuui~+Ut{#HW^R#`CUnmd0bmCj#Ml~3zlQFTumcsR1M1%4eYFl#4eOIJ zVj1L^I|Sj1_%x6=>ClXXqb>EfxLF>3LXC{~UNR!KI+R3-#~W{p^}w`Qy--#^o4#>cnE8*zgshX}viu2gHD4)nZ8{X4<6p4*JzI{nl}(&3KX5MNk}?m9F;~yy zDgoWijhtBth^2ncGv*lm<6rijbtRN>l|7K-q;s2>*0;d*7G2kq-AYhYy8^KAXqwDm z;Ckfu;{kVmi3i!#CjsDa_CC)j$`ZV5!2z31BB4|Zd!u^T%AS%JaZa$I8DwMim1HrL)v$A_|?D!s{Chch6R zdRK6(9u4tr@{O{%xdRxA@}bPaQ#N50HmO%jSLmZvKpQq8hJ0a*%o?{d1`t#dBEA@S zQ3@3|K60!O*U@ar2>qrwNC$?xoKx}nDf{wml(&%h2!v^l#q7;n&( zNGn*q9Rtv}^R)okY|k38Jqz12gwvz4C!f9o)kW2Q>>Bgj=&G9vjE2+F6*xUANQ*RKX>`8iahHbJr1mqdAR5UGVCXHuP2iY|o77b5{gbOPtnn<%)>-w@N0w+zBISwc0hi`K* z{?ZOh1SjnstbhTx>Hn*!#W;-w-KL5-S5%lJt5rcL1|*8LnYqNW2s$x~eo{g0KnTkf z*1VhdI}ij%+=975Os+&*3pU=b?BpK%`{+%o_zfFjWQL73DBkqi8J~rYmVnqHPf~pg z@yk_iF{v=*l>BZq&$tF^-)E3IkkdJgu+JaCD%&db>$h2%{4%@2lU3BhZeRzmI22y3 zFH~qwn(^Er(G;$0ySb4lRE(nauvr(8SdBs6Ovl+r{?ICVaWI~xL7K>pbw11x=bRvS zmIPhMfb`2e^TgMJRBXO)FSxhzJT{CgC7;Dm9htMUvu2R6Y*|^D87vC$F<$n@88OVm=cR za*_jO(By&0aqyd7%WXnGwDtq*g=fo~l7wElY^k0Lejb2JB7jg(dq( zaI|=>mX1>poxNlBhQnWGdII_rMd8hHIA50zf?`ajW}#_{_hEkF53w=??F8m7=ZHk+x^t|k`Gn%6T+ zOOHaCjpkh=^ff&JBYbWYR%eKA@%pujl1FFstZ znGhdI9GlGjafImHkK*ak)=c;3|$tN}nKeum?0eTbQ<-*Jtl} zXSt%kry=RqVHKq@#ceh&h%Xw~pEdWMo}NMZF&1G}_rso$+=i(qn2CH_5hEstG-HIQ zn&em}n`6A|tQ2*GP9b`a!@b?zUD?0bM#;&zERwO#SK%^hi(rR_99*k5HbNX{J#j=3 zCvi-8UGSZikW5Ed#z4kq_e418jA0xx(Bk9qsze8g@G4^fa=K4l8=d`$1cm&Q|0WOb zdY|UBD-Or{@mup34hmAVFc)}tSlAqH5ZY=&8Q)ETshj1pQ@n;x>P%ngJ$ECcXPSAT z6|V$tSkAs=DZ7~snsm7dD2y`0Na&L@^W;EvpfbLdTTL8pY4dQGvpbPCQ!*FyVs&-I zO@|`O(QRP-&Pouya>BOG33g4V@#G5v?U#nqj^tz-H;ZmCnGQEP!KkA-4}33p7Cc=Z z!v_b7U*abO_0J;7m!4TX-FLk#93&1T1bqJIghx zS@CQP#fv|DtGP8qJ_&>e|K*e5<$|HPQ{fz+YT5~)EMR#Os{m;OFaiVKCgb!D+PoEc zzlwTpUpRLw~ao}k?NcK#zCvga*4gwsV36D;g_eL>IKn})> z3lPApgB@kC-I(U|n>;E%Z8iW+#Meb>zd01IMU*#pf8E>tJ}$raxUk>n`!M`|!$3W8 z07+`^`AeY3)&(k&Os`3i5fg-s0G={8j|2YAMW$Rt-;6;#=?9K%J^tyEg`^*6ac_*o zNRRI*Sl-F|;`X}_@5HBZe47Ljr zT<@b~b0b~cgNjP~$No~Z5FboQ((oO2Up2m&d5XK8&TEh|U!bQdCJ08XP>WqH6tB$& z0gdHV8;*djD4ME3gHWl4QHLZcKpzotm>w)Xq(qk4q>k6rFs?W}zX|&YL$R}uP<*;d zL1^T*~1_Y*I0%fGfv z3N50h9SN?rzT6EdUYO1^3%nF^j&g)0J*dd}EYVxxxB-qYuN(e#=WWCPGq64XLqlEJ z4gVxdKV~!fa1r)rP5jgFFHe7Lc$e=_8~)qu7TKv6c{ZEg#UMKV@y7-UbLFf6`)Y)J ztKoMpuc&ON!a@B@G#$RgAQ-VmqU(2j)p{=JOi8NuK z!|O>*<`kF;jLQ5XbCp)1cB%UASml`;+(AnLigXcP&q|`vaPY|Z4rnWXokb4#m~kPt zD|BMk+;2{=ob+6D$SG`|aNt(0fvk@(+`#}bHs}prCP>du`xz^QwEY|ld5-@sO?drW zroEuyUB@^}vO(#eD)=1^3LRT1gNkSz`O9Y#_|J#T1wkL9AyTIy)K?J&X8?pw{Krr} zk|Z2G_K)R*c<y!V)`3Za^h!1Y03nCA-N$(n(oU5>CM^Sh>lg3B?x)B8+bAjY9pu^B6jS4I5l6%5 zvH$Mz33f%%h)CkkickK#M5{V4(M~!+=V|=de;>t#c?~*a{Kupr+|tiL+D+*glD1vV zNMn9{)uF?d)bGc>evsR)F)Z}vp1)GqK-#mSy-k6^6zsl?gozkW_M`Goe+9i5EljJ={TNQD`s+9`cL=BJW7>``X7k6K5Il?o-7R7WsFNfc z4&}i=(1@JTDvrja^~RG{0&nD$wy2_70Q6-4RWb(%*D$0qdDb1^YgOX7PwL&PJT5<( zHgx8F+9he&>{B|?d_wzdHPbs&L`~+LS2{-DwD2Jln+6Xq3~xU(LE4D6VK~O=m)2eN zOQq_*o+mVcPBQJ!w_!d5k550$o&LRvXp+ZF{4&K4EjmKudroV&uOcC|=bY-uO^;wg zq6CmN_Tw3?jO(}g=SMU7o{~!sY1TWlam`}C7*l%aF@r)muS6s2&@1IfkB{J$K&fK`-5dZf;j+P&2 z)no&jV)C*xxT^qY0@zQQ5&XS1C$XJ+t!myyK%F~*H}*A2FNNbte?K>Cog=kQ1OI}0 zOxNCdlEk#*-(=kwgUR1o-BB3K`cdLoVxpYZvyY_>Z`)7Nu(W0maH9XnF=t;dv?N*C zOyEU+kQR@NT%m}_FP%A!Yo4Vh$ia<&dmXV)@KyXd<~)fDt!^CgjfG|=Oygp{_N4kd zqifPpL%Y@-DDuHmP@?QFM93Vkx+$4l7^O zDw$T5NK^V!i2?*L`^P8Yu{$n`S(sM5*sh0~eF-YyaqO+#05{>9E?BI%PB%P!nE< zB#M)K@`hx*zx|KowjU-W#?yK&!!d1H2>duc0UH$;Z;cah>S(EEzbX|JYR}i)d|GoU zh^*43wn(mii+-)Pw+*L8b6Ae|zt4~F^W&lU@z?VE?D#%AmS@KxL-=9v(m!~zlofe3 zPw$lh>JkM{0Noi?Mj8AjV?X1#d$zkY+}pTFS8iM9Ny|Tx(oF|C3HAlae_i}-^#KPN z#B_L0H;A$v51X3cup8_jtRRg(w(c+LZW0Rk{1-!!%Pm{gV_YWm>Lw^s!Max=XEItZ zvhqE7OdMG!w>-r7*2?)*vnNfh%9^a?E$P?`hY(gucG8=eep~BW0wtuW3lct%t_DMY_Nbq*9NmL>W&$w&+-Kyfyg!ac-nexqqCkNTrPKMoHGqqsZnsIAiQ2At9bY@+*0l@h&Hb zy3D9c747m4HZe&JG12)ZcCLyWW2f>0v_NFr;)<7bSb`4cl%#&t#P0xgc%)qdV}BEg zQBhI0n1wBfwQ1Dhk18Ab9SQROBm3+}h~mWW-K;-17E3jPN>*{Mfgo;6#GVesP8Z`< zgWZ>&zB7#x)k-CIoYwBRwIh8s^#7w7-^=%>jOvg^39Pem-V1Dy zx%}928l?MYJOC4PaJC_s zX4Nb7fbWz0`{e$2IJr4AdClB@AUIj>{!OvTddt_hx0r+oPMk!|a31q&I0`{2X)^o^+HIDDU^G}Z({(nc+_*+Kf zef^AD_;;`e>vvRx_>lRfzR##@37LKa=3x}aiRNI z-)bHSwh^5=W|L<4Tld%69T-c-v#quP3qZy}?zQKuk zcUiNKHCjl1k_5O}7H2mrMlMyYsG?NG_br)epvmcHcgnoOeA9H-{uD?gB$}+I8{iBa9(-F?2dxAzP@ zEPIRTtf%cu|19dxhU~1paUy>!-CU!6E!mX1wsH99{>kOLj#MMav0v|To-}1I+6`X5 z3=RS`d-vJi3;)Hl#pJ3ROM5jdrXnEp{Slq*dCCyz%4K6?m`%+lLR`%Y#RwkI+Ax+Y zYW7yttmx78+_roMTpBnypx(D5MYB=pcv8jBHqwwkoAiM&u7EI z!7_S9JL`9(fK9c>^Zl4EF!ed74H|xg*T*JawYrZdEk;r&YY)`sB*~QU`1J)pc7>`P zrXJ+x$ltoT-j>JV6BKNdT|f8pEHU{8fQgu;67>qr8+CN&+@fyO3*pz#ks742uC@5r z0#ir52C;%78v04kXp^>o+LJ|q! zNce?DC9Dgy4UutwlJ&;imq*lN^0Ae26vakUqMcDo=5OMX(VSi`P6%m{@y{p^pdEB` zs~z;Q`R)b}fn0dYFdq=M5NY-D`mC)@F zySK2-+rCQ6XqZ>MS|Q-k-ajt0>0<9{%??hP6n87KISG~}6Oy(2P$MtXMtsb@P#TNL z@sLGs0aYs*Z&z}svoXs9gD6Uj;h@&ge}evQ(u)@lcKVgIA)ClToLCE0Xm@{6*?*Qd zuC_jY@0b6sUz^l^Ag~3+ZTezwcaI^!o-IjHW~Q&4+)QA0cD~9y;Vi2MD|wYOO>N)S z^KdZm-~Q+LZ~sr~iSs-x5{(%;i}Nw*lo5xne6<`2SuJnM;@%Bj1kabvG3~Qg{(DA# z!%8>lPOg^ImTFWR2V{~i?E7hd!1p6FaS<=+j3llx3FTSZo#jXo^)8b6RNz}qvth%( zx;j<7o++u$3OhE?yg05JGUQ!0$dZ2GzlwA48JC%7iJs`exovnIkc9jQc;xE``TsckN-V@(Ql=!V&l!R=($1sE@cn}KElQ)`74PDET3 zvuIHmRlM{f@@kK;37J#fSQ$u&1ZN1(fTqqPHWdTy=#u2#S)OuTl~IPPnIJ~ilCH8A zB^G8>VUzM?Bnur&$=;XIo2N0-0HqW#E3;-RB^^=N3j#f4?;@~W+x?K&KcUhiTA%BF4 zD2T8uk28;xylbty8O|>3XVcO&2OOXS=!qOMe;0WSO2>#ma0}K@MI}_(yazO%9Kr^y zd9(p`qF$EvQ3tgRq~#3$j|@p_5{EtMjnrjq_F?obzw+q54-guaS z(wR!4W2oIHa}Aqr$bgD<3<|YJeK7Y2H1?H~lxM{(WqliP1k{}tLg1IC#Q57Z5nih# zd5O6L(6>Vq3a!&CENJ<`>Mu>;#?f7`v%82v+w^5UUUY&3mq%28FJkmR`yLkDnBMr# zbtV)RE5YOZf|RkX1*i&WIA94ea)uwJw=p%+;DWtNBZ=2m5K{<|u#JkxS!r1OB1>*n zl%Z{g9y$@EFItF3Fg2W{KJG3I9J;1G@c5ZVa>6X{2(Y2BVG$|OeSq3B&#cU8ZIH*b zSJY(F7JJArvbD+H**~i`y#N8+64b#7+Bfgc-gzt(i$8{%E;jwXfqGweDA)JvqdvZ; ztpObbz}2vZk2fY1`}N=c&tZYEW2CT*S|nTGVNtmm)B@Jw9-UK9msDK;)U^OxK(e~c zJVdyvW7le2B&-zVnWjAFyEo85pO7glULul*}-qiB@iH^B~KYUlUpv^os*H zc3A?3oCY&0G-GCh3asM7F$R{_E6j(pi9%?EY|0L#DLoPl6zVXiz81+nAKw1g|E3HP zN&?9#-m@}OBY(mmMHP9rXH$1-uWlY|-(2%gRu{rC45+mv=E`p4(83$3juI!jzbJD_ zp>B_Por=)2uyXdDED079D$5J%t4WFnnC(QiG~(kPTy}ey#s+ZlR6_aeZ0)^xXyVLIIbx*}4!7WeIgI07>4_hVI4SV%P$p?;latf4t`k_Mk! z$XXHWJ#fu19~o=tS_8_nwx@5LN5ES|Uan_bur68>0lb~w=q`$Z1=24!m_1O`K>xeD zzt44`aq%vNY&XW^;Cl+u3T+Dg)Pd!?QOIVFK?Nk7T6&7I!wyO=EZEh<7^-Z6 z*y^oNs}`OQkJNQ&?dkw6W94JCPZa!AiM7zO0s_Fb$!%T_-45CY8|RRa?r#J3&qXJ zxsOwL@RG;Qt!57_ywBv;|Bw~_P4Gj&8C2)-$F#5Mb3X+5`8KG2Yeh*El(Wc!(O$!g zOK0XqHWa<=5G#b;ijQpRXG@69|(H(znO%czJ zT!+n~sRYcZ_-o>tq+bLFtGwJDvENnJ=J#d;tb;LW{(Rx|k6sWO=CFSovZx_+fXzHg z42H2mR9X?3&PE8EGLG;{A;{=+h-PFt7xA3xfUrIjk0b3uBe+nDBiKa7(VP>}ed@TVVp+V2D?9w}%v- z%4~L7?r_femi@(`VQZv4W7>Nb?JgBYVq*-$`W4HD^Bhwc#t9_f>xgkDo7!un0M5ON z;lG}$6-k+|vRR(S58^?67Fg=1updwSlK?@Ww5{IyN4NOpN!FSpv%a!{ETCXbhcta2 zfWZ0zS+a4|8`J(1ru?b(=c=}EvySWvdj5R{eP2P}SI`%&AW{&gy#u&Hf$_Gicc4J~ zlnRKRAc~k{Rn|4crRXlRbWF7_5|P!_7(o@aF*dt>f?>~sHQClkD+*R;_<5>YdzPhT zsVQuR7SwYIaNzm4#p>O*CFrFp6DK}`r94&wl)>1kwc#EIOO0n;(gUD#0DIwMi^SqQ3>bi6BWyeFsyrHq!*iFm#=ZUh#ca%) zZtXg1S$#VJUf`^cWC zuAo_F&3aASx^NmE-3~{$+9Bv@#cehLqEY7qRD3mY&na^(mG_)z3!#vbl?v%#5=&0S zWt;E4Z2!UniKG;;f-m$O-qf^|KX9(6$Q0Hen2F0CuEdD|8l$c9B8E!HlWzpAcAYNil zqM7}f(4d9VER`{5k(oAPk+AJbEh2e?L z!C_^;>H<>YvoJ4Xz(?nj{0z%D0>4>Q=0#rdycM2!vFS-kNS2XIq&j{Y9p>y1qT9?*NR-4+&L+Wd zN#L&=45A1{`9te9*kSDMFqtLsJ#7j2(;^K~cB3FpjK;vcwm|7b3Oy&{2R-@Pg8Uu+ z)k)-tsAt|J;U~`G81skLeend$vBoT@ICekIV#MGamHf5Uo5itz}D$h|>>8VsQR(5V!0G5iozKP0OWhS4=$*+&izXJ(?IJ$@F)ed!{Thf7gjW;Tbgh{6f&iv{~2 z^|+;0Q`0<0^HIin6ESCP7?KcJ_%EOCynM0q_GX6;ja{k1=;K(M{DZVXfBu}XPSWOk z5?R8z3hU8b-hv;q6v97yd<(YS&4_d8j>^dxXYnK)#=UA*Np$VijEf}r)0&YaKqqER z5|C7=i!kYixAa*48tB*7IL+>os6X5=k16k!2~+4CJbkhPL*1yw2+bE6$P#@E{YZ@m zEYkYST{_mGFpQeydfL%@q>zBe+tk&KM${$XI?$~4e3o)FpgZDgkjF?6p$xE#eiT_qoQE6-Ijl_5JiUlqIgfCH9))+wVYMAJ7j2utAUPO^FlBgN9%`NS*c)8_EWd3>AQ z&;5g7R}|U36`Io}okr?5?XjGoNut&8=f8{mpagS9|H(oc#3i2e1b zZ$G!R8#i+j(Yj?=BM>#ec(G{IKGW1%T?=3!BW3?0+K%$ z4TZ>6x)?ZZ(sBn&C5AX~u7-jb{YXbmN`hB1SFH82Lc_LnUh318?8S9?&LIobFbQ0T zNx?Me#qFdu&OS}z`=G};vYYW>(tEJ;?|`YF!AZXa5N^yVLdXMj0EH9j(+P~&VeQS1 zaU?>5FRH3po8Xdu#6L*9iPnV}egsyxwYaxTiiik?5}`Z#T$-H~pP1agZeH@HL0$Jg zP~%GKpKxqyk#|W_>%~@>YmeysnEDqW9D|MhXsDlB#!0&2wx0E-1-cs976(rjr|-0I z5FpUoi*r>gSYc^YpNUS^sutcGR0r^EB(jqr+m8T<5d)=QGcm_`J}IUn71q?b2LsjP0KLTh3^Py_1egms`e5zwWwF7 z#L8~=Oqz#G8rV%?E^;M}QHZmP)};=il;Us?Hc2BY$^$er@1<%CTy9-aDdnL6wb5Lr zIin#H@t_1aG!4|OH2rb6YMz=1`BFLR0hO3>WR|{4GOt>ri9M40BHRJ`7WxFNii+vS zB<{EifTJ$Bu&k)%HjyxjkT5ebnM|)J<6fam@^+LPS_F||L+;5gSe5+Cop}%dVS(*5WX>c1DCF~DEY&905hR9Va?^Q5M`Uga1u4M!ov^!*<{*uNKNtE zAPI{RH;upMWv@vUuG0;MQ8u7mWga9EojUy%4Kazca~vRF-#am4q&QC#G~O>4)TZkzihLD;J*@fKEPt4FEqnz1sqXaBPyIk3QfkoC{~F1zNc(Cmp!+A zc3h)F@N~zUgtAL2-iMj&XrX_w-;hY$Sz(w=A>gV8?aAcwx zL;qhEGRtK_XiG5?BDo3g&7VB)UmVQIiut7*v4I|0ISTVw%jLrICQT7-MU`M=lyy%V zZq+R;Aj>0C>pal4+;oAP^ueg6(7UTJUaqt7xQB#^!k|*>ORSl6ukx&)k$#oMA4A3| zAK-_i)$bQp$WhieK>D+q6{a6sv@ZlExjcVXJRn)PT# zO`yOWeN6iNsYMeeOdN)YpR;5z1V~xuQx^58!aMpQZt=g&RYn3sF^ruQBDP}uJc`0H z0bm)1;mUbZ?~-WG41x6jixxP43l)#eLz;lptdSBIpD8)hda}6jQh4O5(!jrNUtICod8vKnUna>6WOo4M zqYHNvYM!yPUq^JRi}`cw=j&J7^slkN-|xJ=;RFSKspt-pQ96<+#Z|YTue<$SXJ?;r zvvkpH@elTL`|{Ks@G>W%Z)b>qaTQO&NV!E2#m5=&H_FFwNPa zv1UIvQp-g$OF#KX=6k^3Ta(^s8Wb@CT8qu32gTLfd+xt@_A+?-VmUuWPWo$?@7vkW zm#9??%0V!As>&NArTwQ#td7L%%}$9k)>f<4@5a zI2FTow_N6=9?y%W#Q+cvf1rPO2A{V(uc|B>O(!DdChZG9@V)2R7~(<9HvaeL$7hV> z@N=iH8Om_v)qGiLw7s#Xqbos3;P!FVss8Vw^k#yRg9S?k`$k z8Lroy&o?7h(2QxpKqE3*hGl5wgub2Qx1G!8sm5x!39yViVSzHd1^5Q2y|f!elPQ}v zjRjBfH5}U>FJ7H+UMcOu{EF_Qo;bU=9`SX#Mz=iL#umtMo$B;)kWFaNNGvz?0EW@P ztguYbCk3&9_zh{vFm5i@!YQ{NkG0gqX1us05eKIZ&B&PEa#n!}H<^18a3A!{x_hFP2hzm=Apc}QK>W9rt_OqmjghLlr zm%V-eU{NSP_TNhE9_X;JJnODLrv{!rsV!V^VeMEOVJS&}ESK}-LH4buK5r-~qK$B= zDt zorhCc>U~imEw6YY90*e7??2v5{~9&B$t)_fjA3tA5BZ5L0pEB$!CRX6HXFTfN53|@ z{|ih7>)vy_#CDlEZ@4CLO0P3_{9}iH2uJXP!+vr4?(Hif36B1kSmFO1gObE~@4+#- z0vpHoA^8Un$^G8mgCp__UHd*D|KI`n6y@34z3VTg!1tl~M-7doNLV=_j(o7_SpGf? zn-9ZXU%DUhPkW#|eEE>Sj9ysixR8q=@roCDHkyyKd1B*0=z<9meRZQ zBAZfDj%EeGU=Wb)NocTxPyeu-#H3>-c=NuD%3z_uB%d~CM(NZLlbl3vYg(c@G zln<@6mxVY%mXh-%OfCYrEGJQUDeV9luDZZ`e6T{;@T^s z$cJ|X13RKCaE~Yj0q1tEgFsu=;r@}TT&+kh+oX-Jofh-nC_)-1C$S?AdKoXMG{{!4 z3$wL&#xQSmGc`P|x$Ja8%ult}ivH!xD&QePvBFbaT*t9q(W>^s868TD##f=MaYQk8 zo&G!xCvnd+0Bl7=@Q_a>SnZF01c0%!!l*$~Z}G+a&&GCcTf^h9?Yl5f8Qg9X&T)D& zIyb_#|Ag2=K^-opGf4-xg^LkmF?S<7=f2mapflVCB^QLbNB&M!Oad?8kknYr9= z7&MnGM~;$&ky>}W86-ImstI91vUUXSz^GtVbxnmkDAr7?-%`uN`RQD|`D(`T zEWk3JrJN{QT49fA1B#fV4rqC8+G(>KK~`UMBy&)jYMxtfw@>9(mE{fWKx))44j_t` z?n}4zk*6Onjqo1u7tT5p2;fta#=*eHTD5)l@45{knTNybg%J4p612be6w0y7IH~o^ zjosgUTa%j8tozFXJ~PN%;qn_>(g<6<+#E;*6vEfBwn@o~XS$G?Eh6E=`sb zxmc>P&q}@pp%#`8gBzMhlFQOlXy=9;W2iWUwne*G1;ZDghD>>FQ<-`udrUE9k;cN`*x3>AhYVWW&BA~_*4s26q0&@}v;ztkYqq%B+tH!{({It`Si z8>$X+AKTD@)4(I#&yjzlD4B|mzA)%ilUR)u-;GnIK4~7)ebh%4*R#;=qv{UI_Qe^4l!em#7DQj{1 zolE|CXNI+)V?0oZLg^P-F(N+w9HBI6Z|`#060&<13uj5p0JcNK#f&CvcKC}Kt>xRy ze~Y-hx#Vv0FRfI6*$m6f72h7*)h|Wz)WA}K%Qrxg*NlsuX&Jx~$Y?{e4TL7)xEl)OWW(G|k*L=|W6kX;}=`4o2TG3&M8F~&ZU1*YCkMS@3?QoAVE1JJIP)hjgXd3H3Kal;IK8;k zIps_#)DcYQ_0Bf{W}G&Gj2v0(mZZznCZ#=_0)ISZqzM|-4l_QDvZU{V44?vJV#)G$ zYVs;f0Dl~pV&Y?_EsPt3eGAtWy|sCG4SI45G2w7=_;hKVH{*RqlB9n&OG#kP@wr9I zp-*2cql|UaY$_!WIn8X3vlf>ua@yez-JG%-*T|SJvJ9|VoThi&zH~POy~M?}GC`%X zCSNC6+9mH4L!HNbXiCW`>;OiZ{E~*OH^bK&N5%acWL9k2o88H87oIQ9POiUHZpLoJ z<;?+B1oB`X>(x%jK>|&DQV!gNbu;b?rnlGaJ1r*n-w}m7{d5q`RX|+s2YVo$-lOyJU=fGxGjpFmH?>l&?zgT3 zZ(&Y<%|h@N7J~oV7lQZ23*jV6v%menOaCnTNNu9Axd}hL%JOs2()W|Ww8E`3vh``0 zlb)1kRCf5W*FsWm4-e0RY5A{zkGX>!WzsQ|NlYpuiqZFJYXZc|FwL{x_)Di5N?iW! z{}T^01ZSrq6^T>&R^SVs8VxdtJ`Mn1`M3W=pr*1Oz+>3th96pE{-FW@jNt}7&4#l{ zH`m_jRo@n{5;mOgqU!Hsu7h4~{{caxKG7vJ(r)uw$#0+G)nxT9=#(WbM63Qy+wGT3 z2n;m!w2(!Ai=$Ed&F-aN+k30^A&K#DIha__S)gx{Hh5vbZ$-hFBXT*#jhZ?v$N%&l zS&q?r`(ms60vj-kQa5k@s7E}IZYp`>=FP^^M!jmv31uj>T|h-G;&L6b%n=vTe#-N!imO*H32P9o(rQTAJ`jE#GgG@N^Yrtgsu0C+%$zxL$$GGY9R zxo_^OCVV-*xH`XAuz#Zzn&fu9SGq|{t_wN{v%zc<`+p9L*A>}Frx)rW5AxOi;YsjiJ0#-Th@a3OSyM&maKXvKy=!*%cz`NhjXOwKzjr9DO{ovlc zSL1pN>!WisVoj_DCqb7qQ}3BGnIj})rEO-3$+OAF8nYt2Y0gV!`GW?rhx*0%VLorR zyomF^{qIRX`ef~v!7$E4{L&gu?kl;Z9cBrlBZtEnpzib~nBYrmnkCf6AU2X1Eg}+I z{&ELj;536B9s(5qx`<(X9ghK-`8vu;f-F>mipSBY)eT4KC>sPt0)XYIPY)KhquJ^A5?_Ztnz1TmHxN>6`4;Re9JwZ$O z6;INiB=!@aaR@%=C!V@i{-szT(~w_+r@Onpfk$QSw-ZJ6cTrL!UlA#sYl{RlJ8PKf z1<*RmQbxPtuYrDT^@=D8W`DKN)*FuC{UqVUaYThYUCIHL&Ww9z+PY@|-6{OE_*^7q zC4uG6`Hvo6SppbqsF?vQ;6z~8yDrXF4Ny^Zh zG+8)$UYwHVnZSYygs6Z-HFHjLkS!`N@f)IZ-9~z*k;Y?ef!0H0pjv1T|Ce?MpZNPI zp|knzMZ^E)`bt8>!iM)t=julMNxi)%>3WRUK?q#e5wQQ7pv6pm>u6BxNGzf0xf%@e zGX4l}NyxyuO^I-(?xr1+2SkGQW9EIU*Y|B*2kC6W9`Svgb_aCq9V||+w^D-Iac(sw zko3rDrTd~SqwAWaY|JR|tw;|d3a_WY70rG;k&41ZIG=6oE#1+x;OkP?nvSQ&Pv=bs z=9!Vj7nkscJ%sq2p{zcVzhC-K5fZ+l0uG3Yn;%PsE0<}5zJ6$U zKVMw&ryKlxE>rVn{PlSp)%z7i;xj76Vp@#0QPn6b(d3-kV}jT_ovQ^&;x&o5&4krJ zbF1DHE|4rP+~2Tg1P1tDe7Y2zT51v#ZPJihjc-pf00a_Jm0{d%VKR!WH;yz$1ql}< zK^J^#mrP-7Mv5-$45#fU%JVF58mu3B1VE|c0tqWIF5yRQJE`7Wnj_K+F9-rzpS-#m5YvNc7$q^Vu2UIm@-c*~SF^ykN^OM>jbW7+;k? zkUouaIx9XIt~yeB*?U?lWtxE<;q4f{?>z3#)R1gBqj_In39p&VhRxVyZz$)qMIf%& zBsE_gaR4^ZirM9DxwjvsstdV?|O#p`iP8d%&5r#!D1^V-xP z3f-LPJvFWdK#`n3T9YiIN8z)m$Qr$1WaIX zWV>uF$J>Nv+DSM=gi44nK^I?IG;NDsmVT4DmP^d{-V-K%efb4ux_9qS;&M$8CSMQa zkMWS6(zjy+y9f4Iz{{QF*_h5po+nW-44{OwC**gv-%LrG-wmFUzHzWj=DFf^+sD_g zscVVsMF2HuSD}Isfp{wC44Ny5W}JeeC}!S*;G@*$nrdP#6trI0`L3I?5v36j=P|08 z^AJ!C@z$oI{#`id`Cbo-*E}euwWDP|@YsHuGn`jxtXA&D%u5ta#+NP zgl2F@BQuJhjsVcJ zX{UL?w&wi@M&P*-8IeyP7g;_j4-Y&A9ARS zqj@(2iM2P$gvYt>f6V5J+q+r2SlI12mW;&;r z@JzSaj7KAd(N0Z*(3lRV@mh35&_Vf~QA`p57+$9IwN>cXZ?T~NS|G0z(7`aB(FykS zp+L8~iHOgnKmO4_XIrg*%4w|iS@dJaR?Rc%$C4#f?456;IPqU+{UJxT`c*+xDdu09 zA;t(?tH4IZkyJ`j4~DUR#y#gc>)pmq{-d1i(^h|+GQT24}fLy%yoNXj8R=Y@QWAx0QR6Vgt`5pqCk|AdRPGGR^z`lXuzBj`Y23ER)39M-Gf;o(qt*~P=j?(AI*aC zl~wYjbLMZUJ$25SC!>J^?|zEJg;M3jZJu;L$VSBzUK5-mg{nW63A#N_7`q z{$t5a8^@)nY?>}%Eg({leJhjMa*Bxfs!40v5HEi^Cl&hb8&ajO+aGQ&-(L7vm)Dm! z=Vu#^5J%}e5IlV|X6YNGtn%hJ<0_JRA^Y16u)Y}wC~Cr^KU|vbQ3Fv1C0>BddkN2S z@6mleojkH~%}k{0xbPS2|6Svz%e%P1S@QzcW%za$cH{F~I*Xe9oKuz*_lZ3-m8Hts zFO3uTtjd027;pbZAHq}K-q~0-fim;FXC$8rW~vU~>pJol)8II6A)NuC2YK^#3K^}? z&_h?@XD&e``}P3hM@K^G+24F7->be#@)~;(Oa#0$WkOBim#DWc+l2y`8eqyn6&q>I_KsG=npX~8N?dY!+T-yCIg=@87(KQNP|M4JQWpEz8N}LW@ZymkkICXMU8!?fepw&ti=hm;^S($D`9uTcDPk3 zjK88{1RVp62+eVcx9Pwt0yhNTY#1hpqIxgI!D7UFowX1YqzR7;_Axay z84`stfy6(BTD}{_oNnEp!Q3U8SU~)jX?5(djCE$%xN0W_EfmAVz^)l#Ef;GQzgxqr zahQqSJ?3%m&RyFh-JV8w^{p1DR*$qvG|5VXDWC_RtV(18@&K{uE7HkbeLuGcVX(YT-Mvx6Om0X3 zLQJRp>+d&w2<6vd&wtnPe_>#tyL)5iwC9s-a51fG4$7!5h-yVj+QGhC+{`m;2&o!} zUN1Zw$*qst4fhb}EIE0s)L*#ZI@RXnCSSAcfS7@(WT)&M8;v}~BveLA zXcZ0Kb6jhuY(zHtF3ZHOJBVngw%DX8SLjR@_LOM^Zp2Js&aBB-4%f=?%jWT88?~^o zQ`L@iMq28wQnma;J}?FaV_9TXtPS)Of1*taCC8Qg%BQC_QsTeFPO(hP4$xzKyYuV}?vuDdYdv}d3H#0E@ zCaz1gWa?x@uBmrvk$&3HzT5X@hSO@jvqy|Kfrd}LjQ3TR`r(9h8RkHwW;jy<#G`4< z@Y|tJO3ScMFFX-(_h@KYG(&7z#sEnVp-9Chts;q9W@bVt0~}(;4W@1Pi2Au%#6#B-9QY@*AwcmpA%>BEA#E{g zm1Lm3LQFCZpGQ;w`N4mt_wD~m-(GR7RozHpxWqM{np#5*XNc%S&vEBh4cH+iH|`ZX z)U-883$JKd+bj zRxi!t0K-EscpC<@!lF?Q!ZaemHJ`-881mylKenjvM#0A!E%#^^4Dx@q@9bX%{#gzS z;?bawzYo=Z5yiRx?iN`{fBQevN#+LW-Xc-vZ~v1NhOgZR|Jp-f$*%wMMeuS#m;bRO zNpn6eGvzn-kHM!|M#9OuBKg%3{ES*nb@Xa=giaj|&*96g0ri9?dQ?ebjS;+(;#|8b z4Eq{1u1MLP&ehJ%Rj1+q@^trQ!++m7Zup(o$9tqtpFM5(CrNfUh>KCfKR7$@@ZRJd zpLZmCauGm`mhS+&45EZIq_rW$jn#`EnW52jf_jh++>^|Q;fEK?H6Zj#8bHAXy=d}I7r<)Ro zBjLyM>km~{I;ak4*M}9dsdS+n^5xv;#ETUgFy{3};G?$?jzv5%q^qcwgm-YLiladT zH&VkW!K8~GiNRGEOl8@0rxNYyptcs;byW;3!H8E>@cGr@B~7L~sXH3}@q0QC+X&fi z3(R__ef<6u?^YPVM%ZTcA{T^d=JRyuufi@ZgvdXk8aOR$AU_0M`JpvHJ`r|?uN~;} zK!L3x+`j1gFP<#o^d8sbT0N$gG6Z=VTP|~P+$_nuCPYWi!LO~@t18x9Drd%!f zm9H8P8$e=Wea!;$u{89fO#!W|ZU_oyM_)xk14}DArl~Cv%~J6SLhzaUsD^U zt{%VY_5ZLY)C|q=Z>SyqF>SJ-1PJFF%<}K^`}_R<_dLH9rsTm{z79`yQo~bq0xon~ z+wmxCv9)zre`O-62AxOgM;t7*fN}KHBbE+nzSz7fH_GD;Qf?jvBwXN7=CPsv#9(mR zMa9x>OuQz|=c4(Vo45$WpLEx?fkqauWx~xSlm;1L! z#Eyq4`>zUQs?qR4?oEd?`m*iVDNI3)&nkS<3ygX_mv!K>nD-H`FHy{k$9NuUwHvFaDZ5{GQkI&W~3< zB4C=A1|q`5zb&a^cptgJhC12A6-VeN2)(mwNE!kNwrJ z@7%Yp54`1AuzzG9(97c#fAIaO`M7>&8o9CyZe;e_H?dA^y<1B8 zvJFIQ|16&&Sd&y{{vMd`tz_QIiVahA+-^|yx$2CA|3y1vOou=B0&sZ_mQKROUZ`M* z{#|s!EF2C)n9N=>#pLrv`TG^{W8PX1rPWu(V%KOW9%|d8I zvLEFMtY79@PhsjQ5bxITt4PGOE?<{Z-lfBo9ZOSR|t4-qmr(0U??NT!Q@Zs(p^w{iva?)vH|eH{l7${ zj2J3`uyDO0bN>zPyCcBCUKS%93Rxh>iqr*29q^qN6;5Jk{13NC;^~{1POub7ID*_t zT3aX%f1|pQ20-Fu62nc%A;h)zt(js=P4th(`cvx@-)kX&Z!#(pj${8O9EbhTKPvg} zVljXba*gjuFQrm*`raxAz2GkHM?u&RK2HBtlb54=grEE+P61OIe!}0@C@U+#4fX^i zQP+P#DO47`I=w0q&CIi5^O zp&5j;1e@lw;MuSH^zZ)jU$JDK2Mfu6SJ@C&+L8aEb3&s=b)1G1{|(~$k~%BH>XMQ^ z%ozt7UG>wG%D7HyC$5Nn!24^DcJz>yA)3r6r}x=B7E|l_{WM1uJ0|>DbblY(OP=v& zNoBtQf9qy88;?Vp9r10J0y(ARAIeq~1=%c_1%r5#&gb5K!g)qZdHpwrqV#7Cedmt4 z<}9qR?2Rh>7S~fZN2xt$A|%rivm?eM2~w8|u#6Fj1%o<**vB?Z;0S&|mADvh&X{M95gdN2)?ieQ>(6*7EEDtSuc|0wlbuq3_ z>3StU#ZyJk*!jPQwH#D*KzY{P*J_fKcEr32F=(s$`Iecra2gwt+nv0Lu~SJ zirKdpJOMHD{)b+clfA)%*)9Af4iqX8eTsN=2RE*#9ebi56)`q3)fR;3APeNf5 zaCe~sjZbM9s~2nYdCZY}Z1ti-9M(fMzir;gl{J&_3^VowRMBPWANA>5s~>*Mx|?Ox z=Nx$@jMmGfoA2dnTp077pi4)bgGQ6TC$oanqRuoG9Vh`v0?cE!}M+J9<6*6+GUIeXqqNb{?G`E$G-z z;v`NylG9H2=AIH+l4$Xv;lr~0>jxiDRitD`>4|&MbFTWFv`Gpq)(a>U3i!ZZ<%o{X z2kl`+X;8~~UUFPOF;h!_S5@9vl?>&$uVIB;E9w`t+xc9iD8e}ETqWnEfNVFN~N1Mi;7 zLd6l#3}J_aN3N=779z8h?*Uz(zgN2NapDa`5xTcZb}iyu}Jl;WeGHwH>IM*okpr(O;ubh!dMWf)#JK5s{9uuR9`=PN!!(Xot>D( zrtDh0x_SxKO6jImKyNM($WkHhEd zI`lw-eNGIa<4g(WF!RTiBVI9ZJF>9oCWNSSxaxnt^e^EF#uzvfRs_|_{)`NEs{{fb z*unD?Uly7P)m$rPaH*zuubR7qlZ!phTUf>tpNbuh39eRG02{vK=Qf%ikAShx9LYYUE7q7h*!(E z#jW2Tjf>lGk~ghg;dn}mz(8es3D9|6hd^137G?7|4sjh^MBnS)RlnG2vA{I@Y7o3G zjLU?xcMnX7Yq(Pn_w&O+W9@;9t)2sR?S#K~ou%E^Ti0>3PhBtJ@7Dc%_Ien+^j{vl zT<`cJa26uRkwca~Pm30DX}t=7LzA+WV0-*lIiK#xy$a}}O}=WS%A*316p28H&-rhN zRQ3(hHB%R+L8KnhNLtOxG0wnW2G3sm&#->os=ui1>R8!RHR5t z##%*DvNQH}vze{L9tqkh>F!o*GPtigk4V3?MA2+--$XH2jH&AF@|FIVE9U1nNZ6s% z&Y>Vx|7q|{EIVtxah6dVdq_iKtzX~9k?zKi+8~r46K=u_=j>ibm^Ci7*DbyOI4x}+ z0TBk!PBfnn);GbI7Ve;n!0Qh#j@h#)>*7)lOi5xoU)!e`>cGDOOc#T?^Mm%Fk{zYK zo=Cjmu9fFq%6YY}CA-iiWu++rQXJhM0qo8hTB16hqe z;}5OD9a)%TkqcRI^FYBg9l?auLPWcHN!6xaopWmOmXKSCZ7)wJF{~Q5k&4|(l6hmi zV?2)GGG`oZy7B+uDF)!%`;L47rd5Ip$JvaEvB#m7ZVSFvk#2Z+)t>s(sQ(~S$|=G) zE@@v%>YrZJ_fihRV&|VSlnSYbW%O61zNGFo3gLIB(O<6;)@EWJuf!~L^MKoJw%4(V z7@d&~8Jy4(VSyZ~D)C?)b4kYo565Yqn*#D(J7AJp-1!;s*KgBPP!w?e~7X4XXENB8T^v!C;y1Ni7vi^oM$AqT0 zQ|C|Q-Z^*dh`m@Vgt`f;J7wSBPx#$@GIMPHV07v16ub@$)(;{AE!g2|ge904hbvfz z9ukw?v_~s5+(226bVoX@`H0%B&1$78Pf&a?xBt{+{ku(uYU;BF_VU%M;9yNpIW}Mp z9Y7ERfrUe91$dp^62U}eTF^pc)WvANw^4|!cvc&PWjS0iI5V#B0xLa#HdE0Qd1m=o zo<7Diq%fS?{>b)lIAG0}M(CK>8_&|%3hP@P-LJPZ61pm2j+Ja4^u+yR6>cGrh(U(# z(jE9Ewn<53*3{n}4&U!}rWh8}pI4o$o5?{B{@zF=b%4xb&)3n;&x^cRMKZ)&8wch7 zE8rD+>roZ$nJj__z*2c}aL@EK{Oz63Ir`e&uH;J|X!f7R@9Ce|Lbow=m_qHlyA{cK zHYnY23M$W<3HO*Gje;tHp8gaEtsJLiV$7X7dv$nBMQPnVS6v)3Z2hK#x&eL5|Ab76 zz%-znP(|6}_7$9o;*j=C2mawN_Y#N=*7gU31#M<|`Yy-}y z{T;biDe}M7(`?5$xO7gMBqIkb@dBjF0e~Z%NMbMz=L#E=h?X=OYy*x9ivUR-jPPF2 zBLa|vgKeB!B+IGY$5s|ctmZUW`AotOVV@V(V(dvNt?ba)9Jyku! zJ3l)2U(iAXz!O^5`jU<#tW-AY`1r7G{2YfVCGw>AaUZyQ7_U{{Jlgiz&VFt$-PyjyS44*&`2wU*RQNU3pS5S3KW_K=wd$9@dRpv!d69Z5=d z_bl5#QtX2Te&Lwbf&;>7*;cW^ z@i@JW^qhI^y~z-Tr)RZLOaC6HMa7bietDKO0_AS8CB~O8`pU=KI4duW5lP|;l7C@TVW#4O${e;HpadVp1ybh&VE2N{Q~Om^}m?7mOY0GT>-F zAMWOp`ZlhG>IY6cqzg=GPCyx;28LBMr2(Hm#*M1Ht2pBgsaH?^*N3#7TieHd>+So$ z_hfec(L1M3%Q)siOps$>^IPCPJ8md))k_Ww+YUX2zyehHj`&qES^-;_>6XLKxwCD| z`OmhgqJ7d*;P(!Ysp%kiwWi))8enmo$x#AY5lU)w4Pbn+8fi}aEY`Rwxq~-e_{d@W zp!1lB4%wK9qaPbD-A4t`QhY%T7Ex2Wq{7|LZ*-%{6P^0MX=|IjF<19Ce;Z{8KMOxuf0>o026;J=a!}nem|8IB@C|H0SVjSS6gHXnHKn5s1KlPDjM1~pl&<< z(H9Da!1t-TA;~yX$Ow)HtHgKK)d0XR$27@iKi|2e3DP#?fP+TvrL`WOzj<5Pml`F^LYxOC$h2I8>G;mUBp)h^~VoLBGf``7HbEd>;d#+**dyNDI zL=pS%Cb{=S*U=OH{*x-h!k&-C&|rcCB&Hj&R@$hnve)1~G>3b3y&5S#*EVhQY~xZxzD*qULW1rcT0+SZJ`MS46J2q9lGkgaCm{gFe2f{G{y_&>-N zB;`oHAnwTS7RVDADgTm`fvP4w^;iGdFTWgkZ*Y=4_4&VFg-0I6W)9&*nC;%__?FqW z%(i8=zlzz6C);~qt{Hz%ma;ASvz+A#XHg@hJ@Pt^S^p30<#pK0-?G=1 zy;j+4^OCk@vMrNsnd}ivwn%dJqWaDvc4dAxL09Y;Rut(2@$9CcUffdh;}HgmA$|To z^~YwZ^KaEFx$e0Xhp>=5d+k3z3|_67NQOtBPyO9tq&P9aksM2XCO$Y-)pF0bKb&x! zan}jNd4w6iQf4|XtupUOY%;Ow4xS`%;N0J_UFq$hhVhO8OyRSy2i|tJm77FCl7eDf zk_7G{E27^$C|(8dGH3ffdqlf8I#t=}<~=p;j$Z3FbL=taTDHC9eHV&KPn#M7M*ZA!UYW(;?#s zc_(yJ3eIp4%O$ZweK%4~Z<39sE(`}Jl6-W1T_6OR??SfBuE(gi^l*noe4^hU(f?K0 z-Mg)bF5&SVCn6&yV+M?Yr>|bH8$8Od z>ZYzIv|8OOo!AEMjs2Ye21*`tCeC%z0nQrxh9W>HSqqffIiBr+G-ora@`PI78U)|y z5=gFX64wzPgbF^dD#)71eU>O|_#F+C*$jRPBe@UnFdJ$YNGx#y9|HdzYbH*GM|cvl z;zaeh4Mq|B$4i_5qMY8S35O~4qmf)~8Zvq1f>!M*=};{4}mKAEYo#{ymVevh`2^=`9a_wv`!%{^{@t7WrZroOkLRr zG%j3kH!V++82*jNl1G{7`97?4rh<_f<5ScLt-F{e=@baQ{@K|XbqAh@cgZ|e#Exw{ zPvdw=%;~?QHjRmlZvPeQe@$>3R?@<@@CN#uKMY7QOh~Zwmjxn*FgZ4i_gkGrg?|-L z{nHfC^;B`bSnUpu%a~yz=Q`nuT;XzDs&GmRZ3`=o6wQCANr5Fbr#8`L=VK+9fF}7s zWi+|Q<~9@;mG0NzLlBbyRwU>949`$abvh17mq$}tKoU||%NUuEAtU<}z6~cc7}}@B zXtZ>ULzF-r@INR$F{D$bz2*mw58ox!Tk|>8gNS;jk89fEOu|@?s4v?}zDsqUqa_u> za3;750XtCSNz|!eQN}cV&PkjmlbI&Pr#~t1*}Mr<5@bo;jZ8#t)pHV#5P(ITG?Q?w zrbSRL>S<2_`5|}pe6Q22scC`IG<|7S^{4zGn3)G55*0-qasfYkr;%gh&J52)?%GBX z8ODd<3M!uWQ+{$?gg~6h$OWS3qOVa+(h7Gl#e% zbo-21P&d7-(fLXX`Ms+oWpRj`KyJG4LE0m?c|K~&iF;FyRxWf&8;<@pZswt$M-g>( zcP06t$74nyiaB8Lx*CU5eWO+c_=f^@@=ueB4{(6oz?IbIL7T)`sB^`5K%^$#6#ggL z5K&iO&tj-z>;3Wpp}!?!dol8O2T|J$$~1u zNm$i3zkzDtzezD;sN_+2J>u(joIjH6zzT*>e_2lW$a6-|ijXnOT{Z)zdr!0E&i@GT zb^7#dIt%Gv+i0Re%o2$bQj{lL4(@|7->Ti!Nv`(5K}t;JdKAn*`asoojF?NDA6UB)2*Na!1Aw>PXC!cjA+m=R7+ z-OF`yoij+u7h+D5dGOQg&r*$y2w_D(sP4BoWY#}H7TO$fSgIM1pKWf6yh2~PCS{Bi zUGzX4Q{h=sc6+oYRiW}vX>maicP96N=KHX&(x7RaTsc>_{%-}+PiYb>^JtOWK~^tG z8`HNzX$O<$WzkVXj*+<$sneo}ufhuTOj;p$9?;rLpRTH8T!wW5uhazWp4iryL~QRh z#}4$VoH=Gjn3LdZI2%CLmS%`Q2J95T((+m^vilwZL`<}ULZ`*J0wxyjsfso9P`gN- zCn=TkHX(_dFcIC3L(G<#whnbLDJ@-HHD%*}nbC%4fl1dZY@=MAax`9Hfp1#}#d>8WndvO7`3)cgN9%891GmX$i>a?Qb`%sOt z2PkPnish%^2bH(A zN>UaR)rx`(&By~NjOcJfi!I&sQW8Y@U8e#}_%SJ?>4ZMa+4+Qi)_JxrvMsg8O%0y2{?Mbuhy3n0*9Y8T0kY3>TscAaYw<@aPx#h-Z0KLk;DpFbz`-9*# z;LGq$QeQFaxfwbrmi`|kM2Mk=^f)+MY%~yqeqI^lG;9Gcf7uP5b%Sr z%5Uzar5R$WTl&AHs)9aoQ#GMVYsr9Uxqg^nhy4+V0VKckN++9Uk5HdCIqy3v+|e3> zyZbAx2}0E*dQw)AYK{Hr&Fa4Ia>~vi!=fQcpK+;jS%&~u&Dw8Y(k>km818m(8lmpu z8<=C@)s|1%Ap-3cTzWtlEa)nfe&tTB7lx{2jBEc=l_kPq`gJW=p{9kb)+C**D7!3a zqz1HkvZ{DZ4+6m3kYpg~C{$n5w1hYLFqzOdsm)C#SKMZjG2qaToJYL+kSdzyZt1y7sBQ~duzpwB0!hC53-csg=+R@G?N;n&#+ul%o~@r1Zmnlq z>)F)F@tgoPs#=m3-OZ| zFMHpsWxzDf!Pf%}nZ;X_9H5Z4tKU$KIwtCf}5v+eyok{XTMW~ zO&vgUsBYK|aR&+q?IQJ#UzFa?q$uJYv4u(5v>ySGy@gyICuPPK#b%DcdFq5KXveBs zXB69-uuv4hnQZMdPBQ_+7U!*II9N7X{kY4<9F`>Dbaljt=Bt)S0K}1COKvzUayJQd zAhES#r(`>0>)}kxWBerM*vEVf3c!BT}^N zgrKhd3@{fi))Z+vp7SGdWPeg|FIA*`CJ|dX5nhcv0mOX#IdA8?th(b8)nHiwqNS32 z#E8u|tpm#tLzl(8L<}v@PU2r!X_=!LQmhi_W;;wB1Ze&?Cq;J_b_}9{Tj6MKloj}I z81h{_epL$a++~Z_4^aX$`}?C${;Q`w)1Y7+OMX$qfg~L!3@In@yHz$}M7RmdfBB@> zt!}sRR7An-=n@WaTs{A#LfPM6*n|i@L7RvZz#9;WvJnHaBUzI~EweMX2*8<{-E58T zOzHJe-nWDn1F{Pz;~Ru9q&xdx_O52RjT}jzT~ARlhqWC;)<~2s+Z{fTrYxD3C~Hi$ z+dG#Hun4js)?e3;XzF?98TPcdezDCj0aO)9k&>;Rkz->!qFp5t1r`zsAd$%YzCtUN zDpuuZVAXbbwb_3Gryy++zOlh}m6Lt?txG!;89t1{Y4t!sFFG&WgT2lMF=X%jeWPG~ zI?-~!`6ANOEIt&Isab>SGCDJ*KJ2jaw)Js8;};lr!eDEH>1!@0jsdf%y3&%-+9Q`X zPlc=~84~<8(7<4L;qq@gO}I>(eL~X4Td%*DkByeN<+U8gG|fPEG=F)cw1!&K90H=A zJE$2>Jv-9Y(t=yNQ_1f1XT782UAS4d9YEw|tdCUoz3j%@b{z42-r}L4X=?6XB$IhU zGw}@^f`S^Hi6u@_XgIT3=%wKgScdnr`F>cN^T0h|8i)-Rh@Q*TFKs<3!vSk>T0k#X zfW6a#+wH=X20#$)lCrerwt-VJ;VauOZ9n2q@y`UGOZoyA+|M$J&u3+Pqtcesp5fxQ z=d@X(ONhsT7}SpDr00B%x$cPBBbE54>`(gg}-5&xr~1lko{NUZob zp^YwGOIrcYdpqfCNKpnf*Yg?6WQ+qAQsA*C%5nx3c?fD1DNhdazRd7m(_FI$>azV! z##L~!^O`2Kfo1!_!b1B?7gb@|vLvkE@yK>K8si0NoN+~AUekIt%fJh6fQDASKMl!{ zaZiPeQrdpb=X~>EX0Tj*>$sr*dAa{`9oLYdiiH7|a=#iJC4-gTzHNK39mbaH>Q!~M z`zufH#POk4k06>Ui!J|CnoJ``{Rz!>PktTT*>oyX85}>G7}!MJDhTnlV<=_{4Lxi? zf10U-JDcB3F%)CN?bE<7w{Zf@6t`f5(`j$aafjspu>8enT>AIt@ znkaS_pA&j_pMh&CZ=g-~|N2+g;sZC(J`H!{SDIc|>d7BXB5gA4!);=*_(&FO)#fFe z_Hu{f`P;O(A&f=FBmtJe%mAJ@D#CsR)mVvDaK-;lWEJh8FdNd+!BVO)2hGTa=g^E-F~fSL0df0D#O`pO>BJa_ z2usU3#0?)*gg?*v!;8U>^Rnc=ikPFd=GsJUS4E_m(JquPLuHrW<;I1@OUU{tzq z^YSK;-2x~7LCNQ)eBAK>5w+=c1K`qjNWovf_TC(>qtfE*6~Vj*D6&SAg;1<9e|N#H z4g5gbv@GY!9n9rTLOaqlq0JkaEM3JPG)^?c9Hid8JWy0j;L^o$h&^k3h$P004Gel_ z_)`w|yqD{7uu!RYT*@j%!*~^4BX?&#WzRi|Nd!ql?c53wSHneBO{C@4wpcTcu zv)Q2ftDmW5zZc)pu)h~unnhpy6pezPNw5cx*3r%z+FP#;zdjeZ$MCyH!JmBi`GI6U zh&@_w_uc&i`ga`^-WFMzLk$zhnmq1RbgM*8MVyu3h>H>TL-#ZbT81nU1`JxKK+7znNPs*7fGl*{U6vo1H_ic6muNY^n1?^O58Z*+aL(;CjHH(gq zu8d`>)dmmH$`0Ng;HC0s`7#>U5X0a1%;T)^(f%v&P~&*u4b7Z;Yv%fJ|JC_@bm;DK z&d3^pnwzQ~c}V;K5dxnM<9)Ed)HvbzV=^Y|r(c~BF--#E1Qt#BdP8$;{TsiKETceV z%5S;7j7&+sk|m`?Om{gB9CO)1kjhMis%33Gy2%oOaIKbegkVcDPc!=ZC{Wijpqpcn z<#aibAe5&5MeOsO{w}Ws?C_TRL5?%IXi=x7f@^e6G5JnJ3n7DI9?&(2aL##3W;WjD zOe6qEr;Q8!AJOen#1WjmpE9)+E$5<)uc!qr_cOv#@We=FV|}CIfF7coFu4}=9;0QZ z1hw^2L@K0<49i*BqTRKi=P%V*7I^H7l10oCpkBdIu?RIbmGaj*hWSw{5rfxfV!5i% zz>h?InFfNYbs&B|!?aWkk7crw>Ah4?>6hLcGFBb>X-Jx+UnFI0qv}m!vsd&v=*YRa|M$ko(WH zmYjm<$k{5a}(U96lU$duTJdJ2UFGE>cA%P*Z$z~^dgB8xWEqC zvA@4g_RQbjWBIs8!Jph4QS!h5GssJLo7Tg5sf+I+hC7QrLMJChv2;7w1@F7BUcT`T z)|z(dhwgh#w`HUG&P~?$us#FrHK|UmkBzI==R0de$~I6~0~%MvBbHds$yFiS_B^7> zGH;x@RuyV?#X!x1b_nNr%K^`GJZtNnOYdTk>p0lz3AMJXValDpN&T<5)btA)N?#?b zD9VcX7wF8E7i;qc9SucnID@U2wPClyMcr6L7C7;}V$OObZSrA?iRlJWpNT`|SB|6A ze%T-}tcdo^t2qtXH3J3o8(9${+-p+*eD!m4oboufm68mNB-`XnoZ_rs!vQecaD%1o zw%4eTr?=|-AOFL7h9f`tLjxPSZ|Qyg9Gdxz|>S$A^l)8dur7962* zkVZX3t7EH+VHHTu%vQNQZFX}6G+TCGF1YG-^cXy_v3Kr53Gb(P3&ISU?i zsI47&FPM~c|FGkAHaJR5@BxRXGu>}RuBIPmwmji}x!m8|`&;jPG^iNnOo#kt=_{+M zmPWP(V(mFLst~h^U5@JqaUv8>pO`Amc+b75&&*Aqj+cxd&WQ=e>61$nmd$6!m{TlA z9nS$y^*slW!@D!q5bM+#)d_G3cz8BbM67v=nQXYO%5jcNU@R-oFX%)DR^Q%(CL!-k zlvH*l&-gc~W=PR=sZZkt|Iwwr`{aeUmUk^PY&{wY+qZ`T@*nr8;m4IG3B$RR2x8&G zix)JryxJJIeKPx4Y%@EAnXbMmw`wItjiR_Dd`+nbNjPT!{g`AZG@Vg`!!uBmfLzHF#X&(qZM8gU^`QqC|k7T zWQN5jm!O=~E31v8HUK_A!M`oj2`@}NZk5nR0@X~^QinH~M@-a2Zr62Ma`2<(N1F1< z>pUfn`Zo_~j@mnyr6U1{2H9_LXvm@~!ZM1LSNe!QpCxrZ=Xr^N^#SK z(>TfGEXkJcnH+Vw&Zg^Blga7`owL#xc@N(G8I03PSE-sWLrXxrZrN!+a`oh>|LbrFC@C0A zZa0W6bTc%o^%7w#qx9V6KF3VqmM}bVI&k}G2NC9q{%#eyZ z86nJ}SUNhAl3!A%mq-qMtg;;vOV|udtHQ82Xo_6^NtIWrayB@sJ`mx0e{r0D2oNOp zGtO75;G=pBy)dMqHXq?a)uN!S?2uN7uw)Jkw1ti`q8;*baciMN&5%x%U9mvdN{6Ldyd!&9n$VZ zkldHBC3Gn5EkqZ8+4js|Z2T=RpN$31xPKk2aJ;>#c37gEsH9cJUAA0~#ncmq2~X5p zqj3q#+A&n`m7QqMeRc^JihPD~5zhqefWo8%>zC*gy9=_J_-?$641J?rNG<@+%C zve#gj{*rbZQMyOk!vGwJZ63xd;9u{gOadv}Hx2j1LT@W1YIm&6A5#E#tJ(i?G5nWK zql5qs-PgASUThmP?e>VHyxjp;V0qkcAAOZ6-pC_BX1q?MWPgP9Qs|ve4vPuW0k(oL zz95xX&sTxG?}isG_u^tm|Mb7M+>^m^%l&xq{)GNMKheYSa&Ua?m}<>{k_A@5vS!js<*%2TfV#no=y? z{lhl&9LO^=am?hEhNbSBm@Ir-9HpZ&N1zHSt~Ow4f>c+seARr2lgUpbP`YatDXt`Nct z89c}0fIUFI7Xt8c@HE1g^kPFPn^Et&Eb{Sdjnto+1-6ji0D=L79_6JzM<9jL?Cc%y zo7ebJ19rfVI;Jem3%f;p-aG9LfBoEZPstXffuJ7Jc+MNbDZ_!g|9T_V;v_63ZSji* zylodK$_idLy&)Pb6RaR8w{x40G}w=xdy>e2>`?~HlwF$0@h%UZ%!^`5?b-9*aAay{ zJ*r~saJkG%Su9hzeXxkt>AOMv2$S8ULZO;VR5MNB&!EjJynhaaBN|6BkFnI{QsCz# ziKlbmy+NSrnx?akcJxl3Q#&}aJT6n42t2Y?=-mF8w!*g-=c$+>MP}(Nl9r0zAhzs0 zGxd`(GzfT2Kx9mJV#<943J!o&liWQ4njSDF0V#Tw(`DzAQt$yrsdM(P=A9S2il1W_ ze6DErL8Ni4Z@LjOaI%FQH*iLK6Y4+sHKiK!sfd^W6gQ+w#-vr!x`fp*cw~?v9OTe*A?a?RMDL$Cw+rS(oca3;6kAa-+gfG>k!Y1$jekT0Yk#On7_8l3U|Xw*SGX%P(1TJGozSz}*u$3jm9 zDs;$3GfpgI{Dw&~$KZl9gpH0!w)JmqpD%2q5VjWkDkPn=f^Yl!qi&>S`q25q)H+EJ zsSO7;B)qG0>z6zFgd=wI%*N!3l*-$tRP!s`Ij8|Dy)ay`m|dOf2aI*B*w&lDVX3)y z6E~Gf${;xj`(Y*tuU3^R;M5^nJ3_91+0^p{FRBLe!el{jXvq}PBqL2!ya~9 zpDqscpgljoywG=nV9&Y~`O+E#)ynvD36zFZ7&4fb+&+4H?g+(@Tf^mUQ>WYa{leuR zaP2QN?4B9|qN<5cFR;aF7ULw>pG#=hGM?kG^nQx?kyZ(Fcyc7iC2+Yag}kEgbQB6r zF8aGoxvZ$-Pa%kj`@#c-@#~k~i-QeaDQL!x+MnQ`Mtbsj61TZ$8OsYN0<gu&{PMq)KEzIePjNm zza;CsVT)EWcsd{rYPhh6xWge)4k*Nz3M7Nm z7Zifc{;gn`VB`jQ^CGCwrQeaY-y`wKoLlvT5p=t$nt@Ki&%839<=!m0u1e1e#^06( z5`TZTgH8;_S^4VL`wDj{9{?CBfx zo7ouf#55gyDz{W1AV`SaQyC-@jnIE@=*#;|-njn|lVnbXx@ip?^8+ntda zU3g+5LqR(gPU941eLRnTf%^zmFK}hBSdsb-iUJX8NM@1?l?t-7OU5K%tTWNTR{oG+ zKlN)8&rk?|bV-3 zecvrb;O89=fqNpTI~rK!W)A7avrxsxRTC&thRc1Au3ntgBr@2Ir-A$4(~KDW3%Kd# zc|(d!6z~p=3r{qY00#_4eagC|%B=?WGPk7m@O>KmqHI3`F!Yh`yg(7auzL(9 z*qzXl}>>J0E)!^Nyd=CU$%bP}4gC|ctQv(@s^UO#n!q!%nIioOM`fJRi?Qx%ko1tIfeGn% zIt?ob@X=hQh@B{?pEJw^q$6q9z;kBJRx^~k_AbNc$6dvDU7r*-${X6j97~LWuSCRa z9pccI-I9z)vI6KIuT*8j9Jz$W1!S8~0R)-^pMx}nH^ZH2V_r+JzO#Q={8(wjPe3`$?Z%rNER_|WPmaC5}48C9*Y(CHb- zgmA!w@@aNpK0!h~S2wcLfJ3XLbr5%I3-uF8-9!I8KwdKKhtLb;gM??3m{!{rKcg7{ z_2)xm(w+RN)g9G3{#>PT>hGr{K_-#E){zgkP3ux-5XCg+ZxKl6uZ;&=o2{-INhhp7 zUh7E0p1NVBYv%?2EC7#kmVhXy0&aFh`ocVJA(8 zPkiWCdG(Yhm&S_f30(XQn?@{jyx3w$qC-US)JDh}bl8-KAP9mdK6TUu5S&R{2)Bb@e#`ZB*Y{F9`+WG2+4>wAUk$IpeF z9_a5#*nIG8&fE9a;7|GkI_IdzXh@*2^R!P*1pCs|It%zGmfW09Ta!bFh;$CMlqUEh zjqo(9yhj`8>5WdAZ$#VO4L@=aW$b{DO?1T&)}q+tCQ==rIbzs+bwL#l=GvJc06wLl!OsyI?J#iq=s~5^W@i%*0sLj?n`I zPR_c>$8{LR_ThU6{L3-T2nRtQ_G#0~J(f4DRPp4FmOSy-+DAw0=E>BV?OyLP-KY06 zX!`sP4BML0;bXBLk?j1ZKQ-9p3vVQc{!m5cd@WLs!^#jx#&%dXc;XEaN@gEMN11Qo z4J1(1r4yX*pGj5T+PTff+>eTp8n3$uZWoO&Ss!N4cFkdFiZdluMu#~Xsv%{4x4*pbbSF$g;b=K@ahJWsn3lX@^W16RDJgML7hwv$0Gmr%R4ql5ExhEc-S zuveITHYwlUYp=Uw4wt-hI$x+u;tGCrt$lv7zK(>dshJ+OeGusDFT@*f;O$*vMRvoD z@Y*nr$a-tj4;<8QI>bnlhOE36C*jA481fJc?Hedcv!%%r<~SjC2iTTyefKoy{y3?$ z?EA-2%(jEwurHqseREo)eRv0opkoBVfRe2*A6CZ=rcFtQ%~3ScO&knBVSw9fYd$!Z z%lT&~XKxsR0iM-m?!lk@CTmYfUm%%rSfpc|rsjE4PiX6*w}UK0y(Bk{ka!rHSUU6} zIM{7zhBYx6W|L|^lsn5Y71Q!M_69o=CS6Iw4VY#I6}XlxJ)oH3?Nq1iz1gLkH#f7E z?jno`%yGsBu)-L~>U|cxfbtf+cs3ug^^r?etND(g|6Ed87R!Qq1s6u_hZEWkB<1m% zfT9F784HVd@&+ATnvQd`*K%s3$LqpS3PGOM*sn4$8;fpaDD9DN|B-sUO!$HDk0+QJ z@=(t`RQ0g4X1c2x2$>pKg6ua9wRyNCv_}THWajCdI13Ma)dUmJYd`~{ev+aBgc@O| zm_#{eG4~BIm#;bP22sLm04@L=K2=HI*O37Qn&dqAw~`JLZcvz-+vJSRYe$zdjn7D( zoF-ix)Y3DIMWhMi@&Jvzbw{RTYa{KjKx$7zjx|qn00iR|@NyFCMKv{$f>uaA=6IkU zpUWP_U4~5`ax%bHK$2gG@!US= z0HWyZZ}0TfdvhbY+uTnF*>p_veD)%&#dDWTPNnCr*0S?W4z~*Asu5Bo9hjJw?0Gcj$os2 zT;;reLDMPsn9%(|nu1v#jiOjKkCTgoh6yU2`kl0JkG$tmh!-$&ACtpbqB|$+1peD} zqM7rK>lCmBk=t3K`H40x#PoUmXxAiZYd!oYDQFqT(;2vi(U{LRY4}pPayV4}MHCGI z^FexYCLdc^oZ`>xTUXm0*?1SYop%--B(#B_C7>_`vQ9YwImhOz2Wb-THW)7h3idXK_n zZFajk(xG1lun2G8ofOv={Wdp18xmo2KqC>|S|DcrVin=sq~xPu*BVmut z8CUdmed9gUH<%(hT(F8}M;yfXAOdUm_VJTrXm|vk`!A8i^?I=%u$=o@bxPC_pzi(o z-j{ITkiQ{Li#$eVZ{^*{~62|U*6>N>;Ee0swo?CP85r=)jj6!xgonE{*f+R^{ z8OgAXdK|UI_+S>Iuo4&%qb1Bl=wom?Lu(`1iw>!RWRP1}9UDT?E7oq3!gMc6BCB!@ z^;AUP3J+Czc{&~-N=QhLM@U-RHp=gH9)oCSNqMQ|Bleh;M+4rk1V?X$g$OIN$$T$O^x zF$l#o&6Kl$)eNy-TgScTnR6gE{5=w*r+H*@T`n}NhA4cAoS8IE`%~*{UaK0n?lFO= z*n#&h_ZniQQ`S`Zmg6SbhF9f(SYwXRRiiN+GsC7nngMZS>5O<*r7$dnQP*%x`#n;& zNv5|xe$G3pm<%Ur&3fWH48VqrMYo`dTPLv2 z&r}{t)n2Id$U6FffRctL$k~kwYc~vQZs^+u9Zc-BI?JdGr~&h74m%=0$+>cKQCAAF z%iAP<>huk^n>KgQ_~uK`aZ-u5Xs!rZ7eWE8vU(y1me(C#_b=c534 zpB_DO(O{1|9Fpjol|2IrYTnVy1F-EG&X)H5)O9!R||>R zADuVKrNZpB>yyJ-;nvz`=j$_*dHk@8tIDrg^fP(lXS(-Ufe&`?qE;JiXqbzsoF5iG zf=hdO*({)9utGpW8eZn>$4-s} zo`7wrB%A*87s1Q>wGrE@#!Pdq*LYH{e@HGwvtu zU|Ag`la(rtZaJtA3F`ICUI)u!ybkPgwvcw8_dbzq^O62LIXaTc&dztJBN;xFThnmB zp@wUyi|kbMs2NlMIdILZ(eWs6=1blZ7QVjW@b!KbX~lO)Oi|T9Gm}|ZlZ-V?$lOJBklK?BIQd+r zQV;Mmrh+V_QxEy!d1bz4oAZ>R5=9_H3!qKHlnq%|qj_8b+MQ{{J<*xINScxx=?~#si<%-m^orHVd)5!@a1Q51t^4zQS*dUEVY4cn+8!%9* z<>46F&vYLIeu+36m`~r^G=K#{r}hgHx;V>oj&b0O17S)MXmeI3lo$y*kt_+}`QV^O zaRxdaS1M-Z;Hz$Puq&i)9Vk_?kQyXsNO|63Z>IjihxhN_99-6+3o8{%fduGiqELg>c<=AvUrH?#e)Jkpxg!HY<<<3z?qAs06o}_lX3^m8HNGD8_2U5T*vB z^w}$)0rm}~Ij67Y4bO%S!K7i3O*^TJU1v8k?-=6ykLVlR6+#PeokpQmvl~GK> z7%k(JLwNsk`D_+p5fvCSN`t?QL2Cz#i7ZfKUTV-DV4S**3NF>8P8*baPB>1mxWQXb z+PaK2f`I)((awko8KnwOqj_C zuti;0D;wGr^tI)v&B$b<`5%W7>|^{j=;P}=BV}9DsDTlXVV3$xrJ+BqVYniNr}RkE zz!NnycrJmG`<*8c5ARm6Nc`5pA#K7)ZZchUEFc0pGZZ28I~@*VVOa-*dRuXb5F`E_9P)1Xq2J%QPP0z5 zY^S*Z?C5@(6)C6Q<$0^aUub?--LsF*(GX?mMU)8`2Q)oR=z}b!Rro!6sD|BiM>pLA z-Bi2(o8X)3_dUApH~!YMKs?K@?o!JRB=`x3@MUTZ#IqP`?GIn(je-VmsXd8kX!f$v z)E_2MkAd<;nW^i)sFqbSj=180G(iVvSnsPcH@^TfK1?Mx4aX1^X`qRxpq*g$Oj>hZ zWZ>&L-IaDmjsqr%DV$PSX({qNNk&f-hK}HUK2+0Y0gCAeOCT=yB+yN`cF26jb|nGdaOpkH$ZQa>I44xt$E)- zo679jGIH3}NMbaH@{z~}g}@zcE@%>BY1EtYgRHb$f2ImU>}CUY)rd^z5`=Per^#!H zS#^P$Iv_c){*PB|s)(5AQXUF(RY z(lSvT%~-LZnmdKsyH_W#_2`D*v)CwgLpl9FQm#lhW8^D&VzCrI=I0Xj1i)-!Zyf2? z)d(L~I}ygQ$_G=X*m&hXdmX&mT8wKq34u`Fn(Pe|#u~ZTq_5cR!_>z|Xab3+mTFMD zYmRiIPPjr#?<0qAnTWdi8)PQ|R55lDNYUMab{ncmIfES|D*k`}kKBd{>ri0cs8tw) z*y*s;pLCfg2Di^_X1<CI!b@iSqCaI4AG|8(e}oh_5u4`xyZpnUMCv( ze%C4_ zzV39r{%Pi^TIk8aR>7foVNGtZ920E z?2Ios)7%R=`Kn1lq5SbrCgoHq+) zJ{0Pjp$EG^97vdPt`Qjoctj z!z%FVIHi3K@|uorG@zHxRdl1$3dqDixutzYXJKkX8U1!SQE@(uI3P4{0p*D#=~^S= z4jsn(SvpaOsn{j02VetJMUP%hdij;ME?QaJ2q}5VpuRhE3fY@cM~5NrlI_2ox-1k! z;%HBiznoG%a)=zvqWHS_aglpwYje3M0?!;+IB1jAL(9FN`Qv71^TF9^ICTGU zr)SZ zbNKP?CBVAzZ@b|i8Q^XYb~N_MWjZVoZ%CRG&ILS39*SBr zEe@O>M|y!NplM>h43hvu)(7U*I7UO(^|jqByxACQ_RA^*Wp8C4Dj37`m12ygD(XlC z_ab(dH#fsoPAVZz8n!BNIhUm9Cnd*f&@ZI6de*RHLWbDxMDGmH4(ow7ft*O)KS)EH z@Lb3#$uJ@e@_=mpsGo3HFw>b!@?t=8rO0pIdgR58$d6#Vf{U^39xH#+9&G^mEnF;`OS?I%m+JIPjQ;4r0)u-Sf+ci zfJ8-!OjQPLTDEm*`<@+=Xb3g$4yMrWc&8^7QR@HHdO&qI<_S<&cBH1M(BVqFN)11DwZ3RT-wAU1hE52|cho=lNM7np1t`xC~L)=OHBh1}bdjaNF? z_iL}nc{Kd%QzS7^qj9x*kFP@RKmYsx5&QcpE^d+hk91uX2OamlMbj+M)I%{%g47ZP zXE_kwhW=Z+8GW@I>p?4tMi~q=>Enl=543G|S8s1E47>@-USL0Hx8I5-(nTHFOl~_Z z+Ha5AW=7m!4WC3*6(8f5wkjJ%8+h%AbJ4NxP|Wf{s~G38W3uxt*}BQ<=NJU`q!@Fg zCrD^N`B6aQX`X9##@u-0GX0dLdI^bxKPdRO4^q-nIY{__$qY-CU&de&a`*#3Pa#^e z-#2+!Y5ifm+aVZ)y4_!+f7X{wle1_DdZISX3JoXyh`+aT`5p{b$p0x6_#2-05UJ&F zznX^;JO9u=`4Vh3w>LMpnvkR72>bFS-E}gvL)yVceS%!5GUM71U=AoXdl#}&Ol&8J zcJ?mpul82B-LN;n3O!8VVq0XImg-&2o_AzUpr5d*ADtY1z`%j0T^QByq?|(o1TCy- zF*M{CnLK=50gazSYY{|aRj4)NVf@gpRGx?(bIn<}e+J324dczu&;>wjFFOWCg)8No zdA}j)Gfvq+J%{ooY5zROs@J8??L%DU&6DwM80*8fWx&9cIpF@NC0m=@&-{I$j<`rZ zsU_s{h#Jy1xyOEqNpUhunx&LA2C(ZI0&l*!9{31O_Uh9^dYbPLyew)+l1ly&@U{{F zxJAV>W|*H-o%NA75HX@6Bk#+{RxcfvdC(t)E2R)nHx}i%37?ovJVG{s|NQlWZgJrN zFisY+L3p<^mA$W5c0RZF-Sxm4%SnZ@aVML)cV~mgZd1IsBj2j)wCkU1))+ZvWiW2h zUO}4ZY6{sM?J?x9wi~y9bmQZ?QS52=%tj-f8sNYxJ|>cAmQZmdJ?9$N$)=Wa>@Y|b zq$HRij7!*JI#vj6=+)i?NKD{^L9hc|a93Qr*tru&A_tE5y?(uELX~L-?U*9%i!TaD&y> zjAQqQ<}qHOPO%2I&` zxnYPvOZ*RfmQo zl{m*3ecudqcND^3EoQrC?bda_Bu@V0hTKKPr7p_N?oK{^pDb})`PYLKdLGEO!w_(2c|kg{p_8h)16G{bT< z&V%vPl*-{vrRR^+nq|-cADgz|=K+X{Yu|73xUkv3_%3V@rtL0D(WVD`V4?-y<8`Db zZqqlVjqKEu^yuQJrSoQkhv#o>YmPd>pcuuEpGslMnV+x62sGPVAWC_2qq`+1Zr6|_ zEt!PdQp0o>0;bMt%(<%AY4ozHgcw7JBd9tC_rOrBArsOdYWq)-vmT~T*Dc!vOy%s? zmxsV5Z4K#28$`Rhsz(+7{c+q&k#1|u$ z|K4Alz})LIa+G)w7=X|OXB+I8Bov%Zj^cRkQ9H{*oOgz?W0~ppXWi?8^}Qt7g<0S6 zp@ku0FT*_1=G#bjgd%T1pYAFL2EnuL0rlY^0|FYN&B|`RBIZ^}T~w4eB+$Y2^Xx^i zHIJ_GGp+HbJjR?#>gFolcu69rs0kxpuy{d|-!#@@ zD#mEq#CV^pmRM5Uw9LuAk7S&8B-bJT^znU=>!y(ln-)}m)8Bd??96Anuo(KWQZ>P4 zWZf3Aqis1fGNy1CNPn5&=psS_5^Xz6I8{Ju1|hNpSH^BPMVRl(7%F9s$Zs0vR|e+m z^%l~yw&w-IHqG`AJ#*w;rWg#CO4>12oV-g14Aux_&k-U**PP?U%H6atgfM7%IE%>PR4;t)K2f@IH&XoWjH4o$f6}S&R zDC>bgHY)_zAdfZ>BGjlOZ}`mB;nVKNDQRLV!FGx^kYrLO0wb{ZzJ1~!aEfZEX-hD~ z%WU3=T;>f6cr|~A#VR=9j^V_Yp1Mvs0Kv7^v#kyMI@+>;wsEc;zCX@=V898GiQ^q&6gHhL;O}eVmh#FRAu571M1AaT=)GrsS z;mv^l*{r{YfyK*~XF5}F?`w4%!|c+L4?@RRXI(XM{C*p`8*F5q>6-ViQuye8hWbw($KP64J5_-*1XrGcXebdk6pa;B_tEHTwk9ENIZyQ{rtJoQ z=7^z}Vqb|jw+lAK_O3le4VSjDeh3po;dTjg`PeG+*^+0eNE;&sE;f9b zsqFDnhAGbwic50k!Y+aALH{)6tloKo!1gcg)06ifzZg<7l#HvA6=EO=2~<%tT#0@n zmq|{+dqZe$HxECw5zqWNNZnrXFK-Hd$?$(GKYNkXBd* zNarV~U+4tsmb#KIMAAW)rgQcM`M%w-msO=mB`*0MVotJdul@q4R|OxkZUlmMKL zTQ3&u9YTZCtfk7Do5DKeU{w*1)05d-o>+y?U(573R$|m!_qnf_9uyJ=J~UYcu*tR< z3&AI5HbVnH(^q4c{p=J4^MIektbVD|<+->xE&zV0P?TSn91=}kHn5?+jFwOvKxZjI zykkej)D!HN-7p={WV#CKn+2aH6N5kh;Sy09x#h?YPF_%Y^}**w;9!WLlmPl z(evzRIJfL%Gx}H!WcY~G3S&1DoE?*FZuU!CKNj##!=`p1MuDS;nTD8_`*oBtnJB$r zo-*H2G2Lp?KQ99R!dCIz-gpy^YL_?p^>dFqpfdY_BU03Uq+`$lS~4MSB9YF{phF9? z!5>5sXn4psmn#i_NNWLpQTaq0^Yeym0}PCZ5oowKY`9Sn&8E;XkL_Jp2utJf?i~Kz z5ns<+VFq7M9HbNHFg=RFi<9`L%D({dioe^FE8ig7J#q~cTO?Tc&jpEy&f$5c&@k<2 zAGzoL78p?r(wO1<6%*Pl49g`~#ru3+EVJ9a1VSU+&FHuA>e0o1JRJ`NvCo@%oaDL- zk|dzvXff~;IJlOBJ*|renydNz#ghZvikg{eE+9-eDb@Sb145?YJ>!{AaauohtuuPnQ#kb8RcZ=$ z$uN0J3y9QMTMzH9)vM9cWxD+>LF?5VXkum(0up2u4@x)Bu!zglX$Ncc2s z?Mmxy_Z~)lJ)@18-$+v{Ue>kg2jZOt(J-^k`U*RI#f{> z4H@o_KeWu>T20Z&e@6otqN1UESgb3ZvfBmYvwNk6twGx9=-gVNKyD1%1LW1+QI5ap z^EjQRq`kOW*d7KxUeb1QV>TN_o!K{gpQ-_MSENIThr2!VX|@oDxxMN48DL!V-&Qf9 z8B`|Kz?cL0Lq<~bZkD#d9&)6H0qLO4ePAE_nPuFO2|l6J34 z+QKjo3jPbx57Pzl{9(G1Pp(ioNt5i6d%1}7w`XZT!1YnHGb1$DU%UKp_`wIG#QL1A z#Q3D_&P4YbP^`z)=9$`-dFIk-$ZUV024mxX{5~C<&<_05)rY zW${x7MgQ(4+MC+$VvvE2O1`A@dd=xhQXxw zLOrIXtxcM!&?r?1fJoB02XPK<$Vm^ZnI33-gFH(j8-Pi z6|hf!XNna74A{x{>c`~!G5LPy$!9`v@0o&c1u3)27dZf$vwt|_y)+C9OVvCBxmo3f z%sN1g7KNISj}5~pdZ03JLW?ji?6Br+W@E2$Q!`{cBeH`ITyQn41DB@=l#6l3Ht;B^ z3~_iMJ%-b)!KLA9pNGOQC@qU^t+#WQ@|k(@Yy;d>jEY>x%QCrt*BOAYW{^4so5+Zm z(^L#|#yNmkPGqRx>mu($`hHKcX}=b1@L61G=rO@l50s6^?p{@iibcm&h3#=w&xj05`QBd z7cfZk%WRmA*w_v>0e8AgT`Uu6zQ3E>k4?!dZ@CMB6Bbt+7$csz;o1H%JpU-eQ-)(^ zL_-GA&fK_sJUsW?LRPWB7IfD>DRH^z2i)m0&#AAX*d4%gn;3hyJQL4Z#a9|dh{3i7TrfXvX;0x{L%C(tODc=~Q$5g0N0r9*f2Ojbe;DZ@ z;tIr}_g<&%w6|KKXVD#pK6u+-ZEprU^S%t<`X}jxmoPhik%MzzeAaixp40>OCBw+@ zV_Jipxb^5Q3_T`Gh6c*qS%M8xk2tM*bOoVly<*((3mqrmvH{5%_Uo+E8T43-+|J<4)>7S=hb7zB*-*!N>cKBaRhyVos&s8@-G=JaSaO|+UQ-qf@dC$s zdG#%tSEAY9d4rx|S#Xt_blcRBLtA6LdunrrT*_+V{7gFPJjzL zEwtPglpJ#j)rnK7M)Sdu5Q4lzJG3*N@LBExo@emv1D_vbBJnz!V=K%IG$1tIL`_Y& zbrOwBFo5vGZP>*^B(-2%!GkS{ta{>^l+`sR?36$ZegvKk^cLsZrh36HIU2#LZUt)K z*{^NA*nGEc_yu^Akd*Uh&o|$pj67j!CJMq168|*S6FAFa{(IFLq{VDT>IEpr_GnMv zr3u(;F^d=-i;0U-_-mTcn*Id4%N2;=5TZ&~T8u1%z{b^P5td0eN8np( zGQ@DPwc2g3=62b5-W|TFEA_&9tF;gUA#2_R<5U%jbng6{CdbEzTotoVm|6EEnV~~l zSCn#+T!h1kNe1Zes3dU{1ZokCXC$GH#`Kq-$aak`Nvre~f5t!`<;{g2 z=$_uYn;pp9`7Oji_Lj%D70M?PPqs)ESb%XbS&H_U0BS&$zqFEsxy?8dWfPx68@rSu zhHOnB6GSCLB{OJTrWzM1NY0R574;;VR-)%#B`Q zs1&C;xPLFJwpTgIBnaz7&TYn^!@OjUC4-hD`{oL~m+OQif z{*`3fVr;TD8-8sET4APTBhu|TaP*b``W1kRlF7bU$`JnpQgjhKc z1x}u^4ghwjFH~d~$rtP+VLGV-q8patcceY&xwN{K2hEe z&C9Mxn|Ap=3!d$_5AAXhzEhJFFPc)_l~Ezk%tusR)|yf!CSj;Ckt{!`Yu4NZ%Wd#f zJhc%X9`mKyunuu7o1oB!e}fz4Jo|LHwYe#2V$eTGE}jZ+8ttDRB$>G z|N3R{a?V(K_~}G!_(sz`t=UVe)GNk=i@;PiwGP^IAm%^~t&U^+ush6QLiF6Mb4TOJ zH67dSC~NcseO|Zvw3t;5Q?$kLo#CB#2i9CXuV~)<3>-B7-RSyGFA_rs2KdQMKfI2f zH2f#|SWRxWww|yTk-zny!0|zi1U`hMVCk+hn^pxF3%Xg-1Qqnhz+d~o2Ds`j7@E9X z6t>y8KRG~|`~e19p0zx{eJ=>x{M~e|Jb`d&?I0|XdV@L_ z`0g=veA<~W#E9N!-Q!G2cp|>9tkclO07B7bhfekF&CQqo_SW-x(*RC_eH@-<7p9d$ z2g51y)eX=?Py8Jmj>`rVsntOmR<;3o8muKZ4fsNEAjDt~_vpPX?O$(h3t{V@{?hPI z75_oC7Qu)PFabB33jL`!BOTt1dd9U(H~MR|#UyFTdHjX$4%Uq^pl%rEqX#sgvhld^ zr3oDw6D`dYA8N6aq4nGP^Yz(I&dcvV=wMDEOG z)!39q{sI@J=|aJ_H<1OBqht1MiPIiPk^m+L+^_)_T}A~Ym5IZM`Y_TM_rh8~U$4KH zJ9%&j3q7INW%3QEW#4*S*C1%JD4rzYv>)gUU_;75@NC(O;N9UU!a1+Nx+Dmh6j-}yx$du= zI?Q&15tfg{t&A#F{|n$a#U)S$Ti4o6&*#wWhI z_nn1IvQfPhh+=+ROd0t)2E7Qmi*mVKD5S)R#vyNSNxoE zkXR0AXPQ(sx%_~-KFWnbg8G6MAX0-eJ#`k^p?`(|+qi?Ia}s^&3i5x=dUXxbv07~WP#(^gVx-0fohGR*Ys7u^{GOu6Mk=dznChJ9%~V|rOqtX$Z4f*` z2M!%`P_3C1k{wo=ny}G?dqgM<#~`$+2g4!CUtZr6r5L``Df{M(rA4I2Wp3+10)D}_ zX{RHT>SGM{qfe2xM~>>I^s^pLRPlI*z548+eXy_Yof;qTYs1khaIBEpF=wN_0vfk%A~N~-4AteRp}I^62j;(Vkxc=ka2 z#ctLK)kBlvJXWwN?vD8{of(=Wi+qApBTz1h75>qn);Jvxm!vp8aW7kR z7gK}F$CpT14jHlu{ndHo*AE$fnrT#x_!72H2)i6{A^#)EBFlv8ZfrmUk?zk(zF;&k z!aSotcVZkNT+CCBMFbU!6@V+0kG3|p{$aw%Gq`Y((m(Qa6aSMNz=_zDwQXY4A0mRa z;op;IqY@I_x=NlXA9dogw_(v1j85tZc$iEsWF0m+rx}V>a(MFI-+NYTt$jEfL?+Y~ zQxAXAgc*Np#r-w)tVq@Kb;FJ%`j~NTIK&sJctiq}2SEc+wQKbdU?5y*?4W5FZu8IB ziDihE1^?{P#*nk|Dew;ghMxd3jIOoV(no?wVi5tWgZwhh^w3}Xn6TVx7%=Gkp28@# zUbg{W0`LS`(}jG1AU7^Ek~}Mo;vE>KsKM_t)q$Fjm1Al{*=^D~`rD|VwP?zPw1B%o zIJ8iE83|~a8j#=uEIuWlTeM%PV0ayK!SAqmZ}c)T@rzxf%eH&Wk;UDfZ@pu;pD|{@ zE}Zpc_>EG<>eN$S>|UM6;G;ajAVr2iG=wtFX09YfJPezKzwah3FHvpMU$h9c_fIxs z2_nItDrx0W{Jo5q&6`oYY^W}4J?%pDD$(BDZT3a(RyKak-6g4R_Fg_p4R;!c_8=yY zb_GUq%0yO6u1rj!k#!OgZg~4<cKtLYD zkasZ?9vJw08OeX_fup0k7v0b{R%MIuh$ELv7$)?Xx{tKb&}A z0z^P@m-~C|gOd~MB9_F1t?idSBiM^YNiYYTmiuHng_@4*sQm^7)rz(xwnX#^K$UFfYI1_+vB2 z0Z?Kqu2@*}>K3+0+mL0N5o4=@TFHWH@ZR8lIh&-YMW2UHi%vG-18@t3;Tdnb@3a@K+elfGOH591jWyMOuP2_d_?yE|JZa7v#ujUCq*YsL4DARQ zZW^1&jNGi^K2U`RBUuKrNa+r%x^YU3c~4{YhS#zu1mYxg#B|m&_RpLI#UaY|Cs~V( zAcXdX9!1i*I4!%L&Er{EWES)hXXP3s_G>$+F0)(B0VqR1ux@0$q^8rd3U0Kwvz2>h zdpRy?>2I_Jptm|QYPsa8tbX(f)|Q1Yw!m$57XwcWk0WZaLDtf1O+biDC&@_S-J`?= zYSiZ}W5*a|CM1KydIiwM$_qk|sLg1OKGEDU){d5s5e$?MG$Jn5SnwPf1 zAfnT6gLPW;+0gTf{*QLq1rS=sUZ;s9k!%GVl?ClcbmX#wY>jTWeY>oPucA?22aR=> z;r2oM#N6bG71&>kaIrxH)S>h6Kr%TSe*5B_9SiFfj;y#A8I%@>H#VC-cWaJ(a!6mnkbpAAdf%+=I^{rRf>@yS?&?Hoc%Q7g}J(N(yAF z1Xp7VA_P1ELC)69q6JK$E){ha^|+1uMMgV)a&!h%V;F~uZJ z6l>(&;hVV-JcS(&)@gH&)WKn`#dD^fWqMs!jw1gZ_0Cm<1VG4u`OQ{qss?Fl`$yC- zQ=?Fw(GmKSF~^d?$t0{Kiqg-!BV4E;)TGRirnLVdi_>cyNV}tSb94Ku#d#wc(n<9sN*8mx;X8#JH@CSAK5Uwh)Ukbv_B_JvfsZp6?`H1rUUk{4na>ph9@O5) z%eNmc+LF$X$PmEyV38S~xDt6VtIgadXG~se19HL{N6%=R*qICVK9`?K{)65p{dZ&T zm9ROkuAX6aXZ>ae;mb4-$>Giho(P0q`&2VroiZNMa%SFCdK9g$Jw&%^k;J&zOduyQxOuBq^fU5@BLB z+N!bOu9Wh&T5nya98xSZ?A2DVH4jQ`X2mC9`nY*fHwN7GyM<<$0XeG8vHCG*=a}?e zURkc{P@&9sGD@#`m9sV}yE)J7ISzuTH}`V&D99P&SIrr`AmTO1-U$9@;4|4=GMdbN z5@KQ+^AU|>1Nn=*;mm>MD5fXF9Y_l4>5Qu$r0~<#GQ|1(k(e6JAE0x89Cammz@6Cg zD1kucHb^~Hkl!CMS)yK#R?#a?son|ZMR~_Sdypoi=L-@7-p8P&^T?wL3>05YLD;CGh7o>Lb(iVVX$Zn$6;Ri;yE#a?8a^nFNS`jf+8>6%hxvq$NUG()V*pq#SW>c&;Z1AtK zzoHL?sKJ!1HIGC5Id2%hZ-l9^gl*W)_e=or40Dp~3rny}Qg&B?knNqK1)2b>co%lB zqD5<^+bzZ=$9!ZK!Hf-ufB(M&nKXGkvM@=mw{Wt2xA8~y`b>wXrZQ6=^1FDAFigh)WPA7cZ|IAqh6g1QN}->&`nb&+a~|D|3~?9ifOFx_1U%jx>w!L(bc@|i2k`rJrlf&o4Wk`GKt?Qa zJ%k)!zI`phDPA1{SlreO+!pw6frE=R=n?>a@&^$eU68gB*2_9gCq+zqrN7a&4bHU2 z-qEQ0QUFy(a-_GWDnh z;$`Pd8+q}0uwes{iPc9(wr6^$AxmTi)|F)g7*M2VXVCkk_xK(LJ_K2UQ>%U806l(n z4d?L6=Y0?^)cPZI{E8SBb7p8LifR~?L(vba2<lhgLnV#W@ zB{(qwj>f2O1)%$QAtn|!5t|W$%V91Un*49i#SR{SJgMT-O^YQkm7^UP(@;G22EE!v zEH*f!13RD15Y0&9q-mhI?`IpzNlzu%W8`2Yk&#m+O(HRk`fU^OQi)b%ZrCqPY~)l{;fC)%nML%fQOd|+&# z+SPG%Gg4z4-r|^g=4-YF=FVu`@cU7ZRPb)v@UO-oe^vRuNW1+HpV6NaIN~`h4nH7N zL4Yfxuo!F%7e7&vcXIf86707Q+qKT|@;(RGU^Ko?5ul1X03YTf>4w z?DW+CpZ}9rpUIqF_y6O6x(oyiWtTPH{(9|o^IG~ZteSD8!Ov{sxR`#&BxvHMn+@iL zr$y2s(bZIeAD$Mf|I}ucqn|QJp5_fw={Ag)QNORFyp+>VD*#w&)Db03E`}f?Y*9^W z4vk`hu%Nia&~}Fm%v!zu{J4REu!HS&4U%>f$L6|Uh^fuAf;tR=b+8Yw&va^)P(Kpr z2o_pEipgo?^damR^fdrWRo+tF(P{>_Sg}!Q$A7*PyqHfP0}uU$1|$%@`hn41 z3}d9RVAm1){eDuiyT)asCwK77p#V;}16C0)(~)rD9TtAM;#iZa#q%eG%0u@K~ieJ!-u>cxYby4#>STP75Ueg9y zz}|%LccF?S?RXuksA~|jBIk(Ci}+4XPPG6HnMpbW{idy4j{hk0(5>#~>3YMg;anFL zhQ4{3x)FPgyBIqW2@RgPhrwU%0y1(G-l?kv-@PGjLBLZr9K==S5%t*Xf>b%rgT-vb zTPvI3CW=F3oYYS20^sN2oB_|WGRV)jX}avdH2K(=C%}Bo!j>NO zRuf@jge<@Cp9eehMrPW?_km6W+p?KmU;%2kPZv-iXVMdDWRiUoi`S{ugLqZewmLK|l4xjiy{qABRj;4K;0hDx}6)pbP@j|xg1*df8jA-KoWano?AaCCi>JR{*zrnz5Pnq(Kr15+Z4I}Rjmw5nDZd%gq z@8IOjO9XK7hZZS?Q&p$(L{U8Gy&9@fnJIsFkjTdt&fg|x{)#qlbYHVy3|$v4I88pB zeR$&^U%va(JO#w!5BHyCq{3yXzeim}3qj#e3&$HBXD$x-?aA@SgSRJOIL*tUW`@(j z9W*xI<8AHCzWbH$o!N5pH%@MI)1#XVAJKNOy%W6NT3m!@)CO(bH}2$?E&gzpFf_G9 zF(h!}p7CAx*v;OhI3Bl|y$E6NY3AKvX0rh46kZN&oWj)7FhD#_L&Oca7Px$RD1cxb z!{C{t)BxhyKy!bnr=1i^VImA#auzvf2=iJar-D?S)n>$seaJy& z_m1|yQ7}y0;l5qQviiS$v$%V!NRU(VRa?a>OE_8@i}Ob>Jxx@U@(^RD){q`V+%?Xk++zm{leLp*$+kaZJkLoj(+)vy zYNP2a$|^QQCX@AGG}HnMP$NCF24nYjm2Y__g2;lUT5< zC%e_qZ%2Gz$l;|X>&mk)TF1q%c`(Y{Dq{4|?NDD=P=>(oVhmtZlaa{JFkX^W?=(H& zq*x1$X4sTj79r||8DGs$urs)~Tn5!ZSCc7+*AH`CAz9}tZ_%3Q4l5D%x)2mhvQ%+D8q(s+%Q``8B{zV86oyHw7)_3S`#`r3Rf$pvl_@5gZ4KPq_ zVk4WAHZ3B0TSA@=9O(w~p%Jod5*V{^cE`H=zBT*2^(9p>Ym75b*HJcY3CM^Wh~ZQ; zO1w}SytH8S^@A)N8{3kBXrvC$QYe=W_Cd~)h9ueMZ1|YD&E(}*fFU05j2$hHu*jXR z-iyO?^NNP25MdD}yVC#~2#1l!aG3&tcux)U@|# zG-ba~xrBtIF1dpfiGW{a`2ZN^oVkM06!sq}&-@0=vncNZBorc{g}$mKOi9RN!0&;Y zyIO+H=cE6ujLLF;1! z58L2NLAU`(^MbvSrW9}yIJLsPM#74#?SaZ7oKHt+htrKrIfim$`Hi+o24zt(jF^^# zfx{~}waSD=%qD#=n?Q8DgXm8Unr}&pW;=49uC<1^RtXgE=oQ+L<|Oc4`VyEgt?R5e zUCEYQ_A)hr1rRZjn0E`n<8;D>0_Q+)b`&#P#f6$!Pg%`S%)DJHwDEtIkPi>w&;=8v zKbsUFlx`CL)P=-rPG)u#*W5o16VxE`>HBC%5A2rNwMzow)jtsA4Fing#8>#*xp2tqQ?stw|-B znt27#mJN6>>nOAahi0i2&R&3=rmsqdj10-wr0 z&7DKFp9+PU@O`j2!o19m8WZ5cGZpm&VyKQ_c~E9ZkwD&0RCpr%;EvgZ9h>oGBLe!x z@J~;nnaRe8UGvMy*)j*|hj$;}?;Y<|7WLg?nDkpWbiz1r36-ls1Q#ST2JWW#(<+Oy zyrqfg>;%7*Y;wL-9mIORJ7hHRQCFe+~^n=UqV!N~Bk4Ehl6x6L$JR^msm z-`(rK7R&nlFNIwkGKXvXE!}Lo{eePDkl%07-5&<%EC^OvYtSu%TlH(*jq+eOJ@(~C zMGm1JIs4C%i?#WB^Yzvn^cy`%l_EakvR21#0OAx3^t}&e1`9*u< z&EfHzb-wc_Uo-l9`{c|&KY8zUjej8tjhM>9q~AVkJF2~UGbG?Zm^lsG=5qJ_yI3hf zh&rZc@Fiu5-XEPlj?Bp`e>-^boVC^$a~W;m9S7DEddBYMe1`#X6R=8XKt?PH@Z$o% zI!t^>!sq-CYn3?s&=$C18>r-<{3OId_`KzWMf@d`DG9EDN&oh2`nOYTSpcAl1%6Pd zm=OSM&wg8TCW4gbZj^j8jvGMkx%T_F(YOY|UDS9&80@Z~H(4@RmZPVH4?RmeSM;GJ zZ<`n4N`{6K-Be)az4Bkt%zrf(?R_Eok;E*-EJ=b!&&2XN&4-<0ZcI&;HF#i_CYRjm zz}!gWLByTMarzxW^5b$e@`?i_Fa<2o2n@wS|07XfxXUPIIJiA#1VH#;L}xjKYrsD& zi)o?dbA~_2?%N%WMy;+UjfdGj>%qJ2B8|K7;^y+9b#l-?2`n{y@aFL23Io!QdL-&m zUvD80duQuK@N8}&9au9u$Dl}nXM?2BBP(tSw@oxs^(4S!TW>KTy${-iyQ4DIDZges z=gcCro;n&s>T%MAq)HezavDBBU%IS8RBE08r2NDnx>DB^Na931JX8{n%WT+zL-s?B z9;62M>B8`GXniEVQT+zqS@E;nd;ZziH{)1fL1AOG*QGG9Q7iN}hDgi*EYWv{z$GGq z5R#<)#+^~C<ai(jy|hZB^c2#d;M9G7v1afJb5Y_ z0fOlphE-P*U?gZZu+ibyv#OwHqsLtC+kmrSq8`9p8fInym90x_o`#cVp5*KaP$IQ2 zb@>;DZh}E>x3;8*I5Ts0I(xO3;!gL!*rHA+Gv7@-IuE1F79H_hsocwBID-eAg%ef` zl$^QB<*}piHo=As#hfK^)4<8t7RW1woFHI9br)W&A>igY!*And42B4{K+9z0Erf0d zj>g$h)3VLpC?`S?mUB7`)!B5KE3Xh6@wJ3ZlxCI&$pvS#BOeArLo4p)V9;0z^{7mk z7GgWtei=M}359)Ud)|sCxs}tTJIF|IxwWPf$CCb0>JV?nePy{55Q@huz-4`(6h@9< zpmPKqQx6+v#o0uZTFQ~}07eo_+rhD%vUxA@s$_U(xq;uemLLxRO1HalXeLUnHw^Zb z4qa#l6vYCT#12EO76woW;pi~lA|ONcWdQkL1ohrf`K~6`ctmpsayRno%+`j zIrVI?rfnP|mAG^*Rwa<`d6Ya3r1r6ET&q|Mi<1yPC{XXz7f`mX3?l zAZS>R)PP2m>SPuEK*xDha?Xas1zG3NPWG}&@VWAHPG3gYx|sQnkpXz+i=sDglE4)hmGGtC^KBMxgpY6<=sCV z?jPXYnTYn;X0S77Qsmza5~_t#a~$;!iqxtW)utsCTb$L()#W0<`1d@GOBYp)$-x=| zVsZ*}OyE1*aPuHzXzVc#8&cbfV*Jy_#$+-9XW2~}cDgWtZ#>`;%fL5sjrid4fIqaL zU3R9Da#16Zejky7cARDdWEv*)rG)@z94jm87}7x|)4bOI^A?65{r}taf2J~E@N5Rm zzx;guSgu(sj1t^nDZ`MRlIZ4N>|Izev>K=gRgE8Jm|dU{FcyccwVpR)29pD9n3RG~ zVaIGLE=g_yYX?TusoLRANse@2m|@R0%OylO%$i!Gmz|k!N(A$emYoks79#~4e_N=n zqgQj|mr1TO7^(oE{Ws7Hb08*VJ(i)qJ}nz`*5bKknO>m!n?ya z4LW`8!%VhSZjj6+WI{0C(O;%Y7a!iaE$xS@7P>h+|j&U#TJo7{=44=1E~2fSVju6?CcuXn~wY-kM8xd%{=o zfG6t#k}CiR(;sk#PCRv1q}b4e^E^9$_j&K)&C}dFfA`mu^R;3mA-L!7KE9{#b8h&v zb`!^-%g8xNdTEo2Jr&*#dK=Ga4~*ZHk;;+LsBw5FzlY?N!DJ%gaq_B)Ip33}Jiwb7 zbE8sNnal}A*4{;mD#&@^%rc#|WJ1^$`@7Uv%}&|RO(yzeSgt0TRIA7K2eC#NPQ={0 zw{2%`1HJ2YlV;XS=!*$Jtypu!%0tVLX3MFEV*Hy3id;Go^; zl=%jAOvRVH44#}L@BBS@7)WsBKdKO-6%xS85&yMebBDT!b&6(#50v$G!=$aY~7!IUjnMmKV7>#8a;)5gyyIsXrJL@mzs8lgj zW2M#VopJjygoGj`)W+;-kY)gsmD4q$9U7JpJQ>;7h%t8HQv=~EU}cn4$fAs3Zb69dP%{0CS z%H|z4C-(oUhW_sGRt;Mjclv5_7L9E)qh`WRN1aYWuK#L2i0tEhL>wvU^a`O^IpHc| z{Mwmh`05@L-ZUFM#{3u1ed#QfWM2BPV@+2~apTQ6gHG;YmS-#t*nWzF&W|{kzoVhv z?&S?{G>p@{_!H|PGyrA7mwo)(9X0@l9o@<$G@+xyPMmg!%Z~92J(_|%DkPbX{%z3~ z9|cio>^vPL+@~SK&g4&1+V-bKp0-vs5new7cumr~KX&pH>22vVSwjai)9bRb5>~MD zIXGh6zGB$qDvVbDx>lWue>1wBx7H~TD_IYMB$3ZVP$HsII3Mn%f=SoBtW?TaqZl z5mty>l*|~oF3_2v=|TvaclpWMPucX|DPc)t0+}?{fA))7S)V?$)ql#D*T(5Y3q6>p zNXG4~H-JOXRYIKCRpX+}tc#=^BRs5fdaxG)mBQS8T($R5010L)SN7a+yKBsqnvIW{8>|&~8m$!6Cv$Nl~GwPfJ z=-`5po_2Q{hY$9okscwjs0L5Z{zQLfvT^1Dq8J(;=T6YZ1F@*vfFjXgONt>)(6C|! zRT~|;Ez=^AQeP%jaBgUx-l#$Rsu<6ia-G%h2(#%y4r_Q3i6wp7J_cHiYt3%hH;J_x znga&Q&=mKmp&QcZ4OG1$Ew!6SjyT2{Ms1tRRbi@mPXMH(`MnxXgr2;|DuzqGWBg(J z>XN2z-O>_XU8&wfJ5hDj_9f0n-aH zB>>(~#fvzk@R?)fCt4|gqfX?>;WwM;$R>aJ8~wu2YOWp5u_}f~Xx2L9Xz?emOtT5$ z`w3@AWZZ$q#bHdHvoLz5yGe`8Hu3@W!v_7nVVk^RYu%`TR%yt5ez`e$T*$KWIJLOV z;tSyv97uegom3qmfiL0Nj4jJxnVYV^H<{ShGv?Jn8j~{np800GX(7eVRT%@ziFEr+ zNzuayksu|w<+FMS&S&cD!K1gJFattOu<7pr^LtV7p~sR~eZhyO^RnFWi@)~i@WLd0 z*@*HSuErQU*V^Hy{dF5L=1_Q@m)xAmXXkH@x6NUVb)C}*3Zx&}P0E7fSvg1vKjX;1 z{Ioon3~X}U0g###80~k5ao*~xkZsr2ltA*PFfFIx-7((+d~1>DFmmP2V-g1v|5zpZ z+TR`b@wY|uyGbILJ2>9zC`tX}G!8Z5r3tF%p}TkGO5m=v;Gaio#f zygQ;ML`7K3mmDZsW%M}2S<;uBKesSagLI^;mhQ!P=@jpjsVqgBBz+}yp+z?YQQ-_p zkuxKO^ra=XB=_>lJ-!9qz@Ai(Hh?jT$w!*+x+9KWRn!jaH?O;y}c}<`GWz?ncF*& z53NXPKseGJTp+O5#{-fC#uS-Gv6hR)AGaQtfWoTK4o(8VU2z6@4VbvU?(^? zzgtz>?NZ%pm!eJTLAr)sYSR_Qb2YMZ!6{c}%c8xEYNX?|N%A{wd1--kw z+6&)e6tD^5Q1RDHdxe|+L(KloHwmetB%G~Dqt}gI9wnFqGy(tq|BC%J1{#pfQ#d4H zRHe4dF1zMle%;_L(F9N+R2hPllP1-gd*}7X&W2C4xH~%}HopiE5dA!OJvS9T(UwJ% zJJy`}IG2dZcN@nbe!VOIv_ixc_n-;%t8#tm{1Mh{zY`URR^uohqE} zanEGqm*h%D^?)9iH3hMdMPx~&q&3HxUKQE1XI@~2nYfy>y|k+Br;4)qr+?$k=v~7< zK59^N8s6p6ng3x#5_7GP|A8*9iQR6KG}sTHj;cgYQ^Y?%pc?iMkA!^OtE#`uN`1+2 zxcJxKYWQ#Wsc3teQb+j*aoK73KOZ-IJygk6v>dQWk_q0aVcAy`eOaVAML+&cr8W2O+_D^5O3*Je|=OfVRS&ad4F z7hGt=Cn~yDyS#4uA?BdKnnTh$q)b#U$KFULAoU;AYra7s<;JN{-Z@i`1=0|hRR<}^ zIO&|bkHAs*3V~JyU@$SeKmE&7R|ViyBFQIQV;H;CVP*SKv5v&lWD0GuO2)4|nF{E@ zKbd?kUJoTLg2t>VijEMdCk>CStDMwobRO2F+2lE+xYmNB+0;%_4&&)D`Nk)iQZrOD zc&ELyljFUHanv>(+UxsE6N6x)(M)&e9#xFKrW%o3*)H2}#MDd6UeeTTmLO|j)P@Zj z4$nI`XCdao%z0>3%-V2L5z_Sp5Lf*9B&Hi%w^xHVslYm2QZJ1Y-Q9eEZ)6{8`5CPx zIx`fApXhrFPhD-nj~I>U$4vh*)9p-`2{AL>YlL=r9atapxH_-tUeC6JsfdhGf%_Z) zR)&GV{a?a}_V~BBR*I5nsYL{wrVhNnMxP-4tCWsa>pSmbYx++T?P<@T#Cyz!E7{e@b z{7=Fx?la!&b<#DggrpVzoHF8e?!O6OU5hZ7krGl{0>epQ21_1TeYOYdF&$0dzs2k1(is?zWe)JVXY=WfSYg^r`U zn5M8|D4Z>Lp;c_k34+y=&-(TW%~^%M0bq^ojA7OzMe^O@o2R)0MT8$gGV;(xg85Hd z)6X=8bYgG3+1jG^2VH-SlL6|Tx{f>EsVw$?4*ZMKTI+GsCOytpThu$lFfDyyzQ@{w zf7Uc%KdXKM6Av3;N(Ra|*g%4_%`JdWQx3BQ?uP&

W4$WUalf}0mK31MN6zUvBVlvfs56fs4z;T#%^@*&7%l#fny}4 z#*oH=SQXq-$=02M!Ujk*oQWd`J<8(vI4$^&x=A(&;*wm-MdI%;mD>GcVz^r%l3E#2 z))JK!?Wgi6mq$`1C$3uHdJI;3?2c;_Z;esSc(MkPIFwukX>P3resleX z4&9n}cI>Sn*%Bi7I?C;Lb|1OS=3BDL#LPC!>B%!0@XN$c-Z=4D*0$TpY-V~~PICyf z=YB7Msl}60rD5+(W&-06@k~;-E+a-4aw>642r)Jt!UXGcupF(yMgg_q8oOUinZ!w& zO0~TPP18lDEw6ITVyU2K$UWquT@m9|oEY8-y?J3$^QQsC;kswXlSA>lZ4yKQiBmR& zvdaT9f*8Ygt1m%SR$D4U8kWlCqilEg5J)Ey)gkd zVB%vJ*SqqD_SC(~t&K!Z0SQtw@-+w1uJ)zmtHbVQ*RRd4z?E$wFtSLQDfxV9Hu>{X zxb={)245MhPmR8R3leH}>h13C_U1#cNGMwZh)`Md(AKgc{Z?|9LK$=nCP4-cS&;HG zuNIeQ#Zd?`br3GIb$COj*0eaGtE5NeM2K zv9tFr>*8W|)oe-ytVBA=Dg&f6#wuz&Vsrq> z<-yYH#w^e|3f~waM^>9-h&TkRKN4m*}SAV{_`|I83 z|M{ogAs>0R{`}_duYWpz`cTTN*B=i1BR%2qt-k)3|M}M+|MPD@9l6TH8kARA-mciC zAO3J`VaBURY+*W_rfVLPJvt}g&z#deYVWkDgtjMiVLE68wC+^Y1-`KR7yA;FVefB# z`K{@~ek>o$&F;2o-s>;g{q@`DKk}6p?C1Bp{eB~7*wg)b3DPiyQBL=n-R(o>uA7m= zF=pcLpKcDk_g4IL)i!VFQy1^QK7Y*qz5#<^xIZdu`xmUZzq_WJ|Db&qjrjSea@Ttt z`)n}!4NouO=`qYUa$Ijdeg7t3;{28my%i5}`BOt@6#(_srEUEDvCBtVoZ67I_OT&p zW=xtHlQt%7NEQys!Xa64NLCz>b#+7gH)Bb|t9#dUi8A;%viVDa#(m(>z{@-0{qFF? zBf$PU#|?SMhhEh1e%Jo^)#C=sC8nUYimsps4$KL(W+>Svtw>wjis{u1CH#*&{?LHc z5j;-t3LlE#(Q;4D{^P&B%AdvDhYEt~1lGQhz~Q??;o}d-zZ{Y9-K)Caz5A2=7=PGH zIC%Fc^7!HZ0&d60EWbwiQ~r)exE&j}ij8Nm9h_6~h~>Ysw7aN$IIYI&f%bbcadFQL@+Ps(5NE<-30%uQJUazo)~kEV2J(V>+m_V=qD@Z@faI zpXFa39&LgI{@IzK&o|GXm%ismy50S~G}6MuFNa({UL`q^3pKG!1QA@;TniUBSkCvb z*dp780aRp-51A^NJXlL{E_SV|-ebu=wuV5*97fq;ALOs!(AQ9{C-!KZ5tul+C6|~L ztal-6)Sfw~QS#;|!WZb@Gy4Lq89vttG&BgE;vL_#Zk0&wC?Q50=FOPzS~t(EjIe7+9PV(X#I4byjFW zf|Xw;5@G^Xycw(yTwki+ou_MQgb7I2l>nntz?WBAYY6soDp}X)ldn3Dc9AWwwM5F( z20=L0Xk*)Gc{kWlwzkd+dlBUbxpkH?gkj#g{#r{^Kw@Q#AP^5?)_lo>y&@}XEUI|b z92{ZxAs7XtT&-&>Ef?=%auK`^7!^nLJZ-qpQ!Ku$(M6I4Wetonv8^q&P|%OjrKl-s z^5Wx0Sv%JjTH#1$MGAHBDu|<~qvhdG7h9hn1Qv1<5KOwFc#OeH-6yN`I}=rsx6)u( zRYn!P(N*_bpafA1PRinhM9tz>{aTvyq5&H@q_F zfhok27!b1)G{5n@FY|?0q9hm|*|hGZQL4M1{J!@RC|pZUDj`y$QIfQt{FN@(3Ienh z7IFMejMg(Y=`yttQcm8-MnQp`M#p-ruC+ohlsP7+t8EM#!Hv#RSzT?hmCq}eZOX0^ zHhtb0wJdY$vSM=D76>4lS2n(-#XdG)i;Zj~=oLMX@NuK~meS}ovglHh6-%2LZBiS9 zq6GqWuAx@P)yiSiIczkt>qEHM1c3`h6;u*=;YKg9(5#6PXHn6t+60NwSpZLDcMXWO z(MHe^bZ+)(<7@5n$j3k}as%x+h>zG9FRT$hc|u59N2Lq$R_nbw%qa@K5G*5SOM+qC z`d*h1jD((9Lv3$1nn2HyzDkY5#&{4{=QJdr^Rw1j=2a>nVNJ*ZB_ar!Hafd5AGG33 z5W?#iRE21H-YtDl7h#RZvwCtDci9Qj#!eNIsxuQjI zC3cD@z10e-E+>I3)uNXGE6nQ1GEW;ts3DTkK+02`1VSsM;T%j6d!9n6=*lROz=`11 zHcQ9RSF1cWE5oD2;pfs{t~K{W?j>pnG3knn!q|B0vYE8)7r5}9gUGoSP1UrCNz=mn z+?(Lhf<+_#&e$@W^Lt4ioD-QZI(X?+?yth{`>?<=iH{DU7;Hn#(Ag3u5BMT+Wa~vv zS{W}8x&)qd0GCE2h@sP7ag`{aU9yv!afxMLbcCZEMT$XLIX4@mFO7|9Qz%T-#-scO zWpu#ZQ_-t!_}VIG8Z#gh1N#lC((f%6$P>}CDn(SLjLt7QmAf#!HhOJYaJYADAlj>5I%;8xlB#Fj>N@m~(TXVs~6YNC5W zd>r~XD(wICGj>ipb*PneL4hxVjMC&6*fOQesKFP9S+bppvl!ru+EKbrTbC5BX_iJ* zoOG;ZR444^@TZ^pk}bl!YN}YZfIDSp4*++y_bg(_R&XxLHcGQ~K!-jVV4LHz!dx_B zu`6$MSA;bYg@`P4*~k=4ChK#3(94?#t9n7K5P1;ZEb}i+ckKo5ijaD;lK7%a7BHt# z=Z5nS*wg!yFy@+UZ`4JXGFzl@=sTKF6BPl%*;rDuY5UvoeE9(C=iVDI+#Kt&&`~Eb zfA$V_z>dJQayw8AMf)-h`u5G;y+A!}0YY`o`#K5r2JBFvcA|k|k`bB`M>ZTNJ0z41flw`>{6kuibv|cPis^`&(-n{-M4z@fH5Ll5RlYtG&6+qdQ@Bl)5##+Y^RhPkj61a3W&V9j=3Qwt@A zA966icR3g{B?sdbf*0uawEf2$utt9Kr2R+!$SLy_;`Q2p+Jv61_D-kdlM#MM!Ce0I z>=y@}q6VI6zOLY<{e*RQSRMbmIrBHuJNXyB>ILU!$?ol&$7l4FNCj1L@=2#E6gq%r zPo$f;ss{(n&K8H`^Z)SGyT{(O@z%(*$lRh~8|Eh6rq36*_YdjQ#V@BlFLCidKVIBD z{>756-erC#E1%wFp}X(W-KlAxt}oNYm3sG2|MKaYPrj$EUG4dga0B zgI3Hh>-MK_i~DIT{_@MeGG0q&0;I&v+4S-Hca&>%;j`cFN60?8)jctahviV zd2v9o=p!3dTmV1g;WN`g(6B=&@l?R-p}vaHx-&|%<7jH(8b*681{|WjCX+Q3m8^1# zC)Ay{&bcKFSS#q;CsRH81?#?UyH>K6bq2JKbFwQk)LYG#)&^G?xyY!P-NeXacNNYQ zmq->w43G;hth${>JXd@bt`n@oKzUBpzjp#jHAI!P;eaK&iD%up+rt=3^d>2zK)(Ni z1ov2dHL$_TR-RvSh?#N2-l-&z#1>>iNH$289lfxe_xdLQQfb{!Vqvq~)BA_q zD;ic2$U80Tqp(E01yiw)7pEiHk6p8h=AUUL%e$0QtZKsh;Y$r)Z}qiOe0fyustakx z%;4!*UIA$Z23Af}4Dul}&dvwba7t*9l9fVPdr7Oa zD)}3w0-U^sn40hv;*7P^KvxYZuWikOR;`bE#Ra@y2yc|jM(5(P7J5(@TqCG-wE}|I zfpzNzD$NmkG7awDOOd6h$rIWFdd976p#Hr&YWfBis;!tt>)*$0)(|V|Y!DI|fiV*f zQ3vSxHqV zAVR{Hq_a`cfpL3Z>nR9U;}~1pJ}tb|Eyaz@DtctAQm9s!6->Nsr&^q`Mxdnw4irXj zjeku${W|FyDLA4AF0(Rq!J4n%50t^SG6pWP3>D|^c14P@TM;X?BSsIZlsuJ&p9b7U zn|r~9bj~FNBcMm+8GtlWcIRewd@SA;1EQzyq9}-8K(XZIV4M`m2LKcjb z4=P!3&_oCuY(~w+HjRtstEEC2)dF}-AA6ZY=n2F~#Ya`4(88nlO}9zNTM;bY+Q-4B z*K-*wQJJQ(V+G}-$_x8+u+d(HR2@?eN*N=|XEvl?+@<&3+71sIZS-DdT}AmWi^;m% zuIjL%Wq|=~(u}{>)0n%du%jhCD=sIf&odLUZ!(q0li9HqGn zOZ*auKKm9AYt$^bCdb;!KPCR+Tq@dalTr|!RvaA4I$6pbzvli^=;{?233m&skdO*$ zEMw}?H(K3fTN263R3>TJHIwMP+XZ8b${r#3%mQ;qJMjk%d1KNkxTb)@uFeEjnSz@7 zE$I*~D^q}E3$7gfv|QYes_jysSfR02a1V~w0PmaKrCb?Y$*P^z*+Xxzqob-#k%J&> zjG$<%iVnt3ocrw7i^ECED(8$cCt+r~_v-JwCok*QgKUmqW{$v4laa1&uOIpew}hI( z+Zx;9w$c;P{~O)8zm){g-O|Mg&XG7*NVlri1>@aQEIlh=`WC1K#%I~zG3!KbhItR@ z+X)0=LEp8O)cQgfvcQ39xI-WhtgK{$sAtYQz8-`%#aO!TnW|Qd(W#n+%VrLGg-2~` z3))zGA{}C8S?G2pt;^0#A6Pkx~sO=U&CI!)s*2#Xg4&G@o6hPUuGn}9W?-b3R z;`JM?1O^LFXlb`rYr_H#IWi?CgRWi4Blza!{hc<@n*voKTAz~;d&-D@v}5dfkjaapwD7t_Y?oEh{CXR;nyO@6#5&u)R1giI_97N|RN3E;S5W#`9C_j6oeAN0V0A5J86`Cz8 zhW(^P@kmo^b-A6PSS{o)Pr=v;z0Ef19DP z2`p48M5uaH*5`~!^+vT8QDsoFiR3LVognq@r&25ur37vo%s$77aoO(za6-_|pJvwr_ z*6+H3+0uT^nkqC=)}-4}#=>W`oRdC%xbDgVQRQ|6Bc!bw1uN79)oO%swG^$H(KPP!yR*$Ob3*!=^2s+wb{lu8nOQt}L@ zIv@P{=2NdEC)Q{oWK~Vo0uC1-+fLC%^CY&&0y&LmJE{iy>`=P54mo>=Mi7rG4oB6| zwzBYsv@b~9D(&)~fSAkzMLSa3MPi==0<=1ysOC-}H}$)UtUxP(O(?7>qaq3~>jAc9 z@2YVQkxePZ$d+0`ocFRW`SV5TE7O_kWVOh;v64JSrMAxDTbFVxZ4l8FNqQ>Joz@@8 zgGq{zbpo-(Ee z551E^7X*Dd&R|?nX65?(M8@Uy(*Gr)Ea`KyuzhAO5T37}YC?=_eFqumC3?v3G z>s&HMyRnx*vx2K{9`4_NkY8^oA7>TFIbcv#OPE}E_P#c*_F&Oy=OZOFae)#XE3?Y9 zfby=ngb0ns1O=@y*BUs~&z4oGwhGlDx@cWXZ3TMR%)HyweD+Zr){{ zxvM@SM}6>8fH^79Stl1@RM7Y_h;NHmfy>&vN+tvgD|H5^1BTnuKj70c6&zW|qy!i( zHOK554jE$SD^sZ!Y7PraaLn|jkgidwm?5$m*0OJ(v#rM>Yp)h7%P=T;_E9Ozm(lj_ zqFY**jm`4F*ovm6N|+8DJPKHVNJ7(DX+J|4Us>0AgU^5w24KtP?0j@oim&W>u0o!6~w>x{M50&P^PWVJWA zfKx`@PrN5xN>)01j=nBri)~{X6@ANftiN@I7fmfw6n$eQ4_kS1NR%+ zLUUvc*ccEC9$yKHf@nA3Z1qZq&^*jiu6|Tg@_fZ?>c$D8h>(L;*cx_LZZ2Nes+4b{?MOGudYA$ z-*2cFc>7G^?%#j8Ox?+`Uw2%0=)bPQU2h}a2vREUk6FI zcWtk|e2$~g^+5dj<-dbNo$gPcFLn2O%SW1*GyN*+et+polKg!s`~9kL*i(jQrT|eBvYw~<2 zVV|2;?mVve*G9d29QEg;QGbV8PYz#bJ$d^C{5;os(mn?7-I>-?(BMI-Gu^%D1rEYf z0l$vcQ(I*}oiE0x@62vj>#K`Jv8T?AeV5?VqgtO05&T)q{?|UV+>Wl> z+NqoWW)AIcBl1VN=(ZH!H@&bgfBwGQJhcDnZMXWdMpo>KZ>r-QXML(hD_Vsfxng|E zIfK`;{uKi<670!S6JtPCTdCpN2lS;iz!_Bw7KkAzKYH*rX9r<&G!ZlST zv2m-Oa)bmDeUhyOW_`cT4hp-SkP%I)=<`Xq%dT2^?%g`JUYyvfJu@jwvwjo1w|MAH z4JI)_(0W)#Wx%GW%3@K39tu@3vlb`^GEdA+X(uTT?LKMr?(T&FN4Eq6Qj#3vd`=qp zRjo~Z!K5f8&z7OgdRYzjE2TKr<9 z*=ZS#l*wqu5*kjJHQ(K@5K0cIpiRO$jn$(!Z!e7QHfq+PHZ6jhf;u$=FWOtbm7LYE zKN4G)Gdu5Gh*(!Gv^OqRC8|l_tj?+8Yo#S$q@6nim%Wq7LmD+1oOMZk3qh+Fq4Tio z1SOegrL16kBwED^JH^vdo8T8cnGq_!hmX6 zTelm3`m!s@J5(;o1`}$fVbYmuTV6!B798z!mLFm}kogV_dsOdJTWZW!ppVL&M%y-z z9bknrRJ4vHEyf!Bl51BJ7y8hZ(+a8GK7*3*<8>bGSa>-)-+}LHjS0MG+dRjjah^x@ zLS8WQu2`B8?j!iMq-Y`9(Mt4Vf98U$Ybp@~S*P407CF4vWike`qHJ7S{F8oQN6H~W z_LW1B*TNC}Y~CHe-VG|poSMcad4O5hy|;4r9&JofO88X}5-mFxXjClYWr8^cmGxQDBVh=^EvCml^HNP&Jp~J`0ZGpq z^6tyZnI>Bvbd0UBiRADWkS(ln*m?^HShc33$>-kFv;y74p0lhHjhSa*{hR4S zy@Vc#np#FLjh}p4sa7XTvCb0yHO4@VZVnr+&Av&}D6*HGCj~^OFN__Q5d8L!yS#$lCw2cW%9L zbs?*Mf83jPez_p)HrG+`Se@m7u~?qvIQ3S|u!+K&A_H@^hFDzsP9L%f z(32Rza*# zo@}vp3PEM0*Z>q}?{)SR#wuEIj>cl^qET+|jq?V6%V@D^sb-@+aG33@JX@iIdw!4{ zEs+F0wrD%swRQ5=8-PP}t{pI9W5?Hoi?9Cjz_a7`-yqHz!`h=)Cbz~bw=)_Ux3$Te zYHJJ?CW>{I3Dv!P-@r6Fuuf$wDP{mr_Bm&~eHsmF2HCU`8LFh5&nQ9};V67=H5L&< zP^##~>}srsRM>NM5=nuF7M<*NE}MXAS1C(64%Jh$Y^wzY8_01)rHogkeJ~P0ES-Q~ z&NdzdWp}BvtFh;7v$9h?lP-TOj-6#j=`o{@fjh{Aj2|^0BW7j$W^6Tg68;lY>7({ z%Cgi%MJwPq%PsD?m?448H4P}j0_=0pY4MZKDb|(1C7L20$&ul`$5msLo$*;RBb^gR z6_i=5hnwvpRJq0KvPW!cB-Lk~#cu+r5)os{p3$(u)iT8`br)yF^aTyNx|U!ro(c`i zMXhD;vN*X4MJ8+Eq+ly1mBh8x2{2}hF6M>kXrO_pCCDvG47iKLWpDM(*%`_J?-{D* zT#>VKyci^HDAKWV2_!XZr3l_H-?fjK%|;SRac>en>IV&(^%KQj+Qikc#HC)_kjkuv z=-J={c`6?pz_6es99H?TdJcDyOvy30nzUFw<2=o>XwIv+Hg|!9@Zu#{5|Ku$nni4O zKlF&HleBj7C8CN=qiq(`dvdiomN(KV%j8h0VvFQCJ3sYMIHWeFbK@ixOjQEF=evY% zRc$mLEO16uB$IvaLK?FrtgDj665>=A@MA};=KBJEErl! zHNgZ~PPWLtTPjc3P@Yt#G1Ra~(8m(~t<{r`gqup10IWzFUTt=}uV#8qf6QpdCVQP_ zS&?iuXBO>K`tXnOO*xeinxZYIV3S(ACTMd-cUGI8&8XGHthFqqh8J1w;n+fpnp(kP z(B4@tvyw6=#&rX_D2a*!sGuQ|?1n}2F_Pfcwqm7NBsXleOshB9W0`CZU`X<#Bz^&S zR^4e-^U_xiDd2MsApX-uiSAbGYPxt=@{ODCQVXxutnBUCt@)7g61=jd1~6!n&a2_Y zSb)Q2qfq`S!4+|Ct7-I%jtG-gIwVrq&KmZfw$0#KvZNs3t>nBq6YIsTFi`YMHd}^j zs9KbqeW@O9TNMdWNe&XI3TvEJcJ!Q$Yn+!_Yf&;M@Ql;DF$dRcKy936i;*xc zK4Tj}s!Id3vh}%!y8EQ6w^X-e6~#Dc;B?hDNx?!&B}=LBVrsjo z2=A+IhYhVH&pO9zwVWIJbdoVh*w+yKQNo(lkYk1rt3am7MGP)9@tH+aJ|_jIvum*| zNq|7E>`lJ<@(8-LW5odCQ6=QxdkKG88ay*Y(_c_*8q0j~OXPIdTd7Gm-80qdpd#eG z)r1>bS!l#Hki?Rf#G%fLXl$<^zM}4RfR^>2J&QL&MQ9iElVdY7s!-)x8`iuryc(lz ze{a_Yqsy28aZ?LOe$x#8yv+-@7MGX$pT8dXK|37%yqhIf67FcyMpb@c3piL@;*{a1``mrXip;Vzsj0E(F_clHsMd7^(%Asa-$)zf3Zh21ib6@q;rX=}; zQ{vII5vQ|uf3c|>m1TkydK;5rNwroQ9s4f8HIk+kS6u39k^hS_7#~q8oyg=D7~ss) z_Q3#ezdm;E7ffJ!aZKQ6hTk9lbyCHDGPe6a4e^toL9gy^Uit5S{hhb@N1@V+I2^N72vyGOL$-N*m+?(pIL;r`~}?VtW|xT%NhboK6V&DS@#|9o}$kNd;p zHaUF%=AU<0l-~a8_ocKAe)aB$!yo@~&+poN-5tJ@*ZK8t4u5}hMQ;v&=UYBp$$D&@ zH7+0D_x=qZzL!OMC3E%t?ai-bt&og!bNlMwkfqn8{Z3hW7UEH^bjH#P4o%c2EIkFr zyQsZBg6Sy$rToe9%q5zhEbgBZN$-EsyF~oAMUdW;$$BA(p7*Ehtl#xRvaz9Vuk}p< zdav)U-`hXUg{ArG2l?x{09k&>&fHKeA)zgj>4q9qn9M`lb1vO~7GNxr_c#YU4~b|a ze+!`C@l0)85oai9HC7oJInQ1r9uNNG)$M)vjHJo5=a6)hg|e6?Pn?g3-mJKRsyu2$ zkAOMPR<|DyKe%sW#1MmFmwm}GP3D}(1CQ>s9aD*ctV{=2nmzkE9(k)#*y$$RYRPA+ z^6ry2s>h@Ep%VplB9)Lzg9XmQn2yIC_GUxWCOQ|5vxc!w=H6}Si+~~08dIp&cwIQo z7T-Va`z_8y4KBt2I!D%d`snOrU0YNC>znd2T0G{ZNI8kG`@MLslC;DQ~Tt9TF4 zYOAxWrZ`pO4nMI8@qmECWt%og9Z zCydc#=yR^XR!pIoli8l29^d`q)rNRwQqf^@Hh@H(^TWS1rRsEEE?~l9iOwWh*@eKNU9jA9 z1sRHUiV(0BWYjb(+4g0BZg)bLl5E-`BgL1K#R@+>#~$-9qB&H@v$ZE~#*ayE;=>Lgh&hwwS^ z6faHJ`Dk@}#>F*Otbqy@wOvW=FA$h*RH2D$BT6)cv*hdJ2lN5D)w7cn1wA>X{Ve5h zy#M~VKL z#L`YGeCvPIaTa8GHbGs+XH-5*Vh2=9gzR>F;;#kNX=7i8>0pH93t4iuq%hl0c@m%Z z+5KY8W2iov#`cP^Ywuq~+=!ix*`n5B+(Vk>As?mwThOs2ep*Q?Ez|Bb@6G);;2Xgz ze2_Ou;L~(_=II*g?tH_fEIW(Qf>E>J+SBRicc6KlZQzHqAppN4W}Im<5KD+8k$(Zl zS=9+mCR^vdp|-OY zqL&S-dP>eziJy(CT=Hz?@_Fh%#8r4zW@+AE7D|8lkx{`XMh~`?Q|vgZ81pw|N^Q^?I6=a)a*Hz87%TR$RW{fl z$+I{6E#qcwb=IL8h1NBy2ktr1nrO&mt9{BO>)J``GTU7JIO~0uyfrGxasY!Cx6usLM zww;*l?)gppdM#k%|OvmG_iP>}8wzmKKt05s*ZkVMh=&g^?Ab>wt{* zKFEh%Ibz!GW;YTir-TrZ$>+Rdy}U3;=&WLDtd&O?t&fSLwHV@_H9jRIMIbJ&0mQw; zv|JV(>7Z}9oimYbH~FAL;gyr@i%MRO#myPj9)SkKN)gBa`s@t=qX8wMzQ#TGW0PH! zg-Vos0GlyT3_B}71{ICIQajnRR573{3sL!3paMPhKtt3dRGp#?5>*hYxaag>OV6w* z&CWxSP$hbvrDUAA<32r_NOp{ik|igoW|r^#bct+o&2u3oX^Ju~VoVF>a6{y}srxv{ z;^?A`pLcBhG26NIE222J>cvYG-0R+Y9$t2KK)}>Sgp~r|4LZFMPZpw6Rr@Nod-sAH zSfyOWhk=2{JOiL;P~r(=)QO;oHt zw9Q>qih0FWkD&vFoLK7^RLE59tOCQ?y?0+PRhQ%}s?61svw30gN&HQ#1U3(`XVDb) zxZ+E~soH9gl^(>Ap)AXtBM&gBnB;9EumrRmcSXu$JuF}e8d?E2m`JS=X!jKK=Cw3* zq{>N00@_np_>wr8(*?1uDB`UxBzdH5-7jHJb-|aKVsYj7Z(je<*Z4HqD@%qgur4db z#T(>TC^i7Ztdk8&uVhej8l2+QBdaDisl~6ae1o=68LsNl8eKXmsa!^D$$i7@gossj_782 zfaCj-?$uw*G^~UTtz?fN?7i685IOKBaRK#E(!ob0N$xipp#FMQT}e#`IQ+`Q{WYf%c1F6Pg+r)Yk(_U*C0=rpwbvhL1VBwT`)De=Sb0xr`;?d< zL~6Zk(dSTt-*b8X)i_NjX~O^^Z)}#hAy*8J0`2LlIEfzQ-Ru2zw^P%38zps(6qT!n zcKD3HZXdUR3 zR!X)vRg9dZdT6*x+Lw9H`o1K8(cnuOZB@3m&}DD)_hn@P0OCRg3_Ba@%K6u}RB5hW zNgB}_l9QEqc{RS@q9Hb7r^QeZ2|doL0X=$a;%+r3MmR|DUL3fBDyS>b|-C zyivMC|K!jzNv_lF_08>XWz#kk(%t!w(626T!q0=G+qb0E$dQ~j9>@ju#yp$_gjyri z(k>yj_SH`z;Qs3kAO3nT(P+9Yhd)33z=O=_A>Z7;IsEs#tIt@qgZ$0mKjn8H{ilz# zt-E<%+yn0FZcKc!}-yY32T$_-?Y<%GDy>tutLOM0kqz~1$5;Edl(%&M=B*gW zOMg~a_S3{))wlO^fA#wEY0~2#UQ7>P^VMZ=bt~??zqtshdwp|zb@_*iS-HRZaQV+} z?p|Nz>&t&PLC_%0gfXtJL%yUkM&Z%`8AvK7ae3H&u zVR}z~+Am{@i&05Kp3cQwN_47pmT{h5t4#yrR1noV%l}7gAxjAudKl7oey-{hv;OGv{wVxBz(%7}y&9b0UiiYb3oUsI`mtAMLNIEJ|)({fT%6aT9M|x!W21<-wN)2bj(cE~`nvRlI6Dr8oMpN|6eev8Zi>J>p()m(_(=O!_ zf{{k|YV)=i({Qtt5K5zE9zH@E8D~1@nXLn?bAqK%yyguB{4?jQi?+vQgT*BkSa2A6 zTR#t%Xf~_6j2V*GHD;h4zR=>06-nA0V`b@UL{*fXxke{d;ANIx5S*#ZKEE`|?CUBI zIspZ4#rqvi?@S9gEY(JFrt`5doH4zXD(xp2EYI@X)Ng7r6s|ewE%rWs2?HG{$(y*F z4`vyTu<-7mo$~Tgp!VFfm+gJq5`|OVRTYBuokdiqPtax?%>bI^aE;EG0xop< zqlBiBqL3Ix(q8!hy+r11e>R|{5tMYCG_xp8&b)=E|D!-YVL*wNwNkELKK}tD!tsH zE!;KC52p%1kiIBgi%m11V3e~QYo@?JV6{k5f1QbZrz(t*Q}1uFkRUUX460u6neEYOIXlOvOadeQx5S zqnm-rUv!E=7EZpq1zG*E#2_u7Vu0Rnbtqx3@f>6_^@XM*llxL2D)bVfw`|WqpS;e+ z3eY2#o@K-|R&N3&2R>9ka zR^j={a1U3QCcQ3vtXh4fMZ`FIVM1l3)2>iVT_wd}MFQD`1?LfM_Q#O9(NjpJLZl_M zF#XV{VuZ%J0FGQbN~!C@YmIWlWJP$BCaPNIRGVvBZ$#O@dt)3CST7n8a+0p80YIi6T&Fuaa~It0FMB5ClyN z=!oKCaAY40>vP!!hgf6smgtieDng9LM!WRfa>Yirs?sd4}~In zt)(#8hlTm|G1kzkGHaKTJxbN*xoM9nrW92~j1;*#KGc9-%8G~Jt~G47y3$3n*IBsU zM&zR{Fha_1lb6}Wl2zd1r-eD15vFi0lMo1wRf0m$3n6v8Wz$pa>oIucz3{;-^uH5) zmV{4iNaTG%(ljlNJNop8B%tBb5~r$WsngkSy3G+=6h>7URXYK>m%RDpB)!G;O^BUo zn=?pqUZz)Dv$0`Y3&(&6N{Sr7LY$id9cP_R6rl==^PG#WsycI{J~OxKElcB;dg2l01&)|(K`s)bz||}?q+=9fNE^a~s1g%$8`={>zt-lE ztPp8biKSNPWx8s{GQ%==U~DlnbJZo5v45*&vS?i!NWL7xQ{@%fwQfgQ|zTPYlgpV0aNRh3)SvK zQjPTst>-kkiIX)-TeGd?oOQ3(+bK+$AZ#yzH$zs+s@kiq-Ke%5l6fyGc?vB8Lej?C zg~|Ii8JW7 zyBAbh=VR_{C1cuB?jj3ka#g(I(LAl2 zYmZ|u-f!QxJPKhOskFDnSs{B#Qy=9_nt5$!lJUyNniJ~mmo^7BTem1ygp{SWihe>b z!Rctud_?4{5W=LlP%CO7)w1@$30hxE50l9OS56_iv?Q-ILP#D|f`CPX@P>@t%)o9~ z-bQc^mtdPU+@V~S7Q8xom<+iM^#Vj&Ysro8(T7X6dir;ETn!HM+C>=wm;?#k$ zr-3P7crAOb_QGp9^{_9zma7+D%fk@AXrkMR?esr)548I6(^XtwuI|vm zX7xv!@Vh(T{Hd4C^lq%pZmi9pSDV{(z6zUFy}eG`-LTAJ`aaxTgh+ni&#QCt$*a4| zoLyY+Un7qhw%b5ApI6)UYI|O;UafvQzt|iIL04olx8Z`u+cJOZ{?-q7d&c~!+sC}B z%#-@}J$vZI^;`PH(Ri`Ymw4E#cNe?A?!U6yue!}@eY@R|v01Gvk9>Cb*FDwcYD@9> zD&)L5xs%oL1MQzn><<^)a~gl_%PCy1*4LMx=ss6Fh?rMAB;85*7}EA| zw}-Ft1bjHZpt+}yd|G`d_m5WctJU#!?=E^abkSd~cX3TmaK)2!QxaK&!=&=-B~S8} z{(DBg=P*TwHL%*33()}a)9&|ox4L`r>72teU!zA;{2)Of6elkm*Ke4R_j_Kl>vvbQOJ46^|E7nQH-<}cK?`|#Pp9k|D0!7~ z?%_e#KeZ$85r{x{^=n7>yB*nyV0QB|?*?CD&H1tBSA@@KUwn3W21SKra+Nt@RmB@C zF>)OvbHZjTAb2Hp%`fom1)jaYvlnT_0wNvaSz)EK`}s=LI}p4=UNMjTSE9 z8X1G1UneI>olq5_v*aJ3|1C8aok1YT%&l12N9fkcVFUf~Ad+*xqx#^;{<{yH^_|<} zy-bGhW7#8;iz{|Mg?H^{p|e*l;mPaz)a3EU-N*2Gvkh}=3CNXwtH<^CIf9$*MY#MAiri>L{QP6twr&TXoP>DE zqYRzd_niy(Y}d<=-@VOK=#D;gPL5*wQ(b#iN~7LPP2=6irnfZtwyx3mV_l;`-)PV` zTHjz@W0|h8OxIYxYb@U})|<<4^R^H5zuCK{sTk!~viU>j)cbR1#xPeQ-K;mSPLTT- zK6ZW|t}iYx!pyu$X-=K1)_U=?U)8J7p_9?VS)F--`8a(T79v{(3;St4zZ01oG=x!Z0Wgx$i zRM2eM%!Pn{ZW_qzha!E?p9Xqdr8@EX@H5$}t9QH%f1i1qyiQ;2Gzmp!?J=#Y4XIkg zZ1)0+M5*ZCSgLR;ni%GsCVjt7w;a#zcK8g-x+!Eb$}WljKi~iRD&GyW&(hGYBeV0i zY*v5Vl-+sK%KvF+skWO_$kggvJEKTWM0u9P^o zs#YFnO0=JmROj{e4JXx)SJUes!gY@|W&4oU+wJGEqQX8-a&*~HdJ}QI{+aCJrzx{| z_-K#Geap|bU*T_PN@rzJCJT)J?_GKOUFIy+#AmnV<0UQ5sZa5_TAi$hB?G%%Pkn|q z-ggwsb=}=>)OQS3BD{O|`F#f=J!b_*?IJfE+Te4*DjlH=>2&erRzj5Sr4r$#65*v1 z;iVE`23&H^`iF2y0m3j`GENJj9{?t4C9(|EQ50&W^=2XpCA&FPi$H(+mSEGebES9T zUHJ5Mm5EySIAVP%6MZ?}`1--wU46?Ji|utTAcU2!nrswkL3TCO9cjE55o`8Po#`*f zIL)WBpNVU7-~YJ2pxr_yW<$SWZ1n>@_R+8Q*{~;NS?{lPdwQ*_hu7Ndul4F1Oum9O zr^#0@)u7kY$aGhalCP-Q6&@#FwLE5Xn93I1wR--ZlCQMW^5@CCilfY{d))5ul6n2Y z2AVeX7c7`d6_UnSt&c{>T8n{-Xp(RcxrQG=*_b;c=)bML=f^q3&W8x-unT%kFNHw& z!4ZX$1S4<4%KK>N{Pt$MdRK0CFOWi`S7-mtVIu9PeSCX2 z;D__VvE6$z#usnN1W~xg4Y-%zsJXVML5kEu4WE_KpEboX=3$sZQHo>I#bb+2CR@;l z&A82eSO&LyLC;eK_gl8w|2#BZ_df0^(F$r*-ajc?+22?n&%*8-PmUb!X?Wd zWQ!DZt-G6>h{x_CgeuF9HI-^*H_g=Xlne|1S?4j+3Ii1_&Y)j>FyYL~n=X;8{ zVd8i!7$hk2`Ur7`49f8}ZnjPO^^5_t$0RZtE7{Eecsz2Od|esugA2k^3@MG6^+u;; z?xPXKcvioKO3SdDPVM-vOKvh)%Se+^Ocl&zn)+FAkB1&-a}PciRMCeD+~eNONO^pP zVdg@couUn-lQ79p{JwPbA(0BQDiu{?MQrP=on?22wYp*!(h{TvZBpuIK|H0sX~|tns4m9LI!;2A z;Df4?7HnMfcKc+aj1Eakf=*=ci}tgY>yh^Mrb&}+G>s^tmo6z?>Y~Tk?*jVYD~j=& z)N7cj0C z7L8X}EQ%_95^~m7p5m;vAsQzfWa$FZ7F%e8)=lk*m;-{MWgp7_vv+OFb*xDCS0?7Y zdw_%lUgsO;-H{}ut+sp#N%nE~*H0o_wk}j{Kt4T}=uk-VgIracA~RQBSSusU6DylLKK{6;3H*2f?!23Vi-K6Gkz31$xLRxaZW35W`dNn7S0EPhbQj$;B z`9vJFZ;4!l0$|HNExFu7?M1Z{+hR~m-xSr%OV9nRpd2f#aO@h9zIaVPsm#--|9IZ- z3gcs80*IQo=9~bzC=^?=?(gM|H{a{#qv&8`)TfqYo7D)qgkFxhu5&FWHx?^ZF;Ury zmzT6vGFb&iHEIGSj@IDyiHfG>8Uam2sZO!`R^8-r_MyJ-2vv|mJ61SkI*S9ftx~~Q zoJu#i)k`}P?%JhG#yKfh#0&{76b|YHgg0Ps50{_5{rznlO2!v8qu>pCFeT-sXy4!N zjl93Qz8(tCsMAht;=Rz)8qS)~L8?(#JvY-eN*wW4`1v7zK9c1rj!kh`Q&Be_*1+6P z5Y!Jb)lVavlB@vQNFkKcG<)53>gCJr?GR)|AyhEhY*n!Mq!Ti`YsS)qmRO(>hDHV) zZ#kT&LabxV;=7!aK&jCrLvATLKXz>V?QI!VvNh9Fyw1&ApM#kf0egJ?I}K5v-+lTx zs!m2t0UEL-H3JJ~_XUsKan^0m#cM8ULfv}EZDP>;P?`cu=17D5einVOI^sV?l z2EGPzx&+PjKSps7gJu?*|Aw0T_TMWhK3bVuqRyE&ins-X2~5@I0^V+I|NGSAhR2ok zWYsA*2%33B_Oi8s4zw~bYxXV~*}G!wMicE^{~1#YBtfGiYW^`Vs&e!a4y!;_GY7I= z(l|6uo3*A7w|7_k{>V#kjz)7~1J;PgvQlQsy9@XyE6kOCi z?OsNp0O)4na{NFsWm6 z5Y}?zC+~H*FSAq|3);#NHgW$@8PjU zeOFAqPeuew-AdDrg)l>C;G3r5P&MJ47mR-1B~ojDOE)y^L=|hXIu53lBsed&`2=;J zsN+Vmp;hn@DwZv)JgDgd8^-3NBKwwc%{g_v@sIwa3xm+zFizAyj^dgtH9P0G>ekn- z4h468is7EZ+}X6)K6|8WJ%Sh=xLao;C{|SvvugFpj1o&ycj%Zd{^YGSBZ3<_+m$@SD4##&^h8j0>JMYXaHqJ^aEg?SmTw7e#cA5{L$UPnrV0 zE+XIEDI6OmIKegst6w=t%6stWuD<#7v3=A$YP2&!y@8LxBY8~+mkZ248@t1jIAox# zucTJtwB*cw7D4&?%k4NQac;4(%T@uZhqe_;dk68h-CWVAIAqvLh{lG9!soiLIj3TQM;nwuoe*S3(()jD#~IsDRP=?X#DmWmfFlucMILrKj@~t zp<&cj!&d`Um=L%aMcl7;H8*$en=vCmLSR!>cnm`l+#Om<*J@3HVp$)XksZg~g#FE`!fAE70M-yAI z96~NdsDfRpUg~dH7;6anU@74X+B%^tT4X?edUj3b(^NAwXtU^lGq1QNvwb zmuvbw+VM`3?H#Y2G+&GP6?yshbh+nkwG9!KsGqcIS-yDn_IvZepJcnlYzs22=*C`APPjBw7ldQ)D@2>hWZJb%%ySmKCo;h%EZHSMUu#repQnz zINmBy^mlpG;0>Ho({Gj>B`;UE@@V+YThX0pHE`6N3~mLbdkk~;d3cno{&Mr_<6ZkWtb0e!Bvw6UY1tWA zM+=|7;^{{*P1DUnF=DYD>Fip==Xb-?dz`InQ1w+OjVW8xw{MuQ>V0W$^d_)yOI)nC zwYao7p8WaC-J7@i2M5KuKEN($d`lWr5Vl%vUxu~}O@i~Snm)$mWh-0jY575InjBOC zlfXiuR#!_2e=Buly$O2)Ua3Xm!n8iwKT2CupYqVeQlJJ{o49{4*^&7eO;df+t?j6I zvtIn{owyNn`rvMu|oZIU6oUxP-Pi&h$MPjn82Sw3^ufdIJUB95nhN z+x9Zz|EV--tNJ$d$NR~@e946~_y0b(o9n;)=ciA1_k5E#vv+&nZ*=p2R($8r{Og;4 z5z{?2m;>FNUf{dF;=6N;x&8aC-2O0`hx`B6Pg}hN*y!_Ty7}D2wBdR zUVbn>)vKF-|1SEX4ykh;wZGPERX^`7}BMMU|8!Yh}2iz`NhwO)UrY3fQ1yKq&9ox^6{o0AN22Cy{6#CdbBRi62Lv(=@(Dw8ce=wU}+>J zh1t_K$2;d}Y}F=xyEcUoq+lzHW;;KP5~?#yLJgt>wv*-4r;B#+92Al`FX%0&*yBNc`l24YKE2}s*!1eQH`{u<~CU~JB`GL zgJoO|kOg%cg)_8G$1yW37n?K5+UoSXHwpJY)wr!7p%2?w&MtTivy(hy^Z5GPiJZ=N z+EJrcjp=`N8Q*InFk>HJV|QW`8IkI9gkeJyM(l7VXIVk`U zDaz9Y;?VMRTlP_Qdvq$jf;G-WNttVOxajCEpReuu=*}Wq>o8b&6{tI$psGoM3iaWD z7AnlrR*yFS(fKQo>O(dCG`ZejBhHUU`_wb^lL@E*C8w~vcaFzDt+!;kMAPYJ^6Wvk z7dIGAyI2jm7=_j6K=zwe%?rGu&ijn1gotdj50kTxPj=@hr7a4bJz}j{irGzRFU;dt z@d<78$vV@D*{qfRb~df&H#p#HDY2%kwiIFuWtJ)G`L%yLSJxwdc5?E>6mZ6BdIZF} z=Qq=e6PmQ9F*cSKj46SbH-XkE6_2TExC&6P77dBJWyj%J6tCAct>#+1H)#v(5BE%g z+@i18Y@}#sr@tOw_r#iPin`gQs`Eux%Vr96fImVhDOqE(y)O&A%2J2N#H>##8|TC} zfoVR#mk8&K?cX&D3>u=Uriga-$mAKGJtPwl2dPDH5ukD2-T%j|BGGX_Oow7p@2I?{ zbaqS;@113zqxUGTvMg@b-^~a1JmnouucA6*@31M9#Z|X*XWGQ0F3TeR}AXC zIuYOU8Xe5QOQ2lTVb^|?Tgv9@9P@z$<6;&MDTbu(bpsO3=nQDikt+056*~?@Ip3EqcQo#rUA%jbsTj=0uUhSpgR>=U^VtAudeWnl>l8H6; zv+g`zVQV6+X|2s5!@E z5P)(g>eF4D)rNPI$734onxPUZ?w8VPS{=gsRXRBq+o=}feKSPkt}nAh+b{aD zKu28<_zYBL*?%9deaLBROV$hsOA<#tIo*5Y1GzE>nlW0dJIFb4W)az3AYio3TcISF zb-x(e#5Q9lnI>J(E2>wHj*Z(isx!_!QxL7epa_-&&N3~(a6dy-5S+uTDWWOHh2@FI zLBIE)i2&*tvThw`x#?{-1I!6+LX}uGgN~L7i@xOD1o41{#6Zkl_z_}Z=VrAM2UE+( zYKf8i=o09S^i@Due9adWbb5IqQLh4oX45Rk$qU;(rvwLm#nKe8RjYexmfUeLC38d- zQiR1dMfhD^2Uq*~rzAg}@;XqlD4`&jS#hcN`%?FEk2fKq2Z@?Cgdfue5F zO)qy$vgR!q1go3Ba^_Y1JjI)!&L1?-(!Eb;OWmq~J$#Y_6>)E4r^GGUAay~#{c)M2 z0+Q$kO{r4OEi>;;3LNOtc&af=Cd(%IS%Q+`9N-~QRF~|@F=oXnV8V8L2s0sQ=PbWfSillVyw5H()h|9bobjU%D$j)1B^$GnrE-b;<=2pv|!) za!9E!^GE0Te8T+L*&r!fq9~EFA-B87sY1tc;DN!Mr^DwQ7op& z#xSegv$eYuGk{P@f~c#K7b?DM#&^HmScqZ%;0#tJjXItYLjpl-GnJTo zQ>pD5^i{OY5FEmED8mPz7TQ>di4hLQ33M|?Jic$nUw3619wni5hucVq!(^x??y~Rc zu2O-3e2^#<3ITf(V)rQiew5hOXT{BBps_&)Tg6O76HRu_U0-HVn@c=UZcL&qdoGT)mDP*|qsADap{2m*-P5N0 zDxh^O?z(2Q&_vKc;45NxjbXlGq3X~PGBLPDb^>Nq9yu|sllkmAE6N`a zM$LcKg&bZP{GJsb^w^ZacjMVlv*yLmS!pWatM9I6KOI!xF0BoY=VftR7IEFF$7jF2 zJb(TBMF2(-OkiRO40JAxlcTRqzDp^=R^_`0=F2BeTJl|-NmoITuE=*0$wCqm%9iB2 zhysEyR=8i6d>5GV@ru1K>rlam_tEW|jz2%PX4kp>V8>bR?C$v1w(mY({mGp)SFUsY zS>IE*YrVZZsCH3cpcJj@CU!Hg4hLS1jbS9PzPsHxVAmBtUAo2_^er+BjIb}uJAqSt zt<>(8yA-ojkAKmH0gJe~u(Ph)VGkxp-vqzgi*D>NzBOdHjz5jA%&h-Q*Dyi!e{0ZK z#aNKbzGiH`)<2|SP8)>gzBUMr4nw2E(1w8x!V-h9#2~D25LP$<>vF7%t6^b>%X(@m zpN7xhw9KfN4UW4^bX;WRQH!pBsa1o~|C--qqnk-SGB(lk@$BKkycE0;yIjo4mkWoq zT!XB4At5E=RtOzgLxc=*h>hlvVJc)&2trWkq;-%Qw2*i=9qAazRT=z|7C_-IVm+Ov z)2qe0;`MZ93s|(+UF3P2miz15_Y0mIz(N-I{Im>a@OgH7(GS%{%f&_Ooulh2NioH}yM5`0G*qEwb75 zt}BP8ftyBkE$Ly&5QbPh#GP=Or5~URFSnF5vJ|ua zV@S7%X?9sa8^BZ%#k%thSY&OK$o})j%a9+76z*~}rsYWtciOuNbc;Eg>G=B6%@$6e zp=2&l|A<-_q^Z8qne3vu)p+=`FM&Ge)0r?YB2Mpxm`=0KTqq(UYBeAH=+Q*y zTRJBuib&LdaD4&irtfst+vi$2fztlNEDKm;`^`O47~$cK=|WjOW@NEcChFIS?1J2A zMv_QldDOeb)&;u3jCANuH1?;ocR_BnBOP<5c4$smpT)Dw*YCFUy0S2S5bNF0UtnIj zwAb#0UFepG0?XPJYRmA}U_7?JUe_AphE9pK;DVFhq>(keO+DhyohvqcWII52Z|?0b zJ9L@masOeFWw@Ix`UmuKm$?{gsO~>#wT$*D%`bDefxp>eL>R-giw6%Dw`aJ?WSEv* zME#-@Ygn7ygNS2lNq+{+9pDE&P65&OJhgFR2?-zk)Ij&9z+Czo(QB90z)sSu zqW@+?ORWs!!8e;1fLPexDFT>_##|1bdEBw`4LvVh(M~}M|x<{B8XP>uCiZQnXl)G1PJI@dq zt`ZgX3rpNWxy-UY2P~C!rx}J~&ZmRS$VMg>HXJ-%EWvIxBnfjPA;Vcvp9A7?G$ zpC-MoY56VZ2Qks1P)1QBsdgJDXDnw!q|GVn*QJh4s#00j)6-zUgMKP@F zV=*XhehyPaJ?EIsSi3(@-LcrU$(1BS3E$%?8v$jE<{e2X? zo&}S%D6+!+qWb8d{wT-a4|2w^~2iUyvXAWl+IBA=?G} zq!gP&{Me~?t5&{`bQ0uC$v#r`X8O3nbKD+fqxL`>%xJ$Jax>TJ|siaLtoGv#w{><%e~Fr=yfdND3#{)2sRU zwXm*cj6Gq_mFKZbN_aq~vj@UuXc)#4raO!@OJX585;E3tY!YFth*YF(7)kR?xSk2u zPJ|0As+D3*RVX(SE}&KnukbDAN-E?vcHcs>t?pK?6|v^fJ^p*NBSfm7l%0sOeiH!ag~bKS#( z`rjjdSRF^JUeTb^^aAFT1fR2ca1CQSaAyv|G|Hfu*SVzdNpY}p_YG^Sj=4G3mQF{_ z3Ap-}g1QX-p_`4~JKDzRYA!2$ACu)=RxA}( zYCG?0a#>r0Z`2+=Be=VJ=`iISJnX?exv-GhkY0FMkEb_2TXOH^;xe zfAjs5r)U%XDRuQ@$JumOrnYF~s%@(V^^wks?n~E}y1XN{(Dt4KHahdVG%d_o^Uh2q zA~+Sizo5|)7PPP}sLSh*g`L3Ka)X)-cU5S21}!>;&@l>Q zqX(tQ)oA67QwFnLjTc#x#7GZH`ndxuKDp_)NjUB55?4@J<3Y(eHR?zEX?AI0M9nUB zS!QwS*7RMw?v@F~=&*!?MNWV-NodZl#}}~xDmG{ne<{geGaz9)65I|lMu*}OHs)Pr z8LKktNq?2cTcG)L6BOlyYtfse(el*;25$%T`MOp}?lHH2ao2OJSB1@=z+&n@b?F5i zx@F-NQ<20@>`5Y=L_-T|JInzB;t8@5F)9p&;Wi2T^6DOCRX6MeY&Gx~qkhl{z#8FN zPvc=?CY`|R06VQjCz;XXRF^OAuJI#u&yODveMNJG2r@sI_y<$M|M?GT{6h+VrTGuv z_jJr=T!t~=VzD1wBKL#Kn0H+M5^%*!@3`SBz@^kX?&)ccT<)K5+*dfK2!+0JIRpEB zg|Kg2Ax?8b@SlYKk9TN!mb;L?Z(MnD;)a}eTt!cE%8_?dQ%vMA?7X`kb^bD!C;m+$ z6fy@->D@(y&~H>Q@BMa4Pjf8LpO|;!sG`EKG0mm%zX0>wh895JN!gG;=(ufuhfethGGn8U^YU_Pvm_x z6GZ?TCTHKcXNcsOy*%-Z%P>95UHNa%xE!4kH#B@tbP6evWBAWAZV2=`$BLW}zjt`m}pofcF;nfz?;zhl= zQ`)V%hkwaj%FM~w73|*2F3sX5^$}cRoMz>bvHc0jZjYt4PlGlmBs0Y5YJLoGIkCJ= z<1%P^vSX@j-YGUt0qsH~W71hM?|HR6B6FX?|#@<8u@>J!gdl+@i z)`NGGP=dLsbPvI_ChG2g7p4hedvA(!e&!tJK6VMJ&^UIk!nO9B(dk<6T+`M;A*x)+a=G!VNXfB!eCUyaRpt0OLZU`h(`tQ1Cqri7N)EfoF ze>5NA5OBQ@xhgu2hTZSei(-4y&3ieZHSp*gv&?@&JE^Kq>Oxy zWk0c4w$snX>*5-l&w4V%312;Pz>wl(`OE>s?p(rOU1UmtDCiOd&1C?n@A)k3?myOjRqDlZi8sK8W&&1_8S{-VS9~_x3GQ3$UES@#mQH({l?0>uzkhL zTiCv1=IikO;^r-Eud(x0Y`^jI7Pjvg`YOENIQlBK-&p!8w)c2?3*L83y#?F-i4#Ol7NONu&S0Q>9f_xT&+^Y~|NZd}qN^wnz z-G0GxaZQPO1c_FJAh+mlKTAQbZ3*~S+-6Tk3i4TT`*|nei|+(b9&;2&u}usY7WJtS zJxVP7TUOlG@ux0!1+HyiNpOUmXcf9gP6I^=7Ll|jG{z)KP=iT`IFgj;2-kzKw3lnqvPfW z?=CKa^ZFKmE820EJ7~C;p6n;*A^ud!=vA{DJoJ@40^-+yf={d|EsEvZ677;AoU)e0 zHRc3kxt#XEiNHN+4`8kFSyAlBbJ~n#JBcAet|v7Nn)4es zSzmY9LigZ~`M&m2@=AvT@({{my>fQ^{lc^!bO_v9Rnxj=do0K2BYRh6uwW zSPdh?bQB}PX~MXBCowG4p)?_v;UK5(vc>*zPZFGsHTc;VfBWO?`{1LEVm)ab@lbdE z_vIf|+Pyyp-SCa1?`DVmM$Zf9bKj@a_!@>nv(T*GJj$Cle=cu6gQGl(?A}(IwfHS` z_D)Bu6>B?YwQ@ANC4n2tRyrD&h%PTUIV@pNzgJ$^>?7k9haWST}GL{jy+jYSAW+$GrTIYNsvu$>?kiXSNeRYXMW?FJGfcLE`i?`dK~=n{_Zlz@Z!Dx zkb=9L9>OQb&U*Ae52l}fI1H-4$A`hI`9IQGIS(#Ux2^)(JxRyeVQ>OtEI281u#bv@ z|DKiCX{3V-@F?SPI<~;QZq8+`w<*Lm>Ava6g|9gG9si$FVsKEWDk8 ztIy`~_2B`yiK;d-%m#-+^#X8KM-RixLPLr7!yjiPb-yTM|;qXI>yb{ zr`qugtW-bh!XCeKA^1Toe;(h=Z*~o5-nQPN)%;{R3r^J9%rq#fx!j!{iqaiEar+$8 zHjiPLUwNjpd(P+B=3~b;q1CsUuNSBvOT;+nhU2)As?OMY-i0Uc<= z%C&S@7%m>xx)56uysV80cR#tH^x8Yni)oJRz>>1eW-E$rM zJ%vkutmvK%mU=d57*H_LH$XuzHfeD}|JHv7q4u>{_e&8Mb*=b&os7tOuh?#MTB=acuZzh6W#w(X#2 z)7iWPCLCYam3i_k`5A5;e$--ndt;SL?b*I&@0mHZuK&i-Mm~w%A-h(AM8p(g%LNh< zr(qAFY!1zB7~-SW7#)%SgoATaeU)bANLTOdN-vjN(zTvzG7t0;GeYjE4A<)0j+00& zN4$NS-e4;Iu!O&$w$Ps|hI~~F_OZ_CJs+jJg?M;sLCXa_J;rSGzvefYr=aK& zg|1}lo|N((m@>ygDiVeJV-1b<|Lk39ZzD&N{jOiZk28iP=Y4pAg>_;F>%n+; zJl+q&ppjQ~*EB`ekW?T4ej|&dns+6sN;N5!4Y=JD^(rgRh{%Zd{-d{+Z}98%lM8%0 zHX`f;597TvDW`oq>(khgZAdjLbYS4|+fZ)^5w7n#4d-4hxmS$e88<0E!5F@S84V-3 z;lK+hP|P?=Ml6T#M$iZE#*fy)1mBcGhlrJ!G=-R!AU}^vXytZH9+2Y%CCN6{n6(_@ zyLdpni#yi_NROFT&g(-Uef^D1deSVY0%pM>pmEpP)SU%4p3)>)$W_R4F!Y-+xnMCL zAxXC~V%i5&?HC>BMIo$fWHy+?#Us0%G!8oEg%C(2zqt?1^W7?pFip~goI*CvqkyII zmL(7QBIMS2#E8Q};N$^X1l=-^xYPj*j)U5{Z60A8xTh+4;60ePZu0Igf7>)3ehG-7>8(-WB`T8F2^f3>FkPBDlMqrAp-5gc z59Rw&b7SEMGhUiJ(FEG~9q>p@q737#@j*w)FCBiih z4WcZF6ZLtn0*;sqhT?R8_TJX2Y3ZjKaitW*rGtlkFwlRg0W{=*iuW%YV zR2gKkMaf6v81|#t)y{A*-T+t>SW=X1T|~UPiEu7XzV2wKz!K(WkvvLM;K?REaL-kt ztmMg1Uk9#f&(JZyHu&V`Ey#E8nnp}ZQYe(%)CJhB6G<{21BWsO76}l%v}qeU?WTsnk>rYkVBF$x*h>Lt-FLSU8PG`S(>)3m*K^C{kE`El=Q4k^w#c7-eT{=mZPV&9dNthNfKD<)% zvKZf3Wm#YfFQ+FHfjD2(6C~iQG*K|uHwYV6_NF|N6H8Ct|AwHd&L_b<98CfV#s|_c zXHFp5X!E_c%`ruXIib$pSUZ7v36&1rG*uhncrQ;Gn&e&T4^dM^ABz^b~8N9J}Z#B*mO97py5p z&|*#rd?00tMYu4_&o@le=hv#eQOb({+|2v&tTHyVe5aLeCC&zUOSRd`*0lS?T9_|s za3@~8)+|5W8HXoj9OhQGZby7Nt7P_zSe-*V9`?heVIhA86XIzoh6pskU zmDCi+BvMPAK#GGe#bd^OCs}x0l7-+Mk@fP+#Vml;jC&ljW0$HgwG@kN9vl(Tz)4&) z_ifhOd#yq7m*9vZoY6HGrsIhEZX8i_Z?39bqy|{um6K`h+X-^fLc1b3;VebcI?V#o zf%+m~LZh+_vx0eT_u_}@f?UTDUQx8G9?~80E{!cI zkklG^K`3e}a9=`ghQnEcSusU1%? zEILqxEOR#O#+--OmJQn_JiIa&up!}rio&tN2Z?ZDbt6&0UU>-x3YK`KweUO?x+&@5 zMO?t|ojb6e4I4Z2=(Ay=FWpCH9@;4gL$F_p^<7i!VGP4DVK~fN&22$g2pCf$oeat& zA(bmMk(eNvc2)4}@O?Q6VDQD;)&GgFdTkzhOBV>q`VkwUYO$HQg;yJsf3RPl0%<%@ax(b?H-yr*Dm!TRlX zCMj*yTlzDDFz@728qUDbjG37vhQ0l7Gq z8`wZscdgyW+3Lhd09@M!Ps?`fO6R+Br#-UBSL-D?q%0dv}kxIGHGJeUCGE|IBPda-rsPWsw@F z(LhDsU_l&Zx-eQ8fs`#`DvQEO5-zX^goEQnk_^<}V{+0o!({qW^C0bBQP~(C?2W5P z#5;Kc9EV9AM}4e%PdvTjsmVEr!OqzO&z2?8c4eo;>#@g4_`~!cL+|gi@NBdr%Rw>x zWvUYyQ7>Qsvl)_+)_37iNz}f4&4^Tbd!iweB<3kBWg05P=wclfQ&^w`J<3@ppV!mv zyiTuq>q5bw&1aJ}8Ii(?)g>c7!GHH;#09RY9Wq8Q&Caf|;ldDZ4YGk3L|YdOVX%+u z_%C+_Q_6-k9ixt&{pi@)1zoA6C6TXrv62?{i9Olb=Mp^~L;K>FkCLHX;{$7IUlBul zfvG|=ome}Cp5$h7CojJ=hIS9fx8^<>HI<=V z6KM>$$;{m^$k1*rvBB&?ecs5>?g}G0p%EpYwg!G7lC9Y#X&v)`Jdjf}=f6@3p&ZZvV2mS(FtaPARuY!hQfQ zQIolIRCl)9bxn_%uiZQrZuM#u-Bvp&o80hdS$HOA5Y?d#4?V@!BZJZ z9a)~0m;BiK{GoIodd>`H&zpP*XVHU*gC0vk#sPZI^cUOF`_p*Xb9G?3XGdlLuQ~p6 z1ggtLLRAjlpUp~JK71X+Q~SLcVlP@k(MrGQ{bkYvgjgqH248y*<(K%dXegc!2mP-x z_3y0yTYaiLJ?6)r8TUSien0+M4#r_rzfnvS^k8Y#e*v8N*L%Z3YzeHoue+lEkAr`e zqharFAI-nY2a|_f0LJ8ETqN-J3+UHG7JV)M9M2#`j zVk(7<{O87ksp->FF}jkElP>w-2xGLGt*6;`86BZ(hV(`2kJS3?3)UY+TsEY7%qoaC zt&mNHAN!XOpI|yiH7p0tjKWdWerS1MLPx&ZkF5saYpeh0!g9xJpJ8IOP+n0lohC)& zt=TeeTDgWnOiH3GwjMk9iB{cY51P|3hF>1VG-CKZ7@E+@^NJC80+>)$q|S*ydHD9U zXr{WShn>|?QXdOQ>SmOKh3b=2iZQO`6Yq*KQh_8|i7^VsnOw9o1?Nfh(_6!1T`2K+ zbssBvlR`2znro$mD?(#--;0DA_N1@gdZpC{ zfpxC?vTdP;OeEIZ;h#@qy%Hs9mB@M-yIm^lb?o-Yte3IdrL$hfZkNz{3HuZ&t>2F; zXFj#&Iw5=k<}`Vx>qIyU#K)W~C$S6E8&!CskypgTN_%2ChSy6Y@%z7Eoq3o$HcO7w ze%{hDmGd+~Fic{;+#)IU=lXHu?GBIm_!YhketJ1&KUw(uFCT`J2UGU5GN3$s`C!0P zyeLK?z<+*<6M%pDa`9pE&~Ns8$g1C?$u53oLFH<09gCjQVs0I0D8cbrpQz^>Cfl=p zpQHC|LLXd>gFKsA56*k79p?tatRRPZH{V8d!;Q{{eWbxGUz;CksGX0~`8aRY$Ju>t zTkwFbHylao!TxP3EqoDI=a^lQnLUp#!M;Q!%Z+NprYO%%Fb2CA{*w!vA#{Ivm0}kk z2#@axmFg1g`@4)!A@@pWgs1n6i>%$m?=j5-&s8O1keQIznMR;~0?FbkGalW-yL&G4 zG+p2dDV(S25&JUJu2AQ2=zBzxaySmezXXq&P$6~3)muO4N@q->xtB^`-sEe&j)4W9 z5uX4)yuwx9LC_-4OqH+-D7hzGNOg0Yr~UOaXrA_KSzV(%@icbHD=-`GDIAY^I_3^n zI9KEEt}DbvHf)a2bv|sC&FG2n^qz`LiGctwDW$ov@8F*-VQD1b9KXqfO|B{&nay)x zGhQh;pt50S8cWVZMKRBFeNkiUJl7Wyo5(zU!tdf%o~KVDHpye`O|fyF{;sjXMa#2Y zP2p)4ue-*kd90Qin?bj*jQzqh~krCk0q%U&EG08VPI^ZW8n$27adRJi@K z_!zH5Y(1AcPsn}x1f1o=RW43=fjoMOu?Vbdx0b;fqzW^DJ}{Z*a_ zdkv3CzNTY(k5s0{-v|~r;v9A#M&!B@aTnt`%waGLz+}ZFhuK$S%Uhmfs@K>G<-wLx zR2<$}TJX_aGs$BX0&j<=MQqNB)# z_ap0{MgE{J$OWI}wk=3)H0HYtuM6TBRni8=BAXc@ng@vmE;JEDN-hLPDkuhog^?FTxCl@X4t6VBCjt0Kfh_{P8iS)0dM-Pdoc+@Mj}a`W~+F z>&Dcn&QYmu`uG*KQrCZs9!ohCb)ZFFZ$t2Q;K-Mv>o5YcjLQw{N(Dq?KZhMM+7~$aEq|Og<>=cSu+$wAvD-6 zL|7d67HfqJtnem{zv%B*y+3NU%sRwQf{E4ptsJ-yuqbE8K>guGHT&?F@yD-leqGp*?HrhjSi>}chm88=a11+5 z0y*aDd7u#5PL4^1B+KNO7@_6zEsQY3Y2=ujrtJC3oI586aATfY3D=>-m`@!TJFTVi zEsVs0|noDZj?@O;#3tUS~ELa6X|tSAtJpG1guQO zu;iQ+m@-Ki@xBO!00SS{G)=XcnfcI(^mZb>+X>Xc&)I6uV$29GL<(=~cel1Xq+T@CkW_r8b9rO=DmVfJjN(A!Z7cINU6nagkHD(4gxdgm$+U&7$I z$w2Lh;5c1y6gABPDhwx57%Bwu1WDy25@1dibIr1MQ1bg^A&U=?mTa(P4%2_xa}(EEaSGPn)3~} zUB#Slxb3RtJmH?AQqISJhlj^{xmPA^@~%p*M4E4fFW?M-EeYdwV?*uXT?Iijbp*V3 z5x@fH!J?=l9E4K_7fd>>wJBVhT=efT@#6Nc|L9#h2QJUZOu!J{FEwNb1lav<6yO9H z*BKt;DntjWn1229hcE!Q>$mG(IX;74?$^bI!|7*r7=82zj@bj4tnqgu0N9uB!=z`b zX)R)Gha39&RYL#k8GP{n>|JYf+eViCu3v#qQ%=g1`+r$nH3T4KL%+OFh67iIJ~pupV$cu5h=#_+0npbJU>^cu|KpMqANt+subKAV z#cG*kNtAm(pT7Oz{ajT~IIZao{$Uf-y|UgP60@6cAcB9@Rw;D5@c348pX|mPLyjSDP=z_CWW&SbqEqFFTB|2^CQcAK zumTdjy*cx+lU&PdrzImGq(E#rXr26+v4(?-?W)KhEtRfMaybx1CxDK#xrf z2SO=3;{y>uNT4KP$O05$sm%7JF(nLXMS4O1-c`^)yD_|9#@RJ`gO14?T-76b;(={_ zC#vc<+@H|CUDy-bcwXK2^-=ltn7l5|Xp5h4c}8nO|ELJ_FQv^1EEBVBn0?Cx`wP2| zncpmrHd|lWLc#whB9WW%}AKL~+fuTpU^QOm&=GUSDiyvS`Tb^)hOV z-aqd{$Hz9+yvp_Oa=y}48lv2D;zgAFSeA;gqs@6`qS~!G)h8l&YnKtb>k|SKC<*|8of^7YbTCK*sWpuD5@D=CYvm%-`6_KoXxM_t40jsTg`w4A zmnp6V5$4|>Q!T4>hxyy$_8e9=Z-nB$z+~ZmC@ug5V-f&H1&2`YUH^KQh7rD^AjF!6 zFyay2H~XF=)?z2zcL==2Hz^AP@HtKaK#pX+p*_H-?rfuhzyWQxeJ4^;Ww9CRM(SLg zTd62Fx|!3dRq1sjEq@NJM646J1LB+UeeOuEj80R8toFN;%Jr1ZQp-+rqO^2!VyC7P z+Z>;ym^e~e@@eWjQWfK;XDK^zGgJg+wlIy8B}JHbiK*}8T~6^dh18i+%k;#qSZ7W| zW~Ni*Oo69_rh$*hjU@UhcQz6s@=wegbt3j#*!BlQ>}}enlv~X|Ct?_-ZRDiCt!)aM z)$xY0Eg&%)5O!g^L`gE>NLCGTWXxkHl9^}*PzwDs7iAuNh-WE>PTEbt4B6@9V&g1y zJRo$UuPls9xqp!_d&@LXi$MB3gkj0yUR7%4W#U!ZH$Cn&4VP#z4F2W7H2hW zyw#%m))o<}u1@Y+_PJ4#GfPiAvzI_3v&3#xE{MLEr~ah*9`)(NNNY0LTun{!dD z`AM5VQIPZzRhgMDg&$Ii6ybpn6d?)$X`C;j71I(hTeKOFV64jgSE$NN`Bn)OR~)`$18KVqbx(PD2L(0nE5L2^4u zGCdqr8Xl9jg4Dg}J_J#XB7r$1p++Iqib}{r90A2B#T;N5Vye0!rGGCUbei0HznDp8 zOPemdvm%?5bk@0RHKK3xrI|YOFJ7c&zFKN;8LP|J-evshvYxwH^LLJl42*U0(`B5Q z7-E&>iJf|{Ee*%ooM%a~BNSCk%~g>ZX{I4^?iD!XxTr`fi@&vb5nJl?vyA5j4M%1+ z=da$&;StG;OGMqd{FSEDUG1@nv`daOd<_8V>^Lz6z$ z{tIa5XJb)@;f1_ysb*~{k_pH@1{FU+*F zDA{Y7UA4iNNdyH`ea+jop$%py!cc3@_n6x~13SE@?fuGofe_abhk5`w)a7#`uJ1Y~ zy{kjT!P!|+hsp|hWyMGKUly*vYpqK4EDlXO5(fK}c^!l@7;*t5V-!=tG~&h|COFX8 zQaBh1ISH^7#yuV>gCk{d+hguU8MIYr!B)zp&J=1=27L}1Rc8TY_M`iZ3qXwT$+%Qi zXFHPy$Ktd3Kd$Aid3&Gaym!jR6?@QsWC_}@&K@*jAXKmineHL-Adg^3aDSfPL*zlM zAP{>0Us%xg+;ru? zN>n(K2S@VYNFE%?gO9U4k_Sif;7A@E$%7+#a3l|oyP?H#bMXqy>|1}8QAXgqMzhyX})HGk$8*M7{&tkoo5+LCp;AFt+*ZG_~+X7q-R8G&S)vaA2DV6XXJDWg(kM zivjJU&TW4d!R|a>s$l|MaLkYKwqsdWb=fNpp`el?3Rwss_7O56uEYeJZJtWPBqf>x zj5jO74q>asej5qIB+KO1rS*de&iA zP+1=kljb{};1?fJW{IB97go}!Ur1T@Te&0@-Ddh~h_DhN{zzQm`c1Z>k{VOB17=EH zhw<`aX&T!`paB8WxLZ;A($LK^&RdJ~GcGVho$!SA0WUu3{35kWU7In2B&DEJY5Kz0 z9bhe;uRg_X{Sb{f@!VkUGa5L{-SH^045#_2XgEo(!<3B@^+`^s1G2kwyHS{S+1tf#_ug^}>GXOsl#)lpgrnMp!XejVu&F&1@DfsbZHh7a6FNVcO zNFDSC6E@{L6hO6>HpRZ(R|oHBK~7UPykB^3{-yT6L%{?|bvq<49@#u0#*!*P6jj|yjBgO*3+DRC?0+Bt1u5Nr3t>MY_;zZ%tk?b9 zkcqFz=QXDMzxA!mj@~Y^e7P##d`puGp1jT)< z$wvo}A~SLdhH4;FGF&HU zWT9vIKf+kr8tuISNVbR9y*dp3h(flJe(jzouHJS_BC%zadU(Na44iHz4;+9r5@KIq z;__<|V(nhndTH~aj37JlDa zH0nv_1)y{o+v|iOOevTRlzVHCG}+8Twwy5UtZjA5;nT?BcwymF&myq>BOKu?3PP-D z2qPZReQ2m1H+Y!O0U{M?8Zl@hDM8i2@j1RpO`$<~9gQGlaBfGl^3Txxj<)JQLvlPC z_FeHj8Zp)2T#ttR!TBDIiYbG0J~r(S&->V{`!GEBW7Gcd{EtT6iorP`n}rnI@IYGb zabR4Ka2bS!@0m*dwBVT^qhqq|q}Dd!{alcc_>qVhh(w?;2uY+BCIXufD-1-y%oiF` z*sbcpX`JQDI9OTf;$L+sOKiTKnh5QxD*4?tdOkIsRLInLVa@3B-e^!5Ekox*u=qM& zE=}lct|)$WR2At?K39q~CN{oFmRE)Taiv>)ZH15*=JJ1=FIQHrCeE$4P4%ZbJX*>) z^x#?$S(b6EEec-V-kz>zIxnP;SE;AwD~mvX=#=#RWjv45)O1grEld+^B%hX_9WTqz zY~Ai4&et`&s|^+%11+(~Sj_tH&ZlWnW2(cPjrW+AfG7&eYp z1>k%`RZT#jbg9@-pJ9{cB$7@Z8e&*9{G38DH|N0fS z)JASDdJpd(^|8>w*wzYqSYf_>$T1H8+Htt)^#@|`D2fPE5s9c&DrEbrkAIc$wQGo3 ztrJFsxg%xf zi6gU%Sii~sQkrisjp0J?FH5zGqqy9KGqXV+)iqg+j}R+7*(&$hCVQ(3p~s8Cq> zsnEg=zIfMW92c5|vQSPhlngiM$6g_L__zP8lKcmIN8|CCeRdI+pBxpv{i+6ottKsN-b#;{b(9)E^1)coVjte{%qcJuT$4lI)sc9ywj-@ zzE40yG@TGjx~_?)o8Y30PuDWDCymK@xC)2eT|3hOlU&Q|zMfsZ`)s!jBy0$M2p@T* z(|Dn+YI&%;pVu-z_M1F({k{Ek+Yu0VP@d%BFnOQdDT|A$S=;Wf?aanf^ZdMEnKNo% z^*)$RnyRivXCQkTN{6Zt;z)-o3LvI9@HJCF_z~qCbIyE%1XnnMk0eppCsqX9dM6dV z!4-X?rr(#90)8j?wVoeU4ZyG0O(6w+V*P{c!l3wPVsm>ZbK^qfZb%YUBV`Z#4i}=~ z^C8SQ+v)T95SS2mL){u6g6erZ2=Ip2(B|`*q4}n57*85Qae|J`pT1;|?^BXw+T3IL zr8oOw-G8>vhJo-f;XktaYW-!l)j`=@VD|7IS_Z~`n|}!e&*+qW3z!WiW?5B%iKIh9 z_5Mmoy;ur55RwTZIHxMo5*(Ui_KhU9&Zem?=gIw7e5T`}|h%@_Jw(2WKbpeb-9Y(#*Cx(rpbpkbSwrYD2dn`qcR zJ+&oYT zuyQA8qFaTbCt@aEKz*UBMY8N&irz(WA^u3X>{wiAEG{(6U;mZT_QSAacckqV#E8lW zARGbWM;*Z$?x?q4GaE;JSw8jB0{N+gZNg_^v`Cxi9};6+kGG?G!sISH}i5evdV zQ@{c&ppOEoe5w6Vcf%`oaWRMUK44-9Y)5 z#)}+vsSX~^{#D|arvbyCFE29woPQps<^;5paC>DSeVnV%xK^4fPEmv*2?>I}zv-+ZDF^+^52$9Xcn$3vv(99%r2M46Z)54n04%n z6F0*)vutJIXvAivygg1Y(>L#AytsI8F5ByS;4S(d^LP6m2%9T5OEEIIS&ESf(8ckn z55Gxs1Wm}x_dM*`Mqj6+=(M7o?fOsRMmfPU}PA|Jl2?t~Pcw z`_8ZM{3CA7>@Ih zfFZk7x_InB=#VTv!^<7(ViOK*&e?IPH`)BQy zM6#=lJ%5li(3*dSz&z)SXGS@1Uu4`;YB6yN0nM}^20?-R+$EWGzXO4J)|bP`+XXA{W%{JtG@Kdvq|SSqlUxaR$nA}{W|n3)2a9X zLSWQc^x2>P@_93>D})3_PY=B>9y)n^=zLlp^&cO)*j0DdG~W(8pKgX8toZ&femV7r zo&WAniybAEH@vK)AiUnKD7vv$K#lBUiJtYIo?lJAP&Ab~k5V7t_W! z$ZOy>WX}- z&0VMFaPY^%Ph&T^R%Y72_hWeNXS5&5s@hRtF$^S3v55WA_1O2p^<<`vpWsy&5K3vL zaqUg44Eb%`_pRKHNhzl$!?l;0C(P+oncM4dKwO8Ns{%5EL<*DD64F;eX2ow*)%j`$ z4XWivsRRwXPL&rNLm-KXAE6Rte>lpjFoi#QpaFGqV^5g+PUX8sJoATvbI~Inj_m%l zcF?i5GNa7I!e+L9zH0#i#I@Gd60&w4S;$4EN%Z)XA-B#WC?T`VMKAO+=$3huap`YW zs6lVm&m(S$#<~HfHv-M{`qxi8MqMHS6w0Fe^Ttk#MpnJDCLtXodWkEZQbg5GXn;R z+3~j)cfU7={6l5;JG3p|p6>Ch7_j?L9KC5AKX&Tgv*zDSa-;5FmM{lT060P584N%K zN?@2qloCiYtod!#> zY|efw9=D@f!rQO69_D{UE`1+SSb<;N|Zk)`fTRg}=!dm~=hcL+W;o;b@U&~e<6sV56C#3JqCu8?jA$h8+WvVr?DC zgmQ7o%?GNsH%--s0b5H343h(ulK~}%vPSDhfwi--tCtIwV1m(W^_Gdlj!h zLrS*F`nfjf*isbct#e?7AxcEURt^1f3bufof_`m@+b;FmDsFqUYfIdADc6>`?b5A1 z;l4$xHNR1quSVUq7Yzp9&|sV925WG!Le$Ul7wPS>!OyjA3yc z*dIqX{i!v#g<#`f!|V3c-Kr-nx{9?CyeW8JU#KZobZ#ZWaKAZkx{atD{n4P$OG6&q2_SRm-#3oM~AX~3u%>PiXy55jqnPt}O zpdQ0xu3}ZIqq{!AyR7kr>xt@Bk=r!L}E!?`Od@eb5c|5CRBG-1V z-RD5n*bd*;?du>ud5Cq!#yYn=U^nduaK>5YIP_OC$xPjq>{V_~?Fdm4cAf)q z6_gy4h%U|X&yz3|&#^DBK%CCyUf8yC;)~XV&qWmBF_TRYO13stT`=G(vDy*TnU89x+We_Va^Xez42ivCG>Lh0oPEc$BJ2 z(~yNkV$C(mn5r$KdqXC3kUvkPndz}Fa+FBamVmRI(KOo11YhJ*B+)+wga*$zJ5Psw zn&#>gu#q51u!FWL16K(5&eLekhX)9lL~Vy$h@h*UMzbCE@?IkOV+LdnFibKL=h!I8 zrZUIINhadysR+WyN%}irUtXs19h?!7qcnoe;H<~P0pS-Xq0F1tr)RzMi_0X-^g{N+ zqta+v^RpZSAd_JCNN9Hw@n#G}sx1H#2672$lKv+AG`|4wigJ-eFq`^qKq8Vv>znpa zSgKd2y(CTNqL?mMkR|FHF3&^sJ;}IAOu|{6q~9ey&v_bK^wR&y!(VU3wK}^uh5vq@ zD3lvUUgTUI`{Utdx!6uoMioO!5k;huSOphrmRWxw8{}_Ynjr^CTrPG9?|&(x`n`dg zOgcaP{Y&o;i`te&z&_U3x>A2r)X4l>ry72)#5IHW?3J6j|ozz!;tRqJW8mM16)dwF@)=RV9Tg+;d-1Q>K8O6 zNDJ-YUicmxB_ppdiZtoSMUNJ?-p~2Zt5zPk@Ma!>eQy*u&pln@0s>IT?q!M4;YCgW z<%!S>-{7T4gkB^s^sXSnl<~Do&E;h~522^MTx__L+j<3hfpb6sO@l5$FF(UPQQI#> zxbOjz1RZj6nNtK&8g$V+&wHnr7irMt=~)gpTuLpWQz=;P@7Y%XqW??y1Qgx=y|}v8 z%Y-}#b{#IXuO}3OEpdW!ColobSW1y$jAl*WDY_hKVB$=0wBpoLb}{e z20;a+YYFKBfk66I((OjPj^S%QE90a>=D+*<77H1Vrnmc{6~g5+lbqg>RtR_2WsEn1 ztknwP&}zSuqA`DvR*3HzqgN6f<3YE`2_WMzHqmknQBom98>?6}L3o{1h_OUq98K6B zDHS3yMncwJGvA|Bh!zZSQR~5JA{8P)Mxdq7g4{NbpyrT*c#7~CsSxhC%S0AEnO;>Y zBvTnvroI>=Rw_hi5^;{Bx#jDnLI{Hn#jEzzNQGDq{YFls*UN6H5QHq?jz$ySM@oe# zKm^maR?YW)NrhMjcm_rE+KZG5VZ;!uVDxblClx{^B0*y~7ByBXg!%OiXuLMV>q&)Z z=p@Nt^czP=g=nPx9?o4;$Xx;gj7VaUYal-oA@N`x0Rm>xN6n9t3c;ExEl49}kKIxs zhC6_1^q@yegS(-K6(bdrWe{l7 zTzzEMLMKkTOzOHr@}LxQh-U7CQV3?w5SLjFpwqI>VtkcIpsjS~LJ3KQ@IH^e>O!s2H}*{~X!zP3Lr=?Rc7oP;=2p)g=9kA-T!nvfX7)01t#M zC6~EmjKGq|T=Lp_-#M9P#We1&&BT{8YVN%=Jf9ikuceI{Gaq{|^jJITUjjT=IlDZR zRrQ>!yUXswp=w&xW4`hHuS1FGk1}jti@Iei86`$cIe@SOl(<@_*g*rMlO_#pv$&PO zRK=}lIcMN1ltm?}hMGSBh6k)?RJHVgOOOKydr7Jy1i0wE10AvuYmWvd6E*{g2gw{>J<1i$B8%` z1S8>iz5?snlPy&)cF0Z`|@U z!zm&4#}H1@Cv%4LjfC%(u%YzWNtUJnm5J*6TVGv>Fbr?nQM&>s=tOM#vHW(@!1qoe zkjNqBtyM(@&ZKmK*Uc~^A;}~KS}M$lXzqKTD+hia_a}Gg13IA}a8QN{wa_o~zn66h z7sb^}ZL1;)e$pQ-o_l;W|M!F*7cTeWJ3RNdpLBk8o$sSr=T_a@psuY4L6mzun zxxO^gRi6K~Ei)qRA`e1a@Oo_hrd8!6WmH4uKvb&M0?YSs2nJN8Zdf3IMNvtobFiVE z`i<%O_S@LrjqYs~sDX$pXQT39RzSy9E^S7ruoyRJ;^eEo4(hB`?~AQOz(i#LFTutS z;ly2}zgH#Ipv*Di8Z_~neVATbzm%reYBCv_zF*K)U8xiyR=T+4tj7eUFeQC=R^_@e z>H9J+owbzlv>gy)A~cE1(hevgdu*0h%^9u~1tcnew*ZHO_}a7!i96tnlGv(9|sGc3rmCBmVbL4m$by0S(ec& z$ZRiK$DKzHTXL|JaEs7hTfC$t+)LOZxnxQ9kNEj}*}m-GA}n@=a7#YJ5;X4x_iyW6 zya>;GsmI}h%(7$hk{ zpN8G%qNTuY3HJ=;0JjwdSQpy_SBSRW6-BJ5{n-W)IrXC_+V0{4m$a`tT0|-U0U`}< zTY>mhTn5*fs$Pz}hdnxFl zur%5}=!(D(gl(nRJmE@jUguDt7=HS_2q@k6$J3b_=+Q%WG_mc(mEZ}jlD0%mN;(vA z$YdH4MjX!Or5)H=KpcZw8<+{=k0i{a!b)G}FL^e4=zRL^qSFuRxt)u<*+5N4(Tu&7 zAogK8_JcS0-f>n$RmJZHm#F_Gb+7sZr3bd7CY?{Y z9d>>zT;~2CH~pr3n~GxY0@XkGZqgaK@XgVm{_F3Z&oe#fo6g61NTKu7pFV&5!;a8V ze>faX?bjlru#6ZjK0V3Okqd`t(Q>XvM2j$lWUaOY14gz-ix}setkN+7NGU4QF#$wq zj6QJns_L#Uj4pbs6(*01XY%25FD5SZ|7xg=pCJuHLu>t5^k3+-76L>FLi)@I(dOt@ z_|ez*zz8?^y+>48c5Uv=^|s1fY!#F^%B#KtHyBk`05DECu`;R%eFbkixW1X$$#hXX zeSN1UU#qwrsDqM65k!>X!@f{eP9U?)T2bektX_Q)W3+iry|-|{!DqkcKKoa3tG~oW zotwVDVf#M-aRyWV+4Skq*1+C0oaC3m=J}fHB^#J zQ%smO3L~ogt%^}7je|_Sdj(*|*+xAuhFfhm;rj`#*ld^rfy;6bm@-)>2T|B;F%rOU z(^!j7-7POjPt};xOzqMt`LW8(gnRL)8t~J#bVuv_U zLWCg3kmC-$_rhl^~qWxGTdC1 z>8<&d^O2t*YHasHW>|=45=|zP8Lni{erF=X^~~7^iQzZp)@+rOyM!6xCUwASlnE(W zMy->zmD8KxyS0n8vkGVcwZ9r!rJIfE9?({@c*VgojLjo6u6%pC@t^L$3Sit~0v(YP;Ut4U%!uDNUin*K(Q)?1}Xqp$47*_`H0~2mj4yb>H{* z%Hgs9$%kM?sec>|AAUaW6kiXHJD0P6v3G9EjoWw{zwf8uS!(`mWXZypkJ_xPw6qo_8f zY7WNSWoFY=ZvG~F8>NZOGXC;5DiYKFG|S&c+PrL(`Es_(?%uvJw_SCnl)3GG8`ZB> zNnST+<#1$A(%F2ur-1+0*}wm95&it{|Fuq1_7;9oeK%XAqq|kGJND*2&2;$(Ju)BU z-TDh$yxW}9y?5`Z6A~ejF+xCemMBPGu^MXK5WznAdcmKk>*m32Y;ywId zlX-48hrIh~dADi3Cpg)hsRvi^KXu=x+hFeE1;;Ne-gm#x9pytihQ7FuA#PfC$7{Kl?C~kR^5gR3K9zUKK1{T$gpsQQ6dup8NRW_Ol4nXLJQ3E3 z6~{ISKGix&6G0`C=^%w?KibCY@?{0;&l8@PJbz7$NHc@ty_u})7q0H+Mt=RLel%m` zmmreI9%gft^-jgojKZHs)m`=O$E19G|FikC-a>f$xWOxg-?Mp7*T7p#)k9TI-D!1a*&ceFK^RzK`a*@X`384wcteMjzPqQw09bc) zIg6UJsOjnT=T_z4+mmmH%8@wBFco=Pur#N#H;a0Za>6Rj2`{o3r;Mn9F<9<_@2-r_ zQ9|M*MybvVm9t)t(nB9p=!|n#B#A;n6Gj(x|e_%ZHN};lh^*VLi_grLu z`O7yI^1H>~Hw~a)6$==jvh3rcUYj?Xf5(070RpPX8P%9G$rMYmEgh1HxtY*}NTsEj z=m^7-EB2DdpzE&Aqvb3z;>C1hZhp+n>`)G0HXEBhs}+wO*Ugt<1==-HnWYgIvEB3xb59MdunB8-KQR_1!>EF~p z)w}1Pnt5xL*e5-m+W#9hq387{vX4Y_J=OIOhO>ElRBJk;UZ!96NU#4`J^ohCXVFjh z$#3OD5=3R$^LVr<>?6_M#X#Xd0F@Mx=hYRCW4rd}+F~dorCY#E743ZjTCWGXm)phe zE9Qcq=%Qe~Zqmdb4Ut)9e0o?Mx-?k#pVM!qvml;-qL)7Z+bYWSR(;rI>0YXiPZM z1!CG3Jegr$CW0}P7a754(Rdb(-$*nP*%plwaqGvn6^#!t&+qP}nwlT4d zoAt)OD4+G`?vwFOSA`R%we2 z_qL{;3SE_}W{)yXT1ui@pryAL!y}DlKx@Wv1}(uvk(aTu$eN?E6(xqp!{&@=ShBKl zdx;izwTqry0-8v>u1*-B0o}UC+qQx%}8Q~eljmIzOXX1{Vns^u|cN}VXI`)sLY3UHE!S;=_ zD<&_nTsXsFozupSR}hy)i&sOP8D@$W5-1~dwWTgSR zGTYG9QUmIkrldaJ3Y4wKHZx--3qUsGJEN$Wbr)0EO!BE!7LH%KCspQ34(-gbj%~9K zw`CvcR4bO!|FQh=dQU!cxG|huWPDRjUA&v$o*XZ*aCxpck^THLR`JtSlbtL-R8uDc zj;eEwj1n2FqRoKWkCQB(H4i6Dh5C*eW$uarcICR38D)teExh0&1B+By2i0@V(kq!XSfuegi@bq*db@py@h!T)9a5N z$(l#a4a0Z}A_wt%cE!Teh&Xopspi+t4eCpZp^fFXJ?bZFz|&AquS;RCza+Y1I%(-& zOj!m6?g=Cm6N$q#L<+I=UHuM)=hx^=ZP716y5Fqs=7F=lIKyg(J#o6 zVcF1J9S-_2Lc?LF6$4emSE_5DR2SahY2n#A<7 z(m!<+SR>UQNeYQ@lw0^_+D-<>>^o-7zfQD7bjk7sln9F{^v zl1K@Na{du=3z`XcGi8B}1w(AJ-@CXp90@7N1gNBQdv;51 zlH)z$?&k2tTqPqceD$Mjd+pwO(m;y(4_TQH0xps@^Ctt1>Q?Eamu0!zOU{R)?=Mli zco4jI?J_VKy-WEuo_C68eD^sno9VQN{|)3X?F=8c6GDh zKhmcVZOIB3uc02|y80bxz#K?+Fu{=4@dsZPD(Z+`&B$y4I_)nSqAYo2MDErgd1`Q< zgZXbXa#0~2@HdDv^uMWqBQjHy{!d&?!cHhm7^}4d{sKX~xB{}!Q2tMYSHlcxL6J%j zoh~P#6e2;lm5cMRC>r=gDr-$S*8U*KLzDr8^!81b-~E|otgcz{zv|}ZR@nCXx6D(4 zoQwDMfG+@(R>Y5i;|v@Fp<4zxx~RvyHZ@d(A`Glzr&PEZ;3z!kvgAr1zbF5h-7ppj z*l*K%=<(n60ipxbMrsCX$BctG;OEIRZza-yQDJh;x{RfjQXC5eN)Mos|eU z+`*4DDy%eTUViKgLyJao6lL}rsmNKyDWQ2_0%M)i576Jy;WEL$rS8pS+daDSU83Setu6(@ZwOs-}13I zq9Q*ylU$e?42%LSld9`C2Y6+3zMlFiEM>5bo9x~3Pj>3D8UDdmqObg0Hm{45)rlkD zP)z6>5R=jtrLP{I6_au{!7R97K0~gg7jyS&LF)E48odJem@EJ$eXa5ee#<3k9GcP8 zwb}#1iDI~Ss$IJsFz&03G2>LUC+ryUR-q9`f1})h9`s50K_bVWm+s4voly^n4r`Gh zMC%QZ1)r8KUV=l|mn@rw^;hj^sG@B{9gs%YTF?>%jse6;^*hF)2g!fKB+7dI7rodwwgkho>Q{0G@ zlS__GsqSAoYwmtN8CI($N(vX36@_&fVFiWzJerX0?^JA>kkcO2F?u#d($YS2+kUwo z)Hz#xH_*?j*;Vn`=6g`#A4vO&cc?>x;*m}}9Ngapiz9qC1CE>Tv?WK}mh~;=lUJn| z(0un1emJyZ_Kk*^`H-Q!QH=(eBPKGkcS?ug^z0>q7$A9(Y2QW11d(tkUVNV46GlZ;rp1hzpA(p@dR-DkLM#^sTgs859HCWdy;H)(lImy3brLQTF@473fb# zKlTF;NBiC}sk0^#mWZWG{;YUy85U;{vN9P2>6ks#zGAyX?tU4sGc(h4bAM2Jj843I z;P^LEZ$ugkmKWMoB!ZR)Bs$0Lt5JoI5ypS|Uh|zEdEg*rUicn~%NV9VSpNWFO+ALp zzrFU<6jvY|9l(=_m>f@p^E&v^+CQ!$EJ@6&{Sz2zW5{uNef2UargA8!b)F3!FN{Q4 z60+1i0+orMR`b?~uYXN76?m-zH{QDTI4ta^q?D^f9S6@lrD)ddc9b-_SI-#oad-ID zN>nf1T~>Js%$=4uAz_Q`FJ(hTnuj0MIQj_BYKIrj4WZ$46&nUd1qFz^RKfEj3)B(d zA-LM@d%ABLWvg%R3evc68N<~DzGAQ+11W=+$K74D93|=9or^X1RkYzwPJ*4EN%r*c z;0Y$zW%_|LL4T!c9_XPJXyLloYr$xT+bX5rK>P>_koPoinE_7nZyZ&HttFf%RU{eE zx=8({L<#$7)Fu)=vIN(Uf-khB)aGbS=PH8vA?N>!R+n-F25=~Xi81yHm#T%Dr>?6f zZIhd+(yp%$8YK3;8VJ|bECF_{-%4b6G~KtORR(7@P{dC2sEkjoSNsX8`^^6XPfHmGNGg#7-u#pC^uHHL;=37J;i!1Tx~LYefwOw znh05RJglS9Mkdxd?Q_;?mkLK6`gQpynosW^(*jM3)HB^i=Is2DOvm0zv#r|`_7_hw zt-x=5ykj8Hc94IGhYFN&4%(&rwyxs!c$-Rl#LYwEG(MdHUe^f$X+WXIJ1y)qO=oZh)N5C~Tomy|GEAVjv+Dm)>)#cW0wU*_YbQj^}GeH`% zk8N@lWj~UJMFvbueEU&>6TL<%VKz3$D#iW=$%?~D~e<{6Evxva8E0QeYU#sa|z*+Y{OkA6BpCX zvT{ibxx*S@8>GlFM;Mo}#~fmZ+2H1DHTBg@sVB3KGy%tKYtrGawI$4GinQIQCM&LgEoZ z43r3o=(TF?zQ91jVSDY_^%>A>(K#Ll&A=nO?6HBMIqf;<8`5!enhpM_5N-C@fQ{u( zZ36~1UOa2SSW1K?3*wyn8HX!vZs&k#7$dk%R9l-zV`B>(+VaMP+MkIIWd72JOUA}aS{R{HWQ z1_qsH&rZOQoSW6`FmNO|GQ+GupnwdQ#cVS0$0c>uUjKj;m(Hy5KPkz!EjA7r9)m@u zf6rf39MD$Fh>VZHB-k%Du(RwdCe}EYTZd%DVrCQ=5gZxu<61zBOXn&joB@Y{wC6x{ zK;+44#uA7C85wjlcQX#f3jbdifySROh`cyVApM3yBYc3{+BpPX45p{NDTruKvjKqv zd|VdC#Q}6Y;^V%bR&u{+ow`EiAfR3D{>%-}lTN8HU?wQs;ik=39v&Zi(trEJUz8oN zS9=R5tMzgU@zeB;+2ei@*8iFW_g|9&er96sx(_18!foewfc4WImH`wD_T;@V5BoUS zSMI6zeN1@9w%FfH`&%I5rUgzmOU~o9yYWcGwgAyor9<^e2O5%TEOE*i^Xa7Jf4SwC z=k|4(DgP|W?oTnar6*|WzB@Cg>)%f`d}x??8eQMl9hDWUv;OxcuroM1|2kz(h$Cm_ z_=)~Zx69lcZ3+PVdM6_mkRw??{tz(yq|@URvyAna@b+3&7-7%I!Mv-t+w&w&H=&GKX6ER(o*nC)k##TA$ZAqzuhN@0m%76~sXt^9gp z2%P%k?3sT)rULQT5tuy!jbcTqka7lf#%;1z0lfeCMj@!d|4eDvtr(SqE5dEsAaY0t zTTm*j-x^!6(#$irVO5kQb89HNS35FiYbcxOu{~mlNtEiqjG=M|3YMIvIPu|1o0G_; z&QxUA(gBkzqF41d2+x)8r(dXPViEC}nGCz62W09N+=Vml!e8tz13J#+2JV^nCw%-Q z|3?gzjk)RCYC~R}dAG``U?+n6)m(TZe4ND~00z!@7yuGyGHTLrfGhse3HMR}_K9g&XfICw7Z%|q`8E8*(TCbY}Zsj7&FxTuB4^d*Rk}H}5q1 z;1x|$I$AoS{*|ASL^!udAtJP58FE;dL>ZQ`qI~A%ba&mBI-7n9)!j#cX(W3>J)UYG zDMo)(#V&LMFjB{t`CH`98uiTD(t_5EG|oM}*uJaiC`^O%07o_t%JdsF&kV$2L$>ye zjD-^l`&*L;o{5af3JaP+W}H$nIB)o9K)~eKM+9*sk2*C7`eN=R`G9(2n~_=qQw*%7 z;<6tk1J!vWu(|TGA81CB(@U(gaTV+~P_Qu`Z>q66c?#xy<7Cjldh)9g`$0WA)@FO9 z5Q3r3vN^+c2`7^3(Fzo|(rdmt`m3@^E$xmI0z3nHSxxbn zQs>fSgBv&<#%fJWd9kLie)2JMpT`o>&T!f?EHLN5ntB{3=ts?Xa#lX3$wL0&yWg#S zGNr>^2AU!r(8%R5(nDeSi5PGkuOBt5VI)WWpA`HfUC!b%)e@!4LNp1V_X=$i_HE?5 z*{T_`Ai!HjE&B(g7yP(-{21HB9?t>O&T|^cB{ah0Et6FRgs@2bc$8A=HT)MVfce#M;iU`^SPcSK1B?Q4Hf8GdW zQt)GiRpvCRr(*Fl%`}Y=So4zOfj!s)P9rtRKadE3@@7)VT4jg5+F=WPtXYkz-=OIg z{}uJ;Cu?mpsgP!+)z~bVfC0MXkFO#@{pBOSEj(hW|YHz-yZ0BYlAOeV)nc0X9q-+Yd7F*;NWw zPJV=DKO|kEiS3vF|Lh{3Hawqpoa1yg+IpQ<;|s_?gdOtage#cz$^x1C*(1`t#?j8l z;dyM|5^JX`VTeG?m7DT|i>E9f!P%W>X5=wwZ;7QQ|GPFJO#0gY(C^)x&P3fI`Y2&> z8$U($XpAdMmbcr*r#VU=jIz6r0h#UoW2K?bi*A$?4$BlZf~*f}q>`ZLuOe8?I+Nqz z7c8t%acO*3L+`m$#mWTzd?C;%uqwN^$-?=2$f|t*&Nf>1wpPacEGWPsB1}hlyQOEs z%i<|TX3DwZOW2^9h?|*3vWlNwQfZx_;WzDj0mdnv3Cwho{NH-i5>`@^XMuKca^xUp zqOAEs&f;Hd$@iZRhaES}74rVJ{&BUOYtkk<{4#FmL7-z4JB1$i=Waa-UEBq-Ghok! z6mr1?oWuLi%D?s#i<}^c$+(M17`62Lkt>q+u=0eVNEAfhm48()fiDMneg(q`wagJN z6`5vlm8so$-%2y4ad?!IZD^+kI>qIp{B1!|nL`Npj`V*0$1*>`xM^deI;ZDsI08BG zD|X<$taemmnHQMC2$kuIi&{bYZ*- zC)z(k3{LE|qd z*DW)iWEjFc9J77{8u=UbXBTYcB*kuT{2A8_Rp`}X#SZ+r3=@_LqW~_Nhh6Da3G@TR zO_m`x#w|#4DM%I_RM%WLI1kZ3qK`FKR#ws!3s~f@YO9m`ClD21UD!EuM6N$6oR;(P zJ>{O=%rv(T_6w)2x5luZ_!^v6m{%(Sg=C&z1%#8o2oO?r9x1BoKD276dsv@t6u31_ zuN`Cnry{6OQEjDA#}+09_GT|n(vi7ui%h(LcyB2OPHU#SGIR=5i$5=E3F$GWmJ95R zCmPd-LS|jw4#Qr2H1_OWC#ushQmbBOR{ngN;A|_V{8<@Vo-QJ;ZYHqG-)h@1dQtF# z7_$R|R?a9VGct-7WCyw~EEuKurC#OfQPi6l8U5o$NTsrEQ0ohPP4QmnQS4SV4y_wi z>o~_bn{N7<6m5%*qlxLXL*4O&EKY%Nw_#>!IWo)!$`tisb~YwswXsMO%(X^ckb&)l z&mrzLrCT*C*ZR2wX_d~Hz)Fw$I3;|;qcPF&ykObJiG)kz`$F15Ja52vSIfl^-O2D_ z!iUI9-9P38LjTvgtiPRZe9b*0T?Frv?{!`Yt0SMQX$xBYMl=WOsY(DVn}+_2y%E+h zQwKtBnO5{bYs;89;IB}E4Lu7uW%Wuq8pRIUrv0JUI!zlv%=wNG-knfI4v_iXHe|Ln6CbyM?*F{qW@HKKPrs>r?M6JUn>~w$^UEBVwd;v zKaNkFESUryelTYvI(z+ZbvUiF-WO;rl>{C^Fy}ui|Mxna*&h`IODVxSFvjZt_5Po< zR$Bag|Kt5Xrq;XuZ*{7zKNUj$SK)uTKYicNK30dONMytJvFpKGPP7ETTu>)3_UFii z$(M~p6#!6qqH=L%i}sRf^-R*4Mhr$sJ3|FsH2D=<(|mN-n_lVYZ1Q#vRx#t|w-tXH zw&B`8^IM=FEH1{|gJus-JDw}_Wi~^e-xPVBF+;A{$hXJxeYjFLy&W)@z6l6KG46Hm z)&InJk9Yl5n%gBKzzCV^T{UMZm2l~=+1lpASW?bDJtgO9II!bwfMi?OIzrLJ6Kfjz zG+EO(F&MsI{EXs=MCQp@`?sZ^XwLSvS{M@NloAn^h34SkXm6ctb^SGG( z!QRnM@M*64u_%82SRMTmLfWazifPJyG9yi8!@Ce|y^5!KuuxtsDf+h8Z9nqS&G$rb zlnHqq^SQ6Jg;$SON__22n^AK+(Eu{?y2x+LG+HfTULUYGVmPgqZW{n~AU^3xgEGZ| z7Fx22m}opKF}$x6yo0dwZS^9B96Zez)TrNV0uc&l4<>L^&>UvuANFS>kTIkWyZP5a zBu0A>@@GeK<^*;XG1wh+PJzourStCbzc zH)NC2Y$O`(O73N9i!Jh2`_^~kjR)4DI@lZYMXj0raq2wxUWWl&Ve}ZHqL(3_NXJr& zg9;5o_RoM4?6^aqn3OO1S?gN4!VoHV^-OS`54f1^B`iU1Q00(8pquX_;&=&+zuii; z|4lbIRLD$@+{L8JWzg_r70~+=s3(%Of^60D5q?#%31s>D$<2ZSHFA`&1Pilz{HzpV zc^!Xn1X#vk`k-R+<3m_Btwl|Dk9ze{Kj`Vf^6RJitgdZN$Q8SH1$o11K*>==aQnlY z{iLLsnos!Yqr1tyQzzjjYaVP6|g_(-5B)MQ=fzPXz&g9orWL38C zLVl~dXY`rxyPr#yD2&*;7oK{z8~vXIJ)>krR`2n+nN8W>&){r+0ZkcGK3@!jfXnQV z?@J|86Y_{0ZujS}kDV@>2IJuK6U;o>6=^#cEIQ3ese=v)6#`C0D}PGJhk(Ce>Whj`@S)3j;p0)k-+C` zml^1yZ(v7QwLP3{h(@APvnj2^Y+-=n=O`gZWJ#Hkpk(gEz#VT%**i}2cHD=}p6?od zlew+2;qCeL@Gfljo0^26I6Pr$oa@c?NP99A(RHd%2F#vbd!X;C8)YImC2ykd$~huI z?60G47?)RAtk1Zq3;Ff2VNatB^n1vgSKV=R^<(qBha_Vb7qIoqga^lO`X~-2pI1pf zpM3*oo*oYuMXQy>`#PR+^4AM971RT(oe-y8C$5z4Lhr7xsqM)YE<7KY(yukIv| z2#loV4zoouLeJrqMXN2DDOYg$q~-Gt!0qFVstoAq>E~?O258H?_jPGgUXL@b7hgp2 zeb@}11GZjS;g-h{ny<5oYWL=7oUKe(J26TUSw zgU7|NiVd1g6^oK42Io+s zM!80)V-a09QX35Sm)&dYcY0n`UHU7NxRew0Yj>4IS+gpbEUB$xtgQ9h)v_Hz3o6Y> zyG)v4_NVZ*&mSN;FAppBqKu}!4|zBd@L^9LuBbubs=Ca0wJ=(m5+^X%18wdz&#dUf zj2Lk8A=f7aNS?Jnn4KE^OY?1yAfb@VbT7f~=V? zVef~Hd{n8eJRERDqEM2tyAlR~mav4PSq_{qb?zYrvi7Wg5G>&=M+64qGy^#1{{M|%TVEk|<`S*4BC6f($| zXsV<^u~Juy!(b(?7K9F(6+$LRmRX@z;C(|MuoRQvL2At8~w+wW4LSUI6 zZ;+CoO#c5>)u&D*gtEsHr(b5PGFlT2dy@ByMeeQd`dYFEt6s@;J$;bL!j(*c&MSk> zKXQ0^R9NG8>-uxix1r)dX#Dx5i29^bLPAzt(^-Sqz?Bu!#f8-O^6#sezX&k%$-E{r zk@W*DMLxuxU&9&;*Fxt$j%HpV&UYj-C>PC~`b7;T?!|)rBR2$Xepl<-!@uUOWo7>$ zksxhYxU|sAtb8yhsFzgP{ZIm%Xl~s`I28N1`DdnVG<$!IEylQI7_V}*>7PmM@1$(% zDGOps+e#RbDH>od$f(aLr79`Xq7tXYN|AR>3g+n7R$gPCmxp)19Sz)^pEgKGcB^B1 zcwG+kuzi;n3x2GW;_x=*WPaWTuDt|g%Wk2>Y@eVw9HBZ$Q?To3anq$>^i)+}lQ}zQ zuIj-CG%ezCV67IFAl%WqFDqbD^vl*l+fOb}iTRn+;2am&mNe3K^6>iQNh-x?>_0sz zVn#NcWGD6A)Ovc4=`mq4D4eB<8r|z#Tckdb-8K6ELyo*mt>F&K%OQ2+Xfl@7l4aWe z*-XdKbN*V3S{$(w>xUI0V`P=YYLRAI;cflA=!jI$EKDa7Pzap+St_V zUt3#!v4i1)i#DO&`?ess$Vm+@V}WqH1qbdDL-p?YQh3Wi=J;RKW+UQxwS$-bNoF|xnBI74|6Ke#B5&DCt5 zqkFya0O!-eL;1QoS;?1h=Iww8^O-e`pT0UEcz+qu?Dq>%wY zV|~~DEr%7SG?Q3hxf}~?-*{E~O(jf&;_`QR_;WQUM%U&;Xr`fjJHY1h@EJS!SW&r! zDzENrwZWwpKCA)WIP)~p439ibxJ<%Iu#Oe0A(13Z86CzrX93TGlCP{Jx7DuvEBh+{ z=0V!)a>!5fkF0H8myT1+Z>$Y7-mwM`Y&aVS5oIfET+y7GyL2Iodfb@>#n*MY?@=DK z5ih>7Veb4IDp~v^>1ql)=*=yY$0kVo+Lh(xpGB~@?{J~Cv%O-o^uR3abXJ1LDOql+ zZx1ni#yUNrkf}{1ZU1ix@^Shh~=lHcfmknLA$BFmT|Y@Vl!0qV8$elFs}vp zdrhp$J@^=e!-fRPmLP|_yKtZR6tfz({D`_Fy;V|oaJB^`FMJ;eTo&ldn0M7QVGs43!!;O+Q z?DQfP!c0<&47iVdz-V$SL_NVL_O=ZK{i-vVJ&pfbj7&~Rrucb7#R7Y@6>();e4CJJ zxoL#Ki(PQ9{(!%cIcZ3!(T{3N2wX_{0C8d}z5 zBqKvq$-*F&I#TR=wFf4u75lP+KM?I(qsPnnOOgrm%dkCB+?U4P&nSHWFRzns?y(=b z?-K(yULOzTNoz-5UgsEEHR7kK%Oq>$Q}sjGUXY|nBJY42!^;7kF3|i zZ`;CfmXq3Ytq5^f#ijU8e>dbmjw{~KU+=$Hm!LGOcRtgBi;PDi`Iwu#+_UkF`S3PI z(JS0u>$yRZg`}D@&vQMAOO7|#8lS|kWuy&R|opm=>2I14*qbRU}<})1i zP$;Y;rzUN_WhnsRvu3u?!jtphF=E+#E;3o)JBrT2Bx;az%Rm^Iv9#4uJTyoLeYIGE{IEZWxh$!32YX|owiLtt(yjuz zP}{6^9?e2qSRG{0qNe(_2Mfr|6#nz*tj0x-&{UYtxu#are*jqZjRacCE`i~~mnU0d zh^=vFgn+9zrK=S|Z21S`foZ#a0(|1d$O(6#U$bY2Ykig)84Jtu$}ICKirarRK!KmU zd2K)w$Z-J+YFfX~9{5A85aCd|?2xgFTv??Z;U#?&PgL3+LVIx^5kF4I$(1beYKmpB z9f8iEAH5C(z(1s^TpY?xln9QsA^1y|<$j)^@IV}Y$#=A{rWKR0|5RE^LnDjJb&O|T z)j_i5uyedsoJvTeKoyCmE~=QIP8zzeW>S}&Jl?1}{~0n=m5tsq7sHpeGIp16`eDMm z+>p-(<4zvhl_kCP8+S(}ZK>gPQFLKb3r|$_^+;K1-TafCd|32|nEAbz{HTN6y5xwZ z24Hl&RM~1b;fndm=drSUNETnY^GO|gf0))}RGtgHiehK5ekti{HRB#_YQi8;^GFvpJP|&?PIUT&k^GYhWGWk(opP#?TF@fSVyFd}6A)!QJzcdUm zIUEDzZU0lZ8As)M+qN$tE#wyPZ)Q98O{K(D*_^mrO20DfSzcsJiRBzq=^q zlzh8d;ftJs@j z5e2A&Uq2lHqxUCo@Z#$cwVB{?2TV zi?OOMQ24yQ;@a!zQRc5nJva8MXeM8lU{{4OgJR-oBiOWrJfqcbXuxnOq}=~JL2p?W z2i_Mr^D3Nmw4G2T#Umg%$W@_tU7A7aQS+-r=Tvd#q7u8gpe9wC4uhDU%>HalfIY3j zv%SWht)8K;lKIF}vqyvQN&9JEz4-Uvl=cBd#98@{jO1H9{9#NPDel3run||Y$7)Cr z1$^<76(z`tBBaW%d<%(_qnbrNx7xRi86OqV+ux00Df62+Ln$pwLksL)oWq7LE+Xct z9;b}~ZP)FS=wy$c=z%PW6Q!4Kf3p-Hj(Rdf?CDWzD~LBnq$fc0bBeGyN9b=;I~yZc zmL7RDPUKYaa>qj%%(izTmNzIncp$8P*O5da&%kJ-I`om0A)e@R);bM{b>y5OybOpY-w4w-?py zc_ynwqo0$9jJRQ@*8iI$@A;4M zDO3myx*&_`KGS&8Onz`7VA{(tM2-Lj*ggWCkw1^+S!yC6ilE3iKEfdG3Wqt5p{o~| z!?!43#PhE*VW2Hk^AC0h?VRse$H=yu2Hm1u`W@H(B&UQT@eBgPueJbB9FJaVqa>ML zEa!;<-aZ-MEq*oY8;Ua>vT+48aHA2OsW-eO564Ap{O020=8W?8vVGI478Q&1R&syy zf)&xfq<*str$f``59>TfvDuz|f0I7TeB>kHJ}cFnan~j0UbCTMnQhrtU9Lc#!(aHoE}vOEyDu)e z7!2N4Z5?TxirT(ku|Q+}j(X=5>XH9k=NU5-TIEgXT3IQZZPsy8blGvIbXv-b&8`=3 ze%#;QQ2keA_RhJ~asG%HhZC~YqC=zlv}iy1b$7v5u1%x-tfFaF@Vq%lS-+F{Sh*s) z>~@yFy_1r9q9z^H&DPEo29wtfzf%3^KHn)57op3SL{hN~cS(ujVwlKjV}D(kfJ^qd zPROFYQwKT$3s^ZxU1b$W45_BJ#awm%ix?`SP&t-!b{=_;HQ{jZO5l_It(1aW#eqSQ zv`7`9VK3&x_Eb?rSv2r4A=W%<5dX%aFIi2SVpXS z2!yFh%5-l>*iMP*lHzZ!-LO`yM37J>~MX{irQq}L32W@cIW36vzY0DdBm z`|pnWJXw*}xrMX%xIDV-AHHM_%ex&LR8yDlW;d)&OqjKoY^QhG+wk^&OMBiP(e{Q< zr>Zjr3G0NH^2u=iYRP0BV0SA`;&o5Y9y54wkLVZW0k>`YY7!5A&7#stOFr^)+=q@&EkuANrnI^cJ( z_Bg{H>0jH?^-l#G$|WY#+ua;N*4GzFJ7u0ua?b^}&PNdU zmt@kB1ZtCEb=*;&)(4xDiPvqO`g~V;=8@JX;w6P=SLl+qV-6<4 zCzf4uQhi^hIJv-AAVq2S=qT=6}`Wy1YCk-PwO@ zCHK)iIZ^Hy)1IX5xT2PXjteCzc<$==aFQ`xm0}{@+N6x|aHKxL54f>5S|`lQgPsdf z@zoOFZ?5PUCaT$mr^C6^#@MjX#PdJ?ZA~)&yK^ze;x?Iubb&{zhCm4#=ka;I{j9kE zg`c6_JWB_L2h0I)^e^BBDb_IC0oDj`9>5=aK}P#?t~|2cN-dQSWKT`Al5IWLt9$sn zFtFq9s_=&NBtdHoB)Ku_;@;)t1O76z8oVD5kP3LN-+?7<`BKTe!yxoh(>v7$$P2M;z>$uBdM(Ks-NuD&J;3eA z=yUIF#P_(-hc8!XOKT{UHN#1DcZq57FfSg7&>K6`KvxKAWIsafdrvf%CD zu~6(aAI{acb%+9SC7g0IO6L@nkAu^9&v0Vohqqgr1Ey~1!uMsfv5lXMnTMRPH~M@>v+fz9lhZM#= zc66csdckm^XaE8ikx+6JWVJPe0l{jhlVhZsu$6z8Gm^l*M)il)KsYH~-)O#u$`4Ny zFRbbbVGZBCGWEmbN6E?JQvnEK0M6eIzs7S+;y-Jk1d3dXXdKvn1WqW=&SH~5@)A0V0Z|8_}$EWhB&8<)vB zouHL`N!I(zVd!_1zDa(Ek*(Klh4gb#M(Kp-u{#!wIDi7hXjTlWcqTuxF_4g^$*o?& zZ>q|AgD%c`2)4r~YtkaY0nfcwb?QgnA!4#S29bR+#sL(QM$QGe?3Zl8wYuWuCGv}4 z{1rA7X6`n4A290-KsMO_m00_pHfnc6|u)PnU#s&ivf8{r2Cp~E;S1N7-? zp%PGFcw=He%#ALY65ltEN3-?6gBABFqgp$H(ZM?G>m)+jbzov(v1L$R0NDPhb8FB? zEc1$U8feF%#V90B<;sG3O>*>Oc&VwuhWSYVN4BA+Gc|#fvc%;mq-9!7z@EEJa77#C zh8}@>ydA{`gOM*!GAzR-YGoc^z>s=_VNtIYkM(DOONIM`8H^3O^f*q$ngM%7m6-5Z_9IB3Pd5E$xCIj4CRBp4JjGSCQ5K`4yt@2 z-704RH5VaVtl>^@WH7VGzY-<1SaFBqX90oPkoVu9WE?5pruz+H-ydTHq>^#p!3HOW z>!NPO*@={S2ehE#_Y$E!96?uhcs^x(Qq?uzfGO@!Eh#aI_C$TbOvjw8qb;`Mo*(HL z+EWoq-avvg#ar{kKbm%Eg*UB=n{GAJGa4)vwWlOjkd8?vcH07%rag zy+<4&uYHS!myWtG{@<}4*2qF|i90pNB2zs2bbc)QY*gGRq;c?DI(8Z#HFAM_xqC>b)@u}l zn1iVrk{`ToHaA$hl^Y-BJ(i^kLu4Sc=Nw`Kkp&rReLpccYlfp7(=K$+c(1-+S~; zga77HJv3~VjJk~0N8@a9_2qj~mrf^np3`E)O_ffUZ|h=eRyzov1XPVmdW6o5t3A)u zb2lGO?-FybeVb#~=@I97R@`rU1m7PXf>`#Vxj(+NbCP$ezhFhj#qlIs3NE1Tz+!T? zo7?{kKP;a)dtB5)FIl0Mhb~p+wG^Yh$`P@xAwHS4NA7o+eBzo8L+5Y}w%D3=jOJ}V z22OxAfBM?e45*3Y(A+!bA8IU;A+hS>Wt< zIP8vREMB>9DZ6U&5F6AC5XG1qU@bTq{cduorQLTQwGNJ@*?7bS5jRjr=xA!XXK7Gl znH->I&54-okC_l0Tr3t-VN1Vz6?V$wLDHviWt87h7zLi6qOQ&zf0wxX>rc0r%YQ>c zEtUjdoY`s1uOK58B|C=B42+bLzdSf1C%*P>s~%V9#u5}hqXummui&0NDvvsW2LoN| zZ!7oDarh48>*_mh!{io@Dl3fN+8WMm1n_YGu)8Sdjo4D9N{naV493fOl;Wy40vJ632@fjgSe7cDAdr~JgLII)K8Wn1j49^cplVplA=fyH+kUNJ*0a(p{8 z!+`|&xFm8l6wQ+ZG?{6wbMvW?&?}$uD^C}Wy=?>tO^L3kwY5qoiFVHjMGAmc(_{EF zwOCW3!Dg&~VEHj~)2QX(6PHI}Ad9SWG7Z=A86=K(os$b9#e^HuM#)qSlATRRt}6pt zMkj2%IFz>+3ni4&E72DDsIx5?sj0kN>#lTmN)J9l>#cN6b|Y1{8Cp5C z>n5Y;=KfbvO?HSJ^}f?qm2iopJF+{c`I_9(ysjdrr^IZN(RB7Ax4w2b)nW(=3B2jK zf8Gm1G#B{YYsm--L$pwY+-u>43PUs%MSi}R7KT)e{>GckGTCR%Dg+1IOSsQk`HRDJ zg_zIx+bGIt?BZShNYaAlB%zmJ1P`@Ut^IYgmp}p0*|Zp%DD6j<0XSZ{)evXp_rGKl z+UHXRsNp3+>qSh=iB>9;(JiEH%=1*ZQ_xGrUCn`2CsWYPMEuNsE$F1k#a~0UPSf!g z{2I-fXb*$w7ySN&GSjYx3vk(Gy96jM2r3_@!xx&YITGTuOT#qnZ8_>ugUEn380=?D z=zM+}jnrT=c@4@Fv=Oh!ctLKlZaMoDU#I(e7@*&$XDk3$iF4w~O)dZ9XKl zqS0sYNj22Qum6Z8PGK5x)3m? z9znmNmmHD)m^5kUMiN9l|zP7(`{O+2F4Z<8CMr zk_2tTUIG!@Qc1ItUBsYAHyk0cPZgo&Xu*zQfU>{iT&Y%}) zW;&kG_$bt4C-$d4yzeXmF=f7QKExvCuMMSAH2#f8u|j-@vo$_D(I(pAYVA_K{oBUu zC6fLa4UkcsR&53dC_d1&Vz@g`r6;aLO+qGX@Itt4iz$48gC;~tJpn^GDz{laRo!E9 z-ZID&M4;Wjo^7?I)^w0`S1M=*q$gkWI;)vib^uH(IaN51V$h;)_(UchH;DOzq}6Lu z24aZ{8-2a5i+L0ih-nskSJX^L?8z=hN#k-dMf(N@| zFz6#q$Ri{we^#l0w6fep6|idqHGL(Gx?u=pSW#Jj2rscL$7hc&OXkv(2+Rs9tBU6l zRdF)*P)&ph5f#}^W%Uv=H;2BWNjWFMgCizoWX7H|bOd*c@zzL4fEHPz;1O$VCh8FL zKUktxbh?jHA&2spa3#5F1;HJ?Y0~6kHpvIplTL{6$%Iox@=F&MZ#$7BkN*J=)g2c@ zwf|#aUv!}ND%s>{HcDThrZE<49f5qaA4hBOijKl3UObPOdAu}ZOK8g69s48{|BqM| zJ$hJ^E+|K`qHY&vwk1hOwI_A8y!sy#G#&V%KvgF7>G3MaZQI*~e6F~8EDcc7&AJ{3 zZ@n;f;d%`C%sRRSdJ(0OVFNFT;5D?s@{7vaeXnqq!MxU>tlzCPKm zD=G~*ysYZ54|lq;i^s3u|J4`*4qBS6ni#g$8uu@vh{mx+usu75%J1GO#jEN^FfI_} zpu34Y;5q-Jg{VFd0UB^c3~8zIgo>=taw~G0=wpi{-69;Pn8E)O)eb806);U_a`W=b zyS@N+avKJ;@Y|q3Tt_jb^Vm17 zZY?P?h(Favs-X?oW@=C!mQtan3AkSF9&E~D0dPNSq=+x2(JRLchxbK|QE??dOP0At zo7Pad1*fwGz?Nyl=81}%XoBQV|KHxVEVqsu(f$1jEpHZf5d=trsZ=&IsZ?r`Nh(t{ z$xg)wXlpL@xRyNj&DV!-g4BcEut`zAz3{@SJ|IOxB+z~OoCvai>Y=tTMH;BG^25T5 z$6@(1#zJwkrUtFn=mS;HQ828`TUOw&<$uHA;z}&T^jQJ)g3I9C+8_rUw%Y?>XWD`` zkhD@6{urd?Jq7>{PpgO3At<&apnY4P4@IrBH`h7~>pOk=Ak;3>hMf;v?4LWeDX$-l zTvk7azhf@i$jY-fMP6%Dn4m8=3+dTClzoJt(Eax{k?wl6kAOoH7!TRsT^0)b#t-Xl{G2KbVjKRZq5}p|vbPY33Alr; zD;lM|Ddl}bDer8z_Y9x6<4|PBPrHvu!Y#6;-`dCg6^XlJR~K-?+{jYI%p|tQCM-X0 zH?T4Sx=OQoU^evJo7m6)`uVTSUV=`2^fJ&yZ0^%y3O7arpRi&!f6Dnu@#l8Z=mis6G zjES0I_464Jm*1FZJs5dd4gSDhzYN{J@>vH8Dr@rUb(dzFfuXxoKgshS%V2P^NZmiG zG#v`eFZq{v=+<c?AsHm63ryIB3M(o^kryIq9uw$nVphr8_}87Xcn!6QpJ zk_ql9i*YLnd^?alk*@8Af$dSZ-9n!VV|UvziwVp3^=`ZDBQAVxDcyIBactZ3JI!{| zvOLSvTJ1c`cJ+3xQ;l}nlsnaDS4`2WbIiZbf@dyH_H z*IC2n7*M}m`M57{<-Sp2z*Kzb0JqwiMW{(!(`eDok7m?%Hmhyz~V>fY= zP;tlhl7wU(r+K$Kn0LG52v>-%tRr(J^YoWH^IdPy46b^+>#C0QHow~2oJpI_L)UTq zmo#u`F$d-`={l0GBk4NUk)-R0x~^+VsL8r4Fd1ar(|`JUxj zPFE4qw=8D4ekYS^Mu>&O9v;lND}fCgd`zJ67qB;NkX0nkR;>@ z3`s%`g_0!XF^nW3FCnQvcJBSLBnf#jm?R-d67mw7Bq2!>k|ZHX5^?}Tl902IgdB^> zH3woANkZNRD~u!|=R-6jNk}w}jU*x4NRouCLP-)53?fO$9$*?t$RB=Ka+n|_=}3}} zB<0B|Pkw|U9Z5ZsbR^Hml8)qsNYarULXeK+2;6bfksLyjjwIcvM>5~lJMprQJlEDrf&ETA=}6A|ic&taL|0Kt3a+>FooK@= zr&?cBO5T^Bf9Mvx--4o(=AD}FGU8Jux9e0KsBWY0jjt?2t-Zt!9Xgu z4+f&KcrdVr&VvEfydDguCHSCFCDR83sW?0sh{n&sz-syp0#oy95ReFaj6R*^-Z92< zbL71+#$u3tX)45Z(ln|ts1!RRYibSxqETGnpguPQ2W?0qI9OFi$AFr8ItEmgy)lq( z{TqX9i`pnuRozBl8a*roW{rIw?C|sNR3#V=){BvbFr$Z8znFSG9m#8*H-cF?(j7OQC%q)Fh4N!2 zW6zEfC-MS2j{Mkl>_CQ*4-<$dm92No?fHz0UT#k^_k3T=vRDL(yaQRxKq9chdO4`M#W+}bqj8w( zcH==iIKHZg1jIFj=m{n zm03uo+_?SNMCv5(Dl}5_A28p0UcOz}wH;1AW8#(I^}WT$QUJiU=#Rf3PG{HHKTU5r znT3&ASo3+0f>0CzF0&Mh)WRxF)zk7(rGSRO{&NuB;gkkDm*c%Zi9L=Z^ZV85gR=5m{L zea)oH9NX&nnn~9e+|nLvmm8|i(FdrtN(W8FxbURU4O^@FzGhHvUC-bQ18bblFrdov z4BY>vd!OM!tqB?iTe+cOAhmk|3RC-|VL+`>8V1!kreQ#uP8t@5{Z_S^8U~}es$pQ7 zy_yNE^;turv6n;>Gep697HlYN&x;L%ZA{rPpgQY>!E{CEP{>wB5e2KZODIg`;D*6y zR&I#y*w|>IoHBPqfzP?Tfd}c?y@7Fk-!~+%HGo3`TPHX$P_u*sW6pZRVMjP&5{Df^ zcZm1c+}VKN62cVQUpx45+IRi)ngm^-wXW zo^B}~iod8w@|=cPO{WtvLSHx%0qv_cLZRoK@~|WHE%VIq*lpl|iJsvwnwy^42$ij# z8CY|zGaR5X+B3uNklU95>pjC^bPqnWA!=JSB>J=~-x~(0?fH;Hbbb2Fz+J;WvoTud zJ~Mo6;b(?!y!;H|N2Y#e<8sc9Mkh-TK z0%s)5)^Q%h;CdE>7--Ln5CiR*65=w&(<{)meuY$yp>hnBV}`($Ng@t3mCWNcszsAZ zOCEVFV!)H>Qchn%Yr8!rsk@;?G<*FSs1?}c0-UWQ)_2heRGT%|B7s1^jFcR_3TJFQU=_TUJy#2c#7pVlhP5f zaNIDC+`!=pT%R`oes!X_*e=SW=I2n($3^nAU1wK( zy*=dTxZXV zrd42I8oK3)aeYT~!~)~@&bW!aaS?3PI!%Pz32#ANn0p8wq^FZSHf43 z!z>nsai{{{iCpP + + + + d41033826a12ce44a1b33eff2e7905785e0999da + 1211014822 + 319b2951aad2417c8961442ba692d4700962043b + + + + 4f8f83525b232db93a761ed1be79515956b574cf + 1211014822 + 70eb95f379e0db1c9815f0a1cb2269d93e408015 + + + + 28a6aae0cd873e1df286d4a07fc7e54263fec79d + 1211014821 + 5ad445e403218ef4a6585dbfc37ccf31d5a10096 + + + + 553f609c610b0cf51b54efc4c5c618537707ac8d + 1211014821 + 8c840e0b03ad8c2ed0d4ddf57f9a6b5cea3ac412 + + + + 596018d6e767808ac6bf4e89cc0ea1ea7a1916a8 + 1211279868 + 596018d6e767808ac6bf4e89cc0ea1ea7a1916a8 + + diff --git a/tests/zypp/data/Delta/repodata/repomd.xml.asc b/tests/zypp/data/Delta/repodata/repomd.xml.asc new file mode 100644 index 0000000..4533fce --- /dev/null +++ b/tests/zypp/data/Delta/repodata/repomd.xml.asc @@ -0,0 +1,43 @@ +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + + + + + + d41033826a12ce44a1b33eff2e7905785e0999da + 1211014822 + 319b2951aad2417c8961442ba692d4700962043b + + + + 4f8f83525b232db93a761ed1be79515956b574cf + 1211014822 + 70eb95f379e0db1c9815f0a1cb2269d93e408015 + + + + 28a6aae0cd873e1df286d4a07fc7e54263fec79d + 1211014821 + 5ad445e403218ef4a6585dbfc37ccf31d5a10096 + + + + 553f609c610b0cf51b54efc4c5c618537707ac8d + 1211014821 + 8c840e0b03ad8c2ed0d4ddf57f9a6b5cea3ac412 + + + + 596018d6e767808ac6bf4e89cc0ea1ea7a1916a8 + 1211279868 + 596018d6e767808ac6bf4e89cc0ea1ea7a1916a8 + + +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.9 (GNU/Linux) + +iEYEARECAAYFAkgy4a8ACgkQ1iFKyE0tq/K1UgCgkm7T8QgC27qE9labaumrHo8o +o/gAoMX7sCbj6CkSTL8a+9eQf+BD0eDV +=mZtk +-----END PGP SIGNATURE----- diff --git a/tests/zypp/data/Delta/repodata/repomd.xml.key b/tests/zypp/data/Delta/repodata/repomd.xml.key new file mode 100644 index 0000000..66bd5ed --- /dev/null +++ b/tests/zypp/data/Delta/repodata/repomd.xml.key @@ -0,0 +1,43 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +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 +SRTL0aukStJZdNaArDg/PTNxFg== +=ahjB +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/Delta/repodata/updateinfo.xml.gz b/tests/zypp/data/Delta/repodata/updateinfo.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..28061e072b1c95869426339487eafbbb59e7645b GIT binary patch literal 4657 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 n#i`{IKR3x-z~`@ [edit] Distribution +> +> In the past SUSE first released the Personal and Professional versions in boxed sets which included extensive printed documentation, then waited a few months before it released versions on its FTP servers. Under Novell and with advent of openSUSE this has been reversed: SUSE Linux 10.0 was available for download well before the retail release of SUSE Linux 10.0. In addition, Novell has discontinued the Personal version, renamed the Professional version to simply "SUSE Linux", and repriced "SUSE Linux" to about the same as the obsolete Personal version. Now Novell has also renamed SUSE Linux to openSUSE with version 10.2 of the distro. +> +> Starting with version 9.2, an unsupported 1 DVD ISO image of SUSE Professional was made available for download as well as a bootable LiveDVD evaluation. The FTP server continues to operate and has the advantage of "streamlined" installs: Only downloading packages the user feels they need. The ISO has the advantages of an easy install package, the ability to operate even if the user's network card does not work 'out of the box', and less experience needed (i.e., an inexperienced Linux user may not know whether or not to install a certain package, and the ISO offers several preselected sets of packages). The retail box DVD supports x86, and x86_64 installs, but the included CD-ROMs do not include x86_64 support. +> diff --git a/tests/zypp/data/Fetcher/remote-site/diffs/file-1-2.diff.gz b/tests/zypp/data/Fetcher/remote-site/diffs/file-1-2.diff.gz new file mode 100644 index 0000000000000000000000000000000000000000..82941aba353cc69ecfbbb48bdc3f612c442124ba GIT binary patch literal 713 zcmV;)0yh00iwFo@oE}C117>M#Wi2r+GA?9kW@Z3&R84OaF%Z4;D@M5#q_AouR6!41 z2uPI*tqA3U5Sm@jcCC8t$o6KFf6ue`BWVj#58JUl?_=I%bMrg|+(&m2inQHCv>BR^KQTgyrd~lWxu~l^ET`eK#T-f0RUxBox z((Q3SNDS0Bx@u6XOs7zjeH0t?4lrKZh>CJm*NTmth%6I`rJi*6_b$8QAtZHpFTNEOIrut=OzGHabwl2?5Yv(sNN) zg9SI*c6+)wFU~C@W3)~fBf;d7mxy~4(S-J_S&__Ug+XM|Bg;fW z=}RJ%l5%k6afj}cIG6m+{a2U;9)7t8E|7Z_jR_32T1!KLeB?itXXKqY;< zGB_jgC5-~4`%~gO6vpC45*VYZ8n~VRXfi!%bul10J4U|4^)w0_tq& zwp-^@KrU$gb4}NqThc8*9F2bBN}5~CO8z%I9OwBZ4M?tw`N|D4nwrawO_#G-&<`*@ zW{jpeg;Aqt_>??uM)MFhMz9BB3n&zBjkcl|ScnkWm~ch67IT`&B-LB49`R;q(E$rv zASVBNASiOk?9=+~_uH@7S(n+4_37c*F^Bpu-&iaAe+2*lHep(Z literal 0 HcmV?d00001 diff --git a/tests/zypp/data/Fetcher/remote-site/diffs/file-2-3.diff b/tests/zypp/data/Fetcher/remote-site/diffs/file-2-3.diff new file mode 100644 index 0000000..275e632 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/diffs/file-2-3.diff @@ -0,0 +1,36 @@ +14a15,49 +> [edit] Versions +> Major Versions +> 1.0 - April 1994 +> 1.0.9 - July 1994 +> 11/94 - November 1994 +> 4/95 - April 1995 +> 8/95 - August 1995 +> 11/95 - November 1995 +> 4.2 - May 1996 +> 4.3 - September 1996 +> 4.4 - May 1997 +> 4.4.1 - February 1997 +> 5.0 - June 1997 +> 5.1 - November 1997 +> 5.2 - 23 March 1998 +> 6.0 - 21 December 1998 +> 6.1 - 7 April 1999 +> 6.2 - 12 August 1999 +> 6.3 - 25 November 1999 +> 6.4 - 27 March 2000 +> 7.0 - 27 September 2000 +> 7.1 - 24 January 2001 +> 7.2 - 15 June 2001 +> 7.3 - 13 October 2001 +> 8.0 - 22 April 2002 +> 8.1 - 30 September 2002 +> 8.2 - 7 April 2003 +> 9.0 - 15 October 2003 +> 9.1 - 23 April 2004 +> 9.2 - 25 October 2004 +> 9.3 - 16 April 2005 +> 10.0 - 6 October 2005 +> 10.1 - 11 May 2006 +> 10.2 - 7 December 2006 +> diff --git a/tests/zypp/data/Fetcher/remote-site/diffs/file-2-3.diff.gz b/tests/zypp/data/Fetcher/remote-site/diffs/file-2-3.diff.gz new file mode 100644 index 0000000000000000000000000000000000000000..b2db7df4af970f7590d58df43787e24396dcf801 GIT binary patch literal 342 zcmV-c0jd5UiwFp)oE}C117>M#Wi2u-GcIIlW@Z3glEF@dFcd}C&R6sUl<6xi(2a?S zaX~V=FmYpCFifME5hevp{CnH?N-48F_su4Uu)J9a}qI&x^f z2b%)OIJ>!H4;R~=8E7quW!lqvKL14sdo4YD9)8Ww(by%Bd#yGV%E4-Z^XEKH3-ul9 zy2A%D6CNKL)D=i_PhQPsikHM?a#<3|z_TZFv~y!)plDh>_hvKSpR4lGRO*Yh3^s zkX+H=NKp+rdugX3^!T6(3K1qaED&RT&bMZYM7r70+)+(EPMZiQfbdS^y+ka+yGZUS opeHTXd;DZL35xVS1SkN&kHOJ`Xn4x_mxW~a4_g8uMHmAB0C}{Pwg3PC literal 0 HcmV?d00001 diff --git a/tests/zypp/data/Fetcher/remote-site/diffs/file-3-4.diff b/tests/zypp/data/Fetcher/remote-site/diffs/file-3-4.diff new file mode 100644 index 0000000..070e5cf --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/diffs/file-3-4.diff @@ -0,0 +1,5 @@ +14a15,18 +> SUSE has support for resizing NTFS partitions during installation which allows it to co-exist with existing Windows 2000 or XP installations. SUSE has the ability to detect and install drivers for many common winmodems shipped with OEM desktop and laptop systems (such modems are designed to use Windows-specific software to operate). +> +> Several desktop environments such as KDE and GNOME and window managers like Window Maker and Blackbox are included, with the YaST2 installer allowing the user to choose a preselection of GNOME, KDE, or no desktop at all. SUSE ships with multimedia software such as K3B (CD/DVD burning), Amarok (audio playback), and Kaffeine (movie playback). It contains OpenOffice.org, and software for reading and/or creating other common document formats such as PDF. Due to patent problems, the distribution lacks codecs for proprietary formats like avi, but these can be installed with packages available on the internet. MP3s are handled in the fully capable graphical media studio Amarok with the Helix engine (part of RealNetworks' RealPlayer), when RealPlayer is installed. This is due to an agreement between Novell and RealNetworks to ship RealPlayer with SUSE as a solution to MP3 patent problems.[citation needed] +> diff --git a/tests/zypp/data/Fetcher/remote-site/diffs/file-3-4.diff.gz b/tests/zypp/data/Fetcher/remote-site/diffs/file-3-4.diff.gz new file mode 100644 index 0000000000000000000000000000000000000000..f0c5ceaad18a135729f535ce744f3f4832aebed5 GIT binary patch literal 711 zcmV;&0yzC2iwFqAoE}C117>M#Wi2x;G%jRmW@Z3gR9TPHFc5y{SIiq-sbnvZctT?7 zE}&Hp(d822VUkRmQ61Z|op#HwXU6FTZ?QescTBEdU0s2+`LXz?QY=o>q?Q0nHk@`^u%<*+0<`rZ1M0vV3Ng>yq1{Q-uG4YY zcCMyQ5Vh<*)x!|;`>9lk>*RbcW6Z890iTm-Y!eDLn0vDGMs%RUh1HOHY(H2S zYeg*&mvXG+oIU7-hH&so?W$f?(Tony#92%p3Yhd+TrbK>h!3tb;*N19vKC7RF8j=z zDiWn;P1WE>iS>agVb~o@XEkxdV__m`4dK5+3nd-J+FR92IdOpaaD!}6x`H&(u51$p zOR0eA;&$+9D*!c-aLC7NP|O5o+6#J-Y#pCkzEVwR+Z{MdnX1;wlhjqDv`Al00)8k|kEz&iiP* tdh5J+9y7a6gi({3fprNL7XFu~_*HQleoU4~R^zws On November 4, 2003, Novell announced it would acquire SuSE.[2] The acquisition was finalized in January 2004.[3] J. Philips (Novell's corporate technology strategist for the Asia Pacific region) stated that Novell would not "in the medium term" alter the way in which SUSE continues to be developed.[4] At Novell's annual BrainShare gathering in 2004, all computers ran SUSE Linux for the first time. At this gathering it was also announced that the proprietary SUSE administration program YaST2 would be released into the public under the GPL license. +> +> On August 4, 2005, Novell spokesman and director of public relations Bruce Lowry announced that the development of the SUSE Professional series will become more open and within the community project openSUSE try to reach a wider audience of users and developers. The software, by definition of open source, already had their coding "open," but now the development process will be more "open" than before, allowing developers and users to test the product and help develop it. Previously all development work was done in-house by SUSE, and version 10.0 was the first version that had public beta testing. As part of the change, YaST Online Update server access will be complimentary for SUSE Linux users, and along the lines of most open source distributions, there will both be a free download available on the web and a boxed edition. This change in philosophy led to the release of the SUSE Linux 10.0 release on October 6, 2005 in "OSS" (completely open source), "eval" (has both open source and proprietary applications and is actually a fully featured version) and retail boxed-set editions. +> diff --git a/tests/zypp/data/Fetcher/remote-site/diffs/file-4-current.diff.gz b/tests/zypp/data/Fetcher/remote-site/diffs/file-4-current.diff.gz new file mode 100644 index 0000000000000000000000000000000000000000..d54de695e7c2d4cd9cb8986a09e858d24b22a632 GIT binary patch literal 899 zcmV-}1AP1+iwFqWoE}C117>M#Wi2!;hmJh4$uitM-+jY@B2@r=f-)s1R|7fl^uRhX) zqc46hQ!9aP8@kzS-ZkZqwZzW(>^kYmBwBp7J#qJMHbH2cx1ZKeH_!BSl=?H8WW1w= zBMru}H9z#8qtEOzhl6&$T|d2hrq6479E~+|q&IcY>qwmsvk#nvl60f<*6$7!lm6M6 zm}u~U5=Pxc!}Q3V8B9k3XWm_*4rM*gIh~+aw9Y450fXM0q&Im&`!KDDExzUV!UsjU zjHVlD`)&IPP+T%DOQhtf73u{Y{Ve_Z>GqlKP9p#s`ee5BXJF&DBSV%Qqh~N~r#+Q% zgHaYOr#WL{q`DYx%B3K zGR_qB)DoQU0#EceZ@=Cgl>x6HRyY=uK(sWKLi6+97wNKVy2nzk;tOq6Dv$5P-q^72Bk+zP*mG8(m z-XHCz;lXxScKS@rcnp2?^LQYuYfyLbxShW&KxI<&Js&%Iz@F*r{h==$3>A002A4zx4nB literal 0 HcmV?d00001 diff --git a/tests/zypp/data/Fetcher/remote-site/directory.yast b/tests/zypp/data/Fetcher/remote-site/directory.yast new file mode 100644 index 0000000..951afd1 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/directory.yast @@ -0,0 +1,10 @@ +complexdir/ +complexdir-broken/ +diffs/ +file-1.txt +file-2.txt +file-3.txt +file-4.txt +file-current.txt +file-current.txt.asc +file-current.txt.key diff --git a/tests/zypp/data/Fetcher/remote-site/file-1.txt b/tests/zypp/data/Fetcher/remote-site/file-1.txt new file mode 100644 index 0000000..a3670c4 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/file-1.txt @@ -0,0 +1,64 @@ +History + +The SUSE Linux distribution was originally a German translation of Slackware Linux. In mid-1992, Softlanding Linux System (SLS) was founded by Peter MacDonald, and was the first comprehensive distribution to contain elements such as X and TCP/IP. The Slackware distribution (maintained by Patrick Volkerding) was initially based largely on SLS. + +S.u.S.E was founded in late 1992 as a UNIX consulting group, which among other things regularly released software packages that included SLS and Slackware, and printed UNIX/Linux manuals. S.u.S.E is an acronym for the German phrase "Software- und System-Entwicklung" ("Software and system development"). There is a rumour that the name is a tribute to the German computer pioneer Konrad Zuse. They released the first CD version of SLS/Slackware in 1994, under the name S.u.S.E Linux 1.0. It later integrated with the Jurix distribution by Florian La Roche, to release the first really unique S.u.S.E Linux 4.2 in 1996. Over time, SuSE Linux incorporated many aspects of Red Hat Linux (e.g., using RPMs and /etc/sysconfig). In a move to more effectively reach its business audience, SuSE introduced the SuSE Linux Enterpriser Server in 2001, and consecutively changed the company name to SUSE Linux in September 2003 as a part of its overall new branding strategy, as announced by SUSE's marketing VP Uwe Schmid.[1] + +The current mascot of SuSE is Geeko, also known as the "SuSE Lizard" + +[edit] Features + +SUSE includes an installation and administration program called YaST2 which handles hard disk partitioning, system setup, RPM package management, online updates, network and firewall configuration, user administration and more in an integrated interface. + +Starting with the 10.1 release, SuSE includes a secondary installation program known as Zen-Updater, which can be used as a secondary means of installing software and replaces Suse-updater providing notification of software updates on the desktop. + +The latest release, openSUSE 10.2 is available as a retail package and as a no-cost open source package. In terms of software, there are major differences between the two packages (see Reference below), including the fact that the retail edition contains a number of proprietary components, such as Macromedia Flash. In addition, the retail package, available for 59.95 USD, includes a printed manual and limited technical support. openSUSE is available to download freely from their website. The retail and eval versions contain one DVD and six CDs, while openSUSE uses five CDs. It is the first SUSE release to be called openSUSE, previous versions were called SUSE Linux. + +Other flavors include dedicated server editions and groupware servers geared towards corporate networks and enterprises, along with a stripped-down business desktop which runs some software designed for Microsoft Windows out of the box by virtue of WINE. + +SUSE Linux Enterprise Server (SLES) and SUSE Linux Enterprise Desktop (SLED) are Novell's branded version of SUSE targeted at corporate environments. SUSE Linux Enterprise product line (SLES and SLED) include some proprietary software as well as technical support. For instance, SuSE Linux Enterprise Server 9 (SLES 9) has fewer packages (around 1,000 packages) than the SuSE Linux Professional (consumer) distribution which has around 3,500 packages. Most of the packages that have been removed are desktop applications which are more suited to consumers than to a business environment. SLES has a guaranteed life cycle of 5 years and only the SLES products are certified by independent hardware and software vendors. + +[edit] See also +Portal:Free software + Free software Portal + + * Novell + * OpenSUSE + * Linux on zSeries + * List of Linux distributions + * Comparison of Linux distributions + * Commercial and community Linux distributions by the same vendor + * Sax2 + +[edit] References + + 1. ^ Proffitt, B. (2003). SuSE Rebrands Ahead of 9.0 Launch. + 2. ^ Shankland, S. (2003). Novell to acquire SuSE Linux. Retrieved December 20, 2003. + 3. ^ Kennedy, D. (2003). Novell's Linux buy opens road to top. Retrieved December 20, 2003. + 4. ^ Ramesh, R. (2004). Novell: SuSE stays the same, for now. Retrieved January 14, 2004. + + * SuSE Roadmap + * Differences between boxed and retail version + +[edit] External links + + * openSUSE + * Novell SUSE Linux Enterprise 10 + * suse at DistroWatch + * Hacking SUSE Linux + * Fultus Technical Documentation eLibrary - SUSE + * 10.1 Review (tuxmachines.org) + * The Unofficial SUSE FAQ + * SUSE Linux Support Forums + * SUSE Linux Community Forums + * SuseBR Brazilian SUSE Linux Community Forums - + * SUSE Wiki + * SUSEroot + * The Linux Master Forums + * 10.0 Review + * SUSE Support Knowledgebase + * Links about SUSE Linux + * SuSE Linux OS Turkiye + * Planet SuSE - Blogs of SUSE employees and SUSE community members + * Linux Desktop Multiplier - Turn one SLED or openSUSE computer into 10 independent, full-client desktops + * Hong Kong & Macau Novell User Group - An unofficial web site provides news, articles and technical tips. diff --git a/tests/zypp/data/Fetcher/remote-site/file-2.txt b/tests/zypp/data/Fetcher/remote-site/file-2.txt new file mode 100644 index 0000000..1272359 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/file-2.txt @@ -0,0 +1,70 @@ +History + +The SUSE Linux distribution was originally a German translation of Slackware Linux. In mid-1992, Softlanding Linux System (SLS) was founded by Peter MacDonald, and was the first comprehensive distribution to contain elements such as X and TCP/IP. The Slackware distribution (maintained by Patrick Volkerding) was initially based largely on SLS. + +S.u.S.E was founded in late 1992 as a UNIX consulting group, which among other things regularly released software packages that included SLS and Slackware, and printed UNIX/Linux manuals. S.u.S.E is an acronym for the German phrase "Software- und System-Entwicklung" ("Software and system development"). There is a rumour that the name is a tribute to the German computer pioneer Konrad Zuse. They released the first CD version of SLS/Slackware in 1994, under the name S.u.S.E Linux 1.0. It later integrated with the Jurix distribution by Florian La Roche, to release the first really unique S.u.S.E Linux 4.2 in 1996. Over time, SuSE Linux incorporated many aspects of Red Hat Linux (e.g., using RPMs and /etc/sysconfig). In a move to more effectively reach its business audience, SuSE introduced the SuSE Linux Enterpriser Server in 2001, and consecutively changed the company name to SUSE Linux in September 2003 as a part of its overall new branding strategy, as announced by SUSE's marketing VP Uwe Schmid.[1] + +The current mascot of SuSE is Geeko, also known as the "SuSE Lizard" + +[edit] Features + +SUSE includes an installation and administration program called YaST2 which handles hard disk partitioning, system setup, RPM package management, online updates, network and firewall configuration, user administration and more in an integrated interface. + +Starting with the 10.1 release, SuSE includes a secondary installation program known as Zen-Updater, which can be used as a secondary means of installing software and replaces Suse-updater providing notification of software updates on the desktop. + +The latest release, openSUSE 10.2 is available as a retail package and as a no-cost open source package. In terms of software, there are major differences between the two packages (see Reference below), including the fact that the retail edition contains a number of proprietary components, such as Macromedia Flash. In addition, the retail package, available for 59.95 USD, includes a printed manual and limited technical support. openSUSE is available to download freely from their website. The retail and eval versions contain one DVD and six CDs, while openSUSE uses five CDs. It is the first SUSE release to be called openSUSE, previous versions were called SUSE Linux. + +Other flavors include dedicated server editions and groupware servers geared towards corporate networks and enterprises, along with a stripped-down business desktop which runs some software designed for Microsoft Windows out of the box by virtue of WINE. + +SUSE Linux Enterprise Server (SLES) and SUSE Linux Enterprise Desktop (SLED) are Novell's branded version of SUSE targeted at corporate environments. SUSE Linux Enterprise product line (SLES and SLED) include some proprietary software as well as technical support. For instance, SuSE Linux Enterprise Server 9 (SLES 9) has fewer packages (around 1,000 packages) than the SuSE Linux Professional (consumer) distribution which has around 3,500 packages. Most of the packages that have been removed are desktop applications which are more suited to consumers than to a business environment. SLES has a guaranteed life cycle of 5 years and only the SLES products are certified by independent hardware and software vendors. + +[edit] Distribution + +In the past SUSE first released the Personal and Professional versions in boxed sets which included extensive printed documentation, then waited a few months before it released versions on its FTP servers. Under Novell and with advent of openSUSE this has been reversed: SUSE Linux 10.0 was available for download well before the retail release of SUSE Linux 10.0. In addition, Novell has discontinued the Personal version, renamed the Professional version to simply "SUSE Linux", and repriced "SUSE Linux" to about the same as the obsolete Personal version. Now Novell has also renamed SUSE Linux to openSUSE with version 10.2 of the distro. + +Starting with version 9.2, an unsupported 1 DVD ISO image of SUSE Professional was made available for download as well as a bootable LiveDVD evaluation. The FTP server continues to operate and has the advantage of "streamlined" installs: Only downloading packages the user feels they need. The ISO has the advantages of an easy install package, the ability to operate even if the user's network card does not work 'out of the box', and less experience needed (i.e., an inexperienced Linux user may not know whether or not to install a certain package, and the ISO offers several preselected sets of packages). The retail box DVD supports x86, and x86_64 installs, but the included CD-ROMs do not include x86_64 support. + +[edit] See also +Portal:Free software + Free software Portal + + * Novell + * OpenSUSE + * Linux on zSeries + * List of Linux distributions + * Comparison of Linux distributions + * Commercial and community Linux distributions by the same vendor + * Sax2 + +[edit] References + + 1. ^ Proffitt, B. (2003). SuSE Rebrands Ahead of 9.0 Launch. + 2. ^ Shankland, S. (2003). Novell to acquire SuSE Linux. Retrieved December 20, 2003. + 3. ^ Kennedy, D. (2003). Novell's Linux buy opens road to top. Retrieved December 20, 2003. + 4. ^ Ramesh, R. (2004). Novell: SuSE stays the same, for now. Retrieved January 14, 2004. + + * SuSE Roadmap + * Differences between boxed and retail version + +[edit] External links + + * openSUSE + * Novell SUSE Linux Enterprise 10 + * suse at DistroWatch + * Hacking SUSE Linux + * Fultus Technical Documentation eLibrary - SUSE + * 10.1 Review (tuxmachines.org) + * The Unofficial SUSE FAQ + * SUSE Linux Support Forums + * SUSE Linux Community Forums + * SuseBR Brazilian SUSE Linux Community Forums - + * SUSE Wiki + * SUSEroot + * The Linux Master Forums + * 10.0 Review + * SUSE Support Knowledgebase + * Links about SUSE Linux + * SuSE Linux OS Turkiye + * Planet SuSE - Blogs of SUSE employees and SUSE community members + * Linux Desktop Multiplier - Turn one SLED or openSUSE computer into 10 independent, full-client desktops + * Hong Kong & Macau Novell User Group - An unofficial web site provides news, articles and technical tips. diff --git a/tests/zypp/data/Fetcher/remote-site/file-3.txt b/tests/zypp/data/Fetcher/remote-site/file-3.txt new file mode 100644 index 0000000..3ce92b3 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/file-3.txt @@ -0,0 +1,105 @@ +History + +The SUSE Linux distribution was originally a German translation of Slackware Linux. In mid-1992, Softlanding Linux System (SLS) was founded by Peter MacDonald, and was the first comprehensive distribution to contain elements such as X and TCP/IP. The Slackware distribution (maintained by Patrick Volkerding) was initially based largely on SLS. + +S.u.S.E was founded in late 1992 as a UNIX consulting group, which among other things regularly released software packages that included SLS and Slackware, and printed UNIX/Linux manuals. S.u.S.E is an acronym for the German phrase "Software- und System-Entwicklung" ("Software and system development"). There is a rumour that the name is a tribute to the German computer pioneer Konrad Zuse. They released the first CD version of SLS/Slackware in 1994, under the name S.u.S.E Linux 1.0. It later integrated with the Jurix distribution by Florian La Roche, to release the first really unique S.u.S.E Linux 4.2 in 1996. Over time, SuSE Linux incorporated many aspects of Red Hat Linux (e.g., using RPMs and /etc/sysconfig). In a move to more effectively reach its business audience, SuSE introduced the SuSE Linux Enterpriser Server in 2001, and consecutively changed the company name to SUSE Linux in September 2003 as a part of its overall new branding strategy, as announced by SUSE's marketing VP Uwe Schmid.[1] + +The current mascot of SuSE is Geeko, also known as the "SuSE Lizard" + +[edit] Features + +SUSE includes an installation and administration program called YaST2 which handles hard disk partitioning, system setup, RPM package management, online updates, network and firewall configuration, user administration and more in an integrated interface. + +Starting with the 10.1 release, SuSE includes a secondary installation program known as Zen-Updater, which can be used as a secondary means of installing software and replaces Suse-updater providing notification of software updates on the desktop. + +[edit] Versions +Major Versions +1.0 - April 1994 +1.0.9 - July 1994 +11/94 - November 1994 +4/95 - April 1995 +8/95 - August 1995 +11/95 - November 1995 +4.2 - May 1996 +4.3 - September 1996 +4.4 - May 1997 +4.4.1 - February 1997 +5.0 - June 1997 +5.1 - November 1997 +5.2 - 23 March 1998 +6.0 - 21 December 1998 +6.1 - 7 April 1999 +6.2 - 12 August 1999 +6.3 - 25 November 1999 +6.4 - 27 March 2000 +7.0 - 27 September 2000 +7.1 - 24 January 2001 +7.2 - 15 June 2001 +7.3 - 13 October 2001 +8.0 - 22 April 2002 +8.1 - 30 September 2002 +8.2 - 7 April 2003 +9.0 - 15 October 2003 +9.1 - 23 April 2004 +9.2 - 25 October 2004 +9.3 - 16 April 2005 +10.0 - 6 October 2005 +10.1 - 11 May 2006 +10.2 - 7 December 2006 + +The latest release, openSUSE 10.2 is available as a retail package and as a no-cost open source package. In terms of software, there are major differences between the two packages (see Reference below), including the fact that the retail edition contains a number of proprietary components, such as Macromedia Flash. In addition, the retail package, available for 59.95 USD, includes a printed manual and limited technical support. openSUSE is available to download freely from their website. The retail and eval versions contain one DVD and six CDs, while openSUSE uses five CDs. It is the first SUSE release to be called openSUSE, previous versions were called SUSE Linux. + +Other flavors include dedicated server editions and groupware servers geared towards corporate networks and enterprises, along with a stripped-down business desktop which runs some software designed for Microsoft Windows out of the box by virtue of WINE. + +SUSE Linux Enterprise Server (SLES) and SUSE Linux Enterprise Desktop (SLED) are Novell's branded version of SUSE targeted at corporate environments. SUSE Linux Enterprise product line (SLES and SLED) include some proprietary software as well as technical support. For instance, SuSE Linux Enterprise Server 9 (SLES 9) has fewer packages (around 1,000 packages) than the SuSE Linux Professional (consumer) distribution which has around 3,500 packages. Most of the packages that have been removed are desktop applications which are more suited to consumers than to a business environment. SLES has a guaranteed life cycle of 5 years and only the SLES products are certified by independent hardware and software vendors. + +[edit] Distribution + +In the past SUSE first released the Personal and Professional versions in boxed sets which included extensive printed documentation, then waited a few months before it released versions on its FTP servers. Under Novell and with advent of openSUSE this has been reversed: SUSE Linux 10.0 was available for download well before the retail release of SUSE Linux 10.0. In addition, Novell has discontinued the Personal version, renamed the Professional version to simply "SUSE Linux", and repriced "SUSE Linux" to about the same as the obsolete Personal version. Now Novell has also renamed SUSE Linux to openSUSE with version 10.2 of the distro. + +Starting with version 9.2, an unsupported 1 DVD ISO image of SUSE Professional was made available for download as well as a bootable LiveDVD evaluation. The FTP server continues to operate and has the advantage of "streamlined" installs: Only downloading packages the user feels they need. The ISO has the advantages of an easy install package, the ability to operate even if the user's network card does not work 'out of the box', and less experience needed (i.e., an inexperienced Linux user may not know whether or not to install a certain package, and the ISO offers several preselected sets of packages). The retail box DVD supports x86, and x86_64 installs, but the included CD-ROMs do not include x86_64 support. + +[edit] See also +Portal:Free software + Free software Portal + + * Novell + * OpenSUSE + * Linux on zSeries + * List of Linux distributions + * Comparison of Linux distributions + * Commercial and community Linux distributions by the same vendor + * Sax2 + +[edit] References + + 1. ^ Proffitt, B. (2003). SuSE Rebrands Ahead of 9.0 Launch. + 2. ^ Shankland, S. (2003). Novell to acquire SuSE Linux. Retrieved December 20, 2003. + 3. ^ Kennedy, D. (2003). Novell's Linux buy opens road to top. Retrieved December 20, 2003. + 4. ^ Ramesh, R. (2004). Novell: SuSE stays the same, for now. Retrieved January 14, 2004. + + * SuSE Roadmap + * Differences between boxed and retail version + +[edit] External links + + * openSUSE + * Novell SUSE Linux Enterprise 10 + * suse at DistroWatch + * Hacking SUSE Linux + * Fultus Technical Documentation eLibrary - SUSE + * 10.1 Review (tuxmachines.org) + * The Unofficial SUSE FAQ + * SUSE Linux Support Forums + * SUSE Linux Community Forums + * SuseBR Brazilian SUSE Linux Community Forums - + * SUSE Wiki + * SUSEroot + * The Linux Master Forums + * 10.0 Review + * SUSE Support Knowledgebase + * Links about SUSE Linux + * SuSE Linux OS Turkiye + * Planet SuSE - Blogs of SUSE employees and SUSE community members + * Linux Desktop Multiplier - Turn one SLED or openSUSE computer into 10 independent, full-client desktops + * Hong Kong & Macau Novell User Group - An unofficial web site provides news, articles and technical tips. diff --git a/tests/zypp/data/Fetcher/remote-site/file-4.txt b/tests/zypp/data/Fetcher/remote-site/file-4.txt new file mode 100644 index 0000000..e031d57 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/file-4.txt @@ -0,0 +1,109 @@ +History + +The SUSE Linux distribution was originally a German translation of Slackware Linux. In mid-1992, Softlanding Linux System (SLS) was founded by Peter MacDonald, and was the first comprehensive distribution to contain elements such as X and TCP/IP. The Slackware distribution (maintained by Patrick Volkerding) was initially based largely on SLS. + +S.u.S.E was founded in late 1992 as a UNIX consulting group, which among other things regularly released software packages that included SLS and Slackware, and printed UNIX/Linux manuals. S.u.S.E is an acronym for the German phrase "Software- und System-Entwicklung" ("Software and system development"). There is a rumour that the name is a tribute to the German computer pioneer Konrad Zuse. They released the first CD version of SLS/Slackware in 1994, under the name S.u.S.E Linux 1.0. It later integrated with the Jurix distribution by Florian La Roche, to release the first really unique S.u.S.E Linux 4.2 in 1996. Over time, SuSE Linux incorporated many aspects of Red Hat Linux (e.g., using RPMs and /etc/sysconfig). In a move to more effectively reach its business audience, SuSE introduced the SuSE Linux Enterpriser Server in 2001, and consecutively changed the company name to SUSE Linux in September 2003 as a part of its overall new branding strategy, as announced by SUSE's marketing VP Uwe Schmid.[1] + +The current mascot of SuSE is Geeko, also known as the "SuSE Lizard" + +[edit] Features + +SUSE includes an installation and administration program called YaST2 which handles hard disk partitioning, system setup, RPM package management, online updates, network and firewall configuration, user administration and more in an integrated interface. + +Starting with the 10.1 release, SuSE includes a secondary installation program known as Zen-Updater, which can be used as a secondary means of installing software and replaces Suse-updater providing notification of software updates on the desktop. + +SUSE has support for resizing NTFS partitions during installation which allows it to co-exist with existing Windows 2000 or XP installations. SUSE has the ability to detect and install drivers for many common winmodems shipped with OEM desktop and laptop systems (such modems are designed to use Windows-specific software to operate). + +Several desktop environments such as KDE and GNOME and window managers like Window Maker and Blackbox are included, with the YaST2 installer allowing the user to choose a preselection of GNOME, KDE, or no desktop at all. SUSE ships with multimedia software such as K3B (CD/DVD burning), Amarok (audio playback), and Kaffeine (movie playback). It contains OpenOffice.org, and software for reading and/or creating other common document formats such as PDF. Due to patent problems, the distribution lacks codecs for proprietary formats like avi, but these can be installed with packages available on the internet. MP3s are handled in the fully capable graphical media studio Amarok with the Helix engine (part of RealNetworks' RealPlayer), when RealPlayer is installed. This is due to an agreement between Novell and RealNetworks to ship RealPlayer with SUSE as a solution to MP3 patent problems.[citation needed] + +[edit] Versions +Major Versions +1.0 - April 1994 +1.0.9 - July 1994 +11/94 - November 1994 +4/95 - April 1995 +8/95 - August 1995 +11/95 - November 1995 +4.2 - May 1996 +4.3 - September 1996 +4.4 - May 1997 +4.4.1 - February 1997 +5.0 - June 1997 +5.1 - November 1997 +5.2 - 23 March 1998 +6.0 - 21 December 1998 +6.1 - 7 April 1999 +6.2 - 12 August 1999 +6.3 - 25 November 1999 +6.4 - 27 March 2000 +7.0 - 27 September 2000 +7.1 - 24 January 2001 +7.2 - 15 June 2001 +7.3 - 13 October 2001 +8.0 - 22 April 2002 +8.1 - 30 September 2002 +8.2 - 7 April 2003 +9.0 - 15 October 2003 +9.1 - 23 April 2004 +9.2 - 25 October 2004 +9.3 - 16 April 2005 +10.0 - 6 October 2005 +10.1 - 11 May 2006 +10.2 - 7 December 2006 + +The latest release, openSUSE 10.2 is available as a retail package and as a no-cost open source package. In terms of software, there are major differences between the two packages (see Reference below), including the fact that the retail edition contains a number of proprietary components, such as Macromedia Flash. In addition, the retail package, available for 59.95 USD, includes a printed manual and limited technical support. openSUSE is available to download freely from their website. The retail and eval versions contain one DVD and six CDs, while openSUSE uses five CDs. It is the first SUSE release to be called openSUSE, previous versions were called SUSE Linux. + +Other flavors include dedicated server editions and groupware servers geared towards corporate networks and enterprises, along with a stripped-down business desktop which runs some software designed for Microsoft Windows out of the box by virtue of WINE. + +SUSE Linux Enterprise Server (SLES) and SUSE Linux Enterprise Desktop (SLED) are Novell's branded version of SUSE targeted at corporate environments. SUSE Linux Enterprise product line (SLES and SLED) include some proprietary software as well as technical support. For instance, SuSE Linux Enterprise Server 9 (SLES 9) has fewer packages (around 1,000 packages) than the SuSE Linux Professional (consumer) distribution which has around 3,500 packages. Most of the packages that have been removed are desktop applications which are more suited to consumers than to a business environment. SLES has a guaranteed life cycle of 5 years and only the SLES products are certified by independent hardware and software vendors. + +[edit] Distribution + +In the past SUSE first released the Personal and Professional versions in boxed sets which included extensive printed documentation, then waited a few months before it released versions on its FTP servers. Under Novell and with advent of openSUSE this has been reversed: SUSE Linux 10.0 was available for download well before the retail release of SUSE Linux 10.0. In addition, Novell has discontinued the Personal version, renamed the Professional version to simply "SUSE Linux", and repriced "SUSE Linux" to about the same as the obsolete Personal version. Now Novell has also renamed SUSE Linux to openSUSE with version 10.2 of the distro. + +Starting with version 9.2, an unsupported 1 DVD ISO image of SUSE Professional was made available for download as well as a bootable LiveDVD evaluation. The FTP server continues to operate and has the advantage of "streamlined" installs: Only downloading packages the user feels they need. The ISO has the advantages of an easy install package, the ability to operate even if the user's network card does not work 'out of the box', and less experience needed (i.e., an inexperienced Linux user may not know whether or not to install a certain package, and the ISO offers several preselected sets of packages). The retail box DVD supports x86, and x86_64 installs, but the included CD-ROMs do not include x86_64 support. + +[edit] See also +Portal:Free software + Free software Portal + + * Novell + * OpenSUSE + * Linux on zSeries + * List of Linux distributions + * Comparison of Linux distributions + * Commercial and community Linux distributions by the same vendor + * Sax2 + +[edit] References + + 1. ^ Proffitt, B. (2003). SuSE Rebrands Ahead of 9.0 Launch. + 2. ^ Shankland, S. (2003). Novell to acquire SuSE Linux. Retrieved December 20, 2003. + 3. ^ Kennedy, D. (2003). Novell's Linux buy opens road to top. Retrieved December 20, 2003. + 4. ^ Ramesh, R. (2004). Novell: SuSE stays the same, for now. Retrieved January 14, 2004. + + * SuSE Roadmap + * Differences between boxed and retail version + +[edit] External links + + * openSUSE + * Novell SUSE Linux Enterprise 10 + * suse at DistroWatch + * Hacking SUSE Linux + * Fultus Technical Documentation eLibrary - SUSE + * 10.1 Review (tuxmachines.org) + * The Unofficial SUSE FAQ + * SUSE Linux Support Forums + * SUSE Linux Community Forums + * SuseBR Brazilian SUSE Linux Community Forums - + * SUSE Wiki + * SUSEroot + * The Linux Master Forums + * 10.0 Review + * SUSE Support Knowledgebase + * Links about SUSE Linux + * SuSE Linux OS Turkiye + * Planet SuSE - Blogs of SUSE employees and SUSE community members + * Linux Desktop Multiplier - Turn one SLED or openSUSE computer into 10 independent, full-client desktops + * Hong Kong & Macau Novell User Group - An unofficial web site provides news, articles and technical tips. diff --git a/tests/zypp/data/Fetcher/remote-site/file-current.txt b/tests/zypp/data/Fetcher/remote-site/file-current.txt new file mode 100644 index 0000000..0358edd --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/file-current.txt @@ -0,0 +1,113 @@ +History + +The SUSE Linux distribution was originally a German translation of Slackware Linux. In mid-1992, Softlanding Linux System (SLS) was founded by Peter MacDonald, and was the first comprehensive distribution to contain elements such as X and TCP/IP. The Slackware distribution (maintained by Patrick Volkerding) was initially based largely on SLS. + +S.u.S.E was founded in late 1992 as a UNIX consulting group, which among other things regularly released software packages that included SLS and Slackware, and printed UNIX/Linux manuals. S.u.S.E is an acronym for the German phrase "Software- und System-Entwicklung" ("Software and system development"). There is a rumour that the name is a tribute to the German computer pioneer Konrad Zuse. They released the first CD version of SLS/Slackware in 1994, under the name S.u.S.E Linux 1.0. It later integrated with the Jurix distribution by Florian La Roche, to release the first really unique S.u.S.E Linux 4.2 in 1996. Over time, SuSE Linux incorporated many aspects of Red Hat Linux (e.g., using RPMs and /etc/sysconfig). In a move to more effectively reach its business audience, SuSE introduced the SuSE Linux Enterpriser Server in 2001, and consecutively changed the company name to SUSE Linux in September 2003 as a part of its overall new branding strategy, as announced by SUSE's marketing VP Uwe Schmid.[1] + +On November 4, 2003, Novell announced it would acquire SuSE.[2] The acquisition was finalized in January 2004.[3] J. Philips (Novell's corporate technology strategist for the Asia Pacific region) stated that Novell would not "in the medium term" alter the way in which SUSE continues to be developed.[4] At Novell's annual BrainShare gathering in 2004, all computers ran SUSE Linux for the first time. At this gathering it was also announced that the proprietary SUSE administration program YaST2 would be released into the public under the GPL license. + +On August 4, 2005, Novell spokesman and director of public relations Bruce Lowry announced that the development of the SUSE Professional series will become more open and within the community project openSUSE try to reach a wider audience of users and developers. The software, by definition of open source, already had their coding "open," but now the development process will be more "open" than before, allowing developers and users to test the product and help develop it. Previously all development work was done in-house by SUSE, and version 10.0 was the first version that had public beta testing. As part of the change, YaST Online Update server access will be complimentary for SUSE Linux users, and along the lines of most open source distributions, there will both be a free download available on the web and a boxed edition. This change in philosophy led to the release of the SUSE Linux 10.0 release on October 6, 2005 in "OSS" (completely open source), "eval" (has both open source and proprietary applications and is actually a fully featured version) and retail boxed-set editions. + +The current mascot of SuSE is Geeko, also known as the "SuSE Lizard" + +[edit] Features + +SUSE includes an installation and administration program called YaST2 which handles hard disk partitioning, system setup, RPM package management, online updates, network and firewall configuration, user administration and more in an integrated interface. + +Starting with the 10.1 release, SuSE includes a secondary installation program known as Zen-Updater, which can be used as a secondary means of installing software and replaces Suse-updater providing notification of software updates on the desktop. + +SUSE has support for resizing NTFS partitions during installation which allows it to co-exist with existing Windows 2000 or XP installations. SUSE has the ability to detect and install drivers for many common winmodems shipped with OEM desktop and laptop systems (such modems are designed to use Windows-specific software to operate). + +Several desktop environments such as KDE and GNOME and window managers like Window Maker and Blackbox are included, with the YaST2 installer allowing the user to choose a preselection of GNOME, KDE, or no desktop at all. SUSE ships with multimedia software such as K3B (CD/DVD burning), Amarok (audio playback), and Kaffeine (movie playback). It contains OpenOffice.org, and software for reading and/or creating other common document formats such as PDF. Due to patent problems, the distribution lacks codecs for proprietary formats like avi, but these can be installed with packages available on the internet. MP3s are handled in the fully capable graphical media studio Amarok with the Helix engine (part of RealNetworks' RealPlayer), when RealPlayer is installed. This is due to an agreement between Novell and RealNetworks to ship RealPlayer with SUSE as a solution to MP3 patent problems.[citation needed] + +[edit] Versions +Major Versions +1.0 - April 1994 +1.0.9 - July 1994 +11/94 - November 1994 +4/95 - April 1995 +8/95 - August 1995 +11/95 - November 1995 +4.2 - May 1996 +4.3 - September 1996 +4.4 - May 1997 +4.4.1 - February 1997 +5.0 - June 1997 +5.1 - November 1997 +5.2 - 23 March 1998 +6.0 - 21 December 1998 +6.1 - 7 April 1999 +6.2 - 12 August 1999 +6.3 - 25 November 1999 +6.4 - 27 March 2000 +7.0 - 27 September 2000 +7.1 - 24 January 2001 +7.2 - 15 June 2001 +7.3 - 13 October 2001 +8.0 - 22 April 2002 +8.1 - 30 September 2002 +8.2 - 7 April 2003 +9.0 - 15 October 2003 +9.1 - 23 April 2004 +9.2 - 25 October 2004 +9.3 - 16 April 2005 +10.0 - 6 October 2005 +10.1 - 11 May 2006 +10.2 - 7 December 2006 + +The latest release, openSUSE 10.2 is available as a retail package and as a no-cost open source package. In terms of software, there are major differences between the two packages (see Reference below), including the fact that the retail edition contains a number of proprietary components, such as Macromedia Flash. In addition, the retail package, available for 59.95 USD, includes a printed manual and limited technical support. openSUSE is available to download freely from their website. The retail and eval versions contain one DVD and six CDs, while openSUSE uses five CDs. It is the first SUSE release to be called openSUSE, previous versions were called SUSE Linux. + +Other flavors include dedicated server editions and groupware servers geared towards corporate networks and enterprises, along with a stripped-down business desktop which runs some software designed for Microsoft Windows out of the box by virtue of WINE. + +SUSE Linux Enterprise Server (SLES) and SUSE Linux Enterprise Desktop (SLED) are Novell's branded version of SUSE targeted at corporate environments. SUSE Linux Enterprise product line (SLES and SLED) include some proprietary software as well as technical support. For instance, SuSE Linux Enterprise Server 9 (SLES 9) has fewer packages (around 1,000 packages) than the SuSE Linux Professional (consumer) distribution which has around 3,500 packages. Most of the packages that have been removed are desktop applications which are more suited to consumers than to a business environment. SLES has a guaranteed life cycle of 5 years and only the SLES products are certified by independent hardware and software vendors. + +[edit] Distribution + +In the past SUSE first released the Personal and Professional versions in boxed sets which included extensive printed documentation, then waited a few months before it released versions on its FTP servers. Under Novell and with advent of openSUSE this has been reversed: SUSE Linux 10.0 was available for download well before the retail release of SUSE Linux 10.0. In addition, Novell has discontinued the Personal version, renamed the Professional version to simply "SUSE Linux", and repriced "SUSE Linux" to about the same as the obsolete Personal version. Now Novell has also renamed SUSE Linux to openSUSE with version 10.2 of the distro. + +Starting with version 9.2, an unsupported 1 DVD ISO image of SUSE Professional was made available for download as well as a bootable LiveDVD evaluation. The FTP server continues to operate and has the advantage of "streamlined" installs: Only downloading packages the user feels they need. The ISO has the advantages of an easy install package, the ability to operate even if the user's network card does not work 'out of the box', and less experience needed (i.e., an inexperienced Linux user may not know whether or not to install a certain package, and the ISO offers several preselected sets of packages). The retail box DVD supports x86, and x86_64 installs, but the included CD-ROMs do not include x86_64 support. + +[edit] See also +Portal:Free software + Free software Portal + + * Novell + * OpenSUSE + * Linux on zSeries + * List of Linux distributions + * Comparison of Linux distributions + * Commercial and community Linux distributions by the same vendor + * Sax2 + +[edit] References + + 1. ^ Proffitt, B. (2003). SuSE Rebrands Ahead of 9.0 Launch. + 2. ^ Shankland, S. (2003). Novell to acquire SuSE Linux. Retrieved December 20, 2003. + 3. ^ Kennedy, D. (2003). Novell's Linux buy opens road to top. Retrieved December 20, 2003. + 4. ^ Ramesh, R. (2004). Novell: SuSE stays the same, for now. Retrieved January 14, 2004. + + * SuSE Roadmap + * Differences between boxed and retail version + +[edit] External links + + * openSUSE + * Novell SUSE Linux Enterprise 10 + * suse at DistroWatch + * Hacking SUSE Linux + * Fultus Technical Documentation eLibrary - SUSE + * 10.1 Review (tuxmachines.org) + * The Unofficial SUSE FAQ + * SUSE Linux Support Forums + * SUSE Linux Community Forums + * SuseBR Brazilian SUSE Linux Community Forums - + * SUSE Wiki + * SUSEroot + * The Linux Master Forums + * 10.0 Review + * SUSE Support Knowledgebase + * Links about SUSE Linux + * SuSE Linux OS Turkiye + * Planet SuSE - Blogs of SUSE employees and SUSE community members + * Linux Desktop Multiplier - Turn one SLED or openSUSE computer into 10 independent, full-client desktops + * Hong Kong & Macau Novell User Group - An unofficial web site provides news, articles and technical tips. diff --git a/tests/zypp/data/Fetcher/remote-site/file-current.txt.asc b/tests/zypp/data/Fetcher/remote-site/file-current.txt.asc new file mode 100644 index 0000000..1550f57 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/file-current.txt.asc @@ -0,0 +1,98 @@ +-----BEGIN PGP MESSAGE----- +Version: GnuPG v1.4.5 (GNU/Linux) + +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 +=Tb07 +-----END PGP MESSAGE----- diff --git a/tests/zypp/data/Fetcher/remote-site/file-current.txt.key b/tests/zypp/data/Fetcher/remote-site/file-current.txt.key new file mode 100644 index 0000000..3b2cffa --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/file-current.txt.key @@ -0,0 +1,32 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.5 (GNU/Linux) + +mQGiBDslQEkRBADgDXtg08dhjHQpv9SisvzvROcsr6QRFOLWf95GWh7c6SI7Pj5m +TClUaJXBRjLuvOR0L7w8l5nVJ/4kzSjle1ad04eDzP3sB4rNK18l7GAwc0ijV0mp +/Kl9F4iibco3cCIMsjysWgUmlk+dYYWQubQA/EgTs7kFQo9QRxzojqnSywCg/5CZ +5TJ19gNS8knyu819v6ZSkV8D/01Fem2WZejqsmNBNiY1JoWxnTofi3AjMv6j/+Nj +yBuU9ozIhUicx4y+Ro05eKUZ+VAIecVbVhEqH9VUriX48TDrNxu4OGJh62q58s0u +/tqIX5OrvrpmdOC1UTdcc2CM88vssTt8oxauZeM7YAkY9rApXUniyfnJ3fdd3FlC +IbvaA/9XXrlBjG/3HQSPfknbqLlCvEclelRmm6LAX8fuf/JFgj0ctRMAJKB6HOE7 +/pvl3yRMMITwmd9lB/s2u+fqcwV1bDqfnyV8h3KFpTCGM1qKT+EaaT/8JhFJifYD +jBEnUe9mYG7dUlt+Ff9Fj6ZRJQs9vszzQcsJDzNpys+j/KJutbQtRHVuY2FuIE1h +Yy1WaWNhciBHYXLtbiA8ZHVuY2FuQG1hYy12aWNhci5jb20+iGAEEBECABgFAjsl +QEkICwMJCAcCAQoCGQEFGwMAAAAAEgkQwSqJHVebm9QHZUdQRwABAeHRAJsGKaYQ +p44NzYEjS9dsEAT4sYKzDgCgw4c7kDarZL/qKqFvHbvsPS6fRteIRgQQEQIABgUC +OyVG9QAKCRDNHrapZn5C0WO7AKCBUULk55fR/yavkYgUhL9AX0rShgCfQ0jjVarV +QNc/cj5ilTdKqSkeJ8q5Ag0EOyVAShAIAPZCV7cIfwgXcqK61qlC8wXo+VMROU+2 +8W65Szgg2gGnVqMU6Y9AVfPQB8bLQ6mUrfdMZIZJ+AyDvWXpF9Sh01D49Vlf3HZS +Tz09jdvOmeFXklnN/biudE/F/Ha8g8VHMGHOfMlm/xX5u/2RXscBqtNbno2gpXI6 +1Brwv0YAWCvl9Ij9WE5J280gtJ3kkQc2azNsOA1FHQ98iLMcfFstjvbzySPAQ/Cl +WxiNjrtVjLhdONM0/XwXV0OjHRhs3jMhLLUq/zzhsSlAGBGNfISnCnLWhsQDGcgH +KXrKlQzZlp+r0ApQmwJG0wg9ZqRdQZ+cfL2JSyIZJrqrol7DVekyCzsAAgIH/3NY +WNGw9Wa8B6Ow6NyS2WSBrx33ZxInDgObZe72mO/GSyxxZqxPiqTFTpajTD+HWKQu +vSfMGZdD1kJZTrNEI/MNLwVBhrgxLX2qrmq1aJgWa5aRcv05wHuIUrw2g220oZ09 +gUhXuF3U/oDUCAX36d16CaPCMJV1TRUoc2L1WoLP2BjzIkAgKrqUGvIFNsvtXe3c +NU5dSQzF0spExuCz1Wy67/T4fzLSJpiWadl/eN67cp83ega5fyYy9NpISmeiFcV2 +5UJqbQM0ktilZzDhx+evmYd6PHP7i8OqgC1oHajEohfo9kmyO/AXJ/v08svnSJVO +0G/9qQeuFp3JVeBHsN6IVAQYEQIADAUCOyVASgUbDAAAAAASCRDBKokdV5ub1Adl +R1BHAAEBRRIAnjhaS/m/eYLw2g79GuLD/1x12Xj9AKCW04cRwUxoIirwdJxLNRT2 +GoLAdg== +=BjTA +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/Fetcher/remote-site/images-file-unsigned/content b/tests/zypp/data/Fetcher/remote-site/images-file-unsigned/content new file mode 100644 index 0000000..a85d664 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/images-file-unsigned/content @@ -0,0 +1,143 @@ +CONTENTSTYLE 11 +BASEARCHS i586 +DATADIR suse +DESCRDIR suse/setup/descr +DISTRIBUTION openSUSE +FLAVOR dvd +LABEL openSUSE 11.1 +LINGUAS cs da de en en_GB en_US es fi fr hu it ja nb nl pl pt pt_BR ru sv zh zh_CN zh_TW +NAME openSUSE +REFERENCES openSUSE-release = 11.1 +RELNOTESURL http://www.suse.com/relnotes/i386/openSUSE/11.0.42/release-notes-openSUSE.rpm +SUMMARY openSUSE +VERSION 11.1 +META SHA1 dd627cf38a5dee28421690d2ec6abea7af274a50 dvd-11.1-58.1.i586.pat.gz +META SHA1 fa49e3205fea8f95d395710a4ba79f55b4626ccd non_oss-11.1-58.1.i586.pat.gz +META SHA1 f6c6ef681aa5fc4c5e9532f04420d54fbec033a8 packages.cs.gz +META SHA1 cc5438a74d1b39f34bc31fbc2399ae6a95f43bc4 packages.de.gz +META SHA1 90dfa1e81f5515769f5b16fcf31c1ab63c55ff87 packages.DU.gz +META SHA1 b1c6b77703357297ecdd8d74b89a099ebbfe2fe6 packages.en.gz +META SHA1 b137fc7749531183b5250ec907d4b9adf4624288 packages.es.gz +META SHA1 3e55d6d5c21a6a1457ea6fef09c999b28883ade4 packages.fr.gz +META SHA1 b5b6092d57a701d4052ad2bb047636c68ac31d8b packages.gz +META SHA1 a893937892aeff71da1c38aa06f3cce5ba02de1c packages.hu.gz +META SHA1 f6c6ef681aa5fc4c5e9532f04420d54fbec033a8 packages.sk.gz +META SHA1 1d66972a977913541c7cb7130d61ec0e751148ba patterns +HASH SHA1 4ae30edd0588114b642bbb08fbd3fb71d7af257d license.tar.gz +HASH SHA1 67d82aa5cd4f08cf77cc70fe9ca1834a4b6212cc control.xml +HASH SHA1 e727c621ded4324cc61e94c615dbd423436f63e4 media.1/info.txt +HASH SHA1 7442eb13ca3c184fe0d47060dbc56fd45cfcb720 boot/i386/bind +HASH SHA1 99920bc0c322d0d0b63ac361d2f9c8f6bc9e3524 boot/i386/branding +HASH SHA1 ca2f0bce909d73d1bfaa7cdeb98595f17e4524aa boot/i386/common +HASH SHA1 d107fa19616c3eae9d49fe52e54971e5b9c160fa boot/i386/config +HASH SHA1 4b7d8525b1d3588562bea71b26cdb5e48e29ff64 boot/i386/cracklib-dict-full.rpm +HASH SHA1 1a8151b2bf88cf618be74eee60d65063386469e0 boot/i386/fonts-arabic.rpm +HASH SHA1 79aec7c93b730c2355aebd085eddf4195a9c1d36 boot/i386/fonts-thai.rpm +HASH SHA1 52e1040f8e0fae373d7426447b1f9d05d25b90f6 boot/i386/gdb +HASH SHA1 a1ba35bcecde55eb36be2e89b7210998b846be9d boot/i386/indic-fonts.rpm +HASH SHA1 6394ec4eb1883520de23bd2ac043490da6ed8fde boot/i386/initrd-xen +HASH SHA1 6394ec4eb1883520de23bd2ac043490da6ed8fde boot/i386/initrd-xenpae +HASH SHA1 6cebf392eaf1b17b53f3e5e88a6b6c6d8c2b76bb boot/i386/KhmerOS-fonts.rpm +HASH SHA1 e9c779539f1b3f56a96337f262b2bc548e6b223e boot/i386/LIESMICH +HASH SHA1 abdf17a0246be709efbcc7c0e0a68f8ad797a754 boot/i386/LIESMICH.DOS +HASH SHA1 f51e15897e5f77c7a7b4d1600dc53be6f117d9ec boot/i386/lklug.rpm +HASH SHA1 c4dca65aa97554bc45885b22ef4af24ad5177c75 boot/i386/mkbootdisk +HASH SHA1 99920bc0c322d0d0b63ac361d2f9c8f6bc9e3524 boot/i386/openSUSE +HASH SHA1 ae44557c57285f0866be41334fdaa20312ccdeab boot/i386/README +HASH SHA1 4a71ee6114eccfb88582dc5422020cbc5a2639dd boot/i386/README.DOS +HASH SHA1 e12efd095a7fb990d0c4be1e04999e72de84dd6a boot/i386/rescue +HASH SHA1 73e50e6321e6938471c4fc0521e0b2dce54f0346 boot/i386/root +HASH SHA1 9b4cced8b700c6737ab02af8f1521945c925c8f9 boot/i386/rpmlist +HASH SHA1 2181540518e50f88e7e35c619460e746934eacd4 boot/i386/sax2 +HASH SHA1 78d3ee95682c1150aa8a95132ba1c5d0d88c23bd boot/i386/ttf-arphic-uming.rpm +HASH SHA1 55a2d437b32d6c192c60e016756725f7a2e717e9 boot/i386/unfonts.rpm +HASH SHA1 7c6fbdc97c11e5e03098f19c196d85cd63e5ce85 boot/i386/vmlinuz-xen +HASH SHA1 7c6fbdc97c11e5e03098f19c196d85cd63e5ce85 boot/i386/vmlinuz-xenpae +HASH SHA1 67d109ba80c3f396710774ff03ace955a2184dc6 boot/i386/yast2-trans-af.rpm +HASH SHA1 3d835ea74b409914cf40ba48669a11590cffa902 boot/i386/yast2-trans-ar.rpm +HASH SHA1 5654cabb329f0b1251d5743624fdf599b92d71e5 boot/i386/yast2-trans-bg.rpm +HASH SHA1 1015f485542ae7c903ec9d1a9c7983d4701e2824 boot/i386/yast2-trans-bn.rpm +HASH SHA1 454e0f1b79d2076a9ba03b23c34da3cbc3e58e25 boot/i386/yast2-trans-bs.rpm +HASH SHA1 76bbfdb77952db51e9b21dc90ab167f2a46f4580 boot/i386/yast2-trans-ca.rpm +HASH SHA1 59f26af0b058b47f2d821f6fa8102d58af8d0377 boot/i386/yast2-trans-cs.rpm +HASH SHA1 db43e4829de2a26b4bb09aa1e93069af2b230377 boot/i386/yast2-trans-cy.rpm +HASH SHA1 1aee13cb0b0a1f4e7b1bbb49e809fd13919ba7e9 boot/i386/yast2-trans-da.rpm +HASH SHA1 36335f1ff2738071be00be65a64f7d41b7db1c33 boot/i386/yast2-trans-de.rpm +HASH SHA1 5297e40871de03217cfee404cb88e909422ceae8 boot/i386/yast2-trans-el.rpm +HASH SHA1 bc61efbd85302ed96ae51550a163cd0fc9ad59a3 boot/i386/yast2-trans-en_GB.rpm +HASH SHA1 a237b73e48777fcdd42505ec1e007484d9f398da boot/i386/yast2-trans-en_US.rpm +HASH SHA1 f2e0dba8e86a723ab72d7f7490665f8e631f63a1 boot/i386/yast2-trans-es.rpm +HASH SHA1 ca9bd8bf05434d42b6a7c2c7549e2ce0170c6be8 boot/i386/yast2-trans-et.rpm +HASH SHA1 57e5cd63079ac258734f28df5385e5288cd59db0 boot/i386/yast2-trans-fa.rpm +HASH SHA1 2983eb7ba93882e52434f396b49cd6e98d7b7399 boot/i386/yast2-trans-fi.rpm +HASH SHA1 0dfc3b38294524871f527d919ce31d6921cf77c0 boot/i386/yast2-trans-fr.rpm +HASH SHA1 2051d343881b288c5d22aec792e9d13ec192dfd1 boot/i386/yast2-trans-gl.rpm +HASH SHA1 49736a9798a371c3edf02f350ebe4db1e6fff011 boot/i386/yast2-trans-gu.rpm +HASH SHA1 d9737ea270e5166cbc409466c1d2a6f16fcc9f06 boot/i386/yast2-trans-hi.rpm +HASH SHA1 1e222655cfabbf0212e629ed1fccf304847ac732 boot/i386/yast2-trans-hr.rpm +HASH SHA1 1b6e646f9f8abc7c33ef2dd830b72c7a2f775620 boot/i386/yast2-trans-hu.rpm +HASH SHA1 723a18301396eccf7c0620f1f8f016719eaf7543 boot/i386/yast2-trans-id.rpm +HASH SHA1 70c272dbe7bfe963e44e5331edd5f440450bc827 boot/i386/yast2-trans-it.rpm +HASH SHA1 f17bc3588c7d2878821600d42fe174156971f87e boot/i386/yast2-trans-ja.rpm +HASH SHA1 d46ea44b7d98ade64658d1cf388013093d1c0d39 boot/i386/yast2-trans-jv.rpm +HASH SHA1 e4e684ebb7f93ac20461062544b49fe18c88627d boot/i386/yast2-trans-ka.rpm +HASH SHA1 123eb83403b88845cb5efd9046ef39351c1b68c3 boot/i386/yast2-trans-km.rpm +HASH SHA1 85c28913c4432f43fa29d8791d97b3e10456a42a boot/i386/yast2-trans-ko.rpm +HASH SHA1 6692fca0c1acb85b398bcbb9150d0826ea38f2c8 boot/i386/yast2-trans-lo.rpm +HASH SHA1 6247198d1348d31192dc158969ce8ae9252d6f0b boot/i386/yast2-trans-lt.rpm +HASH SHA1 a630f16e50a6227f814751931bb1a1ec15981c29 boot/i386/yast2-trans-mk.rpm +HASH SHA1 4f0bffd5cbeb7d37a7d78f1996cade7ae2ad2420 boot/i386/yast2-trans-mr.rpm +HASH SHA1 bbc950f9fec446e9a5a5876c532cd56e060c5eb4 boot/i386/yast2-trans-nb.rpm +HASH SHA1 edae4d58bd99064bbddd62278875b0387a2d495d boot/i386/yast2-trans-nl.rpm +HASH SHA1 85f1dc1eef8862066050c09eef023705a5d61039 boot/i386/yast2-trans-pa.rpm +HASH SHA1 e1eb02ebedff18a01facc150e00d05385affaa17 boot/i386/yast2-trans-pl.rpm +HASH SHA1 c3d31be5bf8af62c537e1a70db9afc98842b3f82 boot/i386/yast2-trans-pt_BR.rpm +HASH SHA1 b2bcd427139f2e13684a592ff186c3076a5b22d8 boot/i386/yast2-trans-pt.rpm +HASH SHA1 7fdb3299ca8230ec363d3ee8eee24915c931790c boot/i386/yast2-trans-ro.rpm +HASH SHA1 8b9bdb13f3b7c73e8c64303e8614e44bf640cc9f boot/i386/yast2-trans-ru.rpm +HASH SHA1 55876ae86c10a3504bbbcd71e49564f4c0b47149 boot/i386/yast2-trans-si.rpm +HASH SHA1 ee8ce4bc8a06b5094f8d51c79b32806531203d62 boot/i386/yast2-trans-sk.rpm +HASH SHA1 04130a176a24ce3adb663a2bb694fd484f2a7776 boot/i386/yast2-trans-sl.rpm +HASH SHA1 d3408d472a956ffbd1fb49354057da5c0b77879f boot/i386/yast2-trans-sr.rpm +HASH SHA1 fda2c586ff8a17d402108f007c2c6214bcaeca3f boot/i386/yast2-trans-sv.rpm +HASH SHA1 04021fd6654b2e7b6cbff65c094efa8c35424215 boot/i386/yast2-trans-ta.rpm +HASH SHA1 6aaae1e49e3188b5e73bedb3c3cd044c4108cca2 boot/i386/yast2-trans-th.rpm +HASH SHA1 6bb5903b7bc64185352c616099c344f8738bb768 boot/i386/yast2-trans-tr.rpm +HASH SHA1 9f631f117433db5e44a6bbed7c8a50cbbe5e8ac0 boot/i386/yast2-trans-uk.rpm +HASH SHA1 3ba5a8f4f3dc3f454e13223c2ecef9937824a611 boot/i386/yast2-trans-vi.rpm +HASH SHA1 bc2775d3a4a0a3ca80e5a5caa51a6612e7158d32 boot/i386/yast2-trans-wa.rpm +HASH SHA1 a3511637ca9bd4cbf5dc9eca58f8ccf5df49603c boot/i386/yast2-trans-xh.rpm +HASH SHA1 ba8875e4c0febe1d26d27c0c948e93128f14476a boot/i386/yast2-trans-zh_CN.rpm +HASH SHA1 d39b329ce32a0d59bebecd0d87ecfd59cb26e297 boot/i386/yast2-trans-zh_TW.rpm +HASH SHA1 0c6f45e6b01d531ac7e821ae9e479416149e92eb boot/i386/yast2-trans-zu.rpm +HASH SHA1 2325eb886cf06b58ca1892578383b5fcc5b11866 boot/i386/loader/linux +HASH SHA1 586ec9beb26fb337283f3b49149d843a3fb7c821 boot/i386/loader/initrd +HASH SHA1 d6b4db657272efe902f8ce92b53082fda4d5f1ca boot/i386/loader/08000600.spl +HASH SHA1 22d4aeede74fdf44b3c4a2524319fe9cf418d4c6 boot/i386/loader/10240600.spl +HASH SHA1 93e297fb9ffa23d6a167c50c318bbb46b0705e45 boot/i386/loader/10240768.spl +HASH SHA1 8c135621ac91216c3388f9ea9c02127b2f6375a0 boot/i386/loader/12800800.spl +HASH SHA1 54dd2bc17c9f73ad9d6a85489f99f518849cb84d boot/i386/loader/12801024.spl +HASH SHA1 ef0f517a3f3a3240349b9bdd01e794267372c4ab boot/i386/loader/14001050.spl +HASH SHA1 2abbc5b4c7c3dc8134ae1207f9d9e95a640046ef boot/i386/loader/16001200.spl +HASH SHA1 e37862355648f6330b6831c69c989dec02b80ab0 boot/i386/loader/16801050.spl +HASH SHA1 082a7887d2f43d049fdb0fc92c5051f1a5b7e663 boot/i386/loader/19201200.spl +HASH SHA1 ed5f4a87074367bcf8396da7a9b9b3d1be6dfcb2 images/base-i386.tar.lzma +HASH SHA1 9d055cacc983226171cdd3a3fe1acd6bb6fa044e images/base-meta-i386.tar.lzma +HASH SHA1 361e07c44526cd43a2d477b7b3448e49e674f0a8 images/common-base-i386.tar.lzma +HASH SHA1 6854608038e4d3b11fcc950e28ca49e4582fd2a4 images/common-desktop-i386.tar.lzma +HASH SHA1 5f6a43158c017e188309c094cdaf24c346de3dfb images/common-xorg-i386.tar.lzma +HASH SHA1 ce6620b820e494c042398b9fd7ed108578008168 images/details-i386.xml +HASH SHA1 22c466bf9af3003ee95fed6f7fb93b4c8c0cd993 images/gnome-i386.tar.lzma +HASH SHA1 49374551f38fe919cf4545d5af0fea7d45361738 images/gnome-meta-i386.tar.lzma +HASH SHA1 d1e9a38629e353d1f0136ded670cf28213d47e6f images/images.xml +HASH SHA1 0df7debf780a0e01b18004d18ef6ab21410b9480 images/kde-i386.tar.lzma +HASH SHA1 c418a15669de278e523893f030c209c479f490e6 images/kde-meta-i386.tar.lzma +HASH SHA1 6c4238796684f770a0b4ecd1ea4469e5a7a49b0d images/x11-i386.tar.lzma +HASH SHA1 cc50a8bc9d560c8d522660feed5feb019f9b889e images/x11-meta-i386.tar.lzma +KEY SHA1 17162a96933229a9771ee10c0976bdc047a2f53d gpg-pubkey-0dfb3188-41ed929b.asc +KEY SHA1 f6accbb18d705bfc104c893cf7dfca1247a33f3c gpg-pubkey-307e3d54-481f30aa.asc +KEY SHA1 47f6492d127ae9f6aac353a2dd23752fc0ed4f8d gpg-pubkey-3d25d3d9-36e12d04.asc +KEY SHA1 2288e5849740566e4fb65b7c9dc0c7e4f43b1039 gpg-pubkey-56b4177a-47965b33.asc +KEY SHA1 89d4bcd20a281553fd1d4ec1708603ebf88f1a59 gpg-pubkey-7e2e3b05-4816488f.asc +KEY SHA1 06ff5171362496c0db84beeccd29967f580350b2 gpg-pubkey-9c800aca-481f343a.asc +KEY SHA1 04544096c5c3b0ed7b01a83d79e048307c2af919 gpg-pubkey-a1912208-446a0899.asc diff --git a/tests/zypp/data/Fetcher/remote-site/images-file-unsigned/images/images.xml b/tests/zypp/data/Fetcher/remote-site/images-file-unsigned/images/images.xml new file mode 100644 index 0000000..7b252e8 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/images-file-unsigned/images/images.xml @@ -0,0 +1,345 @@ + + + + + + base,enhanced_base,games,imaging,kde4,kde4_basis,multimedia,sw_management,x11,xgl + i386 + kde-meta-i386.tar.lzma + + + KDE [base] + tar + common-base-i386.tar.lzma + + + KDE [xorg] + tar + common-xorg-i386.tar.lzma + + + KDE [desktop] + tar + common-desktop-i386.tar.lzma + + + KDE + tar + kde-i386.tar.lzma + + + KDE [meta] + tar + kde-meta-i386.tar.lzma + + + + + base,enhanced_base,fonts,games,gnome,gnome_basis,imaging,multimedia,sw_management,x11,xgl + i386 + gnome-meta-i386.tar.lzma + + + GNOME [1] + tar + common-base-i386.tar.lzma + + + GNOME [2] + tar + common-xorg-i386.tar.lzma + + + GNOME [4] + tar + common-desktop-i386.tar.lzma + + + GNOME + tar + gnome-i386.tar.lzma + + + GNOME [meta] + tar + gnome-meta-i386.tar.lzma + + + + + base,enhanced_base,sw_management + i386 + base-meta-i386.tar.lzma + + + BASE [1] + tar + base-meta-i386.tar.lzma + + + BASE [2] + tar + base-i386.tar.lzma + + + BASE [3] + tar + common-base-i386.tar.lzma + + + + + base,enhanced_base,fonts,sw_management,x11 + i386 + x11-meta-i386.tar.lzma + + + X11 [1] + tar + x11-meta-i386.tar.lzma + + + X11 [2] + tar + x11-i386.tar.lzma + + + X11 [3] + tar + common-xorg-i386.tar.lzma + + + X11 [4] + tar + common-base-i386.tar.lzma + + + + + base,enhanced_base,games,imaging,kde4,kde4_basis,multimedia,sw_management,x11,xgl + x86_64 + kde-meta-x86_64.tar.lzma + + + KDE [base] + tar + common-base-x86_64.tar.lzma + + + KDE [xorg] + tar + common-xorg-x86_64.tar.lzma + + + KDE [desktop] + tar + common-desktop-x86_64.tar.lzma + + + KDE + tar + kde-x86_64.tar.lzma + + + KDE [meta] + tar + kde-meta-x86_64.tar.lzma + + + + + base,enhanced_base,fonts,games,gnome,gnome_basis,imaging,multimedia,sw_management,x11,xgl + x86_64 + gnome-meta-x86_64.tar.lzma + + + GNOME [1] + tar + common-base-x86_64.tar.lzma + + + GNOME [2] + tar + common-xorg-x86_64.tar.lzma + + + GNOME [4] + tar + common-desktop-x86_64.tar.lzma + + + GNOME + tar + gnome-x86_64.tar.lzma + + + GNOME [meta] + tar + gnome-meta-x86_64.tar.lzma + + + + + base,enhanced_base,sw_management + x86_64 + base-meta-x86_64.tar.lzma + + + BASE [1] + tar + base-meta-x86_64.tar.lzma + + + BASE [2] + tar + base-x86_64.tar.lzma + + + BASE [3] + tar + common-base-x86_64.tar.lzma + + + + + base,enhanced_base,fonts,sw_management,x11 + x86_64 + x11-meta-x86_64.tar.lzma + + + X11 [1] + tar + x11-meta-x86_64.tar.lzma + + + X11 [2] + tar + x11-x86_64.tar.lzma + + + X11 [3] + tar + common-xorg-x86_64.tar.lzma + + + X11 [4] + tar + common-base-x86_64.tar.lzma + + + + + base,enhanced_base,games,imaging,kde4,kde4_basis,multimedia,sw_management,x11,xgl + ppc + kde-meta-ppc.tar.lzma + + + KDE [base] + tar + common-base-ppc.tar.lzma + + + KDE [xorg] + tar + common-xorg-ppc.tar.lzma + + + KDE [desktop] + tar + common-desktop-ppc.tar.lzma + + + KDE + tar + kde-ppc.tar.lzma + + + KDE [meta] + tar + kde-meta-ppc.tar.lzma + + + + + base,enhanced_base,fonts,games,gnome,gnome_basis,imaging,multimedia,sw_management,x11,xgl + ppc + gnome-meta-ppc.tar.lzma + + + GNOME [1] + tar + common-base-ppc.tar.lzma + + + GNOME [2] + tar + common-xorg-ppc.tar.lzma + + + GNOME [4] + tar + common-desktop-ppc.tar.lzma + + + GNOME + tar + gnome-ppc.tar.lzma + + + GNOME [meta] + tar + gnome-meta-ppc.tar.lzma + + + + + base,enhanced_base,sw_management + ppc + base-meta-ppc.tar.lzma + + + BASE [1] + tar + base-meta-ppc.tar.lzma + + + BASE [2] + tar + base-ppc.tar.lzma + + + BASE [3] + tar + common-base-ppc.tar.lzma + + + + + base,enhanced_base,fonts,sw_management,x11 + ppc + x11-meta-ppc.tar.lzma + + + X11 [1] + tar + x11-meta-ppc.tar.lzma + + + X11 [2] + tar + x11-ppc.tar.lzma + + + X11 [3] + tar + common-xorg-ppc.tar.lzma + + + X11 [4] + tar + common-base-ppc.tar.lzma + + + + + diff --git a/tests/zypp/data/Fetcher/remote-site/images-file/content b/tests/zypp/data/Fetcher/remote-site/images-file/content new file mode 100644 index 0000000..a85d664 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/images-file/content @@ -0,0 +1,143 @@ +CONTENTSTYLE 11 +BASEARCHS i586 +DATADIR suse +DESCRDIR suse/setup/descr +DISTRIBUTION openSUSE +FLAVOR dvd +LABEL openSUSE 11.1 +LINGUAS cs da de en en_GB en_US es fi fr hu it ja nb nl pl pt pt_BR ru sv zh zh_CN zh_TW +NAME openSUSE +REFERENCES openSUSE-release = 11.1 +RELNOTESURL http://www.suse.com/relnotes/i386/openSUSE/11.0.42/release-notes-openSUSE.rpm +SUMMARY openSUSE +VERSION 11.1 +META SHA1 dd627cf38a5dee28421690d2ec6abea7af274a50 dvd-11.1-58.1.i586.pat.gz +META SHA1 fa49e3205fea8f95d395710a4ba79f55b4626ccd non_oss-11.1-58.1.i586.pat.gz +META SHA1 f6c6ef681aa5fc4c5e9532f04420d54fbec033a8 packages.cs.gz +META SHA1 cc5438a74d1b39f34bc31fbc2399ae6a95f43bc4 packages.de.gz +META SHA1 90dfa1e81f5515769f5b16fcf31c1ab63c55ff87 packages.DU.gz +META SHA1 b1c6b77703357297ecdd8d74b89a099ebbfe2fe6 packages.en.gz +META SHA1 b137fc7749531183b5250ec907d4b9adf4624288 packages.es.gz +META SHA1 3e55d6d5c21a6a1457ea6fef09c999b28883ade4 packages.fr.gz +META SHA1 b5b6092d57a701d4052ad2bb047636c68ac31d8b packages.gz +META SHA1 a893937892aeff71da1c38aa06f3cce5ba02de1c packages.hu.gz +META SHA1 f6c6ef681aa5fc4c5e9532f04420d54fbec033a8 packages.sk.gz +META SHA1 1d66972a977913541c7cb7130d61ec0e751148ba patterns +HASH SHA1 4ae30edd0588114b642bbb08fbd3fb71d7af257d license.tar.gz +HASH SHA1 67d82aa5cd4f08cf77cc70fe9ca1834a4b6212cc control.xml +HASH SHA1 e727c621ded4324cc61e94c615dbd423436f63e4 media.1/info.txt +HASH SHA1 7442eb13ca3c184fe0d47060dbc56fd45cfcb720 boot/i386/bind +HASH SHA1 99920bc0c322d0d0b63ac361d2f9c8f6bc9e3524 boot/i386/branding +HASH SHA1 ca2f0bce909d73d1bfaa7cdeb98595f17e4524aa boot/i386/common +HASH SHA1 d107fa19616c3eae9d49fe52e54971e5b9c160fa boot/i386/config +HASH SHA1 4b7d8525b1d3588562bea71b26cdb5e48e29ff64 boot/i386/cracklib-dict-full.rpm +HASH SHA1 1a8151b2bf88cf618be74eee60d65063386469e0 boot/i386/fonts-arabic.rpm +HASH SHA1 79aec7c93b730c2355aebd085eddf4195a9c1d36 boot/i386/fonts-thai.rpm +HASH SHA1 52e1040f8e0fae373d7426447b1f9d05d25b90f6 boot/i386/gdb +HASH SHA1 a1ba35bcecde55eb36be2e89b7210998b846be9d boot/i386/indic-fonts.rpm +HASH SHA1 6394ec4eb1883520de23bd2ac043490da6ed8fde boot/i386/initrd-xen +HASH SHA1 6394ec4eb1883520de23bd2ac043490da6ed8fde boot/i386/initrd-xenpae +HASH SHA1 6cebf392eaf1b17b53f3e5e88a6b6c6d8c2b76bb boot/i386/KhmerOS-fonts.rpm +HASH SHA1 e9c779539f1b3f56a96337f262b2bc548e6b223e boot/i386/LIESMICH +HASH SHA1 abdf17a0246be709efbcc7c0e0a68f8ad797a754 boot/i386/LIESMICH.DOS +HASH SHA1 f51e15897e5f77c7a7b4d1600dc53be6f117d9ec boot/i386/lklug.rpm +HASH SHA1 c4dca65aa97554bc45885b22ef4af24ad5177c75 boot/i386/mkbootdisk +HASH SHA1 99920bc0c322d0d0b63ac361d2f9c8f6bc9e3524 boot/i386/openSUSE +HASH SHA1 ae44557c57285f0866be41334fdaa20312ccdeab boot/i386/README +HASH SHA1 4a71ee6114eccfb88582dc5422020cbc5a2639dd boot/i386/README.DOS +HASH SHA1 e12efd095a7fb990d0c4be1e04999e72de84dd6a boot/i386/rescue +HASH SHA1 73e50e6321e6938471c4fc0521e0b2dce54f0346 boot/i386/root +HASH SHA1 9b4cced8b700c6737ab02af8f1521945c925c8f9 boot/i386/rpmlist +HASH SHA1 2181540518e50f88e7e35c619460e746934eacd4 boot/i386/sax2 +HASH SHA1 78d3ee95682c1150aa8a95132ba1c5d0d88c23bd boot/i386/ttf-arphic-uming.rpm +HASH SHA1 55a2d437b32d6c192c60e016756725f7a2e717e9 boot/i386/unfonts.rpm +HASH SHA1 7c6fbdc97c11e5e03098f19c196d85cd63e5ce85 boot/i386/vmlinuz-xen +HASH SHA1 7c6fbdc97c11e5e03098f19c196d85cd63e5ce85 boot/i386/vmlinuz-xenpae +HASH SHA1 67d109ba80c3f396710774ff03ace955a2184dc6 boot/i386/yast2-trans-af.rpm +HASH SHA1 3d835ea74b409914cf40ba48669a11590cffa902 boot/i386/yast2-trans-ar.rpm +HASH SHA1 5654cabb329f0b1251d5743624fdf599b92d71e5 boot/i386/yast2-trans-bg.rpm +HASH SHA1 1015f485542ae7c903ec9d1a9c7983d4701e2824 boot/i386/yast2-trans-bn.rpm +HASH SHA1 454e0f1b79d2076a9ba03b23c34da3cbc3e58e25 boot/i386/yast2-trans-bs.rpm +HASH SHA1 76bbfdb77952db51e9b21dc90ab167f2a46f4580 boot/i386/yast2-trans-ca.rpm +HASH SHA1 59f26af0b058b47f2d821f6fa8102d58af8d0377 boot/i386/yast2-trans-cs.rpm +HASH SHA1 db43e4829de2a26b4bb09aa1e93069af2b230377 boot/i386/yast2-trans-cy.rpm +HASH SHA1 1aee13cb0b0a1f4e7b1bbb49e809fd13919ba7e9 boot/i386/yast2-trans-da.rpm +HASH SHA1 36335f1ff2738071be00be65a64f7d41b7db1c33 boot/i386/yast2-trans-de.rpm +HASH SHA1 5297e40871de03217cfee404cb88e909422ceae8 boot/i386/yast2-trans-el.rpm +HASH SHA1 bc61efbd85302ed96ae51550a163cd0fc9ad59a3 boot/i386/yast2-trans-en_GB.rpm +HASH SHA1 a237b73e48777fcdd42505ec1e007484d9f398da boot/i386/yast2-trans-en_US.rpm +HASH SHA1 f2e0dba8e86a723ab72d7f7490665f8e631f63a1 boot/i386/yast2-trans-es.rpm +HASH SHA1 ca9bd8bf05434d42b6a7c2c7549e2ce0170c6be8 boot/i386/yast2-trans-et.rpm +HASH SHA1 57e5cd63079ac258734f28df5385e5288cd59db0 boot/i386/yast2-trans-fa.rpm +HASH SHA1 2983eb7ba93882e52434f396b49cd6e98d7b7399 boot/i386/yast2-trans-fi.rpm +HASH SHA1 0dfc3b38294524871f527d919ce31d6921cf77c0 boot/i386/yast2-trans-fr.rpm +HASH SHA1 2051d343881b288c5d22aec792e9d13ec192dfd1 boot/i386/yast2-trans-gl.rpm +HASH SHA1 49736a9798a371c3edf02f350ebe4db1e6fff011 boot/i386/yast2-trans-gu.rpm +HASH SHA1 d9737ea270e5166cbc409466c1d2a6f16fcc9f06 boot/i386/yast2-trans-hi.rpm +HASH SHA1 1e222655cfabbf0212e629ed1fccf304847ac732 boot/i386/yast2-trans-hr.rpm +HASH SHA1 1b6e646f9f8abc7c33ef2dd830b72c7a2f775620 boot/i386/yast2-trans-hu.rpm +HASH SHA1 723a18301396eccf7c0620f1f8f016719eaf7543 boot/i386/yast2-trans-id.rpm +HASH SHA1 70c272dbe7bfe963e44e5331edd5f440450bc827 boot/i386/yast2-trans-it.rpm +HASH SHA1 f17bc3588c7d2878821600d42fe174156971f87e boot/i386/yast2-trans-ja.rpm +HASH SHA1 d46ea44b7d98ade64658d1cf388013093d1c0d39 boot/i386/yast2-trans-jv.rpm +HASH SHA1 e4e684ebb7f93ac20461062544b49fe18c88627d boot/i386/yast2-trans-ka.rpm +HASH SHA1 123eb83403b88845cb5efd9046ef39351c1b68c3 boot/i386/yast2-trans-km.rpm +HASH SHA1 85c28913c4432f43fa29d8791d97b3e10456a42a boot/i386/yast2-trans-ko.rpm +HASH SHA1 6692fca0c1acb85b398bcbb9150d0826ea38f2c8 boot/i386/yast2-trans-lo.rpm +HASH SHA1 6247198d1348d31192dc158969ce8ae9252d6f0b boot/i386/yast2-trans-lt.rpm +HASH SHA1 a630f16e50a6227f814751931bb1a1ec15981c29 boot/i386/yast2-trans-mk.rpm +HASH SHA1 4f0bffd5cbeb7d37a7d78f1996cade7ae2ad2420 boot/i386/yast2-trans-mr.rpm +HASH SHA1 bbc950f9fec446e9a5a5876c532cd56e060c5eb4 boot/i386/yast2-trans-nb.rpm +HASH SHA1 edae4d58bd99064bbddd62278875b0387a2d495d boot/i386/yast2-trans-nl.rpm +HASH SHA1 85f1dc1eef8862066050c09eef023705a5d61039 boot/i386/yast2-trans-pa.rpm +HASH SHA1 e1eb02ebedff18a01facc150e00d05385affaa17 boot/i386/yast2-trans-pl.rpm +HASH SHA1 c3d31be5bf8af62c537e1a70db9afc98842b3f82 boot/i386/yast2-trans-pt_BR.rpm +HASH SHA1 b2bcd427139f2e13684a592ff186c3076a5b22d8 boot/i386/yast2-trans-pt.rpm +HASH SHA1 7fdb3299ca8230ec363d3ee8eee24915c931790c boot/i386/yast2-trans-ro.rpm +HASH SHA1 8b9bdb13f3b7c73e8c64303e8614e44bf640cc9f boot/i386/yast2-trans-ru.rpm +HASH SHA1 55876ae86c10a3504bbbcd71e49564f4c0b47149 boot/i386/yast2-trans-si.rpm +HASH SHA1 ee8ce4bc8a06b5094f8d51c79b32806531203d62 boot/i386/yast2-trans-sk.rpm +HASH SHA1 04130a176a24ce3adb663a2bb694fd484f2a7776 boot/i386/yast2-trans-sl.rpm +HASH SHA1 d3408d472a956ffbd1fb49354057da5c0b77879f boot/i386/yast2-trans-sr.rpm +HASH SHA1 fda2c586ff8a17d402108f007c2c6214bcaeca3f boot/i386/yast2-trans-sv.rpm +HASH SHA1 04021fd6654b2e7b6cbff65c094efa8c35424215 boot/i386/yast2-trans-ta.rpm +HASH SHA1 6aaae1e49e3188b5e73bedb3c3cd044c4108cca2 boot/i386/yast2-trans-th.rpm +HASH SHA1 6bb5903b7bc64185352c616099c344f8738bb768 boot/i386/yast2-trans-tr.rpm +HASH SHA1 9f631f117433db5e44a6bbed7c8a50cbbe5e8ac0 boot/i386/yast2-trans-uk.rpm +HASH SHA1 3ba5a8f4f3dc3f454e13223c2ecef9937824a611 boot/i386/yast2-trans-vi.rpm +HASH SHA1 bc2775d3a4a0a3ca80e5a5caa51a6612e7158d32 boot/i386/yast2-trans-wa.rpm +HASH SHA1 a3511637ca9bd4cbf5dc9eca58f8ccf5df49603c boot/i386/yast2-trans-xh.rpm +HASH SHA1 ba8875e4c0febe1d26d27c0c948e93128f14476a boot/i386/yast2-trans-zh_CN.rpm +HASH SHA1 d39b329ce32a0d59bebecd0d87ecfd59cb26e297 boot/i386/yast2-trans-zh_TW.rpm +HASH SHA1 0c6f45e6b01d531ac7e821ae9e479416149e92eb boot/i386/yast2-trans-zu.rpm +HASH SHA1 2325eb886cf06b58ca1892578383b5fcc5b11866 boot/i386/loader/linux +HASH SHA1 586ec9beb26fb337283f3b49149d843a3fb7c821 boot/i386/loader/initrd +HASH SHA1 d6b4db657272efe902f8ce92b53082fda4d5f1ca boot/i386/loader/08000600.spl +HASH SHA1 22d4aeede74fdf44b3c4a2524319fe9cf418d4c6 boot/i386/loader/10240600.spl +HASH SHA1 93e297fb9ffa23d6a167c50c318bbb46b0705e45 boot/i386/loader/10240768.spl +HASH SHA1 8c135621ac91216c3388f9ea9c02127b2f6375a0 boot/i386/loader/12800800.spl +HASH SHA1 54dd2bc17c9f73ad9d6a85489f99f518849cb84d boot/i386/loader/12801024.spl +HASH SHA1 ef0f517a3f3a3240349b9bdd01e794267372c4ab boot/i386/loader/14001050.spl +HASH SHA1 2abbc5b4c7c3dc8134ae1207f9d9e95a640046ef boot/i386/loader/16001200.spl +HASH SHA1 e37862355648f6330b6831c69c989dec02b80ab0 boot/i386/loader/16801050.spl +HASH SHA1 082a7887d2f43d049fdb0fc92c5051f1a5b7e663 boot/i386/loader/19201200.spl +HASH SHA1 ed5f4a87074367bcf8396da7a9b9b3d1be6dfcb2 images/base-i386.tar.lzma +HASH SHA1 9d055cacc983226171cdd3a3fe1acd6bb6fa044e images/base-meta-i386.tar.lzma +HASH SHA1 361e07c44526cd43a2d477b7b3448e49e674f0a8 images/common-base-i386.tar.lzma +HASH SHA1 6854608038e4d3b11fcc950e28ca49e4582fd2a4 images/common-desktop-i386.tar.lzma +HASH SHA1 5f6a43158c017e188309c094cdaf24c346de3dfb images/common-xorg-i386.tar.lzma +HASH SHA1 ce6620b820e494c042398b9fd7ed108578008168 images/details-i386.xml +HASH SHA1 22c466bf9af3003ee95fed6f7fb93b4c8c0cd993 images/gnome-i386.tar.lzma +HASH SHA1 49374551f38fe919cf4545d5af0fea7d45361738 images/gnome-meta-i386.tar.lzma +HASH SHA1 d1e9a38629e353d1f0136ded670cf28213d47e6f images/images.xml +HASH SHA1 0df7debf780a0e01b18004d18ef6ab21410b9480 images/kde-i386.tar.lzma +HASH SHA1 c418a15669de278e523893f030c209c479f490e6 images/kde-meta-i386.tar.lzma +HASH SHA1 6c4238796684f770a0b4ecd1ea4469e5a7a49b0d images/x11-i386.tar.lzma +HASH SHA1 cc50a8bc9d560c8d522660feed5feb019f9b889e images/x11-meta-i386.tar.lzma +KEY SHA1 17162a96933229a9771ee10c0976bdc047a2f53d gpg-pubkey-0dfb3188-41ed929b.asc +KEY SHA1 f6accbb18d705bfc104c893cf7dfca1247a33f3c gpg-pubkey-307e3d54-481f30aa.asc +KEY SHA1 47f6492d127ae9f6aac353a2dd23752fc0ed4f8d gpg-pubkey-3d25d3d9-36e12d04.asc +KEY SHA1 2288e5849740566e4fb65b7c9dc0c7e4f43b1039 gpg-pubkey-56b4177a-47965b33.asc +KEY SHA1 89d4bcd20a281553fd1d4ec1708603ebf88f1a59 gpg-pubkey-7e2e3b05-4816488f.asc +KEY SHA1 06ff5171362496c0db84beeccd29967f580350b2 gpg-pubkey-9c800aca-481f343a.asc +KEY SHA1 04544096c5c3b0ed7b01a83d79e048307c2af919 gpg-pubkey-a1912208-446a0899.asc diff --git a/tests/zypp/data/Fetcher/remote-site/images-file/content.asc b/tests/zypp/data/Fetcher/remote-site/images-file/content.asc new file mode 100644 index 0000000..1e13b6f --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/images-file/content.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v2.0.9 (GNU/Linux) + +iEYEABECAAYFAkkTDKoACgkQm+zCtd2wN1bWFwCcDMWfuN+JDv8/Dew9ozDLNkNM +JbAAn2nqGLhU1PcX6Ev4t/jlPsazliaC +=8Ava +-----END PGP SIGNATURE----- diff --git a/tests/zypp/data/Fetcher/remote-site/images-file/content.key b/tests/zypp/data/Fetcher/remote-site/images-file/content.key new file mode 100644 index 0000000..7b6734f --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/images-file/content.key @@ -0,0 +1,49 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.9 (GNU/Linux) + +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 +aVStjbDRYEnTHQOGsVy9 +=ZZx0 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/Fetcher/remote-site/images-file/images/images.xml b/tests/zypp/data/Fetcher/remote-site/images-file/images/images.xml new file mode 100644 index 0000000..7b252e8 --- /dev/null +++ b/tests/zypp/data/Fetcher/remote-site/images-file/images/images.xml @@ -0,0 +1,345 @@ + + + + + + base,enhanced_base,games,imaging,kde4,kde4_basis,multimedia,sw_management,x11,xgl + i386 + kde-meta-i386.tar.lzma + + + KDE [base] + tar + common-base-i386.tar.lzma + + + KDE [xorg] + tar + common-xorg-i386.tar.lzma + + + KDE [desktop] + tar + common-desktop-i386.tar.lzma + + + KDE + tar + kde-i386.tar.lzma + + + KDE [meta] + tar + kde-meta-i386.tar.lzma + + + + + base,enhanced_base,fonts,games,gnome,gnome_basis,imaging,multimedia,sw_management,x11,xgl + i386 + gnome-meta-i386.tar.lzma + + + GNOME [1] + tar + common-base-i386.tar.lzma + + + GNOME [2] + tar + common-xorg-i386.tar.lzma + + + GNOME [4] + tar + common-desktop-i386.tar.lzma + + + GNOME + tar + gnome-i386.tar.lzma + + + GNOME [meta] + tar + gnome-meta-i386.tar.lzma + + + + + base,enhanced_base,sw_management + i386 + base-meta-i386.tar.lzma + + + BASE [1] + tar + base-meta-i386.tar.lzma + + + BASE [2] + tar + base-i386.tar.lzma + + + BASE [3] + tar + common-base-i386.tar.lzma + + + + + base,enhanced_base,fonts,sw_management,x11 + i386 + x11-meta-i386.tar.lzma + + + X11 [1] + tar + x11-meta-i386.tar.lzma + + + X11 [2] + tar + x11-i386.tar.lzma + + + X11 [3] + tar + common-xorg-i386.tar.lzma + + + X11 [4] + tar + common-base-i386.tar.lzma + + + + + base,enhanced_base,games,imaging,kde4,kde4_basis,multimedia,sw_management,x11,xgl + x86_64 + kde-meta-x86_64.tar.lzma + + + KDE [base] + tar + common-base-x86_64.tar.lzma + + + KDE [xorg] + tar + common-xorg-x86_64.tar.lzma + + + KDE [desktop] + tar + common-desktop-x86_64.tar.lzma + + + KDE + tar + kde-x86_64.tar.lzma + + + KDE [meta] + tar + kde-meta-x86_64.tar.lzma + + + + + base,enhanced_base,fonts,games,gnome,gnome_basis,imaging,multimedia,sw_management,x11,xgl + x86_64 + gnome-meta-x86_64.tar.lzma + + + GNOME [1] + tar + common-base-x86_64.tar.lzma + + + GNOME [2] + tar + common-xorg-x86_64.tar.lzma + + + GNOME [4] + tar + common-desktop-x86_64.tar.lzma + + + GNOME + tar + gnome-x86_64.tar.lzma + + + GNOME [meta] + tar + gnome-meta-x86_64.tar.lzma + + + + + base,enhanced_base,sw_management + x86_64 + base-meta-x86_64.tar.lzma + + + BASE [1] + tar + base-meta-x86_64.tar.lzma + + + BASE [2] + tar + base-x86_64.tar.lzma + + + BASE [3] + tar + common-base-x86_64.tar.lzma + + + + + base,enhanced_base,fonts,sw_management,x11 + x86_64 + x11-meta-x86_64.tar.lzma + + + X11 [1] + tar + x11-meta-x86_64.tar.lzma + + + X11 [2] + tar + x11-x86_64.tar.lzma + + + X11 [3] + tar + common-xorg-x86_64.tar.lzma + + + X11 [4] + tar + common-base-x86_64.tar.lzma + + + + + base,enhanced_base,games,imaging,kde4,kde4_basis,multimedia,sw_management,x11,xgl + ppc + kde-meta-ppc.tar.lzma + + + KDE [base] + tar + common-base-ppc.tar.lzma + + + KDE [xorg] + tar + common-xorg-ppc.tar.lzma + + + KDE [desktop] + tar + common-desktop-ppc.tar.lzma + + + KDE + tar + kde-ppc.tar.lzma + + + KDE [meta] + tar + kde-meta-ppc.tar.lzma + + + + + base,enhanced_base,fonts,games,gnome,gnome_basis,imaging,multimedia,sw_management,x11,xgl + ppc + gnome-meta-ppc.tar.lzma + + + GNOME [1] + tar + common-base-ppc.tar.lzma + + + GNOME [2] + tar + common-xorg-ppc.tar.lzma + + + GNOME [4] + tar + common-desktop-ppc.tar.lzma + + + GNOME + tar + gnome-ppc.tar.lzma + + + GNOME [meta] + tar + gnome-meta-ppc.tar.lzma + + + + + base,enhanced_base,sw_management + ppc + base-meta-ppc.tar.lzma + + + BASE [1] + tar + base-meta-ppc.tar.lzma + + + BASE [2] + tar + base-ppc.tar.lzma + + + BASE [3] + tar + common-base-ppc.tar.lzma + + + + + base,enhanced_base,fonts,sw_management,x11 + ppc + x11-meta-ppc.tar.lzma + + + X11 [1] + tar + x11-meta-ppc.tar.lzma + + + X11 [2] + tar + x11-ppc.tar.lzma + + + X11 [3] + tar + common-xorg-ppc.tar.lzma + + + X11 [4] + tar + common-base-ppc.tar.lzma + + + + + diff --git a/tests/zypp/data/FileChecker/hello.txt b/tests/zypp/data/FileChecker/hello.txt new file mode 100644 index 0000000..10377d3 --- /dev/null +++ b/tests/zypp/data/FileChecker/hello.txt @@ -0,0 +1 @@ +hello this is a test diff --git a/tests/zypp/data/FileChecker/hello.txt.asc b/tests/zypp/data/FileChecker/hello.txt.asc new file mode 100644 index 0000000..f71bd45 --- /dev/null +++ b/tests/zypp/data/FileChecker/hello.txt.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQBGXW7Gm+zCtd2wN1YRAuAXAJ9e2obl0RWM9eBQz8dmPdQjclmamQCfRnJS +XFIPNZAA1XeQL/Dvi51EIwc= +=3TuF +-----END PGP SIGNATURE----- diff --git a/tests/zypp/data/FileChecker/hello.txt.key b/tests/zypp/data/FileChecker/hello.txt.key new file mode 100644 index 0000000..1ee7f92 --- /dev/null +++ b/tests/zypp/data/FileChecker/hello.txt.key @@ -0,0 +1,214 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.6 (GNU/Linux) + +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 +yqfsg94RICpbr50= +=NAat +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/FileChecker/hello2.txt b/tests/zypp/data/FileChecker/hello2.txt new file mode 100644 index 0000000..43e4a03 --- /dev/null +++ b/tests/zypp/data/FileChecker/hello2.txt @@ -0,0 +1,2 @@ +this is another text + diff --git a/tests/zypp/data/KeyRing/installkey.gpg b/tests/zypp/data/KeyRing/installkey.gpg new file mode 100644 index 0000000000000000000000000000000000000000..434c8992d84f2dd52da287d53f25cb8dd3a13cbe GIT binary patch literal 1757 zcmb`{eK->c90%~dzaSZTsl-CIQJd+B(o!xNhrKi^tdyGBL_-^r*9yCmBGo8c^hU}= zGKMmg3gIcTBjqSt!&z7ELZ|Mo=l;06zwY<{_mAKA`8?nA$06?MWjlcoK*N)=McPjX zQv*+3eQ~Y2O`_T!Tj}=L$u>wO?DkJ@<+@EIpY#dA5en4h6=bo`>>`l774 zU#PG)14(6&KvxCGAXCKx%x@<6FQ+n-6)ynXj_dS=d7!13Dxt%Cqcin6f>wTk0v+DFn z(#Gkj_Q|&DQ$yhULMbWX?>m_)eFv{s!7Hw z4UxX%&B5ny>BUjUd48|$ZYj)!yDld)qUgcHJiWSYyJaX*N0+5yuzA|WVvn@Weaj6| z(N-B$bg>K1cPqD`n#7Besf4h*mG3X1oSnP+UuqL1G19oU+;%rsyWTX6N4SI+fI+&;}VAJXgv*27!2#YidA!~4nec0)D`vxUKD6Y z^}5MGRwftQp~f^-(;}w~K7@+*6UP*Lvu>{zkE63tSD&al${g(TF@?kn-)|93IRM0C zH&><|KuD#OGRSISF5ijn^7LADS8r$o%%rv?4w2+}$;9diR9(zBw*AeUT;6`dxg4uB z&cX>x66cnb7B)XebZL$JapTu~(KDO3x4_zbMklC0J3MUj6avGzbb+C6;(13)iFJD9 zGlW(fG)Z~szV!s}&7-VW;Q5DT%R($p3+~cwivIWZ)RF86GaHTvn%7R?oRYiGwt@Z6r`MET$*7fL$bF==E zDwIxa;%M3o2om-%p(D?6swu4x{U~MI0s)}{3|xOxTu9-;e#962D)*b-cI=UocB?A% zzA_d*DmD6{<(*~!6dp&mvyC=Ge!|1_5?g#ioam>aTRqQ2BxHDwY^lJ@Oe>Yi3H8*) J3hG}}e+R&G + + + + 49589f0e6569914ada9293e8c3895cb899b58a58 + 1177395604 + 67b155adc1e7622f7962849ee43965253a797765 + + + + 4174aed6d4ffb8cfee41b64ae357ce1db3fe904a + 1177395604 + 1981b7db9252974869ce1d71443bde69fa9423ca + + + + 2a72bebe987fb613673d9db73120e95a999f143d + 1177395604 + 6a328b1ec1fab195fb69035c13fe4340ee2b9cbd + + diff --git a/tests/zypp/data/KeyRing/repomd.xml.asc b/tests/zypp/data/KeyRing/repomd.xml.asc new file mode 100644 index 0000000..9b68fbb --- /dev/null +++ b/tests/zypp/data/KeyRing/repomd.xml.asc @@ -0,0 +1,7 @@ +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.6 (GNU/Linux) + +iD8DBQBGQFwzvWHYm9mIIb4RAnbuAJsHJkj5X8M5aOxeZ2KUsHjhQ1vKOACdFrQ0 +Vxp3Zznn3w4j5SaGAqpyGWA= +=iu9H +-----END PGP SIGNATURE----- diff --git a/tests/zypp/data/KeyRing/repomd.xml.corrupted b/tests/zypp/data/KeyRing/repomd.xml.corrupted new file mode 100644 index 0000000..b655532 --- /dev/null +++ b/tests/zypp/data/KeyRing/repomd.xml.corrupted @@ -0,0 +1,21 @@ + + + + + 49589f0e6569914ada9293e8c3895cb899b58a58 + 1177395604 + 67b855adc1e7622f7962849ee43965253a797765 + + + + 4174aed6d4ffb8cfee41b64ae357ce1db3fe904a + 1177395604 + 1981b7db9252974869ce1d71443bde69fa9423ca + + + + 2a72bebe987fb613673d9db73120e95a999f143d + 1177395604 + 6a328b1ec1fab195fb69035c13fe4340ee2b9cbd + + diff --git a/tests/zypp/data/Locks/locks b/tests/zypp/data/Locks/locks new file mode 100644 index 0000000..464cd99 --- /dev/null +++ b/tests/zypp/data/Locks/locks @@ -0,0 +1 @@ +query_string: zypper diff --git a/tests/zypp/data/PoolQuery/savedqueries b/tests/zypp/data/PoolQuery/savedqueries new file mode 100644 index 0000000..26d56e6 --- /dev/null +++ b/tests/zypp/data/PoolQuery/savedqueries @@ -0,0 +1,11 @@ +solvable_name: tool +repo: vbox +repo: zyppsvn + +query_string: ma* +repo: opensuse +type: patch +match_type: regex +case_sensitive: on +install_status: not-installed +version: != 0.8.3 diff --git a/tests/zypp/data/PoolQueryCC/rxnames.xml b/tests/zypp/data/PoolQueryCC/rxnames.xml new file mode 100644 index 0000000..d3be84b --- /dev/null +++ b/tests/zypp/data/PoolQueryCC/rxnames.xml @@ -0,0 +1,21 @@ + + + . + ? + * + + + [ + ] + ( + ) + { + } + | + ^ + $ + \ + A + AB + BAB + .A. + diff --git a/tests/zypp/data/PublicKey/multikey.asc b/tests/zypp/data/PublicKey/multikey.asc new file mode 100644 index 0000000..b42b9c7 --- /dev/null +++ b/tests/zypp/data/PublicKey/multikey.asc @@ -0,0 +1,38 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.19 (GNU/Linux) + +mIsERCAdXQEEAL7MrBTz+3SBWpCm2ae2yaDqV3ezQcs2JlvqidJVhsZqQe9/jkxi +KTEQW5+TXF/+BlQSiebunRI7oo3+9U8GyRCgs1sf+yRQWMLzZqRaarzRhw9w+Ihl +edtqYl6/U2JZCb8Adp6d7RzlRliJdJ/VtsfXj2ef7Dwu7elOVSsmaBdtAAYptChT +dVNFIFBhY2thZ2UgU2lnbmluZyBLZXkgPGJ1aWxkQHN1c2UuZGU+iLgEEwECACIC +GwMECwcDAgMVAgMDFgIBAh4BAheABQJL4BplBQkPRMsIAAoJEOOlw2Awfj1UhOsD +/RkkEhOIC9NNad0F5O0rEJxvsI7Nm+6FnNJq8LjyR5+87epQCXgpaBXEGd4RcjjO +TukLaHHrC1T/h4biIyf253VZHr4oJ46sUivNUFq60gl4gk56aTGTNeUWOsgrU4jm +auFca3dbGcNfiJ7c7dF2CkOAR+CPMLPYTvuVIRQBAjeSmQGiBEjKO60RBACeqGqC +khF+Zmzln1G7Jj9EaX6qiigk1hbs5VLQ5205lBIFMocOOAcmB9GI6r9D4VdwTew9 +PaXur4cRi8otaF93DaCCgsBvLsBTVFC1sKgJMJkhB/BKV4GdSCAylSNAzASYelZE +7KJSD1KxdS29HBVN07BOcSCBjR9eRC6kmW9IWwCg0t9U+Jx+CX7Fa9Q5mZ0/OfI1 +Bd8D/joPsDKz2uAit3gEXGgGorQdXiFZIbppLe89Jz9fLq/J9GFdd6lz3Yv2Vsf/ +hsaWPXQl5IZE+p6UPWUDUCwLVioLPQKh1p95KFdLn6pxFwG94UTougtjmm10E2ND +0PdssakeVtdYtNoeagQC1fYKmWyxBgXd4/nfhiNq0wFGsUUEBACbx8MIv5umcIIx +TG8sJRouOjIgRdfmWPiWpxAql+qyPTwnkZytZ0zJrfdVEnKrfX8FkZ86oDN1pc0Z +Zht59PrwxZpC5Kt3x0jNnyztn0FGwkADDhaEdzu8ZFXpkxglbsBAF2jx8HBLEMjN +CFCEYHUoFrcIVfCO/fHJKWZquYKQuLQhVW5zdXBwb3J0ZWQgPHVuc3VwcG9ydGVk +QHN1c2UuZGU+iGYEExECACYCGwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCS+Aa +8wUJCpqtRgAKCRAn+kG9inxk+XmpAKCUcG9rb6yU4jZn8PudBfsuQNhQNgCghiHo +heeFc3pKA2PJ5tUKuPpTLya5Ag0ESMo7tBAIAJr+eL5b7DNd6oEcgMWR2yZieSpr +YMDRGc5lU7HOsApcH2kHleBUQynle5NyYI0LOCuzV5QtAd0gwDV99A8VAVvYrcJl +uuh6Wj2yoENBulEySUZ9LYuGA5ErFDGWEMMbXDLNvvb2MVCDXnLE34aXzRVnDjKd +2+/vzpNFuEECwGZBcf78+u0BNxCfxgLgdKdLZsAmdcFEONu8Zx6hxpoL5h+B1doI +FqgePcAqhw3m7O+R8PCsODBvoIgQfViwk21BNKpnfBSvLFpJTA+AnwnRAuyljmda +hI1LwB7VZ+TSplpsbt08HvmDDPzKsfgURPp+NzsQU0iFmjeaYf/9cDYgbA8AAwUH +/A2dQA0JymANMkViHUt8HHtMpRPfUBEAICRriMmkSIWoUK6hZ/rD8t8PkOG7pfLC +os/WdIPtuuh+56Cw1u48pwXe4nR0M3iqVTxizdldt197MeQejjBppcza7OH7nyga ++NXf/GsniuuHcanImyh8yugaobWeBVD8i2juuLZFmlKc88Z1XWTC1ndB0WduWca2 +XEIJgvPyk84y/r6ItB45R+Pn3b/mafl2ebhI+YG8ywY8lqBhSWnQTNXaKG/ijb+a +xSEPVvNAHonZyv81XUDRNDEO/Rwsxmgb12J41k+5jpcB5yKo4lc6qNdHAwyuxSUB +D/xATGUaSFmUE7mxFlzCr0+ITwQYEQIADwIbDAUCS+AbAwUJCpqtTwAKCRAn+kG9 +inxk+TQ4AKCUWlqp8CgtApaaV/KBmNMhcE9TzwCfcTpQER3EMh/4CgK8wSHFcTuG +QEk= +=Dkxe +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/PublicKey/multikey2.asc b/tests/zypp/data/PublicKey/multikey2.asc new file mode 100644 index 0000000..1ee7f92 --- /dev/null +++ b/tests/zypp/data/PublicKey/multikey2.asc @@ -0,0 +1,214 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.6 (GNU/Linux) + +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 +yqfsg94RICpbr50= +=NAat +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/PublicKey/susekey.asc b/tests/zypp/data/PublicKey/susekey.asc new file mode 100644 index 0000000..b49e52d --- /dev/null +++ b/tests/zypp/data/PublicKey/susekey.asc @@ -0,0 +1,37 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1.4.2 (GNU/Linux) + +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 +=pJli +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/PurgeKernels/arch/@System.repo b/tests/zypp/data/PurgeKernels/arch/@System.repo new file mode 100644 index 0000000..31515f0 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/arch/@System.repo @@ -0,0 +1,485 @@ +=Ver: 3.0 +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-firmware - noarch ++Prv: +kernel-firmware = 20190312-lp151.2.3.1 +kernel-firmware = +-Prv: +=Pkg: kernel-macros 1 0 noarch ++Prv: +kernel-subpackage-macros +kernel-macros = 1-0 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-1 +kernel = 1-1 +kernel-uname-r = 1-1-default +kernel-default = 1-1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 1 x86_64 ++Req: +kernel = 1-1 +-Req: ++Prv: +kernel-livepatch-default-1-1 +kernel-livepatch-default = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 1 x86_64 ++Req: +kernel-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-1 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 1 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 1 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 1 x86_64 ++Req: +kernel-devel = 1-1 +kernel-default-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-1 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: kernel-default 1 2 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-2 +kernel = 1-2 +kernel-uname-r = 1-2-default +kernel-default = 1-2 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 2 x86_64 ++Req: +kernel = 1-2 +-Req: ++Prv: +kernel-livepatch-default-1-2 +kernel-livepatch-default = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 2 x86_64 ++Req: +kernel-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-2 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 2 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 2 x86_64 ++Req: +kernel-devel = 1-2 +kernel-default-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 5 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-5 +kernel = 1-5 +kernel-uname-r = 1-5-default +ksym(foobar) = abdcfee +kernel-default = 1-5 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 5 x86_64 ++Req: +kernel-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-5 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 5 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 5 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 5 x86_64 ++Req: +kernel-devel = 1-5 +kernel-default-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-5 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: dummy-kmp-default 1 0 x86_64 ++Req: +kernel-default-devel +ksym(foobar) = abdcfee +-Req: ++Prv: +kmod(dummy) +dummy-kmp-default = 1-0 +-Prv: +=Pkg: kernel-default 1 1 i686 ++Prv: +multiversion(kernel) +kernel-default-1-1 +kernel = 1-1 +kernel-uname-r = 1-1-default +kernel-default = 1-1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 1 i686 ++Req: +kernel = 1-1 +-Req: ++Prv: +kernel-livepatch-default-1-1 +kernel-livepatch-default = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 1 i686 ++Req: +kernel-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-1 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 1 i686 ++Prv: +kernel-default-devel-debuginfo = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 1 i686 ++Req: +kernel-devel = 1-1 +kernel-default-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-1 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: kernel-default 1 2 i686 ++Prv: +multiversion(kernel) +kernel-default-1-2 +kernel = 1-2 +kernel-uname-r = 1-2-default +kernel-default = 1-2 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 2 i686 ++Req: +kernel = 1-2 +-Req: ++Prv: +kernel-livepatch-default-1-2 +kernel-livepatch-default = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 2 i686 ++Req: +kernel-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-2 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 2 i686 ++Prv: +kernel-default-devel-debuginfo = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 2 i686 ++Req: +kernel-devel = 1-2 +kernel-default-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 5 i686 ++Prv: +multiversion(kernel) +kernel-default-1-5 +kernel = 1-5 +kernel-uname-r = 1-5-default +ksym(foobar) = abdcfee +kernel-default = 1-5 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 5 i686 ++Req: +kernel-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-5 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 5 i686 ++Prv: +kernel-default-devel-debuginfo = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 5 i686 ++Req: +kernel-devel = 1-5 +kernel-default-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-5 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: dummy-kmp-default 1 0 i686 ++Req: +kernel-default-devel +ksym(foobar) = abdcfee +-Req: ++Prv: +kmod(dummy) +dummy-kmp-default = 1-0 +-Prv: +=Pkg: kernel-default 1 1 aarch64 ++Prv: +multiversion(kernel) +kernel-default-1-1 +kernel = 1-1 +kernel-uname-r = 1-1-default +kernel-default = 1-1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 1 aarch64 ++Req: +kernel = 1-1 +-Req: ++Prv: +kernel-livepatch-default-1-1 +kernel-livepatch-default = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 1 aarch64 ++Req: +kernel-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-1 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 1 aarch64 ++Prv: +kernel-default-devel-debuginfo = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 1 aarch64 ++Req: +kernel-devel = 1-1 +kernel-default-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-1 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: kernel-default 1 2 aarch64 ++Prv: +multiversion(kernel) +kernel-default-1-2 +kernel = 1-2 +kernel-uname-r = 1-2-default +kernel-default = 1-2 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 2 aarch64 ++Req: +kernel = 1-2 +-Req: ++Prv: +kernel-livepatch-default-1-2 +kernel-livepatch-default = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 2 aarch64 ++Req: +kernel-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-2 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 2 aarch64 ++Prv: +kernel-default-devel-debuginfo = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 2 aarch64 ++Req: +kernel-devel = 1-2 +kernel-default-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 5 aarch64 ++Prv: +multiversion(kernel) +kernel-default-1-5 +kernel = 1-5 +kernel-uname-r = 1-5-default +ksym(foobar) = abdcfee +kernel-default = 1-5 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 5 aarch64 ++Req: +kernel-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-5 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 5 aarch64 ++Prv: +kernel-default-devel-debuginfo = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 5 aarch64 ++Req: +kernel-devel = 1-5 +kernel-default-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-5 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: dummy-kmp-default 1 0 aarch64 ++Req: +kernel-default-devel +ksym(foobar) = abdcfee +-Req: ++Prv: +kmod(dummy) +dummy-kmp-default = 1-0 +-Prv: diff --git a/tests/zypp/data/PurgeKernels/arch/zypp-control.yaml b/tests/zypp/data/PurgeKernels/arch/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/arch/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/PurgeKernels/fancybuildnr/@System.repo b/tests/zypp/data/PurgeKernels/fancybuildnr/@System.repo new file mode 100644 index 0000000..e08fb27 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/fancybuildnr/@System.repo @@ -0,0 +1,155 @@ +=Ver: 3.0 +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-firmware - noarch ++Prv: +kernel-firmware = 20190312-lp151.2.3.1 +kernel-firmware = +-Prv: +=Pkg: kernel-default 5.7.8 1.1.g8f507a0 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.8-1.1.g8f507a0 +kernel = 5.7.8-1.1.g8f507a0 +kernel-uname-r = 5.7.8-1.g8f507a0-default +kernel-default = 5.7.8-1.1.g8f507a0 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.7.9 1.1.ga010166 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.9-1.1.ga010166 +kernel = 5.7.9-1.1.ga010166 +kernel-uname-r = 5.7.9-1.ga010166-default +kernel-default = 5.7.9-1.1.ga010166 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.7.10 1.1.g6a1b5cf x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.10-1.1.g6a1b5cf +kernel = 5.7.10-1.1.g6a1b5cf +kernel-uname-r = 5.7.10-1.g6a1b5cf-default +kernel-default = 5.7.10-1.1.g6a1b5cf +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.7.10 3.1.gd1148b9 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.10-3.1.gd1148b9 +kernel = 5.7.10-3.1.gd1148b9 +kernel-uname-r = 5.7.10-3.gd1148b9-default +kernel-default = 5.7.10-3.1.gd1148b9 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.7.11 1.1.g5015994 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.11-1.1.g5015994 +kernel = 5.7.11-1.1.g5015994 +kernel-uname-r = 5.7.11-1.g5015994-default +kernel-default = 5.7.11-1.1.g5015994 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.7.12 1.1.g9c98feb x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.12-1.1.g9c98feb +kernel = 5.7.12-1.1.g9c98feb +kernel-uname-r = 5.7.12-1.g9c98feb-default +kernel-default = 5.7.12-1.1.g9c98feb +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.8.0 1.1.gd3bf2d6 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.8.0-1.1.gd3bf2d6 +kernel = 5.8.0-1.1.gd3bf2d6 +kernel-uname-r = 5.8.0-1.gd3bf2d6-default +kernel-default = 5.8.0-1.1.gd3bf2d6 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.8.0 2.1.g9bc0044 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.8.0-2.1.g9bc0044 +kernel = 5.8.0-2.1.g9bc0044 +kernel-uname-r = 5.8.0-2.g9bc0044-default +kernel-default = 5.8.0-2.1.g9bc0044 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.8.0 3.1.gd4e7682 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.8.0-3.1.gd4e7682 +kernel = 5.8.0-3.1.gd4e7682 +kernel-uname-r = 5.8.0-3.gd4e7682-default +kernel-default = 5.8.0-3.1.gd4e7682 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.8.1 1.1.ge6658c9 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.8.1-1.1.ge6658c9 +kernel = 5.8.1-1.1.ge6658c9 +kernel-uname-r = 5.8.1-1.ge6658c9-default +kernel-default = 5.8.1-1.1.ge6658c9 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.8.1 2.1.g553537d x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.8.1-2.1.g553537d +kernel = 5.8.1-2.1.g553537d +kernel-uname-r = 5.8.1-2.g553537d-default +kernel-default = 5.8.1-2.1.g553537d +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default 5.8.1 3.1.g846658e x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.8.1-3.1.g846658e +kernel = 5.8.1-3.1.g846658e +kernel-uname-r = 5.8.1-3.g846658e-default +kernel-default = 5.8.1-3.1.g846658e +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE diff --git a/tests/zypp/data/PurgeKernels/fancybuildnr/zypp-control.yaml b/tests/zypp/data/PurgeKernels/fancybuildnr/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/fancybuildnr/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/PurgeKernels/flavour/@System.repo b/tests/zypp/data/PurgeKernels/flavour/@System.repo new file mode 100644 index 0000000..0f5ba45 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/flavour/@System.repo @@ -0,0 +1,356 @@ +=Ver: 3.0 +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-firmware - noarch ++Prv: +kernel-firmware = 20190312-lp151.2.3.1 +kernel-firmware = +-Prv: + +=Pkg: kernel-macros 1 0 noarch ++Prv: +kernel-subpackage-macros +kernel-macros = 1-0 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-rt 1 1 x86_64 ++Prv: +multiversion(kernel) +kernel-rt-1-1 +kernel = 1-1 +kernel-uname-r = 1-1-rt +kernel-rt = 1-1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel 1 1 x86_64 ++Req: +kernel-devel-rt = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-rt-devel = 1-1 +-Prv: ++Sup: +kernel-rt & kernel-devel-rt +-Sup: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel-debuginfo 1 1 x86_64 ++Prv: +kernel-rt-devel-debuginfo = 1-1 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-devel-rt 1 1 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel-rt = 1-1 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-source-rt 1 1 noarch ++Req: +kernel-devel-rt = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-source-rt = 1-1 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-devel-rt 1 1.2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel-rt = 1-1 +kernel-devel-rt = 1-1.2 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-source-rt 1 1.2 noarch ++Req: +kernel-devel-rt = 1-1.2 +-Req: ++Prv: +multiversion(kernel) +kernel-source-rt = 1-1 +kernel-source-rt = 1-1.2 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-syms-rt 1 1 x86_64 ++Req: +kernel-devel-rt = 1-1 +kernel-rt-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-syms-rt = 1-1 +-Prv: +=Vnd: openSUSE + +=Tim: 1570603549 +=Pkg: kernel-rt 1 2 x86_64 ++Prv: +multiversion(kernel) +kernel-rt-1-2 +kernel = 1-2 +kernel-uname-r = 1-2-rt +kernel-rt = 1-2 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel 1 2 x86_64 ++Req: +kernel-devel-rt = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-rt-devel = 1-2 +-Prv: ++Sup: +kernel-rt & kernel-devel-rt +-Sup: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel-debuginfo 1 2 x86_64 ++Prv: +kernel-rt-devel-debuginfo = 1-2 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-devel-rt 1 2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel-rt = 1-2 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-syms-rt 1 2 x86_64 ++Req: +kernel-devel-rt = 1-2 +kernel-rt-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-syms-rt = 1-2 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-rt 1 3 x86_64 ++Prv: +multiversion(kernel) +kernel-rt-1-3 +kernel = 1-3 +kernel-uname-r = 1-3-rt +kernel-rt = 1-3 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel 1 3 x86_64 ++Req: +kernel-devel-rt = 1-3 +-Req: ++Prv: +multiversion(kernel) +kernel-rt-devel = 1-3 +-Prv: ++Sup: +kernel-rt & kernel-devel-rt +-Sup: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel 1 3.2 x86_64 ++Req: +kernel-devel-rt = 1-3.2 +-Req: ++Prv: +multiversion(kernel) +kernel-rt-devel = 1-3 +kernel-rt-devel = 1-3.2 +-Prv: ++Sup: +kernel-rt & kernel-devel-rt +-Sup: +=Vnd: openSUSE + +=Pkg: kernel-devel-rt 1 3.2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel-rt = 1-3 +kernel-devel-rt = 1-3.2 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-source-rt 1 3.2 noarch ++Req: +kernel-devel-rt = 1-3.2 +-Req: ++Prv: +multiversion(kernel) +kernel-source-rt = 1-3 +kernel-source-rt = 1-3.2 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel-debuginfo 1 3 x86_64 ++Prv: +kernel-rt-devel-debuginfo = 1-3 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-devel-rt 1 3 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel-rt = 1-3 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-syms-rt 1 3 x86_64 ++Req: +kernel-devel-rt = 1-3 +kernel-rt-devel = 1-3 +-Req: ++Prv: +multiversion(kernel) +kernel-syms-rt = 1-3 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-rt 1 4 x86_64 ++Prv: +multiversion(kernel) +kernel-rt-1-4 +kernel = 1-4 +kernel-uname-r = 1-4-rt +kernel-rt = 1-4 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel 1 4 x86_64 ++Req: +kernel-devel-rt = 1-4 +-Req: ++Prv: +multiversion(kernel) +kernel-rt-devel = 1-4 +-Prv: ++Sup: +kernel-rt & kernel-devel-rt +-Sup: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel-debuginfo 1 4 x86_64 ++Prv: +kernel-rt-devel-debuginfo = 1-4 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-devel-rt 1 4 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel-rt = 1-4 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-syms-rt 1 4 x86_64 ++Req: +kernel-devel-rt = 1-4 +kernel-rt-devel = 1-4 +-Req: ++Prv: +multiversion(kernel) +kernel-syms-rt = 1-4 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 + +=Pkg: kernel-rt 1 5 x86_64 ++Prv: +multiversion(kernel) +kernel-rt-1-5 +kernel = 1-5 +kernel-uname-r = 1-5-rt +ksym(foobar) = abdcfee +kernel-rt = 1-5 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel 1 5 x86_64 ++Req: +kernel-devel-rt = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-rt-devel = 1-5 +-Prv: ++Sup: +kernel-rt & kernel-devel-rt +-Sup: +=Vnd: openSUSE + +=Pkg: kernel-rt-devel-debuginfo 1 5 x86_64 ++Prv: +kernel-rt-devel-debuginfo = 1-5 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-devel-rt 1 5 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel-rt = 1-5 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-syms-rt 1 5 x86_64 ++Req: +kernel-devel-rt = 1-5 +kernel-rt-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-syms-rt = 1-5 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 diff --git a/tests/zypp/data/PurgeKernels/flavour/zypp-control.yaml b/tests/zypp/data/PurgeKernels/flavour/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/flavour/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/PurgeKernels/kernel-base/@System.repo b/tests/zypp/data/PurgeKernels/kernel-base/@System.repo new file mode 100644 index 0000000..bd9dcd0 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/kernel-base/@System.repo @@ -0,0 +1,81 @@ +=Ver: 3.0 + +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-firmware - noarch ++Prv: +kernel-firmware = +-Prv: +=Vnd: openSUSE + +=Pkg: kernel-default-base 5.7.8 1.1.1.1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.8-1 +kernel = 5.7.8-1 +kernel-base = 5.7.8-1 +kernel-uname-r = 5.7.8-1-default +kernel-default-base = 5.7.8-1 +kernel-default-base = 5.7.8-1.1 +kernel-default-base = 5.7.8-1.1.1 +kernel-default-base = 5.7.8-1.1.1.1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-default-base 5.7.8 2.1.1.1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.8-2 +kernel = 5.7.8-2 +kernel-base = 5.7.8-2 +kernel-uname-r = 5.7.8-2-default +kernel-default-base = 5.7.8-2 +kernel-default-base = 5.7.8-2.1 +kernel-default-base = 5.7.8-2.1.1 +kernel-default-base = 5.7.8-2.1.1.1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-default-base 5.7.8 3.1.1.1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.7.8-3 +kernel = 5.7.8-3 +kernel-base = 5.7.8-3 +kernel-uname-r = 5.7.8-3-default +kernel-default-base = 5.7.8-3 +kernel-default-base = 5.7.8-3.1 +kernel-default-base = 5.7.8-3.1.1 +kernel-default-base = 5.7.8-3.1.1.1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE + +=Pkg: kernel-default-base 5.8.8 2.1.1.1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.8.8-1 +kernel = 5.8.8-1 +kernel-base = 5.8.8-1 +kernel-uname-r = 5.8.8-1-default +kernel-default-base = 5.8.8-1 +kernel-default-base = 5.8.8-1.1 +kernel-default-base = 5.8.8-1.1.1 +kernel-default-base = 5.8.8-1.1.1.1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE diff --git a/tests/zypp/data/PurgeKernels/kernel-base/zypp-control.yaml b/tests/zypp/data/PurgeKernels/kernel-base/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/kernel-base/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/PurgeKernels/rckrnl/@System.repo b/tests/zypp/data/PurgeKernels/rckrnl/@System.repo new file mode 100644 index 0000000..67b2e59 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/rckrnl/@System.repo @@ -0,0 +1,34 @@ +=Ver: 3.0 +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 5.13.rc7 16.1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.13.rc7-16.1 +kernel = 5.13.rc7-16.1 +kernel-uname-r = 5.13.0-rc7-16-default +kernel-default = 5.13.rc7-16.1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 5.13~rc7 17.1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.13~rc7-17.1 +kernel = 5.13~rc7-17.1 +kernel-uname-r = 5.13.0-rc7-17-default +kernel-default = 5.13~rc7-17.1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 5.13~rc7 18.1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-5.13~rc7-18.1 +kernel = 5.13~rc7-18.1 +kernel-uname-r = 5.13.0-rc7-18-default +kernel-default = 5.13~rc7-18.1 +-Prv: +=Vnd: openSUSE + diff --git a/tests/zypp/data/PurgeKernels/rckrnl/zypp-control.yaml b/tests/zypp/data/PurgeKernels/rckrnl/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/rckrnl/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/PurgeKernels/rebuild/@System.repo b/tests/zypp/data/PurgeKernels/rebuild/@System.repo new file mode 100644 index 0000000..a5da2ec --- /dev/null +++ b/tests/zypp/data/PurgeKernels/rebuild/@System.repo @@ -0,0 +1,86 @@ +=Ver: 3.0 +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-firmware - noarch ++Prv: +kernel-firmware = 20190312-lp151.2.3.1 +kernel-firmware = +-Prv: +=Pkg: kernel-macros 1 0 noarch ++Prv: +kernel-subpackage-macros +kernel-macros = 1-0 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 1.2 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-1 +kernel = 1-1 +kernel-default = 1-1 +kernel-default = 1-1.2 +kernel-uname-r = 1-1-default +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 1.2 x86_64 ++Req: +kernel-devel = 1-1.2 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-1.2 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 1.2 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-1.2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 1 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-1 +kernel-devel = 1-1.2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-source 1 1 noarch ++Req: +kernel-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-source = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-source 1 1.2 noarch ++Req: +kernel-devel = 1-1.2 +-Req: ++Prv: +multiversion(kernel) +kernel-source = 1-1.2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 1 x86_64 ++Req: +kernel-devel = 1-1 +kernel-default-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-1 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 diff --git a/tests/zypp/data/PurgeKernels/rebuild/zypp-control.yaml b/tests/zypp/data/PurgeKernels/rebuild/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/rebuild/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/PurgeKernels/simple/@System.repo b/tests/zypp/data/PurgeKernels/simple/@System.repo new file mode 100644 index 0000000..cc3ea03 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/simple/@System.repo @@ -0,0 +1,350 @@ +=Ver: 3.0 +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-firmware - noarch ++Prv: +kernel-firmware = 20190312-lp151.2.3.1 +kernel-firmware = +-Prv: +=Pkg: kernel-macros 1 0 noarch ++Prv: +kernel-subpackage-macros +kernel-macros = 1-0 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-1 +kernel = 1-1 +kernel-uname-r = 1-1-default +kernel-default = 1-1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 1 x86_64 ++Req: +kernel = 1-1 +-Req: ++Prv: +kernel-livepatch-default-1-1 +kernel-livepatch-default = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 1 x86_64 ++Req: +kernel-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-1 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 1 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 1 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-source 1 1 noarch ++Req: +kernel-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-source = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 1.2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-1 +kernel-devel = 1-1.2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-source 1 1.2 noarch ++Req: +kernel-devel = 1-1.2 +-Req: ++Prv: +multiversion(kernel) +kernel-source = 1-1 +kernel-source = 1-1.2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 1 x86_64 ++Req: +kernel-devel = 1-1 +kernel-default-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-1 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: kernel-default 1 2 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-2 +kernel = 1-2 +kernel-uname-r = 1-2-default +kernel-default = 1-2 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 2 x86_64 ++Req: +kernel = 1-2 +-Req: ++Prv: +kernel-livepatch-default-1-2 +kernel-livepatch-default = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 2 x86_64 ++Req: +kernel-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-2 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 2 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 2 x86_64 ++Req: +kernel-devel = 1-2 +kernel-default-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 3 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-3 +kernel = 1-3 +kernel-uname-r = 1-3-default +kernel-default = 1-3 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 3 x86_64 ++Req: +kernel-devel = 1-3 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-3 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 3.2 x86_64 ++Req: +kernel-devel = 1-3.2 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-3 +kernel-default-devel = 1-3.2 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-devel 1 3.2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-3 +kernel-devel = 1-3.2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-source 1 3.2 noarch ++Req: +kernel-devel = 1-3.2 +-Req: ++Prv: +multiversion(kernel) +kernel-source = 1-3 +kernel-source = 1-3.2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 3 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-3 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 3 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-3 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 3 x86_64 ++Req: +kernel-devel = 1-3 +kernel-default-devel = 1-3 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-3 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 4 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-4 +kernel = 1-4 +kernel-uname-r = 1-4-default +kernel-default = 1-4 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 4 x86_64 ++Req: +kernel-devel = 1-4 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-4 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 4 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-4 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 4 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-4 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 4 x86_64 ++Req: +kernel-devel = 1-4 +kernel-default-devel = 1-4 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-4 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: kernel-default 1 5 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-5 +kernel = 1-5 +kernel-uname-r = 1-5-default +ksym(foobar) = abdcfee +kernel-default = 1-5 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 5 x86_64 ++Req: +kernel-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-5 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 5 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 5 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 5 x86_64 ++Req: +kernel-devel = 1-5 +kernel-default-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-5 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: dummy-kmp-default 1 0 x86_64 ++Req: +kernel-default-devel +ksym(foobar) = abdcfee +-Req: ++Prv: +kmod(dummy) +dummy-kmp-default = 1-0 +-Prv: diff --git a/tests/zypp/data/PurgeKernels/simple/zypp-control.yaml b/tests/zypp/data/PurgeKernels/simple/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/simple/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/PurgeKernels/withdeps/@System.repo b/tests/zypp/data/PurgeKernels/withdeps/@System.repo new file mode 100644 index 0000000..d93fbdd --- /dev/null +++ b/tests/zypp/data/PurgeKernels/withdeps/@System.repo @@ -0,0 +1,223 @@ +=Ver: 3.0 +=Pkg: glibc 1 1 x86_64 ++Prv: +glibc = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-firmware - noarch ++Prv: +kernel-firmware = 20190312-lp151.2.3.1 +kernel-firmware = +-Prv: +=Pkg: kernel-macros 1 0 noarch ++Prv: +kernel-subpackage-macros +kernel-macros = 1-0 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 1 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-1 +kernel = 1-1 +kernel-uname-r = 1-1-default +kernel-default = 1-1 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 1 x86_64 ++Req: +kernel = 1-1 +-Req: ++Prv: +kernel-livepatch-default-1-1 +kernel-livepatch-default = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: foo 1 1 x86_64 ++Req: +kernel = 1-1 +-Req: ++Prv: +foo = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 1 x86_64 ++Req: +kernel-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-1 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 1 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 1 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-1 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 1 x86_64 ++Req: +kernel-devel = 1-1 +kernel-default-devel = 1-1 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-1 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: kernel-default 1 2 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-2 +kernel = 1-2 +kernel-uname-r = 1-2-default +kernel-default = 1-2 +-Prv: ++Rec: +kernel-firmware +-Rec: + +=Vnd: openSUSE +=Pkg: kernel-default-extra 1 2 x86_64 +=Sum: The Standard Kernel - Unsupported kernel modules ++Req: +kernel-default = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-extra = 1-2 +config(kernel-default-extra) = 1-2 +kernel-default-extra = 1-2 +kmod(a) +kmod(b) +ksym(c) +-Prv: + +=Vnd: openSUSE +=Pkg: kernel-livepatch-default 1 2 x86_64 ++Req: +kernel = 1-2 +-Req: ++Prv: +kernel-livepatch-default-1-2 +kernel-livepatch-default = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 2 x86_64 ++Req: +kernel-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-2 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 2 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 2 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 2 x86_64 ++Req: +kernel-devel = 1-2 +kernel-default-devel = 1-2 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-2 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-default 1 5 x86_64 ++Prv: +multiversion(kernel) +kernel-default-1-5 +kernel = 1-5 +kernel-uname-r = 1-5-default +ksym(foobar) = abdcfee +kernel-default = 1-5 +-Prv: ++Rec: +kernel-firmware +-Rec: +=Vnd: openSUSE +=Pkg: kernel-default-devel 1 5 x86_64 ++Req: +kernel-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-default-devel = 1-5 +-Prv: ++Sup: +kernel-default & kernel-devel +-Sup: +=Vnd: openSUSE +=Pkg: kernel-default-devel-debuginfo 1 5 x86_64 ++Prv: +kernel-default-devel-debuginfo = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-devel 1 5 noarch ++Req: +kernel-macros +-Req: ++Prv: +multiversion(kernel) +kernel-devel = 1-5 +-Prv: +=Vnd: openSUSE +=Pkg: kernel-syms 1 5 x86_64 ++Req: +kernel-devel = 1-5 +kernel-default-devel = 1-5 +-Req: ++Prv: +multiversion(kernel) +kernel-syms = 1-5 +-Prv: +=Vnd: openSUSE +=Tim: 1570603549 +=Pkg: dummy-kmp-default 1 0 x86_64 ++Req: +kernel-default-devel +ksym(foobar) = abdcfee +-Req: ++Prv: +kmod(dummy) +dummy-kmp-default = 1-0 +-Prv: +=Pkg: package-needing-krnlmodule 1 0 x86_64 ++Req: +dummy-kmp-default = 1-0 +-Req: ++Prv: +package-needing-krnlmodule = 1-0 +-Prv: diff --git a/tests/zypp/data/PurgeKernels/withdeps/zypp-control.yaml b/tests/zypp/data/PurgeKernels/withdeps/zypp-control.yaml new file mode 100644 index 0000000..e80c106 --- /dev/null +++ b/tests/zypp/data/PurgeKernels/withdeps/zypp-control.yaml @@ -0,0 +1,38 @@ +version: 1.0 +setup: + channels: + - alias: "@System" + url: [] + path: "" + type: NONE + generated: 0 + outdated: 0 + priority: 99 + file: "@System.repo" + arch: x86_64 + locales: + - fate: "" + name: en_US + - fate: "" + name: de + autoinst: + [] + modalias: + [] + multiversion: + [] + resolverFlags: + focus: Job + ignorealreadyrecommended: false + onlyRequires: false + forceResolve: false + cleandepsOnRemove: false + allowDowngrade: false + allowNameChange: false + allowArchChange: false + allowVendorChange: false + dupAllowDowngrade: false + dupAllowNameChange: false + dupAllowArchChange: false + dupAllowVendorChange: false +trials: [] diff --git a/tests/zypp/data/RepoManager/plugin-service-lib-1/services/service b/tests/zypp/data/RepoManager/plugin-service-lib-1/services/service new file mode 100755 index 0000000..a5bb647 --- /dev/null +++ b/tests/zypp/data/RepoManager/plugin-service-lib-1/services/service @@ -0,0 +1,13 @@ +#!/bin/bash +echo " +[repo1] +name=Repository1 +baseurl=http://somehost.com/repo1 +type=rpmmd + +[repo12] +name=Repository2 +baseurl=http://somehost.com/repo2 +type=rpmmd +" + diff --git a/tests/zypp/data/RepoManager/plugin-service-lib-2/services/service b/tests/zypp/data/RepoManager/plugin-service-lib-2/services/service new file mode 100755 index 0000000..97db399 --- /dev/null +++ b/tests/zypp/data/RepoManager/plugin-service-lib-2/services/service @@ -0,0 +1,8 @@ +#!/bin/sh +echo " +[repo3] +name=Repository3 +baseurl=http://somehost.com/repo3 +type=rpmmd +" + diff --git a/tests/zypp/data/RepoManager/proprietary.repo b/tests/zypp/data/RepoManager/proprietary.repo new file mode 100644 index 0000000..0392ffe --- /dev/null +++ b/tests/zypp/data/RepoManager/proprietary.repo @@ -0,0 +1,14 @@ +[macromedia] +name=Macromedia for i386 Linux +baseurl=http://macromedia.rediris.es/rpm/ +enabled=1 +gpgcheck=1 +gpgkey=http://macromedia.mplug.org/FEDORA-GPG-KEY + +[office] +name=Microsoft Office for Linux +baseurl=http://www.microsoft.com/linux/office +enabled=1 +gpgcheck=1 +gpgkey=http://www.microsoft.com/~sballmer/gpgkey.txt + diff --git a/tests/zypp/data/RepoManager/repo/repoindex.xml b/tests/zypp/data/RepoManager/repo/repoindex.xml new file mode 100644 index 0000000..06632c8 --- /dev/null +++ b/tests/zypp/data/RepoManager/repo/repoindex.xml @@ -0,0 +1,24 @@ + + + + + + + diff --git a/tests/zypp/data/RepoManager/repos.d/filesharing.repo b/tests/zypp/data/RepoManager/repos.d/filesharing.repo new file mode 100644 index 0000000..7571d48 --- /dev/null +++ b/tests/zypp/data/RepoManager/repos.d/filesharing.repo @@ -0,0 +1,7 @@ +[filesharing] +name=Filesharing applications (SUSE_Factory) +type=rpm-md +baseurl=http://software.opensuse.org/download/filesharing/SUSE_Factory/ +gpgcheck=1 +gpgkey=http://software.opensuse.org/openSUSE-Build-Service.asc +enabled=1 diff --git a/tests/zypp/data/RepoManager/repos.d/home:dmacvicar.repo b/tests/zypp/data/RepoManager/repos.d/home:dmacvicar.repo new file mode 100644 index 0000000..3a79b29 --- /dev/null +++ b/tests/zypp/data/RepoManager/repos.d/home:dmacvicar.repo @@ -0,0 +1,7 @@ +[home:dmacvicar] +name=Duncan Mac-Vicar SUSE rpms (openSUSE_Factory) +type=rpm-md +baseurl=http://software.opensuse.org/download/home:/dmacvicar/openSUSE_Factory/ +gpgcheck=1 +gpgkey=http://software.opensuse.org/openSUSE-Build-Service.asc +enabled=1 diff --git a/tests/zypp/data/RepoManager/repos.d/proprietary.repo b/tests/zypp/data/RepoManager/repos.d/proprietary.repo new file mode 100644 index 0000000..e78c242 --- /dev/null +++ b/tests/zypp/data/RepoManager/repos.d/proprietary.repo @@ -0,0 +1,5 @@ + +[adobe] +name=acrobat reader +baseurl=http://www.adobe.com/reader/linux + diff --git a/tests/zypp/data/RepoManager/repos.d/ruby.repo b/tests/zypp/data/RepoManager/repos.d/ruby.repo new file mode 100644 index 0000000..435ea1a --- /dev/null +++ b/tests/zypp/data/RepoManager/repos.d/ruby.repo @@ -0,0 +1,7 @@ +[ruby] +name=Ruby is an Interpreted Object-Oriented Scripting Language (openSUSE_Factory) +type=rpm-md +baseurl=http://software.opensuse.org/download/ruby/openSUSE_Factory/ +gpgcheck=1 +gpgkey=http://software.opensuse.org/openSUSE-Build-Service.asc +enabled=1 diff --git a/tests/zypp/data/RepoManager/second/repo/repoindex.xml b/tests/zypp/data/RepoManager/second/repo/repoindex.xml new file mode 100644 index 0000000..3e87256 --- /dev/null +++ b/tests/zypp/data/RepoManager/second/repo/repoindex.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/tests/zypp/data/RpmPkgSigCheck/no.rpm b/tests/zypp/data/RpmPkgSigCheck/no.rpm new file mode 100644 index 0000000..e69de29 diff --git a/tests/zypp/data/RpmPkgSigCheck/signed.key b/tests/zypp/data/RpmPkgSigCheck/signed.key new file mode 100644 index 0000000..5aa6ca0 --- /dev/null +++ b/tests/zypp/data/RpmPkgSigCheck/signed.key @@ -0,0 +1,19 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: rpm-4.11.2 (NSS-3) + +mQENBEkUTD8BCADWLy5d5IpJedHQQSXkC1VK/oAZlJEeBVpSZjMCn8LiHaI9Wq3G +3Vp6wvsP1b3kssJGzVFNctdXt5tjvOLxvrEfRJuGfqHTKILByqLzkeyWawbFNfSQ +93/8OunfSTXC1Sx3hgsNXQuOrNVKrDAQUqT620/jj94xNIg09bLSxsjN6EeTvyiO +mtE9H1J03o9tY6meNL/gcQhxBvwuo205np0JojYBP0pOfN8l9hnIOLkA0yu4ZXig +oKOVmf4iTjX4NImIWldT+UaWTO18NWcCrujtgHueytwYLBNV5N0oJIP2VYuLZfSD +VYuPllv7c6O2UEOXJsdbQaVuzU1HLocDyipnABEBAAG0NG9wZW5TVVNFIFByb2pl +Y3QgU2lnbmluZyBLZXkgPG9wZW5zdXNlQG9wZW5zdXNlLm9yZz6JATwEEwECACYC +GwMGCwkIBwMCBBUCCAMEFgIDAQIeAQIXgAUCU2dN1AUJHR8ElQAKCRC4iy/UPb3C +hGQrB/9teCZ3Nt8vHE0SC5NmYMAE1Spcjkzx6M4r4C70AVTMEQh/8BvgmwkKP/qI +CWo2vC1hMXRgLg/TnTtFDq7kW+mHsCXmf5OLh2qOWCKi55Vitlf6bmH7n+h34Sha +Ei8gAObSpZSF8BzPGl6v0QmEaGKM3O1oUbbB3Z8i6w21CTg7dbU5vGR8Yhi9rNtr +hqrPS+q2yftjNbsODagaOUb85ESfQGx/LqoMePD+7MqGpAXjKMZqsEDP0TbxTwSk +4UKnF4zFCYHPLK3y/hSH5SEJwwPY11l6JGdC1Ue8Zzaj7f//axUs/hTC0UZaEE+a +5v4gbqOcigKaFs9Lc3Bj8b/lE10Y +=i2TA +-----END PGP PUBLIC KEY BLOCK----- diff --git a/tests/zypp/data/RpmPkgSigCheck/signed.rpm b/tests/zypp/data/RpmPkgSigCheck/signed.rpm new file mode 100644 index 0000000000000000000000000000000000000000..410d968eb32efdf804f8416e11c8706a48a6c36e GIT binary patch literal 6932 zcmeHMdsGzH8Na)WiVt#7g4HPL`iRl!EHnF<-Q`HCNKgxvRUm?r;_N(@Ez9m^W`G53 z)8t?pFmkLmR!NK|8uJh$iJ@AnG{VUYr6KReA~fkDw4a81476JTqha6)Ar4QZnF4ndG)9No2x2u8315sI5Ylx4MnJQI z@XLVEpXL>~AzpVS#I?Htp?}?XfZ(sK2gLDL0l{DU37GYjnpoW^lsjkU*uxv+TN96+ zsL(`4kB&qK2H3WN-!y#uSsRtm@#oUxwS9LUyWY`w`llI8e&y0frfxr{c?G-29wQkttxIDV*Lx2CbTZUdJ{`^+QkM}B5 z4%nvFP3_m6i8|=i_tF!qdj7bP`)b$RbzP0Fm*igN^qWWO*;eMl8)eB)Y}a3VzkK&V z^4kqGyD0n1zSX~OkJvMN-_FM9r)uAOzOAm#Kl<_M+$Q13&8<84eO&YPFMjsK?Q3cg z?--4HBT6>fY_zeg-ONa|(a9Q3ywl8zjFGb$C9BB@ zn*rOg;J@vI$d4IfF4Z@rHcl%oxbf6?2bMLA-Er7mmz$e0{!DWHMC)HCHI$xAc2jQ+ zEfudkcRg*3KgT7MuX!|XZPmD2o$oYsdS}0||4)!}dz~_O4&Xe7~bL>B+^1@`TL!G>+pV|e{Vs6mpL@=oTd=R!9>tvsq@#pqPc8bu8@2Mu8|RmI-|kx< z_sI6Ix?8R`)YLxvc3%C;q{(J#UA2(E;wNjrnXoXX-}}YcH#R`IR z5g!3C5^j9mt+PQL4rvMh77%k>kHdCccf&lEa9nqT8Xx*0;XQ;W5#9?3bvP6t9M|P= zJg#Tp{=Nsq_6owU0b)DU^@8?3!e1x+2H|@N?Yfo(0kJ)k@W%*0PWW6v7+=#42;)WA z0AanFF2e1AI3DYW?Fk{SCHhCC0Ec+(WMa<-gm^9P7tbdL5aP8o;Z8v8p9F~e;|cF3 zTnKSpD&ZpG4#FkEGYIz(o<(>WAkH5bAmmugRzR4KE)cTE90i2==*a%Y93%W?Vs8Y* z{;v>z5)kIAdzJ8ufH-~&;gI2$!?dZsQ2DExKfXg3py*yxMI;Ei;_Dq z5<<+&mF%*4!TmBBXoHzzklDb(X#+<5v>1%RHe&`cb8=fhl{lxH^DdIzsw&DfUDa zezy+=%8&&GY-}EDrf_yrp_F6BR(qZ2PQF&Vsy6-S(Vyc_5{kSRiYY=xszlik%bJXW z1P1_Cn}kmbSSQEXSX$srCOgN&d4a@AG-H>XjMHK^+ngK&4lFN9tW^-L_Rtv<{N7RU ze`$Dla1pel2d!n6gY=G?W>TX65>M T7hgL&<@MAW_$|OlIcxp{AaC*6 literal 0 HcmV?d00001 diff --git a/tests/zypp/data/RpmPkgSigCheck/signed_broken.rpm b/tests/zypp/data/RpmPkgSigCheck/signed_broken.rpm new file mode 100644 index 0000000000000000000000000000000000000000..18ca2787318cdb3a57f89b67841e71bf5a7daf1d GIT binary patch literal 6933 zcmeHMdsGzH8Na)WiYPfK!D^IreZ**VmYIFb?s6nWB&dZ73Pey+oSnzAW!c@#46uN0 znjB06Mvm3SDv8lVV;({zF;r`nMo*4JbJ9Shk4ReuwGa_vq>73_zq@knv*S>iwsZ9`Ahldcy2fd*z9Dts6FFTpnBfp>N>ZEyFLAe15C*$9t8j z2W->orw!=NL>_eL`{+s4y?@-ueYI=ey6z_DOL8A``pqK^Y#Vdojq>Ctw(GCGU$J{I z`RzuUP0abSfAz0B!uHJBx3ekgsk--`Z?CWSjeUFuw@Em1bL-B1AJ=~Ui=RDl`22!hI2J>I(Cbk484nC|vPr%<0y-XWy+V*?9JF(HqhSyC=o?hibRC zD4m{nOeF(nlKvlf=Oi8SkAMYF?UXDk+p76gW2M9D^*jW(9Gn;D5VI#{ELcbHj`F>*GeWHlLK zGhjOw{$aXz{kB;X5U<8`f^7y6KK=#kwu* z)mgg^@hh`F?5L7&@A_r*_dD8>o?Lt=U&vZe;a1;2sCItzujbDRlk3mj`9u0#ncBVX z=$Q4{89R>p_s;yL)m&Kds}mP;iZ7b?v`imr=^r=DCS>S^Rr}L+P5yFIpSDA6O(|J) zrRzd+t9{|n`M<>ccI&PAzw;mZ=bm%t7Vhh_M{=k9=_vl$Q;8pVB3C|n5mF$eKuCd* z0wD!L3WO90DG*X1q(Df4kOCnELJIu9D-fu$jf{-=KnSRTA#`6IZXv0m{Rmz|9ZdH( z;v)ct!;P=IbvCHOAuZwG0%DHqaoCRQZkWdqj_Ynv<3m3ryqEAK!utTB4u|}NNKI1A-=DP-_g-Ark?i?in@>5Zki|e~j?sgwF$n@iiTQFkYAq z5Z0^dCfp8)`j2! z{}sYd0>XTCuM&O{5XWyJ{1PDcZ^L{Edaz!Npk9sc)vL2)&ZD?F)#ddlddVy6eH>rN zIYs?w6v~jjB`!f!^yug-Y?v5jR)lV9b~y}d zgL7$Vsi9B^y18ARVn6bDIhilGZ{ZKr=naa@8)RS6eRf>Pe~40?8}B2&!XYUl?!QNu zjG!C0%Q0_>x5y`piXsXrF1NUXD-xCYcWwAhvdbwd>b-XvT$$U;1)P;-T#1+=i;~Mf z8bZv=m7MbVf&DTWXoHzzklDb(X#+<5v>1$mHe&`cbMx9hl{kls^CZeHRTX8b#OqWI zf`};na*s=Oac;6dE?8@DXJ8x5EKM8jW>a9Dc&!ge6&Re7U^xop1mzYzPPHI`)>BSd zOL3Wgfl&jNW2}de|83g?Hlv7}6IcFH8w}9l_jj zxrGOkC+=?U#pB$I$GH~=y?6vp7UIly-e%=!!6fpM&0>;xBg5K6$s#yJiQ#Q5b#JqI zpUaE<<;a5kHa4F%Q#d=RV9GJ$Ydnr~Cts^uRhRzrsL$~y35DMa#T21pRibQ&Wlcsw zf&&1nO~R)Itb^lhEG=**lbz$?yg*_lnz2g`#$hp=Z4QnB2bLEl)+&frd+>}2e(xyo zzcey3lnCvpA!~Wg8pzX*!HI8a(M%2g_^EN1_MAr*DE2utHS!-}{Lbo}p0B&KUsOhR z`q%a}2({sIV~XP%j)!lzOo66S~6=6e8SCs`lSh#jpYWUS-F1x U#n;YGeLb}nehV;C?wW}I01{#G;{X5v literal 0 HcmV?d00001 diff --git a/tests/zypp/data/RpmPkgSigCheck/signed_broken_header.rpm b/tests/zypp/data/RpmPkgSigCheck/signed_broken_header.rpm new file mode 100644 index 0000000000000000000000000000000000000000..f7d09014e28d46ee7d03c193f3e583ec31d64366 GIT binary patch literal 6933 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 + + Novell + SUSE_SLES + 10 + 0 + i586 + sles + + sle-10-i586 + + special_edition + + A43242OOO + A cool distribution + Einfach genial + This is the coolest distribution on the world. + Try it out and find it useful. + Was soll man da sagen? + Einfach toll! + + da + de + + + http://www.suse.com/relnotes/i386/SLE/SERVER/11/release-notes-sles.rpm + http://foo + + + + af + + + + + diff --git a/tests/zypp/data/Vendor/vendors.d/ati b/tests/zypp/data/Vendor/vendors.d/ati new file mode 100644 index 0000000..57f8a7b --- /dev/null +++ b/tests/zypp/data/Vendor/vendors.d/ati @@ -0,0 +1,3 @@ +[main] + +vendors = ati,ati_new,ati_old \ No newline at end of file diff --git a/tests/zypp/data/Vendor/vendors.d/nvidia b/tests/zypp/data/Vendor/vendors.d/nvidia new file mode 100644 index 0000000..772ef16 --- /dev/null +++ b/tests/zypp/data/Vendor/vendors.d/nvidia @@ -0,0 +1,3 @@ +[main] + +vendors = nvidia,suse,old_suse \ No newline at end of file diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/dir/file1 b/tests/zypp/data/mediasetaccess/src1/cd1/dir/file1 new file mode 100644 index 0000000..55efc3e --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd1/dir/file1 @@ -0,0 +1 @@ +this is a file from dir diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/dir/file2 b/tests/zypp/data/mediasetaccess/src1/cd1/dir/file2 new file mode 100644 index 0000000..2ea4f1e --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd1/dir/file2 @@ -0,0 +1 @@ +Occifer! I'm not as think as you stoned I am! diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/dir/subdir/file b/tests/zypp/data/mediasetaccess/src1/cd1/dir/subdir/file new file mode 100644 index 0000000..edb5a3b --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd1/dir/subdir/file @@ -0,0 +1 @@ +this is a file from subdir diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt b/tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt new file mode 100644 index 0000000..87949e6 --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd1/dir/test-big.txt @@ -0,0 +1,15 @@ +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt b/tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt new file mode 100644 index 0000000..32a8037 --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd1/test-big.txt @@ -0,0 +1,29 @@ + + + + + 7135 + + 818dcbb0bbb033aa8b8c9ddd269648d2 + f69a3e53751eb3249c3c36c50290b8da + edf0cf52765c9b5cfeddfd83b62f8517b119ca77 + b0343a8ee06d97c9786b65bcb64c49fbb7e1d517159fac4633ba56f7a521fef0 + 202d21693dabe53ff5f2305d6b78844ffaa3b566b9644d61ca087cab752965b16d6a188def7a9463b5f17fdc50b3d105 + caf260dd5420a6a6df6a558eac69a901cd3e43dbfd37b54e0fb176940f3e09c3f96c7faa22e505777106ebf056c471be7556c8cba80331d6efdb9e763e66190b + 77fc06ff936163cfb6c1b0c68cb47a295a5bf8e3 + 2fcd624ba2ad1adb2ff23af58049b6f7b062754eadd031b1 + 011209ae + 818dcbb0bbb033aa8b8c9ddd269648d2 + + edf0cf52765c9b5cfeddfd83b62f8517b119ca77 + + + + http://localhost:10002/dir/test-big.txt + + + + diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/test.txt b/tests/zypp/data/mediasetaccess/src1/cd1/test.txt new file mode 100644 index 0000000..cf9a2f2 --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd1/test.txt @@ -0,0 +1 @@ +this is cd1 \ No newline at end of file diff --git a/tests/zypp/data/mediasetaccess/src1/cd1/x.media1 b/tests/zypp/data/mediasetaccess/src1/cd1/x.media1 new file mode 100644 index 0000000..e69de29 diff --git a/tests/zypp/data/mediasetaccess/src1/cd2/test.txt b/tests/zypp/data/mediasetaccess/src1/cd2/test.txt new file mode 100644 index 0000000..5687ff9 --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd2/test.txt @@ -0,0 +1 @@ +this is cd2 \ No newline at end of file diff --git a/tests/zypp/data/mediasetaccess/src1/cd2/x.mediabad b/tests/zypp/data/mediasetaccess/src1/cd2/x.mediabad new file mode 100644 index 0000000..deec169 --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd2/x.mediabad @@ -0,0 +1 @@ +.media2 would identify the cd2 correctly \ No newline at end of file diff --git a/tests/zypp/data/mediasetaccess/src1/cd3/test.txt b/tests/zypp/data/mediasetaccess/src1/cd3/test.txt new file mode 100644 index 0000000..6e7f9b2 --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src1/cd3/test.txt @@ -0,0 +1 @@ +this is cd3 \ No newline at end of file diff --git a/tests/zypp/data/mediasetaccess/src1/cd3/x.media3 b/tests/zypp/data/mediasetaccess/src1/cd3/x.media3 new file mode 100644 index 0000000..e69de29 diff --git a/tests/zypp/data/mediasetaccess/src2/test.txt b/tests/zypp/data/mediasetaccess/src2/test.txt new file mode 100644 index 0000000..bd99b59 --- /dev/null +++ b/tests/zypp/data/mediasetaccess/src2/test.txt @@ -0,0 +1 @@ +this is a single media \ No newline at end of file diff --git a/tests/zypp/data/mediasetaccess/src2/x.media b/tests/zypp/data/mediasetaccess/src2/x.media new file mode 100644 index 0000000..e69de29 diff --git a/tests/zyppng/CMakeLists.txt b/tests/zyppng/CMakeLists.txt new file mode 100644 index 0000000..8bb0e47 --- /dev/null +++ b/tests/zyppng/CMakeLists.txt @@ -0,0 +1,10 @@ +ADD_TESTS( + EventLoop + IOBuffer + UnixSignalSource + Pipelines +) + +ADD_SUBDIRECTORY( media ) +ADD_SUBDIRECTORY( io ) +ADD_SUBDIRECTORY( rpc ) diff --git a/tests/zyppng/EventLoop_test.cc b/tests/zyppng/EventLoop_test.cc new file mode 100644 index 0000000..c92cf34 --- /dev/null +++ b/tests/zyppng/EventLoop_test.cc @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include + +#include + +BOOST_AUTO_TEST_CASE(eventloop) +{ + zyppng::EventLoop::Ptr loop = zyppng::EventLoop::create(); + + //we should hit that timer first + zyppng::Timer::Ptr t1 = zyppng::Timer::create(); + + //second hit + zyppng::Timer::Ptr t2 = zyppng::Timer::create(); + + //this in theory would be the 2nd hit but is cleaned up by t1 before that + zyppng::Timer::Ptr t3 = zyppng::Timer::create(); + + //this is a singleshot timer, it should just hit once + zyppng::Timer::Ptr t4 = zyppng::Timer::create(); + + int hitT1 = 0; + int hitT2 = 0; + int hitT4 = 0; + int executedIdle = 0; + int executedIdleOnce = 0; + + t1->sigExpired().connect( [ &hitT1, &t3 ]( zyppng::Timer & ) { + hitT1++; + t3.reset(); + }); + + t2->sigExpired().connect( [ &hitT1, &hitT2, &loop ]( zyppng::Timer & ){ + BOOST_REQUIRE_GT( hitT1, 0 ); + hitT2++; + if ( hitT2 >= 3 ) + loop->quit(); + }); + + t3->sigExpired().connect( [ ]( zyppng::Timer & ){ + BOOST_TEST( false ); + }); + + t4->setSingleShot( true ); + t4->sigExpired().connect( [ &hitT4 ]( zyppng::Timer & ){ + hitT4++; + + //timer deviation should not be too big, can only be tested on a singleShot timer + // ma: disabled as OBS builder have quite big deviation >15 + // BOOST_REQUIRE_LE( t.now() - t.expires(), 3 ); + }); + + //convenience function to execute a function later + zyppng::EventDispatcher::invokeOnIdle( [ &executedIdle](){ executedIdle++; return ( executedIdle < 2 );} ); + + zyppng::EventDispatcher::invokeOnIdle( [ &executedIdleOnce ](){ executedIdleOnce++; return false;} ); + + t1->start( 10 ); + t3->start( 13 ); + t2->start( 15 ); + t4->start( 2 ); + + loop->run(); + + BOOST_REQUIRE_EQUAL( executedIdle, 2 ); + BOOST_REQUIRE_EQUAL( executedIdleOnce, 1 ); + BOOST_REQUIRE_GE ( hitT1, 3 ); + BOOST_REQUIRE_EQUAL( hitT2, 3 ); + BOOST_REQUIRE_EQUAL( hitT4, 1 ); + + t1->stop(); + t2->stop(); + + BOOST_REQUIRE_EQUAL( loop->eventDispatcher()->runningTimers(), 0 ); +} + +BOOST_AUTO_TEST_CASE(createTimerWithoutEV) +{ + BOOST_CHECK_THROW( zyppng::Timer::create(), zypp::Exception); +} + +BOOST_AUTO_TEST_CASE(checkcleanup) +{ + zyppng::EventLoop::Ptr loop = zyppng::EventLoop::create(); + BOOST_REQUIRE_EQUAL( loop->eventDispatcher().get(), zyppng::EventDispatcher::instance().get() ); + + //explicit cleanup + loop.reset(); + BOOST_REQUIRE_EQUAL( static_cast(nullptr), zyppng::EventDispatcher::instance().get() ); + + //implicit cleanup + { + zyppng::EventLoop::create(); + BOOST_REQUIRE_EQUAL( static_cast(nullptr), zyppng::EventDispatcher::instance().get() ); + } +} diff --git a/tests/zyppng/IOBuffer_test.cc b/tests/zyppng/IOBuffer_test.cc new file mode 100644 index 0000000..a97e802 --- /dev/null +++ b/tests/zyppng/IOBuffer_test.cc @@ -0,0 +1,174 @@ +#include +#include +#include + +BOOST_AUTO_TEST_CASE(iobuf) +{ + zyppng::IOBuffer buf ( 10 ); + + zyppng::ByteArray t("Hello World"); + + buf.append( t ); + buf.append( zyppng::ByteArray(" it's a great day!") ); + + + zyppng::ByteArray rbuf( 30, '\0' ); + + BOOST_REQUIRE_EQUAL( buf.size(), 29); + BOOST_REQUIRE_EQUAL( buf.chunks(), 2); + + buf.read( rbuf.data(), 5 ); + BOOST_REQUIRE_EQUAL( std::string_view(rbuf.data()), "Hello" ); + BOOST_REQUIRE_EQUAL( buf.size(), 24); + BOOST_REQUIRE_EQUAL( buf.chunks(), 2); + + buf.read( rbuf.data()+5, 6); + BOOST_REQUIRE_EQUAL( std::string_view(rbuf.data()), "Hello World" ); + BOOST_REQUIRE_EQUAL( buf.size(), 18); + BOOST_REQUIRE_EQUAL( buf.chunks(), 1); + + buf.read( rbuf.data()+11, 18 ); + BOOST_REQUIRE_EQUAL( std::string_view(rbuf.data()), "Hello World it's a great day!" ); + BOOST_REQUIRE_EQUAL( buf.size(), 0); + BOOST_REQUIRE_EQUAL( buf.chunks(), 0); +} + + +BOOST_AUTO_TEST_CASE(iobuf_reserve_and_discard) +{ + zyppng::IOBuffer buf; + buf.reserve( 1234 ); + BOOST_REQUIRE_EQUAL( buf.size(), 1234); + BOOST_REQUIRE_EQUAL( buf.chunks(), 1); + buf.discard( 1234 ); + BOOST_REQUIRE_EQUAL( buf.size(), 0); + BOOST_REQUIRE_EQUAL( buf.chunks(), 0); +} + +BOOST_AUTO_TEST_CASE(iobuf_readtoomuch) +{ + zyppng::IOBuffer buf; + buf.append( zyppng::ByteArray("Short Text") ); + BOOST_REQUIRE_EQUAL( buf.size(), 10); + + zyppng::ByteArray rbuf( 15, '\0' ); + const auto read = buf.read( rbuf.data(), rbuf.size() ); + BOOST_REQUIRE_EQUAL( read, 10 ); + BOOST_REQUIRE_EQUAL( std::string_view(rbuf.data()), "Short Text" ); + BOOST_REQUIRE_EQUAL( buf.size(), 0); +} + +BOOST_AUTO_TEST_CASE(iobuf_reserve_small) +{ + zyppng::IOBuffer buf( 20 ); + buf.append( zyppng::ByteArray("1234567890") ); + buf.append( zyppng::ByteArray("1234567890") ); + BOOST_REQUIRE_EQUAL( buf.chunks(), 1); + buf.append( zyppng::ByteArray("1234567890") ); + BOOST_REQUIRE_EQUAL( buf.chunks(), 2); +} + + +BOOST_AUTO_TEST_CASE(iobuf_indexof) +{ + zyppng::IOBuffer buf(10); + /*|-Chunk1-|*/ + buf.append( zyppng::ByteArray("1234567890") ); + /*|--Chunk2-|*/ + buf.append( zyppng::ByteArray("\n23456\n89a") ); + /*|-Chunk3-|*/ + buf.append( zyppng::ByteArray("9876543210") ); + + BOOST_REQUIRE_EQUAL( buf.chunks(), 3); + BOOST_REQUIRE_EQUAL( buf.indexOf('\n'), 10 ); + BOOST_REQUIRE_EQUAL( buf.indexOf('\n', buf.size(), 10), 10 ); + BOOST_REQUIRE_EQUAL( buf.indexOf('\n', buf.size(), 11), 16 ); + BOOST_REQUIRE_EQUAL( buf.indexOf('\n', buf.size(), 17), -1 ); + BOOST_REQUIRE_EQUAL( buf.indexOf('a', buf.size(), 12), 19 ); +} + +//shamelessly adapted from Qt +BOOST_AUTO_TEST_CASE(iobuf_indexof_progression) +{ + zyppng::IOBuffer buf(16); + for ( int i = 1; i <= 256; i++ ) { + buf.append( zyppng::ByteArray({char(i)})); + } + + for (int i = 16; i < 256; ++i) { + auto index = buf.indexOf(char(i)); + BOOST_REQUIRE_EQUAL(index, (i - 1)); + BOOST_REQUIRE_EQUAL(buf.indexOf(char(i), i, i >> 1), index); + BOOST_REQUIRE_EQUAL(buf.indexOf(char(i), 256, i), -1); + BOOST_REQUIRE_EQUAL(buf.indexOf(char(i), i - 1), -1); // test for absent char + } +} + +BOOST_AUTO_TEST_CASE(reserveAndRead) +{ + zyppng::IOBuffer buf; + // fill buffer with an arithmetic progression + for (int i = 1; i < 256; ++i) { + zyppng::ByteArray ba(i, char(i)); + char *ringPos = buf.reserve( i ); + BOOST_REQUIRE(ringPos); + memcpy(ringPos, ba.data(), i); + } + // readback and check stored data + for (int i = 1; i < 256; ++i) { + zyppng::ByteArray ba; + ba.resize(i); + int64_t thisRead = buf.read(ba.data(), i); + BOOST_REQUIRE_EQUAL(thisRead, int64_t(i)); + BOOST_REQUIRE_EQUAL(std::count( ba.begin(), ba.end(), char(i)), i); + } + BOOST_REQUIRE_EQUAL(buf.size(), 0); +} + +BOOST_AUTO_TEST_CASE(readline) +{ + zyppng::IOBuffer buf(10); + + zyppng::ByteArray b1("Hello World\n"); + buf.append( b1 ); + zyppng::ByteArray b2("Another\n"); + buf.append( b2 ); + zyppng::ByteArray b3("1234\n"); + buf.append( b3 ); + zyppng::ByteArray b4("6789\n"); + buf.append( b4 ); + + BOOST_REQUIRE( buf.canReadLine() ); + + auto r1 = buf.readLine( 5 ); + BOOST_REQUIRE_EQUAL( r1.size(), 0 ); + r1 = buf.readLine(); + BOOST_REQUIRE_EQUAL( std::string_view( r1.data(), r1.size() ), std::string_view(b1.data(), b1.size()) ); + r1 = buf.readLine(); + BOOST_REQUIRE_EQUAL( std::string_view( r1.data(), r1.size() ), std::string_view(b2.data(), b2.size()) ); + r1 = buf.readLine(); + BOOST_REQUIRE_EQUAL( std::string_view( r1.data(), r1.size() ), std::string_view(b3.data(), b3.size()) ); + r1 = buf.readLine( 5 ); + BOOST_REQUIRE_EQUAL( std::string_view( r1.data(), r1.size() ), std::string_view(b4.data(), b4.size()) ); + +} + +BOOST_AUTO_TEST_CASE(move) +{ + zyppng::IOBuffer buf(10); + + zyppng::ByteArray b1("Hello World\n"); + buf.append( b1 ); + zyppng::ByteArray b2("Another\n"); + buf.append( b2 ); + zyppng::ByteArray b3("1234\n"); + buf.append( b3 ); + zyppng::ByteArray b4("6789\n"); + buf.append( b4 ); + + const auto size = buf.size(); + zyppng::IOBuffer buf2( std::move( buf ) ); + + BOOST_REQUIRE_EQUAL( size, buf2.size() ); + +} diff --git a/tests/zyppng/Pipelines_test.cc b/tests/zyppng/Pipelines_test.cc new file mode 100644 index 0000000..3ff7164 --- /dev/null +++ b/tests/zyppng/Pipelines_test.cc @@ -0,0 +1,380 @@ +#include +#include +#include +#include +#include + +using namespace zyppng; + +template +class DelayedValue : public AsyncOp +{ +public: + DelayedValue( T &&value ) { + _timer = zyppng::Timer::create(); + _timer->setSingleShot ( true ); + _timer->sigExpired().connect([this, value = std::move(value) ]( zyppng::Timer & ) mutable { + this->setReady( std::move(value) ); + }); + _timer->start ( 10 ); + } +private: + zyppng::TimerRef _timer; +}; + + +template +class DelayedOp : public AsyncOp> +{ +public: + void operator()( T &&in ) + { + _timer = zyppng::Timer::create(); + _timer->setSingleShot ( true ); + _timer->sigExpired().connect([this, forwardArg = std::move(in)]( zyppng::Timer & ) mutable { + this->setReady( std::invoke( outFunc, std::move(forwardArg))); + }); + _timer->start ( 0 ); + } +private: + zyppng::TimerRef _timer; +}; + +// we can not use primitive types with operator| +struct Int { + Int( int val ) : value(val) {} + + bool operator== ( const Int &other ) const { return value == other.value; } + + int value; +}; + +Int addFive ( Int &&in ) +{ + in.value += 5; + return in; +} + +Int toSignedInt ( std::string &&in ) { + return Int{ std::stoi( in ) }; +} + +std::string toString ( Int &&in ) +{ + return std::to_string(in.value); +} + +// simple sync pipeline, returning the value directly +BOOST_AUTO_TEST_CASE(simplesyncpipe) +{ + using namespace zyppng::operators; + BOOST_CHECK_EQUAL( std::string("10"), ( std::string("5") | &toSignedInt | &addFive | &toString ) ); +} + +BOOST_AUTO_TEST_CASE( syncToAsyncPipeline ) +{ + using namespace zyppng::operators; + + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + auto op = std::string("5") + | std::make_shared>() + | std::make_shared>() + | std::make_shared>() + | [&]( auto && res ){ + BOOST_CHECK_EQUAL ( std::string("10") , res ); + ev->quit (); + return res; + }; + BOOST_CHECK ( !op->isReady () ); + ev->run(); +} + +BOOST_AUTO_TEST_CASE( asyncToAsyncPipeline ) +{ + using namespace zyppng::operators; + + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + + auto op = std::make_shared>("5") + | std::make_shared>() + | std::make_shared>() + | std::make_shared>() + | [&]( auto && res ){ + BOOST_CHECK_EQUAL ( std::string("10") , res ); + ev->quit (); + return res; + }; + BOOST_CHECK ( !op->isReady () ); + ev->run(); +} + +BOOST_AUTO_TEST_CASE( syncToMixedPipeline ) +{ + using namespace zyppng::operators; + + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + auto op = std::string("5") + | std::make_shared>() + | &addFive + | &toString + | [&]( auto && res ){ + BOOST_CHECK_EQUAL ( std::string("10") , res ); + ev->quit (); + return res; + }; + BOOST_CHECK ( !op->isReady () ); + ev->run(); +} + +BOOST_AUTO_TEST_CASE( asyncToMixedPipeline ) +{ + using namespace zyppng::operators; + + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + + auto op = zyppng::AsyncOpRef(std::make_shared>("5")) + | &toSignedInt + | std::make_shared>() + | &toString + | [&]( auto && res ){ + BOOST_CHECK_EQUAL ( std::string("10") , res ); + ev->quit (); + return res; + }; + BOOST_CHECK ( !op->isReady () ); + ev->run(); +} + +BOOST_AUTO_TEST_CASE( asyncToMixedPipelineWithIndirectAsyncCB ) +{ + using namespace zyppng::operators; + + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + + auto op = zyppng::AsyncOpRef(std::make_shared>("5")) + | &toSignedInt + | []( auto &&in ){ in.value += 5; return std::make_shared>(std::move(in)); } + | &toString + | [&]( auto && res ){ + BOOST_CHECK_EQUAL ( std::string("10") , res ); + ev->quit (); + return res; + }; + BOOST_CHECK ( !op->isReady () ); + ev->run(); +} + +BOOST_AUTO_TEST_CASE( asyncToMixedPipelineWithIndirectAsyncCBInStdFunction ) +{ + using namespace zyppng::operators; + + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + + const auto &makePipeline = [&](){ + + const std::function< AsyncOpRef( Int && ) > &addFiveAsync = []( auto &&in ){ in.value += 5; return std::make_shared>(std::move(in)); }; + + return zyppng::AsyncOpRef(std::make_shared>("5")) + | &toSignedInt + | addFiveAsync + | &toString + | [&]( auto && res ){ + BOOST_CHECK_EQUAL ( std::string("10") , res ); + ev->quit (); + return res; + }; + }; + + auto op = makePipeline(); + BOOST_CHECK ( !op->isReady () ); + ev->run(); +} + +BOOST_AUTO_TEST_CASE( syncTransform ) +{ + using namespace zyppng::operators; + std::vector input{ 0, 10, 20 }; + auto res = std::vector(input) | transform( &addFive ); + static_assert( std::is_same_v, decltype(res)> ); + BOOST_CHECK_EQUAL ( res.size(), 3 ); + BOOST_CHECK_EQUAL ( res[0].value, 5 ); + BOOST_CHECK_EQUAL ( res[1].value, 15 ); + BOOST_CHECK_EQUAL ( res[2].value, 25 ); +} + +BOOST_AUTO_TEST_CASE( asyncTransform ) +{ + using namespace zyppng::operators; + + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + + std::vector input{ 0, 10, 20 }; + auto res = std::vector(input) | transform( []( auto &&in ){ in.value += 5; return std::make_shared>(std::move(in)); } ); + static_assert( std::is_same_v>, decltype(res)> ); + BOOST_CHECK ( !res->isReady () ); + + res->onReady ([&]( std::vector &&res ){ + BOOST_CHECK_EQUAL ( res.size(), 3 ); + BOOST_CHECK_EQUAL ( res[0].value, 5 ); + BOOST_CHECK_EQUAL ( res[1].value, 15 ); + BOOST_CHECK_EQUAL ( res[2].value, 25 ); + ev->quit(); + }); +} + +//------------------- Code following here is a compile time test, if it compiles it works as intended ------------------------------------ + +template +class TestAsyncOp : public AsyncOp +{ +public: + void operator()( In && ){} +}; + +int f1Global ( int &&test ){ + return test; +}; + +template +auto f2Global ( T &&test ) { + return AsyncOpRef>(); +}; + +// using fake lambdas here because it seems to be impossible to use real ones in decltype() +struct FakeLambda +{ + int operator()( int &&arg ) { + return arg; + } +}; + +struct FakeLambda2 +{ + template + auto operator()( T &&arg ) { + return arg; + } +}; + +struct FakeLambdaAsync +{ + AsyncOpRef operator()( int &&arg ) { + return AsyncOpRef(); + } +}; + +struct FakeLambdaAsync2 +{ + template + auto operator()( T &&arg ) { + return f2Global(std::move(arg)); + } +}; + +void compiletimeTest () +{ + const auto &makeSyncCallback = []() { + return [](int &&test) { + return test; + }; + }; + + const auto &makeASyncCallback = []() { + return [](int &&test) { + return AsyncOpRef(); + }; + }; + + const auto &f1 = []( int &&test ){ + return test; + }; + const auto &f2 = []( int &&test ) { + return AsyncOpRef(); + }; + + const auto &f1Auto = []( auto &&test ){ + return test; + }; + const auto &f2Auto = []( auto &&test ) { + return AsyncOpRef>(); + }; + + static_assert( detail::is_async_op_v> ); + static_assert( detail::is_async_op_v> ); + static_assert( detail::has_value_type_v> ); + static_assert( detail::is_future_monad_cb_v, int > ); + static_assert( !detail::is_sync_monad_cb_v, int > ); + static_assert( detail::is_sync_monad_cb_v ); + static_assert( !detail::is_future_monad_cb_v ); + static_assert( detail::is_sync_monad_cb_v ); + static_assert( !detail::is_future_monad_cb_v ); + static_assert( !detail::is_future_monad_cb_v > ); + static_assert( !detail::callback_returns_async_op::value ); + static_assert( detail::callback_returns_async_op::value ); + static_assert( detail::is_sync_monad_cb_with_sync_res_v ); + static_assert( !detail::is_sync_monad_cb_with_sync_res_v ); + static_assert( detail::is_sync_monad_cb_with_sync_res_v ); + static_assert( !detail::is_sync_monad_cb_with_sync_res_v ); + static_assert( !detail::is_sync_monad_cb_with_sync_res_v, int> ); + static_assert( !std::conditional_t< detail::is_async_op_v>, std::false_type, std::detected_or_t> >::value ); + + using namespace zyppng::operators; + + // case async -> async + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval>() | std::declval>>() )> ); + + // case sync -> async + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval() | std::declval>>() )> ); + + // case sync -> sync returning a sync value + static_assert( std::is_same_v< int, decltype( std::declval() | f1 )> ); + + // case sync -> generic sync returning a sync value + static_assert( std::is_same_v< int, decltype( std::declval() | f1Auto )> ); + + // case sync -> sync returning a async value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval() | f2 )> ); + + // case sync -> generic sync returning a async value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval() | f2Auto )> ); + + // case sync -> sync returning a sync value , not supported by C++: operator| must have an argument of class or enumerated type + // static_assert( std::is_same_v< int, decltype( std::declval() | std::declval() )> ); + + // case sync -> lambda returning a sync value + static_assert( std::is_same_v< int, decltype( std::declval() | std::declval() )> ); + + // case sync -> generic lambda returning a sync value + static_assert( std::is_same_v< int, decltype( std::declval() | std::declval() )> ); + + // case sync -> lambda returning a async value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval() | std::declval() )> ); + + // case sync -> generic lambda returning a async value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval() | std::declval() )> ); + + // case sync -> sync lambda returned by a function + static_assert( std::is_same_v< int, decltype( std::declval() | makeSyncCallback() ) > ); + + // case async -> sync lambda returned by a function + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval< AsyncOpRef >() | makeSyncCallback() ) > ); + + // case sync -> sync returning a sync value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval>() | &f1Global )> ); + + // case sync -> lambda returning a sync value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval>() | std::declval() )> ); + + // case sync -> generic lambda returning a sync value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval>() | std::declval() )> ); + + // case sync -> lambda returning a async value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval>() | std::declval() )> ); + + // case sync -> generic lambda returning a async value + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval>() | std::declval() )> ); + + // case asyng -> sync lambda with async res returned by a function + static_assert( std::is_same_v< AsyncOpRef, decltype( std::declval< AsyncOpRef >() | makeASyncCallback() ) > ); + +} diff --git a/tests/zyppng/UnixSignalSource_test.cc b/tests/zyppng/UnixSignalSource_test.cc new file mode 100644 index 0000000..863df62 --- /dev/null +++ b/tests/zyppng/UnixSignalSource_test.cc @@ -0,0 +1,141 @@ +#include +#include +#include +#include +#include + +#include + +BOOST_AUTO_TEST_CASE(signalCatcher) +{ + { + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + zyppng::TimerRef secTimer = zyppng::Timer::create(); + secTimer->setSingleShot (true); + secTimer->sigExpired ().connect ([&]( auto &){ + ev->quit (); + }); + + auto sigSource = ev->eventDispatcher ()->unixSignalSource (); + + int receivedSig = -1; + sigSource->sigReceived ().connect ( [&]( int signum ) { + receivedSig = signum; + ev->quit (); + }); + + sigSource->addSignal ( SIGALRM ); + sigSource->addSignal ( SIGINT ); + + // send alarm to our process + alarm(1); + secTimer->start ( 5000 ); + ev->run(); + + BOOST_CHECK_EQUAL( receivedSig, SIGALRM ); + + sigSource->removeSignal ( SIGALRM ); + + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 0 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 1 ); + } + + //after cleaning the event loop the sigmask should be normal again + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 0 ); +} + + +BOOST_AUTO_TEST_CASE(signalCleanup) +{ + + { + zyppng::EventLoopRef ev = zyppng::EventLoop::create(); + auto sigSource = ev->eventDispatcher ()->unixSignalSource (); + + { + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 0 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 0 ); + } + + sigSource->addSignal ( SIGINT ); + sigSource->addSignal ( SIGINT ); + sigSource->addSignal ( SIGINT ); + + { + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 0 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 1 ); + } + + + sigSource->removeSignal ( SIGINT ); + { + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 0 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 1 ); + } + + sigSource->removeSignal ( SIGINT ); + { + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 0 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 1 ); + } + + sigSource->removeSignal ( SIGINT ); + { + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 0 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 0 ); + } + + sigSource->addSignal ( SIGALRM ); + sigSource->addSignal ( SIGALRM ); + sigSource->addSignal ( SIGINT ); + sigSource->addSignal ( SIGINT ); + + { + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 1 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 1 ); + } + + } + + { + sigset_t siset; + ::sigemptyset ( &siset ); + ::pthread_sigmask ( SIG_SETMASK, nullptr, &siset ); + + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGALRM ), 0 ); + BOOST_CHECK_EQUAL( ::sigismember( &siset, SIGINT ), 0 ); + } + +} diff --git a/tests/zyppng/data/downloader/auth-http.meta b/tests/zyppng/data/downloader/auth-http.meta new file mode 100644 index 0000000..ff4b829 --- /dev/null +++ b/tests/zyppng/data/downloader/auth-http.meta @@ -0,0 +1,36 @@ + + + + + 2148018 + + 7e562d52c100b68e9d6a561fa8519575 + 52cabd59ecb55096447322ca99364d50094997a0 + + 9916af41e079f5758d62f7bae3d74d8c5f0557c1 + 852e21a1e914971c0544253e5d8f853b181b13b1 + f4cff1a07588a9ea22d8c193f75988fb00c45306 + c4ef102565900f4f6669ab8596bedcb1ea6f1451 + 3cf13de7699c8a97e0334b4c5a1982f28d297f0a + 489f0546839a4cd49e0eee1738953b327bbb4bf4 + d5739177bc6adf319988055388d20dc0908aec27 + a29de2657b5bbfb9da52d44858fd41eb09d972e8 + 496bdfb70ed41fa5d98ae7d94843206f2578c328 + + + + http://localhost:10001/handler/test.txt + http://localhost:10001/handler/test.txt + http://localhost:10001/handler/test.txt + http://localhost:10001/handler/test.txt + http://localhost:10001/handler/test.txt + http://localhost:10001/handler/test.txt + http://localhost:10001/handler/test.txt + http://localhost:10001/handler/test.txt + + + + diff --git a/tests/zyppng/data/downloader/auth-https.meta b/tests/zyppng/data/downloader/auth-https.meta new file mode 100644 index 0000000..131fee7 --- /dev/null +++ b/tests/zyppng/data/downloader/auth-https.meta @@ -0,0 +1,36 @@ + + + + + 2148018 + + 7e562d52c100b68e9d6a561fa8519575 + 52cabd59ecb55096447322ca99364d50094997a0 + + 9916af41e079f5758d62f7bae3d74d8c5f0557c1 + 852e21a1e914971c0544253e5d8f853b181b13b1 + f4cff1a07588a9ea22d8c193f75988fb00c45306 + c4ef102565900f4f6669ab8596bedcb1ea6f1451 + 3cf13de7699c8a97e0334b4c5a1982f28d297f0a + 489f0546839a4cd49e0eee1738953b327bbb4bf4 + d5739177bc6adf319988055388d20dc0908aec27 + a29de2657b5bbfb9da52d44858fd41eb09d972e8 + 496bdfb70ed41fa5d98ae7d94843206f2578c328 + + + + https://localhost:10001/handler/test.txt + https://localhost:10001/handler/test.txt + https://localhost:10001/handler/test.txt + https://localhost:10001/handler/test.txt + https://localhost:10001/handler/test.txt + https://localhost:10001/handler/test.txt + https://localhost:10001/handler/test.txt + https://localhost:10001/handler/test.txt + + + + diff --git a/tests/zyppng/data/downloader/media.1/media b/tests/zyppng/data/downloader/media.1/media new file mode 100644 index 0000000..c5c8305 --- /dev/null +++ b/tests/zyppng/data/downloader/media.1/media @@ -0,0 +1,3 @@ +openSUSE - openSUSE-15.0-x86_64-Build267.2-Media +openSUSE-15.0-x86_64-Build267.2 +1 diff --git a/tests/zyppng/data/downloader/primary-deltatemplate.xml.zck b/tests/zyppng/data/downloader/primary-deltatemplate.xml.zck new file mode 100644 index 0000000000000000000000000000000000000000..84e21a553a9d7806375d20b462d1ce1615377724 GIT binary patch literal 274659 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

`EzCVk3Pc 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

)*bNCB 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 T@!*RcK2!`V+}(9WAl3f>VI=*r literal 0 HcmV?d00001 diff --git a/tests/zyppng/data/downloader/primary.xml.zck.meta b/tests/zyppng/data/downloader/primary.xml.zck.meta new file mode 100644 index 0000000..2b953ff --- /dev/null +++ b/tests/zyppng/data/downloader/primary.xml.zck.meta @@ -0,0 +1,22 @@ + + + + + 274638 + + e5b4a4abe414f4d71ab4074605b05c09 + 22d7d67a9f7dd879906c58842973957dc4fe506a + + 2f13f8abd8501a05a66e4b9dd70e7af5b3977bb8 + 836b510886ff38a29d344ffa629087be134d1053 + + + + %1% + + + + diff --git a/tests/zyppng/data/downloader/test.txt b/tests/zyppng/data/downloader/test.txt new file mode 100644 index 0000000..983777d --- /dev/null +++ b/tests/zyppng/data/downloader/test.txt @@ -0,0 +1,7595 @@ +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodoLorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. + +Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi. + +Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum. Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. + +Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis. + +At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, At accusam aliquyam diam diam dolore dolores duo eirmod eos erat, et nonumy sed tempor et et invidunt justo labore Stet clita ea et gubergren, kasd magna no rebum. sanctus sea sed takimata ut vero voluptua. est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat. + +Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus. + +Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diff --git a/tests/zyppng/data/downloader/test.txt.meta b/tests/zyppng/data/downloader/test.txt.meta new file mode 100644 index 0000000..2bd0215 --- /dev/null +++ b/tests/zyppng/data/downloader/test.txt.meta @@ -0,0 +1,29 @@ + + + + + 2148018 + + 7e562d52c100b68e9d6a561fa8519575 + 52cabd59ecb55096447322ca99364d50094997a0 + + 9916af41e079f5758d62f7bae3d74d8c5f0557c1 + 852e21a1e914971c0544253e5d8f853b181b13b1 + f4cff1a07588a9ea22d8c193f75988fb00c45306 + c4ef102565900f4f6669ab8596bedcb1ea6f1451 + 3cf13de7699c8a97e0334b4c5a1982f28d297f0a + 489f0546839a4cd49e0eee1738953b327bbb4bf4 + d5739177bc6adf319988055388d20dc0908aec27 + a29de2657b5bbfb9da52d44858fd41eb09d972e8 + 496bdfb70ed41fa5d98ae7d94843206f2578c328 + + + + %1% + + + + diff --git a/tests/zyppng/data/downloader/test_noblock.txt.meta b/tests/zyppng/data/downloader/test_noblock.txt.meta new file mode 100644 index 0000000..68d319c --- /dev/null +++ b/tests/zyppng/data/downloader/test_noblock.txt.meta @@ -0,0 +1,18 @@ + + + + + 2148018 + + 7e562d52c100b68e9d6a561fa8519575 + 52cabd59ecb55096447322ca99364d50094997a0 + + + %1% + + + + diff --git a/tests/zyppng/data/process/echo.sh b/tests/zyppng/data/process/echo.sh new file mode 100755 index 0000000..7648676 --- /dev/null +++ b/tests/zyppng/data/process/echo.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +#just read from the predefined fd (3) until we get a single q and echo everything else to the predefined write fd (4) + +while read -u 3 -r line +do + if [ "$line" == "q" ] + then + printf "Byt Bye" >&2; + exit 0 + fi + + echo "$line" >&4 + echo "Received line $line" >&2 +done +exit 123 diff --git a/tests/zyppng/data/provide/cd1/file1 b/tests/zyppng/data/provide/cd1/file1 new file mode 100644 index 0000000..4d9a9eb --- /dev/null +++ b/tests/zyppng/data/provide/cd1/file1 @@ -0,0 +1 @@ +Medium File 1 diff --git a/tests/zyppng/data/provide/cd1/media.1/media b/tests/zyppng/data/provide/cd1/media.1/media new file mode 100644 index 0000000..564a9ef --- /dev/null +++ b/tests/zyppng/data/provide/cd1/media.1/media @@ -0,0 +1,3 @@ +openSUSE - Testmedium +openSUSE-15.0-x86_64-Build267.2 +4 diff --git a/tests/zyppng/data/provide/cd2/file2 b/tests/zyppng/data/provide/cd2/file2 new file mode 100644 index 0000000..e0626c3 --- /dev/null +++ b/tests/zyppng/data/provide/cd2/file2 @@ -0,0 +1 @@ +Medium File 2 diff --git a/tests/zyppng/data/provide/cd2/media.2/media b/tests/zyppng/data/provide/cd2/media.2/media new file mode 100644 index 0000000..564a9ef --- /dev/null +++ b/tests/zyppng/data/provide/cd2/media.2/media @@ -0,0 +1,3 @@ +openSUSE - Testmedium +openSUSE-15.0-x86_64-Build267.2 +4 diff --git a/tests/zyppng/data/provide/cd3/file3 b/tests/zyppng/data/provide/cd3/file3 new file mode 100644 index 0000000..06cd67e --- /dev/null +++ b/tests/zyppng/data/provide/cd3/file3 @@ -0,0 +1 @@ +Medium File 3 diff --git a/tests/zyppng/data/provide/cd3/media.3/media b/tests/zyppng/data/provide/cd3/media.3/media new file mode 100644 index 0000000..564a9ef --- /dev/null +++ b/tests/zyppng/data/provide/cd3/media.3/media @@ -0,0 +1,3 @@ +openSUSE - Testmedium +openSUSE-15.0-x86_64-Build267.2 +4 diff --git a/tests/zyppng/data/provide/cd4/file4 b/tests/zyppng/data/provide/cd4/file4 new file mode 100644 index 0000000..33948c1 --- /dev/null +++ b/tests/zyppng/data/provide/cd4/file4 @@ -0,0 +1 @@ +Medium File 4 diff --git a/tests/zyppng/data/provide/cd4/media.4/media b/tests/zyppng/data/provide/cd4/media.4/media new file mode 100644 index 0000000..564a9ef --- /dev/null +++ b/tests/zyppng/data/provide/cd4/media.4/media @@ -0,0 +1,3 @@ +openSUSE - Testmedium +openSUSE-15.0-x86_64-Build267.2 +4 diff --git a/tests/zyppng/io/AsyncDataSource_test.cc b/tests/zyppng/io/AsyncDataSource_test.cc new file mode 100644 index 0000000..cda9cad --- /dev/null +++ b/tests/zyppng/io/AsyncDataSource_test.cc @@ -0,0 +1,386 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +BOOST_AUTO_TEST_CASE ( pipe_read_close ) +{ + std::string_view text ("Hello from thread"); + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + bool gotReadChanFinished = false; + bool gotClosed = false; + zypp::ByteArray readData; + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->readFdOpen() ); + + const auto &readAllData = [&](){ + zypp::ByteArray d = dataSource->readAll(); + readData.insert( readData.end(), d.begin(), d.end() ); + }; + + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, readAllData ); + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadFdClosed, [&]( auto, auto ){ + gotClosed = true; + readAllData(); + loop->quit(); + }); + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadChannelFinished, [&]( uint channel ){ + if ( channel == 0 ) { + BOOST_REQUIRE ( !gotReadChanFinished ); + gotReadChanFinished = true; + } + }); + + std::thread writer( []( int writeFd, std::string_view text ){ + ::write( writeFd, text.data(), text.length() ); + ::close( writeFd ); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + + BOOST_REQUIRE ( !dataSource->readFdOpen() ); + + ::close( pipeFds[0] ); + BOOST_REQUIRE_EQUAL( std::string_view( readData.data(), readData.size() ), text ); + BOOST_REQUIRE ( gotReadChanFinished ); + BOOST_REQUIRE ( gotClosed ); +} + +// basically the same as above, but we break the receiving socket by closing the read end +// during a readAll call. +BOOST_AUTO_TEST_CASE ( pipe_read_close2 ) +{ + std::string_view text ("Hello again"); + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + std::mutex lock; + std::condition_variable cv; + bool written = false; + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + bool gotReadChanFinished = false; + bool gotClosed = false; + zypp::ByteArray readData; + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + + const auto &readAllData = [&](){ + zypp::ByteArray d = dataSource->readAll(); + readData.insert( readData.end(), d.begin(), d.end() ); + }; + + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, [&]() { + std::unique_lock l(lock); + if ( !written ){ + cv.wait(l, [&](){ return written; }); + } + + // close the pipe here, breaking the receiving socket + ::close( pipeFds[1] ); + readAllData(); + } ); + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadFdClosed, [&]( auto, auto ){ + gotClosed = true; + readAllData(); + loop->quit(); + }); + + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadChannelFinished, [&]( uint channel ){ + if ( channel == 0 ) { + BOOST_REQUIRE ( !gotReadChanFinished ); + gotReadChanFinished = true; + } + }); + + std::thread writer( [&lock, &written, &cv]( int writeFd, std::string_view text ){ + { + std::unique_lock l(lock); + ::write( writeFd, text.data(), text.length() ); + written = true; + } + cv.notify_all(); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + + ::close( pipeFds[0] ); + BOOST_REQUIRE_EQUAL( std::string_view( readData.data(), readData.size() ), text ); + BOOST_REQUIRE ( gotReadChanFinished ); + BOOST_REQUIRE ( gotClosed ); +} + + +BOOST_AUTO_TEST_CASE ( pipe_write_close ) +{ + std::string_view text ("Hello from main"); + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSink = zyppng::AsyncDataSource::create(); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 3000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + BOOST_REQUIRE( dataSink->openFds( {}, pipeFds[1] ) ); + BOOST_REQUIRE( dataSink->canWrite() ); + + int64_t bytesWritten = 0; + dataSink->connectFunc( &zyppng::AsyncDataSource::sigBytesWritten, [&]( int64_t bytes ){ + bytesWritten += bytes; + if ( std::size_t(bytesWritten) == text.size() ) + loop->quit(); + + }); + + zypp::ByteArray readData; + std::thread reader( [ &readData ]( int readFd, std::string_view text ) { + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + if ( !dataSource->openFds( { readFd } ) ) + return; + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadyRead, [&](){ + zypp::ByteArray d = dataSource->readAll(); + readData.insert( readData.end(), d.begin(), d.end() ); + if ( readData.size() == text.length() ) + loop->quit(); + }); + + loop->run(); + ::close( readFd ); + + }, pipeFds[0], text ); + + BOOST_REQUIRE_EQUAL( dataSink->write( text.data(), text.length() ), text.length() ); + + loop->run(); + reader.join(); + + ::close( pipeFds[1] ); + BOOST_REQUIRE_EQUAL( std::string_view( readData.data(), readData.size() ), text ); +} + +BOOST_AUTO_TEST_CASE ( pipe_close ) +{ + std::string_view text ("Hello from main"); + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSink = zyppng::AsyncDataSource::create(); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 3000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + bool gotClosed = false; + + BOOST_REQUIRE( dataSink->openFds( {}, pipeFds[1] ) ); + BOOST_REQUIRE( dataSink->canWrite() ); + + int64_t bytesWritten = 0; + dataSink->connectFunc( &zyppng::AsyncDataSource::sigBytesWritten, [&]( int64_t bytes ){ + bytesWritten += bytes; + }); + + dataSink->sigWriteFdClosed().connect([&]( auto ){ + gotClosed = true; + loop->quit(); + }); + + // we close the pipe before the loop even has a chance writing to it + ::close( pipeFds[0] ); + + BOOST_REQUIRE_EQUAL( dataSink->write( text.data(), text.length() ), text.length() ); + + loop->run(); + ::close( pipeFds[1] ); + + BOOST_REQUIRE ( gotClosed ); +} + +BOOST_AUTO_TEST_CASE ( multichannel ) +{ + std::string_view text[] = { "Hello to channel1", "Hello to channel2 with more bytes" }; + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + int pipe2Fds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipe2Fds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSink = zyppng::AsyncDataSource::create(); + auto dataSink2 = zyppng::AsyncDataSource::create(); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 10000 ); + + bool timeout = false; + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + timeout = true; + loop->quit(); + }); + + BOOST_REQUIRE( dataSink->openFds( {}, pipeFds[1] ) ); + BOOST_REQUIRE( dataSink->canWrite() ); + + BOOST_REQUIRE( dataSink2->openFds( {}, pipe2Fds[1] ) ); + BOOST_REQUIRE( dataSink2->canWrite() ); + + int64_t bytesWritten = 0; + dataSink->connectFunc( &zyppng::AsyncDataSource::sigBytesWritten, [&]( int64_t bytes ){ + bytesWritten += bytes; + }); + + int64_t bytesWritten2 = 0; + dataSink2->connectFunc( &zyppng::AsyncDataSource::sigBytesWritten, [&]( int64_t bytes ){ + bytesWritten2 += bytes; + }); + + bool dataSink1ABW = false; + dataSink->connectFunc( &zyppng::AsyncDataSource::sigAllBytesWritten, [&]( ){ + dataSink1ABW = true; + }); + + bool dataSink2ABW = false; + dataSink2->connectFunc( &zyppng::AsyncDataSource::sigAllBytesWritten, [&]( ){ + dataSink2ABW = true; + }); + + auto dataReceiver = zyppng::AsyncDataSource::create(); + BOOST_REQUIRE( dataReceiver->openFds( { pipeFds[0], pipe2Fds[0] }, -1 ) ); + BOOST_REQUIRE( dataReceiver->canRead() ); + BOOST_REQUIRE_EQUAL( dataReceiver->readChannelCount(), 2 ); + BOOST_REQUIRE_EQUAL( dataReceiver->currentReadChannel(), 0 ); + + zypp::ByteArray dataRecv[2]; + + dataReceiver->connectFunc( &zyppng::AsyncDataSource::sigChannelReadyRead, [&]( auto channel ) { + dataReceiver->setReadChannel( channel ); + BOOST_REQUIRE_EQUAL( dataReceiver->currentReadChannel(), channel ); + zypp::ByteArray d = dataReceiver->readAll(); + dataRecv[channel].insert( dataRecv[channel].end(), d.begin(), d.end() ); + if ( dataRecv[0].size() > 0 && dataRecv[0].size() == text[0].size() + && dataRecv[1].size() > 0 && dataRecv[1].size() == text[1].size() ) + loop->quit(); + }); + + bool bytesPushed = false; + loop->eventDispatcher()->invokeOnIdle( [ & ](){ + dataSink->write( text[0].data(), text[0].size() ); + dataSink2->write( text[1].data(), text[1].size() ); + bytesPushed = true; + return false; + }); + + loop->run(); + + BOOST_REQUIRE( !timeout ); + BOOST_REQUIRE( dataSink1ABW ); + BOOST_REQUIRE( dataSink2ABW ); + BOOST_REQUIRE_EQUAL( bytesWritten, text[0].size() ); + BOOST_REQUIRE_EQUAL( bytesWritten2, text[1].size() ); + BOOST_REQUIRE_EQUAL( text[0], std::string_view( dataRecv[0].data(), dataRecv[0].size() ) ); + BOOST_REQUIRE_EQUAL( text[1], std::string_view( dataRecv[1].data(), dataRecv[1].size() ) ); +} + +BOOST_AUTO_TEST_CASE ( readl ) +{ + std::string_view text[] = { "Hello\n", "World\n", "123456" }; + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 3000 ); + + bool timeout = false; + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + timeout = true; + }); + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + + dataSource->setReadChannel( 0 ); + dataSource->sigReadyRead ().connect([&](){ + // now write more data without returning to the ev loop, and check if we get it all + ::write( pipeFds[1], text[1].data(), text[1].size() ); + ::write( pipeFds[1], text[2].data(), text[2].size() ); + + auto ba = dataSource->readLine(); + BOOST_REQUIRE_EQUAL( text[0], std::string_view( ba.data(), ba.size() ) ); + ba = dataSource->readLine( text[1].size () + 1 ); // trigger code path with fixed size + BOOST_REQUIRE_EQUAL( text[1], std::string_view( ba.data(), ba.size() ) ); + ba = dataSource->readLine(); + BOOST_REQUIRE_EQUAL( text[2], std::string_view( ba.data(), ba.size() ) ); + loop->quit(); + }); + + //write the first line + ::write( pipeFds[1], text[0].data(), text[0].size() ); + + loop->run(); + + BOOST_REQUIRE( !timeout ); + +} diff --git a/tests/zyppng/io/CMakeLists.txt b/tests/zyppng/io/CMakeLists.txt new file mode 100644 index 0000000..f326520 --- /dev/null +++ b/tests/zyppng/io/CMakeLists.txt @@ -0,0 +1,5 @@ +ADD_TESTS( + UnixSocket + AsyncDataSource + Process +) diff --git a/tests/zyppng/io/Process_test.cc b/tests/zyppng/io/Process_test.cc new file mode 100644 index 0000000..1ad5b37 --- /dev/null +++ b/tests/zyppng/io/Process_test.cc @@ -0,0 +1,368 @@ +#include "TestSetup.h" +#include "TestTools.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define BOOST_TEST_MODULE ExternalProgram +#define DATADIR (Pathname(TESTS_SRC_DIR) + "/zyppng/data/process") + +using zypp::ExternalProgram; + +BOOST_AUTO_TEST_CASE( Basic ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"Hello\";sleep 1;echo \"I'm the second line\";exit 123;", + nullptr + }; + + auto ev = zyppng::EventLoop::create(); + auto proc = zyppng::Process::create(); + + bool gotStarted = false; + proc->connectFunc( &zyppng::Process::sigStarted, [&](){ + gotStarted = true; + }); + + int exitCode = -1; + bool gotFinished = false; + proc->connectFunc( &zyppng::Process::sigFinished, [&]( int status ){ + gotFinished = true; + exitCode = status; + ev->quit(); + }); + + bool gotFailedToStart = false; + proc->connectFunc( &zyppng::Process::sigFailedToStart, [&]( ){ + gotFailedToStart = true; + ev->quit(); + }); + + BOOST_REQUIRE( proc->start( argv ) ); + BOOST_REQUIRE( proc->isRunning() ); + + const auto pid = proc->pid(); + BOOST_REQUIRE ( pid != -1 ); + + ev->run(); + + BOOST_REQUIRE( gotStarted ); + BOOST_REQUIRE( gotFinished ); + BOOST_REQUIRE_EQUAL( exitCode, 123 ); + BOOST_REQUIRE( !gotFailedToStart ); + + proc->setReadChannel( zyppng::Process::StdOut ); + BOOST_REQUIRE( proc->bytesAvailable( ) ); + + auto data = proc->readLine(); + BOOST_REQUIRE_EQUAL( data.asStringView(), std::string_view("Hello\n") ); + + data = proc->readLine(); + BOOST_REQUIRE_EQUAL( data.asStringView(), std::string_view("I'm the second line\n") ); + + BOOST_REQUIRE( !proc->isRunning() ); + BOOST_REQUIRE_EQUAL( proc->exitStatus(), 123 ); + + BOOST_REQUIRE_LT ( ::getpgid( pid ) , 0 ); +} + +BOOST_AUTO_TEST_CASE( InvalidExec ) +{ + const char *argv[] = { + "./NoSuchFileHere", + nullptr + }; + + auto ev = zyppng::EventLoop::create(); + auto proc = zyppng::Process::create(); + + bool gotStarted = false; + proc->connectFunc( &zyppng::Process::sigStarted, [&](){ + gotStarted = true; + }); + + int exitCode = -1; + bool gotFinished = false; + proc->connectFunc( &zyppng::Process::sigFinished, [&]( int status ){ + gotFinished = true; + exitCode = status; + }); + + bool gotFailedToStart = false; + proc->connectFunc( &zyppng::Process::sigFailedToStart, [&]( ){ + gotFailedToStart = true; + }); + + BOOST_REQUIRE( !proc->start( argv ) ); + BOOST_REQUIRE( !proc->isRunning() ); + + BOOST_REQUIRE( !gotStarted ); + BOOST_REQUIRE( !gotFinished ); + BOOST_REQUIRE( gotFailedToStart ); + BOOST_REQUIRE_EQUAL( proc->exitStatus(), 129 ); +} + +/* + * This tests a special feature where we move arbitrary fds into the new process for special use + */ +BOOST_AUTO_TEST_CASE( mapExtraFD ) +{ + auto pipeA = zyppng::Pipe::create( ); + auto pipeB = zyppng::Pipe::create( ); + + BOOST_REQUIRE( pipeA ); + BOOST_REQUIRE( pipeB ); + + auto ev = zyppng::EventLoop::create(); + auto proc = zyppng::Process::create(); + + // we have one pipe we want to write to, so the process can receive data + proc->addFd( pipeA->readFd ); + // and another one the process uses to talk to us + proc->addFd( pipeB->writeFd ); + + auto dataSource = zyppng::AsyncDataSource::create(); + BOOST_REQUIRE( dataSource->openFds( { pipeB->readFd }, pipeA->writeFd ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->canWrite( ) ); + + proc->connectFunc( &zyppng::Process::sigStarted, [&](){ + + // once the process has been started close the ends of the pipes we gave to the process + pipeA->unrefRead(); + pipeB->unrefWrite(); + + // write some data + BOOST_REQUIRE( dataSource->write( zypp::ByteArray("Hello") ) ); + BOOST_REQUIRE( dataSource->write( zypp::ByteArray(" my friend\n" ) ) ); + BOOST_REQUIRE( dataSource->write( zypp::ByteArray("How are you today\n" ) ) ); + BOOST_REQUIRE( dataSource->write( zypp::ByteArray("q\n" ) ) ); + + }); + + ByteArray bytesRead; + const auto &readAllData = [&](){ + const auto &data = dataSource->readAll(); + bytesRead.insert( bytesRead.end(), data.begin(), data.end() ); + }; + + dataSource->sigReadyRead().connect( [&](){ + readAllData(); + }); + + int exitCode = -1; + bool gotFinished = false; + proc->connectFunc( &zyppng::Process::sigFinished, [&]( int status ){ + gotFinished = true; + exitCode = status; + ev->quit(); + }); + + const auto executable = DATADIR/"echo.sh"; + const char *argv[] = { + executable.c_str(), + nullptr + }; + + BOOST_REQUIRE( proc->start( argv ) ); + BOOST_REQUIRE( proc->isRunning() ); + + ev->run(); + + BOOST_REQUIRE_EQUAL ( exitCode, 0 ); + BOOST_REQUIRE ( gotFinished ); + + if ( dataSource->bytesAvailable() ) + readAllData(); + + BOOST_REQUIRE_EQUAL( zypp::ByteArray("Hello my friend\nHow are you today\n"), bytesRead ); + + +} + +#if 0 +BOOST_AUTO_TEST_CASE( StderrToStdout ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"Hello\";sleep 1;echo \"I'm the second line\" >&2;", + nullptr + }; + ExternalProgram proc( argv, ExternalProgram::Stderr_To_Stdout ); + BOOST_CHECK( proc.running() ); + BOOST_REQUIRE ( proc.getpid() != -1 ); + std::string line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("Hello\n") ); + line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("I'm the second line\n") ); + proc.close(); + BOOST_REQUIRE( !proc.running() ); + BOOST_REQUIRE_EQUAL( proc.getpid(), -1 ); +} + +BOOST_AUTO_TEST_CASE( SetEnv ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"${ZYPPENV}\"", + nullptr + }; + ExternalProgram proc( argv, ExternalProgram::Environment{ std::make_pair("ZYPPENV", "Hello from env") }, ExternalProgram::Normal_Stderr ); + std::string line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("Hello from env\n") ); + proc.close(); +} + +// environment of the parent has to be in the child process as well +// some code paths rely on that +BOOST_AUTO_TEST_CASE( ParentEnv ) +{ + const char *argv[] = { + "bash", + "-c", + "echo \"${PARENTENV}${ZYPPENV}\"", + nullptr + }; + + setenv( "PARENTENV", "Hello from", 0 ); + + ExternalProgram proc( argv, ExternalProgram::Environment{ std::make_pair("ZYPPENV", " env") }, ExternalProgram::Normal_Stderr ); + std::string line = proc.receiveLine(); + BOOST_REQUIRE_EQUAL( line, std::string("Hello from env\n") ); + proc.close(); + + unsetenv( "PARENTENV" ); +} + +// weird feature to redirect stdout and stderr +BOOST_AUTO_TEST_CASE( RedirectStdoutAndStderrWithChdir ) +{ + zypp::filesystem::TmpDir dir; + + const zypp::Pathname stdoutPath( dir.path()/"stdout" ); + const zypp::Pathname stderrPath( dir.path()/"stderr" ); + + const std::string stdoutRedir( zypp::str::form(">%s", stdoutPath.c_str() ) ); + const std::string chDir( zypp::str::form("#%s", dir.path().c_str() ) ); + zypp::AutoFD stdErrRedir( ::open( stderrPath.c_str() , O_CREAT | O_RDWR, 0666 ) ); + + BOOST_REQUIRE( *stdErrRedir != -1 ); + + const char *argv[] = { + chDir.c_str(), + stdoutRedir.c_str(), + "bash", + "-c", + "echo \"Hello on stdout\";echo \"Hello on stderr\" >&2;echo \"Hello on file in chdir\" > chdirfile", + nullptr + }; + + ExternalProgram proc (argv, ExternalProgram::Stderr_To_FileDesc, false, *stdErrRedir ); + + int exitCode = proc.close(); + BOOST_REQUIRE( !proc.running() ); + BOOST_REQUIRE_EQUAL( exitCode, 0 ); + + ::close( *stdErrRedir ); + *stdErrRedir = -1; + + BOOST_REQUIRE_EQUAL( TestTools::readFile( stdoutPath ), "Hello on stdout\n"); + BOOST_REQUIRE_EQUAL( TestTools::readFile( stderrPath ), "Hello on stderr\n"); + BOOST_REQUIRE_EQUAL( TestTools::readFile( dir.path() / "chdirfile" ), "Hello on file in chdir\n"); +} + +BOOST_AUTO_TEST_CASE( LongRunningEcho ) +{ + const auto executable = DATADIR/"echo.sh"; + const char *argv[] = { + executable.c_str(), + nullptr + }; + + ExternalProgram proc (argv, ExternalProgram::Normal_Stderr ); + BOOST_REQUIRE( proc.running() ); + BOOST_REQUIRE( proc.send( "Hello" ) ); + BOOST_REQUIRE( proc.send( " my friend\n" ) ); + BOOST_REQUIRE( proc.send( "How are you today\n" ) ); + BOOST_REQUIRE_EQUAL( proc.receiveLine(), "Hello my friend\n" ); + BOOST_REQUIRE_EQUAL( proc.receiveLine(), "How are you today\n" ); + + BOOST_REQUIRE( proc.running() ); + BOOST_REQUIRE( proc.send( "q\n" ) ); + const auto res = proc.close(); + BOOST_REQUIRE_EQUAL( res, 0 ); +} + +BOOST_AUTO_TEST_CASE( SendSignal ) +{ + const auto executable = DATADIR/"echo.sh"; + const char *argv[] = { + executable.c_str(), + nullptr + }; + + ExternalProgram proc (argv, ExternalProgram::Normal_Stderr ); + BOOST_REQUIRE( proc.running() ); + proc.kill( SIGTERM ); + const auto exitCode = proc.close(); + BOOST_REQUIRE_EQUAL( exitCode, SIGTERM+128 ); +} + +BOOST_AUTO_TEST_CASE( CleanerThread_default ) +{ + pid_t pid = -1; + { + ExternalProgram proc( "bash -c 'sleep 2'", ExternalProgram::Normal_Stderr ); + BOOST_CHECK( proc.running() ); + pid = proc.getpid(); + } + std::this_thread::sleep_for( std::chrono::seconds(4) ); + // check if the process is really gone, can't use waitpid because some ExternalProgram + // implementations do spawn processes from a helper thread which means they are not our direct children + BOOST_CHECK_EQUAL( ::getpgid( pid ), -1 ); + BOOST_CHECK_EQUAL( errno, ESRCH ); +} + +BOOST_AUTO_TEST_CASE( ReadTimeout ) +{ + static const char* argv[] = { "sleep", "2", NULL }; + ExternalProgram prog( argv, ExternalProgram::Discard_Stderr ); + BOOST_CHECK_THROW( prog.receiveLine( 100 ), io::TimeoutException ); + BOOST_CHECK_EQUAL( prog.receiveLine( 3000 ), "" ); + BOOST_CHECK_EQUAL( prog.close(), 0 ); +} + +BOOST_AUTO_TEST_CASE( CloseFDs ) +{ + // simple bash script that counts the number of open fds, 4 is the minimum since ls opens one fd to read the /proc/self/fd + std::string_view script ( "if [ $( ls /proc/self/fd | wc -l ) -gt \"4\" ]; then exit 1; fi; exit 0" ); + + const char *argv[] = { + "bash", + "-c", + script.data(), + nullptr + }; + + // open random fds we definitely can read to get higher nr of fds + zypp::AutoFD testFD( ::open( "/proc/self/fd", O_RDONLY ) ); + zypp::AutoFD testFD2( ::open( "/proc/self/fd", O_RDONLY ) ); + + ExternalProgram proc( argv, ExternalProgram::Discard_Stderr ); + const auto exitCode = proc.close(); + BOOST_REQUIRE_EQUAL( exitCode, 0 ); +} +#endif diff --git a/tests/zyppng/io/UnixSocket_test.cc b/tests/zyppng/io/UnixSocket_test.cc new file mode 100644 index 0000000..898dc46 --- /dev/null +++ b/tests/zyppng/io/UnixSocket_test.cc @@ -0,0 +1,416 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +BOOST_AUTO_TEST_CASE ( lorem ) +{ + + const std::string payloadT = + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " + "sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem " + "ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore " + "magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata " + "sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut " + "labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, " + "no sea takimata sanctus est Lorem ipsum dolor sit amet."; + + // make sure we get over the OS buffers + std::string payload; + for ( int i = 0; i < 700; i++ ) { + payload += payloadT; + } + + auto ev = zyppng::EventLoop::create(); + auto listeningSock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto error = zyppng::Socket::NoError; + + int64_t bytesWritten = 0; + zyppng::ByteArray dataReceived; //< This is where the thread will write the data + + auto addr = std::make_shared( "socktest", true ); + BOOST_REQUIRE( listeningSock->bind( addr ) ); + BOOST_REQUIRE( listeningSock->listen() ); + BOOST_REQUIRE_EQUAL( listeningSock->state(), zyppng::Socket::ListeningState ); + + zyppng::Socket::Ptr connection; + + listeningSock->sigIncomingConnection().connect( [&](){ + connection = listeningSock->accept(); + BOOST_REQUIRE_EQUAL( connection->state(), zyppng::Socket::ConnectedState ); + + connection->sigError().connect([&]( const auto err ){ + if ( err == zyppng::Socket::ConnectionDelayed ) + return; + error = err; + ev->quit(); + }); + + connection->sigDisconnected().connect( [&](){ + BOOST_REQUIRE_EQUAL( connection->state(), zyppng::Socket::ClosedState ); + ev->quit(); + }); + + connection->sigBytesWritten().connect( [&]( const auto bytes ){ + bytesWritten += bytes; + }); + + connection->write( payload.data(), payload.size() ); + }); + + std::thread clientThread( [ payload, &dataReceived ](){ + auto ev = zyppng::EventLoop::create(); + auto sock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto timer = zyppng::Timer::create(); + + bool timedOut = false; + bool gotConnected = false; + bool gotDisconnected = false; + bool gotReadChanFinished = false; + auto error = zyppng::Socket::NoError; + + sock->sigError().connect( [&]( const zyppng::Socket::SocketError err ){ + if ( err == zyppng::Socket::ConnectionDelayed ) + return; + error = err; + ev->quit(); + }); + + sock->sigConnected().connect( [&](){ + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ConnectedState ); + gotConnected = true; + }); + + sock->sigDisconnected().connect( [&](){ + gotDisconnected = true; + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ClosedState ); + ev->quit(); + }); + + sock->sigReadChannelFinished().connect( [&]( uint chan ){ + gotReadChanFinished = true; + BOOST_REQUIRE_EQUAL( chan, 0 ); + }); + + sock->sigReadyRead().connect([&](){ + const auto bA = sock->bytesAvailable(); + auto all = sock->readAll(); + + std::cout << "Received" << std::endl; + + dataReceived.insert( dataReceived.end(), all.begin(), all.end() ); + BOOST_REQUIRE_GE( all.size(), bA ); + + if ( dataReceived.size() == payload.length() ) { + std::string_view rec( dataReceived.data(), dataReceived.size() ); + BOOST_REQUIRE_EQUAL( rec, payload ); + sock->disconnect(); + } + }); + + timer->sigExpired().connect([&]( zyppng::Timer &) { + timedOut = true; + ev->quit(); + }); + + timer->start( 30000 ); + + sock->connect( std::make_shared( "socktest", true ) ); + BOOST_REQUIRE( sock->state() == zyppng::Socket::ConnectedState || sock->state() == zyppng::Socket::ConnectingState ); + + + ev->run(); + BOOST_REQUIRE_EQUAL( error, zyppng::Socket::NoError ); + BOOST_REQUIRE( gotConnected ); + BOOST_REQUIRE( gotDisconnected ); + BOOST_REQUIRE( gotReadChanFinished ); + BOOST_REQUIRE_EQUAL( timedOut, false ); + }); + + ev->run(); + clientThread.join(); + + BOOST_REQUIRE_EQUAL( payload , std::string_view( dataReceived.data(), dataReceived.size() ) ); + BOOST_REQUIRE_EQUAL( bytesWritten, payload.size() ); + +} + +BOOST_AUTO_TEST_CASE ( echo ) +{ + + const std::string payload = "Hello World"; + + auto ev = zyppng::EventLoop::create(); + auto listeningSock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto error = zyppng::Socket::NoError; + + auto addr = std::make_shared( "socktest", true ); + BOOST_REQUIRE( listeningSock->bind( addr ) ); + BOOST_REQUIRE( listeningSock->listen() ); + BOOST_REQUIRE_EQUAL( listeningSock->state(), zyppng::Socket::ListeningState ); + + zyppng::Socket::Ptr connection; + zyppng::ByteArray received; + + listeningSock->sigIncomingConnection().connect( [&](){ + connection = listeningSock->accept(); + BOOST_REQUIRE_EQUAL( connection->state(), zyppng::Socket::ConnectedState ); + + connection->sigError().connect([&]( const auto err ){ + if ( err == zyppng::Socket::ConnectionDelayed ) + return; + error = err; + ev->quit(); + }); + + connection->sigDisconnected().connect( [&](){ + BOOST_REQUIRE_EQUAL( connection->state(), zyppng::Socket::ClosedState ); + ev->quit(); + }); + + // just echo received data back right away + connection->sigReadyRead().connect( [&](){ + connection->write( connection->readAll() ); + }); + }); + + std::thread clientThread( [ payload ](){ + auto ev = zyppng::EventLoop::create(); + auto sock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto timer = zyppng::Timer::create(); + + bool timedOut = false; + bool gotConnected = false; + bool gotDisconnected = false; + auto error = zyppng::Socket::NoError; + + sock->sigError().connect( [&]( const zyppng::Socket::SocketError err ){ + if ( err == zyppng::Socket::ConnectionDelayed ) + return; + error = err; + ev->quit(); + }); + + sock->sigConnected().connect( [&](){ + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ConnectedState ); + gotConnected = true; + + + sock->write( payload.data(), payload.size() ); + }); + + sock->sigDisconnected().connect( [&](){ + gotDisconnected = true; + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ClosedState ); + ev->quit(); + }); + + zyppng::ByteArray dataReceived; + sock->sigReadyRead().connect([&](){ + const auto bA = sock->bytesAvailable(); + auto all = sock->readAll(); + + dataReceived.insert( dataReceived.end(), all.begin(), all.end() ); + BOOST_REQUIRE_EQUAL( bA, all.size() ); + + if ( dataReceived.size() == payload.length() ) { + std::string_view rec( dataReceived.data(), dataReceived.size() ); + BOOST_REQUIRE_EQUAL( rec, payload ); + sock->disconnect(); + } + }); + + timer->sigExpired().connect([&]( zyppng::Timer &) { + timedOut = true; + ev->quit(); + }); + + timer->start( 30000 ); + + sock->connect( std::make_shared( "socktest", true ) ); + BOOST_REQUIRE( sock->state() == zyppng::Socket::ConnectedState || sock->state() == zyppng::Socket::ConnectingState ); + + + ev->run(); + BOOST_REQUIRE_EQUAL( error, zyppng::Socket::NoError ); + BOOST_REQUIRE( gotConnected ); + BOOST_REQUIRE( gotDisconnected ); + BOOST_REQUIRE_EQUAL( timedOut, false ); + }); + + ev->run(); + clientThread.join(); +} + +BOOST_AUTO_TEST_CASE ( err ) +{ + auto ev = zyppng::EventLoop::create(); + { + auto sock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + + const auto res = sock->connect( std::make_shared( "socktest", true ) ); + BOOST_REQUIRE( !res ); + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ClosedState ); + BOOST_REQUIRE_EQUAL ( sock->lastError() , zyppng::Socket::ConnectionRefused ); + } + + if ( ::geteuid() != 0 ) { + auto sock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + + const auto res = sock->bind( std::make_shared( "/root/socketicannotcreate", false ) ); + BOOST_REQUIRE( !res ); + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ClosedState ); + BOOST_REQUIRE_EQUAL ( sock->lastError() , zyppng::Socket::InsufficientPermissions ); + } + + { + auto sock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto addr = std::make_shared( "socktest", true ); + sock->bind( addr ); + const auto res = sock->bind( addr ); + BOOST_REQUIRE( !res ); + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ClosedState ); + BOOST_REQUIRE_EQUAL ( sock->lastError() , zyppng::Socket::SocketAlreadyBound ); + } + + { + auto sock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto sock2 = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + + auto addr = std::make_shared( "socktest", true ); + sock->bind( addr ); + + const auto res = sock2->bind( addr ); + BOOST_REQUIRE( !res ); + BOOST_REQUIRE_EQUAL ( sock2->lastError() , zyppng::Socket::AddressInUse ); + } +} + +BOOST_AUTO_TEST_CASE ( lotsofdata ) +{ + + const std::string payload = + "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, " + "sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem " + "ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore " + "magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata " + "sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut " + "labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, " + "no sea takimata sanctus est Lorem ipsum dolor sit amet."; + + auto ev = zyppng::EventLoop::create(); + auto listeningSock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto error = zyppng::Socket::NoError; + + const int iterations = 1000000; + int64_t bytesShouldBeWritten = 0; + int64_t bytesWritten = 0; + int64_t bytesWrittenSignaled = 0; + int64_t bytesReceived = 0; + + auto addr = std::make_shared( "socktest", true ); + BOOST_REQUIRE( listeningSock->bind( addr ) ); + BOOST_REQUIRE( listeningSock->listen() ); + BOOST_REQUIRE_EQUAL( listeningSock->state(), zyppng::Socket::ListeningState ); + + zyppng::Socket::Ptr connection; + + listeningSock->sigIncomingConnection().connect( [&](){ + connection = listeningSock->accept(); + BOOST_REQUIRE_EQUAL( connection->state(), zyppng::Socket::ConnectedState ); + + connection->sigError().connect([&]( const auto err ){ + if ( err == zyppng::Socket::ConnectionDelayed ) + return; + error = err; + ev->quit(); + }); + + connection->sigDisconnected().connect( [&](){ + BOOST_REQUIRE_EQUAL( connection->state(), zyppng::Socket::ClosedState ); + ev->quit(); + }); + + connection->sigReadyRead().connect([&](){ + auto all = connection->readAll(); + bytesReceived += all.size(); + }); + }); + + std::thread clientThread( [ payload, &bytesWritten, &bytesWrittenSignaled, &bytesShouldBeWritten ](){ + auto cev = zyppng::EventLoop::create(); + auto sock = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto timer = zyppng::Timer::create(); + + bool timedOut = false; + bool gotConnected = false; + bool gotDisconnected = false; + + auto error = zyppng::Socket::NoError; + + sock->sigError().connect( [&]( const zyppng::Socket::SocketError err ){ + if ( err == zyppng::Socket::ConnectionDelayed ) + return; + error = err; + cev->quit(); + }); + + sock->sigConnected().connect( [&](){ + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ConnectedState ); + gotConnected = true; + + for ( int i = 0; i < iterations; i++ ) { + auto thisBytesWritten = sock->write( payload.data(), payload.length() ); + bytesShouldBeWritten += payload.length(); + bytesWritten += thisBytesWritten; + + } + sock->disconnect(); + }); + + sock->sigBytesWritten().connect( [&]( const auto bytes ){ + timer->start(); + bytesWrittenSignaled += bytes; + }); + + sock->sigDisconnected().connect( [&](){ + gotDisconnected = true; + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ClosedState ); + cev->quit(); + }); + + timer->sigExpired().connect([&]( zyppng::Timer &) { + timedOut = true; + cev->quit(); + }); + + timer->start( 30000 ); + + sock->connect( std::make_shared( "socktest", true ) ); + + if ( sock->state() == zyppng::Socket::ConnectingState + || sock->state() == zyppng::Socket::ConnectedState + || sock->state() == zyppng::Socket::ClosingState ) { + cev->run(); + } + + BOOST_REQUIRE_EQUAL( sock->state(), zyppng::Socket::ClosedState ); + BOOST_REQUIRE_EQUAL( error, zyppng::Socket::NoError ); + BOOST_REQUIRE( gotConnected ); + BOOST_REQUIRE( gotDisconnected ); + BOOST_REQUIRE_EQUAL( timedOut, false ); + }); + + ev->run(); + clientThread.join(); + + BOOST_REQUIRE_EQUAL( error, zyppng::Socket::ConnectionClosedByRemote ); + BOOST_REQUIRE_EQUAL( bytesWritten, payload.size() * iterations ); + BOOST_REQUIRE_EQUAL( bytesWritten, bytesReceived ); + BOOST_REQUIRE_EQUAL( bytesWritten, bytesWrittenSignaled ); + +} diff --git a/tests/zyppng/media/CMakeLists.txt b/tests/zyppng/media/CMakeLists.txt new file mode 100644 index 0000000..f12bf0b --- /dev/null +++ b/tests/zyppng/media/CMakeLists.txt @@ -0,0 +1,9 @@ +IF( NOT DISABLE_MEDIABACKEND_TESTS) + ADD_TESTS( + NetworkRequestDispatcher + EvDownloader + Provider + ) + target_link_libraries( Provider_test PUBLIC tvm-protocol-obj ) +ENDIF() + diff --git a/tests/zyppng/media/EvDownloader_test.cc b/tests/zyppng/media/EvDownloader_test.cc new file mode 100644 index 0000000..db799c2 --- /dev/null +++ b/tests/zyppng/media/EvDownloader_test.cc @@ -0,0 +1,699 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "WebServer.h" +#include "TestTools.h" + +#include +#include + +#define BOOST_TEST_REQ_SUCCESS(REQ) \ + do { \ + BOOST_REQUIRE_MESSAGE( REQ->state() == zyppng::Download::Finished && !REQ->hasError(), zypp::str::Format(" %1% != zyppng::Download::Success (%2%)") % REQ->state() % REQ->errorString() ); \ + BOOST_REQUIRE_EQUAL( REQ->lastRequestError().type(), zyppng::NetworkRequestError::NoError ); \ + BOOST_REQUIRE( REQ->errorString().empty() ); \ + } while(false) + +#define BOOST_TEST_REQ_FAILED(REQ) \ + do { \ + BOOST_REQUIRE_EQUAL( REQ->state(), zyppng::Download::Finished ); \ + BOOST_REQUIRE( REQ->hasError() ); \ + BOOST_REQUIRE_NE( REQ->lastRequestError().type(), zyppng::NetworkRequestError::NoError ); \ + BOOST_REQUIRE( !REQ->errorString().empty() ); \ + } while(false) + +namespace bdata = boost::unit_test::data; + +bool withSSL[] = {true, false}; + +BOOST_DATA_TEST_CASE( dltest_basic, bdata::make( withSSL ), withSSL) +{ + auto ev = zyppng::EventLoop::create(); + + zyppng::Downloader::Ptr downloader = std::make_shared(); + + //make sure the data here is big enough to cross the threshold of 256 bytes so we get a progress signal emitted and not only the alive signal. + std::string dummyContent = "This is just some dummy content,\nto test downloading and signals.\n" + "This is just some dummy content,\nto test downloading and signals.\n" + "This is just some dummy content,\nto test downloading and signals.\n" + "This is just some dummy content,\nto test downloading and signals.\n"; + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + web.addRequestHandler("getData", WebServer::makeResponse("200", dummyContent ) ); + BOOST_REQUIRE( web.start() ); + + zypp::filesystem::TmpFile targetFile; + zyppng::Url weburl (web.url()); + weburl.setPathName("/handler/getData"); + zyppng::TransferSettings set = web.transferSettings(); + + bool gotStarted = false; + bool gotFinished = false; + bool gotProgress = false; + bool gotAlive = false; + off_t lastProgress = 0; + off_t totalDL = 0; + + std::vector allStates; + + + zyppng::Download::Ptr dl = downloader->downloadFile( zyppng::DownloadSpec(weburl, targetFile.path(), dummyContent.length()) ); + dl->spec().setTransferSettings( set ); + + dl->sigFinished().connect([&]( zyppng::Download & ){ + gotFinished = true; + ev->quit(); + }); + + dl->sigStarted().connect([&]( zyppng::Download & ){ + gotStarted = true; + }); + + dl->sigAlive().connect([&]( zyppng::Download &, off_t ){ + gotAlive = true; + }); + + dl->sigStateChanged().connect([&]( zyppng::Download &, zyppng::Download::State state ){ + allStates.push_back( state ); + }); + + dl->sigProgress().connect([&]( zyppng::Download &, off_t dltotal, off_t dlnow ){ + gotProgress = true; + lastProgress = dlnow; + totalDL = dltotal; + }); + dl->start(); + ev->run(); + + BOOST_TEST_REQ_SUCCESS( dl ); + BOOST_REQUIRE( gotStarted ); + BOOST_REQUIRE( gotFinished ); + BOOST_REQUIRE( gotProgress ); + BOOST_REQUIRE( gotAlive ); + BOOST_REQUIRE_EQUAL( totalDL, dummyContent.length() ); + BOOST_REQUIRE_EQUAL( lastProgress, dummyContent.length() ); + BOOST_REQUIRE ( allStates == std::vector({zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::Finished}) ); +} + + +// Globals are HORRIBLY broken here, do not use any static globals they might not be initialized at the point +// of calling the initializer of the MirrorSet vector, so we are manually initializing the Byte and KByte Units here +const auto makeBytes( zypp::ByteCount::SizeType size ) { + return zypp::ByteCount( size, zypp::ByteCount::Unit( 1LL, "B", 0 ) ); +}; + +const auto makeKBytes( zypp::ByteCount::SizeType size ) { + return zypp::ByteCount( size, zypp::ByteCount::Unit( 1024LL, "KiB", 1 ) ); +}; + + +struct MirrorSet +{ + std::string name; // > mirrors; //all mirrors injected into the metalink file + int expectedFileDownloads; //< how many downloads are direct file downloads + int expectedHandlerDownloads; //< how many started downloads are handler requests + std::vector expectedStates; + bool expectSuccess; //< should the download work out? + zypp::ByteCount chunkSize = makeKBytes( 256 ); + + //zck data + zypp::CheckSum headerChecksum; //< ZChunk header checksum + zypp::ByteCount headerSize; //< ZChunk header size + std::string deltaFilePath; //< ZChunk delta file + + std::ostream & operator<<( std::ostream & str ) const { + str << "MirrorSet{ " << name << " }"; + return str; + } +}; + +namespace boost{ namespace test_tools{ namespace tt_detail{ +template<> +struct print_log_value< MirrorSet > { + void operator()( std::ostream& str, MirrorSet const& set) { + set.operator<<( str ); + } +}; +}}} + +std::vector< MirrorSet > generateMirr () +{ + std::vector< MirrorSet > res; + + //all mirrors good: + res.push_back( MirrorSet() ); + res.back().name = "All good mirrors"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 1; + res.back().expectedFileDownloads = 9; + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}; + for ( int i = 100 ; i >= 10; i -= 10 ) + res.back().mirrors.push_back( std::make_pair( i, "/test.txt") ); + + //all mirrors good big chunk + res.push_back( MirrorSet() ); + res.back().name = "All good mirrors, 1024 chunk size"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 1; + res.back().expectedFileDownloads = 3; + res.back().chunkSize = makeKBytes(1024); + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}; + for ( int i = 100 ; i >= 10; i -= 10 ) + res.back().mirrors.push_back( std::make_pair( i, "/test.txt") ); + + //no mirrors: + res.push_back( MirrorSet() ); + res.back().name = "Empty mirrors"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes (2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 10; + res.back().expectedFileDownloads = 0; + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}; + + //only broken mirrors: + res.push_back( MirrorSet() ); + res.back().name = "All broken mirrors"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 2; //has to fall back to url handler download + res.back().expectedFileDownloads = 10; //should try all mirrors and fail + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::DlSimple, zyppng::Download::Finished}; + for ( int i = 100 ; i >= 10; i -= 10 ) + res.back().mirrors.push_back( std::make_pair( i, "/doesnotexist.txt") ); + + //only broken mirrors: + res.push_back( MirrorSet() ); + res.back().name = "All broken mirrors by params"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 2; //has to fall back to url handler download + res.back().expectedFileDownloads = 0; // Setting up the mirrors will fail before even starting a download, so we should only see requests to the handler directly + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::DlSimple, zyppng::Download::Finished}; + for ( int i = 100 ; i >= 10; i -= 10 ) + res.back().mirrors.push_back( std::make_pair( i, "/test.txt?auth=foobar") ); + + //some broken mirrors: + res.push_back( MirrorSet() ); + res.back().name = "Some broken mirrors less URLs than blocks"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 1; + res.back().expectedFileDownloads = 9 + 3; // 3 should fail due to broken mirrors + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}; + for ( int i = 10 ; i >= 5; i-- ) { + if ( i % 2 ) { + res.back().mirrors.push_back( std::make_pair( i*10, "/doesnotexist.txt") ); + } else { + res.back().mirrors.push_back( std::make_pair( i*10, "/test.txt") ); + } + } + + //some broken mirrors with more URLs than blocks: + res.push_back( MirrorSet() ); + res.back().name = "Some broken mirrors more URLs than blocks"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 1; + //it is not really possible to know how many times the downloads will fail, there are + //5 broken mirrors in the set, but if a working mirror is done before the last broken + //URL is picked from the dataset, not all broken URLs will be used + res.back().expectedFileDownloads = -1; + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}; + for ( int i = 10 ; i >= 1; i-- ) { + if ( i % 2 ) { + res.back().mirrors.push_back( std::make_pair( i*10, "/doesnotexist.txt") ); + } else { + res.back().mirrors.push_back( std::make_pair( i*10, "/test.txt") ); + } + } + + //mirrors where some return a invalid block + res.push_back( MirrorSet() ); + res.back().name = "Some mirrors return broken blocks"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 1; + //it is not really possible to know how many times the downloads will fail, there are + //5 broken mirrors in the set, but if a working mirror is done before the last broken + //URL is picked from the dataset, not all broken URLs will be used + res.back().expectedFileDownloads = -1; + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}; + for ( int i = 10 ; i >= 1; i-- ) { + if ( i % 2 ) { + res.back().mirrors.push_back( std::make_pair( i*10, "/handler/random") ); + } else { + res.back().mirrors.push_back( std::make_pair( i*10, "/test.txt") ); + } + } + //mirrors where some return a invalid range response ( 206 status but no range def ) + res.push_back( MirrorSet() ); + res.back().name = "Some mirrors return boken range responses"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 1; + //it is not really possible to know how many times the downloads will fail, there are + //5 broken mirrors in the set, but if a working mirror is done before the last broken + //URL is picked from the dataset, not all broken URLs will be used + res.back().expectedFileDownloads = -1; + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}; + for ( int i = 10 ; i >= 1; i-- ) { + if ( i % 2 ) { + res.back().mirrors.push_back( std::make_pair( i*10, "/handler/brokenrange") ); + } else { + res.back().mirrors.push_back( std::make_pair( i*10, "/test.txt") ); + } + } + + //all return a invalid range response ( 206 status but no range def ) + res.push_back( MirrorSet() ); + res.back().name = "All mirrors return boken range responses"; + res.back().filename = "test.txt"; + res.back().dlTotal = makeBytes(2148018); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 2; //has to fall back to url handler download + res.back().expectedFileDownloads = 10; //should try all mirrors and fail + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::DlSimple , zyppng::Download::Finished}; + for ( int i = 10 ; i >= 1; i-- ) { + res.back().mirrors.push_back( std::make_pair( i*10, "/handler/brokenrange") ); + } + +#if ENABLE_ZCHUNK_COMPRESSION + //all mirrors good with zck: + res.push_back( MirrorSet() ); + res.back().name = "All good mirrors with zck"; + res.back().filename = "primary.xml.zck"; + res.back().dlTotal = makeBytes(274638); + res.back().expectSuccess = true; + res.back().expectedHandlerDownloads = 3; // query if metalink avail + dl metalink + dl zck head because request is reused + res.back().expectedFileDownloads = 5; // 5 Chunks ( chunk size is at least 4K but is likely a few bytes bigger ) + res.back().expectedStates = { zyppng::Download::InitialState, zyppng::Download::DetectMetaLink, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlZChunkHead, zyppng::Download::DlZChunk, zyppng::Download::Finished}; + res.back().headerChecksum = zypp::CheckSum( zypp::Digest::sha256(), "90a1a1b99ba3b6c8ae9f14b0c8b8c43141c69ec3388bfa3b9915fbeea03926b7"); + res.back().headerSize = makeBytes(11717); + res.back().deltaFilePath = "primary-deltatemplate.xml.zck"; + res.back().chunkSize = makeKBytes(4); + for ( int i = 100 ; i >= 10; i -= 10 ) + res.back().mirrors.push_back( std::make_pair( i, "/primary.xml.zck") ); +#endif + + return res; +} + + +//create one URL line for a metalink template file +std::string makeUrl ( int pref, const zyppng::Url &url ) +{ + return ( zypp::str::Format( "%3%" ) % pref % url.getScheme() % url.asCompleteString() ); +}; + + +static bool requestWantsMetaLink ( const WebServer::Request &req ) +{ + auto it = req.params.find( "HTTP_ACCEPT" ); + if ( it != req.params.end() ) { + if ( (*it).second.find("application/metalink+xml") != std::string::npos || + (*it).second.find("application/metalink4+xml") != std::string::npos ) { + return true; + } + } + return false; +} + +//creates a request handler for the Mock WebServer that returns the metalink data +//specified in \a data if the request has the metalink accept handler +WebServer::RequestHandler makeMetaFileHandler ( const std::string &fName, const std::string *data ) +{ + return [ data, fName ]( WebServer::Request &req ){ + if ( requestWantsMetaLink( req ) ) { + req.rout << WebServer::makeResponseString( "200", { "Content-Type: application/metalink+xml; charset=utf-8\r\n" }, *data ); + return; + } + req.rout << "Location: /"<second, "bytes=" ) ) { + //bytes=786432-1048575 + std::string range = it->second.substr( 6 ); //remove bytes= + size_t dash = range.find_first_of( "-" ); + off_t start = -1; + off_t end = -1; + if ( dash != std::string::npos ) { + start = std::stoll( range.substr( 0, dash ) ); + end = std::stoll( range.substr( dash+1 ) ); + } + + if ( start != -1 && end != -1 ) { + std::string block; + for ( off_t curr = start; curr <= end; curr++ ) { + block += 'a'; + } + req.rout << "Status: 206 Partial Content\r\n" + << "Accept-Ranges: bytes\r\n" + << "Content-Length: "<< block.length() <<"\r\n" + << "Content-Range: bytes "<second, "bytes=" ) ) { + //bytes=786432-1048575 + std::string range = it->second.substr( 6 ); //remove bytes= + size_t dash = range.find_first_of( "-" ); + off_t start = -1; + off_t end = -1; + if ( dash != std::string::npos ) { + start = std::stoll( range.substr( 0, dash ) ); + end = std::stoll( range.substr( dash+1 ) ); + } + + if ( start != -1 && end != -1 ) { + std::string block; + for ( off_t curr = start; curr <= end; curr++ ) { + block += 'a'; + } + req.rout << "Status: 206 Partial Content\r\n" + << "Accept-Ranges: bytes\r\n" + << "Content-Length: "<< block.length() <<"\r\n" + <<"\r\n" + << block; + return; + } + } + req.rout << "Location: /"< downloader = std::make_shared(); + downloader->requestDispatcher()->setMaximumConcurrentConnections( maxDLs ); + + //first metalink download, generate a fully valid one + zyppng::Url weburl (web.url()); + weburl.setPathName( zypp::str::Format("/handler/%1%") % elem.filename ); + + std::string urls; + if ( elem.mirrors.size() ) { + for ( const auto &mirr : elem.mirrors ) { + zyppng::Url mirrUrl ( web.url().asCompleteString() + mirr.second ); + // mirrUrl.setPathName( mirr.second ); + urls += makeUrl( mirr.first, mirrUrl ) + "\n"; + } + } + + std::string metaFile = zypp::str::Format( metaTempl ) % urls; + web.addRequestHandler( elem.filename, makeMetaFileHandler( elem.filename, &metaFile ) ); + web.addRequestHandler( "random", makeJunkBlockHandler( elem.filename ) ); + web.addRequestHandler( "brokenrange", makeBrokenRangeHandler( elem.filename ) ); + + int expectedDownloads = elem.expectedHandlerDownloads + elem.expectedFileDownloads; + int startedDownloads = 0; + int finishedDownloads = 0; + bool downloadHadError = false; + bool gotProgress = false; + bool gotAlive = false; + bool gotMultiDLState = false; + std::vector allStates; + off_t gotTotal = 0; + off_t lastProgress = 0; + + int countHandlerReq = 0; //the requests made to the handler slot + int countFileReq = 0; //the requests made to the file directly, e.g. a mirror read from the metalink file + + auto dl = downloader->downloadFile( zyppng::DownloadSpec(weburl, targetFile) ); + dl->spec().setTransferSettings( web.transferSettings() ) + .setPreferredChunkSize( elem.chunkSize ) + .setHeaderSize( elem.headerSize ) + .setHeaderChecksum( elem.headerChecksum ) + .setDeltaFile( elem.deltaFilePath.empty() ? zypp::Pathname() : testRoot/elem.deltaFilePath ) + .setExpectedFileSize( elem.dlTotal ); + + dl->dispatcher().sigDownloadStarted().connect( [&]( zyppng::NetworkRequestDispatcher &, zyppng::NetworkRequest &req){ + startedDownloads++; + if ( req.url() == weburl ) + countHandlerReq++; + else + countFileReq++; + }); + + dl->dispatcher().sigDownloadFinished().connect( [&]( zyppng::NetworkRequestDispatcher &, zyppng::NetworkRequest &req ){ + finishedDownloads++; + + if ( !downloadHadError ) + downloadHadError = req.hasError(); + }); + + dl->sigFinished().connect([&]( zyppng::Download & ){ + ev->quit(); + }); + + dl->sigAlive().connect([&]( zyppng::Download &, off_t dlnow ){ + gotAlive = true; + lastProgress = dlnow; + }); + + dl->sigProgress().connect([&]( zyppng::Download &, off_t dltotal, off_t dlnow ){ + gotProgress = true; + gotTotal = dltotal; + lastProgress = dlnow; + }); + + dl->sigStateChanged().connect([&]( zyppng::Download &, zyppng::Download::State state ){ + if ( state == zyppng::Download::DlMetalink || state == zyppng::Download::DlZChunk ) + gotMultiDLState = true; + }); + + dl->sigStateChanged().connect([&]( zyppng::Download &, zyppng::Download::State state ){ + allStates.push_back( state ); + }); + + dl->start(); + ev->run(); + + //std::cout << dl->errorString() << std::endl; + + if ( elem.expectSuccess ) + BOOST_TEST_REQ_SUCCESS( dl ); + else + BOOST_TEST_REQ_FAILED ( dl ); + + if ( elem.expectedHandlerDownloads > -1 && elem.expectedFileDownloads > -1 ) { + BOOST_REQUIRE_EQUAL( startedDownloads, expectedDownloads ); + } + + BOOST_REQUIRE_EQUAL( startedDownloads, finishedDownloads ); + BOOST_REQUIRE( gotAlive ); + BOOST_REQUIRE( gotProgress ); + BOOST_REQUIRE( gotMultiDLState ); + if ( elem.dlTotal > 0 ) + BOOST_REQUIRE_EQUAL( lastProgress, elem.dlTotal ); + BOOST_REQUIRE_EQUAL( lastProgress, gotTotal ); + + if ( elem.expectedHandlerDownloads > -1 ) + BOOST_REQUIRE_EQUAL( countHandlerReq, elem.expectedHandlerDownloads ); + + if ( elem.expectedFileDownloads > -1 ) + BOOST_REQUIRE_EQUAL( countFileReq, elem.expectedFileDownloads ); + + if ( !elem.expectedStates.empty() ) + BOOST_REQUIRE( elem.expectedStates == allStates ); +} + +//tests: +// - broken cert +// - correct expected filesize +// - invalid filesize +// - password handling and propagation + + +//creates a request handler that requires a authentication to work +WebServer::RequestHandler createAuthHandler ( ) +{ + return [ ]( WebServer::Request &req ){ + //Basic dGVzdDp0ZXN0 + auto it = req.params.find( "HTTP_AUTHORIZATION" ); + bool authorized = false; + if ( it != req.params.end() ) + authorized = ( it->second == "Basic dGVzdDp0ZXN0" ); + + if ( !authorized ) { + req.rout << "Status: 401 Unauthorized\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "WWW-Authenticate: Basic realm=\"User Visible Realm\", charset=\"UTF-8\" \r\n" + "\r\n" + "Sorry you are not authorized."; + return; + } + + if ( requestWantsMetaLink( req ) ) { + it = req.params.find( "HTTPS" ); + if ( it != req.params.end() && it->second == "on" ) { + req.rout << "Status: 307 Temporary Redirect\r\n" + << "Cache-Control: no-cache\r\n" + << "Location: /auth-https.meta\r\n\r\n"; + } else { + req.rout << "Status: 307 Temporary Redirect\r\n" + << "Cache-Control: no-cache\r\n" + << "Location: /auth-http.meta\r\n\r\n"; + } + return; + } + req.rout << "Status: 307 Temporary Redirect\r\n" + "Location: /test.txt\r\n\r\n"; + return; + }; +}; + +BOOST_DATA_TEST_CASE( dltest_auth, bdata::make( withSSL ), withSSL ) +{ + //don't write or read creds from real settings dir + zypp::filesystem::TmpDir repoManagerRoot; + zypp::ZConfig::instance().setRepoManagerRoot( repoManagerRoot.path() ); + + auto ev = zyppng::EventLoop::create(); + + std::shared_ptr downloader = std::make_shared(); + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"/zyppng/data/downloader").c_str(), 10001, withSSL ); + BOOST_REQUIRE( web.start() ); + + zypp::filesystem::TmpFile targetFile; + zyppng::Url weburl (web.url()); + weburl.setPathName("/handler/test.txt"); + zyppng::TransferSettings set = web.transferSettings(); + + web.addRequestHandler( "test.txt", createAuthHandler() ); + web.addRequestHandler( "quit", [ &ev ]( WebServer::Request & ){ ev->quit();} ); + + { + auto dl = downloader->downloadFile( zyppng::DownloadSpec(weburl, targetFile.path()) ); + dl->spec().setTransferSettings(set); + + dl->sigFinished( ).connect([ &ev ]( zyppng::Download & ){ + ev->quit(); + }); + + dl->start(); + ev->run(); + BOOST_TEST_REQ_FAILED( dl ); + BOOST_REQUIRE_EQUAL( dl->lastRequestError().type(), zyppng::NetworkRequestError::Unauthorized ); + } + + { + auto dl = downloader->downloadFile( zyppng::DownloadSpec(weburl, targetFile.path()) ); + dl->spec().setTransferSettings(set); + + int gotAuthRequest = 0; + + dl->sigFinished( ).connect([ &ev ]( zyppng::Download & ){ + ev->quit(); + }); + + dl->sigAuthRequired().connect( [&]( zyppng::Download &, zyppng::NetworkAuthData &auth, const std::string &availAuth ){ + gotAuthRequest++; + if ( gotAuthRequest >= 2 ) + return; + auth.setUsername("wrong"); + auth.setPassword("credentials"); + }); + + dl->start(); + ev->run(); + BOOST_TEST_REQ_FAILED( dl ); + BOOST_REQUIRE_EQUAL( gotAuthRequest, 2 ); + BOOST_REQUIRE_EQUAL( dl->lastRequestError().type(), zyppng::NetworkRequestError::AuthFailed ); + } + + { + int gotAuthRequest = 0; + std::vector allStates; + auto dl = downloader->downloadFile( zyppng::DownloadSpec(weburl, targetFile.path()) ); + dl->spec().setTransferSettings(set); + + dl->sigFinished( ).connect([ &ev ]( zyppng::Download & ){ + ev->quit(); + }); + + dl->sigAuthRequired().connect( [&]( zyppng::Download &, zyppng::NetworkAuthData &auth, const std::string &availAuth ){ + gotAuthRequest++; + auth.setUrl( web.url() ); + auth.setUsername("test"); + auth.setPassword("test"); + auth.setLastDatabaseUpdate( time( nullptr ) ); + }); + + dl->sigStateChanged().connect([&]( zyppng::Download &, zyppng::Download::State state ){ + allStates.push_back( state ); + }); + + + dl->start(); + ev->run(); + BOOST_TEST_REQ_SUCCESS( dl ); + BOOST_REQUIRE_EQUAL( gotAuthRequest, 1 ); + BOOST_REQUIRE ( allStates == std::vector({ zyppng::Download::InitialState, zyppng::Download::DlMetaLinkInfo, zyppng::Download::PrepareMulti, zyppng::Download::DlMetalink, zyppng::Download::Finished}) ); + } +} diff --git a/tests/zyppng/media/NetworkRequestDispatcher_test.cc b/tests/zyppng/media/NetworkRequestDispatcher_test.cc new file mode 100644 index 0000000..004adc7 --- /dev/null +++ b/tests/zyppng/media/NetworkRequestDispatcher_test.cc @@ -0,0 +1,736 @@ +#include +#include +#include +#include +#include // for hexstr2bytes +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "WebServer.h" +#include "FtpServer.h" +#include "TestTools.h" + + +#define BOOST_TEST_REQ_ERR(REQ, EXPECERR) \ + do { \ + BOOST_REQUIRE( REQ->hasError() ); \ + BOOST_REQUIRE( REQ->error().isError() ); \ + BOOST_REQUIRE_EQUAL( REQ->error().type(), EXPECERR ); \ + } while(false) + +#define BOOST_TEST_REQ_SUCCESS(REQ) \ + do { \ + if ( REQ->hasError() ) \ + BOOST_ERROR( REQ->error().toString() ); \ + BOOST_REQUIRE( !REQ->hasError() ); \ + BOOST_REQUIRE( !REQ->error().isError() ); \ + BOOST_REQUIRE_EQUAL( REQ->error().type(), zyppng::NetworkRequestError::NoError ); \ + } while(false) + +namespace bdata = boost::unit_test::data; + +const char * err404 = "Status: 404 Not Found\r\n" + "Date: Tue, 21 May 2019 08:30:59 GMT\r\n" + "Server: Apache/2.4.23 (Linux/SUSE)\r\n" + "X-Prefix: 93.192.0.0/10\r\n" + "X-AS: 3320\r\n" + "Vary: accept-language,accept-charset" + "Accept-Ranges: bytes" + "Transfer-Encoding: chunked" + "Content-Type: text/html; charset=utf-8" + "Content-Language: en\r\n" + "\r\n" + "Resource is no longer available!"; + +const char * err401 = "Status: 401 Unauthorized\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "WWW-Authenticate: Basic realm=\"User Visible Realm\", charset=\"UTF-8\" \r\n" + "\r\n" + "Sorry you are not authorized."; + +const char * resp204 = "Status: 204\r\n" + "server: Apache\r\n" + "content-type: text/html;charset=UTF-8\r\n" + "date: Wed, 30 Nov 2022 14:31:22 GMT\r\n\r\n"; + +bool withSSL[] = { true, false }; + +BOOST_DATA_TEST_CASE(nwdispatcher_basic, bdata::make( withSSL ), withSSL) +{ + std::string dummyContent = "This is just some dummy content,\nto test downloading and signals."; + + auto ev = zyppng::EventLoop::create(); + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + web.addRequestHandler("getData", WebServer::makeResponse("200 OK", dummyContent ) ); + BOOST_REQUIRE( web.start() ); + + BOOST_REQUIRE( !web.isStopped() ); + + zyppng::TransferSettings set = web.transferSettings(); + auto disp = std::make_shared(); + disp->run(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + bool gotStarted = false; + bool gotFinished = false; + bool gotProgress = false; + off_t lastProgress = 0; + off_t totalDL = 0; + + zypp::filesystem::TmpFile targetFile; + zyppng::Url weburl (web.url()); + weburl.setPathName("/handler/getData"); + + zyppng::NetworkRequest::Ptr reqData = std::make_shared( weburl, targetFile.path() ); + reqData->transferSettings() = set; + reqData->sigStarted().connect( [ &gotStarted ]( zyppng::NetworkRequest& ){ + gotStarted = true; + }); + reqData->sigFinished().connect( [ &gotFinished ]( zyppng::NetworkRequest&, const zyppng::NetworkRequestError & ){ + gotFinished = true; + }); + reqData->sigProgress().connect( [ & ]( zyppng::NetworkRequest &, off_t dltotal, off_t dlnow, off_t, off_t ){ + gotProgress= true; + lastProgress = dlnow; + totalDL = dltotal; + }); + + disp->enqueue( reqData ); + if ( disp->count () ) ev->run(); + + BOOST_TEST_REQ_SUCCESS( reqData ); + BOOST_REQUIRE( gotStarted ); + BOOST_REQUIRE( gotFinished ); + BOOST_REQUIRE( gotProgress ); + BOOST_REQUIRE_EQUAL( totalDL, dummyContent.length() ); + BOOST_REQUIRE_EQUAL( lastProgress, dummyContent.length() ); +} + +BOOST_DATA_TEST_CASE(nwdispatcher_http_errors, bdata::make( withSSL ), withSSL) +{ + auto makeErrorResponder = [] ( std::string err ) -> WebServer::RequestHandler { + return WebServer::makeResponse( err, "This is a error." ); + }; + + auto ev = zyppng::EventLoop::create(); + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + + web.addRequestHandler("get404", WebServer::makeResponse( err404 ) ); + web.addRequestHandler("get401", WebServer::makeResponse( err401 ) ); + web.addRequestHandler("get502", makeErrorResponder( "502 Bad Gateway" ) ); + web.addRequestHandler("get503", makeErrorResponder( "503 Service Unavailable" ) ); + web.addRequestHandler("get504", makeErrorResponder( "504 Gateway Timeout" ) ); + web.addRequestHandler("get403", makeErrorResponder( "403 Forbidden" ) ); + web.addRequestHandler("get410", makeErrorResponder( "410 Gone" ) ); + web.addRequestHandler("get418", makeErrorResponder( "418 I'm a teapot" ) ); + web.addRequestHandler("get204", WebServer::makeResponse( resp204 ) ); + BOOST_REQUIRE( web.start() ); + + zyppng::TransferSettings set = web.transferSettings(); + + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + zyppng::Url weburl (web.url()); + weburl.setPathName("/handler/get404"); + + zypp::filesystem::TmpFile targetFile; + zyppng::NetworkRequest::Ptr req404 = std::make_shared( weburl, targetFile.path() ); + req404->transferSettings() = set; + disp->enqueue( req404 ); + + weburl = zyppng::Url( "bad://127.0.0.1" ); + BOOST_REQUIRE( !disp->supportsProtocol(weburl) ); + zyppng::NetworkRequest::Ptr reqInvProto = std::make_shared( weburl, targetFile.path() ); + reqInvProto->transferSettings() = set; + disp->enqueue( reqInvProto ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get401"); + zyppng::NetworkRequest::Ptr reqUnauthorized = std::make_shared( weburl, targetFile.path() ); + reqUnauthorized->transferSettings() = set; + disp->enqueue( reqUnauthorized ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get401"); + zyppng::NetworkRequest::Ptr reqAuthFailed = std::make_shared( weburl, targetFile.path() ); + reqAuthFailed->transferSettings() = set; + reqAuthFailed->transferSettings().setUsername("test"); + reqAuthFailed->transferSettings().setPassword("test"); + disp->enqueue( reqAuthFailed ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get502"); + zyppng::NetworkRequest::Ptr req502 = std::make_shared( weburl, targetFile.path() ); + req502->transferSettings() = set; + disp->enqueue( req502 ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get503"); + zyppng::NetworkRequest::Ptr req503 = std::make_shared( weburl, targetFile.path() ); + req503->transferSettings() = set; + disp->enqueue( req503 ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get504"); + zyppng::NetworkRequest::Ptr req504 = std::make_shared( weburl, targetFile.path() ); + req504->transferSettings() = set; + disp->enqueue( req504 ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get403"); + zyppng::NetworkRequest::Ptr req403 = std::make_shared( weburl, targetFile.path() ); + req403->transferSettings() = set; + disp->enqueue( req403 ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get410"); + zyppng::NetworkRequest::Ptr req410 = std::make_shared( weburl, targetFile.path() ); + req410->transferSettings() = set; + disp->enqueue( req410 ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get418"); + zyppng::NetworkRequest::Ptr req418 = std::make_shared( weburl, targetFile.path() ); + req418->transferSettings() = set; + disp->enqueue( req418 ); + + weburl = zyppng::Url( web.url() ); + weburl.setPathName("/handler/get204"); + zyppng::NetworkRequest::Ptr get204 = std::make_shared( weburl, targetFile.path() ); + get204->transferSettings() = set; + disp->enqueue( get204 ); + + disp->run(); + if ( disp->count () ) ev->run(); + + BOOST_TEST_REQ_ERR( req404, zyppng::NetworkRequestError::NotFound ); + BOOST_TEST_REQ_ERR( reqInvProto, zyppng::NetworkRequestError::UnsupportedProtocol ); + BOOST_TEST_REQ_ERR( reqUnauthorized, zyppng::NetworkRequestError::Unauthorized ); + BOOST_TEST_REQ_ERR( reqAuthFailed, zyppng::NetworkRequestError::AuthFailed ); + BOOST_TEST_REQ_ERR( req502, zyppng::NetworkRequestError::TemporaryProblem ); + BOOST_TEST_REQ_ERR( req503, zyppng::NetworkRequestError::TemporaryProblem ); + BOOST_TEST_REQ_ERR( req504, zyppng::NetworkRequestError::Timeout ); + BOOST_TEST_REQ_ERR( req403, zyppng::NetworkRequestError::Forbidden ); + BOOST_TEST_REQ_ERR( req410, zyppng::NetworkRequestError::NotFound ); + BOOST_TEST_REQ_ERR( req418, zyppng::NetworkRequestError::ServerReturnedError ); + BOOST_TEST_REQ_SUCCESS( get204 ); +} + +template +void nwdispatcher_download( bool withSSL ) +{ + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + //start request dispatching, does not need to have requests enqueued + disp->run(); + + Server srv((zypp::Pathname(TESTS_SRC_DIR)/"zypp/data/Fetcher/remote-site").c_str(), 10001, withSSL ); + BOOST_REQUIRE( srv.start() ); + + zyppng::TransferSettings set = srv.transferSettings(); + + zyppng::Url weburl (srv.url()); + weburl.setPathName("/complexdir/subdir1/subdir1-file1.txt"); + + const auto &checkFileExists = []( const zypp::filesystem::Pathname &filePath ) -> bool { + zypp::filesystem::PathInfo targetFileInfo( filePath ); + return ( targetFileInfo.isExist() && targetFileInfo.isFile() ); + }; + + const auto &checkFilesum = []( const zypp::filesystem::Pathname &filePath, const zypp::CheckSum sum ) -> bool { + std::string fileSum = zypp::filesystem::checksum( filePath, sum.type() ); + fileSum = zypp::str::trim( fileSum ); + const std::string &expSumStr = sum.checksum (); + return (expSumStr == fileSum); + }; + + + // download a full file using a open range starting from 0 with expected checksum + { + zypp::filesystem::TmpFile targetFile; + zyppng::NetworkRequest::Ptr reqDLFile = std::make_shared( weburl, targetFile.path() ); + std::optional dig = zypp::Digest(); + BOOST_REQUIRE_MESSAGE( dig->create( zypp::Digest::sha1() ), "Unable to create Digest " ); + + reqDLFile->transferSettings() = set; + reqDLFile->addRequestRange(0, 0, std::move(dig), zypp::media::hexstr2bytes("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + BOOST_REQUIRE( checkFileExists(targetFile.path()) ); + BOOST_REQUIRE( checkFilesum(targetFile.path(), zypp::CheckSum::sha1("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15")) ); + } + + // download a full file with expected checksum + { + zypp::filesystem::TmpFile targetFile; + zyppng::NetworkRequest::Ptr reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + BOOST_REQUIRE_MESSAGE( reqDLFile->setExpectedFileChecksum( zypp::CheckSum::sha1("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15") ), "Unable to set expected checksum" ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + BOOST_REQUIRE( checkFileExists(targetFile.path()) ); + BOOST_REQUIRE( checkFilesum(targetFile.path(), zypp::CheckSum::sha1("f1d2d2f924e986ac86fdf7b36c94bcdf32beec15")) ); + } + + // download a full file using a open range starting from 0 but checksum should fail + { + zypp::filesystem::TmpFile targetFile; + zyppng::NetworkRequest::Ptr reqDLFile = std::make_shared( weburl, targetFile.path() ); + std::optional dig = zypp::Digest(); + BOOST_REQUIRE_MESSAGE( dig->create( zypp::Digest::sha1() ), "Unable to create Digest " ); + //modify the checksum -> request should fail now + reqDLFile->addRequestRange(0, 0, std::move(dig), zypp::media::hexstr2bytes("f1d2d2f924e986ac86fdf7b36c94bcdf32beec20") ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_ERR( reqDLFile, zyppng::NetworkRequestError::InvalidChecksum ); + + BOOST_REQUIRE( checkFileExists(targetFile.path()) ); + BOOST_REQUIRE( !checkFilesum(targetFile.path(), zypp::CheckSum::sha1("f1d2d2f924e986ac86fdf7b36c94bcdf32beec20")) ); + } + + // download a full file but checksum should fail + { + zypp::filesystem::TmpFile targetFile; + zyppng::NetworkRequest::Ptr reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + BOOST_REQUIRE_MESSAGE( reqDLFile->setExpectedFileChecksum( zypp::CheckSum::sha1( "f1d2d2f924e986ac86fdf7b36c94bcdf32beec20") ) , "Unable to set expected checksum" ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_ERR( reqDLFile, zyppng::NetworkRequestError::InvalidChecksum ); + + BOOST_REQUIRE( checkFileExists(targetFile.path()) ); + BOOST_REQUIRE( !checkFilesum(targetFile.path(), zypp::CheckSum::sha1( "f1d2d2f924e986ac86fdf7b36c94bcdf32beec20")) ); + } + + { + zypp::filesystem::TmpFile targetFile; + zyppng::NetworkRequest::Ptr reqDLFile = std::make_shared( weburl, targetFile.path() ); + weburl = srv.url(); + weburl.setPathName("/file-1.txt"); + reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + reqDLFile->addRequestRange( 0, 7 ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + BOOST_REQUIRE( checkFileExists(targetFile.path()) ); + BOOST_REQUIRE( checkFilesum(targetFile.path(), zypp::CheckSum::md5(std::string("16d2b386b2034b9488996466aaae0b57"))) ); + } +} + +BOOST_DATA_TEST_CASE(nwdispatcher_http_download, bdata::make( withSSL ), withSSL ) +{ + nwdispatcher_download(withSSL); +} + +BOOST_DATA_TEST_CASE(nwdispatcher_ftp_download, bdata::make( withSSL ), withSSL ) +{ + nwdispatcher_download(withSSL); +} + +BOOST_DATA_TEST_CASE(nwdispatcher_delay_download, bdata::make( withSSL ), withSSL ) +{ + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + disp->run(); + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + + web.addRequestHandler("stalled", []( WebServer::Request &r ){ + std::this_thread::sleep_for( std::chrono::milliseconds ( 2000 ) ); + r.rout << "Status: 200\r\n" + "\r\n" + "Hello"; + }); + + BOOST_REQUIRE( web.start() ); + + zyppng::TransferSettings set = web.transferSettings(); + set.setTimeout( 1 ); + + zypp::filesystem::TmpFile targetFile; + + zyppng::Url weburl (web.url()); + weburl.setPathName("/handler/stalled"); + + zyppng::NetworkRequest::Ptr reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + + BOOST_TEST_REQ_ERR( reqDLFile, zyppng::NetworkRequestError::Timeout ); +} + +template +void nwdispatcher_multipart_dl_impl( bool withSSL ) { + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + disp->run(); + + Server web((zypp::Pathname(TESTS_SRC_DIR)/"zypp/data/Fetcher/remote-site").c_str(), 10001, withSSL ); + BOOST_REQUIRE( web.start() ); + + auto weburl = web.url(); + weburl.setPathName("/file-1.txt"); + + zyppng::TransferSettings set = web.transferSettings(); + zypp::filesystem::TmpFile targetFile; + + auto reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + reqDLFile->addRequestRange( 13, 4 ); + reqDLFile->addRequestRange( 248, 6 ); + reqDLFile->addRequestRange( 76, 9 ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + auto err = reqDLFile->error(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + std::string downloaded = TestTools::readFile ( targetFile.path() ); + BOOST_REQUIRE( !downloaded.empty() ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data()+13 , 4 ), "SUSE" ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data()+248, 6 ), "TCP/IP" ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data()+76 , 9 ), "Slackware" ); +} + +//Get a simple range from a existing file +BOOST_DATA_TEST_CASE(nwdispatcher_multipart_dl_http, bdata::make( withSSL ), withSSL ) +{ + nwdispatcher_multipart_dl_impl(withSSL); +} + +BOOST_DATA_TEST_CASE(nwdispatcher_multipart_dl_ftp, bdata::make( withSSL ), withSSL ) +{ + nwdispatcher_multipart_dl_impl(withSSL); +} + +// Test that simulates us sending a range request to the server and the server answering with a range header but does not send actual range data +BOOST_DATA_TEST_CASE(nwdispatcher_rangereq_norangeanswer, bdata::make( withSSL ), withSSL ) +{ + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + disp->run(); + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + + web.addRequestHandler("norange", []( WebServer::Request &r ){ + r.rout << "Status: 206\r\n" + "\r\n" + "Hello"; + }); + + BOOST_REQUIRE( web.start() ); + + zyppng::TransferSettings set = web.transferSettings(); + zypp::filesystem::TmpFile targetFile; + + zyppng::Url weburl (web.url()); + weburl.setPathName("/handler/norange"); + + zyppng::NetworkRequest::Ptr reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + reqDLFile->addRequestRange( 13, 4 ); + reqDLFile->addRequestRange( 248, 6 ); + reqDLFile->addRequestRange( 76, 9 ); + + disp->enqueue( reqDLFile ); + ev->run(); + + BOOST_TEST_REQ_ERR( reqDLFile, zyppng::NetworkRequestError::ServerReturnedError ); +} + +struct RangeData { + off_t offset; + std::string payload; +}; + +auto makeMultiPartHandler ( std::vector &&values ) +{ + return [ values = std::move(values) ]( WebServer::Request &r ){ + const char *boundary = "THIS_STRING_SEPARATES"; + r.rout << "Status: 206\r\n" + "Content-Type: multipart/byteranges; boundary="<(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + disp->run(); + + const std::string_view str1 = "Hello"; + const std::string_view str2 = "World"; + const std::string_view str3 = "in Multibyte"; + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + web.addRequestHandler("mbyte", makeMultiPartHandler( { + { 10, str2.data() }, + { 0, str1.data() }, + { 25, str3.data() } + })); + + BOOST_REQUIRE( web.start() ); + + auto weburl = web.url(); + weburl.setPathName("/handler/mbyte"); + + zyppng::TransferSettings set = web.transferSettings(); + zypp::filesystem::TmpFile targetFile; + + auto reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + reqDLFile->addRequestRange( 0, str1.length() ); + reqDLFile->addRequestRange( 10, str2.length() ); + reqDLFile->addRequestRange( 25, str3.length() ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + std::string downloaded = TestTools::readFile ( targetFile.path() ); + BOOST_REQUIRE( !downloaded.empty() ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data(), 5 ) , str1 ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data()+10, 5 ), str2 ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data()+25 ) , str3 ); +} + +//Get a range response where the boundary string is part of the data +//Some servers like nginx do not check if the boundary string is inside the data, thus we need +//to make sure the parser is not affected by that +BOOST_DATA_TEST_CASE(nwdispatcher_multipart_dl_weird_data, bdata::make( withSSL ), withSSL ) +{ + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + disp->run(); + + const std::string_view str1 = "SUSE Linux"; + const std::string_view str2 = "World--THIS_STRING_SEPARATES A"; + const std::string_view str3 = "Other String"; + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + web.addRequestHandler("mbyte", makeMultiPartHandler( { + { 0, str1.data() }, + { 25, str2.data() }, + { 70, str3.data() }, + })); + + BOOST_REQUIRE( web.start() ); + + auto weburl = web.url(); + weburl.setPathName("/handler/mbyte"); + + zyppng::TransferSettings set = web.transferSettings(); + zypp::filesystem::TmpFile targetFile; + + auto reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + reqDLFile->addRequestRange( 0, str1.length() ); + reqDLFile->addRequestRange( 25, str2.length() ); + reqDLFile->addRequestRange( 70, str3.length() ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + std::string downloaded = TestTools::readFile ( targetFile.path() ); + BOOST_REQUIRE( !downloaded.empty() ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data() , str1.length() ), str1 ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data()+25, str2.length() ), str2 ); + BOOST_REQUIRE_EQUAL( std::string_view ( downloaded.data()+70, str3.length() ), str3 ); +} + +BOOST_DATA_TEST_CASE(nwdispatcher_multipart_dl_overlap, bdata::make( withSSL ), withSSL ) +{ + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + disp->run(); + + const char *data = "The SUSE Linux distribution was originally a German translation of Slackware Linux. In mid-1992, Softlanding Linux System (SLS) was founded by Peter MacDonald, and was the first comprehensive distribution to contain elements such as X and TCP/IP. The Slackware distribution (maintained by Patrick Volkerding) was initially based largely on SLS."; + const std::string_view str1 = std::string_view( data, 50 ); + const std::string_view str2 = std::string_view( data+40 ); + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + web.addRequestHandler("mbyte", makeMultiPartHandler( { + { 0, std::string( str1.data(), str1.length() ) }, + { 40, str2.data() } + })); + + BOOST_REQUIRE( web.start() ); + + auto weburl = web.url(); + weburl.setPathName("/handler/mbyte"); + + zyppng::TransferSettings set = web.transferSettings(); + zypp::filesystem::TmpFile targetFile; + + auto reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + reqDLFile->addRequestRange( 0, str1.length() ); + reqDLFile->addRequestRange( 40, str2.length() ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + std::string downloaded = TestTools::readFile ( targetFile.path() ); + BOOST_REQUIRE( !downloaded.empty() ); + BOOST_REQUIRE_EQUAL( downloaded, std::string(data) ); +} + +//Get a range response with missing data +BOOST_DATA_TEST_CASE(nwdispatcher_multipart_data_missing, bdata::make( withSSL ), withSSL ) +{ + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + disp->run(); + + const std::string_view str1 = "Hello"; + const std::string_view str2 = "World"; + const std::string_view str3 = "in Multibyte"; + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"data"/"dummywebroot").c_str(), 10001, withSSL ); + web.addRequestHandler("mbyte", makeMultiPartHandler( { + { 10, str2.data() }, + { 0, str1.data() }, + { 25, str3.data() } + })); + + BOOST_REQUIRE( web.start() ); + + auto weburl = web.url(); + weburl.setPathName("/handler/mbyte"); + + zyppng::TransferSettings set = web.transferSettings(); + zypp::filesystem::TmpFile targetFile; + + auto reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + reqDLFile->addRequestRange( 0, str1.length() ); + reqDLFile->addRequestRange( 10, str2.length() + 1 ); + reqDLFile->addRequestRange( 25, str3.length() ); + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + BOOST_TEST_REQ_ERR( reqDLFile, zyppng::NetworkRequestError::MissingData ); +} + +// Get many ranges from a file to force the downloader into using multiple batches +// and the server to generate range failure for requesting > 128 ranges ( configured in nginx.conf ) +BOOST_DATA_TEST_CASE(nwdispatcher_multipart_many_chunks_dl, bdata::make( withSSL ), withSSL ) +{ + auto ev = zyppng::EventLoop::create(); + auto disp = std::make_shared(); + disp->sigQueueFinished().connect( [&ev]( const zyppng::NetworkRequestDispatcher& ){ + ev->quit(); + }); + + disp->run(); + + WebServer web((zypp::Pathname(TESTS_SRC_DIR)/"zypp/data/Fetcher/remote-site").c_str(), 10001, withSSL ); + BOOST_REQUIRE( web.start() ); + + auto weburl = web.url(); + weburl.setPathName("/file-1.txt"); + + auto sourceFile = zypp::Pathname(TESTS_SRC_DIR)/"zypp/data/Fetcher/remote-site/file-1.txt"; + + zyppng::TransferSettings set = web.transferSettings(); + zypp::filesystem::TmpFile targetFile; + + zypp::PathInfo pi( sourceFile ); + + // request every other chunk from the file + zypp::ByteCount seekInterval = pi.size () / 512; + + auto reqDLFile = std::make_shared( weburl, targetFile.path() ); + reqDLFile->transferSettings() = set; + reqDLFile->setUrl( weburl ); + + auto chunkLen = seekInterval / 2; + for ( zypp::ByteCount off = 0;( off + chunkLen )< pi.size(); off += seekInterval ) { + reqDLFile->addRequestRange( off, chunkLen ); + } + + disp->enqueue( reqDLFile ); + if ( disp->count () ) ev->run(); + auto err = reqDLFile->error(); + BOOST_TEST_REQ_SUCCESS( reqDLFile ); + + std::string downloaded = TestTools::readFile ( targetFile.path() ); + + BOOST_REQUIRE( !downloaded.empty() ); + + std::string sourceData = TestTools::readFile ( sourceFile ); + + for ( zypp::ByteCount off = 0;( off + chunkLen )< pi.size(); off += seekInterval ) { + BOOST_REQUIRE_EQUAL( std::string_view ( sourceData.data()+off , chunkLen ), std::string_view ( downloaded.data()+off , chunkLen ) ); + } +} + diff --git a/tests/zyppng/media/Provider_test.cc b/tests/zyppng/media/Provider_test.cc new file mode 100644 index 0000000..696b760 --- /dev/null +++ b/tests/zyppng/media/Provider_test.cc @@ -0,0 +1,1221 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "WebServer.h" +#include "TestTools.h" + +#include +#include + +#ifndef TESTS_BUILD_DIR +#error "TESTS_BUILD_DIR not defined" +#endif + +#define ZYPP_REQUIRE_THROW( statement, exception ) \ + try { BOOST_REQUIRE_THROW( statement, exception ); } catch( ... ) { BOOST_FAIL( #statement" throws unexpected exception"); } + +namespace bdata = boost::unit_test::data; + + +BOOST_AUTO_TEST_CASE( http_prov_time_overflow ) +{ + const int64_t ts = int64_t(INT32_MAX) + 1; + auto inf = zyppng::ProvideMessage::createAuthInfo( 1, "user", "pw", ts ); + auto stomp = inf.toStompMessage (); + auto msg = zyppng::ProvideMessage::fromStompMessage ( stomp.unwrap() ); + BOOST_REQUIRE_EQUAL( ts,msg.unwrap ().value ( zyppng::AuthInfoMsgFields::AuthTimestamp ).asInt64 () ); +} + + +BOOST_AUTO_TEST_CASE( http_prov ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + auto fileUrl = web.url(); + fileUrl.setPathName( "/media.1/media" ); + auto op = prov->provide( fileUrl, zyppng::ProvideFileSpec() ); + + std::exception_ptr err; + std::optional resOpt; + op->onReady([&]( zyppng::expected &&res ){ + ev->quit(); + if ( !res ) + err = res.error(); + else + resOpt = *res; + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); + + BOOST_REQUIRE( !err ); + BOOST_REQUIRE( resOpt.has_value() ); + zypp::PathInfo pi( resOpt->file() ); + BOOST_REQUIRE( pi.isExist() ); + BOOST_REQUIRE( pi.isFile() ); + + std::ifstream in( resOpt->file().asString(), std::ios::binary ); + auto sum = zypp::CheckSum::md5( in ); + BOOST_REQUIRE_EQUAL( sum, std::string("63b4a45ec881d90b83c2e6af7bcbfa78") ); +} + +BOOST_AUTO_TEST_CASE( http_attach ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname (TESTS_SRC_DIR)/"/zyppng/data/downloader"; + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + auto op = prov->attachMedia( web.url(), zyppng::ProvideMediaSpec( "OnlineMedia" ) + .setMediaFile( webRoot / "media.1" / "media" ) + .setMedianr(1) ); + + op->onReady([&]( zyppng::expected &&res ){ + ev->quit(); + BOOST_REQUIRE( res.is_valid() ); + BOOST_REQUIRE( !res->handle().empty() ); + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); +} + +BOOST_AUTO_TEST_CASE( http_attach_prov ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + zyppng::Provide::MediaHandle media; + + auto op = prov->attachMedia( web.url(), zyppng::ProvideMediaSpec( "OnlineMedia" ) + .setMediaFile( webRoot / "media.1" / "media" ) + .setMedianr(1) ) + | and_then ( [&]( zyppng::Provide::MediaHandle &&res ){ + media = std::move(res); + return prov->provide( media, "/test.txt", zyppng::ProvideFileSpec() ); + }); + + std::optional fileRes; + op->onReady([&]( zyppng::expected &&res ){ + if ( res ) + fileRes = std::move(*res); + ev->quit(); + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); + + BOOST_REQUIRE( fileRes.has_value() ); + zypp::PathInfo pi ( fileRes->file() ); + BOOST_REQUIRE( pi.isExist() && pi.isFile() ); + + std::ifstream in( fileRes->file().asString(), std::ios::binary ); + auto sum = zypp::CheckSum::md5( in ); + BOOST_REQUIRE_EQUAL( sum, std::string("7e562d52c100b68e9d6a561fa8519575") ); +} + +BOOST_AUTO_TEST_CASE( http_attach_prov_404 ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + zyppng::Provide::MediaHandle media; + + auto op = prov->attachMedia( web.url(), zyppng::ProvideMediaSpec( "OnlineMedia" ) + .setMediaFile( webRoot / "media.1" / "media" ) + .setMedianr(1) ) + | and_then ( [&]( zyppng::Provide::MediaHandle &&res ){ + media = std::move(res); + return prov->provide( media, "/doesnotexist", zyppng::ProvideFileSpec() ); + }); + + std::optional fileRes; + op->onReady([&]( zyppng::expected &&res ){ + ev->quit(); + + BOOST_REQUIRE(!res); + if ( !res ) { + ZYPP_REQUIRE_THROW( std::rethrow_exception( res.error() ), zypp::media::MediaFileNotFoundException ); + } + + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); +} + + +// special case where we can detect that something is a directory because we already provided a file from the +// directory that's required as a file. +BOOST_AUTO_TEST_CASE( http_attach_prov_notafile ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + zyppng::Provide::MediaHandle media; + std::exception_ptr err; + + auto op = prov->attachMedia( web.url(), zyppng::ProvideMediaSpec( "OnlineMedia" ) + .setMediaFile( webRoot / "media.1" / "media" ) + .setMedianr(1) ) + | and_then ( [&]( zyppng::Provide::MediaHandle &&res ){ + media = std::move(res); + return prov->provide( media, "/media.1", zyppng::ProvideFileSpec() ); + }); + + op->onReady([&]( zyppng::expected &&res ){ + ev->quit(); + if ( !res ) + err = res.error(); + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); + + BOOST_REQUIRE( err ); + ZYPP_REQUIRE_THROW( std::rethrow_exception( err ), zypp::media::MediaNotAFileException ); +} + +//creates a request handler that requires a authentication to work +WebServer::RequestHandler createAuthHandler ( const zypp::Pathname &webroot = "/" ) +{ + return [ webroot ]( WebServer::Request &req ){ + //Basic dGVzdDp0ZXN0 + auto it = req.params.find( "HTTP_AUTHORIZATION" ); + bool authorized = false; + if ( it != req.params.end() ) + authorized = ( it->second == "Basic dGVzdDp0ZXN0" ); + + if ( !authorized ) { + req.rout << "Status: 401 Unauthorized\r\n" + "Content-Type: text/html; charset=utf-8\r\n" + "WWW-Authenticate: Basic realm=\"User Visible Realm\", charset=\"UTF-8\" \r\n" + "\r\n" + "Sorry you are not authorized."; + return; + } + + //remove "/handler/" prefix + std::string key = req.params.at("SCRIPT_NAME").substr( std::string_view("/handler").length() ); + + req.rout << "Status: 307 Temporary Redirect\r\n" + "Location: "<< webroot / key <<"\r\n\r\n"; + return; + }; +}; + +BOOST_AUTO_TEST_CASE( http_prov_auth ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + //don't write or read creds from real settings dir + zypp::filesystem::TmpDir globCredPath; + zypp::filesystem::TmpDir userCredPath; + zypp::media::CredManagerOptions opts; + opts.globalCredFilePath = globCredPath.path() / "credentials.cat"; + opts.userCredFilePath = userCredPath.path() / "credentials.cat"; + prov->setCredManagerOptions( opts ); + + bool gotSigAuthRequired = false; + prov->sigAuthRequired().connect( [&]( const zypp::Url &reqUrl, const std::string &triedUsername, const std::map &extraValues ) -> std::optional { + gotSigAuthRequired = true; + zypp::media::AuthData auth( reqUrl ); + auth.setUsername( "test" ); + auth.setPassword( "test" ); + auth.setLastDatabaseUpdate( time( nullptr ) ); + return auth; + }); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + web.setDefaultHandler( createAuthHandler() ); + + auto fileUrl = web.url(); + fileUrl.setPathName( "/handler/test.txt" ); + auto op = prov->provide( fileUrl, zyppng::ProvideFileSpec() ); + + std::exception_ptr err; + std::optional resOpt; + op->onReady([&]( zyppng::expected &&res ){ + ev->quit(); + if ( !res ) + err = res.error(); + else + resOpt = *res; + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); + + //BOOST_REQUIRE( gotSigAuthRequired ); + BOOST_REQUIRE( !err ); + BOOST_REQUIRE( resOpt.has_value() ); + zypp::PathInfo pi( resOpt->file() ); + BOOST_REQUIRE( pi.isExist() ); + BOOST_REQUIRE( pi.isFile() ); + + std::ifstream in( resOpt->file().asString(), std::ios::binary ); + auto sum = zypp::CheckSum::md5( in ); + BOOST_REQUIRE_EQUAL( sum, std::string("7e562d52c100b68e9d6a561fa8519575") ); +} + +BOOST_AUTO_TEST_CASE( http_prov_auth_nouserresponse ) +{ + using namespace zyppng::operators; + + //don't write or read creds from real settings dir + zypp::filesystem::TmpDir repoManagerRoot; + zypp::ZConfig::instance().setRepoManagerRoot( repoManagerRoot.path() ); + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + //don't write or read creds from real settings dir + zypp::filesystem::TmpDir globCredPath; + zypp::filesystem::TmpDir userCredPath; + zypp::media::CredManagerOptions opts; + opts.globalCredFilePath = globCredPath.path() / "credentials.cat"; + opts.userCredFilePath = userCredPath.path() / "credentials.cat"; + prov->setCredManagerOptions( opts ); + + bool gotSigAuthRequired = false; + prov->sigAuthRequired().connect( [&]( const zypp::Url &, const std::string &, const std::map & ) -> std::optional { + gotSigAuthRequired = true; + return {}; + }); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + web.setDefaultHandler( createAuthHandler() ); + + auto fileUrl = web.url(); + fileUrl.setPathName( "/handler/test.txt" ); + auto op = prov->provide( fileUrl, zyppng::ProvideFileSpec() ); + + std::exception_ptr err; + std::optional resOpt; + op->onReady([&]( zyppng::expected &&res ){ + ev->quit(); + if ( !res ) + err = res.error(); + else + resOpt = *res; + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); + + BOOST_REQUIRE( gotSigAuthRequired ); + BOOST_REQUIRE( err ); + BOOST_REQUIRE( !resOpt.has_value() ); + ZYPP_REQUIRE_THROW( std::rethrow_exception( err ), zypp::media::MediaUnauthorizedException ); +} + +BOOST_AUTO_TEST_CASE( http_prov_auth_wrongpw ) +{ + using namespace zyppng::operators; + + //don't write or read creds from real settings dir + zypp::filesystem::TmpDir repoManagerRoot; + zypp::ZConfig::instance().setRepoManagerRoot( repoManagerRoot.path() ); + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + prov->start(); + + //don't write or read creds from real settings dir + zypp::filesystem::TmpDir globCredPath; + zypp::filesystem::TmpDir userCredPath; + zypp::media::CredManagerOptions opts; + opts.globalCredFilePath = globCredPath.path() / "credentials.cat"; + opts.userCredFilePath = userCredPath.path() / "credentials.cat"; + prov->setCredManagerOptions( opts ); + + int cntAuthRequired = 0; + prov->sigAuthRequired().connect( [&]( const zypp::Url &reqUrl, const std::string &, const std::map & ) -> std::optional { + cntAuthRequired++; + zypp::media::AuthData auth( reqUrl ); + auth.setLastDatabaseUpdate( time( nullptr ) ); + if ( cntAuthRequired >= 2 ) { + auth.setUsername( "test" ); + auth.setPassword( "test" ); + } else { + auth.setUsername( "test" ); + auth.setPassword( "wrong" ); + } + + return auth; + }); + + WebServer web( webRoot.c_str(), 10001, false ); + BOOST_REQUIRE( web.start() ); + + web.setDefaultHandler( createAuthHandler() ); + + auto fileUrl = web.url(); + fileUrl.setPathName( "/handler/test.txt" ); + auto op = prov->provide( fileUrl, zyppng::ProvideFileSpec() ); + + std::exception_ptr err; + std::optional resOpt; + op->onReady([&]( zyppng::expected &&res ){ + ev->quit(); + if ( !res ) + err = res.error(); + else + resOpt = *res; + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); + + BOOST_REQUIRE_EQUAL( cntAuthRequired, 2 ); + BOOST_REQUIRE( !err ); + BOOST_REQUIRE( resOpt.has_value() ); + zypp::PathInfo pi( resOpt->file() ); + BOOST_REQUIRE( pi.isExist() ); + BOOST_REQUIRE( pi.isFile() ); + + std::ifstream in( resOpt->file().asString(), std::ios::binary ); + auto sum = zypp::CheckSum::md5( in ); + BOOST_REQUIRE_EQUAL( sum, std::string("7e562d52c100b68e9d6a561fa8519575") ); +} + +BOOST_AUTO_TEST_CASE( http_attach_prov_auth ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &webRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "downloader"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + + //don't write or read creds from real settings dir + zypp::filesystem::TmpDir globCredPath; + zypp::filesystem::TmpDir userCredPath; + zypp::media::CredManagerOptions opts; + opts.globalCredFilePath = globCredPath.path() / "credentials.cat"; + opts.userCredFilePath = userCredPath.path() / "credentials.cat"; + prov->setCredManagerOptions( opts ); + + int cntAuthRequired = 0; + prov->sigAuthRequired().connect( [&]( const zypp::Url &reqUrl, const std::string &, const std::map & ) -> std::optional { + cntAuthRequired++; + zypp::media::AuthData auth( reqUrl ); + auth.setLastDatabaseUpdate( time( nullptr ) ); + auth.setUsername( "test" ); + auth.setPassword( "test" ); + return auth; + }); + + prov->start(); + + WebServer web( webRoot.c_str(), 10001, false ); + web.setDefaultHandler( createAuthHandler() ); + BOOST_REQUIRE( web.start() ); + + zyppng::Provide::MediaHandle media; + + auto baseUrl = web.url(); + baseUrl.setPathName("/handler"); + + auto op = prov->attachMedia( baseUrl, zyppng::ProvideMediaSpec( "OnlineMedia" ) + .setMediaFile( webRoot / "media.1" / "media" ) + .setMedianr(1) ) + | and_then ( [&]( zyppng::Provide::MediaHandle &&res ){ + media = std::move(res); + return prov->provide( media, "/test.txt", zyppng::ProvideFileSpec() ); + }); + + std::optional fileRes; + op->onReady([&]( zyppng::expected &&res ){ + if ( res ) + fileRes = std::move(*res); + ev->quit(); + }); + + BOOST_REQUIRE( !op->isReady() ); + + if ( !op->isReady() ) + ev->run(); + + BOOST_REQUIRE_EQUAL( cntAuthRequired, 1 ); // after the first auth request all others should work + BOOST_REQUIRE( fileRes.has_value() ); + zypp::PathInfo pi ( fileRes->file() ); + BOOST_REQUIRE( pi.isExist() && pi.isFile() ); + + std::ifstream in( fileRes->file().asString(), std::ios::binary ); + auto sum = zypp::CheckSum::md5( in ); + BOOST_REQUIRE_EQUAL( sum, std::string("7e562d52c100b68e9d6a561fa8519575") ); +} + +static void writeTVMConfig ( const zypp::Pathname &file, const zypp::test::TVMSettings &set ) +{ + try { + YAML::Emitter yOut; + yOut << YAML::convert::encode( set ); + + const auto &fname = file/"tvm.conf"; + std::ofstream fout( fname.asString() ); + fout << yOut.c_str(); + + MIL << "TVM config serialized to: " << fname << std::endl; + + } catch ( YAML::Exception &e ) { + WAR << "YAML exception when serializing the control file: " << e.what() << std::endl; + return; + } catch ( const std::exception &e ) { + WAR << "Error when serializing the control file: " << e.what() << std::endl; + return; + } catch ( ... ) { + WAR << "Unknown error when serializing the control file" << std::endl; + return; + } +} + +static auto makeDVDProv ( zyppng::ProvideRef &prov, const zypp::filesystem::Pathname &devRoot, int mediaNr, const std::string &fName ) +{ + using namespace zyppng::operators; + + return prov->attachMedia( zypp::Url("tvm:/"), zyppng::ProvideMediaSpec("CD Test Set") + .setMediaFile( devRoot / (std::string("cd") + zypp::str::numstring(mediaNr)) / (std::string("media.") + zypp::str::numstring(mediaNr)) / "media" ) + .setMedianr(mediaNr)) + | [&prov, mediaNr, fName]( zyppng::expected &&res ){ + if ( res ) { + std::cout << "Attached " << mediaNr << " as: " << res->handle() << std::endl; + return prov->provide ( *res, fName , zyppng::ProvideFileSpec() ) | [ attachId = *res, &prov ]( auto &&res ) { + if ( !res ) { + try { + std::rethrow_exception(res.error()); + } catch ( const zypp::Exception &e ) { + std::cout << "Provide failed with " << e <file () <::error(res.error()) ); + } + } | []( zyppng::expected &&res ) { + if ( !res ) { + try { + std::rethrow_exception(res.error()); + } catch ( const zypp::Exception &e ) { + std::cout << "Provide failed with " << e <::error(res.error()); + } catch ( ... ) { + std::cout << "Provide failed with exception " << std::endl; + return zyppng::expected::error(res.error()); + } + } else { + return zyppng::expected::success(); + } + }; + } + +BOOST_AUTO_TEST_CASE( tvm_basic ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &devRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "provide"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + + zypp::test::TVMSettings devSet; + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot1", + .insertedPath = (devRoot/"cd1").asString() + } + ); + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot2", + .insertedPath = (devRoot/"cd2").asString() + } + ); + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot3", + .insertedPath = (devRoot/"cd3").asString() + } + ); + writeTVMConfig( provideRoot, devSet ); + + prov->start(); + + std::vector< zyppng::AsyncOpRef>> ops; + + ops.push_back( makeDVDProv( prov, devRoot, 1, "/file1") ); + ops.push_back( makeDVDProv( prov, devRoot, 2, "/file2") ); + ops.push_back( makeDVDProv( prov, devRoot, 3, "/file3") ); + + auto r = std::move(ops) | zyppng::waitFor(); + r->sigReady().connect([&](){ + ev->quit(); + }); + + BOOST_REQUIRE( !r->isReady() ); + + if ( !r->isReady() ) + ev->run(); + + for ( const auto &res : r->get() ) { + BOOST_REQUIRE(res); + } +} + +BOOST_AUTO_TEST_CASE( tvm_medchange ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &devRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "provide"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + + zypp::test::TVMSettings devSet; + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot1", + .insertedPath = (devRoot/"cd1").asString() + } + ); + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot2", + .insertedPath = "" + } + ); + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot3", + .insertedPath = "" + } + ); + writeTVMConfig( provideRoot, devSet ); + + prov->start(); + + bool gotMediaChange = false; + std::vector freeDevices; + int32_t mediaNrAsked = -1; + std::string labelAsked; + prov->sigMediaChangeRequested().connect([&]( const std::string &ref, const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc ){ + gotMediaChange = true; + freeDevices = devices; + labelAsked = label; + mediaNrAsked = mediaNr; + devSet.devices[1].insertedPath = (devRoot/"cd2").asString(); + writeTVMConfig( provideRoot, devSet ); + return zyppng::Provide::RETRY; + }); + + std::vector< zyppng::AsyncOpRef>> ops; + + ops.push_back( makeDVDProv( prov, devRoot, 1, "/file1") ); + ops.push_back( makeDVDProv( prov, devRoot, 2, "/file2") ); + + auto r = std::move(ops) | zyppng::waitFor(); + r->sigReady().connect([&](){ + ev->quit(); + }); + + BOOST_REQUIRE( !r->isReady() ); + + if ( !r->isReady() ) + ev->run(); + + BOOST_REQUIRE( gotMediaChange ); + BOOST_REQUIRE_EQUAL( labelAsked, std::string("CD Test Set") ); + BOOST_REQUIRE_EQUAL( mediaNrAsked, 2 ); + BOOST_REQUIRE( std::find( freeDevices.begin(), freeDevices.end(), "/fakedev/tvm/slot2" ) != freeDevices.end() ); + BOOST_REQUIRE( std::find( freeDevices.begin(), freeDevices.end(), "/fakedev/tvm/slot3" ) != freeDevices.end() ); + for ( const auto &res : r->get() ) { + BOOST_REQUIRE(res); + } +} + +zyppng::Provide::Action cancelOps[] = { zyppng::Provide::ABORT, zyppng::Provide::SKIP }; + +BOOST_DATA_TEST_CASE( tvm_medchange_abort, bdata::make( cancelOps ), cancelOp ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &devRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "provide"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + + zypp::test::TVMSettings devSet; + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot1", + .insertedPath = (devRoot/"cd1").asString() + } + ); + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot2", + .insertedPath = "" + } + ); + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot3", + .insertedPath = "" + } + ); + writeTVMConfig( provideRoot, devSet ); + + prov->start(); + + bool gotMediaChange = false; + std::vector freeDevices; + int32_t mediaNrAsked = -1; + std::string labelAsked; + prov->sigMediaChangeRequested().connect([&]( const std::string &ref, const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc ){ + gotMediaChange = true; + freeDevices = devices; + labelAsked = label; + mediaNrAsked = mediaNr; + return cancelOp; + }); + + auto op1 = makeDVDProv( prov, devRoot, 1, "/file1"); + auto op2 = makeDVDProv( prov, devRoot, 2, "/file2"); + + const auto &readyCB = [&](){ + if ( op1->isReady() && op2->isReady() ) + ev->quit(); + }; + + op1->sigReady().connect( readyCB ); + op2->sigReady().connect( readyCB ); + + BOOST_REQUIRE( !op1->isReady() ); + BOOST_REQUIRE( !op2->isReady() ); + + + if ( !op1->isReady() && !op2->isReady() ) + ev->run(); + + BOOST_REQUIRE( gotMediaChange ); + BOOST_REQUIRE_EQUAL( labelAsked, std::string("CD Test Set") ); + BOOST_REQUIRE_EQUAL( mediaNrAsked, 2 ); + BOOST_REQUIRE( std::find( freeDevices.begin(), freeDevices.end(), "/fakedev/tvm/slot2" ) != freeDevices.end() ); + BOOST_REQUIRE( std::find( freeDevices.begin(), freeDevices.end(), "/fakedev/tvm/slot3" ) != freeDevices.end() ); + BOOST_REQUIRE( op1->get().is_valid() ); + BOOST_REQUIRE( !op2->get().is_valid() ); + if ( cancelOp == zyppng::Provide::ABORT ) { + ZYPP_REQUIRE_THROW( std::rethrow_exception( op2->get().error() ), zypp::AbortRequestException ); + } else { + ZYPP_REQUIRE_THROW( std::rethrow_exception( op2->get().error() ), zypp::SkipRequestException ); + } +} + +BOOST_AUTO_TEST_CASE( tvm_jammed ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &devRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "provide"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + + bool gotMediaChange = false; + prov->sigMediaChangeRequested().connect([&]( const std::string &ref, const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc ){ + gotMediaChange = true; + return zyppng::Provide::ABORT; + }); + + zypp::test::TVMSettings devSet; + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot1", + .insertedPath = (devRoot/"cd1").asString() + } + ); + writeTVMConfig( provideRoot, devSet ); + + prov->start(); + + auto op1 = prov->attachMedia( zypp::Url("tvm:/"), zyppng::ProvideMediaSpec("CD Test Set") + .setMediaFile( devRoot / (std::string("cd") + zypp::str::numstring(1)) / (std::string("media.") + zypp::str::numstring(1)) / "media" ) + .setMedianr(1)); + auto op2 = prov->attachMedia( zypp::Url("tvm:/"), zyppng::ProvideMediaSpec("CD Test Set") + .setMediaFile( devRoot / (std::string("cd") + zypp::str::numstring(2)) / (std::string("media.") + zypp::str::numstring(2)) / "media" ) + .setMedianr(2)); + + + + const auto &readyCB = [&](){ + if ( op1->isReady() && op2->isReady() ) + ev->quit(); + }; + + op1->sigReady().connect( readyCB ); + op2->sigReady().connect( readyCB ); + + + BOOST_REQUIRE( !op1->isReady() ); + BOOST_REQUIRE( !op2->isReady() ); + + + if ( !op1->isReady() && !op2->isReady() ) + ev->run(); + + //we have only one drive which is in use, so we can not be asked for media change + BOOST_REQUIRE( !gotMediaChange ); + BOOST_REQUIRE( op1->get().is_valid() ); + BOOST_REQUIRE( !op2->get().is_valid() ); + ZYPP_REQUIRE_THROW( std::rethrow_exception( op2->get().error() ), zypp::media::MediaJammedException ); +} + +// test if we can release a medium and immediately use the resulting free space for new requests +BOOST_AUTO_TEST_CASE( tvm_jammed_release ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + + const auto &workerPath = zypp::Pathname ( TESTS_BUILD_DIR ).dirname() / "tools" / "workers"; + const auto &devRoot = zypp::Pathname ( TESTS_SRC_DIR ) / "zyppng" / "data" / "provide"; + + zypp::filesystem::TmpDir provideRoot; + + auto prov = zyppng::Provide::create ( provideRoot ); + prov->setWorkerPath ( workerPath ); + + zypp::test::TVMSettings devSet; + + bool mediaChangeAllowed = false; + bool gotInvalidMediaChange = false; + prov->sigMediaChangeRequested().connect([&]( const std::string &ref, const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc ){ + if ( ! mediaChangeAllowed ) { + gotInvalidMediaChange = true; + return zyppng::Provide::ABORT; + } + + devSet.devices[0].insertedPath = (devRoot/"cd2").asString(); + writeTVMConfig( provideRoot, devSet ); + return zyppng::Provide::RETRY; + }); + + devSet.devices.push_back( + zypp::test::TVMSettings::Device{ + .name = "/fakedev/tvm/slot1", + .insertedPath = (devRoot/"cd1").asString() + } + ); + writeTVMConfig( provideRoot, devSet ); + + prov->start(); + + auto op1 = prov->attachMedia( zypp::Url("tvm:/"), zyppng::ProvideMediaSpec("CD Test Set") + .setMediaFile( devRoot / (std::string("cd") + zypp::str::numstring(1)) / (std::string("media.") + zypp::str::numstring(1)) / "media" ) + .setMedianr(1)); + + zyppng::AsyncOpRef> op2; + zyppng::AsyncOpRef> op3; + + bool attach1Success = false; + bool attach3Success = false; + std::exception_ptr op2Error; + op1->sigReady().connect( [&]() { + if ( !op1->get() ) { + attach1Success = false; + ev->quit(); + return; + } + + attach1Success = true; + op2 = prov->attachMedia( zypp::Url("tvm:/"), zyppng::ProvideMediaSpec("CD Test Set") + .setMediaFile( devRoot / (std::string("cd") + zypp::str::numstring(2)) / (std::string("media.") + zypp::str::numstring(2)) / "media" ) + .setMedianr(2)); + + op2->sigReady().connect([&](){ + if ( !op2->get().is_valid() ) { + op2Error = op2->get().error(); + + op1.reset(); // kill the first media handle + mediaChangeAllowed = true; + + op3 = prov->attachMedia( zypp::Url("tvm:/"), zyppng::ProvideMediaSpec("CD Test Set") + .setMediaFile( devRoot / (std::string("cd") + zypp::str::numstring(2)) / (std::string("media.") + zypp::str::numstring(2)) / "media" ) + .setMedianr(2)); + op3->sigReady().connect( [&]() { + ev->quit(); + if ( !op3->get() ) + attach3Success = false; + else + attach3Success = true; + }); + return; + } + ev->quit(); + }); + }); + + BOOST_REQUIRE( !op1->isReady() ); + BOOST_REQUIRE( !op2 || !op2->isReady() ); + BOOST_REQUIRE( !op3 || !op3->isReady() ); + + if ( !op1->isReady() ) + ev->run(); + + //we have only one drive which is in use, so we can not be asked for media change + BOOST_REQUIRE( !gotInvalidMediaChange ); + BOOST_REQUIRE( attach1Success ); + BOOST_REQUIRE( op2Error != nullptr ); + ZYPP_REQUIRE_THROW( std::rethrow_exception( op2Error ), zypp::media::MediaJammedException ); + BOOST_REQUIRE( attach3Success ); + BOOST_REQUIRE( !op2->get().is_valid() ); +} + + +#if 0 +BOOST_AUTO_TEST_CASE( dltest_basic ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create (); + auto prov = zyppng::Provide::create ( "/tmp/provTest" ); + prov->setWorkerPath ( "/home/zbenjamin/build/build-libzypp-Desktop_GCC-Debug/tools/workers" ); + prov->start(); + + std::string baseURL = "http://download.opensuse.org/distribution/leap/15.0/repo/oss"; + std::vector downloads { + "11822f1421ae50fb1a07f72220b79000", "/x86_64/0ad-0.0.22-lp150.2.10.x86_64.rpm", + "b0aaaca4c3763792a495de293c8431c5", "/x86_64/alsa-1.1.5-lp150.4.3.x86_64.rpm", + "a6eb92351c03bcf603a09a2e8eddcead", "/x86_64/amarok-2.9.0-lp150.2.1.x86_64.rpm", + "a2fd84f6d0530abbfe6d5a3da3940d70", "/x86_64/aspell-0.60.6.1-lp150.1.15.x86_64.rpm", + "29b5eab4a9620f158331106df4603866", "/x86_64/atk-devel-2.26.1-lp150.2.4.x86_64.rpm", + "a795874986018674c37af85a62c8f28a", "/x86_64/bing-1.0.5-lp150.2.1.x86_64.rpm", + "ce09cb1af156203c89312f9faffce219", "/x86_64/cdrtools-3.02~a09-lp150.2.11.x86_64.rpm", + "3f57113bd0dea2b5d748b7a343a7fb31", "/x86_64/cfengine-3.11.0-lp150.2.3.x86_64.rpm", + "582cae086f67382e71bf02ff0db554cd", "/x86_64/cgit-1.1-lp150.1.5.x86_64.rpm", + "f10cfc37a20c13d59266241ecc30b152", "/x86_64/ck-devel-0.6.0-lp150.1.3.x86_64.rpm", + "4a19708dc8d58129f8832d934c47888b", "/x86_64/cloud-init-18.2-lp150.1.1.x86_64.rpm", + "7b535587d9bfd8b88edf57b6df5c4d99", "/x86_64/collectd-plugin-pinba-5.7.2-lp150.1.4.x86_64.rpm", + "d86c1d65039645a1895f458f38d9d9e7", "/x86_64/compface-1.5.2-lp150.1.4.x86_64.rpm", + "33a0e878c92b5b298cd6aaec44c0aa46", "/x86_64/compositeproto-devel-0.4.2-lp150.1.6.x86_64.rpm", + "646c6cc180caf27f56bb9ec5b4d50f5b", "/x86_64/corosync-testagents-2.4.4-lp150.3.1.x86_64.rpm", + "10685e733abf77e7439e33471b23612c", "/x86_64/cpupower-bench-4.15-lp150.1.4.x86_64.rpm" + }; + + prov->sigMediaChangeRequested().connect([&]( const std::string &ref, const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc ){ + + std::cout << "Please insert medium: " << mediaNr << " of media set " << label << " into one of the free devices: " << std::endl; + if ( desc ) + std::cout << "Media desc: " << *desc << std::endl; + + std::vector choices; + for ( uint i = 0 ; i < devices.size (); i++ ) { + std::cout << "(" << i << ") Free device: " << devices.at(i) << std::endl; + choices.push_back( zypp::str::numstring(i)); + } + + while ( true ) { + std::string choice; + std::cout << "Select the device you want to use, or a for abort" << std::endl; + std::getline( std::cin, choice ); + if ( choice == "a" ) + return zyppng::Provide::ABORT; + + auto i = std::find( choices.begin(), choices.end(), choice ); + if ( i == choices.end() ) { + std::cout << "Invalid answer, please select a device from the list" << std::endl; + continue; + } + + auto sel = std::distance( choices.begin(), i ); + prov->ejectDevice( ref, devices.at(sel) ); + break; + } + + std::string dummy; + std::cout << "Please insert the medium and press a key to continue" << std::endl; + std::getline( std::cin, dummy ); + + return zyppng::Provide::RETRY; + }); + + prov->sigAuthRequired().connect( [&]( const zypp::Url &reqUrl, const std::string &triedUsername, const std::map &extraValues ) -> std::optional { + std::cout << reqUrl << " requires authentication, previously tried username was: " << triedUsername << std::endl; + std::cout << "Please enter the username: " << std::endl; + std::string username; + std::getline ( std::cin, username ); + std::cout << "Please enter the password: " << std::endl; + std::string pass; + std::getline ( std::cin, pass ); + zypp::media::AuthData d( username, pass ); + return d; + }); + + std::vector< zyppng::AsyncOpRef>> ops; +#if 0 + ops.push_back( prov->attachMedia ( baseURL, zyppng::ProvideMediaSpec( "Label1" ).setMediaFile( "/tmp/provTest/media" ).setMedianr(1) ) + | [&]( zyppng::expected &&res ){ + if ( res ) { + std::cout << "Attached as: " << *res << std::endl; + + std::vector>> provs; + for ( std::size_t i = 0; i < downloads.size(); i+=2 ) { + const auto &pName = zypp::Pathname(downloads[i+1]); + std::cout << "Asking to provide file: " << pName << std::endl; + provs.push_back( prov->provide ( *res, pName, zyppng::ProvideFileSpec() ) | []( auto &&res ) { + if ( !res ) { + try { + std::rethrow_exception(res.error()); + } catch ( const zypp::Exception &e ) { + std::cout << "Provide failed with " << e <file () <>(); + } + + std::cout << "Failed to attach media" << std::endl; + return zyppng::makeReadyResult( std::vector> { zyppng::expected::error(res.error()) } ); + } | []( std::vector> &&results ){ + for ( const auto &r : results ) { + if ( !r ) + return zyppng::expected::error( r.error() ); + } + return zyppng::expected::success(); + }); +#endif + + const auto &makeDVDProv = [&]( int mediaNr, const std::string &fName ){ + return prov->attachMedia( zypp::Url("dvd:/"), zyppng::ProvideMediaSpec("CD Test Set") + .setMediaFile("/tmp/provTest/mediacd") + .setMedianr(mediaNr) + .addCustomHeaderValue ("device", "/dev/sr1") + .addCustomHeaderValue ("device", "/dev/sr2")) + | [&]( zyppng::expected &&res ){ + if ( res ) { + std::cout << "Attached as: " << res->handle() << std::endl; + return prov->provide ( *res, fName , zyppng::ProvideFileSpec() ) | [ attachId = *res, &prov ]( auto &&res ) { + if ( !res ) { + try { + std::rethrow_exception(res.error()); + } catch ( const zypp::Exception &e ) { + std::cout << "Provide failed with " << e <file () <::error(res.error()) ); + } + } | []( zyppng::expected &&res ) { + if ( !res ) { + try { + std::rethrow_exception(res.error()); + } catch ( const zypp::Exception &e ) { + std::cout << "Provide failed with " << e <::error(res.error()); + } catch ( ... ) { + std::cout << "Provide failed with exception " << std::endl; + return zyppng::expected::error(res.error()); + } + } else { + return zyppng::expected::success(); + } + }; + }; + + ops.push_back( makeDVDProv(1, "/file1") ); + ops.push_back( makeDVDProv(1, "/file1") ); + ops.push_back( makeDVDProv(1, "/file1") ); + + auto r = std::move(ops) | zyppng::waitFor>(); + r->onReady( [&]( std::vector> &&results ){ + for ( const auto &res : results ) { + if ( res ) { + std::cout << "Request finished successfull" << std::endl; + } else { + try { + std::rethrow_exception (res.error()); + } catch ( const zypp::Exception &e ) { + std::cout << "Request failed with " << e <quit(); + }); + + ev->run (); + return; +} +#endif diff --git a/tests/zyppng/rpc/CMakeLists.txt b/tests/zyppng/rpc/CMakeLists.txt new file mode 100644 index 0000000..5dd6303 --- /dev/null +++ b/tests/zyppng/rpc/CMakeLists.txt @@ -0,0 +1,3 @@ +ADD_TESTS( + StompMessageStream +) diff --git a/tests/zyppng/rpc/StompMessageStream_test.cc b/tests/zyppng/rpc/StompMessageStream_test.cc new file mode 100644 index 0000000..4396b06 --- /dev/null +++ b/tests/zyppng/rpc/StompMessageStream_test.cc @@ -0,0 +1,441 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + + +BOOST_AUTO_TEST_CASE(ReceiveFrame) +{ + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->readFdOpen() ); + + std::optional received; + + auto msgQueue = zyppng::StompFrameStream::create ( dataSource ); + msgQueue->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, [&](){ + received = msgQueue->nextMessage (); + loop->quit(); + }); + + msgQueue->connectFunc( &zyppng::StompFrameStream::sigInvalidMessageReceived, [&](){ + loop->quit(); + }); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + { + std::string_view text ( + "COMMAND\n" + "content-length:5\n" + "\n" + "Hello\0", 32 + ); + + std::thread writer( []( int writeFd, std::string_view text ){ + ::write( writeFd, text.data(), text.length() ); + ::close( writeFd ); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + } + + ::close( pipeFds[0] ); + + BOOST_REQUIRE( received.has_value () ); + BOOST_REQUIRE_EQUAL( received->command (), "COMMAND" ); + BOOST_REQUIRE_EQUAL( received->bodyRef ().asStringView(), "Hello" ); + +} + +BOOST_AUTO_TEST_CASE(ReceiveFrameBinary) +{ + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->readFdOpen() ); + + std::optional received; + + auto msgQueue = zyppng::StompFrameStream::create ( dataSource ); + msgQueue->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, [&](){ + received = msgQueue->nextMessage (); + loop->quit(); + }); + + msgQueue->connectFunc( &zyppng::StompFrameStream::sigInvalidMessageReceived, [&](){ + loop->quit(); + }); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + { + std::string_view text ( + "COMMAND\n" + "content-length:6\n" + "\n" + "He\0llo\0", 33 + ); + + std::thread writer( []( int writeFd, std::string_view text ){ + ::write( writeFd, text.data(), text.length() ); + ::close( writeFd ); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + } + + ::close( pipeFds[0] ); + + BOOST_REQUIRE( received.has_value () ); + BOOST_REQUIRE_EQUAL( received->command (), "COMMAND" ); + BOOST_REQUIRE( received->bodyRef () == zyppng::ByteArray("He\0llo", 6) ); + +} + +BOOST_AUTO_TEST_CASE(ReceiveFrameNoContentLen) +{ + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->readFdOpen() ); + + std::optional received; + + auto msgQueue = zyppng::StompFrameStream::create ( dataSource ); + msgQueue->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, [&](){ + received = msgQueue->nextMessage (); + loop->quit(); + }); + + msgQueue->connectFunc( &zyppng::StompFrameStream::sigInvalidMessageReceived, [&](){ + loop->quit(); + }); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + loop->quit(); + }); + + { + std::string_view text ( + "COMMAND\n" + "\n" + "Hello\0", 15 + ); + + std::thread writer( []( int writeFd, std::string_view text ){ + ::write( writeFd, text.data(), text.length() ); + ::close( writeFd ); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + } + + ::close( pipeFds[0] ); + + BOOST_REQUIRE( received.has_value () ); + BOOST_REQUIRE_EQUAL( received->command (), "COMMAND" ); + BOOST_REQUIRE_EQUAL( received->bodyRef ().asStringView(), "Hello" ); + +} + +BOOST_AUTO_TEST_CASE(ReceiveMultipleFrames) +{ + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->readFdOpen() ); + + bool receivedErr = false; + bool timedOut = false; + std::vector received; + + auto msgQueue = zyppng::StompFrameStream::create ( dataSource ); + msgQueue->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, [&](){ + received.push_back(*msgQueue->nextMessage()); + }); + + msgQueue->connectFunc( &zyppng::StompFrameStream::sigInvalidMessageReceived, [&](){ + receivedErr = true; + loop->quit(); + }); + + dataSource->connectFunc( &zyppng::AsyncDataSource::sigReadChannelFinished, [&]( uint channel ){ + if ( channel == 0 ) + loop->quit(); + }); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + timedOut = true; + loop->quit(); + }); + + { + std::string_view text ( + "COMMAND\n" + "content-length:5\n" + "\n" + "Hello\0", 32 + ); + + std::thread writer( []( int writeFd, std::string_view text ){ + ::write( writeFd, text.data(), text.length() ); + ::write( writeFd, text.data(), text.length() ); + ::write( writeFd, text.data(), text.length() ); + ::close( writeFd ); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + } + + ::close( pipeFds[0] ); + + BOOST_REQUIRE( !timedOut ); + BOOST_REQUIRE( !receivedErr); + BOOST_REQUIRE_EQUAL( received.size (), 3 ); + + for( uint i = 0; i < received.size(); i++ ) { + BOOST_REQUIRE_EQUAL( received[i].command (), "COMMAND" ); + BOOST_REQUIRE_EQUAL( received[i].bodyRef ().asStringView(), "Hello" ); + } + +} + +BOOST_AUTO_TEST_CASE(InvalidFrame) +{ + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->readFdOpen() ); + + std::optional received; + bool receivedErr = false; + bool timedOut = false; + + auto msgQueue = zyppng::StompFrameStream::create ( dataSource ); + msgQueue->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, [&](){ + received = msgQueue->nextMessage (); + loop->quit(); + }); + + msgQueue->connectFunc( &zyppng::StompFrameStream::sigInvalidMessageReceived, [&](){ + receivedErr = true; + loop->quit(); + }); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + timedOut = true; + loop->quit(); + }); + + { + std::string_view text ( + "COMMAND\n" + "content-length-5\n" //wrong header, colon is missing + "\n" + "Hello\0", 32 + ); + + std::thread writer( []( int writeFd, std::string_view text ){ + ::write( writeFd, text.data(), text.length() ); + ::close( writeFd ); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + } + + ::close( pipeFds[0] ); + + BOOST_REQUIRE( !received.has_value () ); + BOOST_REQUIRE( !timedOut ); + BOOST_REQUIRE( receivedErr ); + +} + +BOOST_AUTO_TEST_CASE(BodyNotTerminated) +{ + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSource = zyppng::AsyncDataSource::create(); + + BOOST_REQUIRE( dataSource->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSource->canRead() ); + BOOST_REQUIRE( dataSource->readFdOpen() ); + + std::optional received; + bool receivedErr = false; + bool timedOut = false; + + auto msgQueue = zyppng::StompFrameStream::create ( dataSource ); + msgQueue->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, [&](){ + received = msgQueue->nextMessage (); + loop->quit(); + }); + + msgQueue->connectFunc( &zyppng::StompFrameStream::sigInvalidMessageReceived, [&](){ + receivedErr = true; + loop->quit(); + }); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + timedOut = true; + loop->quit(); + }); + + { + std::string_view text ( + "COMMAND\n" + "content-length:5\n" //wrong header, colon is missing + "\n" + "Hello", 31 + ); + + std::thread writer( []( int writeFd, std::string_view text ){ + ::write( writeFd, text.data(), text.length() ); + ::write( writeFd, text.data(), text.length() ); + ::close( writeFd ); + }, pipeFds[1], text ); + + loop->run(); + writer.join(); + } + + ::close( pipeFds[0] ); + + BOOST_REQUIRE( !received.has_value () ); + BOOST_REQUIRE( !timedOut ); + BOOST_REQUIRE( receivedErr ); + +} + + +BOOST_AUTO_TEST_CASE(SerializeFrame) +{ + int pipeFds[2] { -1, -1 }; + BOOST_REQUIRE( g_unix_open_pipe( pipeFds, FD_CLOEXEC, nullptr ) ); + + auto loop = zyppng::EventLoop::create(); + auto dataSourceRead = zyppng::AsyncDataSource::create(); + auto dataSourceWrite = zyppng::AsyncDataSource::create(); + + BOOST_REQUIRE( dataSourceRead->openFds( { pipeFds[0] } ) ); + BOOST_REQUIRE( dataSourceRead->canRead() ); + BOOST_REQUIRE( dataSourceRead->readFdOpen() ); + + BOOST_REQUIRE( dataSourceWrite->openFds( {}, pipeFds[1] ) ); + BOOST_REQUIRE( dataSourceWrite->canWrite() ); + + zyppng::IODeviceOStreamBuf streamBuf( dataSourceWrite ); + std::ostream outStr( &streamBuf ); + + zypp::PluginFrame data("COMMAND"); + data.addHeader ("header1", "value"); + data.addHeader ("header2", "value"); + data.addHeader ("header3", "value"); + data.setBody ("Somedata"); + + bool gotBytesWritten = false; + dataSourceWrite->connectFunc( &zyppng::IODevice::sigAllBytesWritten, [&](){ + gotBytesWritten = true; + }); + + BOOST_CHECK_NO_THROW(data.writeTo( outStr )); + + std::optional received; + bool receivedErr = false; + bool timedOut = false; + + auto msgQueue = zyppng::StompFrameStream::create ( dataSourceRead ); + msgQueue->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, [&](){ + received = msgQueue->nextMessage (); + loop->quit(); + }); + + msgQueue->connectFunc( &zyppng::StompFrameStream::sigInvalidMessageReceived, [&](){ + receivedErr = true; + loop->quit(); + }); + + // make sure we are not stuck + auto timer = zyppng::Timer::create(); + timer->start( 1000 ); + timer->connectFunc( &zyppng::Timer::sigExpired, [&]( auto & ){ + timedOut = true; + loop->quit(); + }); + + loop->run(); + + ::close( pipeFds[0] ); + + BOOST_REQUIRE( !timedOut ); + BOOST_REQUIRE( !receivedErr ); + BOOST_REQUIRE( received.has_value () ); + BOOST_REQUIRE_EQUAL( received->command(), "COMMAND" ); + BOOST_REQUIRE_EQUAL( received->headerSize(), 3 ); + BOOST_REQUIRE_EQUAL( received->getHeader("header1", {}), "value" ); + BOOST_REQUIRE_EQUAL( received->getHeader("header2", {}), "value" ); + BOOST_REQUIRE_EQUAL( received->getHeader("header3", {}), "value" ); + BOOST_REQUIRE_EQUAL( received->bodyRef().asStringView(), "Somedata"); + +} diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000..6072d56 --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,60 @@ +## ############################################################ + +FILE( GLOB ALLCC RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*.cc" ) +STRING( REPLACE ".cc" ";" APLLPROG ${ALLCC} ) + +# make sure not to statically linked installed tools +SET( LINKALLSYM CalculateReusableBlocks DownloadFiles ) + +FOREACH( loop_var ${APLLPROG} ) + ADD_EXECUTABLE( ${loop_var} + ${loop_var}.cc + ) + TARGET_LINK_LIBRARIES( ${loop_var} PUBLIC zypp_exe_compiler_flags ${Boost_PROGRAM_OPTIONS_LIBRARY} ) + LIST( FIND LINKALLSYM ${loop_var} NEEDALLSYM ) + if ( NEEDALLSYM EQUAL -1 ) + TARGET_LINK_LIBRARIES( ${loop_var} PUBLIC zypp ) + ELSE() + TARGET_LINK_LIBRARIES( ${loop_var} PUBLIC zypp-allsym ) + ENDIF() +ENDFOREACH( loop_var ) + +## ############################################################ + +INSTALL(TARGETS zypp-CheckAccessDeleted DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") +INSTALL(TARGETS zypp-NameReqPrv DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") + + +SET( ZYPP_TOOLS_DIR ${CMAKE_CURRENT_SOURCE_DIR} ) + +ADD_SUBDIRECTORY( zypp-rpm ) +ADD_SUBDIRECTORY( zypp-media-http ) +ADD_SUBDIRECTORY( zypp-media-disc ) +ADD_SUBDIRECTORY( zypp-media-nfs ) +ADD_SUBDIRECTORY( zypp-media-smb ) +ADD_SUBDIRECTORY( zypp-media-dir ) +ADD_SUBDIRECTORY( zypp-media-disk ) +ADD_SUBDIRECTORY( zypp-media-iso ) +ADD_SUBDIRECTORY( zypp-media-copy ) +ADD_SUBDIRECTORY( zypp-media-tvm ) +ADD_SUBDIRECTORY( zypp-media-chksum ) + +## ############################################################ +OPTION( ENABLE_DEVTOOL_REPOMIRROR "Devtool: build repomirror?" OFF ) +IF ( ENABLE_DEVTOOL_REPOMIRROR ) + MESSAGE( STATUS "DEVTOOL_REPOMIRROR enabled" ) + FIND_PACKAGE( Notcurses++ QUIET ) + if ( NOT Notcurses++_FOUND ) + MESSAGE( FATAL_ERROR " DEVTOOL_REPOMIRROR: Notcurses++ not found" ) + ENDIF() + ADD_SUBDIRECTORY( repomirror ) +ENDIF ( ENABLE_DEVTOOL_REPOMIRROR ) +## ############################################################ + +## ############################################################ +OPTION( ENABLE_DEVTOOL_REFRESHNG "Devtool: build refreshng?" OFF ) +IF ( ENABLE_DEVTOOL_REFRESHNG ) + ADD_SUBDIRECTORY( refresh-ng ) +ENDIF ( ENABLE_DEVTOOL_REFRESHNG ) + +## ############################################################ diff --git a/tools/CalculateReusableBlocks.cc b/tools/CalculateReusableBlocks.cc new file mode 100644 index 0000000..dffcc3a --- /dev/null +++ b/tools/CalculateReusableBlocks.cc @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main ( int argc, char *argv[] ) +{ + if ( argc < 3 ) { + std::cerr << "Usage: CalculateReusebleBlocks " << std::endl; + return 1; + } + + constexpr auto checkFileAccessible = []( const zypp::Pathname &path ){ + zypp::PathInfo pi( path ); + return ( pi.isExist() && pi.isFile() && pi.userMayR() ); + }; + + zypp::Pathname metaLink( zypp::str::asString(argv[1]) ); + zypp::Pathname deltaFile( zypp::str::asString(argv[2]) ); + + if ( !checkFileAccessible(metaLink) ) { + std::cerr << "Metalink file at " << metaLink << " not accessible" << std::endl; + return 1; + } + + if ( !checkFileAccessible(deltaFile) ) { + std::cerr << "Deltafile file at " << deltaFile << " not accessible" << std::endl; + return 1; + } + + zypp::media::MediaBlockList blocks; + if ( zypp::str::hasSuffix( metaLink.asString(), "zsync") ) { + zypp::media::ZsyncParser parser; + try { + parser.parse( metaLink.asString() ); + blocks = parser.getBlockList(); + } catch (const zypp::Exception& e) { + std::cerr << "Failed to parse Metalink file: " << e << std::endl; + return 1; + } catch ( const std::exception &e ) { + std::cerr << "Failed to parse Metalink file: " << e.what() << std::endl; + return 1; + } + } else { + zypp::media::MetaLinkParser parser; + try { + parser.parse( metaLink ); + blocks = parser.getBlockList(); + } catch(const zypp::Exception& e) { + std::cerr << "Failed to parse Metalink file: " << e << std::endl; + return 1; + } + } + + constexpr auto getDownloadSize = []( const zypp::media::MediaBlockList &blocks ){ + size_t size = 0; + for ( size_t i = 0; i < blocks.numBlocks(); i++ ) { + size += blocks.getBlock(i).size; + } + return size; + }; + + zypp::filesystem::TmpFile file; + const auto numBlocksBefore = blocks.numBlocks(); + const zypp::ByteCount sizeBefore = getDownloadSize(blocks); + + std::cout << "Blocks parsed from Metalink file: " << numBlocksBefore << std::endl; + if ( numBlocksBefore ) { + zypp::AutoFILE f( fopen( "Out.test.gz", "w")); + if ( *f ) { + blocks.reuseBlocks( *f, deltaFile.asString() ); + } + } + + const size_t numBlocksAfter = blocks.numBlocks(); + const zypp::ByteCount sizeAfter = getDownloadSize(blocks); + + std::cout << "Finished, reused " << ( numBlocksBefore - numBlocksAfter ) << " of " << numBlocksBefore << " blocks." << std::endl; + std::cout << "Need to download " << sizeAfter << " of " << sizeBefore << std::endl; + return 0; +} diff --git a/tools/DiskUsageCounter.cc b/tools/DiskUsageCounter.cc new file mode 100644 index 0000000..636b028 --- /dev/null +++ b/tools/DiskUsageCounter.cc @@ -0,0 +1,54 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "argparse.h" + +#include +#include + +using std::cout; +using std::cerr; +using std::endl; + +static std::string appname { "NO_NAME" }; + +int errexit( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + cerr << endl << appname << ": ERR: " << msg_r << endl << endl; + return exit_r; +} + +int usage( const argparse::Options & options_r, int return_r = 0 ) +{ + cerr << "USAGE: " << appname << " [OPTION]... [ARGS]..." << endl; + cerr << " Print default mountpoint set for disk usage computation." << endl; + cerr << options_r << endl; + return return_r; +} + +int main( int argc, char * argv[] ) +{ + appname = Pathname::basename( argv[0] ); + + std::string sysRoot { "/" }; + + argparse::Options options; + options.add() + ( "help,h", "Print help and exit." ) + ( "root", "Use the system located below ROOTDIR.", argparse::Option::Arg::required ) + ; + auto result = options.parse( argc, argv ); + + if ( result.count( "help" ) ) + return usage( options ); + + if ( result.count( "root" ) ) + sysRoot = result["root"].arg(); + + // go... + cout << "DiskUsageCounter: relevant mount points detected below '" << sysRoot << "':" << endl; + cout << DiskUsageCounter::detectMountPoints( sysRoot ) << endl; + + return 0; +} diff --git a/tools/DownloadFiles.cc b/tools/DownloadFiles.cc new file mode 100644 index 0000000..c2824d7 --- /dev/null +++ b/tools/DownloadFiles.cc @@ -0,0 +1,259 @@ +// A small tool to test the downloader backend in zypp +// takes a yaml file as first argument that has a list of downloadable files and possible deltafiles to +// use when requesting the file: +// - url: "https://dlmirror.foo/file1" +// delta: "/path/to/delta1" +// - url: "https://dlmirror.foo/file2" +// delta: "/path/to/file2" + + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace po = boost::program_options; + +struct DLEntry { + zypp::Url _url; + zypp::Pathname _deltaFile; + zypp::ByteCount _dlSize; +}; + +// progress for downloading a file +struct DownloadProgressReportReceiver : public zypp::callback::ReceiveReport +{ + DownloadProgressReportReceiver() + { + connect(); + } + + virtual void start( const zypp::Url & uri, zypp::Pathname localfile ) + { + _last_drate_avg = -1; + std::cout << "Starting download of: " << uri << " to " << localfile << std::endl; + ztui::Application::instance ().out().dwnldProgressStart( uri ); + } + + virtual bool progress(int value, const zypp::Url & uri, double drate_avg, double drate_now) + { + ztui::Application::instance ().out().dwnldProgress( uri, value, (long) drate_now); + _last_drate_avg = drate_avg; + return true; + } + + virtual DownloadProgressReport::Action + problem( const zypp::Url & uri, DownloadProgressReport::Error error, const std::string & description ) + { + if ( error == DownloadProgressReport::NO_ERROR ) { + // NO_ERROR: just a report but let the caller proceed as appropriate... + ztui::Application::instance().out().info() << "- " << ( ztui::ColorContext::LOWLIGHT << description ); + return DownloadProgressReport::IGNORE; + } + ztui::Application::instance().out().dwnldProgressEnd(uri, _last_drate_avg, true); + return DownloadProgressReport::ABORT; + } + + // used only to finish, errors will be reported in media change callback (libzypp 3.20.0) + virtual void finish( const zypp::Url & uri, Error error, const std::string & konreason ) + { + ztui::Application::instance().out().dwnldProgressEnd( + uri, _last_drate_avg, ( error == NOT_FOUND ? zypp::indeterminate : zypp::TriBool(error != NO_ERROR) ) ); + } + +private: + double _last_drate_avg; +}; + + + +int main ( int argc, char *argv[] ) +{ + // force the use of the new downloader code + setenv("ZYPP_MEDIANETWORK", "1", 1); + ztui::Application app; + + auto appname = zypp::Pathname::basename( argv[0] ); + po::positional_options_description p; + p.add("control-file", 1); + + po::options_description visibleOptions("Allowed options"); + visibleOptions.add_options() + ("help", "produce help message") + ("mediabackend" , po::value()->default_value("legacy"), "Select the mediabackend to use, possible options: legacy, provider") + ("target-dir" , po::value()->default_value("."), "Directory where to download the files to." ); + + po::options_description positionalOpts; + positionalOpts.add_options () + ("control-file" , po::value(), "Control file to read the urls from" ); + + po::options_description cmdline_options; + cmdline_options.add(visibleOptions).add(positionalOpts); + + const auto &usage = [&](){ + std::cerr << "Usage: " << appname << " [OPTIONS] " << std::endl; + std::cerr << visibleOptions << std::endl; + }; + + po::variables_map vm; + + try { + po::store(po::command_line_parser(argc, argv). + options(cmdline_options).positional(p).run(), vm); + po::notify(vm); + } catch ( const po::error & e ) { + std::cerr << e.what () << std::endl; + usage(); + } + + if ( vm.count ("help") ) { + usage(); + return 0; + } + + if ( !vm.count("control-file") ) { + std::cerr << "Missing the required control-file argument.\n" << std::endl; + usage(); + return 1; + } + + const auto &cFInfo = zypp::PathInfo( vm["control-file"].as()); + if ( !cFInfo.isExist() || !cFInfo.userMayR() ) { + std::cerr << "Control file " << cFInfo.path () << " is not accessible" << std::endl; + usage(); + return 1; + } + + if ( !vm.count("mediabackend") + || ( vm["mediabackend"].as() != "legacy" && vm["mediabackend"].as() != "provider" ) ) { + std::cerr << "Invalid value given for mediabackend option: " << vm["mediabackend"].as() <<".\n"; + usage(); + return 1; + } + + if ( !vm.count("target-dir") ) { + std::cerr << "Targetdir not initialized, this is a bug.\n" << std::endl; + usage(); + return 1; + } + + const zypp::PathInfo targetDir( vm["target-dir"].as() ); + if ( !targetDir.isDir() || !targetDir.userMayRWX() ) { + std::cerr << "Target directory is not accessible." << std::endl; + usage(); + return 1; + } + + constexpr auto makeError = [] ( const std::string &str ) { + std::cerr << str << std::endl; + return 1; + }; + + std::vector entries; + + YAML::Node control; + try { + control = YAML::LoadFile( cFInfo.path().asString() ); + + if ( control.Type() != YAML::NodeType::Sequence ) + return makeError("Root node must be of type Sequence."); + + for ( const auto &dlFile : control ) { + const auto &url = dlFile["url"]; + if ( !url ) { + return makeError("Each element in the control sequence needs a \"url\" field."); + } + if ( url.Type() != YAML::NodeType::Scalar ) + return makeError("Field 'url' must be a scalar."); + + zypp::Url dlUrl( url.as () ); + zypp::Pathname deltaFile; + zypp::ByteCount downloadSize; + + const auto &delta = dlFile["delta"]; + if ( delta ) { + if ( delta.Type() != YAML::NodeType::Scalar ) + return makeError("Field 'delta' must be a scalar."); + + deltaFile = zypp::Pathname( delta.as() ); + } + + const auto &dlSize = dlFile["dlSize"]; + if ( dlSize ) { + if ( dlSize.Type() != YAML::NodeType::Scalar ) + return makeError("Field 'delta' must be a scalar."); + + downloadSize = zypp::ByteCount( dlSize.as() ); + } + + + entries.push_back ( { std::move(dlUrl), std::move(deltaFile), std::move(downloadSize) } ); + } + } catch ( YAML::Exception &e ) { + std::cerr << "YAML exception: " << e.what() << std::endl; + return 1; + } catch ( const std::exception &e ) { + std::cerr << "Error when parsing the control file: " << e.what() << std::endl; + return 1; + } catch ( ... ) { + std::cerr << "Unknown error when parsing the control file" << std::endl; + return 1; + } + + std::vector< zypp::ManagedFile > files; + + std::cout << "Using yaml: " << cFInfo.path() << "\n" + << "Downloading to: " << targetDir.path ().realpath ()<< "\n" + << "Using backend: " << vm["mediabackend"].as() << "\n" + << "Nr of downloads: " << entries.size() << "\n" << std::endl; + + if ( vm["mediabackend"].as() == "provider" ) { + std::cerr << "The provider support is not yet implemented, please try again later." << std::endl; + return 1; + } + + + DownloadProgressReportReceiver receiver; + + if ( entries.size() ) { + for ( const auto &e : entries ) { + try { + + zypp::Url url(e._url); + zypp::Pathname path(url.getPathName()); + + url.setPathName ("/"); + zypp::MediaSetAccess access(url); + + zypp::ManagedFile locFile( targetDir.path().realpath() / path, zypp::filesystem::unlink ); + zypp::filesystem::assert_dir( locFile->dirname() ); + + auto file = access.provideFile( + zypp::OnMediaLocation(path, 1) + .setOptional ( false ) + .setDeltafile ( e._deltaFile ) + .setDownloadSize ( e._dlSize ) ); + + //prevent the file from being deleted when MediaSetAccess gets out of scope + if ( zypp::filesystem::hardlinkCopy(file, locFile) != 0 ) + ZYPP_THROW( zypp::Exception("Can't copy file from " + file.asString() + " to " + locFile->asString() )); + + std::cout << "File downloaded: " << e._url << std::endl; + files.push_back ( locFile ); + + } catch ( const zypp::Exception &e ) { + std::cerr << "Failed to download file: " << e << std::endl; + } + } + } + + //std::cout << "Done, press any key to continue" << std::endl; + //getchar(); + return 0; +} diff --git a/tools/DumpSelectable.cc b/tools/DumpSelectable.cc new file mode 100644 index 0000000..e35359a --- /dev/null +++ b/tools/DumpSelectable.cc @@ -0,0 +1,170 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST + +#include +#include +#include + +static std::string appname( "DumpSelectable" ); + +#define message cout +using std::flush; + +int errexit( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + return exit_r; +} + +int usage( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + cerr << "Usage: " << appname << " [--root ROOTDIR] [OPTIONS] NAME..." << endl; + cerr << " Load all enabled repositories (no refresh) and search for" << endl; + cerr << " Selectables names NAME" << endl; + cerr << " --root Load repos from the system located below ROOTDIR. If ROOTDIR" << endl; + cerr << " denotes a sover testcase, the testcase is loaded." << endl; + cerr << " -v Verbose list solvables data." << endl; + cerr << "" << endl; + return exit_r; +} + +void dumpPi( std::ostream & message, const PoolItem & pi ) +{ + std::string indent(" "); + message << indent << "--------------------------------------------------" << endl; + message << indent << (pi->isSystem() ? "i " : "a ") << pi->satSolvable().asString() << endl; + message << indent << pi->summary() << endl; + if ( pi->isKind() ) + { + message << indent << pi->asKind()->changelog() << endl; + } +} + +/****************************************************************** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +*/ +int main( int argc, char * argv[] ) +{ + INT << "===[START]==========================================" << endl; + appname = Pathname::basename( argv[0] ); + --argc,++argv; + + Pathname sysRoot("/"); + bool verbose = false; + + while ( argc && (*argv)[0] == '-' ) + { + if ( (*argv) == std::string("--root") ) + { + --argc,++argv; + if ( ! argc ) + return errexit("--root requires an argument."); + + if ( ! PathInfo( *argv ).isDir() ) + return errexit("--root requires a directory."); + + sysRoot = *argv; + } + else if ( (*argv) == std::string("-v") ) + { + verbose = true; + } + + --argc,++argv; + } + + if ( ! argc ) + { + return usage(); + } + + /////////////////////////////////////////////////////////////////// + + ZConfig::instance(); + sat::Pool satpool( sat::Pool::instance() ); + + if ( TestSetup::isTestcase( sysRoot ) ) + { + message << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl; + TestSetup test; + test.loadTestcaseRepos( sysRoot ); + } + else if ( TestSetup::isTestSetup( sysRoot ) ) + { + message << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl; + TestSetup test( sysRoot, Arch_x86_64 ); + test.loadRepos(); + } + else + { + // a system + message << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl; + if ( true ) + { + message << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl; + getZYpp()->initializeTarget( sysRoot ); + getZYpp()->target()->load(); + message << satpool.systemRepo() << endl; + } + + if ( true ) + { + RepoManager repoManager( sysRoot ); + RepoInfoList repos = repoManager.knownRepositories(); + for_( it, repos.begin(), repos.end() ) + { + RepoInfo & nrepo( *it ); + + if ( ! nrepo.enabled() ) + continue; + + if ( ! repoManager.isCached( nrepo ) ) + { + message << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + + message << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush; + try + { + repoManager.loadFromCache( nrepo ); + message << satpool.reposFind( nrepo.alias() ) << endl; + } + catch ( const Exception & exp ) + { + message << exp.asString() + "\n" + exp.historyAsString() << endl; + message << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + } + } + } + + /////////////////////////////////////////////////////////////////// + + for ( ; argc; --argc,++argv ) + { + ui::Selectable::Ptr sel( ui::Selectable::get( IdString( *argv ) ) ); + message << dump( sel ) << endl; + if ( verbose ) + { + for_( it, sel->installedBegin(), sel->installedEnd() ) + dumpPi( message, *it ); + for_( it, sel->availableBegin(), sel->availableEnd() ) + dumpPi( message, *it ); + } + } + + INT << "===[END]============================================" << endl << endl; + return 0; +} diff --git a/tools/ProvideSignedDirectory.cc b/tools/ProvideSignedDirectory.cc new file mode 100644 index 0000000..119220d --- /dev/null +++ b/tools/ProvideSignedDirectory.cc @@ -0,0 +1,55 @@ +#include + +#include +#include +#include + +#include +#include +#include +#include + + +using std::endl; + +int main ( int argc, const char * argv[] ) +try { + --argc; + ++argv; + //zypp::base::LogControl::instance().logToStdErr(); + INT << "===[START]==========================================" << endl; + /////////////////////////////////////////////////////////////////// + + zypp::Url oRemoteUrl( argv[0] ); //"http://download.opensuse.org/distribution/openSUSE-current/repo/oss" ); + std::string oRemoteDir( argv[1] ); //"/suse/setup/slide" ); + const bool oRecursive( true ); + zypp::Pathname oLocalDir( "" ); + + zypp::scoped_ptr tmpdir; + if ( oLocalDir.empty() ) + { + tmpdir.reset( new zypp::filesystem::TmpDir ); + oLocalDir = tmpdir->path(); + } + + zypp::Fetcher fetcher; + fetcher.setOptions( zypp::Fetcher::AutoAddIndexes ); + fetcher.enqueueDir( zypp::OnMediaLocation( oRemoteDir ), oRecursive ); + + zypp::KeyRing::setDefaultAccept( zypp::KeyRing::TRUST_KEY_TEMPORARILY ); + zypp::MediaSetAccess media( oRemoteUrl, "/" ); + fetcher.start( oLocalDir, media ); + + zypp::ExternalProgram( "find "+(oLocalDir/oRemoteDir).asString()+" -ls" ) >> std::cout; + + /////////////////////////////////////////////////////////////////// + INT << "===[END]============================================" << endl << endl; + zypp::base::LogControl::instance().logNothing(); + return 0; +} +catch ( const zypp::Exception & exp ) +{ + INT << exp << endl << exp.historyAsString(); +} +catch (...) +{} diff --git a/tools/ScanTwHistory b/tools/ScanTwHistory new file mode 100755 index 0000000..0a7b6df --- /dev/null +++ b/tools/ScanTwHistory @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 + +import urllib3 +import sys +import re + +p = re.compile('.*debuginfo.*') + +http = urllib3.PoolManager() +r = http.request('GET', 'http://download.opensuse.org/history/list') +if ( r.status != 200 ): + print("Failed to download history list\n") + sys.exit(1) + +html = r.data.decode("utf-8") +list = html.split("\n") + +for i in list: + if ( len(i) == 0 ): + continue + print ( "Searching for history in: "+i ) + rEntries = http.request('GET', "http://download.opensuse.org/history/"+i.strip()+"/rpm.list", preload_content=False ) + if ( rEntries.status != 200 ): + print("Failed to download history database for "+i+"\n") + continue + + for line in rEntries: + if ( p.search( line.decode() ) ): + print("Found match: "+line.decode()+" in: "+"http://download.opensuse.org/history/"+i.strip() ) + + +print("Done") \ No newline at end of file diff --git a/tools/ToolScanRepos.cc b/tools/ToolScanRepos.cc new file mode 100644 index 0000000..3b9e7e3 --- /dev/null +++ b/tools/ToolScanRepos.cc @@ -0,0 +1,136 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST + +static std::string appname( "ToolScanRepos" ); + +void message( const std::string & msg_r ) +{ + cerr << "*** " << msg_r << endl; +} + +int usage( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl; + message( msg_r ); + cerr << endl; + } + cerr << "Usage: " << appname << "[OPTIONS] URL..." << endl; + cerr << " Load repos from URL to test system below /tmp/" << appname << "." << endl; + cerr << " -r ROOT Use /tmp/ROOT as location of test system (default: " << appname << ")." << endl; + cerr << " -a ARCH Use ARCH as test system architecture (default: x86_64)." << endl; + cerr << " -c Clear an existing test system (default)." << endl; + cerr << " -n Do not clear an existing test system but reuse it." << endl; + return exit_r; +} + +/****************************************************************** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +*/ +int main( int argc, char * argv[] ) +{ + INT << "===[START]==========================================" << endl; + appname = Pathname::basename( argv[0] ); + --argc; + ++argv; + + if ( ! argc ) + { + return usage(); + } + + /////////////////////////////////////////////////////////////////// + Pathname mtmp( "/tmp" ); + Pathname mroot( mtmp/appname ); + Arch march( Arch_x86_64 ); + bool oClearRoot = true; + + std::vector urls; + + while ( argc ) + { + if ( argv[0] == std::string("-c") ) + { + oClearRoot = true; + } + else if ( argv[0] == std::string("-n") ) + { + oClearRoot = false; + } + else if ( argv[0] == std::string("-r") || argv[0] == std::string("--root")) + { + --argc; + ++argv; + if ( ! argc ) + return usage( "Missing arg to -r ROOT", 101 ); + + if ( *(argv[0]) ) // empty + mroot = mtmp/argv[0]; + else + mroot = mtmp/appname; + } + else if ( argv[0] == std::string("-a") ) + { + --argc; + ++argv; + if ( ! argc ) + return usage( "Missing arg to -a ARCH", 101 ); + + if ( *(argv[0]) ) // empty + march = Arch( argv[0] ); + else + march = Arch_x86_64; + } + else + { + urls.push_back( argv[0] ); + } + --argc; + ++argv; + } + + if ( urls.empty() ) + { + return usage( "Missing URLs", 102 ); + } + + /////////////////////////////////////////////////////////////////// + + if ( oClearRoot ) + { + message( "Clear test system at " + mroot.asString() ); + filesystem::recursive_rmdir( mroot ); + } + else + { + message( "Use test system at " + mroot.asString() ); + } + filesystem::assert_dir( mroot ); + base::LogControl::instance().logfile( mroot/"ToolScanRepos.log" ); + message( "Use logfile " + (mroot/"ToolScanRepos.log").asString() ); + + message( "Use archiecture " + march.asString() ); + TestSetup test( mroot, march ); + + int ret = 0; + for_( it, urls.begin(), urls.end() ) + { + message( "Setup " + *it ); + try + { + test.loadRepo( *it ); + } + catch ( const Exception & exp ) + { + message( exp.asString() + "\n" + exp.historyAsString() ); + ++ret; + } + } + + INT << "===[END]============================================" << endl << endl; + return ret; +} diff --git a/tools/argparse.h b/tools/argparse.h new file mode 100644 index 0000000..c3c4160 --- /dev/null +++ b/tools/argparse.h @@ -0,0 +1,340 @@ +#ifndef ZYPP_TOOLS_ARGPARSE_H +#define ZYPP_TOOLS_ARGPARSE_H + +#include +#include +#include +#include +#include +#include + +//#include seems to be bad with gcc < 4.9 +#include + +/////////////////////////////////////////////////////////////////// +/// Simple arg parser for tools +/// \code +/// argparse::Options options; +/// options.add() +/// ( "help,h", "Print help and exit." ) +/// ( "root", "Use the system located below ROOTDIR.", argparse::Option::Arg::required ) +/// ; +/// auto result = options.parse( argc, argv ); +/// +/// if ( result.count( "root" ) ) +/// sysRoot = result["root"].arg(); +/// \endcode +namespace argparse +{ + using zypp::str::regex; + using zypp::str::smatch; + using zypp::str::regex_match; + + /////////////////////////////////////////////////////////////////// + /// Exception thrown when defining Options or parsing. + class OptionException : public std::exception + { + public: + OptionException( std::string msg_r ) + : _msg { std::move(msg_r) } + {} + + OptionException( std::string msg_r, const std::string & msg2_r ) + : _msg { std::move(msg_r) } + { if ( ! msg2_r.empty() ) _msg += msg2_r; } + + const char* what() const noexcept override + { return _msg.c_str(); } + + private: + std::string _msg; + }; + + /////////////////////////////////////////////////////////////////// + /// Option description (TBD define arg consumer) + class Option + { + public: + enum class Arg { none, required, optional }; + + public: + Option( std::string descr_r, Arg hasarg_r ) + : _descr { std::move(descr_r) } + , _hasarg { hasarg_r } + { + if ( hasarg_r == Arg::optional ) + throw OptionException( "Not yet implemented: Option::Arg::optional" ); + } + + const std::string & descr() const + { return _descr; } + + Arg hasarg() const + { return _hasarg; } + + private: + std::string _descr; + Arg _hasarg; + }; + + + class ParsedOptions; + + /////////////////////////////////////////////////////////////////// + /// Map of option names -> option descriptions. + class Options + { + typedef std::unordered_map> OptionMap; + public: + Options() + {} + + public: + class Injector + { + public: + Injector( OptionMap & optmap_r ) + : _optmap { optmap_r } + {} + + Injector & operator()( const std::string & names_r, std::string descr_r, Option::Arg hasarg_r = Option::Arg::none ) + { + smatch result; + if ( regex_match( names_r, result, regex("([[:alnum:]][-_[:alnum:]]+)(,([[:alnum:]]))?") ) ) + { + auto opt = std::make_shared( std::move(descr_r), hasarg_r ); + add( result[1], opt ); + if ( ! result[3].empty() ) + add( result[3], opt ); + } + else + throw OptionException( "Illegal option names: ", names_r ); + + return *this; + } + + private: + void add( std::string name_r, std::shared_ptr opt_r ) + { + if ( _optmap.count( name_r ) ) + throw OptionException( "Duplicate option name: ", name_r ); + _optmap[name_r] = opt_r; + } + + private: + OptionMap & _optmap; + }; + + Injector add() + { return Injector( _optmap ); } + + public: + ParsedOptions parse( int argc, char * argv[] ) const; + + public: + std::ostream & dumpOn( std::ostream & str_r ) const + { + str_r << "OPTIONS:"; + if ( ! _optmap.empty() ) + { + std::unordered_map, std::string> unify; + for ( const auto & p : _optmap ) + { + std::string & t { unify[p.second] }; + if ( t.empty() ) + t = (p.first.length()>1?"--":"-")+p.first; + else if ( p.first.length() > 1 ) + t = "--"+p.first+", "+t; + else + t = t+", -"+p.first; + } + + boost::format fmt( "\n %1% %|30t|%2%" ); + for ( const auto & p : unify ) + { + fmt % p.second % p.first->descr(); + str_r << fmt.str(); + } + } + else + { + str_r << " This command accepts no options."; + } + return str_r; + } + + private: + OptionMap _optmap; + }; + + inline std::ostream & operator<<( std::ostream & str_r, const Options & obj_r ) + { return obj_r.dumpOn( str_r ); } + + /////////////////////////////////////////////////////////////////// + /// Parsed option incl. option args value (by now just stores the string) + class OptionValue + { + public: + OptionValue( std::shared_ptr opt_r ) + : _opt { opt_r } + {} + + OptionValue( std::shared_ptr opt_r, std::string arg_r ) + : _opt { opt_r } + , _arg { std::make_shared( std::move(arg_r) ) } + {} + + const std::string & arg() const + { + if ( ! _arg ) + throw std::domain_error( "No arg value" ); + + return *_arg; + } + + private: + std::shared_ptr _opt; + std::shared_ptr _arg; + }; + + /////////////////////////////////////////////////////////////////// + /// Parsed options and positional args + class ParsedOptions + { + typedef std::unordered_map> OptionMap; + typedef std::unordered_map, OptionValue> ResultMap; + public: + ParsedOptions( const OptionMap & optmap_r, int argc, char * argv[] ) + : _optmap { optmap_r } + { parse( argc, argv ); } + + public: + size_t count( const std::string & optname_r ) const + { + auto iter = _optmap.find( optname_r ); + if ( iter == _optmap.end() ) + return 0; + + auto resiter = _options.find( iter->second ); + return( resiter == _options.end() ? 0 : 1 ); + } + + const OptionValue & operator[]( const std::string & optname_r ) const + { + return requireOptValByName( optname_r ); + } + + const std::vector & positionals() const + { return _positionals; } + + private: + void parse( int argc, char * argv[] ) + { + bool collectpositional = false; + for ( --argc,++argv; argc; --argc,++argv ) + { + if ( (*argv)[0] == '-' && !collectpositional ) + { + if ( (*argv)[1] == '-' ) + { + if ( (*argv)[2] == '\0' ) + { + // -- rest are positional... + collectpositional = true; + } + else + { + // --longopt + parseoptl( (*argv)+2, argc, argv ); + } + } + else + { + // -s(hortopt) + parseopts( (*argv)+1, argc, argv ); + } + } + else + { + // positional + _positionals.push_back( *argv ); + } + } + } + + private: + std::string dashed( std::string name_r ) const + { return name_r.insert( 0, name_r.size()>1?"--":"-" ); } + + void parseoptl( const std::string & name_r, int & argc, char **& argv ) + { + if ( name_r.length() < 2 ) + throw OptionException( "Illegal long opt: --", name_r ); + + parseopt( name_r, argc, argv ); + } + + void parseopts( const std::string & name_r, int & argc, char **& argv ) + { + if ( name_r.length() != 1 ) + throw OptionException( "Illegal short opt: -", name_r ); + + parseopt( name_r, argc, argv ); + } + + void parseopt( const std::string & name_r, int & argc, char **& argv ) + { + auto opt = requireOptByName( name_r ); + + auto iter = _options.find( opt ); + if ( iter != _options.end() ) + throw OptionException( "Multiple occurrences of option: ", dashed( name_r ) ); + + if ( opt->hasarg() != Option::Arg::none ) + { + if ( opt->hasarg() == Option::Arg::optional ) + throw OptionException( "Not yet implemented: Option::Arg::optional" ); // i.e. '--opt=arg' + + if ( argc < 2 ) + throw OptionException( "Missing argument for option: ", dashed( name_r ) ); + + --argc,++argv; + moveToResult( opt, OptionValue( opt, *argv ) ); + } + else + moveToResult( opt, OptionValue( opt ) ); + } + + void moveToResult( std::shared_ptr opt_r, OptionValue && value_r ) + { _options.insert( std::make_pair( opt_r, std::move(value_r) ) ); } + + std::shared_ptr requireOptByName( const std::string & name_r ) const + { + auto iter = _optmap.find( name_r ); + if ( iter == _optmap.end() ) + throw OptionException( "Unknown option: ", dashed( name_r ) ); + return iter->second; + } + + const OptionValue & requireOptValByName( const std::string & name_r ) const + { + auto iter = _options.find( requireOptByName( name_r ) ); + if ( iter == _options.end() ) + throw OptionException( "Option not present: ", dashed( name_r ) ); + return iter->second; + } + + private: + const OptionMap & _optmap; + ResultMap _options; + std::vector _positionals; + }; + + inline ParsedOptions Options::parse( int argc, char * argv[] ) const + { return ParsedOptions( _optmap, argc, argv ); } + + + +} // namespace argparse +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TOOLS_ARGPARSE_H diff --git a/tools/migrate-sources/CMakeLists.txt b/tools/migrate-sources/CMakeLists.txt new file mode 100644 index 0000000..d89ebeb --- /dev/null +++ b/tools/migrate-sources/CMakeLists.txt @@ -0,0 +1,9 @@ +SET( migrate_SRCS +migrate-sources.cc +) + +ADD_EXECUTABLE( zypp-migrate-sources ${migrate_SRCS} ) +TARGET_LINK_LIBRARIES( zypp-migrate-sources zypp ) +TARGET_LINK_LIBRARIES( zypp-migrate-sources xml2 ) + +INSTALL(TARGETS zypp-migrate-sources RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/zypp ) \ No newline at end of file diff --git a/tools/migrate-sources/migrate-sources.cc b/tools/migrate-sources/migrate-sources.cc new file mode 100644 index 0000000..7ceb802 --- /dev/null +++ b/tools/migrate-sources/migrate-sources.cc @@ -0,0 +1,185 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp-cache" + + +using namespace zypp; + +struct Options +{ + Options() + : fake(false) + , root("/") + , sources_dir("/var/lib/zypp/db/sources") + {} + + bool fake; + Pathname root; + Pathname sources_dir; +}; + +static void clear_cache( const Options &opt ) +{ + Pathname path = opt.root + "/var/lib/zypp/cache"; + if ( PathInfo(path).isDir() ) + { + cout << "Deleting old cache directory (" << path << ")." << endl; + if ( ! opt.fake ) + { + if ( filesystem::recursive_rmdir(path) != 0 ) + ERR << "Error removing cache directory" << path << endl; + } + } + + path = opt.root + "/var/lib/zypp/db"; + if ( PathInfo(path).isDir() ) + { + cout << "Deleting old db directory (" << path << ")." << endl; + if ( ! opt.fake ) + { + if ( filesystem::recursive_rmdir(path) != 0 ) + ERR << "Error removing db directory" << path << endl; + } + } +} + +static void migrate_sources( const Options &opt ) +{ + if ( getenv("YAST_IS_RUNNING") && (string(getenv("YAST_IS_RUNNING")) == "instsys" )) + { + MIL << "YaST is running in instsys. Not migrating old sources. YaST will do it." << endl; + return; + } + else + { + MIL << "YaST not running in instsys." << endl; + } + + zypp::zypp_readonly_hack::IWantIt(); + ZYpp::Ptr Z = zypp::getZYpp(); + RepoManager manager; + + Pathname source_p = opt.root + opt.sources_dir; + + if ( ! PathInfo(source_p).isExist() ) + { + cout << "No sources to migrate." << endl; + clear_cache( opt ); + return; + } + + RepoInfoList sources; + DBG << "Reading source cache in " << source_p << std::endl; + + list entries; + if ( filesystem::readdir( entries, source_p, false ) != 0 ) + ZYPP_THROW(Exception("failed to read directory")); + + int i=0; + for ( list::const_iterator it = entries.begin(); it != entries.end(); ++it ) + { + + MIL << "Processing " << *it << endl; + + std::ifstream anIstream((*it).c_str()); + zypp::parser::xmlstore::XMLSourceCacheParser iter(anIstream, ""); + for (; ! iter.atEnd(); ++iter) { + RepoInfo data = **iter; + string alias = "migrated_" + str::numstring(i); + try { + data.setAlias(alias); + data.setEnabled(false); + cout << "Migrating repo: " << endl << data << endl; + if ( ! opt.fake ) + { + manager.addRepository(data); + } + cout << "Deleting old source: " << *it << endl; + if ( ! opt.fake ) + { + if ( filesystem::unlink(*it) != 0 ) + ERR << "Error removing source " << *it << endl; + // delete old file + } + cout << "saved as " << alias << endl; + ++i; + } + catch ( const Exception &e ) + { + cout << "Error adding repository: " << e.msg() << endl << data << endl; + } + + } + + } + cout << i << " sources migrated."<< endl; + + // reread entries + if ( filesystem::readdir( entries, source_p, false ) != 0 ) + ZYPP_THROW(Exception("failed to read directory")); + if ( entries.size() == 0 ) + { + cout << "all sources migrated. deleting old source directory"<< endl; + if ( ! opt.fake ) + { + if ( filesystem::recursive_rmdir(source_p) != 0 ) + ERR << "Error removing source directory" << source_p << endl; + + clear_cache( opt ); + } + } + else + { + cout << "Not all sources migrated. leaving old source directory"<< endl; + } +} + +void usage(int argc, char **argv) +{ + cout << argv[0] << ". Migrates old sources to 10.3 repositories." << endl; + cout << "Usage:" << endl; + cout << argv[0] << " [--root root-path] [--fake] [--sp sources-path]" << endl; +} + +//----------------------------------------------------------------------------- + +int +main (int argc, char **argv) +{ + MIL << "-------------------------------------" << endl; + Options opt; + int i; + for ( i=1; i < argc; ++i ) + { + + if ( string(argv[i]) == "--help" ) + { + usage(argc, argv); + return 0; + } + if ( string(argv[i]) == "--fake" ) + opt.fake = true; + if ( string(argv[i]) == "--root" ) + opt.root = argv[++i]; + if ( string(argv[i]) == "--sp" ) + opt.sources_dir = argv[++i]; + } + migrate_sources(opt); + + return 0; +} + diff --git a/tools/patch_find_bug.cc b/tools/patch_find_bug.cc new file mode 100644 index 0000000..7262983 --- /dev/null +++ b/tools/patch_find_bug.cc @@ -0,0 +1,113 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST + +#include + +using namespace zypp; +using std::flush; + +static std::string appname( "patch_find_bug" ); + +int errexit( const std::string & msg_r = std::string(), int exit_r = 101 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + return exit_r; +} + + +int usage( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + cerr << "Usage: " << appname << "[OPTIONS] bugnumber..." << endl; + cerr << " Find patches refering to bugnumber (substring)." << endl; + cerr << " --root SYSROOT: Load system located below directory SYSROOT" << endl; + return exit_r; +} + +/****************************************************************** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +*/ +int main( int argc, char * argv[] ) +{ + INT << "===[START]==========================================" << endl; + appname = Pathname::basename( argv[0] ); + --argc; + ++argv; + + if ( ! argc ) + { + return usage(); + } + + /////////////////////////////////////////////////////////////////// + + ZConfig::instance(); + Pathname sysRoot("/"); + + if ( (*argv) == std::string("--root") ) + { + --argc,++argv; + if ( ! argc ) + return errexit("--root requires an argument."); + + if ( ! PathInfo( *argv ).isDir() ) + return errexit("--root requires a directory."); + + sysRoot = *argv; + --argc,++argv; + } + + TestSetup::LoadSystemAt( sysRoot ); + + for ( ; argc; --argc,++argv ) + { + PoolQuery q; + q.setMatchSubstring(); + q.setCaseSensitive( false ); + q.addAttribute( sat::SolvAttr::updateReferenceId, *argv ); + + if ( q.empty() ) + { + cout << "BUG REFERENCE '" << *argv << "': No match found." << endl; + } + else + { + cout << "BUG REFERENCE '" << *argv << endl; + for_( it , q.begin(), q.end() ) + { + // print the solvable that has a match: + cout << " - " << *it << endl; + + if ( true ) + { + // Print details about each match in that solvable: + for_( d, it.matchesBegin(), it.matchesEnd() ) + { + // directly access specific attribute like "subFind(updateReferenceType)": + cout << " - " << d->inSolvAttr() << "\t\"" << d->asString() << "\" has type \"" + << d->subFind( sat::SolvAttr::updateReferenceType ).asString() << "\"" << endl; + + // list the whole updateReference structure: + for_( s, d->subBegin(), d->subEnd() ) + { + cout << " -" << s.inSolvAttr() << "\t\"" << s.asString() << "\"" << endl; + } + } + } + } + } + } + + /////////////////////////////////////////////////////////////////// + INT << "===[END]============================================" << endl << endl; + return 0; +} diff --git a/tools/percent-encode.cc b/tools/percent-encode.cc new file mode 100644 index 0000000..e9260f3 --- /dev/null +++ b/tools/percent-encode.cc @@ -0,0 +1,38 @@ +#include +#include +#include + +static std::string doEncode( const std::string & str_r ) +{ return zypp::url::encode( str_r ); } + +static std::string doDecode( const std::string & str_r ) +{ return zypp::url::decode( str_r ); } + +int main( int argc, const char * argv[] ) +{ + bool encode( true ); + + --argc,++argv; + if ( argc ) + { + if ( *argv == std::string( "-d" ) || *argv == std::string( "--decode" ) ) + encode = false; + else if ( *argv == std::string( "-h" ) || *argv == std::string( "--help" ) ) + { + std::cout << "Usage: percent-encode [OPTION]" << std::endl; + std::cout << "Read lines from stdin and write them percent encoded to stdout." << std::endl; + std::cout << "" << std::endl; + std::cout << "Option:" << std::endl; + std::cout << " -d, --decode Decode lines read from stdin instead of encoding them." << std::endl; + std::cout << " -h --help Print this message." << std::endl; + return 0; + } + } + + std::string (*coder)( const std::string & str_r ) = encode ? doEncode: doDecode; + for( zypp::iostr::EachLine in( std::cin ); in; in.next() ) + { + std::cout << coder( *in ) << std::endl; + } + return 0; +} diff --git a/tools/refresh-ng/CMakeLists.txt b/tools/refresh-ng/CMakeLists.txt new file mode 100644 index 0000000..f9e33e3 --- /dev/null +++ b/tools/refresh-ng/CMakeLists.txt @@ -0,0 +1,14 @@ +PROJECT( refresh-ng C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc +) + +ADD_DEFINITIONS( -DZYPP_BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}" ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} PRIVATE zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} PRIVATE zypp-allsym ) diff --git a/tools/refresh-ng/main.cc b/tools/refresh-ng/main.cc new file mode 100644 index 0000000..1aae085 --- /dev/null +++ b/tools/refresh-ng/main.cc @@ -0,0 +1,214 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST 1 +#include "../../tests/lib/TestSetup.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/*! + * Place terminal referred to by 'fd' in cbreak mode (noncanonical mode + * with echoing turned on). + */ + +bool ttySetCbreak(int fd, struct termios *prevTermios) +{ + struct termios t; + + if (tcgetattr(fd, &t) == -1) + return false; + + if (prevTermios != NULL) + *prevTermios = t; + + // disable canonical mode + t.c_lflag &= ~( ICANON ); + + t.c_cc[VMIN] = 1; /* Character-at-a-time input */ + t.c_cc[VTIME] = 0; /* with blocking */ + + if (tcsetattr(fd, TCSAFLUSH, &t) == -1) + return false; + + return true; +} + +bool setBlocking ( int fd, bool set = true ) { + const int oldFlags = fcntl( fd, F_GETFL, 0 ); + if (oldFlags == -1) return false; + + const int flags = set ? ( oldFlags & ~(O_NONBLOCK) ) : ( oldFlags | O_NONBLOCK ); + if ( oldFlags == flags ) + return true; + + return ( fcntl( fd, F_SETFL, flags ) == 0 ); +} + + + + +int main ( int argc, char *argv[] ) +{ + using namespace zyppng::operators; + + ztui::Application appl; + auto &out = appl.out (); + + try { + auto ctx = zyppng::Context::create (); + + zypp::RepoInfo ri; + ri.setName ("Repo-Oss"); + ri.setAlias ("Repo-Oss"); + ri.setType ( zypp::repo::RepoType::RPMMD_e ); + ri.setBaseUrl( zypp::Url("https://download.opensuse.org/tumbleweed/repo/oss") ); + + zypp::filesystem::assert_dir("/tmp/dltest"); + zypp::Pathname destdir("/tmp/dltest"); + + ctx->sigEvent().connect([&]( zyppng::UserRequestRef req ){ + switch( req->type () ) { + case zyppng::UserRequestType::Message: + out.info ( static_cast(req.get())->message () ); + break; + case zyppng::UserRequestType::ListChoice: { + auto r = static_cast(req.get()); + ztui::PromptOptions popts; + + const auto &answers = r->answers (); + { + auto options = zyppng::transform ( answers, []( const auto &entry ) { return entry.opt; } ); + popts.setOptions( std::move(options), r->defaultAnswer() ); + } + for( unsigned i = 0; i < answers.size(); i++ ) { + popts.setOptionHelp ( i, answers.at(i).detail ); + } + + bool canContinue = true; + std::ifstream stm( "/dev/tty" ); + while ( canContinue ) { + appl.out().prompt( 0, r->label(), popts ); + std::string reply = str::getline( stm, str::TRIM ); + const auto &matches = popts.getReplyMatches ( reply ); + if ( matches.size () == 1 ) { + //valid answer + r->setChoice ( matches[0] ); + canContinue = false; + } else if ( matches.size() > 1 ) { + out.error ("Ambigous answer, try again"); + } else { + out.error ("Invalid answer, try again"); + } + } + break; + } + case zyppng::UserRequestType::BooleanChoice: { + auto r = static_cast(req.get()); + std::string yn( std::string(_("yes")) + "/" + _("no") ); + ztui::PromptOptions popts( yn, 1 ); + appl.out().prompt( 0, r->label(), popts ); + + std::ifstream stm( "/dev/tty" ); + std::string reply = str::getline( stm, str::TRIM ); + r->setChoice ( reply[0] == 'y' ); + break; + } + case zyppng::UserRequestType::KeyTrust: { + auto r = static_cast(req.get()); + + std::string yn( std::string(_("(r)eject")) + "/" + _("trust-(a)lways") + "/" + _("(t)rust") ); + ztui::PromptOptions popts( yn, 0 ); + appl.out().prompt( 0, r->label(), popts ); + + std::ifstream stm( "/dev/tty" ); + std::string reply = str::getline( stm, str::TRIM ); + r->setChoice ( reply[0] == 'a' ? zyppng::TrustKeyRequest::KEY_TRUST_AND_IMPORT : ( reply[0] == 't' ? zyppng::TrustKeyRequest::KEY_TRUST_TEMPORARILY : zyppng::TrustKeyRequest::KEY_DONT_TRUST ) ); + break; + } + case zyppng::UserRequestType::Custom: + out.info ("Received request type: " + req->userData ().type ().asString () ); + break; + } + }); + + + auto observer = zyppng::ProgressObserver::create("Refreshing repositories", 2); + observer->sigProgressChanged().connect([&](zyppng::ProgressObserver &o, double v){ + out.progress( "dl-repo", zypp::str::Str() << "Ref Progress changed to " << o.current() << "/" << o.steps (), o.progress () ); + }); + observer->sigFinished().connect([&](zyppng::ProgressObserver &, zyppng::ProgressObserver::FinishResult finRes ){ + out.info ( zypp::str::Str() << "Progress moved to finished with res: " << finRes << std::endl ); } + ); + + + out.progressStart("dl-repo", "Refreshing repositories"); + + std::vector allSysReps; + { + auto sysRepMgr = zyppng::AsyncRepoManager::create( ctx, zypp::RepoManagerOptions() ).unwrap(); + std::for_each ( sysRepMgr->repoBegin(), sysRepMgr->repoEnd(), [&]( zypp::RepoInfo info ){ + if ( info.enabled () ) { + info.setMetadataPath (zypp::Pathname()); + info.setPackagesPath (zypp::Pathname()); + allSysReps.push_back(info); + } + }); + } + + auto repMgr = zyppng::AsyncRepoManager::create( ctx, zypp::RepoManagerOptions(destdir) ).unwrap(); + auto result = repMgr->refreshMetadata( std::move(allSysReps), zypp::RepoManagerFlags::RefreshIfNeeded, observer ); + observer->setFinished (); + + bool allSuccess = true; + std::for_each( result.begin (), result.end(), [&]( const auto &resPair ) { + if ( !resPair.second ) + allSuccess = false; + + try { + resPair.second.unwrap(); + out.info ( zypp::str::Str() << "Refreshing repository: " << resPair.first.name() << " worked!" ); + } catch ( const zypp::Exception &e ) { + out.error ( zypp::str::Str() << "Refreshing repository: " << resPair.first.name() << " failed with Error: " << e ); + } catch ( const std::exception &e ) { + out.error ( zypp::str::Str() << "Refreshing repository: " << resPair.first.name() << " failed with Error: " << e.what() ); + } catch ( ... ) { + out.error ( zypp::str::Str() << "Refreshing repository: " << resPair.first.name() << " failed with Error: Unknown exception" ); + } + }); + + out.progressEnd("dl-repo", "Refreshing repositories", !allSuccess ); + + } catch ( const zypp::Exception &e ) { + out.error ( zypp::str::Str() << "Error: " << e << std::endl ); + } catch ( const std::exception &e ) { + out.error ( zypp::str::Str() << "Error: " << e.what() << std::endl ); + } catch ( ... ) { + out.error ( zypp::str::Str() << "Error: Unknown exception" << std::endl ); + } + return 0; +} diff --git a/tools/refresh-ng/output.h b/tools/refresh-ng/output.h new file mode 100644 index 0000000..8306e34 --- /dev/null +++ b/tools/refresh-ng/output.h @@ -0,0 +1,269 @@ +#ifndef OUTPUT_H +#define OUTPUT_H + +#include +#include +#include +#include +#include +#include + + +static void zypp_release_ncplane ( struct ncplane *ptr ) { if ( ptr ) ncplane_destroy(ptr); } +static void zypp_release_progbar ( struct ncprogbar *ptr ) { if ( ptr ) ncprogbar_destroy(ptr); } + +class OutputView : public zyppng::Base +{ + public: + ~OutputView() { + } + static std::shared_ptr create( ) { + + auto ptr = std::shared_ptr( new OutputView() ); + ptr->_nc = std::make_unique(); + if ( !ptr->_nc ) + return nullptr; + + ptr->_stdplane = std::unique_ptr( ptr->_nc->get_stdplane() ); + if ( !ptr->_stdplane ) + return nullptr; + + int rows = 0; + int cols = 0; + ptr->_stdplane->get_dim( rows, cols ); + + int top_rows = ( rows - 2 ); + if ( top_rows <= 0 ){ + return nullptr; + } + + int bottom_rows = rows - top_rows; + if ( bottom_rows <= 0 ) { + return nullptr; + } + + // the outer plane this is just used to draw a nice border + ptr->_topOuterPlane = std::make_unique( *ptr->_stdplane, top_rows, cols, 0, 0, nullptr ); + ptr->_topOuterPlane->rounded_box_sized( 0, 0, top_rows, cols, 0 ); + + // the inner plane, here we put the text + int r,c; + ptr->_topOuterPlane->get_dim( r, c ); + ptr->_topPlaneLeft = std::make_unique( *ptr->_topOuterPlane, r-2 , (c-1) / 2, 1, 1 ); + ptr->_topPlaneLeft->set_scrolling( true ); + + ptr->_topPlaneRight = std::make_unique( *ptr->_topOuterPlane, r-2 , c - ptr->_topPlaneLeft->get_dim_x() - 1 , 1, ptr->_topPlaneLeft->get_dim_x() + 1 ); + ptr->_topPlaneRight->set_scrolling( true ); + + // the plane where we show the progressbar text + ptr->_progBarTextPlane = std::make_unique( *ptr->_stdplane, 1 , cols, top_rows, 0 ); + + // to create the progressbar we need to fall back to the C API due to some bugs in the C++ progbar implementation + ncplane_options nopts = { + .y = top_rows+1, + .x = 0, + .rows = bottom_rows-1, + .cols = cols, + .userptr = nullptr, + .name = nullptr, + .resizecb = nullptr, + .flags = 0, + .margin_b = 0, + .margin_r = 0, + }; + + std::unique_ptr bottomPlane( ncplane_create( *ptr->_stdplane, &nopts ), &zypp_release_ncplane ); + if ( !bottomPlane ) { + return nullptr; + } + + struct ncprogbar_options popts = { + .ulchannel = 0, + .urchannel = 0, + .blchannel = 0, + .brchannel = 0, + .flags = 0, + }; + ptr->_progbar = std::unique_ptr ( ncprogbar_create( bottomPlane.release(), &popts ), &zypp_release_progbar ); + if ( !ptr->_progbar ) { + return nullptr; + } + return ptr; + } + + void updateProgress ( const std::string &txt, double prog, bool autoRender = true ) { + if ( !_progbar ) + return; + + _progBarTextPlane->erase(); + _progBarTextPlane->putstr( 0, ncpp::NCAlign::Center, txt.data() ); + ncprogbar_set_progress( _progbar.get(), prog ); + if ( autoRender ) + renderNow(); + } + + void putMsgTxt ( const std::string &txt, bool doAutoRender = true ) { + if ( !_topPlaneLeft ) + return; + + ncplane_puttext( *_topPlaneLeft, -1, NCALIGN_LEFT, txt.data(), nullptr ); + if ( doAutoRender ) + renderNow(); + } + + void putMsgErr ( const std::string &txt, bool doAutoRender = true ) { + if ( !_topPlaneRight ) + return; + + _topPlaneRight->set_fg_rgb( 0xff5349 ); + ncplane_puttext( *_topPlaneRight, -1, NCALIGN_LEFT, txt.data(), nullptr ); + _topPlaneRight->set_fg_default(); + if ( doAutoRender ) + renderNow(); + } + + std::optional promptUser ( const std::string &desc, const std::string &label ) + { + if ( desc.size() ) + putMsgTxt( desc, false ); + putMsgTxt( label + ": " ); + + int curX, curY; + _topPlaneLeft->get_cursor_yx( curY, curX ); + ncplane_options nopts = { + .y = curY, + .x = curX, + .rows = 1, + .cols = _topPlaneLeft->get_dim_x() - curX, + .userptr = nullptr, + .name = nullptr, + .resizecb = nullptr, + .flags = 0, + .margin_b = 0, + .margin_r = 0, + }; + + std::unique_ptr inputPlane( ncplane_create( *_topPlaneLeft, &nopts ), &zypp_release_ncplane ); + if ( !inputPlane ) { + return {}; + } + + auto readOpts = ncreader_options { + .tchannels = 0, + .tattrword = 0, + .flags = NCREADER_OPTION_CURSOR | NCREADER_OPTION_NOCMDKEYS + }; + std::unique_ptr reader( ncreader_create( inputPlane.release(), &readOpts ), []( struct ncreader *relme){ ncreader_destroy(relme, nullptr);} ); + if ( !reader ) + return {}; + + while ( true ) { + renderNow(); + ncinput ni; + _nc->get( true, &ni ); + if ( ni.id == NCKEY_ENTER ) { + break; + } + ncreader_offer_input( reader.get(), &ni ); + } + + std::unique_ptr data( ncreader_contents( reader.get() ), free ); + std::string_view cppData( data.get() ); + if ( cppData.empty() ) + return {}; + + return std::string(cppData); + } + + template + std::vector promptMultiSelect( const std::string &title, const std::string &secondary, const std::vector &data ) { + + // use a boost container here, because the stdlib decided to completely break vector by prematurely optimizing it + boost::container::vector selected( data.size(), false ); + std::vector items; + std::vector> stringsStorage; + items.reserve( data.size() ); + stringsStorage.reserve( data.size() ); + + for ( const T& entry : data ) { + stringsStorage.push_back( std::make_pair( entry.asUserString(), std::string("") ) ); + items.push_back( ncmselector_item{ + .option = stringsStorage.back().first.data(), + .desc = stringsStorage.back().second.data(), + .selected = false + }); + } + items.push_back(ncmselector_item{ + .option = nullptr, + .desc = nullptr, + .selected = false + }); + + std::string_view footer("Press Enter to accept or ESC to cancel."); + + auto selOpts = ncmultiselector_options{ + .title = title.data(), + .secondary = secondary.data(), + .footer = footer.data(), + .items = items.data(), + .maxdisplay = 0, + .opchannels = NCCHANNELS_INITIALIZER(0xe0, 0x80, 0x40, 0, 0, 0), + .descchannels = NCCHANNELS_INITIALIZER(0x80, 0xe0, 0x40, 0, 0, 0), + .titlechannels = NCCHANNELS_INITIALIZER(0x20, 0xff, 0xff, 0, 0, 0x20), + .footchannels = NCCHANNELS_INITIALIZER(0xe0, 0, 0x40, 0x20, 0x20, 0), + .boxchannels = NCCHANNELS_INITIALIZER(0x20, 0xe0, 0xe0, 0x20, 0, 0), + .flags = 0 + }; + + auto tmpPlane = ncpp::Plane( *_stdplane, _stdplane->get_dim_y()-1, _stdplane->get_dim_x()-1, 1, 1 ); + ncpp::MultiSelector selector( tmpPlane, &selOpts); + + while ( true ) { + renderNow(); + ncinput ni; + _nc->get( true, &ni ); + if ( ni.id == NCKEY_ESC ) { + return {}; + } else if ( ni.id == NCKEY_ENTER ) { + break; + } + selector.offer_input( &ni ); + } + + selector.get_selected( selected.data(), selected.size() ); + std::vector selIndices; + for ( int i = 0; i < selected.size(); i++ ) { + if ( selected[i]) + selIndices.push_back(i); + } + + return selIndices; + } + + void renderNow () { + if ( _nc ) _nc->render(); + } + + uint32_t waitForKeys ( std::vector keys = {} ) { + ncinput ni; + while ( true ) { + _nc->get( true, &ni ); + if ( keys.empty() || std::find( keys.begin(), keys.end(), ni.id ) != keys.end() ) + return ni.id; + } + } + + private: + OutputView() : _topOuterPlane( nullptr ), _topPlaneLeft( nullptr ), _topPlaneRight( nullptr ), _progbar( nullptr, &zypp_release_progbar ) {} + + std::unique_ptr _nc; + std::unique_ptr _stdplane; + std::unique_ptr _topOuterPlane; + std::unique_ptr _topPlaneLeft; + std::unique_ptr _topPlaneRight; + std::unique_ptr _progBarTextPlane; + std::unique_ptr _progbar; +}; + + +#endif // OUTPUT_H diff --git a/tools/repomirror/CMakeLists.txt b/tools/repomirror/CMakeLists.txt new file mode 100644 index 0000000..aa86016 --- /dev/null +++ b/tools/repomirror/CMakeLists.txt @@ -0,0 +1,16 @@ +PROJECT( repomirror C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + output.h + main.cc +) + +ADD_DEFINITIONS( -DZYPP_BUILD_DIR="${CMAKE_CURRENT_BINARY_DIR}" ) + +message(${Notcurses++_LIBRARIES}) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp ${Notcurses++_LIBRARIES} -lnotcurses-core ) diff --git a/tools/repomirror/main.cc b/tools/repomirror/main.cc new file mode 100644 index 0000000..43d64f1 --- /dev/null +++ b/tools/repomirror/main.cc @@ -0,0 +1,405 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST 1 +#include "../../tests/lib/TestSetup.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "output.h" + +class DlSkippedException : public zypp::Exception +{ + public: + DlSkippedException() : zypp::Exception("Download was skipped" ) {} +}; + +class MyDLStatus : public zyppng::ProvideStatus +{ + public: + MyDLStatus ( OutputView &out, zyppng::ProvideRef parent ) : ProvideStatus( parent ), _out(out) {} + + virtual void pulse ( ) { + zyppng::ProvideStatus::pulse(); + + const auto &currStats = stats(); + + if ( currStats._expectedBytes == 0 ) + return; + + auto perc = (double)(currStats._finishedBytes + currStats._partialBytes) / (double)currStats._expectedBytes; + std::string txt = zypp::str::Str() << "Downloading " << zypp::ByteCount((currStats._finishedBytes + currStats._partialBytes)) << "/" << currStats._expectedBytes << " (" << currStats._perSecond<<"/s)"; + _out.updateProgress( txt, perc ); + } + + private: + OutputView &_out; +}; + +/*! + * Downloads a solvable via the given handle. + * Returns the AsyncResult + */ +zyppng::AsyncOpRef> provideSolvable ( std::shared_ptr output, zyppng::ProvideMediaHandle handle, const zypp::sat::Solvable &s ) +{ + using namespace zyppng::operators; + + auto prov = handle.parent(); + if ( !prov ) + return zyppng::makeReadyResult( zyppng::expected::error( std::make_exception_ptr( zypp::Exception("Handle without parent!"))) ); + + zypp::PoolItem pi(s); + if ( !pi->isKind() ) { + //output->putMsgErr( zypp::str::Str() << "Skipping 1: " << pi.asUserString() << "\n" ); + return zyppng::makeReadyResult( zyppng::expected::error( std::make_exception_ptr(DlSkippedException())) ); + } + + auto oml = pi.lookupLocation(); + if ( oml.filename().empty() ) { + output->putMsgErr( zypp::str::Str() << "Skipping: " << pi.asUserString() << "\n" ); + return zyppng::makeReadyResult( zyppng::expected::error( std::make_exception_ptr(DlSkippedException())) ); + } + + // enable for more output, but sloooooows the startup time down significantly + //output->putMsgTxt( zypp::str::Str() << "Downloading " << pi.asUserString() << " size is: " << pi.downloadSize() << "\n" ); + + return prov->provide( handle, oml.filename(), zyppng::ProvideFileSpec( oml ) ) + | [output]( zyppng::expected &&res ) { + if ( res ) { + output->putMsgTxt( zypp::str::Str() << "File downloaded: " << res->file() << "\n" ); + } else { + output->putMsgErr( zypp::str::Str() << "Failed to download file\n" ); + try + { + std::rethrow_exception(res.error()); + } + catch(const zypp::Exception& e) + { + output->putMsgErr( zypp::str::Str() << e.asUserHistory() << '\n' ); + } + catch(const std::exception& e) + { + output->putMsgErr( zypp::str::Str() << e.what() << '\n' ); + } + } + return res; + }; +} + +/*! + * Helper function to copy a ProvideRes underlying file to a target destination, keeping the ProvideRes alive until the copy operation has finished + */ +zyppng::AsyncOpRef> copyProvideResToFile ( std::shared_ptr output, zyppng::ProvideRef prov, zyppng::ProvideRes &&res, const zypp::Pathname &targetDir ) +{ + using namespace zyppng::operators; + + auto fName = res.file(); + return prov->copyFile( fName, targetDir/fName.basename() ) + | [ resSave = std::move(res) ] ( auto &&result ) { + // callback lambda to keep the ProvideRes reference around until the op is finished, + // if the op fails the callback will be cleaned up and so the reference + return result; + }; +} + +/*! + * Helper function to calculate a checksum on a ProvideRes result file, keeping the ProvideRes alive during the operation and returning it again after the test was successful, + * here we could also ask the user if a invalid checksum should be accepted and ignore the result if the user wants to + */ +zyppng::AsyncOpRef> checksumIfRequired ( std::shared_ptr output, zyppng::ProvideRef prov, zypp::sat::Solvable solvable, zyppng::ProvideRes &&res ) +{ + using namespace zyppng::operators; + + auto fName = res.file(); + + const auto oml = solvable.lookupLocation(); + if ( !oml.checksum().empty() ) { + output->putMsgTxt( zypp::str::Str()<<" calculating checksum for file: " << fName << "\n"); + + return prov->checksumForFile( fName, oml.checksum().type() ) + | mbind([ output, expectedSum = oml.checksum(), saveRes = std::move(res) ]( auto &&checksumRes ) { + output->putMsgTxt( zypp::str::Str()<<" Got checksum for file: " << saveRes.file() << " is: " << checksumRes << "\n" ); + try { + zypp::CheckSum s( expectedSum.type(), checksumRes ); + if ( expectedSum == s ) + return zyppng::expected::success(std::move(saveRes)); + else + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::CheckSumCheckException( zypp::str::Str() << saveRes.file() << " has wrong checksum" ) ) ); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + + }); + } + + return zyppng::makeReadyResult( zyppng::expected::success(std::move(res)) ); +} + + + +int main ( int argc, char *argv[] ) +{ + using namespace zyppng::operators; + + auto ev = zyppng::EventLoop::create(); + + auto output = OutputView::create(); + if ( !output ) { + std::cerr << "Failed to initialize Output view" << std::endl; + return 1; + } + + output->putMsgTxt("Loading System\n"); + output->putMsgErr("Errors go here\n"); + +#if 0 + { + auto prov = zyppng::Provide::create(); + prov->setStatusTracker( std::make_shared( *output, prov) ); + + zypp::Url test("copy://"); + test.setPathName("/tmp/test/test1"); + + auto rootOp = prov->provide( test, zyppng::ProvideFileSpec().setDestFilenameHint("/tmp/test/test2") ) + | [&]( zyppng::expected &&res ) { + if ( !res ) { + output->putMsgErr( zypp::str::Str() << "Failed to copy file: ", false ); + try { + std::rethrow_exception(res.error()); + + } catch(const zypp::Exception& e) { + output->putMsgErr( zypp::str::Str() << e.asUserHistory() << '\n' ); + + } catch(const std::exception& e) { + output->putMsgErr( zypp::str::Str() << e.what() << '\n' ); + + } catch(...) { + output->putMsgErr( zypp::str::Str() << "Unknown exception\n" ); + } + } else { + output->putMsgTxt( zypp::str::Str() << "Yay copy worked\n" ); + } + return 0; + }; + + prov->start(); + if ( !rootOp->isReady() ) + ev->run(); + output->putMsgTxt( zypp::str::Str() << "Waiting, press Return to exit\n" ); + output->waitForKeys( { NCKEY_ENTER } ); + return 0; + } +#endif + + TestSetup t; + try { + t.LoadSystemAt( "/" ); + } catch ( const zypp::Exception &e ) { + output.reset(); //disable curses + std::cerr << "Failed to load repo info from system." << std::endl; + std::cerr << "Got exception: " << e << std::endl; + return 1; + } + + zypp::RepoManager rManager( zypp::RepoManagerOptions("/") ); + auto pool = t.pool(); + auto satPool = t.satpool(); + + output->putMsgTxt("Loading repositories\n"); + + std::vector myRepos; + for ( const auto &r : t.satpool().repos() ) { + if ( r.isSystemRepo() ) + continue; + myRepos.push_back(r); + } + + if ( !myRepos.size() ) { + output->putMsgTxt( zypp::str::Str() << "No repos found, press any key to exit\n" ); + output->waitForKeys(); + return 0; + } + + std::vector reposToDl = output->promptMultiSelect( "Select the repos you want to download", "", myRepos ); + output->renderNow(); + + if( !reposToDl.size() ) { + output->putMsgTxt( zypp::str::Str() << "No repos selected, press any key to exit\n" ); + output->waitForKeys(); + return 0; + } + + const auto &workerPath = zypp::Pathname ( ZYPP_BUILD_DIR ).dirname() / "tools" / "workers"; + auto prov = zyppng::Provide::create(); + prov->setStatusTracker( std::make_shared( *output, prov) ); + prov->sigAuthRequired().connect( [&](const zypp::Url &reqUrl, const std::string &triedUsername, const std::map &extraValues) -> std::optional { + + auto user = output->promptUser( + zypp::str::Str() << "Auth request for URL: " << reqUrl << "\n" + << "Last tried username was: " << triedUsername << "\n", + "Username" ); + if ( !user ) + return {}; + + zypp::media::AuthData d; + d.setUrl( reqUrl ); + d.setUsername( *user ); + + auto pass = output->promptUser("", "Password"); + if ( pass ) + d.setPassword( *pass ); + + return d; + }); + + std::vector< zyppng::AsyncOpRef< std::vector>> > mop; + + // we need a way to remember the data for the full transaction, there is probably a better way for a real application + std::unordered_map>> repoToMediaToSolvables; + + zypp::Pathname workPath = zypp::Pathname(".").realpath() / "allrpms"; + zypp::filesystem::assert_dir( workPath ); + + for ( const auto repoToDl : reposToDl ) { + const auto &r = myRepos[repoToDl]; + output->putMsgTxt( zypp::str::Str() << "Repo selected to download: " << r.asUserString() << "\n" ); + + auto urlSet = r.info().baseUrls(); + if ( urlSet.empty() ) { + output->putMsgTxt( zypp::str::Str() << "Repo has no mirrors, ignoring!\n" ); + continue; + } + + std::vector urlsWithPath; + std::transform( urlSet.begin(), urlSet.end(), std::back_inserter(urlsWithPath), [&]( const zypp::Url &bUrl ){ + zypp::Url withPath(bUrl); + withPath.setPathName( r.info().path() / bUrl.getPathName() ); + return withPath; + }); + + zypp::ByteCount bc; + output->putMsgTxt( zypp::str::Str() << "Adding Solvables for repo: " << r << "\n" ); + std::unordered_map> &mediaToSolvables = repoToMediaToSolvables[repoToDl]; + std::for_each( satPool.solvablesBegin(), satPool.solvablesEnd(), [&]( const zypp::sat::Solvable &s ) { + if ( s.repository() != r ) + return; + bc += s.downloadSize(); + const auto mediaNr = s.lookupLocation().medianr(); + mediaToSolvables[mediaNr].push_back(s); + }); + output->putMsgTxt( zypp::str::Str() << "Download size for repo: " << r << ":" << bc << "\n" ); + + std::transform( mediaToSolvables.begin(), mediaToSolvables.end(), std::back_inserter(mop), [&]( const auto &s ) { + + auto spec = zyppng::ProvideMediaSpec( r.info().name() ); + zypp::Pathname mediafile = r.info().metadataPath(); + if ( !mediafile.empty() ) { + mediafile += "/media.1/media"; + if ( zypp::PathInfo(mediafile).isExist() ) { + spec.setMediaFile( mediafile ); + spec.setMedianr( s.first ); + } + } + + return prov->attachMedia( urlsWithPath, spec ) + | [ &, &solvables = s.second ]( zyppng::expected &&hdl ) { + + if ( !hdl ) { + output->putMsgErr( zypp::str::Str() << "Failed to attach medium: ", false ); + try { + std::rethrow_exception(hdl.error()); + + } catch(const zypp::Exception& e) { + output->putMsgErr( zypp::str::Str() << e.asUserHistory() << '\n' ); + + } catch(const std::exception& e) { + output->putMsgErr( zypp::str::Str() << e.what() << '\n' ); + + } catch(...) { + output->putMsgErr( zypp::str::Str() << "Unknown exception\n" ); + + } + return std::vector>>{ zyppng::makeReadyResult( zyppng::expected::error( hdl.error() ) ) }; + } + + return zyppng::transform( solvables, [ &, hdl=hdl.get() ]( const zypp::sat::Solvable &s ) { + return s | (std::bind( &provideSolvable, output, hdl, std::placeholders::_1 )) + | mbind (std::bind( &checksumIfRequired, output, prov, sat::Solvable(s), std::placeholders::_1 )) + | mbind (std::bind( ©ProvideResToFile, output, prov, std::placeholders::_1, workPath ) ) ; + }); + } + | zyppng::join() + | [ &r, &output ]( const auto &&res ){ + output->putMsgTxt( zypp::str::Str() << "Finished with rpo: " << r.info().name() << "\n" ); + return res; + }; + }); + } + + std::vector> finalResults; + + auto rootOp = std::move( mop ) + | zyppng::join() + | [&]( std::vector>> &&allResults ) { + // reduce to one vector of results + for ( auto &innerVec : allResults ) { + std::accumulate( std::make_move_iterator(innerVec.begin()), std::make_move_iterator(innerVec.end()), &finalResults, []( std::vector>* vec, auto &&bla ){ + vec->push_back(std::move(bla)); + return vec; + }); + } + ev->quit(); + return 0; + }; + + prov->start(); + if ( !rootOp->isReady() ) + ev->run(); + + int succ = 0; + int skip = 0; + int err = 0; + for ( const auto &res : finalResults ) { + if ( res ) + succ++; + else { + try { + std::rethrow_exception( res.error() ); + } catch(const DlSkippedException& e) { + skip++; + } catch( const zypp::Exception &e ) { + output->putMsgErr( zypp::str::Str()<<"Request failed with: " << e.asUserString() << "\n"); + err++; + } catch( const std::exception &e ) { + output->putMsgErr( zypp::str::Str()<<"Request failed with: " << e.what() << "\n"); + err++; + } catch( ... ) { + output->putMsgErr( zypp::str::Str()<<"Request failed with an unknown error.\n" ); + err++; + } + } + } + #if 0 + for ( const auto &outer : finalResults ) { + + } + #endif + + output->putMsgTxt( zypp::str::Str() << "All done:\nSuccess:" << succ << "\nErrors: "<< err << "\nSkipped:"<putMsgTxt( zypp::str::Str() << "Waiting, press Return to exit\n" ); + output->waitForKeys( { NCKEY_ENTER } ); + return 0; +} diff --git a/tools/repomirror/output.h b/tools/repomirror/output.h new file mode 100644 index 0000000..5a746b3 --- /dev/null +++ b/tools/repomirror/output.h @@ -0,0 +1,295 @@ +#ifndef OUTPUT_H +#define OUTPUT_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void zypp_release_ncplane ( struct ncplane *ptr ) { if ( ptr ) ncplane_destroy(ptr); } +static void zypp_release_progbar ( struct ncprogbar *ptr ) { if ( ptr ) ncprogbar_destroy(ptr); } + +template +using as_user_string_t = decltype(T::asUserString); + +template +constexpr bool has_as_user_string_v = std::is_detected_v; + +template +constexpr bool always_false = false; + +template +inline auto stringify ( const T& value ) { + if constexpr( has_as_user_string_v ) { + return value.asUserString(); + } else if constexpr ( std::is_same_v ) { + return value; + } else if constexpr ( std::is_convertible_v ) { + return (std::string)value; + } else { + static_assert( always_false, "No way to convert to a string"); + } +} + + +class OutputView : public zyppng::Base +{ + public: + ~OutputView() { + } + static std::shared_ptr create( ) { + + auto ptr = std::shared_ptr( new OutputView() ); + ptr->_nc = std::make_unique(); + if ( !ptr->_nc ) + return nullptr; + + ptr->_stdplane = std::unique_ptr( ptr->_nc->get_stdplane() ); + if ( !ptr->_stdplane ) + return nullptr; + + uint rows = 0; + uint cols = 0; + ptr->_stdplane->get_dim( rows, cols ); + + int top_rows = ( rows - 2 ); + if ( top_rows <= 0 ){ + return nullptr; + } + + uint bottom_rows = rows - top_rows; + if ( bottom_rows <= 0 ) { + return nullptr; + } + + // the outer plane this is just used to draw a nice border + ptr->_topOuterPlane = std::make_unique( *ptr->_stdplane, top_rows, cols, 0, 0, nullptr ); + ptr->_topOuterPlane->rounded_box_sized( 0, 0, top_rows, cols, 0 ); + + // the inner plane, here we put the text + uint r,c; + ptr->_topOuterPlane->get_dim( r, c ); + ptr->_topPlaneLeft = std::make_unique( *ptr->_topOuterPlane, r-2 , (c-1) / 2, 1, 1 ); + ptr->_topPlaneLeft->set_scrolling( true ); + + ptr->_topPlaneRight = std::make_unique( *ptr->_topOuterPlane, r-2 , c - ptr->_topPlaneLeft->get_dim_x() - 1 , 1, ptr->_topPlaneLeft->get_dim_x() + 1 ); + ptr->_topPlaneRight->set_scrolling( true ); + + // the plane where we show the progressbar text + ptr->_progBarTextPlane = std::make_unique( *ptr->_stdplane, 1 , cols, top_rows, 0 ); + + // to create the progressbar we need to fall back to the C API due to some bugs in the C++ progbar implementation + ncplane_options nopts = { + .y = top_rows+1, + .x = 0, + .rows = bottom_rows-1, + .cols = cols, + .userptr = nullptr, + .name = nullptr, + .resizecb = nullptr, + .flags = 0, + .margin_b = 0, + .margin_r = 0, + }; + + std::unique_ptr bottomPlane( ncplane_create( *ptr->_stdplane, &nopts ), &zypp_release_ncplane ); + if ( !bottomPlane ) { + return nullptr; + } + + struct ncprogbar_options popts = { + .ulchannel = 0, + .urchannel = 0, + .blchannel = 0, + .brchannel = 0, + .flags = 0, + }; + ptr->_progbar = std::unique_ptr ( ncprogbar_create( bottomPlane.release(), &popts ), &zypp_release_progbar ); + if ( !ptr->_progbar ) { + return nullptr; + } + return ptr; + } + + void updateProgress ( const std::string &txt, double prog, bool autoRender = true ) { + if ( !_progbar ) + return; + + _progBarTextPlane->erase(); + _progBarTextPlane->putstr( 0, ncpp::NCAlign::Center, txt.data() ); + ncprogbar_set_progress( _progbar.get(), prog ); + if ( autoRender ) + renderNow(); + } + + void putMsgTxt ( const std::string &txt, bool doAutoRender = true ) { + if ( !_topPlaneLeft ) + return; + + ncplane_puttext( *_topPlaneLeft, -1, NCALIGN_LEFT, txt.data(), nullptr ); + if ( doAutoRender ) + renderNow(); + } + + void putMsgErr ( const std::string &txt, bool doAutoRender = true ) { + if ( !_topPlaneRight ) + return; + + _topPlaneRight->set_fg_rgb( 0xff5349 ); + ncplane_puttext( *_topPlaneRight, -1, NCALIGN_LEFT, txt.data(), nullptr ); + _topPlaneRight->set_fg_default(); + if ( doAutoRender ) + renderNow(); + } + + std::optional promptUser ( const std::string &desc, const std::string &label ) + { + if ( desc.size() ) + putMsgTxt( desc, false ); + putMsgTxt( label + ": " ); + + uint curX, curY; + _topPlaneLeft->get_cursor_yx( curY, curX ); + ncplane_options nopts = { + .y = (int)curY, + .x = (int)curX, + .rows = 1, + .cols = _topPlaneLeft->get_dim_x() - curX, + .userptr = nullptr, + .name = nullptr, + .resizecb = nullptr, + .flags = 0, + .margin_b = 0, + .margin_r = 0, + }; + + std::unique_ptr inputPlane( ncplane_create( *_topPlaneLeft, &nopts ), &zypp_release_ncplane ); + if ( !inputPlane ) { + return {}; + } + + auto readOpts = ncreader_options { + .tchannels = 0, + .tattrword = 0, + .flags = NCREADER_OPTION_CURSOR | NCREADER_OPTION_NOCMDKEYS + }; + std::unique_ptr reader( ncreader_create( inputPlane.release(), &readOpts ), []( struct ncreader *relme){ ncreader_destroy(relme, nullptr);} ); + if ( !reader ) + return {}; + + while ( true ) { + renderNow(); + ncinput ni; + _nc->get( true, &ni ); + if ( ni.id == NCKEY_ENTER ) { + break; + } + ncreader_offer_input( reader.get(), &ni ); + } + + std::unique_ptr data( ncreader_contents( reader.get() ), free ); + std::string_view cppData( data.get() ); + if ( cppData.empty() ) + return {}; + + return std::string(cppData); + } + + template + std::vector promptMultiSelect( const std::string &title, const std::string &secondary, const std::vector &data ) { + + // use a boost container here, because the stdlib decided to completely break vector by prematurely optimizing it + boost::container::vector selected( data.size(), false ); + std::vector items; + std::vector> stringsStorage; + items.reserve( data.size() ); + stringsStorage.reserve( data.size() ); + + for ( const T& entry : data ) { + stringsStorage.push_back( std::make_pair( stringify(entry), std::string("") ) ); + items.push_back( ncmselector_item{ + .option = stringsStorage.back().first.data(), + .desc = stringsStorage.back().second.data(), + .selected = false + }); + } + items.push_back(ncmselector_item{ + .option = nullptr, + .desc = nullptr, + .selected = false + }); + + std::string_view footer("Press Enter to accept or ESC to cancel."); + + auto selOpts = ncmultiselector_options{ + .title = title.data(), + .secondary = secondary.data(), + .footer = footer.data(), + .items = items.data(), + .maxdisplay = 0, + .opchannels = NCCHANNELS_INITIALIZER(0xe0, 0x80, 0x40, 0, 0, 0), + .descchannels = NCCHANNELS_INITIALIZER(0x80, 0xe0, 0x40, 0, 0, 0), + .titlechannels = NCCHANNELS_INITIALIZER(0x20, 0xff, 0xff, 0, 0, 0x20), + .footchannels = NCCHANNELS_INITIALIZER(0xe0, 0, 0x40, 0x20, 0x20, 0), + .boxchannels = NCCHANNELS_INITIALIZER(0x20, 0xe0, 0xe0, 0x20, 0, 0), + .flags = 0 + }; + + auto tmpPlane = ncpp::Plane( *_stdplane, _stdplane->get_dim_y()-1, _stdplane->get_dim_x()-1, 1, 1 ); + ncpp::MultiSelector selector( tmpPlane, &selOpts); + + while ( true ) { + renderNow(); + ncinput ni; + _nc->get( true, &ni ); + if ( ni.id == NCKEY_ESC ) { + return {}; + } else if ( ni.id == NCKEY_ENTER ) { + break; + } + selector.offer_input( &ni ); + } + + selector.get_selected( selected.data(), selected.size() ); + std::vector selIndices; + for ( int i = 0; i < selected.size(); i++ ) { + if ( selected[i]) + selIndices.push_back(i); + } + + return selIndices; + } + + void renderNow () { + if ( _nc ) _nc->render(); + } + + uint32_t waitForKeys ( std::vector keys = {} ) { + ncinput ni; + while ( true ) { + _nc->get( true, &ni ); + if ( keys.empty() || std::find( keys.begin(), keys.end(), ni.id ) != keys.end() ) + return ni.id; + } + } + + private: + OutputView() : _progbar( nullptr, &zypp_release_progbar ) {} + + std::unique_ptr _nc; + std::unique_ptr _stdplane; + std::unique_ptr _topOuterPlane; + std::unique_ptr _topPlaneLeft; + std::unique_ptr _topPlaneRight; + std::unique_ptr _progBarTextPlane; + std::unique_ptr _progbar; +}; + + +#endif // OUTPUT_H diff --git a/tools/zypp-CheckAccessDeleted.cc b/tools/zypp-CheckAccessDeleted.cc new file mode 100644 index 0000000..accacc3 --- /dev/null +++ b/tools/zypp-CheckAccessDeleted.cc @@ -0,0 +1,176 @@ +#include +#include +#include +#include +#include +#include +#include + +/** Collect max string size. */ +struct TableCol +{ + TableCol( size_t size_r = 0 ) + : size( size_r ) + {} + TableCol( const std::string & header_r ) + : header( header_r ), size( header_r.size() ) + {} + void operator()( const std::string & val_r ) + { if ( val_r.size() > size ) size = val_r.size(); } + + std::string header; + size_t size; +}; + +/** Scan to determine column sizes, then print. */ +struct ProcInfoTable +{ + ProcInfoTable() + : pid ( "PID" ) + , ppid ( "PPID" ) + , puid ( "UID" ) + , login ( "LOGIN" ) + , command ( "COMMAND" ) + , service ( "SERVICE" ) + , files ( "FILES" ) + {} + + void scan( const zypp::CheckAccessDeleted::ProcInfo & val_r ) + { + pid( val_r.pid ); + ppid( val_r.ppid ); + puid( val_r.puid ); + login( val_r.login ); + command( val_r.command ); + service( val_r.service() ); + } + + void printHeader() const + { + printRow( pid.header, + ppid.header, + puid.header, + login.header, + command.header, + service.header, + files.header ); + } + + void print( const zypp::CheckAccessDeleted::ProcInfo & val_r ) const + { + printRow( val_r.pid, + val_r.ppid, + val_r.puid, + val_r.login, + val_r.command, + val_r.service(), + zypp::str::join( val_r.files, ", " ) ); + } + + void printRow( const std::string & pid_r, + const std::string & ppid_r, + const std::string & puid_r, + const std::string & login_r, + const std::string & command_r, + const std::string & service_r, + const std::string & files_r ) const + { + printf( "%*s %*s %*s %-*s %-*s %-*s %-s\n", + (int)pid.size, pid_r.c_str(), + (int)ppid.size, ppid_r.c_str(), + (int)puid.size, puid_r.c_str(), + (int)login.size, login_r.c_str(), + (int)command.size, command_r.c_str(), + (int)service.size, (service_r.empty() ? " -" : service_r.c_str()), + files_r.c_str() ); + } + + TableCol pid; + TableCol ppid; + TableCol puid; + TableCol login; + TableCol command; + TableCol service; + TableCol files; +}; + +void usage ( const std::string &appname ) +{ + std::cout << "Usage: " << appname << " [--help] [--debugFile ] [--zypper]" << std::endl; + std::cout << "List information about all running processe" << std::endl; + std::cout << "which access deleted executables or libraries." << std::endl; + std::cout << std::endl; + std::cout << "GLOBALOPTS:" << std::endl; + std::cout << " --debugFile Use information from instead" << std::endl; + std::cout << " of inspecting the host system." << std::endl; + std::cout << " --zypper Disable verbose checking like zypper does." << std::endl; + std::cout << std::endl; + std::cout << "TABLEHEADERS:" << std::endl; + std::cout << " PID " << "process ID" << std::endl; + std::cout << " PPID " << "parent process ID" << std::endl; + std::cout << " UID " << "process user ID" << std::endl; + std::cout << " LOGIN " << "process login name" << std::endl; + std::cout << " COMMAND " << "process command name" << std::endl; + std::cout << " SERVICE " << "/etc/init.d/ script that might be used to restart the command (guessed)" << std::endl; + std::cout << " FILES " << "list of deleted executables or libraries accessed" << std::endl; +} + +int main( int argc, char * argv[] ) +{ + + std::string progname( zypp::Pathname::basename( argv[0] ) ); + std::string debugInputFile; + bool verbose = true; + argv++; + argc--; + + while( argc > 0 ) { + if ( strcmp( argv[0], "--help" ) == 0 ) + { + usage( progname ); + return 0; + } else if ( strcmp( argv[0], "--debugFile" ) == 0 ) { + if ( argc < 2 ) { + std::cerr << progname << ": debugFile requires a argument" << std::endl; + return 1; + } + + ++argv; + --argc; + debugInputFile = argv[0]; + + } else if ( strcmp( argv[0], "--zypper" ) == 0 ) { + verbose = false; + } else { + std::cerr << progname << ": unexpected argument '" << argv[0] << "'" << std::endl; + std::cerr << "Try `" << progname << " --help' for more information." << std::endl; + return 1; + } + + ++argv; + --argc; + } + + zypp::CheckAccessDeleted checker(false); // wait for explicit call to check() + try { + if ( debugInputFile.empty() ) + checker.check( verbose ); + else + checker.check( debugInputFile, verbose ); + } + catch( const zypp::Exception & err ) + { + std::cerr << err << std::endl << err.historyAsString(); + return 2; + } + + ProcInfoTable table; + for_( it, checker.begin(), checker.end() ) + table.scan( *it ); + + table.printHeader(); + for_( it, checker.begin(), checker.end() ) + table.print( *it ); + + return 0; +} diff --git a/tools/zypp-NameReqPrv.cc b/tools/zypp-NameReqPrv.cc new file mode 100644 index 0000000..6a9a6bc --- /dev/null +++ b/tools/zypp-NameReqPrv.cc @@ -0,0 +1,529 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST + +#include +#include +#include +#include + +static std::string appname( "NameReqPrv" ); + +#define message cout +using std::flush; + +int errexit( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + return exit_r; +} + +int usage( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + cerr << "Usage: " << appname << " [--root ROOTDIR] [OPTIONS] NAME... [[OPTIONS] NAME...]..." << endl; + cerr << " Load all enabled repositories (no refresh) and search for" << endl; + cerr << " occurrences of NAME (regex or -x) in package names or dependencies" << endl; + cerr << " --root Load repos from the system located below ROOTDIR. If ROOTDIR" << endl; + cerr << " denotes a sover testcase, the testcase is loaded." << endl; + cerr << " --installed Process installed packages only." << endl; + cerr << " -i/-I turn on/off case insensitive search (default on)" << endl; + cerr << " -n/-N turn on/off looking for names (default on)" << endl; + cerr << " -p/-P turn on/off looking for provides (default off)" << endl; + cerr << " -r/-R turn on/off looking for requires (default off)" << endl; + cerr << " -c/-C turn on/off looking for conflicts (default off)" << endl; + cerr << " -o/-O turn on/off looking for obsoletes (default off)" << endl; + cerr << " -m/-M turn on/off looking for recommends (default off)" << endl; + cerr << " -s/-S turn on/off looking for supplements (default off)" << endl; + cerr << " -e/-E turn on/off looking for enhan./sugg.(default off)" << endl; + cerr << " -a short for -n -p -r" << endl; + cerr << " -A short for -n -P -R" << endl; + cerr << " -x do exact matching (glob) rather than regex (substring)" << endl; + cerr << " -D dump dependencies of " << endl; + cerr << "" << endl; + return exit_r; +} + +#define COL_R "\033[0;31m" +#define COL_G "\033[0;32m" +#define COL_B "\033[0;34m" +#define COL_C "\033[0;36m" +#define COL_M "\033[0;35m" +#define COL_Y "\033[0;33m" +#define COL_BL "\033[0;30m" +#define COL_WH "\033[1;37m" +#define COL_OFF "\033[0m" + +struct PQSort +{ + // std::less semantic + bool operator()( const sat::Solvable & lhs, const sat::Solvable & rhs ) const + { + { + bool l = lhs.isSystem(); + bool r = rhs.isSystem(); + if ( l != r ) + return r; + } + { + IdString l { lhs.ident() }; + IdString r { rhs.ident() }; + if ( l != r ) + return l < r; + } + return avo( PoolItem(lhs), PoolItem(rhs) ); + return lhs.id() > rhs.id(); + } + + ui::SelectableTraits::AVOrder avo; +}; + +struct Table +{ + using ResultLInes = std::set; + + ResultLInes & row( const sat::Solvable & solv_r ) + { + //smax( _maxSID, ); + smax( _maxNAME, solv_r.ident().size() + solv_r.edition().size() + solv_r.arch().size() ); + smax( _maxREPO, solv_r.repository().name().size(), solv_r.repository().name() ); + //smax( _maxTIME, ); + //smax( _maxVEND, solv_r.vendor().size() ); + return _map[solv_r]; + } + + void row( PoolQuery::const_iterator it_r ) + { + ResultLInes & details { row( *it_r ) }; + for_( match, it_r.matchesBegin(), it_r.matchesEnd() ) { + std::string ent { match->inSolvAttr().asString().substr( 9, 3 )+": " +match->asString() }; + if ( match->inSolvAttr() == sat::SolvAttr::requires + && match->inSolvable().prerequires().contains( Capability(match->id()) ) ) { + static const char * pre = " " COL_C "[PRE]" COL_OFF; + ent[3] = '+'; + ent += pre; + } + details.insert( std::move(ent) ); + } + } + + std::ostream & dumpOn( std::ostream & str ) const + { + #define S " " + + #define fmtSID "%*d" + #define argSID _maxSID, slv.id() + + #define fmtNAME COL_B "%s" COL_OFF "-" COL_G "%s" COL_OFF ".%-*s" + #define argNAME slv.ident().c_str(), slv.edition().c_str(), _maxNAME-slv.ident().size()-slv.edition().size(), slv.arch().c_str() + + #define fmtREPO "(%2d)%-*s" + #define argREPO slv.repository().info().priority(), _maxREPO, slv.repository().name().c_str() + + #define fmtTIME "%s%10ld" + #define argTIME ( slv.isSystem() && slv.installtime() ? "i" : "b" ), time_t( slv.isSystem() && slv.installtime() ? slv.installtime() : slv.buildtime() ) + + #define fmtVEND "%s" + #define argVEND slv.vendor().c_str() + + std::string dind( _maxSID + _maxNAME+2/*-.*/ + 2*strlen(S), ' ' ); + + for ( const auto & el : _map ) { + sat::Solvable slv { el.first }; + const char * tagCol = slv.isSystem() ? COL_M : ui::Selectable::get(slv)->identicalInstalled(PoolItem(slv)) ? COL_C : ""; + + str << str::form( "%s" fmtSID S fmtNAME S "%s" fmtREPO S fmtTIME S fmtVEND COL_OFF "\n", + tagCol, argSID, argNAME, tagCol, argREPO, argTIME, argVEND ); + + for ( const auto & d : el.second ) + str << dind << d << endl; + } + return str; + } + +private: + static void smax( unsigned & var_r, unsigned val_r, std::string_view n = {} ) + { if ( val_r > var_r ) var_r = val_r; } + +private: + unsigned _maxSID = 7; // size + indent + unsigned _maxNAME = 0; + unsigned _maxREPO = 0; + //unsigned _maxTIME = 10; + //unsigned _maxVEND = 0; + std::map _map; +}; + +inline std::ostream & operator<<( std::ostream & str, const Table & table_r ) +{ return table_r.dumpOn( str ); } + +/////////////////////////////////////////////////////////////////// + +void dDump( const std::string & spec_r ) +{ + message << "DUMP " << spec_r << " {"; + + sat::WhatProvides q( Capability::guessPackageSpec( spec_r ) ); + if ( q.empty() ) + { + message << "}" << endl; + return; + } + + for ( const auto & el : q ) + { + message << endl << "==============================" << endl << dump(el); + if ( isKind(el) ) + { + message << endl << "REPLACES: " << make(el)->replacedProducts(); + } + else if ( isKind(el) ) + { + message << endl << "CONTENT: " << make(el)->contents(); + } + else if ( isKind(el) ) + { + message << endl << "STATUS: " << PoolItem(el); + } + } + message << endl << "}" << endl; +} + +/////////////////////////////////////////////////////////////////// + +void dTree( const std::string & cmd_r, const std::string & spec_r ) +{ + message << "tree " << spec_r << " {"; + + sat::WhatProvides spec( Capability::guessPackageSpec( spec_r ) ); + if ( spec.empty() ) + { + message << "}" << endl; + return; + } + + static const std::list attrs { + sat::SolvAttr::requires, + sat::SolvAttr::recommends, + sat::SolvAttr::obsoletes, + sat::SolvAttr::conflicts, + sat::SolvAttr::supplements, + }; + + std::map>> result; // solvables recommending provided capability + { + Table t; + for ( const auto & el : spec ) + { + for ( const auto & cap : el.provides() ) + { + // get attrs matching cap + for ( const auto & attr : attrs ) + { + PoolQuery q; + q.addDependency( attr, cap ); + if ( q.empty() ) + continue; + for_( it, q.begin(), q.end() ) { + for_( match, it.matchesBegin(), it.matchesEnd() ) { + result[attr][*it].insert( match->inSolvAttr().asString().substr( 9, 3 )+": " +match->asString() + + " (" + cap.asString() + ")" + ); + } + } + } + } + } + message << endl << t; + } + + for ( const auto & attr : attrs ) + { + if ( result[attr].empty() ) + continue; + + message << endl << "======== " << attr << " by:" << endl; + Table t; + for ( const auto & el : result[attr] ) + { + auto & details { t.row( el.first ) }; + for ( const auto & cap : el.second ) + details.insert( cap ); + } + message << endl << t << endl; + } + message << "}" << endl; +} + +/****************************************************************** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +*/ +int main( int argc, char * argv[] ) +{ + INT << "===[START]==========================================" << endl; + appname = Pathname::basename( argv[0] ); + --argc,++argv; + + if ( ! argc ) + { + return usage(); + } + + /////////////////////////////////////////////////////////////////// + + auto _ { getZYpp() }; + ZConfig::instance(); + Pathname sysRoot("/"); + sat::Pool satpool( sat::Pool::instance() ); + + if ( argc && (*argv) == std::string("--root") ) + { + --argc,++argv; + if ( ! argc ) + return errexit("--root requires an argument."); + + if ( ! PathInfo( *argv ).isDir() ) + return errexit("--root requires a directory."); + + sysRoot = *argv; + --argc,++argv; + } + + bool onlyInstalled( false ); + if ( argc && (*argv) == std::string("--installed") ) + { + --argc,++argv; + onlyInstalled = true; + } + + if ( TestSetup::isTestcase( sysRoot ) ) + { + message << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl; + TestSetup test; + test.loadTestcaseRepos( sysRoot ); + dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl; + } + else if ( TestSetup::isTestSetup( sysRoot ) ) + { + message << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl; + const char * astr = getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ); + if ( !astr || !*astr ) + astr = getenv( "ZYPP_ARCH" ); + if ( !astr || !*astr ) + astr = "x86_64"; + TestSetup test( sysRoot, Arch( astr ) ); + test.loadRepos(); + dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl; + } + else + { + // a system + message << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl; + if ( true ) + { + message << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl; + getZYpp()->initializeTarget( sysRoot ); + getZYpp()->target()->load(); + message << satpool.systemRepo() << endl; + } + + if ( !onlyInstalled ) + { + RepoManager repoManager( sysRoot ); + RepoInfoList repos = repoManager.knownRepositories(); + for_( it, repos.begin(), repos.end() ) + { + RepoInfo & nrepo( *it ); + + if ( ! nrepo.enabled() ) + continue; + + if ( ! repoManager.isCached( nrepo ) ) + { + message << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + + message << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush; + try + { + repoManager.loadFromCache( nrepo ); + message << satpool.reposFind( nrepo.alias() ) << endl; + } + catch ( const Exception & exp ) + { + message << exp.asString() + "\n" + exp.historyAsString() << endl; + message << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + } + } + } + /////////////////////////////////////////////////////////////////// + + bool ignorecase ( true ); + bool matechexact ( false ); + bool withSrcPackages ( false ); + bool names ( true ); + bool provides ( false ); + bool requires ( false ); + bool conflicts ( false ); + bool obsoletes ( false ); + bool recommends ( false ); + bool supplements ( false ); + bool enhacements ( false ); + + + for ( ; argc; --argc,++argv ) + { + if ( (*argv)[0] == '-' ) + { + for ( const char * arg = (*argv)+1; *arg != '\0'; ++arg ) // -pr for -p -r + { + switch ( *arg ) + { + case 'a': names = true, requires = provides = true; break; + case 'A': names = true, requires = provides = false; break; + case 'D': + if ( argc > 1 ) + { + --argc,++argv; + dDump( *argv ); + } + else + return errexit("-D requires an argument."); + break; + case 'T': + if ( argc > 1 ) + { + std::string cmd { *argv }; + --argc,++argv; + dTree( cmd, *argv ); + } + else + return errexit("-T requires an argument."); + break; + case 'i': ignorecase = true; break; + case 'I': ignorecase = false; break; + case 'x': matechexact = true; break; + case 'n': names = true; break; + case 'N': names = false; break; + case 'r': requires = true; break; + case 'R': requires = false; break; + case 'p': provides = true; break; + case 'P': provides = false; break; + case 'c': conflicts = true; break; + case 'C': conflicts = false; break; + case 'o': obsoletes = true; break; + case 'O': obsoletes = false; break; + case 'm': recommends = true; break; + case 'M': recommends = false; break; + case 's': supplements = true; break; + case 'S': supplements = false; break; + case 'e': enhacements = true; break; + case 'E': enhacements = false; break; + } + } + continue; + } + + PoolQuery q; + if ( onlyInstalled ) + q.setInstalledOnly(); + std::string qstr( *argv ); + + if ( *argv == ResKind::product ) + { + q.addKind( ResKind::product ); + } + else if ( *argv == ResKind::patch ) + { + q.addKind( ResKind::patch ); + } + else if ( *argv == ResKind::pattern ) + { + q.addKind( ResKind::pattern ); + } + else + { + sat::Solvable::SplitIdent ident( qstr ); + if ( ident.kind() != ResKind::package ) + { + q.addKind( ident.kind() ); + q.addString( ident.name().asString() ); + } + else + q.addString( qstr ); + + if ( matechexact ) + q.setMatchGlob(); + else + q.setMatchRegex(); + q.setCaseSensitive( ! ignorecase ); + + if ( names ) + q.addAttribute( sat::SolvAttr::name ); + if ( provides ) + { + q.addDependency( sat::SolvAttr::provides ); + q.addDependency( sat::SolvAttr::provides, Capability(qstr) ); + } + if ( requires ) + { + q.addDependency( sat::SolvAttr::requires ); + q.addDependency( sat::SolvAttr::requires, Capability(qstr) ); + } + if ( conflicts ) + { + q.addDependency( sat::SolvAttr::conflicts ); + q.addDependency( sat::SolvAttr::conflicts, Capability(qstr) ); + } + if ( obsoletes ) + { + q.addDependency( sat::SolvAttr::obsoletes ); + q.addDependency( sat::SolvAttr::obsoletes, Capability(qstr) ); + } + if ( recommends ) + { + q.addDependency( sat::SolvAttr::recommends ); + q.addDependency( sat::SolvAttr::recommends, Capability(qstr) ); + } + if ( supplements ) + { + q.addDependency( sat::SolvAttr::supplements ); + q.addDependency( sat::SolvAttr::supplements, Capability(qstr) ); + } + if ( enhacements ) + { + q.addDependency( sat::SolvAttr::enhances ); + q.addDependency( sat::SolvAttr::enhances, Capability(qstr) ); + q.addDependency( sat::SolvAttr::suggests ); + q.addDependency( sat::SolvAttr::suggests, Capability(qstr) ); + } + } + + message << *argv << " [" << (ignorecase?'i':'_') << (names?'n':'_') << (requires?'r':'_') << (provides?'p':'_') + << (conflicts?'c':'_') << (obsoletes?'o':'_') << (recommends?'m':'_') << (supplements?'s':'_') << (enhacements?'e':'_') + << "] {" << endl; + + Table t; + for_( it, q.begin(), q.end() ) + { + if ( it->isKind( ResKind::srcpackage ) && !withSrcPackages ) + continue; + t.row( it ); + } + message << t << "}" << endl; + } + + INT << "===[END]============================================" << endl << endl; + return 0; +} diff --git a/tools/zypp-cpeid.cc b/tools/zypp-cpeid.cc new file mode 100644 index 0000000..f653b2d --- /dev/null +++ b/tools/zypp-cpeid.cc @@ -0,0 +1,66 @@ +#include +#include +#include + +using std::cout; +using std::endl; +using zypp::CpeId; +using zypp::Pathname; + +int main( int argc, const char * argv[] ) +{ + if ( argc == 1 || argv[1] == std::string( "--help" ) || argv[1] == std::string( "-h" ) ) + { + cout << + "Usage: " << Pathname::basename( argv[0] ) << " [CPEID]...\n" + "Check and print all supplied CPEIDs as FS, URI and WFN.\n" + "Afterwards compare them pairwise. \n" + "\n" + " (wfn:[part=\"a\",vendor=\"openSUSE\",product=\"libzypp\",version=\"14\\.17\\.3\"])\n" + " URI: cpe:/a:openSUSE:libzypp:14.17.3\n" + " FS: cpe:2.3:a:openSUSE:libzypp:14.17.3:*:*:*:*:*:*:*\n" + "\n"; + + return 0; + } + --argc, ++argv; + + + std::vector args; + args.reserve( argc ); + + for ( ; argc; --argc, ++argv ) + { + try { + CpeId cpe( argv[0] ); + cout << '[' << args.size() << "]-----------------------------------------------------------------------------" << endl; + cout << "arg: " << argv[0] << endl; + cout << " (" << cpe.asWfn() << ')' << endl; + cout << "URI: " << cpe.asUri() << endl; + cout << "FS: " << cpe<< endl; + args.push_back( cpe ); + } + catch ( const std::invalid_argument & exp ) + { + cout << "--------------------------------------------------------------------------------" << endl; + cout << "arg: " << argv[0] << endl; + cout << "ERR: " << exp.what() << endl; + } + } + + cout << "--------------------------------------------------------------------------------" << endl; + unsigned lhsidx = 0; + for ( const auto & lhs : args ) + { + unsigned rhsidx = 0; + for ( const auto & rhs : args ) + { + cout << "[" << lhsidx << "] " << lhs << endl; + cout << "[" << rhsidx << "] " << rhs << endl; + cout << " ==> " << compare( lhs, rhs ) << endl; + ++rhsidx; + } + ++lhsidx; + } + return 0; +} diff --git a/tools/zypp-install.cc b/tools/zypp-install.cc new file mode 100644 index 0000000..481a36a --- /dev/null +++ b/tools/zypp-install.cc @@ -0,0 +1,270 @@ +// +// g++ -Wall zypp-install.cc -l zypp -o zypp-install +// +// A small (and simple) demo which walks through zypp, initializing +// and refreshing the repos, selecting packages ('zypper dup'), +// resolving dependencies and finally comitting/installing the +// result (in dry-run mode). +// +// No callbacks, questions or fancy output during commit, but it will +// do a 'zypper dup' if you'd remove the DryRun and DownloadOnly flag. +// +// So be careful if running it as root. +// +#include + +#define TEST_DEBUGLOG 0 + +#if ( TEST_DEBUGLOG ) +#include +#endif +#include +#include +#include + +using std::cin; +using std::cout; +using std::cerr; +using std::endl; +using namespace zypp; + +//////////////////////////////////////////////////////////////////////////////// +int main( int argc, char * argv[] ) +try { + --argc; + ++argv; +#if ( TEST_DEBUGLOG ) +#warning debug log is on + base::LogControl::instance().logfile( "/tmp/zypp-install.log" ); +#endif + + Pathname sysRoot( "/" ); + ZYpp::Ptr zypp = getZYpp(); // acquire initial zypp lock + + //////////////////////////////////////////////////////////////////////////////// + // init Target: + { + cout << "Initialize target at " << sysRoot << endl; + zypp->initializeTarget( sysRoot ); // initialize target + cout << "Loading target resolvables" << endl; + zypp->getTarget()->load(); // load installed packages to pool + } + + //////////////////////////////////////////////////////////////////////////////// + // init Repos: + { + RepoManager repoManager( sysRoot ); + + // sync the current repo set + for ( RepoInfo & nrepo : repoManager.knownRepositories() ) + { + if ( ! nrepo.enabled() ) + continue; + + // Often volatile media are sipped in automated environments + // to avoid media chagne requests: + if ( nrepo.url().schemeIsVolatile() ) + continue; + + bool refreshNeeded = false; + if ( nrepo.autorefresh() ) // test whether to autorefresh repo metadata + { + for ( const Url & url : nrepo.baseUrls() ) + { + try + { + if ( repoManager.checkIfToRefreshMetadata( nrepo, url ) == RepoManager::REFRESH_NEEDED ) + { + cout << "Need to autorefresh repo " << nrepo.alias() << endl; + refreshNeeded = true; + } + break; // exit after first successful checkIfToRefreshMetadata + } + catch ( const Exception & exp ) + {} // Url failed, try next one... + } + // If all urls failed we can leave it to the code below to + // fail if access is actually needed and still failing. + // (missing metadata, package download, ...) + } + + // initial metadata download or cache refresh + if ( ! repoManager.isCached( nrepo ) || refreshNeeded ) + { + cout << "Refreshing repo " << nrepo << endl; + if ( repoManager.isCached( nrepo ) ) + { + repoManager.cleanCache( nrepo ); + } + repoManager.refreshMetadata( nrepo ); + repoManager.buildCache( nrepo ); + } + + // load cache + try + { + cout << "Loading resolvables from " << nrepo.alias() << endl; + repoManager.loadFromCache( nrepo );// load available packages to pool + } + catch ( const Exception & exp ) + { + // cachefile has old fomat (or is corrupted): try yo rebuild it + repoManager.cleanCache( nrepo ); + repoManager.buildCache( nrepo ); + repoManager.loadFromCache( nrepo ); + } + } + } + + cout << zypp->pool() << endl; + cout << "=====[pool ready]==============================" << endl; + + //////////////////////////////////////////////////////////////////////////////// + // GO... + //////////////////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////////////////// + // Select package to install... + // For demo purpose do 'zypper dup' + // otherwise select manually whatever you need... + zypp->resolver()->doUpgrade(); + + + //////////////////////////////////////////////////////////////////////////////// + // solve selection... + { + cout << "Solving dependencies..." << endl; + + unsigned attempt = 0; + while ( ! zypp->resolver()->resolvePool() ) + { + ++attempt; + cout << "Solving dependencies: " << attempt << ". attempt failed" << endl; + const ResolverProblemList & problems( zypp->resolver()->problems() ); + cout << problems.size() << " problems found..." << endl; + // Problem: + // ============================== + // kdepim3-3.5.10-29.1.4.x86_64 requires libsasl2.so.2()(64bit), but this requirement + // cannot be provided deleted providers: cyrus-sasl-2.1.25-28.1.2.x86_64 + // ------------------------------ + // Solution: + // keep obsolete cyrus-sasl-2.1.25-28.1.2.x86_64 + // Solution: + // remove lock to allow removal of kdepim3-3.5.10-29.1.4.x86_64 + // Solution: + // remove lock to allow removal of kdepim3-3.5.10-29.1.4.x86_64 + // Solution: + // break kdepim3-3.5.10-29.1.4.x86_64 by ignoring some of its dependencies + + ProblemSolutionList totry; // only needed if you (interactively) resolve problems... + + unsigned probNo = 0; + for ( const auto & probPtr : problems ) + { + cout << "Problem " << ++probNo << ": " << probPtr->description() << endl; + + const ProblemSolutionList & solutions = probPtr->solutions(); + unsigned solNo = 0; + for ( const auto & solPtr : solutions ) + { + cout << " Solution " << ++solNo << ": " << solPtr->description() << endl; + } + + // if you (interactively) resolve problems pick 1 solution per problem + // and store it int the totry list. After having applied the selected + // start a new attempt. + // + // It's not necessary to process all problems. You can pick a solution + // for the first problem and retry immediately. Often one solution actually + // resolves more than one reported problem. + // + // totry.push_back( solPtr ); + } + + + if ( ! totry.empty() ) + { + cout << "Apply selected solutions..." << endl; + zypp->resolver()->applySolutions( totry ); + cout << "Solving dependencies..." << endl; + continue; + } + // otherwise give up + throw "Solving dependencies failed: Giving up!"; + } + cout << "Dependencies solved" << endl; + } + + //////////////////////////////////////////////////////////////////////////////// + // printing some stats... + if ( false ) + { + cout << "PoolItem summary (individual packages):" << endl; + for ( const PoolItem & pi : zypp->pool() ) + { + if ( pi.status().transacts() ) + cout << " " << pi << endl; + } + } + else + { + cout << "Selectable summary (grouped by name):" << endl; + for ( const ui::Selectable_Ptr & sel : zypp->pool().proxy() ) + { + if ( sel->toModify() ) + cout << " " << sel << endl; + } + } + + //////////////////////////////////////////////////////////////////////////////// + // finally commit.. + { + cout << "Going to commit..." << endl; + // dryRun and DownloadOnly will cause commit to skip + // transaction steps, so you want to check for 'noError' + // rather than 'allDone'. + bool dryRunEtc = false; + + ZYppCommitPolicy policy; + if ( true ) + { + policy.dryRun( true ); + dryRunEtc = true; + } + if ( true ) + { + policy.downloadMode( DownloadOnly ); + dryRunEtc = true; + } + + try + { + ZYppCommitResult result = zypp->commit( policy ); // go.... + if ( ! ( result.allDone() || ( dryRunEtc && result.noError() ) ) ) + { + throw "Incomplete commit!"; + // ZYppCommitResult offers access to the TransactionStepList + // where you can see which packages have been processed and + // which not. + } + cout << "Commit succeeded" << endl; + } + catch ( const Exception & exp ) + { + cout << "Commit aborted with exception:" << endl; + throw; + } + } + cout << "[bye]: " << endl; + return 0; +} +catch ( const Exception & exp ) +{ cerr << exp << endl << exp.historyAsString(); exit( 91 ); } +catch ( const std::exception & exp ) +{ cerr << exp.what() << endl; exit( 92 ); } +catch ( const char * exp ) +{ cerr << (exp?exp:"Oops!") << endl; exit( 93 ); } +catch (...) +{ cerr << "Oops!" << endl; exit( 94 ); } + + diff --git a/tools/zypp-list.cc b/tools/zypp-list.cc new file mode 100644 index 0000000..405fab3 --- /dev/null +++ b/tools/zypp-list.cc @@ -0,0 +1,170 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST + +#include +#include + +static std::string appname( "zypp-list" ); + +#define message cerr +#define OUT cout +using std::flush; + +int errexit( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + return exit_r; +} + +int usage( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + cerr << "Usage: " << appname << " [GLOBALOPTS] COMMAND" << endl; + cerr << "List pool items according to command." << endl; + cerr << endl; + cerr << "GLOBALOPTS:" << endl; + cerr << " --root Load repos from the system located below ROOTDIR. If ROOTDIR" << endl; + cerr << " denotes a sover testcase, the testcase is loaded." << endl; + cerr << " -i, --installed Process installed packages only." << endl; + cerr << endl; + cerr << "COMMANDS:" << endl; + cerr << " locks: List all locked pool items." << endl; + cerr << " ." << endl; + cerr << endl; + return exit_r; +} + +void startup( const Pathname & sysRoot = "/", bool onlyInstalled = false ) +{ + ZConfig::instance(); + sat::Pool satpool( sat::Pool::instance() ); + + if ( TestSetup::isTestcase( sysRoot ) ) + { + message << str::form( "*** Load Testcase from '%s'", sysRoot.c_str() ) << endl; + TestSetup test; + test.loadTestcaseRepos( sysRoot ); + dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl; + } + else if ( TestSetup::isTestSetup( sysRoot ) ) + { + message << str::form( "*** Load TestSetup from '%s'", sysRoot.c_str() ) << endl; + TestSetup test( sysRoot, Arch_x86_64 ); + test.loadRepos(); + dumpRange( message, satpool.reposBegin(), satpool.reposEnd() ) << endl; + } + else + { + // a system + message << str::form( "*** Load system at '%s'", sysRoot.c_str() ) << endl; + if ( true ) + { + message << "*** load target '" << Repository::systemRepoAlias() << "'\t"; + getZYpp()->initializeTarget( sysRoot ); + getZYpp()->target()->load(); + message << satpool.systemRepo() << endl; + } + + if ( !onlyInstalled ) + { + RepoManager repoManager( sysRoot ); + RepoInfoList repos = repoManager.knownRepositories(); + for_( it, repos.begin(), repos.end() ) + { + RepoInfo & nrepo( *it ); + + if ( ! nrepo.enabled() ) + continue; + + if ( ! repoManager.isCached( nrepo ) ) + { + message << str::form( "*** omit uncached repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + + message << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << flush; + try + { + repoManager.loadFromCache( nrepo ); + message << satpool.reposFind( nrepo.alias() ) << endl; + } + catch ( const Exception & exp ) + { + message << exp.asString() + "\n" + exp.historyAsString() << endl; + message << str::form( "*** omit broken repo '%s' (do 'zypper refresh')", nrepo.name().c_str() ) << endl; + continue; + } + } + } + } +} + +/****************************************************************** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +*/ +int main( int argc, char * argv[] ) +{ + INT << "===[START]==========================================" << endl; + appname = Pathname::basename( argv[0] ); + --argc,++argv; + + if ( ! argc ) + { + return usage(); + } + + /////////////////////////////////////////////////////////////////// + + Pathname sysRoot( "/" ); + if ( argc && (*argv) == std::string("--root") ) + { + --argc,++argv; + if ( ! argc ) + return errexit("--root requires an argument."); + + if ( ! PathInfo( *argv ).isDir() ) + return errexit("--root requires a directory."); + + sysRoot = *argv; + --argc,++argv; + } + + bool onlyInstalled( false ); + if ( argc && (*argv) == std::string("--installed") ) + { + --argc,++argv; + onlyInstalled = true; + } + + /////////////////////////////////////////////////////////////////// + + if ( ! argc ) + { + return usage(); + } + + startup( sysRoot, onlyInstalled ); + ResPool pool( ResPool::instance() ); + + if ( argc && (*argv) == std::string("locked") ) + { + OUT << "*** Locked:" << endl; + for_( it, pool.begin(), pool.end() ) + { + if ( (*it).status().isLocked() ) + OUT << *it << endl; + } + } + + INT << "===[END]============================================" << endl << endl; + return 0; +} diff --git a/tools/zypp-media-chksum/CMakeLists.txt b/tools/zypp-media-chksum/CMakeLists.txt new file mode 100644 index 0000000..c48c017 --- /dev/null +++ b/tools/zypp-media-chksum/CMakeLists.txt @@ -0,0 +1,34 @@ +PROJECT( zypp-media-chksum C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-chksum/main.cc b/tools/zypp-media-chksum/main.cc new file mode 100644 index 0000000..3ddae70 --- /dev/null +++ b/tools/zypp-media-chksum/main.cc @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +class ChksumProvider : public zyppng::worker::ProvideWorker +{ + public: + ChksumProvider( std::string_view workerName ) : ProvideWorker( workerName ) { } + + void immediateShutdown() override { } + + protected: + // ProvideWorker interface + zyppng::expected initialize(const zyppng::worker::Configuration &conf) override { + + zyppng::worker::WorkerCaps caps; + caps.set_worker_type ( zyppng::worker::WorkerCaps::CPUBound ); + caps.set_cfg_flags( + zyppng::worker::WorkerCaps::Flags ( + zyppng::worker::WorkerCaps::Pipeline + | zyppng::worker::WorkerCaps::ZyppLogFormat + ) + ); + + return zyppng::expected::success(caps); + } + + void provide() override { + auto &queue = requestQueue(); + + if ( !queue.size() ) + return; + + + auto req = queue.front(); + queue.pop_front(); + + // here we only receive request codes, we only support Provide messages, all others are rejected + // Cancel is never to be received here + if ( req->_spec.code() != zyppng::ProvideMessage::Code::Prov ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , "Request type not implemented" + , false + , {} ); + return; + } + + zypp::Url url; + const auto &urlVal = req->_spec.value( zyppng::ProvideMsgFields::Url ); + try { + url = zypp::Url( urlVal.asString() ); + } catch ( const zypp::Exception &excp ) { + ZYPP_CAUGHT(excp); + + std::string err = zypp::str::Str() << "Invalid URL in request: " << urlVal.asString(); + ERR << err << std::endl; + + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , err + , false + , {} ); + + return; + } + + std::string chksumType; + try { + chksumType = req->_spec.value( std::string_view("chksumType") ).asString(); + } catch ( const zypp::Exception &excp ) { + ZYPP_CAUGHT(excp); + + std::string err = zypp::str::Str() << "No or invalid chksumType in request"; + ERR << err << std::endl; + + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , err + , false + , {} ); + + return; + } + + zypp::Pathname file = url.getPathName(); + if ( ! zypp::PathInfo( file ).isFile() ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotFound + , zypp::str::Str() << "File " << file << " not found." + , false + , {} ); + return; + } + + std::string filesum = zypp::filesystem::checksum( file, chksumType ); + DBG << "Calculated checksum for : " << file << " with type: " << chksumType << " is " << filesum << std::endl; + provideSuccess( req->_spec.requestId(), false, file, {{chksumType, {filesum}}} ); + } + + void cancel(const std::deque::iterator &i ) override { + ERR << "Bug, cancel should never be called for running items" << std::endl; + } + +}; + +int main( int argc, char *argv[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto provider = std::make_shared("zypp-media-chksum"); + auto res = provider->run (STDIN_FILENO, STDOUT_FILENO); + provider->immediateShutdown(); + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-copy/CMakeLists.txt b/tools/zypp-media-copy/CMakeLists.txt new file mode 100644 index 0000000..1d50213 --- /dev/null +++ b/tools/zypp-media-copy/CMakeLists.txt @@ -0,0 +1,34 @@ +PROJECT( zypp-media-copy C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-copy/main.cc b/tools/zypp-media-copy/main.cc new file mode 100644 index 0000000..eca609a --- /dev/null +++ b/tools/zypp-media-copy/main.cc @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include + +class CopyProvider : public zyppng::worker::ProvideWorker +{ + public: + CopyProvider( std::string_view workerName ) : ProvideWorker( workerName ) { } + + void immediateShutdown() override { } + + protected: + // ProvideWorker interface + zyppng::expected initialize(const zyppng::worker::Configuration &conf) override { + + zyppng::worker::WorkerCaps caps; + caps.set_worker_type ( zyppng::worker::WorkerCaps::CPUBound ); + caps.set_cfg_flags( + zyppng::worker::WorkerCaps::Flags ( + zyppng::worker::WorkerCaps::Pipeline + | zyppng::worker::WorkerCaps::ZyppLogFormat + | zyppng::worker::WorkerCaps::FileArtifacts + ) + ); + + return zyppng::expected::success(caps); + } + + void provide() override { + auto &queue = requestQueue(); + + if ( !queue.size() ) + return; + + + auto req = queue.front(); + queue.pop_front(); + + // here we only receive request codes, we only support Provide messages, all others are rejected + // Cancel is never to be received here + if ( req->_spec.code() != zyppng::ProvideMessage::Code::Prov ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , "Request type not implemented" + , false + , {} ); + return; + } + + zypp::Url url; + const auto &urlVal = req->_spec.value( zyppng::ProvideMsgFields::Url ); + try { + url = zypp::Url( urlVal.asString() ); + } catch ( const zypp::Exception &excp ) { + ZYPP_CAUGHT(excp); + + std::string err = zypp::str::Str() << "Invalid URL in request: " << urlVal.asString(); + ERR << err << std::endl; + + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , err + , false + , {} ); + + return; + } + + auto targetFileName = req->_spec.value( zyppng::ProvideMsgFields::Filename ); + if ( !targetFileName.valid() ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , "Copy worker requires a target filename hint" + , false + , {} ); + return; + } + zypp::Pathname targetFilePath( targetFileName.asString() ); + + zypp::PathInfo pi( url.getPathName() ); + if ( !pi.isExist() ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotFound + , zypp::str::Str() << "File " << pi.path() << " not found." + , false + , {} ); + return; + } + + if ( !pi.isFile() ) { + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotAFile + , zypp::str::Str() << "Path " << pi.path() << " exists, but its not a file" + , false + , {} ); + return; + } + + auto res = zypp::filesystem::hardlinkCopy( pi.path(), targetFileName.asString() ); + if ( res == 0 ) { + provideSuccess( req->_spec.requestId(), false, targetFilePath ); + } else { + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , zypp::str::Str() << "Failed to create file " << targetFilePath + , false + , {} ); + } + } + + void cancel(const std::deque::iterator &i ) override { + ERR << "Bug, cancel should never be called for running items" << std::endl; + } + +}; + +int main( int argc, char *argv[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto provider = std::make_shared("zypp-media-copy"); + auto res = provider->run (STDIN_FILENO, STDOUT_FILENO); + provider->immediateShutdown(); + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-dir/CMakeLists.txt b/tools/zypp-media-dir/CMakeLists.txt new file mode 100644 index 0000000..41e6d6e --- /dev/null +++ b/tools/zypp-media-dir/CMakeLists.txt @@ -0,0 +1,36 @@ +PROJECT( zypp-media-dir C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + dirprovider.cc + dirprovider.h +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-dir/dirprovider.cc b/tools/zypp-media-dir/dirprovider.cc new file mode 100644 index 0000000..5a15b03 --- /dev/null +++ b/tools/zypp-media-dir/dirprovider.cc @@ -0,0 +1,135 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "dirprovider.h" +#include +#include +#include + +#include +#include +#include + +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "DirProvider" + + +DirProvider::DirProvider() + : DeviceDriver( zyppng::worker::WorkerCaps::SimpleMount ) +{ } + +DirProvider::~DirProvider() +{ } + +zyppng::worker::AttachResult DirProvider::mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) +{ + try + { + if ( !attachUrl.getHost().empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Host must be empty in dir:// and file:// URLs" + , false ); + } + + // set up the verifier + zyppng::MediaDataVerifierRef verifier; + if ( extras.contains(zyppng::AttachMsgFields::VerifyType) ) { + verifier = zyppng::MediaDataVerifier::createVerifier( extras[zyppng::AttachMsgFields::VerifyType].asString() ); + if ( !verifier ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Invalid verifier type" + , false ); + } + + if ( !verifier->load( extras[zyppng::AttachMsgFields::VerifyData].asString() ) ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create verifier from file" + , false ); + } + } + const auto &devs = knownDevices(); + + // we simulate a device by simply using the pathname + zypp::Pathname path = zypp::Pathname( attachUrl.getPathName() ).realpath(); + const auto &pathStr = path.asString(); + + zypp::PathInfo adir( path ); + if( !adir.isDir()) { + // URl did not point to a directory + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , zypp::str::Str()<< "Specified path '" << attachUrl << "' is not a directory" + , false + ); + } + + // lets check if the path is what we want + auto res = isDesiredMedium( attachUrl, path, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !res ) { + try { + std::rethrow_exception( res.error() ); + } catch( const zypp::Exception& e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , false + , e ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , "Checking the medium failed with an uknown error" + , false ); + } + } + + // first check if we have that device already + auto i = std::find_if( devs.begin(), devs.end(), [&]( const auto &d ) { return d->_name == pathStr; } ); + if ( i != devs.end() ) { + attachedMedia().insert( { attachId, zyppng::worker::AttachedMedia{ ._dev = *i, ._attachRoot = "/" } } ); + return zyppng::worker::AttachResult::success( (*i)->_mountPoint ); + } + + // we did not find a existing device, well lets make a new one + MIL << "New device " << path << " mounted on " << path << std::endl; + auto newDev = std::make_shared( zyppng::worker::Device{ + ._name = pathStr, + ._maj_nr = 0, + ._min_nr = 0, + ._mountPoint = path, + ._ephemeral = true, // device should be removed after the last attachment was released + ._properties = {} + }); + attachedMedia().insert( { attachId, zyppng::worker::AttachedMedia{ ._dev = newDev, ._attachRoot = "/" } } ); + return zyppng::worker::AttachResult::success( path ); + + } catch ( const zypp::Exception &e ) { + return zyppng::worker::AttachResult::error ( + zyppng::ProvideMessage::Code::BadRequest + , false + , e ); + } catch ( const std::exception &e ) { + return zyppng::worker::AttachResult::error ( + zyppng::ProvideMessage::Code::BadRequest + , e.what() + , false ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , "Unknown exception" + , false); + } +} + +void DirProvider::unmountDevice ( zyppng::worker::Device &dev ) { + // do nothing , this is just a local dir +} diff --git a/tools/zypp-media-dir/dirprovider.h b/tools/zypp-media-dir/dirprovider.h new file mode 100644 index 0000000..0bd2adc --- /dev/null +++ b/tools/zypp-media-dir/dirprovider.h @@ -0,0 +1,27 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_DIRPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_DIRPROVIDER_H_INCLUDED + +#include + +class DirProvider : public zyppng::worker::DeviceDriver +{ + public: + DirProvider( ); + ~DirProvider(); + + zyppng::worker::AttachResult mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) override; + + protected: + void unmountDevice ( zyppng::worker::Device &dev ) override; + +}; + +#endif diff --git a/tools/zypp-media-dir/main.cc b/tools/zypp-media-dir/main.cc new file mode 100644 index 0000000..8408bee --- /dev/null +++ b/tools/zypp-media-dir/main.cc @@ -0,0 +1,28 @@ +#include "dirprovider.h" + +#include +#include +#include + + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto driver = std::make_shared(); + auto provider = std::make_shared( "zypp-media-dir", driver ); + driver->setProvider( provider ); + + auto res = provider->run (STDIN_FILENO, STDOUT_FILENO); + + MIL << "DIR Worker shutting down" << std::endl; + + provider->immediateShutdown(); + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-disc/CMakeLists.txt b/tools/zypp-media-disc/CMakeLists.txt new file mode 100644 index 0000000..881046d --- /dev/null +++ b/tools/zypp-media-disc/CMakeLists.txt @@ -0,0 +1,44 @@ +PROJECT( zypp-media-disc C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + discprovider.cc + discprovider.h +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) + +IF ( UDEV_FOUND ) + TARGET_LINK_LIBRARIES( ${PROJECT_NAME} ${UDEV_LIBRARY} ) +ELSE ( UDEV_FOUND ) + IF ( HAL_FOUND ) + TARGET_LINK_LIBRARIES( ${PROJECT_NAME} ${HAL_LIBRARY} ${HAL_STORAGE_LIBRARY} ${DBUS_LIBRARY} ) + ENDIF ( HAL_FOUND ) +ENDIF ( UDEV_FOUND ) diff --git a/tools/zypp-media-disc/discprovider.cc b/tools/zypp-media-disc/discprovider.cc new file mode 100644 index 0000000..b9f6b75 --- /dev/null +++ b/tools/zypp-media-disc/discprovider.cc @@ -0,0 +1,404 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "discprovider.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "DiscProvider" + +extern "C" +{ +#include +#include +#if HAVE_UDEV +#include +#endif +} + +using namespace std::literals; + +DiscProvider::DiscProvider( ) : zyppng::worker::DeviceDriver( zyppng::worker::WorkerCaps::VolatileMount ) +{ } + +DiscProvider::~DiscProvider() +{} + +zyppng::worker::AttachResult DiscProvider::mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) +{ + std::vector devs; + if ( extras.contains( zyppng::AttachMsgFields::Device ) ) { + for ( const auto &d :extras.values( zyppng::AttachMsgFields::Device ) ) { + if ( d.isString() ) { + MIL << "Got device from user we are allowed to use: " << d.asString() << std::endl; + devs.push_back(d.asString()); + } + } + } + + auto &sysDevs = knownDevices(); + + std::vector> possibleDevs; + if ( devs.size () ) { + for ( const auto &d : devs ) { + zypp::PathInfo p(d); + if ( !p.isBlk () ) + continue; + + std::shared_ptr device; + auto i = std::find_if( sysDevs.begin(), sysDevs.end(), [&p]( const auto &sysDev ){ return ( sysDev->_maj_nr == p.devMajor() && sysDev->_min_nr == p.devMinor() ); } ); + if ( i == sysDevs.end() ) { + // this is a device we did not detect before lets see if its a CDROM +#ifdef HAVE_UDEV + zypp::AutoDispose udev( ::udev_new(), ::udev_unref ); + if ( !udev ) { + ERR << "Can't create udev context." << std::endl; + continue; + } + + auto devnum = makedev( p.devMajor(), p.devMinor() ); + zypp::AutoDispose udevDevice( ::udev_device_new_from_devnum ( udev, 'b', devnum ), ::udev_device_unref ); + if ( !udevDevice ) { + ERR << "Can't create udev device from devnum, ignoring." << std::endl; + continue; + } + + if ( zypp::strv::asStringView( ::udev_device_get_property_value( udevDevice, "ID_CDROM" ) ) != "1" ) { + ERR << "Device " << d << " from Attach request is not a CDROM/DVD ignoring!" << std::endl; + continue; + } + + auto dev = std::make_shared( zyppng::worker::Device { + ._name = p.path().asString(), + ._maj_nr = p.devMajor(), + ._min_nr = p.devMinor() } ); + DBG << "Registering device (REQUEST): " << dev->_name << " " << dev->_maj_nr << ":" << dev->_min_nr << std::endl; + sysDevs.push_back ( dev ); + device = dev; +#endif + } else { + device = *i; + } + + if ( device ) + possibleDevs.push_back(device); + } + } else { + possibleDevs = sysDevs; + } + + // if we have no devices at this point controller gets a error + if ( possibleDevs.empty () ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "No useable device found" + , false + ); + } + + const auto attachRoot = zypp::Pathname( attachUrl.getPathName() ); + const auto attachMediaNr = extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt(); + + // set up the verifier + zyppng::MediaDataVerifierRef verifier; + if ( extras.contains( zyppng::AttachMsgFields::VerifyType ) ) { + verifier = zyppng::MediaDataVerifier::createVerifier( extras.value(zyppng::AttachMsgFields::VerifyType).asString() ); + if ( !verifier ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Invalid verifier type" + , false + ); + } + + if ( !verifier->load( extras.value(zyppng::AttachMsgFields::VerifyData).asString() ) ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create verifier from file" + , false + ); + } + } + + //first check if any of the mounted devices are what we want + for( const auto &dev : possibleDevs ) { + if ( dev->_mountPoint.empty() ) + continue; + + auto res = isDesiredMedium( attachUrl, dev->_mountPoint / attachRoot, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !res ) + continue; + + MIL << "Found requested medium in dev " << dev->_name << std::endl; + + // we found the device we want! + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ dev, attachRoot } ) ); + return zyppng::worker::AttachResult::success( dev->_mountPoint / attachRoot ); + } + + std::list filesystems; + + filesystems.push_back("iso9660"); + + // if DVD, try UDF filesystem after iso9660 + if ( attachUrl.getScheme() == "dvd" ) + filesystems.push_back("udf"); + + std::string options; + auto optVal = extras.value( "mountoptions"sv ); + if ( optVal.valid() && optVal.isString() ) + options = optVal.asString(); + + if ( options.empty() ) { + options="ro"; + } + + while ( true ) { + + // remember how many devices we were able to test + uint devicesTested = 0; + + // none of the already mounted devices matched, lets try what we have left + for( const auto &dev : possibleDevs ) { + if ( !dev->_mountPoint.empty() ) + continue; + + MIL << "Trying to mount dev " << dev->_name << std::endl; + + // make sure the tray is closed + zypp::media::CDTools::closeTray( dev->_name ); + + devicesTested++; + zypp::media::Mount mount; + bool mountsucceeded = false; + std::exception_ptr lastErr; + for( auto fsit = filesystems.begin() ; !mountsucceeded && fsit != filesystems.end() ; ++fsit) { + + zypp::Pathname newAp; + try { + newAp = createAttachPoint( this->attachRoot() ); + if ( newAp.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create mount directory." + , false + ); + } + + mount.mount( dev->_name, newAp.asString(), *fsit, options); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 2; + while( !(mountsucceeded=checkAttached( newAp, devicePredicate( dev->_maj_nr, dev->_min_nr ))) && --limit) + { + WAR << "Wait for /proc/mounts update and retry...." << std::endl; + sleep(1); + } + + if( !mountsucceeded) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaMountException( + "Unable to verify that the media was mounted", + dev->_name, newAp.asString() + )); + } else { + dev->_mountPoint = newAp; + break; + } + } + catch (const zypp::media::MediaMountException &e) + { + lastErr = std::current_exception (); + removeAttachPoint(newAp); + ZYPP_CAUGHT(e); + } + catch (const zypp::media::MediaException & excpt_r) + { + removeAttachPoint(newAp); + ZYPP_CAUGHT(excpt_r); + } + } // for filesystems + + if ( mountsucceeded ) { + auto res = isDesiredMedium( attachUrl, dev->_mountPoint / attachRoot, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !res ) { + unmountDevice( *dev ); + continue; + } + + MIL << "Found requested medium in dev " << dev->_name << std::endl; + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ dev, attachRoot } ) ); + return zyppng::worker::AttachResult::success( dev->_mountPoint / attachRoot ); + } + } // for each device + + // we did go through all devices, but didn't find any. + if ( devicesTested == 0 ) { + // no devices are free + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::Jammed + , "No free ressources available" + , false + ); + } else { + + const auto &mountedDevs = zypp::media::Mount::getEntries(); + // k, we need to ask the user to give us the medium we need + // first find the devices that are free + std::vector freeDevs; + for( const auto &dev : possibleDevs ) { + if ( !dev->_mountPoint.empty() ) + continue; + + auto i = std::find_if( mountedDevs.begin (), mountedDevs.end(), [&dev]( const zypp::media::MountEntry &e ) { + zypp::PathInfo pi( e.src ); + return ( pi.isBlk() && pi.devMajor() == dev->_maj_nr && pi.devMinor() == dev->_min_nr ); + }); + + if ( i == mountedDevs.end() ) { + MIL << "Adding " << dev->_name << " to list of free devs" << std::endl; + freeDevs.push_back( dev->_name ); + } + } + + // if there are no devices free, we are jammed + if ( freeDevs.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::Jammed + , "No free ressources available" + , false + ); + } + + auto changeRes = zyppng::worker::ProvideWorker::ABORT; + auto worker = parentWorker(); + if ( worker ) { + changeRes = worker->requestMediaChange ( id, label, attachMediaNr, freeDevs ); + } + + if ( changeRes != zyppng::worker::ProvideWorker::SUCCESS ) { + if ( changeRes == zyppng::worker::ProvideWorker::SKIP) + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediaChangeSkip + , "User asked to skip the media change." + , false); + else + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediaChangeAbort + , "User asked to abort the media change." + , false ); + } + } + } +} + +void DiscProvider::detectDevices( ) +{ + + // helper lambda to add a new device to the internal registry, returning it if its either created or already known + const auto registerDevice = [ this ]( const zypp::PathInfo &devnode, std::string_view reason ) { + auto &sysDevs = knownDevices(); + if ( devnode.isBlk() ) { + auto i = std::find_if( sysDevs.begin(), sysDevs.end(), [&]( const auto &dev ){ + return ( dev->_maj_nr == devnode.devMajor() && dev->_min_nr == devnode.devMinor () ); + }); + + // we already know the device + if ( i != sysDevs.end() ) + return i; + + auto dev = std::make_shared( zyppng::worker::Device{ + ._name = devnode.path().asString(), + ._maj_nr = devnode.devMajor(), + ._min_nr = devnode.devMinor() } ); + DBG << "Found (" << reason << "): " << dev->_name << " " << dev->_maj_nr << ":" << dev->_min_nr << std::endl; + + sysDevs.push_back(dev); + return ( --sysDevs.end() ); + } + return sysDevs.end(); + }; + + + auto &sysDevs = knownDevices(); + + // detect devices available in the system if we did not do it before: + if ( !_devicesDetected ) { + _devicesDetected = true; + +#ifdef HAVE_UDEV + // http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/index.html + zypp::AutoDispose udev( ::udev_new(), ::udev_unref ); + if ( ! udev ) { + ERR << "Can't create udev context." << std::endl; + } else { + zypp::AutoDispose enumerate( ::udev_enumerate_new(udev), ::udev_enumerate_unref ); + if ( ! enumerate ) { + ERR << "Can't create udev list entry." << std::endl; + } else { + ::udev_enumerate_add_match_subsystem( enumerate, "block" ); + ::udev_enumerate_add_match_property( enumerate, "ID_CDROM", "1" ); + ::udev_enumerate_scan_devices( enumerate ); + + struct udev_list_entry * entry = 0; + udev_list_entry_foreach( entry, ::udev_enumerate_get_list_entry( enumerate ) ) + { + + zypp::AutoDispose device( ::udev_device_new_from_syspath( ::udev_enumerate_get_udev( enumerate ), + ::udev_list_entry_get_name( entry ) ), + ::udev_device_unref ); + if ( ! device ) + { + ERR << "Can't create udev device." << std::endl; + continue; + } + + const char * devnodePtr( ::udev_device_get_devnode( device ) ); + if ( ! devnodePtr ) { + ERR << "Got NULL devicenode." << std::endl; + continue; + } + + // In case we need it someday: + //const char * mountpath = ::udev_device_get_property_value( device, "FSTAB_DIR" ); + auto dev = registerDevice( zypp::PathInfo ( devnodePtr ), "udev" ); + if ( dev != sysDevs.end() ) { + if ( ::udev_device_get_property_value( device, "ID_CDROM_DVD" ) ) { + (*dev)->_properties["DVD"] = true; + } else { + (*dev)->_properties["DVD"] = false; + } + } + } + } + } +#endif + if ( sysDevs.empty() ) + { + WAR << "CD/DVD drive detection with UDEV failed! Guessing..." << std::endl; + auto dev = registerDevice( zypp::PathInfo ( "/dev/dvd" ), "GUESS" ); + if ( dev != sysDevs.end() && (*dev)->_properties.count("DVD") == 0 ) + (*dev)->_properties["DVD"] = true; + dev = registerDevice( zypp::PathInfo ( "/dev/cdrom" ), "GUESS" ); + if ( dev != sysDevs.end() && (*dev)->_properties.count("DVD") == 0 ) + (*dev)->_properties["DVD"] = false; + } + } +} diff --git a/tools/zypp-media-disc/discprovider.h b/tools/zypp-media-disc/discprovider.h new file mode 100644 index 0000000..b3ae672 --- /dev/null +++ b/tools/zypp-media-disc/discprovider.h @@ -0,0 +1,31 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_DISCPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_DISCPROVIDER_H_INCLUDED + +#include +#include +#include +#include + +class DiscProvider : public zyppng::worker::DeviceDriver +{ +public: + DiscProvider(); + ~DiscProvider(); + + // DeviceDriver interface + zyppng::worker::AttachResult mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) override; + void detectDevices() override; + +private: + bool _devicesDetected = false; //< We delay device detection to the first attach request, to avoid doing it without needing it +}; + +#endif diff --git a/tools/zypp-media-disc/main.cc b/tools/zypp-media-disc/main.cc new file mode 100644 index 0000000..e19533f --- /dev/null +++ b/tools/zypp-media-disc/main.cc @@ -0,0 +1,27 @@ + +#include "discprovider.h" + +#include +#include + +#include + + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto driver = std::make_shared(); + auto provider = std::make_shared( "zypp-media-disc", driver ); + driver->setProvider( provider ); + + auto res = provider->run (STDIN_FILENO, STDOUT_FILENO); + provider->immediateShutdown(); + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-disk/CMakeLists.txt b/tools/zypp-media-disk/CMakeLists.txt new file mode 100644 index 0000000..f866b9a --- /dev/null +++ b/tools/zypp-media-disk/CMakeLists.txt @@ -0,0 +1,36 @@ +PROJECT( zypp-media-disk C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + diskprovider.cc + diskprovider.h +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-disk/diskprovider.cc b/tools/zypp-media-disk/diskprovider.cc new file mode 100644 index 0000000..7c3d84b --- /dev/null +++ b/tools/zypp-media-disk/diskprovider.cc @@ -0,0 +1,363 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "diskprovider.h" +#include +#include +#include + +#include +#include + +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "DiskProvider" + + +/*! + * Check if specified device file name is + * a disk volume device or throw an error. + */ +bool verifyIfDiskVolume( const zypp::Pathname &dev_name ) +{ + if( dev_name.empty() || + dev_name.asString().compare(0, sizeof("/dev/")-1, "/dev/")) + { + ERR << "Specified device name " << dev_name + << " is not allowed" << std::endl; + return false; + } + + zypp::PathInfo dev_info(dev_name); + if( !dev_info.isBlk()) + { + ERR << "Specified device name " << dev_name + << " is not a block device" << std::endl; + return false; + } + + // check if a volume using /dev/disk/by-uuid links first + { + zypp::Pathname dpath("/dev/disk/by-uuid"); + std::list dlist; + if( zypp::filesystem::readdir(dlist, dpath) == 0) + { + std::list::const_iterator it; + for(it = dlist.begin(); it != dlist.end(); ++it) + { + zypp::PathInfo vol_info(*it); + if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() && + vol_info.devMinor() == dev_info.devMinor()) + { + DBG << "Specified device name " << dev_name + << " is a volume (disk/by-uuid link " + << vol_info.path() << ")" + << std::endl; + return true; + } + } + } + } + + // check if a volume using /dev/disk/by-label links + // (e.g. vbd mapped volumes in a XEN vm) + { + zypp::Pathname dpath("/dev/disk/by-label"); + std::list dlist; + if( zypp::filesystem::readdir(dlist, dpath) == 0) + { + std::list::const_iterator it; + for(it = dlist.begin(); it != dlist.end(); ++it) + { + zypp::PathInfo vol_info(*it); + if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() && + vol_info.devMinor() == dev_info.devMinor()) + { + DBG << "Specified device name " << dev_name + << " is a volume (disk/by-label link " + << vol_info.path() << ")" + << std::endl; + return true; + } + } + } + } + + // check if a filesystem volume using the 'blkid' tool + // (there is no /dev/disk link for some of them) + zypp::ExternalProgram::Arguments args; + args.push_back( "blkid" ); + args.push_back( "-p" ); + args.push_back( dev_name.asString() ); + + zypp::ExternalProgram cmd( args, zypp::ExternalProgram::Stderr_To_Stdout ); + cmd >> DBG; + if ( cmd.close() != 0 ) + { + ERR << cmd.execError() + << "\nSpecified device name " << dev_name + << " is not a usable disk volume" + << std::endl; + return false; + } + return true; +} + + + +DiskProvider::DiskProvider() + : DeviceDriver( zyppng::worker::WorkerCaps::SimpleMount ) +{ } + +DiskProvider::~DiskProvider() +{ } + +zyppng::worker::AttachResult DiskProvider::mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) +{ + try + { + if ( !attachUrl.getHost().empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Host must be empty in dir:// and file:// URLs" + , false + ); + } + + const std::string device = zypp::Pathname(attachUrl.getQueryParam("device")).asString(); + if ( device.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Media url does not contain a device specification" + , false + ); + } + + std::string filesystem = attachUrl.getQueryParam("filesystem"); + if( filesystem.empty() ) + filesystem="auto"; + + zypp::PathInfo dev_info( device ); + if(!dev_info.isBlk()) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Media url does not specify a valid block device" + , false + ); + } + + DBG << "Verifying " << device << " ..." << std::endl; + if( !verifyIfDiskVolume( device)) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Could not verify URL points to a disk volume!" + , false + ); + } + + // disks can have a attach root ( path relative to the device root ) + const auto relAttachRoot = zypp::Pathname( attachUrl.getPathName() ); + + // set up the verifier + zyppng::MediaDataVerifierRef verifier; + if ( extras.value( zyppng::AttachMsgFields::VerifyType ).valid() ) { + verifier = zyppng::MediaDataVerifier::createVerifier( extras.value(zyppng::AttachMsgFields::VerifyType).asString() ); + if ( !verifier ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Invalid verifier type" + , false + ); + } + + if ( !verifier->load( extras.value(zyppng::AttachMsgFields::VerifyData).asString() ) ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create verifier from file" + , false + ); + } + } + const auto &devs = knownDevices(); + + // first check if we have that device already + auto i = std::find_if( devs.begin(), devs.end(), [&]( const auto &d ) { + return d->_maj_nr == dev_info.devMajor() + && d->_min_nr == dev_info.devMinor(); + }); + if ( i != devs.end() ) { + auto res = isDesiredMedium( attachUrl, (*i)->_mountPoint / relAttachRoot, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !res ) { + try { + std::rethrow_exception( res.error() ); + } catch( const zypp::Exception& e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , false + , e + ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , "Checking the medium failed with an uknown error" + , false + ); + } + } else { + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ *i, relAttachRoot } ) ); + return zyppng::worker::AttachResult::success( (*i)->_mountPoint / relAttachRoot ); + } + } + + // we did not find a existing mount, well lets make a new one ... + std::optional bindSource; + auto devPtr = std::make_shared( zyppng::worker::Device{ + ._name = dev_info.path().asString(), + ._maj_nr = dev_info.devMajor(), + ._min_nr = dev_info.devMinor(), + ._mountPoint = {}, + ._ephemeral = true, // forget about the device after we are finished with it + ._properties = {} + }); + + // since the kernel will not let us remount a disc ro if it was already mounted in the system as rw we need to + // go over the existing mounts and revert to a bind mount if we find that the device has a mountpoint already (#163486). + zypp::media::MountEntries entries( zypp::media::Mount::getEntries() ); + for( auto e = entries.cbegin(); e != entries.cend(); ++e) + { + bool is_device = false; + std::string dev_path(zypp::Pathname(e->src).asString()); + zypp::PathInfo dev_info; + + if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 && + dev_info(e->src) && dev_info.isBlk()) { + is_device = true; + } + + if( is_device && devPtr->_maj_nr == dev_info.devMajor() && + devPtr->_min_nr == dev_info.devMinor()) + { + DBG << "Device " << devPtr->_name << " is already mounted, using bind mount!" << std::endl; + bindSource = e->dir; + break; + } + } + + zypp::media::Mount mount; + zypp::Pathname newAp; + try { + newAp = createAttachPoint( attachRoot() ); + if ( newAp.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create mount directory." + , false + ); + } + + std::string options = attachUrl.getQueryParam("mountoptions"); + if(options.empty()) { + options = "ro"; + } + + if( bindSource ) { + options += ",bind"; + mount.mount( bindSource->asString(), newAp.asString(), "none", options); + } else { + mount.mount( dev_info.path().asString(), newAp.asString(), filesystem, options); + } + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + + const auto &checkAttachedDisk = [&]( const zypp::media::MountEntry &e ) { + if ( bindSource) { + if ( *bindSource == e.src ) { + DBG << "Found bound media " + << devPtr->_name + << " in the mount table as " << e.src << std::endl; + return true; + } + } + return DeviceDriver::devicePredicate( devPtr->_maj_nr, devPtr->_min_nr ) ( e ); + }; + + // mount command came back OK, lets wait for mtab to update + while( !(mountsucceeded=checkAttached( newAp, checkAttachedDisk )) && --limit) { + MIL << "Mount did not appear yet, sleeping for 1s" << std::endl; + sleep(1); + } + + // mount didn't work after all, bail out + if ( !mountsucceeded ) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaMountException( + "Unable to verify that the media was mounted", + devPtr->_name, newAp.asString() + )); + } + + // if we reach this place, mount worked -> YAY, lets see if that is the desired medium! + auto isDesired = isDesiredMedium( attachUrl, newAp / relAttachRoot, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !isDesired ) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaNotDesiredException( attachUrl ) ); + } + } + catch ( const zypp::Exception &e ) { + removeAttachPoint(newAp); + ZYPP_CAUGHT(e); + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , false + , e + ); + } + catch ( ... ) { + removeAttachPoint(newAp); + ZYPP_RETHROW( std::current_exception() ); + } + + // mount worked ! YAY + devPtr->_mountPoint = newAp; + knownDevices().push_back( devPtr ); + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ devPtr, relAttachRoot } ) ); + return zyppng::worker::AttachResult::success( devPtr->_mountPoint / relAttachRoot ); + + } catch ( const zypp::Exception &e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , false + , e + ); + } catch ( const std::exception &e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , e.what() + , false + ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , "Unknown exception" + , false + ); + } +} diff --git a/tools/zypp-media-disk/diskprovider.h b/tools/zypp-media-disk/diskprovider.h new file mode 100644 index 0000000..7d5828b --- /dev/null +++ b/tools/zypp-media-disk/diskprovider.h @@ -0,0 +1,25 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_DISKPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_DISKPROVIDER_H_INCLUDED + +#include + +class DiskProvider : public zyppng::worker::DeviceDriver +{ + public: + DiskProvider(); + ~DiskProvider(); + + // DeviceDriver interface + zyppng::worker::AttachResult mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) override; + +}; + +#endif diff --git a/tools/zypp-media-disk/main.cc b/tools/zypp-media-disk/main.cc new file mode 100644 index 0000000..208ee56 --- /dev/null +++ b/tools/zypp-media-disk/main.cc @@ -0,0 +1,26 @@ +#include "diskprovider.h" + +#include +#include +#include + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto driver = std::make_shared(); + auto worker = std::make_shared( "zypp-media-disk", driver ); + driver->setProvider( worker ); + + auto res = worker->run (STDIN_FILENO, STDOUT_FILENO); + + MIL << "DISK Worker shutting down" << std::endl; + + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-http/CMakeLists.txt b/tools/zypp-media-http/CMakeLists.txt new file mode 100644 index 0000000..1424cdb --- /dev/null +++ b/tools/zypp-media-http/CMakeLists.txt @@ -0,0 +1,37 @@ +PROJECT( zypp-media-http C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + networkprovider.cc + networkprovider.h +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-curl ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-http/main.cc b/tools/zypp-media-http/main.cc new file mode 100644 index 0000000..c6fde54 --- /dev/null +++ b/tools/zypp-media-http/main.cc @@ -0,0 +1,21 @@ +#include "networkprovider.h" + +#include +#include + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto provider = std::make_shared("zypp-media-http"); + auto res = provider->run (STDIN_FILENO, STDOUT_FILENO); + provider->immediateShutdown(); + if ( res ) + return 0; + + //@TODO print error + return 1; + //@TODO @WARNING @BUG Initialize the requestmanager with user agent and anon headers \sa anonymousIdHeader, distributionFlavorHeader, agentString +} diff --git a/tools/zypp-media-http/networkprovider.cc b/tools/zypp-media-http/networkprovider.cc new file mode 100644 index 0000000..ac91049 --- /dev/null +++ b/tools/zypp-media-http/networkprovider.cc @@ -0,0 +1,494 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "networkprovider.h" + +#include +#include +#include +#include +#include +#include +#include + + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "NetworkProvider" + + +NetworkProvideItem::NetworkProvideItem(NetworkProvider &parent, zyppng::ProvideMessage &&spec) + : zyppng::worker::ProvideWorkerItem( std::move(spec) ) + , _parent(parent) +{} + +NetworkProvideItem::~NetworkProvideItem() +{ + clearConnections(); + if ( _dl ) { + _dl->cancel(); + } +} + +void NetworkProvideItem::startDownload( std::shared_ptr &&dl ) +{ + if ( _state == ProvideWorkerItem::Running || _dl ) + throw std::runtime_error("Can not start a already running Download"); + + MIL_PRV << "Starting download of : " << dl->spec().url() << "with target path: " << dl->spec().targetPath() << std::endl; + + _connections.clear (); + // we set the state to running immediately but only send the message to controller once the item actually started + _state = ProvideWorkerItem::Running; + _dl = std::move(dl); + _connections.emplace_back( connect( *_dl, &zyppng::Download::sigStarted, *this, &NetworkProvideItem::onStarted ) ); + _connections.emplace_back( connect( *_dl, &zyppng::Download::sigFinished, *this, &NetworkProvideItem::onFinished ) ); + _connections.emplace_back( connect( *_dl, &zyppng::Download::sigAuthRequired, *this, &NetworkProvideItem::onAuthRequired ) ); + + _dl->setStopOnMetalink( true ); + _dl->start(); +} + +void NetworkProvideItem::cancelDownload() +{ + _state = zyppng::worker::ProvideWorkerItem::Finished; + if ( _dl ) { + _dl->cancel(); + clearConnections(); + _dl.reset(); + } +} + +void NetworkProvideItem::clearConnections() +{ + for ( auto c : _connections) + c.disconnect(); + _connections.clear(); +} + +void NetworkProvideItem::onStarted( zyppng::Download & ) +{ + _parent.itemStarted( shared_this() ); +} + +void NetworkProvideItem::onFinished( zyppng::Download & ) +{ + _parent.itemFinished( shared_this() ); +} + +void NetworkProvideItem::onAuthRequired( zyppng::Download &, zyppng::NetworkAuthData &auth, const std::string &availAuth ) +{ + _parent.itemAuthRequired( shared_this(), auth, availAuth ); +} + + +NetworkProvider::NetworkProvider( std::string_view workerName ) + : zyppng::worker::ProvideWorker( workerName ) + , _dlManager( std::make_shared() ) +{ + // we only want to hear about new provides + setProvNotificationMode( ProvideWorker::ONLY_NEW_PROVIDES ); +} + +zyppng::expected NetworkProvider::initialize( const zyppng::worker::Configuration &conf ) +{ + const auto iEnd = conf.end(); + if ( const auto &i = conf.find( std::string(zyppng::AGENT_STRING_CONF) ); i != iEnd ) { + const auto &val = i->second; + MIL << "Setting agent string to: " << val << std::endl; + _dlManager->requestDispatcher()->setAgentString( val ); + } + if ( const auto &i = conf.find( std::string(zyppng::DISTRO_FLAV_CONF) ); i != iEnd ) { + const auto &val = i->second; + MIL << "Setting distro flavor header to: " << val << std::endl; + _dlManager->requestDispatcher()->setHostSpecificHeader("download.opensuse.org", "X-ZYpp-DistributionFlavor", val ); + } + if ( const auto &i = conf.find( std::string(zyppng::ANON_ID_CONF) ); i != iEnd ) { + const auto &val = i->second; + MIL << "Got anonymous ID setting from controller" << std::endl; + _dlManager->requestDispatcher()->setHostSpecificHeader("download.opensuse.org", "X-ZYpp-AnonymousId", val ); + } + if ( const auto &i = conf.find( std::string(zyppng::ATTACH_POINT) ); i != iEnd ) { + const auto &val = i->second; + MIL << "Got attachpoint from controller: " << val << std::endl; + _attachPoint = val; + } else { + return zyppng::expected::error(ZYPP_EXCPT_PTR( zypp::Exception("Attach point required to work.") )); + } + + zyppng::worker::WorkerCaps caps; + caps.set_worker_type ( zyppng::worker::WorkerCaps::Downloading ); + caps.set_cfg_flags( + zyppng::worker::WorkerCaps::Flags ( + zyppng::worker::WorkerCaps::Pipeline + | zyppng::worker::WorkerCaps::ZyppLogFormat + ) + ); + + return zyppng::expected::success(caps); +} + +void NetworkProvider::provide() +{ + auto &queue = requestQueue(); + + if ( !queue.size() ) + return; + + const auto now = std::chrono::steady_clock::now(); + auto &io = controlIO(); + + while ( io.readFdOpen() ) { + // find next pending item + auto i = std::find_if( queue.begin(), queue.end(), [&now]( const zyppng::worker::ProvideWorkerItemRef &req ){ + NetworkProvideItemRef nReq = std::static_pointer_cast(req); + return nReq && nReq->_state == zyppng::worker::ProvideWorkerItem::Pending && nReq->_scheduleAfter < now; + }); + + // none left, bail out + if ( i == queue.end () ) + break; + + auto req = std::static_pointer_cast( *i ); + if ( req->_state != zyppng::worker::ProvideWorkerItem::Pending ) + return; + + MIL_PRV << "About to schedule: " << req->_spec.code() << " with ID: "<< req->_spec.requestId() << std::endl; + + // here we only receive request codes, we only support Provide messages, all others are rejected + // Cancel is never to be received here + if ( req->_spec.code() != zyppng::ProvideMessage::Code::Prov ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , "Request type not implemented" + , false + , {} ); + + queue.erase(i); + continue; + } + + zypp::Url url; + const auto &urlVal = req->_spec.value( zyppng::ProvideMsgFields::Url ); + try { + url = zypp::Url( urlVal.asString() ); + } catch ( const zypp::Exception &excp ) { + ZYPP_CAUGHT(excp); + + std::string err = zypp::str::Str() << "Invalid URL in request: " << urlVal.asString(); + ERR << err << std::endl; + + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , err + , false + , {} ); + + queue.erase(i); + continue; + } + + const auto &fPath = zypp::Pathname( url.getPathName() ); + + /* + * We download into the staging directory first, using the md5sum of the full path as filename. + * Once the download is finished its transferred into the cache directory. This way we can clearly + * distinguish between cancelled downloads and downloads we have completely finished. + */ + zypp::Pathname localPath = zypp::Pathname( _attachPoint ) / "cache" / fPath; + zypp::Pathname stagingPath = ( zypp::Pathname( _attachPoint ) / "staging" / zypp::CheckSum::md5FromString( fPath.asString() ).asString() ).extend(".part"); + + MIL_PRV << "Providing " << url << " to local: " << localPath << " staging: " << stagingPath << std::endl; + + // Cache hit? + zypp::PathInfo cacheFile(localPath); + if ( cacheFile.isExist () ) { + + // could be a directory + if ( !cacheFile.isFile() ) { + MIL_PRV << "Path " << url << " exists in Cache but its not a file!" << std::endl; + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotAFile + , "Not a file" + , false + , {} ); + + queue.erase(i); + continue; + } + + MIL_PRV << "Providing " << url << "Cache HIT" << std::endl; + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideSuccess ( req->_spec.requestId(), true, localPath ); + queue.erase(i); + continue; + } + + if ( zypp::PathInfo(stagingPath).isExist () ) { + // check if there is another request running with this staging file name + auto runningIt = std::find_if( queue.begin (), queue.end(), [&]( const zyppng::worker::ProvideWorkerItemRef &queueItem ){ + if ( req == queueItem || queueItem->_state != zyppng::worker::ProvideWorkerItem::Running ) + return false; + return ( static_cast( queueItem.get() )->_stagingFileName == stagingPath ); + }); + + // we schedule that later again which should result in a immediate cache hit + if ( runningIt != queue.end() ) { + MIL << "Found a existing request that results in the same staging file, postponing the request for later" << std::endl; + req->_scheduleAfter = now; + continue; + } + + MIL<< "Removing broken staging file" << stagingPath << std::endl; + + // here this is most likely a broken download + zypp::filesystem::unlink( stagingPath ); + } + + auto errCode = zypp::filesystem::assert_dir( localPath.dirname() ); + if( errCode ) { + std::string err = zypp::str::Str() << "assert_dir " << localPath.dirname() << " failed"; + DBG << err << std::endl; + + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::InternalError + , err + , false + , {} ); + queue.erase(i); + continue; + } + + errCode = zypp::filesystem::assert_dir( stagingPath.dirname() ); + if( errCode ) { + std::string err = zypp::str::Str() << "assert_dir " << stagingPath.dirname() << " failed"; + DBG << err << std::endl; + + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::InternalError + , err + , false + , {} ); + queue.erase(i); + continue; + } + + bool doMetalink = true; + const auto &metalinkVal = req->_spec.value( zyppng::NETWORK_METALINK_ENABLED ); + if ( metalinkVal.valid() && metalinkVal.isBool () ) { + doMetalink = metalinkVal.asBool(); + MIL << "Explicity setting metalink " << ( doMetalink ? "enabled" : "disabled" ) << std::endl; + } + + ERR << "Forcing Metalink to be disabled until zsync/metalink is correctly implemented again" << std::endl; + doMetalink = false; + + req->_targetFileName = localPath; + req->_stagingFileName = stagingPath; + + const auto &expFilesize = req->_spec.value( zyppng::ProvideMsgFields::ExpectedFilesize ); + const auto &checkExistsOnly = req->_spec.value( zyppng::ProvideMsgFields::CheckExistOnly ); + const auto &deltaFile = req->_spec.value( zyppng::ProvideMsgFields::DeltaFile ); + + zyppng::DownloadSpec spec( + url + , stagingPath + , expFilesize.valid() ? zypp::ByteCount( expFilesize.asInt64() ) : zypp::ByteCount() + ); + spec + .setCheckExistsOnly( checkExistsOnly.valid() ? checkExistsOnly.asBool() : false ) + .setDeltaFile ( deltaFile.valid() ? deltaFile.asString() : zypp::Pathname() ) + .setMetalinkEnabled ( doMetalink ); + + req->startDownload( _dlManager->downloadFile ( spec ) ); + } +} + +void NetworkProvider::cancel( const std::deque::iterator &i ) +{ + auto &queue = requestQueue (); + if ( i == queue.end() ) { + ERR << "Unknown request ID, ignoring." << std::endl; + return; + } + + const auto &req = std::static_pointer_cast(*i); + req->cancelDownload(); + queue.erase(i); +} + +void NetworkProvider::immediateShutdown() +{ + for ( const auto &pItem : requestQueue () ) { + auto ref = std::static_pointer_cast( pItem ); + ref->cancelDownload(); + } +} + +zyppng::worker::ProvideWorkerItemRef NetworkProvider::makeItem(zyppng::ProvideMessage &&spec ) +{ + return std::make_shared( *this, std::move(spec) ); +} + +void NetworkProvider::itemStarted( NetworkProvideItemRef item ) +{ + provideStart( item->_spec.requestId(), item->_dl->spec().url().asCompleteString(), item->_targetFileName.asString(), item->_stagingFileName.asString() ); +} + +void NetworkProvider::itemFinished( NetworkProvideItemRef item ) +{ + auto &queue = requestQueue (); + auto i = std::find( queue.begin(), queue.end(), item ); + if ( i == queue.end() ) { + ERR << "Unknown request finished. This is a BUG!" << std::endl; + return; + } + + item->_state = NetworkProvideItem::Finished; + if ( !item->_dl->hasError() ) { + + if ( item->_dl->stoppedOnMetalink () ) { + // need to read the metalink info and send back a redirect + try { + zypp::media::MetaLinkParser pars; + pars.parse( item->_stagingFileName ); + + std::vector urls; + + for ( const auto &mirr : pars.getMirrors () ) { + try { + zypp::Url url( mirr.url.asCompleteString () ); + urls.push_back(url); + + if ( urls.size() == 10 ) + break; + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + } + } + + // @TODO , restart the download without metalink? + if ( urls.size() == 0 ) + throw zypp::Exception("No usable mirrors in Mirrorlink file"); + + if ( !messageStream()->sendMessage( zyppng::ProvideMessage::createMetalinkRedir( item->_spec.requestId(), urls ) ) ) { + ERR << "Failed to send ProvideSuccess message" << std::endl; + } + + } catch ( const zypp::Exception &exp ) { + zypp::filesystem::hardlinkCopy ( item->_stagingFileName, "/tmp/broken" ); + ZYPP_CAUGHT(exp); + provideFailed( item->_spec.requestId(), zyppng::ProvideMessage::Code::InternalError, exp.asUserString (), false ); + } + + zypp::filesystem::unlink( item->_stagingFileName ); + + } else { + + if ( item->_dl->spec().checkExistsOnly() ) { + // check exist only, we just return success with the target file name + provideSuccess( item->_spec.requestId(), false, item->_targetFileName ); + } + + const auto errCode = zypp::filesystem::rename( item->_stagingFileName, item->_targetFileName ); + if( errCode ) { + + zypp::filesystem::unlink( item->_stagingFileName ); + + std::string err = zypp::str::Str() << "Renaming " << item->_stagingFileName << " to " << item->_targetFileName << " failed!"; + DBG << err << std::endl; + + provideFailed( item->_spec.requestId() + , zyppng::ProvideMessage::Code::InternalError + , err + , false + , {} ); + + } else { + provideSuccess( item->_spec.requestId(), false, item->_targetFileName ); + } + } + } else { + zyppng::HeaderValueMap extra; + bool isTransient = false; + auto errCode = zyppng::ProvideMessage::Code::InternalError; + + const auto &error = item->_dl->lastRequestError(); + switch( error.type() ) { + case zyppng::NetworkRequestError::NoError: { throw std::runtime_error("DownloadError info broken"); break;} + case zyppng::NetworkRequestError::InternalError: { errCode = zyppng::ProvideMessage::Code::InternalError; break;} + case zyppng::NetworkRequestError::RangeFail: { errCode = zyppng::ProvideMessage::Code::InternalError; break;} + case zyppng::NetworkRequestError::Cancelled: { errCode = zyppng::ProvideMessage::Code::Cancelled; break;} + case zyppng::NetworkRequestError::PeerCertificateInvalid: { errCode = zyppng::ProvideMessage::Code::PeerCertificateInvalid; break;} + case zyppng::NetworkRequestError::ConnectionFailed: { errCode = zyppng::ProvideMessage::Code::ConnectionFailed; break;} + case zyppng::NetworkRequestError::ExceededMaxLen: { errCode = zyppng::ProvideMessage::Code::ExpectedSizeExceeded; break;} + case zyppng::NetworkRequestError::InvalidChecksum: { errCode = zyppng::ProvideMessage::Code::InvalidChecksum; break;} + case zyppng::NetworkRequestError::UnsupportedProtocol: { errCode = zyppng::ProvideMessage::Code::BadRequest; break; } + case zyppng::NetworkRequestError::MalformedURL: { errCode = zyppng::ProvideMessage::Code::BadRequest; break; } + case zyppng::NetworkRequestError::TemporaryProblem: { errCode = zyppng::ProvideMessage::Code::InternalError; isTransient = true; break;} + case zyppng::NetworkRequestError::Timeout: { errCode = zyppng::ProvideMessage::Code::Timeout; break;} + case zyppng::NetworkRequestError::Forbidden: { errCode = zyppng::ProvideMessage::Code::Forbidden; break;} + case zyppng::NetworkRequestError::NotFound: { errCode = zyppng::ProvideMessage::Code::NotFound; break;} + case zyppng::NetworkRequestError::Unauthorized: { + errCode = zyppng::ProvideMessage::Code::Unauthorized; + const auto &authHint = error.extraInfoValue("authHint", std::string()); + if ( authHint.size () ) + extra.set ( "authhint", authHint ); + break; + } + case zyppng::NetworkRequestError::AuthFailed: { + errCode = zyppng::ProvideMessage::Code::NoAuthData; + const auto &authHint = error.extraInfoValue("authHint", std::string()); + if ( authHint.size () ) + extra.set ( "authhint", authHint ); + break; + } + //@TODO add extra codes for handling these + case zyppng::NetworkRequestError::Http2Error: + case zyppng::NetworkRequestError::Http2StreamError: + case zyppng::NetworkRequestError::ServerReturnedError: { errCode = zyppng::ProvideMessage::Code::InternalError; break; } + case zyppng::NetworkRequestError::MissingData: { errCode = zyppng::ProvideMessage::Code::BadRequest; break; } + } + + provideFailed( item->_spec.requestId(), errCode, item->_dl->errorString(), isTransient, extra ); + } + queue.erase(i); + + // pick the next request + provide(); +} + +void NetworkProvider::itemAuthRequired( NetworkProvideItemRef item, zyppng::NetworkAuthData &auth, const std::string & availAuth ) +{ + auto res = requireAuthorization( item->_spec.requestId(), auth.url(), auth.username(), auth.lastDatabaseUpdate(), { { std::string( zyppng::AuthDataRequestMsgFields::AuthHint ), availAuth } } ); + if ( !res ) { + auth = zyppng::NetworkAuthData(); + return; + } + + auth.setUrl ( item->_dl->spec().url() ); + auth.setUsername ( res->username ); + auth.setPassword ( res->password ); + auth.setLastDatabaseUpdate ( res->last_auth_timestamp ); + auth.extraValues() = res->extraKeys; + + const auto &keyStr = std::string(zyppng::AuthInfoMsgFields::AuthType); + if ( res->extraKeys.count( keyStr ) ) { + auth.setAuthType( res->extraKeys[keyStr] ); + } + + //@todo migrate away from using NetworkAuthData, AuthData now has a map of extra values that can carry the AuthType + const auto &authTypeKey = std::string( zyppng::AuthInfoMsgFields::AuthType ); + if ( res->extraKeys.count( authTypeKey ) ) + auth.setAuthType( res->extraKeys[ authTypeKey ] ); +} diff --git a/tools/zypp-media-http/networkprovider.h b/tools/zypp-media-http/networkprovider.h new file mode 100644 index 0000000..1fa6807 --- /dev/null +++ b/tools/zypp-media-http/networkprovider.h @@ -0,0 +1,80 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_NETWORKPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_NETWORKPROVIDER_H_INCLUDED + +#include +#include +#include +#include +#include + +namespace zyppng { + class Downloader; + class Download; +} + +class NetworkProvider; + +struct NetworkProvideItem : public zyppng::worker::ProvideWorkerItem +{ +public: + NetworkProvideItem( NetworkProvider &parent, zyppng::ProvideMessage &&spec ); + ~NetworkProvideItem(); + + void startDownload( std::shared_ptr &&dl ); + void cancelDownload (); + + std::shared_ptr _dl; + zypp::Pathname _targetFileName; + zypp::Pathname _stagingFileName; + + std::chrono::steady_clock::time_point _scheduleAfter = std::chrono::steady_clock::time_point::min(); + +private: + void clearConnections (); + void onStarted ( zyppng::Download & ); + void onFinished ( zyppng::Download & ); + void onAuthRequired ( zyppng::Download &, zyppng::NetworkAuthData &auth, const std::string &availAuth ); + +private: + std::vector _connections; + NetworkProvider &_parent; +}; + +using NetworkProvideItemRef = std::shared_ptr; + +class NetworkProvider : public zyppng::worker::ProvideWorker +{ +public: + NetworkProvider( std::string_view workerName ); + void immediateShutdown() override; + +protected: + // ProvideWorker interface + zyppng::expected initialize(const zyppng::worker::Configuration &conf) override; + void provide() override; + void cancel(const std::deque::iterator &i ) override; + zyppng::worker::ProvideWorkerItemRef makeItem(zyppng::ProvideMessage &&spec) override; + + friend struct NetworkProvideItem; + void itemStarted ( NetworkProvideItemRef item ); + void itemFinished ( NetworkProvideItemRef item ); + void itemAuthRequired (NetworkProvideItemRef item, zyppng::NetworkAuthData &auth, const std::string &); + +private: + std::shared_ptr _dlManager; + zypp::Pathname _attachPoint; +}; + + + + + +#endif diff --git a/tools/zypp-media-iso/CMakeLists.txt b/tools/zypp-media-iso/CMakeLists.txt new file mode 100644 index 0000000..0ded4ec --- /dev/null +++ b/tools/zypp-media-iso/CMakeLists.txt @@ -0,0 +1,51 @@ +PROJECT( zypp-media-iso C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + isoprovider.cc + isoprovider.h + ${ZYPP_TOOLS_DIR}/zypp-media-dir/dirprovider.h + ${ZYPP_TOOLS_DIR}/zypp-media-dir/dirprovider.cc + ${ZYPP_TOOLS_DIR}/zypp-media-disk/diskprovider.h + ${ZYPP_TOOLS_DIR}/zypp-media-disk/diskprovider.cc + ${ZYPP_TOOLS_DIR}/zypp-media-nfs/nfsprovider.h + ${ZYPP_TOOLS_DIR}/zypp-media-nfs/nfsprovider.cc + ${ZYPP_TOOLS_DIR}/zypp-media-smb/smbprovider.h + ${ZYPP_TOOLS_DIR}/zypp-media-smb/smbprovider.cc +) + +include_directories( + ${ZYPP_TOOLS_DIR}/zypp-media-dir + ${ZYPP_TOOLS_DIR}/zypp-media-disk + ${ZYPP_TOOLS_DIR}/zypp-media-nfs + ${ZYPP_TOOLS_DIR}/zypp-media-smb +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-iso/isoprovider.cc b/tools/zypp-media-iso/isoprovider.cc new file mode 100644 index 0000000..16d0d6a --- /dev/null +++ b/tools/zypp-media-iso/isoprovider.cc @@ -0,0 +1,399 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "isoprovider.h" +#include +#include + +#include +#include + +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "IsoProvider" + +RaiiHelper::~RaiiHelper() +{ + _backingDriver->detachMedia( id ); + _backingDriver->releaseIdleDevices(); +} + +IsoProvider::IsoProvider( ) + : DeviceDriver( zyppng::worker::WorkerCaps::SimpleMount ) +{ } + +IsoProvider::~IsoProvider() +{ } + +zyppng::worker::AttachResult IsoProvider::mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) +{ + try + { + zypp::Pathname isofile = attachUrl.getQueryParam("iso"); + if( isofile.empty()) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , zypp::str::Str()<<"Media url: "<load( extras.value(zyppng::AttachMsgFields::VerifyData).asString() ) ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create verifier from file" + , false + ); + } + } + + // first check if we have that device already + const auto &devs = knownDevices(); + auto i = std::find_if( devs.begin(), devs.end(), [&]( const auto &d ) { + return d->_name == fullIsoUrl.asString(); + }); + if ( i != devs.end() ) { + // if we can find the device, isDesiredMedium needs to return true, + // otherwise URL and verifier do not match and its not the desired medium + auto res = isDesiredMedium( attachUrl, (*i)->_mountPoint / relAttachRoot, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !res ) { + try { + std::rethrow_exception( res.error() ); + } catch( const zypp::Exception& e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , false + , e + ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , "Checking the medium failed with an uknown error" + , false + ); + } + } else { + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ *i, relAttachRoot } ) ); + return zyppng::worker::AttachResult::success( (*i)->_mountPoint / relAttachRoot ); + } + } + + // helper lambda to invoke the deviceDriver + const auto &attachViaHelper = [&]( auto &driver, const std::string &type ) { + + auto mountRes = driver->mountDevice( id, src, attachId, "", {} ); + if ( !mountRes ) { + return mountRes; + } + + // make sure the media is released as soon as its not needed anymore + auto hlpr = std::make_shared(); + hlpr->_backingDriver = driver; + hlpr->id = attachId; + + // k, get the mountpoint from the backing driver + const auto &attMedias = driver->attachedMedia(); + auto i = attMedias.find( attachId ); + if ( i == attMedias.end() ) { + const std::string &err = zypp::str::Str()<< "Failed to query mounted supporting device: " << src.asString(); + ERR << err << std::endl; + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , err + , false ); + } + + // full path to the ISO in the filesystem + auto isopath = zypp::filesystem::expandlink( i->second._dev->_mountPoint / isofile ); + if( isopath.empty() || !zypp::PathInfo(isopath).isFile()) { + const std::string &err = zypp::str::Str()<< "No ISO file found on given source location: " << src.asString(); + ERR << err << std::endl; + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , err + , false ); + } + + // we have everything we need, let's try to mount it + zypp::media::Mount mount; + zypp::Pathname newAp; + try { + newAp = createAttachPoint( attachRoot() ); + if ( newAp.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create mount directory." + , false + ); + } + + std::string mountpoint( newAp.asString() ); + std::string mountopts("ro,loop"); + + mount.mount( isopath.asString(), mountpoint, + filesystem, mountopts ); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + + // Type ISO: Since 11.1 mtab might contain the name of + // the loop device instead of the iso file: + const auto &checkAttachedISO = [&]( const zypp::media::MountEntry &e ) { + if ( zypp::str::hasPrefix( zypp::Pathname(e.src).asString(), "/dev/loop" ) + && mountpoint == zypp::Pathname(e.dir) ) { + DBG << "Found bound media " + << isopath + << " in the mount table as " << e.src << std::endl; + return true; + } + return false; + }; + + // mount command came back OK, lets wait for mtab to update + while( !(mountsucceeded=checkAttached( newAp, checkAttachedISO )) && --limit) { + MIL << "Mount did not appear yet, sleeping for 1s" << std::endl; + sleep(1); + } + + // mount didn't work after all, bail out + if ( !mountsucceeded ) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaMountException( + "Unable to verify that the media was mounted", + isopath.asString(), newAp.asString() + )); + } + + // if we reach this place, mount worked -> YAY, lets see if that is the desired medium! + auto isDesired = isDesiredMedium( attachUrl, newAp / relAttachRoot, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !isDesired ) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaNotDesiredException( attachUrl ) ); + } + + } catch ( const zypp::Exception &e ) { + removeAttachPoint(newAp); + ZYPP_CAUGHT(e); + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , false + , e + ); + } + + // here we have our device AND it is verified , lets register it and return it to the user + auto devPtr = std::make_shared( zyppng::worker::Device{ + ._name = fullIsoUrl.asString(), + ._maj_nr = 0, + ._min_nr = 0, + ._mountPoint = newAp, + ._ephemeral = true, // forget about the device after we are finished with it + ._properties = {} + }); + devPtr->_properties["raiiHelper"] = hlpr; + + + knownDevices().push_back( devPtr ); + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ devPtr, relAttachRoot } ) ); + return zyppng::worker::AttachResult::success( devPtr->_mountPoint / relAttachRoot ); + + }; + + if( !src.isValid()) { + const std::string &err = zypp::str::Str()<<"Invalid iso filename source media url: "<(); + + auto subAttachRoot = ( attachRoot().realpath()/"disk" ); + zypp::filesystem::assert_dir( subAttachRoot ); + + auto confCopy = config(); + confCopy[std::string(zyppng::ATTACH_POINT)] = subAttachRoot.asString(); + const auto &res = _diskWorker->initialize( confCopy ); + if ( !res ) { + const std::string &err = zypp::str::Str()<< "Failed to initialize worker for: " << src.asString(); + ERR << err << std::endl; + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , err + , false ); + } + } + + return attachViaHelper( _diskWorker, "disk" ); + + } else if ( src.getScheme() == "dir" || src.getScheme() == "file" ) { + + if ( !_dirWorker ) { + _dirWorker = std::make_shared(); + + auto subAttachRoot = ( attachRoot().realpath()/"dir" ); + zypp::filesystem::assert_dir( subAttachRoot ); + + auto confCopy = config(); + confCopy[std::string(zyppng::ATTACH_POINT)] = subAttachRoot.asString(); + const auto &res = _dirWorker->initialize( confCopy ); + if ( !res ) { + const std::string &err = zypp::str::Str()<< "Failed to initialize worker for: " << src.asString(); + ERR << err << std::endl; + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , err + , false ); + } + } + + return attachViaHelper( _dirWorker, "dir" ); + + } else if ( src.getScheme() == "nfs" || src.getScheme() == "nfs4" ) { + + if ( !_nfsWorker ) { + _nfsWorker = std::make_shared(); + + auto subAttachRoot = ( attachRoot().realpath()/"nfs" ); + zypp::filesystem::assert_dir( subAttachRoot ); + + auto confCopy = config(); + confCopy[std::string(zyppng::ATTACH_POINT)] = subAttachRoot.asString(); + const auto &res = _nfsWorker->initialize( confCopy ); + MIL << "AFTER INIT " << _nfsWorker->attachRoot() << std::endl; + if ( !res ) { + const std::string &err = zypp::str::Str()<< "Failed to initialize worker for: " << src.asString(); + ERR << err << std::endl; + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , err + , false ); + } + } + + return attachViaHelper( _nfsWorker, "nfs" ); + + } else if ( src.getScheme() == "smb" || src.getScheme() == "cifs" ) { + + if ( !_smbWorker ) { + _smbWorker = std::make_shared(); + + auto subAttachRoot = ( attachRoot().realpath()/"smb" ); + zypp::filesystem::assert_dir( subAttachRoot ); + + auto confCopy = config(); + confCopy[std::string(zyppng::ATTACH_POINT)] = subAttachRoot.asString(); + const auto &res = _smbWorker->initialize( confCopy ); + if ( !res ) { + const std::string &err = zypp::str::Str()<< "Failed to initialize worker for: " << src.asString(); + ERR << err << std::endl; + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , err + , false ); + } + } + + return attachViaHelper( _smbWorker, "smb" ); + + } else { + const std::string &err = zypp::str::Str()<< "ISO filename source media url scheme is not supported: " << src.asString(); + ERR << err << std::endl; + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , err + , false ); + } + } catch ( const zypp::Exception &e ) { + return zyppng::worker::AttachResult::error ( + zyppng::ProvideMessage::Code::BadRequest + , false + , e ); + } catch ( const std::exception &e ) { + return zyppng::worker::AttachResult::error ( + zyppng::ProvideMessage::Code::BadRequest + , e.what() + , false ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , "Unknown exception" + , false); + } +} diff --git a/tools/zypp-media-iso/isoprovider.h b/tools/zypp-media-iso/isoprovider.h new file mode 100644 index 0000000..72f39fa --- /dev/null +++ b/tools/zypp-media-iso/isoprovider.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_ISOPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_ISOPROVIDER_H_INCLUDED + +#include +#include "dirprovider.h" +#include "smbprovider.h" +#include "diskprovider.h" +#include "nfsprovider.h" + + +struct RaiiHelper +{ + ~RaiiHelper(); + zyppng::worker::DeviceDriverRef _backingDriver; + std::string id; +}; + +class IsoProvider : public zyppng::worker::DeviceDriver +{ + public: + IsoProvider( ); + ~IsoProvider(); + + zyppng::worker::AttachResult mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) override; + + private: + std::shared_ptr _dirWorker; + std::shared_ptr _diskWorker; + std::shared_ptr _nfsWorker; + std::shared_ptr _smbWorker; + +}; + +#endif diff --git a/tools/zypp-media-iso/main.cc b/tools/zypp-media-iso/main.cc new file mode 100644 index 0000000..a384ce6 --- /dev/null +++ b/tools/zypp-media-iso/main.cc @@ -0,0 +1,27 @@ +#include "isoprovider.h" + +#include +#include +#include + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto driver = std::make_shared(); + auto provider = std::make_shared( "zypp-media-iso", driver ); + driver->setProvider( provider ); + + auto res = provider->run (STDIN_FILENO, STDOUT_FILENO); + + MIL << "ISO Worker shutting down" << std::endl; + + provider->immediateShutdown(); + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-nfs/CMakeLists.txt b/tools/zypp-media-nfs/CMakeLists.txt new file mode 100644 index 0000000..34c562e --- /dev/null +++ b/tools/zypp-media-nfs/CMakeLists.txt @@ -0,0 +1,36 @@ +PROJECT( zypp-media-nfs C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + nfsprovider.cc + nfsprovider.h +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-nfs/main.cc b/tools/zypp-media-nfs/main.cc new file mode 100644 index 0000000..17171e1 --- /dev/null +++ b/tools/zypp-media-nfs/main.cc @@ -0,0 +1,23 @@ +#include "nfsprovider.h" + +#include +#include +#include + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto driver = std::make_shared(); + auto worker = std::make_shared( "zypp-media-nfs", driver ); + driver->setProvider( worker ); + + auto res = worker->run (STDIN_FILENO, STDOUT_FILENO); + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-nfs/nfsprovider.cc b/tools/zypp-media-nfs/nfsprovider.cc new file mode 100644 index 0000000..9c23464 --- /dev/null +++ b/tools/zypp-media-nfs/nfsprovider.cc @@ -0,0 +1,262 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "nfsprovider.h" +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "NfsProvider" + +using namespace std::literals::string_view_literals; + +/** + * Value of NFS mount minor timeout (passed to timeo option + * of the NFS mount) in tenths of a second. + * + * The value of 300 should give a major timeout after 3.5 minutes + * for UDP and 1.5 minutes for TCP. (#350309) + */ +constexpr auto NFS_MOUNT_TIMEOUT = 300; +constexpr std::array NFS_MOUNT_FSTYPES = { "nfs"sv, "nfs4"sv }; + +NfsProvider::NfsProvider( ) + : DeviceDriver( zyppng::worker::WorkerCaps::SimpleMount ) +{ } + +NfsProvider::~NfsProvider() +{ } + +zyppng::worker::AttachResult NfsProvider::mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) +{ + try + { + if ( attachUrl.getHost().empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Host can not be empty" + , false + ); + } + + // set up the verifier + zyppng::MediaDataVerifierRef verifier; + zyppng::MediaDataVerifierRef devVerifier; + if ( extras.value( zyppng::AttachMsgFields::VerifyType ).valid() ) { + verifier = zyppng::MediaDataVerifier::createVerifier( extras.value(zyppng::AttachMsgFields::VerifyType).asString() ); + if ( !verifier ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Invalid verifier type" + , false + ); + } + + if ( !verifier->load( extras.value(zyppng::AttachMsgFields::VerifyData).asString() ) ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create verifier from file" + , false + ); + } + } + const auto &devs = knownDevices(); + + // build a device name the same way the old media backend did + std::string path = attachUrl.getHost(); + path += ':'; + path += zypp::Pathname(attachUrl.getPathName()).asString(); + + // first check if we have that device already + auto i = std::find_if( devs.begin(), devs.end(), [&]( const auto &d ) { return d->_name == path; } ); + if ( i != devs.end() ) { + auto res = isDesiredMedium( attachUrl, (*i)->_mountPoint, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !res ) { + try { + std::rethrow_exception( res.error() ); + } catch( const zypp::Exception& e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , false + , e ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , "Checking the medium failed with an uknown error" + , false + ); + } + } else { + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ *i, "/" } ) ); + return zyppng::worker::AttachResult::success( (*i)->_mountPoint ); + } + } + + // we did not find a existing mount, well lets make a new one + // start with some legacy code: + std::string filesystem( attachUrl.getScheme() ); + if ( filesystem != "nfs4" && attachUrl.getQueryParam("type") == "nfs4" ) { + filesystem = "nfs4"; + } + + std::string options = attachUrl.getQueryParam("mountoptions"); + if(options.empty()) { + options="ro"; + } + + std::vector optionList; + zypp::str::split( options, std::back_inserter(optionList), "," ); + std::vector::const_iterator it; + bool contains_lock = false, contains_soft = false, + contains_timeo = false, contains_hard = false; + + for( it = optionList.begin(); it != optionList.end(); ++it ) { + if ( *it == "lock" || *it == "nolock" ) contains_lock = true; + else if ( *it == "soft") contains_soft = true; + else if ( *it == "hard") contains_hard = true; + else if ( it->find("timeo") != std::string::npos ) contains_timeo = true; + } + + if ( !(contains_lock && contains_soft) ) { + // Add option "nolock", unless option "lock" or "unlock" is already set. + // This should prevent the mount command hanging when the portmapper isn't + // running. + if ( !contains_lock ) { + optionList.push_back( "nolock" ); + } + // Add options "soft,timeo=NFS_MOUNT_TIMEOUT", unless they are set + // already or "hard" option is explicitly specified. This prevent + // the mount command from hanging when the nfs server is not responding + // and file transactions from an unresponsive to throw an error after + // a short time instead of hanging forever + if ( !(contains_soft || contains_hard) ) { + optionList.push_back( "soft" ); + if ( !contains_timeo ) { + std::ostringstream s; + s << "timeo=" << NFS_MOUNT_TIMEOUT; + optionList.push_back( s.str() ); + } + } + options = zypp::str::join( optionList, "," ); + } + + zypp::Pathname newAp; + zypp::media::Mount mount; + try + { + newAp = createAttachPoint( attachRoot() ); + if ( newAp.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create mount directory." + , false + ); + } + + mount.mount( path, newAp.asString(), filesystem, options ); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + + // we only check if our attachpoint is in mounts and of type nfs/nfs4, everything else is not reliable anyways + constexpr auto checkFsTypePredicate = []( const zypp::media::MountEntry &entry ){ + return ( std::find( NFS_MOUNT_FSTYPES.begin(), NFS_MOUNT_FSTYPES.end(), entry.type ) != NFS_MOUNT_FSTYPES.end() ); + }; + while( !(mountsucceeded=checkAttached( newAp, checkFsTypePredicate )) && --limit) { + MIL << "Mount did not appear yet, sleeping for 1s" << std::endl; + sleep(1); + } + + if( !mountsucceeded) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaMountException( + "Unable to verify that the media was mounted", + path, newAp.asString() + )); + } + + // if we reach this place, mount worked -> YAY, lets see if that is the desired medium! + const auto &isDesired = isDesiredMedium( attachUrl, newAp, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !isDesired ) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaNotDesiredException( attachUrl ) ); + } + + MIL << "New device " << path << " mounted on " << newAp << std::endl; + auto newDev = std::shared_ptr( new zyppng::worker::Device{ + ._name = path, + ._maj_nr = 0, + ._min_nr = 0, + ._mountPoint = newAp, + ._ephemeral = true, // device should be removed after the last attachment was released + ._properties = {} + }); + knownDevices().push_back( newDev ); + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ newDev, "/" } ) ); + return zyppng::worker::AttachResult::success( newDev->_mountPoint ); + + } + catch (const zypp::media::MediaMountException &e ) + { + removeAttachPoint(newAp); + ZYPP_CAUGHT(e); + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , false + , e + ); + } + catch (const zypp::media::MediaException & e) + { + removeAttachPoint(newAp); + ZYPP_CAUGHT(e); + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , false + , e + ); + } + + // We should never reach this place, but if we do fail the attach request + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , zypp::str::Str()<<"Mounting the medium " << attachUrl << " failed for an unknown reason" + , false + ); + + } catch ( const zypp::Exception &e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , false + , e + ); + } catch ( const std::exception &e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , e.what() + , false + ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , "Unknown exception" + , false + ); + } +} diff --git a/tools/zypp-media-nfs/nfsprovider.h b/tools/zypp-media-nfs/nfsprovider.h new file mode 100644 index 0000000..775eb50 --- /dev/null +++ b/tools/zypp-media-nfs/nfsprovider.h @@ -0,0 +1,25 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_NFSPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_NFSPROVIDER_H_INCLUDED + +#include + +class NfsProvider : public zyppng::worker::DeviceDriver +{ + public: + NfsProvider(); + ~NfsProvider(); + + // DeviceDriver interface + zyppng::worker::AttachResult mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) override; + +}; + +#endif diff --git a/tools/zypp-media-smb/CMakeLists.txt b/tools/zypp-media-smb/CMakeLists.txt new file mode 100644 index 0000000..e18e673 --- /dev/null +++ b/tools/zypp-media-smb/CMakeLists.txt @@ -0,0 +1,36 @@ +PROJECT( zypp-media-smb C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + smbprovider.cc + smbprovider.h +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) + +IF ( INSTALL_NG_BINARIES ) + INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}/workers" ) +ENDIF() + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-smb/main.cc b/tools/zypp-media-smb/main.cc new file mode 100644 index 0000000..4b26683 --- /dev/null +++ b/tools/zypp-media-smb/main.cc @@ -0,0 +1,26 @@ +#include "smbprovider.h" + +#include +#include +#include + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto driver = std::make_shared(); + auto worker = std::make_shared( "zypp-media-smb", driver ); + driver->setProvider( worker ); + + auto res = worker->run (STDIN_FILENO, STDOUT_FILENO); + + MIL << "SMB Worker shutting down" << std::endl; + + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-smb/smbprovider.cc b/tools/zypp-media-smb/smbprovider.cc new file mode 100644 index 0000000..c61655f --- /dev/null +++ b/tools/zypp-media-smb/smbprovider.cc @@ -0,0 +1,342 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "smbprovider.h" +#include +#include +#include + +#include + +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "SmbProvider" + +using namespace std::literals::string_view_literals; + + +/*! + * Get the 1st path component (CIFS share name). + */ +inline std::string getShare( zypp::Pathname spath_r ) +{ + if ( spath_r.empty() ) + return std::string(); + + std::string share( spath_r.absolutename().asString() ); + std::string::size_type sep = share.find( "/", 1 ); + if ( sep == std::string::npos ) + share = share.erase( 0, 1 ); // nothing but the share name in spath_r + else + share = share.substr( 1, sep-1 ); + + // deescape %2f in sharename + while ( (sep = share.find( "%2f" )) != std::string::npos ) { + share.replace( sep, 3, "/" ); + } + + return share; +} + +/*! + * Strip off the 1st path component (CIFS share name). + */ +inline zypp::Pathname stripShare( zypp::Pathname spath_r ) +{ + if ( spath_r.empty() ) + return zypp::Pathname(); + + std::string striped( spath_r.absolutename().asString() ); + std::string::size_type sep = striped.find( "/", 1 ); + if ( sep == std::string::npos ) + return "/"; // nothing but the share name in spath_r + + return striped.substr( sep ); +} + + +SmbProvider::SmbProvider( ) + : DeviceDriver( zyppng::worker::WorkerCaps::SimpleMount ) +{ } + +SmbProvider::~SmbProvider() +{ } + +zyppng::worker::AttachResult SmbProvider::mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) +{ + try + { + if ( attachUrl.getHost().empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Host can not be empty" + , false + ); + } + + // set up the verifier + zyppng::MediaDataVerifierRef verifier; + if ( extras.value( zyppng::AttachMsgFields::VerifyType ).valid() ) { + verifier = zyppng::MediaDataVerifier::createVerifier( extras.value(zyppng::AttachMsgFields::VerifyType).asString() ); + if ( !verifier ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Invalid verifier type" + , false + ); + } + + if ( !verifier->load( extras.value(zyppng::AttachMsgFields::VerifyData).asString() ) ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create verifier from file" + , false + ); + } + } + const auto &devs = knownDevices(); + + // build a device name the same way the old media backend did + std::string path = "//"; + path += attachUrl.getHost() + "/" + getShare( attachUrl.getPathName() ); + + // first check if we have that device already + auto i = std::find_if( devs.begin(), devs.end(), [&]( const auto &d ) { return d->_name == path; } ); + if ( i != devs.end() ) { + auto res = isDesiredMedium( attachUrl, (*i)->_mountPoint, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !res ) { + try { + std::rethrow_exception( res.error() ); + } catch( const zypp::Exception& e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , false + , e + ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediumNotDesired + , "Checking the medium failed with an uknown error" + , false + ); + } + } else { + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ *i, "/" } ) ); + return zyppng::worker::AttachResult::success( (*i)->_mountPoint ); + } + } + + // we did not find a existing mount, well lets make a new one + // start with some legacy code: + zypp::media::Mount::Options options( attachUrl.getQueryParam("mountoptions") ); + + int64_t lastTimestamp = -1; + std::string username = attachUrl.getUsername(); + std::string password = attachUrl.getPassword(); + + if ( ! options.has( "rw" ) ) { + options["ro"]; + } + + // look for a workgroup + std::string workgroup = attachUrl.getQueryParam("workgroup"); + if ( workgroup.empty() ) + workgroup = attachUrl.getQueryParam("domain"); + if ( !workgroup.empty() ) + options["domain"] = workgroup; + + // extract 'username', do not overwrite any _url.username + + zypp::media::Mount::Options::iterator toEnv; + toEnv = options.find("username"); + if ( toEnv != options.end() ) { + if ( username.empty() ) + username = toEnv->second; + options.erase( toEnv ); + } + + toEnv = options.find("user"); // actually cifs specific + if ( toEnv != options.end() ) { + if ( username.empty() ) + username = toEnv->second; + options.erase( toEnv ); + } + + // extract 'password', do not overwrite any _url.password + + toEnv = options.find("password"); + if ( toEnv != options.end() ) { + if ( password.empty() ) + password = toEnv->second; + options.erase( toEnv ); + } + + toEnv = options.find("pass"); // actually cifs specific + if ( toEnv != options.end() ) { + if ( password.empty() ) + password = toEnv->second; + options.erase( toEnv ); + } + + bool canContinue = true; + while ( canContinue ) { + + canContinue = false; + + // pass 'username' and 'password' via environment + zypp::media::Mount::Environment environment; + if ( !username.empty() ) + environment["USER"] = username; + if ( !password.empty() ) + environment["PASSWD"] = password; + + // In case we need a tmpfile, credentials will remove + // it in its destructor after the mount call below. + zypp::filesystem::TmpPath credentials; + if ( !username.empty() || !password.empty() ) + { + zypp::filesystem::TmpFile tmp; + std::ofstream outs( tmp.path().asString().c_str() ); + outs << "username=" << username << std::endl; + outs << "password=" << password << std::endl; + outs.close(); + + credentials = tmp; + options["credentials"] = credentials.path().asString(); + + } else { + // Use 'guest' option unless explicitly disabled (bnc #547354) + if ( options.has( "noguest" ) ) + options.erase( "noguest" ); + else + // prevent smbmount from asking for password + // only add this option if 'credentials' is not used (bnc #560496) + options["guest"]; + } + + zypp::Pathname newAp; + zypp::media::Mount mount; + try + { + newAp = createAttachPoint( attachRoot() ); + if ( newAp.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create mount directory." + , false + ); + } + + mount.mount( path, newAp.asString(), "cifs", options.asString(), environment ); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + + while( !(mountsucceeded=checkAttached( newAp, DeviceDriver::fstypePredicate( path, {"smb", "cifs"} ) )) && --limit) { + MIL << "Mount did not appear yet, sleeping for 1s" << std::endl; + sleep(1); + } + + if ( !mountsucceeded ) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaMountException( + "Unable to verify that the media was mounted", + path, newAp.asString() + )); + } + + // if we reach this place, mount worked -> YAY, lets see if that is the desired medium! + const auto &isDesired = isDesiredMedium( attachUrl, newAp, verifier, extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt() ); + if ( !isDesired ) { + try { + mount.umount( newAp.asString() ); + } catch (const zypp::media::MediaException & excpt_r) { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW( zypp::media::MediaNotDesiredException( attachUrl ) ); + } + + MIL << "New device " << path << " mounted on " << newAp << std::endl; + auto newDev = std::shared_ptr( new zyppng::worker::Device{ + ._name = path, + ._maj_nr = 0, + ._min_nr = 0, + ._mountPoint = newAp, + ._ephemeral = true, // device should be removed after the last attachment was released + ._properties = {} + }); + knownDevices().push_back( newDev ); + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ newDev, "/" } ) ); + return zyppng::worker::AttachResult::success( newDev->_mountPoint ); + + } catch (const zypp::media::MediaMountException & e) { + ZYPP_CAUGHT( e ); + + if ( e.mountError() == "Permission denied" ) { + auto parent = parentWorker(); + if ( parent ) { + auto res = parent->requireAuthorization( id, attachUrl, username, lastTimestamp ); + if ( res ) { + canContinue = true; + username = res->username; + password = res->password; + lastTimestamp = res->last_auth_timestamp; + } + } + if ( !canContinue ) { + removeAttachPoint(newAp); + return zyppng::worker::AttachResult::error( zyppng::ProvideMessage::Code::Forbidden, "No authentication data", false ); + } + } else { + removeAttachPoint(newAp); + return zyppng::worker::AttachResult::error( zyppng::ProvideMessage::Code::MountFailed, false, e ); + } + } catch (const zypp::media::MediaException & e) { + removeAttachPoint(newAp); + ZYPP_CAUGHT(e); + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , false + , e ); + } + } + + // We should never reach this place, but if we do fail the attach request + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , zypp::str::Str()<<"Mounting the medium " << attachUrl << " failed for an unknown reason" + , false + ); + + } catch ( const zypp::Exception &e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , false + , e );; + } catch ( const std::exception &e ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , e.what() + , false + ); + } catch ( ... ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::BadRequest + , "Unknown exception" + , false + ); + } +} diff --git a/tools/zypp-media-smb/smbprovider.h b/tools/zypp-media-smb/smbprovider.h new file mode 100644 index 0000000..1d83990 --- /dev/null +++ b/tools/zypp-media-smb/smbprovider.h @@ -0,0 +1,24 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_SMBPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_SMBPROVIDER_H_INCLUDED + +#include + +class SmbProvider : public zyppng::worker::DeviceDriver +{ + public: + SmbProvider(); + ~SmbProvider(); + + // DeviceDriver interface + zyppng::worker::AttachResult mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) override; +}; + +#endif diff --git a/tools/zypp-media-tvm/CMakeLists.txt b/tools/zypp-media-tvm/CMakeLists.txt new file mode 100644 index 0000000..ab6c756 --- /dev/null +++ b/tools/zypp-media-tvm/CMakeLists.txt @@ -0,0 +1,34 @@ +PROJECT( zypp-media-tvm C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +SET( SOURCES + main.cc + testvmprovider.cc + testvmprovider.h +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} zypp-media ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) +target_link_libraries( ${PROJECT_NAME} tvm-protocol-obj ) +target_link_libraries( ${PROJECT_NAME} ${YAML_CPP_LIBRARIES}) + +set_target_properties( ${PROJECT_NAME} + PROPERTIES + ARCHIVE_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + LIBRARY_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" + RUNTIME_OUTPUT_DIRECTORY "${LIBZYPP_BINARY_DIR}/tools/workers" +) diff --git a/tools/zypp-media-tvm/main.cc b/tools/zypp-media-tvm/main.cc new file mode 100644 index 0000000..c1ce2c5 --- /dev/null +++ b/tools/zypp-media-tvm/main.cc @@ -0,0 +1,23 @@ +#include "testvmprovider.h" + +#include +#include +#include + +int main( int , char *[] ) +{ + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + auto driver = std::make_shared(); + auto worker = std::make_shared( "zypp-media-tvm", driver ); + driver->setProvider(worker); + + auto res = worker->run (STDIN_FILENO, STDOUT_FILENO); + if ( res ) + return 0; + + //@TODO print error + return 1; +} diff --git a/tools/zypp-media-tvm/testvmprovider.cc b/tools/zypp-media-tvm/testvmprovider.cc new file mode 100644 index 0000000..a800bc1 --- /dev/null +++ b/tools/zypp-media-tvm/testvmprovider.cc @@ -0,0 +1,344 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "testvmprovider.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "TestVMProvider" + +#include +#include + +extern "C" +{ +#include +#include +#if HAVE_UDEV +#include +#endif +} + +using namespace std::literals; + +constexpr std::string_view CONTENTDIR_PROP = "contentDir"; + +TestVMProvider::TestVMProvider( ) : zyppng::worker::DeviceDriver( zyppng::worker::WorkerCaps::VolatileMount ) +{ } + +TestVMProvider::~TestVMProvider() +{ } + +zyppng::expected TestVMProvider::initialize(const zyppng::worker::Configuration &conf) +{ + if ( const auto &i = conf.find( std::string(zyppng::PROVIDER_ROOT) ); i != conf.end() ) { + const auto &val = i->second; + MIL << "Got provider root from controller: " << val << std::endl; + _provRoot = val; + } else { + return zyppng::expected::error(ZYPP_EXCPT_PTR( zypp::Exception("Provider root required to work.") )); + } + + return DeviceDriver::initialize( conf ); +} + +zyppng::worker::AttachResult TestVMProvider::mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) +{ + std::vector devs; + if ( extras.contains( zyppng::AttachMsgFields::Device ) ) { + for ( const auto &d : extras.values( zyppng::AttachMsgFields::Device ) ) { + if ( d.isString() ) { + MIL << "Got device from user we are allowed to use: " << d.asString() << std::endl; + devs.push_back(d.asString()); + } + } + } + + auto &sysDevs = knownDevices(); + std::vector> possibleDevs; + if ( devs.size () ) { + for ( const auto &d : devs ) { + std::shared_ptr device; + auto i = std::find_if( sysDevs.begin(), sysDevs.end(), [&]( const auto &sysDev ){ return ( sysDev->_name == d ); } ); + if ( i == sysDevs.end() ) { + ERR << "Device " << d << " from Attach request is not known ignoring!" << std::endl; + continue; + } else { + device = *i; + } + + if ( device ) + possibleDevs.push_back(device); + } + } else { + possibleDevs = sysDevs; + } + + // if we have no devices at this point controller gets a error + if ( possibleDevs.empty () ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "No useable device found" + , false + ); + } + + const auto attachRoot = zypp::Pathname( attachUrl.getPathName() ); + const auto attachMediaNr = extras.value( zyppng::AttachMsgFields::MediaNr, 1 ).asInt(); + + // set up the verifier + zyppng::MediaDataVerifierRef verifier; + if ( extras.contains( zyppng::AttachMsgFields::VerifyType ) ) { + verifier = zyppng::MediaDataVerifier::createVerifier( extras.value(zyppng::AttachMsgFields::VerifyType).asString() ); + if ( !verifier ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Invalid verifier type" + , false + ); + } + + if ( !verifier->load( extras.value(zyppng::AttachMsgFields::VerifyData).asString() ) ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create verifier from file" + , false + ); + } + } + + //first check if any of the mounted devices are what we want + for( const auto &dev : possibleDevs ) { + if ( dev->_mountPoint.empty() ) + continue; + + MIL << "Found mounted device: " << dev->_name << " on mountpoint: " << dev->_mountPoint << std::endl; + + auto res = isDesiredMedium( attachUrl, dev->_mountPoint / attachRoot, verifier, attachMediaNr ); + if ( !res ) + continue; + + MIL << "Found requested medium in dev " << dev->_name << std::endl; + + // we found the device we want! + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ dev, attachRoot } ) ); + return zyppng::worker::AttachResult::success( dev->_mountPoint / attachRoot ); + } + + while ( true ) { + + // pick up changes from the test + detectDevices(); + + // remember how many devices we were able to test + uint devicesTested = 0; + + // none of the already mounted devices matched, lets try what we have left + for( const auto &dev : possibleDevs ) { + if ( !dev->_mountPoint.empty() ) + continue; + + MIL << "Trying to mount dev " << dev->_name << std::endl; + + devicesTested++; + + bool mountsucceeded = false; + + // we simply create a symbolic link in the attach dir to simulate mounting + zypp::Pathname newAp; + try { + newAp = createAttachPoint( this->attachRoot() ); + if ( newAp.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MountFailed + , "Failed to create mount directory." + , false + ); + } + + newAp = newAp/"mount"; + + // simulate failed mount + const auto &contDir = std::any_cast(dev->_properties[std::string(CONTENTDIR_PROP)]); + if ( contDir.empty() ) { + ZYPP_THROW( zypp::media::MediaMountException( + "Failed to mount device", + dev->_name, newAp.asString() + )); + } + + const auto res = zypp::filesystem::symlink( contDir, newAp ); + mountsucceeded = ( res == 0 ); + + if( !mountsucceeded) { + ZYPP_THROW( zypp::media::MediaMountException( + "Failed to mount device", + dev->_name, newAp.asString() + )); + } else { + MIL << "Device mounted on " << newAp << std::endl; + dev->_mountPoint = newAp; + } + } catch (const zypp::media::MediaException & excpt_r) { + removeAttachPoint(newAp.dirname()); + ZYPP_CAUGHT(excpt_r); + } + + if ( mountsucceeded ) { + // lets check if we have the correct medium + auto res = isDesiredMedium( attachUrl, dev->_mountPoint / attachRoot, verifier, attachMediaNr ); + if ( !res ) { + unmountDevice( *dev ); + continue; + } + + MIL << "Found requested medium in dev " << dev->_name << std::endl; + attachedMedia().insert( std::make_pair( attachId, zyppng::worker::AttachedMedia{ dev, attachRoot } ) ); + return zyppng::worker::AttachResult::success( dev->_mountPoint / attachRoot ); + } + } // for each device + + // we did go through all devices, but didn't find any. + if ( devicesTested == 0 ) { + // no devices are free + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::Jammed + , "No free ressources available" + , false + ); + } else { + + // k, we need to ask the user to give us the medium we need + // first find the devices that are free + std::vector freeDevs; + + for( const auto &dev : possibleDevs ) { + if ( !dev->_mountPoint.empty() ) + continue; + + MIL << "Adding " << dev->_name << " to list of free devs" << std::endl; + freeDevs.push_back( dev->_name ); + } + + // if there are no devices free, we are jammed + if ( freeDevs.empty() ) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::Jammed + , "No free ressources available" + , false + ); + } + + auto changeRes = zyppng::worker::ProvideWorker::ABORT; + auto parent = parentWorker(); + if ( parent ) + changeRes = parent->requestMediaChange ( id, label, attachMediaNr, freeDevs ); + if ( changeRes != zyppng::worker::ProvideWorker::SUCCESS ) { + if ( changeRes == zyppng::worker::ProvideWorker::SKIP) { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediaChangeSkip + , "User asked to skip the media change." + , false + ); + } else { + return zyppng::worker::AttachResult::error( + zyppng::ProvideMessage::Code::MediaChangeAbort + , "User asked to abort the media change." + , false + ); + } + } + } + } +} + +void TestVMProvider::unmountDevice( zyppng::worker::Device &dev ) +{ + if ( dev._mountPoint.empty () ) + return; + try { + zypp::filesystem::unlink( dev._mountPoint ); + removeAttachPoint( dev._mountPoint.dirname() ); + } catch (const zypp::media::MediaException & excpt_r) { + ERR << "Failed to unmount device: " << dev._name << std::endl; + ZYPP_CAUGHT(excpt_r); + } + dev._mountPoint = zypp::Pathname(); +} + +void TestVMProvider::detectDevices( ) +{ + + YAML::Node control; + try { + const auto &fname = _provRoot/"tvm.conf"; + control = YAML::LoadFile( fname.asString() ); + + const auto &set = control.as(); + if ( set.devices.empty () ) { + MIL << "No devices configured!" << std::endl; + return; + } + + auto &sysDevs = knownDevices(); + if ( sysDevs.size() ) { + for ( const auto &dev : set.devices ) { + auto iDev = std::find_if( sysDevs.begin(), sysDevs.end(), [&]( const auto &d ){ + return d->_name == dev.name; + }); + if ( iDev == sysDevs.end() ) { + MIL << "Previously unknown device detected" << std::endl; + auto d = std::make_shared( zyppng::worker::Device{ + ._name = dev.name + }); + if ( dev.insertedPath.size() ) { + d->_properties[std::string(CONTENTDIR_PROP)] = zypp::Pathname(dev.insertedPath); + } + sysDevs.push_back(d); + continue; + } + + // mounted devices are never updated + if ( !(*iDev)->_mountPoint.empty() ) { + continue; + } + + (*iDev)->_properties[std::string(CONTENTDIR_PROP)] = zypp::Pathname(dev.insertedPath); + } + } else { + for ( const auto &dev : set.devices ) { + MIL << "Found device: " << dev.name << std::endl; + auto d = std::make_shared( zyppng::worker::Device{ + ._name = dev.name + }); + if ( dev.insertedPath.size() ) { + d->_properties[std::string(CONTENTDIR_PROP)] = zypp::Pathname(dev.insertedPath); + } + sysDevs.push_back(d); + } + } + } catch ( YAML::Exception &e ) { + WAR << "YAML exception: " << e.what() << std::endl; + return; + } catch ( const std::exception &e ) { + WAR << "Error when parsing the control file: " << e.what() << std::endl; + return; + } catch ( ... ) { + WAR << "Unknown error when parsing the control file" << std::endl; + return; + } +} diff --git a/tools/zypp-media-tvm/testvmprovider.h b/tools/zypp-media-tvm/testvmprovider.h new file mode 100644 index 0000000..07bed4b --- /dev/null +++ b/tools/zypp-media-tvm/testvmprovider.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_TOOLS_DISCPROVIDER_H_INCLUDED +#define ZYPP_NG_TOOLS_DISCPROVIDER_H_INCLUDED + +#include +#include +#include +#include + +/*! + * \file Contains a testprovider to simulate volatile mounting devices. + * This is only used in the zypp testsuite. + */ + +class TestVMProvider : public zyppng::worker::DeviceDriver +{ +public: + + TestVMProvider(); + ~TestVMProvider(); + + // DeviceDriver interface + zyppng::expected initialize(const zyppng::worker::Configuration &conf) override; + zyppng::worker::AttachResult mountDevice ( const uint32_t id, const zypp::Url &attachUrl, const std::string &attachId, const std::string &label, const zyppng::HeaderValueMap &extras ) override; + void detectDevices(); + +protected: + void unmountDevice ( zyppng::worker::Device &dev ) override; + +private: + zypp::Pathname _provRoot; +}; + +#endif diff --git a/tools/zypp-pubkey.cc b/tools/zypp-pubkey.cc new file mode 100644 index 0000000..913359c --- /dev/null +++ b/tools/zypp-pubkey.cc @@ -0,0 +1,146 @@ +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST +#define message cout +using std::flush; + +#include +namespace opt = boost::program_options; + +#include +#include + +static std::string appname( "unknown" ); + +int errexit( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + { + cerr << endl << msg_r << endl << endl; + } + return exit_r; +} + +bool byTTL( const PublicKey & lhs, const PublicKey & rhs ) +{ + int cmp = lhs.gpgPubkeyVersion().compare( rhs.gpgPubkeyVersion() ); + if ( cmp ) return cmp < 0; + return lhs.gpgPubkeyRelease() > rhs.gpgPubkeyRelease(); // intentionally reverse cdate +} + +std::ostream & dumpPubkeyOn( std::ostream & str, const PublicKey & key_r ) +{ + std::vector art( key_r.asciiArt().asLines( " ", PublicKey::AsciiArt::USE_COLOR ) ); + + std::vector info; + str::split( (str::Str() << dump(key_r)).str(), std::back_inserter( info ), "\n" ); + + for ( unsigned i = 1; i < info.size(); ++i ) + art[i] += info[i]; + + str << info[0] << endl; + for ( const auto & line : art ) + str << line << endl; + return str << endl; +} + +/****************************************************************** +** +** FUNCTION NAME : main +** FUNCTION TYPE : int +*/ +int main( int argc, char * argv[] ) +{ + appname = Pathname::basename( argv[0] ); + /////////////////////////////////////////////////////////////////// + + opt::options_description options( "Options" ); + options.add_options() + ( "key-file", opt::value >(), + "ASCII ascii armored public key file") + ( "root", opt::value()->default_value( "/" ), + "Use the rmp database from system rooted at ARG") + ( "help,?", "Produce this help message") + ; + + opt::positional_options_description positional; + positional.add( "key-file", -1 ); + + opt::variables_map vm; + opt::store( opt::command_line_parser( argc, argv ).options( options ).positional( positional ).run(), vm ); + opt::notify( vm ); + + if ( vm.count( "help" ) ) + { + cerr << "Usage: " << appname << " [OPTIONS] [key-files...]" << endl; + cerr << "If no key files are given, list info about all gpg-pubkeys in the rpm database." << endl; + cerr << "Otherwise print info about each key and wheter it is present in the rpm database. " << endl; + cerr << options << endl; + return 1; + } + /////////////////////////////////////////////////////////////////// + + if ( ! PathInfo( vm["root"].as() ).isDir() ) + return errexit("--root requires a directory"); + + target::rpm::RpmDb rpmdb; + rpmdb.initDatabase( vm["root"].as() ); + std::list rpmpubkeys( rpmdb.pubkeys() ); + rpmpubkeys.sort( byTTL ); + + + + if ( ! vm.count( "key-file" ) ) + { + std::string last; + for_each_( it, rpmpubkeys ) + { + if ( last == it->gpgPubkeyVersion() ) + cout << *it << endl; + else + { + dumpPubkeyOn( cout, *it ); + last = it->gpgPubkeyVersion(); + } + } + return 0; + } + + /////////////////////////////////////////////////////////////////// + + for_each_( it, vm["key-file"].as< std::vector >() ) + { + cout << "=== " << PathInfo(*it) << endl; + PublicKey pubkey( *it ); + dumpPubkeyOn( cout, pubkey ); + + std::string pubkeyV( pubkey.gpgPubkeyVersion() ); + std::string pubkeyR( pubkey.gpgPubkeyRelease() ); + unsigned count = 0; + for_each_( rpmpub, rpmpubkeys ) + { + if ( rpmpub->gpgPubkeyVersion() == pubkeyV ) + { + int cmp = rpmpub->gpgPubkeyRelease().compare( pubkeyR ); + if ( cmp < 0 ) + cout << "<<< "; + else if ( cmp > 0 ) + cout << ">>> "; + else + { + ++count; + cout << "*** "; + } + cout << "gpg-pubkey-" << rpmpub->gpgPubkeyVersion() << "-" << rpmpub->gpgPubkeyRelease() << " " << rpmpub->daysToLive() << endl; + } + } + if ( ! count ) + { + cout << "*** Not in rpm database." << endl; + } + cout << endl; + } + + /////////////////////////////////////////////////////////////////// + return 0; +} diff --git a/tools/zypp-rpm/BinHeader.cc b/tools/zypp-rpm/BinHeader.cc new file mode 100644 index 0000000..b2b259c --- /dev/null +++ b/tools/zypp-rpm/BinHeader.cc @@ -0,0 +1,432 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/BinHeader.cc + * +*/ + +extern "C" +{ +#ifdef _RPM_5 +#undef RPM_NULL_TYPE +#define RPM_NULL_TYPE rpmTagType(0) +typedef rpmuint32_t rpm_count_t; +#endif +} + +#include + +#include +#include +#include +#include + +#include "BinHeader.h" + +using std::endl; +using namespace zypp; + +/** Helper for header data retieval. + * With \c _RPM_4 use \c ::headerGet; with \c _RPM_5 + * use the meanwhile deprecated \c ::headerGetEntry. + * \ingroup g_RAII + */ +struct HeaderEntryGetter : private base::NonCopyable +{ +public: + HeaderEntryGetter( const Header & h_r, rpmTag & tag_r ); + ~HeaderEntryGetter(); + rpmTagType type(); + rpm_count_t cnt(); + void * val(); +private: +#ifndef _RPM_5 + ::rpmtd _rpmtd; +#else + rpmTagType _type; + rpm_count_t _cnt; + void * _val; +#endif //_RPM_5 +}; + +#ifndef _RPM_5 +inline HeaderEntryGetter::HeaderEntryGetter( const Header & h_r, rpmTag & tag_r ) + : _rpmtd( ::rpmtdNew() ) +{ ::headerGet( h_r, tag_r, _rpmtd, HEADERGET_EXT ); } +inline HeaderEntryGetter::~HeaderEntryGetter() +{ ::rpmtdFreeData( _rpmtd ); ::rpmtdFree( _rpmtd ); } +inline rpmTagType HeaderEntryGetter::type() { return rpmtdType( _rpmtd ); } +inline rpm_count_t HeaderEntryGetter::cnt() { return _rpmtd->count; } +inline void * HeaderEntryGetter::val() { return _rpmtd->data; } +#else +inline HeaderEntryGetter::HeaderEntryGetter( const Header & h_r, rpmTag & tag_r ) + : _type( RPM_NULL_TYPE ) + , _cnt( 0 ) + , _val( 0 ) +{ ::headerGetEntry( h_r, tag_r, hTYP_t(&_type), &_val, &_cnt ); } +inline HeaderEntryGetter::~HeaderEntryGetter() +{ if ( _val && _type == RPM_STRING_ARRAY_TYPE ) free( _val ); } +inline rpmTagType HeaderEntryGetter::type() { return _type; } +inline rpm_count_t HeaderEntryGetter::cnt() { return _cnt; } +inline void * HeaderEntryGetter::val() { return _val; } +#endif //_RPM_5 + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::intList +// +/////////////////////////////////////////////////////////////////// + +unsigned BinHeader::intList::set( void * val_r, unsigned cnt_r, rpmTagType type_r ) +{ + _type = type_r; // remember the type! + if ( val_r ) + switch ( _type ) + { +#if RPM_CHAR_TYPE != RPM_INT8_TYPE + case RPM_CHAR_TYPE: + std::vector( (char*)val_r, ((char*)val_r)+cnt_r ).swap( _data ); + break; +#endif + case RPM_INT8_TYPE: + std::vector( (int8_t*)val_r, ((int8_t*)val_r)+cnt_r ).swap( _data ); + break; + case RPM_INT16_TYPE: + std::vector( (int16_t*)val_r, ((int16_t*)val_r)+cnt_r ).swap( _data ); + break; + case RPM_INT32_TYPE: + std::vector( (int32_t*)val_r, ((int32_t*)val_r)+cnt_r ).swap( _data ); + break; +#ifndef _RPM_5 + case RPM_INT64_TYPE: + std::vector( (int64_t*)val_r, ((int64_t*)val_r)+cnt_r ).swap( _data ); + break; +#endif + default: + std::vector( cnt_r, 0L ).swap( _data ); + break; + } + else + _data.clear(); + return _data.size(); +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::stringList +// +/////////////////////////////////////////////////////////////////// + +unsigned BinHeader::stringList::set( char ** val_r, unsigned cnt_r ) +{ + if ( val_r ) + std::vector( val_r, val_r+cnt_r ).swap( _data ); + else + _data.clear(); + return _data.size(); +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader +// +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::BinHeader +// METHOD TYPE : Constructor +// +BinHeader::BinHeader( Header h_r ) + : _h( h_r ) +{ + if ( _h ) + { + headerLink( _h ); + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::BinHeader +// METHOD TYPE : Constructor +// +BinHeader::BinHeader( BinHeader::Ptr & rhs ) +{ + INT << "INJECT from " << rhs; + if ( ! (rhs && rhs->_h) ) + { + _h = 0; + } + else + { + _h = rhs->_h; // ::headerLink already done in rhs + rhs->_h = 0; + } + INT << ": " << *this << " (" << rhs << ")" << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::~BinHeader +// METHOD TYPE : Destructor +// +BinHeader::~BinHeader() +{ + if ( _h ) + { + headerFree( _h ); + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::assertHeader +// METHOD TYPE : void +// +bool BinHeader::assertHeader() +{ + if ( !_h ) + { + _h = ::headerNew(); + if ( !_h ) + { + INT << "OOPS: NULL HEADER created!" << endl; + return false; + } + } + return true; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::has_tag +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool BinHeader::has_tag( tag tag_r ) const +{ + return( !empty() && ::headerIsEntry( _h, tag_r ) ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::int_list +// METHOD TYPE : unsigned +// +// DESCRIPTION : +// +unsigned BinHeader::int_list( tag tag_r, intList & lst_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return lst_r.set( 0, 0, headerget.type() ); +#if RPM_CHAR_TYPE != RPM_INT8_TYPE + case RPM_CHAR_TYPE: +#endif + case RPM_INT8_TYPE: + case RPM_INT16_TYPE: + case RPM_INT32_TYPE: +#ifndef _RPM_5 + case RPM_INT64_TYPE: +#endif + return lst_r.set( headerget.val(), headerget.cnt(), headerget.type() ); + + default: + INT << "RPM_TAG MISSMATCH: RPM_INTxx_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return lst_r.set( 0, 0, RPM_NULL_TYPE ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::string_list +// METHOD TYPE : unsigned +// +// DESCRIPTION : +// +unsigned BinHeader::string_list( tag tag_r, stringList & lst_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return lst_r.set( 0, 0 ); + case RPM_STRING_ARRAY_TYPE: + return lst_r.set( (char**)headerget.val(), headerget.cnt() ); + + default: + INT << "RPM_TAG MISSMATCH: RPM_STRING_ARRAY_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return lst_r.set( 0, 0 ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::int_val +// METHOD TYPE : int +// +// DESCRIPTION : +// +int BinHeader::int_val( tag tag_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return 0; +#if RPM_CHAR_TYPE != RPM_INT8_TYPE + case RPM_CHAR_TYPE: + return *((char*)headerget.val()); +#endif + case RPM_INT8_TYPE: + return *((int8_t*)headerget.val()); + case RPM_INT16_TYPE: + return *((int16_t*)headerget.val()); + case RPM_INT32_TYPE: + return *((int32_t*)headerget.val()); +#ifndef _RPM_5 + case RPM_INT64_TYPE: + return *((int64_t*)headerget.val()); +#endif + + default: + INT << "RPM_TAG MISSMATCH: RPM_INTxx_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return 0; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::string_val +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string BinHeader::string_val( tag tag_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return ""; + case RPM_STRING_TYPE: + return (char*)headerget.val(); + + default: + INT << "RPM_TAG MISSMATCH: RPM_STRING_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return ""; +} + +std::string BinHeader::nvra() const +{ + if ( !empty() ) { + std::string nvra = string_val( RPMTAG_NVRA ); + if ( nvra.empty() ) { + //name-version-release-arch + nvra = string_val( RPMTAG_NAME ) + "-" + string_val( RPMTAG_VERSION ) + "-" + string_val( RPMTAG_RELEASE) + "-" + string_val( RPMTAG_ARCH ) ; + } + return nvra; + } + return ""; +} + + + +std::string BinHeader::format(const char *fmt) const +{ + zypp::AutoDispose form(headerFormat(_h, fmt, NULL), free); + if ( !form ) + return std::string(); + + return std::string(form); +} + +Header BinHeader::get() const +{ + return _h; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::stringList_val +// METHOD TYPE : std::list +// +// DESCRIPTION : +// +std::list BinHeader::stringList_val( tag tag_r ) const +{ + std::list ret; + + if ( !empty() ) + { + stringList lines; + unsigned count = string_list( tag_r, lines ); + for ( unsigned i = 0; i < count; ++i ) + { + ret.push_back( lines[i] ); + } + } + return ret; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::dumpOn +// METHOD TYPE : ostream & +// +// DESCRIPTION : +// +std::ostream & BinHeader::dumpOn( std::ostream & str ) const +{ + ReferenceCounted::dumpOn( str ); + return str << '{' << (void*)_h << '}'; +} diff --git a/tools/zypp-rpm/BinHeader.h b/tools/zypp-rpm/BinHeader.h new file mode 100644 index 0000000..2148b97 --- /dev/null +++ b/tools/zypp-rpm/BinHeader.h @@ -0,0 +1,156 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/BinHeader.h + * +*/ +#ifndef ZYPP_TARGET_RPM_BINHEADER_H +#define ZYPP_TARGET_RPM_BINHEADER_H + +extern "C" +{ +#include +} + +#include +#include +#include +#include + +#include +#include +#include +#include + +/** + * + **/ +class BinHeader : public zypp::base::ReferenceCounted, private zypp::base::NonCopyable +{ + +public: + + using Ptr = zypp::intrusive_ptr; + + using constPtr = zypp::intrusive_ptr; + + using tag = rpmTag; + + class intList; + + class stringList; + +private: + + Header _h; + + bool assertHeader(); + +public: + + BinHeader( Header h_r = 0 ); + + /** + * Dangerous!<\B> This one takes the header out of rhs + * and leaves rhs empty. + **/ + BinHeader( BinHeader::Ptr & rhs ); + + ~BinHeader() override; + +public: + + bool empty() const + { + return( _h == NULL ); + } + + bool has_tag( tag tag_r ) const; + + unsigned int_list( tag tag_r, intList & lst_r ) const; + + unsigned string_list( tag tag_r, stringList & lst_r ) const; + + int int_val( tag tag_r ) const; + + std::string string_val( tag tag_r ) const; + std::string format ( const char * fmt) const; + + Header get() const; + + std::string nvra() const; + +public: + + std::list stringList_val( tag tag_r ) const; + +public: + + std::ostream & dumpOn( std::ostream & str ) const override; +}; + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::intList +/** + * + **/ +class BinHeader::intList : private zypp::base::NonCopyable +{ + public: + intList() {} + + bool empty() const + { return _data.empty(); } + + unsigned size() const + { return _data.size(); } + + long operator[]( const unsigned idx_r ) const + { return idx_r < _data.size() ? _data[idx_r] : 0; } + + private: + friend class BinHeader; + unsigned set( void * val_r, unsigned cnt_r, rpmTagType type_r ); + + private: + std::vector _data; + rpmTagType _type{ RPM_NULL_TYPE }; +}; + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::stringList +/** + * + **/ +class BinHeader::stringList : private zypp::base::NonCopyable +{ + public: + bool empty() const + { return _data.empty(); } + + unsigned size() const + { return _data.size(); } + + std::string operator[]( const unsigned idx_r ) const + { return idx_r < _data.size() ? _data[idx_r] : std::string(); } + + private: + friend class BinHeader; + unsigned set( char ** val_r, unsigned cnt_r ); + + private: + std::vector _data; +}; + +#endif // ZYPP_TARGET_RPM_BINHEADER_H diff --git a/tools/zypp-rpm/CMakeLists.txt b/tools/zypp-rpm/CMakeLists.txt new file mode 100644 index 0000000..ae824ab --- /dev/null +++ b/tools/zypp-rpm/CMakeLists.txt @@ -0,0 +1,50 @@ +PROJECT( zypp-rpm C CXX ) + +set (CMAKE_CXX_STANDARD 17) +SET (CMAKE_CXX_EXTENSIONS OFF) + +FIND_PACKAGE(Rpm REQUIRED) +IF ( NOT RPM_FOUND) + MESSAGE( FATAL_ERROR " rpm-devel not found" ) +ELSE ( NOT RPM_FOUND) + + INCLUDE_DIRECTORIES(${RPM_INCLUDE_DIR}) + # fix includes not relative to rpm + INCLUDE_DIRECTORIES(${RPM_INCLUDE_DIR}/rpm) + + # rpm verify function and callback states were introduced in rpm-4.15 + if( RPM_LIB_VER VERSION_GREATER_EQUAL "4.15.0" AND RPM_LIB_VER VERSION_LESS "5.0.0") + ADD_DEFINITIONS( -DHAVE_RPM_VERIFY_TRANSACTION_STEP ) + endif() + + if( RPM_LIB_VER VERSION_GREATER_EQUAL "5.0.0" ) + MESSAGE( STATUS "rpm found: enable rpm-4 compat interface." ) + ADD_DEFINITIONS(-D_RPM_5) + endif () +ENDIF( NOT RPM_FOUND) + +SET( SOURCES + errorcodes.h + main.cc + BinHeader.h + BinHeader.cc +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +add_executable( ${PROJECT_NAME} ${SOURCES} ) +target_link_libraries( ${PROJECT_NAME} zypp_exe_compiler_flags ) +target_link_libraries( ${PROJECT_NAME} commit-proto-obj ) +target_link_libraries( ${PROJECT_NAME} zypp-core ) +target_link_libraries( ${PROJECT_NAME} util ) +target_link_libraries( ${PROJECT_NAME} ${RPM_LIBRARY} ${RPMIO_LIBRARY} ) + +INSTALL( TARGETS ${PROJECT_NAME} DESTINATION "${ZYPP_LIBEXEC_INSTALL_DIR}" ) diff --git a/tools/zypp-rpm/errorcodes.h b/tools/zypp-rpm/errorcodes.h new file mode 100644 index 0000000..2346078 --- /dev/null +++ b/tools/zypp-rpm/errorcodes.h @@ -0,0 +1,35 @@ +#ifndef ZYPP_RPM_ERRORCODES_H +#define ZYPP_RPM_ERRORCODES_H + +#include + +// This is supposed to contain header only code, add nothing that would require symbols to be linked +namespace zypprpm { + enum ErrCodes { + NoError = 0, + FailedToOpenDb, + WrongHeaderSize, + WrongMessageFormat, + RpmInitFailed, + FailedToReadPackage, + FailedToAddStepToTransaction, + RpmFinishedWithTransactionError, // we got explicit error problems from rpm + RpmFinishedWithError, // the transaction started but could not be finished) + RpmOrderFailed, // running rpmtsorder failed + FailedToCreateLock, // we were unable to create a lockfile + OtherError = 255 + }; +} + +// we will send a end of message tag through the script FD whenever we receive a "STOP" message +// this message will consist of this tag and a \n +constexpr char endOfScriptTagData[] = { + (char)0xde, + (char)0xad, + (char)0xbe, + (char)0xef, + '\n' +}; +constexpr std::string_view endOfScriptTag ( endOfScriptTagData, 5 ); + +#endif // ZYPP_RPM_ERRORCODES_H diff --git a/tools/zypp-rpm/main.cc b/tools/zypp-rpm/main.cc new file mode 100644 index 0000000..6ee8d99 --- /dev/null +++ b/tools/zypp-rpm/main.cc @@ -0,0 +1,1033 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +// we do not link against libzypp, but these are pure header only files, if that changes +// a copy should be created directly in the zypp-rpm project +#include +#include + +extern "C" +{ +#include +#include +} + +#include "BinHeader.h" +#include "errorcodes.h" + +#include +#include +#include +#include + +// Messages to the zypp log sent on stdout/stderr +#define ZDBG std::cout +#define ZERR std::cerr + +namespace env +{ + /// Allows to increase rpm loglevel + inline bool ZYPP_RPM_DEBUG() + { + static bool val = [](){ + const char * env = getenv("ZYPP_RPM_DEBUG"); + return( env && zypp::str::strToBool( env, true ) ); + }(); + return val; + } +} // namespace env + +namespace dbg +{ + struct _dumpTransactionStep + { + _dumpTransactionStep( const zypp::proto::target::TransactionStep *const step_r ) + : _step { step_r } + {} + std::ostream & dumpOn( std::ostream & str ) const + { + str << "TStep("; + if ( _step ) { + if ( std::holds_alternative(*_step) ) { + const auto &step = std::get(*_step); + str << step.stepId << "|" << step.pathname; + } else if ( std::holds_alternative(*_step) ) { + const auto &step = std::get(*_step); + str << step.stepId << "|" << step.name << "-" << step.version << "-" << step.release << "." << step.arch; + } else { + str << "OOPS"; + } + } else { + str << "NULL"; + } + return str << ")"; + } + const zypp::proto::target::TransactionStep *const _step; + }; + inline std::ostream & operator<<( std::ostream & str, const _dumpTransactionStep & obj ) + { return obj.dumpOn( str ); } + inline _dumpTransactionStep dump( const zypp::proto::target::TransactionStep *const obj ) + { return _dumpTransactionStep( obj ); } + inline _dumpTransactionStep dump( const zypp::proto::target::TransactionStep & obj ) + { return _dumpTransactionStep( &obj ); } + + struct _dumpRpmCallbackType + { + _dumpRpmCallbackType( rpmCallbackType_e flag_r ) + : _flag { flag_r } + {} + std::ostream & dumpOn( std::ostream & str ) const + { + str << "RPMCALLBACK"; + if ( _flag ) { +#define OUTS(E) if ( _flag & RPMCALLBACK_##E ) str << "_" << #E + OUTS( INST_PROGRESS ); + OUTS( INST_START ); + OUTS( INST_OPEN_FILE ); + OUTS( INST_CLOSE_FILE ); + OUTS( TRANS_PROGRESS ); + OUTS( TRANS_START ); + OUTS( TRANS_STOP ); + OUTS( UNINST_PROGRESS ); + OUTS( UNINST_START ); + OUTS( UNINST_STOP ); + OUTS( UNPACK_ERROR ); + OUTS( CPIO_ERROR ); + OUTS( SCRIPT_ERROR ); + OUTS( SCRIPT_START ); + OUTS( SCRIPT_STOP ); + OUTS( INST_STOP ); + OUTS( ELEM_PROGRESS ); +#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP + OUTS( VERIFY_PROGRESS ); + OUTS( VERIFY_START ); + OUTS( VERIFY_STOP ); +#endif +#undef OUTS + } else { + str << "_UNKNOWN"; + } + return str; + } + rpmCallbackType_e _flag; + }; + inline std::ostream & operator<<( std::ostream & str, const _dumpRpmCallbackType & obj ) + { return obj.dumpOn( str ); } + inline _dumpRpmCallbackType dump( rpmCallbackType obj ) + { return _dumpRpmCallbackType( obj ); } +} + +// this is the order we expect the FDs we need to communicate to be set up +// by the parent. This is not pretty but it works and is less effort than +// setting up a Unix Domain Socket and sending FDs over that. +// Usually relying on conventions is not exactly a good idea but in this case we make an exception ;) +enum class ExpectedFds : int { + MessageFd = STDERR_FILENO+1, + ScriptFd = STDERR_FILENO+2 +}; + +using zypp::target::rpm::RpmInstFlag; +using zypp::target::rpm::RpmInstFlags; +using namespace zypprpm; + +void *rpmLibCallback( const void *h, const rpmCallbackType what, const rpm_loff_t amount, const rpm_loff_t total, fnpyKey key, rpmCallbackData data ); +int rpmLogCallback ( rpmlogRec rec, rpmlogCallbackData data ); + +template +void rpmpsPrintToStream ( Stream &str, rpmps ps ) +{ + if ( !ps ) + return; + + rpmProblem p = nullptr; + zypp::AutoDispose psi ( ::rpmpsInitIterator(ps), ::rpmpsFreeIterator ); + while ((p = rpmpsiNext(psi))) { + zypp::AutoFREE msg( rpmProblemString(p) ); + str << "\t" << msg << std::endl; + } +} + +bool recvBytes ( int fd, char *buf, size_t n ) { + size_t read = 0; + while ( read != n ) { + const auto r = zyppng::eintrSafeCall( ::read, fd, buf+read, n - read ); + if ( r <= 0 ) + return false; + + read += r; + } + return true; +} + +bool sendBytes ( int fd, const void *buf, size_t n ) { + const size_t written = zyppng::eintrSafeCall( ::write, fd, buf, n ); + return written == n; +} + +template +bool pushMessage ( const Message &msg ) { + try { + zypp::FdStreamBuf f; + if ( !f.open( static_cast( ExpectedFds::MessageFd ), std::ios_base::out ) ) + return false; + + // do not close the fd once the buffer is discarded + f.disableAutoClose (); + + std::ostream outStr( &f ); + const auto &maybeMessage = msg.toStompMessage(); + if ( !maybeMessage ) { + std::rethrow_exception ( maybeMessage.error() ); + return false; + } + + maybeMessage->writeTo(outStr); + return true; + + } catch ( const zypp::Exception &e ) { + ZERR << "Failed to write message ("< psi ( ::rpmpsInitIterator(ps), ::rpmpsFreeIterator ); + while ((p = rpmpsiNext(psi))) { + zypp::AutoFREE msg( rpmProblemString(p) ); + err.problems.push_back( zypp::str::asString( msg.value() ) ); + } + + return pushMessage( err ); +} + + +using RpmHeader = std::shared_ptr>; +std::pair readPackage( rpmts ts_r, const zypp::filesystem::Pathname &path_r ) +{ + zypp::PathInfo file( path_r ); + if ( ! file.isFile() ) { + ZERR << "Not a file: " << path_r << std::endl; + return std::make_pair( RpmHeader(), -1 ); + } + + FD_t fd = ::Fopen( path_r.c_str(), "r.ufdio" ); + if ( fd == 0 || ::Ferror(fd) ) + { + ZERR << "Can't open file for reading: " << path_r << " (" << ::Fstrerror(fd) << ")" << std::endl; + if ( fd ) + ::Fclose( fd ); + return std::make_pair( RpmHeader(), -1 ); + } + + Header nh = 0; + int res = ::rpmReadPackageFile( ts_r, fd, path_r.asString().c_str(), &nh ); + ::Fclose( fd ); + + if ( ! nh ) + { + ZERR << "Error reading header from " << path_r << " error(" << res << ")" << std::endl; + return std::make_pair( RpmHeader(), res ); + } + + RpmHeader h( nh, ::headerFree ); + return std::make_pair( h, res ); +} + +// Remember 'install source rpm' transaction steps (bsc#1228647, installed separately) +struct SourcePackageInstallHelper +{ + // < transaction step index, path to the .src.rpm > + using StepIndex = std::pair; + using StepIndices = std::vector; + + void remember( std::size_t stepIndex_r, zypp::Pathname pathname_r ) + { + if ( not stepIndices ) stepIndices = StepIndices(); + stepIndices->push_back( {stepIndex_r, std::move(pathname_r)} ); + } + + std::optional stepIndices; // Remembered source rpm installs + std::optional currentStep; // Current transaction step index for rpmLibCallback +}; + +struct TransactionData { + TransactionData( zypp::proto::target::Commit & commitData_r ) + : commitData { commitData_r } + {} + + zypp::proto::target::Commit &commitData; + + // dbinstance of removals to transaction step index + std::unordered_map removePckIndex = {}; + + // the fd used by rpm to dump script output + zypp::AutoDispose rpmFd = {}; + + // Remember 'install source rpm' transaction steps (bsc#1228647, installed separately) + SourcePackageInstallHelper sourcePackageInstallHelper; +}; + +int main( int, char ** ) +{ + + // check if our env is set up correctly + if ( ::isatty(STDIN_FILENO) || ::isatty(STDOUT_FILENO) || ::isatty(STDERR_FILENO) ) { + ZERR << "Running zypp-rpm directly from the console is not supported. This is just a internal helper tool for libzypp." << std::endl; + return OtherError; + } + + // make sure the expected FDs are around too + struct stat sb{}; + if ( fstat( static_cast(ExpectedFds::MessageFd), &sb) == -1 ) { + ZERR << "Expected message fd is not valid, aborting" << std::endl; + return OtherError; + } + if ( (sb.st_mode & S_IFMT) != S_IFIFO ){ + ZERR << "Expected message fd is not a pipe, aborting" << std::endl; + return OtherError; + } + + if ( fstat( static_cast(ExpectedFds::ScriptFd), &sb) == -1 ) { + ZERR << "Expected script fd is not valid, aborting" << std::endl; + return OtherError; + } + if ( (sb.st_mode & S_IFMT) != S_IFIFO ){ + ZERR << "Expected script fd is not a pipe, aborting" << std::endl; + return OtherError; + } + + // lets ignore those, SIGPIPE is better handled via the EPIPE error, and we do not want anyone + // to CTRL+C us + zyppng::blockSignalsForCurrentThread( { SIGPIPE, SIGINT } ); + + // lets read our todo from stdin + // since all we can receive on stdin is the commit message, there is no need to read a envelope first + // we read it directly from the FD + zypp::proto::target::Commit msg; + + try { + zypp::PluginFrame pf( std::cin ); + const auto &expMsg = zypp::proto::target::Commit::fromStompMessage ( pf ); + if ( !expMsg ) { + std::rethrow_exception ( expMsg.error() ); + } + msg = std::move(*expMsg); + } catch ( const zypp::Exception &e ) { + ZERR << "Wrong commit message format, aborting (" << e << ")" << std::endl; + return WrongMessageFormat; + } + + // create or fill a pid file, if there is a existing one just take it over + // if we reach this place libzypp has its global lock and made sure there is + // no still running zypp-rpm instance. So no need to do anything complicated. + using namespace boost::interprocess; + struct s_lockinfo { + s_lockinfo() = default; + s_lockinfo( s_lockinfo && ) = default; + s_lockinfo( const s_lockinfo & ) = delete; + s_lockinfo &operator= ( s_lockinfo && ) = default; + s_lockinfo &operator= ( const s_lockinfo & ) = delete; + + ~s_lockinfo() { + std::scoped_lock lock(fileLock); + clearerr( lockFile ); + ftruncate( fileno (lockFile), 0 ); + fflush( lockFile ); + } + + file_lock fileLock; + zypp::AutoFILE lockFile; + }; + std::optional lockinfo; + if ( !msg.lockFilePath.empty () ) { + lockinfo.emplace(); + zypp::Pathname lockFileName = zypp::Pathname( msg.lockFilePath ) / "zypp-rpm.pid"; + lockinfo->lockFile = std::fopen( lockFileName.c_str(), "w"); + if ( lockinfo->lockFile == nullptr ) { + ZERR << "Failed to create zypp-rpm pidfile." << std::endl; + return FailedToCreateLock; + } + + lockinfo->fileLock = file_lock ( lockFileName.c_str() ); + + std::scoped_lock lock(lockinfo->fileLock); + fprintf(lockinfo->lockFile, "%ld\n", (long)getpid() ); + fflush( lockinfo->lockFile ); + } + + zypp::ShutdownLock lck("zypp-rpm", "Zypp commit running."); + + // we have all data ready now lets start installing + // first we initialize the rpmdb + int rc = ::rpmReadConfigFiles( NULL, NULL ); + if ( rc ) { + ZERR << "rpmReadConfigFiles returned " << rc << std::endl; + return RpmInitFailed; + } + + ::addMacro( NULL, "_dbpath", NULL, msg.dbPath.c_str(), RMIL_CMDLINE ); + + auto ts = zypp::AutoDispose( ::rpmtsCreate(), ::rpmtsFree );; + ::rpmtsSetRootDir( ts, msg.root.c_str() ); + + int tsFlags = RPMTRANS_FLAG_NONE; + int tsVerifyFlags = RPMVSF_DEFAULT; + + const auto &rpmInstFlags = msg.flags; + if ( rpmInstFlags & RpmInstFlag::RPMINST_NODIGEST) + tsVerifyFlags |= _RPMVSF_NODIGESTS; + if ( rpmInstFlags & RpmInstFlag::RPMINST_NOSIGNATURE) + tsVerifyFlags |= _RPMVSF_NOSIGNATURES; + if ( rpmInstFlags & RpmInstFlag::RPMINST_EXCLUDEDOCS) + tsFlags |= RPMTRANS_FLAG_NODOCS; + if ( rpmInstFlags & RpmInstFlag::RPMINST_NOSCRIPTS) + tsFlags |= RPMTRANS_FLAG_NOSCRIPTS; + if ( rpmInstFlags & RpmInstFlag::RPMINST_JUSTDB) + tsFlags |= RPMTRANS_FLAG_JUSTDB; + if ( rpmInstFlags & RpmInstFlag::RPMINST_TEST) + tsFlags |= RPMTRANS_FLAG_TEST; + if ( rpmInstFlags & RpmInstFlag::RPMINST_NOPOSTTRANS) + tsFlags |= RPMTRANS_FLAG_NOPOSTTRANS; + if ( rpmInstFlags & RpmInstFlag::RPMINST_NOSCRIPTS ) + tsFlags |= RPMTRANS_FLAG_NOSCRIPTS; + + // setup transaction settings + ::rpmtsSetFlags( ts, tsFlags ); + + // set the verify flags so readPackage does the right thing + ::rpmtsSetVSFlags( ts, tsVerifyFlags ); + +#ifdef HAVE_RPMTSSETVFYLEVEL + { + int vfylevel = ::rpmtsVfyLevel(ts); + if ( msg.flags() & RpmInstFlag::RPMINST_NODIGEST) + vfylevel &= ~( RPMSIG_DIGEST_TYPE ); + if ( msg.flags() & RpmInstFlag::RPMINST_NOSIGNATURE) + vfylevel &= ~( RPMSIG_SIGNATURE_TYPE); + ::rpmtsSetVfyLevel(ts, vfylevel); + } +#endif + + // open database for reading + if ( rpmtsGetRdb(ts) == NULL ) { + int res = ::rpmtsOpenDB( ts, O_RDWR ); + if ( res ) { + ZERR << "rpmdbOpen error(" << res << "): " << std::endl; + return FailedToOpenDb; + } + } + + // the transaction data we will get in the callback + TransactionData data { msg }; + + // do we care about knowing the public key? + const bool allowUntrusted = ( rpmInstFlags & RpmInstFlag::RPMINST_ALLOWUNTRUSTED ); + + for ( std::size_t i = 0; i < msg.transactionSteps.size(); ++i ) { + const auto &step = msg.transactionSteps[i]; + + if ( std::holds_alternative(step) ) { + + const auto &install = std::get(step); + + const auto &file = install.pathname; + auto rpmHeader = readPackage( ts, install.pathname ); + + switch(rpmHeader.second) { + case RPMRC_OK: + break; + case RPMRC_NOTTRUSTED: + ZERR << zypp::str::Format( "Failed to verify key for %s" ) % file << std::endl; + if ( !allowUntrusted ) + return FailedToReadPackage; + break; + case RPMRC_NOKEY: + ZERR << zypp::str::Format( "Public key unavailable for %s" ) % file << std::endl; + if ( !allowUntrusted ) + return FailedToReadPackage; + break; + case RPMRC_NOTFOUND: + ZERR << zypp::str::Format( "Signature not found for %s" ) % file << std::endl; + if ( !allowUntrusted ) + return FailedToReadPackage; + break; + case RPMRC_FAIL: + ZERR << zypp::str::Format( "Signature does not verify for %s" ) % file << std::endl; + return FailedToReadPackage; + default: + ZERR << zypp::str::Format( "Failed to open(generic error): %1%" ) % file << std::endl; + return FailedToReadPackage; + } + + if ( !rpmHeader.first ) { + ZERR << zypp::str::Format( "Failed to read rpm header from: %1%" )% file << std::endl; + return FailedToReadPackage; + } + + // bsc#1228647: ::rpmtsInstallElement accepts source rpms without an error, but + // is not able to handle them correctly within ::rpmtsRun. We need to remember + // them and run ::rpmInstallSourcePackage after the ::rpmtsRun is done. + if ( ::headerIsSource( rpmHeader.first.get() ) ) { + data.sourcePackageInstallHelper.remember( i, install.pathname ); + continue; + } + + const auto res = ::rpmtsAddInstallElement( ts, rpmHeader.first.get(), &step, !install.multiversion, nullptr ); + if ( res ) { + ZERR << zypp::str::Format( "Failed to add %1% to the transaction." )% file << std::endl; + return FailedToAddStepToTransaction; + } + + } else if ( std::holds_alternative(step) ) { + + const auto &remove = std::get(step); + + const std::string &name = remove.name + + "-" + remove.version + + "-" + remove.release + + "." + remove.arch; + + bool found = false; + zypp::AutoDispose it( ::rpmtsInitIterator( ts, rpmTag(RPMTAG_NAME), remove.name.c_str(), 0 ), ::rpmdbFreeIterator ); + while ( ::Header h = ::rpmdbNextIterator( it ) ) { + BinHeader hdr(h); + if ( hdr.string_val( RPMTAG_VERSION ) == remove.version + && hdr.string_val( RPMTAG_RELEASE ) == remove.release + && hdr.string_val( RPMTAG_ARCH ) == remove.arch ) { + found = true; + + const auto res = ::rpmtsAddEraseElement( ts, hdr.get(), 0 ); + if ( res ) { + ZERR << zypp::str::Format( "Failed to add removal of %1% to the transaction." ) % name << std::endl; + return FailedToAddStepToTransaction; + } + + data.removePckIndex.insert( std::make_pair( headerGetInstance( h ), i ) ); + break; + } + } + + if ( !found ) { + ZERR << "Unable to remove " << name << " it was not found!" << std::endl; + } + + } else { + ZERR << "Ignoring step that is neither a remove, nor a install." << std::endl; + } + + } + + // set the callback function for progress reporting and things + ::rpmtsSetNotifyCallback( ts, rpmLibCallback, &data ); + + // make sure we get da log + ::rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(env::ZYPP_RPM_DEBUG() ? RPMLOG_DEBUG : RPMLOG_INFO) ) ); + ::rpmlogSetCallback( rpmLogCallback, nullptr ); + + // redirect the script output to a fd ( log level MUST be at least INFO ) + data.rpmFd = zypp::AutoDispose ( + ::fdDup( static_cast( ExpectedFds::ScriptFd ) ), + Fclose + ); + + if ( data.rpmFd.value() ) { + //ZDBG << "Assigning script FD" << std::endl; + ::rpmtsSetScriptFd( ts, data.rpmFd ); + } else { + ZERR << "Failed to assign script FD" << std::endl; + } + + +#if 0 + // unset the verify flags, we already checked those when reading the package header and libzypp made sure + // all signatures are fine as well + ::rpmtsSetVSFlags( ts, rpmtsVSFlags(ts) | _RPMVSF_NODIGESTS | _RPMVSF_NOSIGNATURES ); + +#ifdef HAVE_RPMTSSETVFYLEVEL + { + int vfylevel = ::rpmtsVfyLevel(ts); + vfylevel &= ~( RPMSIG_DIGEST_TYPE | RPMSIG_SIGNATURE_TYPE); + ::rpmtsSetVfyLevel(ts, vfylevel); + } +#endif + +#endif + + // handle --nodeps + if ( !( msg.flags & RpmInstFlag::RPMINST_NODEPS) ) { + if ( ::rpmtsCheck(ts) ) { + zypp::AutoDispose ps( ::rpmtsProblems(ts), ::rpmpsFree ); + pushTransactionErrorMessage( ps ); + + std::ostringstream sstr; + sstr << "rpm output:" << "Failed dependencies:" << std::endl; + rpmpsPrintToStream( sstr, ps ); + + const auto &rpmMsg = sstr.str(); + + // TranslatorExplanation the colon is followed by an error message + ZERR << std::string("RPM failed: ") + rpmMsg << std::endl; + return RpmFinishedWithTransactionError; + } + } + + // those two cases are already handled by libzypp at the time a package set arrives here, + // we can safely filter those problems. + int tsProbFilterFlags = RPMPROB_FILTER_REPLACEPKG | RPMPROB_FILTER_OLDPACKAGE; + + if ( msg.ignoreArch ) + tsProbFilterFlags |= RPMPROB_FILTER_IGNOREARCH; + + if ( msg.flags & RpmInstFlag::RPMINST_ALLOWDOWNGRADE ) + tsProbFilterFlags |= ( RPMPROB_FILTER_OLDPACKAGE ); // --oldpackage + + if ( msg.flags & RpmInstFlag::RPMINST_REPLACEFILES ) + tsProbFilterFlags |= ( RPMPROB_FILTER_REPLACENEWFILES + | RPMPROB_FILTER_REPLACEOLDFILES ); // --replacefiles + + if ( msg.flags & RpmInstFlag::RPMINST_FORCE ) + tsProbFilterFlags |= ( RPMPROB_FILTER_REPLACEPKG + | RPMPROB_FILTER_REPLACENEWFILES + | RPMPROB_FILTER_REPLACEOLDFILES + | RPMPROB_FILTER_OLDPACKAGE ); // --force + + if ( msg.flags & RpmInstFlag::RPMINST_IGNORESIZE ) + tsProbFilterFlags |= RPMPROB_FILTER_DISKSPACE | RPMPROB_FILTER_DISKNODES; + + const auto orderRes = rpmtsOrder( ts ); + if ( orderRes ) { + ZERR << zypp::str::Format( "Failed with error %1% while ordering transaction." )% orderRes << std::endl; + return RpmOrderFailed; + } + + // clean up memory that is only used for dependency checks and ordering + rpmtsClean(ts); + + // transaction steps are set up lets execute it + // the way how libRPM works is that it will try to install all packages even if some of them fail + // we need to go over the rpm problem set to mark those steps that have failed, we get no other hint on wether + // it worked or not + const auto transRes = ::rpmtsRun( ts, nullptr, tsProbFilterFlags ); + //data.finishCurrentStep( ); + + if ( transRes != 0 ) { + + auto err = RpmFinishedWithError; + + std::string errMsg; + if ( transRes > 0 ) { + //@NOTE dnf checks if the problem set is empty and if it is seems to treat the transaction as successful, can this really happen? + zypp::AutoDispose ps( ::rpmtsProblems(ts), ::rpmpsFree ); + + pushTransactionErrorMessage( ps ); + + std::ostringstream sstr; + sstr << "rpm output:" << std::endl; + rpmpsPrintToStream( sstr, ps ); + errMsg = sstr.str(); + err = RpmFinishedWithTransactionError; + } else { + errMsg = "Running the transaction failed."; + } + + //HistoryLog().comment( str::form("Transaction failed"), true /*timestamp*/ ); + std::ostringstream sstr; + sstr << "rpm output:" << std::endl << errMsg << std::endl; + //HistoryLog().comment(sstr.str()); + + ZERR << "RPM transaction failed: " + errMsg << std::endl; + return err; + } + + // bsc#1228647: ::rpmtsInstallElement accepts source rpms without an error, but + // is not able to handle them correctly within ::rpmtsRun. We need to remember + // them and run ::rpmInstallSourcePackage after the ::rpmtsRun is done. + if ( data.sourcePackageInstallHelper.stepIndices ) { + ::rpmtsEmpty( ts ); // Re-create an empty transaction set. + auto err = NoError; + for ( const auto & [stepi,path] : *data.sourcePackageInstallHelper.stepIndices ) { + zypp::AutoDispose fd { ::Fopen( path.c_str(), "r" ), ::Fclose }; + data.sourcePackageInstallHelper.currentStep = stepi; // rpmLibCallback needs to look it up + ::rpmRC res = ::rpmInstallSourcePackage( ts, fd, nullptr, nullptr ); + if ( res != 0 ) { + ZERR << "RPM InstallSourcePackage " << path << " failed: " << res << std::endl; + err = RpmFinishedWithError; + } + } + data.sourcePackageInstallHelper.currentStep = std::nullopt; // done + if ( err != NoError ) { + return err; + } + } + + //ZDBG << "Success !!!!" << std::endl; + + return NoError; +} + +std::string_view tagToScriptTypeName ( int tag ) +{ + using namespace std::literals; + switch (tag) { + case RPMTAG_PREIN: + return "prein"sv; + case RPMTAG_PREUN: + return "preun"sv; + case RPMTAG_TRIGGERPREIN: + return "triggerprein"sv; + case RPMTAG_POSTIN: + return "postin"sv; + case RPMTAG_POSTUN: + return "postun"sv; + case RPMTAG_PRETRANS: + return "pretrans"sv; + case RPMTAG_POSTTRANS: + return "posttrans"sv; + case RPMTAG_TRIGGERUN: + return "triggerun"sv; + case RPMTAG_TRIGGERIN: + return "triggerin"sv; + case RPMTAG_TRIGGERPOSTUN: + return "triggerpostun"sv; + case RPMTAG_VERIFYSCRIPT: + return "verifyscript"sv; + default: + return ""sv; + } +} + +void *rpmLibCallback( const void *h, const rpmCallbackType what, const rpm_loff_t amount, const rpm_loff_t total, fnpyKey key, rpmCallbackData data ) +{ + void * rc = NULL; + TransactionData* that = reinterpret_cast( data ); + if ( !that ) + return rc; + + static FD_t fd = NULL; + const BinHeader header( (Header)h ); + + auto iStep = key ? reinterpret_cast< const zypp::proto::target::TransactionStep * >( key ) : nullptr; + if ( !iStep ) { + if ( that->sourcePackageInstallHelper.currentStep ) { + // we're in ::rpmInstallSourcePackage + iStep = &that->commitData.transactionSteps[*(that->sourcePackageInstallHelper.currentStep)]; + } + else if ( h ) { + auto key = headerGetInstance( header.get() ); + if ( key > 0 ) { + auto i = that->removePckIndex.find(key); + if ( i != that->removePckIndex.end() ) + iStep = &that->commitData.transactionSteps[i->second]; + } + } + } + +#if 0 + // dbg log callback sequence (collapsing RPMCALLBACK_INST_PROGRESS) + static rpmCallbackType prev = RPMCALLBACK_UNKNOWN; + if ( what != RPMCALLBACK_INST_PROGRESS || prev != RPMCALLBACK_INST_PROGRESS ) { + ZDBG << "LibCB " << dbg::dump(what) << ": " << dbg::dump(iStep) << " - " << header.nvra() << std::endl; + prev = what; + } +#endif + + const auto &sendEndOfScriptTag = [&](){ + //ZDBG << "Send end of script" << std::endl; + ::Fflush( that->rpmFd ); + ::sendBytes( static_cast( ExpectedFds::ScriptFd ), endOfScriptTag.data(), endOfScriptTag.size() ); + }; + + switch (what) { + case RPMCALLBACK_INST_OPEN_FILE: { + + if ( !iStep || !std::holds_alternative(*iStep) ) + return NULL; + + const auto &install = std::get(*iStep); + if ( install.pathname.empty() ) + return NULL; + + if ( fd != NULL ) + ZERR << "ERR opening a file before closing the old one? Really ? " << std::endl; + fd = Fopen( install.pathname.data(), "r.ufdio" ); + if (fd == NULL || Ferror(fd)) { + ZERR << "Error when opening file " << install.pathname.data() << std::endl; + if (fd != NULL) { + Fclose(fd); + fd = NULL; + } + } else + fd = fdLink(fd); + return (void *)fd; + break; + } + + case RPMCALLBACK_INST_CLOSE_FILE: + fd = fdFree(fd); + if (fd != NULL) { + Fclose(fd); + fd = NULL; + } + break; + + case RPMCALLBACK_INST_START: { + + if ( !iStep || !std::holds_alternative(*iStep) ) + return rc; + + zypp::proto::target::PackageBegin step; + step.stepId = std::get(*iStep).stepId; + pushMessage( step ); + + break; + } + + case RPMCALLBACK_UNINST_START: { + + if ( !iStep ) { + + if ( header.empty() ) { + ZERR << "No header and no transaction step for a uninstall start, not sending anything" << std::endl; + return rc; + } + + // this is a package cleanup send the report accordingly + zypp::proto::target::CleanupBegin step; + step.nvra = header.nvra(); + pushMessage( step ); + + } else { + + if ( !std::holds_alternative(*iStep) ) { + ZERR << "Could not find package in removables " << header << " in transaction elements" << std::endl; + return rc; + } + + zypp::proto::target::PackageBegin step; + step.stepId = std::get(*iStep).stepId; + pushMessage( step ); + } + break; + } + + case RPMCALLBACK_INST_STOP: { + + if ( !iStep ) { + ZERR << "Could not find package " << header << " in transaction elements for " << dbg::dump(what) << std::endl; + return rc; + } + + sendEndOfScriptTag(); + + zypp::proto::target::PackageFinished step; + step.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + pushMessage( step ); + + break; + } + + case RPMCALLBACK_UNINST_STOP: { + + if ( !iStep ) { + if ( header.empty() ) { + ZERR << "No header and no transaction step for a uninstall stop, not sending anything" << std::endl; + return rc; + } + + sendEndOfScriptTag(); + + // this is a package cleanup send the report accordingly + zypp::proto::target::CleanupFinished step; + step.nvra = header.nvra(); + pushMessage( step ); + } else { + + sendEndOfScriptTag(); + + zypp::proto::target::PackageFinished step; + step.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + pushMessage( step ); + + } + + break; + } + case RPMCALLBACK_UNPACK_ERROR: { + + if ( !iStep ) { + ZERR << "Could not find package " << header << " in transaction elements for " << dbg::dump(what) << std::endl; + return rc; + } + + zypp::proto::target::PackageError step; + step.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + pushMessage( step ); + break; + } + + case RPMCALLBACK_INST_PROGRESS: { + + if ( !iStep ) + return rc; + + const auto progress = (double) (total + ? ((((float) amount) / total) * 100) + : 100.0); + + zypp::proto::target::PackageProgress step; + step.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + step.amount = progress; + pushMessage( step ); + + break; + } + + case RPMCALLBACK_UNINST_PROGRESS: { + + const auto progress = (double) (total + ? ((((float) amount) / total) * 100) + : 100.0); + if ( !iStep ) { + if ( header.empty() ) { + ZERR << "No header and no transaction step for a uninstall progress, not sending anything" << std::endl; + return rc; + } + + // this is a package cleanup send the report accordingly + zypp::proto::target::CleanupProgress step; + step.nvra = header.nvra(); + step.amount = progress; + pushMessage( step ); + + } else { + zypp::proto::target::PackageProgress step; + step.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + step.amount = progress; + pushMessage( step ); + } + break; + } + +#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP + case RPMCALLBACK_VERIFY_START: +#endif + case RPMCALLBACK_TRANS_START: { + zypp::proto::target::TransBegin step; + const char *n = "Preparing"; +#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP + if ( what == RPMCALLBACK_VERIFY_START ) + n = "Verifying"; +#endif + step.name = n; + pushMessage( step ); + break; + } + +#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP + case RPMCALLBACK_VERIFY_STOP: +#endif + case RPMCALLBACK_TRANS_STOP: { + sendEndOfScriptTag(); + zypp::proto::target::TransFinished step; + pushMessage( step ); + break; + } + +#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP + case RPMCALLBACK_VERIFY_PROGRESS: +#endif + case RPMCALLBACK_TRANS_PROGRESS: { + const auto percentage = (double) (total + ? ((((float) amount) / total) * 100) + : 100.0); + zypp::proto::target::TransProgress prog; + prog.amount = percentage; + pushMessage( prog ); + break; + } + case RPMCALLBACK_CPIO_ERROR: + ZERR << "CPIO Error when installing package" << std::endl; + break; + case RPMCALLBACK_SCRIPT_START: { + zypp::proto::target::ScriptBegin script; + if ( iStep ) + script.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + else + script.stepId = -1; + + // script type is stored in the amount variable passed to the callback + script.scriptType = std::string( tagToScriptTypeName( amount ) ); + + if ( header.get() ) { + script.scriptPackage = header.nvra(); + } + + pushMessage( script ); + break; + } + + case RPMCALLBACK_SCRIPT_STOP: { + sendEndOfScriptTag(); + zypp::proto::target::ScriptFinished script; + if ( iStep ) + script.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + else + script.stepId = ( -1 ); + pushMessage( script ); + break; + } + case RPMCALLBACK_SCRIPT_ERROR: { + zypp::proto::target::ScriptError script; + if ( iStep ) + script.stepId = std::visit([](const auto &val){ return val.stepId;}, *iStep ); + else + script.stepId = ( -1 ); + + // for RPMCALLBACK_SCRIPT_ERROR 'total' is abused by librpm to distinguish between warning and "real" errors + script.fatal = ( total != RPMRC_OK ); + pushMessage( script ); + break; + } + case RPMCALLBACK_UNKNOWN: + default: + break; + } + + return rc; +} + +int rpmLogCallback ( rpmlogRec rec, rpmlogCallbackData ) +{ + int logRc = 0; + + zypp::proto::target::RpmLog log; + log.level = rpmlogRecPriority(rec); + log.line = zypp::str::asString( ::rpmlogRecMessage(rec) ); + pushMessage( log ); + + return logRc; +} diff --git a/tools/zypp-runpurge.cc b/tools/zypp-runpurge.cc new file mode 100644 index 0000000..ca5f3f8 --- /dev/null +++ b/tools/zypp-runpurge.cc @@ -0,0 +1,83 @@ +#include +#include "argparse.h" + +#define INCLUDE_TESTSETUP_WITHOUT_BOOST +#include "../tests/lib/TestSetup.h" +#undef INCLUDE_TESTSETUP_WITHOUT_BOOST + +static std::string appname { "NO_NAME" }; + +int errexit( const std::string & msg_r = std::string(), int exit_r = 100 ) +{ + if ( ! msg_r.empty() ) + cerr << endl << appname << ": ERR: " << msg_r << endl << endl; + return exit_r; +} + +int usage( const argparse::Options & options_r, int return_r = 0 ) +{ + cerr << "USAGE: " << appname << " [OPTION]... path/to/testcase" << endl; + cerr << " Calculate the kernels that would be purged based on the spec and testcase." << endl; + cerr << options_r << endl; + return return_r; +} + +int main ( int argc, char *argv[] ) +{ + + appname = Pathname::basename( argv[0] ); + argparse::Options options; + options.add() + ( "help,h", "Print help and exit." ) + ( "uname", "The running kernels uname", argparse::Option::Arg::required ) + ( "keepSpec", "The keepspec ( default is oldest,running,latest)", argparse::Option::Arg::required ); + + auto result = options.parse( argc, argv ); + + if ( result.count( "help" ) || !result.count("uname") || !result.positionals().size() ) + return usage( options, 1 ); + + const std::string &testcaseDir = result.positionals().front(); + const auto &pathInfo = PathInfo(testcaseDir); + if ( !pathInfo.isExist() || !pathInfo.isDir() ) { + std::cerr << "Invalid or non existing testcase path: " << testcaseDir << std::endl; + return 1; + } + + if ( ::chdir( testcaseDir.data() ) != 0 ) { + std::cerr << "Failed to chdir to " << testcaseDir << std::endl; + return 1; + } + + TestSetup t; + try { + t.LoadSystemAt( result.positionals().front() ); + } catch ( const zypp::Exception &e ) { + std::cerr << "Failed to load the testcase at " << result.positionals().front() << std::endl; + std::cerr << "Got exception: " << e << std::endl; + return 1; + } + + std::string keepSpec = "oldest,running,latest"; + if ( result.count("keepSpec") ) { + keepSpec = result["keepSpec"].arg(); + } + + PurgeKernels krnls; + krnls.setUnameR( result["uname"].arg() ); + krnls.setKeepSpec( keepSpec ); + krnls.markObsoleteKernels(); + + const auto &makeNVRA = []( const PoolItem &pck ) -> std::string { + return pck.name() + "-" + pck.edition().asString() + "." + pck.arch().asString(); + }; + + auto pool = ResPool::instance(); + const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled ); + for ( auto it = pool.byStatusBegin( toBeUninstalledFilter ); it != pool.byStatusEnd( toBeUninstalledFilter ); it++ ) { + std::cout << "Removing " << makeNVRA(*it) + (it->status().isByUser() ? " (by user)" : " (autoremoved)") << std::endl; + } + + return 0; + +} diff --git a/zypp-core/APIConfig.h.in b/zypp-core/APIConfig.h.in new file mode 100644 index 0000000..6074ad9 --- /dev/null +++ b/zypp-core/APIConfig.h.in @@ -0,0 +1,22 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/APIConfig.h + * \brief Provides API related macros. + */ +#ifndef ZYPP_APICONFIG_H +#define ZYPP_APICONFIG_H + +#define LIBZYPP_VERSION_STRING "@VERSION@" +#define LIBZYPP_VERSION_MAJOR @LIBZYPP_MAJOR@ +#define LIBZYPP_VERSION_MINOR @LIBZYPP_MINOR@ +#define LIBZYPP_VERSION_PATCH @LIBZYPP_PATCH@ +#define LIBZYPP_SOVERSION @LIBZYPP_SO_FIRST@ +#define LIBZYPP_VERSION @LIBZYPP_NUMVERSION@ + +#endif //ZYPP_APICONFIG_H diff --git a/zypp-core/AutoDispose.h b/zypp-core/AutoDispose.h new file mode 100644 index 0000000..8fa3dea --- /dev/null +++ b/zypp-core/AutoDispose.h @@ -0,0 +1,346 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/AutoDispose.h + * +*/ +#ifndef ZYPP_AUTODISPOSE_H +#define ZYPP_AUTODISPOSE_H + +#include +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : AutoDispose + // + /** Reference counted access to a \c Tp object calling a custom + * \c Dispose function when the last AutoDispose handle to it is + * destroyed or reset. + * + * \note As with pointers, constness of an \c AutoDispose object does + * \b not apply to the stored \c Tp object. If the stored \c Tp object + * should be immutable, you should use AutoDispose\. + * + * Pass a filename to the application and provide the appropriate + * code to be executed when the file is no longer needed: + * \code + * struct FileCache + * { + * Pathname getFile(); + * void releaseFile( const Pathname & ); + * }; + * + * static FileCache cache; + * + * void unlink( const Pathname & file_r ); + * + * AutoDispose provideFile( ... ) + * { + * if ( file_is_in_cache ) + * { + * // will call 'cache.releaseFile( file )' + * return AutoDispose( cache.getFile(), + * bind( &FileCache::releaseFile, ref(cache), _1 ) ); + * } + * else if ( file_is_temporary ) + * { + * // will call 'unlink( file )' + * return AutoDispose( file, unlink ); + * } + * else if ( file_is_permanent ) + * { + * // will do nothing. + * return AutoDispose( file ); + * } + * else + * { + * // will do nothing. + * return AutoDispose(); + * } + * } + * \endcode + * + * Exception safe handling of temporary files: + * \code + * void provideFileAt( const Pathname & destination ) + * { + * AutoDispose guard( destination, unlink ); + * + * // Any exception here will lead to 'unlink( destination )' + * // ... + * + * // On success: reset the dispose function to NOOP. + * guard.resetDispose(); + * } + * \endcode + */ + template + class AutoDispose + { + public: + using param_type = typename boost::call_traits::param_type; + using reference = typename boost::call_traits::reference; + using const_reference = typename boost::call_traits::const_reference; + using value_type = Tp; + using result_type = typename boost::call_traits::value_type; + // bsc#1194597: Header is exposed in the public API, so it must be c++11: + // using dispose_param_type = std::conditional_t< std::is_pointer_v || std::is_integral_v, Tp const, reference >; + using dispose_param_type = std::conditional_t< std::is_pointer_v || std::is_integral_v, Tp const, reference >; + + public: + /** Dispose function signatue. */ + using Dispose = function; + + public: + /** Default Ctor using default constructed value and no dispose function. */ + AutoDispose() + : _pimpl( new Impl( value_type() ) ) + {} + + /** Ctor taking dispose function and using default constructed value. */ + explicit AutoDispose( Dispose dispose_r ) + : _pimpl( new Impl( value_type(), std::move(dispose_r) ) ) + {} + + /** Ctor taking value and no dispose function. */ + explicit AutoDispose( value_type value_r ) + : _pimpl( new Impl( std::move(value_r) ) ) + {} + + /** Ctor taking value and dispose function. */ + AutoDispose( value_type value_r, Dispose dispose_r ) + : _pimpl( new Impl( std::move(value_r), std::move(dispose_r) ) ) + {} + + public: + + /** Provide implicit conversion to \c Tp\&. */ + operator reference() const + { return _pimpl->_value; } + + /** Reference to the \c Tp object. */ + reference value() const + { return _pimpl->_value; } + + /** Reference to the \c Tp object. */ + reference operator*() const + { return _pimpl->_value; } + + /** Pointer to the \c Tp object (asserted to be != NULL). */ + value_type * operator->() const + { return & _pimpl->_value; } + + /** Reset to default Ctor values. */ + void reset() + { AutoDispose().swap( *this ); } + + /** Exchange the contents of two AutoDispose objects. */ + void swap( AutoDispose & rhs ) noexcept + { _pimpl.swap( rhs._pimpl ); } + + /** Returns true if this is the only AutoDispose instance managing the current data object */ + bool unique () const + { return _pimpl.unique(); } + + public: + /** Return the current dispose function. */ + const Dispose & getDispose() const + { return _pimpl->_dispose; } + + /** Set a new dispose function. */ + void setDispose( const Dispose & dispose_r ) + { _pimpl->_dispose = dispose_r; } + + /** Set no dispose function. */ + void resetDispose() + { setDispose( Dispose() ); } + + /** Exchange the dispose function. */ + void swapDispose( Dispose & dispose_r ) + { _pimpl->_dispose.swap( dispose_r ); } + + private: + struct Impl : private base::NonCopyable + { + template + Impl( T &&value_r ) + : _value( std::forward(value_r) ) + {} + template + Impl( T &&value_r, D &&dispose_r ) + : _value( std::forward(value_r) ) + , _dispose( std::forward(dispose_r) ) + {} + ~Impl() + { + if ( _dispose ) + try { _dispose( _value ); } catch(...) {} + } + value_type _value; + Dispose _dispose; + }; + + shared_ptr _pimpl; + }; + + template<> + class AutoDispose + { + public: + /** Dispose function signatue. */ + using Dispose = function; + + public: + /** Default Ctor using default constructed value and no dispose function. */ + AutoDispose() + : _pimpl( new Impl() ) + {} + + /** Ctor taking dispose function and using default constructed value. */ + explicit AutoDispose( const Dispose & dispose_r ) + : _pimpl( new Impl( dispose_r ) ) + {} + + public: + + /** Reset to default Ctor values. */ + void reset() + { AutoDispose().swap( *this ); } + + /** Exchange the contents of two AutoDispose objects. */ + void swap( AutoDispose & rhs ) noexcept + { _pimpl.swap( rhs._pimpl ); } + + public: + /** Return the current dispose function. */ + const Dispose & getDispose() const + { return _pimpl->_dispose; } + + /** Set a new dispose function. */ + void setDispose( const Dispose & dispose_r ) + { _pimpl->_dispose = dispose_r; } + + /** Set no dispose function. */ + void resetDispose() + { setDispose( Dispose() ); } + + /** Exchange the dispose function. */ + void swapDispose( Dispose & dispose_r ) + { _pimpl->_dispose.swap( dispose_r ); } + + private: + struct Impl : private base::NonCopyable + { + Impl( ) + {} + + Impl( Dispose dispose_r ) + : _dispose(std::move( dispose_r )) + {} + + ~Impl() + { + if ( _dispose ) + try { _dispose(); } catch(...) {} + } + Dispose _dispose; + }; + shared_ptr _pimpl; + }; + + /*! + * Simple way to run a function at scope exit: + * \code + * bool wasBlocking = unblockFile( fd, true ); + * OnScopeExit cleanup( [wasBlocking, fd](){ + * if ( wasBlocking ) unblockFile( fd, false ); + * }); + * \endcode + */ + using OnScopeExit = AutoDispose; + + struct Deferred : public AutoDispose + { + template + Deferred( F&&cb ); + }; + + template + Deferred::Deferred(F &&cb) : AutoDispose( std::forward(cb) ){} + +#define __zypp_defer_concatenate(__lhs, __rhs) \ + __lhs##__rhs + +#define __zypp_defer_declarator(__id) \ + zypp::Deferred __zypp_defer_concatenate(__defer, __id) = [&]() + +#define zypp_defer \ + __zypp_defer_declarator(__LINE__) + + /////////////////////////////////////////////////////////////////// + + /** \relates AutoDispose Stream output of the \c Tp object. */ + template + inline std::ostream & operator<<( std::ostream & str, const AutoDispose & obj ) + { return str << obj.value(); } + + + /////////////////////////////////////////////////////////////////// + /// \class AutoFD + /// \brief \ref AutoDispose\ calling \c ::close + /// \ingroup g_RAII + /////////////////////////////////////////////////////////////////// + struct AutoFD : public AutoDispose + { + AutoFD( int fd_r = -1 ) : AutoDispose( fd_r, [] ( int fd_r ) { if ( fd_r != -1 ) ::close( fd_r ); } ) {} + }; + + /////////////////////////////////////////////////////////////////// + /// \class AutoFILE + /// \brief \ref AutoDispose\ calling \c ::fclose + /// \see \ref AutoDispose + /// \ingroup g_RAII + /////////////////////////////////////////////////////////////////// + struct AutoFILE : public AutoDispose + { + AutoFILE( FILE* file_r = nullptr ) : AutoDispose( file_r, [] ( FILE* file_r ) { if ( file_r ) ::fclose( file_r ); } ) {} + }; + + /////////////////////////////////////////////////////////////////// + /// \class AutoFREE + /// \brief \ref AutoDispose\ calling \c ::free + /// \ingroup g_RAII + /////////////////////////////////////////////////////////////////// + template + struct AutoFREE : public AutoDispose + { + AutoFREE( Tp* ptr_r = nullptr ) : AutoDispose( ptr_r, [] ( Tp* ptr_r ) { if ( ptr_r ) ::free( ptr_r ); } ) {} + AutoFREE( void* ptr_r ) : AutoFREE( static_cast(ptr_r) ) {} + }; + + template <> + struct AutoFREE : public AutoDispose + { + AutoFREE( void* ptr_r = nullptr ) : AutoDispose( ptr_r, [] ( void* ptr_r ) { if ( ptr_r ) ::free( ptr_r ); } ) {} + }; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_AUTODISPOSE_H diff --git a/zypp-core/ByteArray.h b/zypp-core/ByteArray.h new file mode 100644 index 0000000..f30da27 --- /dev/null +++ b/zypp-core/ByteArray.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_BYTEARRAY_H +#define ZYPP_BYTEARRAY_H + +#include +#include +#include +#include + +namespace zypp { + class ByteArray : public std::vector + { + public: + using vector::vector; + explicit ByteArray ( const std::string &data ) : ByteArray( data.c_str(), data.length() ) { } + explicit ByteArray ( const char *data, const int len = -1 ) : ByteArray( data, data + (len == -1 ? strlen(data) : len) ) { } + std::string asString () const { + if ( size() == 0 ) + return std::string(); + return std::string( data(), size() ); + } + +#ifdef __cpp_lib_string_view + std::string_view asStringView () const { + if ( size() == 0 ) + return std::string_view(); + return std::string_view( data(), size() ); + } +#endif + + static std::size_t maxSize () { + static const auto size = ByteArray().max_size(); + return size; + } + + }; + + class UByteArray : public std::vector + { + public: + using vector::vector; + explicit UByteArray ( const char *data, const int len = -1 ) : UByteArray( data, data + (len == -1 ? strlen(data) : len) ) { } + + static std::size_t maxSize () { + static const auto size = UByteArray().max_size(); + return size; + } + }; +} + + +#endif diff --git a/zypp-core/ByteCount.cc b/zypp-core/ByteCount.cc new file mode 100644 index 0000000..b2eb4a0 --- /dev/null +++ b/zypp-core/ByteCount.cc @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ByteCount.cc + * +*/ +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const ByteCount::Unit ByteCount::B( 1LL, "B", 0 ); + + const ByteCount::Unit ByteCount::K( 1024LL, "KiB", 1 ); + const ByteCount::Unit ByteCount::KiB( K ); + const ByteCount::Unit ByteCount::M( 1048576LL, "MiB", 1 ); + const ByteCount::Unit ByteCount::MiB( M ); + const ByteCount::Unit ByteCount::G( 1073741824LL, "GiB", 2 ); + const ByteCount::Unit ByteCount::GiB( G ); + const ByteCount::Unit ByteCount::T( 1099511627776LL, "TiB", 3 ); + const ByteCount::Unit ByteCount::TiB( T ); + + const ByteCount::Unit ByteCount::kB( 1000LL, "kB", 1 ); + const ByteCount::Unit ByteCount::MB( 1000000LL, "MB", 1 ); + const ByteCount::Unit ByteCount::GB( 1000000000LL, "GB", 2 ); + const ByteCount::Unit ByteCount::TB( 1000000000000LL, "TB", 3 ); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ByteCount::fillBlock + // METHOD TYPE : ByteCount & + // + ByteCount & ByteCount::fillBlock( ByteCount blocksize_r ) + { + if ( _count && blocksize_r ) + { + SizeType diff = _count % blocksize_r; + if ( diff ) + { + if ( _count > 0 ) + { + _count += blocksize_r; + _count -= diff; + } + else + { + _count -= blocksize_r; + _count += diff; + } + } + } + return *this; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ByteCount::bestUnit + // METHOD TYPE : ByteCount::Unit + // + const ByteCount::Unit & ByteCount::bestUnit() const + { + SizeType usize( _count < 0 ? -_count : _count ); + if ( usize < K.factor() ) + return B; + if ( usize < M.factor() ) + return K; + if ( usize < G.factor() ) + return M; + if ( usize < T.factor() ) + return G; + return T; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ByteCount::bestUnit1000 + // METHOD TYPE : ByteCount::Unit + // + const ByteCount::Unit & ByteCount::bestUnit1000() const + { + SizeType usize( _count < 0 ? -_count : _count ); + if ( usize < kB.factor() ) + return B; + if ( usize < MB.factor() ) + return kB; + if ( usize < GB.factor() ) + return MB; + if ( usize < TB.factor() ) + return GB; + return TB; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/ByteCount.h b/zypp-core/ByteCount.h new file mode 100644 index 0000000..47ee01e --- /dev/null +++ b/zypp-core/ByteCount.h @@ -0,0 +1,167 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ByteCount.h + * +*/ +#ifndef ZYPP_BYTECOUNT_H +#define ZYPP_BYTECOUNT_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ByteCount + // + /** Store and operate with byte count. + * + */ + class ZYPP_API ByteCount + { + friend std::ostream & operator<<( std::ostream & str, const ByteCount & obj ); + + public: + + using Unit = base::Unit; + using SizeType = Unit::ValueType; + + /** \name Byte unit constants. */ + //@{ + /** 1 Byte */ + static const Unit B; + + /** 1024 Byte */ + static const Unit K; + static const Unit KiB; + /** 1024^2 Byte */ + static const Unit M; + static const Unit MiB; + /** 1024^3 Byte */ + static const Unit G; + static const Unit GiB; + /** 1024^4 Byte */ + static const Unit T; + static const Unit TiB; + + /** 1000 Byte */ + static const Unit kB; + /** 1000^2 Byte */ + static const Unit MB; + /** 1000^3 Byte */ + static const Unit GB; + /** 1000^4 Byte */ + static const Unit TB; + //@} + + public: + + /** Default ctor */ + ByteCount() + : _count( 0 ) + {} + /** Ctor taking 1 Unit. */ + ByteCount( const Unit & unit_r ) + : _count( unit_r.factor() ) + {} + /** Ctor taking a count and optinal Unit. */ + ByteCount( const SizeType count_r, const Unit & unit_r = B ) + : _count( count_r * unit_r.factor() ) + {} + + public: + + /** Conversion to SizeType. */ + operator SizeType() const + { return _count; } + + /** \name Arithmetic operations. + * \c + \c - \c * \c / are provided via conversion to SizeType. + */ + //@{ + ByteCount & operator+=( const SizeType rhs ) { _count += rhs; return *this; } + ByteCount & operator-=( const SizeType rhs ) { _count -= rhs; return *this; } + ByteCount & operator*=( const SizeType rhs ) { _count *= rhs; return *this; } + ByteCount & operator/=( const SizeType rhs ) { _count /= rhs; return *this; } + + ByteCount & operator++(/*prefix*/) { _count += 1; return *this; } + ByteCount & operator--(/*prefix*/) { _count -= 1; return *this; } + + ByteCount operator++(int/*postfix*/) { return _count++; } + ByteCount operator--(int/*postfix*/) { return _count--; } + //@} + + /** Adjust count to multiple of \a blocksize_r (default 1K). + * Zero blocksize_r is treated as 1B. + */ + ByteCount & fillBlock( ByteCount blocksize_r = K ); + + /** Return count adjusted to multiple of \a blocksize_r (default 1K). */ + ByteCount fullBlocks( ByteCount blocksize_r = K ) const + { return ByteCount(*this).fillBlock( blocksize_r ); } + + /** Return number of blocks of size \a blocksize_r (default 1K). */ + SizeType blocks( ByteCount blocksize_r = K ) const + { return fullBlocks( blocksize_r ) / blocksize_r; } + + public: + + /** Return the best Unit (B,K,M,G,T) for count. */ + const Unit & bestUnit() const; + + /** Return the best Unit (B,kB,MB,GB,TB) for count. */ + const Unit & bestUnit1000() const; + + /** \name Conversion to string. + * \li \a field_width_r Width for the number part (incl. precision) + * \li \a unit_width_r With for the unit symbol (without symbol if zero) + * \li \a prec_r Precision to use. + * \see zypp::base::Unit + */ + //@{ + /** Auto selected Unit and precision. */ + std::string asString( unsigned field_width_r = 0, + unsigned unit_width_r = 1 ) const + { return asString( bestUnit(), field_width_r, unit_width_r ); } + /** Auto selected Unit. */ + std::string asString( unsigned field_width_r, + unsigned unit_width_r, + unsigned prec_r ) const + { return asString( bestUnit(), field_width_r, unit_width_r, prec_r ); } + /** Auto selected precision. */ + std::string asString( const Unit & unit_r, + unsigned field_width_r = 0, + unsigned unit_width_r = 1 ) const + { return asString( unit_r, field_width_r, unit_width_r, unit_r.prec() ); } + /** Nothing auto selected. */ + std::string asString( const Unit & unit_r, + unsigned field_width_r, + unsigned unit_width_r, + unsigned prec_r ) const + { return unit_r.form( _count, field_width_r, unit_width_r, prec_r ); } + //@} + + private: + SizeType _count; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ByteCount Stream output */ + inline std::ostream & operator<<( std::ostream & str, const ByteCount & obj ) + { return str << obj.asString(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BYTECOUNT_H diff --git a/zypp-core/CMakeLists.txt b/zypp-core/CMakeLists.txt new file mode 100644 index 0000000..989e244 --- /dev/null +++ b/zypp-core/CMakeLists.txt @@ -0,0 +1,449 @@ +# Collect all files that may contain translatable texts +FILE( GLOB_RECURSE POT_FILE_DEPENDS RELATIVE ${LIBZYPP_SOURCE_DIR} "*.h" "*.cc" ) +SET( POT_FILE_DEPENDS_ZYPP_CORE ${POT_FILE_DEPENDS} PARENT_SCOPE ) + +INCLUDE_DIRECTORIES ( ${LIBZYPP_SOURCE_DIR} ) + +ADD_DEFINITIONS( -DLOCALEDIR="${CMAKE_INSTALL_PREFIX}/share/locale" -DTEXTDOMAIN="zypp" -DZYPP_DLL ) + +SET( zypp_toplevel_headers + ${CMAKE_CURRENT_BINARY_DIR}/APIConfig.h + AutoDispose.h + ByteArray.h + ByteCount.h + CheckSum.h + Date.h + Digest.h + ExternalProgram.h + Globals.h + KVMap + kvmap.h + ManagedFile.h + onmedialocation.h + OnMediaLocation + Pathname.h + TriBool.h + Url.h + UserData.h +) + +SET( zypp_toplevel_SRCS + ByteCount.cc + CheckSum.cc + Date.cc + Digest.cc + ExternalProgram.cc + onmedialocation.cc + Pathname.cc + ShutdownLock.cc + Url.cc +) +INSTALL( FILES ${zypp_toplevel_headers} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core" ) + +SET( zypp_base_HEADERS + base/DefaultIntegral + base/defaultintegral.h + base/DtorReset + base/dtorreset.h + base/Easy.h + base/EnumClass.h + base/Errno.h + base/Exception.h + base/ExternalDataSource.h + base/Function.h + base/Flags.h + base/filestreambuf.h + base/FileStreamBuf + base/fXstream + base/fxstream.h + base/Gettext.h + base/GzStream + base/gzstream.h + base/Hash.h + base/InputStream + base/inputstream.h + base/IOStream.h + base/IOTools.h + base/Iterable.h + base/Iterator.h + base/LogControl.h + base/LogTools.h + base/Logger.h + base/NonCopyable.h + base/ProfilingFormater.h + base/ProvideNumericId + base/providenumericid.h + base/PtrTypes.h + base/ReferenceCounted.h + base/Regex.h + base/SimpleStreambuf + base/simplestreambuf.h + base/String.h + base/StringV.h + base/Unit.h + base/UserRequestException + base/userrequestexception.h + base/Xml.h +) + +SET( zypp_base_SRCS + base/CleanerThread.cc + base/Exception.cc + base/ExternalDataSource.cc + base/filestreambuf.cc + base/Gettext.cc + base/gzstream.cc + base/inputstream.cc + base/IOStream.cc + base/IOTools.cc + base/LogControl.cc + base/ProfilingFormater.cc + base/ReferenceCounted.cc + base/Regex.cc + base/String.cc + base/StringV.cc + base/Unit.cc + base/userrequestexception.cc + base/Xml.cc +) + +IF (ENABLE_ZCHUNK_COMPRESSION) + + list( APPEND zypp_base_SRCS + base/zckstream.cc + ) + + list( APPEND zypp_base_HEADERS + base/ZckStream + base/zckstream.h + ) + +ENDIF(ENABLE_ZCHUNK_COMPRESSION) + +INSTALL( FILES ${zypp_base_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core/base" ) + + +SET( zypp_fs_SRCS + fs/PathInfo.cc + fs/TmpPath.cc +) + +SET( zypp_fs_HEADERS + fs/PathInfo.h + fs/TmpPath.h + fs/WatchFile + fs/watchfile.h +) + +INSTALL( FILES ${zypp_fs_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core/fs" ) + + +SET( zypp_rpc_SRCS + rpc/PluginFrame.cc + rpc/PluginFrameException.cc +) + +SET( zypp_rpc_HEADERS + rpc/PluginFrame.h + rpc/PluginFrameException.h +) + +INSTALL( FILES ${zypp_rpc_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core/rpc" ) + + +SET( zypp_ui_SRCS + ui/progressdata.cc +) + +SET( zypp_ui_HEADERS + ui/ProgressData + ui/progressdata.h +) + +INSTALL( FILES ${zypp_ui_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core/ui" ) + + +SET( zypp_url_SRCS + url/UrlUtils.cc + url/UrlBase.cc +) + +SET( zypp_url_HEADERS + url/UrlBase.h + url/UrlException.h + url/UrlUtils.h +) + +INSTALL( FILES ${zypp_url_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core/url" ) + +SET( zypp_parser_SRCS + parser/iniparser.cc + parser/inidict.cc + parser/parseexception.cc + parser/sysconfig.cc +) + +SET( zypp_parser_HEADERS + parser/IniParser + parser/iniparser.h + parser/IniDict + parser/inidict.h + parser/ParseException + parser/parseexception.h + parser/Sysconfig + parser/sysconfig.h +) + +INSTALL( FILES ${zypp_parser_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core/parser" ) + +SET( zypp_parser_xml_SRCS + parser/xml/XmlEscape.cc +) + +SET( zypp_parser_xml_HEADERS + parser/xml/XmlEscape.h +) + +INSTALL( FILES ${zypp_parser_xml_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-core/parser/xml" ) + +SET( zyppng_async_HEADERS + zyppng/async/AsyncOp + zyppng/async/asyncop.h +) + +SET( zyppng_base_SRCS + zyppng/base/abstracteventsource.cc + zyppng/base/base.cc + zyppng/base/eventdispatcher_glib.cc + zyppng/base/eventloop_glib.cc + zyppng/base/linuxhelpers.cc + zyppng/base/timer.cc + zyppng/base/threaddata.cc + zyppng/base/socketnotifier.cc + zyppng/base/unixsignalsource.cpp +) + +SET( zyppng_base_HEADERS + zyppng/base/AbstractEventSource + zyppng/base/abstracteventsource.h + zyppng/base/AutoDisconnect + zyppng/base/autodisconnect.h + zyppng/base/Base + zyppng/base/base.h + zyppng/base/EventDispatcher + zyppng/base/eventdispatcher.h + zyppng/base/EventLoop + zyppng/base/eventloop.h + zyppng/base/signals.h + zyppng/base/SocketNotifier + zyppng/base/socketnotifier.h + zyppng/base/statemachine.h + zyppng/base/Timer + zyppng/base/timer.h + zyppng/base/unixsignalsource.h + zyppng/base/zyppglobal.h +) + +SET( zyppng_base_private_HEADERS + zyppng/base/private/abstracteventsource_p.h + zyppng/base/private/base_p.h + zyppng/base/private/eventdispatcher_glib_p.h + zyppng/base/private/eventloop_glib_p.h + zyppng/base/private/linuxhelpers_p.h + zyppng/base/private/threaddata_p.h +) + +SET( zyppng_core_HEADERS + zyppng/core/bytearray.h + zyppng/core/ByteArray + zyppng/core/url.h + zyppng/core/Url + zyppng/core/idstring.h + zyppng/core/IdString + zyppng/core/string.h + zyppng/core/String +) + +SET( zyppng_io_private_HEADERS + zyppng/io/private/asyncdatasource_p.h + zyppng/io/private/iobuffer_p.h + zyppng/io/private/iodevice_p.h + zyppng/io/private/socket_p.h + zyppng/io/private/sockaddr_p.h + zyppng/io/private/abstractspawnengine_p.h + zyppng/io/private/forkspawnengine_p.h +) + +SET( zyppng_io_SRCS + zyppng/io/asyncdatasource.cpp + zyppng/io/iobuffer.cc + zyppng/io/iodevice.cc + zyppng/io/process.cpp + zyppng/io/socket.cc + zyppng/io/sockaddr.cpp + zyppng/io/abstractspawnengine.cc + zyppng/io/forkspawnengine.cc +) + +SET( zyppng_io_HEADERS + zyppng/io/AsyncDataSource + zyppng/io/asyncdatasource.h + zyppng/io/IODevice + zyppng/io/iodevice.h + zyppng/io/Process + zyppng/io/process.h + zyppng/io/Socket + zyppng/io/socket.h + zyppng/io/sockaddr.h + zyppng/io/SockAddr +) + +SET( zyppng_meta_HEADERS + zyppng/meta/Functional + zyppng/meta/functional.h + zyppng/meta/FunctionTraits + zyppng/meta/function_traits.h + zyppng/meta/TypeTraits + zyppng/meta/type_traits.h +) + +SET( zyppng_pipelines_HEADERS + zyppng/pipelines/Algorithm + zyppng/pipelines/algorithm.h + zyppng/pipelines/AsyncResult + zyppng/pipelines/asyncresult.h + zyppng/pipelines/Await + zyppng/pipelines/await.h + zyppng/pipelines/Expected + zyppng/pipelines/expected.h + zyppng/pipelines/Lift + zyppng/pipelines/lift.h + zyppng/pipelines/MTry + zyppng/pipelines/mtry.h + zyppng/pipelines/Redo + zyppng/pipelines/redo.h + zyppng/pipelines/Transform + zyppng/pipelines/transform.h + zyppng/pipelines/Wait + zyppng/pipelines/wait.h +) + +SET( zyppng_rpc_HEADERS + zyppng/rpc/stompframestream.h +) + +SET( zyppng_rpc_SRCS + zyppng/rpc/stompframestream.cc +) + +SET( zyppng_thread_SRCS + zyppng/thread/asyncqueue.cc + zyppng/thread/wakeup.cpp +) + +SET( zyppng_thread_HEADERS + zyppng/thread/AsyncQueue + zyppng/thread/asyncqueue.h + zyppng/thread/private/asyncqueue_p.h + zyppng/thread/Wakeup + zyppng/thread/wakeup.h +) + +SET( zyppng_thread_private_HEADERS +) + +SET( zyppng_ui_SRCS + zyppng/ui/progressobserver.cc + zyppng/ui/userinterface.cc + zyppng/ui/userrequest.cc +) + +SET( zyppng_ui_HEADERS + zyppng/ui/progressobserver.h + zyppng/ui/ProgressObserver + zyppng/ui/userinterface.h + zyppng/ui/UserInterface + zyppng/ui/userrequest.h + zyppng/ui/UserRequest +) + +SET( zyppng_ui_private_HEADERS + zyppng/ui/private/userinterface_p.h +) + +SET ( zypp_HEADERS + ${zypp_toplevel_headers} + ${zyppng_async_HEADERS} + ${zypp_base_HEADERS} + ${zypp_fs_HEADERS} + ${zypp_rpc_HEADERS} + ${zypp_ui_HEADERS} + ${zypp_url_HEADERS} + ${zypp_parser_HEADERS} + ${zypp_parser_xml_HEADERS} + ${zyppng_base_HEADERS} + ${zyppng_base_private_HEADERS} + ${zyppng_core_HEADERS} + ${zyppng_io_HEADERS} + ${zyppng_io_private_HEADERS} + ${zyppng_meta_HEADERS} + ${zyppng_pipelines_HEADERS} + ${zyppng_rpc_HEADERS} + ${zyppng_thread_HEADERS} + ${zyppng_thread_private_HEADERS} + ${zyppng_ui_HEADERS} + ${zyppng_ui_private_HEADERS} +) + +SET ( zypp_SRCS + ${zypp_toplevel_SRCS} + ${zypp_base_SRCS} + ${zypp_fs_SRCS} + ${zypp_rpc_SRCS} + ${zypp_ui_SRCS} + ${zypp_url_SRCS} + ${zypp_parser_SRCS} + ${zypp_parser_xml_SRCS} + ${zyppng_base_SRCS} + ${zyppng_io_SRCS} + ${zyppng_rpc_SRCS} + ${zyppng_thread_SRCS} + ${zyppng_ui_SRCS} +) + +# Default loggroup for all files +SET_LOGGROUP( "zypp-core" ${zypp_SRCS} ) + +# System libraries +SET(UTIL_LIBRARY util) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) + +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +ADD_LIBRARY( zypp-core STATIC ${zypp_SRCS} ${zypp_HEADERS} ) + +target_link_libraries( zypp-core PRIVATE zypp_lib_compiler_flags ) +target_link_libraries( zypp-core INTERFACE ${LIBGLIB_LIBRARIES} ) +target_link_libraries( zypp-core INTERFACE ${OPENSSL_LIBRARIES} ) +target_link_libraries( zypp-core INTERFACE ${CRYPTO_LIBRARIES} ) +target_link_libraries( zypp-core INTERFACE pthread ) +target_link_libraries( zypp-core INTERFACE ${SIGCPP_LIBRARIES} ) +TARGET_LINK_LIBRARIES( zypp-core INTERFACE ${ZLIB_LIBRARY} ) +TARGET_LINK_LIBRARIES( zypp-core INTERFACE ${UTIL_LIBRARY} ) + +IF (ENABLE_ZSTD_COMPRESSION) + TARGET_LINK_LIBRARIES( zypp-core INTERFACE ${ZSTD_LIBRARY}) +ENDIF (ENABLE_ZSTD_COMPRESSION) + +IF (ENABLE_ZCHUNK_COMPRESSION) + TARGET_LINK_LIBRARIES( zypp-core INTERFACE ${ZCHUNK_LDFLAGS}) +ENDIF(ENABLE_ZCHUNK_COMPRESSION) diff --git a/zypp-core/CheckSum.cc b/zypp-core/CheckSum.cc new file mode 100644 index 0000000..fc138fc --- /dev/null +++ b/zypp-core/CheckSum.cc @@ -0,0 +1,216 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CheckSum.cc + * +*/ +#include +#include + +#include +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const std::string & CheckSum::md5Type() + { return Digest::md5(); } + + const std::string & CheckSum::shaType() + { static std::string _type( "sha" ); return _type; } + + const std::string & CheckSum::sha1Type() + { return Digest::sha1(); } + + const std::string & CheckSum::sha224Type() + { return Digest::sha224(); } + + const std::string & CheckSum::sha256Type() + { return Digest::sha256(); } + + const std::string & CheckSum::sha384Type() + { return Digest::sha384(); } + + const std::string & CheckSum::sha512Type() + { return Digest::sha512(); } + + CheckSum::CheckSum( const std::string & type, const std::string & checksum ) + : _type( str::toLower( type ) ) + , _checksum( checksum ) + { + switch ( checksum.size() ) + { + case 128: + if ( _type == sha512Type() ) + return; + if ( _type.empty() || _type == shaType() ) + { + _type = sha512Type(); + return; + } + // else: dubious + break; + + case 96: + if ( _type == sha384Type() ) + return; + if ( _type.empty() || _type == shaType() ) + { + _type = sha384Type(); + return; + } + // else: dubious + break; + + case 64: + if ( _type == sha256Type() ) + return; + if ( _type.empty() || _type == shaType() ) + { + _type = sha256Type(); + return; + } + // else: dubious + break; + + case 56: + if ( _type == sha224Type() ) + return; + if ( _type.empty() || _type == shaType() ) + { + _type = sha224Type(); + return; + } + // else: dubious + break; + + case 40: + if ( _type == sha1Type() ) + return; + if ( _type.empty() || _type == shaType() ) + { + _type = sha1Type(); + return; + } + // else: dubious + break; + + case 32: + if ( _type == md5Type() ) + return; + if ( _type.empty() ) + { + _type = md5Type(); + return; + } + // else: dubious + break; + + case 0: + return; // empty checksum is ok + break; + + default: + if ( _type.empty() ) + { + WAR << "Can't determine type of " << checksum.size() << " byte checksum '" << _checksum << "'" << endl; + return; + } + // else: dubious + break; + } + + // dubious: Throw on malformed known types, otherwise log a warning. + std::string msg = str::form ( _("Dubious type '%s' for %u byte checksum '%s'"), + _type.c_str(), checksum.size(), _checksum.c_str() ); + if ( _type == md5Type() + || _type == shaType() + || _type == sha1Type() + || _type == sha224Type() + || _type == sha256Type() + || _type == sha384Type() + || _type == sha512Type() ) + { + ZYPP_THROW( CheckSumException( msg ) ); + } + else + { + WAR << msg << endl; + } + } + + CheckSum::CheckSum( const std::string & type_r, std::istream & input_r ) + { + if ( input_r.good() && ! type_r.empty() ) + { + _type = str::toLower( type_r ); + _checksum = Digest::digest( _type, input_r ); + if ( ! input_r.eof() || _checksum.empty() ) + { + _type = _checksum = std::string(); + } + } + } + + std::string CheckSum::type() const + { return _type; } + + std::string CheckSum::checksum() const + { return _checksum; } + + bool CheckSum::empty() const + { return (checksum().empty() || type().empty()); } + + std::string CheckSum::asString() const + { + std::ostringstream str; + str << *this; + return str.str(); + } + + std::ostream & operator<<( std::ostream & str, const CheckSum & obj ) + { + if ( obj.checksum().empty() ) + { + return str << std::string("NoCheckSum"); + } + + return str << ( obj.type().empty() ? std::string("UNKNOWN") : obj.type() ) << '-' << obj.checksum(); + } + + std::ostream & dumpAsXmlOn( std::ostream & str, const CheckSum & obj ) + { + const std::string & type( obj.type() ); + const std::string & checksum( obj.checksum() ); + str << ""; + else + str << ">" << checksum << ""; + return str; + } + + /** \relates CheckSum */ + bool operator==( const CheckSum & lhs, const CheckSum & rhs ) + { return lhs.checksum() == rhs.checksum() && lhs.type() == rhs.type(); } + + /** \relates CheckSum */ + bool operator!=( const CheckSum & lhs, const CheckSum & rhs ) + { return ! ( lhs == rhs ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/CheckSum.h b/zypp-core/CheckSum.h new file mode 100644 index 0000000..4cad37b --- /dev/null +++ b/zypp-core/CheckSum.h @@ -0,0 +1,139 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/CheckSum.h + * +*/ +#ifndef ZYPP_CORE_CHECKSUM_H +#define ZYPP_CORE_CHECKSUM_H + +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + struct CheckSumException : public Exception + { + CheckSumException( const std::string & msg ) + : Exception( msg ) + {} + }; + + class CheckSum + { + public: + /** Default Ctor: empty checksum. */ + CheckSum() + {} + /** + * Creates a checksum for algorithm \param type. + * \throws CheckSumException if the checksum is invalid and can't be constructed + */ + CheckSum( const std::string & type, const std::string & checksum ); + /** + * Creates a checksum auto probing the algorithm type. + * \throws CheckSumException if the checksum is invalid and can't be constructed + */ + CheckSum( const std::string & checksum ) + : CheckSum( std::string(), checksum ) + {} + + /** + * Reads the content of \param input_r and computes the checksum. + */ + CheckSum( const std::string & type, std::istream & input_r ); + + /** Ctor from temporary istream */ + CheckSum( const std::string & type, std::istream && input_r ) + : CheckSum( type, input_r ) + {} + + public: + static const std::string & md5Type(); + static const std::string & shaType(); + static const std::string & sha1Type(); + static const std::string & sha224Type(); + static const std::string & sha256Type(); + static const std::string & sha384Type(); + static const std::string & sha512Type(); + + /** \name Creates a checksum for algorithm \param type. */ + //@{ + static CheckSum md5( const std::string & checksum ) { return CheckSum( md5Type(), checksum); } + static CheckSum sha( const std::string & checksum ) { return CheckSum( shaType(), checksum); } + static CheckSum sha1( const std::string & checksum ) { return CheckSum( sha1Type(), checksum); } + static CheckSum sha224( const std::string & checksum ) { return CheckSum( sha224Type(), checksum); } + static CheckSum sha256( const std::string & checksum ) { return CheckSum( sha256Type(), checksum); } + static CheckSum sha384( const std::string & checksum ) { return CheckSum( sha384Type(), checksum); } + static CheckSum sha512( const std::string & checksum ) { return CheckSum( sha512Type(), checksum); } + //@} + + /** \name Reads the content of \param input_r and computes the checksum. */ + //@{ + static CheckSum md5( std::istream & input_r ) { return CheckSum( md5Type(), input_r ); } + static CheckSum sha( std::istream & input_r ) { return CheckSum( sha1Type(), input_r ); } + static CheckSum sha1( std::istream & input_r ) { return CheckSum( sha1Type(), input_r ); } + static CheckSum sha224( std::istream & input_r ) { return CheckSum( sha224Type(), input_r ); } + static CheckSum sha256( std::istream & input_r ) { return CheckSum( sha256Type(), input_r ); } + static CheckSum sha384( std::istream & input_r ) { return CheckSum( sha384Type(), input_r ); } + static CheckSum sha512( std::istream & input_r ) { return CheckSum( sha512Type(), input_r ); } + + static CheckSum md5( std::istream && input_r ) { return CheckSum( md5Type(), std::move(input_r) ); } + static CheckSum sha( std::istream && input_r ) { return CheckSum( sha1Type(), std::move(input_r) ); } + static CheckSum sha1( std::istream && input_r ) { return CheckSum( sha1Type(), std::move(input_r) ); } + static CheckSum sha224( std::istream && input_r ) { return CheckSum( sha224Type(), std::move(input_r) ); } + static CheckSum sha256( std::istream && input_r ) { return CheckSum( sha256Type(), std::move(input_r) ); } + static CheckSum sha384( std::istream && input_r ) { return CheckSum( sha384Type(), std::move(input_r) ); } + static CheckSum sha512( std::istream && input_r ) { return CheckSum( sha512Type(), std::move(input_r) ); } + //@} + + /** \name Reads the content of \param input_r and computes the checksum. */ + //@{ + static CheckSum md5FromString( const std::string & input_r ) { return md5( std::stringstream( input_r ) ); } + static CheckSum shaFromString( const std::string & input_r ) { return sha( std::stringstream( input_r ) ); } + static CheckSum sha1FromString( const std::string & input_r ) { return sha1( std::stringstream( input_r ) ); } + static CheckSum sha224FromString( const std::string & input_r ) { return sha224( std::stringstream( input_r ) ); } + static CheckSum sha256FromString( const std::string & input_r ) { return sha256( std::stringstream( input_r ) ); } + static CheckSum sha384FromString( const std::string & input_r ) { return sha384( std::stringstream( input_r ) ); } + static CheckSum sha512FromString( const std::string & input_r ) { return sha512( std::stringstream( input_r ) ); } + //@} + + public: + std::string type() const; + std::string checksum() const; + bool empty() const; + + public: + std::string asString() const; + + private: + std::string _type; + std::string _checksum; + }; + + /** \relates CheckSum Stream output. */ + std::ostream & operator<<( std::ostream & str, const CheckSum & obj ); + + /** \relates CheckSum XML output. */ + std::ostream & dumpAsXmlOn( std::ostream & str, const CheckSum & obj ); + + /** \relates CheckSum */ + bool operator==( const CheckSum & lhs, const CheckSum & rhs ); + + /** \relates CheckSum */ + bool operator!=( const CheckSum & lhs, const CheckSum & rhs ); + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CHECKSUM_H diff --git a/zypp-core/Date.cc b/zypp-core/Date.cc new file mode 100644 index 0000000..540850f --- /dev/null +++ b/zypp-core/Date.cc @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Date.cc + * +*/ +#include +//#include + +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + /////////////////////////////////////////////////////////////////// + /// \class LocaleGuard + /// \brief Temporarily adjust Locale + /// \ingroup RAII + struct LocaleGuard + { + LocaleGuard() + { + const char * tmp = ::setlocale( LC_TIME, NULL ); + _mylocale = tmp ? tmp : ""; + + if ( _mylocale.find( "UTF-8" ) == std::string::npos + && _mylocale.find( "utf-8" ) == std::string::npos + && _mylocale != "POSIX" + && _mylocale != "C" + && _mylocale != "" ) + { + // language[_territory][.codeset][@modifier] + // add/exchange codeset with UTF-8 + std::string needLocale = ".UTF-8"; + std::string::size_type loc = _mylocale.find_first_of( ".@" ); + if ( loc != std::string::npos ) + { + // prepend language[_territory] + needLocale = _mylocale.substr( 0, loc ) + needLocale; + loc = _mylocale.find_last_of( '@' ); + if ( loc != std::string::npos ) + { + // append [@modifier] + needLocale += _mylocale.substr( loc ); + } + } + else + { + // append ".UTF-8" + needLocale = _mylocale + needLocale; + } + ::setlocale( LC_TIME, needLocale.c_str() ); + } + else + { + // no need to change the locale + _mylocale.clear(); + } + } + + LocaleGuard(const LocaleGuard &) = delete; + LocaleGuard(LocaleGuard &&) = delete; + LocaleGuard &operator=(const LocaleGuard &) = delete; + LocaleGuard &operator=(LocaleGuard &&) = delete; + + ~LocaleGuard() { + if ( ! _mylocale.empty() ) + ::setlocale( LC_TIME, _mylocale.c_str() ); + } + + private: + std::string _mylocale; + }; + /////////////////////////////////////////////////////////////////// + + inline bool isDST( struct tm & tm ) + { + time_t t = ::mktime( &tm ); + struct tm *tm2 = ::localtime( &t ); + return ( tm2 && tm2->tm_isdst > 0 ); + } + + inline const char * _dateFormat( Date::DateFormat dateFormat_r ) + { + static const char * fmt[] = { + "", ///< "" + "%Y-%m-%d", ///< 2014-02-07 + "%Y-%m", ///< 2014-02 + "%Y", ///< 2014 + "%G-W%V", ///< 2014-W06 + "%G-W%V-%u", ///< 2014-W06-5 (1 is Monday) + "%Y-%j", ///< 2014-038 + }; + return fmt[dateFormat_r.asIntegral()]; + } + + inline const char * _timeFormat( Date::TimeFormat timeFormat_r ) + { + static const char * fmt[] = { + "", ///< "" + "%H:%M:%S", ///< 07:06:41 + "%H:%M", ///< 07:06 + "%H", ///< 07 + }; + return fmt[timeFormat_r.asIntegral()]; + } + + inline const char * _timeZoneFormat( Date::TimeZoneFormat timeZoneFormat_r ) + { + static const char * fmt[] = { + "", ///< "" + " %Z", ///< UTC, CET, ... + "%z", ///< +0000 + }; + return fmt[timeZoneFormat_r.asIntegral()]; + } + + inline std::string doForm( const std::string & format_r, Date::TimeBase base_r, const Date::ValueType & date_r ) + { + if ( ! date_r ) + return "0"; + + LocaleGuard guard; + static char buf[512]; + if ( ! strftime( buf, 512, format_r.c_str(), (base_r == Date::TB_UTC ? gmtime : localtime)( &date_r ) ) ) + *buf = '\0'; + else + { + // strip a trailing '00' in a timeZoneFormat + unsigned l = ::strlen( buf ); + if ( l >= 5 + && ( buf[l-1] == '0' ) + && ( buf[l-2] == '0' ) + && ( buf[l-5] == '+' || buf[l-5] == '-') ) + buf[l-2] = '\0'; + } + return buf; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + const Date::ValueType Date::second; + const Date::ValueType Date::minute; + const Date::ValueType Date::hour; + const Date::ValueType Date::day; + const Date::ValueType Date::month28; + const Date::ValueType Date::month29; + const Date::ValueType Date::month30; + const Date::ValueType Date::month31; + const Date::ValueType Date::month; + const Date::ValueType Date::year365; + const Date::ValueType Date::year366; + const Date::ValueType Date::year; + + Date::Date( const std::string & seconds_r ) + { str::strtonum( seconds_r, _date ); } + + Date::Date( const std::string & date_str, const std::string & format ) + : _date( Date( date_str, format, TB_LOCALTIME ) ) + {} + + Date::Date( const std::string & date_str, const std::string & format, Date::TimeBase base_r ) + : _date(0) + { + LocaleGuard guard; + + struct tm tm = {0,0,0,0,0,0,0,0,0,0,0}; + char * res = ::strptime( date_str.c_str(), format.c_str(), &tm ); + if (res == NULL) + throw DateFormatException( str::form( "Invalid date format: '%s'", date_str.c_str() ) ); + + if ( isDST(tm) ) + tm.tm_isdst = 1; + _date = (base_r == TB_UTC ? ::timegm : ::timelocal)( &tm ); + } + + std::string Date::form( const std::string & format_r, Date::TimeBase base_r ) const + { return doForm( format_r, base_r, _date ); } + + std::string Date::print( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const + { + str::Str str; + if ( dateFormat_r != DateFormat::none ) + str << _dateFormat( dateFormat_r ); + if ( timeFormat_r != TimeFormat::none ) + { + if ( dateFormat_r != DateFormat::none ) + str << ' '; + str << _timeFormat( timeFormat_r ); + if ( timeZoneFormat_r != TimeZoneFormat::none ) + str << _timeZoneFormat( timeZoneFormat_r ); + } + return doForm( str, base_r, _date ); + } + + std::string Date::printISO( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r ) const + { + str::Str str; + if ( dateFormat_r != DateFormat::none ) + str << _dateFormat( dateFormat_r ); + if ( timeFormat_r != TimeFormat::none ) + { + if ( dateFormat_r != DateFormat::none ) + str << 'T'; + str << _timeFormat( timeFormat_r ); + switch ( timeZoneFormat_r.asEnum() ) + { + case TimeZoneFormat::none: + break; + case TimeZoneFormat::name: + if ( base_r == TB_UTC ) + { + str << 'Z'; + break; + } + // else: FALLTHROUGH and print offset! + case TimeZoneFormat::offset: + str << _timeZoneFormat( TimeZoneFormat::offset ); + break; + } + } + return doForm( str, base_r, _date ); + } + + std::ostream & dumpAsXmlOn( std::ostream & str, const Date & obj, const std::string & name_r ) + { + return xmlout::node( str, name_r, { + { "time_t", Date::ValueType(obj) }, + { "text", obj.printISO( Date::TB_UTC ) }, + } ); + } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/Date.h b/zypp-core/Date.h new file mode 100644 index 0000000..fb053df --- /dev/null +++ b/zypp-core/Date.h @@ -0,0 +1,271 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Date.h + * +*/ +#ifndef ZYPP_DATE_H +#define ZYPP_DATE_H + +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Date + // + /** Store and operate on date (time_t). + */ + class ZYPP_API Date + { + friend std::ostream & operator<<( std::ostream & str, const Date & obj ); + + public: + + using ValueType = time_t; + using Duration = time_t; + + static const ValueType second = 1; + static const ValueType minute = 60; + static const ValueType hour = 3600; + static const ValueType day = 86400; + static const ValueType month28 = 2419200; + static const ValueType month29 = 2505600; + static const ValueType month30 = 2592000; + static const ValueType month31 = 2678400; + static const ValueType month = month30; + static const ValueType year365 = 31536000; + static const ValueType year366 = 31622400; + static const ValueType year = year365; + + enum TimeBase { TB_LOCALTIME, TB_UTC }; + + /** Default ctor: 0 */ + Date() + : _date( 0 ) + {} + /** Ctor taking time_t value. */ + Date( ValueType date_r ) + : _date( date_r ) + {} + /** Ctor taking time_t value as string. */ + explicit Date( const std::string & seconds_r ); + + /** + * Ctor from a \a date_str (in localtime) formatted using \a format. + * + * \throws DateFormatException in case \a date_str cannot be + * parsed according to \a format. + */ + Date( const std::string & date_str, const std::string & format ); + /** \overload with explicitly given \ref TimeBase. */ + Date( const std::string & date_str, const std::string & format, TimeBase base_r ); + + /** Return the current time. */ + static Date now() + { return ::time( 0 ); } + + public: + /** Conversion to time_t. */ + operator ValueType() const + { return _date; } + + /** \name Arithmetic operations. */ + //@{ + Date operator+( const time_t rhs ) const { return _date + rhs; } + Date operator-( const time_t rhs ) const { return _date - rhs; } + Date operator*( const time_t rhs ) const { return _date * rhs; } + Date operator/( const time_t rhs ) const { return _date / rhs; } + + Date & operator+=( const time_t rhs ) { _date += rhs; return *this; } + Date & operator-=( const time_t rhs ) { _date -= rhs; return *this; } + Date & operator*=( const time_t rhs ) { _date *= rhs; return *this; } + Date & operator/=( const time_t rhs ) { _date /= rhs; return *this; } + + Date & operator++(/*prefix*/) { _date += 1; return *this; } + Date & operator--(/*prefix*/) { _date -= 1; return *this; } + + Date operator++(int/*postfix*/) { return _date++; } + Date operator--(int/*postfix*/) { return _date--; } + //@} + + public: + /** Return string representation according to format as localtime. + * \see 'man strftime' (which is used internaly) for valid + * conversion specifiers in format. + * + * \return An empty string on illegal format, "0" if date is unspecified. + **/ + std::string form( const std::string & format_r ) const + { return form( format_r, TB_LOCALTIME ); } + /** \overload with explicitly given \ref TimeBase. */ + std::string form( const std::string & format_r, TimeBase base_r ) const; + + /** Default string representation of Date. + * The preferred date and time representation for the current locale. + **/ + std::string asString() const + { return form( "%c" ); } + + /** Convert to string representation of calendar time in + * numeric form (like "1029255142"). + **/ + std::string asSeconds() const + { return form( "%s" ); } + + public: + /** \name Printing in various predefined formats */ + //@{ + /** Date formats for printing (use like 'enum class \ref DateFormat') */ + struct EDateFormatDef { enum Enum { + none, ///< "" + calendar, ///< 2014-02-07 + month, ///< 2014-02 + year, ///< 2014 + week, ///< 2014-W06 + weekday, ///< 2014-W06-5 (1 is Monday) + ordinal, ///< 2014-038 + };}; + using DateFormat = base::EnumClass; ///< 'enum class DateFormat' + + /** Time formats for printing (use like 'enum class \ref TimeFormat') */ + struct ETimeFormatDef { enum Enum { + none, ///< "" + seconds, ///< 07:06:41 + minutes, ///< 07:06 + hours, ///< 07 + };}; + using TimeFormat = base::EnumClass; ///< 'enum class TimeFormat' + + /** Timezone indicator for printing (use like 'enum class \ref TimeZoneFormat') */ + struct ETimeZoneFormatDef { enum Enum { + none, ///< "" + name, ///< UTC, CET, ... + offset, ///< +00[:00] + };}; + using TimeZoneFormat = base::EnumClass; ///< 'enum class TimeZoneFormat' + + /** Default format is '2014-02-07 07:06:41 CET' + * The default is \ref DateFormat::calendar, \ref TimeFormat::seconds, \ref TimeZoneFormat::name and + * \ref TB_LOCALTIME. For other formats you don't have to repeat all the defaults, just pass the + * values where you differ. + */ + std::string print( DateFormat dateFormat_r = DateFormat::calendar, TimeFormat timeFormat_r = TimeFormat::seconds, TimeZoneFormat timeZoneFormat_r = TimeZoneFormat::name, TimeBase base_r = TB_LOCALTIME ) const; + /** \overload */ + std::string print( TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r = TimeZoneFormat::name, TimeBase base_r = TB_LOCALTIME ) const + { return print( DateFormat::calendar, timeFormat_r, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string print( DateFormat dateFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r = TB_LOCALTIME ) const + { return print( dateFormat_r, TimeFormat::seconds, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string print( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeBase base_r ) const + { return print( dateFormat_r, timeFormat_r, TimeZoneFormat::name, base_r ); } + /** \overload */ + std::string print( TimeZoneFormat timeZoneFormat_r, TimeBase base_r = TB_LOCALTIME ) const + { return print( DateFormat::calendar, TimeFormat::seconds, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string print( TimeFormat timeFormat_r, TimeBase base_r ) const + { return print( DateFormat::calendar, timeFormat_r, TimeZoneFormat::name, base_r ); } + /** \overload */ + std::string print( DateFormat dateFormat_r, TimeBase base_r ) const + { return print( dateFormat_r, TimeFormat::seconds, TimeZoneFormat::name, base_r ); } + /** \overload */ + std::string print( TimeBase base_r ) const + { return print( DateFormat::calendar, TimeFormat::seconds, TimeZoneFormat::name, base_r ); } + + /** Convenience for printing the date only ['2014-02-07'] + * The default is \ref DateFormat::calendar and \ref TB_LOCALTIME + */ + std::string printDate( DateFormat dateFormat_r = DateFormat::calendar, TimeBase base_r = TB_LOCALTIME ) const + { return print( dateFormat_r, TimeFormat::none, TimeZoneFormat::none, base_r ); } + /** \overload */ + std::string printDate( TimeBase base_r ) const + { return printDate( DateFormat::calendar, base_r ); } + + /** Convenience for printing the time only ['07:06:41 CET'] + * The default is \ref DateFormat::calendar and \ref TB_LOCALTIME + */ + std::string printTime( TimeFormat timeFormat_r = TimeFormat::seconds, TimeZoneFormat timeZoneFormat_r = TimeZoneFormat::name, TimeBase base_r = TB_LOCALTIME ) const + { return print( DateFormat::none, timeFormat_r, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string printTime( TimeZoneFormat timeZoneFormat_r , TimeBase base_r = TB_LOCALTIME ) const + { return printTime( TimeFormat::seconds, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string printTime( TimeFormat timeFormat_r , TimeBase base_r ) const + { return printTime( timeFormat_r, TimeZoneFormat::name, base_r ); } + /** \overload */ + std::string printTime( TimeBase base_r ) const + { return printTime( TimeFormat::seconds, TimeZoneFormat::name, base_r ); } + + /** Default ISO 8601 format is '2014-02-07T07:06:41+01' + * \note As timezone names are not used in ISO, \ref TimeZoneFormat::name is the same as + * \ref TimeZoneFormat::offset when printing in \ref TB_LOCALTIME. When printing \ref TB_UTC + * it uses a \c 'Z' to indicate UTC (Zulu time) rather than printing \c '+00'. + */ + std::string printISO( DateFormat dateFormat_r = DateFormat::calendar, TimeFormat timeFormat_r = TimeFormat::seconds, TimeZoneFormat timeZoneFormat_r = TimeZoneFormat::name, TimeBase base_r = TB_LOCALTIME ) const; + /** \overload */ + std::string printISO( TimeFormat timeFormat_r, TimeZoneFormat timeZoneFormat_r = TimeZoneFormat::name, TimeBase base_r = TB_LOCALTIME ) const + { return printISO( DateFormat::calendar, timeFormat_r, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string printISO( DateFormat dateFormat_r, TimeZoneFormat timeZoneFormat_r, TimeBase base_r = TB_LOCALTIME ) const + { return printISO( dateFormat_r, TimeFormat::seconds, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string printISO( DateFormat dateFormat_r, TimeFormat timeFormat_r, TimeBase base_r ) const + { return printISO( dateFormat_r, timeFormat_r, TimeZoneFormat::name, base_r ); } + /** \overload */ + std::string printISO( TimeZoneFormat timeZoneFormat_r, TimeBase base_r = TB_LOCALTIME ) const + { return printISO( DateFormat::calendar, TimeFormat::seconds, timeZoneFormat_r, base_r ); } + /** \overload */ + std::string printISO( TimeFormat timeFormat_r, TimeBase base_r ) const + { return printISO( DateFormat::calendar, timeFormat_r, TimeZoneFormat::name, base_r ); } + /** \overload */ + std::string printISO( DateFormat dateFormat_r, TimeBase base_r ) const + { return printISO( dateFormat_r, TimeFormat::seconds, TimeZoneFormat::name, base_r ); } + /** \overload */ + std::string printISO( TimeBase base_r ) const + { return printISO( DateFormat::calendar, TimeFormat::seconds, TimeZoneFormat::name, base_r ); } + //@} + + private: + /** Calendar time. + * The number of seconds elapsed since 00:00:00 on January 1, 1970, + * Coordinated Universal Time (UTC). + **/ + ValueType _date; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Date Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Date & obj ) + { return str << obj.asString(); } + + /** \relates Date XML output. + * Print \c time_t and \c text attribute. Allow alternate node name [date]. + */ + std::ostream & dumpAsXmlOn( std::ostream & str, const Date & obj, const std::string & name_r = "date" ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + class ZYPP_API DateFormatException : public Exception + { + public: + DateFormatException( const std::string & msg ) : Exception( msg ) + {} + }; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_DATE_H diff --git a/zypp-core/Digest.cc b/zypp-core/Digest.cc new file mode 100644 index 0000000..0de24e1 --- /dev/null +++ b/zypp-core/Digest.cc @@ -0,0 +1,380 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Digest.cc + * + * \todo replace by Blocxx + * +*/ + +#include // snprintf + +#include +#include +#include +#if OPENSSL_API_LEVEL < 30000 +#include +#else +#include +#endif + +#include +#include + +#include +#include + +#include +#include +#include +#include + +using std::endl; + +namespace zypp { + + const std::string & Digest::md5() + { static std::string _type( "md5" ); return _type; } + + const std::string & Digest::sha1() + { static std::string _type( "sha1" ); return _type; } + + const std::string & Digest::sha224() + { static std::string _type( "sha224" ); return _type; } + + const std::string & Digest::sha256() + { static std::string _type( "sha256" ); return _type; } + + const std::string & Digest::sha384() + { static std::string _type( "sha384" ); return _type; } + + const std::string & Digest::sha512() + { static std::string _type( "sha512" ); return _type; } + + // private data + class Digest::P + { + P(const P& p) = delete; + const P& operator=(const P& p) = delete; + P(P &&) = delete; + P &operator=(P &&) = delete; + + public: + using EvpDataPtr = zypp::shared_ptr; + P(); + ~P(); + + EvpDataPtr mdctx; +#if OPENSSL_API_LEVEL >= 30000 + AutoDispose md; +#else + const EVP_MD *md; +#endif + unsigned char md_value[EVP_MAX_MD_SIZE]; + unsigned md_len; + zypp::ByteCount bytesHashed; + + bool finalized : 1; + static bool openssl_digests_added; + + std::string name; + + inline bool maybeInit(); + inline void cleanup(); + }; + + + + bool Digest::P::openssl_digests_added = false; + + Digest::P::P() : + md(nullptr), + finalized(false) + { + } + + Digest::P::~P() + { + cleanup(); + } + + bool Digest::P::maybeInit() + { + if(!openssl_digests_added) + { +#if OPENSSL_API_LEVEL >= 30000 + // openssl 3.0 does not use engines anymore, instead we fetch algorithms via a new API + // also it seems initialization is implicit, i'm not sure if that call here is even required. + OPENSSL_init_crypto( OPENSSL_INIT_LOAD_CONFIG, nullptr ); + + // md4 was moved to legacy, we need this for zsync + if ( !OSSL_PROVIDER_load( nullptr, "legacy" ) ) { + ERR << "Failed to load legacy openssl provider" << std::endl; + } + if ( !OSSL_PROVIDER_load( nullptr, "default") ) { + ERR << "Failed to load default openssl provider" << std::endl; + } + + OPENSSL_init_crypto( OPENSSL_INIT_ADD_ALL_DIGESTS, nullptr ); +#else +# if OPENSSL_VERSION_NUMBER >= 0x10100000L + OPENSSL_init_crypto( OPENSSL_INIT_LOAD_CONFIG, nullptr ); +# else + OPENSSL_config(NULL); +# endif + ENGINE_load_builtin_engines(); + ENGINE_register_all_complete(); + OpenSSL_add_all_digests(); +#endif + openssl_digests_added = true; + } + + if(!mdctx) + { +#if OPENSSL_API_LEVEL >= 30000 + // this fetches the new provider based algorithms, returned objects have to be free'd + // i wonder if we could cache the providers instead of querying them for every Digest instance.... + md = AutoDispose( EVP_MD_fetch (nullptr, name.c_str(), nullptr), EVP_MD_free ); +#else + md = EVP_get_digestbyname(name.c_str()); +#endif + if(!md) + return false; + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + EvpDataPtr tmp_mdctx(EVP_MD_CTX_create(), EVP_MD_CTX_destroy); +#else + EvpDataPtr tmp_mdctx(EVP_MD_CTX_new(), EVP_MD_CTX_free); +#endif + if (!tmp_mdctx) + return false; + + if (!EVP_DigestInit_ex(tmp_mdctx.get(), md, NULL)) { + return false; + } + + md_len = 0; + ::memset(md_value, 0, sizeof(md_value)); + + bytesHashed = 0; + + mdctx.swap(tmp_mdctx); + } + return true; + } + + void Digest::P::cleanup() + { +#if OPENSSL_API_LEVEL >= 30000 + md.reset(); +#endif + mdctx.reset(); + finalized = false; + } + + Digest::Digest() : _dp( std::make_unique

() ) + { + } + + Digest::Digest(Digest &&other) noexcept : _dp( std::move(other._dp) ) + { + } + + Digest &Digest::operator=(Digest &&other) noexcept + { + _dp = std::move( other._dp ); + return *this; + } + + Digest::~Digest() + { } + + bool Digest::create(const std::string& name) + { + if(name.empty()) return false; + + if(_dp->mdctx) + _dp->cleanup(); + + _dp->name = name; + + return _dp->maybeInit(); + } + + const std::string& Digest::name() + { + return _dp->name; + } + + bool Digest::reset() + { + if (!_dp->mdctx) + return false; + if(!_dp->finalized) + { + (void)EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len); + _dp->finalized = true; + } + if(!EVP_DigestInit_ex(_dp->mdctx.get(), _dp->md, NULL)) + return false; + _dp->finalized = false; + _dp->bytesHashed = 0; + return true; + } + + Digest Digest::clone() const + { + Digest d; + if ( !_dp->name.empty () ) + d.create ( _dp->name ); + return d; + } + + std::string Digest::digest() + { + return digestVectorToString( digestVector() ); + } + + std::string Digest::digestVectorToString(const UByteArray &vec) + { + if ( vec.empty() ) + return std::string(); + + std::vector resData ( vec.size()*2 + 1, '\0' ); + char *mdtxt = &resData[0]; + for(unsigned i = 0; i < vec.size(); ++i) + { + ::snprintf( mdtxt+(i*2), 3, "%02hhx", vec[i]); + } + return std::string( resData.data() ); + } + +#ifdef __cpp_lib_string_view + namespace { + template + BArr hexStrToBArr ( std::string_view str ) { + BArr bytes; + for ( std::string::size_type i = 0; i < str.length(); i+=2 ) + { + #define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \ + : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \ + : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \ + : -1) + int v = c2h(str[i]); + if (v < 0) + return {}; + bytes.push_back(v); + v = c2h(str[i+1]); + if (v < 0) + return {}; + bytes.back() = (bytes.back() << 4) | v; + #undef c2h + } + return bytes; + } + } // namespace + + ByteArray Digest::hexStringToByteArray(std::string_view str) + { + return hexStrToBArr( std::move(str) ); + } + + UByteArray Digest::hexStringToUByteArray( std::string_view str ) + { + return hexStrToBArr( std::move(str) ); + } +#endif + + UByteArray Digest::digestVector() + { + UByteArray r; + if(!_dp->maybeInit()) + return r; + + if(!_dp->finalized) + { + if(!EVP_DigestFinal_ex(_dp->mdctx.get(), _dp->md_value, &_dp->md_len)) + return r; + _dp->finalized = true; + } + r.reserve(_dp->md_len); + for(unsigned i = 0; i < _dp->md_len; ++i) + r.push_back(_dp->md_value[i]); + return r; + } + + bool Digest::update(const char* bytes, size_t len) + { + if(!bytes) + { + return false; + } + + if(!_dp->maybeInit()) + return false; + + if(_dp->finalized) + { + _dp->cleanup(); + if(!_dp->maybeInit()) + return false; + + } + if(!EVP_DigestUpdate(_dp->mdctx.get(), reinterpret_cast(bytes), len)) + return false; + + _dp->bytesHashed += len; + return true; + } + + bool Digest::update(std::istream &is, size_t bufsize) + { + if( !is ) + return false; + + char buf[bufsize]; + + while(is.good()) + { + size_t readed = 0; + is.read(buf, bufsize); + readed = is.gcount(); + if(readed && !update(buf, readed)) + return false; + } + + return true; + } + + ByteCount Digest::bytesHashed() const + { + return _dp->bytesHashed; + } + + std::string Digest::digest(const std::string& name, std::istream& is, size_t bufsize) + { + if(name.empty() || !is) + return std::string(); + + Digest digest; + if(!digest.create(name)) + return std::string(); + + if ( !digest.update( is, bufsize )) + return std::string(); + + return digest.digest(); + } + + std::string Digest::digest( const std::string & name, const std::string & input, size_t bufsize ) + { + std::istringstream is( input ); + return digest( name, is, bufsize ); + } + +} // namespace zypp diff --git a/zypp-core/Digest.h b/zypp-core/Digest.h new file mode 100644 index 0000000..dfcda18 --- /dev/null +++ b/zypp-core/Digest.h @@ -0,0 +1,176 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/Digest.h + * + * \todo replace by Blocxx + * +*/ + +#ifndef ZYPP_CORE_DIGEST_H +#define ZYPP_CORE_DIGEST_H + +#include +#include +#include +#include + +#include +#include +#include + +namespace zypp { + + /** \brief Compute Message Digests (MD5, SHA1 etc) + * + * The computation works by initializing the algorithm using create(). This + * will construct an internal state. successive calls to update() deliver the + * data for which the digest is to be computed. After all data has been + * deliverd, a call to digest() finalizes the computation and returns the + * result + * */ + class Digest + { + private: + class P; + std::unique_ptr

_dp; + + // disabled + Digest(const Digest& d) = delete; + // disabled + const Digest& operator=(const Digest& d) = delete; + + public: + + // moving is fine + Digest(Digest&& other) noexcept; + Digest& operator=( Digest&& other) noexcept; + + /** \name Well known digest algorithm names. */ + //@{ + /** md5 */ + static const std::string & md5(); + /** sha1 */ + static const std::string & sha1(); + /** sha224 */ + static const std::string & sha224(); + /** sha256 */ + static const std::string & sha256(); + /** sha384 */ + static const std::string & sha384(); + /** sha512 */ + static const std::string & sha512(); + //@} + + public: + Digest(); + ~Digest(); + + /** \brief initialize creation of a new message digest + * + * Since openssl is used as backend you may use anything that openssl + * supports (see man 1 dgst). Common examples are md5 or sha1. sha1 + * should be preferred when creating digests to verify the authenticity + * of something. + * + * successive calls to this funcion will destroy the internal state and + * reinit from scratch + * + * @param name name of the message digest algorithm. + * @return whether an error occured + * */ + bool create(const std::string& name); + + /** \brief get the name of the current digest algorithm */ + const std::string& name(); + + /** \brief feed data into digest computation algorithm + * @param bytes + * @param len + * @return whether an error occured + * */ + bool update(const char* bytes, size_t len); + + /** \brief feed data into digest computation algorithm + * @param is + * @param bufsize + * @return whether an error occured + * */ + bool update(std::istream& is, size_t bufsize = 4096); + + /** + * Returns the number of input bytes that have been added to the hash + */ + zypp::ByteCount bytesHashed () const; + + /** \brief get hex string representation of the digest + * + * this function will finalize the digest computation. calls to update + * after this function will start from scratch + * + * @return hex string representation of the digest + * */ + std::string digest(); + + /** \brief get hex string representation of the digest vector given as parameter + * + * @return hex string representation of the digest + * */ + static std::string digestVectorToString ( const UByteArray &vec ); + +#ifdef __cpp_lib_string_view + /** \brief convert the hex string representation of the digest vector given as parameter into the actual byte array representation + * + * @return hex string representation of the digest + * */ + static ByteArray hexStringToByteArray ( std::string_view str ); + static UByteArray hexStringToUByteArray ( std::string_view str ); +#endif + + /** \brief get vector of unsigned char representation of the digest + * + * this function will finalize the digest computation. calls to update + * after this function will start from scratch + * + * @return vector representation of the digest + * */ + UByteArray digestVector(); + + /** \brief reset internal digest state + * + * this function is equivalent to calling create() with an unchanged name, + * but it may be implemented in a more efficient way. + */ + bool reset(); + + /** + * Returns a clone of the current Digest and returns it. + * This is the same as manually creating a Digest with the same name ( so no + * checksum calculation state is copied ) + */ + Digest clone() const; + + /** \brief compute digest of a stream. convenience function + * + * calls create, update and digest in one function. The data for the + * computation is read from the stream + * + * @param name name of the digest algorithm, \see create + * @param is an input stream to get the data from + * @param bufsize size of the buffer used for update(). Be careful, this is on the stack. + * @return the digest or empty on error + * */ + static std::string digest(const std::string& name, std::istream& is, size_t bufsize = 4096); + + /** \overload Reading input data from \c string. */ + static std::string digest( const std::string & name, const std::string & input, size_t bufsize = 4096 ); + }; + +} // namespace zypp + +#endif diff --git a/zypp-core/ExternalProgram.cc b/zypp-core/ExternalProgram.cc new file mode 100644 index 0000000..d056499 --- /dev/null +++ b/zypp-core/ExternalProgram.cc @@ -0,0 +1,570 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ExternalProgram.cc +*/ + +#define _GNU_SOURCE 1 // for ::getline + +#include +#include +#include +#include +#include +#include // openpty +#include // setenv +#include // prctl(), PR_SET_PDEATHSIG + +#include // strsignal +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::exec" + +namespace zypp { + + ExternalProgram::ExternalProgram() + {} + + + ExternalProgram::ExternalProgram( const std::string& commandline, + Stderr_Disposition stderr_disp, + bool use_pty, + int stderr_fd, + bool default_locale, + const Pathname & root ) + { + const char *argv[4]; + argv[0] = "/bin/sh"; + argv[1] = "-c"; + argv[2] = commandline.c_str(); + argv[3] = 0; + + start_program( argv, Environment(), stderr_disp, stderr_fd, default_locale, root.c_str(), false, false, use_pty ); + } + + ExternalProgram::ExternalProgram( const Arguments & argv, + Stderr_Disposition stderr_disp, + bool use_pty, + int stderr_fd, + bool default_locale, + const Pathname & root ) + { + const char * argvp[argv.size() + 1]; + unsigned c = 0; + for_( i, argv.begin(), argv.end() ) + { + argvp[c] = i->c_str(); + ++c; + } + argvp[c] = 0; + + start_program( argvp, Environment(), stderr_disp, stderr_fd, default_locale, root.c_str(), false, false, use_pty ); + } + + ExternalProgram::ExternalProgram( const Arguments & argv, + const Environment & environment, + Stderr_Disposition stderr_disp, + bool use_pty, + int stderr_fd, + bool default_locale, + const Pathname & root ) + { + const char * argvp[argv.size() + 1]; + unsigned c = 0; + for_( i, argv.begin(), argv.end() ) + { + argvp[c] = i->c_str(); + ++c; + } + argvp[c] = 0; + + start_program( argvp, environment, stderr_disp, stderr_fd, default_locale, root.c_str(), false, false, use_pty ); + } + + ExternalProgram::ExternalProgram( const char *const *argv, + Stderr_Disposition stderr_disp, + bool use_pty, + int stderr_fd, + bool default_locale, + const Pathname & root ) + { + start_program( argv, Environment(), stderr_disp, stderr_fd, default_locale, root.c_str(), false, false, use_pty ); + } + + ExternalProgram::ExternalProgram( const char *const * argv, + const Environment & environment, + Stderr_Disposition stderr_disp, + bool use_pty, + int stderr_fd, + bool default_locale, + const Pathname & root ) + { + start_program( argv, environment, stderr_disp, stderr_fd, default_locale, root.c_str(), false, false, use_pty ); + } + + + ExternalProgram::ExternalProgram( const char *binpath, + const char *const *argv_1, + bool use_pty ) + { + int i = 0; + while (argv_1[i++]) + ; + const char *argv[i + 1]; + argv[0] = binpath; + memcpy( &argv[1], argv_1, (i - 1) * sizeof (char *) ); + start_program( argv, Environment(), Normal_Stderr, 1, false, NULL, false, false, use_pty ); + } + + ExternalProgram::ExternalProgram( const char *binpath, + const char *const *argv_1, + const Environment & environment, + bool use_pty ) + { + int i = 0; + while (argv_1[i++]) + ; + const char *argv[i + 1]; + argv[0] = binpath; + memcpy( &argv[1], argv_1, (i - 1) * sizeof (char *) ); + start_program( argv, environment, Normal_Stderr, 1, false, NULL, false, false, use_pty ); + } + + ExternalProgram::~ExternalProgram() + { } + + + + void ExternalProgram::start_program( const char *const *argv, + const Environment & environment, + Stderr_Disposition stderr_disp, + int stderr_fd, + bool default_locale, + const char * root , bool switch_pgid, bool die_with_parent , bool usePty ) + { + if ( _backend ) + return; + + // usePty is only supported by the forking backend + if ( usePty ) { + DBG << "usePty was set, forcing the ForkSpawnEngine to start external processes" << std::endl; + _backend = std::make_unique(); + static_cast(*_backend).setUsePty( true ); + } else { + _backend = zyppng::AbstractSpawnEngine::createDefaultEngine(); + } + + // retrieve options at beginning of arglist + const char * redirectStdin = nullptr; // <[file] + const char * redirectStdout = nullptr; // >[file] + const char * chdirTo = nullptr; // #/[path] + + if ( root ) + { + if ( root[0] == '\0' ) + { + root = nullptr; // ignore empty root + } + else if ( root[0] == '/' && root[1] == '\0' ) + { + // If root is '/' do not chroot, but chdir to '/' + // unless arglist defines another dir. + chdirTo = "/"; + root = nullptr; + } + } + + for ( bool strip = false; argv[0] != nullptr; ++argv ) + { + strip = false; + switch ( argv[0][0] ) + { + case '<': + strip = true; + redirectStdin = argv[0]+1; + if ( *redirectStdin == '\0' ) + redirectStdin = "/dev/null"; + break; + + case '>': + strip = true; + redirectStdout = argv[0]+1; + if ( *redirectStdout == '\0' ) + redirectStdout = "/dev/null"; + break; + + case '#': + strip = true; + if ( argv[0][1] == '/' ) // #/[path] + chdirTo = argv[0]+1; + break; + } + if ( ! strip ) + break; + } + + // those are the FDs that the new process will receive + // AutoFD will take care of closing them on our side + zypp::AutoFD stdinFd = -1; + zypp::AutoFD stdoutFd = -1; + zypp::AutoFD stderrFd = -1; + + // those are the fds we will keep, we put them into autofds in case + // we need to return early without actually spawning the new process + zypp::AutoFD childStdinParentFd = -1; + zypp::AutoFD childStdoutParentFd = -1; + + if ( usePty ) + { + + int master_tty = 0, slave_tty = 0; // fds for pair of ttys + + // Create pair of ttys + DBG << "Using ttys for communication with " << argv[0] << endl; + if ( zyppng::eintrSafeCall( ::openpty, &master_tty, &slave_tty, (char *)0, (termios *)0, (winsize *)0) != 0) + { + _backend->setExecError( str::form( _("Can't open pty (%s)."), strerror(errno) ) ); + _backend->setExitStatus( 126 ); + ERR << _backend->execError() << endl; + return; + } + + stdinFd = slave_tty; + stdoutFd = slave_tty; + childStdinParentFd = master_tty; + childStdoutParentFd = master_tty; + } + else + { + if ( redirectStdin ) { + stdinFd = open( redirectStdin, O_RDONLY ); + } else { + int to_external[2]; + if ( pipe (to_external) != 0 ) + { + _backend->setExecError( str::form( _("Can't open pipe (%s)."), strerror(errno) ) ); + _backend->setExitStatus( 126 ); + ERR << _backend->execError() << endl; + return; + } + stdinFd = to_external[0]; + childStdinParentFd = to_external[1]; + } + + if ( redirectStdout ) { + stdoutFd = open( redirectStdout, O_WRONLY|O_CREAT|O_APPEND, 0600 ); + } else { + + int from_external[2]; + // Create pair of pipes + if ( pipe (from_external) != 0 ) + { + _backend->setExecError( str::form( _("Can't open pipe (%s)."), strerror(errno) ) ); + _backend->setExitStatus( 126 ); + ERR << _backend->execError() << endl; + return; + } + stdoutFd = from_external[1]; + childStdoutParentFd = from_external[0]; + } + } + + // Handle stderr + if (stderr_disp == Discard_Stderr) + { + stderrFd = open("/dev/null", O_WRONLY); + } + else if (stderr_disp == Stderr_To_Stdout) + { + stderrFd = *stdoutFd; + //no double close + stderrFd.resetDispose(); + } + else if (stderr_disp == Stderr_To_FileDesc) + { + // Note: We don't have to close anything regarding stderr_fd. + // Our caller is responsible for that. + stderrFd = stderr_fd; + stderrFd.resetDispose(); + } + + if ( root ) + _backend->setChroot( root ); + if ( chdirTo ) + _backend->setWorkingDirectory( chdirTo ); + + _backend->setDieWithParent( die_with_parent ); + _backend->setSwitchPgid( switch_pgid ); + _backend->setEnvironment( environment ); + _backend->setUseDefaultLocale( default_locale ); + + if ( _backend->start( argv, stdinFd, stdoutFd, stderrFd ) ) { + bool connected = true; + if ( childStdoutParentFd != -1 ) { + inputfile = fdopen( childStdoutParentFd, "r" ); + if ( inputfile ) + childStdoutParentFd.resetDispose(); + else + connected = false; + } + if ( childStdinParentFd != -1 ) { + outputfile = fdopen( childStdinParentFd, "w" ); + if ( outputfile ) + childStdinParentFd.resetDispose(); + else + connected = false; + } + if ( not connected ) + { + ERR << "Cannot create streams to external program " << argv[0] << endl; + ExternalProgram::close(); + } + } else { + // Fork failed, exit code and status was set by backend + return; + } + } + + bool ExternalProgram::waitForExit(std::optional timeout) + { + if ( !_backend ) { + // no backend means no running progress, return true + return true; + } + return _backend->waitForExit( timeout ); + } + + int + ExternalProgram::close() + { + if ( !_backend ) { + ExternalDataSource::close(); + return -1; + } + + if ( _backend->isRunning() ) + { + if ( inputFile() ) + { + // Discard any output instead of closing the pipe, + // but watch out for the command exiting while some + // subprocess keeps the filedescriptor open. + setBlocking( false ); + FILE * inputfile = inputFile(); + int inputfileFd = ::fileno( inputfile ); + long delay = 0; + do + { + /* Watch inputFile to see when it has input. */ + GPollFD rfd; + rfd.fd = inputfileFd; + rfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; + rfd.revents = 0; + + // each try increases our wait by 0.1 seconds, until we have + // 1 sec max timout. + gint timeout = delay < 0 ? 1000 : delay*100; + if ( delay >= 0 && ++delay > 9 ) + delay = -1; + + int retval = zyppng::eintrSafeCall( g_poll, &rfd, 1, timeout ); + if ( retval == -1 ) + { + ERR << "select error: " << strerror(errno) << endl; + break; + } + else if ( retval ) + { + // Data is available now. + static size_t linebuffer_size = 0; // static because getline allocs + static char * linebuffer = 0; // and reallocs if buffer is too small + getline( &linebuffer, &linebuffer_size, inputfile ); + // ::feof check is important as select returns + // positive if the file was closed. + if ( ::feof( inputfile ) ) + break; + clearerr( inputfile ); + } + else + { + // No data within time. + if ( ! _backend->isRunning() ) + break; + } + } while ( true ); + } + + // wait for the process to end) + _backend->isRunning( true ); + } + + ExternalDataSource::close(); + return _backend->exitStatus(); + } + + bool + ExternalProgram::kill() + { + if ( _backend && _backend->isRunning() ) + { + if ( ::kill( _backend->pid(), SIGKILL) == -1 ) { + ERR << "Failed to kill PID " << _backend->pid() << " with error: " << Errno() << std::endl; + return false; + } + close(); + } + return true; + } + + bool ExternalProgram::kill(int sig) + { + if ( _backend && _backend->isRunning() ) + { + if ( ::kill( _backend->pid(), sig ) == -1 ) { + ERR << "Failed to kill PID " << _backend->pid() << " with error: " << Errno() << std::endl; + return false; + } + } + return true; + } + + bool + ExternalProgram::running() + { + if ( !_backend ) return false; + return _backend->isRunning(); + } + + pid_t ExternalProgram::getpid() + { + if ( !running() ) + return -1; + return _backend->pid(); + } + + const std::string &ExternalProgram::command() const + { + if ( !_backend ) { + static std::string empty; + return empty; + } + return _backend->executedCommand(); + } + + const std::string &ExternalProgram::execError() const + { + if ( !_backend ) { + static std::string empty; + return empty; + } + return _backend->execError(); + } + + // origfd will be accessible as newfd and closed (unless they were equal) + void ExternalProgram::renumber_fd (int origfd, int newfd) + { + return zyppng::renumberFd( origfd, newfd ); + } + + std::ostream & ExternalProgram::operator>>( std::ostream & out_r ) + { + setBlocking( true ); + for ( std::string line = receiveLine(); line.length(); line = receiveLine() ) + out_r << line; + return out_r; + } + + ////////////////////////////////////////////////////////////////////// + // + // class ExternalProgramWithStderr + // + ////////////////////////////////////////////////////////////////////// + + namespace externalprogram + { + EarlyPipe::EarlyPipe() + { + _fds[R] = _fds[W] = -1; +#ifdef HAVE_PIPE2 + ::pipe2( _fds, O_NONBLOCK ); +#else + ::pipe( _fds ); + ::fcntl(_fds[R], F_SETFD, O_NONBLOCK ); + ::fcntl(_fds[W], F_SETFD, O_NONBLOCK ); +#endif + _stderr = ::fdopen( _fds[R], "r" ); + } + + EarlyPipe::~EarlyPipe() + { + closeW(); + if ( _stderr ) + ::fclose( _stderr ); + } + } // namespace externalprogram + + bool ExternalProgramWithStderr::stderrGetUpTo( std::string & retval_r, const char delim_r, bool returnDelim_r ) + { + if ( ! _stderr ) + return false; + if ( delim_r && ! _buffer.empty() ) + { + // check for delim already in buffer + std::string::size_type pos( _buffer.find( delim_r ) ); + if ( pos != std::string::npos ) + { + retval_r = _buffer.substr( 0, returnDelim_r ? pos+1 : pos ); + _buffer.erase( 0, pos+1 ); + return true; + } + } + ::clearerr( _stderr ); + do { + int ch = fgetc( _stderr ); + if ( ch != EOF ) + { + if ( ch != delim_r || ! delim_r ) + _buffer.push_back( ch ); + else + { + if ( returnDelim_r ) + _buffer.push_back( delim_r ); + break; + } + } + else if ( ::feof( _stderr ) ) + { + if ( _buffer.empty() ) + return false; + break; + } + else if ( errno != EINTR ) + return false; + } while ( true ); + // HERE: we left after readig at least one char (\n) + retval_r.swap( _buffer ); + _buffer.clear(); + return true; + } + + +} // namespace zypp diff --git a/zypp-core/ExternalProgram.h b/zypp-core/ExternalProgram.h new file mode 100644 index 0000000..f1e131a --- /dev/null +++ b/zypp-core/ExternalProgram.h @@ -0,0 +1,327 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ExternalProgram.h +*/ + + +#ifndef ZYPP_EXTERNALPROGRAM_H +#define ZYPP_EXTERNALPROGRAM_H + +#include + +#include +#include +#include +#include + +#include +#include +#include + +namespace zyppng { + class AbstractSpawnEngine; +} + +namespace zypp { + + /** + * @short Execute a program and give access to its io + * An object of this class encapsulates the execution of + * an external program. It starts the program using fork + * and some exec.. call, gives you access to the program's + * stdio and closes the program after use. + * + * \code + * + * const char* argv[] = + * { + * "/usr/bin/foo, + * "--option1", + * "--option2", + * NULL + * }; + * + * ExternalProgram prog( argv, + * ExternalProgram::Discard_Stderr, + * false, -1, true); + * string line; + * for(line = prog.receiveLine(); + * ! line.empty(); + * line = prog.receiveLine() ) + * { + * stream << line; + * } + * prog.close(); + * + * \endcode + */ + class ZYPP_API ExternalProgram : public zypp::externalprogram::ExternalDataSource + { + + public: + + using Arguments = std::vector; + + /** + * Define symbols for different policies on the handling + * of stderr + */ + enum Stderr_Disposition { + Normal_Stderr, + Discard_Stderr, + Stderr_To_Stdout, + Stderr_To_FileDesc + }; + + /** + * For passing additional environment variables to set + */ + using Environment = std::map; + + /** + * Start the external program by using the shell /bin/sh + * with the option -c. You can use io direction symbols < and >. + * @param commandline a shell commandline that is appended to + * /bin/sh -c. + * @param default_locale whether to set LC_ALL=C before starting + * @param root directory to chroot into; or just 'cd' if '/'l; nothing if empty + */ + ExternalProgram (const std::string& commandline, + Stderr_Disposition stderr_disp = Normal_Stderr, + bool use_pty = false, int stderr_fd = -1, bool default_locale = false, + const Pathname& root = ""); + + /** + * Start an external program by giving the arguments as an arry of char *pointers. + * If environment is provided, varaiables will be added to the childs environment, + * overwriting existing ones. + * + * Initial args starting with \c # are discarded but some are treated specially: + * #/[path] - chdir to /[path] before executing + * + * Stdin redirection: If the \b 1st argument starts with a \b '<', the remaining + * part is treated as file opened for reading on standard input (or \c /dev/null + * if empty). + * \code + * // cat file /tmp/x + * const char* argv[] = { "', the remaining + * part is treated as file opened for writing on standard output (or \c /dev/null + * if empty). + */ + + ExternalProgram(); + + ExternalProgram (const Arguments &argv, + Stderr_Disposition stderr_disp = Normal_Stderr, + bool use_pty = false, int stderr_fd = -1, bool default_locale = false, + const Pathname& root = ""); + + ExternalProgram (const Arguments &argv, const Environment & environment, + Stderr_Disposition stderr_disp = Normal_Stderr, + bool use_pty = false, int stderr_fd = -1, bool default_locale = false, + const Pathname& root = ""); + + ExternalProgram (const char *const *argv, + Stderr_Disposition stderr_disp = Normal_Stderr, + bool use_pty = false, int stderr_fd = -1, bool default_locale = false, + const Pathname& root = ""); + + ExternalProgram (const char *const *argv, const Environment & environment, + Stderr_Disposition stderr_disp = Normal_Stderr, + bool use_pty = false, int stderr_fd = -1, bool default_locale = false, + const Pathname& root = ""); + + ExternalProgram (const char *binpath, const char *const *argv_1, + bool use_pty = false); + + + ExternalProgram (const char *binpath, const char *const *argv_1, const Environment & environment, + bool use_pty = false); + + + ~ExternalProgram() override; + +#ifdef __cpp_lib_optional // YAST/PK explicitly use c++11 until 15-SP3 + /*! + * Wait a certain timeout for the programm to complete, if \a timeout + * is not set this will wait forever, 0 will check if the process is still + * running and return immediately with the result, any other value is the + * timeout in ms to wait. + * + * \returns true if the process has exited in time + */ + bool waitForExit ( std::optional timeout = {} ); +#endif + + /** Wait for the progamm to complete. */ + int close() override; + + /** + * Kill the program + */ + bool kill(); + + /** + * Send a signal to the program + */ + bool kill( int sig ); + + /** + * Return whether program is running + */ + bool running(); + + /** + * return pid + * */ + pid_t getpid(); + + /** The command we're executing. */ + const std::string & command() const; + + /** Some detail telling why the execution failed, if it failed. + * Empty if the command is still running or successfully completed. + * + * \li Can't open pty (%s). + * \li Can't open pipe (%s). + * \li Can't fork (%s). + * \li Command exited with status %d. + * \li Command was killed by signal %d (%s). + */ + const std::string & execError() const; + + /** + * origfd will be accessible as newfd and closed (unless they were equal) + */ + static void renumber_fd (int origfd, int newfd); + + public: + + /** + * Redirect all command output to an \c ostream. + * Returns when the command has completed. + * \code + * std::ostringstream s; + * ExternalProgram("pwd") >> s; + * SEC << s.str() << endl; + * \endcode + * \code + * std::ostringstream s; + * ExternalProgram prog("ls -l wrzl"); + * prog >> s; + * if ( prog.close() == 0 ) + * MIL << s.str() << endl; + * else + * ERR << prog.execError() << endl; + * \endcode + */ + std::ostream & operator>>( std::ostream & out_r ); + + private: + std::unique_ptr _backend; + + protected: + + void start_program (const char *const *argv, const Environment & environment, + Stderr_Disposition stderr_disp = Normal_Stderr, + int stderr_fd = -1, bool default_locale = false, + const char* root = NULL, bool switch_pgid = false, bool die_with_parent = false, bool usePty = false ); + + }; + + + namespace externalprogram + { + /** Helper providing pipe FDs for \ref ExternalProgramWithStderr. + * Moved to a basse class because the pipe needs to be initialized + * before the \ref ExternalProgram base class is initialized. + * \see \ref ExternalProgramWithStderr + */ + struct EarlyPipe + { + enum { R=0, W=1 }; + EarlyPipe(); + ~EarlyPipe(); + void closeW() { if ( _fds[W] != -1 ) { ::close( _fds[W] ); _fds[W] = -1; } } + FILE * fStdErr() { return _stderr; } + protected: + FILE * _stderr; + int _fds[2]; + }; + } // namespace externalprogram + + /** ExternalProgram extended to offer reading programs stderr. + * \see \ref ExternalProgram + */ + class ExternalProgramWithStderr : private externalprogram::EarlyPipe, public ExternalProgram + { + public: + ExternalProgramWithStderr( const Arguments & argv_r, bool defaultLocale_r = false, const Pathname & root_r = "" ) + : ExternalProgram( argv_r, Stderr_To_FileDesc, /*use_pty*/false, _fds[W], defaultLocale_r, root_r ) + { _initStdErr(); } + /** \overlocad Convenience taking just the \a root_r. */ + ExternalProgramWithStderr( const Arguments & argv_r, const Pathname & root_r ) + : ExternalProgramWithStderr( argv_r, false, root_r ) + {} + + ExternalProgramWithStderr( const Arguments & argv_r, const Environment & environment_r, bool defaultLocale_r = false, const Pathname & root_r = "" ) + : ExternalProgram( argv_r, environment_r, Stderr_To_FileDesc, /*use_pty*/false, _fds[W], defaultLocale_r, root_r ) + { _initStdErr(); } + /** \overlocad Convenience taking just the \a root_r. */ + ExternalProgramWithStderr( const Arguments & argv_r, const Environment & environment_r, const Pathname & root_r ) + : ExternalProgramWithStderr( argv_r, environment_r, false, root_r ) + {} + public: + /** Return \c FILE* to read programms stderr (O_NONBLOCK set). */ + using externalprogram::EarlyPipe::fStdErr; + + /** Read data up to \c delim_r from stderr (nonblocking). + * \note If \c delim_r is '\0', we read as much data as possible. + * \return \c false if data are not yet available (\c retval_r remains untouched then). + */ + bool stderrGetUpTo( std::string & retval_r, const char delim_r, bool returnDelim_r = false ); + + /** Read next complete line from stderr (nonblocking). + * \return \c false if data are not yet available (\c retval_r remains untouched then). + */ + bool stderrGetline( std::string & retval_r, bool returnDelim_r = false ) + { return stderrGetUpTo( retval_r, '\n', returnDelim_r ); } + + private: + /** Close write end of the pipe (childs end). */ + void _initStdErr() + { closeW(); } + + private: + std::string _buffer; + }; + + /** ExternalProgram extended to change the progress group ID after forking. + * \see \ref ExternalProgram + */ + class ZYPP_LOCAL ExternalProgramWithSeperatePgid : public ExternalProgram + { + public: + ExternalProgramWithSeperatePgid (const char *const *argv, + Stderr_Disposition stderr_disp = Normal_Stderr, + int stderr_fd = -1, bool default_locale = false, + const Pathname& root = "") : ExternalProgram() + { + start_program( argv, Environment(), stderr_disp, stderr_fd, default_locale, root.c_str(), true ); + } + + }; + +} // namespace zypp + +#endif // ZYPP_EXTERNALPROGRAM_H diff --git a/zypp-core/Globals.h b/zypp-core/Globals.h new file mode 100644 index 0000000..84b3754 --- /dev/null +++ b/zypp-core/Globals.h @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/Globals.h + * \brief Provides API related macros. + */ +#ifndef ZYPP_GLOBALS_H +#define ZYPP_GLOBALS_H + +#include // LIBZYPP_ version defines for the LEGACY macro +#include // some macros used almost everywhere + +/** + * Legacy code we still support. + * + * Deprecated items we can't drop immediately because YAST/PK still + * refer to them or they break binary compatibility, should be + * enclosed in `#if LEGACY(#)` where # is either a minor number(<=99), + * a soversion [<=9999] or numversion [<=999999]. + * + */ +#ifndef LIBZYPP_VERSION_MAJOR +#error Missing APIConfig.h include (LIBZYPP_VERSION_MAJOR) +#endif +#ifndef LIBZYPP_SOVERSION +#error Missing APIConfig.h include (LIBZYPP_SOVERSION) +#endif +#ifndef LIBZYPP_VERSION +#error Missing APIConfig.h include (LIBZYPP_VERSION) +#endif +#define LEGACY(CL) ( CL < 100 && LIBZYPP_VERSION_MAJOR <= CL ) || ( CL < 10000 && LIBZYPP_SOVERSION <= CL ) || LIBZYPP_VERSION <= CL + +/** + * Generic helper definitions for shared library support. + * + * \see e.g. http://gcc.gnu.org/wiki/Visibility + * \code + * extern "C" ZYPP_API void function(int a); + * class ZYPP_API SomeClass + * { + * int c; + * ZYPP_LOCAL void privateMethod(); // Only for use within this DSO + * public: + * Person(int _c) : c(_c) { } + * static void foo(int a); + * }; + * \endcode +};*/ +#if __GNUC__ >= 4 + #define ZYPP_DECL_EXPORT __attribute__ ((visibility ("default"))) + #define ZYPP_DECL_IMPORT __attribute__ ((visibility ("default"))) + #define ZYPP_DECL_HIDDEN __attribute__ ((visibility ("hidden"))) +#else + #define ZYPP_DECL_EXPORT + #define ZYPP_DECL_IMPORT + #define ZYPP_DECL_HIDDEN +#endif + +#ifdef ZYPP_DLL //defined if zypp is compiled as DLL + #define ZYPP_API ZYPP_DECL_EXPORT + #define ZYPP_TESTS ZYPP_DECL_EXPORT + #define ZYPP_LOCAL ZYPP_DECL_HIDDEN +#else + #define ZYPP_API ZYPP_DECL_IMPORT + #define ZYPP_TESTS ZYPP_DECL_IMPORT + #define ZYPP_LOCAL +#endif + +// A small set of internal symbols offered to the deptestomatic +// tool (package libzypp-testsuite-tools) to load and evaluate +// solver testcases. +#define ZYPP_API_DEPTESTOMATIC ZYPP_API + +/** + * The ZYPP_DEPRECATED macro can be used to trigger compile-time warnings + * with gcc >= 3.2 when deprecated functions are used. + * + * For non-inline functions, the macro is used at the very end of the + * function declaration, right before the semicolon, unless it's pure + * virtual: + * + * int deprecatedFunc() const ZYPP_DEPRECATED; + * virtual int deprecatedPureVirtualFunc() const ZYPP_DEPRECATED = 0; + * + * Functions which are implemented inline are handled differently: + * the ZYPP_DEPRECATED macro is used at the front, right before the + * return type, but after "static" or "virtual": + * + * ZYPP_DEPRECATED void deprecatedFuncA() { .. } + * virtual ZYPP_DEPRECATED int deprecatedFuncB() { .. } + * static ZYPP_DEPRECATED bool deprecatedFuncC() { .. } + * + * You can also mark whole structs or classes as deprecated, by inserting + * the ZYPP_DEPRECATED macro after the struct/class keyword, but before + * the name of the struct/class: + * + * class ZYPP_DEPRECATED DeprecatedClass { }; + * struct ZYPP_DEPRECATED DeprecatedStruct { }; + * + * However, deprecating a struct/class doesn't create a warning for gcc + * versions <= 3.3 (haven't tried 3.4 yet). If you want to deprecate a class, + * also deprecate all member functions as well (which will cause warnings). + * + */ +#if __GNUC__ - 0 > 3 || (__GNUC__ - 0 == 3 && __GNUC_MINOR__ - 0 >= 2) + #ifndef ZYPP_DEPRECATED + #define ZYPP_DEPRECATED __attribute__ ((deprecated)) + #endif +#else + #ifndef ZYPP_DEPRECATED + #define ZYPP_DEPRECATED + #endif +#endif + +#endif diff --git a/zypp-core/KVMap b/zypp-core/KVMap new file mode 100644 index 0000000..f4ad6b0 --- /dev/null +++ b/zypp-core/KVMap @@ -0,0 +1 @@ +#include "kvmap.h" diff --git a/zypp-core/ManagedFile.h b/zypp-core/ManagedFile.h new file mode 100644 index 0000000..988771a --- /dev/null +++ b/zypp-core/ManagedFile.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ManagedFile.h + * +*/ +#ifndef ZYPP_MANAGEDFILE_H +#define ZYPP_MANAGEDFILE_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** A Pathname plus associated cleanup code to be executed when + * path is no longer needed. + */ + using ManagedFile = AutoDispose; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_MANAGEDFILE_H diff --git a/zypp-core/OnMediaLocation b/zypp-core/OnMediaLocation new file mode 100644 index 0000000..504e404 --- /dev/null +++ b/zypp-core/OnMediaLocation @@ -0,0 +1 @@ +#include "onmedialocation.h" diff --git a/zypp-core/Pathname.cc b/zypp-core/Pathname.cc new file mode 100644 index 0000000..5d96a1d --- /dev/null +++ b/zypp-core/Pathname.cc @@ -0,0 +1,326 @@ +/*---------------------------------------------------------------------\ + | ____ _ __ __ ___ | + | |__ / \ / / . \ . \ | + | / / \ V /| _/ _/ | + | / /__ | | | | | | | + | /_____||_| |_| |_| | + | | + \---------------------------------------------------------------------*/ +/** \file zypp/Pathname.cc + * +*/ +#include +#include + +#include +#include +#include + +using std::string; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace filesystem + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::_assign + // METHOD TYPE : void + // + void Pathname::_assign( const string & name_r ) + { + _name.clear(); + if ( name_r.empty() ) + return; + _name.reserve( name_r.size() ); + + // Collect up to "/.." + enum Pending { + P_none = 0, // "" + P_slash = 1, // "/" + P_dot1 = 2, // "/." + P_dot2 = 3 // "/.." + } pending = P_none; + + // Assert relative path starting with "./" + // We rely on this below! + if ( name_r[0] != '/' ) + { + _name += '.'; + pending = P_slash; + } + + // Lambda handling the "/.." case: + // [] + "/.." ==> [] + // [.] + "/.." ==> [./..] + // [foo] is always [./foo] due to init above + // [*/..] + "/.." ==> [*/../..] + // [*/foo] + "/.." ==> [*] + auto goParent_f = [&](){ + if ( _name.empty() ) + /*NOOP*/; + else if ( _name.size() == 1 ) // content is '.' + _name += "/.."; + else + { + std::string::size_type pos = _name.rfind( '/' ); + if ( pos == _name.size() - 3 && _name[pos+1] == '.' && _name[pos+2] == '.' ) + _name += "/.."; + else + _name.erase( pos ); + } + }; + + for ( char ch : name_r ) + { + switch ( ch ) + { + case '/': + switch ( pending ) + { + case P_none: pending = P_slash; break; + case P_slash: break; + case P_dot1: pending = P_slash; break; + case P_dot2: goParent_f(); pending = P_slash; break; + } + break; + + case '.': + switch ( pending ) + { + case P_none: _name += '.'; break; + case P_slash: pending = P_dot1; break; + case P_dot1: pending = P_dot2; break; + case P_dot2: _name += "/..."; pending = P_none; break; + } + break; + + default: + switch ( pending ) + { + case P_none: break; + case P_slash: _name += '/'; pending = P_none; break; + case P_dot1: _name += "/."; pending = P_none; break; + case P_dot2: _name += "/.."; pending = P_none; break; + } + _name += ch; + break; + } + } + + switch ( pending ) + { + case P_none: break; + case P_slash: if ( _name.empty() ) _name = "/"; break; + case P_dot1: if ( _name.empty() ) _name = "/"; break; + case P_dot2: goParent_f(); if ( _name.empty() ) _name = "/"; break; + } + return; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::dirname + // METHOD TYPE : Pathname + // + Pathname Pathname::dirname( const Pathname & name_r ) + { + if ( name_r.empty() ) + return Pathname(); + + Pathname ret_t( name_r ); + std::string::size_type idx = ret_t._name.find_last_of( '/' ); + + if ( idx == std::string::npos ) { + ret_t._name = "."; + } else if ( idx == 0 ) { + ret_t._name = "/"; + } else { + ret_t._name.erase( idx ); + } + + return ret_t; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::basename + // METHOD TYPE : string + // + string Pathname::basename( const Pathname & name_r ) + { + if ( name_r.empty() ) + return string(); + + string ret_t( name_r.asString() ); + std::string::size_type idx = ret_t.find_last_of( '/' ); + if ( idx != std::string::npos && ( idx != 0 || ret_t.size() != 1 ) ) { + ret_t.erase( 0, idx+1 ); + } + + return ret_t; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::asUrl + // METHOD TYPE : Url + // + Url Pathname::asUrl( const std::string & scheme_r ) const + { + Url ret; + ret.setPathName( asString() ); + ret.setScheme( scheme_r ); + return ret; + } + + Url Pathname::asUrl() const + { return asUrl( "dir" ); } + + Url Pathname::asDirUrl() const + { return asUrl( "dir" ); } + + Url Pathname::asFileUrl() const + { return asUrl( "file" ); } + + + std::string Pathname::showRoot( const Pathname & root_r, const Pathname & path_r ) + { + return str::Str() << "(" << root_r << ")" << path_r; + } + + std::string Pathname::showRootIf( const Pathname & root_r, const Pathname & path_r ) + { + if ( root_r.empty() || root_r == "/" ) + return path_r.asString(); + return showRoot( root_r, path_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::extension + // METHOD TYPE : string + // + string Pathname::extension( const Pathname & name_r ) + { + if ( name_r.empty() ) + return string(); + + string base( basename( name_r ) ); + std::string::size_type pos = base.rfind( '.' ); + switch ( pos ) + { + case 0: + if ( base.size() == 1 ) // . + return string(); + break; + case 1: + if ( base.size() == 2 && base[0] == '.' ) // .. + return string(); + break; + case std::string::npos: + return string(); + break; + } + return base.substr( pos ); + } + + Pathname Pathname::realpath() const + { + std::string real; + if( !empty()) + { + #if __GNUC__ > 2 + /** GNU extension */ + char *ptr = ::realpath(_name.c_str(), NULL); + if( ptr != NULL) + { + real = ptr; + free( ptr); + } + else + /** the SUSv2 way */ + if( EINVAL == errno) + { + char buff[PATH_MAX + 2]; + memset(buff, '\0', sizeof(buff)); + if( ::realpath(_name.c_str(), buff) != NULL) + { + real = buff; + } + } + #else + char buff[PATH_MAX + 2]; + memset(buff, '\0', sizeof(buff)); + if( ::realpath(_name.c_str(), buff) != NULL) + { + real = buff; + } + #endif + } + return zypp::Pathname(real); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::assertprefix + // METHOD TYPE : Pathname + // + Pathname Pathname::assertprefix( const Pathname & root_r, const Pathname & path_r ) + { + if ( root_r.empty() + || path_r == root_r + || str::hasPrefix( path_r.asString(), root_r.asString() ) ) + return path_r; + return root_r / path_r; + } + + Pathname Pathname::stripprefix( const Pathname & root_r, const Pathname & path_r ) + { + if ( root_r.emptyOrRoot() ) + return path_r; + if ( root_r == path_r ) + return "/"; + std::string rest( str::stripPrefix( path_r.asString(), root_r.asString() ) ); + if ( rest[0] == '/' ) // needs to be a dir prefix! + return rest; + return path_r; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::cat + // METHOD TYPE : Pathname + // + Pathname Pathname::cat( const Pathname & name_r, const Pathname & add_tv ) + { + if ( add_tv.empty() ) + return name_r; + if ( name_r.empty() ) + return add_tv; + + string ret_ti( name_r._name ); + if( add_tv._name[0] != '/' ) + ret_ti += '/'; + return ret_ti + add_tv._name; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Pathname::Extend + // METHOD TYPE : Pathname + // + Pathname Pathname::extend( const Pathname & l, const string & r ) + { + return l.asString() + r; + } + + ///////////////////////////////////////////////////////////////// + } // namespace filesystem + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/Pathname.h b/zypp-core/Pathname.h new file mode 100644 index 0000000..60ac496 --- /dev/null +++ b/zypp-core/Pathname.h @@ -0,0 +1,222 @@ + +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Pathname.h + * +*/ +#ifndef ZYPP_PATHNAME_H +#define ZYPP_PATHNAME_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class Url; + + /////////////////////////////////////////////////////////////////// + namespace filesystem + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Pathname + // + /** Pathname. + * + * \note For convenience Pathname is available as zypp::Pathname too. + * + * Always stores normalized paths (no inner '.' or '..' components + * and no consecutive '/'es). Concatenation automatically adds + * the path separator '/'. + * + * \todo Add support for handling extensions incl. stripping + * extensions from basename (basename("/path/foo.baa", ".baa") ==> "foo") + */ + class ZYPP_API Pathname + { + public: + /** Default ctor: an empty path. */ + Pathname() + {} + + /** Ctor from string. */ + Pathname( const std::string & name_r ) + { _assign( name_r ); } + + /** Ctor from char*. */ + Pathname( const char * name_r ) + { _assign( name_r ? name_r : "" ); } + + /** Copy Ctor */ + Pathname( const Pathname & rhs ) + : _name( rhs._name ) + {} + + /** Swap */ + friend void swap( Pathname & lhs, Pathname & rhs ) noexcept + { + using std::swap; + swap( lhs._name, rhs._name ); + } + + /** Move Ctor */ + Pathname( Pathname && tmp ) noexcept + : _name( std::move( tmp._name ) ) + {} + + /** Assign */ + Pathname & operator=( Pathname rhs ) + { swap( *this, rhs ); return *this; } + + /** Concatenate and assign. \see cat */ + Pathname & operator/=( const Pathname & path_tv ) + { return( *this = cat( *this, path_tv ) ); } + + /** Concatenate and assign. \see cat + * \deprecated: use /= + */ + Pathname & operator+=( const Pathname & path_tv ) + { return( *this = cat( *this, path_tv ) ); } + + /** String representation. */ + const std::string & asString() const + { return _name; } + + /** String representation as "(root)/path" */ + static std::string showRoot( const Pathname & root_r, const Pathname & path_r ); + + /** String representation as "(root)/path", unless \a root is \c "/" or empty. */ + static std::string showRootIf( const Pathname & root_r, const Pathname & path_r ); + + /** Url representation using \c scheme_r schema . */ + Url asUrl( const std::string & scheme_r ) const; + /** \overload using \c dir schema. */ + Url asUrl() const; + /** \overload using \c dir schema. */ + Url asDirUrl() const; + /** \overload using \c file schema. */ + Url asFileUrl() const; + + /** String representation. */ + const char * c_str() const + { return _name.c_str(); } + + /** Test for an empty path. */ + bool empty() const { return _name.empty(); } + /** Test for an absolute path. */ + bool absolute() const { return *_name.c_str() == '/'; } + /** Test for a relative path. */ + bool relative() const { return !( absolute() || empty() ); } + + /** Test for "" or "/". */ + bool emptyOrRoot() const { return( _name.empty() || _name == "/" ); } + + /** Return all but the last component od this path. */ + Pathname dirname() const { return dirname( *this ); } + static Pathname dirname( const Pathname & name_r ); + + /** Return the last component of this path. */ + std::string basename() const { return basename( *this ); } + static std::string basename( const Pathname & name_r ); + + /** Return all of the characters in name after and including + * the last dot in the last element of name. If there is no dot + * in the last element of name then returns the empty string. + */ + std::string extension() const { return extension( *this ); } + static std::string extension( const Pathname & name_r ); + + /** Return this path, adding a leading '/' if relative. */ + Pathname absolutename() const { return absolutename( *this ); } + static Pathname absolutename( const Pathname & name_r ) + { return name_r.relative() ? cat( "/", name_r ) : name_r; } + + /** Return this path, removing a leading '/' if absolute.*/ + Pathname relativename() const { return relativename( *this ); } + static Pathname relativename( const Pathname & name_r ) + { return name_r.absolute() ? cat( ".", name_r ) : name_r; } + + /** Returns this path as the absolute canonical pathname */ + Pathname realpath() const; + + /** Return \c path_r prefixed with \c root_r, unless it is already prefixed. */ + static Pathname assertprefix( const Pathname & root_r, const Pathname & path_r ); + + /** Return \c path_r with any \c root_r dir prefix striped. */ + static Pathname stripprefix( const Pathname & root_r, const Pathname & path_r ); + + /** Concatenation of pathnames. + * \code + * "foo" / "baa" ==> "foo/baa" + * "foo/" / "baa" ==> "foo/baa" + * "foo" / "/baa" ==> "foo/baa" + * "foo/" / "/baa" ==> "foo/baa" + * \endcode + */ + Pathname cat( const Pathname & r ) const { return cat( *this, r ); } + static Pathname cat( const Pathname & l, const Pathname & r ); + + /** Append string \a r to the last component of the path. + * \code + * "foo/baa".extend( ".h" ) ==> "foo/baa.h" + * \endcode + */ + Pathname extend( const std::string & r ) const { return extend( *this, r ); } + static Pathname extend( const Pathname & l, const std::string & r ); + + private: + std::string _name; + void _assign( const std::string & name_r ); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Pathname */ + inline bool operator==( const Pathname & l, const Pathname & r ) + { return l.asString() == r.asString(); } + + /** \relates Pathname */ + inline bool operator!=( const Pathname & l, const Pathname & r ) + { return l.asString() != r.asString(); } + + /** \relates Pathname Concatenate two Pathname. */ + inline Pathname operator/( const Pathname & l, const Pathname & r ) + { return Pathname::cat( l, r ); } + + /** \relates Pathname Concatenate two Pathname. + * \deprecated: use / + */ + inline Pathname operator+( const Pathname & l, const Pathname & r ) + { return Pathname::cat( l, r ); } + + /** \relates Pathname */ + inline bool operator<( const Pathname & l, const Pathname & r ) + { return l.asString() < r.asString(); } + + /////////////////////////////////////////////////////////////////// + + /** \relates Pathname Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Pathname & obj ) + { return str << obj.asString(); } + + ///////////////////////////////////////////////////////////////// + } // namespace filesystem + /////////////////////////////////////////////////////////////////// + + /** Dragged into namespace zypp. */ + using filesystem::Pathname; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PATHNAME_H diff --git a/zypp-core/ShutdownLock.cc b/zypp-core/ShutdownLock.cc new file mode 100644 index 0000000..78e4652 --- /dev/null +++ b/zypp-core/ShutdownLock.cc @@ -0,0 +1,43 @@ +#include "ShutdownLock_p.h" + +#include +#include +#include +#include + +zypp::ShutdownLock::ShutdownLock(const std::string &who, const std::string &reason) +{ + try { + MIL << "Try to acquire an inhibitor lock..." << endl; + std::string whoStr = str::form("--who=%s", who.c_str()); + std::string whyStr = str::form("--why=%s", reason.c_str()); + + const char* argv[] = + { + "/usr/bin/systemd-inhibit", + "--what=sleep:shutdown:idle", + whoStr.c_str(), + "--mode=block", + whyStr.c_str(), + "/usr/bin/cat", + NULL + }; + _prog = shared_ptr( new ExternalProgramWithSeperatePgid( argv, ExternalProgram::Discard_Stderr ) ); + } catch (...) { + } +} + +zypp::ShutdownLock::~ShutdownLock() +{ + if (_prog) { + MIL << "Terminate inhibitor lock: pid " << _prog->getpid() << endl; + _prog->kill( SIGTERM ); + if ( !_prog->waitForExit( 10 * 1000 ) ) { + // do a real kill if the app does not close in 10 seconds + WAR << "systemd-inhibit did not respond to SIGTERM, killing it" << std::endl; + _prog->kill(); + } else { + _prog->close(); + } + } +} diff --git a/zypp-core/ShutdownLock_p.h b/zypp-core/ShutdownLock_p.h new file mode 100644 index 0000000..b4c288a --- /dev/null +++ b/zypp-core/ShutdownLock_p.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ShutdownLock_p.h + * +*/ + +#ifndef ZYPP_SHUTDOWNLOCK_P_H_INCLUDED +#define ZYPP_SHUTDOWNLOCK_P_H_INCLUDED + +#include + +#include +#include + +namespace zypp +{ + +class ExternalProgramWithSeperatePgid; + +/** + * Attempts to create a lock to prevent the system + * from going into hibernate/shutdown. The lock is automatically + * released when the object is destroyed. + */ +class ShutdownLock +{ +public: + ShutdownLock( const std::string &who, const std::string &reason ); + ~ShutdownLock(); + +private: + shared_ptr _prog; + +}; + +} + + +#endif diff --git a/zypp-core/TriBool.h b/zypp-core/TriBool.h new file mode 100644 index 0000000..cf9a82f --- /dev/null +++ b/zypp-core/TriBool.h @@ -0,0 +1,78 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/TriBool.h + * +*/ +#ifndef ZYPP_TRIBOOL_H +#define ZYPP_TRIBOOL_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** 3-state boolean logic (\c true, \c false and \c indeterminate). + * \code + * namespace zypp + * { + * typedef boost::logic::tribool TriBool; + * using boost::logic::tribool; + * using boost::logic::indeterminate; + * } + * \endcode + * + * \warning Be carefull.esp. when comparing \ref TriBool using + * \c operator==, as ( indeterminate == indeterminate ) + * does \b not evaluate \b true. It's \c indeterminate. + * + * \see http://www.boost.org/doc/html/tribool.html + * \ingroup BOOST + */ + using TriBool = boost::logic::tribool; + using boost::logic::tribool; + using boost::logic::indeterminate; + + inline std::string asString( const TriBool & val_r, const std::string & istr_r = std::string(), + const std::string & tstr_r = std::string(), + const std::string & fstr_r = std::string() ) + { + std::string ret; + if (indeterminate(val_r)) + ret = ( istr_r.empty() ? "indeterminate" : istr_r ); + else if (val_r) + ret = ( tstr_r.empty() ? "true" : tstr_r ); + else + ret = ( fstr_r.empty() ? "false" : fstr_r ); + return ret; + } + + /** Convert TriBool to bool returning \a default_r if indeterminate.*/ + inline bool tri2bool( const TriBool & val_r, bool default_r ) + { return indeterminate(val_r) ? default_r : bool(val_r); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +namespace boost +{ + namespace logic + { + /** \relates TriBool stream output */ + inline std::ostream & operator<<(std::ostream & s, const tribool & obj) + { return s << zypp::asString( obj ); } + + /** \relates TriBool whether 2 tribool have the same state (this is NOT ==) */ + inline bool sameTriboolState( tribool lhs, tribool rhs ) + { return( ( indeterminate(lhs) && indeterminate(rhs) ) || ( bool )( lhs == rhs ) ); } + } +} +#endif // ZYPP_TRIBOOL_H diff --git a/zypp-core/Url.cc b/zypp-core/Url.cc new file mode 100644 index 0000000..5f6b6e7 --- /dev/null +++ b/zypp-core/Url.cc @@ -0,0 +1,899 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/Url.cc + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + + using namespace zypp::url; + + + // ----------------------------------------------------------------- + /* + * url = [scheme:] [//authority] /path [?query] [#fragment] + */ + #define RX_SPLIT_URL "^([^:/?#]+:|)" \ + "(//[^/?#]*|)" \ + "([^?#]*)" \ + "([?][^#]*|)" \ + "(#.*|)" + + + //////////////////////////////////////////////////////////////////// + namespace + { ////////////////////////////////////////////////////////////////// + + + // --------------------------------------------------------------- + class LDAPUrl: public UrlBase + { + public: + LDAPUrl(): UrlBase() + { + configure(); + } + + LDAPUrl(LDAPUrl &&) = default; + LDAPUrl &operator=(const LDAPUrl &) = default; + LDAPUrl &operator=(LDAPUrl &&) = default; + LDAPUrl(const LDAPUrl &url) : UrlBase(url) {} + ~LDAPUrl() override = default; + + UrlBase * + clone() const override + { + return new LDAPUrl(*this); + } + + UrlSchemes + getKnownSchemes() const override + { + UrlSchemes schemes(2); + schemes[0] = "ldap"; + schemes[1] = "ldaps"; + return schemes; + } + + void + configure() override + { + config("sep_pathparams", ""); + + config("psep_querystr", "?"); + config("vsep_querystr", ""); + + // host is required (isValid=>false) + // but not mandatory (see RFC 2255), + // that is, accept empty host. + config("require_host", "y"); + + // not allowed here + config("rx_username", ""); + config("rx_password", ""); + config("rx_fragment", ""); + config("rx_pathparams", ""); + } + + zypp::url::ParamMap + getQueryStringMap(zypp::url::EEncoding eflag) const override + { + static const char * const keys[] = { + "attrs", "scope", "filter", "exts", NULL + }; + zypp::url::ParamMap pmap; + zypp::url::ParamVec pvec( getQueryStringVec()); + if( pvec.size() <= 4) + { + for(size_t i=0; ifirst == keys[i]) + { + found=true; + pvec[i] = zypp::url::encode(p->second, join_safe); + } + } + if( !found) + { + ZYPP_THROW(url::UrlNotSupportedException( + str::form(_("Invalid LDAP URL query parameter '%s'"), + p->first.c_str()) + )); + } + } + setQueryStringVec(pvec); + } + }; + + + // --------------------------------------------------------------- + // FIXME: hmm.. + class UrlByScheme + { + private: + using UrlBySchemeMap = std::map; + UrlBySchemeMap urlByScheme; + + public: + UrlByScheme() + { + UrlRef ref; + + // ===================================== + ref.reset( new LDAPUrl()); + addUrlByScheme("ldap", ref); + addUrlByScheme("ldaps", ref); + + + // ===================================== + ref.reset( new UrlBase()); + // don't show empty authority + ref->setViewOptions( zypp::url::ViewOption::DEFAULTS - + zypp::url::ViewOption::EMPTY_AUTHORITY); + + ref->config("with_authority", "n"); // disallow host,... + ref->config("require_pathname", "m"); // path is mandatory + addUrlByScheme("hd", ref); + addUrlByScheme("cd", ref); + addUrlByScheme("dvd", ref); + addUrlByScheme("dir", ref); + addUrlByScheme("iso", ref); + + addUrlByScheme("mailto", ref); + addUrlByScheme("urn", ref); + addUrlByScheme("plugin", ref); // zypp plugable media handler: + + // RFC1738, 3.10: may contain a host + ref->config("with_authority", "y"); // allow host, + ref->config("with_port", "n"); // but no port, + ref->config("rx_username", ""); // username or + ref->config("rx_password", ""); // password ... + addUrlByScheme("file", ref); + + // ===================================== + ref.reset( new UrlBase()); + ref->config("require_host", "m"); // host is mandatory + addUrlByScheme("nfs", ref); + addUrlByScheme("nfs4", ref); + addUrlByScheme("smb", ref); + addUrlByScheme("cifs", ref); + addUrlByScheme("http", ref); + addUrlByScheme("https", ref); + ref->config("path_encode_slash2", "y"); // always encode 2. slash + addUrlByScheme("ftp", ref); + addUrlByScheme("sftp", ref); + addUrlByScheme("tftp", ref); + } + + bool + addUrlByScheme(const std::string &scheme, + UrlRef urlImpl) + { + if( urlImpl && urlImpl->isValidScheme(scheme)) + { + UrlRef ref(urlImpl); + ref->clear(); + urlByScheme[str::toLower(scheme)] = ref; + return true; + } + return false; + } + + UrlRef + getUrlByScheme(const std::string &scheme) const + { + UrlBySchemeMap::const_iterator i(urlByScheme.find(str::toLower(scheme))); + if( i != urlByScheme.end()) + { + return i->second; + } + return UrlRef(); + } + + bool + isRegisteredScheme(const std::string &scheme) const + { + return urlByScheme.find(str::toLower(scheme)) != urlByScheme.end(); + } + + UrlSchemes + getRegisteredSchemes() const + { + UrlBySchemeMap::const_iterator i(urlByScheme.begin()); + UrlSchemes schemes; + + schemes.reserve(urlByScheme.size()); + for( ; i != urlByScheme.end(); ++i) + { + schemes.push_back(i->first); + } + return schemes; + } + }; + + + // --------------------------------------------------------------- + UrlByScheme & g_urlSchemeRepository() + { + static UrlByScheme _v; + return _v; + } + + ////////////////////////////////////////////////////////////////// + } // anonymous namespace + //////////////////////////////////////////////////////////////////// + + + // ----------------------------------------------------------------- + Url::~Url() + { + } + + + // ----------------------------------------------------------------- + Url::Url() + : m_impl( new UrlBase()) + { + } + + + // ----------------------------------------------------------------- + Url::Url(const Url &url) + : m_impl( url.m_impl) + { + if( !m_impl) + { + ZYPP_THROW(url::UrlException( + _("Unable to clone Url object") + )); + } + } + + + // ----------------------------------------------------------------- + Url::Url(zypp::url::UrlRef url) + : m_impl(std::move( url)) + { + if( !m_impl) + { + ZYPP_THROW(url::UrlException( + _("Invalid empty Url object reference") + )); + } + } + + + // ----------------------------------------------------------------- + Url::Url(const std::string &encodedUrl) + : m_impl( parseUrl(encodedUrl)) + { + if( !m_impl) + { + ZYPP_THROW(url::UrlParsingException( + _("Unable to parse Url components") + )); + } + } + + + // ----------------------------------------------------------------- + Url& + Url::operator = (const std::string &encodedUrl) + { + UrlRef url( parseUrl(encodedUrl)); + if( !url) + { + ZYPP_THROW(url::UrlParsingException( + _("Unable to parse Url components") + )); + } + m_impl = url; + return *this; + } + + + // ----------------------------------------------------------------- + Url& + Url::operator = (const Url &url) + { + m_impl = url.m_impl; + return *this; + } + + + // ----------------------------------------------------------------- + // static + bool + Url::registerScheme(const std::string &scheme, + UrlRef urlImpl) + { + return g_urlSchemeRepository().addUrlByScheme(scheme, std::move(urlImpl)); + } + + + // ----------------------------------------------------------------- + // static + UrlRef + Url::parseUrl(const std::string &encodedUrl) + { + UrlRef url; + str::smatch out; + bool ret = false; + + try + { + str::regex rex(RX_SPLIT_URL); + ret = str::regex_match(encodedUrl, out, rex); + } + catch( ... ) + {} + + if(ret && out.size() == 6) + { + std::string scheme = out[1]; + if (scheme.size() > 1) + scheme = scheme.substr(0, scheme.size()-1); + std::string authority = out[2]; + if (authority.size() >= 2) + authority = authority.substr(2); + std::string query = out[4]; + if (query.size() > 1) + query = query.substr(1); + std::string fragment = out[5]; + if (fragment.size() > 1) + fragment = fragment.substr(1); + + url = g_urlSchemeRepository().getUrlByScheme(scheme); + if( !url) + { + url.reset( new UrlBase()); + } + url->init(scheme, authority, out[3], + query, fragment); + } + return url; + } + + + // ----------------------------------------------------------------- + // static + zypp::url::UrlSchemes + Url::getRegisteredSchemes() + { + return g_urlSchemeRepository().getRegisteredSchemes(); + } + + + // ----------------------------------------------------------------- + // static + bool + Url::isRegisteredScheme(const std::string &scheme) + { + return g_urlSchemeRepository().isRegisteredScheme(scheme); + } + + + // ----------------------------------------------------------------- + zypp::url::UrlSchemes + Url::getKnownSchemes() const + { + return m_impl->getKnownSchemes(); + } + + + // ----------------------------------------------------------------- + bool + Url::isValidScheme(const std::string &scheme) const + { + return m_impl->isValidScheme(scheme); + } + + + /////////////////////////////////////////////////////////////////// + namespace + { + inline bool isInList( const char ** begin_r, const char ** end_r, const std::string & scheme_r ) + { + for ( ; begin_r != end_r; ++begin_r ) + if ( scheme_r == *begin_r ) + return true; + return false; + } + } + bool Url::schemeIsLocal( const std::string & scheme_r ) + { + static const char * val[] = { "cd", "dvd", "dir", "hd", "iso", "file" }; + return isInList( arrayBegin(val), arrayEnd(val), scheme_r ); + } + + bool Url::schemeIsRemote( const std::string & scheme_r ) + { + static const char * val[] = { "http", "https", "nfs", "nfs4", "smb", "cifs", "ftp", "sftp", "tftp" }; + return isInList( arrayBegin(val), arrayEnd(val), scheme_r ); + } + + bool Url::schemeIsVolatile( const std::string & scheme_r ) + { + static const char * val[] = { "cd", "dvd" }; + return isInList( arrayBegin(val), arrayEnd(val), scheme_r ); + } + + bool Url::schemeIsDownloading( const std::string & scheme_r ) + { + static const char * val[] = { "http", "https", "ftp", "sftp", "tftp" }; + return isInList( arrayBegin(val), arrayEnd(val), scheme_r ); + } + + bool Url::schemeIsPlugin( const std::string & scheme_r ) + { + return scheme_r == "plugin"; + } + /////////////////////////////////////////////////////////////////// + + // ----------------------------------------------------------------- + bool + Url::isValid() const + { + return m_impl->isValid(); + } + + + // ----------------------------------------------------------------- + std::string + Url::asString() const + { + return m_impl->asString(); + } + + + // ----------------------------------------------------------------- + std::string + Url::asCompleteString() const + { + // make sure, all url components are included; + // regardless of the current configuration... + ViewOptions opts(getViewOptions() + + ViewOption::WITH_SCHEME + + ViewOption::WITH_USERNAME + + ViewOption::WITH_PASSWORD + + ViewOption::WITH_HOST + + ViewOption::WITH_PORT + + ViewOption::WITH_PATH_NAME + + ViewOption::WITH_PATH_PARAMS + + ViewOption::WITH_QUERY_STR + + ViewOption::WITH_FRAGMENT); + return m_impl->asString(opts); + } + + + // ----------------------------------------------------------------- + std::string + Url::asString(const ViewOptions &opts) const + { + return m_impl->asString(opts); + } + + + // ----------------------------------------------------------------- + std::string + Url::getScheme() const + { + return m_impl->getScheme(); + } + + + // ----------------------------------------------------------------- + std::string + Url::getAuthority() const + { + return m_impl->getAuthority(); + } + + // ----------------------------------------------------------------- + std::string + Url::getPathData() const + { + return m_impl->getPathData(); + } + + + // ----------------------------------------------------------------- + std::string + Url::getQueryString() const + { + return m_impl->getQueryString(); + } + + + // ----------------------------------------------------------------- + std::string + Url::getFragment(zypp::url::EEncoding eflag) const + { + return m_impl->getFragment(eflag); + } + + + // ----------------------------------------------------------------- + std::string + Url::getUsername(EEncoding eflag) const + { + return m_impl->getUsername(eflag); + } + + + // ----------------------------------------------------------------- + std::string + Url::getPassword(EEncoding eflag) const + { + return m_impl->getPassword(eflag); + } + + + // ----------------------------------------------------------------- + std::string + Url::getHost(EEncoding eflag) const + { + return m_impl->getHost(eflag); + } + + + // ----------------------------------------------------------------- + std::string + Url::getPort() const + { + return m_impl->getPort(); + } + + + // ----------------------------------------------------------------- + std::string + Url::getPathName(EEncoding eflag) const + { + return m_impl->getPathName(eflag); + } + + + // ----------------------------------------------------------------- + std::string + Url::getPathParams() const + { + return m_impl->getPathParams(); + } + + + // ----------------------------------------------------------------- + zypp::url::ParamVec + Url::getPathParamsVec() const + { + return m_impl->getPathParamsVec(); + } + + + // ----------------------------------------------------------------- + zypp::url::ParamMap + Url::getPathParamsMap(EEncoding eflag) const + { + return m_impl->getPathParamsMap(eflag); + } + + + // ----------------------------------------------------------------- + std::string + Url::getPathParam(const std::string ¶m, EEncoding eflag) const + { + return m_impl->getPathParam(param, eflag); + } + + + // ----------------------------------------------------------------- + zypp::url::ParamVec + Url::getQueryStringVec() const + { + return m_impl->getQueryStringVec(); + } + + + // ----------------------------------------------------------------- + zypp::url::ParamMap + Url::getQueryStringMap(EEncoding eflag) const + { + return m_impl->getQueryStringMap(eflag); + } + + + // ----------------------------------------------------------------- + std::string + Url::getQueryParam(const std::string ¶m, EEncoding eflag) const + { + return m_impl->getQueryParam(param, eflag); + } + + + // ----------------------------------------------------------------- + void + Url::setScheme(const std::string &scheme) + { + if(scheme == m_impl->getScheme()) + { + return; + } + if( m_impl->isKnownScheme(scheme)) + { + m_impl->setScheme(scheme); + return; + } + + UrlRef url = g_urlSchemeRepository().getUrlByScheme(scheme); + if( !url) + { + url.reset( new UrlBase()); + } + url->init( + scheme, + m_impl->getAuthority(), + m_impl->getPathData(), + m_impl->getQueryString(), + m_impl->getFragment(zypp::url::E_ENCODED) + ); + m_impl = url; + } + + + // ----------------------------------------------------------------- + void + Url::setAuthority(const std::string &authority) + { + m_impl->setAuthority(authority); + } + + + // ----------------------------------------------------------------- + void + Url::setPathData(const std::string &pathdata) + { + m_impl->setPathData(pathdata); + } + + + // ----------------------------------------------------------------- + void + Url::setQueryString(const std::string &querystr) + { + m_impl->setQueryString(querystr); + } + + + // ----------------------------------------------------------------- + void + Url::setFragment(const std::string &fragment, EEncoding eflag) + { + m_impl->setFragment(fragment, eflag); + } + + + // ----------------------------------------------------------------- + void + Url::setUsername(const std::string &user, + EEncoding eflag) + { + m_impl->setUsername(user, eflag); + } + + + // ----------------------------------------------------------------- + void + Url::setPassword(const std::string &pass, + EEncoding eflag) + { + m_impl->setPassword(pass, eflag); + } + + + // ----------------------------------------------------------------- + void + Url::setHost(const std::string &host) + { + m_impl->setHost(host); + } + + + // ----------------------------------------------------------------- + void + Url::setPort(const std::string &port) + { + m_impl->setPort(port); + } + + + // ----------------------------------------------------------------- + void + Url::setPathName(const std::string &path, + EEncoding eflag) + { + m_impl->setPathName(path, eflag); + } + + void + Url::setPathName(const Pathname &path, + EEncoding eflag) + { + m_impl->setPathName(path.asString(), eflag); + } + + void + Url::setPathName(const char *path, + EEncoding eflag) + { + m_impl->setPathName(path, eflag); + } + + // ----------------------------------------------------------------- + + void Url::appendPathName( const Pathname & path_r, EEncoding eflag_r ) + { if ( ! path_r.emptyOrRoot() ) setPathName( Pathname(getPathName( eflag_r )) / path_r, eflag_r ); } + + // ----------------------------------------------------------------- + void + Url::setPathParams(const std::string ¶ms) + { + m_impl->setPathParams(params); + } + + + // ----------------------------------------------------------------- + void + Url::setPathParamsVec(const zypp::url::ParamVec &pvec) + { + m_impl->setPathParamsVec(pvec); + } + + + // ----------------------------------------------------------------- + void + Url::setPathParamsMap(const zypp::url::ParamMap &pmap) + { + m_impl->setPathParamsMap(pmap); + } + + + // ----------------------------------------------------------------- + void + Url::setPathParam(const std::string ¶m, const std::string &value) + { + m_impl->setPathParam(param, value); + } + + + // ----------------------------------------------------------------- + void + Url::setQueryStringVec(const zypp::url::ParamVec &pvec) + { + m_impl->setQueryStringVec(pvec); + } + + + // ----------------------------------------------------------------- + void + Url::setQueryStringMap(const zypp::url::ParamMap &pmap) + { + m_impl->setQueryStringMap(pmap); + } + + // ----------------------------------------------------------------- + void + Url::setQueryParam(const std::string ¶m, const std::string &value) + { + m_impl->setQueryParam(param, value); + } + + // ----------------------------------------------------------------- + void + Url::delQueryParam(const std::string ¶m) + { + m_impl->delQueryParam(param); + } + + // ----------------------------------------------------------------- + ViewOptions + Url::getViewOptions() const + { + return m_impl->getViewOptions(); + } + + // ----------------------------------------------------------------- + void + Url::setViewOptions(const ViewOptions &vopts) + { + m_impl->setViewOptions(vopts); + } + + // ----------------------------------------------------------------- + std::ostream & operator<<( std::ostream & str, const Url & url ) + { + return str << url.asString(); + } + + bool operator<( const Url &lhs, const Url &rhs ) + { + return (lhs.asCompleteString() < rhs.asCompleteString()); + } + + bool operator==( const Url &lhs, const Url &rhs ) + { + return (lhs.asCompleteString() == rhs.asCompleteString()); + } + + bool operator!=( const Url &lhs, const Url &rhs ) + { + return (lhs.asCompleteString() != rhs.asCompleteString()); + } + + namespace hotfix1050625 { + std::string asString( const Url & url_r ) + { return url_r.m_impl->asString1050625(); } + } + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp-core/Url.h b/zypp-core/Url.h new file mode 100644 index 0000000..12780d2 --- /dev/null +++ b/zypp-core/Url.h @@ -0,0 +1,871 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/Url.h + */ +#ifndef ZYPP_URL_H +#define ZYPP_URL_H + +#include +#include + + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + class Url; + namespace hotfix1050625 { + std::string asString( const Url & url_r ); + } + namespace filesystem { + class Pathname; + } + using filesystem::Pathname; + + /** + * \class Url + * \brief Url manipulation class. + * + * The generic URL (URI) syntax and its main components are defined in + * RFC3986 (http://rfc.net/rfc3986.html) Section 3, "Syntax Components". + * The scheme specific URL syntax and semantics is defined in the + * specification of the particular scheme. See also RFC1738 + * (http://rfc.net/rfc1738.html), that defines specific syntax for + * several URL schemes. + * + * This class provides methods to access and manipulate generic and + * common scheme-specific URL components (or using the more general + * term, URI components). + * To consider the scheme-specifics of a URL, the Url class contains + * a reference object pointing to a UrlBase or derived object, that + * implements the scheme specifics. + * + * Using the Url::registerScheme() method, it is possible to register + * a preconfigured or derived UrlBase object for a specific scheme + * name. The registered object will be cloned to handle all URLs + * containing the specified scheme name. + * + * \par RFC3986, Syntax Components: + * + * The generic URI syntax consists of a hierarchical sequence of + * components referred to as the scheme, authority, path, query, + * and fragment. + * + * \code + * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ] + * + * hier-part = "//" authority path-abempty + * / path-absolute + * / path-rootless + * / path-empty + * \endcode + * + * The scheme and path components are required, though the path may be + * empty (no characters). + * When authority is present, the path must either be empty or begin + * with a slash ("/") character. + * When authority is not present, the path cannot begin with two slash + * characters ("//"). + * These restrictions result in five different ABNF rules for a path + * (Section 3.3), only one of which will match any given URI reference. + * + * The following are two example URIs and their component parts: + * \code + * foo://example.com:8042/over/there?name=ferret#nose + * \_/ \______________/\_________/ \_________/ \__/ + * | | | | | + * scheme authority path query fragment + * | _____________________|__ + * / \ / \ + * urn:example:animal:ferret:nose + * \endcode + * + */ + class ZYPP_API Url + { + public: + /** + * Encoding flags. + */ + using EEncoding = zypp::url::EEncoding; + + /** + * View options. + */ + using ViewOptions = zypp::url::ViewOptions; + + + ~Url(); + Url(); + + /** + * Create a new Url object as shared copy of the given one. + * + * Upon return, both objects will point to the same underlying + * object. This state will remain until one of the object is + * modified. + * + * \param url The Url object to make a copy of. + * \throws url::UrlException if copy fails (should not happen). + */ + Url(const Url &url); + + + /** + * Create a new Url object as shared copy of the given reference. + * + * Upon return, both objects will point to the same underlying + * object. This state will remain until one of the object is + * modified. + * + * \param url The URL implementation reference to make a copy of. + * \throws url::UrlException if reference is empty. + */ + Url(zypp::url::UrlRef url); + + + /** + * \brief Construct a Url object from percent-encoded URL string. + * + * Parses the \p encodedUrl string using the parseUrl() method + * and assigns the result to the newly created object. + * + * \param encodedUrl A percent-encoded URL string. + * \throws url::UrlParsingException if parsing of the url fails. + * \throws url::UrlNotAllowedException if one of the components + * is not allowed for the scheme. + * \throws url::UrlBadComponentException if one of the components + * contains an invalid character. + */ + Url(const std::string &encodedUrl); + + + /** + * @brief Move construct a Url object + */ + Url(Url &&other) = default; + + + // ----------------- + /** + * \brief Parse a percent-encoded URL string. + * + * Tries to parse the given string into generic URL components + * and creates a clone of a scheme-specialized object or a new + * UrlBase object. + * + * \param encodedUrl A percent-encoded URL string. + * \return A reference to a (derived) UrlBase object or + * empty reference if the \p encodedUrl string + * does not match the generic URL syntax. + * \throws url::UrlNotAllowedException if one of the components + * is not allowed for the scheme. + * \throws url::UrlBadComponentException if one of the components + * contains an invalid character. + */ + static url::UrlRef + parseUrl(const std::string &encodedUrl); + + + // ----------------- + /** + * \brief Assigns parsed percent-encoded URL string to the object. + * + * Parses \p encodedUrl string using the parseUrl() method + * and assigns the result to the current object. + * + * \param encodedUrl A percent-encoded URL string. + * \return A reference to this Url object. + * \throws url::UrlParsingException if parsing of the url fails. + * \throws url::UrlNotAllowedException if one of the components + * is not allowed for the scheme. + * \throws url::UrlBadComponentException if one of the components + * contains an invalid character. + */ + Url& + operator = (const std::string &encodedUrl); + + + /** + * \brief Assign a shared copy of \p url to the current object. + * + * Upon return, both objects will point to the same underlying + * object. This state will remain until one of the objects is + * modified. + * + * \param url The Url object to make a copy of. + * \return A reference to this Url object. + */ + Url& + operator = (const Url &url); + + + /** + * \brief Moves the data from other into the current object + */ + Url &operator=(Url &&other) = default; + + + // ----------------- + /** + * \brief Register a scheme-specific implementation. + * + * \param scheme A name of a scheme. + * \param urlImpl A UrlBase object specialized for this scheme. + * \return True, if the object claims to implement the scheme. + */ + static bool + registerScheme(const std::string &scheme, + url::UrlRef urlImpl); + + /** + * \brief Returns all registered scheme names. + * \return A vector with registered URL scheme names. + */ + static zypp::url::UrlSchemes + getRegisteredSchemes(); + + /** + * \brief Returns if scheme name is registered. + * \return True, if scheme name is registered. + */ + static bool + isRegisteredScheme(const std::string &scheme); + + + // ----------------- + /** + * \brief Returns scheme names known to this object. + * \return A vector with scheme names known by this object. + */ + zypp::url::UrlSchemes + getKnownSchemes() const; + + + /** + * \brief Verifies the specified scheme name. + * + * Verifies the generic syntax of the specified \p scheme name + * and if it is contained in the current object's list of known + * schemes (see getKnownSchemes()) if the list is not empty. + * + * The default implementation in the UrlBase class returns an + * emtpy list of known schemes, causing a check of the generic + * syntax only. + * + * \return True, if generic scheme name syntax is valid and + * the scheme name is known to the current object. + */ + bool + isValidScheme(const std::string &scheme) const; + + + /** hd cd dvd dir file iso */ + static bool schemeIsLocal( const std::string & scheme_r ); + /** \overload nonstatic version */ + bool schemeIsLocal() const { return schemeIsLocal( getScheme() ); } + + /** nfs nfs4 smb cifs http https ftp sftp tftp */ + static bool schemeIsRemote( const std::string & scheme_r ); + /** \overload nonstatic version */ + bool schemeIsRemote() const { return schemeIsRemote( getScheme() ); } + + /** cd dvd */ + static bool schemeIsVolatile( const std::string & scheme_r ); + /** \overload nonstatic version */ + bool schemeIsVolatile() const { return schemeIsVolatile( getScheme() ); } + + /** http https ftp sftp tftp */ + static bool schemeIsDownloading( const std::string & scheme_r ); + /** \overload nonstatic version */ + bool schemeIsDownloading() const { return schemeIsDownloading( getScheme() ); } + + /** plugin */ + static bool schemeIsPlugin( const std::string & scheme_r ); + /** \overload nonstatic version */ + bool schemeIsPlugin() const { return schemeIsPlugin( getScheme() ); } + + /** + * \brief Verifies the Url. + * + * Verifies if the current object contains a non-empty scheme + * name. Additional semantical URL checks may be performed by + * derived UrlBase objects. + * + * \return True, if the Url seems to be valid. + */ + bool + isValid() const; + + + // ----------------- + /** + * Returns a default string representation of the Url object. + * + * By default, a password in the URL will be hidden. + * + * \return A default string representation of the Url object. + */ + std::string + asString() const; + + /** + * Returns a string representation of the Url object. + * + * To include a password in the resulting Url string, use: + * \code + * url.asString(url.getViewOptions() + + * url::ViewOptions::WITH_PASSWORD); + * \endcode + * + * \param opts A combination of view options. + * \return A string representation of the Url object. + */ + std::string + asString(const ViewOptions &opts) const; + + /** + * Returns a complete string representation of the Url object. + * + * This function ignores the configuration of the view options + * in the current object (see setViewOption()) and forces to + * return a string with all URL components included. + * + * \return A complete string representation of the Url object. + */ + std::string + asCompleteString() const; + + + // ----------------- + /** + * Returns the scheme name of the URL. + * \return Scheme name of the current Url object. + */ + std::string + getScheme() const; + + + // ----------------- + /** + * Returns the encoded authority component of the URL. + * + * The returned authority string does not contain the leading + * "//" separator characters, but just its "user:pass@host:port" + * content only. + * + * \return The encoded authority component string. + */ + std::string + getAuthority() const; + + /** + * Returns the username from the URL authority. + * \param eflag Flag if the usename should be percent-decoded or not. + * \return The username sub-component from the URL authority. + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + std::string + getUsername(EEncoding eflag = zypp::url::E_DECODED) const; + + /** + * Returns the password from the URL authority. + * \param eflag Flag if the password should be percent-decoded or not. + * \return The password sub-component from the URL authority. + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + std::string + getPassword(EEncoding eflag = zypp::url::E_DECODED) const; + + /** + * Returns \c true if username \b and password are encoded in the authority component. + */ + bool hasCredentialsInAuthority() const + { return ! ( getUsername().empty() || getPassword().empty() ); } + + /** + * Returns the hostname or IP from the URL authority. + * + * In case the Url contains an IP number, it may be surrounded + * by "[" and "]" characters, for example "[::1]" for an IPv6 + * localhost address. + * + * \param eflag Flag if the host should be percent-decoded or not. + * \return The host sub-component from the URL authority. + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + std::string + getHost(EEncoding eflag = zypp::url::E_DECODED) const; + + /** + * Returns the port from the URL authority. + * \return The port sub-component from the URL authority. + */ + std::string + getPort() const; + + + // ----------------- + /** + * Returns the encoded path component of the URL. + * + * The path data contains the path name, optionally + * followed by path parameters separated with a ";" + * character, for example "/foo/bar;version=1.1". + * + * \return The encoded path component of the URL. + */ + std::string + getPathData() const; + + /** + * Returns the path name from the URL. + * \param eflag Flag if the path should be decoded or not. + * \return The path name sub-component without path parameters + * from Path-Data component of the URL. + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + std::string + getPathName(EEncoding eflag = zypp::url::E_DECODED) const; + + /** + * Returns the path parameters from the URL. + * \return The encoded path parameters from the URL. + */ + std::string + getPathParams() const; + + /** + * Returns a vector with path parameter substrings. + * + * The default path parameter separator is the \c ',' character. + * A schema specific object may overide the default separators. + * + * For example, the path parameters string "foo=1,bar=2" is splited + * by default into a vector containing the substrings "foo=1" and + * "bar=2". + * + * \return The path parameters splited into a vector of substrings. + */ + zypp::url::ParamVec + getPathParamsVec() const; + + /** + * Returns a string map with path parameter keys and values. + * + * The default path parameter separator is the \c ',' character, + * the default key/value separator for the path parameters is + * the \c '=' character. + * A schema specific object may overide the default separators. + * + * For example, the path parameters string "foo=1,bar=2" is splited + * into a map containing "foo" = "1" and "bar" = "2" by default. + * + * \param eflag Flag if the path parameter keys and values should + * be decoded or not. + * \return The path parameters key and values as a string map. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + zypp::url::ParamMap + getPathParamsMap(EEncoding eflag = zypp::url::E_DECODED) const; + + /** + * Return the value for the specified path parameter. + * + * For example, if the path parameters string is "foo=1,bar=2" + * the method will return the substring "1" for the param key + * "foo" and "2" for the param key "bar". + * + * \param param The path parameter key. + * \param eflag Flag if the path parameter keys and values should + * be decoded or not. + * \return The value for the path parameter key or empty string. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + std::string + getPathParam(const std::string ¶m, + EEncoding eflag = zypp::url::E_DECODED) const; + + + // ----------------- + /** + * Returns the encoded query string component of the URL. + * + * The query string is returned without first "?" (separator) + * character. Further "?" characters as in e.g. LDAP URLs + * remain in the returned string. + * + * \return The encoded query string component of the URL. + */ + std::string + getQueryString() const; + + /** + * Returns a vector with query string parameter substrings. + * + * The default query string parameter separator is the \c '&' + * character. + * A schema specific object may overide the default separators. + * + * For example, the query string "foo=1&bar=2" is splited by + * default into a vector containing the substrings "foo=1" and + * "bar=2". + * + * \return The query string splited into a vector of substrings. + */ + zypp::url::ParamVec + getQueryStringVec() const; + + /** + * Returns a string map with query parameter and their values. + * + * The default query string parameter separator is the \c ',' + * character, the default key/value separator the \c '=' character. + * A schema specific object may overide the default separators. + * + * For example, the query string "foo=1&bar=2" is splited by + * default into a map containing "foo" = "1" and "bar" = "2". + * + * \param eflag Flag if the query string keys and values should + * be decoded or not. + * \return The query string as a key/value string map. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + zypp::url::ParamMap + getQueryStringMap(EEncoding eflag = zypp::url::E_DECODED) const; + + /** + * Return the value for the specified query parameter. + * + * For example, if the query string is "foo=1,bar=2" the method + * will return the substring "1" for the param key "foo" and + * "2" for the param key "bar". + * + * \param param The query parameter key. + * \param eflag Flag if the query parameter keys and values should + * be decoded or not. + * \return The value for the query parameter key or empty string. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + std::string + getQueryParam(const std::string ¶m, + EEncoding eflag = zypp::url::E_DECODED) const; + + + // ----------------- + /** + * Returns the encoded fragment component of the URL. + * \param eflag Flag if the fragment should be percent-decoded or not. + * \return The encoded fragment component of the URL. + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + std::string + getFragment(EEncoding eflag = zypp::url::E_DECODED) const; + + + // ----------------- + /** + * \brief Set the scheme name in the URL. + * \param scheme The new scheme name. + * \throws url::UrlBadComponentException if the \p scheme + * contains an invalid character or is empty. + */ + void + setScheme(const std::string &scheme); + + + // ----------------- + /** + * \brief Set the authority component in the URL. + * + * The \p authority string shoud contain the "user:pass@host:port" + * sub-components without any leading "//" separator characters. + * + * \param authority The encoded authority component string. + * \throws url::UrlNotAllowedException if the \p authority + * has to be empty in for the current scheme. + * \throws url::UrlBadComponentException if the \p authority + * contains an invalid character. + * \throws url::UrlParsingException if \p authority parsing fails. + */ + void + setAuthority(const std::string &authority); + + /** + * \brief Set the username in the URL authority. + * \param user The new username. + * \param eflag If the \p username is encoded or not. + * \throws url::UrlNotAllowedException if the \p user + * has to be empty in for the current scheme + * \throws url::UrlBadComponentException if the \p user + * contains an invalid character. + */ + void + setUsername(const std::string &user, + EEncoding eflag = zypp::url::E_DECODED); + + /** + * \brief Set the password in the URL authority. + * \param pass The new password. + * \param eflag If the \p password is encoded or not. + * \throws url::UrlNotAllowedException if the \p pass + * has to be empty in for the current scheme. + * \throws url::UrlBadComponentException if the \p pass + * contains an invalid character. + */ + void + setPassword(const std::string &pass, + EEncoding eflag = zypp::url::E_DECODED); + + /** + * \brief Set the hostname or IP in the URL authority. + * + * The \p host parameter may contain a hostname, an IPv4 address + * in dotted-decimal form or an IPv6 address literal encapsulated + * within square brackets (RFC3513, Sect. 2.2). + * + * A hostname may contain national alphanumeric UTF8 characters + * (letters other than ASCII a-z0-9), that will be encoded. + * This function allows to specify both, a encoded or decoded + * hostname. + * + * Other IP literals in "[v ... ]" square bracket format are not + * supported by the implementation in UrlBase class. + * + * \param host The new hostname or IP address. + * \throws url::UrlNotAllowedException if the \p host (authority) + * has to be empty in for the current scheme. + * \throws url::UrlBadComponentException if the \p host is invalid. + */ + void + setHost(const std::string &host); + + /** + * \brief Set the port number in the URL authority. + * \param port The new port number. + * \throws url::UrlNotAllowedException if the \p port (authority) + * has to be empty in for the current scheme. + * \throws url::UrlBadComponentException if the \p port is invalid. + */ + void + setPort(const std::string &port); + + + // ----------------- + /** + * \brief Set the path data component in the URL. + * + * By default, the \p pathdata string may include path + * parameters separated by the ";" separator character. + * + * \param pathdata The encoded path data component string. + * \throws url::UrlBadComponentException if the \p pathdata + * contains an invalid character. + */ + void + setPathData(const std::string &pathdata); + + /** + * \brief Set the path name. + * \param path The new path name. + * \param eflag If the \p path name is encoded or not. + * \throws url::UrlBadComponentException if the \p path name + * contains an invalid character. + */ + void + setPathName(const std::string &path, + EEncoding eflag = zypp::url::E_DECODED); + /** \overload */ + void + setPathName(const Pathname &path, + EEncoding eflag = zypp::url::E_DECODED); + /** \overload */ + void + setPathName(const char *path, + EEncoding eflag = zypp::url::E_DECODED); + + /** + * \brief Extend the path name. + */ + void appendPathName( const Pathname & path_r, EEncoding eflag_r = zypp::url::E_DECODED ); + + /** + * \brief Set the path parameters. + * \param params The new encoded path parameter string. + * \throws url::UrlBadComponentException if the path \p params + * contains an invalid character. + */ + void + setPathParams(const std::string ¶ms); + + /** + * \brief Set the path parameters. + * \param pvec The vector with encoded path parameters. + * \throws url::UrlBadComponentException if the \p pvec + * contains an invalid character. + */ + void + setPathParamsVec(const zypp::url::ParamVec &pvec); + + /** + * \brief Set the path parameters. + * \param pmap The map with decoded path parameters. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + */ + void + setPathParamsMap(const zypp::url::ParamMap &pmap); + + /** + * \brief Set or add value for the specified path parameter. + * \param param The decoded path parameter name. + * \param value The decoded path parameter value. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + void + setPathParam(const std::string ¶m, const std::string &value); + + + // ----------------- + /** + * \brief Set the query string in the URL. + * \param querystr The new encoded query string. + * \throws url::UrlBadComponentException if the \p querystr + * contains an invalid character. + */ + void + setQueryString(const std::string &querystr); + + /** + * \brief Set the query parameters. + * \param qvec The vector with encoded query parameters. + * \throws url::UrlBadComponentException if the \p qvec + * contains an invalid character. + */ + void + setQueryStringVec(const zypp::url::ParamVec &qvec); + + /** + * \brief Set the query parameters. + * \param qmap The map with decoded query parameters. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + */ + void + setQueryStringMap(const zypp::url::ParamMap &qmap); + + /** + * \brief Set or add value for the specified query parameter. + * \param param The decoded query parameter name. + * \param value The decoded query parameter value. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + void + setQueryParam(const std::string ¶m, const std::string &value); + + /** + * \brief remove the specified query parameter. + * \param param The decoded query parameter name. + * \throws url::UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws url::UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + void + delQueryParam(const std::string ¶m); + + + // ----------------- + /** + * \brief Set the fragment string in the URL. + * \param fragment The new fragment string. + * \param eflag If the \p fragment is encoded or not. + * \throws url::UrlBadComponentException if the \p fragment + * contains an invalid character. + */ + void + setFragment(const std::string &fragment, + EEncoding eflag = zypp::url::E_DECODED); + + + // ----------------- + /** + * Return the view options of the current object. + * + * This method is used to query the view options + * used by the asString() method. + * + * \return The current view option combination. + */ + ViewOptions + getViewOptions() const; + + /** + * Change the view options of the current object. + * + * This method is used to change the view options + * used by the asString() method. + * + * \param vopts New view options combination. + */ + void + setViewOptions(const ViewOptions &vopts); + + private: + friend std::string hotfix1050625::asString( const Url & url_r ); + url::UrlRef m_impl; + }; + + std::ostream & operator<<( std::ostream & str, const Url & url ) ZYPP_API; + + /** + * needed for std::set + */ + bool operator<( const Url &lhs, const Url &rhs ) ZYPP_API; + + /** + * needed for find + */ + bool operator==( const Url &lhs, const Url &rhs ) ZYPP_API; + + + bool operator!=( const Url &lhs, const Url &rhs ) ZYPP_API; + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// + +#endif /* ZYPP_URL_H */ +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp-core/UserData.h b/zypp-core/UserData.h new file mode 100644 index 0000000..ae6b175 --- /dev/null +++ b/zypp-core/UserData.h @@ -0,0 +1,237 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/UserData.h + */ +#ifndef ZYPP_CORE_USERDATA_H +#define ZYPP_CORE_USERDATA_H + +#include +#include +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace callback + { + /////////////////////////////////////////////////////////////////// + /// \class UserData + /// \brief Typesafe passing of user data via callbacks + /// + /// Basically a std::map plus + /// associated \ref ContentType. + /// + /// Constness protects non-empty values from being modified. + /// It is possible to overwrite empty values or to add new ones. + /////////////////////////////////////////////////////////////////// + class UserData + { + public: + typedef boost::any AnyType; + typedef boost::bad_any_cast bad_AnyType_cast; + + typedef std::map DataType; + typedef DataType::size_type size_type; + typedef DataType::key_type key_type; + typedef DataType::value_type value_type; + typedef DataType::const_iterator const_iterator; + + typedef zypp::ContentType ContentType; + + public: + /** Default ctor. */ + UserData() + {} + + /** Ctor taking ContentType. */ + explicit UserData( ContentType type_r ) + : _type( std::move(type_r) ) + {} + /** Ctor taking ContentType. */ + explicit UserData( std::string type_r ) + : UserData( ContentType( std::move(type_r) ) ) + {} + /** Ctor taking ContentType. */ + UserData( std::string type_r, std::string subtype_r ) + : UserData( ContentType( std::move(type_r), std::move(subtype_r) ) ) + {} + + public: + /** Get type. */ + const ContentType & type() const + { return _type; } + + /** Set type. */ + void type( ContentType type_r ) + { _type = std::move(type_r); } + + public: + /** Validate object in a boolean context: has data */ + explicit operator bool() const + { return !empty(); } + + /** Whether \ref data is empty. */ + bool empty() const + { return !_dataP || _dataP->empty(); } + + /** Size of \ref data. */ + size_type size() const + { return _dataP ? _dataP->size() : 0; } + + /** The \ref data. */ + const DataType & data() const + { return dataRef(); } + + /** Whether \a key_r is in \ref data. */ + bool haskey( const std::string & key_r ) const + { return _dataP && _dataP->find( key_r ) != _dataP->end(); } + + /** Whether \a key_r is in \ref data and value is not empty. */ + bool hasvalue( const std::string & key_r ) const + { + bool ret = false; + if ( _dataP ) + { + const_iterator it = _dataP->find( key_r ); + if ( it != _dataP->end() && ! it->second.empty() ) + { + ret = true; + } + } + return ret; + } + + /** Set the value for key (nonconst version always returns true). + * Const version is allowed to set empty values or to add new ones only. + */ + bool set( const std::string & key_r, AnyType val_r ) + { dataRef()[key_r] = std::move(val_r); return true; } + /** \overload const version */ + bool set( const std::string & key_r, AnyType val_r ) const + { + bool ret = false; + AnyType & val( dataRef()[key_r] ); + if ( val.empty() ) + { + val = std::move(val_r); + ret = true; + } + return ret; + } + + /** Set an empty value for \a key_r (if possible). */ + bool reset( const std::string & key_r ) + { return set( key_r, AnyType() ); } + /** \overload const version */ + bool reset( const std::string & key_r ) const + { return set( key_r, AnyType() ); } + + /** Remove key from data.*/ + void erase( const std::string & key_r ) + { if ( _dataP ) _dataP->erase( key_r ); } + + /** \ref get helper returning the keys AnyType value or an empty value if key does not exist. */ + const AnyType & getvalue( const std::string & key_r ) const + { + if ( _dataP ) + { + const_iterator it = _dataP->find( key_r ); + if ( it != _dataP->end() ) + { + return it->second; + } + } + static const AnyType none; + return none; + } + + /** Pass back a const Tp & reference to \a key_r value. + * \throws bad_AnyType_cast if key is not set or value is not of appropriate type + * \code + * UserData data; + * std::string value( "defaultvalue" ); + * try + * { + * value = data.get( "mykey" ); + * } + * catch ( const UserData::bad_AnyType_cast & ) + * { + * // no "mykey" or not a std::sting + * } + * \endcode + */ + template + const Tp & get( const std::string & key_r ) const + { return boost::any_cast( getvalue( key_r ) ); } + + /** Pass back a \a Tp copy of \a key_r value. + * \throws bad_AnyType_cast if key is not set or value is not of appropriate type + * \code + * UserData data; + * std::string value = data.get( "mykey", "defaultvalue" ); + * \endcode + */ + template + Tp get( const std::string & key_r, const Tp & default_r ) const + { Tp ret( default_r ); get( key_r, ret ); return ret; } + + /** If the value for \a key_r is of the same type as \a ret_r, pass it back in \a ret_r and return \c true;. + * \code + * UserData data; + * std::string value( "defaultvalue" ); + * if ( ! data.get( "mykey", value ) + * { + * // no "mykey" or not a std::sting + * } + * \endcode + */ + template + bool get( const std::string & key_r, Tp & ret_r ) const + { + bool ret = false; + if ( _dataP ) + { + const_iterator it = _dataP->find( key_r ); + if ( it != _dataP->end() ) + { + auto ptr = boost::any_cast(&it->second); + if ( ptr ) + { + ret_r = *ptr; + ret = true; + } + } + } + return ret; + } + + private: + DataType & dataRef() const + { if ( ! _dataP ) _dataP.reset( new DataType ); return *_dataP; } + + private: + ContentType _type; + mutable shared_ptr _dataP; + }; + + /** \relates UserData Stream output */ + inline std::ostream & operator<<( std::ostream & str, const UserData & obj ) + { return str << "UserData(" << obj.type() << ":" << obj.size() << ")";} + + } // namespace callback + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CORE_USERDATA_H diff --git a/zypp-core/base/CleanerThread.cc b/zypp-core/base/CleanerThread.cc new file mode 100644 index 0000000..49a414e --- /dev/null +++ b/zypp-core/base/CleanerThread.cc @@ -0,0 +1,85 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/CleanerThread.cc + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct CleanerData +{ + static CleanerData &instance () + { + // C++11 requires that this is thread safe "magic statics" + // this is a intentional leak and will live until the application exits + static CleanerData *data( new CleanerData ); + return *data; + } + + CleanerData () + { + std::thread t ( [&](){ + this->run(); + } ); + t.detach(); //we will control the thread otherwise + } + + void run () + { + // force the kernel to pick another thread to handle signals + zyppng::blockAllSignalsForCurrentThread(); + + zyppng::ThreadData::current().setName("Zypp-Cleaner"); + + std::unique_lock lk( _m ); + + while ( true ) + { + auto filter = []( pid_t pid ){ + int status = 0; + int res = waitpid( pid, &status, WNOHANG ); + // we either got an error, or the child has exited, remove it from list + bool removeMe = ( res == -1 || res == pid ); + return removeMe; + }; + _watchedPIDs.erase( std::remove_if( _watchedPIDs.begin(), _watchedPIDs.end(), filter ), _watchedPIDs.end() ); + + if ( _watchedPIDs.size() ) + _cv.wait_for( lk, std::chrono::milliseconds(100) ); + else + _cv.wait( lk ); + } + } + + std::mutex _m; // < locks all data in CleanerData, do not access it without owning the mutex + std::condition_variable _cv; + + std::vector _watchedPIDs; +}; + + +void zypp::CleanerThread::watchPID( pid_t pid_r ) +{ + CleanerData &data = CleanerData::instance(); + { + std::lock_guard guard( data._m ); + data._watchedPIDs.push_back( pid_r ); + } + //wake the thread up + data._cv.notify_one(); +} diff --git a/zypp-core/base/CleanerThread_p.h b/zypp-core/base/CleanerThread_p.h new file mode 100644 index 0000000..d5669ae --- /dev/null +++ b/zypp-core/base/CleanerThread_p.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/CleanerThread_p.h + * This file contains private API, it will change without notice. + * You have been warned. +*/ + +#include + +#include + +namespace zypp +{ + + class ZYPP_LOCAL CleanerThread + { + public: + CleanerThread() = delete; + static void watchPID ( pid_t pid_r ); + }; + +} diff --git a/zypp-core/base/DefaultIntegral b/zypp-core/base/DefaultIntegral new file mode 100644 index 0000000..6d43a5d --- /dev/null +++ b/zypp-core/base/DefaultIntegral @@ -0,0 +1 @@ +#include "defaultintegral.h" diff --git a/zypp-core/base/DtorReset b/zypp-core/base/DtorReset new file mode 100644 index 0000000..ee44b69 --- /dev/null +++ b/zypp-core/base/DtorReset @@ -0,0 +1 @@ +#include "dtorreset.h" diff --git a/zypp-core/base/Easy.h b/zypp-core/base/Easy.h new file mode 100644 index 0000000..88290a5 --- /dev/null +++ b/zypp-core/base/Easy.h @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Easy.h + * +*/ +#ifndef ZYPP_BASE_EASY_H +#define ZYPP_BASE_EASY_H + +#include +#include + +/** Convenient for-loops using iterator. + * \code + * std::set; _store; + * for_( it, _store.begin(), _store.end() ) + * { + * cout << *it << endl; + * } + * \endcode +*/ +#ifndef __GXX_EXPERIMENTAL_CXX0X__ +#define for_(IT,BEG,END) for ( __typeof__(BEG) IT = BEG, _for_end = END; IT != _for_end; ++IT ) +#else +#define for_(IT,BEG,END) for ( auto IT = BEG, _for_end = END; IT != _for_end; ++IT ) +#endif +#define for_each_(IT,CONT) for_( IT, (CONT).begin(), (CONT).end() ) + +/** Simple C-array iterator + * \code + * const char * defstrings[] = { "", "a", "default", "two words" }; + * for_( it, arrayBegin(defstrings), arrayEnd(defstrings) ) + * cout << *it << endl; + * \endcode +*/ +#define arrayBegin(A) (&A[0]) +#define arraySize(A) (sizeof(A)/sizeof(*A)) +#define arrayEnd(A) (&A[0] + arraySize(A)) + +/** + * \code + * defConstStr( strANY(), "ANY" ); + * std::str str = strANY(); + * \endcode + */ +#define defConstStr(FNC,STR) inline const std::string & FNC { static const std::string val( STR ); return val; } + +#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#if GCC_VERSION < 40600 || not defined(__GXX_EXPERIMENTAL_CXX0X__) +#define nullptr NULL +#endif + +/** Delete copy ctor and copy assign */ +#define NON_COPYABLE(CLASS) \ + CLASS( const CLASS & ) = delete; \ + CLASS & operator=( const CLASS & ) = delete + +/** Default copy ctor and copy assign */ +#define DEFAULT_COPYABLE(CLASS) \ + CLASS( const CLASS & ) = default; \ + CLASS & operator=( const CLASS & ) = default + +/** Delete move ctor and move assign */ +#define NON_MOVABLE(CLASS) \ + CLASS( CLASS && ) = delete; \ + CLASS & operator=( CLASS && ) = delete + +/** Default move ctor and move assign */ +#define DEFAULT_MOVABLE(CLASS) \ + CLASS( CLASS && ) = default; \ + CLASS & operator=( CLASS && ) = default + +/** Delete copy ctor and copy assign but enable default move */ +#define NON_COPYABLE_BUT_MOVE( CLASS ) \ + NON_COPYABLE(CLASS); \ + DEFAULT_MOVABLE(CLASS) + +/** Default move ctor and move assign but enable default copy */ +#define NON_MOVABLE_BUT_COPY( CLASS ) \ + NON_MOVABLE(CLASS); \ + DEFAULT_COPYABLE(CLASS) + + +/** Prevent an universal ctor to be chosen as copy ctor. + * \code + * struct FeedStrings + * { + * template> + * FeedStrings( TARG && arg_r ) + * : _value { std::forward( arg_r ) } + * {} + * + * // Same with variadic template. Could be chosen as copy_ctor. + * template + * FeedStrings( Us &&... us ) + * : ... + * + * private: + * std::string _value; + * \endcode + */ +template +using disable_use_as_copy_ctor = std::enable_if_t>>; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_EASY_H diff --git a/zypp-core/base/EnumClass.h b/zypp-core/base/EnumClass.h new file mode 100644 index 0000000..d752812 --- /dev/null +++ b/zypp-core/base/EnumClass.h @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/EnumClass.h + */ +#ifndef ZYPP_BASE_ENUMCLASS_H +#define ZYPP_BASE_ENUMCLASS_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace base + { + /////////////////////////////////////////////////////////////////// + /// \class EnumClass + /// \brief Type safe enum (workaround SWIG not supporting enum class) + /// \code + /// struct EColorDef { enum Enum { R, G ,B }; }; + /// typedef EnumClass Color; + /// \endcode + /// Conversion to from string can be easily added, e.g. like this: + /// \code + /// struct EColorDef { + /// enum Enum { R, G ,B }; + /// static Enum fromString( const std::string & val_r ); + /// static const std::string & asString( Enum val_r ); + /// }; + /// std::ostream & operator<<( std::ostream & str, const EColorDef & obj ) + /// { return str << EColorDef::asString( obj.inSwitch() ); } + /// + /// typedef EnumClass Color; + /// Color red = Color::fromString("red"); + /// cout << red << endl; // "red" + /// \endcode + /////////////////////////////////////////////////////////////////// + template + class EnumClass : public TEnumDef + { + public: + using Enum = typename TEnumDef::Enum; ///< The underlying enum type + using Integral = std::underlying_type_t;///< The underlying integral type + + EnumClass( Enum val_r ) : _val( val_r ) {} + + /** Underlying enum value for use in switch + * \code + * struct EColorDef { enum Enum { R, G ,B }; } + * typedef EnumClass Color; + * + * Color a; + * switch ( a.asEnum() ) + * \endcode + */ + Enum asEnum() const { return _val; } + + /** Underlying integral value (e.g. array index) + * \code + * struct EColorDef { enum Enum { R, G ,B }; } + * typedef EnumClass Color; + * + * Color a; + * std::string table[] = { "red", "green", "blue" }; + * std::cout << table[a.asIntegral()] << std::endl; + */ + Integral asIntegral() const { return static_cast(_val); } + + friend bool operator==( const EnumClass & lhs, const EnumClass & rhs ) { return lhs._val == rhs._val; } + friend bool operator!=( const EnumClass & lhs, const EnumClass & rhs ) { return lhs._val != rhs._val; } + friend bool operator< ( const EnumClass & lhs, const EnumClass & rhs ) { return lhs._val < rhs._val; } + friend bool operator<=( const EnumClass & lhs, const EnumClass & rhs ) { return lhs._val <= rhs._val; } + friend bool operator> ( const EnumClass & lhs, const EnumClass & rhs ) { return lhs._val > rhs._val; } + friend bool operator>=( const EnumClass & lhs, const EnumClass & rhs ) { return lhs._val >= rhs._val; } + + private: + Enum _val; + }; + } // namespace base + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_ENUMCLASS_H diff --git a/zypp-core/base/Errno.h b/zypp-core/base/Errno.h new file mode 100644 index 0000000..aecc31c --- /dev/null +++ b/zypp-core/base/Errno.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Errno.h + * +*/ +#ifndef ZYPP_BASE_ERRNO_H +#define ZYPP_BASE_ERRNO_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Convenience \c errno wrapper. */ + class Errno + { + public: + /** Default ctor: \c errno */ + Errno() : _errno( errno ) {} + + /** Ctor set to \c errno if error condition, else \c 0. + * \code + * int ret = ::write( fd, buffer, size ); + * DBG << "write returns: " << Errno( ret != size ) << end; + * // on success: "write returns: [0-Success]" + * // on error e.g.: "write returns: [11-Resource temporarily unavailable]" + * \endcode + */ + Errno( bool error_r ) : _errno( error_r ? errno : 0 ) {} + + /** Ctor taking an explicit errno value. */ + Errno( int errno_r ) : _errno( errno_r ) {} + + public: + /** Return the stored errno. */ + int get() const { return _errno; } + + /** Allow implicit conversion to \c int. */ + operator int() const { return get(); } + + /** Return human readable error string. */ + std::string asString() const { return str::form( "[%d-%s]", _errno, ::strerror(_errno) ); } + + private: + int _errno; + }; + + /** \relates Errno Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Errno & obj ) + { return str << obj.asString(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_ERRNO_H diff --git a/zypp-core/base/Exception.cc b/zypp-core/base/Exception.cc new file mode 100644 index 0000000..cc4e012 --- /dev/null +++ b/zypp-core/base/Exception.cc @@ -0,0 +1,229 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Exception.cc + * +*/ +#include +#include + +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace exception_detail + { ///////////////////////////////////////////////////////////////// + + std::string CodeLocation::asString() const + { + return str::form( "%s(%s):%u", + _file.c_str(), + _func.c_str(), + _line ); + } + + std::ostream & operator<<( std::ostream & str, const CodeLocation & obj ) + { return str << obj.asString(); } + + void do_ZYPP_RETHROW(const std::exception_ptr &excpt_r, const CodeLocation &where_r) + { + if ( !excpt_r ) + return; + + try { + std::rethrow_exception (excpt_r); + } catch ( const zypp::Exception &e ) { + Exception::log( e, where_r, "RETHROW: " ); + throw; + } catch ( const std::exception & e ) { + Exception::log( typeid(e).name(), where_r, "RETHROW: " ); + throw; + } catch (...) { + Exception::log( "Unknown Exception", where_r, "RETHROW: " ); + throw; + } + } + + std::exception_ptr do_ZYPP_FWD_EXCPT_PTR( const std::exception_ptr & excpt_r, const CodeLocation & where_r ) + { + try { + std::rethrow_exception( excpt_r ); + } catch ( zypp::Exception &e ) { + e.relocate( where_r ); + Exception::log( e, where_r, "RETHROW (FWD) EXCPTR: " ); + return std::current_exception(); + } catch ( const std::exception & e ) { + Exception::log( typeid(e).name(), where_r, "RETHROW (FWD) EXCPTR: " ); + return std::current_exception(); + } catch (...) { + Exception::log( "Unknown Exception", where_r, "RETHROW (FWD) EXCPTR: " ); + return std::current_exception(); + } + } + + ///////////////////////////////////////////////////////////////// + } // namespace exception_detail + /////////////////////////////////////////////////////////////////// + + Exception::Exception() + {} + + Exception::Exception( const std::string & msg_r ) + : _msg( msg_r ) + {} + + Exception::Exception( std::string && msg_r ) + : _msg( std::move(msg_r) ) + {} + + Exception::Exception( const std::string & msg_r, const Exception & history_r ) + : _msg( msg_r ) + { remember( history_r ); } + + Exception::Exception( std::string && msg_r, const Exception & history_r ) + : _msg( std::move(msg_r) ) + { remember( history_r ); } + + Exception::Exception( const std::string & msg_r, Exception && history_r ) + : _msg( msg_r ) + { remember( std::move(history_r) ); } + + Exception::Exception( std::string && msg_r, Exception && history_r ) + : _msg( std::move(msg_r) ) + { remember( std::move(history_r) ); } + + Exception::~Exception() throw() + {} + + std::string Exception::asString() const + { + std::ostringstream str; + dumpOn( str ); + return str.str(); + } + + std::string Exception::asUserString() const + { + std::ostringstream str; + dumpOn( str ); + // call gettext to translate the message. This will + // not work if dumpOn() uses composed messages. + return _(str.str().c_str()); + } + + std::string Exception::asUserHistory() const + { + if ( historyEmpty() ) + return asUserString(); + + std::string ret( asUserString() ); + if ( ret.empty() ) + return historyAsString(); + + ret += '\n'; + ret += historyAsString(); + return ret; + } + + void Exception::remember( const Exception & old_r ) + { + if ( &old_r != this ) // no self-remember + { + History newh( old_r._history.begin(), old_r._history.end() ); + newh.push_front( old_r.asUserString() ); + _history.swap( newh ); + } + } + + void Exception::remember( Exception && old_r ) + { + if ( &old_r != this ) // no self-remember + { + History & newh( old_r._history ); // stealing it + newh.push_front( old_r.asUserString() ); + _history.swap( newh ); + } + } + + void Exception::remember( std::exception_ptr old_r ) + { + try { + if (old_r) { + std::rethrow_exception(std::move(old_r)); + } + } catch( const Exception& e ) { + remember( e ); + } catch ( const std::exception& e ) { + addHistory( e.what() ); + } catch ( ... ) { + addHistory( "Remembered unknown exception" ); + } + } + + void Exception::addHistory( const std::string & msg_r ) + { _history.push_front( msg_r ); } + + void Exception::addHistory( std::string && msg_r ) + { _history.push_front( std::move(msg_r) ); } + + std::string Exception::historyAsString() const + { + std::ostringstream ret; + if ( not _history.empty() ) { + ret << _("History:") << endl; + for ( const std::string & entry : _history ) { + strv::split( entry, "\n", [&ret]( std::string_view line_r, unsigned idx, bool last_r ) -> void { + if ( not ( last_r && line_r.empty() ) ) + ret << (idx==0?" - ":" ") << line_r << endl; + }); + } + } + return ret.str(); + } + + std::ostream & Exception::dumpOn( std::ostream & str ) const + { return str << _msg; } + + std::ostream & Exception::dumpError( std::ostream & str ) const + { return dumpOn( str << _where << ": " ); } + + std::ostream & operator<<( std::ostream & str, const Exception & obj ) + { return obj.dumpError( str ); } + + + std::string Exception::strErrno( int errno_r ) + { return str::strerror( errno_r ); } + + std::string Exception::strErrno( int errno_r, std::string msg_r ) + { + msg_r += ": "; + return msg_r += strErrno( errno_r ); + } + + void Exception::log( const Exception & excpt_r, const CodeLocation & where_r, + const char *const prefix_r ) + { + INT << where_r << " " << prefix_r << " " << excpt_r.asUserHistory() << endl; + } + + void Exception::log( const char * typename_r, const CodeLocation & where_r, + const char *const prefix_r ) + { + INT << where_r << " " << prefix_r << " exception of type " << typename_r << endl; + } + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/Exception.h b/zypp-core/base/Exception.h new file mode 100644 index 0000000..969c8b2 --- /dev/null +++ b/zypp-core/base/Exception.h @@ -0,0 +1,472 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Exception.h + * +*/ +#ifndef ZYPP_BASE_EXCEPTION_H +#define ZYPP_BASE_EXCEPTION_H + +#include +#include +#include +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace exception_detail + { ///////////////////////////////////////////////////////////////// + + /** Keep _FILE_, _FUNCTION_ and _LINE_. + * Construct it using the \ref ZYPP_EX_CODELOCATION macro. + */ + struct CodeLocation + { + friend std::ostream & operator<<( std::ostream & str, const CodeLocation & obj ); + + /** Ctor */ + CodeLocation() + : _line( 0 ) + {} + + /** Ctor */ + CodeLocation( std::string file_r, + std::string func_r, + unsigned line_r ) + : _file(std::move( file_r )), _func(std::move( func_r )), _line( line_r ) + {} + + /** Location as string */ + std::string asString() const; + + private: + std::string _file; + std::string _func; + unsigned _line; + }; + /////////////////////////////////////////////////////////////////// + + /** Create CodeLocation object storing the current location. */ + //#define ZYPP_EX_CODELOCATION ::zypp::exception_detail::CodeLocation(__FILE__,__FUNCTION__,__LINE__) +#define ZYPP_EX_CODELOCATION ::zypp::exception_detail::CodeLocation(( *__FILE__ == '/' ? strrchr( __FILE__, '/' ) + 1 : __FILE__ ),__FUNCTION__,__LINE__) + + /** \relates CodeLocation Stream output */ + std::ostream & operator<<( std::ostream & str, const CodeLocation & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace exception_detail + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Exception + /** Base class for Exception. + * + * Exception offers to store a message string passed to the ctor. + * Derived classes may provide additional information. Overload + * \ref dumpOn to provide a proper error text. + * + * \li Use \ref ZYPP_THROW to throw exceptions. + * \li Use \ref ZYPP_CAUGHT If you caught an exceptions in order to handle it. + * \li Use \ref ZYPP_RETHROW to rethrow a caught exception. + * + * The use of these macros is not mandatory. but \c ZYPP_THROW and + * \c ZYPP_RETHROW will adjust the code location information stored in + * the Exception. All three macros will drop a line in the logfile. + + * \code + * 43 try + * 44 { + * 45 try + * 46 { + * 47 ZYPP_THROW( Exception("Something bad happened.") ); + * 48 } + * 49 catch ( Exception & excpt ) + * 50 { + * 51 ZYPP_RETHROW( excpt ); + * 52 } + * 53 + * 54 } + * 55 catch ( Exception & excpt ) + * 56 { + * 57 ZYPP_CAUGHT( excpt ); + * 58 } + * \endcode + * The above produces the following log lines: + * \code + * Main.cc(main):47 THROW: Main.cc(main):47: Something bad happened. + * Main.cc(main):51 RETHROW: Main.cc(main):47: Something bad happened. + * Main.cc(main):57 CAUGHT: Main.cc(main):51: Something bad happened. + * \endcode + * + * + * Class Exception now offers a history list of message strings. + * These messages should describe what lead to the exception. + * + * The Exceptions message itself is NOT included in the history. + * + * Rethrow, remembering an old exception: + * \code + * try + * { + * .... + * } + * catch( const Exception & olderr_r ) + * { + * ZYPP_CAUGHT( olderr_r ) + * HighLevelException newerr( "Something failed." ); + * newerr.rember( olderr_r ); + * ZYPP_THROW( newerr ); + * } + * \endcode + * + * Print an Exception, followed by its history, if available: + * \code + * Exception error; + * ERR << error << endl << error.historyAsString(); + * \endcode + * + * \todo That's a draft to have a common way of throwing exceptions. + * Most probably, we'll finally use blocxx exceptions here, but not + * in the remaining code of zypp. If we can, we should try to wrap + * the blocxx macros and typedef the classes in here. + **/ + class ZYPP_API Exception : public std::exception + { + friend std::ostream & operator<<( std::ostream & str, const Exception & obj ); + + public: + using CodeLocation = exception_detail::CodeLocation; + using History = std::list; + using HistoryIterator = History::const_iterator; + using HistorySize = History::size_type; + + /** Default ctor. + * Use \ref ZYPP_THROW to throw exceptions. + */ + Exception(); + + /** Ctor taking a message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + Exception( const std::string & msg_r ); + /** \overload */ + Exception( std::string && msg_r ); + + /** Ctor taking a message and an exception to remember as history + * \see \ref remember + * Use \ref ZYPP_THROW to throw exceptions. + */ + Exception( const std::string & msg_r, const Exception & history_r ); + /** \overload moving */ + Exception( std::string && msg_r, const Exception & history_r ); + /** \overload moving */ + Exception( const std::string & msg_r, Exception && history_r ); + /** \overload moving */ + Exception( std::string && msg_r, Exception && history_r ); + + /** Dtor. */ + ~Exception() throw() override; + + /** Return CodeLocation. */ + const CodeLocation & where() const + { return _where; } + + /** Exchange location on rethrow. */ + void relocate( const CodeLocation & where_r ) const + { _where = where_r; } + + /** Return the message string provided to the ctor. + * \note This is not necessarily the complete error message. + * The whole error message is provided by \ref asString or + * \ref dumpOn. + */ + const std::string & msg() const + { return _msg; } + + /** Error message provided by \ref dumpOn as string. */ + std::string asString() const; + + /** Translated error message as string suitable for the user. + * \see \ref asUserStringHistory + */ + std::string asUserString() const; + + public: + /** \name History list of message strings. + * Maintain a simple list of individual error messages, that lead + * to this Exception. The Exceptions message itself is not included + * in the history. The History list stores the most recent message + * fist. + */ + //@{ + + /** Store an other Exception as history. */ + void remember( const Exception & old_r ); + /** \overload moving */ + void remember( Exception && old_r ); + + /** \overload std::exception_ptr */ + void remember( std::exception_ptr old_r ); + + /** Remembering a plain string is most probably not wanted - we \ref addHistory. + * It would discards the old history and replace it with this string. + * If that's actually your intent, explicitly wrap it into an \ref Exception. + */ + void remember( const std::string & msg_r ) + { addHistory( msg_r ); } + /** \overload moving */ + void remember( std::string && msg_r ) + { addHistory( std::move(msg_r) ); } + + /** Add some message text to the history. */ + void addHistory( const std::string & msg_r ); + /** \overload moving */ + void addHistory( std::string && msg_r ); + + /** \ref addHistory from string container types (oldest first) */ + template + void addToHistory( const TContainer & msgc_r ) + { + for ( const std::string & el : msgc_r ) + addHistory( el ); + } + /** \ref addHistory from string container types (oldest first) moving */ + template + void moveToHistory( TContainer && msgc_r ) + { + for ( std::string & el : msgc_r ) + addHistory( std::move(el) ); + } + + /** Iterator pointing to the most recent message. */ + HistoryIterator historyBegin() const + { return _history.begin(); } + + /** Iterator pointing behind the last message. */ + HistoryIterator historyEnd() const + { return _history.end(); } + + /** Whether the history list is empty. */ + bool historyEmpty() const + { return _history.empty(); } + + /** The size of the history list. */ + HistorySize historySize() const + { return _history.size(); } + + /** The history as string. Empty if \ref historyEmpty. + * Otherwise: + * \code + * History: + * - most recent message + * - 2nd message + * ... + * - oldest message + * \endcode + */ + std::string historyAsString() const; + + /** A single (multiline) string composed of \ref asUserString and \ref historyAsString. */ + std::string asUserHistory() const; + //@} + + protected: + + /** Overload this to print a proper error message. */ + virtual std::ostream & dumpOn( std::ostream & str ) const; + + public: + /** Make a string from \a errno_r. */ + static std::string strErrno( int errno_r ); + /** Make a string from \a errno_r and \a msg_r. */ + static std::string strErrno( int errno_r, std::string msg_r ); + + public: + /** Drop a logline on throw, catch or rethrow. + * Used by \ref ZYPP_THROW macros. + */ + static void log( const Exception & excpt_r, const CodeLocation & where_r, + const char *const prefix_r ); + /** \overrload for not-Exception types thrown via ZYPP_THROW */ + static void log( const char * typename_r, const CodeLocation & where_r, + const char *const prefix_r ); + private: + mutable CodeLocation _where; + std::string _msg; + History _history; + + /** Return message string. */ + const char * what() const throw() override + { return _msg.c_str(); } + + /** Called by std::ostream & operator\<\<. + * Prints \ref CodeLocation and the error message provided by + * \ref dumpOn. + */ + std::ostream & dumpError( std::ostream & str ) const; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Exception Stream output */ + std::ostream & operator<<( std::ostream & str, const Exception & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + namespace exception_detail + { + /** SFINAE: Hide template signature unless \a TExcpt is derived from \ref Exception. */ + template + using EnableIfIsException = std::enable_if_t< std::is_base_of_v, int>; + + /** SFINAE: Hide template signature if \a TExcpt is derived from \ref Exception. */ + template + using EnableIfNotException = std::enable_if_t< !std::is_base_of_v, int>; + + + /** Helper for \ref ZYPP_THROW( Exception ). */ + template = 0> + void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn)); + template> + void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) + { + excpt_r.relocate( where_r ); + Exception::log( excpt_r, where_r, "THROW: " ); + throw( excpt_r ); + } + + /** Helper for \ref ZYPP_THROW( not Exception ). */ + template = 0> + void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn)); + template> + void do_ZYPP_THROW( const TExcpt & excpt_r, const CodeLocation & where_r ) + { + Exception::log( typeid(excpt_r).name(), where_r, "THROW: " ); + throw( excpt_r ); + } + + + /** Helper for \ref ZYPP_THROW( Exception ). */ + template = 0> + void do_ZYPP_CAUGHT( const TExcpt & excpt_r, const CodeLocation & where_r ) + { + Exception::log( excpt_r, where_r, "CAUGHT: " ); + } + + /** Helper for \ref ZYPP_THROW( not Exception ). */ + template = 0> + void do_ZYPP_CAUGHT( const TExcpt & excpt_r, const CodeLocation & where_r ) + { + Exception::log( typeid(excpt_r).name(), where_r, "CAUGHT: " ); + } + + + /** Helper for \ref ZYPP_THROW( Exception ). */ + template = 0> + void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn)); + template> + void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) + { + Exception::log( excpt_r, where_r, "RETHROW: " ); + excpt_r.relocate( where_r ); + throw; + } + + /** Helper for \ref ZYPP_THROW( not Exception ). */ + template = 0> + void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) __attribute__((noreturn)); + template> + void do_ZYPP_RETHROW( const TExcpt & excpt_r, const CodeLocation & where_r ) + { + Exception::log( excpt_r, where_r, "RETHROW: " ); + throw; + } + + void do_ZYPP_RETHROW( const std::exception_ptr & excpt_r, const CodeLocation & where_r ); + + /** Helper for \ref ZYPP_EXCPT_PTR( Exception ). */ + template + std::exception_ptr do_ZYPP_EXCPT_PTR( TExcpt && excpt_r, const CodeLocation & where_r ) + { + if constexpr( std::is_base_of_v> ) { + excpt_r.relocate( where_r ); + Exception::log( excpt_r, where_r, "THROW (EXCPTR): " ); + } else { + Exception::log( typeid(excpt_r).name(), where_r, "THROW (EXCPTR): " ); + } + return std::make_exception_ptr>( std::forward(excpt_r) ); + } + + /** Helper for \ref ZYPP_FWD_CURRENT_EXCPT(). */ + std::exception_ptr do_ZYPP_FWD_EXCPT_PTR( const std::exception_ptr & excpt_r, const CodeLocation & where_r ); + + + } // namespace exception_detail + /////////////////////////////////////////////////////////////////// + + /** \defgroup ZYPP_THROW ZYPP_THROW macros + * Macros for throwing Exception. + * \see \ref zypp::Exception for an example. + */ + //@{ + /** Drops a logline and throws the Exception. */ +#define ZYPP_THROW(EXCPT)\ + ::zypp::exception_detail::do_ZYPP_THROW( EXCPT, ZYPP_EX_CODELOCATION ) + + /** Drops a logline and returns Exception as a std::exception_ptr. */ +#define ZYPP_EXCPT_PTR(EXCPT)\ + ::zypp::exception_detail::do_ZYPP_EXCPT_PTR( EXCPT, ZYPP_EX_CODELOCATION ) + + /** Drops a logline and returns the given Exception as a std::exception_ptr. */ +#define ZYPP_FWD_EXCPT(EXCPT)\ + ::zypp::exception_detail::do_ZYPP_FWD_EXCPT_PTR( EXCPT, ZYPP_EX_CODELOCATION ) + + /** Drops a logline and returns the current Exception as a std::exception_ptr. */ +#define ZYPP_FWD_CURRENT_EXCPT()\ + ::zypp::exception_detail::do_ZYPP_FWD_EXCPT_PTR( std::current_exception(), ZYPP_EX_CODELOCATION ) + + /** Drops a logline telling the Exception was caught (in order to handle it). */ +#define ZYPP_CAUGHT(EXCPT)\ + ::zypp::exception_detail::do_ZYPP_CAUGHT( EXCPT, ZYPP_EX_CODELOCATION ) + + /** Drops a logline and rethrows, updating the CodeLocation. */ +#define ZYPP_RETHROW(EXCPT)\ + ::zypp::exception_detail::do_ZYPP_RETHROW( EXCPT, ZYPP_EX_CODELOCATION ) + + + /** Throw Exception built from a message string. */ +#define ZYPP_THROW_MSG(EXCPTTYPE, MSG)\ + ZYPP_THROW( EXCPTTYPE( MSG ) ) + + /** Throw Exception built from errno. */ +#define ZYPP_THROW_ERRNO(EXCPTTYPE)\ + ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(errno) ) ) + + /** Throw Exception built from errno provided as argument. */ +#define ZYPP_THROW_ERRNO1(EXCPTTYPE, ERRNO)\ + ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(ERRNO) ) ) + + /** Throw Exception built from errno and a message string. */ +#define ZYPP_THROW_ERRNO_MSG(EXCPTTYPE, MSG)\ + ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(errno,MSG) ) ) + + /** Throw Exception built from errno provided as argument and a message string */ +#define ZYPP_THROW_ERRNO_MSG1(EXCPTTYPE, ERRNO,MSG)\ + ZYPP_THROW( EXCPTTYPE( ::zypp::Exception::strErrno(ERRNO,MSG) ) ) + //@} + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_EXCEPTION_H diff --git a/zypp-core/base/ExternalDataSource.cc b/zypp-core/base/ExternalDataSource.cc new file mode 100644 index 0000000..af1da09 --- /dev/null +++ b/zypp-core/base/ExternalDataSource.cc @@ -0,0 +1,147 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/ExternalDataSource.cc + */ + + +#define _GNU_SOURCE 1 // for ::getline + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; + +namespace zypp { + namespace externalprogram { + + ExternalDataSource::ExternalDataSource( FILE *ifile, FILE *ofile ) + : inputfile( ifile ), + outputfile( ofile ), + linebuffer( 0 ), + linebuffer_size( 0 ) + { + } + + + ExternalDataSource::~ExternalDataSource() + { + if (linebuffer) + free( linebuffer ); + close (); + } + + + bool + ExternalDataSource::send( const char *buffer, size_t length ) + { + if ( outputfile ) { + bool success = fwrite( buffer, length, 1, outputfile ) != 0; + fflush( outputfile ); + return success; + } + else + return false; + } + + + bool + ExternalDataSource::send( std::string s ) + { + DBG << "send (" << s << ")"; + return send( s.data(), s.length() ); + } + + + std::string + ExternalDataSource::receiveUpto( char c ) + { + if ( inputfile && !feof( inputfile ) ) + { + std::ostringstream datas; + while ( true ) + { + int readc = fgetc( inputfile ); + if ( readc == EOF ) break; + datas << (char)readc; + if ( (char)readc == c ) break; + } + return datas.str(); + } + return std::string(); + } + + std::string ExternalDataSource::receiveUpto( char c, io::timeout_type timeout ) + { + const auto &received = io::receiveUpto( inputFile(), c, timeout ); + + if ( received.first == io::Timeout ) + ZYPP_THROW( io::TimeoutException() ); + + return received.second; + } + + size_t + ExternalDataSource::receive( char *buffer, size_t length ) + { + if ( inputfile ) + return fread( buffer, 1, length, inputfile ); + else + return 0; + } + + void ExternalDataSource::setBlocking( bool mode ) + { + io::setFILEBlocking( inputfile, mode ); + } + + std::string ExternalDataSource::receiveLine() + { + if ( inputfile ) { + ssize_t nread = zyppng::eintrSafeCallEx( getline, [&](){clearerr ( inputfile );}, &linebuffer, &linebuffer_size, inputfile ); + if ( nread == -1 ) + return ""; + else + return std::string( linebuffer, nread ); + } + else + return ""; + } + + std::string ExternalDataSource::receiveLine( io::timeout_type timeout ) + { + return receiveUpto( '\n', timeout ); + } + + int + ExternalDataSource::close() + { + if ( inputfile && inputfile != outputfile ) + fclose( inputfile ); + if ( outputfile ) + fclose( outputfile ); + inputfile = 0; + outputfile = 0; + return 0; + } + + } // namespace externalprogram +} // namespace zypp + diff --git a/zypp-core/base/ExternalDataSource.h b/zypp-core/base/ExternalDataSource.h new file mode 100644 index 0000000..a7a81c0 --- /dev/null +++ b/zypp-core/base/ExternalDataSource.h @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/ExternalDataSource.h + */ + +#ifndef ZYPP_EXTERNALDATASOURCE_H +#define ZYPP_EXTERNALDATASOURCE_H + +#include + +#include +#include +#include + +namespace zypp { + namespace externalprogram { + + /** + * @short Bidirectional stream to external data + */ + class ZYPP_API ExternalDataSource + { + protected: + FILE *inputfile; + FILE *outputfile; + + private: + char *linebuffer; + size_t linebuffer_size; + + public: + /** + * Create a new instance. + * @param inputfile The stream for reading + * @param outputfile The stream for writing + * Either can be NULL if no reading/writing is allowed. + */ + ExternalDataSource( FILE *inputfile = 0, FILE *outputfile = 0 ); + + /** + * Implicitly close the connection. + */ + virtual ~ExternalDataSource (); + + /** + * Send some data to the output stream. + * @param buffer The data to send + * @param length The size of it + */ + bool send( const char *buffer, size_t length ); + + /** + * Send some data down the stream. + * @param string The data to send + */ + bool send( std::string s ); + + /** + * Read some data from the input stream. + * @param buffer Where to put the data + * @param length How much to read at most + * Returns the amount actually received + */ + size_t receive( char *buffer, size_t length ); + + /** + * Read one line from the input stream. + * Returns the line read, including the terminator. + */ + std::string receiveLine(); + + /** + * Read one line from the input stream. + * Returns the line read, including the terminator. + * \note The delimiter is not removed from the string. + * \note The \a timeout value is to be specified in milliseconds. + * \throws io::TimeoutException if the timeout is reached + */ + std::string receiveLine( io::timeout_type timeout ); + + /** + * Read characters into a string until delimiter \a c or EOF is + * read. + * \note The delimiter is not removed from the string. + */ + std::string receiveUpto( char c ); + + /** + * Read characters into a string until delimiter \a c or EOF is + * read or the \a timeout is reached. + * \note The delimiter is not removed from the string. + * \note The \a timeout value is to be specified in milliseconds. + * \throws io::TimeoutException if the timeout is reached + */ + std::string receiveUpto( char c, io::timeout_type timeout ); + + /** + * Set the blocking mode of the input stream. + * @param mode True if the reader should be blocked waiting for input. + * This is the initial default. + */ + void setBlocking( bool mode ); + + /** + * Close the input and output streams. + */ + virtual int close(); + + /** + * Return the input stream. + */ + FILE *inputFile() const { return inputfile; } + + /** + * Return the output stream. + */ + FILE *outputFile() const { return outputfile; } + }; + + } // namespace externalprogram +} // namespace zypp + +#endif // ZYPP_EXTERNALDATASOURCE_H + diff --git a/zypp-core/base/FileStreamBuf b/zypp-core/base/FileStreamBuf new file mode 100644 index 0000000..3130882 --- /dev/null +++ b/zypp-core/base/FileStreamBuf @@ -0,0 +1 @@ +#include "filestreambuf.h" diff --git a/zypp-core/base/Flags.h b/zypp-core/base/Flags.h new file mode 100644 index 0000000..9082ee8 --- /dev/null +++ b/zypp-core/base/Flags.h @@ -0,0 +1,199 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Flags.h + * +*/ +#ifndef ZYPP_BASE_FLAGS_H +#define ZYPP_BASE_FLAGS_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Flags + // + /** A type-safe way of storing OR-combinations of enum values (like QTs QFlags). + * \see QFlags Class Reference + * \code + * class RpmDb + * { + * public: + * enum DbStateInfoBits { + * DbSI_NO_INIT = 0x0000, + * DbSI_HAVE_V4 = 0x0001, + * DbSI_MADE_V4 = 0x0002, + * DbSI_MODIFIED_V4 = 0x0004, + * DbSI_HAVE_V3 = 0x0008, + * DbSI_HAVE_V3TOV4 = 0x0010, + * DbSI_MADE_V3TOV4 = 0x0020 + * }; + * + * ZYPP_DECLARE_FLAGS(DbStateInfo,DbStateInfoBits); + * }; + * ZYPP_DECLARE_OPERATORS_FOR_FLAGS(RpmDb::DbStateInfo); + * + * ... + * enum Other { OTHERVAL = 13 }; + * { + * XRpmDb::DbStateInfo s; + * s = XRpmDb::DbSI_MODIFIED_V4|XRpmDb::DbSI_HAVE_V4; + * // s |= OTHERVAL; // As desired: it does not compile + * } + * \endcode + */ + template + class Flags + { + public: + using Enum = TEnum; ///< The underlying enum type + using Integral = std::underlying_type_t; ///< The underlying integral type + + public: + constexpr Flags() : _val( 0 ) {} + constexpr Flags( Enum flag_r ) : _val( integral(flag_r) ) {} + constexpr explicit Flags( Integral flag_r ) : _val( flag_r ) {} + + constexpr static Flags none() { return Flags( Integral(0) ); } + constexpr static Flags all() { return Flags( ~Integral(0) ); } + + constexpr bool isNone() const { return _val == Integral(0); } + constexpr bool isAll() const { return _val == ~Integral(0); } + + Flags & operator&=( Flags rhs ) { _val &= integral(rhs); return *this; } + Flags & operator&=( Enum rhs ) { _val &= integral(rhs); return *this; } + + Flags & operator|=( Flags rhs ) { _val |= integral(rhs); return *this; } + Flags & operator|=( Enum rhs ) { _val |= integral(rhs); return *this; } + + Flags & operator^=( Flags rhs ) { _val ^= integral(rhs); return *this; } + Flags & operator^=( Enum rhs ) { _val ^= integral(rhs); return *this; } + + public: + constexpr operator Integral() const { return _val; } + + constexpr Flags operator&( Flags rhs ) const { return Flags( _val & integral(rhs) ); } + constexpr Flags operator&( Enum rhs ) const { return Flags( _val & integral(rhs) ); } + + constexpr Flags operator|( Flags rhs ) const { return Flags( _val | integral(rhs) ); } + constexpr Flags operator|( Enum rhs ) const { return Flags( _val | integral(rhs) ); } + + constexpr Flags operator^( Flags rhs ) const { return Flags( _val ^ integral(rhs) ); } + constexpr Flags operator^( Enum rhs ) const { return Flags( _val ^ integral(rhs) ); } + + constexpr Flags operator~() const { return Flags( ~_val ); } + + constexpr bool operator==( Enum rhs ) const { return( _val == integral(rhs) ); } + constexpr bool operator!=( Enum rhs ) const { return( _val != integral(rhs) ); } + + public: + Flags & setFlag( Flags flag_r, bool newval_r ) { return( newval_r ? setFlag(flag_r) : unsetFlag(flag_r) ); } + Flags & setFlag( Enum flag_r, bool newval_r ) { return( newval_r ? setFlag(flag_r) : unsetFlag(flag_r) ); } + + Flags & setFlag( Flags flag_r ) { _val |= integral(flag_r); return *this; } + Flags & setFlag( Enum flag_r ) { _val |= integral(flag_r); return *this; } + + Flags & unsetFlag( Flags flag_r ) { _val &= ~integral(flag_r); return *this; } + Flags & unsetFlag( Enum flag_r ) { _val &= ~integral(flag_r); return *this; } + + constexpr bool testFlag( Flags flag_r ) const { return testFlag( integral(flag_r) ); } + constexpr bool testFlag( Enum flag_r ) const { return testFlag( integral(flag_r) ); } + + private: + constexpr bool testFlag( Integral flag ) const { return flag ? ( _val & flag ) == flag : !_val; } + + constexpr static Integral integral( Flags obj ) { return obj._val; } + constexpr static Integral integral( Enum obj ) { return static_cast(obj); } + + Integral _val; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Flags Stringify + * Build a string of OR'ed names of each flag value set in \a flag_r. + * Remaining bits in \a flag_r are added as hexstring. + * \code + * enum E { a=1, b=2, c=4 }; + * ZYPP_DECLARE_FLAGS( E, MyFlags ); + * + * MyFlags f = a|b|c; + * cout << f << " = " << stringify( f, { {a,"A"}, {b,"B"} } ) << endl; + * // prints: 0x0007 = [A|B|0x4] + * \endcode + */ + template + std::string stringify( const Flags & flag_r, const std::initializer_list,std::string> > & flaglist_r = {}, + std::string intro_r = "[", std::string sep_r = "|", const std::string &extro_r = "]" ) + { + std::string ret( std::move(intro_r) ); + std::string sep; + + Flags mask; + for ( const auto & pair : flaglist_r ) + { + if ( flag_r.testFlag( pair.first ) ) + { + mask |= pair.first; + ret += sep; + ret += pair.second; + if ( sep.empty() && !sep_r.empty() ) + { sep = std::move(sep_r); } + } + } + mask = flag_r & ~mask; + if ( mask ) + { + ret += sep; + ret += str::hexstring( mask, 0 ); + } + ret += extro_r; + return ret; + } + + template + inline std::ostream & operator<<( std::ostream & str, const Flags & obj ) + { return str << str::hexstring(obj); } + + template + inline std::ostream & operator<<( std::ostream & str, const typename Flags::Enum & obj ) + { return str << Flags(obj); } + + /** \relates Flags */ +#define ZYPP_DECLARE_FLAGS(Name,Enum) typedef zypp::base::Flags Name + + /** \relates Flags */ +#define ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Name) \ +inline constexpr bool operator==( Name::Enum lhs, Name rhs ) { return( rhs == lhs ); } \ +inline constexpr bool operator!=(Name:: Enum lhs, Name rhs ) { return( rhs != lhs ); } \ +inline constexpr Name operator&( Name::Enum lhs, Name::Enum rhs ) { return Name( lhs ) & rhs; } \ +inline constexpr Name operator&( Name::Enum lhs, Name rhs ) { return rhs & lhs; } \ +inline constexpr Name operator|( Name::Enum lhs, Name::Enum rhs ) { return Name( lhs ) | rhs; } \ +inline constexpr Name operator|( Name::Enum lhs, Name rhs ) { return rhs | lhs; } \ +inline constexpr Name operator^( Name::Enum lhs, Name::Enum rhs ) { return Name( lhs ) ^ rhs; } \ +inline constexpr Name operator^( Name::Enum lhs, Name rhs ) { return rhs ^ lhs; } \ +inline constexpr Name operator~( Name::Enum lhs ) { return ~Name( lhs ); } + + /** \relates Flags */ +#define ZYPP_DECLARE_FLAGS_AND_OPERATORS(Name,Enum) \ + ZYPP_DECLARE_FLAGS(Name,Enum); \ + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Name) + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_FLAGS_H diff --git a/zypp-core/base/Function.h b/zypp-core/base/Function.h new file mode 100644 index 0000000..48d672a --- /dev/null +++ b/zypp-core/base/Function.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Function.h + * +*/ +#ifndef ZYPP_BASE_FUNCTION_H +#define ZYPP_BASE_FUNCTION_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /* http://www.boost.org/doc/html/function.html + + The Boost.Function library contains a family of class templates + that are function object wrappers. The notion is similar to a + generalized callback. It shares features with function pointers + in that both define a call interface (e.g., a function taking + two integer arguments and returning a floating-point value) + through which some implementation can be called, and the + implementation that is invoked may change throughout the + course of the program. + + Generally, any place in which a function pointer would be used + to defer a call or make a callback, Boost.Function can be used + instead to allow the user greater flexibility in the implementation + of the target. Targets can be any 'compatible' function object + (or function pointer), meaning that the arguments to the interface + designated by Boost.Function can be converted to the arguments of + the target function object. + */ + using boost::function; + + using std::bind; + using std::placeholders::_1; + using std::placeholders::_2; + using std::placeholders::_3; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_FUNCTION_H diff --git a/zypp-core/base/Gettext.cc b/zypp-core/base/Gettext.cc new file mode 100644 index 0000000..8e88ebb --- /dev/null +++ b/zypp-core/base/Gettext.cc @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Gettext.cc + * +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +extern "C" { +#include +} + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace gettext + { ///////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + // TEXTDOMAIN and LOCALEDIR must be provided via config.h + // or at compile time using -D. + ///////////////////////////////////////////////////////////////// + + inline void assertInit() + { + static bool initialized = false; + if ( ! initialized ) + { + ::bindtextdomain( TEXTDOMAIN, LOCALEDIR ); + ::bind_textdomain_codeset( TEXTDOMAIN, "UTF-8" ); + initialized = true; + } + } + + const char * dgettext( const char * msgid ) + { + assertInit(); + return ::dgettext( TEXTDOMAIN, msgid ); + } + + const char * dngettext( const char * msgid1, const char * msgid2, + unsigned long n ) + { + assertInit(); + return ::dngettext( TEXTDOMAIN, msgid1, msgid2, n ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace gettext + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/Gettext.h b/zypp-core/base/Gettext.h new file mode 100644 index 0000000..b2c4a9b --- /dev/null +++ b/zypp-core/base/Gettext.h @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Gettext.h + * + * Interface to gettext. + * +*/ +#ifndef ZYPP_BASE_GETTEXT_H +#define ZYPP_BASE_GETTEXT_H + +#include + +#ifdef ZYPP_DLL //defined if zypp is compiled as DLL + +/** Just tag text for translation. */ +#undef N_ +#define N_(MSG) MSG + +/** Return translated text. */ +#undef _ +#define _(MSG) ::zypp::gettext::dgettext( MSG ) + +/** Return translated text (plural form). */ +#undef PL_ +#define PL_(MSG1,MSG2,N) ::zypp::gettext::dngettext( MSG1, MSG2, N ) + +#else + +#ifndef N_ +#define N_(MSG) MSG +#endif +#ifndef _ +#define _(MSG) ::gettext( MSG ) +#endif +#ifndef PL_ +#define PL_(MSG1,MSG2,N) ::ngettext( MSG1, MSG2, N ) +#endif + +#endif + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace gettext + { ///////////////////////////////////////////////////////////////// + + /** Return translated text. */ + const char * dgettext( const char * msgid ) ZYPP_API; + + /** Return translated text (plural form). */ + const char * dngettext( const char * msgid1, const char * msgid2, + unsigned long n ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// + } // namespace gettext + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_GETTEXT_H diff --git a/zypp-core/base/GzStream b/zypp-core/base/GzStream new file mode 100644 index 0000000..bf45aca --- /dev/null +++ b/zypp-core/base/GzStream @@ -0,0 +1 @@ +#include "gzstream.h" diff --git a/zypp-core/base/Hash.h b/zypp-core/base/Hash.h new file mode 100644 index 0000000..382e283 --- /dev/null +++ b/zypp-core/base/Hash.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Hash.h + * +*/ +#ifndef ZYPP_BASE_HASH_H +#define ZYPP_BASE_HASH_H + +#include +#include +#include + +/** Define hash function for id based classes. + * Class has to provide a method \c id() retuning a unique number. + * \code + * // in global namespace define: + * ZYPP_DEFINE_ID_HASHABLE( ::zypp::sat::Solvable ) + * \endcode + */ +#define ZYPP_DEFINE_ID_HASHABLE(C) \ +namespace std { \ + template struct hash; \ + template<> struct hash \ + { \ + size_t operator()( const C & __s ) const \ + { return __s.id(); } \ + }; \ +} + +/////////////////////////////////////////////////////////////////// +namespace std +{ + /** clone function for RW_pointer */ + template + inline unordered_set * rwcowClone( const std::unordered_set * rhs ) + { return new std::unordered_set( *rhs ); } + + /** clone function for RW_pointer */ + template + inline std::unordered_map * rwcowClone( const std::unordered_map * rhs ) + { return new std::unordered_map( *rhs ); } +} // namespace std +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_HASH_H diff --git a/zypp-core/base/IOStream.cc b/zypp-core/base/IOStream.cc new file mode 100644 index 0000000..a8f9d0f --- /dev/null +++ b/zypp-core/base/IOStream.cc @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/IOStream.cc + * +*/ +#include +#include +#include +//#include + +#include +#include + +using std::endl; +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace iostr + { ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : getline + ** FUNCTION TYPE : std::string + */ + std::string getline( std::istream & str ) + { + static const unsigned tmpBuffLen = 1024; + static char tmpBuff[tmpBuffLen]; + std::string ret; + do { + str.clear(); + str.getline( tmpBuff, tmpBuffLen ); // always writes '\0' terminated + ret += tmpBuff; + } while( str.rdstate() == std::ios::failbit ); + + return ret; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : EachLine + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : EachLine::EachLine + // METHOD TYPE : Ctor + // + EachLine::EachLine( std::istream & str_r, unsigned lineNo_r ) + : _str( str_r ) + , _lineStart( -1 ) + , _lineNo( lineNo_r ) + , _valid( true ) + { + next(); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : EachLine::next + // METHOD TYPE : bool + // + bool EachLine::next() + { + if ( ! _valid ) + { + return false; + } + + if ( ! _str ) // usg: saw EOF in previous read + { + _line.clear(); + return(_valid = false); + } + + _lineStart = _str.tellg(); + _line = iostr::getline( _str ); + ++_lineNo; + if ( _str.fail() || _str.bad() ) + { + _line.clear(); + return(_valid = false); + } + return(_valid = true); + } + + /////////////////////////////////////////////////////////////////// + // forEachLine + /////////////////////////////////////////////////////////////////// + + int forEachLine( std::istream & str_r, const function& consume_r ) + { + int lineno = 0; + while ( str_r ) + { + std::string line( getline( str_r ) ); + if ( ! (str_r.fail() || str_r.bad()) ) + { + // line contains valid data to be consumed. + ++lineno; + if ( consume_r && ! consume_r( lineno, line ) ) + { + lineno = -lineno; + break; + } + } + } + return lineno; + } + + // MPL checks to assert equal values for PF_?TRIM and str::?TRIM + BOOST_MPL_ASSERT_RELATION( int(PF_LTRIM), ==, int(str::L_TRIM) ); + BOOST_MPL_ASSERT_RELATION( int(PF_RTRIM), ==, int(str::R_TRIM) ); + + int simpleParseFile( std::istream & str_r, ParseFlags flags_r, function consume_r ) + { + return forEachLine( str_r, + [&]( int num_r, std::string line_r )->bool + { + if ( ! consume_r ) + return true; + + if ( flags_r ) + { + if ( flags_r & PF_TRIM ) + line_r = str::trim( line_r, str::Trim( unsigned(flags_r & PF_TRIM) ) ); + + if ( flags_r & ~PF_TRIM ) + { + const char* firstNW = line_r.c_str(); + while ( *firstNW == ' ' || *firstNW == '\t' ) + ++firstNW; + switch ( *firstNW ) + { + case '\0': if ( flags_r & PF_SKIP_EMPTY ) return true; break; + case '#': if ( flags_r & PF_SKIP_SHARP_COMMENT ) return true; break; + } + } + } + return consume_r( num_r, line_r ); + } ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace iostr + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/IOStream.h b/zypp-core/base/IOStream.h new file mode 100644 index 0000000..073b46c --- /dev/null +++ b/zypp-core/base/IOStream.h @@ -0,0 +1,213 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/IOStream.h + * +*/ +#ifndef ZYPP_BASE_IOSTREAM_H +#define ZYPP_BASE_IOSTREAM_H + +#include +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + /** Iostream related utilities. + */ + namespace iostr + { ///////////////////////////////////////////////////////////////// + + /** Save and restore streams \c width, \c precision + * and \c fmtflags. + */ + using IosFmtFlagsSaver = boost::io::ios_base_all_saver; + + + /** Read one line from stream. + * + * Reads everything up to the next newline or EOF. newline + * is read but not returned. + * + * \see \ref forEachLine + */ + std::string getline( std::istream & str ) ZYPP_API; + + /** Copy istream to ostream. + * \return reference to the ostream. + */ + inline std::ostream & copy( std::istream & from_r, std::ostream & to_r ) + { + if ( from_r && to_r ) + { + char ch = 0; + while ( from_r && from_r.get( ch ) ) + to_r.put( ch ); + } + return to_r; + } + + /** Copy istream to ostream, prefixing each line with \a indent_r (default "> " ). + * \return reference to the ostream. + */ + inline std::ostream & copyIndent( std::istream & from_r, std::ostream & to_r, const std::string & indent_r = "> " ) + { + if ( from_r && to_r ) + { + char ch = 0; + bool indent = true; + while ( from_r && from_r.get( ch ) ) + { + if ( indent ) + to_r << indent_r; + indent = ( ch == '\n' ); + to_r.put( ch ); + } + } + return to_r; + } + + /** Copy istream to ostream, prefixing each line with \a indent_r (default "> " ). + * \return reference to the ostream. + */ + inline void tee( std::istream & from_r, std::ostream & to1_r, std::ostream & to2_r ) + { + if ( from_r && ( to1_r ||to2_r ) ) + { + char ch = 0; + while ( from_r && from_r.get( ch ) ) + { + to1_r.put( ch ); + to2_r.put( ch ); + } + } + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : EachLine + // + /** Simple lineparser: Traverse each line in a file. + * + * \code + * std::ifstream infile( "somefile" ); + * for( iostr::EachLine in( infile ); in; in.next() ) + * { + * DBG << *in << endl; + * } + * \endcode + */ + class ZYPP_API EachLine : private base::NonCopyable + { + public: + /** Ctor taking a stream and reading the 1st line from it. */ + EachLine( std::istream & str_r, unsigned lineNo_r = 0 ); + + /** Whether \c this contains a valid line to consume. */ + bool valid() const + { return _valid; } + + /** Evaluate class in a boolean context. */ + explicit operator bool() const + { return _valid; } + + /** Return the current line number. */ + unsigned lineNo() const + { return _lineNo; } + + std::streamoff lineStart() const + { return _lineStart; }; + + /** Set current line number. */ + void setLineNo( unsigned lineNo_r ) + { _lineNo = lineNo_r; } + + /** Access the current line. */ + const std::string & operator*() const + { return _line; } + /** \overload non const access */ + std::string & operator*() + { return _line; } + + /** Access the current line. */ + const std::string * operator->() const + { return &_line; } + + /** Advance to next line. */ + bool next(); + + /** Advance \a num_r lines. */ + bool next( unsigned num_r ) + { + while ( num_r-- && next() ) + ; /* EMPTY */ + return valid(); + } + + private: + std::istream & _str; + std::string _line; + std::streamoff _lineStart; + unsigned _lineNo; + bool _valid; + }; + /////////////////////////////////////////////////////////////////// + + /** Simple lineparser: Call functor \a consume_r for each line. + * + * \param str_r istream to read from. + * \param consume_r callback function taking linenumber and content + * + * The loop is aborted if the callback returns \c false. + * + * \code + * iostr::forEachLine( InputStream( "/my/file/to/read.txt" ), + * []( int num_r, std::string line_r )->bool + * { + * MIL << " [" num_r << "]'" << line_r << "'" << endl; + * return true; + * } ); + * \endcode + * + * \return Number if lines consumed (negative if aborted by callback). + */ + int forEachLine( std::istream & str_r, const function& consume_r ) ZYPP_API; + + /** \ref simpleParseFile modifications before consuming a line. */ + enum ParseFlag + { + PF_LTRIM = 1 << 0, //< left trim whitespace + PF_RTRIM = 1 << 1, //< right trim whitespace + PF_TRIM = PF_LTRIM | PF_RTRIM, //< trim whitespace + PF_SKIP_EMPTY = 1 << 2, //< skip lines containing whitespace only + PF_SKIP_SHARP_COMMENT = 1 << 3 //< skip lines beginning with '#' + }; + ZYPP_DECLARE_FLAGS( ParseFlags, ParseFlag ); + ZYPP_DECLARE_OPERATORS_FOR_FLAGS( ParseFlags ); + + /** Simple lineparser optionally trimming and skipping comments. */ + int simpleParseFile( std::istream & str_r, ParseFlags flags_r, function consume_r ) ZYPP_API; + + /** \overload trimming lines, skipping '#'-comments and empty lines. */ + inline int simpleParseFile( std::istream & str_r, function consume_r ) + { return simpleParseFile( str_r, PF_TRIM | PF_SKIP_EMPTY | PF_SKIP_SHARP_COMMENT , std::move(consume_r) ); } + + ///////////////////////////////////////////////////////////////// + } // namespace iostr + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_IOSTREAM_H diff --git a/zypp-core/base/IOTools.cc b/zypp-core/base/IOTools.cc new file mode 100644 index 0000000..acbb879 --- /dev/null +++ b/zypp-core/base/IOTools.cc @@ -0,0 +1,187 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/IOTools.cc + * +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +namespace zypp::io { + + BlockingMode setFILEBlocking (FILE * file, bool mode ) + { + if ( !file ) return BlockingMode::FailedToSetMode; + return setFDBlocking( ::fileno( file ), mode ); + } + + BlockingMode setFDBlocking(int fd, bool mode) + { + if ( fd == -1 ) + { ERR << strerror( errno ) << std::endl; return BlockingMode::FailedToSetMode; } + + int flags = zyppng::eintrSafeCall( ::fcntl, fd, F_GETFL ); + + if ( flags == -1 ) + { ERR << strerror( errno ) << std::endl; return BlockingMode::FailedToSetMode; } + + BlockingMode oldMode = ( flags & O_NONBLOCK ) == O_NONBLOCK ? BlockingMode::WasNonBlocking : BlockingMode::WasBlocking; + if ( !mode ) + flags = flags | O_NONBLOCK; + else if ( flags & O_NONBLOCK ) + flags = flags ^ O_NONBLOCK; + + flags = zyppng::eintrSafeCall( ::fcntl, fd,F_SETFL,flags ); + + if ( flags == -1 ) + { ERR << strerror(errno) << std::endl; return BlockingMode::FailedToSetMode; } + + return oldMode; + } + + bool writeAll(int fd, void *buf, size_t size) + { + char *tmpBuf = ( char *) buf; + + size_t written = 0; + while ( written < size ) { + const auto res = zyppng::eintrSafeCall( ::write, fd, tmpBuf+written, size-written ); + if ( res < 0 ) // error + return false; + written += res; + } + return true; + } + + ReadAllResult readAll (int fd, void *buf, size_t size ) + { + char *tmpBuf = (char *)buf; + size_t read = 0; + while ( read != size ) { + const auto r = zyppng::eintrSafeCall( ::read, fd, tmpBuf+read, size - read ); + if ( r == 0 ) + return ReadAllResult::Eof; + if ( r < 0 ) + return ReadAllResult::Error; + + read += r; + } + return ReadAllResult::Ok; + } + + std::pair receiveUpto(FILE *file, char c, timeout_type timeout, bool failOnUnblockError ) + { + FILE * inputfile = file; + if ( !file ) + return std::make_pair( ReceiveUpToResult::Error, std::string() ); + + int inputfileFd = ::fileno( inputfile ); + + size_t linebuffer_size = 0; + zypp::AutoFREE linebuf; + + const auto prevMode = setFILEBlocking( file, false ); + if ( prevMode == BlockingMode::FailedToSetMode && failOnUnblockError ) + return std::make_pair( ReceiveUpToResult::Error, std::string() ); + + // reset the blocking mode when we are done + zypp::OnScopeExit resetMode([ prevMode, fd = file ]( ){ + if ( prevMode == BlockingMode::WasBlocking ) + setFILEBlocking( fd, true ); + }); + + bool haveTimeout = (timeout != no_timeout); + int remainingTimeout = static_cast( timeout ); + zypp::AutoDispose timer( nullptr ); + if ( haveTimeout ) + timer = zypp::AutoDispose( g_timer_new(), &g_free ); + + std::string line; + do + { + /* Watch inputFile to see when it has input. */ + + GPollFD fd; + fd.fd = inputfileFd; + fd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; + fd.revents = 0; + + if ( timer ) + g_timer_start( timer ); + + clearerr( inputfile ); + + int retval = zyppng::eintrSafeCall( g_poll, &fd, 1, remainingTimeout ); + if ( retval == -1 ) + { + ERR << "select error: " << zyppng::strerr_cxx() << std::endl; + return std::make_pair( ReceiveUpToResult::Error, std::string() ); + } + else if ( retval ) + { + // Data is available now. + ssize_t nread = zyppng::eintrSafeCallEx( ::getdelim, [&](){ clearerr( inputfile ); }, &linebuf.value(), &linebuffer_size, c, inputfile ); + if ( nread == -1 ) { + if ( ::feof( inputfile ) ) { + return std::make_pair( ReceiveUpToResult::EndOfFile, std::move(line) ); + } + if ( errno != EAGAIN && ( ::ferror( inputfile ) || errno != 0 ) ) { + if ( errno ) ERR << "getdelim error: " << zyppng::strerr_cxx() << std::endl; + else ERR << "Unknown getdelim error." << std::endl; + return std::make_pair( ReceiveUpToResult::Error, std::string() ); + } + } + else + { + if ( nread > 0 ) + line += std::string( linebuf, nread ); + + if ( ! ::ferror( inputfile ) || ::feof( inputfile ) ) { + return std::make_pair( ReceiveUpToResult::Success, std::move(line) ); // complete line + } + } + } + + // we timed out, or were interrupted for some reason + // check if we can wait more + if ( timer ) { + remainingTimeout -= g_timer_elapsed( timer, nullptr ) * 1000; + if ( remainingTimeout <= 0 ) + return std::make_pair( ReceiveUpToResult::Timeout, std::move(line) ); + } + } while ( true ); + } + + TimeoutException::~TimeoutException() noexcept + { } + + std::vector peek_data_fd( FILE *fd, off_t offset, size_t count ) + { + if ( !fd ) + return {}; + + fflush( fd ); + + std::vector data( count + 1 , '\0' ); + + ssize_t l = zyppng::eintrSafeCall( pread, fileno( fd ), data.data(), count, offset ); + if (l == -1) + return {}; + + return data; + } + +} diff --git a/zypp-core/base/IOTools.h b/zypp-core/base/IOTools.h new file mode 100644 index 0000000..c36cfbc --- /dev/null +++ b/zypp-core/base/IOTools.h @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/IOTools.h + * +*/ +#ifndef ZYPP_BASE_IOTOOLS_H +#define ZYPP_BASE_IOTOOLS_H + +#include +#include +#include +#include + +namespace zypp::io { + + enum class BlockingMode{ + FailedToSetMode = -1, ///< Failed to block or unblock the fd + WasBlocking, ///< FD was blocking before + WasNonBlocking ///< FD was non blocking before + }; + + /** + * Enables or disabled non blocking mode on a file descriptor. + * The return value is one of the \ref zypp::io::BlockingMode values + */ + BlockingMode setFILEBlocking ( FILE *file, bool mode = true ); + BlockingMode setFDBlocking ( int fd, bool mode = true ); + + + /*! + Blocks until all data in buf was written to the fd or a error occured + */ + bool writeAll ( int fd, void *buf, size_t size ); + + /*! + Blocks until the number of bytes passed via \a size was received + */ + enum class ReadAllResult { + Error, + Eof, + Ok + }; + ReadAllResult readAll ( int fd, void *buf, size_t size ); + + class ZYPP_API TimeoutException : public Exception + { + public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + TimeoutException() : Exception( "Timeout Exception" ) + {} + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + TimeoutException( const std::string & msg_r ) + : Exception( msg_r ) + {} + + /** Dtor. */ + ~TimeoutException() noexcept override; + }; + + enum ReceiveUpToResult { + Success, + Timeout, + EndOfFile, + Error, + }; + + using timeout_type = size_t; + static constexpr timeout_type no_timeout = static_cast(-1); + + /*! + * Reads data from \a file until it finds a seperator \a c, hits the end of the file or times out. + * The \a timeout value is specified in milliseconds, a timeout of -1 means no timeout. + * If \a failOnUnblockError is set to false the function will not error out if unblocking + * the file descriptor did not work. The default is to fail if it's not possible to unblock the file. + */ + std::pair receiveUpto( FILE * file, char c, timeout_type timeout, bool failOnUnblockError = true ); + + /*! + * Fetches data from a FILE without changing the current file offset + */ + std::vector peek_data_fd ( FILE *fd, off_t offset, size_t count ); +} + +#endif + diff --git a/zypp-core/base/InputStream b/zypp-core/base/InputStream new file mode 100644 index 0000000..05489a6 --- /dev/null +++ b/zypp-core/base/InputStream @@ -0,0 +1 @@ +#include "inputstream.h" diff --git a/zypp-core/base/Iterable.h b/zypp-core/base/Iterable.h new file mode 100644 index 0000000..a87c211 --- /dev/null +++ b/zypp-core/base/Iterable.h @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Iterable.h + */ +#ifndef ZYPP_BASE_ITERABLE_H +#define ZYPP_BASE_ITERABLE_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class Iterable + /// \brief + /// \code + /// struct Foo + /// { + /// class Iterator; + /// typedef Iterable IterableType; + /// + /// Iterator myBegin(); + /// Iterator myEnd(); + /// + /// IterableType iterate() { return makeIterable( myBegin(), myEnd() ); } + /// }; + /// \endcode + /////////////////////////////////////////////////////////////////// + template + class Iterable + { + public: + using size_type = size_t; + using iterator_type = TIterator; + using value_type = typename std::iterator_traits::value_type; + using difference_type = typename std::iterator_traits::difference_type; + using pointer = typename std::iterator_traits::pointer; + using reference = typename std::iterator_traits::reference; + using iterator_category = typename std::iterator_traits::iterator_category; + + /** Ctor taking the iterator pair */ + Iterable() + {} + + /** Ctor taking the iterator pair */ + Iterable( iterator_type begin_r, iterator_type end_r ) + : _begin( std::move(begin_r) ) + , _end( std::move(end_r) ) + {} + + /** Ctor taking the iterator pair */ + Iterable( std::pair range_r ) + : _begin( std::move(range_r.first) ) + , _end( std::move(range_r.second) ) + {} + + iterator_type begin() const + { return _begin; } + + iterator_type end() const + { return _end; } + + bool empty() const + { return( _begin == _end ); } + + size_type size() const + { size_type ret = 0; for ( iterator_type i = _begin; i != _end; ++i ) ++ret; return ret; } + + bool contains( const value_type & val_r ) const + { return( find( val_r ) != _end ); } + + iterator_type find( const value_type & val_r ) const + { iterator_type ret = _begin; for ( ; ret != _end; ++ret ) if ( *ret == val_r ) break; return ret; } + + private: + iterator_type _begin; + iterator_type _end; + }; + + /** \relates Iterable convenient construction. */ + template + Iterable makeIterable( TIterator && begin_r, TIterator && end_r ) + { return Iterable( std::forward(begin_r), std::forward(end_r) ); } + + /** \relates Iterable convenient construction. */ + template + Iterable makeIterable( std::pair &&range_r ) + { return Iterable( std::move(range_r) ); } +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_ITERABLE_H diff --git a/zypp-core/base/Iterator.h b/zypp-core/base/Iterator.h new file mode 100644 index 0000000..791973c --- /dev/null +++ b/zypp-core/base/Iterator.h @@ -0,0 +1,297 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Iterator.h + * +*/ +#ifndef ZYPP_BASE_ITERATOR_H +#define ZYPP_BASE_ITERATOR_H + +#include +#include + +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** \defgroup ITERATOR Boost.Iterator Library + * + * \see http://www.boost.org/libs/iterator/doc/index.html + * + * \li \b counting_iterator: an iterator over a sequence of + * consecutive values. Implements a "lazy sequence" + * \li \b filter_iterator: an iterator over the subset of elements + * of some sequence which satisfy a given predicate + * \li \b function_output_iterator: an output iterator wrapping a + * unary function object; each time an element is written into + * the dereferenced iterator, it is passed as a parameter to + * the function object. + * \li \b indirect_iterator: an iterator over the objects pointed-to + * by the elements of some sequence. + * \li \b permutation_iterator: an iterator over the elements of + * some random-access sequence, rearranged according to some + * sequence of integer indices. + * \li \b reverse_iterator: an iterator which traverses the elements + * of some bidirectional sequence in reverse. Corrects many of the shortcomings of C++98's std::reverse_iterator. + * \li \b shared_container_iterator: an iterator over elements of + * a container whose lifetime is maintained by a shared_ptr + * stored in the iterator. + * \li \b transform_iterator: an iterator over elements which are + * the result of applying some functional transformation to + * the elements of an underlying sequence. This component + * also replaces the old projection_iterator_adaptor. + * \li \b zip_iterator: an iterator over tuples of the elements + * at corresponding positions of heterogeneous underlying + * iterators. + * + * There are in fact more interesting iterator concepts + * available than the ones listed above. Have a look at them. + * + * Some of the iterator types are already dragged into namespace + * zypp. Feel free to add what's missing. + * + * \todo Separate them into individual zypp header files. + */ + //@{ + + /** \class filter_iterator + * An iterator over the subset of elements of some sequence + * which satisfy a given predicate. + * + * Provides boost::filter_iterator and boost::make_filter_iterator + * convenience function. + * \see http://www.boost.org/libs/iterator/doc/filter_iterator.html + * \code + * template + * filter_iterator + * make_filter_iterator(Predicate f, Iterator x, Iterator end = Iterator()); + * + * template + * filter_iterator + * make_filter_iterator(Iterator x, Iterator end = Iterator()); + * \endcode + * Remember the deduction rules for template arguments. + * \code + * struct MyDefaultConstructibleFilter; + * make_filter_iterator( c.begin(), c.end() ); + * make_filter_iterator( MyDefaultConstructibleFilter(), c.begin(), c.end() ); + * ... + * make_filter_iterator( resfilter::ByName("foo"), c.begin(), c.end() ); + * + * \endcode + */ + using boost::filter_iterator; + using boost::make_filter_iterator; + + /** Convenience to create filter_iterator from container::begin(). */ + template + filter_iterator + make_filter_begin( TFilter f, const TContainer & c ) + { + return make_filter_iterator( f, c.begin(), c.end() ); + } + + /** Convenience to create filter_iterator from container::begin(). */ + template + filter_iterator + make_filter_begin( const TContainer & c ) + { + return make_filter_iterator( TFilter(), c.begin(), c.end() ); + } + + /** Convenience to create filter_iterator from container::end(). */ + template + filter_iterator + make_filter_end( TFilter f, const TContainer & c ) + { + return make_filter_iterator( f, c.end(), c.end() ); + } + + /** Convenience to create filter_iterator from container::end(). */ + template + filter_iterator + make_filter_end( const TContainer & c ) + { + return make_filter_iterator( TFilter(), c.end(), c.end() ); + } + + /** \class transform_iterator + * An iterator over elements which are the result of applying + * some functional transformation to the elements of an underlying + * sequence. + * + * Provides boost::transform_iterator and boost::make_transform_iterator + * convenience function. + * \see http://www.boost.org/libs/iterator/doc/transform_iterator.html + * \code + * template + * transform_iterator + * make_transform_iterator(Iterator it, UnaryFunction fun); + * + * template + * transform_iterator + * make_transform_iterator(Iterator it); + * \endcode + */ + using boost::transform_iterator; + using boost::make_transform_iterator; + + /** Functor taking a \c std::pair returning \c std::pair.first. + * \see MapKVIteratorTraits + */ + template + struct GetPairFirst + { + const typename TPair::first_type & operator()( const TPair & pair_r ) const + { return pair_r.first; } + }; + + /** Functor taking a \c std::pair returning \c std::pair.second . + * \see MapKVIteratorTraits + */ + template + struct GetPairSecond + { + const typename TPair::second_type & operator()( const TPair & pair_r ) const + { return pair_r.second; } + }; + + /** Traits for std::map key and value iterators. + * + * \ref GetPairFirst and \ref GetPairSecond help building a transform_iterator + * that iterates over keys or values of a std::map. Class MapKVIteratorTraits + * provides some typedefs, you usg. do not want to write explicitly. + * + * \code + * // typedefs + * typedef std::map MapType; + * + * // transform_iterator, MapType::const_iterator> + * typedef MapKVIteratorTraits::Key_const_iterator MapTypeKey_iterator; + * // transform_iterator, MapType::const_iterator> + * typedef MapKVIteratorTraits::Value_const_iterator MapTypeValue_iterator; + * + * // usage + * MapType mymap; + * + * MapTypeKey_const_iterator keyBegin( make_map_key_begin( mymap ) ); + * MapTypeKey_const_iterator keyEnd ( make_map_key_end( mymap ) ); + * + * MapTypeValue_const_iterator valBegin( make_map_value_begin( mymap ) ); + * MapTypeValue_const_iterator valEnd ( make_map_value_end( mymap ) ); + * + * std::for_each( keyBegin, keyEnd, DoSomething() ); + * std::for_each( valBegin, valEnd, DoSomething() ); + * \endcode + * + * Or short: + * + * \code + * typedef std::map MapType; + * MapType mymap; + * + * std::for_each( make_map_key_begin( mymap ), make_map_key_end( mymap ), DoSomething() ); + * std::for_each( make_map_value_begin( mymap ), make_map_value_end( mymap ), DoSomething() ); + * \endcode + */ + template + struct MapKVIteratorTraits + { + /** The map type */ + using MapType = TMap; + /** The maps key type */ + using KeyType = typename TMap::key_type; + /** The key iterator type */ + using Key_const_iterator = transform_iterator, typename MapType::const_iterator>; + /** The maps value (mapped) type */ + using ValueType = typename TMap::mapped_type; + /** The value iterator type */ + using Value_const_iterator = transform_iterator, typename MapType::const_iterator>; + }; + + /** Convenience to create the key iterator from container::begin() */ + template + inline typename MapKVIteratorTraits::Key_const_iterator make_map_key_begin( const TMap & map_r ) + { return make_transform_iterator( map_r.begin(), GetPairFirst() ); } + + /** Convenience to create the key iterator from container::end() */ + template + inline typename MapKVIteratorTraits::Key_const_iterator make_map_key_end( const TMap & map_r ) + { return make_transform_iterator( map_r.end(), GetPairFirst() ); } + + /** Convenience to create the value iterator from container::begin() */ + template + inline typename MapKVIteratorTraits::Value_const_iterator make_map_value_begin( const TMap & map_r ) + { return make_transform_iterator( map_r.begin(), GetPairSecond() ); } + + /** Convenience to create the value iterator from container::end() */ + template + inline typename MapKVIteratorTraits::Value_const_iterator make_map_value_end( const TMap & map_r ) + { return make_transform_iterator( map_r.end(), GetPairSecond() ); } + + /** Convenience to create the key iterator from container::lower_bound() */ + template + inline typename MapKVIteratorTraits::Key_const_iterator make_map_key_lower_bound( const TMap & map_r, const typename TMap::key_type & key_r ) + { return make_transform_iterator( map_r.lower_bound( key_r ), GetPairFirst() ); } + + /** Convenience to create the key iterator from container::upper_bound() */ + template + inline typename MapKVIteratorTraits::Key_const_iterator make_map_key_upper_bound( const TMap & map_r, const typename TMap::key_type & key_r ) + { return make_transform_iterator( map_r.upper_bound( key_r ), GetPairFirst() ); } + + /** Convenience to create the value iterator from container::lower_bound() */ + template + inline typename MapKVIteratorTraits::Value_const_iterator make_map_value_lower_bound( const TMap & map_r, const typename TMap::key_type & key_r ) + { return make_transform_iterator( map_r.lower_bound( key_r ), GetPairSecond() ); } + + /** Convenience to create the value iterator from container::upper_bound() */ + template + inline typename MapKVIteratorTraits::Value_const_iterator make_map_value_upper_bound( const TMap & map_r, const typename TMap::key_type & key_r ) + { return make_transform_iterator( map_r.upper_bound( key_r ), GetPairSecond() ); } + + + /** Convenience to create an \ref Iterable over the container keys */ + template + inline Iterable::Key_const_iterator> make_map_key_Iterable( const TMap & map_r ) + { return makeIterable( make_map_key_begin( map_r ), make_map_key_end( map_r ) ); } + + /** Convenience to create an \ref Iterable over the container values */ + template + inline Iterable::Value_const_iterator> make_map_value_Iterable( const TMap & map_r ) + { return makeIterable( make_map_value_begin( map_r ), make_map_value_end( map_r ) ); } + + + /** \class function_output_iterator + * An output iterator wrapping a unary function object; each time an + * element is written into the dereferenced iterator, it is passed as + * a parameter to the function object. + * + * Provides boost::function_output_iterator and boost::make_function_output_iterator + * convenience function. + * \see http://www.boost.org/libs/iterator/doc/function_output_iterator.html + * \code + * template + * function_output_iterator + * make_function_output_iterator(const UnaryFunction& f = UnaryFunction()); + * \endcode + */ + using boost::function_output_iterator; + using boost::make_function_output_iterator; + + //@} + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_ITERATOR_H diff --git a/zypp-core/base/LogControl.cc b/zypp-core/base/LogControl.cc new file mode 100644 index 0000000..6a3f25f --- /dev/null +++ b/zypp-core/base/LogControl.cc @@ -0,0 +1,977 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/LogControl.cc + * +*/ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +extern "C" +{ +#include +#include +#include +#include +#include +} + +using std::endl; + +std::once_flag flagReadEnvAutomatically; + +namespace zypp +{ + constexpr std::string_view ZYPP_MAIN_THREAD_NAME( "Zypp-main" ); + + template inline constexpr bool always_false_v = false; + + /*! + * \internal Provides a very simply lock that is using atomics so it can be + * safely used in signal handlers + */ + class SpinLock { + public: + void lock () { + // acquire lock + while ( _atomicLock.test_and_set()) + // Reschedule the current thread while we wait. Maybe, when it is our next turn, the lock is free again. + std::this_thread::yield(); + } + + void unlock() { + _atomicLock.clear(); + } + + private: + // we use a lock-free atomic flag here, so this lock can be safely obtained in a signal handler as well + std::atomic_flag _atomicLock = ATOMIC_FLAG_INIT; + }; + + class LogThread + { + + public: + LogThread(const LogThread &) = delete; + LogThread(LogThread &&) = delete; + LogThread &operator=(const LogThread &) = delete; + LogThread &operator=(LogThread &&) = delete; + + ~LogThread() { stop(); } + + static LogThread &instance () { + static LogThread t; + return t; + } + + void setLineWriter ( boost::shared_ptr writer ) { + std::lock_guard lk( _lineWriterLock ); + _lineWriter = std::move(writer); + } + + boost::shared_ptr getLineWriter () { + std::lock_guard lk( _lineWriterLock ); + auto lw = _lineWriter; + return lw; + } + + void stop () { + _stopSignal.notify(); + if ( _thread.get_id() != std::this_thread::get_id() ) + _thread.join(); + } + + std::thread::id threadId () { + return _thread.get_id(); + } + + static std::string sockPath () { + static std::string path = zypp::str::Format("zypp-logsocket-%1%") % getpid(); + return path; + } + + private: + + LogThread () + { + // Name the thread that started the logger, assuming it's the main thread. + zyppng::ThreadData::current().setName(ZYPP_MAIN_THREAD_NAME); + _thread = std::thread( [this] () { + workerMain(); + }); + } + + void workerMain () { + + // force the kernel to pick another thread to handle signals + zyppng::blockAllSignalsForCurrentThread(); + + zyppng::ThreadData::current().setName("Zypp-Log"); + + auto ev = zyppng::EventLoop::create(); + auto server = zyppng::Socket::create( AF_UNIX, SOCK_STREAM, 0 ); + auto stopNotifyWatch = _stopSignal.makeNotifier( ); + + std::vector clients; + + // bind to a abstract unix domain socket address, which means we do not need to care about cleaning it up + server->bind( std::make_shared( sockPath(), true ) ); + server->listen(); + + // wait for incoming connections from other threads + server->connectFunc( &zyppng::Socket::sigIncomingConnection, [&](){ + + auto cl = server->accept(); + if ( !cl ) return; + clients.push_back( cl ); + + // wait until data is available, we operate line by line so we only + // log a string once we encounter \n + cl->connectFunc( &zyppng::Socket::sigReadyRead, [ this, sock = cl.get() ](){ + auto writer = getLineWriter(); + if ( !writer ) return; + while ( sock->canReadLine() ) { + auto br = sock->readLine(); + writer->writeOut( std::string( br.data(), br.size() - 1 ) ); + } + }, *cl); + + // once a client disconnects we remove it from the std::vector so that the socket is not leaked + cl->connectFunc( &zyppng::Socket::sigDisconnected, [&clients, sock = std::weak_ptr(cl)](){ + auto lock = sock.lock(); + if ( !lock ) + return; + + auto idx = std::find_if( clients.begin(), clients.end(), [lock]( const auto &s ){ return lock.get() == s.get(); } ); + clients.erase( idx ); + }); + + }); + + stopNotifyWatch->connectFunc( &zyppng::SocketNotifier::sigActivated, [&ev]( const auto &, auto ) { + ev->quit(); + }); + + ev->run(); + + // make sure we have written everything + auto writer = getLineWriter(); + if ( writer ) { + for ( auto &sock : clients ){ + auto br = sock->readLine(); + while ( !br.empty() ) { + if ( br.back () == '\n' ) + writer->writeOut( std::string( br.data(), br.size() - 1 ) ); + else + writer->writeOut( std::string( br.data(), br.size() ) ); + + br = sock->readLine(); + } + } + } + } + + private: + std::thread _thread; + zyppng::Wakeup _stopSignal; + + // since the public API uses boost::shared_ptr we can not use the atomic + // functionalities provided in std. + // this lock type can be used safely in signals + SpinLock _lineWriterLock; + // boost shared_ptr has a lock free implementation of reference counting so it can be used from signal handlers as well + boost::shared_ptr _lineWriter{ nullptr }; + }; + + class LogClient + { + public: + LogClient(){ + // make sure the thread is running + LogThread::instance(); + } + + LogClient(const LogClient &) = delete; + LogClient(LogClient &&) = delete; + LogClient &operator=(const LogClient &) = delete; + LogClient &operator=(LogClient &&) = delete; + + ~LogClient() { if (_sockFD >= 0) ::close(_sockFD); } + + /*! + * Tries to connect to the log threads socket, returns true on success or + * if the socket is already connected + */ + bool ensureConnection () { + if ( _sockFD >= 0 ) + return true; + + _sockFD = ::socket( AF_UNIX, SOCK_STREAM, 0 ); + if ( _sockFD == -1 ) + return false; + + zyppng::UnixSockAddr addr( LogThread::sockPath(), true ); + return zyppng::trySocketConnection( _sockFD, addr, 100 ); + } + + /*! + * Sends a message to the log thread. + */ + void pushMessage ( std::string msg ) { + if ( inPushMessage ) { + return; + } + + // make sure we do not end up in a busy loop + zypp::AutoDispose res( &inPushMessage, [](auto val){ + *val = false; + }); + inPushMessage = true; + + // if we are in the same thread as the Log worker we can directly push our messages out, no need to use the socket + if ( std::this_thread::get_id() == LogThread::instance().threadId() ) { + auto writer = LogThread::instance().getLineWriter(); + if ( writer ) + writer->writeOut( msg ); + return; + } + + if(!ensureConnection()) + return; + + if ( msg.back() != '\n' ) + msg.push_back('\n'); + + size_t written = 0; + while ( written < msg.size() ) { + const auto res = zyppng::eintrSafeCall( ::send, _sockFD, msg.data() + written, msg.size() - written, MSG_NOSIGNAL ); + if ( res == -1 ) { + //assume broken socket + ::close( _sockFD ); + _sockFD = -1; + return; + } + written += res; + } + } + + private: + int _sockFD = -1; + bool inPushMessage = false; + }; + +#ifndef ZYPP_NDEBUG + namespace debug + { + // Fg::Black: 30 Bg: 40 Attr::Normal: 22;27 + // Fg::Red: 31 ... Attr::Bright: 1 + // Fg::Green: 32 Attr::Reverse: 7 + // Fg::Yellow: 33 + // Fg::Blue: 34 + // Fg::Magenta: 35 + // Fg::Cyan: 36 + // Fg::White: 37 + // Fg::Default: 39 + static constexpr std::string_view OO { "\033[0m" }; + static constexpr std::string_view WH { "\033[37;40m" }; + static constexpr std::string_view CY { "\033[36;40m" }; + static constexpr std::string_view YE { "\033[33;1;40m" }; + static constexpr std::string_view GR { "\033[32;40m" }; + static constexpr std::string_view RE { "\033[31;1;40m" }; + static constexpr std::string_view MA { "\033[35;40m" }; + + unsigned TraceLeave::_depth = 1; + + std::string tracestr( char tag_r, unsigned depth_r, const char * file_r, const char * fnc_r, int line_r ) + { + static str::Format fmt { "*** %s %s(%s):%d" }; + fmt % std::string(depth_r,tag_r) % file_r % fnc_r % line_r; + return fmt; + } + + TraceLeave::TraceLeave( const char * file_r, const char * fnc_r, int line_r ) + : _file( std::move(file_r) ) + , _fnc( std::move(fnc_r) ) + , _line( line_r ) + { + const std::string & m { tracestr( '>',_depth++, _file,_fnc,_line ) }; + USR << m << endl; + Osd(L_USR("TRACE"),1) << m << endl; + } + + TraceLeave::~TraceLeave() + { + const std::string & m { tracestr( '<',--_depth, _file,_fnc,_line ) }; + USR << m << endl; + Osd(L_USR("TRACE"),1) << m << endl; + } + + Osd::Osd( std::ostream & str, int i ) + : _strout { std::cerr } + , _strlog { str } + { _strout << (i?WH:YE); } + + Osd::~Osd() + { _strout << OO; } + + Osd & Osd::operator<<( std::ostream& (*iomanip)( std::ostream& ) ) + { + _strout << iomanip; + _strlog << iomanip; + return *this; + } +} +#endif // ZYPP_NDEBUG + + /////////////////////////////////////////////////////////////////// + namespace log + { ///////////////////////////////////////////////////////////////// + + StdoutLineWriter::StdoutLineWriter() + : StreamLineWriter( std::cout ) + {} + + StderrLineWriter::StderrLineWriter() + : StreamLineWriter( std::cerr ) + {} + + FileLineWriter::FileLineWriter( const Pathname & file_r, mode_t mode_r ) + { + if ( file_r == Pathname("-") ) + { + _str = &std::cerr; + } + else + { + if ( mode_r ) + { + // not filesystem::assert_file as filesystem:: functions log, + // and this FileWriter is not yet in place. + int fd = ::open( file_r.c_str(), O_CREAT|O_EXCL, mode_r ); + if ( fd != -1 ) + ::close( fd ); + } + // set unbuffered write + std::ofstream * fstr = 0; + _outs.reset( (fstr = new std::ofstream( file_r.asString().c_str(), std::ios_base::app )) ); + fstr->rdbuf()->pubsetbuf(0,0); + _str = &(*fstr); + } + } + + ///////////////////////////////////////////////////////////////// + } // namespace log + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace logger + { ///////////////////////////////////////////////////////////////// + + inline void putStream( const std::string & group_r, LogLevel level_r, + const char * file_r, const char * func_r, int line_r, + const std::string & buffer_r ); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Loglinebuf + // + class Loglinebuf : public std::streambuf { + + public: + /** */ + Loglinebuf( std::string group_r, LogLevel level_r ) + : _group(std::move( group_r )) + , _level( level_r ) + , _file( "" ) + , _func( "" ) + , _line( -1 ) + {} + + Loglinebuf(const Loglinebuf &) = default; + Loglinebuf(Loglinebuf &&) = default; + Loglinebuf &operator=(const Loglinebuf &) = default; + Loglinebuf &operator=(Loglinebuf &&) = default; + + /** */ + ~Loglinebuf() override + { + if ( !_buffer.empty() ) + writeout( "\n", 1 ); + } + + /** */ + void tagSet( const char * fil_r, const char * fnc_r, int lne_r ) + { + _file = fil_r; + _func = fnc_r; + _line = lne_r; + } + + private: + /** */ + std::streamsize xsputn( const char * s, std::streamsize n ) override + { return writeout( s, n ); } + /** */ + int overflow( int ch = EOF ) override + { + if ( ch != EOF ) + { + char tmp = ch; + writeout( &tmp, 1 ); + } + return 0; + } + /** */ + virtual int writeout( const char* s, std::streamsize n ) + { + //logger::putStream( _group, _level, _file, _func, _line, _buffer ); + //return n; + if ( s && n ) + { + const char * c = s; + for ( int i = 0; i < n; ++i, ++c ) + { + if ( *c == '\n' ) { + _buffer += std::string( s, c-s ); + logger::putStream( _group, _level, _file, _func, _line, _buffer ); + _buffer = std::string(); + s = c+1; + } + } + if ( s < c ) + { + _buffer += std::string( s, c-s ); + } + } + return n; + } + + private: + std::string _group; + LogLevel _level; + const char * _file; + const char * _func; + int _line; + std::string _buffer; + }; + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Loglinestream + // + class Loglinestream { + + public: + /** */ + Loglinestream( const std::string & group_r, LogLevel level_r ) + : _mybuf( group_r, level_r ) + , _mystream( &_mybuf ) + {} + + Loglinestream(const Loglinestream &) = delete; + Loglinestream(Loglinestream &&) = delete; + Loglinestream &operator=(const Loglinestream &) = delete; + Loglinestream &operator=(Loglinestream &&) = delete; + + /** */ + ~Loglinestream() + { _mystream.flush(); } + + public: + /** */ + std::ostream & getStream( const char * fil_r, const char * fnc_r, int lne_r ) + { + _mybuf.tagSet( fil_r, fnc_r, lne_r ); + return _mystream; + } + + private: + Loglinebuf _mybuf; + std::ostream _mystream; + }; + /////////////////////////////////////////////////////////////////// + + struct LogControlImpl; + + /* + * Ugly hack to prevent the use of LogControlImpl when libzypp is shutting down. + * Due to the C++ standard, thread_local static instances are cleaned up before the first global static + * destructor is called. So all classes that use logging after that point in time would crash the + * application because it is accessing a variable that has already been destroyed. + */ + int &logControlValidFlag() { + // We are using a POD flag that does not have a destructor, + // to flag if the thread_local destructors were already executed. + // Since TLS data is stored in a segment that is available until the thread ceases to exist it should still be readable + // after thread_local c++ destructors were already executed. Or so I hope. + static thread_local int logControlValid = 0; + return logControlValid; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LogControlImpl + // + /** LogControl implementation (thread_local Singleton). + * + * \note There is a slight difference in using the _lineFormater and _lineWriter! + * \li \c _lineFormater must not be NULL (create default LogControl::LineFormater) + * \li \c _lineWriter is NULL if no logging is performed, this way we can pass + * _no_stream as logstream to the application, and avoid unnecessary formating + * of logliles, which would then be discarded when passed to some dummy + * LineWriter. + */ + struct LogControlImpl + { + public: + bool isExcessive() const { return _excessive; } + + void excessive( bool onOff_r ) + { _excessive = onOff_r; } + + + /** Hint for Formater whether to hide the thread name. */ + bool hideThreadName() const + { + if ( indeterminate(_hideThreadName) ) + _hideThreadName = ( zyppng::ThreadData::current().name() == ZYPP_MAIN_THREAD_NAME ); + return bool(_hideThreadName); + } + /** \overload Setter */ + void hideThreadName( bool onOff_r ) + { _hideThreadName = onOff_r; } + + /** \overload Static getter */ + static bool instanceHideThreadName() + { + auto impl = LogControlImpl::instance(); + return impl ? impl->hideThreadName() : false; + } + /** \overload Static setter */ + static void instanceHideThreadName( bool onOff_r ) + { + auto impl = LogControlImpl::instance(); + if ( impl ) impl->hideThreadName( onOff_r ); + } + + /** Hint for formatter wether we forward all logs to a parents log */ + static bool instanceLogToPPID( ) + { + auto impl = LogControlImpl::instance(); + return impl ? impl->_logToPPIDMode : false; + } + + /** \overload Static setter */ + static void instanceSetLogToPPID( bool onOff_r ) + { + auto impl = LogControlImpl::instance(); + if ( impl ) + impl->_logToPPIDMode = onOff_r; + } + + /** NULL _lineWriter indicates no loggin. */ + void setLineWriter( const shared_ptr & writer_r ) + { LogThread::instance().setLineWriter( writer_r ); } + + shared_ptr getLineWriter() const + { return LogThread::instance().getLineWriter(); } + + /** Assert \a _lineFormater is not NULL. */ + void setLineFormater( const shared_ptr & format_r ) + { + if ( format_r ) + _lineFormater = format_r; + else + _lineFormater.reset( new LogControl::LineFormater ); + } + + void logfile( const Pathname & logfile_r, mode_t mode_r = 0640 ) + { + if ( logfile_r.empty() ) + setLineWriter( shared_ptr() ); + else if ( logfile_r == Pathname( "-" ) ) + setLineWriter( shared_ptr(new log::StderrLineWriter) ); + else + setLineWriter( shared_ptr(new log::FileLineWriter(logfile_r, mode_r)) ); + } + + private: + LogClient _logClient; + std::ostream _no_stream; + bool _excessive; + bool _logToPPIDMode = false; ///< Hint for formatter to use the PPID and always show the thread name + mutable TriBool _hideThreadName = indeterminate; ///< Hint for Formater whether to hide the thread name. + + shared_ptr _lineFormater; + + public: + /** Provide the log stream to write (logger interface) */ + std::ostream & getStream( const std::string & group_r, + LogLevel level_r, + const char * file_r, + const char * func_r, + const int line_r ) + { + if ( ! getLineWriter() ) + return _no_stream; + if ( level_r == E_XXX && !_excessive ) + return _no_stream; + + if ( !_streamtable[group_r][level_r] ) + { + _streamtable[group_r][level_r].reset( new Loglinestream( group_r, level_r ) ); + } + std::ostream & ret( _streamtable[group_r][level_r]->getStream( file_r, func_r, line_r ) ); + if ( !ret ) + { + ret.clear(); + ret << "---format( group_r, level_r, + file_r, func_r, line_r, + message_r ) ); + } + + private: + using StreamPtr = shared_ptr; + using StreamSet = std::map; + using StreamTable = std::map; + /** one streambuffer per group and level */ + StreamTable _streamtable; + zyppng::Socket::Ptr _sock; + + private: + + void readEnvVars () { + if ( getenv("ZYPP_LOGFILE") ) + logfile( getenv("ZYPP_LOGFILE") ); + + if ( getenv("ZYPP_PROFILING") ) + { + shared_ptr formater(new ProfilingFormater); + setLineFormater(formater); + } + } + /** Singleton ctor. + * No logging per default, unless enabled via $ZYPP_LOGFILE. + */ + LogControlImpl() + : _no_stream( NULL ) + , _excessive( getenv("ZYPP_FULLLOG") ) + , _lineFormater( new LogControl::LineFormater ) + { + logControlValidFlag() = 1; + std::call_once( flagReadEnvAutomatically, &LogControlImpl::readEnvVars, this); + + // make sure the LogControl is invalidated when we fork + pthread_atfork( nullptr, nullptr, &LogControl::notifyFork ); + } + + public: + + LogControlImpl(const LogControlImpl &) = delete; + LogControlImpl(LogControlImpl &&) = delete; + LogControlImpl &operator=(const LogControlImpl &) = delete; + LogControlImpl &operator=(LogControlImpl &&) = delete; + + ~LogControlImpl() + { + logControlValidFlag() = 0; + } + + /** The LogControlImpl singleton + * \note As most dtors log, it is inportant that the + * LogControlImpl instance is the last static variable + * destructed. At least destucted after all statics + * which log from their dtor. + */ + static LogControlImpl *instance(); + }; + /////////////////////////////////////////////////////////////////// + + // 'THE' LogControlImpl singleton + inline LogControlImpl *LogControlImpl::instance() + { + thread_local static LogControlImpl _instance; + if ( logControlValidFlag() > 0 ) + return &_instance; + return nullptr; + } + + /////////////////////////////////////////////////////////////////// + + /** \relates LogControlImpl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const LogControlImpl & ) + { + return str << "LogControlImpl"; + } + + /////////////////////////////////////////////////////////////////// + // + // Access from logger:: + // + /////////////////////////////////////////////////////////////////// + + std::ostream & getStream( const char * group_r, + LogLevel level_r, + const char * file_r, + const char * func_r, + const int line_r ) + { + static std::ostream nstream(NULL); + auto control = LogControlImpl::instance(); + if ( !control || !group_r || strlen(group_r ) == 0 ) { + return nstream; + } + + + + return control->getStream( group_r, + level_r, + file_r, + func_r, + line_r ); + } + + /** That's what Loglinebuf calls. */ + inline void putStream( const std::string & group_r, LogLevel level_r, + const char * file_r, const char * func_r, int line_r, + const std::string & buffer_r ) + { + auto control = LogControlImpl::instance(); + if ( !control ) + return; + + control->putStream( group_r, level_r, + file_r, func_r, line_r, + buffer_r ); + } + + bool isExcessive() + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return false; + return impl->isExcessive(); + } + + ///////////////////////////////////////////////////////////////// + } // namespace logger + /////////////////////////////////////////////////////////////////// + + using logger::LogControlImpl; + + /////////////////////////////////////////////////////////////////// + // LineFormater + /////////////////////////////////////////////////////////////////// + std::string LogControl::LineFormater::format( const std::string & group_r, + logger::LogLevel level_r, + const char * file_r, + const char * func_r, + int line_r, + const std::string & message_r ) + { + static char hostname[1024]; + static char nohostname[] = "unknown"; + std::string now( Date::now().form( "%Y-%m-%d %H:%M:%S" ) ); + std::string ret; + + const bool logToPPID = LogControlImpl::instanceLogToPPID(); + if ( !logToPPID && LogControlImpl::instanceHideThreadName() ) + ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d %s", + now.c_str(), level_r, + ( gethostname( hostname, 1024 ) ? nohostname : hostname ), + getpid(), + group_r.c_str(), + file_r, func_r, line_r, + message_r.c_str() ); + else + ret = str::form( "%s <%d> %s(%d) [%s] %s(%s):%d {T:%s} %s", + now.c_str(), level_r, + ( gethostname( hostname, 1024 ) ? nohostname : hostname ), + logToPPID ? getppid() : getpid(), + group_r.c_str(), + file_r, func_r, line_r, + zyppng::ThreadData::current().name().c_str(), + message_r.c_str() ); + return ret; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LogControl + // Forward to LogControlImpl singleton. + // + /////////////////////////////////////////////////////////////////// + + + void LogControl::logfile( const Pathname & logfile_r ) + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + + impl->logfile( logfile_r ); + } + + void LogControl::logfile( const Pathname & logfile_r, mode_t mode_r ) + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + + impl->logfile( logfile_r, mode_r ); + } + + shared_ptr LogControl::getLineWriter() const + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return nullptr; + + return impl->getLineWriter(); + } + + void LogControl::setLineWriter( const shared_ptr & writer_r ) + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + impl->setLineWriter( writer_r ); + } + + void LogControl::setLineFormater( const shared_ptr & formater_r ) + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + impl->setLineFormater( formater_r ); + } + + void LogControl::enableLogForwardingMode(bool enable) + { + LogControlImpl::instanceSetLogToPPID ( enable ); + } + + void LogControl::logNothing() + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + impl->setLineWriter( shared_ptr() ); + } + + void LogControl::logToStdErr() + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + impl->setLineWriter( shared_ptr( new log::StderrLineWriter ) ); + } + + void base::LogControl::emergencyShutdown() + { + LogThread::instance().stop(); + } + + void LogControl::notifyFork() + { + logger::logControlValidFlag () = 0; + } + + void LogControl::logRawLine ( std::string &&line ) + { + LogControlImpl::instance ()->putRawLine ( std::move(line) ); + } + + /////////////////////////////////////////////////////////////////// + // + // LogControl::TmpExcessive + // + /////////////////////////////////////////////////////////////////// + LogControl::TmpExcessive::TmpExcessive() + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + impl->excessive( true ); + } + LogControl::TmpExcessive::~TmpExcessive() + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return; + impl->excessive( false ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const LogControl & ) + { + auto impl = LogControlImpl::instance(); + if ( !impl ) + return str; + return str << *impl; + } + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/LogControl.h b/zypp-core/base/LogControl.h new file mode 100644 index 0000000..3da8b7f --- /dev/null +++ b/zypp-core/base/LogControl.h @@ -0,0 +1,229 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/LogControl.h + * +*/ +#ifndef ZYPP_BASE_LOGCONTROL_H +#define ZYPP_BASE_LOGCONTROL_H + +#include +#include //for std::endl + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace log + { ///////////////////////////////////////////////////////////////// + + /** If you want to log the (formated) loglines by yourself, + * derive from this, and overload \c writeOut. + * Expect \a formated_r to be a formated log line without trailing \c NL. + * Ready to be written to the log. + */ + struct ZYPP_API LineWriter + { + virtual void writeOut( const std::string & /*formated_r*/ ) + {} + virtual ~LineWriter() + {} + }; + + /** Base class for ostream based \ref LineWriter */ + struct StreamLineWriter : public LineWriter + { + StreamLineWriter( std::ostream & str_r ) : _str( &str_r ) {} + + void writeOut( const std::string & formated_r ) override + { (*_str) << formated_r << std::endl; } + + protected: + StreamLineWriter() : _str( 0 ) {} + std::ostream *_str; + }; + + /** \ref LineWriter to stdout. */ + struct StdoutLineWriter : public StreamLineWriter + { + StdoutLineWriter(); + }; + + /** \ref LineWriter to stderr. */ + struct StderrLineWriter : public StreamLineWriter + { + StderrLineWriter(); + }; + + /** \ref LineWriter to file. + * If \c mode_r is not \c 0, \c file_r persissions are changed + * accordingly. \c "-" logs to \c cerr. + */ + struct ZYPP_API FileLineWriter : public StreamLineWriter + { + FileLineWriter( const Pathname & file_r, mode_t mode_r = 0 ); + protected: + shared_ptr _outs; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace log + /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LogControl + // + /** Maintain logfile related options. + * \note A Singleton using a Singleton implementation class, + * that's why there is no _pimpl like in other classes. + */ + class ZYPP_API LogControl + { + friend std::ostream & operator<<( std::ostream & str, const LogControl & obj ); + + public: + /** Singleton access. */ + static LogControl instance() + { return LogControl(); } + + + /** \see \ref log::LineWriter */ + using LineWriter = log::LineWriter; + + /** If you want to format loglines by yourself, + * derive from this, and overload \c format. + * Return a formated logline without trailing \c NL. + * Ready to be written to the log. + */ + struct ZYPP_API LineFormater + { + virtual std::string format( const std::string & /*group_r*/, + logger::LogLevel /*level_r*/, + const char * /*file_r*/, + const char * /*func_r*/, + int /*line_r*/, + const std::string & /*message_r*/ ); + virtual ~LineFormater() {} + }; + + public: + /** Assign a LineFormater. + * If you want to format loglines by yourself. NULL installs the + * default formater. + */ + void setLineFormater( const shared_ptr & formater_r ); + + /*! + * Sets a special log mode that uses the ppid in the log output and always shows the + * thread name (if the default formatter is used). This is only used by internal zypp tools that directly want to log into the + * parents logfile. + */ + void enableLogForwardingMode ( bool enable = true ); + + public: + /** Set path for the logfile. + * Permission for logfiles is set to 0640 unless an explicit mode_t + * value is given. An empty pathname turns off logging. "-" + * logs to std::err. + * \throw if \a logfile_r is not usable. + */ + void logfile( const Pathname & logfile_r ); + void logfile( const Pathname & logfile_r, mode_t mode_r ); + + /** Turn off logging. */ + void logNothing(); + + /** Log to std::err. */ + void logToStdErr(); + + /** will cause the log thread to exit and flush all sockets */ + void emergencyShutdown(); + + /** + * This will completely disable logging. + * It is supposed to be called in the child process after fork() + * was called to shut down all logging completely. + */ + static void notifyFork(); + + /** will push a line to the logthread without formatting it */ + void logRawLine ( std::string &&line ); + + public: + /** Get the current LineWriter */ + shared_ptr getLineWriter() const; + + /** Assign a LineWriter. + * If you want to log the (formated) loglines by yourself. + * NULL turns off logging (same as logNothing) + * \see \ref log::LineWriter + */ + void setLineWriter( const shared_ptr & writer_r ); + + public: + /** Turn on excessive logging for the lifetime of this object.*/ + struct TmpExcessive + { + TmpExcessive(); + ~TmpExcessive(); + }; + + /** Exchange LineWriter for the lifetime of this object. + * \see \ref log::LineWriter + */ + struct ZYPP_API TmpLineWriter + { + TmpLineWriter( const shared_ptr & writer_r = shared_ptr() ) + : _writer( LogControl::instance().getLineWriter() ) + { LogControl::instance().setLineWriter( writer_r ); } + + /** Convenience ctor taking over ownership of an allocated LineWriter. + *\code + * TmpLineWriter mylw( new log::StderrLineWriter ); + * \endcode + */ + template + TmpLineWriter( TLineWriter * _allocated_r ) + : _writer( LogControl::instance().getLineWriter() ) + { LogControl::instance().setLineWriter( shared_ptr( _allocated_r ) ); } + + ~TmpLineWriter() + { LogControl::instance().setLineWriter( _writer ); } + + private: + shared_ptr _writer; + }; + + private: + /** Default ctor: Singleton */ + LogControl() + {} + }; + /////////////////////////////////////////////////////////////////// + + /** \relates LogControl Stream output */ + std::ostream & operator<<( std::ostream & str, const LogControl & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_LOGCONTROL_H diff --git a/zypp-core/base/LogTools.h b/zypp-core/base/LogTools.h new file mode 100644 index 0000000..02e9612 --- /dev/null +++ b/zypp-core/base/LogTools.h @@ -0,0 +1,536 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/LogTools.h + * +*/ +#ifndef ZYPP_BASE_LOGTOOLS_H +#define ZYPP_BASE_LOGTOOLS_H + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#ifdef __GNUG__ +#include +#include +#include +#endif + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + using std::endl; + + /// \brief Helper to produce not-NL-terminated multi line output. + /// Used as leading separator it prints a separating NL by omitting + /// output upon it's first invocation. + /// A custom separator char can be passed to the ctor. + /// \code + /// Container foo { 1,2,3 }; + /// MLSep sep; + /// for ( auto && el : foo ) + /// cout << sep << el; + /// # "1\n2\n3" + /// \endcode + struct MLSep + { + MLSep() {} + MLSep( char sep_r ) : _sep { sep_r } {} + bool _first = true; + char _sep = '\n'; + }; + inline std::ostream & operator<<( std::ostream & str, MLSep & obj ) + { if ( obj._first ) obj._first = false; else str << obj._sep; return str; } + + /** Print range defined by iterators (multiline style). + * \code + * intro [ pfx ITEM [ { sep ITEM }+ ] sfx ] extro + * \endcode + * + * The defaults print the range enclosed in \c {}, one item per + * line indented by 2 spaces. + * \code + * { + * item1 + * item2 + * } + * {} // on empty range + * \endcode + * + * A comma separated list enclosed in \c () would be: + * \code + * dumpRange( stream, begin, end, "(", "", ", ", "", ")" ); + * // or shorter: + * dumpRangeLine( stream, begin, end ); + * \endcode + * + * \note Some special handling is required for printing std::maps. + * Therefore iomaipulators \ref dumpMap, \ref dumpKeys and \ref dumpValues + * are provided. + * \code + * std::map m; + * m["a"]=1; + * m["b"]=2; + * m["c"]=3; + * + * dumpRange( DBG, dumpMap(m).begin(), dumpMap(m).end() ) << endl; + * // { + * // [a] = 1 + * // [b] = 2 + * // [c] = 3 + * // } + * dumpRange( DBG, dumpKeys(m).begin(), dumpKeys(m).end() ) << endl; + * // { + * // a + * // b + * // c + * // } + * dumpRange( DBG, dumpValues(m).begin(), dumpValues(m).end() ) << endl; + * // { + * // 1 + * // 2 + * // 3 + * // } + * dumpRangeLine( DBG, dumpMap(m).begin(), dumpMap(m).end() ) << endl; + * // ([a] = 1, [b] = 2, [c] = 3) + * dumpRangeLine( DBG, dumpKeys(m).begin(), dumpKeys(m).end() ) << endl; + * // (a, b, c) + * dumpRangeLine( DBG, dumpValues(m).begin(), dumpValues(m).end() ) << endl; + * // (1, 2, 3) + * \endcode + */ + template + std::ostream & dumpRange( std::ostream & str, + TIterator begin, TIterator end, + const std::string & intro = "{", + const std::string & pfx = "\n ", + const std::string & sep = "\n ", + const std::string & sfx = "\n", + const std::string & extro = "}" ) + { + str << intro; + if ( begin != end ) + { + str << pfx << *begin; + for ( ++begin; begin != end; ++begin ) + str << sep << *begin; + str << sfx; + } + return str << extro; + } + + /** Print range defined by iterators (single line style). + * \see dumpRange + */ + template + std::ostream & dumpRangeLine( std::ostream & str, + TIterator begin, TIterator end ) + { return dumpRange( str, begin, end, "(", "", ", ", "", ")" ); } + /** \overload for container */ + template + std::ostream & dumpRangeLine( std::ostream & str, const TContainer & cont ) + { return dumpRangeLine( str, cont.begin(), cont.end() ); } + + + /////////////////////////////////////////////////////////////////// + namespace iomanip + { + /////////////////////////////////////////////////////////////////// + /// \class RangeLine + /// \brief Iomanip helper printing dumpRangeLine style + /////////////////////////////////////////////////////////////////// + template + struct RangeLine + { + RangeLine( TIterator begin, TIterator end ) + : _begin( begin ) + , _end( end ) + {} + TIterator _begin; + TIterator _end; + }; + + /** \relates RangeLine */ + template + std::ostream & operator<<( std::ostream & str, const RangeLine & obj ) + { return dumpRangeLine( str, obj._begin, obj._end ); } + + } // namespce iomanip + /////////////////////////////////////////////////////////////////// + + /** Iomanip printing dumpRangeLine style + * \code + * std::vector c( { 1, 1, 2, 3, 5, 8 } ); + * std::cout << rangeLine(c) << std::endl; + * -> (1, 1, 2, 3, 5, 8) + * \endcode + */ + template + iomanip::RangeLine rangeLine( TIterator begin, TIterator end ) + { return iomanip::RangeLine( begin, end ); } + /** \overload for container */ + template + auto rangeLine( const TContainer & cont ) -> decltype( rangeLine( cont.begin(), cont.end() ) ) + { return rangeLine( cont.begin(), cont.end() ); } + + template + std::ostream & operator<<( std::ostream & str, const std::vector & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + template + std::ostream & operator<<( std::ostream & str, const std::set & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + template + std::ostream & operator<<( std::ostream & str, const std::unordered_set & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + template + std::ostream & operator<<( std::ostream & str, const std::multiset & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + template + std::ostream & operator<<( std::ostream & str, const std::list & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + template + std::ostream & operator<<( std::ostream & str, const Iterable & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + /////////////////////////////////////////////////////////////////// + namespace _logtoolsdetail + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // mapEntry + /////////////////////////////////////////////////////////////////// + + /** std::pair wrapper for std::map output. + * Just because we want a special output format for std::pair + * used in a std::map. The mapped std::pair is printed as + * [key] = value. + */ + template + class MapEntry + { + public: + MapEntry( const TPair & pair_r ) + : _pair( &pair_r ) + {} + + const TPair & pair() const + { return *_pair; } + + private: + const TPair *const _pair; + }; + + /** \relates MapEntry Stream output. */ + template + std::ostream & operator<<( std::ostream & str, const MapEntry & obj ) + { + return str << '[' << obj.pair().first << "] = " << obj.pair().second; + } + + /** \relates MapEntry Convenience function to create MapEntry from std::pair. */ + template + MapEntry mapEntry( const TPair & pair_r ) + { return MapEntry( pair_r ); } + + /////////////////////////////////////////////////////////////////// + // dumpMap + /////////////////////////////////////////////////////////////////// + + /** std::map wrapper for stream output. + * Uses a transform_iterator to wrap the std::pair into MapEntry. + * + */ + template + class DumpMap + { + public: + using MapType = TMap; + using PairType = typename TMap::value_type; + using MapEntryType = MapEntry; + + struct Transformer + { + MapEntryType operator()( const PairType & pair_r ) const + { return mapEntry( pair_r ); } + }; + + using MapEntry_const_iterator = transform_iterator; + + public: + DumpMap( const TMap & map_r ) + : _map( &map_r ) + {} + + const TMap & map() const + { return *_map; } + + MapEntry_const_iterator begin() const + { return make_transform_iterator( map().begin(), Transformer() ); } + + MapEntry_const_iterator end() const + { return make_transform_iterator( map().end(), Transformer() );} + + private: + const TMap *const _map; + }; + + /** \relates DumpMap Stream output. */ + template + std::ostream & operator<<( std::ostream & str, const DumpMap & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + /** \relates DumpMap Convenience function to create DumpMap from std::map. */ + template + DumpMap dumpMap( const TMap & map_r ) + { return DumpMap( map_r ); } + + /////////////////////////////////////////////////////////////////// + // dumpKeys + /////////////////////////////////////////////////////////////////// + + /** std::map wrapper for stream output of keys. + * Uses MapKVIterator iterate and write the key values. + * \code + * std::map<...> mymap; + * std::cout << dumpKeys(mymap) << std::endl; + * \endcode + */ + template + class DumpKeys + { + public: + using MapKey_const_iterator = typename MapKVIteratorTraits::Key_const_iterator; + + public: + DumpKeys( const TMap & map_r ) + : _map( &map_r ) + {} + + const TMap & map() const + { return *_map; } + + MapKey_const_iterator begin() const + { return make_map_key_begin( map() ); } + + MapKey_const_iterator end() const + { return make_map_key_end( map() ); } + + private: + const TMap *const _map; + }; + + /** \relates DumpKeys Stream output. */ + template + std::ostream & operator<<( std::ostream & str, const DumpKeys & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + /** \relates DumpKeys Convenience function to create DumpKeys from std::map. */ + template + DumpKeys dumpKeys( const TMap & map_r ) + { return DumpKeys( map_r ); } + + /////////////////////////////////////////////////////////////////// + // dumpValues + /////////////////////////////////////////////////////////////////// + + /** std::map wrapper for stream output of values. + * Uses MapKVIterator iterate and write the values. + * \code + * std::map<...> mymap; + * std::cout << dumpValues(mymap) << std::endl; + * \endcode + */ + template + class DumpValues + { + public: + using MapValue_const_iterator = typename MapKVIteratorTraits::Value_const_iterator; + + public: + DumpValues( const TMap & map_r ) + : _map( &map_r ) + {} + + const TMap & map() const + { return *_map; } + + MapValue_const_iterator begin() const + { return make_map_value_begin( map() ); } + + MapValue_const_iterator end() const + { return make_map_value_end( map() ); } + + private: + const TMap *const _map; + }; + + /** \relates DumpValues Stream output. */ + template + std::ostream & operator<<( std::ostream & str, const DumpValues & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + /** \relates DumpValues Convenience function to create DumpValues from std::map. */ + template + DumpValues dumpValues( const TMap & map_r ) + { return DumpValues( map_r ); } + + ///////////////////////////////////////////////////////////////// + } // namespace _logtoolsdetail + /////////////////////////////////////////////////////////////////// + + // iomanipulator + using _logtoolsdetail::mapEntry; // std::pair as '[key] = value' + using _logtoolsdetail::dumpMap; // dumpRange '[key] = value' + using _logtoolsdetail::dumpKeys; // dumpRange keys + using _logtoolsdetail::dumpValues; // dumpRange values + + template + std::ostream & operator<<( std::ostream & str, const std::map & obj ) + { return str << dumpMap( obj ); } + + template + std::ostream & operator<<( std::ostream & str, const std::unordered_map & obj ) + { return str << dumpMap( obj ); } + + template + std::ostream & operator<<( std::ostream & str, const std::multimap & obj ) + { return str << dumpMap( obj ); } + + /** Print stream status bits. + * Prints the values of a streams \c good, \c eof, \c failed and \c bad bit. + * + * \code + * [g___] - good + * [_eF_] - eof and fail bit set + * [__FB] - fail and bad bit set + * \endcode + */ + inline std::ostream & operator<<( std::ostream & str, const std::basic_ios & obj ) + { + std::string ret( "[" ); + ret += ( obj.good() ? 'g' : '_' ); + ret += ( obj.eof() ? 'e' : '_' ); + ret += ( obj.fail() ? 'F' : '_' ); + ret += ( obj.bad() ? 'B' : '_' ); + ret += "]"; + return str << ret; + } + + /////////////////////////////////////////////////////////////////// + // iomanipulator: str << dump(val) << ... + // calls: std::ostream & dumpOn( std::ostream & str, const Type & obj ) + /////////////////////////////////////////////////////////////////// + + namespace detail + { + template + struct Dump + { + Dump( const Tp & obj_r ) : _obj( obj_r ) {} + const Tp & _obj; + }; + + template + std::ostream & operator<<( std::ostream & str, const Dump & obj ) + { return dumpOn( str, obj._obj ); } + } + + template + detail::Dump dump( const Tp & obj_r ) + { return detail::Dump(obj_r); } + + /** hexdump data on stream + * \code + * hexdump 0000000333 bytes (0x0000014d): + * 0000: 0c 00 01 49 03 00 17 41 04 af 7c 75 5e 4c 2d f7 ...I...A..|u^L-. + * 0010: c9 c9 75 bf a8 41 37 2a d0 03 2c ff 96 d2 43 89 ..u..A7*..,...C. + * 0020: ... + * \endcode + */ + inline std::ostream & hexdumpOn( std::ostream & outs, const unsigned char *ptr, size_t size ) + { + size_t i = 0,c = 0; + unsigned width = 0x10; + outs << str::form( "hexdump %10.10ld bytes (0x%8.8lx):\n", (long)size, (long)size ); + + for ( i = 0; i < size; i += width ) { + outs << str::form( "%4.4lx: ", (long)i ); + /* show hex to the left */ + for ( c = 0; c < width; ++c ) { + if ( i+c < size ) + outs << str::form( "%02x ", ptr[i+c] ); + else + outs << (" "); + } + /* show data on the right */ + for ( c = 0; (c < width) && (i+c < size); ++c ) { + char x = (ptr[i+c] >= 0x20 && ptr[i+c] < 0x7f) ? ptr[i+c] : '.'; + outs << x; + } + outs << std::endl; + } + return outs; + } + /** \overload */ + inline std::ostream & hexdumpOn( std::ostream & outs, const char *ptr, size_t size ) + { return hexdumpOn( outs, (const unsigned char *)ptr, size ); } + + /*! + * Write type info to stream + * @TODO de-inline me + */ + inline std::ostream & operator<<( std::ostream & str, const std::type_info &info ) + { +#ifdef __GNUG__ + int status = -4; // some arbitrary value to eliminate the compiler warning + + // enable c++11 by passing the flag -std=c++11 to g++ + std::unique_ptr res { + abi::__cxa_demangle(info.name(), NULL, NULL, &status), + std::free + }; + return str << std::string((status==0) ? res.get() : info.name()); +#else + return str << info.name(); +#endif + } + +#ifdef __cpp_lib_optional // YAST/PK explicitly use c++11 until 15-SP3 + template + inline std::ostream & operator<<( std::ostream & str, const std::optional & obj ) + { + if ( obj ) + str << "opt(" << *obj << ")"; + else + str << "nullopt"; + return str; + } +#endif + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_LOGTOOLS_H diff --git a/zypp-core/base/Logger.h b/zypp-core/base/Logger.h new file mode 100644 index 0000000..1388b30 --- /dev/null +++ b/zypp-core/base/Logger.h @@ -0,0 +1,192 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Logger.h + * +*/ +#ifndef ZYPP_BASE_LOGGER_H +#define ZYPP_BASE_LOGGER_H +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +#ifndef ZYPP_NDEBUG +namespace zypp +{ + namespace debug + { // impl in LogControl.cc + + // Log code loacaton and block leave + // Indent if nested + struct TraceLeave + { + TraceLeave( const TraceLeave & ) =delete; + TraceLeave & operator=( const TraceLeave & ) =delete; + TraceLeave( const char * file_r, const char * fnc_r, int line_r ); + ~TraceLeave(); + private: + static unsigned _depth; + const char * _file; + const char * _fnc; + int _line; + }; +#define TRACE ::zypp::debug::TraceLeave _TraceLeave( __FILE__, __FUNCTION__, __LINE__ ) + + // OnScreenDebug messages colored to stderr + struct ZYPP_API Osd + { + Osd( std::ostream &, int = 0 ); + ~Osd(); + + template + Osd & operator<<( Tp && val ) + { + _strout << std::forward(val); + _strlog << std::forward(val); + return *this; + } + + Osd & operator<<( std::ostream& (*iomanip)( std::ostream& ) ); + + private: + std::ostream & _strout; + std::ostream & _strlog; + }; +#define OSD ::zypp::debug::Osd(L_USR("OSD")) + } +} +#endif // ZYPP_NDEBUG +/////////////////////////////////////////////////////////////////// + +/** \defgroup ZYPP_BASE_LOGGER_MACROS ZYPP_BASE_LOGGER_MACROS + * Convenience macros for logging. + * + * The macros finally call @ref getStream, providing appropriate arguments, + * to return the log stream. + * + * @code + * L_DBG("foo") << .... + * @endcode + * Logs a debug message for group @a "foo". + * + * @code + * #undef ZYPP_BASE_LOGGER_LOGGROUP + * #define ZYPP_BASE_LOGGER_LOGGROUP "foo" + * + * DBG << .... + * @endcode + * Defines group @a "foo" as default for log messages and logs a + * debug message. + */ +/*@{*/ + +#ifndef ZYPP_BASE_LOGGER_LOGGROUP +/** Default log group if undefined. */ +#define ZYPP_BASE_LOGGER_LOGGROUP "DEFINE_LOGGROUP" +#endif + +#define XXX L_XXX( ZYPP_BASE_LOGGER_LOGGROUP ) +#define DBG L_DBG( ZYPP_BASE_LOGGER_LOGGROUP ) +#define MIL L_MIL( ZYPP_BASE_LOGGER_LOGGROUP ) +#define WAR L_WAR( ZYPP_BASE_LOGGER_LOGGROUP ) +#define ERR L_ERR( ZYPP_BASE_LOGGER_LOGGROUP ) +#define SEC L_SEC( ZYPP_BASE_LOGGER_LOGGROUP ) +#define INT L_INT( ZYPP_BASE_LOGGER_LOGGROUP ) +#define USR L_USR( ZYPP_BASE_LOGGER_LOGGROUP ) + +#define L_XXX(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP, zypp::base::logger::E_XXX ) +#define L_DBG(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP"++", zypp::base::logger::E_MIL ) +#define L_MIL(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP, zypp::base::logger::E_MIL ) +#define L_WAR(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP, zypp::base::logger::E_WAR ) +#define L_ERR(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP, zypp::base::logger::E_ERR ) +#define L_SEC(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP, zypp::base::logger::E_SEC ) +#define L_INT(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP, zypp::base::logger::E_INT ) +#define L_USR(GROUP) ZYPP_BASE_LOGGER_LOG( GROUP, zypp::base::logger::E_USR ) + + +#define L_ENV_CONSTR_DEFINE_FUNC(ENV) \ + namespace zypp::log { \ + bool has_env_constr_##ENV () \ + { \ + static bool has_##ENV = (::getenv(#ENV) != NULL); \ + return has_##ENV; \ + } \ + const char *empty_or_group_if_##ENV ( const char *group ) \ + { \ + return has_env_constr_##ENV() ? group : nullptr; \ + } \ + } + +#define L_ENV_CONSTR_FWD_DECLARE_FUNC(ENV) namespace zypp::log { bool has_env_constr_##ENV (); const char *empty_or_group_if_##ENV ( const char *group ); } +#define L_ENV_CONSTR(ENV,GROUP,LEVEL) ZYPP_BASE_LOGGER_LOG( zypp::log::empty_or_group_if_##ENV( GROUP ), LEVEL ) + +#define L_BASEFILE ( *__FILE__ == '/' ? strrchr( __FILE__, '/' ) + 1 : __FILE__ ) + +/** Actual call to @ref getStream. */ +#define ZYPP_BASE_LOGGER_LOG(GROUP,LEVEL) \ + zypp::base::logger::getStream( GROUP, LEVEL, L_BASEFILE, __FUNCTION__, __LINE__ ) + +/*@}*/ + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace logger + { ///////////////////////////////////////////////////////////////// + + /** Definition of log levels. + * + * @see getStream + */ + enum LogLevel { + E_XXX = 999, /**< Excessive logging. */ + E_DBG = 0, /**< Debug or verbose. */ + E_MIL, /**< Milestone. */ + E_WAR, /**< Warning. */ + E_ERR, /**< Error. */ + E_SEC, /**< Secutrity related. */ + E_INT, /**< Internal error. */ + E_USR /**< User log. */ + }; + + /** Return a log stream to write on. + * + * The returned log stream is determined by @a group_r and + * @a level_r. The remaining arguments @a file_r, @a func_r + * and @a line_r are expected to denote the location in the + * source code that issued the message. + * + * @note You won't call @ref getStream directly, but use the + * @ref ZYPP_BASE_LOGGER_MACROS. + */ + extern std::ostream & getStream( const char * group_r, + LogLevel level_r, + const char * file_r, + const char * func_r, + const int line_r ) ZYPP_API; + extern bool isExcessive() ZYPP_API; + + ///////////////////////////////////////////////////////////////// + } // namespace logger + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_LOGGER_H diff --git a/zypp-core/base/NonCopyable.h b/zypp-core/base/NonCopyable.h new file mode 100644 index 0000000..b154bb1 --- /dev/null +++ b/zypp-core/base/NonCopyable.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/NonCopyable.h +*/ +#ifndef ZYPP_BASE_NONCOPYABLE_H +#define ZYPP_BASE_NONCOPYABLE_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + /** Ensure derived classes cannot be copied. + * Use private inheritance. + */ + using NonCopyable = boost::noncopyable; + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_NONCOPYABLE_H diff --git a/zypp-core/base/ProfilingFormater.cc b/zypp-core/base/ProfilingFormater.cc new file mode 100644 index 0000000..56ea773 --- /dev/null +++ b/zypp-core/base/ProfilingFormater.cc @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/ProfilingFormater.cc + * +*/ + +#include + +#include +#include +#include + +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // ProfilingFormater + /////////////////////////////////////////////////////////////////// + + std::string ProfilingFormater::format( const std::string & group_r, + logger::LogLevel level_r, + const char * file_r, + const char * func_r, + int line_r, + const std::string & message_r ) + { + struct timeval tp; + gettimeofday( &tp, NULL); + + return str::form( "%ld.%ld [%d] <%d> %s(%s):%d %s", + tp.tv_sec, + tp.tv_usec, + level_r, + getpid(), + /*group_r.c_str(),*/ + file_r, func_r, line_r, + message_r.c_str() ); + } + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/ProfilingFormater.h b/zypp-core/base/ProfilingFormater.h new file mode 100644 index 0000000..3b966e4 --- /dev/null +++ b/zypp-core/base/ProfilingFormater.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/ProfilingFormater.h + * +*/ +#ifndef ZYPP_BASE_PROFILINGFORMATER_H +#define ZYPP_BASE_PROFILINGFORMATER_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + struct ProfilingFormater : public LogControl::LineFormater + { + std::string format( const std::string & /*group_r*/, + logger::LogLevel /*level_r*/, + const char * /*file_r*/, + const char * /*func_r*/, + int /*line_r*/, + const std::string & /*message_r*/ ) override; + ~ProfilingFormater() override {} + }; + + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_PROFILINGFORMATER_H diff --git a/zypp-core/base/ProvideNumericId b/zypp-core/base/ProvideNumericId new file mode 100644 index 0000000..73446ce --- /dev/null +++ b/zypp-core/base/ProvideNumericId @@ -0,0 +1 @@ +#include "providenumericid.h" diff --git a/zypp-core/base/PtrTypes.h b/zypp-core/base/PtrTypes.h new file mode 100644 index 0000000..9e9fbd0 --- /dev/null +++ b/zypp-core/base/PtrTypes.h @@ -0,0 +1,647 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/PtrTypes.h + * \ingroup ZYPP_SMART_PTR + * \see ZYPP_SMART_PTR +*/ +#ifndef ZYPP_BASE_PTRTYPES_H +#define ZYPP_BASE_PTRTYPES_H + +#include +#include + +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace str + { + // printing void* (prevents us from including ) + std::string form( const char * format, ... ) __attribute__ ((format (printf, 1, 2))); + } + + /** \defgroup ZYPP_SMART_PTR Smart pointer types + * Smart pointer types. + * + * Namespace zypp provides 3 smart pointer types \b using the + * boost smart pointer library. + * + * \li \c scoped_ptr Simple sole ownership of single objects. Noncopyable. + * + * \li \c shared_ptr Object ownership shared among multiple pointers + * + * \li \c weak_ptr Non-owning observers of an object owned by shared_ptr. + * + * And \ref zypp::RW_pointer, as wrapper around a smart pointer, + * poviding \c const correct read/write access to the object it refers. + */ + /*@{*/ + + /** shared_ptr custom deleter doing nothing. + * A custom deleter is a function being called when the + * last shared_ptr goes out of score. Per default the + * object gets deleted, but you can insall custom deleters + * as well. This one does nothing. + * + * \code + * // Some class providing a std::istream + * struct InpuStream + * { + * // Per deafult use std::cin. + * InputStream() + * : _stream( &std::cin, NullDeleter() ) + * {} + * // Or read from a file. + * InputStream( const Pathname & file_r ) + * : _stream( new ifgzstream( _path.asString().c_str() ) ) + * {} + * // Or use a stream priovided by the application. + * InputStream( std::istream & stream_r ) + * : _stream( &stream_r, NullDeleter() ) + * {} + * + * std::istream & stream() + * { return *_stream; } + * + * private: + * shared_ptr _stream; + * }; + * \endcode + */ + struct NullDeleter + { + void operator()( const void *const ) const + {} + }; + + /** \class scoped_ptr */ + using boost::scoped_ptr; + + /** \class shared_ptr */ + using boost::shared_ptr; + + /** \class weak_ptr */ + using boost::weak_ptr; + + /** \class intrusive_ptr */ + using boost::intrusive_ptr; + + template + inline intrusive_ptr + make_intrusive( Args&&... __args ) { + return intrusive_ptr( new T( std::forward(__args)...) ); + } + + /** */ + using boost::static_pointer_cast; + /** */ + using boost::const_pointer_cast; + /** */ + using boost::dynamic_pointer_cast; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace std +{ ///////////////////////////////////////////////////////////////// + + // namespace sub { + // class Foo; + // typedef zypp::intrusive_ptr Foo_Ptr; // see DEFINE_PTR_TYPE(NAME) macro below + // } + + // Defined in namespace std g++ finds the output operator (König-Lookup), + // even if we typedef the pointer in a different namespace than ::zypp. + // Otherwise we had to define an output operator always in the same namespace + // as the typedef (else g++ will just print the pointer value). + + /** \relates zypp::shared_ptr Stream output. */ + template + inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr & obj ) + { + if ( obj ) + return str << *obj; + return str << std::string("NULL"); + } + /** \overload specialize for void */ + template<> + inline std::ostream & operator<<( std::ostream & str, const zypp::shared_ptr & obj ) + { + if ( obj ) + return str << zypp::str::form( "%p", (void*)obj.get() ); + return str << std::string("NULL"); + } + + /** \relates zypp::shared_ptr Stream output. */ + template + inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr & obj ) + { + if ( obj ) + return dumpOn( str, *obj ); + return str << std::string("NULL"); + } + /** \overload specialize for void */ + template<> + inline std::ostream & dumpOn( std::ostream & str, const zypp::shared_ptr & obj ) + { return str << obj; } + + /** \relates zypp::intrusive_ptr Stream output. */ + template + inline std::ostream & operator<<( std::ostream & str, const zypp::intrusive_ptr & obj ) + { + if ( obj ) + return str << *obj; + return str << std::string("NULL"); + } + /** \relates zypp::intrusive_ptr Stream output. */ + template + inline std::ostream & dumpOn( std::ostream & str, const zypp::intrusive_ptr & obj ) + { + if ( obj ) + return dumpOn( str, *obj ); + return str << std::string("NULL"); + } + ///////////////////////////////////////////////////////////////// +} // namespace std +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // RW_pointer traits + // + /////////////////////////////////////////////////////////////////// + /** + * Don't forgett to provide versions for PtrType and constPtrType, + * esp. if creation a of temporary is not acceptable (eg. when + * checking the ref count value). + */ + namespace rw_pointer { + + template + struct Shared + { + using PtrType = shared_ptr; + using constPtrType = shared_ptr; + /** Check whether pointer is not shared. */ + bool unique( const constPtrType & ptr_r ) + { return !ptr_r || ptr_r.unique(); } + bool unique( const PtrType & ptr_r ) + { return !ptr_r || ptr_r.unique(); } + /** Return number of references. */ + long use_count( const constPtrType & ptr_r ) const + { return ptr_r.use_count(); } + long use_count( const PtrType & ptr_r ) const + { return ptr_r.use_count(); } + }; + + template + struct Intrusive + { + using PtrType = intrusive_ptr; + using constPtrType = intrusive_ptr; + /** Check whether pointer is not shared. */ + bool unique( const constPtrType & ptr_r ) + { return !ptr_r || (ptr_r->refCount() <= 1); } + bool unique( const PtrType & ptr_r ) + { return !ptr_r || (ptr_r->refCount() <= 1); } + /** Return number of references. */ + long use_count( const constPtrType & ptr_r ) const + { return ptr_r ? ptr_r->refCount() : 0; } + long use_count( const PtrType & ptr_r ) const + { return ptr_r ? ptr_r->refCount() : 0; } + }; + + template + struct Scoped + { + using PtrType = scoped_ptr; + using constPtrType = scoped_ptr; + /** Check whether pointer is not shared. */ + bool unique( const constPtrType & ptr_r ) + { return true; } + bool unique( const PtrType & ptr_r ) + { return true; } + /** Return number of references. */ + long use_count( const constPtrType & ptr_r ) const + { return ptr_r ? 1 : 0; } + long use_count( const PtrType & ptr_r ) const + { return ptr_r ? 1 : 0; } + }; + + } + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RW_pointer + // + /** Wrapper for \c const correct access via \ref ZYPP_SMART_PTR. + * + * zypp::RW_pointer\ stores a \ref ZYPP_SMART_PTR + * of type \c DTraits::PtrType, which must be convertible into a D *. + * Pointer style access (via \c -> and \c *) offers a const D * in const + * a context, otherwise a D *. Thus \em RW_ means \em read/write, + * as you get a different type, dependent on whether you're allowed to + * read or write. + * + * Forwarding access from an interface to an implemantation class, an + * RW_pointer prevents const interface methods from accidentally calling + * nonconst implementation methods. + * + * The second template argument defaults to + * DTraits = rw_pointer::Shared thus wraping a + * shared_ptr. To wrap an intrusive_ptr + * use rw_pointer::Intrusive. + * + * \see zypp::RWCOW_pointer for 'copy on write' functionality. + * + * \code + * #include "zypp/base/PtrTypes.h" + * + * class Foo + * { + * ... + * private: + * // Implementation class + * struct Impl; + * // Pointer to implementation; actually a shared_ptr + * RW_pointer _pimpl; + * + * void baa() { _pimpl->... } // is Impl * + * void baa() const { _pimpl->... } // is Impl const * + * }; + * \endcode + */ + template > + struct RW_pointer + { + using PtrType = typename DTraits::PtrType; + using constPtrType = typename DTraits::constPtrType; + + RW_pointer() + {} + + RW_pointer(const RW_pointer &) = default; + RW_pointer(RW_pointer &&) = default; + RW_pointer &operator=(const RW_pointer &) = default; + RW_pointer &operator=(RW_pointer &&) = default; + RW_pointer(std::nullptr_t) {} + + explicit + RW_pointer( typename PtrType::element_type * dptr ) + : _dptr( dptr ) + {} + + explicit + RW_pointer( PtrType dptr ) + : _dptr( dptr ) + {} + + RW_pointer & operator=( std::nullptr_t ) + { reset(); return *this; } + + void reset() + { PtrType().swap( _dptr ); } + + void reset( typename PtrType::element_type * dptr ) + { PtrType( dptr ).swap( _dptr ); } + + void swap( RW_pointer & rhs ) noexcept + { _dptr.swap( rhs._dptr ); } + + void swap( PtrType & rhs ) noexcept + { _dptr.swap( rhs ); } + + explicit operator bool() const + { return _dptr.get() != nullptr; } + + const D & operator*() const + { return *_dptr; }; + + const D * operator->() const + { return _dptr.operator->(); } + + const D * get() const + { return _dptr.get(); } + + D & operator*() + { return *_dptr; } + + D * operator->() + { return _dptr.operator->(); } + + D * get() + { return _dptr.get(); } + + public: + bool unique() const + { return DTraits().unique( _dptr ); } + + long use_count() const + { return DTraits().use_count( _dptr ); } + + constPtrType getPtr() const + { return _dptr; } + + PtrType getPtr() + { return _dptr; } + + constPtrType cgetPtr() + { return _dptr; } + + private: + PtrType _dptr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RW_pointer Stream output. + * + * Print the \c D object the RW_pointer refers, or \c "NULL" + * if the pointer is \c NULL. + */ + template + inline std::ostream & operator<<( std::ostream & str, const RW_pointer & obj ) + { + if ( obj.get() ) + return str << *obj.get(); + return str << std::string("NULL"); + } + + /** \relates RW_pointer */ + template + inline bool operator==( const RW_pointer & lhs, const RW_pointer & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RW_pointer */ + template + inline bool operator==( const RW_pointer & lhs, const typename DPtr::PtrType & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RW_pointer */ + template + inline bool operator==( const typename DPtr::PtrType & lhs, const RW_pointer & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RW_pointer */ + template + inline bool operator==( const RW_pointer & lhs, const typename DPtr::constPtrType & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RW_pointer */ + template + inline bool operator==( const typename DPtr::constPtrType & lhs, const RW_pointer & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RW_pointer */ + template + inline bool operator==( const RW_pointer & lhs, std::nullptr_t ) + { return( lhs.get() == nullptr ); } + /** \relates RW_pointer */ + template + inline bool operator==( std::nullptr_t, const RW_pointer & rhs ) + { return( nullptr == rhs.get() ); } + + + /** \relates RW_pointer */ + template + inline bool operator!=( const RW_pointer & lhs, const RW_pointer & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RW_pointer */ + template + inline bool operator!=( const RW_pointer & lhs, const typename DPtr::PtrType & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RW_pointer */ + template + inline bool operator!=( const typename DPtr::PtrType & lhs, const RW_pointer & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RW_pointer */ + template + inline bool operator!=( const RW_pointer & lhs, const typename DPtr::constPtrType & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RW_pointer */ + template + inline bool operator!=( const typename DPtr::constPtrType & lhs, const RW_pointer & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RW_pointer */ + template + inline bool operator!=( const RW_pointer & lhs, std::nullptr_t ) + { return( lhs.get() != nullptr ); } + /** \relates RW_pointer */ + template + inline bool operator!=( std::nullptr_t, const RW_pointer & rhs ) + { return( nullptr != rhs.get() ); } + + /////////////////////////////////////////////////////////////////// + + /** \relates RWCOW_pointer Clone the underlying object. + * Calls \a rhs -\>clone(). Being defined as a + * function outside \ref RWCOW_pointer allows to overload + * it, in case a specific \a D does not have clone(). + */ + template + inline D * rwcowClone( const D * rhs ) + { return rhs->clone(); } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RWCOW_pointer + // + /** \ref RW_pointer supporting 'copy on write' functionality. + * + * \em Write access to the underlying object creates a copy, iff + * the object is shared. + * + * See \ref RW_pointer. + */ + template > + struct RWCOW_pointer + { + using PtrType = typename DTraits::PtrType; + using constPtrType = typename DTraits::constPtrType; + + RWCOW_pointer() {} + + RWCOW_pointer(std::nullptr_t) {} + + RWCOW_pointer(const RWCOW_pointer &) = default; + + RWCOW_pointer(RWCOW_pointer &&) = default; + + explicit + RWCOW_pointer( typename PtrType::element_type * dptr ) + : _dptr( dptr ) + {} + + explicit + RWCOW_pointer( PtrType dptr ) + : _dptr( dptr ) + {} + + RWCOW_pointer & operator=( std::nullptr_t ) + { reset(); return *this; } + + RWCOW_pointer &operator=(const RWCOW_pointer &) = default; + + RWCOW_pointer &operator=(RWCOW_pointer &&) = default; + + void reset() + { PtrType().swap( _dptr ); } + + void reset( typename PtrType::element_type * dptr ) + { PtrType( dptr ).swap( _dptr ); } + + void swap( RWCOW_pointer & rhs ) noexcept + { _dptr.swap( rhs._dptr ); } + + void swap( PtrType & rhs ) noexcept + { _dptr.swap( rhs ); } + + explicit operator bool() const + { return _dptr.get() != nullptr; } + + const D & operator*() const + { return *_dptr; }; + + const D * operator->() const + { return _dptr.operator->(); } + + const D * get() const + { return _dptr.get(); } + + D & operator*() + { assertUnshared(); return *_dptr; } + + D * operator->() + { assertUnshared(); return _dptr.operator->(); } + + D * get() + { assertUnshared(); return _dptr.get(); } + + public: + bool unique() const + { return DTraits().unique( _dptr ); } + + long use_count() const + { return DTraits().use_count( _dptr ); } + + constPtrType getPtr() const + { return _dptr; } + + PtrType getPtr() + { assertUnshared(); return _dptr; } + + constPtrType cgetPtr() + { return _dptr; } + + private: + + void assertUnshared() + { + if ( !unique() ) + PtrType( rwcowClone( _dptr.get() ) ).swap( _dptr ); + } + + private: + PtrType _dptr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RWCOW_pointer Stream output. + * + * Print the \c D object the RWCOW_pointer refers, or \c "NULL" + * if the pointer is \c NULL. + */ + template + inline std::ostream & operator<<( std::ostream & str, const RWCOW_pointer & obj ) + { + if ( obj.get() ) + return str << *obj.get(); + return str << std::string("NULL"); + } + + /** \relates RWCOW_pointer */ + template + inline bool operator==( const RWCOW_pointer & lhs, const RWCOW_pointer & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RWCOW_pointer */ + template + inline bool operator==( const RWCOW_pointer & lhs, const typename DPtr::PtrType & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RWCOW_pointer */ + template + inline bool operator==( const typename DPtr::PtrType & lhs, const RWCOW_pointer & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RWCOW_pointer */ + template + inline bool operator==( const RWCOW_pointer & lhs, const typename DPtr::constPtrType & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RWCOW_pointer */ + template + inline bool operator==( const typename DPtr::constPtrType & lhs, const RWCOW_pointer & rhs ) + { return( lhs.get() == rhs.get() ); } + /** \relates RWCOW_pointer */ + template + inline bool operator==( const RWCOW_pointer & lhs, std::nullptr_t ) + { return( lhs.get() == nullptr ); } + /** \relates RWCOW_pointer */ + template + inline bool operator==( std::nullptr_t, const RWCOW_pointer & rhs ) + { return( nullptr == rhs.get() ); } + + /** \relates RWCOW_pointer */ + template + inline bool operator!=( const RWCOW_pointer & lhs, const RWCOW_pointer & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RWCOW_pointer */ + template + inline bool operator!=( const RWCOW_pointer & lhs, const typename DPtr::PtrType & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RWCOW_pointer */ + template + inline bool operator!=( const typename DPtr::PtrType & lhs, const RWCOW_pointer & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RWCOW_pointer */ + template + inline bool operator!=( const RWCOW_pointer & lhs, const typename DPtr::constPtrType & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RWCOW_pointer */ + template + inline bool operator!=( const typename DPtr::constPtrType & lhs, const RWCOW_pointer & rhs ) + { return ! ( lhs == rhs ); } + /** \relates RWCOW_pointer */ + template + inline bool operator!=( const RWCOW_pointer & lhs, std::nullptr_t ) + { return( lhs.get() != nullptr ); } + /** \relates RWCOW_pointer */ + template + inline bool operator!=( std::nullptr_t, const RWCOW_pointer & rhs ) + { return( nullptr != rhs.get() ); } + + /////////////////////////////////////////////////////////////////// + + /*@}*/ + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +/** Forward declaration of Ptr types */ +#define DEFINE_PTR_TYPE(NAME) \ +class NAME; \ +extern void intrusive_ptr_add_ref( const NAME * ) ZYPP_API; \ +extern void intrusive_ptr_release( const NAME * ) ZYPP_API; \ +typedef zypp::intrusive_ptr NAME##_Ptr; \ +typedef zypp::intrusive_ptr NAME##_constPtr; + +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_PTRTYPES_H diff --git a/zypp-core/base/ReferenceCounted.cc b/zypp-core/base/ReferenceCounted.cc new file mode 100644 index 0000000..a2f0c0d --- /dev/null +++ b/zypp-core/base/ReferenceCounted.cc @@ -0,0 +1,58 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/base/ReferenceCounted.cc + * +*/ +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + ReferenceCounted::ReferenceCounted() + : _counter( 0 ) + {} + + ReferenceCounted::ReferenceCounted( const ReferenceCounted & /*rhs*/ ) + : _counter( 0 ) + {} + + ReferenceCounted::~ReferenceCounted() + { + if ( _counter ) + { + INT << "~ReferenceCounted: nonzero reference count" << std::endl; + } + } + + void ReferenceCounted::unrefException() const + { + INT << "ReferenceCounted::unref: zero reference count" << std::endl; + throw std::out_of_range( "ReferenceCounted::unref: zero reference count" ); + } + + std::ostream & ReferenceCounted::dumpOn( std::ostream & str ) const + { + return str << "ReferenceCounted(@" << (const void *)this + << "<=" << _counter << ")"; + } + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/ReferenceCounted.h b/zypp-core/base/ReferenceCounted.h new file mode 100644 index 0000000..08c8743 --- /dev/null +++ b/zypp-core/base/ReferenceCounted.h @@ -0,0 +1,144 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/base/ReferenceCounted.h + * +*/ +#ifndef ZYPP_CORE_BASE_REFERENCECOUNTED_H +#define ZYPP_CORE_BASE_REFERENCECOUNTED_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ReferenceCounted + // + /** Base class for reference counted objects. + * \todo Make counter thread safe. + */ + class ZYPP_API ReferenceCounted + { + /** Stream output via dumpOn. */ + friend std::ostream & operator<<( std::ostream & str, const ReferenceCounted & obj ); + + public: + /** Default ctor. + * Initial reference count is zero. + */ + ReferenceCounted(); + + /** Copy ctor. + * Initial reference count is zero. + */ + ReferenceCounted( const ReferenceCounted & rhs ); + + /** Dtor. + * \throw std::out_of_range if reference count is not zero. + */ + virtual ~ReferenceCounted(); + + /** Assignment. + * Reference count remains untouched. + */ + ReferenceCounted & operator=( const ReferenceCounted & ) + { return *this; } + + public: + /** Return reference counter value. */ + unsigned refCount() const + { return _counter; } + + /** Add a reference. */ + void ref() const + { ref_to( ++_counter ); } + + /** Release a reference. + * Deletes the object if reference count gets zero. + * \throw std::out_of_range if reference count is zero. + */ + void unref() const + { + if ( !_counter ) + unrefException(); // will throw! + if ( --_counter ) + unref_to( _counter ); + else + delete this; + } + + /** Called by zypp::intrusive_ptr to add a reference. + * \see ZYPP_SMART_PTR + */ + static void add_ref( const ReferenceCounted * ptr_r ) + { if( ptr_r ) ptr_r->ref(); } + + /** Called by zypp::intrusive_ptr to add a reference. + * \see ZYPP_SMART_PTR + */ + static void release( const ReferenceCounted * ptr_r ) + { if( ptr_r ) ptr_r->unref(); } + + protected: + /** Overload to realize std::ostream & operator\<\<. */ + virtual std::ostream & dumpOn( std::ostream & str ) const; + + /** Trigger derived classes after refCount was increased. */ + virtual void ref_to( unsigned /* rep_cnt_r */ ) const {} + + /** Trigger derived classes after refCount was decreased. + * No trigger is sent, if refCount got zero (i.e. the + * object is deleted). + **/ + virtual void unref_to( unsigned /* rep_cnt_r */ ) const {} + + private: + /** The reference counter. */ + mutable unsigned _counter; + + /** Throws Exception on unref. */ + void unrefException() const; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ReferenceCounted intrusive_ptr hook to add_ref. */ + inline void intrusive_ptr_add_ref( const ReferenceCounted * ptr_r ) + { ReferenceCounted::add_ref( ptr_r ); } + + /** \relates ReferenceCounted intrusive_ptr hook to release. */ + inline void intrusive_ptr_release( const ReferenceCounted * ptr_r ) + { ReferenceCounted::release( ptr_r ); } + + /** \relates ReferenceCounted Stream output. */ + inline std::ostream & operator<<( std::ostream & str, const ReferenceCounted & obj ) + { return obj.dumpOn( str ); } + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#define IMPL_PTR_TYPE(NAME) \ +void intrusive_ptr_add_ref( const NAME * ptr_r ) \ +{ zypp::base::ReferenceCounted::add_ref( ptr_r ); } \ +void intrusive_ptr_release( const NAME * ptr_r ) \ +{ zypp::base::ReferenceCounted::release( ptr_r ); } + +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CORE_BASE_REFERENCECOUNTED_H diff --git a/zypp-core/base/Regex.cc b/zypp-core/base/Regex.cc new file mode 100644 index 0000000..0ceea33 --- /dev/null +++ b/zypp-core/base/Regex.cc @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Regex.cc + * +*/ +#include +#include + +#include + +#include +#include + +using namespace zypp; +using namespace zypp::str; + +regex::regex() +: m_flags( match_extended ) +{} + +regex::regex( const std::string & str, int flags ) +{ assign( str, flags ); } + +regex::~regex() +{ + if ( m_valid ) + regfree( &m_preg ); +} + +void regex::assign( const std::string & str, int flags ) +{ + if ( m_valid ) + regfree( &m_preg ); + + m_valid = false; + m_str = str; + m_flags = flags; + + static constexpr int normal = 1<<16; // deprecated legacy, use match_extended + if ( flags & normal ) flags &= ~normal; + if ( (flags & rxdefault) != rxdefault ) flags |= rxdefault; // always enforced (legacy) + + if ( int err = regcomp( &m_preg, str.c_str(), flags ) ) { + char errbuff[100]; + regerror( err, &m_preg, errbuff, sizeof(errbuff) ); + ZYPP_THROW( regex_error(std::string(errbuff)) ); + } + m_valid = true; +} + +bool regex::matches( const char* s, smatch & matches, int flags ) const +{ + if ( m_valid ) { + const auto possibleMatchCount = m_preg.re_nsub + 1; + matches.pmatch.resize( possibleMatchCount ); + memset( matches.pmatch.data(), -1, sizeof( regmatch_t ) * ( possibleMatchCount ) ); + + if ( s && !regexec( &m_preg, s, matches.pmatch.size(), matches.pmatch.data(), flags ) ) { + matches.match_str = s; + return true; // good match + } + } + // Here: no match + matches.pmatch.clear(); + matches.match_str.clear(); + return false; +} + +bool regex::matches( const char* s ) const +{ + return m_valid && s && !regexec( &m_preg, s, 0, NULL, 0 ); +} + +bool zypp::str::regex_match( const char* s, smatch& matches, const regex& regex ) +{ return regex.matches( s, matches ); } + +bool zypp::str::regex_match( const char* s, const regex& regex ) +{ return regex.matches( s ); } + +smatch::smatch() +{} + +std::string smatch::operator[](unsigned i) const +{ + if ( i < pmatch.size() && pmatch[i].rm_so != -1 ) + return match_str.substr( pmatch[i].rm_so, pmatch[i].rm_eo-pmatch[i].rm_so ); + + return std::string(); +} + +std::string::size_type smatch::begin( unsigned i ) const +{ return( i < pmatch.size() && pmatch[i].rm_so != -1 ? pmatch[i].rm_so : std::string::npos ); } + +std::string::size_type smatch::end( unsigned i ) const +{ return( i < pmatch.size() && pmatch[i].rm_so != -1 ? pmatch[i].rm_eo : std::string::npos ); } + +std::string::size_type smatch::size( unsigned i ) const +{ return( i < pmatch.size() && pmatch[i].rm_so != -1 ? pmatch[i].rm_eo-pmatch[i].rm_so : std::string::npos ); } + +unsigned smatch::size() const +{ + unsigned matches = unsigned(-1); + // Get highest (pmatch[i].rm_so != -1). Just looking for the 1st + // (pmatch[i].rm_so == -1) is wrong as optional mayches "()?" + // may be embeded. + for ( unsigned i = 0; i < pmatch.size(); ++i ) + { + if ( pmatch[i].rm_so != -1 ) + matches = i; + } + return ++matches; +} + +std::string zypp::str::regex_substitute( const std::string &s, const regex ®ex, const std::string &replacement, bool global ) +{ + std::string result; + strv::splitRx( s, regex, [&result,&replacement,global]( std::string_view w, unsigned, bool last ) { + result += w; + if ( !last ) + result += replacement; + return global; + }); + return result; +} diff --git a/zypp-core/base/Regex.h b/zypp-core/base/Regex.h new file mode 100644 index 0000000..eac750e --- /dev/null +++ b/zypp-core/base/Regex.h @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Regex.h + * +*/ +#ifndef ZYPP_BASE_REGEX_H +#define ZYPP_BASE_REGEX_H + +#include +#include +#include + +#include + +////////////////////////////////////////////////////////////////// +namespace zypp +{ + ////////////////////////////////////////////////////////////////// + /// \namespace str + /// \brief String related utilities and \ref ZYPP_STR_REGEX. + namespace str + { + ////////////////////////////////////////////////////////////////// + /// \defgroup ZYPP_STR_REGEX Regular expression matching + /// \brief Regular expressions using the glibc regex library. + /// + /// \see also \ref StrMatcher string matcher also supporting globing, etc. + /// + /// \code + /// str::regex rxexpr( "^(A)?([0-9]*) im" ); + /// str::smatch what; + /// + /// std::string mytext( "Y123 imXXXX" ); + /// if ( str::regex_match( mytext, what, rxexpr ) ) + /// { + /// MIL << "MATCH '" << what[0] << "'" << endl; + /// MIL << " subs: " << what.size()-1 << endl; + /// for_( i, 1U, what.size() ) + /// MIL << " [" << i << "] " << what[i] << endl; + /// } + /// else + /// { + /// WAR << "NO MATCH '" << rxexpr << "' in '" << mytext << endl; + /// } + /// \endcode + ////////////////////////////////////////////////////////////////// + + using regex_error = Exception; + + class smatch; + class regex; + + ////////////////////////////////////////////////////////////////// + /// \brief Regular expression matching + /// + /// \ingroup ZYPP_STR_REGEX + /// \relates regex + /// Return whether a \ref regex matches a specific string. An optionally + /// passed \ref smatch object will contain the match reults. + ////////////////////////////////////////////////////////////////// + bool regex_match( const char * s, smatch & matches, const regex & regex ) ZYPP_API; + + /** \copydoc regex_match \relates regex \ingroup ZYPP_STR_REGEX */ + inline bool regex_match(const std::string & s, smatch & matches, const regex & regex) + { return regex_match( s.c_str(), matches, regex ); } + + /** \copydoc regex_match \relates regex \ingroup ZYPP_STR_REGEX */ + bool regex_match( const char * s, const regex & regex ) ZYPP_API; + + /** \copydoc regex_match \relates regex \ingroup ZYPP_STR_REGEX */ + inline bool regex_match( const std::string & s, const regex & regex ) + { return regex_match( s.c_str(), regex ); } + + /** + * Replaces the matched regex with the string passed in \a replacement. + * If \a global is set the search continues after the first match + * + * \note Using backreferences in the replacement string is NOT supported. + */ + std::string regex_substitute ( const std::string & s, const regex & regex, const std::string &replacement, bool global = true ) ZYPP_API; + + ////////////////////////////////////////////////////////////////// + /// \class regex + /// \brief Regular expression + /// + /// \ingroup ZYPP_STR_REGEX + ////////////////////////////////////////////////////////////////// + class ZYPP_API regex + { + public: + + enum RegFlags { + icase = REG_ICASE, ///< Do not differentiate case + nosubs = REG_NOSUB, ///< Support for substring addressing of matches is not required + match_extended = REG_EXTENDED, ///< Use POSIX Extended Regular Expression syntax when interpreting regex. + newline = REG_NEWLINE, ///< Match newline + rxdefault = match_extended|newline ///< These are enforced even if you don't pass them as flag argument + }; + + enum MatchFlags { + none = 0, + not_bol = REG_NOTBOL ///< Do not match begin of line + }; + + regex(); + regex( const std::string & s, int flags = rxdefault ); + regex( const char* s, int flags = rxdefault ) : regex( std::string(s?s:""), flags ) {} + ~regex(); + + regex( const regex & rhs ) + { assign( rhs.m_str, rhs.m_flags ); } + + regex & operator=( const regex & rhs ) + { assign( rhs.m_str, rhs.m_flags ); return *this; } + + /** + * string representation of the regular expression + */ + std::string asString() const + { return m_str; } + + bool matches( const char * s, str::smatch & matches, int flags = none ) const; + bool matches( const std::string & s_r, str::smatch & matches_r, int flags_r = none ) const + { return matches( s_r.c_str(), matches_r, flags_r ); } + + bool matches( const char * s ) const; + bool matches( const std::string & s_r ) const + { return matches( s_r.c_str() ); } + + public: + /** Expert backdoor. Returns pointer to the compiled regex for direct use in regexec() */ + regex_t * get() + { return & m_preg; } + + private: + void assign( const std::string & s, int flags ); + + private: + friend class smatch; + std::string m_str; + int m_flags; + regex_t m_preg; + bool m_valid = false; + }; + + /** \relates regex Stream output */ + inline std::ostream & operator<<( std::ostream & str, const regex & obj ) + { return str << obj.asString(); } + + ////////////////////////////////////////////////////////////////// + /// \class smatch + /// \brief Regular expression match result + /// + /// \ingroup ZYPP_STR_REGEX + /// + /// Index \c n=0 returns the string object representing the character + /// sequence that matched the whole regular expression. + /// If \c n is out of range, or if \c n is an unmatched sub-expression, + /// then an empty string is returned. + ////////////////////////////////////////////////////////////////// + class ZYPP_API smatch + { + public: + smatch(); + + std::string operator[](unsigned i) const; + + unsigned size() const; + + /** Begin index of subexpression \c i in \a match_str (or std::string::npos) */ + std::string::size_type begin( unsigned i ) const; + + /** End index of subexpression \c i in \a match_str (or std::string::npos) */ + std::string::size_type end( unsigned i ) const; + + /** Size of subexpression \c i (or std::string::npos) */ + std::string::size_type size( unsigned i ) const; + + std::string match_str; + std::vector pmatch; + }; + + } // namespace str + ////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_STRING_H diff --git a/zypp-core/base/SimpleStreambuf b/zypp-core/base/SimpleStreambuf new file mode 100644 index 0000000..2421b3a --- /dev/null +++ b/zypp-core/base/SimpleStreambuf @@ -0,0 +1 @@ +#include "simplestreambuf.h" diff --git a/zypp-core/base/String.cc b/zypp-core/base/String.cc new file mode 100644 index 0000000..ea230bc --- /dev/null +++ b/zypp-core/base/String.cc @@ -0,0 +1,523 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/String.cc + * +*/ +#include +#include + +#include +#include + +#include +#include + +#include + +using std::string; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace str + { ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : form + ** FUNCTION TYPE : std::string + */ + std::string form( const char * format, ... ) + { + SafeBuf safe; + + va_list ap; + va_start( ap, format ); + vasprintf( &safe._buf, format, ap ); + va_end( ap ); + + return safe.asString(); + } + + /****************************************************************** + ** + ** FUNCTION NAME : strerror + ** FUNCTION TYPE : std::string + */ + std::string strerror( int errno_r ) + { + return form( "(%d)%s", errno_r, ::strerror( errno_r ) ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : strToTrue + ** FUNCTION TYPE : bool + */ + bool strToTrue( const C_Str & str ) + { + std::string t( toLower( str ) ); + return( t == "1" + || t == "yes" + || t == "true" + || t == "always" + || t == "on" + || t == "+" + || strtonum( str ) + ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : strToFalse + ** FUNCTION TYPE : bool + */ + bool strToFalse( const C_Str & str ) + { + std::string t( toLower( str ) ); + return ! ( t == "0" + || t == "no" + || t == "false" + || t == "never" + || t == "off" + || t == "-" + ); + } + + TriBool strToTriBool( const C_Str & str ) // from TriBool.h + { + if ( strToTrue( str ) ) return true; + if ( !strToFalse( str ) ) return false; + return indeterminate; + } + + /////////////////////////////////////////////////////////////////// + // Hexencode + /////////////////////////////////////////////////////////////////// + namespace { + /** What's not decoded. */ + inline bool heIsAlNum( char ch ) + { + return ( ( 'a' <= ch && ch <= 'z' ) + ||( 'A' <= ch && ch <= 'Z' ) + ||( '0' <= ch && ch <= '9' ) ); + } + /** Hex-digit to number or -1. */ + inline int heDecodeCh( char ch ) + { + if ( '0' <= ch && ch <= '9' ) + return( ch - '0' ); + if ( 'A' <= ch && ch <= 'F' ) + return( ch - 'A' + 10 ); + if ( 'a' <= ch && ch <= 'f' ) + return( ch - 'a' + 10 ); + return -1; + } + } + + std::string hexencode( const C_Str & str_r ) + { + static const char *const hdig = "0123456789ABCDEF"; + std::string res; + res.reserve( str_r.size() ); + for ( const char * it = str_r.c_str(); *it; ++it ) + { + if ( heIsAlNum( *it ) ) + { + res += *it; + } + else + { + res += '%'; + res += hdig[(unsigned char)(*it)/16]; + res += hdig[(unsigned char)(*it)%16]; + } + } + return res; + } + + std::string hexdecode( const C_Str & str_r ) + { + std::string res; + res.reserve( str_r.size() ); + for_( it, str_r.c_str(), str_r.c_str()+str_r.size() ) + { + if ( *it == '%' ) + { + int d1 = heDecodeCh( *(it+1) ); + if ( d1 != -1 ) + { + int d2 = heDecodeCh( *(it+2) ); + if ( d2 != -1 ) + { + res += (d1<<4)|d2; + it += 2; + continue; + } + } + } + // verbatim if no %XX: + res += *it; + } + return res; + } + /////////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : toLower + ** FUNCTION TYPE : std::string + */ + std::string toLower( const std::string & s ) + { return toLower( std::string(s) ); } + + std::string toLower( std::string && s ) + { + std::string ret( std::move(s) ); + + if ( ret.empty() ) + return ret; + + for ( std::string::size_type i = 0; i < ret.length(); ++i ) + { + if ( isupper( ret[i] ) ) + ret[i] = static_cast(tolower( ret[i] )); + } + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : toUpper + ** FUNCTION TYPE : std::string + */ + std::string toUpper( const std::string & s ) + { return toUpper( std::string(s) ); } + + std::string toUpper( std::string && s ) + { + std::string ret( std::move(s) ); + + if ( ret.empty() ) + return ret; + + for ( std::string::size_type i = 0; i < ret.length(); ++i ) + { + if ( islower( ret[i] ) ) + ret[i] = static_cast(toupper( ret[i] )); + } + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : trim + ** FUNCTION TYPE : std::string + */ + std::string trim( const std::string & s, const Trim trim_r ) + { return trim( std::string(s), trim_r ); } + + std::string trim( std::string && s, const Trim trim_r ) + { + std::string ret( std::move(s) ); + + if ( ret.empty() || trim_r == NO_TRIM ) + return ret; + + if ( trim_r & L_TRIM ) + { + std::string::size_type p = ret.find_first_not_of( " \t\n" ); + if ( p == std::string::npos ) + { + ret.clear(); + return ret; + } + ret.erase( 0, p ); + } + + if ( trim_r & R_TRIM ) + { + std::string::size_type p = ret.find_last_not_of( " \t\n" ); + if ( p == std::string::npos ) + { + ret.clear(); + return ret; + } + ret = ret.erase( p+1 ); + } + + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : stripFirstWord + ** FUNCTION TYPE : std::string + */ + std::string stripFirstWord( std::string & line, const bool ltrim_first ) + { + if ( ltrim_first ) + line = ltrim( line ); + + if ( line.empty() ) + return line; + + std::string ret; + std::string::size_type p = line.find_first_of( " \t" ); + + if ( p == std::string::npos ) { + // no ws on line + ret = line; + line.erase(); + } else if ( p == 0 ) { + // starts with ws + // ret remains empty + line = ltrim( line ); + } + else { + // strip word and ltim line + ret = line.substr( 0, p ); + line = ltrim( line.erase( 0, p ) ); + } + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : stripLastWord + ** FUNCTION TYPE : std::string + */ + std::string stripLastWord( std::string & line, const bool rtrim_first ) + { + if ( rtrim_first ) + line = rtrim( line ); + + if ( line.empty() ) + return line; + + std::string ret; + std::string::size_type p = line.find_last_of( " \t" ); + + if ( p == std::string::npos ) { + // no ws on line + ret = line; + line.erase(); + } else if ( p == line.size()-1 ) { + // ends with ws + // ret remains empty + line = rtrim( line ); + } + else { + // strip word and rtim line + ret = line.substr( p+1 ); + line = rtrim( line.erase( p ) ); + } + return ret; + } + + std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r ) + { + std::string ret( str_r ); + return replaceAll( ret, from_r, to_r ); + } + + std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r ) + { + if ( ! from_r.empty() ) + { + std::string::size_type pos = 0; + while ( (pos = str_r.find( from_r, pos )) != std::string::npos ) + { + str_r.replace( pos, from_r.size(), to_r ); + pos += to_r.size(); + + if ( pos >= str_r.length() ) + break; + } + } + return str_r; + } + + std::string gsubFun( const std::string & str_r, const std::string & from_r, function to_r ) + { + std::string ret( str_r ); + return replaceAllFun( ret, from_r, std::move(to_r) ); + } + + std::string & replaceAllFun( std::string & str_r, const std::string & from_r, const function& to_r ) + { + if ( ! from_r.empty() ) + { + std::string::size_type pos = 0; + while ( (pos = str_r.find( from_r, pos )) != std::string::npos ) + { + std::string to( to_r() ); + str_r.replace( pos, from_r.size(), to ); + pos += to.size(); + + if ( pos >= str_r.length() ) + break; + } + } + return str_r; + } + + std::string escape( const C_Str & str_r, const char sep_r ) + { + std::vector buf; + for_( s, str_r.c_str(), s+str_r.size() ) + { + switch ( *s ) + { + case '"': + case '\'': + case '\\': + buf.push_back( '\\' ); + buf.push_back( *s ); + break; + default: + if ( *s == sep_r ) + buf.push_back( '\\' ); + buf.push_back( *s ); + } + } + return std::string( buf.begin(), buf.end() ); + } + + + std::string bEscape( std::string str_r, const C_Str & special_r ) + { + if ( str_r.empty() ) + return str_r; + + if ( str_r.find_first_of( special_r ) == std::string::npos + && ( ::strchr( special_r.c_str(), '\\' ) || !::strchr( str_r.c_str(), '\\' ) ) ) + return str_r; + + Str buf; + for_( s, str_r.c_str(), s+str_r.size() ) + { + if ( *s == '\\' || ::strchr( special_r.c_str(), *s ) ) + buf << '\\'; + buf << *s; + } + return buf; + } + + #define RXSPECIALCHARS "\\.*+?^$[()|{" + + std::string rxEscapeStr( std::string str_r ) + { + return bEscape( std::move(str_r), RXSPECIALCHARS ); + } + + std::string rxEscapeGlob( std::string str_r ) + { + if ( str_r.empty() ) + return str_r; + + if ( str_r.find_first_of( RXSPECIALCHARS ) == std::string::npos ) + return str_r; + + Str buf; + for_( s, str_r.c_str(), s+str_r.size() ) + { + if ( *s == '\\' ) // + next char literally + { + buf << '\\'; + if ( *(s+1) ) { ++s; buf << *s; } + } + else if ( *s == '?' ) // translate + { + buf << '.'; + } + else if ( *s == '*' ) // translate + { + buf << ".*"; + } + else if ( *s == '[' ) // character class if closing ] is found, else literally + { + const char * e = s+1; + if ( *e == '^' || *e == '!' ) // negated cclass + ++e; + if ( *e == ']' ) // ] in cclass + ++e; + while ( *e && *e != ']' ) // ...to ] or \0 + ++e; + if ( *e ) // on closing ']' + { + ++s; buf << '[' << (*s == '!' ? '^' : *s ); + while ( ++s != e ) + buf << *s; + buf << ']'; + } + else + { + buf << "\\["; + } + } + else if ( ::strchr( RXSPECIALCHARS, *s ) ) // escape + { + buf << '\\' << *s; + } + else + { + buf << *s; + } + } + return buf; + } + + + std::string getline( std::istream & str, const Trim trim_r ) + { + return trim( receiveUpTo( str, '\n' ), trim_r ); + } + + std::string getline( std::istream & str, bool trim_r ) + { + return trim( receiveUpTo( str, '\n' ), trim_r?TRIM:NO_TRIM ); + } + + std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r ) + { + std::ostringstream datas; + do { + char ch = 0; + if ( str.get( ch ) ) + { + if ( ch != delim_r ) + { + datas.put( ch ); + } + else + { + if ( returnDelim_r ) + datas.put( ch ); + break; // --> delimiter found + } + } + else + { + // clear fail bit if we read data before reaching EOF + if ( str.eof() && datas.tellp() ) + str.clear( std::ios::eofbit ); + break; // --> no consumable data. + } + } while ( true ); + return datas.str(); + } + + ///////////////////////////////////////////////////////////////// + } // namespace str + /////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/String.h b/zypp-core/base/String.h new file mode 100644 index 0000000..dde99a6 --- /dev/null +++ b/zypp-core/base/String.h @@ -0,0 +1,1106 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/String.h + * +*/ +#ifndef ZYPP_BASE_STRING_H +#define ZYPP_BASE_STRING_H + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace boost { namespace logic { class tribool; } } +namespace zypp { using TriBool = boost::logic::tribool; } +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /** Request a human readable (translated) string representation of Tp [Tp.asUserString()] + * Classes may implement a default as member function. + */ + template + std::string asUserString( const Tp & val_r ) + { return val_r.asUserString(); } + +}// namespace zypp +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Convenience \c char* constructible from \c std::string and \c char*, + * it maps \c (char*)0 to an empty string. + * + * \code + * bool hasPrefix( const std::string & str_r, const std::string & prefix_r ) + * { return( ::strncmp( str_r.c_str(), prefix_r.c_str(), prefix_r.size() ) == 0 ); } + * \endcode + * + * Called with a plain \c char* as argument, the \c std::string is created form + * for nothing. The implementation actually does not use the \c std::string. + * + * Best would be to implement \c hasPrefix for each combination of \c char* + * and \c std::string arguments: + * + * \code + * bool hasPrefix( const std::string & str_r, const std::string & prefix_r ) + * { return( ::strncmp( str_r.c_str(), prefix_r.c_str(), prefix_r.size() ) == 0 ); } + * + * bool hasPrefix( const std::string & str_r, const char * prefix_r ) + * { return( !prefix_r || ::strncmp( str_r.c_str(), prefix_r, ::strlen(prefix_r) ) == 0 ); } + * + * bool hasPrefix( const char * str_r, const std::string & prefix_r ) + * { return( str_r ? ::strncmp( str_r, prefix_r.c_str(), prefix_r.size() ) == 0 : prefix_r.empty() ); } + * + * bool hasPrefix( const char * str_r, const char * prefix_r ) + * { return( str && prefix_r ? ::strncmp( str_r, prefix_r, ::strlen(prefix_r) ) == 0 + * : !((str_r && *str_r) || (prefix_r && *prefix_r)); } + * \endcode + * + * This is where \ref C_Str can help. Constructible from \c std::string and \c char*, + * it \e reduces the \c std::string to its \c char*. At the same, time it converts + * \c (char*)0 into an \c "" string. + * + * \code + * bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r ) + * { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); } + * \endcode + * + * \todo Check whether to replace by boost::string_ref + */ + class C_Str + { + public: + using size_type = std::string::size_type; + + public: + C_Str() : _val( 0 ), _sze( 0 ) {} + C_Str( char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {} + C_Str( const char * c_str_r ) : _val( c_str_r ), _sze( std::string::npos ) {} + C_Str( const std::string & str_r ) : _val( str_r.c_str() ), _sze( str_r.size() ) {} + C_Str( const boost::string_ref & str_r ) : _val( str_r.data() ), _sze( str_r.size() ) {} +#ifdef __cpp_lib_string_view + C_Str( const std::string_view & str_r ) : _val( str_r.data() ), _sze( str_r.size() ) {} +#endif + + public: + bool isNull() const { return !_val; } + bool empty() const { return !(_val && *_val); } + size_type size() const + { + if ( _sze == std::string::npos ) + { _sze = _val ? ::strlen( _val ) : 0; } + return _sze; + }; + + operator const char *() const { return c_str(); } + const char * c_str() const { return _val ? _val : ""; } + + private: + const char *const _val; + mutable size_type _sze; + }; + + /** \relates C_Str Stream output */ + inline std::ostream & operator<<( std::ostream & str, const C_Str & obj ) + { return str << obj.c_str(); } + + /////////////////////////////////////////////////////////////////// + /** String related utilities and \ref ZYPP_STR_REGEX. + \see \ref ZYPP_STR_REGEX + */ + + namespace str + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /** + * Global asString() that works with std::string too + */ + inline const std::string & asString( const std::string & t ) + { return t; } + + inline std::string && asString( std::string && t ) + { return std::move(t); } + + inline std::string asString( const char * t ) + { return t == nullptr ? std::string() : t; } + + inline std::string asString( char * t ) + { return t == nullptr ? std::string() : t; } + + template + inline std::string asString( const Tp &t ) + { return t.asString(); } + + template + inline std::string asString( const intrusive_ptr &p ) + { return p->asString(); } + + template + inline std::string asString( const weak_ptr &p ) + { return p->asString(); } + + template<> + inline std::string asString( const bool &t ) + { return t ? "true" : "false"; } + + /////////////////////////////////////////////////////////////////// + /** Printf style construction of std::string. */ + std::string form( const char * format, ... ) + __attribute__ ((format (printf, 1, 2))) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + /** Return string describing the \a error_r code. + * Like ::strerror, but the numerical value is included in + * the string as well. + */ + std::string strerror( int errno_r ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + /** Assert \c free called for allocated char *. + * \code + * ... + * SafeBuf safe; + * vasprintf( &safe._buf, format, ap ); + * return safe.asString(); + * \endcode + * + * \ingroup g_RAII + */ + struct SafeBuf + { + char * _buf; + SafeBuf() : _buf( 0 ) {} + ~SafeBuf() { if ( _buf ) free( _buf ); } + std::string asString() const + { return _buf ? std::string(_buf) : std::string(); } + }; + + /////////////////////////////////////////////////////////////////// + /// \class Str + /// \brief Convenient building of std::string via \ref std::ostringstream + /// Basically a \ref std::ostringstream autoconvertible to \ref std::string + /// for building string arguments. + /// \code + /// void fnc( const std::string & txt_r ); + /// fnc( str::Str() << "Hello " << 13 ); + /// + /// std::string txt( str::Str() << 45 ); + /// \endcode + /////////////////////////////////////////////////////////////////// + struct Str + { + template + Str & operator<<( Tp && val ) + { _str << std::forward(val); return *this; } + + Str & operator<<( std::ostream& (*iomanip)( std::ostream& ) ) + { _str << iomanip; return *this; } + + operator std::string() const { return _str.str(); } + std::string asString() const { return _str.str(); } + std::string str() const { return _str.str(); } + + const std::ostream & stream() const { return _str; } + std::ostream & stream() { return _str; } + + void clear() { _str.str( std::string() ); } + + private: + std::ostringstream _str; + }; + + /** \relates Str Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Str & obj ) + { return str << obj.str(); } + + /////////////////////////////////////////////////////////////////// + /// \class Format + /// \brief Convenient building of std::string with \ref boost::format. + /// Basically a \ref boost::format autoconvertible to \ref std::string + /// for building string arguments. + /// \note It won't complain about malformed or incomplete format + /// strings. Usefull when dealing with translations or classes + /// providing a default formater. + /// \code + /// void fnc( const std::string & txt_r ); + /// fnc( str::Format("Hello %1%") % 13 ); + /// + /// std::string txt( str::Format("Hello %1%") % 13 ); + /// \endcode + /////////////////////////////////////////////////////////////////// + struct Format + { + Format() { _fmter.exceptions( boost::io::no_error_bits ); } + Format( const std::string & format_r ) : Format() { _fmter.parse( format_r ); } + + template + Format & operator%( Tp && arg ) + { _fmter % std::forward(arg); return *this; } + + operator std::string() const { return _fmter.str(); } + std::string asString() const { return _fmter.str(); } + std::string str() const { return _fmter.str(); } + + const boost::format & fmter() const { return _fmter; } + boost::format & fmter() { return _fmter; } + + protected: + boost::format _fmter; + }; + + /** \relates Format Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Format & obj ) + { return str << obj.fmter(); } + + /** \name String representation of number. + * + * Optional second argument sets the minimal string width (' ' padded). + * Negative values will cause the number to be left adjusted within the string. + * + * Default width is 0. + * \code + * numstring(42) -> "42" + * numstring(42, 4) -> " 42" + * numstring(42,-4) -> "42 " + * \endcode + **/ + //@{ + inline std::string numstring( char n, int w = 0 ) { return form( "%*hhd", w, n ); } + inline std::string numstring( unsigned char n, int w = 0 ) { return form( "%*hhu", w, n ); } + inline std::string numstring( short n, int w = 0 ) { return form( "%*hd", w, n ); } + inline std::string numstring( unsigned short n, int w = 0 ) { return form( "%*hu", w, n ); } + inline std::string numstring( int n, int w = 0 ) { return form( "%*d", w, n ); } + inline std::string numstring( unsigned n, int w = 0 ) { return form( "%*u", w, n ); } + inline std::string numstring( long n, int w = 0 ) { return form( "%*ld", w, n ); } + inline std::string numstring( unsigned long n, int w = 0 ) { return form( "%*lu", w, n ); } + inline std::string numstring( long long n, int w = 0 ) { return form( "%*lld", w, n ); } + inline std::string numstring( unsigned long long n, int w = 0 ) { return form( "%*llu", w, n ); } + + template<> inline std::string asString( const char & t ) { return numstring( t ); } + template<> inline std::string asString( const unsigned char & t ) { return numstring( t ); } + template<> inline std::string asString( const short & t ) { return numstring( t ); } + template<> inline std::string asString( const unsigned short & t ) { return numstring( t ); } + template<> inline std::string asString( const int & t ) { return numstring( t ); } + template<> inline std::string asString( const unsigned & t ) { return numstring( t ); } + template<> inline std::string asString( const long & t ) { return numstring( t ); } + template<> inline std::string asString( const unsigned long & t ) { return numstring( t ); } + template<> inline std::string asString( const long long & t ) { return numstring( t ); } + template<> inline std::string asString( const unsigned long long & t ) { return numstring( t ); } + //@} + + /////////////////////////////////////////////////////////////////// + /** \name String representation of number as hex value with leading '0x'. + * Optional second argument sets the minimal + * string width (0 padded). Negative values will cause the number to be left adjusted + * within the string. Default width is 10 (4 for char). + *

+     * hexstring(42)           -> "0x0000002a"
+     * hexstring(42, 4)        -> "0x2a"
+     * hexstring(42,-4)        -> "0x2a"
+     * 
+ **/ + //@{ + inline std::string hexstring( char n, int w = 4 ) { return form( "%#0*hhx", w, n ); } + inline std::string hexstring( unsigned char n, int w = 4 ) { return form( "%#0*hhx", w, n ); } + inline std::string hexstring( short n, int w = 10 ){ return form( "%#0*hx", w, n ); } + inline std::string hexstring( unsigned short n, int w = 10 ){ return form( "%#0*hx", w, n ); } + inline std::string hexstring( int n, int w = 10 ){ return form( "%#0*x", w, n ); } + inline std::string hexstring( unsigned n, int w = 10 ){ return form( "%#0*x", w, n ); } + inline std::string hexstring( long n, int w = 10 ){ return form( "%#0*lx", w, n ); } + inline std::string hexstring( unsigned long n, int w = 10 ){ return form( "%#0*lx", w, n ); } + inline std::string hexstring( long long n, int w = 0 ) { return form( "%#0*llx", w, n ); } + inline std::string hexstring( unsigned long long n, int w = 0 ) { return form( "%#0*llx", w, n ); } + //@} + + /////////////////////////////////////////////////////////////////// + /** \name String representation of number as octal value with leading '0'. + * Optional second argument sets the minimal + * string width (0 padded). Negative values will cause the number to be left adjusted + * within the string. Default width is 5 (4 for char). + *
+     * octstring(42)           -> "00052"
+     * octstring(42, 4)        -> "0052"
+     * octstring(42,-4)        -> "052 "
+     * 
+ **/ + //@{ + inline std::string octstring( char n, int w = 4 ) { return form( "%#0*hho", w, n ); } + inline std::string octstring( unsigned char n, int w = 4 ) { return form( "%#0*hho", w, n ); } + inline std::string octstring( short n, int w = 5 ) { return form( "%#0*ho", w, n ); } + inline std::string octstring( unsigned short n, int w = 5 ) { return form( "%#0*ho", w, n ); } + inline std::string octstring( int n, int w = 5 ) { return form( "%#0*o", w, n ); } + inline std::string octstring( unsigned n, int w = 5 ) { return form( "%#0*o", w, n ); } + inline std::string octstring( long n, int w = 5 ) { return form( "%#0*lo", w, n ); } + inline std::string octstring( unsigned long n, int w = 5 ) { return form( "%#0*lo", w, n ); } + inline std::string octstring( long long n, int w = 0 ) { return form( "%#0*llo", w, n ); } + inline std::string octstring( unsigned long long n, int w = 0 ) { return form( "%#0*llo", w, n ); } + //@} + + + /////////////////////////////////////////////////////////////////// + /** String representation of number as bit-string with leading '0's. */ + template + std::string binstring( TInt val_r ) + { + constexpr unsigned bits = sizeof(TInt)*8; + std::string ret( bits, ' ' ); + TInt bit = 1; + for ( unsigned pos = bits; pos > 0; ) + { --pos; ret[pos] = ((val_r & bit)?'1':'0'); bit = bit<<1; } + return ret; + } + + /////////////////////////////////////////////////////////////////// + /** Parsing numbers from string. + */ + //@{ + /** String to integer type determined by template arg. + * \note Only specializations are defined. + * \code + * time_t t = strtonum( "42" ); + * \endcode + */ + template + TInt strtonum( const C_Str & str ); + + template<> + inline short strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); } + template<> + inline int strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); } + template<> + inline long strtonum( const C_Str & str ) { return ::strtol ( str, NULL, 0 ); } + template<> + inline long long strtonum( const C_Str & str ) { return ::strtoll ( str, NULL, 0 ); } + + template<> + inline unsigned short strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); } + template<> + inline unsigned strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); } + template<> + inline unsigned long strtonum( const C_Str & str ) { return ::strtoul ( str, NULL, 0 ); } + template<> + inline unsigned long long strtonum( const C_Str & str ) { return ::strtoull( str, NULL, 0 ); } + + /** String to integer type detemined 2nd function arg \a i. + * \code + * time_t t; strtonum( "42", t ); + * \endcode + */ + template + inline TInt strtonum( const C_Str & str, TInt & i ) + { return i = strtonum( str ); } + //@} + + /////////////////////////////////////////////////////////////////// + /** Parsing boolean from string. + */ + //@{ + /** Return \c true if str is 1, true, yes, on, always (or a nonzero number). */ + bool strToTrue( const C_Str & str ) ZYPP_API; + + /** Return \c false if str is 0, false, no, off, never. */ + bool strToFalse( const C_Str & str ) ZYPP_API; + + /** Parse \c str into a bool depending on the default value. + * If the \c default is true, look for a legal \c false string. + * If the \c default is false, look for a legal \c true string. + */ + inline bool strToBool( const C_Str & str, bool default_r ) + { return( default_r ? strToFalse( str ) : strToTrue( str ) ); } + + /** Parse \c str into a bool if it's a legal \c true or \c false string. + * If \c str is not a recognized \c true or \c false string, \a return_r + * is left unchanged. + */ + inline bool strToBoolNodefault( const C_Str & str, bool & return_r ) + { + if ( strToTrue( str ) ) return (return_r = true); + if ( !strToFalse( str ) ) return (return_r = false); + return return_r; + } + + /** Parse \c str into a bool if it's a legal \c true or \c false string; else \c indeterminate. */ + TriBool strToTriBool( const C_Str & str ) ZYPP_API; + + //@} + + /** + * \short Return a string with all occurrences of \c from_r replaced with \c to_r. + */ + std::string gsub( const std::string & str_r, const std::string & from_r, const std::string & to_r ) ZYPP_API; + + /** \overload A function is called on demand to compute each replacement value. + */ + std::string gsubFun( const std::string & str_r, const std::string & from_r, function to_r ) ZYPP_API; + + /** + * \short Replace all occurrences of \c from_r with \c to_r in \c str_r (inplace). + * A reference to \c str_r is also returned for convenience. + */ + std::string & replaceAll( std::string & str_r, const std::string & from_r, const std::string & to_r ) ZYPP_API; + + /** \overload A function is called on demand to compute each replacement value. + */ + std::string & replaceAllFun( std::string & str_r, const std::string & from_r, const function& to_r ) ZYPP_API; + + /** Enhance readability: insert gaps at regular distance + * \code + * // no gaps + * Key Fingerprint: 22C07BA534178CD02EFE22AAB88B2FD43DBDC284 + * // gapify 8 + * Key Fingerprint: 22C07BA5 34178CD0 2EFE22AA B88B2FD4 3DBDC284 + * // gapify 4 + * Key Fingerprint: 22C0 7BA5 3417 8CD0 2EFE 22AA B88B 2FD4 3DBD C284 + * // gapify 4, '-' + * Key Fingerprint: 22C0-7BA5-3417-8CD0-2EFE-22AA-B88B-2FD4-3DBD-C284 + * \endcode + */ + inline std::string gapify( std::string inp_r, std::string::size_type gap_r = 1, char gapchar = ' ' ) + { + if ( gap_r && inp_r.size() > gap_r ) + { + inp_r.reserve( inp_r.size() + (inp_r.size()-1)/gap_r ); + for ( std::string::size_type pos = gap_r; pos < inp_r.size(); pos += gap_r+1 ) + inp_r.insert( pos, 1, gapchar ); + } + return inp_r; + } + + /////////////////////////////////////////////////////////////////// + /** \name Trimming whitepace. + * \todo optimize l/r trim. + */ + //@{ + /** To define how to trim. */ + enum Trim { + NO_TRIM = 0x00, + L_TRIM = 0x01, + R_TRIM = 0x02, + TRIM = (L_TRIM|R_TRIM) + }; + + std::string trim( const std::string & s, const Trim trim_r = TRIM ) ZYPP_API; + std::string trim( std::string && s, const Trim trim_r = TRIM ) ZYPP_API; + + inline std::string ltrim( const std::string & s ) + { return trim( s, L_TRIM ); } + inline std::string ltrim( std::string && s ) + { return trim( std::move(s), L_TRIM ); } + + inline std::string rtrim( const std::string & s ) + { return trim( s, R_TRIM ); } + inline std::string rtrim( std::string && s ) + { return trim( std::move(s), R_TRIM ); } + //@} + + + /////////////////////////////////////////////////////////////////// + /** \name Split. */ + //@{ + /** Split \a line_r into words. + * Any sequence of characters in \a sepchars_r is treated as + * delimiter. The words are passed to OutputIterator \a result_r. + * \code + * std::vector words; + * str::split( "some line", std::back_inserter(words) ) + * \endcode + * + */ + template + unsigned split( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = " \t", const Trim trim_r = NO_TRIM ) + { + const char * beg = line_r; + const char * cur = beg; + // skip leading sepchars + while ( *cur && ::strchr( sepchars_r, *cur ) ) + ++cur; + unsigned ret = 0; + for ( beg = cur; *beg; beg = cur, ++result_r, ++ret ) + { + // skip non sepchars + while( *cur && !::strchr( sepchars_r, *cur ) ) + ++cur; + // build string + *result_r = trim( std::string( beg, cur-beg ), trim_r ); + // skip sepchars + while ( *cur && ::strchr( sepchars_r, *cur ) ) + ++cur; + } + return ret; + } + + template + unsigned split( const C_Str & line_r, TOutputIterator result_r, const Trim trim_r ) + { return split( line_r, result_r, " \t", trim_r ); } + + + /** Split \a line_r into words with respect to escape delimeters. + * Any sequence of characters in \a sepchars_r is treated as + * delimiter if not inside \c "" or \c '' or escaped by \c \. + * + * \li A non-quoted backslash (\) preserves the literal value of the next character. + * \li Enclosing characters in single quotes preserves the literal value of each + * character within the quotes. A single quote may not occur between single + * quotes, even when preceded by a backslash. + * \li Enclosing characters in double quotes preserves the literal value of all + * characters within the quotes, with the exception of \c \. The backslash + * retains its special meaning only when followed by \c " or \c \. + * + * The words are passed to OutputIterator \a result_r. + * + * \see \ref splitEscaped + * + * \code + * std::vector words; + * str::splitEscaped( "some line", std::back_inserter(words) ) + * \endcode + * + * \code + * example splitted strings + * normal line -> 2 elements ( "normal", "line" ) + * escaped\ line -> 1 element(escaped line) + * "quoted line" -> 1 element same as above + * 'quoted line' -> 1 element same as above + * "escaped quote\"" -> 1 element (escaped quote") + * + * \param line_r The string to parse. + * \param result_r + * \param sepchars_r String of separator characters. + * \param withEmpty Whether to include empty fields between separators in the result. + * + * \endcode + */ + template + unsigned splitEscaped( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = " \t", bool withEmpty = false) + { + const char * beg = line_r; + const char * cur = beg; + unsigned ret = 0; + + // skip leading sepchars + while ( *cur && ::strchr( sepchars_r, *cur ) ) + { + ++cur; + if (withEmpty) + { + *result_r = ""; + ++ret; + } + } + + // there were only sepchars in the string + if (!*cur && withEmpty) + { + *result_r = ""; + return ++ret; + } + + // after the leading sepchars + enum class Quote { None, Slash, Single, Double, DoubleSlash }; + std::vector buf; + Quote quoting = Quote::None; + for ( beg = cur; *beg; beg = cur, ++result_r, ++ret ) + { + // read next value until unquoted sepchar + buf.clear(); + quoting = Quote::None; + do { + switch ( quoting ) + { + case Quote::None: + switch ( *cur ) + { + case '\\': quoting = Quote::Slash; break; + case '\'': quoting = Quote::Single; break; + case '"': quoting = Quote::Double; break; + default: buf.push_back( *cur ); break; + } + break; + + case Quote::Slash: + buf.push_back( *cur ); + quoting = Quote::None; + break; + + case Quote::Single: + switch ( *cur ) + { + case '\'': quoting = Quote::None; break; + default: buf.push_back( *cur ); break; + } + break; + + case Quote::Double: + switch ( *cur ) + { + case '\"': quoting = Quote::None; break; + case '\\': quoting = Quote::DoubleSlash; break; + default: buf.push_back( *cur ); break; + } + break; + + case Quote::DoubleSlash: + switch ( *cur ) + { + case '\"': /*fallthrough*/ + case '\\': buf.push_back( *cur ); break; + default: + buf.push_back( '\\' ); + buf.push_back( *cur ); + break; + } + quoting = Quote::Double; + break; + } + ++cur; + } while ( *cur && ( quoting != Quote::None || !::strchr( sepchars_r, *cur ) ) ); + *result_r = std::string( buf.begin(), buf.end() ); + + + // skip sepchars + if ( *cur && ::strchr( sepchars_r, *cur ) ) + ++cur; + while ( *cur && ::strchr( sepchars_r, *cur ) ) + { + ++cur; + if (withEmpty) + { + *result_r = ""; + ++ret; + } + } + // the last was a separator => one more field + if ( !*cur && withEmpty && ::strchr( sepchars_r, *(cur-1) ) ) + { + *result_r = ""; + ++ret; + } + } + return ret; + } + + /** Split \a line_r into fields. + * Any single character in \a sepchars_r is treated as a + * field separator unless \-escaped. The words are passed + * to OutputIterator. + * \a result_r. + * \code + * "" -> words 0 + * ":" -> words 2 ||| + * "a" -> words 1 |a| + * ":a" -> words 2 ||a| + * "a:" -> words 2 |a|| + * ":a:" -> words 3 ||a|| + * + * \endcode + * + * \code + * std::vector words; + * str::split( "some line", std::back_inserter(words) ) + * \endcode + * + */ + template + unsigned splitFields( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = ":" ) + { + const char * beg = line_r; + const char * cur = beg; + unsigned ret = 0; + for ( beg = cur; *beg; beg = cur, ++result_r ) + { + // skip non sepchars + while( *cur && !::strchr( sepchars_r, *cur ) ) + { + if ( *cur == '\\' && *(cur+1) ) + ++cur; + ++cur; + } + // build string + *result_r = std::string( beg, cur-beg ); + ++ret; + // skip sepchar + if ( *cur ) + { + ++cur; + if ( ! *cur ) // ending with sepchar + { + *result_r = std::string(); // add final empty field + ++ret; + break; + } + } + } + return ret; + } + + /** + * Split \a line_r into fields handling also escaped separators. + * + * \see splitFields() + * \see splitEscaped() + */ + template + unsigned splitFieldsEscaped( const C_Str & line_r, TOutputIterator result_r, const C_Str & sepchars_r = ":" ) + { + return splitEscaped( line_r, result_r, sepchars_r, true /* withEmpty */ ); + } + + //@} + + /////////////////////////////////////////////////////////////////// + /** \name Join. */ + //@{ + /** Join strings using separator \a sep_r (defaults to BLANK). */ + template + std::string join( TIterator begin, TIterator end, const C_Str & sep_r = " " ) + { + std::string res; + for ( TIterator iter = begin; iter != end; ++ iter ) + { + if ( iter != begin ) + res += sep_r; + res += asString(*iter); + } + return res; + } + + /** Join strings using separator \a sep_r (defaults to BLANK). */ + template + std::string join( const TContainer & cont_r, const C_Str & sep_r = " " ) + { return join( cont_r.begin(), cont_r.end(), sep_r ); } + + /** Join strings using separator \a sep_r, quoting or escaping the values. + * Separator defaults to BLANK. Use \ref splitEscaped to restore the + * values. + */ + template + std::string joinEscaped( TIterator begin, TIterator end, const char sep_r = ' ' ) + { + std::vector buf; + for ( TIterator iter = begin; iter != end; ++ iter ) + { + if ( iter != begin ) + buf.push_back( sep_r ); + + if ( iter->empty() ) + { + // empty string goes "" + buf.push_back( '"' ); + buf.push_back( '"' ); + } + else + { + std::string toadd( asString(*iter) ); + for_( ch, toadd.begin(), toadd.end() ) + { + switch ( *ch ) + { + case '"': + case '\'': + case '\\': + buf.push_back( '\\' ); + buf.push_back( *ch ); + break; + default: + if ( *ch == sep_r ) + buf.push_back( '\\' ); + buf.push_back( *ch ); + } + } + } + } + return std::string( buf.begin(), buf.end() ); + } + //@} + + + /////////////////////////////////////////////////////////////////// + /** \name Indent. */ + //@{ + /** Indent by string [" "] optionally wrap. + * Prints nothing for an empty string. Asserts a trainling '\n' on + * the last line. Optionally wrap lines at ' ' at a given length. + */ + inline std::ostream & printIndented( std::ostream & str, const std::string & text_r, const std::string & indent_r = " ", unsigned maxWitdh_r = 0 ) + { + if ( maxWitdh_r ) + { + if ( indent_r.size() >= maxWitdh_r ) + maxWitdh_r = 0; // nonsense: indent larger than line witdh + else + maxWitdh_r -= indent_r.size(); + } + unsigned width = 0; + for ( const char * e = text_r.c_str(), * s = e; *e; s = ++e ) + { + for ( ; *e && *e != '\n'; ++e ) ;/*searching*/ + width = e-s; + if ( maxWitdh_r && width > maxWitdh_r ) + { + // must break line + width = maxWitdh_r; + for ( e = s+width; e > s && *e != ' '; --e ) ;/*searching*/ + if ( e > s ) + width = e-s; // on a ' ', replaced by '\n' + else + e = s+width-1; // cut line; + } + str << indent_r; + str.write( s, width ); + str << "\n"; + if ( !*e ) // on '\0' + break; + } + return str; + } + /** \overload Indent by number of chars [' '] optionally wrap. */ + inline std::ostream & printIndented( std::ostream & str, const std::string & text_r, unsigned indent_r, char indentch_r = ' ', unsigned maxWitdh_r = 0 ) + { return printIndented( str, text_r, std::string( indent_r, indentch_r ), maxWitdh_r ); } + /** \overload Indent by number of chars [' '] wrap. */ + inline std::ostream & printIndented( std::ostream & str, const std::string & text_r, unsigned indent_r, unsigned maxWitdh_r, char indentch_r = ' ' ) + { return printIndented( str, text_r, std::string( indent_r, indentch_r ), maxWitdh_r ); } + + /** Prefix lines by string computed by function taking line begin/end [std::string(const char*, const char*)] + * Prints nothing for an empty string. Asserts a trainling '\n' on the last line. + */ + inline std::ostream & autoPrefix( std::ostream & str, const std::string & text_r, const function& fnc_r ) + { + for ( const char * e = text_r.c_str(); *e; ++e ) + { + const char * s = e; + for ( ; *e && *e != '\n'; ++e ) /*searching*/; + str << fnc_r( s, e ); + str.write( s, e-s ); + str << "\n"; + if ( !*e ) // on '\0' + break; + } + return str; + } + /** \overload Prefix lines by string generated by function [std::string()] */ + inline std::ostream & autoPrefix0( std::ostream & str, const std::string & text_r, function fnc_r ) + { + auto wrap = [&fnc_r]( const char*, const char* )-> std::string { + return fnc_r(); + }; + return autoPrefix( str, text_r, wrap ); + } + //@} + /////////////////////////////////////////////////////////////////// + /** \name Escape. */ + //@{ + /** + * Escape desired character \a c using a backslash. + * + * For use when printing \a c separated values, and where + * \ref joinEscaped() is too heavy. + */ + std::string escape( const C_Str & str_r, const char c = ' ' ) ZYPP_API; + + /** Escape \a next_r and append it to \a str_r using separator \a sep_r. */ + inline void appendEscaped( std::string & str_r, const C_Str & next_r, const char sep_r = ' ' ) + { + if ( ! str_r.empty() ) + str_r += sep_r; + if ( next_r.empty() ) + str_r += "\"\""; + else + str_r += escape( next_r, sep_r ); + } + + /** Return \a str_r with '\'-escaped chars occurring in \a special_r (and '\'). */ + std::string bEscape( std::string str_r, const C_Str & special_r ) ZYPP_API; + + /** Escape plain STRING \a str_r for use in a regex (not anchored by "^" or "$"). */ + std::string rxEscapeStr( std::string str_r ) ZYPP_API; + + /** Escape GLOB \a str_r for use in a regex (not anchored by "^" or "$"). */ + std::string rxEscapeGlob( std::string str_r ) ZYPP_API; + + //! \todo unsecape() + + //@} + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + /** \name Hexencode. + * Encode all characters other than [a-zA-Z0-9] as %XX. + * This includes the % character itself, which becomes %25. + */ + //@{ + /** Encode all characters other than [a-zA-Z0-9] as %XX. + * This includes the % character itself, which becomes %25. + */ + std::string hexencode( const C_Str & str_r ); + /** Decode hexencoded %XX sequences. */ + std::string hexdecode( const C_Str & str_r ); + //@} + /////////////////////////////////////////////////////////////////// + + /** \name Case conversion. */ + //@{ + /** Return lowercase version of \a s + * \todo improve + */ + std::string toLower( const std::string & s ) ZYPP_API; + std::string toLower( std::string && s ) ZYPP_API; + /** \overload */ + inline std::string toLower( const char * s ) + { return( s ? toLower( std::string(s) ) : std::string() ); } + + /** Return uppercase version of \a s + * \todo improve + */ + std::string toUpper( const std::string & s ) ZYPP_API; + std::string toUpper( std::string && s ) ZYPP_API; + /** \overload */ + inline std::string toUpper( const char * s ) + { return( s ? toUpper( std::string(s) ) : std::string() ); } + //@} + + + /** \name Case insensitive comparison. */ + //@{ + inline int compareCI( const C_Str & lhs, const C_Str & rhs ) + { return ::strcasecmp( lhs, rhs ); } + //@} + + /** \name Locate substring. */ + //@{ + /** Locate substring case sensitive. */ + inline bool contains( const C_Str & str_r, const C_Str & val_r ) + { return ::strstr( str_r, val_r ); } + /** Locate substring case insensitive. */ + inline bool containsCI( const C_Str & str_r, const C_Str & val_r ) + { return ::strcasestr( str_r, val_r ); } + //@} + + std::string stripFirstWord( std::string & line, const bool ltrim_first = true ) ZYPP_API; + + std::string stripLastWord( std::string & line, const bool rtrim_first = true ) ZYPP_API; + + /** Return stream content up to (but not returning) the next newline. + * \see \ref receiveUpTo + */ + std::string getline( std::istream & str, bool trim = false ) ZYPP_API; + + /** Return stream content up to (but not returning) the next newline. + * \see \ref receiveUpTo + */ + std::string getline( std::istream & str, const Trim trim_r ) ZYPP_API; + + /** Return stream content up to the next ocurrence of \c delim_r or EOF + * \c delim_r, if found, is always read from the stream. Whether it is + * also returned in the string depends on \c returnDelim_r. + * If the stream status is \c good, \c delim_r was found in the stream. + * If we reached EOF while looking for \c delim_r, \c eof is set; and + * also \c fail, if we did not read any data before. + */ + std::string receiveUpTo( std::istream & str, const char delim_r, bool returnDelim_r = false ); + + /////////////////////////////////////////////////////////////////// + + /** \name String prefix/suffix handling. + */ + //@{ + /** Return whether \a str_r has prefix \a prefix_r. */ + inline bool hasPrefix( const C_Str & str_r, const C_Str & prefix_r ) + { return( ::strncmp( str_r, prefix_r, prefix_r.size() ) == 0 ); } + /** \overload Case insensitive */ + inline bool hasPrefixCI( const C_Str & str_r, const C_Str & prefix_r ) + { return( ::strncasecmp( str_r, prefix_r, prefix_r.size() ) == 0 ); } + + /** Strip a \a prefix_r from \a str_r and return the resulting string. */ + inline std::string stripPrefix( const C_Str & str_r, const C_Str & prefix_r ) + { return( hasPrefix( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); } + /** \overload Case insensitive */ + inline std::string stripPrefixCI( const C_Str & str_r, const C_Str & prefix_r ) + { return( hasPrefixCI( str_r, prefix_r ) ? str_r + prefix_r.size() : str_r.c_str() ); } + + /** Return whether \a str_r has suffix \a suffix_r. */ + inline bool hasSuffix( const C_Str & str_r, const C_Str & suffix_r ) + { return( str_r.size() >= suffix_r.size() && ::strncmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); } + /** \overload Case insensitive */ + inline bool hasSuffixCI( const C_Str & str_r, const C_Str & suffix_r ) + { return( str_r.size() >= suffix_r.size() && ::strncasecmp( str_r + str_r.size() - suffix_r.size() , suffix_r, suffix_r.size() ) == 0 ); } + + /** Strip a \a suffix_r from \a str_r and return the resulting string. */ + inline std::string stripSuffix( const C_Str & str_r, const C_Str & suffix_r ) + { + if ( hasSuffix( str_r, suffix_r ) ) + return std::string( str_r, str_r.size() - suffix_r.size() ); + return str_r.c_str(); + } + /** \overload Case insensitive */ + inline std::string stripSuffixCI( const C_Str & str_r, const C_Str & suffix_r ) + { + if ( hasSuffixCI( str_r, suffix_r ) ) + return std::string( str_r, str_r.size() - suffix_r.size() ); + return str_r.c_str(); + } + + /** Return size of the common prefix of \a lhs and \a rhs. */ + inline std::string::size_type commonPrefix( const C_Str & lhs, const C_Str & rhs ) + { + const char * lp = lhs.c_str(); + const char * rp = rhs.c_str(); + std::string::size_type ret = 0; + while ( *lp == *rp && *lp != '\0' ) + { ++lp, ++rp, ++ret; } + return ret; + } + /** \overload Case insensitive */ + inline std::string::size_type commonPrefixCI( const C_Str & lhs, const C_Str & rhs ) + { + const char * lp = lhs.c_str(); + const char * rp = rhs.c_str(); + std::string::size_type ret = 0; + while ( tolower(*lp) == tolower(*rp) && *lp != '\0' ) + { ++lp, ++rp, ++ret; } + return ret; + } + + + /** alias for \ref hasPrefix */ + inline bool startsWith( const C_Str & str_r, const C_Str & prefix_r ) + { return hasPrefix( str_r, prefix_r ); } + /** \overload Case insensitive */ + inline bool startsWithCI( const C_Str & str_r, const C_Str & prefix_r ) + { return hasPrefixCI( str_r, prefix_r ); } + + /** alias for \ref hasSuffix */ + inline bool endsWith( const C_Str & str_r, const C_Str & prefix_r ) + { return hasSuffix( str_r, prefix_r ); } + /** \overload Case insensitive */ + inline bool endsWithCI( const C_Str & str_r, const C_Str & prefix_r ) + { return hasSuffixCI( str_r, prefix_r ); } + //@} + } // namespace str + /////////////////////////////////////////////////////////////////// + + // drag into zypp:: namespace + using str::asString; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_STRING_H diff --git a/zypp-core/base/StringV.cc b/zypp-core/base/StringV.cc new file mode 100644 index 0000000..3bfb606 --- /dev/null +++ b/zypp-core/base/StringV.cc @@ -0,0 +1,188 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/StringV.cc + */ +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + namespace strv + { + namespace detail + { + /** \ref split working horse for empty \a sep_r case. + * Split at /[BLANK,TAB]+/ and report no-empty words. Trim::right is + * applied to the rest of the line in case the callback aborts further + * processing. + */ + unsigned _splitSimple( std::string_view line_r, const WordConsumer& fnc_r ) + { + // callback stats + unsigned fncCall = 0; + + // NOTE: line_r is not null-terminated! + const char *const eol = line_r.data() + line_r.size(); // the '\0' + const char * searchfrom = line_r.data(); // start of the next search (moves with each cycle!) + + // Empty sep: split at /[BLANK,TAB]+/ and report no-empty words + auto isSep = []( char ch )->bool { return ch == ' '|| ch == '\t'; }; + + auto skipSep = [eol,&isSep]( const char *& ptr )->bool { + while ( ptr < eol && isSep( *ptr ) ) + ++ptr; + return ptr < eol; // whether we ended up at a new wordstart + }; + + auto skipWord = [eol,&isSep]( const char *& ptr )->void { + while ( ptr < eol && ! isSep( *ptr ) ) + ++ptr; + }; + + // For the 'last' CB argument: we must remember a word + // until we know whether another one is following + std::string_view word; + + while ( skipSep( searchfrom ) ) { + const char * wordstart = searchfrom; + // Report a previous word found + if ( ! word.empty() ) { + if ( fnc_r ) { + if ( ! fnc_r( word, fncCall, false/*more to come*/ ) ) { + // Stop searching for further matches. Final report will + // be the remaining line (right trimmed) + const char * wordend = eol; + while ( isSep( *(wordend-1) ) ) // noSep at wordstart stops loop + --wordend; + word = std::string_view( wordstart, wordend-wordstart ); + ++fncCall; + break; + } + } + ++fncCall; + } + // remember new word + ++searchfrom; + skipWord( searchfrom ); + word = std::string_view( wordstart, searchfrom-wordstart ); + } + + // finally report the last word + if ( ! word.empty() ) { + if ( fnc_r ) { + fnc_r( word, fncCall, true/*last*/ ); + } + ++fncCall; + } + + return fncCall; + } + } // namespace detail + + unsigned detail::_split( std::string_view line_r, std::string_view sep_r, Trim trim_r, WordConsumer && fnc_r ) + { + if ( sep_r.empty() ) + return _splitSimple( line_r, std::move( fnc_r ) ); + + // callback stats + bool fncStop = false; + unsigned fncCall = 0; + + using size_type = std::string_view::size_type; + size_type wordstart = 0; // start of the next string to be reported + size_type searchfrom = 0; // start of the next search for a separator + + do { // report lhs word of separator matches... + searchfrom = line_r.find( sep_r, searchfrom ); + if ( fncStop || searchfrom == line_r.npos ) { + break; + } + + // Report lhs word of the match and advance... + if ( fnc_r ) { + if ( ! fnc_r( trim( line_r.substr(wordstart,searchfrom-wordstart), trim_r ), fncCall, false/*more to come*/ ) ) + fncStop= true; // stop searching for further matches + } + ++fncCall; + + // Next wordstart is behind the separator match. + searchfrom += sep_r.size(); + wordstart = searchfrom; + } while( wordstart < line_r.size() ); + + // finally report rhs word of the last separator match (or no match) + if ( fnc_r ) { + if ( wordstart < line_r.size() ) + fnc_r( trim( line_r.substr(wordstart,line_r.size()-wordstart), trim_r ), fncCall, true/*last*/ ); + else // a final match at $ so a final empty word reported (no trim needed) + fnc_r( std::string_view( line_r.data()+line_r.size(), 0 ), fncCall, true/*last*/ ); + } + ++fncCall; + return fncCall; + } + + unsigned detail::_splitRx( std::string_view line_r, const regex & rx_r, const WordConsumer& fnc_r ) + { + // callback stats + bool fncStop = false; + unsigned fncCall = 0; + + // report lhs word of separator matches... + const char *const eol = line_r.data() + line_r.size(); // the '\0' + bool trailingNL = line_r.size() && *(eol-1) == '\n'; // line ends with NL + const char * wordstart = line_r.data(); // start of the next string to be reported + const char * searchfrom = line_r.data(); // start of the next search for a separator (moves with each cycle!) + + // Whether to match the ^ at beginning of the line or after an \n: + auto matchAtBOL = [&]() { + return searchfrom == line_r.data() || *(searchfrom-1) == '\n' ? regex::none : regex::not_bol; + }; + do { // report lhs word of separator matches... + smatch match; + if ( fncStop || ! rx_r.matches( searchfrom, match, matchAtBOL() ) ) { + break; + } + if ( trailingNL && searchfrom+match.begin(0) == eol ) + break; // don't report matches behind a trailing NL + + if ( match.end(0) == 0 && searchfrom == wordstart && searchfrom != line_r.data() ) { + // An empty(!) separator found at wordstart is ignored unless we're at the very beginning. + // If searchfrom == wordstart we just skipped over a not-empty separator. If wordstart is + // not part of a 2nd not-empty separator, we want the next separator to its right. + // Example: Rx:"b*" Str:"0b2" - at pos 2 Rx matches empty; the previous cycle found 'b' and reported the '0'. + ++searchfrom; + } else { + // Report lhs word of the match and advance... + if ( fnc_r ) { + if ( ! fnc_r( std::string_view( wordstart, searchfrom+match.begin(0) - wordstart ), fncCall, false/*more to come*/ ) ) + fncStop= true; // stop searching for further matches + } + ++fncCall; + // Next wordstart is behind the separator match. + // Next searchfrom also, but advances at least by 1. + wordstart = searchfrom+match.end(0); + searchfrom += match.end(0) ? match.end(0) : 1; + } + } while ( searchfrom <= eol ); // incl. '== eol' as there might be an (empty) match at $ + + // finally report rhs word of the last separator match (or no match) + if ( fnc_r ) { + if ( wordstart < eol ) + fnc_r( std::string_view( wordstart, eol-wordstart ), fncCall, true/*last*/ ); + else // a final match at $ so a final empty word reported + fnc_r( std::string_view( eol, 0 ), fncCall, true/*last*/ ); + } + ++fncCall; + return fncCall; + } + + } // namespace strv +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/StringV.h b/zypp-core/base/StringV.h new file mode 100644 index 0000000..b9b444e --- /dev/null +++ b/zypp-core/base/StringV.h @@ -0,0 +1,293 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/StringV.h + * c++17: std::string_view tools + */ +#ifndef ZYPP_BASE_STRINGV_H +#define ZYPP_BASE_STRINGV_H +#include +#ifdef __cpp_lib_string_view + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + namespace strv + { + using regex = str::regex; + using smatch = str::smatch; + + /** Define how to trim. */ + enum class Trim { + notrim = 0, + left = 1<<0, + right = 1<<1, + trim = (left|right), + }; + + ZYPP_DECLARE_FLAGS_AND_OPERATORS( TrimFlag, Trim ); + + /** The default blank. */ + inline constexpr std::string_view blank = " \t"; + + /** Trim \a chars_r at the beginning of \a str_r. */ + inline std::string_view ltrim( std::string_view str_r, std::string_view chars_r = blank ) + { + if ( str_r.empty() ) + return str_r; + auto pos = str_r.find_first_not_of( chars_r ); + if ( pos == str_r.npos ) + str_r.remove_prefix( str_r.size() ); + else if ( pos ) + str_r.remove_prefix( pos ); + return str_r; + } + + /** Trim \a chars_r at the end of \a str_r. */ + inline std::string_view rtrim( std::string_view str_r, std::string_view chars_r = blank ) + { + if ( str_r.empty() ) + return str_r; + auto pos = str_r.find_last_not_of( chars_r ); + if ( pos == str_r.npos ) + str_r.remove_suffix( str_r.size() ); + else if ( (pos = str_r.size()-1-pos) ) + str_r.remove_suffix( pos ); + return str_r; + } + + /** Trim \a chars_r at both sides of \a str_r. */ + inline std::string_view trim( std::string_view str_r, std::string_view chars_r = blank ) + { + if ( str_r.empty() ) + return str_r; + str_r = ltrim( std::move(str_r), chars_r ); + str_r = rtrim( std::move(str_r), chars_r ); + return str_r; + } + + /** Trim \a chars_r at \a trim_r sides of \a str_r. */ + inline std::string_view trim( std::string_view str_r, std::string_view chars_r, TrimFlag trim_r ) + { + if ( str_r.empty() || trim_r == Trim::notrim ) + return str_r; + if ( trim_r.testFlag( Trim::left ) ) + str_r = ltrim( std::move(str_r), chars_r ); + if ( trim_r.testFlag( Trim::right ) ) + str_r = rtrim( std::move(str_r), chars_r ); + return str_r; + } + /** \overload Trimming blanks at \a trim_r sides of \a str_r. */ + inline std::string_view trim( std::string_view str_r, TrimFlag trim_r ) + { return trim( std::move(str_r), blank, std::move(trim_r) ); } + + /** Return whether \a str_r has prefix \a prefix_r. */ + inline bool hasPrefix( std::string_view str_r, std::string_view prefix_r ) + { return( ::strncmp( str_r.data(), prefix_r.data(), prefix_r.size() ) == 0 ); } + + /** \overload Case insensitive */ + inline bool hasPrefixCI( std::string_view str_r, std::string_view prefix_r ) + { return( ::strncasecmp( str_r.data(), prefix_r.data(), prefix_r.size() ) == 0 ); } + + /////////////////////////////////////////////////////////////////// + namespace detail + { + /** Split* functions working horse callback. */ + using WordConsumer = std::function; + + /** \name Split* callback signatures accepted for convenience. + * + * Details may vary for specific split* functions, but basically each separator found + * in line will be enclosed by 2 words being reported. The working horse callback + * offers the \a word, the \a index of word (starting with 0) and a boolean indicating whether + * this is going to be the \a last report. + * + * A callback may optionally return a value convertible to \c bool. Returning \c false + * usually causes split* to stop looking further separators and to finish the reporting. + * + * Accepted callbacks: [bool|void] callback( [std::string_view[, unsigned[, bool]]] ) + * (or no callback at all ) + */ + //@{ + /** bool(std::string_view,unsigned,bool) */ + template + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return std::forward(fnc_r); } + /** void(std::string_view,unsigned,bool) */ + template + && std::is_invocable_r_v + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return [&fnc_r](std::string_view a1,unsigned a2,bool a3)->bool { fnc_r(a1,a2,a3); return true; }; } + + /** bool(std::string_view,unsigned) */ + template + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return [&fnc_r](std::string_view a1,unsigned a2,bool)->bool { return fnc_r(a1,a2); }; } + /** void(std::string_view,unsigned) */ + template + && std::is_invocable_r_v + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return [&fnc_r](std::string_view a1,unsigned a2,bool)->bool { fnc_r(a1,a2); return true; }; } + + /** bool(std::string_view) */ + template + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return [&fnc_r](std::string_view a1,unsigned,bool)->bool { return fnc_r(a1); }; } + /** void(std::string_view) */ + template + && std::is_invocable_r_v + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return [&fnc_r](std::string_view a1,unsigned,bool)->bool { fnc_r(a1); return true; }; } + + /** bool() */ + template + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return [&fnc_r](std::string_view,unsigned,bool)->bool { return fnc_r(); }; } + /** void() */ + template + && std::is_invocable_r_v + , bool> = true> + WordConsumer wordConsumer( Callable && fnc_r ) + { return [&fnc_r](std::string_view,unsigned,bool)->bool { fnc_r(); return true; }; } + //@} + + /** \ref split working horse */ + unsigned _split( std::string_view line_r, std::string_view sep_r, Trim trim_r, WordConsumer && fnc_r ) ZYPP_API; + + /** \ref splitRx working horse */ + unsigned _splitRx(std::string_view line_r, const regex & rx_r, const WordConsumer& fnc_r ); + } // namespace detail + /////////////////////////////////////////////////////////////////// + + /** Split \a line_r into words separated by the regular expression \a rx_r and invoke \a fnc_r with each word. + * + * Each separator match found in \a line_r will be enclosed by 2 words being reported. + * Words may be empty if the separator match is located at the beginning or at the end + * of \a line_r, or if there are consecutive separator match occurrences. + * + * Accepted callbacks: [bool|void]( [std::string_view[, unsigned[, bool]]] ) + * (or no callback at all) + * + * A callback may take the \a word, the \a index of word (starting with 0) and a boolean + * indicating whether this is going to be the \a last report. + * + * A callback may optionally return a value convertible to \c bool. Returning \c false + * causes split to stop looking further separators. The final report will contain the + * remaining part of the \a line_r then. + * + * If the separator does not occur on the line the whole string is reported. + * + * \returns the number of words reported. + */ + template + unsigned splitRx( std::string_view line_r, const regex & rx_r, Callable && fnc_r = Callable() ) + { return detail::_splitRx( line_r, rx_r, detail::wordConsumer( std::forward(fnc_r) ) ); } + + + /** Split \a line_r into words separated by \a sep_r and invoke \a fnc_r with each word. + * + * - If \a sep_r is not empty, each separator found in \a line_r will be enclosed by 2 + * words being reported. Words may be empty if the separator is located at the beginning + * or the end of \a line_r or if there are consecutive occurrences. + * + * - If \a sep_r is unspecified or empty, it splits on whitespace /[BLANK,TAB]+/. In this + * case only the (not empty) words found on the line are reported (trimmed). + * + * The optional \a trim_r argument tells whether whitespace around the words found + * should be trimmed before reporting them. The default is not to trim. + * + * Accepted callbacks: [bool|void]( [std::string_view[, unsigned[, bool]]] ) + * (or no callback at all) + * + * A callback may take the \a word, the \a index of word (starting with 0) and a boolean + * indicating whether this is going to be the \a last report. + * + * A callback may optionally return a value convertible to \c bool. Returning \c false + * causes split to stop looking further separators. The final report will contain the + * remaining part of the \a line_r then. + * + * If the separator does not occur on the line the whole string is reported. + * + * \returns the number of words reported. + * + * \code + * str = "" + * + * split( str, fnc ); + * // [] + * + * split( str, " ", fnc ); + * // [''] + * + * + * str = " " + * + * split( str, fnc ); + * // [] + * + * split( str, " ", fnc ); + * // ['', ''] + * + * + * str = " 1 2 3 4 5 "; + * + * split( str, fnc ); + * // ['1', '2', '3', '4', '5'] + * + * split( str, " ", fnc ); + * // ['', '1', '2', '3', '4', '5', ''] + * + * split( str, " 2", fnc ); + * // [' 1', ' 3 4 5 '] + * + * split( str, " 2", Trim::all, fnc ); + * // ['1', '3 4 5'] + * \endcode + */ + template + unsigned split( std::string_view line_r, std::string_view sep_r, Trim trim_r, Callable && fnc_r = Callable() ) + { return detail::_split( line_r, sep_r, trim_r, detail::wordConsumer( std::forward(fnc_r) ) ); } + + /** \overload Split at \a sep_r and Trim::notrim */ + template + inline unsigned split( std::string_view line_r, std::string_view sep_r, Callable && fnc_r = Callable() ) + { return detail::_split( line_r, sep_r, Trim::notrim, detail::wordConsumer( std::forward(fnc_r) ) ); } + + /** \overload Split at whitespace */ + template + inline unsigned split( std::string_view line_r, Callable && fnc_r = Callable() ) + { return detail::_split( line_r, std::string_view(), Trim::notrim, detail::wordConsumer( std::forward(fnc_r) ) ); } + + inline std::string_view asStringView( const char * t ) + { return t == nullptr ? std::string_view() : t; } + + } // namespace strv +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // __cpp_lib_string_view +#endif // ZYPP_BASE_STRINGV_H diff --git a/zypp-core/base/Unit.cc b/zypp-core/base/Unit.cc new file mode 100644 index 0000000..cb60338 --- /dev/null +++ b/zypp-core/base/Unit.cc @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Unit.cc + * +*/ +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + std::string Unit::form( double val_r, + const std::string & symbol_r, + unsigned field_width_r, + unsigned unit_width_r, + unsigned prec_r ) + { + std::string ret = str::form( "%*.*f", field_width_r, prec_r, val_r ); + if ( unit_width_r ) + { + ret += str::form( " %*s", unit_width_r, symbol_r.c_str() ); + } + return ret; + } + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/base/Unit.h b/zypp-core/base/Unit.h new file mode 100644 index 0000000..b26deff --- /dev/null +++ b/zypp-core/base/Unit.h @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Unit.h + * +*/ +#ifndef ZYPP_BASE_UNIT_H +#define ZYPP_BASE_UNIT_H + +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Unit + // + /** Simple handling of Units. + * + * Unit stores factor and symbol, and a precision value for printing. + * \ref form builds a string from a value according to the format + * specification. + * \code + * static const Unit B( 1, "B", 0 ); + * static const Unit K( 1024, "K", 1 ); + * static const Unit M( 1048576, "M", 1 ); + * static const Unit G( 1073741824, "G", 2 ); + * static const Unit T( 1099511627776, "T", 3 ); + * \endcode + */ + class ZYPP_API Unit + { + public: + using ValueType = long long; + + /** Default ctor */ + Unit() + : _factor( 1 ) + , _prec( 0 ) + {} + + /** ctor */ + Unit( ValueType factor_r, std::string symbol_r, unsigned prec_r ) + : _factor( factor_r ) + , _symbol(std::move( symbol_r )) + , _prec( prec_r ) + {} + + ValueType factor() const + { return _factor; } + + const std::string & symbol() const + { return _symbol; } + + unsigned prec() const + { return _prec; } + + /** Build string representation of \a val_r. */ + std::string form( ValueType val_r, + unsigned field_width_r = 0, + unsigned unit_width_r = 1 ) const + { return form( val_r, field_width_r, unit_width_r, _prec ); } + + std::string form( ValueType val_r, + unsigned field_width_r, + unsigned unit_width_r, + unsigned prec_r ) const + { return form( double(val_r)/_factor, _symbol, + field_width_r, unit_width_r, prec_r ); } + + + static std::string form( double val_r, + const std::string & symbol_r, + unsigned field_width_r, + unsigned unit_width_r, + unsigned prec_r ); + + private: + ValueType _factor; + std::string _symbol; + unsigned _prec; + }; + /////////////////////////////////////////////////////////////////// + + + ///////////////////////////////////////////////////////////////// + } // namespace base + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_UNIT_H diff --git a/zypp-core/base/UserRequestException b/zypp-core/base/UserRequestException new file mode 100644 index 0000000..32bdd8f --- /dev/null +++ b/zypp-core/base/UserRequestException @@ -0,0 +1 @@ +#include "userrequestexception.h" diff --git a/zypp-core/base/Xml.cc b/zypp-core/base/Xml.cc new file mode 100644 index 0000000..3b186c5 --- /dev/null +++ b/zypp-core/base/Xml.cc @@ -0,0 +1,20 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Xml.cc + * +*/ +#include "Xml.h" + +namespace zypp +{ + namespace xmlout + { + constexpr Node::OptionalContentType Node::optionalContent; + } +} diff --git a/zypp-core/base/Xml.h b/zypp-core/base/Xml.h new file mode 100644 index 0000000..949edf1 --- /dev/null +++ b/zypp-core/base/Xml.h @@ -0,0 +1,225 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Xml.h + * +*/ +#ifndef ZYPP_BASE_XML_H +#define ZYPP_BASE_XML_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace xmlout + { + using xml::escape; + using xml::unescape; + + /** \relates NodeAttr NODE ATTRIBUTE representation of types [asString] */ + template + std::string asXmlNodeAttr( const Tp & val_r ) + { return asString( val_r ); } + + /////////////////////////////////////////////////////////////////// + /// \class NodeAttr + /// \brief (Key, Value) string pair of XML node attributes + struct NodeAttr : public std::pair + { + using Pair = std::pair; + + template + NodeAttr( std::string key_r, const Tp & val_r ) + : Pair( std::move(key_r), asXmlNodeAttr(val_r) ) + {} + + NodeAttr( std::string key_r, std::string val_r ) + : Pair( std::move(key_r), std::move(val_r) ) + {} + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class Node + /// \brief RAII writing a nodes start/end tag + /// \code + /// { + /// Node node( std::cout, "node", { "attr", "val" } ); // + /// *node << "write nodes body...." + /// } // + /// \endcode + /// \note If the \ref optionalContent flag is passed to the \c ctor, the start + /// node is kept open, until the first call to \ref operator*. The start node + /// is closed before returning the stream. + /// \code + /// { + /// Node node( std::cout, "node", Node::optionalContent, { "attr", "val" } ); + /// // + /// { + /// Node node( std::cout, "node", Node::optionalContent, { "attr", "val" } ); + /// // write nodes body... + /// } // + /// \endcode + /// + /// \note If the nodename is empty or starts with an \c !, a comment is written. + /// + struct Node + { + NON_COPYABLE_BUT_MOVE( Node ); + using Attr = NodeAttr; + + struct OptionalContentType {}; ///< Ctor arg type + static constexpr OptionalContentType optionalContent = OptionalContentType(); + + /** Ctor taking nodename and attribute list */ + Node( std::ostream & out_r, std::string name_r, const std::initializer_list & attrs_r = {} ) + : _out( out_r ), _name( std::move(name_r) ), _hasContent( true ) + { printStart( attrs_r ); } + + /** Convenience ctor for one attribute pair */ + Node( std::ostream & out_r, std::string name_r, Attr attr_r ) + : Node( out_r, std::move(name_r), { std::move(attr_r) } ) + {} + + /** Optional content ctor taking nodename and attribute list */ + Node( std::ostream & out_r, std::string name_r, OptionalContentType, const std::initializer_list & attrs_r = {} ) + : _out( out_r ), _name( std::move(name_r) ), _hasContent( false ) + { printStart( attrs_r ); } + + /** Optional content Convenience ctor for one attribute pair */ + Node( std::ostream & out_r, std::string name_r, OptionalContentType, Attr attr_r ) + : Node( out_r, std::move(name_r), optionalContent, { std::move(attr_r) } ) + {} + + /** Dtor wrting end tag */ + ~Node() + { + if ( isComment() ) + _out.get() << "-->"; + else + { + if ( _hasContent ) + _out.get() << ""; + else + _out.get() << "/>"; + } + } + + /** Exception type thrown if attributes are added to a closed start node. */ + struct HasContentException{}; + + /** Add additional attributes (requires OptionalContentType) + * \throw HasContentException If start node is already closed + */ + Node & addAttr( const std::initializer_list & attrs_r = {} ) + { + if ( _hasContent ) + throw HasContentException(); + printAttr( attrs_r ); + return *this; + } + + /** \overload for one */ + Node & addAttr( const Attr & attr_r ) + { return addAttr( { attr_r } ); } + + + /** Return the output stream */ + std::ostream & operator*() + { + if ( ! _hasContent ) + { + _hasContent = true; + if ( isComment() ) + _out.get() << "|"; + else + _out.get() << ">"; + } + return _out; + } + + private: + void printStart( const std::initializer_list & attrs_r ) + { + if ( _name.empty() || _name[0] == '!' ) + { + _out.get() << " empty line sep. header and body + + addRawHeader( data ); + + } while ( true ); + + + // check for content-length header + std::optional cLen; + { + const auto &contentLen = getHeaderNT( zypp::PluginFrame::contentLengthHeader(), std::string() ); + if ( !contentLen.empty() ) { + cLen = zyppng::str::safe_strtonum(contentLen); + if ( !cLen ) { + ERR << "Received malformed message from peer: Invalid value for " << zypp::PluginFrame::contentLengthHeader() << ":" << contentLen << std::endl; + ZYPP_THROW( PluginFrameException( "Invalid value for content-length." ) ); + } + + // do not keep the header, we regenerate it again when writing the frame anyway + clearHeader( zypp::PluginFrame::contentLengthHeader() ); + } + + } + + // data + if ( cLen ) { + _body.resize ( (*cLen)+1, '\0' ); + stream_r.read ( _body.data(), (*cLen)+1 ); + + if ( ! stream_r.good() ) + ZYPP_THROW( PluginFrameException( "Missing data in stream" ) ); + if ( _body.back() != '\0' ) + ZYPP_THROW( PluginFrameException( "Missing NUL after body" ) ); + + _body.pop_back (); // get rid of \0 + + } else { + const auto &data = str::receiveUpTo( stream_r, '\0' ); + _body = ByteArray( data.c_str(), data.size() ); + if ( ! stream_r.good() ) + ZYPP_THROW( PluginFrameException( "Missing NUL after body" ) ); + } + } + + std::ostream & PluginFrame::Impl::writeTo( std::ostream & stream_r ) const + { + //DBG << "Write " << *this << " to " << stream_r << endl; + if ( ! stream_r ) + ZYPP_THROW( PluginFrameException( "Bad Stream" ) ); + + // command + stream_r << _command << "\n"; + + // STOMP recommends sending a content-length header + stream_r << contentLengthHeader() << ':' << str::numstring( _body.size() ) << "\n"; + + // header + for_( it, _header.begin(), _header.end() ) + stream_r << escapeHeader(it->first) << ':' << escapeHeader(it->second) << "\n"; + + // header end + stream_r << "\n"; + + // body + stream_r.write( _body.data(), _body.size() ); + + // body end + stream_r << '\0'; + stream_r.flush(); + + if ( ! stream_r ) + ZYPP_THROW( PluginFrameException( "Write error" ) ); + return stream_r; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PluginFrame + // + /////////////////////////////////////////////////////////////////// + + const std::string & PluginFrame::ackCommand() + { + static std::string _val( "ACK" ); + return _val; + } + + const std::string & PluginFrame::errorCommand() + { + static std::string _val( "ERROR" ); + return _val; + } + + const std::string & PluginFrame::enomethodCommand() + { + static std::string _val( "_ENOMETHOD" ); + return _val; + } + + const std::string &PluginFrame::contentLengthHeader() + { + static std::string _val("content-length"); + return _val; + } + + PluginFrame::PluginFrame() + : _pimpl( Impl::nullimpl() ) + {} + + PluginFrame::PluginFrame( const std::string & command_r ) + : _pimpl( new Impl( command_r ) ) + {} + + PluginFrame::PluginFrame(const std::string & command_r, std::string body_r ) + : _pimpl( new Impl( command_r, ByteArray(body_r) ) ) + {} + + PluginFrame::PluginFrame(const std::string & command_r, ByteArray body_r ) + : _pimpl( new Impl( command_r, std::move(body_r) ) ) + {} + + PluginFrame::PluginFrame( const std::string & command_r, HeaderInitializerList contents_r ) + : _pimpl( new Impl( command_r, contents_r ) ) + {} + + PluginFrame::PluginFrame(const std::string & command_r, ByteArray body_r, HeaderInitializerList contents_r ) + : _pimpl( new Impl( command_r, std::move(body_r), contents_r ) ) + {} + + PluginFrame::PluginFrame( std::istream & stream_r ) + : _pimpl( new Impl( stream_r ) ) + {} + + bool PluginFrame::empty() const + { return _pimpl->empty(); } + + const std::string & PluginFrame::command() const + { return _pimpl->command(); } + + void PluginFrame::setCommand( const std::string & command_r ) + { _pimpl->setCommand( command_r ); } + + const ByteArray &PluginFrame::body() const + { return _pimpl->body(); } + + ByteArray &PluginFrame::bodyRef() + { return _pimpl->bodyRef(); } + + void PluginFrame::setBody( const std::string & body_r ) + { _pimpl->setBody( ByteArray(body_r.data(), body_r.size()) ); } + + void PluginFrame::setBody( const ByteArray & body_r ) + { _pimpl->setBody( ByteArray(body_r) ); } + + void PluginFrame::setBody( ByteArray && body_r ) + { _pimpl->setBody( std::move(body_r) ); } + + std::ostream & PluginFrame::writeTo( std::ostream & stream_r ) const + { return _pimpl->writeTo( stream_r ); } + + PluginFrame::HeaderList & PluginFrame::headerList() + { return _pimpl->headerList(); } + + const PluginFrame::HeaderList & PluginFrame::headerList() const + { return _pimpl->headerList(); } + + const std::string & PluginFrame::getHeader( const std::string & key_r ) const + { return _pimpl->getHeader( key_r ); } + + const std::string & PluginFrame::getHeader( const std::string & key_r, const std::string & default_r ) const + { return _pimpl->getHeader( key_r, default_r ); } + + const std::string & PluginFrame::getHeaderNT( const std::string & key_r, const std::string & default_r ) const + { return _pimpl->getHeaderNT( key_r, default_r ); } + + void PluginFrame::setHeader( const std::string & key_r, const std::string & value_r ) + { _pimpl->setHeader( key_r, value_r ); } + + void PluginFrame::addHeader( const std::string & key_r, const std::string & value_r ) + { _pimpl->addHeader( key_r, value_r ); } + + void PluginFrame::addHeader( HeaderInitializerList contents_r ) + { _pimpl->addHeader( contents_r ); } + + void PluginFrame::addRawHeader( const ByteArray &header ) + { + _pimpl->addRawHeader( header.asStringView() ); + } + + void PluginFrame::clearHeader( const std::string & key_r ) + { _pimpl->clearHeader( key_r ); } + + /////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const PluginFrame & obj ) + { return str << *obj._pimpl; } + + bool operator==( const PluginFrame & lhs, const PluginFrame & rhs ) + { + return ( lhs._pimpl == rhs._pimpl ) + || (( lhs.command() == rhs.command() ) && ( lhs.headerList() == rhs.headerList() ) && ( lhs.body() == rhs.body() )); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/rpc/PluginFrame.h b/zypp-core/rpc/PluginFrame.h new file mode 100644 index 0000000..7625147 --- /dev/null +++ b/zypp-core/rpc/PluginFrame.h @@ -0,0 +1,297 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginFrame.h + * +*/ +#ifndef ZYPP_CORE_PLUGINFRAME_H +#define ZYPP_CORE_PLUGINFRAME_H + +#include +#include +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Command frame for communication with \ref PluginScript + * + * \code + * COMMAND + * key:value header lines + * + * multiline body separated from header + * by an empty line and terminated by NUL. + * ^@ + * \endcode + * + * \see PluginScript + */ + class ZYPP_API PluginFrame + { + friend std::ostream & operator<<( std::ostream & str, const PluginFrame & obj ); + friend bool operator==( const PluginFrame & lhs, const PluginFrame & rhs ); + + using HeaderInitializerList = const std::initializer_list> &; + + public: + /** "ACK" command. */ + static const std::string & ackCommand(); + /** "ERROR" command. */ + static const std::string & errorCommand(); + /** "_ENOMETHOD" command. */ + static const std::string & enomethodCommand(); + /** "content-lenght" header name */ + static const std::string &contentLengthHeader(); + + public: + /** Default exception type */ + using Exception = PluginFrameException; + + /** Default ctor (empty frame) */ + PluginFrame(); + + /** Ctor taking the command + * \throw PluginFrameException If \ref setCommand throws + */ + PluginFrame( const std::string & command_r ); + + /** Ctor taking command and body + * \throw PluginFrameException If \ref setCommand throws + */ + PluginFrame(const std::string & command_r, std::string body_r ); + + /** Ctor taking command and body + * \throw PluginFrameException If \ref setCommand throws + */ + PluginFrame(const std::string & command_r, ByteArray body_r ); + + /** Ctor taking the command and a HeaderInitializerList + * \throw PluginFrameException If \ref setCommand throws + */ + PluginFrame( const std::string & command_r, HeaderInitializerList contents_r ); + + /** Ctor taking command, body and a HeaderInitializerList + * \throw PluginFrameException If \ref setCommand throws + */ + PluginFrame(const std::string & command_r, ByteArray body_r, HeaderInitializerList contents_r ); + + /** Ctor reading frame data from a stream + * \throw PluginFrameException On error reading from stream + * \throw PluginFrameException On error parsing the data + */ + PluginFrame( std::istream & stream_r ); + + public: + /** Whether this is an empty frame. */ + bool empty() const; + + /** Evaluate in a boolean context (not an empty frame) */ + explicit operator bool() const + { return !empty(); } + + public: + /** Return the frame command. */ + const std::string & command() const; + + /** Set the frame command + * \throw PluginFrameException If illegal command string (e.g. multiline) + */ + void setCommand( const std::string & command_r ); + + /** Convenience to identify an ACK command. */ + bool isAckCommand() const + { return command() == ackCommand(); } + + /** Convenience to identify an ERROR command. */ + bool isErrorCommand() const + {return command() == errorCommand(); } + + /** Convenience to identify an _ENOMETHOD command. */ + bool isEnomethodCommand() const + {return command() == enomethodCommand(); } + + /** Return the frame body. */ + const ByteArray & body() const; + + /** Return a reference to the frame body. + * This may avoid creating unnecessary copies if you + * want to manipulate large body data. + * \code + * ByteArray tmp; + * frame.bodyRef().swap( tmp ); + * \endcode + */ + ByteArray & bodyRef(); + + /** Set the frame body */ + void setBody( const std::string & body_r ); + + /** Set the frame body */ + void setBody( const ByteArray & body_r ); + + /** Set the frame body */ + void setBody( ByteArray && body_r ); + + public: + /** The header list */ + using HeaderList = std::multimap; + + /** Header list iterator */ + using HeaderListIterator = HeaderList::const_iterator; + + private: + /** Modifyalble header list for internal use only. */ + HeaderList & headerList(); + + public: + /** The header list. */ + const HeaderList & headerList() const; + + /** Whether header list is empty. */ + bool headerEmpty() const + { return headerList().empty(); } + + /** Return size of the header list. */ + unsigned headerSize() const + { return headerList().size(); } + + /** Return iterator pointing to the 1st header (or \ref headerEnd) */ + HeaderListIterator headerBegin() const + { return headerList().begin(); } + + /** Return iterator pointing behind the last header. */ + HeaderListIterator headerEnd() const + { return headerList().end(); } + + /** Clear the list of headers. */ + void headerClear() + { headerList().clear(); } + + + /** Whether the header list contains at least one entry for \c key_r. */ + bool hasKey( const std::string & key_r ) const + { return ! keyEmpty( key_r ); } + + /** \overload */ + bool keyEmpty( const std::string & key_r ) const + { return headerList().find( key_r ) == headerEnd(); } + + /** Return number of header entries for \c key_r. */ + bool keySize( const std::string & key_r ) const + { return headerList().count( key_r ); } + + /** Return iterator pointing to the 1st header for \c key_r (or \ref keyEnd(key_r)) */ + HeaderListIterator keyBegin( const std::string & key_r ) const + { return headerList().lower_bound( key_r ); } + + /** Return iterator pointing behind the last header for \c key_r.*/ + HeaderListIterator keyEnd( const std::string & key_r ) const + { return headerList().upper_bound( key_r ); } + + + /** Return header value for \c key_r. + * \throw PluginFrameException If no header for key_r exists. + * \throw PluginFrameException If multiple header for key_r exist. + */ + const std::string & getHeader( const std::string & key_r ) const; + + /** Return header value for \c key_r or \c default_r if it does not exist. + * \throw PluginFrameException If multiple header for key_r exist. + */ + const std::string & getHeader( const std::string & key_r, const std::string & default_r ) const; + + /** Not throwing version returing one of the matching header values or \c default_r string. */ + const std::string & getHeaderNT( const std::string & key_r, const std::string & default_r = std::string() ) const; + + /** Set header for \c key_r removing all other occurrences of \c key_r. + * \throw PluginFrameException If key contains illegal chars (\c NL or \c :) + * \throw PluginFrameException If value contains illegal chars (\c NL) + */ + void setHeader( const std::string & key_r, const std::string & value_r = std::string() ); + + /** Set a new header list + * \throw PluginFrameException If key contains illegal chars (\c NL or \c :) + * \throw PluginFrameException If value contains illegal chars (\c NL) + */ + void setHeader( HeaderInitializerList contents_r ) + { headerList().clear(); addHeader( contents_r ); } + + /** Add header for \c key_r leaving already existing headers for \c key_r unchanged. + * \throw PluginFrameException If key contains illegal chars (\c NL or \c :) + * \throw PluginFrameException If value contains illegal chars (\c NL) + */ + void addHeader( const std::string & key_r, const std::string & value_r = std::string() ); + /** \overload taking an initializer_list */ + void addHeader( HeaderInitializerList contents_r ); + + /*! + * Parses the header line in \a header and if it is valid adds it to the internal + * header list. + */ + void addRawHeader ( const ByteArray &header ); + + /** Remove all headers for \c key_r. */ + void clearHeader( const std::string & key_r ); + + public: + /** Write frame to stream + * \throw PluginFrameException On error writing to stream + */ + std::ostream & writeTo( std::ostream & stream_r ) const; + + /** \overload Static version. */ + static std::ostream & writeTo( std::ostream & stream_r, const PluginFrame & frame_r ) + { return frame_r.writeTo( stream_r ); } + + /** Read frame from stream + * \throw PluginFrameException If \ref PluginFrame(std::istream&) throws + */ + std::istream & readFrom( std::istream & stream_r ) + { *this = PluginFrame( stream_r ); return stream_r; } + + /** \overload Static version. */ + static std::istream & readFrom( std::istream & stream_r, PluginFrame & frame_r ) + { frame_r = PluginFrame( stream_r ); return stream_r; } + + public: + /** Implementation */ + struct Impl; + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + + /** \relates PluginFrame Stream output for logging */ + std::ostream & operator<<( std::ostream & str, const PluginFrame & obj ); + + /** \relates PluginFrame Stream output writing all data for logging (no throw) */ + inline std::ostream & dumpOn( std::ostream & str, const PluginFrame & obj ) + { if ( str ) try { PluginFrame::writeTo( str, obj ); } catch(...){}; return str; } + + /** \relates PluginFrame Construct from stream. */ + inline std::istream & operator>>( std::istream & str, PluginFrame & obj ) + { return PluginFrame::readFrom( str, obj ); } + + /** \relates PluginFrame Comparison based on content. */ + bool operator==( const PluginFrame & lhs, const PluginFrame & rhs ); + + /** \relates PluginFrame Comparison based on content. */ + inline bool operator!=( const PluginFrame & lhs, const PluginFrame & rhs ) + { return( ! operator==( lhs, rhs ) ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CORE_PLUGINFRAME_H diff --git a/zypp-core/rpc/PluginFrameException.cc b/zypp-core/rpc/PluginFrameException.cc new file mode 100644 index 0000000..a7b40be --- /dev/null +++ b/zypp-core/rpc/PluginFrameException.cc @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginFrameException.cc + * +*/ +#include +//#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + PluginFrameException::PluginFrameException() + : Exception( "PluginFrameException" ) + {} + + PluginFrameException::PluginFrameException( const std::string & msg_r ) + : Exception( msg_r ) + {} + + PluginFrameException::PluginFrameException( const std::string & msg_r, const std::string & hist_r ) + : Exception( msg_r ) + { addHistory( hist_r ); } + + PluginFrameException::~PluginFrameException() throw() + {}; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/rpc/PluginFrameException.h b/zypp-core/rpc/PluginFrameException.h new file mode 100644 index 0000000..afabd20 --- /dev/null +++ b/zypp-core/rpc/PluginFrameException.h @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginFrameException.h + * +*/ +#ifndef ZYPP_CORE_PLUGINFRAMEEXCEPTION_H +#define ZYPP_CORE_PLUGINFRAMEEXCEPTION_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PluginFrameException + // + /** Base class for \ref PluginFrame \ref Exception. */ + class ZYPP_API PluginFrameException : public Exception + { + public: + PluginFrameException(); + PluginFrameException( const std::string & msg_r ); + PluginFrameException( const std::string & msg_r, const std::string & hist_r ); + ~PluginFrameException() throw() override; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CORE_PLUGINFRAMEEXCEPTION_H diff --git a/zypp-core/ui/ProgressData b/zypp-core/ui/ProgressData new file mode 100644 index 0000000..9285d77 --- /dev/null +++ b/zypp-core/ui/ProgressData @@ -0,0 +1 @@ +#include "progressdata.h" diff --git a/zypp-core/ui/progressdata.cc b/zypp-core/ui/progressdata.cc new file mode 100644 index 0000000..d7fbc9a --- /dev/null +++ b/zypp-core/ui/progressdata.cc @@ -0,0 +1,159 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ProgressData.cc + * +*/ +#include +#include +#include +#include + +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "Progress" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ProgressData::report + // METHOD TYPE : void + // + bool ProgressData::report() + { + bool forceReport { _d->_state != RUN }; // bsc#1206949: force reporting the INIT||END states + + static constexpr std::chrono::milliseconds minfequency { 1000 }; + static constexpr std::chrono::milliseconds maxfequency { 100 }; + Data::TimePoint now { Data::TimePoint::clock::now() }; + Data::TimePoint::duration elapsed { now - _d->_last_send }; + if ( not forceReport && elapsed < maxfequency ) { + return true; // skip report, continue per default + } + + // compute value and check whether to report it + if ( hasRange() ) + { + value_type newVal = _d->_val * 100 / ( _d->_max - _d->_min ); + + if ( elapsed > minfequency + || newVal != _d->_last_val + || forceReport ) + { + _d->_last_val = newVal; + _d->_last_send = now; + } + else + return true; // skip report, continue per default + } + else + { + if ( elapsed > minfequency || forceReport ) + { + _d->_last_val = _d->_val; + _d->_last_send = now; + } + else + return true; // skip report, continue per default + } + + // now send report + if ( _d->_state == INIT ) + { + _d->_state = RUN; + DBG << str::form( "{#%u|%s} START", numericId(), name().c_str() ) << endl; + } + // XXX << str::form( "{#%u|%s}(%lld%s)", numericId(), name().c_str(), _d->_last_val, ( hasRange() ? "%" : "!" ) ) << endl; + + if ( _d->_receiver ) + { + if ( ! _d->_receiver( *this ) ) + { + if ( _d->_state != END ) + { + WAR << "User request to ABORT pending action. " + << str::form( "{#%u|%s}(%lld%s)", numericId(), name().c_str(), + _d->_last_val, ( hasRange() ? "%" : "!" ) ) << endl; + } + return false; // aborted by user + } + } + + if ( _d->_state == END ) + { + DBG << str::form( "{#%u|%s} END", numericId(), name().c_str() ) << endl; + } + + return true; // continue per default + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ProgressData & obj ) + { + if ( obj.hasRange() ) + { + return str << str::form( "{%u|%s}[%lld,%lld](%lld)%lld%%)", + obj.numericId(), obj.name().c_str(), + obj.min(), obj.max(), obj.val(), obj.reportValue() ); + } + return str << str::form( "{%u|%s}[-,-](%lld)", + obj.numericId(), obj.name().c_str(), + obj.val() ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + ProgressData makeProgressData( const InputStream & input_r ) + { + ProgressData ret; + ret.name( input_r.name() ); + if ( input_r.size() > 0 ) + ret.range( input_r.size() ); + return ret; + } + + CombinedProgressData::CombinedProgressData( ProgressData &pd, + ProgressData::value_type weight ) + : _weight(weight), + _last_value(0), + _pd(pd) + { + + } + + bool CombinedProgressData::operator()( const ProgressData &progress ) + { + if ( progress.reportAlive() || _pd.reportAlive() || ( _weight == 0 ) ) + return _pd.tick(); + + // factor [0,1] of increase in subtask ( ie: before 0,2 now 0.5 ) + float increment = ((float)(progress.val() - _last_value))/(progress.max() - progress.min()); + // how much the subtask affects the parent task ie: 0,1 + float parent_factor = (float)(_weight)/(_pd.max() - _pd.min()); + // real increment of the parent task + float real_increment = parent_factor*increment; + _last_value = progress.val(); + return _pd.incr( (ProgressData::value_type)( (_pd.max()-_pd.min()) * real_increment) ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-core/ui/progressdata.h b/zypp-core/ui/progressdata.h new file mode 100644 index 0000000..e54475e --- /dev/null +++ b/zypp-core/ui/progressdata.h @@ -0,0 +1,428 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-core/ui/ProgressData + * +*/ +#ifndef ZYPP_CORE_UI_PROGRESSDATA_H +#define ZYPP_CORE_UI_PROGRESSDATA_H + +#include +#include +#include + +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ProgressData + // + /** Maintain [min,max] and counter (value) for progress counting. + * + * This class should provide everything the producer of progress data + * needs. As a convention, a zero sizes range indicates that you are just + * able to send 'still alive' triggers. + * + * The counter should be updated in reasonable intervals. Don't mind whether + * the counter value actually increased or not. ProgressData will recognize + * your triggers and knows when to actually send notification to a consumer. + * + * Each ProgressData object provides a unique numeric id and you may assign + * it a name. + * + * \code + * bool exampleReceiver( const ProgressData & ticks_r ) + * { + * DBG << "got ->" << ticks_r.reportValue() << " (" << ticks_r.val() << ")" << endl; + * return( ticks_r.val() <= 100 ); // Abort if ( val > 100 ) + * } + * + * class Example + * { + * public: + * + * Example( const ProgressData::ReceiverFnc & fnc_r = ProgressData::ReceiverFnc() ) + * : _fnc( fnc_r ) + * {} + * + * void SendTo( const ProgressData::ReceiverFnc & fnc_r ) + * { _fnc = fnc_r; } + * + * public: + * + * void action() + * { + * ProgressData tics( 10 ); // Expect range 0 -> 10 + * tics.name( "test ticks" ); // Some arbitrary name + * tics.sendTo( _fnc ); // Send reports to _fnc + * tics.toMin(); // start sending min (0) + * + * for ( int i = 0; i < 10; ++i ) + * { + * if ( ! tics.set( i ) ) + * return; // user requested abort + * } + * + * tics.toMax(); // take care 100% are reported on success + * } + * + * void action2() + * { + * ProgressData tics; // Just send 'still alive' messages + * tics.name( "test ticks" ); // Some arbitrary name + * tics.sendTo( _fnc ); // Send reports to _fnc + * tics.toMin(); // start sending min (0) + * + * for ( int i = 0; i < 10; ++i ) + * { + * if ( ! tics.set( i ) ) + * return; // user requested abort + * } + * + * tics.toMax(); // + * } + * + * private: + * ProgressData::ReceiverFnc _fnc; + * }; + * \endcode + * \code + * Example t( exampleReceiver ); + * DBG << "Reporting %:" << endl; + * t.action(); + * DBG << "Reporting 'still alive':" << endl; + * t.action2(); + * \endcode + * \code + * Reporting %: + * got ->0 (0) + * got ->10 (1) + * got ->20 (2) + * got ->30 (3) + * got ->40 (4) + * got ->50 (5) + * got ->60 (6) + * got ->70 (7) + * got ->80 (8) + * got ->90 (9) + * got ->100 (10) + * got ->100 (10) + * Reporting 'still alive': + * got ->-1 (0) + * got ->-1 (9) + * \endcode + * + * The different ammount of triggers is due to different rules for sending + * percent or 'still alive' messages. + */ + class ZYPP_API ProgressData : public base::ProvideNumericId + { + public: + using value_type = long long; + /** Most simple version of progress reporting + * The percentage in most cases. Sometimes just keepalive. + * \p sender ProgressData object who sends the progress info + * \p + */ + using ReceiverFnc = function; + + private: + enum State { INIT, RUN, END }; + + class Data + { + public: + using TimePoint = std::chrono::steady_clock::time_point; + + Data( value_type min_r, value_type max_r, value_type val_r ) + : _state( INIT ), _min( min_r ), _max( max_r ), _val( val_r ) + , _last_val( 0 ) + {} + + public: + State _state; + std::string _name; + value_type _min; + value_type _max; + value_type _val; + + ReceiverFnc _receiver; + value_type _last_val; + TimePoint _last_send; + + private: + /** clone for RWCOW_pointer */ + friend Data * rwcowClone( const Data * rhs ); + Data * clone() const { return new Data( *this ); } + }; + + public: + /** Ctor no range [0,0](0). */ + ProgressData() + : _d( new Data( 0, 0, 0 ) ) + {} + + /** Ctor [0,max](0). */ + ProgressData( value_type max_r ) + : _d( new Data( 0, max_r, 0 ) ) + {} + + /** Ctor [min,max](min). */ + ProgressData( value_type min_r, value_type max_r ) + : _d( new Data( min_r, max_r, min_r ) ) + {} + + /** Ctor [min,max](val). */ + ProgressData( value_type min_r, value_type max_r, value_type val_r ) + : _d( new Data( min_r, max_r, val_r ) ) + {} + + ~ProgressData() + { + if ( _d->_state == RUN ) + { + _d->_state = END; + report(); + } + } + + public: + /** Set new \c min value. */ + void min( value_type min_r ) + { _d->_min = min_r; } + + /** Set new \c max value. */ + void max( value_type max_r ) + { _d->_max = max_r; } + + /** Set no range [0,0]. */ + void noRange() + { range( 0, 0 ); } + + /** Set new [0,max]. */ + void range( value_type max_r ) + { range( 0, max_r ); } + + /** Set new [min,max]. */ + void range( value_type min_r, value_type max_r ) + { min( min_r ); max( max_r ); } + + public: + /** Set counter name. */ + void name( const std::string & name_r ) + { _d->_name = name_r; } + + /** Set ReceiverFnc. */ + void sendTo( const ReceiverFnc & fnc_r ) + { _d->_receiver = fnc_r; } + + /** Set no ReceiverFnc. */ + void noSend() + { _d->_receiver = ReceiverFnc(); } + + public: + /** \name Progress reporting. + * + * These methods may actually cause a progress report to be sent. + * + * All methods return \c bool, because a progress receiver may + * return \c false to indicate the desire to abort the pending + * action. The incident is logged, but it's finally up to the caller + * to honor this. + */ + //@{ + + /** Set new counter \c value. */ + bool set( value_type val_r ) + { + _d->_val = val_r; + return report(); + } + + /** Set range and counter from an other \ref ProgressData. */ + bool set( const ProgressData & rhs ) + { + min( rhs.min() ); + max( rhs.max() ); + return set( rhs.val() ); + } + + /** Increment counter \c value (default by 1). */ + bool incr( value_type val_r = 1 ) + { return set( val() + val_r ); } + + /** Decrement counter \c value (default by 1). */ + bool decr( value_type val_r = 1 ) + { return set( val() - val_r ); } + + /** Set counter value to current \c min value. */ + bool toMin() + { return set( min() ); } + + /** Set counter value to current \c max value (unless no range). */ + bool toMax() + { return hasRange() ? set( max() ) : tick(); } + + /** Leave counter value unchanged (still alive). */ + bool tick() + { return report(); } + + //@} + + public: + /** \name Progress receiving. + */ + //@{ + /** @return Current \c min value. */ + value_type min() const + { return _d->_min; } + + /** @return Current \c max value. */ + value_type max() const + { return _d->_max; } + + /** @return Current counter \c value. */ + value_type val() const + { return _d->_val; } + + /** @return Whether [min,max] defines a nonempty range. */ + bool hasRange() const + { return min() != max(); } + + /** @return Whether \ref reportValue will return a percent value. + * Same as \ref hasRange. + * \see \ref reportAlive + */ + bool reportPercent() const + { return hasRange(); } + + /** @return Whether \ref reportValue always returns -1, because we + * trigger 'still alive' messages. I.e. \ref hasrange is \c false. + * \see \ref reportPercent + */ + bool reportAlive() const + { return ! hasRange(); } + + /** @return Either a a percent value or -1. + * \see \ref reportPercent and \ref reportAlive. + */ + value_type reportValue() const + { return hasRange() ? val() * 100 / ( max() - min() ) : -1; } + + /** @return The counters name. */ + const std::string & name() const + { return _d->_name; } + + /** @return The ReceiverFnc. */ + const ReceiverFnc & receiver() const + { return _d->_receiver; } + + /** @return Return \c true if this is the final report sent by the + * ProgressData dtor. + */ + bool finalReport() const + { return( _d->_state == END ); } + + //@} + + private: + /** Send report if necessary. */ + bool report(); + + /** Pointer to data. */ + RWCOW_pointer _d; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ProgressData Stream output */ + std::ostream & operator<<( std::ostream & str, const ProgressData & obj ); + + /////////////////////////////////////////////////////////////////// + + class InputStream; + /** \relates ProgressData Setup from \ref InputStream. */ + ProgressData makeProgressData( const InputStream & input_r ); + + /////////////////////////////////////////////////////////////////// + + /** + * \short Progress callback from another progress + * + * This class allows you to pass a progress callback to a + * subtask based on a current progress data, plus a weight + * value. Every progress reported by the subtask via + * this callback will be forwarded to the main progress + * data, with the corresponding weight. + * + * Example: + * + * \code + * + * // receiver for main task + * void task_receiver( ProgressData &progress ); + * + * // subtask prototypes + * void do_subtask_one( ProgressData::ReceiverFnc &fnc ); + * void do_subtask_two( ProgressData::ReceiverFnc &fnc ); + * + * // main task + * ProgressData progress; + * //progress for subtask 1 + * // which is 80% + * CombinedProgressData sub1(pd, 80); + * // the second is only 20% + * CombinedProgressData sub2(pd, 20); + * do_subtask_one( sub1 ); + * do_subtask_two( sub2 ); + * + * \endcode + */ + class ZYPP_API CombinedProgressData + { + public: + /** + * \short Ctor + * + * Creates a \ref ProgressData::ReceiverFnc + * from a \ref ProgressData object + * + * \param pd \ref ProgressData object + * \param weight Weight of the subtask + * relative to the main task range. + * + * If weight is 0, or \param pd only reports + * keepalives. then only ticks are sent. + * + */ + CombinedProgressData( ProgressData &pd, + ProgressData::value_type weight = 0 ); + + /** + * Implements the \ref ProgressData::ReceiverFnc + * callback interface + */ + bool operator()( const ProgressData &progress ); + + private: + ProgressData::value_type _weight; + ProgressData::value_type _last_value; + ProgressData &_pd; + }; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CORE_UI_PROGRESSDATA_H diff --git a/zypp-core/url/UrlBase.cc b/zypp-core/url/UrlBase.cc new file mode 100644 index 0000000..b5173a3 --- /dev/null +++ b/zypp-core/url/UrlBase.cc @@ -0,0 +1,1458 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/url/UrlBase.cc + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +// in the Estonian locale, a-z excludes t, for example. #302525 +// http://en.wikipedia.org/wiki/Estonian_alphabet +#define a_zA_Z "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + +// --------------------------------------------------------------- +/* +** authority = //[user [:password] @ ] host [:port] +** +** host = hostname | IPv4 | "[" IPv6-IP "]" | "[v...]" +*/ +#define RX_VALID_SCHEME "^[" a_zA_Z "][" a_zA_Z "0-9\\.+-]*$" + +#define RX_VALID_PORT "^[0-9]{1,5}$" + +#define RX_VALID_HOSTNAME "^[[:alnum:]${_}]+([\\.-][[:alnum:]${_}]+)*$" + +#define RX_VALID_HOSTIPV4 \ + "^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$" + +#define RX_VALID_HOSTIPV6 \ + "^\\[[:a-fA-F0-9]+(:[0-9]{1,3}(\\.[0-9]{1,3}){3})?\\]$" + + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + namespace url + { ////////////////////////////////////////////////////////////////// + + + // --------------------------------------------------------------- + /* + ** URL asString() view option constants: + */ + const ViewOption ViewOption::WITH_SCHEME = 0x0001; + const ViewOption ViewOption::WITH_USERNAME = 0x0002; + const ViewOption ViewOption::WITH_PASSWORD = 0x0004; + const ViewOption ViewOption::WITH_HOST = 0x0008; + const ViewOption ViewOption::WITH_PORT = 0x0010; + const ViewOption ViewOption::WITH_PATH_NAME = 0x0020; + const ViewOption ViewOption::WITH_PATH_PARAMS = 0x0040; + const ViewOption ViewOption::WITH_QUERY_STR = 0x0080; + const ViewOption ViewOption::WITH_FRAGMENT = 0x0100; + const ViewOption ViewOption::EMPTY_AUTHORITY = 0x0200; + const ViewOption ViewOption::EMPTY_PATH_NAME = 0x0400; + const ViewOption ViewOption::EMPTY_PATH_PARAMS = 0x0800; + const ViewOption ViewOption::EMPTY_QUERY_STR = 0x1000; + const ViewOption ViewOption::EMPTY_FRAGMENT = 0x2000; + const ViewOption ViewOption::DEFAULTS = 0x07bb; + + const ViewOption ViewOption::hotfix1050625 = 0x8000; + /* + const ViewOption ViewOption::DEFAULTS = + ViewOption::WITH_SCHEME + + ViewOption::WITH_USERNAME + + ViewOption::WITH_HOST + + ViewOption::WITH_PORT + + ViewOption::WITH_PATH_NAME + + ViewOption::WITH_QUERY_STR + + ViewOption::WITH_FRAGMENT + + ViewOption::EMPTY_AUTHORITY + + ViewOption::EMPTY_PATH_NAME; + */ + + // --------------------------------------------------------------- + ViewOption::ViewOption() + : opt(0x07bb) + {} + + // --------------------------------------------------------------- + ViewOption::ViewOption(int option) + : opt(option) + {} + + + // --------------------------------------------------------------- + /* + ** Behaviour configuration variables. + */ + using UrlConfig = std::map; + + + // --------------------------------------------------------------- + + /// \brief Hide passwords embedded in a querystr, + /// + /// Stores the full querystring and maintains a safe version with + /// password field stripped. Url::asString will print the passwords + /// on demand only. + /// + /// \see bsc#1050625: VUL-1: CVE-2017-9271: zypper: proxy credentials written to log files + class SafeQuerystr + { + public: + SafeQuerystr() + {} + + SafeQuerystr( std::string rhs ) + { _assign( std::move(rhs) ); } + + SafeQuerystr & operator=( std::string rhs ) + { _assign( std::move(rhs) ); return *this; } + + + operator const std::string &() const + { return str(); } + + const std::string & str() const + { return fullStr(); } + + const std::string & str( const ViewOptions & viewopts_r ) const + { return (viewopts_r.has( ViewOptions::WITH_PASSWORD ) || viewopts_r.has( ViewOptions::hotfix1050625 )) ? fullStr() : safeStr(); } + + const std::string & fullStr() const + { return _fullQuerytsr; } + + const std::string & safeStr() const + { return _safeQuerytsr ? _safeQuerytsr.value() : _fullQuerytsr; } + + private: + void _assign( std::string && rhs ) + { + _fullQuerytsr = std::move(rhs); + + static constexpr std::string_view tag { "proxypass=" }; + if ( _fullQuerytsr.find( tag ) != std::string::npos ) + { + std::string safe; + strv::split( _fullQuerytsr, "&", [&safe]( std::string_view val ) { + if ( val.substr( 0, tag.size() ) != tag ) { + if ( ! safe.empty() ) + safe += "&"; + safe += val; + } + }); + _safeQuerytsr = std::move(safe); + } + else + _safeQuerytsr = std::nullopt; + } + private: + std::string _fullQuerytsr; ///< + std::optional _safeQuerytsr; ///<. + }; + + /** + * \brief Internal data used by UrlBase. + */ + class UrlBaseData + { + public: + UrlBaseData() + {} + + UrlBaseData(UrlConfig conf) + : config(std::move(conf)) + {} + + UrlConfig config; + ViewOptions vopts; + + std::string scheme; + std::string user; + std::string pass; + std::string host; + std::string port; + std::string pathname; + std::string pathparams; + SafeQuerystr querystr; + std::string fragment; + }; + + + // --------------------------------------------------------------- + /* + ** Anonymous/internal utility namespace: + */ + namespace // anonymous + { + + // ------------------------------------------------------------- + inline void + checkUrlData(const std::string &data, + const std::string &name, + const std::string ®x, + bool show=true) + { + if( regx.empty() || regx == "^$") + { + ZYPP_THROW(UrlNotAllowedException( + str::form(_("Url scheme does not allow a %s"), name.c_str()) + )); + } + else + { + bool valid = false; + try + { + str::regex rex(regx); + valid = str::regex_match(data, rex); + } + catch( ... ) + {} + + if( !valid) + { + if( show) + { + ZYPP_THROW(UrlBadComponentException( + str::form(_("Invalid %s component '%s'"), + name.c_str(), data.c_str()) + )); + } + else + { + ZYPP_THROW(UrlBadComponentException( + str::form(_("Invalid %s component"), name.c_str()) + )); + } + } + } + } + + } // namespace + + + // --------------------------------------------------------------- + UrlBase::~UrlBase() + { + delete m_data; + m_data = NULL; + } + + + // --------------------------------------------------------------- + UrlBase::UrlBase() + : m_data( new UrlBaseData()) + { + configure(); + } + + + // --------------------------------------------------------------- + UrlBase::UrlBase(const UrlBase &url) + : m_data( new UrlBaseData( *(url.m_data))) + { + } + + + // --------------------------------------------------------------- + UrlBase::UrlBase(const std::string &scheme, + const std::string &authority, + const std::string &pathdata, + const std::string &querystr, + const std::string &fragment) + : m_data( new UrlBaseData()) + { + configure(); + init(scheme, authority, pathdata, querystr, fragment); + } + + + // --------------------------------------------------------------- + void + UrlBase::init(const std::string &scheme, + const std::string &authority, + const std::string &pathdata, + const std::string &querystr, + const std::string &fragment) + { + if ( scheme.empty() && *pathdata.c_str() == '/' ) + setScheme("file"); + else + setScheme(scheme); + + setAuthority(authority); + setPathData(pathdata); + setQueryString(querystr); + setFragment(fragment, zypp::url::E_ENCODED); + } + + + // --------------------------------------------------------------- + void + UrlBase::configure() + { + config("sep_pathparams", ";"); + config("psep_pathparam", ","); + config("vsep_pathparam", "="); + + config("psep_querystr", "&"); + config("vsep_querystr", "="); + + config("safe_username", "~!$&'()*+=,;"); + config("safe_password", "~!$&'()*+=,:;"); + config("safe_hostname", "[:]${_}"); + config("safe_pathname", "~!$&'()*+=,:@/"); + config("safe_pathparams", "~!$&'()*+=,:;@/"); + config("safe_querystr", "~!$&'()*+=,:;@/?"); + config("safe_fragment", "~!$&'()*+=,:;@/?"); + + // y=yes (allowed) + // n=no (disallowed, exception if !empty) + config("with_authority", "y"); + config("with_port", "y"); + + // y=yes (required but don't throw if empty) + // n=no (not required, ignore if empty) + // m=mandatory (exception if empty) + config("require_host", "n"); + config("require_pathname","n"); + + // y=yes (encode 2. slash even if authority present) + // n=no (don't encode 2. slash if authority present) + config("path_encode_slash2", "n"); + + config("rx_username", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,;~\\._-]|%[a-fA-F0-9]{2})+$"); + config("rx_password", "^([" a_zA_Z "0-9!$&'\\(\\)*+=,:;~\\._-]|%[a-fA-F0-9]{2})+$"); + + config("rx_pathname", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:@/~\\._-]|%[a-fA-F0-9]{2})+$"); + config("rx_pathparams", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:;@/~\\._-]|%[a-fA-F0-9]{2})+$"); + + config("rx_querystr", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$"); + config("rx_fragment", "^([" a_zA_Z "0-9!$&'\\(\\){}*+=,:;@/?~\\._-]|%[a-fA-F0-9]{2})+$"); + } + + + // --------------------------------------------------------------- + void + UrlBase::config(const std::string &opt, const std::string &val) + { + m_data->config[opt] = val; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::config(const std::string &opt) const + { + UrlConfig::const_iterator v( m_data->config.find(opt)); + if( v != m_data->config.end()) + return v->second; + else + return std::string(); + } + + + // --------------------------------------------------------------- + ViewOptions + UrlBase::getViewOptions() const + { + return m_data->vopts; + } + + + // --------------------------------------------------------------- + void + UrlBase::setViewOptions(const ViewOptions &vopts) + { + m_data->vopts = vopts; + } + + + // --------------------------------------------------------------- + void + UrlBase::clear() + { + zypp::url::UrlConfig config(m_data->config); + zypp::url::ViewOptions vopts(m_data->vopts); + *m_data = UrlBaseData(); + m_data->config = config; + m_data->vopts = vopts; + } + + + // --------------------------------------------------------------- + UrlBase * + UrlBase::clone() const + { + return new UrlBase(*this); + } + + + // --------------------------------------------------------------- + zypp::url::UrlSchemes + UrlBase::getKnownSchemes() const + { + return UrlSchemes(); + } + + + // --------------------------------------------------------------- + bool + UrlBase::isKnownScheme(const std::string &scheme) const + { + std::string lscheme( str::toLower(scheme)); + UrlSchemes schemes( getKnownSchemes()); + UrlSchemes::const_iterator s; + + for(s=schemes.begin(); s!=schemes.end(); ++s) + { + if( lscheme == str::toLower(*s)) + return true; + } + return false; + } + + + // --------------------------------------------------------------- + bool + UrlBase::isValidScheme(const std::string &scheme) const + { + bool valid = false; + try + { + str::regex rex(RX_VALID_SCHEME); + valid = str::regex_match(scheme, rex); + } + catch( ... ) + {} + + if(valid) + { + std::string lscheme( str::toLower(scheme)); + UrlSchemes schemes( getKnownSchemes()); + + if( schemes.empty()) + return true; + + UrlSchemes::const_iterator s; + for(s=schemes.begin(); s!=schemes.end(); ++s) + { + if( lscheme == str::toLower(*s)) + return true; + } + } + return false; + } + + + // --------------------------------------------------------------- + bool + UrlBase::isValid() const + { + /* + ** scheme is the only mandatory component + ** for all url's and is already verified, + ** (except for empty Url instances), so + ** Url with empty scheme is never valid. + */ + if( getScheme().empty()) + return false; + + std::string host( getHost(zypp::url::E_ENCODED)); + if( host.empty() && config("require_host") != "n") + return false; + + std::string path( getPathName(zypp::url::E_ENCODED)); + if( path.empty() && config("require_pathname") != "n") + return false; + + /* + ** path has to begin with "/" if authority avaliable + ** if host is set after the pathname, we can't throw + */ + if( !host.empty() && !path.empty() && path.at(0) != '/') + return false; + + return true; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::asString() const + { + return asString(getViewOptions()); + } + + std::string UrlBase::asString1050625() const + { + // Temp. fix to keep the proxypass in the query when writing the .repo files, + // but otherwise hiding it, when WITH_PASSWORD is not set. + return asString(getViewOptions()+ViewOptions::hotfix1050625); + } + + // --------------------------------------------------------------- + std::string + UrlBase::asString(const zypp::url::ViewOptions &opts) const + { + std::string url; + UrlBaseData tmp; + + if( opts.has(ViewOptions::WITH_SCHEME)) + { + tmp.scheme = getScheme(); + if( !tmp.scheme.empty()) + { + url += tmp.scheme + ":"; + + if( opts.has(ViewOptions::WITH_HOST)) + { + tmp.host = getHost(zypp::url::E_ENCODED); + if( !tmp.host.empty()) + { + url += "//"; + + if( opts.has(ViewOptions::WITH_USERNAME)) + { + tmp.user = getUsername(zypp::url::E_ENCODED); + if( !tmp.user.empty()) + { + url += tmp.user; + + if( opts.has(ViewOptions::WITH_PASSWORD)) + { + tmp.pass = getPassword(zypp::url::E_ENCODED); + if( !tmp.pass.empty()) + { + url += ":" + tmp.pass; + } + } + url += "@"; + } + } + + url += tmp.host; + + if( opts.has(ViewOptions::WITH_PORT)) + { + tmp.port = getPort(); + if( !tmp.port.empty()) + { + url += ":" + tmp.port; + } + } + } + else if( opts.has(ViewOptions::EMPTY_AUTHORITY)) + { + url += "//"; + } + } + else if( opts.has(ViewOptions::EMPTY_AUTHORITY)) + { + url += "//"; + } + } + } + + if( opts.has(ViewOptions::WITH_PATH_NAME)) + { + tmp.pathname = getPathName(zypp::url::E_ENCODED); + if( !tmp.pathname.empty()) + { + if(url.find('/') != std::string::npos) + { + // Url contains authority (that may be empty), + // we may need a rewrite of the encoded path. + tmp.pathname = cleanupPathName(tmp.pathname, true); + if(tmp.pathname.at(0) != '/') + { + url += "/"; + } + } + url += tmp.pathname; + + if( opts.has(ViewOptions::WITH_PATH_PARAMS)) + { + tmp.pathparams = getPathParams(); + if( !tmp.pathparams.empty()) + { + url += ";" + tmp.pathparams; + } + else if( opts.has(ViewOptions::EMPTY_PATH_PARAMS)) + { + url += ";"; + } + } + } + else if( opts.has(ViewOptions::EMPTY_PATH_NAME) + && url.find('/') != std::string::npos) + { + url += "/"; + if( opts.has(ViewOptions::EMPTY_PATH_PARAMS)) + { + url += ";"; + } + } + } + + if( opts.has(ViewOptions::WITH_QUERY_STR)) + { + const std::string & querystr { getQueryString( opts ) }; // full or safe depending on opts + if( !querystr.empty() ) + { + url += "?" + querystr; + } + else if( opts.has(ViewOptions::EMPTY_QUERY_STR)) + { + url += "?"; + } + } + + if( opts.has(ViewOptions::WITH_FRAGMENT)) + { + tmp.fragment = getFragment(zypp::url::E_ENCODED); + if( !tmp.fragment.empty()) + { + url += "#" + tmp.fragment; + } + else if( opts.has(ViewOptions::EMPTY_FRAGMENT)) + { + url += "#"; + } + } + + return url; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getScheme() const + { + return m_data->scheme; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getAuthority() const + { + std::string str; + if( !getHost(zypp::url::E_ENCODED).empty()) + { + if( !getUsername(zypp::url::E_ENCODED).empty()) + { + str = getUsername(zypp::url::E_ENCODED); + if( !getPassword(zypp::url::E_ENCODED).empty()) + { + str += ":" + getPassword(zypp::url::E_ENCODED); + } + str += "@"; + } + + str += getHost(zypp::url::E_ENCODED); + if( !getPort().empty()) + { + str += ":" + getPort(); + } + } + return str; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getPathData() const + { + return getPathName(zypp::url::E_ENCODED) + + config("sep_pathparams") + + getPathParams(); + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getQueryString() const + { + return m_data->querystr; + } + + std::string + UrlBase::getQueryString( const ViewOptions & viewopts_r ) const + { + return m_data->querystr.str( viewopts_r ); + } + + // --------------------------------------------------------------- + std::string + UrlBase::getFragment(EEncoding eflag) const + { + if(eflag == zypp::url::E_DECODED) + return zypp::url::decode(m_data->fragment); + else + return m_data->fragment; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getUsername(EEncoding eflag) const + { + if(eflag == zypp::url::E_DECODED) + return zypp::url::decode(m_data->user); + else + return m_data->user; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getPassword(EEncoding eflag) const + { + if(eflag == zypp::url::E_DECODED) + return zypp::url::decode(m_data->pass); + else + return m_data->pass; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getHost(EEncoding eflag) const + { + if(eflag == zypp::url::E_DECODED) + return zypp::url::decode(m_data->host); + else + return m_data->host; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getPort() const + { + return m_data->port; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getPathName(EEncoding eflag) const + { + if(eflag == zypp::url::E_DECODED) + return zypp::url::decode(m_data->pathname); + else + return cleanupPathName(m_data->pathname); + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getPathParams() const + { + return m_data->pathparams; + } + + + // --------------------------------------------------------------- + zypp::url::ParamVec + UrlBase::getPathParamsVec() const + { + zypp::url::ParamVec pvec; + if( config("psep_pathparam").empty()) + { + pvec.push_back(getPathParams()); + } + else + { + zypp::url::split( + pvec, + getPathParams(), + config("psep_pathparam") + ); + } + return pvec; + } + + + // --------------------------------------------------------------- + zypp::url::ParamMap + UrlBase::getPathParamsMap(EEncoding eflag) const + { + if( config("psep_pathparam").empty() || + config("vsep_pathparam").empty()) + { + ZYPP_THROW(UrlNotSupportedException( + "Path parameter parsing not supported for this URL" + )); + } + zypp::url::ParamMap pmap; + zypp::url::split( + pmap, + getPathParams(), + config("psep_pathparam"), + config("vsep_pathparam"), + eflag + ); + return pmap; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getPathParam(const std::string ¶m, EEncoding eflag) const + { + zypp::url::ParamMap pmap( getPathParamsMap( eflag)); + zypp::url::ParamMap::const_iterator i( pmap.find(param)); + + return i != pmap.end() ? i->second : std::string(); + } + + + // --------------------------------------------------------------- + zypp::url::ParamVec + UrlBase::getQueryStringVec() const + { + zypp::url::ParamVec pvec; + if( config("psep_querystr").empty()) + { + pvec.push_back(getQueryString()); + } + else + { + zypp::url::split( + pvec, + getQueryString(), + config("psep_querystr") + ); + } + return pvec; + } + + + // --------------------------------------------------------------- + zypp::url::ParamMap + UrlBase::getQueryStringMap(EEncoding eflag) const + { + if( config("psep_querystr").empty() || + config("vsep_querystr").empty()) + { + ZYPP_THROW(UrlNotSupportedException( + _("Query string parsing not supported for this URL") + )); + } + zypp::url::ParamMap pmap; + zypp::url::split( + pmap, + getQueryString(), + config("psep_querystr"), + config("vsep_querystr"), + eflag + ); + return pmap; + } + + + // --------------------------------------------------------------- + std::string + UrlBase::getQueryParam(const std::string ¶m, EEncoding eflag) const + { + zypp::url::ParamMap pmap( getQueryStringMap( eflag)); + zypp::url::ParamMap::const_iterator i( pmap.find(param)); + + return i != pmap.end() ? i->second : std::string(); + } + + + // --------------------------------------------------------------- + void + UrlBase::setScheme(const std::string &scheme) + { + if( isValidScheme(scheme)) + { + m_data->scheme = str::toLower(scheme); + } + else + if( scheme.empty()) + { + ZYPP_THROW(UrlBadComponentException( + _("Url scheme is a required component") + )); + } + else + { + ZYPP_THROW(UrlBadComponentException( + str::form(_("Invalid Url scheme '%s'"), scheme.c_str()) + )); + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setAuthority(const std::string &authority) + { + std::string s = authority; + std::string::size_type p = 0,q = 0; + + std::string username, password, host, port; + + if ((p=s.find('@')) != std::string::npos) + { + q = s.find(':'); + if (q != std::string::npos && q < p) + { + setUsername(s.substr(0, q), zypp::url::E_ENCODED); + setPassword(s.substr(q+1, p-q-1), zypp::url::E_ENCODED); + } + else + setUsername(s.substr(0, p), zypp::url::E_ENCODED); + s = s.substr(p+1); + } + if ((p = s.rfind(':')) != std::string::npos && ( (q = s.rfind(']')) == std::string::npos || q < p) ) + { + setHost(s.substr(0, p)); + setPort(s.substr(p+1)); + } + else + setHost(s); + } + + // --------------------------------------------------------------- + void + UrlBase::setPathData(const std::string &pathdata) + { + size_t pos = std::string::npos; + std::string sep(config("sep_pathparams")); + + if( !sep.empty()) + pos = pathdata.find(sep); + + if( pos != std::string::npos) + { + setPathName(pathdata.substr(0, pos), + zypp::url::E_ENCODED); + setPathParams(pathdata.substr(pos + 1)); + } + else + { + setPathName(pathdata, + zypp::url::E_ENCODED); + setPathParams(""); + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setQueryString(const std::string &querystr) + { + if( querystr.empty()) + { + m_data->querystr = querystr; + } + else + { + checkUrlData(querystr, "query string", config("rx_querystr")); + + m_data->querystr = querystr; + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setFragment(const std::string &fragment, + EEncoding eflag) + { + if( fragment.empty()) + { + m_data->fragment = fragment; + } + else + { + if(eflag == zypp::url::E_ENCODED) + { + checkUrlData(fragment, "fragment", config("rx_fragment")); + + m_data->fragment = fragment; + } + else + { + m_data->fragment = zypp::url::encode( + fragment, config("safe_fragment") + ); + } + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setUsername(const std::string &user, + EEncoding eflag) + { + if( user.empty()) + { + m_data->user = user; + } + else + { + if( config("with_authority") != "y") + { + ZYPP_THROW(UrlNotAllowedException( + _("Url scheme does not allow a username") + )); + } + + if(eflag == zypp::url::E_ENCODED) + { + checkUrlData(user, "username", config("rx_username")); + + m_data->user = user; + } + else + { + m_data->user = zypp::url::encode( + user, config("safe_username") + ); + } + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setPassword(const std::string &pass, + EEncoding eflag) + { + if( pass.empty()) + { + m_data->pass = pass; + } + else + { + if( config("with_authority") != "y") + { + ZYPP_THROW(UrlNotAllowedException( + _("Url scheme does not allow a password") + )); + } + + if(eflag == zypp::url::E_ENCODED) + { + checkUrlData(pass, "password", config("rx_password"), false); + + m_data->pass = pass; + } + else + { + m_data->pass = zypp::url::encode( + pass, config("safe_password") + ); + } + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setHost(const std::string &host) + { + if( host.empty()) + { + if(config("require_host") == "m") + { + ZYPP_THROW(UrlNotAllowedException( + _("Url scheme requires a host component") + )); + } + m_data->host = host; + } + else + { + if( config("with_authority") != "y") + { + ZYPP_THROW(UrlNotAllowedException( + _("Url scheme does not allow a host component") + )); + } + + if( isValidHost(host)) + { + std::string temp; + + // always decode in case isValidHost() + // is reimplemented and supports also + // the [v ... ] notation. + if( host.at(0) == '[') + { + temp = str::toUpper(zypp::url::decode(host)); + } + else + { + temp = str::toLower(zypp::url::decode(host)); + } + + m_data->host = zypp::url::encode( + temp, config("safe_hostname") + ); + } + else + { + ZYPP_THROW(UrlBadComponentException( + str::form(_("Invalid host component '%s'"), host.c_str()) + )); + } + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setPort(const std::string &port) + { + if( port.empty()) + { + m_data->port = port; + } + else + { + if( config("with_authority") != "y" || + config("with_port") != "y") + { + ZYPP_THROW(UrlNotAllowedException( + _("Url scheme does not allow a port") + )); + } + + if( isValidPort(port)) + { + m_data->port = port; + } + else + { + ZYPP_THROW(UrlBadComponentException( + str::form(_("Invalid port component '%s'"), port.c_str()) + )); + } + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setPathName(const std::string &path, + EEncoding eflag) + { + if( path.empty()) + { + if(config("require_pathname") == "m") + { + ZYPP_THROW(UrlNotAllowedException( + _("Url scheme requires path name") + )); + } + m_data->pathname = path; + } + else + { + if(eflag == zypp::url::E_ENCODED) + { + checkUrlData(path, "path name", config("rx_pathname")); + + if( !getHost(zypp::url::E_ENCODED).empty()) + { + // has to begin with a "/". For consistency with + // setPathName while the host is empty, we allow + // it in encoded ("%2f") form - cleanupPathName() + // will fix / decode the first slash if needed. + if(!(path.at(0) == '/' || (path.size() >= 3 && + str::toLower(path.substr(0, 3)) == "%2f"))) + { + ZYPP_THROW(UrlNotAllowedException( + _("Relative path not allowed if authority exists") + )); + } + } + + m_data->pathname = cleanupPathName(path); + } + else // zypp::url::E_DECODED + { + if( !getHost(zypp::url::E_ENCODED).empty()) + { + if(path.at(0) != '/') + { + ZYPP_THROW(UrlNotAllowedException( + _("Relative path not allowed if authority exists") + )); + } + } + + m_data->pathname = cleanupPathName( + zypp::url::encode( + path, config("safe_pathname") + ) + ); + } + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setPathParams(const std::string ¶ms) + { + if( params.empty()) + { + m_data->pathparams = params; + } + else + { + checkUrlData(params, "path parameters", config("rx_pathparams")); + + m_data->pathparams = params; + } + } + + + // --------------------------------------------------------------- + void + UrlBase::setPathParamsVec(const zypp::url::ParamVec &pvec) + { + setPathParams( + zypp::url::join( + pvec, + config("psep_pathparam") + ) + ); + } + + + // --------------------------------------------------------------- + void + UrlBase::setPathParamsMap(const zypp::url::ParamMap &pmap) + { + if( config("psep_pathparam").empty() || + config("vsep_pathparam").empty()) + { + ZYPP_THROW(UrlNotSupportedException( + "Path Parameter parsing not supported for this URL" + )); + } + setPathParams( + zypp::url::join( + pmap, + config("psep_pathparam"), + config("vsep_pathparam"), + config("safe_pathparams") + ) + ); + } + + + // --------------------------------------------------------------- + void + UrlBase::setPathParam(const std::string ¶m, const std::string &value) + { + zypp::url::ParamMap pmap( getPathParamsMap(zypp::url::E_DECODED)); + pmap[param] = value; + setPathParamsMap(pmap); + } + + + // --------------------------------------------------------------- + void + UrlBase::setQueryStringVec(const zypp::url::ParamVec &pvec) + { + setQueryString( + zypp::url::join( + pvec, + config("psep_querystr") + ) + ); + } + + + // --------------------------------------------------------------- + void + UrlBase::setQueryStringMap(const zypp::url::ParamMap &pmap) + { + if( config("psep_querystr").empty() || + config("vsep_querystr").empty()) + { + ZYPP_THROW(UrlNotSupportedException( + _("Query string parsing not supported for this URL") + )); + } + setQueryString( + zypp::url::join( + pmap, + config("psep_querystr"), + config("vsep_querystr"), + config("safe_querystr") + ) + ); + } + + // --------------------------------------------------------------- + void + UrlBase::setQueryParam(const std::string ¶m, const std::string &value) + { + zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED)); + pmap[param] = value; + setQueryStringMap(pmap); + } + + // --------------------------------------------------------------- + void + UrlBase::delQueryParam(const std::string ¶m) + { + zypp::url::ParamMap pmap( getQueryStringMap(zypp::url::E_DECODED)); + pmap.erase(param); + setQueryStringMap(pmap); + } + + + // --------------------------------------------------------------- + std::string + UrlBase::cleanupPathName(const std::string &path) const + { + bool authority = !getHost(zypp::url::E_ENCODED).empty(); + return cleanupPathName(path, authority); + } + + // --------------------------------------------------------------- + std::string + UrlBase::cleanupPathName(const std::string &path, bool authority) const + { + std::string copy( path); + + // decode the first slash if it is encoded ... + if(copy.size() >= 3 && copy.at(0) != '/' && + str::toLower(copy.substr(0, 3)) == "%2f") + { + copy.replace(0, 3, "/"); + } + + // if path begins with a double slash ("//"); encode the second + // slash [minimal and IMO sufficient] before the first path + // segment, to fulfill the path-absolute rule of RFC 3986 + // disallowing a "//" if no authority is present. + if( authority) + { + // + // rewrite of "//" to "/%2f" not required, use config + // + if(config("path_encode_slash2") == "y") + { + // rewrite "//" ==> "/%2f" + if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/') + { + copy.replace(1, 1, "%2F"); + } + } + else + { + // rewrite "/%2f" ==> "//" + if(copy.size() >= 4 && copy.at(0) == '/' && + str::toLower(copy.substr(1, 4)) == "%2f") + { + copy.replace(1, 4, "/"); + } + } + } + else + { + // rewrite of "//" to "/%2f" is required (no authority) + if(copy.size() >= 2 && copy.at(0) == '/' && copy.at(1) == '/') + { + copy.replace(1, 1, "%2F"); + } + } + return copy; + } + + + // --------------------------------------------------------------- + bool + UrlBase::isValidHost(const std::string &host) const + { + try + { + str::regex regx(RX_VALID_HOSTIPV6); + if( str::regex_match(host, regx)) + { + struct in6_addr ip; + std::string temp( host.substr(1, host.size()-2)); + + return inet_pton(AF_INET6, temp.c_str(), &ip) > 0; + } + else + { + // matches also IPv4 dotted-decimal adresses... + std::string temp( zypp::url::decode(host)); + str::regex regx(RX_VALID_HOSTNAME); + return str::regex_match(temp, regx); + } + } + catch( ... ) + {} + + return false; + } + + + // --------------------------------------------------------------- + bool + UrlBase::isValidPort(const std::string &port) const + { + try + { + str::regex regx(RX_VALID_PORT); + if( str::regex_match(port, regx)) + { + long pnum = str::strtonum(port); + return ( pnum >= 1 && pnum <= USHRT_MAX); + } + } + catch( ... ) + {} + return false; + } + + + ////////////////////////////////////////////////////////////////// + } // namespace url + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp-core/url/UrlBase.h b/zypp-core/url/UrlBase.h new file mode 100644 index 0000000..0494b9f --- /dev/null +++ b/zypp-core/url/UrlBase.h @@ -0,0 +1,1103 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/url/UrlBase.h + */ +#ifndef ZYPP_URL_URLBASE_H +#define ZYPP_URL_URLBASE_H + +#include +#include + + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + namespace url + { ////////////////////////////////////////////////////////////////// + + + // --------------------------------------------------------------- + /** + * Url::asString() view options. + * + * A instance of this class represents a bit-wise combination + * of view option constants. + * + * It provides ViewOption::operator+() and ViewOption::operator-() + * to modify a view option combination and a ViewOption::has() + * method, to check if a specified option is enabled or not. + */ + struct ZYPP_API ViewOption + { + /** @{ */ + /** + * Option to include scheme name in the URL string. + * + * Disabling this option causes, that the URL string + * contains the path, query and fragment components + * only, for example just "/foo/bar.txt". + * + * This option is \b enabled by default. + */ + static const ViewOption WITH_SCHEME ZYPP_API; + /** + * Option to include username in the URL string. + * + * This option depends on a enabled WITH_SCHEME and + * WITH_HOST options and is \b enabled by default. + */ + static const ViewOption WITH_USERNAME ZYPP_API; + /** + * Option to include password in the URL string. + * + * This option depends on a enabled WITH_SCHEME, + * WITH_HOST and WITH_USERNAME options and is + * \b disabled by default, causing to hide the + * password in the URL authority. + */ + static const ViewOption WITH_PASSWORD ZYPP_API; + /** + * Option to include hostname in the URL string. + * + * This option depends on a enabled WITH_SCHEME + * option and is \b enabled by default. + */ + static const ViewOption WITH_HOST ZYPP_API; + /** + * Option to include port number in the URL string. + * + * This option depends on a enabled WITH_SCHEME and + * WITH_HOST options and is \b enabled by default. + */ + static const ViewOption WITH_PORT ZYPP_API; + /** + * Option to include path name in the URL string. + * + * This option is \b enabled by default. + */ + static const ViewOption WITH_PATH_NAME ZYPP_API; + /** + * Option to include path parameters in the URL string. + * + * This option depends on a enabled WITH_PATH_NAME + * option and is \b disabled by default, causing to + * hide the path parameters. + */ + static const ViewOption WITH_PATH_PARAMS ZYPP_API; + /** + * Option to include query string in the URL string. + * + * This option is \b enabled by default. + */ + static const ViewOption WITH_QUERY_STR ZYPP_API; + /** + * Option to include fragment string in the URL string. + * + * This option is \b enabled by default. + */ + static const ViewOption WITH_FRAGMENT ZYPP_API; + /** @} */ + + /** @{ */ + /** + * Explicitely include the URL authority separator "//". + * + * It causes, that the URL string includes an empty URL + * authority, for example: + * "file:///foo.txt" instead of just "file:/foo.txt". + * + * This option depends on a enabled WITH_SCHEME view + * option and is enabled by default. + */ + static const ViewOption EMPTY_AUTHORITY ZYPP_API; + /** + * Explicitely include the "/" path character. + * + * It causes, that a "/" is added to the Url if the path + * name is empty, for example: + * + * "http://localhost/" instead of just "http://localhost". + * + * This option depends on a enabled WITH_PATH_NAME view + * option and is enabled by default. + */ + static const ViewOption EMPTY_PATH_NAME ZYPP_API; + /** + * Explicitely include the path parameters separator ";". + * + * It causes, that the URL allways contains the ";" path + * parameters separator. + * + * This option depends on a enabled EMPTY_PATH_NAME view + * option and is disabled by default. + */ + static const ViewOption EMPTY_PATH_PARAMS ZYPP_API; + /** + * Explicitely include the query string separator "?". + * + * It causes, that if the query string is requested using + * the WITH_QUERY_STR option, the URL allways contains the + * "?" query string separator, even if the query string is + * empty. + * This option depends on a enabled WITH_QUERY_STR view + * option and is disabled by default. + */ + static const ViewOption EMPTY_QUERY_STR ZYPP_API; + /** + * Explicitely include the fragment string separator "#". + * + * It causes, that if the fragment string is requested using + * the WITH_FRAGMENT option, the URL allways contains the "#" + * fragment string separator, even if the fragment string is + * empty. + * This option depends on a enabled WITH_FRAGMENT view + * option and is disabled by default. + */ + static const ViewOption EMPTY_FRAGMENT ZYPP_API; + /** @} */ + + /** @{ */ + /** + * Default combination of view options. + * + * By default, following view options are enabled: + * WITH_SCHEME, WITH_USERNAME, WITH_HOST, + * WITH_PORT, WITH_PATH_NAME, WITH_QUERY_STR, + * WITH_FRAGMENT, EMPTY_AUTHORITY, EMPTY_PATH_NAME. + */ + static const ViewOption DEFAULTS ZYPP_API; + /** @} */ + + + /** + * Create instance with default combination of view options. + */ + ViewOption(); + + + /** + * Adds \p l and \p r to a new option combination. + * + * @return The new option combination. + */ + friend inline ViewOption + operator + (const ViewOption &l, const ViewOption &r) + { + return ViewOption(l.opt | r.opt); + } + + /** + * Substract \p r from \p l to a new option combination. + * + * @return The new option combination. + */ + friend inline ViewOption + operator - (const ViewOption &l, const ViewOption &r) + { + return ViewOption(l.opt & ~r.opt); + } + + /** + * Assign specified option combination \p o to the current object. + * + * \param o The option or option combination to make a copy of. + * \return A reference to this option combination. + */ + inline ViewOption & + operator = (const ViewOption &o) + { + opt = o.opt; return *this; + } + + /** + * Check if specified option \p o is set in the current object. + * \param o A view option constant. + * \return True, if specified option \p o is + * set/enabled in the instance. + */ + inline bool + has(const ViewOption &o) const + { + return o.opt & opt; + } + + static const ViewOption hotfix1050625; + private: + ViewOption(int option); + int opt; + }; + + + // --------------------------------------------------------------- + /** + * ViewOptions is just an alias for ViewOption. + */ + using ViewOptions = ViewOption; + + + // --------------------------------------------------------------- + /** + * Vector of URL scheme names. + */ + using UrlSchemes = std::vector; + + + // --------------------------------------------------------------- + /** + * Forward declaration of internal UrlBase data. + */ + class UrlBaseData; + + + // --------------------------------------------------------------- + /** + * \brief Generic Url base class. + * + * The UrlBase class implements default behaviour for URL + * manipulations and a base for implementation of scheme- + * specialized URLs for the Url class. + * + */ + class UrlBase + { + public: + + virtual + ~UrlBase(); + + UrlBase(); + + /** + * Create a new Url object as copy of the given one. + * \param url The Url object to make a copy of. + */ + UrlBase(const UrlBase &url); + + /** + * \brief Construct new object and initializes it with + * specified URL components. + * + * \param scheme The scheme name. + * \param authority The encoded authority component data. + * \param pathdata The encoded path component data. + * \param querystr The encoded query string component. + * \param fragment The encoded fragment string component. + * \throws UrlNotAllowedException if one of the components + * is not allowed for the scheme. + * \throws UrlBadComponentException if one of the components + * contains an invalid character. + */ + UrlBase(const std::string &scheme, + const std::string &authority, + const std::string &pathdata, + const std::string &querystr, + const std::string &fragment); + + + // ----------------- + /** + * \brief Clears all data in the object. + */ + virtual void + clear(); + + /** + * Returns pointer to a copy of the current object. + * + * Should be reimplemented by all derived object using + * the copy constructor of the derived class, e.g.: + * \code + * return new MyUrlDerivedFromUrlBase(*this); + * \endcode + * + * \return A pointer to a copy of the current object. + */ + virtual UrlBase * + clone() const; + + /** + * \brief Initializes current object with new URL components. + * + * \param scheme The scheme name. + * \param authority The encoded authority component data. + * \param pathdata The encoded path component data. + * \param querystr The encoded query string component. + * \param fragment The encoded fragment string component. + * \throws UrlNotAllowedException if one of the components + * is not allowed in the scheme. + * \throws UrlBadComponentException if one of the components + * contains an invalid character. + */ + virtual void + init(const std::string &scheme, + const std::string &authority, + const std::string &pathdata, + const std::string &querystr, + const std::string &fragment); + + + // ----------------- + /** + * \brief Returns scheme names known by this object. + * + * This method is used in the isValidScheme() method and + * is intended to be reimplemented by derived classes to + * return the scheme names it implements (is restricted + * or compatible to). + * + * For example, if your derived class implements special + * features of LDAP URLs, this method may return "ldap" + * and "ldaps" scheme names. + * + * The UrlBase class returns an empty vector, that signals + * that it is useable with all URLs. + * + * \return A vector with scheme names known by this object. + */ + virtual UrlSchemes + getKnownSchemes() const; + + /** + * \brief Returns if scheme name is known to this object. + * \return True, if scheme name is known to this object. + */ + virtual bool + isKnownScheme(const std::string &scheme) const; + + + /** + * \brief Verifies specified scheme name. + * + * Verifies the generic syntax of the specified \p scheme name + * and if it is contained in the current object's list of known + * schemes (see getKnownSchemes()) if the list is not empty (as + * in the UrlBase class). + * + * \param scheme The scheme name to verify. + * \return True, if generic scheme name syntax is valid and + * the scheme name is known to the current object. + */ + virtual bool + isValidScheme(const std::string &scheme) const; + + /** + * \brief Verifies the Url. + * + * Verifies if the current object contains a non-empty scheme + * name. Additional semantical URL checks may be performed by + * derived UrlBase-objects. + * + * \return True, if the Url seems to be valid. + */ + virtual bool + isValid() const; + + + // ----------------- + /** + * Returns a default string representation of the Url object. + * + * By default, a password in the URL will be hidden. + * + * \return A default string representation of the Url object. + */ + virtual std::string + asString() const; + + /** + * Returns a string representation of the Url object. + * + * To include a password in the resulting Url string, use: + * \code + * url.asString(url.getViewOptions() + + * url::ViewOptions::WITH_PASSWORD); + * \endcode + * + * \param opts A combination of view options. + * \return A string representation of the Url object. + */ + virtual std::string + asString(const zypp::url::ViewOptions &opts) const; + + + // ----------------- + /** + * Returns the scheme name of the URL. + * \return Scheme name of the current Url object. + */ + virtual std::string + getScheme() const; + + + // ----------------- + /** + * Returns the encoded authority component of the URL. + * + * The returned authority string does not contain the leading + * "//" separator characters, but just its "user:pass@host:port" + * content only. + * + * \return The encoded authority component string. + */ + virtual std::string + getAuthority() const; + + /** + * Returns the username from the URL authority. + * \param eflag Flag if the usename should be percent-decoded or not. + * \return The username sub-component from the URL authority. + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual std::string + getUsername(EEncoding eflag) const; + + /** + * Returns the password from the URL authority. + * \param eflag Flag if the password should be percent-decoded or not. + * \return The password sub-component from the URL authority. + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual std::string + getPassword(EEncoding eflag) const; + + /** + * Returns the hostname or IP from the URL authority. + * + * In case the Url contains an IPv6 number, it is be surrounded + * by "[" and "]" characters, for example "[::1]" for an IPv6 + * localhost address. + * + * \param eflag Flag if the host should be percent-decoded or not. + * \return The host sub-component from the URL authority. + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual std::string + getHost(EEncoding eflag) const; + + /** + * Returns the port number from the URL authority. + * \return The port sub-component from the URL authority. + */ + virtual std::string + getPort() const; + + + // ----------------- + /** + * Returns the encoded path component of the URL. + * + * The path data contains the path name, optionally + * followed by path parameters separated with a ";" + * character, for example "/foo/bar;version=1.1". + * + * \return The encoded path component of the URL. + */ + virtual std::string + getPathData() const; + + /** + * Returns the path name from the URL. + * \param eflag Flag if the path should be decoded or not. + * \return The path name sub-component without path parameters + * from path data component of the URL. + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual std::string + getPathName(EEncoding eflag) const; + + /** + * Returns the encoded path parameters from the URL. + * \return The encoded path parameters from the URL. + */ + virtual std::string + getPathParams() const; + + /** + * Returns a vector with encoded path parameter substrings. + * + * The default path parameter separator is the \c ',' character. + * A schema specific object may overide the default separators. + * + * For example, the path parameters string "foo=1,bar=2" is splited + * by default into a vector containing the substrings "foo=1" and + * "bar=2". + * + * \return The encoded path parameters vector. + */ + virtual zypp::url::ParamVec + getPathParamsVec() const; + + /** + * Returns a string map with path parameter keys and values. + * + * The default path parameter separator is the \c ',' character, + * the default key/value separator for the path parameters is + * the \c '=' character. + * A schema specific object may overide the default separators. + * + * For example, the path parameters string "foo=1,bar=2" is splited + * into a map containing "foo" = "1" and "bar" = "2" by default. + * + * \param eflag Flag if the path parameter keys and values should + * be decoded or not. + * \return The path parameters key and values as a string map. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual zypp::url::ParamMap + getPathParamsMap(EEncoding eflag) const; + + /** + * Return the value for the specified path parameter. + * + * For example, if the path parameters string is "foo=1,bar=2" + * the method will return the substring "1" for the param key + * "foo" and "2" for the param key "bar". + * + * \param param The path parameter key. + * \param eflag Flag if the path parameter keys and values should + * be decoded or not. + * \return The value for the path parameter key or empty string. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual std::string + getPathParam(const std::string ¶m, EEncoding eflag) const; + + + // ----------------- + /** + * Returns the encoded query string component of the URL. + * + * The query string is returned without first "?" (separator) + * character. Further "?" characters as in e.g. LDAP URLs + * remains in the returned string. + * + * \return The encoded query string component of the URL. + */ + virtual std::string + getQueryString() const; + + /** \overload Returns the safe query string (passwds stripped) unless WITH_PASSWORD is set. */ + virtual std::string + getQueryString( const ViewOptions & viewopts_r ) const; + + /** + * Returns a vector with query string parameter substrings. + * + * The default query string parameter separator is the \c '&' + * character. + * A schema specific object may overide the default separators. + * + * For example, the query string "foo=1&bar=2" is splited by + * default into a vector containing the substrings "foo=1" and + * "bar=2". + * + * \return The query string splited into a vector of substrings. + */ + virtual zypp::url::ParamVec + getQueryStringVec() const; + + /** + * Returns a string map with query parameter and their values. + * + * The default query string parameter separator is the \c ',' + * character, the default key/value separator the \c '=' character. + * A schema specific object may overide the default separators. + * + * For example, the query string "foo=1&bar=2" is splited by + * default into a map containing "foo" = "1" and "bar" = "2". + * + * \param eflag Flag if the query string keys and values should + * be decoded or not. + * \return The query string as a key/value string map. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual zypp::url::ParamMap + getQueryStringMap(EEncoding eflag) const; + + /** + * Return the value for the specified query parameter. + * + * For example, if the query string is "foo=1,bar=2" the method + * will return the substring "1" for the param key "foo" and + * "2" for the param key "bar". + * + * \param param The query parameter key. + * \param eflag Flag if the query parameter keys and values should + * be decoded or not. + * \return The value for the query parameter key or empty string. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual std::string + getQueryParam(const std::string ¶m, EEncoding eflag) const; + + + // ----------------- + /** + * Returns the encoded fragment component of the URL. + * \param eflag Flag if the fragment should be percent-decoded or not. + * \return The encoded fragment component of the URL. + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual std::string + getFragment(EEncoding eflag) const; + + + // ----------------- + /** + * \brief Set the scheme name in the URL. + * \param scheme The new scheme name. + * \throws UrlBadComponentException if the \p scheme + * contains an invalid character or is empty. + */ + virtual void + setScheme(const std::string &scheme); + + + // ----------------- + /** + * \brief Set the authority component in the URL. + * + * The \p authority string shoud not contain any leading + * "//" separator characters (just "user:pass@host:port"). + * + * \param authority The authority component string. + * \throws UrlNotAllowedException if the \p authority + * has to be empty in for the current scheme. + * \throws UrlBadComponentException if the \p authority + * contains an invalid character. + * \throws UrlParsingException if \p authority parsing fails. + */ + virtual void + setAuthority(const std::string &authority); + + /** + * \brief Set the username in the URL authority. + * \param user The new username. + * \param eflag If the \p username is encoded or not. + * \throws UrlNotAllowedException if the \p user + * has to be empty in for the current scheme. + * \throws UrlBadComponentException if the \p user + * contains an invalid character. + */ + virtual void + setUsername(const std::string &user, + EEncoding eflag); + + /** + * \brief Set the password in the URL authority. + * \param pass The new password. + * \param eflag If the \p password is encoded or not. + * \throws UrlNotAllowedException if the \p pass + * has to be empty in for the current scheme. + * \throws UrlBadComponentException if the \p pass + * contains an invalid character. + */ + virtual void + setPassword(const std::string &pass, + EEncoding eflag); + + /** + * \brief Set the hostname or IP in the URL authority. + * + * The \p host parameter may contain a hostname, an IPv4 address + * in dotted-decimal form or an IPv6 address literal encapsulated + * within square brackets (RFC3513, Sect. 2.2). + * + * A hostname may contain national alphanumeric UTF8 characters + * (letters other than ASCII a-zA-Z), that will be encoded. + * This function allows to specify both, a encoded or decoded + * hostname. + * + * Other IP literals in "[v ... ]" square bracket format are not + * supported by the implementation in UrlBase class. + * + * \param host The new hostname or IP address. + * \throws UrlNotAllowedException if the \p host + * has to be empty in for the current scheme. + * \throws UrlBadComponentException if the \p host is invalid. + */ + virtual void + setHost(const std::string &host); + + /** + * \brief Set the port number in the URL authority. + * \param port The new port number. + * \throws UrlNotAllowedException if the \p port + * has to be empty in for the current scheme. + * \throws UrlBadComponentException if the \p port is invalid. + */ + virtual void + setPort(const std::string &port); + + + // ----------------- + /** + * \brief Set the path data component in the URL. + * + * By default, the \p pathdata string may include path + * parameters separated by the ";" separator character. + * + * \param pathdata The encoded path data component string. + * \throws UrlBadComponentException if the \p pathdata + * contains an invalid character. + */ + virtual void + setPathData(const std::string &pathdata); + + /** + * \brief Set the path name. + * \param path The new path name. + * \param eflag If the \p path name is encoded or not. + * \throws UrlBadComponentException if the \p path name + * contains an invalid character. + */ + virtual void + setPathName(const std::string &path, + EEncoding eflag); + + /** + * \brief Set the path parameters. + * \param params The new encoded path parameter string. + * \throws UrlBadComponentException if the path \p params + * contains an invalid character. + */ + virtual void + setPathParams(const std::string ¶ms); + + /** + * \brief Set the path parameters. + * \param pvec The vector with encoded path parameters. + * \throws UrlBadComponentException if the \p pvec + * contains an invalid character. + */ + virtual void + setPathParamsVec(const zypp::url::ParamVec &pvec); + + /** + * \brief Set the path parameters. + * \param pmap The map with decoded path parameters. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + */ + virtual void + setPathParamsMap(const zypp::url::ParamMap &pmap); + + /** + * \brief Set or add value for the specified path parameter. + * \param param The decoded path parameter name. + * \param value The decoded path parameter value. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual void + setPathParam(const std::string ¶m, const std::string &value); + + + // ----------------- + /** + * \brief Set the query string in the URL. + * + * The \p querystr string parameter is supposed + * to not to contain the "?" URL query separator + * character (use just a "foo=bar&x=22" instead + * of "?foo=bar&x=22"). + * + * \param querystr The new encoded query string. + * \throws UrlBadComponentException if the \p querystr + * contains an invalid character. + */ + virtual void + setQueryString(const std::string &querystr); + + /** + * \brief Set the query parameters. + * \param qvec The vector with encoded query parameters. + * \throws UrlBadComponentException if the \p qvec + * contains an invalid character. + */ + virtual void + setQueryStringVec(const zypp::url::ParamVec &qvec); + + /** + * \brief Set the query parameters. + * \param qmap The map with decoded query parameters. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + */ + virtual void + setQueryStringMap(const zypp::url::ParamMap &qmap); + + /** + * \brief Set or add value for the specified query parameter. + * \param param The decoded query parameter name. + * \param value The decoded query parameter value. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual void + setQueryParam(const std::string ¶m, const std::string &value); + + /** + * \brief remove the specified query parameter. + * \param param The decoded query parameter name. + * \throws UrlNotSupportedException if parameter parsing + * is not supported for a URL (scheme). + * \throws UrlDecodingException if the decoded result string + * would contain a '\\0' character. + */ + virtual void + delQueryParam(const std::string ¶m); + + + // ----------------- + /** + * \brief Set the fragment string in the URL. + * \param fragment The new fragment string. + * \param eflag If the \p fragment is encoded or not. + * \throws UrlBadComponentException if the \p querystr + * contains an invalid character. + */ + virtual void + setFragment(const std::string &fragment, + EEncoding eflag); + + + // ----------------- + /** + * Configures behaviour of the instance. + * + * This method is called in UrlBase constructors before + * any URL components are applied. + * Derived classes may reimplement this method to change + * the behaviour of the object. + * Use the config() methods to query and change them. + * + * The UrlBase class uses following config variables: + * + * - Common path parameter separators: + * - \a \c sep_pathparams \c ";" + * Separator used to split path parameters from path name. + * Setting it to empty string disables splitting of path + * name and path parameters. Set also rx_pathparams to an + * empty string. + * - \a \c psep_pathparam \c "," + * Separator between path parameters. + * - \a \c vsep_pathparam \c "=" + * Separator between key and value of a path parameter. + * . + * . + * + * - Common query string separators: + * - \a \c psep_querystr \c "&" + * Separator between query string parameters. + * - \a \c vsep_querystr \c "=" + * Separator between key and value of a query parameter. + * . + * . + * + * - Characters in URL components, that are safe without + * URL percent-encoding (see zypp::url::encode()). + * - \a safe_username + * - \a safe_password + * - \a safe_hostname + * - \a safe_pathname + * - \a safe_pathparams + * - \a safe_querystr + * - \a safe_fragment + * . + * . + * + * - Regular expressions used to verify encoded URL + * components and their sub-components: + * - \a rx_username + * - \a rx_password + * - \a rx_pathname + * - \a rx_pathparams + * - \a rx_querystr + * - \a rx_fragment + * . + * . + */ + virtual void + configure(); + + + /** + * Get the value of a UrlBase configuration variable. + * + * See configure() method for names an purpose of the + * configuration variables used in UrlBase class. + * + * \param opt The name of the configuration variable. + * \return The value of the specified variable + * or empty string. + */ + std::string + config(const std::string &opt) const; + + /** + * Set the value of a UrlBase configuration variable. + * + * See configure() method for names an purpose of the + * configuration variables used in UrlBase class. + * + * \param opt The name of the configuration variable. + * \param val The new value for the configuration variable. + */ + void + config(const std::string &opt, const std::string &val); + + + /** + * Return the view options of the current object. + * + * This method is used to query the view options + * used by the asString() method. + * + * \return The current view option combination. + */ + ViewOptions + getViewOptions() const; + + /** + * Change the view options of the current object. + * + * This method is used to change the view options + * used by the asString() method. + * + * \param vopts New view options combination. + */ + void + setViewOptions(const ViewOptions &vopts); + + std::string asString1050625() const; + protected: + /** + * Utility method to cleanup an encoded path name. + * + * By default, this method makes sure, that the first slash + * in the path is not encoded, and that the second slash + * before the first path segment, is encoded (to "%2F"). + * It modifies the path in the url, for example: + * "ftp://host//aaa//bbb" to "ftp://host/%2Faaa//bbb" + * or as encoded path only also "%2f/name" to "/%2fname". + * + * This operation is required to fulfill the path-absolute + * rule of RFC3986, if there is no authority. It avoids the + * missinterpretation of the path as an authority separator. + * + * It is not required if there is an authority ("//" behind + * the "scheme:"), that is in the path-abempty rule, but it + * is used e.g. in ftp url's defined by RFC1738. + * + * We apply this operation in both cases (for all paths), + * but if \p authority is true, the encoding of the second + * slash depends on the schema configuration (for ftp only). + * + * \param path The encoded path name to cleanup. + * \param authority Whether the url contains authority or not. + * \return A modified encoded path. + */ + virtual std::string + cleanupPathName(const std::string &path, bool authority) const; + + /** + * Utility method to cleanup an encoded path name. + * + * This variant of the method checks if the host component + * in the url is empty or not to differentiate if there is + * an authority. + * + * \param path The encoded path name to cleanup. + * \return A modified encoded path. + */ + virtual std::string + cleanupPathName(const std::string &path) const; + + /** + * \brief Verifies specified host or IP. + * + * It verifies, if the specified \p host parameter contains + * a hostname, an IPv4 address in dotted-decimal form or an + * IPv6 address literal encapsulated within square brackets + * (RFC3513, Sect. 2.2). + * + * A hostname in the \p host parameter, may contain national + * alphanumeric UTF8 characters (letters other than ASCII + * a-zA-Z) and allows to specify both, a encoded or decoded + * hostname. + * + * This function does not perform any hostname lookups and + * supports only IPv6 addresses in "[ ... ]" notation. The + * "[v ... ]" square bracket format is not supported by + * this implementation. + * + * \param host The host name or IP to verify. + * \return True, if host seems to be valid. + */ + virtual bool + isValidHost(const std::string &host) const; + + /** + * \brief Verifies specified port number. + * + * \param port The port number to verify. + * \return True, if port number is valid. + */ + virtual bool + isValidPort(const std::string &port) const; + + private: + UrlBaseData *m_data; + }; + + + // --------------------------------------------------------------- + /** + * \brief Copy-On-Write Url reference. + */ + using UrlRef = RWCOW_pointer; + + + ////////////////////////////////////////////////////////////////// + } // namespace url + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// + +#endif /* ZYPP_URL_URLBASE_H */ +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp-core/url/UrlException.h b/zypp-core/url/UrlException.h new file mode 100644 index 0000000..9e6864e --- /dev/null +++ b/zypp-core/url/UrlException.h @@ -0,0 +1,150 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/url/UrlException.h + */ +#ifndef ZYPP_URL_URLEXCEPTION_H +#define ZYPP_URL_URLEXCEPTION_H + +#include + + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + namespace url + { ////////////////////////////////////////////////////////////////// + + + // --------------------------------------------------------------- + /** + * Base class for all URL exceptions. + */ + class ZYPP_API UrlException: public zypp::Exception + { + public: + UrlException() + : zypp::Exception("Url exception") + {} + + UrlException(const std::string &msg) + : zypp::Exception(msg) + {} + + ~UrlException() throw() override {}; + }; + + // --------------------------------------------------------------- + /** + * Thrown if the encoded string contains a NUL byte (%00). + */ + class ZYPP_API UrlDecodingException: public UrlException + { + public: + UrlDecodingException() + : UrlException("Url NUL decoding exception") + {} + + UrlDecodingException(const std::string &msg) + : UrlException(msg) + {} + + ~UrlDecodingException() throw() override {}; + }; + + // --------------------------------------------------------------- + /** + * Thrown if the url or a component can't be parsed at all. + */ + class ZYPP_API UrlParsingException: public UrlException + { + public: + UrlParsingException() + : UrlException("Url parsing failure exception") + {} + + UrlParsingException(const std::string &msg) + : UrlException(msg) + {} + + ~UrlParsingException() throw() override {}; + }; + + // --------------------------------------------------------------- + /** + * Thrown if a url component is invalid. + */ + class ZYPP_API UrlBadComponentException: public UrlException + { + public: + UrlBadComponentException() + : UrlException("Url bad component exception") + {} + + UrlBadComponentException(const std::string &msg) + : UrlException(msg) + {} + + ~UrlBadComponentException() throw() override {}; + }; + + + // --------------------------------------------------------------- + /** + * Thrown if scheme does not allow a component. + */ + class ZYPP_API UrlNotAllowedException: public UrlException + { + public: + UrlNotAllowedException() + : UrlException("Url not allowed component exception") + {} + + UrlNotAllowedException(const std::string &msg) + : UrlException(msg) + {} + + ~UrlNotAllowedException() throw() override {}; + }; + + + // --------------------------------------------------------------- + /** + * Thrown if a feature e.g. parsing of a component + * is not supported for the url/scheme. + */ + class ZYPP_API UrlNotSupportedException: public UrlException + { + public: + UrlNotSupportedException() + : UrlException("Url parsing unsupported exception") + {} + + UrlNotSupportedException(const std::string &msg) + : UrlException(msg) + {} + + ~UrlNotSupportedException() throw() override {}; + }; + + + ////////////////////////////////////////////////////////////////// + } // namespace url + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// + +#endif /* ZYPP_URL_URLEXCEPTION_H */ +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp-core/url/UrlUtils.cc b/zypp-core/url/UrlUtils.cc new file mode 100644 index 0000000..fbb253c --- /dev/null +++ b/zypp-core/url/UrlUtils.cc @@ -0,0 +1,326 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/url/UrlUtils.cc + */ +#include +#include +#include + +#include // strtol +#include // isxdigit +#include + + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + namespace url + { ////////////////////////////////////////////////////////////////// + + + // --------------------------------------------------------------- + std::string + encode(const std::string &str, const std::string &safe, + EEncoding eflag) + { + std::string skip("ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789.~_-"); + static const std::string more(URL_SAFE_CHARS); // ":/?#[]@!$&'()*+,;=" + size_t beg = 0, pos = 0, len = 0; + std::string out; + + for(size_t i=0; i beg) + { + out.append(str, beg, pos - beg); + } + + if( eflag == E_ENCODED && + pos + 2 < len && + str.at(pos) == '%' && + std::isxdigit(str.at(pos + 1)) && + std::isxdigit(str.at(pos + 2))) + { + out.append(str, pos, 3); + beg = pos + 3; + } + else + { + out.append( encode_octet( str.at(pos))); + beg = pos + 1; + } + } + else + { + out.append(str, beg, len - beg); + beg = len; + } + } + return out; + } + + + // --------------------------------------------------------------- + std::string + decode(const std::string &str, bool allowNUL) + { + size_t pos = 0, end = 0, len = 0; + std::string out(str); + + len = out.length(); + pos = end = 0; + while(pos < len) + { + out[end] = out[pos]; + if( pos + 2 < len && out.at(pos) == '%') + { + int c = decode_octet(out.c_str() + pos + 1); + switch(c) + { + case -1: + // not a hex noted octet... + break; + + case 0: + // is a %00 octet allowed ? + if( !allowNUL) + { + ZYPP_THROW(UrlDecodingException( + _("Encoded string contains a NUL byte") + )); + } + default: + // other octets are fine... + out[end] = c; + pos += 2; + break; + } + } + pos++; + end++; + } + if( end < pos) + out.erase(end); + return out; + } + + + // --------------------------------------------------------------- + std::string + encode_octet(const unsigned char c) + { + static const unsigned char tab[] = "0123456789ABCDEF"; + unsigned char out[4]; + + out[0] = '%'; + out[1] = tab[0x0f & (c >> 4)]; + out[2] = tab[0x0f & c]; + out[3] = '\0'; + + //snprintf(out, sizeof(out), "%%%02X", c); + return std::string((char *)out); + } + + + // --------------------------------------------------------------- + int + decode_octet(const char *hex) + { + if(hex && std::isxdigit(hex[0]) && std::isxdigit(hex[1])) + { + char x[3] = { hex[0], hex[1], '\0'}; + return 0xff & ::strtol(x, NULL, 16); + } + else + { + return -1; + } + } + + + // --------------------------------------------------------------- + void + split(ParamVec &pvec, + const std::string &pstr, + const std::string &psep) + { + size_t beg = 0, pos = 0, len = 0; + if( psep.empty()) + { + ZYPP_THROW(UrlNotSupportedException( + _("Invalid parameter array split separator character") + )); + } + + len = pstr.length(); + beg = 0; + + while( beg < len) + { + pos = pstr.find(psep, beg); + if(pos != std::string::npos) + { + pvec.push_back( pstr.substr(beg, pos - beg)); + beg = pos + 1; + } + else + { + pvec.push_back( pstr.substr(beg, len - beg)); + beg = len; + } + } + } + + + // --------------------------------------------------------------- + void + split(ParamMap &pmap, + const std::string &str, + const std::string &psep, + const std::string &vsep, + EEncoding eflag) + { + ParamVec pvec; + ParamVec::const_iterator pitr; + std::string k, v; + size_t pos = 0; + + if( psep.empty() || vsep.empty()) + { + ZYPP_THROW(UrlNotSupportedException( + _("Invalid parameter map split separator character") + )); + } + + split(pvec, str, psep); + + for( pitr = pvec.begin(); pitr != pvec.end(); ++pitr) + { + pos = pitr->find(vsep); + if(pos != std::string::npos) + { + if( eflag == E_DECODED) + { + k = url::decode(pitr->substr(0, pos)); + v = url::decode(pitr->substr(pos + 1)); + pmap[ k ] = v; + } + else + { + k = pitr->substr(0, pos); + v = pitr->substr(pos + 1); + pmap[ k ] = v; + } + } + else + { + if( eflag == E_DECODED) + { + pmap[ url::decode(*pitr) ] = ""; + } + else + { + pmap[ *pitr ] = ""; + } + } + } + } + + + // --------------------------------------------------------------- + std::string + join(const ParamVec &pvec, + const std::string &psep) + { + std::string str; + ParamVec::const_iterator i( pvec.begin()); + + if( i != pvec.end()) + { + str = *i; + while( ++i != pvec.end()) + { + str += psep + *i; + } + } + + return str; + } + + + // --------------------------------------------------------------- + std::string + join(const ParamMap &pmap, + const std::string &psep, + const std::string &vsep, + const std::string &safe) + { + if( psep.empty() || vsep.empty()) + { + ZYPP_THROW(UrlNotSupportedException( + _("Invalid parameter array join separator character") + )); + } + + std::string join_safe; + for(std::string::size_type i=0; ifirst, join_safe); + if( !i->second.empty()) + str += vsep + encode(i->second, join_safe); + + while( ++i != pmap.end()) + { + str += psep + encode(i->first, join_safe); + if( !i->second.empty()) + str += vsep + encode(i->second, join_safe); + } + } + + return str; + } + + + ////////////////////////////////////////////////////////////////// + } // namespace url + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp-core/url/UrlUtils.h b/zypp-core/url/UrlUtils.h new file mode 100644 index 0000000..8eee988 --- /dev/null +++ b/zypp-core/url/UrlUtils.h @@ -0,0 +1,261 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/url/UrlUtils.h + */ +#ifndef ZYPP_URL_URLUTILS_H +#define ZYPP_URL_URLUTILS_H + +#include + +#include +#include +#include + +/** Characters that are safe for URL without percent-encoding. */ +#define URL_SAFE_CHARS ":/?#[]@!$&'(){}*+,;=" + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + /** Url details namespace. */ + namespace url + { ////////////////////////////////////////////////////////////////// + + + // --------------------------------------------------------------- + /** A parameter vector container. + * A string vector containing splited PathParam- or Query-String. + * Each string in the vector is allways URL percent encoded and + * usually contains a "key=value" pair. + */ + using ParamVec = std::vector; + + + /** A parameter map container. + * A map containing key and value pairs parsed from a PathParam- + * or Query-String. + */ + using ParamMap = std::map; + + + /** Encoding flags. + */ + typedef enum { + E_ENCODED, //!< Flag to request encoded string(s). + E_DECODED //!< Flag to request decoded string(s). + } EEncoding; + + + // --------------------------------------------------------------- + /** Encodes a string using URL percent encoding. + * + * By default, all characters except of "a-zA-Z0-9_.-" will be encoded. + * Additional characters from the set ":/?#[]@!$&'()*+,;=", that are + * safe for a URL compoent without encoding, can be specified in the + * \p safe argument. + * + * If the \p eflag parameter is set to E_ENCODED, then already encoded + * substrings will be detected and not encoded a second time. + * + * The following function call will encode the "@" character as "%40", + * but skip encoding of the "%" character, because the \p eflag is set + * to E_ENCODED and "%ba" is detected as a valid encoded character. + * \code + * zypp::url::encode("foo%bar@localhost", "", E_ENCODED); + * \endcode + * With \p eflag set to E_DECODED, the "%" character would be encoded + * as well. The complete encoded string would be "foo%25bar%40localhost". + * + * \param str A string to encode (binary data). + * \param safe Characters safe to skip in encoding, + * e.g. "/" for path names. + * \param eflag If to detect and skip already encoded substrings. + * \return A percent encoded string. + */ + std::string + encode(const std::string &str, const std::string &safe = "", + EEncoding eflag = E_DECODED) ZYPP_API; + + + // --------------------------------------------------------------- + /** Decodes a URL percent encoded string. + * Replaces all occurences of \c "%" in the \p str string + * with the character encoded using the two hexadecimal digits that + * follows the "%" character. + * + * For example, the encoded string "%40%3F%3D%26%25" will be decoded + * to "@?=&%". + * + * \param str A string to decode. + * \param allowNUL A flag, if \c "%00" (encoded \c '\\0') + * is allowed or not. + * \return A decoded strig (may contain binary data). + * \throws UrlDecodingException if \p allowNUL is false and + * a encoded NUL byte (\c "%00") was found in \p str. + */ + std::string + decode(const std::string &str, bool allowNUL = false) ZYPP_API; + + + // --------------------------------------------------------------- + /** Encode one character. + * + * Encode the specified character \p c into its \c "%" + * representation. + * + * \param c A character to encode. + * \return A percent encoded representation of the character, + * e.g. %20 for a ' ' (space). + */ + std::string + encode_octet(const unsigned char c) ZYPP_API; + + + // --------------------------------------------------------------- + /** Decode one character. + * + * Decode the \p hex parameter pointing to (at least) two hexadecimal + * digits into its character value and return it. + * + * Example: + * \code + * char *str = "%40"; + * char *pct = strchr(str, '%'); + * int chr = pct ? decode_octet(pct+1) : -1; + * // chr is set to the '@' ASCII character now. + * \endcode + * + * \param hex Pointer to two hex characters representing + * the character value in percent-encoded strings. + * \return The value (0-255) encoded in the \p hex characters or -1 + * if \p hex does not point to two hexadecimal characters. + */ + int + decode_octet(const char *hex) ZYPP_API; + + + // --------------------------------------------------------------- + /** Split into a parameter vector. + * + * Splits a parameter string \p pstr into substrings using \p psep + * as separator and appends the resulting substrings to \p pvec. + * + * Usual parameter separators are \c '&' for Query- and \c ',' for + * PathParam-Strings. + * + * \param pvec Reference to a result parameter vector. + * \param pstr Reference to the PathParam- or Query-String to split. + * \param psep Parameter separator character to split at. + * \throws UrlNotSupportedException if \p psep separator is empty. + */ + void + split(ParamVec &pvec, + const std::string &pstr, + const std::string &psep); + + + // --------------------------------------------------------------- + /** Split into a parameter map. + * + * Splits a parameter string \p pstr into substrings using \p psep as + * separator and then, each substring into key and value pair using + * \p vsep as separator between parameter key and value and adds them + * to the parameter map \p pmap. + * + * If a parameter substring doesn't contain any value separator \p vsep, + * the substring is used as a parameter key and value is set to an empty + * string. + * + * Usual parameter separators are \c '&' for Query- and \c ',' for + * PathParam-Strings. A usual parameter-value separator is \c '=' for + * both, Query- and PathParam-Strings. + * + * If the encoding flag \p eflag is set to \p E_DECODED, then the key + * and values are dedcoded before they are stored in the map. + * + * \param pmap Reference to a result parameter map. + * \param pstr Reference to the PathParam- or Query-String to split. + * \param psep Separator character to split key-value pairs. + * \param vsep Separator character to split key and value. + * \param eflag Flag if the key and value strings should be URL percent + * decoded before they're stored in the map. + * \throws UrlNotSupportedException if \p psep or \p vsep separator + * is empty. + */ + void + split(ParamMap &pmap, + const std::string &pstr, + const std::string &psep, + const std::string &vsep, + EEncoding eflag = E_ENCODED); + + + // --------------------------------------------------------------- + /** Join parameter vector to a string. + * + * Creates a string containing all substrings from the \p pvec separated + * by \p psep separator character. The substrings in \p pvec should be + * already URL percent encoded and should't contain \p psep characters. + * + * Usual parameter separators are \c '&' for Query- and \c ',' for + * PathParam-Strings. + * + * \param pvec Reference to encoded parameter vector. + * \param psep Parameter separator character to use. + * \return A parameter string. + */ + std::string + join(const ParamVec &pvec, + const std::string &psep); + + + // --------------------------------------------------------------- + /** Join parameter map to a string. + * + * Creates a string containing all parameter key-value pairs from the + * parameter map \p pmap, that will be joined using the \p psep character + * and the parameter key is separated from the parameter value using the + * \p vsep character. Both, key and value will be automatically encoded. + * + * Usual parameter separators are \c '&' for Query- and \c ',' for + * PathParam-Strings. A usual parameter-value separator is \c '=' for + * both, Query- and PathParam-Strings. + * + * See encode() function from details about the \p safe characters. + * + * \param pmap Reference to a parameter map. + * \param psep Separator character to use between key-value pairs. + * \param vsep Separator character to use between keys and values. + * \param safe List of characters to accept without encoding. + * \return A URL percent-encoded parameter string. + * \throws UrlNotSupportedException if \p psep or \p vsep separator + * is empty. + */ + std::string + join(const ParamMap &pmap, + const std::string &psep, + const std::string &vsep, + const std::string &safe); + + + ////////////////////////////////////////////////////////////////// + } // namespace url + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// + +#endif /* ZYPP_URL_URLUTILS_H */ +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp-core/zyppng/async/AsyncOp b/zypp-core/zyppng/async/AsyncOp new file mode 100644 index 0000000..a3dadb9 --- /dev/null +++ b/zypp-core/zyppng/async/AsyncOp @@ -0,0 +1 @@ +#include "asyncop.h" diff --git a/zypp-core/zyppng/async/asyncop.h b/zypp-core/zyppng/async/asyncop.h new file mode 100644 index 0000000..af56171 --- /dev/null +++ b/zypp-core/zyppng/async/asyncop.h @@ -0,0 +1,309 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_ASYNC_ASYNCOP_H_INCLUDED +#define ZYPPNG_ASYNC_ASYNCOP_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + template struct AsyncOp; + ZYPP_FWD_DECL_TYPE_WITH_REFS ( AsyncOpBase ); + + namespace detail { + template > + struct has_value_type : public std::false_type{}; + + template + struct has_value_type> : public std::true_type {}; + + template + constexpr bool has_value_type_v = has_value_type::value; + + template + struct is_asyncop_type : public std::false_type{}; + + template + struct is_asyncop_type*> >> : public std::true_type{}; + + template + constexpr bool is_asyncop_type_v = is_asyncop_type::value; + + /*! + * Detects if a type is a AsyncOp based type. This + * is required in cases where we can not use simple Argument type matching + * but need to decide on the type characteristics. For example when a AsyncOp is + * passed as callback argument in the pipelines. + */ + template + using is_async_op = std::conjunction< + has_value_type>, + is_asyncop_type > + >; + + template < typename T> + constexpr bool is_async_op_v = is_async_op::value; + } + + /*! + * Thrown if code tries to access the result of a async operation + * that is not ready. + */ + class AsyncOpNotReadyException : public zypp::Exception + { + public: + AsyncOpNotReadyException() + : Exception( "AsyncOp instance not ready" ) + {} + ~AsyncOpNotReadyException() override; + }; + inline AsyncOpNotReadyException::~AsyncOpNotReadyException() { } + + class CancelNotImplementedException : public zypp::Exception + { + public: + CancelNotImplementedException() + : Exception ("AsyncOp does not support cancelling the operation") + {} + ~CancelNotImplementedException() override; + }; + inline CancelNotImplementedException::~CancelNotImplementedException() { } + + + class AsyncOpBase : public Base { + + public: + + /*! + * Should return true if the async op supports cancelling, otherwise false + */ + virtual bool canCancel () { + return false; + } + + /*! + * Explicitely cancels the async operation if it supports that, + * otherwise throws a \ref CancelNotImplementedException + * + * Generally every AsyncOp HAS TO support cancelling by releasing the last reference + * to it, however in some special cases we need to be able to cancel programatically + * from the backends and notify the frontends by returning a error from a AsyncOp. + */ + virtual void cancel () { + throw CancelNotImplementedException(); + } + + /*! + * Signal that is emitted once the AsyncOp is started + */ + SignalProxy sigStarted () { + return _sigStarted; + } + + /*! + * Signal that might be emitted during operation of the AsyncOp, + * not every AsyncOp will use this + */ + SignalProxy sigProgress () { + return _sigProgress; + } + + /*! + * Signal that is emitted once the AsyncOp is ready and no + * callback was registered with \ref onReady + */ + SignalProxy sigReady () { + return _sigReady; + } + + protected: + Signal _sigStarted; + Signal _sigReady; + Signal _sigProgress; + }; + + /*! + *\class AsyncOp + * The \a AsyncOp template class is the basic building block for the asynchronous pipelines. + * Its the base for all async callbacks as well as the async result type. That basically means + * every pipeline is just a AsyncOp that contains all previous operations that were defined in the pipeline. + * + * When implementing a async operation that is to be used in a pipeline it is required to add a operator() to the class taking the + * input parameter. After the operation is finished the implementation must call setReady(). Calling + * setReady() must be treated like calling return in a normal function and not execute anymore code on the + * AsyncOp instance afterwards, since the next operation in the pipeline is allowed to free the previous operation + * as soon as it gets ready. + * + * In case no next operation is defined on the AsyncOp ( when the instance is used as result object ) the return value + * is cached internally and can be retrieved with \sa get(). + * + * A async operation can be cancelled by releasing the result object ( the resulting combinatory object ), this will + * destroy all previous operations that are either running or pending as well. The destructors MUST NOT call setReady() but + * only release currently running operations. + */ + template + struct AsyncOp : public AsyncOpBase { + + static_assert(!detail::is_async_op_v, "A async op can never have a async result"); + + using value_type = Result; + using Ptr = std::shared_ptr>; + + AsyncOp () = default; + + AsyncOp ( const AsyncOp &other ) = delete; + AsyncOp& operator= ( const AsyncOp &other ) = delete; + + AsyncOp& operator= ( AsyncOp &&other ) noexcept = default; + AsyncOp ( AsyncOp &&other ) noexcept = default; + + ~AsyncOp() override{} + + /*! + * Sets the async operation ready, in case a callback + * is registered the \a val is directly forwarded without + * storing it. + */ + void setReady ( value_type && val ) { + if ( _readyCb ) { + // use a weak reference to know if `this` was deleted by the callback() + auto weak = weak_from_this(); + _readyCb( std::move( val ) ); + if ( !weak.expired() ) + _readyCb = {}; + } + else { //we need to cache the value because no callback is available + _maybeValue = std::move(val); + _sigReady.emit(); + } + } + + /*! + * Checks if the async operation already has finished. + * + * \note This can only be used when no callback is registered. + */ + bool isReady () const { + return _maybeValue.has_value(); + } + + /*! + * Registeres a callback that is immediately called + * when the object gets into ready state. In case the + * object is in ready state when registering the callback + * it is called right away. + * \note this will disable the emitting of sigReady() so it should + * be only used by the pipeline implementation + * + * \note the callback is removed from the AsyncOp after it was executed + * when the AsyncOp becomes ready + */ + template< typename Fun > + void onReady ( Fun &&cb ) { + this->_readyCb = std::forward(cb); + + if ( isReady() ) { + // use a weak reference to know if `this` was deleted by the callback() + auto weak = weak_from_this(); + + _readyCb( std::move( _maybeValue.value()) ); + + if ( !weak.expired() ) { + // value was passed on, reset the optional + _maybeValue.reset(); + + // reset the callback, it might be a lambda with captured ressources + // that need to be released after returning from the func + _readyCb = {}; + } + } + } + + /*! + * Returns the internally cached value if there is one. + * \throws AsyncOpNotReadyException if called before the operation is ready + */ + value_type &get (){ + if ( !isReady() ) + ZYPP_THROW(AsyncOpNotReadyException()); + return _maybeValue.value(); + } + + private: + std::function _readyCb; + std::optional _maybeValue; + }; + + + template + using AsyncOpRef = std::shared_ptr>; + + + /*! + * Helper mixin for AsyncOp types that host a inner pipeline for + * their logic. This is useful if a lot of state has to be preserved + * over a longer pipeline, instead of capturing all the seperate + * variables into the lambda callbacks it makes more sense to + * use a containing AsyncOp to help with it. + */ + template + struct NestedAsyncOpMixin + { + template + void operator ()( Args &&...args ) { + assert(!_nestedPipeline); + _nestedPipeline = static_cast(this)->makePipeline( std::forward(args)...); + _nestedPipeline->onReady([this]( auto &&val ){ + static_cast(this)->setReady( std::forward(val) ); + }); + } + + private: + AsyncOpRef _nestedPipeline; + }; + + namespace detail { + //A async result that is ready right away + template + struct ReadyResult : public zyppng::AsyncOp< T > + { + ReadyResult( T &&val ) { + this->setReady( std::move(val) ); + } + }; + } + + /*! + * Is \a isAsync is true returns a \ref AsyncOpRef that is always ready, containing the \a result as + * its final value, otherwise the value passed to the function is just forwarded. + */ + template + std::conditional_t, T> makeReadyResult ( T && result ) { + if constexpr ( isAsync ) { + return std::make_shared>( std::forward(result) ); + } else { + return result; + } + } + +} + + + +#endif diff --git a/zypp-core/zyppng/base/AbstractEventSource b/zypp-core/zyppng/base/AbstractEventSource new file mode 100644 index 0000000..9a0facb --- /dev/null +++ b/zypp-core/zyppng/base/AbstractEventSource @@ -0,0 +1 @@ +#include "abstracteventsource.h" diff --git a/zypp-core/zyppng/base/AutoDisconnect b/zypp-core/zyppng/base/AutoDisconnect new file mode 100644 index 0000000..3e47aa5 --- /dev/null +++ b/zypp-core/zyppng/base/AutoDisconnect @@ -0,0 +1 @@ +#include "autodisconnect.h" diff --git a/zypp-core/zyppng/base/Base b/zypp-core/zyppng/base/Base new file mode 100644 index 0000000..afd9123 --- /dev/null +++ b/zypp-core/zyppng/base/Base @@ -0,0 +1 @@ +#include "base.h" diff --git a/zypp-core/zyppng/base/EventDispatcher b/zypp-core/zyppng/base/EventDispatcher new file mode 100644 index 0000000..f13f93f --- /dev/null +++ b/zypp-core/zyppng/base/EventDispatcher @@ -0,0 +1 @@ +#include "eventdispatcher.h" diff --git a/zypp-core/zyppng/base/EventLoop b/zypp-core/zyppng/base/EventLoop new file mode 100644 index 0000000..4dd8ff3 --- /dev/null +++ b/zypp-core/zyppng/base/EventLoop @@ -0,0 +1 @@ +#include "eventloop.h" diff --git a/zypp-core/zyppng/base/Signals b/zypp-core/zyppng/base/Signals new file mode 100644 index 0000000..454a495 --- /dev/null +++ b/zypp-core/zyppng/base/Signals @@ -0,0 +1 @@ +#include "signals.h" diff --git a/zypp-core/zyppng/base/SocketNotifier b/zypp-core/zyppng/base/SocketNotifier new file mode 100644 index 0000000..8b5f5a9 --- /dev/null +++ b/zypp-core/zyppng/base/SocketNotifier @@ -0,0 +1 @@ +#include "socketnotifier.h" diff --git a/zypp-core/zyppng/base/Timer b/zypp-core/zyppng/base/Timer new file mode 100644 index 0000000..165e4e1 --- /dev/null +++ b/zypp-core/zyppng/base/Timer @@ -0,0 +1 @@ +#include "timer.h" diff --git a/zypp-core/zyppng/base/UnixSignalSource b/zypp-core/zyppng/base/UnixSignalSource new file mode 100644 index 0000000..21d71bb --- /dev/null +++ b/zypp-core/zyppng/base/UnixSignalSource @@ -0,0 +1 @@ +#include "unixsignalsource.h" diff --git a/zypp-core/zyppng/base/abstracteventsource.cc b/zypp-core/zyppng/base/abstracteventsource.cc new file mode 100644 index 0000000..b30b1e9 --- /dev/null +++ b/zypp-core/zyppng/base/abstracteventsource.cc @@ -0,0 +1,62 @@ +#include "abstracteventsource.h" +#include "private/abstracteventsource_p.h" +#include "eventdispatcher.h" +#include "private/base_p.h" + +#include + +namespace zyppng { + +AbstractEventSourcePrivate::AbstractEventSourcePrivate( AbstractEventSource &p ) : BasePrivate( p ) +{ + auto ev = EventDispatcher::instance(); + if ( !ev ) + ZYPP_THROW( zypp::Exception( "Creating event sources without a EventDispatcher instance is not supported" ) ); + _ev = ev; +} + +ZYPP_IMPL_PRIVATE(AbstractEventSource) + +AbstractEventSource::AbstractEventSource() + : Base ( * new AbstractEventSourcePrivate( *this ) ) +{ } + +AbstractEventSource::AbstractEventSource( AbstractEventSourcePrivate &dd ) + : Base ( dd ) +{ } + +AbstractEventSource::~AbstractEventSource() +{ + Z_D(); + auto ev = d->_ev.lock(); + //if ev is null , eventloop is shutting down + if ( ev ) + ev->removeEventSource( *this ); +} + +std::weak_ptr AbstractEventSource::eventDispatcher() const +{ + return d_func()->_ev; +} + +void AbstractEventSource::updateFdWatch(int fd, int mode) +{ + auto ev = d_func()->_ev.lock(); + + //if ev is null we are shutting down + if ( !ev ) + return; + ev->updateEventSource( *this, fd, mode ); +} + +void AbstractEventSource::removeFdWatch(int fd) +{ + auto ev = d_func()->_ev.lock(); + + //if ev is null we are shutting down + if ( !ev ) + return; + ev->removeEventSource( *this , fd ); +} + +} diff --git a/zypp-core/zyppng/base/abstracteventsource.h b/zypp-core/zyppng/base/abstracteventsource.h new file mode 100644 index 0000000..109dbdc --- /dev/null +++ b/zypp-core/zyppng/base/abstracteventsource.h @@ -0,0 +1,92 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_BASE_ABSTRACTEVENTSOURCE_H_INCLUDED +#define ZYPP_NG_BASE_ABSTRACTEVENTSOURCE_H_INCLUDED + +#include +#include +#include + +namespace zyppng { + +class EventDispatcher; +class AbstractEventSourcePrivate; + +/*! + * The AbstractEventSource class is the base class for all objects that can + * be tracked using one or more file descriptors + * + * A subclass can register multiple file descriptors to be tracked using + * \a updateFdWatch and remove them with \a removeFdWatch. This is internally + * forwarded to the \sa EventDispatcher belonging to the \a AbstractEventSource. + * + * In case there is activity on the file descriptor the EventDispatcher wakes up + * and forwards it to \a onFdReady. + */ +class LIBZYPP_NG_EXPORT AbstractEventSource : public Base +{ + ZYPP_DECLARE_PRIVATE(AbstractEventSource) +public: + + /*! + * The different types of events a AbstractEventSource can + * listen for. + */ + enum EventTypes { + Read = 0x01, //< The fd is ready to read data without blocking + Write = 0x02, //< The fd has written pending data + Exception = 0x04, //< A exception has happend on the fd + Error = 0x08 //< There was a error polling the fd + }; + + AbstractEventSource(); + AbstractEventSource( AbstractEventSourcePrivate &dd ); + ~AbstractEventSource() override; + + /*! + * Returns the \sa EventDispatcher that takes care of this event source + */ + std::weak_ptr eventDispatcher () const; + + /*! + * Called by the \sa EventDispatcher when activity was detected + * on a registered \a fd. The \a events are set according to the activity + * on the file descriptor. + */ + virtual void onFdReady ( int fd, int events ) = 0; + + /*! + * Called when a event source has registered to receive unix signals + * \note this is not supported yet + */ + virtual void onSignal ( int signal ) = 0; + +protected: + /*! + * Register or update a file descriptor poll mode. + * \param fd The fd to add or update to the watchlist of the \sa EventDispatcher + * \param mode The watchmode used in the watchlist \sa EventTypes + */ + void updateFdWatch ( int fd, int mode ); + + /*! + * Removes the given \a fd from the \sa EventDispatcher watchlist. + * After calling this no more events will be received by the object it was called on. + */ + void removeFdWatch ( int fd ); +}; + +} + +#endif diff --git a/zypp-core/zyppng/base/autodisconnect.h b/zypp-core/zyppng/base/autodisconnect.h new file mode 100644 index 0000000..1a1ae92 --- /dev/null +++ b/zypp-core/zyppng/base/autodisconnect.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#include + +namespace zyppng +{ + /*! + * This can be used to scope a signal/slot connection. + * Basically just like \sa zypp::AutoDispose + */ + struct AutoDisconnect + { + AutoDisconnect( connection &&conn ) : _conn ( std::move(conn) ) {} + AutoDisconnect( AutoDisconnect &&other ) noexcept : _conn ( std::move(other._conn) ) {} + + AutoDisconnect( const AutoDisconnect &other ) = delete; + AutoDisconnect & operator=( const AutoDisconnect & ) = delete; + + ~AutoDisconnect( ) { _conn.disconnect(); } + connection _conn; + }; + +} diff --git a/zypp-core/zyppng/base/base.cc b/zypp-core/zyppng/base/base.cc new file mode 100644 index 0000000..0497599 --- /dev/null +++ b/zypp-core/zyppng/base/base.cc @@ -0,0 +1,76 @@ +#include + +namespace zyppng { + + BasePrivate::~BasePrivate() + { } + + void BasePrivate::init() + { } + + ZYPP_IMPL_PRIVATE(Base) + + Base::Base ( BasePrivate &dd ) + : d_ptr ( &dd ) + { + d_ptr->z_ptr = this; + d_ptr->init(); + } + + Base::Base() : Base( *new BasePrivate(*this) ) + { } + + Base::~Base() + { } + + Base::WeakPtr Base::parent() const + { + return d_func()->parent; + } + + void Base::addChild( const Base::Ptr& child ) + { + Z_D(); + if ( !child ) + return; + + //we are already the parent + auto childParent = child->d_func()->parent.lock(); + if ( childParent.get() == this ) + return; + + if ( childParent ) { + childParent->removeChild( child ); + } + + d->children.insert( child ); + + auto tracker = this->weak_this(); + child->d_func()->parent = tracker; + } + + void Base::removeChild( const Base::Ptr& child ) + { + if ( !child ) + return; + + //we are not the child of this object + if ( child->d_func()->parent.lock().get() != this ) + return; + + Z_D(); + d->children.erase( child ); + child->d_func()->parent.reset(); + } + + const std::unordered_set &Base::children() const + { + return d_func()->children; + } + + std::thread::id Base::threadId() const + { + return d_func()->threadId; + } + +} // namespace zyppng diff --git a/zypp-core/zyppng/base/base.h b/zypp-core/zyppng/base/base.h new file mode 100644 index 0000000..bb3a2dd --- /dev/null +++ b/zypp-core/zyppng/base/base.h @@ -0,0 +1,196 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_BASE_BASE_H_INCLUDED +#define ZYPP_NG_BASE_BASE_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + class Base; + class BasePrivate; + + namespace internal { + template + struct MemberFunction; + + template + struct MemberFunction { + using ClassType = BType; + }; + + template + inline constexpr bool is_base_receiver = std::is_base_of_v || std::is_base_of_v; + + } + + /*! + * The Base class is used as a common base class for objects that emit signals, + * it also supports a parent/child relationship where the parent object keeps + * a reference for all its children. + * + * Generally, all objects that want to send or receive signals should derive from Base, since it + * will help enforcing a correct use of shared_ptr semantics. Generally, with signal/slot emission, + * it is easy to run into the issue of an object being deleted while it emits a signal. Think about a Socket + * that emits a \a closed signal. It might be removed from the list of connections and the last reference of the + * object gets deleted before the signal returns. + * In order to prevent this from happening, we established a rule of "Always own a reference to the object you use". + * The connection helper's \ref Base::connect and \ref Base::connectFunc help with enforcing this rule, even asserting + * when compiled without NDEBUG defined. + * + * \sa zypp/zyppng/base/signals.h + */ + class LIBZYPP_NG_EXPORT Base : public sigc::trackable, public std::enable_shared_from_this + { + NON_COPYABLE(Base); + ZYPP_DECLARE_PRIVATE(Base) + public: + + using Ptr = std::shared_ptr; + using WeakPtr = std::weak_ptr; + + Base (); + virtual ~Base(); + + /*! + * Returns the parent object if there is one, otherwise + * returns a zero WeakPtr + */ + WeakPtr parent() const; + + /*! + * Adds a new object to the child list, the object + * will keep a reference for its entire lifetime or until the object is removed + */ + void addChild ( const Base::Ptr& child ); + + /*! + * Removes a child object from the internal child list + */ + void removeChild (const Ptr& child ); + + /*! + * Returns all child objects of this object + */ + const std::unordered_set &children() const; + + /*! + * Returns the thread ID this object was created in + */ + std::thread::id threadId () const; + + /*! + * Returns all children that can be casted to type T + */ + template + std::vector< std::weak_ptr > findChildren () const { + std::vector< std::weak_ptr > result; + for ( Ptr p : children() ) { + std::shared_ptr casted = std::dynamic_pointer_cast(p); + if ( casted ) + result.push_back( std::weak_ptr(casted) ); + } + return result; + } + + template + inline std::shared_ptr shared_this () const { + return std::static_pointer_cast( shared_from_this() ); + } + + template + inline std::shared_ptr shared_this () { + return std::static_pointer_cast( shared_from_this() ); + } + + template + inline std::weak_ptr weak_this () const { + return std::static_pointer_cast( weak_from_this().lock() ); + } + + template + inline std::weak_ptr weak_this () { + return std::static_pointer_cast( weak_from_this().lock() ); + } + + template + static decltype (auto) make_base_slot( Obj *o, Functor &&f ) { + //static_assert ( !internal::is_base_receiver, "Can not make a slot for a Object that does not derive from Base or BasePrivate."); + return internal::locking_fun( sigc::mem_fun( o, std::forward(f) ), *o ); + } + + /*! + * Preferred way to connect a signal to a slot, this will automatically take care of tracking the target object in the connection + */ + template< typename SenderFunc, typename ReceiverFunc > + static auto connect ( typename internal::MemberFunction::ClassType &s, SenderFunc &&sFun, typename internal::MemberFunction::ClassType &recv, ReceiverFunc &&rFunc ) { + return std::invoke( std::forward(sFun), &s ).connect( make_base_slot( &recv, std::forward(rFunc) ) ); + } + + + /*! + * Convenience func that uses "this" as the sender object in the signal / slot connection, this allows syntax like: + * \code + * object.connect( &Obj::signal, *targetObj, &TargetObj::onSignal ); + * \endcode + */ + template< typename SenderFunc, typename ReceiverFunc > + auto connect ( SenderFunc &&sFun, typename internal::MemberFunction::ClassType &recv, ReceiverFunc &&rFunc ) { + return connect( static_cast::ClassType &>(*this), std::forward(sFun), recv, std::forward(rFunc) ); + } + + /*! + * This allows to connect a lambda to a signal in a \ref Base derived type. Make sure to track the objects used inside the slot for shared_ptr + * correctness ( always own a reference to the object you are calling ) + */ + template< typename SenderFunc, typename ReceiverFunc, typename ...Tracker > + static auto connectFunc ( typename internal::MemberFunction::ClassType &s, SenderFunc &&sFun, ReceiverFunc &&rFunc, const Tracker&...trackers ) { + return std::invoke( std::forward(sFun), &s ).connect( internal::locking_fun( std::forward(rFunc), trackers... ) ); + } + + template< typename SenderFunc, typename ReceiverFunc, typename ...Tracker > + std::enable_if_t< std::is_member_function_pointer_v< SenderFunc >, connection > connectFunc ( SenderFunc &&sFun, ReceiverFunc &&rFunc, const Tracker&...trackers ) { + return connectFunc( static_cast::ClassType &>(*this), std::forward(sFun), std::forward(rFunc), trackers... ); + } + + protected: + Base ( BasePrivate &dd ); + std::unique_ptr d_ptr; + }; + + + template || std::is_base_of_v, bool> = true + > + inline decltype(auto) base_slot( Obj *o, Functor &&f ) + { + return Base::make_base_slot(o, std::forward(f) ); + } + + template || std::is_base_of_v, bool> = true + > + inline decltype(auto) base_slot( Obj &o, Functor &&f ) + { + return Base::make_base_slot(&o, std::forward(f) ); + } + +} // namespace zyppng + +#endif // ZYPP_NG_CORE_BASE_H_INCLUDED diff --git a/zypp-core/zyppng/base/eventdispatcher.h b/zypp-core/zyppng/base/eventdispatcher.h new file mode 100644 index 0000000..282bfb0 --- /dev/null +++ b/zypp-core/zyppng/base/eventdispatcher.h @@ -0,0 +1,200 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_BASE_EVENTDISPATCHER_DEFINED +#define ZYPP_BASE_EVENTDISPATCHER_DEFINED + +#include +#include +#include +#include +#include +#include + +namespace zyppng { + +class SocketNotifier; +class Timer; + +ZYPP_FWD_DECL_TYPE_WITH_REFS( EventDispatcher ); +ZYPP_FWD_DECL_TYPE_WITH_REFS( UnixSignalSource ); +class EventDispatcherPrivate; + +/*! + * The EventDispatcher class implements the libzypp event loop native backend. + * + * Libzypp is using a thread local dispatcher, which means each thread has its own unique disptacher. The only special case is when + * we need to work together with an already exisiting event loop, for example in a Qt application. The default implementation however + * uses the glib eventloop, just like Qt and GTK, so integrating libzypp here is just a matter of passing the default main context + * to the constructor of \ref EventDispatcher. + */ +class LIBZYPP_NG_EXPORT EventDispatcher : public Base +{ + ZYPP_DECLARE_PRIVATE(EventDispatcher) + friend class AbstractEventSource; + friend class Timer; + +public: + + using Ptr = std::shared_ptr; + using WeakPtr = std::shared_ptr; + using IdleFunction = std::function; + + + ~EventDispatcher() override; + + /*! + * Enters the eventloop once and dequeues all pending events, once the event queue is empty the + * function returns + */ + virtual bool run_once(); + + /*! + * \brief Convenience function to schedule a callback to be called later. + * \param callback a std::function that is called after all other events have been processed + */ + template< typename T = IdleFunction > + static void invokeOnIdle ( T &&callback ) + { + auto ev = instance(); + if ( ev ) + ev->invokeOnIdleImpl( std::forward(callback) ); + } + + /*! + * Schedules a \sa std::shared_ptr to be unreferenced in the next idle phase of the + * event loop. + * + * In some cases it might be required to delay the cleanup of a ressource until the current + * event loop iteration was finished, in case there are more pending events for the ressource. + * + * \note Normally this should be handled by using correct shared_ptr semantics, and always owning a reference + * to a object were functions are called on. Only if that is not possible unrefLater should be used. + */ + template< typename T > + static void unrefLater ( T &&ptr ) { + auto ev = instance(); + if ( ev ) + ev->unrefLaterImpl( std::static_pointer_cast( std::forward(ptr) ) ); + } + + /*! + * Immediately clears the list of all shared_ptr's that were registered + * to be unreferenced later. Mainly used to be called when a event loop exits, otherwise we + * might have weird side effects when the main loop instance preserves pointers that should be cleared + * at that point already. Like child items still trying to access the parent object that was already cleaned + * up before the MainLoop instance. + */ + void clearUnrefLaterList (); + + /*! + * Returns the number of the currently active timers + */ + ulong runningTimers() const; + + /*! + * Returns the EventDispatcher instance for the current thread. + */ + static std::shared_ptr instance(); + + /*! + * Registers the given event dispatcher as the default for the current thread. The reference count for the + * shared pointer will not be increased, so the application is responsible to keep it until the application exits. + * \note This must be called before the default dispatcher is registered, otherwise its ignored. + */ + static void setThreadDispatcher ( const std::shared_ptr &disp ); + + /** + * Returns the native dispatcher handle if the used implementation supports it + * \note the glib backend will return the used glib \a GMainContext + */ + void *nativeDispatcherHandle () const; + + /*! + * Waits until one of the requested events in \a events happens on the file descriptor. + * Use \ref AbstractEventSource::EventTypes to define for which events should be polled. + * Returns true on success, \a revents will contain the bitwise combination of \ref AbstractEventSource::EventTypes + * that triggered the wakeup. + */ + static bool waitForFdEvent ( const int fd, int events, int &revents, int &timeout ); + + using WaitPidCallback = std::function; + + /*! + * Tracks a child process until its execution did end. + * Callback is called when the child exits, the callback arguments are pid and status + */ + void trackChildProcess ( int pid, std::function callback ); + + /*! + * Removes a child process from the internal sources, the process will not be reaped + * anymore if it is still running! + * \returns true if the pid was removed + */ + bool untrackChildProcess ( int pid ); + + /*! + * Returns the currently active \ref UnixSignalSource for this EventDispatcher. + * It is required to keep the reference alive as long as signals need to be catched. + */ + UnixSignalSourceRef unixSignalSource (); + +protected: + + /*! + * Create a new instance of the EventDispatcher, if \a ctx is given it is used as the new + * context for the eventloop + */ + EventDispatcher( void *ctx = nullptr ); + + /*! + * \see unrefLater + */ + void unrefLaterImpl ( std::shared_ptr &&ptr ); + + /*! + * \see invokeOnIdle + */ + void invokeOnIdleImpl ( IdleFunction &&callback ); + + /*! + * Updates or registeres a event source in the event loop + * \param notifier The event source implementation that should receive the event notification + * \param fd The file descriptor that is added to the internal watchlist + * \param mode The watch mode for the given file desriptor \sa zyppng::AbstractEventSource::EventTypes + */ + virtual void updateEventSource ( AbstractEventSource ¬ifier, int fd, int mode ); + + /*! + * Removes a file descriptor from the internal watchlist, if \a fd is set to -1 all file descriptors + * associated with the \sa AbstractEventSource are removed + * \param notifier The \sa AbstractEventSource parent of the file descriptor + * \param fd The file descriptor to be removed, set to -1 to remove all descriptors for a \sa AbstractEventSource + */ + virtual void removeEventSource ( AbstractEventSource ¬ifier, int fd = -1 ); + + /*! + * Adds a new Timer instance to the internal timer list + */ + virtual void registerTimer ( Timer &timer ); + + /*! + * Removes a timer from the internal timer list, once a Timer is removed it does not fire anymore + */ + virtual void removeTimer ( Timer &timer ); + +}; + +} + +#endif diff --git a/zypp-core/zyppng/base/eventdispatcher_glib.cc b/zypp-core/zyppng/base/eventdispatcher_glib.cc new file mode 100644 index 0000000..f9acf12 --- /dev/null +++ b/zypp-core/zyppng/base/eventdispatcher_glib.cc @@ -0,0 +1,605 @@ +#include "timer.h" +#include "private/eventdispatcher_glib_p.h" +#include "private/threaddata_p.h" +#include + +#include +#include +#include +#include + +namespace zyppng { + +static int inline readMask () { + return ( G_IO_IN | G_IO_HUP ); +} + +static int inline writeMask () { + return ( G_IO_OUT ); +} + +static int inline excpMask () { + return ( G_IO_PRI ); +} + +static int inline evModeToMask ( int mode ) { + int cond = 0; + if ( mode & AbstractEventSource::Read ) { + cond = readMask() | G_IO_ERR; + } + if ( mode & AbstractEventSource::Write ) { + cond = cond | writeMask() | G_IO_ERR; + } + if ( mode & AbstractEventSource::Exception ) { + cond = cond | excpMask() | G_IO_ERR; + } + return cond; +} + +static int inline gioConditionToEventTypes ( const GIOCondition rEvents, const int requestedEvs ) { + int ev = 0; + if ( ( rEvents & requestedEvs ) != 0 ) { + if ( ( rEvents & readMask() ) && ( requestedEvs & readMask() ) ) + ev = AbstractEventSource::Read; + if ( ( rEvents & writeMask() ) && ( requestedEvs & writeMask() ) ) + ev = ev | AbstractEventSource::Write; + if ( ( rEvents & excpMask()) && ( requestedEvs & excpMask() ) ) + ev = ev | AbstractEventSource::Exception; + if ( ( rEvents & G_IO_ERR) && ( requestedEvs & G_IO_ERR ) ) + ev = ev | AbstractEventSource::Error; + } + return ev; +} + +static GSourceFuncs abstractEventSourceFuncs = { + GAbstractEventSource::prepare, + GAbstractEventSource::check, + GAbstractEventSource::dispatch, + nullptr, + nullptr, + nullptr +}; + +GAbstractEventSource *GAbstractEventSource::create(EventDispatcherPrivate *ev ) { + GAbstractEventSource *src = nullptr; + src = reinterpret_cast(g_source_new(&abstractEventSourceFuncs, sizeof(GAbstractEventSource))); + (void) new (&src->pollfds) std::vector(); + + src->eventSource = nullptr; + src->_ev = ev; + return src; +} + +void GAbstractEventSource::destruct(GAbstractEventSource *src) +{ + for ( GUnixPollFD &fd : src->pollfds ) { + if ( fd.tag ) + g_source_remove_unix_fd( &src->source, fd.tag ); + } + + src->pollfds.clear(); + src->pollfds.std::vector< GUnixPollFD >::~vector(); + g_source_destroy( &src->source ); + g_source_unref( &src->source ); +} + +gboolean GAbstractEventSource::prepare(GSource *, gint *timeout) +{ + //we can not yet determine if the GSource is ready, polling FDs also have no + //timeout, so lets continue + if ( timeout ) + *timeout = -1; + return false; +} + +//here we need to figure out which FDs are pending +gboolean GAbstractEventSource::check( GSource *source ) +{ + GAbstractEventSource *src = reinterpret_cast( source ); + + //check for pending and remove orphaned entries + bool hasPending = false; + + for ( auto fdIt = src->pollfds.begin(); fdIt != src->pollfds.end(); ) { + if ( fdIt->tag == nullptr ) { + //this pollfd was removed, clear it from the list + //for now keep the object in the sources list if the pollfd list gets empty, if it does not register new events until + //next check it is removed for good + fdIt = src->pollfds.erase( fdIt ); + } else { + GIOCondition pendEvents = g_source_query_unix_fd( source, fdIt->tag ); + if ( pendEvents & G_IO_NVAL ){ + //that poll is broken, do we need to do more???? + fdIt = src->pollfds.erase( fdIt ); + } else { + hasPending = hasPending || ( pendEvents & fdIt->reqEvents ); + fdIt++; + } + } + } + + //if the pollfds are empty trigger dispatch so this source can be removed + return hasPending || src->pollfds.empty(); +} + +//Trigger all event sources that have been activated +gboolean GAbstractEventSource::dispatch(GSource *source, GSourceFunc, gpointer) +{ + GAbstractEventSource *src = reinterpret_cast( source ); + + if ( !src ) + return G_SOURCE_REMOVE; + + //sources are only removed here so we do not accidentially mess with the pollfd iterator in the next loop + //were we trigger all ready FDs + if ( src->pollfds.empty() ) { + auto it = std::find( src->_ev->_eventSources.begin(), src->_ev->_eventSources.end(), src ); + + if ( it != src->_ev->_eventSources.end() ) { + GAbstractEventSource::destruct( *it ); + src->_ev->_eventSources.erase( it ); + return G_SOURCE_REMOVE; + } + } + + for ( const GUnixPollFD &pollfd : src->pollfds ) { + //do not trigger orphaned ones + if ( pollfd.tag != nullptr ) { + GIOCondition pendEvents = g_source_query_unix_fd( source, pollfd.tag ); + + if ( (pendEvents & pollfd.reqEvents ) != 0 ) { + int ev = gioConditionToEventTypes( pendEvents, pollfd.reqEvents ); + // we require all event objects to be used in shared_ptr form, by doing this we make sure that the object is not destroyed + // while we still use it. However this WILL throw in case of using the EventSource outside of shared_ptr bounds + auto eventSourceLocked = src->eventSource->shared_this(); + eventSourceLocked->onFdReady( pollfd.pollfd, ev ); + } + } + } + + return G_SOURCE_CONTINUE; +} + +static GSourceFuncs glibTimerSourceFuncs = { + GLibTimerSource::prepare, + GLibTimerSource::check, + GLibTimerSource::dispatch, + nullptr, + nullptr, + nullptr +}; + +//check when this timer expires and set the correct timeout +gboolean GLibTimerSource::prepare(GSource *src, gint *timeout) +{ + GLibTimerSource *source = reinterpret_cast( src ); + if ( !source ) + return false; //not ready for dispatch + + if ( !source->_t ) + return false; + + uint64_t nextTimeout = source->_t->remaining(); + if ( timeout ) { + //this would be a really looong timeout, but be safe + if ( nextTimeout > G_MAXINT ) + *timeout = G_MAXINT; + else + *timeout = static_cast( nextTimeout ); + } + return ( nextTimeout == 0 ); +} + +//this is essentially the same as prepare +gboolean GLibTimerSource::check(GSource *source) +{ + return prepare( source, nullptr ); +} + +//emit the expired timers, restart timers that are no single shots +gboolean GLibTimerSource::dispatch(GSource *src, GSourceFunc, gpointer) +{ + GLibTimerSource *source = reinterpret_cast( src ); + if ( !source ) + return true; + + if ( source->_t == nullptr ) + return true; + //this will emit the expired signal and reset the timer + //or stop it in case its a single shot timer + source->_t->shared_this()->expire(); + return true; +} + +GLibTimerSource *GLibTimerSource::create() +{ + GLibTimerSource *src = nullptr; + src = reinterpret_cast(g_source_new(&glibTimerSourceFuncs, sizeof(GLibTimerSource))); + src->_t = nullptr; + return src; +} + +void GLibTimerSource::destruct(GLibTimerSource *src) +{ + g_source_destroy( &src->source ); + g_source_unref( &src->source ); +} + +/*! + * \brief Called when the event loop is idle, here we run cleanup tasks and call later() callbacks of the user + */ +static gboolean eventLoopIdleFunc ( gpointer user_data ) +{ + auto dPtr = reinterpret_cast( user_data ); + if ( dPtr ) { + if( dPtr->runIdleTasks() ) { + return G_SOURCE_CONTINUE; + } + + g_source_unref ( dPtr->_idleSource ); + dPtr->_idleSource = nullptr; + } + return G_SOURCE_REMOVE; +} + +GlibWaitPIDData::GlibWaitPIDData( GPid pid ) +{ + source = g_child_watch_source_new( pid ); +} + +GlibWaitPIDData::GlibWaitPIDData(GlibWaitPIDData &&other) noexcept + : tag( other.tag ) + , source( other.source ) + , callback( std::move( other.callback ) ) +{ + other.source = nullptr; +} + +GlibWaitPIDData::~GlibWaitPIDData() +{ + if ( source ) { + g_source_destroy( source ); + g_source_unref( source ); + } +} + +GlibWaitPIDData &GlibWaitPIDData::operator=(GlibWaitPIDData &&other) noexcept +{ + tag = other.tag; + source = other.source; + callback = std::move( other.callback ); + other.source = nullptr; + return *this; +} + +EventDispatcherPrivate::EventDispatcherPrivate (GMainContext *ctx , EventDispatcher &p) : BasePrivate(p) +{ + _myThreadId = std::this_thread::get_id(); + + //if we get a context specified ( usually when created for main thread ) we use it + //otherwise we create our own + if ( ctx ) { + _ctx = ctx; + g_main_context_ref ( _ctx ); + } else { + _ctx = g_main_context_new(); + } + // Enable this again once we switch to a full async API that requires a eventloop before calling any zypp functions + // g_main_context_push_thread_default( _ctx ); +} + +EventDispatcherPrivate::~EventDispatcherPrivate() +{ + std::for_each ( _runningTimers.begin(), _runningTimers.end(), []( GLibTimerSource *src ){ + GLibTimerSource::destruct( src ); + }); + std::for_each ( _eventSources.begin(), _eventSources.end(), []( GAbstractEventSource *src ){ + GAbstractEventSource::destruct( src ); + }); + _runningTimers.clear(); + _eventSources.clear(); + + if ( _idleSource ) { + g_source_destroy( _idleSource ); + g_source_unref ( _idleSource ); + } + + //g_main_context_pop_thread_default( _ctx ); + g_main_context_unref( _ctx ); +} + +bool EventDispatcherPrivate::runIdleTasks() +{ + //run all user defined idle functions + //if they return true, they are executed again in the next idle run + decltype ( _idleFuncs ) runQueue; + runQueue.swap( _idleFuncs ); + + while ( runQueue.size() ) { + EventDispatcher::IdleFunction fun( std::move( runQueue.front() ) ); + runQueue.pop(); + if ( fun() ) + _idleFuncs.push( std::move(fun) ); + } + + //keep this as the last thing to call after all user code was executed + if ( _unrefLater.size() ) + _unrefLater.clear(); + + return _idleFuncs.size() || _unrefLater.size(); +} + +void EventDispatcherPrivate::enableIdleSource() +{ + if ( !_idleSource ) { + _idleSource = g_idle_source_new (); + g_source_set_callback ( _idleSource, eventLoopIdleFunc, this, nullptr ); + g_source_attach ( _idleSource, _ctx ); + } +} + +std::shared_ptr EventDispatcherPrivate::create() +{ + return std::shared_ptr( new EventDispatcher() ); +} + +void EventDispatcherPrivate::waitPidCallback( GPid pid, gint status, gpointer user_data ) +{ + EventDispatcherPrivate *that = reinterpret_cast( user_data ); + + try { + auto data = std::move( that->_waitPIDs.at(pid) ); + that->_waitPIDs.erase( pid ); + + if ( data.callback ) + data.callback( pid, status ); + + g_spawn_close_pid( pid ); + + // no need to take care of releasing the GSource, the event loop took care of that + + } catch ( const std::out_of_range &e ) { + return; + } +} + +ZYPP_IMPL_PRIVATE(EventDispatcher) + +EventDispatcher::EventDispatcher(void *ctx) + : Base ( * new EventDispatcherPrivate( reinterpret_cast(ctx), *this ) ) +{ +} + +EventDispatcher::~EventDispatcher() +{ +} + +void EventDispatcher::updateEventSource( AbstractEventSource ¬ifier, int fd, int mode ) +{ + Z_D(); + if ( notifier.eventDispatcher().lock().get() != this ) + ZYPP_THROW( zypp::Exception("Invalid event dispatcher used to update event source") ); + + AbstractEventSource *notifyPtr = ¬ifier; + + GAbstractEventSource *evSrc = nullptr; + auto &evSrcList = d->_eventSources; + auto itToEvSrc = std::find_if( evSrcList.begin(), evSrcList.end(), [ notifyPtr ]( const auto elem ){ return elem->eventSource == notifyPtr; } ); + if ( itToEvSrc == evSrcList.end() ) { + + evSrc = GAbstractEventSource::create( d ); + evSrc->eventSource = notifyPtr; + evSrcList.push_back( evSrc ); + + g_source_attach( &evSrc->source, d->_ctx ); + + } else + evSrc = (*itToEvSrc); + + int cond = evModeToMask( mode ); + auto it = std::find_if( evSrc->pollfds.begin(), evSrc->pollfds.end(), [fd]( const auto &currPollFd ) { + return currPollFd.pollfd == fd; + }); + + if ( it != evSrc->pollfds.end() ) { + //found + it->reqEvents = static_cast( cond ); + g_source_modify_unix_fd( &evSrc->source, it->tag, static_cast(cond) ); + } else { + evSrc->pollfds.push_back( + GUnixPollFD { + static_cast(cond), + fd, + g_source_add_unix_fd( &evSrc->source, fd, static_cast(cond) ) + } + ); + } +} + +void EventDispatcher::removeEventSource( zyppng::AbstractEventSource ¬ifier, int fd ) +{ + Z_D(); + + AbstractEventSource *ptr = ¬ifier; + + if ( notifier.eventDispatcher().lock().get() != this ) + ZYPP_THROW( zypp::Exception("Invalid event dispatcher used to remove event source") ); + + auto &evList = d->_eventSources; + auto it = std::find_if( evList.begin(), evList.end(), [ ptr ]( const auto elem ){ return elem->eventSource == ptr; } ); + + if ( it == evList.end() ) + return; + + auto &fdList = (*it)->pollfds; + + if ( fd == -1 ) { + //we clear out all unix_fd watches but do not destroy the source just yet. We currently might + //be in the dispatch() function of that AbstractEventSource, make sure not to break the iterator + //for the fd's + for ( auto &pFD : fdList ) { + if ( pFD.tag ) + g_source_remove_unix_fd( &(*it)->source, pFD.tag ); + pFD.pollfd = -1; + pFD.tag = nullptr; //mark as orphaned, do not delete the element here this might break dipatching + } + } else { + auto fdIt = std::find_if( fdList.begin(), fdList.end(), [ fd ]( const auto &pFd ){ return pFd.pollfd == fd; } ); + if ( fdIt != fdList.end() ) { + if ( fdIt->tag ) + g_source_remove_unix_fd( &(*it)->source, (*fdIt).tag ); + //also do not remove here, mark as orphaned only to not break iterating in dispatch() + fdIt->tag = nullptr; + fdIt->pollfd = -1; + } + } +} + +void EventDispatcher::registerTimer( Timer &timer ) +{ + Z_D(); + //make sure timer is not double registered + for ( const GLibTimerSource *t : d->_runningTimers ) { + if ( t->_t == &timer ) + return; + } + + GLibTimerSource *newSrc = GLibTimerSource::create(); + newSrc->_t = &timer; + d->_runningTimers.push_back( newSrc ); + + g_source_attach( &newSrc->source, d->_ctx ); +} + +void EventDispatcher::removeTimer( Timer &timer ) +{ + Z_D(); + auto it = std::find_if( d->_runningTimers.begin(), d->_runningTimers.end(), [ &timer ]( const GLibTimerSource *src ){ + return src->_t == &timer; + }); + + if ( it != d->_runningTimers.end() ) { + GLibTimerSource *src = *it; + d->_runningTimers.erase( it ); + GLibTimerSource::destruct( src ); + } +} + +void *EventDispatcher::nativeDispatcherHandle() const +{ + return d_func()->_ctx; +} + +bool EventDispatcher::waitForFdEvent( const int fd, int events , int &revents , int &timeout ) +{ + GPollFD pollFd; + pollFd.fd = fd; + pollFd.events = evModeToMask(events); + + bool eventTriggered = false; + zypp::AutoDispose timer( g_timer_new(), &g_timer_destroy ); + while ( !eventTriggered ) { + g_timer_start( *timer ); + const int res = eintrSafeCall( g_poll, &pollFd, 1, timeout ); + switch ( res ) { + case 0: //timeout + timeout = 0; + return false; + case -1: { // interrupt + // if timeout is -1 we wait until eternity + if ( timeout == -1 ) + continue; + + timeout -= g_timer_elapsed( *timer, nullptr ); + if ( timeout < 0 ) timeout = 0; + if ( timeout <= 0 ) + return false; + + ERR << "g_poll error: " << strerror(errno) << std::endl; + return false; + } + case 1: + eventTriggered = true; + break; + } + } + + revents = gioConditionToEventTypes( (GIOCondition)pollFd.revents, evModeToMask(events) ); + return true; +} + +void EventDispatcher::trackChildProcess( int pid, std::function callback ) +{ + Z_D(); + GlibWaitPIDData data ( pid ); + data.callback = std::move(callback); + + g_source_set_callback ( data.source, (GSourceFunc) &EventDispatcherPrivate::waitPidCallback , d_ptr.get(), nullptr ); + data.tag = g_source_attach ( data.source, d->_ctx ); + d->_waitPIDs.insert( std::make_pair( pid, std::move(data) ) ); +} + +bool EventDispatcher::untrackChildProcess(int pid) +{ + Z_D(); + try { + d->_waitPIDs.erase( pid ); + } catch ( const std::out_of_range &e ) { + return false; + } + return true; +} + +UnixSignalSourceRef EventDispatcher::unixSignalSource() +{ + Z_D(); + // lazy init + UnixSignalSourceRef r; + if ( d->_signalSource.expired ()) { + d->_signalSource = r = UnixSignalSource::create(); + } else { + r = d->_signalSource.lock (); + } + return r; +} + +bool EventDispatcher::run_once() +{ + return g_main_context_iteration( d_func()->_ctx, false ); +} + +void EventDispatcher::invokeOnIdleImpl(EventDispatcher::IdleFunction &&callback) +{ + auto d = instance()->d_func(); + d->_idleFuncs.push( std::move(callback) ); + d->enableIdleSource(); +} + +void EventDispatcher::unrefLaterImpl( std::shared_ptr &&ptr ) +{ + Z_D(); + d->_unrefLater.push_back( std::move(ptr) ); + d->enableIdleSource(); +} + +void EventDispatcher::clearUnrefLaterList () +{ + d_func()->_unrefLater.clear(); +} + +ulong EventDispatcher::runningTimers() const +{ + return d_func()->_runningTimers.size(); +} + +std::shared_ptr EventDispatcher::instance() +{ + return ThreadData::current().dispatcher(); +} + +void EventDispatcher::setThreadDispatcher(const std::shared_ptr &disp) +{ + ThreadData::current().setDispatcher( disp ); +} + +} diff --git a/zypp-core/zyppng/base/eventloop.h b/zypp-core/zyppng/base/eventloop.h new file mode 100644 index 0000000..8aff854 --- /dev/null +++ b/zypp-core/zyppng/base/eventloop.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_BASE_EVENTLOOP_DEFINED +#define ZYPP_BASE_EVENTLOOP_DEFINED + +#include +#include +#include + +// CONTINUE WITH THREAD DATA AND PUT THE DISPATCHER INSTANCE THERE! + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS ( EventDispatcher ); + ZYPP_FWD_DECL_TYPE_WITH_REFS ( EventLoop ); + class EventLoopPrivate; + + ZYPP_FWD_DECL_TYPE_WITH_REFS(EventLoop); + + /*! + * The EventDispatcher class implements the libzypp event loop. + * + * A event loop is used to execute multiple tasks concurrently. This is not implemented using threads but usually by either + * using Timers to poll a ressource or by reacting on events from a file descriptor or socket. + * In a application like zypper where we make use of I/O heavy tasks like downloading packages, rebuilding the repo metadata + * or generating a checksum over a file the application needs to wait more for those tasks to finish than actually doing anything. + * By using a event loop we can start one of those tasks and let the OS handle the execution and subscribe to certain events that can happen, + * utilizing more of the CPU compared to starting all the tasks serially. + * + */ + class LIBZYPP_NG_EXPORT EventLoop : public Base + { + ZYPP_DECLARE_PRIVATE(EventLoop) + + public: + using Ptr = EventLoopRef; + using WeakPtr = EventLoopWeakRef; + + static Ptr create (); + ~EventLoop() override; + + /*! + * Start dispatching events, this function will block until \sa quit was called for the EventLoop instance + */ + void run (); + + /*! + * Stop dispatching events and return control from the run function + */ + void quit (); + + + /*! + * Returns the event dispatcher used by the MainLoop instance + */ + std::shared_ptr eventDispatcher () const; + + private: + EventLoop(); + + }; + +} + +#endif diff --git a/zypp-core/zyppng/base/eventloop_glib.cc b/zypp-core/zyppng/base/eventloop_glib.cc new file mode 100644 index 0000000..6f20dcd --- /dev/null +++ b/zypp-core/zyppng/base/eventloop_glib.cc @@ -0,0 +1,47 @@ +#include "private/eventloop_glib_p.h" +#include + +namespace zyppng { + + EventLoopPrivate::EventLoopPrivate( EventLoop &p ) : BasePrivate( p ) + { } + + ZYPP_IMPL_PRIVATE(EventLoop) + + EventLoop::EventLoop() + : Base ( * new EventLoopPrivate(*this) ) + { + Z_D(); + d->_dispatcher = ThreadData::current().ensureDispatcher(); + d->_loop = g_main_loop_new( reinterpret_cast(d->_dispatcher->nativeDispatcherHandle()), false ); + } + + EventLoop::~EventLoop() + { + g_main_loop_unref( d_func()->_loop ); + } + + EventLoop::Ptr EventLoop::create() + { + return Ptr( new EventLoop() ); + } + + void EventLoop::run() + { + Z_D(); + g_main_context_push_thread_default( reinterpret_cast(d->_dispatcher->nativeDispatcherHandle()) ); + g_main_loop_run( d->_loop ); + d->_dispatcher->clearUnrefLaterList(); + g_main_context_pop_thread_default( reinterpret_cast(d->_dispatcher->nativeDispatcherHandle()) ); + } + + void EventLoop::quit() + { + g_main_loop_quit( d_func()->_loop ); + } + + std::shared_ptr EventLoop::eventDispatcher() const + { + return d_func()->_dispatcher; + } +} diff --git a/zypp-core/zyppng/base/linuxhelpers.cc b/zypp-core/zyppng/base/linuxhelpers.cc new file mode 100644 index 0000000..3fe6a11 --- /dev/null +++ b/zypp-core/zyppng/base/linuxhelpers.cc @@ -0,0 +1,92 @@ +#include "private/linuxhelpers_p.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + bool blockAllSignalsForCurrentThread() + { + sigset_t set; + ::sigfillset(&set); + int res = ::pthread_sigmask(SIG_BLOCK, &set, NULL); + return ( res == 0 ); + } + + bool blockSignalsForCurrentThread( const std::vector &sigs ) + { + sigset_t set; + ::sigemptyset(&set); + for ( const int sig : sigs ) + ::sigaddset( &set, sig ); + + int res = ::pthread_sigmask(SIG_BLOCK, &set, NULL); + return ( res == 0 ); + } + + bool trySocketConnection( int &sockFD, const SockAddr &addr, uint64_t timeout ) + { + int res = -1; + const auto opStarted = zyppng::Timer::now(); + do { + res = zyppng::eintrSafeCall( ::connect, sockFD, addr.nativeSockAddr(), addr.size() ); + if ( res < 0 && errno != ECONNREFUSED && errno != EADDRNOTAVAIL ) { + ERR << "Connection failed with error: " << errno << " " << zyppng::strerr_cxx( errno ) << std::endl; + ::close( sockFD ); + sockFD = -1; + return false; + } + } while ( res == -1 && zyppng::Timer::elapsedSince( opStarted ) < timeout ); + return ( res == 0 ); + } + + void renumberFd (int origfd, int newfd) + { + // It may happen that origfd is already the one we want + // (Although in our circumstances, that would mean somebody has closed + // our stdin or stdout... weird but has appened to Cray, #49797) + if (origfd != newfd) + { + dup2 (origfd, newfd); + ::close (origfd); + } + } + + int64_t bytesAvailableOnFD( int fd ) + { + int value = 0; + if ( ioctl( fd, FIONREAD, &value) >= 0 ) + return int64_t(value); + + return 0; + } + + std::optional Pipe::create( int flags ) + { + int pipeFds[]={ -1, -1 }; + +#ifdef HAVE_PIPE2 + if ( ::pipe2( pipeFds, flags ) != 0 ) + return {}; +#else + if ( ::pipe( pipeFds ) != 0 ) + return {}; + if ( flags != 0 ) { + ::fcntl( pipeFds[0], F_SETFD, flags ); + ::fcntl( pipeFds[1], F_SETFD, flags ); + } +#endif + return Pipe { + .readFd = zypp::AutoFD( pipeFds[0] ), + .writeFd = zypp::AutoFD( pipeFds[1] ) + }; + } + +} diff --git a/zypp-core/zyppng/base/private/abstracteventsource_p.h b/zypp-core/zyppng/base/private/abstracteventsource_p.h new file mode 100644 index 0000000..9f475dc --- /dev/null +++ b/zypp-core/zyppng/base/private/abstracteventsource_p.h @@ -0,0 +1,34 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_BASE_PRIVATE_ABSTRACTEVENTSOURCE_P_H_INCLUDED +#define ZYPPNG_BASE_PRIVATE_ABSTRACTEVENTSOURCE_P_H_INCLUDED + +#include "base_p.h" +#include + +namespace zyppng { + +class AbstractEventSourcePrivate : public BasePrivate +{ + ZYPP_DECLARE_PUBLIC(AbstractEventSource) + +public: + AbstractEventSourcePrivate( AbstractEventSource &p ); + std::weak_ptr _ev; +}; + +} + + +#endif diff --git a/zypp-core/zyppng/base/private/base_p.h b/zypp-core/zyppng/base/private/base_p.h new file mode 100644 index 0000000..e39b3e5 --- /dev/null +++ b/zypp-core/zyppng/base/private/base_p.h @@ -0,0 +1,31 @@ +#ifndef ZYPP_NG_BASE_PRIVATE_BASE_P_H_INCLUDED +#define ZYPP_NG_BASE_PRIVATE_BASE_P_H_INCLUDED + +#include +#include +#include +#include +#include + +namespace zyppng +{ + + class BasePrivate : public sigc::trackable + { + ZYPP_DECLARE_PUBLIC(Base) + public: + BasePrivate ( Base &b ) : z_ptr(&b){} + virtual ~BasePrivate(); + + virtual void init (); + + Base::WeakPtr parent; + std::unordered_set< Base::Ptr > children; + Base *z_ptr = nullptr; + std::thread::id threadId = std::this_thread::get_id(); + }; + +} + + +#endif diff --git a/zypp-core/zyppng/base/private/eventdispatcher_glib_p.h b/zypp-core/zyppng/base/private/eventdispatcher_glib_p.h new file mode 100644 index 0000000..4db8bea --- /dev/null +++ b/zypp-core/zyppng/base/private/eventdispatcher_glib_p.h @@ -0,0 +1,104 @@ +#ifndef ZYPP_BASE_EVENTDISPATCHER_GLIB_P_DEFINED +#define ZYPP_BASE_EVENTDISPATCHER_GLIB_P_DEFINED + +#include "base_p.h" +#include +#include +#include +#include +#include + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS ( UnixSignalSource ); + +struct GUnixPollFD +{ + GIOCondition reqEvents; + int pollfd = -1; + gpointer tag = nullptr; +}; + +/*! + * \internal GSource for all AbstractEventSources + * \attention this struct is initialized with malloc, make sure + * to manually call all constructurs and destructors in the + * \a create and \a destruct functions + */ +struct GAbstractEventSource +{ + GSource source; + EventDispatcherPrivate *_ev; + AbstractEventSource *eventSource; + std::vector pollfds; + + static gboolean prepare(GSource *, gint *timeout); + static gboolean check(GSource *source); + static gboolean dispatch(GSource *source, GSourceFunc, gpointer); + + static GAbstractEventSource *create (EventDispatcherPrivate *ev); + static void destruct ( GAbstractEventSource *src ); +}; + +/*! + * \internal GSource for all Timers + * \attention this struct is initialized with malloc, make sure + * to manually call all constructurs and destructors in the + * \a create and \a destruct functions + */ +struct GLibTimerSource +{ + GSource source; + Timer *_t = nullptr; + + static gboolean prepare(GSource *src, gint *timeout); + static gboolean check(GSource *source); + static gboolean dispatch(GSource *source, GSourceFunc, gpointer); + + static GLibTimerSource *create (); + static void destruct ( GLibTimerSource *src ); +}; + +struct GlibWaitPIDData +{ + GlibWaitPIDData( GPid pid ); + GlibWaitPIDData( GlibWaitPIDData &&other ) noexcept; + ~GlibWaitPIDData(); + + GlibWaitPIDData & operator= ( GlibWaitPIDData &&other ) noexcept; + + guint tag = 0; + GSource *source = nullptr; + EventDispatcher::WaitPidCallback callback; +}; + +class EventDispatcherPrivate : public BasePrivate +{ + ZYPP_DECLARE_PUBLIC(EventDispatcher) +public: + EventDispatcherPrivate( GMainContext *ctx, EventDispatcher &p ); + ~EventDispatcherPrivate() override; + + bool runIdleTasks(); + void enableIdleSource (); + + static std::shared_ptr create ( ); + static void waitPidCallback ( GPid pid, gint status, gpointer user_data ); + + std::thread::id _myThreadId; + GMainContext *_ctx = nullptr; + + GSource *_idleSource = nullptr; + + std::vector _runningTimers; + std::vector _eventSources; + std::vector< std::shared_ptr > _unrefLater; + std::queue< EventDispatcher::IdleFunction > _idleFuncs; + std::unordered_map _waitPIDs; + UnixSignalSourceWeakRef _signalSource; +}; + +} + + +#endif diff --git a/zypp-core/zyppng/base/private/eventloop_glib_p.h b/zypp-core/zyppng/base/private/eventloop_glib_p.h new file mode 100644 index 0000000..39df198 --- /dev/null +++ b/zypp-core/zyppng/base/private/eventloop_glib_p.h @@ -0,0 +1,25 @@ +#ifndef ZYPP_BASE_EVENTLOOP_GLIB_P_DEFINED +#define ZYPP_BASE_EVENTLOOP_GLIB_P_DEFINED + +#include "base_p.h" +#include "threaddata_p.h" +#include +#include + +namespace zyppng { + + class EventLoopPrivate : public BasePrivate + { + ZYPP_DECLARE_PUBLIC(EventLoop) + public: + EventLoopPrivate ( EventLoop &p ); + + std::shared_ptr _dispatcher; + GMainLoop *_loop = nullptr; + + }; + +} + + +#endif diff --git a/zypp-core/zyppng/base/private/linuxhelpers_p.h b/zypp-core/zyppng/base/private/linuxhelpers_p.h new file mode 100644 index 0000000..708dfa9 --- /dev/null +++ b/zypp-core/zyppng/base/private/linuxhelpers_p.h @@ -0,0 +1,87 @@ +#ifndef ZYPP_BASE_LINUXHELPERS_P_H_DEFINED +#define ZYPP_BASE_LINUXHELPERS_P_H_DEFINED + +#include +#include +#include +#include +#include + +namespace zyppng { + + class SockAddr; + + inline std::string strerr_cxx ( const int err = -1 ) { + ByteArray strBuf( 1024, '\0' ); + strerror_r( err == -1 ? errno : err , strBuf.data(), strBuf.size() ); + return std::string( strBuf.data() ); + } + + + /*! + * Extended version of \ref eintrSafeCall + * + * Calls a given \a function in a \a EINTR safe way. The \a restartCb is + * invoked after every time we have to restart \a function because of EINTR, it can be used to + * reset additional errors: + * \code + * FILE *myFile; + * // open file + * // ... + * eintrSafeCall( ::getline, [&](){ ::clearerr(myFile); }, myFile ); + * \endcode + */ + template + auto eintrSafeCallEx ( const Fun &function, const RestartCb &restartCb, Args&&... args ) { + int res = 0; + while ( true ) { + errno = 0; + res = std::invoke(function, args... ); + if ( res == -1 && errno == EINTR ) { + std::invoke( restartCb ); + continue; + } + break; + }; + return res; + } + + template + auto eintrSafeCall ( Fun &&function, Args&&... args ) { + return eintrSafeCallEx( std::forward(function), [](){}, std::forward(args)... ); + } + + bool blockAllSignalsForCurrentThread ( ); + + bool blockSignalsForCurrentThread ( const std::vector &sigs ); + + bool trySocketConnection (int &sockFD, const SockAddr &addr, uint64_t timeout ); + + // origfd will be accessible as newfd and closed (unless they were equal) + void renumberFd (int origfd, int newfd); + + /*! + * Tries to use the FIONREAD ioctl to detect how many bytes are available on a file descriptor, + * this can fail and return 0 so just use it as a indicator on how many bytes are pending + */ + int64_t bytesAvailableOnFD( int fd ); + + /*! + * Small helper struct around creating a Unix pipe to ensure RAII with pipes + */ + struct Pipe { + zypp::AutoFD readFd; + zypp::AutoFD writeFd; + static std::optional create ( int flags = 0 ); + + void unrefWrite( ) { + writeFd = -1; + } + + void unrefRead( ) { + readFd = -1; + } + }; +} + +#endif // LINUXHELPERS_P_H diff --git a/zypp-core/zyppng/base/private/threaddata_p.h b/zypp-core/zyppng/base/private/threaddata_p.h new file mode 100644 index 0000000..d753be9 --- /dev/null +++ b/zypp-core/zyppng/base/private/threaddata_p.h @@ -0,0 +1,45 @@ +#ifndef ZYPP_BASE_THREADDATA_P_DEFINED +#define ZYPP_BASE_THREADDATA_P_DEFINED + +#include +#include +#include +#include + +namespace zyppng +{ + class EventDispatcher; + + struct ThreadData + { + static ZYPP_API ThreadData ¤t(); + + template + void setName( T &&name ) { + _threadName = std::forward( name ); + syncNativeName(); + } + + const std::string &name() const; + + std::shared_ptr dispatcher(); + std::shared_ptr ensureDispatcher(); + void setDispatcher( const std::shared_ptr &disp ); + + + private: + void syncNativeName(); + ThreadData(); + + private: + std::thread::id _threadId; + mutable std::string _threadName; ///< lazy initialized to _threadId if unset + std::thread::native_handle_type _nativeHandle; + std::weak_ptr _dispatcher; + }; + + ThreadData& threadData(); +} + + +#endif diff --git a/zypp-core/zyppng/base/signals.h b/zypp-core/zyppng/base/signals.h new file mode 100644 index 0000000..08d72d2 --- /dev/null +++ b/zypp-core/zyppng/base/signals.h @@ -0,0 +1,377 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_BASE_SIGNALS_H_INCLUDED +#define ZYPP_NG_BASE_SIGNALS_H_INCLUDED + +#ifdef ENABLE_SYWU +#include +#else +#include +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include + +/*! + * \file signals.h + * + * This file implements the signal and slot concept in libzypp. + * + * Signals and slots are basically a implementation of the observer pattern which makes it possible + * for objects to work together without them having to know about each other by connecting the + * signals of one object to the slots of another. Whenever the object owning the signal + * emits said signal, all connected slots are executed. This is especially helpful in async environments + * where we need to react on specific events like timers or filedescriptor events that can + * happen at any time during execution. + * + * Using signals and slots in libzypp requires the developer to make sure + * that all objects that are used in the signal chain can not be deleted + * during emission, for example a Socket emitting the closed() signal might result in + * its deletion. This is usually made sure by taking a reference to the sender object + * via shared_ptr, e.g. the \ref EventLoop does this for all \ref AbstractEventSource 's that are + * registered to receive events using shared_from_this. + * + * To have signals in an Object, it is recommended to subclass the Type from \ref zyppng::Base + * and always have the objects in a \ref std::shared_ptr. + * \ref zyppng::Base provides the \ref zyppng::Base::connect and \ref zyppng::Base::connectFunc + * helpers to connect signals and slots. Connections made with those helpers will make sure the + * receiving objects are properly locked. + * + * The \ref zyppng::Base::connect helper function can be used to connect a signal that is hosted by a \ref zyppng::Base + * derived type to a slot hosted by a \ref zyppng::Base derived type. No special care needs to be taken to make sure + * the receiver object is locked since the function is handling all the details about that: + * \code + * class Receiver : public zyppng::Base + * { + * public: + * static std::shared_ptr create(); + * void writeOnTimeout() { + * std::cout << "Hello World" << std::endl; + * } + * } + * + * auto evLoop = zyppng::EventLoop::create(); + * auto sender = zyppng::Timer::create(); + * auto receiver = Receiver::create(); + * + * // invoking the static Base::connect() function will make sure receiver is locked, the sender will be locked by the + * // eventloop triggering the timeout + * sender->connect( *sender, &zyppng::Timer::sigExpired, *receiver, &Receiver::writeOnTimeout ); + * sender->start(1000); + * evLoop->run(); + * \endcode + * + * The \ref zyppng::Base::connect helper function can be used to connect a signal that is hosted by a \ref zyppng::Base + * derived type to a lambda type slot, commonly used when the developer wants to have the code that is invoked by the signal + * right where the slot is connected, to make the code easier to read or when the slot code is not reused anywhere else. + * + * In this example the receiver object uses a slot to invoke the actual function that handles the event. Since we only connect + * a lambda that invokes the writeOnTimeout function using a caputured \a this pointer we need to manually take care of locking the receiver object during the + * slot invocation by passing it as a extra argument after the lambda. While the code would compile without doing that we + * introduce a bug that is very hard to track down because the subsequent signal emitted from the receiver object causes it to be deleted, + * making the code fail afterwards. + * \code + * class Receiver : public zyppng::Base + * { + * public: + * static std::shared_ptr create(); + * + * void connectToTimer ( std::shared_ptr &p ) { + * p->connectFunc( *sender, &zyppng::Timer::sigExpired, [ this ](){ + * onTimeout(); + * }, *this ); + * } + * + * SignalProxy sigGotTimeout() { + * return _sigGotTimeout; + * } + * + * private: + * void onTimeout() { + * std::cout << "Hello World" << std::endl; + * // emits a subsequent signal + * _sigGotTimeout.emit(); + * + * // calls another function on this after emitting the signal + * // in cases where our instance was not locked by the caller and + * // a slot that received our signal released the last reference to us + * // this will run into a segfault + * this->doSomethingElse(); + * } + * void doSomethingElse() { + * std::cout << "Something else" << std::endl; + * } + * Signal _sigGotTimeout; + * } + * + * auto evLoop = zyppng::EventLoop::create(); + * auto sender = zyppng::Timer::create(); + * auto receiver = Receiver::create(); + * + * // invoking the static Base::connect() function will make sure receiver is locked, the sender will be locked by the + * // eventloop triggering the timeout + * receiver->connectToTimer( sender ); + * + * // release the receiver after the timeout was triggered + * receiver->connectFunc( *receiver, &Receiver::sigGotTimeout, [ &receiver ](){ + * // releasing the receiver Object once the timer was triggered once. If the object + * // is not properly referenced during signal emission we will run into a SEGFAULT + * receiver.reset(); + * }); + * + * sender->start( 1000 ); + * evLoop->run(); + * \endcode + */ +namespace zyppng { + + + /*! + * \class Signal + * Simple signal that can be invoked with the given arguments. + */ + template + class Signal; + + /*! + * \class MemSignal + * This is a special type of signal that takes a reference to the sender + * object during signal emission. This is only required in cases where + * sending a signal might delete the sender and no external object holds a reference to it. + */ + template + class MemSignal; + + class Base; + class BasePrivate; + +#ifdef ENABLE_SYWU + using connection = sywu::Connection; + + template + using SignalProxyBase = sywu::SignalConceptImpl; + + template + class Signal : public sywu::Signal + { }; + + template + class MemSignal : public sywu::MemberSignal + { }; + +#else + using connection = sigc::connection; + using trackable = sigc::trackable; + using sigc::track_obj; + + template + using SignalProxyBase = sigc::signal; + + + template + class Signal : public sigc::signal + { + public: + ~Signal() { + assert(this->impl()->exec_count_ == 0); + if ( this->impl()->exec_count_ > 0 ) { + WAR << "Deleting Signal during emission, this is usually a BUG, Slots will be blocked to prevent SIGSEGV." << std::endl; +#ifdef LIBZYPP_USE_SIGC_BLOCK_WORKAROUND + // older sigc versions will segfault if clear() is called in signal emission + // we use block instead in those cases which seems to have the same result + // since we do not use the slot instances explicitely that _should_ not have side effects + // https://bugzilla.gnome.org/show_bug.cgi?id=784550 + this->block(); + return; +#endif + } + + this->clear(); + } + }; + + template + class MemSignal : public sigc::signal + { + public: + MemSignal ( SignalHost &host ) : _host(host) {} + + ~MemSignal() { + + assert(this->impl()->exec_count_ == 0); + if ( this->impl()->exec_count_ > 0 ) { + WAR << "Deleting MemSignal during emission, this is definitely a BUG, Slots will be blocked to prevent SIGSEGV." << std::endl; +#ifdef LIBZYPP_USE_SIGC_BLOCK_WORKAROUND + // older sigc versions will segfault if clear() is called in signal emission + // we use block instead in those cases which seems to have the same result + // since we do not use the slot instances explicitely that _should_ not have side effects + // https://bugzilla.gnome.org/show_bug.cgi?id=784550 + this->block(); + return; +#endif + } + this->clear(); + } + + template + auto emit( Args&& ...arg ) const { + auto ref = _host.shared_from_this(); + return sigc::signal::emit( std::forward(arg)...); + } + + template + auto operator()( Args&& ...arg ) const { + //auto ref = _host.shared_from_this(); + return sigc::signal::operator()( std::forward(arg)...); + } + + private: + SignalHost &_host; + }; + + namespace internal { + + /*! + * Helper tool that always locks the public object in case a BasePrivate derived type + * is passed. + */ + template + inline auto lock_shared_makeLock ( const T& locker ) { + try { + if constexpr ( std::is_base_of_v ) { + return locker.z_func()->shared_from_this(); + } else { + return locker.shared_from_this(); + } + } catch ( const std::bad_weak_ptr &e ) { + ZYPP_CAUGHT( e ); + ZYPP_THROW( e ); + } + } + + /*! + * Adaptor that locks and tracks the given objects, this implements locking + * of the receiver object in a signal chain. + */ + template + struct lock_shared : public sigc::adapts + { + template + decltype(auto) operator()( Args&&... args ) const { + + try { + auto __attribute__ ((__unused__)) lck = std::apply( []( auto&... lockers ) { + return std::make_tuple( lock_shared_makeLock( lockers.invoke() )... ); + }, _lcks ); + + // seems the overloaded function templates in sigc++2 force us to fully specify the overload + // we want to use. std::invoke() fails in that case. + //return std::invoke( this->functor_, std::forward(args)... ); + if constexpr ( sizeof... (Args) == 0 ) { + return this->functor_(); + } else { + return this->functor_.template operator()(args) )...> ( std::forward(args)... ); + } + } catch ( const std::bad_weak_ptr &e ) { + ZYPP_CAUGHT( e ); + ERR << "Ignoring signal emit due to a bad_weak_ptr exception during object locking. Maybe the signal was sent to a object that is currently destructing?" << std::endl; +#ifndef ZYPP_NDEBUG + assert( false ); +#endif + if constexpr ( !std::is_same_v::result_type> ) + return typename sigc::adapts::result_type{}; + else + return; + } + } + + // Constructs a my_adaptor object that wraps the passed functor. + // Initializes adapts::functor_, which is invoked from operator()(). + explicit lock_shared( const T_functor& functor, const Lockers&... lcks ) : + sigc::adapts(functor), + _lcks( lcks... ) + {} + + std::tuple...> _lcks; + }; + + template< typename Functor, typename ...Obj > + inline decltype(auto) locking_fun( const Functor &f, const Obj&... o ) + { + return lock_shared( f, o...); + } + + } +#endif + + template + class SignalProxy; + + /** + * Hides the signals emit function from external code. + * + * \note based on Glibmms SignalProxy code + */ + template + class SignalProxy + { + public: + using SignalType = SignalProxyBase; + + SignalProxy ( SignalType &sig ) : _sig ( sig ) {} + + /** + * Forwards the arguments to the internal connect function of the signal type + */ + template + connection connect( Args&&... slot ) + { + return _sig.connect( std::forward(slot)... ); + } + + private: + SignalType &_sig; + }; + +} + +#ifndef ENABLE_SYWU +// +// Specialization of sigc::visitor for lock_shared. +namespace sigc +{ + template + struct visitor > + { + template + static void do_visit_each(const T_action& action, + const zyppng::internal::lock_shared& target) + { + sigc::visit_each(action, target.functor_); + std::apply( [&]( auto&... a) { + ((void)sigc::visit_each(action, a),...); + }, target._lcks ); + + } + }; +} // end namespace sigc +#endif + +#endif // ZYPP_NG_CORE_SIGNALS_H_INCLUDED diff --git a/zypp-core/zyppng/base/socketnotifier.cc b/zypp-core/zyppng/base/socketnotifier.cc new file mode 100644 index 0000000..641c80e --- /dev/null +++ b/zypp-core/zyppng/base/socketnotifier.cc @@ -0,0 +1,92 @@ +#include "socketnotifier.h" +#include "private/abstracteventsource_p.h" + +namespace zyppng { + +class SocketNotifierPrivate : public AbstractEventSourcePrivate +{ + ZYPP_DECLARE_PUBLIC(SocketNotifier) +public: + + SocketNotifierPrivate ( SocketNotifier &p ) : + AbstractEventSourcePrivate(p){} + + Signal< void (const SocketNotifier &, int)> _activated; + + int _socket = -1; + int _mode = SocketNotifier::Read; + bool _enabled = false; + +}; + + +ZYPP_IMPL_PRIVATE( SocketNotifier ) + +SocketNotifier::SocketNotifier (int socket, int evTypes ) + : AbstractEventSource ( * new SocketNotifierPrivate( *this ) ) +{ + Z_D(); + d->_socket = socket; + d->_mode = evTypes; +} + +SocketNotifier::Ptr SocketNotifier::create(int socket, int evTypes, bool enable ) +{ + auto ptr = std::shared_ptr( new SocketNotifier( socket, evTypes ) ); + ptr->setEnabled( enable ); + return ptr; +} + +void SocketNotifier::setMode(int mode) +{ + Z_D(); + if ( mode == d->_mode ) + return; + + d->_mode = mode; + + if ( d->_enabled && d->_socket >= 0) + updateFdWatch( d->_socket, d->_mode ); +} + +int SocketNotifier::mode() const +{ + return d_func()->_mode; +} + +void SocketNotifier::setEnabled( bool enabled ) +{ + Z_D(); + if ( enabled == d->_enabled || d->_socket < 0 ) + return; + + d->_enabled = enabled; + + if ( enabled ) + updateFdWatch( d->_socket, d->_mode ); + else + removeFdWatch( -1 ); +} + +int SocketNotifier::socket() const +{ + return d_func()->_socket; +} + +SignalProxy SocketNotifier::sigActivated() +{ + return d_func()->_activated; +} + +void SocketNotifier::onFdReady( int, int events ) +{ + d_func()->_activated.emit( *this, events ); +} + +void SocketNotifier::onSignal( int ) +{ } + + +} + + diff --git a/zypp-core/zyppng/base/socketnotifier.h b/zypp-core/zyppng/base/socketnotifier.h new file mode 100644 index 0000000..f98e312 --- /dev/null +++ b/zypp-core/zyppng/base/socketnotifier.h @@ -0,0 +1,124 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPPNG_BASE_SOCKETNOTIFIER_H_DEFINED +#define ZYPPNG_BASE_SOCKETNOTIFIER_H_DEFINED + +#include +#include +#include + +namespace zyppng { +class SocketNotifierPrivate; + +/*! + * The SocketNotifier class provides a generic way to monitor activity on a file descriptors. + * + * Once a file descriptor was created using either low level OS API or was created by a 3rd party + * library, the SocketNotifier can be created to integrate the file descriptor into the event loop. + * + * Each file descriptor can be monitored for all types of activiy supported by the base class \sa AbstractEventSource. + * + * \code + * // Example code that uses a pipe() to communicate between a thread and the main loop + * zyppng::EventLoop::Ptr loop = zyppng::EventLoop::create(); + * + * int wakeupPipe[2] = { -1, -1 }; + * pipe2 ( wakeupPipe, O_NONBLOCK ); + * + * //listen for activity on the event source + * zyppng::SocketNotifier::Ptr notifier = zyppng::SocketNotifier::create( wakeupPipe[0], zyppng::SocketNotifier::Read, false ); + * notifier->sigActivated().connect([ &loop ]( const zyppng::SocketNotifier ¬ifier, int ) { + * char dummy; + * //read all available data + * while ( read( notifier.socket(), &dummy, 1 ) > 0 ) { + * std::cout<quit(); + * }); + * notifier->setEnabled( true ); + * + * std::thread t( [ &wakeupPipe ](){ + * const char * test = "Some text"; + * std::chrono::milliseconds dura( 1000 ); + * std::this_thread::sleep_for( dura ); + * write( wakeupPipe[1], test, 9 ); + * std::this_thread::sleep_for( dura ); + * return; + * }); + * + * loop->run(); + * + * std::cout << "Bye Bye" << std::endl; + * t.join(); + * \endcode + */ +class SocketNotifier : public AbstractEventSource +{ + ZYPP_DECLARE_PRIVATE( SocketNotifier ) +public: + + using Ptr = std::shared_ptr; + using WeakPtr = std::weak_ptr; + + using EventTypes = AbstractEventSource::EventTypes; + + /*! + * Returns a new SocketNotifier + * \param socket this is the filedescriptor to be modified + * \param evTypes the event types that should be monitored \sa AbstractEventSource::EventTypes + * \param enable If set to true the notifier is enabled right away, otherwise \sa setEnabled needs to be called explicitely + */ + static Ptr create ( int socket, int evTypes, bool enable = true ); + + /*! + * Update the fd watch to the \a mode specified. + * \sa AbstractEventSource::EventTypes + */ + void setMode ( int mode ); + + /*! + * Returns the current mode used to monitor the file descriptor + * \sa AbstractEventSource::EventTypes + */ + int mode () const; + + /*! + * Enables or disables the SocketNotifier + */ + void setEnabled ( bool enabled = true ); + + /*! + * Returns the monitored file descriptor + */ + int socket () const; + + /*! + * Emitted when there is activity on the socket according to the requested mode + */ + SignalProxy sigActivated(); + +protected: + SocketNotifier( int socket, int evTypes ); + + // AbstractEventSource interface +public: + void onFdReady(int, int events) override; + void onSignal(int signal) override; +}; + +} + +#endif diff --git a/zypp-core/zyppng/base/statemachine.h b/zypp-core/zyppng/base/statemachine.h new file mode 100644 index 0000000..9da8aa5 --- /dev/null +++ b/zypp-core/zyppng/base/statemachine.h @@ -0,0 +1,608 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_BASE_STATEMACHINE_INCLUDED_H +#define ZYPP_NG_BASE_STATEMACHINE_INCLUDED_H + +#include +#include + +#include +#include +#include +#include +#include + +namespace zyppng { + + namespace detail { + + template + using EventSource = SignalProxy (T::*)(); + + /** + * \internal + * Internal helper type to wrap the user implemented state types. + * It's mostly used to have a container for the Transitions that belong to the State. + */ + template < class State, class Transitions > + struct StateWithTransitions { + using StateType = State; + Transitions _transitions; + + template< typename StateMachine > + StateWithTransitions ( StateMachine &sm ) : _ptr ( std::make_shared( sm )) { } + StateWithTransitions ( std::shared_ptr &&s ) : _ptr ( std::move(s) ) {} + + // move construction is ok + StateWithTransitions ( StateWithTransitions &&other ) = default; + StateWithTransitions &operator= ( StateWithTransitions &&other ) = default; + + // no copy construction + StateWithTransitions ( const StateWithTransitions &other ) = delete; + StateWithTransitions &operator= ( const StateWithTransitions &other ) = delete; + + static constexpr auto stateId = State::stateId; + static constexpr bool isFinal = State::isFinal; + + void enter( ) { + // keep the pointer around, for we might transition to the next state immediately + auto keepAlive = _ptr; + return keepAlive->enter( ); + } + + void exit( ) { + // keep the pointer around, for we might transition to the next state immediately + auto keepAlive = _ptr; + return keepAlive->exit( ); + } + + std::shared_ptr wrappedState () { + return _ptr; + } + + const std::shared_ptr wrappedState () const { + return _ptr; + } + + private: + // we need to use a std::shared_ptr here so we can correctly reference the object during signal emission + std::shared_ptr _ptr; + }; + + + /** + * this adds the type \a NewType to the collection if the condition is true + */ + template < template typename Templ , typename NewType, typename TupleType, bool condition > + struct add_type_to_collection; + + template < template typename Templ, typename NewType, typename ...Types > + struct add_type_to_collection< Templ, NewType, Templ, true > { + using Type = Templ; + }; + + template < template typename Templ, typename NewType, typename ...Types > + struct add_type_to_collection< Templ, NewType, Templ, false > { + using Type = Templ; + }; + + /** + * Constexpr function that evaluates to true if a variant type \a Variant already contains the type \a Type. + * The \a Compare argument can be used to change how equality of a type is calculated + */ + template < typename Variant, typename Type, template typename Compare = std::is_same, size_t I = 0 > + constexpr bool VariantHasType () { + // cancel the evaluation if we entered the last type in the variant + if constexpr ( I >= std::variant_size_v ) { + return false; + } else { + // if the current type in the variant is the same as the one we are looking for evaluate to true + if ( Compare< std::variant_alternative_t< I, Variant>, Type >::value ) + return true; + + // otherwise call the next iteration with I+1 + return VariantHasType(); + } + } + + /** + * collect all transitions that have the same SourceState as the first type argument + */ + template< class State, class TupleSoFar, class Head, class ...Transitions > + struct collect_transitions_helper { + using NewTuple = typename add_type_to_collection< std::tuple, Head, TupleSoFar, std::is_same_v< State, typename Head::SourceType> >::Type; + using Type = typename collect_transitions_helper::Type; + }; + + template< class State, class TupleSoFar, class Head > + struct collect_transitions_helper { + using Type = typename add_type_to_collection< std::tuple, Head, TupleSoFar, std::is_same_v< State, typename Head::SourceType> >::Type; + }; + + template< class State, class ...Transitions > + struct collect_transitions{ + using Type = typename collect_transitions_helper< State, std::tuple<>, Transitions... >::Type; + }; + + /** + * Iterates over the list of Transitions and collects them all in a std::variant type + */ + template + struct make_state_set_helper { + using WithSource = typename add_type_to_collection< std::variant, typename Head::SourceType, VariantSoFar, !VariantHasType() >::Type; + using WithTarget = typename add_type_to_collection< std::variant, typename Head::TargetType, WithSource, !VariantHasType() >::Type; + using Type = typename make_state_set_helper::Type; + }; + + template + struct make_state_set_helper< VariantSoFar, Head > { + using WithSource = typename add_type_to_collection< std::variant, typename Head::SourceType, VariantSoFar, !VariantHasType() >::Type; + using Type = typename add_type_to_collection< std::variant, typename Head::TargetType, WithSource, !VariantHasType() >::Type; + }; + + template + struct make_state_set { + using InitialVariant = std::variant; + using VariantSoFar = typename add_type_to_collection< std::variant, typename Head::TargetType, InitialVariant , !VariantHasType() >::Type; + using Type = typename make_state_set_helper< VariantSoFar, Transitions...>::Type; + }; + + + /** + * Evaluates to true if type \a A and type \a B wrap the same State type + */ + template + struct is_same_state : public std::is_same< typename A::StateType, typename B::StateType> {}; + + + /** + * Turns a State type into its StateWithTransitions counterpart + */ + template + struct make_statewithtransition { + using Type = StateWithTransitions::Type>; + }; + + /** + * Iterates over each State in the \a StateVariant argument, collects the corresponding + * Transitions and combines the results in a std::variant< StateWithTransitions<...>,... > type. + */ + template + struct make_statewithtransition_set_helper; + + template + struct make_statewithtransition_set_helper< VariantSoFar, std::variant, Transitions... > { + using FullStateType = typename make_statewithtransition::Type; + using NewVariant = typename add_type_to_collection< std::variant, FullStateType, VariantSoFar, !VariantHasType()>::Type; + using Type = typename make_statewithtransition_set_helper< NewVariant, std::variant, Transitions...>::Type; + }; + + template + struct make_statewithtransition_set_helper< VariantSoFar, std::variant, Transitions... > { + using FullStateType = typename make_statewithtransition::Type; + using Type = typename add_type_to_collection< std::variant, FullStateType, VariantSoFar, !VariantHasType()>::Type; + }; + + template + struct make_statewithtransition_set; + + template + struct make_statewithtransition_set< NoState, std::variant, Transitions...>{ + using FirstState = typename make_statewithtransition< HeadState, Transitions...>::Type; + using Type = typename make_statewithtransition_set_helper< std::variant, std::variant, Transitions...>::Type; + }; + } + + constexpr bool DefaultStateCondition(true); + constexpr std::nullptr_t DefaultStateTransition(nullptr); + + /*! + * Defines a transition between \a Source and \a Target states. + * The EventSource \a ev triggers the transition from Source to Target if the condition \a Cond + * evaluates to true. The operation \a Op is called between exiting the old and entering the new state. + * It can be used to transfer information from the old into the new state. + * + * \tparam Source defines the type of the Source state + * \tparam ev takes a member function pointer returning the event trigger signal that is used to trigger the transition to \a Target + * \tparam Target defines the type of the Target state + * \tparam Cond Defines the transition condition, can be used if the same event could trigger different transitions + * based on a condition, this can also be set to a simple boolean true or false + * \tparam Op defines the transition operation from Source to Target states, + * this is either a function with the signature: std::unique_ptr ( Statemachine &, Source & ) + * or it can be a member function pointer of Source with the signature: std::unique_ptr ( Source::* ) ( ) + * + * \note While it would be possible to implement the statemachine to operate only on non pointer types for the states , + * I chose to use std::unique_ptr instead to make the handling of States with signals less error prone. Because even move + * assigning a signal that has connected lambda slots which have captured the this pointer will break the code. While it could + * be worked around to connect and disconnect signals in the enter() and exit() functions not doing so would crash the code. Leaving that + * note here in case we want to change that behaviour in the future. + */ + template < + typename Source, + detail::EventSource ev , + typename Target, + auto Cond = DefaultStateCondition, + auto Op = DefaultStateTransition > + struct Transition { + + using SourceType = Source; + using TargetType = Target; + + + template< typename Statemachine > + std::shared_ptr operator() ( Statemachine &sm, Source &oldState ) { + using OpType = std::decay_t; + // check if we have a member function pointer + if constexpr ( std::is_member_function_pointer_v ) { + return std::invoke( Op, &oldState ); + } else if constexpr ( std::is_null_pointer_v ) { + return std::make_shared(sm); + } else { + return std::invoke( Op, sm, oldState ); + } + } + + bool checkCondition ( Source ¤tState ) { + using CondType = std::decay_t; + if constexpr ( std::is_same_v ) { + return Cond; + } else if constexpr ( std::is_member_function_pointer_v ) { + return std::invoke( Cond, ¤tState ); + } else { + return std::invoke( Cond, currentState ); + } + } + + SignalProxy< void() > eventSource ( Source *st ) { + return std::invoke( ev, st ); + } + + auto eventAccessor () const { + return ev; + } + + }; + + /*! + * \brief This defines the actual StateMachine. + * \tparam Derived is the Statemachine subclass type, this is used to pass a reference to the actual implementation into the State functions. + * \tparam StateId should be a enum with a ID for each state the SM can be in. + * \tparam Transitions variadic template argument taking a list of all \ref Transition types the statemachine should support. + * The First Source State in the Transitions List is always the initial state. + * + * Implementation of a simple signal based statemachine, each state is a user defined state type that has to implement a specific API in order to be compatible. + * No inheritance is required to use the statemachine and everything will be resolved at compile time. + * + * This is how a basic statemachine implementation would look like + * + * \code + * + * // Each state should have a representation in the enum + * enum States { + * StateA, + * StateB, + * ... + * } + * + * class MyStateMachine; + * class State; + * class StateB; + * class StateC; + * class StateD; + * + * // states are just simple types with a few required functions, there is a helper class + * // SimpleState<> to help with the implementation + * class StateA { + * + * // the ID of the state + * static constexpr auto stateId = States::StateA; + * + * // is this a final state? + * static constexpr bool isFinal = false; + * + * // constructor taking the parent statemachine type + * StateA ( MyStateMachine &parent ) {} + * + * // function called when the state is first entered + * void enter() {} + * + * // function called when the state is exited + * void exit () {} + * + * // a state that is not final needs event sources + * SignalProxy sigTransition (); + * + * // a state might even define a transition function to the target states + * std::unique_ptr transitionToB (); + * + * // also condition functions can be defined in a state: + * bool transitionToStateBCondition() const; + * } + * + * // transition functions can also be defined as free functions or static member functions with the signature: + * std::unique_ptr transitionStateBToStateC ( MyStateMachine &sm, StateB &oldState ); + * + * // condition functions can also be defined as free functions or static member functions with the signature: + * bool transitionStateAToStateDCondition( State ¤tState ); + * + * + * // implementing the statemachine itself, using a template helper for better readability: + * template + * using SmBase = zyppng::Statemachine, + * zyppng::Transition< StateB, &StateB::sigTransition, StateD >>; + * + * // by using CRTP we can have a reference to the concrete Statemachine type in the States, allowing us to be much + * // more flexible with the implementation, since all states can now access API exported by the MyStateMachine type. + * // since the Statemachine uses signals, make sure to derive it also from the \ref zyppng::Base type. + * class MyStateMachine : public SmBase, public Base { }; + * + * \endcode + * + * In order to advance the statemachine, each state will have at least one signal ( event ) that tells the statemachine to transition to the next state, optionally + * a condition can be used to block the transition in certain cases. When transitioning from one state to the other a transition operation will be called that + * creates the instance of the target state and do other initializations or can move data from the old to the new state. The default version of the operation just + * returns a new instance of the target state. + * If a signal or event is used multiple times to trigger transitions, only the first transition whose condition evaluates to true will be triggered. All other transitions + * with the same trigger signal will not be even evaluated. + * + * After instantiating the statemachine will be in a internal intial state, in order to move to the first user defined state \ref Statemachine::start must be called. + */ + template < typename Derived, typename StateId, typename ...Transitions > + class Statemachine { + + struct _InitialState{}; + + public: + + using AllStates = typename detail::make_state_set< Transitions... >::Type; + using StateSetHelper = typename detail::make_statewithtransition_set< _InitialState, AllStates, Transitions... >; + using FState = typename StateSetHelper::FirstState; + using StateSet = typename StateSetHelper::Type; + + using StatemachineType = Statemachine< Derived, StateId, Transitions...>; + + public: + Statemachine () { } + virtual ~Statemachine() {} + + /*! + * Advances the state machine into the initial state. + */ + void start () { + if ( _state.index() == 0 || _isInFinalState ) { + _previousState.reset(); + _isInFinalState = false; + _emittedFinalSig = false; + enterState( FState( static_cast(*this) ) ); + } + } + + template + auto visitState ( Func && f ) { + return std::visit( [ func = std::forward(f) ] ( auto &s ) { + using T = std::decay_t; + if constexpr ( std::is_same_v< T, _InitialState > ) { + throw std::exception(); + } else { + auto lock = s.wrappedState(); + return ( func( *lock ) ); + } + }, _state ); + } + + /*! + * Returns the current stateId of the state the SM is currently in. + * If called before start() was called the std::optional will be empty + */ + std::optional currentState () const { + return std::visit( []( const auto &s ) -> std::optional { + using T = std::decay_t; + if constexpr ( std::is_same_v< T, _InitialState > ) { + return {}; + } else { + return T::stateId; + } + }, _state ); + } + + /*! + * Returns the ID of the previous state, or a invalid optional if there + * was no previous state. + */ + std::optional previousState () const { + return _previousState; + } + + /*! + * Returns a reference to the current state object, will throw a exception + * if the passed state type does not match the current states type. + */ + template + std::shared_ptr state () { + using WrappedEventType = typename detail::make_statewithtransition< std::decay_t, Transitions...>::Type; + return std::get( _state ).wrappedState(); + } + + /*! + * Returns a reference to the current state object, will throw a exception + * if the passed state type does not match the current states type. + */ + template + const std::shared_ptr state () const { + using WrappedEventType = typename detail::make_statewithtransition< std::decay_t, Transitions...>::Type; + return std::get( _state ).wrappedState(); + } + + /*! + * Forces the statemachine to enter a specific state, a transition operation will not + * be executed, but the exit() function of the current state will be called. + */ + template + void forceState ( std::unique_ptr &&nS ) { + using WrappedSType = typename detail::make_statewithtransition< std::decay_t, Transitions...>::Type; + std::visit( [this, &nS]( auto &currState ) { + using T = std::decay_t; + if constexpr ( std::is_same_v< T, WrappedSType > ) { + return; + } else if constexpr ( std::is_same_v< T, _InitialState > ) { + enterState ( WrappedSType( std::move(nS) ) ); + } else { + enterState ( currState, WrappedSType( std::move(nS) ) ); + } + }, _state ); + } + + /*! + * Emitted when the statemachine enters a type that has final set to true. + */ + SignalProxy sigFinished () { + return _sigFinished; + } + + /*! + * Emitted everytime the statemachine advanced to a new state, carrying the + * new state's ID. + * \note this signal is emitted before State::enter() is executed, the State object + * however is already created and can be accessed via \ref Statemachine::state() + */ + SignalProxy sigStateChanged () { + return _sigStateChanged; + } + + protected: + + template + void enterState ( OldState &os, NewState &&nS ) { + // disconnect all signals from the current state + clearConnections(); + std::forward(os).exit(); + _previousState = OldState::stateId; + enterState( std::forward(nS) ); + } + + template + void enterState ( NewState &&nS ) { + + if constexpr ( !NewState::isFinal ) { + connectAllTransitions<0>( nS, nS._transitions ); + } + + _state.template emplace( std::forward(nS) ); + + // handle final state things + if constexpr ( NewState::isFinal ) { + _isInFinalState = true; + _emittedFinalSig = false; + } + + // let the outside world know whats going on + _sigStateChanged.emit( NewState::stateId ); + + // call enter on the state as the last thing to do, it might emit a transition event right away + std::get< std::decay_t >( _state ).enter(); + + // emit the final signal, but only if it was not already emitted by a subsequent transition + if ( _isInFinalState && !_emittedFinalSig ) { + _emittedFinalSig = true; + _sigFinished.emit(); + } + + } + + template + auto makeEventCallback ( Transition &transition ) { + using WrappedEventType = typename detail::make_statewithtransition< typename Transition::TargetType, Transitions...>::Type; + return [ mytrans = &transition, this]() mutable { + auto stateLock = std::get< std::decay_t >(_state).wrappedState(); + if ( mytrans->checkCondition( *stateLock ) ) { + auto &st = std::get< std::decay_t >(_state); + enterState( st , WrappedEventType( (*mytrans)( static_cast(*this), *stateLock ) ) ); + } + }; + } + + template< std::size_t I = 0, typename State, typename ...StateTrans> + void connectAllTransitions( State &&nS, std::tuple &transitions ) { + if constexpr (I >= sizeof...(StateTrans)) { + return; + } else { + auto &transition = std::get( transitions ); + //_currentStateConnections.push_back( transition.eventSource ( std::forward(nS).wrappedState().get() ).connect( makeEventCallback< std::decay_t >(transition)) ); + _currentStateConnections.push_back( std::forward(nS).wrappedState()->Base::connectFunc( transition.eventAccessor(), makeEventCallback< std::decay_t >(transition), *static_cast(this) ) ); + connectAllTransitions( std::forward(nS), transitions ); + } + } + + void clearConnections () { + for ( auto &c : _currentStateConnections ) + c.disconnect(); + _currentStateConnections.clear(); + } + + private: + bool _isInFinalState = false; + bool _emittedFinalSig = false; //< Flag to make sure the finished signals is only emitted once + Signal _sigStateChanged; + Signal _sigFinished; + StateSet _state = _InitialState(); + std::optional _previousState; + std::vector _currentStateConnections; + }; + + /*! + * Implements the most basic parts of a State, + * the functions enter() and exit() still need to be implemented in the base class + */ + template < typename StatemachineType, bool isFin > + class BasicState : public Base { + public: + + static constexpr bool isFinal = isFin; + + BasicState( StatemachineType &sm ) : _sm( sm ){} + ~BasicState() override {} + + BasicState( BasicState && ) noexcept = default; + BasicState &operator= ( BasicState && ) noexcept = default; + + StatemachineType &stateMachine () { + return _sm; + } + + const StatemachineType &stateMachine () const { + return _sm; + } + + private: + StatemachineType &_sm; + + }; + + /*! + * Helper type that also includes the State ID, in more complex state machines + * utilizing subclassing in their State objects, + * it might be desireable to have the State ID in the final class implementation + */ + template < typename StatemachineType, auto sId, bool isFin > + class SimpleState : public BasicState { + public: + static constexpr auto stateId = sId; + using BasicState::BasicState; + }; + +} + +#endif // ZYPP_NG_BASE_STATEMACHINE_INCLUDED_H diff --git a/zypp-core/zyppng/base/threaddata.cc b/zypp-core/zyppng/base/threaddata.cc new file mode 100644 index 0000000..8d1a6f5 --- /dev/null +++ b/zypp-core/zyppng/base/threaddata.cc @@ -0,0 +1,64 @@ +#include "private/threaddata_p.h" +#include "private/eventdispatcher_glib_p.h" +#include +#include //for std::endl +#include +#include + +namespace zyppng +{ + ThreadData::ThreadData() + : _threadId( std::this_thread::get_id() ), + _nativeHandle( pthread_self() ) + { + } + + ThreadData &ThreadData::current() + { + static thread_local ThreadData data; + return data; + } + + const std::string &ThreadData::name() const + { + if ( _threadName.empty() ) { + std::stringstream strStr; + strStr << _threadId; + _threadName = strStr.str(); + } + return _threadName; + } + + std::shared_ptr ThreadData::ensureDispatcher() + { + auto sp = _dispatcher.lock(); + if (!sp) { + MIL << "Creating the Event Dispatcher for thread: " << name() << "("<<_threadId<<")" << std::endl; + _dispatcher = sp = EventDispatcherPrivate::create(); + } + return sp; + } + + void ThreadData::setDispatcher( const std::shared_ptr &disp ) + { + if ( _dispatcher.lock() ) { + WAR << "Dispatcher was already created for the current thread" << std::endl; + return; + } + _dispatcher = disp; + } + + void ThreadData::syncNativeName() + { + // length is restricted to 16 characters, including the terminating null byte ('\0') + pthread_setname_np( _nativeHandle, name().substr(0,15).c_str() ); + } + + std::shared_ptr ThreadData::dispatcher() { + auto sp = _dispatcher.lock(); + if (!sp) { + MIL << "Requested Event Dispatcher for thread: " << name() << "("<<_threadId<<") but none was created." << std::endl; + } + return sp; + } +} // namespace zyppng diff --git a/zypp-core/zyppng/base/timer.cc b/zypp-core/zyppng/base/timer.cc new file mode 100644 index 0000000..29bc51c --- /dev/null +++ b/zypp-core/zyppng/base/timer.cc @@ -0,0 +1,192 @@ +#include "timer.h" +#include "private/base_p.h" + +#include "eventdispatcher.h" + +#include +#include +#include + +namespace zyppng { + +using namespace zypp; + + +class TimerPrivate : BasePrivate +{ + ZYPP_DECLARE_PUBLIC(Timer) +public: + TimerPrivate(Timer &p); + + TimerPrivate(const TimerPrivate &) = delete; + TimerPrivate(TimerPrivate &&) = delete; + TimerPrivate &operator=(const TimerPrivate &) = delete; + TimerPrivate &operator=(TimerPrivate &&) = delete; + + ~TimerPrivate() override; + + uint64_t _beginMs = 0; + uint64_t _requestedTimeout = 0; + std::weak_ptr _ev; + bool _isRunning = false; + + Signal< void (Timer &t)> _expired; + + bool _singleShot = false; + +}; + +ZYPP_IMPL_PRIVATE(Timer) + +TimerPrivate::TimerPrivate(Timer &p) : BasePrivate(p) +{ + auto ev = EventDispatcher::instance(); + if ( !ev ) + ZYPP_THROW( zypp::Exception( "Creating timers without a EventDispatcher instance is not supported" ) ); + _ev = ev; +} + +TimerPrivate::~TimerPrivate() +{} + +std::shared_ptr Timer::create() +{ + return std::shared_ptr( new Timer() ); +} + +Timer::~Timer() +{ stop(); } + +void Timer::setSingleShot(bool singleShot) +{ + d_func()->_singleShot = singleShot; +} + +bool Timer::singleShot() const +{ + return d_func()->_singleShot; +} + +uint64_t Timer::now() +{ + return static_cast( g_get_monotonic_time () / 1000 ); +#if 0 + timespec now{0 ,0}; + if ( clock_gettime( CLOCK_MONOTONIC_RAW, &now ) ) { + WAR << "Unable to get current monotonic time, timers will not work" << std::endl; + return 1; + } + return ( uint(now.tv_sec) * 1000 ) + uint( now.tv_nsec * 1e-6 ); +#endif +} + +uint64_t Timer::elapsedSince( const uint64_t start ) +{ + uint64_t nowMs = now(); + return ( nowMs - start ); +} + +uint64_t Timer::started() const +{ + return d_func()->_beginMs; +} + +uint64_t Timer::interval() const +{ + return d_func()->_requestedTimeout; +} + +uint64_t Timer::remaining() const +{ + Z_D(); + + uint64_t elapsed = this->elapsed(); + if ( elapsed >= d->_requestedTimeout ) + return 0; + return ( d->_requestedTimeout - elapsed ); +} + +uint64_t Timer::elapsed() const +{ + Z_D(); + return elapsedSince( d->_beginMs ); +} + +uint64_t Timer::expires() const +{ + return d_func()->_beginMs + d_func()->_requestedTimeout; +} + +SignalProxy Timer::sigExpired() +{ + return d_func()->_expired; +} + +uint64_t Timer::expire() +{ + Z_D(); + //@FIXME, we should not rely on this, maybe a "deleteLater" feature + //in the MainLoop? + //make sure timer is not deleted during signal emission + auto lock = shared_from_this(); + + auto exp = remaining(); + if ( exp == 0 ) { + if ( d->_singleShot ) + stop(); + else + d->_beginMs = now(); + d->_expired.emit( *this ); + } + return exp; +} + +bool Timer::isRunning() const +{ + return d_func()->_isRunning; +} + +void Timer::start() +{ + start ( d_func()->_requestedTimeout ); +} + +void Timer::start( uint64_t timeout ) +{ + Z_D(); + + d->_requestedTimeout = timeout; + d->_beginMs = now(); + + if ( !d->_isRunning ) { + auto ev = d->_ev.lock(); + //if ev is null we are shutting down + if ( !ev ) + return; + ev->registerTimer( *this ); + + d->_isRunning = true; + } + +} + +void Timer::stop() +{ + Z_D(); + + if ( !d->_isRunning ) + return; + + auto ev = d->_ev.lock(); + + //event loop might be shutting down + if ( ev ) + ev->removeTimer( *this ); + + d->_isRunning = false; +} + +Timer::Timer() : Base ( *new TimerPrivate( *this ) ) +{ } + +} diff --git a/zypp-core/zyppng/base/timer.h b/zypp-core/zyppng/base/timer.h new file mode 100644 index 0000000..0f50efe --- /dev/null +++ b/zypp-core/zyppng/base/timer.h @@ -0,0 +1,146 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_BASE_TIMER_H_INCLUDED +#define ZYPP_NG_BASE_TIMER_H_INCLUDED + +#include +#include +#include +#include + +namespace zyppng { + +class TimerPrivate; +class EventDispatcher; +ZYPP_FWD_DECL_TYPE_WITH_REFS (Timer); + +/*! + * \brief The Timer class provides repetitive and single-shot timers. + * + * Provides a high level interface for timers. To use it, create a Timer and + * connect a slot to its \sa sigExpired signal. + * + * \code + * zyppng::Timer::Ptr t1 = zyppng::Timer::create(); + * t1->sigExpired().connect( sigc::mem_fun(this, &HandlerClass::timeout) ); + * t1->start(1000); + * \endcode + * + * The timeout slot will now be called every second. + * + * \note The accuracy of the timer should be around 1ms , but also depends on the underlying hardware. + */ +class Timer : public Base +{ + ZYPP_DECLARE_PRIVATE(Timer) + friend class EventDispatcher; + +public: + + using Ptr = std::shared_ptr; + using WeakPtr = std::shared_ptr; + + /*! + * \brief Creates a new Timer object, the timer is not started at this point + */ + static std::shared_ptr create (); + ~Timer () override; + + /*! + * \brief Sets the timer to trigger only once, after it has expired once + * \sa start needs to be called again + */ + void setSingleShot ( bool singleShot = true ); + + /*! + * \returns true if the timer is a single shot timer + */ + bool singleShot () const; + + /*! + * \returns The current monotonic system time in milliseconds + */ + static uint64_t now (); + + /*! + * \return the time that has elapsed since the timepoint given in \a start + */ + static uint64_t elapsedSince ( const uint64_t start ); + + /*! + * \returns the monotonic system time when the timer started + */ + uint64_t started () const; + + /*! + * \returns the requested interval in milliseconds + */ + uint64_t interval () const; + + /*! + * \returns the remaining time until the timer expires in milliseconds + */ + uint64_t remaining () const; + + /*! + * \return the time that has elapsed since the last call to \a start in milliseconds + */ + uint64_t elapsed () const; + + /*! + * \returns the monotonic system time in ms when the timer is about to expire + */ + uint64_t expires () const; + + /*! + * \brief Advances the internal clock of the timer, if the timer expires the \a sigExpired signal is emitted + * + * \returns the monotonic system time in ms when the timer is about to expire + * \note There should not be any reason to call this manually, the \sa EventDispatcher is taking care of that + */ + uint64_t expire (); + + /*! + * \returns if the timer is currently active + */ + bool isRunning ( ) const; + + /*! + * Starts the timer, if the timer is already running this will restart the currently running timer + */ + void start ( ); + + /*! + * \brief Starts the timer, if the timer is already running this will restart the currently running timer + * \param timeout the new timeout in ms + */ + void start ( uint64_t timeout ); + + /*! + * \brief Stops the timer if it is running. The \sa sigExpired signal will not emit until \sa start was called again. + */ + void stop (); + + /*! + * \brief This signal is always emitted when the timer expires. + */ + SignalProxy sigExpired (); + +protected: + Timer (); +}; + +} + +#endif diff --git a/zypp-core/zyppng/base/unixsignalsource.cpp b/zypp-core/zyppng/base/unixsignalsource.cpp new file mode 100644 index 0000000..0686f33 --- /dev/null +++ b/zypp-core/zyppng/base/unixsignalsource.cpp @@ -0,0 +1,156 @@ +#include "unixsignalsource.h" +#include "private/abstracteventsource_p.h" +#include +#include +#include +#include + +#include +#include + +namespace zyppng { + + class UnixSignalSourcePrivate : public AbstractEventSourcePrivate + { + ZYPP_DECLARE_PUBLIC(UnixSignalSource) + public: + UnixSignalSourcePrivate( UnixSignalSource &p ) : AbstractEventSourcePrivate(p) { + ::sigemptyset ( &_orgSigMask ); + pthread_sigmask (SIG_SETMASK, nullptr, &_orgSigMask); + } + + sigset_t _orgSigMask; + zypp::AutoFD _signalFd; + std::unordered_map _signalRefCount; + Signal _sigReceived; + }; + + ZYPP_IMPL_PRIVATE (UnixSignalSource); + + UnixSignalSource::UnixSignalSource() : AbstractEventSource( *(new UnixSignalSourcePrivate(*this)) ) + { + } + + UnixSignalSource::~UnixSignalSource() + { + Z_D(); + // restore the original sigmask + pthread_sigmask (SIG_SETMASK, &d->_orgSigMask, nullptr); + } + + UnixSignalSourceRef UnixSignalSource::create() + { + return UnixSignalSourceRef( new UnixSignalSource() ); + } + + bool UnixSignalSource::addSignal(int signum ) + { + Z_D(); + + if ( d->_signalRefCount.count(signum) != 0 && d->_signalRefCount[signum] > 0 ) { + // we already handle this signal, just increase refcount + d->_signalRefCount[signum]++; + } else { + + const auto &handleError = [&]() { + d->_signalRefCount.erase ( signum ); + return false; + }; + + // add the signal to our map + d->_signalRefCount[signum] = 1; + + sigset_t sigMask; + sigemptyset (&sigMask ); + + // add all the signals we monitor to our set so we can update the signalfd correctly + for ( const auto &sig : d->_signalRefCount ) { + sigaddset(&sigMask, sig.first); + } + + // signalfd signals should be blocked + // man page says: The set of blocked signals is the union of the current set and the set argument. + // so we should not accidentially delete other blocks done by the application + if (pthread_sigmask (SIG_BLOCK, &sigMask, NULL) == -1) { + return handleError(); + } + + + // set or update our signal fd + zypp::AutoFD aFd = signalfd ( d->_signalFd, &sigMask, SFD_NONBLOCK | SFD_CLOEXEC ); + if ( aFd == -1 ){ + return handleError(); + } + + if ( d->_signalFd != aFd ) { + d->_signalFd = aFd; + } else { + aFd.resetDispose (); + } + updateFdWatch ( aFd, AbstractEventSource::Read ); + } + return true; + } + + bool UnixSignalSource::removeSignal(int signum ) + { + Z_D(); + if ( !d->_signalRefCount.count(signum) || d->_signalRefCount[signum] == 0 ) { + return true; + } + d->_signalRefCount[signum]--; + + if ( d->_signalRefCount[signum] <= 0 ) { + + d->_signalRefCount.erase(signum); + + // remove the signal from our fd + sigset_t sigMask; + sigemptyset ( &sigMask ); + for ( const auto &sig : d->_signalRefCount ) { + sigaddset(&sigMask, sig.first); + } + + auto res = signalfd ( d->_signalFd, &sigMask, SFD_NONBLOCK | SFD_CLOEXEC ); + if ( res == -1 ) { + WAR << "Failed to update signalfd with errno: " << zypp::Errno() << std::endl; + return false; + } + + // unblock the signal + sigemptyset ( &sigMask ); + sigaddset(&sigMask, signum); + pthread_sigmask(SIG_UNBLOCK, &sigMask, NULL); + } + + if ( d->_signalRefCount.size () == 0 ) { + removeFdWatch ( d->_signalFd ); + d->_signalFd = -1; + } + return true; + } + + SignalProxy UnixSignalSource::sigReceived() + { + return d_func()->_sigReceived; + } + + void zyppng::UnixSignalSource::onFdReady( int fd, int events ) + { + Z_D(); + struct signalfd_siginfo sfd_si; + if ( read(fd, &sfd_si, sizeof(sfd_si)) == -1 ) { + WAR << "Failed to read from signalfd" << std::endl; + return; + } + + if ( d->_signalRefCount.count ( sfd_si.ssi_signo )) + d->_sigReceived.emit( sfd_si.ssi_signo ); + else + WAR << "Received unexpected UNIX signal on signalFD: " << sfd_si.ssi_signo << std::endl; + } + + void zyppng::UnixSignalSource::onSignal( int signal ) + {} + +} // namespace zyppng diff --git a/zypp-core/zyppng/base/unixsignalsource.h b/zypp-core/zyppng/base/unixsignalsource.h new file mode 100644 index 0000000..1aefea7 --- /dev/null +++ b/zypp-core/zyppng/base/unixsignalsource.h @@ -0,0 +1,36 @@ +#ifndef ZYPPNG_UNIXSIGNALSOURCE_H +#define ZYPPNG_UNIXSIGNALSOURCE_H + +#include "abstracteventsource.h" + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS ( UnixSignalSource ); + ZYPP_FWD_DECL_TYPE_WITH_REFS ( EventDispatcher ); + class UnixSignalSourcePrivate; + + class UnixSignalSource : public AbstractEventSource + { + ZYPP_DECLARE_PRIVATE (UnixSignalSource); + public: + ~UnixSignalSource() override; + + bool addSignal( int signum ); + bool removeSignal( int signum ); + + SignalProxy sigReceived(); + + protected: + // AbstractEventSource interface + void onFdReady(int fd, int events) override; + void onSignal(int signal) override; + + private: + friend class EventDispatcher; + static UnixSignalSourceRef create (); + UnixSignalSource(); + + }; +} // namespace zyppng + +#endif // ZYPPNG_UNIXSIGNALSOURCE_H diff --git a/zypp-core/zyppng/base/zyppglobal.h b/zypp-core/zyppng/base/zyppglobal.h new file mode 100644 index 0000000..f562d36 --- /dev/null +++ b/zypp-core/zyppng/base/zyppglobal.h @@ -0,0 +1,228 @@ +#ifndef ZYPP_NG_BASE_ZYPPGLOBAL_H_INCLUDED +#define ZYPP_NG_BASE_ZYPPGLOBAL_H_INCLUDED + +#include +#include + +#ifndef EXPORT_EXPERIMENTAL_API +#define LIBZYPP_NG_EXPORT +#define LIBZYPP_NG_NO_EXPORT +#else +#include +#endif + +/* + * Convenience helpers to automatically generate boilerplate code + * for pimpl classes. + * + * Libzypp is using the PIMPL pattern to ensure binary compatiblity between + * different version releases. This keeps rebuilds of applications + * that link against libzypp to a minimum. A PIMPL class simply hides the + * data members and functions that are not part of the public API/ABI in a + * hidden private class, that is only accessible in the implementation files. + * This allows even bigger refactorings to happen behind the scenes. + * + * A simple example would be: + * + * \code + * + * // MyClass.h + * + * // forward declare the private class, always use the public classname + * // with a "Private" postfix: + * class MyClassPrivate; + * + * class MyClass + * { + * public: + * // add all public API functions here + * void doSomething(); + * int getSomething() const; + * private: + * // generate the forward declarations for the pimpl access functions + * ZYPP_DECLARE_PRIVATE(MyClass) + * // the only data member in the public class should be a pointer to the private type + * // named d_ptr + * std::unique_ptr d_ptr; + * }; + * + * // MyClass.cc + * + * // in the implementation file we can now define the private class: + * class MyClassPrivate + * { + * public: + * // add the data members and private functions here + * int something = 0; + * }; + * + * // in the constructor make sure that the private part of the class + * // is initialized too + * MyClass::MyClass() : d_ptr( new MyClassPrivate ) + * {} + * + * int MyClass::getSomething() const + * { + * // automatically generates a pointer named "d" to the + * // pimpl object + * Z_D(); + * return d->something; + * } + * + * void MyClass::doSomething() + * { + * // It is also possible to use the d_func() to access the pointer: + * d_func()->something = 10; + * } + * + * \endcode + * + * \note those macros are inspired by the Qt framework + */ + +template inline T *zyppGetPtrHelper(T *ptr) { return ptr; } +template inline auto zyppGetPtrHelper(const Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); } +template inline auto zyppGetPtrHelper(Ptr &ptr) -> decltype(ptr.operator->()) { return ptr.operator->(); } + +#define ZYPP_DECLARE_PRIVATE(Class) \ + Class##Private* d_func();\ + const Class##Private* d_func() const; \ + friend class Class##Private; + +#define ZYPP_IMPL_PRIVATE(Class) \ + Class##Private* Class::d_func() \ + { return static_cast(zyppGetPtrHelper(d_ptr)); } \ + const Class##Private* Class::d_func() const \ + { return static_cast(zyppGetPtrHelper(d_ptr)); } + +#define ZYPP_DECLARE_PUBLIC(Class) \ + public: \ + inline Class* z_func() { return static_cast(z_ptr); } \ + inline const Class* z_func() const { return static_cast(z_ptr); } \ + friend class Class; \ + private: + +#define Z_D() auto const d = d_func() +#define Z_Z() auto const z = z_func() + +namespace zyppng { + template + using Ref = std::shared_ptr; + + template + using WeakRef = std::weak_ptr; +} + +/*! + * Helper macro to declare Ref types + */ +#define ZYPP_FWD_DECL_REFS(T) \ + using T##Ref = Ref; \ + using T##WeakRef = WeakRef + +/* + * Helper Macro to forward declare types and ref types + */ +#define ZYPP_FWD_DECL_TYPE_WITH_REFS(T) \ + class T; \ + ZYPP_FWD_DECL_REFS(T) + +#define ZYPP_FWD_DECL_TEMPL_TYPE_WITH_REFS_ARG1(T, TArg1) \ + template< typename TArg1> \ + class T; \ + template< typename TArg1> \ + using T##Ref = Ref>; \ + template< typename TArg1> \ + using T##WeakRef = WeakRef> + + +//@TODO enable for c++20 +#if 0 +#define ZYPP_FWD_DECL_TEMPL_TYPE_WITH_REFS(T, TArg1, ...) \ + template< typename TArg1 __VA_OPT__(, typename) __VA_ARGS__ > \ + class T; \ + template< typename TArg1 __VA_OPT__(, typename) __VA_ARGS__ > \ + using T##Ref = std::shared_ptr>; \ + template< typename TArg1 __VA_OPT__(, typename) __VA_ARGS__ > \ + using T##WeakRef = std::weak_ptr> +#endif + +/*! + * Defines a dummy struct that can be used to make a public constructor unusable + * outside the class. \sa ZYPP_ADD_CREATE_FUNC. + */ +#define ZYPP_ADD_PRIVATE_CONSTR_HELPER() \ + struct private_constr_t { private_constr_t () noexcept = default; } + +/*! + * Use this to add the private constr argument to a constructor + */ +#define ZYPP_PRIVATE_CONSTR_ARG \ + private_constr_t + +/*! + * Use this to pass the private constr arg to a constructor + */ +#define ZYPP_PRIVATE_CONSTR_ARG_VAL \ + private_constr_t{} + +/*! + * Helper macro to add the default Class::create() static function + * commonly used in libzypp. + * + * \code + * + * // always forward declare the Ref types so they can be used in the class + * ZYPP_FWD_DECL_TYPE_WITH_REFS(MyClass) + * + * class MyClass + * { + * // this adds the construct template function + * ZYPP_ADD_CREATE_FUNC(MyClass) + * + * public: + * // adds a constructor that takes no args: + * // MyClass::create(); + * ZYPP_DECL_PRIVATE_CONSTR(MyClass) + * + * // adds a constructor with two arguments + * // MyClass::create( 10, "Hello"); + * ZYPP_DECL_PRIVATE_CONSTR_ARGS(MyClass, int arg1, const std::string &label) + * } + * + * ZYPP_IMPL_PRIVATE_CONSTR( MyClass ) { + * // do stuff + * } + * + * ZYPP_IMPL_PRIVATE_CONSTR_ARGS( MyClass, int arg1, const std::string &label ) { + * // do stuff with args + * } + * + * \endcode + * \note requires the ref types for the class to be already defined + * \TODO Add this to already existing objects + */ +#define ZYPP_ADD_CREATE_FUNC(Class) \ + private: \ + ZYPP_ADD_PRIVATE_CONSTR_HELPER(); \ + public: \ + template < typename ...Args > \ + inline static auto create ( Args &&... args ) { \ + return std::make_shared< Class >( private_constr_t{}, std::forward(args)... ); \ + } \ + private: + +/* + * Convenience macros to implement public but private constructors that can be called from Class::create() but + * not by user code. + * + * \sa ZYPP_ADD_CONSTR_FUNC + */ +#define ZYPP_DECL_PRIVATE_CONSTR(Class) Class( private_constr_t ) +#define ZYPP_IMPL_PRIVATE_CONSTR(Class) Class::Class( private_constr_t ) +#define ZYPP_DECL_PRIVATE_CONSTR_ARGS(Class,...) Class( private_constr_t, __VA_ARGS__ ) +#define ZYPP_IMPL_PRIVATE_CONSTR_ARGS(Class,...) Class::Class( private_constr_t, __VA_ARGS__ ) + +#define ZYPP_NODISCARD [[nodiscard]] + +#endif diff --git a/zypp-core/zyppng/core/ByteArray b/zypp-core/zyppng/core/ByteArray new file mode 100644 index 0000000..a3c9c82 --- /dev/null +++ b/zypp-core/zyppng/core/ByteArray @@ -0,0 +1 @@ +#include "bytearray.h" diff --git a/zypp-core/zyppng/core/Env b/zypp-core/zyppng/core/Env new file mode 100644 index 0000000..df8e361 --- /dev/null +++ b/zypp-core/zyppng/core/Env @@ -0,0 +1 @@ +#include "env.h" diff --git a/zypp-core/zyppng/core/IdString b/zypp-core/zyppng/core/IdString new file mode 100644 index 0000000..0e2ce04 --- /dev/null +++ b/zypp-core/zyppng/core/IdString @@ -0,0 +1 @@ +#include "idstring.h" diff --git a/zypp-core/zyppng/core/String b/zypp-core/zyppng/core/String new file mode 100644 index 0000000..eab76f2 --- /dev/null +++ b/zypp-core/zyppng/core/String @@ -0,0 +1 @@ +#include "string.h" diff --git a/zypp-core/zyppng/core/Url b/zypp-core/zyppng/core/Url new file mode 100644 index 0000000..32fa815 --- /dev/null +++ b/zypp-core/zyppng/core/Url @@ -0,0 +1 @@ +#include "url.h" diff --git a/zypp-core/zyppng/core/bytearray.h b/zypp-core/zyppng/core/bytearray.h new file mode 100644 index 0000000..ce90971 --- /dev/null +++ b/zypp-core/zyppng/core/bytearray.h @@ -0,0 +1,25 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPP_NG_CORE_BYTEARRAY_H_INCLUDED +#define ZYPP_NG_CORE_BYTEARRAY_H_INCLUDED + +#include + +namespace zyppng { + using ByteArray = zypp::ByteArray; + using UByteArray = zypp::UByteArray; +} + +#endif diff --git a/zypp-core/zyppng/core/env.h b/zypp-core/zyppng/core/env.h new file mode 100644 index 0000000..0063999 --- /dev/null +++ b/zypp-core/zyppng/core/env.h @@ -0,0 +1,21 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#ifndef ZYPP_NG_CORE_ENV_H_INCLUDED +#define ZYPP_NG_CORE_ENV_H_INCLUDED + +namespace zypp { + /// Namespace intended to collect all environment variables we use + namespace env {} +} + +namespace zyppng { + namespace env = zypp::env; +} + +#endif // ZYPP_NG_CORE_ENV_H_INCLUDED diff --git a/zypp-core/zyppng/core/idstring.h b/zypp-core/zyppng/core/idstring.h new file mode 100644 index 0000000..c28398c --- /dev/null +++ b/zypp-core/zyppng/core/idstring.h @@ -0,0 +1,21 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#ifndef ZYPP_NG_CORE_IDSTRING_H_INCLUDED +#define ZYPP_NG_CORE_IDSTRING_H_INCLUDED + +#include + +namespace zyppng { + + using IdString = zypp::IdString; + using IdStringSet = zypp::IdStringSet; + +} + +#endif diff --git a/zypp-core/zyppng/core/string.h b/zypp-core/zyppng/core/string.h new file mode 100644 index 0000000..b4981e6 --- /dev/null +++ b/zypp-core/zyppng/core/string.h @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#ifndef ZYPP_NG_CORE_STRING_H_INCLUDED +#define ZYPP_NG_CORE_STRING_H_INCLUDED + +#include +#include +#include + +namespace zyppng { + +namespace str { + + using zypp::str::Trim; + + template + std::optional safe_strtonum ( const std::string_view &val) + { + int oerrno = errno; + errno = 0; // strtonum/::strtol has no dedicated error-return-code one could check + const T entryVal = zypp::str::strtonum( val.data() ); + if ( errno == ERANGE ) + return {}; + errno = oerrno; + return entryVal; + } + + template< typename StrType, typename T = std::remove_reference_t > + T trim( StrType&& s, const Trim trim_r ) + { + T ret( std::forward(s) ); + + if ( ret.empty() || trim_r == Trim::NO_TRIM ) + return ret; + + if ( trim_r & Trim::L_TRIM ) + { + typename T::size_type p = ret.find_first_not_of( " \t\r\n" ); + if ( p == T::npos ) + { + if constexpr ( std::is_same_v ) + return T(); + else { + ret.clear(); + return ret; + } + } + ret.remove_prefix( p ); + } + + if ( trim_r & Trim::R_TRIM ) + { + typename T::size_type p = ret.find_last_not_of( " \t\r\n" ); + if ( p == T::npos ) + { + if constexpr ( std::is_same_v ) + return T(); + else { + ret.clear(); + return ret; + } + } + ret.remove_suffix( ret.size() - ( p+1 ) ); + } + + return ret; + } + + template + void split( const boost::string_view & line_r, TOutputIterator result_r, const boost::string_view & sepchars_r = " \t", const Trim trim_r = Trim::NO_TRIM ) + { + //skip initial sepchars + std::string_view::size_type tokenEnd = 0, tokenBegin = line_r.find_first_not_of( sepchars_r ); + + //if we do not find a character that is not in sepchars there is nothing to split + if ( tokenBegin == std::string_view::npos ) + return; + + while ( ( tokenEnd = line_r.find_first_of( sepchars_r, tokenBegin ) ) != std::string_view::npos ) { + auto line = line_r.substr( tokenBegin, tokenEnd-tokenBegin ); + *result_r = trim( line, trim_r ); + + //find start of next token + tokenBegin = line_r.find_first_not_of( sepchars_r, tokenEnd ); + if( tokenBegin == std::string_view::npos ) + break; + } + + //insert the final element + if ( tokenBegin != std::string_view::npos && tokenBegin < line_r.size() ) + *result_r = trim( line_r.substr( tokenBegin ), trim_r ); + } +} + + // use strerror from zypp::str in zyppng + using zypp::str::strerror; + +} + + +#endif diff --git a/zypp-core/zyppng/core/url.h b/zypp-core/zyppng/core/url.h new file mode 100644 index 0000000..6dee4ab --- /dev/null +++ b/zypp-core/zyppng/core/url.h @@ -0,0 +1,18 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#ifndef ZYPP_NG_CORE_URL_H_INCLUDED +#define ZYPP_NG_CORE_URL_H_INCLUDED + +#include + +namespace zyppng { + using Url = zypp::Url; +} + +#endif diff --git a/zypp-core/zyppng/io/AsyncDataSource b/zypp-core/zyppng/io/AsyncDataSource new file mode 100644 index 0000000..29a243e --- /dev/null +++ b/zypp-core/zyppng/io/AsyncDataSource @@ -0,0 +1 @@ +#include "asyncdatasource.h" diff --git a/zypp-core/zyppng/io/IODevice b/zypp-core/zyppng/io/IODevice new file mode 100644 index 0000000..94b8d47 --- /dev/null +++ b/zypp-core/zyppng/io/IODevice @@ -0,0 +1 @@ +#include "iodevice.h" diff --git a/zypp-core/zyppng/io/Process b/zypp-core/zyppng/io/Process new file mode 100644 index 0000000..aaf2a9f --- /dev/null +++ b/zypp-core/zyppng/io/Process @@ -0,0 +1 @@ +#include "process.h" diff --git a/zypp-core/zyppng/io/SockAddr b/zypp-core/zyppng/io/SockAddr new file mode 100644 index 0000000..36c6706 --- /dev/null +++ b/zypp-core/zyppng/io/SockAddr @@ -0,0 +1 @@ +#include "sockaddr.h" diff --git a/zypp-core/zyppng/io/Socket b/zypp-core/zyppng/io/Socket new file mode 100644 index 0000000..88d614f --- /dev/null +++ b/zypp-core/zyppng/io/Socket @@ -0,0 +1 @@ +#include "socket.h" diff --git a/zypp-core/zyppng/io/abstractspawnengine.cc b/zypp-core/zyppng/io/abstractspawnengine.cc new file mode 100644 index 0000000..be7d071 --- /dev/null +++ b/zypp-core/zyppng/io/abstractspawnengine.cc @@ -0,0 +1,214 @@ +#include "private/abstractspawnengine_p.h" +#include +#include +#include +#include +#include + +#include "private/forkspawnengine_p.h" + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::exec" + +namespace zyppng { + + +#if ZYPP_HAS_GLIBSPAWNENGINE + namespace { + + enum class SpawnEngine { + GSPAWN, + PFORK + }; + + SpawnEngine initEngineFromEnv () { + const std::string fBackend ( zypp::str::asString( ::getenv("ZYPP_FORK_BACKEND") ) ); + if ( fBackend.empty() || fBackend == "auto" || fBackend == "pfork" ) { + DBG << "Starting processes via posix fork" << std::endl; + return SpawnEngine::PFORK; + } else if ( fBackend == "gspawn" ) { + DBG << "Starting processes via glib spawn" << std::endl; + return SpawnEngine::GSPAWN; + } + + DBG << "Falling back to starting process via posix fork" << std::endl; + return SpawnEngine::PFORK; + } + + std::unique_ptr engineFromEnv () { + static const SpawnEngine eng = initEngineFromEnv(); + switch ( eng ) { + case SpawnEngine::GSPAWN: + return std::make_unique(); + case SpawnEngine::PFORK: + default: + return std::make_unique(); + } + } + } +#else + + std::unique_ptr engineFromEnv () { + return std::make_unique(); + } + +#endif + + AbstractSpawnEngine::AbstractSpawnEngine() + { + } + + AbstractSpawnEngine::~AbstractSpawnEngine() + { } + + std::unique_ptr AbstractSpawnEngine::createDefaultEngine() + { + return engineFromEnv(); + } + + bool AbstractSpawnEngine::switchPgid() const + { + return _switchPgid; + } + + void AbstractSpawnEngine::setSwitchPgid(bool switchPgid) + { + _switchPgid = switchPgid; + } + + zypp::Pathname AbstractSpawnEngine::workingDirectory() const + { + return _workingDirectory; + } + + void AbstractSpawnEngine::setWorkingDirectory(const zypp::Pathname &workingDirectory) + { + _workingDirectory = workingDirectory; + } + + const std::vector &AbstractSpawnEngine::fdsToMap() const + { + return _mapFds; + } + + void AbstractSpawnEngine::addFd(int fd) + { + _mapFds.push_back( fd ); + } + + void AbstractSpawnEngine::notifyExited(int status) + { + _exitStatus = checkStatus( status ); + _pid = -1; + } + + bool AbstractSpawnEngine::dieWithParent() const + { + return _dieWithParent; + } + + void AbstractSpawnEngine::setDieWithParent( bool dieWithParent ) + { + _dieWithParent = dieWithParent; + } + + int AbstractSpawnEngine::exitStatus() const + { + return _exitStatus; + } + + void AbstractSpawnEngine::setExitStatus(const int state) + { + _exitStatus = state; + } + + const std::string &AbstractSpawnEngine::executedCommand() const + { + return _executedCommand; + } + + const std::string &AbstractSpawnEngine::execError() const + { + return _execError; + } + + void AbstractSpawnEngine::setExecError(const std::string &str) + { + _execError = str; + } + + zypp::Pathname AbstractSpawnEngine::chroot() const + { + return _chroot; + } + + void AbstractSpawnEngine::setChroot( const zypp::Pathname &chroot ) + { + _chroot = chroot; + } + + bool AbstractSpawnEngine::useDefaultLocale() const + { + return _useDefaultLocale; + } + + void AbstractSpawnEngine::setUseDefaultLocale( bool defaultLocale ) + { + _useDefaultLocale = defaultLocale; + } + + AbstractSpawnEngine::Environment AbstractSpawnEngine::environment() const + { + return _environment; + } + + void AbstractSpawnEngine::setEnvironment( const Environment &environment ) + { + _environment = environment; + } + + pid_t AbstractSpawnEngine::pid( ) + { + return _pid; + } + + int AbstractSpawnEngine::checkStatus( int status ) + { + if (WIFEXITED (status)) + { + status = WEXITSTATUS (status); + if(status) + { + WAR << "Pid " << _pid << " exited with status " << status << std::endl; + _execError = zypp::str::form( _("Command exited with status %d."), status ); + } + else + { + // if 'launch' is logged, completion should be logged, + // even if successfull. + DBG << "Pid " << _pid << " successfully completed" << std::endl; + _execError.clear(); // empty if running or successfully completed + } + } + else if (WIFSIGNALED (status)) + { + status = WTERMSIG (status); + std::string sigdetail { strsignal(status) }; + if ( WCOREDUMP(status) ) { + sigdetail += "; Core dumped"; + } + if ( status == SIGKILL ) { + sigdetail += "; Out of memory?"; + } + WAR << "Pid " << _pid << " was killed by signal " << status << " (" << sigdetail << ")" << std::endl; + _execError = zypp::str::form( _("Command was killed by signal %d (%s)."), status, sigdetail.c_str() ); + status+=128; + } + else { + ERR << "Pid " << _pid << " exited with unknown error" << std::endl; + _execError = _("Command exited with unknown error."); + } + return status; + } + +} // namespace zyppng diff --git a/zypp-core/zyppng/io/asyncdatasource.cpp b/zypp-core/zyppng/io/asyncdatasource.cpp new file mode 100644 index 0000000..a1462f4 --- /dev/null +++ b/zypp-core/zyppng/io/asyncdatasource.cpp @@ -0,0 +1,387 @@ +#include "private/asyncdatasource_p.h" + +#include +#include +#include +#include + +namespace zyppng { + + void AsyncDataSourcePrivate::notifierActivated( const SocketNotifier ¬ify, int evTypes ) + { + if ( _writeNotifier.get() == ¬ify ) { + if ( evTypes & SocketNotifier::Error ) { + DBG << "Closing due to error when polling" << std::endl; + closeWriteChannel( AsyncDataSource::RemoteClose ); + return; + } + readyWrite(); + } else { + + auto dev = std::find_if( _readFds.begin(), _readFds.end(), + [ ¬ify ]( const auto &dev ){ return ( dev._readNotifier.get() == ¬ify ); } ); + + if ( dev == _readFds.end() ) { + return; + } + + readyRead( std::distance( _readFds.begin(), dev ) ); + } + } + + void AsyncDataSourcePrivate::readyRead( uint channel ) + { + auto bytesToRead = z_func()->rawBytesAvailable( channel ); + if ( bytesToRead == 0 ) { + // make sure to check if bytes are available even if the ioctl call returns something different + bytesToRead = 4096; + } + + auto &_readBuf = _readChannels[channel]; + char *buf = _readBuf.reserve( bytesToRead ); + const auto bytesRead = z_func()->readData( channel, buf, bytesToRead ); + + if ( bytesRead <= 0 ) { + _readBuf.chop( bytesToRead ); + + switch( bytesRead ) { + // remote close , close the read channel + case 0: { + closeReadChannel( channel, AsyncDataSource::RemoteClose ); + break; + } + // no data is available , just try again later + case -2: break; + // anything else + default: + case -1: { + closeReadChannel( channel, AsyncDataSource::InternalError ); + break; + } + } + return; + } + + if ( bytesToRead > bytesRead ) + _readBuf.chop( bytesToRead-bytesRead ); + + if ( channel == _currentReadChannel ) + _readyRead.emit(); + + _channelReadyRead.emit( channel ); + return; + } + + void AsyncDataSourcePrivate::readyWrite() + { + const auto nwrite = _writeBuffer.frontSize(); + if ( !nwrite ) { + // disable Write notifications so we do not wake up without the need to + _writeNotifier->setEnabled( false ); + return; + } + + const auto nBuf = _writeBuffer.front(); + const auto written = eintrSafeCall( ::write, _writeFd, nBuf, nwrite ); + if ( written == -1 ) { + switch ( errno ) { + case EACCES: + closeWriteChannel( AsyncDataSource::AccessError ); + return; + case EAGAIN: +#if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: +#endif + return; + case EPIPE: + case ECONNRESET: + closeWriteChannel( AsyncDataSource::RemoteClose ); + return; + default: + closeWriteChannel( AsyncDataSource::InternalError ); + return; + } + return; + } + _writeBuffer.discard( written ); + _sigBytesWritten.emit( written ); + + if ( _writeBuffer.size() == 0 ) + _sigAllBytesWritten.emit(); + } + + void AsyncDataSourcePrivate::closeWriteChannel( AsyncDataSource::ChannelCloseReason reason ) + { + bool sig = _writeFd >= 0; + _writeNotifier.reset(); + _writeFd = -1; + _writeBuffer.clear(); + _mode.unsetFlag( AsyncDataSource::WriteOnly ); + if ( sig ) + _sigWriteFdClosed.emit( reason ); + } + + void AsyncDataSourcePrivate::closeReadChannel( uint channel, AsyncDataSource::ChannelCloseReason reason ) + { + auto &readFd = _readFds[channel]; + // we do not clear the read buffer so code has the opportunity to read whats left in there + bool sig = readFd._readFd >= 0; + readFd._readNotifier.reset(); + readFd._readFd = -1; + if ( sig ) { + z_func()->finishReadChannel( channel ); + _sigReadFdClosed.emit( channel, reason ); + } + } + + ZYPP_IMPL_PRIVATE(AsyncDataSource) + + AsyncDataSource::AsyncDataSource() : IODevice( *( new AsyncDataSourcePrivate(*this) ) ) + { } + + AsyncDataSource::AsyncDataSource( AsyncDataSourcePrivate &d ) + : IODevice(d) + {} + + AsyncDataSource::Ptr AsyncDataSource::create() + { + return std::shared_ptr( new AsyncDataSource ); + } + + + bool AsyncDataSource::openFds ( const std::vector& readFds, int writeFd ) + { + Z_D(); + + if ( d->_mode != IODevice::Closed ) + return false; + + IODevice::OpenMode mode; + + bool error = false; + for ( const auto readFd : readFds ) { + if ( readFd >= 0 ) { + mode |= IODevice::ReadOnly; + d->_readFds.push_back( { + readFd, + SocketNotifier::create( readFd, SocketNotifier::Read | AbstractEventSource::Error, true ) + }); + if ( zypp::io::setFDBlocking( readFd, false ) == zypp::io::BlockingMode::FailedToSetMode ) { + ERR << "Failed to set read FD to non blocking" << std::endl; + error = true; + break; + } + d->_readFds.back()._readNotifier->connect( &SocketNotifier::sigActivated, *d, &AsyncDataSourcePrivate::notifierActivated ); + } + } + + if ( writeFd >= 0 && !error ) { + mode |= IODevice::WriteOnly; + if ( zypp::io::setFDBlocking( writeFd, false ) == zypp::io::BlockingMode::FailedToSetMode ) { + ERR << "Failed to set write FD to non blocking" << std::endl; + error = true; + } else { + d->_writeFd = writeFd; + d->_writeNotifier = SocketNotifier::create( writeFd, SocketNotifier::Write | AbstractEventSource::Error, false ); + d->_writeNotifier->connect( &SocketNotifier::sigActivated, *d, &AsyncDataSourcePrivate::notifierActivated ); + } + } + + if( error || !IODevice::open( mode ) ) { + d->_mode = IODevice::Closed; + d->_readFds.clear(); + d->_writeNotifier.reset(); + d->_writeFd = -1; + return false; + } + + // make sure we have enough read buffers + setReadChannelCount( d->_readFds.size() ); + return true; + } + + int64_t zyppng::AsyncDataSource::writeData( const char *data, int64_t count ) + { + Z_D(); + if ( count > 0 ) { + // we always use the write buffer, to make sure the fd is actually writeable + d->_writeBuffer.append( data, count ); + d->_writeNotifier->setEnabled( true ); + } + return count; + } + + int64_t zyppng::AsyncDataSource::readData( uint channel, char *buffer, int64_t bufsize ) + { + Z_D(); + if ( channel >= d->_readFds.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::logic_error( constants::outOfRangeErrMsg.data() ); + } + const auto read = eintrSafeCall( ::read, d->_readFds[channel]._readFd, buffer, bufsize ); + if ( read < 0 ) { + switch ( errno ) { + #if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: + #endif + case EAGAIN: { + return -2; + } + default: + break; + } + } + return read; + } + + int64_t AsyncDataSource::rawBytesAvailable( uint channel ) const + { + Z_D(); + + if ( channel >= d->_readFds.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::logic_error( constants::outOfRangeErrMsg.data() ); + } + + if ( isOpen() && canRead() ) + return zyppng::bytesAvailableOnFD( d->_readFds[channel]._readFd ); + return 0; + } + + void AsyncDataSource::readChannelChanged ( uint channel ) + { + Z_D(); + if ( channel >= d->_readFds.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::logic_error( constants::outOfRangeErrMsg.data() ); + } + } + + void zyppng::AsyncDataSource::close() + { + Z_D(); + for( uint i = 0; i < d->_readFds.size(); ++i ) { + auto &readChan = d->_readFds[i]; + readChan._readNotifier.reset(); + if ( readChan._readFd >= 0) { + finishReadChannel(i); + d->_sigReadFdClosed.emit( i, UserRequest ); + } + } + d->_readFds.clear(); + + d->_writeNotifier.reset(); + d->_writeBuffer.clear(); + if ( d->_writeFd >= 0 ) { + d->_writeFd = -1; + d->_sigWriteFdClosed.emit( UserRequest ); + } + + IODevice::close(); + } + + void AsyncDataSource::closeWriteChannel() + { + Z_D(); + + // if we are open writeOnly, simply call close(); + if ( !canRead() ) { + close(); + return; + } + + d->_mode = ReadOnly; + d->_writeNotifier.reset(); + d->_writeBuffer.clear(); + + if ( d->_writeFd >= 0 ) { + d->_writeFd = -1; + d->_sigWriteFdClosed.emit( UserRequest ); + } + } + + bool AsyncDataSource::waitForReadyRead( uint channel, int timeout ) + { + Z_D(); + if ( !canRead() ) + return false; + + if ( channel >= d->_readFds.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::logic_error( constants::outOfRangeErrMsg.data() ); + } + + bool gotRR = false; + auto rrConn = AutoDisconnect( d->_channelReadyRead.connect([&]( uint activated ){ + gotRR = ( channel == activated ); + }) ); + + // we can only wait if we are open for reading and still have a valid fd + auto &channelRef = d->_readFds[ channel ]; + while ( readFdOpen(channel) && canRead() && !gotRR ) { + int rEvents = 0; + if ( EventDispatcher::waitForFdEvent( channelRef._readFd, AbstractEventSource::Read | AbstractEventSource::Error , rEvents, timeout ) ) { + //simulate signal from read notifier + d->notifierActivated( *channelRef._readNotifier, rEvents ); + } else { + //timeout + return false; + } + } + return gotRR; + } + + void AsyncDataSource::flush () + { + Z_D(); + if ( !canWrite() ) + return; + + int timeout = -1; + while ( canWrite() && d->_writeBuffer.frontSize() ) { + int rEvents = 0; + if ( EventDispatcher::waitForFdEvent( d->_writeFd, AbstractEventSource::Write | AbstractEventSource::Error , rEvents, timeout ) ) { + //simulate signal from write notifier + d->readyWrite(); + } else { + //timeout + return; + } + } + } + + SignalProxy AsyncDataSource::sigWriteFdClosed() + { + return d_func()->_sigWriteFdClosed; + } + + SignalProxy AsyncDataSource::sigReadFdClosed() + { + return d_func()->_sigReadFdClosed; + } + + bool AsyncDataSource::readFdOpen() const + { + Z_D(); + if ( !d->_readChannels.size() ) + return false; + return readFdOpen( d_func()->_currentReadChannel ); + } + + bool AsyncDataSource::readFdOpen(uint channel) const + { + Z_D(); + if ( channel >= d->_readFds.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::logic_error( constants::outOfRangeErrMsg.data() ); + } + auto &channelRef = d->_readFds[ channel ]; + return ( channelRef._readNotifier && channelRef._readFd >= 0 ); + } + + int64_t AsyncDataSource::bytesPending() const + { + return d_func()->_writeBuffer.size(); + } + +} diff --git a/zypp-core/zyppng/io/asyncdatasource.h b/zypp-core/zyppng/io/asyncdatasource.h new file mode 100644 index 0000000..cde778a --- /dev/null +++ b/zypp-core/zyppng/io/asyncdatasource.h @@ -0,0 +1,105 @@ +#ifndef ASYNCDATASOURCE_H +#define ASYNCDATASOURCE_H + +#include +#include + +namespace zyppng { + + class AsyncDataSourcePrivate; + + class AsyncDataSource : public IODevice + { + ZYPP_DECLARE_PRIVATE(AsyncDataSource); + public: + + enum ChannelCloseReason { + RemoteClose, // the other side of the fd was closed + AccessError, // we got an EACCESS when polling the fd + InternalError, // we got a unexpected errno when polling the fd + UserRequest // channel were closed because close() was called + }; + + using Ptr = std::shared_ptr; + using WeakPtr = std::weak_ptr; + + static Ptr create (); + + /*! + * Borrows the given fd's and starts reading/writing to them if data is available. + * Note that \ref AsyncDataSource does not take ownership of the FDs, they need to be closed + * explicitely after they were released with \ref close + */ + bool openFds ( const std::vector& readFds, int writeFd = -1 ); + + /*! + * Closes the \ref AsyncDataSource and releases the used fd's to the calling code. They are NOT + * closed. + */ + void close () override; + + using IODevice::waitForReadyRead; + + virtual void closeWriteChannel (); + + /*! + * Blocks the current event loop to wait until all bytes currently in the buffer have been written to + * the write fd. + * + * \note do not use until there is a very good reason, like event processing should not continue until readyRead was sent + */ + bool waitForReadyRead(uint channel, int timeout) override; + + /*! + * Blocks the current event loop to wait until all bytes currently in the buffer have been written to + * the write fd. + * + * \note do not use until there is a very good reason, like event processing should not continue until bytesWritten was sent + */ + void flush (); + + /*! + * Signal is emitted always when the write channel is closed. + * All data that was not written yet will be discarded and canWrite() will return + * false. + */ + SignalProxy sigWriteFdClosed(); + + /*! + * Signal is emitted always when the write channel is closed, for example + * when the write side of a pipe is closed. All data still residing in the read buffer + * can still be read. + */ + SignalProxy sigReadFdClosed(); + + /*! + * Returns true as long as the default read channel was not closed ( e.g. sigReadFdClosed was emitted ) + */ + bool readFdOpen () const; + + /*! + * Returns true as long as the given read channel was not closed ( e.g. sigReadFdClosed was emitted ) + */ + bool readFdOpen ( uint channel ) const; + + /*! + * Returns the current number of bytes that are not yet written to the data source. + */ + int64_t bytesPending() const override; + + protected: + AsyncDataSource ( ); + AsyncDataSource( AsyncDataSourcePrivate &d ); + int64_t writeData(const char *data, int64_t count) override; + + private: + using IODevice::open; + + int64_t readData( uint channel, char *buffer, int64_t bufsize ) override; + int64_t rawBytesAvailable( uint channel ) const override; + void readChannelChanged ( uint channel ) override; + }; +} + + +#endif // ASYNCDATASOURCE_H diff --git a/zypp-core/zyppng/io/forkspawnengine.cc b/zypp-core/zyppng/io/forkspawnengine.cc new file mode 100644 index 0000000..3b4dee1 --- /dev/null +++ b/zypp-core/zyppng/io/forkspawnengine.cc @@ -0,0 +1,631 @@ +#include "private/forkspawnengine_p.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include // openpty +#include // setenv +#include // prctl(), PR_SET_PDEATHSIG + +#include +#ifdef SYS_pidfd_open +#include +#endif + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::exec" + + +zyppng::AbstractDirectSpawnEngine::~AbstractDirectSpawnEngine() +{ + if ( AbstractDirectSpawnEngine::isRunning() ) { + // we got destructed while the external process is still alive + // make sure the zombie is cleaned up once it exits + zypp::CleanerThread::watchPID( _pid ); + } +} + +bool zyppng::AbstractDirectSpawnEngine::isRunning( bool wait ) +{ + if ( _pid < 0 ) return false; + + int status = 0; + int p = zyppng::eintrSafeCall( ::waitpid, _pid, &status, wait ? 0 : WNOHANG ); + switch ( p ) + { + case -1: + ERR << "waitpid( " << _pid << ") returned error '" << strerror(errno) << "'" << std::endl; + return false; + break; + case 0: + return true; // still running + break; + } + + // Here: completed... + _exitStatus = checkStatus( status ); + _pid = -1; + return false; +} + +bool zyppng::AbstractDirectSpawnEngine::waitForExit( const std::optional &timeout ) +{ + if ( _pid < 0 ) return true; + + // no timeout, wait forever + if ( !timeout.has_value () ) + return !isRunning( true ); + + // busy loop polling in case pidfd is not available or fails, only called if we have a valid timout + const auto &fallbackPoll = [&]( uint64_t timeout ){ + const auto start = Timer::now(); + do { + if ( !isRunning(false) ) + return true; + // give up the CPU, so we do not use 100% just to poll + std::this_thread::sleep_for( std::chrono::milliseconds(1) ); + } while( Timer::elapsedSince ( start ) < timeout ); + + return !isRunning ( false ); + }; + +#ifdef SYS_pidfd_open + // we have pidfd support, but there is not yet a wrapper in glibc + const auto &zypp_pidfd_open = [](pid_t pid, unsigned int flags) -> int { + return syscall( SYS_pidfd_open, pid, flags ); + }; + + zypp::AutoFD pidFd = zyppng::eintrSafeCall( zypp_pidfd_open, _pid, 0 ); + if ( pidFd == -1 ) { + // fallback to manual polling + ERR << "pidfd_open failed, falling back to polling waidpid" << std::endl; + return fallbackPoll( *timeout ); + } + + struct pollfd pollfd; + pollfd.fd = pidFd; + pollfd.events = POLLIN; + + // timeout always has a value set, we established that above + uint64_t tRemaining = *timeout; + + const auto start = Timer::now(); + do { + // posix using int as timeout, could in theory overflow so protect against it + int posixTimeout = tRemaining > INT_MAX ? INT_MAX : static_cast(tRemaining); + + int ready = poll(&pollfd, 1, posixTimeout ); + tRemaining = *timeout - std::min( Timer::elapsedSince( start ), *timeout ); + + if ( ready == -1 && errno != EINTR ) { + ERR << "Polling the pidfd failed with error: " << zypp::Errno() << std::endl; + if ( tRemaining > 0 ) { + ERR << "Falling back to manual polling for the remaining timeout." << std::endl; + return fallbackPoll( tRemaining ); + } + break; + } else if ( pollfd.revents & POLLIN ) { + break; + } + } while( tRemaining > 0 ); + + // set exit status + return !isRunning ( false ); +#else + // we do not have pidfd support, need to busyloop on waitpid until timeout is over + return fallbackPoll( *timeout ); +#endif +} + +void zyppng::AbstractDirectSpawnEngine::mapExtraFds ( int controlFd ) +{ + // we might have gotten other FDs to reuse, lets map them to STDERR_FILENO++ + // BUT we need to make sure the fds are not already in the range we need to map them to + // so we first go over a list and collect those that are safe or move those that are not + int lastFdToKeep = STDERR_FILENO + _mapFds.size(); + int nextBackupFd = lastFdToKeep + 1; //this we will use to count the fds upwards + std::vector safeFds; + for ( auto fd : _mapFds ) { + // If the fds are larger than the last one we will map to, it is safe. + if ( fd > lastFdToKeep ) { + safeFds.push_back( fd ); + } else { + // we need to map the fd after the set of those we want to keep, but also make sure + // that we do not close one of those we have already moved or might move + while (true) { + + int backupTo = nextBackupFd; + nextBackupFd++; + const bool isSafe1 = std::find( _mapFds.begin(), _mapFds.end(), backupTo ) == _mapFds.end(); + const bool isSafe2 = std::find( safeFds.begin(), safeFds.end(), backupTo ) == safeFds.end(); + if ( isSafe1 && isSafe2 && ( controlFd == -1 || backupTo != controlFd) ) { + dup2( fd, backupTo ); + safeFds.push_back( backupTo ); + break; + } + } + } + } + + // now we have a list of safe fds we need to map to the fd we want them to end up + int nextFd = STDERR_FILENO; + for ( auto fd : safeFds ) { + nextFd++; + dup2( fd, nextFd ); + } + + const auto &canCloseFd = [&]( int fd ){ + // controlFD has O_CLOEXEC set so it will be cleaned up :) + if ( controlFd != -1 && controlFd == fd ) + return false; + // make sure we don't close fd's still need + if ( fd <= lastFdToKeep ) + return false; + return true; + }; + + const auto maxFds = ( ::getdtablesize() - 1 ); + //If the rlimits are too high we need to use a different approach + // in detecting how many fds we need to close, or otherwise we are too slow (bsc#1191324) + if ( maxFds > 1024 && zypp::PathInfo( "/proc/self/fd" ).isExist() ) { + + std::vector fdsToClose; + fdsToClose.reserve (256); + + zypp::filesystem::dirForEachExt( "/proc/self/fd", [&]( const zypp::Pathname &p, const zypp::filesystem::DirEntry &entry ){ + if ( entry.type != zypp::filesystem::FT_LINK) + return true; + + const auto &fdVal = zyppng::str::safe_strtonum( entry.name ); + if ( !fdVal || !canCloseFd(*fdVal) ) + return true; + + // we can not call close() directly here because zypp::filesystem::dirForEachExt actually has a fd open on + // /proc/self/fd that we would close as well. So we just remember which fd's we WOULD close and then do it + // after iterating + fdsToClose.push_back (*fdVal); + return true; + }); + for ( int cFd : fdsToClose ) + ::close( cFd ); + } else { + // close all filedescriptors above the last we want to keep + for ( int i = maxFds; i > lastFdToKeep; --i ) { + if ( !canCloseFd(i) ) continue; + ::close( i ); + } + } +} + +void zyppng::AbstractDirectSpawnEngine::resetSignals() +{ + // set all signal handers to their default + struct sigaction act; + memset (&act, 0, sizeof (struct sigaction)); + act.sa_handler = SIG_DFL; + for ( int i = 1; i < NSIG; i++ ) { + // this might return -1 and set errno for unknown signals, but + // thats fine for us. + sigaction(i, &act, NULL); + } + + // clear the sigmask + sigset_t sigMask; + sigemptyset ( &sigMask ); + pthread_sigmask ( SIG_SETMASK, &sigMask, nullptr ); +} + +bool zyppng::ForkSpawnEngine::start( const char * const *argv, int stdin_fd, int stdout_fd, int stderr_fd ) +{ + _pid = -1; + _exitStatus = 0; + _execError.clear(); + _executedCommand.clear(); + _args.clear(); + + if ( !argv || !argv[0] ) { + _execError = _("Invalid spawn arguments given."); + _exitStatus = 128; + return false; + } + + const char * chdirTo = nullptr; + + if ( _chroot == "/" ) { + // If _chroot is '/' do not chroot, but chdir to '/' + // unless arglist defines another dir. + chdirTo = "/"; + _chroot = zypp::Pathname(); + } + + if ( !_workingDirectory.empty() ) + chdirTo = _workingDirectory.c_str(); + + // do not remove the single quotes around every argument, copy&paste of + // command to shell will not work otherwise! + { + _args.clear(); + std::stringstream cmdstr; + for (int i = 0; argv[i]; i++) { + if ( i != 0 ) cmdstr << ' '; + cmdstr << '\''; + cmdstr << argv[i]; + cmdstr << '\''; + _args.push_back( argv[i] ); + } + _executedCommand = cmdstr.str(); + } + DBG << "Executing" << ( _useDefaultLocale?"[C] ":" ") << _executedCommand << std::endl; + + // we use a control pipe to figure out if the exec actually worked, + // this is the approach: + // - create a pipe before forking + // - block on the read end of the pipe in the parent process + // - in the child process we write a error tag + errno into the pipe if we encounter any error and exit + // - If child setup works out, the pipe is auto closed by exec() and the parent process knows from just receiving EOF + // that starting the child was successful, otherwise the blocking read in the parent will return with actual data read from the fd + // which will contain the error description + + enum class ChildErrType : int8_t { + NO_ERR, + CHROOT_FAILED, + CHDIR_FAILED, + EXEC_FAILED + }; + + struct ChildErr { + int childErrno = 0; + ChildErrType type = ChildErrType::NO_ERR; + }; + + auto controlPipe = Pipe::create( O_CLOEXEC ); + if ( !controlPipe ) { + _execError = _("Unable to create control pipe."); + _exitStatus = 128; + return false; + } + + pid_t ppid_before_fork = ::getpid(); + + // Create module process + if ( ( _pid = fork() ) == 0 ) + { + + // child process + resetSignals(); + controlPipe->unrefRead(); + + const auto &writeErrAndExit = [&]( int errCode, ChildErrType type ){ + ChildErr buf { + errno, + type + }; + + zypp::io::writeAll( controlPipe->writeFd, &buf, sizeof(ChildErr) ); + _exit ( errCode ); + }; + + ////////////////////////////////////////////////////////////////////// + // Don't write to the logfile after fork! + ////////////////////////////////////////////////////////////////////// + if ( _use_pty ) + { + setsid(); + dup2 ( stdout_fd, 1); // set new stdout + dup2 ( stdin_fd , 0); // set new stdin + + // We currently have no controlling terminal (due to setsid). + // The first open call will also set the new ctty (due to historical + // unix guru knowledge ;-) ) + + char name[512]; + ttyname_r( stdout_fd , name, sizeof(name) ); + ::close(open(name, O_RDONLY)); + } + else + { + if ( _switchPgid ) + setpgid( 0, 0); + if ( stdin_fd != -1 ) + dup2 ( stdin_fd, 0); // set new stdin + if ( stdout_fd != -1 ) + dup2 ( stdout_fd, 1); // set new stdout + } + + // Handle stderr + if ( stderr_fd != -1 ) + dup2 ( stderr_fd, 2); // set new stderr + + for ( Environment::const_iterator it = _environment.begin(); it != _environment.end(); ++it ) { + setenv( it->first.c_str(), it->second.c_str(), 1 ); + } + + if( _useDefaultLocale ) + setenv("LC_ALL","C",1); + + if( !_chroot.empty() ) + { + if( ::chroot(_chroot.c_str()) == -1) + { + _execError = zypp::str::form( _("Can't chroot to '%s' (%s)."), _chroot.c_str(), strerror(errno).c_str() ); + std::cerr << _execError << std::endl; // After fork log on stderr too + writeErrAndExit( 128, ChildErrType::CHROOT_FAILED ); // No sense in returning! I am forked away!! + } + if ( ! chdirTo ) + chdirTo = "/"; + } + + if ( chdirTo && chdir( chdirTo ) == -1 ) + { + _execError = _chroot.empty() ? zypp::str::form( _("Can't chdir to '%s' (%s)."), chdirTo, strerror(errno).c_str() ) + : zypp::str::form( _("Can't chdir to '%s' inside chroot '%s' (%s)."), chdirTo, _chroot.c_str(), strerror(errno).c_str() ); + + std::cerr << _execError << std::endl;// After fork log on stderr too + writeErrAndExit( 128, ChildErrType::CHDIR_FAILED ); // No sense in returning! I am forked away!! + } + + // map the extra fds the user might have set + mapExtraFds( controlPipe->writeFd ); + + if ( _dieWithParent ) { + // process dies with us + int r = prctl(PR_SET_PDEATHSIG, SIGTERM); + if (r == -1) { + //ignore if it did not work, worst case the process lives on after the parent dies + std::cerr << "Failed to set PR_SET_PDEATHSIG" << std::endl;// After fork log on stderr too + } + + // test in case the original parent exited just + // before the prctl() call + pid_t ppidNow = getppid(); + if (ppidNow != ppid_before_fork) { + // no sense to write to control pipe, parent is gone + std::cerr << "PPID changed from "<( argv ) ); + // don't want to get here + _execError = zypp::str::form( _("Can't exec '%s' (%s)."), _args[0].c_str(), strerror(errno).c_str() ); + std::cerr << _execError << std::endl;// After fork log on stderr too + writeErrAndExit( 129, ChildErrType::EXEC_FAILED ); // No sense in returning! I am forked away!! + ////////////////////////////////////////////////////////////////////// + } + else if ( _pid == -1 ) // Fork failed, close everything. + { + _execError = zypp::str::form( _("Can't fork (%s)."), strerror(errno).c_str() ); + _exitStatus = 127; + ERR << _execError << std::endl; + return false; + } + else { + + // parent process, fork worked lets wait for the exec to happen + controlPipe->unrefWrite(); + + ChildErr buf; + const auto res = zypp::io::readAll( controlPipe->readFd, &buf, sizeof(ChildErr) ); + if ( res == zypp::io::ReadAllResult::Eof ) { + // success!!!! + DBG << "pid " << _pid << " launched" << std::endl; + return true; + } else if ( res == zypp::io::ReadAllResult::Ok ) { + switch( buf.type ) { + case ChildErrType::CHDIR_FAILED: + _execError = zypp::str::form( _("Can't exec '%s', chdir failed (%s)."), _args[0].c_str(), zypp::str::strerror(buf.childErrno).c_str() ); + break; + case ChildErrType::CHROOT_FAILED: + _execError = zypp::str::form( _("Can't exec '%s', chroot failed (%s)."), _args[0].c_str(), zypp::str::strerror(buf.childErrno).c_str() ); + break; + case ChildErrType::EXEC_FAILED: + _execError = zypp::str::form( _("Can't exec '%s', exec failed (%s)."), _args[0].c_str(), zypp::str::strerror(buf.childErrno).c_str() ); + break; + // all other cases need to be some sort of error, because we only get data if the exec fails + default: + _execError = zypp::str::form( _("Can't exec '%s', unexpected error."), _args[0].c_str() ); + break; + } + ERR << "pid " << _pid << " launch failed: " << _execError << std::endl; + + // reap child and collect exit code + isRunning( true ); + return false; + } else { + //reading from the fd failed, this should actually never happen + ERR << "Reading from the control pipe failed. " << errno << ". This is not supposed to happen ever." << std::endl; + return isRunning(); + } + } + return true; +} + +bool zyppng::ForkSpawnEngine::usePty() const +{ + return _use_pty; +} + +void zyppng::ForkSpawnEngine::setUsePty( const bool set ) +{ + _use_pty = set; +} + + +#if ZYPP_HAS_GLIBSPAWNENGINE + +struct GLibForkData { + zyppng::GlibSpawnEngine *that = nullptr; + pid_t pidParent = -1; +}; + +bool zyppng::GlibSpawnEngine::start( const char * const *argv, int stdin_fd, int stdout_fd, int stderr_fd ) +{ + _pid = -1; + _exitStatus = 0; + _execError.clear(); + _executedCommand.clear(); + _args.clear(); + + if ( !argv || !argv[0] ) { + _execError = _("Invalid spawn arguments given."); + _exitStatus = 128; + return false; + } + + const char * chdirTo = nullptr; + + if ( _chroot == "/" ) { + // If _chroot is '/' do not chroot, but chdir to '/' + // unless arglist defines another dir. + chdirTo = "/"; + _chroot = zypp::Pathname(); + } + + if ( !_workingDirectory.empty() ) + chdirTo = _workingDirectory.c_str(); + + // do not remove the single quotes around every argument, copy&paste of + // command to shell will not work otherwise! + { + _args.clear(); + std::stringstream cmdstr; + for (int i = 0; argv[i]; i++) { + if ( i != 0 ) cmdstr << ' '; + cmdstr << '\''; + cmdstr << argv[i]; + cmdstr << '\''; + _args.push_back( argv[i] ); + } + _executedCommand = cmdstr.str(); + } + DBG << "Executing" << ( _useDefaultLocale?"[C] ":" ") << _executedCommand << std::endl; + + // build the env var ptrs + std::vector envStrs; + std::vector envPtrs; + + for ( char **envPtr = environ; *envPtr != nullptr; envPtr++ ) + envPtrs.push_back( *envPtr ); + + envStrs.reserve( _environment.size() ); + envPtrs.reserve( envPtrs.size() + _environment.size() + ( _useDefaultLocale ? 2 : 1 ) ); + for ( const auto &env : _environment ) { + envStrs.push_back( env.first + "=" + env.second ); + envPtrs.push_back( envStrs.back().data() ); + } + if ( _useDefaultLocale ) { + envStrs.push_back( "LC_ALL=C" ); + envPtrs.push_back( envStrs.back().data() ); + } + envPtrs.push_back( nullptr ); + + GLibForkData data; + data.that = this; + data.pidParent = ::getpid(); + + bool needCallback = !_chroot.empty() || _dieWithParent || _switchPgid || _mapFds.size(); + + auto spawnFlags = GSpawnFlags( G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH_FROM_ENVP ); + if ( _mapFds.size() ) + spawnFlags = GSpawnFlags( spawnFlags | G_SPAWN_LEAVE_DESCRIPTORS_OPEN ); + + GPid childPid = -1; + g_autoptr(GError) error = NULL; + g_spawn_async_with_fds( + chdirTo, + (gchar **)argv, + envPtrs.data(), + spawnFlags, + needCallback ? &GlibSpawnEngine::glibSpawnCallback : nullptr, + needCallback ? &data : nullptr, + &childPid, + stdin_fd, //in + stdout_fd, //out + stderr_fd, //err + &error + ); + + if ( !error ) { + _pid = childPid; + } else { + _execError = zypp::str::form( _("Can't fork (%s)."), strerror(errno).c_str() ); + _exitStatus = 127; + ERR << _execError << std::endl; + return false; + } + return true; +} + +void zyppng::GlibSpawnEngine::glibSpawnCallback(void *data) +{ + GLibForkData *d = reinterpret_cast(data); + + d->that->resetSignals(); + bool doChroot = !d->that->_chroot.empty(); + + std::string execError; + + if ( d->that->_switchPgid ) + setpgid( 0, 0); + + if ( doChroot ) { + if ( ::chroot( d->that->_chroot.c_str() ) == -1 ) { + execError = zypp::str::form( "Can't chroot to '%s' (%s).", d->that->_chroot.c_str(), strerror(errno).c_str() ); + std::cerr << execError << std::endl;// After fork log on stderr too + _exit (128); // No sense in returning! I am forked away!! + } + + std::string chdir; //if we are in chroot we need to chdir again + if ( d->that->_workingDirectory.empty() ) { + chdir = "/"; + } else { + chdir = d->that->_workingDirectory.asString(); + } + + if ( !chdir.empty() && ::chdir( chdir.data() ) == -1 ) + { + execError = doChroot ? zypp::str::form( "Can't chdir to '%s' inside chroot '%s' (%s).", chdir.data(), d->that->_chroot.c_str(), strerror(errno).c_str() ) + : zypp::str::form( "Can't chdir to '%s' (%s).", chdir.data(), strerror(errno).c_str() ); + std::cerr << execError << std::endl; // After fork log on stderr too + _exit (128); // No sense in returning! I am forked away!! + } + + } + + if ( d->that->_dieWithParent ) { + // process dies with us + int r = prctl(PR_SET_PDEATHSIG, SIGTERM); + if (r == -1) { + //ignore if it did not work, worst case the process lives on after the parent dies + std::cerr << "Failed to set PR_SET_PDEATHSIG" << std::endl;// After fork log on stderr too + } + + // test in case the original parent exited just + // before the prctl() call + pid_t ppidNow = getppid(); + if (ppidNow != d->pidParent ) { + std::cerr << "PPID changed from "<pidParent<<" to "<< ppidNow << std::endl;// After fork log on stderr too + _exit(128); + } + } + + // map the extra fds the user might have set + d->that->mapExtraFds(); +} +#endif diff --git a/zypp-core/zyppng/io/iobuffer.cc b/zypp-core/zyppng/io/iobuffer.cc new file mode 100644 index 0000000..0141e5c --- /dev/null +++ b/zypp-core/zyppng/io/iobuffer.cc @@ -0,0 +1,248 @@ +#include "private/iobuffer_p.h" +#include +#include + +namespace zyppng { + + enum { + DefChunkSize = 4096 + }; + + IOBuffer::IOBuffer( int64_t chunkSize ) : _defaultChunkSize ( chunkSize == 0 ? DefChunkSize : chunkSize ) + { } + + char *IOBuffer::reserve( int64_t bytes ) + { + assert( bytes > 0 && size_t(bytes) < ByteArray::maxSize() ); + // do we need a new chunk? + if ( _chunks.size() ) { + auto &back = _chunks.back(); + if ( back.available() >= bytes ) { + char * ptr = back._buffer.data() + back.tail; + back.tail += bytes; + return ptr; + } + } + + // not enough space ready allocate a new one + _chunks.push_back( Chunk{} ); + auto &back = _chunks.back(); + back._buffer.insert( back._buffer.end(), std::max( _defaultChunkSize, bytes ), '\0' ); + back.tail += bytes; + return back.data(); + } + + char *IOBuffer::front() + { + if ( frontSize() == 0 ) + return nullptr; + + return _chunks.front().data(); + } + + int64_t IOBuffer::frontSize() const + { + if ( _chunks.empty() ) + return 0; + return _chunks.front().len(); + } + + void IOBuffer::clear() + { + _chunks.clear(); + } + + int64_t IOBuffer::discard( int64_t bytes ) + { + const int64_t bytesToDiscard = std::min(bytes, size()); + if ( bytesToDiscard == size() ) { + clear(); + return bytesToDiscard; + } + + int64_t discardedSoFar = 0; + + // since the chunks might not be used completely we need to iterate over them + // counting how much used bytes we actually discard until we hit the requested amount + while ( discardedSoFar < bytesToDiscard ) { + auto &chunk = _chunks.front(); + const auto bytesInChunk = chunk.len(); + + if ( discardedSoFar + bytesInChunk > bytesToDiscard ) { + chunk.head += ( bytesToDiscard - discardedSoFar ); + discardedSoFar = bytesToDiscard; + } else { + _chunks.erase( _chunks.begin() ); + discardedSoFar += bytesInChunk; + } + } + + + return bytesToDiscard; + } + + /*! + * Removes bytes from the end of the buffer + */ + void IOBuffer::chop( int64_t bytes ) + { + if ( bytes == 0 ) + return; + + bytes = std::min( bytes, size() ); + if ( bytes == size() ) { + clear(); + return; + } + + int64_t choppedSoFar = 0; + while ( choppedSoFar < bytes && _chunks.size() ) { + auto bytesStillToChop = bytes - choppedSoFar; + auto &chunk = _chunks.back(); + + if ( chunk.len() > bytesStillToChop ) { + chunk.tail -= bytesStillToChop; + break; + } else { + choppedSoFar += chunk.len(); + _chunks.pop_back(); + } + } + } + + void IOBuffer::append(const char *data, int64_t count) + { + if ( count <= 0 ) + return; + + assert( count > 0 && size_t(count) < ByteArray::maxSize() ); + + char *buf = reserve( count ); + if ( count == 1 ) + *buf = *data; + else { + ::memcpy( buf, data, count ); + } + } + + void IOBuffer::append(const ByteArray &data) + { + append( data.data(), data.size() ); + } + + int64_t IOBuffer::read( char *buffer, int64_t max ) + { + const size_t bytesToRead = std::min( size(), max ); + size_t readSoFar = 0; + + while ( readSoFar < bytesToRead && _chunks.size() ) { + + auto &chunk = _chunks.front(); + const auto toRead = std::min( bytesToRead - readSoFar, chunk.len() ); + ::memcpy( buffer+readSoFar, chunk.data(), toRead ); + readSoFar += toRead; + + // if we consumed all data in the chunk discard it + chunk.head += toRead; + if( chunk.head >= chunk.tail ) + _chunks.erase( _chunks.begin() ); + } + + return readSoFar; + } + + int64_t IOBuffer::size() const + { + int64_t s = 0; + for ( const auto &c : _chunks ) + s+= c.len(); + return s; + } + + std::vector::size_type IOBuffer::chunks() const + { + return _chunks.size(); + } + + int64_t IOBuffer::indexOf(const char c, int64_t maxCount, int64_t pos ) const + { + if ( maxCount == 0 ) + return -1; + + maxCount = std::min( maxCount, size() ); + + int64_t scannedSoFar = 0; + for ( const auto &chunk : _chunks ) { + + //as long as pos is still after the current chunk just increase the count + if ( scannedSoFar+chunk.len() - 1 < pos ) { + scannedSoFar += chunk.len(); + continue; + } + + const char * const chunkBegin = chunk.data(); + const char *s = chunkBegin; + + size_t lengthToScan = std::min( chunk.len() , maxCount - scannedSoFar ); + if ( pos > 0 && scannedSoFar < pos ) { + const auto adjust = (pos-scannedSoFar); + s += adjust; + lengthToScan -= adjust; + } + + const char *ptr = reinterpret_cast(::memchr( s, c, lengthToScan )); + if ( ptr ) { + return ( ( ptr - chunkBegin ) + scannedSoFar ); + } + + scannedSoFar += chunk.len(); + if ( scannedSoFar >= maxCount ) + break; + } + return -1; + } + + ByteArray IOBuffer::readUntil(const char delim, const int64_t max) + { + assert( ( max >= 2 || max == 0 ) && size_t(max) <= ByteArray::maxSize() ); + + const auto idx = indexOf( delim, max == 0 ? size() : max ); + if ( idx == -1 ) + return {}; + + zyppng::ByteArray b( idx+1, '\0' ); + read( b.data(), idx+1 ); + return b; + } + + int64_t IOBuffer::readUntil(char *buffer, const char delim, int64_t max) + { + assert( buffer != nullptr && max > 1 ); + const auto maxRead = max - 1; + const auto idx = indexOf( delim, maxRead ); + const auto bytesRead = read( buffer, idx == -1 ? maxRead : idx + 1 ); + buffer[bytesRead] = '\0'; + return bytesRead; + } + + ByteArray IOBuffer::readLine( const int64_t max ) + { + return readUntil( '\n', max ); + } + + int64_t IOBuffer::readLine( char *buffer, int64_t max ) + { + return readUntil( buffer, '\n', max ); + } + + bool IOBuffer::canReadUntil(const char delim) const + { + return indexOf(delim) >= 0; + } + + bool IOBuffer::canReadLine() const + { + return canReadUntil('\n'); + } + +} diff --git a/zypp-core/zyppng/io/iodevice.cc b/zypp-core/zyppng/io/iodevice.cc new file mode 100644 index 0000000..bdf1998 --- /dev/null +++ b/zypp-core/zyppng/io/iodevice.cc @@ -0,0 +1,411 @@ +#include "private/iodevice_p.h" + +namespace zyppng { + + IODevicePrivate::IODevicePrivate(IODevice &p) : BasePrivate(p) + { } + + ZYPP_IMPL_PRIVATE(IODevice) + + IODevice::IODevice() : Base( *( new IODevicePrivate(*this)) ) + { } + + IODevice::IODevice(IODevicePrivate &d) : Base(d) + { } + + bool IODevice::open( const OpenMode mode ) + { + Z_D(); + + d->_mode = mode; + d->_readChannels.clear(); + if ( canRead() ) { + d->_readChannels.push_back( IOBuffer( d->_readBufChunkSize ) ); + setReadChannel( 0 ); + } + + return true; + } + + void IODevice::close() + { + Z_D(); + d->_mode = IODevice::Closed; + d->_readChannels.clear(); + } + + void IODevice::setReadChannelCount ( uint channels ) { + Z_D(); + if ( canRead() ) { + d->_readChannels.resize( channels ); + } + } + + void IODevice::finishReadChannel( uint channel ) + { + Z_D(); + if ( channel >= d->_readChannels.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + return; + } + + // just signal code that the read channel is finished) + d->_sigReadChannelFinished.emit( channel ); + } + + void IODevice::setReadChannel ( uint channel ) + { + Z_D(); + if ( !canRead() ) + return; + if ( channel >= d->_readChannels.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::out_of_range( constants::outOfRangeErrMsg.data() ); + } + d->_currentReadChannel = channel; + readChannelChanged( channel ); + } + + uint IODevice::currentReadChannel () const + { + Z_D(); + if ( !canRead() ) + return 0; + return d->_currentReadChannel; + } + + int IODevice::readChannelCount () const + { + Z_D(); + if ( !canRead() ) + return 0; + return d->_readChannels.size(); + } + + bool IODevice::canRead() const + { + return ( d_func()->_mode & IODevice::ReadOnly ); + } + + bool IODevice::canWrite() const + { + return ( d_func()->_mode & IODevice::WriteOnly ); + } + + bool IODevice::isOpen() const + { + return d_func()->_mode != IODevice::Closed; + } + + bool IODevice::canReadLine() const + { + Z_D(); + if ( !canRead() ) + return false; + + return canReadLine( d->_currentReadChannel ); + } + + int64_t IODevice::bytesAvailable() const + { + Z_D(); + return bytesAvailable( d->_currentReadChannel ); + } + + int64_t IODevice::readBufferCount () const + { + Z_D(); + return readBufferCount( d->_currentReadChannel ); + } + + ByteArray IODevice::readAll() + { + Z_D(); + return readAll( d->_currentReadChannel ); + } + + ByteArray IODevice::read( int64_t maxSize ) + { + if ( !canRead() || maxSize <= 0 ) + return {}; + return read( d_func()->_currentReadChannel, maxSize ); + } + + int64_t IODevice::read(char *buf, int64_t maxSize ) + { + Z_D(); + if ( !canRead() ) + return -1; + return read( d->_currentReadChannel, buf, maxSize ); + } + + ByteArray IODevice::readLine( const int64_t maxSize ) + { + if ( !canRead() ) + return {}; + + return channelReadLine( d_func()->_currentReadChannel, maxSize ); + } + + ByteArray IODevice::readAll( uint channel ) + { + return read( channel, bytesAvailable( channel ) ); + } + + ByteArray IODevice::read( uint channel, int64_t maxSize ) + { + if ( !canRead() || maxSize <= 0 ) + return {}; + + ByteArray res( maxSize, '\0' ); + const auto r = read( channel, res.data(), maxSize ); + res.resize( r ); + return res; + } + + int64_t IODevice::read( uint channel, char *buf, int64_t maxSize ) + { + Z_D(); + if ( !canRead() || maxSize < 0 ) + return -1; + + if ( channel >= d->_readChannels.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::out_of_range( constants::outOfRangeErrMsg.data() ); + } + + int64_t readSoFar = d->_readChannels[ channel ].read( buf, maxSize ); + + // try to read more from the device + if ( readSoFar < maxSize ) { + int64_t readFromDev = readData( channel, buf+readSoFar, maxSize - readSoFar ); + if ( readFromDev > 0 ) + return readSoFar + readFromDev; + } + return readSoFar; + } + + ByteArray IODevice::channelReadUntil( uint channel, const char delim, int64_t maxSize ) + { + Z_D(); + if ( !canRead() || maxSize < 0 ) + return {}; + + if ( channel >= d->_readChannels.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::out_of_range( constants::outOfRangeErrMsg.data() ); + } + + ByteArray result; + // largest possible ByteArray in int64_t boundaries + const auto maxBArrSize = int64_t( std::min( ByteArray::maxSize(), std::size_t(std::numeric_limits::max()) ) ); + if ( maxSize > maxBArrSize ) { + ERR << "Calling channelReadUntil with maxSize > int64_t(ByteArray::maxSize) " << std::endl; + maxSize = maxBArrSize - 1; + } + + // how much did we read? + int64_t readSoFar = 0; + + // if we have no size or the size is really big we read incrementally, use the buffer chunk size + // to read full chunks from the buffer if possible + if ( maxSize == 0 || maxSize >= (maxBArrSize - 1) ) { + + // largest possible ByteArray + maxSize = maxBArrSize; + + // we need to read in chunks until we get a \n + int64_t lastReadSize = 0; + result.resize (1); // leave room for \0 + do { + result.resize( std::min( std::size_t(maxSize), std::size_t(result.size() + d->_readBufChunkSize )) ); + lastReadSize = channelReadUntil( channel, result.data() + readSoFar, delim, result.size() - readSoFar ); + if ( lastReadSize > 0) + readSoFar += lastReadSize; + + // check for equal _readBufSize, + // our readData request is always 1 byte bigger than the _readBufChunkSize because of the initial byte we allocated in the result buffer, + // so the \0 that is appended by readLine does not make a difference. + } while( lastReadSize == d->_readBufChunkSize + && result[readSoFar-1] != delim ); + + } else { + result.resize( maxSize ); + readSoFar = channelReadUntil( channel, result.data(), delim, result.size() ); + } + + if ( readSoFar > 0 ) { + // we do not need to keep the \0 in the ByteArray + result.resize( readSoFar ); + } else { + result.clear (); + } + + // make sure we do not waste memory + result.shrink_to_fit(); + + return result; + } + + ByteArray IODevice::channelReadLine( uint channel, int64_t maxSize ) + { + return channelReadUntil( channel, '\n', maxSize ); + } + + int64_t IODevice::channelReadLine( uint channel, char *buf, const int64_t maxSize ) + { + return channelReadUntil( channel, buf, '\n', maxSize ); + } + + int64_t IODevice::channelReadUntil(uint channel, char *buf, const char delimiter, const int64_t maxSize) + { + Z_D(); + + if ( !canRead() || maxSize < 0 ) + return -1; + + if ( channel >= d->_readChannels.size() ) { + ERR << constants::outOfRangeErrMsg << std::endl; + throw std::out_of_range( constants::outOfRangeErrMsg.data() ); + } + + if ( maxSize < 2 ) { + ERR << "channelReadUntil needs at least a buffsize of 2" << std::endl; + return -1; + } + + int64_t toRead = maxSize - 1; // append \0 at the end + int64_t readSoFar = 0; + if ( d->_readChannels[channel].size () > 0 ) + readSoFar = d->_readChannels[channel].readUntil( buf, delimiter, toRead + 1 /*IOBuffer appends \0*/ ); + + if ( readSoFar == toRead || ( readSoFar > 0 && buf[readSoFar-1] == delimiter ) ) { + buf[readSoFar] = '\0'; + return readSoFar; + } + + bool hasError = false; + // if we reach here, the buffer was either empty, or does not contain a \n, in both cases we need to + // read from the device directly until we hit a ending condition + while ( readSoFar < toRead ) { + const auto r = readData( channel, buf+readSoFar, 1 ); + if ( r == 0 ) { + // no data available to be read -> EOF, or data stream empty + break; + } + else if ( r < 0 ) { + hasError = true; + break; + } + readSoFar+=r; + + if ( buf[readSoFar-1] == delimiter ) + break; + } + + if ( readSoFar == 0 ) + return hasError ? -1 : 0; + + buf[readSoFar] = '\0'; + return readSoFar; + } + + int64_t IODevice::bytesAvailable ( uint channel ) const + { + Z_D(); + if ( !canRead() ) + return 0; + return d->_readChannels[channel].size() + rawBytesAvailable( channel ); + } + + int64_t IODevice::readBufferCount(uint channel) const + { + Z_D(); + if ( !canRead() ) + return 0; + return d->_readChannels[channel].size(); + } + + bool IODevice::canReadUntil(uint channel, const char delim) const + { + Z_D(); + if ( !canRead() || channel >= d->_readChannels.size() ) + return false; + return d->_readChannels[channel].canReadUntil( delim ); + } + + bool IODevice::canReadLine ( uint channel ) const + { + Z_D(); + if ( !canRead() || channel >= d->_readChannels.size() ) + return false; + return d->_readChannels[channel].canReadLine(); + } + + int64_t zyppng::IODevice::write( const zyppng::ByteArray &data) + { + if ( !canWrite() ) + return 0; + return write( data.data(), data.size() ); + } + + int64_t IODevice::write( const char *data, int64_t len) + { + if ( !canWrite() || len <= 0 ) + return 0; + return writeData( data, len ); + } + + bool IODevice::waitForReadyRead( int timeout) + { + Z_D(); + if ( !canRead() ) + return false; + + return waitForReadyRead( d->_currentReadChannel, timeout ); + } + + SignalProxy IODevice::sigReadyRead() + { + return d_func()->_readyRead; + } + + SignalProxy IODevice::sigChannelReadyRead () + { + return d_func()->_channelReadyRead; + } + + SignalProxy IODevice::sigBytesWritten() + { + return d_func()->_sigBytesWritten; + } + + SignalProxy< void ()> IODevice::sigAllBytesWritten () + { + return d_func()->_sigAllBytesWritten; + } + + SignalProxy IODevice::sigReadChannelFinished() + { + return d_func()->_sigReadChannelFinished; + } + + + IODeviceOStreamBuf::IODeviceOStreamBuf(IODeviceRef dev) : _dev(dev) + {} + + IODeviceOStreamBuf::int_type IODeviceOStreamBuf::overflow( int_type __c ) + { + if ( !_dev ){ + return traits_type::eof(); + } + char buf = __c; + if ( _dev->write ( &buf, 1 ) == 1 ) { + return traits_type::not_eof(__c); + } + return traits_type::eof(); + } + + +} + diff --git a/zypp-core/zyppng/io/iodevice.h b/zypp-core/zyppng/io/iodevice.h new file mode 100644 index 0000000..2581b0e --- /dev/null +++ b/zypp-core/zyppng/io/iodevice.h @@ -0,0 +1,213 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPPNG_IO_IODEVICE_DEFINED +#define ZYPPNG_IO_IODEVICE_DEFINED + +#include +#include +#include +#include + +namespace zyppng { + + class IODevicePrivate; + ZYPP_FWD_DECL_TYPE_WITH_REFS(IODevice); + + /*! + * The IODevice class represents a async sequential IO device, like a Socket or Pipe, + * to receive and or send data. + */ + class IODevice : public Base + { + ZYPP_DECLARE_PRIVATE(IODevice); + public: + + enum OpenModeFlag { + Closed = 0x0, + ReadOnly = 0x1, + WriteOnly = 0x2, + ReadWrite = ReadOnly | WriteOnly + }; + ZYPP_DECLARE_FLAGS( OpenMode, OpenModeFlag ); + + using Ptr = std::shared_ptr; + using WeakPtr = std::weak_ptr; + + IODevice(); + virtual void close (); + + void setReadChannel ( uint channel ); + uint currentReadChannel () const; + int readChannelCount () const; + + bool canRead () const; + bool canWrite () const; + bool isOpen () const; + + ByteArray readAll (); + ByteArray read ( int64_t maxSize ); + int64_t read ( char *buf, int64_t maxSize ); + virtual ByteArray readLine (const int64_t maxSize = 0 ); + virtual int64_t bytesAvailable () const; + int64_t readBufferCount() const; + bool canReadLine () const; + + ByteArray readAll ( uint channel ); + ByteArray read ( uint channel, int64_t maxSize ); + int64_t read ( uint channel, char *buf, int64_t maxSize ); + + + /*! + * Convenience function that reads a line from the device into a ByteArray. Since + * this function has no way to signal if a error happened, a empty ByteArray is + * returned if there was no data or if a error occured. + */ + ByteArray channelReadUntil ( uint channel, const char delim, int64_t maxSize = 0 ); + + /*! + * Convenience function that reads a line from the device into a ByteArray. Since + * this function has no way to signal if a error happened, a empty ByteArray is + * returned if there was no data or if a error occured. + */ + ByteArray channelReadLine ( uint channel, int64_t maxSize = 0 ); + + /*! + * Reads data from the device until one of the following conditions are met: + * - A \n is encountered + * - maxSize nr of bytes have been read + * - a error occurs on the device + * + * If bytes have been read from the device this always returns the number of bytes that + * have been read, otherwise if no data was read 0 is returned or if a error occurs -1 is returned. + */ + int64_t channelReadLine ( uint channel, char *buf, const int64_t maxSize ); + virtual int64_t bytesAvailable( uint channel ) const; + + /*! + * Returns the number of bytes currently buffered in the read buffer channel + */ + int64_t readBufferCount( uint channel ) const; + + /*! + * Reads data from the device until one of the following conditions are met: + * - The delimiter is encountered + * - maxSize nr of bytes have been read + * - a error occurs on the device + * + * If bytes have been read from the device this always returns the number of bytes that + * have been read, otherwise if no data was read 0 is returned or if a error occurs -1 is returned. + */ + virtual int64_t channelReadUntil ( uint channel, char *buf, const char delimiter, const int64_t maxSize ); + + /*! + * Returns true if a line can be read from the currently buffered data in the given channel + */ + bool canReadLine ( uint channel ) const; + + /*! + * Returns true if delim can be found in the currently buffered data + */ + bool canReadUntil ( uint channel, const char delim ) const; + + + int64_t write ( const ByteArray &data ); + int64_t write ( const char *data, int64_t len ); + + /*! + * Returns the current number of bytes that are not yet written to the device. + */ + virtual int64_t bytesPending() const = 0; + + /*! + * Blocks the current event loop to wait until there are bytes available to read from the device. + * This always operates on the read channel that is selected as the default when the function is first called, + * even if the default channel would be changed during the wait. + * + * \sa zyppng::IODevice::currentReadChannel + * \note do not use until there is a very good reason, like event processing should not continue until readyRead was sent + */ + bool waitForReadyRead(int timeout); + + /*! + * Blocks the current event loop to wait until there are bytes available to read from the given read channel. + * + * \note do not use until there is a very good reason, like event processing should not continue until readyRead was sent + */ + virtual bool waitForReadyRead(uint channel, int timeout) = 0; + + + /*! + * Signal is emitted when there is data available to read on the current default read channel + */ + SignalProxy sigReadyRead (); + + /*! + * Signal is emitted when there is data available on the given channel + */ + SignalProxy sigChannelReadyRead (); + + /*! + * Signal is emitted every time bytes have been written to the underlying device. + * This can be used to track how much data was actually sent. + */ + SignalProxy< void (int64_t)> sigBytesWritten (); + + /*! + * Signal is emitted every time all bytes have been written to the underlying device. + */ + SignalProxy< void ()> sigAllBytesWritten (); + + /*! + * Emitted when the backing device of the given read channel is closed, + * data might be still available in the buffer to read + */ + SignalProxy< void(uint) >sigReadChannelFinished(); + + protected: + IODevice( IODevicePrivate &d ); + virtual bool open ( const OpenMode mode ); + virtual int64_t rawBytesAvailable ( uint channel ) const = 0; + virtual int64_t writeData ( const char *data, int64_t count ) = 0; + virtual int64_t readData ( uint channel, char *buffer, int64_t bufsize ) = 0; + virtual void readChannelChanged ( uint channel ) = 0; + void setReadChannelCount ( uint channels ); + void finishReadChannel ( uint channel ); + }; + ZYPP_DECLARE_OPERATORS_FOR_FLAGS( IODevice::OpenMode ); + + + /*! + * Small wrapper streambuf to support writing data to a IODevice + * using std::ostream + */ + class IODeviceOStreamBuf : public std::streambuf + { + public: + IODeviceOStreamBuf( IODeviceRef dev ); + IODeviceOStreamBuf(const IODeviceOStreamBuf &) = default; + IODeviceOStreamBuf(IODeviceOStreamBuf &&) = default; + IODeviceOStreamBuf &operator=(const IODeviceOStreamBuf &) = default; + IODeviceOStreamBuf &operator=(IODeviceOStreamBuf &&) = default; + + // basic_streambuf interface + protected: + int_type overflow(int_type __c) override; + + private: + IODeviceRef _dev; + }; +} + +#endif diff --git a/zypp-core/zyppng/io/private/abstractspawnengine_p.h b/zypp-core/zyppng/io/private/abstractspawnengine_p.h new file mode 100644 index 0000000..5f0327f --- /dev/null +++ b/zypp-core/zyppng/io/private/abstractspawnengine_p.h @@ -0,0 +1,113 @@ +#ifndef ZYPPNG_IO_PRIVATE_ABSTRACTPROCESSBACKEND_H +#define ZYPPNG_IO_PRIVATE_ABSTRACTPROCESSBACKEND_H + +#include +#include +#include +#include +#include + +#include + +namespace zyppng { + + /*! + * This implements the basic skeleton of ExternalProgram and Process. + * Taking care of forking the process and setting up stdout and stderr so both + * implementations can use the same code + * + */ + class AbstractSpawnEngine + { + public: + + /** + * For passing additional environment variables to set + */ + using Environment = std::map; + + AbstractSpawnEngine(); + virtual ~AbstractSpawnEngine(); + + static std::unique_ptr createDefaultEngine (); + + int exitStatus () const; + void setExitStatus ( const int state ); + + const std::string &executedCommand () const; + const std::string &execError() const; + void setExecError ( const std::string & str ); + + zypp::Pathname chroot() const; + void setChroot( const zypp::Pathname &chroot ); + + bool useDefaultLocale() const; + void setUseDefaultLocale( bool defaultLocale ); + + Environment environment() const; + void setEnvironment( const Environment &environment ); + + /** + * @returns the pid of the forked process, without checking if the process is + * still running. + */ + pid_t pid ( ); + + /*! + * Kickstart the process, if this returns true it is guaranteed that exec() was successful + */ + virtual bool start ( const char *const *argv, int stdin_fd, int stdout_fd, int stderr_fd ) = 0; + + virtual bool waitForExit ( const std::optional &timeout = {} ) = 0; + virtual bool isRunning ( bool wait = false ) = 0; + + /*! + * Used to notify the backend that the process has ended, + * helpful when the process is tracked in another way than calling \ref isRunning, + * for example in a eventloop. + */ + virtual void notifyExited ( int status ); + + bool dieWithParent() const; + void setDieWithParent( bool dieWithParent ); + + bool switchPgid() const; + void setSwitchPgid(bool switchPgid); + + zypp::Pathname workingDirectory() const; + void setWorkingDirectory(const zypp::Pathname &workingDirectory); + + const std::vector &fdsToMap () const; + void addFd ( int fd ); + + int checkStatus(int status); + + protected: + bool _useDefaultLocale = false; + /** Should the process die with the parent process */ + bool _dieWithParent = false; + + bool _switchPgid = false; + + pid_t _pid = -1; + int _exitStatus = 0; + /** Remember execution errors like failed fork/exec. */ + std::string _execError; + /** Store the command we're executing. */ + std::string _executedCommand; + /** The arguments we want to pass to the program. */ + std::vector _args; + /** Environment variables to set in the new process. */ + Environment _environment; + /** Path to chroot into */ + zypp::Pathname _chroot; + /** Working directory */ + zypp::Pathname _workingDirectory; + /** Additional file descriptors we want to map to the new process */ + std::vector _mapFds; + + }; + +} // namespace zyppng + +#endif // ZYPPNG_IO_PRIVATE_ABSTRACTPROCESSBACKEND_H diff --git a/zypp-core/zyppng/io/private/asyncdatasource_p.h b/zypp-core/zyppng/io/private/asyncdatasource_p.h new file mode 100644 index 0000000..b1a327e --- /dev/null +++ b/zypp-core/zyppng/io/private/asyncdatasource_p.h @@ -0,0 +1,39 @@ +#ifndef ZYPP_CORE_ZYPPNG_IO_PRIVATE_ASYNCDATASOURCE_P_H_INCLUDED +#define ZYPP_CORE_ZYPPNG_IO_PRIVATE_ASYNCDATASOURCE_P_H_INCLUDED + +#include +#include +#include "iodevice_p.h" +#include "iobuffer_p.h" + +namespace zyppng { + + class AsyncDataSourcePrivate : public IODevicePrivate { + ZYPP_DECLARE_PUBLIC(AsyncDataSource); + public: + AsyncDataSourcePrivate ( AsyncDataSource &pub ) : IODevicePrivate(pub) {} + struct ReadChannelDev { + int _readFd = -1; + SocketNotifier::Ptr _readNotifier; + }; + std::vector _readFds; + + SocketNotifier::Ptr _writeNotifier; + IOBuffer _writeBuffer; + int _writeFd = -1; + + void notifierActivated (const SocketNotifier ¬ify, int evTypes ); + void readyRead ( uint channel ); + void readyWrite ( ); + + void closeWriteChannel ( AsyncDataSource::ChannelCloseReason reason ); + void closeReadChannel ( uint channel, AsyncDataSource::ChannelCloseReason reason ); + + Signal _sigWriteFdClosed; + Signal _sigReadFdClosed; + }; + +} + + +#endif // ZYPP_CORE_ZYPPNG_IO_PRIVATE_ASYNCDATASOURCE_P_H_INCLUDED diff --git a/zypp-core/zyppng/io/private/forkspawnengine_p.h b/zypp-core/zyppng/io/private/forkspawnengine_p.h new file mode 100644 index 0000000..cb0656d --- /dev/null +++ b/zypp-core/zyppng/io/private/forkspawnengine_p.h @@ -0,0 +1,66 @@ +#ifndef ZYPPNG_IO_PRIVATE_FORKSPAWNENGINE_H +#define ZYPPNG_IO_PRIVATE_FORKSPAWNENGINE_H + +#include "abstractspawnengine_p.h" +#include + +namespace zyppng { + + class AbstractDirectSpawnEngine : public AbstractSpawnEngine + { + public: + ~AbstractDirectSpawnEngine() override; + + bool isRunning ( bool wait = false ) override; + bool waitForExit ( const std::optional &timeout = {} ) override; + + protected: + void mapExtraFds( int controlFd = -1 ); + void resetSignals(); + }; + + /*! + \internal + Process forking engine that's using the traditional fork() approach + */ + class ForkSpawnEngine : public AbstractDirectSpawnEngine + { + public: + bool start( const char *const *argv, int stdin_fd, int stdout_fd, int stderr_fd ) override; + bool usePty () const; + void setUsePty ( const bool set = true ); + + private: + /** + * Set to true, if a pair of ttys is used for communication + * instead of a pair of pipes. + */ + bool _use_pty = false; + }; + +#if GLIB_CHECK_VERSION( 2, 58, 0) + +#define ZYPP_HAS_GLIBSPAWNENGINE 1 + + /*! + \internal + Process forking engine that's using g_spawn from glib which can in most cases optimize + using posix_spawn. + */ + class GlibSpawnEngine : public AbstractDirectSpawnEngine + { + public: + bool start( const char *const *argv, int stdin_fd, int stdout_fd, int stderr_fd ) override; + + private: + static void glibSpawnCallback ( void *data ); + }; + +#else + #define ZYPP_HAS_GLIBSPAWNENGINE 0 +#endif + +} + + +#endif // diff --git a/zypp-core/zyppng/io/private/iobuffer_p.h b/zypp-core/zyppng/io/private/iobuffer_p.h new file mode 100644 index 0000000..741a602 --- /dev/null +++ b/zypp-core/zyppng/io/private/iobuffer_p.h @@ -0,0 +1,64 @@ +#ifndef ZYPPNG_IO_IOBUFFER_P_H +#define ZYPPNG_IO_IOBUFFER_P_H + +#include +#include +#include + +namespace zyppng { + + class IOBuffer { + + struct Chunk { + ByteArray _buffer; + + int64_t head = 0; + int64_t tail = 0; + + char * data () { + return _buffer.data() + head; + } + + const char * data () const { + return _buffer.data() + head; + } + + int64_t available() const { + return _buffer.size() - tail; + } + int64_t len () const { + return tail - head; + } + }; + + public: + IOBuffer( int64_t chunkSize = 0 ); + + char *reserve( int64_t bytes ); + char *front (); + int64_t frontSize () const; + void clear ( ); + int64_t discard( int64_t bytes ); + void chop ( int64_t bytes ); + void append ( const char *data, int64_t count ); + void append ( const ByteArray &data ); + int64_t read ( char *buffer, int64_t max ); + int64_t size ( ) const; + std::vector::size_type chunks () const; + inline int64_t indexOf ( const char c ) const { return indexOf( c, size() ); } + int64_t indexOf (const char c, int64_t maxCount, int64_t pos = 0 ) const; + ByteArray readUntil ( const char delim, const int64_t max = 0 ); + int64_t readUntil( char *buffer, const char delim, int64_t max ); + ByteArray readLine ( const int64_t max = 0 ); + int64_t readLine( char *buffer, int64_t max ); + bool canReadUntil ( const char delim ) const; + bool canReadLine () const; + + private: + int64_t _defaultChunkSize; + std::vector _chunks; + }; + +} + +#endif diff --git a/zypp-core/zyppng/io/private/iodevice_p.h b/zypp-core/zyppng/io/private/iodevice_p.h new file mode 100644 index 0000000..eed00b8 --- /dev/null +++ b/zypp-core/zyppng/io/private/iodevice_p.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPPNG_IO_IODEVICE_P_DEFINED +#define ZYPPNG_IO_IODEVICE_P_DEFINED + +#include +#include +#include +#include +#include "iobuffer_p.h" + + +namespace zyppng { + + namespace constants { + constexpr std::string_view outOfRangeErrMsg("Channel index out of range"); + } + + enum { + DefIoDeviceBufChunkSize = 16384 + }; + + class IODevicePrivate : public BasePrivate { + public: + IODevicePrivate ( IODevice &p ); + + std::vector _readChannels; + uint _currentReadChannel = 0; + int64_t _readBufChunkSize = DefIoDeviceBufChunkSize; + + IODevice::OpenMode _mode = IODevice::Closed; + Signal< void() > _readyRead; + Signal< void(uint) > _channelReadyRead; + Signal< void (int64_t)> _sigBytesWritten; + Signal< void ()> _sigAllBytesWritten; + Signal< void(uint) > _sigReadChannelFinished; + }; + +} + + +#endif diff --git a/zypp-core/zyppng/io/private/sockaddr_p.h b/zypp-core/zyppng/io/private/sockaddr_p.h new file mode 100644 index 0000000..d7a17c5 --- /dev/null +++ b/zypp-core/zyppng/io/private/sockaddr_p.h @@ -0,0 +1,19 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_IO_SOCKADDR_P_H +#define ZYPPNG_IO_SOCKADDR_P_H + +#include + +#endif // ZYPPNG_IO_SOCKADDR_P_H diff --git a/zypp-core/zyppng/io/private/socket_p.h b/zypp-core/zyppng/io/private/socket_p.h new file mode 100644 index 0000000..2f7781b --- /dev/null +++ b/zypp-core/zyppng/io/private/socket_p.h @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPPNG_IO_SOCKET_P_DEFINED +#define ZYPPNG_IO_SOCKET_P_DEFINED + +#include +#include +#include +#include +#include "iodevice_p.h" + +#include + +namespace zyppng { + + class SocketPrivate : public IODevicePrivate + { + ZYPP_DECLARE_PUBLIC(Socket); + public: + + SocketPrivate( int domain, int type, int protocol, Socket &p ) : IODevicePrivate(p), + _domain(domain), + _type( type ), + _protocol( protocol ) + { } + + static Socket::Ptr wrapSocket( int fd, int domain, int type, int protocol, Socket::SocketState state ); + + bool initSocket () ; + void setError ( Socket::SocketError error, std::string &&err, bool emit = true ); + bool handleConnectError ( int error ); + + bool transition ( Socket::SocketState newState ); + Socket::SocketState state () const; + + bool connectToHost (); + void onSocketActivated ( int ev ); + void onSocketActivatedSlot ( const SocketNotifier &, int ev ) { + return onSocketActivated(ev); + } + int64_t rawBytesAvailable () const; + bool readRawBytesToBuffer (); + bool writePendingData (); + + int _domain; + int _type; + int _protocol; + std::shared_ptr _targetAddr; + + int _socket = -1; + bool _borrowedSocket = false; + + //error handling + bool _emittedErr = false; + Socket::SocketError _error = Socket::NoError; + std::string _errorDesc; + + //signals + Signal< void(Socket::SocketError)> _sigError; + Signal< void()> _incomingConnection; + Signal< void()> _connected; + Signal< void()> _disconnected; + + + struct InitialState { + static constexpr Socket::SocketState type() { return Socket::InitialState; } + }; + + struct ConnectingState : public sigc::trackable { + NON_COPYABLE(ConnectingState); + ConnectingState() = default; + + static constexpr Socket::SocketState type() { return Socket::ConnectingState; } + + SocketNotifier::Ptr _connectNotifier; + Timer::Ptr _connectTimeout; + }; + + struct ConnectedState : public sigc::trackable { + NON_COPYABLE(ConnectedState); + ConnectedState() = default; + static constexpr Socket::SocketState type() { return Socket::ConnectedState; } + SocketNotifier::Ptr _socketNotifier; + IOBuffer _writeBuffer; + }; + + struct ListeningState : public sigc::trackable { + NON_COPYABLE(ListeningState); + ListeningState() = default; + static constexpr Socket::SocketState type() { return Socket::ListeningState; } + SocketNotifier::Ptr _socketNotifier; + }; + + struct ClosingState { + static constexpr Socket::SocketState type() { return Socket::ClosingState; } + ClosingState( IOBuffer &&writeBuffer ); + + SocketNotifier::Ptr _socketNotifier; + IOBuffer _writeBuffer; + }; + + struct ClosedState { + static constexpr Socket::SocketState type() { return Socket::ClosedState; } + }; + std::variant< InitialState, ConnectingState, ConnectedState, ListeningState, ClosingState, ClosedState > _state = InitialState(); + }; + +} + +#endif diff --git a/zypp-core/zyppng/io/process.cpp b/zypp-core/zyppng/io/process.cpp new file mode 100644 index 0000000..230f2c9 --- /dev/null +++ b/zypp-core/zyppng/io/process.cpp @@ -0,0 +1,302 @@ +#include "process.h" +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + /*! + * @todo We will receive a started signal here before exec was called, so sigStarted actually just + * signals that the fork has worked out but NOT that the app actually started + */ + + class ProcessPrivate : public AsyncDataSourcePrivate + { + public: + ProcessPrivate( Process &p ) + : AsyncDataSourcePrivate(p) + , _sigFinished(p) + { } + + void cleanup() { + _stdinFd = -1; + _stderrFd = -1; + _stdoutFd = -1; + } + + std::unique_ptr _spawnEngine = AbstractSpawnEngine::createDefaultEngine(); + zypp::AutoFD _stdinFd = -1; + zypp::AutoFD _stderrFd = -1; + zypp::AutoFD _stdoutFd = -1; + Signal _sigStarted; + MemSignal _sigFinished; + Signal _sigFailedToStart; + + Process::OutputChannelMode _channelMode = Process::Seperate; + Process::OutputChannel _currentChannel = Process::StdOut; + }; + + ZYPP_IMPL_PRIVATE(Process) + + Process::Process() : AsyncDataSource( *( new ProcessPrivate(*this) ) ) + { + + } + + Process::Ptr Process::create() + { + return std::shared_ptr( new Process() ); + } + + Process::~Process() + { + Z_D(); + if ( d->_spawnEngine->pid() >= 0 ) { + EventDispatcher::instance()->untrackChildProcess( d->_spawnEngine->pid() ); + DBG << "Process destroyed while still running removing from EventLoop." << std::endl; + } + } + + bool Process::start( const char *const *argv ) + { + Z_D(); + + if ( !EventDispatcher::instance() ) { + ERR << "A valid EventDispatcher needs to be registered before starting a Process" << std::endl; + return false; + } + + if ( isRunning() ) + return false; + + // clean up the previous run + AsyncDataSource::close(); + d->cleanup(); + + // create the pipes we need + auto stdinPipe = Pipe::create( ); + if ( !stdinPipe ) { + d->_sigFailedToStart.emit(); + return false; + } + + auto stdoutPipe = Pipe::create( ); + if ( !stdoutPipe ) { + d->_sigFailedToStart.emit(); + return false; + } + + int stderr_fd = -1; + std::optional stderrPipe; + if ( d->_channelMode == Seperate ) { + stderrPipe = Pipe::create( ); + if ( !stderrPipe ) { + d->_sigFailedToStart.emit(); + return false; + } + stderr_fd = stderrPipe->writeFd; + } else { + stderr_fd = stdoutPipe->writeFd; + } + + if ( d->_spawnEngine->start( argv, stdinPipe->readFd, stdoutPipe->writeFd, stderr_fd ) ) { + + // if we reach this point the engine guarantees that exec() was successful + const auto pid = d->_spawnEngine->pid( ); + + // register to the eventloop right away + EventDispatcher::instance()->trackChildProcess( pid, [this]( int, int status ){ + Z_D(); + d->_spawnEngine->notifyExited( status ); + d->_sigFinished.emit( d->_spawnEngine->exitStatus() ); + }); + + // make sure the fds we need are kept open + d->_stdinFd = std::move( stdinPipe->writeFd ); + d->_stdoutFd = std::move( stdoutPipe->readFd ); + + std::vector rFds { d->_stdoutFd }; + if ( stderrPipe ) { + d->_stderrFd = std::move( stderrPipe->readFd ); + rFds.push_back( d->_stderrFd.value() ); + } + + if ( !openFds( rFds, d->_stdinFd ) ) { + stop( SIGKILL ); + return false; + } + + d->_sigStarted.emit(); + return true; + } + d->_sigFailedToStart.emit(); + return false; + } + + void Process::stop( int signal ) + { + Z_D(); + if ( isRunning() ) { + ::kill( d->_spawnEngine->pid(), signal ); + } + } + + bool Process::isRunning() + { + Z_D(); + return ( d->_spawnEngine->pid() > -1 ); + } + + void Process::close () + { + flush(); + stop(SIGKILL); + d_func()->cleanup(); + AsyncDataSource::close(); + } + + void Process::waitForExit() + { + Z_D(); + if ( d->_spawnEngine->isRunning() ) { + // we will manually track the exit status + EventDispatcher::instance()->untrackChildProcess( d->_spawnEngine->pid() ); + // wait for the process to exit + d->_spawnEngine->isRunning( true ); + } + } + + void Process::closeWriteChannel() + { + Z_D(); + d->_stdinFd = -1; + AsyncDataSource::closeWriteChannel(); + } + + const std::string &Process::executedCommand() const + { + return d_func()->_spawnEngine->executedCommand(); + } + + const std::string &Process::execError() const + { + return d_func()->_spawnEngine->execError(); + } + + zypp::filesystem::Pathname Process::chroot() const + { + return d_func()->_spawnEngine->chroot(); + } + + void Process::setChroot( const zypp::filesystem::Pathname &chroot ) + { + return d_func()->_spawnEngine->setChroot( chroot ); + } + + bool Process::useDefaultLocale() const + { + return d_func()->_spawnEngine->useDefaultLocale(); + } + + void Process::setUseDefaultLocale( bool defaultLocale ) + { + return d_func()->_spawnEngine->setUseDefaultLocale( defaultLocale ); + } + + Process::Environment Process::environment() const + { + return d_func()->_spawnEngine->environment(); + } + + void Process::setEnvironment( const Process::Environment &env ) + { + return d_func()->_spawnEngine->setEnvironment( env ); + } + + pid_t Process::pid() + { + return d_func()->_spawnEngine->pid(); + } + + int Process::exitStatus() const + { + return d_func()->_spawnEngine->exitStatus(); + } + + bool Process::dieWithParent() const + { + return d_func()->_spawnEngine->dieWithParent(); + } + + void Process::setDieWithParent( bool enabled ) + { + return d_func()->_spawnEngine->setDieWithParent( enabled ); + } + + bool Process::switchPgid() const + { + return d_func()->_spawnEngine->switchPgid(); + } + + void Process::setSwitchPgid(bool enabled) + { + return d_func()->_spawnEngine->setSwitchPgid( enabled ); + } + + zypp::filesystem::Pathname Process::workingDirectory() const + { + return d_func()->_spawnEngine->workingDirectory(); + } + + void Process::setWorkingDirectory(const zypp::filesystem::Pathname &wd) + { + return d_func()->_spawnEngine->setWorkingDirectory( wd ); + } + + const std::vector &Process::fdsToMap() const + { + return d_func()->_spawnEngine->fdsToMap(); + } + + void Process::addFd(int fd) + { + return d_func()->_spawnEngine->addFd( fd ); + } + + int Process::stdinFd() + { + return d_func()->_stdinFd; + } + + int Process::stdoutFd() + { + return d_func()->_stdoutFd; + } + + int Process::stderrFd() + { + return d_func()->_stderrFd; + } + + SignalProxy Process::sigStarted() + { + return d_func()->_sigStarted; + } + + SignalProxy Process::sigFailedToStart() + { + return d_func()->_sigFailedToStart; + } + + SignalProxy Process::sigFinished() + { + return d_func()->_sigFinished; + } + + Process::OutputChannelMode Process::outputChannelMode() const { return d_func()->_channelMode; } + void Process::setOutputChannelMode(const OutputChannelMode &outputChannelMode) { d_func()->_channelMode = outputChannelMode; } + +} diff --git a/zypp-core/zyppng/io/process.h b/zypp-core/zyppng/io/process.h new file mode 100644 index 0000000..687b1e3 --- /dev/null +++ b/zypp-core/zyppng/io/process.h @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPPNG_IO_PROCESS_H_DEFINED +#define ZYPPNG_IO_PROCESS_H_DEFINED + +#include +#include +#include +#include +#include + +namespace zyppng { + + class ProcessPrivate; + class IODevice; + + ZYPP_FWD_DECL_TYPE_WITH_REFS (Process); + + class Process : public AsyncDataSource + { + ZYPP_DECLARE_PRIVATE(Process); + public: + /** + * For passing additional environment variables to set + */ + using Environment = std::map; + using Ptr = ProcessRef; + using WeakPtr = ProcessWeakRef; + + enum OutputChannelMode { + Seperate, + Merged + }; + + enum OutputChannel { + StdOut = 0, + StdErr = 1 + }; + + static Ptr create (); + ~Process() override; + + bool start ( const char *const *argv ); + void stop ( int signal = SIGTERM ); + bool isRunning (); + void close () override; + + /*! + * Blocks until the process has exited, during that time readyRead is not + * emitted for any read channels. Call \ref readAll to get all remaining data + * that was written by the process + */ + void waitForExit (); + + /*! + * Close the stdin fd of the subprocess. This is required for processes + * that run until their stdin is closed. + */ + void closeWriteChannel () override; + + const std::string &executedCommand () const; + const std::string &execError() const; + + zypp::Pathname chroot() const; + void setChroot( const zypp::Pathname &chroot ); + + bool useDefaultLocale() const; + void setUseDefaultLocale( bool defaultLocale ); + + Environment environment() const; + void setEnvironment( const Environment &environment ); + + pid_t pid (); + int exitStatus () const; + + bool dieWithParent() const; + void setDieWithParent(bool enabled ); + + bool switchPgid() const; + void setSwitchPgid(bool enabled); + + zypp::Pathname workingDirectory() const; + void setWorkingDirectory(const zypp::Pathname &workingDirectory); + + const std::vector &fdsToMap () const; + void addFd ( int fd ); + + int stdinFd (); + int stdoutFd (); + int stderrFd (); + + SignalProxy sigStarted (); + SignalProxy sigFailedToStart (); + SignalProxy sigFinished (); + + OutputChannelMode outputChannelMode() const; + void setOutputChannelMode(const OutputChannelMode &outputChannelMode); + + protected: + Process(); + }; +} + +#endif // ZYPPNG_IO_PROCESS_H_DEFINED diff --git a/zypp-core/zyppng/io/sockaddr.cpp b/zypp-core/zyppng/io/sockaddr.cpp new file mode 100644 index 0000000..fcd4e36 --- /dev/null +++ b/zypp-core/zyppng/io/sockaddr.cpp @@ -0,0 +1,32 @@ +#include "sockaddr.h" +#include + +namespace zyppng { + + UnixSockAddr::UnixSockAddr(const std::string &path , bool abstract ) : _data( std::make_shared() ) + { + memset( _data.get(), 0, size() ); + + _data->sun_family = AF_UNIX; + if ( path.size() ) { + const auto align = abstract ? 1 : 0; + path.copy( _data->sun_path + align, sizeof( _data->sun_path ) - align - 1 ); + } + } + + sockaddr *UnixSockAddr::nativeSockAddr() const + { + return reinterpret_cast(_data.get()); + } + + std::size_t UnixSockAddr::size() const + { + return sizeof(struct sockaddr_un); + } + + bool UnixSockAddr::isAbstract() const + { + return _data->sun_path[0]; + } + +} diff --git a/zypp-core/zyppng/io/sockaddr.h b/zypp-core/zyppng/io/sockaddr.h new file mode 100644 index 0000000..eb94fb0 --- /dev/null +++ b/zypp-core/zyppng/io/sockaddr.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_IO_SOCKADDR_H_DEFINED +#define ZYPPNG_IO_SOCKADDR_H_DEFINED + +#include +#include +#include +#include + +struct sockaddr_un; + +namespace zyppng { + + class SockAddr { + public: + virtual ~SockAddr(){}; + virtual struct ::sockaddr* nativeSockAddr () const = 0; + virtual std::size_t size () const = 0; + protected: + + }; + + class UnixSockAddr : public SockAddr + { + public: + + using Ptr = std::shared_ptr; + + UnixSockAddr( const std::string &path, bool abstract ); + + // SockAddr interface + sockaddr *nativeSockAddr() const override; + std::size_t size() const override; + + bool isAbstract () const; + + private: + std::shared_ptr _data; + }; +} + +#endif // SOCKADDR_H diff --git a/zypp-core/zyppng/io/socket.cc b/zypp-core/zyppng/io/socket.cc new file mode 100644 index 0000000..1573d47 --- /dev/null +++ b/zypp-core/zyppng/io/socket.cc @@ -0,0 +1,892 @@ +#include "private/socket_p.h" +#include +#include +#include +#include +#include +#include +#include //For FIONREAD +#include +#include +#include + +#include + +namespace zyppng { + + SocketPrivate::ClosingState::ClosingState(IOBuffer &&writeBuffer) + : _writeBuffer( std::move(writeBuffer) ) + { } + + bool SocketPrivate::initSocket() + { + if ( _socket >= 0 ) + return true; + + _error = Socket::NoError; + _emittedErr = false; + + // Since Linux 2.6.27 we can pass additional flags with the type argument to avoid fcntl + // if creating sockets fails we might need to change that + _socket = eintrSafeCall( ::socket, _domain, _type | SOCK_NONBLOCK | SOCK_CLOEXEC, _protocol ); + if ( _socket >= 0 ) + return true; + + switch ( errno ) { + case EACCES: + setError( Socket::InsufficientPermissions, strerr_cxx() ); + break; + case EINVAL: + setError( Socket::InvalidSocketOptions, strerr_cxx() ); + break; + case EMFILE: + case ENFILE: + case ENOBUFS: + case ENOMEM: + setError( Socket::InsufficientRessources, strerr_cxx() ); + break; + case EAFNOSUPPORT: + case EPROTONOSUPPORT: + setError ( Socket::UnsupportedSocketOptions, strerr_cxx() ); + break; + default: + setError( Socket::UnknownSocketError, strerr_cxx() ); + break; + } + + return false; + } + + void SocketPrivate::setError( Socket::SocketError error , std::string &&err, bool emit ) + { + // we only remember the first error that happend + if ( _error == Socket::NoError && _error != error ) { + _emittedErr = emit; + _error = error; + _errorDesc = std::move(err); + } + if ( emit && !_emittedErr ) + _sigError.emit( error ); + } + + bool SocketPrivate::transition( Socket::SocketState newState ) + { + const auto oldState = state(); + + if ( oldState == newState ) + return true; + + switch ( newState ) { + case Socket::InitialState: + setError( Socket::InternalError, "Invalid state transition" ); + return false; + case Socket::ConnectingState: + if ( oldState != Socket::InitialState && oldState != Socket::ClosedState ) { + setError( Socket::InternalError, "Invalid state transition" ); + return false; + } + _state.emplace( ); + return connectToHost(); + break; + case Socket::ConnectedState: { + if ( oldState != Socket::InitialState && oldState != Socket::ConnectingState ) { + setError( Socket::InternalError, "Invalid state transition" ); + return false; + } + auto &s = _state.emplace(); + s._socketNotifier = SocketNotifier::create( _socket, SocketNotifier::Read | SocketNotifier::Error, true ); + s._socketNotifier->connect( &SocketNotifier::sigActivated, *this, &SocketPrivate::onSocketActivatedSlot ); + + z_func()->IODevice::open( IODevice::ReadOnly | IODevice::WriteOnly ); + + _connected.emit(); + break; + } + case Socket::ListeningState: { + if ( state() != Socket::InitialState ) { + setError( Socket::InternalError, "Invalid state transition" ); + return false; + } + auto &s = _state.emplace(); + s._socketNotifier = SocketNotifier::create( _socket, SocketNotifier::Read, true ); + s._socketNotifier->connect( &SocketNotifier::sigActivated, *this, &SocketPrivate::onSocketActivatedSlot ); + break; + } + case Socket::ClosingState: { + if ( state() != Socket::ConnectedState ) { + setError( Socket::InternalError, "Invalid state transition" ); + return false; + } + + auto wbOld = std::move( std::get(_state)._writeBuffer ); + auto &s = _state.emplace( std::move( wbOld ) ); + s._socketNotifier = SocketNotifier::create( _socket, SocketNotifier::Write, true ); + s._socketNotifier->connect( &SocketNotifier::sigActivated, *this, &SocketPrivate::onSocketActivatedSlot ); + break; + } + case Socket::ClosedState: { + _state.emplace(); + if ( z_func()->canRead() ) + z_func()->finishReadChannel( 0 ); + if ( _socket >= 0 && !_borrowedSocket ) + ::close( _socket ); + _socket = -1; + _targetAddr.reset(); + _disconnected.emit(); + z_func()->IODevice::close(); + break; + } + } + return true; + } + + bool SocketPrivate::connectToHost() + { + auto &state = std::get( _state ); + + const int res = eintrSafeCall( ::connect, _socket, _targetAddr->nativeSockAddr(), _targetAddr->size() ); + + auto doDelayedConnect = [ this, &state ](){ + if ( !state._connectNotifier ) { + state._connectNotifier = SocketNotifier::create( _socket, SocketNotifier::Write, true ); + state._connectNotifier->connect( &SocketNotifier::sigActivated, *this, &SocketPrivate::onSocketActivatedSlot ); + } + + if ( !state._connectTimeout ) { + state._connectTimeout = Timer::create(); + state._connectTimeout->connectFunc( &Timer::sigExpired, [this, &state ]( const auto &) { + setError( Socket::ConnectionTimeout, "The connection timed out." ); + state._connectNotifier.reset(); + state._connectTimeout.reset(); + }, *z_func()); + } + state._connectTimeout->setSingleShot( true ); + state._connectTimeout->start( 30000 ); + setError( Socket::ConnectionDelayed, "" ); + return false; + }; + + if ( res < 0 ) { + switch ( errno ) { + case EAGAIN: { + if ( _targetAddr->nativeSockAddr()->sa_family == AF_UNIX ) { + // the Servers backlog is full , we need to wait + return doDelayedConnect(); + } else { + setError( Socket::FailedSocketOperation, strerr_cxx() ); + z_func()->close(); + return false; + } + break; + } + case EINPROGRESS: + return doDelayedConnect(); + break; + + default: + if ( handleConnectError( errno ) == false ) { + z_func()->close(); + return false; + } + } + } + + // connected yay + if ( !transition( Socket::ConnectedState ) ) { + z_func()->close(); + return false; + } + return true; + } + + int64_t zyppng::SocketPrivate::rawBytesAvailable() const + { + if ( state() != Socket::ConnectedState ) + return 0; + + return zyppng::bytesAvailableOnFD( _socket ); + } + + bool SocketPrivate::readRawBytesToBuffer() + { + Z_Z(); + auto bytesToRead = rawBytesAvailable(); + if ( bytesToRead == 0 ) { + // make sure to check if bytes are available even if the ioctl call returns something different + bytesToRead = 4096; + } + + auto &readBuf = _readChannels[0]; + char *buf = readBuf.reserve( bytesToRead ); + const auto bytesRead = z_func()->readData( 0, buf, bytesToRead ); + + if ( bytesRead <= 0 ) { + readBuf.chop( bytesToRead ); + + switch ( bytesRead ) { + case -2: + // there is simply no data to read ignore and try again + return true; + case 0: { + // remote close + setError( Socket::ConnectionClosedByRemote, "The remote host closed the connection", true ); + break; + } + case -1: + default: { + setError( Socket::InternalError, strerr_cxx(), true ); + break; + } + } + z->abort(); + return false; + } + + if ( bytesToRead > bytesRead ) + readBuf.chop( bytesToRead-bytesRead ); + + _readyRead.emit(); + _channelReadyRead.emit(0); + return true; + } + + bool SocketPrivate::writePendingData() + { + return std::visit( [this]( auto &s ){ + using T = std::decay_t; + if constexpr ( std::is_same_v || std::is_same_v ) { + const auto nwrite = s._writeBuffer.frontSize(); + if ( !nwrite ) { + // disable Write notifications so we do not wake up without the need to + s._socketNotifier->setMode( SocketNotifier::Read | SocketNotifier::Error ); + return true; + } + + const auto nBuf = s._writeBuffer.front(); + const auto written = eintrSafeCall( ::send, _socket, nBuf, nwrite, MSG_NOSIGNAL ); + if ( written == -1 ) { + switch ( errno ) { + case EACCES: + setError( Socket::InsufficientPermissions, strerr_cxx() ); + return false; + case EAGAIN: +#if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: +#endif + return true; + case EPIPE: + case ECONNRESET: + setError( Socket::ConnectionClosedByRemote, strerr_cxx() ); + return false; + default: + setError( Socket::InternalError, strerr_cxx() ); + return false; + } + return false; + } + s._writeBuffer.discard( written ); + _sigBytesWritten.emit( written ); + if ( s._writeBuffer.size() == 0 ) + _sigAllBytesWritten.emit(); + } + return true; + }, _state ); + } + + /*! + * Maps \a error into a \ref Socket::SocketError and sets it accordingly in + * the socket. Returns false if the error is fatal and connection needs to stop. + */ + bool zyppng::SocketPrivate::handleConnectError( int error ) + { + switch ( error ) { + case EACCES: + case EPERM: + setError( Socket::InsufficientPermissions, strerr_cxx() ); + return false; + case EADDRINUSE: + setError( Socket::AddressInUse, strerr_cxx() ); + return false; + case EADDRNOTAVAIL: + setError( Socket::AddressNotAvailable, strerr_cxx() ); + return false; + case EAFNOSUPPORT: + setError( Socket::AddressIssue, strerr_cxx() ); + return false; + case ETIMEDOUT: + setError( Socket::ConnectionTimeout, strerr_cxx() ); + return false; + case EALREADY: + setError( Socket::ConnectionDelayed, "" ); + return false; + case ECONNREFUSED: + setError( Socket::ConnectionRefused, strerr_cxx() ); + return false; + case EBADF: + case EFAULT: + case ENOTSOCK: + setError( Socket::InternalError, strerr_cxx() ); // this can only happen if we screw up + return false; + case ENETUNREACH: + setError( Socket::NetworkUnreachable, strerr_cxx() ); + return false; + case EPROTOTYPE: + setError ( Socket::InvalidSocketOptions, strerr_cxx() ); + return false; + case EISCONN: + break; + } + return true; + } + + + void SocketPrivate::onSocketActivated( int ev ) + { + std::visit( [ this, &ev ] ( const auto &currState ) { + using T = std::decay_t; + if constexpr ( std::is_same() ) { + if ( (ev & SocketNotifier::Write) == SocketNotifier::Write ) { + if ( this->_targetAddr->nativeSockAddr()->sa_family == AF_UNIX ) { + // for AF_UNIX sockets we just call connect again + this->connectToHost(); + return; + } else { + + // for others we check with getsockopt as mentioned in connect(2) if the conn was successful + int err = 0; + socklen_t errSize = sizeof ( err ); + ::getsockopt( _socket, SOL_SOCKET, SO_ERROR, &err, &errSize ); + + if ( err == 0 || err == EISCONN ) { + transition( Socket::ConnectedState ); + } else { + if ( err == EINPROGRESS || err == EAGAIN || err == EALREADY ) + return; + handleConnectError( err ); + z_func()->abort(); + } + } + } + + } else if constexpr ( std::is_same() ) { + if ( (ev & SocketNotifier::Write) == SocketNotifier::Write ) { + if ( !writePendingData() ) { + z_func()->abort(); + return; + } + } + if ( (ev & SocketNotifier::Read) == SocketNotifier::Read ) { + if ( !readRawBytesToBuffer() ) { + z_func()->abort(); + return; + } + } + if ( (ev & SocketNotifier::Error) == SocketNotifier::Error ) { + return; + } + + } else if constexpr ( std::is_same() ) { + + if ( (ev & SocketNotifier::Write) == SocketNotifier::Write ) { + if ( !writePendingData() ) { + z_func()->abort(); + return; + + } + + if ( currState._writeBuffer.size() == 0 ) { + transition( Socket::ClosedState ); + } + } + + } else if constexpr ( std::is_same() ) { + + //signal that we have pending connections + _incomingConnection.emit(); + + } else { + DBG << "Unexpected state on socket activation" << std::endl; + } + },_state); + } + + Socket::SocketState SocketPrivate::state() const + { + return std::visit([]( const auto &s ) constexpr { return s.type(); }, _state ); + } + + Socket::Ptr SocketPrivate::wrapSocket(int fd, int domain, int type, int protocol, Socket::SocketState state) + { + // from here on the Socket instance owns the fd, no need to manually close it + // in case of error + auto sptr = Socket::create( domain, type, protocol ); + sptr->d_func()->_socket = fd; + + // make sure the socket is non blocking + if ( !sptr->setBlocking( false ) ) { + DBG << "Failed to unblock socket." << std::endl; + return nullptr; + } + + if( sptr->d_func()->transition( state ) ) + return sptr; + + return nullptr; + } + + ZYPP_IMPL_PRIVATE(Socket) + + Socket::Socket( int domain, int type, int protocol ) + : IODevice( *( new SocketPrivate( domain, type, protocol, *this ))) + { } + + int64_t Socket::rawBytesAvailable( uint channel ) const + { + if ( channel != 0 ) { + constexpr std::string_view msg("Socket does not support multiple read channels"); + ERR << msg << std::endl; + throw std::logic_error( msg.data() ); + } + return d_func()->rawBytesAvailable(); + } + + Socket::~Socket() + { + this->abort(); + } + + Socket::Ptr Socket::create( int domain, int type, int protocol ) + { + return Ptr( new Socket( domain, type, protocol ) ); + } + + bool Socket::bind( const std::shared_ptr &addr ) + { + Z_D(); + if ( !addr || !d->initSocket() ) + return false; + + int res = eintrSafeCall( ::bind, d->_socket, addr->nativeSockAddr(), addr->size() ); + if ( res >= 0) return true; + + switch ( errno ) { + case EACCES: + d->setError( Socket::InsufficientPermissions, strerr_cxx() ); + break; + case EADDRINUSE: + d->setError( Socket::AddressInUse, strerr_cxx() ); + break; + case EBADF: + case ENOTSOCK: + case EFAULT: + d->setError( Socket::InternalError, strerr_cxx() ); // this can only happen if we screw up + break; + case EINVAL: + d->setError( Socket::SocketAlreadyBound, strerr_cxx() ); + break; + case EADDRNOTAVAIL: + d->setError( Socket::AddressNotAvailable, strerr_cxx() ); + break; + case ELOOP: + case ENAMETOOLONG: + case ENOENT: + case ENOTDIR: + case EROFS: + d->setError( Socket::AddressIssue, strerr_cxx() ); + break; + case ENOMEM: + d->setError( Socket::InsufficientRessources, strerr_cxx() ); + break; + default: + d->setError( Socket::UnknownSocketError, strerr_cxx() ); + break; + } + + abort(); + return false; + } + + bool Socket::listen(int backlog) + { + Z_D(); + if ( !d->initSocket() ) + return false; + + int res = eintrSafeCall( ::listen, d->_socket, backlog ); + if ( res >= 0 ) { + d->transition( Socket::ListeningState ); + return true; + } + + switch ( errno ) { + + case EADDRINUSE: + d->setError( Socket::AddressInUse, strerr_cxx() ); + break; + case EBADF: + case ENOTSOCK: + d->setError( Socket::InternalError, strerr_cxx() ); // this can only happen if we screw up + break; + case EOPNOTSUPP: + d->setError( Socket::OperationNotSupported, strerr_cxx() ); + break; + + } + return false; + } + + Socket::Ptr Socket::accept() + { + Z_D(); + if ( d->_socket == -1 ) + return nullptr; + + //accept new pending connections + const auto res = eintrSafeCall( ::accept4, d->_socket, (struct sockaddr*)nullptr, (socklen_t *)nullptr, SOCK_CLOEXEC ); + if ( res < 0 ) { + switch ( errno ) { +#if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: +#endif + case EAGAIN: + case ECONNABORTED: + return nullptr; + break; + default: + d->setError( Socket::InternalError, strerr_cxx() ); + return nullptr; + } + } + + return SocketPrivate::wrapSocket( res, d->_domain, d->_type, d->_protocol, Socket::ConnectedState ); + } + + Socket::Ptr Socket::fromSocket( int fd, Socket::SocketState state ) + { + + int domain = 0; + socklen_t optlen = sizeof(domain); + int res = getsockopt( fd, SOL_SOCKET, SO_DOMAIN, &domain, &optlen ); + if ( res < 0 ) { + DBG << "Error querying socket domain: " << strerr_cxx() << std::endl; + ::close(fd); + return nullptr; + } + + int protocol = 0; + optlen = sizeof(protocol); + res = getsockopt( fd, SOL_SOCKET, SO_PROTOCOL, &protocol, &optlen ); + if ( res < 0 ) { + DBG << "Error querying socket protocol: " << strerr_cxx() << std::endl; + ::close(fd); + return nullptr; + } + + int type = 0; + optlen = sizeof(type); + res = getsockopt( fd, SOL_SOCKET, SO_TYPE, &type, &optlen ); + if ( res < 0 ) { + DBG << "Error querying socket type: " << strerr_cxx() << std::endl; + ::close(fd); + return nullptr; + } + + return SocketPrivate::wrapSocket( fd, domain, type, protocol, state ); + } + + bool Socket::setBlocking( const bool set ) + { + Z_D(); + + if ( !d->initSocket() ) + return false; + + const int oldFlags = fcntl( d->_socket, F_GETFL, 0 ); + if (oldFlags == -1) return false; + + const int flags = set ? ( oldFlags & ~(O_NONBLOCK) ) : ( oldFlags | O_NONBLOCK ); + + // no need to do a syscall if we do not change anything + if ( flags == oldFlags ) + return true; + + if ( fcntl( d->_socket, F_SETFL, flags ) != 0) { + return false; + } + return true; + } + + bool Socket::connect( std::shared_ptr addr ) + { + Z_D(); + + if ( !addr || ( d->state() != Socket::InitialState && d->state() != Socket::ClosedState ) ) + return false; + + if ( !d->initSocket() ) + return false; + + d->_targetAddr = std::move(addr); + if ( !d->transition( Socket::ConnectingState ) ) { + abort(); + return false; + } + + return d->state() == Socket::ConnectedState; + } + + int Socket::nativeSocket() const + { + Z_D(); + return d->_socket; + } + + int Socket::releaseSocket() + { + Z_D(); + auto sock = d->_socket; + d->_socket = -1; + d->transition( Socket::ClosedState ); + return sock; + } + + Socket::SocketError Socket::lastError() const + { + Z_D(); + return d->_error; + } + + void Socket::abort() + { + Z_D(); + d->transition( ClosedState ); + } + + void Socket::close() + { + disconnect(); + } + + void Socket::disconnect() + { + Z_D(); + std::visit([&d]( const auto &s ){ + using Type = std::decay_t; + if constexpr ( std::is_same_v ) { + // we still have pending data, we need to wait for it to be written + if ( s._writeBuffer.size() ) { + d->transition( Socket::ClosingState ); + return; + } + } + d->transition( Socket::ClosedState ); + }, d->_state ); + + } + + int64_t Socket::writeData( const char *data, int64_t count ) + { + Z_D(); + if ( d->state() != SocketState::ConnectedState ) + return 0; + + auto &s = std::get( d->_state ); + + // if the write buffer has already data we need to append to it to keep the correct order + if ( s._writeBuffer.size() ) { + s._writeBuffer.append( data, count ); + //lets try to write some of it + d->writePendingData(); + return count; + } + + auto written = eintrSafeCall( ::send, d->_socket, data, count, MSG_NOSIGNAL ); + if ( written == -1 ) { + switch ( errno ) { +#if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: +#endif + case EAGAIN: { + written = 0; + break; + } + case EPIPE: + case ECONNRESET: { + d->setError( Socket::ConnectionClosedByRemote, strerr_cxx( errno ) ); + return -1; + } + default: { + d->setError( Socket::UnknownSocketError, strerr_cxx( errno ) ); + return -1; + } + } + } + + if ( written >= 0 ) { + if ( written < count ) { + // append the rest of the data to the buffer, so we can return always the full count + s._writeBuffer.append( data + written, count - written ); + s._socketNotifier->setMode( SocketNotifier::Read | SocketNotifier::Write | SocketNotifier::Error ); + } + if ( written > 0 ) + d->_sigBytesWritten.emit( written ); + } + + if ( s._writeBuffer.size() == 0 ) + d->_sigAllBytesWritten.emit(); + + return count; + } + + bool Socket::waitForConnected( int timeout ) + { + Z_D(); + if ( d->state() == Socket::ConnectedState ) + return true; + // we can only wait if we are in connecting state + while ( d->state() == Socket::ConnectingState ) { + int rEvents = 0; + if ( EventDispatcher::waitForFdEvent( d->_socket, AbstractEventSource::Write, rEvents, timeout ) ) { + d->onSocketActivated( rEvents ); + } else { + // timeout + return false; + } + } + return d->state() == Socket::ConnectedState; + } + + bool Socket::waitForAllBytesWritten( int timeout ) + { + Z_D(); + + bool canContinue = true; + bool bufferEmpty = false; + + while ( canContinue && !bufferEmpty ) { + + if ( d->state() != Socket::ConnectedState && d->state() != Socket::ClosingState) + return false; + + std::visit([&]( const auto &s ){ + using T = std::decay_t; + if constexpr ( std::is_same_v || std::is_same_v ) { + if ( s._writeBuffer.size() > 0 ) { + int rEvents = 0; + canContinue = EventDispatcher::waitForFdEvent( d->_socket, AbstractEventSource::Write | AbstractEventSource::Read, rEvents, timeout ); + if ( canContinue ) { + //this will trigger the bytesWritten signal, we check there if the buffer is empty + d->onSocketActivated( rEvents ); + } + } + if ( s._writeBuffer.size() == 0 ){ + canContinue = false; + bufferEmpty = true; + } + } + }, d->_state ); + } + return bufferEmpty; + } + + bool Socket::waitForReadyRead( uint channel, int timeout) + { + Z_D(); + if ( d->state() != Socket::ConnectedState || channel != 0 ) + return false; + + // we can only wait if we are in connected state + while ( d->state() == Socket::ConnectedState && bytesAvailable() <= 0 ) { + int rEvents = 0; + if ( EventDispatcher::waitForFdEvent( d->_socket, AbstractEventSource::Read | AbstractEventSource::Error , rEvents, timeout ) ) { + d->onSocketActivated( rEvents ); + } else { + //timeout + return false; + } + } + return bytesAvailable() > 0; + } + + int64_t Socket::readData( uint channel, char *buffer, int64_t bufsize ) + { + if ( channel != 0 ) { + constexpr std::string_view msg("Socket does not support multiple read channels"); + ERR << msg << std::endl; + throw std::logic_error( msg.data() ); + } + + Z_D(); + if ( d->state() != SocketState::ConnectedState ) + return -1; + + const auto read = eintrSafeCall( ::read, d->_socket, buffer, bufsize ); + + // special case for remote close + if ( read == 0 ) { + d->setError( ConnectionClosedByRemote, "The remote host closed the connection", false ); + return 0; + } else if ( read < 0 ) { + switch ( errno ) { +#if EAGAIN != EWOULDBLOCK + case EWOULDBLOCK: +#endif + case EAGAIN: { + return -2; + } + default: { + d->setError( UnknownSocketError, strerr_cxx( errno ), false ); + return -1; + } + } + } + return read; + } + + void Socket::readChannelChanged ( uint channel ) + { + if ( channel != 0 ) { + constexpr std::string_view msg("Changing the readChannel on a Socket is not supported"); + ERR << msg << std::endl; + throw std::logic_error( msg.data() ); + } + } + + int64_t Socket::bytesPending() const + { + Z_D(); + return std::visit([&]( const auto &s ) -> int64_t { + using T = std::decay_t; + if constexpr ( std::is_same_v || std::is_same_v ) { + return s._writeBuffer.size(); + } + return 0; + }, d->_state ); + } + + Socket::SocketState Socket::state() const + { + return d_func()->state(); + } + + SignalProxy Socket::sigIncomingConnection() + { + return d_func()->_incomingConnection; + } + + SignalProxy Socket::sigConnected() + { + return d_func()->_connected; + } + + SignalProxy Socket::sigDisconnected() + { + return d_func()->_disconnected; + } + + SignalProxy Socket::sigError() + { + return d_func()->_sigError; + } + +} diff --git a/zypp-core/zyppng/io/socket.h b/zypp-core/zyppng/io/socket.h new file mode 100644 index 0000000..e683de2 --- /dev/null +++ b/zypp-core/zyppng/io/socket.h @@ -0,0 +1,230 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPPNG_IO_SOCKET_DEFINED +#define ZYPPNG_IO_SOCKET_DEFINED + +#include +#include +#include + +namespace zyppng { + + class SocketPrivate; + + /*! + * Combines Sockets with the zypp event loop. Generally every socket type that is supported + * by the socket(2) API should work, however currently only Unix Domain sockets are tested. + * + * The useage pattern of this class is similar to the socket(2) API, on the server endpoint + * one listening socket is created and bound to a adress to accept incoming connections. + * For every appected connections a connected socket instance is returned which can be used for communication with the peer. + * + */ + class Socket : public IODevice + { + ZYPP_DECLARE_PRIVATE(Socket); + public: + + enum SocketError { + NoError, + UnknownSocketError, + InsufficientPermissions, + InvalidSocketOptions, + InsufficientRessources, + UnsupportedSocketOptions, + FailedSocketOperation, + SocketAlreadyBound, + SocketNotListening, + AddressInUse, + AddressNotAvailable, + AddressIssue, + OperationNotSupported, + ConnectionTimeout, + ConnectionDelayed, + ConnectionRefused, + ConnectionClosedByRemote, + NetworkUnreachable, + InternalError + }; + + enum SocketState { + InitialState, + ConnectingState, + ConnectedState, + ListeningState, + ClosingState, + ClosedState + }; + + using Ptr = std::shared_ptr; + + /*! + * Creates a new socket with the given \a doman , \a type and \a protocol. + * See socket(2) for available arguments. + * + * \note currently only AF_UNIX, SOCK_STREAM sockets are tested + */ + static Ptr create ( int domain, int type, int protocol ); + ~Socket() override; + + /*! + * Closed the socket and disconnects from the peer. + * The \a disconnected signal will be emitted. + * This is similar to calling \ref disconnect. + */ + void close() override; + + /*! + * Returns the current number of bytes that are not yet written to the socket. + */ + int64_t bytesPending() const override; + + /*! + * Returns the current state the socket is in, + * check \ref SocketState for possible values. + */ + SocketState state () const; + + /*! + * Bind the socket to a local address, this is usually required to listen for incoming connections. + */ + bool bind ( const std::shared_ptr &addr ); + + /*! + * Puts the socket in listen mode, the state is set accordingly. + */ + bool listen ( int backlog = 50 ); + + /*! + * Accepts a pending incoming connection and returns it as a + * intialized connected socket. + * Returns nullptr if there is no pending connection. + */ + Ptr accept (); + + /*! + * This will set the socket into blocking mode. Can be used if there is no + * EventLoop running. (Make sure a EventDispatcher instance exists for the thread) + */ + bool setBlocking ( const bool set = true ); + + + /*! + * Starts to disconnect from the host, wait for the actual + * \ref sigDisconnected signal to arrive before destroying the socket + * otherwise the connection is forcefully aborted + */ + void disconnect (); + + /*! + * Forcefully aborts the connection, no matter if there is still data to be written + * in the write buffer + */ + void abort (); + + /*! + * Starts the connection process to the given adress in \a addr. + * Returns true on success, if false is returned the current state should be + * checked if the connection was simply delayed. In that case the state is \ref ConnectingState + * and error is set to \ref ConnectionDelayed and the socket still tries to connect. + */ + bool connect ( std::shared_ptr addr ); + + /*! + * Blocks the current event loop to wait for the connected event on the socket. + * \note do not use until there is no other way + */ + bool waitForConnected ( int timeout = -1 ); + + /*! + * Blocks the current event loop to wait until all bytes from the buffer have been written + * to the device. + * + * \note do not use until there is no other way + */ + bool waitForAllBytesWritten ( int timeout = -1 ); + + /*! + * Blocks the current event loop to wait until there are bytes available to read from the device + * + * \note do not use until there is no other way + */ + bool waitForReadyRead ( uint channel, int timeout = -1 ) override; + + /*! + * Returns the native socket handle. + */ + int nativeSocket () const; + + /*! + * This will release the current socket and instantly transition into + * ClosedState. All unwritten data in the buffers will be discarded, + * so consider to use \ref waitForAllBytesWritten before you call this function. + * + * \returns the socket or -1 if there was no socket connected + */ + int releaseSocket (); + + /*! + * Return the last error that was encountered by the socket. + */ + SocketError lastError () const; + + /*! + * Signals when there are new incoming connection pending. + * \note Make sure to accept all connection otherwise the event loop keeps triggering that signal + */ + SignalProxy sigIncomingConnection (); + + /*! + * Signal is emitted as soon as the socket enters the connected state. It is not possible to + * read and write data. + */ + SignalProxy sigConnected (); + + /*! + * Signal is emitted always when the socket was closed. In the signal handler it is still possible + * to read all pending data in the read buffer, which will be discarded right after emitting the signal. + * \note when the socket should be deleted in a slot connected to this signal make sure + * to delay the delete using the EventDispatcher. + */ + SignalProxy sigDisconnected (); + + /*! + * Signal is emitted whenever a error happend in the socket. Make sure to check + * the actual error code to determine if the error is fatal. + */ + SignalProxy sigError (); + + + /*! + * Makes a socket instance out of a existing socket file descriptor, + * the instance takes ownership of the fd + */ + static Ptr fromSocket ( int fd, SocketState state ); + + protected: + Socket ( int domain, int type, int protocol ); + + + // IODevice interface + protected: + int64_t rawBytesAvailable( uint channel = 0 ) const override; + int64_t writeData(const char *data, int64_t count) override; + int64_t readData( uint channel, char *buffer, int64_t bufsize ) override; + void readChannelChanged ( uint channel ) override; + }; +} +#endif diff --git a/zypp-core/zyppng/meta/FunctionTraits b/zypp-core/zyppng/meta/FunctionTraits new file mode 100644 index 0000000..9ca6429 --- /dev/null +++ b/zypp-core/zyppng/meta/FunctionTraits @@ -0,0 +1 @@ +#include "function_traits.h" diff --git a/zypp-core/zyppng/meta/Functional b/zypp-core/zyppng/meta/Functional new file mode 100644 index 0000000..e910f69 --- /dev/null +++ b/zypp-core/zyppng/meta/Functional @@ -0,0 +1 @@ +#include "functional.h" diff --git a/zypp-core/zyppng/meta/TypeTraits b/zypp-core/zyppng/meta/TypeTraits new file mode 100644 index 0000000..a7648c8 --- /dev/null +++ b/zypp-core/zyppng/meta/TypeTraits @@ -0,0 +1 @@ +#include "type_traits.h" diff --git a/zypp-core/zyppng/meta/function_traits.h b/zypp-core/zyppng/meta/function_traits.h new file mode 100644 index 0000000..be84530 --- /dev/null +++ b/zypp-core/zyppng/meta/function_traits.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +* //Code based on a blogpost on https://functionalcpp.wordpress.com/2013/08/05/function-traits/ +* +*/ +#ifndef ZYPPNG_META_FUNCTION_TRAITS_H_INCLUDED +#define ZYPPNG_META_FUNCTION_TRAITS_H_INCLUDED + +#include +#include +#include + +namespace zyppng { + +template +struct function_traits; + +template +struct function_traits +{ + using return_type = R; + + static constexpr std::size_t arity = sizeof...(Args); + + template + struct argument + { + static_assert(N >= 0 && N < arity, "error: invalid parameter index."); + using type = typename std::tuple_element>::type; + }; +}; + +// function pointer +template +struct function_traits : public function_traits +{ }; + +// function ref +template +struct function_traits : public function_traits +{ }; + +// member function pointer +template +struct function_traits : public function_traits +{}; + +// const member function pointer, this will match lambdas too +template +struct function_traits : public function_traits +{}; + +// member object pointer +template +struct function_traits : public function_traits +{}; + +template +using has_call_operator = decltype (&T::operator()); + +//functor with one overload +template +struct function_traits> : public function_traits +{}; + +} +#endif diff --git a/zypp-core/zyppng/meta/functional.h b/zypp-core/zyppng/meta/functional.h new file mode 100644 index 0000000..e2aa6df --- /dev/null +++ b/zypp-core/zyppng/meta/functional.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_META_FUNCTIONAL_H_INCLUDED +#define ZYPPNG_META_FUNCTIONAL_H_INCLUDED + +#include + +#if __cplusplus <= 201402L || !defined ( __cpp_lib_invoke ) + +#include + +// this is a workaround for std::invoke not being available in C++14 +// and the proposed minimal implementation in +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4169.html + +namespace std { + template + typename std::enable_if< + std::is_member_pointer::type>::value, + typename std::result_of::type + >::type invoke(Functor&& f, Args&&... args) + { + return std::mem_fn(f)(std::forward(args)...); + } + + template + typename std::enable_if< + !std::is_member_pointer::type>::value, + typename std::result_of::type + >::type invoke(Functor&& f, Args&&... args) + { + return std::forward(f)(std::forward(args)...); + } +} + +#endif + +/*! + * Simple helper template to make a callback that binds the "this" pointer, to be used in + * a pipeline. + */ +template +auto mem_fn_cb( Obj& o, Ret (Obj::*objMemFunc)( Arg&& ) ) { + return [tPtr = &o, fun = objMemFunc ]( Arg &&r ){ + return std::invoke(fun, tPtr, std::move(r) ); + }; +} + +template +auto mem_fn_cb( Obj& o, Ret (Obj::*objMemFunc)( const Arg& ) ) { + return [tPtr = &o, fun = objMemFunc ]( const Arg &r ){ + return std::invoke(fun, tPtr, r ); + }; +} + +template +auto mem_fn_cb( Obj& o, Ret (Obj::*objMemFunc)( Arg ) ) { + return [tPtr = &o, fun = objMemFunc ]( Arg r ){ + if constexpr ( std::is_invocable_v< decltype (fun), Obj*, Arg&&> ) { + return std::invoke(fun, tPtr, std::move(r) ); + } else { + return std::invoke(fun, tPtr, r ); + } + }; +} + + +#endif diff --git a/zypp-core/zyppng/meta/type_traits.h b/zypp-core/zyppng/meta/type_traits.h new file mode 100644 index 0000000..f98a994 --- /dev/null +++ b/zypp-core/zyppng/meta/type_traits.h @@ -0,0 +1,135 @@ +#ifndef ZYPPNG_META_TYPE_TRAITS_INCLUDED +#define ZYPPNG_META_TYPE_TRAITS_INCLUDED + +#include +#include + +#if !defined ( __cpp_lib_void_t ) + +namespace std { + //define void_t since it is only available starting with C++17 in some compilers + template struct make_void { typedef void type;}; + template using void_t = typename make_void::type; +} + +#endif + +namespace std { + +#if __cplusplus < 202002L + +//implementation of the detector idiom, used to help with SFINAE +//from https://en.cppreference.com/w/cpp/experimental/is_detected + +namespace detail { +template class Op, class... Args> +struct detector { + using value_t = std::false_type; + using type = Default; +}; + +template class Op, class... Args> +struct detector>, Op, Args...> { + using value_t = std::true_type; + using type = Op; +}; + +struct nonesuch{ + ~nonesuch( ) = delete; + nonesuch( nonesuch const& ) = delete; + void operator = ( nonesuch const& ) = delete; +}; + +} // namespace detail + +template using bool_constant = integral_constant; + +template class Op, class... Args> +using is_detected = typename detail::detector::value_t; + +template class Op, class... Args> +using detected_t = typename detail::detector::type; + +template class Op, class... Args> +using detected_or = detail::detector; + +template< template class Op, class... Args > +constexpr bool is_detected_v = is_detected::value; + +template< class Default, template class Op, class... Args > +using detected_or_t = typename detected_or::type; + +template class Op, class... Args> +using is_detected_exact = std::is_same>; + +template class Op, class... Args> +constexpr bool is_detected_exact_v = is_detected_exact::value; + +template class Op, class... Args> +using is_detected_convertible = std::is_convertible, To>; + +template class Op, class... Args> +constexpr bool is_detected_convertible_v = is_detected_convertible::value_t::value; + +template< class T > +struct remove_cvref { + using type = std::remove_cv_t>; +}; + +template< class T > +using remove_cvref_t = typename remove_cvref::type; + +#endif + +#if __cplusplus < 201703L + +//https://en.cppreference.com/w/cpp/types/conjunction) +template struct conjunction : std::true_type { }; +template struct conjunction : B1 { }; +template +struct conjunction + : std::conditional_t, B1> {}; + +//https://en.cppreference.com/w/cpp/types/disjunction +template struct disjunction : std::false_type { }; +template struct disjunction : B1 { }; +template +struct disjunction + : std::conditional_t> { }; + +//https://en.cppreference.com/w/cpp/types/negation +template +struct negation : std::bool_constant< !bool(B::value)> { }; + +#endif +} + + +namespace zyppng { + //check wether something is a instance of a template type + template < template< class ... > class Templ, class Type > + struct is_instance_of : std::false_type{}; + + template < template< typename ... > class Templ, typename... Args > + struct is_instance_of> : std::true_type{}; + + //Provides the member typedef type which is the type pointed to by T, or, if T is not a pointer, then type is the same as T. + template< typename T> + struct remove_smart_ptr{ using type = std::remove_cv_t; }; + + template< typename T> + struct remove_smart_ptr>{ using type = std::remove_cv_t; }; + + template< typename T> + struct remove_smart_ptr>{ using type = std::remove_cv_t; }; + + template< typename T> + using remove_smart_ptr_t = typename remove_smart_ptr::type; + + //helper template to print type parameters + template + class myerror_t; +} + +#endif diff --git a/zypp-core/zyppng/pipelines/Algorithm b/zypp-core/zyppng/pipelines/Algorithm new file mode 100644 index 0000000..d895867 --- /dev/null +++ b/zypp-core/zyppng/pipelines/Algorithm @@ -0,0 +1 @@ +#include "algorithm.h" diff --git a/zypp-core/zyppng/pipelines/AsyncResult b/zypp-core/zyppng/pipelines/AsyncResult new file mode 100644 index 0000000..f18a9f5 --- /dev/null +++ b/zypp-core/zyppng/pipelines/AsyncResult @@ -0,0 +1 @@ +#include "asyncresult.h" diff --git a/zypp-core/zyppng/pipelines/Await b/zypp-core/zyppng/pipelines/Await new file mode 100644 index 0000000..e810934 --- /dev/null +++ b/zypp-core/zyppng/pipelines/Await @@ -0,0 +1 @@ +#include "await.h" diff --git a/zypp-core/zyppng/pipelines/Expected b/zypp-core/zyppng/pipelines/Expected new file mode 100644 index 0000000..88660ed --- /dev/null +++ b/zypp-core/zyppng/pipelines/Expected @@ -0,0 +1 @@ +#include "expected.h" diff --git a/zypp-core/zyppng/pipelines/Lift b/zypp-core/zyppng/pipelines/Lift new file mode 100644 index 0000000..21b7993 --- /dev/null +++ b/zypp-core/zyppng/pipelines/Lift @@ -0,0 +1 @@ +#include "lift.h" diff --git a/zypp-core/zyppng/pipelines/MTry b/zypp-core/zyppng/pipelines/MTry new file mode 100644 index 0000000..dd9e772 --- /dev/null +++ b/zypp-core/zyppng/pipelines/MTry @@ -0,0 +1 @@ +#include "mtry.h" diff --git a/zypp-core/zyppng/pipelines/Redo b/zypp-core/zyppng/pipelines/Redo new file mode 100644 index 0000000..373b4f9 --- /dev/null +++ b/zypp-core/zyppng/pipelines/Redo @@ -0,0 +1 @@ +#include "redo.h" diff --git a/zypp-core/zyppng/pipelines/Transform b/zypp-core/zyppng/pipelines/Transform new file mode 100644 index 0000000..070a973 --- /dev/null +++ b/zypp-core/zyppng/pipelines/Transform @@ -0,0 +1 @@ +#include "transform.h" diff --git a/zypp-core/zyppng/pipelines/Wait b/zypp-core/zyppng/pipelines/Wait new file mode 100644 index 0000000..bc9e384 --- /dev/null +++ b/zypp-core/zyppng/pipelines/Wait @@ -0,0 +1 @@ +#include "wait.h" diff --git a/zypp-core/zyppng/pipelines/algorithm.h b/zypp-core/zyppng/pipelines/algorithm.h new file mode 100644 index 0000000..6286057 --- /dev/null +++ b/zypp-core/zyppng/pipelines/algorithm.h @@ -0,0 +1,223 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_PIPELINES_ALGORITHM_H_INCLUDED +#define ZYPPNG_PIPELINES_ALGORITHM_H_INCLUDED + +#include +#include + +namespace zyppng { + + namespace detail { + + struct ContinueUntilValidPredicate { + template< class Arg > + bool operator()( const Arg &value ) { + // works if operator bool() const is implemented by type Arg + if ( value ) return true; + return false; + } + }; + + template + struct showme; + + template < class Container, class AsyncResType, class Transformation, class Predicate, class DefaultType > + struct AsyncFirstOfImpl : public AsyncOp { + + AsyncFirstOfImpl( Container &&inData, Transformation &&transFunc, DefaultType &&defaultVal, Predicate &&predicate ) + : _inData ( std::move(inData) ) + , _transFunc ( std::move(transFunc) ) + , _defaultVal( std::move(defaultVal) ) + , _predicate ( std::move(predicate)) + , _currIter ( _inData.begin() ) { execute(); } + + private: + void execute() { + // seems this is empty we are ready + if ( _currIter == _inData.end() ) { + return returnDefault(); + } + invokeCurrent(); + } + + void resultReady ( AsyncResType &&res ) { + + if ( !_predicate(res) ) { + _currIter = std::next( _currIter ); + // seems we reached the end + if ( _currIter == _inData.end() ) { + return returnDefault(); + } + invokeCurrent(); + } else { + this->setReady ( std::move(res) ); + return; + } + + } + + void invokeCurrent() { + _currentPipeline = std::invoke( _transFunc, std::move( *_currIter ) ); + _currentPipeline->onReady( [ this ]( AsyncResType &&res ) { + this->resultReady( std::move(res)); + }); + } + void returnDefault() { + this->setReady ( std::move(_defaultVal) ); + return; + } + + private: + Container _inData; + Transformation _transFunc; + DefaultType _defaultVal; + Predicate _predicate; + typename Container::iterator _currIter; + AsyncOpRef _currentPipeline; + }; + + template < class Transformation, class Predicate, class DefaultType > + struct FirstOfHelper { + + FirstOfHelper( Transformation transFunc, DefaultType defaultVal, Predicate predicate ) + : _transFunc ( std::move(transFunc) ) + , _defaultVal( std::move(defaultVal) ) + , _predicate ( std::move(predicate)) { } + + template < class Container + , typename ...CArgs> + auto operator()( Container &&container ) { + + using InputType = typename Container::value_type; + static_assert( std::is_invocable_v, "Transformation function must take the container value type as input " ); + static_assert( std::is_rvalue_reference_v(container))>, "Input container must be a rvalue reference" ); + + using OutputType = std::invoke_result_t; + + if constexpr ( detail::is_async_op_v ) { + + using AsyncResultType = typename remove_smart_ptr_t::value_type; + + static_assert( std::is_same_v, "Default type and transformation result type must match" ); + + using ImplType = AsyncFirstOfImpl; + return static_cast>( std::make_shared( std::forward(container), std::move(_transFunc), std::move(_defaultVal), std::move(_predicate) ) ); + + } else { + + static_assert( std::is_same_v, "Default type and transformation result type must match" ); + + for ( auto &in : std::forward(container) ) { + OutputType res = std::invoke( _transFunc, std::move(in) ); + if ( _predicate(res) ) { + return res; + } + } + return _defaultVal; + } + } + + private: + Transformation _transFunc; + DefaultType _defaultVal; + Predicate _predicate; + }; + + } + + /*! + * Provide a dummy error type for when there is no entry found + */ + class NotFoundException : public zypp::Exception { + public: + NotFoundException() : zypp::Exception("No Entry found"){} + }; + + template < class Transformation, class DefaultType, class Predicate > + inline auto firstOf( Transformation &&transformFunc, DefaultType &&def, Predicate &&predicate = detail::ContinueUntilValidPredicate() ) { + return detail::FirstOfHelper ( std::forward(transformFunc), std::forward(def), std::forward(predicate) ); + } + + namespace detail { + + template + bool containsOneOfExceptionImpl( const std::exception_ptr &exceptionPtr ) { + try { + if constexpr ( sizeof...(Rest) == 0 ) { + // on the lowest level we throw the exception + std::rethrow_exception ( exceptionPtr ); + } else { + return containsOneOfExceptionImpl(exceptionPtr); + } + } catch ( const Excpt &e ) { + return true; + } + } + + } + + /*! + * Checks if a given std::exception_ptr contains one of the given exception types + * in the template arguments: + * + * \code + * + * expected result = someFuncReturningExpected(); + * if ( !result && containsOneOfException( result.error() ) ) { + * std::cout << "Contains either zypp::FileNotFoundException or SomeOtherException" << std::endl; + * } + * + * \endcode + * + * Detects exceptions by throwing and catching them, so always pass the specific exception types to check for.. + */ + template + bool containsOneOfException( const std::exception_ptr &exceptionPtr ) { + try { + return detail::containsOneOfExceptionImpl( exceptionPtr ); + } catch ( ... ) {} + return false; + } + + /*! + * Checks if a given std::exception_ptr contains the given exception type + * in the template type argument: + * + * \code + * + * expected result = someFuncReturningExpected(); + * if ( !result && containsException( result.error() ) ) { + * std::cout << "Contains zypp::FileNotFoundException" << std::endl; + * } + * + * \endcode + */ + template + bool containsException( const std::exception_ptr &exceptionPtr ) { + try { + std::rethrow_exception ( exceptionPtr );; + } catch ( const Excpt &e ) { + return true; + } catch ( ... ) {} + return false; + } + + +} + + + + +#endif diff --git a/zypp-core/zyppng/pipelines/asyncresult.h b/zypp-core/zyppng/pipelines/asyncresult.h new file mode 100644 index 0000000..7a3cd4a --- /dev/null +++ b/zypp-core/zyppng/pipelines/asyncresult.h @@ -0,0 +1,343 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_MONADIC_ASYNCRESULT_H_INCLUDED +#define ZYPPNG_MONADIC_ASYNCRESULT_H_INCLUDED + +#include +#include +#include +#include + +namespace zyppng { + + + namespace detail { + + template< typename Callback, typename MsgType, typename = std::void_t<> > + struct is_future_monad_cb : public std::false_type{}; + + template< typename Callback, typename MsgType > + struct is_future_monad_cb >, + decltype ( std::declval>()( std::declval()) )//check if the callback has a operator() member with the correct signature + > + > : public std::true_type{}; + + /*! + * Checks if a Callable object is of type async_op and if + * it accepts the given MsgType and returns the expected type + */ + template< typename Callback, typename MsgType > + constexpr bool is_future_monad_cb_v = is_future_monad_cb::value; + + template< typename Callback, typename MsgType, typename = std::void_t<> > + struct is_sync_monad_cb : public std::false_type{}; + + template< typename Callback, typename MsgType > + struct is_sync_monad_cb >, + std::enable_if_t< !std::is_same_v< void, decltype ( std::declval()(std::declval())) > > > //check if the callback has the correct signature: cb( MsgType ) + > : public std::true_type{}; + + /*! + * Checks if a Callable object is a syncronous callback type with the expected signature + */ + template< typename Callback, typename MsgType, typename = std::void_t<> > + constexpr bool is_sync_monad_cb_v = is_sync_monad_cb::value; + + + template + using callback_returns_async_op = is_async_op< std::invoke_result_t>; + + + template< typename Callback, typename MsgType, typename = std::void_t<> > + struct is_sync_monad_cb_with_async_res : public std::false_type{}; + + template< typename Callback, typename MsgType > + struct is_sync_monad_cb_with_async_res::value >, + std::enable_if_t< callback_returns_async_op::value >> + > : public std::true_type{}; + + template< typename Callback, typename MsgType, typename = std::void_t<> > + struct is_sync_monad_cb_with_sync_res : public std::false_type{}; + + template< typename Callback, typename MsgType > + struct is_sync_monad_cb_with_sync_res::value >, + std::enable_if_t< !callback_returns_async_op::value > > + > : public std::true_type{}; + + /*! + * Checks if a Callable object is a syncronous callback type with the expected signature + */ + template + constexpr bool is_sync_monad_cb_with_async_res_v = is_sync_monad_cb_with_async_res::value; + + /*! + * Checks if the given Callback is a function returning a syncronous result + */ + template + constexpr bool is_sync_monad_cb_with_sync_res_v = is_sync_monad_cb_with_sync_res::value; + + + /*! + * The AsyncResult class is used to bind previous operations to a new operation and to carry + * the result of the full pipeline. It has a pointer to the _prevTask, which is usually + * a AsyncResult too, and to the task it should execute once the previous task enters ready state. + * + * In theory this is a single linked list, but each node owns all the previous nodes, means that once + * a node is destroyed all previous ones are destroyed as well. Basically the async results are nested objects, where + * the outermost object is the last to be executed. While executing the nodes they are cleaned up right away + * after they enter finished or ready state. + * + * When returned to the code the AsyncResult is casted into the AsyncOp base class, otherwise the type + * information gets too complex and matching the pipe operator functions is a nightmare. This could be revisited + * with newer C++ versions. + * + * \todo with newer C++ versions revisit the possibility to use non shared ptr types throughout the pipeline instead of + * the current smart pointer solution. + */ + //template + //struct AsyncResult; + + template + struct is_nested_async : public std::false_type {}; + + template + struct is_nested_async>> : public std::true_type {}; + + template + constexpr bool is_nested_async_v = is_nested_async::value; + + + // case 1: connect async result to async callback + template + struct AsyncToAsyncResult : public zyppng::AsyncOp< AOpRes > { + + static_assert( !is_async_op_v, "A AsyncResult can never return a async value" ); + static_assert( !is_async_op_v, "A incoming value can never be a async value" ); + + AsyncToAsyncResult ( AsyncOpRef && prevTask, std::shared_ptr &&cb ) + : _prevTask( std::move(prevTask) ) + , _myTask( std::move(cb) ) { + connect(); + } + + AsyncToAsyncResult ( const AsyncToAsyncResult &other ) = delete; + AsyncToAsyncResult& operator= ( const AsyncToAsyncResult &other ) = delete; + + AsyncToAsyncResult ( AsyncToAsyncResult &&other ) = delete; + AsyncToAsyncResult& operator= ( AsyncToAsyncResult &&other ) = delete; + + virtual ~AsyncToAsyncResult() {} + + void connect () { + //not using a lambda here on purpose, binding this into a lambda that is stored in the _prev + //object causes segfaults on gcc when the lambda is cleaned up with the _prev objects signal instance + _prevTask->onReady( std::bind( &AsyncToAsyncResult::readyWasCalled, this, std::placeholders::_1) ); + _myTask->onReady( [this] ( AOpRes && res ){ + this->setReady( std::move( res ) ); + }); + } + + private: + // we need to store the passed argument in our stack, otherwise we + // run into memory issues if the argument is moved out of the _prevTask object + // so even though we std::move() the argument further we need to copy it here + void readyWasCalled ( PrevRes res ) { + //MIL << "Setting ready: " << typeid(this) << std::endl; + if ( _prevTask ) { + //dumpInfo(); + _prevTask.reset(); + } + + _myTask->operator()(std::move(res)); + } + + AsyncOpRef _prevTask; + std::shared_ptr _myTask; + }; + + template + struct AsyncToSyncResult; + + // case 2: connect async result to sync callback returning a sync value + template + struct AsyncToSyncResult >> + : public zyppng::AsyncOp< typename std::invoke_result_t > { + + using value_type = std::invoke_result_t; + static_assert( !is_async_op_v, "A AsyncResult can never return a async value" ); + static_assert( !is_async_op_v, "A incoming value can never be a async value" ); + + template + AsyncToSyncResult ( AsyncOpRef && prevTask, CBType &&cb ) + : _prevTask( std::move(prevTask) ) + , _myTask( std::forward(cb) ) { + connect(); + } + + AsyncToSyncResult ( const AsyncToSyncResult &other ) = delete; + AsyncToSyncResult& operator= ( const AsyncToSyncResult &other ) = delete; + + AsyncToSyncResult ( AsyncToSyncResult &&other ) = delete; + AsyncToSyncResult& operator= ( AsyncToSyncResult &&other ) = delete; + + virtual ~AsyncToSyncResult() {} + + void connect () { + //not using a lambda here on purpose, binding this into a lambda that is stored in the _prev + //object causes segfaults on gcc when the lambda is cleaned up with the _prev objects signal instance + _prevTask->onReady( std::bind( &AsyncToSyncResult::readyWasCalled, this, std::placeholders::_1) ); + } + + private: + // we need to store the passed argument in our stack, otherwise we + // run into memory issues if the argument is moved out of the _prevTask object + // so even though we std::move() the argument further we need to copy it here + void readyWasCalled ( PrevRes res ) { + //MIL << "Setting ready: " << typeid(this) << std::endl; + if ( _prevTask ) { + _prevTask.reset(); + } + + this->setReady( std::invoke( _myTask, std::move( res )) ); + } + AsyncOpRef _prevTask; + Callback _myTask; + }; + + + // case 3: connect async result to sync callback returning a async value + template + struct AsyncToSyncResult >> + : public zyppng::AsyncOp< typename remove_smart_ptr_t>::value_type> { + + using value_type = typename remove_smart_ptr_t>::value_type; + static_assert(!is_async_op_v< value_type >, "A AsyncResult can never return a async value" ); + + template + AsyncToSyncResult ( AsyncOpRef && prevTask, CBType &&cb ) + : _prevTask( std::move(prevTask) ) + , _myTask( std::forward(cb) ) { + connect(); + } + + AsyncToSyncResult ( const AsyncToSyncResult &other ) = delete; + AsyncToSyncResult& operator= ( const AsyncToSyncResult &other ) = delete; + + AsyncToSyncResult ( AsyncToSyncResult &&other ) = delete; + AsyncToSyncResult& operator= ( AsyncToSyncResult &&other ) = delete; + + virtual ~AsyncToSyncResult() {} + + void connect () { + //not using a lambda here on purpose, binding this into a lambda that is stored in the _prev + //object causes segfaults on gcc when the lambda is cleaned up with the _prev objects signal instance + _prevTask->onReady( std::bind( &AsyncToSyncResult::readyWasCalled, this, std::placeholders::_1) ); + } + + private: + // we need to store the passed argument in our stack, otherwise we + // run into memory issues if the argument is moved out of the _prevTask object + // so even though we std::move() the argument further we need to copy it here + void readyWasCalled ( PrevRes res ) { + + //MIL << "Setting ready "<onReady( [this]( value_type &&val ) { + //MIL << "Setting ready "<setReady( std::move(val) ); + }); + } + AsyncOpRef _prevTask; + Callback _myTask; + AsyncOpRef _asyncResult; + }; + } + + namespace operators { + + template< typename PrevOp , typename Callback, + std::enable_if_t< detail::is_async_op_v, int > = 0, + std::enable_if_t< detail::is_future_monad_cb_v, int > = 0 > + auto operator| ( std::shared_ptr &&in, std::shared_ptr&& c ) -> AsyncOpRef + { + using PrevOpRes = typename PrevOp::value_type; + return std::make_shared>( std::move(in), std::move(c) ); + } + + template< typename PrevOp , typename Callback, + std::enable_if_t< detail::is_async_op_v, int > = 0, + std::enable_if_t< detail::is_sync_monad_cb_with_async_res_v, int > = 0 + > + auto operator| ( std::shared_ptr &&in, Callback &&c ) + { + using PrevOpRes = typename PrevOp::value_type; + using CbType = std::remove_reference_t; + using Ret = typename detail::AsyncToSyncResult::value_type; + if ( in->isReady() ) + return AsyncOpRef( std::invoke( std::forward(c), std::move(in->get()) ) ); + return AsyncOpRef( new detail::AsyncToSyncResult( std::move(in), std::forward(c) ) ); + } + + template< typename PrevOp , typename Callback, + std::enable_if_t< detail::is_async_op_v, int > = 0, + std::enable_if_t< detail::is_sync_monad_cb_with_sync_res_v, int > = 0 + > + auto operator| ( std::shared_ptr &&in, Callback &&c ) + { + using PrevOpRes = typename PrevOp::value_type; + using CbType = std::remove_reference_t; + using Ret = typename detail::AsyncToSyncResult::value_type; + + if ( in->isReady() ) + return makeReadyResult( std::invoke( std::forward(c), std::move(in->get()) ) ); + return AsyncOpRef( new detail::AsyncToSyncResult( std::move(in), std::forward(c) ) ); + } + + template< typename PrevRes , typename CallbackOp, + std::enable_if_t< !detail::is_async_op_v, int > = 0 , + std::enable_if_t< detail::is_future_monad_cb_v, int > = 0 > + auto operator| ( PrevRes &&in, CallbackOp &&c ) -> AsyncOpRef::value_type> + { + // sync message to async callback case + std::forward(c)->operator()( std::forward(in) ); + return c; + } + + // sync to sync callback case, we do not need to differentiate between a callback with a async result or a normal one + // in both cases we simply can use the return type of the callback function + template< typename SyncRes + , typename Callback + , std::enable_if_t< !detail::is_async_op_v< SyncRes >, int > = 0 + , std::enable_if_t< detail::is_sync_monad_cb_v< Callback, SyncRes >, int > = 0 + > + auto operator| ( SyncRes &&in, Callback &&c ) + { + return std::forward(c)(std::forward(in)); + } + } +} + +#endif diff --git a/zypp-core/zyppng/pipelines/await.h b/zypp-core/zyppng/pipelines/await.h new file mode 100644 index 0000000..826671f --- /dev/null +++ b/zypp-core/zyppng/pipelines/await.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_MONADIC_AWAIT_H_INCLUDED +#define ZYPPNG_MONADIC_AWAIT_H_INCLUDED + + +#include +#include + +namespace zyppng { + + namespace detail + { + template struct AwaitImpl; + + template + struct AwaitImpl (ArgType::*)()> : public zyppng::AsyncOp< std::shared_ptr > { + + using SigGetter = SignalProxy (ArgType::*)(); + + template + AwaitImpl ( S&& sigGet ) : _sigGet( std::forward(sigGet ) ) {} + + virtual ~AwaitImpl(){ } + + void operator() ( std::shared_ptr &&req ) { + _req = std::move(req); + std::invoke( _sigGet, _req ).connect( sigc::mem_fun(this, &AwaitImpl::sigHandler) ); + } + + private: + template < typename RetType = SigR > + std::enable_if_t< std::is_same_v, RetType > + sigHandler ( SigT... ) { + this->setReady( std::move(_req) ); + } + + template < typename RetType = SigR > + std::enable_if_t< !std::is_same_v, RetType > + sigHandler ( SigT... ) { + this->setReady( std::move(_req) ); + return {}; + } + + std::shared_ptr _req; + SigGetter _sigGet; + }; + } + + //return a async op that waits for a signal to emitted by a object + template + auto await ( SignalGetter &&sigGet ) + { + return std::make_shared>( std::forward(sigGet) ); + } + +} + +#endif diff --git a/zypp-core/zyppng/pipelines/expected.h b/zypp-core/zyppng/pipelines/expected.h new file mode 100644 index 0000000..fe42933 --- /dev/null +++ b/zypp-core/zyppng/pipelines/expected.h @@ -0,0 +1,716 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +* Based on code by Ivan Čukić (BSD/MIT licensed) from the functional cpp book +*/ + +#ifndef ZYPP_ZYPPNG_MONADIC_EXPECTED_H +#define ZYPP_ZYPPNG_MONADIC_EXPECTED_H + +#include +#include +#include +#include + +namespace zyppng { + + template + class ZYPP_NODISCARD expected { + protected: + union { + T m_value; + E m_error; + }; + + bool m_isValid; + + expected() // used internally + { + } + + public: + + using value_type = T; + using error_type = E; + + ~expected() + { + if (m_isValid) { + m_value.~T(); + } else { + m_error.~E(); + } + } + + expected(const expected &other) + : m_isValid(other.m_isValid) + { + if (m_isValid) { + new (&m_value) T(other.m_value); + } else { + new (&m_error) E(other.m_error); + } + } + + expected(expected &&other) noexcept + : m_isValid(other.m_isValid) + { + if (m_isValid) { + new (&m_value) T( std::move(other.m_value) ); + } else { + new (&m_error) E( std::move(other.m_error) ); + } + } + + expected &operator= (expected other) + { + swap(other); + return *this; + } + + void swap(expected &other) noexcept + { + using std::swap; + if (m_isValid) { + if (other.m_isValid) { + // Both are valid, just swap the values + swap(m_value, other.m_value); + + } else { + // We are valid, but the other one is not + // we need to do the whole dance + auto temp = std::move(other.m_error); // moving the error into the temp + other.m_error.~E(); // destroying the original error object + new (&other.m_value) T(std::move(m_value)); // moving our value into the other + m_value.~T(); // destroying our value object + new (&m_error) E(std::move(temp)); // moving the error saved to the temp into us + std::swap(m_isValid, other.m_isValid); // swap the isValid flags + } + + } else { + if (other.m_isValid) { + // We are not valid, but the other one is, + // just call swap on other and rely on the + // implementation in the previous case + other.swap(*this); + + } else { + // Everything is rotten, just swap the errors + swap(m_error, other.m_error); + std::swap(m_isValid, other.m_isValid); + } + } + } + + template + static expected success(ConsParams && ...params) + { + // silence clang-tidy about uninitialized class members, we manually intialize them. + // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject) + expected result; + result.m_isValid = true; + new(&result.m_value) T(std::forward(params)...); + return result; + } + + template + static expected error(ConsParams && ...params) + { + // silence clang-tidy about uninitialized class members, we manually intialize them. + // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject) + expected result; + result.m_isValid = false; + new(&result.m_error) E(std::forward(params)...); + return result; + } + + operator bool() const + { + return m_isValid; + } + + bool is_valid() const + { + return m_isValid; + } + + #ifdef NO_EXCEPTIONS + # define THROW_MSG_IF_EXCEPTIONS_ARE_ENABLED(WHAT) std::terminate() + #else + # define THROW_MSG_IF_EXCEPTIONS_ARE_ENABLED(WHAT) throw std::logic_error(WHAT) + #endif + + T &get() + { + if (!m_isValid) THROW_MSG_IF_EXCEPTIONS_ARE_ENABLED("expected contains no value"); + return m_value; + } + + const T &get() const + { + if (!m_isValid) THROW_MSG_IF_EXCEPTIONS_ARE_ENABLED("expected contains no value"); + return m_value; + } + + /*! + * Unwraps the value if the expected is valid, otherwise throws an exception. + * If the Error type is std::exception_ptr the exception will be rethrown, otherwise + * the Error object is directly thrown as if calling: + * \code + * expected test = functionReturningError(); + * throw test.error(); + * \endcode + */ + T &unwrap() + { + if (!m_isValid) { +#ifdef NO_EXCEPTIONS + std::terminate(); +#else + if constexpr ( std::is_same_v ) { + std::rethrow_exception ( error() ); + } else { + throw error(); + } +#endif + } + return m_value; + } + + const T &unwrap() const + { + if (!m_isValid) { +#ifdef NO_EXCEPTIONS + std::terminate(); +#else + if constexpr ( std::is_same_v() ) { + std::rethrow_exception ( error() ); + } else { + throw error(); + } +#endif + } + return m_value; + } + + T &operator* () + { + return get(); + } + + const T &operator* () const + { + return get(); + } + + T *operator-> () + { + return &get(); + } + + const T *operator-> () const + { + return &get(); + } + + E &error() + { + if (m_isValid) THROW_MSG_IF_EXCEPTIONS_ARE_ENABLED("There is no error in this expected"); + return m_error; + } + + const E &error() const + { + if (m_isValid) THROW_MSG_IF_EXCEPTIONS_ARE_ENABLED("There is no error in this expected"); + return m_error; + } + + #undef THROW_IF_EXCEPTIONS_ARE_ENABLED + + template + void visit(F f) { + if (m_isValid) { + f(m_value); + } else { + f(m_error); + } + } + }; + + + template + class ZYPP_NODISCARD expected { + private: + union { + void* m_value; + E m_error; + }; + + bool m_isValid; + + expected() {} //used internally + + public: + ~expected() + { + if (m_isValid) { + // m_value.~T(); + } else { + m_error.~E(); + } + } + + expected(const expected &other) + : m_isValid(other.m_isValid) + { + if (m_isValid) { + // new (&m_value) T(other.m_value); + } else { + new (&m_error) E(other.m_error); + } + } + + expected(expected &&other) noexcept + : m_isValid(other.m_isValid) + { + if (m_isValid) { + // new (&m_value) T(std::move(other.m_value)); + } else { + new (&m_error) E(std::move(other.m_error)); + } + } + + expected &operator= (expected other) + { + swap(other); + return *this; + } + + void swap(expected &other) noexcept + { + using std::swap; + if (m_isValid) { + if (other.m_isValid) { + // Both are valid, we do not have any values + // to swap + + } else { + // We are valid, but the other one is not. + // We need to move the error into us + auto temp = std::move(other.m_error); // moving the error into the temp + other.m_error.~E(); // destroying the original error object + new (&m_error) E(std::move(temp)); // moving the error into us + std::swap(m_isValid, other.m_isValid); // swapping the isValid flags + } + + } else { + if (other.m_isValid) { + // We are not valid, but the other one is, + // just call swap on other and rely on the + // implementation in the previous case + other.swap(*this); + + } else { + // Everything is rotten, just swap the errors + swap(m_error, other.m_error); + std::swap(m_isValid, other.m_isValid); + } + } + } + + static expected success() + { + // silence clang-tidy about uninitialized class members, we manually intialize them. + // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject) + expected result; + result.m_isValid = true; + result.m_value = nullptr; + return result; + } + + template + static expected error(ConsParams && ...params) + { + // silence clang-tidy about uninitialized class members, we manually intialize them. + // NOLINTNEXTLINE(clang-analyzer-optin.cplusplus.UninitializedObject) + expected result; + result.m_isValid = false; + new(&result.m_error) E(std::forward(params)...); + return result; + } + + operator bool() const + { + return m_isValid; + } + + bool is_valid() const + { + return m_isValid; + }; + + #ifdef NO_EXCEPTIONS + # define THROW_IF_EXCEPTIONS_ARE_ENABLED(WHAT) std::terminate() + #else + # define THROW_IF_EXCEPTIONS_ARE_ENABLED(WHAT) throw std::logic_error(WHAT) + #endif + + E &error() + { + if (m_isValid) THROW_IF_EXCEPTIONS_ARE_ENABLED("There is no error in this expected"); + return m_error; + } + + const E &error() const + { + if (m_isValid) THROW_IF_EXCEPTIONS_ARE_ENABLED("There is no error in this expected"); + return m_error; + } + + void unwrap() const + { + if (!m_isValid) { +#ifdef NO_EXCEPTIONS + std::terminate(); +#else + if constexpr ( std::is_same_v ) { + std::rethrow_exception ( error() ); + } else { + throw error(); + } +#endif + } + } + + }; + + template + static expected,Err> make_expected_success( Type &&t ) + { + return expected,Err>::success( std::forward(t) ); + } + + namespace detail { + + // helper to figure out the return type for a mbind callback, if the ArgType is void the callback is considered to take no argument. + // Due to how std::conditional works, we cannot pass std::invoke_result_t but instead use the template type std::invoke_result, since + // one of the two options have no "::type" because the substitution fails, this breaks the std::conditional_t since it can only work with two well formed + // types. Instead we pass in the template types and evaluate the ::type in the end, when the correct invoke_result was chosen. + template < typename Function, typename ArgType> + using mbind_cb_result_t = typename std::conditional_t< std::is_same_v, std::invoke_result,std::invoke_result >::type; + + template + bool waitForCanContinueExpected( const expected &value ) { + return value.is_valid(); + } + } + + + template < typename T + , typename E + , typename Function + , typename ResultType = detail::mbind_cb_result_t + > + ResultType and_then( const expected& exp, Function &&f) + { + if (exp) { + if constexpr ( std::is_same_v ) + return std::invoke( std::forward(f) ); + else + return std::invoke( std::forward(f), exp.get() ); + } else { + if constexpr ( !detail::is_async_op< remove_smart_ptr_t >::value ) + return ResultType::error(exp.error()); + else + return makeReadyResult( remove_smart_ptr_t::value_type::error(exp.error()) ); + } + } + + template < typename T + , typename E + , typename Function + , typename ResultType = detail::mbind_cb_result_t + > + ResultType and_then( expected &&exp, Function &&f) + { + if (exp) { + if constexpr ( std::is_same_v ) + return std::invoke( std::forward(f) ); + else + return std::invoke( std::forward(f), std::move(exp.get()) ); + } else { + if constexpr ( !detail::is_async_op< ResultType >::value ) + return ResultType::error( std::move(exp.error()) ); + else + return makeReadyResult( remove_smart_ptr_t::value_type::error(exp.error()) ); + } + } + + template < typename T + , typename E + , typename Function + , typename ResultType = detail::mbind_cb_result_t + > + ResultType or_else( const expected& exp, Function &&f) + { + if (!exp) { + return std::invoke( std::forward(f), exp.error() ); + } else { + if constexpr ( !detail::is_async_op< remove_smart_ptr_t >::value ) + return exp; + else + return makeReadyResult( std::move(exp) ); + } + } + + template < typename T + , typename E + , typename Function + , typename ResultType = detail::mbind_cb_result_t + > + ResultType or_else( expected&& exp, Function &&f) + { + if (!exp) { + return std::invoke( std::forward(f), std::move(exp.error()) ); + } else { + if constexpr ( !detail::is_async_op< remove_smart_ptr_t >::value ) + return exp; + else + return makeReadyResult( std::move(exp) ); + } + } + + + /*! + * Collects all values from a Container of \ref expected values, returning the + * contained values or the first error encountered as a expected> + */ + template < template< class, class... > class Container, + typename T, + typename E, + typename ...CArgs > + std::enable_if_t, expected,E>> collect( Container, CArgs...>&& in ) { + Container res; + for( auto &v : in ) { + if ( !v ) + return expected,E>::error( std::move(v.error()) ); + res.push_back( std::move(v.get()) ); + } + return expected,E>::success( std::move(res) ); + } + + /*! + * Specialization of collect working on a Container of expected values, + * returning either success or the error encountered. + */ + template < template< class, class... > class Container, + typename T, + typename E, + typename ...CArgs > + std::enable_if_t, expected> collect( Container, CArgs...>&& in ) { + for( auto &v : in ) { + if ( !v ) + return expected::error( std::move(v.error()) ); + } + return expected::success( ); + } + + template < typename T + , typename E + , typename Function + > + expected inspect( expected exp, Function &&f ) + { + if (exp) { + const auto &val = exp.get(); + std::invoke( std::forward(f), val ); + } + return exp; + } + + template < typename T + , typename E + , typename Function + > + expected inspect_err( expected exp, Function &&f) + { + if (!exp) { + const auto &err = exp.error(); + std::invoke( std::forward(f), err ); + } + return exp; + } + + + namespace detail { + + template + struct and_then_helper { + Callback function; + + template< typename T, typename E > + auto operator()( const expected& exp ) { + return and_then( exp, function ); + } + + template< typename T, typename E > + auto operator()( expected&& exp ) { + return and_then( std::move(exp), function ); + } + }; + + template + struct or_else_helper { + Callback function; + + template< typename T, typename E > + auto operator()( const expected& exp ) { + return or_else( exp, function ); + } + + template< typename T, typename E > + auto operator()( expected&& exp ) { + return or_else( std::move(exp), function ); + } + }; + + template + struct inspect_helper { + Callback function; + + template< typename T, typename E > + auto operator()( expected&& exp ) { + return inspect( std::move(exp), function ); + } + }; + + template + struct inspect_err_helper { + Callback function; + + template< typename T, typename E > + auto operator()( expected&& exp ) { + return inspect_err( std::move(exp), function ); + } + }; + + struct collect_helper { + template < typename T > + inline auto operator()( T&& in ) { + return collect( std::forward(in) ); + } + }; + } + + namespace operators { + template + auto mbind ( Fun && function ) { + return detail::and_then_helper { + std::forward(function) + }; + } + + template + auto and_then ( Fun && function ) { + return detail::and_then_helper { + std::forward(function) + }; + } + + template + auto or_else ( Fun && function ) { + return detail::or_else_helper { + std::forward(function) + }; + } + + template + auto inspect ( Fun && function ) { + return detail::inspect_helper { + std::forward(function) + }; + } + + template + auto inspect_err ( Fun && function ) { + return detail::inspect_err_helper { + std::forward(function) + }; + } + + inline detail::collect_helper collect() { + return detail::collect_helper(); + } + } + + + /*! + * This is logically the same as \code transform() | collect() \endcode , but the inner loop will stop waiting / transforming + * as soon as a error is encountered and returns the error right away. + */ + template < template< class, class... > class Container, + typename Msg, + typename Transformation, + typename Ret = std::result_of_t, + typename ...CArgs + > + auto transform_collect( Container&& in, Transformation &&f ) + { + using namespace zyppng::operators; + if constexpr ( detail::is_async_op_v ) { + using AsyncRet = typename remove_smart_ptr_t::value_type; + static_assert( is_instance_of::value, "Transformation function must return a expected type" ); + + return transform( std::move(in), f ) + // cancel WaitFor if one of the async ops returns a error + | detail::WaitForHelperExt( detail::waitForCanContinueExpected ) + | collect(); + + } else { + static_assert( is_instance_of::value, "Transformation function must return a expected type" ); + Container results; + for ( auto &v : in ) { + auto res = f(std::move(v)); + if ( res ) { + results.push_back( std::move(res.get()) ); + } else { + return expected>::error( res.error() ); + } + } + return expected>::success( std::move(results) ); + } + } + + namespace detail { + template + struct transform_collect_helper { + Fun _callback; + template + auto operator() ( T &&in ) { + return transform_collect( std::forward(in), _callback ); + } + }; + } + + namespace operators { + template + auto transform_collect( Transformation &&f ) { + return detail::transform_collect_helper{ std::forward(f)}; + } + } + + + +} + +#endif + diff --git a/zypp-core/zyppng/pipelines/lift.h b/zypp-core/zyppng/pipelines/lift.h new file mode 100644 index 0000000..43cf8e1 --- /dev/null +++ b/zypp-core/zyppng/pipelines/lift.h @@ -0,0 +1,80 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_MONADIC_LIFT_H_INCLUDED +#define ZYPPNG_MONADIC_LIFT_H_INCLUDED + +#include +#include +#include + +#include +#include + +namespace zyppng { + + namespace detail { + template + struct lifter { + + lifter( LiftedFun &&fun ) : _fun(std::move(fun)) {} + lifter( lifter && ) = default; + ~lifter(){} + + template< typename T1 + , typename T2 + , typename Ret = std::pair, T2> + > + Ret operator()( std::pair &&data ) { + return std::make_pair( std::invoke( _fun, std::move(data.first) ), std::move(data.second) ); + } + private: + LiftedFun _fun; + }; + + template < typename AsyncOp > + struct lifter< std::shared_ptr, std::void_t< std::enable_if_t< zyppng::detail::is_async_op::value > > > { + + using LiftedFun = std::shared_ptr; + + lifter( LiftedFun &&fun ) : _fun(std::move(fun)) {} + lifter( lifter && ) = default; + ~lifter(){} + + template< typename T1 + , typename T2 + > + auto operator()( std::pair &&data ) { + + using namespace zyppng; + using namespace zyppng::operators; + + return std::move(data.first) + | ( std::move(_fun) ) + | [ other = std::move(data.second)]( auto && res ) mutable { + return std::make_pair( std::forward(res), std::move(other) ); + }; + } + private: + LiftedFun _fun; + }; + } + + template< typename Fun > + auto lift ( Fun && func ) { + return detail::lifter( std::forward(func) ); + } + +} + +#endif diff --git a/zypp-core/zyppng/pipelines/mtry.h b/zypp-core/zyppng/pipelines/mtry.h new file mode 100644 index 0000000..1712b5c --- /dev/null +++ b/zypp-core/zyppng/pipelines/mtry.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +* Based on code by Ivan Čukić (BSD/MIT licensed) from the functional cpp book +*/ + +#ifndef ZYPP_ZYPPNG_MONADIC_MTRY_H +#define ZYPP_ZYPPNG_MONADIC_MTRY_H + +#include "expected.h" + +namespace zyppng { + + template < typename F + , typename ...Args + , typename Ret = std::invoke_result_t + , typename Exp = expected + > + Exp mtry(F &&f, Args&& ...args) + { + try { + if constexpr ( std::is_same_v ) { + std::invoke(std::forward(f), std::forward(args)... ); + return expected::success(); + } else { + return expected::success(std::invoke(std::forward(f), std::forward(args)... )); + } + } catch (...) { + return expected::error(ZYPP_FWD_CURRENT_EXCPT()); + } + } + + + namespace detail + { + template + struct mtry_helper { + Callback function; + + template < typename ...Args > + auto operator()( Args&& ...args ){ + return mtry( function, std::forward(args)... ); + } + }; + } + + namespace operators { + template + auto mtry ( Fun && function ) { + return detail::mtry_helper { + std::forward(function) + }; + } + } + + +} + +#endif /* !MTRY_H */ diff --git a/zypp-core/zyppng/pipelines/redo.h b/zypp-core/zyppng/pipelines/redo.h new file mode 100644 index 0000000..8016695 --- /dev/null +++ b/zypp-core/zyppng/pipelines/redo.h @@ -0,0 +1,150 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_MONADIC_REDO_H_INCLUDED +#define ZYPPNG_MONADIC_REDO_H_INCLUDED + +#include +#include +#include +#include + +namespace zyppng { + + namespace detail { + + + template< typename Task, typename Pred, typename = void > + struct RedoWhileImpl + { + + static_assert ( !is_async_op< zyppng::remove_smart_ptr >::value, "" ); + + template + RedoWhileImpl( T &&t, P &&p ) : + _task( std::forward(t) ) + , _pred( std::forward

(p) ) {} + + template + std::enable_if_t< is_async_op< remove_smart_ptr_t> >::value == false, Arg > operator()( Arg &&arg ) { + Arg store = std::forward(arg); + do { + auto res = _task ( Arg(store) ); + if ( !_pred( res ) ) + return std::move(res); + } while( true ); + } + + template + static auto create ( T &&t, P &&p ) { + return RedoWhileImpl( std::forward(t), std::forward

(p)); + } + + private: + Task _task; + Pred _pred; + }; + + template< typename MyAsyncOp, typename Pred > + struct RedoWhileImpl< std::shared_ptr,Pred, std::enable_if_t< is_async_op< MyAsyncOp >::value > > : public AsyncOp { + + using Task = std::shared_ptr; + using OutType = typename MyAsyncOp::value_type; + + template + RedoWhileImpl( T &&t, P &&p ) : + _task( std::forward(t) ) + , _pred( std::forward

(p) ) {} + + static_assert ( !is_async_op< remove_smart_ptr >::value, "" ); + + template + void operator()( InType &&arg ) { + _task->onReady( + [this, inArg = arg]( OutType &&a) mutable { + if ( _pred(a) ) + this->operator()(std::move(inArg)); + else + this->setReady( std::move(a) ); + } + ); + _task->operator()( InType(arg) ); + } + + template + static auto create ( T &&t, P &&p ) { + return std::make_shared( std::forward(t), std::forward

(p)); + } + + private: + + Task _task; + Pred _pred; + std::shared_ptr> _pipeline; + }; + + //implementation for a function returning a asynchronous result + template< typename Task, typename Pred > + struct RedoWhileImpl< Task,Pred, std::enable_if_t< is_async_op< remove_smart_ptr_t::return_type> >::value > > : public AsyncOp< typename remove_smart_ptr_t::return_type>::value_type> { + + using FunRet = remove_smart_ptr_t::return_type>; + + //the task function needs to return the same type it takes + using OutType = typename FunRet::value_type; + + template + RedoWhileImpl( T &&t, P &&p ) : + _task( std::forward(t) ) + , _pred( std::forward

(p) ) {} + + template + void operator() ( InType &&arg ) { + _asyncRes.reset(); + _asyncRes = _task( InType( arg ) ); + _asyncRes->onReady( + [this, inArg = arg ]( OutType &&arg ) mutable { + if ( _pred(arg) ) + this->operator()( std::move(inArg) ); + else + this->setReady( std::move(arg) ); + }); + } + + template + static auto create ( T &&t, P &&p ) { + return std::make_shared( std::forward(t), std::forward

(p)); + } + + private: + std::shared_ptr> _asyncRes; + + Task _task; + Pred _pred; + }; + + //check if it is possible to query the given type for function_traits + template + using has_func_trait = typename function_traits::return_type; + + } + + template + auto redo_while ( Task &&todo, Pred &&until ) + { + static_assert ( std::is_detected_v< detail::has_func_trait, Task >, "Not possible to deduce the function_traits for Task, maybe a generic lambda?" ); + return detail::RedoWhileImpl::create( std::forward(todo), std::forward(until) ); + } + +} + +#endif diff --git a/zypp-core/zyppng/pipelines/transform.h b/zypp-core/zyppng/pipelines/transform.h new file mode 100644 index 0000000..abc38df --- /dev/null +++ b/zypp-core/zyppng/pipelines/transform.h @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +*/ + + +#ifndef ZYPP_ZYPPNG_MONADIC_TRANSFORM_H +#define ZYPP_ZYPPNG_MONADIC_TRANSFORM_H + +#include +#include +#include +#include +#include + +namespace zyppng { + +template < template< class, class... > class Container, + typename Msg, + typename Transformation, + typename Ret = std::result_of_t, + typename ...CArgs > +Container transform( Container&& val, Transformation &&transformation ) +{ + Container res; + std::transform( std::make_move_iterator(val.begin()), std::make_move_iterator(val.end()), std::back_inserter(res), std::forward(transformation) ); + return res; +} + +template < template< class, class... > class Container, + typename Msg, + typename Transformation, + typename Ret = std::result_of_t, + typename ...CArgs > +Container transform( const Container& val, Transformation &&transformation ) +{ + Container res; + std::transform( val.begin(), val.end(), std::back_inserter(res), std::forward(transformation) ); + return res; +} + +namespace detail { + template + struct transform_helper { + Transformation function; + + template< class Container > + auto operator()( Container&& arg ) { + if constexpr ( detail::is_sync_monad_cb_with_async_res_v ) { + using namespace zyppng::operators; + return zyppng::transform( std::forward(arg), function ) | zyppng::waitFor(); + } else { + return zyppng::transform( std::forward(arg), function ); + } + } + }; +} + +namespace operators { + + template + auto transform(Transformation&& transformation) + { + return detail::transform_helper{ + std::forward(transformation)}; + } +} + +} + +#endif diff --git a/zypp-core/zyppng/pipelines/wait.h b/zypp-core/zyppng/pipelines/wait.h new file mode 100644 index 0000000..7b3c3f7 --- /dev/null +++ b/zypp-core/zyppng/pipelines/wait.h @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +*/ + +#ifndef ZYPP_ZYPPNG_MONADIC_WAIT_H +#define ZYPP_ZYPPNG_MONADIC_WAIT_H + +#include +#include + +namespace zyppng { + +namespace detail { + + template < template< class, class... > class Container, + class AsyncOp, + class ...CArgs + > + struct WaitForImpl : public zyppng::AsyncOp< Container > { + + using AsyncOpRes = typename AsyncOp::value_type; + + static_assert( detail::is_async_op_v, "Result type needs to be derived from AsyncOp"); + + WaitForImpl ( std::function canContinue = {} ) + : _canContinue( std::move(canContinue) ){}; + + WaitForImpl ( const WaitForImpl &other ) = delete; + WaitForImpl& operator= ( const WaitForImpl &other ) = delete; + + WaitForImpl& operator= ( WaitForImpl &&other ) = default; + WaitForImpl ( WaitForImpl &&other ) = default; + + void operator()( Container< std::shared_ptr, CArgs...> &&ops ) { + assert( _allOps.empty() ); + + if ( ops.empty () ) { + this->setReady( std::move(_allResults) ); + } + + _allOps = std::move( ops ); + for ( auto &op : _allOps ) { + op->onReady( [ this ]( AsyncOpRes &&res ) { + this->resultReady( std::move(res)); + }); + } + } + + private: + void resultReady ( AsyncOpRes &&res ) { + _allResults.push_back( std::move( res ) ); + + bool done = ( _allOps.size() == _allResults.size()) || ( _canContinue && !_canContinue(_allResults.back())); + if ( done ) { + //release all ops we waited on + _allOps.clear(); + + this->setReady( std::move(_allResults) ); + } + } + + Container< std::shared_ptr, CArgs... > _allOps; + Container< AsyncOpRes > _allResults; + std::function _canContinue; + }; + + struct WaitForHelper + { + template< + template< class, class... > class Container, + class AsyncOp, + typename ...CArgs, + std::enable_if_t< detail::is_async_op_v, int> = 0 + > + auto operator()( Container< std::shared_ptr< AsyncOp >, CArgs... > &&ops ) -> zyppng::AsyncOpRef< Container > { + auto aOp = std::make_shared>( ); + aOp->operator()( std::move(ops) ); + return aOp; + } + + template< + template< class, class... > class Container, + class Res, + typename ...CArgs, + std::enable_if_t< !detail::is_async_op_v, int> = 0 + > + auto operator()( Container< Res, CArgs... > ops ) -> Container< Res, CArgs... > { + return ops; + } + }; + + + template + struct WaitForHelperExt + { + WaitForHelperExt( std::function &&fn ) : _cb( std::move(fn) ) {} + + template< + template< class, class... > class Container, + class AsyncOp, + typename ...CArgs, + std::enable_if_t< detail::is_async_op_v, int> = 0 + > + auto operator()( Container< std::shared_ptr< AsyncOp >, CArgs... > &&ops ) -> zyppng::AsyncOpRef< Container > { + auto aOp = std::make_shared>( _cb ); + aOp->operator()( std::move(ops) ); + return aOp; + } + + private: + std::function _cb; + }; + +} + +/*! + * Returns a async operation that waits for all async operations which are passed to it and collects their results, + * forwarding them as one + */ +inline auto waitFor ( ) { + return detail::WaitForHelper(); //std::make_shared>>(); +} + +inline auto join ( ) { + return detail::WaitForHelper(); +} + +} +#endif diff --git a/zypp-core/zyppng/rpc/stompframestream.cc b/zypp-core/zyppng/rpc/stompframestream.cc new file mode 100644 index 0000000..9c92d3f --- /dev/null +++ b/zypp-core/zyppng/rpc/stompframestream.cc @@ -0,0 +1,327 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include "stompframestream.h" +#include +#include + +#include +#include + +namespace zyppng { + + constexpr auto MAX_CMDLEN = 256; + constexpr auto MAX_HDRLEN = 8 * 1024; // we might send long paths in headers + constexpr auto MAX_BODYLEN = 1024 * 1024; // 1Mb for now, we do not want to use up all the memory + + InvalidMessageReceivedException::InvalidMessageReceivedException( const std::string &msg ) + : zypp::Exception( zypp::str::Str() << "Invalid Message received: (" << msg <<")" ) + { } + + zyppng::StompFrameStream::StompFrameStream( IODevice::Ptr iostr ) : _ioDev( std::move(iostr) ) + { + connect( *_nextMessageTimer, &Timer::sigExpired, *this, &StompFrameStream::timeout ); + _nextMessageTimer->setSingleShot(false); + + connect( *_ioDev, &IODevice::sigReadyRead, *this, &StompFrameStream::readAllMessages ); + if ( _ioDev->isOpen () && _ioDev->canRead () ) + readAllMessages (); + } + + bool StompFrameStream::readNextMessage( ) + { + const auto &parseError = [this](){ + _parserState = ParseError; + _pendingMessage.reset(); + _pendingBodyLen.reset(); + _sigInvalidMessageReceived.emit(); + }; + + // ATTENTION: Remember to also update the parser logic in zypp-core/rpc/PluginFrame.cc + // if code here is changed or features are added. + + // loop until we have a full message, or we have no more data to read + while(true) { + switch( _parserState ) { + case ParseError: { + // we got a parse error before, try to recover by reading until the next \0 + bool gotTerm = false; + while ( _ioDev->bytesAvailable ( ) ) { + auto d = _ioDev->read (1); + if ( !d.size() ) + break; + + if ( d.front () == '\0' ){ + gotTerm = true; + _parserState = ReceiveCommand; + break; + } + } + + if ( gotTerm ) + continue; + + return false; + } + case ReceiveCommand: { + const auto ba = _ioDev->readBufferCount(); + if ( !_ioDev->canReadLine() ) { + if ( ba > MAX_CMDLEN ) { + ERR << "Received malformed message from peer, CMD line exceeds: " << MAX_CMDLEN << " bytes" << std::endl; + parseError(); + continue; + } + return false; + } + + ByteArray command = _ioDev->readLine( MAX_CMDLEN ); + command.pop_back(); // remove \n + if ( command.empty() ) { + // STOMP spec says multiple EOLs after a message are allowed, so we just ignore empty lines + // if they happen before a new frame starts + WAR << "Received empty line before command, ignoring" << std::endl; + return false; + } + + if ( !_pendingMessage ) + _pendingMessage = zypp::PluginFrame(); + _pendingMessage->setCommand( command.asString() ); + _parserState = ReceiveHeaders; + + break; + } + + case ReceiveHeaders: { + const auto ba = _ioDev->readBufferCount(); + if ( !_ioDev->canReadLine() ) { + if ( ba > MAX_HDRLEN ) { + ERR << "Received malformed message from peer, header line exceeds: " << MAX_HDRLEN << " bytes" << std::endl; + parseError(); + continue; + } + return false; + } + + ByteArray header = _ioDev->readLine( MAX_HDRLEN ); + header.pop_back(); // remove \n + if ( header.empty () ) { + // --> empty line sep. header and body + _parserState = ReceiveBody; + + // if we received a content-length header we set the flag for the body parser to know it has to read + // n bytes before expecting the \0 terminator + const auto &contentLen = _pendingMessage->getHeaderNT( zypp::PluginFrame::contentLengthHeader(), std::string() ); + std::optional cLen; + if ( !contentLen.empty() ) { + cLen = zyppng::str::safe_strtonum(contentLen); + if ( !cLen ) { + ERR << "Received malformed message from peer: Invalid value for " << zypp::PluginFrame::contentLengthHeader() << ":" << contentLen << std::endl; + parseError(); + continue; + } +#if 0 + if ( (*cLen) > MAX_BODYLEN ) { + ERR << "Message body exceeds maximum length: " << zypp::ByteCount( *cLen ) << " vs " << zypp::ByteCount( MAX_BODYLEN ) << std::endl; + parseError(); + continue; + } +#endif + + _pendingBodyLen = *cLen; + _pendingMessage->clearHeader( zypp::PluginFrame::contentLengthHeader() ); + } + } else { + try { + _pendingMessage->addRawHeader ( header ); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + ERR << "Received malformed message from peer, header format invalid: " << header.asStringView() << " (" << e << ")" << std::endl; + parseError(); + continue; + } + } + break; + } + + case ReceiveBody: { + + ByteArray body; + if ( _pendingBodyLen ) { + // we need to read the required body bytes plus the terminating \0 + const auto reqBytes = (*_pendingBodyLen) + 1; + if ( _ioDev->bytesAvailable() < reqBytes ) + return false; + + body = _ioDev->read( reqBytes ); + if ( body.back () != '\0' ) { + ERR << "Received malformed message from peer: Body was not terminated with \\0" << std::endl; + parseError(); + continue; + } + + body.pop_back (); // remove \0 + + } else { + // we do not know the body size, need to read until \0 + const auto ba = _ioDev->readBufferCount(); + if ( !_ioDev->canReadUntil( _ioDev->currentReadChannel (), '\0' ) ) { + if ( ba > MAX_BODYLEN ) { + ERR << "Message body exceeds maximum length: " << zypp::ByteCount( _ioDev->readBufferCount() ) << " vs " << zypp::ByteCount( MAX_BODYLEN ) << std::endl; + parseError(); + continue; + } + return false; + } + + body = _ioDev->channelReadUntil( _ioDev->currentReadChannel (), '\0' ); + body.pop_back(); // remove the \0 + } + + // if we reach this place we have a full message, store the body and lets go) + _pendingMessage->setBody( std::move(body) ); + + _messages.emplace_back( std::move(*_pendingMessage) ); + _pendingMessage.reset(); + _pendingBodyLen.reset(); + _parserState = ReceiveCommand; + + _sigNextMessage.emit (); + + if ( _messages.size() ) { + // nag the user code until all messages have been used up + _nextMessageTimer->start(0); + } + + // once we have a message, exit the loop so other things can be done + return true; + } + } + } + } + + void StompFrameStream::timeout(const Timer &) + { + if ( _messages.size() ) + _sigNextMessage.emit(); + + if ( !_messages.size() ) + _nextMessageTimer->stop(); + } + + std::optional zyppng::StompFrameStream::nextMessage( const std::string &msgName ) + { + if ( !_messages.size () ) { + + // try to read the next messages from the fd + { + _sigNextMessage.block (); + zypp::OnScopeExit unblock([&](){ + _sigNextMessage.unblock(); + }); + readAllMessages(); + } + + if ( !_messages.size () ) + return {}; + } + + std::optional res; + + if( msgName.empty() ) { + res = std::move( _messages.front () ); + _messages.pop_front(); + + } else { + const auto i = std::find_if( _messages.begin(), _messages.end(), [&]( const zypp::PluginFrame &msg ) { + return msg.command() == msgName; + }); + + if ( i != _messages.end() ) { + res = std::move(*i); + _messages.erase(i); + } + } + + if ( _messages.size() ) + _nextMessageTimer->start(0); + else + _nextMessageTimer->stop(); + + return res; + } + + std::optional StompFrameStream::nextMessageWait( const std::string &msgName ) + { + // make sure the signal is not emitted until we have the next message + _sigNextMessage.block (); + zypp::OnScopeExit unblock([&](){ + _sigNextMessage.unblock(); + }); + + bool receivedInvalidMsg = false; + AutoDisconnect defered( connectFunc( *this, &StompFrameStream::sigInvalidMessageReceived, [&](){ + receivedInvalidMsg = true; + })); + + const bool hasMsgName = msgName.size(); + while ( !receivedInvalidMsg && _ioDev->isOpen() && _ioDev->canRead() ) { + if ( _messages.size() ) { + if ( hasMsgName ) { + std::optional msg = nextMessage(msgName); + if ( msg ) return msg; + } + else { + break; + } + } + + if ( !_ioDev->waitForReadyRead ( -1 ) ) { + // this can only mean that a error happened, like device was closed + return {}; + } + } + return nextMessage (msgName); + } + + bool zyppng::StompFrameStream::sendFrame( const zypp::PluginFrame &env ) + { + if ( !_ioDev->canWrite () ) + return false; + + try { + IODeviceOStreamBuf ostrbuf(_ioDev); + std::ostream output(&ostrbuf); + env.writeTo ( output ); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + ERR << "Failed to serialize message to stream" << std::endl; + return false; + } + + return true; + } + + SignalProxy zyppng::StompFrameStream::sigMessageReceived() + { + return _sigNextMessage; + } + + SignalProxy StompFrameStream::sigInvalidMessageReceived() + { + return _sigInvalidMessageReceived; + } + + void StompFrameStream::readAllMessages() + { + bool cont = true; + while ( cont && _ioDev->bytesAvailable() ) { + cont = readNextMessage (); + } + } +} diff --git a/zypp-core/zyppng/rpc/stompframestream.h b/zypp-core/zyppng/rpc/stompframestream.h new file mode 100644 index 0000000..389ecee --- /dev/null +++ b/zypp-core/zyppng/rpc/stompframestream.h @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +-----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ + +#ifndef ZYPP_CORE_ZYPPNG_RPC_STOMPFRAMESTREAM_H_INCLUDED +#define ZYPP_CORE_ZYPPNG_RPC_STOMPFRAMESTREAM_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (StompFrameStream); + + class ZYPP_API InvalidMessageReceivedException : public zypp::Exception + { + public: + InvalidMessageReceivedException( const std::string &msg = {}); + }; + + namespace rpc { + + template + expected toStompMessage( const T& msg ) { + return msg.toStompMessage(); + } + + template + expected fromStompMessage( const zypp::PluginFrame &message ) { + return T::fromStompMessage( message ); + } + + // Reads data from the stomp message and converts it to the target type + // used to read header values and values serialized into a terminated data field + template + void parseDataIntoField( const std::string &headerVal, T &target ) + { + if constexpr ( std::is_same_v ) { + const auto &triBool = zypp::str::strToTriBool ( headerVal ); + if ( indeterminate(triBool) ) { + ZYPP_THROW ( zypp::PluginFrameException( "Invalid value for boolean field" ) ); + } + target = bool(triBool); + } else if constexpr ( std::is_same_v ) { + target = headerVal; + } else { + // numbers + auto val = zyppng::str::safe_strtonum ( headerVal ); + if ( !val ) + ZYPP_THROW ( zypp::PluginFrameException( "Invalid value for numerical field" ) ); + target = *val; + } + } + + // queries a header value and calls parseDataIntoField on it + template + void parseHeaderIntoField( const zypp::PluginFrame &msg, const std::string &name, T &target ) + { + return parseDataIntoField ( msg.getHeader(name), target ); + } + + template + inline zypp::PluginFrame prepareFrame() { + return zypp::PluginFrame ( std::string( T::typeName.data(), T::typeName.length() ) ); + } + + } + + /*! + * + * Implements the basic protocol for sending zypp RPC messages over a IODevice + * using the STOMP frame format as message type. + */ + class ZYPP_API StompFrameStream : public zyppng::Base + { + public: + + using Ptr = StompFrameStreamRef; + + /*! + * Uses the given iostream to send and receive messages. + * If the device is already open and readable tries to read messages right away. + * So make sure to check if messages have already been received via \ref nextMessage + */ + static Ptr create( IODevice::Ptr iostr ) { + return Ptr( new StompFrameStream( std::move(iostr) ) ); + } + + /*! + * Returns the next message in the queue, wait for the \ref sigMessageReceived signal + * to know when new messages have arrived. + * If \a msgName is specified returns the next message in the queue that matches the msgName + */ + std::optional nextMessage ( const std::string &msgName = "" ); + + /*! + * Waits until at least one message is in the queue and returns it. Will return a empty + * optional if a error occurs. + * + * If \a msgName is set this will block until a message with the given message name arrives and returns it + * + * \note Make sure to check if there are more than one messages in the queue after this function returns + */ + std::optional nextMessageWait ( const std::string &msgName = "" ); + + /*! + * Send out a PluginFrame to the other side, depending on the underlying device state + * this will be buffered and send when the device is writeable again. + */ + bool sendFrame ( const zypp::PluginFrame &message ); + + template + bool sendMessage ( const T &message ) + { + if constexpr ( std::is_same_v ) { + return sendFrame( message ); + } else { + const auto &msg = rpc::toStompMessage(message); + if ( !msg ) { + ERR << "Failed to serialize message" << std::endl; + return false; + } + return sendFrame( *msg ); + } + } + + template + static expected< T > parseMessage ( const zypp::PluginFrame &m ) { + return rpc::fromStompMessage(m); + } + + /*! + * Reads all messages from the underlying IO Device, this is usually called automatically + * but when shutting down this can be used to process all remaining messages. + */ + void readAllMessages (); + + /*! + * Emitted when new messages have arrived. This will continuously be emitted + * as long as messages are in the queue. + */ + SignalProxy sigMessageReceived (); + + /*! + * Signal is emitted every time there was data on the line that could not be parsed + */ + SignalProxy sigInvalidMessageReceived (); + + private: + StompFrameStream( IODevice::Ptr iostr ); + bool readNextMessage (); + void timeout( const zyppng::Timer &); + + enum ParserState { + ReceiveCommand, + ReceiveHeaders, + ReceiveBody, + ParseError + } _parserState = ReceiveCommand; + + std::optional _pendingMessage; + std::optional _pendingBodyLen; + + IODevice::Ptr _ioDev; + Timer::Ptr _nextMessageTimer = Timer::create(); + std::deque _messages; + Signal _sigNextMessage; + Signal _sigInvalidMessageReceived; + + }; +} + +#endif // ZYPP_CORE_ZYPPNG_RPC_STOMPFRAMESTREAM_H_INCLUDED diff --git a/zypp-core/zyppng/thread/AsyncQueue b/zypp-core/zyppng/thread/AsyncQueue new file mode 100644 index 0000000..e948e2c --- /dev/null +++ b/zypp-core/zyppng/thread/AsyncQueue @@ -0,0 +1 @@ +#include "asyncqueue.h" diff --git a/zypp-core/zyppng/thread/Wakeup b/zypp-core/zyppng/thread/Wakeup new file mode 100644 index 0000000..6650b49 --- /dev/null +++ b/zypp-core/zyppng/thread/Wakeup @@ -0,0 +1 @@ +#include "wakeup.h" diff --git a/zypp-core/zyppng/thread/asyncqueue.cc b/zypp-core/zyppng/thread/asyncqueue.cc new file mode 100644 index 0000000..73be29f --- /dev/null +++ b/zypp-core/zyppng/thread/asyncqueue.cc @@ -0,0 +1,111 @@ +#include "private/asyncqueue_p.h" +#include +#include + +#include + +namespace zyppng { + + AsyncQueueBase::~AsyncQueueBase() + { } + + void AsyncQueueBase::addWatch(AsyncQueueWatch &watch) + { + std::lock_guard lock(_watchLock); + _watches.insert( &watch ); + } + + void AsyncQueueBase::removeWatch(AsyncQueueWatch &watch) + { + std::lock_guard lock(_watchLock); + _watches.erase( &watch ); + } + + void AsyncQueueBase::notifyWatches() + { + std::lock_guard lock(_watchLock); + std::for_each( _watches.begin(), _watches.end(), []( AsyncQueueWatch *w ){ + w->postNotifyEvent(); + }); + } + + AsyncQueueWatchPrivate::AsyncQueueWatchPrivate(std::shared_ptr &&q , AsyncQueueWatch &p) : AbstractEventSourcePrivate(p) + , _queue( std::move(q) ) + { + GError *error = NULL; + + if (!g_unix_open_pipe (fds, FD_CLOEXEC, &error)) + ERR << "Creating pipes for AsyncQueueWatch: " << error->message << std::endl; + + if (!g_unix_set_fd_nonblocking (fds[0], TRUE, &error) || + !g_unix_set_fd_nonblocking (fds[1], TRUE, &error)) + ERR << "Set pipes non-blocking for AsyncQueueWatch: "<< error->message << std::endl; + } + + AsyncQueueWatchPrivate::~AsyncQueueWatchPrivate() + { + close (fds[0]); + close (fds[1]); + } + + ZYPP_IMPL_PRIVATE(AsyncQueueWatch) + + AsyncQueueWatch::AsyncQueueWatch(std::shared_ptr &&queue ) + : AsyncQueueWatch( *( new AsyncQueueWatchPrivate( std::move(queue), *this ) ) ) + { } + + AsyncQueueWatch::AsyncQueueWatch(AsyncQueueWatchPrivate &dd) + : AbstractEventSource( dd ) + { } + + std::shared_ptr AsyncQueueWatch::create( std::shared_ptr queue ) + { + std::shared_ptr ptr ( new AsyncQueueWatch( std::move(queue) ) ); + auto d = ptr->d_func(); + ptr->updateFdWatch( d->fds[0], AbstractEventSource::Read ); + d->_queue->addWatch( *ptr ); + return ptr; + } + + AsyncQueueWatch::~AsyncQueueWatch() + { + // sync point, since the queue locks all its watches before changing or notifying them + // we should never run into a bad situation where the AsyncQueueWatch is deleted while notified from a different thread. + // In case watches are notified this will block and the other way round + d_func()->_queue->removeWatch( *this ); + } + + void AsyncQueueWatch::postNotifyEvent() + { + Z_D(); + int res = -1; + guint8 one = 1; + + do { + errno = 0; + res = write (d->fds[1], &one, sizeof one); + } while (G_UNLIKELY (res == -1 && errno == EINTR)); + } + + SignalProxy AsyncQueueWatch::sigMessageAvailable() + { + return d_func()->_sigMessageAvailable; + } + + void AsyncQueueWatch::onFdReady( int , int ) + { + Z_D(); + char buffer[16]; + + /* read until it is empty */ + while (read (d->fds[0], buffer, sizeof buffer) == sizeof buffer); + d->_sigMessageAvailable.emit(); + } + + void AsyncQueueWatch::onSignal(int) + { + } + + +} + diff --git a/zypp-core/zyppng/thread/asyncqueue.h b/zypp-core/zyppng/thread/asyncqueue.h new file mode 100644 index 0000000..6e34daa --- /dev/null +++ b/zypp-core/zyppng/thread/asyncqueue.h @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#ifndef ZYPP_NG_THREAD_ASYNCQUEUE_H_INCLUDED +#define ZYPP_NG_THREAD_ASYNCQUEUE_H_INCLUDED + +#include + +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + class AsyncQueueWatch; + + class AsyncQueueBase { + public: + virtual ~AsyncQueueBase(); + + void addWatch ( AsyncQueueWatch &watch ); + void removeWatch ( AsyncQueueWatch &watch ); + void notifyWatches ( ); + + private: + std::set _watches; + std::recursive_mutex _watchLock; + }; + + /*! + * AsyncQueue provides a thread safe way to send messages between threads. + * Using this class makes only sense for multithreaded applications. + */ + template< class Message > + class AsyncQueue : public AsyncQueueBase { + + public: + + using Ptr = std::shared_ptr; + + static Ptr create () { + return Ptr( new AsyncQueue() ); + } + + AsyncQueue(const AsyncQueue&) = delete; + AsyncQueue& operator=(const AsyncQueue&) = delete; + + /*! + * Pushes a new message into the queue, make sure to manually + * acqiure the lock before calling this function and \ref notify after + * unlocking it again. This function should be used when multiple messages should be pushed + * into the queue before notifying the threads. + * \sa push + */ + template< typename T = Message > + void pushUnlocked ( T &&value ) { + _messages.push( std::forward(value) ); + } + + /*! + * Pushes a new message into the queue and notify all waiting + * threads that there is new data available. + */ + template< typename T = Message > + void push ( T &&value ) { + { + std::lock_guard lk( _mut ); + pushUnlocked( std::forward(value) ); + } + notify(); + } + + /*! + * Pops the first message from the queue, blocking until there is data available. + */ + Message pop () { + std::unique_lock lk( _mut ); + _cv.wait( lk, [this](){ return _messages.size() > 0; } ); + Message msg = std::move( _messages.front() ); + _messages.pop(); + return msg; + } + + /*! + * Tries to pop the first element from the queue, if no data is available returns a empty + * \ref std::optional instead of blocking. + */ + std::optional tryPop () { + std::lock_guard lk( _mut ); + return tryPopUnlocked(); + } + + /*! + * Same as \ref tryPop but does not lock the mutex, make sure to acquire the lock before + * calling this function. + */ + std::optional tryPopUnlocked () { + if ( _messages.size() ) { + Message msg = std::move( _messages.front() ); + _messages.pop(); + return msg; + } + return {}; + } + + /*! + * Locks the internal mutex, use \ref std::lock_guard instead of manually + * calling lock and unlock. + */ + void lock () { + _mut.lock(); + } + + /*! + * Unlocks the internal mutex, use \ref std::lock_guard instead of manually + * calling lock and unlock. + */ + void unlock () { + _mut.unlock(); + } + + /*! + * Notifies all waiting threads and registered \ref AsyncQueueWatch instances that + * new data is available. + */ + void notify () { + _cv.notify_all(); + notifyWatches(); + } + + private: + AsyncQueue() = default; + std::queue _messages; + std::mutex _mut; + std::condition_variable _cv; + }; + + class AsyncQueueWatchPrivate; + class LIBZYPP_NG_EXPORT AsyncQueueWatch : public AbstractEventSource + { + ZYPP_DECLARE_PRIVATE(AsyncQueueWatch) + public: + + static std::shared_ptr create ( std::shared_ptr queue ); + ~AsyncQueueWatch() override; + + void postNotifyEvent (); + + SignalProxy sigMessageAvailable(); + + // AbstractEventSource interface + void onFdReady(int fd, int events) override; + void onSignal(int signal) override; + + protected: + AsyncQueueWatch( std::shared_ptr &&queue ); + AsyncQueueWatch( AsyncQueueWatchPrivate &dd ); + }; + +} + + +#endif diff --git a/zypp-core/zyppng/thread/private/asyncqueue_p.h b/zypp-core/zyppng/thread/private/asyncqueue_p.h new file mode 100644 index 0000000..b9d1523 --- /dev/null +++ b/zypp-core/zyppng/thread/private/asyncqueue_p.h @@ -0,0 +1,26 @@ +#ifndef ZYPP_NG_THREAD_PRIVATE_ASYNCQUEUE_P_H +#define ZYPP_NG_THREAD_PRIVATE_ASYNCQUEUE_P_H + +#include +#include +#include + +#include + +namespace zyppng { + + class AsyncQueueWatchPrivate : public AbstractEventSourcePrivate + { + ZYPP_DECLARE_PUBLIC(AsyncQueueWatch) + public: + AsyncQueueWatchPrivate( std::shared_ptr &&q, AsyncQueueWatch &p ); + ~AsyncQueueWatchPrivate() override; + + std::shared_ptr _queue; + gint fds[2] = { -1, -1 }; + Signal< void()> _sigMessageAvailable; + }; + +} + +#endif // ZYPP_NG_THREAD_PRIVATE_ASYNCQUEUE_P_H diff --git a/zypp-core/zyppng/thread/wakeup.cpp b/zypp-core/zyppng/thread/wakeup.cpp new file mode 100644 index 0000000..7c537bd --- /dev/null +++ b/zypp-core/zyppng/thread/wakeup.cpp @@ -0,0 +1,44 @@ +#include "wakeup.h" + +#include +#include + +#include +#include + +namespace zyppng { + + Wakeup::Wakeup() + { + ::pipe ( _wakeupPipe ); + ::fcntl( _wakeupPipe[0], F_SETFL, O_NONBLOCK ); + } + + Wakeup::~Wakeup() + { + ::close (_wakeupPipe[0]); + ::close (_wakeupPipe[1]); + } + + void Wakeup::notify() + { + eintrSafeCall( ::write, _wakeupPipe[1], "\n", 1); + } + + void Wakeup::ack() + { + char dummy = 0; + while ( eintrSafeCall( ::read, _wakeupPipe[0], &dummy, 1 ) > 0 ) { continue; } + } + + int Wakeup::pollfd() const + { + return _wakeupPipe[0]; + } + + std::shared_ptr Wakeup::makeNotifier( const bool enabled ) const + { + return SocketNotifier::create( _wakeupPipe[0], zyppng::SocketNotifier::Read, enabled ); + } + +} diff --git a/zypp-core/zyppng/thread/wakeup.h b/zypp-core/zyppng/thread/wakeup.h new file mode 100644 index 0000000..1ec180e --- /dev/null +++ b/zypp-core/zyppng/thread/wakeup.h @@ -0,0 +1,58 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#ifndef ZYPP_NG_THREAD_WAKEUP_H_INCLUDED +#define ZYPP_NG_THREAD_WAKEUP_H_INCLUDED + +#include + +namespace zyppng { + + class SocketNotifier; + + /*! + * Simple helper class that can be used to notify a thread to wake up. + * This is guaranteed to use signal safe means to wake up the thread. + */ + class Wakeup + { + public: + Wakeup(); + ~Wakeup(); + + /*! + * Post a notification to the thread. + */ + void notify(); + + /*! + * Called from the thread to acknowledge and clear the wakeup signal + * \note If this is not called the EventLoop in the thread will constantly wake up + */ + void ack(); + + /*! + * Returns the internal FD to be used in the thread to poll for notifications + */ + int pollfd() const; + + /*! + * Convenience function to create a \ref zyppng::SocketNotifier that is listening for incoming + * notifications. + */ + std::shared_ptr makeNotifier( const bool enabled = true ) const; + + private: + int _wakeupPipe[2] = { -1, -1 }; + }; + +} + + + +#endif // ZYPP_NG_THREAD_WAKEUP_H_INCLUDED diff --git a/zypp-core/zyppng/ui/ProgressObserver b/zypp-core/zyppng/ui/ProgressObserver new file mode 100644 index 0000000..87340d1 --- /dev/null +++ b/zypp-core/zyppng/ui/ProgressObserver @@ -0,0 +1 @@ +#include "progressobserver.h" diff --git a/zypp-core/zyppng/ui/UserInterface b/zypp-core/zyppng/ui/UserInterface new file mode 100644 index 0000000..00f29e1 --- /dev/null +++ b/zypp-core/zyppng/ui/UserInterface @@ -0,0 +1 @@ +#include "userinterface.h" diff --git a/zypp-core/zyppng/ui/UserRequest b/zypp-core/zyppng/ui/UserRequest new file mode 100644 index 0000000..890f836 --- /dev/null +++ b/zypp-core/zyppng/ui/UserRequest @@ -0,0 +1 @@ +#include "userrequest.h" diff --git a/zypp-core/zyppng/ui/private/userinterface_p.h b/zypp-core/zyppng/ui/private/userinterface_p.h new file mode 100644 index 0000000..7139184 --- /dev/null +++ b/zypp-core/zyppng/ui/private/userinterface_p.h @@ -0,0 +1,22 @@ +#ifndef ZYPP_NG_UI_PRIVATE_USERINTERFACE_P_H +#define ZYPP_NG_UI_PRIVATE_USERINTERFACE_P_H + +#include +#include +#include + +namespace zyppng { + + class UserInterfacePrivate : public BasePrivate + { + ZYPP_DECLARE_PUBLIC(UserInterface) + public: + UserInterfacePrivate( UserInterface &b ) : BasePrivate(b) {} + + Signal _sigEvent; + }; + +} + + +#endif diff --git a/zypp-core/zyppng/ui/progressobserver.cc b/zypp-core/zyppng/ui/progressobserver.cc new file mode 100644 index 0000000..309b819 --- /dev/null +++ b/zypp-core/zyppng/ui/progressobserver.cc @@ -0,0 +1,358 @@ +#include "progressobserver.h" +#include "zypp-core/AutoDispose.h" +#include +#include + +namespace zyppng { + + class ProgressObserverPrivate : public BasePrivate + { + ZYPP_DECLARE_PUBLIC(ProgressObserver) + public: + ProgressObserverPrivate( ProgressObserver &p ) : BasePrivate(p) {} + + + void updateProgress (); + void setLabel( const std::string &label ); + + + ProgressObserverWeakRef _parent; + std::string _label; + + // the current counter value + double _counterValue = 0; + + // the number of steps we are going to have + double _counterSteps = 0; + + // the value of all finished progresses + double _finishedValue = 0; + + // the steps of all finished progresses + double _finishedSteps = 0; + + int _baseValue = 0; + int _baseSteps = 100; + + bool _started = false; + bool _ignoreChildSigs = false; + + struct ChildInfo { + ChildInfo( std::vector &&conns, float weight ) : _signalConns( std::move(conns) ), _childWeight( weight ) {} + ChildInfo( ChildInfo &&other ) noexcept + : _signalConns( std::move(other._signalConns) ) + , _childWeight( other._childWeight ) + { + other._signalConns.clear (); + } + ChildInfo( const ChildInfo &other ) = delete; + ~ChildInfo() { + std::for_each( _signalConns.begin (), _signalConns.end(), []( auto &sig ){ sig.disconnect(); }); + } + + ChildInfo &operator=( const ChildInfo & ) = delete; + ChildInfo &operator=( ChildInfo &&other ) + { + _childWeight = other._childWeight; + _signalConns = std::move(other._signalConns); + other._signalConns.clear (); + return *this; + } + + std::vector _signalConns; + float _childWeight = 1.0; // the factor how much increase a step in the child is worth in the parent + }; + + std::vector _children; + std::vector< ChildInfo > _childInfo; + + void onChildStarted(ProgressObserver &); + void updateCounters(); + void onChildFinished( ProgressObserver &child , ProgressObserver::FinishResult ); + + Signal _sigStarted; + Signal _sigLabelChanged; + Signal _sigStepsChanged; + Signal _sigValueChanged; + Signal _sigProgressChanged; + Signal _sigFinished; + Signal _sigNewSubprogress; + }; + + ZYPP_IMPL_PRIVATE(ProgressObserver) + + void ProgressObserverPrivate::onChildStarted( ProgressObserver &/*child*/ ) + { + if ( !_started ) z_func()->start(); + } + + void ProgressObserverPrivate::updateCounters() + { + if ( _ignoreChildSigs ) + return; + + double currProgressSteps = _baseValue; + double accumSteps = static_cast(_baseSteps); + + for ( std::vector::size_type i = 0; i < _children.size (); i++ ) { + const auto childPtr = _children[i].get(); + const auto &childInfo = _childInfo[i]; + const auto weight = childInfo._childWeight; + currProgressSteps += childPtr->current() * weight; + accumSteps += childPtr->steps()* weight; + } + + bool notifyAccuMaxSteps = _counterSteps != accumSteps ; + bool notifyCurrSteps = _counterValue != currProgressSteps; + + _counterSteps = accumSteps; + _counterValue = currProgressSteps; + + if ( !_started ) + return; + + if ( notifyAccuMaxSteps ) + _sigStepsChanged.emit( *z_func(), _counterSteps ); + if ( notifyCurrSteps) { + _sigValueChanged.emit( *z_func(), notifyCurrSteps ); + _sigProgressChanged.emit( *z_func(), z_func()->progress() ); + } + } + + void ProgressObserverPrivate::onChildFinished(ProgressObserver &child, ProgressObserver::FinishResult ) + { + auto i = std::find_if( _children.begin (), _children.end (), [&]( const auto &elem ) { return ( &child == elem.get() ); } ); + if ( i == _children.end() ) { + WAR << "Unknown child sent a finished message, ignoring" << std::endl; + return; + } + + const auto idx = std::distance ( _children.begin (), i ); + _children.erase(i); + _childInfo.erase( _childInfo.begin () + idx ); + updateCounters(); + } + + ZYPP_IMPL_PRIVATE_CONSTR_ARGS ( ProgressObserver, const std::string &label, int steps ) : Base( *( new ProgressObserverPrivate( *this ) ) ) + { + Z_D(); + d->_baseSteps = steps; + d->_label = label; + d->updateCounters(); + } + + void ProgressObserverPrivate::setLabel(const std::string &label) + { + if ( _label == label ) + return; + _label = label; + _sigLabelChanged.emit ( *z_func(), label ); + } + + + int ProgressObserver::steps() const + { + return d_func()->_counterSteps; + } + + bool ProgressObserver::started() const + { + return d_func()->_started; + } + + void ProgressObserver::start() + { + Z_D(); + if ( d->_started ) + return; + + d->updateCounters(); + + d->_started = true; + d->_sigStarted.emit( *this ); + } + + void ProgressObserver::reset() + { + Z_D(); + { + zypp::DtorReset deferedReset( d->_ignoreChildSigs, false ); + d->_ignoreChildSigs = true; + std::for_each( d->_children.begin (), d->_children.end(), []( auto &child ) { child->reset(); }); + } + d->updateCounters(); + } + + double ProgressObserver::progress() const + { + return 100.0 * current() / steps(); + } + + double ProgressObserver::current() const + { + return d_func()->_counterValue; + } + + const std::vector &ProgressObserver::children() + { + return d_func()->_children; + } + + const std::string &ProgressObserver::label() const + { + return d_func()->_label; + } + + SignalProxy ProgressObserver::sigStarted() + { + return d_func()->_sigStarted; + } + + SignalProxy ProgressObserver::sigLabelChanged() + { + return d_func()->_sigLabelChanged; + } + + SignalProxy ProgressObserver::sigStepsChanged() + { + return d_func()->_sigStepsChanged; + } + + SignalProxy ProgressObserver::sigValueChanged() + { + return d_func()->_sigValueChanged; + } + + SignalProxy ProgressObserver::sigProgressChanged() + { + return d_func()->_sigProgressChanged; + } + + SignalProxy ProgressObserver::sigFinished() + { + return d_func()->_sigFinished; + } + + SignalProxy ProgressObserver::sigNewSubprogress() + { + return d_func()->_sigNewSubprogress; + } + + void ProgressObserver::setBaseSteps(int steps) + { + Z_D(); + if ( d->_baseSteps == steps ) + return; + + d->_baseSteps = steps; + + // update stats + d->updateCounters(); + } + + void ProgressObserver::setLabel(const std::string &label) + { + d_func()->setLabel( label ); + } + + void ProgressObserver::setCurrent(double curr) + { + Z_D(); + auto set = std::max(0, std::min( curr, d->_baseSteps ) ); + if ( set == d->_baseValue ) + return; + d->_baseValue = set; + + //update stats + d->updateCounters(); + } + + int ProgressObserver::baseSteps() const + { + return d_func()->_baseSteps; + } + + void ProgressObserver::setFinished( FinishResult result ) + { + Z_D(); + + // finish all children first, started children are removed via their finished signal + // others we have to manually remove + while ( d->_children.size() ) { + auto back = d->_children.back(); + bool remove = !back->started (); + back->setFinished( result ); + if ( remove ) d->_children.pop_back(); + } + + if ( result != Error ) + setCurrent( d->_baseSteps ); + + if ( d->_started ) + d->_sigFinished.emit( *this , result ); + } + + void ProgressObserver::inc( double inc, const std::optional &newLabel ) + { + setCurrent ( d_func()->_baseValue + inc ); + if ( newLabel ) setLabel ( *newLabel ); + } + + void ProgressObserver::registerSubTask( const ProgressObserverRef& child, float weight ) + { + Z_D(); + auto i = std::find( d->_children.begin(), d->_children.end(), child ); + const auto adjustedWeight = std::min( std::max( 0.0, weight ), 1.0 ); + if ( i != d->_children.end() ) { + const auto index = std::distance ( d->_children.begin (), i ); + d->_childInfo[index]._childWeight = adjustedWeight; + } else { + d->_children.push_back( child ); + d->_childInfo.push_back( { + { connectFunc ( *child, &ProgressObserver::sigStepsChanged, [this]( auto &sender, auto ){ d_func()->updateCounters(); }, *this ), + connectFunc ( *child, &ProgressObserver::sigValueChanged, [this]( auto &sender, auto ){ d_func()->updateCounters(); }, *this ), + connect ( *child, &ProgressObserver::sigStarted, *d, &ProgressObserverPrivate::onChildStarted ), + connect ( *child, &ProgressObserver::sigFinished, *d, &ProgressObserverPrivate::onChildFinished ) + } + , adjustedWeight + }); + d->_sigNewSubprogress.emit( *this, child ); + + // if the child has been started already, we also need to start() + if ( child->started () ) + start(); + } + + // update stats + d->updateCounters(); + } + + ProgressObserverRef ProgressObserver::makeSubTask( float weight, const std::string &label, int steps ) + { + auto r = ProgressObserver::create( label, steps ); + registerSubTask ( r, weight ); + return r; + } + + /*! + * Creates a new \ref zypp::ProgressData::ReceiverFnc and links it to the current ProgressObserver, + * this can be used to interface with zypp code that was not yet migrated to the new ProgressObserver + * API. + * + * \note the returned \ref zypp::ProgressData::ReceiverFnc will keep a reference to the \a ProgressObserver + */ + zypp::ProgressData::ReceiverFnc ProgressObserver::makeProgressDataReceiver() + { + return [ sThis = shared_this() ]( const zypp::ProgressData & data ){ + auto instance = sThis.get(); + instance->start(); + instance->setBaseSteps ( data.max () - data.min () ); + instance->setCurrent ( data.val () - data.min () ); + instance->setLabel ( data.name () ); + if ( data.finalReport() ) + instance->setFinished(); + return true; + }; + } + +} // namespace zyppng diff --git a/zypp-core/zyppng/ui/progressobserver.h b/zypp-core/zyppng/ui/progressobserver.h new file mode 100644 index 0000000..e13042d --- /dev/null +++ b/zypp-core/zyppng/ui/progressobserver.h @@ -0,0 +1,261 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPPNG_PROGRESSOBSERVER_H +#define ZYPPNG_PROGRESSOBSERVER_H + +#include +#include +#include +#include +#include + +// backwards compat +#include + + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS( ProgressObserver ); + class ProgressObserverPrivate; + + class ProgressObserver : public Base + { + ZYPP_DECLARE_PRIVATE(ProgressObserver) + ZYPP_ADD_CREATE_FUNC(ProgressObserver) + + public: + + enum FinishResult { + Success, + Error + }; + + ZYPP_DECL_PRIVATE_CONSTR_ARGS(ProgressObserver, const std::string &label = std::string(), int steps = 100 ); + + void setBaseSteps( int steps ); + int baseSteps ( ) const; + int steps ( ) const; + bool started ( ) const; + + /*! + * Tells the \ref ProgressObserver to start sending signals on updates. + * If start was not called, no progress update or finished signals are emitted. + * + * Calling start will also trigger all parent observers to be started, but not the children + */ + void start ( ); + void reset ( ); + void setCurrent ( double curr ); + void setFinished ( FinishResult result = Success ); + void inc ( double inc = 1.0, const std::optional &newLabel = {} ); + + double progress() const; + double current() const; + + + inline static ProgressObserverRef makeSubTask( ProgressObserverRef parentProgress, float weight = 1.0, const std::string &label = std::string(), int steps = 100 ) { + if ( parentProgress ) return parentProgress->makeSubTask( weight, label, steps ); + return nullptr; + } + + inline static void start ( ProgressObserverRef progress ) { + if ( progress ) progress->start(); + } + + inline static void setup( ProgressObserverRef progress, const std::string &label = std::string(), int steps = 100 ) { + if ( progress ) { + progress->setLabel( label ); + progress->setBaseSteps ( steps ); + } + } + + inline static void increase( ProgressObserverRef progress, double inc = 1.0, const std::optional &newLabel = {} ) { + if ( progress ) progress->inc ( inc, newLabel ); + } + + inline static void setCurrent ( ProgressObserverRef progress, double curr ) { + if ( progress ) progress->setCurrent ( curr ); + } + + inline static void setLabel ( ProgressObserverRef progress, const std::string &label ) { + if ( progress ) progress->setLabel ( label ); + } + + inline static void setSteps ( ProgressObserverRef progress, int steps ) { + if ( progress ) progress->setBaseSteps ( steps ); + } + + inline static void finish ( ProgressObserverRef progress, ProgressObserver::FinishResult result = ProgressObserver::Success ) { + if ( progress ) progress->setFinished ( result ); + } + + const std::vector &children(); + + void setLabel ( const std::string &label ); + const std::string &label () const; + + void registerSubTask ( const ProgressObserverRef& child, float weight = 1.0 ); + + ProgressObserverRef makeSubTask( float weight = 1.0 ,const std::string &label = std::string(), int steps = 100 ); + + zypp::ProgressData::ReceiverFnc makeProgressDataReceiver (); + + SignalProxy sigStarted (); + SignalProxy sigLabelChanged (); + SignalProxy sigStepsChanged(); + SignalProxy sigValueChanged(); + SignalProxy sigProgressChanged(); + SignalProxy sigFinished(); + SignalProxy sigNewSubprogress(); + + }; + + namespace operators { + + namespace detail { + + enum class progress_helper_mode { + Start, + Increase, + Set, + Finish + }; + + template + struct progress_helper { + + progress_helper( ProgressObserverRef &&progressObserver, std::optional &&newStr, double inc ) + : _progressObserver( std::move(progressObserver) ) + , _newString( std::move(newStr) ) + , _progressInc( inc ) + {} + + template + auto operator() ( T &&t ) { + update(); + return std::forward(t); + } + + void operator()() { + update(); + } + + void update() { + if ( _progressObserver ) { + if constexpr ( mode == progress_helper_mode::Increase ) { + _progressObserver->inc( _progressInc, _newString ); + } else { + _progressObserver->setCurrent ( _progressInc ); + if ( _newString ) + _progressObserver->setLabel ( *_newString ); + } + } + } + + private: + ProgressObserverRef _progressObserver; + std::optional _newString; + double _progressInc; + }; + + template <> + struct progress_helper + { + progress_helper( ProgressObserverRef &&progressObserver ) + : _progressObserver( std::move(progressObserver) ){} + + template + auto operator() ( T &&t ) { + update(); + return std::forward(t); + } + + void operator()() { + update(); + } + + void update() { + if ( _progressObserver ) { _progressObserver->start(); } + } + + private: + ProgressObserverRef _progressObserver; + }; + + template <> + struct progress_helper + { + progress_helper( ProgressObserverRef &&progressObserver, ProgressObserver::FinishResult result = ProgressObserver::Success ) + : _progressObserver( std::move(progressObserver) ) + , _result(result){} + + template + auto operator() ( T &&t ) { + update(); + return std::forward(t); + } + + void operator()() { + update(); + } + + void update() { + if ( _progressObserver ) { _progressObserver->setFinished( _result ); } + } + + private: + ProgressObserverRef _progressObserver; + ProgressObserver::FinishResult _result; + }; + } + + /*! + * Starts the the given \ref ProgressObserver, forwarding the pipeline value without touching it + */ + inline auto startProgress( ProgressObserverRef progressObserver ) { + return detail::progress_helper( std::move(progressObserver) ); + } + + /*! + * Increases the \ref ProgressObserver by the given \a progIncrease, forwarding the pipeline value without touching it. + * Can also set a new label via \a newStr + */ + inline auto incProgress( ProgressObserverRef progressObserver, double progrIncrease = 1.0, std::optional newStr = {} ) { + return detail::progress_helper( std::move(progressObserver), std::move(newStr), progrIncrease ); + } + + /*! + * Sets the current value in the given \ref ProgressObserver, forwarding the pipeline value without touching it + * Can also set a new label via \a newStr + */ + inline auto setProgress( ProgressObserverRef progressObserver, double progrValue, std::optional newStr = {} ) { + return detail::progress_helper( std::move(progressObserver), std::move(newStr), progrValue ); + } + + /*! + * Sets the label value in the given \ref ProgressObserver, forwarding the pipeline value without touching it + */ + inline auto setProgressLabel( ProgressObserverRef progressObserver, std::string newStr ) { + // use the Increase functor, it allows us to let the progress value untouched and just sets the strings + return detail::progress_helper( std::move(progressObserver), std::move(newStr), 0.0 ); + } + + /*! + * Sets the the given \ref ProgressObserver to finished, forwarding the pipeline value without touching it + */ + inline auto finishProgress( ProgressObserverRef progressObserver, ProgressObserver::FinishResult result = ProgressObserver::Success ) { + return detail::progress_helper( std::move(progressObserver), result ); + } + + + } + +} // namespace zyppng + +#endif // ZYPPNG_PROGRESSOBSERVER_H diff --git a/zypp-core/zyppng/ui/userinterface.cc b/zypp-core/zyppng/ui/userinterface.cc new file mode 100644 index 0000000..8d1b9bc --- /dev/null +++ b/zypp-core/zyppng/ui/userinterface.cc @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "private/userinterface_p.h" +#include + +namespace zyppng { + + ZYPP_IMPL_PRIVATE(UserInterface) + + ZYPP_IMPL_PRIVATE_CONSTR( UserInterface ) : Base ( *( new UserInterfacePrivate(*this) ) ) { } + + UserInterface::UserInterface( UserInterfacePrivate &d ) : Base(d) + { } + + void UserInterface::sendUserRequest(const UserRequestRef& event) + { + Z_D(); + d->_sigEvent.emit( event ); + } + + SignalProxy UserInterface::sigEvent() + { + return d_func()->_sigEvent; + } +} diff --git a/zypp-core/zyppng/ui/userinterface.h b/zypp-core/zyppng/ui/userinterface.h new file mode 100644 index 0000000..65986d3 --- /dev/null +++ b/zypp-core/zyppng/ui/userinterface.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_CORE_ZYPPNG_USERINTERFACE_H +#define ZYPP_CORE_ZYPPNG_USERINTERFACE_H + +#include +#include + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS( UserInterface ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( UserRequest ); + + class UserInterfacePrivate; + + /*! + * Generic code that allows libzypp to send messages and request + * directly to the user code. + * + * Every time a new request is sent the \ref UserInterface::sigEvent signal + * is emitted, which deliveres the specific request. Depending on the + * type of request the frontend code can return data to libzypp, for example + * if a user wants to trust a key, or a simple password request. + * + */ + class UserInterface : public Base + { + ZYPP_DECLARE_PRIVATE(UserInterface) + ZYPP_ADD_CREATE_FUNC(UserInterface) + + public: + ZYPP_DECL_PRIVATE_CONSTR(UserInterface); + void sendUserRequest( const UserRequestRef& event ); + SignalProxy sigEvent(); + + protected: + UserInterface( UserInterfacePrivate &d ); + }; + +} + +#endif diff --git a/zypp-core/zyppng/ui/userrequest.cc b/zypp-core/zyppng/ui/userrequest.cc new file mode 100644 index 0000000..320fe64 --- /dev/null +++ b/zypp-core/zyppng/ui/userrequest.cc @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "userrequest.h" +#include +#include + +namespace zyppng +{ + UserRequest::UserRequest( UserData userData ) + : _userData( std::move(userData) ) + { } + + UserRequest::~UserRequest() + { } + + const UserData &UserRequest::userData() const + { + return _userData; + } + + UserData &UserRequest::userData() + { + return _userData; + } + + ZYPP_IMPL_PRIVATE_CONSTR_ARGS(ShowMessageRequest, std::string message, MType mType, UserData data ) + : UserRequest( std::move(data) ) + , _type( mType ) + , _message( std::move(message) ) + { } + + UserRequestType ShowMessageRequest::type() const + { + return UserRequestType::Message; + } + + ShowMessageRequest::MType ShowMessageRequest::messageType() + { + return _type; + } + + const std::string &ShowMessageRequest::message() const + { + return _message; + } + + ZYPP_IMPL_PRIVATE_CONSTR_ARGS(ListChoiceRequest, std::string label, std::vector answers, index_type defaultAnswer, UserData userData ) + : UserRequest( std::move(userData) ) + , _label( std::move(label) ) + , _answers( std::move(answers) ) + , _answer( std::move(defaultAnswer) ) + , _default( std::move(defaultAnswer) ) + { } + + UserRequestType ListChoiceRequest::type() const + { + return UserRequestType::ListChoice; + } + + const std::string &ListChoiceRequest::label() const + { + return _label; + } + + void ListChoiceRequest::setChoice(const index_type sel ) + { + if ( sel >= _answers.size() ) + ZYPP_THROW( std::logic_error("Selection index is out of range") ); + _answer = sel; + } + + ListChoiceRequest::index_type ListChoiceRequest::choice() const + { + return _answer; + } + + ListChoiceRequest::index_type ListChoiceRequest::defaultAnswer() const + { + return _default; + } + + const std::vector &ListChoiceRequest::answers() const + { + return _answers; + } + + ZYPP_IMPL_PRIVATE_CONSTR_ARGS(BooleanChoiceRequest, std::string label, const bool defaultAnswer, UserData userData ) + : UserRequest( std::move(userData) ) + , _label( std::move(label) ) + , _answer( defaultAnswer ) + { } + + UserRequestType BooleanChoiceRequest::type() const + { + return UserRequestType::BooleanChoice; + } + + const std::string &BooleanChoiceRequest::label() const + { + return _label; + } + + void BooleanChoiceRequest::setChoice(const bool sel) + { + _answer = sel; + } + + bool BooleanChoiceRequest::choice() const + { + return _answer; + } + +} diff --git a/zypp-core/zyppng/ui/userrequest.h b/zypp-core/zyppng/ui/userrequest.h new file mode 100644 index 0000000..9f09497 --- /dev/null +++ b/zypp-core/zyppng/ui/userrequest.h @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_CORE_ZYPPNG_USERREQUEST_H +#define ZYPP_CORE_ZYPPNG_USERREQUEST_H + +#include +#include +#include +#include +namespace zyppng { + + using UserData = zypp::callback::UserData; + using ContentType = zypp::ContentType; + + + ZYPP_FWD_DECL_TYPE_WITH_REFS( UserRequest ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( ShowMessageRequest ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( ListChoiceRequest ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( BooleanChoiceRequest ); + + /* + constexpr std::string_view CTYPE_SHOW_MESSAGE_REQUEST ("userreq/show-message"); + constexpr std::string_view CTYPE_LIST_CHOICE_REQUEST ("userreq/list-choice"); + constexpr std::string_view CTYPE_BOOLEAN_COICE_REQUEST("userreq/boolean-choice"); + */ + + + enum class UserRequestType : uint { + Message, // simple message to the user, no input or predefined like y/n + ListChoice, // request to select from a list of options + BooleanChoice, // request user to say yes or no + KeyTrust, // request to the user to trust a key + Custom = 512 + }; + + /*! + * The UserRequest class provides a base object to send UI requests to the user, + * every time libzypp needs input from the User, a UserRequest is generated and sent + * via the \ref UserInterface to the user code, which can decide how to render the request, + * a CLI app would render a prompt, while a UI application likely would open a popup window. + */ + class UserRequest : public Base + { + public: + UserRequest( UserData userData = {} ); + ~UserRequest() override; + virtual UserRequestType type() const = 0; + const UserData &userData() const; + UserData &userData(); + + private: + UserData _userData; + }; + + + + /*! + * The ShowMessageRequest class represents a simple informal message that the code needs to + * print on the users screen + * + * \code + * context->sendUserRequest( ShowMessageRequest::create("Repository downloaded") ); + * \endcode + */ + class ShowMessageRequest : public UserRequest + { + ZYPP_ADD_CREATE_FUNC(ShowMessageRequest) + public: + + enum class MType { + Debug, Info, Warning, Error, Important, Data + }; + + ZYPP_DECL_PRIVATE_CONSTR_ARGS(ShowMessageRequest, std::string message, MType mType = MType::Info, UserData data = {} ); + UserRequestType type() const override; + + MType messageType(); + const std::string &message() const; + + private: + MType _type = MType::Info; + std::string _message; + }; + + + + /*! + * The ListChoice Request class represents a choice request to the user, + * the possible answers are given via a vector of possible choices. + * + * \code + * + * auto request = ListChoiceRequest::create( "Please select the choice you want: ", { {"y", "Info about y"}, {"n", "Info about n"}, {"d", "Info about d"} }, 1 ); + * context->sendUserRequest( request ); + * + * const auto choice = request->choice(); + * switch( choice ) { + * case 0: + * // handle 'y' choice + * break; + * case 1: + * // handle 'n' choice + * break; + * case 2: + * // handle 'd' choice + * break; + * default: + * // error, should not happen! + * break; + * } + * + * \endcode + */ + class ListChoiceRequest : public UserRequest + { + ZYPP_ADD_CREATE_FUNC(ListChoiceRequest) + public: + + struct Choice { + std::string opt; + std::string detail; + }; + + using index_type = std::vector::size_type; + + ZYPP_DECL_PRIVATE_CONSTR_ARGS(ListChoiceRequest, std::string label, std::vector answers, index_type defaultAnswer, UserData userData = {} ); + UserRequestType type() const override; + + const std::string &label() const; + + void setChoice ( const index_type sel ); + index_type choice() const; + + index_type defaultAnswer() const; + + const std::vector &answers() const; + + + private: + std::string _label; + std::vector _answers; + index_type _answer = 0; + index_type _default = 0; + }; + + + class BooleanChoiceRequest : public UserRequest + { + ZYPP_ADD_CREATE_FUNC(BooleanChoiceRequest) + + public: + ZYPP_DECL_PRIVATE_CONSTR_ARGS(BooleanChoiceRequest, std::string label, const bool defaultAnswer = false, UserData userData = {} ); + UserRequestType type() const override; + + const std::string &label() const; + + void setChoice ( const bool sel ); + bool choice() const; + + private: + std::string _label; + bool _answer = false; + + }; + +} + + +#endif diff --git a/zypp-curl/CMakeLists.txt b/zypp-curl/CMakeLists.txt new file mode 100644 index 0000000..412c775 --- /dev/null +++ b/zypp-curl/CMakeLists.txt @@ -0,0 +1,193 @@ +# Collect all files that may contain translatable texts +FILE( GLOB_RECURSE POT_FILE_DEPENDS RELATIVE ${LIBZYPP_SOURCE_DIR} "*.h" "*.cc" ) +SET( POT_FILE_DEPENDS_ZYPP_CURL ${POT_FILE_DEPENDS} PARENT_SCOPE ) + +INCLUDE_DIRECTORIES ( ${LIBZYPP_SOURCE_DIR} ) + +ADD_DEFINITIONS( -DLOCALEDIR="${CMAKE_INSTALL_PREFIX}/share/locale" -DTEXTDOMAIN="zypp" -DZYPP_DLL ) + +SET( zypp_curl_HEADERS + CurlConfig + curlconfig.h + ProxyInfo + proxyinfo.h + TransferSettings + transfersettings.h +) + +SET( zypp_curl_private_HEADERS + private/curlhelper_p.h +) + +SET( zypp_curl_SRCS + curlconfig.cc + proxyinfo.cc + curlhelper.cc + transfersettings.cc +) + +INSTALL( FILES ${zypp_curl_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-curl" ) + +SET( zypp_curl_auth_HEADERS + auth/CurlAuthData + auth/curlauthdata.h +) + +SET( zypp_curl_auth_private_HEADERS +) + +SET( zypp_curl_auth_SRCS + auth/curlauthdata.cc +) + +INSTALL( FILES ${zypp_curl_auth_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-curl/auth" ) + +IF( NOT DISABLE_LIBPROXY ) + SET(zypp_curl_proxyinfo_libproxy_SRCS proxyinfo/proxyinfolibproxy.cc) + SET(zypp_curl_proxyinfo_libproxy_HEADERS proxyinfo/ProxyInfoLibproxy proxyinfo/proxyinfolibproxy.h) +ENDIF( ) + +SET( zypp_curl_proxyinfo_SRCS + proxyinfo/proxyinfosysconfig.cc + ${zypp_curl_proxyinfo_libproxy_SRCS} +) + +SET( zypp_curl_proxyinfo_HEADERS + proxyinfo/proxyinfoimpl.h + proxyinfo/ProxyInfoSysconfig + proxyinfo/proxyinfosysconfig.h + ${zypp_curl_proxyinfo_libproxy_HEADERS} + proxyinfo/proxyinfos.h +) + +INSTALL( FILES ${zypp_curl_proxyinfo_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/zypp-curl/proxyinfo ) + +SET( zypp_curl_ng_network_SRCS + ng/network/curlmultiparthandler.cc + ng/network/downloader.cc + ng/network/downloadspec.cc + ng/network/mirrorcontrol.cc + ng/network/networkrequestdispatcher.cc + ng/network/networkrequesterror.cc + ng/network/request.cc +) + +SET( zypp_curl_ng_network_HEADERS + ng/network/curlmultiparthandler.h + ng/network/AuthData + ng/network/authdata.h + ng/network/Downloader + ng/network/downloader.h + ng/network/DownloadSpec + ng/network/downloadspec.h + ng/network/NetworkRequestDispatcher + ng/network/networkrequestdispatcher.h + ng/network/NetworkRequestError + ng/network/networkrequesterror.h + ng/network/Request + ng/network/request.h + ng/network/TransferSettings + ng/network/transfersettings.h +) + +SET( zypp_curl_ng_network_private_HEADERS + ng/network/private/downloader_p.h + ng/network/private/mediadebug_p.h + ng/network/private/mirrorcontrol_p.h + ng/network/private/networkrequestdispatcher_p.h + ng/network/private/networkrequesterror_p.h + ng/network/private/request_p.h + ng/network/private/downloaderstates/base_p.h + ng/network/private/downloaderstates/basicdownloader_p.h + ng/network/private/downloaderstates/detectmeta_p.h + ng/network/private/downloaderstates/final_p.h + ng/network/private/downloaderstates/initial_p.h + ng/network/private/downloaderstates/metalinkinfo_p.h + ng/network/private/downloaderstates/metalink_p.h + ng/network/private/downloaderstates/mirrorhandling_p.h + ng/network/private/downloaderstates/normal_p.h + ng/network/private/downloaderstates/preparemulti_p.h + ng/network/private/downloaderstates/rangedownloader_p.h + ng/network/private/downloaderstates/zck_p.h +) + +SET( zypp_curl_ng_network_private_SRCS + ng/network/private/downloaderstates/basicdownloader_p.cc + ng/network/private/downloaderstates/detectmeta_p.cc + ng/network/private/downloaderstates/final_p.cc + ng/network/private/downloaderstates/initial_p.cc + ng/network/private/downloaderstates/metalinkinfo_p.cc + ng/network/private/downloaderstates/metalink_p.cc + ng/network/private/downloaderstates/mirrorhandling_p.cc + ng/network/private/downloaderstates/normal_p.cc + ng/network/private/downloaderstates/preparemulti_p.cc + ng/network/private/downloaderstates/rangedownloader_p.cc + ng/network/private/downloaderstates/zck_p.cc +) + +# ng files are not installed yet +# INSTALL( FILES ${zypp_curl_ng_network_HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/zypp-curl/ng/network ) + +SET( zypp_curl_parser_HEADERS + parser/MediaBlockList + parser/mediablocklist.h + parser/metadatahelper.h + parser/MetaLinkParser + parser/metalinkparser.h + parser/ZsyncParser + parser/zsyncparser.h +) + +SET( zypp_curl_parser_private_HEADERS +) + +SET( zypp_curl_parser_SRCS + parser/mediablocklist.cc + parser/metadatahelper.cc + parser/metalinkparser.cc + parser/zsyncparser.cc +) + +INSTALL( FILES ${zypp_curl_parser_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-curl/parser" ) + + +SET( zypp_curl_lib_SRCS + ${zypp_curl_SRCS} + ${zypp_curl_auth_SRCS} + ${zypp_curl_ng_network_SRCS} + ${zypp_curl_parser_SRCS} + ${zypp_curl_proxyinfo_SRCS} + ${zypp_curl_ng_network_private_SRCS} +) +SET( zypp_curl_lib_HEADERS + ${zypp_curl_private_HEADERS} ${zypp_curl_HEADERS} + ${zypp_curl_auth_private_HEADERS} ${zypp_curl_auth_HEADERS} + ${zypp_curl_ng_network_HEADERS} ${zypp_curl_ng_network_private_HEADERS} + ${zypp_curl_parser_private_HEADERS} ${zypp_curl_parser_HEADERS} + ${zypp_curl_proxyinfo_HEADERS} +) + +# Default loggroup for all files +SET_LOGGROUP( "zypp-curl" $${zypp_curl_lib_SRCS} ) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +ADD_LIBRARY( zypp-curl STATIC ${zypp_curl_lib_SRCS} ${zypp_curl_lib_HEADERS} + ng/network/curlmultiparthandler.h ng/network/curlmultiparthandler.cc ) + +target_link_libraries( zypp-curl PRIVATE zypp_lib_compiler_flags ) +target_link_libraries( zypp-curl INTERFACE ${CURL_LIBRARIES} ) +target_link_libraries( zypp-curl INTERFACE ${LIBXML2_LIBRARIES} ) + +IF( NOT DISABLE_LIBPROXY ) + # required for dlload and dlclose + target_link_libraries( zypp-curl INTERFACE ${CMAKE_DL_LIBS} ) +ENDIF() diff --git a/zypp-curl/CurlConfig b/zypp-curl/CurlConfig new file mode 100644 index 0000000..e951c82 --- /dev/null +++ b/zypp-curl/CurlConfig @@ -0,0 +1 @@ +#include "curlconfig.h" diff --git a/zypp-curl/ProxyInfo b/zypp-curl/ProxyInfo new file mode 100644 index 0000000..3f6ba49 --- /dev/null +++ b/zypp-curl/ProxyInfo @@ -0,0 +1 @@ +#include "proxyinfo.h" diff --git a/zypp-curl/TransferSettings b/zypp-curl/TransferSettings new file mode 100644 index 0000000..5b45827 --- /dev/null +++ b/zypp-curl/TransferSettings @@ -0,0 +1 @@ +#include "transfersettings.h" diff --git a/zypp-curl/auth/CurlAuthData b/zypp-curl/auth/CurlAuthData new file mode 100644 index 0000000..f3bbe6b --- /dev/null +++ b/zypp-curl/auth/CurlAuthData @@ -0,0 +1 @@ +#include "curlauthdata.h" diff --git a/zypp-curl/auth/curlauthdata.cc b/zypp-curl/auth/curlauthdata.cc new file mode 100644 index 0000000..d464744 --- /dev/null +++ b/zypp-curl/auth/curlauthdata.cc @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/auth/curlauthdata.cc + * +*/ + +#include "curlauthdata.h" + +#include +#include +#include + +#include + + +using std::endl; + +namespace zypp::media { + + CurlAuthData::CurlAuthData() + : AuthData() + , _auth_type_str() + , _auth_type(CURLAUTH_NONE) + {} + + CurlAuthData::CurlAuthData(const AuthData & authData) + : AuthData(authData) + , _auth_type_str() + , _auth_type(CURLAUTH_NONE) + {} + + bool CurlAuthData::valid() const + { + return username().size() && password().size(); + } + + std::ostream & CurlAuthData::dumpOn( std::ostream & str ) const + { + AuthData::dumpOn(str) << endl + << " auth_type: " << _auth_type_str << " (" << _auth_type << ")"; + return str; + } + + long CurlAuthData::auth_type_str2long( std::string & auth_type_str ) + { + return auth_type_str2long( const_cast< const std::string &>(auth_type_str) ); + } + + long CurlAuthData::auth_type_str2long( const std::string & auth_type_str ) + { + curl_version_info_data *curl_info = curl_version_info(CURLVERSION_NOW); + + std::vector list; + std::vector::const_iterator it; + long auth_type = CURLAUTH_NONE; + + zypp::str::split(auth_type_str, std::back_inserter(list), ","); + + for(it = list.begin(); it != list.end(); ++it) + { + if(*it == "basic") + { + auth_type |= CURLAUTH_BASIC; + } + else + if(*it == "digest") + { + auth_type |= CURLAUTH_DIGEST; + } + else + if((curl_info && (curl_info->features & CURL_VERSION_NTLM)) && + (*it == "ntlm")) + { + auth_type |= CURLAUTH_NTLM; + } + else + if((curl_info && (curl_info->features & CURL_VERSION_SPNEGO)) && + (*it == "spnego" || *it == "negotiate")) + { + // there is no separate spnego flag for this auth type + auth_type |= CURLAUTH_GSSNEGOTIATE; + } + else + if((curl_info && (curl_info->features & CURL_VERSION_GSSNEGOTIATE)) && + (*it == "gssnego" || *it == "negotiate")) + { + auth_type |= CURLAUTH_GSSNEGOTIATE; + } + else + { + ZYPP_THROW(MediaException(str::Format(_("Unsupported HTTP authentication method '%s'")) % *it)); + } + } + + return auth_type; + } + + std::string CurlAuthData::auth_type_long2str(long auth_type) + { + std::list auth_list; + + if(auth_type & CURLAUTH_GSSNEGOTIATE) + auth_list.push_back("negotiate"); + + if(auth_type & CURLAUTH_NTLM) + auth_list.push_back("ntlm"); + + if(auth_type & CURLAUTH_DIGEST) + auth_list.push_back("digest"); + + if(auth_type & CURLAUTH_BASIC) + auth_list.push_back("basic"); + + return str::join(auth_list, ","); + } + + std::ostream & operator << (std::ostream & str, const CurlAuthData & auth_data) + { + auth_data.dumpOn(str); + return str; + } + +} diff --git a/zypp-curl/auth/curlauthdata.h b/zypp-curl/auth/curlauthdata.h new file mode 100644 index 0000000..b15af32 --- /dev/null +++ b/zypp-curl/auth/curlauthdata.h @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/auth/CurlAuthData + * +*/ +#ifndef ZYPP_CURL_AUTH_CURLAUTHDATA_H_INCLUDED +#define ZYPP_CURL_AUTH_CURLAUTHDATA_H_INCLUDED + +#include + +namespace zypp { + namespace media { + /** + * Curl HTTP authentication data. + */ + class ZYPP_API CurlAuthData : public AuthData { + public: + /** + * Default constructor. Initializes username and password to empty strings + * and authetication type to CURLAUTH_NONE. + */ + CurlAuthData(); + + CurlAuthData(const AuthData & authData); + + CurlAuthData(std::string & username, std::string & password, std::string & auth_type) + : AuthData(username,password), _auth_type_str(auth_type) + { + _auth_type = auth_type_str2long(auth_type); + } + + CurlAuthData(std::string & username, std::string & password, long auth_type) + : AuthData(username,password), _auth_type(auth_type) + { + _auth_type_str = auth_type_long2str(auth_type); + } + + /** + * Checks validity of authentication data. + * \return true if the object contains non-empty username, + * non-empty password, and specifies authentication type; false otherwise. + */ + bool valid() const override; + + /** + * Set HTTP authentication type(s) to use. + * \param comma separated list of HTTP authentication type names + */ + void setAuthType(std::string auth_type) + { + _auth_type_str = auth_type; _auth_type = auth_type_str2long(auth_type); + } + + /** + * Set HTTP authentication type(s) to use. + * \param HTTP authentication type as in long ORed form. + * \see curl.h for available auth types + */ + void setAuthType(long auth_type) + { + _auth_type = auth_type; + _auth_type_str = auth_type_long2str(auth_type); + } + + long authType() const { return _auth_type; } + std::string authTypeAsString() const { return _auth_type_str; } + + std::string getUserPwd() const { return username() + ":" + password(); } + + + /** + * Converts a string of comma separated list of authetication type names + * into a long of ORed CURLAUTH_* identifiers. + * The method also automatically leaves out any auth types declared + * not supported by curl_version_info(). + * + * \throws MediaException if an invalid authentication type name is + * encountered. + */ + static long auth_type_str2long( std::string & auth_type_str ); + static long auth_type_str2long( const std::string &auth_type_str ); + + /** + * Converts a long of ORed CURLAUTH_* identifiers into a string of comma + * separated list of authentication type names. + */ + static std::string auth_type_long2str(long auth_type); + + std::ostream & dumpOn( std::ostream & str ) const override; + + private: + std::string _auth_type_str; + long _auth_type; + }; + + using CurlAuthData_Ptr = shared_ptr; + std::ostream & operator << (std::ostream & str, const CurlAuthData & auth_data); + } +} + +#endif diff --git a/zypp-curl/curlconfig.cc b/zypp-curl/curlconfig.cc new file mode 100644 index 0000000..bfa14d7 --- /dev/null +++ b/zypp-curl/curlconfig.cc @@ -0,0 +1,185 @@ +#include +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +namespace zypp +{ + namespace media + { + + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CurlConfig::parseConfig + // METHOD TYPE : int + // + int CurlConfig::parseConfig(CurlConfig & config, const std::string & filename) + { + Pathname curlrcFile; + + if(filename.empty()) + { + // attempts to load .curlrc from the homedir + char *home = getenv("HOME"); + if(home) + curlrcFile = std::string( home ) + std::string( "/.curlrc" ); + } + else + curlrcFile = filename; + + PathInfo h_info(curlrcFile.dirname(), PathInfo::LSTAT); + PathInfo c_info(curlrcFile, PathInfo::LSTAT); + + if( h_info.isDir() && h_info.userMayRX() && + c_info.isFile() && c_info.userMayR() ) + { + MIL << "Going to parse " << curlrcFile << endl; + } + else + { + char buf[32] = ""; + WAR << "Not allowed to parse '" << curlrcFile + << "': dir/file owner: " << h_info.owner() << "/" << c_info.owner() + << ", process uid: " << getuid() + << " (" << (!getlogin_r(buf, 31) ? buf : "") << ")" << std::endl; + + return 1; + } + + std::ifstream inp(curlrcFile.c_str()); + for(iostr::EachLine in( inp ); in; in.next()) + { + std::string line = str::trim(*in); + + // skip empty lines and comments + if (line.empty()) + continue; + switch (line[0]) + { + case '#': + case '/': + case '\r': + case '\n': + case '*': + case '\0': + continue; + } + + // DBG << "line " << in.lineNo() << ": " << line << endl; // can't log passwords + + const char * beg = line.c_str(); + const char * cur = beg; + +// space, '=' and ':' are all valid separators in curlrc +#define ISSEP(x) (((x)=='=') || ((x) == ':') || isspace(x)) + + // skip leading dashes (they are optional) + while (*cur && *cur == '-') + cur++; + beg = cur; + + // skip non-separator characters + while (*cur && !ISSEP(*cur)) + cur++; + + std::string option(beg, cur - beg); + + // skip separator characters + while (*cur && ISSEP(*cur)) + cur++; + + // rewind to the end of the line + beg = cur; + while (*cur) + cur++; + + std::string value(beg, cur - beg); + + DBG << "GOT: " << option << endl; + + if (!value.empty()) + { + // quoted parameter + if (value[0] == '\"') + { + // remove the quotes + std::string::size_type pos = value.rfind('\"'); + bool cut_last = + pos == value.size() - 1 && pos > 1 && value[pos-1] != '\\'; + value = value.substr(1, + cut_last ? value.size() - 2 : value.size() - 1); + + // replace special characters: + pos = 0; + while ((pos = value.find('\\', pos)) != std::string::npos) + { + // just erase the backslash if it is found at the end + if (pos == value.size() - 1) + { + value = value.erase(pos, 1); + break; + } + + switch(value[pos+1]) + { + case 't': + value = value.replace(pos, 2, "\t"); + break; + case 'n': + value = value.replace(pos, 2, "\n"); + break; + case 'r': + value = value.replace(pos, 2, "\r"); + break; + case 'v': + value = value.replace(pos, 2, "\v"); + break; + case '\\': + value = value.erase(pos++, 1); + break; + default:; + value = value.erase(pos, 1); + } + } + } + + // DBG << "PARAM: " << value << endl; // can't log passwords + } + + CurlConfig::setParameter(config, option, value); + } // for EachLine in curlrc + + return 0; + } + + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CurlConfig::setParameter + // METHOD TYPE : int + // + int CurlConfig::setParameter(CurlConfig & config, + const std::string & option, + const std::string & value) + { + if (option == "proxy-user") + config.proxyuserpwd = value; + // add more curl config data here as they become needed + // else if (option == "foo") + else + DBG << "Ignoring option " << option << endl; + + return 0; + } + + + } // namespace media +} // namespace zypp diff --git a/zypp-curl/curlconfig.h b/zypp-curl/curlconfig.h new file mode 100644 index 0000000..a9c466c --- /dev/null +++ b/zypp-curl/curlconfig.h @@ -0,0 +1,57 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/CurlConfig +*/ +#ifndef ZYPP_CURL_CURLCONFIG_H_INCLUDED +#define ZYPP_CURL_CURLCONFIG_H_INCLUDED + +//#include +#include + +namespace zypp +{ + namespace media + { + + + /** + * Structure holding values of curlrc options. + */ + struct CurlConfig + { + public: + /** + * Parse a curlrc file and store the result in the \a config structure. + * + * \param config a CurlConfig structure + * \param filename path to the curlrc file. If empty, ~/.curlrc is used. + * \return 0 on success, 1 if problem occurs. + */ + static int parseConfig(CurlConfig & config, const std::string & filename = ""); + + /** + * Stores the \a value of the \a option in the \a config structure or + * logs an unknown option. + * + * \return 0 on success, 1 if problem occurs. + */ + static int setParameter(CurlConfig & config, + const std::string & option, + const std::string & value); + + public: + std::string proxyuserpwd; + // add more curl config data here as they become needed + }; + + + } // namespace media +} // namespace zypp + +#endif /*ZYPP_CURL_CURLCONFIG_H_INCLUDED*/ diff --git a/zypp-curl/curlhelper.cc b/zypp-curl/curlhelper.cc new file mode 100644 index 0000000..54fa7b9 --- /dev/null +++ b/zypp-curl/curlhelper.cc @@ -0,0 +1,530 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/curlhelper.cc + * +*/ +#include "private/curlhelper_p.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TRANSFER_TIMEOUT_MAX 60 * 60 + +using std::endl; +using namespace zypp; + +namespace zypp +{ + namespace env + { + const long & ZYPP_MEDIA_CURL_DEBUG() + { + static const long ret = [](){ + const char * env = getenv("ZYPP_MEDIA_CURL_DEBUG"); + return env && *env ? str::strtonum( env ) : 0; + }(); + return ret; + } + + int ZYPP_MEDIA_CURL_IPRESOLVE() + { + static int _v = [](){ + int ret = 0; + if ( const char * envp = getenv( "ZYPP_MEDIA_CURL_IPRESOLVE" ) ) { + WAR << "env set: $ZYPP_MEDIA_CURL_IPRESOLVE='" << envp << "'" << std::endl; + if ( strcmp( envp, "4" ) == 0 ) ret = 4; + else if ( strcmp( envp, "6" ) == 0 ) ret = 6; + } + return ret; + }(); + return _v; + } + } // namespace env +} // namespace zypp + +namespace internal +{ + +void globalInitCurlOnce() +{ + // function-level static <=> std::call_once + static bool once __attribute__ ((__unused__)) = ( [] { + MIL << "global_init libcurl: build version: (" << LIBCURL_VERSION << "), runtime version: (" << curl_version_info(CURLVERSION_NOW)->version << ") " << endl; + if ( curl_global_init( CURL_GLOBAL_ALL ) != 0 ) + WAR << "curl global init failed" << std::endl; + } (), true ); +} + +uint curlVersion() +{ + auto curlV = curl_version_info ( CURLVERSION_NOW ); + return curlV->version_num; +} + +int log_curl( CURL * curl, curl_infotype info, char * ptr, size_t len, void * max_lvl ) +{ + if ( max_lvl == nullptr ) + return 0; + + long maxlvl = *((long *)max_lvl); + const char * pfx = ""; + bool isContent = true; // otherwise it's data + switch( info ) + { + case CURLINFO_TEXT: if ( maxlvl < 1 ) return 0; pfx = "*"; break; + case CURLINFO_HEADER_IN: if ( maxlvl < 2 ) return 0; pfx = "<"; break; + case CURLINFO_HEADER_OUT: if ( maxlvl < 2 ) return 0; pfx = ">"; break; + case CURLINFO_SSL_DATA_IN: if ( maxlvl < 3 ) return 0; isContent = false; pfx = "<[SSL]"; break; + case CURLINFO_SSL_DATA_OUT: if ( maxlvl < 3 ) return 0; isContent = false; pfx = ">[SSL]"; break; + case CURLINFO_DATA_IN: if ( maxlvl < 3 ) return 0; isContent = false; pfx = "<[DTA]"; break; + case CURLINFO_DATA_OUT: if ( maxlvl < 3 ) return 0; isContent = false; pfx = ">[DTA]"; break; + + default: + return 0; + } + + // We'd like to keep all log messages within function `log_curl` + // because this tag to grep for is known and communicate to users. + if ( isContent ) { + std::vector lines; // don't want log from within the lambda + strv::split( std::string_view( ptr, len ), "\n", [&lines]( std::string_view line, unsigned, bool last ) { + if ( last ) return; // empty word after final \n + line = strv::rtrim( line, "\r" ); + lines.push_back( line ); + }); + for ( const auto & line : lines ) { + if ( str::hasPrefix( line, "Authorization:" ) ) { + std::string_view::size_type pos { line.find( " ", 15 ) }; // Authorization: + if ( pos == std::string::npos ) + pos = 15; + DBG << curl << " " << pfx << " " << line.substr( 0, pos ) << " " << endl; + } + else + DBG << curl << " " << pfx << " " << line << endl; + } + } else { + if ( maxlvl < 4 ) + DBG << curl << " " << pfx << " " << len << " byte" << endl; + else + hexdumpOn( DBG << curl << " " << pfx << " ", ptr, len ); + } + return 0; +} + +void setupZYPP_MEDIA_CURL_DEBUG( CURL *curl ) +{ + if ( not curl ) { + INT << "Got a NULL curl handle" << endl; + return; + } + if ( env::ZYPP_MEDIA_CURL_DEBUG() > 0 ) { + curl_easy_setopt( curl, CURLOPT_VERBOSE, 1L ); + curl_easy_setopt( curl, CURLOPT_DEBUGFUNCTION, log_curl ); + curl_easy_setopt( curl, CURLOPT_DEBUGDATA, &env::ZYPP_MEDIA_CURL_DEBUG() ); + } +} + +size_t log_redirects_curl( char *ptr, size_t size, size_t nmemb, void *userdata) +{ + //INT << "got header: " << std::string(ptr, ptr + size*nmemb) << endl; + + char * lstart = ptr, * lend = ptr; + size_t pos = 0; + size_t max = size * nmemb; + while (pos + 1 < max) + { + // get line + for (lstart = lend; *lend != '\n' && pos < max; ++lend, ++pos); + + // look for "Location" + if ( strncasecmp( lstart, "Location:", 9 ) == 0 ) + { + std::string line { lstart, *(lend-1)=='\r' ? lend-1 : lend }; + DBG << "redirecting to " << line << std::endl; + if ( userdata ) { + *reinterpret_cast( userdata ) = line; + } + return max; + } + + // continue with the next line + if (pos + 1 < max) + { + ++lend; + ++pos; + } + else + break; + } + + return max; +} + +/** + * Fills the settings structure using options passed on the url + * for example ?timeout=x&proxy=foo + */ +void fillSettingsFromUrl( const Url &url, media::TransferSettings &s ) +{ + { + const std::string & param { url.getQueryParam("timeout") }; + if( ! param.empty() ) + { + long num = str::strtonum(param); + if( num >= 0 && num <= TRANSFER_TIMEOUT_MAX ) + s.setTimeout( num ); + } + } + { + std::string param { url.getUsername() }; + if ( ! param.empty() ) + { + s.setUsername( std::move(param) ); + param = url.getPassword(); + if ( ! param.empty() ) + s.setPassword( std::move(param) ); + } + else + { + // if there is no username, set anonymous auth + if ( ( url.getScheme() == "ftp" || url.getScheme() == "tftp" ) && s.username().empty() ) + s.setAnonymousAuth(); + } + } + if ( url.getScheme() == "https" ) + { + s.setVerifyPeerEnabled( false ); + s.setVerifyHostEnabled( false ); + + const std::string & verify { url.getQueryParam("ssl_verify") }; + if( verify.empty() || verify == "yes" ) + { + s.setVerifyPeerEnabled( true ); + s.setVerifyHostEnabled( true ); + } + else if ( verify == "no" ) + { + s.setVerifyPeerEnabled( false ); + s.setVerifyHostEnabled( false ); + } + else + { + std::vector flags; + str::split( verify, std::back_inserter(flags), "," ); + for ( const auto & flag : flags ) + { + if ( flag == "host" ) + s.setVerifyHostEnabled( true ); + else if ( flag == "peer" ) + s.setVerifyPeerEnabled( true ); + else + ZYPP_THROW( media::MediaBadUrlException(url, "Unknown ssl_verify flag "+flag) ); + } + } + } + { + Pathname ca_path { url.getQueryParam("ssl_capath") }; + if( ! ca_path.empty() ) + { + if( ! PathInfo(ca_path).isDir() || ! ca_path.absolute() ) + ZYPP_THROW(media::MediaBadUrlException(url, "Invalid ssl_capath path")); + else + s.setCertificateAuthoritiesPath( std::move(ca_path) ); + } + } + { + Pathname client_cert { url.getQueryParam("ssl_clientcert") }; + if( ! client_cert.empty() ) + { + if( ! PathInfo(client_cert).isFile() || ! client_cert.absolute() ) + ZYPP_THROW(media::MediaBadUrlException(url, "Invalid ssl_clientcert file")); + else + s.setClientCertificatePath( std::move(client_cert) ); + } + } + { + Pathname client_key { url.getQueryParam("ssl_clientkey") }; + if( ! client_key.empty() ) + { + if( ! PathInfo(client_key).isFile() || ! client_key.absolute() ) + ZYPP_THROW(media::MediaBadUrlException(url, "Invalid ssl_clientkey file")); + else + s.setClientKeyPath( std::move(client_key) ); + } + } + { + std::string param { url.getQueryParam( "proxy" ) }; + if ( ! param.empty() ) + { + if ( param == EXPLICITLY_NO_PROXY ) { + // Workaround TransferSettings shortcoming: With an + // empty proxy string, code will continue to look for + // valid proxy settings. So set proxy to some non-empty + // string, to indicate it has been explicitly disabled. + s.setProxy(EXPLICITLY_NO_PROXY); + s.setProxyEnabled(false); + } + else { + const std::string & proxyport { url.getQueryParam( "proxyport" ) }; + if ( ! proxyport.empty() ) { + param += ":"; + param += proxyport; + } + s.setProxy( std::move(param) ); + s.setProxyEnabled( true ); + } + } + } + { + std::string param { url.getQueryParam( "proxyuser" ) }; + if ( ! param.empty() ) + { + s.setProxyUsername( std::move(param) ); + s.setProxyPassword( url.getQueryParam( "proxypass" ) ); + } + } + { + // HTTP authentication type + std::string param { url.getQueryParam("auth") }; + if ( ! param.empty() && (url.getScheme() == "http" || url.getScheme() == "https") ) + { + try + { + media::CurlAuthData::auth_type_str2long (param ); // check if we know it + } + catch ( const media::MediaException & ex_r ) + { + DBG << "Rethrowing as MediaUnauthorizedException."; + ZYPP_THROW(media::MediaUnauthorizedException(url, ex_r.msg(), "", "")); + } + s.setAuthType( std::move(param) ); + } + } + { + // workarounds + const std::string & param { url.getQueryParam("head_requests") }; + if( ! param.empty() && param == "no" ) + s.setHeadRequestsAllowed( false ); + } +} + +/** + * Reads the system proxy configuration and fills the settings + * structure proxy information + */ +void fillSettingsSystemProxy( const Url& url, media::TransferSettings &s ) +{ + media::ProxyInfo proxy_info; + if ( proxy_info.useProxyFor( url ) ) + { + // We must extract any 'user:pass' from the proxy url + // otherwise they won't make it into curl (.curlrc wins). + try { + Url u( proxy_info.proxy( url ) ); + s.setProxy( u.asString( url::ViewOption::WITH_SCHEME + url::ViewOption::WITH_HOST + url::ViewOption::WITH_PORT ) ); + // don't overwrite explicit auth settings + if ( s.proxyUsername().empty() ) + { + s.setProxyUsername( u.getUsername( url::E_ENCODED ) ); + s.setProxyPassword( u.getPassword( url::E_ENCODED ) ); + } + s.setProxyEnabled( true ); + } + catch (...) {} // no proxy if URL is malformed + } +} + +void curlEscape( std::string & str_r, + const char char_r, const std::string & escaped_r ) { + for ( std::string::size_type pos = str_r.find( char_r ); + pos != std::string::npos; pos = str_r.find( char_r, pos ) ) { + str_r.replace( pos, 1, escaped_r ); + } +} + +std::string curlEscapedPath( std::string path_r ) { + curlEscape( path_r, ' ', "%20" ); + return path_r; +} + +std::string curlUnEscape( const std::string& text_r ) { + char * tmp = curl_unescape( text_r.c_str(), 0 ); + std::string ret( tmp ); + curl_free( tmp ); + return ret; +} + +Url clearQueryString(const Url &url) +{ + Url curlUrl (url); + curlUrl.setUsername( "" ); + curlUrl.setPassword( "" ); + curlUrl.setPathParams( "" ); + curlUrl.setFragment( "" ); + curlUrl.delQueryParam("cookies"); + curlUrl.delQueryParam("proxy"); + curlUrl.delQueryParam("proxyport"); + curlUrl.delQueryParam("proxyuser"); + curlUrl.delQueryParam("proxypass"); + curlUrl.delQueryParam("ssl_capath"); + curlUrl.delQueryParam("ssl_verify"); + curlUrl.delQueryParam("ssl_clientcert"); + curlUrl.delQueryParam("ssl_clientkey"); + curlUrl.delQueryParam("timeout"); + curlUrl.delQueryParam("auth"); + curlUrl.delQueryParam("username"); + curlUrl.delQueryParam("password"); + curlUrl.delQueryParam("mediahandler"); + curlUrl.delQueryParam("credentials"); + curlUrl.delQueryParam("head_requests"); + return curlUrl; +} + +// bsc#933839: propagate proxy settings passed in the repo URL +// boo#1127591: propagate ssl settings passed in the repo URL +zypp::Url propagateQueryParams( zypp::Url url_r, const zypp::Url & template_r ) +{ + using namespace std::literals::string_literals; + for ( const std::string ¶m : { "proxy"s, "proxyport"s, "proxyuser"s, "proxypass"s, "ssl_capath"s, "ssl_verify"s } ) + { + const std::string & value( template_r.getQueryParam( param ) ); + if ( ! value.empty() ) + url_r.setQueryParam( param, value ); + } + return url_r; +} + +CurlPollHelper::CurlPollHelper(CurlPoll &p) : _parent(p) { + curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETFUNCTION, socketcb ); + curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETDATA, this ); + curl_multi_setopt( _parent._multi, CURLMOPT_TIMERFUNCTION, timercb ); + curl_multi_setopt( _parent._multi, CURLMOPT_TIMERDATA, this ); +} + +CurlPollHelper::~CurlPollHelper() { + curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETFUNCTION, nullptr ); + curl_multi_setopt( _parent._multi, CURLMOPT_SOCKETDATA, nullptr ); + curl_multi_setopt( _parent._multi, CURLMOPT_TIMERFUNCTION, nullptr ); + curl_multi_setopt( _parent._multi, CURLMOPT_TIMERDATA, nullptr ); +} + +int CurlPollHelper::socketcb(CURL *easy, curl_socket_t s, int what, CurlPollHelper *userp, void *sockp) { + auto it = std::find_if( userp->socks.begin(), userp->socks.end(), [&]( const GPollFD &fd){ return fd.fd == s; }); + gushort events = 0; + if ( what == CURL_POLL_REMOVE ) { + if ( it == userp->socks.end() ) { + WAR << "Ignoring unknown socket in static_socketcb" << std::endl; + return 0; + } + userp->socks.erase(it); + return 0; + } else if ( what == CURL_POLL_IN ) { + events = G_IO_IN | G_IO_HUP | G_IO_ERR; + } else if ( what == CURL_POLL_OUT ) { + events = G_IO_OUT | G_IO_ERR; + } else if ( what == CURL_POLL_INOUT ) { + events = G_IO_IN | G_IO_OUT | G_IO_HUP | G_IO_ERR; + } + + if ( it != userp->socks.end() ) { + it->events = events; + it->revents = 0; + } else { + userp->socks.push_back( + GPollFD{ + .fd = s, + .events = events, + .revents = 0 + } + ); + } + return 0; +} + +int CurlPollHelper::timercb(CURLM *, long timeout_ms, CurlPollHelper *thatPtr) { + if ( !thatPtr ) + return 0; + if ( timeout_ms == -1 ) + thatPtr->timeout_ms.reset(); // curl wants to delete its timer + else + thatPtr->timeout_ms = timeout_ms; // maximum time curl wants us to sleep + return 0; +} + +CURLMcode internal::CurlPollHelper::handleSocketActions( const std::vector &actionsFds , int first ) +{ + for ( int sock = first; sock < actionsFds.size(); sock++ ) { + const auto &waitFd = actionsFds[sock]; + if ( waitFd.revents == 0 ) + continue; + + int ev = 0; + if ( (waitFd.revents & G_IO_HUP) == G_IO_HUP + || (waitFd.revents & G_IO_IN) == G_IO_IN ) { + ev = CURL_CSELECT_IN; + } + if ( (waitFd.revents & G_IO_OUT) == G_IO_OUT ) { + ev |= CURL_CSELECT_OUT; + } + if ( (waitFd.revents & G_IO_ERR) == G_IO_ERR ) { + ev |= CURL_CSELECT_ERR; + } + + int runn = 0; + CURLMcode mcode = curl_multi_socket_action( _parent._multi, waitFd.fd, ev, &runn ); + if (mcode != CURLM_OK) + return mcode; + } + return CURLM_OK; +} + +CURLMcode internal::CurlPollHelper::handleTimout() +{ + int handles = 0; + return curl_multi_socket_action( _parent._multi, CURL_SOCKET_TIMEOUT, 0, &handles ); +} + +/*! + * Enables the redirection protocols that we support, this code is a bit ugly + * because for newer versions we need to detect the current curl version at runtime, but at the same + * time need the compile time switch in case we are built against a older libcurl version. + * + * Reason for this is that we do not explicitely require the libcurl version we are built against, + * this could mean we are ending up with a libcurl older than the one we built against. + * + * See bsc#1218831 + */ +CURLcode setCurlRedirProtocols(CURL *curl) +{ +#if CURLVERSION_AT_LEAST(7,19,4) +#if CURLVERSION_AT_LEAST(7,85,0) + // runtime version might be different from build version + if( ::internal::curlVersion() >= CURL_VERSION_BITS(7,85,0) ) { + return curl_easy_setopt ( curl, CURLOPT_REDIR_PROTOCOLS_STR, "https" ); + } else { + return curl_easy_setopt ( curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS ); + } +#else + return curl_easy_setopt ( curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTPS ); +#endif +#endif // #if CURLVERSION_AT_LEAST(7,19,4) + return CURLE_OK; +} + +} diff --git a/zypp-curl/ng/network/AuthData b/zypp-curl/ng/network/AuthData new file mode 100644 index 0000000..30f2bac --- /dev/null +++ b/zypp-curl/ng/network/AuthData @@ -0,0 +1 @@ +#include "authdata.h" diff --git a/zypp-curl/ng/network/DownloadSpec b/zypp-curl/ng/network/DownloadSpec new file mode 100644 index 0000000..0902f3c --- /dev/null +++ b/zypp-curl/ng/network/DownloadSpec @@ -0,0 +1 @@ +#include "downloadspec.h" diff --git a/zypp-curl/ng/network/Downloader b/zypp-curl/ng/network/Downloader new file mode 100644 index 0000000..fb93454 --- /dev/null +++ b/zypp-curl/ng/network/Downloader @@ -0,0 +1 @@ +#include "downloader.h" diff --git a/zypp-curl/ng/network/MirrorControl b/zypp-curl/ng/network/MirrorControl new file mode 100644 index 0000000..ccb180e --- /dev/null +++ b/zypp-curl/ng/network/MirrorControl @@ -0,0 +1 @@ +#include "mirrorcontrol.h" diff --git a/zypp-curl/ng/network/NetworkRequestDispatcher b/zypp-curl/ng/network/NetworkRequestDispatcher new file mode 100644 index 0000000..6c7f0ed --- /dev/null +++ b/zypp-curl/ng/network/NetworkRequestDispatcher @@ -0,0 +1 @@ +#include "networkrequestdispatcher.h" diff --git a/zypp-curl/ng/network/NetworkRequestError b/zypp-curl/ng/network/NetworkRequestError new file mode 100644 index 0000000..d2b752b --- /dev/null +++ b/zypp-curl/ng/network/NetworkRequestError @@ -0,0 +1 @@ +#include "networkrequesterror.h" diff --git a/zypp-curl/ng/network/Request b/zypp-curl/ng/network/Request new file mode 100644 index 0000000..2b671df --- /dev/null +++ b/zypp-curl/ng/network/Request @@ -0,0 +1 @@ +#include "request.h" diff --git a/zypp-curl/ng/network/TransferSettings b/zypp-curl/ng/network/TransferSettings new file mode 100644 index 0000000..5b45827 --- /dev/null +++ b/zypp-curl/ng/network/TransferSettings @@ -0,0 +1 @@ +#include "transfersettings.h" diff --git a/zypp-curl/ng/network/authdata.h b/zypp-curl/ng/network/authdata.h new file mode 100644 index 0000000..c9d9db7 --- /dev/null +++ b/zypp-curl/ng/network/authdata.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_MEDIA_NETWORK_AUTHDATA_H_INCLUDED +#define ZYPPNG_MEDIA_NETWORK_AUTHDATA_H_INCLUDED + +#include + +namespace zyppng { + +using AuthData = zypp::media::AuthData; +using AuthData_Ptr = zypp::media::AuthData_Ptr; + +using NetworkAuthData = zypp::media::CurlAuthData; +using NetworkAuthData_Ptr = zypp::media::CurlAuthData_Ptr; + +} + + + + +#endif diff --git a/zypp-curl/ng/network/curlmultiparthandler.cc b/zypp-curl/ng/network/curlmultiparthandler.cc new file mode 100644 index 0000000..39731c2 --- /dev/null +++ b/zypp-curl/ng/network/curlmultiparthandler.cc @@ -0,0 +1,728 @@ +#include "curlmultiparthandler.h" + +#include +#include + +#include + +#include + +namespace zyppng { + + namespace { + + class CurlMultiPartSetoptError : public zypp::Exception + { + public: + CurlMultiPartSetoptError ( CURLcode code ) : _code(code){}; + CURLcode code() const; + private: + CURLcode _code; + }; + + CURLcode CurlMultiPartSetoptError::code() const { + return _code; + } + + class CurlMultInitRangeError : public zypp::Exception + { + public: + CurlMultInitRangeError ( std::string what ) : zypp::Exception( std::move(what) ){} + }; + + } + + size_t CurlMultiPartHandler::curl_hdrcallback(char *ptr, size_t size, size_t nmemb, void *userdata) + { + if ( !userdata ) + return 0; + + CurlMultiPartHandler *that = reinterpret_cast( userdata ); + return that->hdrcallback( ptr, size, nmemb ); + } + + size_t CurlMultiPartHandler::curl_wrtcallback(char *ptr, size_t size, size_t nmemb, void *userdata) + { + if ( !userdata ) + return 0; + + CurlMultiPartHandler *that = reinterpret_cast( userdata ); + return that->wrtcallback( ptr, size, nmemb ); + } + + void CurlMultiPartHandler::Range::restart() + { + _rangeState = CurlMultiPartHandler::Pending; + bytesWritten = 0; + if ( _digest ) _digest->reset(); + } + + CurlMultiPartHandler::Range CurlMultiPartHandler::Range::clone() const + { + return Range { + .start = start, + .len = len, + .bytesWritten = 0, + ._digest = _digest ? _digest->clone() : std::optional{}, + ._checksum = _checksum, + ._relevantDigestLen = _relevantDigestLen, + ._chksumPad = _chksumPad, + .userData = userData, + ._rangeState = _rangeState + }; + } + + CurlMultiPartHandler::Range CurlMultiPartHandler::Range::make(size_t start, size_t len, std::optional &&digest, CheckSumBytes &&expectedChkSum, std::any &&userData, std::optional digestCompareLen, std::optional dataBlockPadding) + { + return Range { + .start = start, + .len = len, + .bytesWritten = 0, + ._digest = std::move( digest ), + ._checksum = std::move( expectedChkSum ), + ._relevantDigestLen = std::move( digestCompareLen ), + ._chksumPad = std::move( dataBlockPadding ), + .userData = std::move( userData ), + ._rangeState = State::Pending + }; + } + + CurlMultiPartHandler::CurlMultiPartHandler(ProtocolMode mode, void *easyHandle, std::vector &ranges, CurlMultiPartDataReceiver &receiver) + : _protocolMode( mode ) + , _easyHandle( easyHandle ) + , _receiver( receiver ) + , _requestedRanges( ranges ) + { + // non http can only do range by range + if ( _protocolMode == ProtocolMode::Basic ) { + WAR << "!!!! Downloading ranges without HTTP might be slow !!!!" << std::endl; + _rangeAttemptIdx = _rangeAttemptSize - 1; + } + } + + CurlMultiPartHandler::~CurlMultiPartHandler() + { + if ( _easyHandle ) { + curl_easy_setopt( _easyHandle, CURLOPT_HEADERFUNCTION, nullptr ); + curl_easy_setopt( _easyHandle, CURLOPT_HEADERDATA, nullptr ); + curl_easy_setopt( _easyHandle, CURLOPT_WRITEFUNCTION, nullptr ); + curl_easy_setopt( _easyHandle, CURLOPT_WRITEDATA, nullptr ); + } + } + + size_t CurlMultiPartHandler::hdrcallback(char *ptr, size_t size, size_t nmemb) + { + // it is valid to call this function with no data to read, just call the given handler + // or return ok + if ( size * nmemb == 0) + return _receiver.headerfunction( ptr, size * nmemb ); + + if ( _protocolMode == ProtocolMode::HTTP ) { + + std::string_view hdr( ptr, size*nmemb ); + + hdr.remove_prefix( std::min( hdr.find_first_not_of(" \t\r\n"), hdr.size() ) ); + const auto lastNonWhitespace = hdr.find_last_not_of(" \t\r\n"); + if ( lastNonWhitespace != hdr.npos ) + hdr.remove_suffix( hdr.size() - (lastNonWhitespace + 1) ); + else + hdr = std::string_view(); + + // we just received whitespaces, wait for more + if ( !hdr.size() ) { + return ( size * nmemb ); + } + + if ( zypp::strv::hasPrefixCI( hdr, "HTTP/" ) ) { + + long statuscode = 0; + (void)curl_easy_getinfo( _easyHandle, CURLINFO_RESPONSE_CODE, &statuscode); + + const auto &doRangeFail = [&](){ + WAR << _easyHandle << " " << "Range FAIL, trying with a smaller batch" << std::endl; + + setCode ( Code::RangeFail, "Expected range status code 206, but got none." ); + + // reset all ranges we requested to pending, we never got the data for them + std::for_each( _requestedRanges.begin (), _requestedRanges.end(), []( auto &range ) { + if ( range._rangeState == Running ) + range._rangeState = Pending; + }); + return 0; + }; + + // ignore other status codes, maybe we are redirected etc. + if ( ( statuscode >= 200 && statuscode <= 299 && statuscode != 206 ) + || statuscode == 416 ) { + return doRangeFail(); + } + + } else if ( zypp::strv::hasPrefixCI( hdr, "Content-Range:") ) { + Range r; + + size_t fileLen = 0; + if ( !parseContentRangeHeader( hdr, r.start, r.len, fileLen ) ) { + //@TODO shouldn't we map this to a extra error? After all this is not our fault + setCode( Code::InternalError, "Invalid Content-Range header format." ); + return 0; + } + + if ( !_reportedFileSize ) { + WAR << "Setting request filesize to " << fileLen << std::endl; + _reportedFileSize = fileLen; + } + + DBG << _easyHandle << " " << "Got content range :" << r.start << " len " << r.len << std::endl; + _gotContentRangeInfo = true; + _currentSrvRange = std::move(r); + + } else if ( zypp::strv::hasPrefixCI( hdr, "Content-Type:") ) { + std::string sep; + if ( parseContentTypeMultiRangeHeader( hdr, sep ) ) { + _gotContentRangeInfo = true; + _isMuliPartResponse = true; + _seperatorString = "--"+sep; + } + } + } + + return _receiver.headerfunction( ptr, size * nmemb ); + } + + size_t CurlMultiPartHandler::wrtcallback(char *ptr, size_t size, size_t nmemb) + { + const auto max = ( size * nmemb ); + + //it is valid to call this function with no data to write, just call the given handler + if ( max == 0) + return _receiver.writefunction( ptr, {}, max ); + + // try to consume all bytes that have been given to us + size_t bytesConsumedSoFar = 0; + while ( bytesConsumedSoFar != max ) { + + std::optional seekTo; + + // this is called after all headers have been processed + if ( !_allHeadersReceived ) { + _allHeadersReceived = true; + + // no ranges at all, this is a error + if ( _protocolMode == ProtocolMode::HTTP && !_gotContentRangeInfo ) { + //we got a invalid response, the status code pointed to being partial ( 206 ) but we got no range definition + setCode( Code::ServerReturnedError, "Invalid data from server, range respone was announced but there was no range definiton." ); + return 0; + } + } + + if ( _protocolMode == ProtocolMode::HTTP && _currentSrvRange && !_currentRange ) { + /* + this branch is responsible to find a range that overlaps the current server range, so we know which of our ranges to fill + Entering here means we are in one of two situations: + + 1) we just have finished writing a requested range but + still have not completely consumed a range that we have received from the server. + Since HTTP std allows the server to coalesce requested ranges in order to optimize downloads + we need to find the best match ( because the current offset might not even be in our requested ranges ) + + 2) we just parsed a Content-Length header and start a new block + */ + + std::optional foundRange; + const size_t beginSrvRange = _currentSrvRange->start + _currentSrvRange->bytesWritten; + const size_t endSrvRange = beginSrvRange + (_currentSrvRange->len - _currentSrvRange->bytesWritten); + auto currDist = ULONG_MAX; + for ( uint i = 0; i < _requestedRanges.size(); i++ ) { + const auto &currR = _requestedRanges[i]; + + // do not allow double ranges + if ( currR._rangeState == Finished || currR._rangeState == Error ) + continue; + + // check if the range was already written + if ( currR.len && currR.len == currR.bytesWritten ) + continue; + + const auto currRBegin = currR.start + currR.bytesWritten; + if ( !( beginSrvRange <= currRBegin && endSrvRange >= currRBegin ) ) + continue; + + // calculate the distance of the current ranges offset+data written to the range we got back from the server + const auto newDist = currRBegin - beginSrvRange; + + // exact match + if ( currRBegin == beginSrvRange && currR.len == _currentSrvRange->len ) { + foundRange = i; + break; + } + + if ( !foundRange ) { + foundRange = i; + currDist = newDist; + } else { + //pick the range with the closest distance + if ( newDist < currDist ) { + foundRange = i; + currDist = newDist; + } + } + } + + if ( !foundRange ) { + // @TODO shouldn't we simply consume the rest of the range here and see if future data will contain a matchable range again? + setCode( Code::InternalError, "Unable to find a matching range for data returned by the server."); + return 0; + } + + //set the found range as the current one + _currentRange = *foundRange; + + //continue writing where we stopped + seekTo = _requestedRanges[*foundRange].start + _requestedRanges[*foundRange].bytesWritten; + + //if we skip bytes we need to advance our written bytecount + const auto skipBytes = *seekTo - beginSrvRange; + bytesConsumedSoFar += skipBytes; + _currentSrvRange->bytesWritten += skipBytes; + + std::string errBuf = "Receiver cancelled starting the current range."; + if ( !_receiver.beginRange (*_currentRange, errBuf) ) { + setCode( Code::InternalError, "Receiver cancelled starting the current range."); + return 0; + } + + } else if ( _protocolMode != ProtocolMode::HTTP && !_currentRange ) { + // if we are not running in HTTP mode we can only request a single range, that means we get our data + // in one continous stream. Since our + // ranges are ordered by start, we just pick the first one that is marked as running + if ( !_currentRange ) { + const auto i = std::find_if( _requestedRanges.begin (), _requestedRanges.end(), []( const Range &r){ return r._rangeState == Running; }); + if ( i == _requestedRanges.end() ) { + setCode( Code::InternalError, "Received data but no range was marked as requested." ); + return 0; + } + + _currentRange = std::distance( _requestedRanges.begin(), i ); + + //continue writing where we stopped + seekTo = _requestedRanges[*_currentRange].start + _requestedRanges[*_currentRange].bytesWritten; + } + } + + if ( _currentRange ) { + /* + * We have data to write and know the target range + */ + + // make sure we do not read over the current server range + auto availableData = max - bytesConsumedSoFar; + if ( _currentSrvRange ) { + availableData = std::min( availableData, _currentSrvRange->len - _currentSrvRange->bytesWritten ); + } + + auto &rng = _requestedRanges[*_currentRange]; + + // do only write what we need until the range is full + const auto bytesToWrite = rng.len > 0 ? std::min( rng.len - rng.bytesWritten, availableData ) : availableData; + + auto written = _receiver.writefunction( ptr + bytesConsumedSoFar, seekTo, bytesToWrite ); + if ( written <= 0 ) + return 0; + + if ( rng._digest && rng._checksum.size() ) { + if ( !rng._digest->update( ptr + bytesConsumedSoFar, written ) ) + return 0; + } + + rng.bytesWritten += written; + if ( _currentSrvRange ) _currentSrvRange->bytesWritten += written; + + // range is done + if ( rng.len > 0 && rng.bytesWritten >= rng.len ) { + std::string errBuf = "Receiver cancelled after finishing the current range."; + bool rngIsValid = validateRange( rng ); + if ( !_receiver.finishedRange (*_currentRange, rngIsValid, errBuf) ) { + setCode( Code::InternalError, "Receiver cancelled starting the current range."); + return 0; + } + _currentRange.reset(); + } + + if ( _currentSrvRange && _currentSrvRange->len > 0 && _currentSrvRange->bytesWritten >= _currentSrvRange->len ) { + _currentSrvRange.reset(); + // we ran out of data in the current chunk, reset the target range if it is not a open range as well, because next data will be + // a chunk header again + if ( _isMuliPartResponse ) + _currentRange.reset(); + } + + bytesConsumedSoFar += written; + } + + if ( bytesConsumedSoFar == max ) + return max; + + if ( _protocolMode == ProtocolMode::HTTP && !_currentRange && !_currentSrvRange ) { + /* + This branch is reponsible to parse the multibyte response we got from the + server and parse the next target range from it + */ + + std::string_view incoming( ptr + bytesConsumedSoFar, max - bytesConsumedSoFar ); + auto hdrEnd = incoming.find("\r\n\r\n"); + if ( hdrEnd == incoming.npos ) { + //no header end in the data yet, push to buffer and return + _rangePrefaceBuffer.insert( _rangePrefaceBuffer.end(), incoming.begin(), incoming.end() ); + return max; + } + + //append the data of the current header to the buffer and parse it + _rangePrefaceBuffer.insert( _rangePrefaceBuffer.end(), incoming.begin(), incoming.begin() + ( hdrEnd + 4 ) ); + bytesConsumedSoFar += ( hdrEnd + 4 ); //header data plus header end + + std::string_view data( _rangePrefaceBuffer.data(), _rangePrefaceBuffer.size() ); + auto sepStrIndex = data.find( _seperatorString ); + if ( sepStrIndex == data.npos ) { + setCode( Code::InternalError, "Invalid multirange header format, seperator string missing." ); + return 0; + } + + auto startOfHeader = sepStrIndex + _seperatorString.length(); + std::vector lines; + zypp::strv::split( data.substr( startOfHeader ), "\r\n", zypp::strv::Trim::trim, [&]( std::string_view strv ) { lines.push_back(strv); } ); + for ( const auto &hdrLine : lines ) { + if ( zypp::strv::hasPrefixCI(hdrLine, "Content-Range:") ) { + size_t fileLen = 0; + Range r; + //if we can not parse the header the message must be broken + if(! parseContentRangeHeader( hdrLine, r.start, r.len, fileLen ) ) { + setCode( Code::InternalError, "Invalid Content-Range header format." ); + return 0; + } + if ( !_reportedFileSize ) { + _reportedFileSize = fileLen; + } + _currentSrvRange = std::move(r); + break; + } + } + + if ( !_currentSrvRange ){ + setCode( Code::InternalError, "Could not read a server range from the response." ); + return 0; + } + + //clear the buffer again + _rangePrefaceBuffer.clear(); + } + } + + return bytesConsumedSoFar; + } + + void *CurlMultiPartHandler::easyHandle() const + { + return _easyHandle; + } + + bool CurlMultiPartHandler::canRecover() const + { + // We can recover from RangeFail errors if we have more batch sizes to try + // we never auto downgrade to last range set ( which is 1 ) because in that case + // just downloading the full file is usually faster. + if ( _lastCode == Code::RangeFail ) + return ( _rangeAttemptIdx + 1 < ( _rangeAttemptSize - 1 ) ) && hasMoreWork(); + return false; + } + + bool CurlMultiPartHandler::hasMoreWork() const + { + // check if we have ranges that have never been requested + return std::any_of( _requestedRanges.begin(), _requestedRanges.end(), []( const auto &range ){ return range._rangeState == Pending; }); + } + + bool CurlMultiPartHandler::hasError() const + { + return _lastCode != Code::NoError; + } + + CurlMultiPartHandler::Code CurlMultiPartHandler::lastError() const + { + return _lastCode; + } + + const std::string &CurlMultiPartHandler::lastErrorMessage() const + { + return _lastErrorMsg; + } + + bool CurlMultiPartHandler::prepareToContinue( ) + { + if ( hasMoreWork() ) { + // go to the next range batch level if we are restarted due to a failed range request + if ( _lastCode == Code::RangeFail ) { + if ( _rangeAttemptIdx + 1 >= _rangeAttemptSize ) { + setCode ( Code::RangeFail, "No more range batch sizes available", true ); + return false; + } + _rangeAttemptIdx++; + } + return true; + } + + setCode ( Code::NoError, "Request has no more work", true ); + return false; + + } + + void CurlMultiPartHandler::finalize() + { + // if we still have a current range set it valid by checking the checksum + if ( _currentRange ) { + auto &currR = _requestedRanges[*_currentRange]; + std::string errBuf; + bool rngIsValid = validateRange( currR ); + _receiver.finishedRange (*_currentRange, rngIsValid, errBuf); + _currentRange.reset(); + } + } + + bool CurlMultiPartHandler::verifyData() + { + finalize(); + + for ( auto &r : _requestedRanges ) { + if ( r._rangeState != CurlMultiPartHandler::Finished ) { + if ( r.len > 0 && r.bytesWritten != r.len ) + setCode( Code::MissingData, (zypp::str::Format("Did not receive all requested data from the server ( off: %1%, req: %2%, recv: %3% ).") % r.start % r.len % r.bytesWritten ) ); + else if ( r._digest && r._checksum.size() && !checkIfRangeChkSumIsValid(r) ) { + setCode( Code::InvalidChecksum, (zypp::str::Format("Invalid checksum %1%, expected checksum %2%") % r._digest->digest() % zypp::Digest::digestVectorToString( r._checksum ) ) ); + } else { + setCode( Code::InternalError, (zypp::str::Format("Download of block failed.") ) ); + } + //we only report the first error + break; + } + } + return ( _lastCode == Code::NoError ); + } + + bool CurlMultiPartHandler::prepare( ) + { + _lastCode = Code::NoError; + _lastErrorMsg.clear(); + _seperatorString.clear(); + _currentSrvRange.reset(); + _reportedFileSize.reset(); + _gotContentRangeInfo = false; + _allHeadersReceived = false; + _isMuliPartResponse = false; + + if ( _requestedRanges.size() == 0 ) { + setCode( Code::InternalError, "Calling the CurlMultiPartHandler::prepare function without a range to download is not supported."); + return false; + } + + const auto setCurlOption = [&]( CURLoption opt, auto &&data ) + { + auto ret = curl_easy_setopt( _easyHandle, opt, data ); + if ( ret != 0 ) { + throw CurlMultiPartSetoptError(ret); + } + }; + + try { + setCurlOption( CURLOPT_HEADERFUNCTION, CurlMultiPartHandler::curl_hdrcallback ); + setCurlOption( CURLOPT_HEADERDATA, this ); + setCurlOption( CURLOPT_WRITEFUNCTION, CurlMultiPartHandler::curl_wrtcallback ); + setCurlOption( CURLOPT_WRITEDATA, this ); + + std::string rangeDesc; + uint rangesAdded = 0; + auto maxRanges = _rangeAttempt[_rangeAttemptIdx]; + + // helper function to build up the request string for the range + auto addRangeString = [ &rangeDesc, &rangesAdded ]( const std::pair &range ) { + std::string rangeD = zypp::str::form("%llu-", static_cast( range.first ) ); + if( range.second > 0 ) + rangeD.append( zypp::str::form( "%llu", static_cast( range.second ) ) ); + + if ( rangeDesc.size() ) + rangeDesc.append(",").append( rangeD ); + else + rangeDesc = std::move( rangeD ); + + rangesAdded++; + }; + + std::optional> currentZippedRange; + bool closedRange = true; + for ( auto &range : _requestedRanges ) { + + if ( range._rangeState != Pending ) + continue; + + //reset the download results + range.bytesWritten = 0; + + //when we have a open range in the list of ranges we will get from start of range to end of file, + //all following ranges would never be marked as valid, so we have to fail early + if ( !closedRange ) + throw CurlMultInitRangeError("It is not supported to request more ranges after a open range."); + + const auto rangeEnd = range.len > 0 ? range.start + range.len - 1 : 0; + closedRange = (rangeEnd > 0); + + bool added = false; + + // we try to compress the requested ranges into as big chunks as possible for the request, + // when receiving we still track the original ranges so we can collect and test their checksums + if ( !currentZippedRange ) { + added = true; + currentZippedRange = std::make_pair( range.start, rangeEnd ); + } else { + //range is directly consecutive to the previous range + if ( currentZippedRange->second + 1 == range.start ) { + added = true; + currentZippedRange->second = rangeEnd; + } else { + //this range does not directly follow the previous one, we build the string and start a new one + if ( rangesAdded +1 >= maxRanges ) break; + added = true; + addRangeString( *currentZippedRange ); + currentZippedRange = std::make_pair( range.start, rangeEnd ); + } + } + + // remember range was already requested + if ( added ) { + setRangeState( range, Running ); + range.bytesWritten = 0; + if ( range._digest ) + range._digest->reset(); + } + + if ( rangesAdded >= maxRanges ) { + MIL << _easyHandle << " " << "Reached max nr of ranges (" << maxRanges << "), batching the request to not break the server" << std::endl; + break; + } + } + + // add the last range too + if ( currentZippedRange ) + addRangeString( *currentZippedRange ); + + MIL << _easyHandle << " " << "Requesting Ranges: " << rangeDesc << std::endl; + + setCurlOption( CURLOPT_RANGE, rangeDesc.c_str() ); + + } catch( const CurlMultiPartSetoptError &err ) { + setCode( Code::InternalError, "" ); + } catch( const CurlMultInitRangeError &err ) { + setCode( Code::InternalError, err.asUserString() ); + } catch( const zypp::Exception &err ) { + setCode( Code::InternalError, err.asUserString() ); + } catch( const std::exception &err ) { + setCode( Code::InternalError, zypp::str::asString(err.what()) ); + } + return ( _lastCode == Code::NoError ); + } + + void CurlMultiPartHandler::setCode(Code c, std::string msg , bool force) + { + // never overwrite a error, this is reset when we restart + if ( _lastCode != Code::NoError && !force ) + return; + + _lastCode = c; + _lastErrorMsg = std::move(msg); + _receiver.notifyErrorCodeChanged(); + } + + bool CurlMultiPartHandler::parseContentRangeHeader( const std::string_view &line, size_t &start, size_t &len, size_t &fileLen ) + { + //content-range: bytes 10485760-19147879/19147880 + static const zypp::str::regex regex("^Content-Range:[[:space:]]+bytes[[:space:]]+([0-9]+)-([0-9]+)\\/([0-9]+)$", zypp::str::regex::rxdefault | zypp::str::regex::icase ); + + zypp::str::smatch what; + if( !zypp::str::regex_match( std::string(line), what, regex ) || what.size() != 4 ) { + DBG << _easyHandle << " " << "Invalid Content-Range Header format: '" << std::string(line) << std::endl; + return false; + } + + size_t s = zypp::str::strtonum( what[1]); + size_t e = zypp::str::strtonum( what[2]); + fileLen = zypp::str::strtonum( what[3]); + start = s; + len = ( e - s ) + 1; + return true; + } + + bool CurlMultiPartHandler::parseContentTypeMultiRangeHeader( const std::string_view &line, std::string &boundary ) + { + static const zypp::str::regex regex("^Content-Type:[[:space:]]+multipart\\/byteranges;[[:space:]]+boundary=(.*)$", zypp::str::regex::rxdefault | zypp::str::regex::icase ); + + zypp::str::smatch what; + if( zypp::str::regex_match( std::string(line), what, regex ) ) { + if ( what.size() >= 2 ) { + boundary = what[1]; + return true; + } + } + return false; + } + + bool CurlMultiPartHandler::validateRange( Range &rng ) + { + if ( rng._digest && rng._checksum.size() ) { + if ( ( rng.len == 0 || rng.bytesWritten == rng.len ) && checkIfRangeChkSumIsValid(rng) ) + setRangeState(rng, Finished); + else + setRangeState(rng, Error); + } else { + if ( rng.len == 0 ? true : rng.bytesWritten == rng.len ) + setRangeState(rng, Finished); + else + setRangeState(rng, Error); + } + return ( rng._rangeState == Finished ); + } + + bool CurlMultiPartHandler::checkIfRangeChkSumIsValid ( Range &rng ) + { + if ( rng._digest && rng._checksum.size() ) { + auto bytesHashed = rng._digest->bytesHashed (); + if ( rng._chksumPad && *rng._chksumPad > bytesHashed ) { + MIL_MEDIA << _easyHandle << " " << "Padding the digest to required block size" << std::endl; + zypp::ByteArray padding( *rng._chksumPad - bytesHashed, '\0' ); + rng._digest->update( padding.data(), padding.size() ); + } + auto digVec = rng._digest->digestVector(); + if ( rng._relevantDigestLen ) { + digVec.resize( *rng._relevantDigestLen ); + } + return ( digVec == rng._checksum ); + } + + // no checksum required + return true; + } + + void CurlMultiPartHandler::setRangeState( Range &rng, State state ) + { + if ( rng._rangeState != state ) { + rng._rangeState = state; + } + } + + std::optional CurlMultiPartHandler::currentRange() const + { + return _currentRange; + } + + std::optional CurlMultiPartHandler::reportedFileSize() const + { + return _reportedFileSize; + } + +} // namespace zyppng diff --git a/zypp-curl/ng/network/curlmultiparthandler.h b/zypp-curl/ng/network/curlmultiparthandler.h new file mode 100644 index 0000000..fca6b36 --- /dev/null +++ b/zypp-curl/ng/network/curlmultiparthandler.h @@ -0,0 +1,189 @@ +#ifndef ZYPPNG_CURLMULTIPARTHANDLER_H +#define ZYPPNG_CURLMULTIPARTHANDLER_H + +#include +#include +#include +#include +#include + +#include +#include + +namespace zyppng { + + /*! + * Data receiver interface for the \ref CurlMultiPartHandler class. + */ + class CurlMultiPartDataReceiver { + public: + virtual ~CurlMultiPartDataReceiver() = default; + + /*! + * Called for all received header data, after it was processed by the \ref CurlMultiPartHandler. + */ + virtual size_t headerfunction ( char *ptr, size_t bytes ) = 0; + + /*! + * Data callback func, this is called whenever there is actual data to be written to the file. + * If \a offset is set, usually when starting to write a new range, it means to continue to write on the current file pointer position, otherwise + * seek to the given one. + */ + virtual size_t writefunction ( char *ptr, std::optional offset, size_t bytes ) = 0; + + /*! + * Called everytime a new range is about to be written, returning false from the + * function will immediately cancel the request and not write anything to the file. + * + * @param range The index of the range that is to be started + * @param cancelReason Set to indicate why the request was cancelled. + */ + virtual bool beginRange ( off_t range, std::string &cancelReason ) { return true; }; + + /*! + * Called everytime a range was finished, returning false from the function will cancel the request. + * + * \note Normally \ref CurlMultiPartHandler will try to finish all ranges before failing even if one of them + * can not be validated. If the code should cancel early do it via returning false here. + * + * @param range The index of the range that was finished + * @param validated Indicates of the range data could be validated against its given checksum + * @param cancelReason Set to indicate why the request was cancelled. + */ + virtual bool finishedRange ( off_t range, bool validated, std::string &cancelReason ) { return true; }; + + /*! + * Called everytime the error code changes, this is just to notify that a error was set + */ + virtual void notifyErrorCodeChanged () {}; + }; + + /*! + * \brief The CurlMultiPartHandler class + * + * multirange support for HTTP requests (https://tools.ietf.org/html/rfc7233), if not operating + * on a HTTP/HTTPS URL this will batch multirange requests one by one, so maybe don't use it there + * + */ + class CurlMultiPartHandler : public Base + { + public: + + enum class ProtocolMode{ + Basic, //< use this mode if no special checks are required in header or write callbacks + HTTP //< this mode is used for HTTP and HTTPS downloads + }; + + // when requesting ranges from the server, we need to make sure not to request + // too many at the same time. Instead we batch our requests and reuse the open + // connection until we have the full file. + // However different server have different maximum nr of ranges, so we start with + // a high number and decrease until we find a rangecount that works + constexpr static unsigned _rangeAttempt[] = { + 255, + 127, + 63, + 15, + 5, + 1 + }; + + constexpr static unsigned _rangeAttemptSize = ( sizeof( _rangeAttempt ) / sizeof(unsigned) ); + + enum State { + Pending, //< waiting to be dispatched + Running, //< currently running + Finished, //< finished successfully + Error, //< Error, use error function to figure out the issue + }; + + using CheckSumBytes = UByteArray; + using Code = NetworkRequestError::Type; + + struct Range { + size_t start = 0; + size_t len = 0; + size_t bytesWritten = 0; + std::optional _digest = {}; //< zypp::Digest that is updated when data is written, can be used to validate the file contents with a checksum + + /** + * Enables automated checking of downloaded contents against a checksum. + * Only makes a difference if \ref _digest is initialized too + * + * \note expects checksum in byte NOT in string format + */ + CheckSumBytes _checksum; + std::optional _relevantDigestLen; //< If this is initialized , it defines how many bytes of the resulting checkum are compared + std::optional _chksumPad; //< If initialized we need to pad the digest with zeros before calculating the final checksum + std::any userData; //< Custom data the user can associate with the Range + + State _rangeState = State::Pending; //< Flag to know if this range has been already requested and if the request was successful + + void restart(); + Range clone() const; + + static Range make ( size_t start, size_t len = 0, std::optional &&digest = {}, CheckSumBytes &&expectedChkSum = CheckSumBytes(), std::any &&userData = std::any(), std::optional digestCompareLen = {}, std::optional _dataBlockPadding = {} ); + }; + + CurlMultiPartHandler( ProtocolMode mode, void *easyHandle, std::vector &ranges, CurlMultiPartDataReceiver &receiver ); + ~CurlMultiPartHandler() override; + + void *easyHandle() const; + bool canRecover() const; + bool hasMoreWork() const; + + bool hasError() const; + + Code lastError() const; + const std::string &lastErrorMessage() const; + + bool validateRange(Range &rng); + + bool prepare( ); + bool prepareToContinue( ); + void finalize( ); + + bool verifyData( ); + + std::optional reportedFileSize() const; + std::optional currentRange() const; + + private: + + void setCode ( Code c, std::string msg, bool force = false ); + + static size_t curl_hdrcallback ( char *ptr, size_t size, size_t nmemb, void *userdata ); + static size_t curl_wrtcallback ( char *ptr, size_t size, size_t nmemb, void *userdata ); + + size_t hdrcallback ( char *ptr, size_t size, size_t nmemb ); + size_t wrtcallback ( char *ptr, size_t size, size_t nmemb ); + bool parseContentRangeHeader(const std::string_view &line, size_t &start, size_t &len, size_t &fileLen); + bool parseContentTypeMultiRangeHeader(const std::string_view &line, std::string &boundary); + bool checkIfRangeChkSumIsValid( Range &rng ); + void setRangeState ( Range &rng, State state ); + + ProtocolMode _protocolMode = ProtocolMode::HTTP; + void *_easyHandle = nullptr; + CurlMultiPartDataReceiver &_receiver; + + Code _lastCode = Code::NoError; + std::string _lastErrorMsg; + + bool _allHeadersReceived = false; //< set to true once writefunc was called once e.g. all headers have been received + bool _gotContentRangeInfo = false; //< Set to true if the server indicates ranges + bool _isMuliPartResponse = false; //< Set to true if the respone is in multipart form + + std::string _seperatorString; ///< The seperator string for multipart responses as defined in RFC 7233 Section 4.1 + std::vector _rangePrefaceBuffer; ///< Here we buffer + + std::optional _currentRange; + std::optional _currentSrvRange; + std::optional _reportedFileSize; ///< Filesize as reported by the content range or byte range headers + + unsigned _rangeAttemptIdx = 0; + std::vector &_requestedRanges; ///< the requested ranges that need to be downloaded + }; + +} // namespace zyppng + +#endif // ZYPPNG_CURLMULTIPARTHANDLER_H diff --git a/zypp-curl/ng/network/downloader.cc b/zypp-curl/ng/network/downloader.cc new file mode 100644 index 0000000..df8639b --- /dev/null +++ b/zypp-curl/ng/network/downloader.cc @@ -0,0 +1,421 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + DownloadPrivateBase::DownloadPrivateBase(Downloader &parent, std::shared_ptr requestDispatcher, std::shared_ptr mirrors, DownloadSpec &&spec, Download &p) + : BasePrivate(p) + , _requestDispatcher ( std::move(requestDispatcher) ) + , _mirrorControl( std::move(mirrors) ) + , _spec( std::move(spec) ) + , _parent( &parent ) + {} + + DownloadPrivateBase::~DownloadPrivateBase() + { } + + bool DownloadPrivateBase::handleRequestAuthError( const std::shared_ptr& req, const zyppng::NetworkRequestError &err ) + { + //Handle the auth errors explicitly, we need to give the user a way to put in new credentials + //if we get valid new credentials we can retry the request + bool retry = false; + if ( err.type() == NetworkRequestError::Unauthorized || err.type() == NetworkRequestError::AuthFailed ) { + + MIL << "Authentication failed for " << req->url() << " trying to recover." << std::endl; + + TransferSettings &ts = req->transferSettings(); + const auto &applyCredToSettings = [&ts]( const AuthData_Ptr& auth, const std::string &authHint ) { + ts.setUsername( auth->username() ); + ts.setPassword( auth->password() ); + auto nwCred = dynamic_cast( auth.get() ); + if ( nwCred ) { + // set available authentication types from the error + if ( nwCred->authType() == CURLAUTH_NONE ) + nwCred->setAuthType( authHint ); + + // set auth type (seems this must be set _after_ setting the userpwd) + if ( nwCred->authType() != CURLAUTH_NONE ) { + // FIXME: only overwrite if not empty? + ts.setAuthType(nwCred->authTypeAsString()); + } + } + }; + + // try to find one in the cache + zypp::url::ViewOption vopt; + vopt = vopt + - zypp::url::ViewOption::WITH_USERNAME + - zypp::url::ViewOption::WITH_PASSWORD + - zypp::url::ViewOption::WITH_QUERY_STR; + + auto cachedCred = zypp::media::CredentialManager::findIn( _credCache, req->url(), vopt ); + + // only consider a cache entry if its newer than what we tried last time + if ( cachedCred && cachedCred->lastDatabaseUpdate() > req->_authTimestamp ) { + MIL << "Found a credential match in the cache!" << std::endl; + applyCredToSettings( cachedCred, "" ); + _lastTriedAuthTime = req->_authTimestamp = cachedCred->lastDatabaseUpdate(); + retry = true; + } else { + + NetworkAuthData_Ptr credFromUser = NetworkAuthData_Ptr( new NetworkAuthData() ); + credFromUser->setUrl( req->url() ); + credFromUser->setLastDatabaseUpdate ( req->_authTimestamp ); + + //in case we got a auth hint from the server the error object will contain it + std::string authHint = err.extraInfoValue("authHint", std::string()); + + _sigAuthRequired.emit( *z_func(), *credFromUser, authHint ); + if ( credFromUser->valid() ) { + // remember for next time , we don't want to ask the user again for the same URL set + _credCache.insert( credFromUser ); + applyCredToSettings( credFromUser, authHint ); + _lastTriedAuthTime = req->_authTimestamp = credFromUser->lastDatabaseUpdate(); + retry = true; + } + } + } + return retry; + } + +#if ENABLE_ZCHUNK_COMPRESSION + bool DownloadPrivateBase::hasZckInfo() const + { + if ( zypp::indeterminate(_specHasZckInfo) ) + _specHasZckInfo = ( _spec.headerSize() > 0 && isZchunkFile( _spec.deltaFile() ) ); + return bool(_specHasZckInfo); + } +#endif + + void DownloadPrivateBase::Request::disconnectSignals() + { + _sigStartedConn.disconnect(); + _sigProgressConn.disconnect(); + _sigFinishedConn.disconnect(); + } + + DownloadPrivate::DownloadPrivate(Downloader &parent, std::shared_ptr requestDispatcher, std::shared_ptr mirrors, DownloadSpec &&spec, Download &p) + : DownloadPrivateBase( parent, std::move(requestDispatcher), std::move(mirrors), std::move(spec), p ) + { } + + void DownloadPrivate::init() + { + Base::connectFunc( *this, &DownloadStatemachine::sigFinished, [this](){ + DownloadPrivateBase::_sigFinished.emit( *z_func() ); + } ); + + Base::connectFunc( *this, &DownloadStatemachine::sigStateChanged, [this]( const auto state ){ + DownloadPrivateBase::_sigStateChanged.emit( *z_func(), state ); + } ); + } + + void DownloadPrivate::start() + { + auto cState = currentState(); + if ( !cState ) + DownloadStatemachine::start(); + + cState = currentState(); + if ( *cState != Download::InitialState && *cState != Download::Finished ) { + // the state machine has advaned already, we can only restart it in a finished state + return; + } + + //reset state variables + _specHasZckInfo = zypp::indeterminate; + _emittedSigStart = false; + _stoppedOnMetalink = false; + _lastTriedAuthTime = 0; + + // restart the statemachine + if ( cState == Download::Finished ) + DownloadStatemachine::start(); + + //jumpstart the process + state()->initiate(); + } + + + NetworkRequestError DownloadPrivateBase::safeFillSettingsFromURL( const Url &url, TransferSettings &set) + { + auto buildExtraInfo = [this, &url](){ + std::map extraInfo; + extraInfo.insert( {"requestUrl", url } ); + extraInfo.insert( {"filepath", _spec.targetPath() } ); + return extraInfo; + }; + + NetworkRequestError res; + try { + ::internal::fillSettingsFromUrl( url, set ); + if ( _spec.settings().proxy().empty() ) + ::internal::fillSettingsSystemProxy( url, set ); + +#if 0 + /* Fixes bsc#1174011 "auth=basic ignored in some cases" + * We should proactively add the password to the request if basic auth is configured + * and a password is available in the credentials but not in the URL. + * + * We will be a bit paranoid here and require that the URL has a user embedded, otherwise we go the default route + * and ask the server first about the auth method + */ + if ( set.authType() == "basic" + && set.username().size() + && !set.password().size() ) { + zypp::media::CredentialManager cm( _parent ? _parent->credManagerOptions() : zypp::media::CredManagerOptions() ); + const auto cred = cm.getCred( url ); + if ( cred && cred->valid() ) { + if ( !set.username().size() ) + set.setUsername(cred->username()); + set.setPassword(cred->password()); + } + } +#endif + + } catch ( const zypp::media::MediaBadUrlException & e ) { + res = NetworkRequestErrorPrivate::customError( NetworkRequestError::MalformedURL, e.asString(), buildExtraInfo() ); + } catch ( const zypp::media::MediaUnauthorizedException & e ) { + res = NetworkRequestErrorPrivate::customError( NetworkRequestError::AuthFailed, e.asString(), buildExtraInfo() ); + } catch ( const zypp::Exception & e ) { + res = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, e.asString(), buildExtraInfo() ); + } + return res; + } + + Download::Download(zyppng::Downloader &parent, std::shared_ptr requestDispatcher, std::shared_ptr mirrors, zyppng::DownloadSpec &&spec) + : Base( *new DownloadPrivate( parent, std::move(requestDispatcher), std::move(mirrors), std::move(spec), *this ) ) + { } + + ZYPP_IMPL_PRIVATE(Download) + + Download::~Download() + { + if ( state() != InitialState && state() != Finished ) + cancel(); + } + + Download::State Download::state() const + { + const auto &s = d_func()->currentState(); + if ( !s ) + return Download::InitialState; + return *s; + } + + NetworkRequestError Download::lastRequestError() const + { + if ( state() == Finished ) { + return d_func()->state()->_error; + } + return NetworkRequestError(); + } + + bool Download::hasError() const + { + return lastRequestError().isError(); + } + + std::string Download::errorString() const + { + const auto &lReq = lastRequestError(); + if (! lReq.isError() ) { + return {}; + } + + return ( zypp::str::Format("%1%(%2%)") % lReq.toString() % lReq.nativeErrorString() ); + } + + void Download::start() + { + d_func()->start(); + } + + void Download::prioritize() + { + Z_D(); + + if ( !d->_requestDispatcher ) + return; + + d->_defaultSubRequestPriority = NetworkRequest::Critical; + + // we only reschedule requests when we are in a state that downloads in blocks + d->visitState( []( auto &s ){ + using T = std::decay_t; + if constexpr ( std::is_same_v +#if ENABLE_ZCHUNK_COMPRESSION + || std::is_same_v +#endif + ) { + s.reschedule(); + } + }); + } + + void Download::cancel() + { + Z_D(); + d->forceState ( std::make_unique( NetworkRequestErrorPrivate::customError( NetworkRequestError::Cancelled, "Download was cancelled explicitly" ), *d_func() ) ); + } + + void Download::setStopOnMetalink(const bool set) + { + d_func()->_stopOnMetalink = set; + } + + bool Download::stoppedOnMetalink() const + { + return d_func()->_stoppedOnMetalink; + } + + DownloadSpec &Download::spec() + { + return d_func()->_spec; + } + + const DownloadSpec &Download::spec() const + { + return d_func()->_spec; + } + + uint64_t Download::lastAuthTimestamp() const + { + return d_func()->_lastTriedAuthTime; + } + + zyppng::NetworkRequestDispatcher &Download::dispatcher() const + { + return *d_func()->_requestDispatcher; + } + + SignalProxy Download::sigStarted() + { + return d_func()->_sigStarted; + } + + SignalProxy Download::sigStateChanged() + { + return d_func()->DownloadPrivateBase::_sigStateChanged; + } + + SignalProxy zyppng::Download::sigAlive() + { + return d_func()->_sigAlive; + } + + SignalProxy Download::sigProgress() + { + return d_func()->_sigProgress; + } + + SignalProxy Download::sigFinished() + { + return d_func()->DownloadPrivateBase::_sigFinished; + } + + SignalProxy Download::sigAuthRequired() + { + return d_func()->_sigAuthRequired; + } + + DownloaderPrivate::DownloaderPrivate(std::shared_ptr mc, Downloader &p) + : BasePrivate(p) + , _mirrors( std::move(mc) ) + { + _requestDispatcher = std::make_shared( ); + if ( !_mirrors ) { + _mirrors = MirrorControl::create(); + } + } + + void DownloaderPrivate::onDownloadStarted(Download &download) + { + _sigStarted.emit( *z_func(), download ); + } + + void DownloaderPrivate::onDownloadFinished( Download &download ) + { + _sigFinished.emit( *z_func(), download ); + + auto it = std::find_if( _runningDownloads.begin(), _runningDownloads.end(), [ &download ]( const std::shared_ptr &dl){ + return dl.get() == &download; + }); + + if ( it != _runningDownloads.end() ) { + //make sure this is not deleted before all user code was done + _runningDownloads.erase( it ); + } + + if ( _runningDownloads.empty() ) + _queueEmpty.emit( *z_func() ); + } + + ZYPP_IMPL_PRIVATE(Downloader) + + Downloader::Downloader( ) + : Base ( *new DownloaderPrivate( {}, *this ) ) + { + + } + + Downloader::Downloader( std::shared_ptr mc ) + : Base ( *new DownloaderPrivate( std::move(mc), *this ) ) + { } + + Downloader::~Downloader() + { + Z_D(); + while ( d->_runningDownloads.size() ) { + d->_runningDownloads.back()->cancel(); + d->_runningDownloads.pop_back(); + } + } + + std::shared_ptr Downloader::downloadFile(const zyppng::DownloadSpec &spec ) + { + Z_D(); + std::shared_ptr dl ( new Download ( *this, d->_requestDispatcher, d->_mirrors, DownloadSpec(spec) ) ); + + d->_runningDownloads.push_back( dl ); + dl->connect( &Download::sigFinished, *d, &DownloaderPrivate::onDownloadFinished ); + d->_requestDispatcher->run(); + + return dl; + } + + std::shared_ptr Downloader::requestDispatcher() const + { + return d_func()->_requestDispatcher; + } + + SignalProxy Downloader::sigStarted() + { + return d_func()->_sigStarted; + } + + SignalProxy Downloader::sigFinished() + { + return d_func()->_sigFinished; + } + + SignalProxy Downloader::queueEmpty() + { + return d_func()->_queueEmpty; + } + +} diff --git a/zypp-curl/ng/network/downloader.h b/zypp-curl/ng/network/downloader.h new file mode 100644 index 0000000..13dc730 --- /dev/null +++ b/zypp-curl/ng/network/downloader.h @@ -0,0 +1,273 @@ +#ifndef ZYPP_NG_MEDIA_CURL_DOWNLOADER_H_INCLUDED +#define ZYPP_NG_MEDIA_CURL_DOWNLOADER_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#include + +namespace zypp::media { + class TransferSettings; +} + +namespace zyppng { + + class NetworkRequestDispatcher; + class DownloaderPrivate; + class Download; + class DownloadSpec; + class MirrorControl; + + using TransferSettings = zypp::media::TransferSettings; + + ZYPP_FWD_DECL_TYPE_WITH_REFS( Downloader ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( Download ); + + + /** + * @brief The Downloader class + * + * Provides a high level interface to the \sa HttpRequestDispatcher, + * implementing Metalink on top. If in doubt which one to use, always + * use this one. + */ + class LIBZYPP_NG_EXPORT Downloader : public Base + { + ZYPP_DECLARE_PRIVATE( Downloader ) + public: + + using Ptr = DownloaderRef; + using WeakPtr = DownloaderWeakRef; + + Downloader(); + Downloader( std::shared_ptr mc ); + ~Downloader() override; + + /*! + * Generates a new Download object in waiting state + */ + std::shared_ptr downloadFile ( const DownloadSpec &spec ); + + /*! + * Returns the internally used \sa zyppng::NetworkRequestDispatcher used by the \a Downloader + * to enqueue network requests + */ + std::shared_ptr requestDispatcher () const; + + /*! + * Emitted when a \sa zyppng::Download created by this Downloader instance was started + */ + SignalProxy sigStarted ( ); + + /*! + * Signal that is emitted when a \sa zyppng::Download created by this Downloader instance was finished + * \note Just as with \sa zyppng::NetworkRequest 's the finished signal does not mean the Download was successful + */ + SignalProxy sigFinished ( ); + + /*! + * Signal is always emitted when there are not Downloads anymore waiting in the queue + */ + SignalProxy queueEmpty ( ); + }; + + class DownloadPrivate; + + /*! + * The Download class represents a possibly multipart download. + * + * The \a Download class is a more high level interface compared to \sa zyppng::NetworkRequest, it can internally + * make use of features like metalinks and tries to be as resilient as possible with errors during a download. Due to this + * it is represented internally as a state machine. All transitions are signalled and can be followed. + * + * \code + * zyppng::EventLoop::Ptr loop = zyppng::EventLoop::create(); + * zyppng::Downloader dl; + * + * dl.queueEmpty().connect( [ &loop ]( zyppng::Downloader & ) { + * loop->quit(); + * }); + * + * zypp::Url url ( "https://download.opensuse.org/distribution/leap/15.0/repo/oss/x86_64/0ad-0.0.22-lp150.2.10.x86_64.rpm" ); + * zypp::Pathname target("/tmp/0ad-0.0.22-lp150.2.10.x86_64.rpm"); + * + * std::shared_ptr req = dl.downloadFile( zypp::DownloadSpec(url, target) ); + * req->sigStarted().connect( []( zyppng::Download &dl ) { + * std::cout << "Download started: " << dl.targetPath() << std::endl; + * }); + * + * req->sigFinished().connect( []( zyppng::Download &dl ) { + * std::cout << "Download finished: " << dl.targetPath() << std::endl; + * if ( dl.state() != zyppng::Download::Success ) + * std::cout << "\t has error: " << dl.errorString() << std::endl; + * }); + * + * req->sigAlive().connect( []( zyppng::Download &dl, off_t dlnow ) { + * std::cout << dl.targetPath().asString() << " at: " << std::endl + * << "dlnow: "<< dlnow<< std::endl; + * }); + * + * req->sigProgress().connect( []( zyppng::Download &dl, off_t dltotal, off_t dlnow ) { + * std::cout << dl.targetPath().asString() << " at: " << std::endl + * << "dltotal: "<< dltotal<< std::endl + * << "dlnow: "<< dlnow<< std::endl; + * }); + * + * req->start(); + * loop->run(); + * + * \endcode + * + */ + class LIBZYPP_NG_EXPORT Download : public Base + { + ZYPP_DECLARE_PRIVATE( Download ) + + public: + + using Ptr = DownloadRef; + using WeakPtr = DownloadWeakRef; + + /*! + * The states of the internal state machine. Each of them represents a different + * stage of the lifetime of a Download. + */ + enum State { + InitialState, //< This is the initial state. It is only set before a download starts. + DetectMetaLink, //< Metalink downloads are enabled, trying to detect if we get a metalink or not + DlMetaLinkInfo, //< Downloading the metalink description file + PrepareMulti, //< This state is set for async preparations of the multi download, like mirror rating + DlMetalink, //< Metalink download is running + DlZChunkHead, //< Zchunk header download is running + DlZChunk, //< Zchunk download is running + DlSimple, //< Simple download running, no optimizations + Finished, //< Download has finished + }; + + ~Download() override; + + /*! + * Returns the current internal state of the Download + * \sa zyppng::Download::State + */ + State state () const; + + /*! + * Returns the last \sa zyppng::NetworkRequestError enountered while downloading the file. + * This will just represent the very last error that could not be recovered from. In case of + * a Metalink download that ususally means that all mirrors and the initial URL failed to download for + * some reason. + */ + NetworkRequestError lastRequestError () const; + + /*! + * Returns true if \ref lastRequestError would return a valid \ref NetworkRequestError + */ + bool hasError () const; + + /*! + * Returns a readable reason why the download failed. + * \sa lastRequestError + */ + std::string errorString () const; + + /*! + * Triggers the start of the download, this needs to be called in order for the statemachine + * to advance. + */ + void start (); + + /*! + * This will raise all requests currenty in pending state to have \ref NetworkRequest::Critial priority, + * which means they will be started even before requests with \ref NetworkRequest::High priority. + * + * \note Use this feature only if the request result is required right away because the application is waiting for it, overuse of this + * might hurt performance + */ + void prioritize(); + + /*! + * Aborts the current download + */ + void cancel (); + + /*! + * This will finalize the download once a metalink file was received. This is a special setting used + * if the metalink file should be processed outside of the Downloader. + */ + void setStopOnMetalink ( const bool set = true ); + + /*! + * Returns true if the download was stopped after receiving metalink data. The target file + * will contain the metalink description. + */ + bool stoppedOnMetalink () const; + + /*! + * Returns a reference to the internally used download spec. + * \sa zyppng::DownloadSpec + * \note Changing settings after the download started might result in undefined or weird behaviour + */ + DownloadSpec &spec (); + const DownloadSpec &spec () const; + + /*! + * Returns the timestamp of the last auth credentials that were loaded from the CredentialManager. + * If no credentials were tried, this returns 0 + */ + uint64_t lastAuthTimestamp () const; + + /*! + * Returns a reference to the internally used \sa zyppng::NetworkRequestDispatcher + */ + NetworkRequestDispatcher &dispatcher () const; + + /*! + * Signals that the dispatcher dequeued the request and actually starts downloading data + */ + SignalProxy sigStarted (); + + /*! + * Signals that the state of the \a Download has changed + */ + SignalProxy sigStateChanged (); + + /*! + * Signals that the download is alive but still in initial stage ( trying to figure out if metalink / zsync ) + */ + SignalProxy sigAlive (); + + /*! + * Signals if there was data read from the download + */ + SignalProxy sigProgress (); + + /*! + * Signals that the download finished. + */ + SignalProxy sigFinished ( ); + + /*! + * Is emitted when a request requires authentication and it was not given or if auth failed. + * A connected slot should fill in the \a auth information in order to provide login credentials. + * + * \note the URL in the \a auth data is set to the url of the request needing authorization. + * This URL can be different than the one in the spec, due to redirect/metalink. + * Also the lastDatabaseUpdate field is set to the timestamp of the auth data that was tried already ( if available ) + */ + SignalProxy sigAuthRequired ( ); + + private: + friend class zyppng::Downloader; + /*! + * A download can only directly be created by the \sa zyppng::Downloader + */ + Download ( Downloader &parent, std::shared_ptr requestDispatcher, std::shared_ptr mirrors, DownloadSpec &&spec ); + }; +} + +#endif diff --git a/zypp-curl/ng/network/downloadspec.cc b/zypp-curl/ng/network/downloadspec.cc new file mode 100644 index 0000000..38ea559 --- /dev/null +++ b/zypp-curl/ng/network/downloadspec.cc @@ -0,0 +1,169 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include "downloadspec.h" +#include + +namespace zyppng { + + class DownloadSpecPrivate { + public: + DownloadSpecPrivate() = default; + DownloadSpecPrivate &operator=(const DownloadSpecPrivate &) = delete; + DownloadSpecPrivate &operator=(DownloadSpecPrivate &&) = delete; + DownloadSpecPrivate(const DownloadSpecPrivate &other) = default; + DownloadSpecPrivate( DownloadSpecPrivate &&other ) noexcept = default; + + DownloadSpecPrivate *clone () const { + return new DownloadSpecPrivate(*this); + } + + zypp::Url _url; + TransferSettings _settings; + zypp::Pathname _delta; + zypp::ByteCount _expectedFileSize; + zypp::Pathname _targetPath; + bool _checkExistanceOnly = false; //< this will NOT download the file, but only query the server if it exists + bool _metalink_enabled = true; //< should the download try to use metalinks + zypp::ByteCount _headerSize; //< Optional file header size for things like zchunk + std::optional _headerChecksum; //< Optional file header checksum + zypp::ByteCount _preferred_chunk_size = 0; + }; + + ZYPP_IMPL_PRIVATE( DownloadSpec ) + + DownloadSpec::DownloadSpec( Url file , zypp::filesystem::Pathname targetPath, zypp::ByteCount expectedFileSize ) : d_ptr( new DownloadSpecPrivate() ) + { + // default settings + d_ptr->_url = std::move(file); + d_ptr->_targetPath = std::move(targetPath); + d_ptr->_expectedFileSize = std::move( expectedFileSize ); + } + + const Url &DownloadSpec::url() const + { + return d_ptr->_url; + } + + DownloadSpec &DownloadSpec::setUrl(const Url &url) + { + d_ptr->_url = url; + return *this; + } + + const zypp::Pathname &DownloadSpec::targetPath() const + { + return d_ptr->_targetPath; + } + + DownloadSpec &DownloadSpec::setTargetPath(const zypp::filesystem::Pathname &path) + { + d_ptr->_targetPath = path; + return *this; + } + + DownloadSpec &DownloadSpec::setMetalinkEnabled(bool enable) + { + d_ptr->_metalink_enabled = enable; + return *this; + } + + bool DownloadSpec::metalinkEnabled() const + { + return d_ptr->_metalink_enabled; + } + + DownloadSpec &DownloadSpec::setCheckExistsOnly(bool set) + { + d_ptr->_checkExistanceOnly = ( set ); + return *this; + } + + bool DownloadSpec::checkExistsOnly() const + { + return d_ptr->_checkExistanceOnly; + } + + DownloadSpec &DownloadSpec::setDeltaFile(const zypp::Pathname &file) + { + d_ptr->_delta = file; + return *this; + } + + zypp::Pathname DownloadSpec::deltaFile() const + { + return d_ptr->_delta; + } + + DownloadSpec &DownloadSpec::setPreferredChunkSize(const zypp::ByteCount &bc) + { + d_ptr->_preferred_chunk_size = bc; + return *this; + } + + zypp::ByteCount DownloadSpec::preferredChunkSize() const + { + return d_ptr->_preferred_chunk_size; + } + + const TransferSettings &DownloadSpec::settings() const + { + return d_ptr->_settings; + } + + DownloadSpec & DownloadSpec::setTransferSettings(TransferSettings &&set) + { + d_ptr->_settings = std::move( set ); + return *this; + } + + DownloadSpec & DownloadSpec::setTransferSettings(const TransferSettings &set) + { + d_ptr->_settings = set; + return *this; + } + + DownloadSpec &DownloadSpec::setExpectedFileSize(const zypp::ByteCount &bc) + { + d_ptr->_expectedFileSize = bc; + return *this; + } + + zypp::ByteCount DownloadSpec::expectedFileSize() const + { + return d_ptr->_expectedFileSize; + } + + DownloadSpec &DownloadSpec::setHeaderSize(const zypp::ByteCount &bc) + { + d_ptr->_headerSize = bc; + return *this; + } + + zypp::ByteCount DownloadSpec::headerSize() const + { + return d_ptr->_headerSize; + } + + const std::optional &DownloadSpec::headerChecksum() const + { + Z_D(); + return d->_headerChecksum; + } + + DownloadSpec &DownloadSpec::setHeaderChecksum(const zypp::CheckSum &sum) + { + Z_D(); + if ( sum.empty() ) + d->_headerChecksum.reset(); + else { + d->_headerChecksum = sum; + } + return *this; + } +} diff --git a/zypp-curl/ng/network/downloadspec.h b/zypp-curl/ng/network/downloadspec.h new file mode 100644 index 0000000..c879954 --- /dev/null +++ b/zypp-curl/ng/network/downloadspec.h @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_MEDIA_NETWORK_DOWNLOADSPEC_H +#define ZYPPNG_MEDIA_NETWORK_DOWNLOADSPEC_H + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace zyppng { + + + class DownloadSpecPrivate; + using TransferSettings = zypp::media::TransferSettings; + + /*! + * Specifies all aspects of a download. Used together with the + * \ref zyppng::Download and \ref zyppng::Downloader classes + */ + class DownloadSpec + { + ZYPP_DECLARE_PRIVATE( DownloadSpec ) + + public: + DownloadSpec(Url file, zypp::filesystem::Pathname targetPath, + zypp::ByteCount expectedFileSize = zypp::ByteCount()); + + DownloadSpec( const DownloadSpec &other ) = default; + DownloadSpec &operator= ( const DownloadSpec &other ) = default; + + DownloadSpec(DownloadSpec &&) noexcept = default; + DownloadSpec &operator=(DownloadSpec &&) noexcept = default; + /*! + * Returns the source URL of the download + */ + const Url &url () const; + DownloadSpec &setUrl ( const Url &url ); + + /*! + * Returns the target file path, this is where the downloaded data is stored + */ + const zypp::Pathname &targetPath() const; + DownloadSpec &setTargetPath ( const zypp::Pathname &path ); + + /*! + * Enabled or disabled metalink handling. Enabled by default. + * \note if Metalink is enabled the Download tells the server that it accepts metalink files by adding a specific header + * to the request. + */ + DownloadSpec &setMetalinkEnabled ( bool enable = true ); + bool metalinkEnabled ( ) const; + + /*! + * Enables a special mode, in this case only the existance of the file is checked but no data is actually downloaded + */ + DownloadSpec &setCheckExistsOnly ( bool set = true ); + bool checkExistsOnly ( ) const; + + /*! + * Set a already existing local file to be used for partial downloading, in case of a multichunk download all chunks from the + * file that have the expected checksum will be reused instead of downloaded + */ + DownloadSpec &setDeltaFile ( const zypp::Pathname &file ); + zypp::filesystem::Pathname deltaFile() const; + + /*! + * Sets the prefered amount of bytes the downloader tries to request from a single server per metalink chunk request. + * If the metalink description has smaller chunks those are coalesced to match the preferred size. + * + * Setting this to 0 tells the \ref Downloader instance to automatically calculate the chunk size. This is also the default. + */ + DownloadSpec &setPreferredChunkSize ( const zypp::ByteCount &bc ); + zypp::ByteCount preferredChunkSize() const; + + /*! + * Returns the \sa zyppng::TransferSettings for the download. The settings are reused for + * possible sub downloads, however authentication data is stripped if the subdownload uses a different host to + * fetch the data from. If there is no auth data known \sa sigAuthRequired is emitted. + */ + const TransferSettings &settings () const; + DownloadSpec &setTransferSettings( TransferSettings &&set ); + DownloadSpec &setTransferSettings( const TransferSettings &set ); + + DownloadSpec &setExpectedFileSize ( const zypp::ByteCount &bc ); + zypp::ByteCount expectedFileSize() const; + + DownloadSpec &setHeaderSize ( const zypp::ByteCount &bc ); + zypp::ByteCount headerSize() const; + + const std::optional &headerChecksum () const; + DownloadSpec &setHeaderChecksum ( const zypp::CheckSum &sum ); + + private: + zypp::RWCOW_pointer d_ptr; + }; + +} + +#endif // ZYPPNG_MEDIA_NETWORK_DOWNLOADSPEC_H diff --git a/zypp-curl/ng/network/mirrorcontrol.cc b/zypp-curl/ng/network/mirrorcontrol.cc new file mode 100644 index 0000000..fb258ae --- /dev/null +++ b/zypp-curl/ng/network/mirrorcontrol.cc @@ -0,0 +1,302 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include "private/mirrorcontrol_p.h" +#include "private/mediadebug_p.h" +#include +#include +#include +#include + +namespace zyppng { + + constexpr uint penaltyIncrease = 100; + constexpr uint defaultSampleTime = 2; + constexpr uint defaultMaxConnections = 5; + + MirrorControl::Mirror::Mirror( MirrorControl &parent ) : _parent( parent ) + {} + + void MirrorControl::Mirror::startTransfer() + { + runningTransfers++; + } + + void MirrorControl::Mirror::finishTransfer(const bool success) + { + if ( success ) { + if ( penalty >= penaltyIncrease ) penalty -= penaltyIncrease; + successfulTransfers++; + failedTransfers = 0; + } else { + penalty += penaltyIncrease; + failedTransfers++; + } + transferUnref(); + } + + void MirrorControl::Mirror::cancelTransfer() + { + transferUnref(); + } + + uint MirrorControl::Mirror::maxConnections() const + { + return ( _maxConnections > 0 ? _maxConnections : defaultMaxConnections ); //max connections per mirror @todo make this configurable + } + + bool MirrorControl::Mirror::hasFreeConnections() const + { + return ( runningTransfers < maxConnections() ); + } + + void MirrorControl::Mirror::transferUnref() + { + const auto newCount = runningTransfers - 1; + if ( newCount < 0 ) + return; + + bool stillLoaded = ( newCount ) >= maxConnections(); + runningTransfers--; + if ( !stillLoaded ) + _parent._sigNewMirrorsReady.emit(); + } + + MirrorControl::MirrorControl() + { + // set up the single shot timer, that way we can emit a signal after we finished processing all + // events that have queued up in the event loop instead of constantly firing the signal + _newMirrSigDelay = Timer::create(); + _newMirrSigDelay->setSingleShot( true ); + _newMirrSigDelay->connectFunc( &Timer::sigExpired, [this]( const auto & ){ + _sigNewMirrorsReady.emit(); + }); + + _dispatcher = std::make_shared(); + _queueEmptyConn = _dispatcher->connectFunc( &NetworkRequestDispatcher::sigQueueFinished, [ this ]( NetworkRequestDispatcher& ) { + //tell the world the queue is empty + + std::vector< std::unordered_map::const_iterator > allOfEm; + for ( auto i = _handles.begin(); i != _handles.end(); i++ ) { + allOfEm.push_back( i ); + } + + std::sort( allOfEm.begin(), allOfEm.end(), []( const auto &a, const auto &b ){ + return ( zypp::str::compareCI( a->second->mirrorUrl.asString().c_str(), b->second->mirrorUrl.asString().c_str() ) < 0 ); + }); + + DBG_MEDIA << "Finished probing mirrors, these are the results: \n"; + for ( const auto &iter : allOfEm ) { + DBG_MEDIA << "Mirror: " << iter->second->mirrorUrl << ", rating is: " << iter->second->rating << "\n"; + } + DBG_MEDIA << "End Mirror probing results." << std::endl; + + _sigAllMirrorsReady.emit(); + }, *this ); + _dispatcher->run(); + } + + MirrorControl::Ptr MirrorControl::create() + { + return std::shared_ptr( new MirrorControl ); + } + + MirrorControl::~MirrorControl() + { + // do not send signals to us while we are destructing + _queueEmptyConn.disconnect(); + + if ( _dispatcher->count() > 0 ) { + MIL << "Destroying MirrorControl while measurements are still running, aborting" << std::endl; + for ( auto &mirr : _handles ) { + if ( mirr.second->_request ) { + mirr.second->_finishedConn.disconnect(); + _dispatcher->cancel( *mirr.second->_request ); + } + } + } + + } + + void MirrorControl::registerMirrors( const std::vector &urls ) + { + bool doesKnowSomeMirrors = false; + for ( const auto &mirror : urls ) { + + const auto scheme = mirror.url.getScheme(); + if ( scheme == "http" || scheme == "https" || scheme == "ftp" || scheme == "tftp" ) { + + const std::string urlKey = makeKey( mirror.url ); + + // already there + const auto hndlIt = _handles.find( urlKey ); + if ( hndlIt != _handles.end() ) { + doesKnowSomeMirrors = true; + continue; + } + + auto mirrorHandle = std::shared_ptr( new Mirror(*this) ); + mirrorHandle->rating = mirror.priority; + mirrorHandle->_maxConnections = mirror.maxConnections; + mirrorHandle->mirrorUrl = mirror.url; + mirrorHandle->mirrorUrl.setPathName("/"); + + mirrorHandle->_request = std::make_shared( mirrorHandle->mirrorUrl, "/dev/null", NetworkRequest::WriteShared ); + mirrorHandle->_request->setOptions( NetworkRequest::ConnectionTest ); + mirrorHandle->_request->transferSettings().setTimeout( defaultSampleTime ); + mirrorHandle->_request->transferSettings().setConnectTimeout( defaultSampleTime ); + mirrorHandle->_finishedConn = mirrorHandle->_request->connectFunc( &NetworkRequest::sigFinished, [ mirrorHandle, &someReadyDelay = _newMirrSigDelay ]( NetworkRequest &req, const NetworkRequestError & ){ + + if ( req.hasError() ) + ERR << "Mirror request failed: " << req.error().toString() << " ; " << req.extendedErrorString() << "; for url: "<(timings->connect - timings->namelookup); + } else { + // we can not get any measurements, maximum penalty + connTime = std::chrono::seconds( defaultSampleTime ); + } + + DBG_MEDIA << "Got rating for mirror: " << mirrorHandle->mirrorUrl << ", rating was " << mirrorHandle->rating; + mirrorHandle->rating += connTime.count(); + DBG_MEDIA << " rating is now " << mirrorHandle->rating << " conn time was " << connTime.count() << std::endl; + + // clean the request up + mirrorHandle->_finishedConn.disconnect(); + mirrorHandle->_request.reset(); + + // start the timer to emit someMirrorsReady + someReadyDelay->start( 0 ); + }); + + _dispatcher->enqueue( mirrorHandle->_request ); + _handles.insert( std::make_pair(urlKey, mirrorHandle ) ); + } + } + + if ( doesKnowSomeMirrors ) + _sigNewMirrorsReady.emit(); + + if ( _dispatcher->count() == 0 ) { + // we did know all Mirrors before, notify the outside world we are ready + _sigAllMirrorsReady.emit(); + } + } + + MirrorControl::PickResult MirrorControl::pickBestMirror( const std::vector &mirrors ) + { + bool hasPendingRating = false; + std::vector< MirrorPick > possibleMirrs; + for ( auto i = mirrors.begin(); i != mirrors.end(); i++ ) { + const auto key = makeKey( *i ); + const auto hdlIt = this->_handles.find( key ); + if ( hdlIt == _handles.end( ) ) + continue; + // still waiting for the request to finish + if ( hdlIt->second->_request ) { + hasPendingRating = true; + continue; + } + possibleMirrs.push_back( std::make_pair( i, hdlIt->second ) ); + } + + if ( possibleMirrs.empty() && hasPendingRating ) { + // still waiting return , tell the caller to try again later + return PickResult{ PickResult::Again, std::make_pair( mirrors.end(), MirrorHandle() ) }; + } + + std::stable_sort( possibleMirrs.begin(), possibleMirrs.end(), []( const auto &a, const auto &b ) { + return a.second->rating < b.second->rating; + }); + + bool hasLoadedOne = false; // do we have a mirror that will be ready again later? + for ( const auto &mirr : possibleMirrs ) { + if ( !mirr.second->hasFreeConnections() ) { + hasLoadedOne = true; + continue; + } + if ( mirr.second->failedTransfers >= 10 ) + continue; + return PickResult{ PickResult::Ok, mirr }; + } + + if ( hasLoadedOne ){ + // we have mirrors, but they have reached maximum capacity, tell the caller to delay the call + return PickResult{ PickResult::Again, std::make_pair( mirrors.end(), MirrorHandle() ) }; + } + + return PickResult{ PickResult::Unknown, std::make_pair( mirrors.end(), MirrorHandle() ) }; + } + + SignalProxy MirrorControl::sigNewMirrorsReady() + { + return _sigNewMirrorsReady; + } + + SignalProxy MirrorControl::sigAllMirrorsReady() + { + return _sigAllMirrorsReady; + } + + std::string MirrorControl::makeKey(const zypp::Url &url) const + { + return url.asString( zypp::Url::ViewOptions::WITH_SCHEME + + zypp::Url::ViewOptions::WITH_HOST + + zypp::Url::ViewOptions::WITH_PORT + + zypp::Url::ViewOptions::EMPTY_AUTHORITY + ); + } + +#if 0 + + MirrorRef::MirrorRef( MirrorControl::MirrorHandle handle ) + { + _data = std::make_shared( handle, false ); + } + + MirrorRef::~MirrorRef() + { } + + void MirrorRef::startTransfer() + { + _data->_myHandle->startTransfer(); + _data->_cancelOnDestruct = true; + } + + void MirrorRef::finishTransfer(const bool success) + { + _data->_cancelOnDestruct = false; + _data->_myHandle->finishTransfer( success ); + } + + void MirrorRef::cancelTransfer() + { + _data->_cancelOnDestruct = false; + _data->_myHandle->cancelTransfer(); + } + + MirrorRef::operator bool() const + { + return _data->_myHandle.operator bool(); + } + + MirrorControl::MirrorHandle MirrorRef::get() + { + return _data->_myHandle; + } + + MirrorRef::Helper::~Helper() + { + if ( _cancelOnDestruct ) + _myHandle->cancelTransfer(); + } +#endif + +} diff --git a/zypp-curl/ng/network/networkrequestdispatcher.cc b/zypp-curl/ng/network/networkrequestdispatcher.cc new file mode 100644 index 0000000..d8b5862 --- /dev/null +++ b/zypp-curl/ng/network/networkrequestdispatcher.cc @@ -0,0 +1,547 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using namespace boost; + +L_ENV_CONSTR_DEFINE_FUNC(ZYPP_MEDIA_CURL_DEBUG) + + +namespace zyppng { + +static const std::string & defaultAgentString() +{ + // we need to add the release and identifier to the + // agent string. + // The target could be not initialized, and then this information + // is guessed. + static const std::string _value( + zypp::str::form( + "ZYpp " LIBZYPP_VERSION_STRING " (curl %s)" + , curl_version_info(CURLVERSION_NOW)->version + ) + ); + return _value; +} + + +NetworkRequestDispatcherPrivate::NetworkRequestDispatcherPrivate( NetworkRequestDispatcher &p ) + : BasePrivate( p ) + , _timer( Timer::create() ) + , _multi ( curl_multi_init() ) + , _userAgent( defaultAgentString() ) +{ + ::internal::globalInitCurlOnce(); + + curl_multi_setopt( _multi, CURLMOPT_TIMERFUNCTION, NetworkRequestDispatcherPrivate::multi_timer_cb ); + curl_multi_setopt( _multi, CURLMOPT_TIMERDATA, reinterpret_cast( this ) ); + curl_multi_setopt( _multi, CURLMOPT_SOCKETFUNCTION, NetworkRequestDispatcherPrivate::static_socket_callback ); + curl_multi_setopt( _multi, CURLMOPT_SOCKETDATA, reinterpret_cast( this ) ); + + // disabled explicit pipelining since it breaks our tests on releases < 15.2 + // we could consider enabling it starting with a specific CURL version + // curl_multi_setopt( _multi, CURLMOPT_PIPELINING, CURLPIPE_MULTIPLEX|CURLPIPE_HTTP1 ); + + _timer->setSingleShot( true ); + _timer->connect( &Timer::sigExpired, *this, &NetworkRequestDispatcherPrivate::multiTimerTimout ); +} + +NetworkRequestDispatcherPrivate::~NetworkRequestDispatcherPrivate() +{ + cancelAll( NetworkRequestErrorPrivate::customError( NetworkRequestError::Cancelled, "Dispatcher shutdown" ) ); + curl_multi_cleanup( _multi ); +} + +//called by curl to setup a timer +int NetworkRequestDispatcherPrivate::multi_timer_cb( CURLM *, long timeout_ms, void *thatPtr ) +{ + NetworkRequestDispatcherPrivate *that = reinterpret_cast( thatPtr ); + assert( that != nullptr ); + + if ( timeout_ms >= 0 ) { + that->_timer->start( static_cast(timeout_ms) ); + } else { + //cancel the timer + that->_timer->stop(); + } + return 0; +} + +void NetworkRequestDispatcherPrivate::multiTimerTimout(const Timer &) +{ + handleMultiSocketAction( CURL_SOCKET_TIMEOUT, 0 ); +} + +int NetworkRequestDispatcherPrivate::static_socket_callback(CURL * easy, curl_socket_t s, int what, void *userp, SocketNotifier *socketp ) +{ + NetworkRequestDispatcherPrivate *that = reinterpret_cast( userp ); + assert( that != nullptr ); + return that->socketCallback( easy, s, what, socketp ); +} + +int NetworkRequestDispatcherPrivate::socketCallback(CURL *easy, curl_socket_t s, int what, void * ) +{ + std::shared_ptr socketp; + + if ( _socketHandler.count( s ) == 0 ) { + if ( what == CURL_POLL_REMOVE || what == CURL_POLL_NONE ) + return 0; + + socketp = SocketNotifier::create( s, SocketNotifier::Read, false ); + _socketHandler.insert( std::make_pair( s, socketp ) ); + + socketp->connect( &SocketNotifier::sigActivated, *this, &NetworkRequestDispatcherPrivate::onSocketActivated ); + } else { + socketp = _socketHandler[s]; + } + + //should never happen + if ( !socketp ) { + if ( what == CURL_POLL_REMOVE || what == CURL_POLL_NONE ) + return 0; + + if ( _socketHandler.count( s ) > 0 ) + _socketHandler.erase( s ); + + void *privatePtr = nullptr; + if ( curl_easy_getinfo( easy, CURLINFO_PRIVATE, &privatePtr ) != CURLE_OK ) { + privatePtr = nullptr; //make sure this was not filled with bad info + } + + if ( privatePtr ) { + NetworkRequestPrivate *request = reinterpret_cast( privatePtr ); + //we stop the download, if we can not listen for socket changes we can not correctly do anything + setFinished( *request->z_func(), NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Unable to assign socket listener." ) ); + return 0; + } else { + //a broken handle without anything assigned, also should never happen but make sure and clean it up + WAR << "Cleaning up unassigned easy handle" << std::endl; + curl_multi_remove_handle( _multi, easy ); + curl_easy_cleanup( easy ); + return 0; + } + } + + //remove the socket + if ( what == CURL_POLL_REMOVE ) { + socketp->setEnabled( false ); + _socketHandler.erase( s ); + return 0; + } + + if ( what == CURL_POLL_IN ) { + socketp->setMode( SocketNotifier::Read ); + } else if ( what == CURL_POLL_OUT ) { + socketp->setMode( SocketNotifier::Write ); + } else if ( what == CURL_POLL_INOUT ) { + socketp->setMode( SocketNotifier::Read | SocketNotifier::Write ); + } + + socketp->setEnabled(); + return 0; +} + +void NetworkRequestDispatcherPrivate::onSocketActivated( const SocketNotifier &listener, int events ) +{ + int evBitmask = 0; + if ( (events & SocketNotifier::Read) == SocketNotifier::Read ) + evBitmask |= CURL_CSELECT_IN; + if ( (events & SocketNotifier::Write) == SocketNotifier::Write ) + evBitmask |= CURL_CSELECT_OUT; + if ( (events & SocketNotifier::Error) == SocketNotifier::Error ) + evBitmask |= CURL_CSELECT_ERR; + + handleMultiSocketAction( listener.socket(), evBitmask ); +} + +void NetworkRequestDispatcherPrivate::handleMultiSocketAction(curl_socket_t nativeSocket, int evBitmask) +{ + int running = 0; + + // when inside a curl callback we can not call another multi curl API, + // for now just lock the thing, but we should consider rewriting this + // to post events instead of doing direct calls simply to decouple from + // that limitation + CURLMcode rc = CURLM_OK; + { + zypp::DtorReset lockSet( _locked ); + _locked = true; + rc = curl_multi_socket_action( _multi, nativeSocket, evBitmask, &running ); + } + if (rc != 0) { + //we can not recover from a error like that, cancel all and stop + NetworkRequestError err = NetworkRequestErrorPrivate::fromCurlMError( rc ); + cancelAll( err ); + //emit error + _lastError = err; + _sigError.emit( *z_func() ); + return; + } + + // make sure we dequeue pending requests ( in case a call to dequeue was blocked during the API call ) + zypp::OnScopeExit scopeFinally([this](){ + this->dequeuePending(); + }); + + int msgs_left = 0; + CURLMsg *msg = nullptr; + while( (msg = curl_multi_info_read( _multi, &msgs_left )) ) { + if(msg->msg == CURLMSG_DONE) { + CURL *easy = msg->easy_handle; + CURLcode res = msg->data.result; + + void *privatePtr = nullptr; + if ( curl_easy_getinfo( easy, CURLINFO_PRIVATE, &privatePtr ) != CURLE_OK ) { + WAR << "Unable to get CURLINFO_PRIVATE" << std::endl; + continue; + } + + if ( !privatePtr ) { + //broken easy handle not associated, should never happen but clean it up + WAR << "Cleaning up unassigned easy handle" << std::endl; + curl_multi_remove_handle( _multi, easy ); + curl_easy_cleanup( easy ); + continue; + } + + NetworkRequestPrivate *request = reinterpret_cast( privatePtr ); + request->dequeueNotify(); + + if ( request->hasMoreWork() && ( res == CURLE_OK || request->canRecover() ) ) { + std::string errBuf = "Broken easy handle in request"; + if ( !request->_easyHandle ) { + NetworkRequestError e = NetworkRequestErrorPrivate::customError ( NetworkRequestError::InternalError, std::move(errBuf) ); + setFinished( *request->z_func(), e ); + continue; + } + + // remove the handle from multi to change options + curl_multi_remove_handle( _multi, request->_easyHandle ); + + errBuf = "Failed to reinitialize the request"; + if ( !request->prepareToContinue ( errBuf ) ) { + NetworkRequestError e = NetworkRequestErrorPrivate::customError ( NetworkRequestError::InternalError, std::move(errBuf) ); + setFinished( *request->z_func(), e ); + } else { + // add the request back to the multi handle, it is not done + if ( !addRequestToMultiHandle( *request->z_func() ) ) + continue; + + request->aboutToStart( ); + } + } else { + //trigger notification about file downloaded + NetworkRequestError e = NetworkRequestErrorPrivate::fromCurlError( *request->z_func(), res, request->errorMessage() ); + setFinished( *request->z_func(), e ); + } + //attention request could be deleted from here on + } + } +} + +void NetworkRequestDispatcherPrivate::cancelAll( const NetworkRequestError& result ) +{ + //prevent dequeuePending from filling up the runningDownloads again + zypp::DtorReset lockReset( _locked ); + _locked = true; + + while ( _runningDownloads.size() ) { + std::shared_ptr &req = _runningDownloads.back(); + setFinished(*req, result ); + } + while ( _pendingDownloads.size() ) { + std::shared_ptr &req = _pendingDownloads.back(); + setFinished(*req, result ); + } +} + +void NetworkRequestDispatcherPrivate::setFinished( NetworkRequest &req, NetworkRequestError result ) +{ + auto delReq = []( auto &list, NetworkRequest &req ) -> std::shared_ptr { + auto it = std::find_if( list.begin(), list.end(), [ &req ]( const std::shared_ptr &r ) { + return req.d_func() == r->d_func(); + } ); + if ( it != list.end() ) { + auto ptr = *it; + list.erase( it ); + return ptr; + } + return nullptr; + }; + + // We have a tricky situation if a network request is called when inside a callback. In those cases, it is + // not allowed to call curl_multi_remove_handle. We need to tell the callback to fail, so the download + // is cancelled by curl itself. We also need to store the current result for later + auto rmode = std::get_if( &req.d_func()->_runningMode ); + if ( rmode ) { + if ( rmode->_isInCallback ) { + // the first cached result wins) + if ( !rmode->_cachedResult ) + rmode->_cachedResult = result; + return; + } else if ( rmode->_cachedResult ) { + result = rmode->_cachedResult.value(); + } + } + + auto rLocked = delReq( _runningDownloads, req ); + if ( !rLocked ) + rLocked = delReq( _pendingDownloads, req ); + + void *easyHandle = req.d_func()->_easyHandle; + if ( easyHandle ) + curl_multi_remove_handle( _multi, easyHandle ); + + req.d_func()->_dispatcher = nullptr; + + //first set the result, the Request might have a checksum to check as well so a currently + //successful request could fail later on + req.d_func()->setResult( std::move(result) ); + _sigDownloadFinished.emit( *z_func(), req ); + + //we got a open slot, try to dequeue or send the finished signals if all queues are empty + dequeuePending(); +} + +bool NetworkRequestDispatcherPrivate::addRequestToMultiHandle(NetworkRequest &req) +{ + CURLMcode rc = curl_multi_add_handle( _multi, req.d_func()->_easyHandle ); + if ( rc != 0 ) { + setFinished( req, NetworkRequestErrorPrivate::fromCurlMError( rc ) ); + return false; + } + return true; +} + +void NetworkRequestDispatcherPrivate::dequeuePending() +{ + if ( !_isRunning || _locked ) + return; + + while ( _maxConnections == -1 || ( (std::size_t)_maxConnections > _runningDownloads.size() ) ) { + if ( !_pendingDownloads.size() ) + break; + + std::shared_ptr req = std::move( _pendingDownloads.front() ); + _pendingDownloads.pop_front(); + + std::string errBuf = "Failed to initialize easy handle"; + if ( !req->d_func()->initialize( errBuf ) ) { + //@TODO store the CURL error in the errors extra info + setFinished( *req, NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, std::move(errBuf) ) ); + continue; + } + + if ( !addRequestToMultiHandle( *req ) ) + continue; + + req->d_func()->aboutToStart(); + _sigDownloadStarted.emit( *z_func(), *req ); + + _runningDownloads.push_back( std::move(req) ); + } + + //check for empty queues + if ( _pendingDownloads.size() == 0 && _runningDownloads.size() == 0 ) { + //once we finished all requests, cancel the timer too, so curl is not called without requests + _timer->stop(); + _sigQueueFinished.emit( *z_func() ); + } +} + +ZYPP_IMPL_PRIVATE(NetworkRequestDispatcher) + +NetworkRequestDispatcher::NetworkRequestDispatcher( ) + : Base( * new NetworkRequestDispatcherPrivate ( *this ) ) +{ + +} + +bool NetworkRequestDispatcher::supportsProtocol( const Url &url ) +{ + curl_version_info_data *curl_info = nullptr; + curl_info = curl_version_info(CURLVERSION_NOW); + // curl_info does not need any free (is static) + if (curl_info->protocols) + { + const char * const *proto = nullptr; + std::string scheme( url.getScheme() ); + bool found = false; + for(proto=curl_info->protocols; !found && *proto; ++proto) { + if( scheme == std::string((const char *)*proto)) + found = true; + } + return found; + } + return true; +} + +void NetworkRequestDispatcher::setMaximumConcurrentConnections( const int maxConn ) +{ + d_func()->_maxConnections = maxConn; +} + +int NetworkRequestDispatcher::maximumConcurrentConnections () const +{ + return d_func()->_maxConnections; +} + +void NetworkRequestDispatcher::enqueue(const std::shared_ptr &req ) +{ + if ( !req ) + return; + Z_D(); + + if ( std::find( d->_runningDownloads.begin(), d->_runningDownloads.end(), req ) != d->_runningDownloads.end() ) { + WAR << "Ignoring request to enqueue download " << req->url().asString() << " request is already running " << std::endl; + return; + } + + if ( std::find( d->_pendingDownloads.begin(), d->_pendingDownloads.end(), req ) != d->_pendingDownloads.end() ) { + WAR << "Ignoring request to enqueue download " << req->url().asString() << " request is already enqueued " << std::endl; + return; + } + + req->d_func()->_dispatcher = this; + if ( req->priority() == NetworkRequest::Normal ) + d->_pendingDownloads.push_back( req ); + else { + auto it = std::find_if( d->_pendingDownloads.begin(), d->_pendingDownloads.end(), [ prio = req->priority() ]( const auto &pendingReq ){ + return pendingReq->priority() < prio; + }); + + //if we have a valid iterator, decrement we found a pending download request with lower prio, insert before that + if ( it != d->_pendingDownloads.end() && it != d->_pendingDownloads.begin() ) + it--; + d->_pendingDownloads.insert( it, req ); + } + + //dequeue if running and we have capacity + d->dequeuePending(); +} + +void NetworkRequestDispatcher::setAgentString( const std::string &agent ) +{ + Z_D(); + if ( agent.empty() ) + d->_userAgent = defaultAgentString(); + else + d->_userAgent = agent; +} + +const std::string &NetworkRequestDispatcher::agentString() const +{ + return d_func()->_userAgent; +} + +void NetworkRequestDispatcher::setHostSpecificHeader( const std::string &host, const std::string &headerName, const std::string &value ) +{ + Z_D(); + if ( value.empty() ) { + if ( auto i = d->_customHeaders.find( host ); i != d->_customHeaders.end() ) { + if ( auto v = i->second.find( headerName ); v != i->second.end() ) { + i->second.erase (v); + } + if ( i->second.empty() ) + d->_customHeaders.erase(i); + } + return; + } + d->_customHeaders[host][headerName] = value; +} + +const NetworkRequestDispatcher::SpecificHeaderMap &NetworkRequestDispatcher::hostSpecificHeaders() const +{ + return d_func()->_customHeaders; +} + +void NetworkRequestDispatcher::cancel( NetworkRequest &req, std::string reason ) +{ + cancel( req, NetworkRequestErrorPrivate::customError( NetworkRequestError::Cancelled, reason.size() ? std::move(reason) : "Request explicitly cancelled" ) ); +} + +void NetworkRequestDispatcher::cancel(NetworkRequest &req, const NetworkRequestError &err) +{ + Z_D(); + + if ( req.d_func()->_dispatcher != this ) { + //TODO throw exception + return; + } + + d->setFinished( req, err ); +} + +void NetworkRequestDispatcher::run() +{ + Z_D(); + d->_isRunning = true; + + if ( d->_pendingDownloads.size() ) + d->dequeuePending(); +} + +void NetworkRequestDispatcher::reschedule() +{ + Z_D(); + if ( !d->_pendingDownloads.size() ) + return; + + std::stable_sort( d->_pendingDownloads.begin(), d->_pendingDownloads.end(), []( const auto &a, const auto &b ){ + return a->priority() < b->priority(); + }); + + d->dequeuePending(); +} + +size_t NetworkRequestDispatcher::count() +{ + Z_D(); + return d->_pendingDownloads.size() + d->_runningDownloads.size(); +} + +const zyppng::NetworkRequestError &NetworkRequestDispatcher::lastError() const +{ + return d_func()->_lastError; +} + +SignalProxy NetworkRequestDispatcher::sigDownloadStarted() +{ + return d_func()->_sigDownloadStarted; +} + +SignalProxy NetworkRequestDispatcher::sigDownloadFinished() +{ + return d_func()->_sigDownloadFinished; +} + +SignalProxy NetworkRequestDispatcher::sigQueueFinished() +{ + return d_func()->_sigQueueFinished; +} + +SignalProxy NetworkRequestDispatcher::sigError() +{ + return d_func()->_sigError; +} + +} diff --git a/zypp-curl/ng/network/networkrequestdispatcher.h b/zypp-curl/ng/network/networkrequestdispatcher.h new file mode 100644 index 0000000..eeedd87 --- /dev/null +++ b/zypp-curl/ng/network/networkrequestdispatcher.h @@ -0,0 +1,193 @@ +#ifndef ZYPP_NG_MEDIA_CURL_CURL_H_INCLUDED +#define ZYPP_NG_MEDIA_CURL_CURL_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +#include + +namespace zyppng { + + class NetworkRequestDispatcherPrivate; + class NetworkRequest; + + /*! + * The NetworkRequestDispatcher class is used to run multiple NetworkRequest instances + * at the same time, making full use of the event loop. + * + * Dispatching is implemented using a internal priority queue, all requests in the + * queue are set to waiting. Once a request is dequeued it is initialized and started + * right away. Its possible to change the maximum number of concurrent connections to control + * the load on the network. + * + * \code + * zyppng::EventLoop::Ptr loop = zyppng::EventLoop::create(); + * zyppng::NetworkRequestDispatcher downloader; + * + * zypp::Url url ( "https://download.opensuse.org/distribution/leap/15.0/repo/oss/x86_64/0ad-0.0.22-lp150.2.10.x86_64.rpm" ); + * zypp::Pathname target("/tmp/0ad-0.0.22-lp150.2.10.x86_64.rpm"); + * + * std::shared_ptr req = std::make_shared( zypp::Url(url), target ); + * + * std::shared_ptr dig = std::make_shared(); + * if ( !dig->create( zypp::Digest::md5() ) ) { + * std::cerr << "Unable to create Digest " << std::endl; + * return 1; + * } + * + * req->setDigest( dig ); + * req->setExpectedChecksum( hexstr2bytes("11822f1421ae50fb1a07f72220b79000") ); + * + * req->sigStarted().connect( [] ( const zyppng::NetworkRequest &r ){ + * std::cout << r.url() << " started downloading " << std::endl; + * }); + * + * req->sigFinished().connect( [] ( const zyppng::NetworkRequest &r, const zyppng::NetworkRequestError &err ){ + * if ( err.isError() ) { + * std::cout << r.url() << " finsihed with err " << err.nativeErrorString() << " : "<< err.isError() << " : " << err.toString() << std::endl; + * } else { + * std::cout << r.url() << " finished downloading " << std::endl; + * } + * }); + * + * req->sigProgress().connect( [] ( const zyppng::NetworkRequest &r, off_t dltotal, off_t dlnow, off_t ultotal, off_t ulnow ){ + * std::cout << r.url() << " at: " << std::endl + * << "dltotal: "<< dltotal<< std::endl + * << "dlnow: "<< dlnow<< std::endl + * << "ultotal: "<< ultotal<< std::endl + * << "ulnow: "<< ulnow<< std::endl; + * }); + * + * downloader.enqueue( req ); + * + * downloader.sigQueueFinished().connect( [ &loop ]( const zyppng::NetworkRequestDispatcher & ) { + * loop->quit(); + * }); + * + * downloader.run( ); + * loop->run(); + * \code + * + * \sa zyppng::Downloader + */ + class LIBZYPP_NG_EXPORT NetworkRequestDispatcher : public Base + { + ZYPP_DECLARE_PRIVATE(NetworkRequestDispatcher) + public: + + using Ptr = std::shared_ptr; + using WeakPtr = std::weak_ptr; + + NetworkRequestDispatcher ( ); + + /*! + * Returns true if the protocol used in the Url scheme is supported by + * the dispatcher backend + */ + static bool supportsProtocol ( const Url &url ); + + /*! + * Change the number of the concurrently started requests, the default is 10. + * Setting this to -1 means there is no limit. + */ + void setMaximumConcurrentConnections ( const int maxConn ); + + /** + * returns the maximum number of allowed concurrent connections + */ + int maximumConcurrentConnections () const; + + /*! + * Enqueues a new \a request and puts it into the waiting queue. If the dispatcher + * is already running and has free capacatly the request might be started right away + */ + void enqueue ( const std::shared_ptr &req ); + + /*! + * Changes the agent header valur to \a agent. + */ + void setAgentString ( const std::string &agent ); + + /*! + * Returns the currenty set agent string + */ + const std::string &agentString () const; + + /*! + * Adds a header to each request to a specific host, this is used to send + * anonymous statistics to download.opensuse.org. + * Setting a host/headerName combination to a empty string removes the header from being send again. + * + * \note This will add the header to ALL requests that match the given host, for more fine grained control use \ref TransferSettings + * \note is empty by default + */ + void setHostSpecificHeader ( const std::string &host, const std::string &headerName, const std::string &value ); + + + using SpecificHeaderMap = std::unordered_map< std::string, std::unordered_map>; + + /*! + * Returns the currenty set host specific headers + */ + const SpecificHeaderMap &hostSpecificHeaders() const; + + + /*! + * Cancels the request \a req setting the error description to \a reason. + */ + void cancel ( NetworkRequest &req , std::string reason = std::string() ); + + /*! + * Cancels the request \a req setting the error to \a err. + */ + void cancel ( NetworkRequest &req , const NetworkRequestError &err ); + + /*! + * Start dispatching requests, this needs to be done explicitly before any request can be executed. + */ + void run ( ); + + /*! + * Reschedule enqueued requests based on their priorities + */ + void reschedule (); + + /*! + * Returns the number of requests in the running and waiting queues + */ + size_t count (); + + /*! + * Returns the last encountered error in a request. + */ + const NetworkRequestError &lastError() const; + + /*! + * Signal is emitted when a download is started + */ + SignalProxy sigDownloadStarted(); + + /*! + * Emitted when a request was finished, check the request to see if it was successful + */ + SignalProxy sigDownloadFinished(); + + /*! + * Emitted when the internal request queue is completely processed and all requests are finished. + */ + SignalProxy sigQueueFinished (); + + /*! + * Emitted when there is a error in the backend the dispatcher can not recover from. All requests are cancelled + * use \a lastError to get more information. + */ + SignalProxy sigError (); + }; +} + + +#endif diff --git a/zypp-curl/ng/network/networkrequesterror.cc b/zypp-curl/ng/network/networkrequesterror.cc new file mode 100644 index 0000000..ea9550f --- /dev/null +++ b/zypp-curl/ng/network/networkrequesterror.cc @@ -0,0 +1,321 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include + +namespace zyppng { + +ZYPP_IMPL_PRIVATE(NetworkRequestError); + +constexpr std::string_view CurlNativeErrorCodeDescKey = "nativeErrorCodeDesc"; +constexpr std::string_view CurlNativeErrorDescKey = "nativeErrorDesc"; + +NetworkRequestErrorPrivate::NetworkRequestErrorPrivate(NetworkRequestError::Type code, std::string &&msg, std::map &&extraInfo) + : _errorCode(code) + , _errorMessage( std::move(msg) ) +, _extraInfo( std::move(extraInfo) ) +{ } + +NetworkRequestErrorPrivate *NetworkRequestErrorPrivate::clone() const +{ + return new NetworkRequestErrorPrivate( *this ); +} + +NetworkRequestError NetworkRequestErrorPrivate::customError( NetworkRequestError::Type t, std::string &&errorMsg, std::map &&extraInfo ) +{ + return NetworkRequestError( *new NetworkRequestErrorPrivate(t, errorMsg.empty() ? typeToString(t) : std::move(errorMsg), std::move(extraInfo)) ); +} + +NetworkRequestError NetworkRequestErrorPrivate::fromCurlError(NetworkRequest &req, int nativeCode , const std::string &nativeError ) +{ + + Url url = req.url(); + NetworkRequestError::Type c = NetworkRequestError::NoError; + std::string err; + std::map extraInfo; + + if ( nativeCode != 0 ) { + + const char *nativeErr = curl_easy_strerror( static_cast(nativeCode) ); + if ( nativeErr != nullptr ) + extraInfo.insert( { CurlNativeErrorCodeDescKey.data(), std::string( nativeErr ) } ); + + if ( !nativeError.empty() ) + extraInfo.insert( { CurlNativeErrorDescKey.data(), nativeError } ); + + extraInfo.insert( { "requestUrl", url } ); + extraInfo.insert( { "curlCode", nativeCode } ); + extraInfo.insert( { "filepath", req.targetFilePath().asString() } ); + extraInfo.insert( { "lastRedirect", req.lastRedirectInfo() } ); + + switch ( nativeCode ) + { + case CURLE_UNSUPPORTED_PROTOCOL: + c = NetworkRequestError::UnsupportedProtocol; + err = typeToString( c ); + if ( !req.lastRedirectInfo().empty() ) + { + err += " or redirect ("; + err += req.lastRedirectInfo(); + err += ")"; + } + break; + case CURLE_URL_MALFORMAT: case CURLE_URL_MALFORMAT_USER: + c = NetworkRequestError::MalformedURL; + break; + case CURLE_LOGIN_DENIED: + c = NetworkRequestError::Unauthorized; + break; + case CURLE_HTTP_RETURNED_ERROR: { + long httpReturnCode = 0; + CURLcode infoRet = curl_easy_getinfo( req.nativeHandle(), + CURLINFO_RESPONSE_CODE, + &httpReturnCode ); + + if ( infoRet == CURLE_OK ) { + extraInfo.insert( { "responseCode", httpReturnCode } ); + + std::string msg = "HTTP response: " + zypp::str::numstring( httpReturnCode ); + switch ( httpReturnCode ) + { + case 401: { + std::string auth_hint; + { + long auth_info = CURLAUTH_NONE; + + CURLcode infoRet = + curl_easy_getinfo(req.nativeHandle(), CURLINFO_HTTPAUTH_AVAIL, &auth_info); + + if(infoRet == CURLE_OK) { + extraInfo.insert( { "authHint", zypp::media::CurlAuthData::auth_type_long2str(auth_info) } ); + } + } + + //if there is already a user:password entry in the settings the auth simply failed + //@TODO write a testcase for this + if ( !req.transferSettings().userPassword().empty() ) { + c = NetworkRequestError::AuthFailed; + } else { + c = NetworkRequestError::Unauthorized; + } + + break; + } + + case 502: // bad gateway (bnc #1070851) + case 503: // service temporarily unavailable (bnc #462545) + c = NetworkRequestError::TemporaryProblem; + err = zypp::str::form( _("Location '%s' is temporarily unaccessible."), url.asString().c_str() ); + break; + case 504: // gateway timeout + c = NetworkRequestError::Timeout; + err = zypp::str::form(_("Timeout exceeded when accessing '%s'."), url.asString().c_str() ); + break; + case 403: { + std::string msg403; + if ( url.getHost().find(".suse.com") != std::string::npos ) + msg403 = _("Visit the SUSE Customer Center to check whether your registration is valid and has not expired."); + else if (url.asString().find("novell.com") != std::string::npos) + msg403 = _("Visit the Novell Customer Center to check whether your registration is valid and has not expired."); + + c = NetworkRequestError::Forbidden; + err = msg403; + break; + } + case 404: + case 410: + c = NetworkRequestError::NotFound; + err = zypp::str::form( _("File '%s' not found on medium '%s'"), req.targetFilePath().c_str(), url.asString().c_str() ); + break; + + default: + c = NetworkRequestError::ServerReturnedError; + err = zypp::str::form(_("Download (curl) error for '%s':\n" + "Error code: %s\n"), url.asString().c_str(), zypp::str::numstring( httpReturnCode ).c_str() ) ; + break; + } + } else { + c = NetworkRequestError::ServerReturnedError; + err = zypp::str::form(_("Download (curl) error for '%s':\n" + "Unable to retrieve HTTP response\n"), url.asString().c_str() ) ; + } + } + break; + case CURLE_FTP_COULDNT_RETR_FILE: +#if CURLVERSION_AT_LEAST(7,16,0) + case CURLE_REMOTE_FILE_NOT_FOUND: +#endif + case CURLE_FTP_ACCESS_DENIED: + case CURLE_TFTP_NOTFOUND: + c = NetworkRequestError::NotFound; + break; + case CURLE_BAD_PASSWORD_ENTERED: + case CURLE_FTP_USER_PASSWORD_INCORRECT: + c = NetworkRequestError::AuthFailed; + break; + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case CURLE_FTP_CANT_GET_HOST: + c = NetworkRequestError::ConnectionFailed; + break; + case CURLE_WRITE_ERROR: { + // this error code also handles the cases when a callback returned a error. + c = NetworkRequestError::InternalError; + break; + } + case CURLE_PARTIAL_FILE: + c = NetworkRequestError::ServerReturnedError; + break; + case CURLE_OPERATION_TIMEDOUT: + c = NetworkRequestError::Timeout; + break; + case CURLE_ABORTED_BY_CALLBACK: + c = NetworkRequestError::Cancelled; + break; + case CURLE_PEER_FAILED_VERIFICATION: + c = NetworkRequestError::PeerCertificateInvalid; + break; + case CURLE_HTTP2: + c = NetworkRequestError::Http2Error; + break; + case CURLE_HTTP2_STREAM: + c = NetworkRequestError::Http2StreamError; + break; + default: + c = NetworkRequestError::ServerReturnedError; + break; + } + } + + if ( err.empty() ) + err = typeToString( c ); + + err += " Curl error (" + zypp::str::numstring( nativeCode ) + ")"; + + return NetworkRequestError( *new NetworkRequestErrorPrivate(c, std::move(err), std::move(extraInfo)) ); +} + +NetworkRequestError NetworkRequestErrorPrivate::fromCurlMError( int nativeCode ) +{ + const char *nativeErr = curl_multi_strerror( static_cast(nativeCode) ); + + std::map extraInfo; + extraInfo.insert( { "curlMCode", nativeCode } ); + + std::string err; + if ( nativeErr == nullptr ) + err = "The dispatcher returned an unknown error"; + else + err = std::string( nativeErr ); + + return NetworkRequestError( *new NetworkRequestErrorPrivate(NetworkRequestError::InternalError, std::move(err), std::move(extraInfo)) ); +} + +NetworkRequestError::NetworkRequestError(zyppng::NetworkRequestErrorPrivate &d ) + : d_ptr( &d ) +{ } + +NetworkRequestError::NetworkRequestError() + : d_ptr( new NetworkRequestErrorPrivate( NoError, {}, {} ) ) +{ } + +NetworkRequestError::Type NetworkRequestError::type() const +{ + return d_func()->_errorCode; +} + +std::string NetworkRequestError::toString() const +{ + return d_func()->_errorMessage; +} + +bool NetworkRequestError::isError() const +{ + return d_func()->_errorCode != NoError; +} + +const std::map &NetworkRequestError::extraInfo() const +{ + return d_func()->_extraInfo; +} + +std::string NetworkRequestErrorPrivate::typeToString( NetworkRequestError::Type t ) +{ + switch ( t ) { + case NetworkRequestError::NoError: + return "No error"; + case NetworkRequestError::InternalError: + return "Internal Error"; + case NetworkRequestError::Cancelled: + return "The request was cancelled"; + case NetworkRequestError::ExceededMaxLen: + return "The request exceeded the maximum download size"; + case NetworkRequestError::InvalidChecksum: + return "The downloaded data did not result in a valid checksum"; + case NetworkRequestError::PeerCertificateInvalid: + return "The peer certificate could not be verified"; + case NetworkRequestError::ConnectionFailed: + return "Connection failed"; + case NetworkRequestError::UnsupportedProtocol: + return "Unsupported protocol"; + case NetworkRequestError::MalformedURL: + return "Bad URL"; + case NetworkRequestError::TemporaryProblem: + return "Requested location is temporarily unaccessible."; + case NetworkRequestError::Timeout: + return "Timeout reached"; + case NetworkRequestError::Forbidden: + return "Access to requested URL is forbidden."; + case NetworkRequestError::NotFound: + return "File not found"; + case NetworkRequestError::Unauthorized: + return "Authentication required but not provided."; + case NetworkRequestError::AuthFailed: + return "Login failed."; + case NetworkRequestError::ServerReturnedError: + return "Server returned an error for the given request."; + case NetworkRequestError::MissingData: + return "Server did not send all requested ranges."; + case NetworkRequestError::RangeFail: + return "Invalid data from server, multipart was requested but there was no range status code."; + case NetworkRequestError::Http2Error: + return "Server returned a HTTP/2 error."; + case NetworkRequestError::Http2StreamError: + return "Server returned a HTTP/2 stream error."; + } + return std::string(); +} + +std::string NetworkRequestError::nativeErrorString() const +{ + Z_D(); + + auto it = d->_extraInfo.find(CurlNativeErrorDescKey.data()); + if ( it != d->_extraInfo.end() ) { + try { + return boost::any_cast( it->second ); + } catch ( const boost::bad_any_cast &) { } + } + + it = d->_extraInfo.find(CurlNativeErrorCodeDescKey.data()); + if ( it != d->_extraInfo.end() ) { + try { + return boost::any_cast( it->second ); + } catch ( const boost::bad_any_cast &) { } + } + + return std::string(); +} + +} diff --git a/zypp-curl/ng/network/networkrequesterror.h b/zypp-curl/ng/network/networkrequesterror.h new file mode 100644 index 0000000..20cefbc --- /dev/null +++ b/zypp-curl/ng/network/networkrequesterror.h @@ -0,0 +1,108 @@ +#ifndef ZYPP_NG_MEDIA_CURL_NETWORK_REQUEST_ERROR_H_INCLUDED +#define ZYPP_NG_MEDIA_CURL_NETWORK_REQUEST_ERROR_H_INCLUDED + +#include +#include +#include +#include +#include + +namespace zyppng { + +class NetworkRequest; +class NetworkRequestErrorPrivate; + + /** + * @brief The NetworkRequestError class + * Represents a error that occured in \see NetworkDownloadRequest + * or \see NetworkRequestDispatcher + * + * + * \attention Keep in sync with zypp/zyppng/proto/networkrequest.proto !!! + */ + class LIBZYPP_NG_EXPORT NetworkRequestError + { + public: + enum Type { + NoError = 0, + InternalError, //< A error in the dispatcher that is not caused by the backend, check the error string + Cancelled, //< The request was cancelled + PeerCertificateInvalid, //< the peer certificate validation failed + ConnectionFailed, //< connecting to the server failed + ExceededMaxLen, //< the downloaded data exceeded the requested maximum lenght + InvalidChecksum, //< The downloaded data has a different checksum than expected + UnsupportedProtocol, //< The protocol given in the URL scheme is not supported by the backend + MalformedURL, //< The given URL is malformed + TemporaryProblem, //< There was a temporary problem with the server side + Timeout, //< The request timed out + Forbidden, //< Accessing the requested ressource on the server was forbidden + NotFound, //< The requested path in the URL does not exist on the server + Unauthorized, //<< No auth data given but authorization required + AuthFailed, //<< Auth data was given, but authorization failed + ServerReturnedError, //<< A error was returned by the server that is not explicitly handled + MissingData, //<< The download was a multirange download and we did not get all data that was requested, if that is returned some ranges might have been downloaded successful + RangeFail, //<< The download was a multirange download but the server decided to return the full file. + Http2Error, //<< Special error code for HTTP2 related errors + Http2StreamError, //<< Special error code for HTTP2 stream related errors + }; + + NetworkRequestError (); + + NetworkRequestError(const NetworkRequestError &) = default; + NetworkRequestError(NetworkRequestError &&) noexcept = default; + NetworkRequestError &operator=(const NetworkRequestError &) = default; + NetworkRequestError &operator=(NetworkRequestError &&) noexcept = default; + /** + * @brief type + * Returns the type of the error + */ + Type type () const; + + /** + * @brief toString + * Returns a string representation of the error + */ + std::string toString () const; + + /** + * @brief isError + * Will return true if this is a actual error + */ + bool isError () const; + + /*! + * Tries to find \a key in the extraInfo map, if the key is not found + * or the value can not be converted to the requested type \a defaultVal is returned. + */ + template + T extraInfoValue ( const std::string &key, T &&defaultVal = T() ) const { + auto &t = extraInfo(); + auto it = t.find(key); + if ( it != t.end() ) { + try { + return boost::any_cast( it->second ); + } catch ( const boost::bad_any_cast &) { } + } + return defaultVal; + } + + /*! + * Returns the error extraInfo map. + */ + const std::map &extraInfo () const; + + /*! + * Returns the string returned by the backend if available. + */ + std::string nativeErrorString() const; + + protected: + NetworkRequestError( NetworkRequestErrorPrivate &d ); + + private: + ZYPP_DECLARE_PRIVATE(NetworkRequestError) + zypp::RWCOW_pointer d_ptr; + }; +} + +#endif diff --git a/zypp-curl/ng/network/private/downloader_p.h b/zypp-curl/ng/network/private/downloader_p.h new file mode 100644 index 0000000..6f9b95b --- /dev/null +++ b/zypp-curl/ng/network/private/downloader_p.h @@ -0,0 +1,117 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADER_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADER_P_H_INCLUDED + +#include + +#include "downloaderstates/base_p.h" +#include "downloaderstates/initial_p.h" +#include "downloaderstates/detectmeta_p.h" +#include "downloaderstates/metalinkinfo_p.h" +#include "downloaderstates/preparemulti_p.h" +#include "downloaderstates/metalink_p.h" +#include "downloaderstates/normal_p.h" +#include "downloaderstates/final_p.h" +#if ENABLE_ZCHUNK_COMPRESSION +#include "downloaderstates/zck_p.h" +#endif + +namespace zyppng { + + /** + * our known states: + * InitialState //< initial state before we start downloading + * DetectMetalinkState //< First attempt to get the zchunk header, but we might receive metalink data instead + * DlMetaLinkInfoState //< We got Metalink, lets get the full metalink file or we got no zchunk in the first place + * PrepareMultiState //< Parsing the metalink file and preparing the mirrors + * DLZckHeadState //< Download the ZChunk Header + * DLZckState //< Download the File in ZChunk Mode + * DlMetalinkState //< Download the File in Metalink Mode + * DlNormalFileState //< Simple Plain download, no chunking + * FinishedState //< We are done + */ + + template + using DownloadStatemachine = Statemachine< Derived, Download::State, + // Source State, State Change Event TargetState, Transition Condition, Transition operation + Transition< InitialState, &InitialState::sigTransitionToDetectMetalinkState, DetectMetalinkState >, + Transition< InitialState, &InitialState::sigTransitionToDlMetaLinkInfoState, DlMetaLinkInfoState >, +#if ENABLE_ZCHUNK_COMPRESSION + Transition< InitialState, &InitialState::sigTransitionToDLZckHeaderState, DLZckHeadState, DefaultStateCondition, &InitialState::toDLZckHeadState >, +#endif + Transition< InitialState, &InitialState::sigTransitionToDlNormalFileState, DlNormalFileState >, + + Transition< DetectMetalinkState, &DetectMetalinkState::sigFinished, DlMetaLinkInfoState, &DetectMetalinkState::toMetalinkGuard, &DetectMetalinkState::toDlMetaLinkInfoState >, +#if ENABLE_ZCHUNK_COMPRESSION + Transition< DetectMetalinkState, &DetectMetalinkState::sigFinished, DLZckHeadState, &DetectMetalinkState::toZckHeadDownloadGuard, &DetectMetalinkState::toDLZckHeadState >, +#endif + Transition< DetectMetalinkState, &DetectMetalinkState::sigFinished, DlNormalFileState, &DetectMetalinkState::toSimpleDownloadGuard >, + + Transition< DlMetaLinkInfoState, &DlMetaLinkInfoState::sigFinished, FinishedState, DefaultStateCondition, &DlMetaLinkInfoState::transitionToFinished >, + Transition< DlMetaLinkInfoState, &DlMetaLinkInfoState::sigGotMetadata, PrepareMultiState, DefaultStateCondition, &DlMetaLinkInfoState::transitionToPrepareMulti >, + Transition< DlMetaLinkInfoState, &DlMetaLinkInfoState::sigFailed, FinishedState, DefaultStateCondition, &DlMetaLinkInfoState::transitionToFinished >, + + Transition< PrepareMultiState, &PrepareMultiState::sigFinished, DlMetalinkState, &PrepareMultiState::toMetalinkDownloadGuard , &PrepareMultiState::transitionToMetalinkDl >, +#if ENABLE_ZCHUNK_COMPRESSION + Transition< PrepareMultiState, &PrepareMultiState::sigFinished, DLZckHeadState, &PrepareMultiState::toZckHeadDownloadGuard, &PrepareMultiState::transitionToZckHeadDl >, +#endif + Transition< PrepareMultiState, &PrepareMultiState::sigFallback, DlNormalFileState, DefaultStateCondition, &PrepareMultiState::fallbackToNormalTransition >, + Transition< PrepareMultiState, &PrepareMultiState::sigFailed, DlNormalFileState >, + +#if ENABLE_ZCHUNK_COMPRESSION + Transition< DLZckHeadState, &DLZckHeadState::sigFinished, DLZckState, DefaultStateCondition, &DLZckHeadState::transitionToDlZckState >, + Transition< DLZckHeadState, &DLZckHeadState::sigFailed, DlNormalFileState >, + + Transition< DLZckState, &DLZckState::sigFinished, FinishedState, DefaultStateCondition, &DLZckState::transitionToFinished >, + Transition< DLZckState, &DLZckState::sigFallback, DlNormalFileState >, +#endif + + Transition< DlMetalinkState, &DlMetalinkState::sigFinished, FinishedState, DefaultStateCondition, &DlMetalinkState::transitionToFinished >, + Transition< DlMetalinkState, &DlMetalinkState::sigFailed, FinishedState, &DlMetalinkState::toFinalStateCondition, &DlMetalinkState::transitionToFinished >, + Transition< DlMetalinkState, &DlMetalinkState::sigFailed, DlNormalFileState, &DlMetalinkState::toSimpleDownloadCondition >, + + Transition< DlNormalFileState, &DlNormalFileState::sigFinished, FinishedState, DefaultStateCondition, &DlNormalFileState::transitionToFinished >, + Transition< DlNormalFileState, &DlNormalFileState::sigFailed, FinishedState, DefaultStateCondition, &DlNormalFileState::transitionToFinished > + >; + + class DownloadPrivate : public DownloadPrivateBase, public DownloadStatemachine + { + public: + DownloadPrivate ( Downloader &parent, std::shared_ptr requestDispatcher, std::shared_ptr mirrors, DownloadSpec &&spec, Download &p ); + void start (); + void init() override; + }; + + class DownloaderPrivate : public BasePrivate + { + ZYPP_DECLARE_PUBLIC(Downloader) + public: + DownloaderPrivate( std::shared_ptr mc, Downloader &p ); + + std::vector< std::shared_ptr > _runningDownloads; + std::shared_ptr _requestDispatcher; + + void onDownloadStarted ( Download &download ); + void onDownloadFinished ( Download &download ); + + Signal< void ( Downloader &parent, Download& download )> _sigStarted; + Signal< void ( Downloader &parent, Download& download )> _sigFinished; + Signal< void ( Downloader &parent )> _queueEmpty; + std::shared_ptr _mirrors; + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/base_p.h b/zypp-curl/ng/network/private/downloaderstates/base_p.h new file mode 100644 index 0000000..0eac110 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/base_p.h @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_BASE_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_BASE_P_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + class NetworkRequestDispatcher; + class DownloadPrivate; + + /*! + * The pimpl for Downloader, the reason this is split up in DownloadPrivateBase and DownloadBase + * is that for defining the States in the Statemachine while making DownloadPrivate the statemachine itself + * we need this separation. This trick allowes the states to "know" the statemachine type and access some of + * its features. + */ + class DownloadPrivateBase : public BasePrivate + { + ZYPP_DECLARE_PUBLIC(Download) + public: + DownloadPrivateBase ( Downloader &parent, std::shared_ptr requestDispatcher, std::shared_ptr mirrors, DownloadSpec &&spec, Download &p ); + ~DownloadPrivateBase () override; + + struct Block { + off_t start = 0; + size_t len = 0; + + std::string chksumtype; + std::optional chksumVec; + std::optional chksumCompareLen; //< initialized if only the first few bytes of the checksum should be considered + std::optional chksumPad; //< initialized if the hashed blocks for a digest need to be padded if a block is smaller ( e.g. last block in a zsync file ) + + int _retryCount = 0; //< how many times was this request restarted + NetworkRequestError _failedWithErr; //< what was the error this request failed with + }; + + struct Request : public NetworkRequest { + + using NetworkRequest::NetworkRequest; + using Ptr = std::shared_ptr; + using WeakPtr = std::shared_ptr; + + template + void connectSignals ( Receiver &dl ) { + _sigStartedConn = connect ( &NetworkRequest::sigStarted, dl, &Receiver::onRequestStarted ); + _sigProgressConn = connect ( &NetworkRequest::sigProgress, dl, &Receiver::onRequestProgress ); + _sigFinishedConn = connect ( &NetworkRequest::sigFinished, dl, &Receiver::onRequestFinished ); + } + void disconnectSignals (); + + time_t _authTimestamp = 0; //< timestamp of the AuthData we tried already + Url _originalUrl; //< The unstripped URL as it was passed to Download , before transfer settings are removed + MirrorControl::MirrorHandle _myMirror; + + connection _sigStartedConn; + connection _sigProgressConn; + connection _sigFinishedConn; + }; + + + bool _emittedSigStart = false; + bool handleRequestAuthError(const std::shared_ptr& req, const zyppng::NetworkRequestError &err); + + NetworkRequestError safeFillSettingsFromURL ( const Url &url, TransferSettings &set ); + +#if ENABLE_ZCHUNK_COMPRESSION + bool hasZckInfo () const; +#endif + + std::shared_ptr _requestDispatcher; + std::shared_ptr _mirrorControl; + + zypp::media::CredentialManager::CredentialSet _credCache; //< the credential cache for this download + + DownloadSpec _spec; // the download settings + mutable zypp::TriBool _specHasZckInfo = zypp::indeterminate; + + Downloader *_parent = nullptr; + + time_t _lastTriedAuthTime = 0; //< if initialized this shows the last timestamp that got from user code for a auth request + bool _stopOnMetalink = false; //< Stop the download if a metalink was received for external parsing + bool _stoppedOnMetalink = false; //< Statemachine was stopped after receiving a metalink file + NetworkRequest::Priority _defaultSubRequestPriority = NetworkRequest::High; + + Signal< void ( Download &req )> _sigStarted; + Signal< void ( Download &req, Download::State state )> _sigStateChanged; + Signal< void ( Download &req, off_t dlnow )> _sigAlive; + Signal< void ( Download &req, off_t dltotal, off_t dlnow )> _sigProgress; + Signal< void ( Download &req )> _sigFinished; + Signal< void ( zyppng::Download &req, zyppng::NetworkAuthData &auth, const std::string &availAuth )> _sigAuthRequired; + + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.cc b/zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.cc new file mode 100644 index 0000000..cf6ea31 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.cc @@ -0,0 +1,211 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +#include + +#include "basicdownloader_p.h" + +namespace zyppng { + + BasicDownloaderStateBase::BasicDownloaderStateBase(std::shared_ptr &&req, DownloadPrivate &parent) + : MirrorHandlingStateBase( parent ) + , _request( std::move(req) ) + { } + + void BasicDownloaderStateBase::enter() + { + if ( _request ) { + const auto &spec = stateMachine()._spec; + MIL_MEDIA << "Reusing request from previous state" << std::endl; + _request->setOptions( Request::Default ); + _request->setPriority( Request::Normal ); + _request->resetRequestRanges(); + _request->setTargetFilePath( spec.targetPath() ); + _request->setFileOpenMode( Request::WriteExclusive ); + _request->transferSettings() = spec.settings(); + startRequest(); + return; + } + + if ( _fileMirrors.size() ) { + const auto res = prepareNextMirror(); + // for Delayed or OK we can just continue here + if ( res != MirrorHandlingStateBase::Failed ) + return; + } + failedToPrepare(); + } + + void BasicDownloaderStateBase::exit() + { + if ( _request ) { + _request->disconnectSignals(); + _request.reset(); + } + } + + void BasicDownloaderStateBase::mirrorReceived( MirrorControl::MirrorPick mirror ) + { + auto &sm = stateMachine(); + auto url = sm._spec.url(); + auto set = sm._spec.settings(); + + auto err = setupMirror( mirror, url, set ); + if ( err.isError() ) { + WAR << "Setting up mirror " << mirror.second->mirrorUrl << " failed with error: " << err.toString() << "(" << err.nativeErrorString() << "), falling back to original URL." << std::endl; + failedToPrepare(); + } + startWithMirror( mirror.second, url, set ); + } + + void BasicDownloaderStateBase::failedToPrepare() + { + startWithoutMirror(); + } + + void BasicDownloaderStateBase::startWithMirror( MirrorControl::MirrorHandle mirror, const zypp::Url &url, const TransferSettings &set ) + { + auto &sm = stateMachine(); + const auto &spec = sm._spec; + + _request = std::make_shared( ::internal::clearQueryString(url), spec.targetPath() ) ; + _request->_myMirror = std::move(mirror); + _request->_originalUrl = url; + _request->transferSettings() = set; + + startRequest(); + } + + void BasicDownloaderStateBase::startWithoutMirror() + { + auto &sm = stateMachine(); + const auto &spec = sm._spec; + + auto url = spec.url(); + auto set = spec.settings(); + auto err = sm.safeFillSettingsFromURL( url, set ); + if ( err.isError() ) + return failed( std::move(err) ); + startWithMirror( nullptr, url, set ); + } + + void BasicDownloaderStateBase::startRequest() + { + auto &sm = stateMachine(); + + if ( !_request ) + return failed("Request was not intialized before starting it."); + + if ( _chksumtype && _chksumVec ) { + std::optional fileDigest = zypp::Digest(); + if ( fileDigest->create( *_chksumtype ) ) + // to run the checksum for the full file we need to request one big range with open end + _request->addRequestRange( 0, 0, std::move(fileDigest), *_chksumVec ); + } + + if ( sm._spec.checkExistsOnly() ) + _request->setOptions( _request->options() | Request::HeadRequest ); + + if ( !initializeRequest( _request ) ) { + return failed( "Failed to initialize request" ); + } + + if ( stateMachine().previousState() && *stateMachine().previousState() != Download::InitialState ) { + //make sure this request will run asap + _request->setPriority( sm._defaultSubRequestPriority ); + } + + _request->connectSignals( *this ); + sm._requestDispatcher->enqueue( _request ); + } + + bool BasicDownloaderStateBase::initializeRequest( std::shared_ptr & ) + { + return true; + } + + void BasicDownloaderStateBase::gotFinished() + { + _sigFinished.emit(); + } + + void BasicDownloaderStateBase::failed( std::string &&str ) + { + failed( NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, std::move(str) ) ); + } + + void BasicDownloaderStateBase::failed( NetworkRequestError &&err ) + { + _error = std::move( err ); + zypp::filesystem::unlink( stateMachine()._spec.targetPath() ); + + _sigFailed.emit(); + } + + void BasicDownloaderStateBase::onRequestStarted( NetworkRequest & ) + { + auto &sm = stateMachine(); + if ( !sm._emittedSigStart ) { + sm._emittedSigStart = true; + stateMachine()._sigStarted.emit( *stateMachine().z_func() ); + } + if ( _request->_myMirror ) + _request->_myMirror->startTransfer(); + } + + void BasicDownloaderStateBase::handleRequestProgress( NetworkRequest &req, off_t dltotal, off_t dlnow ) + { + auto &sm = stateMachine(); + const off_t expFSize = sm._spec.expectedFileSize(); + if ( expFSize > 0 && expFSize < req.downloadedByteCount() ) { + sm._requestDispatcher->cancel( req, NetworkRequestErrorPrivate::customError( NetworkRequestError::ExceededMaxLen ) ); + return; + } + return sm._sigProgress.emit( *sm.z_func(), (expFSize > 0 ? expFSize : dltotal), dlnow ); + } + + void BasicDownloaderStateBase::onRequestProgress( NetworkRequest &req, off_t dltotal, off_t dlnow, off_t, off_t ) + { + handleRequestProgress( req, dltotal, dlnow ); + } + + void BasicDownloaderStateBase::onRequestFinished( NetworkRequest &req, const NetworkRequestError &err ) + { + auto lck = stateMachine().z_func()->shared_from_this(); + auto &sm = stateMachine(); + + if ( _request->_myMirror ) + _request->_myMirror->finishTransfer( !err.isError() ); + + if ( req.hasError() ) { + // if we get authentication failure we try to recover + if ( sm.handleRequestAuthError( _request, err ) ) { + //make sure this request will run asap + _request->setPriority( sm._defaultSubRequestPriority ); + sm._requestDispatcher->enqueue( _request ); + return; + } + + MIL << req.nativeHandle() << " " << "Downloading on " << stateMachine()._spec.url() << " failed with error "<< err.toString() << " " << err.nativeErrorString() << std::endl; + if ( req.lastRedirectInfo ().size () ) + MIL << req.nativeHandle() << " Last redirection target was: " << req.lastRedirectInfo () << std::endl; + + return failed( NetworkRequestError(err) ); + } + + gotFinished(); + } + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.h b/zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.h new file mode 100644 index 0000000..56882c3 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/basicdownloader_p.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_BASICDOWNLOADER_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_BASICDOWNLOADER_P_H_INCLUDED + +#include "base_p.h" +#include "mirrorhandling_p.h" +#include + +namespace zyppng { + + /*! + * State implementation for the generic part of a simple file downloader, that knows + * how to use the mirrors if available. + */ + struct BasicDownloaderStateBase : public MirrorHandlingStateBase { + + using Request = DownloadPrivateBase::Request; + + BasicDownloaderStateBase ( DownloadPrivate &parent ) : MirrorHandlingStateBase( parent ){} + BasicDownloaderStateBase ( std::shared_ptr &&req, DownloadPrivate &parent ); + + void enter (); + void exit (); + + virtual bool initializeRequest ( std::shared_ptr &r ); + virtual void gotFinished (); + virtual void failed(NetworkRequestError &&err); + void failed (std::string &&str ); + + void onRequestStarted ( NetworkRequest & ); + void onRequestProgress ( NetworkRequest &, off_t dltotal, off_t dlnow, off_t, off_t ); + void onRequestFinished ( NetworkRequest &req , const NetworkRequestError &err ); + + const NetworkRequestError &error () const { + return _error; + } + + std::shared_ptr _request; + std::optional _chksumtype; //< The file checksum type if available + std::optional _chksumVec; //< The file checksum if available + + // MirrorHandlingStateBase interface + void mirrorReceived(MirrorControl::MirrorPick mirror) override; + void failedToPrepare() override; + + protected: + void startWithMirror ( MirrorControl::MirrorHandle mirror, const zypp::Url &url, const TransferSettings &set ); + void startWithoutMirror ( ); + void startRequest (); + virtual void handleRequestProgress (NetworkRequest &req, off_t dltotal, off_t dlnow ); + NetworkRequestError _error; + Signal< void () > _sigFinished; + Signal< void () > _sigFailed; + + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/detectmeta_p.cc b/zypp-curl/ng/network/private/downloaderstates/detectmeta_p.cc new file mode 100644 index 0000000..9c34bb5 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/detectmeta_p.cc @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include + +#include "detectmeta_p.h" +#include "metalinkinfo_p.h" + +namespace zyppng { + + DetectMetalinkState::DetectMetalinkState(DownloadPrivate &parent) : SimpleState( parent ){ + MIL << "Entering DetectMetalinkState for url: " << parent._spec.url() << std::endl; + } + + void DetectMetalinkState::enter() + { + _request.reset(); + _gotMetalink = false; + + auto &sm = stateMachine(); + const auto &url = sm._spec.url(); + + MIL_MEDIA << "Detecting if metalink is available on " << url << std::endl; + + _request = std::make_shared( ::internal::clearQueryString( url ), zypp::Pathname("/dev/null") ); + + _request->_originalUrl = url; + _request->transferSettings() = sm._spec.settings(); + _request->transferSettings().addHeader("Accept: */*, application/metalink+xml, application/metalink4+xml"); + _request->setOptions( _request->options() | NetworkRequest::HeadRequest ); + + _request->connectSignals( *this ); + sm._requestDispatcher->enqueue( _request ); + } + + void DetectMetalinkState::exit() + { + if ( _request ) { + _request->disconnectSignals(); + _request.reset(); + } + } + + void DetectMetalinkState::onRequestStarted( NetworkRequest & ) + { + stateMachine()._sigStarted.emit( *stateMachine().z_func() ); + } + + void DetectMetalinkState::onRequestProgress( NetworkRequest &, off_t, off_t dlnow, off_t, off_t ) + { + stateMachine()._sigAlive.emit( *stateMachine().z_func(), dlnow ); + } + + void DetectMetalinkState::onRequestFinished( NetworkRequest &req, const NetworkRequestError &err ) + { + auto lck = stateMachine().z_func()->shared_from_this(); + if ( req.hasError() ) { + WAR << req.nativeHandle() << " " << "Detecing if metalink is possible for url " << req.url() << " failed with error " << err.toString() << " falling back to download without metalink." << std::endl; + if ( req.lastRedirectInfo ().size () ) + WAR << req.nativeHandle() << " Last redirection target was: " << req.lastRedirectInfo () << std::endl; + + _error = err; + _gotMetalink = false; + return _sigFinished.emit(); + } + + std::string cType = req.contentType(); + _gotMetalink = ( cType.find("application/metalink+xml") == 0 || cType.find("application/metalink4+xml") == 0 ); + MIL << req.nativeHandle() << " " << "Metalink detection result on url " << req.url() << " is " << _gotMetalink << std::endl; + _sigFinished.emit(); + } + + std::shared_ptr DetectMetalinkState::toDlMetaLinkInfoState() + { + _request->disconnectSignals(); + auto nState = std::make_shared( std::move( _request ), stateMachine() ); + _request = nullptr; + return nState; + } + + bool DetectMetalinkState::toSimpleDownloadGuard() const + { +#if ENABLE_ZCHUNK_COMPRESSION + return !toMetalinkGuard() && !toZckHeadDownloadGuard(); +#else + return !toMetalinkGuard(); +#endif + } + +#if ENABLE_ZCHUNK_COMPRESSION + bool DetectMetalinkState::toZckHeadDownloadGuard() const + { + return !toMetalinkGuard() && stateMachine().hasZckInfo(); + } + + std::shared_ptr DetectMetalinkState::toDLZckHeadState() + { + // we have no mirrors, the range downloader would need to fall back to using the base URL + if ( _error.isError() || !_request ) + return std::make_shared( std::vector { stateMachine()._spec.url() }, stateMachine() ); + else { + // reuse our request + _request->disconnectSignals(); + auto nstate = std::make_shared( std::vector { stateMachine()._spec.url() }, std::move(_request), stateMachine() ); + _request = nullptr; + return nstate; + } + } +#endif + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/detectmeta_p.h b/zypp-curl/ng/network/private/downloaderstates/detectmeta_p.h new file mode 100644 index 0000000..fb35418 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/detectmeta_p.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_DETECTMETA_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_DETECTMETA_P_H_INCLUDED + +#include "base_p.h" +#include + +namespace zyppng { + + struct DlMetaLinkInfoState; +#if ENABLE_ZCHUNK_COMPRESSION + struct DLZckHeadState; +#endif + + /*! + * State implementation for the metalink detection phase, + * this state issues a HEAD request while setting the magic + * "Accept: *\/\*, application/metalink+xml, application/metalink4+xml" + * header in the request to figure out if a metalink file is available or not. + * + * In order to use metalink support the server + * needs to correctly return the metalink file content type, + * otherwise we proceed to not downloading a metalink file + */ + struct DetectMetalinkState : public zyppng::SimpleState< DownloadPrivate, Download::DetectMetaLink, false > { + + using Request = DownloadPrivateBase::Request; + + DetectMetalinkState ( DownloadPrivate &parent ); + + void enter (); + void exit (); + + void onRequestStarted ( NetworkRequest & ); + void onRequestProgress ( NetworkRequest &, off_t, off_t dlnow, off_t, off_t ); + void onRequestFinished ( NetworkRequest &req , const NetworkRequestError &err ); + + + const NetworkRequestError &error () const { + return _error; + } + + SignalProxy< void () > sigFinished() { + return _sigFinished; + } + + bool toMetalinkGuard () const { + return _gotMetalink; + } + std::shared_ptr toDlMetaLinkInfoState(); + + bool toSimpleDownloadGuard () const; + +#if ENABLE_ZCHUNK_COMPRESSION + bool toZckHeadDownloadGuard () const; + std::shared_ptr toDLZckHeadState(); +#endif + + std::shared_ptr _request; + + private: + NetworkRequestError _error; + bool _gotMetalink = false; + Signal< void () > _sigFinished; + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/final_p.cc b/zypp-curl/ng/network/private/downloaderstates/final_p.cc new file mode 100644 index 0000000..1dcb3c0 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/final_p.cc @@ -0,0 +1,23 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include "final_p.h" + +namespace zyppng { + + FinishedState::FinishedState(NetworkRequestError &&error, DownloadPrivate &parent) + : SimpleState( parent ) + , _error( std::move(error) ) + { + MIL << "About to enter FinishedState for url " << parent._spec.url() << std::endl; + } + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/final_p.h b/zypp-curl/ng/network/private/downloaderstates/final_p.h new file mode 100644 index 0000000..039aa694 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/final_p.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_FINAL_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_FINAL_P_H_INCLUDED + +#include "base_p.h" +#include + +namespace zyppng { + + /*! + * Final state implementation, we enter this state as the very last step. It carries + * the result of the whole operation. + */ + struct FinishedState : public SimpleState< DownloadPrivate, Download::Finished, true > + { + FinishedState ( NetworkRequestError &&error, DownloadPrivate &parent ); + + void enter (){} + void exit (){} + + NetworkRequestError _error; + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/initial_p.cc b/zypp-curl/ng/network/private/downloaderstates/initial_p.cc new file mode 100644 index 0000000..a764688 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/initial_p.cc @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include + +#include "initial_p.h" +#if ENABLE_ZCHUNK_COMPRESSION +#include "zck_p.h" +#endif + +namespace zyppng { + + void InitialState::enter(){ MIL_MEDIA << "Entering initial state" << std::endl; } + + void InitialState::exit(){ MIL_MEDIA << "Leaving initial state" << std::endl; } + + void InitialState::initiate() + { + auto &sm = stateMachine(); + const auto &spec = sm._spec; + + if ( spec.checkExistsOnly() ) { + MIL_MEDIA << "Check exists only enabled" << std::endl; + return _sigTransitionToDlNormalFileState.emit(); + } + +#if ENABLE_ZCHUNK_COMPRESSION + bool deltaZck = isZchunkFile( spec.deltaFile() ); +#endif + if ( spec.metalinkEnabled() ) { +#if ENABLE_ZCHUNK_COMPRESSION + if ( deltaZck && spec.headerSize() > 0 ) { + MIL_MEDIA << "We might have a zck file, detecting metalink first" << std::endl; + return _sigTransitionToDetectMetalinkState.emit(); + } +#endif + MIL_MEDIA << "No zchunk data available but metalink requested, going to download metalink directly." << std::endl; + return _sigTransitionToDlMetaLinkInfoState.emit(); + } + +#if ENABLE_ZCHUNK_COMPRESSION + // no Metalink, maybe we can directly download zck + if ( deltaZck && spec.headerSize() > 0 ) { + MIL_MEDIA << "No metalink but zckunk data availble trying to download ZckHead directly." << std::endl; + return _sigTransitionToDLZckHeaderState.emit(); + } +#endif + MIL_MEDIA << "Fallback to normal DL" << std::endl; + _sigTransitionToDlNormalFileState.emit(); + } + +#if ENABLE_ZCHUNK_COMPRESSION + std::shared_ptr InitialState::toDLZckHeadState() + { + // we have no mirrors, the range downloader would need to fall back to using the base URL + return std::make_shared( std::vector { stateMachine()._spec.url() }, stateMachine() ); + } +#endif + + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/initial_p.h b/zypp-curl/ng/network/private/downloaderstates/initial_p.h new file mode 100644 index 0000000..7ef6989 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/initial_p.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_INITIAL_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_INITIAL_P_H_INCLUDED + +#include "base_p.h" +#include + +namespace zyppng { + +#if ENABLE_ZCHUNK_COMPRESSION + struct DLZckHeadState; +#endif + + /*! + * Initial state implementation, this state is used only to kickstart the statemachine + */ + struct InitialState : public zyppng::SimpleState< DownloadPrivate, Download::InitialState, false > { + + InitialState ( DownloadPrivate &parent ) : SimpleState( parent ){} + + void enter ();; + void exit (); + + void initiate(); + + SignalProxy< void () > sigTransitionToDetectMetalinkState() { + return _sigTransitionToDetectMetalinkState; + } + + SignalProxy< void () > sigTransitionToDlMetaLinkInfoState() { + return _sigTransitionToDlMetaLinkInfoState; + } + +#if ENABLE_ZCHUNK_COMPRESSION + SignalProxy< void () > sigTransitionToDLZckHeaderState() { + return _sigTransitionToDLZckHeaderState; + } +#endif + + SignalProxy< void () > sigTransitionToDlNormalFileState() { + return _sigTransitionToDlNormalFileState; + } + +#if ENABLE_ZCHUNK_COMPRESSION + std::shared_ptr toDLZckHeadState (); +#endif + + private: + Signal _sigTransitionToDetectMetalinkState; + Signal _sigTransitionToDlMetaLinkInfoState; +#if ENABLE_ZCHUNK_COMPRESSION + Signal _sigTransitionToDLZckHeaderState; +#endif + Signal _sigTransitionToDlNormalFileState; + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/metalink_p.cc b/zypp-curl/ng/network/private/downloaderstates/metalink_p.cc new file mode 100644 index 0000000..2053b00 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/metalink_p.cc @@ -0,0 +1,164 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "metalink_p.h" +#include "final_p.h" + + #include +#include + +namespace zyppng { + + DlMetalinkState::DlMetalinkState(zypp::media::MediaBlockList &&blockList, std::vector &&mirrors, DownloadPrivate &parent) + : RangeDownloaderBaseState( std::move(mirrors), parent ) + , _blockList( std::move(blockList) ) + { + MIL << "About to enter DlMetalinkState for url " << parent._spec.url() << std::endl; + } + + void DlMetalinkState::enter() + { + auto &sm = stateMachine(); + const auto &spec = sm._spec; + + _fileSize = sm._spec.expectedFileSize(); + + //first we try to reuse blocks from the deltafile , if we have one + if ( !spec.deltaFile().empty() ) { + zypp::PathInfo dFileInfo ( spec.deltaFile() ); + if ( dFileInfo.isFile() && dFileInfo.isR() ) { + FILE *f = fopen( spec.targetPath().asString().c_str(), "w+b" ); + if ( !f ) { + setFailed( NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, zypp::str::Format("Failed to open target file.(errno %1%)" ) % errno ) ); + return; + } + + try { + _blockList.reuseBlocks ( f, spec.deltaFile().asString() ); + } catch ( ... ) { } + + fclose( f ); + } else { + DBG << "Delta XFER: Delta file: " << spec.deltaFile() << " does not exist or is not readable." << std::endl; + } + } else { + DBG << "Delta XFER: No delta file given, can not reuse blocks." << std::endl; + } + + // setup the base downloader + _error = {}; + _ranges.clear(); + _failedRanges.clear(); + _downloadedMultiByteCount = 0; + + if ( _blockList.haveFileChecksum() ) { + _fileChecksumType = _blockList.fileChecksumType(); + _fileChksumVec = _blockList.getFileChecksum(); + } + + const size_t fLen = _blockList.getFilesize(); + if ( _fileSize > 0 ) { + // check if the file size as reported by zchunk is equal to the one we expect + if ( _fileSize != fLen ) { + return setFailed( NetworkRequestErrorPrivate::customError( + NetworkRequestError::ExceededMaxLen, + zypp::str::Format("Metalink file reports a different filesize than what was expected ( Meta: %1% != Exp: %2%).") % fLen % _fileSize ) + ); + } + } else { + _fileSize = fLen; + } + + const auto maxConns = sm._requestDispatcher->maximumConcurrentConnections(); + if ( sm._spec.preferredChunkSize() == 0 ) { + const auto autoBlkSize = makeBlksize( _fileSize ); + if ( maxConns == -1 ) { + _preferredChunkSize = autoBlkSize; + } else { + _preferredChunkSize = _fileSize / maxConns; + if ( _preferredChunkSize < autoBlkSize ) + _preferredChunkSize = autoBlkSize; + else if ( _preferredChunkSize > zypp::ByteCount( 100, zypp::ByteCount::M ) ) + _preferredChunkSize = zypp::ByteCount( 100, zypp::ByteCount::M ); + } + } else { + // spec chunk size overrules the automatic one + _preferredChunkSize = sm._spec.preferredChunkSize(); + } + + MIL << "Downloading " << sm._spec.url() << " with " << _preferredChunkSize << " chunk size over " << maxConns << std::endl; + + // remember how many bytes we need to download + size_t bytesToDl = 0; + // do we need to pad the digest when calculating the checksum for blocks + const auto &chksumPad = _blockList.checksumPad (); + for ( size_t i = 0; i < _blockList.numBlocks(); i++ ) { + const auto &mediaBlock = _blockList.getBlock( i ); + const auto &blockSum = _blockList.getChecksum ( i ); + _ranges.push_back( + Block{ + .start = mediaBlock.off, + .len = mediaBlock.size, + .chksumtype = _blockList.getChecksumType(), + .chksumVec = blockSum, + .chksumCompareLen = blockSum.size( ), + .chksumPad = chksumPad > 0 ? chksumPad : std::optional() + } ); + + bytesToDl += mediaBlock.size; + } + // substract the length of the blocks we have to download from the overall file size + _downloadedMultiByteCount = fLen - bytesToDl; + + ensureDownloadsRunning(); + } + + void DlMetalinkState::exit() + { + cancelAll( NetworkRequestError() ); + } + + void DlMetalinkState::setFinished() + { + if ( _fileChecksumType.size() && _fileChksumVec ) { + //TODO move this into a external application so we do not need to block on it + //need to check file digest + zypp::Digest dig; + dig.create( _fileChecksumType ); + + std::ifstream istrm( stateMachine()._spec.targetPath().asString(), std::ios::binary); + if ( !istrm.is_open() ) { + setFailed( "Failed to verify file digest (Could not open target file)." ); + return; + } + if ( !dig.update( istrm ) ) { + setFailed( "Failed to verify file digest (Could not read target file)." ); + return; + } + + const auto &calculatedChksum = dig.digestVector(); + if ( *_fileChksumVec != calculatedChksum ) { + setFailed( "Failed to verify file digest (Checksum did not match)." ); + return; + } + } + RangeDownloaderBaseState::setFinished(); + } + + std::shared_ptr DlMetalinkState::transitionToFinished() + { + return std::make_shared( std::move(_error), stateMachine() ); + } + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/metalink_p.h b/zypp-curl/ng/network/private/downloaderstates/metalink_p.h new file mode 100644 index 0000000..8f7d1b0 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/metalink_p.h @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_METALINK_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_METALINK_P_H_INCLUDED + +#include "base_p.h" +#include "rangedownloader_p.h" +#include + +#include + +namespace zyppng { + + struct FinishedState; + + /*! + * Metalink download state implementation, this downloads the requested file + * in metalink ranges. + */ + struct DlMetalinkState : public RangeDownloaderBaseState { + + static constexpr auto stateId = Download::DlMetalink; + + DlMetalinkState ( zypp::media::MediaBlockList &&blockList, std::vector &&mirrors, DownloadPrivate &parent ); + + void enter (); + void exit (); + void setFinished () override; + + std::shared_ptr transitionToFinished (); + + // in case of error we might fall back, except for the errors listed here + bool toFinalStateCondition () { + return ( _error.type() == NetworkRequestError::Unauthorized + || _error.type() == NetworkRequestError::AuthFailed ); + } + + bool toSimpleDownloadCondition () { + return !toFinalStateCondition(); + } + + SignalProxy< void () > sigFinished() { + return _sigFinished; + } + + SignalProxy< void () > sigFailed() { + return _sigFailed; + } + + private: + zypp::media::MediaBlockList _blockList; + std::string _fileChecksumType; + std::optional> _fileChksumVec; + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.cc b/zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.cc new file mode 100644 index 0000000..c6a3221 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.cc @@ -0,0 +1,123 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "metalinkinfo_p.h" + +namespace zyppng { + + namespace { + } + + DlMetaLinkInfoState::DlMetaLinkInfoState(DownloadPrivate &parent) + : BasicDownloaderStateBase( parent ) + { + MIL << "Downloading metalink/zsync on " << parent._spec.url() << std::endl; + } + + DlMetaLinkInfoState::DlMetaLinkInfoState(std::shared_ptr &&prevRequest, DownloadPrivate &parent) + : BasicDownloaderStateBase( std::move(prevRequest), parent ) + { + MIL << "Downloading metalink/zsync on " << parent._spec.url() << std::endl; + } + + std::shared_ptr DlMetaLinkInfoState::transitionToFinished() + { + MIL << "Downloading on " << stateMachine()._spec.url() << " transition to final state. " << std::endl; + return std::make_shared( std::move(_error), stateMachine() ); + } + + std::shared_ptr DlMetaLinkInfoState::transitionToPrepareMulti() + { + _request->disconnectSignals(); + auto prepareMode = ( _detectedMetaType == MetaDataType::MetaLink ? PrepareMultiState::Metalink : PrepareMultiState::Zsync ); + auto nState = std::make_shared( std::move( _request ), prepareMode, stateMachine() ); + _request = nullptr; + return nState; + } + + bool DlMetaLinkInfoState::initializeRequest(std::shared_ptr &r ) + { + MIL << "Requesting Metadata info from server!" << std::endl; + r->transferSettings().addHeader("Accept: */*, application/x-zsync, application/metalink+xml, application/metalink4+xml"); + return BasicDownloaderStateBase::initializeRequest(r); + } + + void DlMetaLinkInfoState::gotFinished() + { + // some proxies do not store the content type, so also look at the file to find + // out if we received a metalink (bnc#649925) + if ( _detectedMetaType == MetaDataType::None ) + _detectedMetaType = zypp::media::looks_like_meta_file( _request->targetFilePath() ); + if ( _detectedMetaType == MetaDataType::None ) { + // Move to finished state + MIL << "Downloading on " << stateMachine()._spec.url() << " was successful, no metalink/zsync data. " << std::endl; + return BasicDownloaderStateBase::gotFinished(); + } + + auto &sm = stateMachine(); + if ( sm._stopOnMetalink ) { + MIL << "Stopping after receiving MetaData as requested" << std::endl; + sm._stoppedOnMetalink = true; + return BasicDownloaderStateBase::gotFinished(); + } + + // Move to Prepare Multi state + if ( _detectedMetaType == MetaDataType::Zsync ) + MIL << "Downloading on " << sm._spec.url() << " returned a Zsync file " << std::endl; + else + MIL << "Downloading on " << sm._spec.url() << " returned a Metalink file" << std::endl; + _sigGotMetadata.emit(); + } + + void DlMetaLinkInfoState::handleRequestProgress(NetworkRequest &req, off_t dltotal, off_t dlnow) + { + auto &sm = stateMachine(); + + if ( _detectedMetaType == MetaDataType::None && dlnow < zypp::media::minMetalinkProbeSize ) { + // can't tell yet, ... + return sm._sigAlive.emit( *sm.z_func(), dlnow ); + } + + if ( _detectedMetaType == MetaDataType::None ) { + std::string cType = req.contentType(); + if ( cType.find("application/x-zsync") == 0 ) + _detectedMetaType = MetaDataType::Zsync; + else if ( cType.find("application/metalink+xml") == 0 || cType.find("application/metalink4+xml") == 0 ) + _detectedMetaType = MetaDataType::MetaLink; + } + + if ( _detectedMetaType == MetaDataType::None ) { + _detectedMetaType = zypp::media::looks_like_meta_data( req.peekData( 0, zypp::media::minMetalinkProbeSize ) ); + } + + if ( _detectedMetaType != MetaDataType::None ) { + // this is a metalink file change the expected filesize + if ( zypp::ByteCount( 2, zypp::ByteCount::MB) < req.downloadedByteCount() ) { + WAR << "Metadata file exceeds 2MB in filesize, aborting."<cancel( req, NetworkRequestErrorPrivate::customError( NetworkRequestError::ExceededMaxLen ) ); + return; + } + + return sm._sigAlive.emit( *sm.z_func(), dlnow ); + + } else { + // still no metalink, we assume a normal download, not perfect though + if ( !_fallbackMilWritten ) { + _fallbackMilWritten = true; + MIL << "No Metalink file detected after " << zypp::media::minMetalinkProbeSize << ", falling back to normal progress updates" << std::endl; + } + return BasicDownloaderStateBase::handleRequestProgress( req, dltotal, dlnow ); + } + } +} diff --git a/zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.h b/zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.h new file mode 100644 index 0000000..7f0742d --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/metalinkinfo_p.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_METALINKINFO_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_METALINKINFO_P_H_INCLUDED + +#include "base_p.h" +#include "basicdownloader_p.h" +#include +#include + +namespace zyppng { + + struct FinishedState; + struct PrepareMultiState; + + using MetaDataType = zypp::media::MetaDataType; + + /*! + * State to download the actual metalink file, we can however not be 100% sure that we actually + * will get a metalink file, so we need to check the content type or in bad cases the + * data we get from the server. + */ + struct DlMetaLinkInfoState : public BasicDownloaderStateBase { + static constexpr auto stateId = Download::DlMetaLinkInfo; + + DlMetaLinkInfoState( DownloadPrivate &parent ); + DlMetaLinkInfoState( std::shared_ptr &&prevRequest, DownloadPrivate &parent ); + + SignalProxy< void () > sigFinished() { + return _sigFinished; + } + SignalProxy< void () > sigGotMetadata() { + return _sigGotMetadata; + } + SignalProxy< void () > sigFailed() { + return _sigFailed; + } + + std::shared_ptr transitionToFinished (); + std::shared_ptr transitionToPrepareMulti (); + + bool initializeRequest( std::shared_ptr &r ) override; + void gotFinished () override; + + protected: + MetaDataType _detectedMetaType = MetaDataType::None; + Signal< void () > _sigGotMetadata; + + void handleRequestProgress ( NetworkRequest &req, off_t dltotal, off_t dlnow ) override; + + private: + bool _fallbackMilWritten = false; //< Flag to know if we already logged that we fall back to the normal progress + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.cc b/zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.cc new file mode 100644 index 0000000..b26c8a4 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.cc @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include + +#include "mirrorhandling_p.h" + +namespace zyppng { + + MirrorHandlingStateBase::MirrorHandlingStateBase( DownloadPrivate &parent ) + : BasicState(parent) + { } + + MirrorHandlingStateBase::~MirrorHandlingStateBase() + { + _sigMirrorsReadyConn.disconnect(); + } + + MirrorHandlingStateBase::PrepareResult MirrorHandlingStateBase::prepareNextMirror() + { + auto &sm = stateMachine(); + auto res = sm._mirrorControl->pickBestMirror( _fileMirrors ); + if ( res.code == MirrorControl::PickResult::Again ) { + if ( !_sigMirrorsReadyConn ) + _sigMirrorsReadyConn = sm._mirrorControl->connectFunc( &MirrorControl::sigNewMirrorsReady, [this](){ + _sigMirrorsReadyConn.disconnect(); + prepareNextMirror(); + }, *this ); + return Delayed; + } else if ( res.code == MirrorControl::PickResult::Unknown ) { + failedToPrepare(); + return Failed; + } + mirrorReceived( res.result ); + return Ok; + } + + NetworkRequestError MirrorHandlingStateBase::setupMirror( const MirrorControl::MirrorPick &pick, Url &url, TransferSettings &set ) + { + auto &sm = stateMachine(); + Url myUrl; + TransferSettings settings; + + myUrl = *pick.first; + + settings = sm._spec.settings(); + //if this is a different host than the initial request, we reset username/password + if ( myUrl.getHost() != sm._spec.url().getHost() ) { + settings.setUsername( std::string() ); + settings.setPassword( std::string() ); + settings.setAuthType( std::string() ); + } + + NetworkRequestError err = sm.safeFillSettingsFromURL( myUrl, settings ); + if ( err.type() != NetworkRequestError::NoError ) + return err; + + url = myUrl; + set = settings; + return err; + } + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.h b/zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.h new file mode 100644 index 0000000..b061bd3 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/mirrorhandling_p.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_MIRRORHANDLING_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_MIRRORHANDLING_P_H_INCLUDED + +#include +#include "base_p.h" + +namespace zyppng { + + /*! + * superclass state implementation for all states that need to handle async mirror requests + */ + struct MirrorHandlingStateBase : public zyppng::BasicState< DownloadPrivate, false > + { + + MirrorHandlingStateBase ( DownloadPrivate &parent ); + ~MirrorHandlingStateBase() override; + enum PrepareResult { + Failed, + Ok, + Delayed + }; + + /*! + * Request a new mirror, the \a PrepareResult shows if \ref setupMirror was already called + * or if the request was \a Delayed. + */ + PrepareResult prepareNextMirror (); + + + /*! + * Common code to setup a mirror after it was received, can result in errors if the mirror url contains + * settings that are invalid. + * Will return settings and url via parameters. + */ + NetworkRequestError setupMirror( const MirrorControl::MirrorPick &pick, Url &url, TransferSettings &set ); + + /*! + * This is called once a mirror became ready, either directly if a mirror is ready or it was delayed + * and called asynchronously + */ + virtual void mirrorReceived ( MirrorControl::MirrorPick mirror ) = 0; + + /*! + * Gets called in case a mirror failed to prepare, + * probably because none of the mirrors in \a _fileMirrors is known by \ref MirrorControl + */ + virtual void failedToPrepare (){}; + + std::vector _fileMirrors; //< all mirrors of the currently requested file + + private: + connection _sigMirrorsReadyConn; //< the internal connection to the mirrors ready signal + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/normal_p.cc b/zypp-curl/ng/network/private/downloaderstates/normal_p.cc new file mode 100644 index 0000000..9a29168 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/normal_p.cc @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include + +#include "normal_p.h" +#include "final_p.h" + +namespace zyppng { + + DlNormalFileState::DlNormalFileState( DownloadPrivate &parent ) : BasicDownloaderStateBase( parent ) + { + MIL << "About to enter DlNormalFileState for url " << parent._spec.url() << std::endl; + } + + + DlNormalFileState::DlNormalFileState( std::shared_ptr &&oldReq, DownloadPrivate &parent ) : BasicDownloaderStateBase( std::move(oldReq), parent ) + { + MIL << "About to enter DlNormalFileState for url " << parent._spec.url() << std::endl; + } + + std::shared_ptr DlNormalFileState::transitionToFinished() + { + return std::make_shared( std::move(_error), stateMachine() ); + } + + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/normal_p.h b/zypp-curl/ng/network/private/downloaderstates/normal_p.h new file mode 100644 index 0000000..d8b0114 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/normal_p.h @@ -0,0 +1,47 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_NORMAL_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_NORMAL_P_H_INCLUDED + +#include "base_p.h" +#include "basicdownloader_p.h" +#include + +namespace zyppng { + + struct FinishedState; + + /*! + * Just a plain normal file download, no metalink, nothing fancy. + * If this fails we have no more fallbacks + */ + struct DlNormalFileState : public BasicDownloaderStateBase { + static constexpr auto stateId = Download::DlSimple; + + DlNormalFileState( DownloadPrivate &parent ); + DlNormalFileState( std::shared_ptr &&oldReq, DownloadPrivate &parent ); + + std::shared_ptr transitionToFinished (); + + SignalProxy< void () > sigFinished() { + return _sigFinished; + } + SignalProxy< void () > sigFailed() { + return _sigFailed; + } + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/preparemulti_p.cc b/zypp-curl/ng/network/private/downloaderstates/preparemulti_p.cc new file mode 100644 index 0000000..c5903d2 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/preparemulti_p.cc @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include + +#include "preparemulti_p.h" + +#if ENABLE_ZCHUNK_COMPRESSION +#include "zck_p.h" +#endif + +namespace zyppng { + + PrepareMultiState::PrepareMultiState( std::shared_ptr oldReq, Mode m, DownloadPrivate &parent ) + : SimpleState( parent ) + , _mode(m) + , _oldRequest(std::move( oldReq )) + { + MIL << "About to enter PrepareMultiState for URL: " << parent._spec.url() << std::endl; + } + + void PrepareMultiState::enter( ) + { + auto &sm = stateMachine(); + const auto &spec = sm._spec; + const auto &url = spec.url(); + const auto &targetPath = spec.targetPath(); +#if ENABLE_ZCHUNK_COMPRESSION + _haveZckData = (isZchunkFile( spec.deltaFile() ) && spec.headerSize() > 0); + MIL << " Upgrading request for URL: "<< url << " to multipart download , which zckunk=" << _haveZckData << std::endl; +#else + MIL << " Upgrading request for URL: "<< url << " to multipart download , which zckunk=false" << std::endl; +#endif + + + //we have a metalink download, lets parse it and see what we got + _mirrors.clear(); + + std::vector mirrs; + + try { + + const auto &parseMetadata = [&]( auto &&parser ) { + using T = std::decay_t; + constexpr auto metalinkMode = std::is_same< T, zypp::media::MetaLinkParser>(); + + parser.parse( targetPath ); + + // we only care about the metalink chunks if we have no zchunk data + #if ENABLE_ZCHUNK_COMPRESSION + if ( !_haveZckData ) { + #else + if ( true ) { + #endif + auto bl = parser.getBlockList(); + if ( !bl.haveBlocks() ) + MIL << "Got no blocks for URL " << spec.url() << " but got filesize? " << bl.getFilesize() << std::endl; + if ( bl.haveBlocks() || bl.haveFilesize() ) + _blockList = std::move(bl); + } + + //migrate some settings from the base url to the mirror + if constexpr ( !metalinkMode ) { + const auto &urlList = parser.getUrls(); + std::for_each( urlList.begin(), urlList.end(), [&]( const auto &url ) { + mirrs.push_back( { 0, -1, url } ); + }); + } else { + mirrs = parser.getMirrors(); + } + + for ( auto urliter = mirrs.begin(); urliter != mirrs.end(); ++urliter ) { + try { + const std::string scheme = urliter->url.getScheme(); + if (scheme == "http" || scheme == "https" || scheme == "ftp" || scheme == "tftp") { + if ( !sm._requestDispatcher->supportsProtocol( urliter->url )) { + urliter = mirrs.erase( urliter ); + continue; + } + urliter->url = ::internal::propagateQueryParams( urliter->url, url ); + _mirrors.push_back( urliter->url ); + } + } + catch (...) { } + } + + if ( mirrs.empty() ) { + mirrs.push_back( { 0, -1, url } ); + _mirrors.push_back( url ); + } + }; + + switch( _mode ) { + case Zsync: { + parseMetadata( zypp::media::ZsyncParser() ); + break; + } + case Metalink: { + parseMetadata( zypp::media::MetaLinkParser() ); + break; + } + } + } catch ( const zypp::Exception &ex ) { + std::string err = zypp::str::Format("Failed to parse metalink information.(%1%)" ) % ex.asUserString(); + WAR << err << std::endl; + _error = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, std::move(err) ); + _sigFailed.emit(); + return; + } + + if ( mirrs.size() == 0 ) { + std::string err = zypp::str::Format("Invalid metalink information.( No mirrors in metalink file)" ); + WAR << err << std::endl; + _error = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, std::move(err) ); + _sigFailed.emit(); + return; + } + + //remove the metalink file + zypp::filesystem::unlink( targetPath ); + _mirrorControlReadyConn = sm._mirrorControl->connect( &MirrorControl::sigNewMirrorsReady, *this, &PrepareMultiState::onMirrorsReady ); + + // this will emit a mirrorsReady signal once some connection tests have been done + sm._mirrorControl->registerMirrors( mirrs ); + } + + void PrepareMultiState::exit() + { + // if we did not pass on the existing request to the next state we destroy it here + if ( _oldRequest ) + _oldRequest.reset(); + } + + void PrepareMultiState::onMirrorsReady() + { + auto &sm = stateMachine(); + const auto &spec = sm._spec; + const auto &url = spec.url(); + _mirrorControlReadyConn.disconnect(); + +#if ENABLE_ZCHUNK_COMPRESSION + if ( _haveZckData ) { + _sigFinished.emit(); + return; + } +#endif + + // we have no zchunk data, so for a multi download we need a blocklist + if ( !_blockList.haveBlocks() ) { + //if we have no filesize we can not generate a blocklist, we need to fall back to normal download + if ( !_blockList.haveFilesize() ) { + + //fall back to normal download but use a mirror from the mirror list + //otherwise we get HTTPS to HTTP redirect errors + _sigFallback.emit(); + return; + } else { + //we generate a blocklist on the fly based on the filesize + + MIL << "Generate blocklist, since there was none in the metalink file." << url << std::endl; + + off_t currOff = 0; + off_t filesize = _blockList.getFilesize(); + const auto prefSize = std::max( sm._spec.preferredChunkSize(), zypp::ByteCount(4, zypp::ByteCount::K) ); + + while ( currOff < filesize ) { + + auto blksize = filesize - currOff ; + if ( blksize > prefSize ) + blksize = prefSize; + + _blockList.addBlock( currOff, blksize ); + currOff += blksize; + } + + MIL_MEDIA << "Generated blocklist: " << std::endl << _blockList << std::endl << " End blocklist " << std::endl; + } + } + + _sigFinished.emit(); + } + + std::shared_ptr PrepareMultiState::fallbackToNormalTransition() + { + MIL << "No blocklist and no filesize, falling back to normal download for URL " << stateMachine()._spec.url() << std::endl; + std::shared_ptr ptr; + if ( _oldRequest ) { + ptr = std::make_shared( std::move(_oldRequest), stateMachine() ); + } else { + ptr = std::make_shared( stateMachine() ); + } + + ptr->_fileMirrors = std::move(_mirrors); + if ( _blockList.haveFileChecksum() ) { + ptr->_chksumtype = _blockList.fileChecksumType(); + ptr->_chksumVec = _blockList.getFileChecksum(); + } + + return ptr; + } + + std::shared_ptr PrepareMultiState::transitionToMetalinkDl() + { + return std::make_shared( std::move(_blockList), std::move(_mirrors), stateMachine() ); + } + + std::shared_ptr PrepareMultiState::transitionToFinished() + { + return std::make_shared( std::move(_error), stateMachine() ); + } + +#if ENABLE_ZCHUNK_COMPRESSION + std::shared_ptr PrepareMultiState::transitionToZckHeadDl() + { + if ( _oldRequest ) + return std::make_shared( std::move(_mirrors), std::move(_oldRequest), stateMachine() ); + return std::make_shared( std::move(_mirrors), stateMachine() ); + } + + bool PrepareMultiState::toZckHeadDownloadGuard() const + { + return ( stateMachine().hasZckInfo() ); + } +#endif + + bool PrepareMultiState::toMetalinkDownloadGuard() const + { +#if ENABLE_ZCHUNK_COMPRESSION + return (!toZckHeadDownloadGuard()); +#else + return true; +#endif + } + +} diff --git a/zypp-curl/ng/network/private/downloaderstates/preparemulti_p.h b/zypp-curl/ng/network/private/downloaderstates/preparemulti_p.h new file mode 100644 index 0000000..3735507 --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/preparemulti_p.h @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_PREPAREMULTI_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_PREPAREMULTI_P_H_INCLUDED + +#include "base_p.h" +#include + +#include + +namespace zyppng { + + struct DlNormalFileState; + struct DlMetalinkState; + struct FinishedState; + +#if ENABLE_ZCHUNK_COMPRESSION + struct DLZckHeadState; +#endif + + /*! + * Metalink peparation state implementation, this state parses the downloaded Metalink file + * and registeres all mirrors in \ref MirrorControl. Once the first mirror becomes ready it passes on + * to the next state. + */ + struct PrepareMultiState : public zyppng::SimpleState< DownloadPrivate, Download::PrepareMulti, false > { + + using Request = DownloadPrivateBase::Request; + + enum Mode { + Zsync, + Metalink + }; + + PrepareMultiState ( std::shared_ptr oldReq, Mode m, DownloadPrivate &parent ); + + void enter (); + void exit (); + + const NetworkRequestError &error () const { + return _error; + } + + SignalProxy< void () > sigFinished() { + return _sigFinished; + } + SignalProxy< void () > sigFailed() { + return _sigFailed; + } + SignalProxy< void () > sigFallback() { + return _sigFallback; + } + + std::shared_ptr fallbackToNormalTransition (); + std::shared_ptr transitionToMetalinkDl (); + std::shared_ptr transitionToFinished (); +#if ENABLE_ZCHUNK_COMPRESSION + std::shared_ptr transitionToZckHeadDl (); + bool toZckHeadDownloadGuard () const; +#endif + + bool toMetalinkDownloadGuard () const; + + std::vector _mirrors; + zypp::media::MediaBlockList _blockList; + + private: + sigc::connection _mirrorControlReadyConn; + + void onMirrorsReady (); +#if ENABLE_ZCHUNK_COMPRESSION + bool _haveZckData = false; //< do we have zck data ready +#endif + Mode _mode; //< wether we should expect a metalink or zsync file + std::shared_ptr _oldRequest; //< exising request of previous states, that the next states might reuse + NetworkRequestError _error; + Signal< void () > _sigFinished; + Signal< void () > _sigFallback; + Signal< void () > _sigFailed; + }; + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.cc b/zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.cc new file mode 100644 index 0000000..2296a2c --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.cc @@ -0,0 +1,441 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include + +#include "rangedownloader_p.h" + +namespace zyppng { + + void RangeDownloaderBaseState::onRequestStarted( NetworkRequest & ) + { } + + void RangeDownloaderBaseState::onRequestProgress( NetworkRequest &, off_t , off_t, off_t , off_t ) + { + off_t dlnowMulti = _downloadedMultiByteCount; + for( const auto &req : _runningRequests ) { + dlnowMulti += req->downloadedByteCount(); + } + + if ( !assertExpectedFilesize( dlnowMulti ) ) + return; + + stateMachine()._sigProgress.emit( *stateMachine().z_func(), _fileSize, dlnowMulti ); + } + + void RangeDownloaderBaseState::onRequestFinished( NetworkRequest &req, const zyppng::NetworkRequestError &err ) + { + auto lck = stateMachine().z_func()->shared_from_this(); + auto it = std::find_if( _runningRequests.begin(), _runningRequests.end(), [ &req ]( const std::shared_ptr &r ) { + return ( r.get() == &req ); + }); + if ( it == _runningRequests.end() ) + return; + + auto reqLocked = *it; + + //remove from running + _runningRequests.erase( it ); + + //feed the working URL back into the mirrors in case there are still running requests that might fail + // @TODO , finishing the transfer might never be called in case of cancelling the request, need a better way to track running transfers + if ( reqLocked->_myMirror ) + reqLocked->_myMirror->finishTransfer( !err.isError() ); + + if ( err.isError() ) { + return handleRequestError( reqLocked, err ); + } + + _downloadedMultiByteCount += req.downloadedByteCount(); + if ( !assertExpectedFilesize( _downloadedMultiByteCount ) ) { + return; + } + + MIL << req.nativeHandle() << " " << "Request finished successfully."<requestedRanges(); + std::for_each( rngs.begin(), rngs.end(), [&req]( const auto &b ){ DBG_MEDIA << req.nativeHandle() << " " << "-> Block " << b.start << " finished." << std::endl; } ); + + auto restartReqWithBlock = [ this ]( std::shared_ptr &req, std::vector &&blocks ) { + MIL << req->nativeHandle() << " " << "Reusing Request to download blocks:"<url().getScheme() ) ) ) { + return setFailed( "Failed to restart request with new blocks." ); + } + return; + + } else { + //if we have failed blocks, try to download them with this mirror + if ( !_failedRanges.empty() ) { + + auto fblks = getNextFailedBlocks( reqLocked->url().getScheme() ); + MIL << req.nativeHandle() << " " << "Reusing to download failed blocks: "<_originalUrl ); + + // make sure downloads are running, at this point + ensureDownloadsRunning(); + } + + void RangeDownloaderBaseState::handleRequestError( std::shared_ptr req, const zyppng::NetworkRequestError &err ) + { + bool retry = false; + auto &parent = stateMachine(); + + + //Handle the auth errors explicitly, we need to give the user a way to put in new credentials + //if we get valid new credentials we can retry the request + if ( err.type() == NetworkRequestError::Unauthorized || err.type() == NetworkRequestError::AuthFailed ) { + retry = parent.handleRequestAuthError( req, err ); + } else { + + //if a error happens during a multi download we try to use another mirror to download the failed block + MIL << req->nativeHandle() << " " << "Request failed " << req->extendedErrorString() << "(" << req->url() << ")" << std::endl; + if ( req->lastRedirectInfo ().size () ) + MIL << req->nativeHandle() << " Last redirection target was: " << req->lastRedirectInfo () << std::endl; + + NetworkRequestError dummyErr; + + const auto &fRanges = req->failedRanges(); + try { + std::transform( fRanges.begin(), fRanges.end(), std::back_inserter(_failedRanges), [ &req ]( const auto &r ){ + Block b = std::any_cast(r.userData);; + b._failedWithErr = req->error(); + if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 ) + DBG_MEDIA << "Adding failed block to failed blocklist: " << b.start << " " << b.len << " (" << req->error().toString() << " [" << req->error().nativeErrorString()<< "])" << std::endl; + return b; + }); + + // try to fill the open spot right away + ensureDownloadsRunning(); + return; + + } catch ( const zypp::Exception &ex ) { + //we just log the exception and fall back to a normal download + WAR << "Multipart download failed: " << ex.asString() << std::endl; + } + } + + //if rety is true we just enqueue the request again, usually this means authentication was updated + if ( retry ) { + //make sure this request will run asap + req->setPriority( parent._defaultSubRequestPriority ); + + //this is not a new request, only add to queues but do not connect signals again + addNewRequest( req, false ); + return; + } + + //we do not have more mirrors left we can try + cancelAll ( err ); + + // not all hope is lost, maybe a normal download can work out? + // fall back to normal download + _sigFailed.emit(); + } + + void RangeDownloaderBaseState::ensureDownloadsRunning() + { + if ( _inEnsureDownloadsRunning ) + return; + + zypp::OnScopeExit clearFlag( [this]() { + _inEnsureDownloadsRunning = false; + }); + + _inEnsureDownloadsRunning = true; + + //check if there is still work to do + while ( _ranges.size() || _failedRanges.size() ) { + + // download was already finished + if ( _error.isError() ) + return; + + if ( _runningRequests.size() >= 10 ) + break; + + // prepareNextMirror will automatically call mirrorReceived() once there is a mirror ready + const auto &res = prepareNextMirror(); + // if mirrors are delayed we stop here, once the mirrors are ready we get called again + if ( res == MirrorHandlingStateBase::Delayed ) + return; + else if ( res == MirrorHandlingStateBase::Failed ) { + failedToPrepare(); + return; + } + } + + // check if we are done at this point + if ( _runningRequests.empty() ) { + + if ( _failedRanges.size() || _ranges.size() ) { + setFailed( NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Unable to download all blocks." ) ); + return; + } + + // seems we were successfull , transition to finished state + setFinished(); + } + } + + void RangeDownloaderBaseState::mirrorReceived( MirrorControl::MirrorPick mirror ) + { + + auto &parent = stateMachine(); + Url myUrl; + TransferSettings settings; + + auto err = setupMirror( mirror, myUrl, settings ); + if ( err.isError() ) { + WAR << "Failure to setup mirror " << myUrl << " with error " << err.toString() << "("<< err.nativeErrorString() << "), dropping it from the list of mirrors." << std::endl; + // if a mirror fails , we remove it from our list + _fileMirrors.erase( mirror.first ); + + // make sure this is retried + ensureDownloadsRunning(); + return; + } + + auto blocks = getNextBlocks( myUrl.getScheme() ); + if ( !blocks.size() ) + blocks = getNextFailedBlocks( myUrl.getScheme() ); + + if ( !blocks.size() ) { + // We have no blocks. In theory, that should never happen, but for safety, we error out here. It is better than + // getting stuck. + setFailed( NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Mirror requested after all blocks were downloaded." ) ); + return; + } + + const auto &spec = parent._spec; + + std::shared_ptr req = std::make_shared( ::internal::clearQueryString( myUrl ), spec.targetPath(), NetworkRequest::WriteShared ); + req->_myMirror = mirror.second; + req->_originalUrl = myUrl; + req->setPriority( parent._defaultSubRequestPriority ); + req->transferSettings() = settings; + + // if we download chunks we do not want to wait for too long on mirrors that have slow activity + // note: this sets the activity timeout, not the download timeout + req->transferSettings().setTimeout( 2 ); + + MIL << "Creating Request to download blocks via mirror: " << myUrl << std::endl; + if ( !addBlockRanges( req, std::move(blocks) ) ) { + setFailed( NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Failed to add blocks to request." ) ); + return; + } + + // we just use a mirror once per file, remove it from the list + _fileMirrors.erase( mirror.first ); + + addNewRequest( req ); + + // trigger next downloads + ensureDownloadsRunning(); + } + + void RangeDownloaderBaseState::failedToPrepare() + { + // it was impossible to find a new mirror, check if we still have running requests we can wait for, if not + // we can only fail at this point + if ( !_runningRequests.size() ) { + setFailed( NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "No valid mirror found" ) ); + } + } + + void RangeDownloaderBaseState::reschedule() + { + bool triggerResched = false; + for ( auto &req : _runningRequests ) { + if ( req->state() == NetworkRequest::Pending ) { + triggerResched = true; + req->setPriority( NetworkRequest::Critical, false ); + } + } + if ( triggerResched ) + stateMachine()._requestDispatcher->reschedule(); + } + + void RangeDownloaderBaseState::addNewRequest(const std::shared_ptr& req , const bool connectSignals) + { + if ( connectSignals ) + req->connectSignals( *this ); + + _runningRequests.push_back( req ); + stateMachine()._requestDispatcher->enqueue( req ); + + if ( req->_myMirror ) + req->_myMirror->startTransfer(); + } + + bool RangeDownloaderBaseState::assertExpectedFilesize( off_t currentFilesize ) + { + const off_t expFSize = stateMachine()._spec.expectedFileSize(); + if ( expFSize > 0 && expFSize < currentFilesize ) { + setFailed( NetworkRequestErrorPrivate::customError( NetworkRequestError::ExceededMaxLen ) ); + return false; + } + return true; + } + + /** + * Just initialize the requests ranges from the internal blocklist + */ + bool RangeDownloaderBaseState::addBlockRanges ( const std::shared_ptr& req , const std::vector& blocks ) const + { + req->resetRequestRanges(); + for ( const auto &block : blocks ) { + if ( block.chksumVec && block.chksumtype.size() ) { + std::optional dig = zypp::Digest(); + if ( !dig->create( block.chksumtype ) ) { + WAR_MEDIA << "Trying to create Digest with chksum type " << block.chksumtype << " failed " << std::endl; + return false; + } + + if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 ) + DBG_MEDIA << "Starting block " << block.start << " with checksum " << zypp::Digest::digestVectorToString( *block.chksumVec ) << "." << std::endl; + req->addRequestRange( block.start, block.len, std::move(dig), *block.chksumVec, std::any( block ), block.chksumCompareLen, block.chksumPad ); + } else { + + if ( zypp::env::ZYPP_MEDIA_CURL_DEBUG() > 3 ) + DBG_MEDIA << "Starting block " << block.start << " without checksum." << std::endl; + req->addRequestRange( block.start, block.len, {}, {}, std::any( block ) ); + } + } + return true; + } + + void zyppng::RangeDownloaderBaseState::setFailed(NetworkRequestError &&err) + { + _error = std::move( err ); + cancelAll( _error ); + zypp::filesystem::unlink( stateMachine()._spec.targetPath() ); + _sigFailed.emit(); + } + + void RangeDownloaderBaseState::setFailed(std::string &&reason) + { + setFailed( NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, std::move(reason) ) ); + } + + void RangeDownloaderBaseState::setFinished() + { + _error = NetworkRequestError(); + _sigFinished.emit(); + } + + void RangeDownloaderBaseState::cancelAll(const NetworkRequestError &err) + { + while( _runningRequests.size() ) { + auto req = _runningRequests.back(); + req->disconnectSignals(); + _runningRequests.pop_back(); + stateMachine()._requestDispatcher->cancel( *req, err ); + if ( req->_myMirror ) + req->_myMirror->cancelTransfer(); + } + } + + std::vector RangeDownloaderBaseState::getNextBlocks( const std::string &urlScheme ) + { + std::vector blocks; + const auto prefSize = std::max( _preferredChunkSize, zypp::ByteCount(4, zypp::ByteCount::K) ); + size_t accumulatedSize = 0; + + bool canDoRandomBlocks = ( zypp::str::hasPrefixCI( urlScheme, "http") ); + + std::optional lastBlockEnd; + while ( _ranges.size() && accumulatedSize < prefSize ) { + const auto &r = _ranges.front(); + + if ( !canDoRandomBlocks && lastBlockEnd ) { + if ( static_cast(r.start) != (*lastBlockEnd)+1 ) + break; + } + + lastBlockEnd = r.start + r.len - 1; + accumulatedSize += r.len; + + blocks.push_back( std::move( _ranges.front() ) ); + _ranges.pop_front(); + + } + DBG_MEDIA << "Accumulated " << blocks.size() << " blocks with accumulated size of: " << accumulatedSize << "." << std::endl; + return blocks; + } + + std::vector RangeDownloaderBaseState::getNextFailedBlocks( const std::string &urlScheme ) + { + const auto prefSize = std::max( _preferredChunkSize, zypp::ByteCount(4, zypp::ByteCount::K) ); + // sort the failed requests by block number, this should make sure get them in offset order as well + _failedRanges.sort( []( const auto &a , const auto &b ){ return a.start < b.start; } ); + + bool canDoRandomBlocks = ( zypp::str::hasPrefixCI( urlScheme, "http") ); + + std::vector fblks; + std::optional lastBlockEnd; + size_t accumulatedSize = 0; + while ( _failedRanges.size() ) { + + const auto &block =_failedRanges.front(); + + //we need to check if we have consecutive blocks because only http mirrors support random request ranges + if ( !canDoRandomBlocks && lastBlockEnd ) { + if ( static_cast(block.start) != (*lastBlockEnd)+1 ) + break; + } + + lastBlockEnd = block.start + block.len - 1; + accumulatedSize += block.len; + + fblks.push_back( std::move( _failedRanges.front() )); + _failedRanges.pop_front(); + + fblks.back()._retryCount += 1; + + if ( accumulatedSize >= prefSize ) + break; + } + + return fblks; + } + + zypp::ByteCount RangeDownloaderBaseState::makeBlksize ( size_t filesize ) + { + // this case should never happen because we never start a multi download if we do not know the filesize beforehand + if ( filesize == 0 ) return 4 * 1024 * 1024; + else if ( filesize < 4*1024*1024 ) return filesize; + else if ( filesize < 8*1024*1024 ) return 4*1024*1024; + else if ( filesize < 16*1024*1024 ) return 8*1024*1024; + else if ( filesize < 256*1024*1024 ) return 10*1024*1024; + return 4*1024*1024; + } +} diff --git a/zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.h b/zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.h new file mode 100644 index 0000000..23497ab --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/rangedownloader_p.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_RANGEDOWNLOADER_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_RANGEDOWNLOADER_P_H_INCLUDED + +#include "base_p.h" +#include "mirrorhandling_p.h" +#include + +namespace zyppng { + + /*! + * Generic state implementation for all states that download a file in blocks from + * a fixed set of mirrors. + */ + struct RangeDownloaderBaseState : public MirrorHandlingStateBase { + + using Request = DownloadPrivateBase::Request; + using Block = DownloadPrivateBase::Block; + + RangeDownloaderBaseState ( std::vector &&mirrors, DownloadPrivate &parent ) : + MirrorHandlingStateBase(parent) { + _fileMirrors = std::move(mirrors); + } + + void ensureDownloadsRunning (); + void reschedule (); + + const NetworkRequestError &error () const { + return _error; + } + + void setFailed ( NetworkRequestError &&err ); + void setFailed ( std::string && reason ); + virtual void setFinished ( ); + void cancelAll ( const NetworkRequestError &err ); + + void onRequestStarted ( NetworkRequest & ); + void onRequestProgress ( NetworkRequest &, off_t, off_t, off_t, off_t ); + void onRequestFinished ( NetworkRequest &req , const NetworkRequestError &err ); + + // MirrorHandlingStateBase interface + void mirrorReceived(MirrorControl::MirrorPick mirror) override; + void failedToPrepare() override; + + static zypp::ByteCount makeBlksize ( size_t filesize ); + + protected: + NetworkRequestError _error; + bool _inEnsureDownloadsRunning = false; //< Flag to prevent multiple entry to ensureDownloadsRunning + + size_t _fileSize = 0; //< The expected filesize, this is used to make sure we do not write after the end offset of the expected file size + zypp::ByteCount _preferredChunkSize = 0; //< The preferred chunk size we want to download per request + std::list _ranges; + + //keep a list with failed blocks in case we run out of mirrors, + //in that case we can retry to download them once we have a finished download + std::list _failedRanges; + + off_t _downloadedMultiByteCount = 0; //< the number of bytes that were already fetched in RunningMulti state + + std::vector< std::shared_ptr > _runningRequests; + + // we only define the signals here and add the accessor functions in the subclasses, static casting of + // the class type is not allowed at compile time, so they would not be useable in the transition table otherwise + Signal< void () > _sigFinished; + Signal< void () > _sigFailed; + + private: + void handleRequestError( std::shared_ptr req, const zyppng::NetworkRequestError &err ); + bool addBlockRanges(const std::shared_ptr& req, const std::vector& blocks ) const; + void addNewRequest (const std::shared_ptr& req, const bool connectSignals = true ); + bool assertExpectedFilesize ( off_t currentFilesize ); + + std::vector getNextBlocks ( const std::string &urlScheme ); + std::vector getNextFailedBlocks( const std::string &urlScheme ); + }; + + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/zck_p.cc b/zypp-curl/ng/network/private/downloaderstates/zck_p.cc new file mode 100644 index 0000000..426b54a --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/zck_p.cc @@ -0,0 +1,296 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#if ENABLE_ZCHUNK_COMPRESSION + +#include +#include +#include +#include + +#include "zck_p.h" + +#include +#include +#include + +extern "C" { +#include +} + +namespace zyppng { + + bool isZchunkFile ( const zypp::Pathname &file ) { + std::ifstream dFile( file.c_str() ); + if ( !dFile.is_open() ) + return false; + + constexpr std::string_view magic("\0ZCK1", 5); + + std::array< char, magic.size() > lead; + lead.fill('\0'); + dFile.read( lead.data(), lead.size() ); + return ( magic == std::string_view( lead.data(), lead.size()) ); + } + + DLZckHeadState::DLZckHeadState( std::vector &&mirrors, std::shared_ptr &&oldReq, DownloadPrivate &parent ) + : BasicDownloaderStateBase( std::move(oldReq), parent ) + { + _fileMirrors = std::move(mirrors); + MIL << "About to enter DlZckHeadState for url " << parent._spec.url() << std::endl; + } + + DLZckHeadState::DLZckHeadState( std::vector &&mirrors, DownloadPrivate &parent ) + : BasicDownloaderStateBase( parent ) + { + _fileMirrors = std::move(mirrors); + MIL << "About to enter DlZckHeadState for url " << parent._spec.url() << std::endl; + } + + + bool DLZckHeadState::initializeRequest(std::shared_ptr &r ) + { + BasicDownloaderStateBase::initializeRequest( r ); + + const auto &s = stateMachine()._spec; + if ( s.headerSize() == 0 ) { + ERR << "Downloading the zck header was requested, but headersize is zero." << std::endl; + return false; + } + + std::optional digest; + NetworkRequest::CheckSumBytes sum; + + const auto &headerSum = s.headerChecksum(); + if ( headerSum ) { + digest = zypp::Digest(); + if ( !digest->create( headerSum->type() ) ) { + ERR << "Unknown header checksum type " << headerSum->type() << std::endl; + return false; + } + sum = zypp::Digest::hexStringToUByteArray( headerSum->checksum() ); + } + + r->addRequestRange( 0, s.headerSize(), std::move(digest), sum ); + return true; + } + + void DLZckHeadState::gotFinished() + { + if ( isZchunkFile( stateMachine()._spec.targetPath() ) ) + return BasicDownloaderStateBase::gotFinished(); + failed ( "Downloaded header is not a zchunk header"); + } + + std::shared_ptr DLZckHeadState::transitionToDlZckState() + { + MIL_MEDIA << "Downloaded the header of size: " << _request->downloadedByteCount() << std::endl; + return std::make_shared( std::move(_fileMirrors), stateMachine() ); + } + + DLZckState::DLZckState(std::vector &&mirrors, DownloadPrivate &parent) + : RangeDownloaderBaseState( std::move(mirrors), parent ) + { + MIL_MEDIA << "About to enter DLZckState for url " << parent._spec.url() << std::endl; + } + + void DLZckState::enter() + { + auto &sm = stateMachine(); + const auto &spec = sm._spec; + + // setup the base downloader + _error = {}; + _ranges.clear(); + _failedRanges.clear(); + + // @TODO get this from zchunk file? + _fileSize = spec.expectedFileSize(); + + zypp::AutoFD src_fd = open( spec.deltaFile().asString().c_str(), O_RDONLY); + if(src_fd < 0) + return setFailed ( zypp::str::Format("Unable to open %1%") % spec.deltaFile() ); + + zypp::AutoDispose zck_src ( zck_create(), []( auto ptr ) { if ( ptr ) zck_free( &ptr ); } ); + if( !zck_src ) + return setFailed ( zypp::str::Format("%1%") % zck_get_error(NULL) ); + + if(!zck_init_read(zck_src, src_fd)) + return setFailed ( zypp::str::Format( "Unable to open %1%: %2%") % spec.deltaFile() % zck_get_error(zck_src) ); + + zypp::AutoFD target_fd = open( spec.targetPath().asString().c_str(), O_RDWR); + if(target_fd < 0) + return setFailed ( zypp::str::Format("Unable to open %1%") % spec.targetPath() ); + + zypp::AutoDispose zckTarget ( zck_create(), []( auto ptr ) { if ( ptr ) zck_free( &ptr ); } ); + if( !zckTarget ) + return setFailed ( zypp::str::Format("%1%") % zck_get_error(NULL) ); + + if(!zck_init_read(zckTarget, target_fd)) + return setFailed ( zypp::str::Format( "Unable to open %1%: %2%") % spec.targetPath() % zck_get_error(zckTarget) ); + + // Returns 0 for error, -1 for invalid checksum and 1 for valid checksum + switch ( zck_find_valid_chunks(zckTarget) ) { + case 0: // Returns 0 if there was a error + return setFailed ( zypp::str::Format( "Unable to open %1%: %2%") % spec.targetPath() % zck_get_error(zckTarget) ); + case 1: // getting a 1 would mean the file is already complete, basically impossible but lets handle it anyway + return setFinished(); + } + + const auto srcHashType = zck_get_chunk_hash_type( zckTarget ); + const auto targetHashType = zck_get_chunk_hash_type( zckTarget ); + + const size_t fLen = zck_get_length( zckTarget ); + if ( _fileSize > 0 ) { + // check if the file size as reported by zchunk is equal to the one we expect + if ( _fileSize != fLen ) { + return setFailed( NetworkRequestErrorPrivate::customError( + NetworkRequestError::ExceededMaxLen, + zypp::str::Format("Zchunk header reports a different filesize than what was expected ( Zck: %1% != Exp: %2%).") % fLen % _fileSize ) + ); + } + } else { + _fileSize = fLen; + } + + const auto maxConns = sm._requestDispatcher->maximumConcurrentConnections(); + if ( sm._spec.preferredChunkSize() == 0 ) { + const auto autoBlkSize = makeBlksize( _fileSize ); + if ( maxConns == -1 ) { + _preferredChunkSize = autoBlkSize; + } else { + _preferredChunkSize = _fileSize / maxConns; + if ( _preferredChunkSize < autoBlkSize ) + _preferredChunkSize = autoBlkSize; + else if ( _preferredChunkSize > zypp::ByteCount( 100, zypp::ByteCount::M ) ) + _preferredChunkSize = zypp::ByteCount( 100, zypp::ByteCount::M ); + } + } else { + // spec chunk size overrules the automatic one + _preferredChunkSize = sm._spec.preferredChunkSize(); + } + + if( srcHashType != targetHashType ) + return setFailed ( zypp::str::Format( "ERROR: Chunk hash types don't match. Source Hash: %1% vs Target Hash: %2%") + % zck_hash_name_from_type ( srcHashType ) + % zck_hash_name_from_type ( targetHashType ) ); + + if(!zck_copy_chunks( zck_src, zckTarget )) + return setFailed ( zypp::str::Format( "Unable to copy chunks from deltafile.") ); + + // will reset all chunks that are marked as failed back to missing + zck_reset_failed_chunks( zckTarget ); + + + // we calculate what is already downloaded by substracting the block sizes we still need to download from the full file size + _downloadedMultiByteCount = _fileSize; + + auto chunk = zck_get_first_chunk( zckTarget ); + do { + // Get validity of current chunk: 1 = valid, 0 = missing, -1 = invalid + if ( zck_get_chunk_valid( chunk ) == 1 ) + continue; + + zypp::AutoFREE zckDigest( zck_get_chunk_digest( chunk ) ); + UByteArray chksumVec = zypp::Digest::hexStringToUByteArray( std::string_view( zckDigest.value() ) ); + std::string chksumName; + std::optional chksumCompareLen; + + switch ( targetHashType ) { + case ZCK_HASH_SHA1: { + chksumName = zypp::Digest::sha1(); + break; + } + case ZCK_HASH_SHA256: { + chksumName = zypp::Digest::sha256(); + break; + } + case ZCK_HASH_SHA512: { + chksumName = zypp::Digest::sha512(); + break; + } + case ZCK_HASH_SHA512_128: { + // defined in zchunk as + // SHA-512/128 (first 128 bits of SHA-512 checksum) + chksumName = zypp::Digest::sha512(); + chksumCompareLen = chksumVec.size(); + break; + } + default: { + return setFailed ( zypp::str::Format( "Unsupported chunk hash type: %1%.") % zck_hash_name_from_type( targetHashType ) ); + } + } + + const auto s = static_cast( zck_get_chunk_start( chunk ) ); + const auto l = static_cast( zck_get_chunk_comp_size ( chunk ) ); + + MIL_MEDIA << "Downloading block " << s << " with length " << l << " checksum " << zckDigest.value() << " type " << chksumName << std::endl; + + _ranges.push_back( Block{ + .start = s, + .len = l, + .chksumtype = chksumName, + .chksumVec = std::move( chksumVec ), + .chksumCompareLen = std::move(chksumCompareLen) + } ); + + // substract the block length from the already downloaded bytes size + _downloadedMultiByteCount -= l; + + } while ( (chunk = zck_get_next_chunk( chunk )) ); + + ensureDownloadsRunning(); + } + + void DLZckState::exit() + { + cancelAll( NetworkRequestError() ); + } + + std::shared_ptr DLZckState::transitionToFinished() + { + return std::make_shared( std::move(_error), stateMachine() ); + } + + void DLZckState::setFinished() + { + const auto &spec = stateMachine()._spec; + + zypp::AutoFD target_fd = open( spec.targetPath().asString().c_str(), O_RDONLY ); + if( target_fd < 0 ) + return setFailed ( zypp::str::Format("Unable to open %1%") % spec.targetPath() ); + + zypp::AutoDispose zckTarget ( zck_create(), []( auto ptr ) { if ( ptr ) zck_free( &ptr ); } ); + if( !zckTarget ) + return setFailed ( zypp::str::Format("%1%") % zck_get_error(nullptr) ); + + if(!zck_init_read(zckTarget, target_fd)) + return setFailed ( zypp::str::Format( "Unable to open %1%: %2%") % spec.targetPath() % zck_get_error(zckTarget) ); + + /* Validate the chunk and data checksums for the current file. + * Returns 0 for error, -1 for invalid checksum and 1 for valid checksum */ + const auto res = zck_validate_checksums( zckTarget ); + if ( res == 0 || res == -1 ) { + if( zck_is_error(nullptr) ) { + std::string err = zck_get_error(NULL); + zck_clear_error(NULL); + return setFailed( std::move(err) ); + } + if( zck_is_error(zckTarget) ) + return setFailed( zck_get_error(zckTarget) ); + return setFailed( "zck_validate_checksums returned a unknown error." ); + } + + // everything is valid + RangeDownloaderBaseState::setFinished(); + } + +} + +#endif diff --git a/zypp-curl/ng/network/private/downloaderstates/zck_p.h b/zypp-curl/ng/network/private/downloaderstates/zck_p.h new file mode 100644 index 0000000..fab2b8c --- /dev/null +++ b/zypp-curl/ng/network/private/downloaderstates/zck_p.h @@ -0,0 +1,85 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_ZCK_P_H_INCLUDED +#define ZYPP_CURL_NG_NETWORK_PRIVATE_DOWNLOADERSTATES_ZCK_P_H_INCLUDED + +#include "base_p.h" +#include "basicdownloader_p.h" +#include "rangedownloader_p.h" +#include + +namespace zyppng { + +#if ENABLE_ZCHUNK_COMPRESSION + + struct DLZckState; + struct FinishedState; + + bool isZchunkFile ( const zypp::Pathname &file ); + + /*! + * Zchunk header download state implementation. This downloads only the + * zck header to calculate which ranges/blocks are required for download. + */ + struct DLZckHeadState : public BasicDownloaderStateBase { + static constexpr auto stateId = Download::DlZChunkHead; + + DLZckHeadState( std::vector &&mirrors, DownloadPrivate &parent ); + DLZckHeadState( std::vector &&mirrors, std::shared_ptr &&oldReq, DownloadPrivate &parent ); + + bool initializeRequest( std::shared_ptr &r ) override; + void gotFinished () override; + + std::shared_ptr transitionToDlZckState (); + + SignalProxy< void () > sigFinished() { + return _sigFinished; + } + SignalProxy< void () > sigFailed() { + return _sigFailed; + } + }; + + /*! + * State implementation for the actual zck download. This downloads the + * zck file from different mirrors in ranges. + */ + struct DLZckState : public RangeDownloaderBaseState { + + static constexpr auto stateId = Download::DlZChunk; + + DLZckState ( std::vector &&mirrors, DownloadPrivate &parent ); + + void enter (); + void exit (); + + std::shared_ptr transitionToFinished (); + + SignalProxy< void () > sigFinished() { + return _sigFinished; + } + + SignalProxy< void () > sigFallback() { + return _sigFailed; + } + + void setFinished() override; + + }; + +#endif + +} + +#endif diff --git a/zypp-curl/ng/network/private/mediadebug_p.h b/zypp-curl/ng/network/private/mediadebug_p.h new file mode 100644 index 0000000..0a626f9 --- /dev/null +++ b/zypp-curl/ng/network/private/mediadebug_p.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_MEDIADEBUG_H_INCLUDED +#define ZYPP_NG_MEDIADEBUG_H_INCLUDED + +#include + +L_ENV_CONSTR_FWD_DECLARE_FUNC(ZYPP_MEDIA_CURL_DEBUG); + +#ifdef ZYPP_BASE_LOGGER_LOGGROUP +#undef ZYPP_BASE_LOGGER_LOGGROUP +#endif + +#define ZYPP_BASE_LOGGER_LOGGROUP "ZYPP_MEDIA_CURL" + +#define XXX_MEDIA L_XXX_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) +#define DBG_MEDIA L_DBG_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) +#define MIL_MEDIA L_MIL_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) +#define WAR_MEDIA L_WAR_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) +#define ERR_MEDIA L_ERR_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) +#define SEC_MEDIA L_SEC_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) +#define INT_MEDIA L_INT_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) +#define USR_MEDIA L_USR_MEDIA( ZYPP_BASE_LOGGER_LOGGROUP ) + +#define L_XXX_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP, zypp::base::logger::E_XXX ) +#define L_DBG_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP"++", zypp::base::logger::E_MIL ) +#define L_MIL_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP, zypp::base::logger::E_MIL ) +#define L_WAR_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP, zypp::base::logger::E_WAR ) +#define L_ERR_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP, zypp::base::logger::E_ERR ) +#define L_SEC_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP, zypp::base::logger::E_SEC ) +#define L_INT_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP, zypp::base::logger::E_INT ) +#define L_USR_MEDIA(GROUP) L_ENV_CONSTR( ZYPP_MEDIA_CURL_DEBUG, GROUP, zypp::base::logger::E_USR ) + +#endif // ZYPP_NG_MEDIADEBUG_H_INCLUDED diff --git a/zypp-curl/ng/network/private/mirrorcontrol_p.h b/zypp-curl/ng/network/private/mirrorcontrol_p.h new file mode 100644 index 0000000..062f185 --- /dev/null +++ b/zypp-curl/ng/network/private/mirrorcontrol_p.h @@ -0,0 +1,132 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_CURL_NG_NETWORK_PRIVATE_MIRRORCONTROL_P_H +#define ZYPP_CURL_NG_NETWORK_PRIVATE_MIRRORCONTROL_P_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + class MirrorControl : public Base { + + public: + + struct Mirror { + + Url mirrorUrl; + uint rating = 100; // rating based on connection time higher is worse + uint penalty = 0; //additional value that is added to the rating when sorting the mirrors, is increased and lowered for failed or successful transactions + uint maxRanges = 0; //the maximum number of ranges that can be requested from this mirror + uint finishedTransfers = 0; //how many transfers did we already send to the mirror + uint runningTransfers = 0; //currently running transfers + uint failedTransfers = 0; //how many transfers have failed in a row using this mirror + uint successfulTransfers = 0; //how many transfers were successful + + void startTransfer(); + void finishTransfer( const bool success ); + void cancelTransfer(); + uint maxConnections () const; + bool hasFreeConnections () const; + + private: + Mirror( MirrorControl &parent ); + void transferUnref (); + + private: + friend class MirrorControl; + MirrorControl &_parent; + NetworkRequest::Ptr _request; + sigc::connection _finishedConn; + + uint _maxConnections = 0; //the maximum number of concurrent connections to this mirror, 0 means use system default + }; + + using Ptr = std::shared_ptr; + using MirrorHandle = std::shared_ptr; + using MirrorPick = std::pair< std::vector::const_iterator, MirrorHandle >; + + static Ptr create (); + ~MirrorControl() override; + void registerMirrors( const std::vector &urls ); + + /*! + * Tries to pick the best mirror from the set of URLs passed. + * In case of a pending request, the result code will be set to "Again". + */ + struct PickResult { + enum { + Ok, + Again, + Unknown + } code = Unknown; + MirrorPick result; + }; + PickResult pickBestMirror( const std::vector &mirrors ); + + bool allMirrorsReady () const; + + SignalProxy sigNewMirrorsReady(); + SignalProxy sigAllMirrorsReady(); + private: + MirrorControl(); + std::string makeKey ( const zypp::Url &url ) const; + sigc::connection _queueEmptyConn; + NetworkRequestDispatcher::Ptr _dispatcher; //Mirror Control using its own NetworkRequestDispatcher, to avoid waiting for other downloads + std::unordered_map _handles; + + Timer::Ptr _newMirrSigDelay; // we use a delay timer to emit the "someMirrorsReady" signal + + Signal _sigAllMirrorsReady; + Signal _sigNewMirrorsReady; + }; + +#if 0 + + /*! + * Simple helper class to automatically cancel running transfers on destruction + */ + class MirrorRef + { + public: + MirrorRef ( MirrorControl::MirrorHandle handle ); + ~MirrorRef(); + + void startTransfer(); + void finishTransfer( const bool success ); + void cancelTransfer(); + operator bool() const; + + MirrorControl::MirrorHandle get(); + + private: + struct Helper { + ~Helper(); + MirrorControl::MirrorHandle _myHandle; + bool _cancelOnDestruct = false; + }; + std::shared_ptr _data; + }; +#endif + +} + +#endif // ZYPP_CURL_NG_NETWORK_PRIVATE_MIRRORCONTROL_P_H diff --git a/zypp-curl/ng/network/private/networkrequestdispatcher_p.h b/zypp-curl/ng/network/private/networkrequestdispatcher_p.h new file mode 100644 index 0000000..0b0a4f9 --- /dev/null +++ b/zypp-curl/ng/network/private/networkrequestdispatcher_p.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_MEDIA_CURL_PRIVATE_CURL_P_H_INCLUDED +#define ZYPP_NG_MEDIA_CURL_PRIVATE_CURL_P_H_INCLUDED + +#include +#include +#include +#include +#include +#include + +namespace zyppng { + +class Timer; +class SocketNotifier; + +class NetworkRequestDispatcherPrivate : public BasePrivate +{ + ZYPP_DECLARE_PUBLIC(NetworkRequestDispatcher) +public: + NetworkRequestDispatcherPrivate ( NetworkRequestDispatcher &p ); + ~NetworkRequestDispatcherPrivate() override; + + int _maxConnections = 10; + + std::deque< std::shared_ptr > _pendingDownloads; + std::vector< std::shared_ptr > _runningDownloads; + + std::shared_ptr _timer; + std::map< curl_socket_t, std::shared_ptr > _socketHandler; + + bool _isRunning = false; + bool _locked = false; //if set to true, no new requests will be dequeued + CURLM *_multi = nullptr; + + NetworkRequestError _lastError; + + std::string _userAgent; + std::unordered_map< std::string, std::unordered_map > _customHeaders; + + //signals + Signal< void ( NetworkRequestDispatcher &, NetworkRequest & )> _sigDownloadStarted; + Signal< void ( NetworkRequestDispatcher &, NetworkRequest & )> _sigDownloadFinished; + Signal< void ( NetworkRequestDispatcher & )> _sigQueueFinished; + Signal< void ( NetworkRequestDispatcher & )> _sigError; + +private: + static int multi_timer_cb ( CURLM *multi, long timeout_ms, void *g ); + static int static_socket_callback(CURL *easy, curl_socket_t s, int what, void *userp, SocketNotifier *socketp ); + + void multiTimerTimout ( const Timer &t ); + int socketCallback(CURL *easy, curl_socket_t s, int what, void * ); + + void cancelAll ( const NetworkRequestError& result ); + bool addRequestToMultiHandle ( NetworkRequest &req ); + void setFinished( NetworkRequest &req , NetworkRequestError result ); + + void onSocketActivated ( const SocketNotifier &listener, int events ); + + void handleMultiSocketAction ( curl_socket_t nativeSocket, int evBitmask ); + void dequeuePending (); +}; +} + +#endif diff --git a/zypp-curl/ng/network/private/networkrequesterror_p.h b/zypp-curl/ng/network/private/networkrequesterror_p.h new file mode 100644 index 0000000..af83b3f --- /dev/null +++ b/zypp-curl/ng/network/private/networkrequesterror_p.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_MEDIA_CURL_PRIVATE_NETWORKREQUESTERROR_P_H_INCLUDED +#define ZYPP_NG_MEDIA_CURL_PRIVATE_NETWORKREQUESTERROR_P_H_INCLUDED + +#include +#include + +namespace zyppng { + +class NetworkRequestErrorPrivate +{ +public: + NetworkRequestErrorPrivate( NetworkRequestError::Type code, std::string &&msg, std::map && extraInfo ); + + NetworkRequestErrorPrivate *clone () const; + + NetworkRequestError::Type _errorCode = NetworkRequestError::InternalError; + std::string _errorMessage; + std::map _extraInfo; + + static zyppng::NetworkRequestError customError( NetworkRequestError::Type t, std::string &&errorMsg = "", std::map &&extraInfo = {} ); + static zyppng::NetworkRequestError fromCurlError( NetworkRequest &req, int nativeCode , const std::string &nativeError ); + static zyppng::NetworkRequestError fromCurlMError ( int nativeCode ); + static std::string typeToString( NetworkRequestError::Type t ); +}; + +} + +#endif diff --git a/zypp-curl/ng/network/private/request_p.h b/zypp-curl/ng/network/private/request_p.h new file mode 100644 index 0000000..7a76dd2 --- /dev/null +++ b/zypp-curl/ng/network/private/request_p.h @@ -0,0 +1,192 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_NG_MEDIA_CURL_PRIVATE_REQUEST_P_H_INCLUDED +#define ZYPP_NG_MEDIA_CURL_PRIVATE_REQUEST_P_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace zyppng { + + class NetworkRequestPrivate : public BasePrivate, public CurlMultiPartDataReceiver + { + ZYPP_DECLARE_PUBLIC(NetworkRequest) + public: + enum class ProtocolMode{ + Default, //< use this mode if no special checks are required in header or write callbacks + HTTP //< this mode is used for HTTP and HTTPS downloads + } _protocolMode = ProtocolMode::Default; + + NetworkRequestPrivate(Url &&url, zypp::Pathname &&targetFile, NetworkRequest::FileMode fMode, NetworkRequest &p ); + ~NetworkRequestPrivate() override; + + bool initialize( std::string &errBuf ); + + bool setupHandle ( std::string &errBuf ); + + bool assertOutputFile (); + + /*! + * \internal + * Called by the dispatcher if we report a error. If this function returns + * true we are qeued again and reinitialize is called + */ + bool canRecover () const; + + /*! + * Prepares the request before it is queued again + * currently this is used only for range batching but could be used to + * recover from other types of errors too + */ + bool prepareToContinue ( std::string &errBuf ); + + /*! + * \internal + * This will return true if the download needs to be queued again to + * continue downloading more stuff. + */ + bool hasMoreWork() const; + + /*! + * \internal + * Prepares the request to be started, or restarted for a range batch request. + */ + void aboutToStart ( ); + + /*! + * \internal + * Tells the request it was just removed from the curl multi handle and is about + * to be finalized. This function is called before \ref hasPendingRanges and \ref setResult + */ + void dequeueNotify(); + + void setResult ( NetworkRequestError &&err ); + void reset (); + void resetActivityTimer (); + + void onActivityTimeout (Timer &); + + std::string errorMessage () const; + + + std::array _errorBuf; //provide a buffer for a nicely formatted error for CURL + + template + void setCurlOption ( CURLoption opt, T data ) + { + auto ret = curl_easy_setopt( _easyHandle, opt, data ); + if ( ret != 0 ) { + ZYPP_THROW( zypp::media::MediaCurlSetOptException( _url, _errorBuf.data() ) ); + } + } + + Url _url; //file URL + zypp::Pathname _targetFile; //target file + TransferSettings _settings; + NetworkRequest::Options _options; + zypp::ByteCount _expectedFileSize; // the file size as expected by the user code + std::vector _requestedRanges; ///< the requested ranges that need to be downloaded + + struct FileVerifyInfo { + zypp::Digest _fileDigest; + zypp::CheckSum _fileChecksum; + }; + std::optional _fileVerification; ///< The digest for the full file + + NetworkRequest::FileMode _fMode = NetworkRequest::WriteExclusive; + NetworkRequest::Priority _priority = NetworkRequest::Normal; + + std::string _lastRedirect; ///< to log/report redirections + const std::string _currentCookieFile = "/var/lib/YaST2/cookies"; + + void *_easyHandle = nullptr; // the easy handle that controlling this request + NetworkRequestDispatcher *_dispatcher = nullptr; // the parent downloader owning this request + + //signals + Signal< void ( NetworkRequest &req )> _sigStarted; + Signal< void ( NetworkRequest &req, zypp::ByteCount count )> _sigBytesDownloaded; + Signal< void ( NetworkRequest &req, off_t dltotal, off_t dlnow, off_t ultotal, off_t ulnow )> _sigProgress; + Signal< void ( NetworkRequest &req, const NetworkRequestError &err )> _sigFinished; + + static int curlProgressCallback ( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow ); + + size_t headerfunction ( char *ptr, size_t bytes ) override; + size_t writefunction (char *ptr, std::optional offset, size_t bytes ) override; + void notifyErrorCodeChanged () override; + + std::unique_ptr< curl_slist, decltype (&curl_slist_free_all) > _headers; + + struct pending_t; + struct running_t; + struct prepareNextRangeBatch_t; + + struct pending_t { + pending_t(){} + std::unique_ptr _partialHelper = {}; + }; + + struct prepareNextRangeBatch_t + { + prepareNextRangeBatch_t( running_t &&prevState ); + zypp::AutoFILE _outFile; //the file we are writing to + off_t _downloaded = 0; //downloaded bytes + std::unique_ptr _partialHelper = {}; + }; + + struct running_t { + running_t( pending_t &&prevState ); + running_t( prepareNextRangeBatch_t &&prevState ); + + Timer::Ptr _activityTimer = Timer::create(); + + zypp::AutoFILE _outFile; + std::unique_ptr _partialHelper = {}; + + // handle the case when cancel() is called from a slot to the progress signal + bool _isInCallback = false; + + // used to handle cancel() when emitting the progress signal, or when we explicitely trigger + // a error during callbacks. + std::optional _cachedResult; + + off_t _lastProgressNow = -1; // last value returned from CURL, lets only send signals if we get actual updates + off_t _downloaded = 0; //downloaded bytes + off_t _currentFileOffset = 0; + + zypp::ByteCount _contentLenght; // the content length as reported by the server + }; + + struct finished_t { + off_t _downloaded = 0; //downloaded bytes + zypp::ByteCount _contentLenght = 0; // the content length as reported by the server + NetworkRequestError _result; // the overall result of the download + }; + + std::variant< pending_t, running_t, prepareNextRangeBatch_t, finished_t > _runningMode = pending_t(); + }; +} + +#endif diff --git a/zypp-curl/ng/network/request.cc b/zypp-curl/ng/network/request.cc new file mode 100644 index 0000000..8a607d2 --- /dev/null +++ b/zypp-curl/ng/network/request.cc @@ -0,0 +1,1056 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +namespace zyppng { + + namespace { + static size_t nwr_headerCallback ( char *ptr, size_t size, size_t nmemb, void *userdata ) { + if ( !userdata ) + return 0; + + NetworkRequestPrivate *that = reinterpret_cast( userdata ); + return that->headerfunction( ptr, size * nmemb ); + } + static size_t nwr_writeCallback ( char *ptr, size_t size, size_t nmemb, void *userdata ) { + if ( !userdata ) + return 0; + + NetworkRequestPrivate *that = reinterpret_cast( userdata ); + return that->writefunction( ptr, {}, size * nmemb ); + } + + //helper for std::visit + template struct always_false : std::false_type {}; + } + + NetworkRequestPrivate::prepareNextRangeBatch_t::prepareNextRangeBatch_t(running_t &&prevState) + : _outFile( std::move(prevState._outFile) ) + , _downloaded( prevState._downloaded ) + , _partialHelper( std::move(prevState._partialHelper) ) + { } + + NetworkRequestPrivate::running_t::running_t( pending_t &&prevState ) + : _partialHelper( std::move(prevState._partialHelper) ) + { } + + NetworkRequestPrivate::running_t::running_t( prepareNextRangeBatch_t &&prevState ) + : _outFile( std::move(prevState._outFile) ) + , _partialHelper( std::move(prevState._partialHelper) ) + , _downloaded( prevState._downloaded ) + { } + + NetworkRequestPrivate::NetworkRequestPrivate(Url &&url, zypp::Pathname &&targetFile, NetworkRequest::FileMode fMode , NetworkRequest &p) + : BasePrivate(p) + , _url ( std::move(url) ) + , _targetFile ( std::move( targetFile) ) + , _fMode ( std::move(fMode) ) + , _headers( std::unique_ptr< curl_slist, decltype (&curl_slist_free_all) >( nullptr, &curl_slist_free_all ) ) + { } + + NetworkRequestPrivate::~NetworkRequestPrivate() + { + if ( _easyHandle ) { + //clean up for now, later we might reuse handles + curl_easy_cleanup( _easyHandle ); + //reset in request but make sure the request was not enqueued again and got a new handle + _easyHandle = nullptr; + } + } + + bool NetworkRequestPrivate::initialize( std::string &errBuf ) + { + reset(); + + if ( _easyHandle ) + //will reset to defaults but keep live connections, session ID and DNS caches + curl_easy_reset( _easyHandle ); + else + _easyHandle = curl_easy_init(); + return setupHandle ( errBuf ); + } + + bool NetworkRequestPrivate::setupHandle( std::string &errBuf ) + { + ::internal::setupZYPP_MEDIA_CURL_DEBUG( _easyHandle ); + curl_easy_setopt( _easyHandle, CURLOPT_ERRORBUFFER, this->_errorBuf.data() ); + + const std::string urlScheme = _url.getScheme(); + if ( urlScheme == "http" || urlScheme == "https" ) + _protocolMode = ProtocolMode::HTTP; + + try { + + setCurlOption( CURLOPT_PRIVATE, this ); + setCurlOption( CURLOPT_XFERINFOFUNCTION, NetworkRequestPrivate::curlProgressCallback ); + setCurlOption( CURLOPT_XFERINFODATA, this ); + setCurlOption( CURLOPT_NOPROGRESS, 0L); + setCurlOption( CURLOPT_FAILONERROR, 1L); + setCurlOption( CURLOPT_NOSIGNAL, 1L); + + std::string urlBuffer( _url.asString() ); + setCurlOption( CURLOPT_URL, urlBuffer.c_str() ); + + setCurlOption( CURLOPT_WRITEFUNCTION, nwr_writeCallback ); + setCurlOption( CURLOPT_WRITEDATA, this ); + + if ( _options & NetworkRequest::ConnectionTest ) { + setCurlOption( CURLOPT_CONNECT_ONLY, 1L ); + setCurlOption( CURLOPT_FRESH_CONNECT, 1L ); + } + if ( _options & NetworkRequest::HeadRequest ) { + // instead of returning no data with NOBODY, we return + // little data, that works with broken servers, and + // works for ftp as well, because retrieving only headers + // ftp will return always OK code ? + // See http://curl.haxx.se/docs/knownbugs.html #58 + if ( _protocolMode == ProtocolMode::HTTP && _settings.headRequestsAllowed() ) + setCurlOption( CURLOPT_NOBODY, 1L ); + else + setCurlOption( CURLOPT_RANGE, "0-1" ); + } + + //make a local copy of the settings, so headers are not added multiple times + TransferSettings locSet = _settings; + + if ( _dispatcher ) { + locSet.setUserAgentString( _dispatcher->agentString().c_str() ); + + // add custom headers as configured (bsc#955801) + const auto &cHeaders = _dispatcher->hostSpecificHeaders(); + if ( auto i = cHeaders.find(_url.getHost()); i != cHeaders.end() ) { + for ( const auto &[key, value] : i->second ) { + locSet.addHeader( zypp::str::trim( zypp::str::form( + "%s: %s", key.c_str(), value.c_str() ) + )); + } + } + } + + locSet.addHeader("Pragma:"); + + /** Force IPv4/v6 */ + switch ( zypp::env::ZYPP_MEDIA_CURL_IPRESOLVE() ) + { + case 4: setCurlOption( CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4 ); break; + case 6: setCurlOption( CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6 ); break; + default: break; + } + + setCurlOption( CURLOPT_HEADERFUNCTION, &nwr_headerCallback ); + setCurlOption( CURLOPT_HEADERDATA, this ); + + /** + * Connect timeout + */ + setCurlOption( CURLOPT_CONNECTTIMEOUT, locSet.connectTimeout() ); + // If a transfer timeout is set, also set CURLOPT_TIMEOUT to an upper limit + // just in case curl does not trigger its progress callback frequently + // enough. + if ( locSet.timeout() ) + { + setCurlOption( CURLOPT_TIMEOUT, 3600L ); + } + + if ( urlScheme == "https" ) + { + if ( :: internal::setCurlRedirProtocols ( _easyHandle ) != CURLE_OK ) { + ZYPP_THROW( zypp::media::MediaCurlSetOptException( _url, _errorBuf.data() ) ); + } + + if( locSet.verifyPeerEnabled() || + locSet.verifyHostEnabled() ) + { + setCurlOption(CURLOPT_CAPATH, locSet.certificateAuthoritiesPath().c_str()); + } + + if( ! locSet.clientCertificatePath().empty() ) + { + setCurlOption(CURLOPT_SSLCERT, locSet.clientCertificatePath().c_str()); + } + if( ! locSet.clientKeyPath().empty() ) + { + setCurlOption(CURLOPT_SSLKEY, locSet.clientKeyPath().c_str()); + } + +#ifdef CURLSSLOPT_ALLOW_BEAST + // see bnc#779177 + setCurlOption( CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST ); +#endif + setCurlOption(CURLOPT_SSL_VERIFYPEER, locSet.verifyPeerEnabled() ? 1L : 0L); + setCurlOption(CURLOPT_SSL_VERIFYHOST, locSet.verifyHostEnabled() ? 2L : 0L); + // bnc#903405 - POODLE: libzypp should only talk TLS + setCurlOption(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); + } + + // follow any Location: header that the server sends as part of + // an HTTP header (#113275) + setCurlOption( CURLOPT_FOLLOWLOCATION, 1L); + // 3 redirects seem to be too few in some cases (bnc #465532) + setCurlOption( CURLOPT_MAXREDIRS, 6L ); + + //set the user agent + setCurlOption(CURLOPT_USERAGENT, locSet.userAgentString().c_str() ); + + + /*---------------------------------------------------------------* + CURLOPT_USERPWD: [user name]:[password] + Url::username/password -> CURLOPT_USERPWD + If not provided, anonymous FTP identification + *---------------------------------------------------------------*/ + if ( locSet.userPassword().size() ) + { + setCurlOption(CURLOPT_USERPWD, locSet.userPassword().c_str()); + std::string use_auth = _settings.authType(); + if (use_auth.empty()) + use_auth = "digest,basic"; // our default + long auth = zypp::media::CurlAuthData::auth_type_str2long(use_auth); + if( auth != CURLAUTH_NONE) + { + DBG << _easyHandle << " " << "Enabling HTTP authentication methods: " << use_auth + << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl; + setCurlOption(CURLOPT_HTTPAUTH, auth); + } + } + + if ( locSet.proxyEnabled() && ! locSet.proxy().empty() ) + { + DBG << _easyHandle << " " << "Proxy: '" << locSet.proxy() << "'" << std::endl; + setCurlOption(CURLOPT_PROXY, locSet.proxy().c_str()); + setCurlOption(CURLOPT_PROXYAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST|CURLAUTH_NTLM ); + + /*---------------------------------------------------------------* + * CURLOPT_PROXYUSERPWD: [user name]:[password] + * + * Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD + * If not provided, $HOME/.curlrc is evaluated + *---------------------------------------------------------------*/ + + std::string proxyuserpwd = locSet.proxyUserPassword(); + + if ( proxyuserpwd.empty() ) + { + zypp::media::CurlConfig curlconf; + zypp::media::CurlConfig::parseConfig(curlconf); // parse ~/.curlrc + if ( curlconf.proxyuserpwd.empty() ) + DBG << _easyHandle << " " << "Proxy: ~/.curlrc does not contain the proxy-user option" << std::endl; + else + { + proxyuserpwd = curlconf.proxyuserpwd; + DBG << _easyHandle << " " << "Proxy: using proxy-user from ~/.curlrc" << std::endl; + } + } + else + { + DBG << _easyHandle << " " << _easyHandle << " " << "Proxy: using provided proxy-user '" << _settings.proxyUsername() << "'" << std::endl; + } + + if ( ! proxyuserpwd.empty() ) + { + setCurlOption(CURLOPT_PROXYUSERPWD, ::internal::curlUnEscape( proxyuserpwd ).c_str()); + } + } +#if CURLVERSION_AT_LEAST(7,19,4) + else if ( locSet.proxy() == EXPLICITLY_NO_PROXY ) + { + // Explicitly disabled in URL (see fillSettingsFromUrl()). + // This should also prevent libcurl from looking into the environment. + DBG << _easyHandle << " " << "Proxy: explicitly NOPROXY" << std::endl; + setCurlOption(CURLOPT_NOPROXY, "*"); + } + +#endif + // else: Proxy: not explicitly set; libcurl may look into the environment + + /** Speed limits */ + if ( locSet.minDownloadSpeed() != 0 ) + { + setCurlOption(CURLOPT_LOW_SPEED_LIMIT, locSet.minDownloadSpeed()); + // default to 10 seconds at low speed + setCurlOption(CURLOPT_LOW_SPEED_TIME, 60L); + } + +#if CURLVERSION_AT_LEAST(7,15,5) + if ( locSet.maxDownloadSpeed() != 0 ) + setCurlOption(CURLOPT_MAX_RECV_SPEED_LARGE, locSet.maxDownloadSpeed()); +#endif + + zypp::filesystem::assert_file_mode( _currentCookieFile, 0600 ); + if ( zypp::str::strToBool( _url.getQueryParam( "cookies" ), true ) ) + setCurlOption( CURLOPT_COOKIEFILE, _currentCookieFile.c_str() ); + else + MIL << _easyHandle << " " << "No cookies requested" << std::endl; + setCurlOption(CURLOPT_COOKIEJAR, _currentCookieFile.c_str() ); + +#if CURLVERSION_AT_LEAST(7,18,0) + // bnc #306272 + setCurlOption(CURLOPT_PROXY_TRANSFER_MODE, 1L ); +#endif + + // Append settings custom headers to curl. + // TransferSettings assert strings are trimmed (HTTP/2 RFC 9113) + for ( const auto &header : locSet.headers() ) { + if ( !z_func()->addRequestHeader( header.c_str() ) ) + ZYPP_THROW(zypp::media::MediaCurlInitException(_url)); + } + + if ( _headers ) + setCurlOption( CURLOPT_HTTPHEADER, _headers.get() ); + + // set up ranges if required + if( !( _options & NetworkRequest::ConnectionTest ) && !( _options & NetworkRequest::HeadRequest ) ){ + if ( _requestedRanges.size() ) { + + std::sort( _requestedRanges.begin(), _requestedRanges.end(), []( const auto &elem1, const auto &elem2 ){ + return ( elem1.start < elem2.start ); + }); + + CurlMultiPartHandler *helper = nullptr; + if ( auto initState = std::get_if(&_runningMode) ) { + + auto multiPartMode = _protocolMode == ProtocolMode::HTTP ? CurlMultiPartHandler::ProtocolMode::HTTP : CurlMultiPartHandler::ProtocolMode::Basic; + initState->_partialHelper = std::make_unique( + multiPartMode + , _easyHandle + , _requestedRanges + , *this + ); + helper = initState->_partialHelper.get(); + + } else if ( auto pendingState = std::get_if(&_runningMode) ) { + helper = pendingState->_partialHelper.get(); + } else { + errBuf = "Request is in invalid state to call setupHandle"; + return false; + } + + if ( !helper->prepare () ) { + errBuf = helper->lastErrorMessage (); + return false; + } + } + } + + return true; + + } catch ( const zypp::Exception &excp ) { + ZYPP_CAUGHT(excp); + errBuf = excp.asString(); + } + return false; + } + + bool NetworkRequestPrivate::assertOutputFile() + { + auto rmode = std::get_if( &_runningMode ); + if ( !rmode ) { + DBG << _easyHandle << "Can only create output file in running mode" << std::endl; + return false; + } + // if we have no open file create or open it + if ( !rmode->_outFile ) { + std::string openMode = "w+b"; + if ( _fMode == NetworkRequest::WriteShared ) + openMode = "r+b"; + + rmode->_outFile = fopen( _targetFile.asString().c_str() , openMode.c_str() ); + + //if the file does not exist create a new one + if ( !rmode->_outFile && _fMode == NetworkRequest::WriteShared ) { + rmode->_outFile = fopen( _targetFile.asString().c_str() , "w+b" ); + } + + if ( !rmode->_outFile ) { + rmode->_cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError + ,zypp::str::Format("Unable to open target file (%1%). Errno: (%2%:%3%)") % _targetFile.asString() % errno % strerr_cxx() ); + return false; + } + } + + return true; + } + + bool NetworkRequestPrivate::canRecover() const + { + // We can recover from RangeFail errors if the helper indicates it + auto rmode = std::get_if( &_runningMode ); + if ( rmode->_partialHelper ) return rmode->_partialHelper->canRecover(); + return false; + } + + bool NetworkRequestPrivate::prepareToContinue( std::string &errBuf ) + { + auto rmode = std::get_if( &_runningMode ); + if ( !rmode ) { + errBuf = "NetworkRequestPrivate::prepareToContinue called in invalid state"; + return false; + } + + if ( rmode->_partialHelper && rmode->_partialHelper->hasMoreWork() ) { + + bool hadRangeFail = rmode->_partialHelper->lastError () == NetworkRequestError::RangeFail; + + _runningMode = prepareNextRangeBatch_t( std::move(std::get( _runningMode )) ); + + auto &prepMode = std::get(_runningMode); + if ( !prepMode._partialHelper->prepareToContinue() ) { + errBuf = prepMode._partialHelper->lastErrorMessage(); + return false; + } + + if ( hadRangeFail ) { + // we reset the handle to default values. We do this to not run into + // "transfer closed with outstanding read data remaining" error CURL sometimes returns when + // we cancel a connection because of a range error to request a smaller batch. + // The error will still happen but much less frequently than without resetting the handle. + // + // Note: Even creating a new handle will NOT fix the issue + curl_easy_reset( _easyHandle ); + } + if ( !setupHandle(errBuf)) + return false; + + return true; + } + errBuf = "Request has no more work"; + return false; + + } + + bool NetworkRequestPrivate::hasMoreWork() const + { + // check if we have ranges that have never been requested + return std::any_of( _requestedRanges.begin(), _requestedRanges.end(), []( const auto &range ){ return range._rangeState == CurlMultiPartHandler::Pending; }); + } + + void NetworkRequestPrivate::aboutToStart( ) + { + bool isRangeContinuation = std::holds_alternative( _runningMode ); + if ( isRangeContinuation ) { + MIL << _easyHandle << " " << "Continuing a previously started range batch." << std::endl; + _runningMode = running_t( std::move(std::get( _runningMode )) ); + } else { + _runningMode = running_t( std::move(std::get( _runningMode )) ); + } + + auto &m = std::get( _runningMode ); + + if ( m._activityTimer ) { + DBG_MEDIA << _easyHandle << " Setting activity timeout to: " << _settings.timeout() << std::endl; + m._activityTimer->connect( &Timer::sigExpired, *this, &NetworkRequestPrivate::onActivityTimeout ); + m._activityTimer->start( static_cast( _settings.timeout() * 1000 ) ); + } + + if ( !isRangeContinuation ) + _sigStarted.emit( *z_func() ); + } + + void NetworkRequestPrivate::dequeueNotify() + { + if ( std::holds_alternative(_runningMode) ) { + auto &rmode = std::get( _runningMode ); + if ( rmode._partialHelper ) + rmode._partialHelper->finalize(); + } + } + + void NetworkRequestPrivate::setResult( NetworkRequestError &&err ) + { + finished_t resState; + resState._result = std::move(err); + + if ( std::holds_alternative(_runningMode) ) { + + auto &rmode = std::get( _runningMode ); + resState._downloaded = rmode._downloaded; + resState._contentLenght = rmode._contentLenght; + + if ( resState._result.type() == NetworkRequestError::NoError && !(_options & NetworkRequest::HeadRequest) && !(_options & NetworkRequest::ConnectionTest) ) { + if ( _requestedRanges.size( ) ) { + //we have a successful download lets see if we got everything we needed + if ( !rmode._partialHelper->verifyData() ){ + NetworkRequestError::Type err = rmode._partialHelper->lastError(); + resState._result = NetworkRequestErrorPrivate::customError( err, std::string(rmode._partialHelper->lastErrorMessage()) ); + } + + // if we have ranges we need to fill our digest from the full file + if ( _fileVerification && resState._result.type() == NetworkRequestError::NoError ) { + if ( fseek( rmode._outFile, 0, SEEK_SET ) != 0 ) { + resState._result = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Unable to set output file pointer." ); + } else { + constexpr size_t bufSize = 4096; + char buf[bufSize]; + while( auto cnt = fread(buf, 1, bufSize, rmode._outFile ) > 0 ) { + _fileVerification->_fileDigest.update(buf, cnt); + } + } + } + } // if ( _requestedRanges.size( ) ) + } + + // finally check the file digest if we have one + if ( _fileVerification && resState._result.type() == NetworkRequestError::NoError ) { + const UByteArray &calcSum = _fileVerification->_fileDigest.digestVector (); + const UByteArray &expSum = zypp::Digest::hexStringToUByteArray( _fileVerification->_fileChecksum.checksum () ); + if ( calcSum != expSum ) { + resState._result = NetworkRequestErrorPrivate::customError( + NetworkRequestError::InvalidChecksum + , (zypp::str::Format("Invalid file checksum %1%, expected checksum %2%") + % _fileVerification->_fileDigest.digest() + % _fileVerification->_fileChecksum.checksum () ) ); + } + } + + rmode._outFile.reset(); + } + + _runningMode = std::move( resState ); + _sigFinished.emit( *z_func(), std::get(_runningMode)._result ); + } + + void NetworkRequestPrivate::reset() + { + _protocolMode = ProtocolMode::Default; + _headers.reset( nullptr ); + _errorBuf.fill( 0 ); + _runningMode = pending_t(); + + if ( _fileVerification ) + _fileVerification->_fileDigest.reset (); + + std::for_each( _requestedRanges.begin (), _requestedRanges.end(), []( CurlMultiPartHandler::Range &range ) { + range.restart(); + }); + } + + void NetworkRequestPrivate::onActivityTimeout( Timer &t ) + { + MIL_MEDIA << _easyHandle << " Request timeout interval: " << t.interval()<< " remaining: " << t.remaining() << std::endl; + std::map extraInfo; + extraInfo.insert( {"requestUrl", _url } ); + extraInfo.insert( {"filepath", _targetFile } ); + _dispatcher->cancel( *z_func(), NetworkRequestErrorPrivate::customError( NetworkRequestError::Timeout, "Download timed out", std::move(extraInfo) ) ); + } + + std::string NetworkRequestPrivate::errorMessage() const + { + return std::string( _errorBuf.data() ); + } + + void NetworkRequestPrivate::resetActivityTimer() + { + if ( std::holds_alternative( _runningMode ) ){ + auto &rmode = std::get( _runningMode ); + if ( rmode._activityTimer && rmode._activityTimer->isRunning() ) + rmode._activityTimer->start(); + } + } + + int NetworkRequestPrivate::curlProgressCallback( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow ) + { + if ( !clientp ) + return CURLE_OK; + NetworkRequestPrivate *that = reinterpret_cast( clientp ); + + if ( !std::holds_alternative(that->_runningMode) ){ + DBG << that->_easyHandle << " " << "Curl progress callback was called in invalid state "<< that->z_func()->state() << std::endl; + return -1; + } + + auto &rmode = std::get( that->_runningMode ); + + //reset the timer + that->resetActivityTimer(); + + rmode._isInCallback = true; + if ( rmode._lastProgressNow != dlnow ) { + rmode._lastProgressNow = dlnow; + that->_sigProgress.emit( *that->z_func(), dltotal, dlnow, ultotal, ulnow ); + } + rmode._isInCallback = false; + + return rmode._cachedResult ? CURLE_ABORTED_BY_CALLBACK : CURLE_OK; + } + + size_t NetworkRequestPrivate::headerfunction( char *ptr, size_t bytes ) + { + //it is valid to call this function with no data to write, just return OK + if ( bytes == 0) + return 0; + + resetActivityTimer(); + + if ( _protocolMode == ProtocolMode::HTTP ) { + + std::string_view hdr( ptr, bytes ); + + hdr.remove_prefix( std::min( hdr.find_first_not_of(" \t\r\n"), hdr.size() ) ); + const auto lastNonWhitespace = hdr.find_last_not_of(" \t\r\n"); + if ( lastNonWhitespace != hdr.npos ) + hdr.remove_suffix( hdr.size() - (lastNonWhitespace + 1) ); + else + hdr = std::string_view(); + + auto &rmode = std::get( _runningMode ); + if ( !hdr.size() ) { + return ( bytes ); + } + if ( _expectedFileSize && rmode._partialHelper ) { + const auto &repSize = rmode._partialHelper->reportedFileSize (); + if ( repSize && repSize != _expectedFileSize ) { + rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Reported downloaded data length is not what was expected." ); + return 0; + } + } + if ( zypp::strv::hasPrefixCI( hdr, "HTTP/" ) ) { + + long statuscode = 0; + (void)curl_easy_getinfo( _easyHandle, CURLINFO_RESPONSE_CODE, &statuscode); + + // if we have a status 204 we need to create a empty file + if( statuscode == 204 && !( _options & NetworkRequest::ConnectionTest ) && !( _options & NetworkRequest::HeadRequest ) ) + assertOutputFile(); + + } else if ( zypp::strv::hasPrefixCI( hdr, "Location:" ) ) { + _lastRedirect = hdr.substr( 9 ); + DBG << _easyHandle << " " << "redirecting to " << _lastRedirect << std::endl; + + } else if ( zypp::strv::hasPrefixCI( hdr, "Content-Length:") ) { + auto lenStr = str::trim( hdr.substr( 15 ), zypp::str::TRIM ); + auto str = std::string ( lenStr.data(), lenStr.length() ); + auto len = zypp::str::strtonum( str.data() ); + if ( len > 0 ) { + DBG << _easyHandle << " " << "Got Content-Length Header: " << len << std::endl; + rmode._contentLenght = zypp::ByteCount(len, zypp::ByteCount::B); + } + } + } + + return bytes; + } + + size_t NetworkRequestPrivate::writefunction( char *data, std::optional offset, size_t max ) + { + resetActivityTimer(); + + //it is valid to call this function with no data to write, just return OK + if ( max == 0) + return 0; + + //in case of a HEAD request, we do not write anything + if ( _options & NetworkRequest::HeadRequest ) { + return ( max ); + } + + auto &rmode = std::get( _runningMode ); + + // if we have no open file create or open it + if ( !assertOutputFile() ) + return 0; + + if ( offset ) { + // seek to the given offset + if ( fseek( rmode._outFile, *offset, SEEK_SET ) != 0 ) { + rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, + "Unable to set output file pointer." ); + return 0; + } + rmode._currentFileOffset = *offset; + } + + if ( _expectedFileSize && rmode._partialHelper ) { + const auto &repSize = rmode._partialHelper->reportedFileSize (); + if ( repSize && repSize != _expectedFileSize ) { + rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Reported downloaded data length is not what was expected." ); + return 0; + } + } + + //make sure we do not write after the expected file size + if ( _expectedFileSize && _expectedFileSize <= static_cast( rmode._currentFileOffset + max) ) { + rmode._cachedResult = NetworkRequestErrorPrivate::customError( NetworkRequestError::InternalError, "Downloaded data exceeds expected length." ); + return 0; + } + + auto written = fwrite( data, 1, max, rmode._outFile ); + if ( written == 0 ) + return 0; + + // if we are not downloading in ranges, we can update the file digest on the fly if we have one + if ( !rmode._partialHelper && _fileVerification ) { + _fileVerification->_fileDigest.update( data, written ); + } + + rmode._currentFileOffset += written; + + // count the number of real bytes we have downloaded so far + rmode._downloaded += written; + _sigBytesDownloaded.emit( *z_func(), rmode._downloaded ); + + return written; + } + + void NetworkRequestPrivate::notifyErrorCodeChanged() + { + auto rmode = std::get_if( &_runningMode ); + if ( !rmode || !rmode->_partialHelper || !rmode->_partialHelper->hasError() ) + return; + + // oldest cached result wins + if ( rmode->_cachedResult ) + return; + + auto lastErr = NetworkRequestErrorPrivate::customError( rmode->_partialHelper->lastError() , std::string(rmode->_partialHelper->lastErrorMessage()) ); + MIL_MEDIA << _easyHandle << " Multipart handler announced error code " << lastErr.toString () << std::endl; + rmode->_cachedResult = lastErr; + } + + ZYPP_IMPL_PRIVATE(NetworkRequest) + + NetworkRequest::NetworkRequest(zyppng::Url url, zypp::filesystem::Pathname targetFile, zyppng::NetworkRequest::FileMode fMode) + : Base ( *new NetworkRequestPrivate( std::move(url), std::move(targetFile), std::move(fMode), *this ) ) + { + } + + NetworkRequest::~NetworkRequest() + { + Z_D(); + + if ( d->_dispatcher ) + d->_dispatcher->cancel( *this, "Request destroyed while still running" ); + } + + void NetworkRequest::setExpectedFileSize( zypp::ByteCount expectedFileSize ) + { + d_func()->_expectedFileSize = std::move( expectedFileSize ); + } + + void NetworkRequest::setPriority( NetworkRequest::Priority prio, bool triggerReschedule ) + { + Z_D(); + d->_priority = prio; + if ( state() == Pending && triggerReschedule && d->_dispatcher ) + d->_dispatcher->reschedule(); + } + + NetworkRequest::Priority NetworkRequest::priority() const + { + return d_func()->_priority; + } + + void NetworkRequest::setOptions( Options opt ) + { + d_func()->_options = opt; + } + + NetworkRequest::Options NetworkRequest::options() const + { + return d_func()->_options; + } + + void NetworkRequest::addRequestRange(size_t start, size_t len, std::optional &&digest, CheckSumBytes expectedChkSum , std::any userData, std::optional digestCompareLen, std::optional chksumpad ) + { + Z_D(); + if ( state() == Running ) + return; + + d->_requestedRanges.push_back( Range::make( start, len, std::move(digest), std::move( expectedChkSum ), std::move( userData ), digestCompareLen, chksumpad ) ); + } + + void NetworkRequest::addRequestRange(zyppng::NetworkRequest::Range &&range ) + { + Z_D(); + if ( state() == Running ) + return; + + d->_requestedRanges.push_back( std::move(range) ); + auto &rng = d->_requestedRanges.back(); + rng._rangeState = CurlMultiPartHandler::Pending; + rng.bytesWritten = 0; + if ( rng._digest ) + rng._digest->reset(); + } + + bool NetworkRequest::setExpectedFileChecksum( const zypp::CheckSum &expected ) + { + Z_D(); + if ( state() == Running ) + return false; + + zypp::Digest fDig; + if ( !fDig.create( expected.type () ) ) + return false; + + d->_fileVerification = NetworkRequestPrivate::FileVerifyInfo{ + ._fileDigest = std::move(fDig), + ._fileChecksum = expected + }; + return true; + } + + void NetworkRequest::resetRequestRanges() + { + Z_D(); + if ( state() == Running ) + return; + d->_requestedRanges.clear(); + } + + std::vector NetworkRequest::failedRanges() const + { + const auto mystate = state(); + if ( mystate != Finished && mystate != Error ) + return {}; + + Z_D(); + + std::vector failed; + for ( auto &r : d->_requestedRanges ) { + if ( r._rangeState != CurlMultiPartHandler::Finished ) { + failed.push_back( r.clone() ); + } + } + return failed; + } + + const std::vector &NetworkRequest::requestedRanges() const + { + return d_func()->_requestedRanges; + } + + const std::string &NetworkRequest::lastRedirectInfo() const + { + return d_func()->_lastRedirect; + } + + void *NetworkRequest::nativeHandle() const + { + return d_func()->_easyHandle; + } + + std::optional NetworkRequest::timings() const + { + const auto myerr = error(); + const auto mystate = state(); + if ( mystate != Finished ) + return {}; + + Timings t; + + auto getMeasurement = [ this ]( const CURLINFO info, std::chrono::microseconds &target ){ + using FPSeconds = std::chrono::duration; + double val = 0; + const auto res = curl_easy_getinfo( d_func()->_easyHandle, info, &val ); + if ( CURLE_OK == res ) { + target = std::chrono::duration_cast( FPSeconds(val) ); + } + }; + + getMeasurement( CURLINFO_NAMELOOKUP_TIME, t.namelookup ); + getMeasurement( CURLINFO_CONNECT_TIME, t.connect); + getMeasurement( CURLINFO_APPCONNECT_TIME, t.appconnect); + getMeasurement( CURLINFO_PRETRANSFER_TIME , t.pretransfer); + getMeasurement( CURLINFO_TOTAL_TIME, t.total); + getMeasurement( CURLINFO_REDIRECT_TIME, t.redirect); + + return t; + } + + std::vector NetworkRequest::peekData( off_t offset, size_t count ) const + { + Z_D(); + + if ( !std::holds_alternative( d->_runningMode) ) + return {}; + + const auto &rmode = std::get( d->_runningMode ); + return zypp::io::peek_data_fd( rmode._outFile, offset, count ); + } + + Url NetworkRequest::url() const + { + return d_func()->_url; + } + + void NetworkRequest::setUrl(const Url &url) + { + Z_D(); + if ( state() == NetworkRequest::Running ) + return; + + d->_url = url; + } + + const zypp::filesystem::Pathname &NetworkRequest::targetFilePath() const + { + return d_func()->_targetFile; + } + + void NetworkRequest::setTargetFilePath( const zypp::filesystem::Pathname &path ) + { + Z_D(); + if ( state() == NetworkRequest::Running ) + return; + d->_targetFile = path; + } + + NetworkRequest::FileMode NetworkRequest::fileOpenMode() const + { + return d_func()->_fMode; + } + + void NetworkRequest::setFileOpenMode( FileMode mode ) + { + Z_D(); + if ( state() == NetworkRequest::Running ) + return; + d->_fMode = std::move( mode ); + } + + std::string NetworkRequest::contentType() const + { + char *ptr = NULL; + if ( curl_easy_getinfo( d_func()->_easyHandle, CURLINFO_CONTENT_TYPE, &ptr ) == CURLE_OK && ptr ) + return std::string(ptr); + return std::string(); + } + + zypp::ByteCount NetworkRequest::reportedByteCount() const + { + return std::visit([](auto& arg) -> zypp::ByteCount { + using T = std::decay_t; + if constexpr (std::is_same_v || std::is_same_v ) + return zypp::ByteCount(0); + else if constexpr (std::is_same_v + || std::is_same_v) + return arg._contentLenght; + else + static_assert(always_false::value, "Unhandled state type"); + }, d_func()->_runningMode); + } + + zypp::ByteCount NetworkRequest::downloadedByteCount() const + { + return std::visit([](auto& arg) -> zypp::ByteCount { + using T = std::decay_t; + if constexpr (std::is_same_v) + return zypp::ByteCount(); + else if constexpr (std::is_same_v + || std::is_same_v + || std::is_same_v) + return arg._downloaded; + else + static_assert(always_false::value, "Unhandled state type"); + }, d_func()->_runningMode); + } + + TransferSettings &NetworkRequest::transferSettings() + { + return d_func()->_settings; + } + + NetworkRequest::State NetworkRequest::state() const + { + return std::visit([this](auto& arg) { + using T = std::decay_t; + if constexpr (std::is_same_v) + return Pending; + else if constexpr (std::is_same_v || std::is_same_v ) + return Running; + else if constexpr (std::is_same_v) { + if ( std::get( d_func()->_runningMode )._result.isError() ) + return Error; + else + return Finished; + } + else + static_assert(always_false::value, "Unhandled state type"); + }, d_func()->_runningMode); + } + + NetworkRequestError NetworkRequest::error() const + { + const auto s = state(); + if ( s != Error && s != Finished ) + return NetworkRequestError(); + return std::get( d_func()->_runningMode)._result; + } + + std::string NetworkRequest::extendedErrorString() const + { + if ( !hasError() ) + return std::string(); + + return error().nativeErrorString(); + } + + bool NetworkRequest::hasError() const + { + return error().isError(); + } + + bool NetworkRequest::addRequestHeader( const std::string &header ) + { + Z_D(); + + curl_slist *res = curl_slist_append( d->_headers ? d->_headers.get() : nullptr, header.c_str() ); + if ( !res ) + return false; + + if ( !d->_headers ) + d->_headers = std::unique_ptr< curl_slist, decltype (&curl_slist_free_all) >( res, &curl_slist_free_all ); + + return true; + } + + SignalProxy NetworkRequest::sigStarted() + { + return d_func()->_sigStarted; + } + + SignalProxy NetworkRequest::sigBytesDownloaded() + { + return d_func()->_sigBytesDownloaded; + } + + SignalProxy NetworkRequest::sigProgress() + { + return d_func()->_sigProgress; + } + + SignalProxy NetworkRequest::sigFinished() + { + return d_func()->_sigFinished; + } + +} diff --git a/zypp-curl/ng/network/request.h b/zypp-curl/ng/network/request.h new file mode 100644 index 0000000..f244cbf --- /dev/null +++ b/zypp-curl/ng/network/request.h @@ -0,0 +1,293 @@ +#ifndef ZYPP_NG_MEDIA_CURL_REQUEST_H_INCLUDED +#define ZYPP_NG_MEDIA_CURL_REQUEST_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zypp { + class Digest; + class CheckSum; + + namespace media { + class AuthData; + } +} + +namespace zyppng { + + using AuthData = zypp::media::AuthData; + + class NetworkRequestDispatcher; + class NetworkRequestPrivate; + + /*! + * Represents a (http/https/ftp) request. This is the low level API for the + * \sa zyppng::Downloader , usually it makes more sense to use the Downloader for the + * more features it supports. + * After creating a NetworkRequest and changing the required settings is enqueued + * to the \sa zyppng::NetworkRequestDispatcher. + */ + class LIBZYPP_NG_EXPORT NetworkRequest : public Base + { + public: + + using Ptr = std::shared_ptr; + using WeakPtr = std::weak_ptr; + using DigestPtr = std::shared_ptr; + using CheckSumBytes = UByteArray; + + enum State { + Pending, //< waiting to be dispatched + Running, //< currently running + Finished, //< finished successfully + Error, //< Error, use error function to figure out the issue + }; + + enum Priority { + Normal, //< Requests with normal priority will be enqueued as they come in + High, //< Request with high priority will be moved to the front of the queue + Critical = 100, //< Those requests will be enqueued as fast as possible, even before High priority requests, this should be used only if requests needs to start immediately + }; + + enum FileMode { + WriteExclusive, //< the request will create its own file, overwriting anything that already exists + WriteShared //< the request will create or open the file in shared mode and only write between \a start and \a len + }; + + enum OptionBits { + Default = 0x00, //< no special options, just do a normal download + HeadRequest = 0x01, //< only request the header part of the file + ConnectionTest = 0x02 //< only connect to collect connection speed information + }; + ZYPP_DECLARE_FLAGS(Options, OptionBits); + + using Range = CurlMultiPartHandler::Range; + + struct Timings { + std::chrono::microseconds namelookup; + std::chrono::microseconds connect; + std::chrono::microseconds appconnect; + std::chrono::microseconds pretransfer; + std::chrono::microseconds total; + std::chrono::microseconds redirect; + }; + + /*! + * \param url The source URL of the download + * \param targetFile The path where the file should be stored + * \param fMode The mode in which the file is opened in. + */ + NetworkRequest(Url url, zypp::Pathname targetFile, FileMode fMode = WriteExclusive ); + ~NetworkRequest() override; + + /*! + * Sets the expected file size for the download. + * In case of a Multi-Range-Download the \a NetworkRequest will check if the download + * would write behind the expectedFileSize and fail. + */ + void setExpectedFileSize ( zypp::ByteCount expectedFileSize ); + + /*! + * Sets the priority of the NetworkRequest, this will affect where + * the \sa NetworkRequestDispatcher puts the Request in the Queue. + * \note changing this makes only sense in Pending state. + */ + void setPriority ( Priority prio, bool triggerReschedule = true ); + + /*! + * Returns the requested priority of the NetworkRequest + */ + Priority priority ( ) const; + + /*! + * Change request options. + * + * \note changing this makes only sense before the request was started + */ + void setOptions ( Options opt ); + + /*! + * Returns the currently set options + */ + Options options () const; + + /*! + * Adds a new range to the requested range list, the ranges can not overlap + * \note This will not change a running download + */ + void addRequestRange ( size_t start, size_t len = 0, std::optional &&digest = {}, CheckSumBytes expectedChkSum = CheckSumBytes(), std::any userData = std::any(), std::optional digestCompareLen = {}, std::optional chksumpad = {} ); + + void addRequestRange ( Range &&range ); + + /*! + * Sets the expected checksum for the full file. + * \note This will not change a running download + */ + bool setExpectedFileChecksum( const zypp::CheckSum &expected ); + + /*! + * Clears all requested ranges, the next download will get the complete file + * \note This will not change a running download + */ + void resetRequestRanges ( ); + + std::vector failedRanges () const; + const std::vector &requestedRanges () const; + + /*! + * Returns the last redirect information from the headers. + */ + const std::string &lastRedirectInfo() const; + + /*! + * Returns a pointer to the native CURL easy handle + * + * \note consider adding the functionality here instead of using the Handle directly. + * In case we ever decide to switch out the CURL backend your code will break + */ + void *nativeHandle () const; + + /** + * After the request is finished query the timings that were collected + * during download + */ + std::optional timings () const; + + /*! + * Will return the data at \a offset with length \a count. + * If there is not yet enough data a empty vector will be returned + */ + std::vector peekData ( off_t offset, size_t count ) const; + + /*! + * Returns the request URL + */ + Url url () const; + + /** + * This will change the URL of the request. + * \note calling this on a currently running request has no impact + */ + void setUrl ( const Url & url ); + + /** + * Returns the target filename path + */ + const zypp::Pathname & targetFilePath () const; + + /** + * Changes the target file path of the download + * \note calling this on a currently running request has no impact + */ + void setTargetFilePath ( const zypp::Pathname &path ); + + /** + * Returns the currently configured file open mode + */ + FileMode fileOpenMode () const; + + /** + * Sets the file open mode to \a mode. + * \note calling this on a currently running request has no impact + */ + void setFileOpenMode ( FileMode mode ); + + /** + * Returns the content type as reported from the server + * \note can only return a valid value if the download has started already + */ + std::string contentType () const; + + /** + * Returns the number of bytes that are reported from the backend as the full download size, those can + * be 0 even when the download is already running. + * \note When downloading ranges, the reported byte count could be reported just partially due to + * range batching. + */ + zypp::ByteCount reportedByteCount() const; + + /** + * Returns the number of already downloaded bytes as reported by the backend + */ + zypp::ByteCount downloadedByteCount() const; + + /*! + * Returns a writeable reference to the internal \sa zyppng::TransferSettings. + * \note calling this on a already running request has no impact + */ + TransferSettings &transferSettings (); + + /** + * Returns the current state the \a HttpDownloadRequest is in + */ + State state () const; + + /** + * Returns the last set Error + */ + NetworkRequestError error () const; + + /** + * In some cases, curl can provide extended error information collected at + * runtime. In those cases, it is possible to query that information. + */ + std::string extendedErrorString() const; + + /** + * Checks if there was a error with the request + */ + bool hasError () const; + + /*! + * Adds a raw header to the request data. Use this to send custom headers + * to the server. + */ + bool addRequestHeader(const std::string &header ); + + /** + * Signals that the dispatcher dequeued the request and actually starts downloading data + */ + SignalProxy sigStarted (); + + /** + * Signals that new data has been downloaded, this is only the payload and does not include control data bytes + */ + SignalProxy sigBytesDownloaded (); + + /** + * Signals if there was data read from the download + * \note this signals the raw numbers of bytes that were downloaded, for the number of payload data bytes ( excluding control data ) + * use \ref downloadedByteCount + */ + SignalProxy sigProgress (); + + /** + * Signals that the download finished. + * + * \note After this signal was emitted the Curl handle is reset, + * so all queries to it need to be done in a Slot connected to this signal + */ + SignalProxy sigFinished ( ); + + private: + friend class NetworkRequestDispatcher; + friend class NetworkRequestDispatcherPrivate; + ZYPP_DECLARE_PRIVATE( NetworkRequest ) + }; + +} +ZYPP_DECLARE_OPERATORS_FOR_FLAGS(zyppng::NetworkRequest::Options); + +#endif diff --git a/zypp-curl/ng/network/transfersettings.h b/zypp-curl/ng/network/transfersettings.h new file mode 100644 index 0000000..14a229a --- /dev/null +++ b/zypp-curl/ng/network/transfersettings.h @@ -0,0 +1,23 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPPNG_MEDIA_HTTP_TRANSFERSETTINGS_H_INCLUDED +#define ZYPPNG_MEDIA_HTTP_TRANSFERSETTINGS_H_INCLUDED + +#include + +namespace zyppng { +using TransferSettings = zypp::media::TransferSettings; +} + +#endif diff --git a/zypp-curl/parser/MediaBlockList b/zypp-curl/parser/MediaBlockList new file mode 100644 index 0000000..08ac596 --- /dev/null +++ b/zypp-curl/parser/MediaBlockList @@ -0,0 +1 @@ +#include "mediablocklist.h" diff --git a/zypp-curl/parser/MetaLinkParser b/zypp-curl/parser/MetaLinkParser new file mode 100644 index 0000000..d4e060c --- /dev/null +++ b/zypp-curl/parser/MetaLinkParser @@ -0,0 +1 @@ +#include "metalinkparser.h" diff --git a/zypp-curl/parser/ZsyncParser b/zypp-curl/parser/ZsyncParser new file mode 100644 index 0000000..f6461d4 --- /dev/null +++ b/zypp-curl/parser/ZsyncParser @@ -0,0 +1 @@ +#include "zsyncparser.h" diff --git a/zypp-curl/parser/mediablocklist.cc b/zypp-curl/parser/mediablocklist.cc new file mode 100644 index 0000000..094f45c --- /dev/null +++ b/zypp-curl/parser/mediablocklist.cc @@ -0,0 +1,1104 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + \file zypp-curl/parser/mediablocklist.cc + + This file implements the delta file block reuse algorithm. If the available hashes use rolling checksum style + hashes, we use the zsync algorithm to search for blocks that are available. + + The basic idea of zsync is that on the server side a metadata file is generated, this file contains a list of checksums + for each block in the target file ( the file we want to download ) as well as some other important informations + like the size of the blocks, file checksum and mirrors. The client ( we ) then can use a delta file, basically + a older version of the file we want to download, to find reusable blocks identified by their checksum. + + A simple approach would be now to calculate all checksums in the delta file for each block, but that does not take into + account that the blocks we want to reuse have moved in the file, e.g. a new set bytes of data was put in the beginning + of the file, shifting all blocks to a new offset most likely not as a multiple of blocksize or worse not even a power of 2. + Think a block is 2k but the data inserted is only 200 bytes, offsetting all blocks for 200bytes, in that case the simple approach could not reuse a single block + of data because it can't find them. + + To work around this problem the code calculates the checksums on every possible byte offset of the delta file. To speed this process + up when finding a block we skip forward to the end of the block. If there is a match at x, its very unlikely to find another match starting + inside the boundaries of the current block ( between x and x + blocksize - 1 ), except if the file has a lot of redundancy. + + This process naturally can take very long if there are no, or just a few matching blocks in the two files. To speed this up + a multi step checksum process is used. First we calculate a very cheap to calculate weak checksum for each block based on + the Adler-32 checksum: + + \f[ + a(k,l) = (\sum_{i=k}^l X_i) \bmod M + \f] + \f[ + \begin{align} + b(k,l) &= (\sum_{i=k}^l (l-i+1)X_i) \bmod M \\ + &= (\sum_{i=k}^l a(k,i) ) \bmod M + \end{align} + \f] + \f[ + s(k,l) = a(k,l) + 2^{16} b(k,l) + \f] + + where \f$s(k, l)\f$ is the rolling checksum of the bytes \f$X_k \ldots X_l\f$. For simplicity and speed, we use \f$M = 2^{16}\f$. + + The important property of this checksum is that successive values can be computed very efficiently using recurrence relations: + \f[ + a(k+1,l+1) = (a(k,l) - X_k + X_{l+1}) \bmod M + \f] + \f[ + b(k+1,l+1) = (b(k,l) - (l-k+1) X_k + a(k+1,l+1)) \bmod M + \f] + + To understand why we can use recurrence relations its important to look at the formulas written out + for a simple example, we will ignore the modulo operation for simplicity: + + For the \a a formula is simple to see that we just need to subtract the value of the byte moving out of the block and add the + value of the new byte coming in at the end + \f[ + \begin{align} + a(0,2) &= X_0 + X_1 + X_2 \\ + a(1,3) &= a(0,2) - X_0 + X_3 \\ + &= X_0 + X_1 + X_2 - X_0 + X_3 \\ + &= X_1 + X_2 + X_3 + \end{align} + \f] + + The \a b part is a bit more complex, writing the formula out also shows us why \a b can be expressed as: \f$b=(\sum_{i=k}^l a(k,i) ) \bmod M\f$: + \f[ + \begin{align} + b(0,2) &= 3X_0 + 2X_1 + X_2 \\ + &= X_0 + X_0 +X_0 + X_1 + X_1 + X_2 \\ + &= X0 + X0 + X1 + X0 +X1 +X2 \\ + &= a(0,0) + a(0,1) + a(0,2) = (\sum_{i=k}^l a(k,i) ) + \end{align} + \f] + \f[ + \begin{align} + b(1,3) &= b(0,2) - (2-0+1)X_0 + a(1,3) \\ + &= b(0,2) - 3X_0 + a(1,3) \\ + &= 3X_0 + 2X_1 + X_2 - 3X_0 + X_1 + X_2 + X_3 \\ + &= 3X_1 + 2X_2 + X_3 + \end{align} + \f] + + This shows us that we can very quickly calculate the new checksum of a block at offset \a i+1 based on the checksum of the block at offset \a i. + + If the weak checksum matches, a stronger MD4 checksum is calculated for the same block to make sure we really got the block we wanted. If the strong checksum + matches as well the block is written to the target file and removed from the list of blocks we still need to find. The read offset then jumps to the end + of the current bock: \a offset+blocksize and continues the process from there. + + Zsync additionally can require that always a sequence of 2 neighboring blocks need to match before they are considered a match. This depends on the filesize and is specified in the zsync metadata file. + According to the zsync docs this greatly lowers the probability of a false match and allows to send smaller checksums for the blocks, minimizing the data we need to download in the meta datafile. + + More in depth docs can be found at http://zsync.moria.org.uk/paper and https://rsync.samba.org/tech_report +*/ + +#include "mediablocklist.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +using namespace zypp::base; + +namespace zypp { + namespace media { + + namespace { + + struct rsum { + unsigned short a = 0; + unsigned short b = 0; + } __attribute__((packed)); + + /* rcksum_calc_rsum_block(data, data_len) + * Calculate the rsum for a single block of data. */ + rsum rcksum_calc_rsum_block(const unsigned char *data, size_t len) { + unsigned short a = 0; + unsigned short b = 0; + + while (len) { + unsigned char c = *data++; + a += c; + b += len * c; + len--; + } + return rsum{ a, b }; + } + + // update the rsum by removing the old and adding the new char + #define UPDATE_RSUM(a, b, oldc, newc, bshift) do { (a) += ((unsigned char)(newc)) - ((unsigned char)(oldc)); (b) += (a) - ((oldc) << (bshift)); } while (0) + + /** + * Zsync uses a different rsum length based on the blocksize, since we always calculate the big + * checksum we need to cut off the bits we are not interested in + */ + void inline truncateRsum ( unsigned int &rs, const int rsumlen ) + { + switch(rsumlen) + { + case 3: + rs &= 0xffffff; + break; + case 2: + rs &= 0xffff; + break; + case 1: + rs &= 0xff; + break; + default: + break; + } + } + + } + +MediaBlockList::MediaBlockList(off_t size) +: filesize(size), + haveblocks(false), + chksumlen(0), + chksumpad(0), + rsumlen(0), + rsumseq(0), + rsumpad(0) +{ } + +size_t +MediaBlockList::addBlock(off_t off, size_t size) +{ + haveblocks = true; + blocks.push_back(MediaBlock( off, size )); + return blocks.size() - 1; +} + +void +MediaBlockList::setFileChecksum(std::string ctype, int cl, unsigned char *c) +{ + if (!cl) + return; + fsumtype = std::move(ctype); + fsum.resize(cl); + memcpy(&fsum[0], c, cl); +} + +std::string MediaBlockList::fileChecksumType() const +{ + return fsumtype; +} + +const UByteArray &MediaBlockList::getFileChecksum() +{ + return fsum; +} + +bool +MediaBlockList::createFileDigest(Digest &digest) const +{ + return digest.create(fsumtype); +} + +bool +MediaBlockList::verifyFileDigest(Digest &digest) const +{ + if (!haveFileChecksum()) + return true; + std::vectordig = digest.digestVector(); + if (dig.empty() || dig.size() < fsum.size()) + return false; + return memcmp(&dig[0], &fsum[0], fsum.size()) ? false : true; +} + +void +MediaBlockList::setChecksum(size_t blkno, const std::string& cstype, int csl, unsigned char *cs, size_t cspad) +{ + if (!csl) + return; + if (!chksumlen) + { + if (blkno) + return; + chksumlen = csl; + chksumtype = cstype; + chksumpad = cspad; + } + if (csl != chksumlen || cstype != chksumtype || cspad != chksumpad || blkno != chksums.size() / chksumlen) + return; + chksums.resize(chksums.size() + csl); + memcpy(&chksums[csl * blkno], cs, csl); +} + +void +MediaBlockList::setRsum(size_t blkno, int rsl, unsigned int rs, size_t rspad) +{ + if (!rsl) + return; + if (!rsumlen) + { + if (blkno) + return; + rsumlen = rsl; + rsumpad = rspad; + } + if (rsl != rsumlen || rspad != rsumpad || blkno != rsums.size()) + return; + rsums.push_back(rs); +} + +void +MediaBlockList::setRsumSequence( uint seq ) +{ + rsumseq = seq; +} + +bool +MediaBlockList::createDigest(Digest &digest) const +{ + return digest.create(chksumtype); +} + +bool +MediaBlockList::verifyDigest(size_t blkno, Digest &digest) const +{ + if (!haveChecksum(blkno)) + return true; + size_t size = blocks[blkno].size; + if (!size) + return true; + if (chksumpad > size) + { + char pad[chksumpad - size]; + memset(pad, 0, chksumpad - size); + digest.update(pad, chksumpad - size); + } + std::vectordig = digest.digestVector(); + if (dig.empty() || dig.size() < size_t(chksumlen)) + return false; + return memcmp(&dig[0], &chksums[chksumlen * blkno], chksumlen) ? false : true; +} + +unsigned int +MediaBlockList::updateRsum(unsigned int rs, const char* bytes, size_t len) const +{ + if (!len) + return rs; + + unsigned short s = 0, m = 0; + s = (rs >> 16) & 65535; + m = rs & 65535; + for (; len > 0 ; len--) + { + unsigned short c = (unsigned char)*bytes++; + s += c; + m += s; + } + return (s & 65535) << 16 | (m & 65535); +} + +bool +MediaBlockList::verifyRsum(size_t blkno, unsigned int rs) const +{ + if (!haveRsum(blkno)) + return true; + size_t size = blocks[blkno].size; + if (!size) + return true; + if (rsumpad > size) + { + unsigned short s = 0, m = 0; + s = (rs >> 16) & 65535; + m = rs & 65535; + m += s * (rsumpad - size); + rs = (s & 65535) << 16 | (m & 65535); + } + truncateRsum( rs, rsumlen ); + return rs == rsums[blkno]; +} + +bool +MediaBlockList::checkRsum(size_t blkno, const unsigned char *buf, size_t bufl) const +{ + if (blkno >= blocks.size() || bufl < blocks[blkno].size) + return false; + unsigned int rs = updateRsum(0, (const char *)buf, blocks[blkno].size); + return verifyRsum(blkno, rs); +} + +bool +MediaBlockList::checkChecksum(size_t blkno, const unsigned char *buf, size_t bufl) const +{ + if (blkno >= blocks.size() || bufl < blocks[blkno].size) + return false; + Digest dig; + if (!createDigest(dig)) + return false; + dig.update((const char *)buf, blocks[blkno].size); + return verifyDigest(blkno, dig); +} + +UByteArray MediaBlockList::getChecksum(size_t blkno) const +{ + if ( !haveChecksum(blkno) ) + return {}; + + UByteArray buf ( chksumlen, '\0' ); + memcpy( buf.data(), chksums.data()+(chksumlen * blkno), chksumlen ); + return buf; +} + +std::string MediaBlockList::getChecksumType() const +{ + return chksumtype; +} + +size_t MediaBlockList::checksumPad() const +{ + return chksumpad; +} + +// specialized version of checkChecksum that can deal with a "rotated" buffer +bool +MediaBlockList::checkChecksumRotated(size_t blkno, const unsigned char *buf, size_t bufl, size_t start) const +{ + if (blkno >= blocks.size() || bufl < blocks[blkno].size) + return false; + if (start == bufl) + start = 0; + Digest dig; + if (!createDigest(dig)) + return false; + size_t size = blocks[blkno].size; + size_t len = bufl - start > size ? size : bufl - start; + dig.update((const char *)buf + start, len); + if (size > len) + dig.update((const char *)buf, size - len); + return verifyDigest(blkno, dig); +} + +// write block to the file. can also deal with "rotated" buffers +void +MediaBlockList::writeBlock(size_t blkno, FILE *fp, const unsigned char *buf, size_t bufl, size_t start, std::vector &found) const +{ + if (blkno >= blocks.size() || bufl < blocks[blkno].size) + return; + off_t off = blocks[blkno].off; + size_t size = blocks[blkno].size; + if (fseeko(fp, off, SEEK_SET)) + return; + if (start == bufl) + start = 0; + size_t len = bufl - start > size ? size : bufl - start; + if (fwrite(buf + start, len, 1, fp) != 1) + return; + if (size > len && fwrite(buf, size - len, 1, fp) != 1) + return; + found[blkno] = true; + found[blocks.size()] = true; +} + +static size_t +fetchnext(FILE *fp, unsigned char *bp, size_t blksize, size_t pushback, unsigned char *pushbackp) +{ + size_t l = blksize; + int c = 0; + + if (pushback) + { + if (pushbackp != bp) + memmove(bp, pushbackp, pushback); + bp += pushback; + l -= pushback; + } + while (l) + { + c = getc(fp); + if (c == EOF) + break; + *bp++ = c; + l--; + } + if (l) + memset(bp, 0, l); + return blksize - l; +} + +void MediaBlockList::reuseBlocks(FILE *wfp, const std::string& filename) +{ + + zypp::AutoFILE fp; + + if ( !chksumlen ) { + DBG << "Delta XFER: Can not reuse blocks because we have no chksumlen" << std::endl; + return; + } + + if ( (fp = fopen(filename.c_str(), "r")) == 0 ) { + DBG << "Delta XFER: Can not reuse blocks, unable to open file "<< filename << std::endl; + return; + } + + size_t nblks = blocks.size(); + std::vector found( nblks + 1 ); + if (rsumlen && !rsums.empty()) { + + const auto rsumAMask = rsumlen < 3 ? 0 : rsumlen == 3 ? 0xff : 0xffff; + + // we are building a array of rsum structs to directly access a and b parts of the checksum + // we make the array bigger so that the code calculating the rsum hashes does not need to care + // about the array size + // @TODO move that to the function adding new rsums when removing the old code + auto zsyncRsumsData = std::make_unique( rsums.size() + rsumseq ); + auto zsyncRsums = zsyncRsumsData.get(); + for ( std::size_t i = 0; i < rsums.size(); i++ ) { + const auto &rs = rsums[i]; + unsigned short s = 0, m = 0; + s = (rs >> 16) & 65535; + m = rs & 65535; + zsyncRsums[i] = rsum{ s, m }; + } + + // we use the same code as zsync to calc the hash + const auto & calc_rhash = [&]( const rsum* e ) -> unsigned { + unsigned h = e[0].b; + if ( this->rsumseq > 1 ) { + for ( uint i = 1; i < rsumseq; i++ ) { + h ^= e[i].b << 3; + } + } else { + h ^= ( e[0].a & rsumAMask ) << 3; + } + return h; + }; + + size_t blksize = blocks[0].size; + if (nblks == 1 && rsumpad && rsumpad > blksize) + blksize = rsumpad; + + // create hash of checksums + // build the hashtable + uint rsumHashMask = 0; + { + int i = 16; + + /* Try hash size of 2^i; step down the value of i until we find a good size */ + while ((2 << (i - 1)) > nblks && i > 4) + i--; + + /* Allocate hash based on rsum */ + rsumHashMask = (2 << i) - 1; + } + + // a array indexed via hash with lists of blocks resulting in the same rsum hash + auto rsumHashTableData = std::make_unique[]>( rsumHashMask + 1 ); + auto rsumHashTable = rsumHashTableData.get(); + + // Now fill in the hash tables. + for ( size_t id = 0; id < nblks; id++) { + const auto hash = calc_rhash( &zsyncRsums[id] ); + auto &hashList = rsumHashTable[ hash & rsumHashMask ]; + hashList.push_back(id); + } + + // we read in 16 sequences at once to speed up processing + constexpr auto BLOCKCNT = 16; + + // we allocate the buffer so that we always have the data to verify 16 blocks, if we need to do + // sequence matching we grow the buffer accordingly + const auto readBufSize = blksize * rsumseq * BLOCKCNT; + + // buffer thats going to hold our cached data + auto readBufData = std::make_unique( readBufSize ); + memset(readBufData.get(), 0, blksize); + + // avoid using .get() all the time + auto readBuf = readBufData.get(); + + // our running checksums for the blocks we need to match in sequence + auto seqRsumsData = std::make_unique ( rsumseq ); + auto seqRsums = seqRsumsData.get(); + + // use byteshift instead of multiplication if the blksize is a power of 2 + // a value is a power of 2 if ( N & N-1 ) == 0 + int bshift = 0; // how many bytes do we need to shift + if ((blksize & (blksize - 1)) == 0) + for (bshift = 0; size_t(1 << bshift) != blksize; bshift++) + ; + + bool init = true; + // when we are in a run of matches, we remember which block ID would need to match next in order + // to continue writing + std::optional nextReqMatchInSequence; + off_t dataOffset = 0; //< Our current read offset in the buffer + off_t dataLen = 0; //< The length of our read buffer + + // helper lambda that follows a list of hashmap entries and tries to write those that match + const auto &tryWriteMatchingBlocks = [&]( const std::vector &list, const u_char *currBuf, uint reqMatches ){ + // the number of blocks we have transferred to the target file + int targetBlocksWritten = 0; + + // reset the next match hint + nextReqMatchInSequence.reset(); + + for ( const auto blkno : list ) { + + if ( found[blkno] ) + continue; + + const auto blockRsum = &zsyncRsums[blkno]; + + uint weakMatches = 0; + + // first check only the current block, we maybe can skip checking the others + // if we are in a run of matches + if ( (seqRsums[0].a & rsumAMask) != blockRsum[0].a || + seqRsums[0].b != blockRsum[0].b ) + continue; + + weakMatches++; + + for ( uint i = 1; i < reqMatches; i++ ) { + if ( (seqRsums[i].a & rsumAMask) != blockRsum[i].a || + seqRsums[i].b != blockRsum[i].b ) + break; + weakMatches++; + } + + if ( weakMatches < reqMatches ) + continue; + + // we have a weak match, now we need to calc the checksums for the blocks + uint realMatches = 0; + for( uint i = 0; i < reqMatches; i++ ) { + if ( !checkChecksum(blkno + i, currBuf + ( i * blksize ), blksize ) ) { + break; + } + realMatches++; + } + + // check if we have the amount of matches we need ( only 1 if we are in a block sequence ) + if( realMatches < reqMatches ) + continue; + + // we found blocks that match , write them to target but keep searching the hashmap + // in case we have redundancies + const auto nextPossibleMatch = blkno + realMatches; + if ( !found[nextPossibleMatch] ) + nextReqMatchInSequence = nextPossibleMatch; // remember that we are currently in a run of matches, next iteration we just need to look at one block + + for( uint i = 0; i < realMatches; i++ ) { + writeBlock( blkno + i, wfp, currBuf + ( i * blksize ), blksize, 0, found ); + targetBlocksWritten++; + } + } + return targetBlocksWritten; + }; + + if (!rsumseq) + rsumseq = nblks > 1 && chksumlen < 16 ? 2 : 1; + + const off_t seqMatchLen = ( blksize * rsumseq ); //< how many bytes do we need to match when searching a block + + while (! feof(fp) ) { + if ( init ) { + // fill the buffer for the first time + dataLen = fread( readBuf, 1, readBufSize, fp ); + init = false; + } else { + // move the remaining data to the begin and read from the file to fill up the buffer again + const auto remainLen = dataLen-dataOffset; + if ( remainLen ) + memmove( readBuf, readBuf+dataOffset, remainLen ); + + dataLen = fread( readBuf+remainLen, 1, readBufSize-remainLen, fp ); + dataLen += remainLen; + dataOffset = 0; + } + + // if we hit eof, pad with zeros + if ( feof(fp) ) { + memset( readBuf + dataLen, 0, readBufSize - dataLen ); + dataLen = readBufSize; + } + + if ( dataLen < seqMatchLen ) + return; + + // intialize our first set of checksums + for( uint i = 0; i < rsumseq; i++ ) + seqRsums[i] = rcksum_calc_rsum_block( readBuf + ( i * blksize ), blksize ); + + //read over the buffer we have allocated so far + while ( true ) { + + if ( dataOffset + seqMatchLen > dataLen ) + break; + + u_char *currBuf = readBuf + dataOffset; + + // the number of deltafile blocks we have matched, e.g. how much blocks + // can we skip forward + uint deltaBlocksMatched = 0; + + if ( nextReqMatchInSequence.has_value() ) { + if ( tryWriteMatchingBlocks( { *nextReqMatchInSequence }, currBuf, 1 ) > 0 ) + deltaBlocksMatched = 1; + + } else { + const auto hash = calc_rhash( seqRsums ); + + // reference to the list of blocks that share our calculated hash + auto &blockListForHash = rsumHashTable[ hash & rsumHashMask ]; + if ( blockListForHash.size() ) { + if ( tryWriteMatchingBlocks( blockListForHash, currBuf, rsumseq ) > 0 ) + deltaBlocksMatched = rsumseq; + } + } + + if ( deltaBlocksMatched > 0 ) { + // we jump forward in the buffer to after what we matched + dataOffset += ( deltaBlocksMatched * blksize ); + + if ( dataOffset + seqMatchLen > dataLen ) + break; + + if ( deltaBlocksMatched < rsumseq ) { + //@TODO move the rsums we already have + } + + for( uint i = 0; i < rsumseq; i++ ) + seqRsums[i] = rcksum_calc_rsum_block( readBuf + dataOffset + ( i * blksize ), blksize ); + + + } else { + // we found nothing advance the window by one byte and update the rsums + dataOffset++; + if ( dataOffset + seqMatchLen > dataLen ) + break; + for ( uint i = 0; i < rsumseq; i++ ) { + const auto blkOff = ( i*blksize ); + u_char oldC = (currBuf + blkOff)[0]; + u_char newC = (currBuf + blkOff)[blksize]; + UPDATE_RSUM( seqRsums[i].a, seqRsums[i].b, oldC, newC, bshift ); + } + } + } + } + } + else if (chksumlen >= 16) + { + // dummy variant, just check the checksums + size_t bufl = 4096; + off_t off = 0; + auto buf = std::make_unique( bufl ); + for (size_t blkno = 0; blkno < blocks.size(); ++blkno) + { + if (off > blocks[blkno].off) + continue; + size_t blksize = blocks[blkno].size; + if (blksize > bufl) + { + bufl = blksize; + buf = std::make_unique( bufl ); + } + size_t skip = blocks[blkno].off - off; + while (skip) + { + size_t l = skip > bufl ? bufl : skip; + if (fread(buf.get(), l, 1, fp) != 1) + break; + skip -= l; + off += l; + } + if (fread(buf.get(), blksize, 1, fp) != 1) + break; + if (checkChecksum(blkno, buf.get(), blksize)) + writeBlock(blkno, wfp, buf.get(), blksize, 0, found); + off += blksize; + } + } + if (!found[nblks]) { + DBG << "Delta XFER: No reusable blocks found for " << filename << std::endl; + return; + } + // now throw out all of the blocks we found + std::vector nblocks; + std::vector nchksums; + std::vector nrsums; + + size_t originalSize = 0; + size_t newSize = 0; + for (size_t blkno = 0; blkno < blocks.size(); ++blkno) + { + const auto &blk = blocks[blkno]; + originalSize += blk.size; + if (!found[blkno]) + { + // still need it + nblocks.push_back(blk); + newSize += blk.size; + if (chksumlen && (blkno + 1) * chksumlen <= chksums.size()) + { + nchksums.resize(nblocks.size() * chksumlen); + memcpy(&nchksums[(nblocks.size() - 1) * chksumlen], &chksums[blkno * chksumlen], chksumlen); + } + if (rsumlen && (blkno + 1) <= rsums.size()) + nrsums.push_back(rsums[blkno]); + } + } + DBG << "Delta XFER: Found blocks to reuse, " << blocks.size() << " vs " << nblocks.size() << ", resused blocks: " << blocks.size() - nblocks.size() << "\n" + << "Old transfer size: " << originalSize << " new size: " << newSize << std::endl; + blocks = nblocks; + chksums = nchksums; + rsums = nrsums; +} + +void MediaBlockList::reuseBlocksOld(FILE *wfp, const std::string& filename) +{ + + zypp::AutoFILE fp; + + if ( !chksumlen ) { + DBG << "Delta XFER: Can not reuse blocks because we have no chksumlen" << std::endl; + return; + } + + if ( (fp = fopen(filename.c_str(), "r")) == 0 ) { + DBG << "Delta XFER: Can not reuse blocks, unable to open file "<< filename << std::endl; + return; + } + size_t nblks = blocks.size(); + std::vector found; + found.resize(nblks + 1); + if (rsumlen && !rsums.empty()) + { + size_t blksize = blocks[0].size; + if (nblks == 1 && rsumpad && rsumpad > blksize) + blksize = rsumpad; + + // create hash of checksums + + // calculate the size of the hashtable by setting + // all bits to 1 up the to currently set MSB + // if we have 00010010 we end up with 00011111 + unsigned int hm = rsums.size() * 2; + while (hm & (hm - 1)) { + hm &= hm - 1; + } + hm = hm * 2 - 1; + + // we want at least a size if 0011 1111 1111 1111 + if (hm < 16383) + hm = 16383; + + // simple hashtable of checksums + auto rsumHashTable = std::make_unique( hm+1 ); + memset(rsumHashTable.get(), 0, (hm + 1) * sizeof(unsigned int)); + + // insert each rsum into the hash table + for (unsigned int i = 0; i < rsums.size(); i++) + { + if (blocks[i].size != blksize && (i != nblks - 1 || rsumpad != blksize)) + continue; + unsigned int r = rsums[i]; + unsigned int h = r & hm; + unsigned int hh = 7; + while (rsumHashTable[h]) + h = (h + hh++) & hm; + rsumHashTable[h] = i + 1; + } + + // read in block by block to find matches + // the read buffer "buf" works like a ring buffer, means that once we are done with reading a full block + // and didn't find a match we start again at buf[0] , filling the buffer up again, rotating until we find + // a matching block. Once we find a matching block all we need to do is check if the current offset "i" + // is at the end of the buffer, then we can simply write the full buffer out, or if its somewhere in between + // then the begin of our block is buf[i+1, bufsize-1] and the end buf[0,i] + auto ringBuf = std::make_unique( blksize ); + + // we use a second buffer to read in the next block if we are required to match more than one block at the same time. + auto buf2 = std::make_unique( blksize ); + + // when we are required to match more than one block, it is read into buf2 advancing the file pointer, + // to make sure that we do not loose those bytes in case the match fails we remember their count and + // start in buf2, in the next loop those will be consumed before reading from the file again + size_t pushback = 0; + unsigned char *pushbackp = 0; + + // use byteshift instead of multiplication if the blksize is a power of 2 + // a value is a power of 2 if ( N & N-1 ) == 0 + int bshift = 0; // how many bytes do we need to shift + if ((blksize & (blksize - 1)) == 0) + for (bshift = 0; size_t(1 << bshift) != blksize; bshift++) + ; + + // a and b are the LS and MS bytes of the checksum, calculated a rolling style Adler32 checksum + // + // a(k,l) = (\sum_{i=k}^l X_i) \bmod M + unsigned short a = 0, b = 0; + a = b = 0; + memset(ringBuf.get(), 0, blksize); + bool eof = 0; + bool init = 1; + + if (!rsumseq) + rsumseq = nblks > 1 && chksumlen < 16 ? 2 : 1; + + while (!eof) + { + for (size_t i = 0; i < blksize; i++) + { + // get the next character from the file + // or if there are pushback chars use those + int c = 0; + if (eof) + c = 0; + else + { + if (pushback) + { + c = *pushbackp++; + pushback--; + } + else + c = getc(fp); + if (c == EOF) + { + eof = true; + c = 0; + if (!i || rsumseq == 2) + break; + } + } + + // calculate the rsum on the fly using recurrence relations, see https://rsync.samba.org/tech_report/node3.html + // basically we subtract the checksum value of a byte the leaves the current block window and add the new incoming one + // using this trick we do not need to calculate the full block checksum + // the least significant part of the checksum ( lower 8 bits ) is simply the sum of all chars in the block , modulo 2^16 + // zsync uses only a 16bit type to calculate the sums and as far as i can see does not do the modulo per block as the formula + // says it should, we might need to do the same + int oc = ringBuf[i]; + ringBuf[i] = c; + + a += c - oc; + + // this is calculates the most significant part of the checksum, bshift should be always set since blocksize + // should always be a power of 2 + if (bshift) + b += a - ( oc << bshift ); + else + // This seems to make no sense it does not even factor in the character itself + b += 2 * blksize; + + if (init) + { + // continue reading bytes until we have the full block in our buffer + if (size_t(i) != blksize - 1) + continue; + init = 0; + } + + unsigned int r = ((unsigned int)a & 65535) << 16 | ((unsigned int)b & 65535); + truncateRsum(r, rsumlen); + + unsigned int h = r & hm; + unsigned int hh = 7; + + // go through our hashmap to find all the matching rsums + for (; rsumHashTable[h]; h = (h + hh++) & hm) + { + size_t blkno = rsumHashTable[h] - 1; + + // does the current block match? + if (rsums[blkno] != r) + continue; + if (found[blkno]) + continue; + + // if we need to always match 2 blocks in sequence, get the next block + // and check its checksum + if (rsumseq == 2) + { + if (eof || blkno + 1 >= nblks) + continue; + pushback = fetchnext(fp, buf2.get(), blksize, pushback, pushbackp); + pushbackp = buf2.get(); + if (!pushback) + continue; + + if (!checkRsum(blkno + 1, buf2.get(), blksize)) + continue; + } + + // here we have matched all blocks that we need, do the heavy checksum + if (!checkChecksumRotated(blkno, ringBuf.get(), blksize, i + 1)) + continue; + + // heavy checksum for second block + if (rsumseq == 2 && !checkChecksum(blkno + 1, buf2.get(), blksize)) + continue; + + // write the first and second blocks if applicable + writeBlock(blkno, wfp, ringBuf.get(), blksize, i + 1, found); + if (rsumseq == 2) + { + writeBlock(blkno + 1, wfp, buf2.get(), blksize, 0, found); + pushback = 0; + blkno++; + } + + // try to continue as long as we still match blocks + while (!eof) + { + blkno++; + pushback = fetchnext(fp, buf2.get(), blksize, pushback, pushbackp); + pushbackp = buf2.get(); + if (!pushback) + break; + + if (!checkRsum(blkno, buf2.get(), blksize)) + break; + + if (!checkChecksum(blkno, buf2.get(), blksize)) + break; + + writeBlock(blkno, wfp, buf2.get(), blksize, 0, found); + pushback = 0; + } + + // if we get to this part we found at least a block, skip over the current block and start reading + // in a full block + init = true; + memset(ringBuf.get(), 0, blksize); + a = b = 0; + i = size_t(-1); // start with 0 on next iteration + break; + } + } + } + } + else if (chksumlen >= 16) + { + // dummy variant, just check the checksums + size_t bufl = 4096; + off_t off = 0; + auto buf = std::make_unique( bufl ); + for (size_t blkno = 0; blkno < blocks.size(); ++blkno) + { + if (off > blocks[blkno].off) + continue; + size_t blksize = blocks[blkno].size; + if (blksize > bufl) + { + bufl = blksize; + buf = std::make_unique( bufl ); + } + size_t skip = blocks[blkno].off - off; + while (skip) + { + size_t l = skip > bufl ? bufl : skip; + if (fread(buf.get(), l, 1, fp) != 1) + break; + skip -= l; + off += l; + } + if (fread(buf.get(), blksize, 1, fp) != 1) + break; + if (checkChecksum(blkno, buf.get(), blksize)) + writeBlock(blkno, wfp, buf.get(), blksize, 0, found); + off += blksize; + } + } + if (!found[nblks]) { + DBG << "Delta XFER: No reusable blocks found for " << filename << std::endl; + return; + } + // now throw out all of the blocks we found + std::vector nblocks; + std::vector nchksums; + std::vector nrsums; + + size_t originalSize = 0; + size_t newSize = 0; + for (size_t blkno = 0; blkno < blocks.size(); ++blkno) + { + const auto &blk = blocks[blkno]; + originalSize += blk.size; + if (!found[blkno]) + { + // still need it + nblocks.push_back(blk); + newSize += blk.size; + if (chksumlen && (blkno + 1) * chksumlen <= chksums.size()) + { + nchksums.resize(nblocks.size() * chksumlen); + memcpy(&nchksums[(nblocks.size() - 1) * chksumlen], &chksums[blkno * chksumlen], chksumlen); + } + if (rsumlen && (blkno + 1) <= rsums.size()) + nrsums.push_back(rsums[blkno]); + } + } + DBG << "Delta XFER: Found blocks to reuse, " << blocks.size() << " vs " << nblocks.size() << ", resused blocks: " << blocks.size() - nblocks.size() << "\n" + << "Old transfer size: " << originalSize << " new size: " << newSize << std::endl; + blocks = nblocks; + chksums = nchksums; + rsums = nrsums; +} + +std::string +MediaBlockList::asString() const +{ + std::string s; + size_t i = 0, j = 0; + + if (filesize != off_t(-1)) + { + long long size = filesize; + s = zypp::str::form("[ BlockList, file size %lld\n", size); + } + else + s = "[ BlockList, filesize unknown\n"; + if (!haveblocks) + s += " No block information\n"; + if (chksumpad) + s += zypp::str::form(" Checksum pad %zd\n", chksumpad); + if (rsumpad) + s += zypp::str::form(" Rsum pad %zd\n", rsumpad); + for (i = 0; i < blocks.size(); ++i) + { + long long off=blocks[i].off; + long long size=blocks[i].size; + s += zypp::str::form(" (%8lld, %8lld)", off, size); + if (chksumlen && chksums.size() >= (i + 1) * chksumlen) + { + s += " " + chksumtype + ":"; + for (j = 0; j < size_t(chksumlen); j++) + s += zypp::str::form("%02hhx", chksums[i * chksumlen + j]); + } + if (rsumlen && rsums.size() > i) + { + s += " RSUM:"; + s += zypp::str::form("%0*x", 2 * rsumlen, rsums[i]); + } + s += "\n"; + } + s += "]"; + return s; +} + + } // namespace media +} // namespace zypp diff --git a/zypp-curl/parser/mediablocklist.h b/zypp-curl/parser/mediablocklist.h new file mode 100644 index 0000000..8e0d08e --- /dev/null +++ b/zypp-curl/parser/mediablocklist.h @@ -0,0 +1,164 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/parser/MediaBlockList + * +*/ +#ifndef ZYPP_CURL_PARSER_MEDIABLOCKLIST_H +#define ZYPP_CURL_PARSER_MEDIABLOCKLIST_H + +#include +#include +#include + +#include + +namespace zypp { + namespace media { + +/** + * a single block from the blocklist, consisting of an offset and a size + **/ +struct MediaBlock { + MediaBlock( off_t off_r, size_t size_r ) + : off( off_r ) + , size( size_r ) + {} + off_t off; + size_t size; +}; + +class MediaBlockList { +public: + MediaBlockList(off_t filesize=off_t(-1)); + + /** + * do we have a blocklist describing the file? + * set to true when addBlock() is called + **/ + inline bool haveBlocks() const { + return haveblocks; + } + /** + * add a block with offset off and size size to the block list. Note + * that blocks must be ordered and must not overlap. returns the + * block number. + **/ + size_t addBlock(off_t off, size_t size); + + /** + * return the offset/size of a block with number blkno + **/ + inline const MediaBlock &getBlock(size_t blkno) const { + return blocks[blkno]; + } + /** + * return the number of blocks in the blocklist + **/ + inline size_t numBlocks() const { + return blocks.size(); + } + + /** + * set / return the size of the whole file + **/ + inline void setFilesize(off_t newfilesize=off_t(-1)) { + filesize = newfilesize; + } + inline off_t getFilesize() const { + return filesize; + } + inline bool haveFilesize() const { + return filesize != off_t(-1); + } + + /** + * set / verify the checksum over the whole file + **/ + void setFileChecksum(std::string ctype, int cl, unsigned char *c); + std::string fileChecksumType () const; + + const UByteArray &getFileChecksum( ); + bool createFileDigest(Digest &digest) const; + bool verifyFileDigest(Digest &digest) const; + inline bool haveFileChecksum() const { + return !fsumtype.empty() && fsum.size(); + } + + /** + * set / verify the (strong) checksum over a single block + **/ + void setChecksum(size_t blkno, const std::string& cstype, int csl, unsigned char *cs, size_t cspad=0); + bool checkChecksum(size_t blkno, const unsigned char *buf, size_t bufl) const; + UByteArray getChecksum( size_t blkno ) const; + std::string getChecksumType( ) const; + size_t checksumPad() const; + bool createDigest(Digest &digest) const; + bool verifyDigest(size_t blkno, Digest &digest) const; + inline bool haveChecksum(size_t blkno) const { + return chksumlen && chksums.size() >= chksumlen * (blkno + 1); + } + + /** + * set / verify the (weak) rolling checksum over a single block + **/ + void setRsum(size_t blkno, int rsl, unsigned int rs, size_t rspad=0); + + /** + * how many blocks in sequence need to have the correct checksums to be + * considered a match + */ + void setRsumSequence( uint seq ); + bool checkRsum(size_t blkno, const unsigned char *buf, size_t bufl) const; + unsigned int updateRsum(unsigned int rs, const char *bytes, size_t len) const; + bool verifyRsum(size_t blkno, unsigned int rs) const; + inline bool haveRsum(size_t blkno) const { + return rsumlen && rsums.size() >= blkno + 1; + } + + /** + * scan a file for blocks from our blocklist. if we find a suitable block, + * it is removed from the list + **/ + void reuseBlocksOld(FILE *wfp, const std::string& filename); + void reuseBlocks(FILE *wfp, const std::string& filename); + + /** + * return block list as string + **/ + std::string asString() const; + +private: + void writeBlock(size_t blkno, FILE *fp, const unsigned char *buf, size_t bufl, size_t start, std::vector &found) const; + bool checkChecksumRotated(size_t blkno, const unsigned char *buf, size_t bufl, size_t start) const; + + off_t filesize; + std::string fsumtype; + UByteArray fsum; + + bool haveblocks; + std::vector blocks; + + std::string chksumtype; + int chksumlen; + size_t chksumpad; + std::vector chksums; + + int rsumlen; + uint rsumseq; // < how many consecutive matches are required + size_t rsumpad; + std::vector rsums; +}; + +inline std::ostream & operator<<(std::ostream &str, const MediaBlockList &bl) +{ return str << bl.asString(); } + + } // namespace media +} // namespace zypp + +#endif // ZYPP_CURL_PARSER_MEDIABLOCKLIST_H diff --git a/zypp-curl/parser/metadatahelper.cc b/zypp-curl/parser/metadatahelper.cc new file mode 100644 index 0000000..8d9df9f --- /dev/null +++ b/zypp-curl/parser/metadatahelper.cc @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "metadatahelper.h" + +#include +#include + +namespace zypp::media { + + MetaDataType looks_like_meta_data(const std::vector &data) + { + if ( data.empty() ) + return MetaDataType::None; + + const char *p = data.data(); + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + + // If we have a zsync file, it has to start with zsync: + if ( !strncasecmp( p, "zsync:", 6 ) ) { + return MetaDataType::Zsync; + } + + if (!strncasecmp(p, "') + p++; + if (*p == '>') + p++; + while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n') + p++; + } + bool ret = !strncasecmp( p, " fd( fopen( file.c_str(), "r" ), &fclose ); + return looks_like_meta_file( fd.get() ); + } + + MetaDataType looks_like_meta_file(FILE *file) + { + if ( !file ) + return MetaDataType::None; + return looks_like_meta_data( io::peek_data_fd( file, 0, minMetalinkProbeSize ) ); + } + +} diff --git a/zypp-curl/parser/metadatahelper.h b/zypp-curl/parser/metadatahelper.h new file mode 100644 index 0000000..5f3414f --- /dev/null +++ b/zypp-curl/parser/metadatahelper.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_CURL_PARSER_METADATAHELPER_H +#define ZYPP_CURL_PARSER_METADATAHELPER_H + +/*! + * \file contains helpers for detecting and handling download metadata... + * e.g. zsync or metalink + */ + + +#include +#include +#include + +namespace zypp::media { + + enum class MetaDataType { + None = 0, + Zsync, + MetaLink + }; + + constexpr auto minMetalinkProbeSize = 256; //< The nr of bytes we download to decide if we got a metadata file or not + + MetaDataType looks_like_meta_data( const std::vector &data ); + MetaDataType looks_like_meta_file( const zypp::Pathname &file ); + MetaDataType looks_like_meta_file( FILE *file ); +} + + +#endif diff --git a/zypp-curl/parser/metalinkparser.cc b/zypp-curl/parser/metalinkparser.cc new file mode 100644 index 0000000..c6aee08 --- /dev/null +++ b/zypp-curl/parser/metalinkparser.cc @@ -0,0 +1,537 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/parser/metalinkparser.cc + * + */ + +#include "metalinkparser.h" +#include +#include +#include + +#include +#include +#include + +#include + +using namespace zypp::base; + +namespace zypp::env +{ + /** Hack to circumvent the currently poor --root support. */ + inline bool ZYPP_METALINK_DEBUG() + { + static bool val = [](){ + const char * env = getenv("ZYPP_METALINK_DEBUG"); + return( env && zypp::str::strToBool( env, true ) ); + }(); + return val; + } +} + +namespace zypp::media { + enum ParserState { + STATE_START, + STATE_METALINK, + STATE_FILES, + STATE_FILE, + STATE_M4FILE, + STATE_SIZE, + STATE_M4SIZE, + STATE_VERIFICATION, + STATE_HASH, + STATE_M4HASH, + STATE_PIECES, + STATE_M4PIECES, + STATE_PHASH, + STATE_M4PHASH, + STATE_RESOURCES, + STATE_URL, + STATE_M4URL, + NUMSTATES + }; + + struct transition { + std::string elementName; //< Name of the element for the transition to trigger + ParserState transitionTo; //< The state we go into when the element name in \a elementName is encountered + int docontent; //< Store the content of the element in the \a content member + }; + + /*! + * Returns a map of all state transitions that are supported. + * Key of the map is the current state, the value is a list of all supported transitions + * of the the current state. + */ + const std::unordered_map > & transitions () { + static std::unordered_map > map { + { STATE_START, { + { "metalink", STATE_METALINK, 0}, + } + }, + { STATE_METALINK, { + { "files", STATE_FILES, 0 }, + { "file", STATE_M4FILE, 0 }, + } + }, + { STATE_FILES, { + { "file", STATE_FILE, 0}, + } + }, + { STATE_FILE, { + { "size", STATE_SIZE, 1 }, + { "verification", STATE_VERIFICATION, 0 }, + { "resources", STATE_RESOURCES, 0 }, + } + }, + { STATE_VERIFICATION, { + { "hash", STATE_HASH, 1 }, + { "pieces", STATE_PIECES, 0 }, + } + }, + { STATE_PIECES, { + { "hash", STATE_PHASH, 1 }, + } + }, + { STATE_RESOURCES, { + { "url", STATE_URL, 1 }, + } + }, + { STATE_M4FILE, { + { "size", STATE_M4SIZE, 1 }, + { "hash", STATE_M4HASH, 1}, + { "url", STATE_M4URL, 1}, + { "pieces", STATE_M4PIECES, 0}, + } + }, + { STATE_M4PIECES, { + { "hash", STATE_M4PHASH, 1 }, + } + }, + }; + + return map; + } + +static void XMLCALL startElement(void *userData, const xmlChar *name, const xmlChar **atts); +static void XMLCALL endElement(void *userData, const xmlChar *name); +static void XMLCALL characterData(void *userData, const xmlChar *s, int len); + +struct ml_parsedata : private zypp::base::NonCopyable { + ml_parsedata() + : parser( nullptr ) + , state( STATE_START ) + , depth( 0 ) + , statedepth( 0 ) + , docontent( 0 ) + , gotfile( 0 ) + , size( -1 ) + , blksize( 0 ) + , piecel( 0 ) + , chksuml( 0 ) + { + content.reserve( 256 ); + + xmlSAXHandler sax; + memset(&sax, 0, sizeof(sax)); + sax.startElement = startElement; + sax.endElement = endElement; + sax.characters = characterData; + + //internally creates a copy of xmlSaxHandler, so having it as local variable is save + parser = AutoDispose( xmlCreatePushParserCtxt(&sax, this, NULL, 0, NULL), xmlFreeParserCtxt ); + } + + void doTransition ( const transition &t ) { + parentStates.push( state ); + state = t.transitionTo; + docontent = t.docontent; + statedepth = depth; + content.clear(); + } + + void popState () { + state = parentStates.top(); + statedepth--; + parentStates.pop(); + + } + + AutoDispose parser; + + ParserState state; //< current state as defined in \ref stateswitch + std::stack parentStates; + + int depth; //< current element depth of traversing the document elements + + /*! + * Current element depts expected by the current state, + * if depth != statedepth we ignore all elements and just increase and decrease depth until they match again. + * This is basically a helper variable that allows us to ignore elements we do not care about + */ + int statedepth; + + std::string content; //< content of the current element + int docontent; //< should the content of the current elem be parsed + + int gotfile; + off_t size; + std::vector urls; + size_t blksize; + + std::vector piece; + int piecel; + + std::vector sha1; + std::vector zsync; + + UByteArray chksum; + int chksuml; +}; + +/** + * Look up a xml attribute in the passed array \a atts. + * Returns a pointer to the value of the attribute if one is found, otherwise nullptr. + */ +static const char * +find_attr(const char *txt, const xmlChar **atts) +{ + if(!atts) { + return nullptr; + } + + for (; *atts; atts += 2) + { + if (!strcmp(reinterpret_cast(*atts), txt)) + return reinterpret_cast(atts[1]); + } + return nullptr; +} + +static void XMLCALL +startElement(void *userData, const xmlChar *name, const xmlChar **atts) +{ + struct ml_parsedata *pd = reinterpret_cast(userData); + + // if the current element depth does not match the expected depth for the current state we + // ignore the element and just increase the depth + if (pd->depth != pd->statedepth) { + pd->depth++; + return; + } + pd->depth++; + + const auto &trMap = transitions(); + const auto currStateTrs = trMap.find( pd->state ); + if ( currStateTrs == trMap.end() ) + return; + + // check if the current element name is part of our transitions + auto foundTr = std::find_if( currStateTrs->second.begin(), currStateTrs->second.end(), [name]( const auto &tr ){ + return tr.elementName == reinterpret_cast(name); + }); + + if ( foundTr == currStateTrs->second.end() ) { + // we found no possible transition, ignore + return; + } + + if ( ( foundTr->transitionTo == STATE_FILE || foundTr->transitionTo == STATE_M4FILE ) && pd->gotfile++) + return; /* ignore all but the first file */ + + // advance the state machine and prepare variables for the new state + pd->doTransition( *foundTr ); + + switch(pd->state) + { + case STATE_URL: + case STATE_M4URL: + { + const char *priority = find_attr("priority", atts); + const char *preference = find_attr("preference", atts); + const char *maxconnections = find_attr("maxconnections", atts); + int prio = 0; + auto &mirr = pd->urls.emplace_back(); + if (priority) + prio = str::strtonum(priority); + else if (preference) + prio = 101 - str::strtonum(preference); + else + prio = 999999; + mirr.priority = prio; + + if ( maxconnections ) + mirr.maxConnections = str::strtonum( maxconnections ); + + break; + } + case STATE_PIECES: + case STATE_M4PIECES: + { + const char *type = find_attr("type", atts); + const char *length = find_attr("length", atts); + size_t blksize = 0; + + if (!type || !length) + { + pd->popState(); + break; + } + blksize = str::strtonum(length); + if (!blksize || (pd->blksize && pd->blksize != blksize)) + { + pd->popState(); + break; + } + pd->blksize = blksize; + pd->piece.clear(); + if (!strcmp(type, "sha1") || !strcmp(type, "sha-1")) + pd->piecel = 20; + else if (!strcmp(type, "zsync")) + pd->piecel = 4; + else + { + pd->popState(); + break; + } + break; + } + case STATE_HASH: + case STATE_M4HASH: + { + const char *type = find_attr("type", atts); + if (!type) + type = "?"; + if ((!strcmp(type, "sha1") || !strcmp(type, "sha-1")) && pd->chksuml < 20) + pd->chksuml = 20; + else if (!strcmp(type, "sha256") || !strcmp(type, "sha-256")) + pd->chksuml = 32; + else + { + pd->popState(); + pd->docontent = 0; + } + break; + } + case STATE_PHASH: + case STATE_M4PHASH: + { + const char *piece = find_attr("piece", atts); + if ( pd->state == STATE_PHASH && (!piece || str::strtonum(piece) != pd->piece.size()) ) + { + pd->popState(); + } + break; + } + default: + break; + } +} + +UByteArray hexstr2bytes( const std::string& str ) +{ + return Digest::hexStringToUByteArray( str ); +} + +static void XMLCALL +endElement(void *userData, const xmlChar *) +{ + struct ml_parsedata *pd = reinterpret_cast(userData); + //printf("end depth %d-%d name %s\n", pd->depth, pd->statedepth, name); + if (pd->depth != pd->statedepth) + { + pd->depth--; + return; + } + switch (pd->state) + { + case STATE_SIZE: + case STATE_M4SIZE: + pd->size = (off_t)str::strtonum(pd->content); //strtoull(pd->content, 0, 10); + break; + case STATE_HASH: + case STATE_M4HASH: + pd->chksum.clear(); + pd->chksum = hexstr2bytes( pd->content ); + if ( pd->content.length() != size_t(pd->chksuml) * 2 || !pd->chksum.size() ) + { + pd->chksum.clear(); + pd->chksuml = 0; + } + break; + case STATE_PHASH: + case STATE_M4PHASH: { + if ( pd->content.length() != size_t(pd->piecel) * 2 ) + break; + UByteArray pieceHash = hexstr2bytes( pd->content ); + if ( !pieceHash.size() ) + pieceHash.resize( pd->piecel, 0 ); + pd->piece.push_back( pieceHash ); + break; + } + case STATE_PIECES: + case STATE_M4PIECES: + if (pd->piecel == 4) + pd->zsync = pd->piece; + else + pd->sha1 = pd->piece; + + pd->piecel = 0; + pd->piece.clear(); + break; + case STATE_URL: + case STATE_M4URL: + if ( pd->content.length() ) + pd->urls.back().url = std::string(pd->content); + else + // without a actual URL the mirror is useless + pd->urls.pop_back(); + break; + default: + break; + } + + pd->depth--; + pd->popState(); + pd->docontent = 0; +} + +static void XMLCALL +characterData(void *userData, const xmlChar *s, int len) +{ + struct ml_parsedata *pd = reinterpret_cast(userData); + if (!pd->docontent) + return; + + if ( pd->content.length() + len + 1 > pd->content.capacity() ) + pd->content.reserve( pd->content.capacity() + 256 ); + pd->content.append( s, s+len ); +} + + +MetaLinkParser::MetaLinkParser() + : pd( new ml_parsedata ) +{} + +MetaLinkParser::~MetaLinkParser() +{ + delete pd; +} + +void +MetaLinkParser::parse(const Pathname &filename) +{ + parse(InputStream(filename)); +} + +void +MetaLinkParser::parse(const InputStream &is) +{ + char buf[4096]; + if (!is.stream()) + ZYPP_THROW(Exception("MetaLinkParser: no such file")); + while (is.stream().good()) + { + is.stream().read(buf, sizeof(buf)); + parseBytes(buf, is.stream().gcount()); + } + parseEnd(); + MIL << "Parsed " << pd->urls.size() << " mirrors from " << is.path() << std::endl; + if ( env::ZYPP_METALINK_DEBUG() ) { + for ( const auto &mirr : pd->urls ) + DBG << "- " << mirr.priority << " " << mirr.url << std::endl; + } +} + +void +MetaLinkParser::parseBytes(const char *buf, size_t len) +{ + if (!len) + return; + + if (xmlParseChunk(pd->parser, buf, len, 0)) { + ZYPP_THROW(Exception("Parse Error")); + } +} + +void +MetaLinkParser::parseEnd() +{ + if (xmlParseChunk(pd->parser, NULL, 0, 1)) { + ZYPP_THROW(Exception("Parse Error")); + } + if (pd->urls.size() ) { + stable_sort(pd->urls.begin(), pd->urls.end(), []( const auto &a, const auto &b ){ + return a.priority < b.priority; + }); + } +} + +std::vector +MetaLinkParser::getUrls() const +{ + std::vector urls; + urls.reserve(pd->urls.size()); + for ( const auto &mirr : pd->urls ) + urls.push_back( mirr.url ); + return urls; +} + +const std::vector &MetaLinkParser::getMirrors() const +{ + return pd->urls; +} + +MediaBlockList MetaLinkParser::getBlockList() const +{ + MediaBlockList bl(pd->size); + if (pd->chksuml == 20) + bl.setFileChecksum("SHA1", pd->chksuml, pd->chksum.data() ); + else if (pd->chksuml == 32) + bl.setFileChecksum("SHA256", pd->chksuml, pd->chksum.data()); + if (pd->size != off_t(-1) && pd->blksize) + { + size_t nb = (pd->size + pd->blksize - 1) / pd->blksize; + off_t off = 0; + size_t size = pd->blksize; + for ( size_t i = 0; i < nb; i++ ) + { + if (i == nb - 1) + { + size = pd->size % pd->blksize; + if (!size) + size = pd->blksize; + } + size_t blkno = bl.addBlock(off, size); + if ( i < pd->sha1.size()) + { + bl.setChecksum(blkno, "SHA1", 20, pd->sha1[i].data()); + if ( i < pd->zsync.size()) + { + unsigned char *p = pd->zsync[i].data(); + bl.setRsum(blkno, 4, p[0] | p[1] << 8 | p[2] << 16 | p[3] << 24, pd->blksize); + } + } + off += pd->blksize; + } + } + return bl; +} + +const std::vector &MetaLinkParser::getZsyncBlockHashes() const +{ + return pd->zsync; +} + +const std::vector &MetaLinkParser::getSHA1BlockHashes() const +{ + return pd->sha1; +} + +} // namespace zypp::media diff --git a/zypp-curl/parser/metalinkparser.h b/zypp-curl/parser/metalinkparser.h new file mode 100644 index 0000000..74b2e63 --- /dev/null +++ b/zypp-curl/parser/metalinkparser.h @@ -0,0 +1,88 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/parser/MetaLinkParser + * +*/ +#ifndef ZYPP_CURL_PARSER_METALINKPARSER_H_INCLUDED +#define ZYPP_CURL_PARSER_METALINKPARSER_H_INCLUDED + +#include + +#include +#include +#include +#include +#include +#include + +namespace zypp::media { + +struct ml_parsedata; + +struct MetalinkMirror { + int priority = 0; + int maxConnections = -1; //< How many connections can be opened to that mirror, -1 means no limit was defined. + Url url; +}; + +class MetaLinkParser : private zypp::base::NonCopyable { +public: + MetaLinkParser(); + ~MetaLinkParser(); + + /** + * parse a file consisting of metalink xml data + * \throws Exception + **/ + void parse(const Pathname &filename); + + /** + * parse an InputStream consisting of metalink xml data + * \throws Exception + **/ + void parse(const InputStream &is); + + /** + * parse a chunk of a file consisting of metalink xml data. + * \throws Exception + **/ + void parseBytes(const char* bytes, size_t len); + /** + * tells the parser that all chunks are now processed + * \throws Exception + **/ + void parseEnd(); + + /** + * return the download urls from the parsed metalink data + **/ + std::vector getUrls() const; + + /** + * return the mirrors from the parsed metalink data + */ + const std::vector &getMirrors() const; + + /** + * return the block list from the parsed metalink data + **/ + MediaBlockList getBlockList() const; + + const std::vector &getZsyncBlockHashes() const; + const std::vector &getSHA1BlockHashes() const; + +private: + struct ml_parsedata *pd; +}; + +UByteArray hexstr2bytes( const std::string& str ); + +} // namespace zypp::media + +#endif // ZYPP_CURL_PARSER_METALINKPARSER_H_INCLUDED diff --git a/zypp-curl/parser/zsyncparser.cc b/zypp-curl/parser/zsyncparser.cc new file mode 100644 index 0000000..3f72c8f --- /dev/null +++ b/zypp-curl/parser/zsyncparser.cc @@ -0,0 +1,203 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/ZsyncParser.cc + * + */ + +#include "zsyncparser.h" +#include + +#include +#include +#include +#include + +#include +#include +#include + +using std::endl; +using namespace zypp::base; + +namespace zypp::env +{ + /** Hack to circumvent the currently poor --root support. */ + inline bool ZYPP_METALINK_DEBUG() + { + static bool val = [](){ + const char * env = getenv("ZYPP_METALINK_DEBUG"); + return( env && zypp::str::strToBool( env, true ) ); + }(); + return val; + } +} + +namespace zypp { + namespace media { + +ZsyncParser::ZsyncParser() +{ + filesize = off_t(-1); + blksize = 0; + sql = rsl = csl = 0; +} + +static int +hexstr2bytes(unsigned char *buf, const char *str, int buflen) +{ + int i = 0; + for (i = 0; i < buflen; i++) + { +#define c2h(c) (((c)>='0' && (c)<='9') ? ((c)-'0') \ + : ((c)>='a' && (c)<='f') ? ((c)-('a'-10)) \ + : ((c)>='A' && (c)<='F') ? ((c)-('A'-10)) \ + : -1) + int v = c2h(*str); + str++; + if (v < 0) + return 0; + buf[i] = v; + v = c2h(*str); + str++; + if (v < 0) + return 0; + buf[i] = (buf[i] << 4) | v; +#undef c2h + } + return buflen; +} + +void +ZsyncParser::parse( const Pathname &filename ) +{ + char buf[4096]; + + std::ifstream is(filename.c_str()); + if (!is) + ZYPP_THROW(Exception("ZsyncParser: no such file")); + is.exceptions(std::ifstream::eofbit | std::ifstream::failbit | std::ifstream::badbit); + off_t filesize = off_t(-1); + while (is.good()) + { + is.getline(buf, sizeof(buf)); + if (!*buf) + break; + if (!strncmp(buf, "Length: ", 8)) + filesize = (off_t)strtoull(buf + 8, 0, 10); + else if (!strncmp(buf, "Hash-Lengths: ", 14)) + (void)sscanf(buf + 14, "%d,%d,%d", &sql, &rsl, &csl); + else if (!strncmp(buf, "Blocksize: ", 11)) + blksize = atoi(buf + 11); + else if (!strncmp(buf, "URL: http://", 12) || !strncmp(buf, "URL: https://", 13) || !strncmp(buf, "URL: ftp://", 11) || !strncmp(buf, "URL: tftp://", 12) ) + urls.push_back(buf + 5); + else if (!strncmp(buf, "SHA-1: ", 7)) + { + unsigned char sha1[20]; + if (hexstr2bytes(sha1, buf + 7, 20) == 20) + bl.setFileChecksum("SHA1", 20, sha1); + } + } + if (filesize == off_t(-1)) + ZYPP_THROW(Exception("Parse Error")); + if (blksize <= 0 || (blksize & (blksize - 1)) != 0) + ZYPP_THROW(Exception("Parse Error: illegal block size")); + bl.setFilesize(filesize); + + if (filesize) + { + if (csl < 3 || csl > 16 || rsl < 1 || rsl > 4 || sql < 1 || sql > 2) + ZYPP_THROW(Exception("Parse Error: illegal hash lengths")); + + bl.setRsumSequence( sql ); + + size_t nblks = (filesize + blksize - 1) / blksize; + size_t i = 0; + off_t off = 0; + size_t size = blksize; + for (i = 0; i < nblks; i++) + { + if (i == nblks - 1) + { + size = filesize % blksize; + if (!size) + size = blksize; + } + size_t blkno = bl.addBlock(off, size); + unsigned char rp[16]; + rp[0] = rp[1] = rp[2] = rp[3] = 0; + try { + is.read((char *)rp + 4 - rsl, rsl); + } catch ( const std::exception &e ) { + if ( !is.good() ) { + if (is.bad()) + throw zypp::Exception( "I/O error while reading" ); + else if (is.eof()) + throw zypp::Exception( "End of file reached unexpectedly" ); + else if (is.fail()) + throw zypp::Exception( "Non-integer data encountered" ); + else + throw zypp::Exception( "Unknown IO err" ); + } + } + + bl.setRsum(blkno, rsl, rp[0] << 24 | rp[1] << 16 | rp[2] << 8 | rp[3], blksize); + try { + is.read((char *)rp, csl); + } catch ( const std::exception &e ) { + if ( !is.good() ) { + if (is.bad()) + throw zypp::Exception( "I/O error while reading" ); + else if (is.eof()) + throw zypp::Exception( "End of file reached unexpectedly" ); + else if (is.fail()) + throw zypp::Exception( "Non-integer data encountered" ); + else + throw zypp::Exception( "Unknown IO err" ); + } + } + if ( !is.good() ) { + if (is.bad()) + throw zypp::Exception( "I/O error while reading" ); + else if (is.eof()) + throw zypp::Exception( "End of file reached unexpectedly" ); + else if (is.fail()) + throw zypp::Exception( "Non-integer data encountered" ); + else + throw zypp::Exception( "Unknown IO err" ); + } + bl.setChecksum(blkno, "MD4", csl, rp, blksize); + off += size; + } + } + is.close(); + MIL << "Parsed " << urls.size() << " mirrors from " << filename << std::endl; + if ( env::ZYPP_METALINK_DEBUG() ) { + for ( const auto &url : urls ) + DBG << "- " << url << std::endl; + } +} + +std::vector +ZsyncParser::getUrls() +{ + std::vector ret; + size_t i = 0; + for (i = 0; i < urls.size(); i++) + ret.push_back(Url(urls[i])); + return ret; +} + +MediaBlockList +ZsyncParser::getBlockList() +{ + return bl; +} + + } // namespace media +} // namespace zypp diff --git a/zypp-curl/parser/zsyncparser.h b/zypp-curl/parser/zsyncparser.h new file mode 100644 index 0000000..a5679f3 --- /dev/null +++ b/zypp-curl/parser/zsyncparser.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/parser/zsyncparser.h + * +*/ +#ifndef ZYPP_CURL_PARSER_ZSYNCPARSER_H +#define ZYPP_CURL_PARSER_ZSYNCPARSER_H + +#include + +#include +#include +#include +#include + +namespace zypp { + namespace media { + +class ZsyncParser : private zypp::base::NonCopyable { +public: + ZsyncParser(); + + /** + * parse a file consisting of zlink data + * \throws Exception + **/ + void parse( const Pathname &filename ); + /** + * return the download urls from the parsed metalink data + **/ + std::vector getUrls(); + /** + * return the block list from the parsed metalink data + **/ + MediaBlockList getBlockList(); + +private: + off_t filesize; + size_t blksize; + int sql; + int rsl; + int csl; + MediaBlockList bl; + std::vector urls; +}; + + } // namespace media +} // namespace zypp + +#endif // ZYPP_CURL_PARSER_ZSYNCPARSER_H diff --git a/zypp-curl/private/curlhelper_p.h b/zypp-curl/private/curlhelper_p.h new file mode 100644 index 0000000..53d316e --- /dev/null +++ b/zypp-curl/private/curlhelper_p.h @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_PRIVATE_CURLHELPER_P_H_INCLUDED +#define ZYPP_MEDIA_PRIVATE_CURLHELPER_P_H_INCLUDED + +#include +#include +#include + +#include + +#define EXPLICITLY_NO_PROXY "_none_" + +#undef CURLVERSION_AT_LEAST +#define CURLVERSION_AT_LEAST(M,N,O) LIBCURL_VERSION_NUM >= ((((M)<<8)+(N))<<8)+(O) + +using GPollFD = struct _GPollFD; + +namespace zypp +{ + namespace env + { + /** \c const long& for setting CURLOPT_DEBUGDATA + * Returns a reference to a static variable, so it's + * safe to pass it's address to CURLOPT_DEBUGDATA. + */ + const long & ZYPP_MEDIA_CURL_DEBUG(); + + /** 4/6 to force IPv4/v6 */ + int ZYPP_MEDIA_CURL_IPRESOLVE(); + } // namespace env +} //namespace zypp + +//do not export +namespace internal { + +void globalInitCurlOnce(); + +uint curlVersion(); + +/** Setup CURLOPT_VERBOSE and CURLOPT_DEBUGFUNCTION according to env::ZYPP_MEDIA_CURL_DEBUG. */ +void setupZYPP_MEDIA_CURL_DEBUG( CURL *curl ); +size_t log_redirects_curl( char *ptr, size_t size, size_t nmemb, void *userdata); + +void fillSettingsFromUrl( const zypp::Url &url, zypp::media::TransferSettings &s ); +void fillSettingsSystemProxy( const zypp::Url& url, zypp::media::TransferSettings &s ); + +void curlEscape( std::string & str_r, const char char_r, const std::string & escaped_r ); +std::string curlEscapedPath( std::string path_r ); +std::string curlUnEscape( const std::string& text_r ); + +zypp::Url clearQueryString(const zypp::Url &url); +zypp::Url propagateQueryParams( zypp::Url url_r, const zypp::Url & template_r ); + +CURLcode setCurlRedirProtocols(CURL *curl); + +/*! + * Helper class to simplify using the curl multi API, takes + * care of remembering the registered sockets and the required curl timeout. + */ +struct CurlPollHelper +{ + struct CurlPoll { + CURLM *_multi = nullptr; + }; + + CurlPollHelper( CurlPoll &p ); + ~CurlPollHelper(); + + /*! + * Iterator over the passed in poll fd's and call curl_multi_socket_action on them if one of + * them signals that events have happened + */ + CURLMcode handleSocketActions( const std::vector &actionsFds, int first = 0 ); + + /*! + * Tells libcurl that the requested timeout was reached. + */ + CURLMcode handleTimout (); + + /*! + * Callback for libcurl when it wants us to track or stop us from tracking a socket + */ + static int socketcb (CURL * easy, curl_socket_t s, int what, CurlPollHelper *userp, void *sockp ); + + /*! + * Callback for libcurl when it wants us to start/update/remove a timer + */ + static int timercb( CURLM *, long timeout_ms, CurlPollHelper *thatPtr ); + + CurlPoll &_parent; + std::vector socks; //< This is the list of fd's we need to track, events have been set by curl + std::optional timeout_ms = 0; //if set curl wants a timeout +}; + +} + +#endif //ZYPP_MEDIA_PRIVATE_CURLHELPER_P_H_INCLUDED diff --git a/zypp-curl/proxyinfo.cc b/zypp-curl/proxyinfo.cc new file mode 100644 index 0000000..66b4af8 --- /dev/null +++ b/zypp-curl/proxyinfo.cc @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/ProxyInfo.cc + * +*/ + +#include "proxyinfo.h" +#include +#include + +#include + +#include "proxyinfo/proxyinfoimpl.h" +#include "proxyinfo/proxyinfos.h" + +using namespace zypp::base; + +namespace zypp { + namespace media { + + shared_ptr ProxyInfo::Impl::_nullimpl; + + ProxyInfo::ProxyInfo() +#ifdef WITH_LIBPROXY_SUPPORT + : _pimpl( (ProxyInfoLibproxy::isAvailabe() ? static_cast(new ProxyInfoLibproxy()) : static_cast(new ProxyInfoSysconfig("proxy"))) ) +#else + : _pimpl( new ProxyInfoSysconfig("proxy") ) +#endif + {} + + ProxyInfo::ProxyInfo(ProxyInfo::ImplPtr pimpl_r) + : _pimpl(std::move(pimpl_r)) + {} + + bool ProxyInfo::enabled() const + { return _pimpl->enabled(); } + + std::string ProxyInfo::proxy(const Url & url_r) const + { return _pimpl->proxy(url_r); } + + ProxyInfo::NoProxyList ProxyInfo::noProxy() const + { return _pimpl->noProxy(); } + + ProxyInfo::NoProxyIterator ProxyInfo::noProxyBegin() const + { return _pimpl->noProxyBegin(); } + + ProxyInfo::NoProxyIterator ProxyInfo::noProxyEnd() const + { return _pimpl->noProxyEnd(); } + + bool ProxyInfo::useProxyFor( const Url & url_r ) const + { return _pimpl->useProxyFor( url_r ); } + + } // namespace media +} // namespace zypp diff --git a/zypp-curl/proxyinfo.h b/zypp-curl/proxyinfo.h new file mode 100644 index 0000000..485cafb --- /dev/null +++ b/zypp-curl/proxyinfo.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/ProxyInfo + * +*/ +#ifndef ZYPP_CURL_PROXYINFO_H_INCLUDED +#define ZYPP_CURL_PROXYINFO_H_INCLUDED + +#include +#include + +#include + +namespace zypp { + + class Url; + + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ProxyInfo + class ProxyInfo + { + public: + using Ptr = intrusive_ptr; + using constPtr = intrusive_ptr; + using NoProxyList = std::list; + using NoProxyIterator = std::list::const_iterator; + + /** Implementation */ + struct Impl; + using ImplPtr = shared_ptr; + + /** Default Ctor: guess the best available implementation. */ + ProxyInfo(); + /** Ctor taking a specific implementation. */ + ProxyInfo( ProxyInfo::ImplPtr pimpl_r ); + + bool enabled() const; + std::string proxy(const Url & url) const; + NoProxyList noProxy() const; + NoProxyIterator noProxyBegin() const; + NoProxyIterator noProxyEnd() const; + + /** Return \c true if \ref enabled and \a url_r does not match \ref noProxy. */ + bool useProxyFor( const Url & url_r ) const; + + private: + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_CURL_PROXYINFO_H_INCLUDED diff --git a/zypp-curl/proxyinfo/ProxyInfoLibproxy b/zypp-curl/proxyinfo/ProxyInfoLibproxy new file mode 100644 index 0000000..ce37f68 --- /dev/null +++ b/zypp-curl/proxyinfo/ProxyInfoLibproxy @@ -0,0 +1 @@ +#include "proxyinfolibproxy.h" diff --git a/zypp-curl/proxyinfo/ProxyInfoSysconfig b/zypp-curl/proxyinfo/ProxyInfoSysconfig new file mode 100644 index 0000000..3e75561 --- /dev/null +++ b/zypp-curl/proxyinfo/ProxyInfoSysconfig @@ -0,0 +1 @@ +#include "proxyinfosysconfig.h" diff --git a/zypp-curl/proxyinfo/proxyinfoimpl.h b/zypp-curl/proxyinfo/proxyinfoimpl.h new file mode 100644 index 0000000..9315150 --- /dev/null +++ b/zypp-curl/proxyinfo/proxyinfoimpl.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/proxyinfo/proxyinfoimpl.h + * +*/ +#ifndef ZYPP_CURL_PROXYINFO_PROXYINFOIMPL_H_INCLUDED +#define ZYPP_CURL_PROXYINFO_PROXYINFOIMPL_H_INCLUDED + +#include +#include + +#include +#include +#include + +namespace zypp { + namespace media { + + struct ProxyInfo::Impl + { + /** Ctor */ + Impl() + {} + + /** Dtor */ + virtual ~Impl() + {} + + public: + /** */ + virtual bool enabled() const = 0; + /** */ + virtual std::string proxy(const Url & url_r) const = 0; + /** */ + virtual ProxyInfo::NoProxyList noProxy() const = 0; + /** */ + virtual ProxyInfo::NoProxyIterator noProxyBegin() const = 0; + /** */ + virtual ProxyInfo::NoProxyIterator noProxyEnd() const = 0; + + /** Return \c true if \ref enabled and \a url_r does not match \ref noProxy. */ + bool useProxyFor( const Url & url_r ) const + { + if ( ! enabled() || proxy( url_r ).empty() ) + return false; + + ProxyInfo::NoProxyList noproxy( noProxy() ); + if ( noproxy.size() == 1 && noproxy.front() == "*" ) + return false; // just an asterisk disables all. + + // No proxy: Either an exact match, or the previous character + // is a '.', so host is within the same domain. + // A leading '.' in the pattern is ignored. Some implementations + // need '.foo.ba' to prevent 'foo.ba' from matching 'xfoo.ba'. + std::string host( str::toLower( url_r.getHost() ) ); + for_( it, noproxy.begin(), noproxy.end() ) + { + std::string pattern( str::toLower( (*it)[0] == '.' ? it->c_str() + 1 : it->c_str() ) ); + if ( str::hasSuffix( host, pattern ) + && ( host.size() == pattern.size() + || host[host.size()-pattern.size()-1] == '.' ) ) + return false; + } + return true; + } + + public: + /** Default Impl: empty sets. */ + static shared_ptr _nullimpl; + }; + + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_PROXYINFO_PROXYINFOIMPL_H diff --git a/zypp-curl/proxyinfo/proxyinfolibproxy.cc b/zypp-curl/proxyinfo/proxyinfolibproxy.cc new file mode 100644 index 0000000..0dbc478 --- /dev/null +++ b/zypp-curl/proxyinfo/proxyinfolibproxy.cc @@ -0,0 +1,214 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/proxyinfo/proxyinfolibproxy.cc + * +*/ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include // for dlload, dlsym, dlclose +#include // g_clear_pointer and g_strfreev + +using std::endl; +using namespace zypp::base; + +namespace zypp { + namespace media { + + namespace { + + using CreateFactoryCb = CreateFactorySig; + using DelFactoryCb = DelFactorySig; + using GetProxiesCb = GetProxiesSig; + + struct LibProxyAPI + { + zypp::AutoDispose libProxyLibHandle; + CreateFactoryCb createProxyFactory = nullptr; + DelFactoryCb deleteProxyFactory = nullptr; + GetProxiesCb getProxies = nullptr; + FreeProxiesCb freeProxies = nullptr; + + /*! + * \internal + * Older versions of libproxy do not have a callback to free the proxy list, + * so we provide one. + */ + static void fallbackFreeProxies( char **proxies ) { + g_clear_pointer (&proxies, g_strfreev); + } + + static std::unique_ptr create() { + MIL << "Detecting libproxy availability" << std::endl; + zypp::AutoDispose handle( dlopen("libproxy.so.1", RTLD_LAZY ), []( void *ptr ){ if ( ptr ) ::dlclose(ptr); }); + if ( !handle ) { + MIL << "No libproxy support detected (could not load library): " << dlerror() << std::endl; + return nullptr; + } + + std::unique_ptr apiInstance = std::make_unique(); + apiInstance->libProxyLibHandle = std::move(handle); + apiInstance->createProxyFactory = (CreateFactoryCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_new" ); + if ( !apiInstance->createProxyFactory ){ + ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_new): " << dlerror() << std::endl; + return nullptr; + } + apiInstance->deleteProxyFactory = (DelFactoryCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_free" ); + if ( !apiInstance->deleteProxyFactory ){ + ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_free): " << dlerror() << std::endl; + return nullptr; + } + apiInstance->getProxies = (GetProxiesCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_get_proxies" ); + if ( !apiInstance->getProxies ){ + ERR << "Incompatible libproxy detected (could not resolve px_proxy_factory_get_proxies): " << dlerror() << std::endl; + return nullptr; + } + apiInstance->freeProxies = (FreeProxiesCb)::dlsym ( apiInstance->libProxyLibHandle, "px_proxy_factory_free_proxies" ); + if ( !apiInstance->freeProxies ){ + MIL << "Older version of libproxy detected, using fallback function to free the proxy list (could not resolve px_proxy_factory_free_proxies): " << dlerror() << std::endl; + apiInstance->freeProxies = &fallbackFreeProxies; + } + + MIL << "Libproxy is available" << std::endl; + return apiInstance; + } + }; + + LibProxyAPI *proxyApi() { + static std::unique_ptr api = LibProxyAPI::create(); + return api.get(); + } + + LibProxyAPI &assertProxyApi() { + auto api = proxyApi(); + if ( !api ) + ZYPP_THROW( zypp::Exception("LibProxyAPI is not available.") ); + return *api; + } + } + + struct TmpUnsetEnv + { + TmpUnsetEnv(const char *var_r) : _set(false), _var(var_r) { + const char * val = getenv( _var.c_str() ); + if ( val ) + { + _set = true; + _val = val; + ::unsetenv( _var.c_str() ); + } + } + + TmpUnsetEnv(const TmpUnsetEnv &) = delete; + TmpUnsetEnv(TmpUnsetEnv &&) = delete; + TmpUnsetEnv &operator=(const TmpUnsetEnv &) = delete; + TmpUnsetEnv &operator=(TmpUnsetEnv &&) = delete; + + ~TmpUnsetEnv() + { + if ( _set ) + { + setenv( _var.c_str(), _val.c_str(), 1 ); + } + } + + bool _set; + std::string _var; + std::string _val; + }; + + static pxProxyFactoryType * getProxyFactory() + { + static pxProxyFactoryType * proxyFactory = 0; + + // Force libproxy into using "/etc/sysconfig/proxy" + // if it exists. + static WatchFile sysconfigProxy( "/etc/sysconfig/proxy", WatchFile::NO_INIT ); + if ( sysconfigProxy.hasChanged() ) + { + MIL << "Build Libproxy Factory from /etc/sysconfig/proxy" << endl; + if ( proxyFactory ) + assertProxyApi().deleteProxyFactory( proxyFactory ); + + TmpUnsetEnv envguard[] __attribute__ ((__unused__)) = { "KDE_FULL_SESSION", "GNOME_DESKTOP_SESSION_ID", "DESKTOP_SESSION" }; + proxyFactory = assertProxyApi().createProxyFactory(); + } + else if ( ! proxyFactory ) + { + MIL << "Build Libproxy Factory" << endl; + proxyFactory = assertProxyApi().createProxyFactory(); + } + + return proxyFactory; + } + + ProxyInfoLibproxy::ProxyInfoLibproxy() + : ProxyInfo::Impl() + , _factory( getProxyFactory()) + { + _enabled = !(_factory == NULL); + } + + ProxyInfoLibproxy::~ProxyInfoLibproxy() + {} + + bool ProxyInfoLibproxy::isAvailabe() + { + return ( proxyApi () != nullptr ); + } + + std::string ProxyInfoLibproxy::proxy(const Url & url_r) const + { + if (!_enabled) + return ""; + + const url::ViewOption vopt = + url::ViewOption::WITH_SCHEME + + url::ViewOption::WITH_HOST + + url::ViewOption::WITH_PORT + + url::ViewOption::WITH_PATH_NAME; + + auto &api = assertProxyApi (); + + zypp::AutoDispose proxies( + api.getProxies(_factory, (char *)url_r.asString(vopt).c_str()) + , api.freeProxies + ); + if ( !proxies.value() ) + return ""; + + /* cURL can only handle HTTP proxies, not SOCKS. And can only handle + one. So look through the list and find an appropriate one. */ + std::optional result; + for (int i = 0; proxies[i]; i++) { + if ( !result && !strncmp(proxies[i], "http://", 7) ) { + result = str::asString( proxies[i] ); + } + } + + return result.value_or( "" ); + } + + ProxyInfo::NoProxyIterator ProxyInfoLibproxy::noProxyBegin() const + { return _no_proxy.begin(); } + + ProxyInfo::NoProxyIterator ProxyInfoLibproxy::noProxyEnd() const + { return _no_proxy.end(); } + + } // namespace media +} // namespace zypp diff --git a/zypp-curl/proxyinfo/proxyinfolibproxy.h b/zypp-curl/proxyinfo/proxyinfolibproxy.h new file mode 100644 index 0000000..13a23ab --- /dev/null +++ b/zypp-curl/proxyinfo/proxyinfolibproxy.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/proxyinfo/ProxyInfoLibproxy.h + * +*/ +#ifndef ZYPP_MEDIA_PROXYINFO_PROXYINFOLIBPROXY_H +#define ZYPP_MEDIA_PROXYINFO_PROXYINFOLIBPROXY_H + +#include + +#include +#include +#include + +extern "C" { + typedef struct _pxProxyFactory pxProxyFactoryType; +} + +namespace zypp { + namespace media { + + template + using CreateFactorySig = ProxyFactoryType *(*) (void); + + template + using DelFactorySig = void (*) (ProxyFactoryType *self); + + template + using GetProxiesSig = char **(*) (ProxyFactoryType *self, const char *url); + + using FreeProxiesCb = void (*) (char **proxies); + + class ProxyInfoLibproxy : public ProxyInfo::Impl + { + public: + ProxyInfoLibproxy(); + /** */ + ~ProxyInfoLibproxy() override; + + static bool isAvailabe(); + + /** */ + bool enabled() const override + { return _enabled; } + /** */ + std::string proxy(const Url & url_r) const override; + /** */ + ProxyInfo::NoProxyList noProxy() const override + { return _no_proxy; } + /** */ + ProxyInfo::NoProxyIterator noProxyBegin() const override; + /** */ + ProxyInfo::NoProxyIterator noProxyEnd() const override; + private: + DefaultIntegral _enabled; + ProxyInfo::NoProxyList _no_proxy; + pxProxyFactoryType *_factory; + }; + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_PROXYINFO_PROXYINFOLIBPROXY_H diff --git a/zypp-curl/proxyinfo/proxyinfos.h b/zypp-curl/proxyinfo/proxyinfos.h new file mode 100644 index 0000000..0ef455a --- /dev/null +++ b/zypp-curl/proxyinfo/proxyinfos.h @@ -0,0 +1,23 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/proxyinfo/proxyinfos.h + * +*/ +#ifndef ZYPP_CURL_PROXYINFO_PROXYINFOS_H_INCLUDED +#define ZYPP_CURL_PROXYINFO_PROXYINFOS_H_INCLUDED + +#include +#include + +#include +#ifdef WITH_LIBPROXY_SUPPORT +#include +#endif + +#endif // ZYPP_CURL_PROXYINFO_PROXYINFOS_H_INCLUDED diff --git a/zypp-curl/proxyinfo/proxyinfosysconfig.cc b/zypp-curl/proxyinfo/proxyinfosysconfig.cc new file mode 100644 index 0000000..deb59ca --- /dev/null +++ b/zypp-curl/proxyinfo/proxyinfosysconfig.cc @@ -0,0 +1,67 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/proxyinfo/ProxyInfoSysconfig.cc + * +*/ + +#include "proxyinfosysconfig.h" + +#include +#include + +#include +#include +#include + + +using namespace zypp::base; + +namespace zypp { + namespace media { + + ProxyInfoSysconfig::ProxyInfoSysconfig(const Pathname & path) + : ProxyInfo::Impl() + { + std::map data = sysconfig::read( + path.relative() + ? "/etc/sysconfig" + path + : path); + std::map::const_iterator it = data.find("PROXY_ENABLED"); + if (it != data.end()) + _enabled = it->second != "no"; + it = data.find("HTTP_PROXY"); + if (it != data.end()) + _proxies["http"] = it->second; + it = data.find("HTTPS_PROXY"); + if (it != data.end()) + _proxies["https"] = it->second; + it = data.find("FTP_PROXY"); + if (it != data.end()) + _proxies["ftp"] = it->second; + it = data.find("NO_PROXY"); + if (it != data.end()) + str::split(it->second, std::back_inserter(_no_proxy), ", \t"); + } + + std::string ProxyInfoSysconfig::proxy(const Url & url_r) const + { + std::map::const_iterator it = _proxies.find(url_r.getScheme()); + if (it != _proxies.end()) + return it->second; + return ""; + } + + ProxyInfo::NoProxyIterator ProxyInfoSysconfig::noProxyBegin() const + { return _no_proxy.begin(); } + + ProxyInfo::NoProxyIterator ProxyInfoSysconfig::noProxyEnd() const + { return _no_proxy.end(); } + + } // namespace media +} // namespace zypp diff --git a/zypp-curl/proxyinfo/proxyinfosysconfig.h b/zypp-curl/proxyinfo/proxyinfosysconfig.h new file mode 100644 index 0000000..b7889d9 --- /dev/null +++ b/zypp-curl/proxyinfo/proxyinfosysconfig.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/proxyinfo/ProxyInfoSysconfig + * +*/ +#ifndef ZYPP_CURL_PROXYINFO_PROXYINFOSYSCONFIG_H_INCLUDED +#define ZYPP_CURL_PROXYINFO_PROXYINFOSYSCONFIG_H_INCLUDED + +#include +#include + +#include +#include +#include +#include + +namespace zypp { + namespace media { + + + class ProxyInfoSysconfig : public ProxyInfo::Impl + { + public: + ProxyInfoSysconfig(const Pathname & path); + /** */ + bool enabled() const override + { return _enabled; } + /** */ + std::string proxy(const Url & url_r) const override; + /** */ + ProxyInfo::NoProxyList noProxy() const override + { return _no_proxy; } + /** */ + ProxyInfo::NoProxyIterator noProxyBegin() const override; + /** */ + ProxyInfo::NoProxyIterator noProxyEnd() const override; + private: + DefaultIntegral _enabled; + ProxyInfo::NoProxyList _no_proxy; + std::map _proxies; + }; + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_CURL_PROXYINFO_PROXYINFOSYSCONFIG_H_INCLUDED diff --git a/zypp-curl/transfersettings.cc b/zypp-curl/transfersettings.cc new file mode 100644 index 0000000..ad10640 --- /dev/null +++ b/zypp-curl/transfersettings.cc @@ -0,0 +1,321 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/transfersettings.cc + * +*/ + +#include "transfersettings.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +using std::endl; + +#define CURL_BINARY "/usr/bin/curl" + +namespace zypp +{ + namespace media + { + class TransferSettings::Impl + { + public: + Impl() : _useproxy( false ), + _timeout( MediaConfig::instance().download_transfer_timeout() ), + _connect_timeout( MediaConfig::instance().download_connect_timeout() ), + _maxConcurrentConnections( MediaConfig::instance().download_max_concurrent_connections() ), + _minDownloadSpeed(MediaConfig::instance().download_min_download_speed()), + _maxDownloadSpeed(MediaConfig::instance().download_max_download_speed()), + _maxSilentTries(MediaConfig::instance().download_max_silent_tries() ), + _verify_host(false), + _verify_peer(false), + _ca_path("/etc/ssl/certs"), + _head_requests_allowed(true) + {} + + Impl(const Impl &) = default; + Impl(Impl &&) = default; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + virtual ~Impl() {} + + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + + public: + void safeAddHeader( std::string val_r ) { + // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space. + // Trim and discard empty header. + val_r = str::trim( std::move(val_r) ); + if ( not val_r.empty() ) + _headers.push_back( std::move(val_r) ); + else + WAR << "Discard empty header" << endl; + } + + public: + std::vector _headers; + std::string _useragent; + std::string _username; + std::string _password; + bool _useproxy; + std::string _proxy; + std::string _proxy_username; + std::string _proxy_password; + std::string _authtype; + long _timeout; + long _connect_timeout; + Url _url; + Pathname _targetdir; + + long _maxConcurrentConnections; + long _minDownloadSpeed; + long _maxDownloadSpeed; + long _maxSilentTries; + + bool _verify_host; + bool _verify_peer; + Pathname _ca_path; + Pathname _client_cert_path; + Pathname _client_key_path; + + // workarounds + bool _head_requests_allowed; + }; + + TransferSettings::TransferSettings() + : _impl(new TransferSettings::Impl()) + {} + + void TransferSettings::reset() + { _impl.reset(new TransferSettings::Impl()); } + + + void TransferSettings::addHeader( const std::string & val_r ) + { _impl->safeAddHeader( val_r ); } + void TransferSettings::addHeader( std::string && val_r ) + { _impl->safeAddHeader( std::move(val_r) ); } + + const TransferSettings::Headers &TransferSettings::headers() const + { + //@TODO check if we could use a vector of std::string_view here + return _impl->_headers; + } + + void TransferSettings::setUserAgentString( const std::string &val_r ) + { _impl->_useragent = str::trim( val_r ); } // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space + + void TransferSettings::setUserAgentString( std::string && val_r ) + { _impl->_useragent = str::trim( std::move(val_r) ); } // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space + + const std::string &TransferSettings::userAgentString() const + { return _impl->_useragent; } + + + void TransferSettings::setUsername( const std::string &val_r ) + { _impl->_username = val_r; } + + void TransferSettings::setUsername( std::string && val_r ) + { _impl->_username = std::move(val_r); } + + const std::string &TransferSettings::username() const + { return _impl->_username; } + + void TransferSettings::setPassword( const std::string & val_r ) + { _impl->_password = val_r; } + + void TransferSettings::setPassword( std::string && val_r ) + { _impl->_password = std::move(val_r); } + + const std::string &TransferSettings::password() const + { return _impl->_password; } + + std::string TransferSettings::userPassword() const + { + std::string userpwd = username(); + if ( password().size() ) { + userpwd += ":" + password(); + } + return userpwd; + } + + void TransferSettings::setAnonymousAuth() + { + setUsername("anonymous"); + setPassword("yast@" LIBZYPP_VERSION_STRING); + } + + + void TransferSettings::setProxyEnabled( bool enabled ) + { _impl->_useproxy = enabled; } + + bool TransferSettings::proxyEnabled() const + { return _impl->_useproxy; } + + + void TransferSettings::setProxy( const std::string &val_r ) + { _impl->_proxy = val_r; } + + void TransferSettings::setProxy( std::string && val_r ) + { _impl->_proxy = std::move(val_r); } + + const std::string &TransferSettings::proxy() const + { return _impl->_proxy; } + + + void TransferSettings::setProxyUsername( const std::string &val_r ) + { _impl->_proxy_username = val_r; } + + void TransferSettings::setProxyUsername( std::string && val_r ) + { _impl->_proxy_username = std::move(val_r); } + + const std::string &TransferSettings::proxyUsername() const + { return _impl->_proxy_username; } + + void TransferSettings::setProxyPassword( const std::string &val_r ) + { _impl->_proxy_password = val_r; } + + void TransferSettings::setProxyPassword( std::string && val_r ) + { _impl->_proxy_password = std::move(val_r); } + + const std::string &TransferSettings::proxyPassword() const + { return _impl->_proxy_password; } + + std::string TransferSettings::proxyUserPassword() const + { + std::string userpwd = proxyUsername(); + if ( proxyPassword().size() ) { + userpwd += ":" + proxyPassword(); + } + return userpwd; + } + + + void TransferSettings::setTimeout( long t ) + { _impl->_timeout = (t); } + + long TransferSettings::timeout() const + { return _impl->_timeout; } + + + void TransferSettings::setConnectTimeout( long t ) + { _impl->_connect_timeout = (t); } + + long TransferSettings::connectTimeout() const + { return _impl->_connect_timeout; } + + + void TransferSettings::setMaxConcurrentConnections( long v ) + { _impl->_maxConcurrentConnections = (v); } + + long TransferSettings::maxConcurrentConnections() const + { return _impl->_maxConcurrentConnections; } + + + void TransferSettings::setMinDownloadSpeed( long v ) + { _impl->_minDownloadSpeed = (v); } + + long TransferSettings::minDownloadSpeed() const + { return _impl->_minDownloadSpeed; } + + + void TransferSettings::setMaxDownloadSpeed( long v ) + { _impl->_maxDownloadSpeed = (v); } + + long TransferSettings::maxDownloadSpeed() const + { return _impl->_maxDownloadSpeed; } + + + void TransferSettings::setMaxSilentTries( long v ) + { _impl->_maxSilentTries = (v); } + + long TransferSettings::maxSilentTries() const + { return _impl->_maxSilentTries; } + + + void TransferSettings::setVerifyHostEnabled( bool enabled ) + { _impl->_verify_host = (enabled); } + + bool TransferSettings::verifyHostEnabled() const + { return _impl->_verify_host; } + + + void TransferSettings::setVerifyPeerEnabled( bool enabled ) + { _impl->_verify_peer = enabled; } + + bool TransferSettings::verifyPeerEnabled() const + { return _impl->_verify_peer; } + + void TransferSettings::setClientCertificatePath( const Pathname &val_r ) + { _impl->_client_cert_path = val_r; } + + void TransferSettings::setClientCertificatePath( Pathname && val_r ) + { _impl->_client_cert_path = std::move( val_r ); } + + const Pathname &TransferSettings::clientCertificatePath() const + { return _impl->_client_cert_path; } + + + void TransferSettings::setClientKeyPath( const Pathname &val_r ) + { _impl->_client_key_path = val_r; } + + void TransferSettings::setClientKeyPath( Pathname && val_r ) + { _impl->_client_key_path = std::move( val_r ); } + + const Pathname &TransferSettings::clientKeyPath() const + { return _impl->_client_key_path; } + + + void TransferSettings::setCertificateAuthoritiesPath( const Pathname &val_r ) + { _impl->_ca_path = val_r; } + + void TransferSettings::setCertificateAuthoritiesPath( Pathname && val_r ) + { _impl->_ca_path = std::move(val_r); } + + const Pathname &TransferSettings::certificateAuthoritiesPath() const + { return _impl->_ca_path; } + + + void TransferSettings::setAuthType( const std::string &val_r ) + { _impl->_authtype = val_r; } + + void TransferSettings::setAuthType( std::string && val_r ) + { _impl->_authtype = std::move(val_r); } + + const std::string &TransferSettings::authType() const + { return _impl->_authtype; } + + + void TransferSettings::setHeadRequestsAllowed( bool allowed ) + { _impl->_head_requests_allowed = allowed; } + + bool TransferSettings::headRequestsAllowed() const + { return _impl->_head_requests_allowed; } + + } // namespace media +} // namespace zypp diff --git a/zypp-curl/transfersettings.h b/zypp-curl/transfersettings.h new file mode 100644 index 0000000..d1fb200 --- /dev/null +++ b/zypp-curl/transfersettings.h @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-curl/TransferSettings + * + */ +#ifndef ZYPP_CURL_TRANSFER_SETTINGS_H_INCLUDED +#define ZYPP_CURL_TRANSFER_SETTINGS_H_INCLUDED + +#include +#include +#include +#include +#include +#include +namespace zypp +{ + namespace media + { + + /////////////////////////////////////////////////////////////////// + /// \brief Holds transfer setting + /// + /// \note bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a + /// space. The class asserts \ref headers and \ref userAgentString + /// return trimmed strings. Strings are trimmed when set. Empty + // strings are discarded. + class TransferSettings + { + public: + /** Constructs a transfer program cmd line access. */ + TransferSettings(); + + using Headers = std::vector; + + /** reset the settings to the defaults */ + void reset(); + + /** add a header, on the form "Foo: Bar" (trims)*/ + void addHeader( std::string && val_r ); + void addHeader( const std::string & val_r ); + + /** returns a list of all added headers (trimmed) */ + const Headers &headers() const; + + /** sets the user agent ie: "Mozilla v3" (trims) */ + void setUserAgentString( std::string && val_r ); + void setUserAgentString( const std::string &val_r ); + + /** user agent string (trimmed)*/ + const std::string &userAgentString() const; + + + /** sets the auth username */ + void setUsername( const std::string &val_r ); + void setUsername( std::string && val_r ); + + /** auth username */ + const std::string &username() const; + + /** sets the auth password */ + void setPassword( const std::string & val_r ); + void setPassword( std::string && val_r ); + + /** auth password */ + const std::string &password() const; + + /** returns the user and password as a user:pass string */ + std::string userPassword() const; + + /** sets anonymous authentication (ie: for ftp) */ + void setAnonymousAuth(); + + + /** whether the proxy is used or not */ + void setProxyEnabled( bool enabled ); + + /** proxy is enabled */ + bool proxyEnabled() const; + + + /** proxy to use if it is enabled */ + void setProxy( const std::string &val_r ); + void setProxy( std::string && val_r ); + + /** proxy host */ + const std::string &proxy() const; + + + /** sets the proxy user */ + void setProxyUsername( const std::string &val_r ); + void setProxyUsername( std::string && val_r ); + + /** proxy auth username */ + const std::string &proxyUsername() const; + + /** sets the proxy password */ + void setProxyPassword( const std::string &val_r ); + void setProxyPassword( std::string && val_r ); + + /** proxy auth password */ + const std::string &proxyPassword() const; + + /** returns the proxy user and password as a user:pass string */ + std::string proxyUserPassword() const; + + + /** set the connect timeout */ + void setConnectTimeout( long t ); + + /** connection timeout */ + long connectTimeout() const; + + + /** set the transfer timeout */ + void setTimeout( long t ); + + /** transfer timeout */ + long timeout() const; + + + /** Set maximum number of concurrent connections for a single transfer */ + void setMaxConcurrentConnections(long v); + + /** Maximum number of concurrent connections for a single transfer */ + long maxConcurrentConnections() const; + + + /** Set minimum download speed (bytes per second) until the connection is dropped */ + void setMinDownloadSpeed(long v); + + /** Minimum download speed (bytes per second) until the connection is dropped */ + long minDownloadSpeed() const; + + + /** Set max download speed (bytes per second) */ + void setMaxDownloadSpeed(long v); + + /** Maximum download speed (bytes per second) */ + long maxDownloadSpeed() const; + + + /** Set maximum silent retries */ + void setMaxSilentTries(long v); + + /** Maximum silent retries */ + long maxSilentTries() const; + + + /** Sets whether to verify host for ssl */ + void setVerifyHostEnabled( bool enabled ); + + /** Whether to verify host for ssl */ + bool verifyHostEnabled() const; + + + /** Sets whether to verify host for ssl */ + void setVerifyPeerEnabled( bool enabled ); + + /** Whether to verify peer for ssl */ + bool verifyPeerEnabled() const; + + + /** Sets the SSL certificate authorities path */ + void setCertificateAuthoritiesPath( const Pathname &val_r ); + void setCertificateAuthoritiesPath( Pathname && val_r ); + + /** SSL certificate authorities path ( default: /etc/ssl/certs ) */ + const Pathname &certificateAuthoritiesPath() const; + + + /** set the allowed authentication types */ + void setAuthType( const std::string &val_r ); + void setAuthType( std::string && val_r ); + + /** get the allowed authentication types */ + const std::string &authType() const; + + + /** set whether HEAD requests are allowed */ + void setHeadRequestsAllowed(bool allowed); + + /** whether HEAD requests are allowed */ + bool headRequestsAllowed() const; + + + /** Sets the SSL client certificate file */ + void setClientCertificatePath( const Pathname &val_r ); + void setClientCertificatePath( Pathname && val_r ); + + /** SSL client certificate file */ + const Pathname &clientCertificatePath() const; + + + /** Sets the SSL client key file */ + void setClientKeyPath( const Pathname &val_r ); + void setClientKeyPath( Pathname && val_r ); + + /** SSL client key file */ + const Pathname &clientKeyPath() const; + + protected: + class Impl; + RWCOW_pointer _impl; + }; + + } // namespace media +} // namespece zypp + +#endif // ZYPP_CURL_TRANSFER_SETTINGS_H_INCLUDED diff --git a/zypp-history.lr b/zypp-history.lr new file mode 100644 index 0000000..86002d8 --- /dev/null +++ b/zypp-history.lr @@ -0,0 +1,11 @@ +/var/log/zypp/history { + compress + dateext + notifempty + missingok + nocreate + + maxage 1827 + rotate 99 + size 10M +} diff --git a/zypp-media/CDTools b/zypp-media/CDTools new file mode 100644 index 0000000..82702a8 --- /dev/null +++ b/zypp-media/CDTools @@ -0,0 +1 @@ +#include "cdtools.h" diff --git a/zypp-media/CMakeLists.txt b/zypp-media/CMakeLists.txt new file mode 100644 index 0000000..0b25633 --- /dev/null +++ b/zypp-media/CMakeLists.txt @@ -0,0 +1,142 @@ +# Collect all files that may contain translatable texts +FILE( GLOB_RECURSE POT_FILE_DEPENDS RELATIVE ${LIBZYPP_SOURCE_DIR} "*.h" "*.cc" ) +SET( POT_FILE_DEPENDS_ZYPP_MEDIA ${POT_FILE_DEPENDS} PARENT_SCOPE ) + +INCLUDE_DIRECTORIES ( ${LIBZYPP_SOURCE_DIR} ) + +ADD_DEFINITIONS( -DLOCALEDIR="${CMAKE_INSTALL_PREFIX}/share/locale" -DTEXTDOMAIN="zypp" -DZYPP_DLL ) + +SET( zypp_media_HEADERS + CDTools + cdtools.h + FileCheckException + filecheckexception.h + MediaConfig + mediaconfig.h + mediaexception.h + MediaException + mount.h + Mount +) + +SET( zypp_media_private_HEADERS +) + +SET( zypp_media_SRCS + cdtools.cc + filecheckexception.cc + mediaconfig.cc + mediaexception.cc + mount.cc +) + +INSTALL( FILES ${zypp_media_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-media" ) + +SET( zypp_media_auth_HEADERS + auth/AuthData + auth/authdata.h + auth/CredentialFileReader + auth/credentialfilereader.h + auth/CredentialManager + auth/credentialmanager.h +) + +SET( zypp_media_auth_private_HEADERS +) + +SET( zypp_media_auth_SRCS + auth/authdata.cc + auth/credentialfilereader.cc + auth/credentialmanager.cc +) + +INSTALL( FILES ${zypp_media_auth_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-media/auth" ) + +SET( zypp_media_ng_HEADERS + ng/headervaluemap.h + ng/HeaderValueMap + ng/lazymediahandle.h + ng/LazyMediaHandle + ng/provide.h + ng/Provide + ng/providefwd.h + ng/ProvideFwd + ng/provide-configvars.h + ng/providespec.h + ng/ProvideSpec + ng/provideres.h + ng/provideitem.h + ng/ProvideRes + ng/mediaverifier.h + ng/MediaVerifier + ng/worker/devicedriver.h + ng/worker/DeviceDriver + ng/worker/provideworker.h + ng/worker/ProvideWorker + ng/worker/mountingworker.h + ng/worker/MountingWorker +) + +SET( zypp_media_ng_private_HEADERS + ng/private/attachedmediainfo_p.h + ng/private/provide_p.h + ng/private/providefwd_p.h + ng/private/provideitem_p.h + ng/private/providemessage_p.h + ng/private/providequeue_p.h + ng/private/provideres_p.h + ng/private/providedbg_p.h +) + +SET( zypp_media_ng_SRCS + ng/attachedmediainfo.cc + ng/headervaluemap.cc + ng/provide.cc + ng/provideres.cc + ng/providespec.cc + ng/provideitem.cc + ng/providemessage.cc + ng/providequeue.cc + ng/mediaverifier.cc + ng/worker/devicedriver.cc + ng/worker/provideworker.cc + ng/worker/mountingworker.cc +) + +INSTALL( FILES ${zypp_media_ng_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-media/ng" ) + + +SET( zypp_media_lib_SRCS + ${zypp_media_SRCS} + ${zypp_media_auth_SRCS} + ${zypp_media_ng_SRCS} +) +SET( zypp_media_lib_HEADERS + ${zypp_media_private_HEADERS} ${zypp_media_HEADERS} + ${zypp_media_auth_private_HEADERS} ${zypp_media_auth_HEADERS} + ${zypp_media_ng_private_HEADERS} ${zypp_media_ng_HEADERS} +) + +# Default loggroup for all files +SET_LOGGROUP( "zypp-media" ${zypp_media_lib_SRCS} ) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + + set_source_files_properties( + ng/providemessage.cc + PROPERTIES + SKIP_LINTING ON + ) + + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set( CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK} ) + endif(ZYPP_CXX_CPPCHECK) + +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +ADD_LIBRARY( zypp-media STATIC ${zypp_media_lib_SRCS} ${zypp_media_lib_HEADERS} ) +target_link_libraries( zypp-media PRIVATE zypp_lib_compiler_flags ) diff --git a/zypp-media/FileCheckException b/zypp-media/FileCheckException new file mode 100644 index 0000000..c67d2c3 --- /dev/null +++ b/zypp-media/FileCheckException @@ -0,0 +1 @@ +#include "filecheckexception.h" diff --git a/zypp-media/MediaConfig b/zypp-media/MediaConfig new file mode 100644 index 0000000..9d38d63 --- /dev/null +++ b/zypp-media/MediaConfig @@ -0,0 +1 @@ +#include "mediaconfig.h" diff --git a/zypp-media/MediaException b/zypp-media/MediaException new file mode 100644 index 0000000..8144aa6 --- /dev/null +++ b/zypp-media/MediaException @@ -0,0 +1 @@ +#include "mediaexception.h" diff --git a/zypp-media/Mount b/zypp-media/Mount new file mode 100644 index 0000000..584dfa7 --- /dev/null +++ b/zypp-media/Mount @@ -0,0 +1 @@ +#include "mount.h" diff --git a/zypp-media/auth/AuthData b/zypp-media/auth/AuthData new file mode 100644 index 0000000..30f2bac --- /dev/null +++ b/zypp-media/auth/AuthData @@ -0,0 +1 @@ +#include "authdata.h" diff --git a/zypp-media/auth/CredentialFileReader b/zypp-media/auth/CredentialFileReader new file mode 100644 index 0000000..a89049c --- /dev/null +++ b/zypp-media/auth/CredentialFileReader @@ -0,0 +1 @@ +#include "credentialfilereader.h" diff --git a/zypp-media/auth/CredentialManager b/zypp-media/auth/CredentialManager new file mode 100644 index 0000000..334f711 --- /dev/null +++ b/zypp-media/auth/CredentialManager @@ -0,0 +1 @@ +#include "credentialmanager.h" diff --git a/zypp-media/auth/authdata.cc b/zypp-media/auth/authdata.cc new file mode 100644 index 0000000..8ae4fab --- /dev/null +++ b/zypp-media/auth/authdata.cc @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/auth/authdata.cc + * + */ + +#include "authdata.h" +#include + +using std::endl; + +namespace zypp { + namespace media { + + +AuthData::AuthData(const Url & url) + : _url(url), _lastChange(0) +{ + _username = url.getUsername(); + _password = url.getPassword(); +} + + +bool AuthData::valid() const +{ + return username().size() && password().size(); +} + +time_t AuthData::lastDatabaseUpdate() const +{ + return _lastChange; +} + +void AuthData::setLastDatabaseUpdate( time_t time ) +{ + _lastChange = time; +} + +const std::map &AuthData::extraValues() const +{ + return _extraValues; +} + +std::map &AuthData::extraValues() +{ + return _extraValues; +} + +std::ostream & AuthData::dumpOn( std::ostream & str ) const +{ + if (_url.isValid()) + str << "[" << _url.asString( url::ViewOptions() - url::ViewOptions::WITH_USERNAME - url::ViewOptions::WITH_PASSWORD ) << "]" << endl; + else + str << "[]" << endl; + str << "username: '" << _username << "'" << std::endl + << "password: " << (_password.empty() ? "" : ""); + return str; +} + +std::ostream & AuthData::dumpAsIniOn( std::ostream & str ) const +{ + if (_url.isValid()) + str + << "[" << _url.asString( + url::ViewOptions() + - url::ViewOptions::WITH_USERNAME + - url::ViewOptions::WITH_PASSWORD) + << "]" << endl; + + str + << "username = " << _username << endl + << "password = " << _password << endl; + + for ( const auto &v : _extraValues ) { + if ( v.first == "username" || v.first == "password" ) + continue; + str << v.first << " = " << v.second << endl; + } + + return str; +} + +std::ostream & operator << (std::ostream & str, const AuthData & auth_data) +{ + auth_data.dumpOn(str); + return str; +} + + } // namespace media +} // namespace zypp diff --git a/zypp-media/auth/authdata.h b/zypp-media/auth/authdata.h new file mode 100644 index 0000000..746c0ae --- /dev/null +++ b/zypp-media/auth/authdata.h @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/auth/AuthData + * Convenience interface for handling authentication data of media user. + */ +#ifndef ZYPP_MEDIA_AUTH_DATA_H +#define ZYPP_MEDIA_AUTH_DATA_H + +#include +#include + +#include + +namespace zypp { + namespace media { + +/////////////////////////////////////////////////////////////////// + + +/** + * Class for handling media authentication data. This is the most generic + * class containing only username and password members. + */ +class ZYPP_API AuthData +{ +public: + AuthData() + {} + + AuthData(const Url & url); + + AuthData(std::string username, std::string password) + : _username(std::move(username)), _password(std::move(password)), _lastChange(0) + {} + + virtual ~AuthData() {}; + + /** + * Checks validity of authentication data. + * \return true if the object contains non-empty username and + * non-empty password, false otherwise. + */ + virtual bool valid() const; + + void setUrl(const Url & url) { _url = url; } + void setUsername(const std::string & username) { _username = username; } + void setPassword(const std::string & password) { _password = password; } + + Url url() const { return _url; } + std::string username() const { return _username; } + std::string password() const { return _password; } + + /*! + * Returns the timestamp of the last change to the database this + * credential is stored in, or 0 if it is not known. + */ + time_t lastDatabaseUpdate () const; + void setLastDatabaseUpdate ( time_t time ); + + const std::map &extraValues() const; + std::map &extraValues(); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + virtual std::ostream & dumpAsIniOn( std::ostream & str ) const; + +private: + Url _url; + std::string _username; + std::string _password; + time_t _lastChange; //< timestamp of the last change to the database this credential is stored in + std::map _extraValues; +}; + +using AuthData_Ptr = shared_ptr; +std::ostream & operator << (std::ostream & str, const AuthData & auth_data); + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_AUTH_DATA_H diff --git a/zypp-media/auth/credentialfilereader.cc b/zypp-media/auth/credentialfilereader.cc new file mode 100644 index 0000000..eddaee4 --- /dev/null +++ b/zypp-media/auth/credentialfilereader.cc @@ -0,0 +1,150 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/auth/credentialfilereader + * + */ + +#include "credentialfilereader.h" + +#include + +#include +#include +#include +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "parser" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace media + { + /////////////////////////////////////////////////////////////////// + namespace + { + // Looks like INI but allows multiple sections for the same URL + // but different user (in .cat files). So don't use an Ini + // Also support a global section without '[URL]' which is used + // in credential files. + // ------------------------------------- + // username = emptyUSER + // password = emptyPASS + // ------------------------------------- + // [http://server/tmp/sumafake222] + // username = USER + // password = PASS + // + // [http://server/tmp/sumafake222] + // username = USER2 + // password = PASS + // ------------------------------------- + struct CredentialFileReaderImpl : public parser::IniParser + { + using ProcessCredentials = CredentialFileReader::ProcessCredentials; + + struct StopParsing {}; + + CredentialFileReaderImpl( const Pathname & input_r, const ProcessCredentials & callback_r ) + : _input( input_r ) + , _callback( callback_r ) + { + zypp::PathInfo pi( input_r ); + _lastChange = pi.mtime(); + + try + { + parse( input_r ); + } + catch ( StopParsing ) + { /* NO error but consumer aborted parsing */ } + } + + // NO-OP; new sections are opened in consume() + void beginParse() override + { /*EMPTY*/ } + + // start a new section [url] + void consume( const std::string & section_r ) override + { + endParse(); // close any open section + _secret.reset( new AuthData ); + try + { + _secret->setUrl( Url(section_r) ); + } + catch ( const url::UrlException & ) + { + ERR << "Ignore invalid URL '" << section_r << "' in file " << _input << endl; + _secret.reset(); // ignore this section + } + } + + void consume( const std::string & section_r, const std::string & key_r, const std::string & value_r ) override + { + if ( !_secret && section_r.empty() ) + _secret.reset( new AuthData ); // a initial global section without [URL] + + if ( _secret ) + { + if ( key_r == "username" ) + _secret->setUsername( value_r ); + else if ( key_r == "password" ) + _secret->setPassword( value_r ); + else + _secret->extraValues()[key_r] = value_r; + } + // else: ignored section due to wrong URL + } + + // send any valid pending section + void endParse() override + { + if ( _secret ) + { + if ( _secret->valid() ) + { + _secret->setLastDatabaseUpdate( _lastChange ); + if ( !_callback( _secret ) ) + throw( StopParsing() ); + } + else + ERR << "Ignore invalid credentials for URL '" << _secret->url() << "' in file " << _input << endl; + } + } + + private: + const Pathname & _input; + const ProcessCredentials & _callback; + AuthData_Ptr _secret; + time_t _lastChange; + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CredentialFileReader + // + ////////////////////////////////////////////////////////////////////// + + CredentialFileReader::CredentialFileReader( const Pathname & crfile_r, const ProcessCredentials & callback_r ) + { CredentialFileReaderImpl( crfile_r, callback_r ); } + + CredentialFileReader::~CredentialFileReader() + {} + + } // namespace media + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-media/auth/credentialfilereader.h b/zypp-media/auth/credentialfilereader.h new file mode 100644 index 0000000..54bf6f6 --- /dev/null +++ b/zypp-media/auth/credentialfilereader.h @@ -0,0 +1,50 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/auth/CredentialFileReader + * + */ +#ifndef ZYPP_MEDIA_AUTH_CREDENTIALFILEREADER_H +#define ZYPP_MEDIA_AUTH_CREDENTIALFILEREADER_H + +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace media + { + ////////////////////////////////////////////////////////////////////// + /// \class CredentialFileReader + /// \brief Parse credentials files and catalogs + class CredentialFileReader + { + public: + /** Callback invoked for each entry found in the file. + * Return \c false to abort parsing. + */ + using ProcessCredentials = function; + + CredentialFileReader( const Pathname & crfile_r, const ProcessCredentials & callback_r ); + ~CredentialFileReader(); + private: + ProcessCredentials _callback; + }; + ////////////////////////////////////////////////////////////////////// + + } // namespace media + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif /* ZYPP_MEDIA_AUTH_CREDENTIALFILEREADER_H */ diff --git a/zypp-media/auth/credentialmanager.cc b/zypp-media/auth/credentialmanager.cc new file mode 100644 index 0000000..75f3527 --- /dev/null +++ b/zypp-media/auth/credentialmanager.cc @@ -0,0 +1,512 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/auth/credentialmanager.cc + * + */ + +#include "credentialmanager.h" + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace bpci = boost::interprocess; + + +using std::endl; + +#define USER_CREDENTIALS_FILE ".zypp/credentials.cat" + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////// + namespace media + { //////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : AuthDataComparator + // + ////////////////////////////////////////////////////////////////////// + + bool AuthDataComparator::operator()( const AuthData_Ptr & lhs, const AuthData_Ptr & rhs ) const + { + static const url::ViewOption vopt = url::ViewOption::DEFAULTS + - url::ViewOption::WITH_USERNAME + - url::ViewOption::WITH_PASSWORD + - url::ViewOption::WITH_QUERY_STR; + // std::less semantic! + int cmp = lhs->url().asString(vopt).compare( rhs->url().asString(vopt) ); + if ( ! cmp ) + cmp = lhs->username().compare( rhs->username() ); + return( cmp < 0 ); + } + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CredManagerOptions + // + ////////////////////////////////////////////////////////////////////// + + CredManagerOptions::CredManagerOptions(const Pathname & rootdir) + : globalCredFilePath(rootdir / MediaConfig::instance().credentialsGlobalFile()) + , customCredFileDir(rootdir / MediaConfig::instance().credentialsGlobalDir()) + { + char * homedir = getenv("HOME"); + if (homedir) + userCredFilePath = rootdir / homedir / USER_CREDENTIALS_FILE; + } + + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CredentialManager::Impl + // + struct CredentialManager::Impl + { + Impl(CredManagerOptions &&options); + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() + {} + + void init_globalCredentials(); + void init_userCredentials(); + + bool processCredentials(AuthData_Ptr & cred); + + AuthData_Ptr getCred(const Url & url) const; + AuthData_Ptr getCredFromFile(const Pathname & file); + void saveGlobalCredentials(); + void saveUserCredentials(); + + + CredManagerOptions _options; + + CredentialSet _credsGlobal; + CredentialSet _credsUser; + CredentialSet _credsTmp; + + bool _globalDirty; + bool _userDirty; + }; + ////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CredentialManager::Impl + // + ////////////////////////////////////////////////////////////////////// + + CredentialManager::Impl::Impl(CredManagerOptions &&options) + : _options(std::move(options)) + , _globalDirty(false) + , _userDirty(false) + { + init_globalCredentials(); + init_userCredentials(); + } + + + void CredentialManager::Impl::init_globalCredentials() + { + if (_options.globalCredFilePath.empty()) + DBG << "global cred file not known"; + else if (PathInfo(_options.globalCredFilePath).isExist()) + { + /* list entries; + if (filesystem::readdir(entries, _options.globalCredFilePath, false) != 0) + ZYPP_THROW(Exception("failed to read directory")); + + for_(it, entries.begin(), entries.end())*/ + + CredentialFileReader(_options.globalCredFilePath, + bind(&Impl::processCredentials, this, _1)); + } + else + DBG << "global cred file does not exist"; + + _credsGlobal = _credsTmp; _credsTmp.clear(); + DBG << "Got " << _credsGlobal.size() << " global records." << endl; + } + + + void CredentialManager::Impl::init_userCredentials() + { + if (_options.userCredFilePath.empty()) + DBG << "user cred file not known"; + else if (PathInfo(_options.userCredFilePath).isExist()) + { + /* list entries; + if (filesystem::readdir(entries, _options.userCredFilePath, false ) != 0) + ZYPP_THROW(Exception("failed to read directory")); + + for_(it, entries.begin(), entries.end())*/ + CredentialFileReader(_options.userCredFilePath, + bind(&Impl::processCredentials, this, _1)); + } + else + DBG << "user cred file does not exist" << endl; + + _credsUser = _credsTmp; _credsTmp.clear(); + DBG << "Got " << _credsUser.size() << " user records." << endl; + } + + + bool CredentialManager::Impl::processCredentials(AuthData_Ptr & cred) + { + _credsTmp.insert(cred); + return true; + } + + + AuthData_Ptr CredentialManager::findIn(const CredentialManager::CredentialSet & set, + const Url & url, + url::ViewOption vopt) + { + const std::string & username = url.getUsername(); + for( CredentialManager::CredentialIterator it = set.begin(); it != set.end(); ++it ) + { + if ( !(*it)->url().isValid() ) + continue; + + // this ignores url params - not sure if it is good or bad... + if ( url.asString(vopt).find((*it)->url().asString(vopt)) == 0 ) + { + if ( username.empty() || username == (*it)->username() ) + return *it; + } + } + + return AuthData_Ptr(); + } + + AuthData_Ptr CredentialManager::Impl::getCred(const Url & url) const + { + AuthData_Ptr result; + + // compare the urls via asString(), but ignore password + // default url::ViewOption will take care of that. + // operator==(Url,Url) compares the whole Url + + url::ViewOption vopt; + vopt = vopt + - url::ViewOption::WITH_USERNAME + - url::ViewOption::WITH_PASSWORD + - url::ViewOption::WITH_QUERY_STR; + + // search in global credentials + result = findIn(_credsGlobal, url, vopt); + + // search in home credentials + if (!result) + result = findIn(_credsUser, url, vopt); + + if (result) + DBG << "Found credentials for '" << url << "':" << endl << *result; + else + DBG << "No credentials for '" << url << "'" << endl; + + return result; + } + + + AuthData_Ptr CredentialManager::Impl::getCredFromFile(const Pathname & file) + { + AuthData_Ptr result; + + Pathname credfile; + if (file.absolute()) + // get from that file + credfile = file; + else + // get from /etc/zypp/credentials.d, delete the leading path + credfile = _options.customCredFileDir / file.basename(); + + PathInfo pi { credfile }; + if ( pi.userMayR() ) try { + // make sure only our thread accesses the file + bpci::file_lock lockFile ( credfile.c_str() ); + bpci::scoped_lock lock( lockFile ); + + CredentialFileReader(credfile, bind(&Impl::processCredentials, this, _1)); + } + catch ( ... ) { + WAR << pi << " failed to lock file for reading." << endl; + } + + if (_credsTmp.empty()) + WAR << pi << " does not contain valid credentials or is not readable." << endl; + else + { + result = *_credsTmp.begin(); + _credsTmp.clear(); + } + + return result; + } + + static int save_creds_in_file( + CredentialManager::CredentialSet &creds, + const Pathname & file, + const mode_t mode) + { + int ret = 0; + filesystem::assert_file_mode( file, mode ); + + const auto now = time( nullptr ); + + PathInfo pi { file }; + if ( pi.userMayRW() ) try { + // make sure only our thread accesses the file + bpci::file_lock lockFile ( file.c_str() ); + bpci::scoped_lock lock( lockFile ); + + std::ofstream fs(file.c_str()); + for_(it, creds.begin(), creds.end()) + { + (*it)->dumpAsIniOn(fs); + (*it)->setLastDatabaseUpdate( now ); + fs << endl; + } + if ( !fs ) { + WAR << pi << " failed to write credentials to file." << endl; + ret = 1; + } + fs.close(); + } + catch ( ... ) { + WAR << pi << " failed to lock file for writing." << endl; + ret = 1; + } + + return ret; + } + + void CredentialManager::Impl::saveGlobalCredentials() + { + save_creds_in_file(_credsGlobal, _options.globalCredFilePath, 0640); + } + + void CredentialManager::Impl::saveUserCredentials() + { + save_creds_in_file(_credsUser, _options.userCredFilePath, 0600); + } + + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CredentialManager + // + ////////////////////////////////////////////////////////////////////// + + CredentialManager::CredentialManager(CredManagerOptions opts) + : _pimpl(new Impl(std::move(opts))) + {} + + + AuthData_Ptr CredentialManager::getCred(const Url & url) + { + std::string credfile = url.getQueryParam("credentials"); + if (credfile.empty()) + return _pimpl->getCred(url); + return _pimpl->getCredFromFile(credfile); + } + + + AuthData_Ptr CredentialManager::getCredFromFile(const Pathname & file) + { return _pimpl->getCredFromFile(file); } + + + void CredentialManager::addCred(const AuthData & cred) + { + if ( !cred.url().isValid() ) + ZYPP_THROW( MediaInvalidCredentialsException( "URL must be valid in order to save AuthData." ) ); + + Pathname credfile = cred.url().getQueryParam("credentials"); + if (credfile.empty()) + //! \todo ask user where to store these creds. saving to user creds for now + addUserCred(cred); + else + saveInFile(cred, credfile); + } + + time_t CredentialManager::timestampForCredDatabase ( const zypp::Url &url ) + { + Pathname credfile; + if ( url.isValid() ) { + credfile = url.getQueryParam("credentials"); + } + + if (credfile.empty()) + credfile = _pimpl->_options.userCredFilePath; + + zypp::PathInfo pi(credfile); + if ( pi.isExist() && pi.isFile() ) + return pi.mtime(); + + return 0; + } + + void CredentialManager::addGlobalCred(const AuthData & cred) + { + if ( !cred.url().isValid() ) + ZYPP_THROW( MediaInvalidCredentialsException( "URL must be valid in order to save AuthData." ) ); + + AuthData_Ptr c_ptr; + c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed + std::pair ret = _pimpl->_credsGlobal.insert(c_ptr); + if (ret.second) + _pimpl->_globalDirty = true; + else if ((*ret.first)->password() != cred.password()) + { + _pimpl->_credsGlobal.erase(ret.first); + _pimpl->_credsGlobal.insert(c_ptr); + _pimpl->_globalDirty = true; + } + } + + + void CredentialManager::addUserCred(const AuthData & cred) + { + if ( !cred.url().isValid() ) + ZYPP_THROW( MediaInvalidCredentialsException( "URL must be valid in order to save AuthData." ) ); + + AuthData_Ptr c_ptr; + c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed + std::pair ret = _pimpl->_credsUser.insert(c_ptr); + if (ret.second) + _pimpl->_userDirty = true; + else if ((*ret.first)->password() != cred.password()) + { + _pimpl->_credsUser.erase(ret.first); + _pimpl->_credsUser.insert(c_ptr); + _pimpl->_userDirty = true; + } + } + + + void CredentialManager::save() + { + if (_pimpl->_globalDirty) + _pimpl->saveGlobalCredentials(); + if (_pimpl->_userDirty) + _pimpl->saveUserCredentials(); + _pimpl->_globalDirty = false; + _pimpl->_userDirty = false; + } + + + void CredentialManager::saveInGlobal(const AuthData & cred) + { + addGlobalCred(cred); + save(); + } + + + void CredentialManager::saveInUser(const AuthData & cred) + { + addUserCred(cred); + save(); + } + + + void CredentialManager::saveInFile(const AuthData & cred, const Pathname & credFile) + { + AuthData_Ptr c_ptr; + c_ptr.reset(new AuthData(cred)); // FIX for child classes if needed + c_ptr->setUrl(Url()); // don't save url in custom creds file + CredentialManager::CredentialSet creds; + creds.insert(c_ptr); + + int ret = 0; + if (credFile.absolute()) + ret = save_creds_in_file(creds, credFile, 0640); + else + ret = save_creds_in_file( + creds, _pimpl->_options.customCredFileDir / credFile, 0600); + + if (!ret) + { + //! \todo figure out the reason(?), call back to user + ERR << "error saving the credentials" << endl; + } + } + + + void CredentialManager::clearAll(bool global) + { + if (global) + { + if (!filesystem::unlink(_pimpl->_options.globalCredFilePath)) + ERR << "could not delete user credentials file " + << _pimpl->_options.globalCredFilePath << endl; + _pimpl->_credsUser.clear(); + } + else + { + if (!filesystem::unlink(_pimpl->_options.userCredFilePath)) + ERR << "could not delete global credentials file" + << _pimpl->_options.userCredFilePath << endl; + _pimpl->_credsGlobal.clear(); + } + } + + + CredentialManager::CredentialIterator CredentialManager::credsGlobalBegin() const + { return _pimpl->_credsGlobal.begin(); } + + CredentialManager::CredentialIterator CredentialManager::credsGlobalEnd() const + { return _pimpl->_credsGlobal.end(); } + + CredentialManager::CredentialSize CredentialManager::credsGlobalSize() const + { return _pimpl->_credsGlobal.size(); } + + bool CredentialManager::credsGlobalEmpty() const + { return _pimpl->_credsGlobal.empty(); } + + + CredentialManager::CredentialIterator CredentialManager::credsUserBegin() const + { return _pimpl->_credsUser.begin(); } + + CredentialManager::CredentialIterator CredentialManager::credsUserEnd() const + { return _pimpl->_credsUser.end(); } + + CredentialManager::CredentialSize CredentialManager::credsUserSize() const + { return _pimpl->_credsUser.size(); } + + bool CredentialManager::credsUserEmpty() const + { return _pimpl->_credsUser.empty(); } + + + //////////////////////////////////////////////////////////////////// + } // media + ////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// +} // zypp +////////////////////////////////////////////////////////////////////// diff --git a/zypp-media/auth/credentialmanager.h b/zypp-media/auth/credentialmanager.h new file mode 100644 index 0000000..0c31b28 --- /dev/null +++ b/zypp-media/auth/credentialmanager.h @@ -0,0 +1,196 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/auth/CredentialManager + * + */ +#ifndef ZYPP_MEDIA_AUTH_CREDENTIALMANAGER_H +#define ZYPP_MEDIA_AUTH_CREDENTIALMANAGER_H + +#include + +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + class Url; + + ////////////////////////////////////////////////////////////////////// + namespace media + { //////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CredManagerOptions + // + /** + * \todo configurable cred file locations + */ + struct ZYPP_API CredManagerOptions + { + CredManagerOptions(const Pathname & rootdir = ""); + + Pathname globalCredFilePath; + Pathname userCredFilePath; + Pathname customCredFileDir; + }; + ////////////////////////////////////////////////////////////////////// + + // comparator for CredentialSet + struct ZYPP_API AuthDataComparator + { + bool operator()(const AuthData_Ptr & lhs, const AuthData_Ptr & rhs) const; + }; + + ////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CredentialManager + // + /** + * \todo better method names + * \todo delete(AuthData) method + */ + class ZYPP_API CredentialManager + { + public: + using CredentialSet = std::set; + using CredentialSize = CredentialSet::size_type; + using CredentialIterator = CredentialSet::const_iterator; + + + CredentialManager(CredManagerOptions opts = CredManagerOptions()); + + ~CredentialManager() + {} + + public: + /** + * Get credentials for the specified \a url. + * + * If the URL contains also username, it will be used to find the match + * for this user (in case mutliple are available). + * + * \param url URL to find credentials for. + * \return Pointer to retrieved authentication data on success or an empty + * AuthData_Ptr otherwise. + * \todo return a copy instead? + */ + AuthData_Ptr getCred(const Url & url); + + /** + * Read credentials from a file. + */ + AuthData_Ptr getCredFromFile(const Pathname & file); + + /** + * Add new global credentials. + */ + void addGlobalCred(const AuthData & cred); + + /** + * Add new user credentials. + */ + void addUserCred(const AuthData & cred); + + /** + * Add new credentials with user callbacks. + * + * If the cred->url() contains 'credentials' query parameter, the + * credentials will be automatically saved to the specified file using the + * \ref saveInFile() method. + * + * Otherwise a callback will be called asking whether to save to custom + * file, or to global or user's credentials catalog. + * + * \todo Currently no callback is called, credentials are automatically + * saved to user's credentials.cat if no 'credentials' parameter + * has been specified + */ + void addCred(const AuthData & cred); + + /** + * Saves any unsaved credentials added via \ref addUserCred() or + * \a addGlobalCred() methods. + */ + void save(); + + /** + * Saves given \a cred to global credentials file. + * + * \note Use this method to add just one piece of credentials. To add + * multiple items at once, use addGlobalCred() followed + * by save() + */ + void saveInGlobal(const AuthData & cred); + + /** + * Saves given \a cred to user's credentials file. + * + * \note Use this method to add just one piece of credentials. To add + * multiple items at once, use addUserCred() followed + * by save() + */ + void saveInUser(const AuthData & cred); + + /** + * Saves given \a cred to user specified credentials file. + * + * If the credFile path is absolute, it will be saved at that precise + * location. If \a credFile is just a filename, it will be saved + * in \ref CredManagerOptions::customCredFileDir. Otherwise the current + * working directory will be prepended to the file path. + */ + void saveInFile(const AuthData &, const Pathname & credFile); + + /** + * Remove all global or user credentials from memory and disk. + * + * \param global Whether to remove global or user credentials. + */ + void clearAll(bool global = false); + + /*! + * Helper function to find a matching AuthData instance in a CredentialSet + */ + static AuthData_Ptr findIn( const CredentialManager::CredentialSet & set, const Url & url, url::ViewOption vopt ); + + /*! + * Returns the timestamp of the database the given URL creds would be stored + */ + time_t timestampForCredDatabase ( const zypp::Url &url ); + + CredentialIterator credsGlobalBegin() const; + CredentialIterator credsGlobalEnd() const; + CredentialSize credsGlobalSize() const; + bool credsGlobalEmpty() const; + + CredentialIterator credsUserBegin() const; + CredentialIterator credsUserEnd() const; + CredentialSize credsUserSize() const; + bool credsUserEmpty() const; + + struct Impl; + private: + RW_pointer _pimpl; + }; + ////////////////////////////////////////////////////////////////////// + + + //////////////////////////////////////////////////////////////////// + } // media + ////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// +} // zypp +////////////////////////////////////////////////////////////////////// + +#endif /* ZYPP_MEDIA_AUTH_CREDENTIALMANAGER_H */ diff --git a/zypp-media/cdtools.cc b/zypp-media/cdtools.cc new file mode 100644 index 0000000..a4c9829 --- /dev/null +++ b/zypp-media/cdtools.cc @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "cdtools.h" + +extern "C" +{ +#include +#include +} + +#include +#include +#include +#include + + +/* +** If defined to the full path of the eject utility, +** it will be used additionally to the eject-ioctl. +*/ +#define EJECT_TOOL_PATH "/bin/eject" + + +namespace zypp::media { + + bool CDTools::openTray(const std::string &device_r) + { + int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK|O_CLOEXEC ); + int res = -1; + + if ( fd != -1) + { + res = ::ioctl( fd, CDROMEJECT ); + ::close( fd ); + } + + if ( res ) + { + if( fd == -1) + { + WAR << "Unable to open '" << device_r + << "' (" << ::strerror( errno ) << ")" << std::endl; + } + else + { + WAR << "Eject " << device_r + << " failed (" << ::strerror( errno ) << ")" << std::endl; + } + +#if defined(EJECT_TOOL_PATH) + DBG << "Try to eject " << device_r << " using " + << EJECT_TOOL_PATH << " utility" << std::endl; + + const char *cmd[3]; + cmd[0] = EJECT_TOOL_PATH; + cmd[1] = device_r.c_str(); + cmd[2] = NULL; + ExternalProgram eject(cmd, ExternalProgram::Stderr_To_Stdout); + + for(std::string out( eject.receiveLine()); + out.length(); out = eject.receiveLine()) + { + DBG << " " << out; + } + + if(eject.close() != 0) + { + WAR << "Eject of " << device_r << " failed." << std::endl; + return false; + } +#else + return false; +#endif + } + MIL << "Eject of " << device_r << " successful." << std::endl; + return true; + } + + bool CDTools::closeTray(const std::string &device_r) + { + int fd = ::open( device_r.c_str(), O_RDONLY|O_NONBLOCK|O_CLOEXEC ); + if ( fd == -1 ) { + WAR << "Unable to open '" << device_r << "' (" << ::strerror( errno ) << ")" << std::endl; + return false; + } + int res = ::ioctl( fd, CDROMCLOSETRAY ); + ::close( fd ); + if ( res ) { + WAR << "Close tray " << device_r << " failed (" << ::strerror( errno ) << ")" << std::endl; + return false; + } + DBG << "Close tray " << device_r << std::endl; + return true; + } + +} diff --git a/zypp-media/cdtools.h b/zypp-media/cdtools.h new file mode 100644 index 0000000..e5489ce --- /dev/null +++ b/zypp-media/cdtools.h @@ -0,0 +1,29 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/cdtools.h + * +*/ + +#ifndef ZYPP_MEDIA_CDTOOLS_H +#define ZYPP_MEDIA_CDTOOLS_H + +#include + +namespace zypp::media { + + class CDTools + { + public: + static bool openTray( const std::string & device_r ); + static bool closeTray( const std::string & device_r ); + }; + +} + +#endif diff --git a/zypp-media/filecheckexception.cc b/zypp-media/filecheckexception.cc new file mode 100644 index 0000000..2d5384e --- /dev/null +++ b/zypp-media/filecheckexception.cc @@ -0,0 +1,12 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/filecheckexception.cc + * +*/ +#include "filecheckexception.h" diff --git a/zypp-media/filecheckexception.h b/zypp-media/filecheckexception.h new file mode 100644 index 0000000..98e92aa --- /dev/null +++ b/zypp-media/filecheckexception.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_MEDIA_FILECHECKEXCEPTION_H +#define ZYPP_MEDIA_FILECHECKEXCEPTION_H + +#include + +namespace zypp { + + class ZYPP_API FileCheckException : public Exception + { + public: + FileCheckException(std::string msg) + : Exception(std::move(msg)) + {} + }; + + class ZYPP_API CheckSumCheckException : public FileCheckException + { + public: + CheckSumCheckException(std::string msg) + : FileCheckException(std::move(msg)) + {} + }; + + class ZYPP_API SignatureCheckException : public FileCheckException + { + public: + SignatureCheckException(std::string msg) + : FileCheckException(std::move(msg)) + {} + }; + +} + +#endif // ZYPP_MEDIA_FILECHECKEXCEPTION_H diff --git a/zypp-media/mediaconfig.cc b/zypp-media/mediaconfig.cc new file mode 100644 index 0000000..589c73f --- /dev/null +++ b/zypp-media/mediaconfig.cc @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/mediaconfig.cc + * +*/ + +#include "mediaconfig.h" +#include +#include + +namespace zypp { + + class MediaConfigPrivate { + public: + + MediaConfigPrivate() + : download_max_concurrent_connections( 5 ) + , download_min_download_speed ( 0 ) + , download_max_download_speed ( 0 ) + , download_max_silent_tries ( 5 ) + , download_transfer_timeout ( 180 ) + , download_connect_timeout ( 60 ) + { } + + Pathname credentials_global_dir_path; + Pathname credentials_global_file_path; + + int download_max_concurrent_connections; + int download_min_download_speed; + int download_max_download_speed; + int download_max_silent_tries; + int download_transfer_timeout; + int download_connect_timeout; + + }; + + MediaConfig::MediaConfig() : d_ptr( new MediaConfigPrivate() ) + { } + + MediaConfig &MediaConfig::instance() + { + static MediaConfig instance; + return instance; + } + + bool MediaConfig::setConfigValue( const std::string §ion, const std::string &entry, const std::string &value ) + { + Z_D(); + if ( section == "main" ) { + if ( entry == "credentials.global.dir" ) { + d->credentials_global_dir_path = Pathname(value); + return true; + } else if ( entry == "credentials.global.file" ) { + d->credentials_global_file_path = Pathname(value); + return true; + + } else if ( entry == "download.max_concurrent_connections" ) { + str::strtonum(value, d->download_max_concurrent_connections); + return true; + + } else if ( entry == "download.min_download_speed" ) { + str::strtonum(value, d->download_min_download_speed); + return true; + + } else if ( entry == "download.max_download_speed" ) { + str::strtonum(value, d->download_max_download_speed); + return true; + + } else if ( entry == "download.max_silent_tries" ) { + str::strtonum(value, d->download_max_silent_tries); + return true; + + } else if ( entry == "download.connect_timeout" ) { + str::strtonum(value, d->download_connect_timeout); + if ( d->download_connect_timeout < 0 ) + d->download_connect_timeout = 0; + return true; + + } else if ( entry == "download.transfer_timeout" ) { + str::strtonum(value, d->download_transfer_timeout); + if ( d->download_transfer_timeout < 0 ) d->download_transfer_timeout = 0; + else if ( d->download_transfer_timeout > 3600 ) d->download_transfer_timeout = 3600; + return true; + } + } + return false; + } + + Pathname MediaConfig::credentialsGlobalDir() const + { + Z_D(); + return ( d->credentials_global_dir_path.empty() ? + Pathname("/etc/zypp/credentials.d") : d->credentials_global_dir_path ); + } + + Pathname MediaConfig::credentialsGlobalFile() const + { + Z_D(); + return ( d->credentials_global_file_path.empty() ? + Pathname("/etc/zypp/credentials.cat") : d->credentials_global_file_path ); + } + + long MediaConfig::download_max_concurrent_connections() const + { return d_func()->download_max_concurrent_connections; } + + long MediaConfig::download_min_download_speed() const + { return d_func()->download_min_download_speed; } + + long MediaConfig::download_max_download_speed() const + { return d_func()->download_max_download_speed; } + + long MediaConfig::download_max_silent_tries() const + { return d_func()->download_max_silent_tries; } + + long MediaConfig::download_transfer_timeout() const + { return d_func()->download_transfer_timeout; } + + long MediaConfig::download_connect_timeout() const + { return d_func()->download_connect_timeout; } + + ZYPP_IMPL_PRIVATE(MediaConfig) +} + + diff --git a/zypp-media/mediaconfig.h b/zypp-media/mediaconfig.h new file mode 100644 index 0000000..8e0de5e --- /dev/null +++ b/zypp-media/mediaconfig.h @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/MediaConfig + * +*/ +#ifndef ZYPP_MEDIA_MEDIACONFIG_H +#define ZYPP_MEDIA_MEDIACONFIG_H + +#include +#include +#include +#include +#include + +namespace zypp { + + class MediaConfigPrivate; + + /*! + * Helper class to collect global options and settings related to zypp-media. + * Use it to avoid hardcoded values and calls to getZYpp() just + * to retrieve some value like credentials path or download related settings. + * + * Note, if you add settings to this file, please follow the following + * convention: + * + * namespace.settingname + * + * should become + * + * namespace_settingName() + * + * \ingroup ZyppConfig + * \ingroup Singleton + */ + class MediaConfig : private base::NonCopyable + { + ZYPP_DECLARE_PRIVATE(MediaConfig) + public: + + /*! Singleton ctor */ + static MediaConfig & instance(); + + bool setConfigValue ( const std::string §ion, const std::string &entry, const std::string &value ); + + /*! + * Defaults to /etc/zypp/credentials.d + */ + Pathname credentialsGlobalDir() const; + + /*! + * Defaults to /etc/zypp/credentials.cat + */ + Pathname credentialsGlobalFile() const; + + /*! + * Maximum number of concurrent connections for a single transfer + */ + long download_max_concurrent_connections() const; + + /*! + * Minimum download speed (bytes per second) + * until the connection is dropped + */ + long download_min_download_speed() const; + + /*! + * Maximum download speed (bytes per second) + */ + long download_max_download_speed() const; + + /*! + * Maximum silent tries + */ + long download_max_silent_tries() const; + + /*! + * Maximum time in seconds that you allow a transfer operation to take. + */ + long download_transfer_timeout() const; + + /*! + * Maximum time in seconds that you allow the connection phase to the server to take. + */ + long download_connect_timeout() const; + + private: + MediaConfig(); + std::unique_ptr d_ptr; + }; + +} + +#endif diff --git a/zypp-media/mediaexception.cc b/zypp-media/mediaexception.cc new file mode 100644 index 0000000..a9ceecb --- /dev/null +++ b/zypp-media/mediaexception.cc @@ -0,0 +1,227 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/mediaexception.cc + * +*/ + +#include + +#include +#include + +#include + +using std::endl; +using zypp::str::form; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + namespace media { + ///////////////////////////////////////////////////////////////// + + MediaException::~MediaException () noexcept {} + + std::ostream & MediaMountException::dumpOn( std::ostream & str ) const + { + str << form(_("Failed to mount %s on %s"), _source.c_str(), _target.c_str() ); + if( !_cmdout.empty()) + str << ": " << _error << " (" << _cmdout << ")"; + else + str << ": " << _error; + return str; + } + + std::ostream & MediaUnmountException::dumpOn( std::ostream & str ) const + { + return str << form(_("Failed to unmount %s"), _path.c_str() ) << " : " << _error; + } + + std::ostream & MediaBadFilenameException::dumpOn( std::ostream & str ) const + { + return str << form(_("Bad file name: %s"), _filename.c_str() ); + } + + std::ostream & MediaNotOpenException::dumpOn( std::ostream & str ) const + { + return str << form(_("Medium not opened when trying to perform action '%s'."), _action.c_str() ); + } + + std::ostream & MediaFileNotFoundException::dumpOn( std::ostream & str) const + { + return str << form( _("File '%s' not found on medium '%s'"), _filename.c_str(), _url.c_str() ); + } + + std::ostream & MediaWriteException::dumpOn( std::ostream & str) const + { + return str << form(_("Cannot write file '%s'."), _filename.c_str() ); + } + + std::ostream & MediaNotAttachedException::dumpOn( std::ostream & str) const + { + return str << _("Medium not attached") << ": " << _url; + } + + std::ostream & MediaBadAttachPointException::dumpOn( std::ostream & str) const + { + return str << _("Bad media attach point") << ": " << _url; + } + + std::ostream & MediaCurlInitException::dumpOn( std::ostream & str) const + { + // TranslatorExplanation: curl is the name of a library, don't translate + return str << form(_("Download (curl) initialization failed for '%s'"), _url.c_str() ); + } + + std::ostream & MediaSystemException::dumpOn( std::ostream & str) const + { + return str << form(_("System exception '%s' on medium '%s'."), _message.c_str(), _url.c_str() ); + } + + std::ostream & MediaNotAFileException::dumpOn( std::ostream & str) const + { + return str << form(_("Path '%s' on medium '%s' is not a file."), _path.c_str(), _url.c_str() ); + } + + std::ostream & MediaNotADirException::dumpOn( std::ostream & str) const + { + return str << form(_("Path '%s' on medium '%s' is not a directory."), _path.c_str(), _url.c_str() ); + } + + std::ostream & MediaBadUrlException::dumpOn( std::ostream & str) const + { + if( _msg.empty()) + { + return str << _("Malformed URI") << ": " << _url; + } + else + { + return str << _msg << ": " << _url; + } + } + + std::ostream & MediaBadUrlEmptyHostException::dumpOn( std::ostream & str) const + { + return str << _("Empty host name in URI") << ": " << _url; + } + + std::ostream & MediaBadUrlEmptyFilesystemException::dumpOn( std::ostream & str) const + { + return str << _("Empty filesystem in URI") << ": " << _url; + } + + std::ostream & MediaBadUrlEmptyDestinationException::dumpOn( std::ostream & str) const + { + return str << _("Empty destination in URI") << ": " << _url; + } + + std::ostream & MediaUnsupportedUrlSchemeException::dumpOn( std::ostream & str) const + { + return str << form(_("Unsupported URI scheme in '%s'."), _url.c_str() ); + } + + std::ostream & MediaNotSupportedException::dumpOn( std::ostream & str) const + { + return str << _("Operation not supported by medium") << ": " << _url; + } + + std::ostream & MediaCurlException::dumpOn( std::ostream & str) const + { + // TranslatorExplanation: curl is the name of a library, don't translate + return str << form(_( + "Download (curl) error for '%s':\n" + "Error code: %s\n" + "Error message: %s\n"), _url.c_str(), _err.c_str(), _msg.c_str()); + } + + std::ostream & MediaCurlSetOptException::dumpOn( std::ostream & str) const + { + // TranslatorExplanation: curl is the name of a library, don't translate + return str << form(_("Error occurred while setting download (curl) options for '%s':"), _url.c_str() ); + if ( !_msg.empty() ) + str << endl << _msg; + } + + std::ostream & MediaNotDesiredException::dumpOn( std::ostream & str ) const + { + return str << form(_("Media source '%s' does not contain the desired medium"), _url.c_str() ); + } + + std::ostream & MediaIsSharedException::dumpOn( std::ostream & str ) const + { + return str << form(_("Medium '%s' is in use by another instance"), _name.c_str() ); + } + + std::ostream & MediaNotEjectedException::dumpOn( std::ostream & str ) const + { + if( _name.empty() ) + return str << _("Cannot eject any media"); + else + return str << form(_("Cannot eject media '%s'"), _name.c_str()); + } + + std::ostream & MediaUnauthorizedException::dumpOn( std::ostream & str ) const + { + str << msg(); + if( !_url.asString().empty()) + str << " (" << _url << ")"; + if( !_err.empty()) + str << ": " << _err; + return str; + } + + std::ostream & MediaForbiddenException::dumpOn( std::ostream & str ) const + { + str << form(_("Permission to access '%s' denied."), _url.c_str()); + if ( !_msg.empty() ) + str << endl << _msg; + return str; + } + + std::ostream & MediaTimeoutException::dumpOn( std::ostream & str ) const + { + str << form(_("Timeout exceeded when accessing '%s'."), _url.c_str() ); + if ( !_msg.empty() ) + str << endl << _msg; + return str; + } + + std::ostream &MediaFileSizeExceededException::dumpOn(std::ostream &str) const + { + str << form(_("Downloaded data exceeded the expected filesize '%s' of '%s'."), _expectedFileSize.asString().c_str(), _url.c_str() ); + if ( !_msg.empty() ) + str << endl << _msg; + return str; + } + + std::ostream & MediaTemporaryProblemException::dumpOn( std::ostream & str ) const + { + str << form(_("Location '%s' is temporarily unaccessible."), _url.c_str() ); + if ( !_msg.empty() ) + str << endl << _msg; + return str; + } + + std::ostream & MediaBadCAException::dumpOn( std::ostream & str ) const + { + str << form(_(" SSL certificate problem, verify that the CA cert is OK for '%s'."), _url.c_str() ); + if ( !_msg.empty() ) + str << endl << _msg; + return str; + } + + std::ostream & MediaJammedException::dumpOn( std::ostream & str ) const { + str << _("No free ressources available to attach medium."); + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace media +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp-media/mediaexception.h b/zypp-media/mediaexception.h new file mode 100644 index 0000000..7a88763 --- /dev/null +++ b/zypp-media/mediaexception.h @@ -0,0 +1,576 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/MediaException + * +*/ +#ifndef ZYPP_MEDIA_MEDIAEXCEPTION_H +#define ZYPP_MEDIA_MEDIAEXCEPTION_H + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + namespace media { + /////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaException + /** Just inherits Exception to separate media exceptions + * + **/ + class ZYPP_API MediaException : public Exception + { + public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + MediaException() : Exception( "Media Exception" ) + {} + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + MediaException( const std::string & msg_r ) + : Exception( msg_r ) + {} + + /** Dtor. */ + ~MediaException() noexcept override; + }; + + class ZYPP_API MediaMountException : public MediaException + { + public: + MediaMountException() + : MediaException( "Media Mount Exception" ) + {} + + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + MediaMountException( std::string error_r, + std::string source_r, + std::string target_r, + std::string cmdout_r="") + : MediaException() + , _error(std::move(error_r)) + , _source(std::move(source_r)) + , _target(std::move(target_r)) + , _cmdout(std::move(cmdout_r)) + {} + /** Dtor. */ + ~MediaMountException() noexcept override {} + + const std::string & mountError() const + { return _error; } + const std::string & mountSource() const + { return _source; } + const std::string & mountTarget() const + { return _target; } + const std::string & mountOutput() const + { return _cmdout; } + + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _error; + std::string _source; + std::string _target; + std::string _cmdout; + }; + + class ZYPP_API MediaUnmountException : public MediaException + { + public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + MediaUnmountException( std::string error_r, + std::string path_r ) + : MediaException() + , _error(std::move(error_r)) + , _path(std::move(path_r)) + {} + /** Dtor. */ + ~MediaUnmountException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _error; + std::string _path; + }; + + class ZYPP_API MediaJammedException : public MediaException + { + public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + MediaJammedException() : MediaException( "Media Jammed Exception" ) + {} + + /** Dtor. */ + ~MediaJammedException() noexcept override {}; + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + + private: + }; + + class ZYPP_API MediaBadFilenameException : public MediaException + { + public: + MediaBadFilenameException(std::string filename_r) + : MediaException() + , _filename(std::move(filename_r)) + {} + ~MediaBadFilenameException() noexcept override {} + std::string filename() const { return _filename; } + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _filename; + }; + + class ZYPP_API MediaNotOpenException : public MediaException + { + public: + MediaNotOpenException(std::string action_r) + : MediaException() + , _action(std::move(action_r)) + {} + ~MediaNotOpenException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _action; + }; + + class ZYPP_API MediaFileNotFoundException : public MediaException + { + public: + MediaFileNotFoundException(const Url & url_r, + const Pathname & filename_r) + : MediaException() + , _url(url_r.asString()) + , _filename(filename_r.asString()) + {} + ~MediaFileNotFoundException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + std::string _filename; + }; + + class ZYPP_API MediaWriteException : public MediaException + { + public: + MediaWriteException(const Pathname & filename_r) + : MediaException() + , _filename(filename_r.asString()) + {} + ~MediaWriteException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _filename; + }; + + class ZYPP_API MediaNotAttachedException : public MediaException + { + public: + MediaNotAttachedException(const Url & url_r) + : MediaException() + , _url(url_r.asString()) + {} + ~MediaNotAttachedException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + }; + + class ZYPP_API MediaBadAttachPointException : public MediaException + { + public: + MediaBadAttachPointException(const Url & url_r) + : MediaException() + , _url(url_r.asString()) + {} + ~MediaBadAttachPointException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + }; + + class ZYPP_API MediaCurlInitException : public MediaException + { + public: + MediaCurlInitException(const Url & url_r) + : MediaException() + , _url(url_r.asString()) + {} + ~MediaCurlInitException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + }; + + class ZYPP_API MediaSystemException : public MediaException + { + public: + MediaSystemException(const Url & url_r, + std::string message_r) + : MediaException() + , _url(url_r.asString()) + , _message(std::move(message_r)) + {} + ~MediaSystemException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + std::string _message; + }; + + class ZYPP_API MediaNotAFileException : public MediaException + { + public: + MediaNotAFileException(const Url & url_r, + const Pathname & path_r) + : MediaException() + , _url(url_r.asString()) + , _path(path_r.asString()) + {} + ~MediaNotAFileException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + std::string _path; + }; + + class ZYPP_API MediaNotADirException : public MediaException + { + public: + MediaNotADirException(const Url & url_r, + const Pathname & path_r) + : MediaException() + , _url(url_r.asString()) + , _path(path_r.asString()) + {} + ~MediaNotADirException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + std::string _path; + }; + + class ZYPP_API MediaBadUrlException : public MediaException + { + public: + MediaBadUrlException(const Url & url_r, + std::string msg_r = std::string()) + : MediaException() + , _url(url_r.asString()) + , _msg(std::move(msg_r)) + {} + ~MediaBadUrlException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _msg; + }; + + class ZYPP_API MediaBadUrlEmptyHostException : public MediaBadUrlException + { + public: + MediaBadUrlEmptyHostException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + ~MediaBadUrlEmptyHostException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + }; + + class ZYPP_API MediaBadUrlEmptyFilesystemException : public MediaBadUrlException + { + public: + MediaBadUrlEmptyFilesystemException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + ~MediaBadUrlEmptyFilesystemException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + }; + + class ZYPP_API MediaBadUrlEmptyDestinationException : public MediaBadUrlException + { + public: + MediaBadUrlEmptyDestinationException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + ~MediaBadUrlEmptyDestinationException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + }; + + class ZYPP_API MediaUnsupportedUrlSchemeException : public MediaBadUrlException + { + public: + MediaUnsupportedUrlSchemeException(const Url & url_r) + : MediaBadUrlException(url_r) + {} + ~MediaUnsupportedUrlSchemeException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + }; + + class ZYPP_API MediaNotSupportedException : public MediaException + { + public: + MediaNotSupportedException(const Url & url_r) + : MediaException() + , _url(url_r.asString()) + {} + ~MediaNotSupportedException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + }; + + class ZYPP_API MediaCurlException : public MediaException + { + public: + MediaCurlException(const Url & url_r, + std::string err_r, + std::string msg_r) + : MediaException() + , _url(url_r.asString()) + , _err(std::move(err_r)) + , _msg(std::move(msg_r)) + {} + ~MediaCurlException() noexcept override {} + std::string errstr() const { return _err; } + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _err; + std::string _msg; + }; + + class ZYPP_API MediaCurlSetOptException : public MediaException + { + public: + MediaCurlSetOptException(const Url & url_r, std::string msg_r) + : MediaException() + , _url(url_r.asString()) + , _msg(std::move(msg_r)) + {} + ~MediaCurlSetOptException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _msg; + }; + + class ZYPP_API MediaNotDesiredException : public MediaException + { + public: + MediaNotDesiredException(const Url & url_r) + : MediaException() + , _url(url_r.asString()) + {} + ~MediaNotDesiredException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _url; + }; + + class ZYPP_API MediaIsSharedException : public MediaException + { + public: + /** + * \param name A media source as string (see MediaSource class). + */ + MediaIsSharedException(std::string name) + : MediaException() + , _name(std::move(name)) + {} + ~MediaIsSharedException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _name; + }; + + class ZYPP_API MediaNotEjectedException: public MediaException + { + public: + MediaNotEjectedException() + : MediaException("Can't eject any media") + , _name("") + {} + + MediaNotEjectedException(std::string name) + : MediaException("Can't eject media") + , _name(std::move(name)) + {} + ~MediaNotEjectedException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + std::string _name; + }; + + class ZYPP_API MediaUnauthorizedException: public MediaException + { + public: + MediaUnauthorizedException() + : MediaException("Unauthorized media access") + , _url("") + , _err("") + , _hint("") + {} + + MediaUnauthorizedException(Url url_r, + const std::string &msg_r, + std::string err_r, + std::string hint_r) + : MediaException(msg_r) + , _url(std::move(url_r)) + , _err(std::move(err_r)) + , _hint(std::move(hint_r)) + {} + + ~MediaUnauthorizedException() noexcept override {} + + const Url & url() const { return _url; } + const std::string & err() const { return _err; } + /** comma separated list of available authentication types */ + const std::string & hint() const { return _hint; } + + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + Url _url; + std::string _err; + std::string _hint; + }; + + class ZYPP_API MediaForbiddenException : public MediaException + { + public: + MediaForbiddenException(const Url & url_r, const std::string & msg = "") + : MediaException(msg) + , _url(url_r.asString()), _msg(msg) + {} + ~MediaForbiddenException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _msg; + }; + + class ZYPP_API MediaTimeoutException : public MediaException + { + public: + MediaTimeoutException(const Url & url_r, const std::string & msg = "") + : MediaException(msg) + , _url(url_r.asString()), _msg(msg) + {} + ~MediaTimeoutException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _msg; + }; + + class ZYPP_API MediaFileSizeExceededException : public MediaException + { + public: + MediaFileSizeExceededException(const Url & url_r, const ByteCount &cnt_r, const std::string & msg = "") + : MediaException(msg) + , _url(url_r.asString()) + , _msg(msg) + , _expectedFileSize(cnt_r) + {} + ~MediaFileSizeExceededException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _msg; + ByteCount _expectedFileSize; + }; + + /** For HTTP 503 and similar. */ + class ZYPP_API MediaTemporaryProblemException : public MediaException + { + public: + MediaTemporaryProblemException(const Url & url_r, const std::string & msg = "") + : MediaException(msg) + , _url(url_r.asString()), _msg(msg) + {} + ~MediaTemporaryProblemException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _msg; + }; + + class ZYPP_API MediaBadCAException : public MediaException + { + public: + MediaBadCAException(const Url & url_r, const std::string & msg = "") + : MediaException(msg) + , _url(url_r.asString()), _msg(msg) + {} + ~MediaBadCAException() noexcept override {} + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + std::string _url; + std::string _msg; + }; + + class ZYPP_API MediaInvalidCredentialsException : public MediaException + { + public: + MediaInvalidCredentialsException( const std::string & msg = "" ) + : MediaException(msg) + {} + ~MediaInvalidCredentialsException() noexcept override {} + }; + + class ZYPP_API MediaRequestCancelledException : public MediaException + { + public: + MediaRequestCancelledException( const std::string & msg = "" ) + : MediaException(msg) + {} + ~MediaRequestCancelledException() noexcept override {} + }; + + ///////////////////////////////////////////////////////////////// + } // namespace media +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_MEDIA_MEDIAEXCEPTION_H diff --git a/zypp-media/mount.cc b/zypp-media/mount.cc new file mode 100644 index 0000000..62cb608 --- /dev/null +++ b/zypp-media/mount.cc @@ -0,0 +1,276 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/Mount.cc + * +*/ + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +#ifndef N_ +#define N_(STR) STR +#endif + + +namespace zypp { + namespace media { + + std::ostream & operator<<( std::ostream & str, const MountEntry & obj ) + { + str << obj.src << " on " << obj.dir << " type " << obj.type; + if ( ! obj.opts.empty() ) + str << " (" << obj.opts << ")"; + return str; + } + + + +bool MountEntry::isBlockDevice() const +{ + PathInfo dev_info; + return ( str::hasPrefix( Pathname(src).asString(), "/dev/" ) && dev_info(src) && dev_info.isBlk() ); +} + +Mount::Mount() +{} + +Mount::~Mount() +{} + +void Mount::mount( const std::string & source, + const std::string & target, + const std::string & filesystem, + const std::string & options, + const Environment & environment) +{ + const char *const argv[] = { + "/bin/mount", + "-t", filesystem.c_str(), + "-o", options.c_str(), + source.c_str(), + target.c_str(), + NULL + }; + + std::string err; // Error summary + std::string value; // legacy: Exception collects just the last output line + ExternalProgram prog { argv, environment, ExternalProgram::Stderr_To_Stdout, false, -1, true }; + for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() ) { + output[output.size()-1] = '\0'; // clip tailing NL + value = std::move( output ); + DBG << "stdout: " << value << endl; + + if ( value.find( "is already mounted on" ) != std::string::npos ) { + err = "Media already mounted"; + } + else if ( value.find( "ermission denied" ) != std::string::npos ) { + err = "Permission denied"; + } + else if ( value.find( "wrong fs type" ) != std::string::npos ) { + err = "Invalid filesystem on media"; + } + else if ( value.find( "No medium found" ) != std::string::npos ) { + err = "No medium found"; + } + else if ( value.find( "Not a directory" ) != std::string::npos ) { + if ( filesystem == "nfs" || filesystem == "nfs4" ) { + err = "NFS path is not a directory"; + } + else { + err = "Unable to find directory on the media"; + } + } + } + int exitCode = prog.close(); + + if ( exitCode != 0 ) { + if ( err.empty() ) err = "Mounting media failed"; + WAR << "mount " << source << " " << target << ": " << exitCode << ": " << err << endl; + ZYPP_THROW(MediaMountException(err, source, target, value)); + } + else + MIL << "mounted " << source << " " << target << endl; +} + +void Mount::umount( const std::string & path ) +{ + const char *const argv[] = { + "/bin/umount", + path.c_str(), + NULL + }; + + std::string err; // Error summary + int exitCode = -1; + + bool doRetry = false; + unsigned numRetry = 2; + do { + if ( doRetry ) { + if ( numRetry-- ) { + WAR << "umount " << path << ": " << exitCode << ": " << err << " - retrying in 1 sec." << endl; + sleep( 1 ); + err.clear(); + doRetry = false; + } + else { + WAR << "umount " << path << ": " << exitCode << ": " << err << " - giving up" << endl; + break; + } + } + + ExternalProgram prog { argv, ExternalProgram::Stderr_To_Stdout, false, -1, true }; + for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() ) { + output.pop_back(); // clip tailing NL + DBG << "stdout: " << output << endl; + + if ( output.find ( " is busy" ) != std::string::npos ) { // 'device|target is busy' + err = "Device is busy"; + doRetry = true; + } + } + exitCode = prog.close(); + + } while( exitCode != 0 && doRetry ); + + if ( exitCode != 0 ) { + if ( err.empty() ) err = "Unmounting media failed"; + WAR << "umount " << path << ": " << exitCode << ": " << err << endl; + ZYPP_THROW(MediaUnmountException(err, path)); + } + else + MIL << "unmounted " << path << endl; +} + +// STATIC +MountEntries +Mount::getEntries(const std::string &mtab) +{ + MountEntries entries; + std::vector mtabs; + bool verbose = false; + + if( mtab.empty()) + { + mtabs.push_back("/proc/mounts"); + // Also read /etc/mtab if it is a file (on newer sytems + // mtab is a symlink to /proc/mounts). + // Reason for this is the different representation of + // mounted loop devices: + // /etc/mtab: /tmp/SLES-11-SP2-MINI-ISO-x86_64-Beta2-DVD.iso on /mnt type iso9660 (ro,loop=/dev/loop0) + // /proc/mounts: /dev/loop0 /mnt iso9660 ro,relatime 0 0 + if ( PathInfo( "/etc/mtab", PathInfo::LSTAT ).isFile() ) + mtabs.push_back("/etc/mtab"); + } + else + { + mtabs.push_back(mtab); + } + + std::vector::const_iterator t; + for( t=mtabs.begin(); t != mtabs.end(); ++t) + { + if( verbose) + { + DBG << "Reading mount table from '" << *t << "'" << std::endl; + } + FILE *fp = setmntent(t->c_str(), "re"); + if( fp) + { + char buf[PATH_MAX * 4]; + struct mntent ent; + + memset(buf, 0, sizeof(buf)); + memset(&ent, 0, sizeof(ent)); + + while( getmntent_r(fp, &ent, buf, sizeof(buf)) != NULL) + { + if( ent.mnt_fsname && *ent.mnt_fsname && + ent.mnt_dir && *ent.mnt_dir && + ent.mnt_type && *ent.mnt_type && + ent.mnt_opts && *ent.mnt_opts) + { + MountEntry entry( + ent.mnt_fsname, ent.mnt_dir, + ent.mnt_type, ent.mnt_opts, + ent.mnt_freq, ent.mnt_passno + ); + + // Attempt quick fix for bnc#710269: + // MountEntry is "//dist/install/ on /var/adm/mount/AP_0x00000001 type cifs (ro,relatime,unc=\dist\install,username=,domain=suse.de" + // but looking for "Looking for media(cifs)attached(*/var/adm/mount/AP_0x00000001)" + // Kick the trailing '/' in "//dist/install/" + // TODO: Check and fix comparison in MediaHandler::checkAttached instead. + if ( entry.src.size() > 1 // not for "/" + && entry.src[entry.src.size()-1] == '/' ) + { + entry.src.erase( entry.src.size()-1 ); + } + entries.push_back(entry); + + memset(buf, 0, sizeof(buf)); + memset(&ent, 0, sizeof(ent)); + } + } + endmntent(fp); + + if( entries.empty()) + { + WAR << "Unable to read any entry from the mount table '" << *t << "'" + << std::endl; + } + else + { + // OK, have a non-empty mount table. + t = mtabs.end(); + break; + } + } + else + { + int err = errno; + verbose = true; + WAR << "Failed to read the mount table '" << *t << "': " + << ::strerror(err) + << std::endl; + errno = err; + } + } + return entries; +} + +time_t Mount::getMTime() +{ + time_t mtime = zypp::PathInfo("/etc/mtab").mtime(); + if( mtime <= 0) + { + WAR << "Failed to retrieve modification time of '/etc/mtab'" + << std::endl; + } + return mtime; +} + + } // namespace media +} // namespace zypp diff --git a/zypp-media/mount.h b/zypp-media/mount.h new file mode 100644 index 0000000..1d07496 --- /dev/null +++ b/zypp-media/mount.h @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/Mount + * +*/ + +// -*- C++ -*- + +#ifndef ZYPP_MEDIA_MOUNT_H +#define ZYPP_MEDIA_MOUNT_H + +#include +#include +#include +#include + +#include +#include +#include + +namespace zypp { + namespace media { + + + /** + * A "struct mntent" like mount entry structure, + * but using std::strings. + */ + struct MountEntry + { + MountEntry(std::string source, + std::string target, + std::string fstype, + std::string options, + const int dumpfreq = 0, + const int passnum = 0) + : src(std::move(source)) + , dir(std::move(target)) + , type(std::move(fstype)) + , opts(std::move(options)) + , freq(dumpfreq) + , pass(passnum) + {} + + /** + * Returns true if the src part points to a block device in /dev + */ + bool isBlockDevice () const; + + std::string src; //!< name of mounted file system + std::string dir; //!< file system path prefix + std::string type; //!< filesystem / mount type + std::string opts; //!< mount options + int freq; //!< dump frequency in days + int pass; //!< pass number on parallel fsck + }; + + /** \relates MountEntry + * A vector of mount entries. + */ + using MountEntries = std::vector; + + /** \relates MountEntry Stream output */ + std::ostream & operator<<( std::ostream & str, const MountEntry & obj ); + + /** + * @short Interface to the mount program + */ + class Mount + { + public: + + /** + * For passing additional environment variables + * to mount + **/ + using Environment = ExternalProgram::Environment; + + /** + * Mount options. 'key' or 'key=value' pairs, separated by ',' + **/ + using Options = KVMap>; + + public: + + /** + * Create an new instance. + */ + Mount(); + + /** + * Clean up. + */ + ~Mount(); + + /** + * mount device + * + * @param source what to mount (e.g. /dev/hda3) + * @param target where to mount (e.g. /mnt) + * @param filesystem which filesystem to use (e.g. reiserfs) (-t parameter) + * @param options mount options (e.g. ro) (-o parameter) + * @param environment optinal environment to pass (e.g. PASSWD="sennah") + * + * \throws MediaException + * + */ + + void mount ( const std::string& source, + const std::string& target, + const std::string& filesystem, + const std::string& options, + const Environment& environment = Environment() ); + + /** umount device + * + * @param path device or mountpoint to umount + * + * \throws MediaException + * + * */ + void umount (const std::string& path); + + public: + + /** + * Return mount entries from /etc/mtab or /etc/fstab file. + * + * @param mtab The name of the (mounted) file system description + * file to read from. This file should be one /etc/mtab, + * /etc/fstab or /proc/mounts. Default is to read + * /proc/mounts and /etc/mtab in case is not a symlink + * to /proc/mounts. + * @returns A vector with mount entries or empty vector if reading + * or parsing of the mtab file(s) failed. + */ + static MountEntries + getEntries(const std::string &mtab = ""); + + /** + * Get the modification time of the /etc/mtab file. + * \return Modification time of the /etc/mtab file. + */ + static time_t getMTime(); + }; + + + } // namespace media +} // namespace zypp + +#endif diff --git a/zypp-media/ng/HeaderValueMap b/zypp-media/ng/HeaderValueMap new file mode 100644 index 0000000..c36a1e7 --- /dev/null +++ b/zypp-media/ng/HeaderValueMap @@ -0,0 +1 @@ +#include "headervaluemap.h" diff --git a/zypp-media/ng/LazyMediaHandle b/zypp-media/ng/LazyMediaHandle new file mode 100644 index 0000000..28a3aae --- /dev/null +++ b/zypp-media/ng/LazyMediaHandle @@ -0,0 +1 @@ +#include "lazymediahandle.h" diff --git a/zypp-media/ng/MediaVerifier b/zypp-media/ng/MediaVerifier new file mode 100644 index 0000000..4dce643 --- /dev/null +++ b/zypp-media/ng/MediaVerifier @@ -0,0 +1 @@ +#include "mediaverifier.h" diff --git a/zypp-media/ng/Provide b/zypp-media/ng/Provide new file mode 100644 index 0000000..f0da3a0 --- /dev/null +++ b/zypp-media/ng/Provide @@ -0,0 +1 @@ +#include "provide.h" diff --git a/zypp-media/ng/ProvideFwd b/zypp-media/ng/ProvideFwd new file mode 100644 index 0000000..adb64a2 --- /dev/null +++ b/zypp-media/ng/ProvideFwd @@ -0,0 +1 @@ +#include "zypp-media/ng/providefwd.h" diff --git a/zypp-media/ng/ProvideItem b/zypp-media/ng/ProvideItem new file mode 100644 index 0000000..723ce4d --- /dev/null +++ b/zypp-media/ng/ProvideItem @@ -0,0 +1 @@ +#include "provideitem.h" diff --git a/zypp-media/ng/ProvideRes b/zypp-media/ng/ProvideRes new file mode 100644 index 0000000..f51c6ba --- /dev/null +++ b/zypp-media/ng/ProvideRes @@ -0,0 +1 @@ +#include "provideres.h" diff --git a/zypp-media/ng/ProvideSpec b/zypp-media/ng/ProvideSpec new file mode 100644 index 0000000..3fa0e22 --- /dev/null +++ b/zypp-media/ng/ProvideSpec @@ -0,0 +1 @@ +#include "providespec.h" diff --git a/zypp-media/ng/attachedmediainfo.cc b/zypp-media/ng/attachedmediainfo.cc new file mode 100644 index 0000000..87be7ed --- /dev/null +++ b/zypp-media/ng/attachedmediainfo.cc @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +*/ +#include "private/attachedmediainfo_p.h" + +namespace zyppng { + + IMPL_PTR_TYPE( AttachedMediaInfo ) + + + AttachedMediaInfo::AttachedMediaInfo( const std::string &id, ProvideQueue::Config::WorkerType workerType, const zypp::Url &baseUrl, ProvideMediaSpec &spec ) + : AttachedMediaInfo( id, {}, workerType, baseUrl, spec ) + { } + + AttachedMediaInfo::AttachedMediaInfo( const std::string &id, ProvideQueueWeakRef backingQueue, ProvideQueue::Config::WorkerType workerType, const zypp::Url &baseUrl, const ProvideMediaSpec &mediaSpec , const std::optional &mnt ) + : _name(id) + , _backingQueue( std::move(backingQueue) ) + , _workerType( workerType ) + , _attachedUrl( baseUrl ) + , _spec( mediaSpec ) + , _localMountPoint( mnt ) + { + // idle on construction, since only the Provide has a reference atm + _idleSince = std::chrono::steady_clock::now(); + } + + void AttachedMediaInfo::setName(std::string &&name) + { + _name = std::move(name); + } + + const std::string &AttachedMediaInfo::name() const + { + return _name; + } + + void AttachedMediaInfo::unref_to(unsigned int refCnt) const { + // last reference is always owned by the Provide instance + if ( refCnt == 1 ) + _idleSince = std::chrono::steady_clock::now(); + } + + void AttachedMediaInfo::ref_to(unsigned int refCnt) const { + if ( _idleSince && refCnt > 1 ) _idleSince.reset(); + } + bool AttachedMediaInfo::isSameMedium(const std::vector &urls, const ProvideMediaSpec &spec) { + + const auto check = _spec.isSameMedium(spec); + if ( !zypp::indeterminate (check) ) + return (bool)check; + + // let the URL rule + return ( std::find( urls.begin(), urls.end(), _attachedUrl ) != urls.end() ); + } + +} diff --git a/zypp-media/ng/headervaluemap.cc b/zypp-media/ng/headervaluemap.cc new file mode 100644 index 0000000..49017a9 --- /dev/null +++ b/zypp-media/ng/headervaluemap.cc @@ -0,0 +1,247 @@ +#include "headervaluemap.h" +#include + +namespace zyppng { + + HeaderValueMap::Value HeaderValueMap::InvalidValue; + + HeaderValue::HeaderValue() + : _val ( new value_type() ) + {} + + HeaderValue::HeaderValue( const HeaderValue &other ) + : _val ( new value_type( *other._val ) ) + {} + + HeaderValue::HeaderValue( HeaderValue &&other ) noexcept + : _val ( new value_type( std::move(*other._val) ) ) + {} + + HeaderValue::HeaderValue( const bool val ) + : _val ( new value_type(val) ) + {} + + HeaderValue::HeaderValue( const int32_t val ) + : _val ( new value_type(val) ) + {} + + HeaderValue::HeaderValue( const int64_t val ) + : _val ( new value_type(val) ) + {} + + HeaderValue::HeaderValue( const std::string &val ) + : _val ( new value_type(val) ) + {} + + HeaderValue::HeaderValue(const char *val) + : HeaderValue( zypp::str::asString (val) ) + {} + + HeaderValue::HeaderValue( std::string &&val ) + : _val ( new value_type( std::move(val) ) ) + {} + + bool HeaderValue::valid() const + { + return ( _val->index () > 0 ); + } + + bool HeaderValue::isString() const + { + return std::holds_alternative(*_val); + } + + bool HeaderValue::isInt() const + { + return std::holds_alternative(*_val); + } + + bool HeaderValue::isInt64() const + { + return std::holds_alternative(*_val); + } + + bool HeaderValue::isBool() const + { + return std::holds_alternative(*_val); + } + + const std::string &HeaderValue::asString() const + { + return std::get(*_val); + } + + int32_t HeaderValue::asInt() const + { + return std::get(*_val); + } + + int64_t HeaderValue::asInt64() const + { + if ( std::holds_alternative(*_val) ) + return std::get( *_val ); + return std::get(*_val); + } + + bool HeaderValue::asBool() const + { + return std::get(*_val); + } + + HeaderValue::value_type &HeaderValue::asVariant() + { + return *_val; + } + + const HeaderValue::value_type &HeaderValue::asVariant() const + { + return *_val; + } + + HeaderValue &HeaderValue::operator=(const HeaderValue &other) + { + *_val = *other._val; + return *this; + } + + bool HeaderValue::operator==(const HeaderValue &other) const + { + return ( *_val == *other._val ); + } + + HeaderValue &HeaderValue::operator= ( HeaderValue &&other ) noexcept + { + *_val = std::move( *other._val ); + return *this; + } + + HeaderValue &HeaderValue::operator= ( const std::string &val ) + { + *_val = val; + return *this; + } + + HeaderValue &HeaderValue::operator= ( int32_t val ) + { + *_val = val; + return *this; + } + + HeaderValue &HeaderValue::operator= ( int64_t val ) + { + *_val = val; + return *this; + } + + HeaderValue &HeaderValue::operator= ( bool val ) + { + *_val = val; + return *this; + } + + + HeaderValueMap::HeaderValueMap( std::initializer_list init ) + : _values( std::move(init) ) + { } + + bool HeaderValueMap::contains(const std::string &key) const + { + return _values.count (key) > 0 && _values.at(key).size () > 0 ; + } + + void HeaderValueMap::set(const std::string &key, Value val) + { + auto i = _values.find (key); + if ( i == _values.end() ) { + _values.insert ( std::make_pair(key, std::vector{std::move(val)}) ); + } else { + i->second = std::vector{std::move(val)}; + } + } + + void HeaderValueMap::set( const std::string &key, std::vector val ) + { + auto i = _values.find (key); + if ( i == _values.end() ) { + _values.insert ( std::make_pair(key, std::move(val)) ); + } else { + i->second = std::move(val); + } + } + + void HeaderValueMap::add(const std::string &key, const Value &val) + { + auto i = _values.find (key); + if ( i == _values.end() ) { + _values.insert ( std::make_pair(key, std::vector{val}) ); + } else { + i->second.push_back(val); + } + } + + void HeaderValueMap::clear() + { + _values.clear(); + } + + HeaderValueMap::ValueMap::size_type HeaderValueMap::size() const noexcept + { + return _values.size(); + } + + std::vector &HeaderValueMap::values(const std::string &key) + { + return _values[key]; + } + + const std::vector &HeaderValueMap::values(const std::string &key) const + { + return _values.at(key); + } + + HeaderValueMap::Value HeaderValueMap::value ( const std::string_view &str, const HeaderValueMap::Value &defaultVal) const + { return value( std::string(str), defaultVal ); } + + HeaderValueMap::Value HeaderValueMap::value ( const std::string &str, const HeaderValueMap::Value &defaultVal) const + { + if ( !contains(str) || !_values.at(str).size() ) + return defaultVal; + return _values.at(str).back(); + } + + HeaderValueMap::Value &HeaderValueMap::operator[](const std::string &key) + { + if ( !contains(key) ) + return InvalidValue; + return _values[key].back(); + } + + HeaderValueMap::Value &HeaderValueMap::operator[]( const std::string_view &key ) + { + return (*this)[std::string(key)]; + } + + const HeaderValueMap::Value &HeaderValueMap::operator[]( const std::string &key ) const + { + if ( !contains(key) ) + return InvalidValue; + return _values.at(key).back(); + } + + const HeaderValueMap::Value &HeaderValueMap::operator[]( const std::string_view &key ) const + { + return (*this)[std::string(key)]; + } + + HeaderValueMap::const_iterator HeaderValueMap::erase(const const_iterator &i) + { + auto yi = _values.erase(i.base()); + return HeaderValueMap::const_iterator(yi); + } + + bool HeaderValueMap::erase(const std::string &key) + { + return ( _values.erase(key) > 0 ); + } + +} diff --git a/zypp-media/ng/headervaluemap.h b/zypp-media/ng/headervaluemap.h new file mode 100644 index 0000000..ae51d8d --- /dev/null +++ b/zypp-media/ng/headervaluemap.h @@ -0,0 +1,197 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_MEDIA_NG_HEADERVALUEMAP_H_INCLUDED +#define ZYPP_MEDIA_NG_HEADERVALUEMAP_H_INCLUDED + +#include +#include +#include +#include +#include + +namespace zyppng { + + class HeaderValue + { + public: + using value_type = std::variant; + + HeaderValue(); + + HeaderValue( const HeaderValue &other ); + HeaderValue( HeaderValue &&other ) noexcept; + + HeaderValue( const bool val ); + HeaderValue( const int32_t val ); + HeaderValue( const int64_t val ); + HeaderValue( std::string &&val ); + HeaderValue( const std::string &val ); + HeaderValue( const char *val ); + + bool valid () const; + + bool isString () const; + bool isInt () const; + bool isInt64 () const; + bool isDouble () const; + bool isBool () const; + + const std::string &asString () const; + int32_t asInt () const; + int64_t asInt64 () const; + bool asBool () const; + + value_type &asVariant (); + const value_type &asVariant () const; + + HeaderValue &operator= ( const HeaderValue &other ); + HeaderValue &operator= ( HeaderValue &&other ) noexcept; + HeaderValue &operator= ( const std::string &val ); + HeaderValue &operator= ( int32_t val ); + HeaderValue &operator= ( int64_t val ); + HeaderValue &operator= ( bool val ); + + bool operator== ( const HeaderValue &other ) const; + + private: + zypp::RWCOW_pointer _val; + }; + + class HeaderValueMap + { + public: + using Value = HeaderValue; + using ValueMap = std::map>; + + static Value InvalidValue; + + class const_iterator + : public boost::iterator_adaptor< + HeaderValueMap::const_iterator // Derived + , ValueMap::const_iterator // Base + , std::pair // Value + , boost::use_default // CategoryOrTraversal + , const std::pair // Reference + > + { + public: + const_iterator() + : const_iterator::iterator_adaptor_() {} + + explicit const_iterator( const ValueMap::const_iterator &val ) + { this->base_reference() = val; } + + const_iterator( const HeaderValueMap::const_iterator &other ) + : const_iterator::iterator_adaptor_( other.base() ) {} + + const std::string &key () const { + return this->base_reference()->first; + } + + const Value &value() const { + auto &l = base_reference ()->second; + if ( l.empty() ) { + return InvalidValue; + } + return l.back(); + } + + private: + friend class boost::iterator_core_access; + void increment() { + this->base_reference() = ++this->base_reference(); + } + + std::pair dereference() const + { + return std::pair( key(), value() ); + } + }; + + HeaderValueMap() = default; + HeaderValueMap( std::initializer_list init ); + + bool contains( const std::string &key ) const; + bool contains( const std::string_view &key ) const { + return contains(std::string(key)); + } + + void set( const std::string &key, Value val ); + void set( const std::string &key, std::vector val ); + void add( const std::string &key, const Value &val); + void clear (); + ValueMap::size_type size() const noexcept; + + std::vector &values ( const std::string &key ); + const std::vector &values ( const std::string &key ) const; + + std::vector &values ( const std::string_view &key ) { + return values( std::string(key) ); + } + + const std::vector &values ( const std::string_view &key ) const { + return values( std::string(key) ); + } + + /*! + * Returns the last entry with key \a str in the list of values + * or the default value specified in \a defaultVal + */ + Value value ( const std::string_view &str, const Value &defaultVal = Value() ) const; + Value value ( const std::string &str, const Value &defaultVal = Value() ) const; + + Value &operator[]( const std::string &key ); + Value &operator[]( const std::string_view &key ); + const Value &operator[]( const std::string &key ) const; + const Value &operator[]( const std::string_view &key ) const; + + const_iterator erase( const const_iterator &i ); + bool erase( const std::string &key ); + + const_iterator begin() const { + return const_iterator( _values.begin() ); + } + const_iterator end() const { + return const_iterator( _values.end() ); + } + + ValueMap::iterator beginList() { + return _values.begin(); + } + ValueMap::iterator endList() { + return _values.end(); + } + + ValueMap::const_iterator beginList() const { + return _values.begin(); + } + ValueMap::const_iterator endList() const { + return _values.end(); + } + + ValueMap::const_iterator cbeginList() const { + return _values.cbegin(); + } + ValueMap::const_iterator cendList() const { + return _values.cend(); + } + + private: + ValueMap _values; + }; +} + +namespace zypp { + template<> + inline zyppng::HeaderValue::value_type* rwcowClone( const zyppng::HeaderValue::value_type * rhs ) + { return new zyppng::HeaderValue::value_type(*rhs); } +} + + +#endif diff --git a/zypp-media/ng/lazymediahandle.h b/zypp-media/ng/lazymediahandle.h new file mode 100644 index 0000000..45897e0 --- /dev/null +++ b/zypp-media/ng/lazymediahandle.h @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_MEDIA_NG_LAZYMEDIAHANDLE_H +#define ZYPP_MEDIA_NG_LAZYMEDIAHANDLE_H + +#include +#include + + +namespace zyppng +{ + template < class ProvideType > + class LazyMediaHandle { + public: + using MediaHandle = typename ProvideType::MediaHandle; + using ParentType = ProvideType; + + friend ProvideType; + + LazyMediaHandle( Ref provider, std::vector urls, ProvideMediaSpec spec ) + : _sharedData( + std::make_shared( + std::move(provider) + ,std::move(urls) + ,std::move(spec) + )) + { } + + LazyMediaHandle(const LazyMediaHandle &) = default; + LazyMediaHandle(LazyMediaHandle &&) = default; + LazyMediaHandle &operator=(const LazyMediaHandle &) = default; + LazyMediaHandle &operator=(LazyMediaHandle &&) = default; + + const Ref &parent () const { + return _sharedData->_provider.lock(); + } + + /*! + * Returns the first mirror used for this lazy handle, + * otherwise returns a empty url. + */ + const zypp::Url &baseUrl() const { + if ( !_sharedData->_mediaHandle ) { + static zypp::Url invalidHandle; + if ( _sharedData->_urls.empty() ) + return invalidHandle; + return _sharedData->_urls.front(); + } else { + return _sharedData->_mediaHandle->baseUrl(); + } + } + + const std::vector &urls() const { + return _sharedData->_urls; + } + + std::optional handle () const { + return _sharedData->_mediaHandle; + } + + const ProvideMediaSpec &spec() const { + return _sharedData->_spec; + } + + const std::optional &localPath() const + { + static std::optional noHandle; + if ( !attached() ) + return noHandle; + return _sharedData->_mediaHandle.localPath(); + } + + bool attached() const { + return _sharedData->_mediaHandle.has_value(); + } + + private: + + struct Data { + Data(Ref &&provider, std::vector &&urls, + ProvideMediaSpec &&spec) + : _provider(std::move(provider)), _urls(std::move(urls)), + _spec(std::move(spec)) {} + + Data(const Data &) = delete; + Data(Data &&) = delete; + Data &operator=(const Data &) = delete; + Data &operator=(Data &&) = delete; + + WeakRef _provider; + std::vector _urls; + ProvideMediaSpec _spec; + std::optional _mediaHandle; + }; + Ref _sharedData; + }; +} + +#endif // ZYPP_MEDIA_NG_LAZYMEDIAHANDLE_H diff --git a/zypp-media/ng/mediaverifier.cc b/zypp-media/ng/mediaverifier.cc new file mode 100644 index 0000000..0251dc9 --- /dev/null +++ b/zypp-media/ng/mediaverifier.cc @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "mediaverifier.h" +#include +#include +#include +#include +#include +#include "private/providedbg_p.h" + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (SuseMediaDataVerifier); + + class SuseMediaDataVerifier : public MediaDataVerifier + { + public: + // MediaDataVerifier interface + bool valid() const override; + bool matches(const MediaDataVerifierRef &rhs) const override; + const std::string &mediaVendor() const override; + const std::string &mediaIdent() const override; + uint totalMedia() const override; + std::ostream &toStream(std::ostream &str) const override; + bool load( const zypp::Pathname &data ) override; + bool loadFromMedium(const zypp::filesystem::Pathname &data, uint expectedMediaNr ) override; + zypp::filesystem::Pathname mediaFilePath(uint mediaNr) const override; + MediaDataVerifierRef clone () const override; + std::string expectedAsUserString( uint mediaNr ) const override; + + private: + std::string _mediaVendor; + std::string _mediaIdent; + uint _totalMedia = 0; + }; + + zypp::Pathname SuseMediaDataVerifier::mediaFilePath(uint mediaNr) const + { + zypp::str::Format fmt { "/media.%d/media" }; + return (fmt % zypp::str::numstring( mediaNr )).asString(); + } + + bool SuseMediaDataVerifier::loadFromMedium( const zypp::filesystem::Pathname &data, uint expectedMediaNr ) + { + return load ( data / mediaFilePath(expectedMediaNr) ); + } + + bool SuseMediaDataVerifier::valid() const + { return ! (_mediaVendor.empty() || _mediaIdent.empty()); } + + bool SuseMediaDataVerifier::matches(const MediaDataVerifierRef &rhs) const + { + auto conv = std::dynamic_pointer_cast(rhs); + return conv && valid() && conv->_mediaVendor == _mediaVendor && conv->_mediaIdent == _mediaIdent; + } + + uint SuseMediaDataVerifier::totalMedia() const + { + return _totalMedia; + } + + std::ostream &SuseMediaDataVerifier::toStream( std::ostream &str ) const + { + return str << "[" << _mediaVendor << "|" << _mediaIdent << "/" << _totalMedia << "]"; + } + + bool SuseMediaDataVerifier::load( const zypp::Pathname &path_r ) + { + std::ifstream inp( path_r.c_str() ); + if ( !inp ) { + ERR << "Can't setup a SUSEMediaVerifier from file: " << path_r.asString() << std::endl; + return false; + } + getline( inp, _mediaVendor ); + getline( inp, _mediaIdent ); + std::string buffer; + getline( inp, buffer ); + zypp::str::strtonum( buffer, _totalMedia ); + //if ( !_totalMedia ) _totalMedia = 1; + // loaded but maybe not valid + return true; + } + + const std::string &SuseMediaDataVerifier::mediaIdent() const + { + return _mediaIdent; + } + + const std::string &SuseMediaDataVerifier::mediaVendor() const + { + return _mediaVendor; + } + + MediaDataVerifierRef SuseMediaDataVerifier::clone () const + { + return SuseMediaDataVerifierRef( new SuseMediaDataVerifier( *this ) ); + } + + std::string SuseMediaDataVerifier::expectedAsUserString( uint mediaNr ) const + { + // Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. + zypp::str::Format fmt { _("Expected medium %1%/%2% identified by file '%3%' with content:") }; + return zypp::str::Str() + << ( fmt % mediaNr % _totalMedia % mediaFilePath( mediaNr ) ) << "\n" + << " " << _mediaVendor << "\n" + << " " << _mediaIdent; + } + + MediaDataVerifier::MediaDataVerifier() noexcept + { } + + MediaDataVerifier::~MediaDataVerifier() + { } + + MediaDataVerifierRef MediaDataVerifier::createVerifier( const std::string &verifierType ) + { + if ( verifierType == "SuseMediaV1" ) { + return SuseMediaDataVerifierRef( new SuseMediaDataVerifier() ); + } + return nullptr; + } + + std::ostream &operator<<(std::ostream &str, const MediaDataVerifierRef &obj) + { + if ( obj ) + return obj->toStream(str); + return str << "[MediaVerifier: null]"; + } + +} diff --git a/zypp-media/ng/mediaverifier.h b/zypp-media/ng/mediaverifier.h new file mode 100644 index 0000000..81ca7b6 --- /dev/null +++ b/zypp-media/ng/mediaverifier.h @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_MEDIA_NG_MEDIAVERIFIER_H_INCLUDED +#define ZYPP_MEDIA_NG_MEDIAVERIFIER_H_INCLUDED + +#include +#include +#include + +namespace zypp { + namespace filesystem { + class Pathname; + } + using filesystem::Pathname; +} + +namespace zyppng { + + /*! + * The MediaDataVerifier is used to verify if a specific medium, e.g. a DVD, is the + * medium we actually need. Each verifier is defined by a verifier type and the data + * that is used to validate against the medium. + */ + class MediaDataVerifier + { + public: + + MediaDataVerifier() noexcept; + virtual ~MediaDataVerifier(); + + static MediaDataVerifierRef createVerifier ( const std::string &verifierType ); + + /** Data considered to be valid if we have vendor and ident. */ + virtual bool valid() const = 0; + + /** Whether \a rhs belongs to the same media set. */ + virtual bool matches( const MediaDataVerifierRef & rhs ) const = 0; + + /*! + * Returns the media vendor string + */ + virtual const std::string &mediaVendor() const = 0; + + /*! + * Returns the media ident string + */ + virtual const std::string &mediaIdent() const = 0; + + /*! + * Returns the total number of mediums in this set + */ + virtual uint totalMedia() const = 0; + + /*! + * Writes the mediaverifier data to stream + */ + virtual std::ostream & toStream ( std::ostream & str ) const = 0; + + /*! + * Load verification information from a given file, all media data must + * be storeable in a file so that the controller can store a copy of it somewhere. + */ + virtual bool load( const zypp::Pathname &data ) = 0; + + /*! + * Generates the file information from a mounted medium, the path given in \a data + * is the mountpoint of the device. + */ + virtual bool loadFromMedium( const zypp::Pathname &data, uint mediaNr ) = 0; + + /*! + * Returns the path of the media identifier file on the medium + */ + virtual zypp::Pathname mediaFilePath ( uint mediaNr ) const = 0; + + /*! + * Clones \a this and returns a reference to the clone + */ + virtual MediaDataVerifierRef clone () const = 0; + + /*! + * Returns a error string describing the expected medium. + */ + virtual std::string expectedAsUserString( uint mediaNr = 1 ) const = 0; + }; + + /** \relates Stream output */ + std::ostream & operator<<( std::ostream & str, const MediaDataVerifierRef & obj ); + + + +} + +#endif diff --git a/zypp-media/ng/private/attachedmediainfo_p.h b/zypp-media/ng/private/attachedmediainfo_p.h new file mode 100644 index 0000000..4db69dd --- /dev/null +++ b/zypp-media/ng/private/attachedmediainfo_p.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_PRIVATE_ATTACHEDMEDIAINFO_P_H_INCLUDED +#define ZYPP_MEDIA_PRIVATE_ATTACHEDMEDIAINFO_P_H_INCLUDED + +#include "providefwd_p.h" +#include "providequeue_p.h" +#include "zypp-core/base/ReferenceCounted.h" +#include +#include +#include +#include + +namespace zyppng { + + class ProvidePrivate; + + DEFINE_PTR_TYPE(AttachedMediaInfo); + + class AttachedMediaInfo : public zypp::base::ReferenceCounted, private zypp::base::NonCopyable { + + protected: + void unref_to( unsigned int refCnt ) const override; + void ref_to( unsigned refCnt ) const override; + + public: + AttachedMediaInfo( const std::string &id, ProvideQueue::Config::WorkerType workerType, const zypp::Url &baseUrl, ProvideMediaSpec &spec ); + AttachedMediaInfo( const std::string &id, ProvideQueueWeakRef backingQueue, ProvideQueue::Config::WorkerType workerType, const zypp::Url &baseUrl, const ProvideMediaSpec &mediaSpec, const std::optional &mnt = {} ); + + void setName( std::string &&name ); + const std::string &name() const; + + /*! + * Returns true if \a other requests the same medium as this instance + */ + bool isSameMedium ( const std::vector &urls, const ProvideMediaSpec &spec ); + + std::string _name; + ProvideQueueWeakRef _backingQueue; //< if initialized contains a weak reference to the queue that owns this medium + ProvideQueue::Config::WorkerType _workerType; + zypp::Url _attachedUrl; // the URL that was used for the attach request + ProvideMediaSpec _spec; + std::optional _localMountPoint; // if initialized tells where the workers mounted to medium + mutable std::optional _idleSince; ///< Set if the medium is idle + }; + +} + +#endif diff --git a/zypp-media/ng/private/provide_p.h b/zypp-media/ng/private/provide_p.h new file mode 100644 index 0000000..01c224b --- /dev/null +++ b/zypp-media/ng/private/provide_p.h @@ -0,0 +1,150 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_PRIVATE_PROVIDE_P_H_INCLUDED +#define ZYPP_MEDIA_PRIVATE_PROVIDE_P_H_INCLUDED + +#include "providefwd_p.h" +#include "providequeue_p.h" +#include "attachedmediainfo_p.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + namespace constants { + constexpr std::string_view DEFAULT_PROVIDE_WORKER_PATH = ZYPP_WORKER_PATH; + constexpr std::string_view ATTACHED_MEDIA_SUFFIX = "-media"; + constexpr auto DEFAULT_ACTIVE_CONN_PER_HOST = 5; //< how many simultanious connections to the same host are allowed + constexpr auto DEFAULT_ACTIVE_CONN = 10; //< how many simultanious connections are allowed + constexpr auto DEFAULT_MAX_DYNAMIC_WORKERS = 20; + constexpr auto DEFAULT_CPU_WORKERS = 4; + } + + class ProvideQueue; + class ProvidePrivate : public BasePrivate + { + ZYPP_DECLARE_PUBLIC(Provide); + public: + ProvidePrivate( zypp::Pathname &&workDir, Provide &pub ); + + enum ScheduleReason + { + ProvideStart, + QueueIdle, + EnqueueItem, + EnqueueReq, + RestartAttach, + FinishReq + }; + + void schedule( ScheduleReason reason ); + + bool queueRequest ( ProvideRequestRef req ); + bool dequeueRequest( ProvideRequestRef req, std::exception_ptr error ); + void queueItem ( ProvideItemRef item ); + void dequeueItem ( ProvideItem *item ); + + std::string nextMediaId () const; + AttachedMediaInfo_Ptr addMedium ( AttachedMediaInfo_Ptr &&medium ); + + std::string effectiveScheme ( const std::string &scheme ) const; + + void onPulseTimeout ( Timer & ); + void onQueueIdle (); + void onItemStateChanged ( ProvideItem &item ); + expected schemeConfig(const std::string &scheme); + + std::optional addToFileCache ( const zypp::Pathname &downloadedFile ); + bool isInCache ( const zypp::Pathname &downloadedFile ) const; + + bool isRunning() const; + + const zypp::Pathname &workerPath() const; + const std::string queueName( ProvideQueue &q ) const; + + std::vector &attachedMediaInfos(); + + std::list &items(); + + zypp::media::CredManagerOptions &credManagerOptions (); + + std::vector sanitizeUrls ( const std::vector &urls ); + + ProvideStatusRef log () { + return _log; + } + + uint32_t nextRequestId(); + + Signal< Provide::MediaChangeAction ( const std::string &, const std::string &, const int32_t, const std::vector &, const std::optional &) > _sigMediaChange; + Signal< std::optional ( const zypp::Url &reqUrl, const std::string &triedUsername, const std::map &extraValues ) > _sigAuthRequired; + + protected: + void doSchedule (Timer &); + + //@TODO should we make those configurable? + std::unordered_map< std::string, std::string > _workerAlias { + {"ftp" ,"http"}, + {"tftp" ,"http"}, + {"https","http"}, + {"cifs" ,"smb" }, + {"nfs4" ,"nfs" }, + {"cd" ,"disc"}, + {"dvd" ,"disc"}, + {"file" ,"dir" }, + {"hd" ,"disk"} + }; + + bool _isRunning = false; + bool _isScheduling = false; + Timer::Ptr _pulseTimer = Timer::create(); + Timer::Ptr _scheduleTrigger = Timer::create(); //< instead of constantly calling schedule we set a trigger event so it runs as soon as event loop is on again + zypp::Pathname _workDir; + + std::list< ProvideItemRef > _items; //< The list of running provide Items, each of them can spawn multiple requests + uint32_t _nextRequestId = 0; //< The next request ID , we use controller wide unique IDs instead of worker locals IDs , its easier to track + + struct QueueItem { + std::string _schemeName; + std::deque _requests; + }; + std::deque _queues; //< List of request queues for the workers, grouped by scheme. We use a deque and not a map because of possible changes to the list of queues during scheduling + + + std::vector< AttachedMediaInfo_Ptr > _attachedMediaInfos; //< List of currently attached medias + + std::unordered_map< std::string, ProvideQueueRef > _workerQueues; + std::unordered_map< std::string, ProvideQueue::Config > _schemeConfigs; + + struct FileCacheItem { + zypp::ManagedFile _file; + std::optional _deathTimer; // timepoint where this item was seen first without a refcount + }; + std::unordered_map< std::string, FileCacheItem > _fileCache; + + zypp::Pathname _workerPath; + zypp::media::CredManagerOptions _credManagerOptions; + + ProvideStatusRef _log; + Signal _sigIdle; + }; +} + +#endif diff --git a/zypp-media/ng/private/providedbg_p.h b/zypp-media/ng/private/providedbg_p.h new file mode 100644 index 0000000..b5def83 --- /dev/null +++ b/zypp-media/ng/private/providedbg_p.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_NG_PROVIDEDBG_P_H_INCLUDED +#define ZYPP_MEDIA_NG_PROVIDEDBG_P_H_INCLUDED + +#include + +L_ENV_CONSTR_FWD_DECLARE_FUNC(ZYPP_MEDIA_PROVIDER_DEBUG) + +#ifdef ZYPP_BASE_LOGGER_LOGGROUP +#undef ZYPP_BASE_LOGGER_LOGGROUP +#endif + +#define ZYPP_BASE_LOGGER_LOGGROUP "ZYPP_MEDIA_PROVIDE" + +namespace zyppng { + inline bool provideDebugEnabled() { + return zypp::log::has_env_constr_ZYPP_MEDIA_PROVIDER_DEBUG(); + } +} + +#define XXX_PRV if( zyppng::provideDebugEnabled() ) XXX +#define DBG_PRV if( zyppng::provideDebugEnabled() ) DBG +#define MIL_PRV if( zyppng::provideDebugEnabled() ) MIL +#define WAR_PRV if( zyppng::provideDebugEnabled() ) WAR +#define ERR_PRV if( zyppng::provideDebugEnabled() ) ERR +#define SEC_PRV if( zyppng::provideDebugEnabled() ) SEC +#define INT_PRV if( zyppng::provideDebugEnabled() ) INT +#define USR_PRV if( zyppng::provideDebugEnabled() ) USR + + +#endif // ZYPP_MEDIA_NG_PROVIDEDBG_P_H_INCLUDED diff --git a/zypp-media/ng/private/providefwd_p.h b/zypp-media/ng/private/providefwd_p.h new file mode 100644 index 0000000..7ef0392 --- /dev/null +++ b/zypp-media/ng/private/providefwd_p.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_PRIVATE_PROVIDE_FWD_P_H_INCLUDED +#define ZYPP_MEDIA_PRIVATE_PROVIDE_FWD_P_H_INCLUDED + +#include +namespace zyppng { + ZYPP_FWD_DECL_TYPE_WITH_REFS(ProvideQueue); + ZYPP_FWD_DECL_TYPE_WITH_REFS(ProvideWorker); + ZYPP_FWD_DECL_TYPE_WITH_REFS(ProvideFileItem); + ZYPP_FWD_DECL_TYPE_WITH_REFS(AttachMediaItem); + ZYPP_FWD_DECL_TYPE_WITH_REFS(DetachMediaItem); + ZYPP_FWD_DECL_TYPE_WITH_REFS(ProvideRequest); + + class ProvideMessage; + + template< typename T > + class ProvidePromise; + template< typename T > + using ProvidePromiseRef = std::shared_ptr>; + template< typename T > + using ProvidePromiseWeakRef = std::weak_ptr>; +} + +#endif diff --git a/zypp-media/ng/private/provideitem_p.h b/zypp-media/ng/private/provideitem_p.h new file mode 100644 index 0000000..ea1aec4 --- /dev/null +++ b/zypp-media/ng/private/provideitem_p.h @@ -0,0 +1,206 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_PRIVATE_PROVIDE_ITEM_P_H_INCLUDED +#define ZYPP_MEDIA_PRIVATE_PROVIDE_ITEM_P_H_INCLUDED + +#include "providefwd_p.h" +#include "providequeue_p.h" +#include "attachedmediainfo_p.h" +#include "providemessage_p.h" +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + /*! + * The internal request type, which represents all possible + * user requests and exports some convenience functions for the scheduler to + * directly access relevant data + */ + class ProvideRequest { + public: + + friend class ProvideItem; + + static expected create( ProvideItem &owner, const std::vector &urls, const std::string &id, ProvideMediaSpec &spec ); + static expected create ( ProvideItem &owner, const std::vector &urls, ProvideFileSpec &spec ); + static expected createDetach( const zypp::Url &url ); + + ProvideItem * owner() { return _owner; } + + uint code () const { return _message.code(); } + + void setCurrentQueue ( ProvideQueueRef ref ); + ProvideQueueRef currentQueue (); + + const ProvideMessage &provideMessage () const { return _message; } + ProvideMessage &provideMessage () { return _message; } + + const std::optional activeUrl() const; + void setActiveUrl ( const zypp::Url &urlToUse ); + + void setUrls( const std::vector & urls ) { + _mirrors = urls; + } + + const std::vector &urls() const { + return _mirrors; + } + + zypp::Url url() const { + return _mirrors.front(); + } + + void setUrl( const zypp::Url & url ) { + _mirrors = {url}; + } + + void clearForRestart () { + _pastRedirects.clear(); + _activeUrl.reset(); + _myQueue.reset(); + } + + private: + ProvideRequest( ProvideItem *owner, const std::vector &urls, ProvideMessage &&msg ) : _owner(owner), _message(std::move(msg) ), _mirrors(urls) {} + ProvideItem *_owner = nullptr; // destructor of ProvideItem will dequeue the item, so no need to do refcount here + ProvideMessage _message; + std::vector _mirrors; + std::vector _pastRedirects; + std::optional _activeUrl; + ProvideQueueWeakRef _myQueue; + }; + + class ProvideItemPrivate : public BasePrivate + { + public: + ProvideItemPrivate( ProvidePrivate & parent, ProvideItem &pub ) : BasePrivate(pub), _parent(parent) {} + ProvidePrivate &_parent; + ProvideItem::State _itemState = ProvideItem::Uninitialized; + std::chrono::steady_clock::time_point _itemStarted; + std::chrono::steady_clock::time_point _itemFinished; + std::optional _prevStats; + std::optional _currStats; + Signal _sigStateChanged; + }; + + /*! + * The object returned to the user code to track the internal Item. + * Releasing the last reference to it will cancel the operation but the corresponding ProvideItem + * will remain in the Queue until the cancel operation was finished. + */ + template< typename T > + class ProvidePromise : public AsyncOp> + { + public: + ProvidePromise( ProvideItemRef provideItem ) + : _myProvide( provideItem ) + {} + + ~ProvidePromise() + { + auto prov = _myProvide.lock(); + if ( prov ) + prov->released(); + } + + private: + ProvideItemWeakRef _myProvide; //weak reference to the internal item so we can cancel the op on desctruction + }; + + /*! + * Item downloading and providing a file + */ + class ProvideFileItem : public ProvideItem + { + public: + + static ProvideFileItemRef create ( const std::vector &urls,const ProvideFileSpec &request, ProvidePrivate &parent ); + + // ProvideItem interface + void initialize () override; + ProvidePromiseRef promise(); + + void setMediaRef ( Provide::MediaHandle &&hdl ); + Provide::MediaHandle & mediaRef (); + + ItemStats makeStats () override; + zypp::ByteCount bytesExpected () const override; + + protected: + ProvideFileItem ( const std::vector &urls,const ProvideFileSpec &request, ProvidePrivate &parent ); + + void informalMessage ( ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg ) override; + + using ProvideItem::finishReq; + void finishReq ( ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg ) override; + void cancelWithError ( std::exception_ptr error ) override; + expected authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map &extraFields ) override; + + private: + Provide::MediaHandle _handleRef; //< If we are using a attached media, this will keep the reference around + bool _promiseCreated = false; + std::vector _mirrorList; //< All available URLs, first one is the primary + ProvideFileSpec _initialSpec; //< The initial spec as defined by the user code + zypp::Pathname _targetFile; //< The target file as reported by the worker + zypp::Pathname _stagingFile; //< The staging file as reported by the worker + zypp::ByteCount _expectedBytes; //< The nr of bytes we want to provide + ProvidePromiseWeakRef _promise; + }; + + + /*! + * Item attaching and verifying a medium + */ + class AttachMediaItem : public ProvideItem + { + public: + ~AttachMediaItem(); + static AttachMediaItemRef create ( const std::vector &urls, const ProvideMediaSpec &request, ProvidePrivate &parent ); + SignalProxy< void( const zyppng::expected & ) > sigReady (); + + ProvidePromiseRef promise(); + + protected: + AttachMediaItem ( const std::vector &urls, const ProvideMediaSpec &request, ProvidePrivate &parent ); + + // ProvideItem interface + void initialize () override; + + using ProvideItem::finishReq; + void finishReq ( ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg ) override; + void cancelWithError( std::exception_ptr error ) override; + void finishWithSuccess (AttachedMediaInfo_Ptr medium ); + expected authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map &extraFields ) override; + + void onMasterItemReady ( const zyppng::expected& result ); + + private: + Signal< void( const zyppng::expected & )> _sigReady; + bool _promiseCreated = false; + connection _masterItemConn; + std::vector _mirrorList; //< All available URLs, first one is the primary + ProvideMediaSpec _initialSpec; //< The initial spec as defined by the user code + ProvideQueue::Config::WorkerType _workerType = ProvideQueue::Config::Invalid; + ProvidePromiseWeakRef _promise; + MediaDataVerifierRef _verifier; + }; +} + +#endif diff --git a/zypp-media/ng/private/providemessage_p.h b/zypp-media/ng/private/providemessage_p.h new file mode 100644 index 0000000..4d76f2c --- /dev/null +++ b/zypp-media/ng/private/providemessage_p.h @@ -0,0 +1,596 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +*/ +#ifndef ZYPP_MEDIA_PRIVATE_PROVIDE_MESSAGE_P_H_INCLUDED +#define ZYPP_MEDIA_PRIVATE_PROVIDE_MESSAGE_P_H_INCLUDED + +#include +#include + +/*! + \internal + General: + ------- + This file contains the protocol definitions used in media worker backends. These backends are + used by zypp mainly to acquire files from different types of media via a generalized API. However, + it can also be used to implement helpers for special needs, e.g. copying files around or rewriting URLs. + + Every worker type is identified by the schema used in a URL e.g. dvd for getting files from DVDs or https for downloading. + This makes it possible to easily extend zypp with support for new schemes by implementing a new worker type without the need + to modify zypp itself. A important functionality is the possibility to redirect URLs to different workers, making it possible + to implement special schemes that need to remodel a URL in special ways before they are processed by the general backends. + + Communication Format: + --------------------- + Each message is serialized into a STOMP frame and sent over the communication medium. + STOMP is basically a HTTP like protocol, see https://stomp.github.io and \sa zypp::PluginFrame for details. + + Communication channel: + ---------------------- + Communication between the worker processes and the zypp main process will happen via the standard unix file descriptors: + stdin, stdout and stderr. stdin and stdout are used to send and receive messages between main and worker processes, while + stderr is used to output logging that is generated by the worker processes. These logs are forwarded to the main zypp log. + + The workers are supposed to shut down as soon as their stdin is closed. This is important to not block the controller process + that is waiting for this to happen, to fetch all log lines that are emitted by the worker when shutting down. + + + Worker Requirements: + -------------------- + Async communication: + Every worker needs to be able to handle messages asynchronously, the frontend will send requests to the worker as + they are given by the frontend code and does not apply any ordering. This means workers need to remember queries they sent to the frontend and manage + the code waiting for the result accordingly. The only exception to this is the handshake messages, where the frontend will always + send the worker configuration first, directly after spawning the worker process and the worker will answer with its capabilities. + Once those messages have been exchanged, zypp will start to send requests as defined below. + The frontend will buffer messages sent to the workers, so they do not need to keep the socket empty, however if possible workers should + support handling multiple requests. + + Cleaning up: + ------------ + A worker needs to maintain a mountpoint/download location as long as needed. Since only the frontend can decide when a location + is not required anymore it will send a "ReleaseResource" message with a worker generated ID that releases said ressource. + Examples for this are mountpoints that a worker created or download areas that were used by the worker to < the files to + + Worker Types: + ------------- + Currently zypp knows 4 different types of workers: + + * Downloading: Simplest type of worker that just download the files from a remote location without the need to mount something beforehand. + This is the simplest file provider that does not need to implement special functions. It is possible to freely redirect requests + between different variations of this worker type, all other types of workers do NOT support redirections. + Per remote host a own instance is started except if the SingleInstance flag is set. It is adviceable to set the SingleInstance flag on all + workers that do not do any long running requests. + + * Mounting: This type of worker needs to mount filesystems, but is not restricted by local volatile devices. For example smb, nfs, dir or even disk. + It has to additionally implement the Attach/Verify workflow. + Mounting handlers are always started as SingleInstance workers. + + * VolatileMounting: Most complex type of workers that mounts local devices that are volatile. This worker needs to also implement the device change workflow. + This type of worker exists only to implement the dvd worker. + VolatileMounting handlers are started as SingleInstance workers. + + * CPU Bound: Simple zypp internal workhorse type that can be implemented to run async processes like extracting a compressed file or creating a checksum. + For this type of worker a own instance per CPU is started on demand by default. + + Attach/Mount Workflow ( does not apply to Downloading and CPU bound worker types ) : + Each handler that marks itself as Mounting or VolatileMounting needs to implement the attach/mount workflow. This means that the controller needs to rely + on the handler to correctly mount and identify a medium. In the Attach message the controller may send media identification data and identification type to the worker + to specify the exact medium it is looking for. The worker then needs to mount the filesystem and perform the validation check, if the check succeeds the worker + will assign the unique attach point ID it has received from the contoller to the attachpoint and sends back a AttachResult containing the information. + At this point the worker needs to keep the mountpoint and attachpoint around until the controller sends a Detach request for it. + If the verification fails the worker will unmount the filesystem and send back a AttachResult message with the error bits set. + If the controller does not send verification data, every device/remoteFS that is successfully mounted is considered valid. + + After a medium was mounted the controller will send provide requests to the worker that have URLs formed like: + -media:///path/to/file. For example: dvd-media://1d6c0810-2bd6-45f3-9890-0268422a6f14/path/to/file , the attachID part is just a example, the controller uses + generates IDs that can be expressed as a URL hostname. + Another important aspect to keep in mind, is that a attach point is not the same as a mount point. Since a attach point additionally contains the path relative to the + filesystem root on the device. For example: the repository drivers is in a subdirectory of a dvd, so we'd get a attach request for the base url: dvd:/drivers, this would + result in a attachpoint id of "abcdef123" the device would be mounted in "/mnt/device". All subsequent requests are relative to the attachpoint and would look like: + dvd-media://abcdef123/file , which results in a lookup for the file: "/mnt/device/drivers/file1". + + Due to historical reasons a single device/filesystem can contain multiple mediums. So the worker needs to make sure to not unmount the filesystem too early. + For example dvd:/repo-1 and dvd:/repo-2 , both mediums are on the same disc, hence the worker will need to maintain two mount IDs and can only release the device itself + when both have been detached. + In some cases its even possible that multiple mediums reside in the same (sub)directory on a filesystem. For example when a multi DVD set was copied together into + one directory shared over NFS. + + + Message status codes + --------------------- + The response codes are roughtly modelled like HTTP status codes, they can happen during the full runtime of a certain request. + + Informational messages (100–199) + Success messages (200–299) + Redirection messages (300–399) + Client error messages (400–499) + Server error messages (500–599) + Controller messages (600–699) + Worker messages (700-799) + + + - Code: 100 - Provide started + Desc: Sent to the controller once a worker starts providing a request + Note that this is a optional message, its perfectly valid if 200 ( Provide Success ) is sent directly after the file was requested. + Fields: + required string url + string local_filename -> The local filename where the file will be provided to, used by the controller to track progress + string staging_filename -> The staging file used while downloading + + + - Code: 200 - Provide Finished + Desc: Sent to the controller once a worker finished a job successfully. + Fields: + required string local_filename -> The path where the worker has placed the file + required bool cacheHit -> Set to true if the file was found in a worker cache + + + - Code: 201 - Attach Finished + Desc: Sent to the controller once a worker mounted a medium successfully. + Fields: + optional string localMountPoint -> Where the device was locally mounted if applicable, e.g. http does not mount + + - Code: 202 - Auth Info + Desc: Response sent by the controller to a AUTH_REQUIRED request. + The last_auth_timestamp contains the last change of the auth database. This timestamp should be included + in successive AUTH_REQUIRED requests, so that the controller knows if its outdated or if the Auth was read from the store once + and now we need to ask the user to provide new auth info. + Fields: + required string username + required string password + required int64 auth_timestamp -> timestamp of the auth data, this should be stored in the worker in case it fails again + optional string authType -> comma seperated list of selected auth types, used by the network provider + + + - Code: 203 - Media changed + Desc: Sent to the worker once the user acknowledged a media change request + Fields: + - None - + + - Code: 204 - Detach Finished + Desc: Sent to the controller once a worker detached a medium successfully. + Fields: + - None - + + + - Code: 300 - Redirect + Desc: A Downloading worker can generate a Redirect message to reroute a request to a different + Downloading worker. This can be used to implement special handlers where a URL needs to be rewritten + before it can actually be fetched. + This is similar to sending a 200 - Provide Finished message since it will take the request out of the workers queue + + Note: Redirecting is ONLY supported between Downloading workers. Sending this message from other worker types + or redirecting to non Dowloading workers results in failing the user request with a redirect error. + Fields: + required string new_url -> the full URL we want to redirect to + + + - Code: 301 - Metalink Redirect + Desc: A worker can generate a list of mirrors, this is similar to a Redirect response but supports + giving the Controller a list of possible URLs to try. + This is similar to sending a 200 - Provide Finished message since it will take the request out of the workers queue. + The mirror list is ordered by priority, meaning the first mirror has the highest. + Fields: + repeated string new_url -> full URL we want to redirect to + + + + 4xx and 5xx messages, all of those messages have the same Response type structure: + + Code: 4xx / 5xx - Client error + Desc: Sent to the controller for requests that fail due to a client error + Fields: + required string reason -> The reason as a string + optional string history -> The error history that lead to the error + bool transient -> If this is set to true, the controller will try to request the file again at a later time + + Currently reserved error codes: + 400: Bad Request -> invalid request, the receiver can not process it + 401: Unauthorized -> no auth info avail but auth required + extraFields: string authHint + 402: Forbidden -> auth was given but failed or no access rights to the requested resource + extraFields: string authHint + 403: PeerCertificateInvalid -> the peer certificate validation failed + 404: Not Found -> the requested resource does not exist on the medium + 405: Expected Size Exceeded -> the downloaded data exceeded the requested maximum lenght + 406: Connection failed -> connecting to the server failed + 407: Timeout -> the request timed out + 408: Cancelled -> request was cancelled by the user + 409: Invalid checksum -> the downloaded data has a different checksum than expected + 410: Mount failed -> mounting the requested resource failed + 411: Jammed -> ATTACH request failed due to insufficient resources + 412: Media Change Abort -> User decided to abort the request + 413: Media Change Skip -> User decided to abort the request with a skip command( request will fail but will report "skipped" as the reason ) + 414: No Auth data -> Only sent by the controller for a 700 - Auth Data Request + 416: Media not desired -> The desired medium was not found on the given URL ( attach request ) + + 500: InternalError -> a error in the worker that is not recoverable, check reason string + + Controller -> Worker requests + ----------------------------- + + - Code: 600 - Provide + Desc: Message to tell the worker about a ressource it should provide + Fields: + required string url -> The URL of the request + string filename -> target filename hint, this is not required to be considered by the workers + string delta_file -> local path to a file that is supposed to be used for delta downloads + int64 expected_filesize -> The expected download filesize, workers should fail if a server does not reports the exact same filesize + bool check_existance_only -> this will NOT download the file but only query the server if its existant + bool metalink_enabled -> enables/disables metalink handling + + - Code: 601 - Cancel + Desc: Sent by the controller if a request should be cancelled. The worker should stop the given request and return a + 408 response. + Fields: + - None - + + - Code: 602 - Attach + Desc: If a worker signals the frontend it needs to mount/unmount resources the controller will first send a Attach + message for each base_url it encounters that targets the workers scheme. All workers that do not set this flag + do not need to care about this special message. + In fact receiving this message in a worker that is not a mounting type should result + in returning a error to the controller. + + If the verifyType field is NOT set, the verifyData field will be ignored and the worker does not need to + verify the device on the given location. + Fields: + required string url -> the base URL we want to attach to + required string attach_id -> controller generated ID string to uniquely identiy a attached medium + required string label -> Label of the medium + string verify_type -> name of the verification type, currently only suseV1 ( required if verify_data is present ) + bytes verify_data -> verification data ( required if verify_type is present ) + int32 media_nr -> the nr of the medium in the set ( required if verify_type is present ) + repeated string device -> optional field containing a device that can be used for attachment + + - Code: 603 - Detach + Desc: Send by the controller process when a medium is no longer required. + The worker has to immediately unmount the medium, no answer to the controller is expected. + Since there is no connected request, the request ID in this message will not be considered + Fields: + required string url -> the attachment URL containing the controller generated ID string to uniquely identify a attached medium, e.g. dvd:/// + + + Worker -> Controller requests + ----------------------------- + + - Code: 700 - Auth Data Request + Desc: In case a worker needs authorization info it can generate this request. + The last_auth_timestamp field is present if the request had received auth info before. + Fields: + required string effective_url -> the effective URL we want to fetch, this is not necessarily the same as the request URL + int64 last_auth_timestamp -> timestamp of previously received auth informationpJuds + optional string username -> username tried in the last auth attempt + optional string authHint -> comma seperated list of available authentication types + optional repeated string -> all other key:value pairs are treated as extra keys. + Possible Resposes: 414, 202 + + + - Code: 701 - Media Change Request + Desc: Generated by a worker to ask the user to insert a different medium. This will BLOCK the controller and the handler + until the user answered the request. This is a special request only used by the CDROM handler + Fields: + required string label -> name of the medium we need + required int32 media_nr -> which medium from the media set is required + required repeated string device -> free device to be used to insert the media into + string desc -> medium desc + Possible Resposes: 412, 413, 203 + +*/ + +#include +#include +#include +#include // for FieldType +#include + +#include + +namespace zypp::proto { + class Envelope; + class Configuration; + class Capabilities; + class ProvideMessage; +} + +namespace zyppng { + + enum MessageCodes : uint32_t { + NoCode = 0, + FirstInformalCode = 100, + ProvideStarted = 100, + LastInformalCode = 199, + + FirstSuccessCode = 200, + ProvideFinished = 200, + AttachFinished = 201, + AuthInfo = 202, + MediaChanged = 203, + DetachFinished = 204, + LastSuccessCode = 299, + + FirstRedirCode = 300, + Redirect = 300, + Metalink = 301, + LastRedirCode = 399, + + FirstClientErrCode = 400, + BadRequest = 400, + Unauthorized = 401, + Forbidden = 402, + PeerCertificateInvalid = 403, + NotFound = 404, + ExpectedSizeExceeded = 405, + ConnectionFailed = 406, + Timeout = 407, + Cancelled = 408, + InvalidChecksum = 409, + MountFailed = 410, + Jammed = 411, + MediaChangeAbort = 412, + MediaChangeSkip = 413, + NoAuthData = 414, + NotAFile = 415, + MediumNotDesired = 416, + LastClientErrCode = 499, + + FirstSrvErrCode = 500, + InternalError = 500, + ProtocolError = 501, + LastSrvErrCode = 599, + + FirstControllerCode = 600, + Prov = 600, + Cancel = 601, + Attach = 602, + Detach = 603, + LastControllerCode = 699, + + FirstWorkerCode = 700, + AuthDataRequest = 700, + MediaChangeRequest = 701, + LastWorkerCode = 799, + }; + + class ProviderConfiguration : public std::map + { + public: + using map::map; + + static constexpr std::string_view typeName = "ProviderConfiguration"; + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + }; + + class WorkerCaps + { + public: + /*! The worker type, see the description in Worker Types above */ + enum WorkerType : uint32_t { + Invalid = 0, + Downloading = 1, + SimpleMount = 2, + VolatileMount = 3, + CPUBound = 4, + }; + + enum Flags : uint32_t { + None = 0, // Just for completeness + SingleInstance = 1, // If this flag is set a worker can only be started once, this is implicit in some worker types. + Pipeline = 2, // The worker can handle multiple requests at the same time + ZyppLogFormat = 4, // The worker writes messages to stderr in zypp log format + FileArtifacts = 8, // The results of this worker are artifacts, which means they need to be cleaned up. This is implicit for all downloading workers. For all mounting workers this is ignored. + // CPU bound workers can use it to signal they leave artifact files behind that need to be cleaned up + }; + + explicit WorkerCaps(); + ~WorkerCaps(); + + WorkerCaps(const WorkerCaps &) = default; + WorkerCaps(WorkerCaps &&) = default; + WorkerCaps &operator=(const WorkerCaps &) = default; + WorkerCaps &operator=(WorkerCaps &&) = default; + + uint32_t protocol_version() const; // The workers should set this field to the protocol version they implement. + WorkerType worker_type() const; + Flags cfg_flags() const; + const std::string &worker_name() const; + + void set_protocol_version( uint32_t v ); + void set_worker_type( WorkerType t ); + void set_cfg_flags( Flags f ); + void set_worker_name( std::string name ); + + static constexpr std::string_view typeName = "WorkerCaps"; + zyppng::expected toStompMessage() const; + static zyppng::expected fromStompMessage( const zypp::PluginFrame &msg ); + + private: + uint32_t _protocolVersion = 1; + uint32_t _workerType = Invalid; + uint32_t _cfgFlags = None; + std::string _workerName; + }; + + namespace ProvideMessageFields { + constexpr std::string_view RequestCode("requestCode"); + constexpr std::string_view RequestId("requestId"); + } + + namespace ProvideStartedMsgFields + { + constexpr std::string_view Url ("url"); + constexpr std::string_view LocalFilename ("local_filename"); + constexpr std::string_view StagingFilename ("staging_filename"); + } + + namespace ProvideFinishedMsgFields + { + constexpr std::string_view LocalFilename ("local_filename"); + constexpr std::string_view CacheHit ("cacheHit"); + } + + namespace AuthInfoMsgFields + { + constexpr std::string_view Username ("username"); + constexpr std::string_view Password ("password"); + constexpr std::string_view AuthTimestamp ("auth_timestamp"); + constexpr std::string_view AuthType ("authType"); + } + + namespace RedirectMsgFields + { + constexpr std::string_view NewUrl ("new_url"); + } + + namespace MetalinkRedirectMsgFields + { + constexpr std::string_view NewUrl ("new_url"); + } + + namespace ErrMsgFields + { + constexpr std::string_view Reason ("reason"); + constexpr std::string_view Transient ("transient"); + constexpr std::string_view History ("history"); + } + + namespace ProvideMsgFields + { + constexpr std::string_view Url ("url"); + constexpr std::string_view Filename ("filename"); + constexpr std::string_view DeltaFile ("delta_file"); + constexpr std::string_view ExpectedFilesize ("expected_filesize"); + constexpr std::string_view CheckExistOnly ("check_existance_only"); + constexpr std::string_view MetalinkEnabled ("metalink_enabled"); + } + + namespace AttachMsgFields + { + constexpr std::string_view Url ("url"); + constexpr std::string_view AttachId ("attach_id"); + constexpr std::string_view VerifyType ("verify_type"); + constexpr std::string_view VerifyData ("verify_data"); + constexpr std::string_view MediaNr ("media_nr"); + constexpr std::string_view Device ("device"); + constexpr std::string_view Label ("label"); + } + + namespace AttachFinishedMsgFields + { + constexpr std::string_view LocalMountPoint ("local_mountpoint"); + } + + namespace DetachMsgFields + { + constexpr std::string_view Url ("url"); + } + + namespace AuthDataRequestMsgFields + { + constexpr std::string_view EffectiveUrl ("effective_url"); + constexpr std::string_view LastAuthTimestamp ("last_auth_timestamp"); + constexpr std::string_view LastUser ("username"); + constexpr std::string_view AuthHint ("authHint"); + } + + namespace MediaChangeRequestMsgFields + { + constexpr std::string_view Label ("label"); + constexpr std::string_view MediaNr ("media_nr"); + constexpr std::string_view Device ("device"); + constexpr std::string_view Desc ("desc"); + } + + namespace EjectMsgFields + { + constexpr std::string_view device ("device"); + } + + class ProvideMessage + { + public: + using Code = MessageCodes; + + ProvideMessage(const ProvideMessage &) = default; + ProvideMessage(ProvideMessage &&) = default; + ProvideMessage &operator=(const ProvideMessage &) = default; + ProvideMessage &operator=(ProvideMessage &&) = default; + using FieldVal = HeaderValue; + + static constexpr std::string_view typeName = "ProvideMessage"; + + static expected create ( const zypp::PluginFrame &message ); + expected toStompMessage() const; + static expected fromStompMessage( const zypp::PluginFrame &msg ); + + static ProvideMessage createProvideStarted ( const uint32_t reqId, const zypp::Url &url , const std::optional &localFilename = {}, const std::optional &stagingFilename = {} ); + static ProvideMessage createProvideFinished ( const uint32_t reqId, const std::string &localFilename , bool cacheHit ); + static ProvideMessage createAttachFinished ( const uint32_t reqId, const std::optional &localMountPoint = {} ); + static ProvideMessage createDetachFinished ( const uint32_t reqId ); + static ProvideMessage createAuthInfo ( const uint32_t reqId, const std::string &user, const std::string &pw, int64_t timestamp, const std::map &extraValues = {} ); + static ProvideMessage createMediaChanged ( const uint32_t reqId ); + static ProvideMessage createRedirect ( const uint32_t reqId, const zypp::Url &newUrl ); + static ProvideMessage createMetalinkRedir ( const uint32_t reqId, const std::vector &newUrls ); + static ProvideMessage createErrorResponse (const uint32_t reqId, const Code code, const std::string &reason, bool transient = false ); + + static ProvideMessage createProvide ( const uint32_t reqId + , const zypp::Url &url + , const std::optional &filename = {} + , const std::optional &deltaFile = {} + , const std::optional &expFilesize = {} + , bool checkExistOnly = false ); + + static ProvideMessage createCancel ( const uint32_t reqId ); + + static ProvideMessage createAttach( const uint32_t reqId + , const zypp::Url &url + , const std::string attachId + , const std::string &label + , const std::optional &verifyType = {} + , const std::optional &verifyData = {} + , const std::optional &mediaNr = {} ); + + static ProvideMessage createDetach ( const uint32_t reqId, const zypp::Url &attachUrl ); + static ProvideMessage createAuthDataRequest ( const uint32_t reqId, const zypp::Url &effectiveUrl, const std::string &lastTriedUser ="", const std::optional &lastAuthTimestamp = {}, const std::map &extraValues = {} ); + static ProvideMessage createMediaChangeRequest ( const uint32_t reqId, const std::string &label, int32_t mediaNr, const std::vector &devices, const std::optional &desc ); + + uint requestId () const; + void setRequestId ( const uint id ); + + Code code() const; + void setCode (const Code newCode ); + + const std::vector &values ( const std::string_view &str ) const; + const std::vector &values ( const std::string &str ) const; + const HeaderValueMap &headers() const; + /*! + * Returns the last entry with key \a str in the list of values + * or the default value specified in \a defaultVal + */ + FieldVal value ( const std::string_view &str, const FieldVal &defaultVal = FieldVal() ) const; + FieldVal value ( const std::string &str, const FieldVal &defaultVal = FieldVal() ) const; + void setValue ( const std::string &name, const FieldVal &value ); + void setValue ( const std::string_view &name, const FieldVal &value ); + void addValue ( const std::string &name, const FieldVal &value ); + void addValue ( const std::string_view &name, const FieldVal &value ); + + private: + ProvideMessage(); + uint _reqId = -1; + Code _code = NoCode; + HeaderValueMap _headers; + }; +} + +#endif diff --git a/zypp-media/ng/private/providequeue_p.h b/zypp-media/ng/private/providequeue_p.h new file mode 100644 index 0000000..0c06b39 --- /dev/null +++ b/zypp-media/ng/private/providequeue_p.h @@ -0,0 +1,143 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_PRIVATE_PROVIDE_QUEUE_P_H_INCLUDED +#define ZYPP_MEDIA_PRIVATE_PROVIDE_QUEUE_P_H_INCLUDED + +#include "providefwd_p.h" +#include "providemessage_p.h" +#include +#include +#include + +#include +#include + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (StompFrameStream); + + class ProvideQueue : public Base + { + public: + friend struct ProvideResourceData; + + static constexpr uint32_t InvalidId = (uint32_t) -1; + using Config = zyppng::WorkerCaps; + + using TimePoint = std::chrono::time_point; + + struct Item { + + enum State { + Pending, + Queued, + Running, + Cancelling, + Finished + }; + State _state = Pending; + bool isAttachRequest () const; + bool isFileRequest () const; + bool isDetachRequest() const; + + ProvideRequestRef _request; + }; + + ProvideQueue( ProvidePrivate &parent ); + ~ProvideQueue(); + bool startup ( const std::string &workerScheme, const zypp::Pathname &workDir, const std::string &hostname = "" ); + void enqueue ( ProvideRequestRef request ); + void cancel ( ProvideRequest *item, std::exception_ptr error ); + void detach ( const std::string &id ); + void scheduleNext (); + bool canScheduleMore () const;; + bool empty () const; + + /*! + * Check if the queue is currently idle + */ + bool isIdle () const; + + /*! + * Time point since the queue started to be idle + */ + std::optional idleSince () const; + + /*! + * How many items does this queue currently have + */ + uint requestCount () const; + + /*! + * How many active items does this queue currently have + */ + uint activeRequests () const; + + /*! + * How much bytes does this queue has to download / process, + * for pending requests this is only set if the \ref ProvideSpec + * has a expected download size set. + */ + zypp::ByteCount expectedProvideSize() const; + + /*! + * Returns the hostname this worker belongs to. + * If the worker was not associated with a hostname this will return a empty string. + */ + const std::string &hostname () const; + + const Config &workerConfig () const; + + SignalProxy sigIdle(); + + private: + bool doStartup (); + void processMessage ( ); + void readAllStderr (); + void forwardToLog ( std::string &&logLine ); + void processReadyRead( int channel ); + void procFinished ( int exitCode ); + uint32_t nextRequestId(); + + /*! + * Dequeues the request referenced by \a it. + * Returns a iterator to the next element in the active list + */ + std::list< ProvideQueue::Item >::iterator dequeueActive ( std::list::iterator it ); + void fatalWorkerError ( const std::exception_ptr &reason = nullptr ); + void immediateShutdown ( const std::exception_ptr &reason ); + + /*! + * Cancels the item the iterator \a i is pointing to, advancing the iterator to the next element in the list + */ + std::list< ProvideQueue::Item >::iterator cancelActiveItem (std::list::iterator i, const std::exception_ptr &error ); + + private: + bool _queueShuttingDown = false; + uint8_t _crashCounter = 0; + Config _capabilities; + zypp::Pathname _currentExe; + std::string _myHostname; + ProvidePrivate &_parent; + std::deque< Item > _waitQueue; + std::list< Item > _activeItems; + Process::Ptr _workerProc; + StompFrameStreamRef _messageStream; + Signal _sigIdle; + std::optional _idleSince; + }; + +} + +#endif diff --git a/zypp-media/ng/private/provideres_p.h b/zypp-media/ng/private/provideres_p.h new file mode 100644 index 0000000..b129043 --- /dev/null +++ b/zypp-media/ng/private/provideres_p.h @@ -0,0 +1,23 @@ +#ifndef ZYPP_MEDIA_PRIVATE_PROVIDERES_P_H +#define ZYPP_MEDIA_PRIVATE_PROVIDERES_P_H + +#include +#include +#include +#include +#include "providefwd_p.h" + +namespace zyppng { + /*! + * \internal + * The internal shared data structure for \sa ProvideRes objects. + */ + struct ProvideResourceData { + zyppng::Provide::MediaHandle _mediaHandle; + zypp::ManagedFile _myFile; + zypp::Url _resourceUrl; //< The resource where the file was provided from + HeaderValueMap _responseHeaders; //< The response headers + }; +} + +#endif // ZYPP_MEDIA_PRIVATE_PROVIDERES_P_H diff --git a/zypp-media/ng/provide-configvars.h b/zypp-media/ng/provide-configvars.h new file mode 100644 index 0000000..54eccd9 --- /dev/null +++ b/zypp-media/ng/provide-configvars.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_MEDIA_PROVIDE_CONFIGVARS_H_INCLUDED +#define ZYPP_MEDIA_PROVIDE_CONFIGVARS_H_INCLUDED + +#include + +namespace zyppng { + // special config strings sent to the workers: + constexpr std::string_view AGENT_STRING_CONF("zconfig://media/UserAgent"); + constexpr std::string_view DISTRO_FLAV_CONF("zconfig://media/DistributionFlavor"); + constexpr std::string_view ANON_ID_CONF("zconfig://media/AnonymousId"); + constexpr std::string_view ATTACH_POINT("zconfig://media/AttachPoint"); + constexpr std::string_view PROVIDER_ROOT("zconfig://media/ProviderRoot"); + + + // request related settings: + constexpr std::string_view NETWORK_METALINK_ENABLED("zypp-nw-metalink-enabled"); //< Enable or disable metalink for a specific request + constexpr std::string_view HANDLER_SPECIFIC_DEVICES("zypp-req-specific-devices"); //< Limit the request to a set of devices. Devices are comma seperated. +} + +#endif diff --git a/zypp-media/ng/provide.cc b/zypp-media/ng/provide.cc new file mode 100644 index 0000000..72b9acd --- /dev/null +++ b/zypp-media/ng/provide.cc @@ -0,0 +1,1321 @@ +#include "private/provide_p.h" +#include "private/providedbg_p.h" +#include "private/providequeue_p.h" +#include "private/provideitem_p.h" +#include +#include +#include +#include +#include +#include +#include + +// required to generate uuids +#include + + +L_ENV_CONSTR_DEFINE_FUNC(ZYPP_MEDIA_PROVIDER_DEBUG) + +namespace zyppng { + + ProvidePrivate::ProvidePrivate(zypp::filesystem::Pathname &&workDir, Provide &pub) + : BasePrivate(pub) + , _workDir( std::move(workDir) ) + , _workerPath( constants::DEFAULT_PROVIDE_WORKER_PATH.data() ) + { + if ( _workDir.empty() ) { + _workDir = zypp::Pathname(".").realpath(); + } else { + _workDir = _workDir.realpath(); + } + + MIL << "Provider workdir is: " << _workDir << std::endl; + + _scheduleTrigger->setSingleShot(true); + Base::connect( *_scheduleTrigger, &Timer::sigExpired, *this, &ProvidePrivate::doSchedule ); + } + + void ProvidePrivate::schedule( ScheduleReason reason ) + { + if ( provideDebugEnabled () ) { + std::string_view reasonStr; + switch( reason ) { + case ProvideStart: + reasonStr = "ProvideStart"; + break; + case QueueIdle: + reasonStr = "QueueIdle"; + break; + case EnqueueItem: + reasonStr = "EnqueueItem"; + break; + case EnqueueReq: + reasonStr = "EnqueueReq"; + break; + case FinishReq: + reasonStr = "FinishReq"; + break; + case RestartAttach: + reasonStr = "RestartAttach"; + break; + } + DBG << "Triggering the schedule timer (" << reasonStr << ")" << std::endl; + } + + // we use a single shot timer that instantly times out when the event loop is entered the next time + // this way we compress many schedule requests that happen during a eventloop run into one + _scheduleTrigger->start(0); + } + + void ProvidePrivate::doSchedule ( zyppng::Timer & ) + { + if ( !_isRunning ) { + MIL << "Provider is not started, NOT scheduling" << std::endl; + return; + } + + if ( _isScheduling ) { + DBG_PRV << "Scheduling triggered during scheduling, returning immediately." << std::endl; + return; + } + + const int cpuLimit = +#ifdef _SC_NPROCESSORS_ONLN + sysconf(_SC_NPROCESSORS_ONLN) * 2; +#else + DEFAULT_CPU_WORKERS; +#endif + + // helper lambda to find the worker that is idle for the longest time + constexpr auto findLaziestWorker = []( const auto &workerQueues, const auto &idleNames ) { + auto candidate = workerQueues.end(); + ProvideQueue::TimePoint candidateIdleSince = ProvideQueue::TimePoint::max(); + + //find the worker thats idle the longest + for ( const auto &name : idleNames ) { + auto thisElem = workerQueues.find(name); + if ( thisElem == workerQueues.end() ) + continue; + + const auto idleS = thisElem->second->idleSince(); + if ( idleS + && ( candidate == workerQueues.end() || *idleS < candidateIdleSince ) ) { + candidateIdleSince = *idleS; + candidate = thisElem; + } + } + + if ( candidate != workerQueues.end() ) + MIL_PRV << "Found idle worker:" << candidate->first << " idle since: " << candidateIdleSince.time_since_epoch().count() << std::endl; + + return candidate; + }; + + // clean up old media + + for ( auto iMedia = _attachedMediaInfos.begin(); iMedia != _attachedMediaInfos.end(); ) { + if ( (*iMedia)->refCount() > 1 ) { + MIL_PRV << "Not releasing media " << (*iMedia)->_name << " refcount is not zero" << std::endl; + ++iMedia; + continue; + } + if ( (*iMedia)->_workerType == ProvideQueue::Config::Downloading ) { + // we keep the information around for an hour so we do not constantly download the media files for no reason + if ( (*iMedia)->_idleSince && std::chrono::steady_clock::now() - (*iMedia)->_idleSince.value() >= std::chrono::hours(1) ) { + MIL << "Detaching medium " << (*iMedia)->_name << " for baseUrl " << (*iMedia)->_attachedUrl << std::endl; + iMedia = _attachedMediaInfos.erase(iMedia); + continue; + } else { + MIL_PRV << "Not releasing media " << (*iMedia)->_name << " downloading worker and not timed out yet." << std::endl; + } + } else { + // mounting handlers, we need to send a request to the workers + auto bQueue = (*iMedia)->_backingQueue.lock(); + if ( bQueue ) { + zypp::Url url = (*iMedia)->_attachedUrl; + url.setScheme( url.getScheme() + std::string( constants::ATTACHED_MEDIA_SUFFIX) ); + url.setAuthority( (*iMedia)->_name ); + const auto &req = ProvideRequest::createDetach( url ); + if ( req ) { + MIL << "Detaching medium " << (*iMedia)->_name << " for baseUrl " << (*iMedia)->_attachedUrl << std::endl; + bQueue->enqueue ( *req ); + iMedia = _attachedMediaInfos.erase(iMedia); + continue; + } else { + ERR << "Could not send detach request, creating the request failed" << std::endl; + } + } else { + ERR << "Could not send detach request since no backing queue was defined" << std::endl; + } + } + ++iMedia; + } + + zypp::DtorReset schedFlag( _isScheduling, false ); + _isScheduling = true; + + const auto schedStart = std::chrono::steady_clock::now(); + MIL_PRV << "Start scheduling" << std::endl; + + zypp::OnScopeExit deferExitMessage( [&](){ + const auto dur = std::chrono::steady_clock::now() - schedStart; + MIL_PRV << "Exit scheduling after:" << std::chrono::duration_cast( dur ).count () << std::endl; + }); + + // bump inactive items + for ( auto it = _items.begin (); it != _items.end(); ) { + // was maybe released during scheduling + if ( !(*it) ) + it = _items.erase(it); + else { + auto &item = *it; + if ( item->state() == ProvideItem::Uninitialized ) { + item->initialize(); + } + it++; + } + } + + // we are scheduling now, everything that triggered the timer until now we can forget about + _scheduleTrigger->stop(); + + for( auto queueIter = _queues.begin(); queueIter != _queues.end(); queueIter ++ ) { + + const auto &scheme = queueIter->_schemeName; + auto &queue = queueIter->_requests; + + if ( !queue.size() ) + continue; + + const auto &configOpt = schemeConfig ( scheme ); + + MIL_PRV << "Start scheduling for scheme:" << scheme << " queue size is: " << queue.size() << std::endl; + + if ( !configOpt ) { + // FAIL all requests in this queue + ERR << "Scheme: " << scheme << " failed to return a valid configuration." << std::endl; + + while( queue.size() ) { + auto item = std::move( queue.front() ); + queue.pop_front(); + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to query scheme config.")) ); + } + + continue; + } + + // the scheme config that defines how we schedule requests on this set of queues + const auto &config = configOpt.get(); + const auto isSingleInstance = ( (config.cfg_flags() & ProvideQueue::Config::SingleInstance) == ProvideQueue::Config::SingleInstance ); + if ( config.worker_type() == ProvideQueue::Config::Downloading && !isSingleInstance ) { + + for( auto i = queue.begin (); i != queue.end(); ) { + + // this is the only place where we remove elements from the queue when the scheduling flag is active + // other code just nulls out requests in the queue if during scheduling items need to be removed + while ( i != queue.end() && !(*i) ) { + i = queue.erase(i); + } + + if ( i == queue.end() ) + break; + + ProvideRequestRef item = *i; + + // Downloading queues do not support attaching via a AttachRequest, this is handled by simply providing the media verification files + // If we hit this code path, its a bug + if( item->code() == ProvideMessage::Code::Attach || item->code() == ProvideMessage::Code::Detach ) { + i = queue.erase(i); + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR( zypp::Exception("Downloading Queues do not support ProvideMessage::Code::Attach requests") ) ); + continue; + } + + MIL_PRV << "Trying to schedule request: " << item->urls().front() << std::endl; + + // how many workers for this type do already exist + int existingTypeWorkers = 0; + + // how many currently active connections are there + int existingConnections = 0; + + // all currently available possible queues for the request + std::vector< std::pair > possibleHostWorkers; + + // currently idle workers + std::vector idleWorkers; + + // all mirrors without a existing worker + std::vector mirrsWithoutWorker; + for ( const auto &url : item->urls() ) { + + if ( effectiveScheme( url.getScheme() ) != scheme ) { + MIL << "Mirror URL " << url << " is incompatible with current scheme: " << scheme << ", ignoring." << std::endl; + continue; + } + + if( item->owner()->canRedirectTo( item, url ) ) + mirrsWithoutWorker.push_back( url ); + else { + MIL_PRV << "URL was rejected" << url << std::endl; + } + } + + // at this point the list contains all useable mirrors, if this list is empty the request needs to fail + if( mirrsWithoutWorker.size() == 0 ) { + MIL << "Request has NO usable URLs" << std::endl; + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR(zypp::media::MediaException("No usable URLs in request spec.")) ); + i = queue.erase(i); + continue; + } + + + for ( auto &[ queueName, workerQueue ] : _workerQueues ) { + if ( ProvideQueue::Config::Downloading != workerQueue->workerConfig().worker_type() ) + continue; + + existingTypeWorkers ++; + existingConnections += workerQueue->activeRequests(); + + if ( workerQueue->isIdle() ) + idleWorkers.push_back (queueName); + + if ( !zypp::str::startsWith( queueName, scheme ) ) + continue; + + for ( auto i = mirrsWithoutWorker.begin (); i != mirrsWithoutWorker.end(); ) { + const auto &u = *i; + if ( u.getHost() == workerQueue->hostname() ) { + if ( workerQueue->requestCount() < constants::DEFAULT_ACTIVE_CONN_PER_HOST ) + possibleHostWorkers.push_back( {u, workerQueue.get()} ); + i = mirrsWithoutWorker.erase( i ); + // we can not stop after removing the first hit, since there could be multiple mirrors with the same hostname + } else { + ++i; + } + } + } + + if( provideDebugEnabled() ) { + MIL << "Current stats: " << std::endl; + MIL << "Existing type workers: " << existingTypeWorkers << std::endl; + MIL << "Existing active connections: " << existingConnections << std::endl; + MIL << "Possible host workers: "<< possibleHostWorkers.size() << std::endl; + MIL << "Mirrors without worker: " << mirrsWithoutWorker.size() << std::endl; + } + + // need to wait for requests to finish in order to schedule more requests + if ( existingConnections >= constants::DEFAULT_ACTIVE_CONN ) { + MIL_PRV << "Reached maximum nr of connections, break" << std::endl; + break; + } + + // if no workers are running, take the first mirror and start a worker for it + // if < nr of workers are running, use a mirror we do not have a conn yet to + if ( existingTypeWorkers < constants::DEFAULT_MAX_DYNAMIC_WORKERS + && mirrsWithoutWorker.size() ) { + + MIL_PRV << "Free worker slots and available mirror URLs, starting a new worker" << std::endl; + + //@TODO out of the available mirrors use the best one based on statistics ( if available ) + bool found = false; + for( const auto &url : mirrsWithoutWorker ) { + + // mark this URL as used now, in case the queue can not be started we won't try it anymore + if ( !item->owner()->safeRedirectTo ( item, url ) ) + continue; + + ProvideQueueRef q = std::make_shared( *this ); + if ( !q->startup( scheme, _workDir / scheme / url.getHost(), url.getHost() ) ) { + break; + } else { + + MIL_PRV << "Started worker for " << url.getHost() << " enqueing request" << std::endl; + + item->setActiveUrl(url); + found = true; + + std::string str = zypp::str::Format("%1%://%2%") % scheme % url.getHost(); + _workerQueues[str] = q; + q->enqueue( item ); + break; + } + } + + if( found ) { + i = queue.erase(i); + continue; + } + } + + // if we cannot start a new worker, find the best queue where we can push the item into + if ( possibleHostWorkers.size() ) { + + MIL_PRV << "No free worker slots, looking for the best existing worker" << std::endl; + bool found = false; + while( possibleHostWorkers.size () ) { + std::vector< std::pair >::iterator candidate = possibleHostWorkers.begin(); + for ( auto i = candidate+1; i != possibleHostWorkers.end(); i++ ) { + if ( i->second->activeRequests () < candidate->second->activeRequests () ) + candidate = i; + } + + if ( !item->owner()->safeRedirectTo( item, candidate->first ) ) { + possibleHostWorkers.erase( candidate ); + continue; + } + + MIL_PRV << "Using existing worker " << candidate->first.getHost() << " to download request" << std::endl; + + found = true; + item->setActiveUrl( candidate->first ); + candidate->second->enqueue( item ); + break; + } + + if( found ) { + i = queue.erase(i); + continue; + } + } + + // if we reach this place all we can now try is to decomission idle queues and use the new slot to start + // a new worker + if ( idleWorkers.size() && mirrsWithoutWorker.size() ) { + + MIL_PRV << "No free worker slots, no slots in existing queues, trying to decomission idle queues." << std::endl; + + auto candidate = findLaziestWorker( _workerQueues, idleWorkers ); + if ( candidate != _workerQueues.end() ) { + + // for now we decomission the worker and start a new one, should we instead introduce a "reset" message + // that repurposes the worker to another hostname/workdir config? + _workerQueues.erase(candidate); + + //@TODO out of the available mirrors use the best one based on statistics ( if available ) + bool found = false; + for( const auto &url : mirrsWithoutWorker ) { + + if ( !item->owner()->safeRedirectTo ( item, url ) ) + continue; + + ProvideQueueRef q = std::make_shared( *this ); + if ( !q->startup( scheme, _workDir / scheme / url.getHost(), url.getHost() ) ) { + break; + } else { + + MIL_PRV << "Replaced worker for " << url.getHost() << ", enqueing request" << std::endl; + + item->setActiveUrl(url); + found = true; + + auto str = zypp::str::Format("%1%://%2%") % scheme % url.getHost(); + _workerQueues[str] = q; + q->enqueue( item ); + } + } + + if( found ) { + i = queue.erase(i); + continue; + } + } + } + + // if we reach here we skip over the item and try to schedule it again later + MIL_PRV << "End of line, deferring request for next try." << std::endl; + i++; + + } + } else if ( config.worker_type() == ProvideQueue::Config::CPUBound && !isSingleInstance ) { + + for( auto i = queue.begin (); i != queue.end(); ) { + + // this is the only place where we remove elements from the queue when the scheduling flag is active + // other code just nulls out requests in the queue if during scheduling items need to be removed + while ( i != queue.end() && !(*i) ) { + i = queue.erase(i); + } + + if ( i == queue.end() ) + break; + + // make a real reference so it does not dissapear when we remove it from the queue + ProvideRequestRef item = *i; + + // CPU bound queues do not support attaching via a AttachRequest, this is handled by simply providing the media verification files + // If we hit this code path, its a bug + if( item->code() == ProvideMessage::Code::Attach || item->code() == ProvideMessage::Code::Detach ) { + i = queue.erase(i); + if ( item->owner () ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR( zypp::Exception("CPU bound Queues do not support ProvideAttachSpecRef requests") ) ); + continue; + } + + MIL_PRV << "Trying to schedule request: " << item->urls().front() << std::endl; + + // how many workers for this type do already exist + int existingTypeWorkers = 0; + int existingSchemeWorkers = 0; + + // all currently available possible queues for the request + std::vector< ProvideQueue* > possibleWorkers; + + // currently idle workers + std::vector idleWorkers; + + // the URL we are going to use this time + zypp::Url url; + + //CPU bound queues do not spawn per mirrors, we use the first compatible URL + for ( const auto &tmpurl : item->urls() ) { + if ( effectiveScheme( tmpurl.getScheme() ) != scheme ) { + MIL << "Mirror URL " << tmpurl << " is incompatible with current scheme: " << scheme << ", ignoring." << std::endl; + continue; + } + url = tmpurl; + break; + } + + // at this point if the URL is empty the request needs to fail + if( !url.isValid() ) { + MIL << "Request has NO usable URLs" << std::endl; + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR(zypp::media::MediaException("No usable URLs in request spec.")) ); + i = queue.erase(i); + continue; + } + + for ( auto &[ queueName, workerQueue ] : _workerQueues ) { + + if ( ProvideQueue::Config::CPUBound != workerQueue->workerConfig().worker_type() ) + continue; + + const bool thisScheme = zypp::str::startsWith( queueName, scheme ); + + existingTypeWorkers ++; + if ( thisScheme ) { + existingSchemeWorkers++; + if ( workerQueue->canScheduleMore() ) + possibleWorkers.push_back(workerQueue.get()); + } + + if ( workerQueue->isIdle() ) + idleWorkers.push_back(queueName); + } + + if( provideDebugEnabled() ) { + MIL << "Current stats: " << std::endl; + MIL << "Existing type workers: " << existingTypeWorkers << std::endl; + MIL << "Possible CPU workers: "<< possibleWorkers.size() << std::endl; + } + + // first we use existing idle workers of the current type + if ( possibleWorkers.size() ) { + bool found = false; + for ( auto &w : possibleWorkers ) { + if ( w->isIdle() ) { + MIL_PRV << "Using existing idle worker to provide request" << std::endl; + // this is not really required because we are not doing redirect checks + item->owner()->redirectTo ( item, url ); + item->setActiveUrl( url ); + w->enqueue( item ); + i = queue.erase(i); + found = true; + break; + } + } + if ( found ) + continue; + } + + // we first start as many workers as we need before queueing more request to existing ones + if ( existingTypeWorkers < cpuLimit ) { + + MIL_PRV << "Free CPU slots, starting a new worker" << std::endl; + + // this is not really required because we are not doing redirect checks + item->owner()->redirectTo ( item, url ); + + ProvideQueueRef q = std::make_shared( *this ); + if ( q->startup( scheme, _workDir / scheme ) ) { + + item->setActiveUrl(url); + + auto str = zypp::str::Format("%1%#%2%") % scheme % existingSchemeWorkers; + _workerQueues[str] = q; + q->enqueue( item ); + i = queue.erase(i); + continue; + } else { + // CPU bound requests can not recover from this error + i = queue.erase(i); + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR( zypp::Exception("Unable to start worker for request.") ) ); + continue; + } + } + + // we can not start more workers, all we can do now is fill up queues of existing ones + if ( possibleWorkers.size() ) { + MIL_PRV << "No free CPU slots, looking for the best existing worker" << std::endl; + + if( possibleWorkers.size () ) { + std::vector::iterator candidate = possibleWorkers.begin(); + for ( auto i = candidate+1; i != possibleWorkers.end(); i++ ) { + if ( (*i)->activeRequests () < (*candidate)->activeRequests () ) + candidate = i; + } + + // this is not really required because we are not doing redirect checks + item->owner()->redirectTo ( item, url ); + + MIL_PRV << "Using existing worker to provide request" << std::endl; + item->setActiveUrl( url ); + (*candidate)->enqueue( item ); + i = queue.erase(i); + continue; + } + } + + // if we reach this place all we can now try is to decomission idle queues and use the new slot to start + // a new worker + if ( idleWorkers.size() ) { + + MIL_PRV << "No free CPU slots, no slots in existing queues, trying to decomission idle queues." << std::endl; + + auto candidate = findLaziestWorker( _workerQueues, idleWorkers ); + if ( candidate != _workerQueues.end() ) { + + _workerQueues.erase(candidate); + + // this is not really required because we are not doing redirect checks + item->owner()->redirectTo ( item, url ); + + ProvideQueueRef q = std::make_shared( *this ); + if ( q->startup( scheme, _workDir / scheme ) ) { + + MIL_PRV << "Replaced worker, enqueing request" << std::endl; + + item->setActiveUrl(url); + + auto str = zypp::str::Format("%1%#%2%") % scheme % ( existingSchemeWorkers + 1 ); + _workerQueues[str] = q; + q->enqueue( item ); + i = queue.erase(i); + continue; + } else { + // CPU bound requests can not recover from this error + i = queue.erase(i); + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR( zypp::Exception("Unable to start worker for request.") ) ); + continue; + } + } + } else { + MIL_PRV << "No idle workers and no free CPU spots, wait for the next schedule run" << std::endl; + break; + } + + // if we reach here we skip over the item and try to schedule it again later + MIL_PRV << "End of line, deferring request for next try." << std::endl; + i++; + } + + } else { + // either SingleInstance worker or Mounting/VolatileMounting + + for( auto i = queue.begin (); i != queue.end(); ) { + + // this is the only place where we remove elements from the queue when the scheduling flag is active + // other code just nulls out requests in the queue if during scheduling items need to be removed + while ( i != queue.end() && !(*i) ) { + i = queue.erase(i); + } + + if ( i == queue.end() ) + break; + + // make a real reference so it does not dissapear when we remove it from the queue + ProvideRequestRef item = *i; + MIL_PRV << "Trying to schedule request: " << item->urls().front() << std::endl; + + zypp::Url url; + + //mounting queues do not spawn per mirrors, we use the first compatible URL + for ( const auto &tmpurl : item->urls() ) { + if ( effectiveScheme( tmpurl.getScheme() ) != scheme ) { + MIL << "Mirror URL " << tmpurl << " is incompatible with current scheme: " << scheme << ", ignoring." << std::endl; + continue; + } + url = tmpurl; + break; + } + + // at this point if the URL is empty the request needs to fail + if( !url.isValid() ) { + MIL << "Request has NO usable URLs" << std::endl; + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR(zypp::media::MediaException("No usable URLs in request spec.")) ); + i = queue.erase(i); + continue; + } + + + ProvideQueue *qToUse = nullptr; + if ( !_workerQueues.count(scheme) ) { + ProvideQueueRef q = std::make_shared( *this ); + if ( !q->startup( scheme, _workDir / scheme ) ) { + ERR << "Worker startup failed!" << std::endl; + // mounting/single instance requests can not recover from this error + i = queue.erase(i); + + if ( item->owner() ) + item->owner()->finishReq( nullptr, item, ZYPP_EXCPT_PTR( zypp::Exception("Unable to start worker for request.") ) ); + continue; + } + + MIL_PRV << "Started worker, enqueing request" << std::endl; + qToUse = q.get(); + _workerQueues[scheme] = q; + } else { + MIL_PRV << "Found worker, enqueing request" << std::endl; + qToUse = _workerQueues.at(scheme).get(); + } + + // this is not really required because we are not doing redirect checks + item->owner()->redirectTo ( item, url ); + + item->setActiveUrl(url); + qToUse->enqueue( item ); + i = queue.erase(i); + } + } + } + } + + std::list &ProvidePrivate::items() + { + return _items; + } + + zypp::media::CredManagerOptions &ProvidePrivate::credManagerOptions () + { + return _credManagerOptions; + } + + std::vector ProvidePrivate::sanitizeUrls(const std::vector &urls) + { + std::vector usableMirrs; + std::optional scheme; + + for ( auto mirrIt = urls.begin() ; mirrIt != urls.end(); mirrIt++ ) { + const auto &s = schemeConfig( effectiveScheme( mirrIt->getScheme() ) ); + if ( !s ) { + WAR << "URL: " << *mirrIt << " is not supported, ignoring!" << std::endl; + continue; + } + if ( !scheme ) { + scheme = *s; + usableMirrs.push_back ( *mirrIt ); + } else { + if ( scheme->worker_type () == s->worker_type () ) { + usableMirrs.push_back( *mirrIt ); + } else { + WAR << "URL: " << *mirrIt << " has different worker type than the primary URL: "<< usableMirrs.front() <<", ignoring!" << std::endl; + } + } + } + + if ( !scheme || usableMirrs.empty() ) { + return {}; + } + + return usableMirrs; + } + + std::vector &ProvidePrivate::attachedMediaInfos() + { + return _attachedMediaInfos; + } + + expected ProvidePrivate::schemeConfig( const std::string &scheme ) + { + if ( auto i = _schemeConfigs.find( scheme ); i != _schemeConfigs.end() ) { + return expected::success(i->second); + } else { + // we do not have the queue config yet, we need to start a worker to get one + ProvideQueue q( *this ); + if ( !q.startup( scheme, _workDir / scheme ) ) { + return expected::error(ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to start worker to read scheme config."))); + } + auto newItem = _schemeConfigs.insert( std::make_pair( scheme, q.workerConfig() )); + return expected::success(newItem.first->second); + } + } + + std::optional ProvidePrivate::addToFileCache( const zypp::filesystem::Pathname &downloadedFile ) + { + const auto &key = downloadedFile.asString(); + + if ( !zypp::PathInfo(downloadedFile).isExist() ) { + _fileCache.erase ( key ); + return {}; + } + + auto i = _fileCache.insert( { key, FileCacheItem() } ); + if ( !i.second ) { + // file did already exist in the cache, return the shared data + i.first->second._deathTimer.reset(); + return i.first->second._file; + } + + i.first->second._file = zypp::ManagedFile( downloadedFile, zypp::filesystem::unlink ); + return i.first->second._file; + } + + bool ProvidePrivate::isInCache ( const zypp::Pathname &downloadedFile ) const + { + const auto &key = downloadedFile.asString(); + return (_fileCache.count(key) > 0); + } + + void ProvidePrivate::queueItem ( ProvideItemRef item ) + { + _items.push_back( item ); + schedule( ProvidePrivate::EnqueueItem ); + } + + void ProvidePrivate::dequeueItem( ProvideItem *item) + { + auto elem = std::find_if( _items.begin(), _items.end(), [item]( const auto &i){ return i.get() == item; } ); + if ( elem != _items.end() ) { + if ( _isScheduling ) { + (*elem).reset(); + } else { + _items.erase(elem); + } + } + } + + std::string ProvidePrivate::nextMediaId() const + { + zypp::AutoDispose rawStr( g_uuid_string_random (), g_free ); + return zypp::str::asString ( rawStr.value() ); + } + + AttachedMediaInfo_Ptr ProvidePrivate::addMedium( AttachedMediaInfo_Ptr &&medium ) + { + assert( medium ); + if ( !medium ) + return nullptr; + + MIL_PRV << "Registered new media attachment with ID: " << medium->name() << " with mountPoint: (" << medium->_localMountPoint.value_or(zypp::Pathname()) << ")" << std::endl; + _attachedMediaInfos.push_back( std::move(medium) ); + + return _attachedMediaInfos.back(); + } + + bool ProvidePrivate::queueRequest ( ProvideRequestRef req ) + { + const auto &schemeName = effectiveScheme( req->url().getScheme() ); + auto existingQ = std::find_if( _queues.begin (), _queues.end(), [&schemeName]( const auto &qItem) { + return (qItem._schemeName == schemeName); + }); + if ( existingQ != _queues.end() ) { + existingQ->_requests.push_back(req); + } else { + _queues.push_back( ProvidePrivate::QueueItem{ schemeName, {req} } ); + } + + schedule( ProvidePrivate::EnqueueReq ); + return true; + } + + bool ProvidePrivate::dequeueRequest(ProvideRequestRef req , std::exception_ptr error) + { + auto queue = req->currentQueue (); + if ( queue ) { + queue->cancel( req.get(), error ); + return true; + } else { + // Request not started yet, search request queues + for ( auto &q : _queues ) { + auto elem = std::find( q._requests.begin(), q._requests.end(), req ); + if ( elem != q._requests.end() ) { + q._requests.erase(elem); + + if ( req->owner() ) + req->owner()->finishReq( nullptr, req, error ); + return true; + } + } + } + return false; + } + + const zypp::Pathname &ProvidePrivate::workerPath() const + { + return _workerPath; + } + + const std::string ProvidePrivate::queueName( ProvideQueue &q ) const + { + for ( const auto &v : _workerQueues ) { + if ( v.second.get() == &q ) + return v.first; + } + return {}; + } + + bool ProvidePrivate::isRunning() const + { + return _isRunning; + } + + std::string ProvidePrivate::effectiveScheme(const std::string &scheme) const + { + const std::string &ss = zypp::str::stripSuffix( scheme, constants::ATTACHED_MEDIA_SUFFIX ); + if ( auto it = _workerAlias.find ( ss ); it != _workerAlias.end () ) { + return it->second; + } + return ss; + } + + void ProvidePrivate::onPulseTimeout( Timer & ) + { + DBG_PRV << "Pulse timeout" << std::endl; + + auto now = std::chrono::steady_clock::now(); + + if ( _log ) _log->pulse(); + + // release old cache files + for ( auto i = _fileCache.begin (); i != _fileCache.end(); ) { + auto &cacheItem = i->second; + if ( cacheItem._file.unique() ) { + if ( cacheItem._deathTimer ) { + if ( now - *cacheItem._deathTimer < std::chrono::seconds(20) ) { + MIL << "Releasing file " << *i->second._file << " from cache, death timeout." << std::endl; + i = _fileCache.erase(i); + continue; + } + } else { + // start the death timeout + cacheItem._deathTimer = std::chrono::steady_clock::now(); + } + } + + ++i; + } + } + + void ProvidePrivate::onQueueIdle() + { + if ( !_items.empty() ) + return; + for ( auto &[k,q] : _workerQueues ) { + if ( !q->empty() ) + return; + } + + // all queues are empty + _sigIdle.emit(); + } + + void ProvidePrivate::onItemStateChanged( ProvideItem &item ) + { + if ( item.state() == ProvideItem::Finished ) { + auto itemRef = item.shared_this(); + auto i = std::find( _items.begin(), _items.end(), itemRef ); + if ( i == _items.end() ) { + ERR << "State of unknown Item changed, ignoring" << std::endl; + return; + } + if ( _isScheduling ) + i->reset(); + else + _items.erase(i); + } + if ( _items.empty() ) + onQueueIdle(); + } + + uint32_t ProvidePrivate::nextRequestId() + { + //@TODO is it required to handle overflow? + return ++_nextRequestId; + } + + ProvideMediaHandle::ProvideMediaHandle(Provide &parent, AttachedMediaInfo_Ptr mediaInfoRef ) + : _parent( parent.weak_this() ) + , _mediaRef( std::move(mediaInfoRef) ) + {} + + std::shared_ptr ProvideMediaHandle::parent() const + { + return _parent.lock(); + } + + bool ProvideMediaHandle::isValid() const + { + return ( _mediaRef.get() != nullptr ); + } + + std::string ProvideMediaHandle::handle() const + { + if ( !_mediaRef ) + return {}; + return _mediaRef->_name; + } + + const zypp::Url &ProvideMediaHandle::baseUrl() const + { + static zypp::Url invalidHandle; + if ( !_mediaRef ) + return invalidHandle; + return _mediaRef->_attachedUrl; + } + + const std::optional &ProvideMediaHandle::localPath() const + { + static std::optional invalidHandle; + if ( !_mediaRef ) + return invalidHandle; + return _mediaRef->_localMountPoint; + } + + AttachedMediaInfo_constPtr ProvideMediaHandle::mediaInfo() const + { + return _mediaRef; + } + + + Provide::Provide( const zypp::Pathname &workDir ) : Base( *new ProvidePrivate( zypp::Pathname(workDir), *this ) ) + { + Z_D(); + connect( *d->_pulseTimer, &Timer::sigExpired, *d, &ProvidePrivate::onPulseTimeout ); + } + + ProvideRef Provide::create( const zypp::filesystem::Pathname &workDir ) + { + return ProvideRef( new Provide(workDir) ); + } + + expected Provide::prepareMedia(const std::vector &urls, const ProvideMediaSpec &request) + { + Z_D(); + // sanitize the mirrors to contain only URLs that have same worker types + std::vector usableMirrs = d->sanitizeUrls( urls ); + if ( usableMirrs.empty() ) { + return expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No valid mirrors available") )); + } + return expected::success( shared_this(), std::move(usableMirrs), request ); + } + + expected Provide::prepareMedia(const zypp::Url &url, const ProvideMediaSpec &request) + { + return prepareMedia( std::vector{url}, request ); + } + + AsyncOpRef > Provide::attachMediaIfNeeded( LazyMediaHandle lazyHandle) + { + using namespace zyppng::operators; + if ( lazyHandle.attached() ) + return makeReadyResult( expected::success( *lazyHandle.handle() ) ); + + MIL << "Attaching lazy medium with label: [" << lazyHandle.spec().label() << "]" << std::endl; + + return attachMedia( lazyHandle.urls(), lazyHandle.spec () ) + | and_then([lazyHandle]( MediaHandle handle ) { + lazyHandle._sharedData->_mediaHandle = handle; + return expected::success( std::move(handle) ); + }); + } + + AsyncOpRef> Provide::attachMedia( const zypp::Url &url, const ProvideMediaSpec &request ) + { + return attachMedia ( std::vector{url}, request ); + } + + AsyncOpRef> Provide::attachMedia( const std::vector &urls, const ProvideMediaSpec &request ) + { + Z_D(); + + // sanitize the mirrors to contain only URLs that have same worker types + std::vector usableMirrs = d->sanitizeUrls( urls ); + if ( usableMirrs.empty() ) { + return makeReadyResult( expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No valid mirrors available") )) ); + } + + // first check if there is a already attached medium we can use as well + auto &attachedMedia = d->attachedMediaInfos (); + for ( auto &medium : attachedMedia ) { + if ( medium->isSameMedium ( usableMirrs, request ) ) { + return makeReadyResult( expected::success( Provide::MediaHandle( *this, medium ) )); + } + } + + auto op = AttachMediaItem::create( usableMirrs, request, *d_func() ); + d->queueItem (op); + return op->promise(); + } + + AsyncOpRef< expected > Provide::provide( const std::vector &urls, const ProvideFileSpec &request ) + { + Z_D(); + auto op = ProvideFileItem::create( urls, request, *d ); + d->queueItem (op); + return op->promise(); + } + + AsyncOpRef< expected > Provide::provide( const zypp::Url &url, const ProvideFileSpec &request ) + { + return provide( std::vector{ url }, request ); + } + + AsyncOpRef< expected > Provide::provide( const MediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request ) + { + Z_D(); + const auto i = std::find( d->_attachedMediaInfos.begin(), d->_attachedMediaInfos.end(), attachHandle.mediaInfo() ); + if ( i == d->_attachedMediaInfos.end() ) { + return makeReadyResult( expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("Invalid attach handle")) ) ); + } + + // for downloading items we need to make the baseUrl part of the request URL + zypp::Url url = (*i)->_attachedUrl; + + // real mount devices use a ID to reference a attached medium, for those we do not need to send the baseUrl as well since its already + // part of the mount point, so if we mount host:/path/to/repo to the ID 1234 and look for the file /path/to/repo/file1 the request URL will look like: nfs-media://1234/file1 + if ( (*i)->_workerType == ProvideQueue::Config::SimpleMount || (*i)->_workerType == ProvideQueue::Config::VolatileMount ) { + url = zypp::Url(); + // work around the zypp::Url requirements for certain Url schemes by attaching a suffix, that way we are always able to have a authority + url.setScheme( (*i)->_attachedUrl.getScheme() + std::string(constants::ATTACHED_MEDIA_SUFFIX) ); + url.setAuthority( (*i)->_name ); + url.setPathName("/"); + } + + url.appendPathName( fileName ); + auto op = ProvideFileItem::create( {url}, request, *d ); + op->setMediaRef( MediaHandle( *this, (*i) )); + d->queueItem (op); + + return op->promise(); + } + + AsyncOpRef > Provide::provide( const LazyMediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request ) + { + using namespace zyppng::operators; + return attachMediaIfNeeded ( attachHandle ) + | and_then([weakMe = weak_this(), fName = fileName, req = request ]( MediaHandle handle ){ + auto me = weakMe.lock(); + if ( !me ) + return makeReadyResult(expected::error(ZYPP_EXCPT_PTR(zypp::Exception("Provide was released during a operation")))); + return me->provide( handle, fName, req); + }); + } + + zyppng::AsyncOpRef > Provide::checksumForFile( const zypp::Pathname &p, const std::string &algorithm ) + { + using namespace zyppng::operators; + + zypp::Url url("chksum:///"); + url.setPathName( p ); + auto fut = provide( url, zyppng::ProvideFileSpec().setCustomHeaderValue( "chksumType", algorithm ) ) + | and_then( [algorithm]( zyppng::ProvideRes &&chksumRes ) { + if ( chksumRes.headers().contains(algorithm) ) { + try { + return expected::success( zypp::CheckSum( algorithm, chksumRes.headers().value(algorithm).asString() ) ); + } catch ( ... ) { + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + return expected::error( ZYPP_EXCPT_PTR( zypp::FileCheckException("Invalid/Empty checksum returned from worker") ) ); + } ); + return fut; + } + + AsyncOpRef> Provide::copyFile ( const zypp::Pathname &source, const zypp::Pathname &target ) + { + using namespace zyppng::operators; + + zypp::Url url("copy:///"); + url.setPathName( source ); + auto fut = provide( url, ProvideFileSpec().setDestFilenameHint( target )) + | and_then( [&]( ProvideRes &©Res ) { + return expected::success( copyRes.asManagedFile() ); + } ); + return fut; + } + + AsyncOpRef > Provide::copyFile( ProvideRes &&source, const zypp::filesystem::Pathname &target ) + { + using namespace zyppng::operators; + + auto fName = source.file(); + return copyFile( fName, target ) + | [ resSave = std::move(source) ] ( auto &&result ) { + // callback lambda to keep the ProvideRes reference around until the op is finished, + // if the op fails the callback will be cleaned up and so the reference + return result; + }; + } + + void Provide::start () + { + Z_D(); + d->_isRunning = true; + d->_pulseTimer->start( 5000 ); + d->schedule( ProvidePrivate::ProvideStart ); + if ( d->_log ) d->_log->provideStart(); + } + + void Provide::setWorkerPath(const zypp::filesystem::Pathname &path) + { + d_func()->_workerPath = path; + } + + bool Provide::ejectDevice(const std::string &queueRef, const std::string &device) + { + if ( !queueRef.empty() ) { + return zypp::media::CDTools::openTray(device); + } + return false; + } + + void Provide::setStatusTracker( ProvideStatusRef tracker ) + { + d_func()->_log = tracker; + } + + const zypp::Pathname &Provide::providerWorkdir () const + { + return d_func()->_workDir; + } + + const zypp::media::CredManagerOptions &Provide::credManangerOptions () const + { + Z_D(); + return d->_credManagerOptions; + } + + void Provide::setCredManagerOptions( const zypp::media::CredManagerOptions & opt ) + { + d_func()->_credManagerOptions = opt; + } + + SignalProxy Provide::sigIdle() + { + return d_func()->_sigIdle; + } + + SignalProxy &, const std::optional &)> Provide::sigMediaChangeRequested() + { + return d_func()->_sigMediaChange; + } + + SignalProxy< std::optional ( const zypp::Url &reqUrl, const std::string &triedUsername, const std::map &extraValues ) > Provide::sigAuthRequired() + { + return d_func()->_sigAuthRequired; + } + + ZYPP_IMPL_PRIVATE(Provide); + + ProvideStatus::ProvideStatus( ProvideRef parent ) + : _provider( parent ) + { } + + void ProvideStatus::provideStart () + { + _stats = Stats(); + _stats._startTime = std::chrono::steady_clock::now(); + _stats._lastPulseTime = std::chrono::steady_clock::now(); + } + + void ProvideStatus::itemDone ( ProvideItem &item ) + { + const auto &sTime = item.startTime(); + const auto &fTime = item.finishedTime(); + if ( sTime > sTime.min() && fTime >= sTime ) { + auto duration = std::chrono::duration_cast( item.finishedTime() - item.startTime() ); + if ( duration.count() ) + MIL << "Item finished after " << duration.count() << " seconds, with " << zypp::ByteCount( item.currentStats()->_bytesProvided.operator zypp::ByteCount::SizeType() / duration.count() ) << "/s" << std::endl; + MIL << "Item finished after " << (item.finishedTime() - item.startTime()).count() << " ns" << std::endl; + } + pulse( ); + } + + void ProvideStatus::itemFailed ( ProvideItem &item ) + { + MIL << "Item failed" << std::endl; + } + + const ProvideStatus::Stats& ProvideStatus::stats() const + { + return _stats; + } + + void ProvideStatus::pulse ( ) + { + auto prov = _provider.lock(); + if ( !prov ) + return; + + const auto lastFinishedBytes = _stats._finishedBytes; + const auto lastPartialBytes = _stats._partialBytes; + _stats._expectedBytes = _stats._finishedBytes; // finished bytes are expected too! + zypp::ByteCount tmpPartialBytes (0); // bytes that are finished in staging, but not commited to cache yet + + for ( const auto &i : prov->d_func()->items() ) { + + if ( !i // maybe released during scheduling + || i->state() == ProvideItem::Cancelling ) + continue; + + if ( i->state() == ProvideItem::Uninitialized + || i->state() == ProvideItem::Pending ) { + _stats._expectedBytes += i->bytesExpected(); + continue; + } + + i->pulse(); + + const auto & stats = i->currentStats(); + const auto & prevStats = i->previousStats(); + if ( !stats || !prevStats ) { + ERR << "Bug! Stats should be initialized by now" << std::endl; + continue; + } + + if ( i->state() == ProvideItem::Downloading + || i->state() == ProvideItem::Processing + || i->state() == ProvideItem::Finalizing ) { + _stats._expectedBytes += stats->_bytesExpected; + tmpPartialBytes += stats->_bytesProvided; + } else if ( i->state() == ProvideItem::Finished ) { + _stats._finishedBytes += stats->_bytesProvided; // remember those bytes are finished in stats directly + _stats._expectedBytes += stats->_bytesProvided; + } + } + + const auto now = std::chrono::steady_clock::now(); + const auto sinceLast = std::chrono::duration_cast( now - _stats._lastPulseTime ); + const auto lastFinB = lastPartialBytes + lastFinishedBytes; + const auto currFinB = tmpPartialBytes + _stats._finishedBytes; + + const auto diff = currFinB - lastFinB; + _stats._lastPulseTime = now; + _stats._partialBytes = tmpPartialBytes; + + if ( sinceLast >= std::chrono::seconds(1) ) + _stats._perSecondSinceLastPulse = ( diff / ( sinceLast.count() ) ); + + auto sinceStart = std::chrono::duration_cast( _stats._lastPulseTime - _stats._startTime ); + if ( sinceStart.count() ) { + const size_t diff = _stats._finishedBytes + _stats._partialBytes; + _stats._perSecond = zypp::ByteCount( diff / sinceStart.count() ); + } + } +} diff --git a/zypp-media/ng/provide.h b/zypp-media/ng/provide.h new file mode 100644 index 0000000..3051d52 --- /dev/null +++ b/zypp-media/ng/provide.h @@ -0,0 +1,203 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_MEDIA_PROVIDE_H_INCLUDED +#define ZYPP_MEDIA_PROVIDE_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zypp { + class Url; + namespace media { + struct CredManagerOptions; + } +} + +/*! + * @TODO Fix bsc#1174011 "auth=basic ignored in some cases" for provider + * We should proactively add the password to the request if basic auth is configured + * and a password is available in the credentials but not in the URL. + * + * We should be a bit paranoid here and require that the URL has a user embedded, otherwise we go the default route + * and ask the server first about the auth method + * + * @TODO Make sure URLs are rewritten, e.g. MediaSetAccess::rewriteUrl + */ +namespace zyppng { + + class ProvidePrivate; + using AnyMap = std::unordered_map; + DEFINE_PTR_TYPE(AttachedMediaInfo); + + /*! + * RAII helper for media handles + */ + class ProvideMediaHandle + { + public: + + using ParentType = Provide; + + ProvideMediaHandle () = default; + ProvideMediaHandle ( Provide &parent, AttachedMediaInfo_Ptr mediaInfoRef ); + std::shared_ptr parent() const; + bool isValid () const; + std::string handle() const; + const zypp::Url &baseUrl() const; + const std::optional &localPath() const; + zyppng::AttachedMediaInfo_constPtr mediaInfo() const; + private: + ProvideWeakRef _parent; + AttachedMediaInfo_Ptr _mediaRef; + }; + + /*! + * Provide status observer object, this can be used to provide good insight into the status of the provider, its items and + * all running requests. + */ + class ProvideStatus + { + public: + + struct Stats { + std::chrono::steady_clock::time_point _startTime; + std::chrono::steady_clock::time_point _lastPulseTime; + uint _itemsSinceStart = 0; //< How many items have been started since Provide::start() was called + uint _runningItems = 0; //< How many items are currently running + zypp::ByteCount _finishedBytes; //< The number of bytes that were finished completely + zypp::ByteCount _expectedBytes; //< The number of currently expected bytes + zypp::ByteCount _partialBytes; //< The number of bytes of items that were already partially downloaded but the item they belong to is not finished + zypp::ByteCount _perSecondSinceLastPulse; //< The download speed since the last pulse + zypp::ByteCount _perSecond; //< The download speed we are currently operating with + }; + + ProvideStatus( ProvideRef parent ); + virtual ~ProvideStatus(){} + + virtual void provideStart (); + virtual void provideDone (){} + virtual void itemStart ( ProvideItem &item ){} + virtual void itemDone ( ProvideItem &item ); + virtual void itemFailed ( ProvideItem &item ); + virtual void requestStart ( ProvideItem &item, uint32_t reqId, const zypp::Url &url, const AnyMap &extraData = {} ){} + virtual void requestDone ( ProvideItem &item, uint32_t reqId, const AnyMap &extraData = {} ){} + virtual void requestRedirect ( ProvideItem &item, uint32_t reqId, const zypp::Url &toUrl, const AnyMap &extraData = {} ){} + virtual void requestFailed ( ProvideItem &item, uint32_t reqId, const std::exception_ptr &err, const AnyMap &requestData = {} ){} + virtual void pulse ( ); + + const Stats &stats() const; + + private: + Stats _stats; + ProvideWeakRef _provider; + }; + + class Provide : public Base + { + ZYPP_DECLARE_PRIVATE(Provide); + template friend class ProvidePromise; + friend class ProvideItem; + friend class ProvideMediaHandle; + friend class ProvideStatus; + public: + + using MediaHandle = ProvideMediaHandle; + using LazyMediaHandle = zyppng::LazyMediaHandle; + using Res = ProvideRes; + + static ProvideRef create( const zypp::Pathname &workDir = "" ); + + /*! + * Prepares a lazy handle, that is attached only if a actual provide() is called onto it. + * Use this to delay a media attach until its used the first time + */ + expected prepareMedia ( const std::vector &urls, const ProvideMediaSpec &request ); + expected prepareMedia ( const zypp::Url &url, const ProvideMediaSpec &request ); + + AsyncOpRef> attachMediaIfNeeded( LazyMediaHandle lazyHandle ); + AsyncOpRef> attachMedia( const std::vector &urls, const ProvideMediaSpec &request ); + AsyncOpRef> attachMedia( const zypp::Url &url, const ProvideMediaSpec &request ); + + AsyncOpRef> provide( const std::vector &urls, const ProvideFileSpec &request ); + AsyncOpRef> provide( const zypp::Url &url, const ProvideFileSpec &request ); + AsyncOpRef> provide( const MediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request ); + AsyncOpRef> provide( const LazyMediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request ); + + + /*! + * Schedules a job to calculate the checksum for the given file + */ + AsyncOpRef> checksumForFile ( const zypp::Pathname &p, const std::string &algorithm ); + + /*! + * Schedules a copy job to copy a file from \a source to \a target + */ + AsyncOpRef> copyFile ( const zypp::Pathname &source, const zypp::Pathname &target ); + AsyncOpRef> copyFile ( ProvideRes &&source, const zypp::Pathname &target ); + + void start(); + void setWorkerPath( const zypp::Pathname &path ); + bool isRunning() const; + bool ejectDevice ( const std::string &queueRef, const std::string &device ); + + void setStatusTracker( ProvideStatusRef tracker ); + + const zypp::Pathname &providerWorkdir () const; + + const zypp::media::CredManagerOptions &credManangerOptions () const; + void setCredManagerOptions( const zypp::media::CredManagerOptions & opt ); + + SignalProxy sigIdle(); + + enum Action { + ABORT, // abort and return error + RETRY, // retry + SKIP // abort and set skip request + }; + using MediaChangeAction = std::optional; + + /*! + * Connect to this signal to handle media change requests + * + * \note It is NOT supported to shutdown the provider or cancel items when in this callback + * Returning Abort here will effectively cancel the current item anyway. + */ + SignalProxy &devices, const std::optional &desc )> sigMediaChangeRequested( ); + + /*! + * This signal is emitted in case a request signaled a need to get Auth Info and nothing was found + * in the \ref zypp::media::CredentialManager. + */ + SignalProxy< std::optional ( const zypp::Url &reqUrl, const std::string &triedUsername, const std::map &extraValues ) > sigAuthRequired(); + + + static auto copyResultToDest ( ProvideRef provider, const zypp::Pathname &targetPath ) { + return [ providerRef=std::move(provider), targetPath = targetPath ]( ProvideRes &&file ){ + zypp::filesystem::assert_dir( targetPath.dirname () ); + return providerRef->copyFile( std::move(file), targetPath ); + }; + } + + + private: + Provide( const zypp::Pathname &workDir ); + }; + +} +#endif diff --git a/zypp-media/ng/providefwd.h b/zypp-media/ng/providefwd.h new file mode 100644 index 0000000..7400fd3 --- /dev/null +++ b/zypp-media/ng/providefwd.h @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* You have been warned! +* +*/ +#ifndef ZYPP_MEDIA_PROVIDE_FWD_H_INCLUDED +#define ZYPP_MEDIA_PROVIDE_FWD_H_INCLUDED + +#include +#include + +namespace zyppng { + ZYPP_FWD_DECL_TYPE_WITH_REFS (Provide); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProvideMediaSpec); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProvideFileSpec); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProvideItem); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProvideRequest); + ZYPP_FWD_DECL_TYPE_WITH_REFS (MediaDataVerifier); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProvideStatus); + class HeaderValueMap; + class ProvideMediaHandle; +} + +#endif diff --git a/zypp-media/ng/provideitem.cc b/zypp-media/ng/provideitem.cc new file mode 100644 index 0000000..87afebc --- /dev/null +++ b/zypp-media/ng/provideitem.cc @@ -0,0 +1,1208 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "private/providedbg_p.h" +#include "private/provideitem_p.h" +#include "private/provide_p.h" +#include "private/providemessage_p.h" +#include "private/provideres_p.h" +#include "provide-configvars.h" +#include +#include +#include "mediaverifier.h" +#include + +using namespace std::literals; + +namespace zyppng { + + static constexpr std::string_view DEFAULT_MEDIA_VERIFIER("SuseMediaV1"); + + expected ProvideRequest::create(ProvideItem &owner, const std::vector &urls, const std::string &id, ProvideMediaSpec &spec ) + { + if ( urls.empty() ) + return expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("List of URLs can not be empty") ) ); + + auto m = ProvideMessage::createAttach( ProvideQueue::InvalidId, urls.front(), id, spec.label() ); + if ( !spec.mediaFile().empty() ) { + m.setValue( AttachMsgFields::VerifyType, std::string(DEFAULT_MEDIA_VERIFIER.data()) ); + m.setValue( AttachMsgFields::VerifyData, spec.mediaFile().asString() ); + m.setValue( AttachMsgFields::MediaNr, int32_t(spec.medianr()) ); + } + + const auto &cHeaders = spec.customHeaders(); + for ( auto i = cHeaders.beginList (); i != cHeaders.endList(); i++) { + for ( const auto &val : i->second ) + m.addValue( i->first, val ); + } + + return expected::success( ProvideRequestRef( new ProvideRequest(&owner, urls, std::move(m))) ); + } + + expected ProvideRequest::create( ProvideItem &owner, const std::vector &urls, ProvideFileSpec &spec ) + { + if ( urls.empty() ) + return expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("List of URLs can not be empty") ) ); + + auto m = ProvideMessage::createProvide ( ProvideQueue::InvalidId, urls.front() ); + const auto &destFile = spec.destFilenameHint(); + const auto &deltaFile = spec.deltafile(); + const int64_t fSize = spec.downloadSize();; + + if ( !destFile.empty() ) + m.setValue( ProvideMsgFields::Filename, destFile.asString() ); + if ( !deltaFile.empty() ) + m.setValue( ProvideMsgFields::DeltaFile, deltaFile.asString() ); + if ( fSize ) + m.setValue( ProvideMsgFields::ExpectedFilesize, fSize ); + m.setValue( ProvideMsgFields::CheckExistOnly, spec.checkExistsOnly() ); + + const auto &cHeaders = spec.customHeaders(); + for ( auto i = cHeaders.beginList (); i != cHeaders.endList(); i++) { + for ( const auto &val : i->second ) + m.addValue( i->first, val ); + } + + return expected::success( ProvideRequestRef( new ProvideRequest(&owner, urls, std::move(m)) ) ); + } + + expected ProvideRequest::createDetach( const zypp::Url &url ) + { + auto m = ProvideMessage::createDetach ( ProvideQueue::InvalidId , url ); + return expected::success( ProvideRequestRef( new ProvideRequest( nullptr, { url }, std::move(m) ) ) ); + } + + ZYPP_IMPL_PRIVATE(ProvideItem); + + ProvideItem::ProvideItem( ProvidePrivate &parent ) + : Base( *new ProvideItemPrivate( parent, *this ) ) + { } + + ProvideItem::~ProvideItem() + { } + + ProvidePrivate &ProvideItem::provider() + { + return d_func()->_parent; + } + + bool ProvideItem::safeRedirectTo( ProvideRequestRef startedReq, const zypp::Url &url ) + { + if ( !canRedirectTo( startedReq, url ) ) + return false; + + redirectTo( startedReq, url ); + return true; + } + + void ProvideItem::redirectTo( ProvideRequestRef startedReq, const zypp::Url &url ) + { + //@TODO strip irrelevant stuff from URL + startedReq->_pastRedirects.push_back ( url ); + } + + bool ProvideItem::canRedirectTo( ProvideRequestRef startedReq, const zypp::Url &url ) + { + // make sure there is no redirect loop + if ( !startedReq->_pastRedirects.size() ) + return true; + + if ( std::find( startedReq->_pastRedirects.begin(), startedReq->_pastRedirects.end(), url ) != startedReq->_pastRedirects.end() ) + return false; + + return true; + } + + const std::optional &ProvideItem::currentStats() const + { + return d_func()->_currStats; + } + + const std::optional &ProvideItem::previousStats() const + { + return d_func()->_prevStats; + } + + std::chrono::steady_clock::time_point ProvideItem::startTime() const + { + return d_func()->_itemStarted; + } + + std::chrono::steady_clock::time_point ProvideItem::finishedTime() const { + return d_func()->_itemFinished; + } + + void ProvideItem::pulse () + { + Z_D(); + if ( d->_currStats ) + d->_prevStats = d->_currStats; + + d->_currStats = makeStats(); + + // once the item is finished the pulse time is always the finish time + if ( d->_itemState == Finished ) + d->_currStats->_pulseTime = d->_itemFinished; + } + + zypp::ByteCount ProvideItem::bytesExpected () const + { + return 0; + } + + ProvideItem::ItemStats ProvideItem::makeStats () + { + return ItemStats { + ._pulseTime = std::chrono::steady_clock::now(), + ._runningRequests = _runningReq ? (uint)1 : (uint)0 + }; + } + + void ProvideItem::informalMessage ( ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg ) + { + if ( req != _runningReq ) { + WAR << "Received event for unknown request, ignoring" << std::endl; + return; + } + + if ( msg.code() == ProvideMessage::Code::ProvideStarted ) { + MIL << "Request: "<< req->url() << " was started" << std::endl; + } + + } + + void ProvideItem::cacheMiss( ProvideRequestRef req ) + { + if ( req != _runningReq ) { + WAR << "Received event for unknown request, ignoring" << std::endl; + return; + } + + MIL << "Request: "<< req->url() << " CACHE MISS, request will be restarted by queue." << std::endl; + } + + void ProvideItem::finishReq(ProvideQueue &, ProvideRequestRef finishedReq, const ProvideMessage &msg ) + { + if ( finishedReq != _runningReq ) { + WAR << "Received event for unknown request, ignoring" << std::endl; + return; + } + + auto log = provider().log(); + + // explicitely handled codes + const auto code = msg.code(); + if ( code == ProvideMessage::Code::Redirect ) { + + // remove the old request + _runningReq.reset(); + + try { + + MIL << "Request finished with redirect." << std::endl; + + zypp::Url newUrl( msg.value( RedirectMsgFields::NewUrl ).asString() ); + if ( !safeRedirectTo( finishedReq, newUrl ) ) { + cancelWithError( ZYPP_EXCPT_PTR ( zypp::media::MediaException("Redirect Loop")) ); + return; + } + + MIL << "Request redirected to: " << newUrl << std::endl; + + if ( log ) log->requestRedirect( *this, msg.requestId(), newUrl ); + + finishedReq->setUrl( newUrl ); + + if ( !enqueueRequest( finishedReq ) ) { + cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) ); + } + } catch ( ... ) { + cancelWithError( std::current_exception() ); + return; + } + return; + + } else if ( code == ProvideMessage::Code::Metalink ) { + + // remove the old request + _runningReq.reset(); + + MIL << "Request finished with mirrorlist from server." << std::endl; + + //@TODO do we need to merge this with the mirrorlist we got from the user? + // or does a mirrorlist from d.o.o invalidate that? + + std::vector urls; + const auto &mirrors = msg.values( MetalinkRedirectMsgFields::NewUrl ); + for( auto i = mirrors.cbegin(); i != mirrors.cend(); i++ ) { + try { + zypp::Url newUrl( i->asString() ); + if ( !canRedirectTo( finishedReq, newUrl ) ) + continue; + urls.push_back ( newUrl ); + } catch ( ... ) { + if ( i->isString() ) + WAR << "Received invalid URL from worker: " << i->asString() << " ignoring!" << std::endl; + else + WAR << "Received invalid value for newUrl from worker ignoring!" << std::endl; + } + } + + if ( urls.size () == 0 ) { + cancelWithError( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No mirrors left to redirect to.")) ); + return; + } + + MIL << "Found usable nr of mirrors: " << urls.size () << std::endl; + finishedReq->setUrls( urls ); + + // disable metalink + finishedReq->provideMessage().setValue( ProvideMsgFields::MetalinkEnabled, false ); + + if ( log ) log->requestDone( *this, msg.requestId() ); + + if ( !enqueueRequest( finishedReq ) ) { + cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) ); + } + + MIL << "End of mirrorlist handling"<< std::endl; + return; + + } else if ( code >= ProvideMessage::Code::FirstClientErrCode && code <= ProvideMessage::Code::LastSrvErrCode ) { + + // remove the old request + _runningReq.reset(); + + std::exception_ptr errPtr; + try { + const auto reqUrl = finishedReq->activeUrl().value(); + const auto reason = msg.value( ErrMsgFields::Reason ).asString(); + switch ( code ) { + case ProvideMessage::Code::BadRequest: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException (zypp::str::Str() << "Bad request for URL: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::PeerCertificateInvalid: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException(zypp::str::Str() << "PeerCertificateInvalid Error for URL: " << reqUrl << " " << reason) ); + break; + case ProvideMessage::Code::ConnectionFailed: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException(zypp::str::Str() << "ConnectionFailed Error for URL: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::ExpectedSizeExceeded: { + + std::optional filesize; + const auto &hdrs = finishedReq->provideMessage ().headers (); + if ( hdrs.contains( ProvideMsgFields::ExpectedFilesize ) ) { + const auto &val = hdrs.value ( ProvideMsgFields::ExpectedFilesize ); + if ( val.valid() ) + filesize = val.asInt64(); + } + + if ( !filesize ) { + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "ExceededExpectedSize Error for URL: " << reqUrl << " " << reason ) ); + } else { + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaFileSizeExceededException(reqUrl, *filesize ) ); + } + break; + } + case ProvideMessage::Code::Cancelled: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Request was cancelled: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::InvalidChecksum: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "InvalidChecksum Error for URL: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::Timeout: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaTimeoutException(reqUrl) ); + break; + case ProvideMessage::Code::NotFound: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaFileNotFoundException(reqUrl, "") ); + break; + case ProvideMessage::Code::Forbidden: + case ProvideMessage::Code::Unauthorized: { + + const auto &hintVal = msg.value( "authHint"sv ); + std::string hint; + if ( hintVal.valid() && hintVal.isString() ) { + hint = hintVal.asString(); + } + + //@TODO retry here with timestamp from cred store check + // we let the request fail after it checked the store + + errPtr = ZYPP_EXCPT_PTR ( zypp::media::MediaUnauthorizedException( + reqUrl, reason, "", hint + )); + break; + + } + case ProvideMessage::Code::MountFailed: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "MountFailed Error for URL: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::Jammed: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaJammedException() ); + break; + case ProvideMessage::Code::MediaChangeSkip: + errPtr = ZYPP_EXCPT_PTR( zypp::SkipRequestException ( zypp::str::Str() << "User-requested skipping for URL: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::MediaChangeAbort: + errPtr = ZYPP_EXCPT_PTR( zypp::AbortRequestException( zypp::str::Str() <<"Aborting requested by user for URL: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::InternalError: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "WorkerSpecific Error for URL: " << reqUrl << " " << reason ) ); + break; + case ProvideMessage::Code::NotAFile: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaNotAFileException(reqUrl, "") ); + break; + case ProvideMessage::Code::MediumNotDesired: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaNotDesiredException(reqUrl) ); + break; + default: + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Unknown Error for URL: " << reqUrl << " " << reason ) ); + break; + } + } catch (...) { + errPtr = ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Invalid error message received for URL: " << *finishedReq->activeUrl() << " code: " << code ) ); + } + + if ( log ) log->requestFailed( *this, msg.requestId(), errPtr ); + // finish the request + cancelWithError( errPtr ); + return; + } + + // if we reach here we don't know how to handle the message + _runningReq.reset(); + cancelWithError( ZYPP_EXCPT_PTR (zypp::media::MediaException("Unhandled message received for ProvideFileItem")) ); + } + + void ProvideItem::finishReq(ProvideQueue *, ProvideRequestRef finishedReq , const std::exception_ptr excpt) + { + if ( finishedReq != _runningReq ) { + WAR << "Received event for unknown request, ignoring" << std::endl; + return; + } + + if ( _runningReq ) { + auto log = provider().log(); + if ( log ) log->requestFailed( *this, finishedReq->provideMessage().requestId(), excpt ); + } + + _runningReq.reset(); + cancelWithError(excpt); + } + + expected ProvideItem::authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map &extraFields ) + { + + if ( req != _runningReq ) { + WAR << "Received authenticationRequired for unknown request, rejecting" << std::endl; + return expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unknown request in authenticationRequired, this is a bug.") ) ); + } + + try { + zypp::media::CredentialManager mgr ( provider().credManagerOptions() ); + + MIL << "Looking for existing auth data for " << effectiveUrl << "more recent then " << lastTimestamp << std::endl; + + auto credPtr = mgr.getCred( effectiveUrl ); + if ( credPtr && credPtr->lastDatabaseUpdate() > lastTimestamp ) { + MIL << "Found existing auth data for " << effectiveUrl << "ts: " << credPtr->lastDatabaseUpdate() << std::endl; + return expected::success( *credPtr ); + } + + if ( credPtr ) MIL << "Found existing auth data for " << effectiveUrl << "but too old ts: " << credPtr->lastDatabaseUpdate() << std::endl; + + std::string username; + if ( auto i = extraFields.find( std::string(AuthDataRequestMsgFields::LastUser) ); i != extraFields.end() ) { + username = i->second; + } + + + MIL << "NO Auth data found, asking user. Last tried username was: " << username << std::endl; + + auto userAuth = provider()._sigAuthRequired.emit( effectiveUrl, username, extraFields ); + if ( !userAuth || !userAuth->valid() ) { + MIL << "User rejected to give auth" << std::endl; + return expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("No auth given by user." ) ) ); + } + + mgr.addCred( *userAuth ); + mgr.save(); + + // rather ugly, but update the timestamp to the last mtime of the cred database our URL belongs to + // otherwise we'd need to reload the cred database + userAuth->setLastDatabaseUpdate( mgr.timestampForCredDatabase( effectiveUrl ) ); + + return expected::success(*userAuth); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + + bool ProvideItem::enqueueRequest( ProvideRequestRef request ) + { + // base item just supports one running request at a time + if ( _runningReq ) + return ( _runningReq == request ); + + _runningReq = request; + return d_func()->_parent.queueRequest( request ); + } + + void ProvideItem::updateState( const State newState ) + { + Z_D(); + if ( d->_itemState != newState ) { + + bool started = ( d->_itemState == Uninitialized && ( newState != Finished )); + auto log = provider().log(); + + const auto oldState = d->_itemState; + d->_itemState = newState; + d->_sigStateChanged( *this, oldState, d->_itemState ); + + if ( started ) { + d->_itemStarted = std::chrono::steady_clock::now(); + pulse(); + if ( log ) log->itemStart( *this ); + } + + if ( newState == Finished ) { + d->_itemFinished = std::chrono::steady_clock::now(); + pulse(); + if ( log) log->itemDone( *this ); + d->_parent.dequeueItem(this); + } + // CAREFUL, 'this' might be invalid from here on + } + } + + void ProvideItem::released() + { + if ( state() == Finished || state() == Finalizing ) + return; + + MIL << "Item Cleanup due to released Promise in state:" << state() << std::endl; + cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Cancelled by user.")) ); + } + + ProvideItem::State ProvideItem::state () const + { + return d_func()->_itemState; + } + + void ProvideRequest::setCurrentQueue( ProvideQueueRef ref ) + { + _myQueue = ref; + } + + ProvideQueueRef ProvideRequest::currentQueue() + { + return _myQueue.lock(); + } + + const std::optional ProvideRequest::activeUrl() const + { + ProvideMessage::FieldVal url; + switch ( this->_message.code () ) { + case ProvideMessage::Code::Attach: + url = _message.value( AttachMsgFields::Url ); + break; + case ProvideMessage::Code::Detach: + url = _message.value( DetachMsgFields::Url ); + break; + case ProvideMessage::Code::Prov: + url = _message.value( ProvideMsgFields::Url ); + break; + default: + // should never happen because we guard the constructor + throw std::logic_error("Invalid message type in ProvideRequest"); + } + if ( !url.valid() ) { + return {}; + } + + try { + auto u = zypp::Url( url.asString() ); + return u; + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + } + + return {}; + } + + void ProvideRequest::setActiveUrl(const zypp::Url &urlToUse) { + + switch ( this->_message.code () ) { + case ProvideMessage::Code::Attach: + this->_message.setValue( AttachMsgFields::Url, urlToUse.asCompleteString() ); + break; + case ProvideMessage::Code::Detach: + this->_message.setValue( DetachMsgFields::Url, urlToUse.asCompleteString() ); + break; + case ProvideMessage::Code::Prov: + this->_message.setValue( ProvideMsgFields::Url, urlToUse.asCompleteString() ); + break; + default: + // should never happen because we guard the constructor + throw std::logic_error("Invalid message type in ProvideRequest"); + } + } + + ProvideFileItem::ProvideFileItem(const std::vector &urls, const ProvideFileSpec &request, ProvidePrivate &parent) + : ProvideItem( parent ) + , _mirrorList ( urls ) + , _initialSpec ( request ) + { } + + ProvideFileItemRef ProvideFileItem::create(const std::vector &urls, const ProvideFileSpec &request, ProvidePrivate &parent ) + { + return ProvideFileItemRef( new ProvideFileItem( urls, request, parent ) ); + } + + void ProvideFileItem::initialize() + { + if ( state() != Uninitialized || _runningReq ) { + WAR << "Double init of ProvideFileItem!" << std::endl; + return; + } + + auto req = ProvideRequest::create( *this, _mirrorList, _initialSpec ); + if ( !req ){ + cancelWithError( req.error() ); + return ; + } + + if ( enqueueRequest( *req ) ) { + _expectedBytes = _initialSpec.downloadSize(); + updateState( Pending ); + } else { + cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) ); + return ; + } + } + + ProvidePromiseRef ProvideFileItem::promise() + { + if ( !_promiseCreated ) { + _promiseCreated = true; + auto promiseRef = std::make_shared>( shared_this() ); + _promise = promiseRef; + return promiseRef; + } + return _promise.lock(); + } + + void ProvideFileItem::setMediaRef ( Provide::MediaHandle &&hdl ) + { + _handleRef = std::move(hdl); + } + + Provide::MediaHandle &ProvideFileItem::mediaRef () + { + return _handleRef; + } + + void ProvideFileItem::informalMessage ( ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg ) + { + if ( req != _runningReq ) { + WAR << "Received event for unknown request, ignoring" << std::endl; + return; + } + + if ( msg.code() == ProvideMessage::Code::ProvideStarted ) { + MIL << "Provide File Request: "<< req->url() << " was started" << std::endl; + auto log = provider().log(); + + auto locPath = msg.value( ProvideStartedMsgFields::LocalFilename, std::string() ).asString(); + if ( !locPath.empty() ) + _targetFile = zypp::Pathname(locPath); + + locPath = msg.value( ProvideStartedMsgFields::StagingFilename, std::string() ).asString(); + if ( !locPath.empty() ) + _stagingFile = zypp::Pathname(locPath); + + if ( log ) { + auto effUrl = req->activeUrl().value_or( zypp::Url() ); + try { + effUrl = zypp::Url( msg.value( ProvideStartedMsgFields::Url).asString() ); + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + } + + AnyMap m; + m["spec"] = _initialSpec; + if ( log ) log->requestStart( *this, msg.requestId(), effUrl, m ); + updateState( Downloading ); + } + } + } + + void zyppng::ProvideFileItem::ProvideFileItem::finishReq( zyppng::ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg ) + { + if ( finishedReq != _runningReq ) { + WAR << "Received event for unknown request, ignoring" << std::endl; + return; + } + + if ( msg.code () == ProvideMessage::Code::ProvideFinished ) { + + auto log = provider().log(); + if ( log ) { + AnyMap m; + m["spec"] = _initialSpec; + if ( log ) log->requestDone( *this, msg.requestId(), m ); + } + + MIL << "Request was successfully finished!" << std::endl; + // request is def done + _runningReq.reset(); + + std::optional resFile; + + try { + const auto locFilename = msg.value( ProvideFinishedMsgFields::LocalFilename ).asString(); + const auto cacheHit = msg.value( ProvideFinishedMsgFields::CacheHit ).asBool(); + const auto &wConf = queue.workerConfig(); + + const bool checkExistsOnly = _initialSpec.checkExistsOnly(); + const bool doesDownload = wConf.worker_type() == ProvideQueue::Config::Downloading; + const bool fileNeedsCleanup = doesDownload || ( wConf.worker_type() == ProvideQueue::Config::CPUBound && wConf.cfg_flags() & ProvideQueue::Config::FileArtifacts ); + + if ( doesDownload && !checkExistsOnly ) { + + resFile = provider().addToFileCache ( locFilename ); + if ( !resFile ) { + if ( cacheHit ) { + MIL << "CACHE MISS, file " << locFilename << " was already removed, queueing again" << std::endl; + cacheMiss ( finishedReq ); + finishedReq->clearForRestart(); + enqueueRequest( finishedReq ); + return; + } else { + // if we reach here it seems that a new file, that was not in cache before, vanished between + // providing it and receiving the finished message. + // unlikely this can happen but better be safe than sorry + cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("File vanished between downloading and adding it to cache.")) ); + return; + } + } + + } else { + resFile = zypp::ManagedFile( zypp::filesystem::Pathname(locFilename) ); + if ( fileNeedsCleanup && !checkExistsOnly ) + resFile->setDispose( zypp::filesystem::unlink ); + else + resFile->resetDispose(); + } + + _targetFile = locFilename; + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + cancelWithError( std::current_exception() ); + } catch ( const std::exception &e ) { + ZYPP_CAUGHT(e); + cancelWithError( std::current_exception() ); + } catch ( ...) { + cancelWithError( std::current_exception() ); + } + + // keep the media handle around as long as the file is used by the code + auto resObj = std::make_shared(); + resObj->_mediaHandle = this->_handleRef; + resObj->_myFile = *resFile; + resObj->_resourceUrl = *(finishedReq->activeUrl()); + resObj->_responseHeaders = msg.headers(); + + // if there is a exception escaping the pipeline we need to rethrow it after cleaning up + std::exception_ptr excpt; + auto p = promise(); + if ( p ) { + try { + p->setReady( expected::success( ProvideRes( resObj )) ); + } catch( const zypp::Exception &e ) { + ERR << "Caught unhandled pipline exception:" << e << std::endl; + ZYPP_CAUGHT(e); + excpt = std::current_exception (); + } catch ( const std::exception &e ) { + ERR << "Caught unhandled pipline exception:" << e.what() << std::endl; + ZYPP_CAUGHT(e); + excpt = std::current_exception (); + } catch ( ...) { + ERR << "Caught unhandled unknown exception:" << std::endl; + excpt = std::current_exception (); + } + } + + updateState( Finished ); + + if ( excpt ) { + ERR << "Rethrowing pipeline exception, this is a BUG!" << std::endl; + std::rethrow_exception ( excpt ); + } + + } else { + ProvideItem::finishReq ( queue, finishedReq, msg ); + } + } + + + void zyppng::ProvideFileItem::cancelWithError( std::exception_ptr error ) + { + if ( _runningReq ) { + auto weakThis = weak_from_this (); + provider().dequeueRequest ( _runningReq, error ); + if ( weakThis.expired () ) + return; + } + + // if we reach this place for some reason finishReq was not called, lets clean up manually + _runningReq.reset(); + auto p = promise(); + if ( p ) { + try { + p->setReady( expected::error( error ) ); + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + } + } + updateState( Finished ); + } + + expected ProvideFileItem::authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map &extraFields ) + { + zypp::Url urlToUse = effectiveUrl; + if ( _handleRef.isValid() ) { + // if we have a attached medium this overrules the URL we are going to ask the user about... this is how the old media backend did handle this + // i guess there were never password protected repositories that have different credentials on the redirection targets + auto &attachedMedia = provider().attachedMediaInfos(); + if ( std::find( attachedMedia.begin(), attachedMedia.end(), _handleRef.mediaInfo() ) == attachedMedia.end() ) + return expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("Attachment handle vanished during request.") ) ); + urlToUse = _handleRef.mediaInfo()->_attachedUrl; + } + return ProvideItem::authenticationRequired( queue, req, urlToUse, lastTimestamp, extraFields ); + } + + ProvideFileItem::ItemStats ProvideFileItem::makeStats () + { + zypp::ByteCount providedByNow; + + bool checkStaging = false; + if ( !_targetFile.empty() ) { + zypp::PathInfo inf( _targetFile ); + if ( inf.isExist() && inf.isFile() ) + providedByNow = zypp::ByteCount( inf.size() ); + else + checkStaging = true; + } + + if ( checkStaging && !_stagingFile.empty() ) { + zypp::PathInfo inf( _stagingFile ); + if ( inf.isExist() && inf.isFile() ) + providedByNow = zypp::ByteCount( inf.size() ); + } + + auto baseStats = ProvideItem::makeStats(); + baseStats._bytesExpected = bytesExpected(); + baseStats._bytesProvided = providedByNow; + return baseStats; + } + + zypp::ByteCount ProvideFileItem::bytesExpected () const + { + return (_initialSpec.checkExistsOnly() ? zypp::ByteCount(0) : _expectedBytes); + } + + AttachMediaItem::AttachMediaItem( const std::vector &urls, const ProvideMediaSpec &request, ProvidePrivate &parent ) + : ProvideItem ( parent ) + , _mirrorList ( urls ) + , _initialSpec ( request ) + { } + + AttachMediaItem::~AttachMediaItem() + { + MIL << "Killing the AttachMediaItem" << std::endl; + } + + ProvidePromiseRef AttachMediaItem::promise() + { + if ( !_promiseCreated ) { + _promiseCreated = true; + auto promiseRef = std::make_shared>( shared_this() ); + _promise = promiseRef; + return promiseRef; + } + return _promise.lock(); + } + + void AttachMediaItem::initialize() + { + if ( state() != Uninitialized ) { + WAR << "Double init of AttachMediaItem!" << std::endl; + return; + } + updateState(Processing); + + if ( _mirrorList.empty() ) { + cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("No usable mirrors in mirrorlist.")) ); + return; + } + + // shortcut to the provider instance + auto &prov= provider(); + + // sanitize the mirrors to contain only URLs that have same worker types + std::vector usableMirrs; + std::optional scheme; + + for ( auto mirrIt = _mirrorList.begin() ; mirrIt != _mirrorList.end(); mirrIt++ ) { + const auto &s = prov.schemeConfig( prov.effectiveScheme( mirrIt->getScheme() ) ); + if ( !s ) { + WAR << "URL: " << *mirrIt << " is not supported, ignoring!" << std::endl; + continue; + } + if ( !scheme ) { + scheme = *s; + usableMirrs.push_back ( *mirrIt ); + } else { + if ( scheme->worker_type () == s->worker_type () ) { + usableMirrs.push_back( *mirrIt ); + } else { + WAR << "URL: " << *mirrIt << " has different worker type than the primary URL: "<< usableMirrs.front() <<", ignoring!" << std::endl; + } + } + } + + // save the sanitized mirrors + _mirrorList = usableMirrs; + + if ( !scheme || _mirrorList.empty() ) { + auto prom = promise(); + if ( prom ) { + try { + prom->setReady( expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No valid mirrors available") )) ); + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + } + } + updateState( Finished ); + return; + } + + // first check if there is a already attached medium we can use as well + auto &attachedMedia = prov.attachedMediaInfos (); + + for ( auto &medium : attachedMedia ) { + if ( medium->isSameMedium ( _mirrorList, _initialSpec ) ) { + finishWithSuccess ( medium ); + return; + } + } + + for ( auto &otherItem : prov.items() ) { + auto attachIt = std::dynamic_pointer_cast(otherItem); + if ( !attachIt // not the right type + || attachIt.get() == this // do not attach to ourselves + || attachIt->state () == Uninitialized // item was not initialized + || attachIt->state () == Finalizing // item cleaning up + || attachIt->state () == Finished ) // item done + continue; + + // does this Item attach the same medium? + const auto sameMedium = attachIt->_initialSpec.isSameMedium( _initialSpec); + if ( zypp::indeterminate(sameMedium) ) { + // check the primary URLs ( should we do a full list compare? ) + if ( attachIt->_mirrorList.front() != _mirrorList.front() ) + continue; + } + else if ( !(bool)sameMedium ) + continue; + + MIL << "Found item providing the same medium, attaching to finished signal and waiting for it to be finished" << std::endl; + + // it does, connect to its ready signal and just wait + _masterItemConn = connect( *attachIt, &AttachMediaItem::sigReady, *this, &AttachMediaItem::onMasterItemReady ); + return; + } + + _workerType = scheme->worker_type(); + + switch( _workerType ) { + case ProvideQueue::Config::Downloading: { + + // if the media file is empty in the spec we can not do anything + // simply pretend attach worked + if( _initialSpec.mediaFile().empty() ) { + finishWithSuccess( prov.addMedium( zypp::make_intrusive( provider().nextMediaId(), _workerType, _mirrorList.front(), _initialSpec ) ) ); + return; + } + + // prepare the verifier with the data + auto smvDataLocal = MediaDataVerifier::createVerifier("SuseMediaV1"); + if ( !smvDataLocal ) { + cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, no verifier instance was returned.")) ); + return; + } + + if ( !smvDataLocal->load( _initialSpec.mediaFile() ) ) { + cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, unable to load local verify data.")) ); + return; + } + + _verifier = smvDataLocal; + + std::vector urls; + urls.reserve( _mirrorList.size () ); + + for ( zypp::Url url : _mirrorList ) { + url.appendPathName ( ( zypp::str::Format("/media.%d/media") % _initialSpec.medianr() ).asString() ); + urls.push_back(url); + } + + // for downloading schemes we ask for the /media.x/media file and check the data manually + ProvideFileSpec spec; + spec.customHeaders() = _initialSpec.customHeaders(); + + // disable metalink + spec.customHeaders().set( std::string(NETWORK_METALINK_ENABLED), false ); + + auto req = ProvideRequest::create( *this, urls, spec ); + if ( !req ) { + cancelWithError( req.error() ); + return; + } + if ( !enqueueRequest( *req ) ) { + cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) ); + return; + } + updateState ( Downloading ); + break; + } + case ProvideQueue::Config::VolatileMount: + case ProvideQueue::Config::SimpleMount: { + + const auto &newId = provider().nextMediaId(); + auto req = ProvideRequest::create( *this, _mirrorList, newId, _initialSpec ); + if ( !req ) { + cancelWithError( req.error() ); + return; + } + if ( !enqueueRequest( *req ) ) { + ERR << "Failed to queue request" << std::endl; + cancelWithError( ZYPP_EXCPT_PTR(zypp::media::MediaException("Failed to queue request")) ); + return; + } + break; + } + default: { + auto prom = promise(); + if ( prom ) { + try { + prom->setReady( expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("URL scheme does not support attaching.") )) ); + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + } + } + updateState( Finished ); + return; + } + } + } + + void AttachMediaItem::finishWithSuccess( AttachedMediaInfo_Ptr medium ) + { + + updateState(Finalizing); + + auto prom = promise(); + try { + if ( prom ) { + try { + prom->setReady( expected::success( Provide::MediaHandle( *static_cast( provider().z_func() ), medium ) ) ); + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + } + } + } catch ( const std::exception &e ) { + ERR << "WTF " << e.what () << std::endl; + } catch ( ... ) { + ERR << "WTF " << std::endl; + } + + // tell others as well + _sigReady.emit( zyppng::expected::success(medium.get()) ); + + prom->isReady (); + + MIL << "Before setFinished" << std::endl; + updateState( Finished ); + return; + } + + void AttachMediaItem::cancelWithError( std::exception_ptr error ) + { + MIL << "Cancelling Item with error" << std::endl; + updateState(Finalizing); + + // tell children + _sigReady.emit( expected::error(error) ); + + if ( _runningReq ) { + // we might get deleted when calling dequeueRequest + auto weakThis = weak_from_this (); + provider().dequeueRequest ( _runningReq, error ); + if ( weakThis.expired () ) + return; + } + + // if we reach this place we had no runningReq, clean up manually + _runningReq.reset(); + _masterItemConn.disconnect(); + + auto p = promise(); + if ( p ) { + try { + p->setReady( expected::error( error ) ); + } catch( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + } + } + updateState( Finished ); + } + + void AttachMediaItem::onMasterItemReady( const zyppng::expected &result ) + { + + _masterItemConn.disconnect(); + + if ( result ) { + finishWithSuccess( AttachedMediaInfo_Ptr(result.get()) ); + } else { + try { + std::rethrow_exception ( result.error() ); + } catch ( const zypp::media::MediaRequestCancelledException & e) { + // in case a item was cancelled, we revert to Pending state and trigger the scheduler. + // This will make sure that all our sibilings that also depend on the master + // can revert to pending state and we only get one new master in the next schedule run + MIL_PRV << "Master item was cancelled, reverting to Uninitialized state and waiting for scheduler to run again" << std::endl; + updateState (Uninitialized); + provider().schedule( ProvidePrivate::RestartAttach ); + + } catch ( ... ) { + cancelWithError( std::current_exception() ); + } + } + } + + AttachMediaItemRef AttachMediaItem::create( const std::vector &urls, const ProvideMediaSpec &request, ProvidePrivate &parent ) + { + return AttachMediaItemRef( new AttachMediaItem(urls, request, parent) ); + } + + SignalProxy &)> AttachMediaItem::sigReady() + { + return _sigReady; + } + + void AttachMediaItem::finishReq ( ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg ) + { + if ( finishedReq != _runningReq ) { + WAR << "Received event for unknown request, ignoring" << std::endl; + return; + } + + if( _workerType == ProvideQueue::Config::Downloading ) { + // success + if ( msg.code() == ProvideMessage::Code::ProvideFinished ) { + + updateState(Finalizing); + + zypp::Url baseUrl = *finishedReq->activeUrl(); + // remove /media.n/media + baseUrl.setPathName( zypp::Pathname(baseUrl.getPathName()).dirname().dirname() ); + + // we got the file, lets parse it + auto smvDataRemote = MediaDataVerifier::createVerifier("SuseMediaV1"); + if ( !smvDataRemote ) { + return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, no verifier instance was returned.")) ); + } + + if ( !smvDataRemote->load( msg.value( ProvideFinishedMsgFields::LocalFilename ).asString() ) ) { + return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, unable to load remote verify data.")) ); + } + + // check if we got a valid media file + if ( !smvDataRemote->valid () ) { + return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unable to verify the medium, unable to load local verify data.")) ); + } + + // check if the received file matches with the one we have in the spec + if (! _verifier->matches( smvDataRemote ) ) { + DBG << "expect: " << _verifier << " medium " << _initialSpec.medianr() << std::endl; + DBG << "remote: " << smvDataRemote << std::endl; + return cancelWithError( ZYPP_EXCPT_PTR( zypp::media::MediaNotDesiredException( *finishedReq->activeUrl() ) ) ); + } + + // all good, register the medium and tell all child items + _runningReq.reset(); + return finishWithSuccess( provider().addMedium( zypp::make_intrusive( provider().nextMediaId(), _workerType, baseUrl, _initialSpec) ) ); + + } else if ( msg.code() == ProvideMessage::Code::NotFound ) { + + // simple downloading attachment we need to check the media file contents + // in case of a error we might tolerate a file not found error in certain situations + if ( _verifier->totalMedia () == 1 ) { + // relaxed , tolerate a vanished media file + _runningReq.reset(); + + return finishWithSuccess( provider().addMedium( zypp::make_intrusive( provider().nextMediaId(), _workerType, _mirrorList.front(), _initialSpec ) ) ); + } else { + return ProvideItem::finishReq ( queue, finishedReq, msg ); + } + } else { + return ProvideItem::finishReq ( queue, finishedReq, msg ); + } + } else { + // real device attach + if ( msg.code() == ProvideMessage::Code::AttachFinished ) { + + std::optional mntPoint; + auto mountPtVal = msg.value( zyppng::AttachFinishedMsgFields::LocalMountPoint ); + if ( mountPtVal.valid() && mountPtVal.isString() ) { + mntPoint = zypp::Pathname(mountPtVal.asString()); + } + + _runningReq.reset(); + return finishWithSuccess( provider().addMedium( zypp::make_intrusive( + finishedReq->provideMessage().value( AttachMsgFields::AttachId ).asString() + , queue.weak_this() + , _workerType + , *finishedReq->activeUrl() + , _initialSpec + , mntPoint ) ) ); + } + } + + // unhandled message , let the base impl do it + return ProvideItem::finishReq ( queue, finishedReq, msg ); + } + + expected AttachMediaItem::authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map &extraFields ) + { + zypp::Url baseUrl = effectiveUrl; + if( _workerType == ProvideQueue::Config::Downloading ) { + // remove /media.n/media + baseUrl.setPathName( zypp::Pathname(baseUrl.getPathName()).dirname().dirname() ); + } + return ProvideItem::authenticationRequired( queue, req, baseUrl, lastTimestamp, extraFields ); + } + +} diff --git a/zypp-media/ng/provideitem.h b/zypp-media/ng/provideitem.h new file mode 100644 index 0000000..b3eddbc --- /dev/null +++ b/zypp-media/ng/provideitem.h @@ -0,0 +1,192 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_MEDIA_PROVIDEITEM_H_INCLUDED +#define ZYPP_MEDIA_PROVIDEITEM_H_INCLUDED + +#include +#include +#include +#include + +namespace zyppng +{ + class ProvidePrivate; + class ProvideItemPrivate; + + /*! + * Represents a operation added to the provide queue by the user code. A "user" operation can have multiple + * steps of downloading and processing one or multiple files. Even though this class is in public API space it's + * not possible to implement custom Items since more internal API would be required for it. It is only public to + * support the \ref ProvideStatus class, so it can query details of a Item. + */ + class ProvideItem : public Base + { + ZYPP_DECLARE_PRIVATE(ProvideItem); + friend class Provide; + friend class ProvidePrivate; + friend class ProvideQueue; + public: + enum State { + Uninitialized, //< Item was added to the queue but not yet initialized + Pending, //< The Item is waiting to be queued and does nothing + Downloading, //< The Item is fetching data + Processing, //< The Item has fetched all data but is still doing other things + Cancelling, //< The Item was cancelled and waits + Finalizing, //< The Item has finished all work and is currently cleaning up + Finished //< The Item is done and can be dequeued + }; + + struct ItemStats { + std::chrono::steady_clock::time_point _pulseTime; + uint _runningRequests; + zypp::ByteCount _bytesProvided; + zypp::ByteCount _bytesExpected; + }; + + ProvideItem( ProvidePrivate &parent ); + ~ProvideItem (); + + /*! + * Called by the controller when the item is supposed to start fetching / processing + */ + virtual void initialize () = 0; + + /*! + * Called when the promise reference is released by the user process, cancel all running requests if there are any and clean up + */ + virtual void released (); + + State state () const; + + /*! + * Signal that is emitted when the state of the Item has changed + */ + SignalProxy sigStateChanged(); + + ProvidePrivate &provider(); + + /*! + * Returns true if a redirect is allowed and does not conflict with previous redirects. + * Otherwise false is returned. This does not remember the passed URL as a redirect + */ + virtual bool canRedirectTo ( ProvideRequestRef startedReq, const zypp::Url &url ); + + /*! + * Returns the item statistics that were collected the last time pulse() was called on the item. + * If the item has not been started yet, this returns a empty optional + */ + const std::optional ¤tStats() const; + + /*! + * Returns the item statistics that were collected the previous time pulse() was called on the item. + * \note The item needs to be started and pulse() needs to be called at least once for this func to return something + */ + const std::optional &previousStats() const; + + /*! + * Returns the time point when the item started to process/download. + * If the item has not started yet, this returns epoch + */ + virtual std::chrono::steady_clock::time_point startTime() const; + + /*! + * Returns the time point when the item was finished. + * If the item was not finished yet, this returns epoch + */ + virtual std::chrono::steady_clock::time_point finishedTime() const; + + /*! + * Updates the item statistics, this is called automatically by the \ref Provide instance and usually does not + * need to be called explicitely by usercode. + */ + void pulse (); + + /*! + * Returns the bytes the item expects to provide, the default impl returns 0 + */ + virtual zypp::ByteCount bytesExpected () const; + + protected: + virtual ItemStats makeStats (); + + /*! + * Request received a informal message, e.g. ProvideStarted + */ + virtual void informalMessage ( ProvideQueue &, ProvideRequestRef req, const ProvideMessage &msg ); + + /*! + * Request had a cache miss and will be queued again, forget all about the request + */ + virtual void cacheMiss ( ProvideRequestRef req ); + + /*! + * Request was finished by the queue + * Base implementation handles redirect, metalink and error messages. If a different message is + * received, \ref cancelWithError is called. + * + * A subclass has to overload this function to handle success messages + */ + virtual void finishReq ( ProvideQueue &queue, ProvideRequestRef finishedReq, const ProvideMessage &msg ); + + /*! + * Request was finished with a error + * The base implementation simply calls \ref cancelWithError + * + * \note \a queue is allowed to be a nullptr here + */ + virtual void finishReq ( ProvideQueue *queue, ProvideRequestRef finishedReq, const std::exception_ptr excpt ); + + /*! + * Request needs authentication data, the function is supposed to return the AuthData to use for the response, or an error + * The default implementation simply uses the given URL to look for a Auth match in the \ref zypp::media::CredentialManager. + */ + virtual expected authenticationRequired ( ProvideQueue &queue, ProvideRequestRef req, const zypp::Url &effectiveUrl, int64_t lastTimestamp, const std::map &extraFields ); + + /*! + * Remembers previous redirects and returns false if the URL was encountered before, use this + * to prevent the item getting caught in a redirect loop + */ + bool safeRedirectTo ( ProvideRequestRef startedReq, const zypp::Url &url ); + + /*! + * Similar to \ref safeRedirectTo, but does not check if a URL was already used by this Request before. + */ + void redirectTo ( ProvideRequestRef startedReq, const zypp::Url &url ); + + /*! + * Enqueue the request in the correct queue, the item implementation is supposed to hold its own + * reference to all started requests, the base implementation just keeps track of 1 request at a time. + */ + virtual bool enqueueRequest( ProvideRequestRef request ); + + /*! + * Cancels all running requests and immediately moves to error state + */ + virtual void cancelWithError ( std::exception_ptr error ) = 0; + + /*! + * Dequeue this item and stop all requests in queues running + * Call this when the item is cancelled or finished. + */ + bool dequeue (); + + /*! + * Call this when the state of the item changes. + * + * \note calling updateState with state \ref Finished will potentially delete the Item instance + */ + void updateState( const State newState ); + + void setFinished (); + + protected: + ProvideRequestRef _runningReq; + }; +} +#endif // ZYPP_MEDIA_PROVIDEITEM_H_INCLUDED diff --git a/zypp-media/ng/providemessage.cc b/zypp-media/ng/providemessage.cc new file mode 100644 index 0000000..a5823f4 --- /dev/null +++ b/zypp-media/ng/providemessage.cc @@ -0,0 +1,712 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "private/providemessage_p.h" +#include "zypp-core/zyppng/rpc/stompframestream.h" + +#include +#include +#include + +namespace zyppng { + + zyppng::expected ProviderConfiguration::toStompMessage() const + { + auto frame = rpc::prepareFrame(); + for ( const auto &v : *this ) { + frame.addHeader( v.first, v.second ); + } + return zyppng::expected::success( std::move(frame) ); + } + + zyppng::expected ProviderConfiguration::fromStompMessage(const zypp::PluginFrame &msg) + { + try { + if ( msg.command() != ProviderConfiguration::typeName ) + ZYPP_THROW( InvalidMessageReceivedException("Message is not of type ProviderConfiguration") ); + + ProviderConfiguration res; + for ( auto i = msg.headerBegin (); i != msg.headerEnd(); i++ ) { + res.insert_or_assign ( i->first, i->second ); + } + + return zyppng::expected::success ( std::move(res) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + /*! + * Worker Capabilities , sent by the workers to the provider + */ + WorkerCaps::WorkerCaps() + { } + + WorkerCaps::~WorkerCaps() + { } + + uint32_t WorkerCaps::protocol_version() const + { + return _protocolVersion; + } + + WorkerCaps::WorkerType WorkerCaps::worker_type() const + { + return static_cast(_workerType); + } + + WorkerCaps::Flags WorkerCaps::cfg_flags() const + { + return static_cast(_cfgFlags); + } + + const std::string &WorkerCaps::worker_name() const + { + return _workerName; + } + + void WorkerCaps::set_protocol_version(uint32_t v) + { + _protocolVersion = v; + } + + void WorkerCaps::set_worker_type(WorkerType t) + { + _workerType = t; + } + + void WorkerCaps::set_cfg_flags(Flags f) + { + _cfgFlags = f; + } + + void WorkerCaps::set_worker_name(std::string name) + { + _workerName = std::move(name); + } + + zyppng::expected WorkerCaps::toStompMessage() const + { + try { + zypp::PluginFrame pf = zyppng::rpc::prepareFrame(); + pf.addHeader ( "protocolVersion", zypp::str::asString (_protocolVersion) ); + pf.addHeader ( "workerType" , zypp::str::asString (_workerType) ); + pf.addHeader ( "cfgFlags" , zypp::str::asString (_cfgFlags) ); + pf.addHeader ( "workerName" , zypp::str::asString (_workerName) ); + return zyppng::expected::success ( std::move(pf) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + zyppng::expected WorkerCaps::fromStompMessage(const zypp::PluginFrame &msg) + { + try { + if ( msg.command() != WorkerCaps::typeName ) + ZYPP_THROW( InvalidMessageReceivedException("Message is not of type WorkerCaps") ); + + WorkerCaps res; + zyppng::rpc::parseHeaderIntoField( msg, "protocolVersion", res._protocolVersion ); + zyppng::rpc::parseHeaderIntoField( msg, "workerType", res._workerType ); + zyppng::rpc::parseHeaderIntoField( msg, "cfgFlags", res._cfgFlags ); + zyppng::rpc::parseHeaderIntoField( msg, "workerName", res._workerName ); + return zyppng::expected::success ( std::move(res) ); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT (e); + return zyppng::expected::error( ZYPP_EXCPT_PTR(e) ); + } + } + + template + static zyppng::expected doParseField( const std::string &val, ProvideMessage &t, std::string_view msgtype, std::string_view name ) { + try { + T tVal; // the target value type + zyppng::rpc::parseDataIntoField ( val, tVal ); + t.addValue( name, std::move(tVal) ); + return zyppng::expected::success(); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + return zyppng::expected::error( ZYPP_EXCPT_PTR( InvalidMessageReceivedException( zypp::str::Str() << "Parse error " << msgtype << ", Field " << name << " has invalid type" ) ) ); + } + } + + ProvideMessage::ProvideMessage() + { } + + expected ProvideMessage::create(const zypp::PluginFrame &msg) + { + if ( msg.command() != ProvideMessage::typeName ) { + return zyppng::expected::error( ZYPP_EXCPT_PTR( InvalidMessageReceivedException("Message is not of type WorkerCaps") ) ); + } + + const std::string &codeStr = msg.getHeaderNT( std::string(ProvideMessageFields::RequestCode) ); + if ( codeStr.empty () ) { + return zyppng::expected::error( ZYPP_EXCPT_PTR ( InvalidMessageReceivedException("Invalid message, PluginFrame has no requestId header.")) ); + } + + const auto c = zyppng::str::safe_strtonum( codeStr ).value_or ( NoCode ); + const auto validCode = ( c >= ProvideMessage::Code::FirstInformalCode && c <= ProvideMessage::Code::LastInformalCode ) + || ( c >= ProvideMessage::Code::FirstSuccessCode && c <= ProvideMessage::Code::LastSuccessCode ) + || ( c >= ProvideMessage::Code::FirstRedirCode && c <= ProvideMessage::Code::LastRedirCode ) + || ( c >= ProvideMessage::Code::FirstClientErrCode && c <= ProvideMessage::Code::LastClientErrCode ) + || ( c >= ProvideMessage::Code::FirstSrvErrCode && c <= ProvideMessage::Code::LastSrvErrCode ) + || ( c >= ProvideMessage::Code::FirstControllerCode && c <= ProvideMessage::Code::LastControllerCode) + || ( c >= ProvideMessage::Code::FirstWorkerCode && c <= ProvideMessage::Code::LastWorkerCode ); + if ( !validCode ) { + return zyppng::expected::error( ZYPP_EXCPT_PTR ( InvalidMessageReceivedException("Invalid code in PluginFrame")) ); + } + + const std::string & idStr = msg.getHeaderNT( std::string(ProvideMessageFields::RequestId) ); + if ( idStr.empty () ) { + return zyppng::expected::error( ZYPP_EXCPT_PTR ( InvalidMessageReceivedException("Invalid message, PluginFrame has no requestId header.")) ); + } + + const auto &maybeId = zyppng::str::safe_strtonum( idStr ); + if ( !maybeId ) { + return zyppng::expected::error( ZYPP_EXCPT_PTR ( InvalidMessageReceivedException("Invalid message, can not parse requestId header.")) ); + } + + ProvideMessage pMessage; + pMessage.setCode ( static_cast(c) ); + pMessage.setRequestId ( *maybeId ); + + #define DEF_REQ_FIELD( fname ) bool has_##fname = false + + #define PARSE_FIELD( msgtype, fname, ftype, _C_ ) \ + if ( name == #fname ) { \ + const auto &res = doParseField( val, pMessage, #msgtype, #fname ); \ + if ( !res ) { \ + return zyppng::expected::error(res.error()); \ + } \ + _C_ \ + } + + #define HANDLE_UNKNOWN_FIELD( fname, val ) { \ + pMessage.addValue( fname, val ); \ + } + + #define OR_HANDLE_UNKNOWN_FIELD( fname, val ) else HANDLE_UNKNOWN_FIELD( fname, val ) + + #define BEGIN_PARSE_HEADERS \ + for ( const auto &header : msg.headerList() ) { \ + const auto &name = header.first; \ + const auto &val = header.second; + + #define END_PARSE_HEADERS } + + #define PARSE_REQ_FIELD( msgtype, fname, ftype ) PARSE_FIELD( msgtype, fname, ftype, has_##fname = true; ) + #define OR_PARSE_REQ_FIELD( msgtype, fname, ftype ) else PARSE_REQ_FIELD( msgtype, fname, ftype ) + #define PARSE_OPT_FIELD( msgtype, fname, ftype ) PARSE_FIELD( msgtype, fname, ftype, ) + #define OR_PARSE_OPT_FIELD( msgtype, fname, ftype ) else PARSE_OPT_FIELD( msgtype, fname, ftype ) + + #define FAIL_IF_NOT_SEEN_REQ_FIELD( msgtype, fname ) \ + if ( !has_##fname ) \ + return expected::error( ZYPP_EXCPT_PTR( InvalidMessageReceivedException( zypp::str::Str() << #msgtype <<" message does not contain required " << #fname << " field" ) ) ) + + auto validateErrorMsg = [&]( const auto &msg ){ + DEF_REQ_FIELD(reason); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( Error, reason, std::string ) + OR_PARSE_OPT_FIELD ( Error, history, std::string ) + OR_PARSE_OPT_FIELD ( Error, transient, bool ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( Error, reason ); + return expected::success( std::move(pMessage) ); + }; + + switch ( c ) + { + case ProvideMessage::Code::ProvideStarted: { + DEF_REQ_FIELD(url); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( ProvideStarted, url, std::string ) + OR_PARSE_OPT_FIELD ( ProvideStarted, local_filename, std::string ) + OR_PARSE_OPT_FIELD ( ProvideStarted, staging_filename, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( ProvideStarted, url ); + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::ProvideFinished: { + DEF_REQ_FIELD(cacheHit); + DEF_REQ_FIELD(local_filename); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( ProvideFinished, cacheHit, bool ) + OR_PARSE_REQ_FIELD ( ProvideFinished, local_filename, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( ProvideFinished, cacheHit ); + FAIL_IF_NOT_SEEN_REQ_FIELD( ProvideFinished, local_filename ); + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::AttachFinished: { + BEGIN_PARSE_HEADERS + PARSE_OPT_FIELD ( AttachFinished, local_mountpoint, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::DetachFinished: { + // no known fields + BEGIN_PARSE_HEADERS + HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::AuthInfo: { + DEF_REQ_FIELD(username); + DEF_REQ_FIELD(password); + DEF_REQ_FIELD(auth_timestamp); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( AuthInfo, username, std::string ) + OR_PARSE_REQ_FIELD ( AuthInfo, password, std::string ) + OR_PARSE_REQ_FIELD ( AuthInfo, auth_timestamp, int64_t ) + OR_PARSE_OPT_FIELD ( AuthInfo, authType, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( ProvideStarted, username ); + FAIL_IF_NOT_SEEN_REQ_FIELD( ProvideStarted, password ); + FAIL_IF_NOT_SEEN_REQ_FIELD( ProvideStarted, auth_timestamp ); + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::MediaChanged: + // no known fields + BEGIN_PARSE_HEADERS + HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + return expected::success( std::move(pMessage) ); + + case ProvideMessage::Code::Redirect: { + DEF_REQ_FIELD(new_url); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( Redirect, new_url, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( Redirect, new_url ); + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::Metalink: { + DEF_REQ_FIELD(new_url); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( Metalink, new_url, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( Metalink, new_url ); + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::BadRequest: + case ProvideMessage::Code::Unauthorized: + case ProvideMessage::Code::Forbidden: + case ProvideMessage::Code::PeerCertificateInvalid: + case ProvideMessage::Code::NotFound: + case ProvideMessage::Code::ExpectedSizeExceeded: + case ProvideMessage::Code::ConnectionFailed: + case ProvideMessage::Code::Timeout: + case ProvideMessage::Code::Cancelled: + case ProvideMessage::Code::InvalidChecksum: + case ProvideMessage::Code::MountFailed: + case ProvideMessage::Code::Jammed: + case ProvideMessage::Code::NoAuthData: + case ProvideMessage::Code::MediaChangeAbort: + case ProvideMessage::Code::MediaChangeSkip: + case ProvideMessage::Code::InternalError: { + return validateErrorMsg(msg); + } + case ProvideMessage::Code::Prov: { + DEF_REQ_FIELD(url); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( Provide, url, std::string ) + OR_PARSE_OPT_FIELD ( Provide, filename, std::string ) + OR_PARSE_OPT_FIELD ( Provide, delta_file, std::string ) + OR_PARSE_OPT_FIELD ( Provide, expected_filesize, int64_t ) + OR_PARSE_OPT_FIELD ( Provide, check_existance_only, bool ) + OR_PARSE_OPT_FIELD ( Provide, metalink_enabled, bool ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( Provide, url ); + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::Cancel: + // no known fields + BEGIN_PARSE_HEADERS + HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + return expected::success( std::move(pMessage) ); + + case ProvideMessage::Code::Attach: { + std::exception_ptr error; + + DEF_REQ_FIELD(url); + DEF_REQ_FIELD(attach_id); + DEF_REQ_FIELD(label); + + // not really required, but this way we can check if all false or all true + DEF_REQ_FIELD(verify_type); + DEF_REQ_FIELD(verify_data); + DEF_REQ_FIELD(media_nr); + + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( Attach, url , std::string ) + OR_PARSE_REQ_FIELD ( Attach, attach_id , std::string ) + OR_PARSE_REQ_FIELD ( Attach, label , std::string ) + OR_PARSE_REQ_FIELD ( Attach, verify_type, std::string ) + OR_PARSE_REQ_FIELD ( Attach, verify_data, std::string ) + OR_PARSE_REQ_FIELD ( Attach, media_nr , int32_t ) + OR_PARSE_OPT_FIELD ( Attach, device , std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( Provide, url ); + FAIL_IF_NOT_SEEN_REQ_FIELD( Provide, label ); + FAIL_IF_NOT_SEEN_REQ_FIELD( Provide, attach_id ); + if ( ! ( ( has_verify_data == has_verify_type ) && ( has_verify_type == has_media_nr ) ) ) + return expected::error( ZYPP_EXCPT_PTR ( InvalidMessageReceivedException("Error in Attach message, one of the following fields is not set or invalid: ( verify_type, verify_data, media_nr ). Either none or all need to be set. ")) ); + + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::Detach: { + DEF_REQ_FIELD(url); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( Detach, url, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( Detach, url ); + + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::AuthDataRequest: { + DEF_REQ_FIELD(effective_url); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( AuthDataRequest, effective_url, std::string ) + OR_PARSE_OPT_FIELD ( AuthDataRequest, last_auth_timestamp, int64_t ) + OR_PARSE_OPT_FIELD ( AuthDataRequest, username, std::string ) + OR_PARSE_OPT_FIELD ( AuthDataRequest, authHint, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( AuthDataRequest, effective_url ); + + return expected::success( std::move(pMessage) ); + } + case ProvideMessage::Code::MediaChangeRequest: { + DEF_REQ_FIELD(label); + DEF_REQ_FIELD(media_nr); + DEF_REQ_FIELD(device); + BEGIN_PARSE_HEADERS + PARSE_REQ_FIELD ( MediaChangeRequest, label, std::string ) + OR_PARSE_REQ_FIELD ( MediaChangeRequest, media_nr, int32_t ) + OR_PARSE_REQ_FIELD ( MediaChangeRequest, device, std::string ) + OR_PARSE_OPT_FIELD ( MediaChangeRequest, desc, std::string ) + OR_HANDLE_UNKNOWN_FIELD( name, val ) + END_PARSE_HEADERS + FAIL_IF_NOT_SEEN_REQ_FIELD( MediaChangeRequest, label ); + FAIL_IF_NOT_SEEN_REQ_FIELD( MediaChangeRequest, media_nr ); + FAIL_IF_NOT_SEEN_REQ_FIELD( MediaChangeRequest, device ); + + return expected::success( std::move(pMessage) ); + } + default: { + // all error messages have the same format + if ( c >= ProvideMessage::Code::FirstClientErrCode && c <= ProvideMessage::Code::LastSrvErrCode ) { + return validateErrorMsg(msg); + } + } + } + + // we should never reach this line because we check in the beginning if the know the message code + return zyppng::expected::error( ZYPP_EXCPT_PTR ( InvalidMessageReceivedException("Unknown code in PluginFrame")) ); + } + + expected ProvideMessage::toStompMessage() const + { + zypp::PluginFrame f = rpc::prepareFrame(); + f.addHeader ( std::string(ProvideMessageFields::RequestCode), zypp::str::asString (static_cast(_code)) ); + f.addHeader ( std::string(ProvideMessageFields::RequestId), zypp::str::asString (_reqId) ); + for ( auto i = _headers.beginList (); i != _headers.endList(); i++ ) { + for ( const auto &val : i->second ) { + const auto &strVal = std::visit([&]( const auto &val ){ + if constexpr( std::is_same_v, std::monostate> ) + return std::string(); + else { + return zypp::str::asString(val); + } + }, val.asVariant() ); + if ( strVal.empty () ) + continue; + f.addHeader( i->first, strVal ); + } + } + + return expected::success ( std::move(f) ); + } + + expected ProvideMessage::fromStompMessage(const zypp::PluginFrame &msg) + { + return ProvideMessage::create(msg); + } + + ProvideMessage ProvideMessage::createProvideStarted( const uint32_t reqId, const zypp::Url &url, const std::optional &localFilename, const std::optional &stagingFilename ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::ProvideStarted ); + msg.setRequestId ( reqId ); + msg.setValue ( ProvideStartedMsgFields::Url, url.asCompleteString() ); + if ( localFilename ) + msg.setValue ( ProvideStartedMsgFields::LocalFilename, *localFilename ); + if ( stagingFilename ) + msg.setValue ( ProvideStartedMsgFields::StagingFilename, *stagingFilename ); + + return msg; + } + + ProvideMessage ProvideMessage::createProvideFinished( const uint32_t reqId, const std::string &localFilename, bool cacheHit ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::ProvideFinished ); + msg.setRequestId ( reqId ); + msg.setValue ( ProvideFinishedMsgFields::LocalFilename, localFilename ); + msg.setValue ( ProvideFinishedMsgFields::CacheHit, cacheHit ); + + return msg; + } + + ProvideMessage ProvideMessage::createAttachFinished(const uint32_t reqId , const std::optional &localMountPoint ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::AttachFinished ); + msg.setRequestId ( reqId ); + + if ( localMountPoint ) + msg.setValue ( AttachFinishedMsgFields::LocalMountPoint, *localMountPoint ); + + return msg; + } + + ProvideMessage ProvideMessage::createDetachFinished(const uint32_t reqId) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::DetachFinished ); + msg.setRequestId ( reqId ); + + return msg; + } + + ProvideMessage ProvideMessage::createAuthInfo( const uint32_t reqId, const std::string &user, const std::string &pw, int64_t timestamp, const std::map &extraValues ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::AuthInfo ); + msg.setRequestId ( reqId ); + msg.setValue ( AuthInfoMsgFields::Username, user ); + msg.setValue ( AuthInfoMsgFields::Password, pw ); + msg.setValue ( AuthInfoMsgFields::AuthTimestamp, timestamp ); + for ( auto i : extraValues ) { + msg.setValue( i.first, i.second ); + } + return msg; + } + + ProvideMessage ProvideMessage::createMediaChanged( const uint32_t reqId ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::MediaChanged ); + msg.setRequestId ( reqId ); + + return msg; + } + + ProvideMessage ProvideMessage::createRedirect( const uint32_t reqId, const zypp::Url &newUrl ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::Redirect ); + msg.setRequestId ( reqId ); + msg.setValue ( RedirectMsgFields::NewUrl, newUrl.asCompleteString() ); + + return msg; + } + + ProvideMessage ProvideMessage::createMetalinkRedir( const uint32_t reqId, const std::vector &newUrls ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::Metalink ); + msg.setRequestId ( reqId ); + for( const auto &val : newUrls ) + msg.addValue( MetalinkRedirectMsgFields::NewUrl, val.asCompleteString() ); + + return msg; + } + + ProvideMessage ProvideMessage::createErrorResponse( const uint32_t reqId, const Code code, const std::string &reason, bool transient ) + { + ProvideMessage msg; + if ( code < Code::FirstClientErrCode || code > Code::LastSrvErrCode ) + ZYPP_THROW(std::out_of_range("code must be between 400 and 599")); + msg.setCode ( code ); + msg.setRequestId ( reqId ); + msg.setValue ( ErrMsgFields::Reason, reason ); + msg.setValue ( ErrMsgFields::Transient, transient ); + return msg; + } + + ProvideMessage ProvideMessage::createProvide( const uint32_t reqId, const zypp::Url &url, const std::optional &filename, const std::optional &deltaFile, const std::optional &expFilesize, bool checkExistOnly ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::Prov ); + msg.setRequestId ( reqId ); + msg.setValue ( ProvideMsgFields::Url, url.asCompleteString() ); + + if ( filename ) + msg.setValue ( ProvideMsgFields::Filename, *filename ); + if ( deltaFile ) + msg.setValue ( ProvideMsgFields::DeltaFile, *deltaFile ); + if ( expFilesize ) + msg.setValue ( ProvideMsgFields::ExpectedFilesize, *expFilesize ); + msg.setValue ( ProvideMsgFields::CheckExistOnly, checkExistOnly ); + + return msg; + } + + ProvideMessage ProvideMessage::createCancel( const uint32_t reqId ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::Cancel ); + msg.setRequestId ( reqId ); + + return msg; + } + + ProvideMessage ProvideMessage::createAttach(const uint32_t reqId, const zypp::Url &url, const std::string attachId, const std::string &label, const std::optional &verifyType, const std::optional &verifyData, const std::optional &mediaNr ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::Attach ); + msg.setRequestId ( reqId ); + msg.setValue ( AttachMsgFields::Url, url.asCompleteString() ); + msg.setValue ( AttachMsgFields::AttachId, attachId ); + msg.setValue ( AttachMsgFields::Label, label ); + + if ( verifyType.has_value() && verifyData.has_value() && mediaNr.has_value() ) { + msg.setValue ( AttachMsgFields::VerifyType, *verifyType ); + msg.setValue ( AttachMsgFields::VerifyData, *verifyData ); + msg.setValue ( AttachMsgFields::MediaNr, *mediaNr ); + } else { + if ( !( ( verifyType.has_value() == verifyData.has_value() ) && ( verifyData.has_value() == mediaNr.has_value() ) ) ) + WAR << "Attach message requires verifyType, verifyData and mediaNr either set together or not set at all." << std::endl; + } + + return msg; + } + + ProvideMessage ProvideMessage::createDetach( const uint32_t reqId, const zypp::Url &attachUrl ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::Detach ); + msg.setRequestId ( reqId ); + msg.setValue ( DetachMsgFields::Url, attachUrl.asCompleteString() ); + + return msg; + } + + ProvideMessage ProvideMessage::createAuthDataRequest( const uint32_t reqId, const zypp::Url &effectiveUrl, const std::string &lastTriedUser, const std::optional &lastAuthTimestamp, const std::map &extraValues ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::AuthDataRequest ); + msg.setRequestId ( reqId ); + msg.setValue ( AuthDataRequestMsgFields::EffectiveUrl, effectiveUrl.asCompleteString() ); + if ( lastTriedUser.size() ) + msg.setValue( AuthDataRequestMsgFields::LastUser, lastTriedUser ); + if ( lastAuthTimestamp ) + msg.setValue ( AuthDataRequestMsgFields::LastAuthTimestamp, *lastAuthTimestamp ); + + return msg; + } + + ProvideMessage ProvideMessage::createMediaChangeRequest( const uint32_t reqId, const std::string &label, int32_t mediaNr, const std::vector &devices, const std::optional &desc ) + { + ProvideMessage msg; + msg.setCode ( ProvideMessage::Code::MediaChangeRequest ); + msg.setRequestId ( reqId ); + msg.setValue ( MediaChangeRequestMsgFields::Label, label ); + msg.setValue ( MediaChangeRequestMsgFields::MediaNr, mediaNr ); + for ( const auto &device : devices ) + msg.addValue ( MediaChangeRequestMsgFields::Device, device ); + if ( desc ) + msg.setValue ( MediaChangeRequestMsgFields::Desc, *desc ); + + return msg; + } + + uint ProvideMessage::requestId() const + { + return _reqId; + } + + void ProvideMessage::setRequestId(const uint id) + { + _reqId = id; + } + + ProvideMessage::Code ProvideMessage::code() const + { + return _code; + } + + void ProvideMessage::setCode(const ProvideMessage::Code newCode ) + { + _code = newCode; + } + + const std::vector &ProvideMessage::values( const std::string_view &str ) const + { + return _headers.values ( str ); + } + + const std::vector &ProvideMessage::values( const std::string &str ) const + { + return values( std::string_view(str)); + } + + ProvideMessage::FieldVal ProvideMessage::value( const std::string_view &str, const FieldVal &defaultVal ) const + { + return _headers.value ( str, defaultVal ); + } + + const HeaderValueMap &ProvideMessage::headers() const + { + return _headers; + } + + ProvideMessage::FieldVal ProvideMessage::value( const std::string &str, const FieldVal &defaultVal ) const + { + return value( std::string_view(str), defaultVal ); + } + + void ProvideMessage::setValue( const std::string &name, const FieldVal &value ) + { + setValue( std::string_view(name), value ); + } + + void ProvideMessage::setValue( const std::string_view &name, const FieldVal &value ) + { + _headers.set( std::string(name), value ); + } + + void ProvideMessage::addValue( const std::string &name, const FieldVal &value ) + { + return addValue( std::string_view(name), value ); + } + + void ProvideMessage::addValue( const std::string_view &name, const FieldVal &value ) + { + _headers.add( std::string(name), value ); + } + +} diff --git a/zypp-media/ng/providequeue.cc b/zypp-media/ng/providequeue.cc new file mode 100644 index 0000000..6b0ffd0 --- /dev/null +++ b/zypp-media/ng/providequeue.cc @@ -0,0 +1,784 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "private/providequeue_p.h" +#include "private/provideitem_p.h" +#include "private/provide_p.h" +#include "private/providedbg_p.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace zyppng { + + bool ProvideQueue::Item::isAttachRequest() const + { + if ( !_request ) + return false; + return ( _request->code () == ProvideMessage::Code::Attach ); + } + + bool ProvideQueue::Item::isFileRequest() const + { + if ( !_request ) + return false; + return ( _request->code () == ProvideMessage::Code::Prov ); + } + + bool ProvideQueue::Item::isDetachRequest() const + { + if ( !_request ) + return false; + return ( _request->code () == ProvideMessage::Code::Detach ); + } + + ProvideQueue::ProvideQueue(ProvidePrivate &parent) : _parent(parent) + { } + + ProvideQueue::~ProvideQueue() + { + if ( zyppng::provideDebugEnabled() ) { + if ( this->_activeItems.size() || this->_waitQueue.size() ) { + DBG << "Queue shutdown with Items still running" << std::endl; + } + } + immediateShutdown(std::make_exception_ptr(zypp::media::MediaException("Cancelled by queue shutdown"))); + } + + bool ProvideQueue::startup(const std::string &workerScheme, const zypp::filesystem::Pathname &workDir, const std::string &hostname ) { + + if ( _workerProc ) { + ERR << "Queue Worker was already initialized" << std::endl; + return true; + } + + _myHostname = hostname; + + const auto &pN = _parent.workerPath() / ( "zypp-media-"+workerScheme ) ; + MIL << "Trying to start " << pN << std::endl; + const auto &pi = zypp::PathInfo( pN ); + if ( !pi.isExist() ) { + ERR << "Failed to find worker for " << workerScheme << std::endl; + return false; + } + + if ( !pi.userMayX() ) { + ERR << "Failed to start worker for " << workerScheme << " binary " << pi.asString() << " is not executable." << std::endl; + return false; + } + + if ( zypp::filesystem::assert_dir( workDir ) != 0 ) { + ERR << "Failed to assert working directory '" << workDir << "' for worker " << workerScheme << std::endl; + return false; + } + + _currentExe = pN; + _workerProc = Process::create(); + _workerProc->setWorkingDirectory ( workDir ); + _messageStream = StompFrameStream::create( _workerProc ); + return doStartup(); + } + + + void ProvideQueue::enqueue( ProvideRequestRef request ) + { + Item i; + i._request = request; + i._request->provideMessage().setRequestId( nextRequestId() ); + request->setCurrentQueue( shared_this() ); + _waitQueue.push_back( std::move(i) ); + if ( _parent.isRunning() ) + scheduleNext(); + } + + void ProvideQueue::cancel( ProvideRequest *item , std::exception_ptr error ) + { + const auto &isSameItem = [item]( const Item &i ){ + if ( i.isDetachRequest () ) + return false; + return i._request.get() == item; + }; + + if ( !item ) + return; + + if ( item->code() != ProvideMessage::Code::Attach + && item->code() != ProvideMessage::Code::Prov ) { + ERR << "Can not cancel a " << item->code() << " request!" << std::endl; + return; + } + + if ( auto i = std::find_if( _waitQueue.begin(), _waitQueue.end(), isSameItem ); i != _waitQueue.end() ) { + auto &reqRef = i->_request; + reqRef->setCurrentQueue(nullptr); + if ( reqRef->owner() ) + reqRef->owner()->finishReq( this, reqRef, error ); + _waitQueue.erase(i); + _parent.schedule( ProvidePrivate::FinishReq ); // let the parent scheduler run since we have a open spot now + } else if ( auto i = std::find_if( _activeItems.begin(), _activeItems.end(), isSameItem ); i != _activeItems.end() ) { + cancelActiveItem(i, error); + } + } + + std::list::iterator ProvideQueue::dequeueActive( std::list::iterator it ) + { + if ( it == _activeItems.end() ) + return it; + + if ( it->_request ) + it->_request->setCurrentQueue( nullptr ); + + auto i = _activeItems.erase(it); + _parent.schedule ( ProvidePrivate::FinishReq ); // Trigger the scheduler + scheduleNext (); // keep the active items full + return i; + } + + void ProvideQueue::fatalWorkerError( const std::exception_ptr &reason ) + { + immediateShutdown( reason ? reason : std::make_exception_ptr( zypp::media::MediaException("Fatal worker error")) ); + } + + void ProvideQueue::immediateShutdown( const std::exception_ptr &reason ) + { + _queueShuttingDown = true; + + while ( _waitQueue.size() ) { + auto &item = _waitQueue.front(); + auto &reqRef = item._request; + if ( reqRef && reqRef->owner() && !item.isDetachRequest() ) + reqRef->owner()->finishReq( this, reqRef, reason ); + _waitQueue.pop_front(); + } + + for ( auto i = _activeItems.begin(); i != _activeItems.end(); ) { + auto &reqRef = i->_request; + if ( reqRef && reqRef->owner() && !i->isDetachRequest() ) { + i = cancelActiveItem(i, reason ); + } else { + i++; + } + } + + if ( _workerProc && _workerProc->isRunning() ) { + _workerProc->flush(); + _workerProc->closeWriteChannel(); + _workerProc->waitForExit(); + readAllStderr(); + } + } + + std::list< ProvideQueue::Item >::iterator ProvideQueue::cancelActiveItem( std::list< Item >::iterator i , const std::__exception_ptr::exception_ptr &error ) + { + auto &reqRef = i->_request; + + // already in cancelling process or finished + if ( i->_state == Item::Cancelling || i->_state == Item::Finished ) + return (++i); + + // not possible but lets be safe + if ( i->_state == Item::Pending ) { + reqRef->setCurrentQueue(nullptr); + if ( reqRef->owner() ) + reqRef->owner()->finishReq( this, reqRef, error ); + return dequeueActive(i); + } + + // we first need to cancel the item + auto c = ProvideMessage::createCancel ( i->_request->provideMessage().requestId() ); + if( !_messageStream->sendMessage(c) ) + ERR << "Failed to send cancel message to worker" << std::endl; + + i->_state = Item::Cancelling; + reqRef->setCurrentQueue(nullptr); + if ( reqRef->owner() ) + reqRef->owner()->finishReq( this, reqRef, error ); + reqRef.reset(); + return (++i); + } + + void ProvideQueue::scheduleNext() + { + if ( _queueShuttingDown ) + return; + + while ( _waitQueue.size() && canScheduleMore() ) { + auto item = std::move( _waitQueue.front() ); + _waitQueue.pop_front(); + + auto &reqRef = item._request; + if ( !reqRef->activeUrl() ) { + ERR << "Item without active URL enqueued, this is a BUG." << std::endl; + if ( reqRef->owner() ) + reqRef->owner()->finishReq( this, reqRef, ZYPP_EXCPT_PTR (zypp::media::MediaException("Item needs a activeURL to be queued.")) ); + continue; + } + + if ( !_messageStream->sendMessage( reqRef->provideMessage() ) ) { + ERR << "Failed to send message to worker process." << std::endl; + fatalWorkerError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Failed to communicate with worker process.") ) ); + return; + } + + item._state = Item::Queued; + _activeItems.push_back( std::move(item) ); + _idleSince.reset(); + } + + if ( _waitQueue.empty() && _activeItems.empty() ) { + _parent.schedule( ProvidePrivate::QueueIdle ); + if ( !_idleSince ) + _idleSince = std::chrono::steady_clock::now(); + _sigIdle.emit(); + } + } + + bool ProvideQueue::canScheduleMore() const + { + return ( _activeItems.size() == 0 || ( _capabilities.cfg_flags () & zyppng::WorkerCaps::Pipeline ) == zyppng::WorkerCaps::Pipeline ); + } + + bool ProvideQueue::isIdle() const + { + return ( empty() ); + } + + std::optional ProvideQueue::idleSince() const + { + return _idleSince; + } + + bool ProvideQueue::empty() const + { + return ( _activeItems.empty() && _waitQueue.empty() ); + } + + uint ProvideQueue::requestCount() const + { + return _activeItems.size() + _waitQueue.size(); + } + + uint ProvideQueue::activeRequests() const + { + return _activeItems.size(); + } + + zypp::ByteCount ProvideQueue::expectedProvideSize() const + { + zypp::ByteCount dlSize; + for ( const auto &i : _waitQueue ) { + if ( i.isDetachRequest () ) + continue; + + auto &reqRef = i._request; + if ( reqRef->code() != ProvideMessage::Code::Prov ) + continue; + dlSize += reqRef->provideMessage().value( ProvideMsgFields::ExpectedFilesize, int64_t(0) ).asInt64(); + } + for ( const auto &i : _activeItems ) { + if ( i.isDetachRequest () ) + continue; + auto &reqRef = i._request; + if ( reqRef->code() != ProvideMessage::Code::Prov ) + continue; + dlSize += reqRef->provideMessage().value( ProvideMsgFields::ExpectedFilesize, int64_t(0) ).asInt64(); + } + return dlSize; + } + + const std::string &ProvideQueue::hostname() const + { + return _myHostname; + } + + const ProvideQueue::Config &ProvideQueue::workerConfig() const + { + return _capabilities; + } + + SignalProxy ProvideQueue::sigIdle() + { + return _sigIdle; + } + + bool ProvideQueue::doStartup() + { + if ( _currentExe.empty() ) + return false; + + //const char *argv[] = { "gdbserver", ":10000", _currentExe.c_str(), nullptr }; + const char *argv[] = { _currentExe.c_str(), nullptr }; + if ( !_workerProc->start( argv) ) { + ERR << "Failed to execute worker" << std::endl; + + _messageStream.reset (); + _workerProc.reset (); + + return false; + } + + // make sure the default read channel is StdOut so RpcMessageStream gets all the rpc messages + _workerProc->setReadChannel ( Process::StdOut ); + + // we are ready to send the data + + ProviderConfiguration conf; + // @TODO actually write real config data :D + conf.insert ( { AGENT_STRING_CONF.data (), "ZYpp " LIBZYPP_VERSION_STRING } ); + conf.insert ( { ATTACH_POINT.data (), _workerProc->workingDirectory().asString() } ); + conf.insert ( { PROVIDER_ROOT.data (), _parent.z_func()->providerWorkdir().asString() } ); + + const auto &cleanupOnErr = [&](){ + readAllStderr(); + _messageStream.reset (); + _workerProc->close(); + _workerProc.reset(); + return false; + }; + + if ( !_messageStream->sendMessage( conf ) ) { + ERR << "Failed to send initial message to queue worker" << std::endl; + return cleanupOnErr(); + } + + // wait for the data to be written + _workerProc->flush (); + + // wait until we receive a message + const auto &caps = _messageStream->nextMessageWait(); + if ( !caps || caps->command() != WorkerCaps::typeName ) { + ERR << "Worker did not sent a capabilities message, aborting" << std::endl; + return cleanupOnErr(); + } + + { + auto p = _messageStream->parseMessage( *caps ); + if ( !p ) + return cleanupOnErr(); + + _capabilities = std::move(*p); + } + + DBG << "Received config for worker: " << this->_currentExe.asString() << " Worker Type: " << this->_capabilities.worker_type() << " Flags: " << std::bitset<32>( _capabilities.cfg_flags() ).to_string() << std::endl; + + // now we can set up signals and start processing messages + connect( *_messageStream, &StompFrameStream::sigMessageReceived, *this, &ProvideQueue::processMessage ); + connect( *_workerProc, &IODevice::sigChannelReadyRead, *this, &ProvideQueue::processReadyRead ); + connect( *_workerProc, &Process::sigFinished, *this, &ProvideQueue::procFinished ); + + // make sure we do not miss messages + processMessage(); + return true; + } + + void ProvideQueue::processMessage() { + + const auto &getRequest = [&]( const auto &exp ) -> decltype(_activeItems)::iterator { + if ( !exp ) { + ERR << "Ignoring invalid request!" << std::endl; + return _activeItems.end(); + } + + auto i = std::find_if( _activeItems.begin(), _activeItems.end(), [&]( const auto &elem ) { + if ( ! elem._request ) + return false; + return exp->requestId() == elem._request->provideMessage().requestId(); + }); + + if ( i == _activeItems.end() ) { + ERR << "Ignoring unknown request ID: " << exp->requestId() << std::endl; + return _activeItems.end(); + } + + return i; + }; + + const auto &sendErrorToWorker = [&]( const uint32_t reqId, const MessageCodes code, const std::string &reason, bool transient = false ) { + auto r = ProvideMessage::createErrorResponse ( reqId, code, reason, transient ); + if ( !_messageStream->sendMessage( r ) ) { + ERR << "Failed to send Error message to worker process." << std::endl; + fatalWorkerError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Failed to communicate with worker process.") ) ); + return false; + } + return true; + }; + + const bool doesDownload = this->_capabilities.worker_type() == Config::Downloading; + const bool fileNeedsCleanup = doesDownload || ( _capabilities.worker_type() == Config::CPUBound && _capabilities.cfg_flags() & Config::FileArtifacts ); + + while ( auto msg = _messageStream->nextMessage () ) { + + if ( msg->command() == ProvideMessage::typeName ) { + + const auto &provMsg = ProvideMessage::create(*msg); + if ( !provMsg ) { + fatalWorkerError( provMsg.error() ); + return; + } + + const auto &reqIter = getRequest( provMsg ); + if ( reqIter == _activeItems.end() ) { + if ( provMsg->code() == ProvideMessage::Code::ProvideFinished && fileNeedsCleanup ) { + const auto locFName = provMsg->value( ProvideFinishedMsgFields::LocalFilename ).asString(); + if ( !_parent.isInCache(locFName) ) { + MIL << "Received a ProvideFinished message for a non existant request. Since this worker reported to create file artifacts, the file is cleaned up." << std::endl; + zypp::filesystem::unlink( locFName ); + } + } + continue; + } + + auto &req = *reqIter; + auto &reqRef =req._request; + + const auto code = provMsg->code(); + + if ( code >= ProvideMessage::Code::FirstInformalCode && code <= ProvideMessage::Code::LastInformalCode ) { + + // send the message to the item but don't dequeue + if ( reqRef && reqRef->owner() ) + reqRef->owner()->informalMessage ( *this, reqRef, *provMsg ); + continue; + + } else if ( code >= ProvideMessage::Code::FirstSuccessCode && code <= ProvideMessage::Code::LastSuccessCode ) { + + if ( req._state == Item::Cancelling ) { + req._state = Item::Finished; + dequeueActive( reqIter ); + continue; + } + + if ( code == ProvideMessage::Code::ProvideFinished ) { + + // we are going to register the file to the cache if this is a downloading worker, so it can not leak + // no matter if the item does the correct dance or not, this code is duplicated by all ProvideItems that receive ProvideFinished + // results that require file cleanups. + // we keep the ref around until after sending the result to the item. At that point it should take a reference + std::optional dataRef; + + if ( !reqIter->isFileRequest() ) { + ERR << "Invalid message for request ID: " << reqIter->_request->provideMessage().requestId() << std::endl; + fatalWorkerError(); + return; + } + + const auto &isCheckExistsOnlyVal = reqRef->provideMessage().value( ProvideMsgFields::CheckExistOnly ); + bool isCheckExistsOnly = isCheckExistsOnlyVal.valid() ? isCheckExistsOnlyVal.asBool() : false; + + // when a worker is downloading we keep a internal book of cache files + if ( doesDownload && !isCheckExistsOnly ) { + const auto locFName = provMsg->value( ProvideFinishedMsgFields::LocalFilename ).asString(); + if ( provMsg->value( ProvideFinishedMsgFields::CacheHit, false ).asBool()) { + dataRef = _parent.addToFileCache ( locFName ); + if ( !dataRef ) { + MIL << "CACHE MISS, file " << locFName << " was already removed, queueing again" << std::endl; + if ( reqRef->owner() ) + reqRef->owner()->cacheMiss( reqRef ); + reqRef->provideMessage().setRequestId( InvalidId ); + req._state = Item::Pending; + _waitQueue.push_front( req ); + dequeueActive( reqIter ); + continue; + } + } else { + + dataRef = _parent.addToFileCache ( locFName ); + + // unlikely this can happen but better be safe than sorry + if ( !dataRef ) { + req._state = Item::Finished; + reqRef->setCurrentQueue(nullptr); + auto resp = ProvideMessage::createErrorResponse ( provMsg->requestId(), ProvideMessage::Code::InternalError, "File vanished between downloading and adding it to cache." ); + if ( reqRef->owner() ) + reqRef->owner()->finishReq( *this, reqRef, resp ); + dequeueActive( reqIter ); + continue; + } + } + } + } + + // send the message to the item and dequeue + reqRef->setCurrentQueue(nullptr); + if ( reqRef->owner() ) + reqRef->owner()->finishReq( *this, reqRef, *provMsg ); + req._state = Item::Finished; + dequeueActive( reqIter ); + continue; + + } else if ( code >= ProvideMessage::Code::FirstClientErrCode && code <= ProvideMessage::Code::LastSrvErrCode ) { + + if ( req._state == Item::Cancelling ) { + req._state = Item::Finished; + dequeueActive( reqIter ); + continue; + } + + // send the message to the item and dequeue + reqRef->setCurrentQueue(nullptr); + + if ( reqRef->owner() ) + reqRef->owner()->finishReq( *this, reqRef, *provMsg ); + + req._state = Item::Finished; + dequeueActive( reqIter ); + continue; + + } else if ( code >= ProvideMessage::Code::FirstRedirCode && code <= ProvideMessage::Code::LastRedirCode ) { + + // redir is like a finished message, we can simply forgot about a cancelling request + if ( req._state == Item::Cancelling ) { + req._state = Item::Finished; + dequeueActive( reqIter ); + continue; + } + + // send the message to the item and dequeue + reqRef->setCurrentQueue(nullptr); + if ( reqRef->owner() ) + reqRef->owner()->finishReq( *this, reqRef, *provMsg ); + req._state = Item::Finished; + dequeueActive( reqIter ); + continue; + + } else if ( code >= ProvideMessage::Code::FirstControllerCode && code <= ProvideMessage::Code::LastControllerCode ) { + + ERR << "Received Controller message from worker, this is a fatal error. Cancelling all requests!" << std::endl; + fatalWorkerError ( ZYPP_EXCPT_PTR( zypp::media::MediaException("Controller message received from worker.") ) ); + return; + + } else if ( code >= ProvideMessage::Code::FirstWorkerCode && code <= ProvideMessage::Code::LastWorkerCode ) { + + if ( code == ProvideMessage::Code::AuthDataRequest ) { + if ( !reqIter->isFileRequest() && !reqIter->isAttachRequest() ) { + ERR << "Invalid message for request ID: " << reqRef->provideMessage().requestId() << std::endl; + fatalWorkerError(); + return; + } + + // if the file was cancelled we send a failure back + if( reqIter->_state == Item::Cancelling ) { + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::NoAuthData, "Item was cancelled") ) + return; + continue; + } + + // we need a owner item to fetch the auth data for us + if ( !reqRef->owner() ) { + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::NoAuthData, "Request has no owner" ) ) + return; + continue; + } + + if ( !reqRef->activeUrl() ) { + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::NoAuthData, "Item has no active URL, this is a bug." ) ) + return; + continue; + } + + try { + zypp::Url u( provMsg->value( AuthDataRequestMsgFields::EffectiveUrl ).asString() ); + + std::map extraVals; + for( const auto &hdr : provMsg->headers() ) { + + if ( hdr.first == AuthDataRequestMsgFields::EffectiveUrl + || hdr.first == AuthDataRequestMsgFields::LastAuthTimestamp ) + continue; + + if ( !hdr.second.isString() ) { + WAR << "Ignoring non string value for " << hdr.first << std::endl; + continue; + } + + extraVals[hdr.first] = hdr.second.asString(); + } + + const auto &authOpt = reqRef->owner()->authenticationRequired( *this, reqRef, u, provMsg->value( AuthDataRequestMsgFields::LastAuthTimestamp ).asInt64(), extraVals ); + if ( !authOpt ) { + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::NoAuthData, "No auth given by user." ) ) + return; + continue; + } + + auto r = ProvideMessage::createAuthInfo ( reqRef->provideMessage().requestId(), authOpt->username(), authOpt->password(), authOpt->lastDatabaseUpdate(), authOpt->extraValues() ); + if ( !_messageStream->sendMessage( r ) ) { + ERR << "Failed to send AuthorizationInfo to worker process." << std::endl; + fatalWorkerError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Failed to communicate with worker process.") ) ); + return; + } + continue; + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::NoAuthData, e.asString() ) ) + return; + continue; + } + + } else if ( code == ProvideMessage::Code::MediaChangeRequest ) { + + if ( !reqIter->isAttachRequest() ) { + ERR << "Invalid message for request ID: " << reqIter->_request->provideMessage().requestId() << std::endl; + fatalWorkerError(); + return; + } + + // if the file was cancelled we send a failure back + if( reqIter->_state == Item::Cancelling ) { + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::MediaChangeAbort, "Item was cancelled" ) ) + return; + continue; + } + + MIL << "Worker sent a MediaChangeRequest, asking the user to insert the correct medium" << std::endl; + + //const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc + std::vector freeDevs; + for ( const auto &val : provMsg->values( MediaChangeRequestMsgFields::Device) ) { + freeDevs.push_back( val.asString() ); + } + + std::optional desc; + const auto &descVal = provMsg->value( MediaChangeRequestMsgFields::Desc ); + if ( descVal.valid () && descVal.isString() ) + desc = descVal.asString(); + + auto res = _parent._sigMediaChange.emit( + _parent.queueName(*this), + provMsg->value( MediaChangeRequestMsgFields::Label ).asString(), + provMsg->value( MediaChangeRequestMsgFields::MediaNr ).asInt(), + freeDevs, + desc + ); + + auto action = res ? *res : Provide::Action::ABORT; + switch ( action ) { + case Provide::Action::RETRY: { + MIL << "Sending back a MediaChanged message, retrying to find medium " << std::endl; + auto r = ProvideMessage::createMediaChanged ( reqIter->_request->provideMessage().requestId() ); + if ( !_messageStream->sendMessage( r ) ){ + ERR << "Failed to send MediaChanged to worker process." << std::endl; + fatalWorkerError( ZYPP_EXCPT_PTR( zypp::media::MediaException("Failed to communicate with worker process.") ) ); + return; + } + continue; + } + case Provide::Action::ABORT: { + MIL << "Sending back a MediaChangeFailure message, request will fail " << std::endl; + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::MediaChangeAbort, "Cancelled by User" ) ) + return; + continue; + } + case Provide::Action::SKIP: { + MIL << "Sending back a MediaChangeFailure message, request will fail " << std::endl; + if ( !sendErrorToWorker( reqRef->provideMessage().requestId(), ProvideMessage::Code::MediaChangeSkip, "Skipped by User" ) ) + return; + continue; + } + } + } else { + // if there is a unsupported worker request we need to stop immediately because the worker will be blocked until it gets a answer + ERR << "Unsupported worker request: "<command() << " with code " << code << " ignoring! " << std::endl; + } + + } else { + ERR << "Received unsupported message " << msg->command() << "ignoring" << std::endl; + } + } + } + + /*! + * Reads all of the log lines from stderr, call only when shutting down the queue + * because this will also read partial lines and forwards them + */ + void ProvideQueue::readAllStderr() + { + // read all stderr data so we get the full logs + auto ba = _workerProc->channelReadLine(Process::StdErr); + while ( !ba.empty() ) { + forwardToLog(std::string( ba.data(), ba.size() ) ); + ba = _workerProc->channelReadLine(Process::StdErr); + } + } + + void ProvideQueue::forwardToLog( std::string &&logLine ) + { + if ( (_capabilities.cfg_flags () & zyppng::WorkerCaps::ZyppLogFormat) == zyppng::WorkerCaps::ZyppLogFormat ) + zypp::base::LogControl::instance ().logRawLine( std::move(logLine) ); + else + MIL << "Message from worker: " << _capabilities.worker_name() << ":" << logLine << std::endl; + } + + void ProvideQueue::processReadyRead(int channel) { + // ignore stdout here + if ( channel == Process::StdOut ) + return; + + // forward the stderr output to the log bypassing the formatter + // the worker already formatted the line + while ( _workerProc->canReadLine(Process::StdErr) ) { + const auto &data = _workerProc->channelReadLine( Process::StdErr ); + if ( data.empty() ) + return; + + forwardToLog(std::string( data.data(), data.size() ) ); + } + } + + void ProvideQueue::procFinished(int exitCode) + { + // process all pending messages + processMessage(); + + // get all of the log lines + readAllStderr(); + + // shut down + // @todo implement worker restart in case of a unexpected exit + if ( !_queueShuttingDown ) + immediateShutdown( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unexpected queue worker exit!") ) ); + +#if 0 + if ( !_queueShuttingDown ) { + + _crashCounter++; + if ( _crashCounter > 3 ) { + immediateShutdown( ZYPP_EXCPT_PTR( zypp::media::MediaException("Unexpected queue worker exit!") ) ); + return; + } + + MIL << "Unexpected queue worker exit with code: " << exitCode << std::endl; + // try to spawn the worker again, move active items back to wait list and start over + + if ( !doStartup () ) { + + } + } +#endif + } + + uint32_t ProvideQueue::nextRequestId() { + return _parent.nextRequestId(); + } +} diff --git a/zypp-media/ng/provideres.cc b/zypp-media/ng/provideres.cc new file mode 100644 index 0000000..5b6a304 --- /dev/null +++ b/zypp-media/ng/provideres.cc @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "provideres.h" +#include "private/provideres_p.h" + +namespace zyppng { + + ProvideRes::ProvideRes( std::shared_ptr dataPtr ) : _data(dataPtr) + { } + + ProvideRes::~ProvideRes() + { } + + const zypp::filesystem::Pathname ProvideRes::file() const + { + return _data->_myFile; + } + + const zypp::ManagedFile & ProvideRes::asManagedFile () const + { + return _data->_myFile; + } + + const ProvideMediaHandle &ProvideRes::mediaHandle () const + { + return _data->_mediaHandle; + } + + const zypp::Url &ProvideRes::resourceUrl () const + { + return _data->_resourceUrl; + } + + const HeaderValueMap &ProvideRes::headers () const + { + return _data->_responseHeaders; + } + +} diff --git a/zypp-media/ng/provideres.h b/zypp-media/ng/provideres.h new file mode 100644 index 0000000..9c43b57 --- /dev/null +++ b/zypp-media/ng/provideres.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/source/ProvideRes.h + */ +#ifndef ZYPP_MEDIA_PROVIDERES_H_INCLUDED +#define ZYPP_MEDIA_PROVIDERES_H_INCLUDED + +#include +#include +#include +#include + + +namespace zyppng +{ + + struct ProvideResourceData; + + /** + * \class ProvideRes + * A ProvideRes object is a reference counted ownership of a resource in the cache provided by + * a \ref Provide instance. + * It is generally advisable to release a ProvideRes instance asap, to make sure resources + * can be released and devices are free to be ejected. + * + * \note all ProvideRes instances will become invalid when the \ref Provide instance is + * released. + */ + class ProvideRes + { + public: + ProvideRes( std::shared_ptr dataPtr ); + virtual ~ProvideRes(); + + /*! + * Returns the path to the provided file + */ + const zypp::Pathname file () const; + + /*! + * Returns a reference to the internally used managed file instance. + * \note If you obtain this for a file that is inside the providers working directory ( e.g. a provide result for a download ), + * the continued use after the Provide instance was relased is undefined behaviour and not supported! + */ + const zypp::ManagedFile & asManagedFile () const; + + /*! + * Returns a reference to the currently held media handle, this can be a invalid handle + */ + const ProvideMediaHandle &mediaHandle () const; + + /*! + * The URL this ressource was provided from, can be empty + */ + const zypp::Url &resourceUrl () const; + + /*! + * All headers that were received from the worker when sending the result + */ + const HeaderValueMap &headers () const; + + private: + std::shared_ptr _data; + }; +} + + +#endif diff --git a/zypp-media/ng/providespec.cc b/zypp-media/ng/providespec.cc new file mode 100644 index 0000000..52c9ab6 --- /dev/null +++ b/zypp-media/ng/providespec.cc @@ -0,0 +1,288 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp-media/providespec.cc + * +*/ + +#include +#include +#include "providespec.h" + +using std::endl; + +namespace zyppng +{ + class ProvideSpecBasePrivate + { + public: + ProvideSpecBasePrivate() {} + ProvideSpecBasePrivate(const ProvideSpecBasePrivate &) = default; + ProvideSpecBasePrivate(ProvideSpecBasePrivate &&) = delete; + ProvideSpecBasePrivate &operator=(const ProvideSpecBasePrivate &) = delete; + ProvideSpecBasePrivate &operator=(ProvideSpecBasePrivate &&) = delete; + virtual ~ProvideSpecBasePrivate() {} + HeaderValueMap _customHeaders; + }; + + + class ProvideMediaSpec::Impl : public ProvideSpecBasePrivate + { + public: + Impl() + {} + + Impl( std::string &&label, zypp::Pathname &&vPath, unsigned medianr ) + : _label(std::move( label )) + , _medianr( medianr ) + , _verifyDataPath(std::move(vPath)) + {} + + std::string _label; + unsigned _medianr = 0U; + zypp::Pathname _verifyDataPath; + + public: + /** Offer default Impl. */ + static zypp::shared_ptr nullimpl() + { static zypp::shared_ptr _nullimpl( new Impl ); return _nullimpl; } + + private: + friend ProvideMediaSpec::Impl * zypp::rwcowClone( const ProvideMediaSpec::Impl * rhs ); + Impl * clone() const { return new Impl( *this ); } + }; + + class ProvideFileSpec::Impl : public ProvideSpecBasePrivate + { + public: + Impl() + {} + + zypp::Pathname _destFilenameHint; + zypp::Pathname _mediaSpecFile; + bool _checkExistsOnly = false; + + bool _optional = false; + zypp::ByteCount _downloadSize; + zypp::CheckSum _checksum; + + zypp::ByteCount _openSize; + zypp::CheckSum _openChecksum; + + zypp::ByteCount _headerSize; + zypp::CheckSum _headerChecksum; + + zypp::Pathname _deltafile; + + + public: + /** Offer default Impl. */ + static zypp::shared_ptr nullimpl() + { static zypp::shared_ptr _nullimpl( new Impl ); return _nullimpl; } + + private: + friend ProvideFileSpec::Impl * zypp::rwcowClone( const ProvideFileSpec::Impl * rhs ); + Impl * clone() const { return new Impl( *this ); } + }; + + + ProvideMediaSpec::ProvideMediaSpec( std::string label, zypp::filesystem::Pathname verifyData, unsigned medianr ) + : _pimpl( new Impl( std::move(label), std::move(verifyData), medianr ) ) + { + + } + + const std::string &ProvideMediaSpec::label() const + { return _pimpl->_label; } + + ProvideMediaSpec &ProvideMediaSpec::setLabel(const std::string &label) + { + _pimpl->_label = label; + return *this; + } + + unsigned ProvideMediaSpec::medianr() const + { return _pimpl->_medianr; } + + ProvideMediaSpec &ProvideMediaSpec::setMedianr(unsigned medianr) + { + _pimpl->_medianr = medianr; + return *this; + } + + zypp::filesystem::Pathname ProvideMediaSpec::mediaFile() const + { return _pimpl->_verifyDataPath; } + + ProvideMediaSpec &ProvideMediaSpec::setMediaFile(const zypp::filesystem::Pathname &pName) + { + _pimpl->_verifyDataPath = pName; + return *this; + } + + HeaderValueMap &ProvideMediaSpec::customHeaders() + { return _pimpl->_customHeaders; } + + const HeaderValueMap &ProvideMediaSpec::customHeaders() const + { return _pimpl->_customHeaders; } + + ProvideMediaSpec &ProvideMediaSpec::setCustomHeaderValue(const std::string &key, const HeaderValueMap::Value &val) + { + _pimpl->_customHeaders.set( key,val ); + return *this; + } + + ProvideMediaSpec &ProvideMediaSpec::addCustomHeaderValue(const std::string &key, const HeaderValueMap::Value &val) + { + _pimpl->_customHeaders.add( key,val ); + return *this; + } + + zypp::TriBool ProvideMediaSpec::isSameMedium( const ProvideMediaSpec &other ) + { + // first check if we have the same media data + if ( _pimpl->_verifyDataPath != other._pimpl->_verifyDataPath ) + return false; + + // if the verify file is not empty check the medianr + if ( !_pimpl->_verifyDataPath.empty() ) { + return _pimpl->_medianr == other._pimpl->_medianr; + } + + // can't tell without the URL + return zypp::indeterminate; + } + + /** \relates ProvideSpec::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const ProvideFileSpec::Impl & obj ) + { + return str << "{" << obj._destFilenameHint << "{" << obj._downloadSize << "|" << obj._checksum << "|" << obj._deltafile << "}" << "}"; + } + + /** \relates ProvideSpec::Impl Verbose stream output */ + inline std::ostream & dumpOn( std::ostream & str, const ProvideFileSpec::Impl & obj ) + { return str << obj; } + + + ProvideFileSpec::ProvideFileSpec() + : _pimpl( new Impl() ) + {} + + ProvideFileSpec::ProvideFileSpec( const zypp::OnMediaLocation &loc ) + : _pimpl( new Impl() ) + { + setDownloadSize( loc.downloadSize() ); + setOptional( loc.optional() ); + setChecksum( loc.checksum() ); + setOpenSize( loc.openSize() ); + setOpenChecksum( loc.openChecksum() ); + setHeaderSize( loc.headerSize() ); + setHeaderChecksum( loc.headerChecksum() ); + setDeltafile( loc.deltafile() ); + } + + ProvideFileSpec::~ProvideFileSpec() + {} + + const zypp::filesystem::Pathname &ProvideFileSpec::destFilenameHint() const + { return _pimpl->_destFilenameHint; } + + ProvideFileSpec &ProvideFileSpec::setDestFilenameHint(const zypp::filesystem::Pathname &filename) + { _pimpl->_destFilenameHint = filename; return *this; } + + bool ProvideFileSpec::checkExistsOnly() const + { return _pimpl->_checkExistsOnly; } + + ProvideFileSpec &ProvideFileSpec::setCheckExistsOnly(const bool set) + { _pimpl->_checkExistsOnly = set; return *this; } + + bool ProvideFileSpec::optional() const + { return _pimpl->_optional; } + + ProvideFileSpec & ProvideFileSpec::setOptional( bool val_r ) + { _pimpl->_optional = (val_r); return *this; } + + const zypp::ByteCount & ProvideFileSpec::downloadSize() const + { return _pimpl->_downloadSize; } + + ProvideFileSpec & ProvideFileSpec::setDownloadSize( const zypp::ByteCount &val_r ) + { _pimpl->_downloadSize = (val_r); return *this; } + + const zypp::CheckSum & ProvideFileSpec::checksum() const + { return _pimpl->_checksum; } + + ProvideFileSpec & ProvideFileSpec::setChecksum( const zypp::CheckSum &val_r ) + { _pimpl->_checksum = (val_r); return *this; } + + const zypp::ByteCount & ProvideFileSpec::openSize() const + { return _pimpl->_openSize; } + + ProvideFileSpec & ProvideFileSpec::setOpenSize( const zypp::ByteCount &val_r ) + { _pimpl->_openSize = (val_r); return *this; } + + const zypp::CheckSum & ProvideFileSpec::openChecksum() const + { return _pimpl->_openChecksum; } + + ProvideFileSpec & ProvideFileSpec::setOpenChecksum( const zypp::CheckSum &val_r ) + { _pimpl->_openChecksum = (val_r); return *this; } + + const zypp::ByteCount & ProvideFileSpec::headerSize() const + { return _pimpl->_headerSize; } + + ProvideFileSpec & ProvideFileSpec::setHeaderSize( const zypp::ByteCount &val_r ) + { _pimpl->_headerSize = (val_r); return *this; } + + const zypp::CheckSum & ProvideFileSpec::headerChecksum() const + { return _pimpl->_headerChecksum; } + + ProvideFileSpec & ProvideFileSpec::setHeaderChecksum( const zypp::CheckSum &val_r ) + { _pimpl->_headerChecksum = (val_r); return *this; } + + const zypp::Pathname &ProvideFileSpec::deltafile() const + { return _pimpl->_deltafile; } + + ProvideFileSpec &ProvideFileSpec::setDeltafile( const zypp::Pathname &path ) + { _pimpl->_deltafile = (path); return *this; } + + HeaderValueMap &ProvideFileSpec::customHeaders() + { return _pimpl->_customHeaders; } + + const HeaderValueMap &ProvideFileSpec::customHeaders() const + { return _pimpl->_customHeaders; } + + ProvideFileSpec &ProvideFileSpec::setCustomHeaderValue(const std::string &key, const HeaderValueMap::Value &val) + { + _pimpl->_customHeaders.set( key,val ); + return *this; + } + + ProvideFileSpec &ProvideFileSpec::addCustomHeaderValue(const std::string &key, const HeaderValueMap::Value &val) + { + _pimpl->_customHeaders.add( key,val ); + return *this; + } + + zypp::OnMediaLocation ProvideFileSpec::asOnMediaLocation( const zypp::Pathname &path, unsigned int mediaNr ) const + { + return zypp::OnMediaLocation( path, mediaNr ) + .setDownloadSize( downloadSize() ) + .setOptional( optional() ) + .setChecksum( checksum() ) + .setOpenSize( openSize() ) + .setOpenChecksum( openChecksum() ) + .setHeaderSize( headerSize() ) + .setHeaderChecksum( headerChecksum() ) + .setDeltafile( deltafile() ); + } + + std::ostream & operator<<( std::ostream & str, const ProvideFileSpec & obj ) + { return str << *obj._pimpl; } + + std::ostream & dumpOn( std::ostream & str, const ProvideFileSpec & obj ) + { return dumpOn( str, *obj._pimpl ); } + +} // namespace zypp diff --git a/zypp-media/ng/providespec.h b/zypp-media/ng/providespec.h new file mode 100644 index 0000000..356f992 --- /dev/null +++ b/zypp-media/ng/providespec.h @@ -0,0 +1,206 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/source/ProvideSpec.h + */ +#ifndef ZYPP_MEDIA_PROVIDESPEC_H_INCLUDED +#define ZYPP_MEDIA_PROVIDESPEC_H_INCLUDED + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng +{ + + class ProvideMediaSpec + { + public: + + ProvideMediaSpec(std::string label="", zypp::Pathname verifyData = zypp::Pathname(), unsigned medianr = 1 ); + + /*! + * The label of the medium, this will be shown in case a media change is required + */ + const std::string &label() const; + + /*! + * Changes the label of the medium + */ + ProvideMediaSpec &setLabel( const std::string &label ); + + /*! + * The media number the resource is located on. + */ + unsigned medianr() const; + + /*! + * Individual manipulation of \c medianr (prefer \ref setLocation). + */ + ProvideMediaSpec & setMedianr( unsigned medianr ); + + /*! + * Returns the media validation file path. This can be empty if there + * is no file to validate. + */ + zypp::Pathname mediaFile () const; + + /*! + * Changes the media file to the name path \a pName. + */ + ProvideMediaSpec &setMediaFile( const zypp::Pathname &pName ); + + /*! + * Returns a map of custom key->value pairs that can control special aspects + * of how all files are provided by the medium after it was attached + */ + HeaderValueMap &customHeaders(); + const HeaderValueMap &customHeaders() const; + + /*! + * Set the custom header value identified by \a key to \a val + */ + ProvideMediaSpec &setCustomHeaderValue ( const std::string &key, const HeaderValueMap::Value &val ); + + /*! + * Adds the custom header value \a val to the list of values identified by \a key + */ + ProvideMediaSpec &addCustomHeaderValue ( const std::string &key, const HeaderValueMap::Value &val ); + + zypp::TriBool isSameMedium ( const ProvideMediaSpec &other ); + + public: + class Impl; ///< Implementation class. + private: + zypp::RWCOW_pointer _pimpl; ///< Pointer to implementation. + }; + + + class ProvideFileSpec + { + friend std::ostream & operator<<( std::ostream &str, const ProvideFileSpec &obj ); + friend std::ostream & dumpOn( std::ostream &str, const ProvideFileSpec &obj ); + + public: + ProvideFileSpec(); + + ProvideFileSpec(const zypp::OnMediaLocation &loc); + + ProvideFileSpec(const ProvideFileSpec &) = default; + ProvideFileSpec(ProvideFileSpec &&) noexcept = default; + + ProvideFileSpec &operator=(const ProvideFileSpec &) = default; + ProvideFileSpec &operator=(ProvideFileSpec &&) noexcept = default; + + /** Dtor */ + ~ProvideFileSpec(); + + template + static ProvideFileSpecRef create ( T... args ) { + return std::make_shared( std::forward(args)... ); + } + + /*! + * The destination file name, this is optional and is only + * a hint to the \ref Provide instance where to put the file IF possible. The + * file provider does not need to consider this. + */ + const zypp::Pathname &destFilenameHint() const; + ProvideFileSpec &setDestFilenameHint ( const zypp::Pathname &filename ); + + bool checkExistsOnly () const; + ProvideFileSpec & setCheckExistsOnly( const bool set = true ); + + + /** Whether this is an optional resource. + * This is a hint to the downloader not to report an error if + * the resource is not present on the server. + */ + bool optional() const; + /** Set whether the resource is \ref optional. */ + ProvideFileSpec & setOptional( bool val ); + + /** The size of the resource on the server. */ + const zypp::ByteCount &downloadSize() const; + /** Set the \ref downloadSize. */ + ProvideFileSpec &setDownloadSize( const zypp::ByteCount &val_r ); + + /** The checksum of the resource on the server. */ + const zypp::CheckSum &checksum() const; + /** Set the \ref checksum. */ + ProvideFileSpec &setChecksum( const zypp::CheckSum &val_r ); + + + /** The size of the resource once it has been uncompressed or unpacked. */ + const zypp::ByteCount &openSize() const; + /** Set the \ref openSize. */ + ProvideFileSpec &setOpenSize( const zypp::ByteCount &val_r ); + + /** The checksum of the resource once it has been uncompressed or unpacked. */ + const zypp::CheckSum &openChecksum() const; + /** Set the \ref openChecksum. */ + ProvideFileSpec &setOpenChecksum( const zypp::CheckSum &val_r ); + + /** The size of the header prepending the resource (e.g. for zchunk). */ + const zypp::ByteCount &headerSize() const; + /** Set the \ref headerSize. */ + ProvideFileSpec &setHeaderSize( const zypp::ByteCount &val_r ); + + /** The checksum of the header prepending the resource (e.g. for zchunk). */ + const zypp::CheckSum &headerChecksum() const; + /** Set the \ref headerChecksum. */ + ProvideFileSpec &setHeaderChecksum( const zypp::CheckSum &val_r ); + + /** The existing deltafile that can be used to reduce download size ( zchunk or metalink ) */ + const zypp::Pathname &deltafile() const; + /** Set the \ref deltafile. */ + ProvideFileSpec &setDeltafile( const zypp::Pathname &path ); + + /*! + * Returns a map of custom key->value pairs that can control special aspects + * of how the provide operation is processed. + * + * @todo should this actually just be a list of pair(string,string) instead of map? -> easier way to send multiple values to a worker + */ + HeaderValueMap &customHeaders(); + const HeaderValueMap &customHeaders() const; + + /*! + * Set the custom header value identified by \a key to \a val + */ + ProvideFileSpec &setCustomHeaderValue ( const std::string &key, const HeaderValueMap::Value &val ); + + /*! + * Adds the custom header value \a val to the list of values identified by \a key + */ + ProvideFileSpec &addCustomHeaderValue ( const std::string &key, const HeaderValueMap::Value &val ); + + zypp::OnMediaLocation asOnMediaLocation ( const zypp::Pathname &path, unsigned int mediaNr ) const; + + public: + class Impl; ///< Implementation class. + private: + zypp::RWCOW_pointer _pimpl; ///< Pointer to implementation. + }; + + /** \relates ProvideSpec Stream output */ + std::ostream & operator<<( std::ostream &str, const ProvideFileSpec &obj ); + + /** \relates ProvideSpec Verbose stream output */ + std::ostream & dumpOn( std::ostream &str, const ProvideFileSpec &obj ); + +} // namespace zypp + +#endif // ZYPP_MEDIA_PROVIDESPEC_H_INCLUDED diff --git a/zypp-media/ng/worker/DeviceDriver b/zypp-media/ng/worker/DeviceDriver new file mode 100644 index 0000000..4942597 --- /dev/null +++ b/zypp-media/ng/worker/DeviceDriver @@ -0,0 +1 @@ +#include "devicedriver.h" diff --git a/zypp-media/ng/worker/MountingWorker b/zypp-media/ng/worker/MountingWorker new file mode 100644 index 0000000..2c46378 --- /dev/null +++ b/zypp-media/ng/worker/MountingWorker @@ -0,0 +1 @@ +#include "mountingworker.h" diff --git a/zypp-media/ng/worker/ProvideWorker b/zypp-media/ng/worker/ProvideWorker new file mode 100644 index 0000000..7d39856 --- /dev/null +++ b/zypp-media/ng/worker/ProvideWorker @@ -0,0 +1 @@ +#include "provideworker.h" diff --git a/zypp-media/ng/worker/devicedriver.cc b/zypp-media/ng/worker/devicedriver.cc new file mode 100644 index 0000000..9e27be0 --- /dev/null +++ b/zypp-media/ng/worker/devicedriver.cc @@ -0,0 +1,381 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "devicedriver.h" +#include +#include +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zyppng::worker::DeviceDriver" + +namespace zyppng::worker +{ + + DeviceDriver::DeviceDriver ( WorkerCaps::WorkerType wType ) + : _wType( wType ) + { } + + void DeviceDriver::setProvider ( ProvideWorkerWeakRef workerRef ) + { + _parentWorker = workerRef; + } + + zyppng::expected DeviceDriver::initialize(const zyppng::worker::Configuration &conf) + { + if ( const auto &i = conf.find( std::string(zyppng::ATTACH_POINT) ); i != conf.end() ) { + const auto &val = i->second; + MIL << "Got attachpoint from controller: " << val << std::endl; + _attachRoot = zypp::Pathname(val).realpath(); + } else { + return zyppng::expected::error(ZYPP_EXCPT_PTR( zypp::Exception("Attach point required to work.") )); + } + + _config = conf; + + zyppng::worker::WorkerCaps caps; + caps.set_worker_type ( _wType ); + caps.set_cfg_flags( + zyppng::worker::WorkerCaps::Flags ( + zyppng::worker::WorkerCaps::Pipeline + | zyppng::worker::WorkerCaps::ZyppLogFormat + | zyppng::worker::WorkerCaps::SingleInstance + ) + ); + + return zyppng::expected::success(caps); + } + + bool DeviceDriver::detachMedia ( const std::string &attachId ) + { + auto i = _attachedMedia.find( attachId ); + if ( i == _attachedMedia.end() ) + return false; + + _attachedMedia.erase(i); + return true; + } + + void DeviceDriver::releaseIdleDevices () + { + for ( auto i = _sysDevs.begin (); i != _sysDevs.end(); ) { + if ( i->use_count() == 1 && !(*i)->_mountPoint.empty() ) { + MIL << "Unmounting device " << (*i)->_name << " since its not used anymore" << std::endl; + unmountDevice(*(*i)); + if ( (*i)->_ephemeral ) { + i = _sysDevs.erase(i); + continue; + } + } + ++i; + } + } + + void DeviceDriver::detectDevices() + { + return; + } + + std::vector> &DeviceDriver::knownDevices() + { + return _sysDevs; + } + + const std::vector> &DeviceDriver::knownDevices() const + { + return _sysDevs; + } + + std::unordered_map &DeviceDriver::attachedMedia() + { + return _attachedMedia; + } + + void DeviceDriver::immediateShutdown() + { + // here we need to unmount everything + for ( auto i = _sysDevs.begin (); i != _sysDevs.end(); ) { + unmountDevice(*(*i)); + if ( (*i)->_ephemeral ) { + i = _sysDevs.erase(i); + continue; + } + ++i; + } + _attachedMedia.clear(); + } + + ProvideWorkerRef DeviceDriver::parentWorker () const + { + return _parentWorker.lock(); + } + + void DeviceDriver::unmountDevice ( Device &dev ) + { + if ( dev._mountPoint.empty () ) + return; + try { + zypp::media::Mount mount; + mount.umount( dev._mountPoint.asString() ); + removeAttachPoint( dev._mountPoint ); + } catch (const zypp::media::MediaException & excpt_r) { + ERR << "Failed to unmount device: " << dev._name << std::endl; + ZYPP_CAUGHT(excpt_r); + } + dev._mountPoint = zypp::Pathname(); + } + + bool DeviceDriver::isVolatile () const + { + return false; + } + + void DeviceDriver::setAttachRoot ( const zypp::Pathname &root ) + { + _attachRoot = root; + } + + zypp::Pathname DeviceDriver::attachRoot () const + { + if ( _attachRoot.empty() ) { + MIL << "Attach root is empty" << std::endl; + return zypp::Pathname(".").realpath(); + } + return _attachRoot; + } + + const zyppng::worker::Configuration &DeviceDriver::config() const + { + return _config; + } + + zyppng::expected DeviceDriver::isDesiredMedium ( const zypp::Url &deviceUrl, const zypp::Pathname &mountPoint, const zyppng::MediaDataVerifierRef &verifier, uint mediaNr ) + { + if ( !verifier ) { + // at least the requested path must exist on the medium + zypp::PathInfo p( mountPoint ); + if ( p.isExist() && p.isDir() ) + return zyppng::expected::success(); // we have no valid data + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaNotDesiredException( deviceUrl ) ) ); + } + + auto devVerifier = verifier->clone(); + if ( !devVerifier ) { + // unlikely to happen + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::Exception("Failed to clone verifier") ) ); + } + + // bsc#1180851: If there is just one not-volatile medium in the set + // tolerate a missing (vanished) media identifier and let the URL rule. + bool relaxed = verifier->totalMedia() == 1 && !isVolatile(); + + const auto &relMediaPath = devVerifier->mediaFilePath( mediaNr ); + zypp::Pathname mediaFile { mountPoint / relMediaPath }; + zypp::PathInfo pi( mediaFile ); + if ( !pi.isExist() ) { + if ( relaxed ) + return zyppng::expected::success(); + auto excpt = zypp::media::MediaFileNotFoundException( deviceUrl, relMediaPath ) ; + excpt.addHistory( verifier->expectedAsUserString( mediaNr ) ); + return zyppng::expected::error( ZYPP_EXCPT_PTR( std::move(excpt) ) ); + } + if ( !pi.isFile() ) { + if ( relaxed ) + return zyppng::expected::success(); + auto excpt = zypp::media::MediaNotAFileException( deviceUrl, relMediaPath ) ; + excpt.addHistory( verifier->expectedAsUserString( mediaNr ) ); + return zyppng::expected::error( ZYPP_EXCPT_PTR( std::move(excpt) ) ); + } + + if ( !devVerifier->load( mediaFile ) ) { + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::Exception("Failed to load media information from medium") ) ); + } + if ( !verifier->matches( devVerifier ) ) { + return zyppng::expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaNotDesiredException( deviceUrl ) ) ); + } + return zyppng::expected::success(); + } + + zypp::Pathname DeviceDriver::createAttachPoint( const zypp::Pathname &attach_root ) const + { + zypp::Pathname apoint; + + if( attach_root.empty() || !attach_root.absolute()) { + ERR << "Create attach point: invalid attach root: '" + << attach_root << "'" << std::endl; + return apoint; + } + + zypp::PathInfo adir( attach_root ); + if( !adir.isDir() || (geteuid() != 0 && !adir.userMayRWX())) { + DBG << "Create attach point: attach root is not a writable directory: '" + << attach_root << "'" << std::endl; + return apoint; + } + + static bool cleanup_once( true ); + if ( cleanup_once ) + { + cleanup_once = false; + DBG << "Look for orphaned attach points in " << adir << std::endl; + std::list entries; + zypp::filesystem::readdir( entries, attach_root, false ); + for ( const std::string & entry : entries ) + { + if ( ! zypp::str::hasPrefix( entry, "AP_0x" ) ) + continue; + zypp::PathInfo sdir( attach_root + entry ); + if ( sdir.isDir() + && sdir.dev() == adir.dev() + && ( zypp::Date::now()-sdir.mtime() > zypp::Date::month ) ) + { + DBG << "Remove orphaned attach point " << sdir << std::endl; + zypp::filesystem::recursive_rmdir( sdir.path() ); + } + } + } + + zypp::filesystem::TmpDir tmpdir( attach_root, "AP_0x" ); + if ( tmpdir ) + { + apoint = tmpdir.path().asString(); + if ( ! apoint.empty() ) + { + tmpdir.autoCleanup( false ); // Take responsibility for cleanup. + } + else + { + ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl; + } + } + else + { + ERR << "Unable to create attach point below " << attach_root << std::endl; + } + return apoint; + } + + void DeviceDriver::removeAttachPoint( const zypp::filesystem::Pathname &attachRoot ) const + { + if( !attachRoot.empty() && + zypp::PathInfo(attachRoot).isDir() && + attachRoot != "/" ) { + int res = rmdir( attachRoot ); + if ( res == 0 ) { + MIL << "Deleted default attach point " << attachRoot << std::endl; + } else { + ERR << "Failed to Delete default attach point " << attachRoot + << " errno(" << res << ")" << std::endl; + } + } + } + + bool DeviceDriver::checkAttached ( const zypp::filesystem::Pathname &mountPoint, const std::function predicate ) + { + bool isAttached = false; + time_t old_mtime = _attach_mtime; + _attach_mtime = zypp::media::Mount::getMTime(); + if( !(old_mtime <= 0 || _attach_mtime != old_mtime) ) { + // OK, skip the check (we've seen it at least once) + isAttached = true; + } else { + if( old_mtime > 0) + DBG << "Mount table changed - rereading it" << std::endl; + else + DBG << "Forced check of the mount table" << std::endl; + + for( const auto &entry : zypp::media::Mount::getEntries() ) { + + if ( mountPoint != zypp::Pathname(entry.dir) ) + continue; // at least the mount points must match + if ( predicate(entry) ) { + isAttached = true; + break; + } + } + } + + // force recheck + if ( !isAttached ) + _attach_mtime = 0; + + return isAttached; + } + + const std::function DeviceDriver::devicePredicate( unsigned int majNr, unsigned int minNr ) + { + return [ majNr, minNr ]( const zypp::media::MountEntry &entry ) -> bool { + if( entry.isBlockDevice() ) { + zypp::PathInfo dev_info( entry.src ); + if ( dev_info.devMajor () == majNr && dev_info.devMinor () == minNr ) { + DBG << "Found device " + << majNr << ":" << minNr + << " in the mount table as " << entry.src << std::endl; + return true; + } + } + return false; + }; + } + + const std::function DeviceDriver::fstypePredicate( const std::string &src, const std::vector &fstypes ) + { + return [ srcdev=src, fst=fstypes ]( const zypp::media::MountEntry &entry ) -> bool { + if( !entry.isBlockDevice() ) { + if ( std::find( fst.begin(), fst.end(), entry.type ) != fst.end() ) { + if ( srcdev == entry.src ) { + DBG << "Found media mount" + << " in the mount table as " << entry.src << std::endl; + return true; + } + } + } + return false; + }; + } + + const std::function DeviceDriver::bindMountPredicate( const std::string &src ) + { + return [ srcdev=src ]( const zypp::media::MountEntry &entry ) -> bool { + if( !entry.isBlockDevice() ) { + if ( srcdev == entry.src ) { + DBG << "Found bound media " + << " in the mount table as " << entry.src << std::endl; + return true; + } + } + return false; + }; + } + + AttachError::AttachError ( const MessageCodes code, const std::string &reason, const bool transient, const HeaderValueMap &extra) + : _code( code ), + _reason( reason ), + _transient( transient ), + _extra( extra ) + { + + } + + AttachError::AttachError ( const MessageCodes code, const bool transient, const zypp::Exception &e ) + : _code( code ), + _reason( e.asUserString() ), + _transient( transient ) + { + if ( !e.historyEmpty() ) { + _extra = { { std::string(zyppng::ErrMsgFields::History), { zyppng::HeaderValueMap::Value(e.historyAsString()) }} }; + } + } + + +} diff --git a/zypp-media/ng/worker/devicedriver.h b/zypp-media/ng/worker/devicedriver.h new file mode 100644 index 0000000..0ebd6c1 --- /dev/null +++ b/zypp-media/ng/worker/devicedriver.h @@ -0,0 +1,202 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_MEDIA_NG_WORKER_DEVICEDRIVER_H_INCLUDED +#define ZYPP_MEDIA_NG_WORKER_DEVICEDRIVER_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng::worker +{ + + ZYPP_FWD_DECL_TYPE_WITH_REFS (DeviceDriver); + + struct Device + { + std::string _name; //!< Path of the device node or URL for e.g. nfs devices + unsigned int _maj_nr = 0; //!< Major number of the device + unsigned int _min_nr = 0; //!< Minor number of the device + zypp::Pathname _mountPoint = {};//!< Mountpoint of the device, if empty dev is not mounted + bool _ephemeral = false; //!< If set to true the device is removed from the internal list after the last attachpoint was released + std::unordered_map _properties = {}; + }; + + struct AttachedMedia + { + std::shared_ptr _dev; + zypp::Pathname _attachRoot; + }; + + struct AttachError + { + AttachError ( const MessageCodes code, const std::string &reason, const bool transient, const HeaderValueMap &extra = {} ); + AttachError ( const MessageCodes code, const bool transient, const zypp::Exception &e ); + + MessageCodes _code; + std::string _reason; + bool _transient; + HeaderValueMap _extra; + }; + + // either the mountpoint or an error + using AttachResult = expected; + + /*! + * Abstract base class to be used together with the \sa MountingWorker class to control + * attaching and detaching of a multitude of different media types via a unified interface. + * Reimplement this class to easily support a new backend that utilizes the "mount" command to + * attach real filesystems to the system. + */ + class DeviceDriver : public zyppng::Base + { + public: + + DeviceDriver ( WorkerCaps::WorkerType wType ); + + /*! + * Tells the driver which provide worker to use when requiring auth data or media changes + */ + void setProvider ( ProvideWorkerWeakRef workerRef ); + + /*! + * Called by the provide loop whenever a attach request is received. + */ + virtual AttachResult mountDevice ( const uint32_t id, const zypp::Url &mediaUrl, const std::string &attachId, const std::string &label, const HeaderValueMap &extras ) = 0; + + + + virtual zyppng::expected initialize(const zyppng::worker::Configuration &conf); + + + /*! + * Detaches the medium referenced by \a attachId. + * Returns false if the medium could not be found + * + * \note this will not unmount the physical devices. + * Call \ref releaseIdleDevices to force this. + * + */ + bool detachMedia ( const std::string &attachId ); + + /*! + * Physically detaches all devices that are not referenced by a attachment anymore + */ + void releaseIdleDevices (); + + /*! + * Called by the parent to populate the device array every time a provide request arrives, only + * relevant for workers that operate on detectable devices. + * The base implementation does nothing + */ + virtual void detectDevices(); + + /*! + * Returns a list of all currently known devices, a subclass should always make sure + * that all currently mounted devices are present in that list. + */ + std::vector> &knownDevices(); + + /*! + * Returns a list of all currently known devices, a subclass should always make sure + * that all currently mounted devices are present in that list. + */ + const std::vector> &knownDevices() const; + + /*! + * Returns the list of currently attached medias + */ + std::unordered_map &attachedMedia(); + + /*! + * Returns true if the worker handles volatile devices ( e.g. DVDs ). + * The default impl returns false. + */ + virtual bool isVolatile () const; + + /*! + * Changes the attach root to a specific path, otherwise realpath(".") is used. + */ + void setAttachRoot ( const zypp::Pathname &root ); + + /*! + * Returns the \a attachRoot as dictated by the controller + */ + zypp::Pathname attachRoot () const; + + /*! + * The system is shutting down, release all ressources + */ + virtual void immediateShutdown(); + + /*! + * Returns the parent worker if set + */ + ProvideWorkerRef parentWorker () const; + + /*! + * Returns the configuration that was sent by the controller + */ + const zyppng::worker::Configuration &config() const; + + protected: + /*! + * Forcefully unmounts the device, this does not check if there any attached medias still relying on it + */ + virtual void unmountDevice ( Device &dev ); + + /*! + * Checks if the medium \a deviceUrl mounted on \a path matches the \a verifier and \a mediaNr + */ + zyppng::expected isDesiredMedium ( const zypp::Url &deviceUrl, const zypp::Pathname &mountPoint, const zyppng::MediaDataVerifierRef &verifier, uint mediaNr = 1 ); + + + zypp::Pathname createAttachPoint(const zypp::Pathname &attach_root) const; + void removeAttachPoint ( const zypp::Pathname &attach_pt ) const; + bool checkAttached ( const zypp::Pathname &mountPoint, const std::function predicate ); + + /*! + * Returns a predicate for the \ref checkAttached function that looks for a real device in the mount table + */ + static const std::function devicePredicate ( unsigned int majNr, unsigned int minNr ); + + /*! + * Returns a predicate for the \ref checkAttached function that looks for a virtual mount ( like smb or nfs ) in the mount table + */ + static const std::function fstypePredicate ( const std::string &src, const std::vector &fstypes ); + + /*! + * Returns a predicate for the \ref checkAttached function that looks for a bind mount in the mount table + */ + static const std::function bindMountPredicate ( const std::string &src ); + + private: + WorkerCaps::WorkerType _wType; + ProviderConfiguration _config; + time_t _attach_mtime = 0; //< Timestamp of the mtab we did read + zypp::Pathname _attachRoot; + std::vector> _sysDevs; + std::unordered_map _attachedMedia; + ProvideWorkerWeakRef _parentWorker; + }; + + + + +} + +#endif diff --git a/zypp-media/ng/worker/mountingworker.cc b/zypp-media/ng/worker/mountingworker.cc new file mode 100644 index 0000000..bdc37d5 --- /dev/null +++ b/zypp-media/ng/worker/mountingworker.cc @@ -0,0 +1,191 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "mountingworker.h" +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "MountingWorker" + +namespace zyppng::worker +{ + + MountingWorker::MountingWorker( std::string_view workerName, DeviceDriverRef driver ) + : ProvideWorker( workerName ) + , _driver(driver) + { } + + MountingWorker::~MountingWorker() + { + _driver->immediateShutdown(); + } + + zyppng::expected MountingWorker::initialize( const zyppng::worker::Configuration &conf ) + { + return _driver->initialize(conf); + } + + void MountingWorker::provide() + { + _driver->detectDevices(); + auto &queue = requestQueue(); + + if ( !queue.size() ) + return; + + auto req = queue.front(); + queue.pop_front(); + + MIL_PRV << "Received provide: " << req->_spec.code() << std::endl; + + try { + switch ( req->_spec.code () ) { + case zyppng::ProvideMessage::Code::Attach: { + + const auto attachUrl = zypp::Url( req->_spec.value( zyppng::AttachMsgFields::Url ).asString() ); + const auto label = req->_spec.value( zyppng::AttachMsgFields::Label, "No label" ).asString(); + const auto attachId = req->_spec.value( zyppng::AttachMsgFields::AttachId ).asString(); + HeaderValueMap vals; + for ( const auto &i : req->_spec.headers() ) { + if ( i.first == zyppng::AttachMsgFields::Url + || i.first == zyppng::AttachMsgFields::Label + || i.first == zyppng::AttachMsgFields::AttachId ) + continue; + vals.set( i.first, i.second ); + } + + const auto &res = _driver->mountDevice( req->_spec.requestId(), attachUrl, attachId, label, vals ); + if ( !res ) { + const auto &err = res.error(); + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , err._code + , err._reason + , err._transient + , err._extra ); + return; + } + + MIL << "Attach of " << attachUrl << " was successfull" << std::endl; + + attachSuccess( req->_spec.requestId(), res.get().asString() ); + return; + } + case zyppng::ProvideMessage::Code::Detach: { + + const auto url = zypp::Url( req->_spec.value( zyppng::DetachMsgFields::Url ).asString() ); + const auto &attachId = url.getAuthority(); + + if ( _driver->detachMedia( attachId ) ) { + detachSuccess ( req->_spec.requestId() ); + } else { + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotFound + , "Attach ID not known." + , false + , {} ); + return; + } + + _driver->releaseIdleDevices(); + return; + } + + case zyppng::ProvideMessage::Code::Prov: { + + const auto url = zypp::Url( req->_spec.value( zyppng::DetachMsgFields::Url ).asString() ); + const auto &attachId = url.getAuthority(); + const auto &path = zypp::Pathname(url.getPathName()); + const auto &availMedia = _driver->attachedMedia(); + + auto i = availMedia.find( attachId ); + if ( i == availMedia.end() ) { + ERR << "Unknown Attach ID " << attachId << std::endl; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotFound + , "Attach ID not known." + , false + , {} ); + return; + } + + const auto &locPath = i->second._dev->_mountPoint / i->second._attachRoot / path; + + MIL << "Trying to find file: " << locPath << std::endl; + + zypp::PathInfo info( locPath ); + if( info.isFile() ) { + provideSuccess ( req->_spec.requestId(), false, locPath ); + return; + } + + if (info.isExist()) + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotAFile + , zypp::str::Str() << "Path " << path << " exists, but its not a file" + , false + , {} ); + else + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::NotFound + , zypp::str::Str() << "File " << path << " not found on medium" + , false + , {} ); + + + break; + } + default: { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , "Request type not implemented" + , false + , {} ); + return; + } + } + } catch ( const zypp::Exception &e ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , e.asString() + , false + , {} ); + return; + } catch ( const std::exception &e ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , e.what() + , false + , {} ); + return; + } catch ( ... ) { + req->_state = zyppng::worker::ProvideWorkerItem::Finished; + provideFailed( req->_spec.requestId() + , zyppng::ProvideMessage::Code::BadRequest + , "Unknown exception" + , false + , {} ); + return; + } + } + + void MountingWorker::cancel( const std::deque::iterator &i ) + { + ERR << "Bug, cancel should never be called for running items" << std::endl; + } + + void MountingWorker::immediateShutdown() + { + _driver->immediateShutdown(); + } +} diff --git a/zypp-media/ng/worker/mountingworker.h b/zypp-media/ng/worker/mountingworker.h new file mode 100644 index 0000000..f200d13 --- /dev/null +++ b/zypp-media/ng/worker/mountingworker.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_MEDIA_NG_WORKER_MOUNTINGWORKER_H_INCLUDED +#define ZYPP_MEDIA_NG_WORKER_MOUNTINGWORKER_H_INCLUDED + +#include +#include +#include +#include +#include + +namespace zyppng::worker +{ + class MountingWorker : public zyppng::worker::ProvideWorker + { + public: + MountingWorker( std::string_view workerName, DeviceDriverRef driver ); + ~MountingWorker(); + + void immediateShutdown() override; + + protected: + // ProvideWorker interface + zyppng::expected initialize(const zyppng::worker::Configuration &conf) override; + void provide() override; + void cancel( const std::deque::iterator &i ) override; + + private: + DeviceDriverRef _driver; + bool _devicesDetected = false; //< We delay device detection to the first attach request, to avoid doing it without needing it + }; +} + +#endif diff --git a/zypp-media/ng/worker/provideworker.cc b/zypp-media/ng/worker/provideworker.cc new file mode 100644 index 0000000..d5ccb90 --- /dev/null +++ b/zypp-media/ng/worker/provideworker.cc @@ -0,0 +1,466 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "provideworker.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "ProvideWorker" + +namespace zyppng::worker { + + using namespace zyppng::operators; + + RequestCancelException::RequestCancelException() : zypp::media::MediaException ("Request was cancelled") + { } + + ProvideWorker::ProvideWorker(std::string_view workerName) : _workerName(workerName) + { + // do not change the order of these calls, otherwise showing the threadname does not work + // enableLogForwardingMode will initialize the log which would override the current thread name + zypp::base::LogControl::instance().enableLogForwardingMode( true ); + ThreadData::current().setName( workerName ); + + // we use a singleshot timer that triggers message handling + connect( *_msgAvail, &Timer::sigExpired, *this, &ProvideWorker::messageLoop ); + _msgAvail->setSingleShot(true); + + // another timer to trigger a delayed shutdown + connectFunc( *_delayedShutdown, &Timer::sigExpired, [this]( zyppng::Timer & ) { + maybeDelayedShutdown(); + }, *this ); + _delayedShutdown->setSingleShot(true); + } + + ProvideWorker::~ProvideWorker() + { } + + StompFrameStreamRef ProvideWorker::messageStream() const + { + return _stream; + } + + expected ProvideWorker::run( int recv, int send ) + { + // reentry not supported + assert ( !_isRunning ); + + zypp::DtorReset res( _isRunning ); + _isRunning = true; + + initLog(); + + zypp::OnScopeExit cleanup([&](){ + _stream.reset(); + _controlIO.reset(); + _loop.reset(); + }); + + _controlIO = AsyncDataSource::create(); + if ( !_controlIO->openFds( { recv }, send ) ) { + return expected::error( ZYPP_EXCPT_PTR(zypp::Exception("Failed to open control FDs")) ); + } + + connect( *_controlIO, &AsyncDataSource::sigReadFdClosed, *this, &ProvideWorker::readFdClosed ); + connect( *_controlIO, &AsyncDataSource::sigWriteFdClosed, *this, &ProvideWorker::writeFdClosed ); + + _stream = StompFrameStream::create( _controlIO ); + + return executeHandshake () | and_then( [&]() { + AutoDisconnect disC[] = { + connect( *_stream, &StompFrameStream::sigMessageReceived, *this, &ProvideWorker::messageReceived ), + connect( *_stream, &StompFrameStream::sigInvalidMessageReceived, *this, &ProvideWorker::onInvalidMessageReceived ) + }; + _loop->run(); + if ( _fatalError ) + return expected::error( _fatalError ); + return expected::success(); + }); + } + + std::deque &ProvideWorker::requestQueue() + { + return _pendingProvides; + } + + ProvideWorker::ProvideNotificatioMode ProvideWorker::provNotificationMode() const { + return _provNotificationMode; + } + + void ProvideWorker::setProvNotificationMode( const ProvideNotificatioMode &provNotificationMode ) { + _provNotificationMode = provNotificationMode; + } + + void ProvideWorker::initLog() + { + // by default we log to strErr, if user code wants to change that it can overload this function + zypp::base::LogControl::instance().logToStdErr(); + } + + ProvideWorkerItemRef ProvideWorker::makeItem( ProvideMessage &&spec ) + { + return std::make_shared( std::move(spec) ); + } + + void ProvideWorker::provideStart(const uint32_t id, const zypp::Url &url, const zypp::filesystem::Pathname &localFile, const zypp::Pathname &stagingFile ) + { + if ( !_stream->sendMessage( ProvideMessage::createProvideStarted ( id + , url + , localFile.empty () ? std::optional() : localFile.asString () + , stagingFile.empty () ? std::optional() : stagingFile.asString () + ) ) ) { + ERR << "Failed to send ProvideStart message" << std::endl; + } + } + + void ProvideWorker::provideSuccess(const uint32_t id, bool cacheHit, const zypp::filesystem::Pathname &localFile, const HeaderValueMap extra ) + { + MIL_PRV << "Sending provideSuccess for id " << id << " file " << localFile << std::endl; + auto msg = ProvideMessage::createProvideFinished( id ,localFile.asString() ,cacheHit); + for ( auto i = extra.beginList (); i != extra.endList(); i++ ) { + for ( const auto &val : i->second ) + msg.addValue( i->first, val ); + } + if ( !_stream->sendMessage( msg ) ) { + ERR << "Failed to send ProvideSuccess message" << std::endl; + } + } + + void ProvideWorker::provideFailed(const uint32_t id, const ProvideMessage::Code code, const std::string &reason, const bool transient, const HeaderValueMap extra ) + { + MIL_PRV << "Sending provideFailed for request " << id << " err: " << reason << std::endl; + auto msg = ProvideMessage::createErrorResponse ( id, code, reason, transient ); + for ( auto i = extra.beginList (); i != extra.endList(); i++ ) { + for ( const auto &val : i->second ) + msg.addValue( i->first, val ); + } + if ( !_stream->sendMessage( msg ) ) { + ERR << "Failed to send ProvideFailed message" << std::endl; + } + } + + + void ProvideWorker::provideFailed ( const uint32_t id, const ProvideMessage::Code code, const bool transient, const zypp::Exception &e ) + { + zyppng::HeaderValueMap extra; + if ( !e.historyEmpty() ) { + extra = { { std::string(zyppng::ErrMsgFields::History), { zyppng::HeaderValueMap::Value(e.historyAsString()) }} }; + } + provideFailed( id + , code + , e.asUserString() + , transient + , extra ); + } + + + void ProvideWorker::attachSuccess(const uint32_t id, const std::optional &localMountPoint) + { + MIL_PRV << "Sending attachSuccess for request " << id << std::endl; + if ( !_stream->sendMessage( ProvideMessage::createAttachFinished ( id, localMountPoint ) ) ) { + ERR << "Failed to send AttachFinished message" << std::endl; + } else { + MIL << "Sent back attach success" << std::endl; + } + } + + void ProvideWorker::detachSuccess(const uint32_t id) + { + MIL_PRV << "Sending detachSuccess for request " << id << std::endl; + if ( !_stream->sendMessage( ProvideMessage::createDetachFinished ( id ) ) ) { + ERR << "Failed to send DetachFinished message" << std::endl; + } + } + + expected ProvideWorker::sendAndWaitForResponse( const ProvideMessage &request , const std::vector &responseCodes ) + { + // make sure immediateShutdown is not called while we are blocking here + zypp::DtorReset delayedReset( _inControllerRequest ); + _inControllerRequest = true; + + if ( !_stream->sendMessage( request ) ) + return expected::error( ZYPP_EXCPT_PTR(zypp::Exception("Failed to send message")) ); + + // flush the io device, this will block until all bytes are written + _controlIO->flush(); + + while ( !_fatalError ) { + + const auto &msg = _stream->nextMessageWait() | [&]( auto &&nextMessage ) { + if ( !nextMessage ) { + if ( _fatalError ) + return expected::error( _fatalError ); + else + return expected::error( ZYPP_EXCPT_PTR(zypp::Exception("Failed to wait for response")) ); + } + return expected::success( std::move(*nextMessage) ); + } | and_then ( [&]( auto && m) { + return parseReceivedMessage(m); + } ); + + if ( !msg ) { + ERR << "Failed to receive message" << std::endl; + return msg; + } + + if ( std::find( responseCodes.begin (), responseCodes.end(), msg->code() ) != responseCodes.end() ) { + return msg; + } + + // remember other messages for later + MIL << "Remembering message for later: " << msg->code () << std::endl; + _pendingMessages.push_back(*msg); + _msgAvail->start(0); + } + return expected::error( _fatalError ); + } + + ProvideWorker::MediaChangeRes ProvideWorker::requestMediaChange(const uint32_t id, const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc ) + { + return sendAndWaitForResponse( ProvideMessage::createMediaChangeRequest ( id, label, mediaNr, devices, desc ), { ProvideMessage::Code::MediaChanged, ProvideMessage::Code::MediaChangeAbort, ProvideMessage::Code::MediaChangeSkip } ) + | [&]( expected &&m ) { + if ( !m ) { + MIL << "Failed to wait for message, aborting the request " << std::endl; + return ProvideWorker::MediaChangeRes::ABORT; + } + MIL << "Wait finished, with messages still pending: " << this->_pendingMessages.size() << " and provs still pending: " << this->_pendingProvides.size() << std::endl; + if ( m->code() == ProvideMessage::Code::MediaChanged ) + return ProvideWorker::MediaChangeRes::SUCCESS; + else if ( m->code() == ProvideMessage::Code::MediaChangeSkip ) + return ProvideWorker::MediaChangeRes::SKIP; + else + return ProvideWorker::MediaChangeRes::ABORT; + }; + } + + expected ProvideWorker::requireAuthorization( const uint32_t id, const zypp::Url &url, const std::string &lastTriedUsername, const int64_t lastTimestamp, const std::map &extraFields ) + { + return sendAndWaitForResponse( ProvideMessage::createAuthDataRequest( id, url, lastTriedUsername, lastTimestamp, extraFields ), { ProvideMessage::Code::AuthInfo, ProvideMessage::Code::NoAuthData } ) + | and_then( [&]( ProvideMessage &&m ) { + if ( m.code() == ProvideMessage::Code::AuthInfo ) { + + AuthInfo inf; + for( const auto &hdr : m.headers () ) { + if ( hdr.first == AuthInfoMsgFields::Username ) { + inf.username = hdr.second.asString(); + } else if ( hdr.first == AuthInfoMsgFields::Password ) { + inf.password = hdr.second.asString(); + } else if ( hdr.first == AuthInfoMsgFields::AuthTimestamp ) { + inf.last_auth_timestamp = hdr.second.asInt64(); + } else { + if ( !hdr.second.isString() ) { + ERR << "Ignoring invalid extra value, " << hdr.first << " is not of type string" << std::endl; + } + inf.extraKeys[hdr.first] = hdr.second.asString(); + } + } + return expected::success(inf); + + } + return expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("No Auth data")) ); + }); + } + + AsyncDataSource &ProvideWorker::controlIO() + { + return *_controlIO.get(); + } + + expected ProvideWorker::executeHandshake() + { + const auto &helo = _stream->nextMessageWait(); + if ( !helo ) { + ERR << "Could not receive a handshake message, aborting" << std::endl; + return expected::error( ZYPP_EXCPT_PTR(zypp::Exception("Failed to receive handshake message")) );; + } + + auto exp = _stream->parseMessage( *helo ); + if ( !exp ) { + invalidMessageReceived( exp.error() ); + return expected::error(exp.error()); + } + + return std::move(*exp) | [&]( auto conf ) { + + _workerConf = std::move(conf); + + auto &mediaConf = zypp::MediaConfig::instance(); + for( const auto &[key,value] : _workerConf ) { + zypp::Url keyUrl( key ); + if ( keyUrl.getScheme() == "zconfig" && keyUrl.getAuthority() == "main" ) { + mediaConf.setConfigValue( keyUrl.getAuthority(), zypp::Pathname(keyUrl.getPathName()).basename(), value ); + } + } + + return initialize( _workerConf ) | and_then([&]( WorkerCaps &&caps ){ + + caps.set_worker_name( _workerName.data() ); + + caps.set_cfg_flags ( WorkerCaps::Flags(caps.cfg_flags() | WorkerCaps::ZyppLogFormat) ); + if ( !_stream->sendMessage ( caps ) ) { + return expected::error( ZYPP_EXCPT_PTR(zypp::Exception("Failed to send capabilities")) ); + } + return expected::success (); + }); + }; + } + + void ProvideWorker::messageLoop( Timer & ) + { + if ( _fatalError ) + return; + + while ( _pendingMessages.size () ) { + auto m = _pendingMessages.front (); + _pendingMessages.pop_front (); + handleSingleMessage(m); + } + + if ( !_fatalError && _pendingProvides.size() ) { + provide(); + } + + // keep poking until there are no provides anymore + if ( !_fatalError && ( _pendingMessages.size() || ( _pendingProvides.size () && _provNotificationMode == QUEUE_NOT_EMTPY ) ) ) { + _msgAvail->start(0); + } + + } + + void ProvideWorker::maybeDelayedShutdown() + { + if ( _inControllerRequest ) { + _delayedShutdown->start(0); + return; + } + + immediateShutdown(); + _loop->quit (); + } + + void ProvideWorker::readFdClosed( uint, AsyncDataSource::ChannelCloseReason ) + { + MIL << "Read FD closed, exiting." << std::endl; + maybeDelayedShutdown(); + } + + void ProvideWorker::writeFdClosed( AsyncDataSource::ChannelCloseReason ) + { + MIL << "Write FD closed, exiting." << std::endl; + maybeDelayedShutdown(); + } + + void ProvideWorker::messageReceived() + { + while ( auto message = _stream->nextMessage() ) { + if ( _fatalError ) + break; + pushSingleMessage(*message); + } + } + + void ProvideWorker::onInvalidMessageReceived() + { + invalidMessageReceived( std::exception_ptr() ); + } + + void ProvideWorker::invalidMessageReceived( std::exception_ptr p ) + { + ERR << "Received a invalid message on the input stream, aborting" << std::endl; + if ( p ) + _fatalError = p; + else + _fatalError = ZYPP_EXCPT_PTR( InvalidMessageReceivedException() ); + immediateShutdown(); + _loop->quit(); + } + + void ProvideWorker::handleSingleMessage( const ProvideMessage &provide ) + { + const auto code = provide.code(); + // we only accept requests here + if ( code >= ProvideMessage::Code::FirstControllerCode && code <= ProvideMessage::Code::LastControllerCode ) { + + MIL_PRV << "Received request: " << code << std::endl; + + if ( code == ProvideMessage::Code::Cancel ) { + const auto &i = std::find_if( _pendingProvides.begin (), _pendingProvides.end(), [ id = provide.requestId() ]( const auto &it ){ return it->_spec.requestId() == id; } ); + if ( i != _pendingProvides.end() ) { + switch ( (*i)->_state ) { + case ProvideWorkerItem::Pending: + _stream->sendMessage ( ProvideMessage::createErrorResponse ( provide.requestId (), ProvideMessage::Code::Cancelled, "Cancelled by user." ) ); + _pendingProvides.erase(i); + break; + case ProvideWorkerItem::Running: + cancel(i); + break; + case ProvideWorkerItem::Finished: + break; + } + MIL << "Received Cancel for unknown request: " << provide.requestId() << ", ignoring!" << std::endl; + } + return; + } + + _pendingProvides.push_back( makeItem (ProvideMessage(provide)) ); + return; + } + ERR << "Unsupported request with code: " << code << " received!" << std::endl; + } + + void ProvideWorker::pushSingleMessage( const zypp::PluginFrame &message ) + { + const auto &handle = [&]( const zypp::PluginFrame &message ){ + return parseReceivedMessage (message ) + | and_then( [&]( ProvideMessage &&provide ){ + _pendingMessages.push_back(provide); + _msgAvail->start(0); + return expected::success(); + }) + | or_else( [&]( std::exception_ptr ) -> expected { + return expected::error( ZYPP_EXCPT_PTR( std::invalid_argument(zypp::str::Str()<<"Unknown message received: " << message.command() )) ); + }); + }; + + const auto &exp = handle( message ); + if ( !exp ) { + try { + std::rethrow_exception ( exp.error () ); + } catch ( const zypp::Exception &e ) { + ERR << "Catched exception during message handling: " << e << std::endl; + } catch ( const std::exception &e ) { + ERR << "Catched exception during message handling: " << e.what()<< std::endl; + } catch ( ... ) { + ERR << "Unknown Exception during message handling" << std::endl; + } + } + } + + expected ProvideWorker::parseReceivedMessage( const zypp::PluginFrame &m) + { + auto exp = ProvideMessage::create(m); + if ( !exp ) + invalidMessageReceived( exp.error() ); + return exp; + } +} diff --git a/zypp-media/ng/worker/provideworker.h b/zypp-media/ng/worker/provideworker.h new file mode 100644 index 0000000..1de07dc --- /dev/null +++ b/zypp-media/ng/worker/provideworker.h @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_MEDIA_PROVIDE_WORKER_H_INCLUDED +#define ZYPP_MEDIA_PROVIDE_WORKER_H_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace zyppng::worker { + + using WorkerCaps = zyppng::WorkerCaps; + using Message = zyppng::ProvideMessage; + using Configuration = zyppng::ProviderConfiguration; + + struct AuthInfo + { + std::string username; + std::string password; + int64_t last_auth_timestamp = 0; + std::map extraKeys = {}; + }; + + class ZYPP_API RequestCancelException : public zypp::media::MediaException + { + public: + RequestCancelException(); + }; + + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProvideWorker); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProvideWorkerItem); + + class ProvideWorkerItem : public zyppng::Base + { + public: + enum State { + Pending, + Running, + Finished + }; + + ProvideWorkerItem( ProvideMessage &&spec ) : _spec( std::move(spec) ) { } + + State _state = Pending; + ProvideMessage _spec; + }; + + class ProvideWorker : public Base + { + public: + + enum ProvideNotificatioMode { + ONLY_NEW_PROVIDES, // provide is called only when new provide requests are added to the queue + QUEUE_NOT_EMTPY // provide is called continiously until the queue is empty + }; + + ProvideWorker( std::string_view workerName ); + virtual ~ProvideWorker(); + + StompFrameStreamRef messageStream() const; + + expected run ( int recv = STDIN_FILENO, int send = STDOUT_FILENO ); + + std::deque &requestQueue(); + /*! + * Called when the worker process exits + */ + virtual void immediateShutdown (){}; + + /*! + * This will request a media change from the user and BLOCK until it was acknowledged. + * + */ + enum MediaChangeRes { + SUCCESS, + ABORT, + SKIP + }; + MediaChangeRes requestMediaChange ( const uint32_t id, const std::string &label, const int32_t mediaNr, const std::vector &devices, const std::optional &desc = {} ); + + /*! + * This will send a authorization request message to the controller, asking for credentials for a given \a url. + * The \a lastTimstamp should be initialized with the last \ref AuthInfo timestamp that was received from the controller + * or -1 if none was received before. + * + * \note this blocks until a answer is received, all other received messages are delayed + */ + expected requireAuthorization ( const uint32_t id, const zypp::Url &url, const std::string &lastTriedUsername = "", const int64_t lastTimestamp = -1, const std::map &extraFields = {} ); + + ProvideNotificatioMode provNotificationMode() const; + void setProvNotificationMode(const ProvideNotificatioMode &provNotificationMode); + + protected: + virtual void initLog(); + virtual expected initialize ( const Configuration &conf ) = 0; + + /*! + * Automatically called whenever a new item is enqueued. + */ + virtual void provide ( ) = 0; + virtual void cancel ( const std::deque::iterator &request ) = 0; + + /*! + * Always called to create new items for the request queue, + * override this to populate the queue with instances of custom \ref ProvideItem subclasses. + * + * Cancel requests are directly handled by calling cancel(), however Attach and Detach requests are enqueued as well + */ + virtual ProvideWorkerItemRef makeItem (ProvideMessage &&spec ); + + /*! + * Send a \a ProvideStart signal to the controller, this is to notify the controller that we have started providing the file + * the argument \a localFile has to refer to the file where the file will be provided into, it will be used to calculate + * statistics about download speed on the controller side. + * The \a stagingFile argument can be used for cases where the worker uses a staging area to download files into but later moves + * the file over to the result filename. In those cases the provider will check both locations for the file when calculating stats + * + * \note Always call \ref ref before sending this message. + */ + void provideStart ( const uint32_t id, const zypp::Url &url, const zypp::Pathname &localFile, const zypp::Pathname &stagingFile = {} ); + + /*! + * Send a \a ProvideSuccess message to the controller. This is to signal that we are finished with providing a file + * and release the file to be used by the controller side. + */ + void provideSuccess (const uint32_t id, bool cacheHit, const zypp::Pathname &localFile, const HeaderValueMap extra = {} ); + + /*! + * Send a \a ProvideFailed message to the controller. This is to signal that we are failed providing a resource + * + * \note If the request referenced a \a ident before make sure to manually release it after sending the message. + */ + void provideFailed (const uint32_t id, const ProvideMessage::Code code, const std::string &reason, const bool transient, const HeaderValueMap extra = {} ); + + /*! + * Overload of provideFailed that takes a \ref zypp::Exception to fill in the error details + * + * \note If the request referenced a \a ident before make sure to manually release it after sending the message. + */ + void provideFailed (const uint32_t id, const ProvideMessage::Code code, const bool transient, const zypp::Exception &e ); + + /*! + * Send a \a AttachSuccess message to the controller. This is to signal that we are finished with mounting and verifying a medium + */ + void attachSuccess ( const uint32_t id, const std::optional &localMountPoint = {} ); + + /*! + * Send a \a DetachSuccess message to the controller. This is to signal that we are finished unmounting a medium + */ + void detachSuccess ( const uint32_t id ); + + /*! + * Send a \a Redirect message to the controller for the given request ID. This is similar to sending a \a ProvideSuccess message + * and the request will be removed from the queue, which means the worker also has to remove it from its internal queue. + */ + void redirect ( const uint32_t id, const zypp::Url &url, const zypp::Pathname &newPath ); + + /*! + * Returns the control IO datasource, only valid after \ref run was called + */ + AsyncDataSource &controlIO (); + + + private: + expected executeHandshake (); + void maybeDelayedShutdown (); + void messageLoop ( Timer & ); + void readFdClosed ( uint, AsyncDataSource::ChannelCloseReason ); + void writeFdClosed ( AsyncDataSource::ChannelCloseReason ); + void messageReceived (); + void onInvalidMessageReceived ( ); + void invalidMessageReceived ( std::exception_ptr p ); + void handleSingleMessage (const ProvideMessage &provide ); + void pushSingleMessage (const zypp::PluginFrame &msg ); + expected sendAndWaitForResponse ( const ProvideMessage &request, const std::vector &responseCodes ); + expected parseReceivedMessage(const zypp::PluginFrame &m ); + + private: + ProvideNotificatioMode _provNotificationMode = QUEUE_NOT_EMTPY; + bool _inControllerRequest = false; //< Used to signalize that we are currently in a blocking controller callback + bool _isRunning = false; + std::string_view _workerName; + EventLoop::Ptr _loop = EventLoop::create(); + Timer::Ptr _msgAvail = Timer::create(); + Timer::Ptr _delayedShutdown = Timer::create(); + AsyncDataSource::Ptr _controlIO; + StompFrameStreamRef _stream; + ProviderConfiguration _workerConf; + + std::exception_ptr _fatalError; //< Error that caused the eventloop to stop + + std::deque _pendingMessages; + std::deque _pendingProvides; + }; +} + + +#endif diff --git a/zypp-tui/Application b/zypp-tui/Application new file mode 100644 index 0000000..fa42be4 --- /dev/null +++ b/zypp-tui/Application @@ -0,0 +1 @@ +#include "application.h" diff --git a/zypp-tui/CMakeLists.txt b/zypp-tui/CMakeLists.txt new file mode 100644 index 0000000..4ded622 --- /dev/null +++ b/zypp-tui/CMakeLists.txt @@ -0,0 +1,90 @@ +# Collect all files that may contain translatable texts +FILE( GLOB_RECURSE POT_FILE_DEPENDS RELATIVE ${LIBZYPP_SOURCE_DIR} "*.h" "*.cc" ) +SET( POT_FILE_DEPENDS_ZYPP_TUI ${POT_FILE_DEPENDS} PARENT_SCOPE ) + +INCLUDE_DIRECTORIES ( ${LIBZYPP_SOURCE_DIR} ) + +ADD_DEFINITIONS( -DLOCALEDIR="${CMAKE_INSTALL_PREFIX}/share/locale" -DTEXTDOMAIN="zypp" -DZYPP_DLL ) + +FIND_PACKAGE( Readline REQUIRED ) + +SET( zypp_tui_toplevel_headers + Application + application.h + Config + config.h + Table.h +) +INSTALL( FILES ${zypp_tui_toplevel_headers} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-tui" ) + +SET( zypp_tui_output_headers + output/AliveCursor.h + output/Out.h + output/OutNormal.h + output/PromptOptions + output/promptoptions.h + output/Utf8.h +) +INSTALL( FILES ${zypp_tui_output_headers} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-tui/output" ) + +SET( zypp_tui_utils_headers + utils/ansi.h + utils/colors.h + utils/console.h + utils/richtext.h + utils/text.h +) +INSTALL( FILES ${zypp_tui_utils_headers} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp-tui/utils" ) + + +SET( zypp_tui_headers + ${zypp_tui_toplevel_headers} + ${zypp_tui_output_headers} + ${zypp_tui_utils_headers} +) + +SET( zypp_tui_SRCS + application.cc + config.cc + Table.cc + output/Out.cc + output/OutNormal.cc + output/promptoptions.cc + utils/colors.cc + utils/console.cc + utils/richtext.cc + utils/text.cc +) + +SET ( zypp_HEADERS + ${zypp_tui_headers} +) + +SET ( zypp_SRCS + ${zypp_tui_SRCS} +) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +ADD_LIBRARY( zypp-tui STATIC ${zypp_SRCS} ${zypp_HEADERS} ) +add_dependencies( zypp-tui zypp-core ) + +set_target_properties( zypp-tui PROPERTIES COMPILE_FLAGS "-ffat-lto-objects") + +target_link_libraries( zypp-tui PRIVATE zypp_lib_compiler_flags ) +target_link_libraries( zypp-tui INTERFACE ${READLINE_LIBRARY}) +target_include_directories( zypp-tui PUBLIC ${READLINE_INCLUDE_DIR}) +# target_compile_options( zypp-tui PUBLIC ${READLINE_CFLAGS_OTHER}) + +INSTALL(TARGETS zypp-tui ARCHIVE DESTINATION ${LIB_INSTALL_DIR} ) + +# utils/text.* utils/console.* utils/colors.* utils/ansi.h output/Utf8.h output/AliveCursor.h utils/richtext.* output/Out.* output/OutNormal.* Table.* +# -> move config for colors to zypp-tui diff --git a/zypp-tui/Config b/zypp-tui/Config new file mode 100644 index 0000000..1ac2545 --- /dev/null +++ b/zypp-tui/Config @@ -0,0 +1 @@ +#include "config.h" diff --git a/zypp-tui/Table.cc b/zypp-tui/Table.cc new file mode 100644 index 0000000..9ac16df --- /dev/null +++ b/zypp-tui/Table.cc @@ -0,0 +1,468 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "Table.h" + +// libzypp logger settings +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypper" + +namespace ztui { + +const char * asYesNo( bool val_r ) { return val_r ? _("Yes") : _("No"); } + +TableLineStyle Table::defaultStyle = Ascii; + +static const char * lines[][3] = { + { "|", "-", "+"}, ///< Ascii + // utf 8 + { "\xE2\x94\x82", "\xE2\x94\x80", "\xE2\x94\xBC" }, ///< light + { "\xE2\x94\x83", "\xE2\x94\x81", "\xE2\x95\x8B" }, ///< heavy + { "\xE2\x95\x91", "\xE2\x95\x90", "\xE2\x95\xAC" }, ///< double + { "\xE2\x94\x86", "\xE2\x94\x84", "\xE2\x94\xBC" }, ///< light 3 + { "\xE2\x94\x87", "\xE2\x94\x85", "\xE2\x94\x8B" }, ///< heavy 3 + { "\xE2\x94\x82", "\xE2\x94\x81", "\xE2\x94\xBF" }, ///< v light, h heavy + { "\xE2\x94\x82", "\xE2\x95\x90", "\xE2\x95\xAA" }, ///< v light, h double + { "\xE2\x94\x83", "\xE2\x94\x80", "\xE2\x95\x82" }, ///< v heavy, h light + { "\xE2\x95\x91", "\xE2\x94\x80", "\xE2\x95\xAB" }, ///< v double, h light + { ":", "-", "+" }, ///< colon separated values +}; + + +namespace { + /// Compare wchar_t case sensitive. + inline int wccmp( const wchar_t & l, const wchar_t & r ) + { return l == r ? 0 : l < r ? -1 : 1; } + + /// Compare wchar_t case insensitive. + inline int wccasecmp( const wchar_t & l, const wchar_t & r ) + { return ::wcsncasecmp( &l, &r, 1 ); } + + /// Whether wchar_t is a Zero digit. + inline bool isZero( const wchar_t & ch ) + { return ch == L'0'; } + + /// Whether wchar_t is a digit. + inline bool isDigit( const wchar_t & ch ) + { return ::iswdigit( ch ); } + + /// Whether both wchar_t are digits. + inline bool bothDigits( const wchar_t & l, const wchar_t & r ) + { return isDigit( l ) && isDigit( r ); } + + /// Whether both wchar_t are no digits. + inline bool bothNotDigits( const wchar_t & l, const wchar_t & r ) + { return not ( isDigit( l ) || isDigit( r ) ); } + + /// Whether both are at the end of the string. + inline bool bothAtEnd( const mbs::MbsIteratorNoSGR & lit, const mbs::MbsIteratorNoSGR & rit ) + { return lit.atEnd() && rit.atEnd(); } + + /// Whether there are one or more trailing Zeros. + inline bool skipTrailingZeros( mbs::MbsIteratorNoSGR & it ) + { + if ( isZero( *it ) ) { + do { ++it; } while ( isZero( *it ) ); + return it.atEnd(); + } + return false; + } + + /// compare like numbers: longer digit sequence wins, otherwise first difference + inline int wcnumcmpValue( mbs::MbsIteratorNoSGR & lit, mbs::MbsIteratorNoSGR & rit ) + { + // PRE: no leading Zeros + // POST: if 0(equal) is returned, all digis were skipped + int diff = 0; + for ( ;; ++lit, ++rit ) { + if ( isDigit( *lit ) ) { + if ( isDigit( *rit ) ) { + if ( not diff && *lit != *rit ) + diff = *lit < *rit ? -1 : 1; + } + else + return 1; // DIG !DIG + } + else { + if ( isDigit( *rit ) ) + return -1; // !DIG DIG + else + return diff; // !DIG !DIG + } + } + } +} // namespace + +int TableRow::Less::defaultStrComp( bool ci_r, const std::string & lhs, const std::string & rhs ) +{ + auto wcharcmp = &wccmp; // always start with case sensitive compare + int nbias = 0; // remember the 1st difference (in case num compare equal) + int cbias = 0; // remember the 1st difference (in case ci compare equal) + int cmp = 0; + mbs::MbsIteratorNoSGR lit { lhs }; + mbs::MbsIteratorNoSGR rit { rhs }; + while ( true ) { + + // Endgame: tricky: trailing Zeros are ignored, but count as nbias if there is none. + if ( lit.atEnd() ) { + if ( skipTrailingZeros( rit ) && not nbias ) return -1; + return rit.atEnd() ? (nbias ? nbias : cbias) : -1; + } + if ( rit.atEnd() ) { + if ( skipTrailingZeros( lit ) && not nbias ) return 1; + return lit.atEnd() ? (nbias ? nbias : cbias) : 1; + } + + // num <> num? + if ( bothDigits( *lit, *rit ) ) { + if ( isZero( *lit ) || isZero( *rit ) ) { + int lead = 0; // the more leasing zeros a number has, the less: 001 01 1 + while ( isZero( *lit ) ) { ++lit; --lead; } + while ( isZero( *rit ) ) { ++rit; ++lead; } + if ( not nbias && lead ) + nbias = bothAtEnd( lit, rit ) ? -lead : lead; // the less trailing zeros, the less: a a0 a00 + } + if ( (cmp = wcnumcmpValue( lit, rit )) ) + return cmp; + continue; // already skipped all digits + } + else { + if ( (cmp = wcharcmp( *lit, *rit )) ) { + if ( not cbias ) cbias = cmp; // remember the 1st difference (by wccmp) + if ( ci_r ) { + if ( (cmp = wccasecmp( *lit, *rit )) ) + return cmp; + wcharcmp = &wccasecmp; + ci_r = false; + } + else + return cmp; + } + } + ++lit; ++rit; + } +} + +TableRow & TableRow::add( std::string s ) +{ + if ( _translateColumns ) + _translatedColumns.push_back( _(s.c_str()) ); + _columns.push_back( std::move(s) ); + return *this; +} + +TableRow & TableRow::addDetail( std::string s ) +{ + _details.push_back( std::move(s) ); + return *this; +} + +// 1st implementation: no width calculation, just tabs +std::ostream & TableRow::dumbDumpTo( std::ostream & stream ) const +{ + bool seen_first = false; + for ( container::const_iterator i = _columns.begin(); i != _columns.end(); ++i ) + { + if ( seen_first ) + stream << '\t'; + seen_first = true; + + stream << *i; + } + return stream << std::endl; +} + +std::ostream & TableRow::dumpDetails( std::ostream & stream, const Table & parent ) const +{ + mbs::MbsWriteWrapped mww( stream, 4, parent._screen_width ); + for ( const std::string & text : _details ) + { + mww.writePar( text ); + } + mww.gotoParBegin(); + return stream; +} + +std::ostream & TableRow::dumpTo( std::ostream & stream, const Table & parent ) const +{ + const char * vline = parent._style == none ? "" : lines[parent._style][0]; + + unsigned ssize = 0; // string size in columns + bool seen_first = false; + + stream.setf( std::ios::left, std::ios::adjustfield ); + stream << std::string( parent._margin, ' ' ); + // current position at currently printed line + int curpos = parent._margin; + // On a table with 2 edition columns highlight the editions + // except for the common prefix. + std::string::size_type editionSep( std::string::npos ); + + container::const_iterator i = _columns.begin (), e = _columns.end (); + const unsigned lastCol = _columns.size() - 1; + for ( unsigned c = 0; i != e ; ++i, ++c ) + { + const std::string & s( *i ); + + if ( seen_first ) + { + bool do_wrap = parent._do_wrap // user requested wrapping + && parent._width > parent._screen_width // table is wider than screen + && ( curpos + (int)parent._max_width[c] + (parent._style == none ? 2 : 3) > parent._screen_width // the next table column would exceed the screen size + || parent._force_break_after == (int)(c - 1) ); // or the user wishes to first break after the previous column + + if ( do_wrap ) + { + // start printing the next table columns to new line, + // indent by 2 console columns + stream << std::endl << std::string( parent._margin + 2, ' ' ); + curpos = parent._margin + 2; // indent == 2 + } + else + // vertical line, padded with spaces + stream << ' ' << vline << ' '; + stream.width( 0 ); + } + else + seen_first = true; + + // stream.width (widths[c]); // that does not work with multibyte chars + ssize = mbs_width( s ); + if ( ssize > parent._max_width[c] ) + { + unsigned cutby = parent._max_width[c] - 2; + std::string cutstr = mbs_substr_by_width( s, 0, cutby ); + stream << ( _ctxt << cutstr ) << std::string(cutby - mbs_width( cutstr ), ' ') << "->"; + } + else + { + if ( !parent._inHeader && parent.header().hasStyle( c, table::CStyle::Edition ) && Application::instance().config().do_colors ) + { + const std::set & editionColumns { parent.header().editionColumns() }; + // Edition column + if ( editionColumns.size() == 2 ) + { + // 2 Edition columns - highlight difference + if ( editionSep == std::string::npos ) + { + editionSep = zypp::str::commonPrefix( _columns[*editionColumns.begin()], + _columns[*(++editionColumns.begin())] ); + } + + if ( editionSep == 0 ) + { + stream << ( ColorContext::CHANGE << s ); + } + else if ( editionSep == s.size() ) + { + stream << ( _ctxt << s ); + } + else + { + stream << ( _ctxt << s.substr( 0, editionSep ) ) << ( ColorContext::CHANGE << s.substr( editionSep ) ); + } + } + else + { + // highlight edition-release separator + editionSep = s.find( '-' ); + if ( editionSep != std::string::npos ) + { + stream << ( _ctxt << s.substr( 0, editionSep ) << ( ColorContext::HIGHLIGHT << "-" ) << s.substr( editionSep+1 ) ); + } + else // no release part + { + stream << ( _ctxt << s ); + } + } + } + else // no special style + { + stream << ( _ctxt << s ); + } + stream.width( c == lastCol ? 0 : parent._max_width[c] - ssize ); + } + stream << ""; + curpos += parent._max_width[c] + (parent._style == none ? 2 : 3); + } + stream << std::endl; + + if ( !_details.empty() ) + { + dumpDetails( stream, parent ); + } + return stream; +} + +// ----------------------( Table )--------------------------------------------- + +Table::Table() + : _has_header( false ) + , _max_col( 0 ) + , _max_width( 1, 0 ) + , _width( 0 ) + , _style( defaultStyle ) + , _screen_width( get_screen_width() ) + , _margin( 0 ) + , _force_break_after( -1 ) + , _do_wrap( false ) + , _inHeader( false ) +{} + +Table & Table::add( TableRow tr ) +{ + _rows.push_back( std::move(tr) ); + return *this; +} + +Table & Table::setHeader( TableHeader tr ) +{ + _header = std::move(tr); + _has_header = !_header.empty(); + return *this; +} + +void Table::allowAbbrev( unsigned column) +{ + if ( column >= _abbrev_col.size() ) + { + _abbrev_col.reserve( column + 1 ); + _abbrev_col.insert( _abbrev_col.end(), column - _abbrev_col.size() + 1, false ); + } + _abbrev_col[column] = true; +} + +void Table::updateColWidths( const TableRow & tr ) const +{ + // how much columns spearators add to the width of the table + int sepwidth = _style == none ? 2 : 3; + // initialize the width to -sepwidth (the first column does not have a line + // on the left) + _width = -sepwidth; + + // ensure that _max_width[col] exists + const auto &columns = tr.columns(); + if ( _max_width.size() < columns.size() ) + { + _max_width.resize( columns.size(), 0 ); + _max_col = _max_width.size()-1; + } + + unsigned c = 0; + for ( const auto & col : columns ) + { + unsigned &max = _max_width[c++]; + unsigned cur = mbs_width( col ); + + if ( max < cur ) + max = cur; + + _width += max + sepwidth; + } + _width += _margin * 2; +} + +void Table::dumpRule( std::ostream &stream ) const +{ + const char * hline = _style != none ? lines[_style][1] : " "; + const char * cross = _style != none ? lines[_style][2] : " "; + + bool seen_first = false; + + stream.width( 0 ); + stream << std::string(_margin, ' ' ); + for ( unsigned c = 0; c <= _max_col; ++c ) + { + if ( seen_first ) + stream << hline << cross << hline; + seen_first = true; + // FIXME: could use fill character if hline were a (wide) character + for ( unsigned i = 0; i < _max_width[c]; ++i ) + stream << hline; + } + stream << std::endl; +} + +std::ostream & Table::dumpTo( std::ostream & stream ) const +{ + // compute column sizes + if ( _has_header ) + updateColWidths( _header ); + for ( const auto & row : _rows ) + updateColWidths( row ); + + // reset column widths for columns that can be abbreviated + //! \todo allow abbrev of multiple columns? + unsigned c = 0; + for ( std::vector::const_iterator it = _abbrev_col.begin(); it != _abbrev_col.end() && c <= _max_col; ++it, ++c ) + { + if ( *it && _width > _screen_width && + // don't resize the column to less than 3, or if the resulting table + // would still exceed the screen width (bnc #534795) + _max_width[c] > 3 && + _width - _screen_width < ((int) _max_width[c]) - 3 ) + { + _max_width[c] -= _width - _screen_width; + break; + } + } + + if ( _has_header ) + { + zypp::DtorReset inHeader( _inHeader, false ); + _inHeader = true; + _header.dumpTo( stream, *this ); + dumpRule (stream); + } + + for ( const auto & row : _rows ) + row.dumpTo( stream, *this ); + + return stream; +} + +void Table::wrap( int force_break_after ) +{ + if ( force_break_after >= 0 ) + _force_break_after = force_break_after; + _do_wrap = true; +} + +void Table::lineStyle( TableLineStyle st ) +{ + if ( st < TLS_End ) + _style = st; +} + +void Table::margin( unsigned margin ) +{ + if ( margin < (unsigned)(_screen_width/2) ) + _margin = margin; + else + ERR << "margin of " << margin << " is greater than half of the screen" << std::endl; +} + +// Local Variables: +// c-basic-offset: 2 +// End: +} diff --git a/zypp-tui/Table.h b/zypp-tui/Table.h new file mode 100644 index 0000000..3ebd740 --- /dev/null +++ b/zypp-tui/Table.h @@ -0,0 +1,645 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_TABULE_H +#define ZYPP_TUI_TABULE_H + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include +#include + +namespace ztui { + +const char * asYesNo( bool val_r ); ///> _("Yes") or _("No") + +/** Custom sort index type for table rows representing solvables (like detailed search results). */ +using SolvableCSI = std::pair; + +/////////////////////////////////////////////////////////////////// +// Custom sort index helpers +namespace csidetail +{ + /** Default comparator for custom sort indices (std::compare semantic). */ + template + inline int simpleAnyTypeComp ( const boost::any &l_r, const boost::any &r_r ) + { + T l = boost::any_cast(l_r); + T r = boost::any_cast(r_r); + return ( l < r ? -1 : l > r ? 1 : 0 ); + } + + template <> + inline int simpleAnyTypeComp ( const boost::any &l_r, const boost::any &r_r ) + { + SolvableCSI l = boost::any_cast(l_r); + SolvableCSI r = boost::any_cast(r_r); + + if ( l.first == r.first ) + return 0; // quick check Solvable Id + + int cmp = l.first.name().compare( r.first.name() ); + if ( cmp ) + return cmp; + + cmp = l.first.kind().compare( r.first.kind() ); + if ( cmp ) + return cmp; + + if ( l.second == r.second ) + return 0; + return ( l.second < r.second ? -1 : 1 ); // `>`! best version up + } +} // namespace csidetail +/////////////////////////////////////////////////////////////////// + +//! table drawing style +enum TableLineStyle { + Ascii = 0, ///< | - + + Light, + Heavy, + Double, + Light3, + Heavy3, + LightHeavy, + LightDouble, + HeavyLight, + DoubleLight, + Colon, + none, + TLS_End, ///< sentinel +}; + +class Table; + +/////////////////////////////////////////////////////////////////// +// Conditional Table column helpers. +namespace ctcdetail +{ + /// Remember either \a _if or \a _else function. + template + struct ColumnIf + { + ColumnIf( bool condition_r, std::function if_r, std::function else_r ) + { if ( condition_r ) _if = std::move(if_r); else _else = std::move(else_r); } + std::function _if; + std::function _else; + }; + /// Specialization both functions return the same type + template + struct ColumnIf + { + ColumnIf( bool condition_r, std::function if_r, std::function else_r ) + : _ifelse { condition_r ? std::move(if_r) : std::move(else_r) } + {} + ColumnIf( bool condition_r, std::function && if_r ) + { if ( condition_r ) _ifelse = std::move(if_r); } + std::function _ifelse; + }; +} +/////////////////////////////////////////////////////////////////// +/// Conditional Table column factory. +/// +/// Creates an conditional \ref TableRow or \ref TableHeader entry, +/// depending on the value of \a condition_r. The columns content, +/// if needed, is determined calling the function object matching the +/// condition. +/// +/// An empty function object will cause the column to be hidden and no +/// content will be retrieved (see overloaded operator<<(TableRow &,..)). +/// +/// \code +/// TableRow() +/// << "first" +/// << ColumnIf( condition, [](){ return "second"; }, [](){ return "one but last"; } ) +/// << "last"; +/// \endcode +template +auto ColumnIf( bool condition_r, Tif_ && if_r, Telse_ && else_r ) -> ctcdetail::ColumnIf +{ return { condition_r, std::forward(if_r), std::forward(else_r) }; } +/** \overload no column on 'else' */ +template +auto ColumnIf( bool condition_r, Tif_ && if_r ) -> ctcdetail::ColumnIf +{ return { condition_r, std::forward(if_r) }; } + + +namespace table +{ + /// Table column styles + /// + /// \see \ref Column style setter below. + /// \code + /// th << table::Column( N_("Name"), CStyle::SortCi ); + /// \endcode + enum class CStyle + { + Default = 0, + Edition, ///< Editions with v-r setparator highlighted + SortCi, ///< String values to be sorted case insensitive + }; +} + + +class TableRow +{ +private: + std::ostream & dumpDetails( std::ostream & stream, const Table & parent ) const; + +public: + struct Less; ///< Binary predicate for sorting. + + TableRow() + : _ctxt( ColorContext::DEFAULT ) + {} + + explicit TableRow( unsigned c ) + : _ctxt( ColorContext::DEFAULT ) + { _columns.reserve(c); } + + explicit TableRow( ColorContext ctxt_r ) + : _ctxt( ctxt_r ) + {} + + TableRow( unsigned c, ColorContext ctxt_r ) + : _ctxt( ctxt_r ) + { _columns.reserve(c); } + + TableRow & add( std::string s ); + + template + TableRow & add( const Tp_ & val_r ) + { return add( zypp::str::asString( val_r ) ); } + + + TableRow & addDetail( std::string s ); + + template + TableRow & addDetail( const Tp_ & val_r ) + { return addDetail( zypp::str::asString( val_r ) ); } + + + bool empty() const + { return _columns.empty(); } + + // return number of columns + unsigned size() const + { return _columns.size(); } + + unsigned cols() const + { return size(); } + + //! tab separated output + std::ostream & dumbDumpTo( std::ostream & stream ) const; + //! output with \a parent table attributes + std::ostream & dumpTo( std::ostream & stream, const Table & parent ) const; + + using container = std::vector; + + const boost::any &userData() const + { return _userData; } + + void userData( const boost::any &n_r ) + { _userData = n_r; } + + // BinaryPredicate + + const container & columns() const + { return _translateColumns ? _translatedColumns : _columns; } + + container & columns() + { return _translateColumns ? _translatedColumns : _columns; } + + const container & columnsNoTr() const + { return _columns; } + + container & columnsNoTr() + { return _columns; } + +protected: + bool _translateColumns = false; +private: + container _columns; + container _translatedColumns; + container _details; + ColorContext _ctxt; + boost::any _userData; ///< user defined sort index, e.g. if string values don't work due to coloring +}; + +/** \relates TableRow Add colummn. */ +template +TableRow & operator<<( TableRow & tr, Tp_ && val ) +{ return tr.add( zypp::asString( std::forward(val) ) ); } +/** \overload preserving TableRow rvalue reference. */ +template +TableRow && operator<<( TableRow && tr, Tp_ && val ) +{ return std::move( tr << std::forward(val) ); } + +/** \overload universal refernce for conditional Table columns */ +template TableRow & operator<<( TableRow & tr, const ctcdetail::ColumnIf & val ) +{ if ( val._if ) tr.add( val._if() ); else if ( val._else ) tr.add( val._else() ); return tr; } +/** \overload universal refernce for conditional Table columns */ +template TableRow & operator<<( TableRow & tr, ctcdetail::ColumnIf & val ) +{ if ( val._if ) tr.add( val._if() ); else if ( val._else ) tr.add( val._else() ); return tr; } +/** \overload universal refernce for conditional Table columns */ +template TableRow & operator<<( TableRow & tr, ctcdetail::ColumnIf && val ) +{ if ( val._if ) tr.add( val._if() ); else if ( val._else ) tr.add( val._else() ); return tr; } + +/** \overload universal refernce for conditional Table columns (specialized) */ +template TableRow & operator<<( TableRow & tr, const ctcdetail::ColumnIf & val ) +{ if ( val._ifelse ) tr.add( val._ifelse() ); return tr; } +/** \overload universal refernce for conditional Table columns (specialized) */ +template TableRow & operator<<( TableRow & tr, ctcdetail::ColumnIf & val ) +{ if ( val._ifelse ) tr.add( val._ifelse() ); return tr; } +/** \overload universal refernce for conditional Table columns (specialized) */ +template TableRow & operator<<( TableRow & tr, ctcdetail::ColumnIf && val ) +{ if ( val._ifelse ) tr.add( val._ifelse() ); return tr; } + + +class TableHeader : public TableRow +{ +public: + using CStyle = table::CStyle; + //! Constructor. Reserve place for c columns. + TableHeader (unsigned c = 0): TableRow (c) { _translateColumns = true; } + + bool hasStyle( unsigned c, CStyle s ) const + { return _cstyle.count(c) && _cstyle.at(c) == s; } + + CStyle style( unsigned c ) const + { return _cstyle.count(c) ? _cstyle.at(c) : CStyle::Default; } + + void style( unsigned c, CStyle s ) + { _cstyle[c] = s; } + + + std::set editionColumns() const + { + std::set ret; + for ( const auto & [c,s] : _cstyle ) { + if ( s == CStyle::Edition ) + ret.insert( c ); + } + return ret; + } + +private: + std::map _cstyle; ///< Column style and sort hints are remembered here +}; + +/** \relates TableHeader Add column. */ +template +TableHeader & operator<<( TableHeader & th, Tp_ && val ) +{ static_cast(th) << std::forward(val); return th; } +/** \overload preserving TableHeader rvalue reference. */ +template +TableHeader && operator<<( TableHeader && th, Tp_ && val ) +{ return std::move( th << std::forward(val) ); } + + +struct TableRow::Less +{ + using SortParam = std::tuple; ///< column and sortCI + + Less( const TableHeader & header_r, const std::list& by_columns_r ) + { + for ( unsigned curr_column : by_columns_r ) { + _by_columns.push_back( SortParam( curr_column, header_r.hasStyle( curr_column, table::CStyle::SortCi ) ) ); + } + } + + bool operator()( const TableRow & a_r, const TableRow & b_r ) const + { + int c = 0; + for ( const SortParam &sortParam : _by_columns ) { + if ( (c = compCol( sortParam, a_r, b_r )) ) + return c < 0; + } + return false; + } + +private: + int compCol( const SortParam & sortParam_r, const TableRow & a_r, const TableRow & b_r ) const + { + const auto & [ byColumn, sortCI ] { sortParam_r }; + bool noL = byColumn >= a_r._columns.size(); + bool noR = byColumn >= b_r._columns.size(); + + if ( noL || noR ) { + if ( noL && noR ) { + using csidetail::simpleAnyTypeComp; + + const boost::any &lUserData = a_r.userData(); + const boost::any &rUserData = b_r.userData(); + + if ( lUserData.empty() && !rUserData.empty() ) + return -1; + + else if ( !lUserData.empty() && rUserData.empty() ) + return 1; + + else if ( lUserData.empty() && rUserData.empty() ) + return 0; + + else if ( lUserData.type() != rUserData.type() ) { + ZYPP_THROW( zypp::Exception( zypp::str::form("Incompatible user types") ) ); + + } else if ( lUserData.type() == typeid(SolvableCSI) ) { + return simpleAnyTypeComp ( lUserData, rUserData ); + + } else if ( lUserData.type() == typeid(std::string) ) { + return simpleAnyTypeComp( lUserData, rUserData ); + + } else if ( lUserData.type() == typeid(unsigned) ) { + return simpleAnyTypeComp( lUserData, rUserData ); + + } else if ( lUserData.type() == typeid(int) ) { + return simpleAnyTypeComp( lUserData, rUserData ); + + } + ZYPP_THROW( zypp::Exception( zypp::str::form("Unsupported user types") ) ); + } else + return ( noL && ! noR ? -1 : ! noL && noR ? 1 : 0); + } + return defaultStrComp( sortCI, a_r._columns[byColumn], b_r._columns[byColumn] ); + } + + /** Natural('sort -V' like) [case insensitive] compare ignoring ANSI SGR chars. */ + static int defaultStrComp( bool ci_r, const std::string & lhs, const std::string & rhs ); + +private: + std::list _by_columns; +}; + +/** \todo nice idea but poor interface */ +class Table +{ +public: + using container = std::list; + + static TableLineStyle defaultStyle; + + Table & add( TableRow tr ); + + Table & setHeader( TableHeader tr ); + + + std::ostream & dumpTo( std::ostream & stream ) const; + bool empty() const { return _rows.empty(); } + + + /** Unsorted - pseudo sort column indicating not to sort. */ + static constexpr unsigned Unsorted = unsigned(-1); + /** UserData - sort column using a custom sort index. */ + static constexpr unsigned UserData = unsigned(-2); + + /** Get the default sort column or \ref Unsorted (default) */ + unsigned defaultSortColumn() const { return _defaultSortColumn; } + + /** Set a \ref defaultSortColumn */ + void defaultSortColumn( unsigned byColumn_r ) { _defaultSortColumn = byColumn_r; } + + /** Sort by \ref defaultSortColumn */ + void sort() { sort( unsigned(_defaultSortColumn ) ); } + + /** Sort by \a byColumn_r */ + void sort( unsigned byColumn_r ) { if ( byColumn_r != Unsorted ) _rows.sort( TableRow::Less( header(), { byColumn_r } ) ); } + void sort( const std::list & byColumns_r ) { if ( byColumns_r.size() ) _rows.sort( TableRow::Less( header(), byColumns_r ) ); } + void sort( std::list && byColumns_r ) { if ( byColumns_r.size() ) _rows.sort( TableRow::Less( header(), std::move(byColumns_r) ) ); } + + /** Custom sort */ + template, int> = 0> + void sort( TCompare && less_r ) { _rows.sort( std::forward(less_r) ); } + + void lineStyle( TableLineStyle st ); + void wrap( int force_break_after = -1 ); + void allowAbbrev( unsigned column ); + void margin( unsigned margin ); + + const TableHeader & header() const + { return _header; } + const container & rows() const + { return _rows; } + container & rows() + { return _rows; } + + Table(); + +private: + void dumpRule( std::ostream & stream ) const; + void updateColWidths( const TableRow & tr ) const; + + bool _has_header; + TableHeader _header; + container _rows; + + //! maximum column index seen in this table + mutable unsigned _max_col; + //! maximum width of respective columns + mutable std::vector _max_width; + //! table width (columns) + mutable int _width; + //! table line drawing style + TableLineStyle _style; + //! amount of space we have to print this table + int _screen_width; + //! whether to abbreviate the respective column if needed + std::vector _abbrev_col; + //! left/right margin in number of spaces + unsigned _margin; + //! if _do_wrap is set, first break the table at this column; + //! If negative, wrap as needed. + int _force_break_after; + //! Whether to wrap the table if it exceeds _screen_width + bool _do_wrap; + + zypp::DefaultIntegral _defaultSortColumn; + + mutable bool _inHeader; + + friend class TableRow; +}; + +namespace table +{ + /// Table column style setter. + /// + /// \see \ref CStyle colum styles. + /// \code + /// th << table::Column( N_("Name"), CStyle::SortCi ); + /// \endcode + struct Column + { + Column( std::string header_r, CStyle style_r = CStyle::Default ) + : _header( std::move(header_r) ) + , _style( style_r ) + {} + std::string _header; + CStyle _style; + }; + /** \relates table::Column set \ref TableHeader style. */ + inline TableHeader & operator<<( TableHeader & th, Column && obj ) + { th.style( th.cols(), obj._style ); return th << std::move(obj._header); } + /** \relates table::Column set \ref TableHeader style.*/ + inline TableHeader && operator<<( TableHeader && th, Column && obj ) + { return std::move( th << std::move(obj) ); } +} + + +inline Table & operator<<( Table & table, TableRow tr ) +{ return table.add( std::move(tr) ); } + +inline Table & operator<<( Table & table, TableHeader tr ) +{ return table.setHeader( std::move(tr) ); } + + +inline std::ostream & operator<<( std::ostream & stream, const Table & table ) +{ return table.dumpTo( stream ); } + + +/////////////////////////////////////////////////////////////////// +/// \class PropertyTable +/// \brief Aligned key/value with multiline support +/// Key : value 1 +/// LongKey : value 2 +/// Multiline : +/// line 1 +/// line 2 +/// Next Key : value 3 +/// +/////////////////////////////////////////////////////////////////// +class PropertyTable +{ +public: + PropertyTable() + { _table.lineStyle( ztui::Colon ); } + + static const char * emptyListTag() { return "---"; } + +public: + /////////////////////////////////////////////////////////////////// + // Key / Value + template + PropertyTable & add( const KeyType & key_r ) + { _table << ( TableRow() << key_r << "" ); return *this; } + + template + PropertyTable & add( const KeyType & key_r, const ValueType & val_r ) + { _table << ( TableRow() << key_r << val_r ); return *this; } + + template + PropertyTable & add( const KeyType & key_r, bool val_r ) + { _table << ( TableRow() << key_r << asYesNo( val_r ) ); return *this; } + + /////////////////////////////////////////////////////////////////// + // Key / Value in details (e.g. Description:) + template + PropertyTable & addDetail( const ValueType & val_r ) + { last().addDetail( val_r ); return *this; } + + template + PropertyTable & addDetail( const KeyType & key_r, const ValueType & val_r ) + { _table << ( TableRow() << key_r << "" ).addDetail( val_r ); return *this; } + + /////////////////////////////////////////////////////////////////// + // Key / Container + template + PropertyTable & add( const KeyType & key_r, Iterator_ begin_r, Iterator_ end_r, bool forceDetails_r = false ) + { + TableRow r; + r << key_r; + if ( begin_r != end_r ) + { + unsigned cnt = 1; + Iterator_ first = begin_r++; + if ( begin_r == end_r && ! forceDetails_r ) + r << *first; // only one value + else + { + r.addDetail( *first ); // list all in details + while ( begin_r != end_r ) + { + ++cnt; + r.addDetail( *(begin_r++) ); + } + r << "["+zypp::str::numstring(cnt)+"]"; // size as value + } + } + else + { r << emptyListTag(); } // dummy to get the ":" if empty + _table << r; + return *this; + } + + template + PropertyTable & lst( const KeyType & key_r, const ContainerType & lst_r, bool forceDetails_r = false ) + { return add( key_r, lst_r.begin(), lst_r.end(), forceDetails_r ); } + + template + PropertyTable & add( const KeyType & key_r, const std::set & lst_r, bool forceDetails_r = false ) + { return lst( key_r, lst_r, forceDetails_r ); } + template + PropertyTable & add( const KeyType & key_r, const std::list & lst_r, bool forceDetails_r = false ) + { return lst( key_r, lst_r, forceDetails_r ); } + template + PropertyTable & add( const KeyType & key_r, const std::vector & lst_r, bool forceDetails_r = false ) + { return lst( key_r, lst_r, forceDetails_r ); } + + /////////////////////////////////////////////////////////////////// + // misc + PropertyTable & paint( ansi::Color color_r, bool cond_r = true ) + { + if ( cond_r ) + { + // FIXME re-coloring like this works only once + std::string & lastval( _table.rows().back().columns().back() ); + lastval = ColorString( lastval, color_r ).str(); + } + return *this; + } + + TableRow & last() + { return _table.rows().back(); } + + std::string & lastKey() + { return last().columns()[0]; } + + std::string & lastValue() + { return last().columns()[1]; } + +public: + friend std::ostream & operator << ( std::ostream & str, const PropertyTable & obj ) + { return str << obj._table; } + +private: + Table _table; +}; + +} + +// Local Variables: +// c-basic-offset: 2 +// End: +#endif diff --git a/zypp-tui/application.cc b/zypp-tui/application.cc new file mode 100644 index 0000000..466a668 --- /dev/null +++ b/zypp-tui/application.cc @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include "application.h" +#include +#include + +namespace ztui { + + namespace { + Application **getApplicationInstance () { + thread_local Application *app = nullptr; + return &app; + } + } + + Application::Application() + : _exitCode(ZTUI_EXIT_OK) + , _config( new Config() ) + { init(); } + + Application::Application(std::shared_ptr &&cfg) + : _exitCode(ZTUI_EXIT_OK) + , _config( std::move(cfg) ) + { init(); } + + void Application::init() + { + // ALWAYS do this FIRST! + *getApplicationInstance() = this; + _out = std::make_shared(); + } + + Application::~Application() + { + // set the thread local global to null again + *getApplicationInstance() = nullptr; + } + + Application &Application::instance() + { + auto instPtr = *getApplicationInstance (); + if ( !instPtr ) + ZYPP_THROW( zypp::Exception("No ztui::Application intance registered, its required to create one manually before using ztui.") ); + return *instPtr; + } + + const Config &Application::config() const + { + return *_config; + } + + Config &Application::mutableConfig() + { + return *_config; + } + + Out &Application::out() + { + if ( not _out ) { + _out.reset(new OutNormal( Out::QUIET )); + } + return *_out; + } + + void Application::setOutputWriter(Out *out) + { + if ( out == _out.get() ) + return; + _out.reset ( out ); + } + + void Application::setExitCode(int exit) { + WAR << "setExitCode " << exit << std::endl; + _exitCode = exit; + } + +} diff --git a/zypp-tui/application.h b/zypp-tui/application.h new file mode 100644 index 0000000..ad0cfdb --- /dev/null +++ b/zypp-tui/application.h @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_TUIAPPLICATION_INCLUDED +#define ZYPP_TUI_TUIAPPLICATION_INCLUDED + +#include +#include +#include + +namespace ztui { + + class Out; + static constexpr int ZTUI_EXIT_OK = 0; + + class Application : private zypp::base::NonCopyable + { + public: + Application(); + virtual ~Application(); + + /*! + * Returns the \ref Application instance for the current thread after it + * was created. + */ + static Application & instance(); + + const Config &config () const; + Config &mutableConfig(); + + virtual Out & out(); + virtual void setOutputWriter( Out * out ); + + int exitCode() const { return _exitCode; } + void setExitCode( int exit ); + + protected: + Application ( std::shared_ptr &&cfg ); + + private: + void init(); + int _exitCode; + std::shared_ptr _config; + std::shared_ptr _out; + }; +} + + + +#endif diff --git a/zypp-tui/config.cc b/zypp-tui/config.cc new file mode 100644 index 0000000..994ab02 --- /dev/null +++ b/zypp-tui/config.cc @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ +#include "config.h" +#include +#include +#include + +namespace ztui { + Config::Config() + : do_ttyout ( mayUseANSIEscapes() ) + , do_colors ( hasANSIColor() ) + , color_result (ansi::Color::fromString("default")) + , color_msgStatus (ansi::Color::fromString("default")) + , color_msgError (ansi::Color::fromString("red")) + , color_msgWarning (ansi::Color::fromString("purple")) + , color_prompt (ansi::Color::fromString("bold")) + , color_promptOption(ansi::Color::nocolor()) // follow color_prompt + , color_positive (ansi::Color::fromString("green")) + , color_change (ansi::Color::fromString("brown")) + , color_negative (ansi::Color::fromString("red")) + , color_highlight (ansi::Color::fromString("cyan")) + , color_lowlight (ansi::Color::fromString("brown")) + , color_osdebug (ansi::Color::fromString("default") < ansi::Color::Attr::Reverse) + { } + +} diff --git a/zypp-tui/config.h b/zypp-tui/config.h new file mode 100644 index 0000000..bbc7f76 --- /dev/null +++ b/zypp-tui/config.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_CONFIG_INCLUDED +#define ZYPP_TUI_CONFIG_INCLUDED + +#include + +namespace ztui { + + class Config { + public: + + Config (); + + /** + * True unless output is a dumb tty or file. In this case we should not use + * any ANSI Escape sequences (at least those moving the cursor; color may + * be explicitly enabled 'zypper --color ..| less' + */ + bool do_ttyout; + + /** + * Whether to colorize the output. This is evaluated according to + * color_useColors and do_ttyout. + */ + bool do_colors; + + ansi::Color color_result; + ansi::Color color_msgStatus; + ansi::Color color_msgError; + ansi::Color color_msgWarning; + ansi::Color color_prompt; + ansi::Color color_promptOption; + ansi::Color color_positive; + ansi::Color color_change; + ansi::Color color_negative; + ansi::Color color_highlight; + ansi::Color color_lowlight; + ansi::Color color_osdebug; + + }; + +} + +#endif diff --git a/zypp-tui/output/AliveCursor.h b/zypp-tui/output/AliveCursor.h new file mode 100644 index 0000000..c2674b9 --- /dev/null +++ b/zypp-tui/output/AliveCursor.h @@ -0,0 +1,80 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_OUTPUT_ALIVE_CURSOR_H +#define ZYPP_TUI_OUTPUT_ALIVE_CURSOR_H + +#include + +namespace ztui { + +class AliveCursor +{ + public: + friend std::ostream & operator<<( std::ostream & str, const AliveCursor & obj ); + + AliveCursor() : _current('-') + {} + + char current() const + { return _current; } + + void increase() + { + switch ( _current ) + { + case '-': + _current = '\\'; + break; + case '\\': + _current = '|'; + break; + case '|': + _current = '/'; + break; + case '/': + _current = '-'; + break; + } + } + + AliveCursor & operator++() + { + increase(); + return *this; + } + + AliveCursor & operator++(int) + { + increase(); + return *this; + } + + AliveCursor & done() + { + _current = '*'; + return *this; + } + + private: + char _current; +}; + +/** \relates Date Stream output */ +inline std::ostream & operator<<( std::ostream & str, const AliveCursor & obj ) +{ return str << obj.current(); } + +} + +#endif + diff --git a/zypp-tui/output/Out.cc b/zypp-tui/output/Out.cc new file mode 100644 index 0000000..5856e04 --- /dev/null +++ b/zypp-tui/output/Out.cc @@ -0,0 +1,180 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include + +#include +#include + +#include + +#include "Out.h" +#include +#include +#include "Utf8.h" + +namespace ztui { + + namespace text { + // translator: usually followed by a ' ' and some explanatory text + ColorString tagNote() { return HIGHLIGHTString(_("Note:") ); } + // translator: usually followed by a ' ' and some explanatory text + ColorString tagWarning() { return MSG_WARNINGString(_("Warning:") ); } + // translator: usually followed by a ' ' and some explanatory text + ColorString tagError() { return MSG_ERRORString(_("Error:") ); } + + const char * qContinue() { return _("Continue?"); } + } + +/////////////////////////////////////////////////////////////////// +namespace out +{ + unsigned defaultTermwidth() + { return Application::instance().out().termwidth(); } +} // namespace out +/////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +// class TermLine +//////////////////////////////////////////////////////////////////////////////// + +std::string TermLine::get( unsigned width_r, SplitFlags flags_r, char exp_r ) const +{ + utf8::string l(lhs); // utf8::string::size() returns visible chars (ignores ansi SGR)! + utf8::string r(rhs); + + if ( width_r == out::termwidthUnlimited ) + return zypp::str::Str() << l << r; // plain string if zero width + + unsigned llen = l.size(); + unsigned rlen = r.size(); + int diff = width_r - llen - rlen; + + //AutoDispose _delay( 1, ::sleep ); + + if ( diff > 0 ) + { + // expand... + if ( ! ( flags_r.testFlag( SF_EXPAND ) && ::isatty(STDOUT_FILENO) ) ) + return zypp::str::Str() << l << r; + + if ( percentHint < 0 || percentHint > 100 ) + return zypp::str::Str() << l << std::string( diff, exp_r ) << r; + + // else: draw % indicator + // ------- + // <1%>=== + // .<99%>= + // .<100%> + if ( percentHint == 0 ) + return zypp::str::Str() << l << std::string( diff, '-' ) << r; + + + unsigned pc = diff * percentHint / 100; // diff > 0 && percentHint > 0 + if ( diff < 6 ) // not enough space for fancy stuff + return zypp::str::Str() << l << std::string( pc, '.' ) << std::string( diff-pc, '=' ) << r; + + // else: less boring + std::string tag( zypp::str::Str() << '<' << percentHint << "%>" ); + pc = pc > tag.size() ? (diff - tag.size()) * percentHint / 100 : 0; + return zypp::str::Str() << l << std::string( pc, '.' ) << tag << std::string( diff-pc-tag.size(), '=' ) << r; + } + else if ( diff < 0 ) + { + // truncate... + if ( flags_r.testFlag( SF_CRUSH ) ) + { + if ( rlen > width_r ) + return r.substr( 0, width_r ).str(); + return zypp::str::Str() << l.substr( 0, width_r - rlen ) << r; + } + else if ( flags_r.testFlag( SF_SPLIT ) ) + { + zypp::str::Str out; + if ( llen > width_r ) + mbs_write_wrapped( out.stream(), l.str(), 0, width_r ); + else + out << l; + return out << "\n" << ( rlen > width_r ? r.substr( 0, width_r ) : std::string( width_r - rlen, ' ' ) + r ); + } + // else: + return zypp::str::Str() << l << r; + } + // else: fits exactly + return zypp::str::Str() << l << r; +} + +//////////////////////////////////////////////////////////////////////////////// +// class Out +//////////////////////////////////////////////////////////////////////////////// + +constexpr Out::Type Out::TYPE_NONE; +constexpr Out::Type Out::TYPE_ALL; + +Out::~Out() +{} + +bool Out::progressFilter() +{ + return verbosity() < Out::NORMAL; +} + +std::string Out::zyppExceptionReport(const zypp::Exception & e) +{ + return e.asUserHistory(); +} + +void Out::searchResult( const Table & table_r ) +{ + std::cout << table_r; +} + +void Out::progressEnd( const std::string & id, const std::string & label, ProgressEnd donetag_r ) +{ + // translator: Shown as result tag in a progress bar: ............[done] + static const std::string done { _("done") }; + // translator: Shown as result tag in a progress bar: .......[attention] + static const std::string attention { MSG_WARNINGString(_("attention")).str() }; + // translator: Shown as result tag in a progress bar: ...........[error] + static const std::string error { MSG_ERRORString(_("error")).str() }; + + const std::string & donetag { donetag_r==ProgressEnd::done ? done : donetag_r==ProgressEnd::error ? error : attention }; + progressEnd( id, label, donetag, donetag_r==ProgressEnd::error ); +} + +//////////////////////////////////////////////////////////////////////////////// +// class Out::Error +//////////////////////////////////////////////////////////////////////////////// + +int Out::Error::report( Application & app_r ) const +{ + if ( ! ( _msg.empty() && _hint.empty() ) ) + app_r.out().error( _msg, _hint ); + if ( _exitcode != ZTUI_EXIT_OK ) // ZTUI_EXIT_OK indicates exitcode is already set. + app_r.setExitCode( _exitcode ); + return app_r.exitCode(); +} + +std::string Out::Error::combine( std::string && msg_r, const zypp::Exception & ex_r ) +{ + if ( msg_r.empty() ) + { + msg_r = combine( ex_r ); + } + else + { + msg_r += "\n"; + msg_r += combine( ex_r ); + } + return std::move(msg_r); +} +std::string Out::Error::combine( const zypp::Exception & ex_r ) +{ return Application::instance().out().zyppExceptionReport( ex_r ); } + +} diff --git a/zypp-tui/output/Out.h b/zypp-tui/output/Out.h new file mode 100644 index 0000000..0eccde6 --- /dev/null +++ b/zypp-tui/output/Out.h @@ -0,0 +1,1180 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef OUT_H_ +#define OUT_H_ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace ztui { + +class Application; + +/// ProgressBars default end tags. +enum class ProgressEnd { done, attention, error }; + +namespace text +{ + ColorString tagNote(); ///< translated "Note:" highlighted + ColorString tagWarning(); ///< translated "Warning:" warning color + ColorString tagError(); ///< translated "Error:" error color + const char * qContinue(); ///< translated "Continue?" + + /** Simple join of two string types */ + template + inline std::string join( const Tltext & ltext, const Trtext & rtext, const char * sep = " " ) + { std::string ret( zypp::str::asString(ltext) ); ret += sep; ret += zypp::str::asString(rtext); return ret; } + + /** Whether the \a str_r ends with a WS. */ + inline bool endsOnWS( const std::string & str_r ) + { + bool ret = false; + if ( !str_r.empty() ) + { int l = *str_r.rbegin(); if ( ::strchr( " \n\t", l ) ) ret = true; } + return ret; + } + + inline const char * optBlankAfter( const std::string & str_r ) + { return( endsOnWS( str_r ) ? "" : " " ); } +} + +namespace out +{ + static constexpr unsigned termwidthUnlimited = 0u; + unsigned defaultTermwidth(); // Zypper::instance().out().termwidth() +} // namespace out + +namespace out +{ + /*! + * \class ListLayout + * \brief Basic list layout + * \todo fix design made in eile + */ + struct ListLayout + { + template struct Writer; + + ListLayout( bool singleline_r, bool wrapline_r, bool gaped_r, unsigned indent_r ) + : _singleline( singleline_r ) + , _wrapline( wrapline_r ) + , _gaped( gaped_r ) + , _indent( indent_r ) + {} + bool _singleline; ///< one list element per line + bool _wrapline; ///< fold lines longer than \c _linewidth + bool _gaped; ///< add extra NL before element (if singleline) + unsigned _indent; ///< amount of indent + }; + + namespace detail + { + template + struct ListLayoutInit : public ListLayout { ListLayoutInit() : ListLayout( singleline_, wrapline_, gaped_, indent_ ) {} }; + } + + using XmlListLayout = detail::ListLayoutInit; + using DefaultListLayout = detail::ListLayoutInit; ///< one element per line, no indent + using DefaultGapedListLayout = detail::ListLayoutInit; ///< one element per line, no indent, gaped + using IndentedListLayout = detail::ListLayoutInit; ///< one element per line, indented + using IndentedGapedListLayout = detail::ListLayoutInit;///< one element per line, indented, gaped + using CompressedListLayout = detail::ListLayoutInit; ///< multiple elements per line, indented + + /*! + * \class TableLayout + * \brief Basic table layout + */ + struct TableLayout + { + template struct Writer; + }; + + using DefaultTableLayout = TableLayout; ///< Simple Table + + // Either specialize per Type or define a custom Formater: + + /** \relates XmlFormater XML representation of types [no default] */ + template + std::string asXmlListElement( const Tp & val_r ); + inline std::string asXmlListElement( const std::string & val_r ){ return val_r; } + inline std::string asXmlListElement( const char * val_r ) { return val_r; } + + /** \relates ListFormater NORMAL representation of types in lists [no default] */ + template + std::string asListElement( const Tp & val_r ); + inline std::string asListElement( const std::string & val_r ) { return val_r; } + inline std::string asListElement( const char * val_r ) { return val_r; } + + /** \relates TableFormater NORMAL representation of types as TableHeader [no default] */ + template + TableHeader asTableHeader(); + + template <> + inline TableHeader asTableHeader() + { return TableHeader(); } + + /** \relates TableFormater NORMAL representation of types as TableRow [no default] */ + template + TableRow asTableRow( const Tp & val_r ); + + /////////////////////////////////////////////////////////////////// + /// \class XmlFormater + /// \brief XML representation of types in container [asXmlListElement] + /////////////////////////////////////////////////////////////////// + struct XmlFormater + { + template + std::string xmlListElement( const Tp & val_r ) const//< XML representation of element + { return asXmlListElement( val_r ); } + }; + + /////////////////////////////////////////////////////////////////// + /// \class ListFormater + /// \brief Default representation of types in Lists [asListElement] + /////////////////////////////////////////////////////////////////// + struct ListFormater : public XmlFormater + { + using NormalLayout = DefaultListLayout; //< ListLayout for NORMAL lists + + template + std::string listElement( const Tp & val_r ) const //< NORMAL representation of list element + { return asListElement( val_r ); } + }; + + /////////////////////////////////////////////////////////////////// + /// \class TableFormater + /// \brief Special list formater writing a Table [asTableHeader|asTableRow] + /////////////////////////////////////////////////////////////////// + struct TableFormater : public XmlFormater + { + using NormalLayout = DefaultTableLayout; //< NORMAL layout as Table + + TableHeader header() const //< TableHeader for TableRow representation + { return asTableHeader<>(); } + + template //< Representation as TableRow + TableRow row( const Tp & val_r ) const + { return asTableRow( val_r ); } + }; + + /////////////////////////////////////////////////////////////////// + /// \class XmlFormaterAdaptor + /// \brief Adaptor mapping xmlListElement->listElement for container XML output + /////////////////////////////////////////////////////////////////// + /** Adaptor */ + template + struct XmlFormaterAdaptor + { + using NormalLayout = XmlListLayout; //< Layout as XML list + + template + std::string listElement( const Tp & val_r ) const //< use TFormater::asXmlListElement + { return _formater.xmlListElement( val_r ); } + + XmlFormaterAdaptor( const TFormater & formater_r ) + : _formater( formater_r ) + {} + private: + const TFormater & _formater; + }; + +} // namespace out +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace out +{ + /////////////////////////////////////////////////////////////////// + /// \class ListLayout::Writer + /// \brief Write out a List according to the layout + // TODO: wrap singlelines; support for attributed text; + /////////////////////////////////////////////////////////////////// + template + struct ListLayout::Writer + { + NON_COPYABLE( Writer ); + + Writer( std::ostream & str_r, const ListLayout & layout_r, const TFormater & formater_r ) + : _str( str_r ) + , _layout( layout_r ) + , _formater( formater_r ) + , _linewidth( defaultTermwidth() ) + , _indent( _layout._indent, ' ' ) + {} + + ~Writer() + { if ( !_layout._singleline && _cpos ) _str << std::endl; } + + template + void operator<<( Tp && val_r ) const + { + const std::string & element( _formater.listElement( std::forward(val_r) ) ); + + if ( _layout._singleline ) + { + if ( _layout._gaped ) + _str << std::endl; + _str << _indent << element << std::endl; + } + else + { + if ( _cpos != 0 && ! fitsOnLine( 1/*' '*/ + element.size() ) ) + endLine(); + + if ( _cpos == 0 ) + { + if ( !_indent.empty() ) + printAndCount( _indent ); + } + else + printAndCount( " " ); + + printAndCount( element ); + } + } + + private: + bool fitsOnLine( unsigned size_r ) const + { return( !_layout._wrapline || _linewidth == out::termwidthUnlimited || _cpos + size_r <= _linewidth ); } + + void printAndCount( const std::string & element_r ) const + { _cpos += element_r.size(); _str << element_r; } + + void endLine() const + { _str << std::endl; _cpos = 0U; } + + private: + std::ostream & _str; + const ListLayout & _layout; + const TFormater & _formater; + const unsigned _linewidth; ///< desired line width + const std::string _indent; + mutable unsigned _cpos = 0U; + }; + + /////////////////////////////////////////////////////////////////// + /// \class TableLayout::Writer + /// \brief Write out a Table according to the layout + /////////////////////////////////////////////////////////////////// + template + struct TableLayout::Writer + { + NON_COPYABLE( Writer ); + + Writer( std::ostream & str_r, const TableLayout & layout_r, const TFormater & formater_r ) + : _str( str_r ) + , _layout( layout_r ) + , _formater( formater_r ) + {} + + ~Writer() + { + if ( !_t.empty() ) + { + _t.setHeader( _formater.header() ); + _str << _t; + } + } + + template + void operator<<( Tp && val_r ) const + { _t.add( _formater.row( std::forward(val_r) ) ); } + + private: + std::ostream & _str; + const TableLayout & _layout; + const TFormater & _formater; + mutable Table _t; + }; + + + /** Write formatted container to stream */ + template + void writeContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r, const TLayout & layout_r = TLayout() ) + { + typedef typename TLayout::template Writer Writer; + Writer writer( str_r, layout_r, formater_r ); + for ( auto && el : container_r ) + writer << el; + } + + /** Write XML formatted container to stream */ + template + void xmlWriteContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r ) + { writeContainer( str_r, container_r, out::XmlFormaterAdaptor(formater_r) ); } + +} // namespace out +/////////////////////////////////////////////////////////////////// + +// Too simple on small terminals as esc-sequences may get truncated. +// A table like writer for attributed strings is desirable. +struct TermLine +{ + enum SplitFlag + { + SF_CRUSH = 1<<0, //< truncate lhs, then rhs + SF_SPLIT = 1<<1, //< split line across two + SF_EXPAND = 1<<2 //< expand short lines iff stdout is a tty + }; + ZYPP_DECLARE_FLAGS( SplitFlags, SplitFlag ); + + TermLine( SplitFlags flags_r, char exp_r ) : flagsHint( flags_r ), expHint( exp_r ) {} + TermLine( SplitFlags flags_r ) : flagsHint( flags_r ) {} + TermLine( char exp_r ) : expHint( exp_r ) {} + TermLine() {} + + SplitFlags flagsHint; //< flags to use if not passed to \ref get + zypp::DefaultIntegral expHint; //< expand char to use if not passed to \ref get + zypp::DefaultIntegral percentHint; //< draw progress indicator in expanded space if in [0,100] + + zypp::str::Str lhs; //< left side + zypp::str::Str rhs; //< right side + + + /** Return plain line made of lhs + rhs */ + std::string get() const + { return std::string(lhs) + std::string(rhs); } + + /** Return line optionally formatted according to \a width_r and \a flags_r. + * If \a width_r or \a flags_r is zero a plain line made of lhs + rhs is returned. + */ + std::string get( unsigned width_r, SplitFlags flags_r, char exp_r ) const; + /** \overload */ + std::string get( unsigned width_r, SplitFlags flags_r ) const + { return get( width_r, flags_r, expHint ); } + /** \overload */ + std::string get( unsigned width_r, char exp_r ) const + { return get( width_r, flagsHint, exp_r ); } + /** \overload */ + std::string get( unsigned width_r ) const + { return get( width_r, flagsHint, expHint ); } +}; +ZYPP_DECLARE_OPERATORS_FOR_FLAGS( TermLine::SplitFlags ); + +/** + * Base class for producing common (for now) zypper output. + * + * This is an abstract class providing interface for writing output like + * info messages, warnings, error messages, user prompts, progress reports, + * and download progress reports. See descriptions of the methods for more + * details. + * + * The output is produced using Out derived class instances. + * + * + * + * // create output object + * SomePointerType out; + * if (options.count("xmlout")) + * out = new OutXML(); + * else + * out = new OutNormal(); + * + * out->info("output instance ready to use", Out::HIGH); + * out->info("Doing foo"); + * try + * { + * foo(); + * out->prompt(PROMPT_FOO, "Need your action?", "y/n"); // see output/prompt.h + * if (action()) + * out->info("result", Out::QUIET); // always show the result + * else + * cout << "special result" << endl; // special output must be done + * // the usual way for now + * } + * catch(const Exception & e) + * { + * out->error(e, "Problem doing foo", "Do 'bar' to deal with this"); + * } + * + * + */ +class Out : private zypp::base::NonCopyable +{ +public: + /** Verbosity levels. */ + typedef enum + { + QUIET = 0, ///< Only important messages (no progress or status, only the result). + NORMAL = 1, ///< Default output verbosity level. Progress for important tasks, moderate + ///< amount of status messages, operation information, result. + HIGH = 2, ///< More detailed description of the operations. + DEBUG = 3 ///< \todo drop this level in favor of zypper.log? + } Verbosity; + + /** Known output types implemented by derived classes. */ + enum TypeBit + { + TYPE_NORMAL = 0x01<<0, ///< plain text output + TYPE_XML = 0x01<<1 ///< xml output + }; + ZYPP_DECLARE_FLAGS(Type,TypeBit); + + static constexpr Type TYPE_NONE = Type(0x00); + static constexpr Type TYPE_ALL = Type(0xff); + + using PromptId = unsigned; + +protected: + Out(TypeBit type, Verbosity verbosity = NORMAL) + : _verbosity(verbosity), _type(type) + {} + +public: + virtual ~Out(); + +protected: + /////////////////////////////////////////////////////////////////// + /// \class ParentOut + /// \brief Convenience base class storing the back reference to Out. + struct ParentOut + { + ParentOut( Out & out_r ) : _out( out_r ) {} + Out & out() { return _out; } + private: + Out & _out; + }; + +public: + /////////////////////////////////////////////////////////////////// + /// \class XmlNode + /// \brief XML only: RAII writing a XML nodes start/end tag + /// \code + /// { + /// XmlNode( "node", { "attr", "val" } ); // + /// ... + /// } // + /// \endcode + struct XmlNode : protected ParentOut + { + using Attr = zypp::xmlout::Node::Attr; + + /** Ctor taking nodename and attribute list. */ + XmlNode( Out & out_r, const std::string & name_r, const std::initializer_list & attrs_r = {} ) + : ParentOut( out_r ) + { + if ( out().typeXML() && ! name_r.empty() ) + { _node.reset( new zypp::xmlout::Node( std::cout, name_r, attrs_r ) ); } + } + + /** Convenience ctor for one attribute pair */ + XmlNode( Out & out_r, const std::string & name_r, Attr attr_r ) + : XmlNode( out_r, name_r, { std::move(attr_r) } ) + {} + + /** Move ctor */ + XmlNode( XmlNode && rhs ) noexcept : ParentOut( rhs ) { _node.swap( rhs._node ); } + + private: + zypp::scoped_ptr _node; + }; + /////////////////////////////////////////////////////////////////// + + /** XML only: Write a leaf node without PCDATA + * \code + * + * \endcode + */ + void xmlNode( const std::string & name_r, const std::initializer_list & attrs_r = {} ) + { if ( typeXML() ) { zypp::xmlout::node( std::cout, name_r, attrs_r ); } } + /** \overload for one attribute pair */ + void xmlNode( const std::string & name_r, XmlNode::Attr attr_r ) + { xmlNode( name_r, { std::move(attr_r) } ); } + + /////////////////////////////////////////////////////////////////// + /// \class TitleNode + /// \brief XmlNode with optional normal text headline (NL appended) + struct TitleNode : public XmlNode + { + TitleNode( XmlNode && node_r, const std::string & title_r = "" ) + : XmlNode( std::move(node_r) ) + { if ( out().typeNORMAL() && ! title_r.empty() ) std::cout << title_r << std::endl; } + }; + +private: + /** Write container creating a TitleNode with \c size="nnn" attribute and + * replacing optional \c %1% in \a title_r with size. */ + template + void container( const std::string & nodeName_r, const std::string & title_r, + const TContainer & container_r, const TFormater & formater_r ) + { + TitleNode guard( XmlNode( *this, nodeName_r, XmlNode::Attr( "size", zypp::str::numstring( container_r.size() ) ) ), + zypp::str::Format( title_r ) % container_r.size() ); + switch ( type() ) + { + case TYPE_NORMAL: + writeContainer( std::cout, container_r, formater_r ); + break; + case TYPE_XML: + ztui::out::xmlWriteContainer( std::cout, container_r, formater_r ); + break; + } + } + +public: + /** Write list from container creating a TitleNode with \c size="nnn" attribute and + * replacing optional \c %1% in \a title_r with size. */ + template + void list( const std::string & nodeName_r, const std::string & title_r, + const TContainer & container_r, const TFormater & formater_r = TFormater() ) + { container( nodeName_r, title_r, container_r, formater_r ); } + + /** Write table from container creating a TitleNode with \c size="nnn" attribute and + * replacing optional \c %1% in \a title_r with size. */ + template + void table( const std::string & nodeName_r, const std::string & title_r, + const TContainer & container_r, const TFormater & formater_r = TFormater() ) + { container( nodeName_r, title_r, container_r, formater_r ); } + +public: + /** NORMAL: An empty line */ + void gap() { if ( type() == TYPE_NORMAL ) std::cout << std::endl; } + + void printRichText( std::string text, unsigned indent_r = 0U ) + { ztui::printRichText( std::cout, std::move(text), indent_r, termwidth() ); } + + + /** Less common Paragraph formats */ + struct ParFormat // placeholder until we need it + {}; + + /** Paragraph of text, optionally indented, or without leading gap */ + template + void par( size_t indent_r, const Text & text_r, ParFormat format_r = ParFormat() ) + { + gap(); // if needed make it optional via ParFormat + zypp::str::Str formated; + mbs_write_wrapped( formated.stream(), zypp::str::asString(text_r), indent_r, defaultFormatWidth( 100 ) ); + info( formated ); + } + /** \overload convenience for unindented */ + template + void par( const Text & text_r, ParFormat format_r = ParFormat() ) + { par( 0, text_r, format_r ); } + + + /** Paragraph of text preceded by 'tag_r' and a ' ' */ + template + void taggedPar( size_t indent_r, const TText & tag_r, const Text & text_r, ParFormat format_r = ParFormat() ) + { par( indent_r, text::join( tag_r, text_r ), format_r ); } + /** \overload convenience for unindented par */ + template + void taggedPar( const TText & tag_r, const Text & text_r, ParFormat format_r = ParFormat() ) + { taggedPar( 0, tag_r, text_r, format_r ); } + + + /** Paragraph tagged with 'Note: ' */ + template + void notePar( size_t indent_r, const Text & text_r, ParFormat format_r = ParFormat() ) + { taggedPar( indent_r, text::tagNote(), text_r, format_r ); } + /** \overload convenience for unindented par */ + template + void notePar( const Text & text_r, ParFormat format_r = ParFormat() ) + { notePar( 0, text_r, format_r ); } + + /** Paragraph tagged with 'Warning: ' */ + template + void warningPar( size_t indent_r, const Text & text_r, ParFormat format_r = ParFormat() ) + { taggedPar( indent_r, text::tagWarning(), text_r, format_r ); } + /** \overload convenience for unindented par */ + template + void warningPar( const Text & text_r, ParFormat format_r = ParFormat() ) + { warningPar( 0, text_r, format_r ); } + + /** Paragraph tagged with 'Error: ' */ + template + void errorPar( size_t indent_r, const Text & text_r, ParFormat format_r = ParFormat() ) + { taggedPar( indent_r, text::tagError(), text_r, format_r ); } + /** \overload convenience for unindented par */ + template + void errorPar( const Text & text_r, ParFormat format_r = ParFormat() ) + { errorPar( 0, text_r, format_r ); } + +public: + /** + * Show an info message. + * + * \param msg The message to be displayed. + * \param verbosity Minimal level o verbosity in which the message will be + * shown. Out::QUIET means the message will be always be + * displayed. Out::HIGH means the message will be displayed + * only if the current verbosity level is HIGH (-v) or DEBUG + * (-vv). + * \param mask Determines the types of output for which is this message + * intended. By default, the message will be shown in all + * types of output. + */ + virtual void info(const std::string & msg, Verbosity verbosity = NORMAL, Type mask = TYPE_ALL) = 0; + /** \overload concatenating 2 strings (e.g. translated and untranslated parts) */ + void info( std::string msg, const std::string & msg2, Verbosity verbosity = NORMAL, Type mask = TYPE_ALL ) + { info( (msg+=msg2), verbosity, mask ); } + + /** \ref info taking a \ref TermLine */ + virtual void infoLine(const TermLine & msg_r, Verbosity verbosity_r = NORMAL, Type mask_r = TYPE_ALL) + { info( msg_r.get(), verbosity_r, mask_r ); } + + struct Info : protected ParentOut + { + NON_COPYABLE( Info ); + + Info( Out & out_r ) + : ParentOut( out_r ) + , _str( new std::ostringstream ) + {} + + Info( Out::Info && rhs ) noexcept + : ParentOut( rhs ) + , _str( std::move(rhs._str) ) + {} + + ~Info() + { out().info( _str->str() ); } + + template + std::ostream & operator<<( const Tp & val ) + { return (*_str) << val; /*return *this;*/ } + + operator std::ostream &() + { return *_str; } + + std::ostream & stream() + { return *_str; } + + private: + std::unique_ptr _str; // work around missing move ctor + }; + + Info info() { return Info( *this ); } + + + /** Info message, 2 strings L/R-adjusted. */ + void infoLR( const std::string & lmsg, const std::string & rmsg, Verbosity verbosity = NORMAL, Type mask = TYPE_ALL ) + { + TermLine outstr( TermLine::SF_SPLIT | TermLine::SF_EXPAND ); + outstr.lhs << lmsg; + outstr.rhs << ' ' << rmsg; + infoLine( outstr, verbosity, mask ); + } + + /** Info message with R-adjusted "(hint)". */ + void infoLRHint( const std::string & lmsg, const std::string & hint, Verbosity verbosity = NORMAL, Type mask = TYPE_ALL ) + { + TermLine outstr( TermLine::SF_SPLIT | TermLine::SF_EXPAND ); + outstr.lhs << lmsg; + outstr.rhs << " (" << hint << ')'; + infoLine( outstr, verbosity, mask ); + } + + + /** + * Show a warning. + * + * \param msg The warning message to be displayed. + * \param verbosity Minimal level o verbosity in which the message will be + * shown. Out::QUIET means the message will be always be + * displayed. Out::HIGH means the message will be displayed + * only if the current verbosity level is HIGH (-v) or DEBUG + * (-vv). + * \param mask Determines the types of output for which is this message + * intended. By default, the message will be shown in all + * types of output. + */ + virtual void warning(const std::string & msg, Verbosity verbosity = NORMAL, Type mask = TYPE_ALL) = 0; + + /** Convenience class for error reporting. */ + struct Error; + + /** + * Show an error message and an optional hint. + * + * An error message should be shown regardless of the verbosity level. + * + * \param problem_desc Problem description (what happened) + * \param hint Hint for the user (what to do, or explanation) + */ + virtual void error(const std::string & problem_desc, const std::string & hint = "") = 0; + + /** + * Prints the problem description caused by an exception, its cause and, + * optionally, a hint for the user. + * + * \param e Exception which caused the problem. + * \param Problem description for the user. + * \param Hint for the user how to cope with the problem. + */ + virtual void error(const zypp::Exception & e, + const std::string & problem_desc, + const std::string & hint = "") = 0; + + //! \todo provide an error() method with a/r/i prompt, more read_action_ari here + + /** \name Progress of an operation. */ + //@{ + + /** Convenience class for progress output. */ + class ProgressBar; + + /** + * Start of an operation with reported progress. + * + * \param id Identifier. Any string used to match multiple overlapping + * progress reports (doesn't happen now, + * but probably will in the future). + * \param label Progress description. + * \param is_tick false for known progress percentage, true + * for 'still alive' notifications + */ + virtual void progressStart(const std::string & id, + const std::string & label, + bool is_tick = false) = 0; + + /** + * Progress report for an on-going operation. + * + * \param id Identifier. Any string used to match multiple overlapping + * progress reports. + * \param label Progress description. + * \param value Percentage value or -1 if unknown ('still alive' + * notification) + */ + virtual void progress(const std::string & id, + const std::string & label, + int value = -1) = 0; + + /** + * End of an operation with reported progress. + * + * \param id Identifier. Any string used to match multiple overlapping + * progress reports. + * \param label Progress description. + * \param donetag Optional string overwriting the default [done]/[error] tags. + * \param error false if the operation finished with success, + * true otherwise. + */ + virtual void progressEnd(const std::string & id, + const std::string & label, + const std::string & donetag, + bool error = false) = 0; + /** \overload using the default [done]/[attention]/[error] tags in screen output. depending on \a donetag. */ + void progressEnd( const std::string & id, const std::string & label, ProgressEnd donetag ); + /** \overload using the default [done]/[error] tags in screen output depending on \a error. */ + void progressEnd( const std::string & id, const std::string & label, bool error = false ) + { progressEnd( id, label, error ? ProgressEnd::error : ProgressEnd::done ); } + //@} + + /** \name Download progress with download rate */ + //@{ + /** + * Reoprt start of a download. + * + * \param uri Uri of the file to download. + */ + virtual void dwnldProgressStart(const zypp::Url & uri) = 0; + + /** + * Reports download progress. + * + * \param uri Uri of the file being downloaded. + * \param value Value of the progress in percents. -1 if unknown. + * \param rate Current download rate in B/s. -1 if unknown. + */ + virtual void dwnldProgress(const zypp::Url & uri, + int value = -1, + long rate = -1) = 0; + /** + * Reports end of a download. + * + * \param uri Uri of the file to download. + * \param rate Average download rate at the end. -1 if unknown. + * \param error Error flag - did the download finish with error? \c indeterminate == 'not found' + */ + virtual void dwnldProgressEnd(const zypp::Url & uri, + long rate = -1, + zypp::TriBool error = false) = 0; + //@} + + /** + * Print out a search result. + * + * Default implementation prints \a table_r on \c stdout. + * + * \param table_r Table containing the search result. + * + * \todo Using a more generic format than a Table is desired. + */ + virtual void searchResult( const Table & table_r ); + + /** + * Prompt the user for a decision. + * + * \param id Unique prompt identifier for use by machines. + * \param prompt Prompt text. + * \param options A PromptOptions object + * \param startdesc Initial detailed description of the prompt to be + * prepended to the \a prompt text. Should be used + * only whe prompting for the first time and left empty + * when retrying after an invalid answer has been given. + * \see prompt.h + * \see ../zypper-prompt.h + */ + virtual void prompt(PromptId id, + const std::string & prompt, + const PromptOptions & poptions, + const std::string & startdesc = "") = 0; + + /** + * Print help for prompt, if available. + * This method should be called after '?' prompt option has been entered. + */ + virtual void promptHelp(const PromptOptions & poptions) = 0; + +public: + /** Get current verbosity. */ + Verbosity verbosity() const { return _verbosity; } + + /** Set current verbosity. */ + void setVerbosity(Verbosity verbosity) { _verbosity = verbosity; } + + /** Convenience macro for exception safe scoped verbosity change + * \code + * { + * // shut up zypper + * SCOPED_VERBOSITY( Zypper::instance().out(), Out::QUIET ); + * // expands to: + * // const auto & raii __attribute__ ((__unused__))( Zypper::instance().out().scopedVerbosity( Out::QUIET ) ); + * ... + * // leaving the block restores previous verbosity + * } + * \endcode + */ +#define SCOPED_VERBOSITY( OUT, LEVEL ) const auto & raii __attribute__ ((__unused__))( (OUT).scopedVerbosity( LEVEL )) + + /** Return RAII class for exception safe scoped verbosity change. */ + zypp::DtorReset scopedVerbosity( Verbosity verbosity_r ) + { + std::swap( _verbosity, verbosity_r ); + return zypp::DtorReset( _verbosity, verbosity_r ); + } + + /** Hint for a handler whether config would allow to use colors. */ + virtual void setUseColors( bool yesno ) {} + +public: + /** Return the type of the instance. */ + TypeBit type() const { return _type; } + + /** Test for a specific type */ + bool type( TypeBit type_r ) const { return type() == type_r; } + /** \overload test for TYPE_NORMAL */ + bool typeNORMAL() const { return type( TYPE_NORMAL ); } + /** \overload test for TPE_XML */ + bool typeXML() const { return type( TYPE_XML ); } + + /** Terminal width or 150 if unlimited. + * If a \a desired_r value is given, return the + * closest width that fits the terminal. + */ + unsigned defaultFormatWidth( unsigned desired_r = 0 ) const + { + unsigned ret = termwidth(); + if ( ret == out::termwidthUnlimited ) + ret = desired_r ? desired_r : 150U; + else if ( desired_r < ret ) + ret = desired_r; + return ret; + } + + /** Width for formatted output [0==unlimited]. */ + virtual unsigned termwidth() const { return out::termwidthUnlimited; } + +protected: + + /** + * Determine whether the output is intended for the particular type. + */ + virtual bool mine(Type type) = 0; + + /** + * Determine whether to show progress. + * + * \return true if the progress should be filtered out, + * false if it should be shown. + */ + virtual bool progressFilter(); + + /** + * Return a Exception as a string suitable for output. + */ + virtual std::string zyppExceptionReport(const zypp::Exception & e); + +private: + Verbosity _verbosity; + const TypeBit _type; +}; + +ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Out::Type); + +/////////////////////////////////////////////////////////////////// +/// \class Out::ProgressBar +/// \brief Convenience class for progress output. +/// +/// Progress start and end messages are provided upon object +/// construction and deletion. Progress data are sent through a +/// ProgressData object accessible via \ref operator->. +/// +/// \code +/// { +/// Out::ProgressBar report( _zypper.out(), "Prepare action" ); +/// for ( unsigned i = 0; i < 10; ++ i ) +/// { +/// report->tick(); // turn wheel +/// sleep(1); +/// } +/// report->range( 10 ); // switch to percent mode [0,10] +/// report.print( "Running action" ); +/// for ( unsigned i = 0; i < 10; ++ i ) +/// { +/// report-> +/// report->set( i ); // send 0%, 10%, ... +/// sleep(1); +/// } +/// // report.error( "Action failed" ); +/// } +/// \endcode +/// +/// If non zero values for \a current_r or \a total_r are passed to +/// the ctor, the label is prefixed by either "(#C)" or "(#C/#T)" +/// +/// \todo ProgressData provides NumericId which might be used as +/// id for_out.progress*(). +/////////////////////////////////////////////////////////////////// +class Out::ProgressBar : private zypp::base::NonCopyable +{ +public: + /** Indicator type for ctor not drawing an initial start bar. */ + struct NoStartBar {}; + /** Indicator argument for ctor not drawing an initial start bar.*/ + static constexpr NoStartBar noStartBar = NoStartBar(); + +public: + /** Ctor not displaying an initial progress bar. + * If non zero values for \a current_r or \a total_r are passed, + * the label is prefixed by either "(#C)" or "(#C/#T)" + */ + ProgressBar( Out & out_r, NoStartBar, std::string progressId_r, const std::string & label_r, unsigned current_r = 0, unsigned total_r = 0 ) + : _out( out_r ) + , _progressId(std::move( progressId_r )) + { + if ( total_r ) + _labelPrefix = zypp::str::form( "(%*u/%u) ", numDigits( total_r ), current_r, total_r ); + else if ( current_r ) + _labelPrefix = zypp::str::form( "(%u) ", current_r ); + _progress.name( label_r ); + _progress.sendTo( Print( *this ) ); + } + + ProgressBar( Out & out_r,NoStartBar, const std::string & label_r, unsigned current_r = 0, unsigned total_r = 0 ) + : ProgressBar( out_r, noStartBar, "", label_r, current_r, total_r ) + {} + + /** Ctor displays initial progress bar. + * If non zero values for \a current_r or \a total_r are passed, + * the label is prefixed by either "(#C)" or "(#C/#T)" + */ + ProgressBar( Out & out_r, const std::string & progressId_r, const std::string & label_r, unsigned current_r = 0, unsigned total_r = 0 ) + : ProgressBar( out_r, noStartBar, progressId_r, label_r, current_r, total_r ) + { + // print the initial progress bar + _out.progressStart( _progressId, outLabel( _progress.name() ) ); + } + + ProgressBar( Out & out_r, const std::string & label_r, unsigned current_r = 0, unsigned total_r = 0 ) + : ProgressBar( out_r, "", label_r, current_r, total_r ) + {} + + /** Dtor displays final progress bar. + * Unless \ref error has explicitly been set, an error is indicated if + * a \ref ProgressData range has been set, but 100% were not reached. + */ + ~ProgressBar() + { + _progress.noSend(); // suppress ~ProgressData final report + if ( not _donetag ) + error( _progress.reportValue() != 100 && _progress.reportPercent() ); + _out.progressEnd( _progressId, outLabel( _progress.name() ), *_donetag ); + } + + /** Immediately print the progress bar not waiting for a new trigger. */ + void print() + { _out.progress( _progressId, outLabel( _progress.name() ), _progress.reportValue() ); } + + /** \overload also change the progress bar label. */ + void print( const std::string & label_r ) + { _progress.name( label_r ); print(); } + + /** Explicitly indicate the error condition for the final progress bar. */ + void error( ProgressEnd donetag_r = ProgressEnd::error ) + { _donetag = donetag_r; } + + /** \overload just done/error. */ + void error( bool error_r ) + { _donetag = error_r ? ProgressEnd::error : ProgressEnd::done; } + + /** Reset any error condition. */ + void errorreset() + { _donetag.reset(); } + + /** \overload also change the progress bar label. */ + void error( const std::string & label_r ) + { _progress.name( label_r ); error( true ); } + + /** \overload also change the progress bar label and disambiguate. */ + void error( const char * label_r ) + { _progress.name( label_r ); error( true ); } + +public: + /** \name Access the embedded ProgressData object */ + //@{ + zypp::ProgressData * operator->() + { return &_progress; } + + const zypp::ProgressData * operator->() const + { return &_progress; } + + zypp::ProgressData & operator*() + { return _progress; } + + const zypp::ProgressData & operator*() const + { return _progress; } + //@} + +private: + /** ProgressData::ReceiverFnc printing to a ProgressBar. + * + * \note This could also be used to let an external \ref ProgressData object + * trigger a \ref ProgressBar. \ref ProgressBar::label and \ref ProgressBar::print + * however use the embedded ProgressData object (esp. it's label). So don't mix this. + */ + struct Print + { + Print( ProgressBar & bar_r ) : _bar( &bar_r ) {} + bool operator()( const zypp::ProgressData & progress_r ) + { _bar->_out.progress( _bar->_progressId, _bar->outLabel( progress_r.name() ), progress_r.reportValue() ); return true; } + private: + ProgressBar * _bar; + }; + + std::string outLabel( const std::string & msg_r ) const + { return _labelPrefix.empty() ? msg_r : _labelPrefix + msg_r; } + + int numDigits( unsigned num_r ) const + { int ret = 1; while ( num_r /= 10 ) ++ret; return ret; } + +private: + Out & _out; + std::optional _donetag; + zypp::ProgressData _progress; + std::string _progressId; + std::string _labelPrefix; +}; +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +/// \class Out::Error +/// \brief Convenience class Error reporting. +/// +/// Called action methods may \c throw this as exception. The calling function +/// should catch and process it (e.g. by calling \ref report). +/// +/// This allows e.g. active \ref Out::ProgressBar objects to close properly +/// before the error message is displayed. +/// +/// \code +/// try { +/// Out::ProgressBar report( zypper_r.out(), _("Scanning download directory") ); +/// report->range( todolist.size() ); +/// // now report will indicate an error id closed before reaching 100% +/// .... +/// if ( some error ) +/// throw( Out::Error( ZYPPER_EXIT_ERR_BUG, +/// _("Failed to read download directory"), +/// Errno().asString() ) ); +/// +/// } +/// catch ( const SourceDownloadImpl::Error & error_r ) +/// { +/// // Default way of processing a caught Error exception: +/// // - Write error message and optional hint to screen. +/// // - Set the ZYPPER_EXIT_ code if necessary. +/// // - Return the current ZYPPER_EXIT_ code. +/// return error_r.report( zypper_r ); +/// } +/// \endcode +/////////////////////////////////////////////////////////////////// +struct Out::Error +{ + Error( int exitcode_r ) + : _exitcode( exitcode_r ) {} + + // basic: code msg hint + Error( int exitcode_r, std::string msg_r, std::string hint_r = std::string() ) + : _exitcode( exitcode_r ), _msg( std::move(msg_r) ), _hint( std::move(hint_r) ) {} + + // code exception hint + Error( int exitcode_r, const zypp::Exception & ex_r, std::string hint_r = std::string() ) + : _exitcode( exitcode_r ), _msg( combine( ex_r ) ), _hint( std::move(hint_r) ) {} + + // code (msg exception) hint + Error( int exitcode_r, std::string msg_r, const zypp::Exception & ex_r, std::string hint_r = std::string() ) + : _exitcode( exitcode_r ), _msg( combine( std::move(msg_r), ex_r ) ), _hint( std::move(hint_r) ) {} + + /** Default way of processing a caught \ref Error exception. + * \li Write error message and optional hint to screen. + * \li Set the ZYPPER_EXIT_ code if necessary. + * \returns the zypper exitcode. + */ + int report( Application & app_r ) const; + + int _exitcode; //< ZYPPER_EXIT_OK indicates exitcode is already set. + std::string _msg; + std::string _hint; + +private: + static std::string combine( std::string && msg_r, const zypp::Exception & ex_r ); + static std::string combine( const zypp::Exception & ex_r ); +}; + +} + +#endif /*OUT_H_*/ diff --git a/zypp-tui/output/OutNormal.cc b/zypp-tui/output/OutNormal.cc new file mode 100644 index 0000000..de13b77 --- /dev/null +++ b/zypp-tui/output/OutNormal.cc @@ -0,0 +1,462 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include + +#include + +#include +#include // for download progress reporting +#include +#include // for toUpper() +#include + +#include +#include + +#include "OutNormal.h" + +using std::cout; +using std::cerr; +using std::endl; + +namespace ztui { + +OutNormal::OutNormal( Verbosity verbosity_r ) +: Out( TYPE_NORMAL, verbosity_r ) +, _use_colors( false ) +, _isatty( do_ttyout() ) +, _newline( true ) +, _oneup( false ) +{} + +OutNormal::~OutNormal() +{} + +bool OutNormal::mine( Type type ) +{ return( type & Out::TYPE_NORMAL ); } + +bool OutNormal::infoWarningFilter( Verbosity verbosity_r, Type mask ) +{ + if ( !mine( mask ) ) + return true; + if ( verbosity() < verbosity_r ) + return true; + return false; +} + +void OutNormal::fixupProgressNL() +{ + if ( !_newline ) // An active Progress bar is not NL terminated + cout << ansi::tty::clearLN; // Wipe it before writing out a normal line to the screen + // Alternative : cout << endl; to Keep the progress bar visible. +} + +void OutNormal::info( const std::string & msg_r, Verbosity verbosity_r, Type mask ) +{ + if ( infoWarningFilter( verbosity_r, mask ) ) + return; + + fixupProgressNL(); + + ColorString msg( msg_r, ColorContext::MSG_STATUS ); + if ( verbosity_r == Out::QUIET ) + msg = ColorContext::RESULT; + else if ( verbosity_r == Out::DEBUG ) + msg = ColorContext::OSDEBUG; + + cout << msg << endl; + _newline = true; +} + +void OutNormal::infoLine( const TermLine & msg, Verbosity verbosity_r, Type mask ) +{ info( msg.get( termwidth() ), verbosity_r, mask ); } + +void OutNormal::warning( const std::string & msg, Verbosity verbosity_r, Type mask ) +{ + if ( infoWarningFilter( verbosity_r, mask ) ) + return; + + fixupProgressNL(); + + cout << ( ColorContext::MSG_WARNING << _("Warning: ") ) << msg << endl; + _newline = true; +} + +void OutNormal::error( const std::string & problem_desc, const std::string & hint ) +{ + fixupProgressNL(); + + cerr << ( ColorContext::MSG_ERROR << problem_desc ); + if ( !hint.empty() && verbosity() > Out::QUIET ) + cerr << endl << hint; + cerr << endl; + _newline = true; +} + +// ---------------------------------------------------------------------------- + +void OutNormal::error( const zypp::Exception & e, const std::string & problem_desc, const std::string & hint ) +{ + fixupProgressNL(); + + // problem and cause + cerr << ( ColorContext::MSG_ERROR << problem_desc << endl << zyppExceptionReport(e) ) << endl; + + // hint + if ( !hint.empty() && verbosity() > Out::QUIET ) + cerr << hint << endl; + + _newline = true; +} + +// ---------------------------------------------------------------------------- +inline std::ostream & PROGRESS_FLUSH( std::ostream & str ) { + static const bool dbg = getenv("ZYPPER_PBD"); // every progress bar redraw on a single line + return (dbg ? str << std::endl : str << std::flush ); +} + +void OutNormal::displayProgress ( const std::string & s, int percent ) +{ + static AliveCursor cursor; + + if ( _isatty ) + { + TermLine outstr( TermLine::SF_CRUSH | TermLine::SF_EXPAND, '-' ); + outstr.lhs << s << ' '; + + // dont display percents if invalid + if ( percent >= 0 && percent <= 100 ) + { + outstr.percentHint = percent; + } + ++cursor; + outstr.rhs << '[' << cursor.current() << ']'; + + if ( _oneup ) + cout << ansi::tty::clearLN << ansi::tty::cursorUP; + cout << ansi::tty::clearLN; + + std::string outline( outstr.get( termwidth() ) ); + cout << outline << PROGRESS_FLUSH; + // no _oneup if CRUSHed // _oneup = ( outline.length() > termwidth() ); + } + else + cout << '.' << std::flush; +} + +// ---------------------------------------------------------------------------- + +void OutNormal::displayTick( const std::string & s ) +{ + static AliveCursor cursor; + + if ( _isatty ) + { + TermLine outstr( TermLine::SF_CRUSH | TermLine::SF_EXPAND, '-' ); + ++cursor; + outstr.lhs << s << ' '; + outstr.rhs << '[' << cursor.current() << ']'; + + if( _oneup ) + cout << ansi::tty::clearLN << ansi::tty::cursorUP; + cout << ansi::tty::clearLN; + + std::string outline( outstr.get( termwidth() ) ); + cout << outline << PROGRESS_FLUSH; + // no _oneup if CRUSHed // _oneup = ( outline.length() > termwidth() ); + } + else + cout << '.' << std::flush; +} + +// ---------------------------------------------------------------------------- +void OutNormal::progressStart( const std::string & id, const std::string & label, bool is_tick ) +{ + if ( progressFilter() ) + return; + + if ( !_isatty ) + cout << label << " ["; + + if ( is_tick ) + displayTick( label ); + else + displayProgress( label, 0 ); + + _newline = false; +} + +void OutNormal::progress( const std::string & id, const std::string & label, int value ) +{ + if (progressFilter()) + return; + + if (value) + displayProgress(label, value); + else + displayTick(label); + + _newline = false; +} + +void OutNormal::progressEnd( const std::string & id, const std::string & label, const std::string & donetag, bool error ) +{ + if ( progressFilter() ) + return; + + if ( !error && _use_colors ) + cout << ColorContext::MSG_STATUS; + + TermLine outstr( TermLine::SF_CRUSH | TermLine::SF_EXPAND, '.' ); + if ( _isatty ) + { + if ( _oneup ) + { + cout << ansi::tty::clearLN << ansi::tty::cursorUP; + _oneup = false; + } + cout << ansi::tty::clearLN; + + outstr.lhs << label << ' '; + outstr.rhs << '['; + } + // else: just write the donetag + + outstr.rhs << donetag << ']'; + + std::string outline( outstr.get( termwidth() ) ); + cout << outline << endl << std::flush; + _newline = true; + + if ( !error && _use_colors ) + cout << ColorContext::DEFAULT; +} + +// progress with download rate +void OutNormal::dwnldProgressStart( const zypp::Url & uri ) +{ + if ( verbosity() < NORMAL ) + return; + + if ( _isatty ) + cout << ansi::tty::clearLN; + + TermLine outstr( TermLine::SF_CRUSH | TermLine::SF_EXPAND, '-' ); + outstr.lhs << _("Retrieving:") << ' '; + if ( verbosity() == DEBUG ) + outstr.lhs << uri; + else + outstr.lhs << zypp::Pathname(uri.getPathName()).basename(); + outstr.lhs << ' '; + if (_isatty) + outstr.rhs << '[' << _("starting") << ']'; + else + outstr.rhs << '[' ; + + std::string outline( outstr.get( termwidth() ) ); + cout << outline << PROGRESS_FLUSH; + // no _oneup if CRUSHed // _oneup = (outline.length() > termwidth()); + + _newline = false; +} + +void OutNormal::dwnldProgress( const zypp::Url & uri, int value, long rate ) +{ + if ( verbosity() < NORMAL ) + return; + + if ( !_isatty ) + { + cout << '.' << std::flush; + return; + } + + if( _oneup ) + cout << ansi::tty::clearLN << ansi::tty::cursorUP; + cout << ansi::tty::clearLN; + + TermLine outstr( TermLine::SF_CRUSH | TermLine::SF_EXPAND, '-' ); + outstr.lhs << _("Retrieving:") << " "; + if ( verbosity() == DEBUG ) + outstr.lhs << uri; + else + outstr.lhs << zypp::Pathname(uri.getPathName()).basename(); + outstr.lhs << ' '; + + // dont display percents if invalid + if ( value >= 0 && value <= 100 ) + outstr.percentHint = value; + + static AliveCursor cursor; + ++cursor; + outstr.rhs << '[' << cursor.current(); + if ( rate > 0 ) + outstr.rhs << " (" << zypp::ByteCount(rate) << "/s)"; + outstr.rhs << ']'; + + std::string outline( outstr.get( termwidth() ) ); + cout << outline << PROGRESS_FLUSH; + // no _oneup if CRUSHed // _oneup = (outline.length() > termwidth()); + _newline = false; +} + +void OutNormal::dwnldProgressEnd( const zypp::Url & uri, long rate, zypp::TriBool error ) +{ + if ( verbosity() < NORMAL ) + return; + + if ( bool(!error) && _use_colors ) + cout << ColorContext::MSG_STATUS; + + TermLine outstr( TermLine::SF_CRUSH | TermLine::SF_EXPAND, '.' ); + if ( _isatty ) + { + if( _oneup ) + cout << ansi::tty::clearLN << ansi::tty::cursorUP; + cout << ansi::tty::clearLN; + outstr.lhs << _("Retrieving:") << " "; + if ( verbosity() == DEBUG ) + outstr.lhs << uri; + else + outstr.lhs << zypp::Pathname(uri.getPathName()).basename(); + outstr.lhs << ' '; + outstr.rhs << '['; + if ( zypp::indeterminate( error ) ) + // Translator: download progress bar result: "........[not found]" + outstr.rhs << CHANGEString(_("not found") ); + else if ( error ) + // Translator: download progress bar result: "............[error]" + outstr.rhs << NEGATIVEString(_("error") ); + else + // Translator: download progress bar result: ".............[done]" + outstr.rhs << _("done"); + } + else + outstr.rhs << ( zypp::indeterminate( error ) ? _("not found") : ( error ? _("error") : _("done") ) ); + + if ( rate > 0 ) + outstr.rhs << " (" << zypp::ByteCount(rate) << "/s)"; + outstr.rhs << ']'; + + std::string outline( outstr.get( termwidth() ) ); + cout << outline << endl << std::flush; + _newline = true; + + if ( bool(!error) && _use_colors ) + cout << ColorContext::DEFAULT; +} + +void OutNormal::prompt( PromptId id, const std::string & prompt, const PromptOptions & poptions, const std::string & startdesc ) +{ + fixupProgressNL(); + + if ( startdesc.empty() ) + { + if ( _isatty ) + cout << ansi::tty::clearLN; + } + else + cout << startdesc << endl; + + std::ostringstream pstr; + ColorStream cout( pstr, ColorContext::PROMPT ); // scoped color on std::cout + + cout << prompt; + if ( ! poptions.empty() ) + cout << text::optBlankAfter(prompt) << ColorString( poptions.optionString() ); + cout << ": "; + + if ( do_colors() ) + { + // bsc#948566: Terminal is dumb and simply counts the amount of printable + // characters. If the number of printable characters within ansi SGR sequences + // is not a multiple of 8, tab stops are not computed correctly. We use + // superfluous resets ("\033[0m"; 3 printable chars) to fill up. + // Better ideas are welcome. + size_t invis = 0; + bool insgr = false; + for ( char ch : pstr.str() ) + { + if ( insgr ) + { + ++invis; + if ( ch == 'm' ) + insgr = false; + } + else if ( ch == '\033' ) + insgr = true; + } + invis %= 8; + + if ( invis ) + { + // "\033[0m" has 3 printable chars: + // ( resets[to fill] * 3 ) % 8 == to fill + // 0 1 2 3 4 5 6 7 + static const size_t resets[] = { 0,3,6,1,4,7,2,5 }; + for ( size_t i = resets[8-invis]; i; --i ) + cout << ansi::Color::SGRReset(); + } + } + + std::cout << pstr.str() << std::flush; + // prompt ends with newline (user hits ) unless exited abnormaly + _newline = true; +} + +void OutNormal::promptHelp( const PromptOptions & poptions ) +{ + cout << endl; + + if ( poptions.helpEmpty() ) + cout << _("No help available for this prompt.") << endl; + + // Nevertheless list all option names and their '#NUM' shortcut + unsigned pos = 0; // Userland counter #NUM (starts with #1) + + zypp::str::Format fopt { "#%-2d: %-10s" }; + for ( unsigned idx = 0; idx < poptions.options().size(); ++idx ) + { + if ( poptions.isDisabled(idx) ) + continue; + + cout << ( fopt % ++pos % poptions.options()[idx] ); + if ( ! poptions.helpEmpty() ) + { + const std::string & help { poptions.optionHelp(idx) }; + cout << " - "; + if ( help.empty() ) + cout << ( ColorContext::LOWLIGHT << "(" << _("no help available for this option") << ")" ); + else + cout << help; + } + cout << endl; + } + + ColorStream cout( std::cout, ColorContext::PROMPT ); // scoped color on std::cout + cout << endl << ColorString( poptions.optionString() ) << ": " << std::flush; + // prompt ends with newline (user hits ) unless exited abnormaly + _newline = true; +} + +unsigned OutNormal::termwidth() const +{ + if ( _isatty ) + { + struct winsize wns; + if ( !ioctl( 1, TIOCGWINSZ, &wns ) ) + return wns.ws_col; + } + return Out::termwidth(); // unlimited +} + +} diff --git a/zypp-tui/output/OutNormal.h b/zypp-tui/output/OutNormal.h new file mode 100644 index 0000000..144ea6a --- /dev/null +++ b/zypp-tui/output/OutNormal.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef OUTNORMAL_H_ +#define OUTNORMAL_H_ + +#include +#include +#include + +namespace ztui { + +class OutNormal : public Out +{ +public: + OutNormal(Verbosity verbosity = NORMAL); + ~OutNormal() override; + +public: + void info( const std::string & msg, Verbosity verbosity, Type mask ) override; + void infoLine( const TermLine & msg, Verbosity verbosity, Type mask ) override; + void warning( const std::string & msg, Verbosity verbosity, Type mask ) override; + void error( const std::string & problem_desc, const std::string & hint ) override; + void error( const zypp::Exception & e, const std::string & problem_desc, const std::string & hint ) override; + + // progress + void progressStart( const std::string & id, const std::string & label, bool is_tick ) override; + void progress( const std::string & id, const std::string & label, int value ) override; + void progressEnd( const std::string & id, const std::string & label, const std::string & donetag, bool error) override; + + // progress with download rate + void dwnldProgressStart( const zypp::Url & uri ) override; + void dwnldProgress( const zypp::Url & uri, int value, long rate ) override; + void dwnldProgressEnd( const zypp::Url & uri, long rate, zypp::TriBool error ) override; + + void prompt( PromptId id, const std::string & prompt, const PromptOptions & poptions, const std::string & startdesc ) override; + + void promptHelp( const PromptOptions & poptions ) override; + + void setUseColors( bool value ) override + { _use_colors = value; } + +protected: + bool mine( Type type ) override; + + /* Return current terminal width or 'unsigned(-1)' when failed */ + unsigned termwidth() const override; + +private: + bool infoWarningFilter(Verbosity verbosity, Type mask); + void fixupProgressNL(); //< Make sure we're at BOL even if a ProgressBar is active + void displayProgress(const std::string & s, int percent); + void displayTick(const std::string & s); + + bool _use_colors; + bool _isatty; + /* Newline flag. false if the last output did not end with new line character + * (like in a self-overwriting progress line), false otherwise. */ + bool _newline; + /* True if the last output line was longer than the terminal width */ + bool _oneup; +}; + +} + +#endif /*OUTNORMAL_H_*/ diff --git a/zypp-tui/output/PromptOptions b/zypp-tui/output/PromptOptions new file mode 100644 index 0000000..028b1d8 --- /dev/null +++ b/zypp-tui/output/PromptOptions @@ -0,0 +1 @@ +#include "promptoptions.h" diff --git a/zypp-tui/output/Utf8.h b/zypp-tui/output/Utf8.h new file mode 100644 index 0000000..4a9e24d --- /dev/null +++ b/zypp-tui/output/Utf8.h @@ -0,0 +1,197 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_OUTPUT_UTF8_H_ +#define ZYPP_TUI_OUTPUT_UTF8_H_ + +#include +#include +#include + +#include +#include +#include + +namespace ztui { + +/////////////////////////////////////////////////////////////////// +namespace utf8 +{ + /** Simple utf8 string */ + class string + { + public: + using size_type = std::string::size_type; + static const size_type npos = std::string::npos; + + public: + string() {} + string( const char * rhs ) : _str( rhs ) {} + string( std::string rhs ) : _str(std::move( rhs )) {} + + public: + const char * c_str() const { return _str.c_str(); } + const std::string & str() const { return _str; } + std::string & str() { return _str; } + + public: + /** utf8 size */ + size_type size() const + { + // test for locales using dual width fonts: + static bool isCJK = []()->bool { + const char * lang = ::getenv( "LANG" ); + return ( lang && ( !strncmp( lang, "zh", 2 ) + || !strncmp( lang, "ko", 2 ) + || !strncmp( lang, "ja", 2 ) ) ); + }(); + + if ( isCJK ) + { + // this should actually be correct for ALL locales: + size_type len = 0; + const char *s = _str.c_str(); + for ( size_type slen = _str.size(); slen > 0; ) + { + if ( *s == '\033' && *(s+1) == '[' ) // skip ansi SGR + { + slen -= 2; s += 2; + while ( slen > 0 && *s != 'm' ) + { --slen; ++s; } + if ( slen > 0 ) + { --slen; ++s; } + continue; + } + + wchar_t wc = 0; + size_t bytes = mbrtowc( &wc, s, slen, NULL ); + if ( bytes <= 0 ) + break; + len += wcwidth( wc ); + slen -= bytes; + s += bytes; + } + return len; + } + + // NON CJK: faster and hopefully accurate enough: + // simply do not count continuation bytes '10xxxxxx' + size_type ret = _str.size(); + size_type ansi = 0; + for ( auto ch : _str ) + { + if ( ansi ) + { + if ( ansi == 1 && ch == '[' ) + { + ansi = 2; + continue; + } + else if ( ansi >= 2 ) // not testing for in [0-9;m] + { + ++ansi; + if ( ch == 'm' ) // SGR end + { ret -= ansi; ansi = 0; } + continue; + } + } + + if ( isContinuationByte( ch ) ) + --ret; + else if ( ch == '\033' ) + ansi = 1; + } + return ret; + } + + /** \overload std::string has both too */ + size_type length() const + { return size(); } + + /** utf8 substring */ + string substr( size_type pos_r = 0, size_type len_r = npos ) const + { + size_type p = upos( pos_r ); + size_type l = upos( len_r, p ); + return string( _str.substr( p, ( l == npos ? npos : l-p ) ) ); + } + + private: + /** Test for continuation byte \c '10xxxxxx' */ + bool isContinuationByte( char ch ) const + { return( (ch & 0xC0) == 0x80 ); } + + /** Return start of codepoint \a pos_r starting at position \c start_r. */ + size_type upos( size_type pos_r, size_type start_r = 0 ) const + { + if ( pos_r == npos || start_r > _str.size() ) + return npos; + + size_type upos = start_r; + for ( const char * chp = _str.c_str() + upos; *chp; ++chp, ++upos ) + { + if ( ! isContinuationByte( *chp ) ) + { + if ( pos_r ) + --pos_r; + else + return upos; + + while ( *chp == '\033' && *(chp+1) == '[' ) // skip any ansi SGR + { + chp += 2; + upos += 2; + while ( *chp && *chp != 'm' ) + { ++chp; ++upos; } + if ( *chp ) + { ++chp; ++upos; } + else + break; // incomplete ansi SGR + } + if ( ! *chp ) + break; // incomplete ansi SGR + } + } + return( pos_r ? npos : upos ); + } + + private: + std::string _str; + }; + + /** \relates string concatenation */ + inline string operator+( const string & lhs, const string & rhs ) + { return string( lhs.str() + rhs.str() ); } + /** \overload */ + inline string operator+( const string & lhs, const std::string & rhs ) + { return string( lhs.str() + rhs ); } + /** \overload */ + inline string operator+( const std::string & lhs, const string & rhs ) + { return string( lhs + rhs.str() ); } + /** \overload */ + inline string operator+( const string & lhs, const char * rhs ) + { return string( lhs.str() + rhs ); } + /** \overload */ + inline string operator+( const char * lhs, const string & rhs ) + { return string( lhs + rhs.str() ); } + + /** \relates string Stream output */ + inline std::ostream & operator<<( std::ostream & str, const string & obj ) + { return str << obj.str(); } + +} // namespace utf8 +/////////////////////////////////////////////////////////////////// + +} + +#endif // ZYPP_TUI_OUTPUT_UTF8_H_ diff --git a/zypp-tui/output/promptoptions.cc b/zypp-tui/output/promptoptions.cc new file mode 100644 index 0000000..85af05a --- /dev/null +++ b/zypp-tui/output/promptoptions.cc @@ -0,0 +1,196 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include "promptoptions.h" + +#include +#include +#include + +namespace ztui { + + // ---------------------------------------------------------------------------- + + PromptOptions::PromptOptions( StrVector options_r, unsigned defaultOpt_r ) + { setOptions( std::move(options_r), defaultOpt_r ); } + + PromptOptions::PromptOptions( const std::string & optionstr_r, unsigned defaultOpt_r ) + { setOptions( optionstr_r, defaultOpt_r ); } + + // ---------------------------------------------------------------------------- + + PromptOptions::~PromptOptions() + {} + + // ---------------------------------------------------------------------------- + + void PromptOptions::setOptions( StrVector options_r, unsigned defaultOpt_r ) + { + _options.swap( options_r ); + if ( _options.size() <= defaultOpt_r ) + { + INT << "Invalid default option index " << defaultOpt_r << std::endl; + _default = 0; + } + else + _default = defaultOpt_r; + } + + void PromptOptions::setOptions( const std::string & optionstr_r, unsigned defaultOpt_r ) + { + StrVector options; + zypp::str::split( optionstr_r, back_inserter(options), "/" ); + setOptions( std::move(options), defaultOpt_r ); + } + + ColorString PromptOptions::optionString() const + { + bool hidden = false; // have enabled options not shown at the prompt (/...)? + unsigned shown = 0; + unsigned showmax = ( _shown_count < 0 ? _options.size() : (unsigned)_shown_count ); + + std::ostringstream str; + str << "["; + + const char * slash = ""; // "/" after the 1st option + for ( unsigned idx = 0; idx < _options.size(); ++idx ) + { + if ( isDisabled(idx) ) + continue; + + if ( shown < showmax ) + { + str << slash << ( ColorContext::PROMPT_OPTION << _options[idx] ); + if ( !shown ) slash = "/"; + ++shown; + } + else + { + hidden = true; + break; // don't mind how many + } + } + + if ( hidden || !_opt_help.empty() ) + { + str << slash << ( hidden ? "..." : "" ) << ( ColorContext::PROMPT_OPTION << "?" ); + if ( hidden ) + // translators: Press '?' to see all options embedded in this prompt: "Continue? [y/n/? shows all options] (y):" + str << " " << _("shows all options"); + } + + str << "]"; + + if ( !_options.empty() ) + str << " (" << ( ColorContext::PROMPT_OPTION << _options[_default] ) << ")"; + + return ColorString( str.str() ); + } + + + void PromptOptions::setOptionHelp( unsigned opt, const std::string & help_str ) + { + if ( help_str.empty() ) + return; + + if ( opt >= _options.size() ) + { + WAR << "attempt to set option help for non-existing option." + << " text: " << help_str << std::endl; + return; + } + + if ( opt >= _opt_help.capacity() ) + _opt_help.reserve( _options.size() ); + if ( opt >= _opt_help.size( )) + _opt_help.resize( _options.size() ); + + _opt_help[opt] = help_str; + } + + std::vector PromptOptions::getReplyMatches( const std::string & reply_r ) const + { + std::vector ret; + + // #NUM ? (direct index into option vector) + if ( reply_r[0] == '#' && reply_r[1] != '\0' ) + { + unsigned num = 0; // -1 : if no match + for ( const char * cp = reply_r.c_str()+1; *cp; ++cp ) + { + if ( '0' <= *cp && *cp <= '9' ) + { + num *= 10; + num += (*cp-'0'); + } + else + { + num = unsigned(-1); + break; + } + } + + if ( num != unsigned(-1) ) + { + // userland counting! #1 is the 1st (enabled) option (#0 will never match) + if ( num != 0 ) + { + for ( unsigned i = 0; i < _options.size(); ++i ) + { + if ( isDisabled(i) ) + continue; + + if ( --num == 0 ) + { + ret.push_back( i ); + break; + } + } + } + return ret; // a match - good or bad - will be eaten + } + // no match falls through.... + } + + const std::string & lreply { zypp::str::toLower( reply_r ) }; + for ( unsigned i = 0; i < _options.size(); ++i ) + { + if ( isDisabled(i) ) + continue; + + const std::string & lopt { zypp::str::toLower( _options[i] ) }; + + if ( lopt == lreply ) { // prefer an exact match ("1/11") + ret.clear(); + ret.push_back( i ); + break; + } + else if ( zypp::str::hasPrefix( lopt, lreply ) ) + ret.push_back( i ); + } + + return ret; + } + + std::string PromptOptions::replyMatchesStr( const std::vector & matches_r ) const + { + zypp::str::Str str; + const char * sep = "("; // "," after the 1st option + for ( unsigned idx : matches_r ) + { + str << sep << _options[idx]; + if ( *sep != ',' ) sep =","; + } + return str << ")"; + } + + bool PromptOptions::isYesNoPrompt() const + { return _options.size() == 2 && _options[0] == _("yes") && _options[1] == _("no"); } + +} diff --git a/zypp-tui/output/promptoptions.h b/zypp-tui/output/promptoptions.h new file mode 100644 index 0000000..1e393d3 --- /dev/null +++ b/zypp-tui/output/promptoptions.h @@ -0,0 +1,121 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_OUTPUT_PROMPTOPTIONS_H_INCLUDED +#define ZYPP_TUI_OUTPUT_PROMPTOPTIONS_H_INCLUDED + +#include +#include +#include + +#include + +namespace ztui { + + /** + * Example: + * + * PromptOptions popts; + * popts.setOptions(_("y/n/p"), 0 / * default reply * /); + * popts.setOptionHelp(0, _("Help for option 'y'")); + * popts.setOptionHelp(1, _("Help for option 'n'")); + * ... + * zypper.out().prompt(PROMPT_YN_INST_REMOVE_CONTINUE, prompt_text, popts); + * unsigned reply = + * get_prompt_reply(zypper, PROMPT_YN_INST_REMOVE_CONTINUE, popts); + * + */ + class PromptOptions + { + public: + using StrVector = std::vector; + + /** + * Default c-tor. + */ + PromptOptions() {}; + + /** Ctor taking the option values as vector */ + PromptOptions( StrVector options_r, unsigned defaultOpt_r ); + + /** + * Constructor. + * + * \param optionstr_r translated option string containing one or more + * options separated by slash '/' character + * e.g. "yes/no/?" or "1/s/r/c" + * \param defaultOpt_r index of the default answer within the \a option_str + */ + PromptOptions( const std::string & optionstr_r, unsigned defaultOpt_r ); + + /** D-tor */ + ~PromptOptions(); + + const StrVector & options() const { return _options; } + void setOptions( StrVector options_r, unsigned defaultOpt_r ); + void setOptions( const std::string & optionstr_r, unsigned defaultOpt_r ); + + unsigned defaultOpt() const { return _default; } + /** Option string (may have embedded color codes) */ + ColorString optionString() const; + bool empty() const { return _options.empty(); } + bool isYesNoPrompt() const; + + const std::string & optionHelp(unsigned opt) const + { static std::string empty; return opt < _opt_help.size() ? _opt_help[opt] : empty; } + //const std::string getOptionHelp(const std::string & opt_str); + void setOptionHelp(unsigned opt, const std::string & help_str); + bool helpEmpty() const { return _opt_help.empty(); } + + bool isEnabled(unsigned opt) const + { return !isDisabled(opt); } + bool isDisabled(unsigned opt) const + { return _disabled.count(opt); } + void disable(unsigned opt) + { _disabled.insert(opt); } + void enable(unsigned opt) + { _disabled.erase(opt); } + void enableAll() + { _disabled.clear(); } + + unsigned shownCount() const + { return _shown_count; } + void setShownCount(unsigned count) + { _shown_count = count; } + + /** Return the indices of option string matches (lowercase/prefix or #NUM). */ + std::vector getReplyMatches( const std::string & reply_r ) const; + /** The returned reply matches as '(,)' list. */ + std::string replyMatchesStr( const std::vector & matches_r ) const; + + private: + /** option strings */ + StrVector _options; + /** index of the default option */ + unsigned _default = 0; + /** help strings corresponding to options */ + StrVector _opt_help; + /** set of options to ignore */ + std::set _disabled; + /** + * Number of options to show (the rest will still be available and visible + * through '?' help). If negative, all options will be shown. Zero is allowed. + */ + int _shown_count = -1; + }; + + + +} + +#endif // ZYPP_TUI_OUTPUT_PROMPTOPTIONS_H_INCLUDED diff --git a/zypp-tui/utils/ansi.h b/zypp-tui/utils/ansi.h new file mode 100644 index 0000000..ffb9afe --- /dev/null +++ b/zypp-tui/utils/ansi.h @@ -0,0 +1,864 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_UTILS_ANSI_H +#define ZYPP_TUI_UTILS_ANSI_H + +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace ztui { + +/** True unless output is a dumb tty or file. + * In this case we should not use any ANSI Escape sequences moving the cursor. + */ +bool do_ttyout(); // implemented in colors.cc + +/** If output is done in colors (depends on config) */ +bool do_colors(); // implemented in colors.cc + +/** Simple check whether stdout is a (not dumb) tty */ +bool mayUseANSIEscapes(); + +/** Simple check whether stdout can handle colors */ +bool hasANSIColor(); + +/////////////////////////////////////////////////////////////////// +namespace ansi +{ + /////////////////////////////////////////////////////////////////// + namespace tty + { + /////////////////////////////////////////////////////////////////// + /// \class EscapeSequence + /// \brief ANSI Escape sequences and their fallback if no tty + /////////////////////////////////////////////////////////////////// + class EscapeSequence + { + public: + EscapeSequence( const char * ansi_r, const char * fallback_r = "" ) + : _seq( ansi_r ) + , _fbck( fallback_r ) + {} + + const char * str() const + { + if ( _fbck ) // determine _seq<>_fbck on 1st use (dtor is too early as do_ttyout() is not yet ready) + { + if ( ! do_ttyout() ) + _seq = _fbck; + _fbck = nullptr; + } + return _seq; + } + + private: + mutable const char * _seq; + mutable const char * _fbck; + }; + + /** \relates EscapeSequence stream output */ + inline std::ostream & operator<<( std::ostream & str, const EscapeSequence & obj ) + { return str << obj.str(); } + + + // EscapeSequence definitions in colors.cc + + extern const EscapeSequence clearLN; ///< Clear entire line + + extern const EscapeSequence cursorUP; ///< Cursor up 1 line + extern const EscapeSequence cursorDOWN; ///< Cursor down 1 line + extern const EscapeSequence cursorRIGHT; ///< Cursor right 1 char + extern const EscapeSequence cursorLEFT; ///< Cursor left 1 char + + } // namespace tty + /////////////////////////////////////////////////////////////////// + +#define ZYPPER_TRACE_SGR 0 +#undef ESC +#if ( ZYPPER_TRACE_SGR < 2 ) +#define ESC "\033" +#else +#define ESC "@" +#endif + /////////////////////////////////////////////////////////////////// + /// \class ColorTraits + /// \brief Traits class to enable custom \ref Color construction + /// + /// This enables using user types (usaually enums) to be used as \ref Color + /// with \ref ColorString or \ref ColorStream classes: + /// \code + /// enum ColorContext { Red, Green, Blue }; + /// + /// cout << "default" + /// << ( ColorContext::Green << "green" + /// << ColorContext::Red << "switch to red" + /// << ( ColorContext::Blue << "blue" ) + /// << "still red" ) + /// << "default" << endl; + /// \endcode + /// + /// You need to define a function ansi::Color customColorCtor( EnumType enum_r ) + /// which associates enum value and \ref Color: + /// \code + /// ansi::Color customColorCtor( ColorContext ctxt_r ) + /// { return Color associated with each enum value } + /// \endcode + /// + /// Then specailize \ref ColorTraits for your enum to enable using it as \ref ColorStream + /// \code + /// namespace ansi + /// { + /// template<> + /// struct ColorTraits + /// { enum { customColorCtor = true }; }; + /// } + /// \endcode + /// + /// This will enable your enum being impicitly converted into ansi::Color, especially + /// when used together with \ref ColorString and \ref ColorStream. Printing your enum + /// on a stream, will also print the associated colors SGR sequence: + /// \code + /// // provided via ColorTraits: + /// std::ostream & operator<<( std::ostream & str, ColorContext obj ) + /// { return str << ansi::Color( obj ); } + /// \endcode + /////////////////////////////////////////////////////////////////// + template + struct ColorTraits + { enum { customColorCtor = false }; }; + + // enabled via ctor Color::Constant -> Color + /** \relates ColorTraits SFINAE: hide template signatures unless enum is enabled in \ref ColorTraits */ + template + using EnableIfCustomColorCtor = std::enable_if_t< ansi::ColorTraits>::customColorCtor >; + + /** \relates ColorTraits SFINAE: hide template signatures unless enum is enabled in \ref ColorTraits */ + template + using DisableIfCustomColorCtor = std::enable_if_t< !ansi::ColorTraits>::customColorCtor >; + + /////////////////////////////////////////////////////////////////// + /// \class Color + /// \brief Various ways to define ansi SGR sequences. + /// + /// Any color component (\ref Attr, \ref Fg, \ref Bg) may have the + /// value \c Uchanged, indicating that this component should remain + /// unchanged when the terminal color is set. To mimic this use + /// \ref operator<<= which updates a color by omitting \c Unchanged + /// components. + ///nocolor + /// \note The function \ref do_colors determines if ansi SGR sequences + /// are generated for colors at all. + /// + /////////////////////////////////////////////////////////////////// + class Color + { + public: + /** Color attributes */ + enum class Attr : std::uint8_t + { Unchanged, Normal, Bright, Reverse }; + + /** Foreground colors */ + enum class Fg : std::uint8_t + { Unchanged, Default, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White }; + + /** Backgroud colors */ + enum class Bg : std::uint8_t + { Unchanged, Default, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White }; + + /** Color unique id type */ + using UidType = std::uint32_t; + + /** Predefined (foregreound) color contants + * Intentionally not an enum class, so it can be used as + * \c Color::Red, \c Color::Default, etc. + */ + enum Constant : std::uint8_t + { + Black, BrightBlack, // BrightBlack = Darkgray + Red, BrightRed, + Green, BrightGreen, + Yellow, BrightYellow, // Yellow = Brown on Standard VGA + Blue, BrightBlue, + Magenta, BrightMagenta, + Cyan, BrightCyan, + White, BrightWhite, // White = Gray + Default, BrightDefault + }; + + public: + /** Default ctor: terminal default color */ + Color() + : _comp( Attr::Normal, Fg::Default, Bg::Default ) + {} + + Color( Attr attr_r, Fg fg_r = Fg::Unchanged, Bg bg_r = Bg::Unchanged ) + : _comp( attr_r, fg_r, bg_r ) + {} + + Color( Attr attr_r, Bg bg_r ) + : _comp( attr_r, Fg::Unchanged, bg_r ) + {} + + Color( Fg fg_r, Bg bg_r = Bg::Unchanged ) + : _comp( Attr::Unchanged, fg_r, bg_r ) + {} + + Color( Bg bg_r ) + : _comp( Attr::Unchanged, Fg::Unchanged, bg_r ) + {} + + /** Color constant combined with background (\ref Bg::Default) */ + Color( Constant color_r, Bg bg_r = Bg::Default ) + : _comp( ( color_r % 2 ? Attr::Bright : Attr::Normal ), Fg::Default, bg_r ) + { + switch ( color_r ) + { + case Black: + case BrightBlack: _comp.fg = Fg::Black; break; + case Red: + case BrightRed: _comp.fg = Fg::Red; break; + case Green: + case BrightGreen: _comp.fg = Fg::Green; break; + case Yellow: + case BrightYellow: _comp.fg = Fg::Yellow; break; + case Blue: + case BrightBlue: _comp.fg = Fg::Blue; break; + case Magenta: + case BrightMagenta: _comp.fg = Fg::Magenta; break; + case Cyan: + case BrightCyan: _comp.fg = Fg::Cyan; break; + case White: + case BrightWhite: _comp.fg = Fg::White; break; + default: + case Default: + case BrightDefault: break; + } + } + + /** Custom ctor from ColorTraits enabled type */ + template> + Color( CCC_ && color_r ) + : Color( customColorCtor( std::forward(color_r) ) ) + {} + + public: + /** Leave everything unchanged */ + static Color nocolor() + { return Color( UidType(0) ); } + + /*! + * Returns the Color corresponding to the \a colorName. + * If \a colorName does not match a known string this returns the + * same as \ref nocolor. + * + * \code + * Color::fromString("bold red"); + * \endcode + * + */ + static Color fromString( const std::string &colorName ); + + /** Evaluate in boolean context (not \ref nocolor) */ + explicit operator bool() const + { return uid(); } + + /** ANSI SGR sesquence to reset all attributes + * \note Printing this SGR sequence has the same visible effect as setting + * \ref Color::Default. Classes supporting re-coloring, like \ref ColorString, + * however differ between both. While Color::Default is a color to use, + * thus to keep when re-coloring, \ref SGRReset is used as placeholder for + * later coloring. + */ + static const std::string & SGRReset() + { +#if ( ZYPPER_TRACE_SGR ) + static const std::string & _reset( *(new std::string( ESC"[0m[!]" )) ); // live until program ends +#else + static const std::string & _reset( *(new std::string( ESC"[0m" )) ); // live until program ends +#endif + static const std::string & _noreset( *(new std::string( "" )) ); // live until program ends + if(!do_colors()) return _noreset; + return _reset; + } + + public: + /** Update Color (assign components which are not \c Unchanged in rhs ) */ + Color & operator<=( Color rhs ) + { + if ( rhs._comp.attr != Attr::Unchanged ) _comp.attr = rhs._comp.attr; + if ( rhs._comp.fg != Fg::Unchanged ) _comp.fg = rhs._comp.fg; + if ( rhs._comp.bg != Bg::Unchanged ) _comp.bg = rhs._comp.bg; + return *this; + } + /** \overload */ + Color & operator<=( Color::Attr rhs ) + { if ( rhs != Attr::Unchanged ) _comp.attr = rhs; return *this; } + /** \overload */ + Color & operator<=( Color::Fg rhs ) + { if ( rhs != Fg::Unchanged ) _comp.fg = rhs; return *this; } + /** \overload */ + Color & operator<=( Color::Bg rhs ) + { if ( rhs != Bg::Unchanged ) _comp.bg = rhs; return *this; } + /** \overload */ + inline Color & operator<=( Color::Constant rhs ); + + /** Return updated color */ + Color operator<( Color rhs ) const + { return Color(*this) <= rhs; } + /** \overload */ + Color operator<( Color::Attr rhs ) const + { return Color(*this) <= rhs; } + /** \overload */ + Color operator<( Color::Fg rhs ) const + { return Color(*this) <= rhs; } + /** \overload */ + Color operator<( Color::Bg rhs ) const + { return Color(*this) <= rhs; } + /** \overload */ + inline Color operator<( Color::Constant rhs ) const; + + public: + Attr attr() const + { return _comp.attr; } + + Color & attr( Attr attr_r ) + { _comp.attr = attr_r; return *this; } + + Fg fg() const + { return _comp.fg; } + + Color & fg( Fg fg_r ) + { _comp.fg = fg_r; return *this; } + + Bg bg() const + { return _comp.bg; } + + Color & bg( Bg bg_r ) + { _comp.bg = bg_r; return *this; } + + /** Each color has a unique numeric id */ + UidType uid() const + { return _comp.uid; } + + /** The colors SGRsequence if \ref do_colors is \c true */ + const std::string & str() const + { return genSGR( *this ); } + + /** The colors SGRsequence human readable */ + std::string debugstr() const + { return genSGR( *this ).c_str()+1; } + + public: + /** \relates Color */ + friend inline bool operator==( Color lhs, Color rhs ) + { return( lhs.uid() == rhs.uid() ); } + + /** \relates Color */ + friend inline bool operator!=( Color lhs, Color rhs ) + { return ! ( lhs == rhs ); } + + private: + /** Return a colors SGRsequence if \ref do_colors retruns \c true */ + static std::string & genSGR( Color color_r ) + { + static std::map & _def( *(new std::map) ); // live until program ends + + if ( ! ( color_r && do_colors() ) ) // nocolor, all ::Unchanged, uid 0: return empty string + { +#if ( ZYPPER_TRACE_SGR ) + std::string & ret( _def[0] ); + if ( ret.empty() ) + ret = "[]"; + return ret; +#else + return _def[0]; +#endif + } + + std::string & ret( _def[color_r._comp.uid] ); + if ( ret.empty() ) + { + ret += ESC"["; + switch ( color_r._comp.attr ) + { + case Attr::Normal: ret += "22;27;"; break; + case Attr::Bright: ret += "1;"; break; + case Attr::Reverse: ret += "7;"; break; + default: + case Attr::Unchanged: break; + } + switch ( color_r._comp.fg ) + { + case Fg::Black: ret += "30;"; break; + case Fg::Red: ret += "31;"; break; + case Fg::Green: ret += "32;"; break; + case Fg::Yellow: ret += "33;"; break; + case Fg::Blue: ret += "34;"; break; + case Fg::Magenta: ret += "35;"; break; + case Fg::Cyan: ret += "36;"; break; + case Fg::White: ret += "37;"; break; + case Fg::Default: ret += "39;"; break; + default: + case Fg::Unchanged: break; + } + switch ( color_r._comp.bg ) + { + case Bg::Black: ret += "40;"; break; + case Bg::Red: ret += "41;"; break; + case Bg::Green: ret += "42;"; break; + case Bg::Yellow: ret += "43;"; break; + case Bg::Blue: ret += "44;"; break; + case Bg::Magenta: ret += "45;"; break; + case Bg::Cyan: ret += "46;"; break; + case Bg::White: ret += "47;"; break; + case Bg::Default: ret += "49;"; break; + default: + case Bg::Unchanged: break; + } + *ret.rbegin() = 'm'; // turn trailing ';' into 'm' +#if ( ZYPPER_TRACE_SGR ) + ret += ( color_r == Color() ? "[*]" : "[@]" ); +#endif + } + return ret; + } + + private: + /** ctor nocolor, all ::Unchanged, uid 0 */ + Color ( UidType ) {} + + union Comp { + Comp() // nocolor, all ::Unchanged, uid 0 + : uid( 0 ) + {} + + Comp( Attr attr_r, Fg fg_r, Bg bg_r ) + : attr( attr_r ), fg( fg_r ), bg( bg_r ), _f( 0 ) + {} + + struct { + Color::Attr attr; // std::uint8_t + Color::Fg fg; // std::uint8_t + Color::Bg bg; // std::uint8_t + std::uint8_t _f; // std::uint8_t + }; + UidType uid; // std::uint32_t + } _comp; + }; + + template<> + struct ColorTraits + { enum { customColorCtor = true }; }; // enabled via ctor Color::Constant -> Color + + // Implememtation after ColorTraits instantiation ! + Color & Color::operator<=( Color::Constant rhs ) { return this->operator<=( Color( rhs, Bg::Unchanged ) ); } + Color Color::operator<( Color::Constant rhs ) const { return Color(*this) <= rhs; } + + /** \relates Color Print the colors SGRsequence if \ref do_colors is \c true */ + inline std::ostream & operator<<( std::ostream & str, Color obj ) + { return str << obj.str(); } + + /////////////////////////////////////////////////////////////////// + /// \class ColorString + /// \brief Colored string if \ref do_colors + /// + /// Stores a plain std::string (which may have color codes embedded) + /// along with a \ref Color. Retrieving the string will render + /// all uncolored (\ref Color::nololor) parts of the string in the + /// \ref Color. + /// + /// In contrary to a \ref ColorStream you can change the basic color + /// of the string without losing embedded highlights. + /// + /// \note Printing a \ref ColorString renderd in \ref Color::noclolor + /// on a \ref ColorStream will render the string in the ColorStreams + /// color. + /////////////////////////////////////////////////////////////////// + class ColorString + { + public: + ColorString() + : _color( Color::nocolor() ) + {} + + /** Ctor from color */ + explicit ColorString( Color color_r ) + : _color( color_r ) + {} + + /** Ctor from string */ + explicit ColorString( const std::string & str_r ) + : _str( str_r ) + , _color( Color::nocolor() ) + {} + /** \overload moving */ + explicit ColorString( std::string && str_r ) + : _str( std::move(str_r) ) + , _color( Color::nocolor() ) + {} + + /** Ctor from string and color */ + ColorString( const std::string & str_r, Color color_r ) + : _str( str_r ) + , _color( color_r ) + {} + /** \overload moving */ + ColorString( std::string && str_r, Color color_r ) + : _str( std::move(str_r) ) + , _color( color_r ) + {} + + /** Ctor from color and string */ + ColorString( Color color_r, const std::string & str_r ) + : _str( str_r ) + , _color( color_r ) + {} + /** \overload moving */ + ColorString( Color color_r, std::string && str_r ) + : _str( std::move(str_r) ) + , _color( color_r ) + {} + + public: + /** Assign new string */ + ColorString & operator=( const std::string & str_r ) + { _str = str_r; return *this; } + /** \overload moving */ + ColorString & operator=( std::string && str_r ) + { _str = std::move(str_r); return *this; } + + /////////////////////////////////////////////////////////////////// + // Append via '<<' (not '+=' '+') because it's + // strictly evaluated left-to-right: + // + // ColorString sep( "-", Color::Cyan ); + // ColorString ver( "version" ); + // + // ver << sep << "release"; // + prints "-" in cyan :) + // + // ver += sep + "release"; // - prints "-release" in cyan :( + // ver += sep += "release"; // - prints "-release" in cyan :( + // (ver += sep) += "release"; // + but ugly syntax + // + /** Append a \Ref ColorString */ + ColorString & operator<<( const ColorString & rhs ) + { _str += rhs.str(); return *this; } + + /** Append a string */ + ColorString & operator<<( const std::string & str_r ) + { _str += str_r; return *this; } + + public: + /** Assign \ref Color */ + ColorString & operator=( Color color_r ) + { _color = color_r; return *this; } + + /** Update \ref Color */ + ColorString & operator<=( Color color_r ) + { _color <= color_r; return *this; } + + /** Return a copy with different color. */ + ColorString operator()( Color color_r ) const + { return ColorString( _str, color_r ); } + + public: + /** Return strings \ref Color */ + Color color() const + { return _color; } + + public: + /** Whether the underlying string is empty */ + bool empty() const + { return plainstr().empty(); } + + /** Size of the underlying string */ + std::string::size_type size() const + { return plainstr().size(); } + + /** Return the colored string if \ref do_colors */ + std::string str() const + { return str( _color ); } + /** \overload */ + std::string asString() const + { return str(); } + + /** Return the string rendered in a differernt color if \ref do_colors */ + std::string str( Color color_r ) const + { + std::string ret( plainstr() ); + if ( do_colors() && color_r ) + { + using zypp::str::replaceAll; + replaceAll( ret, Color::SGRReset(), color_r.str() ); + ret = color_r.str() + ret + Color::SGRReset(); + } +#if ( ZYPPER_TRACE_SGR ) + return "[\"<]" + ret + "[>\"]"; +#endif + return ret; + } + + public: + /** Return the underlying plain string */ + const std::string & plainstr() const + { return _str; } + + /** Return the underlying plain string */ + std::string & plainstr() + { return _str; } + + /** Access the underlying plain string via \c operator* */ + const std::string & operator*() const + { return plainstr(); } + + /** Access the underlying plain string via \c operator* */ + std::string & operator*() + { return plainstr(); } + + private: + std::string _str; + Color _color; + }; + + /** \relates ColorString Print colored on ostream */ + inline std::ostream & operator<<( std::ostream & str, const ColorString & obj ) + { return str << obj.str(); } + + /////////////////////////////////////////////////////////////////// + /// \class ColorStream + /// \brief Colored stream output if \ref do_colors + /// + /// If an \c ostream& is passed to the constructor, we directly print + /// to this steam. Otherwise an ostringstream is used as buffer until + /// the buffered \ref ColorStream itself is printed. Printing an unbuffered + /// steam prints an empty string. + /// + /// \note Printing directly to a stream, the color is active throughout the + /// ColorStreams lifetime (set in ctor, reset in dtor). + /// + /// \see \ref ColorTraits for how to enable convenient \class ColorStream + /// handling via an enum type. + /// \code + /// ColorStream cstr( std::move( ColorContext::Red << "Error " << 42 ) ); + /// + /// cout << "default" + /// << ( ColorContext::Green << "prints green" + /// << ColorContext::Red << "switch to red" + /// << ( ColorContext::Blue << "prints blue" ) + /// << "still prints red" ) + /// << "default" << endl; + /// \endcode + /// + /// \note This class is not copyable but movable. + /////////////////////////////////////////////////////////////////// + class ColorStream + { + struct nullDeleter { void operator() (void const *) const {}; }; + + public: + /** Default Ctor (\ref Color::Default) */ + ColorStream() + {} + + /** Ctor taking a \ref Color */ + explicit ColorStream( Color color_r ) + : _color( color_r ) + {} + + /** Ctor directly printing to a \ref std::ostream (\ref Color::Default) */ + explicit ColorStream( std::ostream & direct_r ) + : ColorStream( direct_r, Color::Default ) + {} + + /** Ctor directly printing to a \ref std::ostream in \ref Color */ + ColorStream( std::ostream & direct_r, Color color_r ) + : _directP( &direct_r ) + , _color( color_r ) + { (*_directP) << _color; } + + /** non copyable */ + ColorStream( const ColorStream & ) = delete; + ColorStream & operator=( const ColorStream & ) = delete; + + /** movable */ + ColorStream( ColorStream && ) = default; + ColorStream & operator=( ColorStream && ) = default; + + ~ColorStream() + { if ( _directP ) (*_directP) << Color::SGRReset(); } + + /** Explicit conversion to \ref std::ostream (creates buffer if not direct) */ + explicit operator std::ostream &() + { return stream(); } + + public: + /** Change the streams \ref Color */ + ColorStream & operator=( Color color_r ) + { + _color = color_r; + if ( hasStream() ) + stream() << _color; + return *this; + } + + /** Update the streams \ref Color */ + ColorStream & operator<=( Color color_r ) + { + _color <= color_r; + if ( hasStream() ) + stream() << _color; + return *this; + } + + public: + /** Return streams \ref Color */ + Color color() const + { return _color; } + + public: + /** Return a buffered streams content as (colored) string */ + std::string str() const + { + std::string ret; + if ( hasContent() ) + { + ret = _bufferP->str(); + ret += Color::SGRReset(); + } + return ret; + } + + public: + /** Printing a \ref Color (also via enum) updates the streams \ref Color */ + ColorStream & operator<<( Color color_r ) + { return operator<=( color_r ); } + + /** Printing a \ref ColorString using his \ref Color + * \note \ref ColorString in \ref Color::nocolor is renderd in streams color + */ + ColorStream & operator<<( const ColorString & val_r ) + { stream() << ( val_r.color() ? val_r.str() : val_r.str(_color) ) << _color; return *this; } + + /** Printing another \ref ColorStream using his \ref Color */ + ColorStream & operator<<( const ColorStream & val_r ) +#if ( ZYPPER_TRACE_SGR ) + { if ( val_r.hasContent() ) stream() << "[<<]" << val_r.content() << _color << "[>>]"; return *this; } +#else + { if ( val_r.hasContent() ) stream() << val_r.content() << _color; return *this; } +#endif + + /** All other types are printed via std::ostream */ + template> + ColorStream & operator<<( const Tp_ & val_r ) // ! Universal reference here would be too greedy + { stream() << val_r; return *this; } + + /** \overload for omaip */ + ColorStream & operator<<( std::ostream & (*omanip)( std:: ostream & ) ) + { stream() << omanip; return *this; } + + public: + /** \relates ColorStream Print colored on ostream */ + friend inline std::ostream & operator<<( std::ostream & str, const ColorStream & obj ) +#if ( ZYPPER_TRACE_SGR ) + { if ( obj.hasContent() ) str << "[<<]" << obj.content() << Color::SGRReset() << "[>>]"; return str; } +#else + { if ( obj.hasContent() ) str << obj.content() << Color::SGRReset(); return str; } +#endif + + private: + /** Direct or non-empty buffer */ + bool hasStream() const + { return _directP || _bufferP; } + + /** Reference to the underlying ostream (direct or auto-created buffer) */ + std::ostream & stream() const + { + if ( _directP ) + return *_directP; + + if ( !_bufferP ) + { + _bufferP.reset( new std::ostringstream ); + *_bufferP << _color; + } + return *_bufferP; + } + + /** Non-empty buffer (implies direct) */ + bool hasContent() const + { return !!_bufferP; } + + /** Content of a non-empty buffered stream or empty */ + std::string content() const + { + std::string ret; + if ( hasContent() ) + ret = _bufferP->str(); + return ret; + } + + private: + std::unique_ptr _directP; + mutable std::unique_ptr _bufferP; + Color _color; + }; + /////////////////////////////////////////////////////////////////// + +#undef ZYPPER_TRACE_SGR +} // namespace ansi +/////////////////////////////////////////////////////////////////// + +// Drag them into this namespace: +using ansi::ColorString; +using ansi::ColorStream; + +/** \relates ColorStream Create \ref ColorStream via \ref Color */ +template +inline ansi::ColorStream operator<<( ansi::Color color_r, Tp_ && val_r ) +{ return std::move( ansi::ColorStream( color_r ) << std::forward(val_r) ); } +/** \overload for omanip */ +inline ansi::ColorStream operator<<( ansi::Color color_r, std::ostream & (*omanip)( std::ostream & ) ) +{ return std::move( ansi::ColorStream( color_r ) << omanip ); } + +/** \relates ColorStream Create \ref ColorStream via enum << expr */ +template > +inline ansi::ColorStream operator<<( CCC_ && color_r, Tp_ && val_r ) +{ return std::move( ansi::ColorStream( std::forward(color_r) ) << std::forward(val_r) ); } +/** \overload for omanip */ +template > +inline ansi::ColorStream operator<<( CCC_ && color_r, std::ostream & (*omanip)( std:: ostream & ) ) +{ return std::move( ansi::ColorStream( std::forward(color_r) ) << omanip ); } + +} + + +namespace std +{ +/** \relates ansi::Color Stream oputput for ColorTraits enabled types + * Defined in namespace 'std' because namespace of 'CCC_' may vary + */ +template> +inline ostream & operator<<( ostream & str, CCC_ && color_r ) +{ return str << ztui::ansi::Color( forward(color_r) ); } +} // namespace std + +#endif // ZYPP_TUI_UTILS_ANSI_H diff --git a/zypp-tui/utils/colors.cc b/zypp-tui/utils/colors.cc new file mode 100644 index 0000000..869f51d --- /dev/null +++ b/zypp-tui/utils/colors.cc @@ -0,0 +1,149 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include + +#include +#include +#include "colors.h" + +namespace ztui { + +namespace env +{ + inline bool NO_COLOR() + { return ::getenv("NO_COLOR"); } +} // namespace env + +/////////////////////////////////////////////////////////////////// +// from ansi.h + +bool do_ttyout() +{ + return Application::instance().config().do_ttyout; +} + +bool do_colors() +{ + return Application::instance().config().do_colors; +} + +bool mayUseANSIEscapes() +{ + constexpr auto detectAnsiEscapes = [](){ + if ( ::isatty(STDOUT_FILENO) ) + { + char *term = ::getenv("TERM"); + if ( term && ::strcmp( term, "dumb" ) ) + return true; + } + return false; + }; + + static bool mayUse = detectAnsiEscapes(); + return mayUse; +} + +bool hasANSIColor() +{ return mayUseANSIEscapes() && not env::NO_COLOR(); } + +namespace ansi +{ + namespace tty + { + const EscapeSequence clearLN ( "\033[2K\r", "\n" ); + const EscapeSequence cursorUP ( "\033[1A" ); + const EscapeSequence cursorDOWN ( "\033[1B" ); + const EscapeSequence cursorRIGHT ( "\033[1C" ); + const EscapeSequence cursorLEFT ( "\033[1D" ); + } // namespace tty + + + Color Color::fromString(const std::string &colorName) + { + static const std::map _def = { + { "black", ansi::Color::Black }, + { "darkgrey", ansi::Color::BrightBlack }, + { "red", ansi::Color::Red }, + { "green", ansi::Color::Green }, + { "brown", ansi::Color::Yellow }, + { "yellow", ansi::Color::BrightYellow }, + { "blue", ansi::Color::Blue }, + { "magenta", ansi::Color::Magenta }, + { "purple", ansi::Color::Magenta }, + { "cyan", ansi::Color::Cyan }, + { "grey", ansi::Color::White }, + { "white", ansi::Color::BrightWhite }, + { "default", ansi::Color::Default }, + { "", ansi::Color::Default }, // matches "bold" "light" "bright" NOT "" + }; + + ansi::Color ret = ansi::Color::nocolor(); + + if ( colorName.empty() ) // "" when undefined in config file + return ret; + + std::string name_r = zypp::str::toLower( colorName ); + + if ( zypp::str::hasPrefix( name_r, "bold" ) ) { + name_r.erase( 0, 4 ); + ret <= ansi::Color::Attr::Bright; + + } else if ( zypp::str::hasPrefix( name_r, "light" ) ) { + name_r.erase( 0, 5 ); + ret <= ansi::Color::Attr::Bright; + + } else if ( zypp::str::hasPrefix( name_r, "bright" ) ) { + name_r.erase( 0, 6 ); + ret <= ansi::Color::Attr::Bright; + } + + auto && it = _def.find( name_r ); + if ( it == _def.end() ) + { + ERR << "Unknown color name '" << name_r << "'" << std::endl; + ret = ansi::Color::Default; + } + else + { + ret = ( it->second < ret ); + } + return ret; + } + + +} // namespace tty +// from ansi.h +/////////////////////////////////////////////////////////////////// + +ansi::Color customColorCtor( ColorContext ctxt_r ) +{ + const ztui::Config & conf( Application::instance().config() ); + switch ( ctxt_r ) + { + case ColorContext::RESULT: return conf.color_result; + case ColorContext::MSG_STATUS: return conf.color_msgStatus; + case ColorContext::MSG_WARNING: return conf.color_msgWarning; + case ColorContext::MSG_ERROR: return conf.color_msgError; + case ColorContext::PROMPT: return conf.color_prompt; + case ColorContext::PROMPT_OPTION: return conf.color_promptOption; + case ColorContext::POSITIVE: return conf.color_positive; + case ColorContext::CHANGE: return conf.color_change; + case ColorContext::NEGATIVE: return conf.color_negative; + case ColorContext::HIGHLIGHT: return conf.color_highlight; + case ColorContext::LOWLIGHT: return conf.color_lowlight; + case ColorContext::OSDEBUG: return conf.color_osdebug; + + case ColorContext::DEFAULT: + break; // use default... + } + return ansi::Color::Default; // default +} + +} diff --git a/zypp-tui/utils/colors.h b/zypp-tui/utils/colors.h new file mode 100644 index 0000000..d95aca8 --- /dev/null +++ b/zypp-tui/utils/colors.h @@ -0,0 +1,92 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +#ifndef ZYPP_TUI_UTILS_COLORS_H_ +#define ZYPP_TUI_UTILS_COLORS_H_ + +#include +#include + +#include "ansi.h" + +namespace ztui { + +/** True unless output is a dumb tty or file. + * In this case we should not use any ANSI Escape sequences moving the cursor. + */ +bool do_ttyout(); + +/** If output is done in colors (depends on config) */ +bool do_colors(); + +/////////////////////////////////////////////////////////////////// + +enum class ColorContext +{ + DEFAULT, + + RESULT, + MSG_STATUS, + MSG_ERROR, + MSG_WARNING, + PROMPT, + PROMPT_OPTION, + POSITIVE, + CHANGE, + NEGATIVE, + HIGHLIGHT, + LOWLIGHT, + + OSDEBUG +}; + +/** \relates ColorContext map to \ref ansi::Color */ +ansi::Color customColorCtor( ColorContext ctxt_r ); + +namespace ansi +{ + // Enable using ColorContext as ansi::SGRSequence + template<> + struct ColorTraits + { enum { customColorCtor = true }; }; +} + +// ColorString types +template +struct CCString : public ColorString +{ + CCString() : ColorString( _ctxt ) {} + explicit CCString( const std::string & str_r ) : ColorString( _ctxt, str_r ) {} + explicit CCString( std::string && str_r ) : ColorString( _ctxt, std::move(str_r) ) {} +}; + +template +inline ansi::ColorStream & operator<<( ansi::ColorStream & cstr_r, const CCString<_ctxt> & cstring_r ) +{ return cstr_r << (const ColorString &)cstring_r; } + +using DEFAULTString = CCString; + +using MSG_STATUSString = CCString; +using MSG_ERRORString = CCString; +using MSG_WARNINGString = CCString; + +using POSITIVEString = CCString; +using CHANGEString = CCString; +using NEGATIVEString = CCString; + +using HIGHLIGHTString = CCString; +using LOWLIGHTString = CCString; + +} + +#endif /* ZYPP_TUI_UTILS_COLORS_H_ */ diff --git a/zypp-tui/utils/console.cc b/zypp-tui/utils/console.cc new file mode 100644 index 0000000..ae012d7 --- /dev/null +++ b/zypp-tui/utils/console.cc @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +/** \file console.cc + * Miscellaneous console utilities. + */ +#include +#include + +#include +#include +#include +#include + +namespace ztui { + +// ---------------------------------------------------------------------------- + +// Read a string. "\004" (^D) on EOF. +std::string readline_getline() +{ + std::string ret; + + //::rl_catch_signals = 0; + /* Get a line from the user. */ + if ( char * line_read = ::readline( "zypper> " ) ) + { + ret = line_read; + /* If the line has any text in it, save it on the history. */ + if ( *line_read ) + ::add_history( line_read ); + ::free( line_read ); + } + else + ret = "\004"; + + return ret; +} + +// ---------------------------------------------------------------------------- + +unsigned get_screen_width() +{ + if ( !::isatty(STDOUT_FILENO) ) + return -1; // no clipping + + int width = 80; + + const char *cols_env = getenv("COLUMNS"); + if ( cols_env ) + width = ::atoi( cols_env ); + else + { + ::rl_initialize(); + //::rl_reset_screen_size(); + ::rl_get_screen_size( NULL, &width ); + } + + // safe default + if ( !width ) + width = 80; + + return width; +} + +// ---------------------------------------------------------------------------- + +void clear_keyboard_buffer() +{ + // note: this will not clear characters typed after the last \n + std::ifstream stm( "/dev/tty" ); + char s[8]; + while (stm.good() && stm.readsome(s, 8)); +} + +} diff --git a/zypp-tui/utils/console.h b/zypp-tui/utils/console.h new file mode 100644 index 0000000..00ac6c4 --- /dev/null +++ b/zypp-tui/utils/console.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + +/** \file console.h + * Miscellaneous console utilities. + */ + +#ifndef ZYPP_TUI_UTILS_CONSOLE_H_ +#define ZYPP_TUI_UTILS_CONSOLE_H_ + +#include + +namespace ztui { + +/** Use readline to get line of input. */ +std::string readline_getline(); + +/** + * Reads COLUMNS environment variable or gets the screen width from readline, + * in that order. Falls back to 80 if all that fails. + * + * \NOTE In case stdout is not connected to a terminal max. unsigned + * is returned. This should prevent clipping when output is redirected. + */ +unsigned get_screen_width(); + +/** + * Clear the keyboard buffer. + * Useful before showing the user prompt message to catch any unwanted + * key hits (bnc #649248). + * + * \NOTE This will not clear characters typed after the last \n + */ +void clear_keyboard_buffer(); + +} + +#endif /* ZYPP_TUI_UTILS_CONSOLE_H_ */ diff --git a/zypp-tui/utils/richtext.cc b/zypp-tui/utils/richtext.cc new file mode 100644 index 0000000..08b1cb6 --- /dev/null +++ b/zypp-tui/utils/richtext.cc @@ -0,0 +1,275 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ +#include +#include +#include +#include + +#include +#include + +namespace ztui { + +using std::endl; +using namespace zypp; + +enum tags { + PARAGRAPH, + PRE, + BLOCKQUOTE, + BOLD, + UNDERLINED, + ANCHOR, + HEADER1, + HEADER2, + HEADER3, + BREAK_LINE, + EM, + ITALIC, + HR, + LI, + OL, + UL, + TT, + QT, + BIG, + CODE, + CENTER, + //special for unknown tags + UNKNOWN +}; + +std::map _rtTagmap; + +bool pre; +bool ordered; +unsigned count_list_items; + +void fillTagmap() +{ + _rtTagmap["p"] = PARAGRAPH; + _rtTagmap["a"] = ANCHOR; + _rtTagmap["b"] = BOLD; + _rtTagmap["u"] = UNDERLINED; + _rtTagmap["i"] = ITALIC; + _rtTagmap["br"] = BREAK_LINE; + _rtTagmap["em"] = EM; + _rtTagmap["h1"] = HEADER1; + _rtTagmap["h2"] = HEADER2; + _rtTagmap["h3"] = HEADER3; + _rtTagmap["hr"] = HR; + _rtTagmap["li"] = LI; + _rtTagmap["ol"] = OL; + _rtTagmap["ul"] = UL; + _rtTagmap["qt"] = QT; + _rtTagmap["tt"] = TT; + _rtTagmap["big"] = BIG; + _rtTagmap["pre"] = PRE; + _rtTagmap["bold"] = BOLD; + _rtTagmap["code"] = CODE; + _rtTagmap["font"] = UNKNOWN; //not parsed in parser + _rtTagmap["large"] = UNKNOWN; //same as ncurses + _rtTagmap["small"] = UNKNOWN; // same as necurses + _rtTagmap["center"] = CENTER; + _rtTagmap["strong"] = BOLD; // same as necurses + _rtTagmap["blockquote"] = BLOCKQUOTE; // same as necurses + +} + +std::string closeTag( std::vector& tagStack ) +{ + if( tagStack.empty() ) + { + WAR << "closing tag before any opening" << endl;; + return ""; + } + tags t = tagStack.back(); + tagStack.pop_back(); + switch ( t ) + { + case PARAGRAPH: + return "\n\n"; + case LI: + return "\n"; + case PRE: + pre = false; //fall thrue + default: + return ""; + } +} + +std::string openTag( std::vector& tagStack, std::string & tag ) +{ + tag = str::trim(tag); + std::map::const_iterator it = _rtTagmap.find( tag ); + tags t; + if ( it == _rtTagmap.end() ) + { + if ( tag.size() > 3 && tag[0] == '!' && tag[1] == '-' && tag[2] == '-' ) + return ""; //comment + WAR << "unknown rich text tag " << tag << endl; + t = UNKNOWN; + } + else + { + t = it->second; + } + tagStack.push_back( t ); + switch ( t ) + { + case HR: + tagStack.pop_back(); //hr haven't closing tag + return "--------------------"; + + case PARAGRAPH: + return ""; + case BREAK_LINE: + tagStack.pop_back(); //br haven't closing tag + return "\n"; + case OL: + ordered = true; + count_list_items = 0; + return "\n"; + case UL: + ordered = false; + return "\n"; + case LI: + if ( ordered ) + { + std::ostringstream res; + res << ++count_list_items << ") "; + return res.str(); + } + else + { + return "- "; + } + case PRE: + pre = true; //fall thrue + default: + return ""; + } +} + +std::map ampersmap; + +void fillAmpersmap() +{ + ampersmap["gt"] =">"; + ampersmap["lt"] ="<"; + ampersmap["amp"] ="&"; + ampersmap["quot"] ="\""; + ampersmap["nbsp"] =" "; //TODO REAL NBSP + ampersmap["product"] ="product"; //TODO replace with real name +} + +std::string getStringFromAmpr( const std::string & str ) +{ + if ( ampersmap.empty() ) + fillAmpersmap(); + + std::string::size_type end = str.find( ';' ); + DBG << "val ampr is: " << str << endl; + if ( str[0] == '#' ) //first is value + { + int res = 0; + std::istringstream sstr( str.substr( 1, end ) ); + sstr >> res; + DBG << res << endl; + if ( res != 0 ) + { + return std::string( 1,(char)res ); //return char + } + else + { + WAR << "unknown number " << str << endl; + return ""; + } + } + + DBG << end << " " << str.substr( 0, end ) << endl; + return ampersmap[str.substr( 0, end )]; + +} + +std::string processRichText( const std::string& text ) +{ + if ( _rtTagmap.empty() ) + fillTagmap(); + //state machine vars + pre = false; + + std::vector tagStack; + + std::string res; + res.reserve( text.size() ); + std::string::size_type pos = 0; + do { + switch( text[pos] ) + { + case ' ': + case '\n': + case '\t': + case '\v': + case '\r': + if ( pre ) + res.push_back( text[pos] ); + else + { + if ( text[pos] == ' ' ) + res.push_back( ' ' ); + } + break; + case '<': + if ( pos+1 == text.npos ) + { + WAR << "ended with nonclosed tag."<< endl; + return res; //chyba, tohle by se nemelo stavat + } + if ( text[pos+1] == '/' ) //close tag + { + pos = text.find( '>', pos ); + res.append( closeTag( tagStack ) ); + } + else + { + std::string::size_type tagEndPos = text.find( '>', pos ); + if ( tagEndPos == text.npos ) + { + WAR << "ended with non-closed tag " << endl; + return res; + } + std::string tagname( text.substr( pos+1, tagEndPos-pos-1 ) ); + pos = tagEndPos; + res.append( openTag( tagStack, tagname ) ); + } + break; + case '&': + { + std::string::size_type semipos = text.find( ';', pos ); + std::string tmp = getStringFromAmpr( text.substr( pos+1, pos-semipos-1 ) ); + DBG << "tmp is: " << tmp << endl; + res.append( tmp ); + pos = semipos; + break; + } + default: + res.push_back( text[pos] ); + } + + ++pos; + } while ( pos != text.size() ); + return res; +} + +} diff --git a/zypp-tui/utils/richtext.h b/zypp-tui/utils/richtext.h new file mode 100644 index 0000000..a04c5b3 --- /dev/null +++ b/zypp-tui/utils/richtext.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ +#ifndef ZYPP_TUI_UTILS_RICHTEXT_H_ +#define ZYPP_TUI_UTILS_RICHTEXT_H_ + +#include +#include +#include + +namespace ztui { + +/** Print [Rich]Text optionally indented. + * Richtext is introduced by a '' + * or '

+ * The need for refresh is evaluated according to the following conditions, + * in that order: + *

    + *
  • the refresh policy (refresh may be forced) + *
  • the repo.refresh.delay ZConfig value compared to the difference between + * cached index file timestamp and actual time + *
  • the timestamp of cached repo index file compared to the remote + * index file timestamp. + *
+ *

+ * This method checks the status against the specified url only. If more + * baseurls are defined for in the RepoInfo, each one must be check + * individually. Example: + * + * + * + * RepoInfo info; + * // try urls one by one + * for ( RepoInfo::urls_const_iterator it = info.baseUrlsBegin(); + * it != info.baseUrlsEnd(); ++it ) + * { + * try + * { + * // check whether to refresh metadata + * // if the check fails for this url, it throws, so another url will be checked + * if (checkIfToRefreshMetadata(info, *it, policy)!=RepoInfo::REFRESH_NEEDED) + * return; + * + * // do the actual refresh + * } + * catch (const Exception & e) + * { + * ZYPP_CAUGHT(e); + * ERR << *it << " doesn't look good. Trying another url." << endl; + * } + * } // for all urls + * + * handle("No more URLs."); + * + * + * + * \param info + * \param url + * \param policy + * \return state of repository + * \see RefreshCheckStatus + * \throws RepoUnknownTypeException + * \throws repo::RepoNoAliasException if can't figure an alias + * \throws Exception on unknown error + * + */ + RefreshCheckStatus checkIfToRefreshMetadata( const RepoInfo &info, + const Url &url, + RawMetadataRefreshPolicy policy = RefreshIfNeeded); + + /** + * \short Path where the metadata is downloaded and kept + * + * Given a repoinfo, tells where \ref RepoManager will download + * and keep the raw metadata. + * + * \param info Repository information + * + * \throws repo::RepoNoAliasException if can't figure an alias + */ + Pathname metadataPath( const RepoInfo &info ) const; + + + /** + * \short Path where the rpm packages are downloaded and kept + * + * Given a repoinfo, tells where \ref RepoProvidePackage will download + * and keep the .rpm files. + * + * \param info Repository information + * + * \throws repo::RepoNoAliasException if can't figure an alias + */ + Pathname packagesPath( const RepoInfo &info ) const; + + + /** + * \short Refresh local raw cache + * + * Will try to download the metadata + * + * In case of falure the metadata remains + * as it was before. + * + * \throws repo::RepoNoUrlException if no urls are available. + * \throws repo::RepoNoAliasException if can't figure an alias + * \throws repo::RepoUnknownTypeException if the metadata is unknown + * \throws repo::RepoException if the repository is invalid + * (no valid metadata found at any of baseurls) + */ + void refreshMetadata( const RepoInfo &info, + RawMetadataRefreshPolicy policy = RefreshIfNeeded, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Clean local metadata + * + * Empty local metadata. + * + * \throws repo::RepoNoAliasException if can't figure an alias + * \throws Exception on unknown error. + */ + void cleanMetadata( const RepoInfo &info, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Clean local package cache + * + * Empty local directory with downloaded packages + * + * \throws repo::RepoNoAliasException if can't figure an alias + * \throws Exception on unknown error. + */ + void cleanPackages( const RepoInfo &info, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Status of metadata cache + */ + RepoStatus cacheStatus( const RepoInfo &info ) const; + + /** + * \short Refresh local cache + * + * Will try to build the cache from local metadata. + * + * If the cache exists it will be overwriten. + * + * \note the local metadata must be valid. + * + * \throws repo::RepoNoAliasException if can't figure + * an alias to look in cache + * \throws repo::RepoMetadataException if the metadata + * is not enough to build a cache (empty, incorrect, or + * refresh needed) + * \throws repo::RepoUnknownTypeException + * \throws parser::ParseException if parser encounters an error. + * \throws Exception on unknown error. + */ + void buildCache( const RepoInfo &info, + CacheBuildPolicy policy = BuildIfNeeded, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short clean local cache + * + * Clean the cached version of the metadata + * + * \note the local metadata must be valid. + * + * \throws repo::RepoNoAliasException if can't figure an alias to look in cache + * \throws cache::CacheRecordNotFoundException if the cache could not be + * cleaned because of repository record not found. + * \throws Exception on unknown error. + */ + void cleanCache( const RepoInfo &info, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Whether a repository exists in cache + * + * \param RepoInfo to be checked. + */ + bool isCached( const RepoInfo &info ) const; + + + /** + * \short Load resolvables into the pool + * + * Creating from cache requires that the repository is + * refreshed (metadata downloaded) and cached + * + * \throws repo::RepoNoAliasException if can't figure an alias to look in cache + * \throw RepoNotCachedException When the source is not cached. + */ + void loadFromCache( const RepoInfo &info, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * Remove any subdirectories of cache directories which no longer belong + * to any of known repositories. + * + * These can be temporary directories left by interrupted refresh, + * or dirs left after changing .repo files outside of libzypp. + */ + void cleanCacheDirGarbage( const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Probe repo metadata type. + * + * The location to probe consists of the base \a url (you may think of it as + * a mountpoint) and the \a path to the repository on the mounted media + * (ususally \c / ). + */ + repo::RepoType probe( const Url & url, const Pathname & path ) const; + /** + * \overload Using the default path \c "/". + */ + repo::RepoType probe( const Url & url ) const; + + + /** + * \short Adds a repository to the list of known repositories. + * + * + * + * \throws repo::RepoAlreadyExistsException If the repo clash some + * unique attribute like alias + * \throws RepoUnknownType + * If RepoManagerOptions::probe is true + * and repository type can't be determined. + * \throws RepoException + * If RepoManagerOptions::probe is true and access to the url fails. + * \throws Exception On other errors. + */ + void addRepository( const RepoInfo &info, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Adds repositores from a repo file to the list of known repositories. + * \param url Url of the repo file. The URL is subject to repo variable expansion. + * + * \throws repo::RepoAlreadyExistsException If the repo clash some + * unique attribute like alias + * \throws MediaException If the access to the url fails + * \throws ParseException If the file parsing fails + * \throws RepoUnknownType If repository type can't be determined + * \throws RepoException ON other repository related errors + * \throws Exception On other errors. + */ + void addRepositories( const Url &url, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + /** + * \short Remove the best matching repository from known repos list + * + * \throws RepoNotFoundException If no repo match + */ + void removeRepository( const RepoInfo & info, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Modify repository attributes + * + * \throws RepoAlreadyExistsException if the alias specified in newinfo + * is already used by another repository + * \throws RepoNotFoundException If no repo match + * \throws ParseException If the file parsing fails + * \throws Exception On other errors. + */ + void modifyRepository( const std::string &alias, + const RepoInfo & newinfo, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + /** \overload Take alias from RepoInfo. */ + void modifyRepository( const RepoInfo & newinfo, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ) + { modifyRepository( newinfo.alias(), newinfo, progressrcv ); } + + /** + * \short Find a matching repository info + * + * \note if multiple repositories incorrectly share the + * same alias, the first one found will be returned. + * + * \param alias Repository alias + * \param progressrcv Progress reporting function + * \return RepoInfo of the found repository + * \throws RepoNotFoundException If no repo match the alias + * \throws ParseException If the file parsing fails + * \throws Exception On other errors. + */ + RepoInfo getRepositoryInfo( const std::string &alias, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + /** + * \short Find repository info by URL. + * + * \param url URL to find. + * \param urlview url::ViewOption to influence URL matching. + * \param progressrcv Progress receiver function. + * \return RepoInfo of the found repository. + * + * \note if multpile repositories incorrectly share the + * same URL, the first one found will be returned. + * + * \note the string representation of the URLs are compared. + * The \a urlview can be used to influence which + parts of the URL are to be compared. + * + * \throws RepoNotFoundException If no repo match + * \throws ParseException If the file parsing fails + * \throws Exception On other errors. + */ + RepoInfo getRepositoryInfo( const Url & url, + const url::ViewOption & urlview = url::ViewOption::DEFAULTS, + const ProgressData::ReceiverFnc & progressrcv = ProgressData::ReceiverFnc() ); + + + /** \name Known services. + * + * The known services are read from + * \ref RepoManagerOptions::knownServicesPath passed on the Ctor. + * Which defaults to ZYpp global settings. + */ + //@{ + /** + * Gets true if no service is in RepoManager (so no one in specified location) + * + * \return true if any ServiceInfo is in RepoManager + */ + bool serviceEmpty() const; + + /** + * Gets count of service in RepoManager (in specified location) + * + * \return count of service + */ + ServiceSizeType serviceSize() const; + + /** + * Iterator to first service in internal storage. + * \note Iterator is immutable, so you cannot change pointed ServiceInfo + * \return Iterator to first service + */ + ServiceConstIterator serviceBegin() const; + + /** + * Iterator to place behind last service in internal storage. + * \return iterator to end + */ + ServiceConstIterator serviceEnd() const; + + /** Iterate the known services. */ + Iterable services() const; + + /** List of known services. */ + std::list knownServices() const + { return std::list(serviceBegin(),serviceEnd()); } + + /** + * \short Finds ServiceInfo by alias or return \ref ServiceInfo::noService + * + * \param alias unique identifier of service + * \return information about service + */ + ServiceInfo getService( const std::string & alias ) const; + + /** Return whether there is a known service for \c alias. */ + bool hasService( const std::string & alias ) const; + //@} + + /** + * \short Probe the type or the service. + */ + repo::ServiceType probeService( const Url &url ) const; + + /** + * Adds a new service by its alias and URL + * + * \param alias unique identifier of the service + * \param url url to service + * + * \throws FIXME RepoAlreadyExistException and as reponame is service name + */ + void addService( const std::string & alias, const Url& url ); + + /** + * Adds new service + * + * \param service service info + * + * \throws FIXME RepoAlreadyExistException and as reponame is service name + */ + void addService( const ServiceInfo & service ); + + /** + * Removes service specified by its name + * + * \param alias unique indientifier of the service to remove + * + * \throws RepoException if service is not found or file with ServiceInfo cannot be deleted + * \throws Exception if file contain more services and rewrite file failed + */ + void removeService( const std::string & alias ); + /** \overload Take alias from ServiceInfo */ + void removeService( const ServiceInfo & service ); + + + /** + * Refreshes all enabled services. + * + * \see refreshService(ServiceInfo) + */ + void refreshServices( const RefreshServiceOptions & options_r = RefreshServiceOptions() ); + + /** + * Refresh specific service. + * + * \param alias unique indientifier of the service to refresh + * + * \throws RepoException if service is not found. + * \throws MediaException If there's a problem downloading the repo index file. + */ + void refreshService( const std::string & alias, const RefreshServiceOptions & options_r = RefreshServiceOptions() ); + /** \overload Take alias from ServiceInfo */ + void refreshService( const ServiceInfo & service, const RefreshServiceOptions & options_r = RefreshServiceOptions() ); + + /** + * Modifies service file (rewrites it with new values) and underlying + * repositories if needed. + * + * Modifications of a service can lead to rewrite of all .repo files of + * contained repositories. Particularily, disabling a service (changing + * ServiceInfo::enabled() from true to false) will disable all contained + * repositories. Renaming of a service will modify the "service" key + * of all contained repositories. + * + * \param oldAlias Old alias of the service + * \param service ServiceInfo object containing new data + * + * \throws RepoException if sservice with oldAlias is not known + * \throws Exception if have problems with files + */ + void modifyService( const std::string & oldAlias, const ServiceInfo & service ); + /** \overload Take alias from ServiceInfo. */ + void modifyService( const ServiceInfo & service ) + { modifyService( service.alias(), service ); } + + /*! + * Checks for any of the given \a urls if there is no geoip data available, caches the results + * in the metadata cache for 24hrs. The given urls need to be configured as valid geoIP targets ( usually download.opensuse.org ) + */ + void refreshGeoIp ( const RepoInfo::url_set &urls ); + + private: + /** + * Functor thats filter RepoInfo by service which it belongs to. + */ + struct MatchServiceAlias + { + public: + MatchServiceAlias( std::string alias_ ) : alias(std::move(alias_)) {} + bool operator()( const RepoInfo & info ) const + { return info.service() == alias; } + private: + std::string alias; + }; + + public: + + /** + * fill to output iterator repositories in service name. This output iterator can perform + * any action on with Repo or service Container, because it is sets and it isn't dynamic recreate. + * + * \note Don't use this function with RepoManager::removeRepository(), it will lead to segfaults + * due to invalidated internal iterators. FIXME can this be solved (using STL) so that this + * warning would not be needed? + * + * \param alias service alias + * \param out output iterator which get all the repositories belonging to + * specified service + * + * example how set priority for each RepoInfo in this service: + * \code + * //functor + * class ChangePriority + * { + * private: + * int priority; + * public: + * ChangePriority(int prio) : priority(prio) {} + * // missing rewrite priority back via RepoManager::modifyRepo + * void doIt( RepoInfo info ) { info.setPriority(priority); } + * } + * + * //somewhere in code + * ChangePriority changer(10); + * getRepositoriesInService(name, + * boost::make_function_output_iterator( + * bind(&ChangePriority::doIt, &changer, _1))); + * \endcode + */ + template + void getRepositoriesInService( const std::string & alias, + OutputIterator out ) const + { + MatchServiceAlias filter(alias); + + std::copy( boost::make_filter_iterator( filter, repoBegin(), repoEnd() ), + boost::make_filter_iterator( filter, repoEnd(), repoEnd() ), + out); + } + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoManager Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoManager & obj ) ZYPP_API; + + /** Iterate the known repositories. */ + inline Iterable RepoManager::repos() const + { return makeIterable( repoBegin(), repoEnd() ); } + + /** Iterate the known services. */ + inline Iterable RepoManager::services() const + { return makeIterable( serviceBegin(), serviceEnd() ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_REPOMANAGER_H diff --git a/zypp/RepoManagerFlags.h b/zypp/RepoManagerFlags.h new file mode 100644 index 0000000..ba08e9c --- /dev/null +++ b/zypp/RepoManagerFlags.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoManager.h + * +*/ +#ifndef ZYPP_REPOMANAGER_FLAGS_INCLUDED_H +#define ZYPP_REPOMANAGER_FLAGS_INCLUDED_H + +#include + +namespace zypp { + namespace RepoManagerFlags { + + enum RawMetadataRefreshPolicy + { + RefreshIfNeeded, + RefreshForced, + RefreshIfNeededIgnoreDelay + }; + + enum CacheBuildPolicy + { + BuildIfNeeded, + BuildForced + }; + + /** Flags for tuning RefreshService */ + enum RefreshServiceBit + { + RefreshService_restoreStatus = (1<<0), ///< Force restoring repo enabled/disabled status + RefreshService_forceRefresh = (1<<1), ///< Force refresh even if TTL is not reached + }; + ZYPP_DECLARE_FLAGS(RefreshServiceFlags,RefreshServiceBit); + + /** Options tuning RefreshService */ + using RefreshServiceOptions = RefreshServiceFlags; + + /** + * Possibly return state of RepoManager::checkIfToRefreshMetadata function + */ + enum RefreshCheckStatus { + REFRESH_NEEDED, /**< refresh is needed */ + REPO_UP_TO_DATE, /**< repository not changed */ + REPO_CHECK_DELAYED /**< refresh is delayed due to settings */ + }; + } + + ZYPP_DECLARE_OPERATORS_FOR_FLAGS( RepoManagerFlags::RefreshServiceFlags ); +} +#endif //ZYPP_REPOMANAGER_FLAGS_INCLUDED_H diff --git a/zypp/RepoManagerOptions.cc b/zypp/RepoManagerOptions.cc new file mode 100644 index 0000000..402e01a --- /dev/null +++ b/zypp/RepoManagerOptions.cc @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoManagerOptions.cc + * +*/ + +#include "RepoManagerOptions.h" +#include + +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + // + // class RepoManagerOptions + // + //////////////////////////////////////////////////////////////////// + + RepoManagerOptions::RepoManagerOptions( const Pathname & root_r ) + { + repoCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoCachePath() ); + repoRawCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoMetadataPath() ); + repoSolvCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoSolvfilesPath() ); + repoPackagesCachePath = Pathname::assertprefix( root_r, ZConfig::instance().repoPackagesPath() ); + knownReposPath = Pathname::assertprefix( root_r, ZConfig::instance().knownReposPath() ); + knownServicesPath = Pathname::assertprefix( root_r, ZConfig::instance().knownServicesPath() ); + pluginsPath = Pathname::assertprefix( root_r, ZConfig::instance().pluginsPath() ); + probe = ZConfig::instance().repo_add_probe(); + + rootDir = root_r; + } + + RepoManagerOptions RepoManagerOptions::makeTestSetup( const Pathname & root_r ) + { + RepoManagerOptions ret; + ret.repoCachePath = root_r; + ret.repoRawCachePath = root_r/"raw"; + ret.repoSolvCachePath = root_r/"solv"; + ret.repoPackagesCachePath = root_r/"packages"; + ret.knownReposPath = root_r/"repos.d"; + ret.knownServicesPath = root_r/"services.d"; + ret.pluginsPath = root_r/"plugins"; + ret.rootDir = root_r; + return ret; + } + + std::ostream & operator<<( std::ostream & str, const RepoManagerOptions & obj ) + { +#define OUTS(X) str << " " #X "\t" << obj.X << std::endl + str << "RepoManagerOptions (" << obj.rootDir << ") {" << std::endl; + OUTS( repoRawCachePath ); + OUTS( repoSolvCachePath ); + OUTS( repoPackagesCachePath ); + OUTS( knownReposPath ); + OUTS( knownServicesPath ); + OUTS( pluginsPath ); + str << "}" << std::endl; +#undef OUTS + return str; + } +} diff --git a/zypp/RepoManagerOptions.h b/zypp/RepoManagerOptions.h new file mode 100644 index 0000000..fa37c64 --- /dev/null +++ b/zypp/RepoManagerOptions.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoManager.h + * +*/ +#ifndef ZYPP_REPOMANAGER_OPTIONS_H +#define ZYPP_REPOMANAGER_OPTIONS_H + +#include +#include +#include + +namespace zypp +{ + /** + * Repo manager settings. + * Settings default to ZYpp global settings. + */ + struct ZYPP_API RepoManagerOptions + { + /** Default ctor following \ref ZConfig global settings. + * If an optional \c root_r directory is given, all paths will + * be prefixed accordingly. + * \code + * root_r\repoCachePath + * \repoRawCachePath + * \repoSolvCachePath + * \repoPackagesCachePath + * \knownReposPath + * \endcode + */ + RepoManagerOptions( const Pathname & root_r = Pathname() ); + + /** Test setup adjusting all paths to be located below one \c root_r directory. + * \code + * root_r\ - repoCachePath + * \raw - repoRawCachePath + * \solv - repoSolvCachePath + * \packages - repoPackagesCachePath + * \repos.d - knownReposPath + * \endcode + */ + static RepoManagerOptions makeTestSetup( const Pathname & root_r ); + + Pathname repoCachePath; + Pathname repoRawCachePath; + Pathname repoSolvCachePath; + Pathname repoPackagesCachePath; + Pathname knownReposPath; + Pathname knownServicesPath; + Pathname pluginsPath; + bool probe; + /** + * Target distro ID to be used when refreshing repo index services. + * Repositories not maching this ID will be skipped/removed. + * + * If empty, \ref Target::targetDistribution() will be used instead. + */ + std::string servicesTargetDistro; + + /** remembers root_r value for later use */ + Pathname rootDir; + }; + + std::ostream & operator<<( std::ostream & str, const RepoManagerOptions & obj ); +} + +#endif diff --git a/zypp/RepoStatus.cc b/zypp/RepoStatus.cc new file mode 100644 index 0000000..f0756b4 --- /dev/null +++ b/zypp/RepoStatus.cc @@ -0,0 +1,255 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoStatus.cc + * +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + /** Recursive computation of max dir timestamp. */ + void recursiveTimestamp( const Pathname & dir_r, time_t & max_r ) + { + std::list dircontent; + if ( filesystem::readdir( dircontent, dir_r, false/*no dots*/ ) != 0 ) + return; // readdir logged the error + + for_( it, dircontent.begin(), dircontent.end() ) + { + PathInfo pi( dir_r + *it, PathInfo::LSTAT ); + if ( pi.isDir() ) + { + if ( pi.mtime() > max_r ) + max_r = pi.mtime(); + recursiveTimestamp( pi.path(), max_r ); + } + } + } + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoStatus::Impl + // + /** RepoStatus implementation. */ + struct RepoStatus::Impl + { + using Checksums = std::set; + + public: + /** Assign data called from RepoStatus ctor (adds magic). + * + * \Note Changing magic will at once invalidate all solv file caches. + * Helpfull if solv file content must be refreshed (e.g. due to different + * repo2solv arguments) even if raw metadata are unchanged. Only values + * set from a RepoStatus ctor need magic to be added! + */ + void assignFromCtor( std::string && checksum_r, Date && timestamp_r ) + { + if ( !checksum_r.empty() ) { + static const std::string magic( "43" ); + checksum_r += magic; + _checksums.insert( std::move(checksum_r) ); + } + _timestamp = std::move(timestamp_r); + } + + /** Inject raw data (no magic added). */ + void inject( std::string && checksum_r, Date && timestamp_r ) + { + if ( !checksum_r.empty() ) { + _checksums.insert( std::move(checksum_r) ); + _cachedchecksum.reset(); + } + + if ( timestamp_r > _timestamp ) + _timestamp = std::move(timestamp_r); + } + + /** Inject the raw data from rhs */ + void injectFrom( const Impl & rhs ) + { + if ( &rhs == this ) // no self insert + return; + + if ( !rhs._checksums.empty() ) { + _checksums.insert( rhs._checksums.begin(), rhs._checksums.end() ); + _cachedchecksum.reset(); + } + + if ( rhs._timestamp > _timestamp ) + _timestamp = rhs._timestamp; + } + + bool empty() const + { return _checksums.empty(); } + + std::string checksum() const + { + std::string ret; + if ( _checksums.empty() ) + return ret; + + if ( _checksums.size() == 1 ) + ret = *_checksums.begin(); + else { + if ( !_cachedchecksum ) { + std::stringstream ss; + for ( std::string_view c : _checksums ) + ss << c; + _cachedchecksum = CheckSum::sha1(ss).checksum(); + } + ret = *_cachedchecksum; + } + return ret; + } + + Date timestamp() const + { return _timestamp; } + + /** Dump to log file (not to/from CookieFile). */ + std::ostream & dumpOn( std::ostream & str ) const + { return str << ( empty() ? "NO_REPOSTATUS" : checksum() ) << " " << time_t(_timestamp); } + + public: + void assignFromCookieFile( const Pathname & path_r, bool useMtime_r = false ) + { + std::ifstream file( path_r.c_str() ); + if ( not file ) { + WAR << "No cookie file " << path_r << endl; + return; + } + // line := "[checksum] time_t" !!! ALWAYS strip time from line + std::string line { str::getline( file ) }; + const std::string & time { str::stripLastWord( line ) }; + + Date stmp { useMtime_r ? PathInfo( path_r ).mtime() : str::strtonum( time ) }; + inject( std::move(line), std::move(stmp) ); // raw inject to avoid magic being added + } + + private: + Checksums _checksums; + Date _timestamp; + + mutable std::optional _cachedchecksum; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoStatus + // + /////////////////////////////////////////////////////////////////// + + RepoStatus::RepoStatus() + : _pimpl( new Impl() ) + {} + + RepoStatus::RepoStatus( const Pathname & path_r ) + : _pimpl( new Impl() ) + { + PathInfo info( path_r ); + if ( info.isExist() ) + { + if ( info.isFile() ) + { + _pimpl->assignFromCtor( filesystem::sha1sum( path_r ), Date( info.mtime() ) ); + } + else if ( info.isDir() ) + { + time_t t = info.mtime(); + recursiveTimestamp( path_r, t ); + _pimpl->assignFromCtor( CheckSum::sha1FromString( str::numstring( t ) ).checksum(), Date( t ) ); + } + } + } + + RepoStatus::RepoStatus( const RepoInfo & info_r ) + : _pimpl( new Impl() ) + { + _pimpl->assignFromCtor( CheckSum::sha1FromString( info_r.url().asString() ).checksum(), Date() ); + } + + RepoStatus::RepoStatus( std::string checksum_r, Date timestamp_r ) + : _pimpl( new Impl() ) + { + _pimpl->assignFromCtor( std::move(checksum_r), std::move(timestamp_r) ); + } + + RepoStatus::~RepoStatus() + {} + + RepoStatus RepoStatus::fromCookieFile( const Pathname & path_r ) + { + RepoStatus ret; + ret._pimpl->assignFromCookieFile( path_r ); + return ret; + } + + RepoStatus RepoStatus::fromCookieFileUseMtime( const Pathname & path_r ) + { + RepoStatus ret; + ret._pimpl->assignFromCookieFile( path_r, /*useMtime*/true ); + return ret; + } + + void RepoStatus::saveToCookieFile( const Pathname & path_r ) const + { + std::ofstream file(path_r.c_str()); + if (!file) { + ZYPP_THROW (Exception( "Can't open " + path_r.asString() ) ); + } + file << _pimpl->checksum() << " " << time_t(_pimpl->timestamp()) << endl; + file.close(); + } + + bool RepoStatus::empty() const + { return _pimpl->empty(); } + + Date RepoStatus::timestamp() const + { return _pimpl->timestamp(); } + + std::ostream & operator<<( std::ostream & str, const RepoStatus & obj ) + { return obj._pimpl->dumpOn( str ); } + + RepoStatus operator&&( const RepoStatus & lhs, const RepoStatus & rhs ) + { + RepoStatus result { lhs }; + result._pimpl->injectFrom( *rhs._pimpl ); + return result; + } + + bool operator==( const RepoStatus & lhs, const RepoStatus & rhs ) + { return lhs._pimpl->checksum() == rhs._pimpl->checksum(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/RepoStatus.h b/zypp/RepoStatus.h new file mode 100644 index 0000000..7aaf2c7 --- /dev/null +++ b/zypp/RepoStatus.h @@ -0,0 +1,127 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoStatus.h + * +*/ +#ifndef ZYPP2_REPOSTATUS_H +#define ZYPP2_REPOSTATUS_H + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class RepoInfo; + + /////////////////////////////////////////////////////////////////// + /// \class RepoStatus + /// \brief Track changing files or directories. + /// + /// Compute timestamp and checksum for individual files or + /// directories (recursively) to track changing content. + /// + /// The timestamp most probably denotes the time the data were + /// changed the last time, that's why it is exposed. + /// + /// The checksum however is an implementation detail and of no + /// use outside this class. \ref operator== tells if the checksums + /// of two rRepoStatus are the same. + /////////////////////////////////////////////////////////////////// + class ZYPP_API RepoStatus + { + friend std::ostream & operator<<( std::ostream & str, const RepoStatus & obj ); + friend RepoStatus operator&&( const RepoStatus & lhs, const RepoStatus & rhs ); + friend bool operator==( const RepoStatus & lhs, const RepoStatus & rhs ); + + public: + /** Default ctor */ + RepoStatus(); + /** Compute status for single file or directory (recursively) + * + * Timestamp is the files mtime or the youngest mtime in the + * directory tree. + * + * \note Construction from a non existing file or direcory + * will result in an empty status. + */ + explicit RepoStatus( const Pathname & path_r ); + + /** Compute status of a \a RepoInfo to track changes requiring a refresh. */ + explicit RepoStatus( const RepoInfo & info_r ); + + /** Explicitly specify checksum string and timestamp to use. */ + RepoStatus( std::string checksum_r, Date timestamp_r ); + + /** Dtor */ + ~RepoStatus(); + + RepoStatus(const RepoStatus &) = default; + RepoStatus(RepoStatus &&) noexcept = default; + RepoStatus &operator=(const RepoStatus &) = default; + RepoStatus &operator=(RepoStatus &&) noexcept = default; + + public: + /** Reads the status from a cookie file. + * \returns An empty \ref RepoStatus if the file does not + * exist or is not readable. + * \see \ref saveToCookieFile + */ + static RepoStatus fromCookieFile( const Pathname & path ); + + /** Reads the status from a cookie file but uses the files mtime. + * Similar to the ctor's behavior, the returned timestamp + * is the cookie file's mtime. By touching an index or cookie + * file one may state the last time the data were found being + * up-to-date. + * Such a CookieFile is used e.g. as a pseudo metadata indexfile + * for plaindir repos. + */ + static RepoStatus fromCookieFileUseMtime( const Pathname & path ); + + /** Save the status information to a cookie file + * \throws Exception if the file can't be saved + * \see \ref fromCookieFile + */ + void saveToCookieFile( const Pathname & path_r ) const; + + public: + /** Whether the status is empty (empty checksum) */ + bool empty() const; + + /** The time the data were changed the last time */ + Date timestamp() const; + + public: + struct Impl; ///< Implementation + private: + RWCOW_pointer _pimpl; ///< Pointer to implementation + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoStatus Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoStatus & obj ) ZYPP_API; + + /** \relates RepoStatus Combine two RepoStatus (combined checksum and newest timestamp) */ + RepoStatus operator&&( const RepoStatus & lhs, const RepoStatus & rhs ) ZYPP_API; + + /** \relates RepoStatus Whether 2 RepoStatus refer to the same content checksum */ + bool operator==( const RepoStatus & lhs, const RepoStatus & rhs ) ZYPP_API; + + /** \relates RepoStatus Whether 2 RepoStatus refer to different content checksums */ + inline bool operator!=( const RepoStatus & lhs, const RepoStatus & rhs ) + { return ! ( lhs == rhs ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_REPOSTATUS_H diff --git a/zypp/Repository.cc b/zypp/Repository.cc new file mode 100644 index 0000000..f28e2f3 --- /dev/null +++ b/zypp/Repository.cc @@ -0,0 +1,448 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Repository.cc + * +*/ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const Repository Repository::noRepository; + + const std::string & Repository::systemRepoAlias() + { return sat::detail::PoolImpl::systemRepoAlias(); } + + ///////////////////////////////////////////////////////////////// + + sat::detail::CRepo * Repository::get() const + { return myPool().getRepo( _id ); } + +#define NO_REPOSITORY_RETURN( VAL ) \ + sat::detail::CRepo * _repo( get() ); \ + if ( ! _repo ) return VAL + +#define NO_REPOSITORY_THROW( VAL ) \ + sat::detail::CRepo * _repo( get() ); \ + if ( ! _repo ) ZYPP_THROW( VAL ) + + bool Repository::isSystemRepo() const + { + NO_REPOSITORY_RETURN( false ); + return myPool().isSystemRepo( _repo ); + } + + std::string Repository::alias() const + { + NO_REPOSITORY_RETURN( std::string() ); + if ( ! _repo->name ) + return std::string(); + return _repo->name; + } + + std::string Repository::name() const + { return info().name(); } + + std::string Repository::label() const + { return info().label(); } + + int Repository::satInternalPriority() const + { + NO_REPOSITORY_RETURN( INT_MIN ); + return _repo->priority; + } + + int Repository::satInternalSubPriority() const + { + NO_REPOSITORY_RETURN( INT_MIN ); + return _repo->subpriority; + } + + Repository::ContentRevision Repository::contentRevision() const + { + NO_REPOSITORY_RETURN( ContentRevision() ); + sat::LookupRepoAttr q( sat::SolvAttr::repositoryRevision, *this ); + return q.empty() ? std::string() : q.begin().asString(); + } + + Repository::ContentIdentifier Repository::contentIdentifier() const + { + NO_REPOSITORY_RETURN( ContentIdentifier() ); + sat::LookupRepoAttr q( sat::SolvAttr::repositoryRepoid, *this ); + return q.empty() ? std::string() : q.begin().asString(); + } + + bool Repository::hasContentIdentifier( const ContentIdentifier & id_r ) const + { + NO_REPOSITORY_RETURN( false ); + sat::LookupRepoAttr q( sat::SolvAttr::repositoryRepoid, *this ); + for_( it, q.begin(), q.end() ) + if ( it.asString() == id_r ) + return true; + return false; + } + + zypp::Date Repository::generatedTimestamp() const + { + NO_REPOSITORY_RETURN( 0 ); + sat::LookupRepoAttr q( sat::SolvAttr::repositoryTimestamp, *this ); + return( q.empty() ? 0 : q.begin().asUnsigned() ); + } + + zypp::Date Repository::suggestedExpirationTimestamp() const + { + NO_REPOSITORY_RETURN( 0 ); + Date generated = generatedTimestamp(); + if ( ! generated ) + return 0; // do not calculate over a missing generated timestamp + + sat::LookupRepoAttr q( sat::SolvAttr::repositoryExpire, *this ); + if ( q.empty() ) + return 0; + + return generated + Date(q.begin().asUnsigned()); + } + + Repository::Keywords Repository::keywords() const + { + NO_REPOSITORY_RETURN( Keywords() ); + return Keywords( sat::SolvAttr::repositoryKeywords, *this, sat::LookupAttr::REPO_ATTR ); + } + + bool Repository::hasKeyword( const std::string & val_r ) const + { + for ( const auto & val : keywords() ) + if ( val == val_r ) + return true; + return false; + } + + bool Repository::maybeOutdated() const + { + NO_REPOSITORY_RETURN( false ); + // system repo is not mirrored + if ( isSystemRepo() ) + return false; + + Date suggested = suggestedExpirationTimestamp(); + + // if no data, don't suggest + if ( ! suggested ) + return false; + + return suggestedExpirationTimestamp() < Date::now(); + } + + bool Repository::providesUpdatesFor( const CpeId & cpeid_r ) const + { + NO_REPOSITORY_RETURN( false ); + if ( ! cpeid_r ) + return false; // filter queries/products without CpeId, as an empty CpeId matches ANYthing. + + // check in repository metadata + for_( it, updatesProductBegin(), updatesProductEnd() ) + { + if ( compare( cpeid_r, it.cpeId(), SetRelation::subset ) ) + return true; + } + + // check whether known products refer to this as update repo + sat::LookupRepoAttr myIds( sat::SolvAttr::repositoryRepoid, *this ); // usually just one, but... + if ( ! myIds.empty() ) + { + const ResPool & pool( ResPool::instance() ); + for_( it, pool.byKindBegin(), pool.byKindEnd() ) + { + Product::constPtr prod( (*it)->asKind() ); + if ( compare( cpeid_r, prod->cpeId(), SetRelation::superset ) ) + { + for_( myId, myIds.begin(), myIds.end() ) + { + if ( prod->hasUpdateContentIdentifier( myId.asString() ) ) + return true; + } + } + } + } + return false; + } + + bool Repository::isUpdateRepo() const + { + NO_REPOSITORY_RETURN( false ); + + // check in repository metadata + if ( updatesProductBegin() != updatesProductEnd() ) + return true; + + // check whether known products refer to this as update repo + sat::LookupRepoAttr myIds( sat::SolvAttr::repositoryRepoid, *this ); // usually just one, but... + if ( ! myIds.empty() ) + { + const ResPool & pool( ResPool::instance() ); + for_( it, pool.byKindBegin(), pool.byKindEnd() ) + { + for_( myId, myIds.begin(), myIds.end() ) + { + if ( (*it)->asKind()->hasUpdateContentIdentifier( myId.asString() ) ) + return true; + } + } + } + return false; + } + + bool Repository::solvablesEmpty() const + { + NO_REPOSITORY_RETURN( true ); + return !_repo->nsolvables; + } + + Repository::size_type Repository::solvablesSize() const + { + NO_REPOSITORY_RETURN( 0 ); + return _repo->nsolvables; + } + + Repository::SolvableIterator Repository::solvablesBegin() const + { + NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ), + sat::detail::SolvableIterator(), + sat::detail::SolvableIterator() ) ); + return make_filter_iterator( detail::ByRepository( *this ), + sat::detail::SolvableIterator(_repo->start), + sat::detail::SolvableIterator(_repo->end) ); + } + + Repository::SolvableIterator Repository::solvablesEnd() const + { + NO_REPOSITORY_RETURN( make_filter_iterator( detail::ByRepository( *this ), + sat::detail::SolvableIterator(), + sat::detail::SolvableIterator() ) ); + return make_filter_iterator(detail::ByRepository( *this ), + sat::detail::SolvableIterator(_repo->end), + sat::detail::SolvableIterator(_repo->end) ); + } + + Repository::ProductInfoIterator Repository::compatibleWithProductBegin() const + { + NO_REPOSITORY_RETURN( ProductInfoIterator() ); + return ProductInfoIterator( sat::SolvAttr::repositoryDistros, *this ); + } + + Repository::ProductInfoIterator Repository::compatibleWithProductEnd() const + { + return ProductInfoIterator(); + } + + Repository::ProductInfoIterator Repository::updatesProductBegin() const + { + NO_REPOSITORY_RETURN( ProductInfoIterator() ); + return ProductInfoIterator( sat::SolvAttr::repositoryUpdates, *this ); + } + + Repository::ProductInfoIterator Repository::updatesProductEnd() const + { + return ProductInfoIterator(); + } + + RepoInfo Repository::info() const + { + NO_REPOSITORY_RETURN( RepoInfo() ); + return myPool().repoInfo( _repo ); + } + + void Repository::setInfo( const RepoInfo & info_r ) + { + NO_REPOSITORY_THROW( Exception( "Can't set RepoInfo for norepo." ) ); + if ( info_r.alias() != alias() ) + { + ZYPP_THROW( Exception( str::form( "RepoInfo alias (%s) does not match repository alias (%s)", + info_r.alias().c_str(), alias().c_str() ) ) ); + } + myPool().setRepoInfo( _repo, info_r ); + MIL << *this << endl; + } + + void Repository::clearInfo() + { + NO_REPOSITORY_RETURN(); + myPool().setRepoInfo( _repo, RepoInfo() ); + } + + void Repository::eraseFromPool() + { + NO_REPOSITORY_RETURN(); + MIL << *this << " removed from pool" << endl; + myPool()._deleteRepo( _repo ); + _id = sat::detail::noRepoId; + } + + Repository Repository::nextInPool() const + { + NO_REPOSITORY_RETURN( noRepository ); + for_( it, sat::Pool::instance().reposBegin(), sat::Pool::instance().reposEnd() ) + { + if ( *it == *this ) + { + if ( ++it != _for_end ) + return *it; + break; + } + } + return noRepository; + } + + void Repository::addSolv( const Pathname & file_r ) + { + NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) ); + + AutoDispose file( ::fopen( file_r.c_str(), "re" ), ::fclose ); + if ( file == NULL ) + { + file.resetDispose(); + ZYPP_THROW( Exception( "Can't open solv-file: "+file_r.asString() ) ); + } + + if ( myPool()._addSolv( _repo, file ) != 0 ) + { + ZYPP_THROW( Exception( "Error reading solv-file: "+file_r.asString() ) ); + } + + MIL << *this << " after adding " << file_r << endl; + } + + void Repository::addHelix( const Pathname & file_r ) + { + NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) ); + + std::string command( file_r.extension() == ".gz" ? "zcat " : "cat " ); + command += file_r.asString(); + + AutoDispose file( ::popen( command.c_str(), "re" ), ::pclose ); + if ( file == NULL ) + { + file.resetDispose(); + ZYPP_THROW( Exception( "Can't open helix-file: "+file_r.asString() ) ); + } + + if ( myPool()._addHelix( _repo, file ) != 0 ) + { + ZYPP_THROW( Exception( "Error reading helix-file: "+file_r.asString() ) ); + } + + MIL << *this << " after adding " << file_r << endl; + } + + void Repository::addTesttags( const Pathname & file_r ) + { + NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo." ) ); + + std::string command( file_r.extension() == ".gz" ? "zcat " : "cat " ); + command += file_r.asString(); + + AutoDispose file( ::popen( command.c_str(), "re" ), ::pclose ); + if ( file == NULL ) + { + file.resetDispose(); + ZYPP_THROW( Exception( "Can't open testtags-file: "+file_r.asString() ) ); + } + + if ( myPool()._addTesttags( _repo, file ) != 0 ) + { + ZYPP_THROW( Exception( "Error reading testtags-file: "+file_r.asString() ) ); + } + + MIL << *this << " after adding " << file_r << endl; + } + + sat::detail::SolvableIdType Repository::addSolvables( unsigned count_r ) + { + NO_REPOSITORY_THROW( Exception( "Can't add solvables to norepo.") ); + return myPool()._addSolvables( _repo, count_r ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Repository & obj ) + { + if ( ! obj ) + return str << "noRepository"; + + return str << "sat::repo(" << obj.alias() << ")" + << "{" + << "prio " << obj.get()->priority << '.' << obj.get()->subpriority + << ", size " << obj.solvablesSize() + << "}"; + } + + std::ostream & dumpAsXmlOn( std::ostream & str, const Repository & obj ) + { + return xmlout::node( str, "repository", { + { "name", obj.name() }, + { "alias", obj.alias() } + } ); + } + + ////////////////////////////////////////////////////////////////// + namespace detail + { + void RepositoryIterator::increment() + { + if ( base() ) + { + sat::detail::CPool * satpool = sat::Pool::instance().get(); + do { + ++base_reference(); + } while ( base() < satpool->repos+satpool->nrepos && !*base() ); + } + } + } // namespace detail + ////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // Repository::ProductInfoIterator + // + /////////////////////////////////////////////////////////////////// + + Repository::ProductInfoIterator::ProductInfoIterator( sat::SolvAttr attr_r, Repository repo_r ) + { base_reference() = sat::LookupRepoAttr( std::move(attr_r), repo_r ).begin(); } + + std::string Repository::ProductInfoIterator::label() const + { return base_reference().subFind( sat::SolvAttr::repositoryProductLabel ).asString(); } + + CpeId Repository::ProductInfoIterator::cpeId() const + { return CpeId( base_reference().subFind( sat::SolvAttr::repositoryProductCpeid ).asString(), CpeId::noThrow ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Repository.h b/zypp/Repository.h new file mode 100644 index 0000000..67147a9 --- /dev/null +++ b/zypp/Repository.h @@ -0,0 +1,517 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Repository.h + * +*/ +#ifndef ZYPP_SAT_REPOSITORY_H +#define ZYPP_SAT_REPOSITORY_H + +#include +#include +#include +#include +#include // LookupAttrTools.h included at EOF +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace detail + { + struct ByRepository; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Repository + // + /** */ + class ZYPP_API Repository : protected sat::detail::PoolMember + { + public: + using SolvableIterator = filter_iterator; + using size_type = sat::detail::size_type; + using IdType = sat::detail::RepoIdType; + + using Keywords = sat::ArrayAttr; + + using ContentRevision = std::string; + using ContentIdentifier = std::string; + + public: + /** Default ctor creates \ref noRepository.*/ + Repository() + : _id( sat::detail::noRepoId ) {} + + Repository(const Repository &) = default; + Repository(Repository &&) noexcept = default; + Repository &operator=(const Repository &) = default; + Repository &operator=(Repository &&) noexcept = default; + + /** \ref PoolImpl ctor. */ + explicit Repository( IdType id_r ) + : _id( id_r ) {} + + public: + /** Represents no \ref Repository. */ + static const Repository noRepository; + + /** Evaluate \ref Repository in a boolean context (\c != \c noRepository). */ + explicit operator bool() const + { return get() != nullptr; } + + /** Reserved system repository alias \c @System. */ + static const std::string & systemRepoAlias(); + + /** Return whether this is the system repository. */ + bool isSystemRepo() const; + + public: + /** + * Short unique string to identify a repo. + * ie: openSUSE-10.3 + * + * If you are looking for a label to display + * see \ref name(). + * ie: "openSUSE 10.3 Main repository" + * + */ + std::string alias() const; + + /** Label to display for this repo. */ + std::string name() const; + + /** Alias or name, according to \ref ZConfig::repoLabelIsAlias */ + std::string label() const; + + /** User string: \ref label (alias or name) */ + std::string asUserString() const + { return label(); } + + public: + /** Timestamp or arbitrary user supplied string. + * \c /repomd/revision/text() in \c repomd.xml. + */ + ContentRevision contentRevision() const; + + /** Unique string identifying a repositories content. + * \c /repomd/tags/repo/text() in \c repomd.xml. + * \code + * + * + * obsrepository://build.suse.de/SUSE:Factory:Head:Internal/standard + * \endcode + * Semantically the value is just a plain string, even + * if OBS often uses the location of the project as + * unique identifier. + */ + ContentIdentifier contentIdentifier() const; + + /** Whether \a id_r matches this repos content identifier. */ + bool hasContentIdentifier( const ContentIdentifier & id_r ) const; + + /** + * Timestamp when this repository was generated + * + * Usually this value is calculated as the newer + * timestamp from the timestamp of all the resources + * that conform the repository's metadata. + * + * For example in a rpm-md repository, it would be + * the resource specified in the xml file whith + * the newest timestamp attribute (which is the + * timestamp of the file in the server ). + * + * The timestamp is 0 if the repository does not + * specify when it was generated. + * + */ + Date generatedTimestamp() const; + + /** + * Suggested expiration timestamp. + * + * Repositories can define an amount of time + * they expire, with the generated timestamp as + * the base point of time. + * + * Note that is the responsability of the repository + * to freshen the generated timestamp to tell the + * client that the repo is alive and updating the + * metadata. + * + * The timestamp is 0 if the repository does not specify + * an expiration date. + * + */ + Date suggestedExpirationTimestamp() const; + + /** + * repository keywords (tags) + */ + Keywords keywords() const; + + /** Whether \a val_r is present in keywords. */ + bool hasKeyword( const std::string & val_r ) const; + + /** + * The suggested expiration date of this repository + * already passed + * + * rpm-md repositories can provide this tag using the + * expire extension tag: + * \see http://en.opensuse.org/Standards/Rpm_Metadata#SUSE_repository_info_.28suseinfo.xml.29.2C_extensions_to_repomd.xml + */ + bool maybeOutdated() const; + + /** Hint whether the Repo may provide updates for a product. + * + * Either the repository claims to update a product via a repository updates + * tag in its metadata or a known product lists the repositories ContentIdentifier + * as a required update repo. + */ + bool isUpdateRepo() const; + + /** Hint whether the Repo may provide updates for a product identified by its \ref CpeId + * + * Either the repository claims to update a product via a repository updates + * tag in its metadata or a known product lists the repositories ContentIdentifier + * as required update repo. + */ + bool providesUpdatesFor( const CpeId & cpeid_r ) const; + + /** Whether \ref Repository contains solvables. */ + bool solvablesEmpty() const; + + /** Number of solvables in \ref Repository. */ + size_type solvablesSize() const; + + /** Iterator to the first \ref Solvable. */ + SolvableIterator solvablesBegin() const; + + /** Iterator behind the last \ref Solvable. */ + SolvableIterator solvablesEnd() const; + + /** Iterate the repositories Solvables. */ + Iterable solvables() const; + + public: + + /** Query class for Repository related products */ + class ProductInfoIterator; + + /** + * Get an iterator to the beginning of the repository + * compatible distros. + * \note This is only a hint. There is no guarantee that + * the repository is built for that product. + * \see Repository::ProductInfoIterator + */ + ProductInfoIterator compatibleWithProductBegin() const; + + /** + * Get an iterator to the end of the repository + * compatible distros. + * \see Repository::ProductInfoIterator + */ + ProductInfoIterator compatibleWithProductEnd() const; + + /** Iterate the repository compatible distros. */ + Iterable compatibleWithProduct() const; + + + /** + * Get an iterator to the beginning of distos the repository + * provides upadates for. + * \note This is only a hint within the repositories metadata. + * The same realation might be expressed by a product listing + * this repositories ContentIdentifier as required update repo. + * \see Repository::ProductInfoIterator + */ + ProductInfoIterator updatesProductBegin() const; + + /** + * Get an iterator to the end of distos the repository + * provides upadates for. + * \see Repository::ProductInfoIterator + */ + ProductInfoIterator updatesProductEnd() const; + + /** Iterate distos the repository provides upadates for. */ + Iterable updatesProduct() const; + + public: + /** Return any associated \ref RepoInfo. */ + RepoInfo info() const; + + /** Set \ref RepoInfo for this repository. + * \throws Exception if this is \ref noRepository + * \throws Exception if the \ref RepoInfo::alias + * does not match the \ref Repository::name. + */ + void setInfo( const RepoInfo & info_r ); + + /** Remove any \ref RepoInfo set for this repository. */ + void clearInfo(); + + public: + /** Remove this \ref Repository from its \ref Pool. */ + void eraseFromPool(); + + /** Functor calling \ref eraseFromPool. */ + struct EraseFromPool; + + public: + /** Return next Repository in \ref Pool (or \ref noRepository). */ + Repository nextInPool() const; + + public: + /** \name Repository content manipulating methods. + * \todo maybe a separate Repository/Solvable content manip interface + * provided by the pool. + */ + //@{ + /** Load \ref Solvables from a solv-file. + * In case of an exception the repository remains in the \ref Pool. + * \throws Exception if this is \ref noRepository + * \throws Exception if loading the solv-file fails. + * \see \ref Pool::addRepoSolv and \ref Repository::EraseFromPool + */ + void addSolv( const Pathname & file_r ); + + /** Load \ref Solvables from a helix-file. + * Supports loading of gzip compressed files (.gz). In case of an exception + * the repository remains in the \ref Pool. + * \throws Exception if this is \ref noRepository + * \throws Exception if loading the helix-file fails. + * \see \ref Pool::addRepoHelix and \ref Repository::EraseFromPool + */ + void addHelix( const Pathname & file_r ); + + /** Load \ref Solvables from a libsolv testtags-file. + * Supports loading of gzip compressed files (.gz). In case of an exception + * the repository remains in the \ref Pool. + * \throws Exception if this is \ref noRepository + * \throws Exception if loading the helix-file fails. + * \see \ref Pool::addRepoTesttags and \ref Repository::EraseFromPool + */ + void addTesttags(const Pathname &file_r); + + /** Add \c count_r new empty \ref Solvable to this \ref Repository. */ + sat::Solvable::IdType addSolvables( unsigned count_r ); + /** \overload Add only one new \ref Solvable. */ + sat::Solvable::IdType addSolvable() + { return addSolvables( 1 ); } + //@} + + public: + /** Expert backdoor. */ + sat::detail::CRepo * get() const; + /** Expert backdoor. */ + IdType id() const { return _id; } + /** libsolv internal priorities. + * Unlike the \ref RepoInfo priority which tries to be YUM conform + * (H[1-99]L), this one is the solver's internal priority representation. + * It is type \c int and, as one might expect, the higher the value, + * the higher the priority. Subpriority is currently used to express + * media preferences (\see \ref MediaPriority). + */ + //@{ + int satInternalPriority() const; + int satInternalSubPriority() const; + //@} + private: + IdType _id; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Repository Stream output */ + std::ostream & operator<<( std::ostream & str, const Repository & obj ) ZYPP_API; + + /** \relates Repository XML output */ + std::ostream & dumpAsXmlOn( std::ostream & str, const Repository & obj ) ZYPP_API; + + /** \relates Repository */ + inline bool operator==( const Repository & lhs, const Repository & rhs ) + { return lhs.get() == rhs.get(); } + + /** \relates Repository */ + inline bool operator!=( const Repository & lhs, const Repository & rhs ) + { return lhs.get() != rhs.get(); } + + /** \relates Repository */ + inline bool operator<( const Repository & lhs, const Repository & rhs ) + { return lhs.get() < rhs.get(); } + + /////////////////////////////////////////////////////////////////// + /** + * Query class for Repository related products + * + * Products are identified by CpeIds within the repositories metadata. + * \see http://en.opensuse.org/Standards/Rpm_Metadata#SUSE_repository_info_.28suseinfo.xml.29.2C_extensions_to_repomd.xml + * + * The iterator does not provide a dereference + * operator so you can do * on it, but you can + * access the attributes of each related product + * directly from the iterator. + * + * \code + * for_( it, repo.compatibleWithProductBegin(), repo.compatibleWithProductEnd() ) + * { + * cout << it.label() << ": " << it.cpeid() << endl; + * } + * \endcode + * + */ + class Repository::ProductInfoIterator : public boost::iterator_adaptor< + Repository::ProductInfoIterator // Derived + , sat::LookupAttr::iterator // Base + , int // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , int // Reference + > + { + public: + ProductInfoIterator() + {} + + /** Product label */ + std::string label() const; + + /** The Common Platform Enumeration name for this product. */ + CpeId cpeId() const; + + private: + friend class Repository; + /** Hide ctor as just a limited set of attributes is valid. */ + explicit ProductInfoIterator( sat::SolvAttr attr_r, Repository repo_r ); + + private: + friend class boost::iterator_core_access; + int dereference() const { return 0; } + }; + /////////////////////////////////////////////////////////////////// + + /** Iterate the repository compatible distros. */ + inline Iterable Repository::compatibleWithProduct() const + { return makeIterable( compatibleWithProductBegin(), compatibleWithProductEnd() ); } + + /** Iterate distos the repository provides upadates for. */ + inline Iterable Repository::updatesProduct() const + { return makeIterable( updatesProductBegin(), updatesProductEnd() ); } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Repository::EraseFromPool + // + /** Functor removing \ref Repository from its \ref Pool. + * + * E.g. used as dispose function in. \ref AutoDispose + * to provide a convenient and exception safe temporary + * \ref Repository. + * \code + * sat::Pool satpool; + * MIL << "1 " << satpool << endl; + * { + * AutoDispose tmprepo( (Repository::EraseFromPool()) ); + * *tmprepo = satpool.reposInsert( "A" ); + * tmprepo->addSolv( "sl10.1-beta7-packages.solv" ); + * DBG << "2 " << satpool << endl; + * // Calling 'tmprepo.resetDispose();' here + * // would keep the Repo. + * } + * MIL << "3 " << satpool << endl; + * \endcode + * \code + * 1 sat::pool(){0repos|2solv} + * 2 sat::pool(){1repos|2612solv} + * 3 sat::pool(){0repos|2solv} + * \endcode + * Leaving the block without calling tmprepo.resetDispose(); + * before, will automatically remove the \ref Repo from its \ref Pool. + */ + struct Repository::EraseFromPool + { + void operator()( Repository repository_r ) const + { repository_r.eraseFromPool(); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepositoryIterator + // + /** */ + class ZYPP_API RepositoryIterator : public boost::iterator_adaptor< + RepositoryIterator // Derived + , sat::detail::CRepo ** // Base + , Repository // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , Repository // Reference + > + { + public: + RepositoryIterator() + : RepositoryIterator::iterator_adaptor_( 0 ) + {} + + explicit RepositoryIterator( sat::detail::CRepo ** p ) + : RepositoryIterator::iterator_adaptor_( p ) + {} + + private: + friend class boost::iterator_core_access; + + Repository dereference() const + { return Repository( *base() ); } + + void increment(); + }; + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ByRepository + // + /** Functor filtering \ref Solvable by \ref Repository.*/ + struct ByRepository + { + public: + ByRepository( const Repository & repository_r ) : _repository( repository_r ) {} + ByRepository( sat::detail::RepoIdType id_r ) : _repository( id_r ) {} + ByRepository() {} + + bool operator()( const sat::Solvable & slv_r ) const + { return slv_r.repository() == _repository; } + + private: + Repository _repository; + }; + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + + inline Iterable Repository::solvables() const + { return makeIterable( solvablesBegin(), solvablesEnd() ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +// Late include as sat::ArrayAttr requires Repository.h +#include + +#endif // ZYPP_SAT_REPOSITORY_H diff --git a/zypp/ResFilters.h b/zypp/ResFilters.h new file mode 100644 index 0000000..f52e05f --- /dev/null +++ b/zypp/ResFilters.h @@ -0,0 +1,345 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResFilters.h + * +*/ +#ifndef ZYPP_RESFILTERS_H +#define ZYPP_RESFILTERS_H + +#include +#include +#include + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace resfilter + { ///////////////////////////////////////////////////////////////// + + /** \defgroup RESFILTERS Filter functors operating on ResObjects. + * \ingroup g_Functor + * + * A simple filter is a function or functor matching the signature: + * \code + * bool simplefilter( ResObject::Ptr ); + * \endcode + * + * \note It's not neccessary that your function or functor actually + * returns \c bool. Anything which is convertible into a \c bool + * will do; + * + * Besides basic filter functors which actually evaluate the + * \c ResObject (e.g. \ref ByKind, \ref ByName) you may + * use \ref LOGICALFILTERS to build more complex filters. + * + * \code + * // some 'action' functor, printing and counting + * // ResObjects. + * struct PrintAndCount + * { + * PrintAndCount( unsigned & counter_r ) + * : _counter( counter_r ) + * {} + * + * bool operator()( ResObject::Ptr p ) const + * { + * DBG << *p << endl; + * ++_counter; + * return true; + * } + * + * unsigned & _counter; + * }; + * + * ResStore store; + * unsigned counter = 0; + * + * // print and count all resolvables + * store.forEach( PrintAndCount(counter) ); + * + * // print and count all resolvables named "kernel" + * counter = 0; + * store.forEach( ByName("kernel"), PrintAndCount(counter) ); + * + * // print and count all Packages named "kernel" + * counter = 0; + * store.forEach( chain( ByKind(ResKind::package), + * ByName("kernel") ), + * PrintAndCount(counter) ); + * + * // print and count all Packages not named "kernel" + * counter = 0; + * store.forEach( chain( ByKind(ResKind::package), + * not_c(ByName("kernel")) ), + * PrintAndCount(counter) ); + * + * // same as above ;) + * counter = 0; + * store.forEach( chain( ByKind(ResKind::package), + * chain( not_c(ByName("kernel")), + * PrintAndCount(counter) ) ), + * true_c() ); + * \endcode + * + * As you can see in the last example there is no difference in using + * a filter or an action functor, as both have the same signature. + * A difference of course is the way forEach interprets the returned + * value. + * + * Consequently you can netgate and chain actions as well. Thus + * PrintAndCount(counter) could be + * chain(Print(),Count(counter)), if these functors are + * provided. + * + * \note These functors are not limited to be used with ResStore::forEach. + * You can use them with std::algorithms as well. + * + * \c PrintAndCount is an example how a functor can return data collected + * during the query. You ca easily write a collector, that takes a + * std:list\\& and fills it with the matches + * found. + * + * But as a rule of thumb, a functor should be lightweight. If you + * want to get data out, pass references to variables in (and assert + * these variables live as long as the query lasts). Or use std::ref. + * + * Internally all functors are passed by value. Thus it would not help + * you to create an instance of some collecting functor, and pass it + * to the query. The query will then fill a copy of your functor, you + * won't get the data back. (Well, you probabely could, by using + * boosr::ref). + * + * Why functors and not plain functions? + * + * You can use plain functions if they don't have to deliver data back to + * the application. + * The \c C-style approach is having functions that take a void * data + * as last argument. This \c data pointer is then passed arround and casted + * up and down. + * + * If you look at a functor, you'll see that it contains both, the function + * to call (its operator()) and the data you'd otherwise pass as + * void * data. That's nice and safe. + * + * \todo migrate to namespace filter and enhance to support Solvables as well. + */ + //@{ + /////////////////////////////////////////////////////////////////// + // + // Some ResObject attributes + // + /////////////////////////////////////////////////////////////////// + + /** */ + template + inline filter::ByKind byKind() + { return filter::ByKind( ResTraits::kind ); } + + /** Select ResObject by name. */ + struct ByName + { + ByName() + {} + + ByName( std::string name_r ) + : _name(std::move( name_r )) + {} + + bool operator()( const ResObject::constPtr& p ) const + { + return p->name() == _name; + } + + std::string _name; + }; + + /** Select ResObject by repository or repository alias. */ + struct ByRepository + { + ByRepository( Repository repository_r ) + : _alias( repository_r.info().alias() ) + {} + + ByRepository( std::string alias_r ) + : _alias(std::move( alias_r )) + {} + + bool operator()( const ResObject::constPtr& p ) const + { + return p->repoInfo().alias() == _alias; + } + + std::string _alias; + }; + + /** Select ResObject by Edition using \a TCompare functor. + * + * Selects ResObject if TCompare( ResObject->edition(), _edition ) + * is \c true. + * \code + * // use the convenience funktions to create ByEdition: + * + * byEdition( someedition ); // selects ResObjects with edition == someedition + * + * byEdition( someedition, CompareByGT() ) // edition > someedition + * \endcode + */ + template > + struct ByEdition + { + ByEdition( Edition edition_r, TCompare cmp_r ) + : _edition(std::move( edition_r )) + , _cmp( cmp_r ) + {} + + bool operator()( const ResObject::constPtr& p ) const + { + return _cmp( p->edition(), _edition ); + } + + Edition _edition; + TCompare _cmp; + }; + + /** */ + template + ByEdition byEdition( const Edition & edition_r, TCompare cmp_r ) + { return ByEdition( edition_r, cmp_r ); } + + /** */ + template + ByEdition byEdition( const Edition & edition_r ) + { return byEdition( edition_r, TCompare() ); } + + + /** Select ResObject by Arch using \a TCompare functor. + * + * Selects ResObject if TCompare( ResObject->arch(), _arch ) + * is \c true. + * \code + * // use the convenience funktions to create ByArch: + * + * byArch( somearch ); // selects ResObjects with arch == somearch + * + * byArch( somearch, CompareByGT() ) // arch > somearch + * \endcode + */ + template > + struct ByArch + { + ByArch( const Arch & arch_r, TCompare cmp_r ) + : _arch( arch_r ) + , _cmp( cmp_r ) + {} + + bool operator()( const ResObject::constPtr& p ) const + { + return _cmp( p->arch(), _arch ); + } + + Arch _arch; + TCompare _cmp; + }; + + /** */ + template + ByArch byArch( const Arch & arch_r, TCompare cmp_r ) + { return ByArch( arch_r, cmp_r ); } + + /** */ + template + ByArch byArch( const Arch & arch_r ) + { return byArch( arch_r, TCompare() ); } + + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // Some PoolItem attributes + // + /////////////////////////////////////////////////////////////////// + + /** Select PoolItem by installed. */ + struct ByInstalled + { + bool operator()( const PoolItem & p ) const + { + return p.status().isInstalled(); + } + }; + + /** Select PoolItem by uninstalled. */ + struct ByUninstalled + { + bool operator()( const PoolItem & p ) const + { + return p.status().isUninstalled(); + } + }; + + /** Select PoolItem by transact. */ + struct ByTransact + { + bool operator()( const PoolItem & p ) const + { + return p.status().transacts(); + } + }; + + /** Select PoolItem by lock. */ + struct ByLock + { + bool operator()( const PoolItem & p ) const + { + return p.status().isLocked(); + } + }; + + /** Select PoolItem by keep. */ + struct ByKeep + { + bool operator()( const PoolItem & p ) const + { + return p.status().isKept(); + } + }; + + /** PoolItem which is recommended. */ + struct ByRecommended + { + bool operator()( const PoolItem & p ) const + { + return p.status().isRecommended(); + } + }; + + /** PoolItem which is suggested. */ + struct BySuggested + { + bool operator()( const PoolItem & p ) const + { + return p.status().isSuggested(); + } + }; + + //@} + ///////////////////////////////////////////////////////////////// + } // namespace resfilter + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESFILTERS_H diff --git a/zypp/ResKind.cc b/zypp/ResKind.cc new file mode 100644 index 0000000..4c07090 --- /dev/null +++ b/zypp/ResKind.cc @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResKind.cc + * +*/ +#include + +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const ResKind ResKind::nokind; + const ResKind ResKind::package ( "package" ); + const ResKind ResKind::patch ( "patch" ); + const ResKind ResKind::pattern ( "pattern" ); + const ResKind ResKind::product ( "product" ); + const ResKind ResKind::srcpackage ( "srcpackage" ); + const ResKind ResKind::application ( "application" ); + + template<> + const ResKind ResTraits ::kind( ResKind::package ); + template<> + const ResKind ResTraits ::kind( ResKind::patch ); + template<> + const ResKind ResTraits ::kind( ResKind::pattern ); + template<> + const ResKind ResTraits ::kind( ResKind::product ); + template<> + const ResKind ResTraits ::kind( ResKind::srcpackage ); + template<> + const ResKind ResTraits::kind( ResKind::application ); + + ResKind ResKind::explicitBuiltin( const char * str_r ) + { + if ( str_r && str_r[0] && str_r[1] && str_r[2] ) + { + switch ( str_r[3] ) + { + // NOTE: it needs to be assertd that the separating ':' is present + // if a known kind is retuirned. Dependent code relies on this! + #define OUTS(K,S) if ( !::strncmp( str_r, ResKind::K.c_str(), S ) && str_r[S] == ':' ) return ResKind::K + // ----v + case 'c': OUTS( patch, 5 ); break; + case 'd': OUTS( product, 7 ); break; + case 'k': OUTS( package, 7 ); break; + case 'l': OUTS( application, 11 );break; + case 'p': OUTS( srcpackage, 10 ); break; + case 't': OUTS( pattern, 7 ); break; + #undef OUTS + } + } + return nokind; + } + + std::string ResKind::satIdent( const ResKind & refers_r, const std::string & name_r ) + { + if ( ! refers_r || refers_r == package || refers_r == srcpackage ) + return name_r; + return str::form( "%s:%s", refers_r.c_str(), name_r.c_str() ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ResKind.h b/zypp/ResKind.h new file mode 100644 index 0000000..44231a0 --- /dev/null +++ b/zypp/ResKind.h @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResKind.h + * +*/ +#ifndef ZYPP_RESKIND_H +#define ZYPP_RESKIND_H + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class ResKind + /// \brief Resolvable kinds. + /// A \b lowercased string and used as identification. Comparison + /// against string values is always case insensitive. + /////////////////////////////////////////////////////////////////// + class ZYPP_API ResKind : public IdStringType + { + public: + /** \name Some builtin ResKind constants. */ + //@{ + /** Value representing \c nokind ("")*/ + static const ResKind nokind; + + static const ResKind package; + static const ResKind patch; + static const ResKind pattern; + static const ResKind product; + static const ResKind srcpackage; + static const ResKind application; + //@} + + /** Return the builtin kind if \a str_r explicitly prefixed. + * \a str_r must start with a builtin kind followed by a \c ':'. + * If no builtin kind is detected, \ref nokind is returned, + * which usually indicates a \ref package or \ref srcpackage. + */ + static ResKind explicitBuiltin( const char * str_r ); + /** \overload */ + static ResKind explicitBuiltin( const std::string & str_r ) + { return explicitBuiltin( str_r.c_str() ); } + /** \overload */ + static ResKind explicitBuiltin( const IdString & str_r ) + { return explicitBuiltin( str_r.c_str() ); } + + public: + /** Default ctor: \ref nokind */ + ResKind() {} + + /** Ctor taking kind as string. */ + explicit ResKind( sat::detail::IdType id_r ) : _str( str::toLower(IdString(id_r).c_str()) ) {} + explicit ResKind( const IdString & idstr_r ) : _str( str::toLower(idstr_r.c_str()) ) {} + explicit ResKind( const std::string & str_r ) : _str( str::toLower(str_r) ) {} + explicit ResKind( const char * cstr_r ) : _str( str::toLower(cstr_r) ) {} + + public: + /** Return libsolv identifier for name. + * Libsolv combines the objects kind and name in a single + * identifier \c "pattern:kde_multimedia", \b except for packages + * and source packes. They are not prefixed by any kind string. + */ + static std::string satIdent( const ResKind & refers_r, const std::string & name_r ); + /** \overload */ + std::string satIdent( const std::string & name_r ) const + { return satIdent( *this, name_r ); } + + private: + static int _doCompare( const char * lhs, const char * rhs ) + { + if ( lhs == rhs ) return 0; + if ( lhs && rhs ) return ::strcasecmp( lhs, rhs ); + return( lhs ? 1 : -1 ); + } + + private: + friend class IdStringType; + IdString _str; + }; + + /** \relates ResKind XML output. */ + inline std::ostream & dumpAsXmlOn( std::ostream & str, const ResKind & obj ) + { return str << "" << obj << ""; } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESKIND_H diff --git a/zypp/ResObject.cc b/zypp/ResObject.cc new file mode 100644 index 0000000..fa98802 --- /dev/null +++ b/zypp/ResObject.cc @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResObject.cc + * +*/ + +#include + +using namespace zypp; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + + IMPL_PTR_TYPE(ResObject); + + ResObject::ResObject( const sat::Solvable & solvable_r ) + : Resolvable( solvable_r ) + {} + + ResObject::~ResObject() + {} + + std::ostream & ResObject::dumpOn( std::ostream & str ) const + { + return Resolvable::dumpOn( str ); + } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + ResObject::Ptr makeResObject( const sat::Solvable & solvable_r ) + { + if ( ! solvable_r ) + return 0; + + ResKind kind( solvable_r.kind() ); +#define OUTS(X) if ( kind == ResTraits::kind ) return make( solvable_r ); + OUTS( Package ); + OUTS( Patch ); + OUTS( Pattern ); + OUTS( Product ); + OUTS( SrcPackage ); + OUTS( Application ); +#undef OUTS + // unknow => return a plain ResObject + return new ResObject( solvable_r ); + } +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ResObject.h b/zypp/ResObject.h new file mode 100644 index 0000000..69f932c --- /dev/null +++ b/zypp/ResObject.h @@ -0,0 +1,156 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResObject.h + * +*/ +#ifndef ZYPP_RESOBJECT_H +#define ZYPP_RESOBJECT_H + +#include + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class ResObject + /// \brief Base for resolvable objects + /// + /// \note \ref Resolvable is a SolvableType, which provides direct + /// access to many of the underlying sat::Solvables properties. + /// Don't add common properties here, but in \ref sat::Solvable + /// and extend \ref sat::SolvableType. + /// + /// \see \ref makeResObject for how to construct ResObjects. + /// \todo Merge with Resolvable + /////////////////////////////////////////////////////////////////// + class ZYPP_API ResObject : public Resolvable + { + public: + using Self = ResObject; + using TraitsType = ResTraits; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + /** Convert \c this into a Ptr of a certain Kind. + * This is a convenience to access type specific + * attributes. + * \return \c NULL if \c this is not of the specified kind. + * \code + * PoolItem pi; + * Package::constPtr pkg = pi->asKind(); + * + * if ( pi->isKind() ) + * DBG << pi->asKind()->keywords() << endl; + * \endcode + */ + template + inline typename ResTraits::constPtrType asKind() const; + + template + inline typename ResTraits::PtrType asKind(); + + public: + /** + * \short Vendor + * \deprecated Though typedef'ed to std::string, Vendor is actually an \ref IdString. + */ + Vendor vendor() const + { return Resolvable::vendor().asString(); } + + protected: + friend ResObject::Ptr makeResObject( const sat::Solvable & solvable_r ); + /** Ctor */ + ResObject( const sat::Solvable & solvable_r ); + /** Dtor */ + ~ResObject() override; + /** Helper for stream output */ + std::ostream & dumpOn( std::ostream & str ) const override; + /** This is a \ref sat::SolvableType (allow implicit conversion in derived classes). */ + operator sat::Solvable() const + { return satSolvable(); } + }; + /////////////////////////////////////////////////////////////////// + + /** Create \ref ResObject from \ref sat::Solvable. + * + * This function creates the apropriate kind of ResObject + * depending on the sat::Solvables kind, and returns a smart + * pointer to it. + * + * If the sat::Solvables kind is not convertible, a NULL + * pointer is returned. + * + * \code + * sat::Solvable s; + * ResObject::Ptr p( makeResObject( s ) ); + * ResObject::Ptr q( make( s ) ); + * Package::Ptr pkg( make( s ) ); + * \endcode + */ + ResObject::Ptr makeResObject( const sat::Solvable & solvable_r ) ZYPP_API; + + /** Directly create a certain kind of ResObject from \ref sat::Solvable. + * + * If the sat::Solvables kind is not appropriate, a NULL + * pointer is returned. + * \code + * sat::Solvable s; + * ResObject::Ptr p( makeResObject( s ) ); + * ResObject::Ptr q( make( s ) ); + * Package::Ptr pkg( make( s ) ); + * \endcode + * \todo make<> was a poor choice (AFAIR because gcc had some trouble with + * asKind<>(sat::Solvable)). Remove it in favour of asKind<>(sat::Solvable) + */ + template + inline typename ResTraits::PtrType make( const sat::Solvable & solvable_r ) + { return( isKind( solvable_r ) ? new TRes( solvable_r ) : 0 ); } + /** \overload Specialisation for ResObject autodetecting the kind of resolvable. */ + template<> + inline ResObject::Ptr make( const sat::Solvable & solvable_r ) + { return makeResObject( solvable_r ); } + + /** Directly create a certain kind of ResObject from \ref sat::Solvable. */ + template + inline typename ResTraits::PtrType asKind( const sat::Solvable & solvable_r ) + { return make( solvable_r ); } + + /** Convert ResObject::Ptr into Ptr of a certain Kind. + * \return \c NULL iff \a p is \c NULL or points to a Resolvable + * not of the specified Kind. + * \relates ResObject + * \code + * asKind(resPtr); + * \endcode + */ + template + inline typename ResTraits::PtrType asKind( const ResObject::Ptr & p ) + { return dynamic_pointer_cast(p); } + + template + inline typename ResTraits::constPtrType asKind( const ResObject::constPtr & p ) + { return dynamic_pointer_cast(p); } + + template + inline typename ResTraits::constPtrType ResObject::asKind() const + { return dynamic_cast( this ); } + + template + inline typename ResTraits::PtrType ResObject::asKind() + { return dynamic_cast( this ); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESOBJECT_H diff --git a/zypp/ResObjects.h b/zypp/ResObjects.h new file mode 100644 index 0000000..e38c520 --- /dev/null +++ b/zypp/ResObjects.h @@ -0,0 +1,22 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResObjects.h + * +*/ +#ifndef ZYPP_RESOBJECTS_H +#define ZYPP_RESOBJECTS_H + +#include +#include +#include +#include +#include +#include + +#endif // ZYPP_RESOBJECTS_H diff --git a/zypp/ResPool.cc b/zypp/ResPool.cc new file mode 100644 index 0000000..70ce19f --- /dev/null +++ b/zypp/ResPool.cc @@ -0,0 +1,156 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResPool.cc + * +*/ +#include +#include +//#include + +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // class ResPool + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResPool::instance + // METHOD TYPE : ResPool + // + ResPool ResPool::instance() + { + static ResPool _val( pool::PoolTraits::Impl_Ptr( new pool::PoolImpl ) ); + return _val; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResPool::ResPool + // METHOD TYPE : Ctor + // + ResPool::ResPool( pool::PoolTraits::Impl_Ptr impl_r ) + : _pimpl( std::move(impl_r) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // Forward to impementation: + // + /////////////////////////////////////////////////////////////////// + + ResPoolProxy ResPool::proxy() const + { return _pimpl->proxy( *this ); } + + Resolver & ResPool::resolver() const + { return *getZYpp()->resolver(); } + + const SerialNumber & ResPool::serial() const + { return _pimpl->serial(); } + + bool ResPool::empty() const + { return _pimpl->empty(); } + + ResPool::size_type ResPool::size() const + { return _pimpl->size(); } + + PoolItem ResPool::find( const sat::Solvable & slv_r ) const + { return _pimpl->find( slv_r ); } + + ResPool::EstablishedStates ResPool::establishedStates() const + { return _pimpl->establishedStates(); } + + ResPool::size_type ResPool::knownRepositoriesSize() const + { return _pimpl->knownRepositoriesSize(); } + + ResPool::repository_iterator ResPool::knownRepositoriesBegin() const + { return _pimpl->knownRepositoriesBegin(); } + + ResPool::repository_iterator ResPool::knownRepositoriesEnd() const + { return _pimpl->knownRepositoriesEnd(); } + + Repository ResPool::reposFind( const std::string & alias_r ) const + { return _pimpl->reposFind( alias_r ); } + + bool ResPool::hardLockQueriesEmpty() const + { return _pimpl->hardLockQueries().empty(); } + + ResPool::size_type ResPool::hardLockQueriesSize() const + { return _pimpl->hardLockQueries().size(); } + + ResPool::hardLockQueries_iterator ResPool::hardLockQueriesBegin() const + { return _pimpl->hardLockQueries().begin(); } + + ResPool::hardLockQueries_iterator ResPool::hardLockQueriesEnd() const + { return _pimpl->hardLockQueries().end(); } + + void ResPool::setHardLockQueries( const HardLockQueries & newLocks_r ) + { _pimpl->setHardLockQueries( newLocks_r ); } + + void ResPool::getHardLockQueries( HardLockQueries & activeLocks_r ) + { _pimpl->getHardLockQueries( activeLocks_r ); } + + + const pool::PoolTraits::ItemContainerT & ResPool::store() const + { return _pimpl->store(); } + + const pool::PoolTraits::Id2ItemT & ResPool::id2item() const + { return _pimpl->id2item(); } + + /////////////////////////////////////////////////////////////////// + // + // Forward to sat::Pool: + // + /////////////////////////////////////////////////////////////////// + void ResPool::setRequestedLocales( const LocaleSet & locales_r ) + { sat::Pool::instance().setRequestedLocales( locales_r ); } + + bool ResPool::addRequestedLocale( const Locale & locale_r ) + { return sat::Pool::instance().addRequestedLocale( locale_r ); } + + bool ResPool::eraseRequestedLocale( const Locale & locale_r ) + { return sat::Pool::instance().eraseRequestedLocale( locale_r ); } + + const LocaleSet & ResPool::getRequestedLocales() const + { return sat::Pool::instance().getRequestedLocales(); } + + bool ResPool::isRequestedLocale( const Locale & locale_r ) const + { return sat::Pool::instance().isRequestedLocale( locale_r ); } + + const LocaleSet & ResPool::getAvailableLocales() const + { return sat::Pool::instance().getAvailableLocales(); } + + bool ResPool::isAvailableLocale( const Locale & locale_r ) const + { return sat::Pool::instance().isAvailableLocale( locale_r ); } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ResPool & obj ) + { + return dumpPoolStats( str << "ResPool " << sat::Pool::instance() << endl << " ", + obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ResPool.h b/zypp/ResPool.h new file mode 100644 index 0000000..f1347ac --- /dev/null +++ b/zypp/ResPool.h @@ -0,0 +1,483 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResPool.h + * +*/ +#ifndef ZYPP_RESPOOL_H +#define ZYPP_RESPOOL_H + +#include +#include + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class SerialNumber; + class ResPoolProxy; + class Resolver; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResPool + // + /** Global ResObject pool. + * + * Explicitly shared singleton. + * + * \note Filter iterators provided by ResPool are intended to + * operate on internal index tables for faster access. If the + * the index is not yet implemented, they are realized as + * an ordinary filter iterator. Do not provide filter iterators + * here, if there is no index table for it. + * + * For most (*Begin,*End) iterator-pairs there's also an \ref Iterable + * provided, so you can use then in range-based for loops: + * \code + * // classic: + * for_( it, pool.filterBegin(myfilter), pool.filterEnd(myfilter) ) + * { ... } + * + * // range based: + * for ( const PoolItem & pi : pool.filter(myfilter) ) + * { ... } + * \endcode + * + * \include n_ResPool_nomorenameiter + */ + class ZYPP_API ResPool + { + friend std::ostream & operator<<( std::ostream & str, const ResPool & obj ); + + public: + /** \ref PoolItem */ + using value_type = PoolItem; + using size_type = pool::PoolTraits::size_type; + using const_iterator = pool::PoolTraits::const_iterator; + using repository_iterator = pool::PoolTraits::repository_iterator; + + public: + /** Singleton ctor. */ + static ResPool instance(); + + /** preliminary */ + ResPoolProxy proxy() const; + + /** The Resolver */ + Resolver & resolver() const; + + public: + /** The pools serial number. Changing whenever the + * whenever the content changes. (Resolvables or + * Dependencies). + */ + const SerialNumber & serial() const; + + public: + /** */ + bool empty() const; + /** */ + size_type size() const; + + /** \name Iterate over all PoolItems (all kinds). */ + //@{ + /** */ + const_iterator begin() const + { return make_filter_begin( pool::ByPoolItem(), store() ); } + /** */ + const_iterator end() const + { return make_filter_end( pool::ByPoolItem(), store() ); } + //@} + + public: + /** Return the corresponding \ref PoolItem. + * Pool and sat pool should be in sync. Returns an empty + * \ref PoolItem if there is no corresponding \ref PoolItem. + * \see \ref PoolItem::satSolvable. + */ + PoolItem find( const sat::Solvable & slv_r ) const; + /** \overload */ + PoolItem find( const ResObject::constPtr & resolvable_r ) const + { return( resolvable_r ? find( resolvable_r->satSolvable() ) : PoolItem() ); } + + public: + /** \name Iterate over all PoolItems matching a \c TFilter. */ + //@{ + template + filter_iterator filterBegin( const TFilter & filter_r ) const + { return make_filter_begin( filter_r, *this ); } + + template + filter_iterator filterEnd( const TFilter & filter_r ) const + { return make_filter_end( filter_r, *this ); } + + template + Iterable > filter( const TFilter & filter_r ) const + { return makeIterable( filterBegin( filter_r ), filterEnd( filter_r ) ); } + //@} + + /** \name Iterate over all PoolItems by status. + * + * Simply pass the \ref ResStatus predicate you want to use as filter: + * \code + * // iterate over all orphaned items: + * for_( it, pool.byStatusBegin(&ResStatus::isOrphaned), pool.byStatusEnd(&ResStatus::isOrphaned) ) + * {...} + * \endcode + * + * Or use \ref filter::ByStatus in more complex queries: + * \code + * // iterate over all (orphaned and recommended) items: + * functor::Chain myfilter( filter::ByStatus(&ResStatus::isOrphaned), + * filter::ByStatus(&ResStatus::isRecommended) ); + * for_( it, pool.filterBegin(myfilter), pool.filterEnd(myfilter) ) + * { ... } + * \endcode + */ + //@{ + filter_iterator byStatusBegin( const filter::ByStatus & filter_r ) const + { return make_filter_begin( filter_r, *this ); } + + filter_iterator byStatusEnd( const filter::ByStatus & filter_r ) const + { return make_filter_end( filter_r, *this ); } + + Iterable > byStatus( const filter::ByStatus & filter_r ) const + { return makeIterable( byStatusBegin( filter_r ), byStatusEnd( filter_r ) ); } + //@} + + public: + /** \name Iterate over all PoolItems of a certain name and kind. */ + //@{ + using ByIdent = pool::ByIdent; + using byIdent_iterator = pool::PoolTraits::byIdent_iterator; + + byIdent_iterator byIdentBegin( const ByIdent & ident_r ) const + { + return make_transform_iterator( id2item().equal_range( ident_r.get() ).first, + pool::PoolTraits::Id2ItemValueSelector() ); + } + + byIdent_iterator byIdentBegin( ResKind kind_r, IdString name_r ) const + { return byIdentBegin( ByIdent(std::move(kind_r),name_r) ); } + + byIdent_iterator byIdentBegin( ResKind kind_r, const C_Str & name_r ) const + { return byIdentBegin( ByIdent(std::move(kind_r),name_r) ); } + + template + byIdent_iterator byIdentBegin( IdString name_r ) const + { return byIdentBegin( ByIdent(ResTraits::kind,name_r) ); } + + template + byIdent_iterator byIdentBegin( const C_Str & name_r ) const + { return byIdentBegin( ByIdent(ResTraits::kind,name_r) ); } + + /** Derive name and kind from \ref PoolItem. */ + byIdent_iterator byIdentBegin( const PoolItem & pi_r ) const + { return byIdentBegin( ByIdent(pi_r.satSolvable()) ); } + /** Derive name and kind from \ref sat::Solvable. */ + byIdent_iterator byIdentBegin( sat::Solvable slv_r ) const + { return byIdentBegin( ByIdent(slv_r) ); } + /** Takes a \ref sat::Solvable::ident string. */ + byIdent_iterator byIdentBegin( IdString ident_r ) const + { return byIdentBegin( ByIdent(ident_r) ); } + + + byIdent_iterator byIdentEnd( const ByIdent & ident_r ) const + { + return make_transform_iterator( id2item().equal_range( ident_r.get() ).second, + pool::PoolTraits::Id2ItemValueSelector() ); + } + + byIdent_iterator byIdentEnd( ResKind kind_r, IdString name_r ) const + { return byIdentEnd( ByIdent(std::move(kind_r),name_r) ); } + + byIdent_iterator byIdentEnd( ResKind kind_r, const C_Str & name_r ) const + { return byIdentEnd( ByIdent(std::move(kind_r),name_r) ); } + + template + byIdent_iterator byIdentEnd( IdString name_r ) const + { return byIdentEnd( ByIdent(ResTraits::kind,name_r) ); } + + template + byIdent_iterator byIdentEnd( const C_Str & name_r ) const + { return byIdentEnd( ByIdent(ResTraits::kind,name_r) ); } + + /** Derive name and kind from \ref PoolItem. */ + byIdent_iterator byIdentEnd( const PoolItem & pi_r ) const + { return byIdentEnd( ByIdent(pi_r.satSolvable()) ); } + /** Derive name and kind from \ref sat::Solvable. */ + byIdent_iterator byIdentEnd( sat::Solvable slv_r ) const + { return byIdentEnd( ByIdent(slv_r) ); } + /** Takes a \ref sat::Solvable::ident string. */ + byIdent_iterator byIdentEnd( IdString ident_r ) const + { return byIdentEnd( ByIdent(ident_r) ); } + + + Iterable byIdent( const ByIdent & ident_r ) const + { return makeIterable( byIdentBegin( ident_r ), byIdentEnd( ident_r ) ); } + + Iterable byIdent( const ResKind& kind_r, IdString name_r ) const + { return makeIterable( byIdentBegin( kind_r, name_r ), byIdentEnd( kind_r, name_r ) ); } + + Iterable byIdent( const ResKind& kind_r, const C_Str & name_r ) const + { return makeIterable( byIdentBegin( kind_r, name_r ), byIdentEnd( kind_r, name_r ) ); } + + template + Iterable byIdent( IdString name_r ) const + { return makeIterable( byIdentBegin( name_r ), byIdentEnd( name_r ) ); } + + template + Iterable byIdent( const C_Str & name_r ) const + { return makeIterable( byIdentBegin( name_r ), byIdentEnd( name_r ) ); } + + Iterable byIdent( const PoolItem & pi_r ) const + { return makeIterable( byIdentBegin( pi_r ), byIdentEnd( pi_r ) ); } + + Iterable byIdent(sat::Solvable slv_r ) const + { return makeIterable( byIdentBegin( slv_r ), byIdentEnd( slv_r ) ); } + + Iterable byIdent( IdString ident_r ) const + { return makeIterable( byIdentBegin( ident_r ), byIdentEnd( ident_r ) ); } + //@} + + public: + /** \name Iterate over all ResObjects of a certain kind. */ + //@{ + using ByKind = filter::ByKind; + using byKind_iterator = filter_iterator; + + byKind_iterator byKindBegin( const ResKind & kind_r ) const + { return make_filter_begin( ByKind(kind_r), *this ); } + + template + byKind_iterator byKindBegin() const + { return make_filter_begin( resfilter::byKind(), *this ); } + + byKind_iterator byKindEnd( const ResKind & kind_r ) const + { return make_filter_end( ByKind(kind_r), *this ); } + + template + byKind_iterator byKindEnd() const + { return make_filter_end( resfilter::byKind(), *this ); } + + Iterable byKind( const ResKind & kind_r ) const + { return makeIterable( byKindBegin( kind_r ), byKindEnd( kind_r ) ); } + + template + Iterable byKind() const + { return makeIterable( byKindBegin(), byKindEnd() ); } + //@} + + public: + /** \name Iterate over all ResObjects with a certain name (all kinds). */ + //@{ + using ByName = zypp::resfilter::ByName; + using byName_iterator = filter_iterator; + + byName_iterator byNameBegin( const std::string & name_r ) const + { return make_filter_begin( ByName(name_r), *this ); } + + byName_iterator byNameEnd( const std::string & name_r ) const + { return make_filter_end( ByName(name_r), *this ); } + + Iterable byName( const std::string & name_r ) const + { return makeIterable( byNameBegin( name_r ), byNameEnd( name_r ) ); } + //@} + + public: + /** \name Misc Data. */ + //@{ + /////////////////////////////////////////////////////////////////// + /// A copy of the Pools initial ValidateValues of pseudo installed items. + /// + /// AKA Patch status. Whenever the Pools content changes, the status + /// of pseudo installed items (like Patches) is computed (roughly whether + /// their dependencies are broken or satisfied) and remembered. + /// + /// Comparing the item's established state against its current state + /// tells how the current transaction would influence the item (break + /// or repair a Patch). + /// + class EstablishedStates + { + public: + ~EstablishedStates(); + /** Map holding pseudo installed items where current and established status differ. */ + using ChangedPseudoInstalled = std::map; + /** Return all pseudo installed items whose current state differs from the established one */ + ChangedPseudoInstalled changedPseudoInstalled() const; + private: + class Impl; + RW_pointer _pimpl; + private: + friend class pool::PoolImpl; + /** Factory: \ref ResPool::establishedStates */ + EstablishedStates( shared_ptr pimpl_r ) + : _pimpl { std::move(pimpl_r) } + {} + }; + /////////////////////////////////////////////////////////////////// + + /** Factory for \ref EstablishedStates. + * A few internal algorithms benefit from keeping an instance across pool + * content changes. User code usually want's to call \ref changedPseudoInstalled + * directly. + */ + EstablishedStates establishedStates() const; + + /** Map holding pseudo installed items where current and established status differ. */ + using ChangedPseudoInstalled = EstablishedStates::ChangedPseudoInstalled; + + /** Return all pseudo installed items whose current state differs from their initial one. + * E.g. a Patch may become SATISFIED by updating the packages it refers to. + * For this to happen it does not matter whether you selected the Patch or + * whether you selected the individual Packages. + * A Patches status is computed and updated with every solver run. + */ + ChangedPseudoInstalled changedPseudoInstalled() const + { return establishedStates().changedPseudoInstalled(); } + //@} + public: + /** \name Iterate over all Repositories that contribute ResObjects. + */ + //@{ + size_type knownRepositoriesSize() const; + + repository_iterator knownRepositoriesBegin() const; + + repository_iterator knownRepositoriesEnd() const; + + /** Find a \ref Repository named \c alias_r. + * Returns \ref Repository::noRepository if there is no such \ref Repository. + */ + Repository reposFind( const std::string & alias_r ) const; + + Iterable knownRepositories() const + { return makeIterable( knownRepositoriesBegin(), knownRepositoriesEnd() ); } + //@} + + public: + /** \name Handle locale support. + * + * A \ref filter::ByLocaleSupport is provided to iterate over + * all items supporting a specific locale. + * + * \see \ref sat::LocaleSupport for a more convenient interface. + * + * \code + * ResPool pool( ResPool::instance() ); + * + * filter::ByLocaleSupport f( Locale("de") ); + * for_( it, pool.filterBegin(f), pool.filterEnd(f) ) + * { + * MIL << *it << endl; // supporting "de" + * } + * + * f = filter::ByLocaleSupport( pool.getRequestedLocales() ); + * for_( it, pool.filterBegin(f), pool.filterEnd(f) ) + * { + * MIL << *it << endl; // supporting any requested locale + * } + * \endcode + */ + //@{ + /** Set the requested locales. + * Languages to be supported by the system, e.g. language specific + * packages to be installed. + */ + void setRequestedLocales( const LocaleSet & locales_r ); + + /** Add one \ref Locale to the set of requested locales. + * Return \c true if \c locale_r was newly added to the set. + */ + bool addRequestedLocale( const Locale & locale_r ); + + /** Erase one \ref Locale from the set of requested locales. + * Return \c false if \c locale_r was not found in the set. + */ + bool eraseRequestedLocale( const Locale & locale_r ); + + /** Return the requested locales. + * \see \ref setRequestedLocales + */ + const LocaleSet & getRequestedLocales() const; + + /** Whether this \ref Locale is in the set of requested locales. */ + bool isRequestedLocale( const Locale & locale_r ) const; + + /** Get the set of available locales. + * This is computed from the package data so it actually + * represents all locales packages claim to support. + */ + const LocaleSet & getAvailableLocales() const; + + /** Whether this \ref Locale is in the set of available locales. */ + bool isAvailableLocale( const Locale & locale_r ) const; + //@} + + public: + /** \name Handle hard locks (e.g set from /etc/zypp/locks). + * + * As this kind of lock is query based, it's quite expensive. + * + * These queries are re-evaluated when adding new repos to the pool. + */ + //@{ + using HardLockQueries = pool::PoolTraits::HardLockQueries; + using hardLockQueries_iterator = pool::PoolTraits::hardLockQueries_iterator; + + bool hardLockQueriesEmpty() const; + size_type hardLockQueriesSize() const; + hardLockQueries_iterator hardLockQueriesBegin() const; + hardLockQueries_iterator hardLockQueriesEnd() const; + + Iterable hardLockQueries() const + { return makeIterable( hardLockQueriesBegin(), hardLockQueriesEnd() ); } + + /** Set a new set of queries. + * The hard-locks of existing PoolItems are adjusted according + * to the queries. (usually called on target load) + */ + void setHardLockQueries( const HardLockQueries & newLocks_r ); + + /** Suggest a new set of queries based on the current selection. + * (usually remembered on commit). + */ + void getHardLockQueries( HardLockQueries & activeLocks_r ); + //@} + + private: + const pool::PoolTraits::ItemContainerT & store() const; + const pool::PoolTraits::Id2ItemT & id2item() const; + + private: + /** Ctor */ + ResPool( pool::PoolTraits::Impl_Ptr impl_r ); + /** Access to implementation. */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ResPool Stream output */ + std::ostream & operator<<( std::ostream & str, const ResPool & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#include + +#endif // ZYPP_RESPOOL_H diff --git a/zypp/ResPoolProxy.cc b/zypp/ResPoolProxy.cc new file mode 100644 index 0000000..a461a20 --- /dev/null +++ b/zypp/ResPoolProxy.cc @@ -0,0 +1,338 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResPoolProxy.cc + * +*/ +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Tem. friend of PoolItem */ + struct PoolItemSaver + { + void saveState( const ResPool& pool_r ) + { + std::for_each( pool_r.begin(), pool_r.end(), + std::mem_fn(&PoolItem::saveState) ); + } + + void saveState( const ResPool& pool_r, const ResKind & kind_r ) + { + std::for_each( pool_r.byKindBegin(kind_r), pool_r.byKindEnd(kind_r), + std::mem_fn(&PoolItem::saveState) ); + } + + void restoreState( const ResPool& pool_r ) + { + std::for_each( pool_r.begin(), pool_r.end(), + std::mem_fn(&PoolItem::restoreState) ); + } + + void restoreState( const ResPool& pool_r, const ResKind & kind_r ) + { + std::for_each( pool_r.byKindBegin(kind_r), pool_r.byKindEnd(kind_r), + std::mem_fn(&PoolItem::restoreState) ); + } + + bool diffState( const ResPool& pool_r ) const + { + // return whether some PoolItem::sameState reported \c false. + return( invokeOnEach( pool_r.begin(), pool_r.end(), + std::mem_fn(&PoolItem::sameState) ) < 0 ); + } + + bool diffState( const ResPool& pool_r, const ResKind & kind_r ) const + { + // return whether some PoolItem::sameState reported \c false. + return( invokeOnEach( pool_r.byKindBegin(kind_r), pool_r.byKindEnd(kind_r), + std::mem_fn(&PoolItem::sameState) ) < 0 ); + } + }; + + namespace + { + ui::Selectable::Ptr makeSelectablePtr( pool::PoolImpl::Id2ItemT::const_iterator begin_r, + pool::PoolImpl::Id2ItemT::const_iterator end_r ) + { + pool::PoolTraits::byIdent_iterator begin( begin_r, pool::PoolTraits::Id2ItemValueSelector() ); + pool::PoolTraits::byIdent_iterator end( end_r, pool::PoolTraits::Id2ItemValueSelector() ); + sat::Solvable solv( begin->satSolvable() ); + + return new ui::Selectable( ui::Selectable::Impl_Ptr( new ui::Selectable::Impl( solv.kind(), solv.name(), begin, end ) ) ); + } + } // namespace + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResPoolProxy::Impl + // + /** ResPoolProxy implementation. + * \todo Seedup as it is still using old index + */ + struct ResPoolProxy::Impl + { + friend std::ostream & operator<<( std::ostream & str, const Impl & obj ); + friend std::ostream & dumpOn( std::ostream & str, const Impl & obj ); + + using SelectableIndex = std::unordered_map; + using const_iterator = ResPoolProxy::const_iterator; + + public: + Impl() + :_pool( ResPool::instance() ) + {} + + Impl( ResPool &&pool_r, const pool::PoolImpl & poolImpl_r ) + : _pool( std::move(pool_r) ) + { + const pool::PoolImpl::Id2ItemT & id2item( poolImpl_r.id2item() ); + if ( ! id2item.empty() ) + { + // set startpoint + pool::PoolImpl::Id2ItemT::const_iterator cbegin = id2item.begin(); + + for_( it, id2item.begin(), id2item.end() ) + { + if ( it->first != cbegin->first ) + { + // starting a new Selectable, create the previous one + ui::Selectable::Ptr p( makeSelectablePtr( cbegin, it ) ); + _selPool.insert( SelectablePool::value_type( p->kind(), p ) ); + _selIndex[cbegin->first] = p; + // remember new startpoint + cbegin = it; + } + } + // create the final one + ui::Selectable::Ptr p( makeSelectablePtr( cbegin, id2item.end() ) ); + _selPool.insert( SelectablePool::value_type( p->kind(), p ) ); + _selIndex[cbegin->first] = p; + } + } + + public: + ui::Selectable::Ptr lookup( const pool::ByIdent & ident_r ) const + { + SelectableIndex::const_iterator it( _selIndex.find( ident_r.get() ) ); + if ( it != _selIndex.end() ) + return it->second; + return ui::Selectable::Ptr(); + } + + public: + bool empty() const + { return _selPool.empty(); } + + size_type size() const + { return _selPool.size(); } + + const_iterator begin() const + { return make_map_value_begin( _selPool ); } + + const_iterator end() const + { return make_map_value_end( _selPool ); } + + public: + bool empty( const ResKind & kind_r ) const + { return( _selPool.count( kind_r ) == 0 ); } + + size_type size( const ResKind & kind_r ) const + { return _selPool.count( kind_r ); } + + const_iterator byKindBegin( const ResKind & kind_r ) const + { return make_map_value_lower_bound( _selPool, kind_r ); } + + const_iterator byKindEnd( const ResKind & kind_r ) const + { return make_map_value_upper_bound( _selPool, kind_r ); } + + public: + size_type knownRepositoriesSize() const + { return _pool.knownRepositoriesSize(); } + + repository_iterator knownRepositoriesBegin() const + { return _pool.knownRepositoriesBegin(); } + + repository_iterator knownRepositoriesEnd() const + { return _pool.knownRepositoriesEnd(); } + + public: + + void saveState() const + { PoolItemSaver().saveState( _pool ); } + + void saveState( const ResKind & kind_r ) const + { PoolItemSaver().saveState( _pool, kind_r ); } + + void restoreState() const + { PoolItemSaver().restoreState( _pool ); } + + void restoreState( const ResKind & kind_r ) const + { PoolItemSaver().restoreState( _pool, kind_r ); } + + bool diffState() const + { return PoolItemSaver().diffState( _pool ); } + + bool diffState( const ResKind & kind_r ) const + { return PoolItemSaver().diffState( _pool, kind_r ); } + + private: + ResPool _pool; + mutable SelectablePool _selPool; + mutable SelectableIndex _selIndex; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ResPoolProxy::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const ResPoolProxy::Impl & obj ) + { + return str << "ResPoolProxy (" << obj._pool.serial() << ") [" << obj._pool.size() + << "solv/" << obj.size()<< "sel]"; + } + + namespace detail + { + struct DumpFilter + { + bool operator()( const ui::Selectable::Ptr & selp ) const + { return selp->toModify(); } + }; + } + + /** \relates ResPoolProxy::Impl Verbose stream output */ + inline std::ostream & dumpOn( std::ostream & str, const ResPoolProxy::Impl & obj ) + { + detail::DumpFilter f; + return dumpRange( str << obj << " toModify: ", + make_filter_begin( f, obj ), + make_filter_end( f, obj ) ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResPoolProxy + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResPoolProxy::ResPoolProxy + // METHOD TYPE : Ctor + // + ResPoolProxy::ResPoolProxy() + : _pimpl( Impl::nullimpl() ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResPoolProxy::ResPoolProxy + // METHOD TYPE : Ctor + // + ResPoolProxy::ResPoolProxy( ResPool pool_r, const pool::PoolImpl & poolImpl_r ) + : _pimpl( new Impl( std::move(pool_r), poolImpl_r ) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResPoolProxy::~ResPoolProxy + // METHOD TYPE : Dtor + // + ResPoolProxy::~ResPoolProxy() + {} + + /////////////////////////////////////////////////////////////////// + // + // forward to implementation + // + /////////////////////////////////////////////////////////////////// + + ui::Selectable::Ptr ResPoolProxy::lookup( const pool::ByIdent & ident_r ) const + { return _pimpl->lookup( ident_r ); } + + bool ResPoolProxy::empty() const + { return _pimpl->empty(); } + + ResPoolProxy::size_type ResPoolProxy::size() const + { return _pimpl->size(); } + + ResPoolProxy::const_iterator ResPoolProxy::begin() const + { return _pimpl->begin(); } + + ResPoolProxy::const_iterator ResPoolProxy::end() const + { return _pimpl->end(); } + + bool ResPoolProxy::empty( const ResKind & kind_r ) const + { return _pimpl->empty( kind_r ); } + + ResPoolProxy::size_type ResPoolProxy::size( const ResKind & kind_r ) const + { return _pimpl->size( kind_r ); } + + ResPoolProxy::const_iterator ResPoolProxy::byKindBegin( const ResKind & kind_r ) const + { return _pimpl->byKindBegin( kind_r ); } + + ResPoolProxy::const_iterator ResPoolProxy::byKindEnd( const ResKind & kind_r ) const + { return _pimpl->byKindEnd( kind_r ); } + + ResPoolProxy::size_type ResPoolProxy::knownRepositoriesSize() const + { return _pimpl->knownRepositoriesSize(); } + + ResPoolProxy::repository_iterator ResPoolProxy::knownRepositoriesBegin() const + { return _pimpl->knownRepositoriesBegin(); } + + ResPoolProxy::repository_iterator ResPoolProxy::knownRepositoriesEnd() const + { return _pimpl->knownRepositoriesEnd(); } + + void ResPoolProxy::saveState() const + { _pimpl->saveState(); } + + void ResPoolProxy::saveState( const ResKind & kind_r ) const + { _pimpl->saveState( kind_r ); } + + void ResPoolProxy::restoreState() const + { _pimpl->restoreState(); } + + void ResPoolProxy::restoreState( const ResKind & kind_r ) const + { _pimpl->restoreState( kind_r ); } + + bool ResPoolProxy::diffState() const + { return _pimpl->diffState(); } + + bool ResPoolProxy::diffState( const ResKind & kind_r ) const + { return _pimpl->diffState( kind_r ); } + + std::ostream & operator<<( std::ostream & str, const ResPoolProxy & obj ) + { return str << *obj._pimpl; } + + std::ostream & dumpOn( std::ostream & str, const ResPoolProxy & obj ) + { return dumpOn( str, *obj._pimpl ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ResPoolProxy.h b/zypp/ResPoolProxy.h new file mode 100644 index 0000000..cf16d6f --- /dev/null +++ b/zypp/ResPoolProxy.h @@ -0,0 +1,311 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResPoolProxy.h + * +*/ +#ifndef ZYPP_RESPOOLPROXY_H +#define ZYPP_RESPOOLPROXY_H + +#include +#include + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResPoolProxy + // + /** ResPool::instance().proxy(); + * \todo integrate it into ResPool + */ + class ZYPP_API ResPoolProxy + { + friend std::ostream & operator<<( std::ostream & str, const ResPoolProxy & obj ); + friend std::ostream & dumpOn( std::ostream & str, const ResPoolProxy & obj ); + using SelectablePool = std::multimap; + + public: + /** Implementation */ + struct Impl; + + using const_iterator = MapKVIteratorTraits::Value_const_iterator; + using size_type = SelectablePool::size_type; + + using repository_iterator = ResPool::repository_iterator; + + public: + + /** Default ctor: no pool + * Nonempty proxies are provided by \ref ResPool. + * \see \ref ResPool::proxy + * \code + * ResPoolProxy p( ResPool::instance().proxy() ); + * \endcode + */ + ResPoolProxy(); + + /** Dtor */ + ~ResPoolProxy(); + + public: + /** \name Lookup individual Selectables. */ + //@{ + ui::Selectable::Ptr lookup( const pool::ByIdent & ident_r ) const; + + ui::Selectable::Ptr lookup( IdString ident_r ) const + { return lookup( pool::ByIdent( ident_r ) ); } + + ui::Selectable::Ptr lookup( ResKind kind_r, const std::string & name_r ) const + { return lookup( pool::ByIdent( std::move(kind_r), name_r ) ); } + + ui::Selectable::Ptr lookup( const sat::Solvable & solv_r ) const + { return lookup( pool::ByIdent( solv_r ) ); } + + ui::Selectable::Ptr lookup( const ResObject::constPtr & resolvable_r ) const + { return resolvable_r ? lookup( resolvable_r->satSolvable() ) : ui::Selectable::Ptr(); } + + ui::Selectable::Ptr lookup( const PoolItem & pi_r ) const + { return lookup( pi_r.satSolvable() ); } + //@} + + public: + /** \name Iterate through all Selectables of a all kind. */ + //@{ + bool empty() const; + size_type size() const; + const_iterator begin() const; + const_iterator end() const; + //@} + + /** \name Iterate through all Selectables of a certain kind. */ + //@{ + /** True if there are items of a certain kind. */ + bool empty( const ResKind & kind_r ) const; + + template + bool empty() const + { return empty( ResTraits::kind ); } + + /** Number of Items of a certain kind. */ + size_type size( const ResKind & kind_r ) const; + + template + size_type size() const + { return size( ResTraits::kind ); } + + const_iterator byKindBegin( const ResKind & kind_r ) const; + + template + const_iterator byKindBegin() const + { return byKindBegin( ResTraits::kind ); } + + + const_iterator byKindEnd( const ResKind & kind_r ) const; + + template + const_iterator byKindEnd() const + { return byKindEnd( ResTraits::kind ); } + + + Iterable byKind( const ResKind & kind_r ) const + { return makeIterable( byKindBegin( kind_r ), byKindEnd( kind_r ) ); } + + template + Iterable byKind() const + { return makeIterable( byKindBegin(), byKindEnd() ); } + + //@} + + public: + /** \name Iterate through all Repositories that contribute ResObjects. + */ + //@{ + size_type knownRepositoriesSize() const; + + repository_iterator knownRepositoriesBegin() const; + + repository_iterator knownRepositoriesEnd() const; + + Iterable knownRepositories() const + { return makeIterable( knownRepositoriesBegin(), knownRepositoriesEnd() ); } + //@} + + public: + /** Test whether there is at least one ui::Selectable with + * an installed object. + */ + bool hasInstalledObj( const ResKind & kind_r ) const + { + return( make_begin( kind_r ) + != make_end( kind_r ) ); + } + + template + bool hasInstalledObj() const + { return hasInstalledObj( ResTraits::kind ); } + + public: + /** \name Save and restore state per kind of resolvable. + * Simple version, no safety net. So don't restore or diff, + * if you didn't save before. + * + * Diff returns true, if current stat differs from the saved + * state. + * + * Use \ref scopedSaveState for exception safe scoped save/restore + */ + //@{ + void saveState() const; + + void saveState( const ResKind & kind_r ) const; + + template + void saveState() const + { return saveState( ResTraits::kind ); } + + void restoreState() const; + + void restoreState( const ResKind & kind_r ) const; + + template + void restoreState() const + { return restoreState( ResTraits::kind ); } + + bool diffState() const; + + bool diffState( const ResKind & kind_r ) const; + + template + bool diffState() const + { return diffState( ResTraits::kind ); } + + /** + * \class ScopedSaveState + * \brief Exception safe scoped save/restore state. + * Call \ref acceptState to prevent the class from restoring + * the remembered state. + * \ingroup g_RAII + */ + struct ScopedSaveState; + + ScopedSaveState scopedSaveState() const; + + ScopedSaveState scopedSaveState( const ResKind & kind_r ) const; + + template + ScopedSaveState && scopedSaveState() const + { return scopedSaveState( ResTraits::kind ); } + + //@} + + private: + template + filter_iterator + make_begin( TFilter filter_r, const ResKind & kind_r ) const + { + return make_filter_iterator( filter_r, + byKindBegin(kind_r), + byKindEnd(kind_r) ); + } + template + filter_iterator + make_begin( const ResKind & kind_r ) const + { + return make_begin( TFilter(), kind_r ); + } + + + template + filter_iterator + make_end( TFilter filter_r, const ResKind & kind_r ) const + { + return make_filter_iterator( filter_r, + byKindEnd(kind_r), + byKindEnd(kind_r) ); + } + template + filter_iterator + make_end( const ResKind & kind_r ) const + { + return make_end( TFilter(), kind_r ); + } + + private: + friend class pool::PoolImpl; + /** Ctor */ + ResPoolProxy( ResPool pool_r, const pool::PoolImpl & poolImpl_r ); + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ResPoolProxy Stream output */ + std::ostream & operator<<( std::ostream & str, const ResPoolProxy & obj ); + + /** \relates ResPoolProxy Verbose stream output */ + std::ostream & dumpOn( std::ostream & str, const ResPoolProxy & obj ); + + /////////////////////////////////////////////////////////////////// + + struct ResPoolProxy::ScopedSaveState + { + NON_COPYABLE_BUT_MOVE( ScopedSaveState ); + + ScopedSaveState( const ResPoolProxy & pool_r ) + : _pimpl( new Impl( pool_r ) ) + { _pimpl->saveState(); } + + ScopedSaveState( const ResPoolProxy & pool_r, const ResKind & kind_r ) + : _pimpl( new Impl( pool_r, kind_r ) ) + { _pimpl->saveState(); } + + ~ScopedSaveState() + { if ( _pimpl ) _pimpl->restoreState(); } + + void acceptState() + { _pimpl.reset(); } + + private: + struct Impl + { + Impl( const ResPoolProxy & pool_r ) + : _pool( pool_r ) + {} + Impl( const ResPoolProxy & pool_r, const ResKind & kind_r ) + : _pool( pool_r ), _kind( new ResKind( kind_r ) ) + {} + void saveState() + { if ( _kind ) _pool.saveState( *_kind ); else _pool.saveState(); } + void restoreState() + { if ( _kind ) _pool.restoreState( *_kind ); else _pool.restoreState(); } + ResPoolProxy _pool; + scoped_ptr _kind; + + }; + std::unique_ptr _pimpl; + }; + + inline ResPoolProxy::ScopedSaveState ResPoolProxy::scopedSaveState() const + { return ScopedSaveState( *this ); } + + inline ResPoolProxy::ScopedSaveState ResPoolProxy::scopedSaveState( const ResKind & kind_r ) const + { return ScopedSaveState( *this, kind_r ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESPOOLPROXY_H diff --git a/zypp/ResStatus.cc b/zypp/ResStatus.cc new file mode 100644 index 0000000..009a054 --- /dev/null +++ b/zypp/ResStatus.cc @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResStatus.cc + * +*/ +#include +//#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const ResStatus ResStatus::toBeInstalled (UNINSTALLED, UNDETERMINED, TRANSACT); + const ResStatus ResStatus::toBeUninstalled (INSTALLED, UNDETERMINED, TRANSACT); + const ResStatus ResStatus::toBeUninstalledDueToUpgrade (INSTALLED, UNDETERMINED, TRANSACT, EXPLICIT_INSTALL, DUE_TO_UPGRADE); + const ResStatus ResStatus::toBeUninstalledDueToObsolete(INSTALLED, UNDETERMINED, TRANSACT, EXPLICIT_INSTALL, DUE_TO_OBSOLETE); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResStatus::ResStatus + // METHOD TYPE : Ctor + // + ResStatus::ResStatus() + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResStatus::ResStatus + // METHOD TYPE : Ctor + // + ResStatus::ResStatus( bool isInstalled_r ) + : _bitfield( isInstalled_r ? INSTALLED : UNINSTALLED ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ResStatus::~ResStatus + // METHOD TYPE : Dtor + // + ResStatus::~ResStatus() + {} + + + ResStatus::ResStatus (enum StateValue s, enum ValidateValue v, enum TransactValue t, enum InstallDetailValue i, enum RemoveDetailValue r) + : _bitfield (s) + { + fieldValueAssign(v); + fieldValueAssign(t); + if (t == TRANSACT) { + if (s == INSTALLED) fieldValueAssign(r); + else fieldValueAssign(i); + } + } + + namespace + { + // NOTE: Strings defined here are written to the history file + // and used by zypper. Do not change them! + static const char* strBROKEN = "needed"; + static const char* strSATISFIED = "applied"; + static const char* strNONRELEVANT = "not-needed"; + static const char* strUNDETERMINED = "undetermined"; + } + + std::string ResStatus::validateValueAsString( ValidateValue val_r ) + { + const char* ret = strUNDETERMINED; + switch ( val_r ) + { + case BROKEN: ret = strBROKEN; break; + case SATISFIED: ret = strSATISFIED; break; + case NONRELEVANT: ret = strNONRELEVANT; break; + case UNDETERMINED:break;// to avoid default: + } + return ret; + } + + ResStatus::ValidateValue ResStatus::stringToValidateValue( const std::string & str_r ) + { + ValidateValue ret = UNDETERMINED; + if ( str_r == strBROKEN ) ret = BROKEN; + else if ( str_r == strSATISFIED ) ret = SATISFIED; + else if ( str_r == strNONRELEVANT ) ret = NONRELEVANT; + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ResStatus & obj ) + { + str << (obj.isInstalled() ? "I" : "U"); + + str << (obj.isBroken() ? "B" : + ( obj.isSatisfied() ? "S" : + ( obj.isNonRelevant() ? "N" : "_") ) ); + + str << (obj.transacts () ? "T" + : (obj.isLocked() ? "L" : "_") ); + + if (obj.isBySolver()) str << "s"; + else if (obj.isByApplLow()) str << "l"; + else if (obj.isByApplHigh()) str << "h"; + else if (obj.isByUser()) str << "u"; + + str << (obj.isToBeUninstalledDueToObsolete() ? "O" : + ( obj.isToBeUninstalledDueToUpgrade() ? "U" : + ( obj.isToBeInstalledSoft() ? "S" : "_" ) ) ); + + str << (obj.isRecommended() ? "r" : "" ); + str << (obj.isSuggested() ? "s" : "" ); + str << (obj.isOrphaned() ? "o" : "" ); + str << (obj.isUnneeded() ? "u" : "" ); + + return str; + } + + +#define OUTS(X) case ResStatus::X: return str << #X; break + + std::ostream & operator<<( std::ostream & str, ResStatus::TransactValue obj ) + { + switch ( obj ) + { + OUTS( KEEP_STATE ); + OUTS( LOCKED ); + OUTS( TRANSACT ); + } + return str; + } + + std::ostream & operator<<( std::ostream & str, ResStatus::TransactByValue obj ) + { + switch ( obj ) + { + OUTS( SOLVER ); + OUTS( APPL_LOW ); + OUTS( APPL_HIGH ); + OUTS( USER ); + } + return str; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ResStatus.h b/zypp/ResStatus.h new file mode 100644 index 0000000..9e5c46d --- /dev/null +++ b/zypp/ResStatus.h @@ -0,0 +1,754 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResStatus.h + * +*/ +#ifndef ZYPP_RESSTATUS_H +#define ZYPP_RESSTATUS_H + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace resstatus + { + struct UserLockQueryManip; + class StatusBackup; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ResStatus + // + /** Status bitfield. + * + * \li \c StateField Whether the resolvable is or uninstalled (available). + * \li \c ValidateField Validate status computed by the solver as + * nonrelevant: it is unimportant for the user + * satisfied: it important nothing has to be done + * broken: it is incomplete. So e.g. an update is needed + * \li \c TransactField Whether to transact this resolvable + * (delete if installed install if uninstalled). + * In case the resolvable is locked, only USER may modify the + * transact bit. + * \li \c TransactByField Who triggered the transaction. Transaction + * bit may be reset by higer levels only. + * \li \c TransactDetailField Reason why the Resolvable transacts. + * Splitted into \c InstallDetailValue and \c RemoveDetailValue + * dependent on the kind of transaction. + * \li \c WeakField The solvable will be recommended/suggested by + * a to be installed/deleted solvable. + * + */ + class ZYPP_API ResStatus + { + friend std::ostream & operator<<( std::ostream & str, const ResStatus & obj ); + friend bool operator==( const ResStatus & lhs, const ResStatus & rhs ); + + public: + /** \name BitField range definitions. + * + * \note Enlarge FieldType if more bits are needed. It's not yet + * checked by the compiler. + */ + //@{ + using FieldType = uint16_t; + using BitFieldType = bit::BitField; + // Bit Ranges within FieldType defined by 1st bit and size: + using StateField = bit::Range; + using ValidateField = bit::Range; + using TransactField = bit::Range; + using TransactByField = bit::Range; + using TransactDetailField = bit::Range; + using LicenceConfirmedField = bit::Range; + using WeakField = bit::Range; + using UserLockQueryField = bit::Range; // internal + // enlarge FieldType if more bits are needed. It's not yet + // checked by the compiler. + //@} + public: + + /** \name Status values. + * + * Each enum corresponds to a BitField range. + * \note Take care that enumerator values actually fit into + * the corresponding field. It's not yet checked by the compiler. + */ + //@{ + enum StateValue + { + UNINSTALLED = bit::RangeValue::value, + INSTALLED = bit::RangeValue::value + }; + enum ValidateValue + { + UNDETERMINED = bit::RangeValue::value, + BROKEN = bit::RangeValue::value, + SATISFIED = bit::RangeValue::value, + NONRELEVANT = bit::RangeValue::value + }; + enum TransactValue + { + KEEP_STATE = bit::RangeValue::value, + LOCKED = bit::RangeValue::value, // locked, must not transact + TRANSACT = bit::RangeValue::value // transact according to state + }; + enum TransactByValue + { + SOLVER = bit::RangeValue::value, + APPL_LOW = bit::RangeValue::value, + APPL_HIGH = bit::RangeValue::value, + USER = bit::RangeValue::value + }; + + enum DetailValue + { + /** Detail for no transact, i.e. reset any Install/RemoveDetailValue. */ + NO_DETAIL = bit::RangeValue::value, + }; + enum InstallDetailValue + { + EXPLICIT_INSTALL = bit::RangeValue::value, + SOFT_INSTALL = bit::RangeValue::value + }; + enum RemoveDetailValue + { + EXPLICIT_REMOVE = bit::RangeValue::value, + SOFT_REMOVE = bit::RangeValue::value, + DUE_TO_OBSOLETE = bit::RangeValue::value, + DUE_TO_UPGRADE = bit::RangeValue::value + }; + + enum LicenceConfirmedValue + { + LICENCE_UNCONFIRMED = bit::RangeValue::value, + LICENCE_CONFIRMED = bit::RangeValue::value + }; + + enum WeakValue // Unlike the other fields those are BITS that may be or'ed! + { + NO_WEAK = bit::RangeValue::value, + SUGGESTED = bit::RangeValue::value, + RECOMMENDED = bit::RangeValue::value, + ORPHANED = bit::RangeValue::value, + UNNEEDED = bit::RangeValue::value + }; + + enum UserLockQuery // internal + { + USERLOCK_NOMATCH = bit::RangeValue::value, + USERLOCK_MATCH = bit::RangeValue::value + }; + //@} + + public: + + /** Default ctor. */ + ResStatus(); + + /** Ctor setting the initial . */ + ResStatus( bool isInstalled_r ); + + /** Dtor. */ + ~ResStatus(); + + ResStatus(const ResStatus &) = default; + ResStatus(ResStatus &&) noexcept = default; + ResStatus &operator=(const ResStatus &) = default; + ResStatus &operator=(ResStatus &&) noexcept = default; + + /** Debug helper returning the bitfield. + * It's save to expose the bitfield, as it can't be used to + * recreate a ResStatus. So it is not possible to bypass + * transition rules. + */ + BitFieldType bitfield() const + { return _bitfield; } + + public: + + bool isLicenceConfirmed() const + { return fieldValueIs( LICENCE_CONFIRMED ); } + + void setLicenceConfirmed( bool toVal_r = true ) + { fieldValueAssign( toVal_r ? LICENCE_CONFIRMED : LICENCE_UNCONFIRMED ); } + + public: + bool isRecommended() const + { return _bitfield.test( RECOMMENDED ); } + + bool isSuggested() const + { return _bitfield.test( SUGGESTED ); } + + bool isOrphaned() const + { return _bitfield.test( ORPHANED ); } + + bool isUnneeded() const + { return _bitfield.test( UNNEEDED ); } + + bool hasWeak() const + { return ! fieldValueIs( NO_WEAK ); } + + void resetWeak() + { return fieldValueAssign( NO_WEAK ); } + + void setRecommended( bool toVal_r = true ) + { _bitfield.set( RECOMMENDED, toVal_r ); } + + void setSuggested( bool toVal_r = true ) + { _bitfield.set( SUGGESTED, toVal_r ); } + + void setOrphaned( bool toVal_r = true ) + { _bitfield.set( ORPHANED, toVal_r ); } + + void setUnneeded( bool toVal_r = true ) + { _bitfield.set( UNNEEDED, toVal_r ); } + + public: + ValidateValue validate() const + { return (ValidateValue)_bitfield.value(); } + + bool isUndetermined() const + { return fieldValueIs( UNDETERMINED ); } + + bool isSatisfied() const + { return fieldValueIs( SATISFIED ); } + + bool isBroken() const + { return fieldValueIs( BROKEN ); } + + bool isNonRelevant() const + { return fieldValueIs( NONRELEVANT ); } + + std::string validateValueAsString() const + { return validateValueAsString( validate() ); } + + /** ValidateValue to string used in the history file. */ + static std::string validateValueAsString( ValidateValue val_r ); + + /** ValidateValue from string used in the history file. */ + static ValidateValue stringToValidateValue( const std::string & str_r ); + + public: + // These two are IMMUTABLE! + + bool isInstalled() const + { return fieldValueIs( INSTALLED ); } + + bool isUninstalled() const + { return fieldValueIs( UNINSTALLED ); } + + public: + + bool staysInstalled() const + { return isInstalled() && !transacts(); } + + bool wasInstalled() const { return staysInstalled(); } //for old status + + bool isToBeInstalled() const + { return isUninstalled() && transacts(); } + + bool staysUninstalled() const + { return isUninstalled() && !transacts(); } + + bool wasUninstalled() const { return staysUninstalled(); } // for old status + + bool isToBeUninstalled() const + { return isInstalled() && transacts(); } + + bool isLocked() const + { return fieldValueIs( LOCKED ); } + + bool isUserLocked() const + { return isLocked() && isByUser(); } + + bool isSoftLocked() const + { return isKept() && ( isByApplLow() || isByUser() ); } + + bool isKept() const + { return fieldValueIs( KEEP_STATE ); } + + bool transacts() const + { return fieldValueIs( TRANSACT ); } + + TransactValue getTransactValue() const + { return (TransactValue)_bitfield.value(); } + + /** True if would be on system after commit. */ + bool onSystem() const + { return( isInstalled() != transacts() ); } + + /** True if would be off system after commit. */ + bool offSystem() const + { return ! onSystem(); } + + bool isBySolver() const + { return fieldValueIs( SOLVER ); } + + bool isByApplLow() const + { return fieldValueIs( APPL_LOW ); } + + bool isByApplHigh() const + { return fieldValueIs( APPL_HIGH ); } + + bool isByUser() const + { return fieldValueIs( USER ); } + + TransactByValue getTransactByValue() const + { return (TransactByValue)_bitfield.value(); } + + bool setTransactByValue(TransactByValue causer) + { + if ( isLessThan( causer ) ) { + fieldValueAssign( causer ); + return true; + } else { + return false; + } + } + + bool isToBeUninstalledDueToObsolete () const + { return isToBeUninstalled() && fieldValueIs( DUE_TO_OBSOLETE ); } + + bool isToBeUninstalledDueToUpgrade() const + { return isToBeUninstalled() && fieldValueIs( DUE_TO_UPGRADE ); } + + bool isToBeInstalledSoft () const + { return isToBeInstalled() && fieldValueIs( SOFT_INSTALL ); } + + bool isToBeInstalledNotSoft () const + { return isToBeInstalled() && !fieldValueIs( SOFT_INSTALL ); } + + bool isToBeUninstalledSoft () const + { return isToBeUninstalled() && fieldValueIs( SOFT_REMOVE ); } + + private: + /** \name Internal hard lock maintenance */ + //@{ + friend struct resstatus::UserLockQueryManip; + + void setUserLockQueryMatch( bool match_r ) + { fieldValueAssign( match_r ? USERLOCK_MATCH : USERLOCK_NOMATCH ); } + //@} + public: + bool isUserLockQueryMatch() const + { return fieldValueIs( USERLOCK_MATCH ); } + + public: + + //------------------------------------------------------------------------ + // get/set functions, returning \c true if requested status change + // was successful (i.e. leading to the desired transaction). + // If a lower level (e.g.SOLVER) wants to transact, but it's + // already set by a higher level, \c true should be returned. + // Removing a higher levels transaction bit should fail. + // + // The may functions checks only, if the action would return true + // if it is called. + + /** Set TransactValue. + * Convenience to set TransactValue from enum. + */ + bool setTransactValue( TransactValue newVal_r, TransactByValue causer_r ) + { + switch ( newVal_r ) + { + case KEEP_STATE: + return setTransact( false, causer_r ); + break; + case LOCKED: + return setLock( true, causer_r ); + break; + case TRANSACT: + return setTransact( true, causer_r ); + break; + } + return false; + } + + bool maySetTransactValue( TransactValue newVal_r, TransactByValue causer_r ) + { + bit::BitField savBitfield = _bitfield; + bool ret = setTransactValue( newVal_r, causer_r ); + _bitfield = savBitfield; + return ret; + } + + /** Apply a lock (prevent transaction). + * Currently by USER or APPL_HIGH only, but who knows... + * Set LOCKED from KEEP_STATE to be sure all transaction + * details were reset properly. + */ + bool setLock( bool toLock_r, TransactByValue causer_r ) + { + if ( toLock_r == isLocked() ) + { + // we're already in the desired state, but in case of + // LOCKED, remember a superior causer. + if ( isLocked() && isLessThan( causer_r ) ) + fieldValueAssign( causer_r ); + return true; + } + // Here: Lock status is to be changed: + if ( causer_r != USER && causer_r != APPL_HIGH ) + return false; + if ( toLock_r ) { + // We're in unlocked state, which includes TRANSACT. + // Causer must be allowed to reset this. But from + // KEEP_STATE every causer is allowed to set the lock. + if ( ! setTransact( false, causer_r ) ) + return false; + fieldValueAssign( LOCKED ); + fieldValueAssign( causer_r ); + } else { + // To leave Locked state it needs a superior causer. + if ( isGreaterThan( causer_r ) ) + return false; + fieldValueAssign( KEEP_STATE ); + fieldValueAssign( SOLVER ); // reset to lowest causer + // in order to distinguish from keep_state_by_user + } + return true; + } + + bool maySetLock( bool to_r, TransactByValue causer_r ) + { + bit::BitField savBitfield = _bitfield; + bool ret = setLock( to_r, causer_r ); + _bitfield = savBitfield; + return ret; + } + + /** Toggle between TRANSACT and KEEP_STATE. + * LOCKED state means KEEP_STATE. But in contrary to KEEP_STATE, + * LOCKED state is immutable for \a causer_r less than TransactByValue. + * KEEP_STATE may be changed by any \a causer_r. + */ + bool setTransact( bool toTansact_r, TransactByValue causer_r ) + { + if ( toTansact_r == transacts() ) + { + // we're already in the desired state, but in case of + // TRANSACT, remember a superior causer. + if ( transacts() && isLessThan( causer_r ) ) + fieldValueAssign( causer_r ); + + fieldValueAssign( NO_DETAIL ); // Details has to be set again + return true; + } + // Here: transact status is to be changed: + if ( ! fieldValueIs( KEEP_STATE ) + && isGreaterThan( causer_r ) ) { + return false; + } + + if ( toTansact_r ) + { + fieldValueAssign( TRANSACT ); + } + else + { + fieldValueAssign( KEEP_STATE ); + } + fieldValueAssign( NO_DETAIL ); // Details has to be set again + fieldValueAssign( causer_r ); + return true; + } + + bool maySetTransact( bool val_r, TransactByValue causer ) + { + bit::BitField savBitfield = _bitfield; + bool ret = setTransact (val_r, causer); + _bitfield = savBitfield; + return ret; + } + + /** */ + bool setSoftLock( TransactByValue causer_r ) + { + if ( ! setTransact( false, causer_r ) ) + return false; + if ( fieldValueIs( KEEP_STATE ) + && isLessThan( causer_r ) ) + fieldValueAssign( causer_r ); + return true; + } + + /** Not the same as setTransact( false ). + */ + bool resetTransact( TransactByValue causer_r ) + { + if ( ! setTransact( false, causer_r ) ) + return false; + if ( fieldValueIs( KEEP_STATE ) ) + fieldValueAssign( SOLVER ); + return true; + } + + /** Soft toggle between TRANSACT and KEEP_STATE. + * Similar to setTransact, but leaving KEEP_STATE also requires + * a superior \a causerLimit_r. So this is a kind of soft lock. + * \code + * // SOLVER wants to set TRANSACT, iff KEEP_STATE is + * // not superior to APPL_LOW. + * setSoftTransact( true, SOLVER, APPL_LOW ); + * \endcode + */ + bool setSoftTransact( bool toTansact_r, TransactByValue causer_r, + TransactByValue causerLimit_r ) + { + if ( fieldValueIs( KEEP_STATE ) + && toTansact_r != transacts() + && isGreaterThan( causerLimit_r ) ) + { + // any transact status change requires a superior causer. + return false; + } + return setTransact( toTansact_r, causer_r ); + } + + bool setSoftTransact( bool toTansact_r, TransactByValue causer_r ) + { return setSoftTransact( toTansact_r, causer_r, causer_r ); } + + bool maySetSoftTransact( bool val_r, TransactByValue causer, + TransactByValue causerLimit_r ) + { + bit::BitField savBitfield = _bitfield; + bool ret = setSoftTransact( val_r, causer, causerLimit_r ); + _bitfield = savBitfield; + return ret; + } + + bool maySetSoftTransact( bool val_r, TransactByValue causer ) + { return maySetSoftTransact( val_r, causer, causer ); } + + bool setToBeInstalled (TransactByValue causer) + { + if (isInstalled()) return false; + return setTransact (true, causer); + } + + bool maySetToBeInstalled (TransactByValue causer) + { + bit::BitField savBitfield = _bitfield; + bool ret = setToBeInstalled (causer); + _bitfield = savBitfield; + return ret; + } + + bool setToBeUninstalled (TransactByValue causer) + { + if (!isInstalled()) return false; + return setTransact (true, causer); + } + + bool maySetToBeUninstalled (TransactByValue causer) + { + bit::BitField savBitfield = _bitfield; + bool ret = setToBeUninstalled (causer); + _bitfield = savBitfield; + return ret; + } + + //------------------------------------------------------------------------ + // *** These are only for the Resolver *** + + bool setToBeUninstalledDueToObsolete ( ) + { + if (!setToBeUninstalled (SOLVER)) return false; + fieldValueAssign(DUE_TO_OBSOLETE); + return true; + } + + bool setToBeUninstalledDueToUpgrade ( TransactByValue causer ) + { + if (!setToBeUninstalled (causer)) return false; + fieldValueAssign(DUE_TO_UPGRADE); + return true; + } + + bool setToBeInstalledSoft ( ) + { + if (isInstalled() + || !setSoftTransact (true, SOLVER)) + return false; + + fieldValueAssign(SOFT_INSTALL); + return true; + } + + bool setToBeUninstalledSoft ( ) + { + if (!isInstalled() + || !setSoftTransact (true, SOLVER)) + return false; + + fieldValueAssign(SOFT_REMOVE); + return true; + } + + bool maySetToBeUninstalledSoft () + { + bit::BitField savBitfield = _bitfield; + bool ret = setToBeUninstalledSoft (); + _bitfield = savBitfield; + return ret; + } + + bool isSoftInstall () { + return fieldValueIs (SOFT_INSTALL); + } + + bool isSoftUninstall () { + return fieldValueIs (SOFT_REMOVE); + } + + bool setSoftInstall (bool flag) { + fieldValueAssign(flag?SOFT_INSTALL:0); + return true; + } + + bool setSoftUninstall (bool flag) { + fieldValueAssign(flag?SOFT_REMOVE:0); + return true; + } + + bool setUndetermined () + { + fieldValueAssign(UNDETERMINED); + return true; + } + + bool setSatisfied () + { + fieldValueAssign(SATISFIED); + return true; + } + + bool setBroken () + { + fieldValueAssign(BROKEN); + return true; + } + + bool setNonRelevant () + { + fieldValueAssign(NONRELEVANT); + return true; + } + + bool setStatus( const ResStatus& newStatus_r ) + { + // State field is immutable! + if ( _bitfield.value() != newStatus_r._bitfield.value() ) + return false; + // Transaction state change allowed? + if ( ! setTransactValue( newStatus_r.getTransactValue(), newStatus_r.getTransactByValue() ) ) + return false; + + // Ok, we take it all.. + _bitfield = newStatus_r._bitfield; + return true; + } + + /** \name Builtin ResStatus constants. */ + //@{ + static const ResStatus toBeInstalled; + static const ResStatus toBeUninstalled; + static const ResStatus toBeUninstalledDueToUpgrade; + static const ResStatus toBeUninstalledDueToObsolete; + //@} + + private: + /** Ctor for intialization of builtin constants. */ + ResStatus( StateValue s, + ValidateValue v = UNDETERMINED, + TransactValue t = KEEP_STATE, + InstallDetailValue i = EXPLICIT_INSTALL, + RemoveDetailValue r = EXPLICIT_REMOVE ); + + /** Return whether the corresponding Field has value \a val_r. + */ + template + bool fieldValueIs( FieldType val_r ) const + { return _bitfield.isEqual( val_r ); } + + /** Set the corresponding Field to value \a val_r. + */ + template + void fieldValueAssign( FieldType val_r ) + { _bitfield.assign( val_r ); } + + /** compare two values. + */ + template + bool isGreaterThan( FieldType val_r ) + { return _bitfield.value() > val_r; } + + template + bool isLessThan( FieldType val_r ) + { return _bitfield.value() < val_r; } + + private: + friend class resstatus::StatusBackup; + BitFieldType _bitfield; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ResStatus Stream output */ + std::ostream & operator<<( std::ostream & str, const ResStatus & obj ) ZYPP_API; + + /** \relates ResStatus Stream output */ + std::ostream & operator<<( std::ostream & str, ResStatus::TransactValue obj ) ZYPP_API; + + /** \relates ResStatus Stream output */ + std::ostream & operator<<( std::ostream & str, ResStatus::TransactByValue obj ) ZYPP_API; + + /** \relates ResStatus */ + inline bool operator==( const ResStatus & lhs, const ResStatus & rhs ) + { return lhs._bitfield == rhs._bitfield; } + + /** \relates ResStatus */ + inline bool operator!=( const ResStatus & lhs, const ResStatus & rhs ) + { return ! (lhs == rhs); } + + /////////////////////////////////////////////////////////////////// + + namespace resstatus + { + class StatusBackup + { + public: + StatusBackup() + : _status( 0 ) + {} + + StatusBackup( ResStatus & status_r ) + : _status( &status_r ) + , _bitfield( _status->_bitfield ) + {} + + void replay() + { if ( _status ) _status->_bitfield = _bitfield; } + + private: + ResStatus * _status; + ResStatus::BitFieldType _bitfield; + }; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESSTATUS_H diff --git a/zypp/ResTraits.h b/zypp/ResTraits.h new file mode 100644 index 0000000..b499cca --- /dev/null +++ b/zypp/ResTraits.h @@ -0,0 +1,155 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResTraits.h + * +*/ +#ifndef ZYPP_RESTRAITS_H +#define ZYPP_RESTRAITS_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace traits + { ///////////////////////////////////////////////////////////////// + + /** Those are denoted to be installed, if the + * solver verifies them as being satisfied. */ + inline bool isPseudoInstalled( const ResKind& kind_r ) + { return( kind_r == ResKind::patch ); } + + ///////////////////////////////////////////////////////////////// + } // namespace traits + /////////////////////////////////////////////////////////////////// + + /** \defgroup ZYPP_RESOLVABLE_SMART_POINTER_TYPES + * Resolvable smart pointer types. + * + * Forward declaration of all Resolvable smart pointer + * types provided in \c ResTraits.h (recommended in header files): + * \code + * #include "zypp/ResTraits.h" + * + * Resolvable_Ptr // Resolvable * + * ResTraits::PtrType // same as above + * + * Resolvable_constPtr // const Resolvable * + * ResTraits::constPtrType // same as above + * \endcode + * + * Synonym, but requires \c Resolvable.h being included: + * \code + * #include "zypp/Resolvable.h" + * + * Resolvable::Ptr // same as Resolvable_Ptr but requires Resolvable.h + * Resolvable::constPtr // same as Resolvable_constPtr but requires Resolvable.h + * \endcode + * + * \note When adding a \c NewResolvable type here, dont forgett to + * put IMPL_PTR_TYPE(NewResolvable); into the \c NewResolvable.cc. + * Also check class \ref ResKind, ResKind.cc, ResObject.cc(makeResObject) + */ + //@{ + DEFINE_PTR_TYPE( Resolvable ); + DEFINE_PTR_TYPE( ResObject ); + + DEFINE_PTR_TYPE( Package ); + DEFINE_PTR_TYPE( SrcPackage ); + DEFINE_PTR_TYPE( Pattern ); + DEFINE_PTR_TYPE( Product ); + DEFINE_PTR_TYPE( Patch ); + DEFINE_PTR_TYPE( Application ); + //@} + + /** Frequently associated. */ + class PoolItem; + + /** ResTraits. Defines common types and the ResKind value. */ + template + struct ResTraits + { + using KindType = ResKind; + using PtrType = intrusive_ptr; + using constPtrType = intrusive_ptr; + + static const ResKind kind ZYPP_API; ///< Defined in ResKind.cc + + /** Those are denoted to be installed, if the + * solver verifies them as being satisfied. */ + static bool isPseudoInstalled() { return traits::isPseudoInstalled( kind ); } + }; + + // Defined in ResKind.cc + template<> const ResKind ResTraits::kind ZYPP_API; + template<> const ResKind ResTraits::kind ZYPP_API; + template<> const ResKind ResTraits::kind ZYPP_API; + template<> const ResKind ResTraits::kind ZYPP_API; + template<> const ResKind ResTraits::kind ZYPP_API; + template<> const ResKind ResTraits::kind ZYPP_API; + + /** ResTraits specialisation for Resolvable. + * Resolvable is common base and has no Kind value. + */ + template<> + struct ResTraits + { + using KindType = ResKind; + using PtrType = intrusive_ptr; + using constPtrType = intrusive_ptr; + }; + + /** ResTraits specialisation for ResObject. + * ResObject is common base and has no Kind value. + */ + template<> + struct ResTraits + { + using KindType = ResKind; + using PtrType = intrusive_ptr; + using constPtrType = intrusive_ptr; + }; + + /** Convenient access to well known ResKinds. + * \code + * ResKind packagekind = ResKind::package; + * ResKind packagekind = resKind(); + * \endcode + */ + template + inline ResKind resKind() { return ResTraits::kind; } + + /** Convenient test for ResKinds. + * \code + * ResKind value; + * if ( ResKind::package == value ) + * if ( resKind() == value ) + * if ( isKind( value ) ) + * \endcode + */ + template + inline bool isKind( const ResKind & val_r ) + { return( resKind() == val_r ); } + /** \overload */ + template + inline bool isKind( const std::string & val_r ) + { return( resKind() == val_r ); } + /** \overload */ + template + inline bool isKind( const char * val_r ) + { return( resKind() == val_r ); } + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESTRAITS_H diff --git a/zypp/Resolvable.cc b/zypp/Resolvable.cc new file mode 100644 index 0000000..ee0c5a6 --- /dev/null +++ b/zypp/Resolvable.cc @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Resolvable.cc + * +*/ +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + IMPL_PTR_TYPE(Resolvable); + + Resolvable::Resolvable( const sat::Solvable & solvable_r ) + : _solvable( solvable_r ) + {} + + Resolvable::~Resolvable() + {} + + PoolItem Resolvable::poolItem() const + { return PoolItem( *this ); } + + std::ostream & Resolvable::dumpOn( std::ostream & str ) const + { return str << satSolvable(); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Resolvable.h b/zypp/Resolvable.h new file mode 100644 index 0000000..05e5e4f --- /dev/null +++ b/zypp/Resolvable.h @@ -0,0 +1,176 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Resolvable.h + * +*/ +#ifndef ZYPP_RESOLVABLE_H +#define ZYPP_RESOLVABLE_H + +#include +#include + +#include + +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + class PoolItem; + /////////////////////////////////////////////////////////////////// + /// \class Resolvable + /// \brief Base for resolvable objects + /// + /// \note \ref Resolvable is a SolvableType, which provides direct + /// access to many of the underlying sat::Solvables properties. + /// Don't add common properties here, but in \ref sat::Solvable + /// and extend \ref sat::SolvableType. + /// + /// In most cases you want to retrieve the common properties directly + /// from a \ref PoolItem or \ref sat::Solvable. Construction from and + /// explicit conversion to sat::Solvable are supported. Next goal is + /// to get rid of the smart pointer hierarchy. A Resolvable is actually + /// an unsigned and derived classes contain no data, so it makes little + /// sense to wrap this into ReferenceCounted smart pointer. + /// + /// \todo Merge with ResObject + /// \todo Get rid of refcout/smart_prt bloat, as this type is actually IdBased (i.e. sizeof(unsigned)) + /////////////////////////////////////////////////////////////////// + class ZYPP_API Resolvable : public sat::SolvableType, + public base::ReferenceCounted, private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const Resolvable & obj ); + + public: + using Self = Resolvable; + using TraitsType = ResTraits; + using Kind = TraitsType::KindType; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + /** This is a \ref sat::SolvableType. */ + explicit operator sat::Solvable() const + { return _solvable; } + + /** Access the corresponding \ref PoolItem. */ + PoolItem poolItem() const; + + protected: + /** Ctor */ + Resolvable( const sat::Solvable & solvable_r ); + /** Dtor */ + ~Resolvable() override; + /** Helper for stream output */ + std::ostream & dumpOn( std::ostream & str ) const override; + + private: + sat::Solvable _solvable; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Resolvable Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Resolvable & obj ) + { return obj.dumpOn( str ); } + + /** \relates Resolvable More verbose stream output including dependencies */ + inline std::ostream & dumpOn( std::ostream & str, const Resolvable & obj ) + { return dumpOn( str, obj.satSolvable() ); } + + /** Test whether a Resolvable::Ptr is of a certain Kind. + * \return \c Ture iff \a p is not \c NULL and points to a Resolvable + * of the specified Kind. + * \relates Resolvable + * \code + * isKind(resPtr); + * \endcode + */ + template + inline bool isKind( const Resolvable::constPtr & p ) + { return p && p->isKind(); } + + // Specialization for Resolvable: Always true. + template<> + inline bool isKind( const Resolvable::constPtr & p ) + { return !!p; } + + // Specialization for ResObject: Always true. + template<> + inline bool isKind( const Resolvable::constPtr & p ) + { return !!p; } + + + /** Convert Resolvable::Ptr into Ptr of a certain Kind. + * \return \c NULL iff \a p is \c NULL or points to a Resolvable + * not of the specified Kind. + * \relates Resolvable + * \code + * asKind(resPtr); + * \endcode + */ + template + inline typename ResTraits::PtrType asKind( const Resolvable::Ptr & p ) + { return dynamic_pointer_cast(p); } + + template + inline typename ResTraits::constPtrType asKind( const Resolvable::constPtr & p ) + { return dynamic_pointer_cast(p); } + + /////////////////////////////////////////////////////////////////// + + /** \relates Resolvable Compare Resolvable::constPtr according to \a kind and \a name. + * \deprecated Get rid of refcout/smart_prt bloat, use + */ + inline int compareByN( const Resolvable::constPtr & lhs, const Resolvable::constPtr & rhs ) + { + int ret = 0; + if ( lhs != rhs ) + { + if ( lhs && rhs ) + ret = compareByN( *lhs, *rhs ); + else + ret = lhs ? 1 : -1; + } + return ret; + } + + /** \relates Resolvable Compare according to \a kind, \a name and \a edition. */ + inline int compareByNVR( const Resolvable::constPtr & lhs, const Resolvable::constPtr & rhs ) + { + int ret = 0; + if ( lhs != rhs ) + { + if ( lhs && rhs ) + ret = compareByNVR( *lhs, *rhs ); + else + ret = lhs ? 1 : -1; + } + return ret; + } + + /** \relates Resolvable Compare Resolvable::constPtr according to \a kind, \a name, \a edition and \a arch. */ + inline int compareByNVRA( const Resolvable::constPtr & lhs, const Resolvable::constPtr & rhs ) + { + int ret = 0; + if ( lhs != rhs ) + { + if ( lhs && rhs ) + ret = compareByNVRA( *lhs, *rhs ); + else + ret = lhs ? 1 : -1; + } + return ret; + } +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESOLVABLE_H diff --git a/zypp/Resolver.cc b/zypp/Resolver.cc new file mode 100644 index 0000000..5602cbd --- /dev/null +++ b/zypp/Resolver.cc @@ -0,0 +1,187 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Resolver.cc + * +*/ +#include + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include +#include +#include + + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + using namespace solver; + + IMPL_PTR_TYPE(Resolver); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Resolver::Resolver + // METHOD TYPE : Ctor + // + Resolver::Resolver( const ResPool & pool ) + : _pimpl( new solver::detail::ResolverInternal(pool) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Resolver::~Resolver + // METHOD TYPE : Dtor + // + Resolver::~Resolver() + {} + + /////////////////////////////////////////////////////////////////// + // + // Resolver interface forwarded to implementation + // + /////////////////////////////////////////////////////////////////// + void Resolver::setDefaultSolverFlags( bool all_r ) + { return _pimpl->setDefaultSolverFlags( all_r ); } + + sat::detail::CSolver * Resolver::get() const + { return _pimpl->get(); } + + bool Resolver::verifySystem () + { return _pimpl->verifySystem(); } + + bool Resolver::resolvePool () + { return _pimpl->resolvePool(); } + + bool Resolver::resolveQueue( solver::detail::SolverQueueItemList & queue ) + { return _pimpl->resolveQueue(queue); } + + void Resolver::undo() + { _pimpl->undo(); } + + ResolverProblemList Resolver::problems () + { return _pimpl->problems (); } + + void Resolver::applySolutions( const ProblemSolutionList & solutions ) + { _pimpl->applySolutions (solutions); } + + sat::Transaction Resolver::getTransaction() + { return _pimpl->getTransaction(); } + + bool Resolver::doUpgrade() + { return _pimpl->doUpgrade(); } + + void Resolver::doUpdate() + { _pimpl->doUpdate(); } + + void Resolver::setFocus( ResolverFocus focus_r ) { _pimpl->setFocus( focus_r ); } + ResolverFocus Resolver::focus() const { return _pimpl->focus(); } + + void Resolver::setForceResolve( bool yesno_r ) { _pimpl->setForceResolve( yesno_r ); } + bool Resolver::forceResolve() const { return _pimpl->forceResolve(); } + + void Resolver::setIgnoreAlreadyRecommended( bool yesno_r) { _pimpl->setIgnoreAlreadyRecommended( yesno_r ); } + bool Resolver::ignoreAlreadyRecommended() const { return _pimpl->ignoreAlreadyRecommended(); } + + void Resolver::setOnlyRequires( bool yesno_r ) { _pimpl->setOnlyRequires( yesno_r ); } + void Resolver::resetOnlyRequires() { _pimpl->setOnlyRequires( indeterminate ); } + bool Resolver::onlyRequires() const { return _pimpl->onlyRequires(); } + + void Resolver::setUpgradeMode( bool yesno_r ) { return _pimpl->setUpgradeMode( yesno_r ); } + bool Resolver::upgradeMode() const { return _pimpl->isUpgradeMode(); } + + void Resolver::setUpdateMode( bool yesno_r ) { return _pimpl->setUpdateMode( yesno_r ); } + bool Resolver::updateMode() const { return _pimpl->isUpdateMode(); } + + void Resolver::setRemoveOrphaned( bool yesno_r ) { return _pimpl->setRemoveOrphaned( yesno_r ); } + bool Resolver::removeOrphaned() const { return _pimpl->removeOrphaned(); } + + void Resolver::setRemoveUnneeded( bool yesno_r ) { return _pimpl->setRemoveUnneeded( yesno_r ); } + bool Resolver::removeUnneeded() const { return _pimpl->removeUnneeded(); } + + void Resolver::setSystemVerification( bool yesno_r ) { _pimpl->setVerifyingMode( yesno_r ); } + void Resolver::setDefaultSystemVerification() { _pimpl->setVerifyingMode( indeterminate ); } + bool Resolver::systemVerification() const { return _pimpl->isVerifyingMode(); } + + void Resolver::setSolveSrcPackages( bool yesno_r ) { _pimpl->setSolveSrcPackages( yesno_r ); } + void Resolver::setDefaultSolveSrcPackages() { _pimpl->setSolveSrcPackages( indeterminate ); } + bool Resolver::solveSrcPackages() const { return _pimpl->solveSrcPackages(); } + + void Resolver::setCleandepsOnRemove( bool yesno_r ) { _pimpl->setCleandepsOnRemove( yesno_r ); } + void Resolver::setDefaultCleandepsOnRemove() { _pimpl->setCleandepsOnRemove( indeterminate ); } + bool Resolver::cleandepsOnRemove() const { return _pimpl->cleandepsOnRemove(); } + +#define ZOLV_FLAG_BOOL( ZSETTER, ZGETTER ) \ + void Resolver::ZSETTER( bool yesno_r ){ _pimpl->ZSETTER( yesno_r ); } \ + bool Resolver::ZGETTER() const { return _pimpl->ZGETTER(); } \ + +#define ZOLV_FLAG_TRIBOOL( ZSETTER, ZDEFAULT, ZGETTER ) \ + ZOLV_FLAG_BOOL( ZSETTER , ZGETTER ) \ + void Resolver::ZDEFAULT() { _pimpl->ZSETTER( indeterminate ); } \ + + ZOLV_FLAG_TRIBOOL( setAllowDowngrade, setDefaultAllowDowngrade, allowDowngrade ) + ZOLV_FLAG_TRIBOOL( setAllowNameChange, setDefaultAllowNameChange, allowNameChange ) + ZOLV_FLAG_TRIBOOL( setAllowArchChange, setDefaultAllowArchChange, allowArchChange ) + ZOLV_FLAG_TRIBOOL( setAllowVendorChange, setDefaultAllowVendorChange, allowVendorChange ) + + ZOLV_FLAG_TRIBOOL( dupSetAllowDowngrade, dupSetDefaultAllowDowngrade, dupAllowDowngrade ) + ZOLV_FLAG_TRIBOOL( dupSetAllowNameChange, dupSetDefaultAllowNameChange, dupAllowNameChange ) + ZOLV_FLAG_TRIBOOL( dupSetAllowArchChange, dupSetDefaultAllowArchChange, dupAllowArchChange ) + ZOLV_FLAG_TRIBOOL( dupSetAllowVendorChange, dupSetDefaultAllowVendorChange, dupAllowVendorChange ) + +#undef ZOLV_FLAG_BOOL +#undef ZOLV_FLAG_TRIBOOL + + void Resolver::addUpgradeRepo( Repository repo_r ) { _pimpl->addUpgradeRepo( repo_r ); } + bool Resolver::upgradingRepos() const { return !_pimpl->upgradeRepos().empty(); } + bool Resolver::upgradingRepo( Repository repo_r ) const { return _pimpl->upgradingRepo( repo_r ); } + void Resolver::removeUpgradeRepo( Repository repo_r ) { _pimpl->removeUpgradeRepo( repo_r ); } + void Resolver::removeUpgradeRepos() { _pimpl->removeUpgradeRepos(); } + + void Resolver::addRequire( const Capability & capability ) { _pimpl->addExtraRequire( capability ); } + void Resolver::addConflict( const Capability & capability ) { _pimpl->addExtraConflict( capability ); } + void Resolver::removeRequire( const Capability & capability ) { _pimpl->removeExtraRequire( capability ); } + void Resolver::removeConflict( const Capability & capability ){ _pimpl->removeExtraConflict( capability ); } + + CapabilitySet Resolver::getRequire() const { return _pimpl->extraRequires(); } + CapabilitySet Resolver::getConflict() const { return _pimpl->extraConflicts(); } + + std::list Resolver::problematicUpdateItems() const + { return _pimpl->problematicUpdateItems(); } + + bool Resolver::createSolverTestcase( const std::string & dumpPath, bool runSolver ) + { + solver::detail::Testcase testcase (dumpPath); + return testcase.createTestcase(*_pimpl, true, runSolver); + } + + solver::detail::ItemCapKindList Resolver::isInstalledBy( const PoolItem & item ) + { return _pimpl->isInstalledBy (item); } + + solver::detail::ItemCapKindList Resolver::installs( const PoolItem & item ) + { return _pimpl->installs (item); } + + solver::detail::ItemCapKindList Resolver::satifiedByInstalled( const PoolItem & item ) + { return _pimpl->satifiedByInstalled (item); } + + solver::detail::ItemCapKindList Resolver::installedSatisfied( const PoolItem & item ) + { return _pimpl->installedSatisfied (item); } + + void Resolver::reset() + { _pimpl->reset( false ); /* Do not keep extra requires/conflicts */ } + + std::ostream & operator<<( std::ostream & str, const Resolver & obj ) + { return str << *obj._pimpl; } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Resolver.h b/zypp/Resolver.h new file mode 100644 index 0000000..de29099 --- /dev/null +++ b/zypp/Resolver.h @@ -0,0 +1,501 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Resolver.h + * +*/ +#ifndef ZYPP_RESOLVER_H +#define ZYPP_RESOLVER_H + +#include +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace sat + { + class Transaction; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Resolver + // + /** + * Dependency resolver interface. + * + * To resolve dependencies after making changes to the \ref ResPool (using + * \ref addRequire(), \ref addConflict(), \ref applySolutions(), or by making + * the changes directly on the \ref PoolItem status objects, + * call the \ref resolvePool() method. + */ + class ZYPP_API Resolver : public base::ReferenceCounted, private base::NonCopyable + { + public: + + /** Ctor */ + Resolver( const ResPool & pool ); + /** Dtor */ + ~Resolver() override; + + /** + * Reset all solver flags to the systems default (e.g. from zypp.conf). + * + * Call this to discard all settings you explicitly applied here. All flags + * are adjusted to follow the current systems default. If you want to reset + * just a specific flag, call its 'setDefault...' method. + * + * Calling the method with \a all_r is set to \c false, is used internally. + * It updates only those flags which were not explicitly changed. E.g after + * switching to a target which uses different defaults in its zypp.conf.. + */ + void setDefaultSolverFlags( bool all_r = true ); + + /** + * Resolve package dependencies: + * + * Enter \ref systemVerification mode to monitor and repair dependencies + * of already installed packages, and solve immediately. + * + * Call \ref setSystemVerification to turn of this mode. + **/ + bool verifySystem(); + + + /** + * Resolve package dependencies: + * + * Try to execute all pending transactions (there may be more than + * one!). + * The solver collects all transactions (install/delete resolvables) + * from the pool, generates task, solving it and writes the + * results back to pool + * + * Returns "true" on success (i.e., if there were no problems that + * need user interaction) and "false" if there were problems. In + * the latter case, use problems() and later applySolutions() + * below. + **/ + bool resolvePool(); + + + /** + * Resolve package dependencies: + * + * The solver works off the given queue and writes back the solution + * to pool. + * + * Returns "true" on success (i.e., if there were no problems that + * need user interaction) and "false" if there were problems. In + * the latter case, use problems() and later applySolutions() + * below. + * The solution could be that the solver remove/add some entries + * in the task queue. So make a new call of resolveQueue after you + * have applied any solution AND check the parameter "queue" if + * there has been any changes by the solver and adapt these changes + * to e.g. the selectables. + * + **/ + bool resolveQueue( solver::detail::SolverQueueItemList & queue ); + + /* + * Undo solver changes done in resolvePool() + * Throwing away all ignored dependencies. + */ + void undo(); + + /* + * Resets solver information and verify option. + */ + void reset(); + + + /** + * Do an distribution upgrade (DUP) + * + * Perform a distribution upgrade. This performs an update of + * all packages with a special resolver algorithm which takes + * care of package splits, pattern and product updates, + * etc. + * This call also turns the solver into \ref upgradeMode, so + * consecutive calls to \ref resolvePool performed in this + * mode too. Call \ref setUpgradeMode to turn this mode off. + * + * \see \ref addUpgradeRepo + **/ + bool doUpgrade(); + + /** + * Update to newest package + * + * Install the newest version of your installed packages as + * far as possible. This means a newer package will NOT be + * installed if it generates dependency problems. + * So the user will not get an error message. + * + **/ + void doUpdate( ); + + /** + * Unmaintained packages which does not fit to + * the updated system (broken dependencies) will be + * deleted. + * Return the list of deleted items. + * Note : This list is valid after the call doUpgrade() only. + **/ + std::list problematicUpdateItems() const; + + /** + * Return the dependency problems found by the last call to + * resolveDependencies(). If there were no problems, the returned + * list will be empty. + **/ + ResolverProblemList problems(); + + + /** + * Apply problem solutions. No more than one solution per problem + * can be applied. + **/ + void applySolutions( const ProblemSolutionList & solutions ); + + /** + * Return the \ref Transaction computed by the last solver run. + */ + sat::Transaction getTransaction(); + + /** + * Define the resolver's general attitude when resolving jobs. + * \see \ref ResolverFocus + */ + void setFocus( ResolverFocus focus_r ); + ResolverFocus focus() const; + + /** + * Remove resolvables which are conflicts with others or + * have unfulfilled requirements. + * This behaviour is favourited by ZMD. + **/ + void setForceResolve( bool force ); + bool forceResolve() const; + + /** + * Ignore recommended packages that were already recommended by + * the installed packages + **/ + void setIgnoreAlreadyRecommended( bool yesno_r ); + bool ignoreAlreadyRecommended() const; + + /** + * Setting whether required packages are installed ONLY + * So recommended packages, language packages and packages which depend + * on hardware (modalias) will not be regarded. + **/ + void setOnlyRequires( bool yesno_r ); + void resetOnlyRequires(); // set back to default (described in zypp.conf) + bool onlyRequires() const; + + /** + * Setting whether the solver should perform in 'upgrade' mode or + * not. + * \see \ref doUpgrade. + */ + void setUpgradeMode( bool yesno_r ); + bool upgradeMode() const; + + /** + * Setting whether the solver should perform in 'update' mode or + * not. If on, it will add a resolver job to update all packages. + * \see \ref doUpdate. + */ + void setUpdateMode( bool yesno_r ); + bool updateMode() const; + + /** + * Set whether to remove unused orphans in 'upgrade' mode. + * + * Orphaned packages are those which are neither provided by any repository + * not have update candidates within any repository. They often denoted as + * dropped or not-wanted. They are leftovers of previous distribution + * versions. + * + * \Note 3rd party .rpm packages simply installed are seen as orphaned and + * may be removed by dup. Collecting these packages in a directory and + * adding this directory as a (plaindir) repo turns them into wanted + * packages. They are kind of protected by being part of an enabled + * repository. + */ + void setRemoveOrphaned( bool yesno_r ); + bool removeOrphaned() const; + + /** + * File weak remove jobs for unneeded installed packages. + * + * \Note There needs to be one (even if empty) solver run before + * unneeded installed packages are determined. So this does not + * contribute to the very first solver run. + * + * \Note In order to tailor the \c unneeded classification one needs + * to be able to control the \c autoinstalled property of a package. + * Only autoinstalled packages can be unneeded. So switching the + * autoinstalled property is the way to (potentially) add or (surely) + * remove a package from the unneeded set. + */ + void setRemoveUnneeded( bool yesno_r ); + bool removeUnneeded() const; + + /** \name Solver flags (non DUP modes) + * Default for all flags is \c false unless overwritten by zypp.conf. + */ + //@{ + /** Whether to allow one to downgrade installed solvable */ + void setAllowDowngrade( bool yesno_r ); + void setDefaultAllowDowngrade(); // Set back to default + bool allowDowngrade() const; + + /** Whether to allow one to change name of installed solvable */ + void setAllowNameChange( bool yesno_r ); + void setDefaultAllowNameChange(); // Set back to default + bool allowNameChange() const; + + /** Whether to allow one to change architecture of installed solvables */ + void setAllowArchChange( bool yesno_r ); + void setDefaultAllowArchChange(); // Set back to default + bool allowArchChange() const; + + /** Whether to allow one to change vendor of installed solvables + * \see \ref VendorAttr for definition of vendor equivalence. + */ + void setAllowVendorChange( bool yesno_r ); + void setDefaultAllowVendorChange(); // Set back to default + bool allowVendorChange() const; + //@} + + /** + * System verification mode also monitors and repairs dependencies + * of already installed packages. + * \see \ref verifySystem + */ + void setSystemVerification( bool yesno_r ); + void setDefaultSystemVerification(); + bool systemVerification() const; + + /** + * Set whether to solve source packages build dependencies per default. + * Usually turned off and if, enabled per source package. + * \NOTE This affects only source packges selected in the \ref ResPool. No solver rule + * will be generated for them. Source packages requested via e.g. \ref addRequire will + * always be solved. + * \NOTE Be carefull. The older the source package is, the stranger may be the + * result of solving its build dependencies. + */ + void setSolveSrcPackages( bool yesno_r ); + void setDefaultSolveSrcPackages(); + bool solveSrcPackages() const; + + /** + * Cleanup when deleting packages. Whether the solver should, per default, + * try to remove packages exclusively required by the ones it's asked to delete. + */ + void setCleandepsOnRemove( bool yesno_r ); + void setDefaultCleandepsOnRemove(); // set back to default (in zypp.conf) + bool cleandepsOnRemove() const; + + /** \name Solver flags for DUP mode. + * DUP mode default settings differ from 'ordinary' ones. Default for + * all DUP flags is \c true unless overwritten by zypp.conf. + */ + //@{ + /** dup mode: allow one to downgrade installed solvable */ + void dupSetAllowDowngrade( bool yesno_r ); + void dupSetDefaultAllowDowngrade(); // Set back to default (in zypp.conf) + bool dupAllowDowngrade() const; + + /** dup mode: allow one to change name of installed solvable */ + void dupSetAllowNameChange( bool yesno_r ); + void dupSetDefaultAllowNameChange(); // Set back to default (in zypp.conf) + bool dupAllowNameChange() const; + + /** dup mode: allow one to change architecture of installed solvables */ + void dupSetAllowArchChange( bool yesno_r ); + void dupSetDefaultAllowArchChange(); // Set back to default (in zypp.conf) + bool dupAllowArchChange() const; + + /** dup mode: allow one to change vendor of installed solvables*/ + void dupSetAllowVendorChange( bool yesno_r ); + void dupSetDefaultAllowVendorChange(); // Set back to default (in zypp.conf) + bool dupAllowVendorChange() const; + //@} + + /** \name Upgrade to content of a specific repository. + * \note This is an ordinary solver request. You should simply + * \ref resolvePool to execute, and not \ref doUpgrade. + */ + //@{ + /** + * Adding request to perform a dist upgrade restricted to this repository. + * + * This is what e.g. zypper dup --repo myrepo should perform. + * \see \ref doUpgrade + */ + void addUpgradeRepo( Repository repo_r ); + + /** + * Whether there is at least one \c UpgradeRepo request pending + */ + bool upgradingRepos() const; + + /** + * Whether there is an \c UpgradeRepo request pending for this repo. + */ + bool upgradingRepo( Repository repo_r ) const; + + /** + * Remove an upgrade request for this repo. + */ + void removeUpgradeRepo( Repository repo_r ); + + /** + * Remove all upgrade repo requests. + */ + void removeUpgradeRepos(); + //@} + + /** + * Adding additional requirement + * + */ + void addRequire( const Capability & capability ); + + /** + * Adding additional conflict + * + */ + void addConflict( const Capability & capability ); + + /** + * Remove the additional requirement set by \ref addRequire(Capability). + * + */ + void removeRequire( const Capability & capability ); + + /** + * Remove the additional conflict set by \ref addConflict(Capability). + * + */ + void removeConflict( const Capability & capability ); + + /** + * Get all the additional requirements set by \ref addRequire(Capability). + * + */ + CapabilitySet getRequire() const; + + /** + * Get all the additional conflicts set by \ref addConflict(Capability). + * + */ + CapabilitySet getConflict() const; + + /** + * Generates a solver Testcase of the current state + * + * \parame dumpPath destination directory of the created directory + * \return true if it was successful + */ + bool createSolverTestcase( const std::string & dumpPath = "/var/log/YaST2/solverTestcase", bool runSolver = true ); + + /** + * Gives information about WHO has pused an installation of an given item. + * + * \param item Evaluate additional information for this resolvable. + * \return A list of structures which contains: + * item Item which has triggered the installation of the given param item. + * initialInstallation This item has triggered the installation + * Not already fullfilled requierement only. + * cap Capability which has triggerd this installation + * capKind Kind of that capability (e.g. Dep::REQUIRES,Dep::RECOMMENDS,... ) + * + * Note: In order to have a result start a solver run before. Not matter if it is valid or invalid. + * + */ + solver::detail::ItemCapKindList isInstalledBy( const PoolItem & item ); + + /** + * Gives information about WHICH additional items will be installed due the installation of an item. + * + * \param item Evaluate additional information for this resolvable. + * \return A list of structures which contains: + * item Item which has triggered the installation of the given param item. + * initialInstallation This item has triggered the installation + * Not already fullfilled requierement only. + * cap Capability which has triggerd this installation + * capKind Kind of that capability (e.g. Dep::REQUIRES,Dep::RECOMMENDS,... ) + * + * Note: In order to have a result start a solver run before. Not matter if it is valid or invalid. + * + */ + solver::detail::ItemCapKindList installs( const PoolItem & item ); + + /** + * Gives information about WHICH installed items are requested by the installation of an item. + * + * \param item Evaluate additional information for this resolvable. + * \return A list of structures which contains: + * item Item which has triggered the installation of the given param item. + * initialInstallation This item has triggered the installation + * Not already fullfilled requierement only. + * cap Capability which has triggerd this installation + * capKind Kind of that capability (e.g. Dep::REQUIRES,Dep::RECOMMENDS,... ) + * + * Note: In order to have a result start a solver run before. Not matter if it is valid or invalid. + * + */ + solver::detail::ItemCapKindList satifiedByInstalled( const PoolItem & item ); + + + /** + * Gives information about WHICH items require an already installed item. + * + * \param item Evaluate additional information for this resolvable. + * \return A list of structures which contains: + * item Item which has triggered the installation of the given param item. + * initialInstallation This item has triggered the installation + * Not already fullfilled requierement only. + * cap Capability which has triggerd this installation + * capKind Kind of that capability (e.g. Dep::REQUIRES,Dep::RECOMMENDS,... ) + * + * Note: In order to have a result start a solver run before. Not matter if it is valid or invalid. + * + */ + solver::detail::ItemCapKindList installedSatisfied( const PoolItem & item ); + + public: + /** Expert backdoor. */ + sat::detail::CSolver * get() const; + + private: + friend std::ostream & operator<<( std::ostream & str, const Resolver & obj ); + zypp::RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Resolver Stream output */ + std::ostream & operator<<( std::ostream & str, const Resolver & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESOLVER_H diff --git a/zypp/ResolverFocus.cc b/zypp/ResolverFocus.cc new file mode 100644 index 0000000..36a87fc --- /dev/null +++ b/zypp/ResolverFocus.cc @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResolverFocus.cc + */ +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + std::string asString( const ResolverFocus & val_r ) + { + switch ( val_r ) + { +#define OUTS(V) case ResolverFocus::V: return #V; break + OUTS( Default ); + OUTS( Job ); + OUTS( Installed ); + OUTS( Update ); +#undef OUTS + } + // Oops! + std::string ret { str::Str() << "ResolverFocus(" << static_cast(val_r) << ")" }; + WAR << "asString: dubious " << ret << endl; + return ret; + } + + bool fromString( const std::string & val_r, ResolverFocus & ret_r ) + { + switch ( val_r[0] ) + { +#define OUTS(V) if ( ::strcasecmp( val_r.c_str(), #V ) == 0 ) { ret_r = ResolverFocus::V; return true; } + case 'D': + case 'd': + OUTS( Default ); + break; + + case 'J': + case 'j': + OUTS( Job ); + break; + + case 'I': + case 'i': + OUTS( Installed ); + break; + + case 'U': + case 'u': + OUTS( Update ); + break; + + case '\0': + ret_r = ResolverFocus::Default; + return true; + break; +#undef OUTS + } + // Oops! + WAR << "fromString: unknown ResolverFocus '" << val_r << "'" << endl; + return false; + } +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ResolverFocus.h b/zypp/ResolverFocus.h new file mode 100644 index 0000000..2c0e008 --- /dev/null +++ b/zypp/ResolverFocus.h @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResolverFocus.h + */ +#ifndef ZYPP_RESOLVERFOCUS_H +#define ZYPP_RESOLVERFOCUS_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /** The resolver's general attitude. */ + enum class ResolverFocus + { + Default = 0 ///< Request the standard behavior (as defined in zypp.conf or 'Job') + ,Job ///< Focus on installing the best version of the requested packages + ,Installed ///< Focus on applying as little changes to the installed packages as needed + ,Update ///< Focus on updating requested packages and their dependencies as much as possible + }; + + /** \relates ResolverFocus Conversion to string (enumerator name) */ + std::string asString( const ResolverFocus & val_r ) ZYPP_API; + + /** \relates ResolverFocus Conversion from string (enumerator name, case insensitive, empty string is Default) + * \returns \c false if \a val_r is not recognized + */ + bool fromString( const std::string & val_r, ResolverFocus & ret_r ) ZYPP_API; + + /** \relates ResolverFocus Conversion from string (convenience) + * \returns \ref ResolverFocus::Default if \a val_r is not recognized + */ + inline ResolverFocus resolverFocusFromString( const std::string & val_r ) + { ResolverFocus ret_r { ResolverFocus::Default }; fromString( val_r, ret_r ); return ret_r; } + + /** \relates ResolverFocus Stream output */ + inline std::ostream & operator<<( std::ostream & str, const ResolverFocus & obj ) + { return str << asString( obj ); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESOLVERFOCUS_H diff --git a/zypp/ResolverNamespace.h b/zypp/ResolverNamespace.h new file mode 100644 index 0000000..5304ee7 --- /dev/null +++ b/zypp/ResolverNamespace.h @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ResolverNamespace.h + */ +#ifndef ZYPP_RESOLVERNAMESPACE_H +#define ZYPP_RESOLVERNAMESPACE_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /** The resolver's dependency namespaces */ + enum class ResolverNamespace : std::uint8_t + { + language = 1<<0, ///< language support + modalias = 1<<1, ///< hardware support + filesystem = 1<<2, ///< filesystems + }; + + /** \relates ResolverNamespace Flags */ + ZYPP_DECLARE_FLAGS_AND_OPERATORS(ResolverNamespaces,ResolverNamespace); + + /** \relates ResolverNamespace All bits set. */ + static constexpr const ResolverNamespaces NoResolverNamespaces = ResolverNamespace(); + + /** \relates ResolverNamespace All bits set. */ + static constexpr const ResolverNamespaces AllResolverNamespaces = ResolverNamespace(0xff); + + /** \relates ResolverNamespace The underlying libsolv ID */ + inline constexpr IdString asIdString( ResolverNamespace obj ) + { + return IdString( obj == ResolverNamespace::language ? sat::detail::namespaceLanguage + : obj == ResolverNamespace::modalias ? sat::detail::namespaceModalias + : obj == ResolverNamespace::filesystem ? sat::detail::namespaceFilesystem + : sat::detail::noId ); + } + + /** \relates ResolverNamespace String representation */ + inline std::string asString( ResolverNamespace obj ) + { return asIdString( obj ).asString(); } + + /** \relates ResolverNamespace Stream output */ + inline std::ostream & operator<<( std::ostream & str, ResolverNamespace obj ) + { return str << asIdString( obj ); } + + /** \relates ResolverNamespaces Stream output */ + inline std::ostream & operator<<( std::ostream & str, ResolverNamespaces obj ) + { + return str << stringify( obj, { + { ResolverNamespace::language, "language" }, + { ResolverNamespace::modalias, "modalias" }, + { ResolverNamespace::filesystem, "filesystem" }, + }, "namespace:", "|", "" ); + } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESOLVERNAMESPACE_H diff --git a/zypp/ResolverProblem.cc b/zypp/ResolverProblem.cc new file mode 100644 index 0000000..4ac87e0 --- /dev/null +++ b/zypp/ResolverProblem.cc @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* ResolverProblem.cc + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#include + +#include +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + IMPL_PTR_TYPE(ResolverProblem); + + ///////////////////////////////////////////////////////////////////////// + namespace + { + // HACK for bsc#985674: filter duplicate solutions + // + inline bool solutionInList( const ProblemSolutionList & solutions_r, const ProblemSolution_Ptr & solution_r ) + { + for ( const ProblemSolution_Ptr & solution : solutions_r ) + { + if ( solution->description() == solution_r->description() + && solution->details() == solution_r->details() + && solution->actions().size() == solution_r->actions().size() ) + return true; + } + return false; + } + } // namespace + ///////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class ResolverProblem::Impl + /// \brief ResolverProblem implementation. + /////////////////////////////////////////////////////////////////// + struct ResolverProblem::Impl + { + Impl() + {} + + Impl( std::string && description ) + : _description( std::move(description) ) + {} + + Impl( std::string && description, std::string && details ) + : _description( std::move(description) ) + , _details( std::move(details) ) + {} + + Impl( std::string && description, std::string && details, std::vector &&completeProblemInfo ) + : _description( std::move(description) ) + , _details( std::move(details) ) + , _completeProblemInfo ( std::move(completeProblemInfo) ) + {} + + std::string _description; + std::string _details; + ProblemSolutionList _solutions; + std::vector _completeProblemInfo; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + ResolverProblem::ResolverProblem() + : _pimpl( new Impl() ) + {} + + ResolverProblem::ResolverProblem( std::string description ) + : _pimpl( new Impl( std::move(description) ) ) + {} + + ResolverProblem::ResolverProblem( std::string description, std::string details ) + : _pimpl( new Impl( std::move(description), std::move(details) ) ) + {} + + ResolverProblem::ResolverProblem( std::string description, std::string details, std::vector &&completeProblemInfo ) + : _pimpl( new Impl( std::move(description), std::move(details), std::move(completeProblemInfo) ) ) + {} + + ResolverProblem::~ResolverProblem() + {} + + + const std::string & ResolverProblem::description() const + { return _pimpl->_description; } + + const std::string & ResolverProblem::details() const + { return _pimpl->_details; } + + const ProblemSolutionList & ResolverProblem::solutions() const + { return _pimpl->_solutions; } + + const std::vector & ResolverProblem::completeProblemInfo() const + { return _pimpl->_completeProblemInfo; } + + void ResolverProblem::setDescription( std::string description ) + { _pimpl->_description = std::move(description); } + + void ResolverProblem::setDetails( std::string details ) + { _pimpl->_details = std::move(details); } + + void ResolverProblem::addSolution( const ProblemSolution_Ptr& solution, bool inFront ) + { + if ( ! solutionInList( _pimpl->_solutions, solution ) ) // bsc#985674: filter duplicate solutions + { + if (inFront) + { _pimpl->_solutions.push_front( solution ); } + else + { _pimpl->_solutions.push_back( solution ); } + } + } + + + std::ostream & operator<<( std::ostream & os, const ResolverProblem & obj ) + { + os << "Problem:" << endl; + os << "==============================" << endl; + os << obj.description() << endl; + os << obj.details() << endl; + os << "------------------------------" << endl; + os << obj.solutions(); + os << "==============================" << endl; + return os; + } + + std::ostream & operator<<( std::ostream & os, const ResolverProblemList & obj ) + { return dumpRange( os, obj.begin(), obj.end(), "", "", ", ", "", "" ); } + +} // namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/ResolverProblem.h b/zypp/ResolverProblem.h new file mode 100644 index 0000000..365cfcd --- /dev/null +++ b/zypp/ResolverProblem.h @@ -0,0 +1,106 @@ +/* + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Author: Stefan Hundhammer + * + **/ + +#ifndef ZYPP_RESOLVERPROBLEM_H +#define ZYPP_RESOLVERPROBLEM_H + +#include +#include +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////////// + /// \class ResolverProblem + /// \brief Describe a solver problem and offer solutions. + /////////////////////////////////////////////////////////////////////// + class ZYPP_API ResolverProblem : public base::ReferenceCounted + { + public: + /** Constructor. */ + ResolverProblem(); + /** Constructor. */ + ResolverProblem( std::string description ); + /** Constructor. */ + ResolverProblem( std::string description, std::string details ); + /** Constructor. */ + ResolverProblem( std::string description, std::string details, std::vector &&completeProblemInfo ); + + /** Destructor. */ + ~ResolverProblem() override; + + + /** + * Return a one-line description of the problem. + **/ + const std::string & description() const; + + /** + * Return a (possibly muti-line) detailed description of the problem + * or an empty string if there are no useful details. + **/ + const std::string & details() const; + + /** + * Return a one-line description for each problematic rule in the problem tree + **/ + const std::vector & completeProblemInfo() const; + + /** + * Return the possible solutions to this problem. + * All problems should have at least 2-3 (mutually exclusive) solutions: + * + * - Undo: Do not perform the offending transaction + * (do not install the package that had unsatisfied requirements, + * do not remove the package that would break other packages' requirements) + * + * - Remove referrers: Remove all packages that would break because + * they depend on the package that is requested to be removed + * + * - Ignore: Inject artificial "provides" for a missing requirement + * (pretend that requirement is satisfied) + **/ + const ProblemSolutionList & solutions() const; + + + /** + * Set description of the problem. + **/ + void setDescription( std::string description ); + + /** + * Set detail description of the problem. + **/ + void setDetails( std::string details ); + + /** + * Add a solution to this problem. This class takes over ownership of + * the problem and will delete it when neccessary. + **/ + void addSolution( const ProblemSolution_Ptr& solution, bool inFront = false ); + + private: + struct Impl; + RWCOW_pointer _pimpl; + }; + + /** \relates ResolverProblem Stream output */ + std::ostream & operator<<( std::ostream &, const ResolverProblem & obj ) ZYPP_API; + + /** \relates ResolverProblem Stream output */ + std::ostream & operator<<( std::ostream &, const ResolverProblemList & obj ) ZYPP_API; + + +} // namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_RESOLVERPROBLEM_H + diff --git a/zypp/ServiceInfo.cc b/zypp/ServiceInfo.cc new file mode 100644 index 0000000..0ad9b08 --- /dev/null +++ b/zypp/ServiceInfo.cc @@ -0,0 +1,242 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ServiceInfo.cc + * + */ +#include +#include + +#include +#include +#include + +#include +#include + +using std::endl; +using zypp::xml::escape; + +/////////////////////////////////////////////////////////////////////////////// +namespace zypp +{////////////////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ServiceInfo::Impl + // + struct ServiceInfo::Impl + { + using ReposToEnable = ServiceInfo::ReposToEnable; + using ReposToDisable = ServiceInfo::ReposToDisable; + + public: + RepoVariablesReplacedUrl _url; + repo::ServiceType _type; + ReposToEnable _reposToEnable; + ReposToDisable _reposToDisable; + RepoStates _repoStates; + DefaultIntegral _ttl; + Date _lrf; + + public: + Impl() + {} + + Impl(const Url &url_r) : _url(url_r) {} + + Impl(const Impl &) = default; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() + {} + + void setProbedType( const repo::ServiceType & type_r ) const + { + if ( _type == repo::ServiceType::NONE + && type_r != repo::ServiceType::NONE ) + { + // lazy init! + const_cast(this)->_type = type_r; + } + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ServiceInfo::Impl + // + /////////////////////////////////////////////////////////////////// + + const ServiceInfo ServiceInfo::noService; + + ServiceInfo::ServiceInfo() : _pimpl( new Impl() ) {} + + ServiceInfo::ServiceInfo(const std::string & alias) + : repo::RepoInfoBase(alias), _pimpl( new Impl() ) + {} + + ServiceInfo::ServiceInfo(const std::string & alias, const Url & url) + : repo::RepoInfoBase(alias), _pimpl( new Impl(url) ) + {} + + ServiceInfo::~ServiceInfo() + {} + + Url ServiceInfo::url() const // Variables replaced + { return _pimpl->_url.transformed(); } + + Url ServiceInfo::rawUrl() const // Raw + { return _pimpl->_url.raw(); } + + void ServiceInfo::setUrl( const Url& url ) // Raw + { _pimpl->_url.raw() = url; } + + repo::ServiceType ServiceInfo::type() const { return _pimpl->_type; } + void ServiceInfo::setType( const repo::ServiceType & type ) { _pimpl->_type = type; } + void ServiceInfo::setProbedType( const repo::ServiceType &t ) const { _pimpl->setProbedType( t ); } + + Date::Duration ServiceInfo::ttl() const { return _pimpl->_ttl; } + void ServiceInfo::setTtl( Date::Duration ttl_r ) { _pimpl->_ttl = ttl_r; } + void ServiceInfo::setProbedTtl( Date::Duration ttl_r ) const { const_cast(this)->setTtl( ttl_r ); } + + Date ServiceInfo::lrf() const { return _pimpl->_lrf; } + void ServiceInfo::setLrf( Date lrf_r ) { _pimpl->_lrf = lrf_r; } + + bool ServiceInfo::reposToEnableEmpty() const { return _pimpl->_reposToEnable.empty(); } + ServiceInfo::ReposToEnable::size_type ServiceInfo::reposToEnableSize() const { return _pimpl->_reposToEnable.size(); } + ServiceInfo::ReposToEnable::const_iterator ServiceInfo::reposToEnableBegin() const { return _pimpl->_reposToEnable.begin(); } + ServiceInfo::ReposToEnable::const_iterator ServiceInfo::reposToEnableEnd() const { return _pimpl->_reposToEnable.end(); } + + bool ServiceInfo::repoToEnableFind( const std::string & alias_r ) const + { return( _pimpl->_reposToEnable.find( alias_r ) != _pimpl->_reposToEnable.end() ); } + + void ServiceInfo::addRepoToEnable( const std::string & alias_r ) + { + _pimpl->_reposToEnable.insert( alias_r ); + _pimpl->_reposToDisable.erase( alias_r ); + } + + void ServiceInfo::delRepoToEnable( const std::string & alias_r ) + { _pimpl->_reposToEnable.erase( alias_r ); } + + void ServiceInfo::clearReposToEnable() + { _pimpl->_reposToEnable.clear(); } + + + bool ServiceInfo::reposToDisableEmpty() const { return _pimpl->_reposToDisable.empty(); } + ServiceInfo::ReposToDisable::size_type ServiceInfo::reposToDisableSize() const { return _pimpl->_reposToDisable.size(); } + ServiceInfo::ReposToDisable::const_iterator ServiceInfo::reposToDisableBegin() const { return _pimpl->_reposToDisable.begin(); } + ServiceInfo::ReposToDisable::const_iterator ServiceInfo::reposToDisableEnd() const { return _pimpl->_reposToDisable.end(); } + + bool ServiceInfo::repoToDisableFind( const std::string & alias_r ) const + { return( _pimpl->_reposToDisable.find( alias_r ) != _pimpl->_reposToDisable.end() ); } + + void ServiceInfo::addRepoToDisable( const std::string & alias_r ) + { + _pimpl->_reposToDisable.insert( alias_r ); + _pimpl->_reposToEnable.erase( alias_r ); + } + + void ServiceInfo::delRepoToDisable( const std::string & alias_r ) + { _pimpl->_reposToDisable.erase( alias_r ); } + + void ServiceInfo::clearReposToDisable() + { _pimpl->_reposToDisable.clear(); } + + + const ServiceInfo::RepoStates & ServiceInfo::repoStates() const { return _pimpl->_repoStates; } + void ServiceInfo::setRepoStates( RepoStates newStates_r ) { swap( _pimpl->_repoStates, newStates_r ); } + + + std::ostream & operator<<( std::ostream & str, const ServiceInfo::RepoState & obj ) + { + return str + << "enabled=" << obj.enabled << " " + << "autorefresh=" << obj.autorefresh << " " + << "priority=" << obj.priority; + } + + std::ostream & ServiceInfo::dumpAsIniOn( std::ostream & str ) const + { + RepoInfoBase::dumpAsIniOn(str) + << "url = " << hotfix1050625::asString( rawUrl() ) << endl + << "type = " << type() << endl; + + if ( ttl() ) + str << "ttl_sec = " << ttl() << endl; + + if ( lrf() ) + str << "lrf_dat = " << lrf().asSeconds() << endl; + + if ( ! repoStates().empty() ) + { + unsigned cnt = 0U; + for ( const auto & el : repoStates() ) + { + std::string tag( "repo_" ); + tag += str::numstring( ++cnt ); + const RepoState & state( el.second ); + + str << tag << "=" << el.first << endl + << tag << "_enabled=" << state.enabled << endl + << tag << "_autorefresh=" << state.autorefresh << endl; + if ( state.priority != RepoInfo::defaultPriority() ) + str + << tag << "_priority=" << state.priority << endl; + } + } + + if ( ! reposToEnableEmpty() ) + str << "repostoenable = " << str::joinEscaped( reposToEnableBegin(), reposToEnableEnd() ) << endl; + if ( ! reposToDisableEmpty() ) + str << "repostodisable = " << str::joinEscaped( reposToDisableBegin(), reposToDisableEnd() ) << endl; + return str; + } + + std::ostream & ServiceInfo::dumpAsXmlOn( std::ostream & str, const std::string & content ) const + { + str + << "" << endl; + else + str << ">" << endl << content << "" << endl; + + return str; + } + + + std::ostream & operator<<( std::ostream& str, const ServiceInfo &obj ) + { + return obj.dumpAsIniOn(str); + } + + +/////////////////////////////////////////////////////////////////////////////// +} //namespace zypp +/////////////////////////////////////////////////////////////////////////////// diff --git a/zypp/ServiceInfo.h b/zypp/ServiceInfo.h new file mode 100644 index 0000000..5e04699 --- /dev/null +++ b/zypp/ServiceInfo.h @@ -0,0 +1,232 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ServiceInfo.h + * + */ +#ifndef ZYPP_SERVICE_H +#define ZYPP_SERVICE_H + +#include +#include + +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class ServiceInfo + /// \brief Service data + /// + /// \note Name and Url are subject to repo variable replacement + /// (\see \ref RepoVariablesStringReplacer). + /// + class ZYPP_API ServiceInfo : public repo::RepoInfoBase + { + public: + /** Default ctor creates \ref noService.*/ + ServiceInfo(); + + /** + * Creates ServiceInfo with specified alias. + * + * \param alias unique short name of service + */ + ServiceInfo( const std::string & alias ); + + /** + * ServiceInfo with alias and its URL + * + * \param alias unique shortname of service + * \param url url to service + */ + ServiceInfo( const std::string & alias, const Url& url ); + + ~ServiceInfo() override; + + public: + /** Represents an empty service. */ + static const ServiceInfo noService ZYPP_API; + + public: + + /** The service url */ + Url url() const; + + /** The service raw url (no variables replaced) */ + Url rawUrl() const; + + /** Set the service url (raw value) */ + void setUrl( const Url& url ); + + + /** Service type */ + repo::ServiceType type() const; + + /** Set service type */ + void setType( const repo::ServiceType & type ); + + /** Lazy init service type */ + void setProbedType( const repo::ServiceType & t ) const; + + /** \name Housekeeping data + * You don't want to use the setters unless you are a \ref RepoManager. + */ + //@{ + /** Sugested TTL between two metadata auto-refreshs. + * The value (in seconds) may be provided in repoindex.xml:xpath:/repoindex@ttl. + * Default is \a 0 - perform each auto-refresh request. + */ + Date::Duration ttl() const; + + /** Set sugested TTL. */ + void setTtl( Date::Duration ttl_r ); + + /** Lazy init sugested TTL. */ + void setProbedTtl( Date::Duration ttl_r ) const; + + /** Date of last refresh (if known). */ + Date lrf() const; + + /** Set date of last refresh. */ + void setLrf( Date lrf_r ); + //@} + // + /** \name Set of repos (repository aliases) to enable on next refresh. + * + * Per default new repositories are created in disabled state. But repositories + * mentioned here will be created in enabled state on the next refresh. + * Afterwards they get removed from the list. + */ + //@{ + /** Container of repos. */ + using ReposToEnable = std::set; + bool reposToEnableEmpty() const; + ReposToEnable::size_type reposToEnableSize() const; + ReposToEnable::const_iterator reposToEnableBegin() const; + ReposToEnable::const_iterator reposToEnableEnd() const; + Iterable reposToEnable() const + { return makeIterable( reposToEnableBegin(), reposToEnableEnd() ); } + + /** Whether \c alias_r is mentioned in ReposToEnable. */ + bool repoToEnableFind( const std::string & alias_r ) const; + + /** Add \c alias_r to the set of ReposToEnable. */ + void addRepoToEnable( const std::string & alias_r ); + /** Remove \c alias_r from the set of ReposToEnable. */ + void delRepoToEnable( const std::string & alias_r ); + /** Clear the set of ReposToEnable. */ + void clearReposToEnable(); + //@} + + /** \name Set of repos (repository aliases) to disable on next refresh. + * + * Repositories mentioned here will be disabled on the next refresh, in case they + * still exist. Afterwards they get removed from the list. + */ + //@{ + /** Container of repos. */ + using ReposToDisable = std::set; + bool reposToDisableEmpty() const; + ReposToDisable::size_type reposToDisableSize() const; + ReposToDisable::const_iterator reposToDisableBegin() const; + ReposToDisable::const_iterator reposToDisableEnd() const; + Iterable reposToDisable() const + { return makeIterable( reposToDisableBegin(), reposToDisableEnd() ); } + + /** Whether \c alias_r is mentioned in ReposToDisable. */ + bool repoToDisableFind( const std::string & alias_r ) const; + + /** Add \c alias_r to the set of ReposToDisable. */ + void addRepoToDisable( const std::string & alias_r ); + /** Remove \c alias_r from the set of ReposToDisable. */ + void delRepoToDisable( const std::string & alias_r ); + /** Clear the set of ReposToDisable. */ + void clearReposToDisable(); + //@} + + /** \name The original repo state as defined by the repoindex.xml upon last refresh. + * + * This state is remembered to detect any user modifications applied to the repos. + * It may not be available for all repos or in plugin services. In this case all + * changes requested by a service refresh are applied unconditionally. + */ + //@{ + struct RepoState + { + bool enabled; + bool autorefresh; + unsigned priority; + + RepoState() + : enabled( false ), autorefresh( true ), priority( RepoInfo::defaultPriority() ) + {} + RepoState( const RepoInfo & repo_r ) + : enabled( repo_r.enabled() ), autorefresh( repo_r.autorefresh() ), priority( repo_r.priority() ) + {} + bool operator==( const RepoState & rhs ) const + { return( enabled==rhs.enabled && autorefresh==rhs.autorefresh && priority==rhs.priority ); } + bool operator!=( const RepoState & rhs ) const + { return ! operator==( rhs ); } + friend std::ostream & operator<<( std::ostream & str, const RepoState & obj ); + }; + using RepoStates = std::map; + + /** Access the remembered repository states. */ + const RepoStates & repoStates() const; + + /** Remember a new set of repository states. */ + void setRepoStates( RepoStates newStates_r ); + //@} + + public: + /** + * Writes ServiceInfo to stream in ".service" format + * + * \param str stream where serialized version service is written + */ + std::ostream & dumpAsIniOn( std::ostream & str ) const override; + + /** + * Write an XML representation of this ServiceInfo object. + * + * \param str + * \param content if not empty, produces content + * otherwise + */ + std::ostream & dumpAsXmlOn( std::ostream & str, const std::string & content = "" ) const override; + + struct Impl; + + private: + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ServiceInfo */ + using ServiceInfo_Ptr = shared_ptr; + /** \relates ServiceInfo */ + using ServiceInfo_constPtr = shared_ptr; + /** \relates ServiceInfo */ + using ServiceInfoList = std::list; + + /** \relates ServiceInfo Stream output */ + std::ostream & operator<<( std::ostream & str, const ServiceInfo & obj ) ZYPP_API; + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_REPOSITORY_H diff --git a/zypp/Signature.cc b/zypp/Signature.cc new file mode 100644 index 0000000..f2a26b6 --- /dev/null +++ b/zypp/Signature.cc @@ -0,0 +1,30 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + Signature::Signature() + { + + } + + std::ostream & Signature::dumpOn( std::ostream & str ) const + { + return str; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Signature.h b/zypp/Signature.h new file mode 100644 index 0000000..3db2274 --- /dev/null +++ b/zypp/Signature.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + + +#ifndef ZYPP_Signature_H +#define ZYPP_Signature_H + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class Signature + { + public: + Signature(); + ~Signature(); + + /** Overload to realize stream output. */ + std::ostream & dumpOn( std::ostream & str ) const; + + private: + }; + + /** \relates Signature Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Signature & obj ) + { return obj.dumpOn( str ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_Signature_H diff --git a/zypp/SrcPackage.cc b/zypp/SrcPackage.cc new file mode 100644 index 0000000..07439ec --- /dev/null +++ b/zypp/SrcPackage.cc @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/SrcPackage.cc + * +*/ +#include +/////////////////////////////////////////////////////////////////// +namespace zyppintern +{ + using namespace zypp; + // in Package.cc + Pathname cachedLocation( const OnMediaLocation & loc_r, const RepoInfo & repo_r ); +} // namespace zyppintern +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(SrcPackage); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : SrcPackage::SrcPackage + // METHOD TYPE : Ctor + // + SrcPackage::SrcPackage( const sat::Solvable & solvable_r ) + : ResObject( solvable_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : SrcPackage::~SrcPackage + // METHOD TYPE : Dtor + // + SrcPackage::~SrcPackage() + {} + + /////////////////////////////////////////////////////////////////// + // + // SrcPackage interface forwarded to implementation + // + /////////////////////////////////////////////////////////////////// + + std::string SrcPackage::sourcePkgType() const + { return lookupStrAttribute( sat::SolvAttr::arch ); } + + OnMediaLocation SrcPackage::location() const + { return lookupLocation(); } + + Pathname SrcPackage::cachedLocation() const + { return zyppintern::cachedLocation( location(), repoInfo() ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/SrcPackage.h b/zypp/SrcPackage.h new file mode 100644 index 0000000..be071e3 --- /dev/null +++ b/zypp/SrcPackage.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/SrcPackage.h + * +*/ +#ifndef ZYPP_SRCPACKAGE_H +#define ZYPP_SRCPACKAGE_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(SrcPackage); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SrcPackage + // + /** SrcPackage interface. + */ + class ZYPP_API SrcPackage : public ResObject + { + + public: + using Self = SrcPackage; + using TraitsType = ResTraits; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + /** The type of the source rpm ("src" or "nosrc"). */ + std::string sourcePkgType() const; + + /** location of resolvable in repo */ + OnMediaLocation location() const; + + /** Location of the downloaded package in cache or an empty path. */ + Pathname cachedLocation() const; + + /** Whether the package is cached. */ + bool isCached() const + { return ! cachedLocation().empty(); } + + protected: + friend Ptr make( const sat::Solvable & solvable_r ); + /** Ctor */ + SrcPackage( const sat::Solvable & solvable_r ); + /** Dtor */ + ~SrcPackage() override; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SRCPACKAGE_H diff --git a/zypp/SysContent.cc b/zypp/SysContent.cc new file mode 100644 index 0000000..4b5bffe --- /dev/null +++ b/zypp/SysContent.cc @@ -0,0 +1,457 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/SysContent.cc + * +*/ +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace syscontent + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace // Writer helpers + { ///////////////////////////////////////////////////////////////// + + /** writeXml helper. + * \return tag="value" if value not empty, else + * an empty string. + */ + inline std::string attrIf( const std::string & tag_r, + const std::string & value_r ) + { + std::string ret; + if ( ! value_r.empty() ) + { + ret += " "; + ret += tag_r; + ret += "=\""; + ret += value_r; + ret += "\""; + } + return ret; + } + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Writer::Impl + // + /** \see Writer */ + class Writer::Impl + { + public: + std::ostream & writeXml( std::ostream & str ) const; + + public: + std::string _name; + Edition _edition; + std::string _description; + StorageT _onsys; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Writer::Impl::writeXml + // METHOD TYPE : std::ostream & + // + std::ostream & Writer::Impl::writeXml( std::ostream & str ) const + { + // intro + str << "\n"; + str << "\n"; + // ident data + str << " \n"; + str << " " << _name << "\n"; + str << " \n"; + str << " " << _description << "\n"; + str << " " << Date::now().asSeconds() << "\n"; + str << " \n"; + // ResObjects + str << " \n"; + for ( iterator it = _onsys.begin(); it != _onsys.end(); ++it ) + { + str << " kind().asString() ) + << attrIf( "name", (*it)->name() ) + << attrIf( "epoch", str::numstring((*it)->edition().epoch()) ) + << attrIf( "ver", (*it)->edition().version() ) + << attrIf( "rel", (*it)->edition().release() ) + << attrIf( "arch", (*it)->arch().asString() ) + << "/>\n"; + } + str << " \n"; + // extro + str << "" << endl; + return str; + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Writer + // + /////////////////////////////////////////////////////////////////// + + Writer::Writer() + : _pimpl( Impl::nullimpl() ) + {} + + const std::string & Writer::name() const + { return _pimpl->_name; } + + Writer & Writer::name( const std::string & val_r ) + { _pimpl->_name = val_r; return *this; } + + const Edition & Writer::edition() const + { return _pimpl->_edition; } + + Writer & Writer::edition( const Edition & val_r ) + { _pimpl->_edition = val_r; return *this; } + + const std::string & Writer::description() const + { return _pimpl->_description; } + + Writer & Writer::description( const std::string & val_r ) + { _pimpl->_description = val_r; return *this; } + + void Writer::addInstalled( const PoolItem & obj_r ) + { + if ( obj_r.status().isInstalled() ) + { + _pimpl->_onsys.insert( obj_r.resolvable() ); + } + } + + void Writer::addIf( const PoolItem & obj_r ) + { + if ( obj_r.status().isInstalled() != obj_r.status().transacts() + && ! ( obj_r.status().transacts() && obj_r.status().isBySolver() ) ) + { + _pimpl->_onsys.insert( obj_r.resolvable() ); + } + } + + void Writer::add( const ResObject::constPtr & obj_r ) + { _pimpl->_onsys.insert( obj_r ); } + + bool Writer::empty() const + { return _pimpl->_onsys.empty(); } + + Writer::size_type Writer::size() const + { return _pimpl->_onsys.size(); } + + Writer::const_iterator Writer::begin() const + { return _pimpl->_onsys.begin(); } + + Writer::const_iterator Writer::end() const + { return _pimpl->_onsys.end(); } + + std::ostream & Writer::writeXml( std::ostream & str ) const + { return _pimpl->writeXml( str ); } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Reader::Entry::Impl + // + class Reader::Entry::Impl + { + public: + std::string _kind; + std::string _name; + Edition _edition; + Arch _arch; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Reader::Entry + // + /////////////////////////////////////////////////////////////////// + + Reader::Entry::Entry() + : _pimpl( new Impl ) + {} + + Reader::Entry::Entry( const shared_ptr & pimpl_r ) + : _pimpl( pimpl_r ) + {} + + const std::string & Reader::Entry::kind() const + { return _pimpl->_kind; } + + const std::string & Reader::Entry::name() const + { return _pimpl->_name; } + + const Edition & Reader::Entry::edition() const + { return _pimpl->_edition; } + + const Arch & Reader::Entry::arch() const + { return _pimpl->_arch; } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Reader::Impl + // + /** \see Reader */ + class Reader::Impl + { + public: + Impl() + {} + + Impl( std::istream & input_r ); + + public: + std::string _name; + Edition _edition; + std::string _description; + Date _created; + + std::list _content; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace // Reader helpers + { ///////////////////////////////////////////////////////////////// + + using namespace xml; + + /** Sycontent xml node structure. */ + struct SycontentNode : public ParseDef + { + SycontentNode( Mode mode_r ) + : ParseDef( "syscontent", mode_r ) + { + (*this)("ident", OPTIONAL) + ("onsys", OPTIONAL) + ; + + (*this)["ident"] + ("name", OPTIONAL) + ("version", OPTIONAL) + ("description", OPTIONAL) + ("created", OPTIONAL) + ; + + (*this)["onsys"] + ("entry", MULTIPLE_OPTIONAL) + ; + } + }; + + /** Parse Edition from ver/rel/eopch attributes. */ + struct ConsumeEdition : public ParseDefConsume + { + ConsumeEdition( Edition & value_r ) + : _value( & value_r ) + {} + + void start( const Node & node_r ) override + { + *_value = Edition( node_r.getAttribute("ver").asString(), + node_r.getAttribute("rel").asString(), + node_r.getAttribute("epoch").asString() ); + } + + Edition *_value; + }; + + /** Parse std::string from node value. */ + struct ConsumeString : public ParseDefConsume + { + ConsumeString( std::string & value_r ) + : _value( & value_r ) + {} + + void text( const Node & node_r ) override + { + *_value = node_r.value().asString(); + } + + std::string *_value; + }; + + /** Parse Date from node value. */ + struct ConsumeDate : public ParseDefConsume + { + ConsumeDate( Date & value_r ) + : _value( & value_r ) + {} + + void text( const Node & node_r ) override + { + *_value = Date(node_r.value().asString()); + } + + Date *_value; + }; + + /** Parse entry list. */ + struct ConsumeEntries : public ParseDefConsume + { + ConsumeEntries( std::list & value_r ) + : _value( & value_r ) + {} + + void start( const Node & node_r ) override + { + shared_ptr centry( new Reader::Entry::Impl ); + + centry->_kind = node_r.getAttribute("kind").asString(); + centry->_name = node_r.getAttribute("name").asString(); + centry->_edition = Edition( node_r.getAttribute("ver").asString(), + node_r.getAttribute("rel").asString(), + node_r.getAttribute("epoch").asString() ); + centry->_arch = Arch( node_r.getAttribute("arch").asString() ); + + _value->push_back( Reader::Entry( centry ) ); + } + + std::list *_value; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::Impl::Impl + // METHOD TYPE : Constructor + // + Reader::Impl::Impl( std::istream & input_r ) + { + xml::Reader reader( input_r ); + SycontentNode rootNode( xml::ParseDef::MANDTAORY ); + + rootNode["ident"]["name"].setConsumer + ( new ConsumeString( _name ) ); + + rootNode["ident"]["version"].setConsumer + ( new ConsumeEdition( _edition ) ); + + rootNode["ident"]["description"].setConsumer + ( new ConsumeString( _description ) ); + + rootNode["ident"]["created"].setConsumer + ( new ConsumeDate( _created ) ); + + rootNode["onsys"]["entry"].setConsumer + ( new ConsumeEntries( _content ) ); + + // parse + rootNode.take( reader ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Reader + // + /////////////////////////////////////////////////////////////////// + + Reader::Reader() + : _pimpl( Impl::nullimpl() ) + {} + + Reader::Reader( std::istream & input_r ) + : _pimpl( new Impl( input_r ) ) + {} + + const std::string & Reader::name() const + { return _pimpl->_name; } + + const Edition & Reader::edition() const + { return _pimpl->_edition; } + + const std::string & Reader::description() const + { return _pimpl->_description; } + + const Date & Reader::ctime() const + { return _pimpl->_created; } + + bool Reader::empty() const + { return _pimpl->_content.empty(); } + + Reader::size_type Reader::size() const + { return _pimpl->_content.size(); } + + Reader::const_iterator Reader::begin() const + { return _pimpl->_content.begin(); } + + Reader::const_iterator Reader::end() const + { return _pimpl->_content.end(); } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : inline std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Reader & obj ) + { + return str << "syscontent(" << obj.name() << "-" << obj.edition() + << ", " << obj.size() << " entries" + << ", created " << obj.ctime() + << ")"; + } + + ///////////////////////////////////////////////////////////////// + } // namespace syscontent + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/SysContent.h b/zypp/SysContent.h new file mode 100644 index 0000000..fac900a --- /dev/null +++ b/zypp/SysContent.h @@ -0,0 +1,265 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/SysContent.h + * +*/ +#ifndef ZYPP_SYSCONTENT_H +#define ZYPP_SYSCONTENT_H + +#include +#include +#include + +#include + +#include +#include +#include + +#ifdef YUILogComponent +// Work around https://github.com/libyui/libyui/issues/78 +// The hack here is needed to allow older libyui-qt-pkg building +// against current libzypp. Otherwise libyui builds for Code15.4 +// or older will break. +#define BOOST_BIND_GLOBAL_PLACEHOLDERS +#include +#endif + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace syscontent + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Writer + // + /** Collect and serialize a set of \ref ResObject. + * \code + * + * + * + * mycollection + * + * All the cool stuff... + * 1165270942 + * + * + * + * + * + * + * \endcode + * \see Reader + */ + class ZYPP_API Writer + { + using StorageT = std::set; + public: + using value_type = StorageT::value_type; + using size_type = StorageT::size_type; + using iterator = StorageT::iterator; + using const_iterator = StorageT::const_iterator; + + public: + /** Default Ctor. */ + Writer(); + + public: + /** \name Identification. + * User provided optional data to identify the collection. + */ + //@{ + /** Get name. */ + const std::string & name() const; + + /** Set name. */ + Writer & name( const std::string & val_r ); + + /** Get edition. */ + const Edition & edition() const; + + /** Set edition. */ + Writer & edition( const Edition & val_r ); + + /** Get description. */ + const std::string & description() const; + + /** Set description.*/ + Writer & description( const std::string & val_r ); + //@} + + public: + /** \name Collecting data. + * \code + * syscontent::Writer contentW; + * contentW.name( "mycollection" ) + * .edition( Edition( "1.0" ) ) + * .description( "All the cool stuff..." ); + * + * ResPool pool( getZYpp()->pool() ); + * for_each( pool.begin(), pool.end(), + * bind( &syscontent::Writer::addIf, ref(contentW), _1 ) ); + * + * std::ofstream my_file( "some_file" ); + * my_file << contentW; + * my_file.close(); + * \endcode + */ + //@{ + /** Collect currently installed \ref PoolItem. */ + void addInstalled( const PoolItem & obj_r ); + + /** Collect \ref PoolItem if it stays on the system. + * I.e. it stays installed or is tagged to be installed. + * Solver selected items are omitted. + */ + void addIf( const PoolItem & obj_r ); + + /** Unconditionally add this \ref ResObject (or \ref PoolItem). */ + void add( const ResObject::constPtr & obj_r ); + //@} + + public: + /** \name Collected data. */ + //@{ + /** Whether no data collected so far. */ + bool empty() const; + + /** Number of items collected. */ + size_type size() const; + + /** Iterator to the begin of collected data. */ + const_iterator begin() const; + + /** Iterator to the end of collected data. */ + const_iterator end() const; + //@} + + public: + /** Write collected data as XML. + * Read them back using \ref Reader. + */ + std::ostream & writeXml( std::ostream & str ) const; + + private: + class Impl; + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Writer Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Writer & obj ) + { return obj.writeXml( str ); } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Reader + // + /** Retrieve \ref ResObject data serialized by \ref Writer. + * \see Writer + */ + class ZYPP_API Reader + { + public: + /** Restored \ref ResObject data. */ + class Entry; + + private: + using StorageT = std::list; + + public: + using value_type = StorageT::value_type; + using size_type = StorageT::size_type; + using iterator = StorageT::iterator; + using const_iterator = StorageT::const_iterator; + + public: + /** Default Ctor. */ + Reader(); + + /** Ctor parsing data from \a input_r. + * \throws Exception on read or parse error. + */ + Reader( std::istream & input_r ); + + public: + /** \name Identification. + * User provided optional data to identify the collection. + */ + //@{ + /** Get name. */ + const std::string & name() const; + + /** Get edition. */ + const Edition & edition() const; + + /** Get description. */ + const std::string & description() const; + + /** Get creation date. */ + const Date & ctime() const; + + public: + /** \name Collected data. */ + //@{ + /** Whether no data collected so far. */ + bool empty() const; + + /** Number of items collected. */ + size_type size() const; + + /** Iterator to the begin of collected data. */ + const_iterator begin() const; + + /** Iterator to the end of collected data. */ + const_iterator end() const; + //@} + + private: + class Impl; + RWCOW_pointer _pimpl; + }; + + /** \relates Reader Stream output */ + std::ostream & operator<<( std::ostream & str, const Reader & obj ); + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Reader::Entry + // + /** Restored \ref ResObject data. */ + class ZYPP_API Reader::Entry + { + public: + Entry(); + const std::string & kind() const; + const std::string & name() const; + const Edition & edition() const; + const Arch & arch() const; + public: + class Impl; + Entry( const shared_ptr & pimpl_r ); + private: + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace syscontent + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SYSCONTENT_H diff --git a/zypp/Target.cc b/zypp/Target.cc new file mode 100644 index 0000000..5866d17 --- /dev/null +++ b/zypp/Target.cc @@ -0,0 +1,144 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Target.cc + * +*/ +#include + +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(Target); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Target::Target + // METHOD TYPE : Ctor + // + Target::Target( const Pathname & root, bool doRebuild_r ) + : _pimpl( new Impl(root,doRebuild_r) ) + { + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Target::Target + // METHOD TYPE : Ctor + // + Target::Target( const Impl_Ptr & impl_r ) + : _pimpl( impl_r ) + { + assert( impl_r ); + } + + std::ostream & operator<<( std::ostream & str, const Target::DistributionLabel & obj ) + { + str << "summary=" << obj.summary << endl; + str << "shortName=" << obj.shortName << endl; + return str; + } + + /////////////////////////////////////////////////////////////////// + // + // Forward to TargetImpl: + // + /////////////////////////////////////////////////////////////////// + + void Target::buildCache() + { _pimpl->buildCache(); } + + void Target::cleanCache() + { _pimpl->clearCache(); } + + void Target::load() + { _pimpl->load(); } + + void Target::reload() + { _pimpl->reload(); } + + void Target::unload() + { _pimpl->unload(); } + + target::rpm::RpmDb & Target::rpmDb() + { return _pimpl->rpm(); } + + Pathname Target::root() const + { return _pimpl->root(); } + + bool Target::providesFile (const std::string & name_str, const std::string & path_str) const + { return _pimpl->providesFile (name_str, path_str); } + + std::string Target::whoOwnsFile (const std::string & path_str) const + { return _pimpl->whoOwnsFile (path_str); } + + std::ostream & Target::dumpOn( std::ostream & str ) const + { return _pimpl->dumpOn( str ); } + + Product::constPtr Target::baseProduct() const + { return _pimpl->baseProduct(); } + + LocaleSet Target::requestedLocales() const + { return _pimpl->requestedLocales(); } + LocaleSet Target::requestedLocales( const Pathname & root_r ) + { return target::TargetImpl::requestedLocales( root_r ); } + + void Target::updateAutoInstalled() + { return _pimpl->updateAutoInstalled(); } + + std::string Target::targetDistribution() const + { return _pimpl->targetDistribution(); } + std::string Target::targetDistribution( const Pathname & root_r ) + { return target::TargetImpl::targetDistribution( root_r ); } + + std::string Target::targetDistributionRelease() const + { return _pimpl->targetDistributionRelease(); } + std::string Target::targetDistributionRelease( const Pathname & root_r ) + { return target::TargetImpl::targetDistributionRelease( root_r ); } + + std::string Target::targetDistributionFlavor() const + { return _pimpl->targetDistributionFlavor(); } + std::string Target::targetDistributionFlavor( const Pathname & root_r ) + { return target::TargetImpl::targetDistributionFlavor( root_r ); } + + Target::DistributionLabel Target::distributionLabel() const + { return _pimpl->distributionLabel(); } + Target::DistributionLabel Target::distributionLabel( const Pathname & root_r ) + { return target::TargetImpl::distributionLabel( root_r ); } + + std::string Target::distributionVersion() const + { return _pimpl->distributionVersion(); } + std::string Target::distributionVersion( const Pathname & root_r ) + { return target::TargetImpl::distributionVersion( root_r ); } + + std::string Target::distributionFlavor() const + { return _pimpl->distributionFlavor(); } + std::string Target::distributionFlavor( const Pathname & root_r ) + { return target::TargetImpl::distributionFlavor( root_r ); } + + std::string Target::anonymousUniqueId() const + { return _pimpl->anonymousUniqueId(); } + std::string Target::anonymousUniqueId( const Pathname & root_r ) + { return target::TargetImpl::anonymousUniqueId( root_r ); } + + const VendorAttr & Target::vendorAttr() const + { return _pimpl->vendorAttr(); } + void Target::vendorAttr( VendorAttr vendorAttr_r ) + { _pimpl->vendorAttr( std::move(vendorAttr_r) ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Target.h b/zypp/Target.h new file mode 100644 index 0000000..b0e6fa2 --- /dev/null +++ b/zypp/Target.h @@ -0,0 +1,262 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Target.h + * +*/ +#ifndef ZYPP_TARGET_H +#define ZYPP_TARGET_H + +#include + +#include +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + class VendorAttr; + namespace target + { + class TargetImpl; + namespace rpm { + class RpmDb; + } + } + namespace zypp_detail + { + class ZYppImpl; + } + + DEFINE_PTR_TYPE(Target); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Target + // + /** + */ + class ZYPP_API Target : public base::ReferenceCounted, public base::NonCopyable + { + public: + using Impl = target::TargetImpl; + using Impl_Ptr = intrusive_ptr; + using PoolItemList = std::list; + + public: + + /** + * builds or refreshes the target cache + */ + void buildCache(); + + /** + * cleans the target cache (.solv files) + */ + void cleanCache(); + + /** + * load resolvables into the pool + */ + void load(); + + void reload(); + + /** + * unload target resolvables from the + * pool + */ + void unload(); + + /** Refference to the RPM database */ + target::rpm::RpmDb & rpmDb(); + + /** If the package is installed and provides the file + Needed to evaluate split provides during Resolver::Upgrade() */ + bool providesFile (const std::string & name_str, const std::string & path_str) const; + + /** Return name of package owning \a path_str + * or empty string if no installed package owns \a path_str. + **/ + std::string whoOwnsFile (const std::string & path_str) const; + + /** Return the root set for this target */ + Pathname root() const; + + /** Whether the targets \ref root is not \c "/". */ + bool chrooted() const + { return( ! root().emptyOrRoot() ); } + + /** Return the path prefixed by the target root, unless it already is prefixed. */ + Pathname assertRootPrefix( const Pathname & path_r ) const + { return Pathname::assertprefix( root(), path_r ); } + + /** + * returns the target base installed product, also known as + * the distribution or platform. + * + * returns 0 if there is no base installed product in the + * pool. + * + * \note this method requires the target to be loaded, + * otherwise it will return 0 as no product is found. + * + * if you require some base product attributes when the + * target is not loaded into the pool, see + * \ref targetDistribution , \ref targetDistributionRelease + * and \ref distributionVersion that obtain the data + * on demand from the installed product information. + */ + Product::constPtr baseProduct() const; + + /** + * \brief Languages to be supported by the system. + * E.g. language specific packages to be installed. + */ + LocaleSet requestedLocales() const; + /** \overload Use a specific root_r, if empty the default targets root, or '/' + */ + static LocaleSet requestedLocales( const Pathname & root_r ); + + /** Update the database of autoinstalled packages. + * This is done on commit, so you usually don't need to call this explicitly. + */ + void updateAutoInstalled(); + + public: + /** \name Base product and registration. + * + * Static methods herein allow one to retrieve the values without explicitly + * initializing the \ref Target. They take a targets root directory as + * argument. If an empty \ref Pathname is passed, an already existing + * Targets root is used, otherwise \c "/" is assumed. + */ + //@{ + /** This is \c register.target attribute of the installed base product. + * Used for registration and \ref Service refresh. + */ + std::string targetDistribution() const; + /** \overload */ + static std::string targetDistribution( const Pathname & root_r ); + + /** This is \c register.release attribute of the installed base product. + * Used for registration. + */ + std::string targetDistributionRelease() const; + /** \overload */ + static std::string targetDistributionRelease( const Pathname & root_r ); + + /** This is \c register.flavor attribute of the installed base product. + * Used for registration. + * \note don't mistake this for \ref distributionFlavor + */ + std::string targetDistributionFlavor() const; + /** \overload */ + static std::string targetDistributionFlavor( const Pathname & root_r ); + + struct DistributionLabel { std::string shortName; std::string summary; }; + /** This is \c shortName and \c summary attribute of the installed base product. + * Used e.g. for the bootloader menu. + */ + DistributionLabel distributionLabel() const; + /** \overload */ + static DistributionLabel distributionLabel( const Pathname & root_r ); + + /** This is \c version attribute of the installed base product. + * For example http://download.opensue.org/update/11.0 + * The 11.0 corresponds to the base product version. + */ + std::string distributionVersion() const; + /** \overload */ + static std::string distributionVersion( const Pathname & root_r ); + + /** + * This is \c flavor attribute of the installed base product + * but does not require the target to be loaded as it remembers + * the last used one. It can be empty is the target has never + * been loaded, as the value is not present in the system + * but computer from a package provides + * \note don't mistake this for \ref targetDistributionFlavor + */ + std::string distributionFlavor() const; + /** \overload */ + static std::string distributionFlavor( const Pathname & root_r ); + + /** + * anonymous unique id + * + * This id is generated once and stays in the + * saved in the target. + * It is unique and is used only for statistics. + * + */ + std::string anonymousUniqueId() const; + /** \overload */ + static std::string anonymousUniqueId( const Pathname & root_r ); + //@} + + public: + /** \name Definition of vendor equivalence. + * \see \ref VendorAttr + */ + //@{ + /** The targets current vendor equivalence settings. + * Initialized from the targets /etc/zypp/vendors.d. + */ + const VendorAttr & vendorAttr() const; + /** Assign new vendor equivalence settings to the target. */ + void vendorAttr( VendorAttr vendorAttr_r ); + //@} + + public: + /** Ctor. If \c doRebuild_r is \c true, an already existing + * database is rebuilt (rpm --rebuilddb ). + */ + explicit + Target( const Pathname & root = "/", bool doRebuild_r = false ); + /** Ctor */ + explicit + Target( const Impl_Ptr & impl_r ); + + private: + friend std::ostream & operator<<( std::ostream & str, const Target & obj ); + /** Stream output. */ + std::ostream & dumpOn( std::ostream & str ) const override; + + private: + /** Direct access to Impl. */ + friend class zypp_detail::ZYppImpl; + + /** Pointer to implementation */ + RW_pointer > _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Target Stream output. */ + inline std::ostream & operator<<( std::ostream & str, const Target & obj ) + { return obj.dumpOn( str ); } + + /** \relates Target::DistributionLabel Stream output. + * Write out the content as key/value pairs: + * \code + * summary=Beautiful Name + * shortName=BN + * \endcode + */ + std::ostream & operator<<( std::ostream & str, const Target::DistributionLabel & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_H diff --git a/zypp/TmpPath.cc b/zypp/TmpPath.cc new file mode 100644 index 0000000..5c294c0 --- /dev/null +++ b/zypp/TmpPath.cc @@ -0,0 +1,11 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/TmpPath.cc + * +*/ diff --git a/zypp/TmpPath.h b/zypp/TmpPath.h new file mode 100644 index 0000000..4035418 --- /dev/null +++ b/zypp/TmpPath.h @@ -0,0 +1,12 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/TmpPath.h + * +*/ +#include diff --git a/zypp/TriBool.h b/zypp/TriBool.h new file mode 100644 index 0000000..1e15bcf --- /dev/null +++ b/zypp/TriBool.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Url.h b/zypp/Url.h new file mode 100644 index 0000000..14da27d --- /dev/null +++ b/zypp/Url.h @@ -0,0 +1 @@ +#include diff --git a/zypp/UserData.h b/zypp/UserData.h new file mode 100644 index 0000000..3885494 --- /dev/null +++ b/zypp/UserData.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Vendor.h b/zypp/Vendor.h new file mode 100644 index 0000000..f0cd29f --- /dev/null +++ b/zypp/Vendor.h @@ -0,0 +1,30 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Vendor.h + * +*/ +#ifndef ZYPP_VENDOR_H +#define ZYPP_VENDOR_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + using Vendor = std::string; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#include "VendorAttr.h" + +#endif // ZYPP_VENDOR_H diff --git a/zypp/VendorAttr.cc b/zypp/VendorAttr.cc new file mode 100644 index 0000000..9407e56 --- /dev/null +++ b/zypp/VendorAttr.cc @@ -0,0 +1,343 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/VendorAttr.cc +*/ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::VendorAttr" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class VendorAttr::Impl + /// \brief VendorAttr implementation. + /////////////////////////////////////////////////////////////////// + class VendorAttr::Impl // : private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const Impl & obj ); + public: + /** Ctor. + * bsc#1030686: The legacy default equivalence of 'suse' and 'opensuse' + * has been removed. + * bnc#812608: No prefix compare in opensuse namespace, so just create + * a class for 'suse*' + */ + Impl() + { _vendorGroupMap["suse"] = ++_vendorGroupId; } + + public: + /** Add a new equivalent vendor set. */ + void addVendorList( VendorList && vendorList_r ); + + /** Return whether two vendor strings should be treated as equivalent.*/ + bool equivalent( IdString lVendor, IdString rVendor ) const + { return lVendor == rVendor || vendorMatchId( lVendor ) == vendorMatchId( rVendor ); } + + /** Return whether two vendor strings should be treated as equivalent or are (suse/opensuse).*/ + bool relaxedEquivalent( IdString lVendor, IdString rVendor ) const + { + if ( equivalent( lVendor, rVendor ) ) + return true; + + static const IdString suse { "suse" }; + static const IdString opensuse { "opensuse" }; + unsigned sid = vendorMatchId( suse ); + unsigned oid = vendorMatchId( opensuse ); + if ( sid == oid ) + return false; // (suse/opensuse) are equivalent, so these are not + + auto isSuse = [sid,oid]( unsigned v )-> bool { return v==sid || v==oid; }; + return isSuse( vendorMatchId(lVendor) ) && isSuse( vendorMatchId(rVendor) ); + } + + unsigned foreachVendorList( const std::function& fnc_r ) const + { + std::map lists; + for( const auto & el : _vendorGroupMap ) + lists[el.second].push_back( el.first ); + + unsigned ret = 0; + for ( auto el : lists ) { + VendorList & vlist { el.second }; + if ( vlist.empty() ) + continue; + ++ret; + if ( fnc_r && !fnc_r( std::move(vlist) ) ) + break; + } + return ret; + } + + private: + using VendorGroupMap = std::map; + VendorGroupMap _vendorGroupMap; ///< Vendor group definition. Equivalent groups share the same ID. + unsigned _vendorGroupId = 0; ///< Highest group ID in use (incremented). + + private: + using VendorMatchEntry = DefaultIntegral; + using VendorMatch = std::unordered_map; + mutable VendorMatch _vendorMatch; ///< Cache mapping vendor strings to equivalence class ID + mutable unsigned _nextId = 0; ///< Least equivalence class ID in use (decremented). + + /** Reset vendor match cache if _vendorGroupMap was changed. */ + void vendorMatchIdReset() + { + _nextId = 0; + _vendorMatch.clear(); + } + + /** Helper mapping a vendor string to its eqivalence class ID. + * + * \li Return the vendor strings eqivalence class ID stored in _vendorMatch. + * \li If not found, assign and return the eqivalence class ID of the lowercased string. + * \li If not found, assign and return a new ID (look into the predefined VendorGroupMap (id>0), + * otherwise create a new ID (<0)). + */ + unsigned vendorMatchId( IdString vendor ) const; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + + unsigned VendorAttr::Impl::vendorMatchId( IdString vendor ) const + { + VendorMatchEntry & ent { _vendorMatch[vendor] }; + if ( ! ent ) + { + IdString lcvendor { str::toLower( vendor.asString() ) }; + VendorMatchEntry & lcent( _vendorMatch[lcvendor] ); + if ( ! lcent ) + { + // Cache miss - check whether it belongs to a vendor group. + // Otherwise assign a new class ID to it. + unsigned myid = 0; + + // bnc#812608: no prefix compare in opensuse namespace + if ( str::hasPrefix( lcvendor.c_str(), "opensuse" ) ) + { + if ( auto it = _vendorGroupMap.find( lcvendor.c_str() ); it != _vendorGroupMap.end() ) + myid = it->second; + } + else + { + // Compare this entry with the global vendor map. + // Reversed to get the longest prefix. + for ( VendorGroupMap::const_reverse_iterator it = _vendorGroupMap.rbegin(); it != _vendorGroupMap.rend(); ++it ) + { + if ( str::hasPrefix( lcvendor.c_str(), it->first ) ) { + myid = it->second; + break; // found + } + } + } + + if ( ! myid ) + myid = --_nextId; // get a new class ID + + ent = lcent = myid; // remember the new DI + } + else + ent = lcent; // take the ID from the lowercased vendor string + } + return ent; + } + + void VendorAttr::Impl::addVendorList( VendorList && vendorList_r ) + { + // Will add a new equivalence group unless we merge with existing groups. + unsigned targetId = _vendorGroupId + 1; + + // (!) Convert the group strings in place to lowercase before adding/checking. + // Extend/join already existing groups if they are referenced. + for ( std::string & vendor : vendorList_r ) + { + vendor = str::toLower( std::move(vendor) ); + + if ( _vendorGroupMap.count( vendor ) ) + { + unsigned joinId = _vendorGroupMap[vendor]; + if ( targetId == _vendorGroupId + 1 ) { + targetId = joinId; // will extend the existing group + } + else if ( targetId != joinId ) { + // yet another existing group -> join it into the target group + for ( auto & el : _vendorGroupMap ) { + if ( el.second == joinId ) + el.second = targetId; + } + } + vendor.clear(); // no need to add it later + } + } + + // Now add the new entries + for ( std::string & vendor : vendorList_r ) { + if ( ! vendor.empty() ) + _vendorGroupMap[vendor] = targetId; + } + + if ( targetId == _vendorGroupId + 1 ) + ++_vendorGroupId; + + // invalidate any match cache + vendorMatchIdReset(); + } + + /** \relates VendorAttr::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const VendorAttr::Impl & obj ) + { + str << "Equivalent vendors:"; + for( const auto & p : obj._vendorGroupMap ) { + str << endl << " [" << p.second << "] " << p.first; + } + return str; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : VendorAttr + // + /////////////////////////////////////////////////////////////////// + + const VendorAttr & VendorAttr::instance() + { + Target_Ptr trg { getZYpp()->getTarget() }; + return trg ? trg->vendorAttr() : noTargetInstance(); + } + + VendorAttr & VendorAttr::noTargetInstance() + { + static VendorAttr _val { ZConfig::instance().vendorPath() }; + return _val; + } + + VendorAttr::VendorAttr() + : _pimpl( new Impl ) + { + MIL << "Initial: " << *this << endl; + } + + VendorAttr::VendorAttr( const Pathname & initial_r ) + : _pimpl( new Impl ) + { + addVendorDirectory( initial_r ); + MIL << "Initial " << initial_r << ": " << *this << endl; + } + + VendorAttr::~VendorAttr() + {} + + bool VendorAttr::addVendorDirectory( const Pathname & dirname_r ) + { + if ( PathInfo pi { dirname_r }; ! pi.isDir() ) { + MIL << "Not a directory " << pi << endl; + return false; + } + + filesystem::dirForEach( dirname_r, filesystem::matchNoDots(), + [this]( const Pathname & dir_r, const std::string & str_r )->bool + { + this->addVendorFile( dir_r/str_r ); + return true; + } + ); + return true; + } + + bool VendorAttr::addVendorFile( const Pathname & filename_r ) + { + if ( PathInfo pi { filename_r }; ! pi.isFile() ) { + MIL << "Not a file " << pi << endl; + return false; + } + + parser::IniDict dict { InputStream(filename_r) }; + for ( const auto & el : dict.entries("main") ) + { + if ( el.first == "vendors" ) + { + VendorList tmp; + strv::split( el.second, ",", strv::Trim::trim, + [&tmp]( std::string_view word ) { + if ( ! word.empty() ) + tmp.push_back( std::string(word) ); + } ); + _addVendorList( std::move(tmp) ); + break; + } + } + return true; + } + + void VendorAttr::_addVendorList( VendorList && vendorList_r ) + { _pimpl->addVendorList( std::move(vendorList_r) ); } + + unsigned VendorAttr::foreachVendorList( std::function fnc_r ) const + { return _pimpl->foreachVendorList( std::move(fnc_r) ); } + + ////////////////////////////////////////////////////////////////// + // vendor equivalence: + ////////////////////////////////////////////////////////////////// + + bool VendorAttr::equivalent( IdString lVendor, IdString rVendor ) const + { return _pimpl->equivalent( lVendor, rVendor );} + + bool VendorAttr::equivalent( const Vendor & lVendor, const Vendor & rVendor ) const + { return _pimpl->equivalent( IdString( lVendor ), IdString( rVendor ) ); } + + bool VendorAttr::equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const + { return _pimpl->equivalent( lVendor.vendor(), rVendor.vendor() ); } + + bool VendorAttr::equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const + { return _pimpl->equivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); } + + + bool VendorAttr::relaxedEquivalent( IdString lVendor, IdString rVendor ) const + { return _pimpl->relaxedEquivalent( lVendor, rVendor );} + + bool VendorAttr::relaxedEquivalent( const Vendor & lVendor, const Vendor & rVendor ) const + { return _pimpl->relaxedEquivalent( IdString( lVendor ), IdString( rVendor ) ); } + + bool VendorAttr::relaxedEquivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const + { return _pimpl->relaxedEquivalent( lVendor.vendor(), rVendor.vendor() ); } + + bool VendorAttr::relaxedEquivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const + { return _pimpl->relaxedEquivalent( lVendor.satSolvable().vendor(), rVendor.satSolvable().vendor() ); } + + ////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const VendorAttr & obj ) + { return str << *obj._pimpl; } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + diff --git a/zypp/VendorAttr.h b/zypp/VendorAttr.h new file mode 100644 index 0000000..230c48e --- /dev/null +++ b/zypp/VendorAttr.h @@ -0,0 +1,171 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/VendorAttr.h +*/ +#ifndef ZYPP_VENDORATTR_H +#define ZYPP_VENDORATTR_H + +#include +#include +#include + +#include +#include +#include +#include + +#include // LEGACY macros + +/////////////////////////////////////////////////////////////////// +namespace zypp { +////////////////////////////////////////////////////////////////// + + class PoolItem; + namespace sat + { + class Solvable; + } + +/** Definition of vendor equivalence. + * + * Packages with equivalent vendor strings may replace themselves without + * creating a solver error. + * + * Per default vendor strings starting with \c "suse" are treated as + * being equivalent. This may be tuned by providing customized + * vendor description files in \c /etc/zypp/vendors.d. + * + * \code + * [main] + * vendors = MyVendor,AlternateName + * \endcode + * + * By this vendor strings starting with "MyVendor" or "AlternateName" + * are considered to be equivalent. Packages from equivalent vendors + * may replace each other without being considered as a 'vendor change'. + * + * \note bnc#812608: Within the "opensuse*" namespace exact matches + * (case insensitive) are required. "vendors = suse,opensuse" will + * allow switching between "suse*" and "opensuse", but not e.g. + * "opensuse build service". + * + * \see \ref pg_zypp-solv-vendorchange +*/ +class ZYPP_API VendorAttr +{ + friend std::ostream & operator<<( std::ostream & str, const VendorAttr & obj ); + + public: + /** (Pseudo)Singleton, mapped to the current \ref Target::vendorAttr settings or to \ref noTargetInstance. */ + static const VendorAttr & instance(); + + /** Singleton, settings used if no \ref Target is active. + * The instance is initialized with the settings found in the system below /. + * The active Targets settings can be changed via \ref Target::vendorAttr. + */ + static VendorAttr & noTargetInstance(); + + public: + /** Ctor providing the default set. */ + VendorAttr(); + + /** Ctor reading the \a initial_r definitions from a dir or file. */ + VendorAttr( const Pathname & initial_r ); + + /** Dtor */ + ~VendorAttr(); + + VendorAttr(const VendorAttr &) = default; + VendorAttr(VendorAttr &&) noexcept = default; + VendorAttr &operator=(const VendorAttr &) = default; + VendorAttr &operator=(VendorAttr &&) noexcept = default; + + /** + * Adding new equivalent vendors described in a directory + **/ + bool addVendorDirectory( const Pathname & dirname_r ); + + /** + * Adding new equivalent vendors described in a file + **/ + bool addVendorFile( const Pathname & filename_r ); + + /** Preferred type to pass equivalent vendor strings. */ + using VendorList = std::vector; + + /** + * Adding new equivalent vendor strings container. + **/ + void addVendorList( VendorList && list_r ) + { _addVendorList( std::move(list_r) ); } + /** \overload copying the data */ + void addVendorList( const VendorList & list_r ) + { _addVendorList( VendorList(list_r) ); } + /** \overload from arbitrary string container */ + template + void addVendorList( const TContainer & container_r ) + { + VendorList tmp; + for ( const auto & el : container_r ) + tmp.push_back( std::string(el) ); + _addVendorList( std::move(tmp) ); + } + /** \overload from std::initializer_list */ + template + void addVendorList( const std::initializer_list & container_r ) + { + VendorList tmp; + for ( const auto & el : container_r ) + tmp.push_back( std::string(el) ); + _addVendorList( std::move(tmp) ); + } + + /** Return whether two vendor strings should be treated as the same vendor. + * Usually the solver is allowed to automatically select a package of an + * equivalent vendor when updating. Replacing a package with one of a + * different vendor usually must be confirmed by the user. + */ + bool equivalent( const Vendor & lVendor, const Vendor & rVendor ) const; + /** \overload using \ref IdStrings */ + bool equivalent( IdString lVendor, IdString rVendor ) const; + /** \overload using \ref sat::Solvable */ + bool equivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const; + /** \overload using \ref PoolItem */ + bool equivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const; + + /** Like \ref equivalent but always unifies suse and openSUSE vendor */ + bool relaxedEquivalent( const Vendor & lVendor, const Vendor & rVendor ) const; + /** \overload using \ref IdStrings */ + bool relaxedEquivalent( IdString lVendor, IdString rVendor ) const; + /** \overload using \ref sat::Solvable */ + bool relaxedEquivalent( sat::Solvable lVendor, sat::Solvable rVendor ) const; + /** \overload using \ref PoolItem */ + bool relaxedEquivalent( const PoolItem & lVendor, const PoolItem & rVendor ) const; + + public: + /** Call \a fnc_r for each equivalent vendor list (return \c false to break). + * \return The number of calls to \a fnc_r. + */ + unsigned foreachVendorList( std::function fnc_r ) const; + + public: + class Impl; ///< Implementation class. + RWCOW_pointer _pimpl; ///< Pointer to implementation. + + void _addVendorList( VendorList && list_r ); +}; + +/** \relates VendorAttr Stream output */ +std::ostream & operator<<( std::ostream & str, const VendorAttr & obj ) ZYPP_API; + +/////////////////////////////////////////////////////////////////// +}; // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif // ZYPP_VENDORATTR_H diff --git a/zypp/VendorSupportOptions.cc b/zypp/VendorSupportOptions.cc new file mode 100644 index 0000000..34d79fa --- /dev/null +++ b/zypp/VendorSupportOptions.cc @@ -0,0 +1,65 @@ + +#include +#include + +namespace zypp +{ + +std::string +asUserString( VendorSupportOption opt ) +{ + switch (opt) + { + case VendorSupportUnknown: + return _("unknown"); + break; + case VendorSupportUnsupported: + return _("unsupported"); + break; + case VendorSupportLevel1: + return _("Level 1"); + break; + case VendorSupportLevel2: + return _("Level 2"); + break; + case VendorSupportLevel3: + return _("Level 3"); + break; + case VendorSupportACC: + return _("Additional Customer Contract Necessary"); + case VendorSupportSuperseded: + return _("Discontinued and superseded by a different package"); + } + return _("invalid"); +} + +std::string asUserStringDescription( VendorSupportOption opt ) +{ + switch (opt) + { + case VendorSupportUnknown: + return _("The level of support is unspecified"); + break; + case VendorSupportUnsupported: + return _("The vendor does not provide support."); + break; + case VendorSupportLevel1: + return _("Problem determination, which means technical support designed to provide compatibility information, installation assistance, usage support, on-going maintenance and basic troubleshooting. Level 1 Support is not intended to correct product defect errors."); + break; + case VendorSupportLevel2: + return _("Problem isolation, which means technical support designed to duplicate customer problems, isolate problem area and provide resolution for problems not resolved by Level 1 Support."); + break; + case VendorSupportLevel3: + return _("Problem resolution, which means technical support designed to resolve complex problems by engaging engineering in resolution of product defects which have been identified by Level 2 Support."); + break; + case VendorSupportACC: + return _("An additional customer contract is necessary for getting support."); + case VendorSupportSuperseded: + return _("The package was discontinued and has been superseded by a new package with a different name."); + } + return _("Unknown support option. Description not available"); +} + +} + + diff --git a/zypp/VendorSupportOptions.h b/zypp/VendorSupportOptions.h new file mode 100644 index 0000000..f31b65c --- /dev/null +++ b/zypp/VendorSupportOptions.h @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/VendorSupportOptions.h + * +*/ +#ifndef ZYPP_VendorSupportOptions_H +#define ZYPP_VendorSupportOptions_H + +#include +#include + +namespace zypp +{ + + enum VendorSupportOption + { + /** + * The support for this package is unknown + */ + VendorSupportUnknown = 0, + /** + * The package is known to be unsupported by the vendor + */ + VendorSupportUnsupported = (1<<0), + /** + * Additional Customer Contract necessary + */ + VendorSupportACC = (1<<1), + /** + * Problem determination, which means technical support + * designed to provide compatibility information, + * installation assistance, usage support, on-going maintenance + * and basic troubleshooting. Level 1 Support is not intended to + * correct product defect errors. + * + * May have different semantics for different organizations. + */ + VendorSupportLevel1 = (1<<2), + /** + * Problem isolation, which means technical support designed + * to duplicate customer problems, isolate problem area and provide + * resolution for problems not resolved by Level 1 Support. + * + * May have different semantics for different organizations. + */ + VendorSupportLevel2 = (1<<3), + /** + * Problem resolution, which means technical support designed + * to resolve complex problems by engaging engineering in resolution + * of product defects which have been identified by Level 2 Support. + * + * May have different semantics for different organizations. + */ + VendorSupportLevel3 = (1<<4), + + /** + * The package was discontinued and has been superseded by a new package + * with a different name. The new package is the successor of the + * old package, and as such only the new package is supported + * in the future. + * + * The old package will not receive updates anymore, so it's highly + * recommended to switch to the new package as soon as possible. + * + * \Note Packages carrying this flag also return the name of a + * successor in \ref Package::supersededBy(). + */ + VendorSupportSuperseded = (1<<5), + }; + + // Make a flag set for this + ZYPP_DECLARE_FLAGS(VendorSupportOptions,VendorSupportOption); + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(VendorSupportOptions) + + /** + * converts the support option to a name intended to be printed + * to the user. + * + * Note the description is based in the way Novell defines the support + * levels, and the semantics may be different for other vendors. + */ + std::string asUserString( VendorSupportOption ) ZYPP_API; + + /** + * converts the support option to a description intended to be printed + * to the user. + * + * Note the description is based in the way Novell defines the support + * levels, and the semantics may be different for other vendors. + */ + std::string asUserStringDescription( VendorSupportOption ) ZYPP_API; + +} + +#endif diff --git a/zypp/ZConfig.cc b/zypp/ZConfig.cc new file mode 100644 index 0000000..d709997 --- /dev/null +++ b/zypp/ZConfig.cc @@ -0,0 +1,1351 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZConfig.cc + * +*/ +extern "C" +{ +#include +#include +#if __GLIBC_PREREQ (2,16) +#include // getauxval for PPC64P7 detection +#endif +#include +#include +} +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +using std::endl; +using namespace zypp::filesystem; +using namespace zypp::parser; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zconfig" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /** \addtogroup ZyppConfig Zypp Configuration Options + * + * The global \c zypp.conf configuration file is per default located in \c /etc/zypp/. + * An alternate config file can be set using the environment varaible \c ZYPP_CONF= + * (see \ref zypp-envars). + * + * \section ZyppConfig_ZyppConfSample Sample zypp.conf + * \include ../zypp.conf + */ + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // From rpm's lib/rpmrc.c +# if defined(__linux__) && defined(__x86_64__) + static inline void cpuid(uint32_t op, uint32_t op2, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) + { + asm volatile ( + "cpuid\n" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "a" (op), "c" (op2)); + } + + /* From gcc's gcc/config/i386/cpuid.h */ + /* Features (%eax == 1) */ + /* %ecx */ + #define bit_SSE3 (1 << 0) + #define bit_SSSE3 (1 << 9) + #define bit_FMA (1 << 12) + #define bit_CMPXCHG16B (1 << 13) + #define bit_SSE4_1 (1 << 19) + #define bit_SSE4_2 (1 << 20) + #define bit_MOVBE (1 << 22) + #define bit_POPCNT (1 << 23) + #define bit_OSXSAVE (1 << 27) + #define bit_AVX (1 << 28) + #define bit_F16C (1 << 29) + + /* Extended Features (%eax == 0x80000001) */ + /* %ecx */ + #define bit_LAHF_LM (1 << 0) + #define bit_LZCNT (1 << 5) + + /* Extended Features (%eax == 7) */ + /* %ebx */ + #define bit_BMI (1 << 3) + #define bit_AVX2 (1 << 5) + #define bit_BMI2 (1 << 8) + #define bit_AVX512F (1 << 16) + #define bit_AVX512DQ (1 << 17) + #define bit_AVX512CD (1 << 28) + #define bit_AVX512BW (1 << 30) + #define bit_AVX512VL (1u << 31) + + static int get_x86_64_level(void) + { + int level = 1; + + unsigned int op_1_ecx = 0, op_80000001_ecx = 0, op_7_ebx = 0, unused = 0; + cpuid(1, 0, &unused, &unused, &op_1_ecx, &unused); + cpuid(0x80000001, 0, &unused, &unused, &op_80000001_ecx, &unused); + cpuid(7, 0, &unused, &op_7_ebx, &unused, &unused); + + const unsigned int op_1_ecx_lv2 = bit_SSE3 | bit_SSSE3 | bit_CMPXCHG16B | bit_SSE4_1 | bit_SSE4_2 | bit_POPCNT; + if ((op_1_ecx & op_1_ecx_lv2) == op_1_ecx_lv2 && (op_80000001_ecx & bit_LAHF_LM)) + level = 2; + + const unsigned int op_1_ecx_lv3 = bit_FMA | bit_MOVBE | bit_OSXSAVE | bit_AVX | bit_F16C; + const unsigned int op_7_ebx_lv3 = bit_BMI | bit_AVX2 | bit_BMI2; + if (level == 2 && (op_1_ecx & op_1_ecx_lv3) == op_1_ecx_lv3 && (op_7_ebx & op_7_ebx_lv3) == op_7_ebx_lv3 + && (op_80000001_ecx & bit_LZCNT)) + level = 3; + + const unsigned int op_7_ebx_lv4 = bit_AVX512F | bit_AVX512DQ | bit_AVX512CD | bit_AVX512BW | bit_AVX512VL; + if (level == 3 && (op_7_ebx & op_7_ebx_lv4) == op_7_ebx_lv4) + level = 4; + + return level; + } +# endif + /////////////////////////////////////////////////////////////////// + + /** Determine system architecture evaluating \c uname and \c /proc/cpuinfo. + */ + Arch _autodetectSystemArchitecture() + { + struct ::utsname buf; + if ( ::uname( &buf ) < 0 ) + { + ERR << "Can't determine system architecture" << endl; + return Arch_noarch; + } + + Arch architecture( buf.machine ); + MIL << "Uname architecture is '" << buf.machine << "'" << endl; + + if ( architecture == Arch_x86_64 ) + { +#if defined(__linux__) && defined(__x86_64__) + switch ( get_x86_64_level() ) + { + case 2: + architecture = Arch_x86_64_v2; + WAR << "CPU has 'x86_64': architecture upgraded to '" << architecture << "'" << endl; + break; + case 3: + architecture = Arch_x86_64_v3; + WAR << "CPU has 'x86_64': architecture upgraded to '" << architecture << "'" << endl; + break; + case 4: + architecture = Arch_x86_64_v4; + WAR << "CPU has 'x86_64': architecture upgraded to '" << architecture << "'" << endl; + break; + } +# endif + } + else if ( architecture == Arch_i686 ) + { + // some CPUs report i686 but dont implement cx8 and cmov + // check for both flags in /proc/cpuinfo and downgrade + // to i586 if either is missing (cf bug #18885) + std::ifstream cpuinfo( "/proc/cpuinfo" ); + if ( cpuinfo ) + { + for( iostr::EachLine in( cpuinfo ); in; in.next() ) + { + if ( str::hasPrefix( *in, "flags" ) ) + { + if ( in->find( "cx8" ) == std::string::npos + || in->find( "cmov" ) == std::string::npos ) + { + architecture = Arch_i586; + WAR << "CPU lacks 'cx8' or 'cmov': architecture downgraded to '" << architecture << "'" << endl; + } + break; + } + } + } + else + { + ERR << "Cant open " << PathInfo("/proc/cpuinfo") << endl; + } + } + else if ( architecture == Arch_sparc || architecture == Arch_sparc64 ) + { + // Check for sun4[vum] to get the real arch. (bug #566291) + std::ifstream cpuinfo( "/proc/cpuinfo" ); + if ( cpuinfo ) + { + for( iostr::EachLine in( cpuinfo ); in; in.next() ) + { + if ( str::hasPrefix( *in, "type" ) ) + { + if ( in->find( "sun4v" ) != std::string::npos ) + { + architecture = ( architecture == Arch_sparc64 ? Arch_sparc64v : Arch_sparcv9v ); + WAR << "CPU has 'sun4v': architecture upgraded to '" << architecture << "'" << endl; + } + else if ( in->find( "sun4u" ) != std::string::npos ) + { + architecture = ( architecture == Arch_sparc64 ? Arch_sparc64 : Arch_sparcv9 ); + WAR << "CPU has 'sun4u': architecture upgraded to '" << architecture << "'" << endl; + } + else if ( in->find( "sun4m" ) != std::string::npos ) + { + architecture = Arch_sparcv8; + WAR << "CPU has 'sun4m': architecture upgraded to '" << architecture << "'" << endl; + } + break; + } + } + } + else + { + ERR << "Cant open " << PathInfo("/proc/cpuinfo") << endl; + } + } + else if ( architecture == Arch_armv8l || architecture == Arch_armv7l || architecture == Arch_armv6l ) + { + std::ifstream platform( "/etc/rpm/platform" ); + if (platform) + { + for( iostr::EachLine in( platform ); in; in.next() ) + { + if ( str::hasPrefix( *in, "armv8hl-" ) ) + { + architecture = Arch_armv8hl; + WAR << "/etc/rpm/platform contains armv8hl-: architecture upgraded to '" << architecture << "'" << endl; + break; + } + if ( str::hasPrefix( *in, "armv7hl-" ) ) + { + architecture = Arch_armv7hl; + WAR << "/etc/rpm/platform contains armv7hl-: architecture upgraded to '" << architecture << "'" << endl; + break; + } + if ( str::hasPrefix( *in, "armv6hl-" ) ) + { + architecture = Arch_armv6hl; + WAR << "/etc/rpm/platform contains armv6hl-: architecture upgraded to '" << architecture << "'" << endl; + break; + } + } + } + } +#if __GLIBC_PREREQ (2,16) + else if ( architecture == Arch_ppc64 ) + { + const char * platform = (const char *)getauxval( AT_PLATFORM ); + int powerlvl = 0; + if ( platform && sscanf( platform, "power%d", &powerlvl ) == 1 && powerlvl > 6 ) + architecture = Arch_ppc64p7; + } +#endif + return architecture; + } + + /** The locale to be used for texts and messages. + * + * For the encoding to be used the preference is + * + * LC_ALL, LC_CTYPE, LANG + * + * For the language of the messages to be used, the preference is + * + * LANGUAGE, LC_ALL, LC_MESSAGES, LANG + * + * Note that LANGUAGE can contain more than one locale name, it can be + * a list of locale names like for example + * + * LANGUAGE=ja_JP.UTF-8:de_DE.UTF-8:fr_FR.UTF-8 + + * \todo Support dynamic fallbacklists defined by LANGUAGE + */ + Locale _autodetectTextLocale() + { + Locale ret( Locale::enCode ); + const char * envlist[] = { "LC_ALL", "LC_MESSAGES", "LANG", NULL }; + for ( const char ** envvar = envlist; *envvar; ++envvar ) + { + const char * envlang = getenv( *envvar ); + if ( envlang ) + { + std::string envstr( envlang ); + if ( envstr != "POSIX" && envstr != "C" ) + { + Locale lang( envstr ); + if ( lang ) + { + MIL << "Found " << *envvar << "=" << envstr << endl; + ret = lang; + break; + } + } + } + } + MIL << "Default text locale is '" << ret << "'" << endl; +#warning HACK AROUND BOOST_TEST_CATCH_SYSTEM_ERRORS + setenv( "BOOST_TEST_CATCH_SYSTEM_ERRORS", "no", 1 ); + return ret; + } + + + inline Pathname _autodetectSystemRoot() + { + Target_Ptr target( getZYpp()->getTarget() ); + return target ? target->root() : Pathname(); + } + + inline Pathname _autodetectZyppConfPath() + { + const char *env_confpath = getenv( "ZYPP_CONF" ); + return env_confpath ? env_confpath : "/etc/zypp/zypp.conf"; + } + + ///////////////////////////////////////////////////////////////// + } // namespace zypp + /////////////////////////////////////////////////////////////////// + + /** Mutable option. */ + template + struct Option + { + using value_type = Tp; + + /** No default ctor, explicit initialisation! */ + Option( value_type initial_r ) + : _val( std::move(initial_r) ) + {} + + Option & operator=( value_type newval_r ) + { set( std::move(newval_r) ); return *this; } + + /** Get the value. */ + const value_type & get() const + { return _val; } + + /** Autoconversion to value_type. */ + operator const value_type &() const + { return _val; } + + /** Set a new value. */ + void set( value_type newval_r ) + { _val = std::move(newval_r); } + + private: + value_type _val; + }; + + /** Mutable option with initial value also remembering a config value. */ + template + struct DefaultOption : public Option + { + using value_type = Tp; + using option_type = Option; + + explicit DefaultOption( value_type initial_r ) + : Option( initial_r ) + , _default( std::move(initial_r) ) + {} + + DefaultOption & operator=( value_type newval_r ) + { this->set( std::move(newval_r) ); return *this; } + + /** Reset value to the current default. */ + void restoreToDefault() + { this->set( _default.get() ); } + + /** Reset value to a new default. */ + void restoreToDefault( value_type newval_r ) + { setDefault( std::move(newval_r) ); restoreToDefault(); } + + /** Get the current default value. */ + const value_type & getDefault() const + { return _default.get(); } + + /** Set a new default value. */ + void setDefault( value_type newval_r ) + { _default.set( std::move(newval_r) ); } + + private: + option_type _default; + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZConfig::Impl + // + /** ZConfig implementation. + * \todo Enrich section and entry definition by some comment + * (including the default setting and provide some method to + * write this into a sample zypp.conf. + */ + class ZConfig::Impl + { + using MultiversionSpec = std::set; + + /// Settings that follow a changed Target + struct TargetDefaults + { + TargetDefaults() + : solver_focus ( ResolverFocus::Default ) + , solver_onlyRequires ( false ) + , solver_allowVendorChange ( false ) + , solver_dupAllowDowngrade ( true ) + , solver_dupAllowNameChange ( true ) + , solver_dupAllowArchChange ( true ) + , solver_dupAllowVendorChange ( true ) + , solver_cleandepsOnRemove ( false ) + , solver_upgradeTestcasesToKeep ( 2 ) + , solverUpgradeRemoveDroppedPackages ( true ) + {} + + bool consume( const std::string & entry, const std::string & value ) + { + if ( entry == "solver.focus" ) + { + fromString( value, solver_focus ); + } + else if ( entry == "solver.onlyRequires" ) + { + solver_onlyRequires.set( str::strToBool( value, solver_onlyRequires ) ); + } + else if ( entry == "solver.allowVendorChange" ) + { + solver_allowVendorChange.set( str::strToBool( value, solver_allowVendorChange ) ); + } + else if ( entry == "solver.dupAllowDowngrade" ) + { + solver_dupAllowDowngrade.set( str::strToBool( value, solver_dupAllowDowngrade ) ); + } + else if ( entry == "solver.dupAllowNameChange" ) + { + solver_dupAllowNameChange.set( str::strToBool( value, solver_dupAllowNameChange ) ); + } + else if ( entry == "solver.dupAllowArchChange" ) + { + solver_dupAllowArchChange.set( str::strToBool( value, solver_dupAllowArchChange ) ); + } + else if ( entry == "solver.dupAllowVendorChange" ) + { + solver_dupAllowVendorChange.set( str::strToBool( value, solver_dupAllowVendorChange ) ); + } + else if ( entry == "solver.cleandepsOnRemove" ) + { + solver_cleandepsOnRemove.set( str::strToBool( value, solver_cleandepsOnRemove ) ); + } + else if ( entry == "solver.upgradeTestcasesToKeep" ) + { + solver_upgradeTestcasesToKeep.set( str::strtonum( value ) ); + } + else if ( entry == "solver.upgradeRemoveDroppedPackages" ) + { + solverUpgradeRemoveDroppedPackages.restoreToDefault( str::strToBool( value, solverUpgradeRemoveDroppedPackages.getDefault() ) ); + } + else + return false; + + return true; + } + + ResolverFocus solver_focus; + Option solver_onlyRequires; + Option solver_allowVendorChange; + Option solver_dupAllowDowngrade; + Option solver_dupAllowNameChange; + Option solver_dupAllowArchChange; + Option solver_dupAllowVendorChange; + Option solver_cleandepsOnRemove; + Option solver_upgradeTestcasesToKeep; + DefaultOption solverUpgradeRemoveDroppedPackages; + }; + + public: + Impl() + : _parsedZyppConf ( _autodetectZyppConfPath() ) + , cfg_arch ( defaultSystemArchitecture() ) + , cfg_textLocale ( defaultTextLocale() ) + , cfg_cache_path { "/var/cache/zypp" } + , cfg_metadata_path { "" } // empty - follows cfg_cache_path + , cfg_solvfiles_path { "" } // empty - follows cfg_cache_path + , cfg_packages_path { "" } // empty - follows cfg_cache_path + , updateMessagesNotify ( "" ) + , repo_add_probe ( false ) + , repo_refresh_delay ( 10 ) + , repoLabelIsAlias ( false ) + , download_use_deltarpm ( true ) + , download_use_deltarpm_always ( false ) + , download_media_prefer_download( true ) + , download_mediaMountdir ( "/var/adm/mount" ) + , commit_downloadMode ( DownloadDefault ) + , gpgCheck ( true ) + , repoGpgCheck ( indeterminate ) + , pkgGpgCheck ( indeterminate ) + , apply_locks_file ( true ) + , pluginsPath ( "/usr/lib/zypp/plugins" ) + , geoipEnabled ( true ) + , geoipHosts { "download.opensuse.org" } + { + MIL << "libzypp: " LIBZYPP_VERSION_STRING << endl; + if ( PathInfo(_parsedZyppConf).isExist() ) + { + parser::IniDict dict( _parsedZyppConf ); + for ( IniDict::section_const_iterator sit = dict.sectionsBegin(); + sit != dict.sectionsEnd(); + ++sit ) + { + const std::string& section(*sit); + //MIL << section << endl; + for ( IniDict::entry_const_iterator it = dict.entriesBegin(*sit); + it != dict.entriesEnd(*sit); + ++it ) + { + std::string entry(it->first); + std::string value(it->second); + + if ( _mediaConf.setConfigValue( section, entry, value ) ) + continue; + + //DBG << (*it).first << "=" << (*it).second << endl; + if ( section == "main" ) + { + if ( _initialTargetDefaults.consume( entry, value ) ) + continue; + + if ( entry == "arch" ) + { + Arch carch( value ); + if ( carch != cfg_arch ) + { + WAR << "Overriding system architecture (" << cfg_arch << "): " << carch << endl; + cfg_arch = carch; + } + } + else if ( entry == "cachedir" ) + { + cfg_cache_path.restoreToDefault( value ); + } + else if ( entry == "metadatadir" ) + { + cfg_metadata_path.restoreToDefault( value ); + } + else if ( entry == "solvfilesdir" ) + { + cfg_solvfiles_path.restoreToDefault( value ); + } + else if ( entry == "packagesdir" ) + { + cfg_packages_path.restoreToDefault( value ); + } + else if ( entry == "configdir" ) + { + cfg_config_path = Pathname(value); + } + else if ( entry == "reposdir" ) + { + cfg_known_repos_path = Pathname(value); + } + else if ( entry == "servicesdir" ) + { + cfg_known_services_path = Pathname(value); + } + else if ( entry == "varsdir" ) + { + cfg_vars_path = Pathname(value); + } + else if ( entry == "repo.add.probe" ) + { + repo_add_probe = str::strToBool( value, repo_add_probe ); + } + else if ( entry == "repo.refresh.delay" ) + { + str::strtonum(value, repo_refresh_delay); + } + else if ( entry == "repo.refresh.locales" ) + { + std::vector tmp; + str::split( value, back_inserter( tmp ), ", \t" ); + + boost::function transform( + [](const std::string & str_r)->Locale{ return Locale(str_r); } + ); + repoRefreshLocales.insert( make_transform_iterator( tmp.begin(), transform ), + make_transform_iterator( tmp.end(), transform ) ); + } + else if ( entry == "download.use_deltarpm" ) + { + download_use_deltarpm = str::strToBool( value, download_use_deltarpm ); + } + else if ( entry == "download.use_deltarpm.always" ) + { + download_use_deltarpm_always = str::strToBool( value, download_use_deltarpm_always ); + } + else if ( entry == "download.media_preference" ) + { + download_media_prefer_download.restoreToDefault( str::compareCI( value, "volatile" ) != 0 ); + } + else if ( entry == "download.media_mountdir" ) + { + download_mediaMountdir.restoreToDefault( Pathname(value) ); + } + else if ( entry == "download.use_geoip_mirror") { + geoipEnabled = str::strToBool( value, geoipEnabled ); + } + else if ( entry == "commit.downloadMode" ) + { + commit_downloadMode.set( deserializeDownloadMode( value ) ); + } + else if ( entry == "gpgcheck" ) + { + gpgCheck.restoreToDefault( str::strToBool( value, gpgCheck ) ); + } + else if ( entry == "repo_gpgcheck" ) + { + repoGpgCheck.restoreToDefault( str::strToTriBool( value ) ); + } + else if ( entry == "pkg_gpgcheck" ) + { + pkgGpgCheck.restoreToDefault( str::strToTriBool( value ) ); + } + else if ( entry == "vendordir" ) + { + cfg_vendor_path = Pathname(value); + } + else if ( entry == "multiversiondir" ) + { + cfg_multiversion_path = Pathname(value); + } + else if ( entry == "multiversion.kernels" ) + { + cfg_kernel_keep_spec = value; + } + else if ( entry == "solver.checkSystemFile" ) + { + solver_checkSystemFile = Pathname(value); + } + else if ( entry == "solver.checkSystemFileDir" ) + { + solver_checkSystemFileDir = Pathname(value); + } + else if ( entry == "multiversion" ) + { + MultiversionSpec & defSpec( _multiversionMap.getDefaultSpec() ); + str::splitEscaped( value, std::inserter( defSpec, defSpec.end() ), ", \t" ); + } + else if ( entry == "locksfile.path" ) + { + locks_file = Pathname(value); + } + else if ( entry == "locksfile.apply" ) + { + apply_locks_file = str::strToBool( value, apply_locks_file ); + } + else if ( entry == "update.datadir" ) + { + update_data_path = Pathname(value); + } + else if ( entry == "update.scriptsdir" ) + { + update_scripts_path = Pathname(value); + } + else if ( entry == "update.messagessdir" ) + { + update_messages_path = Pathname(value); + } + else if ( entry == "update.messages.notify" ) + { + updateMessagesNotify.set( value ); + } + else if ( entry == "rpm.install.excludedocs" ) + { + rpmInstallFlags.setFlag( target::rpm::RPMINST_EXCLUDEDOCS, + str::strToBool( value, false ) ); + } + else if ( entry == "history.logfile" ) + { + history_log_path = Pathname(value); + } + else if ( entry == "techpreview.ZYPP_SINGLE_RPMTRANS" ) + { + DBG << "techpreview.ZYPP_SINGLE_RPMTRANS=" << value << endl; + ::setenv( "ZYPP_SINGLE_RPMTRANS", value.c_str(), 1 ); + } + else if ( entry == "techpreview.ZYPP_MEDIANETWORK" ) + { + DBG << "techpreview.ZYPP_MEDIANETWORK=" << value << endl; + ::setenv( "ZYPP_MEDIANETWORK", value.c_str(), 1 ); + } + } + } + } + } + else + { + MIL << _parsedZyppConf << " not found, using defaults instead." << endl; + _parsedZyppConf = _parsedZyppConf.extend( " (NOT FOUND)" ); + } + + // legacy: + if ( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) ) + { + Arch carch( getenv( "ZYPP_TESTSUITE_FAKE_ARCH" ) ); + if ( carch != cfg_arch ) + { + WAR << "ZYPP_TESTSUITE_FAKE_ARCH: Overriding system architecture (" << cfg_arch << "): " << carch << endl; + cfg_arch = carch; + } + } + MIL << "ZConfig singleton created." << endl; + } + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + ~Impl() {} + + void notifyTargetChanged() + { + Pathname newRoot { _autodetectSystemRoot() }; + MIL << "notifyTargetChanged (" << newRoot << ")" << endl; + + if ( newRoot.emptyOrRoot() ) { + _currentTargetDefaults.reset(); // to initial settigns from / + } + else { + _currentTargetDefaults = TargetDefaults(); + + Pathname newConf { newRoot/_autodetectZyppConfPath() }; + if ( PathInfo(newConf).isExist() ) { + parser::IniDict dict( newConf ); + for ( const auto & [entry,value] : dict.entries( "main" ) ) { + (*_currentTargetDefaults).consume( entry, value ); + } + } + else { + MIL << _parsedZyppConf << " not found, using defaults." << endl; + } + } + } + + public: + /** Remember any parsed zypp.conf. */ + Pathname _parsedZyppConf; + + Arch cfg_arch; + Locale cfg_textLocale; + + DefaultOption cfg_cache_path; // Settings from the config file are also remembered + DefaultOption cfg_metadata_path; // 'default'. Cleanup in RepoManager e.g needs to tell + DefaultOption cfg_solvfiles_path; // whether settings in effect are config values or + DefaultOption cfg_packages_path; // custom settings applied vie set...Path(). + + Pathname cfg_config_path; + Pathname cfg_known_repos_path; + Pathname cfg_known_services_path; + Pathname cfg_vars_path; + Pathname cfg_repo_mgr_root_path; + + Pathname cfg_vendor_path; + Pathname cfg_multiversion_path; + std::string cfg_kernel_keep_spec; + Pathname locks_file; + + Pathname update_data_path; + Pathname update_scripts_path; + Pathname update_messages_path; + DefaultOption updateMessagesNotify; + + bool repo_add_probe; + unsigned repo_refresh_delay; + LocaleSet repoRefreshLocales; + bool repoLabelIsAlias; + + bool download_use_deltarpm; + bool download_use_deltarpm_always; + DefaultOption download_media_prefer_download; + DefaultOption download_mediaMountdir; + + Option commit_downloadMode; + + DefaultOption gpgCheck; + DefaultOption repoGpgCheck; + DefaultOption pkgGpgCheck; + + Pathname solver_checkSystemFile; + Pathname solver_checkSystemFileDir; + + MultiversionSpec & multiversion() { return getMultiversion(); } + const MultiversionSpec & multiversion() const { return getMultiversion(); } + + bool apply_locks_file; + + target::rpm::RpmInstFlags rpmInstallFlags; + + Pathname history_log_path; + + std::string userData; + + Option pluginsPath; + + bool geoipEnabled; + + std::vector geoipHosts; + + /* Other config singleton instances */ + MediaConfig &_mediaConf = MediaConfig::instance(); + + + public: + const TargetDefaults & targetDefaults() const { return _currentTargetDefaults ? *_currentTargetDefaults : _initialTargetDefaults; } + TargetDefaults & targetDefaults() { return _currentTargetDefaults ? *_currentTargetDefaults : _initialTargetDefaults; } + private: + TargetDefaults _initialTargetDefaults; ///< Initial TargetDefaults from / + std::optional _currentTargetDefaults; ///< TargetDefaults while --root + + private: + // HACK for bnc#906096: let pool re-evaluate multiversion spec + // if target root changes. ZConfig returns data sensitive to + // current target root. + // TODO Actually we'd need to scan the target systems zypp.conf and + // overlay all system specific values. + struct MultiversionMap + { + using SpecMap = std::map; + + MultiversionSpec & getSpec( Pathname root_r, const Impl & zConfImpl_r ) // from system at root + { + // _specMap[] - the plain zypp.conf value + // _specMap[/] - combine [] and multiversion.d scan + // _specMap[root] - scan root/zypp.conf and root/multiversion.d + + if ( root_r.empty() ) + root_r = "/"; + bool cacheHit = _specMap.count( root_r ); + MultiversionSpec & ret( _specMap[root_r] ); // creates new entry on the fly + + if ( ! cacheHit ) + { + // bsc#1193488: If no (/root)/.../zypp.conf exists use the default zypp.conf + // multiversion settings. It is a legacy that the packaged multiversion setting + // in zypp.conf (the kernel) may differ from the builtin default (empty). + // But we want a missing config to behave similar to the default one, otherwise + // a bare metal install easily runs into trouble. + if ( root_r == "/" || scanConfAt( root_r, ret, zConfImpl_r ) == 0 ) + ret = _specMap[Pathname()]; + scanDirAt( root_r, ret, zConfImpl_r ); // add multiversion.d at root_r + using zypp::operator<<; + MIL << "MultiversionSpec '" << root_r << "' = " << ret << endl; + } + return ret; + } + + MultiversionSpec & getDefaultSpec() // Spec from zypp.conf parsing; called before any getSpec + { return _specMap[Pathname()]; } + + private: + int scanConfAt( const Pathname& root_r, MultiversionSpec & spec_r, const Impl & zConfImpl_r ) + { + static const str::regex rx( "^multiversion *= *(.*)" ); + str::smatch what; + return iostr::simpleParseFile( InputStream( Pathname::assertprefix( root_r, _autodetectZyppConfPath() ) ), + [&]( int num_r, std::string line_r )->bool + { + if ( line_r[0] == 'm' && str::regex_match( line_r, what, rx ) ) + { + str::splitEscaped( what[1], std::inserter( spec_r, spec_r.end() ), ", \t" ); + return false; // stop after match + } + return true; + } ); + } + + void scanDirAt( const Pathname& root_r, MultiversionSpec & spec_r, const Impl & zConfImpl_r ) + { + // NOTE: Actually we'd need to scan and use the root_r! zypp.conf values. + Pathname multiversionDir( zConfImpl_r.cfg_multiversion_path ); + if ( multiversionDir.empty() ) + multiversionDir = ( zConfImpl_r.cfg_config_path.empty() + ? Pathname("/etc/zypp") + : zConfImpl_r.cfg_config_path ) / "multiversion.d"; + + filesystem::dirForEach( Pathname::assertprefix( root_r, multiversionDir ), + [&spec_r]( const Pathname & dir_r, const char *const & name_r )->bool + { + MIL << "Parsing " << dir_r/name_r << endl; + iostr::simpleParseFile( InputStream( dir_r/name_r ), + [&spec_r]( int num_r, std::string line_r )->bool + { + DBG << " found " << line_r << endl; + spec_r.insert( std::move(line_r) ); + return true; + } ); + return true; + } ); + } + + private: + SpecMap _specMap; + }; + + MultiversionSpec & getMultiversion() const + { return _multiversionMap.getSpec( _autodetectSystemRoot(), *this ); } + + mutable MultiversionMap _multiversionMap; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ZConfig::instance + // METHOD TYPE : ZConfig & + // + ZConfig & ZConfig::instance() + { + static ZConfig _instance; // The singleton + return _instance; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ZConfig::ZConfig + // METHOD TYPE : Ctor + // + ZConfig::ZConfig() + : _pimpl( new Impl ) + { + about( MIL ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ZConfig::~ZConfig + // METHOD TYPE : Dtor + // + ZConfig::~ZConfig( ) + {} + + void ZConfig::notifyTargetChanged() + { return _pimpl->notifyTargetChanged(); } + + Pathname ZConfig::systemRoot() const + { return _autodetectSystemRoot(); } + + Pathname ZConfig::repoManagerRoot() const + { + return ( _pimpl->cfg_repo_mgr_root_path.empty() + ? systemRoot() : _pimpl->cfg_repo_mgr_root_path ); + } + + void ZConfig::setRepoManagerRoot(const zypp::filesystem::Pathname &root) + { _pimpl->cfg_repo_mgr_root_path = root; } + + /////////////////////////////////////////////////////////////////// + // + // system architecture + // + /////////////////////////////////////////////////////////////////// + + Arch ZConfig::defaultSystemArchitecture() + { + static Arch _val( _autodetectSystemArchitecture() ); + return _val; + } + + Arch ZConfig::systemArchitecture() const + { return _pimpl->cfg_arch; } + + void ZConfig::setSystemArchitecture( const Arch & arch_r ) + { + if ( arch_r != _pimpl->cfg_arch ) + { + WAR << "Overriding system architecture (" << _pimpl->cfg_arch << "): " << arch_r << endl; + _pimpl->cfg_arch = arch_r; + } + } + + /////////////////////////////////////////////////////////////////// + // + // text locale + // + /////////////////////////////////////////////////////////////////// + + Locale ZConfig::defaultTextLocale() + { + static Locale _val( _autodetectTextLocale() ); + return _val; + } + + Locale ZConfig::textLocale() const + { return _pimpl->cfg_textLocale; } + + void ZConfig::setTextLocale( const Locale & locale_r ) + { + if ( locale_r != _pimpl->cfg_textLocale ) + { + WAR << "Overriding text locale (" << _pimpl->cfg_textLocale << "): " << locale_r << endl; + _pimpl->cfg_textLocale = locale_r; + // Propagate changes + sat::Pool::instance().setTextLocale( locale_r ); + } + } + + /////////////////////////////////////////////////////////////////// + // user data + /////////////////////////////////////////////////////////////////// + + bool ZConfig::hasUserData() const + { return !_pimpl->userData.empty(); } + + std::string ZConfig::userData() const + { return _pimpl->userData; } + + bool ZConfig::setUserData( const std::string & str_r ) + { + for_( ch, str_r.begin(), str_r.end() ) + { + if ( *ch < ' ' && *ch != '\t' ) + { + ERR << "New user data string rejectded: char " << (int)*ch << " at position " << (ch - str_r.begin()) << endl; + return false; + } + } + MIL << "Set user data string to '" << str_r << "'" << endl; + _pimpl->userData = str_r; + return true; + } + + /////////////////////////////////////////////////////////////////// + + Pathname ZConfig::repoCachePath() const + { + return ( _pimpl->cfg_cache_path.get().empty() + ? Pathname("/var/cache/zypp") : _pimpl->cfg_cache_path.get() ); + } + + Pathname ZConfig::pubkeyCachePath() const + { + return repoCachePath()/"pubkeys"; + } + + void ZConfig::setRepoCachePath(const zypp::filesystem::Pathname &path_r) + { + _pimpl->cfg_cache_path = path_r; + } + + Pathname ZConfig::repoMetadataPath() const + { + return ( _pimpl->cfg_metadata_path.get().empty() + ? (repoCachePath()/"raw") : _pimpl->cfg_metadata_path.get() ); + } + + void ZConfig::setRepoMetadataPath(const zypp::filesystem::Pathname &path_r) + { + _pimpl->cfg_metadata_path = path_r; + } + + Pathname ZConfig::repoSolvfilesPath() const + { + return ( _pimpl->cfg_solvfiles_path.get().empty() + ? (repoCachePath()/"solv") : _pimpl->cfg_solvfiles_path.get() ); + } + + void ZConfig::setRepoSolvfilesPath(const zypp::filesystem::Pathname &path_r) + { + _pimpl->cfg_solvfiles_path = path_r; + } + + Pathname ZConfig::repoPackagesPath() const + { + return ( _pimpl->cfg_packages_path.get().empty() + ? (repoCachePath()/"packages") : _pimpl->cfg_packages_path.get() ); + } + + void ZConfig::setRepoPackagesPath(const zypp::filesystem::Pathname &path_r) + { + _pimpl->cfg_packages_path = path_r; + } + + Pathname ZConfig::builtinRepoCachePath() const + { return _pimpl->cfg_cache_path.getDefault().empty() ? Pathname("/var/cache/zypp") : _pimpl->cfg_cache_path.getDefault(); } + + Pathname ZConfig::builtinRepoMetadataPath() const + { return _pimpl->cfg_metadata_path.getDefault().empty() ? (builtinRepoCachePath()/"raw") : _pimpl->cfg_metadata_path.getDefault(); } + + Pathname ZConfig::builtinRepoSolvfilesPath() const + { return _pimpl->cfg_solvfiles_path.getDefault().empty() ? (builtinRepoCachePath()/"solv") : _pimpl->cfg_solvfiles_path.getDefault(); } + + Pathname ZConfig::builtinRepoPackagesPath() const + { return _pimpl->cfg_packages_path.getDefault().empty() ? (builtinRepoCachePath()/"packages") : _pimpl->cfg_packages_path.getDefault(); } + + /////////////////////////////////////////////////////////////////// + + Pathname ZConfig::configPath() const + { + return ( _pimpl->cfg_config_path.empty() + ? Pathname("/etc/zypp") : _pimpl->cfg_config_path ); + } + + Pathname ZConfig::knownReposPath() const + { + return ( _pimpl->cfg_known_repos_path.empty() + ? (configPath()/"repos.d") : _pimpl->cfg_known_repos_path ); + } + + Pathname ZConfig::knownServicesPath() const + { + return ( _pimpl->cfg_known_services_path.empty() + ? (configPath()/"services.d") : _pimpl->cfg_known_services_path ); + } + + Pathname ZConfig::needrebootFile() const + { return configPath()/"needreboot"; } + + Pathname ZConfig::needrebootPath() const + { return configPath()/"needreboot.d"; } + + void ZConfig::setGeoipEnabled( bool enable ) + { _pimpl->geoipEnabled = enable; } + + bool ZConfig::geoipEnabled () const + { return _pimpl->geoipEnabled; } + + Pathname ZConfig::geoipCachePath() const + { return builtinRepoCachePath()/"geoip.d"; } + + const std::vector ZConfig::geoipHostnames () const + { return _pimpl->geoipHosts; } + + Pathname ZConfig::varsPath() const + { + return ( _pimpl->cfg_vars_path.empty() + ? (configPath()/"vars.d") : _pimpl->cfg_vars_path ); + } + + Pathname ZConfig::vendorPath() const + { + return ( _pimpl->cfg_vendor_path.empty() + ? (configPath()/"vendors.d") : _pimpl->cfg_vendor_path ); + } + + Pathname ZConfig::locksFile() const + { + return ( _pimpl->locks_file.empty() + ? (configPath()/"locks") : _pimpl->locks_file ); + } + + /////////////////////////////////////////////////////////////////// + + bool ZConfig::repo_add_probe() const + { return _pimpl->repo_add_probe; } + + unsigned ZConfig::repo_refresh_delay() const + { return _pimpl->repo_refresh_delay; } + + LocaleSet ZConfig::repoRefreshLocales() const + { return _pimpl->repoRefreshLocales.empty() ? Target::requestedLocales("") :_pimpl->repoRefreshLocales; } + + bool ZConfig::repoLabelIsAlias() const + { return _pimpl->repoLabelIsAlias; } + + void ZConfig::repoLabelIsAlias( bool yesno_r ) + { _pimpl->repoLabelIsAlias = yesno_r; } + + bool ZConfig::download_use_deltarpm() const + { return _pimpl->download_use_deltarpm; } + + bool ZConfig::download_use_deltarpm_always() const + { return download_use_deltarpm() && _pimpl->download_use_deltarpm_always; } + + bool ZConfig::download_media_prefer_download() const + { return _pimpl->download_media_prefer_download; } + + void ZConfig::set_download_media_prefer_download( bool yesno_r ) + { _pimpl->download_media_prefer_download.set( yesno_r ); } + + void ZConfig::set_default_download_media_prefer_download() + { _pimpl->download_media_prefer_download.restoreToDefault(); } + + long ZConfig::download_max_concurrent_connections() const + { return _pimpl->_mediaConf.download_max_concurrent_connections(); } + + long ZConfig::download_min_download_speed() const + { return _pimpl->_mediaConf.download_min_download_speed(); } + + long ZConfig::download_max_download_speed() const + { return _pimpl->_mediaConf.download_max_download_speed(); } + + long ZConfig::download_max_silent_tries() const + { return _pimpl->_mediaConf.download_max_silent_tries(); } + + long ZConfig::download_transfer_timeout() const + { return _pimpl->_mediaConf.download_transfer_timeout(); } + + Pathname ZConfig::download_mediaMountdir() const { return _pimpl->download_mediaMountdir; } + void ZConfig::set_download_mediaMountdir( Pathname newval_r ) { _pimpl->download_mediaMountdir.set( std::move(newval_r) ); } + void ZConfig::set_default_download_mediaMountdir() { _pimpl->download_mediaMountdir.restoreToDefault(); } + + DownloadMode ZConfig::commit_downloadMode() const + { return _pimpl->commit_downloadMode; } + + + bool ZConfig::gpgCheck() const { return _pimpl->gpgCheck; } + TriBool ZConfig::repoGpgCheck() const { return _pimpl->repoGpgCheck; } + TriBool ZConfig::pkgGpgCheck() const { return _pimpl->pkgGpgCheck; } + + void ZConfig::setGpgCheck( bool val_r ) { _pimpl->gpgCheck.set( val_r ); } + void ZConfig::setRepoGpgCheck( TriBool val_r ) { _pimpl->repoGpgCheck.set( val_r ); } + void ZConfig::setPkgGpgCheck( TriBool val_r ) { _pimpl->pkgGpgCheck.set( val_r ); } + + void ZConfig::resetGpgCheck() { _pimpl->gpgCheck.restoreToDefault(); } + void ZConfig::resetRepoGpgCheck() { _pimpl->repoGpgCheck.restoreToDefault(); } + void ZConfig::resetPkgGpgCheck() { _pimpl->pkgGpgCheck.restoreToDefault(); } + + + ResolverFocus ZConfig::solver_focus() const { return _pimpl->targetDefaults().solver_focus; } + bool ZConfig::solver_onlyRequires() const { return _pimpl->targetDefaults().solver_onlyRequires; } + bool ZConfig::solver_allowVendorChange() const { return _pimpl->targetDefaults().solver_allowVendorChange; } + bool ZConfig::solver_dupAllowDowngrade() const { return _pimpl->targetDefaults().solver_dupAllowDowngrade; } + bool ZConfig::solver_dupAllowNameChange() const { return _pimpl->targetDefaults().solver_dupAllowNameChange; } + bool ZConfig::solver_dupAllowArchChange() const { return _pimpl->targetDefaults().solver_dupAllowArchChange; } + bool ZConfig::solver_dupAllowVendorChange() const { return _pimpl->targetDefaults().solver_dupAllowVendorChange; } + bool ZConfig::solver_cleandepsOnRemove() const { return _pimpl->targetDefaults().solver_cleandepsOnRemove; } + unsigned ZConfig::solver_upgradeTestcasesToKeep() const { return _pimpl->targetDefaults().solver_upgradeTestcasesToKeep; } + + bool ZConfig::solverUpgradeRemoveDroppedPackages() const { return _pimpl->targetDefaults().solverUpgradeRemoveDroppedPackages; } + void ZConfig::setSolverUpgradeRemoveDroppedPackages( bool val_r ) { _pimpl->targetDefaults().solverUpgradeRemoveDroppedPackages.set( val_r ); } + void ZConfig::resetSolverUpgradeRemoveDroppedPackages() { _pimpl->targetDefaults().solverUpgradeRemoveDroppedPackages.restoreToDefault(); } + + + Pathname ZConfig::solver_checkSystemFile() const + { return ( _pimpl->solver_checkSystemFile.empty() + ? (configPath()/"systemCheck") : _pimpl->solver_checkSystemFile ); } + + Pathname ZConfig::solver_checkSystemFileDir() const + { return ( _pimpl->solver_checkSystemFileDir.empty() + ? (configPath()/"systemCheck.d") : _pimpl->solver_checkSystemFileDir ); } + + + namespace + { + inline void sigMultiversionSpecChanged() + { + sat::detail::PoolMember::myPool().multiversionSpecChanged(); + } + } + + const std::set & ZConfig::multiversionSpec() const { return _pimpl->multiversion(); } + void ZConfig::multiversionSpec( std::set new_r ) { _pimpl->multiversion().swap( new_r ); sigMultiversionSpecChanged(); } + void ZConfig::clearMultiversionSpec() { _pimpl->multiversion().clear(); sigMultiversionSpecChanged(); } + void ZConfig::addMultiversionSpec( const std::string & name_r ) { _pimpl->multiversion().insert( name_r ); sigMultiversionSpecChanged(); } + void ZConfig::removeMultiversionSpec( const std::string & name_r ) { _pimpl->multiversion().erase( name_r ); sigMultiversionSpecChanged(); } + + bool ZConfig::apply_locks_file() const + { return _pimpl->apply_locks_file; } + + Pathname ZConfig::update_dataPath() const + { + return ( _pimpl->update_data_path.empty() + ? Pathname("/var/adm") : _pimpl->update_data_path ); + } + + Pathname ZConfig::update_messagesPath() const + { + return ( _pimpl->update_messages_path.empty() + ? Pathname(update_dataPath()/"update-messages") : _pimpl->update_messages_path ); + } + + Pathname ZConfig::update_scriptsPath() const + { + return ( _pimpl->update_scripts_path.empty() + ? Pathname(update_dataPath()/"update-scripts") : _pimpl->update_scripts_path ); + } + + std::string ZConfig::updateMessagesNotify() const + { return _pimpl->updateMessagesNotify; } + + void ZConfig::setUpdateMessagesNotify( const std::string & val_r ) + { _pimpl->updateMessagesNotify.set( val_r ); } + + void ZConfig::resetUpdateMessagesNotify() + { _pimpl->updateMessagesNotify.restoreToDefault(); } + + /////////////////////////////////////////////////////////////////// + + target::rpm::RpmInstFlags ZConfig::rpmInstallFlags() const + { return _pimpl->rpmInstallFlags; } + + + Pathname ZConfig::historyLogFile() const + { + return ( _pimpl->history_log_path.empty() ? + Pathname("/var/log/zypp/history") : _pimpl->history_log_path ); + } + + Pathname ZConfig::credentialsGlobalDir() const + { + return _pimpl->_mediaConf.credentialsGlobalDir(); + } + + Pathname ZConfig::credentialsGlobalFile() const + { + return _pimpl->_mediaConf.credentialsGlobalFile(); + } + + /////////////////////////////////////////////////////////////////// + + std::string ZConfig::distroverpkg() const + { return "system-release"; } + + /////////////////////////////////////////////////////////////////// + + Pathname ZConfig::pluginsPath() const + { return _pimpl->pluginsPath.get(); } + + std::string ZConfig::multiversionKernels() const + { + return _pimpl->cfg_kernel_keep_spec; + } + + /////////////////////////////////////////////////////////////////// + + std::ostream & ZConfig::about( std::ostream & str ) const + { + str << "libzypp: " LIBZYPP_VERSION_STRING << endl; + + str << "libsolv: " << solv_version; + if ( ::strcmp( solv_version, LIBSOLV_VERSION_STRING ) ) + str << " (built against " << LIBSOLV_VERSION_STRING << ")"; + str << endl; + + str << "zypp.conf: '" << _pimpl->_parsedZyppConf << "'" << endl; + str << "TextLocale: '" << textLocale() << "' (" << defaultTextLocale() << ")" << endl; + str << "SystemArchitecture: '" << systemArchitecture() << "' (" << defaultSystemArchitecture() << ")" << endl; + return str; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ZConfig.h b/zypp/ZConfig.h new file mode 100644 index 0000000..59b8321 --- /dev/null +++ b/zypp/ZConfig.h @@ -0,0 +1,612 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZConfig.h + * +*/ +#ifndef ZYPP_ZCONFIG_H +#define ZYPP_ZCONFIG_H + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + // just for the friend declaration + template class RepoManager; +} + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class RepoManager; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZConfig + // + /** Interim helper class to collect global options and settings. + * Use it to avoid hardcoded values and calls to getZYpp() just + * to retrieve some value like architecture, languages or temppath. + * + * It reads /etc/zypp/zypp.conf, the filename can be overridden by + * setting the ZYPP_CONF environment variable to a different file. + * Config values for \ref MediaConfig are forwarded to the MediaConfig + * singleton. + * + * Note, if you add settings to this file, please follow the following + * convention: + * + * namespace.settingname + * + * should become + * + * namespace_settingName() + * + * \ingroup ZyppConfig + * \ingroup Singleton + */ + class ZYPP_API ZConfig : private base::NonCopyable + { + public: + + /** Singleton ctor */ + static ZConfig & instance(); + + /** Print some detail about the current libzypp version.*/ + std::ostream & about( std::ostream & str ) const; + + public: + + /** The target root directory. + * Returns an empty path if no target is set. + */ + Pathname systemRoot() const; + + /** The RepoManager root directory. + * Returns the same as \ref systemRoot() if not explicitly set. + */ + Pathname repoManagerRoot() const; + + /** Sets the RepoManager root directory. + * \sa repoManagerRoot() + */ + void setRepoManagerRoot ( const Pathname &root ); + + public: + + /** The autodetected system architecture. */ + static Arch defaultSystemArchitecture(); + + /** The system architecture zypp uses. */ + Arch systemArchitecture() const; + + /** Override the zypp system architecture. + * This is useful for test scenarious. But be warned, zypp does + * not expect the system architecture to change at runtime. So + * set it at the very beginning before you access any other + * zypp component. + */ + void setSystemArchitecture( const Arch & arch_r ); + + /** Reset the zypp system architecture to the default. */ + void resetSystemArchitecture() + { setSystemArchitecture( defaultSystemArchitecture() ); } + + public: + /** The autodetected preferred locale for translated texts. + */ + static Locale defaultTextLocale(); + + /** The locale for translated texts zypp uses. + */ + Locale textLocale() const; + + /** Set the preferred locale for translated texts. */ + void setTextLocale( const Locale & locale_r ); + + /** Reset the locale for translated texts to the default. */ + void resetTextLocale() + { setTextLocale( defaultTextLocale() ); } + + public: + /** \name Maintain user data + * \see \ref zypp-userdata + */ + //@{ + /** Whether a (non empty) user data sting is defined. */ + bool hasUserData() const; + + /** User defined string value to be passed to log, history, plugins... */ + std::string userData() const; + + /** Set a new \ref userData string. + * \returns \c TRUE if the string was accepted; \c FALSE if the + * string was rejected due to nonprintable characters or newlines. + */ + bool setUserData( const std::string & str_r ); + //@} + + public: + /** + * Path where the caches are kept (/var/cache/zypp) + * \ingroup g_ZC_REPOCACHE + */ + Pathname repoCachePath() const; + + /** + * Set a new \a path as the default repo cache path + */ + void setRepoCachePath ( const Pathname &path_r ); + + /** + * Path where the pubkey caches + */ + Pathname pubkeyCachePath() const; + + /** + * Path where the repo metadata is downloaded and kept (repoCachePath()/raw). + * \ingroup g_ZC_REPOCACHE + */ + Pathname repoMetadataPath() const; + + + /** + * Set a new \a path as the default repo cache path + */ + void setRepoMetadataPath ( const Pathname &path_r ); + + /** + * Path where the repo solv files are created and kept (repoCachePath()/solv). + * \ingroup g_ZC_REPOCACHE + */ + Pathname repoSolvfilesPath() const; + + /** + * Set a new \a path as the default repo cache path + */ + void setRepoSolvfilesPath ( const Pathname &path_r ); + + /** + * Path where the repo packages are downloaded and kept (repoCachePath()/packages). + * \ingroup g_ZC_REPOCACHE + */ + Pathname repoPackagesPath() const; + + + /** + * Set a new \a path as the default repo cache path + */ + void setRepoPackagesPath ( const Pathname &path_r ); + + /** + * Path where the configfiles are kept (/etc/zypp). + * \ingroup g_ZC_CONFIGFILES + */ + Pathname configPath() const; + + /** + * Path where the known repositories .repo files are kept (configPath()/repos.d). + * \ingroup g_ZC_CONFIGFILES + */ + Pathname knownReposPath() const; + + /** + * Path where the known services .service files are kept (configPath()/services.d). + * \ingroup g_ZC_CONFIGFILES + */ + Pathname knownServicesPath() const; + + /** + * Path of the default needreboot config file (configPath()/needreboot). + * \ingroup g_ZC_CONFIGFILES + */ + Pathname needrebootFile() const; + + /** + * Path where the custom needreboot config files are kept (configPath()/needreboot.d). + * \ingroup g_ZC_CONFIGFILES + */ + Pathname needrebootPath() const; + + /** + * Enables or disables the use of the geoip feature of download.opensuse.org + */ + void setGeoipEnabled( bool enable = true ); + + /** + * Returns true if zypp should use the geoip feature of download.opensuse.org + */ + bool geoipEnabled () const; + + /** + * Path where the geoip caches are kept (/var/cache/zypp/geoip) + */ + Pathname geoipCachePath() const; + + /** + * All hostnames we want to rewrite using the geoip feature. The \ref RepoManager + * will try to query each hostname via: https://hostname/geoip to receive a redirection + * target for requests to the given hostname. The geoip targets are cached in \ref geoipCachePath. + */ + const std::vector geoipHostnames () const; + + /** + * Path containing custom repo variable definitions (configPath()/vars.d). + * \see \ref zypp::repo::RepoVarExpand Repo variable expander + * \ingroup g_ZC_CONFIGFILES + */ + Pathname varsPath() const; + + /** + * Whether repository urls should be probed. + / config option + * repo.add.probe + */ + bool repo_add_probe() const; + + /** + * Amount of time in minutes that must pass before another refresh. + */ + unsigned repo_refresh_delay() const; + + /** + * List of locales for which translated package descriptions should be downloaded. + */ + LocaleSet repoRefreshLocales() const; + + /** + * Whether to use repository alias or name in user messages (progress, + * exceptions, ...). + * True: use alias, false: use name. + */ + bool repoLabelIsAlias() const; + + /** + * Whether to use repository alias or name in user messages (progress, + * exceptions, ...). Console applications might prefer to use and display + * the shorter alias instead of full repository name. + * + * Default: false; i.e. repo label is 'name' + */ + void repoLabelIsAlias( bool yesno_r ); + + /** + * Maximum number of concurrent connections for a single transfer + */ + long download_max_concurrent_connections() const; + + /** + * Minimum download speed (bytes per second) + * until the connection is dropped + */ + long download_min_download_speed() const; + + /** + * Maximum download speed (bytes per second) + */ + long download_max_download_speed() const; + + /** + * Maximum silent tries + */ + long download_max_silent_tries() const; + + /** + * Maximum time in seconds that you allow a transfer operation to take. + */ + long download_transfer_timeout() const; + + + /** Whether to consider using a deltarpm when downloading a package. + * Config option download.use_deltarpm (true) + */ + bool download_use_deltarpm() const; + + /** Whether to consider using a deltarpm even when rpm is local. + * This requires \ref download_use_deltarpm being \c true. + * Config option download.use_deltarpm.always (false) + */ + bool download_use_deltarpm_always() const; + + /** + * Hint which media to prefer when installing packages (download vs. CD). + * \see class \ref media::MediaPriority + */ + bool download_media_prefer_download() const; + /** \overload */ + bool download_media_prefer_volatile() const + { return ! download_media_prefer_download(); } + /** + * Set \ref download_media_prefer_download to a specific value. + */ + void set_download_media_prefer_download( bool yesno_r ); + /** + * Set \ref download_media_prefer_download to the configfiles default. + */ + void set_default_download_media_prefer_download(); + + /** Path where media are preferably mounted or downloaded. + * Config option download.media_mountdir (/var/adm/mount) + * Needs to be a (writable) directory, otherwise /var/tmp is fallback. + */ + Pathname download_mediaMountdir() const; + /** Set alternate value. */ + void set_download_mediaMountdir( Pathname newval_r ); + /** Reset to zypp.cong default. */ + void set_default_download_mediaMountdir(); + + /** + * Commit download policy to use as default. + */ + DownloadMode commit_downloadMode() const; + + /** \name Signature checking (repodata and packages) + * If \ref gpgcheck is \c on (the default), we will either check the signature + * of repo metadata (packages are secured via checksum in the metadata), or the + * signature of an rpm package to install if its repo metadata is not signed + * or not checked. If \ref gpgcheck is \c off, no checks are performed. + * + * The default behavior can be altered by explicitly setting \ref repo_gpgcheck and/or + * \ref pkg_gpgcheck to perform those checks always (\c on) or never (\c off). + * + * Explicitly setting \c gpgcheck, \c repo_gpgcheck or \c pkg_gpgcheck in a + * repositories \a .repo file will overwrite the defaults here. + */ + //@{ + bool gpgCheck() const; ///< Turn signature checking on/off (on) + TriBool repoGpgCheck() const; ///< Check repo matadata signatures (indeterminate - according to gpgcheck) + TriBool pkgGpgCheck() const; ///< Check rpm package signatures (indeterminate - according to gpgcheck) + + void setGpgCheck( bool val_r ); ///< Change the value + void setRepoGpgCheck( TriBool val_r ); ///< Change the value + void setPkgGpgCheck( TriBool val_r ); ///< Change the value + + void resetGpgCheck(); ///< Reset to the zconfig default + void resetRepoGpgCheck(); ///< Reset to the zconfig default + void resetPkgGpgCheck(); ///< Reset to the zconfig default + //@} + // + /** + * Directory for equivalent vendor definitions (configPath()/vendors.d) + * \ingroup g_ZC_CONFIGFILES + */ + Pathname vendorPath() const; + + /** + * The resolver's general attitude when resolving jobs. + */ + ResolverFocus solver_focus() const; + + /** + * Solver regards required packages,patterns,... only + */ + bool solver_onlyRequires() const; + + /** + * File in which dependencies described which has to be + * fulfilled for a running system. + */ + Pathname solver_checkSystemFile() const; + + /** + * Directory, which may or may not contain files in which + * dependencies described which has to be fulfilled for a + * running system. + */ + Pathname solver_checkSystemFileDir() const; + + /** + * Whether vendor check is by default enabled. + */ + bool solver_allowVendorChange() const; + + /** DUP tune: Whether to allow version downgrades upon DUP. */ + bool solver_dupAllowDowngrade() const; + + /** DUP tune: Whether to follow package renames upon DUP. */ + bool solver_dupAllowNameChange() const; + + /** DUP tune: Whether to allow package arch changes upon DUP. */ + bool solver_dupAllowArchChange() const; + + /** DUP tune: Whether to allow package vendor changes upon DUP. */ + bool solver_dupAllowVendorChange() const; + + /** + * Whether removing a package should also remove no longer needed requirements. + */ + bool solver_cleandepsOnRemove() const; + + /** + * When committing a dist upgrade (e.g. zypper dup) + * a solver testcase is written. It is needed in bugreports, + * in case something went wrong. This returns the number of + * testcases to keep on the system. Old cases will be deleted, + * as new ones are created. Use \c 0 to write no testcase at all. + */ + unsigned solver_upgradeTestcasesToKeep() const; + + /** Whether dist upgrade should remove a products dropped packages (true). + * + * A new product may suggest a list of old and no longer supported + * packages (dropped packages). Performing a dist upgrade the solver + * may try to delete them, even if they do not cause any dependency + * problem. + * + * Turning this option off, the solver will not try to remove those + * packages unless they actually do cause dependency trouble. At any + * time you may use zypper to detect orphaned packages, and do the + * cleanup manually. Or simply leave them installed as long as you don't + * need the disk space. + */ + bool solverUpgradeRemoveDroppedPackages() const; + /** Set \ref solverUpgradeRemoveDroppedPackages to \a val_r. */ + void setSolverUpgradeRemoveDroppedPackages( bool val_r ); + /** Reset \ref solverUpgradeRemoveDroppedPackages to the \c zypp.conf default. */ + void resetSolverUpgradeRemoveDroppedPackages(); + + /** \name Packages which can be installed in different versions at the same time. + * + * This returns the config file values (\c names or \c provides:...). The + * corresponding packages have the \c multiversionInstall property set. Those + * packages will be installed using 'rpm -i', so they will not implicitly obsolete + * other installed versions. + * + * \see \ref sat::SolvableType + */ + //@{ + const std::set & multiversionSpec() const; + void multiversionSpec( std::set new_r ); + void clearMultiversionSpec(); + void addMultiversionSpec( const std::string & name_r ); + void removeMultiversionSpec( const std::string & name_r ); + //@} + + /** + * Path where zypp can find or create lock file (configPath()/locks) + * \ingroup g_ZC_CONFIGFILES + */ + Pathname locksFile() const; + + /** + * Whether locks file should be read and applied after start (true) + */ + bool apply_locks_file() const; + + /** + * Path where the update items are kept (/var/adm) + */ + Pathname update_dataPath() const; + + /** + * Path where the repo metadata is downloaded and kept (update_dataPath()/). + * \ingroup g_ZC_REPOCACHE + */ + Pathname update_scriptsPath() const; + + /** + * Path where the repo solv files are created and kept (update_dataPath()/solv). + * \ingroup g_ZC_REPOCACHE + */ + Pathname update_messagesPath() const; + + /** \name Command to be invoked to send update messages. */ + //@{ + /** Command definition for sending update messages.*/ + std::string updateMessagesNotify() const; + /** Set a new command definition (see update.messages.notify in zypp.conf). */ + void setUpdateMessagesNotify( const std::string & val_r ); + /** Reset to the zypp.conf default. */ + void resetUpdateMessagesNotify(); + //@} + + /** \name Options for package installation */ + //@{ + /** The default \ref target::rpm::RpmInstFlags for \ref ZYppCommitPolicy. + * Or-combination of \ref target::rpm::RpmInstFlag. + * \code + * ZConfig.instance().rpmInstallFlags().testFlag( target::rpm::RPMINST_EXCLUDEDOCS ); + * \endcode + */ + target::rpm::RpmInstFlags rpmInstallFlags() const; + //@} + + /** + * Path where ZYpp install history is logged. Defaults to + * /var/log/zypp/history. + * + * \see http://en.opensuse.org/Libzypp/Package_History + */ + Pathname historyLogFile() const; + + /** + * Defaults to /etc/zypp/credentials.d + */ + Pathname credentialsGlobalDir() const; + + /** + * Defaults to /etc/zypp/credentials.cat + */ + Pathname credentialsGlobalFile() const; + + /** Package telling the "product version" on systems not using /etc/product.d/baseproduct. + * + * On RHEL, Fedora and others the "product version" is determined by the first package + * providing 'system-release'. This value is not hardcoded in YUM and can be configured + * with the $distroverpkg variable. + * + * Defaults to 'system-release'. + */ + std::string distroverpkg() const; + + /** \name Plugins */ + //@{ + /** + * Defaults to \c /usr/lib/zypp/plugins + */ + Pathname pluginsPath() const; + + /*! + * Defaults to a empty string, if no keep spec is defined no kernels are removed + */ + std::string multiversionKernels() const; + + //@} + + public: + class Impl; + + ZConfig(const ZConfig &) = delete; + ZConfig(ZConfig &&) = delete; + ZConfig &operator=(const ZConfig &) = delete; + ZConfig &operator=(ZConfig &&) = delete; + + /** Dtor */ + ~ZConfig(); + void notifyTargetChanged(); ///< internal + + private: + friend class RepoManager; + template friend class zyppng::RepoManager; + /** The builtin config file value. */ + Pathname builtinRepoCachePath() const; + /** The builtin config file value. */ + Pathname builtinRepoMetadataPath() const; + /** The builtin config file value. */ + Pathname builtinRepoSolvfilesPath() const; + /** The builtin config file value. */ + Pathname builtinRepoPackagesPath() const; + + private: + friend class Impl; + /** Default ctor. */ + ZConfig(); + /** Pointer to implementation */ + RW_pointer > _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ZCONFIG_H diff --git a/zypp/ZYpp.cc b/zypp/ZYpp.cc new file mode 100644 index 0000000..89ab7e3 --- /dev/null +++ b/zypp/ZYpp.cc @@ -0,0 +1,104 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYpp.cc + * +*/ +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + // class ZYpp: + // ctor and dtor implemented in ZYppFactory.cc + + std::ostream & operator<<( std::ostream & str, const ZYpp & obj ) + { return str << *obj._pimpl; } + + /////////////////////////////////////////////////////////////////// + // + // Forward to Impl: + // + /////////////////////////////////////////////////////////////////// + + ResPool ZYpp::pool() const + { return _pimpl->pool(); } + + DiskUsageCounter::MountPointSet ZYpp::diskUsage() + { return _pimpl->diskUsage(); } + + void ZYpp::setPartitions(const DiskUsageCounter::MountPointSet &mp) + { return _pimpl->setPartitions(mp); } + + DiskUsageCounter::MountPointSet ZYpp::getPartitions() const + { return _pimpl->getPartitions(); } + + ResPoolProxy ZYpp::poolProxy() const + { return _pimpl->poolProxy(); } + + Resolver_Ptr ZYpp::resolver() const + { return _pimpl->resolver(); } + + KeyRing_Ptr ZYpp::keyRing() const + { return _pimpl->keyRing(); } + + /////////////////////////////////////////////////////////////////// + // + // Forward to Impl: + // + /////////////////////////////////////////////////////////////////// + + Target_Ptr ZYpp::target() const + { return _pimpl->target(); } + + Target_Ptr ZYpp::getTarget() const + { return _pimpl->getTarget(); } + + void ZYpp::initializeTarget( const Pathname & root, bool doRebuild_r ) + { _pimpl->initializeTarget( root, doRebuild_r ); } + + void ZYpp::finishTarget() + { _pimpl->finishTarget(); } + + void ZYpp::setShutdownSignal() + { zypp_detail::ZYppImpl::setShutdownSignal(); } + + void ZYpp::clearShutdownSignal() + { zypp_detail::ZYppImpl::clearShutdownSignal(); } + + ZYppCommitResult ZYpp::commit( const ZYppCommitPolicy & policy_r ) + { return _pimpl->commit( policy_r ); } + + void ZYpp::installSrcPackage( const SrcPackage_constPtr & srcPackage_r ) + { _pimpl->installSrcPackage( srcPackage_r ); } + + ManagedFile ZYpp::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ) + {return _pimpl->provideSrcPackage( srcPackage_r ); } + /////////////////////////////////////////////////////////////////// + + Pathname ZYpp::homePath() const + { return _pimpl->homePath(); } + + Pathname ZYpp::tmpPath() const + { return _pimpl->tmpPath(); } + + void ZYpp::setHomePath( const Pathname & path ) + { _pimpl->setHomePath(path); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ZYpp.h b/zypp/ZYpp.h new file mode 100644 index 0000000..af376a7 --- /dev/null +++ b/zypp/ZYpp.h @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYpp.h + * +*/ +#ifndef ZYPP_ZYPP_H +#define ZYPP_ZYPP_H +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace zyppng { + class Context; +} + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace zypp_detail + { + class ZYppImpl; + } + + class ZYppFactory; + class ResPool; + class ResPoolProxy; + class KeyRing; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYpp + // + /** + * \todo define Exceptions + * ZYpp API main interface + */ + class ZYPP_API ZYpp : private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const ZYpp & obj ); + + public: + // can't get swig working if shared_ptr is without namespace here + using Ptr = ::boost::shared_ptr; + using constPtr = ::boost::shared_ptr; + + public: + + /** + * Access to the global resolvable pool. + * Same as \ref zypp::ResPool::instance + */ + ResPool pool() const; + + /** Pool of ui::Selectable. + * Based on the ResPool, ui::Selectable groups ResObjetcs of + * same kind and name. + */ + ResPoolProxy poolProxy() const; + + DiskUsageCounter::MountPointSet diskUsage(); + + void setPartitions(const DiskUsageCounter::MountPointSet &mp); + + DiskUsageCounter::MountPointSet getPartitions() const; + + public: + /** + * \throws Exception + */ + Target_Ptr target() const; + + /** Same as \ref target but returns NULL if target is not + * initialized, instead of throwing. + */ + Target_Ptr getTarget() const; + + /** + * \throws Exception + * Just init the target, dont populate store or pool. + * If \c doRebuild_r is \c true, an already existing + * database is rebuilt (rpm --rebuilddb ). + */ + void initializeTarget(const Pathname & root, bool doRebuild_r = false); + + /** + * \throws Exception + */ + void finishTarget(); + + /** + * To be called from zyppers signal handlers. Sets a shutdown signal + * in a signal and thread safe way. + */ + static void setShutdownSignal(); + + /** + * To be called from zypper code. This resets the shutdown signal state + * to normal.. + */ + static void clearShutdownSignal(); + + public: + using CommitResult = ZYppCommitResult; + + /** Commit changes and transactions. + * \param \ref CommitPolicy + * \return \ref CommitResult + * \throws Exception + */ + ZYppCommitResult commit( const ZYppCommitPolicy & policy_r ); + + /** Install a source package on the Target. + * \throws Exception + */ + void installSrcPackage( const SrcPackage_constPtr & srcPackage_r ); + + /** Provides a source package on the Target. + * \throws Exception + */ + ManagedFile provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ); + + public: + /** */ + Resolver_Ptr resolver() const; + KeyRing_Ptr keyRing() const; + + public: + /** Get the path where zypp related plugins store persistent data and caches */ + Pathname homePath() const; + + /** Get the path where zypp related plugins store temp data */ + Pathname tmpPath() const; + + /** set the home, if you need to change it */ + void setHomePath( const Pathname & path ); + + private: + /** Factory */ + friend class ZYppFactory; + using Impl = zypp_detail::ZYppImpl; + using Impl_Ptr = shared_ptr; + /** Factory ctor */ + explicit ZYpp( const Impl_Ptr & impl_r ); + private: + /** Deleted via shared_ptr */ + friend void ::boost::checked_delete(ZYpp*) BOOST_NOEXCEPT; // template inline void checked_delete(T * x) + /** Dtor */ + ~ZYpp(); + private: + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ZYPP_H diff --git a/zypp/ZYppCallbacks.h b/zypp/ZYppCallbacks.h new file mode 100644 index 0000000..68f4f98 --- /dev/null +++ b/zypp/ZYppCallbacks.h @@ -0,0 +1,1068 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppCallbacks.h + * +*/ +#ifndef ZYPP_ZYPPCALLBACKS_H +#define ZYPP_ZYPPCALLBACKS_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // bsc#1194597: CurlAuthData must be exposed for zypper + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace sat + { + class Queue; + class FileConflicts; + } // namespace sat + /////////////////////////////////////////////////////////////////// + + struct ZYPP_API ProgressReport : public callback::ReportBase + { + virtual void start( const ProgressData &/*task*/ ) + {} + + virtual bool progress( const ProgressData &/*task*/ ) + { return true; } + +// virtual Action problem( +// Repo /*source*/ +// , Error /*error*/ +// , const std::string &/*description*/ ) +// { return ABORT; } + + virtual void finish( const ProgressData &/*task*/ ) + {} + + }; + + struct ProgressReportAdaptor + { + + ProgressReportAdaptor( callback::SendReport &report ) + : _report(report) + , _first(true) + {} + + ProgressReportAdaptor( const ProgressData::ReceiverFnc &fnc, + callback::SendReport &report ) + : _fnc(fnc) + , _report(report) + , _first(true) + {} + + bool operator()( const ProgressData &progress ) + { + if ( _first ) + { + _report->start(progress); + _first = false; + } + + bool value = _report->progress(progress); + if ( _fnc ) + value &= _fnc(progress); + + if ( progress.finalReport() ) + { + _report->finish(progress); + } + return value; + } + + ProgressData::ReceiverFnc _fnc; + callback::SendReport &_report; + bool _first; + }; + + //////////////////////////////////////////////////////////////////////////// + + namespace repo + { + // progress for downloading a resolvable + struct ZYPP_API DownloadResolvableReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE, // ignore this resolvable but continue + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + INVALID // the downloaded file is invalid + }; + + /** Hint that package is available in the local cache (no download needed). + * This will be the only trigger for an already cached package. + */ + virtual void infoInCache( Resolvable::constPtr res_r, const Pathname & localfile_r ) + {} + + virtual void start( + Resolvable::constPtr /*resolvable_ptr*/ + , const Url &/*url*/ + ) {} + + + // Dowmload delta rpm: + // - path below url reported on start() + // - expected download size (0 if unknown) + // - download is interruptable + // - problems are just informal + virtual void startDeltaDownload( const Pathname & /*filename*/, const ByteCount & /*downloadsize*/ ) + {} + + virtual bool progressDeltaDownload( int /*value*/ ) + { return true; } + + virtual void problemDeltaDownload( const std::string &/*description*/ ) + {} + + virtual void finishDeltaDownload() + {} + + // Apply delta rpm: + // - local path of downloaded delta + // - aplpy is not interruptable + // - problems are just informal + virtual void startDeltaApply( const Pathname & /*filename*/ ) + {} + + virtual void progressDeltaApply( int /*value*/ ) + {} + + virtual void problemDeltaApply( const std::string &/*description*/ ) + {} + + virtual void finishDeltaApply() + {} + + // return false if the download should be aborted right now + virtual bool progress(int /*value*/, Resolvable::constPtr /*resolvable_ptr*/) + { return true; } + + virtual Action problem( + Resolvable::constPtr /*resolvable_ptr*/ + , Error /*error*/ + , const std::string &/*description*/ + ) { return ABORT; } + + + /** Detail information about the result of a performed pkgGpgCheck. + * + * Userdata sent: + * \param "ResObject" ResObject::constPtr of the downloaded package (Package or SrcPackage) + * \param "Localpath" Pathname to downloaded package on disk + * \param "CheckPackageResult" RpmDb::CheckPackageResult of signature check + * \param "CheckPackageDetail" RpmDb::CheckPackageDetail logmessages of rpm signature check + * + * Userdata accepted: + * \param "Action" DownloadResolvableReport::Action user advice how to behave on error (ABORT). + * If you set just an empty value here, a default problem report will be triggered. + * + * Legacy data: + * \param "Package" Replaced by \c "ResObject" in 16.10.0. Package::constPtr of the package (\c nullptr in case of a SrcPackage) + */ + virtual void pkgGpgCheck( const UserData & userData_r = UserData() ) + {} + + virtual void finish(Resolvable::constPtr /*resolvable_ptr*/ + , Error /*error*/ + , const std::string &/*reason*/ + ) {} + }; + + // progress for probing a source + struct ZYPP_API ProbeRepoReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY // retry + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + INVALID, // th source is invalid + UNKNOWN + }; + + virtual void start(const Url &/*url*/) {} + virtual void failedProbe( const Url &/*url*/, const std::string &/*type*/ ) {} + virtual void successProbe( const Url &/*url*/, const std::string &/*type*/ ) {} + virtual void finish(const Url &/*url*/, Error /*error*/, const std::string &/*reason*/ ) {} + + virtual bool progress(const Url &/*url*/, int /*value*/) + { return true; } + + virtual Action problem( const Url &/*url*/, Error /*error*/, const std::string &/*description*/ ) { return ABORT; } + }; + + struct ZYPP_API RepoCreateReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // skip refresh, ignore failed refresh + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + REJECTED, + INVALID, // th source is invali + UNKNOWN + }; + + virtual void start( const zypp::Url &/*url*/ ) {} + virtual bool progress( int /*value*/ ) + { return true; } + + virtual Action problem( + const zypp::Url &/*url*/ + , Error /*error*/ + , const std::string &/*description*/ ) + { return ABORT; } + + virtual void finish( + const zypp::Url &/*url*/ + , Error /*error*/ + , const std::string &/*reason*/ ) + {} + }; + + struct ZYPP_API RepoReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // skip refresh, ignore failed refresh + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + INVALID // th source is invalid + }; + + virtual void start( const ProgressData &/*task*/, const RepoInfo /*repo*/ ) {} + virtual bool progress( const ProgressData &/*task*/ ) + { return true; } + + virtual Action problem( + Repository /*source*/ + , Error /*error*/ + , const std::string &/*description*/ ) + { return ABORT; } + + virtual void finish( + Repository /*source*/ + , const std::string &/*task*/ + , Error /*error*/ + , const std::string &/*reason*/ ) + {} + }; + + + ///////////////////////////////////////////////////////////////// + } // namespace source + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace media + { + // media change request callback + struct ZYPP_API MediaChangeReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE, // ignore this media in future, not available anymore + IGNORE_ID, // ignore wrong medium id + CHANGE_URL, // change media URL + EJECT // eject the medium + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the medie not found at all + IO, // error accessing the media + INVALID, // media is broken + WRONG, // wrong media, need a different one + IO_SOFT /**< IO error which can happen on worse connection like timeout exceed */ + }; + + /** + * + * \param url in: url for which the media is requested, + * out: url to use instead of the original one + * \param mediumNr requested medium number + * \param label label of requested medium + * \param error type of error from \ref Error enum + * \param description error message (media not desired or error foo occured) + * \param devices list of the available devices (for eject) + * \param dev_current in: index of the currently used device in the \a devices list + * out: index of the devices to be ejected in the \a devices list + * \return \ref Action (ABORT by default) + */ + virtual Action requestMedia( + Url & /* url (I/O parameter) */ + , unsigned /*mediumNr*/ + , const std::string & /* label */ + , Error /*error*/ + , const std::string & /*description*/ + , const std::vector & /* devices */ + , unsigned int & /* dev_current (I/O param) */ + ) { return ABORT; } + }; + + /////////////////////////////////////////////////////////////////// + /// \class ScopedDisableMediaChangeReport + /// \brief Temporarily disable MediaChangeReport + /// Sometimes helpful to suppress interactive messages connected to + /// MediaChangeReport while fallback URLs are avaialble. + struct ZYPP_API ScopedDisableMediaChangeReport + { + /** Disbale MediaChangeReport if \a condition_r is \c true.*/ + ScopedDisableMediaChangeReport( bool condition_r = true ); + private: + shared_ptr > _guard; + }; + + // progress for downloading a file + struct ZYPP_API DownloadProgressReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // ignore the failure + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + ACCESS_DENIED, // user authent. failed while accessing restricted file + ERROR // other error + }; + + virtual void start( const Url &/*file*/, Pathname /*localfile*/ ) {} + + /** + * Download progress. + * + * \param value Percentage value. + * \param file File URI. + * \param dbps_avg Average download rate so far. -1 if unknown. + * \param dbps_current Current download (cca last 1 sec). -1 if unknown. + */ + virtual bool progress(int /*value*/, const Url &/*file*/, + double dbps_avg = -1, + double dbps_current = -1) + { return true; } + + virtual Action problem( + const Url &/*file*/ + , Error /*error*/ + , const std::string &/*description*/ + ) { return ABORT; } + + virtual void finish( + const Url &/*file*/ + , Error /*error*/ + , const std::string &/*reason*/ + ) {} + }; + + // authentication issues report + struct ZYPP_API AuthenticationReport : public callback::ReportBase + { + /** + * Prompt for authentication data. + * + * \param url URL which required the authentication + * \param msg prompt text + * \param auth_data input/output object for handling authentication + * data. As an input parameter auth_data can be prefilled with + * username (from previous try) or auth_type (available + * authentication methods aquired from server (only CurlAuthData)). + * As an output parameter it serves for sending username, password + * or other special data (derived AuthData objects). + * \return true if user chooses to continue with authentication, + * false otherwise + */ + virtual bool prompt(const Url & /* url */, + const std::string & /* msg */, + AuthData & /* auth_data */) + { + return false; + } + }; + + ///////////////////////////////////////////////////////////////// + } // namespace media + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace target + { + /** Request to display the pre commit message of a patch. */ + struct ZYPP_API PatchMessageReport : public callback::ReportBase + { + /** Display \c patch->message(). + * Return \c true to continue, \c false to abort commit. + */ + virtual bool show( Patch::constPtr & /*patch*/ ) + { return true; } + }; + + /** Indicate execution of a patch script. This is a sort of + * \c %post script shipped by a package and to be executed + * after the package was installed. + */ + struct ZYPP_API PatchScriptReport : public callback::ReportBase + { + enum Notify { OUTPUT, PING }; + enum Action { + ABORT, // abort commit and return error + RETRY, // (re)try to execute this script + IGNORE // ignore any failue and continue + }; + + /** Start executing the script provided by package. + */ + virtual void start( const Package::constPtr & /*package*/, + const Pathname & /*script path*/ ) + {} + /** Progress provides the script output. If the script is quiet, + * from time to time still-alive pings are sent to the ui. Returning \c FALSE + * aborts script execution. + */ + virtual bool progress( Notify /*OUTPUT or PING*/, + const std::string & /*output*/ = std::string() ) + { return true; } + /** Report error. */ + virtual Action problem( const std::string & /*description*/ ) + { return ABORT; } + /** Report success. */ + virtual void finish() + {} + }; + + /////////////////////////////////////////////////////////////////// + /// \class FindFileConflictstReport + /// \brief Check for package file conflicts in commit (after download) + /// + /// File conflict check requires that all packages are downloaded and + /// now available in the cache (need to access the filelists). Missing + /// packages are omitted from check and their number is reported in + /// \a noFilelist_r. This usually happens if download mode 'as-needed' + /// is used. + /////////////////////////////////////////////////////////////////// + struct ZYPP_API FindFileConflictstReport : public callback::ReportBase + { + /** + * \param progress_r Progress counter for packages to check. + * \return \c true to continue, \c false upon user abort request. + */ + virtual bool start( const ProgressData & progress_r ) + { return true; } + + /** + * \param progress_r Progress counter for packages to check. + * \param noFilelist_r Queue of so far skipped solvables (no filelist/not yet downloaded). + * \return \c true to continue, \c false upon user abort request. + */ + virtual bool progress( const ProgressData & progress_r, const sat::Queue & noFilelist_r ) + { return true; } + + /** + * \param progress_r Progress counter for packages to check. + * \param noFilelist_r Queue of skipped solvables (no filelist/not yet downloaded). + * \param conflicts_r File conflits queue. + * \return \c true to continue, \c false upon user abort request. + */ + virtual bool result( const ProgressData & progress_r, const sat::Queue & noFilelist_r, const sat::FileConflicts & conflicts_r ) + { return true; } + }; + + + /////////////////////////////////////////////////////////////////// + namespace rpm + { + + // progress for installing a resolvable + struct ZYPP_API InstallResolvableReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // ignore the failure + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + INVALID // th resolvable is invalid + }; + + // the level of RPM pushing + /** \deprecated We fortunately no longer do 3 attempts. */ + enum RpmLevel { + RPM, + RPM_NODEPS, + RPM_NODEPS_FORCE //!< only this one used + }; + + virtual void start( + Resolvable::constPtr /*resolvable*/ + ) {} + + virtual bool progress(int /*value*/, Resolvable::constPtr /*resolvable*/) + { return true; } + + virtual Action problem( + Resolvable::constPtr /*resolvable*/ + , Error /*error*/ + , const std::string &/*description*/ + , RpmLevel /*level*/ + ) { return ABORT; } + + virtual void finish( + Resolvable::constPtr /*resolvable*/ + , Error /*error*/ + , const std::string &/*reason*/ + , RpmLevel /*level*/ + ) {} + + /** "rpmout/installpkg": Additional rpm output (sent immediately). + * Data: + * solvable : satSolvable processed + * line : std::reference_wrapper + * lineno : unsigned + */ + static const UserData::ContentType contentRpmout ZYPP_API; + }; + + // progress for removing a resolvable + struct ZYPP_API RemoveResolvableReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // ignore the failure + }; + + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + INVALID // th resolvable is invalid + }; + + virtual void start( + Resolvable::constPtr /*resolvable*/ + ) {} + + virtual bool progress(int /*value*/, Resolvable::constPtr /*resolvable*/) + { return true; } + + virtual Action problem( + Resolvable::constPtr /*resolvable*/ + , Error /*error*/ + , const std::string &/*description*/ + ) { return ABORT; } + + virtual void finish( + Resolvable::constPtr /*resolvable*/ + , Error /*error*/ + , const std::string &/*reason*/ + ) {} + + /** "rpmout/removepkg": Additional rpm output (sent immediately). + * For data \see \ref InstallResolvableReport::contentRpmout + */ + static const UserData::ContentType contentRpmout ZYPP_API; + }; + + // progress for rebuilding the database + struct ZYPP_API RebuildDBReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // ignore the failure + }; + + enum Error { + NO_ERROR, + FAILED // failed to rebuild + }; + + virtual void start(Pathname /*path*/) {} + + virtual bool progress(int /*value*/, Pathname /*path*/) + { return true; } + + virtual Action problem( + Pathname /*path*/ + , Error /*error*/ + , const std::string &/*description*/ + ) { return ABORT; } + + virtual void finish( + Pathname /*path*/ + , Error /*error*/ + , const std::string &/*reason*/ + ) {} + }; + +#if LEGACY(17) + // progress for converting the database + /// \deprecated Still used by y2-bindings in Code15 (libyzpp major 17) + struct ZYPP_DEPRECATED ConvertDBReport : public callback::ReportBase + { + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // ignore the failure + }; + + enum Error { + NO_ERROR, + FAILED // conversion failed + }; + + virtual void start( Pathname /*path*/ ) + {} + + virtual bool progress( int/*value*/, Pathname/*path*/ ) + { return true; } + + virtual Action problem( Pathname/*path*/, Error/*error*/, const std::string &/*description*/ ) + { return ABORT; } + + virtual void finish( Pathname/*path*/, Error/*error*/, const std::string &/*reason*/ ) + {} + }; +#endif + + /////////////////////////////////////////////////////////////////// + /// \brief Report active throughout the whole rpm transaction. + /// + /// The report covers events not directly related to an individual + /// sub-task. Mostly log lines. + /// \todo maybe include the sub-task reports here as well, so it + /// becomes the only report needed to follow the transaction. + /////////////////////////////////////////////////////////////////// + struct ZYPP_API SingleTransReport : public callback::ReportBase + { + /** \c "zypp-rpm/logline" report a line suitable to be written to the screen. + * UserData: + * \c "line" : std::reference_wrapper; the line to show + * \c "level" : enum class loglevel; rendering hint + */ + static const UserData::ContentType contentLogline ZYPP_API; + /** Rendering hint for log-lines to show. */ + enum class loglevel { dbg, msg, war, err, crt }; + /** Suggested prefix for log-lines to show. */ + static const char *const loglevelPrefix( loglevel level_r ) + { + switch ( level_r ) { + case loglevel::crt: return "fatal error: "; + case loglevel::err: return "error: "; + case loglevel::war: return "warning: "; + case loglevel::msg: return ""; + case loglevel::dbg: return "D: "; + } + return ""; + } + }; + + // Generic transaction reports, this is used for verifying and preparing tasks, the name param + // for the start function defines which report we are looking at + struct ZYPP_API TransactionReportSA : public callback::ReportBase + { + enum Error { + NO_ERROR, // everything went perfectly fine + FINISHED_WITH_ERRORS, // the transaction was finished, but some errors happened + FAILED // the transaction failed completely + }; + + virtual void start( + const std::string &/*name*/, + const UserData & = UserData() /*userdata*/ + ) {} + + virtual void progress( + int /*value*/, + const UserData & = UserData() /*userdata*/ + ) { } + + virtual void finish( + Error /*error*/, + const UserData & = UserData() /*userdata*/ + ) {} + + /** "zypp-rpm/transactionsa": Additional rpm output (sent immediately). + * Data: + * line : std::reference_wrapper + */ + static const UserData::ContentType contentRpmout ZYPP_API; + }; + + + // progress for installing a resolvable in single transaction mode + struct ZYPP_API InstallResolvableReportSA : public callback::ReportBase + { + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + INVALID // th resolvable is invalid + }; + + virtual void start( + Resolvable::constPtr /*resolvable*/, + const UserData & = UserData() /*userdata*/ + ) {} + + virtual void progress( + int /*value*/, + Resolvable::constPtr /*resolvable*/, + const UserData & = UserData() /*userdata*/ + ) { return; } + + virtual void finish( + Resolvable::constPtr /*resolvable*/ + , Error /*error*/, + const UserData & = UserData() /*userdata*/ + ) {} + + /** "zypp-rpm/installpkgsa": Additional rpm output (sent immediately). + * Data: + * solvable : satSolvable processed + * line : std::reference_wrapper + */ + static const UserData::ContentType contentRpmout ZYPP_API; + }; + + // progress for removing a resolvable in single transaction mode + struct ZYPP_API RemoveResolvableReportSA : public callback::ReportBase + { + enum Error { + NO_ERROR, + NOT_FOUND, // the requested Url was not found + IO, // IO error + INVALID // th resolvable is invalid + }; + + virtual void start( + Resolvable::constPtr /*resolvable*/, + const UserData & = UserData() /*userdata*/ + ) {} + + virtual void progress( + int /*value*/, + Resolvable::constPtr /*resolvable*/, + const UserData & = UserData() /*userdata*/ + ) { return; } + + virtual void finish( + Resolvable::constPtr /*resolvable*/ + , Error /*error*/ + , const UserData & = UserData() /*userdata*/ + ) {} + + /** "zypp-rpm/removepkgsa": Additional rpm output (sent immediately). + * For data \see \ref InstallResolvableReportSA::contentRpmout + */ + static const UserData::ContentType contentRpmout ZYPP_API; + }; + + // progress for cleaning up the old version of a package after it was upgraded to a new version + struct ZYPP_API CleanupPackageReportSA : public callback::ReportBase + { + enum Error { + NO_ERROR + }; + + virtual void start( + const std::string & /*nvra*/, + const UserData & = UserData() /*userdata*/ + ) {} + + virtual void progress( + int /*value*/, + const UserData & = UserData() /*userdata*/ + ) { return; } + + virtual void finish( + Error /*error*/, + const UserData & = UserData() /*userdata*/ + ) {} + + /** "zypp-rpm/cleanupkgsa": Additional rpm output (sent immediately). + * For data \see \ref InstallResolvableReportSA::contentRpmout + */ + static const UserData::ContentType contentRpmout ZYPP_API; + }; + + + // progress for script thats executed during a commit transaction + // the resolvable can be null, for things like posttrans scripts + struct ZYPP_API CommitScriptReportSA : public callback::ReportBase + { + enum Error { + NO_ERROR, + WARN, + CRITICAL // the script failure prevented solvable installation + }; + + virtual void start( + const std::string & /*scriptType*/, + const std::string & /*packageName ( can be empty )*/, + Resolvable::constPtr /*resolvable ( can be null )*/, + const UserData & = UserData() /*userdata*/ + ) {} + + virtual void progress( + int /*value*/, + Resolvable::constPtr /*resolvable*/, + const UserData & = UserData() /*userdata*/ + ) { return; } + + virtual void finish( + Resolvable::constPtr /*resolvable*/ + , Error /*error*/, + const UserData & = UserData() /*userdata*/ + ) {} + + /** "zypp-rpm/scriptsa": Additional rpm output (sent immediately). + * Data: + * solvable : satSolvable processed ( can be empty ) + * line : std::reference_wrapper + */ + static const UserData::ContentType contentRpmout ZYPP_API; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace rpm + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + + class PoolQuery; + + /** \name Locks */ + //@{ + /** + * Callback for cleaning locks which doesn't lock anything in pool. + */ + + struct ZYPP_API CleanEmptyLocksReport : public callback::ReportBase + { + /** + * action performed by cleaning api to specific lock + */ + enum Action { + ABORT, /**< abort and return error */ + DELETE, /**< delete empty lock */ + IGNORE /**< skip empty lock */ + }; + + /** + * result of cleaning + */ + enum Error { + NO_ERROR, /**< no problem */ + ABORTED /** cleaning aborted by user */ + }; + + /** + * cleaning is started + */ + virtual void start( + ) {} + + /** + * progress of cleaning specifies in percents + * \return if continue + */ + virtual bool progress(int /*value*/) + { return true; } + + /** + * When find empty lock ask what to do with it + * \return action + */ + virtual Action execute( + const PoolQuery& /*error*/ + ) { return DELETE; } + + /** + * cleaning is done + */ + virtual void finish( + Error /*error*/ + ) {} + + }; + + /** + * this callback handles merging old locks with newly added or removed + */ + struct ZYPP_API SavingLocksReport : public callback::ReportBase + { + /** + * action for old lock which is in conflict + * \see ConflictState + */ + enum Action { + ABORT, /**< abort and return error*/ + DELETE, /**< delete conflicted lock */ + IGNORE /**< skip conflict lock */ + }; + + /** + * result of merging + */ + enum Error { + NO_ERROR, /**< no problem */ + ABORTED /**< cleaning aborted by user */ + }; + + /** + * type of conflict of old and new lock + */ + enum ConflictState{ + SAME_RESULTS, /**< locks lock same item in pool but its parameters are different */ + INTERSECT /**< locks lock some file and unlocking lock unlock only part + * of iti, so removing old lock can unlock more items in pool */ + }; + + virtual void start() {} + + /** + * merging still live + * \return if continue + */ + virtual bool progress() + { return true; } + + /** + * When user unlock something which is locked by non-identical query + */ + virtual Action conflict( + const PoolQuery&, /**< problematic query*/ + ConflictState + ) { return DELETE; } + + virtual void finish( + Error /*error*/ + ) {} + }; + + /////////////////////////////////////////////////////////////////// + /// \class JobReport + /// \brief Generic report for sending messages. + /////////////////////////////////////////////////////////////////// + struct ZYPP_API JobReport : public callback::ReportBase + { + public: + /** message type (use like 'enum class \ref MsgType') */ + struct EMsgTypeDef { + enum Enum { debug, info, warning, error, important, data }; + }; + typedef base::EnumClass MsgType; ///< 'enum class MsgType' + + /** typsafe map of userdata */ + typedef callback::UserData UserData; + + public: + /** Send a ready to show message text. */ + virtual bool message( MsgType type_r, const std::string & msg_r, const UserData & userData_r ) const + { return true; } + + + /** \name Static sender instance */ + //@{ + /** Singleton sender instance */ + static callback::SendReport & instance(); // impl in ZYppImpl.cc + + /** send debug message text */ + static bool debug( const std::string & msg_r, const UserData & userData_r = UserData() ) + { return instance()->message( MsgType::debug, msg_r, userData_r ); } + + /** send message text */ + static bool info( const std::string & msg_r, const UserData & userData_r = UserData() ) + { return instance()->message( MsgType::info, msg_r, userData_r ); } + + /** send warning text */ + static bool warning( const std::string & msg_r, const UserData & userData_r = UserData() ) + { return instance()->message( MsgType::warning, msg_r, userData_r ); } + + /** send error text */ + static bool error( const std::string & msg_r, const UserData & userData_r = UserData() ) + { return instance()->message( MsgType::error, msg_r, userData_r ); } + + /** send important message text */ + static bool important( const std::string & msg_r, const UserData & userData_r = UserData() ) + { return instance()->message( MsgType::important, msg_r, userData_r ); } + + /** send data message */ + static bool data( const std::string & msg_r, const UserData & userData_r = UserData() ) + { return instance()->message( MsgType::data, msg_r, userData_r ); } + //@} + }; + + /////////////////////////////////////////////////////////////////// + /// \class UserDataJobReport + /// \brief \ref JobReport convenience sending this instance of \ref UserData with each message. + /////////////////////////////////////////////////////////////////// + struct ZYPP_API UserDataJobReport : public JobReport::UserData + { + using JobReport::UserData::UserData; + + bool debug( const std::string & msg_r ) { return JobReport::debug( msg_r, *this ); } + bool info( const std::string & msg_r ) { return JobReport::info( msg_r, *this ); } + bool warning( const std::string & msg_r ) { return JobReport::warning( msg_r, *this ); } + bool error( const std::string & msg_r ) { return JobReport::error( msg_r, *this ); } + bool important( const std::string & msg_r ) { return JobReport::important( msg_r, *this ); } + bool data( const std::string & msg_r ) { return JobReport::data( msg_r, *this ); } + }; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif // ZYPP_ZYPPCALLBACKS_H diff --git a/zypp/ZYppCommit.h b/zypp/ZYppCommit.h new file mode 100644 index 0000000..2b99745 --- /dev/null +++ b/zypp/ZYppCommit.h @@ -0,0 +1,26 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppCommit.h + * +*/ +#ifndef ZYPP_ZYPPCOMMIT_H +#define ZYPP_ZYPPCOMMIT_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ZYPPCOMMIT_H diff --git a/zypp/ZYppCommitPolicy.cc b/zypp/ZYppCommitPolicy.cc new file mode 100644 index 0000000..098f7be --- /dev/null +++ b/zypp/ZYppCommitPolicy.cc @@ -0,0 +1,198 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppCommitPolicy.cc + * +*/ + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + inline bool ImZYPPER() + { return filesystem::readlink( "/proc/self/exe" ).basename() == "zypper"; } + + bool singleTransInEnv () + { +#ifdef SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER + static bool singleTrans = ImZYPPER(); +#else // SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER + static bool singleTrans = ImZYPPER() && ([]()->bool{ + const char *val = ::getenv("ZYPP_SINGLE_RPMTRANS"); + bool ret = ( val && std::string_view( val ) == "1" ); +#ifdef NO_SINGLETRANS_USERMERGE + // Bug 1189788 - UsrMerge: filesystem package breaks system when upgraded in a single rpm transaction + // While the bug is not fixed, we don't allow ZYPP_SINGLE_RPMTRANS=1 on a not UsrMerged system. + // I.e. if /lib is a directory and not a symlink. + if ( ret && PathInfo( "/lib", PathInfo::LSTAT ).isDir() ) { + WAR << "Ignore $ZYPP_SINGLE_RPMTRANS=1: Bug 1189788 - UsrMerge: filesystem package breaks system when upgraded in a single rpm transaction" << std::endl; + JobReport::info( + "[boo#1189788] Tumbleweeds filesystem package seems to be unable to perform the\n" + " UsrMerge reliably in a single transaction. The requested\n" + " $ZYPP_SINGLE_RPMTRANS=1 will therefore be IGNORED because\n" + " the UsrMerge did not yet happen on this system." + , JobReport::UserData( "cmdout", "[boo#1189788]" ) ); + return false; + } +#endif + if ( ret ) { + JobReport::info( + "[TechPreview] $ZYPP_SINGLE_RPMTRANS=1 : New rpm install backend is enabled\n" + " If you find any bugs or issues please let us know:\n" + " https://bugzilla.opensuse.org/\n" + " Component: libzypp (or zypper)\n" + " And please attach the /var/log/zypper.log to the bug report." + , JobReport::UserData( "cmdout" ) ); + } + return ret; + })(); +#endif // SINGLE_RPMTRANS_AS_DEFAULT_FOR_ZYPPER + return singleTrans; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppCommitPolicy::Impl + // + /////////////////////////////////////////////////////////////////// + + class ZYppCommitPolicy::Impl + { + public: + Impl() + : _restrictToMedia ( 0 ) + , _downloadMode ( ZConfig::instance().commit_downloadMode() ) + , _rpmInstFlags ( ZConfig::instance().rpmInstallFlags() ) + , _syncPoolAfterCommit ( true ) + , _singleTransMode ( singleTransInEnv() ) + {} + + public: + unsigned _restrictToMedia; + DownloadMode _downloadMode; + target::rpm::RpmInstFlags _rpmInstFlags; + bool _syncPoolAfterCommit; + bool _singleTransMode; //< run everything in one big rpm transaction + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const { return new Impl( *this ); } + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppCommitPolicy + // + /////////////////////////////////////////////////////////////////// + + ZYppCommitPolicy::ZYppCommitPolicy() + : _pimpl( new Impl ) + {} + + + ZYppCommitPolicy & ZYppCommitPolicy::restrictToMedia( unsigned mediaNr_r ) + { _pimpl->_restrictToMedia = ( mediaNr_r == 1 ) ? 1 : 0; return *this; } + + unsigned ZYppCommitPolicy::restrictToMedia() const + { return _pimpl->_restrictToMedia; } + + + ZYppCommitPolicy & ZYppCommitPolicy::dryRun( bool yesNo_r ) + { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_TEST, yesNo_r ); return *this; } + + bool ZYppCommitPolicy::dryRun() const + { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_TEST );} + + ZYppCommitPolicy & ZYppCommitPolicy::downloadMode( DownloadMode val_r ) + { + if ( singleTransModeEnabled() && val_r == DownloadAsNeeded ) { + DBG << val_r << " is not compatible with singleTransMode, falling back to " << DownloadInAdvance << std::endl; + _pimpl->_downloadMode = DownloadInAdvance; + } + _pimpl->_downloadMode = val_r; return *this; + } + + DownloadMode ZYppCommitPolicy::downloadMode() const + { + if ( singleTransModeEnabled() && _pimpl->_downloadMode == DownloadAsNeeded ) { + DBG << _pimpl->_downloadMode << " is not compatible with singleTransMode, falling back to " << DownloadInAdvance << std::endl; + return DownloadInAdvance; + } + return _pimpl->_downloadMode; + } + + ZYppCommitPolicy & ZYppCommitPolicy::rpmInstFlags( target::rpm::RpmInstFlags newFlags_r ) + { _pimpl->_rpmInstFlags = newFlags_r; return *this; } + + ZYppCommitPolicy & ZYppCommitPolicy::rpmNoSignature( bool yesNo_r ) + { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_NOSIGNATURE, yesNo_r ); return *this; } + + ZYppCommitPolicy & ZYppCommitPolicy::rpmExcludeDocs( bool yesNo_r ) + { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_EXCLUDEDOCS, yesNo_r ); return *this; } + + target::rpm::RpmInstFlags ZYppCommitPolicy::rpmInstFlags() const + { return _pimpl->_rpmInstFlags; } + + bool ZYppCommitPolicy::rpmNoSignature() const + { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_NOSIGNATURE ); } + + bool ZYppCommitPolicy::rpmExcludeDocs() const + { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_EXCLUDEDOCS ); } + + ZYppCommitPolicy &ZYppCommitPolicy::allowDowngrade(bool yesNo_r) + { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_ALLOWDOWNGRADE, yesNo_r ); return *this; } + + bool ZYppCommitPolicy::allowDowngrade() const + { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_ALLOWDOWNGRADE ); } + + ZYppCommitPolicy &ZYppCommitPolicy::replaceFiles( bool yesNo_r ) + { _pimpl->_rpmInstFlags.setFlag( target::rpm::RPMINST_REPLACEFILES, yesNo_r ); return *this; } + + bool ZYppCommitPolicy::replaceFiles( ) const + { return _pimpl->_rpmInstFlags.testFlag( target::rpm::RPMINST_REPLACEFILES ); } + + ZYppCommitPolicy & ZYppCommitPolicy::syncPoolAfterCommit( bool yesNo_r ) + { _pimpl->_syncPoolAfterCommit = yesNo_r; return *this; } + + bool ZYppCommitPolicy::syncPoolAfterCommit() const + { return _pimpl->_syncPoolAfterCommit; } + + bool ZYppCommitPolicy::singleTransModeEnabled() const + { return _pimpl->_singleTransMode; } + + std::ostream & operator<<( std::ostream & str, const ZYppCommitPolicy & obj ) + { + str << "CommitPolicy("; + if ( obj.restrictToMedia() ) + str << " restrictToMedia:" << obj.restrictToMedia(); + if ( obj.dryRun() ) + str << " dryRun"; + str << " " << obj.downloadMode(); + if ( obj.syncPoolAfterCommit() ) + str << " syncPoolAfterCommit"; + if ( obj.rpmInstFlags() ) + str << " rpmInstFlags{" << str::hexstring(obj.rpmInstFlags()) << "}"; + return str << " )"; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ZYppCommitPolicy.h b/zypp/ZYppCommitPolicy.h new file mode 100644 index 0000000..b8c8502 --- /dev/null +++ b/zypp/ZYppCommitPolicy.h @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppCommitPolicy.h + * +*/ +#ifndef ZYPP_ZYPPCOMMITPOLICY_H +#define ZYPP_ZYPPCOMMITPOLICY_H + +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppCommitPolicy + // + /** Options and policies for ZYpp::commit. + * \see \ref ZYpp::commit + */ + class ZYPP_API ZYppCommitPolicy + { + public: + + ZYppCommitPolicy(); + + public: + /** Restrict commit to media 1. + * Fake outstanding YCP fix: Honour restriction to media 1 + * at installation, but install all remaining packages if + * post-boot (called with mediaNr_r > 1). + */ + ZYppCommitPolicy & restrictToMedia( unsigned mediaNr_r ); + + /** Process all media (default) */ + ZYppCommitPolicy & allMedia() + { return restrictToMedia( 0 ); } + + unsigned restrictToMedia() const; + + + /** Set dry run (default: false). + * Dry-run should not change anything on the system, unless + * the \ref downloadMode is set to \ref DownloadOnly. In that + * case packages are downloaded to the local cache. + */ + ZYppCommitPolicy & dryRun( bool yesNo_r ); + + bool dryRun() const; + + + /** Commit download policy to use. (default: \ref DownloadDefault) + * \note \ref DownloadOnly also implies a \ref dryRun. + */ + ZYppCommitPolicy & downloadMode( DownloadMode val_r ); + + DownloadMode downloadMode() const; + + + /** The default \ref target::rpm::RpmInstFlags. (default: none)*/ + ZYppCommitPolicy & rpmInstFlags( target::rpm::RpmInstFlags newFlags_r ); + + /** Use rpm option --nosignature (default: false) */ + ZYppCommitPolicy & rpmNoSignature( bool yesNo_r ); + + /** Use rpm option --excludedocs (default: false) */ + ZYppCommitPolicy & rpmExcludeDocs( bool yesNo_r ); + + target::rpm::RpmInstFlags rpmInstFlags() const; + + bool rpmNoSignature() const; + + bool rpmExcludeDocs() const; + + /** Allow to replace a newer package with an older one (rollback to a older version). */ + ZYppCommitPolicy & allowDowngrade( bool yesNo_r ); + bool allowDowngrade() const; + + /** If enabled it allows installation of packages even if they replace files from other, already installed, packages. */ + ZYppCommitPolicy & replaceFiles( bool yesNo_r ); + bool replaceFiles() const; + + /** Kepp pool in sync with the Target databases after commit (default: true) */ + ZYppCommitPolicy & syncPoolAfterCommit( bool yesNo_r ); + bool syncPoolAfterCommit() const; + + bool singleTransModeEnabled () const; + + public: + /** Implementation */ + class Impl; + private: + /** Pointer to data. */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ZYppCommitPolicy Stream output. */ + std::ostream & operator<<( std::ostream & str, const ZYppCommitPolicy & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ZYPPCOMMITPOLICY_H diff --git a/zypp/ZYppCommitResult.cc b/zypp/ZYppCommitResult.cc new file mode 100644 index 0000000..04379df --- /dev/null +++ b/zypp/ZYppCommitResult.cc @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppCommitResult.cc + * +*/ + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppCommitResult::Impl + // + /////////////////////////////////////////////////////////////////// + + class ZYppCommitResult::Impl + { + public: + Impl() + {} + + public: + Pathname _root; + FalseBool _attemptToModify; + FalseBool _singleTransactionMode; + sat::Transaction _transaction; + TransactionStepList _transactionStepList; + UpdateNotifications _updateMessages; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const { return new Impl( *this ); } + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppCommitResult + // + /////////////////////////////////////////////////////////////////// + + ZYppCommitResult::ZYppCommitResult() + : _pimpl( new Impl ) + {} + + ZYppCommitResult::ZYppCommitResult( const ZYppCommitResult & lhs_r ) + : _pimpl( lhs_r._pimpl ) + {} + + ZYppCommitResult::ZYppCommitResult( const Pathname & root_r ) + : _pimpl( new Impl ) + { _pimpl->_root = root_r; } + + ZYppCommitResult::~ZYppCommitResult() + {} + + const Pathname & ZYppCommitResult::root() const + { return _pimpl->_root; } + + bool ZYppCommitResult::attemptToModify() const + { return _pimpl->_attemptToModify; } + + void ZYppCommitResult::attemptToModify( bool yesno_r ) + { _pimpl->_attemptToModify = yesno_r; } + + bool ZYppCommitResult::singleTransactionMode() const + { return _pimpl->_singleTransactionMode; } + + void ZYppCommitResult::setSingleTransactionMode( bool yesno_r ) + { _pimpl->_singleTransactionMode = yesno_r; } + + const sat::Transaction & ZYppCommitResult::transaction() const + { return _pimpl->_transaction; } + + sat::Transaction & ZYppCommitResult::rTransaction() + { return _pimpl->_transaction; } + + const ZYppCommitResult::TransactionStepList & ZYppCommitResult::transactionStepList() const + { return _pimpl->_transactionStepList; } + + ZYppCommitResult::TransactionStepList & ZYppCommitResult::rTransactionStepList() + { return _pimpl->_transactionStepList; } + + const UpdateNotifications & ZYppCommitResult::updateMessages() const + { return _pimpl->_updateMessages; } + + UpdateNotifications & ZYppCommitResult::rUpdateMessages() + { return _pimpl->_updateMessages; } + + /////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const ZYppCommitResult & obj ) + { + DefaultIntegral result[4]; + for_( it, obj.transaction().actionBegin(), obj.transaction().actionEnd() ) + { + ++result[0]; + switch ( it->stepStage() ) + { + case sat::Transaction::STEP_DONE : ++result[1]; break; + case sat::Transaction::STEP_ERROR : ++result[2]; break; + case sat::Transaction::STEP_TODO : ++result[3]; break; + } + } + str << "CommitResult " + << " (total " << result[0] + << ", done " << result[1] + << ", error " << result[2] + << ", skipped " << result[3] + << ", updateMessages " << obj.updateMessages().size() + << ")"; + return str; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ZYppCommitResult.h b/zypp/ZYppCommitResult.h new file mode 100644 index 0000000..304ab7a --- /dev/null +++ b/zypp/ZYppCommitResult.h @@ -0,0 +1,200 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppCommitResult.h + * +*/ +#ifndef ZYPP_ZYPPCOMMITRESULT_H +#define ZYPP_ZYPPCOMMITRESULT_H + +#include +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace sat + { + class Transaction; + } + + /** Pair of \ref sat::Solvable and \ref Pathname. */ + class UpdateNotificationFile + { + public: + UpdateNotificationFile( sat::Solvable solvable_r, Pathname file_r ) + : _solvable( solvable_r ), _file(std::move( file_r )) + {} + public: + sat::Solvable solvable() const { return _solvable; } + const Pathname & file() const { return _file; } + private: + sat::Solvable _solvable; + Pathname _file; + }; + + using UpdateNotifications = std::list; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppCommitResult + // + /** Result returned from ZYpp::commit. + * + * \note Transaction data are provided and maintained during commit. + * Though the interface does not inhibit manipulation of transaction + * data outside commit (those methods could have been made \c private:), + * this is not recommended as you may easily mess up things. + * + * \see \ref ZYpp::commit + */ + class ZYPP_API ZYppCommitResult + { + public: + using TransactionStepList = std::vector; + + public: + ZYppCommitResult(); + ZYppCommitResult( const ZYppCommitResult & lhs_r ); + ZYppCommitResult( const Pathname & root_r ); + ~ZYppCommitResult(); + + public: + /** Remembered root directory of the target. + * \Note Pathnames within this class are relative to the + * targets root directory. + */ + const Pathname & root() const; + + /** \c True if at least one attempt to actually install/remove packages was made. + * While this is false there should have been no serious modifications to the system. + * Mainly used to detect whether commit failed while preloading the caches or within + * the real action. + */ + bool attemptToModify() const; + + /** Set \ref attemptToModify */ + void attemptToModify( bool yesno_r ); + + /** + * \c True if the commit was executed in one big rpm transaction. This can be used to figure out + * when it is required to show more information about which packages failed during the transaction, + * because otherwise, that information might get lost in the backlog. + */ + bool singleTransactionMode() const; + void setSingleTransactionMode( bool yesno_r ); + + /** The full transaction list. + * The complete list including transaction steps that do not require + * any action (like obsoletes or non-package actions). Depending on + * \ref ZYppCommitPolicy::restrictToMedia only a subset of this + * transaction might have been executed. + * \see \ref transactionStepList. + */ + const sat::Transaction & transaction() const; + + /** Manipulate \ref transaction */ + sat::Transaction & rTransaction(); + + /** List of \ref sat::Transaction::Step to be executed by commit. + * The list of transaction step commit actually tried to execute. + */ + const TransactionStepList & transactionStepList() const; + + /** Manipulate \ref transactionStepList. */ + TransactionStepList & rTransactionStepList(); + + /** List of update messages installed during this commit. + * \Note Pathnames are relative to the targets root directory. + * \code + * ZYppCommitResult result; + * ... + * if ( ! result.updateMessages().empty() ) + * { + * MIL << "Received " << result.updateMessages().size() << " update notification(s):" << endl; + * for_( it, result.updateMessages().begin(), result.updateMessages().end() ) + * { + * MIL << "- From " << it->solvable().asString() << " in file " << Pathname::showRootIf( result.root(), it->file() ) << ":" << endl; + * { + * // store message files content in a string: + * InputStream istr( Pathname::assertprefix( result.root(), it->file() ) ); + * std::ostringstream strstr; + * iostr::copy( istr, strstr ); + * std::string message( strstr.str() ); // contains the message + * } + * { + * // or write out the message file indented: + * InputStream istr( Pathname::assertprefix( result.root(), it->file() ) ); + * iostr::copyIndent( istr, MIL, "> " ) << endl; + * } + * } + * } + * \endcode + */ + const UpdateNotifications & updateMessages() const; + + /** Manipulate \ref updateMessages + * \Note Pathnames are relative to the targets root directory. + */ + UpdateNotifications & rUpdateMessages(); + + public: + + /** \name Some statistics based on \ref Transaction + * + * Class \ref Transaction allows to count and iterate the action steps to + * get more detailed information about the transaction result. Here are just + * a few convenience methods for easy evaluation. + * + * \code + * ZYppCommitResult result; + * const sat::Transaction & trans( result.transaction() ); + * for_( it, trans.actionBegin(~sat::Transaction::STEP_DONE), trans.actionEnd() ) + * { + * // process all steps not DONE (ERROR and TODO) + * if ( it->satSolvable() ) + * std::cout << it->satSolvable() << endl; + * else // deleted @System solvable: print post mortem data available + * std::cout << it->ident() << endl; + * } + * \endcode + * \see \ref Transaction, \ref transaction() + */ + //@{ + /** Whether all steps were performed successfully (none skipped or error) */ + bool allDone() const + { return transaction().actionEmpty( ~sat::Transaction::STEP_DONE ); } + + /** Whether an error ocurred (skipped streps are ok). */ + bool noError() const + { return transaction().actionEmpty( sat::Transaction::STEP_ERROR ); } + //@} + + public: + /** Implementation */ + class Impl; + private: + /** Pointer to data. */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ZYppCommitResult Stream output. */ + std::ostream & operator<<( std::ostream & str, const ZYppCommitResult & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ZYPPCOMMITRESULT_H diff --git a/zypp/ZYppFactory.cc b/zypp/ZYppFactory.cc new file mode 100644 index 0000000..71e1df1 --- /dev/null +++ b/zypp/ZYppFactory.cc @@ -0,0 +1,483 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppFactory.cc + * +*/ +extern "C" +{ +#include +} +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include + +using boost::interprocess::file_lock; +using boost::interprocess::scoped_lock; +using boost::interprocess::sharable_lock; + +using std::endl; + +namespace zyppintern { void repoVariablesReset(); } // upon re-acquiring the lock... + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace sighandler + { + /// Signal handler logging a stack trace + template + class SigBacktraceHandler + { + static void backtraceHandler( int sig ) { + INT << "Error: signal " << SIG << endl << dumpBacktrace << endl; + base::LogControl::instance().emergencyShutdown(); + ::signal( SIG, lastSigHandler ); + } + static ::sighandler_t lastSigHandler; + }; + template + ::sighandler_t SigBacktraceHandler::lastSigHandler { ::signal( SIG, SigBacktraceHandler::backtraceHandler ) }; + + // Explicit instantiation installs the handler: + template class SigBacktraceHandler; + template class SigBacktraceHandler; + } + + namespace env + { + /** Hack to circumvent the currently poor --root support. */ + inline Pathname ZYPP_LOCKFILE_ROOT() + { return getenv("ZYPP_LOCKFILE_ROOT") ? getenv("ZYPP_LOCKFILE_ROOT") : "/"; } + } + + /////////////////////////////////////////////////////////////////// + namespace zypp_readonly_hack + { ///////////////////////////////////////////////////////////////// + + static bool active = getenv("ZYPP_READONLY_HACK"); + + ZYPP_API void IWantIt() // see zypp/zypp_detail/ZYppReadOnlyHack.h + { + active = true; + MIL << "ZYPP_READONLY promised." << endl; + } + + bool IGotIt() + { + return active; + } + + ///////////////////////////////////////////////////////////////// + } // namespace zypp_readonly_hack + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class ZYppGlobalLock + /// \brief Our broken global lock + /// + /////////////////////////////////////////////////////////////////// + class ZYppGlobalLock + { + public: + ZYppGlobalLock(Pathname &&lFilePath) + : _zyppLockFilePath(std::move(lFilePath)), _zyppLockFile(NULL), + _lockerPid(0), _cleanLock(false) { + filesystem::assert_dir(_zyppLockFilePath.dirname() ); + } + + ZYppGlobalLock(const ZYppGlobalLock &) = delete; + ZYppGlobalLock(ZYppGlobalLock &&) = delete; + ZYppGlobalLock &operator=(const ZYppGlobalLock &) = delete; + ZYppGlobalLock &operator=(ZYppGlobalLock &&) = delete; + + ~ZYppGlobalLock() + { + if ( _cleanLock ) + try { + // Exception safe access to the lockfile. + ScopedGuard closeOnReturn( accessLockFile() ); + { + scoped_lock flock( _zyppLockFileLock ); // aquire write lock + // Truncate the file rather than deleting it. Other processes may + // still use it to synchronsize. + ftruncate( fileno(_zyppLockFile), 0 ); + } + MIL << "Cleaned lock file. (" << getpid() << ")" << std::endl; + } + catch(...) {} // let no exception escape. + } + + pid_t lockerPid() const + { return _lockerPid; } + + const std::string & lockerName() const + { return _lockerName; } + + const Pathname & zyppLockFilePath() const + { return _zyppLockFilePath; } + + + private: + Pathname _zyppLockFilePath; + file_lock _zyppLockFileLock; + FILE * _zyppLockFile; + + pid_t _lockerPid; + std::string _lockerName; + bool _cleanLock; + + private: + using ScopedGuard = shared_ptr; + + /** Exception safe access to the lockfile. + * \code + * // Exception safe access to the lockfile. + * ScopedGuard closeOnReturn( accessLockFile() ); + * \endcode + */ + ScopedGuard accessLockFile() + { + _openLockFile(); + return ScopedGuard( static_cast(0), + std::bind( std::mem_fn( &ZYppGlobalLock::_closeLockFile ), this ) ); + } + + /** Use \ref accessLockFile. */ + void _openLockFile() + { + if ( _zyppLockFile != NULL ) + return; // is open + + // open pid file rw so we are sure it exist when creating the flock + _zyppLockFile = fopen( _zyppLockFilePath.c_str(), "a+" ); + if ( _zyppLockFile == NULL ) + ZYPP_THROW( Exception( "Cant open " + _zyppLockFilePath.asString() ) ); + _zyppLockFileLock = _zyppLockFilePath.c_str(); + MIL << "Open lockfile " << _zyppLockFilePath << endl; + } + + /** Use \ref accessLockFile. */ + void _closeLockFile() + { + if ( _zyppLockFile == NULL ) + return; // is closed + + clearerr( _zyppLockFile ); + fflush( _zyppLockFile ); + // http://www.boost.org/doc/libs/1_50_0/doc/html/interprocess/synchronization_mechanisms.html + // If you are using a std::fstream/native file handle to write to the file + // while using file locks on that file, don't close the file before releasing + // all the locks of the file. + _zyppLockFileLock = file_lock(); + fclose( _zyppLockFile ); + _zyppLockFile = NULL; + MIL << "Close lockfile " << _zyppLockFilePath << endl; + } + + + bool isProcessRunning( pid_t pid_r ) + { + // it is another program, not me, see if it is still running + Pathname procdir( Pathname("/proc")/str::numstring(pid_r) ); + PathInfo status( procdir ); + MIL << "Checking " << status << endl; + + if ( ! status.isDir() ) + { + DBG << "No such process." << endl; + return false; + } + + static char buffer[513]; + buffer[0] = buffer[512] = 0; + // man proc(5): /proc/[pid]/cmdline is empty if zombie. + if ( std::ifstream( (procdir/"cmdline").c_str() ).read( buffer, 512 ).gcount() > 0 ) + { + _lockerName = buffer; + DBG << "Is running: " << _lockerName << endl; + return true; + } + + DBG << "In zombie state." << endl; + return false; + } + + pid_t readLockFile() + { + clearerr( _zyppLockFile ); + fseek( _zyppLockFile, 0, SEEK_SET ); + long readpid = 0; + fscanf( _zyppLockFile, "%ld", &readpid ); + MIL << "read: Lockfile " << _zyppLockFilePath << " has pid " << readpid << " (our pid: " << getpid() << ") "<< std::endl; + return (pid_t)readpid; + } + + void writeLockFile() + { + clearerr( _zyppLockFile ); + fseek( _zyppLockFile, 0, SEEK_SET ); + ftruncate( fileno(_zyppLockFile), 0 ); + fprintf(_zyppLockFile, "%ld\n", (long)getpid() ); + fflush( _zyppLockFile ); + _cleanLock = true; // cleanup on exit + MIL << "write: Lockfile " << _zyppLockFilePath << " got pid " << getpid() << std::endl; + } + + /*! + * Expects the calling function to lock the access lock + */ + bool safeCheckIsLocked() + { + _lockerPid = readLockFile(); + if ( _lockerPid == 0 ) { + // no or empty lock file + return false; + } else if ( _lockerPid == getpid() ) { + // keep my own lock + return false; + } else { + // a foreign pid in lock + if ( isProcessRunning( _lockerPid ) ) { + WAR << _lockerPid << " is running and has a ZYpp lock. Sorry." << std::endl; + return true; + } else { + MIL << _lockerPid << " is dead. Ignoring the existing lock file." << std::endl; + return false; + } + } + } + + public: + + bool isZyppLocked() + { + if ( geteuid() != 0 ) + return false; // no lock as non-root + + // Exception safe access to the lockfile. + ScopedGuard closeOnReturn( accessLockFile() ); + scoped_lock flock( _zyppLockFileLock ); // aquire write lock + return safeCheckIsLocked (); + } + + /** Try to aquire a lock. + * \return \c true if zypp is already locked by another process. + */ + bool zyppLocked() + { + if ( geteuid() != 0 ) + return false; // no lock as non-root + + // Exception safe access to the lockfile. + ScopedGuard closeOnReturn( accessLockFile() ); + scoped_lock flock( _zyppLockFileLock ); // aquire write lock + if ( !safeCheckIsLocked() ) { + writeLockFile(); + return false; + } + return true; + } + + }; + + /////////////////////////////////////////////////////////////////// + namespace + { + static weak_ptr _theZYppInstance; + static scoped_ptr _theGlobalLock; // on/off in sync with _theZYppInstance + + ZYppGlobalLock & globalLock() + { + if ( !_theGlobalLock ) + _theGlobalLock.reset( new ZYppGlobalLock( ZYppFactory::lockfileDir() / "zypp.pid" ) ); + return *_theGlobalLock; + } + } //namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYpp + // + /////////////////////////////////////////////////////////////////// + + ZYpp::ZYpp( const Impl_Ptr & impl_r ) + : _pimpl( impl_r ) + { + ::zyppintern::repoVariablesReset(); // upon re-acquiring the lock... + MIL << "ZYpp is on..." << endl; + } + + ZYpp::~ZYpp() + { + _theGlobalLock.reset(); + MIL << "ZYpp is off..." << endl; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppFactoryException + // + /////////////////////////////////////////////////////////////////// + + ZYppFactoryException::ZYppFactoryException( std::string msg_r, pid_t lockerPid_r, std::string lockerName_r ) + : Exception( std::move(msg_r) ) + , _lockerPid( lockerPid_r ) + , _lockerName(std::move( lockerName_r )) + {} + + ZYppFactoryException::~ZYppFactoryException() throw () + {} + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppFactory + // + /////////////////////////////////////////////////////////////////// + + ZYppFactory ZYppFactory::instance() + { return ZYppFactory(); } + + ZYppFactory::ZYppFactory() + {} + + ZYppFactory::~ZYppFactory() + {} + + /////////////////////////////////////////////////////////////////// + // + ZYpp::Ptr ZYppFactory::getZYpp() const + { + + const auto &makeLockedError = []( pid_t pid, const std::string &lockerName ){ + const std::string &t = str::form(_("System management is locked by the application with pid %d (%s).\n" + "Close this application before trying again."), pid, lockerName.c_str() ); + return ZYppFactoryException(t, pid, lockerName ); + }; + + ZYpp::Ptr _instance = _theZYppInstance.lock(); + if ( ! _instance ) + { + if ( geteuid() != 0 ) + { + MIL << "Running as user. Skip creating " << globalLock().zyppLockFilePath() << std::endl; + } + else if ( zypp_readonly_hack::active ) + { + MIL << "ZYPP_READONLY active." << endl; + } + else if ( globalLock().zyppLocked() ) + { + bool failed = true; + // bsc#1184399,1213231: A negative ZYPP_LOCK_TIMEOUT will wait forever. + const long LOCK_TIMEOUT = str::strtonum( getenv( "ZYPP_LOCK_TIMEOUT" ) ); + if ( LOCK_TIMEOUT != 0 ) + { + Date logwait = Date::now(); + Date giveup; /* 0 = forever */ + if ( LOCK_TIMEOUT > 0 ) { + giveup = logwait+LOCK_TIMEOUT; + MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Waiting for the zypp lock until " << giveup << endl; + } + else + MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Waiting for the zypp lock..." << endl; + + unsigned delay = 0; + do { + if ( delay < 60 ) + delay += 1; + else { + Date now { Date::now() }; + if ( now - logwait > Date::day ) { + WAR << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Another day has passed waiting for the zypp lock..." << endl; + logwait = now; + } + } + sleep( delay ); + { + zypp::base::LogControl::TmpLineWriter shutUp; // be quiet + failed = globalLock().zyppLocked(); + } + } while ( failed && ( not giveup || Date::now() <= giveup ) ); + + if ( failed ) { + MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Gave up waiting for the zypp lock." << endl; + } + else { + MIL << "$ZYPP_LOCK_TIMEOUT=" << LOCK_TIMEOUT << " sec. Finally got the zypp lock." << endl; + } + } + if ( failed ) + ZYPP_THROW( makeLockedError( globalLock().lockerPid(), globalLock().lockerName() )); + + // we got the global lock, now make sure zypp-rpm is not still running + { + ZYppGlobalLock zyppRpmLock( ZYppFactory::lockfileDir() / "zypp-rpm.pid" ); + if ( zyppRpmLock.isZyppLocked () ) { + // release global lock, we will exit now + _theGlobalLock.reset(); + ZYPP_THROW( makeLockedError( zyppRpmLock.lockerPid(), zyppRpmLock.lockerName() )); + } + } + } + + // Here we go... + static ZYpp::Impl_Ptr _theImplInstance; // for now created once + if ( !_theImplInstance ) + _theImplInstance.reset( new ZYpp::Impl ); + _instance.reset( new ZYpp( _theImplInstance ) ); + _theZYppInstance = _instance; + } + + return _instance; + } + + /////////////////////////////////////////////////////////////////// + // + bool ZYppFactory::haveZYpp() const + { return !_theZYppInstance.expired(); } + + zypp::Pathname ZYppFactory::lockfileDir() + { + return env::ZYPP_LOCKFILE_ROOT() / "run"; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj ) + { + return str << "ZYppFactory"; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ZYppFactory.h b/zypp/ZYppFactory.h new file mode 100644 index 0000000..847a48a --- /dev/null +++ b/zypp/ZYppFactory.h @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ZYppFactory.h + * +*/ +#ifndef ZYPP_ZYPPFACTORY_H +#define ZYPP_ZYPPFACTORY_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class ZYPP_API ZYppFactoryException : public Exception + { + public: + ZYppFactoryException( std::string msg_r, pid_t lockerPid_r, std::string lockerName_r ); + ~ZYppFactoryException() throw () override; + public: + pid_t lockerPid() const { return _lockerPid; } + const std::string & lockerName() const { return _lockerName; } + private: + pid_t _lockerPid; + std::string _lockerName; + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppFactory + // + /** ZYpp factory class (Singleton) + */ + class ZYPP_API ZYppFactory + { + friend std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj ); + + public: + /** Singleton ctor */ + static ZYppFactory instance(); + /** Dtor */ + ~ZYppFactory(); + + public: + /** \return Pointer to the ZYpp instance. + * \throw EXCEPTION In case we can't acquire a lock. + */ + ZYpp::Ptr getZYpp() const; + + /** Whether the ZYpp instance is already created.*/ + bool haveZYpp() const; + + static zypp::Pathname lockfileDir (); + + private: + /** Default ctor. */ + ZYppFactory(); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ZYppFactory Stream output */ + std::ostream & operator<<( std::ostream & str, const ZYppFactory & obj ); + + /** \relates ZYppFactory Convenience to get the Pointer + * to the ZYpp instance. + * \see ZYppFactory::getZYpp + */ + inline ZYpp::Ptr getZYpp() + { return ZYppFactory::instance().getZYpp(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ZYPPFACTORY_H diff --git a/zypp/base/Algorithm.h b/zypp/base/Algorithm.h new file mode 100644 index 0000000..f5fb661 --- /dev/null +++ b/zypp/base/Algorithm.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Algorithm.h + * +*/ +#ifndef ZYPP_BASE_ALGORITHM_H +#define ZYPP_BASE_ALGORITHM_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Iterate through [begin_r,end_r) and invoke \a fnc_r + * on each item that passes \a filter_r. + * + * Iteration aborts if \a fnc_r returns \c false. + * + * \return Number of invokations of \a fnc_r, negative if + * loop was aborted by \a fnc_. + */ + template + inline int invokeOnEach( TIterator begin_r, TIterator end_r, + TFilter filter_r, + TFunction fnc_r ) + { + int cnt = 0; + for ( TIterator it = begin_r; it != end_r; ++it ) + { + if ( filter_r( *it ) ) + { + ++cnt; + if ( ! fnc_r( *it ) ) + return -cnt; + } + } + return cnt; + } + + /** Iterate through [begin_r,end_r) and invoke \a fnc_r + * on each item. + * + * Iteration aborts if \a fnc_r returns \c false. + * + * \return Number of invokations of \a fnc_r, negative if + * loop was aborted by \a fnc_. + */ + template + inline int invokeOnEach( TIterator begin_r, TIterator end_r, + TFunction fnc_r ) + { + int cnt = 0; + for ( TIterator it = begin_r; it != end_r; ++it ) + { + ++cnt; + if ( ! fnc_r( *it ) ) + return -cnt; + } + return cnt; + } + + template + bool contains ( const Container &c, const Elem &elem ) + { + return ( std::find( c.begin(), c.end(), elem ) != c.end() ); + } + + template + bool any_of ( const Container &c, Fnc &&cb ) + { + return std::any_of( c.begin(), c.end(), std::forward(cb) ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_ALGORITHM_H diff --git a/zypp/base/Backtrace.cc b/zypp/base/Backtrace.cc new file mode 100644 index 0000000..a97a156 --- /dev/null +++ b/zypp/base/Backtrace.cc @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Backtrace.cc + */ +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + std::ostream & dumpBacktrace( std::ostream & stream_r ) + { + // get void*'s for all entries on the stack + static const size_t arraySize = 50; + void *array[arraySize]; + size_t size = ::backtrace( array, arraySize ); + + // Print out all frames to stderr. Separate sigsegvHandler stack + // [dumpBacktrace][sigsegvHandler][libc throwing] from actual + // code stack. + char ** messages = ::backtrace_symbols( array, size ); + if ( messages ) + { + static const size_t handlerStack = 3; // [dumpBacktrace][sigsegvHandler][libc throwing] + static const size_t first = 0; + for ( size_t i = first; i < size; ++i ) + { + char * mangled_name = 0; + char * offset_begin = 0; + char * offset_end = 0; + + // find parentheses and +address offset surrounding mangled name + for ( char * p = messages[i]; *p; ++p ) + { + if ( *p == '(' ) + { + mangled_name = p; + } + else if ( *p == '+' ) + { + offset_begin = p; + } + else if ( *p == ')' ) + { + offset_end = p; + break; + } + } + + int btLevel = i-handlerStack; // negative level in sigsegvHandler + if ( i > first ) + { + stream_r << endl; + if ( btLevel == 0 ) + stream_r << "vvvvvvvvvv----------------------------------------" << endl; + } + stream_r << "[" << (btLevel<0 ?"hd":"bt") << "]: (" << btLevel << ") "; + + // if the line could be processed, attempt to demangle the symbol + if ( mangled_name && offset_begin && offset_end && mangled_name < offset_begin ) + { + *mangled_name++ = '\0'; + *offset_begin++ = '\0'; + *offset_end++ = '\0'; + + int status = 0; + char * real_name = ::abi::__cxa_demangle( mangled_name, 0, 0, &status ); + + // if demangling is successful, output the demangled function name + if ( status == 0 ) + { + stream_r << messages[i] << " : " << real_name << "+" << offset_begin << offset_end; + } + // otherwise, output the mangled function name + else + { + stream_r << messages[i] << " : " << mangled_name << "+" << offset_begin << offset_end; + } + ::free( real_name ); + } + else + { + // otherwise, print the whole line + stream_r << messages[i]; + } + } + ::free( messages ); + } + return stream_r; + } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/base/Backtrace.h b/zypp/base/Backtrace.h new file mode 100644 index 0000000..6ead58e --- /dev/null +++ b/zypp/base/Backtrace.h @@ -0,0 +1,38 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Backtrace.h + */ +#ifndef ZYPP_BASE_BACKTRACE_H +#define ZYPP_BASE_BACKTRACE_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + + /** Dump current stack trace to a stream. + * Thanks to http://stackoverflow.com/questions/77005. + * \code + * #include + * std::cerr << zypp::dumpBacktrace << std::endl; + * \endcode + * \code + * #include + * std::string trace( str::Str() << zypp::dumpBacktrace ); + * \endcode + */ + std::ostream & dumpBacktrace( std::ostream & stream_r ) ZYPP_API; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_BACKTRACE_H diff --git a/zypp/base/Collector.h b/zypp/base/Collector.h new file mode 100644 index 0000000..37a87d9 --- /dev/null +++ b/zypp/base/Collector.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Collector.h + * +*/ +#ifndef ZYPP_BASE_COLLECTOR_H +#define ZYPP_BASE_COLLECTOR_H + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace functor +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Collector + // + /** Functor feeding values to an output_iterator. + * + * \code + * LocaleSet locales; + * for_each( begin(), end(), + * collector( std::inserter( locales_r, locales_r.begin() ) ) ); + * \endcode + * + * \see Convenience constructor \ref collector. + */ + template + struct Collector + { + Collector( TOutputIterator iter_r ) : _iter( iter_r ) {} + + template + bool operator()( const Tp & value_r ) const + { + *_iter++ = value_r; + return true; + } + + private: + mutable TOutputIterator _iter; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Collector Convenience constructor. */ + template + inline Collector collector( TOutputIterator iter_r ) + { return Collector( iter_r ); } + + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace functor +/////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_COLLECTOR_H diff --git a/zypp/base/Counter.h b/zypp/base/Counter.h new file mode 100644 index 0000000..a22a889 --- /dev/null +++ b/zypp/base/Counter.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Counter.h + * +*/ +#ifndef ZYPP_BASE_COUNTER_H +#define ZYPP_BASE_COUNTER_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Counter + // + /** Integral type with initial value \c 0. + */ + template + class Counter + { + public: + Counter( TInt value_r = TInt(0) ) + : _value( TInt( value_r ) ) + {} + + operator TInt &() + { return _value; } + + operator const TInt &() const + { return _value; } + + public: + TInt _value; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_COUNTER_H diff --git a/zypp/base/Debug.h b/zypp/base/Debug.h new file mode 100644 index 0000000..2b2b017 --- /dev/null +++ b/zypp/base/Debug.h @@ -0,0 +1,185 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Debug.h + * + * Debuging tools which should not be used in released code. +*/ +#ifndef ZYPP_NDEBUG +#warning ZYPP_BASE_DEBUG_H included +#ifndef ZYPP_BASE_DEBUG_H +#define ZYPP_BASE_DEBUG_H + +#include +//#include +//#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace debug + { ///////////////////////////////////////////////////////////////// + + /** \defgroup DEBUG Debug tools + */ + +#define TAG INT << __PRETTY_FUNCTION__ << std::endl + + /** 'ps v' */ + inline std::ostream & dumpMemOn( std::ostream & str, const std::string & msg = std::string() ) + { + static std::string mypid( str::numstring( getpid() ) ); + const char* argv[] = + { + "ps", + "v", + mypid.c_str(), + NULL + }; + ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); + + str << "MEMUSAGE " << msg << std::endl; + for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() ) + str << line; + + prog.close(); + return str; + } + + /////////////////////////////////////////////////////////////////// + /** \defgroup DBG_TRACER Tracer + * \ingroup DEBUG + */ + //@{ + /** Base for a simple tracer. Provides an enum indicating which + * traced functions were called. + */ + struct TraceCADBase + { + enum What { CTOR, COPYCTOR, MOVECTOR, ASSIGN, MOVEASSIGN, DTOR, PING }; + std::string _ident; + }; + + /** \relates TraceCADBase Stream output of TraceCADBase::What. */ + inline std::ostream & operator<<( std::ostream & str, TraceCADBase::What obj ) + { + switch( obj ) + { + case TraceCADBase::CTOR: return str << "CTOR"; + case TraceCADBase::COPYCTOR: return str << "COPYCTOR"; + case TraceCADBase::MOVECTOR: return str << "MOVECTOR"; + case TraceCADBase::ASSIGN: return str << "ASSIGN"; + case TraceCADBase::MOVEASSIGN: return str << "MOVEASSIGN"; + case TraceCADBase::DTOR: return str << "DTOR"; + case TraceCADBase::PING: return str << "PING"; + } + return str; + } + + /** A simple tracer for (copy) Construction, Assignment, and + * Destruction. To trace class Foo, derive public from + * TraceCAD. This tracer simply calls traceCAD in each + * traced method, and traceCAD simply drops a line in the log. + * + * This tracer logs construction, copy construction, assignment, + * destruction and ping. + * + * assignment: In case the traced class defines an operator= + * it must be altered to call TraceCAD::operator=, otherwise it + * won't be triggered. + * + * ping: Completely up to you. Call ping somewhere in the traced + * class to indicate something. In case you overload traceCAD, do + * whatever is appropriate on ping. It's just an offer to perform + * logging or actions here, and not in the traced code. + * + * But traceCAD may be overloaded to produce more stats. + * + * \see \c Example.COW_debug.cc. + */ + template + struct TraceCAD : public base::ProvideNumericId, unsigned long> + , public TraceCADBase + { + static unsigned long & _totalTraceCAD() + { static unsigned long _val = 0; + return _val; } + + TraceCAD() + { _ident = __PRETTY_FUNCTION__; + ++_totalTraceCAD(); + traceCAD( CTOR, *this, *this ); } + + TraceCAD( const TraceCAD & rhs ) + { ++_totalTraceCAD(); + traceCAD( COPYCTOR, *this, rhs ); } + + TraceCAD( TraceCAD && rhs ) noexcept + { ++_totalTraceCAD(); + traceCAD( MOVECTOR, *this, rhs ); } + + TraceCAD & operator=( const TraceCAD & rhs ) + { traceCAD( ASSIGN, *this, rhs ); return *this; } + + TraceCAD & operator=( TraceCAD && rhs ) noexcept + { traceCAD( MOVEASSIGN, *this, rhs ); return *this; } + + virtual ~TraceCAD() + { --_totalTraceCAD(); + traceCAD( DTOR, *this, *this ); } + + void ping() const + { traceCAD( PING, *this, *this ); } + }; + + /** \relates TraceCAD Stream output. */ + template + inline std::ostream & operator<<( std::ostream & str, const TraceCAD & obj ) + { return str << "(ID " << obj.numericId() << ", TOTAL " << obj._totalTraceCAD() + << ") [" << &obj << "] "; } + + /** Drop a log line about the traced method. Overload to + * fit your needs. + */ + template + void traceCAD( TraceCADBase::What what_r, + const TraceCAD & self_r, + const TraceCAD & rhs_r ) + { + switch( what_r ) + { + case TraceCADBase::CTOR: + case TraceCADBase::PING: + case TraceCADBase::DTOR: + L_DBG("DEBUG") << what_r << self_r << " (" << self_r._ident << ")" << std::endl; + break; + + case TraceCADBase::COPYCTOR: + case TraceCADBase::MOVECTOR: + case TraceCADBase::ASSIGN: + case TraceCADBase::MOVEASSIGN: + L_DBG("DEBUG") << what_r << self_r << "( " << rhs_r << ")" << " (" << self_r._ident << ")" << std::endl; + break; + } + } + //@} + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace debug + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_DEBUG_H +#endif // ZYPP_NDEBUG diff --git a/zypp/base/DefaultIntegral.h b/zypp/base/DefaultIntegral.h new file mode 100644 index 0000000..91edf2d --- /dev/null +++ b/zypp/base/DefaultIntegral.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/DrunkenBishop.cc b/zypp/base/DrunkenBishop.cc new file mode 100644 index 0000000..e7c2118 --- /dev/null +++ b/zypp/base/DrunkenBishop.cc @@ -0,0 +1,409 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/DrunkenBishop.cc + */ +#include +#include +//#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace base + { + /////////////////////////////////////////////////////////////////// + namespace + { + /** Direction the drunken Bishop wants to move. */ + enum class Direction : std::uint8_t // actually 2 bits + { + NW = 0x0, + NE = 0x1, + SW = 0x2, + SE = 0x3, + }; + + /** Convert a hex digit (case insensitive) into its (4bit) integral value. + * \throws std::invalid_argument if char + */ + inline std::uint8_t hexDigit( char ch_r ) + { + switch ( ch_r ) + { + case 'F': case 'f': return 15; + case 'E': case 'e': return 14; + case 'D': case 'd': return 13; + case 'C': case 'c': return 12; + case 'B': case 'b': return 11; + case 'A': case 'a': return 10; + case '9': return 9; + case '8': return 8; + case '7': return 7; + case '6': return 6; + case '5': return 5; + case '4': return 4; + case '3': return 3; + case '2': return 2; + case '1': return 1; + case '0': return 0; + } + throw std::invalid_argument( str::Str() << "Not a hex digit '" << ch_r << "'" ); + } + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class DrunkenBishop::Impl + /// \brief DrunkenBishop implementation. + /////////////////////////////////////////////////////////////////// + class DrunkenBishop::Impl : private base::NonCopyable + { + public: + /** Default is an empty board. */ + Impl() + : _h( 0U ) + , _w( 0u ) + , _s( 0U ) + , _e( 0U ) + , _renderSSH( true ) + {} + + /** Build up a new board. + * \throws std::invalid_argument + */ + void compute( const std::string & data_r, const std::string & title_r, unsigned height_r = Auto, unsigned width_r = Auto ) + { + // store rendering details + _renderSSH = ( data_r.size() <= 32 ); // up to the ssh fingerprint size + _fp = str::toUpper( data_r.size() <= 8 ? data_r : data_r.substr( data_r.size()-8 ) ); + _tt = title_r; + + // init the board + _h = odd(height_r); + _w = odd(width_r); + + if ( _h == Auto ) + { + if ( _renderSSH ) + { _w = 17; _h = 9; } + else + { _w = 19; _h = 11; } + } + else if ( _w == Auto ) + { + _w = (2*_h)-1; + } + + _board = std::vector( _w*_h, 0 ); + _s = _w*_h/2; // start + _e = _s; // current/end + ++_board[_e]; + + // go + for ( const char * ch = data_r.c_str(); *ch; /*NOOP*/ ) + { + std::uint8_t next4 = bite( ch ); + // next4: 0x94 + // bits: 10 01 01 00 + // step: 4 3 2 1 + static const std::uint8_t stepMask(0x3); + move( Direction( next4 & stepMask ) ); + move( Direction( (next4>>2) & stepMask ) ); + move( Direction( (next4>>4) & stepMask ) ); + move( Direction( (next4>>6) ) ); + } + } + + /** Render board to a stream. */ + std::ostream & dumpOn( std::ostream & str, const std::string & prefix_r, Options options_r ) const + { + if ( _board.empty() ) + { + // "++\n" + // "++" + return str << prefix_r << "++" << endl << prefix_r << "++"; + } + + static const char * colorReset = "\033[0m"; + static const char * colorBg = "\033[48;5;242m"; + bool useColor = options_r.testFlag( USE_COLOR ); + + renderTitleOn( str << prefix_r , _tt ); + + for ( unsigned p = 0; p < _board.size(); ++p ) + { + if ( ( p % _w ) == 0 ) + { + if ( p ) + str << ( useColor ? colorReset: "" ) << '|'; + str << endl << prefix_r << '|' << ( useColor ? colorBg : "" ); + } + renderOn( str, useColor, p ); + } + str << ( useColor ? colorReset: "" ) << '|'; + + renderTitleOn( str << endl << prefix_r, _fp ); + return str; + } + + private: + /** Increment even width/height values. */ + static unsigned odd( unsigned val_r ) + { return( val_r == Auto ? val_r : val_r|1U ); } + + /** Get next 4 moves (8 bit) from next 2 hex digits (1st digit != '\0' asserted, 0-pad if necessary). + * \throws std::invalid_argument if char is not a hex digit or 1st char is \c \0 + */ + static std::uint8_t bite( const char *& ch_r ) + { + std::uint8_t ret = hexDigit( *ch_r ) << 4; + if ( *(++ch_r) ) + ret |= hexDigit( *(ch_r++) ); + return ret; + } + + private: + /** Move Bishop from \ref _e into \a direction_r and update the \ref _board. */ + void move( Direction direction_r ) + { + switch ( direction_r ) + { + case Direction::NW: + if ( atTL() ) + /*no move*/; + else if ( atT() ) + _e -= 1; + else if ( atL() ) + _e -= _w; + else + _e -= _w+1; + break; + + case Direction::NE: + if ( atTR() ) + /*no move*/; + else if ( atT() ) + _e += 1; + else if ( atR() ) + _e -= _w; + else + _e -= _w-1; + break; + + case Direction::SW: + if ( atBL() ) + /*no move*/; + else if ( atB() ) + _e -= 1; + else if ( atL() ) + _e += _w; + else + _e += _w-1; + break; + + case Direction::SE: + if ( atBR() ) + /*no move*/; + else if ( atB() ) + _e += 1; + else if ( atR() ) + _e += _w; + else + _e += _w+1; + break; + + default: + throw std::invalid_argument( str::Str() << "Bad Direction " << unsigned(direction_r) ); + } + // update the board + ++_board[_e]; + } + + /** Whether \ref _e is in the top left corner. */ + bool atTL() const + { return( _e == 0 ); } + + /** Whether \ref _e is in the top right corner. */ + bool atTR() const + { return( _e == _w-1 ); } + + /** Whether \ref _e is in the bottom left corner. */ + bool atBL() const + { return( _e == _board.size()-_w ); } + + /** Whether \ref _e is in the bottom right corner. */ + bool atBR() const + { return( _e == _board.size()-1 ); } + + /** Whether \ref _e is in the top row. */ + bool atT() const + { return( _e < _w ); } + + /** Whether \ref _e is in the bottom row. */ + bool atB() const + { return( _e >= _board.size()-_w ); } + + /** Whether \ref _e is in the left column. */ + bool atL() const + { return( ( _e % _w ) == 0 ); } + + /** Whether \ref _e is in the right column. */ + bool atR() const + { return( ( _e % _w ) == (_w-1) ); } + + private: + /** ANSI color heatmap. */ + const char * color( std::uint8_t idx_r ) const + { + static const std::vector colors = { + "", // no coin + "\033[38;5;21m", // blue (cold) + "\033[38;5;39m", + "\033[38;5;50m", + "\033[38;5;48m", + "\033[38;5;46m", // green + "\033[38;5;118m", + "\033[38;5;190m", + "\033[38;5;226m", // yellow + "\033[38;5;220m", + "\033[38;5;214m", // orange + "\033[38;5;208m", + "\033[38;5;202m", + "\033[38;5;196m", // red + "\033[38;5;203m", + "\033[38;5;210m", + "\033[38;5;217m", // pink + "\033[38;5;224m", + "\033[38;5;231m", // white (hot) + }; +#if 0 + // cycle through heat map to test all colors + if ( ! idx_r ) + return ""; + static unsigned i = 0; + if ( ++i == colors.size() ) + i = 1; + return colors[i]; +#endif + return ( idx_r < colors.size() ? colors[idx_r] : *colors.rbegin() ); + } + + /** Render non empty title strings */ + std::ostream & renderTitleOn( std::ostream & str, const std::string & title_r ) const + { + std::string buffer( _w+2, '-' ); + *buffer.begin() = *buffer.rbegin() = '+'; + + if ( !title_r.empty() && _w >= 2 ) // extra 2 for "[]" + { + std::string::size_type tlen = std::min( title_r.size(), std::string::size_type(_w-2) ); + std::string::size_type tpos = (_w-tlen)/2; // not (_w-2-tlen) because buffer is size _w+2 + buffer[tpos++] = '['; + for ( std::string::size_type p = 0; p < tlen; ++p, ++tpos ) + buffer[tpos] = title_r[p]; + buffer[tpos] = ']'; + } + return str << buffer; + } + + /** Render board numbers to printable chars. */ + std::ostream & renderOn( std::ostream & str, bool useColor_r, unsigned pos_r ) const + { + static const std::string sshSet( " .o+=*BOX@%&#/^" ); + static const std::string gpgSet( " .^:li?(fxXZ#MW&8%@" ); + const std::string & charSet( _renderSSH ? sshSet : gpgSet ); + + if ( useColor_r ) + str << color( _board[pos_r] ); + + if ( pos_r == _e ) + return str << 'E'; + + if ( pos_r == _s ) + return str << 'S'; + + return str << ( _board[pos_r] < charSet.size() ? charSet[_board[pos_r]] : *charSet.rbegin() ); + } + + private: + /** Request default width/height values. */ + static constexpr const unsigned Auto = unsigned(-1); + + private: + std::vector _board; ///< the board + unsigned _h; ///< board height + unsigned _w; ///< board with + unsigned _s; ///< start position + unsigned _e; ///< end position + + private: + bool _renderSSH; ///< whether to render the ssh (or gpg) char set + std::string _fp; ///< fingerprint to render as bottom title + std::string _tt; ///< text to render as top title + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + }; + + /////////////////////////////////////////////////////////////////// + // CLASS NAME : DrunkenBishop + /////////////////////////////////////////////////////////////////// + + DrunkenBishop::DrunkenBishop() + : _pimpl( Impl::nullimpl() ) + { /*nothing to compute*/ } + + DrunkenBishop::DrunkenBishop( const std::string & data_r, const std::string & title_r ) + : _pimpl( new Impl ) + { _pimpl->compute( data_r, title_r ); } + + DrunkenBishop::DrunkenBishop( const std::string & data_r, const std::string & title_r, unsigned height_r ) + : _pimpl( new Impl ) + { _pimpl->compute( data_r, title_r, height_r ); } + + DrunkenBishop::DrunkenBishop( const std::string & data_r, const std::string & title_r, unsigned height_r, unsigned width_r ) + : _pimpl( new Impl ) + { _pimpl->compute( data_r, title_r, height_r, width_r ); } + + DrunkenBishop::~DrunkenBishop() + {} + + std::ostream & DrunkenBishop::dumpOn( std::ostream & str, const std::string & prefix_r, Options options_r ) const + { return _pimpl->dumpOn( str, prefix_r, options_r ); } + + std::string DrunkenBishop::asString( const std::string & prefix_r, Options options_r ) const + { + std::ostringstream str; + dumpOn( str, prefix_r, options_r ); + return str.str(); + } + + std::vector DrunkenBishop::asLines( const std::string & prefix_r, Options options_r ) const + { + std::vector ret; + str::split( asString( prefix_r, options_r ), std::back_inserter(ret), "\n" ); + return ret; + } + + } // namespace base + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/base/DrunkenBishop.h b/zypp/base/DrunkenBishop.h new file mode 100644 index 0000000..c89e9c9 --- /dev/null +++ b/zypp/base/DrunkenBishop.h @@ -0,0 +1,130 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/DrunkenBishop.h + */ +#ifndef ZYPP_BASE_DRUNKENBISHOP_H +#define ZYPP_BASE_DRUNKENBISHOP_H + +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace base + { + /////////////////////////////////////////////////////////////////// + /// \class DrunkenBishop + /// \brief Random art fingerprint visualization + /// Visualize fingerprint data on a [17x9] (SSH) or [19x11] (GPG) or + /// custom sized board. The default board size and layout depends on + /// the data string length (above 32 the GPG board and layout is used). + /// + /// The data string should be an even sized HEX string, otherwise + /// it will be 0-padded. + /// + /// All ctor calls may throw \ref std::invalid_argument. + /// + /// \code + /// [SuSE Package Signing Key ] + /// +------[Title]------+ + /// | . . ^ | fpr FEAB502539D846DB2C0961CA70AF9E8139DB7C82 + /// | : : . | id 70AF9E8139DB7C82 + /// | ^ ^ . | cre 1481108255 Wed Dec 7 11:57:35 2016 + /// | ^ . l i | exp 1607252255 Sun Dec 6 11:57:35 2020 + /// | : ^ . f : | ttl 992 + /// | ? ^ .Sl | rpm 39db7c82-5847eb1f + /// | E i ... | + /// | ^ .. | + /// | . . | + /// | . . | + /// | .... | + /// +----[39DB7C82]-----+ + /// \endcode + //// + /// Based on https://github.com/atoponce/keyart, the development location + /// for the Debian signing-party package. We try to use the same charset + /// and heatmap. + /// See also http://dirk-loss.de/sshvis/drunken_bishop.pdf. + /////////////////////////////////////////////////////////////////// + class ZYPP_API DrunkenBishop + { + friend std::ostream & operator<<( std::ostream & str, const DrunkenBishop & obj ); + + public: + /** Default ctor: empty board (1x1) */ + DrunkenBishop(); + + /** Ctor taking a data string (and optional title) and using a default (SSH/GPG) board. */ + DrunkenBishop( const std::string & data_r, const std::string & title_r = std::string() ); + + /** Ctor also taking a desired board height (even value is incremented, width is 2*height-1). */ + DrunkenBishop( const std::string & data_r, const std::string & title_r, unsigned height_r ); + /** Ctor \overload without optional title */ + DrunkenBishop( const std::string & data_r, unsigned height_r ) + : DrunkenBishop( data_r, std::string(), height_r ) + {} + + /** Ctor also taking a desired board height and width (even values are incremented). */ + DrunkenBishop( const std::string & data_r, const std::string & title_r, unsigned height_r, unsigned width_r ); + /** Ctor \overload without optional title */ + DrunkenBishop( const std::string & data_r, unsigned height_r, unsigned width_r ) + : DrunkenBishop( data_r, std::string(), height_r, width_r ) + {} + + /** Dtor */ + ~DrunkenBishop(); + + public: + /* Rendering options */ + enum OptionBits { + USE_COLOR = (1<<0), ///< use colors + }; + ZYPP_DECLARE_FLAGS(Options,OptionBits); + + /** Render board to steam.*/ + std::ostream & dumpOn( std::ostream & str, Options options_r = Options() ) const + { return dumpOn( str, std::string(), options_r ); } + /** \overload taking an indent string prefixing each line. */ + std::ostream & dumpOn( std::ostream & str, const std::string & prefix_r, Options options_r = Options() ) const; + + /** Render board as string.*/ + std::string asString( Options options_r = Options() ) const + { return asString( std::string(), options_r ); } + /** \overload taking an indent string prefixing each line. */ + std::string asString( const std::string & prefix_r, Options options_r = Options() ) const; + + /** Render to an array of lines. */ + std::vector asLines( Options options_r = Options() ) const + { return asLines( std::string(), options_r ); } + /** \overload taking an indent string prefixing each line. */ + std::vector asLines( const std::string & prefix_r, Options options_r = Options() ) const; + + public: + class Impl; ///< Implementation class. + private: + RW_pointer _pimpl; ///< Pointer to implementation. + }; + + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(DrunkenBishop::Options); + + /** \relates DrunkenBishop Stream output */ + inline std::ostream & operator<<( std::ostream & str, const DrunkenBishop & obj ) + { return obj.dumpOn( str ); } + + } // namespace base + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_DRUNKENBISHOP_H diff --git a/zypp/base/DtorReset.h b/zypp/base/DtorReset.h new file mode 100644 index 0000000..0ba69d8 --- /dev/null +++ b/zypp/base/DtorReset.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Easy.h b/zypp/base/Easy.h new file mode 100644 index 0000000..96526c2 --- /dev/null +++ b/zypp/base/Easy.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/EnumClass.h b/zypp/base/EnumClass.h new file mode 100644 index 0000000..54ca819 --- /dev/null +++ b/zypp/base/EnumClass.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Env.h b/zypp/base/Env.h new file mode 100644 index 0000000..9dd846a --- /dev/null +++ b/zypp/base/Env.h @@ -0,0 +1,78 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Env.h + */ +#ifndef ZYPP_BASE_ENV_H +#define ZYPP_BASE_ENV_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace env + { + /////////////////////////////////////////////////////////////////// + /// \class ScopedSet + /// \brief Temporarily set/unset an environment variable + /// \ingroup g_RAII + struct ScopedSet + { + ScopedSet( const ScopedSet & ) = delete; + ScopedSet & operator=( const ScopedSet & ) = delete; + + ScopedSet( ScopedSet && ) = default; + ScopedSet & operator=( ScopedSet && ) = default; + + public: + /** Default ctor (NOOP). */ + ScopedSet() + {} + + /** Set \a var_r to \a val_r (unsets \a var_r if \a val_r is a \c nullptr). */ + ScopedSet( std::string var_r, const char * val_r ) + : _var { std::move(var_r) } + { + if ( !_var.empty() ) + { + if ( const char * orig = ::getenv( _var.c_str() ) ) + _val.reset( new std::string( orig ) ); + setval( val_r ); + } + } + + /** Restore the original setting. */ + ~ScopedSet() + { + if ( !_var.empty() ) + setval( _val ? _val->c_str() : nullptr ); + } + + private: + void setval( const char * val_r ) + { + if ( val_r ) + ::setenv( _var.c_str(), val_r, 1 ); + else + ::unsetenv( _var.c_str() ); + } + + private: + std::string _var; + std::unique_ptr _val; + }; + + } // namespace env + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_ENV_H diff --git a/zypp/base/Errno.h b/zypp/base/Errno.h new file mode 100644 index 0000000..c3ffab3 --- /dev/null +++ b/zypp/base/Errno.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Exception.h b/zypp/base/Exception.h new file mode 100644 index 0000000..56a820a --- /dev/null +++ b/zypp/base/Exception.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/ExternalDataSource.h b/zypp/base/ExternalDataSource.h new file mode 100644 index 0000000..753692a --- /dev/null +++ b/zypp/base/ExternalDataSource.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Flags.h b/zypp/base/Flags.h new file mode 100644 index 0000000..38edf7d --- /dev/null +++ b/zypp/base/Flags.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Function.h b/zypp/base/Function.h new file mode 100644 index 0000000..74d3c95 --- /dev/null +++ b/zypp/base/Function.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Functional.h b/zypp/base/Functional.h new file mode 100644 index 0000000..054fcbb --- /dev/null +++ b/zypp/base/Functional.h @@ -0,0 +1,282 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Functional.h + * +*/ +#ifndef ZYPP_BASE_FUNCTIONAL_H +#define ZYPP_BASE_FUNCTIONAL_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace functor + { ///////////////////////////////////////////////////////////////// + /** \defgroup LOGICALFILTERS Functors for building compex queries. + * \ingroup g_Functor + * + * Some logical functors to build more complex queries: + * + * \li \ref True and \ref False. No supprise, they always return + * \c true or \c false. + * \li \ref Not\. TCondition is a functor, and + * its result is inverted. + * \li \ref Chain\. \c TACondition and \c TBCondition + * are functors, and Chain evaluates TACondition && TBCondition. + * + * As it's no fun to get and write the correct template arguments, + * convenience functions creating the correct functor are provided. + * + * \li \c true_c and \c false_c. (provided just to match the schema) + * \li \c not_c. Takes a functor as argument and returns the appropriate + * \ref Not functor. + * \li \c chain. Takes two functors and returns the appropriate + * \ref Cain functor. + * + * \code + * struct Print; // functor printing elements + * struct Count; // functor counting number of elements + * + * std::for_each( c.begin(), c.end(), + * chain( Print(), Count() ) ); + * \endcode + */ + //@{ + + /* functor that always returns a copied value */ + template + struct Constant + { + Constant( const TConst &value ) + : _value(value) + {} + + template + TConst operator()( Tp ) const + { return _value; } + + TConst operator()() const + { return _value; } + + TConst _value; + }; + + template + inline Constant constant( const TConst &value ) + { return Constant(value); } + + /** Logical functor always \c true. */ + struct True + { + template + bool operator()( Tp ) const + { + return true; + } + }; + + /** Convenience function for creating a True. */ + inline True true_c() + { return True(); } + + /** Logical functor always \c false. + */ + struct False + { + template + bool operator()( Tp ) const + { + return false; + } + }; + + /** Convenience function for creating a False. */ + inline False false_c() + { return False(); } + + /** Logical functor inverting \a TCondition. + */ + template + struct Not + { + Not( TCondition cond_r ) + : _cond( cond_r ) + {} + + template + bool operator()( Tp t ) const + { + return ! _cond( t ); + } + + TCondition _cond; + }; + + /** Convenience function for creating a Not from \a TCondition. */ + template + inline Not not_c( TCondition cond_r ) + { + return Not( cond_r ); + } + + /** Logical functor chaining \a TACondition \c OR \a TBCondition. + */ + template + struct Or + { + Or( TACondition conda_r, TBCondition condb_r ) + : _conda( conda_r ) + , _condb( condb_r ) + {} + + template + bool operator()( Tp t ) const + { + return _conda( t ) || _condb( t ); + } + + TACondition _conda; + TBCondition _condb; + }; + + /** Convenience function for creating a Or from two conditions + * \a conda_r OR \a condb_r. + */ + template + inline Or or_c( TACondition conda_r, TBCondition condb_r ) + { + return Or( conda_r, condb_r ); + } + + /** Logical functor chaining \a TACondition \c AND \a TBCondition. + */ + template + struct Chain + { + Chain( TACondition conda_r, TBCondition condb_r ) + : _conda( conda_r ) + , _condb( condb_r ) + {} + + template + bool operator()( Tp t ) const + { + return _conda( t ) && _condb( t ); + } + + TACondition _conda; + TBCondition _condb; + }; + + /** Convenience function for creating a Chain from two conditions + * \a conda_r and \a condb_r. + */ + template + inline Chain chain( TACondition conda_r, TBCondition condb_r ) + { + return Chain( conda_r, condb_r ); + } + + //@} + /////////////////////////////////////////////////////////////////// + + /** \defgroup ACTIONFUNCTOR + * \ingroup g_Functor + */ + //@{ + + /** Strore the 1st result found in the variable passed to the ctor. + * \code + * PoolItem result; + * invokeOnEach( pool.byIdentBegin(installed), pool.byIdentEnd(installed), + * filter::SameItem( installed ), + * getFirst( result ) ); + * \endcode + */ + template + struct GetFirst + { + GetFirst( Tp & result_r ) + : _result( &result_r ) + {} + bool operator()( const Tp & val_r ) + { *_result = val_r; return false; } + + private: + Tp * _result; + }; + + /** Convenience function for creating \ref GetFirst. */ + template + GetFirst getFirst( Tp & result_r ) + { return GetFirst( result_r ); } + + + /** Strore the last result found in the variable passed to the ctor. + */ + template + struct GetLast + { + GetLast( Tp & result_r ) + : _result( &result_r ) + {} + bool operator()( const Tp & val_r ) + { *_result = val_r; return true; } + + private: + Tp * _result; + }; + + /** Convenience function for creating \ref GetLast. */ + template + GetLast getLast( Tp & result_r ) + { return GetLast( result_r ); } + + + /** Store all results found to some output_iterator. + * \code + * std::vector result; + * parser::ProductFileReader::scanDir( functor::getAll( std::back_inserter( result ) ), + sysRoot / "etc/products.d" ); + * \endcode + */ + template + struct GetAll + { + GetAll( TOutputIterator result_r ) + : _result( result_r ) + {} + + template + bool operator()( const Tp & val_r ) const + { *(_result++) = val_r; return true; } + + private: + mutable TOutputIterator _result; + }; + + /** Convenience function for creating \ref GetAll. */ + template + GetAll getAll( TOutputIterator result_r ) + { return GetAll( result_r ); } + + //@} + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace functor + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_FUNCTIONAL_H diff --git a/zypp/base/Gettext.h b/zypp/base/Gettext.h new file mode 100644 index 0000000..e136e3a --- /dev/null +++ b/zypp/base/Gettext.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/GzStream.h b/zypp/base/GzStream.h new file mode 100644 index 0000000..0dd438a --- /dev/null +++ b/zypp/base/GzStream.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Hash.h b/zypp/base/Hash.h new file mode 100644 index 0000000..4bd3d65 --- /dev/null +++ b/zypp/base/Hash.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/IOStream.h b/zypp/base/IOStream.h new file mode 100644 index 0000000..37fe07d --- /dev/null +++ b/zypp/base/IOStream.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/IOTools.h b/zypp/base/IOTools.h new file mode 100644 index 0000000..81827fb --- /dev/null +++ b/zypp/base/IOTools.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/InputStream.h b/zypp/base/InputStream.h new file mode 100644 index 0000000..d00e841 --- /dev/null +++ b/zypp/base/InputStream.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Iterable.h b/zypp/base/Iterable.h new file mode 100644 index 0000000..ca98e83 --- /dev/null +++ b/zypp/base/Iterable.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Iterator.h b/zypp/base/Iterator.h new file mode 100644 index 0000000..2cbfbb7 --- /dev/null +++ b/zypp/base/Iterator.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Json.h b/zypp/base/Json.h new file mode 100644 index 0000000..0d26519 --- /dev/null +++ b/zypp/base/Json.h @@ -0,0 +1,383 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Json.h + * +*/ +#ifndef ZYPP_BASE_JSON_H +#define ZYPP_BASE_JSON_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace json + { + // JSN Keywords + inline static const std::string & nullJSON() { static const std::string _s( "null" ); return _s; } + inline static const std::string & trueJSON() { static const std::string _s( "true" ); return _s; } + inline static const std::string & falseJSON() { static const std::string _s( "false" ); return _s; } + + /////////////////////////////////////////////////////////////////// + namespace detail + { + inline std::string strEncode( std::string val_r ) + { + typedef unsigned char uchar; + + std::string::size_type add = 2; // enclosing "s + for_( r, val_r.begin(), val_r.end() ) + { + if ( uchar(*r) < 32u ) + { + switch ( *r ) + { + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + add += 1; // "\c" + break; + default: + add += 5; // "\uXXXX" + break; + } + } + else + { + switch ( *r ) + { + case '"': + case '/': + case '\\': + add += 1; // \-escape + break; + } + } + } + + val_r.resize( val_r.size() + add, '@' ); + auto w( val_r.rbegin() ); + auto r( w + add ); + + *w++ = '"'; + for ( ; r != val_r.rend(); ++r ) + { + if ( uchar(*r) < 32u ) + { + static const char * digit = "0123456789abcdef"; + switch ( *r ) + { + case '\b': // "\c" + *w++ = 'b'; + *w++ = '\\'; + break; + case '\f': // "\c" + *w++ = 'f'; + *w++ = '\\'; + break; + case '\n': // "\c" + *w++ = 'n'; + *w++ = '\\'; + break; + case '\r': // "\c" + *w++ = 'r'; + *w++ = '\\'; + break; + case '\t': // "\c" + *w++ = 't'; + *w++ = '\\'; + break; + default: // "\uXXXX" + *w++ = digit[uchar(*r) % 15]; + *w++ = digit[uchar(*r) / 16]; + *w++ = '0'; + *w++ = '0'; + *w++ = 'u'; + *w++ = '\\'; + break; + } + } + else + { + switch ( (*w++ = *r) ) + { + case '"': + case '/': + case '\\': // \-escape + *w++ = '\\'; + break; + } + } + } + *w++ = '"'; + return val_r; + } + } // namespace detail + /////////////////////////////////////////////////////////////////// + + // null + inline std::string toJSON( void ) { return nullJSON(); } + inline std::string toJSON( std::nullptr_t ) { return nullJSON(); } + + // bool + inline std::string toJSON( bool val_r ) { return val_r ? trueJSON() : falseJSON(); } + inline std::string toJSON( const void * val_r ) { return val_r ? trueJSON() : falseJSON(); } + + // numbers + inline std::string toJSON( short val_r ) { return str::numstring( val_r ); } + inline std::string toJSON( unsigned short val_r ) { return str::numstring( val_r ); } + inline std::string toJSON( int val_r ) { return str::numstring( val_r ); } + inline std::string toJSON( unsigned val_r ) { return str::numstring( val_r ); } + inline std::string toJSON( long val_r ) { return str::numstring( val_r ); } + inline std::string toJSON( unsigned long val_r ) { return str::numstring( val_r ); } + inline std::string toJSON( long long val_r ) { return str::numstring( val_r ); } + inline std::string toJSON( unsigned long long val_r ){ return str::numstring( val_r ); } + + // strings + inline std::string toJSON( const char val_r ) { return detail::strEncode( std::string( 1, val_r ) ); } + inline std::string toJSON( const char * val_r ) { return val_r ? detail::strEncode( val_r ) : nullJSON(); } + inline std::string toJSON( const std::string & val_r ){ return detail::strEncode( val_r ); } + + // container to Array + template std::string toJSON( const std::vector & cont_r ); + template std::string toJSON( const std::list & cont_r ); + template std::string toJSON( const std::set & cont_r ); + + // map to Object + template std::string toJSON( const std::map & cont_r ); + + /** Type to JSON string representation. + * This can be implemented as non-static memberfunction \c asJSON, + * or as non-memberfunction \c toJSON; + * \code + * class Type; + * std::string Type::asJSON() const; + * std::string toJSON( const Type & ); + * \endcode + */ + template + std::string toJSON( const T & val_r ) { return val_r.asJSON(); } + + /////////////////////////////////////////////////////////////////// + /// \class Value + /// \brief JSON representation of datatypes via \ref toJSON + /// \code + /// namespace mynamspace + /// { + /// struct Mydata + /// {...}; + /// + /// std::string toJSON( const Mydata & ) + /// { return json::Array{ "answer", 42 }.asJSON(); } + /// } + /// + /// mynamspace::Mydata data; + /// json::Object bigone { + /// { "mydata", data }, + /// { "panic", false }, + /// { "nested", json::Object{ {"one",1}, {"two",2}, {"three",3} } } + /// }; + /// + /// cout << bigone << endl; + ///\endcode + /// \see http://www.json.org/ + /////////////////////////////////////////////////////////////////// + struct Value + { + /** Default ctor (null) */ + Value() : _data( toJSON() ) {} + + /** Copy ctor */ + Value( const Value & rhs ) : _data( rhs._data ) {} + + /** Ctor creating a JSON representation of \a T via \ref toJSON(T) */ + template + Value( const T & val_r ) : _data( toJSON( val_r ) ) {} + + /** JSON representation */ + const std::string & asJSON() const + { return _data; } + + /** String representation */ + const std::string & asString() const + { return asJSON(); } + + /** Stream output */ + std::ostream & dumpOn( std::ostream & str ) const + { return str << _data; } + + private: + std::string _data; + }; + + /** \relates Value Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Value & obj ) + { return obj.dumpOn( str ); } + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class String + /// \brief JSON string + /// Force representation as JSON string, mapping e.g. \c null values + /// to an empty string. Maninly used in \ref Object as key. + /////////////////////////////////////////////////////////////////// + struct String : public Value + { + String() : Value( "" ) {} + String( std::nullptr_t ) : Value( "" ) {} + + String( const char val_r ) : Value( val_r ) {} + String( const char * val_r ) : Value( val_r ? val_r : "" ) {} + String( const std::string & val_r ): Value( val_r ) {} + }; + + /////////////////////////////////////////////////////////////////// + /// \class Array + /// \brief JSON array + /////////////////////////////////////////////////////////////////// + struct Array + { + Array() {} + + /** Construct from container iterator */ + template + Array( Iterator begin, Iterator end ) + { for_( it, begin, end ) add( *it ); } + + /** Construct from container initializer list { v1, v2,... } */ + Array( const std::initializer_list & contents_r ) + : Array( contents_r.begin(), contents_r.end() ) + {} + + /** Push JSON Value to Array */ + void add( const Value & val_r ) + { _data.push_back( val_r.asJSON() ); } + + /** \overload from container initializer list { v1, v2,... } */ + void add( const std::initializer_list & contents_r ) + { for_( it, contents_r.begin(), contents_r.end() ) add( *it ); } + + /** JSON representation */ + std::string asJSON() const + { return str::Str() << *this; } + + /** String representation */ + std::string asString() const + { return asJSON(); } + + /** Stream output */ + std::ostream & dumpOn( std::ostream & str ) const + { + if ( _data.empty() ) + return str << "[]"; + str << '[' << *_data.begin(); + for_( val, ++_data.begin(), _data.end() ) + str << ", " << *val; + return str << ']'; + } + + private: + std::list _data; + }; + + /** \relates Array Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Array & obj ) + { return obj.dumpOn( str ); } + + template + std::string toJSON( const std::vector & cont_r ) + { return json::Array( cont_r.begin(), cont_r.end() ).asJSON(); } + + template + std::string toJSON( const std::list & cont_r ) + { return json::Array( cont_r.begin(), cont_r.end() ).asJSON(); } + + template + std::string toJSON( const std::set & cont_r ) + { return json::Array( cont_r.begin(), cont_r.end() ).asJSON(); } + + /////////////////////////////////////////////////////////////////// + /// \class Object + /// \brief JSON object + /////////////////////////////////////////////////////////////////// + struct Object + { + Object() {} + + /** Construct from map-iterator */ + template + Object( Iterator begin, Iterator end ) + { for_( it, begin, end ) add( it->first, it->second ); } + + /** Construct from map-initializer list { {k1,v1}, {k2,v2},... } */ + Object( const std::initializer_list> & contents_r ) + : Object( contents_r.begin(), contents_r.end() ) + {} + + /** Add key/value pair */ + void add( const String & key_r, const Value & val_r ) + { _data[key_r.asJSON()] = val_r.asJSON(); } + + /** \overload from map-initializer list { {k1,v1}, {k2,v2},... } */ + void add( const std::initializer_list> & contents_r ) + { for_( it, contents_r.begin(), contents_r.end() ) add( it->first, it->second ); } + + /** JSON representation */ + std::string asJSON() const + { return str::Str() << *this; } + + /** String representation */ + std::string asString() const + { return asJSON(); } + + /** Stream output */ + std::ostream & dumpOn( std::ostream & str ) const + { + using std::endl; + if ( _data.empty() ) + return str << "{}"; + dumpOn( str << '{' << endl, _data.begin() ); + for_ ( val, ++_data.begin(), _data.end() ) + dumpOn( str << ',' << endl, val ); + return str << endl << '}'; + } + + private: + std::ostream & dumpOn( std::ostream & str, std::map::const_iterator val_r ) const + { return str << val_r->first << ": " << val_r->second; } + + std::map _data; + }; + + /** \relates Object Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Object & obj ) + { return obj.dumpOn( str ); } + + template + std::string toJSON( const std::map & cont_r ) + { return json::Object( cont_r.begin(), cont_r.end() ).asJSON(); } + + + } // namespace json + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_JSON_H diff --git a/zypp/base/LocaleGuard.h b/zypp/base/LocaleGuard.h new file mode 100644 index 0000000..f8d6ccd --- /dev/null +++ b/zypp/base/LocaleGuard.h @@ -0,0 +1,66 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/LocaleGuard.h + */ +#ifndef ZYPP_BASE_LOCALEGUARD_H +#define ZYPP_BASE_LOCALEGUARD_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class LocaleGuard + /// \brief Temorarily change a locale category value + /// \ingroup g_RAII + /////////////////////////////////////////////////////////////////// + class LocaleGuard + { + NON_COPYABLE(LocaleGuard); + NON_MOVABLE(LocaleGuard); + + public: + /** Ctor saving the current locale category value. */ + LocaleGuard( int category_r, const std::string & value_r = "C" ) + : _category( -1 ) + { + const char * ovalue = ::setlocale( category_r, nullptr ); + if ( ovalue && ovalue != value_r ) + { + _category = category_r; + _value = ovalue; + ::setlocale( _category, value_r.c_str() ); + } + } + + /** Dtor asserts the saved locale category value is restored. */ + ~LocaleGuard() + { restore(); } + + /** immediately restore the saved locale category value. */ + void restore() + { + if ( _category != -1 ) + { + ::setlocale( _category, _value.c_str() ); + _category = -1; + } + } + + private: + int _category; ///< saved category or -1 if no restore needed + std::string _value; ///< saved category value + }; +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_LOCALEGUARD_H diff --git a/zypp/base/LogControl.h b/zypp/base/LogControl.h new file mode 100644 index 0000000..58da1b1 --- /dev/null +++ b/zypp/base/LogControl.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/LogTools.h b/zypp/base/LogTools.h new file mode 100644 index 0000000..e7bf2ba --- /dev/null +++ b/zypp/base/LogTools.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Logger.h b/zypp/base/Logger.h new file mode 100644 index 0000000..adb9515 --- /dev/null +++ b/zypp/base/Logger.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Measure.cc b/zypp/base/Measure.cc new file mode 100644 index 0000000..e0f8cc2 --- /dev/null +++ b/zypp/base/Measure.cc @@ -0,0 +1,259 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Measure.cc + * +*/ +extern "C" +{ +#include +#include +} +#include +#include + +#include +#include +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "Measure" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace debug + { ///////////////////////////////////////////////////////////////// + + /** Times measured by \ref Measure. */ + struct Tm + { + Tm() + : _real( 0 ) + , _proc( tmsEmpty ) + {} + + void get() + { + _real = ::time(NULL); + ::times( &_proc ); + } + + Tm operator-( const Tm & rhs ) const + { + Tm ret( *this ); + ret._real -= rhs._real; + ret._proc.tms_utime -= rhs._proc.tms_utime; + ret._proc.tms_stime -= rhs._proc.tms_stime; + ret._proc.tms_cutime -= rhs._proc.tms_cutime; + ret._proc.tms_cstime -= rhs._proc.tms_cstime; + return ret; + } + + std::string asString() const + { + std::string ret( timeStr( _real ) ); + ret += " (u "; + ret += timeStr( asSec( _proc.tms_utime ) ); + ret += " s "; + ret += timeStr( asSec( _proc.tms_stime ) ); + ret += " c "; + ret += timeStr( asSec( _proc.tms_cutime + _proc.tms_cstime ) ); + ret += ")"; + return ret; + } + + std::string stringIf( clock_t ticks_r, const std::string & tag_r ) const + { + std::string ret; + if ( ticks_r ) + { + ret += tag_r; + ret += timeStr( asSec( ticks_r ) ); + } + return ret; + } + + double asSec( clock_t ticks_r ) const + { return double(ticks_r) / ticks; } + + std::string timeStr( time_t sec_r ) const + { + time_t h = sec_r/3600; + sec_r -= h*3600; + time_t m = sec_r/60; + sec_r -= m*60; + if ( h ) + return str::form( "%lu:%02lu:%02lu", h, m, sec_r ); + if ( m ) + return str::form( "%lu:%02lu", m, sec_r ); + return str::form( "%lu", sec_r ); + } + + std::string timeStr( double sec_r ) const + { + time_t h = time_t(sec_r)/3600; + sec_r -= h*3600; + time_t m = time_t(sec_r)/60; + sec_r -= m*60; + if ( h ) + return str::form( "%lu:%02lu:%05.2lf", h, m, sec_r ); + if ( m ) + return str::form( "%lu:%05.2lf", m, sec_r ); + return str::form( "%.2lf", sec_r ); + } + + /** Systems ticks per second. */ + static const long ticks; + /** Empty struct tms. */ + static const struct tms tmsEmpty; + /** Real time via \c ::time. */ + time_t _real; + /** Process times via \c ::times. */ + struct tms _proc; + }; + + const struct tms Tm::tmsEmpty = { 0, 0, 0, 0 }; + const long Tm::ticks = sysconf(_SC_CLK_TCK); + + /** \refers Tm Stream output. */ + std::ostream & operator<<( std::ostream & str, const Tm & obj ) + { + return str << obj.asString(); + } + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Measure::Impl + // + /** Measure implementation. */ + class Measure::Impl + { + public: + Impl( std::string &&ident_r, std::ostream * log_r = nullptr ) + : _ident (std::move( ident_r )) + , _level ( _glevel ) + , _seq ( 0 ) + , _log ( log_r ) + { + _glevel += ".."; + log() << _level << "START MEASURE(" << _ident << ")" << endl; + _start.get(); + } + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() + { + _stop.get(); + ++_seq; + std::ostream & str( log() << _level << "MEASURE(" << _ident << ") " ); + dumpMeasure( str ); + _glevel.erase( 0, 2 ); + } + + void restart() + { + log() << _level << "RESTART MEASURE(" << _ident << ")" << endl; + _start = _stop; + } + + void elapsed( const std::string & tag_r = std::string() ) const + { + _stop.get(); + ++_seq; + std::ostream & str( log() << _level << "ELAPSED(" << _ident << ") " ); + dumpMeasure( str, tag_r ); + _elapsed = _stop; + } + + /** Return the log stream. */ + std::ostream & log() const + { return _log ? *_log : INT; } + std::ostream * logp() const + { return _log; } + + private: + std::ostream & dumpMeasure( std::ostream & str_r, const std::string & tag_r = std::string() ) const + { + str_r << ( _stop - _start ); + if ( _seq > 1 ) // diff to previous _elapsed + { + str_r << " [" << ( _stop - _elapsed ) << "]"; + } + if ( ! tag_r.empty() ) + str_r << " - " << tag_r; + return str_r << endl; + } + + private: + static std::string _glevel; + + std::string _ident; + std::string _level; + Tm _start; + mutable unsigned _seq; + mutable Tm _elapsed; + mutable Tm _stop; + + std::ostream * _log = nullptr; + }; + + std::string Measure::Impl::_glevel; + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Measure + // + /////////////////////////////////////////////////////////////////// + + Measure::Measure() + {} + + Measure::Measure( std::string ident_r ) + : _pimpl( new Impl( std::move(ident_r) ) ) + {} + + Measure::Measure( std::string ident_r, std::ostream & out_r ) + : _pimpl( new Impl( std::move(ident_r), &out_r ) ) + {} + + Measure::~Measure() + {} + + void Measure::start( std::string ident_r ) + { stop(); _pimpl.reset( _pimpl ? new Impl( std::move(ident_r), _pimpl->logp() ) : new Impl( std::move(ident_r) ) ); } + + void Measure::restart() + { _pimpl->restart(); } + + void Measure::elapsed() const + { if ( _pimpl ) _pimpl->elapsed(); } + void Measure::elapsed( const std::string & tag_r ) const + { if ( _pimpl ) _pimpl->elapsed( tag_r ); } + void Measure::elapsed( long tag_r ) const + { if ( _pimpl ) _pimpl->elapsed( asString( tag_r ) ); } + + void Measure::stop() + { _pimpl.reset(); } + + ///////////////////////////////////////////////////////////////// + } // namespace debug + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/base/Measure.h b/zypp/base/Measure.h new file mode 100644 index 0000000..99513c0 --- /dev/null +++ b/zypp/base/Measure.h @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Measure.h + * +*/ +#ifndef ZYPP_BASE_MEASURE_H +#define ZYPP_BASE_MEASURE_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace debug + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Measure + // + /** Tool to measure elapsed real and process times. + * + * Timer is started by either passing a string to the ctor, + * or callign \ref start. The string passed is printed on + * all messages to help identifying the timer. + * + * Elapsed time is printed on calling \ref elapsed (timer + * keeps running) or \ref stop. + * + * Calling \ref stop, stops the timer. The same, if the timer + * goes out of scope. + * + * Elapsed time is printed as: + * \code + * 'REAL TIME' (u 'USER TIME' s 'SYSTEM TIME' c 'TIME OF CHILDREN') + * \endcode + * In brackets the time elapsed since a previous call to \ref elapsed. + * All units are seconds. + * + * \code + * Measure m( "Parse" ); + * ... + * m.elapsed(); + * ... + * m.elapsed(); + * ... + * m.elapsed(); + * ... + * m.stop(); + * + * // START MEASURE(Parse) + * // ELAPSED(Parse) 0 (u 0.13 s 0.00 c 0.00) + * // ELAPSED(Parse) 0 (u 0.15 s 0.02 c 0.00) [ 0 (u 0.02 s 0.02 c 0.00)] + * // ELAPSED(Parse) 0 (u 0.17 s 0.02 c 0.00) [ 0 (u 0.02 s 0.00 c 0.00)] + * // MEASURE(Parse) 0 (u 0.17 s 0.02 c 0.00) [ 0 (u 0.00 s 0.00 c 0.00)] + * \endcode + */ + class ZYPP_API Measure + { + public: + /** Default Ctor does nothing. */ + Measure(); + + /** Ctor taking \a ident_r string and auto starts timer. */ + explicit + Measure(std::string ident_r ); + /** \overload log to custom ostream */ + Measure(std::string ident_r, std::ostream & out_r ); + + /** Dtor. */ + ~Measure(); + + /** Start timer for \a ident_r string. + * Implies stoping a running timer. + */ + void start(std::string ident_r = std::string() ); + + /** re start the timer without reset-ing it. */ + void restart(); + + /** Print elapsed time for a running timer. + * Timer keeps on running. + */ + void elapsed() const; + /** \overload Tagging the time with some text + * \code + * elapsed( "after action foo..." ); + * \endcode + */ + void elapsed( const std::string & tag_r ) const; + /** \overload Tagging the time with e.g. a line number + * \code + * elapsed( __LINE__ ); + * \endcode + */ + void elapsed( long tag_r ) const; + + /** Stop a running timer. */ + void stop(); + + private: + /** Implementation. */ + class Impl; + /** Pointer to implementation. */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace debug + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_MEASURE_H diff --git a/zypp/base/NamedValue.h b/zypp/base/NamedValue.h new file mode 100644 index 0000000..495032b --- /dev/null +++ b/zypp/base/NamedValue.h @@ -0,0 +1,161 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/NamedValue.h + * +*/ +#ifndef ZYPP_BASE_NAMEDVALUE_H +#define ZYPP_BASE_NAMEDVALUE_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + + /////////////////////////////////////////////////////////////////// + /// \class NamedValue + /// \brief Simple value<>name mapping supporting aliases. + /// \code + /// enum Commands { + /// CMD_1, + /// CMD_2 + /// }; + /// NamedValue clist; + /// // Value | Name | Alias... + /// clist( CMD_1 ) | "cmd1"; + /// clist( CMD_2 ) | "cmd2" | "second"; + /// + /// std::string name( clist.getName( CMD_1 ) ); + /// Commands cmd( clist.getValue( "second" ) ); + /// \endcode + /////////////////////////////////////////////////////////////////// + template< class Tp, const bool _tWithAlias = true > + class NamedValue + { + using NameMap = std::map; + using ValueMap = std::map; + + public: + /** Whether not initialized (no (name,value) pair remembered) */ + bool empty() const + { return( _nameMap.empty() && _valueMap.empty() ); } + + public: + /** \name Get value for name or alias. */ + //@{ + /** Whether there is a \c value mapped for \a name_r. + */ + bool haveValue( const std::string & name_r ) const + { + typename NameMap::const_iterator it( _nameMap.find( name_r ) ); + return( it != _nameMap.end() ); + } + + /** Get value mapped for name or alias. + * \return \c true if name or alias was found. + */ + bool getValue( const std::string & name_r, Tp & value_r ) const + { + typename NameMap::const_iterator it( _nameMap.find( name_r ) ); + if ( it == _nameMap.end() ) + return false; + value_r = it->second; + return true; + } + /** \overload \throws std::out_of_range exception if \a name_r was not found. */ + const Tp & getValue( const std::string & name_r ) const + { return _nameMap.at( name_r ); } + //@} + + + /** \name Get name for value. */ + //@{ + /** Whether there is a \c name mapped for \a value_r. + */ + bool haveName( const std::string & value_r ) const + { + typename ValueMap::const_iterator it( _valueMap.find( value_r ) ); + return( it != _valueMap.end() ); + } + + /** Get name of value. + * \return \c true if name or alias was found. + */ + bool getName( const Tp & value_r, std::string & name_r ) const + { + typename ValueMap::const_iterator it( _valueMap.find( value_r ) ); + if ( it == _valueMap.end() ) + return false; + value_r = it->second; + return true; + } + /** \overload \throws std::out_of_range exception if \a value_r was not found. */ + const std::string & getName( const Tp & value_r ) const + { return _valueMap.at( value_r ); } + //@} + + public: + /** \name Inserter + */ + //@{ + class TInserter + { + public: + TInserter( NamedValue & parent_r, const Tp & value_r ) + : _parent( &parent_r ) + , _value( value_r ) + {} + TInserter & operator|( const std::string & name_r ) + { _parent->insert( _value, name_r ); return *this; } + private: + NamedValue * _parent; + Tp _value; + }; + + TInserter operator()( const Tp & value_r ) + { return TInserter( *this, value_r ); } + //@} + + /** Remember name (1st call) or alias (subsequent calls). + * \return \C true if this is the 1st call for \a value_r. + * \throws std::logic_error if \a name_r is already used as name or alias. + * \throws std::logic_error if \c _tWithAlias is \c false and a name for \a value_r is already defined. + */ + bool insert( const Tp & value_r, const std::string & name_r ) + { + typename NameMap::const_iterator nit( _nameMap.find( name_r ) ); + if ( nit != _nameMap.end() ) // duplicate name + throw std::logic_error( "NamedValue::insert name" ); + + typename ValueMap::const_iterator tit( _valueMap.find( value_r ) ); + if ( tit != _valueMap.end() ) // duplicate value, i.e. an alias + { + if ( !_tWithAlias ) + throw std::logic_error( "NamedValue::insert alias" ); + + _nameMap[name_r] = value_r; + return false; + } + // here: 1st entry for value_r + _nameMap[name_r] = value_r; + _valueMap[value_r] = name_r; + return true; + } + + private: + NameMap _nameMap; + ValueMap _valueMap; + }; + /////////////////////////////////////////////////////////////////// + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_NAMEDVALUE_H diff --git a/zypp/base/NonCopyable.h b/zypp/base/NonCopyable.h new file mode 100644 index 0000000..8377350 --- /dev/null +++ b/zypp/base/NonCopyable.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/ProfilingFormater.h b/zypp/base/ProfilingFormater.h new file mode 100644 index 0000000..21048bd --- /dev/null +++ b/zypp/base/ProfilingFormater.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/ProvideNumericId.h b/zypp/base/ProvideNumericId.h new file mode 100644 index 0000000..87314ea --- /dev/null +++ b/zypp/base/ProvideNumericId.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/PtrTypes.h b/zypp/base/PtrTypes.h new file mode 100644 index 0000000..4f408e7 --- /dev/null +++ b/zypp/base/PtrTypes.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Random.cc b/zypp/base/Random.cc new file mode 100644 index 0000000..72db3b3 --- /dev/null +++ b/zypp/base/Random.cc @@ -0,0 +1,51 @@ +#include +#include +#include +#include + + +namespace zypp { namespace base { + + // Taken from KApplication +int random_int() +{ + static bool init = false; + if (!init) + { + unsigned int seed = 0; + init = true; + int fd = open("/dev/urandom", O_RDONLY|O_CLOEXEC); + if (fd < 0 || ::read(fd, &seed, sizeof(seed)) != sizeof(seed)) + { + // No /dev/urandom... try something else. + srand(getpid()); + seed = rand()+time(0); + } + if (fd >= 0) close(fd); + srand(seed); + } + return rand(); +} + +// Taken from KApplication +std::string random_string(int length) +{ + if (length <=0 ) return std::string(); + + std::string str; str.resize( length ); + int i = 0; + while (length--) + { + int r=::random() % 62; + r+=48; + if (r>57) r+=7; + if (r>90) r+=6; + str[i++] = char(r); + // so what if I work backwards? + } + return str; +} + + +} } + diff --git a/zypp/base/Random.h b/zypp/base/Random.h new file mode 100644 index 0000000..9c988f9 --- /dev/null +++ b/zypp/base/Random.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_BASE_Random_H +#define ZYPP_BASE_Random_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace base + { /////////////////////////// + // Taken from KApplication + int random_int(); + // Taken from KApplication + std::string random_string(int length); + + + /** Return a random number from [0,RAND_MAX[. */ + inline unsigned random() + { + return random_int(); + } + /** Return a random number from [0,size_r[. */ + inline unsigned random( unsigned size_r ) + { + return random_int() % size_r; + } + /** Return a random number from [min_r,min_r+size_r[. */ + inline unsigned random( unsigned min_r, unsigned size_r ) + { + return min_r + random( size_r ); + } + + + } //ns base +} // ns zypp + +#endif + diff --git a/zypp/base/ReferenceCounted.h b/zypp/base/ReferenceCounted.h new file mode 100644 index 0000000..3e892ce --- /dev/null +++ b/zypp/base/ReferenceCounted.h @@ -0,0 +1,17 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/ReferenceCounted.h + * +*/ +#ifndef ZYPP_BASE_REFERENCECOUNTED_H +#define ZYPP_BASE_REFERENCECOUNTED_H + +#include + +#endif // ZYPP_BASE_REFERENCECOUNTED_H diff --git a/zypp/base/Regex.h b/zypp/base/Regex.h new file mode 100644 index 0000000..77bd206 --- /dev/null +++ b/zypp/base/Regex.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/SerialNumber.cc b/zypp/base/SerialNumber.cc new file mode 100644 index 0000000..df02d82 --- /dev/null +++ b/zypp/base/SerialNumber.cc @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/SerialNumber.cc + * +*/ +#include +//#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SerialNumber + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : SerialNumber::SerialNumber + // METHOD TYPE : Ctor + // + SerialNumber::SerialNumber( bool dirty_r ) + : _dirty( dirty_r ) + , _serial( 0 ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : SerialNumber::~SerialNumber + // METHOD TYPE : Dtor + // + SerialNumber::~SerialNumber() + {} + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const SerialNumber & obj ) + { + return str << "SERIAL" << (obj._dirty?"*":"(") << obj._serial << (obj._dirty?"*":")"); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SerialNumberWatcher + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : SerialNumberWatcher::SerialNumberWatcher + // METHOD TYPE : Ctor + // + SerialNumberWatcher::SerialNumberWatcher( unsigned serial_r ) + : _serial( serial_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : SerialNumberWatcher::SerialNumberWatcher + // METHOD TYPE : Ctor + // + SerialNumberWatcher::SerialNumberWatcher( const SerialNumber & serial_r ) + : _serial( serial_r.serial() ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : SerialNumber::~SerialNumber + // METHOD TYPE : Dtor + // + SerialNumberWatcher::~SerialNumberWatcher() + {} + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const SerialNumberWatcher & obj ) + { + return str << "LAST_SERIAL(" << obj._serial << ")"; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/base/SerialNumber.h b/zypp/base/SerialNumber.h new file mode 100644 index 0000000..b1e3f4c --- /dev/null +++ b/zypp/base/SerialNumber.h @@ -0,0 +1,184 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/SerialNumber.h + * +*/ +#ifndef ZYPP_BASE_SERIALNUMBER_H +#define ZYPP_BASE_SERIALNUMBER_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SerialNumber + // + /** Simple serial number provider. + * + * \ref serial returns a serial number. The number returned stays + * the same unless \ref setDirty was called to bring the object + * into \c dirty state. The next call to \ref serial will increment + * the serial number and bring the object into \c clean state. + * + * \code + * SerialNumber sno; + * sno.serial(); // SERIAL(0); () = clean + * sno.setDirty(); // SERIAL*0*; ** = dirty + * sno.serial(); // SERIAL(1) + * sno.setDirty(); // SERIAL*1* + * sno.setDirty(); // SERIAL*1* + * sno.serial(); // SERIAL(2) + * \endcode + */ + class SerialNumber + { + friend std::ostream & operator<<( std::ostream & str, const SerialNumber & obj ); + + public: + /** Ctor taking initial \c dirty value. */ + SerialNumber( bool dirty_r = false ); + /** Dtor */ + virtual ~SerialNumber(); + + public: + void setDirty() + { _dirty = true; } + + public: + bool dirty() const + { return _dirty; } + + bool clean() const + { return !_dirty; } + + unsigned serial() const + { + if ( _dirty ) + { + ++_serial; + _dirty = false; + } + return _serial; + } + + private: + mutable bool _dirty; + mutable unsigned _serial; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates SerialNumber Stream output */ + std::ostream & operator<<( std::ostream & str, const SerialNumber & obj ); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SerialNumberWatcher + // + /** Simple serial number watcher. + * + * \ref SerialNumberWatcher remembers a serial number + * and tells whenever new numbers you feed change. + * + * All methods are overloaded to take an \unsigned or a + * const SerialNumber & as argument. + * + * \code + * SerialNumber sno; + * + * void check() + * { + * static SerialNumberWatcher watcher( sno ); + * + * if ( watcher.remember( sno ) ) + * { + * cout << "Serial number changed." << endl; + * } + * } + * + * int main() + * { + * check(); // This call would trigger, if check used a + * // default constructed SerialNumberWatcher. + * + * check(); // + * sno.dirty(); + * check(); // "Serial number changed." + * check(); // + * sno.dirty(); + * check(); // "Serial number changed." + * \endcode + */ + class SerialNumberWatcher + { + friend std::ostream & operator<<( std::ostream & str, const SerialNumberWatcher & obj ); + + public: + /** Ctor taking an initial \c serial value. + * + * A default constructed SerialNumberWatcher remembers the serial + * number (unsigned)-1. So it is most likely the the 1st + * call to \ref remember returns \ref isDirty. + * + * Vice versa, initializing the SerialNumberWatcher with the current + * SerialNumber, most likely prevents the 1st to \ref remember to + * return \ref isDirty. + */ + SerialNumberWatcher( unsigned serial_r = (unsigned)-1 ); + /** Ctor taking an initial \c serial value. */ + SerialNumberWatcher( const SerialNumber & serial_r ); + /** Dtor */ + virtual ~SerialNumberWatcher(); + + public: + /** Return whether \c serial_r differs. */ + bool isDirty( unsigned serial_r ) const + { return( _serial != serial_r ); } + /** \overload */ + bool isDirty( const SerialNumber & serial_r ) const + { return( _serial != serial_r.serial() ); } + + /** Return whether \c serial_r is still unchanged. */ + bool isClean( unsigned serial_r ) const + { return( _serial == serial_r ); } + /** \overload */ + bool isClean( const SerialNumber & serial_r ) const + { return( _serial == serial_r.serial() ); } + + public: + /** Return \ref isDirty, storing \c serial_r as new value. */ + bool remember( unsigned serial_r ) const + { + if ( isDirty( serial_r ) ) + { + _serial = serial_r; + return true; + } + return false; + } + /** \overload */ + bool remember( const SerialNumber & serial_r ) const + { return remember( serial_r.serial() ); } + + private: + mutable unsigned _serial; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates SerialNumberWatcher Stream output */ + std::ostream & operator<<( std::ostream & str, const SerialNumberWatcher & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_SERIALNUMBER_H diff --git a/zypp/base/SetRelationMixin.cc b/zypp/base/SetRelationMixin.cc new file mode 100644 index 0000000..60f84c8 --- /dev/null +++ b/zypp/base/SetRelationMixin.cc @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/SetRelationMixin.cc + */ + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + const std::string & ESetCompareDef::asString( Enum val_r ) + { + static std::map _table = { + { uncomparable, "{?}" }, + { equal, "{=}" }, + { properSubset, "{<}" }, + { properSuperset, "{>}" }, + { disjoint, "{ }" }, + }; + return _table[val_r]; + } + + const std::string & ESetRelationDef::asString( Enum val_r ) + { + static std::map _table = { + { uncomparable, "{??}" }, + { equal, "{==}" }, + { properSubset, "{<<}" }, + { properSuperset, "{>>}" }, + { disjoint, "{ }" }, + { subset, "{<=}" }, + { superset, "{>=}" }, + }; + return _table[val_r]; + } +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/base/SetRelationMixin.h b/zypp/base/SetRelationMixin.h new file mode 100644 index 0000000..aa2f6ad --- /dev/null +++ b/zypp/base/SetRelationMixin.h @@ -0,0 +1,242 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/SetRelationMixin.h + */ +#ifndef ZYPP_BASE_SETRELATIONMIXIN_H +#define ZYPP_BASE_SETRELATIONMIXIN_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class ESetCompareDef + /// \brief Result of set comparison (use like 'enum class \ref SetCompare') + /// This is the type a \c compare function should return. + /////////////////////////////////////////////////////////////////// + struct ESetCompareDef { + enum Enum { + uncomparable = 0, ///< "{?}" + equal = (1<<0), ///< "{=}" + properSubset = (1<<1), ///< "{<}" + properSuperset = (1<<2), ///< "{>}" + disjoint = (1<<3), ///< "{ }" + }; + /** String representantion */ + static const std::string & asString( Enum val_r ) ZYPP_API; + }; + /** \relates ESetCompareDef typedef 'enum class SetCompare' */ + using SetCompare = base::EnumClass; + + /** \relates SetCompare Stream output */ + inline std::ostream & operator<<( std::ostream & str, const SetCompare::Enum & obj ) + { return str << SetCompare::asString( obj ); } + /** \overload */ + inline std::ostream & operator<<( std::ostream & str, const SetCompare & obj ) + { return str << obj.asEnum(); } + + /////////////////////////////////////////////////////////////////// + /// \class ESetRelationDef + /// \brief Set Relation based on \ref SetCompare (use like 'enum class \ref SetRelation') + /// Comparison (\c== \c!=) between \ref SetRelation and \ref SetCompare + /// is defined to let \c SetRelation::subset match \c SetCompare::equal + /// as well as \c SetCompare::properSubset. Accordingly \c SetRelation::subset + /// matches \c SetCompare::equal as well as \c SetCompare::properSuperset. + /////////////////////////////////////////////////////////////////// + struct ESetRelationDef { + enum Enum { + uncomparable = SetCompare::uncomparable, ///< "{??}" + equal = SetCompare::equal, ///< "{==}" + properSubset = SetCompare::properSubset, ///< "{<<}" + properSuperset = SetCompare::properSuperset, ///< "{>>}" + disjoint = SetCompare::disjoint, ///< "{ }" + subset = properSubset|equal, ///< "{<=}" + superset = properSuperset|equal, ///< "{>=}" + }; + /** String representantion */ + static const std::string & asString( Enum val_r ) ZYPP_API; + }; + /** \relates ESetRelationDef typedef 'enum class SetRelation' */ + using SetRelation = base::EnumClass; + + /** \relates SetRelation Stream output */ + inline std::ostream & operator<<( std::ostream & str, const SetRelation::Enum & obj ) + { return str << SetRelation::asString( obj ); } + /** \overload */ + inline std::ostream & operator<<( std::ostream & str, const SetRelation & obj ) + { return str << obj.asEnum(); } + + /** \relates SetRelation \relates SetCompare Matching \ref SetCompare and \ref SetRelation */ + inline bool operator==( const SetRelation::Enum & lhs, const SetCompare::Enum & rhs ) + { return( lhs&rhs || !(lhs|rhs) ); } + /** \overload */ + inline bool operator==( const SetRelation::Enum & lhs, const SetCompare & rhs ) + { return( lhs == rhs.asEnum() ); } + /** \overload */ + inline bool operator==( const SetRelation & lhs, const SetCompare::Enum & rhs ) + { return( lhs.asEnum() == rhs ); } + /** \overload */ + inline bool operator==( const SetRelation & lhs, const SetCompare & rhs ) + { return( lhs.asEnum() == rhs.asEnum() ); } + /** \overload */ + inline bool operator==( const SetCompare::Enum & lhs, const SetRelation::Enum & rhs ) + { return( rhs == lhs ); } + /** \overload */ + inline bool operator==( const SetCompare::Enum & lhs, const SetRelation & rhs ) + { return( rhs == lhs ); } + /** \overload */ + inline bool operator==( const SetCompare & lhs, const SetRelation::Enum & rhs ) + { return( rhs == lhs ); } + /** \overload */ + inline bool operator==( const SetCompare & lhs, const SetRelation & rhs ) + { return( rhs == lhs ); } + + /** \relates SetRelation \relates SetCompare Matching \ref SetCompare and \ref SetRelation */ + inline bool operator!=( const SetRelation::Enum & lhs, const SetCompare::Enum & rhs ) + { return !( lhs == rhs ); } + /** \overload */ + inline bool operator!=( const SetRelation::Enum & lhs, const SetCompare & rhs ) + { return !( lhs == rhs ); } + /** \overload */ + inline bool operator!=( const SetRelation & lhs, const SetCompare::Enum & rhs ) + { return !( lhs == rhs ); } + /** \overload */ + inline bool operator!=( const SetRelation & lhs, const SetCompare & rhs ) + { return !( lhs == rhs ); } + /** \overload */ + inline bool operator!=( const SetCompare::Enum & lhs, const SetRelation::Enum & rhs ) + { return !( lhs == rhs ); } + /** \overload */ + inline bool operator!=( const SetCompare::Enum & lhs, const SetRelation & rhs ) + { return !( lhs == rhs ); } + /** \overload */ + inline bool operator!=( const SetCompare & lhs, const SetRelation::Enum & rhs ) + { return !( lhs == rhs ); } + /** \overload */ + inline bool operator!=( const SetCompare & lhs, const SetRelation & rhs ) + { return !( lhs == rhs ); } + + /////////////////////////////////////////////////////////////////// + namespace base + { + /////////////////////////////////////////////////////////////////// + /// \class SetRelationMixin + /// \brief Provide set relation methods based on Derived::setRelationMixinCompare + /// A class using this mixin must provide: + /// \code + /// SetCompare setRelationMixinCompare( const Derived & rhs ) const; + /// \endcode + /// \see \ref SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN + /// \ingroup g_CRTP + /////////////////////////////////////////////////////////////////// + template + class SetRelationMixin + { + public: + /** Compare sets */ + SetCompare compare( const Derived & trg ) const + { return derived().setRelationMixinCompare( trg ); } + /** \overload */ + SetCompare compare( const SetRelationMixin & trg ) const + { return compare( trg.derived() ); } + + /** Compare sets and match against \ref SetCompare */ + bool compare( const Derived & trg, SetCompare cmp ) const + { return compare( trg ) == cmp; } + /** \overload */ + bool compare( const SetRelationMixin & trg, SetCompare cmp ) const + { return compare( trg ) == cmp; } + + /** Compare sets and match against \ref SetRelation */ + bool compare( const Derived & trg, SetRelation rel ) const + { return compare( trg ) == rel; } + /** \overload */ + bool compare( const SetRelationMixin & trg, SetRelation rel ) const + { return compare( trg ) == rel; } + + protected: + SetRelationMixin() {} + DEFAULT_COPYABLE( SetRelationMixin ); + DEFAULT_MOVABLE( SetRelationMixin ); + ~SetRelationMixin() {} + + private: + /** Access to sublass Derived*/ + const Derived & derived() const + { return *static_cast( this ); } + }; + + /** \relates SetRelationMixin Compare sets */ + template + inline SetCompare compare( const SetRelationMixin & src, const SetRelationMixin & trg ) + { return src.compare( trg ); } + + /** \relates SetRelationMixin Compare sets and match against \ref SetCompare */ + template + inline bool compare( const SetRelationMixin & src, const SetRelationMixin & trg, SetCompare cmp ) + { return src.compare( trg, cmp ); } + + /** \relates SetRelationMixin Compare sets and match against \ref SetRelation */ + template + inline bool compare( const SetRelationMixin & src, const SetRelationMixin & trg, SetRelation rel ) + { return src.compare( trg, rel ); } + + /** \relates SetRelationMixin Equal */ + template + inline bool operator==( const SetRelationMixin & src, const SetRelationMixin & trg ) + { return src.compare( trg, SetRelation::equal ); } + + /** \relates SetRelationMixin Unequal */ + template + inline bool operator!=( const SetRelationMixin & src, const SetRelationMixin & trg ) + { return !( src == trg ); } + + /** \relates SetRelationMixin Define compare between Derived and some other type (e.g. std::string) + * \code + * class Foo : public base::SetRelationMixin {...}; + * SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN( Foo, const char * ); + * SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN( Foo, const std::string & ); + * \endcode + */ +#define SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN(DERIVED_TYPE,OTHER_TYPE) \ + inline SetCompare compare( const base::SetRelationMixin & src, OTHER_TYPE trg ) \ + { return src.compare( DERIVED_TYPE(trg) ); } \ + inline SetCompare compare( OTHER_TYPE src, const base::SetRelationMixin & trg ) \ + { return DERIVED_TYPE(src).compare( trg ); } \ + \ + inline bool compare( const base::SetRelationMixin & src, OTHER_TYPE trg, SetCompare cmp ) \ + { return src.compare( DERIVED_TYPE(trg), cmp ); } \ + inline bool compare( OTHER_TYPE src, const base::SetRelationMixin & trg, SetCompare cmp ) \ + { return DERIVED_TYPE(src).compare( trg, cmp ); } \ + \ + inline bool compare( const base::SetRelationMixin & src, OTHER_TYPE trg, SetRelation rel ) \ + { return src.compare( DERIVED_TYPE(trg), rel ); } \ + inline bool compare( OTHER_TYPE src, const base::SetRelationMixin & trg, SetRelation rel ) \ + { return DERIVED_TYPE(src).compare( trg, rel ); } \ + \ + inline bool operator==( const base::SetRelationMixin & src, OTHER_TYPE trg ) \ + { return src.compare( DERIVED_TYPE(trg), SetRelation::equal ); } \ + inline bool operator==( OTHER_TYPE src, const base::SetRelationMixin & trg ) \ + { return DERIVED_TYPE(src).compare( trg, SetRelation::equal ); } \ + \ + inline bool operator!=( const base::SetRelationMixin & src, OTHER_TYPE trg ) \ + { return !( src == trg ); } \ + inline bool operator!=( OTHER_TYPE src, const base::SetRelationMixin & trg ) \ + { return !( src == trg ); } + + } // namespace base + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_SETRELATIONMIXIN_H diff --git a/zypp/base/SetTracker.h b/zypp/base/SetTracker.h new file mode 100644 index 0000000..795033d --- /dev/null +++ b/zypp/base/SetTracker.h @@ -0,0 +1,197 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/SetTracker.h + */ +#ifndef ZYPP_BASE_SETTRACKER_H +#define ZYPP_BASE_SETTRACKER_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace base + { + /////////////////////////////////////////////////////////////////// + /// \class SetTracker + /// \brief Track added/removed set items based on an initial set. + /// + /// The class maintains the \ref current set of items and also records + /// the changes compared to the initial set (\ref added and \ref removed + /// items) if you use the tracking API. + /// + /// It is also possible to directly manipulate the three sets. + /// + /// \note The tracking API expects the template arg to have set semantic. + /////////////////////////////////////////////////////////////////// + template + struct SetTracker + { + typedef TSet set_type; + typedef typename TSet::key_type key_type; + typedef typename TSet::value_type value_type; + + /** Default Ctor: empty set */ + SetTracker() + {} + + /** Ctor taking an initial set */ + SetTracker( set_type initial_r ) + : _current( std::move(initial_r) ) + {} + + /// \name Tracking API + //@{ + /** (Re-)Start tracking the current set (discards previously tracked changes). + * \return \c False (set did not change) + */ + bool setInitial() + { _added.clear(); _removed.clear(); return false; } + + /** Start tracking a new set (discards previously tracked changes). + * \return Whether the set did change (new!=current) + */ + bool setInitial( set_type new_r ) + { + setInitial(); + bool changed = ( new_r != _current ); + if ( changed ) + { + _current = std::move(new_r); + } + return changed; + } + + + /** Set a \a new_r set and track changes. + * \return Whether the set has changed + */ + bool set( set_type new_r ) + { + bool changed = ( new_r != _current ); + if ( changed ) + { + // build the initial (cur-add+rem) set in _current + setDifference( _current, _added, _removed ); + _current.swap( _removed ); + _added.clear(); + _removed.clear(); + + const set_type & initial( _current ); + setDifference( initial, new_r, _removed ); + setDifference( new_r, initial, _added ); + _current.swap( new_r ); + } + return changed; + } + + /** Add an element to the set and track changes. + * \return Whether the set has changed + */ + bool add( const value_type & val_r ) + { + bool done = _current.insert( val_r ).second; + if ( done ) + { + if ( ! _removed.erase( val_r ) ) + _added.insert( val_r ); + } + return done; + } + + /** Remove an element from the set and track changes. + * \return Whether the set has changed + */ + bool remove( const value_type & val_r ) + { + bool done = _current.erase( val_r ); + if ( done ) + { + if ( ! _added.erase( val_r ) ) + _removed.insert( val_r ); + } + return done; + } + //@} + + /// \name Query and retrieval + //@{ + /** Whether \a val_r is in the set. */ + bool contains( const key_type & key_r ) const { return find( _current, key_r ); } + + /** Whether \a val_r is tracked as added. */ + bool wasAdded( const key_type & key_r ) const { return find( _added, key_r ); } + + /** Whether \a val_r is tracked as removed. */ + bool wasRemoved( const key_type & key_r ) const { return find( _removed, key_r ); } + + + /** Return the current set. */ + const set_type & current() const { return _current; } + + /** Return the set of added items. */ + const set_type & added() const { return _added; } + + /** Return the set of removed items. */ + const set_type & removed() const { return _removed; } + //@} + + /// \name Direct manipulation + //@{ + /** Return the current set. */ + set_type & current() { return _current; } + + /** Return the set of added items. */ + set_type & added() { return _added; } + + /** Return the set of removed items. */ + set_type & removed() { return _removed; } + //@} + + private: + + static bool find( const set_type & set_r, const key_type & key_r ) + { return set_r.find( key_r ) != set_r.end(); } + + template + static void setDifference( const TORDERED_SET & lhs, const TORDERED_SET & rhs, TORDERED_SET & result_r ) + { + // std::set_difference requires ordered sets! + std::set_difference( lhs.begin(), lhs.end(), rhs.begin(), rhs.end(), + std::inserter( result_r, result_r.end() ), + typename TORDERED_SET::key_compare() ); + } + + template + static void setDifference( const TUNORDERED_SET & lhs, const TUNORDERED_SET & rhs, TUNORDERED_SET & result_r ) + { + // std::set_difference requires ordered sets! + for ( const auto & l : lhs ) + { if ( rhs.find( l ) == rhs.end() ) result_r.insert( l ); } + } + + private: + set_type _current; + set_type _added; + set_type _removed; + }; + + /** \relates SetTracker Stream output */ + template + std::ostream & operator<<( std::ostream & str, const SetTracker & obj ) + { return str << "set(" << obj.current().size() << "|+" << obj.added().size() << "|-" << obj.removed().size() << ')'; } + + } // namespace base + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_SETTRACKER_H diff --git a/zypp/base/Signal.h b/zypp/base/Signal.h new file mode 100644 index 0000000..d733acb --- /dev/null +++ b/zypp/base/Signal.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/Signal.h + * +*/ +#ifndef ZYPP_BASE_SIGNAL_H +#define ZYPP_BASE_SIGNAL_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Exception safe signal handler save/restore. + * \ingroup g_RAII + */ + class SignalSaver + { + public: + SignalSaver( int signum_r, sighandler_t handler_r ) + : _signum( signum_r ) + { _orighandler = ::signal( signum_r, handler_r ); } + ~SignalSaver() + { ::signal( _signum, _orighandler ); } + private: + int _signum; + ::sighandler_t _orighandler; + }; + + /** Exception safe sigprocmask save/restore. + * \ingroup g_RAII + */ + class SigprocmaskSaver + { + public: + /** Ctor saving the original sigprocmask. */ + SigprocmaskSaver() + { ::sigprocmask( SIG_SETMASK, NULL, &_origmask ); } + /** Dtor restoring the original sigprocmask. */ + ~SigprocmaskSaver() + { ::sigprocmask( SIG_SETMASK, &_origmask, NULL ); } + public: + /** Temporary block signal. */ + void block( int signum_r ) + { + ::sigset_t mask; + ::sigemptyset( & mask ); + ::sigaddset( & mask, signum_r ); + ::sigprocmask( SIG_BLOCK, &mask, NULL ); + } + /** Temporary unblock signal. */ + void unblock( int signum_r ) + { + ::sigset_t mask; + ::sigemptyset( & mask ); + ::sigaddset( & mask, signum_r ); + ::sigprocmask( SIG_UNBLOCK, &mask, NULL ); + } + /** Whether signal delivery is pending. */ + bool pending( int signum_r ) + { + ::sigset_t mask; + ::sigpending( &mask ); + return ::sigismember( &mask, signum_r ); + } + /** Wait for signals not blocked in original sigprocmask. */ + void suspend() + { ::sigsuspend( &_origmask ); } + private: + ::sigset_t _origmask; + }; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_SIGNAL_H diff --git a/zypp/base/SimpleStreambuf.h b/zypp/base/SimpleStreambuf.h new file mode 100644 index 0000000..fbe9c09 --- /dev/null +++ b/zypp/base/SimpleStreambuf.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/StrMatcher.cc b/zypp/base/StrMatcher.cc new file mode 100644 index 0000000..b8b73db --- /dev/null +++ b/zypp/base/StrMatcher.cc @@ -0,0 +1,349 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/StrMatcher.cc + * +*/ +extern "C" +{ +#include +} + +#include +#include + +#include +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + // class Match + /////////////////////////////////////////////////////////////////// + + const int Match::_modemask = SEARCH_STRINGMASK; + const int Match::_flagmask = ~_modemask; + + // option flags + const Match Match::NOCASE (SEARCH_NOCASE); + + // sat::LookupAttr option flags + const Match Match::NO_STORAGE_SOLVABLE(SEARCH_NO_STORAGE_SOLVABLE); + const Match Match::SUB (SEARCH_SUB); + const Match Match::ARRAYSENTINEL (SEARCH_ARRAYSENTINEL); + const Match Match::DISABLED_REPOS (SEARCH_DISABLED_REPOS); + const Match Match::COMPLETE_FILELIST (SEARCH_COMPLETE_FILELIST); + const Match Match::SKIP_KIND (SEARCH_SKIP_KIND); + const Match Match::FILES (SEARCH_FILES); + const Match Match::CHECKSUMS (SEARCH_CHECKSUMS); + + Match::Mode Match::mode() const + { + switch ( modeval() ) + { + case 0: return NOTHING; break; + case SEARCH_STRING: return STRING; break; + case SEARCH_STRINGSTART: return STRINGSTART; break; + case SEARCH_STRINGEND: return STRINGEND; break; + case SEARCH_SUBSTRING: return SUBSTRING; break; + case SEARCH_GLOB: return GLOB; break; + case SEARCH_REGEX: return REGEX; break; + } + return OTHER; + } + + int Match::modeval( Mode mode_r ) + { + switch ( mode_r ) + { + case NOTHING: return 0; break; + case STRING: return SEARCH_STRING; break; + case STRINGSTART: return SEARCH_STRINGSTART; break; + case STRINGEND: return SEARCH_STRINGEND; break; + case SUBSTRING: return SEARCH_SUBSTRING; break; + case GLOB: return SEARCH_GLOB; break; + case REGEX: return SEARCH_REGEX; break; + case OTHER: return SEARCH_STRINGMASK; break; + } + return SEARCH_STRINGMASK; + } + + std::string Match::asString() const + { std::ostringstream str; str << *this; return str.str(); } + + std::ostream & operator<<( std::ostream & str, Match::Mode obj ) + { + switch ( obj ) + { +#define OUTS(V) case Match::V: return str << #V; break + OUTS( NOTHING ); + OUTS( STRING ); + OUTS( STRINGSTART ); + OUTS( STRINGEND ); + OUTS( SUBSTRING ); + OUTS( GLOB ); + OUTS( REGEX ); + OUTS( OTHER ); +#undef OUTS + } + return str << "Match::Mode::UNKNOWN"; + } + + std::ostream & operator<<( std::ostream & str, const Match & obj ) + { + if ( ! obj ) + return str << "NOTHING"; + + const char * sep = "|"; + Match::Mode mode( obj.mode() ); + switch ( mode ) + { + case Match::NOTHING: + sep = 0; // suppress 'NOTHING|' + break; + case Match::OTHER: + str << mode<<"("< _matcher; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( _search, _flags ); } + }; + + /** \relates StrMatcher::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const StrMatcher::Impl & obj ) + { + return str << "\"" << obj.searchstring() << "\"{" << obj.flags() << "}"; + } + + /////////////////////////////////////////////////////////////////// + // class StrMatcher + /////////////////////////////////////////////////////////////////// + + StrMatcher::StrMatcher() + : _pimpl( new Impl ) + {} + + StrMatcher::StrMatcher( const std::string & search_r ) + : _pimpl( new Impl( search_r, Match::STRING ) ) + {} + StrMatcher::StrMatcher( std::string && search_r ) + : _pimpl( new Impl( std::move(search_r), Match::STRING ) ) + {} + + StrMatcher::StrMatcher( const std::string & search_r, const Match & flags_r ) + : _pimpl( new Impl( search_r, flags_r ) ) + {} + StrMatcher::StrMatcher( std::string && search_r, const Match & flags_r ) + : _pimpl( new Impl( std::move(search_r), flags_r ) ) + {} + + StrMatcher::StrMatcher( const std::string & search_r, const Match::Mode & flags_r ) + : _pimpl( new Impl( search_r, flags_r ) ) + {} + StrMatcher::StrMatcher( std::string && search_r, const Match::Mode & flags_r ) + : _pimpl( new Impl( std::move(search_r), flags_r ) ) + {} + + StrMatcher::StrMatcher( const std::string & search_r, int flags_r ) + : _pimpl( new Impl( search_r, Match(flags_r) ) ) + {} + StrMatcher::StrMatcher( std::string && search_r, int flags_r ) + : _pimpl( new Impl( std::move(search_r), Match(flags_r) ) ) + {} + + void StrMatcher::compile() const + { return _pimpl->compile(); } + + bool StrMatcher::isCompiled() const + { return _pimpl->isCompiled(); } + + bool StrMatcher::doMatch( const char * string_r ) const + { return _pimpl->doMatch( string_r ); } + + const std::string & StrMatcher::searchstring() const + { return _pimpl->searchstring(); } + + void StrMatcher::setSearchstring( const std::string & string_r ) + { _pimpl->setSearchstring( string_r ); } + void StrMatcher::setSearchstring( std::string && string_r ) + { _pimpl->setSearchstring( std::move(string_r) ); } + + void StrMatcher::setSearchstring( const std::string & string_r, const Match & flags_r ) + { + _pimpl->setSearchstring( string_r ); + _pimpl->setFlags( flags_r ); + } + void StrMatcher::setSearchstring( std::string && string_r, const Match & flags_r ) + { + _pimpl->setSearchstring( std::move(string_r) ); + _pimpl->setFlags( flags_r ); + } + + const Match & StrMatcher::flags() const + { return _pimpl->flags(); } + + void StrMatcher::setFlags( const Match & flags_r ) + { _pimpl->setFlags( flags_r ); } + + std::ostream & operator<<( std::ostream & str, const StrMatcher & obj ) + { return str << *obj._pimpl; } + + bool operator==( const StrMatcher & lhs, const StrMatcher & rhs ) + { + return ( lhs.flags() == rhs.flags() + && lhs.searchstring() == rhs.searchstring() ); + } + + bool operator<( const StrMatcher & lhs, const StrMatcher & rhs ) + { + if ( lhs.flags().get() != rhs.flags().get() ) + return ( lhs.flags().get() < rhs.flags().get() ); + + return ( lhs.searchstring() < rhs.searchstring() ); + } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/base/StrMatcher.h b/zypp/base/StrMatcher.h new file mode 100644 index 0000000..43c7f60 --- /dev/null +++ b/zypp/base/StrMatcher.h @@ -0,0 +1,410 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/StrMatcher.h + * +*/ +#ifndef ZYPP_BASE_STRMATCHER_H +#define ZYPP_BASE_STRMATCHER_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class Match + /// \brief String matching option flags as used e.g. by \ref StrMatcher. + /// + /// \code + /// Match mode( Match::GLOB | Match::NOCASE ); + /// \endcode + /////////////////////////////////////////////////////////////////// + class ZYPP_API Match + { + private: + static const int _modemask; + static const int _flagmask; + + public: + /** Mode flags (mutual exclusive). */ + enum Mode + { + NOTHING, //!< Match nothing + STRING, //!< Excat matching + STRINGSTART, //!< Match at string start + STRINGEND, //!< Match at string end + SUBSTRING, //!< Match substring + GLOB, //!< Glob + REGEX, //!< Regular Expression + OTHER //!< Something else. + }; + + /** \name \ref Option flags + * Most flags are actually \ref sat::LookupAttr specific, as they tell + * how to retrieve the attribute values from solv-files. The plain + * \ref StrMatcher will ignore those flags and use the ones related + * to string matching only. + */ + //@{ + static const Match NOCASE; //!< If set, match case insensitive. + //@} + + /** \name \ref sat::LookupAttr option flags + * These flags are actually \ref sat::LookupAttr specific, as they tell + * how to retrieve the attribute values from solv-files. The plain + * \ref StrMatcher will ignore these flags and use the ones related + * to string matching only. + */ + //@{ + static const Match NO_STORAGE_SOLVABLE; //!< LookupAttr: internal + static const Match SUB; //!< LookupAttr: internal + static const Match ARRAYSENTINEL; //!< LookupAttr: internal + static const Match DISABLED_REPOS; //!< LookupAttr: internal + static const Match COMPLETE_FILELIST; //!< LookupAttr: internal + static const Match SKIP_KIND; //!< LookupAttr: skip any \c kind: prefix when looking at a \ref Solvable name. + static const Match FILES; //!< LookupAttr: match full path when matching in filelists, otherwise just the basenames. + static const Match CHECKSUMS; //!< LookupAttr: also look for matches in checksums + //@} + + public: + /** Default ctor \c 0 or \ref NOTHING. */ + Match() + : _val( 0 ) + {} + + /** Ctor from \ref Mode value. */ + Match( Mode val_r ) + : _val( modeval( val_r ) ) + {} + + /** Just in case one needs it. */ + explicit Match( int val_r ) + : _val( val_r ) + {} + + /** Evaluate in a boolean context ( != 0 ). */ + explicit operator bool() const + { return _val; } + + public: + /** Test whether \c all of the \a rhs bits are set (same mode if \a rhs has one). */ + bool test( const Match & rhs ) const + { return ( ( flagval() & rhs.flagval() ) == rhs.flagval() ) && ( !rhs.modeval() || rhs.modeval() == modeval() ); } + + /** Whether at least one of the \a rhs bits is set (or the same mode). */ + bool testAnyOf( const Match & rhs ) const + { return ( flagval() & rhs.flagval() ) || ( rhs.modeval() && rhs.modeval() == modeval() ); } + + /** Set all of the \a rhs bits (setting a new mode if \a rhs has one). */ + void set( const Match & rhs ) + { + if ( rhs.modeval() ) + _val = rhs._val | flagval(); // also set the rhs mode + else + _val |= rhs._val; // just set the flags + } + + /** Unset all of the \a rhs bits (unsets mode if the same as \a rhs). */ + void unset( const Match & rhs ) + { + if ( modeval() == rhs.modeval() ) + _val = flagval() & ~rhs.flagval(); // also unset mode + else + _val &= ~rhs.flagval(); // just unset falgs + } + + /** Depending on the value of \a onoff, set or unset flags. */ + void turn( const Match & rhs, bool onoff ) + { onoff ? set( rhs ) : unset( rhs ); } + + /** Add flags. */ + Match & operator|=( const Match & rhs ) + { set( rhs ); return *this; } + + /** Remove flags.*/ + Match & operator-=( const Match & rhs ) + { unset( rhs ); return *this; } + + public: + /** Return the \c mode part. */ + Mode mode() const; + + /** Return the \c flags part. */ + Match flags() const + { return Match( flagval() ); } + + public: + /** \name Low level integer representation. */ + //@{ + /** Return the integer representation. */ + int get() const { return _val; } + /** Return the modes integer representation. */ + int modeval() const { return _val & _modemask; } + /** Return the flags integer representation. */ + int flagval() const { return _val & _flagmask; } + //@} + + public: + /** \name Mode flag manip/query convenience. */ + //@{ + /** Whether this has mode \a rhs */ + bool isMode( Mode rhs ) const + { return modeval() == modeval( rhs ); } + /** Whether this has mode \ref STRING. */ + bool isModeString() const + { return isMode( STRING ); } + /** Whether this has mode \ref STRINGSTART. */ + bool isModeStringstart() const + { return isMode( STRINGSTART ); } + /** Whether this has mode \ref STRINGEND. */ + bool isModeStringend() const + { return isMode( STRINGEND ); } + /** Whether this has mode \ref SUBSTRING. */ + bool isModeSubstring() const + { return isMode( SUBSTRING ); } + /** Whether this has mode \ref GLOB. */ + bool isModeGlob() const + { return isMode( GLOB ); } + /** Whether this has mode \ref REGEX. */ + bool isModeRegex() const + { return isMode( REGEX ); } + + /** Set the mode part to \a rhs . */ + void setMode( Mode rhs ) + { _val = modeval( rhs ) | flagval(); } + /** Set the mode \ref STRING. */ + void setModeString() + { setMode( STRING ); } + /** Set the mode \ref STRINGSTART. */ + void setModeStringstart() + { setMode( STRINGSTART ); } + /** Set the mode \ref STRINGEND. */ + void setModeStringend() + { setMode( STRINGEND ); } + /** Set the mode \ref SUBSTRING. */ + void setModeSubstring() + { setMode( SUBSTRING ); } + /** Set the mode \ref GLOB. */ + void setModeGlob() + { setMode( GLOB ); } + /** Set the mode \ref REGEX. */ + void setModeRegex() + { setMode( REGEX ); } + //@} + + /** String representation. */ + std::string asString() const; + + private: + /** Numeric value for enum (short for Match(m).get()). */ + static int modeval( Mode mode_r ); + + private: + int _val; + }; + + /** \relates Match */ + inline bool operator==( const Match & lhs, const Match & rhs ) + { return lhs.get() == rhs.get(); } + /** \relates Match */ + inline bool operator!=( const Match & lhs, const Match & rhs ) + { return lhs.get() != rhs.get(); } + + /** \relates Match */ + inline Match operator|( const Match & lhs, const Match & rhs ) + { return Match(lhs) |= rhs; } + /** \relates Match \overload to disambiguate 'int|int'. */ + inline Match operator|( Match::Mode lhs, Match::Mode rhs ) + { return Match(lhs) |= rhs; } + + /** \relates Match */ + inline Match operator-( const Match & lhs, const Match & rhs ) + { return Match(lhs) -= rhs; } + /** \relates Match \overload to disambiguate 'int-int'. */ + inline Match operator-( Match::Mode lhs, Match::Mode rhs ) + { return Match(lhs) -= rhs; } + + /** \relates Match::Mode Stream output */ + std::ostream & operator<<( std::ostream & str, Match::Mode obj ) ZYPP_API; + + /** \relates Match Stream output */ + std::ostream & operator<<( std::ostream & str, const Match & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + /// \class MatchException + /// \brief Exceptions thrown from attribute matching. + /////////////////////////////////////////////////////////////////// + struct ZYPP_API MatchException : public Exception + { + /** Supplied message. */ + explicit MatchException( const std::string & msg_r ) : Exception( msg_r ) {} + }; + + /////////////////////////////////////////////////////////////////// + /// \class MatchUnknownModeException + /// \brief Unknown match mode. + /////////////////////////////////////////////////////////////////// + struct ZYPP_API MatchUnknownModeException : public MatchException + { + /** Supplied message. */ + explicit MatchUnknownModeException( const std::string & msg_r ) : MatchException( msg_r ) {} + + /** Build message including the \a mode and optional the pattern string. */ + MatchUnknownModeException( const Match & mode_r, const std::string & msg_r = std::string() ); + }; + + /////////////////////////////////////////////////////////////////// + /// \class MatchInvalidRegexException + /// \brief Invalid regular expression (failed ::regcomp). + /////////////////////////////////////////////////////////////////// + struct ZYPP_API MatchInvalidRegexException : public MatchException + { + /** Supplied message. */ + explicit MatchInvalidRegexException( const std::string & msg_r ) : MatchException( msg_r ) {} + + /** Build message including the \a regex and \c ::regcomp returncode (use \c 0 if unknown). */ + MatchInvalidRegexException( const std::string & regex_r, int regcomp_r ); + }; + + /////////////////////////////////////////////////////////////////// + /// \class StrMatcher + /// \brief String matching (STRING|SUBSTRING|GLOB|REGEX). + /// + /// Used by e.g. \ref PoolQuery and \ref LookupAttr for queries, + /// but it can also be used for matching arbitrary strings. + /// + /// \code + /// StrMatcher matches( "foo", Match::SUBSTRING ); + /// for_( it, stringlist.begin(), stringlist().end() ) + /// { + /// if ( matches( *it ) ) + /// cout << *it << " has substring 'foo'" << endl; + /// } + /// \endcode + /// + /// \Note Those flags are always set: REG_EXTENDED | REG_NOSUB | REG_NEWLINE + /////////////////////////////////////////////////////////////////// + class StrMatcher + { + friend std::ostream & operator<<( std::ostream & str, const StrMatcher & obj ); + + public: + using Exception = MatchException; + + public: + /** Implementation */ + struct Impl; + + public: + /** Default ctor matches nothing. */ + StrMatcher(); + + /** Ctor from string matches in \ref Match::STRING mode per default. */ + StrMatcher( const std::string & search_r ); + /** \overload for rvalues */ + StrMatcher( std::string && search_r ); + + /** Ctor taking string and \ref Match flags. */ + StrMatcher( const std::string & search_r, const Match & flags_r ); + /** \overload for rvalues */ + StrMatcher( std::string && search_r, const Match & flags_r ); + + /** Ctor taking string and \ref Match::Mode. + * Needed because we want them to be treated as \ref Match, + * and not as \ref int as the compiler woud do. + */ + StrMatcher( const std::string & search_r, const Match::Mode & flags_r ); + /** \overload for rvalues */ + StrMatcher( std::string && search_r, const Match::Mode & flags_r ); + + /** Low level interface wraps \a flags into \ref Match. */ + StrMatcher( const std::string & search_r, int flags_r ); + /** \overload for rvalues */ + StrMatcher( std::string && search_r, int flags_r ); + + /** Evaluate in a boolean context ( ! searchstring().empty() ). */ + explicit operator bool() const + { return !searchstring().empty(); } + + public: + /** Return whether string matches. + * You can use it with any class that impements \c c_str. + * (\c std::string, \ref Pathname, \ref IdString, ...). + * \Note \c NULL never matches. + */ + template + bool operator()( const Tp & string_r ) const + { return doMatch( string_r.c_str() ); } + /** \overload */ + bool operator()( const char * string_r ) const + { return doMatch( string_r ); } + + public: + /** The current searchstring. */ + const std::string & searchstring() const; + + /** Set a new searchstring. */ + void setSearchstring( const std::string & string_r ); + /** \overload for rvalues */ + void setSearchstring( std::string && string_r ); + + /** Set a new searchstring and flags. */ + void setSearchstring( const std::string & string_r, const Match & flags_r ); + /** \overload for rvalues */ + void setSearchstring( std::string && string_r, const Match & flags_r ); + + /** The current search flags. */ + const Match & flags() const; + + /** Set new search flags. */ + void setFlags( const Match & flags_r ); + + public: + /** Compile the pattern e.g. in case of \c REGEX. + * \throws MatchUnknownModeException If the \ref Match flag more than + * one mode bit set. + * \throws MatchInvalidRegexException If \ref Match::REGEX is set + * and \ref searchstring is not a valid regular expression. + */ + void compile() const; + + /** Whether the \ref StrMatcher is already compiled. */ + bool isCompiled() const; + + /** Return whether string matches. + * Compiles the \ref StrMatcher if this was not yet done. + * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile. + */ + bool doMatch( const char * string_r ) const; + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + + /** \relates StrMatcher Stream output */ + std::ostream & operator<<( std::ostream & str, const StrMatcher & obj ); + + /** \relates StrMatcher */ + bool operator==( const StrMatcher & lhs, const StrMatcher & rhs ); + + /** \relates StrMatcher */ + inline bool operator!=( const StrMatcher & lhs, const StrMatcher & rhs ) + { return !( lhs == rhs ); } + + /** \relates StrMatcher Arbitrary order for std::container. */ + bool operator<( const StrMatcher & lhs, const StrMatcher & rhs ); + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_STRMATCHER_H diff --git a/zypp/base/String.h b/zypp/base/String.h new file mode 100644 index 0000000..62cb1ec --- /dev/null +++ b/zypp/base/String.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/StringV.h b/zypp/base/StringV.h new file mode 100644 index 0000000..620f719 --- /dev/null +++ b/zypp/base/StringV.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Sysconfig.h b/zypp/base/Sysconfig.h new file mode 100644 index 0000000..c16b25b --- /dev/null +++ b/zypp/base/Sysconfig.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/TypeTraits.h b/zypp/base/TypeTraits.h new file mode 100644 index 0000000..9d93cd4 --- /dev/null +++ b/zypp/base/TypeTraits.h @@ -0,0 +1,58 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/TypeTraits.h + */ +#ifndef ZYPP_TYPETRAITS_H +#define ZYPP_TYPETRAITS_H + +#include + +/////////////////////////////////////////////////////////////////// +// Helper types from https://en.cppreference.com/ +namespace std +{ +#if __cplusplus < 202002L + +#endif // __cplusplus < 202002L + + +#if __cplusplus < 201703L + template< class Base, class Derived > + inline constexpr bool is_base_of_v = is_base_of::value; + + template< class T > + inline constexpr bool is_integral_v = is_integral::value; + + template< class T > + inline constexpr bool is_pointer_v = is_pointer::value; +#endif // __cplusplus < 201703L + + +#if __cplusplus < 201402L + template< bool B, class T, class F > + using conditional_t = typename conditional::type; + + template< class T > + using decay_t = typename decay::type; + + template< bool B, class T = void > + using enable_if_t = typename enable_if::type; + + template< class T > + using remove_reference_t = typename remove_reference::type; + + template< class T > + using result_of_t = typename result_of::type; + + template< class T > + using underlying_type_t = typename underlying_type::type; +#endif // __cplusplus < 201402L +} // namespace std +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TYPETRAITS_H diff --git a/zypp/base/Unit.h b/zypp/base/Unit.h new file mode 100644 index 0000000..e91d22b --- /dev/null +++ b/zypp/base/Unit.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/UserRequestException.h b/zypp/base/UserRequestException.h new file mode 100644 index 0000000..613729c --- /dev/null +++ b/zypp/base/UserRequestException.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/ValueTransform.h b/zypp/base/ValueTransform.h new file mode 100644 index 0000000..be851a3 --- /dev/null +++ b/zypp/base/ValueTransform.h @@ -0,0 +1,168 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/base/ValueTransform.h + */ +#ifndef ZYPP_BASE_VALUETRANSFORM_H +#define ZYPP_BASE_VALUETRANSFORM_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace base + { + /////////////////////////////////////////////////////////////////// + /// \class ValueTransform + /// \brief Helper managing raw values with transformed representation + /// + /// This helper enforces to explicitly state whether you are using + /// the raw or the variable replaced value. Usually you set \c raw + /// and get \c transformed (unless writing \c raw to some config file). + /// + /// Used e.g. vor variable replaced config strings. + /////////////////////////////////////////////////////////////////// + template + struct ValueTransform + { + using RawType = Tp; + using Transformator = TUnaryFunction; + using TransformedType = std::result_of_t; + + public: + ValueTransform() + {} + + explicit ValueTransform( RawType raw_r ) + : _raw( std::move(raw_r) ) + {} + + ValueTransform( RawType raw_r, Transformator transform_r ) + : _raw( std::move(raw_r) ), _transform( std::move(transform_r) ) + {} + + public: + /** Get the raw value */ + const RawType & raw() const + { return _raw; } + + /** Set the raw value */ + RawType & raw() + { return _raw; } + + public: + /** Return a transformed copy of the raw value */ + TransformedType transformed() const + { return _transform( _raw ); } + + /** Return a transformed copy of an arbitrary \a RawType */ + TransformedType transformed( const RawType & raw_r ) const + { return _transform( raw_r ); } + + /** Return the transformator */ + const Transformator & transformator() const + { return _transform; } + + private: + RawType _raw; + Transformator _transform; + }; + + /////////////////////////////////////////////////////////////////// + /// \class ContainerTransform + /// \brief Helper managing a container of raw values with transformed representation + /// + /// This helper enforces to explicitly state wheter you are using + /// the raw or the variable replaced value. Usually you set \c raw + /// and get \c transformed (uness writing \c raw to some config file). + /// + /// Offers iterating over transformed strings in the list. + /////////////////////////////////////////////////////////////////// + template + struct ContainerTransform + { + using Container = TContainer; + using Transformator = TUnaryFunction; + using size_type = typename Container::size_type; + using RawType = typename Container::value_type; + using TransformedType = std::result_of_t; + + public: + ContainerTransform() + {} + + explicit ContainerTransform( Container raw_r ) + : _raw( std::move(raw_r) ) + {} + + ContainerTransform( Container raw_r, Transformator transform_r ) + : _raw( std::move(raw_r) ), _transform( std::move(transform_r) ) + {} + + public: + bool empty() const + { return _raw.empty(); } + + size_type size() const + { return _raw.size(); } + + using RawConstIterator = typename Container::const_iterator; + + RawConstIterator rawBegin() const + { return _raw.begin(); } + + RawConstIterator rawEnd() const + { return _raw.end(); } + + /** Get the raw value */ + const Container & raw() const + { return _raw; } + + /** Set the raw value */ + Container & raw() + { return _raw; } + + public: + using TransformedConstIterator = transform_iterator; + + TransformedConstIterator transformedBegin() const + { return make_transform_iterator( _raw.begin(), _transform ); } + + TransformedConstIterator transformedEnd() const + { return make_transform_iterator( _raw.end(), _transform ); } + + /** Return copy with transformed variables (expensive) */ + Container transformed() const + { return Container( transformedBegin(), transformedEnd() ); } + + /** Return a transformed copy of an arbitrary \a RawType */ + TransformedType transformed( const RawType & raw_r ) const + { return _transform( raw_r ); } + + /** Return a transformed copy of a \a RawConstIterator raw value */ + TransformedType transformed( const RawConstIterator & rawIter_r ) const + { return _transform( *rawIter_r ); } + + /** Return the transformator */ + const Transformator & transformator() const + { return _transform; } + + private: + Container _raw; + Transformator _transform; + }; + + } // namespace base + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BASE_VALUETRANSFORM_H diff --git a/zypp/base/WatchFile.h b/zypp/base/WatchFile.h new file mode 100644 index 0000000..663b71d --- /dev/null +++ b/zypp/base/WatchFile.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/Xml.h b/zypp/base/Xml.h new file mode 100644 index 0000000..b852cde --- /dev/null +++ b/zypp/base/Xml.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/ZckStream.h b/zypp/base/ZckStream.h new file mode 100644 index 0000000..8ee7800 --- /dev/null +++ b/zypp/base/ZckStream.h @@ -0,0 +1 @@ +#include diff --git a/zypp/base/fXstream.h b/zypp/base/fXstream.h new file mode 100644 index 0000000..d0caaee --- /dev/null +++ b/zypp/base/fXstream.h @@ -0,0 +1 @@ +#include diff --git a/zypp/libzypp.map b/zypp/libzypp.map new file mode 100644 index 0000000..57fae15 --- /dev/null +++ b/zypp/libzypp.map @@ -0,0 +1,12 @@ +ZYPP_plain { + global: + extern "C++" { + zypp::*; + vtable?for?zypp::*; + typeinfo?for?zypp::*; + typeinfo?name?for?zypp::*; + guard?variable?for?zypp::*; + }; + local: + *; +}; diff --git a/zypp/media/CredentialFileReader.h b/zypp/media/CredentialFileReader.h new file mode 100644 index 0000000..da0d8fa --- /dev/null +++ b/zypp/media/CredentialFileReader.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/CredentialManager.h b/zypp/media/CredentialManager.h new file mode 100644 index 0000000..61dd4a2 --- /dev/null +++ b/zypp/media/CredentialManager.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/CurlConfig.h b/zypp/media/CurlConfig.h new file mode 100644 index 0000000..f710b72 --- /dev/null +++ b/zypp/media/CurlConfig.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/MediaBlockList.h b/zypp/media/MediaBlockList.h new file mode 100644 index 0000000..e6424ea --- /dev/null +++ b/zypp/media/MediaBlockList.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/MediaCD.cc b/zypp/media/MediaCD.cc new file mode 100644 index 0000000..0b73935 --- /dev/null +++ b/zypp/media/MediaCD.cc @@ -0,0 +1,674 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCD.cc + * +*/ +extern "C" +{ +#include +#include +#if HAVE_UDEV +#include +#endif +} + +#include // strerror +#include // getenv +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; + +/* +** if to throw exception on eject errors or ignore them +*/ +#define REPORT_EJECT_ERRORS 0 + + +////////////////////////////////////////////////////////////////// +namespace zypp +{ + ////////////////////////////////////////////////////////////////// + namespace media + { + + ////////////////////////////////////////////////////////////////// + namespace + { + using DeviceList = std::list; + + ////////////////////////////////////////////////////////////////// + /// \brief Try to detect cd/dvd devices using udev + /// + /// Returns an empty device list on error. + ////////////////////////////////////////////////////////////////// + DeviceList systemDetectDevices( bool supportingDVD_r ) + { + DeviceList detected; + +#ifdef HAVE_UDEV + // http://www.kernel.org/pub/linux/utils/kernel/hotplug/libudev/index.html + zypp::AutoDispose udev( ::udev_new(), ::udev_unref ); + if ( ! udev ) + { + ERR << "Can't create udev context." << endl; + return DeviceList(); + } + + zypp::AutoDispose enumerate( ::udev_enumerate_new(udev), ::udev_enumerate_unref ); + if ( ! enumerate ) + { + ERR << "Can't create udev list entry." << endl; + return DeviceList(); + } + + ::udev_enumerate_add_match_subsystem( enumerate, "block" ); + ::udev_enumerate_add_match_property( enumerate, "ID_CDROM", "1" ); + ::udev_enumerate_scan_devices( enumerate ); + + struct udev_list_entry * entry = 0; + udev_list_entry_foreach( entry, ::udev_enumerate_get_list_entry( enumerate ) ) + { + zypp::AutoDispose device( ::udev_device_new_from_syspath( ::udev_enumerate_get_udev( enumerate ), + ::udev_list_entry_get_name( entry ) ), + ::udev_device_unref ); + if ( ! device ) + { + ERR << "Can't create udev device." << endl; + continue; + } + + if ( supportingDVD_r && ! ::udev_device_get_property_value( device, "ID_CDROM_DVD" ) ) + { + continue; // looking for dvd only + } + + const char * devnodePtr( ::udev_device_get_devnode( device ) ); + if ( ! devnodePtr ) + { + ERR << "Got NULL devicenode." << endl; + continue; + } + + // In case we need it someday: + //const char * mountpath = ::udev_device_get_property_value( device, "FSTAB_DIR" ); + + PathInfo devnode( devnodePtr ); + if ( devnode.isBlk() ) + { + MediaSource media( "cdrom", devnode.path().asString(), devnode.devMajor(), devnode.devMinor() ); + DBG << "Found (udev): " << media << std::endl; + detected.push_back( media ); + } + } + if ( detected.empty() ) + { + WAR << "Did not find any CD/DVD device." << endl; + } +#endif + return detected; + } + + } // namespace + ////////////////////////////////////////////////////////////////// + + + MediaCD::MediaCD( const Url & url_r, const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, url_r.getPathName(), false ) + , _lastdev( -1 ) + , _lastdev_tried( -1 ) + { + MIL << "MediaCD::MediaCD(" << url_r << ", " << attach_point_hint_r << ")" << endl; + + if ( url_r.getScheme() != "dvd" && url_r.getScheme() != "cd" ) + { + ERR << "Unsupported schema in the Url: " << url_r.asString() << endl; + ZYPP_THROW(MediaUnsupportedUrlSchemeException(_url)); + } + + std::string devices = _url.getQueryParam( "devices" ); + if ( ! devices.empty() ) + { + std::vector words; + str::split( devices, std::back_inserter(words), "," ); + for ( const std::string & device : words ) + { + if ( device.empty() ) + continue; + + MediaSource media( "cdrom", device, 0, 0 ); + _devices.push_back( media ); + DBG << "use device (delayed verify)" << device << endl; + } + } + else + { + DBG << "going to use on-demand device list" << endl; + return; + } + + if ( _devices.empty() ) + { + ERR << "Unable to find any cdrom drive for " << _url.asString() << endl; + ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url)); + } + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::openTray + // METHOD TYPE : bool + // + bool MediaCD::openTray( const std::string & device_r ) + { + return CDTools::openTray(device_r); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::closeTray + // METHOD TYPE : bool + // + bool MediaCD::closeTray( const std::string & device_r ) + { + return CDTools::closeTray(device_r); + } + + + MediaCD::DeviceList MediaCD::detectDevices( bool supportingDVD_r ) const + { + DeviceList detected( systemDetectDevices( supportingDVD_r ) ); + + if ( detected.empty() ) + { + WAR << "CD/DVD drive detection with UDEV failed! Guessing..." << std::endl; + PathInfo dvdinfo( "/dev/dvd" ); + PathInfo cdrinfo( "/dev/cdrom" ); + if ( dvdinfo.isBlk() ) + { + MediaSource media( "cdrom", dvdinfo.path().asString(), dvdinfo.devMajor(), dvdinfo.devMinor() ); + DBG << "Found (GUESS): " << media << std::endl; + detected.push_back( media ); + } + if ( cdrinfo.isBlk() + && ! ( cdrinfo.devMajor() == dvdinfo.devMajor() && cdrinfo.devMinor() == dvdinfo.devMinor() ) ) + { + MediaSource media( "cdrom", cdrinfo.path().asString(), cdrinfo.devMajor(), cdrinfo.devMinor() ); + DBG << "Found (GUESS): " << media << std::endl; + detected.push_back( media ); + } + } + + // NOTE: On the fly build on-demand device list. Code was moved to + // here to get rid of code duplication, while keeping the ABI. Acuallty + // this code should be moved to a _devices accessor method. + if ( _devices.empty() ) + { + DBG << "creating on-demand device list" << endl; + //default is /dev/cdrom; for dvd: /dev/dvd if it exists + std::string device( "/dev/cdrom" ); + if ( _url.getScheme() == "dvd" && PathInfo( "/dev/dvd" ).isBlk() ) + { + device = "/dev/dvd"; + } + + PathInfo dinfo( device ); + if ( dinfo.isBlk() ) + { + MediaSource media( "cdrom", device, dinfo.devMajor(), dinfo.devMinor() ); + if ( detected.empty() ) + { + _devices.push_front( media ); // better try this than nothing + } + else + { + for( const auto & d : detected ) + { + // /dev/cdrom or /dev/dvd to the front + if ( media.equals( d ) ) + _devices.push_front( d ); + else + _devices.push_back( d ); + } + } + } + else + { + // no /dev/cdrom or /dev/dvd link + _devices = detected; + } + } + + return detected; + } + + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaCD::attachTo( bool next ) + { + DBG << "next " << next << " last " << _lastdev << " last tried " << _lastdev_tried << endl; + if ( next && _lastdev == -1 ) + ZYPP_THROW(MediaNotSupportedException(url())); + + // This also fills the _devices list on demand + DeviceList detected( detectDevices( _url.getScheme() == "dvd" ? true : false ) ); + + Mount mount; + MediaMountException merr; + + std::string options = _url.getQueryParam( "mountoptions" ); + if ( options.empty() ) + { + options="ro"; + } + + //TODO: make configurable + std::list filesystems; + + filesystems.push_back("iso9660"); + + // if DVD, try UDF filesystem after iso9660 + if ( _url.getScheme() == "dvd" ) + filesystems.push_back("udf"); + + // try all devices in sequence + int count = 0; + std::string mountpoint( attachPoint().asString() ); + bool mountsucceeded = false; + for ( DeviceList::iterator it = _devices.begin() ; ! mountsucceeded && it != _devices.end() ; ++it, ++count ) + { + DBG << "count " << count << endl; + if (next && count <=_lastdev_tried ) + { + DBG << "skipping device " << it->name << endl; + continue; + } + _lastdev_tried = count; + + // bnc#755815: _devices contains either devices passed as url option + // or autodetected ones. Accept both as long as they are block + // devices. + MediaSource temp( *it ); + PathInfo dinfo( temp.name ); + if ( ! dinfo.isBlk() ) + { + WAR << "skipping non block device: " << dinfo << endl; + continue; + } + DBG << "trying device " << dinfo << endl; + + temp.maj_nr = dinfo.devMajor(); + temp.min_nr = dinfo.devMinor(); + MediaSourceRef media( new MediaSource(temp)); + AttachedMedia ret( findAttachedMedia( media)); + + if( ret.mediaSource && ret.attachPoint && + !ret.attachPoint->empty()) + { + DBG << "Using a shared media " + << ret.mediaSource->name + << " attached on " + << ret.attachPoint->path + << endl; + removeAttachPoint(); + setAttachPoint(ret.attachPoint); + setMediaSource(ret.mediaSource); + _lastdev = count; + mountsucceeded = true; + break; + } + + { + MediaManager manager; + MountEntries entries( manager.getMountEntries()); + MountEntries::const_iterator e; + for( e = entries.begin(); e != entries.end(); ++e) + { + bool is_device = false; + std::string dev_path(Pathname(e->src).asString()); + PathInfo dev_info; + + if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 && + dev_info(e->src) && dev_info.isBlk()) + { + is_device = true; + } + + if( is_device && media->maj_nr == dev_info.devMajor() && + media->min_nr == dev_info.devMinor()) + { + AttachPointRef ap( new AttachPoint(e->dir, false)); + AttachedMedia am( media, ap); + { + DBG << "Using a system mounted media " + << media->name + << " attached on " + << ap->path + << endl; + + media->iown = false; // mark attachment as foreign + + setMediaSource(media); + setAttachPoint(ap); + _lastdev = count; + mountsucceeded = true; + break; + } + } + } + if( mountsucceeded) + break; + } + + // close tray + closeTray( it->name ); + + // try all filesystems in sequence + for(std::list::iterator fsit = filesystems.begin() + ; !mountsucceeded && fsit != filesystems.end() + ; ++fsit) + { + try + { + if( !isUseableAttachPoint( attachPoint() ) ) + { + setAttachPoint( createAttachPoint(), true ); + mountpoint = attachPoint().asString(); + } + + mount.mount(it->name, mountpoint, *fsit, options); + + setMediaSource(media); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 2; + while( !(mountsucceeded=isAttached()) && --limit) + { + WAR << "Wait for /proc/mounts update and retry...." << endl; + sleep(1); + } + + if( mountsucceeded) + { + _lastdev = count; + } + else + { + setMediaSource(MediaSourceRef()); + try + { + mount.umount(attachPoint().asString()); + } + catch (const MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW(MediaMountException( + "Unable to verify that the media was mounted", + it->name, mountpoint + )); + } + } + catch (const MediaMountException &e) + { + merr = e; + removeAttachPoint(); + ZYPP_CAUGHT(e); + } + catch (const MediaException & excpt_r) + { + removeAttachPoint(); + ZYPP_CAUGHT(excpt_r); + } + } // for filesystems + } // for _devices + + if (!mountsucceeded) + { + _lastdev = -1; + + if( !merr.mountOutput().empty()) + { + ZYPP_THROW(MediaMountException(merr.mountError(), + _url.asString(), + mountpoint, + merr.mountOutput())); + } + else + { + ZYPP_THROW(MediaMountException("Mounting media failed", + _url.asString(), mountpoint)); + } + } + DBG << _lastdev << " " << count << endl; + } + + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCD::releaseFrom( const std::string & ejectDev ) + { + Mount mount; + try + { + AttachedMedia am( attachedMedia()); + if(am.mediaSource && am.mediaSource->iown) + mount.umount(am.attachPoint->path.asString()); + } + catch (const Exception & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + if (!ejectDev.empty()) + { + forceRelaseAllMedia(false); + if(openTray( ejectDev )) + return; + } + ZYPP_RETHROW(excpt_r); + } + + // eject device + if (!ejectDev.empty()) + { + forceRelaseAllMedia(false); + if( !openTray( ejectDev )) + { +#if REPORT_EJECT_ERRORS + ZYPP_THROW(MediaNotEjectedException(ejectDev)); +#endif + } + } + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::forceEject + // METHOD TYPE : void + // + // Asserted that media is not attached. + // + void MediaCD::forceEject( const std::string & ejectDev_r ) + { +#if REPORT_EJECT_ERRORS + bool ejected = false; +#endif + if ( ! isAttached() ) // no device mounted in this instance + { + // This also fills the _devices list on demand + DeviceList detected( detectDevices( _url.getScheme() == "dvd" ? true : false ) ); + for_( it, _devices.begin(), _devices.end() ) + { + MediaSourceRef media( new MediaSource( *it ) ); + if ( media->name != ejectDev_r ) + continue; + + // bnc#755815: _devices contains either devices passed as url option + // or autodetected ones. Accept both as long as they are block + // devices. + PathInfo dinfo( media->name ); + if( ! dinfo.isBlk() ) + { + WAR << "skipping non block device: " << dinfo << endl; + continue; + } + DBG << "trying device " << dinfo << endl; + + // FIXME: we have also to check if it is mounted in the system + AttachedMedia ret( findAttachedMedia( media)); + if( !ret.mediaSource ) + { + forceRelaseAllMedia( media, false ); + if ( openTray( it->name ) ) + { +#if REPORT_EJECT_ERRORS + ejected = true; +#endif + break; // on 1st success + } + } + } + } +#if REPORT_EJECT_ERRORS + if( !ejected) + { + ZYPP_THROW(MediaNotEjectedException()); + } +#endif + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCD::isAttached + // METHOD TYPE : bool + // + // DESCRIPTION : Override check if media is attached. + // + bool + MediaCD::isAttached() const + { + return checkAttached(false); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCD::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCD::getFile( const OnMediaLocation &file ) const + { + MediaHandler::getFile( file ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCD::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCD::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaCD::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCD::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaCD::getDirInfo( filesystem::DirContent & retlist, const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + + bool MediaCD::getDoesFileExist( const Pathname & filename ) const + { + return MediaHandler::getDoesFileExist( filename ); + } + + + bool MediaCD::hasMoreDevices() + { + if (_devices.size() == 0) + return false; + else if (_lastdev_tried < 0) + return true; + + return (unsigned) _lastdev_tried < _devices.size() - 1; + } + + + void MediaCD::getDetectedDevices( std::vector & devices, unsigned int & index ) const + { + if ( ! devices.empty() ) + devices.clear(); + + if ( _devices.empty() ) + // This also fills the _devices list on demand + detectDevices( _url.getScheme() == "dvd" ? true : false ); + + for ( const auto & it : _devices ) + devices.push_back( it.name ); + + index = ( _lastdev >= 0 ? (unsigned)_lastdev : 0 ); + + MIL << "got " << devices.size() << " detected devices, current: " + << (index < devices.size() ? devices[index] : "") + << "(" << index << ")" << endl; + } + + } // namespace media + ////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////// diff --git a/zypp/media/MediaCD.h b/zypp/media/MediaCD.h new file mode 100644 index 0000000..3d0b17a --- /dev/null +++ b/zypp/media/MediaCD.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCD.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIACD_H +#define ZYPP_MEDIA_MEDIACD_H + +#include +#include + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaCD + /** + * @short Implementation class for CD/DVD MediaHandler + * @see MediaHandler + **/ + class MediaCD : public MediaHandler { + + private: + using DeviceList = std::list; + /** list of devices to try to mount */ + mutable DeviceList _devices; + + /** number of last successful mounted device in list */ + int _lastdev; + int _lastdev_tried; + + static bool openTray( const std::string & device_r ); + static bool closeTray( const std::string & device_r ); + + DeviceList detectDevices(bool supportingDVD) const; + + protected: + + void attachTo (bool next = false) override; + void releaseFrom( const std::string & ejectDev ) override; + void getFile(const OnMediaLocation & file) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + bool getDoesFileExist( const Pathname & filename ) const override; + + void forceEject(const std::string & ejectDev) override; + + bool hasMoreDevices() override; + + void + getDetectedDevices(std::vector & devices, + unsigned int & index) const override; + + public: + + MediaCD( const Url & url_r, + const Pathname & attach_point_hint_r ); + + ~MediaCD() override { try { release(); } catch(...) {} } + + bool isAttached() const override; + }; + +/////////////////////////////////////////////////////////////////// + } // namespace media +} // namespace zypp +#endif // ZYPP_MEDIA_MEDIACD_H diff --git a/zypp/media/MediaCIFS.cc b/zypp/media/MediaCIFS.cc new file mode 100644 index 0000000..43b4ef4 --- /dev/null +++ b/zypp/media/MediaCIFS.cc @@ -0,0 +1,471 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCIFS.cc + * +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using std::endl; + +namespace zypp { + namespace media { + + /****************************************************************** + ** + ** + ** FUNCTION NAME : getShare + ** FUNCTION TYPE : inline Pathname + ** + ** Get the 1st path component (CIFS share name). + */ + inline std::string getShare( const Pathname& spath_r ) + { + if ( spath_r.empty() ) + return std::string(); + + std::string share( spath_r.absolutename().asString() ); + std::string::size_type sep = share.find( '/', 1 ); + if ( sep == std::string::npos ) + share = share.erase( 0, 1 ); // nothing but the share name in spath_r + else + share = share.substr( 1, sep-1 ); + + // deescape %2f in sharename + while ( (sep = share.find( "%2f" )) != std::string::npos ) { + share.replace( sep, 3, "/" ); + } + + return share; + } + + /****************************************************************** + ** + ** + ** FUNCTION NAME : stripShare + ** FUNCTION TYPE : inline Pathname + ** + ** Strip off the 1st path component (CIFS share name). + */ + inline Pathname stripShare( const Pathname& spath_r ) + { + if ( spath_r.empty() ) + return Pathname(); + + std::string striped( spath_r.absolutename().asString() ); + std::string::size_type sep = striped.find( '/', 1 ); + if ( sep == std::string::npos ) + return "/"; // nothing but the share name in spath_r + + return striped.substr( sep ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaCIFS + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCIFS::MediaCIFS + // METHOD TYPE : Constructor + // + // DESCRIPTION : + // + MediaCIFS::MediaCIFS( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, + stripShare( url_r.getPathName() ), // urlpath WITHOUT share name at attachpoint + false ) // does_download + { + MIL << "MediaCIFS::MediaCIFS(" << url_r << ", " << attach_point_hint_r << ")" << endl; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCIFS::attachTo + // METHOD TYPE : PMError + /** + * Asserted that not already attached, and attachPoint is a directory. + * + * Authentication: credentials can be specified in the following few ways + * (the first has the highest preference). + * - URL username:password + * - mountoptions URL query parameter (see man mount.cifs) + * - CredentialManager - either previously saved credentials will be used + * or the user will be promted for them via AuthenticationReport callback. + * + * \note The implementation currently serves both, "smb" and + * and "cifs" URLs, but passes "cifs" to the mount command + * in any case. + */ + void MediaCIFS::attachTo(bool next) + { + if(_url.getHost().empty()) + ZYPP_THROW(MediaBadUrlEmptyHostException(_url)); + if(next) + ZYPP_THROW(MediaNotSupportedException(_url)); + + std::string path = "//"; + path += _url.getHost() + "/" + getShare( _url.getPathName() ); + + MediaSourceRef media( new MediaSource( "cifs", path)); + AttachedMedia ret( findAttachedMedia( media)); + + if( ret.mediaSource && + ret.attachPoint && + !ret.attachPoint->empty()) + { + DBG << "Using a shared media " + << ret.mediaSource->name + << " attached on " + << ret.attachPoint->path + << endl; + + removeAttachPoint(); + setAttachPoint(ret.attachPoint); + setMediaSource(ret.mediaSource); + return; + } + + if( !isUseableAttachPoint( attachPoint() ) ) + { + setAttachPoint( createAttachPoint(), true ); + } + std::string mountpoint( attachPoint().asString() ); + + Mount mount; + CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot())); + + Mount::Options options( _url.getQueryParam("mountoptions") ); + std::string username = _url.getUsername(); + std::string password = _url.getPassword(); + + if ( ! options.has( "rw" ) ) { + options["ro"]; + } + + // look for a workgroup + std::string workgroup = _url.getQueryParam("workgroup"); + if ( workgroup.empty() ) + workgroup = _url.getQueryParam("domain"); + if ( !workgroup.empty() ) + options["domain"] = workgroup; + + // extract 'username', do not overwrite any _url.username + + Mount::Options::iterator toEnv; + toEnv = options.find("username"); + if ( toEnv != options.end() ) { + if ( username.empty() ) + username = toEnv->second; + options.erase( toEnv ); + } + + toEnv = options.find("user"); // actually cifs specific + if ( toEnv != options.end() ) { + if ( username.empty() ) + username = toEnv->second; + options.erase( toEnv ); + } + + // extract 'password', do not overwrite any _url.password + + toEnv = options.find("password"); + if ( toEnv != options.end() ) { + if ( password.empty() ) + password = toEnv->second; + options.erase( toEnv ); + } + + toEnv = options.find("pass"); // actually cifs specific + if ( toEnv != options.end() ) { + if ( password.empty() ) + password = toEnv->second; + options.erase( toEnv ); + } + + if ( username.empty() || password.empty() ) + { + AuthData_Ptr c = cm.getCred(_url); + if (c) + { + username = c->username(); + password = c->password(); + } + } + + bool firstTry = true; + bool authRequired = false; + AuthData authdata; + do // repeat this while the mount returns "Permission denied" error + { + // get credentials from authenicate() + if ( !firstTry ) + { + username = authdata.username(); + password = authdata.password(); + } + + // pass 'username' and 'password' via environment + Mount::Environment environment; + if ( !username.empty() ) + environment["USER"] = username; + if ( !password.empty() ) + environment["PASSWD"] = password; + + ////////////////////////////////////////////////////// + // In case we need a tmpfile, credentials will remove + // it in its destructor after the mout call below. + filesystem::TmpPath credentials; + if ( !username.empty() || !password.empty() ) + { + filesystem::TmpFile tmp; + std::ofstream outs( tmp.path().asString().c_str() ); + outs << "username=" << username << endl; + outs << "password=" << password << endl; + outs.close(); + + credentials = tmp; + options["credentials"] = credentials.path().asString(); + } + else + { + // Use 'guest' option unless explicitly disabled (bnc #547354) + if ( options.has( "noguest" ) ) + options.erase( "noguest" ); + else + // prevent smbmount from asking for password + // only add this option if 'credentials' is not used (bnc #560496) + options["guest"]; + } + + // + ////////////////////////////////////////////////////// + + try + { + mount.mount( path, mountpoint, "cifs", + options.asString(), environment ); + setMediaSource(media); + break; + } + catch (const MediaMountException & e) + { + ZYPP_CAUGHT( e ); + + if ( e.mountError() == "Permission denied" ) + authRequired = authenticate( authdata, firstTry ); + else + ZYPP_RETHROW( e ); + } + + firstTry = false; + } + while ( authRequired ); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + while( !(mountsucceeded=isAttached()) && --limit) + sleep(1); + + if ( !mountsucceeded ) + { + setMediaSource(MediaSourceRef()); + try + { + mount.umount(attachPoint().asString()); + } + catch (const MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW(MediaMountException( + "Unable to verify that the media was mounted", + path, mountpoint + )); + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCIFS::isAttached + // METHOD TYPE : bool + // + // DESCRIPTION : Override check if media is attached. + // + bool + MediaCIFS::isAttached() const + { + return checkAttached(true); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCIFS::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCIFS::releaseFrom( const std::string & ejectDev ) + { + Mount mount; + mount.umount(attachPoint().asString()); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCIFS::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCIFS::getFile ( const OnMediaLocation &file ) const + { + MediaHandler::getFile( file ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaCIFS::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaCIFS::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCIFS::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaCIFS::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaCIFS::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaCIFS::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + bool MediaCIFS::getDoesFileExist( const Pathname & filename ) const + { + return MediaHandler::getDoesFileExist( filename ); + } + + bool MediaCIFS::authenticate(AuthData & authdata, bool firstTry) const + { + //! \todo need a way to pass different CredManagerOptions here + CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot())); + + // get stored credentials + AuthData_Ptr cmcred = cm.getCred(_url); + + AuthData_Ptr smbcred; + smbcred.reset(new AuthData()); + callback::SendReport auth_report; + + // preset the username if present in current url + if (!_url.getUsername().empty() && firstTry) + smbcred->setUsername(_url.getUsername()); + // if CM has found some credentials, preset the username from there + else if (cmcred) + smbcred->setUsername(cmcred->username()); + + // indicate we have no good credentials from CM + cmcred.reset(); + + std::string prompt_msg = str::form( + //!\todo add comma to the message for the next release + _("Authentication required for '%s'"), _url.asString().c_str()); + + // ask user + if (auth_report->prompt(_url, prompt_msg, *smbcred)) + { + DBG << "callback answer: retry" << endl + << "AuthData: " << *smbcred << endl; + + if (smbcred->valid()) + { + cmcred = smbcred; + // if (credentials->username() != _url.getUsername()) + // _url.setUsername(credentials->username()); + /** + * \todo find a way to save the url with changed username + * back to repoinfo or dont store urls with username + * (and either forbid more repos with the same url and different + * user, or return a set of credentials from CM and try them one + * by one) + */ + } + } + else + DBG << "callback answer: cancel" << endl; + + // set username and password + if (cmcred) + { + authdata.setUsername(cmcred->username()); + authdata.setPassword(cmcred->password()); + + // save the credentials + cmcred->setUrl(_url); + cm.addCred(*cmcred); + cm.save(); + + return true; + } + + return false; + } + + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaCIFS.h b/zypp/media/MediaCIFS.h new file mode 100644 index 0000000..22ffcc4 --- /dev/null +++ b/zypp/media/MediaCIFS.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCIFS.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIACIFS_H +#define ZYPP_MEDIA_MEDIACIFS_H + +#include + +namespace zypp { + namespace media { + + class AuthData; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaCIFS + /** + * @short Implementation class for CIFS MediaHandler + * + * NOTE: The implementation serves both, "smb" and "cifs" URLs, + * but passes "cifs" to the mount command in any case. + * @see MediaHandler + **/ + class MediaCIFS : public MediaHandler { + + protected: + + void attachTo (bool next = false) override; + void releaseFrom( const std::string & ejectDev ) override; + void getFile( const OnMediaLocation & file ) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + bool getDoesFileExist( const Pathname & filename ) const override; + + public: + MediaCIFS( const Url& url_r, + const Pathname & attach_point_hint_r ); + + ~MediaCIFS() override { try { release(); } catch(...) {} } + + bool isAttached() const override; + + private: + bool authenticate( AuthData & authdata, bool firstTry ) const; + }; + +///////////////////////////////////////////////////////////////////A + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIACIFS_H diff --git a/zypp/media/MediaCurl.cc b/zypp/media/MediaCurl.cc new file mode 100644 index 0000000..c1db252 --- /dev/null +++ b/zypp/media/MediaCurl.cc @@ -0,0 +1,1588 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCurl.cc + * +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for zypp_poll + +#include +#include +#include +#include +#include +#include +#include + +using std::endl; + +namespace internal { + using namespace zypp; + /// \brief Bottleneck filtering all DownloadProgressReport issued from Media[Muli]Curl. + /// - Optional files will send no report until data are actually received (we know it exists). + /// - Control the progress report frequency passed along to the application. + struct OptionalDownloadProgressReport : public callback::ReceiveReport + { + using TimePoint = std::chrono::steady_clock::time_point; + + OptionalDownloadProgressReport( bool isOptional=false ) + : _oldRec { Distributor::instance().getReceiver() } + , _isOptional { isOptional } + { connect(); } + + OptionalDownloadProgressReport(const OptionalDownloadProgressReport &) = delete; + OptionalDownloadProgressReport(OptionalDownloadProgressReport &&) = delete; + OptionalDownloadProgressReport &operator= (const OptionalDownloadProgressReport &) = delete; + OptionalDownloadProgressReport &operator= (OptionalDownloadProgressReport &&) = delete; + + ~OptionalDownloadProgressReport() override { + if (_oldRec) + Distributor::instance().setReceiver(*_oldRec); + else + Distributor::instance().noReceiver(); + } + + void reportbegin() override + { if ( _oldRec ) _oldRec->reportbegin(); } + + void reportend() override + { if ( _oldRec ) _oldRec->reportend(); } + + void report( const UserData & userData_r = UserData() ) override + { if ( _oldRec ) _oldRec->report( userData_r ); } + + + void start( const Url & file_r, Pathname localfile_r ) override + { + if ( not _oldRec ) return; + if ( _isOptional ) { + // delay start until first data are received. + _startFile = file_r; + _startLocalfile = std::move(localfile_r); + return; + } + _oldRec->start( file_r, localfile_r ); + } + + bool progress( int value_r, const Url & file_r, double dbps_avg_r = -1, double dbps_current_r = -1 ) override + { + if ( not _oldRec ) return true; + if ( notStarted() ) { + if ( not ( value_r || dbps_avg_r || dbps_current_r ) ) + return true; + sendStart(); + } + + //static constexpr std::chrono::milliseconds minfequency { 1000 }; only needed if we'd avoid sending reports without change + static constexpr std::chrono::milliseconds maxfequency { 100 }; + TimePoint now { TimePoint::clock::now() }; + TimePoint::duration elapsed { now - _lastProgressSent }; + if ( elapsed < maxfequency ) + return true; // continue + _lastProgressSent = now; + return _oldRec->progress( value_r, file_r, dbps_avg_r, dbps_current_r ); + } + + Action problem( const Url & file_r, Error error_r, const std::string & description_r ) override + { + if ( not _oldRec || notStarted() ) return ABORT; + return _oldRec->problem( file_r, error_r, description_r ); + } + + void finish( const Url & file_r, Error error_r, const std::string & reason_r ) override + { + if ( not _oldRec || notStarted() ) return; + _oldRec->finish( file_r, error_r, reason_r ); + } + + private: + // _isOptional also indicates the delayed start + bool notStarted() const + { return _isOptional; } + + void sendStart() + { + if ( _isOptional ) { + // we know _oldRec is valid... + _oldRec->start( _startFile, std::move(_startLocalfile) ); + _isOptional = false; + } + } + + private: + Receiver *const _oldRec; + bool _isOptional; + Url _startFile; + Pathname _startLocalfile; + TimePoint _lastProgressSent; + }; + + struct ProgressData + { + ProgressData( CURL *curl, time_t timeout = 0, zypp::Url url = zypp::Url(), + zypp::ByteCount expectedFileSize_r = 0, + zypp::callback::SendReport *_report = nullptr ); + + void updateStats( curl_off_t dltotal = 0.0, curl_off_t dlnow = 0.0 ); + + int reportProgress() const; + + CURL * curl() + { return _curl; } + + bool timeoutReached() const + { return _timeoutReached; } + + bool fileSizeExceeded() const + { return _fileSizeExceeded; } + + ByteCount expectedFileSize() const + { return _expectedFileSize; } + + void expectedFileSize( ByteCount newval_r ) + { _expectedFileSize = newval_r; } + + private: + CURL * _curl; + zypp::Url _url; + time_t _timeout; + bool _timeoutReached; + bool _fileSizeExceeded; + ByteCount _expectedFileSize; + zypp::callback::SendReport *report; + + time_t _timeStart = 0; ///< Start total stats + time_t _timeLast = 0; ///< Start last period(~1sec) + time_t _timeRcv = 0; ///< Start of no-data timeout + time_t _timeNow = 0; ///< Now + + curl_off_t _dnlTotal = 0.0; ///< Bytes to download or 0 if unknown + curl_off_t _dnlLast = 0.0; ///< Bytes downloaded at period start + curl_off_t _dnlNow = 0.0; ///< Bytes downloaded now + + int _dnlPercent= 0; ///< Percent completed or 0 if _dnlTotal is unknown + + double _drateTotal= 0.0; ///< Download rate so far + double _drateLast = 0.0; ///< Download rate in last period + }; + + + + ProgressData::ProgressData(CURL *curl, time_t timeout, Url url, ByteCount expectedFileSize_r, zypp::callback::SendReport< zypp::media::DownloadProgressReport> *_report) + : _curl( curl ) + , _url(std::move( url )) + , _timeout( timeout ) + , _timeoutReached( false ) + , _fileSizeExceeded ( false ) + , _expectedFileSize( expectedFileSize_r ) + , report( _report ) + {} + + void ProgressData::updateStats( curl_off_t dltotal, curl_off_t dlnow ) + { + time_t now = _timeNow = time(0); + + // If called without args (0.0), recompute based on the last values seen + if ( dltotal && dltotal != _dnlTotal ) + _dnlTotal = dltotal; + + if ( dlnow && dlnow != _dnlNow ) + { + _timeRcv = now; + _dnlNow = dlnow; + } + + // init or reset if time jumps back + if ( !_timeStart || _timeStart > now ) + _timeStart = _timeLast = _timeRcv = now; + + // timeout condition + if ( _timeout ) + _timeoutReached = ( (now - _timeRcv) > _timeout ); + + // check if the downloaded data is already bigger than what we expected + _fileSizeExceeded = _expectedFileSize > 0 && _expectedFileSize < static_cast(_dnlNow); + + // percentage: + if ( _dnlTotal ) + _dnlPercent = int( _dnlNow * 100 / _dnlTotal ); + + // download rates: + _drateTotal = double(_dnlNow) / std::max( int(now - _timeStart), 1 ); + + if ( _timeLast < now ) + { + _drateLast = double(_dnlNow - _dnlLast) / int(now - _timeLast); + // start new period + _timeLast = now; + _dnlLast = _dnlNow; + } + else if ( _timeStart == _timeLast ) + _drateLast = _drateTotal; + } + + int ProgressData::reportProgress() const + { + if ( _fileSizeExceeded ) + return 1; + if ( _timeoutReached ) + return 1; // no-data timeout + if ( report && !(*report)->progress( _dnlPercent, _url, _drateTotal, _drateLast ) ) + return 1; // user requested abort + return 0; + } + + const char * anonymousIdHeader() + { + // we need to add the release and identifier to the + // agent string. + // The target could be not initialized, and then this information + // is guessed. + // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space + static const std::string _value( str::trim( str::form( + "X-ZYpp-AnonymousId: %s", + Target::anonymousUniqueId( Pathname()/*guess root*/ ).c_str() + ))); + return _value.c_str(); + } + + const char * distributionFlavorHeader() + { + // we need to add the release and identifier to the + // agent string. + // The target could be not initialized, and then this information + // is guessed. + // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space + static const std::string _value( str::trim( str::form( + "X-ZYpp-DistributionFlavor: %s", + Target::distributionFlavor( Pathname()/*guess root*/ ).c_str() + ))); + return _value.c_str(); + } + + const char * agentString() + { + // we need to add the release and identifier to the + // agent string. + // The target could be not initialized, and then this information + // is guessed. + // bsc#1212187: HTTP/2 RFC 9113 forbids fields ending with a space + static const std::string _value( str::trim( str::form( + "ZYpp " LIBZYPP_VERSION_STRING " (curl %s) %s" + , curl_version_info(CURLVERSION_NOW)->version + , Target::targetDistribution( Pathname()/*guess root*/ ).c_str() + ))); + return _value.c_str(); + } + + /// Attempt to work around certain issues by autoretry in MediaCurl::getFileCopy + /// E.g. curl error: 92: HTTP/2 PROTOCOL_ERROR as in bsc#1205843, zypper/issues/457,... + /// ma: These errors were caused by a space terminated user agent string (bsc#1212187) + class MediaCurlExceptionMayRetryInternaly : public media::MediaCurlException + { + public: + MediaCurlExceptionMayRetryInternaly( const Url & url_r, + const std::string & err_r, + const std::string & msg_r ) + : media::MediaCurlException( url_r, err_r, msg_r ) + {} + //~MediaCurlExceptionMayRetryInternaly() noexcept {} + }; + +} + + +using namespace internal; +using namespace zypp::base; + +namespace zypp { + + namespace media { + +Pathname MediaCurl::_cookieFile = "/var/lib/YaST2/cookies"; + +// we use this define to unbloat code as this C setting option +// and catching exception is done frequently. +/** \todo deprecate SET_OPTION and use the typed versions below. */ +#define SET_OPTION(opt,val) do { \ + ret = curl_easy_setopt ( _curl, opt, val ); \ + if ( ret != 0) { \ + ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); \ + } \ + } while ( false ) + +#define SET_OPTION_OFFT(opt,val) SET_OPTION(opt,(curl_off_t)val) +#define SET_OPTION_LONG(opt,val) SET_OPTION(opt,(long)val) +#define SET_OPTION_VOID(opt,val) SET_OPTION(opt,(void*)val) + +MediaCurl::MediaCurl( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaNetworkCommonHandler( url_r, attach_point_hint_r, + "/", // urlpath at attachpoint + true ), // does_download + _curl( NULL ), + _customHeaders(0L) +{ + _curlError[0] = '\0'; + + MIL << "MediaCurl::MediaCurl(" << url_r << ", " << attach_point_hint_r << ")" << endl; + + globalInitCurlOnce(); + + if( !attachPoint().empty()) + { + PathInfo ainfo(attachPoint()); + Pathname apath(attachPoint() + "XXXXXX"); + char *atemp = ::strdup( apath.asString().c_str()); + char *atest = NULL; + if( !ainfo.isDir() || !ainfo.userMayRWX() || + atemp == NULL || (atest=::mkdtemp(atemp)) == NULL) + { + WAR << "attach point " << ainfo.path() + << " is not useable for " << url_r.getScheme() << endl; + setAttachPoint("", true); + } + else if( atest != NULL) + ::rmdir(atest); + + if( atemp != NULL) + ::free(atemp); + } +} + +Url MediaCurl::clearQueryString(const Url &url) const +{ + return internal::clearQueryString(url); +} + +void MediaCurl::setCookieFile( const Pathname &fileName ) +{ + _cookieFile = fileName; +} + +void MediaCurl::setCurlError(const char* error) +{ + // FIXME(dmllr): Use strlcpy if available for better performance + strncpy(_curlError, error, sizeof(_curlError)-1); + _curlError[sizeof(_curlError)-1] = '\0'; +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::checkProtocol(const Url &url) const +{ + curl_version_info_data *curl_info = NULL; + curl_info = curl_version_info(CURLVERSION_NOW); + // curl_info does not need any free (is static) + if (curl_info->protocols) + { + const char * const *proto = nullptr; + std::string scheme( url.getScheme()); + bool found = false; + for(proto=curl_info->protocols; !found && *proto; ++proto) + { + if( scheme == std::string((const char *)*proto)) + found = true; + } + if( !found) + { + std::string msg("Unsupported protocol '"); + msg += scheme; + msg += "'"; + ZYPP_THROW(MediaBadUrlException(_url, msg)); + } + } +} + +void MediaCurl::setupEasy() +{ + ::internal::setupZYPP_MEDIA_CURL_DEBUG( _curl ); + + curl_easy_setopt(_curl, CURLOPT_HEADERFUNCTION, log_redirects_curl); + curl_easy_setopt(_curl, CURLOPT_HEADERDATA, &_lastRedirect); + CURLcode ret = curl_easy_setopt( _curl, CURLOPT_ERRORBUFFER, _curlError ); + if ( ret != 0 ) { + ZYPP_THROW(MediaCurlSetOptException(_url, "Error setting error buffer")); + } + + SET_OPTION(CURLOPT_FAILONERROR, 1L); + SET_OPTION(CURLOPT_NOSIGNAL, 1L); + + // create non persistant settings + // so that we don't add headers twice + TransferSettings vol_settings(_settings); + + // add custom headers for download.opensuse.org (bsc#955801) + if ( _url.getHost() == "download.opensuse.org" ) + { + vol_settings.addHeader(anonymousIdHeader()); + vol_settings.addHeader(distributionFlavorHeader()); + } + vol_settings.addHeader("Pragma:"); + + _settings.setUserAgentString(agentString()); + + // fill some settings from url query parameters + try + { + fillSettingsFromUrl(_url, _settings); + } + catch ( const MediaException &e ) + { + disconnectFrom(); + ZYPP_RETHROW(e); + } + // if the proxy was not set (or explicitly unset) by url, then look... + if ( _settings.proxy().empty() ) + { + // ...at the system proxy settings + fillSettingsSystemProxy(_url, _settings); + } + + /** Force IPv4/v6 */ + switch ( env::ZYPP_MEDIA_CURL_IPRESOLVE() ) + { + case 4: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); break; + case 6: SET_OPTION(CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); break; + } + + /** + * Connect timeout + */ + SET_OPTION(CURLOPT_CONNECTTIMEOUT, _settings.connectTimeout()); + // If a transfer timeout is set, also set CURLOPT_TIMEOUT to an upper limit + // just in case curl does not trigger its progress callback frequently + // enough. + if ( _settings.timeout() ) + { + SET_OPTION(CURLOPT_TIMEOUT, 3600L); + } + + // follow any Location: header that the server sends as part of + // an HTTP header (#113275) + SET_OPTION(CURLOPT_FOLLOWLOCATION, 1L); + // 3 redirects seem to be too few in some cases (bnc #465532) + SET_OPTION(CURLOPT_MAXREDIRS, 6L); + + if ( _url.getScheme() == "https" ) + { + if ( :: internal::setCurlRedirProtocols ( _curl ) != CURLE_OK ) { + ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); + } + + if( _settings.verifyPeerEnabled() || + _settings.verifyHostEnabled() ) + { + SET_OPTION(CURLOPT_CAPATH, _settings.certificateAuthoritiesPath().c_str()); + } + + if( ! _settings.clientCertificatePath().empty() ) + { + SET_OPTION(CURLOPT_SSLCERT, _settings.clientCertificatePath().c_str()); + } + if( ! _settings.clientKeyPath().empty() ) + { + SET_OPTION(CURLOPT_SSLKEY, _settings.clientKeyPath().c_str()); + } + +#ifdef CURLSSLOPT_ALLOW_BEAST + // see bnc#779177 + ret = curl_easy_setopt( _curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_ALLOW_BEAST ); + if ( ret != 0 ) { + disconnectFrom(); + ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); + } +#endif + SET_OPTION(CURLOPT_SSL_VERIFYPEER, _settings.verifyPeerEnabled() ? 1L : 0L); + SET_OPTION(CURLOPT_SSL_VERIFYHOST, _settings.verifyHostEnabled() ? 2L : 0L); + // bnc#903405 - POODLE: libzypp should only talk TLS + SET_OPTION(CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1); + } + + SET_OPTION(CURLOPT_USERAGENT, _settings.userAgentString().c_str() ); + + /* Fixes bsc#1174011 "auth=basic ignored in some cases" + * We should proactively add the password to the request if basic auth is configured + * and a password is available in the credentials but not in the URL. + * + * We will be a bit paranoid here and require that the URL has a user embedded, otherwise we go the default route + * and ask the server first about the auth method + */ + if ( _settings.authType() == "basic" + && _settings.username().size() + && !_settings.password().size() ) { + + CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot())); + const auto cred = cm.getCred( _url ); + if ( cred && cred->valid() ) { + if ( !_settings.username().size() ) + _settings.setUsername(cred->username()); + _settings.setPassword(cred->password()); + } + } + + /*---------------------------------------------------------------* + CURLOPT_USERPWD: [user name]:[password] + + Url::username/password -> CURLOPT_USERPWD + If not provided, anonymous FTP identification + *---------------------------------------------------------------*/ + + if ( _settings.userPassword().size() ) + { + SET_OPTION(CURLOPT_USERPWD, _settings.userPassword().c_str()); + std::string use_auth = _settings.authType(); + if (use_auth.empty()) + use_auth = "digest,basic"; // our default + long auth = CurlAuthData::auth_type_str2long(use_auth); + if( auth != CURLAUTH_NONE) + { + DBG << "Enabling HTTP authentication methods: " << use_auth + << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl; + SET_OPTION(CURLOPT_HTTPAUTH, auth); + } + } + + if ( _settings.proxyEnabled() && ! _settings.proxy().empty() ) + { + DBG << "Proxy: '" << _settings.proxy() << "'" << endl; + SET_OPTION(CURLOPT_PROXY, _settings.proxy().c_str()); + SET_OPTION(CURLOPT_PROXYAUTH, CURLAUTH_BASIC|CURLAUTH_DIGEST|CURLAUTH_NTLM ); + /*---------------------------------------------------------------* + * CURLOPT_PROXYUSERPWD: [user name]:[password] + * + * Url::option(proxyuser and proxypassword) -> CURLOPT_PROXYUSERPWD + * If not provided, $HOME/.curlrc is evaluated + *---------------------------------------------------------------*/ + + std::string proxyuserpwd = _settings.proxyUserPassword(); + + if ( proxyuserpwd.empty() ) + { + CurlConfig curlconf; + CurlConfig::parseConfig(curlconf); // parse ~/.curlrc + if ( curlconf.proxyuserpwd.empty() ) + DBG << "Proxy: ~/.curlrc does not contain the proxy-user option" << endl; + else + { + proxyuserpwd = curlconf.proxyuserpwd; + DBG << "Proxy: using proxy-user from ~/.curlrc" << endl; + } + } + else + { + DBG << "Proxy: using provided proxy-user '" << _settings.proxyUsername() << "'" << endl; + } + + if ( ! proxyuserpwd.empty() ) + { + SET_OPTION(CURLOPT_PROXYUSERPWD, curlUnEscape( proxyuserpwd ).c_str()); + } + } +#if CURLVERSION_AT_LEAST(7,19,4) + else if ( _settings.proxy() == EXPLICITLY_NO_PROXY ) + { + // Explicitly disabled in URL (see fillSettingsFromUrl()). + // This should also prevent libcurl from looking into the environment. + DBG << "Proxy: explicitly NOPROXY" << endl; + SET_OPTION(CURLOPT_NOPROXY, "*"); + } +#endif + else + { + DBG << "Proxy: not explicitly set" << endl; + DBG << "Proxy: libcurl may look into the environment" << endl; + } + + /** Speed limits */ + if ( _settings.minDownloadSpeed() != 0 ) + { + SET_OPTION(CURLOPT_LOW_SPEED_LIMIT, _settings.minDownloadSpeed()); + // default to 10 seconds at low speed + SET_OPTION(CURLOPT_LOW_SPEED_TIME, 60L); + } + +#if CURLVERSION_AT_LEAST(7,15,5) + if ( _settings.maxDownloadSpeed() != 0 ) + SET_OPTION_OFFT(CURLOPT_MAX_RECV_SPEED_LARGE, _settings.maxDownloadSpeed()); +#endif + + /*---------------------------------------------------------------* + *---------------------------------------------------------------*/ + + _currentCookieFile = _cookieFile.asString(); + if ( ::geteuid() == 0 || PathInfo(_currentCookieFile).owner() == ::geteuid() ) + filesystem::assert_file_mode( _currentCookieFile, 0600 ); + + const auto &cookieFileParam = _url.getQueryParam( "cookies" ); + if ( !cookieFileParam.empty() && str::strToBool( cookieFileParam, true ) ) + SET_OPTION(CURLOPT_COOKIEFILE, _currentCookieFile.c_str() ); + else + MIL << "No cookies requested" << endl; + SET_OPTION(CURLOPT_COOKIEJAR, _currentCookieFile.c_str() ); + SET_OPTION(CURLOPT_XFERINFOFUNCTION, &progressCallback ); + SET_OPTION(CURLOPT_NOPROGRESS, 0L); + +#if CURLVERSION_AT_LEAST(7,18,0) + // bnc #306272 + SET_OPTION(CURLOPT_PROXY_TRANSFER_MODE, 1L ); +#endif + // Append settings custom headers to curl. + // TransferSettings assert strings are trimmed (HTTP/2 RFC 9113) + for ( const auto &header : vol_settings.headers() ) { + _customHeaders = curl_slist_append(_customHeaders, header.c_str()); + if ( !_customHeaders ) + ZYPP_THROW(MediaCurlInitException(_url)); + } + SET_OPTION(CURLOPT_HTTPHEADER, _customHeaders); +} + +/////////////////////////////////////////////////////////////////// + + +void MediaCurl::attachTo (bool next) +{ + if ( next ) + ZYPP_THROW(MediaNotSupportedException(_url)); + + if ( !_url.isValid() ) + ZYPP_THROW(MediaBadUrlException(_url)); + + checkProtocol(_url); + if( !isUseableAttachPoint( attachPoint() ) ) + { + setAttachPoint( createAttachPoint(), true ); + } + + disconnectFrom(); // clean _curl if needed + _curl = curl_easy_init(); + if ( !_curl ) { + ZYPP_THROW(MediaCurlInitException(_url)); + } + try + { + setupEasy(); + } + catch (Exception & ex) + { + disconnectFrom(); + ZYPP_RETHROW(ex); + } + + // FIXME: need a derived class to propelly compare url's + MediaSourceRef media( new MediaSource(_url.getScheme(), _url.asString())); + setMediaSource(media); +} + +bool +MediaCurl::checkAttachPoint(const Pathname &apoint) const +{ + return MediaHandler::checkAttachPoint( apoint, true, true); +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::disconnectFrom() +{ + if ( _customHeaders ) + { + curl_slist_free_all(_customHeaders); + _customHeaders = 0L; + } + + if ( _curl ) + { + // bsc#1201092: Strange but within global_dtors we may exceptions here. + try { curl_easy_cleanup( _curl ); } + catch (...) { ; } + _curl = NULL; + } +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::releaseFrom( const std::string & ejectDev ) +{ + disconnect(); +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::getFile( const OnMediaLocation &file ) const +{ + // Use absolute file name to prevent access of files outside of the + // hierarchy below the attach point. + getFileCopy( file, localPath(file.filename()).absolutename() ); +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::getFileCopy( const OnMediaLocation & srcFile , const Pathname & target ) const +{ + + const auto &filename = srcFile.filename(); + + // Optional files will send no report until data are actually received (we know it exists). + OptionalDownloadProgressReport reportfilter( srcFile.optional() ); + callback::SendReport report; + + Url fileurl(getFileUrl(filename)); + + bool firstAuth = true; // bsc#1210870: authenticate must not return stored credentials more than once. + unsigned internalTry = 0; + static constexpr unsigned maxInternalTry = 3; + + do + { + try + { + doGetFileCopy( srcFile, target, report ); + break; // success! + } + // retry with proper authentication data + catch (MediaUnauthorizedException & ex_r) + { + if ( authenticate(ex_r.hint(), firstAuth) ) { + firstAuth = false; // must not return stored credentials again + continue; // retry + } + + report->finish(fileurl, zypp::media::DownloadProgressReport::ACCESS_DENIED, ex_r.asUserHistory()); + ZYPP_RETHROW(ex_r); + } + // unexpected exception + catch (MediaException & excpt_r) + { + if ( typeid(excpt_r) == typeid( MediaCurlExceptionMayRetryInternaly ) ) { + ++internalTry; + if ( internalTry < maxInternalTry ) { + // just report (NO_ERROR); no interactive request to the user + report->problem(fileurl, media::DownloadProgressReport::NO_ERROR, excpt_r.asUserHistory()+_("Will try again...")); + continue; // retry + } + excpt_r.addHistory( str::Format(_("Giving up after %1% attempts.")) % maxInternalTry ); + } + + media::DownloadProgressReport::Error reason = media::DownloadProgressReport::ERROR; + if( typeid(excpt_r) == typeid( media::MediaFileNotFoundException ) || + typeid(excpt_r) == typeid( media::MediaNotAFileException ) ) + { + reason = media::DownloadProgressReport::NOT_FOUND; + } + report->finish(fileurl, reason, excpt_r.asUserHistory()); + ZYPP_RETHROW(excpt_r); + } + } + while ( true ); + report->finish(fileurl, zypp::media::DownloadProgressReport::NO_ERROR, ""); +} + +/////////////////////////////////////////////////////////////////// + +bool MediaCurl::getDoesFileExist( const Pathname & filename ) const +{ + bool retry = false; + + do + { + try + { + return doGetDoesFileExist( filename ); + } + // authentication problem, retry with proper authentication data + catch (MediaUnauthorizedException & ex_r) + { + if(authenticate(ex_r.hint(), !retry)) + retry = true; + else + ZYPP_RETHROW(ex_r); + } + // unexpected exception + catch (MediaException & excpt_r) + { + ZYPP_RETHROW(excpt_r); + } + } + while (retry); + + return false; +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::evaluateCurlCode(const Pathname &filename, + CURLcode code, + bool timeout_reached) const +{ + if ( code != 0 ) + { + Url url; + if (filename.empty()) + url = _url; + else + url = getFileUrl(filename); + + std::string err; + { + switch ( code ) + { + case CURLE_UNSUPPORTED_PROTOCOL: + err = " Unsupported protocol"; + if ( !_lastRedirect.empty() ) + { + err += " or redirect ("; + err += _lastRedirect; + err += ")"; + } + break; + case CURLE_URL_MALFORMAT: + case CURLE_URL_MALFORMAT_USER: + err = " Bad URL"; + break; + case CURLE_LOGIN_DENIED: + ZYPP_THROW( + MediaUnauthorizedException(url, "Login failed.", _curlError, "")); + break; + case CURLE_HTTP_RETURNED_ERROR: + { + long httpReturnCode = 0; + CURLcode infoRet = curl_easy_getinfo( _curl, + CURLINFO_RESPONSE_CODE, + &httpReturnCode ); + if ( infoRet == CURLE_OK ) + { + std::string msg = "HTTP response: " + str::numstring( httpReturnCode ); + switch ( httpReturnCode ) + { + case 401: + { + std::string auth_hint = getAuthHint(); + + DBG << msg << " Login failed (URL: " << url.asString() << ")" << std::endl; + DBG << "MediaUnauthorizedException auth hint: '" << auth_hint << "'" << std::endl; + + ZYPP_THROW(MediaUnauthorizedException( + url, "Login failed.", _curlError, auth_hint + )); + } + + case 502: // bad gateway (bnc #1070851) + case 503: // service temporarily unavailable (bnc #462545) + ZYPP_THROW(MediaTemporaryProblemException(url)); + case 504: // gateway timeout + ZYPP_THROW(MediaTimeoutException(url)); + case 403: + { + std::string msg403; + if ( url.getHost().find(".suse.com") != std::string::npos ) + msg403 = _("Visit the SUSE Customer Center to check whether your registration is valid and has not expired."); + else if (url.asString().find("novell.com") != std::string::npos) + msg403 = _("Visit the Novell Customer Center to check whether your registration is valid and has not expired."); + ZYPP_THROW(MediaForbiddenException(url, msg403)); + } + case 404: + case 410: + ZYPP_THROW(MediaFileNotFoundException(_url, filename)); + } + + DBG << msg << " (URL: " << url.asString() << ")" << std::endl; + ZYPP_THROW(MediaCurlException(url, msg, _curlError)); + } + else + { + std::string msg = "Unable to retrieve HTTP response:"; + DBG << msg << " (URL: " << url.asString() << ")" << std::endl; + ZYPP_THROW(MediaCurlException(url, msg, _curlError)); + } + } + break; + case CURLE_FTP_COULDNT_RETR_FILE: +#if CURLVERSION_AT_LEAST(7,16,0) + case CURLE_REMOTE_FILE_NOT_FOUND: +#endif + case CURLE_FTP_ACCESS_DENIED: + case CURLE_TFTP_NOTFOUND: + err = "File not found"; + ZYPP_THROW(MediaFileNotFoundException(_url, filename)); + break; + case CURLE_BAD_PASSWORD_ENTERED: + case CURLE_FTP_USER_PASSWORD_INCORRECT: + err = "Login failed"; + break; + case CURLE_COULDNT_RESOLVE_PROXY: + case CURLE_COULDNT_RESOLVE_HOST: + case CURLE_COULDNT_CONNECT: + case CURLE_FTP_CANT_GET_HOST: + err = "Connection failed"; + break; + case CURLE_WRITE_ERROR: + err = "Write error"; + break; + case CURLE_PARTIAL_FILE: + case CURLE_OPERATION_TIMEDOUT: + timeout_reached = true; // fall though to TimeoutException + // fall though... + case CURLE_ABORTED_BY_CALLBACK: + if( timeout_reached ) + { + err = "Timeout reached"; + ZYPP_THROW(MediaTimeoutException(url)); + } + else + { + err = "User abort"; + } + break; + + default: + err = "Curl error " + str::numstring( code ); + break; + } + + // uhm, no 0 code but unknown curl exception + ZYPP_THROW(MediaCurlException(url, err, _curlError)); + } + } + else + { + // actually the code is 0, nothing happened + } +} + +/////////////////////////////////////////////////////////////////// + +bool MediaCurl::doGetDoesFileExist( const Pathname & filename ) const +{ + DBG << filename.asString() << endl; + + if(!_url.isValid()) + ZYPP_THROW(MediaBadUrlException(_url)); + + if(_url.getHost().empty()) + ZYPP_THROW(MediaBadUrlEmptyHostException(_url)); + + Url url(getFileUrl(filename)); + + DBG << "URL: " << url.asString() << endl; + // Use URL without options and without username and passwd + // (some proxies dislike them in the URL). + // Curl seems to need the just scheme, hostname and a path; + // the rest was already passed as curl options (in attachTo). + Url curlUrl( clearQueryString(url) ); + + // + // See also Bug #154197 and ftp url definition in RFC 1738: + // The url "ftp://user@host/foo/bar/file" contains a path, + // that is relative to the user's home. + // The url "ftp://user@host//foo/bar/file" (or also with + // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file" + // contains an absolute path. + // + _lastRedirect.clear(); + std::string urlBuffer( curlUrl.asString()); + CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL, + urlBuffer.c_str() ); + if ( ret != 0 ) { + ZYPP_THROW(MediaCurlSetOptException(url, _curlError)); + } + + // If no head requests allowed (?head_requests=no): + // Instead of returning no data with NOBODY, we return + // little data, that works with broken servers, and + // works for ftp as well, because retrieving only headers + // ftp will return always OK code ? + // See http://curl.haxx.se/docs/knownbugs.html #58 + /// RAII Handler for temp. setting a head/range request + struct TempSetHeadRequest + { + TempSetHeadRequest(CURL *curl_r, bool doHttpHeadRequest_r) + : _curl{curl_r}, _doHttpHeadRequest{doHttpHeadRequest_r} { + if ( _doHttpHeadRequest ) { + curl_easy_setopt( _curl, CURLOPT_NOBODY, 1L ); + } else { + curl_easy_setopt( _curl, CURLOPT_RANGE, "0-1" ); + } + } + TempSetHeadRequest(const TempSetHeadRequest &) = delete; + TempSetHeadRequest(TempSetHeadRequest &&) = delete; + TempSetHeadRequest &operator=(const TempSetHeadRequest &) = delete; + TempSetHeadRequest &operator=(TempSetHeadRequest &&) = delete; + ~TempSetHeadRequest() { + if ( _doHttpHeadRequest ) { + curl_easy_setopt( _curl, CURLOPT_NOBODY, 0L); + /* yes, this is why we never got to get NOBODY working before, + because setting it changes this option too, and we also* + need to reset it + See: http://curl.haxx.se/mail/archive-2005-07/0073.html + */ + curl_easy_setopt( _curl, CURLOPT_HTTPGET, 1L ); + } else { + curl_easy_setopt( _curl, CURLOPT_RANGE, NULL ); + } + } + private: + CURL * _curl; + bool _doHttpHeadRequest; + } _guard( _curl, (_url.getScheme() == "http" || _url.getScheme() == "https") && _settings.headRequestsAllowed() ); + + + AutoFILE file { ::fopen( "/dev/null", "w" ) }; + if ( !file ) { + ERR << "fopen failed for /dev/null" << endl; + ZYPP_THROW(MediaWriteException("/dev/null")); + } + + ret = curl_easy_setopt( _curl, CURLOPT_WRITEDATA, (*file) ); + if ( ret != 0 ) { + ZYPP_THROW(MediaCurlSetOptException(url, _curlError)); + } + + CURLcode ok = executeCurl(); + MIL << "perform code: " << ok << " [ " << curl_easy_strerror(ok) << " ]" << endl; + + // as we are not having user interaction, the user can't cancel + // the file existence checking, a callback or timeout return code + // will be always a timeout. + try { + evaluateCurlCode( filename, ok, true /* timeout */); + } + catch ( const MediaFileNotFoundException &e ) { + // if the file did not exist then we can return false + return false; + } + catch ( const MediaException &e ) { + // some error, we are not sure about file existence, rethrw + ZYPP_RETHROW(e); + } + // exists + return ( ok == CURLE_OK ); +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::doGetFileCopy( const OnMediaLocation &srcFile , const Pathname & target, callback::SendReport & report, RequestOptions options ) const +{ + Pathname dest = target.absolutename(); + if( assert_dir( dest.dirname() ) ) + { + DBG << "assert_dir " << dest.dirname() << " failed" << endl; + ZYPP_THROW( MediaSystemException(getFileUrl(srcFile.filename()), "System error on " + dest.dirname().asString()) ); + } + + ManagedFile destNew { target.extend( ".new.zypp.XXXXXX" ) }; + AutoFILE file; + { + AutoFREE buf { ::strdup( (*destNew).c_str() ) }; + if( ! buf ) + { + ERR << "out of memory for temp file name" << endl; + ZYPP_THROW(MediaSystemException(getFileUrl(srcFile.filename()), "out of memory for temp file name")); + } + + AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) }; + if( tmp_fd == -1 ) + { + ERR << "mkstemp failed for file '" << destNew << "'" << endl; + ZYPP_THROW(MediaWriteException(destNew)); + } + destNew = ManagedFile( (*buf), filesystem::unlink ); + + file = ::fdopen( tmp_fd, "we" ); + if ( ! file ) + { + ERR << "fopen failed for file '" << destNew << "'" << endl; + ZYPP_THROW(MediaWriteException(destNew)); + } + tmp_fd.resetDispose(); // don't close it here! ::fdopen moved ownership to file + } + + DBG << "dest: " << dest << endl; + DBG << "temp: " << destNew << endl; + + // set IFMODSINCE time condition (no download if not modified) + if( PathInfo(target).isExist() && !(options & OPTION_NO_IFMODSINCE) ) + { + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (long)PathInfo(target).mtime()); + } + else + { + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L); + } + try + { + doGetFileCopyFile( srcFile, dest, file, report, options); + } + catch (Exception &e) + { + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L); + ZYPP_RETHROW(e); + } + + long httpReturnCode = 0; + CURLcode infoRet = curl_easy_getinfo(_curl, + CURLINFO_RESPONSE_CODE, + &httpReturnCode); + bool modified = true; + if (infoRet == CURLE_OK) + { + DBG << "HTTP response: " + str::numstring(httpReturnCode); + if ( httpReturnCode == 304 + || ( httpReturnCode == 213 && (_url.getScheme() == "ftp" || _url.getScheme() == "tftp") ) ) // not modified + { + DBG << " Not modified."; + modified = false; + } + DBG << endl; + } + else + { + WAR << "Could not get the response code." << endl; + } + + if (modified || infoRet != CURLE_OK) + { + // apply umask + if ( ::fchmod( ::fileno(file), filesystem::applyUmaskTo( 0644 ) ) ) + { + ERR << "Failed to chmod file " << destNew << endl; + } + + file.resetDispose(); // we're going to close it manually here + if ( ::fclose( file ) ) + { + ERR << "Fclose failed for file '" << destNew << "'" << endl; + ZYPP_THROW(MediaWriteException(destNew)); + } + + // move the temp file into dest + if ( rename( destNew, dest ) != 0 ) { + ERR << "Rename failed" << endl; + ZYPP_THROW(MediaWriteException(dest)); + } + destNew.resetDispose(); // no more need to unlink it + } + + DBG << "done: " << PathInfo(dest) << endl; +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::doGetFileCopyFile( const OnMediaLocation & srcFile, const Pathname & dest, FILE *file, callback::SendReport & report, RequestOptions options ) const +{ + DBG << srcFile.filename().asString() << endl; + + if(!_url.isValid()) + ZYPP_THROW(MediaBadUrlException(_url)); + + if(_url.getHost().empty()) + ZYPP_THROW(MediaBadUrlEmptyHostException(_url)); + + Url url(getFileUrl(srcFile.filename())); + + DBG << "URL: " << url.asString() << endl; + // Use URL without options and without username and passwd + // (some proxies dislike them in the URL). + // Curl seems to need the just scheme, hostname and a path; + // the rest was already passed as curl options (in attachTo). + Url curlUrl( clearQueryString(url) ); + + // + // See also Bug #154197 and ftp url definition in RFC 1738: + // The url "ftp://user@host/foo/bar/file" contains a path, + // that is relative to the user's home. + // The url "ftp://user@host//foo/bar/file" (or also with + // encoded slash as %2f) "ftp://user@host/%2ffoo/bar/file" + // contains an absolute path. + // + _lastRedirect.clear(); + std::string urlBuffer( curlUrl.asString()); + CURLcode ret = curl_easy_setopt( _curl, CURLOPT_URL, + urlBuffer.c_str() ); + if ( ret != 0 ) { + ZYPP_THROW(MediaCurlSetOptException(url, _curlError)); + } + + ret = curl_easy_setopt( _curl, CURLOPT_WRITEDATA, file ); + if ( ret != 0 ) { + ZYPP_THROW(MediaCurlSetOptException(url, _curlError)); + } + + // Set callback and perform. + internal::ProgressData progressData(_curl, _settings.timeout(), url, srcFile.downloadSize(), &report); + if (!(options & OPTION_NO_REPORT_START)) + report->start(url, dest); + if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, &progressData ) != 0 ) { + WAR << "Can't set CURLOPT_PROGRESSDATA: " << _curlError << endl;; + } + + ret = executeCurl(); +#if CURLVERSION_AT_LEAST(7,19,4) + // bnc#692260: If the client sends a request with an If-Modified-Since header + // with a future date for the server, the server may respond 200 sending a + // zero size file. + // curl-7.19.4 introduces CURLINFO_CONDITION_UNMET to check this condition. + if ( ftell(file) == 0 && ret == 0 ) + { + long httpReturnCode = 33; + if ( curl_easy_getinfo( _curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) == CURLE_OK && httpReturnCode == 200 ) + { + long conditionUnmet = 33; + if ( curl_easy_getinfo( _curl, CURLINFO_CONDITION_UNMET, &conditionUnmet ) == CURLE_OK && conditionUnmet ) + { + WAR << "TIMECONDITION unmet - retry without." << endl; + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L); + ret = executeCurl(); + } + } + } +#endif + + if ( curl_easy_setopt( _curl, CURLOPT_PROGRESSDATA, NULL ) != 0 ) { + WAR << "Can't unset CURLOPT_PROGRESSDATA: " << _curlError << endl;; + } + + if ( ret != 0 ) + { + ERR << "curl error: " << ret << ": " << _curlError + << ", temp file size " << ftell(file) + << " bytes." << endl; + + // the timeout is determined by the progress data object + // which holds whether the timeout was reached or not, + // otherwise it would be a user cancel + try { + + if ( progressData.fileSizeExceeded() ) + ZYPP_THROW(MediaFileSizeExceededException(url, progressData.expectedFileSize())); + + evaluateCurlCode( srcFile.filename(), ret, progressData.timeoutReached() ); + } + catch ( const MediaException &e ) { + // some error, we are not sure about file existence, rethrw + ZYPP_RETHROW(e); + } + } +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::getDir( const Pathname & dirname, bool recurse_r ) const +{ + filesystem::DirContent content; + getDirInfo( content, dirname, /*dots*/false ); + + for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) { + Pathname filename = dirname + it->name; + int res = 0; + + switch ( it->type ) { + case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all + case filesystem::FT_FILE: + getFile( OnMediaLocation( filename ) ); + break; + case filesystem::FT_DIR: // newer directory.yast contain at least directory info + if ( recurse_r ) { + getDir( filename, recurse_r ); + } else { + res = assert_dir( localPath( filename ) ); + if ( res ) { + WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl; + } + } + break; + default: + // don't provide devices, sockets, etc. + break; + } + } +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const +{ + getDirectoryYast( retlist, dirname, dots ); +} + +/////////////////////////////////////////////////////////////////// + +void MediaCurl::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const +{ + getDirectoryYast( retlist, dirname, dots ); +} + +/////////////////////////////////////////////////////////////////// +// +int MediaCurl::aliveCallback( void *clientp, curl_off_t /*dltotal*/, curl_off_t dlnow, curl_off_t /*ultotal*/, curl_off_t /*ulnow*/ ) +{ + internal::ProgressData *pdata = reinterpret_cast( clientp ); + if( pdata ) + { + // Do not propagate dltotal in alive callbacks. MultiCurl uses this to + // prevent a percentage raise while downloading a metalink file. Download + // activity however is indicated by propagating the download rate (via dlnow). + pdata->updateStats( 0.0, dlnow ); + return pdata->reportProgress(); + } + return 0; +} + +int MediaCurl::progressCallback( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow ) +{ + internal::ProgressData *pdata = reinterpret_cast( clientp ); + if( pdata ) + { + // work around curl bug that gives us old data + long httpReturnCode = 0; + if ( curl_easy_getinfo( pdata->curl(), CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0 ) + return aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow ); + + pdata->updateStats( dltotal, dlnow ); + return pdata->reportProgress(); + } + return 0; +} + +CURL *MediaCurl::progressCallback_getcurl( void *clientp ) +{ + internal::ProgressData *pdata = reinterpret_cast(clientp); + return pdata ? pdata->curl() : 0; +} + +/////////////////////////////////////////////////////////////////// + +std::string MediaCurl::getAuthHint() const +{ + long auth_info = CURLAUTH_NONE; + + CURLcode infoRet = + curl_easy_getinfo(_curl, CURLINFO_HTTPAUTH_AVAIL, &auth_info); + + if(infoRet == CURLE_OK) + { + return CurlAuthData::auth_type_long2str(auth_info); + } + + return ""; +} + +/** + * MediaMultiCurl needs to reset the expected filesize in case a metalink file is downloaded + * otherwise this function should not be called + */ +void MediaCurl::resetExpectedFileSize(void *clientp, const ByteCount &expectedFileSize) +{ + internal::ProgressData *data = reinterpret_cast(clientp); + if ( data ) { + data->expectedFileSize( expectedFileSize ); + } +} + +/*! + * Executes the given curl handle in a multi context + * + * \note this should not be a const function, but API forces us to do so + */ +CURLcode MediaCurl::executeCurl() const +{ + // initialize our helpers + AutoDispose cMulti( + internal::CurlPollHelper::CurlPoll{ curl_multi_init() } + ,[](auto &releaseMe ){ if (releaseMe._multi) curl_multi_cleanup(releaseMe._multi); } + ); + + if (!cMulti->_multi) + ZYPP_THROW(MediaCurlInitException(_url)); + + // we could derive from that, but currently that does not make a lot of sense + internal::CurlPollHelper _curlHelper(cMulti.value()); + + // add the easy handle to the multi instance + if ( curl_multi_add_handle( cMulti->_multi, _curl ) != CURLM_OK ) + ZYPP_THROW(MediaCurlException( _url, "curl_multi_add_handle", "unknown error")); + + // make sure the handle is cleanly removed from the multi handle + OnScopeExit autoRemove([&](){ curl_multi_remove_handle( cMulti->_multi, _curl ); }); + + // kickstart curl, this will cause libcurl to go over the added handles and register sockets and timeouts + CURLMcode mcode = _curlHelper.handleTimout(); + if (mcode != CURLM_OK) + ZYPP_THROW(MediaCurlException( _url, "curl_multi_socket_action", "unknown error")); + + bool canContinue = true; + while ( canContinue ) { + + // copy watched sockets in case curl changes the vector as we go over the events later + std::vector requestedFds = _curlHelper.socks; + + int r = zypp_detail::zypp_poll( requestedFds, _curlHelper.timeout_ms.value_or( -1 ) ); + if ( r == -1 ) + ZYPP_THROW( MediaCurlException(_url, "zypp_poll() failed", "unknown error") ); + + // run curl + if ( r == 0 ) { + CURLMcode mcode = _curlHelper.handleTimout(); + if (mcode != CURLM_OK) + ZYPP_THROW(MediaCurlException(_url, "curl_multi_socket_action", "unknown error")); + } else { + CURLMcode mcode = _curlHelper.handleSocketActions( requestedFds ); + if (mcode != CURLM_OK) + ZYPP_THROW(MediaCurlException(_url, "curl_multi_socket_action", "unknown error")); + } + + CURLMsg *msg = nullptr; + int nqueue = 0; + while ((msg = curl_multi_info_read( cMulti->_multi, &nqueue)) != 0) { + if ( msg->msg != CURLMSG_DONE ) continue; + if ( msg->easy_handle != _curl ) continue; + + return msg->data.result; + } + } + return CURLE_OK; +} + +/////////////////////////////////////////////////////////////////// + +bool MediaCurl::authenticate(const std::string & availAuthTypes, bool firstTry) const +{ + //! \todo need a way to pass different CredManagerOptions here + CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot())); + CurlAuthData_Ptr credentials; + + // get stored credentials + AuthData_Ptr cmcred = cm.getCred(_url); + + if (cmcred && firstTry) + { + credentials.reset(new CurlAuthData(*cmcred)); + DBG << "got stored credentials:" << endl << *credentials << endl; + } + // if not found, ask user + else + { + + CurlAuthData_Ptr curlcred; + curlcred.reset(new CurlAuthData()); + callback::SendReport auth_report; + + // preset the username if present in current url + if (!_url.getUsername().empty() && firstTry) + curlcred->setUsername(_url.getUsername()); + // if CM has found some credentials, preset the username from there + else if (cmcred) + curlcred->setUsername(cmcred->username()); + + // indicate we have no good credentials from CM + cmcred.reset(); + + std::string prompt_msg = str::Format(_("Authentication required for '%s'")) % _url.asString(); + + // set available authentication types from the exception + // might be needed in prompt + curlcred->setAuthType(availAuthTypes); + + // ask user + if (auth_report->prompt(_url, prompt_msg, *curlcred)) + { + DBG << "callback answer: retry" << endl + << "CurlAuthData: " << *curlcred << endl; + + if (curlcred->valid()) + { + credentials = curlcred; + // if (credentials->username() != _url.getUsername()) + // _url.setUsername(credentials->username()); + /** + * \todo find a way to save the url with changed username + * back to repoinfo or dont store urls with username + * (and either forbid more repos with the same url and different + * user, or return a set of credentials from CM and try them one + * by one) + */ + } + } + else + { + DBG << "callback answer: cancel" << endl; + } + } + + // set username and password + if (credentials) + { + // HACK, why is this const? + const_cast(this)->_settings.setUsername(credentials->username()); + const_cast(this)->_settings.setPassword(credentials->password()); + + // set username and password + CURLcode ret = curl_easy_setopt(_curl, CURLOPT_USERPWD, _settings.userPassword().c_str()); + if ( ret != 0 ) ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); + + // set available authentication types from the exception + if (credentials->authType() == CURLAUTH_NONE) + credentials->setAuthType(availAuthTypes); + + // set auth type (seems this must be set _after_ setting the userpwd) + if (credentials->authType() != CURLAUTH_NONE) + { + // FIXME: only overwrite if not empty? + const_cast(this)->_settings.setAuthType(credentials->authTypeAsString()); + ret = curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, credentials->authType()); + if ( ret != 0 ) ZYPP_THROW(MediaCurlSetOptException(_url, _curlError)); + } + + if (!cmcred) + { + credentials->setUrl(_url); + cm.addCred(*credentials); + cm.save(); + } + + return true; + } + + return false; +} + +//need a out of line definiton, otherwise vtable is emitted for every translation unit +MediaCurl::Callbacks::~Callbacks() {} + + } // namespace media +} // namespace zypp +// diff --git a/zypp/media/MediaCurl.h b/zypp/media/MediaCurl.h new file mode 100644 index 0000000..3ded2e6 --- /dev/null +++ b/zypp/media/MediaCurl.h @@ -0,0 +1,183 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCurl.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIACURL_H +#define ZYPP_MEDIA_MEDIACURL_H + +#include +#include +#include + +#include + +namespace zypp { + namespace media { + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : MediaCurl +/** + * @short Implementation class for FTP, HTTP and HTTPS MediaHandler + * @see MediaHandler + **/ +class MediaCurl : public MediaNetworkCommonHandler +{ + public: + enum RequestOption + { + /** Defaults */ + OPTION_NONE = 0x0, + /** retrieve only a range of the file */ + OPTION_RANGE = 0x1, + /** only issue a HEAD (or equivalent) request */ + OPTION_HEAD = 0x02, + /** to not add a IFMODSINCE header if target exists */ + OPTION_NO_IFMODSINCE = 0x04, + /** do not send a start ProgressReport */ + OPTION_NO_REPORT_START = 0x08, + }; + ZYPP_DECLARE_FLAGS(RequestOptions,RequestOption); + + protected: + + Url clearQueryString(const Url &url) const; + + void attachTo (bool next = false) override; + void releaseFrom( const std::string & ejectDev ) override; + void getFile( const OnMediaLocation & file ) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + /** + * Repeatedly calls doGetDoesFileExist() until it successfully returns, + * fails unexpectedly, or user cancels the operation. This is used to + * handle authentication or similar retry scenarios on media level. + */ + bool getDoesFileExist( const Pathname & filename ) const override; + + /** + * \see MediaHandler::getDoesFileExist + */ + virtual bool doGetDoesFileExist( const Pathname & filename ) const; + + /** + * + * \throws MediaException + * + */ + void disconnectFrom() override; + /** + * + * \throws MediaException + * + */ + void getFileCopy( const OnMediaLocation& srcFile, const Pathname & targetFilename ) const override; + + /** + * + * \throws MediaException + * + */ + virtual void doGetFileCopy( const OnMediaLocation &srcFile, const Pathname & targetFilename, callback::SendReport & _report, RequestOptions options = OPTION_NONE ) const; + + + bool checkAttachPoint(const Pathname &apoint) const override; + + public: + + MediaCurl( const Url & url_r, + const Pathname & attach_point_hint_r ); + + ~MediaCurl() override { try { release(); } catch(...) {} } + + static void setCookieFile( const Pathname & ); + + class Callbacks + { + public: + virtual ~Callbacks(); + virtual bool progress( int percent ) = 0; + }; + + protected: + /** Callback sending just an alive trigger to the UI, without stats (e.g. during metalink download). */ + static int aliveCallback( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow ); + /** Callback reporting download progress. */ + static int progressCallback( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow ); + static CURL *progressCallback_getcurl( void *clientp ); + /** + * check the url is supported by the curl library + * \throws MediaBadUrlException if there is a problem + **/ + void checkProtocol(const Url &url) const; + + /** + * initializes the curl easy handle with the data from the url + * \throws MediaCurlSetOptException if there is a problem + **/ + virtual void setupEasy(); + + /** + * Evaluates a curl return code and throws the right MediaException + * \p filename Filename being downloaded + * \p code Code curl returnes + * \p timeout Whether we reached timeout, which we need to differentiate + * in case the codes aborted-by-callback or timeout are returned by curl + * Otherwise we can't differentiate abort from timeout. Here you may + * want to pass the progress data object timeout-reached value, or + * just true if you are not doing user interaction. + * + * \throws MediaException If there is a problem + */ + void evaluateCurlCode(const zypp::Pathname &filename, CURLcode code, bool timeout) const; + + void doGetFileCopyFile( const OnMediaLocation & srcFile, const Pathname & dest, FILE *file, callback::SendReport & report, RequestOptions options = OPTION_NONE ) const; + + static void resetExpectedFileSize ( void *clientp, const ByteCount &expectedFileSize ); + + private: + + CURLcode executeCurl() const; + + /** + * Return a comma separated list of available authentication methods + * supported by server. + */ + std::string getAuthHint() const; + + bool authenticate(const std::string & availAuthTypes, bool firstTry) const; + + bool detectDirIndex() const; + + private: + std::string _currentCookieFile; + static Pathname _cookieFile; + char _curlError[ CURL_ERROR_SIZE ]; + + mutable std::string _lastRedirect; ///< to log/report redirections + + protected: + CURL *_curl; + curl_slist *_customHeaders; + + const char* curlError() const { return _curlError; }; + void setCurlError(const char* error); +}; +ZYPP_DECLARE_OPERATORS_FOR_FLAGS(MediaCurl::RequestOptions); + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIACURL_H diff --git a/zypp/media/MediaDIR.cc b/zypp/media/MediaDIR.cc new file mode 100644 index 0000000..4f416b5 --- /dev/null +++ b/zypp/media/MediaDIR.cc @@ -0,0 +1,184 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDIR.cc + * +*/ + +#include + +#include +#include + +#include +#include + +using std::endl; + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDIR + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::MediaDIR + // METHOD TYPE : Constructor + // + // DESCRIPTION : Attach point is always url_r.getPathName(), + // as files are not copied. + // Thus attach_point_hint_r is ignored. + // + MediaDIR::MediaDIR( const Url & url_r, + const Pathname & /*attach_point_hint_r*/ ) + : MediaHandler( url_r, url_r.getPathName(), + "/", // urlpath below attachpoint + false ) // does_download + { + MIL << "MediaDIR::MediaDIR(" << url_r << ")" << endl; + if( !url_r.getHost().empty()) + { + ZYPP_THROW(MediaBadUrlException(url_r, + "Hostname not allowed in the Url" + )); + } + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaDIR::attachTo(bool next) + { + if(next) + ZYPP_THROW(MediaNotSupportedException(url())); + + // fetch attach point from url again if needed ... + // it may happen that attachPointHint (and attachPoint()) + // does not contain any path, because the directory has + // not existed while the handler was constructed. + if( attachPoint().empty() && !url().getPathName().empty()) + { + Pathname real( getRealPath(url().getPathName())); + + PathInfo adir( real); + if( adir.isDir()) + { + // set attachpoint only if the dir exists + setAttachPoint( real, false); + } + else + { + ZYPP_THROW(MediaBadUrlException(url(), + "Specified path '" + url().getPathName() + "' is not a directory" + )); + } + } + + // attach point is same as source path... we do not mount here + if(attachPoint().empty()) + { + ZYPP_THROW(MediaBadUrlException(url(), + "The media URL does not provide any useable directory path" + )); + } + else + if(!PathInfo(attachPoint()).isDir()) + { + ZYPP_THROW(MediaBadUrlException(url(), + "Specified path '" + attachPoint().asString() + "' is not a directory" + )); + } + + MediaSourceRef media(new MediaSource("dir", attachPoint().asString())); + setMediaSource(media); + } + + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::releaseFrom + // METHOD TYPE : void + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDIR::releaseFrom( const std::string & ejectDev ) + { + return; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDIR::getFile( const OnMediaLocation &file ) const + { + MediaHandler::getFile( file ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDIR::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDIR::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDIR::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDIR::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDIR::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + bool MediaDIR::getDoesFileExist( const Pathname & filename ) const + { + return MediaHandler::getDoesFileExist( filename ); + } + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaDIR.h b/zypp/media/MediaDIR.h new file mode 100644 index 0000000..a3bd8ef --- /dev/null +++ b/zypp/media/MediaDIR.h @@ -0,0 +1,55 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDIR.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIADIR_H +#define ZYPP_MEDIA_MEDIADIR_H + +#include + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDIR + + /** + * @short Implementation class for DIR MediaHandler + * @see MediaHandler + **/ + class MediaDIR : public MediaHandler { + + protected: + + void attachTo (bool next = false) override; + void releaseFrom( const std::string & ejectDev ) override; + void getFile( const OnMediaLocation & file ) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + bool getDoesFileExist( const Pathname & filename ) const override; + + public: + + MediaDIR( const Url & url_r, + const Pathname & attach_point_hint_r ); + + ~MediaDIR() override { try { release(); } catch(...) {} } + }; + + /////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIADIR_H diff --git a/zypp/media/MediaDISK.cc b/zypp/media/MediaDISK.cc new file mode 100644 index 0000000..ac3e79e --- /dev/null +++ b/zypp/media/MediaDISK.cc @@ -0,0 +1,409 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDISK.cc + * +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/* +** verify devices names as late as possible (while attach) +*/ +#define DELAYED_VERIFY 1 + + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDISK + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::MediaDISK + // METHOD TYPE : Constructor + // + // DESCRIPTION : + // + MediaDISK::MediaDISK( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, + url_r.getPathName(), // urlpath below attachpoint + false ) // does_download + { + MIL << "MediaDISK::MediaDISK(" << url_r << ", " << attach_point_hint_r << ")" << endl; + + _device = Pathname(_url.getQueryParam("device")).asString(); + if( _device.empty()) + { + ERR << "Media url does not contain a device specification" << std::endl; + ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url)); + } +#if DELAYED_VERIFY + DBG << "Verify of " << _device << " delayed" << std::endl; +#else + if( !verifyIfDiskVolume( _device)) + { + ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url)); + } +#endif + + _filesystem = _url.getQueryParam("filesystem"); + if(_filesystem.empty()) + _filesystem="auto"; + + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDISK::verifyIfDiskVolume + // METHOD TYPE : void + // + // DESCRIPTION : Check if specified device file name is + // a disk volume device or throw an error. + // + bool MediaDISK::verifyIfDiskVolume(const Pathname &dev_name) + { + if( dev_name.empty() || + dev_name.asString().compare(0, sizeof("/dev/")-1, "/dev/")) + { + ERR << "Specified device name " << dev_name + << " is not allowed" << std::endl; + return false; + } + + PathInfo dev_info(dev_name); + if( !dev_info.isBlk()) + { + ERR << "Specified device name " << dev_name + << " is not a block device" << std::endl; + return false; + } + + // check if a volume using /dev/disk/by-uuid links first + { + Pathname dpath("/dev/disk/by-uuid"); + std::list dlist; + if( zypp::filesystem::readdir(dlist, dpath) == 0) + { + std::list::const_iterator it; + for(it = dlist.begin(); it != dlist.end(); ++it) + { + PathInfo vol_info(*it); + if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() && + vol_info.devMinor() == dev_info.devMinor()) + { + DBG << "Specified device name " << dev_name + << " is a volume (disk/by-uuid link " + << vol_info.path() << ")" + << std::endl; + return true; + } + } + } + } + + // check if a volume using /dev/disk/by-label links + // (e.g. vbd mapped volumes in a XEN vm) + { + Pathname dpath("/dev/disk/by-label"); + std::list dlist; + if( zypp::filesystem::readdir(dlist, dpath) == 0) + { + std::list::const_iterator it; + for(it = dlist.begin(); it != dlist.end(); ++it) + { + PathInfo vol_info(*it); + if( vol_info.isBlk() && vol_info.devMajor() == dev_info.devMajor() && + vol_info.devMinor() == dev_info.devMinor()) + { + DBG << "Specified device name " << dev_name + << " is a volume (disk/by-label link " + << vol_info.path() << ")" + << std::endl; + return true; + } + } + } + } + + // check if a filesystem volume using the 'blkid' tool + // (there is no /dev/disk link for some of them) + ExternalProgram::Arguments args; + args.push_back( "blkid" ); + args.push_back( "-p" ); + args.push_back( dev_name.asString() ); + + ExternalProgram cmd( args, ExternalProgram::Stderr_To_Stdout ); + cmd >> DBG; + if ( cmd.close() != 0 ) + { + ERR << cmd.execError() << endl + << "Specified device name " << dev_name + << " is not a usable disk volume" + << std::endl; + return false; + } + return true; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaDISK::attachTo(bool next) + { + if(next) + ZYPP_THROW(MediaNotSupportedException(url())); + // FIXME + // do mount --bind /

'(bsc#935885) tag. + */ +inline std::ostream & printRichText( std::ostream & str, std::string text, unsigned indent_r = 0U, unsigned width_r = 0U ) +{ + std::string processRichText( const std::string& text ); + + if ( text.empty() ) + return str; + + static const zypp::str::regex rttag("^[ \t\r\n]*<(p|!--[- ]*DT:Rich[ -]*--)>"); + if( zypp::str::regex_match( text, rttag ) ) + text = processRichText( text ); + + return zypp::str::printIndented( str, text, indent_r, width_r ); // even unindented as it also asserts a trailing '/n' +} + +/** Return [Rich]Text optionally indented as string. */ +inline std::string printRichText( std::string text, unsigned indent_r = 0U, unsigned width_r = 0U ) +{ + zypp::str::Str s; + printRichText( s.stream(), std::move(text), indent_r, width_r ); + return s.str(); +} + +} + +#endif + diff --git a/zypp-tui/utils/text.cc b/zypp-tui/utils/text.cc new file mode 100644 index 0000000..0cc862f --- /dev/null +++ b/zypp-tui/utils/text.cc @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------*/ + +#include +#include +#include "text.h" + +namespace ztui { + +std::string mbs_substr_by_width( boost::string_ref text_r, std::string::size_type colpos_r, std::string::size_type collen_r ) +{ + std::string ret; + if ( collen_r ) + { + const char * spos = nullptr; + size_t slen = 0; + + size_t colend = ( collen_r == std::string::npos ? std::string::npos : colpos_r+collen_r ); // will exploit npos == size_t(-1) + size_t pos = 0; + for( mbs::MbsIterator it( text_r ); ! it.atEnd(); ++it ) + { + // collect sequences [pos,end[ in [colpos_r,colend[ + // partial overlaps are padded + size_t end = pos + it.columns(); + + if ( pos < colpos_r ) // starts before range + { + if ( end > colpos_r ) // pad incomplete sequence at range begin + ret += std::string( std::min(end,colend)-colpos_r, ' ' ); + } + else // starts inside range (pos < colend by the way we loop) + { + if ( end <= colend ) // completely inside + { + if ( !spos ) + spos = it.pos(); + slen += it.size(); + } + else // partial outside + { + if ( spos ) + { + ret += std::string( spos, slen ); + spos = nullptr; + slen = 0; // don't collect it after loop + } + ret += std::string( colend-pos, ' ' ); + break; // done + } + } + + if ( end >= colend ) + break; + pos = end; + } + if ( spos ) + ret += std::string( spos, slen ); + } + return ret; +} + +} diff --git a/zypp-tui/utils/text.h b/zypp-tui/utils/text.h new file mode 100644 index 0000000..57268ab --- /dev/null +++ b/zypp-tui/utils/text.h @@ -0,0 +1,659 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +----------------------------------------------------------------------/ +* +* This file contains private API, this might break at any time between releases. +* Strictly for internal use! +*/ + + +#ifndef ZYPP_UTILS_TEXT_H_ +#define ZYPP_UTILS_TEXT_H_ + +#include +#include + +#include +#include +#include + +namespace ztui { + +/////////////////////////////////////////////////////////////////// +namespace mbs +{ +#define ZYPPER_TRACE_MBS 0 + + struct MbToWc + { + static const char _oooooooo = 0000; + static const char _Xooooooo = 0200; + static const char _XXoooooo = 0300; + static const char _XXXooooo = 0340; + static const char _XXXXoooo = 0360; + static const char _XXXXXooo = 0370; + static const char _ooXXXXXX = 0077; + + MbToWc( char ch ) + : _wc( ch ) + , _cont( -1 ) + { + if ( (_wc & _XXXooooo) == _XXoooooo ) // '110xxxxx' + { _wc &= ~_XXXooooo; _cont = 1; } + else if ( (_wc & _XXXXoooo) == _XXXooooo ) // '1110xxxx' + { _wc &= ~_XXXXoooo; _cont = 2; } + else if ( (_wc & _XXXXXooo) == _XXXXoooo ) // '11110xxx' + { _wc &= ~_XXXXXooo; _cont = 3; } + else if ( (_wc & _Xooooooo) == _oooooooo ) // '0xxxxxxx' + { _cont = 0; } + else // something broken + { _wc = L'?'; } + } + + bool add( char ch ) // return whether ch is a continuation char + { + if ( (ch & _XXoooooo) == _Xooooooo ) // '10xxxxxx' + { + if ( _cont > 0 ) + { _wc = (_wc<<6)+(ch & _ooXXXXXX); --_cont; } + return true; + } + if ( _cont > 0 ) // error, else ignore excess chars + { _wc = L'?'; _cont = -1; } + return false; + } + + wchar_t _wc; + char _cont; + }; + + /////////////////////////////////////////////////////////////////// + /// \class MbsIterator + /// \brief Iterate chars and ANSI SGR in a multi-byte character string + /// + /// The iterator offers (\ref pos, \ref size) of the current \c wchar + /// within the original \a text_r. Also the number of \ref columns the + /// current \c wchar occupies on the screen. + /// + /// \note: The iterator contents fakes all WS to either '\n' or ' '. + /// \note: \ref isCH includes SGR sequences + /////////////////////////////////////////////////////////////////// + struct MbsIterator + { + MbsIterator( boost::string_ref text_r ) + : _text( text_r ) + , _tpos( _text.data() ) + , _trest( _text.size() ) + , _tread( 0 ) + , _cols( size_t(-1) ) + , _wc( L'\0' ) + { memset( &_mbstate, 0, sizeof(_mbstate) ); operator++(); } + + /** Use with care; all WS are faked to either '\n' or ' ' */ + wchar_t & operator*() { return _wc; } + const wchar_t & operator*() const { return _wc; } + + const char * pos() const { return _tpos; } + size_t size() const { return _tread; } + size_t columns() const + { + if ( _cols == size_t(-1) ) + { + if ( _wc < L' ' ) + _cols = 0; // CTRLs + else + { + _cols = ::wcwidth( _wc ); + if ( _cols == size_t(-1) ) + _cols = 1; // -1 due to LC_CTYPE? + } + } + return _cols; + } + + boost::string_ref ref() const { return boost::string_ref( _tpos, _tread ); } + + bool atEnd() const { return _trest == 0; } + bool isNL() const { return( _wc == L'\n' ); } + bool isWS() const { return( _wc == L' ' ); } + bool isCH() const { return !( atEnd() || isNL() || isWS() ); } + bool isSGR() const { return not atEnd() && _wc == L'\033'; } + + MbsIterator & operator++() + { + if ( !atEnd() ) + { + _tpos += _tread; + _trest -= _tread; + + //we hit the end + if ( _trest == 0 ) { + setToEnd(); + return *this; + } + + _tread = ::mbrtowc( &_wc, _tpos, _trest, &_mbstate ); + + _cols = size_t(-1); + + if ( _tread >= (size_t)-2 ) + { + // common case is -1 due to LC_CTYPE + // skip this and continue with next mb + memset( &_mbstate, 0, sizeof(_mbstate) ); + _tread = 1; + MbToWc c( *_tpos ); + while ( ( _tread < _trest ) && c.add( *(_tpos+_tread) ) ) + _tread += 1; + _wc = c._wc; + } + + switch ( _tread ) + { +// case (size_t)-2: +// case (size_t)-1: +// _tread = 0; +// // fall through + case 0: + setToEnd(); + break; + + default: + if ( ::iswspace(_wc) ) + { + switch ( _wc ) + { + case L'\n': + case L' ': + break; + default: + _wc = L' '; + } + } + else if ( _wc == L'\033' ) // ansi SGR ? + { + unsigned asize = ansiSize( _tpos ); + if ( asize && asize <= _trest ) + _tread = asize; + } + break; + } + } + return *this; + } + + private: + unsigned ansiSize( const char * pos_r ) + { + unsigned ret = 0; + const char * p = pos_r; + if ( *p == '\033' && *(++p) == '[' ) + { + for ( char ch = *(++p); ( '0' <= ch && ch <= '9' ) || ch ==';'; ch = *(++p) ) + {;} + if ( *p == 'm' ) + ret = p+1 - pos_r; + } + return ret; + } + + void setToEnd () + { + _trest = 0; // atEnd + _wc = L'\0'; + } + + boost::string_ref _text; + const char * _tpos; // start of last ::mbrtowc + size_t _trest; // _tpos to end of string + size_t _tread; // consumed in last ::mbrtowc + mutable size_t _cols; // number of columns occupied on screen + + wchar_t _wc; // result of last ::mbrtowc + mbstate_t _mbstate; + }; + + /////////////////////////////////////////////////////////////////// + /// \class MbsIteratorNoSGR + /// \brief \ref MbsIterator skipping ANSI SGR + /////////////////////////////////////////////////////////////////// + struct MbsIteratorNoSGR : public MbsIterator + { + MbsIteratorNoSGR( boost::string_ref text_r ) + : MbsIterator( text_r ) + { skipSGR(); } + + MbsIteratorNoSGR & operator++() + { + MbsIterator::operator++(); + skipSGR(); + return *this; + } + + private: + void skipSGR() + { while ( isSGR() ) MbsIterator::operator++(); } + }; + + /////////////////////////////////////////////////////////////////// + /// \class MbsWriteWrapped + /// \brief Write MBString optionally wrapped and indented. + /// + /// The class assumes the output starts at the beginning of a + /// new term line. Every '\n' in text starts a new paragraph + /// (on an new line with default indent). + /// + /// WS at par begin increments indent for this par. + /// + /// Use \ref gotoNextLine to open a new indented line without + /// stating a new par. + /// + /// If MbsWriteWrapped is used in conjunction with plain screen + /// output, you can use \ref resetToParBegin to reset housekeeping + /// data after plain screen output. + /////////////////////////////////////////////////////////////////// + struct MbsWriteWrapped + { + MbsWriteWrapped( std::ostream & out ) + : MbsWriteWrapped( out, 0, 0 ) + {} + + MbsWriteWrapped( std::ostream & out, size_t wrap_r ) + : MbsWriteWrapped( out, 0, wrap_r ) + {} + + MbsWriteWrapped( std::ostream & out, size_t indent_r, size_t wrap_r, int indentFix_r = 0 ) + : _out( out ) + , _defaultWrap( wrap_r ) + , _defaultIndent( indent_r ) + , _defaultIndentFix( indentFix_r ) + , _indent( saneIncrementIndent( 0, _defaultIndent, _defaultWrap ) ) + , _indentFix( _defaultIndentFix ) + , _indentGap( 0 ) + , _lpos( 0 ) + , _gap( 0 ) + , _gapForced( 0 ) + , _gapLines( 0 ) + , _word( nullptr ) + , _wSize( 0 ) + , _wColumns( 0 ) + {} + + size_t defaultWrap() const { return _defaultWrap; } + size_t defaultIndent() const { return _defaultIndent; } + int defaultIndentFix() const { return _defaultIndentFix; } + + size_t indent() const { return _indent; } + size_t lpos() const { return _lpos; } + + bool atLineBegin() const { return( _lpos == 0 ); } + bool atParBegin() const { return( _lpos == 0 && !_gapLines ); } + + /** Reset housekeeping data to the beginning of a paragraph (does not write anything) */ + void resetToParBegin() + { + clearGap(); + clearWord(); + clearIndent(); + _lpos = 0; + } + + + /** Write out any pending word and start a new par (NL unconditionally) */ + void gotoNextPar() + { + writeout(true); + clearIndent(); +#if ( ZYPPER_TRACE_MBS) + _out << "" << std::endl; // "" +#else + _out << std::endl; // "" +#endif + _lpos = 0; + } + + /** Open a new paragraph if not \ref atParBegin */ + void gotoParBegin() + { if ( ! atParBegin() ) gotoNextPar(); } + + + /** Add \a count_r (1) new lines in this par (BR unconditionally) */ + void gotoNextLine( size_t count_r = 1 ) + { + if ( count_r ) + { + writeout(true); // but keep indent + _gapLines += count_r; +#if ( ZYPPER_TRACE_MBS ) + while ( count_r-- ) + _out << "
" << std::endl; // "
" +#else + _out << std::string( count_r, '\n' ); +#endif + _lpos = 0; + } + } + + /** Open a new line in this paragraph if not \ref atLineBegin */ + void gotoLineBegin() + { if ( ! atLineBegin() ) gotoNextLine(); } + + + /** Temporarily increase indent */ + struct ScopedIndentIncrement : private zypp::DtorReset + { + ScopedIndentIncrement( MbsWriteWrapped & mww_r, size_t increment_r ) + : DtorReset( mww_r._indent ) + { mww_r._indent = mww_r.saneIncrementIndent( increment_r ); } + }; + /** \relates ScopedIndentIncrement Temporarily increase indent. */ + ScopedIndentIncrement scopedIndentIncrement( size_t increment_r ) + { return ScopedIndentIncrement( *this, increment_r ); } + + + /** Write \a text_r; starting a new paragraph. */ + void startPar( boost::string_ref text_r ) + { + gotoParBegin(); + write( text_r ); + } + /** \overload Indented */ + void startPar( boost::string_ref text_r, size_t increment_r ) + { ScopedIndentIncrement s1( *this, increment_r ); startPar( text_r ); } + + + /** Continue writing text at the current position. */ + void addString( boost::string_ref text_r ) + { + write( text_r ); + } + /** \overload Indented */ + void addString( boost::string_ref text_r, size_t increment_r ) + { ScopedIndentIncrement s1( *this, increment_r ); addString( text_r ); } + + + /** Continue writing text (separated by WS if not \ref atLineBegin). */ + void writeText( boost::string_ref text_r ) + { + _gapForced = 1; + write( text_r ); + } + /** \overload Indented */ + void writeText( boost::string_ref text_r, size_t increment_r ) + { ScopedIndentIncrement s1( *this, increment_r ); writeText( text_r ); } + + + /** Write \a text_r; starting a new paragraph and ending it after the text was written. */ + void writePar( boost::string_ref text_r ) + { + gotoParBegin(); + write( text_r ); + gotoParBegin(); + } + /** \overload Indented */ + void writePar( boost::string_ref text_r, size_t increment_r ) + { ScopedIndentIncrement s1( *this, increment_r ); writePar( text_r ); } + + + /** Write a \a tag_r with indented definition \a text_r. + * Optional \a tagincr_r (0) and \a textincr_r (28) are counted on + * top of the base increment. + */ + void writeDefinition( boost::string_ref tag_r, boost::string_ref text_r, size_t tagincr_r, size_t textincr_r ) + { + gotoParBegin(); + { + ScopedIndentIncrement s1( *this, tagincr_r ); + write( tag_r, /*leadingWSindents_r*/false ); + } + { + ScopedIndentIncrement s1( *this, textincr_r ); + if ( _lpos < _indent ) + _gapForced = _indent - _lpos; + else + gotoNextLine(); + write( text_r ); + } + gotoParBegin(); + } + /** \overload Use default tag/text increment */ + void writeDefinition( boost::string_ref tag_r, boost::string_ref text_r ) + { writeDefinition( tag_r, text_r, 0, 28 ); } + /** \overload Indented */ + void writeDefinition( boost::string_ref tag_r, boost::string_ref text_r, size_t tagincr_r, size_t textincr_r, size_t increment_r ) + { ScopedIndentIncrement s1( *this, increment_r ); writeDefinition( tag_r, text_r, tagincr_r, textincr_r ); } + /** \overload Indented using default tag/text increment */ + void writeDefinition( boost::string_ref tag_r, boost::string_ref text_r, size_t increment_r ) + { ScopedIndentIncrement s1( *this, increment_r ); writeDefinition( tag_r, text_r ); } + + + private: + /** Append \a text_r indented and wrapped at the current position. + * All words and NL are written, only trailing WS is remembered. + */ + void write( boost::string_ref text_r, bool leadingWSindents_r = true ) + { + for( MbsIterator it( text_r ); ! it.atEnd(); ++it ) + { + if ( it.isNL() ) + { + gotoNextPar(); // write out any pending word and start new par + } + else if ( it.isWS() ) + { + if ( _word ) // write out pending word and start new gap + { + writeout(); + ++_gap; + } + else + { + if ( atParBegin() && leadingWSindents_r ) // ws at par begin may increment indent + ++_indentGap; + else + ++_gap; + } + } + else // non WS // remember in word + { + if ( !_word ) + _word = it.pos(); + _wSize += it.size(); + _wColumns += it.columns(); + } + } + writeout(); // write out any pending word; gaps are remembered for next text + } + + /** Write any pending "indent/gap+word" and reset for next word. + * If \a force_r, gap is cleared even if no word is pending. This + * is used before writing a '\n'. + */ + void writeout( bool force_r = false ) + { + if ( _word ) + { + _writeoutPending(); + // reset gaps and word + clearGap(); + clearWord(); + } + else if ( force_r ) + clearGap(); + } + + void _writeoutPending() + { + // NOTE: we are either atLineBegin or in a _gap between words + if ( !atLineBegin() ) + { + if ( _gap < _gapForced ) + _gap = _gapForced; + if ( !_defaultWrap || _lpos+_gap+_wColumns <= _defaultWrap ) + { + _out << std::string( _gap, ' ' ) << boost::string_ref( _word, _wSize ); + _lpos += _gap + _wColumns; + return; + } + // Here: did not fit on this line + // suppress gap and write indented on next line + clearGap(); + _out << std::endl; + _lpos = 0; + } + + // Here: atLineBegin + unsigned useIndent = fixIndent( _indent + _indentGap + _gap ); + + if ( _defaultWrap ) // fix large indent + { while ( useIndent >= _defaultWrap ) useIndent -= _defaultWrap; } + + // Try writing the whole word + if ( !_defaultWrap || useIndent+_wColumns <= _defaultWrap ) + { + _out << std::string( useIndent, ' ' ) << boost::string_ref( _word, _wSize ); + _lpos += useIndent + _wColumns; + return; + } + + // Still here: word is too big, we need to split it :( + for( MbsIterator it( boost::string_ref( _word, _wSize ) ); ! it.atEnd(); ++it ) + { + if ( atLineBegin() ) + { + _out << std::string( useIndent, ' ' ); + _lpos += useIndent; + } + _out << it.ref(); + ++_lpos; + if ( _lpos >= _defaultWrap ) + { + _out << std::endl; + _lpos = 0; + } + } + } + + /** Return fixed indent_r */ + static size_t fixIndent( size_t indent_r, int indentFix_r ) + { + if ( indentFix_r ) + { + if ( indentFix_r < 0 && ( size_t(-indentFix_r) >= indent_r ) ) + indent_r = 0; + else + indent_r += indentFix_r; + } + return indent_r; + } + + /** Return fixed indent_r (unsets _indentFix) */ + size_t fixIndent( size_t indent_r ) + { + indent_r = fixIndent( indent_r, _indentFix ); + _indentFix = 0; + return indent_r; + } + + /** Return incremented indent, but not to more than 50% of the remaining line size if wrapped. */ + static size_t saneIncrementIndent( size_t current_r, size_t increment_r, size_t wrap_r ) + { + if ( ! increment_r ) + return current_r; + + increment_r += current_r; + if ( wrap_r && current_r < wrap_r ) + { + size_t limit = current_r + ( (wrap_r-current_r)/2 ); + if ( limit < increment_r ) + increment_r = limit; + } + return increment_r; + } + + /** Return incremented \c _indent, but not more than 50% of the remaining line size if wrapped. */ + size_t saneIncrementIndent( size_t increment_r ) + { return saneIncrementIndent( _indent, increment_r, _defaultWrap ); } + + /** Set default indent at par start (reloads \c _indentFix) */ + void clearIndent() + { _indentFix = _defaultIndentFix; _indentGap = 0; } + + /** Set no gaps */ + void clearGap() + { _gap = 0; _gapForced = 0; _gapLines = 0; } + + /** Set no word pending */ + void clearWord() + { _word = nullptr; _wSize = 0; _wColumns = 0; } + + std::ostream & _out; + const size_t _defaultWrap; + const size_t _defaultIndent; + const int _defaultIndentFix; + + size_t _indent; // base indent for par + int _indentFix; // indent correction for a pars 1st line + size_t _indentGap; // additional indent for current par + + size_t _lpos; // cursor pos on current line + + size_t _gap; // amount of WS before next word + size_t _gapForced; // forced WS before next word + size_t _gapLines; // forced NL before next word/par + + const char * _word; // current word start in text + size_t _wSize; // current word size in byte + size_t _wColumns; // current word screen columns + }; +#undef ZYPPER_TRACE_MBS +} // namespace mbs +/////////////////////////////////////////////////////////////////// + +/** + * Wrap and indent given \a text and write it to the output stream \a out. + * + * TODO + * - delete whitespace at the end of lines + * - keep one-letter words with the next + * + * \param out output stream to write to + * \param test text to wrap + * \param indent number of columns by which to indent the whole text + * \param wrap number of columns the text should be wrapped into + * \param indentFix additional indent/outdent for the first line (default: \c 0) + */ +inline void mbs_write_wrapped( std::ostream & out, boost::string_ref text_r, size_t indent_r, size_t wrap_r, int indentFix_r = 0 ) +{ + mbs::MbsWriteWrapped mww( out, indent_r, wrap_r, indentFix_r ); + mww.addString( text_r ); +} +/** \overload for str::Str */ +inline void mbs_write_wrapped( std::ostream & out, const zypp::str::Str & text_r, size_t indent_r, size_t wrap_r, int indentFix_r = 0 ) +{ mbs_write_wrapped( out, text_r.str(), indent_r, wrap_r, indentFix_r ); } + +/** Returns the column width of a multi-byte character string \a text_r */ +inline size_t mbs_width( boost::string_ref text_r ) +{ + size_t ret = 0; + for( mbs::MbsIterator it( text_r ); ! it.atEnd(); ++it ) + ret += it.columns(); + return ret; +} + +/** + * Returns a substring of a multi-byte character string \a text_r starting + * at screen column \a cpos_r and being at most \a clen_r columns wide. + * The string is ' ' padded if multicolumn characters are clipped at start + * or end. + */ +std::string mbs_substr_by_width( boost::string_ref text_r, std::string::size_type colpos_r = 0, std::string::size_type collen_r = std::string::npos ); + +} + +#endif /* ZYPP_UTILS_TEXT_H_ */ diff --git a/zypp.conf b/zypp.conf new file mode 100644 index 0000000..3707fcf --- /dev/null +++ b/zypp.conf @@ -0,0 +1,704 @@ +## Configuration file for software management +## /etc/zypp/zypp.conf +## +## Boolean values are 0 1 yes no on off true false + + +[main] + + +## +## Override the detected architecture +## +## Valid values: i586, i686, x86_64, ppc, ppc64, ia64, s390, s390x, .. +## Default value: Autodetected +## +## ** CAUTION: Only set if you know what you're doing ! +## ** Changing this needs a full refresh (incl. download) +## ** of all repository data. +## +# arch = s390 + + +## +## Path where the caches are kept. +## +## Valid values: A directory +## Default value: /var/cache/zypp +## +# cachedir = /var/cache/zypp + + +## +## Path where the repo metadata is downloaded and kept. +## +## Valid values: A directory +## Default value: {cachedir}/raw +## +## Changing this needs a full refresh (incl. download) of all repository data +## +# metadatadir = /var/cache/zypp/raw + + +## +## Path where the repo solv files are created and kept. +## +## Valid values: A directory +## Default value: {cachedir}/solv +## +# solvfilesdir = /var/cache/zypp/solv + + +## +## Path where the repo packages are downloaded and kept. +## +## Valid values: A directory +## Default value: {cachedir}/packages +## +# packagesdir = /var/cache/zypp/packages + + +## +## Path where the configuration files are kept. +## +## Valid values: A directory +## Default value: /etc/zypp +## +# configdir = /etc/zypp + +## +## Path where the known repositories .repo files are kept +## +## Valid values: A directory +## Default value: {configdir}/repos.d +## +## Changing this invalidates all known repositories +## +# reposdir = /etc/zypp/repos.d + +## +## Path where the known services .service files are kept +## +## Valid values: A directory +## Default value: {configdir}/services.d +## +## Changing this invalidates all known services +## +# servicesdir = /etc/zypp/services.d + +## +## Path where custom repo variable definitions are kept +## +## Valid values: A directory +## Default value: {configdir}/vars.d +## +## Changing this undefines all custom repo variables. Built-in +## variables (like '$arch', '$basearch' or $releasever) are not +## affected, but reset to their default values. +## +## A custom repo variable is defined by creating a file inside the +## directory. The variable name equals the file name. The file's first +## line (up to but not including the newline character) defines the +## variables value. +## +# varsdir = /etc/zypp/vars.d + +## +## Whether repository urls should be probed when added +## +## Valid values: boolean +## Default value: false +## +## If true, accessability of repositories is checked immediately (when added) +## (e.g. 'zypper ar' will check immediately) +## If false, accessability of repositories is checked when refreshed +## (e.g. 'zypper ar' will delay the check until the next refresh) +## +# repo.add.probe = false + + +## +## Amount of time in minutes that must pass before another refresh. +## +## Valid values: Integer +## Default value: 10 +## +## If you have autorefresh enabled for a repository, it is checked for +## up-to-date metadata not more often than every +## minutes. If an automatic request for refresh comes before +## minutes passed since the last check, the request is ignored. +## +## A value of 0 means the repository will always be checked. To get the opposite +## effect, disable autorefresh for your repositories. +## +## This option has no effect for repositories with autorefresh disabled, nor for +## user-requested refresh. +## +# repo.refresh.delay = 10 + +## +## Translated package descriptions to download from repos. +## +## A list of locales for which translated package descriptions should +## be downloaded, in case they are available and the repo supports this. +## Not all repo formats support downloading specific translations only. +## +## Valid values: List of locales like 'en', 'en_US'... +## Default value: RequestedLocales +## +## If data for a specific locale are not available, we try to find some +## fallback. Translations for 'en' are always downloaded. +## +# repo.refresh.locales = en, de + +## +## Maximum number of concurrent connections to use per transfer +## +## Valid values: Integer +## Default value: 5 +## +## This setting is only used if more than one is possible +## Setting it to a reasonable number avoids flooding servers +## +# download.max_concurrent_connections = 5 + +## +## Sets the minimum download speed (bytes per second) +## until the connection is dropped +## This can be useful to prevent security attacks on hosts by +## providing updates at very low speeds. +## +## 0 means no limit +## +# download.min_download_speed = 0 + +## Maximum download speed (bytes per second) +## 0 means no limit +# download.max_download_speed = 0 + +## Number of tries per download which will be +## done without user interaction +## 0 means no limit (use with caution) +# download.max_silent_tries = 5 + +## +## Maximum time in seconds that you allow the connection phase to the server to take. +## +## This only limits the connection phase, it has no impact once it has connected. +## (see also CURLOPT_CONNECTTIMEOUT) +## +## Valid values: Integer +## Default value: 60 +## +# download.connect_timeout = 60 + +## +## Maximum time in seconds that you allow a transfer operation to take. +## +## This is useful for preventing your batch jobs from hanging for hours due +## to slow networks or links going down. Limiting operations to less than a +## few minutes risk aborting perfectly normal operations. +## +## Valid values: [0,3600] +## Default value: 180 +## +# download.transfer_timeout = 180 + +## +## Whether to consider using a .delta.rpm when downloading a package +## +## Valid values: boolean +## Default value: true +## +## Using a delta rpm will decrease the download size for package updates +## since it does not contain all files of the package but only the binary +## diff of changed ones. Recreating the rpm package on the local machine +## is an expensive operation (memory,CPU). If your network connection is +## not too slow, you benefit from disabling .delta.rpm. +## +# download.use_deltarpm = true + +## +## Whether to consider using a deltarpm even when rpm is local +## +## Valid values: boolean +## Default value: false +## +## This option has no effect unless download.use_deltarpm is set true. +## +# download.use_deltarpm.always = false + +## +## Hint which media to prefer when installing packages (download vs. CD). +## +## Valid values: download, volatile +## Default value: download +## +## Note that this just a hint. First of all the solver will choose the 'best' +## package according to its repos priority, version and architecture. But if +## there is a choice, we will prefer packages from the desired media. +## +## Packages available locally are always preferred. The question is whether +## you prefer packages being downloaded via FTP/HTTP/HTTPS (download), rather +## than being prompted to insert a CD/DVD (volatile), in case they are available +## on both media. +## +## Name | Priority | URI +## openSUSE-11.1 99 dvd:/// +## openSUSE-11.1-Oss 99 http://download.opensuse.org/distribution/11.1/repo/oss +## +## In the above example 2 repositories with similar content are used. Rather +## than raising the priority of one of them to 'prefer' a certain media, you +## should use the same priority for both and set download.media_preference +## instead. +## +## download.media_preference = download + +## +## Path where media are preferably mounted or downloaded +## +## Valid values: A (writable) directory +## Default value: /var/adm/mount +## +## The media backend will try to organize media mount points and download areas +## below this directory, unless a different location is requested by the application. +## +## If the directory is not accessible and read/writable for a specific user, +## the fallback is to use /var/tmp. +## +## download.media_mountdir = /var/adm/mount + +## +## Whether to use the geoip feature of download.opensuse.org +## +## Valid values: boolean +## Default value: true +## +## The media backend can rewrite download requests to the geographically closest available mirror. +## Which exact mirror is used will be determined by requesting a "geoip" file from download.opensuse.org +## via a HTTP GET request to https://download.opensuse.org/geoip , the server will use the clients IP to +## determine the closest mirror if available. +## Some specific files are however excluded from this redirection due to security reasons, especially the +## repo metadata index and it's key and checksum files: repomd.xml, repomd.xml.key and repomd.xml.asc +## +## download.use_geoip_mirror = true + +## +## Signature checking (repo metadata and downloaded rpm packages) +## +## boolean gpgcheck (default: on) +## boolean repo_gpgcheck (default: unset -> according to gpgcheck) +## boolean pkg_gpgcheck (default: unset -> according to gpgcheck) +## +## Explicitly setting 'gpgcheck', 'repo_gpgcheck' 'pkg_gpgcheck' in a +## repositories .repo file will overwrite the defaults for this specific +## repo. +## +## If 'gpgcheck' is 'on' (the default) we will check the signature of repo metadata +## (packages are secured via checksum inside the metadata). Using unsigned repos +## needs to be confirmed. +## Packages from signed repos are accepted if their checksum matches the checksum +## stated in the repo metadata. +## Packages from unsigned repos need a valid gpg signature, using unsigned packages +## needs to be confirmed. +## +## The above default behavior can be tuned by explicitly setting 'repo_gpgcheck' +## and/or 'pkg_gpgcheck': +## +## 'repo_gpgcheck = on' same as the default. +## +## 'repo_gpgcheck = off' will silently accept unsigned repos. It will NOT turn off +## signature checking on the whole. Nevertheless, it's not a secure setting. +## +## 'pkg_gpgcheck = on' will enforce the package signature checking and the need +## to confirm unsigned packages for all repos (signed and unsigned). +## +## 'pkg_gpgcheck = off' will silently accept unsigned packages. It will NOT turn off +## signature checking on the whole. Nevertheless, it's not a secure setting. +## +## If 'gpgCheck' is 'off' (not recommended), no checks are performed. You can still +## enable them individually by setting 'repo_gpgcheck' and/or 'pkg_gpgcheck' to 'on'. +## +## DISABLING GPG CHECKS IS NOT RECOMMENDED. +## Signing data enables the recipient to verify that no modifications +## occurred after the data were signed. Accepting data with no, wrong +## or unknown signature can lead to a corrupted system and in extreme +## cases even to a system compromise. +## +# repo_gpgcheck = unset -> according to gpgcheck +# pkg_gpgcheck = unset -> according to gpgcheck + +## +## Commit download policy to use as default. +## +## DownloadOnly, Just download all packages to the local cache. +## Do not install. Implies a dry-run. +## +## DownloadInAdvance, First download all packages to the local cache. +## Then start to install. +## +## DownloadInHeaps, Similar to DownloadInAdvance, but try to split +## the transaction into heaps, where at the end of +## each heap a consistent system state is reached. +## +## DownloadAsNeeded Alternating download and install. Packages are +## cached just to avid CD/DVD hopping. This is the +## traditional behaviour. +## +## If a value is not set, empty or unknown, we pick +## some sane default. +## +## commit.downloadMode = + +## +## Defining directory which contains vendor description files. +## +## Each file in this directory defines a (comma separated) list of +## equivalent vendors string prefixes (case-insensitive comparison): +## ------------------------- file begin ----------------------- +## [main] +## vendors = MyVendor,AlternateName +## ------------------------- file end ----------------------- +## By this vendor strings starting with "MyVendor" or "AlternateName" +## are considered to be equivalent. Packages from equivalent vendors +## may replace each other without being considered as a 'vendor change'. +## +## NOTE: Within the "opensuse*" namespace exact matches (case insensitive) +## are required. "vendors = suse,opensuse" will allow switching between +## "suse*" and "opensuse", but not e.g. "opensuse build service". +## +## Valid values: A directory +## Default value: {configdir}/vendors.d +## +# vendordir = /etc/zypp/vendors.d + + +## +## The solver's general attitude when resolving jobs. +## +## Valid values: +## +## Job - Focus on installing the best version of the requested packages. +## Add missing dependencies as needed. This is the solver's default. +## +## Installed - Focus on applying as little changes to the installed packages +## as needed. Choosing an older version of a package is valid if +## its dependencies require less changes to the system. +## +## Update - Focus on updating requested packages and their dependencies as +## much as possible. +## +## Default - If the value is not set, empty or unknown, we use the default. +## +# solver.focus = + +## +## Whether only required packages are installed. +## +## Recommended packages, will not be regarded. +## +## Valid values: boolean +## Default value: false +## +# solver.onlyRequires = false + +## +## EXPERTS ONLY: Per default the solver will not replace packages of +## different vendors, unless you explicitly ask to do so. Setting this +## option to TRUE will disable this vendor check (unless the application +## explicitly re-enables it). Packages will then be considered based on +## repository priority and version only. This may easily damage your system. +## +## Valid values: boolean +## Default value: false +## +# solver.allowVendorChange = false + +## +## EXPERTS ONLY: TUNE DISTRIBUTION UPGRADE (DUP) +## Set whether to allow package version downgrades upon DUP. +## +## Valid values: boolean +## Default value: true +## +# solver.dupAllowDowngrade = true + +## +## EXPERTS ONLY: TUNE DISTRIBUTION UPGRADE (DUP) +## Set whether follow package renames upon DUP. +## +## Valid values: boolean +## Default value: true +## +# solver.dupAllowNameChange = true + +## +## EXPERTS ONLY: TUNE DISTRIBUTION UPGRADE (DUP) +## Set whether to allow changing the packages architecture upon DUP. +## +## Valid values: boolean +## Default value: true +## +# solver.dupAllowArchChange = true + +## +## EXPERTS ONLY: TUNE DISTRIBUTION UPGRADE (DUP) +## Set whether to allow changing the packages vendor upon DUP. If you +## are following a continuous distribution like Tumbleweed or Factory +## where you use 'zypper dup --no-allow-vendor-change' quite frequently, +## you may indeed benefit from disabling the VendorChange. Packages from +## OBS repos will then be kept rather than being overwritten by Tumbleweeds +## version. +## +## Valid values: boolean +## Default value: true +## +# solver.dupAllowVendorChange = true + +## +## EXPERTS ONLY: Cleanup when deleting packages. Whether the solver should +## per default try to remove packages exclusively required by the ones it's +## asked to delete. +## +## This option should be used on a case by case basis, enabled via +## command line options or switches the applications offer. Changing +## the global default on a system where unattended actions are performed, +## may easily damage your system. +## +## CHANGING THE DEFAULT IS NOT RECOMMENDED. +## +## Valid values: boolean +## Default value: false +## +# solver.cleandepsOnRemove = false + +## +## This file contains requirements/conflicts which fulfill the +## needs of a running system. +## For example the system would be broken if not glibc or kernel is +## installed. +## So the user will be informed if these packages will be deleted. +## +## Format: Each line represents one dependency: +## e.g. +## requires:kernel +## requires:glibc +## Default value: {configdir}/systemCheck +## +# solver.checkSystemFile = /etc/zypp/systemCheck + +## +## This directory can contain files that contain requirements/conflicts +## which fulfill the needs of a running system (see checkSystemFile). +## +## Files are read in alphabetical order. +## +## Default value: {configdir}/systemCheck.d +## +# solver.checkSystemFileDir = /etc/zypp/systemCheck.d + +## +## When committing a dist upgrade (e.g. 'zypper dup') a solver testcase +## is written to /var/log/updateTestcase-. It is needed in bugreports. +## This option returns the number of testcases to keep on the system. Old +## cases will be deleted, as new ones are created. +## +## Use 0 to write no testcase at all, or -1 to keep all testcases. +## +## Valid values: Integer +## Default value: 2 +## +# solver.upgradeTestcasesToKeep = 2 + +## +## Whether dist upgrade should remove a products dropped packages. +## +## A new product may suggest a list of old and no longer supported +## packages (dropped packages). Performing a dist upgrade the solver +## may try to delete them, even if they do not cause any dependency +## problem. +## +## Turning this option off, the solver will not try to remove those +## packages unless they actually do cause dependency trouble. You may +## do the cleanup manually, or simply leave them installed as long +## as you don't need the disk space. +## +## Valid values: Boolean +## Default value: true +## +# solver.upgradeRemoveDroppedPackages = true + +## +## Packages which can be installed in different versions at the same time. +## +## Packages are selected either by name, or by provides. In the later case +## the string must start with "provides:" immediately followed by the capability. +## +## Example: +## kernel - just packages with name 'kernel' +## provides:multiversion(kernel) - all packages providing 'multiversion(kernel)' +## (kernel and kmp packages should do this) +## Valid values: +## Comma separated list of packages. +## +## Default value: +## empty +## +multiversion = provides:multiversion(kernel) + +## +## Defining directory which may contain additional multiversion definitions. +## +## If the directory exists, each file in this directory is scanned, expecting +## one valid multiversion list entry per line. Empty lines and lines starting +## with '#' are ignored. +## ------------------------- [/etc/zypp/multiversion.d/example file begin] ----------------------- +## # An alternate way to enable kernel packages being +## # installed in parallel: +## +## provides:multiversion(kernel) +## ------------------------- [/etc/zypp/multiversion.d/example file end] ----------------------- +## +## Valid values: A directory +## Default value: {configdir}/multiversion.d +## +# multiversiondir = /etc/zypp/multiversion.d + +## Comma separated list of kernel packages to keep installed in parallel, if the +## above multiversion variable is set. Packages can be specified as +## 2.6.32.12-0.7 - Exact version to keep +## latest - Keep kernel with the highest version number +## latest-N - Keep kernel with the Nth highest version number +## running - Keep the running kernel +## oldest - Keep kernel with the lowest version number (the GA kernel) +## oldest+N - Keep kernel with the Nth lowest version number +## +## Note: This entry is not evaluated by libzypp, but by the +## purge-kernels service (via /sbin/purge-kernels). +## +## Default: Do not delete any kernels if multiversion = provides:multiversion(kernel) is set +multiversion.kernels = latest,latest-1,running + +## +## Path to locks file. If not exist then is create. +## In this file is saved also UI locks. +## +## valid value: path to file or place where file can be created +## default value: {configdir}/locks +## +# locksfile.path = /etc/zypp/locks + +## +## Whether to apply locks in locks file after zypp start. +## +## Valid values: boolean +## Default value: true +## +# locksfile.apply = true + +## +## Where update items are stored +## (example: scripts, messages) +## +## Valid values: path to directory +## Default value: /var/adm +## +# update.datadir = /var/adm + +## +## Where update messages are stored +## +## Valid values: path to directory +## Default value: {update.datadir}/update-messages +## +# update.messagesdir = /var/adm/update-messages + +## +## Where update scripts are stored +## +## Valid values: path to directory +## Default value: {update.datadir}/update-scripts +## +# update.scriptsdir = /var/adm/update-scripts + +## +## Command to be invoked to send update messages. +## +## Packages may leave an update message file in {update.messagesdir}. +## At the end of each commit, zypp collects those messages and may send +## a notification to the user. +## +## zypp will prepare the update messages according to the selected +## content format and pipe the content to the command. +## +## Format: +## single - For each update message invoke the command and send +## the message. +## none - For each update message invoke the command but don't +## use a pipe to send any data. You probably want to pass +## the message file on the commandline using %P (see +## Substitutions). +## digest - Single invocation of the command, sending the path +## names of all update message. One per line. +## bulk - Single invocation of the command, sending the +## concatenated content of all update messages, separated +## by Ctrl-L. +## +## Substitutions: +## %p - package identification (name-version-release.arch) +## %P - full path to the update message file +## +## Valid values: The value is specified as "format | command". +## An empty value will turn off any notification. +## +## Examples: single | mail -s 'Update message from %p' root +## none | my-send-script -f %P +## +## Default value: +## +# update.messages.notify = + +## +## Options for package installation: excludedocs +## +## Don't install any files which are marked as documentation. +## +## Valid values: boolean +## Default value: no +## +# rpm.install.excludedocs = no + +## +## Location of history log file. +## +## The history log is described at +## http://en.opensuse.org/Libzypp/Package_History +## +## Valid values: absolute path to a file +## Default value: /var/log/zypp/history +## +# history.logfile = /var/log/zypp/history + +## +## Global credentials directory path. +## +## If a URL contains ?credentials= parameter, the credentials will +## be stored and looked for in a file named in this directory. +## +## Valid values: absolute path to a directory +## Default value: /etc/zypp/credentials.d +## +# credentials.global.dir = /etc/zypp/credentials.d + +## +## Global credentials catalog file path. +## +## This file contains a catalog of all known user credentials which were +## not stored via the ?credentials= URL parameter, i.e. passed +## in URL as username:password component, or entered by user in +## an authentication dialog. +## +## Valid values: absolute path to a file +## Default value: /etc/zypp/credentials.cat +## +# credentials.global.file = /etc/zypp/credentials.cat diff --git a/zypp/APIConfig.h b/zypp/APIConfig.h new file mode 100644 index 0000000..dcb5aec --- /dev/null +++ b/zypp/APIConfig.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Application.cc b/zypp/Application.cc new file mode 100644 index 0000000..b5d4892 --- /dev/null +++ b/zypp/Application.cc @@ -0,0 +1,31 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Application.cc + */ +#include + +//#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + IMPL_PTR_TYPE( Application ); + + Application::Application( const sat::Solvable & solvable_r ) + : ResObject( solvable_r ) + {} + + Application::~Application() + {} + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Application.h b/zypp/Application.h new file mode 100644 index 0000000..5bc7ac5 --- /dev/null +++ b/zypp/Application.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Application.h + */ +#ifndef ZYPP_APPLICATION_H +#define ZYPP_APPLICATION_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + DEFINE_PTR_TYPE(Application); + + /////////////////////////////////////////////////////////////////// + /// \class Application + /// \brief Class representing an application (appdata.xml) + /////////////////////////////////////////////////////////////////// + class ZYPP_API Application : public ResObject + { + public: + using Self = Application; + using TraitsType = ResTraits; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + // no attributes defined by now + + protected: + friend Ptr make( const sat::Solvable & solvable_r ); + /** Ctor */ + Application( const sat::Solvable & solvable_r ); + /** Dtor */ + ~Application() override; + }; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_APPLICATION_H diff --git a/zypp/Arch.cc b/zypp/Arch.cc new file mode 100644 index 0000000..cc4e408 --- /dev/null +++ b/zypp/Arch.cc @@ -0,0 +1,586 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Arch.cc + * +*/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Arch::CompatEntry + // + /** Holds an architecture ID and its compatible relation. + * An architecture is compatibleWith, if its _idBit is set in + * _compatBits. noarch has ID 0, non-builtin archs have ID 1 and + * have to be treated specially. + */ + struct Arch::CompatEntry + { + /** Bitfield for architecture IDs and compatBits relation. + * \note Need one bit for each builtin Arch. + * \todo Migrate to some infinite BitField + */ + using CompatBits = bit::BitField; + + CompatEntry( const std::string & archStr_r, + CompatBits::IntT idBit_r = 1 ) + : _idStr( archStr_r ) + , _archStr( archStr_r ) + , _idBit( idBit_r ) + , _compatBits( idBit_r ) + {} + + CompatEntry( IdString archStr_r, + CompatBits::IntT idBit_r = 1 ) + : _idStr( archStr_r ) + , _archStr( archStr_r.asString() ) + , _idBit( idBit_r ) + , _compatBits( idBit_r ) + {} + + void addCompatBit( const CompatBits & idBit_r ) const + { + if ( idBit_r && ! (_compatBits & idBit_r) ) + { + _compatBits |= idBit_r; + } + } + + /** Return whether \c this is compatible with \a targetEntry_r.*/ + bool compatibleWith( const CompatEntry & targetEntry_r ) const + { + switch ( _idBit.value() ) + { + case 0: + // this is noarch and always comatible + return true; + break; + case 1: + // this is a non builtin: self compatible only + return _archStr == targetEntry_r._archStr; + break; + } + // This is a builtin: compatible if mentioned in targetEntry_r + return bool( targetEntry_r._compatBits & _idBit ); + } + + /** compare by score, then archStr. */ + int compare( const CompatEntry & rhs ) const + { + if ( _idBit.value() != rhs. _idBit.value() ) + return( _idBit.value() < rhs. _idBit.value() ? -1 : 1 ); + return _archStr.compare( rhs._archStr ); // Id 1: non builtin + } + + bool isBuiltIn() const + { return( _idBit != CompatBits(1) ); } + + IdString::IdType id() const + { return _idStr.id(); } + + IdString _idStr; + std::string _archStr; // frequently used by the UI so we keep a reference + CompatBits _idBit; + mutable CompatBits _compatBits; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Arch::CompatEntry Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj ) + { + Arch::CompatEntry::CompatBits bit( obj._idBit ); + unsigned bitnum = 0; + while ( bit ) + { + ++bitnum; + bit >>= 1; + } + return str << str::form( "%-15s ", obj._archStr.c_str() ) << str::numstring(bitnum,2) << ' ' + << obj._compatBits << ' ' << obj._compatBits.value(); + } + + /** \relates Arch::CompatEntry */ + inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs ) + { return lhs._idStr == rhs._idStr; } + /** \relates Arch::CompatEntry */ + inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs ) + { return ! ( lhs == rhs ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry ); + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + // Builtin architecture STRING VALUES to be + // used in defCompatibleWith below! + // + // const IdString _foo( "foo" ); + // const Arch Arch_foo( _foo() ); + // + // NOTE: Builtin CLASS Arch CONSTANTS are defined below. + // You have to change them accordingly in Arch.h. + // + // NOTE: Thake care CompatBits::IntT is able to provide one + // bit for each architecture. + // + #define DEF_BUILTIN(A) \ + namespace { static inline const IdString & a_##A () { static IdString _str(#A); return _str; } } \ + const Arch Arch_##A( a_##A() ) + + DEF_BUILTIN( noarch ); + + DEF_BUILTIN( i386 ); + DEF_BUILTIN( i486 ); + DEF_BUILTIN( i586 ); + DEF_BUILTIN( i686 ); + DEF_BUILTIN( athlon ); + DEF_BUILTIN( x86_64 ); + DEF_BUILTIN( x86_64_v2 ); + DEF_BUILTIN( x86_64_v3 ); + DEF_BUILTIN( x86_64_v4 ); + + DEF_BUILTIN( pentium3 ); + DEF_BUILTIN( pentium4 ); + + DEF_BUILTIN( s390 ); + DEF_BUILTIN( s390x ); + + DEF_BUILTIN( ppc ); + DEF_BUILTIN( ppc64 ); + DEF_BUILTIN( ppc64p7 ); + + DEF_BUILTIN( ppc64le ); + + DEF_BUILTIN( ia64 ); + + DEF_BUILTIN( alphaev67 ); + DEF_BUILTIN( alphaev6 ); + DEF_BUILTIN( alphapca56 ); + DEF_BUILTIN( alphaev56 ); + DEF_BUILTIN( alphaev5 ); + DEF_BUILTIN( alpha ); + + DEF_BUILTIN( sparc64v ); + DEF_BUILTIN( sparcv9v ); + DEF_BUILTIN( sparc64 ); + DEF_BUILTIN( sparcv9 ); + DEF_BUILTIN( sparcv8 ); + DEF_BUILTIN( sparc ); + + DEF_BUILTIN( aarch64 ); + + DEF_BUILTIN( armv7tnhl ); /* exists? */ + DEF_BUILTIN( armv7thl ); /* exists? */ + + DEF_BUILTIN( armv7hnl ); /* legacy: */DEF_BUILTIN( armv7nhl ); + DEF_BUILTIN( armv8hl ); + DEF_BUILTIN( armv7hl ); + DEF_BUILTIN( armv6hl ); + + DEF_BUILTIN( armv8l ); + DEF_BUILTIN( armv7l ); + DEF_BUILTIN( armv6l ); + DEF_BUILTIN( armv5tejl ); + DEF_BUILTIN( armv5tel ); + DEF_BUILTIN( armv5tl ); + DEF_BUILTIN( armv5l ); + DEF_BUILTIN( armv4tl ); + DEF_BUILTIN( armv4l ); + DEF_BUILTIN( armv3l ); + + DEF_BUILTIN( riscv64 ); + + DEF_BUILTIN( sh3 ); + + DEF_BUILTIN( sh4 ); + DEF_BUILTIN( sh4a ); + + DEF_BUILTIN( m68k ); + + DEF_BUILTIN( mips ); + DEF_BUILTIN( mipsel ); + DEF_BUILTIN( mips64 ); + DEF_BUILTIN( mips64el ); + + DEF_BUILTIN( loong64 ); +#undef DEF_BUILTIN + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CompatSet + // + /** Maintain architecture compatibility (Singleton by the way it is used). + * + * Povides \ref Arch::CompatEntry for \ref Arch. Defines the + * compatibleWith relation. + * \li \c noarch has _idBit 0 + * \li \c nonbuiltin archs have _idBit 1 + */ + struct ArchCompatSet : private base::NonCopyable + { + using CompatEntry = Arch::CompatEntry; + using CompatBits = CompatEntry::CompatBits; + + using Set = std::unordered_set; + using iterator = Set::iterator; + using const_iterator = Set::const_iterator; + + /** Singleton access. */ + static ArchCompatSet & instance() + { + static ArchCompatSet _instance; + return _instance; + } + + /** Return the entry related to \a archStr_r. + * Creates an entry for nonbuiltin archs. + */ + const Arch::CompatEntry & assertDef( const std::string & archStr_r ) + { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; } + /** \overload */ + const Arch::CompatEntry & assertDef( IdString archStr_r ) + { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; } + + const_iterator begin() const + { return _compatSet.begin(); } + + const_iterator end() const + { return _compatSet.end(); } + + struct DumpOnCompare + { + int operator()( const CompatEntry & lhs, const CompatEntry & rhs ) const + { return lhs._idBit.value() < rhs._idBit.value(); } + }; + + std::ostream & dumpOn( std::ostream & str ) const + { + str << "ArchCompatSet:"; + std::list ov( _compatSet.begin(), _compatSet.end() ); + ov.sort( DumpOnCompare() ); + for_( it, ov.begin(), ov.end() ) + { + str << endl << ' ' << *it; + } + return str; + } + + private: + /** Singleton ctor. */ + ArchCompatSet() + { + // _noarch must have _idBit 0. + // Other builtins have 1-bit set + // and are initialized done on the fly. + _compatSet.insert( Arch::CompatEntry( a_noarch(), 0 ) ); + /////////////////////////////////////////////////////////////////// + // Define the CompatibleWith relation: + // + // NOTE: Order of definition is significant! (Arch::compare) + // - define compatible (less) architectures first! + // + defCompatibleWith( a_i386(), a_noarch() ); + defCompatibleWith( a_i486(), a_noarch(),a_i386() ); + defCompatibleWith( a_i586(), a_noarch(),a_i386(),a_i486() ); + defCompatibleWith( a_i686(), a_noarch(),a_i386(),a_i486(),a_i586() ); + defCompatibleWith( a_athlon(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() ); + defCompatibleWith( a_x86_64(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon() ); + defCompatibleWith( a_x86_64_v2(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64() ); + defCompatibleWith( a_x86_64_v3(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64(),a_x86_64_v2() ); + defCompatibleWith( a_x86_64_v4(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon(),a_x86_64(),a_x86_64_v2(),a_x86_64_v3() ); + + defCompatibleWith( a_pentium3(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() ); + defCompatibleWith( a_pentium4(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_pentium3() ); + + defCompatibleWith( a_ia64(), a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() ); + // + defCompatibleWith( a_s390(), a_noarch() ); + defCompatibleWith( a_s390x(), a_noarch(),a_s390() ); + // + defCompatibleWith( a_ppc(), a_noarch() ); + defCompatibleWith( a_ppc64(), a_noarch(),a_ppc() ); + defCompatibleWith( a_ppc64p7(), a_noarch(),a_ppc(),a_ppc64() ); + // + defCompatibleWith( a_ppc64le(), a_noarch() ); + // + defCompatibleWith( a_alpha(), a_noarch() ); + defCompatibleWith( a_alphaev5(), a_noarch(),a_alpha() ); + defCompatibleWith( a_alphaev56(), a_noarch(),a_alpha(),a_alphaev5() ); + defCompatibleWith( a_alphapca56(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56() ); + defCompatibleWith( a_alphaev6(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56() ); + defCompatibleWith( a_alphaev67(), a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56(),a_alphaev6() ); + // + defCompatibleWith( a_sparc(), a_noarch() ); + defCompatibleWith( a_sparcv8(), a_noarch(),a_sparc() ); + defCompatibleWith( a_sparcv9(), a_noarch(),a_sparc(),a_sparcv8() ); + defCompatibleWith( a_sparcv9v(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() ); + // + defCompatibleWith( a_sparc64(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() ); + defCompatibleWith( a_sparc64v(), a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9(),a_sparcv9v(),a_sparc64() ); + // + defCompatibleWith( a_armv3l(), a_noarch() ); + defCompatibleWith( a_armv4l(), a_noarch(),a_armv3l() ); + defCompatibleWith( a_armv4tl(), a_noarch(),a_armv3l(),a_armv4l() ); + defCompatibleWith( a_armv5l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl() ); + defCompatibleWith( a_armv5tl(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l() ); + defCompatibleWith( a_armv5tel(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl() ); + defCompatibleWith( a_armv5tejl(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel() ); + defCompatibleWith( a_armv6l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl() ); + defCompatibleWith( a_armv7l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl(),a_armv6l() ); + defCompatibleWith( a_armv8l(), a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl(),a_armv6l(),a_armv7l() ); + + defCompatibleWith( a_armv6hl(), a_noarch() ); + defCompatibleWith( a_armv7hl(), a_noarch(),a_armv6hl() ); + defCompatibleWith( a_armv8hl(), a_noarch(),a_armv7hl() ); + defCompatibleWith( a_armv7hnl(), a_noarch(),a_armv7hl(),a_armv6hl() ); + /*legacy: rpm uses v7hnl */ + defCompatibleWith( a_armv7nhl(), a_noarch(),a_armv7hnl(),a_armv7hl(),a_armv6hl() ); + + /*?*/defCompatibleWith( a_armv7thl(), a_noarch(),a_armv7hl() ); + /*?*/defCompatibleWith( a_armv7tnhl(), a_noarch(),a_armv7hl(),a_armv7nhl(),a_armv7thl() ); + + defCompatibleWith( a_aarch64(), a_noarch() ); + // + defCompatibleWith( a_riscv64(), a_noarch() ); + // + defCompatibleWith( a_sh3(), a_noarch() ); + // + defCompatibleWith( a_sh4(), a_noarch() ); + defCompatibleWith( a_sh4a(), a_noarch(),a_sh4() ); + + defCompatibleWith( a_m68k(), a_noarch() ); + + defCompatibleWith( a_mips(), a_noarch() ); + defCompatibleWith( a_mipsel(), a_noarch() ); + defCompatibleWith( a_mips64(), a_noarch() ); + defCompatibleWith( a_mips64el(), a_noarch() ); + + defCompatibleWith( a_loong64(), a_noarch() ); + // + /////////////////////////////////////////////////////////////////// + // dumpOn( USR ) << endl; + } + + private: + /** Return the next avialable _idBit. + * Ctor injects _noarch into the _compatSet, 1 is for + * nonbuiltin archs, so we can use size for + * buitin archs. + */ + CompatBits::IntT nextIdBit() const + { + if ( CompatBits::size == _compatSet.size() ) + { + // Provide more bits in CompatBits::IntT + INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl; + ZYPP_THROW( Exception("Need more bits to encode architectures.") ); + } + CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size()); + return nextBit; + } + + /** Assert each builtin Arch gets an unique _idBit when + * inserted into the _compatSet. + */ + const CompatEntry & assertCompatSetEntry( IdString archStr_r ) + { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; } + + /** Initialize builtin Archs and set _compatBits. + */ + void defCompatibleWith( IdString targetArch_r, + IdString arch0_r, + IdString arch1_r = IdString(), + IdString arch2_r = IdString(), + IdString arch3_r = IdString(), + IdString arch4_r = IdString(), + IdString arch5_r = IdString(), + IdString arch6_r = IdString(), + IdString arch7_r = IdString(), + IdString arch8_r = IdString(), + IdString arch9_r = IdString() ) + { + const CompatEntry & target( assertCompatSetEntry( targetArch_r ) ); + target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit ); +#define SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit ) + SETARG(1); SETARG(2); SETARG(3); SETARG(4); + SETARG(5); SETARG(6); SETARG(7); SETARG(8); SETARG(9); +#undef SETARG + } + + private: + Set _compatSet; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Arch + // + /////////////////////////////////////////////////////////////////// + + const Arch Arch_empty ( IdString::Empty ); + // remaining Arch_* constants are defined by DEF_BUILTIN above. + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::Arch + // METHOD TYPE : Ctor + // + Arch::Arch() + : _entry( &ArchCompatSet::instance().assertDef( a_noarch() ) ) + {} + + Arch::Arch( IdString::IdType id_r ) + : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) ) + {} + + Arch::Arch( const IdString & idstr_r ) + : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) ) + {} + + Arch::Arch( const std::string & str_r ) + : _entry( &ArchCompatSet::instance().assertDef( str_r ) ) + {} + + Arch::Arch( const char * cstr_r ) + : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) ) + {} + + Arch::Arch( const CompatEntry & rhs ) + : _entry( &rhs ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::idStr + // METHOD TYPE : IdString + // + IdString Arch::idStr() const + { return _entry->_idStr; } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::asString + // METHOD TYPE : const std::string & + // + const std::string & Arch::asString() const + { return _entry->_archStr; } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::isBuiltIn + // METHOD TYPE : bool + // + bool Arch::isBuiltIn() const + { return _entry->isBuiltIn(); } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::compatibleWith + // METHOD TYPE : bool + // + bool Arch::compatibleWith( const Arch & targetArch_r ) const + { return _entry->compatibleWith( *targetArch_r._entry ); } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::baseArch + // METHOD TYPE : Arch + // + Arch Arch::baseArch( ) const + { + // check the multilib archs: + if (Arch_x86_64.compatibleWith(*this)) + { + return Arch_x86_64; + } + if (Arch_sparc64v.compatibleWith(*this)) + { + return Arch_sparc64v; + } + if (Arch_sparc64.compatibleWith(*this)) + { + return Arch_sparc64; + } + if (Arch_ppc64.compatibleWith(*this)) + { + return Arch_ppc64; + } + if (Arch_s390x.compatibleWith(*this)) + { + return Arch_s390x; + } + // Here: no multilib; return arch before noarch + CompatSet cset( compatSet( *this ) ); + if ( cset.size() > 2 ) // systemArchitecture, ..., basearch, noarch + { + return *(++cset.rbegin()); + } + return *this; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::compare + // METHOD TYPE : bool + // + int Arch::compare( const Arch & rhs ) const + { return _entry->compare( *rhs._entry ); } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Arch::compatSet + // METHOD TYPE : Arch::CompatSet + // + Arch::CompatSet Arch::compatSet( const Arch & targetArch_r ) + { + Arch::CompatSet ret; + + for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin(); + it != ArchCompatSet::instance().end(); ++it ) + { + if ( it->compatibleWith( *targetArch_r._entry ) ) + { + ret.insert( Arch(*it) ); + } + } + + return ret; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Arch.h b/zypp/Arch.h new file mode 100644 index 0000000..aa84240 --- /dev/null +++ b/zypp/Arch.h @@ -0,0 +1,375 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Arch.h + * +*/ +#ifndef ZYPP_ARCH_H +#define ZYPP_ARCH_H + +#include +#include +#include +#include + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Arch + // + /** Architecture. + */ + class ZYPP_API Arch + { + public: + /** Default ctor \ref Arc_noarch. */ + Arch(); + + /** Ctor taking Arch as string. */ + explicit Arch( IdString::IdType id_r ); + explicit Arch( const IdString & idstr_r ); + explicit Arch( const std::string & str_r ); + explicit Arch( const char * cstr_r ); + + public: + /** \name IdStringType like interface. + * We can't use the complete \ref IdStringType mixin until + * _doCompare can be redefined on any level, not just as char*. + */ + //@{ + /** String representation of Arch. */ + IdString idStr() const; + /** \overload */ + const std::string & asString() const; + /** \overload */ + const char * c_str() const + { return asString().c_str(); } + + /** Test for an empty Arch (this is \ref Arch_epmty, not \ref Arch_noarch ). */ + bool empty() const + { return asString().empty(); } + + /** Size of the string representation. */ + unsigned size() const + { return asString().size(); } + + /** Expert backdoor. */ + IdString::IdType id() const + { return idStr().id(); } + //@} + + public: + /** Whether this is a buitin (or known) architecture. + * Used e.g. in \ref Capability to determine whether + * some trailing \c ".string" is part ot the name or + * restriction to an architecture. + */ + bool isBuiltIn() const; + + public: + /** Compatibility relation. + * \return \c True iff \c this is compatible with \a targetArch_r. + * \code + * Arch_noarch.compatibleWith( ... ) ==> always true; + * Arch_i686.compatibleWith( Arch_x86_64 ) ==> true; + * Arch_x86_64.compatibleWith( Arch_i686 ) ==> false; + * \endcode + */ + bool compatibleWith( const Arch & targetArch_r ) const; + + /** + * \return the arch before noarch if it's not a multilib arch + * (e.g. x86_64,sparc64v,sparc64,ppc64,s390x). + */ + Arch baseArch() const; + + /** \overload static version. */ + static Arch baseArch( const Arch & targetArch_r ) + { return targetArch_r.baseArch(); } + + /** Arch comparison. + * Compatible architectures are treated as \c less (i.e. i686>i386>noarch). + * So \c Arch_noarch is the least Arch. Equivalent architectures + * (compatible in both directions) are ordered arbitrary. + */ + int compare( const Arch & rhs ) const; + + /** Arch comparison (static version). */ + static int compare( const Arch & lhs, const Arch & rhs ) + { return lhs.compare( rhs ); } + + public: + /** Reversed arch order, best Arch first. */ + using CompatSet = std::set>; + + /** Return a set of all Arch's \ref compatibleWith a \a targetArch_r. + * \note The set is ordered according to compare, thus iterating + * will start at \a targetArch_r and end with \c Arch_noarch. + * \code + * Arch::CompatSet cset( Arch::compatSet( Arch_x86_64 ) ); + * + * cout << str::join( make_transform_iterator( cset.begin(), std::mem_fn(&Arch::asString) ), + * make_transform_iterator( cset.end(), std::mem_fn(&Arch::asString) ) ) + * << endl; + * + * // Prints: x86_64 athlon i686 i586 i486 i386 noarch + * \endcode + */ + static CompatSet compatSet( const Arch & targetArch_r ); + + /** */ + static std::string asString( const CompatSet & cset ) + { + // Explicitely select the overload we want, clang seems to choke if there is a static overload for the + // member function we want to capture in std::mem_fn (fixes GH-478) + const std::string & (Arch::*memfn)( ) const = &Arch::asString; + return str::join( make_transform_iterator( cset.begin(), std::mem_fn( memfn ) ), + make_transform_iterator( cset.end(), std::mem_fn( memfn ) ) ); + } + + public: + struct CompatEntry; + private: + Arch( const CompatEntry & ); + const CompatEntry * _entry; + }; + /////////////////////////////////////////////////////////////////// + + /** \name Builtin architecture constants. + * + * Defined outside Arch as e.g. \c Arch_i386, because some names, + * like \c i388, are used as \c #define, thus unusable as identifier + * like \c Arch::i386. + */ + //@{ + /** \relates Arch + * This is an empty \ref Arch represented by an empty string. + * Sometimes used to indicate an any or an unknown Arch. Don't + * confuse this with \ref Arch_noarch, which is in fact an + * architecture. + */ + extern const Arch Arch_empty ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_noarch ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_pentium4 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_pentium3 ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_x86_64_v4 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_x86_64_v3 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_x86_64_v2 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_x86_64 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_athlon ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_i686 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_i586 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_i486 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_i386 ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_s390x ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_s390 ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_ppc64le ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_ppc64p7 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_ppc64 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_ppc ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_ia64 ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_alphaev67 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_alphaev6 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_alphapca56 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_alphaev56 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_alphaev5 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_alpha ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_sparc64v ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_sparc64 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_sparcv9v ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_sparcv9 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_sparcv8 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_sparc ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_aarch64 ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_armv7tnh ZYPP_API; /* exists? */ + /** \relates Arch */ + extern const Arch Arch_armv7thl ZYPP_API; /* exists? */ + + /** \relates Arch */ + extern const Arch Arch_armv7hnl ZYPP_API, /* legacy: */Arch_armv7nhl ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv7hl ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv6hl ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_armv8hl ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv8l ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv7l ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv6l ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv5tejl ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv5tel ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv5tl ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv5l ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv4tl ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv4l ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_armv3l ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_riscv64 ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_sh3 ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_sh4 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_sh4a ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_m68k ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_mips ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_mipsel ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_mips64 ZYPP_API; + /** \relates Arch */ + extern const Arch Arch_mips64el ZYPP_API; + + /** \relates Arch */ + extern const Arch Arch_loong64 ZYPP_API; + //@} + + /////////////////////////////////////////////////////////////////// + + /** \relates Arch stream output. */ + inline std::ostream & operator<<( std::ostream & str, const Arch & obj ) + { return str << obj.asString(); } + + /** \relates Arch XML output. */ + inline std::ostream & dumpAsXmlOn( std::ostream & str, const Arch & obj ) + { return str << "" << obj << ""; } + + /** \name Equality based on string value. */ + //@{ + /** \relates Arch */ + inline bool operator==( const Arch & lhs, const Arch & rhs ) + { return lhs.asString() == rhs.asString(); } + + /** \relates Arch */ + inline bool operator==( const Arch & lhs, const std::string & rhs ) + { return lhs.asString() == rhs; } + + /** \relates Arch */ + inline bool operator==( const std::string & lhs, const Arch & rhs ) + { return lhs == rhs.asString(); } + + /** \relates Arch */ + inline bool operator!=( const Arch & lhs, const Arch & rhs ) + { return !( lhs == rhs ); } + + /** \relates Arch */ + inline bool operator!=( const Arch & lhs, const std::string & rhs ) + { return !( lhs == rhs ); } + + /** \relates Arch */ + inline bool operator!=( const std::string & lhs, const Arch & rhs ) + { return !( lhs == rhs ); } + //@} + + /////////////////////////////////////////////////////////////////// + + /** Functor finding compatible architectures. + * \see Arch::compatibleWith + */ + struct ArchCompatibleWith + { + /** The target architecture */ + Arch _targetArch; + /** Ctor taking the target architecture */ + ArchCompatibleWith( const Arch & targetArch_r ) + : _targetArch( targetArch_r ) + {} + /** Call Arch::compatibleWith ( \c _targetArch ) on \a rhs. */ + bool operator()( const Arch & rhs ) const + { return rhs.compatibleWith( _targetArch ); } + }; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace std +{ ///////////////////////////////////////////////////////////////// + /** \relates zypp::Arch Default order for std::container based Arch::compare.*/ + template<> +#ifdef __clang__ +constexpr +#endif + inline bool less::operator()( const zypp::Arch & lhs, const zypp::Arch & rhs ) const + { return lhs.compare( rhs ) < 0; } + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ARCH_H diff --git a/zypp/AutoDispose.h b/zypp/AutoDispose.h new file mode 100644 index 0000000..df53541 --- /dev/null +++ b/zypp/AutoDispose.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Bit.h b/zypp/Bit.h new file mode 100644 index 0000000..9a01016 --- /dev/null +++ b/zypp/Bit.h @@ -0,0 +1,344 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Bit.h + * +*/ +#ifndef ZYPP_BIT_H +#define ZYPP_BIT_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// + /** + * \todo Use boost::mpl library to assert constraints + * at compiletime! There various like (TInt is an integral type) + * (begin+size < maxbits) or ( field dependent + * constants must be within the range defined by size ). + */ + namespace bit + { ///////////////////////////////////////////////////////////////// + + namespace bit_detail + { + /** Generate constants with \a _size trailing '1'-bits */ + template + struct Gen1Bits + { + static const TInt value = (Gen1Bits::value << 1)+1; + }; + /** Specialization for \a _length 0 */ + template + struct Gen1Bits + { + static const TInt value = 0; + }; + } + + /** Number of bits available in \a TInt. */ + template + struct MaxBits + { + using IntT = TInt; + static const unsigned value = (sizeof(IntT)*8); + }; + + /** For printing bits. */ + template + inline std::string asString( TInt val, char zero = '0', char one = '1' ) + { + std::string s( MaxBits::value, zero ); + for( unsigned i = MaxBits::value; i; ) + { + --i; + if ( val & (TInt)1 ) + s[i] = one; + val = val >> 1; + }; + return s; + } + + /** A bitmaks of \a _size 1-bits starting at bit \a _begin. */ + template + struct Mask + { + using IntT = TInt; + static const IntT value = bit_detail::Gen1Bits::value << _begin; + static const IntT inverted = ~value; + }; + + /** Range of bits starting at bit \a _begin with length \a _size. */ + template + struct Range + { + using IntT = TInt; + using MaxBits = zypp::bit::MaxBits; + using Mask = zypp::bit::Mask; + + static const unsigned begin = _begin; + static const unsigned size = _size; + static const unsigned end = _begin + _size; + }; + /** Range specialisation for (illegal) zero \a _size. + * Force error at compiletime. Currently because types + * and values are undefined + */ + template + struct Range + {}; + + /** A value with in a Range. + * \code + * typedef Range SubField; // bits 2,3,4 in a char field + * SubField::Mask::value; // 00011100 + * RangeValue::value; // 00000000 + * RangeValue::value; // 00000100 + * RangeValue::value; // 00001000 + * RangeValue::value; // 00001100 + * \endcode + */ + template + struct RangeValue + { + using RangeT = TRange; + using IntT = typename TRange::IntT; + + static const IntT value = _value << RangeT::begin; + }; + + /** A single 1-bit within a Range. + * \code + * typedef Range SubField; // bits 2,3,4 in a char field + * SubField::Mask::value; // 00011100 + * RangeBit::value; // 00000100 + * RangeBit::value; // 00001000 + * RangeBit::value; // 00010000 + * \endcode + */ + template + struct RangeBit + { + using RangeT = TRange; + using IntT = typename TRange::IntT; + + static const IntT value = IntT(1) << (RangeT::begin + _pos); + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : BitField + // + /** An integral type used as BitField. + * + * Most methods exist as templated and nontemplated + * version. The nontemplated operates on the complete + * BitField, while the tamplated ones are restricted + * to the given Range. + * \code + * BitField bf; // 00000000 + * typedef Range SubField; // bits 2,3,4 in a char field + * + * bf.assign( -1 ); // assign SubField in -1 + * // to SubField in bf. + * // 00011100 + * bf.assign( -1 ); // assign -1 to bf + * // 11111111 + * bf.assign( 0 ); // 11100011 + * \endcode + */ + template + class BitField : public Range::value> + { + public: + /** Default ctor: zero. */ + BitField() + : _value( (TInt)0 ) + {} + /** Ctor taking an \a TInt. */ + BitField( const TInt & value_r ) + : _value( value_r ) + {} + + public: + /** Validate in a boolean context. */ + explicit operator bool() const + { return _value != (TInt)0; } + + public: + /** Return the value. */ + template + TInt value() const + { + return _value & TRange::Mask::value; + } + TInt value() const + { + return _value; + } + + /** Value as bit string. */ + template + std::string asString() const + { + return bit::asString( _value & TRange::Mask::value, '_' ); + } + std::string asString() const + { + return bit::asString( _value, '_' ); + } + + /** Assign Range in \a rhs to \c this. */ + template + BitField & assign( TInt rhs ) + { + _value = (_value & TRange::Mask::inverted) + | (rhs & TRange::Mask::value); + return *this; + } + BitField & assign( TInt rhs ) + { + _value = rhs; + return *this; + } + + /** Test for equal value within a Range. */ + template + bool isEqual( TInt rhs ) const + { + return (_value & TRange::Mask::value) + == (rhs & TRange::Mask::value); + } + bool isEqual( TInt rhs ) const + { + return _value == rhs; + } + + public: + + /** Set or unset bits of \a rhs. */ + template + BitField & set( TInt rhs, bool doset_r ) + { return set( (rhs & TRange::Mask::value), doset_r ); } + + BitField & set( TInt rhs, bool doset_r ) + { return doset_r ? set( rhs ) : unset( rhs ); } + + /** Set bits of \a rhs. */ + template + BitField & set( TInt rhs ) + { return set( rhs & TRange::Mask::value ); } + + BitField & set( TInt rhs ) + { _value |= rhs; return *this; } + + /** Unset bits of \a rhs. */ + template + BitField & unset( TInt rhs ) + { return unset( rhs & TRange::Mask::value ); } + + BitField & unset( TInt rhs ) + { _value &= ~rhs; return *this; } + + /** Test whether \b all bits of \a rhs are set. */ + template + bool test( TInt rhs ) + { return test( rhs & TRange::Mask::value ); } + + bool test( TInt rhs ) const + { return (_value & rhs) == rhs; } + + /** Test whether \b at \b least \b one bit of \a rhs is set. */ + template + bool testAnyOf( TInt rhs ) + { return testAnyOf( rhs & TRange::Mask::value ); } + + bool testAnyOf( TInt rhs ) const + { return (_value & rhs); } + + public: + + BitField & operator=( const BitField & rhs ) + { _value = rhs._value; return *this; } + + BitField & operator&=( const BitField & rhs ) + { _value &= rhs._value; return *this; } + + BitField & operator|=( const BitField & rhs ) + { _value |= rhs._value; return *this; } + + BitField & operator^=( const BitField & rhs ) + { _value ^= rhs._value; return *this; } + + BitField & operator<<=( unsigned num ) + { _value <<= num; return *this; } + + BitField & operator>>=( unsigned num ) + { _value >>= num; return *this; } + + BitField operator~() const + { return ~_value; } + + private: + TInt _value; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates BitField Stream output */ + template + std::ostream & operator<<( std::ostream & str, const BitField & obj ) + { + return str << obj.asString(); + } + + /** \relates BitField */ + template + inline bool operator==( const BitField & lhs, const BitField & rhs ) + { return lhs.value() == rhs.value(); } + + /** \relates BitField */ + template + inline bool operator!=( const BitField & lhs, const BitField & rhs ) + { return ! (lhs == rhs); } + + + /** \relates BitField */ + template + inline BitField operator&( const BitField & lhs, const BitField & rhs ) + { return BitField(lhs) &= rhs; } + + /** \relates BitField */ + template + inline BitField operator|( const BitField & lhs, const BitField & rhs ) + { return BitField(lhs) |= rhs; } + + /** \relates BitField */ + template + inline BitField operator^( const BitField & lhs, const BitField & rhs ) + { return BitField(lhs) ^= rhs; } + + /** \relates BitField */ + template + inline BitField operator<<( const BitField & lhs, unsigned num ) + { return BitField(lhs) <<= num; } + + /** \relates BitField */ + template + inline BitField operator>>( const BitField & lhs, unsigned num ) + { return BitField(lhs) >>= num; } + + ///////////////////////////////////////////////////////////////// + } // namespace bit + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BIT_H diff --git a/zypp/Bitmap.h b/zypp/Bitmap.h new file mode 100644 index 0000000..79e40d9 --- /dev/null +++ b/zypp/Bitmap.h @@ -0,0 +1,22 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Bitmap.h + * +*/ +#ifndef ZYPP_BITMAP_H +#define ZYPP_BITMAP_H + +#include +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + using Bitmap = sat::Map; +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_BITMAP_H diff --git a/zypp/ByteArray.h b/zypp/ByteArray.h new file mode 100644 index 0000000..017126a --- /dev/null +++ b/zypp/ByteArray.h @@ -0,0 +1 @@ +#include diff --git a/zypp/ByteCount.h b/zypp/ByteCount.h new file mode 100644 index 0000000..20e2e49 --- /dev/null +++ b/zypp/ByteCount.h @@ -0,0 +1 @@ +#include diff --git a/zypp/CMakeLists.txt b/zypp/CMakeLists.txt new file mode 100644 index 0000000..4b71ca4 --- /dev/null +++ b/zypp/CMakeLists.txt @@ -0,0 +1,1072 @@ +# Collect all files that may contain translatable texts +FILE( GLOB_RECURSE POT_FILE_DEPENDS RELATIVE ${LIBZYPP_SOURCE_DIR} "*.h" "*.cc" ) +SET( POT_FILE_DEPENDS_ZYPP ${POT_FILE_DEPENDS} PARENT_SCOPE ) + +ADD_DEFINITIONS( -DZYPP_DLL ) +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/sywu/include ) +INCLUDE_DIRECTORIES( ${LIBZYPP_SOURCE_DIR} ${LIBZYPP_BINARY_DIR} ${LIBZYPP_SOURCE_DIR}/libs/zypp-core SYSTEM ) + + +FIND_PACKAGE(Rpm REQUIRED) +IF ( NOT RPM_FOUND) + MESSAGE( FATAL_ERROR " rpm-devel not found" ) +ENDIF ( NOT RPM_FOUND) + + + +# add_definitions( -DENABLE_SYWU ) +# add_subdirectory(sywu) + +IF (ENABLE_ZCHUNK_COMPRESSION) + INCLUDE_DIRECTORIES( ${ZCHUNK_INCLUDEDIR} ) +ENDIF(ENABLE_ZCHUNK_COMPRESSION) +#FILE(WRITE filename "message to write"... ) + +SET( zypp_SRCS + Application.cc + Capabilities.cc + Capability.cc + CapMatch.cc + Changelog.cc + CheckSum.cc + CpeId.cc + Dep.cc + Digest.cc + DiskUsageCounter.cc + DownloadMode.cc + Edition.cc + PluginScript.cc + PluginScriptException.cc + PluginExecutor.cc + Fetcher.cc + FileChecker.cc + Glob.cc + HistoryLog.cc + HistoryLogData.cc + IdString.cc + InstanceId.cc + KeyManager.cc + KeyRing.cc + KeyRingContexts.cc + Locks.cc + MediaSetAccess.cc + Package.cc + Patch.cc + PathInfo.cc + Pattern.cc + PoolItem.cc + PoolItemBest.cc + PoolQuery.cc + PoolQueryResult.cc + ProblemSolution.cc + Product.cc + ProvideFilePolicy.cc + PublicKey.cc + PurgeKernels.cc + Range.cc + Rel.cc + RepoInfo.cc + RepoManager.cc + RepoManagerOptions.cc + Repository.cc + RepoStatus.cc + ResKind.cc + ResObject.cc + Resolvable.cc + Resolver.cc + ResolverFocus.cc + ResolverProblem.cc + ResPool.cc + ResPoolProxy.cc + ResStatus.cc + ServiceInfo.cc + Signature.cc + SrcPackage.cc + SysContent.cc + Target.cc + TmpPath.cc + VendorAttr.cc + VendorSupportOptions.cc + ZYpp.cc + ZYppCommitPolicy.cc + ZYppCommitResult.cc + ZYppFactory.cc +) +SET( zypp_EARLY_SRCS + ZConfig.cc + Arch.cc + Locale.cc + CountryCode.cc + LanguageCode.cc +) + +SET( zypp_HEADERS + APIConfig.h + Application.h + Arch.h + Bit.h + Bitmap.h + Callback.h + Capabilities.h + Capability.h + CapMatch.h + Changelog.h + CheckSum.h + ContentType.h + CountryCode.h + CpeId.h + Dep.h + Digest.h + DiskUsageCounter.h + DownloadMode.h + Edition.h + PluginScript.h + PluginScriptException.h + PluginExecutor.h + Fetcher.h + FileChecker.h + Glob.h + HistoryLog.h + HistoryLogData.h + IdString.h + IdStringType.h + InstanceId.h + KeyContext.h + KeyManager.h + KeyRing.h + KeyRingContexts.h + KVMap.h + LanguageCode.h + Locale.h + Locks.h + ManagedFile.h + MediaProducts.h + MediaSetAccess.h + Vendor.h + OnMediaLocation.h + Package.h + PackageKeyword.h + Patch.h + PathInfo.h + Pattern.h + PoolItem.h + PoolItemBest.h + PoolQuery.h + PoolQueryUtil.tcc + PoolQueryResult.h + ProblemSolution.h + ProblemTypes.h + Product.h + ProvideFilePolicy.h + PublicKey.h + PurgeKernels.h + Range.h + RelCompare.h + Rel.h + RepoInfo.h + RepoManager.h + RepoManagerFlags.h + RepoManagerOptions.h + Repository.h + RepoStatus.h + Filter.h + ResFilters.h + ResKind.h + ResObject.h + ResObjects.h + Resolvable.h + Resolver.h + ResolverFocus.h + ResolverNamespace.h + ResolverProblem.h + ResPool.h + ResPoolProxy.h + ResStatus.h + ResTraits.h + ServiceInfo.h + Signature.h + SrcPackage.h + SysContent.h + Target.h + TmpPath.h + UserData.h + VendorAttr.h + VendorSupportOptions.h + ZConfig.h + ZYppCallbacks.h + ZYppCommit.h + ZYppCommitPolicy.h + ZYppCommitResult.h + ZYppFactory.h + ZYpp.h +) + +INSTALL( FILES ${zypp_HEADERS} DESTINATION "${INCLUDE_INSTALL_DIR}/zypp" ) + +SET( zypp_base_SRCS + base/Backtrace.cc + base/DrunkenBishop.cc + base/SerialNumber.cc + base/Random.cc + base/Measure.cc + base/SetRelationMixin.cc + base/StrMatcher.h + base/StrMatcher.cc +) + +SET( zypp_base_HEADERS + base/Backtrace.h + base/Collector.h + base/DrunkenBishop.h + base/SerialNumber.h + base/Env.h + base/Random.h + base/Algorithm.h + base/Counter.h + base/Debug.h + base/Functional.h + base/Json.h + base/LocaleGuard.h + base/Measure.h + base/NamedValue.h + base/ReferenceCounted.h + base/SetRelationMixin.h + base/SetTracker.h + base/Signal.h + base/StrMatcher.h + base/TypeTraits.h + base/ValueTransform.h +) + +INSTALL( FILES + ${zypp_base_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/base +) + +SET( zypp_media_SRCS + media/MediaHandler.cc + media/MediaHandlerFactory.cc + media/MediaNFS.cc + media/MediaCD.cc + media/MediaDIR.cc + media/MediaDISK.cc + media/MediaCIFS.cc + media/MediaNetworkCommonHandler.cc + media/MediaNetwork.cc + media/MediaCurl.cc + media/MediaMultiCurl.cc + media/MediaISO.cc + media/MediaPlugin.cc + media/MediaSource.cc + media/MediaManager.cc + media/MediaPriority.cc + media/UrlResolverPlugin.cc +) + +SET( zypp_media_HEADERS + media/MediaCD.h + media/MediaCIFS.h + media/MediaCurl.h + media/MediaMultiCurl.h + media/MediaNetworkCommonHandler.h + media/MediaNetwork.h + media/MediaDIR.h + media/MediaDISK.h + media/MediaException.h + media/MediaHandler.h + media/MediaHandlerFactory.h + media/MediaISO.h + media/MediaPlugin.h + media/MediaManager.h + media/MediaNFS.h + media/MediaSource.h + media/MediaPriority.h + media/UrlResolverPlugin.h +) + +INSTALL( FILES + ${zypp_media_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/media +) + +SET( zypp_ng_SRCS + ng/context.cc + ng/progressobserveradaptor.cc + ng/reporthelper.cc + ng/repomanager.cc + ng/userrequest.cc + ng/repo/downloader.cc + ng/repo/refresh.cc + ng/repo/workflows/plaindir.cc + ng/repo/workflows/repodownloaderwf.cc + ng/repo/workflows/repomanagerwf.cc + ng/repo/workflows/rpmmd.cc + ng/repo/workflows/serviceswf.cc + ng/repo/workflows/susetags.cc + ng/workflows/checksumwf.cc + ng/workflows/contextfacade.cc + ng/workflows/downloadwf.cc + ng/workflows/keyringwf.cc + ng/workflows/mediafacade.cc + ng/workflows/repoinfowf.cc + ng/workflows/signaturecheckwf.cc +) + +SET( zypp_ng_HEADERS + ng/context.h + ng/Context + ng/progressobserveradaptor.h + ng/reporthelper.h + ng/repomanager.h + ng/RepoManager + ng/userrequest.h + ng/UserRequest + ng/repo/downloader.h + ng/repo/Downloader + ng/repo/refresh.h + ng/repo/Refresh + ng/repo/workflows/plaindir.h + ng/repo/workflows/repodownloaderwf.h + ng/repo/workflows/repomanagerwf.h + ng/repo/workflows/rpmmd.h + ng/repo/workflows/serviceswf.h + ng/repo/workflows/susetags.h + ng/workflows/checksumwf.h + ng/workflows/contextfacade.h + ng/workflows/downloadwf.h + ng/workflows/keyringwf.h + ng/workflows/mediafacade.h + ng/workflows/logichelpers.h + ng/workflows/repoinfowf.h + ng/workflows/signaturecheckwf.h +) + +SET( zypp_ng_private_HEADERS + ng/private/context_p.h + ng/private/repomanager_p.h +) + +#INSTALL( FILES +# ${zypp_ng_HEADERS} +# DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/repo +#) + + +SET( zypp_parser_SRCS + parser/HistoryLogReader.cc + parser/RepoFileReader.cc + parser/RepoindexFileReader.cc + parser/ServiceFileReader.cc + parser/ProductFileReader.cc +) + +SET( zypp_parser_HEADERS + parser/HistoryLogReader.h + parser/ParserProgress.h + parser/RepoFileReader.h + parser/RepoindexFileReader.h + parser/ServiceFileReader.h + parser/ProductFileReader.h +) + +INSTALL( FILES + ${zypp_parser_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/parser +) + +SET( zypp_parser_susetags_SRCS + parser/susetags/RepoIndex.cc + parser/susetags/ContentFileReader.cc +) + +SET( zypp_parser_susetags_HEADERS + parser/susetags/RepoIndex.h + parser/susetags/ContentFileReader.h +) + +INSTALL( FILES + ${zypp_parser_susetags_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/parser/susetags +) + +SET( zypp_parser_xml_SRCS + parser/xml/Node.cc + parser/xml/ParseDef.cc + parser/xml/ParseDefConsume.cc + parser/xml/ParseDefException.cc + parser/xml/Reader.cc + parser/xml/XmlString.cc + parser/xml/libxmlfwd.cc +) + +SET( zypp_parser_xml_HEADERS + parser/xml/Parse.h + parser/xml/Node.h + parser/xml/ParseDef.h + parser/xml/ParseDefConsume.h + parser/xml/ParseDefException.h + parser/xml/ParseDefTraits.h + parser/xml/Reader.h + parser/xml/XmlString.h + parser/xml/libxmlfwd.h +) + +INSTALL( FILES + ${zypp_parser_xml_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/parser/xml +) + +SET( zypp_parser_yum_SRCS + parser/yum/RepomdFileReader.cc +) + +SET( zypp_parser_yum_HEADERS + parser/yum/RepomdFileReader.h +) + +INSTALL( FILES + ${zypp_parser_yum_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/parser/yum +) + +SET( zypp_pool_SRCS + pool/PoolImpl.cc + pool/PoolStats.cc +) + +SET( zypp_pool_HEADERS + pool/PoolImpl.h + pool/PoolStats.h + pool/PoolTraits.h + pool/ByIdent.h +) + +INSTALL( FILES + ${zypp_pool_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/pool +) + +# SET( zypp_solver_detail_SRCS ) + +SET( zypp_solver_HEADERS + solver/Types.h +) + +INSTALL( FILES + ${zypp_solver_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/solver +) + +SET( zypp_solver_detail_SRCS + solver/detail/ProblemSolutionIgnore.cc + solver/detail/ProblemSolutionCombi.cc + solver/detail/Resolver.cc + solver/detail/SolutionAction.cc + solver/detail/Testcase.cc + solver/detail/SolverQueueItem.cc + solver/detail/SolverQueueItemInstall.cc + solver/detail/SolverQueueItemDelete.cc + solver/detail/SolverQueueItemUpdate.cc + solver/detail/SolverQueueItemInstallOneOf.cc + solver/detail/SolverQueueItemLock.cc + solver/detail/SATResolver.cc + solver/detail/SystemCheck.cc +) + +SET( zypp_solver_detail_HEADERS + solver/detail/ProblemSolutionIgnore.h + solver/detail/ProblemSolutionCombi.h + solver/detail/Resolver.h + solver/detail/SolutionAction.h + solver/detail/Testcase.h + solver/detail/Types.h + solver/detail/SolverQueueItem.h + solver/detail/SolverQueueItemInstall.h + solver/detail/SolverQueueItemDelete.h + solver/detail/SolverQueueItemUpdate.h + solver/detail/SolverQueueItemInstallOneOf.h + solver/detail/SolverQueueItemLock.h + solver/detail/ItemCapKind.h + solver/detail/SATResolver.h + solver/detail/SystemCheck.h +) + +INSTALL( FILES + ${zypp_solver_detail_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/solver/detail +) + +SET( zypp_sat_SRCS + sat/Pool.cc + sat/Solvable.cc + sat/SolvableSet.cc + sat/SolvableSpec.cc + sat/SolvIterMixin.cc + sat/Map.cc + sat/Queue.cc + sat/FileConflicts.cc + sat/Transaction.cc + sat/WhatProvides.cc + sat/WhatObsoletes.cc + sat/LocaleSupport.cc + sat/LookupAttr.cc + sat/SolvAttr.cc +) + +SET( zypp_sat_HEADERS + sat/Pool.h + sat/Solvable.h + sat/SolvableSet.h + sat/SolvableType.h + sat/SolvableSpec.h + sat/SolvIterMixin.h + sat/Map.h + sat/Queue.h + sat/FileConflicts.h + sat/Transaction.h + sat/WhatProvides.h + sat/WhatObsoletes.h + sat/LocaleSupport.h + sat/LookupAttr.h + sat/LookupAttrTools.h + sat/SolvAttr.h +) + +INSTALL( FILES + ${zypp_sat_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/sat +) + +SET( zypp_sat_detail_SRCS + sat/detail/PoolImpl.cc +) + +SET( zypp_sat_detail_HEADERS + sat/detail/PoolMember.h + sat/detail/PoolImpl.h +) + +INSTALL( FILES + ${zypp_sat_detail_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/sat/detail +) + + +SET( zypp_target_SRCS + target/RpmPostTransCollector.cc + target/RequestedLocalesFile.cc + target/SolvIdentFile.cc + target/HardLocksFile.cc + target/CommitPackageCache.cc + target/CommitPackageCacheImpl.cc + target/CommitPackageCacheReadAhead.cc + target/TargetCallbackReceiver.cc + target/TargetException.cc + target/TargetImpl.cc + target/TargetImpl.commitFindFileConflicts.cc + +) + +SET( zypp_target_HEADERS + target/RpmPostTransCollector.h + target/RequestedLocalesFile.h + target/SolvIdentFile.h + target/HardLocksFile.h + target/CommitPackageCache.h + target/CommitPackageCacheImpl.h + target/CommitPackageCacheReadAhead.h + target/TargetCallbackReceiver.h + target/TargetException.h + target/TargetImpl.h +) + +INSTALL( FILES + ${zypp_target_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/target +) + +SET( zypp_target_modalias_SRCS + target/modalias/Modalias.cc +) + +SET( zypp_target_modalias_HEADERS + target/modalias/Modalias.h +) + +INSTALL( FILES + ${zypp_target_modalias_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/target/modalias +) + +SET( zypp_target_rpm_SRCS + target/rpm/BinHeader.cc + target/rpm/RpmCallbacks.cc + target/rpm/RpmDb.cc + target/rpm/RpmException.cc + target/rpm/RpmHeader.cc + target/rpm/librpmDb.cc +) + +SET( zypp_target_rpm_HEADERS + target/rpm/BinHeader.h + target/rpm/RpmCallbacks.h + target/rpm/RpmFlags.h + target/rpm/RpmDb.h + target/rpm/RpmException.h + target/rpm/RpmHeader.h + target/rpm/librpm.h + target/rpm/librpmDb.h +) + +INSTALL( FILES + ${zypp_target_rpm_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/target/rpm +) + +SET( zypp_ui_SRCS + ui/Selectable.cc + ui/SelectableImpl.cc + ui/Status.cc + ui/UserWantedPackages.cc +) + +SET( zypp_ui_HEADERS + ui/SelFilters.h + ui/Selectable.h + ui/SelectableImpl.h + ui/SelectableTraits.h + ui/Status.h + ui/UserWantedPackages.h +) + +INSTALL( FILES + ${zypp_ui_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/ui +) + +INSTALL( FILES + ${zypp_url_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/url +) + +SET( zypp_zypp_detail_SRCS + zypp_detail/ZYppImpl.cc +) + +SET( zypp_zypp_detail_HEADERS + zypp_detail/keyring_p.h + zypp_detail/urlcredentialextractor_p.h + zypp_detail/ZYppImpl.h + zypp_detail/ZYppReadOnlyHack.h +) + +INSTALL( FILES + ${zypp_zypp_detail_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/zypp_detail +) + +SET( zypp_repo_SRCS + repo/RepoException.cc + repo/RepoMirrorList.cc + repo/RepoType.cc + repo/ServiceType.cc + repo/PackageProvider.cc + repo/SrcPackageProvider.cc + repo/RepoProvideFile.cc + repo/DeltaCandidates.cc + repo/Applydeltarpm.cc + repo/PackageDelta.cc + repo/SUSEMediaVerifier.cc + repo/MediaInfoDownloader.cc + repo/RepoVariables.cc + repo/RepoInfoBase.cc + repo/PluginRepoverification.cc + repo/PluginServices.cc +) + +SET( zypp_repo_HEADERS + repo/RepoException.h + repo/RepoMirrorList.h + repo/RepoType.h + repo/ServiceType.h + repo/PackageProvider.h + repo/SrcPackageProvider.h + repo/RepoProvideFile.h + repo/DeltaCandidates.h + repo/Applydeltarpm.h + repo/PackageDelta.h + repo/SUSEMediaVerifier.h + repo/MediaInfoDownloader.h + repo/RepoVariables.h + repo/RepoInfoBase.h + repo/PluginRepoverification.h + repo/PluginServices.h +) + +INSTALL( FILES + ${zypp_repo_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/repo +) + +SET( zypp_repo_yum_SRCS + repo/yum/RepomdFileCollector.cc +) + +SET( zypp_repo_yum_HEADERS + repo/yum/RepomdFileCollector.h +) + +SET( zypp_repo_susetags_SRCS +) + +SET( zypp_repo_susetags_HEADERS +) + + +#################################################################### + +SET( zypp_misc_HEADERS + Misc.h + misc/DefaultLoadSystem.h + misc/CheckAccessDeleted.h + misc/TestcaseSetup.h + misc/LoadTestcase.h +) + +SET( zypp_misc_SRCS + misc/DefaultLoadSystem.cc + misc/CheckAccessDeleted.cc + misc/TestcaseSetup.cc + misc/LoadTestcase.cc +) + +INSTALL( FILES + ${zypp_misc_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/misc +) + +#################################################################### + + +SET ( zypp_core_compat_HEADERS + ByteCount.h + Url.h + Globals.h + ExternalProgram.h + Date.h + AutoDispose.h + TriBool.h + Pathname.h + ByteArray.h + ProgressData.h +) + +INSTALL( FILES + ${zypp_core_compat_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp +) + +SET ( zypp_core_base_compat_HEADERS + base/Xml.h + base/Function.h + base/Flags.h + base/StringV.h + base/Iterator.h + base/NonCopyable.h + base/Exception.h + base/Unit.h + base/String.h + base/Regex.h + base/IOTools.h + base/IOStream.h + base/Gettext.h + base/EnumClass.h + base/Logger.h + base/Easy.h + base/ProfilingFormater.h + base/ExternalDataSource.h + base/LogTools.h + base/LogControl.h + base/Hash.h + base/PtrTypes.h + base/Errno.h + base/Iterable.h + base/DefaultIntegral.h + base/DtorReset.h + base/GzStream.h + base/InputStream.h + base/ProvideNumericId.h + base/SimpleStreambuf.h + base/Sysconfig.h + base/UserRequestException.h + base/WatchFile.h + base/fXstream.h +) + +IF (ENABLE_ZCHUNK_COMPRESSION) +list( APPEND zypp_core_base_compat_HEADERS + base/ZckStream.h +) +ENDIF(ENABLE_ZCHUNK_COMPRESSION) + +INSTALL( FILES + ${zypp_core_base_compat_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/base +) + +SET ( zypp_core_url_compat_HEADERS + url/UrlException.h + url/UrlUtils.h + url/UrlBase.h +) + +INSTALL( FILES + ${zypp_core_url_compat_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/url +) + + +SET ( zypp_media_compat_HEADERS + media/CredentialFileReader.h + media/CredentialManager.h + media/MediaBlockList.h + media/MediaUserAuth.h + media/MetaLinkParser.h + media/ProxyInfo.h + media/TransferSettings.h + media/Mount.h + media/CurlConfig.h +) + +INSTALL( FILES + ${zypp_media_compat_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/media +) + +SET ( zypp_core_parser_xml_compat_HEADERS + parser/xml/XmlEscape.h +) + +INSTALL( FILES + ${zypp_core_parser_xml_compat_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/parser/xml +) + + +SET ( zypp_core_parser_compat_HEADERS + parser/IniDict.h + parser/IniParser.h + parser/ParseException.h +) + +INSTALL( FILES + ${zypp_core_parser_compat_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/parser +) + +IF ( LIBPROXY_FOUND ) + SET(zypp_media_proxyinfo_libproxy_HEADERS media/proxyinfo/ProxyInfoLibproxy.h) +ENDIF( LIBPROXY_FOUND ) + +SET( zypp_media_compat_proxyinfo_HEADERS + media/proxyinfo/ProxyInfoImpl.h + media/proxyinfo/ProxyInfoSysconfig.h + ${zypp_media_proxyinfo_libproxy_HEADERS} + media/proxyinfo/ProxyInfos.h +) + +INSTALL( FILES + ${zypp_media_compat_proxyinfo_HEADERS} + DESTINATION ${INCLUDE_INSTALL_DIR}/zypp/media/proxyinfo +) + +SET( zypp_lib_SRCS +${zypp_misc_SRCS} +${zypp_pool_SRCS} +${zypp_parser_susetags_SRCS} +${zypp_parser_xml_SRCS} +${zypp_parser_yum_SRCS} +${zypp_parser_SRCS} +${zypp_media_proxyinfo_SRCS} +${zypp_media_SRCS} +${zypp_ng_SRCS} +${zypp_url_SRCS} +${zypp_repo_SRCS} +${zypp_repo_yum_SRCS} +${zypp_repo_susetags_SRCS} +${zypp_repo_data_SRCS} +${zypp_target_rpm_SRCS} +${zypp_target_hal_SRCS} +${zypp_target_modalias_SRCS} +${zypp_target_SRCS} +${zypp_solver_detail_SRCS} +${zypp_ui_SRCS} +${zypp_SRCS} +${zypp_zypp_detail_SRCS} +${zypp_sat_SRCS} +${zypp_sat_detail_SRCS} +${zypp_EARLY_SRCS} +${zypp_base_SRCS} +) + +SET( zypp_lib_HEADERS +${zypp_target_rpm_HEADERS} +${zypp_parser_tagfile_HEADERS} +${zypp_parser_susetags_HEADERS} +${zypp_parser_yum_HEADERS} +${zypp_parser_xml_HEADERS} +${zypp_parser_HEADERS} +${zypp_ui_HEADERS} +${zypp_media_HEADERS} +${zypp_media_compat_proxyinfo_HEADERS} +${zypp_ng_HEADERS} +${zypp_ng_private_HEADERS} +${zypp_base_HEADERS} +${zypp_solver_HEADERS} +${zypp_solver_detail_HEADERS} +${zypp_sat_HEADERS} +${zypp_sat_detail_HEADERS} +${zypp_url_HEADERS} +${zypp_HEADERS} +${zypp_zypp_detail_HEADERS} +${zypp_repo_HEADERS} +${zypp_source_susetags_HEADERS} +${zypp_target_modalias_HEADERS} +${zypp_target_HEADERS} +${zypp_pool_HEADERS} +${zypp_misc_HEADERS} +${zypp_core_compat_HEADERS} +${zypp_core_base_compat_HEADERS} +${zypp_core_url_compat_HEADERS} +${zypp_core_parser_compat_HEADERS} +${zypp_media_compat_HEADERS} +) + +# Default loggroup for all files +SET_LOGGROUP( "zypp" ${zypp_lib_SRCS} ) + +# override some defaults +SET_LOGGROUP( "libsolv" ${zypp_sat_SRCS} ) + +if ( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + + message(NOTICE "Enabling static analysis: ${ZYPP_CXX_CLANG_TIDY} ${ZYPP_CXX_CPPCHECK}") + + set_source_files_properties( + target/TargetImpl.cc + PROPERTIES + SKIP_LINTING ON + ) + + if (ZYPP_CXX_CLANG_TIDY) + set( CMAKE_CXX_CLANG_TIDY ${ZYPP_CXX_CLANG_TIDY} ) + endif(ZYPP_CXX_CLANG_TIDY) + + if (ZYPP_CXX_CPPCHECK) + set(CMAKE_CXX_CPPCHECK ${ZYPP_CXX_CPPCHECK}) + endif(ZYPP_CXX_CPPCHECK) + +endif( ZYPP_CXX_CLANG_TIDY OR ZYPP_CXX_CPPCHECK ) + +# due to limitations in cmake object libraries feature( object files are not derived transiently, they are only added to the target if they are added DIRECTLY) +# we have this function that adds all zypp objects to a specified target. +function(add_zypp_lib target shared_or_static ) + + set ( _link_mode PRIVATE ) + if ( ${shared_or_static} STREQUAL STATIC ) + message(NOTICE "Building ${target} static") + set ( _link_mode INTERFACE ) + else() + message(NOTICE "Building ${target} shared") + endif() + + ADD_LIBRARY( ${target} ${shared_or_static} ) + + SET_TARGET_PROPERTIES ( ${target} PROPERTIES VERSION "${LIBZYPP_VERSION_INFO}" ) + SET_TARGET_PROPERTIES ( ${target} PROPERTIES SOVERSION "${LIBZYPP_SOVERSION_INFO}" ) + + target_link_libraries( ${target} PRIVATE zypp_lib_compiler_flags ) + TARGET_LINK_LIBRARIES( ${target} PRIVATE zypp-objlib ) + target_link_libraries( ${target} PRIVATE commit-proto-obj ) + + # CAUTION, link those libs always first and always in that order, + # otherwise you get symbol lookup errors when linking against libzypp + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} zypp-curl ) + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} zypp-media ) + + + # CAUTION, link zypp-tui.a at last, to prevent undefined references + # in case tui functions are used in libzypp. + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} zypp-tui ) + + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} zypp-core ) + + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} ${LibSolv_LIBRARIES} ) + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} ${RPM_LIBRARY} ${RPMIO_LIBRARY} ) + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} ${GETTEXT_LIBRARIES} ) + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} ${Boost_THREAD_LIBRARY}) + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} ${GPGME_LIBRARIES}) + target_link_libraries( ${target} ${_link_mode} ${YAML_CPP_LIBRARIES}) + + IF ( UDEV_FOUND ) + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} ${UDEV_LIBRARY} ) + ELSE ( UDEV_FOUND ) + IF ( HAL_FOUND ) + TARGET_LINK_LIBRARIES( ${target} ${_link_mode} ${HAL_LIBRARY} ${HAL_STORAGE_LIBRARY} ${DBUS_LIBRARY} ) + ENDIF ( HAL_FOUND ) + ENDIF ( UDEV_FOUND ) +endfunction() + + +ADD_LIBRARY( zypp-objlib OBJECT ${zypp_lib_SRCS} ${zypp_lib_HEADERS} ) + +target_link_libraries( zypp-objlib PRIVATE zypp_lib_compiler_flags ) + +target_include_directories( zypp-objlib PUBLIC ${RPM_INCLUDE_DIR}) + +# fix includes not relative to rpm +target_include_directories( zypp-objlib PUBLIC ${RPM_INCLUDE_DIR}/rpm) + +# rpm verify function and callback states were introduced in rpm-4.15 +if( RPM_LIB_VER VERSION_GREATER_EQUAL "4.15.0" AND RPM_LIB_VER VERSION_LESS "5.0.0") + target_compile_definitions( zypp-objlib PUBLIC HAVE_RPM_VERIFY_TRANSACTION_STEP ) +endif() + +if( RPM_LIB_VER VERSION_GREATER_EQUAL "5.0.0" ) + MESSAGE( STATUS "rpm found: enable rpm-4 compat interface." ) + target_compile_definitions( zypp-objlib PUBLIC _RPM_5) +endif () + +add_zypp_lib( zypp SHARED ) +set_target_properties ( zypp PROPERTIES LINK_FLAGS "-Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libzypp.map" ) +INSTALL(TARGETS zypp LIBRARY DESTINATION ${LIB_INSTALL_DIR} ) + +# library with more symbols for tests etc +add_zypp_lib( zypp-allsym STATIC ) + +#this part does nothing yet, only when switching away from using a map file to +#a approach where symbols are exported explicitly it would make a difference +#ZYPPNG symbols need to be added to the map file to be exported +IF( EXPORT_NG_API ) +ADD_DEFINITIONS(-DEXPORT_EXPERIMENTAL_API) +INCLUDE(GenerateExportHeader) +message("Exporting experimental libzypp-ng API") +GENERATE_EXPORT_HEADER( + zypp + BASE_NAME zypp-ng + PREFIX_NAME LIB +) +ENDIF ( EXPORT_NG_API ) + +# install XML schemas +FILE( GLOB YUM_SCHEMA_FILES ${LIBZYPP_SOURCE_DIR}/zypp/parser/yum/schema/*.rng ) +INSTALL(FILES ${YUM_SCHEMA_FILES} DESTINATION "${CMAKE_INSTALL_PREFIX}/share/zypp/schema/yum" ) + +ADD_CUSTOM_TARGET ( buildmon + COMMAND test ! -x ./buildmon || ./buildmon +) + +ADD_CUSTOM_COMMAND ( + TARGET zypp POST_BUILD + COMMAND test ! -x ./buildmon || ./buildmon +) diff --git a/zypp/Callback.h b/zypp/Callback.h new file mode 100644 index 0000000..3b6d340 --- /dev/null +++ b/zypp/Callback.h @@ -0,0 +1,319 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Callback.h + * +*/ +#ifndef ZYPP_CALLBACK_H +#define ZYPP_CALLBACK_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** \todo Eliminate this! */ + namespace HACK { + class Callback + { + }; + } // namespace HACK + + /////////////////////////////////////////////////////////////////// + /** Callbacks light. + * + * \par The task report structure (SENDER SIDE). + * + * A default constructible struct derived from callback::ReportBase. + * It \b must \b not contain any data, just virtual methods. + * + * These are the functions the sender invokes, and which will be forwarded + * to some receiver. If no receiver is present, the defined default + * implementations are invoked. + * + * For methods returning non-void, define a reasonable return value, + * because this is what you get back in case no receiver is listening. + * + * This way, the sending side does not need to know whether some receiver + * is listening, and it enables the receiver to return a reasonable value + * in case it has got no idea what else to return. + * + * \code + * struct Foo : public callback::ReportBase + * { + * virtual void ping( int i ) + * {} + * virtual int pong() + * { return -1; } + * + * }; + * \endcode + * + * \par Sending a Task report (SENDER SIDE). + * + * Simply create a callback::SendReport, where TReport + * is your task report structure. Invoke the callback functions + * as needed. That's it. + * + * \note Even creation and destruction of a callback::SendReport + * are indicated to a receiver. So even in case of an Exception, + * the receiver is able to recognize, that the task ended. + * So don't create it without need. + * + * \code + * { + * callback::SendReport report; + * report->ping( 13 ); + * int response = report->pong(); + * } + * \endcode + * + * \par Receiving Task reports (RECEIVER SIDE). + * + * To receive task reports of type \c Foo the recipient class + * derives from callback::ReceiveReport\. callback::ReceiveReport + * inherits \c Foo and provides two additional virtual methods: + * + * \code + * virtual void reportbegin() {} + * virtual void reportend() {} + * \endcode + * + * These two are automatically invoked, whenever the sender + * creates a callback::SendReport instance, and when it gets + * destructed. So even if the sending task is aborted without + * sending an explicit notification, the reciever may notice it, + * by overloading \c reportend. + * + * Overload the methods you're interested in. + * + * \note In case you must return some value and don't know which, + * return the task structures default. The author of the task + * structure had to provide this value, so it's probably better + * than anything you \e invent. + * \code + * int somefunction() + * { + * ...// don't know what to return? + * return Foo::somefunction(); + * } + * \endcode + * + * \par Connecting the Receiver + * + * For this callback::ReceiveReport provides 4 methods: + * \code + * void connect(); + * void disconnect(); + * bool connected() const; + * ReceiveReport * whoIsConnected() const; + * \endcode + * + * \li \c connect Connect this ReceiveReport (in case some other + * ReceiveReport is connected, it get disconnected. Remember it is + * a Callback light). + * \li \c disconnect Disconnect this ReceiveReport in case it is + * connected. If not connected, nothing happens. + * \li \c connected Test whether this ReceiveReport is currently + * connected. + * \li \c whoIsConnected Return a 'ReceiveReport*' to the currently + * connected ReceiveReport, or \c NULL if none is connected. + * + * \par Passing Userdata via Callbacks + * + * For typesafe passing of user data via callbacks, \see \ref UserData. + * + * ReportBase provides a generic \ref callback::ReportBase:report method + * which can be used to communicate by encoding everything in its \a UserData + * argument. + * + * Convenient sending can be achieved by installing non-virtual methods + * in the TReport class, which encode the arguments in UserData and send + * them via ReportBase::report(). + * + * Convenient receiving can be achieved by installing virtual methods in + * the TReport class, which can be simply overloaded by the receiver. Downside + * of this is that adding virtual methods breaks binary compatibility. + */ + namespace callback + { ///////////////////////////////////////////////////////////////// + + /** */ + struct ZYPP_API ReportBase + { + typedef callback::UserData UserData; + typedef UserData::ContentType ContentType; + + /** The most generic way of sending/receiving data. */ + virtual void report( const UserData & userData_r = UserData() ) + {} + + virtual ~ReportBase() + {} + }; + + /** */ + template + struct DistributeReport; + + /** */ + template + struct ZYPP_API ReceiveReport : public TReport + { + typedef TReport ReportType; + typedef ReceiveReport Receiver; + typedef DistributeReport Distributor; + + virtual ~ReceiveReport() + { disconnect(); } + + ReceiveReport * whoIsConnected() const + { return Distributor::instance().getReceiver(); } + + bool connected() const + { return whoIsConnected() == this; } + + void connect() + { Distributor::instance().setReceiver( *this ); } + + void disconnect() + { Distributor::instance().unsetReceiver( *this ); } + + virtual void reportbegin() + {} + virtual void reportend() + {} + }; + + /** */ + template + struct ZYPP_API DistributeReport + { + public: + typedef TReport ReportType; + typedef ReceiveReport Receiver; + typedef DistributeReport Distributor; + + static DistributeReport & instance() + { + static DistributeReport _self; + return _self; + } + + Receiver * getReceiver() const + { return _receiver == &_noReceiver ? 0 : _receiver; } + + void setReceiver( Receiver & rec_r ) + { _receiver = &rec_r; } + + void unsetReceiver( Receiver & rec_r ) + { if ( _receiver == &rec_r ) noReceiver(); } + + void noReceiver() + { _receiver = &_noReceiver; } + + public: + Receiver * operator->() + { return _receiver; } + + private: + DistributeReport() + : _receiver( &_noReceiver ) + {} + Receiver _noReceiver; + Receiver * _receiver; + }; + + /** */ + template + struct ZYPP_API SendReport : private zypp::base::NonCopyable + { + typedef TReport ReportType; + typedef ReceiveReport Receiver; + typedef DistributeReport Distributor; + + SendReport() + { Distributor::instance()->reportbegin(); } + + ~SendReport() + { Distributor::instance()->reportend(); } + + static Receiver * whoIsConnected() + { return Distributor::instance().getReceiver(); } + + static bool connected() + { return whoIsConnected(); } + + Distributor & operator->() + { return Distributor::instance(); } + }; + + /** Temporarily connect a ReceiveReport then restore the previous one. + * + * Pass the ReceiveReport you want to connect temporarily + * to the ctor. The ReceiveReport is connected, a previously + * connected ReceiveReport is remembered and re-connected in + * the dtor. + * Use the default ctpr to temporarily disconnect any connected report. + * \code + * struct FooReceive : public callback::ReceiveReport + * {..}; + * struct FooReceive2 : public callback::ReceiveReport + * {..}; + * + * FooReceive r; + * FooReceive2 r2; + * + * r.connect(); + * ... // r receiving the report + * { + * callback::TempConnect temp( r2 ); + * ...// r2 receiving the report + * } + * ...// r receiving the report + * \endcode + */ + template + struct ZYPP_API TempConnect + { + typedef TReport ReportType; + typedef ReceiveReport Receiver; + typedef DistributeReport Distributor; + + TempConnect() + : _oldRec( Distributor::instance().getReceiver() ) + { + Distributor::instance().noReceiver(); + } + + TempConnect( Receiver & rec_r ) + : _oldRec( Distributor::instance().getReceiver() ) + { + rec_r.connect(); + } + + ~TempConnect() + { + if ( _oldRec ) + Distributor::instance().setReceiver( *_oldRec ); + else + Distributor::instance().noReceiver(); + } + private: + Receiver * _oldRec; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace callback + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CALLBACK_H diff --git a/zypp/CapMatch.cc b/zypp/CapMatch.cc new file mode 100644 index 0000000..ddf23cc --- /dev/null +++ b/zypp/CapMatch.cc @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CapMatch.cc + * +*/ +#include +//#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const CapMatch CapMatch::yes( true ); + const CapMatch CapMatch::no( false ); + const CapMatch CapMatch::irrelevant; + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const CapMatch & obj ) + { + if ( obj._result == CapMatch::IRRELEVANT ) + return str << "IRRELEVANT"; + return str << ( obj._result == CapMatch::MATCH ? "MATCH" : "NOMATCH" ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/CapMatch.h b/zypp/CapMatch.h new file mode 100644 index 0000000..822598d --- /dev/null +++ b/zypp/CapMatch.h @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CapMatch.h + * +*/ +#ifndef ZYPP_CAPMATCH_H +#define ZYPP_CAPMATCH_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CapMatch + // + /** Tri state Capability match result. + * + * CapMatch::irrelevant denotes a result value that should be ignored. + * Therfore it behaves neutral when used in ! && || expressions. + * + * \code + * CapMatch any + * (CapMatch::irrelevant && any) == any // true + * (CapMatch::irrelevant || any) == any // true + * ( !CapMatch::irrelevant ) == CapMatch::irrelevant // true + * \endcode + */ + class ZYPP_API CapMatch + { + enum Result { NOMATCH, MATCH, IRRELEVANT }; + + public: + + CapMatch() + : _result( IRRELEVANT ) + {} + + CapMatch( bool val_r ) + : _result( val_r ? MATCH : NOMATCH ) + {} + + static const CapMatch yes; + static const CapMatch no; + static const CapMatch irrelevant; + + friend bool operator==( const CapMatch & lhs, const CapMatch & rhs ) + { return lhs._result == rhs._result; } + + friend bool operator!=( const CapMatch & lhs, const CapMatch & rhs ) + { return lhs._result != rhs._result; } + + friend CapMatch operator!( const CapMatch & lhs ) + { + if ( lhs._result == CapMatch::IRRELEVANT ) + return lhs; + return !(lhs._result == CapMatch::MATCH); + } + + friend CapMatch operator&&( const CapMatch & lhs, const CapMatch & rhs ) + { + if ( lhs._result == CapMatch::IRRELEVANT ) + return rhs; + if ( rhs._result == CapMatch::IRRELEVANT ) + return lhs; + return (lhs._result == CapMatch::MATCH) + && (rhs._result == CapMatch::MATCH); + } + + friend CapMatch operator||( const CapMatch & lhs, const CapMatch & rhs ) + { + if ( lhs._result == CapMatch::IRRELEVANT ) + return rhs; + if ( rhs._result == CapMatch::IRRELEVANT ) + return lhs; + return (lhs._result == CapMatch::MATCH) + || (rhs._result == CapMatch::MATCH); + } + + friend std::ostream & operator<<( std::ostream & str, const CapMatch & obj ); + + private: + Result _result; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CapMatch Stream output */ + std::ostream & operator<<( std::ostream & str, const CapMatch & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CAPMATCH_H diff --git a/zypp/Capabilities.cc b/zypp/Capabilities.cc new file mode 100644 index 0000000..36fdeea --- /dev/null +++ b/zypp/Capabilities.cc @@ -0,0 +1,72 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Capabilities.cc + * +*/ +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + Capabilities:: Capabilities( const sat::detail::IdType * base_r, sat::detail::IdType skip_r ) + : _begin( base_r ) + { + if ( ! _begin ) + return; + + if ( skip_r ) + { + for ( const sat::detail::IdType * end = _begin; *end; ++end ) + { + if ( *end == skip_r ) + { + _begin = end+1; + return; + } + } + } + // skipp all ==> empty + _begin = 0; + } + + + Capabilities::size_type Capabilities::size() const + { + if ( ! _begin ) + return 0; + + // jump over libsolvs internal ids. + Capabilities::size_type ret = 0; + for ( const sat::detail::IdType * end = _begin; *end; ++end ) + { + if ( ! sat::detail::isDepMarkerId( *end ) ) + ++ret; + } + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Capabilities & obj ) + { + return dumpRange( str << "(" << obj.size() << ")", obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Capabilities.h b/zypp/Capabilities.h new file mode 100644 index 0000000..47cd406 --- /dev/null +++ b/zypp/Capabilities.h @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Capabilities.h + * +*/ +#ifndef ZYPP_SAT_CAPABILITIES_H +#define ZYPP_SAT_CAPABILITIES_H + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Capabilities + // + /** Container of \ref Capability (currently read only). + * + * \note libsolv dependency lists may include internal ids + * which must be skipped on iteration or size calculation + * (\see \ref detail::isDepMarkerId). + */ + class ZYPP_API Capabilities + { + public: + typedef Capability value_type; + typedef unsigned size_type; + + enum Mode { SKIP_TO_INTERNAL }; + + public: + /** Default ctor */ + Capabilities() + : _begin( 0 ) + {} + + /** Ctor from Id pointer (friend \ref Solvable). */ + explicit + Capabilities( const sat::detail::IdType * base_r ) + : _begin( base_r ) + {} + + /** Ctor from Id pointer (friend \ref Solvable). + * Jump behind skip_r (e.g. behind prereqMarker). + */ + Capabilities( const sat::detail::IdType * base_r, sat::detail::IdType skip_r ); + + public: + /** Whether the container is empty. */ + bool empty() const + { return ! ( _begin && *_begin ); } + + /** Number of capabilities inside. */ + size_type size() const; + + public: + class const_iterator; + + /** Iterator pointing to the first \ref Capability. */ + const_iterator begin() const; + + /** Iterator pointing behind the last \ref Capability. */ + const_iterator end() const; + + public: + /** Return whether the set contains \a lhs (the Id)*/ + bool contains( const Capability & lhs ) const; + + /** Return whether \a lhs matches at least one capability in set. */ + bool matches( const Capability & lhs ) const; + + private: + const sat::detail::IdType * _begin; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Capabilities Stream output */ + std::ostream & operator<<( std::ostream & str, const Capabilities & obj ); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Capabilities::const_iterator + // + /** \ref Capabilities iterator. + */ + class Capabilities::const_iterator : public boost::iterator_adaptor< + const_iterator // Derived + , const sat::detail::IdType * // Base + , const Capability // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , const Capability // Reference + > + { + public: + const_iterator() + : const_iterator::iterator_adaptor_( 0 ) + {} + + explicit const_iterator( const sat::detail::IdType * _idx ) + : const_iterator::iterator_adaptor_( _idx ) + { + if ( base_reference() && sat::detail::isDepMarkerId( *base_reference() ) ) + { + _tagged = true; + ++base_reference(); + } + } + + public: + /** Return \c true if the \ref Capability is \c tagged. + * The meaning of \c tagged depends on the kind of dependency you + * are processing. It is a hint that the iteratir skipped some + * internal marker, indicating that subsequent cabailities have + * a special property. Within a \ref Solvables requirements e.g. + * the pre-requirements are tagged. + * \code + * Capabilities req( solvable.requires() ); + * for_( it, req.begin(), req.end() ) + * { + * if ( it.tagged() ) + * cout << *it << " (is prereq)" << endl; + * else + * cout << *it << endl; + * } + * \endcode + */ + bool tagged() const { return _tagged; } + + private: + friend class boost::iterator_core_access; + + reference dereference() const + { return ( base() ) ? Capability( *base() ) : Capability::Null; } + + template + bool equal( const boost::iterator_adaptor & rhs ) const + { // NULL pointer is eqal pointer to Id 0 + return ( base() == rhs.base() // includes both NULL... + || ( !rhs.base() && !*base() ) + || ( !base() && !*rhs.base() ) ); + } + + void increment() + { // jump over libsolvs internal ids. + if ( sat::detail::isDepMarkerId( *(++base_reference()) ) ) + { + _tagged = true; + ++base_reference(); + } + } + + private: + DefaultIntegral _tagged; + }; + /////////////////////////////////////////////////////////////////// + + inline Capabilities::const_iterator Capabilities::begin() const + { return const_iterator( _begin ); } + + inline Capabilities::const_iterator Capabilities::end() const + { return const_iterator( 0 ); } + + inline bool Capabilities::contains( const Capability & lhs ) const + { + for ( const Capability & rhs : *this ) + if ( lhs == rhs ) + return true; + return false; + } + + inline bool Capabilities::matches( const Capability & lhs ) const + { + for ( const Capability & rhs : *this ) + if ( lhs.matches( rhs ) == CapMatch::yes ) + return true; + return false; + } + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_CAPABILITIES_H diff --git a/zypp/Capability.cc b/zypp/Capability.cc new file mode 100644 index 0000000..ca0b67d --- /dev/null +++ b/zypp/Capability.cc @@ -0,0 +1,728 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Capability.cc + * +*/ +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + /// Round Robin string buffer + template + struct TempStrings + { + /** Reference to the next (cleared) tempstring. */ + std::string & getNext() + { unsigned c = _next; _next = (_next+1) % TLen; _buf[c].clear(); return _buf[c]; } + + private: + unsigned _next = 0; + std::string _buf[TLen]; + }; + + /** backward skip whitespace starting at pos_r */ + inline std::string::size_type backskipWs( const std::string & str_r, std::string::size_type pos_r ) + { + for ( ; pos_r != std::string::npos; --pos_r ) + { + char ch = str_r[pos_r]; + if ( ch != ' ' && ch != '\t' ) + break; + } + return pos_r; + } + + /** backward skip non-whitespace starting at pos_r */ + inline std::string::size_type backskipNWs( const std::string & str_r, std::string::size_type pos_r ) + { + for ( ; pos_r != std::string::npos; --pos_r ) + { + char ch = str_r[pos_r]; + if ( ch == ' ' || ch == '\t' ) + break; + } + return pos_r; + } + + /** Split any 'op edition' from str_r */ + void splitOpEdition( std::string & str_r, Rel & op_r, Edition & ed_r ) + { + if ( str_r.empty() ) + return; + std::string::size_type ch( str_r.size()-1 ); + + // check whether the one but last word is a valid Rel: + if ( (ch = backskipWs( str_r, ch )) != std::string::npos ) + { + std::string::size_type ee( ch ); + if ( (ch = backskipNWs( str_r, ch )) != std::string::npos ) + { + std::string::size_type eb( ch ); + if ( (ch = backskipWs( str_r, ch )) != std::string::npos ) + { + std::string::size_type oe( ch ); + ch = backskipNWs( str_r, ch ); // now before 'op'? begin + if ( op_r.parseFrom( str_r.substr( ch+1, oe-ch ) ) ) + { + // found a legal 'op' + ed_r = Edition( str_r.substr( eb+1, ee-eb ) ); + if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS + ch = backskipWs( str_r, ch ); + str_r.erase( ch+1 ); + return; + } + } + } + } + // HERE: Didn't find 'name op edition' + // As a convenience we check for an embeded 'op' (not surounded by WS). + // But just '[<=>]=?|!=' and not inside '()'. + ch = str_r.find_last_of( "<=>)" ); + if ( ch != std::string::npos && str_r[ch] != ')' ) + { + std::string::size_type oe( ch ); + + // do edition first: + ch = str_r.find_first_not_of( " \t", oe+1 ); + if ( ch != std::string::npos ) + ed_r = Edition( str_r.substr( ch ) ); + + // now finish op: + ch = oe-1; + if ( str_r[oe] != '=' ) // '[<>]' + { + op_r = ( str_r[oe] == '<' ) ? Rel::LT : Rel::GT; + } + else + { // '?=' + if ( ch != std::string::npos ) + { + switch ( str_r[ch] ) + { + case '<': --ch; op_r = Rel::LE; break; + case '>': --ch; op_r = Rel::GE; break; + case '!': --ch; op_r = Rel::NE; break; + case '=': --ch; // fall through + default: op_r = Rel::EQ; break; + } + } + } + + // finally name: + if ( ch != std::string::npos ) // 'op' is not at str_r begin, so skip WS + ch = backskipWs( str_r, ch ); + str_r.erase( ch+1 ); + return; + } + // HERE: It's a plain 'name' + } + + /** Build \ref Capability from data. No parsing required. + */ + sat::detail::IdType relFromStr( sat::detail::CPool * pool_r, + const Arch & arch_r, + const std::string & name_r, + Rel op_r, + const Edition & ed_r, + const ResKind & kind_r ) + { + // First build the name, non-packages prefixed by kind + sat::Solvable::SplitIdent split( kind_r, name_r ); + sat::detail::IdType nid( split.ident().id() ); + + if ( split.kind() == ResKind::srcpackage ) + { + // map 'kind srcpackage' to 'arch src', the pseudo architecture + // libsolv uses. + nid = ::pool_rel2id( pool_r, nid, IdString(ARCH_SRC).id(), REL_ARCH, /*create*/true ); + } + + // Extend name by architecture, if provided and not a srcpackage + if ( ! arch_r.empty() && kind_r != ResKind::srcpackage ) + { + nid = ::pool_rel2id( pool_r, nid, arch_r.id(), REL_ARCH, /*create*/true ); + } + + // Extend 'op edition', if provided + if ( op_r != Rel::ANY && ed_r != Edition::noedition ) + { + nid = ::pool_rel2id( pool_r, nid, ed_r.id(), op_r.bits(), /*create*/true ); + } + + return nid; + } + + /** Build \ref Capability from data, just parsing name for '[.arch]' and detect + * 'kind srcpackage' (will be mapped to arch \c src). + */ + sat::detail::IdType relFromStr( sat::detail::CPool * pool_r, + const std::string & name_r, Rel op_r, const Edition & ed_r, + const ResKind & kind_r ) + { + static const Arch srcArch( IdString(ARCH_SRC).asString() ); + static const Arch nosrcArch( IdString(ARCH_NOSRC).asString() ); + static const std::string srcKindPrefix( ResKind::srcpackage.asString() + ':' ); + + // check for an embedded 'srcpackage:foo' to be mapped to 'foo' and 'ResKind::srcpackage'. + if ( kind_r.empty() && str::hasPrefix( name_r, srcKindPrefix ) ) + { + return relFromStr( pool_r, Arch_empty, name_r.substr( srcKindPrefix.size() ), op_r, ed_r, ResKind::srcpackage ); + } + + Arch arch( Arch_empty ); + std::string name( name_r ); + + std::string::size_type asep( name_r.rfind( '.' ) ); + if ( asep != std::string::npos ) + { + Arch ext( name_r.substr( asep+1 ) ); + if ( ext.isBuiltIn() || ext == srcArch || ext == nosrcArch ) + { + arch = ext; + name.erase( asep ); + } + } + + return relFromStr( pool_r, arch, name, op_r, ed_r, kind_r ); + } + + /** Full parse from string, unless Capability::PARSED. + */ + sat::detail::IdType relFromStr( sat::detail::CPool * pool_r, + const Arch & arch_r, // parse from name if empty + const std::string & str_r, const ResKind & kind_r, + Capability::CtorFlag flag_r ) + { + std::string name( str_r ); + Rel op; + Edition ed; + if ( flag_r == Capability::UNPARSED ) + { + splitOpEdition( name, op, ed ); + } + + if ( arch_r.empty() ) + return relFromStr( pool_r, name, op, ed, kind_r ); // parses for name[.arch] + // else + return relFromStr( pool_r, arch_r, name, op, ed, kind_r ); + } + + /** Parse richdeps from string, otherwise fall back to the traditional parser. */ + sat::detail::IdType richOrRelFromStr( sat::detail::CPool * pool_r, const std::string & str_r, const ResKind & prefix_r, Capability::CtorFlag flag_r ) + { + if ( str_r[0] == '(' ) { + sat::detail::IdType res { sat::detail::PoolMember::myPool().parserpmrichdep( str_r.c_str() ) }; + if ( res ) return res; + // else: no richdep, so fall back to the ordinary parser which in + // case of doubt turns the string into a NAMED cap. + } + return relFromStr( pool_r, Arch_empty, str_r, prefix_r, flag_r ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + const Capability Capability::Null( STRID_NULL ); + const Capability Capability::Empty( STRID_EMPTY ); + + ///////////////////////////////////////////////////////////////// + + Capability::Capability( const char * str_r, const ResKind & prefix_r, CtorFlag flag_r ) + : _id( richOrRelFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) ) + {} + + Capability::Capability( const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r ) + : _id( richOrRelFromStr( myPool().getPool(), str_r, prefix_r, flag_r ) ) + {} + + Capability::Capability( const Arch & arch_r, const char * str_r, const ResKind & prefix_r, CtorFlag flag_r ) + : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) ) + {} + + Capability::Capability( const Arch & arch_r, const std::string & str_r, const ResKind & prefix_r, CtorFlag flag_r ) + : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) ) + {} + + Capability::Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) ) + {} + + Capability::Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), Arch_empty, str_r, prefix_r, flag_r ) ) + {} + + Capability::Capability( const Arch & arch_r, const char * str_r, CtorFlag flag_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) ) + {} + + Capability::Capability( const Arch & arch_r, const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), arch_r, str_r, prefix_r, flag_r ) ) + {} + + /////////////////////////////////////////////////////////////////// + // Ctor from . + /////////////////////////////////////////////////////////////////// + + Capability::Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), name_r, Rel(op_r), Edition(ed_r), prefix_r ) ) + {} + Capability::Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), name_r, op_r, Edition(ed_r), prefix_r ) ) + {} + Capability::Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), name_r, op_r, ed_r, prefix_r ) ) + {} + + /////////////////////////////////////////////////////////////////// + // Ctor from . + /////////////////////////////////////////////////////////////////// + + Capability::Capability( const std::string & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, Rel(op_r), Edition(ed_r), prefix_r ) ) + {} + Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, Edition(ed_r), prefix_r ) ) + {} + Capability::Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), Arch(arch_r), name_r, op_r, ed_r, prefix_r ) ) + {} + Capability::Capability( const Arch & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), arch_r, name_r, Rel(op_r), Edition(ed_r), prefix_r ) ) + {} + Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, Edition(ed_r), prefix_r ) ) + {} + Capability::Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r ) + : _id( relFromStr( myPool().getPool(), arch_r, name_r, op_r, ed_r, prefix_r ) ) + {} + + /////////////////////////////////////////////////////////////////// + // Ctor creating a namespace: capability. + /////////////////////////////////////////////////////////////////// + + Capability::Capability( ResolverNamespace namespace_r, IdString value_r ) + : _id( ::pool_rel2id( myPool().getPool(), asIdString(namespace_r).id(), (value_r.empty() ? STRID_NULL : value_r.id() ), REL_NAMESPACE, /*create*/true ) ) + {} + + /////////////////////////////////////////////////////////////////// + // https://rpm-software-management.github.io/rpm/manual/boolean_dependencies.html + namespace + { + inline const char * opstr( int op_r ) + { + switch ( op_r ) + { + case REL_GT: return " > "; + case REL_EQ: return " = "; + case REL_LT: return " < "; + case REL_GT|REL_EQ: return " >= "; + case REL_LT|REL_EQ: return " <= "; + case REL_GT|REL_LT: return " != "; + case REL_GT|REL_LT|REL_EQ: return " <=> "; + case REL_AND: return " and "; + case REL_OR: return " or "; + case REL_COND: return " if "; + case REL_UNLESS: return " unless "; + case REL_ELSE: return " else "; + case REL_WITH: return " with "; + case REL_WITHOUT: return " without "; + } + return "UNKNOWNCAPREL"; + } + + inline bool isBoolOp( int op_r ) + { + switch ( op_r ) { + case REL_AND: + case REL_OR: + case REL_COND: + case REL_UNLESS: + case REL_ELSE: + case REL_WITH: + case REL_WITHOUT: + return true; + } + return false; + } + + inline bool needsBrace( int op_r, int parop_r ) + { + return ( isBoolOp( parop_r ) || parop_r == 0 ) && isBoolOp( op_r ) + && ( parop_r != op_r || op_r == REL_COND || op_r == REL_UNLESS || op_r == REL_ELSE ) + && not ( ( parop_r == REL_COND || parop_r == REL_UNLESS ) && op_r == REL_ELSE ); + } + + void cap2strHelper( std::string & outs_r, sat::detail::CPool * pool_r, sat::detail::IdType id_r, int parop_r ) + { + if ( ISRELDEP(id_r) ) { + ::Reldep * rd = GETRELDEP( pool_r, id_r ); + int op = rd->flags; + + if ( op == CapDetail::CAP_ARCH ) { + if ( rd->evr == ARCH_SRC || rd->evr == ARCH_NOSRC ) { + // map arch .{src,nosrc} to kind srcpackage + outs_r += ResKind::srcpackage.c_str(); + outs_r += ":"; + outs_r += IdString(rd->name).c_str(); + return; + } + cap2strHelper( outs_r, pool_r, rd->name, op ); + outs_r += "."; + cap2strHelper( outs_r, pool_r, rd->evr, op ); + return; + } + + if ( op == CapDetail::CAP_NAMESPACE ) { + cap2strHelper( outs_r, pool_r, rd->name, op ); + outs_r += "("; + cap2strHelper( outs_r, pool_r, rd->evr, op ); + outs_r += ")"; + return; + } + + if ( op == REL_FILECONFLICT ) + { + cap2strHelper( outs_r, pool_r, rd->name, op ); + return; + } + + if ( needsBrace( op, parop_r ) ) { + outs_r += "("; + cap2strHelper( outs_r, pool_r, rd->name, op ); + outs_r += opstr( op ); + cap2strHelper( outs_r, pool_r, rd->evr, op ); + outs_r += ")"; + return; + } + + cap2strHelper( outs_r, pool_r, rd->name, op ); + outs_r += opstr( op ); + cap2strHelper( outs_r, pool_r, rd->evr, op ); + } + else + outs_r += IdString(id_r).c_str(); + } + } // namespace + /////////////////////////////////////////////////////////////////// + + const char * Capability::c_str() const + { + if ( not id() ) return ""; + if ( not ISRELDEP(id()) ) return IdString(id()).c_str(); + + static TempStrings<5> tempstrs; // Round Robin buffer to prolong the lifetime of the returned char* + + std::string & outs { tempstrs.getNext() }; + cap2strHelper( outs, myPool().getPool(), id(), 0 ); + return outs.c_str(); + } + + CapMatch Capability::_doMatch( sat::detail::IdType lhs, sat::detail::IdType rhs ) + { + if ( lhs == rhs ) + return CapMatch::yes; + + CapDetail l( lhs ); + CapDetail r( rhs ); + + switch ( l.kind() ) + { + case CapDetail::NOCAP: + return( r.kind() == CapDetail::NOCAP ); // NOCAP matches NOCAP only + break; + case CapDetail::EXPRESSION: + return CapMatch::irrelevant; + break; + case CapDetail::NAMED: + case CapDetail::VERSIONED: + break; + } + + switch ( r.kind() ) + { + case CapDetail::NOCAP: + return CapMatch::no; // match case handled above + break; + case CapDetail::EXPRESSION: + return CapMatch::irrelevant; + break; + case CapDetail::NAMED: + case CapDetail::VERSIONED: + break; + } + // comparing two simple caps: + if ( l.name() != r.name() ) + return CapMatch::no; + + // if both are arch restricted they must match + if ( l.arch() != r.arch() + && ! ( l.arch().empty() || r.arch().empty() ) ) + return CapMatch::no; + + // isNamed matches ANY edition: + if ( l.isNamed() || r.isNamed() ) + return CapMatch::yes; + + // both are versioned: + return overlaps( Edition::MatchRange( l.op(), l.ed() ), + Edition::MatchRange( r.op(), r.ed() ) ); + } + + bool Capability::isInterestingFileSpec( const char * name_r ) + { + static str::smatch what; + static const str::regex filenameRegex( + "/(s?bin|lib(64)?|etc)/|^/usr/(games/|share/(dict/words|magic\\.mime)$)|^/opt/gnome/games/", + str::regex::nosubs ); + + return str::regex_match( name_r, what, filenameRegex ); + } + + Capability Capability::guessPackageSpec( const std::string & str_r, bool & rewrote_r ) + { + Capability cap( str_r ); + CapDetail detail( cap.detail() ); + + // str_r might be the form "libzypp-1.2.3-4.5(.arch)' + // correctly parsed as name capability by the ctor. + // TODO: Think about allowing glob char in name - for now don't process + if ( detail.isNamed() && !::strpbrk( detail.name().c_str(), "*?[{" ) + && ::strrchr( detail.name().c_str(), '-' ) && sat::WhatProvides( cap ).empty() ) + { + Arch origArch( detail.arch() ); // to support a trailing .arch + + std::string guess( detail.name().asString() ); + std::string::size_type pos( guess.rfind( '-' ) ); + guess[pos] = '='; + + Capability guesscap( origArch, guess ); + detail = guesscap.detail(); + + ResPool pool( ResPool::instance() ); + // require name part matching a pool items name (not just provides!) + if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) ) + { + rewrote_r = true; + return guesscap; + } + + // try the one but last '-' + if ( pos ) + { + guess[pos] = '-'; + if ( (pos = guess.rfind( '-', pos-1 )) != std::string::npos ) + { + guess[pos] = '='; + + guesscap = Capability( origArch, guess ); + detail = guesscap.detail(); + + // require name part matching a pool items name (not just provides!) + if ( pool.byIdentBegin( detail.name() ) != pool.byIdentEnd( detail.name() ) ) + { + rewrote_r = true; + return guesscap; + } + } + } + } + + rewrote_r = false; + return cap; + } + + Capability Capability::guessPackageSpec( const std::string & str_r ) + { + bool dummy = false; + return guessPackageSpec( str_r, dummy ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Capability & obj ) + { + return str << obj.c_str(); + } + + std::ostream & dumpOn( std::ostream & str, const Capability & obj ) + { + return str << ( obj ? ::pool_dep2str( sat::Pool::instance().get(), obj.id() ) : "" ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CapDetail + // + /////////////////////////////////////////////////////////////////// + + void CapDetail::_init() + { + // : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 ) + + if ( _lhs == sat::detail::emptyId || _lhs == sat::detail::noId ) + return; // NOCAP + + if ( ! ISRELDEP(_lhs) ) + { + // this is name without arch! + _kind = NAMED; + return; + } + + ::Reldep * rd = GETRELDEP( myPool().getPool(), _lhs ); + _lhs = rd->name; + _rhs = rd->evr; + _flag = rd->flags; + + if ( Rel::isRel( _flag ) ) + { + _kind = VERSIONED; + // Check for name.arch... + if ( ! ISRELDEP(_lhs) ) + return; // this is name without arch! + rd = GETRELDEP( myPool().getPool(), _lhs ); + if ( rd->flags != CAP_ARCH ) + return; // this is not name.arch + // This is name.arch: + _lhs = rd->name; + _archIfSimple = rd->evr; + } + else if ( rd->flags == CAP_ARCH ) + { + _kind = NAMED; + // This is name.arch: + _lhs = rd->name; + _archIfSimple = rd->evr; + } + else + { + _kind = EXPRESSION; + return; + } + // map back libsolvs pseudo arch 'src' to kind srcpackage + if ( _archIfSimple == ARCH_SRC || _archIfSimple == ARCH_NOSRC ) + { + _lhs = IdString( (ResKind::srcpackage.asString() + ":" + IdString(_lhs).c_str()).c_str() ).id(); + _archIfSimple = 0; + } + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const CapDetail & obj ) + { + static const char archsep = '.'; + switch ( obj.kind() ) + { + case CapDetail::NOCAP: + return str << ""; + break; + + case CapDetail::NAMED: + str << obj.name(); + if ( obj.hasArch() ) + str << archsep << obj.arch(); + return str; + break; + + case CapDetail::VERSIONED: + str << obj.name(); + if ( obj.hasArch() ) + str << archsep << obj.arch(); + return str << " " << obj.op() << " " << obj.ed(); + break; + + case CapDetail::EXPRESSION: + { + std::string outs; + auto pool = sat::Pool::instance().get(); + auto op = obj.capRel(); + if ( obj.capRel() == CapDetail::CAP_NAMESPACE ) { + cap2strHelper( outs, pool, obj.lhs().id(), op ); + outs += "("; + cap2strHelper( outs, pool, obj.rhs().id(), op ); + outs += ")"; + } + else { + outs += "("; + cap2strHelper( outs, pool, obj.lhs().id(), op ); + outs += opstr( op ); + cap2strHelper( outs, pool, obj.rhs().id(), op ); + outs += ")"; + } + return str << outs; + } + break; + } + return str << ""; + } + + std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj ) + { + switch ( obj ) + { + case CapDetail::NOCAP: return str << "NoCap"; break; + case CapDetail::NAMED: return str << "NamedCap"; break; + case CapDetail::VERSIONED: return str << "VersionedCap"; break; + case CapDetail::EXPRESSION: return str << "CapExpression"; break; + } + return str << "UnknownCap"; + } + + std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj ) + { + switch ( obj ) + { + case CapDetail::REL_NONE: return str << "NoCapRel"; break; + case CapDetail::CAP_AND: return str << "and"; break; // & + case CapDetail::CAP_OR: return str << "or"; break; // | + case CapDetail::CAP_COND: return str << "if"; break; + case CapDetail::CAP_UNLESS: return str << "unless"; break; + case CapDetail::CAP_ELSE: return str << "else"; break; + case CapDetail::CAP_WITH: return str << "with"; break; // + + case CapDetail::CAP_WITHOUT: return str << "without"; break; // - + case CapDetail::CAP_NAMESPACE: return str << "NAMESPACE"; break; + case CapDetail::CAP_ARCH: return str << "ARCH"; break; + } + return str << "UnknownCapRel("+str::numstring(obj)+")"; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Capability.h b/zypp/Capability.h new file mode 100644 index 0000000..2544565 --- /dev/null +++ b/zypp/Capability.h @@ -0,0 +1,405 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Capability.h + * +*/ +#ifndef ZYPP_CAPABILITY_H +#define ZYPP_CAPABILITY_H + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class Capability; + class CapDetail; + class Arch; + + using CapabilitySet = std::unordered_set; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Capability + // + /** A sat capability. + * + * A Capability: "name[.arch] [op edition]" or a \c richdep[1] + * + * If a certain \ref ResKind is specified upon construction, the + * capabilities name part is prefixed, unless it already contains a + * well known kind spec. If no \ref ResKind is specified, it's assumed + * you refer to a package or the name is already prefixed: + * \code + * Capability( "foo" ) ==> 'foo' + * Capability( "foo", ResKind::package ) ==> 'foo' + * Capability( "foo", ResKind::pattern ) ==> 'pattern:foo' + * Capability( "pattern:foo" ) ==> 'pattern:foo' + * // in doubt an explicit name prefix wins: + * Capability( "pattern:foo", ResKind::package ) ==> 'pattern:foo' + * Capability( "package:foo", ResKind::pattern ) ==> 'foo' + * \endcode + * + * [1] https://rpm-software-management.github.io/rpm/manual/boolean_dependencies.html + * \see \ref CapDetail + */ + class ZYPP_API Capability: protected sat::detail::PoolMember + { + public: + enum CtorFlag { PARSED, UNPARSED }; + + public: + /** Default ctor, \ref Empty capability. */ + Capability() : _id( sat::detail::emptyId ) {} + + /** Ctor from id. */ + explicit Capability( sat::detail::IdType id_r ) : _id( id_r ) {} + + /** \name Ctors parsing a Capability: "name[.arch] [op edition]" or ( arch, "name [op edition]") + */ + //@{ + /** Ctor from string. + * \a str_r is parsed to see if it forms a richdep. Subsequent arguments are meaningless + * in that case. If it's no richdep we continue as described below. + * + * \a str_r is parsed to check whether it contains an [op edition] part, + * unless the \ref PARSED flag is passed to the ctor. In that case "name[.arch]" + * is assumed. + * + * \ref Capability legacy is to parse everything unknown into a \ref NAMED + * cap. This is often used to turn user supplied search strings with an optional + * edition range restriction into \ref PoolQuery arguments ('/gcc[0-9]+/ >= 8'). + */ + explicit Capability( const char * str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED ); + /** \overload */ + explicit Capability( const std::string & str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED ); + /** \overload Explicitly specify the \c arch. */ + Capability( const Arch & arch_r, const char * str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED ); + /** \overload Explicitly specify the \c arch. */ + Capability( const Arch & arch_r, const std::string & str_r, const ResKind & prefix_r = ResKind(), CtorFlag flag_r = UNPARSED ); + + /** \overload Convenience for parsed (name only, no "[op edition]) packages: Capability( "glibc", PARSED ); */ + Capability( const char * str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() ); + /** \overload Explicitly specify the \c arch. */ + Capability( const Arch & arch_r, const char * str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const Arch & arch_r, const std::string & str_r, CtorFlag flag_r, const ResKind & prefix_r = ResKind() ); + //@} + + + /** \name Ctors parsing a broken down Capability: ( "name[.arch]", op, edition ) + */ + //@{ + /** Ctor from name[.arch] op edition. */ + Capability( const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() ); + //@} + + /** \name Ctors taking a broken down Capability: ( arch, name, op, edition ) + */ + //@{ + /** Ctor from arch name op edition. */ + Capability( const std::string & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const std::string & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const Arch & arch_r, const std::string & name_r, const std::string & op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const std::string & ed_r, const ResKind & prefix_r = ResKind() ); + /** \overload */ + Capability( const Arch & arch_r, const std::string & name_r, Rel op_r, const Edition & ed_r, const ResKind & prefix_r = ResKind() ); + //@} + + /** \name Ctor creating a namespace: capability. + * An empty \a value_r (std::string or IdString) will also be mapped to IdString::Null, + * creating a namespace: capability which in most contexts matches all members of this namespace. + */ + //@{ + Capability( ResolverNamespace namespace_r, IdString value_r = IdString::Null ); + Capability( ResolverNamespace namespace_r, const char * value_r ) : Capability( namespace_r, IdString(value_r) ) {} + Capability( ResolverNamespace namespace_r, const std::string & value_r ) : Capability( namespace_r, IdString(value_r) ) {} + //@} + public: + /** No or Null \ref Capability ( Id \c 0 ). */ + static const Capability Null; + + /** Empty Capability. */ + static const Capability Empty; + + public: + /** Evaluate in a boolean context ( ! empty() ). */ + explicit operator bool() const + { return ! empty(); } + + /** Whether the \ref Capability is empty. + * This is true for \ref Null and \ref Empty. + */ + bool empty() const + { return( _id == sat::detail::emptyId || _id == sat::detail::noId ); } + + public: + /** Conversion to const char * */ + const char * c_str() const; + + /** \overload */ + std::string asString() const + { return c_str(); } + + public: + /** Helper providing more detailed information about a \ref Capability. */ + CapDetail detail() const; + + public: + /** \name Match two simple capabilities. + * + * Two simple capabilities match if they have the same \c name + * and their \c edition ranges overlap. Where no edition matches + * ANY edition. \see \ref Edition::match. + * + * If a capability expression is involved, \ref matches returns + * \ref CapMatch::irrelevant. + */ + //@{ + static CapMatch matches( const Capability & lhs, const Capability & rhs ) { return _doMatch( lhs.id(), rhs.id() ); } + static CapMatch matches( const Capability & lhs, const IdString & rhs ) { return _doMatch( lhs.id(), rhs.id() ); } + static CapMatch matches( const Capability & lhs, const std::string & rhs ) { return _doMatch( lhs.id(), Capability(rhs).id() ); } + static CapMatch matches( const Capability & lhs, const char * rhs ) { return _doMatch( lhs.id(), Capability(rhs).id() );} + + static CapMatch matches( const IdString & lhs, const Capability & rhs ) { return _doMatch( lhs.id(), rhs.id() ); } + static CapMatch matches( const IdString & lhs, const IdString & rhs ) { return _doMatch( lhs.id(), rhs.id() ); } + static CapMatch matches( const IdString & lhs, const std::string & rhs ) { return _doMatch( lhs.id(), Capability(rhs).id() ); } + static CapMatch matches( const IdString & lhs, const char * rhs ) { return _doMatch( lhs.id(), Capability(rhs).id() ); } + + static CapMatch matches( const std::string & lhs, const Capability & rhs ) { return _doMatch( Capability(lhs).id(), rhs.id() );} + static CapMatch matches( const std::string & lhs, const IdString & rhs ) { return _doMatch( Capability(lhs).id(), rhs.id() ); } + static CapMatch matches( const std::string & lhs, const std::string & rhs ) { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); } + static CapMatch matches( const std::string & lhs, const char * rhs ) { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); } + + static CapMatch matches( const char * lhs, const Capability & rhs ) { return _doMatch( Capability(lhs).id(), rhs.id() );} + static CapMatch matches( const char * lhs, const IdString & rhs ) { return _doMatch( Capability(lhs).id(), rhs.id() ); } + static CapMatch matches( const char * lhs, const std::string & rhs ) { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); } + static CapMatch matches( const char * lhs, const char * rhs ) { return _doMatch( Capability(lhs).id(), Capability(rhs).id() ); } + + CapMatch matches( const Capability & rhs ) const { return _doMatch( id(), rhs.id() ); } + CapMatch matches( const IdString & rhs ) const { return _doMatch( id(), rhs.id() ); } + CapMatch matches( const std::string & rhs ) const { return _doMatch( id(), Capability(rhs).id() ); } + CapMatch matches( const char * rhs ) const { return _doMatch( id(), Capability(rhs).id() ); } + //@} + + /** \ref matches functor. + */ + struct Matches + { + CapMatch operator()( const Capability & lhs, const Capability & rhs ) const + { return Capability::matches( lhs, rhs ); } + }; + + public: + /** Test for a filename that is likely being REQUIRED. + * Files below \c /bin , \c /sbin , \c /lib etc. Scanning a + * packages filelist, an \e interesting filename might be worth + * being remembered in PROVIDES. + */ + static bool isInterestingFileSpec( const IdString & name_r ) { return isInterestingFileSpec( name_r.c_str() ); } + static bool isInterestingFileSpec( const std::string & name_r ) { return isInterestingFileSpec( name_r.c_str() ); } + static bool isInterestingFileSpec( const char * name_r ); + + /** \ref Capability parser also guessing \c "libzypp-1.2.3-4.5.x86_64" formats. + * + * The argument might be in the form \c "libzypp-devel-1.2.3.x86_64". + * Passed to the Capability ctor, this would correctly be parsed as name + * capability, because actually the edition part had to be separated by a + * \c '=', and the architecture had to be appended to the name. + * So this is how it actually had to look like: \c "libzypp-devel.x86_64=1.2.3" + * + * Obviously we have to guess if, and where to split name and edition. In + * fact \c "devel" could also be the version and \c "1.2.3" would be the + * release then. + * + * Assuming this Capability should be provided by some package in + * the \ref ResPool, we check this. If unprovided, we substitute the last, + * (or one but last) \c '-' by a \c '='. If the name part (without version) + * of the resulting Capability matches a package name (not provides!) in + * the \ref ResPool, this Capability is returned. + * + * Otherwise we return the Capability originally created from + * \a str_r. + * + * \note: As this method will access the global pool, the returned + * result depends on the pools content. + */ + static Capability guessPackageSpec( const std::string & str_r ); + /** \overload Taking an additional bool indicating whether \c str_r made + * a valid \ref Capability (\c true) or the result was was guessed by + * rewiting a \c '-' to \c '='. (\c false). + */ + static Capability guessPackageSpec( const std::string & str_r, bool & rewrote_r ); + + public: + /** Expert backdoor. */ + sat::detail::IdType id() const + { return _id; } + private: + /** Match two Capabilities */ + static CapMatch _doMatch( sat::detail::IdType lhs, sat::detail::IdType rhs ); + private: + sat::detail::IdType _id; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Capability Stream output */ + std::ostream & operator<<( std::ostream & str, const Capability & obj ) ZYPP_API; + + /** \relates Capability Detailed stream output */ + std::ostream & dumpOn( std::ostream & str, const Capability & obj ) ZYPP_API; + + /** \relates Capability */ + inline bool operator==( const Capability & lhs, const Capability & rhs ) + { return lhs.id() == rhs.id(); } + + /** \relates Capability */ + inline bool operator!=( const Capability & lhs, const Capability & rhs ) + { return lhs.id() != rhs.id(); } + + /** \relates Capability Arbitrary order. */ + inline bool operator<( const Capability & lhs, const Capability & rhs ) + { return lhs.id() < rhs.id(); } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CapDetail + // + /** Helper providing more detailed information about a \ref Capability. + * + * Capabilities are classified to be either \c SIMPLE: + * \code + * name[.arch] [op edition] + * with op := <|<=|=|>=|>|!= + * \endcode + * or formed by some \c EXPRESSION: + * \code + * ( left_cap op right_cap ) + * with op := and|or|if|unless|else|with|without + * \endcode + * + */ + class ZYPP_API CapDetail: protected sat::detail::PoolMember + { + public: + enum Kind + { + NOCAP = 0x00, + NAMED = 0x01, + VERSIONED = 0x02, + EXPRESSION = 0x04 + }; + + /** Enum values corresponding with libsolv defines. + * \note MPL check in PoolImpl.cc + */ + enum CapRel + { + REL_NONE = 0, ///< Not an expression + CAP_AND = 16, ///< \c and + CAP_OR = 17, ///< \c or + + CAP_COND = 22, ///< \c if + CAP_UNLESS = 29, ///< \c unless + CAP_ELSE = 26, ///< \c else + + CAP_WITH = 18, ///< \c with + CAP_WITHOUT = 28, ///< \c without + + CAP_NAMESPACE = 19, ///< + CAP_ARCH = 20, ///< Used internally + }; + + public: + CapDetail() + : _kind( NOCAP ), _lhs( 0 ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 ) + {} + explicit CapDetail( const Capability & cap_r ) + : _kind( NOCAP ), _lhs( cap_r.id() ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 ) + { _init(); } + explicit CapDetail( sat::detail::IdType id_r ) + : _kind( NOCAP ), _lhs( id_r ), _rhs( 0 ), _flag( 0 ), _archIfSimple( 0 ) + { _init(); } + + public: + Kind kind() const { return _kind; } + bool isNull() const { return _kind == NOCAP; } + bool isNamed() const { return _kind == NAMED; } + bool isVersioned() const { return _kind == VERSIONED; } + bool isSimple() const { return _kind & (NAMED|VERSIONED); } + bool isExpression() const { return _kind == EXPRESSION; } + + /** \name Is simple: name[.arch] [op edition] */ + //@{ + bool hasArch() const { return _archIfSimple; } + IdString arch() const { return _archIfSimple ? IdString( _archIfSimple ) : IdString(); } + IdString name() const { return isSimple() ? IdString( _lhs ) : IdString(); } + Rel op() const { return isVersioned() ? Rel( _flag ) : isSimple() ? Rel::ANY : Rel::NONE; } + Edition ed() const { return isVersioned() ? Edition( _rhs ) : Edition(); } + //@} + + /** \name Is expression cap op cap */ + //@{ + Capability lhs() const { return isExpression() ? Capability( _lhs ) : Capability::Null; } + CapRel capRel() const { return isExpression() ? CapRel(_flag) : REL_NONE; } + Capability rhs() const { return isExpression() ? Capability( _rhs ) : Capability::Null; } + //@} + + private: + void _init(); + private: + Kind _kind; + sat::detail::IdType _lhs; + sat::detail::IdType _rhs; + unsigned _flag; + sat::detail::IdType _archIfSimple; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CapDetail Stream output */ + std::ostream & operator<<( std::ostream & str, const CapDetail & obj ) ZYPP_API; + + /** \relates CapDetail Stream output */ + std::ostream & operator<<( std::ostream & str, CapDetail::Kind obj ) ZYPP_API; + + /** \relates CapDetail Stream output */ + std::ostream & operator<<( std::ostream & str, CapDetail::CapRel obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + + inline CapDetail Capability::detail() const { return CapDetail( _id ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +ZYPP_DEFINE_ID_HASHABLE( ::zypp::Capability ); + +#endif // ZYPP_CAPABILITY_H diff --git a/zypp/Changelog.cc b/zypp/Changelog.cc new file mode 100644 index 0000000..5f35e03 --- /dev/null +++ b/zypp/Changelog.cc @@ -0,0 +1,32 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Changelog.cc + * +*/ +#include +#include + +#include + +using std::endl; + +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** \relates ChangelogEntry */ + std::ostream & operator<<( std::ostream & out, const ChangelogEntry & obj ) + { + out << obj.date() << " " << obj.author() << endl << obj.text() << endl; + return out; + } + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Changelog.h b/zypp/Changelog.h new file mode 100644 index 0000000..3e319b3 --- /dev/null +++ b/zypp/Changelog.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Changelog.h + * +*/ +#ifndef ZYPP_CHANGELOG_H +#define ZYPP_CHANGELOG_H + +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ChangelogEntry + // + /** Single entry in a change log + */ + class ChangelogEntry + { + public: + /** Default ctor */ + ChangelogEntry( const Date & d, + std::string a, + std::string t ) + : _date( d ), _author(std::move( a )), _text(std::move( t )) + {}; + /** Dtor */ + ~ChangelogEntry() + {} + Date date() const { return _date; } + std::string author() const { return _author; } + std::string text() const { return _text; } + + private: + Date _date; + std::string _author; + std::string _text; + }; + + /** List of ChangelogEntry. */ + using Changelog = std::list; + + /** \relates ChangelogEntry */ + std::ostream & operator<<( std::ostream & out, const ChangelogEntry & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif // ZYPP_CHANGELOG_H diff --git a/zypp/CheckSum.cc b/zypp/CheckSum.cc new file mode 100644 index 0000000..97b0507 --- /dev/null +++ b/zypp/CheckSum.cc @@ -0,0 +1,11 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CheckSum.cc + * +*/ diff --git a/zypp/CheckSum.h b/zypp/CheckSum.h new file mode 100644 index 0000000..d431c59 --- /dev/null +++ b/zypp/CheckSum.h @@ -0,0 +1,17 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CheckSum.h + * +*/ +#ifndef ZYPP_CHECKSUM_H +#define ZYPP_CHECKSUM_H + +#include + +#endif // ZYPP_CHECKSUM_H diff --git a/zypp/ContentType.h b/zypp/ContentType.h new file mode 100644 index 0000000..f892b07 --- /dev/null +++ b/zypp/ContentType.h @@ -0,0 +1,142 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ContentType.h + */ +#ifndef ZYPP_CONTENTTYPE_H +#define ZYPP_CONTENTTYPE_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class ContentType + /// \brief Mime type like \c 'type/subtype' classification of content + /// + /// Used e.g. in \ref callback::UserData to describe the kind of + /// user data passed as \c void* to a callback. Neither type nor + /// subtype may contain a '/'. + /////////////////////////////////////////////////////////////////// + class ContentType + { + public: + /** Default ctor: empty */ + ContentType() + {} + + /** Ctor taking "type[/subtype]" + * \throws std::invalid_argument if string is malformed + */ + explicit ContentType( std::string type_r ) + { + std::string::size_type pos = type_r.find( '/' ); + if ( pos != std::string::npos ) + { + testAndSet( _subtype, type_r.substr( pos+1 ) ); + type_r.erase( pos ); + } + testAndSet( _type, std::move(type_r) ); + } + + /** Ctor taking type and subtype + * \throws std::invalid_argument if string is malformed + */ + ContentType( std::string type_r, std::string subtype_r ) + { + testAndSet( _type, std::move(type_r) ); + testAndSet( _subtype, std::move(subtype_r) ); + } + + public: + /** Get type */ + const std::string & type() const + { return _type; } + + /** Set type + * \throws std::invalid_argument if string is malformed + */ + void type( std::string type_r ) + { _type = std::move(type_r); } + + /** Get subtype */ + const std::string & subtype() const + { return _subtype; } + + /** Set subtype + * \throws std::invalid_argument if string is malformed + */ + void subtype( std::string subtype_r ) + { _subtype = std::move(subtype_r); } + + public: + /** Whether type and subtype are empty */ + bool empty() const + { return emptyType() && emptySubtype(); } + /** Whether type is empty */ + bool emptyType() const + { return _type.empty(); } + /** Whether subtype is empty */ + bool emptySubtype() const + { return _subtype.empty(); } + + /** Validate object in a boolean context: !empty */ + explicit operator bool () const + { return !empty(); } + + /** String representation "type[/subtype]" */ + std::string asString() const + { std::string ret( type() ); if ( ! emptySubtype() ) { ret += "/"; ret += subtype(); } return ret; } + + private: + void testAndSet( std::string & var_r, std::string val_r ) + { + if ( val_r.find_first_of( "/ \t\r\n" ) != std::string::npos ) + throw std::invalid_argument( "ContentType: illegal char in '" + val_r + "'" ); + var_r = std::move(val_r); + } + private: + std::string _type; + std::string _subtype; + }; + + /** \relates ContentType Stream output */ + inline std::ostream & operator<<( std::ostream & str, const ContentType & obj ) + { return str << obj.asString(); } + + /** \relates ContentType */ + inline bool operator==( const ContentType & lhs, const ContentType & rhs ) + { return lhs.type() == rhs.type() && lhs.subtype() == rhs.subtype(); } + + /** \relates ContentType */ + inline bool operator!=( const ContentType & lhs, const ContentType & rhs ) + { return !( lhs == rhs ); } + + /** \relates ContentType */ + inline bool operator<( const ContentType & lhs, const ContentType & rhs ) + { int cmp = lhs.type().compare( rhs.type() ); return cmp < 0 || ( cmp == 0 && lhs.subtype() < rhs.subtype() ); } + + /** \relates ContentType */ + inline bool operator<=( const ContentType & lhs, const ContentType & rhs ) + { return lhs < rhs || lhs == rhs; } + + /** \relates ContentType */ + inline bool operator>( const ContentType & lhs, const ContentType & rhs ) + { return !( lhs <= rhs ); } + + /** \relates ContentType */ + inline bool operator>=( const ContentType & lhs, const ContentType & rhs ) + { return !( lhs < rhs ); } + + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CONTENTTYPE_H diff --git a/zypp/CountryCode.cc b/zypp/CountryCode.cc new file mode 100644 index 0000000..90c6377 --- /dev/null +++ b/zypp/CountryCode.cc @@ -0,0 +1,418 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CountryCode.cc + * +*/ +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + + /** Wrap static codemap data. */ + struct CodeMaps // singleton + { + /** The singleton */ + static CodeMaps & instance() + { + static CodeMaps _instance; + return _instance; + } + + /** Lookup (translated) name for \a index_r.*/ + std::string name( IdString index_r ) + { + Link link( getIndex( index_r ) ); + + std::string ret; + if ( link->second ) + { ret = _(link->second); } + else + { + ret = _("Unknown country: "); + ret += "'"; + ret += index_r.c_str(); + ret += "'"; + } + return ret; + } + + private: + using CodeMap = std::unordered_map; + using Link = CodeMap::const_iterator; + + using IndexMap = std::unordered_map; + + /** Ctor initializes the code maps. + * http://www.iso.org/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html + */ + CodeMaps(); + + /** Return \ref Link for \a index_r, creating it if necessary. */ + Link getIndex( IdString index_r ) + { + auto it = _indexMap.find( index_r ); + return( it != _indexMap.end() + ? it->second + : newIndex( index_r, index_r.asString() ) ); + } + + /** Return the CodeMap Index for \a code_r. */ + Link newIndex( IdString index_r, const std::string & code_r ) + { + Link link = _codeMap.find( code_r ); + if ( link != _codeMap.end() ) + return (_indexMap[index_r] = link); + + // not found: Remember a new code + CodeMap::value_type nval( code_r, nullptr ); + + if ( code_r.size() != 2 ) + WAR << "Malformed CountryCode '" << code_r << "' (expect 2-letter)" << endl; + + std::string ucode( str::toUpper( code_r ) ); + if ( ucode != code_r ) + { + WAR << "Malformed CountryCode '" << code_r << "' (not upper case)" << endl; + // but maybe we're lucky with the lower case code + // and find a language name. + link = _codeMap.find( ucode ); + if ( link != _codeMap.end() ) + { + nval.second = link->second; + } + } + MIL << "Remember CountryCode '" << code_r << "': '" << (nval.second?nval.second:"Unknown country") << "'" << endl; + return (_indexMap[index_r] = _codeMap.insert( nval ).first); + } + + private: + CodeMap _codeMap; + IndexMap _indexMap; + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // class CountryCode + /////////////////////////////////////////////////////////////////// + + const CountryCode CountryCode::noCode; + + CountryCode::CountryCode() + {} + + CountryCode::CountryCode( IdString str_r ) + : _str( str_r ) + {} + + CountryCode::CountryCode( const std::string & str_r ) + : _str( str_r ) + {} + + CountryCode::CountryCode( const char * str_r ) + : _str( str_r ) + {} + + CountryCode::~CountryCode() + {} + + + std::string CountryCode::name() const + { return CodeMaps::instance().name( _str ); } + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + CodeMaps::CodeMaps() + { + // Defined CountryCode constants + _codeMap[""] = N_( "No Code" ); + + struct Init + { + const char *iso3166; + const char *name; + }; + + const Init init[] = { + {"AD", N_( "Andorra" ) }, // :AND:020: + {"AE", N_( "United Arab Emirates" ) }, // :ARE:784: + {"AF", N_( "Afghanistan" ) }, // :AFG:004: + {"AG", N_( "Antigua and Barbuda" ) }, // :ATG:028: + {"AI", N_( "Anguilla" ) }, // :AIA:660: + {"AL", N_( "Albania" ) }, // :ALB:008: + {"AM", N_( "Armenia" ) }, // :ARM:051: + {"AN", N_( "Netherlands Antilles" ) }, // :ANT:530: + {"AO", N_( "Angola" ) }, // :AGO:024: + {"AQ", N_( "Antarctica" ) }, // :ATA:010: + {"AR", N_( "Argentina" ) }, // :ARG:032: + {"AS", N_( "American Samoa" ) }, // :ASM:016: + {"AT", N_( "Austria" ) }, // :AUT:040: + {"AU", N_( "Australia" ) }, // :AUS:036: + {"AW", N_( "Aruba" ) }, // :ABW:533: + {"AX", N_( "Aland Islands" ) }, // :ALA:248: + {"AZ", N_( "Azerbaijan" ) }, // :AZE:031: + {"BA", N_( "Bosnia and Herzegovina" ) }, // :BIH:070: + {"BB", N_( "Barbados" ) }, // :BRB:052: + {"BD", N_( "Bangladesh" ) }, // :BGD:050: + {"BE", N_( "Belgium" ) }, // :BEL:056: + {"BF", N_( "Burkina Faso" ) }, // :BFA:854: + {"BG", N_( "Bulgaria" ) }, // :BGR:100: + {"BH", N_( "Bahrain" ) }, // :BHR:048: + {"BI", N_( "Burundi" ) }, // :BDI:108: + {"BJ", N_( "Benin" ) }, // :BEN:204: + {"BM", N_( "Bermuda" ) }, // :BMU:060: + {"BN", N_( "Brunei Darussalam" ) }, // :BRN:096: + {"BO", N_( "Bolivia" ) }, // :BOL:068: + {"BR", N_( "Brazil" ) }, // :BRA:076: + {"BS", N_( "Bahamas" ) }, // :BHS:044: + {"BT", N_( "Bhutan" ) }, // :BTN:064: + {"BV", N_( "Bouvet Island" ) }, // :BVT:074: + {"BW", N_( "Botswana" ) }, // :BWA:072: + {"BY", N_( "Belarus" ) }, // :BLR:112: + {"BZ", N_( "Belize" ) }, // :BLZ:084: + {"CA", N_( "Canada" ) }, // :CAN:124: + {"CC", N_( "Cocos (Keeling) Islands" ) }, // :CCK:166: + {"CD", N_( "Congo" ) }, // :COD:180: + {"CF", N_( "Central African Republic" ) }, // :CAF:140: + {"CG", N_( "Congo" ) }, // :COG:178: + {"CH", N_( "Switzerland" ) }, // :CHE:756: + {"CI", N_( "Cote D'Ivoire" ) }, // :CIV:384: + {"CK", N_( "Cook Islands" ) }, // :COK:184: + {"CL", N_( "Chile" ) }, // :CHL:152: + {"CM", N_( "Cameroon" ) }, // :CMR:120: + {"CN", N_( "China" ) }, // :CHN:156: + {"CO", N_( "Colombia" ) }, // :COL:170: + {"CR", N_( "Costa Rica" ) }, // :CRI:188: + {"CU", N_( "Cuba" ) }, // :CUB:192: + {"CV", N_( "Cape Verde" ) }, // :CPV:132: + {"CX", N_( "Christmas Island" ) }, // :CXR:162: + {"CY", N_( "Cyprus" ) }, // :CYP:196: + {"CZ", N_( "Czech Republic" ) }, // :CZE:203: + {"DE", N_( "Germany" ) }, // :DEU:276: + {"DJ", N_( "Djibouti" ) }, // :DJI:262: + {"DK", N_( "Denmark" ) }, // :DNK:208: + {"DM", N_( "Dominica" ) }, // :DMA:212: + {"DO", N_( "Dominican Republic" ) }, // :DOM:214: + {"DZ", N_( "Algeria" ) }, // :DZA:012: + {"EC", N_( "Ecuador" ) }, // :ECU:218: + {"EE", N_( "Estonia" ) }, // :EST:233: + {"EG", N_( "Egypt" ) }, // :EGY:818: + {"EH", N_( "Western Sahara" ) }, // :ESH:732: + {"ER", N_( "Eritrea" ) }, // :ERI:232: + {"ES", N_( "Spain" ) }, // :ESP:724: + {"ET", N_( "Ethiopia" ) }, // :ETH:231: + {"FI", N_( "Finland" ) }, // :FIN:246: + {"FJ", N_( "Fiji" ) }, // :FJI:242: + {"FK", N_( "Falkland Islands (Malvinas)" ) }, // :FLK:238: + {"FM", N_( "Federated States of Micronesia" ) }, // :FSM:583: + {"FO", N_( "Faroe Islands" ) }, // :FRO:234: + {"FR", N_( "France" ) }, // :FRA:250: + {"FX", N_( "Metropolitan France" ) }, // :FXX:249: + {"GA", N_( "Gabon" ) }, // :GAB:266: + {"GB", N_( "United Kingdom" ) }, // :GBR:826: + {"GD", N_( "Grenada" ) }, // :GRD:308: + {"GE", N_( "Georgia" ) }, // :GEO:268: + {"GF", N_( "French Guiana" ) }, // :GUF:254: + {"GG", N_( "Guernsey" ) }, + {"GH", N_( "Ghana" ) }, // :GHA:288: + {"GI", N_( "Gibraltar" ) }, // :GIB:292: + {"GL", N_( "Greenland" ) }, // :GRL:304: + {"GM", N_( "Gambia" ) }, // :GMB:270: + {"GN", N_( "Guinea" ) }, // :GIN:324: + {"GP", N_( "Guadeloupe" ) }, // :GLP:312: + {"GQ", N_( "Equatorial Guinea" ) }, // :GNQ:226: + {"GR", N_( "Greece" ) }, // :GRC:300: + {"GS", N_( "South Georgia and the South Sandwich Islands" ) }, // :SGS:239: + {"GT", N_( "Guatemala" ) }, // :GTM:320: + {"GU", N_( "Guam" ) }, // :GUM:316: + {"GW", N_( "Guinea-Bissau" ) }, // :GNB:624: + {"GY", N_( "Guyana" ) }, // :GUY:328: + {"HK", N_( "Hong Kong" ) }, // :HKG:344: + {"HM", N_( "Heard Island and McDonald Islands" ) }, // :HMD:334: + {"HN", N_( "Honduras" ) }, // :HND:340: + {"HR", N_( "Croatia" ) }, // :HRV:191: + {"HT", N_( "Haiti" ) }, // :HTI:332: + {"HU", N_( "Hungary" ) }, // :HUN:348: + {"ID", N_( "Indonesia" ) }, // :IDN:360: + {"IE", N_( "Ireland" ) }, // :IRL:372: + {"IL", N_( "Israel" ) }, // :ISR:376: + {"IM", N_( "Isle of Man" ) }, + {"IN", N_( "India" ) }, // :IND:356: + {"IO", N_( "British Indian Ocean Territory" ) }, // :IOT:086: + {"IQ", N_( "Iraq" ) }, // :IRQ:368: + {"IR", N_( "Iran" ) }, // :IRN:364: + {"IS", N_( "Iceland" ) }, // :ISL:352: + {"IT", N_( "Italy" ) }, // :ITA:380: + {"JE", N_( "Jersey" ) }, + {"JM", N_( "Jamaica" ) }, // :JAM:388: + {"JO", N_( "Jordan" ) }, // :JOR:400: + {"JP", N_( "Japan" ) }, // :JPN:392: + {"KE", N_( "Kenya" ) }, // :KEN:404: + {"KG", N_( "Kyrgyzstan" ) }, // :KGZ:417: + {"KH", N_( "Cambodia" ) }, // :KHM:116: + {"KI", N_( "Kiribati" ) }, // :KIR:296: + {"KM", N_( "Comoros" ) }, // :COM:174: + {"KN", N_( "Saint Kitts and Nevis" ) }, // :KNA:659: + {"KP", N_( "North Korea" ) }, // :PRK:408: + {"KR", N_( "South Korea" ) }, // :KOR:410: + {"KW", N_( "Kuwait" ) }, // :KWT:414: + {"KY", N_( "Cayman Islands" ) }, // :CYM:136: + {"KZ", N_( "Kazakhstan" ) }, // :KAZ:398: + {"LA", N_( "Lao People's Democratic Republic" ) }, // :LAO:418: + {"LB", N_( "Lebanon" ) }, // :LBN:422: + {"LC", N_( "Saint Lucia" ) }, // :LCA:662: + {"LI", N_( "Liechtenstein" ) }, // :LIE:438: + {"LK", N_( "Sri Lanka" ) }, // :LKA:144: + {"LR", N_( "Liberia" ) }, // :LBR:430: + {"LS", N_( "Lesotho" ) }, // :LSO:426: + {"LT", N_( "Lithuania" ) }, // :LTU:440: + {"LU", N_( "Luxembourg" ) }, // :LUX:442: + {"LV", N_( "Latvia" ) }, // :LVA:428: + {"LY", N_( "Libya" ) }, // :LBY:434: + {"MA", N_( "Morocco" ) }, // :MAR:504: + {"MC", N_( "Monaco" ) }, // :MCO:492: + {"MD", N_( "Moldova" ) }, // :MDA:498: + {"ME", N_( "Montenegro" ) }, + {"MF", N_( "Saint Martin" ) }, + {"MG", N_( "Madagascar" ) }, // :MDG:450: + {"MH", N_( "Marshall Islands" ) }, // :MHL:584: + {"MK", N_( "Macedonia" ) }, // :MKD:807: + {"ML", N_( "Mali" ) }, // :MLI:466: + {"MM", N_( "Myanmar" ) }, // :MMR:104: + {"MN", N_( "Mongolia" ) }, // :MNG:496: + {"MO", N_( "Macao" ) }, // :MAC:446: + {"MP", N_( "Northern Mariana Islands" ) }, // :MNP:580: + {"MQ", N_( "Martinique" ) }, // :MTQ:474: + {"MR", N_( "Mauritania" ) }, // :MRT:478: + {"MS", N_( "Montserrat" ) }, // :MSR:500: + {"MT", N_( "Malta" ) }, // :MLT:470: + {"MU", N_( "Mauritius" ) }, // :MUS:480: + {"MV", N_( "Maldives" ) }, // :MDV:462: + {"MW", N_( "Malawi" ) }, // :MWI:454: + {"MX", N_( "Mexico" ) }, // :MEX:484: + {"MY", N_( "Malaysia" ) }, // :MYS:458: + {"MZ", N_( "Mozambique" ) }, // :MOZ:508: + {"NA", N_( "Namibia" ) }, // :NAM:516: + {"NC", N_( "New Caledonia" ) }, // :NCL:540: + {"NE", N_( "Niger" ) }, // :NER:562: + {"NF", N_( "Norfolk Island" ) }, // :NFK:574: + {"NG", N_( "Nigeria" ) }, // :NGA:566: + {"NI", N_( "Nicaragua" ) }, // :NIC:558: + {"NL", N_( "Netherlands" ) }, // :NLD:528: + {"NO", N_( "Norway" ) }, // :NOR:578: + {"NP", N_( "Nepal" ) }, // :NPL:524: + {"NR", N_( "Nauru" ) }, // :NRU:520: + {"NU", N_( "Niue" ) }, // :NIU:570: + {"NZ", N_( "New Zealand" ) }, // :NZL:554: + {"OM", N_( "Oman" ) }, // :OMN:512: + {"PA", N_( "Panama" ) }, // :PAN:591: + {"PE", N_( "Peru" ) }, // :PER:604: + {"PF", N_( "French Polynesia" ) }, // :PYF:258: + {"PG", N_( "Papua New Guinea" ) }, // :PNG:598: + {"PH", N_( "Philippines" ) }, // :PHL:608: + {"PK", N_( "Pakistan" ) }, // :PAK:586: + {"PL", N_( "Poland" ) }, // :POL:616: + {"PM", N_( "Saint Pierre and Miquelon" ) }, // :SPM:666: + {"PN", N_( "Pitcairn" ) }, // :PCN:612: + {"PR", N_( "Puerto Rico" ) }, // :PRI:630: + {"PS", N_( "Palestinian Territory" ) }, // :PSE:275: + {"PT", N_( "Portugal" ) }, // :PRT:620: + {"PW", N_( "Palau" ) }, // :PLW:585: + {"PY", N_( "Paraguay" ) }, // :PRY:600: + {"QA", N_( "Qatar" ) }, // :QAT:634: + {"RE", N_( "Reunion" ) }, // :REU:638: + {"RO", N_( "Romania" ) }, // :ROU:642: + {"RS", N_( "Serbia" ) }, + {"RU", N_( "Russian Federation" ) }, // :RUS:643: + {"RW", N_( "Rwanda" ) }, // :RWA:646: + {"SA", N_( "Saudi Arabia" ) }, // :SAU:682: + {"SB", N_( "Solomon Islands" ) }, // :SLB:090: + {"SC", N_( "Seychelles" ) }, // :SYC:690: + {"SD", N_( "Sudan" ) }, // :SDN:736: + {"SE", N_( "Sweden" ) }, // :SWE:752: + {"SG", N_( "Singapore" ) }, // :SGP:702: + {"SH", N_( "Saint Helena" ) }, // :SHN:654: + {"SI", N_( "Slovenia" ) }, // :SVN:705: + {"SJ", N_( "Svalbard and Jan Mayen" ) }, // :SJM:744: + {"SK", N_( "Slovakia" ) }, // :SVK:703: + {"SL", N_( "Sierra Leone" ) }, // :SLE:694: + {"SM", N_( "San Marino" ) }, // :SMR:674: + {"SN", N_( "Senegal" ) }, // :SEN:686: + {"SO", N_( "Somalia" ) }, // :SOM:706: + {"SR", N_( "Suriname" ) }, // :SUR:740: + {"ST", N_( "Sao Tome and Principe" ) }, // :STP:678: + {"SV", N_( "El Salvador" ) }, // :SLV:222: + {"SY", N_( "Syria" ) }, // :SYR:760: + {"SZ", N_( "Swaziland" ) }, // :SWZ:748: + {"TC", N_( "Turks and Caicos Islands" ) }, // :TCA:796: + {"TD", N_( "Chad" ) }, // :TCD:148: + {"TF", N_( "French Southern Territories" ) }, // :ATF:260: + {"TG", N_( "Togo" ) }, // :TGO:768: + {"TH", N_( "Thailand" ) }, // :THA:764: + {"TJ", N_( "Tajikistan" ) }, // :TJK:762: + {"TK", N_( "Tokelau" ) }, // :TKL:772: + {"TM", N_( "Turkmenistan" ) }, // :TKM:795: + {"TN", N_( "Tunisia" ) }, // :TUN:788: + {"TO", N_( "Tonga" ) }, // :TON:776: + {"TL", N_( "East Timor" ) }, // :TLS:626: + {"TR", N_( "Turkey" ) }, // :TUR:792: + {"TT", N_( "Trinidad and Tobago" ) }, // :TTO:780: + {"TV", N_( "Tuvalu" ) }, // :TUV:798: + {"TW", N_( "Taiwan" ) }, // :TWN:158: + {"TZ", N_( "Tanzania" ) }, // :TZA:834: + {"UA", N_( "Ukraine" ) }, // :UKR:804: + {"UG", N_( "Uganda" ) }, // :UGA:800: + {"UM", N_( "United States Minor Outlying Islands" ) },// :UMI:581: + {"US", N_( "United States" ) }, // :USA:840: + {"UY", N_( "Uruguay" ) }, // :URY:858: + {"UZ", N_( "Uzbekistan" ) }, // :UZB:860: + {"VA", N_( "Holy See (Vatican City State)" ) }, // :VAT:336: + {"VC", N_( "Saint Vincent and the Grenadines" ) }, // :VCT:670: + {"VE", N_( "Venezuela" ) }, // :VEN:862: + {"VG", N_( "British Virgin Islands" ) }, // :VGB:092: + {"VI", N_( "Virgin Islands, U.S." ) }, // :VIR:850: + {"VN", N_( "Vietnam" ) }, // :VNM:704: + {"VU", N_( "Vanuatu" ) }, // :VUT:548: + {"WF", N_( "Wallis and Futuna" ) }, // :WLF:876: + {"WS", N_( "Samoa" ) }, // :WSM:882: + {"YE", N_( "Yemen" ) }, // :YEM:887: + {"YT", N_( "Mayotte" ) }, // :MYT:175: + {"ZA", N_( "South Africa" ) }, // :ZAF:710: + {"ZM", N_( "Zambia" ) }, // :ZMB:894: + {"ZW", N_( "Zimbabwe" ) }, // :ZWE:716: + + { NULL, NULL } + }; + + for (const Init * i = init; i->iso3166 != NULL; ++i) + _codeMap[i->iso3166] = i->name; + } + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/CountryCode.h b/zypp/CountryCode.h new file mode 100644 index 0000000..e5ccb1a --- /dev/null +++ b/zypp/CountryCode.h @@ -0,0 +1,75 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CountryCode.h + * +*/ +#ifndef ZYPP_COUNTRYCODE_H +#define ZYPP_COUNTRYCODE_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class CountryCode + /// \brief Country codes (iso3166-1-alpha-2). + /// + /// In fact the class will not prevent to use a non iso country code. + /// Just a warning will appear in the log. + /////////////////////////////////////////////////////////////////// + class ZYPP_API CountryCode : public IdStringType + { + public: + /** Default Ctor: \ref noCode */ + CountryCode(); + + /** Ctor from string. */ + explicit CountryCode( IdString str_r ); + + /** Ctor from string. */ + explicit CountryCode( const std::string & str_r ); + + /** Ctor from string. */ + explicit CountryCode( const char * str_r ); + + /** Dtor */ + ~CountryCode(); + + public: + + /** \name CountryCode constants. */ + //@{ + /** Empty code. */ + static const CountryCode noCode; + //@} + + public: + /** Return the country code asString. */ + std::string code() const + { return std::string(_str); } + + /** Return the translated country name; if unknown the country code. */ + std::string name() const; + + private: + friend class IdStringType; + IdString _str; + }; +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// + +ZYPP_DEFINE_ID_HASHABLE( ::zypp::CountryCode ); + +#endif // ZYPP_COUNTRYCODE_H diff --git a/zypp/CpeId.cc b/zypp/CpeId.cc new file mode 100644 index 0000000..ea8f2ed --- /dev/null +++ b/zypp/CpeId.cc @@ -0,0 +1,1056 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CpeId.cc + */ +#include +#include + +#include +#include +#include + +#include + +using std::endl; + +/** Initializer list with all wfn attributes */ +#define WFN_ATTRIBUTES {\ + Attribute::part, \ + Attribute::vendor, \ + Attribute::product, \ + Attribute::version, \ + Attribute::update, \ + Attribute::edition, \ + Attribute::language, \ + Attribute::sw_edition,\ + Attribute::target_sw, \ + Attribute::target_hw, \ + Attribute::other, \ +} + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + /** Hex-digit to number or -1. */ + inline int heDecodeCh( char ch ) + { + if ( '0' <= ch && ch <= '9' ) + return( ch - '0' ); + if ( 'A' <= ch && ch <= 'F' ) + return( ch - 'A' + 10 ); + if ( 'a' <= ch && ch <= 'f' ) + return( ch - 'a' + 10 ); + return -1; + } + + /** Printable non whitespace in [0x00,0x7f] valid in WFN */ + inline bool chIsValidRange( char ch ) + { return( '!' <= ch && ch <= '~' ); } + + /** Alpha */ + inline bool chIsAlpha( char ch ) + { return( ( 'a' <= ch && ch <= 'z' ) || ( 'A' <= ch && ch <= 'Z' ) ); } + + /** Digit */ + inline bool chIsNum( char ch ) + { return( '0' <= ch && ch <= '9' ); } + + /** Alphanum */ + inline bool chIsAlNum( char ch ) + { return( chIsAlpha( ch ) || chIsNum( ch ) ); } + + /** Alphanum or \c underscore are unescaped in WFN */ + inline bool chIsWfnUnescaped( char ch ) + { return( chIsAlNum( ch ) || ch == '_' ); } + + } // namespace + /////////////////////////////////////////////////////////////////// + + constexpr CpeId::NoThrowType CpeId::noThrow; + + /////////////////////////////////////////////////////////////////// + /// \class CpeId::Impl + /// \brief CpeId implementation. + /////////////////////////////////////////////////////////////////// + class CpeId::Impl : private base::NonCopyable + { + using Wfn = std::array; + + public: + Impl() {} + + Impl( const std::string & cpe_r ) + : _wfn( unbind( cpe_r ) ) + {} + + public: + explicit operator bool() const + { for ( const auto & val : _wfn ) if ( ! val.isANY() ) return true; return false; } + + std::string asFs() const + { + str::Str ret; + ret << "cpe:2.3"; + for ( auto ai : WFN_ATTRIBUTES ) + { + ret << ':' << _wfn[ai].asFs(); + } + return ret; + } + + std::string asUri() const + { + str::Str ret; + ret << "cpe:/"; + std::string val; + unsigned colon = 0; // to remember trailing colons + for ( auto ai : WFN_ATTRIBUTES ) + { + val = _wfn[ai].asUri(); + + if ( ai == Attribute::edition ) + { + if ( ! ( _wfn[Attribute::sw_edition].isANY() + && _wfn[Attribute::target_sw].isANY() + && _wfn[Attribute::target_hw].isANY() + && _wfn[Attribute::other].isANY() ) ) + { + // packing is needed + val = str::Str() + << '~' << val//Attribute::edition + << '~' << _wfn[Attribute::sw_edition].asUri() + << '~' << _wfn[Attribute::target_sw].asUri() + << '~' << _wfn[Attribute::target_hw].asUri() + << '~' << _wfn[Attribute::other].asUri(); + } + } + + if ( ! val.empty() ) + { + if ( colon ) + ret << std::string( colon, ':' ); + ret << val; + colon = 1; + } + else + ++colon; + + if ( ai == Attribute::language ) + break; // remaining attrs packaed in edition + } + return ret; + } + + std::string asWfn() const + { + str::Str ret; + ret << "wfn:["; + for ( auto ai : WFN_ATTRIBUTES ) + { + const Value & val( _wfn[ai] ); + if ( ! val.isANY() ) + { + if ( ai ) ret << ','; + ret << Attribute::asString( ai ) << '='; + if ( val.isString() ) + ret << '"' << val << '"'; + else + ret << "NA"; // as ANY is omitted, it must be NA + } + } + return ret << "]"; + } + + public: + SetCompare setRelationMixinCompare( const Impl & trg ) const + { + SetCompare ret = SetCompare::equal; + for ( auto ai : WFN_ATTRIBUTES ) + { + switch ( _wfn[ai].compare( trg._wfn[ai] ).asEnum() ) + { + case SetCompare::uncomparable: + ret = SetCompare::uncomparable; + break; + + case SetCompare::equal: + break; + + case SetCompare::properSubset: + if ( ret == SetCompare::equal ) + ret = SetCompare::properSubset; + else if ( ret != SetCompare::properSubset ) + ret = SetCompare::uncomparable; + break; + + case SetCompare::properSuperset: + if ( ret == SetCompare::equal ) + ret = SetCompare::properSuperset; + else if ( ret != SetCompare::properSuperset ) + ret = SetCompare::uncomparable; + break; + + case SetCompare::disjoint: + ret = SetCompare::disjoint; + break; + } + if ( ret == SetCompare::uncomparable || ret == SetCompare::disjoint ) + break; + } + return ret; + } + + private: + /** Assign \a val_r if it meets \a attr_r specific contraints. + * \throws std::invalid_argument if string is malformed + */ + static void assignAttr( Wfn & wfn_r, Attribute attr_r, const Value & val_r ) + { + if ( val_r.isString() ) + { + switch ( attr_r.asEnum() ) + { + case Attribute::part: + { + const std::string & wfn( val_r.asWfn() ); + switch ( wfn[0] ) + { + case 'h': + case 'o': + case 'a': + if ( wfn[1] == '\0' ) + break; + // else: fallthrough + default: + throw std::invalid_argument( str::Str() << "CpeId:Wfn:part: '" << wfn << "' illegal value; expected: 'h' | 'o' | 'a'" ); + break; + } + } + break; + + case Attribute::language: + { + const std::string & wfn( val_r.asWfn() ); + std::string::size_type len = 0; + // (2*3ALPHA) ["-" (2ALPHA / 3DIGIT)] + if ( chIsAlpha( wfn[0] ) && chIsAlpha( wfn[1] ) ) + { + len = chIsAlpha( wfn[2] ) ? 3 : 2; + if ( wfn[len] == '-' ) + { + if ( chIsAlpha( wfn[len+1] ) && chIsAlpha( wfn[len+2] ) ) + len += 3; + else if ( chIsNum( wfn[len+1] ) && chIsNum( wfn[len+2] ) && chIsNum( wfn[len+3] ) ) + len += 4; + } + } + if ( wfn.size() != len ) + throw std::invalid_argument( str::Str() << "CpeId:Wfn:language: '" << wfn << "' illegal value; expected RFC5646 conform: language ['-' region]" ); + } + break; + + default: + // no contraints + break; + } + } + wfn_r[attr_r.asIntegral()] = val_r; + } + + private: + /** Parse magic and unbind accordingly + * \throws std::invalid_argument if string is malformed + */ + static Wfn unbind( const std::string & cpe_r ); + + /** Parse Uri and unbind + * \throws std::invalid_argument if string is malformed + */ + static Wfn unbindUri( const std::string & cpe_r ); + + /** Parse Fs and unbind + * \throws std::invalid_argument if string is malformed + */ + static Wfn unbindFs( const std::string & cpe_r ); + + private: + Wfn _wfn; + }; + + CpeId::Impl::Wfn CpeId::Impl::unbind( const std::string & cpe_r ) + { + Wfn ret; + if ( cpe_r[0] == 'c' + && cpe_r[1] == 'p' + && cpe_r[2] == 'e' + && cpe_r[3] == ':' ) + { + if ( cpe_r[4] == '/' ) + { + ret = unbindUri( cpe_r ); + } + else if ( cpe_r[4] == '2' + && cpe_r[5] == '.' + && cpe_r[6] == '3' + && cpe_r[7] == ':' ) + { + ret = unbindFs( cpe_r ); + } + else + throw std::invalid_argument( "CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" ); + } + else if ( cpe_r[0] != '\0' ) + throw std::invalid_argument( "CpeId: bad magic; expected: 'cpe:2.3:' | 'cpe:/'" ); + return ret; + } + + CpeId::Impl::Wfn CpeId::Impl::unbindUri( const std::string & cpe_r ) + { + Wfn ret; + + static constexpr unsigned numUriAttr = 7u; // basic URI attibutes + std::vector field; + field.reserve( Attribute::numAttributes ); // reserve 7 + 4 for packed extened attrs in edition + if ( str::splitFields( cpe_r.c_str()+5/* skip magic 'cpe:/' */, std::back_inserter(field), ":" ) > numUriAttr ) + throw std::invalid_argument( str::Str() << "CpeId:Uri: too many fields (" << field.size() << "); expected " << numUriAttr ); + field.resize( Attribute::numAttributes ); // fillup with ANY(""), + + for ( auto ai : WFN_ATTRIBUTES ) + { + if ( ai == Attribute::edition && field[ai][0] == '~' ) + { + // unpacking is needed + static constexpr unsigned numPacks = 6u; // dummy_before_~ + edition + 4 extended attributes + std::vector pack; + pack.reserve( numPacks ); + if ( str::splitFields( field[ai], std::back_inserter(pack), "~" ) > numPacks ) + throw std::invalid_argument( str::Str() << "CpeId:Uri:edition: too many packs (" << pack.size() << "); expected " << numPacks ); + pack.resize( numPacks ); // fillup with ANY(""), should be noOP + + pack[1].swap( field[Attribute::edition] ); + pack[2].swap( field[Attribute::sw_edition] ); + pack[3].swap( field[Attribute::target_sw] ); + pack[4].swap( field[Attribute::target_hw] ); + pack[5].swap( field[Attribute::other] ); + } + assignAttr( ret, ai, Value( field[ai], Value::uriFormat ) ); + } + return ret; + } + + CpeId::Impl::Wfn CpeId::Impl::unbindFs( const std::string & cpe_r ) + { + Wfn ret; + + std::vector field; + field.reserve( Attribute::numAttributes ); + if ( str::splitFields( cpe_r.c_str()+8/* skip magic 'cpe:2.3:' */, std::back_inserter(field), ":" ) > Attribute::numAttributes ) + throw std::invalid_argument( str::Str() << "CpeId:Fs: too many fields (" << field.size() << "); expected 11" /*<< Attribute::numAttributes but g++ currently can't resoolve this as constexpr*/ ); + if ( !field.empty() && field.back().empty() ) // A trailing ':' leads to an empty (illegal) field, but we fillup missing fields with ANY|"*" + field.back() = "*"; + field.resize( Attribute::numAttributes, "*" ); // fillup with ANY|"*" + + for ( auto ai : WFN_ATTRIBUTES ) + { + assignAttr( ret, ai, Value( field[ai], Value::fsFormat ) ); + } + return ret; + } + + + /////////////////////////////////////////////////////////////////// + // class CpeId + /////////////////////////////////////////////////////////////////// + + std::string CpeId::NoThrowType::lastMalformed; + + CpeId::CpeId() + : _pimpl( new Impl ) + {} + + CpeId::CpeId( const std::string & cpe_r ) + : _pimpl( new Impl( cpe_r ) ) + {} + + CpeId::CpeId( const std::string & cpe_r, NoThrowType ) + { + try + { + _pimpl.reset( new Impl( cpe_r ) ); + NoThrowType::lastMalformed.clear(); + } + catch(...) + { + _pimpl.reset( new Impl ); + NoThrowType::lastMalformed = cpe_r; + } + } + + CpeId::~CpeId() + {} + + CpeId::operator bool() const + { return bool(*_pimpl); } + + std::string CpeId::asFs() const + { return _pimpl->asFs(); } + + std::string CpeId::asUri() const + { return _pimpl->asUri(); } + + std::string CpeId::asWfn() const + { return _pimpl->asWfn(); } + + SetCompare CpeId::setRelationMixinCompare( const CpeId & trg ) const + { return _pimpl->setRelationMixinCompare( *trg._pimpl ); } + + /////////////////////////////////////////////////////////////////// + // class CpeId::WfnAttribute + /////////////////////////////////////////////////////////////////// + + const std::string & CpeId::EAttributeDef::asString( Enum val_r ) + { + static std::map _table = { +#define OUTS(N) { N, #N } + OUTS( part ), + OUTS( vendor ), + OUTS( product ), + OUTS( version ), + OUTS( update ), + OUTS( edition ), + OUTS( language ), + OUTS( sw_edition ), + OUTS( target_sw ), + OUTS( target_hw ), + OUTS( other ), +#undef OUTS + }; + return _table[val_r]; + } + + /////////////////////////////////////////////////////////////////// + // class CpeId::Value + /////////////////////////////////////////////////////////////////// + + const CpeId::Value CpeId::Value::ANY; + const CpeId::Value CpeId::Value::NA( "" ); + + constexpr CpeId::Value::FsFormatType CpeId::Value::fsFormat; + constexpr CpeId::Value::UriFormatType CpeId::Value::uriFormat; + + CpeId::Value::Value( const std::string & value_r ) + { + if ( value_r.empty() ) // NA + { + if ( ! CpeId::Value::NA._value ) // initialized by this ctor! + _value.reset( new std::string ); + else + _value = CpeId::Value::NA._value; + } + else if ( value_r != "*" ) // ANY is default constructed + { + bool starting = true; // false after the 1st non-? + for_( chp, value_r.begin(), value_r.end() ) + { + switch ( *chp ) + { + case '\\': // quoted + ++chp; + if ( ! chIsValidRange( *chp ) ) + { + if ( *chp ) + throw std::invalid_argument( str::Str() << "CpeId:Wfn: illegal quoted character '\\" << reinterpret_cast(*chp) << "'" ); + else + throw std::invalid_argument( "CpeId:Wfn: Backslash escapes nothing" ); + } + else if ( chIsWfnUnescaped( *chp ) ) + throw std::invalid_argument( str::Str() << "CpeId:Wfn: unnecessarily quoted character '\\" << *chp << "'" ); + else if ( starting && *chp == '-' && chp+1 == value_r.end() ) + throw std::invalid_argument( str::Str() << "CpeId:Wfn: '\\-' is illegal value" ); + break; + + case '?': // sequence at beginning or end of string + while ( *(chp+1) == '?' ) + ++chp; + if ( ! ( starting || chp+1 == value_r.end() ) ) + throw std::invalid_argument( "CpeId:Wfn: embedded ?" ); + break; + + case '*': // single at beginning or end of string + if ( ! ( starting || chp+1 == value_r.end() ) ) + throw std::invalid_argument( "CpeId:Wfn: embedded *" ); + break; + + default: // everything else unquoted + if ( ! chIsWfnUnescaped( *chp ) ) + { + if ( chIsValidRange( *chp ) ) + throw std::invalid_argument( str::Str() << "CpeId:Wfn: missing quote before '" << *chp << "'" ); + else + throw std::invalid_argument( str::Str() << "CpeId:Wfn: illegal character '" << reinterpret_cast(*chp) << "'" ); + } + break; + } + if ( starting ) + starting = false; + } + _value.reset( new std::string( value_r ) ); + } + } + + CpeId::Value::Value( const std::string & encoded_r, FsFormatType ) + { + if ( encoded_r != "*" ) // ANY is default constructed + { + if ( encoded_r == "-" ) // NA + { + _value = CpeId::Value::NA._value; + } + else + { + str::Str result; + bool starting = true; // false after the 1st non-? + for_( chp, encoded_r.begin(), encoded_r.end() ) + { + switch ( *chp ) + { + case '\\': // may stay quoted + ++chp; + if ( chIsWfnUnescaped( *chp ) ) + result << *chp; + else if ( chIsValidRange( *chp ) ) + result << '\\' << *chp; + else if ( *chp ) + throw std::invalid_argument( str::Str() << "CpeId:Fs: illegal quoted character '\\" << *chp << "'" ); + else + throw std::invalid_argument( "CpeId:Fs: Backslash escapes nothing" ); + break; + + case '?': // sequence at beginning or end of string + result << '?'; + while ( *(chp+1) == '?' ) + { + ++chp; + result << '?'; + } + if ( ! ( starting || chp+1 == encoded_r.end() ) ) + throw std::invalid_argument( "CpeId:Fs: embedded ?" ); + break; + + case '*': // single at beginning or end of string + if ( starting || chp+1 == encoded_r.end() ) + result << '*'; + else + throw std::invalid_argument( "CpeId:Fs: embedded *" ); + break; + + default: + if ( chIsWfnUnescaped( *chp ) ) + result << *chp; + else if ( chIsValidRange( *chp ) ) + result << '\\' << *chp; + else + throw std::invalid_argument( str::Str() << "CpeId:Fs: illegal character '" << reinterpret_cast(*chp) << "'" ); + break; + } + if ( starting ) + starting = false; + } + if ( starting ) + throw std::invalid_argument( "CpeId:Fs: '' value is illegal" ); + _value.reset( new std::string( result ) ); + } + } + } + + CpeId::Value::Value( const std::string & encoded_r, UriFormatType ) + { + if ( ! encoded_r.empty() ) // ANY is default constructed + { + if ( encoded_r == "-" ) // NA + { + _value = CpeId::Value::NA._value; + } + else + { + str::Str result; + bool starting = true; // false after the 1st non-? (%01) + for_( chp, encoded_r.begin(), encoded_r.end() ) + { + char ch = *chp; + + if ( ch == '%' ) // legal '%xx' sequence first + { + int d1 = heDecodeCh( *(chp+1) ); + if ( d1 != -1 ) + { + int d2 = heDecodeCh( *(chp+2) ); + if ( d2 != -1 ) + { + chp += 2; // skip sequence + if ( d1 == 0 ) + { + if ( d2 == 1 ) // %01 - ? valid sequence at begin or end + { + result << '?'; + while ( *(chp+1) == '%' && *(chp+2) == '0' && *(chp+3) == '1' ) + { + chp += 3; + result << '?'; + } + if ( starting || chp+1 == encoded_r.end() ) + { + starting = false; + continue; // -> continue; + } + else + throw std::invalid_argument( "CpeId:Uri: embedded %01" ); + } + else if ( d2 == 2 ) // %02 - * valid at begin or end + { + if ( starting || chp+1 == encoded_r.end() ) + { + result << '*'; + starting = false; + continue; // -> continue; + } + else + throw std::invalid_argument( "CpeId:Uri: embedded %02" ); + } + } + ch = (d1<<4)|d2; + if ( ! chIsValidRange( ch ) ) + throw std::invalid_argument( str::Str() << "CpeId:Uri: illegal % encoded character '" << reinterpret_cast(ch) << "'" ); + } + } + } + else if ( ! chIsValidRange( ch ) ) + throw std::invalid_argument( str::Str() << "CpeId:Uri: illegal character '" << reinterpret_cast(ch) << "'" ); + + if ( chIsWfnUnescaped( ch ) ) + result << ch; + else + result << '\\' << ch; + + if ( starting ) + starting = false; + } + _value.reset( new std::string( result ) ); + } + } + } + + std::string CpeId::Value::asWfn() const + { + std::string ret; + if ( ! _value ) + { + static const std::string any( "*" ); + ret = any; + } + else + ret = *_value; // includes "" for NA + return ret; + } + + std::string CpeId::Value::asFs() const + { + std::string ret; + if ( isANY() ) + { + static const std::string asterisk( "*" ); + ret = asterisk; + } + else if ( isNA() ) + { + static const std::string dash( "-" ); + ret = dash; + } + else + { + str::Str result; + for_( chp, _value->begin(), _value->end() ) + { + if ( *chp != '\\' ) + result << *chp; + else + { + ++chp; + switch ( *chp ) + { + case '-': + case '.': + case '_': + result << *chp; // without escaping + break; + + case '\0': + throw std::invalid_argument( "CpeId:Wfn: Backslash escapes nothing" ); + break; + + default: + result << '\\' << *chp; + break; + } + } + } + ret = result; + } + return ret; + } + + std::string CpeId::Value::asUri() const + { + std::string ret; // ANY + if ( ! isANY() ) + { + if ( isNA() ) + { + static const std::string dash( "-" ); + ret = dash; + } + else + { + str::Str result; + for_( chp, _value->begin(), _value->end() ) + { + if ( chIsWfnUnescaped( *chp ) ) + { + result << *chp; + } + else + { + static const char *const hdig = "0123456789abcdef"; + switch ( *chp ) + { + case '\\': + ++chp; + switch ( *chp ) + { + case '-': + case '.': + result << *chp; // without encodeing + break; + + case '\0': + throw std::invalid_argument( "CpeId:Wfn: Backslash escapes nothing" ); + break; + + default: + result << '%' << hdig[(unsigned char)(*chp)/16] << hdig[(unsigned char)(*chp)%16]; + break; + } + break; + + case '?': + result << "%01"; + break; + + case '*': + result << "%02"; + break; + + default: + throw std::invalid_argument( str::Str() << "CpeId:Wfn: illegal char '" << *chp << "' in WFN" ); + break; + } + } + } + ret = result; + } + } + return ret; + } + + /////////////////////////////////////////////////////////////////// + namespace + { + /** Whether it's a wildcard character ([*?]). */ + inline bool isWildchar( char ch_r ) + { return( ch_r == '*' || ch_r == '?' ); } + + /** Whether there is an even number of consecutive backslashes before and including \a rbegin_r + * An even number of backslashes means the character following is unescaped. + */ + inline bool evenNumberOfBackslashes( const std::string::const_reverse_iterator& rbegin_r, const std::string::const_reverse_iterator& rend_r ) + { + unsigned backslashes = 0; + for_( it, rbegin_r, rend_r ) + { + if ( *it == '\\' ) + ++backslashes; + else + break; + } + return !(backslashes & 1U); + } + + /** Number of chars (not counting escaping backslashes) in [begin_r,end_r[ */ + inline unsigned trueCharsIn( const std::string & str_r, std::string::size_type begin_r, std::string::size_type end_r ) + { + unsigned chars = 0; + for_( it, begin_r, end_r ) + { + ++chars; + if ( str_r[it] == '\\' ) + { + if ( ++it == end_r ) + break; + } + } + return chars; + } + + /** Match helper comparing 2 Wildcardfree string values (case insensitive). */ + inline bool matchWildcardfreeString( const std::string & lhs, const std::string & rhs ) + { return( str::compareCI( lhs, rhs ) == 0 ); } + + /** Match helper matching Wildcarded source against Wildcardfree target. + * + * Constraints on usage of the unquoted question mark (zero or one char in \a trg): + * 1. An unquoted question mark MAY be used at the beginning and/or the end of an + * attribute-value string. + * 2. A contiguous sequence of unquoted question marks MAY appear at the beginning + * and/or the end of an attribute-value string. + * 3. An unquoted question mark SHALL NOT be used in any other place in an + * attribute-value string. + * + * Constraints on usage of the unquoted asterisk (zero or more chars in \a trg): + * 1. A single unquoted asterisk MAY be used as the entire attribute-value string. + * 2. A single unquoted asterisk MAY be used at the beginning and/or end of an + * attribute-value string. + * 3. An unquoted asterisk SHALL NOT be used in any other place in an attribute-value + * string. + * + * Unquoted question marks and asterisks MAY appear in the same attribute-value string + * as long as they meet the constraints above. + * + * Example of illegal usage: "foo?bar", "bar??baz", "q??x", + * "foo*bar", "**foo", "bar***", + * "*?foobar", "foobar*?" + * + * \note Relies on \a src and \a trg being wellformed. + */ + inline bool matchWildcardedString( std::string src, std::string trg ) + { + // std::string::npos remembers an asterisk + // unescaped wildcard prefix + std::string::size_type prefx = 0; + switch ( *src.begin() ) // wellformed implies not empty + { + case '*': + if ( src.size() == 1 ) + return true; // "*" matches always: superset + // else + prefx = std::string::npos; + src.erase( 0, 1 ); + break; + case '?': + ++prefx; + for_( it, ++src.begin(), src.end() ) + { if ( *it == '?' ) ++prefx; else break; } + if ( src.size() == prefx ) + return( trg.size() <= prefx ); // "??..?": superset if at most #prefx chars + // else + src.erase( 0, prefx ); + break; + default: + break; + } + // unescaped wildcard suffix + std::string::size_type suffx = 0; + if ( ! src.empty() ) + { + switch ( *src.rbegin() ) + { + case '*': + if ( evenNumberOfBackslashes( ++src.rbegin(), src.rend() ) ) + { + suffx = std::string::npos; + src.erase( src.size()-1 ); + } + break; + case '?': + ++suffx; + for_( it, ++src.rbegin(), src.rend() ) + { if ( *it == '?' ) ++suffx; else break; } + if ( ! evenNumberOfBackslashes( src.rbegin()+suffx, src.rend() ) ) + --suffx; // last '?' was escaped. + src.erase( src.size()-suffx ); + break; + default: + break; + } + } + // now match; find src in trg an check surrounding wildcards + src = str::toLower( src ); + trg = str::toLower( trg ); + for ( std::string::size_type match = trg.find( src, 0 ); + match != std::string::npos; + match = trg.find( src, match+1 ) ) + { + if ( prefx != std::string::npos && trueCharsIn( trg, 0, match ) > prefx ) + break; // not "*", and already more chars than "?"s before match: disjoint + std::string::size_type frontSize = match + src.size(); + if ( suffx != std::string::npos && trueCharsIn( trg, frontSize, trg.size() ) > suffx ) + continue; // not "*", and still more chars than "?"s after match: check next match + return true; // match: superset + } + return false; // disjoint + } + } // namespace + /////////////////////////////////////////////////////////////////// + + bool CpeId::Value::containsWildcard() const + { + const std::string & value( *_value ); + return ( isWildchar( *value.begin() ) + || ( isWildchar( *value.rbegin() ) && evenNumberOfBackslashes( ++value.rbegin(), value.rend() ) ) ); + } + + /////////////////////////////////////////////////////////////////// + /// Symmetric attribute compare if wildcards are involved! + /// The specs define any comarison with a wildcarded attribute as + /// target to return \c uncomparable: + /// \code + /// wildcardfree <=> wildcarded ==> uncomparable, + /// wildcarded <=> wildcardfree ==> superset or disjoint + /// \endcode + /// But a symmetric result is much more intuitive: + /// \code + /// wildcardfree <=> wildcarded ==> subset or disjoint + /// wildcarded <=> wildcardfree ==> superset or disjoint + /// \endcode + /////////////////////////////////////////////////////////////////// +#define WFN_STRICT_SPEC 0 +#if WFN_STRICT_SPEC + //SetCompare CpeId::Value::setRelationMixinCompare( const CpeId::Value & trg ) const + { + static const SetCompare kNeedsCloserLook( SetCompare::Enum(-1) ); // artificial Compare value + static const SetCompare matchTabel[4][4] = {{ + /* ANY, ANY */ SetCompare::equal, + /* ANY, NA */ SetCompare::properSuperset, + /* ANY, wildcardfree */ SetCompare::properSuperset, + /* ANY, wildcarded */ SetCompare::uncomparable, + },{ + /* NA, ANY */ SetCompare::properSubset, + /* NA, NA */ SetCompare::equal, + /* NA, wildcardfree */ SetCompare::disjoint, + /* NA, wildcarded */ SetCompare::uncomparable, + },{ + /* wildcardfree, ANY */ SetCompare::properSubset, + /* wildcardfree, NA */ SetCompare::disjoint, + /* wildcardfree, wildcardfree */ kNeedsCloserLook, // equal or disjoint + /* wildcardfree, wildcarded */ SetCompare::uncomparable, + },{ + /* wildcarded, ANY */ SetCompare::properSubset, + /* wildcarded, NA */ SetCompare::disjoint, + /* wildcarded, wildcardfree */ kNeedsCloserLook, // superset or disjoint + /* wildcarded, wildcarded */ SetCompare::uncomparable, + }}; + + Type srcType = type(); + Type trgType = trg.type(); + SetCompare ret = matchTabel[srcType.asIntegral()][trgType.asIntegral()]; + if ( ret == kNeedsCloserLook ) + { + if ( srcType == Type::wildcardfree ) // trgType == Type::wildcardfree + { + // simple string compare + ret = matchWildcardfreeString( *_value, *trg._value ) ? SetCompare::equal : SetCompare::disjoint; + } + else if ( srcType == Type::wildcarded ) // trgType == Type::wildcardfree + { + // Needs wildcard compare + ret = matchWildcardedString( *_value, *trg._value ) ? SetCompare::properSuperset : SetCompare::disjoint; + } + } + return ret; + } +#else + SetCompare CpeId::Value::setRelationMixinCompare( const CpeId::Value & trg ) const + { + /////////////////////////////////////////////////////////////////// + // ANY, ANY => equal + // ANY, NA => properSuperset + // ANY, wildcardfree => properSuperset + // ANY, wildcarded => properSuperset + // + // NA, ANY => properSubset + // NA, NA => equal + // NA, wildcardfree => disjoint + // NA, wildcarded => disjoint + // + // wildcardfree, ANY => properSubset + // wildcardfree, NA => disjoint + // wildcardfree, wildcardfree => NeedsCloserLook: equal or disjoint + // wildcardfree, wildcarded => NeedsCloserLook: subset or disjoint + // + // wildcarded, ANY => properSubset + // wildcarded, NA => disjoint + // wildcarded, wildcardfree => NeedsCloserLook: superset or disjoint + // wildcarded, wildcarded => NeedsCloserLook" equal or uncomparable + /////////////////////////////////////////////////////////////////// + + SetCompare ret = SetCompare::disjoint; + + if ( isANY() ) + { + ret = trg.isANY() ? SetCompare::equal : SetCompare::properSuperset; + } + else if ( trg.isANY() ) + { + ret = SetCompare::properSubset; + } + else if ( isNA() ) + { + if ( trg.isNA() ) ret = SetCompare::equal; // else: SetCompare::disjoint; + } + else if ( ! trg.isNA() ) // else: SetCompare::disjoint; + { + // NeedsCloserLook: + if ( isWildcarded() ) + { + if ( trg.isWildcarded() ) + { + // simple string compare just to detect 'equal' + ret = matchWildcardfreeString( *_value, *trg._value ) ? SetCompare::equal : SetCompare::uncomparable; + } + else + { + // Needs wildcard compare (src,trg) + if ( matchWildcardedString( *_value, *trg._value ) ) ret = SetCompare::properSuperset; // else: SetCompare::disjoint; + } + } + else + { + if ( trg.isWildcarded() ) + { + // Needs wildcard compare (trg,src) + if ( matchWildcardedString( *trg._value, *_value ) ) ret = SetCompare::properSubset; // else: SetCompare::disjoint; + } + else + { + // simple string compare + if ( matchWildcardfreeString( *_value, *trg._value ) ) ret = SetCompare::equal; // else: SetCompare::disjoint; + } + } + } + return ret; + } +#endif // WFN_STRICT_SPEC + + std::ostream & operator<<( std::ostream & str, const CpeId::Value & obj ) + { return str << obj.asString(); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/CpeId.h b/zypp/CpeId.h new file mode 100644 index 0000000..5b0c9a6 --- /dev/null +++ b/zypp/CpeId.h @@ -0,0 +1,304 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/CpeId.h + */ +#ifndef ZYPP_CPEID_H +#define ZYPP_CPEID_H + +#include +#include + +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class CpeId + /// \brief Common Platform Enumearation (2.3) + /// See http://cpe.mitre.org/ for more information on the + /// Common Platform Enumearation. + /////////////////////////////////////////////////////////////////// + class ZYPP_API CpeId : public base::SetRelationMixin + { + public: + /** WFN attribute value */ + class Value; + + public: + /** WFN attributes (use like 'enum class \ref Attribute') */ + struct EAttributeDef { + enum Enum { + part, //< attribute (2.2) + vendor, //< attribute (2.2) + product, //< attribute (2.2) + version, //< attribute (2.2) + update, //< attribute (2.2) + edition, //< attribute (2.2) + language, //< attribute (2.2) + sw_edition, //< extended attribute (2.3) + target_sw, //< extended attribute (2.3) + target_hw, //< extended attribute (2.3) + other //< extended attribute (2.3) + }; + static constexpr unsigned numAttributes = other+1; ///< number of attributes + static const std::string & asString( Enum val_r ); ///< string representantion + }; + using Attribute = base::EnumClass; ///< 'enum class Attribute' + + public: + /** Indicator type for non-trowing ctor. */ + struct NoThrowType { static std::string lastMalformed; }; + /** Indicator argument for non-trowing ctor. */ + static constexpr NoThrowType noThrow = NoThrowType(); + + public: + /** Default ctor: ANY-Cpeid, all attribute values are ANY */ + CpeId(); + + /** Ctor parsing from string representation (empty or URI or FS) + * \throws std::invalid_argument if string is malformed + */ + explicit CpeId( const std::string & cpe_r ); + + /** Ctor parsing from string representation (empty or URI or FS) + * \throws std::invalid_argument if string is malformed + */ + explicit CpeId( const char * cpe_r ) + : CpeId( std::string( cpe_r ? cpe_r : "" ) ) + {} + + /** Ctor parsing from string (empty or URI or FS, non throwing) + * Creates an empty CpeId if string is malformed. + */ + CpeId( const std::string & cpe_r, NoThrowType ); + + /** Dtor */ + ~CpeId(); + + public: + /** Evaluate in boolean context: not an ANY-CpeId */ + explicit operator bool() const; + + /** Default string representation [\ref asFS]. */ + std::string asString() const + { return asFs(); } + + /** String representation as Formated-String (in/out). + * \code + * cpe:2.3:a:opensuse:libzypp:14.16.0:beta:*:*:*:*:*:* + * \endcode + */ + std::string asFs() const; + + /** String representation as URI (in/out). + * \code + * cpe:/a:opensuse:libzypp:14.16.0:beta + * \endcode + */ + std::string asUri() const; + + /** String representation as Well-Formed-Name (internal format, out only). + * \code + * wfn:[part="a",vendor="opensuse",product="libzypp", version="14\.16\.0",update="beta"] + * \endcode + */ + std::string asWfn() const; + + private: + friend SetCompare base::SetRelationMixin::compare( const CpeId & ) const; + /** CPE name matching hook for \ref SetRelationMixin */ + SetCompare setRelationMixinCompare( const CpeId & trg ) const; + + public: + class Impl; ///< Implementation class. + private: + RWCOW_pointer _pimpl; ///< Pointer to implementation. + }; + + SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN( CpeId, const char * ); + SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN( CpeId, const std::string & ); + + /** \relates CpeId Stream output */ + inline std::ostream & operator<<( std::ostream & str, const CpeId & obj ) + { return str << obj.asString(); } + + /** \relates CpeId::Attribute Stream output */ + inline std::ostream & operator<<( std::ostream & str, const CpeId::Attribute & obj ) + { return str << CpeId::Attribute::asString( obj.asEnum() ); } + + + /////////////////////////////////////////////////////////////////// + /// \class CpeId::Value + /// \brief WFN attribute value + /// + /// Valid WFN string values are not empty, contain alphanumeric chars, underscore, + /// no whitespace, printable non-alphanumeric characters must be quoted by a + /// backslash. + /// + /// Unescaped asterisk and question mark are special characters and may occur at + /// the beginning and or end of the string. The asterisk must not be used more than + /// once in asequense. The question mark may be used more than once in a sequence. + /// + /// A single asterisk must not be used as attribute value, nor a single quoted hyphen. + /// + /// A single question mark may be used as value. + /// + /// \see http://cpe.mitre.org/ for more information on the Common Platform Enumeration. + /////////////////////////////////////////////////////////////////// + class CpeId::Value : public base::SetRelationMixin + { + public: + /** Logical value matching ANY value. */ + static const Value ANY; + + /** Logical value indicating “not applicable/not used" */ + static const Value NA; + + public: + /** Indicator type for ctor arg in FS format. */ + struct FsFormatType {}; + /** Indicator argument for ctor arg in FS format. */ + static constexpr FsFormatType fsFormat = FsFormatType(); + + /** Indicator type for ctor arg in URI format. */ + struct UriFormatType {}; + /** Indicator argument for ctor arg in URI format. */ + static constexpr UriFormatType uriFormat = UriFormatType(); + + public: + /** Default ctor: ANY */ + Value() + {} + + /** Ctor from string (WFN format; \c "*" represents ANY; \c "" represents NA) + * \throws std::invalid_argument if string is malformed (\see \ref isValidWfn). + */ + explicit Value( const std::string & value_r ); + + /** Ctor from char* (WFN format; \c nullptr or \c "*" represent ANY; \c "" represents NA) + * \throws std::invalid_argument if string is malformed (\see \ref isValidWfn). + */ + explicit Value( const char * value_r ) + : Value( std::string( value_r ? value_r : "*" ) ) + {} + + /** Ctor from string (FS format, \c "*" represents ANY; \c "-" represents NA) + * \throws std::invalid_argument if string is malformed. + */ + Value( const std::string & encoded_r, FsFormatType ); + + /** Ctor from string (URI format, \c "" represents ANY; \c "-" represents NA) + * \throws std::invalid_argument if string is malformed. + */ + Value( const std::string & encoded_r, UriFormatType ); + + public: + /** Classification of \ref Value types mostly for \ref match (use like 'enum class \ref Type') */ + struct ETypeDef { + enum Enum { + ANY, + NA, + wildcardfree, + wildcarded, + }; + }; + using Type = base::EnumClass; ///< 'enum class Type' + + /** Return the \ref Type of this \ref Value. */ + Type type() const + { + if ( !_value ) return Type::ANY; + if ( _value->empty() ) return Type::NA; + return( isWildcarded() ? Type::wildcarded : Type::wildcardfree ); + } + + /** Whether value is ANY. ) */ + bool isANY() const + { return !_value; } + + /** Whether value is NA. ) */ + bool isNA() const + { return _value && _value->empty(); } + + /** Whether it's a logical value (ANY|NA). */ + bool isLogical() const + { return !_value || _value->empty(); } + /** \overload for Type */ + bool isLogical( Type type_r ) const + { return( type_r == Type::ANY || type_r == Type::NA ); } + + /** Whether it's an attribute value string (not logical value). */ + bool isString() const + { return _value && !_value->empty(); } + /** \overload for Type */ + bool isString( Type type_r ) const + { return( type_r == Type::wildcardfree || type_r == Type::wildcarded ); } + + /** An attribute value string without wildcards ([*?] at begin and/or end) */ + bool isWildcardfree() const + { return isString() && ! containsWildcard(); } + + /** An attribute value string with wildcards ([*?] at begin and/or end) */ + bool isWildcarded() const + { return isString() && containsWildcard(); } + + public: + /** Default string representation [\ref asWfn]. */ + std::string asString() const + { return asWfn(); } + + /** String representation as in Well-Formed-Name (ANY:"*", NA:""). + * \code + * wfn:[part="a",vendor="opensuse",product="libzypp", version="14\.16\.0",update="beta"] + * \endcode + */ + std::string asWfn() const; + + /** String representation as in Formated-String (ANY:"*", NA:"-") + * \code + * cpe:2.3:a:opensuse:libzypp:14.16.0:beta:*:*:*:*:*:* + * \endcode + */ + std::string asFs() const; + + /** String representation as in URI (ANY:"", NA:"-") + * \code + * cpe:/a:opensuse:libzypp:14.16.0:beta + * \endcode + */ + std::string asUri() const; + + private: + friend SetCompare base::SetRelationMixin::compare( const Value & ) const; + /** CPE name matching hook for \ref SetRelationMixin */ + SetCompare setRelationMixinCompare( const Value & trg ) const; + + /** HAs unquoted [*?] at begin and/or end of value. + * \note \ref isString() must be asserted! + */ + bool containsWildcard() const; + + private: + RWCOW_pointer _value; + }; + + SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN( CpeId::Value, const char * ); + SETRELATIONMIXIN_DEFINE_COMPARE_BETWEEN( CpeId::Value, const std::string & ); + + /** \relates CpeId::Value Stream output */ + std::ostream & operator<<( std::ostream & str, const CpeId::Value & obj ); + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_CPEID_H diff --git a/zypp/Date.h b/zypp/Date.h new file mode 100644 index 0000000..717e196 --- /dev/null +++ b/zypp/Date.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Dep.cc b/zypp/Dep.cc new file mode 100644 index 0000000..3cf7164 --- /dev/null +++ b/zypp/Dep.cc @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Dep.cc + * +*/ +#include +#include + +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace + { + inline Dep::for_use_in_switch parse( const std::string & strval_r ) + { + const std::map _table = { + { "provides", Dep::PROVIDES_e }, + { "prerequires", Dep::PREREQUIRES_e }, + { "requires", Dep::REQUIRES_e }, + { "conflicts", Dep::CONFLICTS_e }, + { "obsoletes", Dep::OBSOLETES_e }, + { "recommends", Dep::RECOMMENDS_e }, + { "suggests", Dep::SUGGESTS_e }, + { "enhances", Dep::ENHANCES_e }, + { "supplements", Dep::SUPPLEMENTS_e } + }; + + auto it = _table.find( str::toLower( strval_r ) ); + if ( it == _table.end() ) + { + ZYPP_THROW( Exception("Dep parse: illegal string value '"+strval_r+"'") ); + } + return it->second; + } + } + + /////////////////////////////////////////////////////////////////// + + const Dep Dep::PROVIDES ( Dep::PROVIDES_e ); + const Dep Dep::PREREQUIRES( Dep::PREREQUIRES_e ); + const Dep Dep::REQUIRES ( Dep::REQUIRES_e ); + const Dep Dep::CONFLICTS ( Dep::CONFLICTS_e ); + const Dep Dep::OBSOLETES ( Dep::OBSOLETES_e ); + const Dep Dep::RECOMMENDS ( Dep::RECOMMENDS_e ); + const Dep Dep::SUGGESTS ( Dep::SUGGESTS_e ); + const Dep Dep::ENHANCES ( Dep::ENHANCES_e ); + const Dep Dep::SUPPLEMENTS( Dep::SUPPLEMENTS_e ); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Dep::Dep + // METHOD TYPE : Ctor + // + Dep::Dep( const std::string & strval_r ) + : _type( parse( strval_r ) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Dep::asString + // METHOD TYPE : const std::string & + // + const std::string & Dep::asString() const + { + static const std::map _table = { + { PROVIDES_e, "provides" }, + { PREREQUIRES_e, "prerequires" }, + { REQUIRES_e, "requires" }, + { CONFLICTS_e, "conflicts" }, + { OBSOLETES_e, "obsoletes" }, + { RECOMMENDS_e, "recommends" }, + { SUGGESTS_e, "suggests" }, + { ENHANCES_e, "enhances" }, + { SUPPLEMENTS_e, "supplements" } + }; + return _table.at(_type); + } + + std::string Dep::asUserString() const + { + switch ( inSwitch() ) + { + case PROVIDES_e: return _("Provides"); break; + case PREREQUIRES_e: return _("Prerequires"); break; + case REQUIRES_e: return _("Requires"); break; + case CONFLICTS_e: return _("Conflicts"); break; + case OBSOLETES_e: return _("Obsoletes"); break; + case RECOMMENDS_e: return _("Recommends"); break; + case SUGGESTS_e: return _("Suggests"); break; + case ENHANCES_e: return _("Enhances"); break; + case SUPPLEMENTS_e: return _("Supplements"); break; + } + return ""; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Dep.h b/zypp/Dep.h new file mode 100644 index 0000000..0847a87 --- /dev/null +++ b/zypp/Dep.h @@ -0,0 +1,123 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Dep.h + * +*/ +#ifndef ZYPP_DEP_H +#define ZYPP_DEP_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Dep + // + /** Enumeration class of dependency types. + * \ingroup g_EnumerationClass + */ + struct ZYPP_API Dep + { + friend bool operator==( const Dep & lhs, const Dep & rhs ); + friend bool operator!=( const Dep & lhs, const Dep & rhs ); + /** Arbitrary order to allow Dep as key in std::container. */ + friend bool operator<( const Dep & lhs, const Dep & rhs ); + + /** \name Dependency types + * These are the \em real dependency type contants to + * use. Don't mind that it's not an enum. + * \see \ref zypp::Dep::inSwitch + */ + //@{ + static const Dep PROVIDES ZYPP_API; + static const Dep PREREQUIRES ZYPP_API; + static const Dep REQUIRES ZYPP_API; + static const Dep CONFLICTS ZYPP_API; + static const Dep OBSOLETES ZYPP_API; + static const Dep RECOMMENDS ZYPP_API; + static const Dep SUGGESTS ZYPP_API; + static const Dep ENHANCES ZYPP_API; + static const Dep SUPPLEMENTS ZYPP_API; + //@} + + /** Enumarators provided \b only for use \ref inSwitch statement. + * \see inSwitch + */ + enum for_use_in_switch { + PROVIDES_e, + PREREQUIRES_e, + REQUIRES_e, + CONFLICTS_e, + OBSOLETES_e, + RECOMMENDS_e, + SUGGESTS_e, + ENHANCES_e, + SUPPLEMENTS_e, + }; + + /** Ctor from string. + * Legal values for \a strval_r are the constants names + * (case insignificant). + * + * \throw PARSE if \a strval_r is not legal. + * \todo refine exceptions and check throw. + */ + explicit + Dep( const std::string & strval_r ); + + /** String representation of dependency type. + * \return The constants names lowercased. + */ + const std::string & asString() const ZYPP_API; + + /** Translated dependency type (capitalized). + * \return The capitalized constants names translated. + */ + std::string asUserString() const ZYPP_API; + + /** Enumarator provided for use in \c switch statement. */ + for_use_in_switch inSwitch() const + { return _type; } + + private: + /** Ctor to initialize the dependency type contants. */ + Dep( for_use_in_switch type_r ) + : _type( type_r ) + {} + /** The operator. */ + for_use_in_switch _type; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Dep Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Dep & obj ) + { return str << obj.asString(); } + + /////////////////////////////////////////////////////////////////// + + /** \relates Dep */ + inline bool operator==( const Dep & lhs, const Dep & rhs ) + { return lhs._type == rhs._type; } + + /** \relates Dep */ + inline bool operator!=( const Dep & lhs, const Dep & rhs ) + { return lhs._type != rhs._type; } + + /** \relates Dep */ + inline bool operator<( const Dep & lhs, const Dep & rhs ) + { return lhs._type < rhs._type; } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_DEP_H diff --git a/zypp/Digest.cc b/zypp/Digest.cc new file mode 100644 index 0000000..01d3c49 --- /dev/null +++ b/zypp/Digest.cc @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Digest.cc + * + * \todo replace by Blocxx + * +*/ + + +#include +#include + +#ifdef DIGEST_TESTSUITE +#include +#endif + +#include +#include + +using std::endl; + +namespace zypp { + + bool DigestReport::askUserToAcceptNoDigest( const zypp::Pathname &file ) + { return false; } + + bool DigestReport::askUserToAccepUnknownDigest( const Pathname &file, const std::string &name ) + { return false; } + + bool DigestReport::askUserToAcceptWrongDigest( const Pathname &file, const std::string &requested, const std::string &found ) + { return false; } + +#ifdef DIGEST_TESTSUITE + int main(int argc, char *argv[]) + { + using namespace std; + bool openssl = false; + unsigned argpos = 1; + + if(argc > 1 && std::string(argv[argpos]) == "--openssl") + { + openssl = true; + ++argpos; + } + + if(argc - argpos < 2) + { + cerr << "Usage: " << argv[0] << " " << endl; + return 1; + } + + const char* digestname = argv[argpos++]; + const char* fn = argv[argpos++]; + + std::ifstream file(fn); + + std::string digest = Digest::digest(digestname, file); + + if(openssl) + cout << digestname << "(" << fn << ")= " << digest << endl; + else + cout << digest << " " << fn << endl; + + return 0; + } +#endif + +} // namespace zypp diff --git a/zypp/Digest.h b/zypp/Digest.h new file mode 100644 index 0000000..1655020 --- /dev/null +++ b/zypp/Digest.h @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Digest.h + * + * \todo replace by Blocxx + * +*/ + +#ifndef ZYPP_MEDIA_DIGEST_H +#define ZYPP_MEDIA_DIGEST_H + +#include + +#include +#include + +namespace zypp { + + struct ZYPP_API DigestReport : public callback::ReportBase + { + virtual bool askUserToAcceptNoDigest( const zypp::Pathname &file ); + virtual bool askUserToAccepUnknownDigest( const Pathname &file, const std::string &name ); + virtual bool askUserToAcceptWrongDigest( const Pathname &file, const std::string &requested, const std::string &found ); + }; + +} // namespace zypp +#endif diff --git a/zypp/DiskUsageCounter.cc b/zypp/DiskUsageCounter.cc new file mode 100644 index 0000000..ba5b6b9 --- /dev/null +++ b/zypp/DiskUsageCounter.cc @@ -0,0 +1,359 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/DiskUsageCounter.cc + * + */ +extern "C" +{ +#include +} + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + DiskUsageCounter::MountPointSet calcDiskUsage( DiskUsageCounter::MountPointSet result, const Bitmap & installedmap_r ) + { + if ( result.empty() ) + { + // partitioning is not set + return result; + } + + sat::Pool satpool( sat::Pool::instance() ); + + // init libsolv result vector with mountpoints + static const ::DUChanges _initdu = { 0, 0, 0, 0 }; + std::vector< ::DUChanges> duchanges( result.size(), _initdu ); + { + unsigned idx = 0; + for_( it, result.begin(), result.end() ) + { + duchanges[idx].path = it->dir.c_str(); + if ( it->growonly ) + duchanges[idx].flags |= DUCHANGES_ONLYADD; + ++idx; + } + } + // now calc... + ::pool_calc_duchanges( satpool.get(), + const_cast(installedmap_r), + &duchanges[0], + duchanges.size() ); + + // and process the result + { + unsigned idx = 0; + for_( it, result.begin(), result.end() ) + { + // Limit estimated waste (half block per file) as it does not apply to + // btrfs, which reports up to 64K blocksize (bsc#974275,bsc#965322) + static const ByteCount blockAdjust( 2, ByteCount::K ); // (files * blocksize) / 2 / 1K; result value in K! + + it->pkg_size = it->used_size // current usage + + duchanges[idx].kbytes // package data size + + ( duchanges[idx].files * ( it->fstype == "btrfs" ? 4096 : it->block_size ) / blockAdjust ); // half block per file + ++idx; + } + } + + return result; + } + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( const ResPool & pool_r ) const + { + Bitmap bitmap( Bitmap::poolSize ); + + // build installedmap (installed != transact) + // stays installed or gets installed + for_( it, pool_r.begin(), pool_r.end() ) + { + if ( it->status().isInstalled() != it->status().transacts() ) + { + bitmap.set( sat::asSolvable()(*it).id() ); + } + } + return calcDiskUsage( _mps, bitmap ); + } + + DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( sat::Solvable solv_r ) const + { + Bitmap bitmap( Bitmap::poolSize ); + bitmap.set( solv_r.id() ); + + // temp. unset @system Repo + DtorReset tmp( sat::Pool::instance().get()->installed ); + sat::Pool::instance().get()->installed = nullptr; + + return calcDiskUsage( _mps, bitmap ); + } + + DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( const Bitmap & bitmap_r ) const + { + // temp. unset @system Repo + DtorReset tmp( sat::Pool::instance().get()->installed ); + sat::Pool::instance().get()->installed = nullptr; + + return calcDiskUsage( _mps, bitmap_r ); + } + + DiskUsageCounter::MountPointSet DiskUsageCounter::detectMountPoints( const std::string & rootdir ) + { + DiskUsageCounter::MountPointSet ret; + + typedef std::map Btrfsfilter; + Btrfsfilter btrfsfilter; // see btrfs hack below + + std::ifstream procmounts( "/proc/mounts" ); + + if ( !procmounts ) { + WAR << "Unable to read /proc/mounts" << std::endl; + } else { + + std::string prfx; + if ( rootdir != "/" ) + prfx = rootdir; // rootdir not / + + while ( procmounts ) { + std::string l = str::getline( procmounts ); + if ( !(procmounts.fail() || procmounts.bad()) ) { + // data to consume + + // rootfs / rootfs rw 0 0 + // /dev/root / reiserfs rw 0 0 + // proc /proc proc rw 0 0 + // devpts /dev/pts devpts rw 0 0 + // /dev/hda5 /boot ext2 rw 0 0 + // shmfs /dev/shm shm rw 0 0 + // usbdevfs /proc/bus/usb usbdevfs rw 0 0 + + std::vector words; + str::split( l, std::back_inserter(words) ); + + if ( words.size() < 3 ) { + WAR << "Suspicious entry in /proc/mounts: " << l << std::endl; + continue; + } + + // + // Filter devices without '/' (proc,shmfs,..) + // + if ( words[0].find( '/' ) == std::string::npos ) { + DBG << "Discard mount point : " << l << std::endl; + continue; + } + + // remove /proc entry + if (words[0] == "/proc") + { + DBG << "Discard /proc filesystem: " << l << std::endl; + continue; + } + + // + // Filter mountpoints not at or below _rootdir + // + std::string mp = words[1]; + if ( prfx.size() ) { + if ( mp.compare( 0, prfx.size(), prfx ) != 0 ) { + // mountpoint not below rootdir + DBG << "Unwanted mount point : " << l << std::endl; + continue; + } + // strip prfx + mp.erase( 0, prfx.size() ); + if ( mp.empty() ) { + mp = "/"; + } else if ( mp[0] != '/' ) { + // mountpoint not below rootdir + DBG << "Unwanted mount point : " << l << std::endl; + continue; + } + } + + // + // Filter cdrom + // + if ( words[2] == "iso9660" ) { + DBG << "Discard cdrom : " << l << std::endl; + continue; + } + + if ( words[2] == "vfat" || words[2] == "fat" || words[2] == "ntfs" || words[2] == "ntfs-3g") + { + MIL << words[1] << " contains ignored fs (" << words[2] << ')' << std::endl; + continue; + } + + // + // Filter some common unwanted mountpoints + // + const char * mpunwanted[] = { + "/mnt", "/media", "/mounts", "/floppy", "/cdrom", + "/suse", "/tmp", "/var/tmp", "/var/adm/mount", "/var/adm/YaST", + /*last*/0/*entry*/ + }; + + const char ** nomp = mpunwanted; + for ( ; *nomp; ++nomp ) { + std::string pre( *nomp ); + if ( mp.compare( 0, pre.size(), pre ) == 0 // mp has prefix pre + && ( mp.size() == pre.size() || mp[pre.size()] == '/' ) ) { + break; + } + } + if ( *nomp ) { + DBG << "Filter mount point : " << l << std::endl; + continue; + } + + // + // Check whether mounted readonly + // + MountPoint::HintFlags hints; + + std::vector flags; + str::split( words[3], std::back_inserter(flags), "," ); + + for ( unsigned i = 0; i < flags.size(); ++i ) { + if ( flags[i] == "ro" ) { + hints |= MountPoint::Hint_readonly; + break; + } + } + if ( hints.testFlag( MountPoint::Hint_readonly ) ) { + DBG << "Filter ro mount point : " << l << std::endl; + continue; + } + + // + // check for snapshotting btrfs + // + bool btrfshack = false; + if ( words[2] == "btrfs" ) + { + btrfshack = true; + if ( geteuid() != 0 ) + { + DBG << "Assume snapshots on " << words[1] << ": non-root user can't check" << std::endl; + hints |= MountPoint::Hint_growonly; + } + else + { + // For now just check whether there is + // at least one snapshot on the volume: + ExternalProgram prog({"btrfs","subvolume","list","-s",words[1]}); + std::string line( prog.receiveLine() ); + if ( ! line.empty() ) + { + DBG << "Found a snapshot on " << words[1] << ": " << line; // has trailing std::endl + hints |= MountPoint::Hint_growonly; + } + prog.kill(); + } + } + + // + // statvfs (full path!) and get the data + // + struct statvfs sb; + if ( statvfs( words[1].c_str(), &sb ) != 0 ) { + WAR << "Unable to statvfs(" << words[1] << "); errno " << errno << std::endl; + ret.insert( DiskUsageCounter::MountPoint( mp, words[2], 0LL, 0LL, 0LL, 0LL, hints ) ); + } + else + { + // + // Filter zero sized devices (bnc#769819) + // + if ( sb.f_blocks == 0 || sb.f_bsize == 0 ) + { + DBG << "Filter zero-sized mount point : " << l << std::endl; + continue; + } + if ( btrfshack ) + { + // HACK: + // Collect just the top/1st mountpoint of each btrfs volume + // (by device). This filters away nested subvolumes + // which otherwise break per package disk usage computation. + // FIX: Computation must learn to handle multiple mount points + // contributing to the same file system. + MountPoint & bmp( btrfsfilter[words[0]] ); + if ( bmp.fstype.empty() ) // 1st occurance + { + bmp = DiskUsageCounter::MountPoint( mp, words[2], sb.f_bsize, + ((long long)sb.f_blocks)*sb.f_bsize/1024, + ((long long)(sb.f_blocks - sb.f_bfree))*sb.f_bsize/1024, 0LL, hints ); + } + else if ( bmp.dir > mp ) + bmp.dir = mp; + continue; + } + ret.insert( DiskUsageCounter::MountPoint( mp, words[2], sb.f_bsize, + ((long long)sb.f_blocks)*sb.f_bsize/1024, + ((long long)(sb.f_blocks - sb.f_bfree))*sb.f_bsize/1024, 0LL, hints ) ); + } + } + } + } + + // collect filtered btrfs volumes + for ( auto && bmp : btrfsfilter ) + ret.insert( std::move(bmp.second) ); + + return ret; + } + + DiskUsageCounter::MountPointSet DiskUsageCounter::justRootPartition() + { + DiskUsageCounter::MountPointSet ret; + ret.insert( DiskUsageCounter::MountPoint() ); + return ret; + } + + std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPoint & obj ) + { + str << "dir:[" << obj.dir << "] [ bs: " << obj.blockSize() + << " ts: " << obj.totalSize() + << " us: " << obj.usedSize() + << " (+-: " << obj.commitDiff() + << ")" << (obj.readonly?"r":"") << (obj.growonly?"g":"") << " " << obj.fstype << "]"; + return str; + } + + std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPointSet & obj ) + { return dumpRange( str, obj.begin(), obj.end() ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/DiskUsageCounter.h b/zypp/DiskUsageCounter.h new file mode 100644 index 0000000..be4c665 --- /dev/null +++ b/zypp/DiskUsageCounter.h @@ -0,0 +1,228 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/DiskUsageCounter.h + * +*/ +#ifndef ZYPP_DISKUSAGE_COUNTER_H +#define ZYPP_DISKUSAGE_COUNTER_H + +#include +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class DiskUsageCounter + /// \brief Compute disk space occupied by packages across partitions/directories + /////////////////////////////////////////////////////////////////// + class ZYPP_API DiskUsageCounter + { + + public: + /////////////////////////////////////////////////////////////////// + /// \class MountPoint + /// \brief Mount point description + /// If \ref block_size is set \ref DiskUsageCoutner will assume + /// half a block_size is wasted per file, in case a package + /// provides detailed isk usage information. + /////////////////////////////////////////////////////////////////// + struct MountPoint + { + friend std::ostream & operator<<( std::ostream & str, const MountPoint & obj ); + std::string dir; ///< Directory name + std::string fstype; ///< Filesystem type (provided by \ref detectMountPoints) + long long block_size; ///< Block size of the filesystem in B (0 if you don't care) + long long total_size; ///< Total size of the filesystem in KiB (0 if you don't care) + long long used_size; ///< Used size of the filesystem in KiB (0 if you don't care) + mutable long long pkg_size; ///< Used size after installation in KiB (computed by \ref DiskUsageCoutner) + // hint bits: + bool readonly:1; ///< hint for readonly partitions + bool growonly:1; ///< hint for growonly partitions (e.g. snapshotting btrfs) + + + /** HinFlags for ctor */ + enum Hint + { + NoHint = 0, + Hint_readonly = (1<<0), ///< readonly partitions + Hint_growonly = (1<<1), ///< growonly partitions (e.g. snapshotting btrfs) + }; + ZYPP_DECLARE_FLAGS(HintFlags,Hint); + + /** Ctor initialize directory, fstype and sizes */ + MountPoint( std::string d = "/", + std::string f = std::string(), + long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL, + HintFlags hints = NoHint ) + : dir(std::move(d)), fstype(std::move(f)) + , block_size(bs), total_size(total), used_size(used), pkg_size(pkg) + , readonly(hints.testFlag(Hint_readonly)) + , growonly(hints.testFlag(Hint_growonly)) + {} + /** \overload const char * to allow e.g. initiailzer lists + * \code + * MountPointSet( { "/", "/usr", "/var" } ) + * \endcode + */ + MountPoint( const char * d, + const std::string & f = std::string(), + long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL, + HintFlags hints = NoHint ) + : MountPoint( std::string(d?d:""), f, bs, total, used, pkg, hints ) + {} + + + /** Ctor initialize directory and sizes */ + MountPoint( const std::string & d, + long long bs, long long total = 0LL, long long used = 0LL, long long pkg = 0LL, + HintFlags hints = NoHint ) + : MountPoint( d, std::string(), bs, total, used, pkg, hints ) + {} + /** \overload const char * */ + MountPoint( const char * d, + long long bs, long long total = 0LL, long long used = 0LL, long long pkg = 0LL, + HintFlags hints = NoHint ) + : MountPoint( std::string(d?d:""), bs, total, used, pkg, hints ) + {} + + + /** Ctor just name and hints, all sizes 0 */ + MountPoint( const std::string & d, HintFlags hints ) + : MountPoint( d, std::string(), 0LL, 0LL, 0LL, 0LL, hints ) + {} + /** \overload const char * */ + MountPoint( const char * d, HintFlags hints ) + : MountPoint( std::string(d?d:""), hints ) + {} + /** \overload to prevent propagation Hint -> long long */ + MountPoint( const std::string & d, Hint hint ) + : MountPoint( d, HintFlags(hint) ) + {} + /** \overload to prevent propagation Hint -> long long */ + MountPoint( const char * d, Hint hint ) + : MountPoint( std::string(d?d:""), HintFlags(hint) ) + {} + + /** Sort by directory name */ + bool operator<( const MountPoint & rhs ) const + { return dir < rhs.dir; } + + /** Block size of the filesystem as \ref ByteCount for convenience. */ + ByteCount blockSize() const + { return ByteCount( block_size, ByteCount::B ); } + + /** Total size of the filesystem as \ref ByteCount for convenience. */ + ByteCount totalSize() const + { return ByteCount( total_size, ByteCount::K ); } + + /** Used size of the filesystem as \ref ByteCount for convenience. */ + ByteCount usedSize() const + { return ByteCount( used_size, ByteCount::K ); } + + /** Free size of the filesystem as \ref ByteCount for convenience. */ + ByteCount freeSize() const + { return ByteCount( total_size-used_size, ByteCount::K ); } + + /** Used size after installation as \ref ByteCount for convenience. */ + ByteCount usedAfterCommit() const + { return ByteCount( pkg_size, ByteCount::K ); } + + /** Free size after installation as \ref ByteCount for convenience. */ + ByteCount freeAfterCommit() const + { return ByteCount( total_size-pkg_size, ByteCount::K ); } + + /** Size change due to installation as \ref ByteCount for convenience. */ + ByteCount commitDiff() const + { return ByteCount( pkg_size-used_size, ByteCount::K ); } + }; + /////////////////////////////////////////////////////////////////// + + using MountPointSet = std::set; + + DiskUsageCounter() + {} + + /** Ctor taking the MountPointSet to compute */ + DiskUsageCounter( MountPointSet mps_r ) + : _mps(std::move( mps_r )) + {} + + /** Set a MountPointSet to compute */ + void setMountPoints( const MountPointSet & mps_r ) + { _mps = mps_r; } + + /** Get the current MountPointSet */ + const MountPointSet & getMountPoints() const + { return _mps; } + + /** Get mountpoints of system below \a rootdir + * If we happen to detect snapshotting btrfs partitions, the MountPoint::growonly + * hint is set. Disk usage computation will assume that deleted packages will not + * free any space (kept in a snapshot). + */ + static MountPointSet detectMountPoints( const std::string & rootdir = "/" ); + + /** Only one entry for "/" to collect total sizes */ + static MountPointSet justRootPartition(); + + + /** Compute disk usage if the current transaction woud be commited. */ + MountPointSet disk_usage( const ResPool & pool ) const; + + /** Compute disk usage of a single Solvable */ + MountPointSet disk_usage( sat::Solvable solv_r ) const; + /** \overload for PoolItem */ + MountPointSet disk_usage( const PoolItem & pi_r ) const + { return disk_usage( sat::asSolvable()( pi_r ) ); } + /** \overload for ResObject */ + MountPointSet disk_usage( const ResObject::constPtr & obj_r ) const + { return disk_usage( sat::asSolvable()( obj_r ) ); } + + /** Compute disk usage of a collection defined by a solvable bitmap. */ + MountPointSet disk_usage( const Bitmap & bitmap_r ) const; + + /** Compute disk usage of a collection (convertible by \ref asSolvable). */ + template + MountPointSet disk_usage( Iterator begin_r, Iterator end_r ) const + { + Bitmap bitmap( Bitmap::poolSize ); + for_( it, begin_r, end_r ) + bitmap.set( sat::asSolvable()( *it ).id() ); + return disk_usage( bitmap ); + } + + private: + MountPointSet _mps; + }; + /////////////////////////////////////////////////////////////////// + + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(DiskUsageCounter::MountPoint::HintFlags); + + /** \relates DiskUsageCounter::MountPoint Stream output */ + std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPoint & obj ) ZYPP_API; + + /** \relates DiskUsageCounter::MountPointSet Stream output */ + std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPointSet & obj ) ZYPP_API; + + /** \relates DiskUsageCounter Stream output */ + inline std::ostream & operator<<( std::ostream & str, const DiskUsageCounter & obj ) + { return str << obj.getMountPoints(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_DISKUSAGE_COUNTER_H diff --git a/zypp/DownloadMode.cc b/zypp/DownloadMode.cc new file mode 100644 index 0000000..eb007ff --- /dev/null +++ b/zypp/DownloadMode.cc @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/DownloadMode.cc + * +*/ +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + bool deserialize( const std::string & str_r, DownloadMode & result_r ) + { +#define OUTS(VAL) if ( str::compareCI( str_r, #VAL ) == 0 ) { result_r = VAL; return true; } + OUTS( DownloadOnly ); + OUTS( DownloadInAdvance ); + OUTS( DownloadInHeaps ); + OUTS( DownloadAsNeeded ); +#undef OUTS + return false; + } + + std::ostream & operator<<( std::ostream & str, DownloadMode obj ) + { + switch ( obj ) + { +#define OUTS(VAL) case VAL: return str << #VAL; break + OUTS( DownloadDefault ); + OUTS( DownloadOnly ); + OUTS( DownloadInAdvance ); + OUTS( DownloadInHeaps ); + OUTS( DownloadAsNeeded ); +#undef OUTS + } + return str << "DownloadMode(" << int(obj) << ")"; + } + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/DownloadMode.h b/zypp/DownloadMode.h new file mode 100644 index 0000000..ff26325 --- /dev/null +++ b/zypp/DownloadMode.h @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/DownloadMode.h + * +*/ +#ifndef ZYPP_DOWNLOADMODE_H +#define ZYPP_DOWNLOADMODE_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Supported commit download policies. */ + enum DownloadMode + { + DownloadDefault, //!< libzypp will decide what to do. + DownloadOnly, //!< Just download all packages to the local cache. + //!< Do not install. Implies a dry-run. + DownloadInAdvance, //!< First download all packages to the local cache. + //!< Then start to install. + DownloadInHeaps, //!< Similar to DownloadInAdvance, but try to split + //!< the transaction into heaps, where at the end of + //!< each heap a consistent system state is reached. + DownloadAsNeeded //!< Alternating download and install. Packages are + //!< cached just to avid CD/DVD hopping. This is the + //!< traditional behaviour. + }; + + /** \relates DownloadMode Parse from string. + * On success the \ref DownloadMode is returned via \a result_r, + * and the function returns \c true. Otherwise it returns \c false + * and \a result_r remains unchanged. + */ + bool deserialize( const std::string & str_r, DownloadMode & result_r ); + + /** \relates DownloadMode Parse from string. + * Similar as \ref deserialize, but silently return \ref DownloadDefault + * in case of a parse error. + */ + inline DownloadMode deserializeDownloadMode( const std::string & str_r ) + { + DownloadMode ret( DownloadDefault ); + deserialize( str_r, ret ); + return ret; + } + + /** \relates DownloadMode Stream output. */ + std::ostream & operator<<( std::ostream & str, DownloadMode obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_DOWNLOADMODE_H diff --git a/zypp/Edition.cc b/zypp/Edition.cc new file mode 100644 index 0000000..f938a55 --- /dev/null +++ b/zypp/Edition.cc @@ -0,0 +1,138 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Edition.cc + * +*/ +extern "C" +{ +#include +} +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + inline std::string makeevrstr( const std::string & version_r, + const std::string & release_r, + Edition::epoch_t epoch_r ) + { + std::string ret( version_r ); + if ( ! release_r.empty() ) + { + ret += "-"; + ret += release_r; + } + return ( epoch_r ? str::numstring( epoch_r ) + ":" + ret + : ret ); + } + + inline std::string makeevrstr( const char * version_r, + const char * release_r, + Edition::epoch_t epoch_r ) + { return makeevrstr( std::string(version_r?version_r:""), + std::string(release_r?release_r:""), + epoch_r ); + } + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + const Edition Edition::noedition; + + /////////////////////////////////////////////////////////////////// + + Edition::Edition( const std::string & version_r, + const std::string & release_r, + epoch_t epoch_r ) + : _str( makeevrstr( version_r, release_r, epoch_r ) ) + {} + + Edition::Edition( const char * version_r, + const char * release_r, + epoch_t epoch_r ) + : _str( makeevrstr( version_r, release_r, epoch_r ) ) + {} + + Edition::Edition( const std::string & version_r, + const std::string & release_r, + const std::string & epoch_r ) + : _str( makeevrstr( version_r, release_r, str::strtonum( epoch_r ) ) ) + {} + + Edition::Edition( const char * version_r, + const char * release_r, + const char * epoch_r ) + : _str( makeevrstr( version_r, release_r, str::strtonum( epoch_r ) ) ) + {} + + Edition::epoch_t Edition::epoch() const + { + const char * str( c_str() ); + const char * sep = str; + // skip edition + for ( ; *sep >= '0' && *sep <= '9'; ++sep ) + ; // NOOP + if ( *sep == ':' ) + return str::strtonum( std::string( str, sep-str ) ); + return 0; + } + + std::string Edition::version() const + { + const char * str( c_str() ); + const char * sep = str; + // skip edition + for ( ; *sep >= '0' && *sep <= '9'; ++sep ) + ; // NOOP + if ( *sep == ':' ) + str = sep+1; + // strip release + sep = ::strrchr( str, '-' ); + if ( sep ) + return std::string( str, sep-str ); + return str; + } + + std::string Edition::release() const + { + const char * str( c_str() ); + const char * sep = ::strrchr( str, '-' ); + // get release + if ( sep ) + return sep+1; + return std::string(); + } + + int Edition::_doCompare( const char * lhs, const char * rhs ) + { + if ( lhs == rhs ) return 0; + if ( lhs && rhs ) return ::pool_evrcmp_str( myPool().getPool(), lhs, rhs, EVRCMP_COMPARE ); + return( lhs ? 1 : -1 ); + } + + int Edition::_doMatch( const char * lhs, const char * rhs ) + { + if ( lhs == rhs ) return 0; + if ( lhs && rhs ) return ::pool_evrcmp_str( myPool().getPool(), lhs, rhs, EVRCMP_MATCH ); + return( lhs ? 1 : -1 ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + + diff --git a/zypp/Edition.h b/zypp/Edition.h new file mode 100644 index 0000000..fe4d2ed --- /dev/null +++ b/zypp/Edition.h @@ -0,0 +1,193 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Edition.h + * +*/ +#ifndef ZYPP_EDITION_H +#define ZYPP_EDITION_H + +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Edition + // + /** Edition represents [epoch:]version[-release] + * + * \li \c epoch (optional) number, Edition::noepoch if not supplied + * \li \c version (required) string, may not contain '-' + * \li \c release (optional) string, may not contain '-' + * + * Comparison is actually \reg g_BackendSpecific. + * + * \li \b RPM: Edition are ordered according to \c epoch, then \c version, + * then \c release. Version and release strings are compared by splitting + * them into segments of alpha or digit sequences. Segments are compared + * according to their type. On mixed types a string compares less than a + * number. + * \code + * compare( 1.a, 1.0 ) == -1 (<) + * compare( 1.0, 1.a ) == 1 (>) + * compare( 1.0, 1_0 ) == 0 (==) + * \endcode + * + * \attention operator< defines equivalence classes of version strings, as non + * alphanumeric chars are ignored. That' why \c 1.0 and \c 1_0 compare equal + * in the example.
+ * + * \attention Edition::match compares two editions, treating empty + * version or release strings as wildcard. Thus match is not transitive, + * and you don't want to use it to order keys in a a std::container. + * + * \ingroup g_BackendSpecific + */ + class ZYPP_API Edition : public IdStringType + { + public: + /** Type of an epoch. */ + using epoch_t = unsigned int; + + /** Value representing \c noepoch. */ + static const epoch_t noepoch = 0; + + /** Value representing \c noedition ("") + * This is in fact a valid Edition. It's what the default ctor + * creates or will be parsed from an empty string. + */ + static const Edition noedition; + + public: + /** Default ctor: \ref noedition. */ + Edition() {} + + /** Ctor taking edition as string. */ + explicit Edition( IdString::IdType id_r ) : _str( id_r ) {} + explicit Edition( const IdString & idstr_r ) : _str( idstr_r ) {} + explicit Edition( const std::string & str_r ) : _str( str_r ) {} + explicit Edition( const char * cstr_r ) : _str( cstr_r ) {} + + /** Ctor taking \a version_r, \a release_r and optional \a epoch_r */ + Edition( const std::string & version_r, + const std::string & release_r, + epoch_t epoch_r = noepoch ); + /** \overload */ + Edition( const char * version_r, + const char * release_r, + epoch_t epoch_r = noepoch ); + + /** Ctor taking \a version_r, \a release_r and optional \a epoch_r as string. */ + Edition( const std::string & version_r, + const std::string & release_r, + const std::string & epoch_r ); + /** \overload */ + Edition( const char * version_r, + const char * release_r, + const char * epoch_r ); + + public: + /** Epoch */ + epoch_t epoch() const; + + /** Version */ + std::string version() const; + + /** Release */ + std::string release() const; + + public: + /** \ref compare functor. + * \see \ref RelCompare. + */ + using Compare = zypp::Compare; + + /** \ref Edition \ref Range based on \ref Compare. + * \see \ref RelCompare. + */ + using CompareRange = Range; + + public: + /** \name Match two Editions + * Match two Editions returning -1,0,1, treating empty + * version/release strings as \c ANY. + */ + //@{ + static int match( const Edition & lhs, const Edition & rhs ) { return match( lhs.idStr(), rhs.idStr() ); } + static int match( const Edition & lhs, const IdString & rhs ) { return match( lhs.idStr(), rhs ); } + static int match( const Edition & lhs, const std::string & rhs ) { return _doMatch( lhs.c_str(), rhs.c_str() ); } + static int match( const Edition & lhs, const char * rhs ) { return _doMatch( lhs.c_str(), rhs );} + + static int match( const IdString & lhs, const Edition & rhs ) { return match( lhs, rhs.idStr() ); } + static int match( const IdString & lhs, const IdString & rhs ) { return lhs.compareEQ( rhs ) ? 0 : + _doMatch( lhs.c_str(), rhs.c_str() ); } + static int match( const IdString & lhs, const std::string & rhs ) { return _doMatch( lhs.c_str(), rhs.c_str() ); } + static int match( const IdString & lhs, const char * rhs ) { return _doMatch( lhs.c_str(), rhs ); } + + static int match( const std::string & lhs, const Edition & rhs ) { return _doMatch( lhs.c_str(), rhs.c_str() );} + static int match( const std::string & lhs, const IdString & rhs ) { return _doMatch( lhs.c_str(), rhs.c_str() ); } + static int match( const std::string & lhs, const std::string & rhs ) { return _doMatch( lhs.c_str(), rhs.c_str() ); } + static int match( const std::string & lhs, const char * rhs ) { return _doMatch( lhs.c_str(), rhs ); } + + static int match( const char * lhs, const Edition & rhs ) { return _doMatch( lhs, rhs.c_str() );} + static int match( const char * lhs, const IdString & rhs ) { return _doMatch( lhs, rhs.c_str() ); } + static int match( const char * lhs, const std::string & rhs ) { return _doMatch( lhs, rhs.c_str() ); } + static int match( const char * lhs, const char * rhs ) { return _doMatch( lhs, rhs ); } + + int match( const Edition & rhs ) const { return match( idStr(), rhs.idStr() ); } + int match( const IdString & rhs ) const { return match( idStr(), rhs ); } + int match( const std::string & rhs ) const { return _doMatch( c_str(), rhs.c_str() ); } + int match( const char * rhs ) const { return _doMatch( c_str(), rhs ); } + //@} + + /** \ref match functor. + * \see \ref RelCompare. + */ + struct Match + { + int operator()( const Edition & lhs, const Edition & rhs ) const + { return Edition::match( lhs, rhs ); } + }; + + /** \ref Edition \ref Range based on \ref Match. + * \see \ref RelCompare. + */ + using MatchRange = Range; + + private: + static int _doCompare( const char * lhs, const char * rhs ) ZYPP_API; + static int _doMatch( const char * lhs, const char * rhs ); + + private: + friend class IdStringType; + IdString _str; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Edition XML output. */ + inline std::ostream & dumpAsXmlOn( std::ostream & str, const Edition & obj ) + { return str << ""; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_EDITION_H diff --git a/zypp/ExternalProgram.h b/zypp/ExternalProgram.h new file mode 100644 index 0000000..806a71a --- /dev/null +++ b/zypp/ExternalProgram.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Fetcher.cc b/zypp/Fetcher.cc new file mode 100644 index 0000000..df1a5c0 --- /dev/null +++ b/zypp/Fetcher.cc @@ -0,0 +1,934 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Fetcher.cc + * +*/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::fetcher" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** + * class that represents indexes which add metadata + * to fetcher jobs and therefore need to be retrieved + * in advance. + */ + struct FetcherIndex + { + FetcherIndex( const OnMediaLocation &loc ) + : location(loc) + {} + /** Index localtion. */ + OnMediaLocation location; + /** Whether we read this index. */ + DefaultIntegral read; + }; + + using FetcherIndex_Ptr = shared_ptr; + + /** std::set ordering (less semantic) */ + struct SameFetcherIndex + { + bool operator()( const FetcherIndex_Ptr & lhs, const FetcherIndex_Ptr & rhs ) const + { + if ( lhs == rhs ) + return false; // incl. NULL == NULL + if ( ! lhs ) + return true; // NULL < nonNULL + if ( ! rhs ) + return false; // nonNULL > NULL + // both nonNULL ==> compare medianr and path + if ( lhs->location.medianr() == rhs->location.medianr() ) + return lhs->location.filename() < rhs->location.filename(); + //else + return lhs->location.medianr() < rhs->location.medianr(); + } + }; + + /** + * Class to encapsulate the \ref OnMediaLocation object + * and the \ref FileChecker together + */ + struct FetcherJob + { + enum Flag + { + None = 0x0000, + Directory = 0x0001, + Recursive = 0x0002, + RecursiveDirectory = Directory | Recursive, + // check checksums even if there is no such + // checksum (warns of no checksum) + AlwaysVerifyChecksum = 0x0004, + }; + ZYPP_DECLARE_FLAGS(Flags, Flag); + + FetcherJob(const FetcherJob &) = default; + FetcherJob(FetcherJob &&) = default; + FetcherJob &operator=(const FetcherJob &) = default; + FetcherJob &operator=(FetcherJob &&) = default; + + FetcherJob(const OnMediaLocation &loc) : location(loc), flags(None) { + //MIL << location << endl; + } + + ~FetcherJob() + { + //MIL << location << " | * " << checkers.size() << endl; + } + + OnMediaLocation location; + //CompositeFileChecker checkers; + std::list checkers; + Flags flags; + }; + + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(FetcherJob::Flags); + using FetcherJob_Ptr = shared_ptr; + + std::ostream & operator<<( std::ostream & str, const FetcherJob_Ptr & obj ) + { + return str << obj->location; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Fetcher::Impl + // + /** Fetcher implementation. */ + class Fetcher::Impl + { + friend std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj ); + + public: + Impl(); + + Impl(const Impl &) = default; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() {} + + void setOptions( Fetcher::Options options ); + Fetcher::Options options() const; + + void addIndex( const OnMediaLocation &resource ); + + void enqueueDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() ); + void enqueueDigestedDir( const OnMediaLocation &resource, bool recursive, const FileChecker &checker = FileChecker() ); + + void enqueue( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() ); + void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() ); + void addCachePath( const Pathname &cache_dir ); + void reset(); + void setMediaSetAccess ( MediaSetAccess &media ); + void start( const Pathname &dest_dir, + const ProgressData::ReceiverFnc &progress ); + void start( const Pathname &dest_dir, + MediaSetAccess &media, + const ProgressData::ReceiverFnc & progress_receiver ); + + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + private: + /** + * download the indexes and reads them + */ + void downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir); + + /** + * download the indexes and reads them + */ + void downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir); + + /** + * reads a downloaded index file and updates internal + * attributes table + * + * The index lists files relative to a directory, which is + * normally the same as the index file is located. + */ + void readIndex( const Pathname &index, const Pathname &basedir ); + + /** specific version of \ref readIndex for CHECKSUMS file */ + void readChecksumsIndex( const Pathname &index, const Pathname &basedir ); + + /** specific version of \ref readIndex for content file */ + void readContentFileIndex( const Pathname &index, const Pathname &basedir ); + + /** reads the content of a directory but keeps a cache **/ + void getDirectoryContent( MediaSetAccess &media, const OnMediaLocation &resource, filesystem::DirContent &content ); + + /** + * Tries to locate the file represented by job by looking at + * the cache (matching checksum is mandatory). Returns the + * location of the cached file or an empty \ref Pathname. + */ + Pathname locateInCache( const OnMediaLocation & resource_r, const Pathname & destDir_r ); + /** + * Validates the provided file against its checkers. + * \throws Exception + */ + void validate( const Pathname & localfile_r, const std::list & checkers_r ); + + /** + * scan the directory and adds the individual jobs + */ + void addDirJobs( MediaSetAccess &media, const OnMediaLocation &resource, + const Pathname &dest_dir, FetcherJob::Flags flags ); + + /** + * auto discovery and reading of indexes + */ + void autoaddIndexes( const filesystem::DirContent &content, + MediaSetAccess &media, + const OnMediaLocation &resource, + const Pathname &dest_dir ); + /** + * Provide the resource to \ref dest_dir + */ + void provideToDest( MediaSetAccess & media_r, const Pathname & destDir_r , const FetcherJob_Ptr & jobp_r ); + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + + std::list _resources; + std::set _indexes; + std::set _caches; + // checksums read from the indexes + std::map _checksums; + // cache of dir contents + std::map _dircontent; + + MediaSetAccess * _mediaSetAccess = nullptr; + + Fetcher::Options _options; + }; + /////////////////////////////////////////////////////////////////// + + void Fetcher::Impl::enqueueDigested( const OnMediaLocation &resource, const FileChecker & ) + { + if ( _mediaSetAccess ) + _mediaSetAccess->precacheFiles( {resource} ); + + FetcherJob_Ptr job; + job.reset(new FetcherJob(resource)); + job->flags |= FetcherJob:: AlwaysVerifyChecksum; + _resources.push_back(job); + } + + Fetcher::Impl::Impl() + : _options(0) + { + } + + void Fetcher::Impl::setOptions( Fetcher::Options options ) + { _options = options; } + + Fetcher::Options Fetcher::Impl::options() const + { return _options; } + + void Fetcher::Impl::enqueueDir( const OnMediaLocation &resource, + bool recursive, + const FileChecker &checker ) + { + FetcherJob_Ptr job; + job.reset(new FetcherJob(resource)); + if ( checker ) + job->checkers.push_back(checker); + if ( recursive ) + job->flags |= FetcherJob::Recursive; + job->flags |= FetcherJob::Directory; + + _resources.push_back(job); + } + + void Fetcher::Impl::enqueueDigestedDir( const OnMediaLocation &resource, + bool recursive, + const FileChecker &checker ) + { + FetcherJob_Ptr job; + job.reset(new FetcherJob(resource)); + if ( checker ) + job->checkers.push_back(checker); + if ( recursive ) + job->flags |= FetcherJob::Recursive; + job->flags |= FetcherJob::Directory; + job->flags |= FetcherJob::AlwaysVerifyChecksum; + + _resources.push_back(job); + + } + + void Fetcher::Impl::enqueue( const OnMediaLocation &resource, const FileChecker &checker ) + { + if ( _mediaSetAccess ) + _mediaSetAccess->precacheFiles( {resource} ); + + FetcherJob_Ptr job; + job.reset(new FetcherJob(resource)); + if ( checker ) + job->checkers.push_back(checker); + _resources.push_back(job); + } + + void Fetcher::Impl::addIndex( const OnMediaLocation &resource ) + { + MIL << "adding index " << resource << endl; + _indexes.insert(FetcherIndex_Ptr(new FetcherIndex(resource))); + } + + + void Fetcher::Impl::reset() + { + _resources.clear(); + _indexes.clear(); + _checksums.clear(); + _dircontent.clear(); + } + + void Fetcher::Impl::setMediaSetAccess( MediaSetAccess &media ) + { + _mediaSetAccess = &media; + } + + void Fetcher::Impl::addCachePath( const Pathname &cache_dir ) + { + PathInfo info(cache_dir); + if ( info.isExist() ) + { + if ( info.isDir() ) + { + DBG << "Adding fetcher cache: '" << cache_dir << "'." << endl; + _caches.insert(cache_dir); + } + else + { + // don't add bad cache directory, just log the error + ERR << "Not adding cache: '" << cache_dir << "'. Not a directory." << endl; + } + } + else + { + ERR << "Not adding cache '" << cache_dir << "'. Path does not exists." << endl; + } + + } + + Pathname Fetcher::Impl::locateInCache( const OnMediaLocation & resource_r, const Pathname & destDir_r ) + { + Pathname ret; + // No checksum - no match + if ( resource_r.checksum().empty() ) + return ret; + + // first check in the destination directory + Pathname cacheLocation = destDir_r / resource_r.filename(); + if ( PathInfo(cacheLocation).isExist() && is_checksum( cacheLocation, resource_r.checksum() ) ) + { + swap( ret, cacheLocation ); + return ret; + } + + MIL << "start fetcher with " << _caches.size() << " cache directories." << endl; + for( const Pathname & cacheDir : _caches ) + { + cacheLocation = cacheDir / resource_r.filename(); + if ( PathInfo(cacheLocation).isExist() && is_checksum( cacheLocation, resource_r.checksum() ) ) + { + MIL << "file " << resource_r.filename() << " found in cache " << cacheDir << endl; + swap( ret, cacheLocation ); + return ret; + } + } + + return ret; + } + + void Fetcher::Impl::validate( const Pathname & localfile_r, const std::list & checkers_r ) + { + try + { + MIL << "Checking job [" << localfile_r << "] (" << checkers_r.size() << " checkers )" << endl; + + for ( const FileChecker & chkfnc : checkers_r ) + { + if ( chkfnc ) + chkfnc( localfile_r ); + else + ERR << "Invalid checker for '" << localfile_r << "'" << endl; + } + + } + catch ( const FileCheckException &e ) + { + throw; // let known exceptions bypass silently + } + catch ( const Exception &e ) + { + throw; // slet known exceptions bypass silently + } + catch (...) + { + ZYPP_THROW(Exception("Unknown error while validating " + localfile_r.asString())); + } + } + + void Fetcher::Impl::autoaddIndexes( const filesystem::DirContent &content, + MediaSetAccess &media, + const OnMediaLocation &resource, + const Pathname &dest_dir ) + { + auto fnc_addIfInContent( [&]( const std::string & index_r ) -> bool + { + if ( find( content.begin(), content.end(), filesystem::DirEntry(index_r,filesystem::FT_FILE) ) == content.end() ) + return false; + // add the index of this directory + OnMediaLocation indexloc( resource ); + indexloc.changeFilename( resource.filename() + index_r ); + addIndex( indexloc ); + // we need to read it now + downloadAndReadIndexList( media, dest_dir ); + return true; + } ); + + if ( _options & AutoAddChecksumsIndexes ) + { + fnc_addIfInContent( "CHECKSUMS" ) || fnc_addIfInContent( "SHA1SUMS" ); + } + if ( _options & AutoAddContentFileIndexes ) + { + fnc_addIfInContent( "content" ); + } + } + + void Fetcher::Impl::getDirectoryContent( MediaSetAccess &media, + const OnMediaLocation &resource, + filesystem::DirContent &content ) + { + if ( _dircontent.find(resource.filename().asString()) + != _dircontent.end() ) + { + filesystem::DirContent filled(_dircontent[resource.filename().asString()]); + + std::copy(filled.begin(), filled.end(), std::back_inserter(content)); + } + else + { + filesystem::DirContent tofill; + media.dirInfo( tofill, + resource.filename(), + false /* dots */, + resource.medianr()); + std::copy(tofill.begin(), tofill.end(), std::back_inserter(content)); + _dircontent[resource.filename().asString()] = tofill; + } + } + + void Fetcher::Impl::addDirJobs( MediaSetAccess &media, + const OnMediaLocation &resource, + const Pathname &dest_dir, FetcherJob::Flags flags ) + { + // first get the content of the directory so we can add + // individual transfer jobs + MIL << "Adding directory " << resource.filename() << endl; + filesystem::DirContent content; + try { + getDirectoryContent(media, resource, content); + } + catch ( media::MediaFileNotFoundException & exception ) + { + ZYPP_CAUGHT( exception ); + WAR << "Skipping subtree hidden at " << resource.filename() << endl; + return; + } + + // this method test for the option flags so indexes are added + // only if the options are enabled + autoaddIndexes(content, media, resource, dest_dir); + + for ( filesystem::DirContent::const_iterator it = content.begin(); + it != content.end(); + ++it ) + { + // skip CHECKSUMS* as they were already retrieved + if ( str::hasPrefix(it->name, "CHECKSUMS") || str::hasPrefix(it->name, "SHA1SUMS") ) + continue; + + Pathname filename = resource.filename() + it->name; + + switch ( it->type ) + { + case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all + case filesystem::FT_FILE: + { + CheckSum chksm(resource.checksum()); + if ( _checksums.find(filename.asString()) != _checksums.end() ) + { + // the checksum can be replaced with the one in the index. + chksm = _checksums[filename.asString()]; + //MIL << "resource " << filename << " has checksum in the index file." << endl; + } + else + WAR << "Resource " << filename << " has no checksum in the index either." << endl; + + if ( flags & FetcherJob::AlwaysVerifyChecksum ) + enqueueDigested(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm)); + else + enqueue(OnMediaLocation(filename, resource.medianr()).setChecksum(chksm)); + break; + } + case filesystem::FT_DIR: // newer directory.yast contain at least directory info + if ( flags & FetcherJob::Recursive ) + addDirJobs(media, filename, dest_dir, flags); + break; + default: + // don't provide devices, sockets, etc. + break; + } + } + } + + void Fetcher::Impl::provideToDest( MediaSetAccess & media_r, const Pathname & destDir_r , const FetcherJob_Ptr & jobp_r ) + { + const OnMediaLocation & resource( jobp_r->location ); + + try + { + scoped_ptr releaseFileGuard; // will take care provided files get released + + // get cached file (by checksum) or provide from media + Pathname tmpFile = locateInCache( resource, destDir_r ); + if ( tmpFile.empty() ) + { + MIL << "Not found in cache, retrieving..." << endl; + tmpFile = media_r.provideFile( resource, resource.optional() ? MediaSetAccess::PROVIDE_NON_INTERACTIVE : MediaSetAccess::PROVIDE_DEFAULT ); + releaseFileGuard.reset( new MediaSetAccess::ReleaseFileGuard( media_r, resource ) ); // release it when we leave the block + } + + // The final destination: locateInCache also checks destFullPath! + // If we find a cache match (by checksum) at destFullPath, take + // care it gets deleted, in case the validation fails. + ManagedFile destFullPath( destDir_r / resource.filename() ); + if ( tmpFile == destFullPath ) + destFullPath.setDispose( filesystem::unlink ); + + // validate the file (throws if not valid) + validate( tmpFile, jobp_r->checkers ); + + // move it to the final destination + if ( tmpFile == destFullPath ) + destFullPath.resetDispose(); // keep it! + else + { + if ( assert_dir( destFullPath->dirname() ) != 0 ) + ZYPP_THROW( Exception( "Can't create " + destFullPath->dirname().asString() ) ); + + if ( filesystem::hardlinkCopy( tmpFile, destFullPath ) != 0 ) + ZYPP_THROW( Exception( "Can't hardlink/copy " + tmpFile.asString() + " to " + destDir_r.asString() ) ); + } + } + catch ( Exception & excpt ) + { + if ( resource.optional() ) + { + ZYPP_CAUGHT( excpt ); + WAR << "optional resource " << resource << " could not be transferred." << endl; + return; + } + else + { + excpt.remember( "Can't provide " + resource.filename().asString() ); + ZYPP_RETHROW( excpt ); + } + } + } + + // helper class to consume a content file + struct ContentReaderHelper : public parser::susetags::ContentFileReader + { + ContentReaderHelper() + { + setRepoIndexConsumer( bind( &ContentReaderHelper::consumeIndex, this, _1 ) ); + } + + void consumeIndex( const parser::susetags::RepoIndex_Ptr & data_r ) + { _repoindex = data_r; } + + parser::susetags::RepoIndex_Ptr _repoindex; + }; + + // generic function for reading indexes + void Fetcher::Impl::readIndex( const Pathname &index, const Pathname &basedir ) + { + if ( index.basename() == "CHECKSUMS" || index.basename() == "SHA1SUMS" ) + readChecksumsIndex(index, basedir); + else if ( index.basename() == "content" ) + readContentFileIndex(index, basedir); + else + WAR << index << ": index file format not known" << endl; + } + + // reads a content file index + void Fetcher::Impl::readContentFileIndex( const Pathname &index, const Pathname &basedir ) + { + ContentReaderHelper reader; + reader.parse(index); + MIL << index << " contains " << reader._repoindex->mediaFileChecksums.size() << " checksums." << endl; + for_( it, reader._repoindex->mediaFileChecksums.begin(), reader._repoindex->mediaFileChecksums.end() ) + { + // content file entries don't start with / + _checksums[(basedir + it->first).asString()] = it->second; + } + } + + // reads a CHECKSUMS (old SHA1SUMS) file index + void Fetcher::Impl::readChecksumsIndex( const Pathname &index, const Pathname &basedir ) + { + std::ifstream in( index.c_str() ); + if ( ! in.fail() ) + { + std::string buffer; + while ( getline( in, buffer ) ) + { + + if ( buffer[0] == '#' ) + continue; // simple comment + + CheckSum checksum( str::stripFirstWord( buffer, /*ltrim before strip*/true ) ); + if ( checksum.empty() ) + continue; // empty line | unknown cheksum format + + if ( buffer.empty() ) + { + WAR << "Missing filename in CHECKSUMS file: " << index.asString() << " (" << checksum << ")" << endl; + continue; + } + + _checksums[(basedir/buffer).asString()] = checksum; + } + } + else + ZYPP_THROW(Exception("Can't open CHECKSUMS file: " + index.asString())); + } + + void Fetcher::Impl::downloadIndex( MediaSetAccess &media, const OnMediaLocation &resource, const Pathname &dest_dir) + { + MIL << "downloading index " << resource << endl; + // create a new fetcher with a different state to transfer the + // file containing checksums and its signature + Fetcher fetcher; + // signature checker for index. We havent got the signature from + // the nextwork yet. + SignatureFileChecker sigchecker; + + // build the name of the index and the signature + const OnMediaLocation& idxloc(resource); + OnMediaLocation sigloc(resource); + OnMediaLocation keyloc(resource); + + // we should not fail the download if those don't exists + // the checking will warn later + sigloc.setOptional(true); + keyloc.setOptional(true); + + // calculate signature and key name + sigloc.changeFilename( sigloc.filename().extend(".asc") ); + keyloc.changeFilename( keyloc.filename().extend(".key") ); + + //assert_dir(dest_dir + idxloc.filename().dirname()); + + // transfer the signature + fetcher.enqueue(sigloc); + fetcher.start( dest_dir, media ); + // if we get the signature, update the checker + if ( PathInfo(dest_dir + sigloc.filename()).isExist() ) + sigchecker = SignatureFileChecker(dest_dir + sigloc.filename()); + + fetcher.reset(); + + // now the key + fetcher.enqueue(keyloc); + fetcher.start( dest_dir, media ); + fetcher.reset(); + + // try to import the key + if ( PathInfo(dest_dir + keyloc.filename()).isExist() ) + getZYpp()->keyRing()->importKey(PublicKey(dest_dir + keyloc.filename()), false); + else + WAR << "No public key specified by user for index '" << keyloc.filename() << "'"<< endl; + + // now the index itself + fetcher.enqueue( idxloc, FileChecker(sigchecker) ); + fetcher.start( dest_dir, media ); + fetcher.reset(); + } + + // this method takes all the user pointed indexes, gets them and also tries to + // download their signature, and verify them. After that, it parses each one + // to fill the checksum cache. + void Fetcher::Impl::downloadAndReadIndexList( MediaSetAccess &media, const Pathname &dest_dir) + { + // if there is no indexes, then just return to avoid + // the directory listing + if ( _indexes.empty() ) + { + MIL << "No indexes to read." << endl; + return; + } + + for_( it_idx, _indexes.begin(), _indexes.end() ) + { + if ( (*it_idx)->read ) + { + DBG << "Already read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl; + } + else + { + // base::LogControl::TmpLineWriter shutUp; + downloadIndex( media, (*it_idx)->location, dest_dir ); + // now we have the indexes in dest_dir + readIndex( dest_dir + (*it_idx)->location.filename(), (*it_idx)->location.filename().dirname() ); + // Take care we don't process it again + MIL << "Remember read index " << PathInfo(dest_dir + (*it_idx)->location.filename()) << endl; + (*it_idx)->read = true; + } + } + MIL << "done reading indexes" << endl; + } + + void Fetcher::Impl::start( const Pathname &dest_dir, + const ProgressData::ReceiverFnc & progress ) + { + if ( !_mediaSetAccess ) + ZYPP_THROW( zypp::Exception("Called Fetcher::start without setting MediaSetAccess before.") ); + start( dest_dir, *_mediaSetAccess, progress ); + } + + // start processing all fetcher jobs. + // it processes any user pointed index first + void Fetcher::Impl::start( const Pathname &dest_dir, + MediaSetAccess &media, + const ProgressData::ReceiverFnc & progress_receiver ) + { + _mediaSetAccess = nullptr; //reset the internally stored MediaSetAccess + + ProgressData progress(_resources.size()); + progress.sendTo(progress_receiver); + + downloadAndReadIndexList(media, dest_dir); + + for ( const FetcherJob_Ptr & jobp : _resources ) + { + if ( jobp->flags & FetcherJob::Directory ) + { + const OnMediaLocation location(jobp->location); + addDirJobs(media, location, dest_dir, jobp->flags); + continue; + } + + // may be this code can be factored out + // together with the autodiscovery of indexes + // of addDirJobs + if ( ( _options & AutoAddChecksumsIndexes ) || + ( _options & AutoAddContentFileIndexes ) ) + { + // if auto indexing is enabled, then we need to read the + // index for each file. We look only in the directory + // where the file is. this is expensive of course. + filesystem::DirContent content; + getDirectoryContent(media, jobp->location.filename().dirname(), content); + // this method test for the option flags so indexes are added + // only if the options are enabled + MIL << "Autodiscovering signed indexes on '" + << jobp->location.filename().dirname() << "' for '" + << jobp->location.filename() << "'" << endl; + + autoaddIndexes(content, media, jobp->location.filename().dirname(), dest_dir); + + // also look in the root of the media + content.clear(); + getDirectoryContent(media, Pathname("/"), content); + // this method test for the option flags so indexes are added + // only if the options are enabled + MIL << "Autodiscovering signed indexes on '" + << "/" << "' for '" + << jobp->location.filename() << "'" << endl; + + autoaddIndexes(content, media, Pathname("/"), dest_dir); + } + + // if the checksum is empty, but the checksum is in one of the + // indexes checksum, then add a checker + if ( jobp->location.checksum().empty() ) + { + if ( _checksums.find(jobp->location.filename().asString()) + != _checksums.end() ) + { + CheckSum chksm = _checksums[jobp->location.filename().asString()]; + ChecksumFileChecker digest_check(chksm); + jobp->checkers.push_back(digest_check); + } + else + { + // if the index checksum is empty too, we only add the checker + // if the AlwaysVerifyChecksum option is set on + if ( jobp->flags & FetcherJob::AlwaysVerifyChecksum ) + { + // add the checker with the empty checksum + ChecksumFileChecker digest_check(jobp->location.checksum()); + jobp->checkers.push_back(digest_check); + } + } + } + else + { + // checksum is not empty, so add a checksum checker + ChecksumFileChecker digest_check(jobp->location.checksum()); + jobp->checkers.push_back(digest_check); + } + + // Provide and validate the file. If the file was not transferred + // and no exception was thrown, it was an optional file. + provideToDest( media, dest_dir, jobp ); + + if ( ! progress.incr() ) + ZYPP_THROW(AbortRequestException()); + } // for each job + } + + /** \relates Fetcher::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Fetcher::Impl & obj ) + { + for ( std::list::const_iterator it_res = obj._resources.begin(); it_res != obj._resources.end(); ++it_res ) + { + str << *it_res; + } + return str; + } + + Fetcher::Fetcher() + : _pimpl( new Impl() ) + {} + + Fetcher::~Fetcher() + {} + + void Fetcher::setOptions( Fetcher::Options options ) + { + _pimpl->setOptions(options); + } + + Fetcher::Options Fetcher::options() const + { + return _pimpl->options(); + } + + void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker, const Pathname &deltafile ) + { + enqueueDigested( OnMediaLocation(resource).setDeltafile(deltafile), checker ); + } + + void Fetcher::enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker ) + { + _pimpl->enqueueDigested( resource, checker ); + } + + void Fetcher::enqueueDir( const OnMediaLocation &resource, + bool recursive, + const FileChecker &checker ) + { + _pimpl->enqueueDir(resource, recursive, checker); + } + + void Fetcher::enqueueDigestedDir( const OnMediaLocation &resource, + bool recursive, + const FileChecker &checker ) + { + _pimpl->enqueueDigestedDir(resource, recursive, checker); + } + + + void Fetcher::addIndex( const OnMediaLocation &resource ) + { + _pimpl->addIndex(resource); + } + + + void Fetcher::enqueue( const OnMediaLocation &resource, const FileChecker &checker ) + { + _pimpl->enqueue(resource, checker); + } + + + void Fetcher::addCachePath( const Pathname &cache_dir ) + { + _pimpl->addCachePath(cache_dir); + } + + void Fetcher::reset() + { + _pimpl->reset(); + } + + void Fetcher::setMediaSetAccess( MediaSetAccess &media ) + { + _pimpl->setMediaSetAccess( media ); + } + + void Fetcher::start(const zypp::filesystem::Pathname &dest_dir, const ProgressData::ReceiverFnc &progress) + { + _pimpl->start( dest_dir, progress ); + } + + void Fetcher::start( const Pathname &dest_dir, + MediaSetAccess &media, + const ProgressData::ReceiverFnc & progress_receiver ) + { + _pimpl->start(dest_dir, media, progress_receiver); + } + + std::ostream & operator<<( std::ostream & str, const Fetcher & obj ) + { + return str << *obj._pimpl; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + diff --git a/zypp/Fetcher.h b/zypp/Fetcher.h new file mode 100644 index 0000000..d0665f7 --- /dev/null +++ b/zypp/Fetcher.h @@ -0,0 +1,357 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Fetcher.h + * +*/ +#ifndef ZYPP_FETCHER_H +#define ZYPP_FETCHER_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** + * This class allows to retrieve a group of files in a confortable + * way, providing some smartness that does not belong to the + * media layer like: + * + * \li Configurable local caches to retrieve already + * donwloaded files. + * \li File checkers that can check for right checksums + * digital signatures, etc. + * + * \code + * MediaSetAccess access(url, path); + * Fetcher fetcher; + * fetcher.enqueue( OnMediaLocation().setLocation("/somefile") ); + * fetcher.addCachePath("/tmp/cache") + * fetcher.start( "/download-dir, access ); + * fetcher.reset(); + * \endcode + * + * To use the checkers. just create a functor implementing + * bool operator()(const Pathname &file) \see FileChecker. + * Pass the necessary validation data in the constructor + * of the functor, and pass the object to the \ref enqueue + * method. + * + * \code + * ChecksumFileChecker checker(CheckSum("sha1", "...."); + * fetcher.enqueue( location, checker); + * \endcode + * + * If you need to use more than one checker + * \see CompositeFileChecker + * + * Additionally, you can automatically enqueue a job + * with a checksum checker by using \ref enqueueDigested + * which will use the \ref OnMediaLocation checksum + * automatically. + * + * \code + * location.setChecksum(CheckSum("sha1", "....")); + * fetcher.enqueueDigested(location); + * \endcode + * + * \note If the checksum of the location is empty, but + * \ref enqueueDigested is used, then the user will get a + * warning that the file has no checksum. + * + * Additionally, Fetcher supports checking the downloaded + * content by using signed indexes on the remote side. + * + * \code + * MediaSetAccess access(url, path); + * Fetcher fetcher; + * fetcher.addIndex(OnMediaLocation("/content")); + * fetcher.enqueue( OnMediaLocation().setLocation("/somefile") ); + * fetcher.start( "/download-dir, access ); + * fetcher.reset(); + * \endcode + * + * Indexes are supported in CHECKSUMS format (simple text file) + * with checksum and file name, or content file, whith + * HASH SHA1 line entries. + * + * \note The indexes file names are relative to the directory + * where the index is. + * + * \note libzypp-11.x: Introduction of sha256 lead to the insight + * that using SHA1SUMS as filename was a bad choice. New media store + * the checksums in a CHECKSUMS file. If a CHECKSUMS file is not + * present, we fall back looking for a SHA1SUMS file. The checksum + * type (md5,sha1,sha256) is auto detected by looking at the cheksums + * length. No need to somehow encode it in the filename. + */ + class ZYPP_API Fetcher + { + friend std::ostream & operator<<( std::ostream & str, + const Fetcher & obj ); + public: + /** Implementation */ + class Impl; + public: + + /** + * Various option flags to change behavior + */ + enum Option + { + /** + * If a content file is found, it is + * downloaded and read. + */ + AutoAddContentFileIndexes = 0x0001, + /** + * If a CHECKSUMS file is found, it is + * downloaded and read. + */ + AutoAddChecksumsIndexes = 0x0002, + /** + * If a content or CHECKSUMS file is found, + * it is downloaded and read. + */ + AutoAddIndexes = AutoAddContentFileIndexes | AutoAddChecksumsIndexes, + }; + ZYPP_DECLARE_FLAGS(Options, Option); + + /** Default ctor */ + Fetcher(); + /** Dtor */ + virtual ~Fetcher(); + + public: + + /** + * Set the Fetcher options + * \see Fetcher::Options + */ + void setOptions( Options options ); + + /** + * Get current options + * \see Fetcher::Options + */ + Options options() const; + + /** + * Adds an index containing metadata (for example + * checksums ) that will be retrieved and read + * before the job processing starts. + * + * Nothing will be transferred or checked + * until \ref start() is called. + * + * The index is relative to the media path, and + * the listed files too. + * + * Indexes in the SHA1SUM format, and YaST + * content file + * + * The file has to be signed or the user will be + * warned that the file is unsigned. You can + * place the signature next to the file adding the + * .asc extension. + * + * If you expect the key to not to be in the target + * system, then you can place it next to the index + * using adding the .key extension. + * + */ + void addIndex( const OnMediaLocation &resource ); + + /** + * Enqueue a object for transferal, they will not + * be transferred until \ref start() is called + * + */ + void enqueue( const OnMediaLocation &resource, + const FileChecker &checker = FileChecker() ); + + /** + * Enqueue a object for transferal, they will not + * be transferred until \ref start() is called + * + * \note As \ref OnMediaLocation contains the digest information, + * a \ref ChecksumFileChecker is automatically added to the + * transfer job, so make sure you don't add another one or + * the user could be asked twice. + * + * \todo FIXME implement checker == operator to avoid this. + */ + void enqueueDigested( const OnMediaLocation &resource, const FileChecker &checker = FileChecker() ); + + + /** + * \deprecated + * the deltafile argument is part of OnMediaLocation now, please use \ref enqueueDigested without the + * deltafile argument + */ + ZYPP_DEPRECATED void enqueueDigested( const OnMediaLocation &resource, + const FileChecker &checker, const Pathname &deltafile ); + + + /** + * Enqueue a directory + * + * As the files to be enqueued are not known + * in advance, all files whose checksum can + * be found in some index are enqueued with + * checksum checking. Otherwise they are not. + * + * Some index may provide + * the checksums, either by \ref addIndex or + * using \ref AutoAddIndexes flag. + * + * Files are checked by providing a + * CHECKSUMS or content file listing + * filename + * and a respective CHECKSUMS.asc/content.asc which has + * the signature for the checksums. + * + * If you expect the user to not have the key of + * the signature either in the trusted or untrusted + * keyring, you can offer it as CHECKSUMS.key (or content.key) + * + * \param recursive True if the complete tree should + * be enqueued. + * + * \note As \ref checksums are read from the index, + * a \ref ChecksumFileChecker is automatically added to + * transfer jobs having a checksum available, + * so make sure you don't add another one or + * the user could be asked twice. + * + * \note The format of the file CHECKSUMS is the output of: + * ls | grep -v CHECKSUMS | xargs sha256sum > CHECKSUMS + * in each subdirectory. + * + * \note Every file CHECKSUMS.* except of CHECKSUMS.(asc|key|(void)) will + * not be transferred and will be ignored. + * + */ + void enqueueDir( const OnMediaLocation &resource, + bool recursive = false, + const FileChecker &checker = FileChecker() ); + + /** + * Enqueue a directory and always check for + * checksums. + * + * As the files to be enqueued are not known + * in advance, all files are enqueued with + * checksum checking. If the checksum of some file is + * not in some index, then there will be a verification + * warning ( \ref DigestReport ). + * + * Therefore some index will need to provide + * the checksums, either by \ref addIndex or + * using \ref AutoAddIndexes flag. + * + * Files are checked by providing a + * CHECKSUMS or content file listing + * filename + * and a respective CHECKSUMS.asc/content.asc which has + * the signature for the checksums. + * + * If you expect the user to not have the key of + * the signature either in the trusted or untrusted + * keyring, you can offer it as CHECKSUMS.key (or content.key) + * + * \param recursive True if the complete tree should + * be enqueued. + * + * \note As \ref checksums are read from the index, + * a \ref ChecksumFileChecker is automatically added to every + * transfer job, so make sure you don't add another one or + * the user could be asked twice. + * + * \note The format of the file CHECKSUMS is the output of: + * ls | grep -v CHECKSUMS | xargs sha256sum > CHECKSUMS + * in each subdirectory. + * + * \note Every file CHECKSUMS.* except of CHECKSUMS.(asc|key|(void)) will + * not be transferred and will be ignored. + * + */ + void enqueueDigestedDir( const OnMediaLocation &resource, + bool recursive = false, + const FileChecker &checker = FileChecker() ); + + /** + * adds a directory to the list of directories + * where to look for cached files + */ + void addCachePath( const Pathname &cache_dir ); + + /** + * Reset the transfer (jobs) list + * \note It does not reset the cache directory list + */ + void reset(); + + /** + * Sets the media set access that will be used to precache and + * to download the files when \ref start is called. Calling \ref start + * will reset the media access. + */ + void setMediaSetAccess ( MediaSetAccess &media ); + + /** + * start the transfer to a destination directory + * \a dest_dir + * The media has to be provides with \ref setMediaSetAccess before + * calling this version of start. + * The file tree will be replicated inside this + * directory + * + */ + void start( const Pathname &dest_dir, + const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() ); + + /** + * start the transfer to a destination directory + * \a dest_dir + * You have to provde a media set access + * \a media to get the files from + * The file tree will be replicated inside this + * directory + * + */ + void start( const Pathname &dest_dir, + MediaSetAccess &media, + const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() ); + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Fetcher::Options); + + /** \relates Fetcher Stream output */ + std::ostream & operator<<( std::ostream & str, const Fetcher & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_FETCHER_H diff --git a/zypp/FileChecker.cc b/zypp/FileChecker.cc new file mode 100644 index 0000000..c73351b --- /dev/null +++ b/zypp/FileChecker.cc @@ -0,0 +1,118 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/FileChecker.cc + * +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "FileChecker" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + ChecksumFileChecker::ChecksumFileChecker( CheckSum checksum ) + : _checksum(std::move(checksum)) + {} + + void ChecksumFileChecker::operator()( const Pathname &file ) const + { + const auto &res = zyppng::CheckSumWorkflow::verifyChecksum ( zyppng::SyncContext::create(), _checksum, file ); + if ( !res ) { + std::rethrow_exception( res.error ( ) ); + } + } + + void NullFileChecker::operator()(const Pathname &file ) const + { + MIL << "+ null check on " << file << endl; + return; + } + + void CompositeFileChecker::operator()(const Pathname &file ) const + { + //MIL << _checkers.size() << " checkers" << endl; + for ( std::list::const_iterator it = _checkers.begin(); it != _checkers.end(); ++it ) + { + if ( *it ) + { + //MIL << "+ chk" << endl; + (*it)(file); + } + else + { + ERR << "Invalid checker" << endl; + } + } + } + + void CompositeFileChecker::add( const FileChecker &checker ) + { _checkers.push_back(checker); } + + + SignatureFileChecker::SignatureFileChecker() + {} + + SignatureFileChecker::SignatureFileChecker( Pathname signature_r ) + { _verifyContext.signature( std::move(signature_r) ); } + + void SignatureFileChecker::addPublicKey( const Pathname & publickey_r ) + { addPublicKey( PublicKey(publickey_r) ); } + + void SignatureFileChecker::addPublicKey( const PublicKey & publickey_r ) + { getZYpp()->keyRing()->importKey( publickey_r, false ); } + + void SignatureFileChecker::operator()( const Pathname & file_r ) const + { + // const_cast because the workflow is allowed to store result values here + SignatureFileChecker & self { const_cast(*this) }; + self._verifyContext.file( file_r ); + + auto res = zyppng::SignatureFileCheckWorkflow::verifySignature ( zyppng::SyncContext::create(), keyring::VerifyFileContext(_verifyContext) ); + if ( !res ) { + std::rethrow_exception( res.error ( ) ); + } + self._verifyContext = std::move( *res ); + } + + keyring::VerifyFileContext &SignatureFileChecker::verifyContext() + { + return _verifyContext; + } + + const keyring::VerifyFileContext &SignatureFileChecker::verifyContext() const + { + return _verifyContext; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const FileChecker & obj ) + { + return str; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/FileChecker.h b/zypp/FileChecker.h new file mode 100644 index 0000000..ed20a01 --- /dev/null +++ b/zypp/FileChecker.h @@ -0,0 +1,155 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/FileChecker.h + * +*/ +#ifndef ZYPP_FILECHECKER_H +#define ZYPP_FILECHECKER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class PublicKey; + + /** + * Functor signature used to check files. + * \param file File to check. + * + * \throws FileCheckException when the file does not + * validate and the user don't want to continue. + */ + typedef function FileChecker; + + /** + * Built in file checkers + */ + + /** + * \short Checks for a valid checksum and interacts with the user. + */ + class ChecksumFileChecker + { + public: + typedef CheckSumCheckException ExceptionType; + /** + * Constructor. + * \param checksum Checksum that validates the file + */ + ChecksumFileChecker( CheckSum checksum ); + /** + * \short Try to validate the file + * \param file File to validate. + * + * \throws CheckSumCheckException if validation fails + */ + void operator()( const Pathname &file ) const; + private: + CheckSum _checksum; + }; + + /** + * \short Checks for the validity of a signature + */ + class SignatureFileChecker + { + public: + typedef SignatureCheckException ExceptionType; + + public: + /** Default Ctor for unsigned files. + * + * Use it when you don't have a signature and you want + * to check whether the user accepts an unsigned file. + */ + SignatureFileChecker(); + + /** Ctor taking the detached signature. */ + SignatureFileChecker( Pathname signature_r ); + + /** Add a public key to the list of known keys. */ + void addPublicKey( const PublicKey & publickey_r ); + /** \overload Convenience taking the public keys pathname. */ + void addPublicKey( const Pathname & publickey_r ); + + /** Call \ref KeyRing::verifyFileSignatureWorkflow to verify the file. + * + * Keep in mind the the workflow may return \c true (\ref fileAccepted) due to user interaction + * or global defaults even if a signature was not actually sucessfully verified. Whether a + * signature was actually sucessfully verified can be determined by checking \ref fileValidated + * which is invokes IFF a signature for this file actually validated. + * + * \param file_r File to validate. + * + * \throws SignatureCheckException if validation fails + */ + void operator()( const Pathname & file_r ) const; + + keyring::VerifyFileContext &verifyContext(); + const keyring::VerifyFileContext &verifyContext() const; + + private: + keyring::VerifyFileContext _verifyContext; + }; + + /** + * \short Checks for nothing + * Used as the default checker + */ + class NullFileChecker + { + public: + void operator()( const Pathname &file ) const; + }; + + /** + * \short Checker composed of more checkers. + * + * Allows to create a checker composed of various + * checkers altothether. It will only + * validate if all the checkers validate. + * + * \code + * CompositeFileChecker com; + * com.add(checker1); + * com.add(checker2); + * fetcher.enqueue(location, com); + * \endcode + */ + class CompositeFileChecker + { + public: + void add( const FileChecker &checker ); + /** + * \throws FileCheckException if validation fails + */ + void operator()( const Pathname &file ) const; + + int checkersSize() const { return _checkers.size(); } + private: + std::list _checkers; + }; + + /** \relates FileChecker Stream output */ + std::ostream & operator<<( std::ostream & str, const FileChecker & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_FILECHECKER_H diff --git a/zypp/Filter.h b/zypp/Filter.h new file mode 100644 index 0000000..f53b495 --- /dev/null +++ b/zypp/Filter.h @@ -0,0 +1,219 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Filter.h + * +*/ +#ifndef ZYPP_FILTER_H +#define ZYPP_FILTER_H + +#include +#include + +#include +#include +// #include included at the end! +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace filter + { ///////////////////////////////////////////////////////////////// + /** \defgroup POOLFILTER Collection solvable filter functors. + * + * All functors should be able to process \ref Solvable as well + * as \ref PoolItem. + * + * \code + * // The same filter... + * filter::ByLocaleSupport f( Locale("de") ); + * + * // ...can be used to iterate the sat::Pool... + * sat::Pool satpool( sat::Pool::instance() ); + * for_( it, satpool.filterBegin(f), satpool.filterEnd(f) ) + * { + * MIL << *it << endl; // prints sat::Solvable + * } + * + * // ...as well as the ResPool. + * ResPool pool ( ResPool::instance() ); + * for_( it, pool.filterBegin(f), pool.filterEnd(f) ) + * { + * MIL << *it << endl; // prints PoolItem + * } + * \endcode + * \ingroup g_Functor + */ + //@{ + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ByLocaleSupport + // + /** Filter solvables according to their locale support. + */ + class ByLocaleSupport + { + private: + using LS1 = bool (sat::Solvable::*)(const Locale &) const; + using LS2 = bool (sat::Solvable::*)(const LocaleSet &) const; + + public: + /** Solvables with locale support. */ + ByLocaleSupport() + : _sel( std::mem_fn(&sat::Solvable::supportsLocales) ) + {} + + /** Solvables supporting \c locale_r. */ + explicit ByLocaleSupport( const Locale & locale_r ) + : _sel( std::bind( std::mem_fn((LS1)&sat::Solvable::supportsLocale), _1, locale_r ) ) + {} + + /** Solvables supporting at least one locale in \c locales_r. */ + explicit ByLocaleSupport( const LocaleSet & locales_r ) + : _sel( std::bind( std::mem_fn((LS2)&sat::Solvable::supportsLocale), _1, locales_r ) ) + {} + + public: + /** Filter on \ref Solvable. */ + bool operator()( const sat::Solvable & solv_r ) const + { return _sel && _sel( solv_r ); } + + /** Filter fitting PoolItem/ResObject. */ + template + bool operator()( const TSolv & solv_r ) const + { return operator()( solv_r.satSolvable() ); } + + private: + function _sel; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ByKind + // + /** Filter solvables according to their kind. + */ + class ByKind + { + public: + ByKind() + {} + + ByKind( ResKind kind_r ) + : _kind(std::move( kind_r )) + {} + + public: + /** Filter on \ref Solvable. */ + bool operator()( const sat::Solvable & solv_r ) const + { return solv_r.isKind( _kind ); } + + /** Filter fitting PoolItem/ResObject. */ + template + bool operator()( const TSolv & solv_r ) const + { return operator()( solv_r.satSolvable() ); } + + private: + ResKind _kind; + }; + + /** \relates ByKind templated convenience ctor. */ + template + inline ByKind byKind() + { return ByKind( ResTraits::kind ); } + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ByStatus + // + /** Filter solvables according to their status. + */ + class ByStatus + { + public: + using Predicate = bool (ResStatus::*)() const; + + public: + ByStatus( Predicate pred_r = 0 ) + : _pred( pred_r ) + {} + + public: + /** Filter on \ref PoolItem. */ + bool operator()( const PoolItem & pi_r ) const + { return _pred && (pi_r.status().*_pred)(); } + + /** Filter fitting sat::Solvable/ResObject. */ + template + bool operator()( const TSolv & solv_r ) const + { return operator()( PoolItem(solv_r) ); } + + private: + Predicate _pred; + }; + /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SameItemAs + // + /** Filter items with at least same NVRA, vendor. + * This is usually used to find available packages + * that matche an insytalled one. + */ + class SameItemAs + { + public: + SameItemAs( const sat::Solvable & solv_r ) + : _item( solv_r ) + {} + + /** Fitting PoolItem/ResObject. */ + template + SameItemAs( const TSolv & solv_r ) + : _item( solv_r.satSolvable() ) + {} + + public: + /** Filter on \ref Solvable. */ + bool operator()( const sat::Solvable & solv_r ) const + { + return solv_r.name() == _item.name() + && solv_r.edition() == _item.edition() + && solv_r.arch() == _item.arch() + && solv_r.vendor() == _item.vendor(); + } + + /** Filter fitting PoolItem/ResObject. */ + template + bool operator()( const TSolv & solv_r ) const + { return operator()( solv_r.satSolvable() ); } + + private: + sat::Solvable _item; + }; + /////////////////////////////////////////////////////////////////// + //@} + + ///////////////////////////////////////////////////////////////// + } // namespace filter + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#include + +#endif // ZYPP_FILTER_H diff --git a/zypp/Glob.cc b/zypp/Glob.cc new file mode 100644 index 0000000..4b34152 --- /dev/null +++ b/zypp/Glob.cc @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Glob.cc + * +*/ +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace filesystem + { ///////////////////////////////////////////////////////////////// + + int Glob::add( const char * pattern_r, Flags flags_r ) + { + static Flags kAppend( GLOB_APPEND ); // not published + if ( ! flags_r ) + flags_r = _defaultFlags; + if ( _result ) + flags_r |= kAppend; + else + _result.reset( new ::glob_t ); + return( _lastGlobReturn = ::glob( pattern_r, flags_r, NULL, &(*_result) ) ); + } + + void Glob::clear() + { + if ( _result ) + { + ::globfree( &(*_result) ); + _result.reset(); + _lastGlobReturn = 0; + } + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Glob & obj ) + { + return dumpRange( str << "(" << obj.size() << ")", obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace filesystem + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Glob.h b/zypp/Glob.h new file mode 100644 index 0000000..8e8fffb --- /dev/null +++ b/zypp/Glob.h @@ -0,0 +1,271 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Glob.h + * +*/ +#ifndef ZYPP_GLOB_H +#define ZYPP_GLOB_H + +extern "C" +{ +#include +} + +#include + +#include +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace filesystem + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Glob + // + /** Find pathnames matching a pattern. + * \code + * Glob glob( Glob::kBrace ); + * glob.add( "/somewhere/solverTestcase/ *{.xml,.xml.gz}" ); + * glob.add( "/somewhere/else/a*" ); + * for_( it, glob.begin(), glob.end() ) + * ... + * \endcode + * \code + * std::list plist; + * Glob::collect( "/somewherre/solverTestcase/ *{.xml,.xml.gz}", Glob::kBrace, + * std::back_inserter( plist ) ); + * \endcode + * \see Manual page glob(3) + */ + class ZYPP_API Glob : private base::NonCopyable + { + public: + using size_type = size_t; + using value_type = const char *; + + /** Iterate NULL terminated \c char* array. */ + class const_iterator : public boost::iterator_adaptor< + const_iterator // Derived + , char ** // Base + , value_type // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , const value_type // Reference + > + { + public: + const_iterator() + : const_iterator::iterator_adaptor_( 0 ) + {} + + explicit const_iterator( char ** _idx ) + : const_iterator::iterator_adaptor_( _idx && *_idx ? _idx : 0 ) + {} + + private: + friend class boost::iterator_core_access; + void increment() + { + if ( base_reference() && !*(++base_reference()) ) + base_reference() = 0; + } + reference dereference() const + { return( base() ? *base() : 0 ); } + }; + /////////////////////////////////////////////////////////////////// + + public: + /** Individual bits to combine in \ref Flags. */ + enum Bits { + kErr = GLOB_ERR, //!< Return on read errors. + kMark = GLOB_MARK, //!< Append a slash to each name. + kNoSort = GLOB_NOSORT, //!< Don't sort the names. + // unsupported kDoOffs = GLOB_DOOFFS, //!< Insert PGLOB->gl_offs NULLs. + kNoCheck = GLOB_NOCHECK, //!< If nothing matches, return the pattern. + // autoapplied kAppend = GLOB_APPEND, //!< Append to results of a previous call. + kNoEscape = GLOB_NOESCAPE, //!< Backslashes don't quote metacharacters. + kPeriod = GLOB_PERIOD, //!< Leading `.' can be matched by metachars. + // unsupported kMagChar = GLOB_MAGCHAR,//!< Set in gl_flags if any metachars seen. + kAltDirFunc = GLOB_ALTDIRFUNC, //!< Use gl_opendir et al functions. + kBrace = GLOB_BRACE, //!< Expand "{a,b}" to "a" "b". + kNoMagic = GLOB_NOMAGIC, //!< If no magic chars, return the pattern. + kTilde = GLOB_TILDE, //!< Expand ~user and ~ to home directories. + kOnlyDir = GLOB_ONLYDIR, //!< Match only directories. + kTildeCheck = GLOB_TILDE_CHECK, //!< Like GLOB_TILDE but return an error if the user name is not available. + }; + + /** type Flags: Type-safe OR-combination of \ref Bits. */ + ZYPP_DECLARE_FLAGS( Flags, Bits ); + + public: + /** Default ctor optionally taking the default flags. + * The flags passed here are the default for \ref add. + * \see \ref setDefaultFlags + */ + Glob( Flags flags_r = Flags() ) + : _defaultFlags( flags_r ) + {} + + /** Ctor adding pathnames matching \a pattern_r. + * The flags passed here are the default for \ref add. + * \see \ref setDefaultFlags + */ + explicit Glob( const Pathname & pattern_r, Flags flags_r = Flags() ) + : _defaultFlags( flags_r ) + { add( pattern_r, flags_r ); } + /** \overload */ + explicit Glob( const std::string & pattern_r, Flags flags_r = Flags() ) + : _defaultFlags( flags_r ) + { add( pattern_r, flags_r ); } + /** \overload */ + explicit Glob( const char * pattern_r, Flags flags_r = Flags() ) + : _defaultFlags( flags_r ) + { add( pattern_r, flags_r ); } + + /** Dtor */ + ~Glob() + { if ( _result ) ::globfree( &(*_result) ); } + + /** Add pathnames matching \a pattern_r to the current result. + * + * Any flags passed here override the global default passed to + * the ctor. GLOB_APPEND is atomatically added to the flags + * f needed. + * + * This invalidates all iterators. + * \see \ref setDefaultFlags + * \return the value returned by ::glob(). + */ + int add( const Pathname & pattern_r, Flags flags_r = Flags() ) + { return add( pattern_r.c_str(), flags_r ); } + /** \overload */ + int add( const std::string & pattern_r, Flags flags_r = Flags() ) + { return add( pattern_r.c_str(), flags_r ); } + /** \overload */ + int add( const char * pattern_r, Flags flags_r = Flags() ); + + /** Clear all results found so far. \ref defaultFlags remain active. */ + void clear(); + + /** Clear all results and reset \ref defaultFlags. */ + void reset( Flags flags_r = Flags() ) + { clear(); setDefaultFlags( flags_r ); } + + + public: + /** The default flags passed to \c ::glob(). */ + Flags defaultFlags() const + { return _defaultFlags; } + + /** Set the default flags passed to \c ::glob(). */ + void setDefaultFlags( Flags flags_r = Flags() ) + { _defaultFlags = flags_r; } + + /** Returns the value returned by the last call to \c ::glob(). + * \c Zero on successful completion. Otherwise \c GLOB_NOSPACE or \c GLOB_ABORTED + * or \c GLOB_NOMATCH. + */ + int lastGlobReturn() const + { return _lastGlobReturn; } + + public: + /** Whether matches were found. */ + bool empty() const + { return ! ( _result && _result->gl_pathc ); } + + /** The number of matches found so far. */ + size_type size() const + { return( _result ? _result->gl_pathc : 0 ); } + + /** Iterator pointing to the first result. */ + const_iterator begin() const + { return( _result ? const_iterator( _result->gl_pathv ) : const_iterator() ); } + + /** Iterator pointing behind the last result. */ + const_iterator end() const + { return const_iterator(); } + + public: + + /** \name Collecting Glob results to some TOutputIterator + * \code + * std::list p; + * Glob::collect( "/bin/a*.dat}", std::back_inserter(p) ); + * Glob::collect( "/bin/a*{.xml,.xml.gz}", Glob::kBrace, std::back_inserter(p) ); + * \endcode + */ + //@{ + /** Write glob result to some \c OutputIterator. */ + template + static int collect( const Pathname & pattern_r, TOutputIterator result_r ) + { return collect( pattern_r.c_str(), Flags(), result_r ); } + /** \overload */ + template + static int collect( const std::string & pattern_r, TOutputIterator result_r ) + { return collect( pattern_r.c_str(), Flags(), result_r ); } + /** \overload */ + template + static int collect( const char * pattern_r, TOutputIterator result_r ) + { return collect( pattern_r, Flags(), result_r ); } + + /** \overload With \ref Flags */ + template + static int collect( const Pathname & pattern_r, Flags flags_r, TOutputIterator result_r ) + { return collect( pattern_r.c_str(), flags_r, result_r ); } + /** \overload */ + template + static int collect( const std::string & pattern_r, Flags flags_r, TOutputIterator result_r ) + { return collect( pattern_r.c_str(), flags_r, result_r ); } + /** \overload */ + template + static int collect( const char * pattern_r, Flags flags_r, TOutputIterator result_r ) + { + Glob glob( pattern_r, flags_r ); + if ( glob.lastGlobReturn() == 0 ) + for_( it, glob.begin(), glob.end() ) + (*result_r)++ = typename TOutputIterator::container_type::value_type(*it); + return glob.lastGlobReturn(); + } + //@} + + private: + Flags _defaultFlags; + scoped_ptr< ::glob_t> _result; + DefaultIntegral _lastGlobReturn; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Glob Stream output */ + std::ostream & operator<<( std::ostream & str, const Glob & obj ); + + /** \relates Glob::const_iterator Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Glob::const_iterator & obj ) + { return str << *obj; } + + ZYPP_DECLARE_OPERATORS_FOR_FLAGS( Glob::Flags ); + + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace filesystem + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_GLOB_H diff --git a/zypp/Globals.h b/zypp/Globals.h new file mode 100644 index 0000000..58d7385 --- /dev/null +++ b/zypp/Globals.h @@ -0,0 +1 @@ +#include diff --git a/zypp/HistoryLog.cc b/zypp/HistoryLog.cc new file mode 100644 index 0000000..a1a5444 --- /dev/null +++ b/zypp/HistoryLog.cc @@ -0,0 +1,359 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/HistoryLog.cc + * + */ +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +using std::endl; +using std::string; + +namespace zypp +{ + namespace + { + inline string timestamp() + { return zypp::Date::now().form( HISTORY_LOG_DATE_FORMAT ); } + + inline string userAtHostname() + { + static char buf[256]; + string result; + char * tmp = ::cuserid(buf); + if (tmp) + { + result = string(tmp); + if (!::gethostname(buf, 255)) + result += "@" + string(buf); + } + return result; + } + + static std::string pidAndAppname() + { + static std::string _val; + if ( _val.empty() ) + { + pid_t mypid = getpid(); + zypp::Pathname p( "/proc/"+zypp::str::numstring(mypid)+"/exe" ); + zypp::Pathname myname( zypp::filesystem::readlink( p ) ); + + _val += zypp::str::numstring(mypid); + _val += ":"; + _val += myname.basename(); + } + return _val; + } + + static std::string cmdline() + { + static std::string _val; + if ( _val.empty() ) + { + pid_t mypid = getpid(); + { + std::ifstream cmdlineStr( Pathname("/proc/"+zypp::str::numstring(mypid)+"/cmdline").c_str() ); + char ch = 0; + const char * sep = "'"; + while ( cmdlineStr && cmdlineStr.get( ch ) ) + { + if ( sep ) + { + _val += sep; + sep = nullptr; + } + switch ( ch ) + { + case '\0': _val += '\''; sep = " '"; break; + case '\n': _val += ' '; break; + case '\\': _val += '\\'; _val += '\\'; break; + case '|': _val += '\\'; _val += '|'; break; + default: _val += ch; break; + } + } + } + } + return _val; + } + } // namespace + + namespace + { + const char _sep = '|'; + std::ofstream _log; + unsigned _refcnt = 0; + Pathname _fname; + Pathname _fnameLastFail; + + inline void openLog() + { + if ( _fname.empty() ) + _fname = ZConfig::instance().historyLogFile(); + + _log.clear(); + _log.open( _fname.asString().c_str(), std::ios::out|std::ios::app ); + if( !_log && _fnameLastFail != _fname ) + { + ERR << "Could not open logfile '" << _fname << "'" << endl; + _fnameLastFail = _fname; + } + } + + inline void closeLog() + { + _log.clear(); + _log.close(); + } + + inline void refUp() + { + if ( !_refcnt ) + openLog(); + ++_refcnt; + } + + inline void refDown() + { + --_refcnt; + if ( !_refcnt ) + closeLog(); + } + } // namespace + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : HistoryLog + // + /////////////////////////////////////////////////////////////////// + + HistoryLog::HistoryLog( const Pathname & rootdir ) + { + setRoot( rootdir ); + refUp(); + } + + HistoryLog::~HistoryLog() + { + refDown(); + } + + void HistoryLog::setRoot( const Pathname & rootdir ) + { + if ( ! rootdir.absolute() ) + return; + + if ( _refcnt ) + closeLog(); + + _fname = ZConfig::instance().historyLogFile(); + if ( _fname != "/dev/null" ) // no need to redirect /dev/null into the target + _fname = rootdir / _fname; + filesystem::assert_dir( _fname.dirname() ); + MIL << "installation log file " << _fname << endl; + + if ( _refcnt ) + openLog(); + } + + const Pathname & HistoryLog::fname() + { + if ( _fname.empty() ) + _fname = ZConfig::instance().historyLogFile(); + return _fname; + } + + ///////////////////////////////////////////////////////////////////////// + + void HistoryLog::comment( const string & comment, bool timestamp_r ) + { + if (comment.empty()) + return; + + _log << "# "; + if ( timestamp_r ) + _log << timestamp() << " "; + + const char * s = comment.c_str(); + const char * c = s; + unsigned size = comment.size(); + + // ignore the last newline + if (comment[size-1] == '\n') + --size; + + for ( unsigned i = 0; i < size; ++i, ++c ) + if ( *c == '\n' ) + { + _log << string( s, c + 1 - s ) << "# "; + s = c + 1; + } + + if ( s < c ) + _log << std::string( s, c-s ); + + _log << endl; + } + + ///////////////////////////////////////////////////////////////////////// + + void HistoryLog::stampCommand() + { + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::STAMP_COMMAND.asString(true) // 2 action + << _sep << userAtHostname() // 3 requested by + << _sep << cmdline() // 4 command + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 6 userdata + << endl; + + } + + void HistoryLog::install( const PoolItem & pi ) + { + if ( ! pi.isKind() ) return; + const Package::constPtr p = asKind(pi.resolvable()); + + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::INSTALL.asString(true) // 2 action + << _sep << p->name() // 3 name + << _sep << p->edition() // 4 evr + << _sep << p->arch(); // 5 arch + + // ApplLow is what the solver selected on behalf of the user. + if (pi.status().isByUser() || pi.status().isByApplLow() ) + _log << _sep << userAtHostname(); // 6 requested by + else if (pi.status().isByApplHigh()) + _log << _sep << pidAndAppname(); + else + _log << _sep; + + _log + << _sep << p->repoInfo().alias() // 7 repo alias + << _sep << p->checksum().checksum() // 8 checksum + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 9 userdata + << endl; + } + + + void HistoryLog::remove( const PoolItem & pi ) + { + if ( ! pi.isKind() ) return; + const Package::constPtr p = asKind(pi.resolvable()); + + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::REMOVE.asString(true) // 2 action + << _sep << p->name() // 3 name + << _sep << p->edition() // 4 evr + << _sep << p->arch(); // 5 arch + + // ApplLow is what the solver selected on behalf of the user. + if ( pi.status().isByUser() || pi.status().isByApplLow() ) + _log << _sep << userAtHostname(); // 6 requested by + else if (pi.status().isByApplHigh()) + _log << _sep << pidAndAppname(); + else + _log << _sep; + + _log + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 7 userdata + << endl; + } + + ///////////////////////////////////////////////////////////////////////// + + void HistoryLog::addRepository(const RepoInfo & repo) + { + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::REPO_ADD.asString(true) // 2 action + << _sep << str::escape(repo.alias(), _sep) // 3 alias + << _sep << str::escape(repo.url().asString(), _sep) // 4 primary URL + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata + << endl; + } + + + void HistoryLog::removeRepository(const RepoInfo & repo) + { + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::REPO_REMOVE.asString(true) // 2 action + << _sep << str::escape(repo.alias(), _sep) // 3 alias + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 4 userdata + << endl; + } + + + void HistoryLog::modifyRepository( + const RepoInfo & oldrepo, const RepoInfo & newrepo) + { + if (oldrepo.alias() != newrepo.alias()) + { + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::REPO_CHANGE_ALIAS.asString(true) // 2 action + << _sep << str::escape(oldrepo.alias(), _sep) // 3 old alias + << _sep << str::escape(newrepo.alias(), _sep) // 4 new alias + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata + << endl; + } + if ( oldrepo.url() != newrepo.url() ) + { + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::REPO_CHANGE_URL.asString(true) // 2 action + << _sep << str::escape(oldrepo.url().asString(), _sep) // 3 old url + << _sep << str::escape(newrepo.url().asString(), _sep) // 4 new url + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 5 userdata + << endl; + } + } + + void HistoryLog::patchStateChange( const PoolItem & pi, ResStatus::ValidateValue oldstate ) + { + if ( ! pi.isKind() ) return; + const Patch::constPtr p = asKind(pi.resolvable()); + + _log + << timestamp() // 1 timestamp + << _sep << HistoryActionID::PATCH_STATE_CHANGE.asString(true) // 2 action + << _sep << p->name() // 3 name + << _sep << p->edition() // 4 evr + << _sep << p->arch() // 5 arch + << _sep << p->repoInfo().alias() // 6 repo alias + << _sep << p->severity() // 7 severity + << _sep << p->category() // 8 category + << _sep << ResStatus::validateValueAsString( oldstate ) // 9 old state + << _sep << pi.status().validateValueAsString() // 10 new state + << _sep << str::escape(ZConfig::instance().userData(), _sep) // 11 userdata + << endl; + } + + /////////////////////////////////////////////////////////////////// + +} // namespace zypp diff --git a/zypp/HistoryLog.h b/zypp/HistoryLog.h new file mode 100644 index 0000000..96c9a7f --- /dev/null +++ b/zypp/HistoryLog.h @@ -0,0 +1,139 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/HistoryLog.h + * + */ +#ifndef ZYPP_TARGET_COMMITLOG_H +#define ZYPP_TARGET_COMMITLOG_H + +#include + +#include +#include + +namespace zypp +{ + class PoolItem; + class RepoInfo; + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLog + /// \brief Writing the zypp history file + /// \ingroup g_ZyppHistory + /// + /// Reference counted signleton for writhing the zypp history file. + /// The history file is opened on demand and closed when the last + /// HistoryLog object drops its reference. Thus HistoryLog objects + /// should be local to those functions, writing the log, and must + /// not be stored permanently. + /// + /// \code + /// some method () + /// { + /// PoolItem pi; + /// ... + /// HistoryLog().install(pi); + /// ... + /// HistoryLog().comment(someMessage); + /// } + /// \endcode + /// + /// \note Take care to set proper target root dir if needed. Either pass + /// it via the constructor, or set it via setRoot(Pathname) method. + /// The default location of the file is determined by + /// \ref zypp::ZConfig::historyLogPath (default: \c /var/log/zypp/history). + /// + /// \todo The implementation as pseudo signleton is questionable. + /// Use shared_ptr instead of handcrafted ref/unref. Manage multiple + /// logs at different locations. + /////////////////////////////////////////////////////////////////// + class HistoryLog + { + HistoryLog( const HistoryLog & ); + HistoryLog & operator=( const HistoryLog & ); + public: + /** + * Constructor with an optional root directory. + * + * \param rootdir actual target root directory + */ + HistoryLog( const Pathname & rootdir = Pathname() ); + ~HistoryLog(); + + /** + * Set new root directory to the default history log file path. + * + * This path will be prepended to the default log file path. This should + * be done where there is a potential that the target root has changed. + * + * \param root new root directory. + */ + static void setRoot( const Pathname & root ); + + /** + * Get the current log file path. + */ + static const Pathname & fname(); + + /** + * Log a comment (even multiline). + * + * \param comment the comment + * \param timestamp whether to include a timestamp at the start of the comment + */ + void comment( const std::string & comment, bool timestamp = false ); + + /** Log info about the current process. */ + void stampCommand(); + + /** + * Log installation (or update) of a package. + */ + void install( const PoolItem & pi ); + + /** + * Log removal of a package + */ + void remove( const PoolItem & pi ); + + /** + * Log a newly added repository. + * + * \param repo info about the added repository + */ + void addRepository( const RepoInfo & repo ); + + /** + * Log recently removed repository. + * + * \param repo info about the removed repository + */ + void removeRepository( const RepoInfo & repo ); + + /** + * Log certain modifications to a repository. + * + * \param oldrepo info about the old repository + * \param newrepo info about the new repository + */ + void modifyRepository( const RepoInfo & oldrepo, const RepoInfo & newrepo ); + + /** + * Log state changes in patches + * + * \param oldstate info about the old state + */ + void patchStateChange( const PoolItem & pi, ResStatus::ValidateValue oldstate ); + + }; + /////////////////////////////////////////////////////////////////// + +} // namespace zypp + +#endif // ZYPP_TARGET_COMMITLOG_H diff --git a/zypp/HistoryLogData.cc b/zypp/HistoryLogData.cc new file mode 100644 index 0000000..d7aa520 --- /dev/null +++ b/zypp/HistoryLogData.cc @@ -0,0 +1,333 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +/** \file zypp/HistoryLogData.cc + * + */ +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + using parser::ParseException; + + /////////////////////////////////////////////////////////////////// + // + // class HistoryActionID + // + /////////////////////////////////////////////////////////////////// + + const HistoryActionID HistoryActionID::NONE (HistoryActionID::NONE_e); + const HistoryActionID HistoryActionID::INSTALL (HistoryActionID::INSTALL_e); + const HistoryActionID HistoryActionID::REMOVE (HistoryActionID::REMOVE_e); + const HistoryActionID HistoryActionID::REPO_ADD (HistoryActionID::REPO_ADD_e); + const HistoryActionID HistoryActionID::REPO_REMOVE (HistoryActionID::REPO_REMOVE_e); + const HistoryActionID HistoryActionID::REPO_CHANGE_ALIAS (HistoryActionID::REPO_CHANGE_ALIAS_e); + const HistoryActionID HistoryActionID::REPO_CHANGE_URL (HistoryActionID::REPO_CHANGE_URL_e); + const HistoryActionID HistoryActionID::STAMP_COMMAND (HistoryActionID::STAMP_COMMAND_e); + const HistoryActionID HistoryActionID::PATCH_STATE_CHANGE (HistoryActionID::PATCH_STATE_CHANGE_e); + + HistoryActionID::HistoryActionID(const std::string & strval_r) + : _id(parse(strval_r)) + {} + + HistoryActionID::ID HistoryActionID::parse( const std::string & strval_r ) + { + typedef std::map MapType; + static MapType _table; + if ( _table.empty() ) + { + // initialize it + _table["install"] = INSTALL_e; + _table["remove"] = REMOVE_e; + _table["radd"] = REPO_ADD_e; + _table["rremove"] = REPO_REMOVE_e; + _table["ralias"] = REPO_CHANGE_ALIAS_e; + _table["rurl"] = REPO_CHANGE_URL_e; + _table["command"] = STAMP_COMMAND_e; + _table["patch"] = PATCH_STATE_CHANGE_e; + _table["NONE"] = _table["none"] = NONE_e; + } + + MapType::const_iterator it = _table.find( strval_r ); + if ( it != _table.end() ) + return it->second; + // else: + WAR << "Unknown history action ID '" + strval_r + "'" << endl; + return NONE_e; + } + + + const std::string & HistoryActionID::asString( bool pad ) const + { + typedef std::pair PairType; + typedef std::map MapType; + static MapType _table; + if ( _table.empty() ) + { + // initialize it pad(7) (for now) + _table[INSTALL_e] = PairType( "install" , "install" ); + _table[REMOVE_e] = PairType( "remove" , "remove " ); + _table[REPO_ADD_e] = PairType( "radd" , "radd " ); + _table[REPO_REMOVE_e] = PairType( "rremove" , "rremove" ); + _table[REPO_CHANGE_ALIAS_e] = PairType( "ralias" , "ralias " ); + _table[REPO_CHANGE_URL_e] = PairType( "rurl" , "rurl " ); + _table[STAMP_COMMAND_e] = PairType( "command" , "command" ); + _table[PATCH_STATE_CHANGE_e]= PairType( "patch" , "patch " ); + _table[NONE_e] = PairType( "NONE" , "NONE " ); + } + + return( pad ? _table[_id].second : _table[_id].first ); + } + + std::ostream & operator << (std::ostream & str, const HistoryActionID & id) + { return str << id.asString(); } + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // class HistoryLogData::Impl + // + /////////////////////////////////////////////////////////////////// + class HistoryLogData::Impl + { + public: + Impl( FieldVector & fields_r, size_type expect_r ) + { + _checkFields( fields_r, expect_r ); + _field.swap( fields_r ); + // For whatever reason writer is ' '-padding the action field + // but we don't want to modify the vector before we moved it. + _field[ACTION_INDEX] = str::trim( _field[ACTION_INDEX] ); + _action = HistoryActionID( _field[ACTION_INDEX] ); + } + + Impl( FieldVector & fields_r, HistoryActionID action_r, size_type expect_r ) + { + _checkFields( fields_r, expect_r ); + // For whatever reason writer is ' '-padding the action field + // but we don't want to modify the vector before we moved it. + std::string trimmed( str::trim( fields_r[ACTION_INDEX] ) ); + _action = HistoryActionID( trimmed ); + if ( _action != action_r ) + { + ZYPP_THROW( ParseException( str::form( "Bad action id. Got %s, expected %s.", + _action.asString().c_str(), + action_r.asString().c_str() ) ) ); + } + _field.swap( fields_r ); + // now adjust action field: + _field[ACTION_INDEX] = trimmed; + } + + void _checkFields( const FieldVector & fields_r, size_type expect_r ) + { + if ( expect_r < 2 ) // at least 2 fields (date and action) are required + expect_r = 2; + if ( fields_r.size() < expect_r ) + { + ZYPP_THROW( ParseException( str::form( "Bad number of fields. Got %zd, expected at least %zd.", + fields_r.size(), + expect_r ) ) ); + } + try + { + _date = Date( fields_r[DATE_INDEX], HISTORY_LOG_DATE_FORMAT ); + } + catch ( const std::exception & excpt ) + { + ZYPP_THROW( ParseException( excpt.what() ) ); // invalid date format + } + // _action handled later + } + + public: + FieldVector _field; + Date _date; + HistoryActionID _action; + }; + + /////////////////////////////////////////////////////////////////// + // + // class HistoryLogData + // + /////////////////////////////////////////////////////////////////// + + HistoryLogData::HistoryLogData( FieldVector & fields_r, size_type expect_r ) + : _pimpl( new Impl( fields_r, expect_r ) ) + {} + + HistoryLogData::HistoryLogData( FieldVector & fields_r, HistoryActionID expectedId_r, size_type expect_r ) + : _pimpl( new Impl( fields_r, expectedId_r, expect_r ) ) + {} + + HistoryLogData::~HistoryLogData() + {} + + HistoryLogData::Ptr HistoryLogData::create( FieldVector & fields_r ) + { + if ( fields_r.size() >= 2 ) + { + // str::trim( _field[ACTION_INDEX] ); + switch ( HistoryActionID( str::trim( fields_r[ACTION_INDEX] ) ).toEnum() ) + { +#define OUTS(E,T) case HistoryActionID::E: return Ptr( new T( fields_r ) ); break; + OUTS( INSTALL_e, HistoryLogDataInstall ); + OUTS( REMOVE_e, HistoryLogDataRemove ); + OUTS( REPO_ADD_e, HistoryLogDataRepoAdd ); + OUTS( REPO_REMOVE_e, HistoryLogDataRepoRemove ); + OUTS( REPO_CHANGE_ALIAS_e, HistoryLogDataRepoAliasChange ); + OUTS( REPO_CHANGE_URL_e, HistoryLogDataRepoUrlChange ); + OUTS( STAMP_COMMAND_e, HistoryLogDataStampCommand ); + OUTS( PATCH_STATE_CHANGE_e, HistoryLogPatchStateChange ); +#undef OUTS + // intentionally no default: + case HistoryActionID::NONE_e: + break; + } + } + // unknown action or invalid fields? Ctor will accept or throw. + return Ptr( new HistoryLogData( fields_r ) ); + } + + bool HistoryLogData::empty() const + { return _pimpl->_field.empty(); } + + HistoryLogData::size_type HistoryLogData::size() const + { return _pimpl->_field.size(); } + + HistoryLogData::const_iterator HistoryLogData::begin() const + { return _pimpl->_field.begin(); } + + HistoryLogData::const_iterator HistoryLogData::end() const + { return _pimpl->_field.end(); } + + const std::string & HistoryLogData::optionalAt( size_type idx_r ) const + { + static const std::string _empty; + return( idx_r < size() ? _pimpl->_field[idx_r] : _empty ); + } + + const std::string & HistoryLogData::at( size_type idx_r ) const + { return _pimpl->_field.at( idx_r ); } + + + Date HistoryLogData::date() const + { return _pimpl->_date; } + + HistoryActionID HistoryLogData::action() const + { return _pimpl->_action; } + + + std::ostream & operator<<( std::ostream & str, const HistoryLogData & obj ) + { return str << str::joinEscaped( obj.begin(), obj.end(), '|' ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogDataInstall + /////////////////////////////////////////////////////////////////// + HistoryLogDataInstall::HistoryLogDataInstall( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogDataInstall::name() const { return optionalAt( NAME_INDEX ); } + Edition HistoryLogDataInstall::edition() const { return Edition( optionalAt( EDITION_INDEX ) ); } + Arch HistoryLogDataInstall::arch() const { return Arch( optionalAt( ARCH_INDEX ) ); } + std::string HistoryLogDataInstall::reqby() const { return optionalAt( REQBY_INDEX ); } + std::string HistoryLogDataInstall::repoAlias() const { return optionalAt( REPOALIAS_INDEX ); } + CheckSum HistoryLogDataInstall::checksum() const { return optionalAt( CHEKSUM_INDEX ); } + std::string HistoryLogDataInstall::userdata() const { return optionalAt( USERDATA_INDEX ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogPatchStateChange + /////////////////////////////////////////////////////////////////// + HistoryLogPatchStateChange::HistoryLogPatchStateChange( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogPatchStateChange::name() const { return optionalAt( NAME_INDEX ); } + Edition HistoryLogPatchStateChange::edition() const { return Edition( optionalAt( EDITION_INDEX ) ); } + Arch HistoryLogPatchStateChange::arch() const { return Arch( optionalAt( ARCH_INDEX ) ); } + std::string HistoryLogPatchStateChange::repoAlias() const { return optionalAt( REPOALIAS_INDEX ); } + Patch::SeverityFlag HistoryLogPatchStateChange::severity() const { return Patch::severityFlag( optionalAt( SEVERITY_INDEX ) ); } + Patch::Category HistoryLogPatchStateChange::category() const { return Patch::categoryEnum( optionalAt( CATEGORY_INDEX ) ); } + std::string HistoryLogPatchStateChange::oldstate() const { return optionalAt( OLDSTATE_INDEX ); } + std::string HistoryLogPatchStateChange::newstate() const { return optionalAt( NEWSTATE_INDEX ); } + std::string HistoryLogPatchStateChange::userdata() const { return optionalAt( USERDATA_INDEX ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogDataRemove + /////////////////////////////////////////////////////////////////// + HistoryLogDataRemove::HistoryLogDataRemove( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogDataRemove::name() const { return optionalAt( NAME_INDEX ); } + Edition HistoryLogDataRemove::edition() const { return Edition( optionalAt( EDITION_INDEX ) ); } + Arch HistoryLogDataRemove::arch() const { return Arch( optionalAt( ARCH_INDEX ) ); } + std::string HistoryLogDataRemove::reqby() const { return optionalAt( REQBY_INDEX ); } + std::string HistoryLogDataRemove::userdata() const { return optionalAt( USERDATA_INDEX ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogDataRepoAdd + /////////////////////////////////////////////////////////////////// + HistoryLogDataRepoAdd::HistoryLogDataRepoAdd( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogDataRepoAdd::alias() const { return optionalAt( ALIAS_INDEX ); } + Url HistoryLogDataRepoAdd::url() const { return optionalAt( URL_INDEX ); } + std::string HistoryLogDataRepoAdd::userdata() const { return optionalAt( USERDATA_INDEX ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogDataRepoRemove + /////////////////////////////////////////////////////////////////// + HistoryLogDataRepoRemove::HistoryLogDataRepoRemove( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogDataRepoRemove::alias() const { return optionalAt( ALIAS_INDEX ); } + std::string HistoryLogDataRepoRemove::userdata() const { return optionalAt( USERDATA_INDEX ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogDataRepoAliasChange + /////////////////////////////////////////////////////////////////// + HistoryLogDataRepoAliasChange::HistoryLogDataRepoAliasChange( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogDataRepoAliasChange::oldAlias() const { return optionalAt( OLDALIAS_INDEX ); } + std::string HistoryLogDataRepoAliasChange::newAlias() const { return optionalAt( NEWALIAS_INDEX ); } + std::string HistoryLogDataRepoAliasChange::userdata() const { return optionalAt( USERDATA_INDEX ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogDataRepoUrlChange + /////////////////////////////////////////////////////////////////// + HistoryLogDataRepoUrlChange::HistoryLogDataRepoUrlChange( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogDataRepoUrlChange::alias() const { return optionalAt( ALIAS_INDEX ); } + Url HistoryLogDataRepoUrlChange::newUrl() const { return optionalAt( NEWURL_INDEX ); } + std::string HistoryLogDataRepoUrlChange::userdata() const { return optionalAt( USERDATA_INDEX ); } + + /////////////////////////////////////////////////////////////////// + // class HistoryLogDataStampCommand + /////////////////////////////////////////////////////////////////// + HistoryLogDataStampCommand::HistoryLogDataStampCommand( FieldVector & fields_r ) + : HistoryLogData( fields_r ) + {} + std::string HistoryLogDataStampCommand::executedBy() const { return optionalAt( USER_INDEX ); } + std::string HistoryLogDataStampCommand::command() const { return optionalAt( COMMAND_INDEX ); } + std::string HistoryLogDataStampCommand::userdata() const { return optionalAt( USERDATA_INDEX ); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/HistoryLogData.h b/zypp/HistoryLogData.h new file mode 100644 index 0000000..e720f67 --- /dev/null +++ b/zypp/HistoryLogData.h @@ -0,0 +1,469 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +/** \file zypp/HistoryLogData.h + * + */ +#ifndef ZYPP_HISTORYLOGDATA_H_ +#define ZYPP_HISTORYLOGDATA_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define HISTORY_LOG_DATE_FORMAT "%Y-%m-%d %H:%M:%S" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class HistoryActionID + /// \brief Enumeration of known history actions. + /// \ingroup g_EnumerationClass + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + struct HistoryActionID + { + static const HistoryActionID NONE ZYPP_API; + + static const HistoryActionID INSTALL ZYPP_API; + static const HistoryActionID REMOVE ZYPP_API; + static const HistoryActionID REPO_ADD ZYPP_API; + static const HistoryActionID REPO_REMOVE ZYPP_API; + static const HistoryActionID REPO_CHANGE_ALIAS ZYPP_API; + static const HistoryActionID REPO_CHANGE_URL ZYPP_API; + static const HistoryActionID STAMP_COMMAND ZYPP_API; + static const HistoryActionID PATCH_STATE_CHANGE ZYPP_API; + + enum ID + { + NONE_e, + + INSTALL_e, + REMOVE_e, + REPO_ADD_e, + REPO_REMOVE_e, + REPO_CHANGE_ALIAS_e, + REPO_CHANGE_URL_e, + STAMP_COMMAND_e, + PATCH_STATE_CHANGE_e + }; + + HistoryActionID() : _id(NONE_e) {} + + HistoryActionID(ID id) : _id(id) {} + + explicit HistoryActionID(const std::string & strval_r); + + ID toEnum() const { return _id; } + + static HistoryActionID::ID parse(const std::string & strval_r); + + const std::string & asString(bool pad = false) const; + + private: + ID _id; + }; + + /** \relates HistoryActionID */ + inline bool operator==( const HistoryActionID & lhs, const HistoryActionID & rhs ) + { return lhs.toEnum() == rhs.toEnum(); } + + /** \relates HistoryActionID */ + inline bool operator!=( const HistoryActionID & lhs, const HistoryActionID & rhs ) + { return lhs.toEnum() != rhs.toEnum(); } + + /** \relates HistoryActionID */ + std::ostream & operator << (std::ostream & str, const HistoryActionID & id); + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogData + /// \brief A zypp history log line split into fields + /// \ingroup g_ZyppHistory + /// + /// Each valid history log line starts with a date and HistoryActionID + /// field. Subsequent fields depend on the kind of action. See derived + /// classes for convenient access to those flields. + /// + /// HistoryLogData itself provides mostly generic access to the fields + /// plain string values. Derived classes for well known entries tell + /// + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + + using FieldVector = std::vector; + using size_type = FieldVector::size_type; + using const_iterator = FieldVector::const_iterator; + + public: + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has not at least \a expect_r entries + * \note 2 fields (date and action) are always required. + */ + explicit HistoryLogData( FieldVector & fields_r, size_type expect_r = 2 ); + + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or not at least \a expect_r entries. + * \note 2 fields (date and action) are always required. + */ + HistoryLogData( FieldVector & fields_r, HistoryActionID action_r, size_type expect_r = 2 ); + + /** Dtor */ + virtual ~HistoryLogData(); + + /** Factory method creating HistoryLogData classes. + * + * Moves \a fields_r into a HistoryLogData or derived object, depending on the + * HistoryActionID. For known action ids a coresponing HistoryLogData class + * is created, to allow convenient access to the field values. For unknown + * action ids a plain HistoryLogData object is created. \ref HistoryActionID + * \ref NONE_e id used in this case. + * + * \throws ParseException if \a fields_r does not contain the required format. + */ + static Ptr create( FieldVector & fields_r ); + + public: + /** Whether FieldVector is empty. */ + bool empty() const; + + /** Number of fields in vector. */ + size_type size() const; + + /** Iterator pointing to 1st element in vector (or end()). */ + const_iterator begin() const; + + /** Iterator pointing behind the last element in vector. */ + const_iterator end() const; + + /** Access (optional) field by number. + * \returns an empty string if \a idx_r is out of range. + * \see \ref at + */ + const std::string & optionalAt( size_type idx_r ) const; + /** \overload */ + const std::string & operator[]( size_type idx_r ) const + { return optionalAt( idx_r ); } + + /** Access (required) field by number. + * \throws std::out_of_range if \a idx_r is out of range. + * \see \ref optionalAt + */ + const std::string & at( size_type idx_r ) const; + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = 0, ///< date + ACTION_INDEX = 1, ///< HistoryActionID + }; + + public: + Date date() const; ///< date + HistoryActionID action() const; ///< HistoryActionID (or \c NONE_e if unknown) + + public: + class Impl; ///< Implementation class + private: + RWCOW_pointer _pimpl; ///< Pointer to implementation + protected: + HistoryLogData & operator=( const HistoryLogData & ); ///< no base class assign + }; + + /** \relates HistoryLogData Stream output */ + std::ostream & operator<<( std::ostream & str, const HistoryLogData & obj ); + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogDataInstall + /// \brief A zypp history log line for an installed packaged. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogDataInstall : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogDataInstall( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + NAME_INDEX, ///< package name + EDITION_INDEX, ///< package edition + ARCH_INDEX, ///< package architecture + REQBY_INDEX, ///< requested by (user@hostname, pid:appname, or empty (solver)) + REPOALIAS_INDEX, ///< repository providing the package + CHEKSUM_INDEX, ///< package checksum + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string name() const; ///< package name + Edition edition() const; ///< package edition + Arch arch() const; ///< package architecture + std::string reqby() const; ///< requested by (user@hostname, pid:appname, or empty (solver)) + std::string repoAlias() const; ///< repository providing the package + CheckSum checksum() const; ///< package checksum + std::string userdata() const; ///< userdata/transactionID + }; + + //PATCH SEVERITY CATEGORY OLDSTATE NEWSTATE + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogPatchStateChange + /// \brief A zypp history log line for an installed packaged. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogPatchStateChange : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogPatchStateChange( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + NAME_INDEX, ///< patch name + EDITION_INDEX, ///< patch edition + ARCH_INDEX, ///< patch architecture + REPOALIAS_INDEX, ///< repository providing the patch + SEVERITY_INDEX, ///< patch severity + CATEGORY_INDEX, ///< patch category + OLDSTATE_INDEX, ///< the state of the patch before the change + NEWSTATE_INDEX, ///< the state of the patch after the change + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string name() const; ///< package name + Edition edition() const; ///< package edition + Arch arch() const; ///< package architecture + std::string repoAlias() const; ///< repository providing the package + Patch::SeverityFlag severity() const; + Patch::Category category() const; + std::string oldstate() const; + std::string newstate() const; + std::string userdata() const; ///< userdata/transactionID + }; + + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogDataRemove + /// \brief A zypp history log line for a removed packge. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogDataRemove : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogDataRemove( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + NAME_INDEX, ///< package name + EDITION_INDEX, ///< package edition + ARCH_INDEX, ///< package architecture + REQBY_INDEX, ///< requested by (user@hostname, pid:appname, or empty (solver)) + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string name() const; ///< package name + Edition edition() const; ///< package edition + Arch arch() const; ///< package architecture + std::string reqby() const; ///< requested by (user@hostname, pid:appname, or empty (solver)) + std::string userdata() const; ///< userdata/transactionID + }; + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogDataRepoAdd + /// \brief A zypp history log line for an added repository. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogDataRepoAdd : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogDataRepoAdd( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + ALIAS_INDEX, ///< repository alias + URL_INDEX, ///< repository url + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string alias() const; ///< repository alias + Url url() const; ///< repository url + std::string userdata() const; ///< userdata/transactionID + }; + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogDataRepoRemove + /// \brief A zypp history log line for a removed repository. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogDataRepoRemove : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogDataRepoRemove( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + ALIAS_INDEX, ///< repository alias + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string alias() const; ///< repository alias + std::string userdata() const; ///< userdata/transactionID + }; + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogDataRepoAliasChange + /// \brief A zypp history log line for a repo alias change. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogDataRepoAliasChange : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogDataRepoAliasChange( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + OLDALIAS_INDEX, ///< repositories old alias + NEWALIAS_INDEX, ///< repositories new alias + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string oldAlias() const; ///< repositories old alias + std::string newAlias() const; ///< repositories new alias + std::string userdata() const; ///< userdata/transactionID + }; + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogDataRepoUrlChange + /// \brief A zypp history log line for a repo url change. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogDataRepoUrlChange : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogDataRepoUrlChange( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + ALIAS_INDEX, ///< repository alias + NEWURL_INDEX, ///< repositories new url + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string alias() const; ///< repository alias + Url newUrl() const; ///< repositories new url + std::string userdata() const; ///< userdata/transactionID + }; + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogDataStampCommand + /// \brief A zypp history log line identifying the program that + /// triggered the following commit. + /// \ingroup g_ZyppHistory + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogDataStampCommand : public HistoryLogData + { + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + /** Ctor \b moving \a FieldVector (via swap). + * \throws ParseException if \a fields_r has the wrong \ref HistoryActionID or number of fields. + */ + HistoryLogDataStampCommand( FieldVector & fields_r ); + + public: + enum Index ///< indices of known fields + { + DATE_INDEX = HistoryLogData::DATE_INDEX, + ACTION_INDEX = HistoryLogData::ACTION_INDEX, + USER_INDEX, ///< executed by user@hostname + COMMAND_INDEX, ///< the commandline executed + USERDATA_INDEX, ///< userdata/transactionID + }; + + public: + std::string executedBy() const; ///< executed by user@hostname + std::string command() const; ///< the commandline executed + std::string userdata() const; ///< userdata/transactionID + }; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif /* ZYPP_HISTORYLOGDATA_H_ */ diff --git a/zypp/IdString.cc b/zypp/IdString.cc new file mode 100644 index 0000000..2091757 --- /dev/null +++ b/zypp/IdString.cc @@ -0,0 +1,92 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/IdString.cc + * +*/ +#include +#include + +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + const IdString IdString::Null ( sat::detail::noId ); + const IdString IdString::Empty( sat::detail::emptyId ); + + ///////////////////////////////////////////////////////////////// + + IdString::IdString( const char * str_r ) + : _id( ::pool_str2id( myPool().getPool(), str_r, /*create*/true ) ) + {} + + IdString::IdString( const char * str_r, unsigned len_r ) + : _id( ::pool_strn2id( myPool().getPool(), str_r, len_r, /*create*/true ) ) + {} + + IdString::IdString( const std::string & str_r ) + : IdString( str_r.c_str(), str_r.length() ) + {} + + IdString::IdString( boost::string_ref str_r ) + : IdString( str_r.data(), str_r.length() ) + {} + + unsigned IdString::size() const + { return ::strlen( c_str() ); } + + const char * IdString::c_str() const + { return _id ? ::pool_id2str( myPool().getPool(), _id ) : ""; } + + int IdString::compare( const IdString & rhs ) const + { + if ( _id == rhs._id ) + return 0; + // Explicitly handle IdString::Null < "" + if ( ! _id ) + return -1; + if ( ! rhs._id ) + return 1; + return ::strcmp( c_str(), rhs.c_str() ); + } + + int IdString::compare( const char * rhs ) const + { + // Explicitly handle IdString::Null == (const char *)0 + if ( ! _id ) + return rhs ? -1 : 0; + if ( ! rhs ) + return _id ? 1 : 0; + return ::strcmp( c_str(), rhs ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const IdString & obj ) + { + return str << obj.c_str(); + } + + std::ostream & dumpOn( std::ostream & str, const IdString & obj ) + { + return str << '(' << obj.id() << ')' << obj.c_str(); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/IdString.h b/zypp/IdString.h new file mode 100644 index 0000000..00a478d --- /dev/null +++ b/zypp/IdString.h @@ -0,0 +1,249 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/IdString.h + * +*/ +#ifndef ZYPP_SAT_IDSTR_H +#define ZYPP_SAT_IDSTR_H + +#include +#include +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class IdString; + using IdStringSet = std::unordered_set; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : IdString + // + /** Access to the sat-pools string space. + * + * Construction from string will place a copy of the string in the + * string space, if it is not already present. + * + * While comparison differs between \ref IdString::Null and \ref IdString::Empty + * ( \c NULL and \c "" ), both are represented by an empty string \c "". + */ + class ZYPP_API IdString : protected sat::detail::PoolMember + { + public: + using IdType = sat::detail::IdType; + + public: + /** Default ctor, empty string. */ + constexpr IdString() : _id( sat::detail::emptyId ) {} + + /** Ctor from id. */ + constexpr explicit IdString( IdType id_r ) : _id( id_r ) {} + + /** Ctor from string. */ + explicit IdString( const char * str_r ); + + /** Ctor from string (pointer,length). */ + IdString( const char * str_r, unsigned len_r ); + + /** Ctor from string. */ + explicit IdString( const std::string & str_r ); + + /** Ctor from boost::string_ref. */ + explicit IdString( boost::string_ref str_r ); + +#ifdef __cpp_lib_string_view + explicit IdString( std::string_view str_r ) + : IdString( str_r.data(), str_r.size() ) + {} +#endif + + public: + /** No or Null string ( Id \c 0 ). */ + static const IdString Null; + + /** Empty string. */ + static const IdString Empty; + + public: + /** Evaluate in a boolean context ( != \c Null ). */ + constexpr explicit operator bool() const + { return _id; } + + /** Whether the string is empty. + * This is true for \ref Null and \ref Empty. + */ + constexpr bool empty() const + { return( _id == sat::detail::emptyId || _id == sat::detail::noId ); } + + /** The strings size. */ + unsigned size() const; + + public: + /** Conversion to const char * */ + const char * c_str() const; + + /** Conversion to std::string */ + std::string asString() const + { return c_str(); } + + /** Explicit conversion to std::string */ + explicit operator std::string() const + { return asString(); } + +#ifdef __cpp_lib_string_view + /** As \c std::string_view */ + std::string_view asStringView() const + { return { c_str(), size() }; } + + /** Explicit conversion to \c std::string_view */ + explicit operator std::string_view() const + { return asStringView(); } +#endif + + public: + /** Fast compare equal. */ + bool compareEQ( const IdString & rhs ) const + { return( _id == rhs.id() ); } + + /** Compare IdString returning -1,0,1. */ + int compare( const IdString & rhs ) const; + + /** \overload */ + int compare( const char * rhs ) const; + + /** \overload */ + int compare( const std::string & rhs ) const + { return compare( rhs.c_str() ); } + + public: + /** Expert backdoor. */ + IdType id() const + { return _id; } + + private: + IdType _id; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates IdString Stream output */ + std::ostream & operator<<( std::ostream & str, const IdString & obj ) ZYPP_API; + + /** \relates IdString Stream output */ + std::ostream & dumpOn( std::ostream & str, const IdString & obj ) ZYPP_API; + + /** \relates IdString Equal */ + inline bool operator==( const IdString & lhs, const IdString & rhs ) + { return lhs.compareEQ( rhs ); } + /** \overload */ + inline bool operator==( const IdString & lhs, const char * rhs ) + { return lhs.compare( rhs ) == 0; } + /** \overload */ + inline bool operator==( const IdString & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) == 0; } + /** \overload */ + inline bool operator==( const char * lhs, const IdString & rhs ) + { return rhs.compare( lhs ) == 0; } + /** \overload */ + inline bool operator==( const std::string & lhs, const IdString & rhs ) + { return rhs.compare( lhs ) == 0; } + + /** \relates IdString NotEqual */ + inline bool operator!=( const IdString & lhs, const IdString & rhs ) + { return ! lhs.compareEQ( rhs ); } + /** \overload */ + inline bool operator!=( const IdString & lhs, const char * rhs ) + { return lhs.compare( rhs ) != 0; } + /** \overload */ + inline bool operator!=( const IdString & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) != 0; } + /** \overload */ + inline bool operator!=( const char * lhs, const IdString & rhs ) + { return rhs.compare( lhs ) != 0; } + /** \overload */ + inline bool operator!=( const std::string & lhs, const IdString & rhs ) + { return rhs.compare( lhs ) != 0; } + + /** \relates IdString Less */ + inline bool operator<( const IdString & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) < 0; } + /** \overload */ + inline bool operator<( const IdString & lhs, const char * rhs ) + { return lhs.compare( rhs ) < 0; } + /** \overload */ + inline bool operator<( const IdString & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) < 0; } + /** \overload */ + inline bool operator<( const char * lhs, const IdString & rhs ) + { return rhs.compare( lhs ) >= 0; } + /** \overload */ + inline bool operator<( const std::string & lhs, const IdString & rhs ) + { return rhs.compare( lhs ) >= 0; } + + /** \relates IdString LessEqual*/ + inline bool operator<=( const IdString & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) <= 0; } + /** \overload */ + inline bool operator<=( const IdString & lhs, const char * rhs ) + { return lhs.compare( rhs ) <= 0; } + /** \overload */ + inline bool operator<=( const IdString & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) <= 0; } + /** \overload */ + inline bool operator<=( const char * lhs, const IdString & rhs ) + { return rhs.compare( lhs ) > 0; } + /** \overload */ + inline bool operator<=( const std::string & lhs, const IdString & rhs ) + { return rhs.compare( lhs ) > 0; } + + /** \relates IdString Greater */ + inline bool operator>( const IdString & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) > 0; } + /** \overload */ + inline bool operator>( const IdString & lhs, const char * rhs ) + { return lhs.compare( rhs ) > 0; } + /** \overload */ + inline bool operator>( const IdString & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) > 0; } + /** \overload */ + inline bool operator>( const char * lhs, const IdString & rhs ) + { return rhs.compare( lhs ) <= 0; } + /** \overload */ + inline bool operator>( const std::string & lhs, const IdString & rhs ) + { return rhs.compare( lhs ) <= 0; } + + /** \relates IdString GreaterEqual */ + inline bool operator>=( const IdString & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) >= 0; } + /** \overload */ + inline bool operator>=( const IdString & lhs, const char * rhs ) + { return lhs.compare( rhs ) >= 0; } + /** \overload */ + inline bool operator>=( const IdString & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) >= 0; } + /** \overload */ + inline bool operator>=( const char * lhs, const IdString & rhs ) + { return rhs.compare( lhs ) < 0; } + /** \overload */ + inline bool operator>=( const std::string & lhs, const IdString & rhs ) + { return rhs.compare( lhs ) < 0; } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +ZYPP_DEFINE_ID_HASHABLE( ::zypp::IdString ); + +#endif // ZYPP_SAT_IDSTR_H diff --git a/zypp/IdStringType.h b/zypp/IdStringType.h new file mode 100644 index 0000000..87e019a --- /dev/null +++ b/zypp/IdStringType.h @@ -0,0 +1,353 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/IdStringType.h + * +*/ +#ifndef ZYPP_IDSTRINGTYPE_H +#define ZYPP_IDSTRINGTYPE_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : IdStringType + // + /** Base class for creating \ref IdString based types. + * + * Just by deriving from \ref IdStringType a class provides all + * the operations an \ref IdString does. (incl. conversion to string types, + * comparison of string types and stream output). + * + * To disable any comparison, declare (but do not define) \ref _doCompare + * in your class. + * \code + * class NoCompare : public IdStringType + * { + * private: + * static int _doCompare( const char * lhs, const char * rhs ); + * + * }; + * \endcode + * + * If you need a different than the default lexicographical + * order, write your own \ref _doCompare. + * + * \code + * // uses default lexicographical order + * class CaseCmp : public IdStringType + * { + * public: + * CaseCmp() {} + * explicit CaseCmp( const char * cstr_r ) : _str( cstr_r ) {} + * private: + * friend class IdStringType; + * IdString _str; + * }; + * + * // uses case insensitive comparison order + * class NoCaseCmp : public IdStringType + * { + * public: + * NoCaseCmp() {} + * explicit NoCaseCmp( const char * cstr_r ) : _str( cstr_r ) {} + * private: + * static int _doCompare( const char * lhs, const char * rhs ) + * { + * if ( lhs == rhs ) return 0; + * if ( lhs && rhs ) return ::strcasecmp( lhs, rhs ); + * return( lhs ? 1 : -1 ); + * } + * private: + * friend class IdStringType; + * IdString _str; + * }; + * + * CaseCmp ca( "a" ); + * NoCaseCmp na( "a" ); + * DBG << "ca == a ? " << (ca == "a") << endl; // ca == a ? 1 + * DBG << "ca == A ? " << (ca == "A") << endl; // ca == A ? 0 + * DBG << "na == a ? " << (na == "a") << endl; // na == a ? 1 + * DBG << "na == A ? " << (na == "A") << endl; // na == A ? 1 + * \endcode + * \todo allow redefinition of order vis _doCompare not only for char* but on any level + * \ingroup g_CRTP + */ + template + class IdStringType : protected sat::detail::PoolMember + { + public: + using IdType = IdString::IdType; + + protected: + IdStringType() = default; + IdStringType(const IdStringType &) = default; + IdStringType &operator=(const IdStringType &) = default; + IdStringType(IdStringType &&) noexcept = default; + IdStringType &operator=(IdStringType &&) noexcept = default; + ~IdStringType() = default; + + private: + const Derived & self() const { return *static_cast( this ); } + + public: + IdString idStr() const { return self()._str; } + + bool empty() const { return idStr().empty(); } + unsigned size() const { return idStr().size(); } + const char * c_str() const { return idStr().c_str(); } + std::string asString() const { return idStr().asString(); } + +#ifdef __cpp_lib_string_view + std::string_view asStringView() const { return idStr().asStringView(); } + explicit operator std::string_view() const { return asStringView(); } +#endif + + IdType id() const { return idStr().id(); } + + public: + /** Evaluate in a boolean context ( ! empty() ). */ + explicit operator bool() const + { return ! empty(); } + + /** Explicit conversion to IdString */ + explicit operator IdString() const + { return idStr(); } + + /** Explicit conversion to std::string */ + explicit operator std::string() const + { return asString(); } + + public: + // - break it down to idString/const char* <=> idString/cont char* + // - handle idString(0)/NULL being the least value + // - everything else goes to _doCompare (no NULL) + static int compare( const Derived & lhs, const Derived & rhs ) { return compare( lhs.idStr(), rhs.idStr() ); } + static int compare( const Derived & lhs, const IdString & rhs ) { return compare( lhs.idStr(), rhs ); } + static int compare( const Derived & lhs, const std::string & rhs ) { return compare( lhs.idStr(), rhs.c_str() ); } + static int compare( const Derived & lhs, const char * rhs ) { return compare( lhs.idStr(), rhs );} + + static int compare( const IdString & lhs, const Derived & rhs ) { return compare( lhs, rhs.idStr() ); } + static int compare( const IdString & lhs, const IdString & rhs ) { return lhs == rhs ? 0 : Derived::_doCompare( (lhs ? lhs.c_str() : (const char *)0 ), + (rhs ? rhs.c_str() : (const char *)0 ) ); } + static int compare( const IdString & lhs, const std::string & rhs ) { return compare( lhs, rhs.c_str() ); } + static int compare( const IdString & lhs, const char * rhs ) { return Derived::_doCompare( (lhs ? lhs.c_str() : (const char *)0 ), rhs ); } + + static int compare( const std::string & lhs, const Derived & rhs ) { return compare( lhs.c_str(), rhs.idStr() ); } + static int compare( const std::string & lhs, const IdString & rhs ) { return compare( lhs.c_str(), rhs ); } + static int compare( const std::string & lhs, const std::string & rhs ) { return compare( lhs.c_str(), rhs.c_str() ); } + static int compare( const std::string & lhs, const char * rhs ) { return compare( lhs.c_str(), rhs ); } + + static int compare( const char * lhs, const Derived & rhs ) { return compare( lhs, rhs.idStr() ); } + static int compare( const char * lhs, const IdString & rhs ) { return Derived::_doCompare( lhs, (rhs ? rhs.c_str() : (const char *)0 ) ); } + static int compare( const char * lhs, const std::string & rhs ) { return compare( lhs, rhs.c_str() ); } + static int compare( const char * lhs, const char * rhs ) { return Derived::_doCompare( lhs, rhs ); } + + public: + int compare( const Derived & rhs ) const { return compare( idStr(), rhs.idStr() ); } + int compare( const IdStringType & rhs ) const { return compare( idStr(), rhs.idStr() ); } + int compare( const IdString & rhs ) const { return compare( idStr(), rhs ); } + int compare( const std::string & rhs ) const { return compare( idStr(), rhs.c_str() ); } + int compare( const char * rhs ) const { return compare( idStr(), rhs ); } + + private: + static inline int _doCompare( const char * lhs, const char * rhs ) ZYPP_API + { + if ( ! lhs ) return rhs ? -1 : 0; + return rhs ? ::strcmp( lhs, rhs ) : 1; + } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates IdStringType Stream output */ + template + inline std::ostream & operator<<( std::ostream & str, const IdStringType & obj ) + { return str << obj.c_str(); } + + /** \relates IdStringType Equal */ + template + inline bool operator==( const IdStringType & lhs, const IdStringType & rhs ) + { return lhs.compare( rhs ) == 0; } + /** \overload */ + template + inline bool operator==( const IdStringType & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) == 0; } + /** \overload */ + template + inline bool operator==( const IdStringType & lhs, const char * rhs ) + { return lhs.compare( rhs ) == 0; } + /** \overload */ + template + inline bool operator==( const IdStringType & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) == 0; } + /** \overload */ + template + inline bool operator==( const IdString & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) == 0; } + /** \overload */ + template + inline bool operator==( const char * lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) == 0; } + /** \overload */ + template + inline bool operator==( const std::string & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) == 0; } + + /** \relates IdStringType NotEqual */ + template + inline bool operator!=( const IdStringType & lhs, const IdStringType & rhs ) + { return lhs.compare( rhs ) != 0; } + /** \overload */ + template + inline bool operator!=( const IdStringType & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) != 0; } + /** \overload */ + template + inline bool operator!=( const IdStringType & lhs, const char * rhs ) + { return lhs.compare( rhs ) != 0; } + /** \overload */ + template + inline bool operator!=( const IdStringType & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) != 0; } + /** \overload */ + template + inline bool operator!=( const IdString & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) != 0; } + /** \overload */ + template + inline bool operator!=( const char * lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) != 0; } + /** \overload */ + template + inline bool operator!=( const std::string & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) != 0; } + + /** \relates IdStringType Less */ + template + inline bool operator<( const IdStringType & lhs, const IdStringType & rhs ) + { return lhs.compare( rhs ) < 0; } + /** \overload */ + template + inline bool operator<( const IdStringType & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) < 0; } + /** \overload */ + template + inline bool operator<( const IdStringType & lhs, const char * rhs ) + { return lhs.compare( rhs ) < 0; } + /** \overload */ + template + inline bool operator<( const IdStringType & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) < 0; } + /** \overload */ + template + inline bool operator<( const IdString & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) >= 0; } + /** \overload */ + template + inline bool operator<( const char * lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) >= 0; } + /** \overload */ + template + inline bool operator<( const std::string & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) >= 0; } + + /** \relates IdStringType LessEqual */ + template + inline bool operator<=( const IdStringType & lhs, const IdStringType & rhs ) + { return lhs.compare( rhs ) <= 0; } + /** \overload */ + template + inline bool operator<=( const IdStringType & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) <= 0; } + /** \overload */ + template + inline bool operator<=( const IdStringType & lhs, const char * rhs ) + { return lhs.compare( rhs ) <= 0; } + /** \overload */ + template + inline bool operator<=( const IdStringType & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) <= 0; } + /** \overload */ + template + inline bool operator<=( const IdString & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) > 0; } + /** \overload */ + template + inline bool operator<=( const char * lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) > 0; } + /** \overload */ + template + inline bool operator<=( const std::string & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) > 0; } + + /** \relates IdStringType Greater */ + template + inline bool operator>( const IdStringType & lhs, const IdStringType & rhs ) + { return lhs.compare( rhs ) > 0; } + /** \overload */ + template + inline bool operator>( const IdStringType & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) > 0; } + /** \overload */ + template + inline bool operator>( const IdStringType & lhs, const char * rhs ) + { return lhs.compare( rhs ) > 0; } + /** \overload */ + template + inline bool operator>( const IdStringType & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) > 0; } + /** \overload */ + template + inline bool operator>( const IdString & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) <= 0; } + /** \overload */ + template + inline bool operator>( const char * lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) <= 0; } + /** \overload */ + template + inline bool operator>( const std::string & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) <= 0; } + + /** \relates IdStringType GreaterEqual */ + template + inline bool operator>=( const IdStringType & lhs, const IdStringType & rhs ) + { return lhs.compare( rhs ) >= 0; } + /** \overload */ + template + inline bool operator>=( const IdStringType & lhs, const IdString & rhs ) + { return lhs.compare( rhs ) >= 0; } + /** \overload */ + template + inline bool operator>=( const IdStringType & lhs, const char * rhs ) + { return lhs.compare( rhs ) >= 0; } + /** \overload */ + template + inline bool operator>=( const IdStringType & lhs, const std::string & rhs ) + { return lhs.compare( rhs ) >= 0; } + /** \overload */ + template + inline bool operator>=( const IdString & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) < 0; } + /** \overload */ + template + inline bool operator>=( const char * lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) < 0; } + /** \overload */ + template + inline bool operator>=( const std::string & lhs, const IdStringType & rhs ) + { return rhs.compare( lhs ) < 0; } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_IDSTRINGTYPE_H diff --git a/zypp/InstanceId.cc b/zypp/InstanceId.cc new file mode 100644 index 0000000..70a088c --- /dev/null +++ b/zypp/InstanceId.cc @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/InstanceId.cc + * +*/ +//#include +//#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + std::string InstanceId::getIdFor( sat::Solvable slv_r ) const + { + if ( ! slv_r ) + return std::string(); + + std::string ret( _namespace ); + if ( ! ret.empty() ) + ret += ':'; + + if ( slv_r.isKind() ) // libsolv uses no namespace in SrcPackage ident! + { + ret += ResKind::srcpackage.c_str(); + ret += ':'; + } + + ret += str::form( "%s-%s-%s.%s@%s", + slv_r.ident().c_str(), + slv_r.edition().version().c_str(), + slv_r.edition().release().c_str(), + slv_r.arch().c_str(), + slv_r.repository().alias().c_str() ); + return ret; + } + + PoolItem InstanceId::findPoolItem( const std::string& str_r ) const + { + // [namespace:]--.@ + std::string::size_type namespaceOff( _namespace.size() ); + + if ( namespaceOff ) + { + if ( ! str::hasPrefix( str_r, _namespace ) || str_r[namespaceOff] != ':' ) + return PoolItem(); + ++namespaceOff; // for the ':' + } + + // check repo + std::string::size_type rdelim( str_r.find( '@' ) ); + if ( rdelim == std::string::npos ) + return PoolItem(); + + Repository repo( sat::Pool::instance().reposFind( str_r.substr( rdelim+1) ) ); + if ( ! repo ) + return PoolItem(); + + // check n-v-r.a from behind + std::string::size_type delim = str_r.rfind( '.', rdelim ); + if ( delim == std::string::npos ) + return PoolItem(); + + Arch arch( str_r.substr( delim+1, rdelim-delim-1 ) ); + + // v-r starts at one but last '-' + rdelim = delim; + delim = str_r.rfind( '-', rdelim ); + if ( delim == std::string::npos ) + return PoolItem(); + + if ( delim == rdelim-1 ) // supress an empty release + rdelim = delim; + + delim = str_r.rfind( '-', delim-1 ); + if ( delim == std::string::npos ) + return PoolItem(); + + Edition ed( str_r.substr( delim+1, rdelim-delim-1 ) ); + + // eveythig before is name (except the leading ":") + std::string identstring( str_r.substr( namespaceOff, delim-namespaceOff ) ); + + // now lookup in pool.. + sat::Solvable::SplitIdent ident( (IdString(identstring)) ); + ResPool pool( ResPool::instance() ); + for_( it, pool.byIdentBegin( ident.kind(), ident.name() ), pool.byIdentEnd( ident.kind(), ident.name() ) ) + { + sat::Solvable solv( (*it).satSolvable() ); + if ( solv.repository() == repo && solv.arch() == arch && solv.edition() == ed ) + { + return *it; + } + } + return PoolItem(); + } + + bool InstanceId::isSystemId( const std::string& str_r ) const + { return str::hasSuffix( str_r, Repository::systemRepoAlias() ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/InstanceId.h b/zypp/InstanceId.h new file mode 100644 index 0000000..3121488 --- /dev/null +++ b/zypp/InstanceId.h @@ -0,0 +1,110 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/InstanceId.h + * +*/ +#ifndef ZYPP_INSTANCEID_H +#define ZYPP_INSTANCEID_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : InstanceId + // + /** + * Build string to identify/retrieve a specific \a Solvable. + * + * "[:]--.@" + * + * Any namespace that prepends the InstanceIds must be + * passed to the ctor. Conversion to/from instanceId can + * be done via function call \c operator(). + * + * \code + * InstanceId instanceId( "SUSE:" ); // using a namespace + * + * ResPool pool( ResPool::instance() ); + * for_( it, pool.begin(), pool.end() ) + * { + * std::cout << instanceId(*it) << endl; + * } + * \endcode + */ + class ZYPP_API InstanceId + { + public: + /** Default ctor empty empty namespace */ + InstanceId() + {} + + /** Ctor taking namespace */ + InstanceId( std::string namespace_r ) + : _namespace(std::move( namespace_r )) + {} + + public: + /** \ref Solvable to \ref InstanceId string. */ + std::string getIdFor( sat::Solvable slv_r ) const; + /** \ref PoolItem to \ref InstanceId string. */ + std::string getIdFor( const PoolItem & pi_r ) const + { return getIdFor( pi_r.satSolvable() ); } + + /** \ref InstanceId string to \ref Solvable. */ + sat::Solvable findSolvable( const std::string &str_r ) const + { return findPoolItem( str_r ).satSolvable(); } + /** \ref InstanceId string to \ref PoolItem. */ + PoolItem findPoolItem( const std::string& str_r ) const; + + public: + /** \ref Solvable to \ref InstanceId string. */ + std::string operator()( sat::Solvable slv_r ) const + { return getIdFor( slv_r ); } + + /** \ref PoolItem to \ref InstanceId string. */ + std::string operator()( const PoolItem & pi_r ) const + { return getIdFor( pi_r ); } + + /** \ref InstanceId string to \ref PoolItem. */ + PoolItem operator()( const std::string &str_r ) const + { return findPoolItem( str_r ); } + + /** Quick test whether the InstanceId string would refer + * to a system (installed) Solvable. */ + bool isSystemId( const std::string& str_r ) const; + + public: + /** The namespace in use. */ + const std::string & getNamespace() const + { return _namespace; } + + /** Set a new namespace. */ + void setNamespace( const std::string & namespace_r ) + { _namespace = namespace_r; } + + /** Set no (empty) namespace. */ + void unsetNamespace() + { _namespace.clear(); } + + private: + std::string _namespace; + }; + ///////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_INSTANCEID_H diff --git a/zypp/KVMap.h b/zypp/KVMap.h new file mode 100644 index 0000000..5971cf2 --- /dev/null +++ b/zypp/KVMap.h @@ -0,0 +1 @@ +#include diff --git a/zypp/KeyContext.h b/zypp/KeyContext.h new file mode 100644 index 0000000..2768a7d --- /dev/null +++ b/zypp/KeyContext.h @@ -0,0 +1,27 @@ +#ifndef KEYCONTEXT_H_ +#define KEYCONTEXT_H_ + +#include + +namespace zypp { + + struct KeyContext + { + public: + KeyContext(){} + KeyContext( const RepoInfo & repoinfo ) : _repoInfo( repoinfo ) {} + + /** Is the context unknown? */ + bool empty() const { return _repoInfo.alias().empty(); } + + public: + const RepoInfo repoInfo() const { return _repoInfo; } + void setRepoInfo(const RepoInfo & repoinfo) { _repoInfo = repoinfo; } + + private: + RepoInfo _repoInfo; + }; + +} + +#endif /*KEYCONTEXT_H_*/ diff --git a/zypp/KeyManager.cc b/zypp/KeyManager.cc new file mode 100644 index 0000000..c276fea --- /dev/null +++ b/zypp/KeyManager.cc @@ -0,0 +1,545 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::gpg" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + // @TODO [threading] + // make sure to call the init code of gpgme only once + // this might need to be moved to a different location when + // threads are introduced into libzypp + boost::once_flag gpgme_init_once = BOOST_ONCE_INIT; + + void initGpgme () + { + const char *version = gpgme_check_version(NULL); + if ( version ) + { + MIL << "Initialized libgpgme version: " << version << endl; + } + else + { + MIL << "Initialized libgpgme with unknown version" << endl; + } + } + + //using boost::interprocess pointer because it allows a custom deleter + using GpgmeDataPtr = boost::interprocess::scoped_ptr>; + using GpgmeKeyPtr = boost::interprocess::scoped_ptr<_gpgme_key, boost::function>; + using FILEPtr = boost::interprocess::scoped_ptr>; + + struct GpgmeErr + { + GpgmeErr( gpgme_error_t err_r = GPG_ERR_NO_ERROR ) + : _err( err_r ) + {} + operator gpgme_error_t() const { return _err; } + private: + gpgme_error_t _err; + }; + + std::ostream & operator<<( std::ostream & str, const GpgmeErr & obj ) + { return str << "<" << gpgme_strsource(obj) << "> " << gpgme_strerror(obj); } + + /** \relates gpgme_import_result_t Stream output. */ + std::ostream & operator<<( std::ostream & str, const _gpgme_op_import_result & obj ) + { + str << "gpgme_op_import_result {" << endl; + str << " " << obj.considered << " The total number of considered keys." << endl; + str << " " << obj.no_user_id << " The number of keys without user ID." << endl; + str << " " << obj.imported << " The total number of imported keys." << endl; + str << " " << obj.imported_rsa << " imported RSA keys." << endl; + str << " " << obj.unchanged << " unchanged keys." << endl; + str << " " << obj.new_user_ids << " new user IDs." << endl; + str << " " << obj.new_sub_keys << " new sub keys." << endl; + str << " " << obj.new_signatures << " new signatures." << endl; + str << " " << obj.new_revocations << " new revocations." << endl; + str << " " << obj.secret_read << " secret keys read." << endl; + str << " " << obj.secret_imported << " imported secret keys." << endl; + str << " " << obj.secret_unchanged << " unchanged secret keys." << endl; + str << " " << obj.not_imported << " keys not imported." << endl; + for ( gpgme_import_status_t p = obj.imports; p; p = p->next ) + { + str << " - " << p->fpr << ": " << p->result << endl; + } + // In V.1.11: str << " " << obj.skipped_v3_keys << " skipped v3 keys." << endl; + return str << "}"; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + struct GpgmeException : public KeyRingException + { + GpgmeException( const std::string & in_r, const GpgmeErr & err_r ) + : KeyRingException( str::Format( "libgpgme error in '%1%': %2%" ) % in_r % err_r ) + {} + }; + + class KeyManagerCtx::Impl + { + public: + Impl() + { boost::call_once( gpgme_init_once, initGpgme ); } + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() { + if (_ctx) + gpgme_release(_ctx); + } + + /** Return all fingerprints found in \a signature_r. */ + std::list readSignaturesFprs( const Pathname & signature_r ) + { return readSignaturesFprsOptVerify( signature_r ); } + + /** Return all fingerprints found in \a signature_r. */ + std::list readSignaturesFprs( const ByteArray & signature_r ) + { return readSignaturesFprsOptVerify( signature_r ); } + + /** Tries to verify the \a file_r using \a signature_r. */ + bool verifySignaturesFprs( const Pathname & file_r, const Pathname & signature_r ) + { + bool verify = false; + readSignaturesFprsOptVerify( signature_r, file_r, &verify ); + return verify; + } + + template< typename Callback > + bool importKey(GpgmeDataPtr &data, Callback &&calcDataSize ); + + gpgme_ctx_t _ctx { nullptr }; + bool _volatile { false }; ///< readKeyFromFile workaround bsc#1140670 + + private: + /** Return all fingerprints found in \a signature_r and optionally verify the \a file_r on the fly. + * + * If \a verify_r is not a \c nullptr, log verification errors and return + * whether all signatures are good. + */ + std::list readSignaturesFprsOptVerify( const Pathname & signature_r, const Pathname & file_r = "/dev/null", bool * verify_r = nullptr ); + std::list readSignaturesFprsOptVerify( const ByteArray& keyData_r, const Pathname & file_r = "/dev/null", bool * verify_r = nullptr ); + std::list readSignaturesFprsOptVerify( GpgmeDataPtr &sigData, const Pathname & file_r = "/dev/null", bool * verify_r = nullptr ); + }; + +std::list KeyManagerCtx::Impl::readSignaturesFprsOptVerify( const Pathname & signature_r, const Pathname & file_r, bool * verify_r ) +{ + //lets be pessimistic + if ( verify_r ) + *verify_r = false; + + if (!PathInfo( signature_r ).isExist()) + return std::list(); + + FILEPtr sigFile(fopen(signature_r.c_str(), "rb"), fclose); + if (!sigFile) { + ERR << "Unable to open signature file '" << signature_r << "'" <(); + } + + GpgmeDataPtr sigData(nullptr, gpgme_data_release); + GpgmeErr err = gpgme_data_new_from_stream (&sigData.get(), sigFile.get()); + if (err) { + ERR << err << endl; + return std::list(); + } + + return readSignaturesFprsOptVerify( sigData, file_r, verify_r ); +} + +std::list KeyManagerCtx::Impl::readSignaturesFprsOptVerify( const ByteArray &keyData_r, const filesystem::Pathname &file_r, bool *verify_r ) +{ + //lets be pessimistic + if ( verify_r ) + *verify_r = false; + + GpgmeDataPtr sigData(nullptr, gpgme_data_release); + GpgmeErr err = gpgme_data_new_from_mem(&sigData.get(), keyData_r.data(), keyData_r.size(), 1 ); + if (err) { + ERR << err << endl; + return std::list(); + } + + return readSignaturesFprsOptVerify( sigData, file_r, verify_r ); +} + +std::list KeyManagerCtx::Impl::readSignaturesFprsOptVerify(GpgmeDataPtr &sigData, const filesystem::Pathname &file_r, bool *verify_r) +{ + //lets be pessimistic + if ( verify_r ) + *verify_r = false; + + FILEPtr dataFile(fopen(file_r.c_str(), "rb"), fclose); + if (!dataFile) + return std::list(); + + GpgmeDataPtr fileData(nullptr, gpgme_data_release); + GpgmeErr err = gpgme_data_new_from_stream (&fileData.get(), dataFile.get()); + if (err) { + ERR << err << endl; + return std::list(); + } + + err = gpgme_op_verify(_ctx, sigData.get(), fileData.get(), NULL); + if (err != GPG_ERR_NO_ERROR) { + ERR << err << endl; + return std::list(); + } + + gpgme_verify_result_t res = gpgme_op_verify_result(_ctx); + if (!res || !res->signatures) { + ERR << "Unable to read signature fingerprints" <(); + } + + bool foundBadSignature = false; + bool foundGoodSignature = false; + std::list signatures; + for ( gpgme_signature_t sig = res->signatures; sig; sig = sig->next ) { + + if ( sig->fpr ) + { + // bsc#1100427: With libgpgme11-1.11.0 and if a recent gpg version was used + // to create the signature, the field may contain the full fingerprint, but + // we're expected to return the ID. + // [https://github.com/gpg/gpgme/commit/478d1650bbef84958ccce439fac982ef57b16cd0] + std::string id( sig->fpr ); + if ( id.size() > 16 ) + id = id.substr( id.size()-16 ); + + DBG << "Found signature with ID: " << id << " in " << file_r << std::endl; + signatures.push_back( std::move(id) ); + } + + if ( verify_r && sig->status != GPG_ERR_NO_ERROR ) { + const auto status = gpgme_err_code(sig->status); + + // bsc#1180721: libgpgme started to return signatures of unknown keys, which breaks + // our workflow when verifying files that have multiple signatures, including some that are + // not in the trusted keyring. We should not fail if we have unknown or expired keys and at least a good one. + // We will however keep the behaviour of failing if we find a bad signatures even if others are good. + if ( status != GPG_ERR_KEY_EXPIRED && status != GPG_ERR_NO_PUBKEY ) + { + WAR << "Failed signature check: " << file_r << " " << GpgmeErr(sig->status) << endl; + if ( !foundBadSignature ) + foundBadSignature = true; + } + else + { + WAR << "Legacy: Ignore expired or unknown key: " << file_r << " " << GpgmeErr(sig->status) << endl; + // for now treat expired keys as good signature + if ( status == GPG_ERR_KEY_EXPIRED ) + foundGoodSignature = true; + } + } else { + foundGoodSignature = true; + } + } + + if ( verify_r ) + *verify_r = (!foundBadSignature) && foundGoodSignature; + return signatures; +} + +KeyManagerCtx::KeyManagerCtx() +: _pimpl( new Impl ) +{} + +KeyManagerCtx KeyManagerCtx::createForOpenPGP() +{ + static Pathname tmppath( zypp::myTmpDir() / "PublicKey" ); + filesystem::assert_dir( tmppath ); + + KeyManagerCtx ret { createForOpenPGP( tmppath ) }; + ret._pimpl->_volatile = true; // readKeyFromFile workaround bsc#1140670 + return ret; +} + +KeyManagerCtx KeyManagerCtx::createForOpenPGP( const Pathname & keyring_r ) +{ + DBG << "createForOpenPGP(" << keyring_r << ")" << endl; + + KeyManagerCtx ret; + gpgme_ctx_t & ctx { ret._pimpl->_ctx }; + + // create the context + GpgmeErr err = gpgme_new( &ctx ); + if ( err != GPG_ERR_NO_ERROR ) + ZYPP_THROW( GpgmeException( "gpgme_new", err ) ); + + // use OpenPGP + err = gpgme_set_protocol( ctx, GPGME_PROTOCOL_OpenPGP ); + if ( err != GPG_ERR_NO_ERROR ) + ZYPP_THROW( GpgmeException( "gpgme_set_protocol", err ) ); + + if ( !keyring_r.empty() ) { + // get engine information to read current state + gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info( ctx ); + if ( !enginfo ) + ZYPP_THROW( GpgmeException( "gpgme_ctx_get_engine_info", err ) ); + + err = gpgme_ctx_set_engine_info( ctx, GPGME_PROTOCOL_OpenPGP, enginfo->file_name, keyring_r.c_str() ); + if ( err != GPG_ERR_NO_ERROR ) + ZYPP_THROW( GpgmeException( "gpgme_ctx_set_engine_info", err ) ); + } + + return ret; +} + +Pathname KeyManagerCtx::homedir() const +{ + Pathname ret; + if ( gpgme_engine_info_t enginfo = gpgme_ctx_get_engine_info( _pimpl->_ctx ) ) + ret = enginfo->home_dir; + return ret; +} + +std::list KeyManagerCtx::listKeys() +{ + std::list ret; + GpgmeErr err = GPG_ERR_NO_ERROR; + + // Reset gpgme_keylist_mode on return! + AutoDispose guard { gpgme_get_keylist_mode( _pimpl->_ctx ), bind( &gpgme_set_keylist_mode, _pimpl->_ctx, _1 ) }; + // Let listed keys include signatures (required if PublicKeyData are created from the key) + if ( (err = gpgme_set_keylist_mode( _pimpl->_ctx, GPGME_KEYLIST_MODE_LOCAL | GPGME_KEYLIST_MODE_SIGS )) != GPG_ERR_NO_ERROR ) { + ERR << "gpgme_set_keylist_mode: " << err << endl; + return ret; + } + + if ( (err = gpgme_op_keylist_start( _pimpl->_ctx, NULL, 0 )) != GPG_ERR_NO_ERROR ) { + ERR << "gpgme_op_keylist_start: " << err << endl; + return ret; + } + // Close list operation on return! + AutoDispose guard2 { _pimpl->_ctx, &gpgme_op_keylist_end }; + + AutoDispose key { nullptr, &gpgme_key_release }; + for ( ; gpgme_op_keylist_next( _pimpl->_ctx, &(*key) ) == GPG_ERR_NO_ERROR; key.getDispose()( key ) ) { + PublicKeyData data { PublicKeyData::fromGpgmeKey( key ) }; + if ( data ) + ret.push_back( data ); + } + + return ret; +} + +std::list KeyManagerCtx::readKeyFromFile( const Pathname & keyfile_r ) +{ + // bsc#1140670: GPGME does not support reading keys from a keyfile using + // gpgme_data_t and gpgme_op_keylist_from_data_start. Despite GPGME_KEYLIST_MODE_SIGS + // the signatures are missing, but we need them to create proper PublicKeyData objects. + // While this is not resolved, we read into a temp. keyring. Impl::_volatile helps + // to detect whether we can clear and import into the current context or need to + // create a temp. one. + std::list ret; + + if ( _pimpl->_volatile ) { + // in a volatile context we can simple clear the keyring... + filesystem::clean_dir( homedir() ); + if ( importKey( keyfile_r ) ) + ret = listKeys(); + } else { + // read in a volatile context + ret = createForOpenPGP().readKeyFromFile( keyfile_r ); + } + + return ret; +} + +bool KeyManagerCtx::verify(const Pathname &file, const Pathname &signature) +{ + return _pimpl->verifySignaturesFprs(file, signature); +} + +bool KeyManagerCtx::exportKey(const std::string &id, std::ostream &stream) +{ + GpgmeErr err = GPG_ERR_NO_ERROR; + + GpgmeKeyPtr foundKey; + + //search for requested key id + gpgme_key_t key = nullptr; + gpgme_op_keylist_start(_pimpl->_ctx, NULL, 0); + while (!(err = gpgme_op_keylist_next(_pimpl->_ctx, &key))) { + if (key->subkeys && id == str::asString(key->subkeys->keyid)) { + GpgmeKeyPtr(key, gpgme_key_release).swap(foundKey); + break; + } + gpgme_key_release(key); + } + gpgme_op_keylist_end(_pimpl->_ctx); + + if (!foundKey) { + WAR << "Key " << id << "not found" << endl; + return false; + } + + //function needs a array of keys to export + gpgme_key_t keyarray[2]; + keyarray[0] = foundKey.get(); + keyarray[1] = NULL; + + GpgmeDataPtr out(nullptr, gpgme_data_release); + err = gpgme_data_new (&out.get()); + if (err) { + ERR << err << endl; + return false; + } + + //format as ascii armored + gpgme_set_armor (_pimpl->_ctx, 1); + // bsc#1179222: Remove outdated self signatures when exporting the key. + // The keyring does not order the signatures when multiple versions of the + // same key are imported. Rpm however uses the 1st to compute the -release + // of the gpg-pubkey. So we export only the latest to get a proper-release. + err = gpgme_op_export_keys (_pimpl->_ctx, keyarray, GPGME_EXPORT_MODE_MINIMAL, out.get()); + if (!err) { + int ret = gpgme_data_seek (out.get(), 0, SEEK_SET); + if (ret) { + ERR << "Unable to seek in exported key data" << endl; + return false; + } + + const int bufsize = 512; + char buf[bufsize + 1]; + while ((ret = gpgme_data_read(out.get(), buf, bufsize)) > 0) { + stream.write(buf, ret); + } + + //failed to read from buffer + if (ret < 0) { + ERR << "Unable to read exported key data" << endl; + return false; + } + } else { + ERR << "Error exporting key: "<< err << endl; + return false; + } + + //if we reach this point export was successful + return true; +} + +bool KeyManagerCtx::importKey(const Pathname &keyfile) +{ + if ( !PathInfo( keyfile ).isExist() ) { + ERR << "Keyfile '" << keyfile << "' does not exist."; + return false; + } + + GpgmeDataPtr data(nullptr, gpgme_data_release); + GpgmeErr err; + + err = gpgme_data_new_from_file(&data.get(), keyfile.c_str(), 1); + if (err) { + ERR << "Error importing key: "<< err << endl; + return false; + } + + return _pimpl->importKey( data, [&](){ return PathInfo(keyfile).size(); } ); +} + +bool KeyManagerCtx::importKey( const ByteArray &keydata ) +{ + GpgmeDataPtr data(nullptr, gpgme_data_release); + GpgmeErr err; + + err = gpgme_data_new_from_mem( &data.get(), keydata.data(), keydata.size(), 1); + if (err) { + ERR << "Error importing key: "<< err << endl; + return false; + } + + return _pimpl->importKey( data, [&](){ return keydata.size(); } ); +} + +template +bool KeyManagerCtx::Impl::importKey(GpgmeDataPtr &data, Callback &&calcDataSize) +{ + GpgmeErr err; + err = gpgme_op_import( _ctx, data.get() ); + if (err) { + ERR << "Error importing key: "<< err << endl; + return false; + } + + // Work around bsc#1127220 [libgpgme] no error upon incomplete import due to signal received. + // We need this error, otherwise RpmDb will report the missing keys as 'probably v3'. + if ( gpgme_import_result_t res = gpgme_op_import_result(_ctx) ) + { + if ( ! res->considered && std::forward(calcDataSize)() ) + { + DBG << *res << endl; + ERR << "Error importing key: No keys considered (bsc#1127220, [libgpgme] signal received?)" << endl; + return false; + } + } + + return (err == GPG_ERR_NO_ERROR); +} + +bool KeyManagerCtx::deleteKey(const std::string &id) +{ + gpgme_key_t key = nullptr; + GpgmeErr err = GPG_ERR_NO_ERROR; + + gpgme_op_keylist_start(_pimpl->_ctx, NULL, 0); + + while (!(err = gpgme_op_keylist_next(_pimpl->_ctx, &key))) { + if (key->subkeys && id == str::asString(key->subkeys->keyid)) { + err = gpgme_op_delete(_pimpl->_ctx, key, 0); + + gpgme_key_release(key); + gpgme_op_keylist_end(_pimpl->_ctx); + + if (err) { + ERR << "Error deleting key: "<< err << endl; + return false; + } + return true; + } + gpgme_key_release(key); + } + + gpgme_op_keylist_end(_pimpl->_ctx); + WAR << "Key: '"<< id << "' not found." << endl; + return false; +} + +std::list KeyManagerCtx::readSignatureFingerprints(const Pathname &signature) +{ return _pimpl->readSignaturesFprs(signature); } + +std::list KeyManagerCtx::readSignatureFingerprints(const ByteArray &keyData) +{ return _pimpl->readSignaturesFprs(keyData); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/KeyManager.h b/zypp/KeyManager.h new file mode 100644 index 0000000..71e1d7c --- /dev/null +++ b/zypp/KeyManager.h @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/KeyManager.h + * +*/ +#ifndef ZYPP_KEYMANAGER_H +#define ZYPP_KEYMANAGER_H + +#include +#include +#include +#include + +#include + +namespace zypp +{ + + /////////////////////////////////////////////////////////////////// + /// \class KeyManagerCtx::KeyManagerCtx + /// \brief Wrapper for GPGME + /// + /// Encapsulates all calls to the gpgme library, each instance + /// represents a context of operations on the specified keyring. + /////////////////////////////////////////////////////////////////// +class KeyManagerCtx +{ + public: + /** Creates a new KeyManagerCtx for PGP using a volatile temp. homedir/keyring. + * + * Mainly used with methods, which need a context but do not need a keyring + * (like \ref readKeyFromFile or \ref readSignatureFingerprints). + * + * \note The underlying keyring is intentionally NOT the users keyring. + * Think of it as a volatile keyring whose content may get cleared anytime. + * + * \throws KeyRingException if context can not be created or set up + */ + static KeyManagerCtx createForOpenPGP(); + + /** Creates a new KeyManagerCtx for PGP using a custom homedir/keyring. + * + * \note If you explicitly pass an empty \c Pathname, no homedir/keyring + * will be set and GPGME will use its defaults. + * + * \throws KeyRingException if context can not be created or set up + */ + static KeyManagerCtx createForOpenPGP( const Pathname & keyring_r ); + + /** Return the homedir/keyring. */ + Pathname homedir() const; + + /** Returns a list of all public keys found in the current keyring */ + std::list listKeys(); + + /** Returns a list of all \a PublicKeyData found in \a file */ + std::list readKeyFromFile(const Pathname & file); + + /** Tries to verify \a file using \a signature, returns true on success */ + bool verify(const Pathname & file, const Pathname & signature); + + /** Exports the key with \a id into the given \a stream, returns true on success */ + bool exportKey(const std::string & id, std::ostream & stream); + + /** Tries to import a key from \a keyfile, returns true on success */ + bool importKey(const Pathname & keyfile); + + /** Tries to import a key from \a buffer, returns true on success */ + bool importKey(const ByteArray & keydata); + + /** Tries to delete a key specified by \a id, returns true on success */ + bool deleteKey (const std::string & id); + + /** Reads all fingerprints from the \a signature file , returns a list of all found fingerprints */ + std::list readSignatureFingerprints(const Pathname & signature); + + /** Reads all fingerprints from the \a buffer, returns a list of all found fingerprints */ + std::list readSignatureFingerprints( const ByteArray & keyData ); + + private: + KeyManagerCtx(); + + class Impl; + RW_pointer _pimpl; ///< Pointer to implementation +}; + +} + + +#endif diff --git a/zypp/KeyRing.cc b/zypp/KeyRing.cc new file mode 100644 index 0000000..6080746 --- /dev/null +++ b/zypp/KeyRing.cc @@ -0,0 +1,514 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/KeyRing.cc + * +*/ + +#include "zypp_detail/keyring_p.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // JobReport::instance +#include + +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::KeyRing" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(KeyRing); + + namespace + { + KeyRing::DefaultAccept _keyRingDefaultAccept( KeyRing::ACCEPT_NOTHING ); + } + + KeyRing::DefaultAccept KeyRing::defaultAccept() + { return _keyRingDefaultAccept; } + + void KeyRing::setDefaultAccept( DefaultAccept value_r ) + { + MIL << "Set new KeyRing::DefaultAccept: " << value_r << endl; + _keyRingDefaultAccept = value_r; + } + + void KeyRingReport::infoVerify( const std::string & file_r, const PublicKeyData & keyData_r, const KeyContext & keycontext ) + {} + + bool KeyRingReport::askUserToAcceptUnsignedFile( const std::string & file, const KeyContext & keycontext ) + { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNSIGNED_FILE ); } + + KeyRingReport::KeyTrust + KeyRingReport::askUserToAcceptKey( const PublicKey & key, const KeyContext & keycontext ) + { + if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_KEY_TEMPORARILY ) ) + return KEY_TRUST_TEMPORARILY; + if ( _keyRingDefaultAccept.testFlag( KeyRing::TRUST_AND_IMPORT_KEY ) ) + return KEY_TRUST_AND_IMPORT; + return KEY_DONT_TRUST; + } + + bool KeyRingReport::askUserToAcceptUnknownKey( const std::string & file, const std::string & id, const KeyContext & keycontext ) + { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_UNKNOWNKEY ); } + + bool KeyRingReport::askUserToAcceptVerificationFailed( const std::string & file, const PublicKey & key, const KeyContext & keycontext ) + { return _keyRingDefaultAccept.testFlag( KeyRing::ACCEPT_VERIFICATION_FAILED ); } + + bool KeyRingReport::askUserToAcceptPackageKey(const PublicKey &key_r, const KeyContext &keycontext_r) + { + UserData data(ACCEPT_PACKAGE_KEY_REQUEST); + data.set("PublicKey", key_r); + data.set("KeyContext", keycontext_r); + report(data); + + if ( data.hasvalue("TrustKey") ) + return data.get("TrustKey"); + return false; + } + + void KeyRingReport::reportNonImportedKeys(const std::set &keys_r) + { + UserData data(KEYS_NOT_IMPORTED_REPORT); + data.set("Keys", keys_r); + report(data); + } + + void KeyRingReport::reportAutoImportKey( const std::list & keyDataList_r, + const PublicKeyData & keySigning_r, + const KeyContext &keyContext_r ) + { + UserData data { REPORT_AUTO_IMPORT_KEY }; + data.set( "KeyDataList", keyDataList_r ); + data.set( "KeySigning", keySigning_r ); + data.set( "KeyContext", keyContext_r ); + report( data ); + } + + /////////////////////////////////////////////////////////////////// + + CachedPublicKeyData::Manip::Manip(CachedPublicKeyData &cache_r, filesystem::Pathname keyring_r) + : _cache { cache_r } + , _keyring { std::move(keyring_r) } + {} + + KeyManagerCtx &CachedPublicKeyData::Manip::keyManagerCtx() { + if ( not _context ) { + _context = KeyManagerCtx::createForOpenPGP( _keyring ); + } + // frankly: don't remember why an explicit setDirty was introduced and + // why WatchFile was not enough. Maybe some corner case when the keyrings + // are created? + _cache.setDirty( _keyring ); + return _context.value(); + } + + CachedPublicKeyData::Cache::Cache() {} + + void CachedPublicKeyData::Cache::setDirty() + { + _keyringK.reset(); + _keyringP.reset(); + } + + void CachedPublicKeyData::Cache::assertCache(const filesystem::Pathname &keyring_r) + { + // .kbx since gpg2-2.1 + if ( !_keyringK ) + _keyringK.reset( new WatchFile( keyring_r/"pubring.kbx", WatchFile::NO_INIT ) ); + if ( !_keyringP ) + _keyringP.reset( new WatchFile( keyring_r/"pubring.gpg", WatchFile::NO_INIT ) ); + } + + bool CachedPublicKeyData::Cache::hasChanged() const + { + bool k = _keyringK->hasChanged(); // be sure both files are checked + bool p = _keyringP->hasChanged(); + return k || p; + } + + const std::list &CachedPublicKeyData::operator()(const filesystem::Pathname &keyring_r) const + { return getData( keyring_r ); } + + void CachedPublicKeyData::setDirty(const filesystem::Pathname &keyring_r) + { _cacheMap[keyring_r].setDirty(); } + + CachedPublicKeyData::Manip CachedPublicKeyData::manip(filesystem::Pathname keyring_r) { return Manip( *this, std::move(keyring_r) ); } + + const std::list &CachedPublicKeyData::getData(const filesystem::Pathname &keyring_r) const + { + Cache & cache( _cacheMap[keyring_r] ); + // init new cache entry + cache.assertCache( keyring_r ); + return getData( keyring_r, cache ); + } + + const std::list &CachedPublicKeyData::getData(const filesystem::Pathname &keyring_r, Cache &cache_r) const + { + if ( cache_r.hasChanged() ) { + cache_r._data = KeyManagerCtx::createForOpenPGP( keyring_r ).listKeys(); + MIL << "Found keys: " << cache_r._data << std::endl; + } + return cache_r._data; + } + + + /////////////////////////////////////////////////////////////////// + + namespace + { + /// Handle signal emission from within KeyRing::Impl::importKey + struct ImportKeyCBHelper + { + void operator()( const PublicKey & key_r ) + { + try { + _rpmdbEmitSignal->trustedKeyAdded( key_r ); + _emitSignal->trustedKeyAdded( key_r ); + } + catch ( const Exception & excp ) + { + ERR << "Could not import key into rpmdb: " << excp << endl; + // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback + JobReport::error( excp.asUserHistory() ); + } + } + + private: + callback::SendReport _rpmdbEmitSignal; + callback::SendReport _emitSignal; + }; + } // namespace + + KeyRing::Impl::Impl(const filesystem::Pathname &baseTmpDir) + : _trusted_tmp_dir( baseTmpDir, "zypp-trusted-kr" ) + , _general_tmp_dir( baseTmpDir, "zypp-general-kr" ) + , _base_dir( baseTmpDir ) + { + MIL << "Current KeyRing::DefaultAccept: " << _keyRingDefaultAccept << std::endl; + } + + void KeyRing::Impl::importKey( const PublicKey & key, bool trusted ) + { + importKey( key.path(), trusted ? trustedKeyRing() : generalKeyRing() ); + MIL << "Imported key " << key << " to " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl; + + if ( trusted ) + { + ImportKeyCBHelper emitSignal; + if ( key.hiddenKeys().empty() ) + { + emitSignal( key ); + } + else + { + // multiple keys: Export individual keys ascii armored to import in rpmdb + emitSignal( exportKey( key, trustedKeyRing() ) ); + for ( const PublicKeyData & hkey : key.hiddenKeys() ) + emitSignal( exportKey( hkey, trustedKeyRing() ) ); + } + } + } + + void KeyRing::Impl::multiKeyImport( const Pathname & keyfile_r, bool trusted_r ) + { + importKey( keyfile_r, trusted_r ? trustedKeyRing() : generalKeyRing() ); + } + + void KeyRing::Impl::deleteKey( const std::string & id, bool trusted ) + { + PublicKeyData keyDataToDel( publicKeyExists( id, trusted ? trustedKeyRing() : generalKeyRing() ) ); + if ( ! keyDataToDel ) + { + WAR << "Key to delete [" << id << "] is not in " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl; + return; + } + deleteKey( id, trusted ? trustedKeyRing() : generalKeyRing() ); + MIL << "Deleted key [" << id << "] from " << (trusted ? "trustedKeyRing" : "generalKeyRing" ) << endl; + + if ( trusted ) + try { + PublicKey key( keyDataToDel ); + + callback::SendReport rpmdbEmitSignal; + rpmdbEmitSignal->trustedKeyRemoved( key ); + + callback::SendReport emitSignal; + emitSignal->trustedKeyRemoved( key ); + } + catch ( const Exception & excp ) + { + ERR << "Could not delete key from rpmmdb: " << excp << endl; + // TODO: JobReport as hotfix for bsc#1057188; should bubble up and go through some callback + JobReport::error( excp.asUserHistory() ); + } + } + + PublicKeyData KeyRing::Impl::publicKeyExists( const std::string & id, const Pathname & keyring ) + { + if ( _allowPreload && keyring == generalKeyRing() ) { + _allowPreload = false; + preloadCachedKeys(); + } + + PublicKeyData ret; + for ( const PublicKeyData & key : publicKeyData( keyring ) ) + { + if ( key.providesKey( id ) ) + { + ret = key; + break; + } + } + DBG << (ret ? "Found" : "No") << " key [" << id << "] in keyring " << keyring << endl; + return ret; + } + + void KeyRing::Impl::preloadCachedKeys() + { + MIL << "preloadCachedKeys into general keyring..." << endl; + CachedPublicKeyData::Manip manip { keyRingManip( generalKeyRing() ) }; // Provides the context if we want to manip a cached keyring. + + // For now just load the 'gpg-pubkey-*.{asc,key}' files into the general keyring, + // if their id (derived from the filename) is not in the trusted ring. + // TODO: Head for a persistent general keyring. + std::set cachedirs; + ZConfig & conf { ZConfig::instance() }; + cachedirs.insert( conf.pubkeyCachePath() ); + cachedirs.insert( "/usr/lib/rpm/gnupg/keys" ); + if ( Pathname r = conf.systemRoot(); r != "/" && not r.empty() ) { + cachedirs.insert( r / conf.pubkeyCachePath() ); + cachedirs.insert( r / "/usr/lib/rpm/gnupg/keys" ); + } + if ( Pathname r = conf.repoManagerRoot(); r != "/" && not r.empty() ) { + cachedirs.insert( r / conf.pubkeyCachePath() ); + cachedirs.insert( r / "/usr/lib/rpm/gnupg/keys" ); + } + + std::map keyCandidates; // Collect one file path per keyid + const str::regex rx { "^gpg-pubkey-([[:xdigit:]]{8,})(-[[:xdigit:]]{8,})?\\.(asc|key)$" }; + for ( const auto & cache : cachedirs ) { + dirForEach( cache, + [&rx,&keyCandidates]( const Pathname & dir_r, const char *const file_r )->bool { + str::smatch what; + if ( str::regex_match( file_r, what, rx ) ) { + Pathname & remember { keyCandidates[what[1]] }; + if ( remember.empty() ) { + remember = dir_r / file_r; + } + } + return true; + } + ); + } + + for ( const auto & p : keyCandidates ) { + // Avoid checking the general keyring while it is flagged dirty. + // Checking the trusted ring is ok, and most keys will be there anyway. + const std::string & id { p.first }; + const Pathname & path { p.second }; + if ( isKeyTrusted(id) ) + continue; + if ( manip.keyManagerCtx().importKey( path ) ) { + DBG << "preload key file " << path << endl; + } + else { + WAR << "Skipping: Can't preload key file " << path << endl; + } + } + } + + PublicKey KeyRing::Impl::exportKey( const PublicKeyData & keyData, const Pathname & keyring ) + { + return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData ); + } + + PublicKey KeyRing::Impl::exportKey( const std::string & id, const Pathname & keyring ) + { + PublicKeyData keyData( publicKeyExists( id, keyring ) ); + if ( keyData ) + return PublicKey( dumpPublicKeyToTmp( keyData.id(), keyring ), keyData ); + + // Here: key not found + WAR << "No key [" << id << "] to export from " << keyring << endl; + return PublicKey(); + } + + + void KeyRing::Impl::dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream ) + { + KeyManagerCtx::createForOpenPGP( keyring ).exportKey(id, stream); + } + + filesystem::TmpFile KeyRing::Impl::dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring ) + { + filesystem::TmpFile tmpFile( _base_dir, "pubkey-"+id+"-" ); + MIL << "Going to export key [" << id << "] from " << keyring << " to " << tmpFile.path() << endl; + + std::ofstream os( tmpFile.path().c_str() ); + dumpPublicKey( id, keyring, os ); + os.close(); + return tmpFile; + } + + std::list KeyRing::Impl::publicKeys( const Pathname & keyring ) + { + const std::list & keys( publicKeyData( keyring ) ); + std::list ret; + + for_( it, keys.begin(), keys.end() ) + { + PublicKey key( exportKey( *it, keyring ) ); + ret.push_back( key ); + MIL << "Found key " << key << endl; + } + return ret; + } + + void KeyRing::Impl::importKey( const Pathname & keyfile, const Pathname & keyring ) + { + if ( ! PathInfo( keyfile ).isExist() ) + // TranslatorExplanation first %s is key name, second is keyring name + ZYPP_THROW(KeyRingException( str::Format(_("Tried to import not existent key %s into keyring %s")) + % keyfile.asString() + % keyring.asString() )); + + CachedPublicKeyData::Manip manip { keyRingManip( keyring ) }; // Provides the context if we want to manip a cached keyring. + if ( ! manip.keyManagerCtx().importKey( keyfile ) ) + ZYPP_THROW(KeyRingException(_("Failed to import key."))); + } + + void KeyRing::Impl::deleteKey( const std::string & id, const Pathname & keyring ) + { + CachedPublicKeyData::Manip manip { keyRingManip( keyring ) }; // Provides the context if we want to manip a cached keyring. + if ( ! manip.keyManagerCtx().deleteKey( id ) ) + ZYPP_THROW(KeyRingException(_("Failed to delete key."))); + } + + std::string KeyRing::Impl::readSignatureKeyId( const Pathname & signature ) + { + if ( ! PathInfo( signature ).isFile() ) + ZYPP_THROW(KeyRingException( str::Format(_("Signature file %s not found")) % signature.asString() )); + + MIL << "Determining key id of signature " << signature << endl; + + std::list fprs = KeyManagerCtx::createForOpenPGP().readSignatureFingerprints( signature ); + if ( ! fprs.empty() ) { + std::string &id = fprs.back(); + MIL << "Determined key id [" << id << "] for signature " << signature << endl; + return id; + } + return std::string(); + } + + bool KeyRing::Impl::verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring ) + { + return KeyManagerCtx::createForOpenPGP( keyring ).verify( file, signature ); + } + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : KeyRing + // + /////////////////////////////////////////////////////////////////// + + KeyRing::KeyRing( const Pathname & baseTmpDir ) + : _pimpl( new Impl( baseTmpDir ) ) + {} + + KeyRing::~KeyRing() + {} + + KeyRing::Impl &KeyRing::pimpl() + { + return *_pimpl; + } + + void KeyRing::allowPreload( bool yesno_r ) + { _pimpl->allowPreload( yesno_r ); } + + + void KeyRing::importKey( const PublicKey & key, bool trusted ) + { _pimpl->importKey( key, trusted ); } + + void KeyRing::multiKeyImport( const Pathname & keyfile_r, bool trusted_r ) + { _pimpl->multiKeyImport( keyfile_r, trusted_r ); } + + std::string KeyRing::readSignatureKeyId( const Pathname & signature ) + { return _pimpl->readSignatureKeyId( signature ); } + + void KeyRing::deleteKey( const std::string & id, bool trusted ) + { _pimpl->deleteKey( id, trusted ); } + + std::list KeyRing::publicKeys() + { return _pimpl->publicKeys(); } + + std:: list KeyRing::trustedPublicKeys() + { return _pimpl->trustedPublicKeys(); } + + std::list KeyRing::publicKeyData() + { return _pimpl->publicKeyData(); } + + std::list KeyRing::trustedPublicKeyData() + { return _pimpl->trustedPublicKeyData(); } + + PublicKeyData KeyRing::publicKeyData( const std::string &id_r ) + { return _pimpl->publicKeyExists( id_r ); } + + PublicKeyData KeyRing::trustedPublicKeyData(const std::string &id_r) + { return _pimpl->trustedPublicKeyExists( id_r ); } + + bool KeyRing::verifyFileSignature( const Pathname & file, const Pathname & signature ) + { return _pimpl->verifyFileSignature( file, signature ); } + + bool KeyRing::verifyFileTrustedSignature( const Pathname & file, const Pathname & signature ) + { return _pimpl->verifyFileTrustedSignature( file, signature ); } + void KeyRing::dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream ) + { _pimpl->dumpPublicKey( id, trusted, stream ); } + + PublicKey KeyRing::exportPublicKey( const PublicKeyData & keyData ) + { return _pimpl->exportPublicKey( keyData ); } + + PublicKey KeyRing::exportTrustedPublicKey( const PublicKeyData & keyData ) + { return _pimpl->exportTrustedPublicKey( keyData ); } + + bool KeyRing::isKeyTrusted( const std::string & id ) + { return _pimpl->isKeyTrusted( id ); } + + bool KeyRing::isKeyKnown( const std::string & id ) + { return _pimpl->isKeyKnown( id ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/KeyRing.h b/zypp/KeyRing.h new file mode 100644 index 0000000..1e80cc7 --- /dev/null +++ b/zypp/KeyRing.h @@ -0,0 +1,354 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/KeyRing.h + * +*/ +#ifndef ZYPP_KEYRING_H +#define ZYPP_KEYRING_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(KeyRing); + + /** Callbacks from signature verification workflow. + * + * Per default all methods answer \c false. This may be canged + * by calling \ref KeyRing::setDefaultAccept. + * \code + * KeyRing::setDefaultAccept( KeyRing::ACCEPT_UNSIGNED_FILE | KeyRing::ACCEPT_VERIFICATION_FAILED ); + * \endcode + * \see \ref KeyRing + */ + struct ZYPP_API KeyRingReport : public callback::ReportBase + { + /** + * User reply options for the askUserToTrustKey callback. + * + * \param filedes Name of the file (repo alias) or filename if not available + */ + enum KeyTrust + { + /** + * User has chosen not to trust the key. + */ + KEY_DONT_TRUST = 0, + /** + * This basically means, we knew the key, but it was not trusted. User + * has chosen to continue, but not import the key. + */ + KEY_TRUST_TEMPORARILY, + /** + * Import the key. + * This means saving the key in the trusted database so next run it will appear as trusted. + * Nothing to do with KEY_TRUST_TEMPORARILY, as you CAN trust a key without importing it, + * basically you will be asked every time again. + * There are programs who prefer to manage the trust keyring on their own and use trustKey + * without importing it into rpm. + */ + KEY_TRUST_AND_IMPORT + }; + + /** + * Ask user to trust and/or import the key to trusted keyring. + * \see KeyTrust + */ + virtual KeyTrust askUserToAcceptKey( const PublicKey &key, const KeyContext &keycontext = KeyContext() ); + + /** Informal callback showing the trusted key that will be used for verification. */ + virtual void infoVerify( const std::string & file_r, const PublicKeyData & keyData_r, const KeyContext &keycontext = KeyContext() ); + + virtual bool askUserToAcceptUnsignedFile( const std::string &file, const KeyContext &keycontext = KeyContext() ); + + /** + * we DONT know the key, only its id, but we have never seen it, the difference + * with trust key is that if you dont have it, you can't import it later. + * The answer means continue yes or no? + * + */ + virtual bool askUserToAcceptUnknownKey( const std::string &file, const std::string &id, const KeyContext &keycontext = KeyContext() ); + + /** + * The file \ref filedesc is signed but the verification failed + * + * \param filedesc Filename or its description. + */ + virtual bool askUserToAcceptVerificationFailed( const std::string &file, const PublicKey &key, const KeyContext &keycontext = KeyContext() ); + + /** + * Ask user to trust and/or import the package key to trusted keyring, using ReportBase::report + * + * The UserData object will have the following fields: + * UserData::type \ref ACCEPT_PACKAGE_KEY_REQUEST + * "PublicKey" The PublicKey to be accepted + * "KeyContext" The KeyContext + * + * Userdata accepted: + * "TrustKey" bool user can either trust or not trust the key + * + * \see KeyTrust + * \sa ReportBase::report + * \note this is a non virtual function and will use ReportBase::report to send the report. + * + */ + bool askUserToAcceptPackageKey( const PublicKey &key_r, const KeyContext &keycontext_r = KeyContext() ); + /** \relates askUserToAcceptPackageKey generic reports UserData::type */ + constexpr static const char * ACCEPT_PACKAGE_KEY_REQUEST = "KeyRingReport/AcceptPackageKey"; + + /** + * Notify the user about keys that were not imported from the + * rpm key database into zypp keyring + * + * The UserData object will have the following fields: + * UserData::type \ref KEYS_NOT_IMPORTED_REPORT + * std::set "Keys" set of keys that were not imported + * + */ + void reportNonImportedKeys( const std::set &keys_r ); + /** \relates reportNonImportedKeys generic reports UserData::type */ + constexpr static const char *KEYS_NOT_IMPORTED_REPORT = "KeyRingReport/KeysNotImported"; + + + /** + * Notify that a repository auto imported new package signing keys. + * + * To auto import new package signing keys, the repositories metadata must be + * signed by an already trusted key. + * + * The UserData object will have the following fields: + * UserData::type \ref REPORT_AUTO_IMPORT_KEY + * "KeyDataList" List of KeyData to import + * "KeySigning" KeyData of signing key + * "KeyContext" The KeyContext + */ + void reportAutoImportKey( const std::list & keyDataList_r, + const PublicKeyData & keySigning_r, + const KeyContext &keyContext_r ); + /** \relates reportAutoImportKey generic reports UserData::type */ + constexpr static const char *REPORT_AUTO_IMPORT_KEY = "KeyRingReport/reportAutoImportKey"; + }; + + struct ZYPP_API KeyRingSignals : public callback::ReportBase + { + virtual void trustedKeyAdded( const PublicKey &/*key*/ ) + {} + virtual void trustedKeyRemoved( const PublicKey &/*key*/ ) + {} + }; + + class ZYPP_API KeyRingException : public Exception + { + public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + KeyRingException() + : Exception( "Bad Key Exception" ) + {} + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + KeyRingException( const std::string & msg_r ) + : Exception( msg_r ) + {} + /** Dtor. */ + ~KeyRingException() throw() override {}; + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : KeyRing + // + /** Gpg key handling. + * + */ + class ZYPP_API KeyRing : public base::ReferenceCounted, private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const KeyRing & obj ); + + public: + /** \name Default answers in verification workflow. + * Per default all answers are \c false. + */ + //@{ + /** \ref DefaultAccept flags (\see \ref base::Flags) are used to + * define the default callback answers during signature verification. + * \code + * KeyRing::setDefaultAccept( KeyRing::ACCEPT_UNSIGNED_FILE | ACCEPT_VERIFICATION_FAILED ); + * \endcode + * \see \ref KeyRingReport. + */ + enum DefaultAcceptBits + { + ACCEPT_NOTHING = 0x0000, + ACCEPT_UNSIGNED_FILE = 0x0001, + ACCEPT_UNKNOWNKEY = 0x0002, + TRUST_KEY_TEMPORARILY = 0x0004, + TRUST_AND_IMPORT_KEY = 0x0008, + ACCEPT_VERIFICATION_FAILED = 0x0010, + }; + ZYPP_DECLARE_FLAGS( DefaultAccept, DefaultAcceptBits ); + + /** Get the active accept bits. */ + static DefaultAccept defaultAccept(); + + /** Set the active accept bits. */ + static void setDefaultAccept( DefaultAccept value_r ); + //@} + + public: + /** Implementation */ + struct Impl; + + public: + /** Default ctor */ + KeyRing(const Pathname &baseTmpDir); + + /** + * imports a key from a file. + * throw if key was not imported + */ + void importKey( const PublicKey &key, bool trusted = false); + + /** Initial import from \ref RpmDb. */ + void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false ); + + void dumpTrustedPublicKey( const std::string &id, std::ostream &stream ) + { dumpPublicKey(id, true, stream); } + + void dumpUntrustedPublicKey( const std::string &id, std::ostream &stream ) + { dumpPublicKey(id, false, stream); } + + void dumpPublicKey( const std::string &id, bool trusted, std::ostream &stream ); + + /** Export a public key identified by its key data. */ + PublicKey exportPublicKey( const PublicKeyData & keyData ); + + /** Export a trusted public key identified by its key data. */ + PublicKey exportTrustedPublicKey( const PublicKeyData & keyData ); + + /** + * reads the public key id from a signature + */ + std::string readSignatureKeyId( const Pathname &signature ); + + /** + * true if the key id is trusted + */ + bool isKeyTrusted( const std::string &id ); + + /** + * true if the key id is knows, that means + * at least exist on the untrusted keyring + */ + bool isKeyKnown( const std::string &id ); + + /** + * removes a key from the keyring. + * If trusted is true, Remove it from trusted keyring too. + */ + void deleteKey( const std::string &id, bool trusted = false ); + + /** + * Get a list of public keys in the keyring (incl. ASCII armored keys in tmpfiles) + */ + std::list publicKeys(); + + /** + * Get a list of trusted public keys in the keyring (incl. ASCII armored keys in tmpfiles) + */ + std::list trustedPublicKeys(); + + /** + * Get a list of public key data in the keyring (key data only) + */ + std::list publicKeyData(); + + /** + * Get a list of trusted public key data in the keyring (key data only) + */ + std::list trustedPublicKeyData(); + + /** + * Get a public key's data in the keyring (key data only) + */ + PublicKeyData publicKeyData( const std::string &id ); + + /** + * Get a trusted public key's data in the keyring (key data only) + */ + PublicKeyData trustedPublicKeyData( const std::string &id ); + + /** + * Verifies a file against a signature, with no user interaction + * + * \param file Path of the file to be verified + * \param signature Signature to verify the file against + */ + bool verifyFileSignature( const Pathname &file, const Pathname &signature ) ZYPP_API; + + bool verifyFileTrustedSignature( const Pathname &file, const Pathname &signature ) ZYPP_API; + + /** Dtor */ + ~KeyRing() override; + + /** Access to private functions for the KeyRingWorkflow implementations */ + KeyRing::Impl &pimpl(); + + public: + /** The general keyring may be populated with known keys stored on the system. */ + void allowPreload( bool yesno_r ); + + private: + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates KeyRing Stream output */ + inline std::ostream & operator<<( std::ostream & str, const KeyRing & /*obj*/ ) + { + //return str << obj.asString(); + return str; + } + + /** \relates KeyRing::DefaultAccept */ + ZYPP_DECLARE_OPERATORS_FOR_FLAGS( KeyRing::DefaultAccept ); + + /////////////////////////////////////////////////////////////////// + + namespace target + { + namespace rpm + { + /** Internal connection to rpm database. Not for public use. */ + struct KeyRingSignals : public ::zypp::KeyRingSignals + {}; + } + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_KEYRING_H diff --git a/zypp/KeyRingContexts.cc b/zypp/KeyRingContexts.cc new file mode 100644 index 0000000..6d30a21 --- /dev/null +++ b/zypp/KeyRingContexts.cc @@ -0,0 +1,142 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/KeyRingContexts.cc + */ +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp::keyring +{ + /////////////////////////////////////////////////////////////////// + /// \class VerifyFileContext::Impl + /// Directly accessed by verifyFileSignatureWorkflow + /// to set the result data. + /////////////////////////////////////////////////////////////////// + class VerifyFileContext::Impl + { + public: + Impl() + {} + Impl( Pathname file_r ) + : _file( std::move(file_r) ) + {} + Impl( Pathname file_r, Pathname signature_r ) + : _file( std::move(file_r) ) + , _signature( std::move(signature_r) ) + {} + + void resetResults() + { _fileAccepted = _fileValidated = _signatureIdTrusted = false; _signatureId.clear(); } + + // In: + Pathname _file; + Pathname _signature; + std::optional _shortFile; + KeyContext _keyContext; + BuddyKeys _buddyKeys; + + // Results: + bool _fileAccepted = false; + bool _fileValidated = false; + std::string _signatureId; + bool _signatureIdTrusted = false; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + + VerifyFileContext::VerifyFileContext() + : _pimpl( new Impl() ) + {} + VerifyFileContext::VerifyFileContext( Pathname file_r ) + : _pimpl( new Impl( std::move(file_r) ) ) + {} + VerifyFileContext::VerifyFileContext( Pathname file_r, Pathname signature_r ) + : _pimpl( new Impl( std::move(file_r), std::move(signature_r) ) ) + {} + VerifyFileContext::~VerifyFileContext() + {} + + // In: + const Pathname & VerifyFileContext::file() const + { return _pimpl->_file; } + + void VerifyFileContext::file( Pathname file_r ) + { _pimpl->_file = std::move(file_r); } + + const Pathname & VerifyFileContext::signature() const + { return _pimpl->_signature; } + + void VerifyFileContext::signature( Pathname signature_r ) + { _pimpl->_signature = std::move(signature_r); } + + std::string VerifyFileContext::shortFile() const + { return _pimpl->_shortFile.has_value() ? _pimpl->_shortFile.value() : _pimpl->_file.basename(); } + + void VerifyFileContext::shortFile( std::string shortFile_r ) + { _pimpl->_shortFile = std::move(shortFile_r); } + + const KeyContext & VerifyFileContext::keyContext() const + { return _pimpl->_keyContext; } + + void VerifyFileContext::keyContext( KeyContext keyContext_r ) + { _pimpl->_keyContext = std::move(keyContext_r); } + + const VerifyFileContext::BuddyKeys & VerifyFileContext::buddyKeys() const + { return _pimpl->_buddyKeys; } + + void VerifyFileContext::addBuddyKey( std::string sid_r ) + { _pimpl->_buddyKeys.insert( std::move(sid_r) ); } + + // Results: + void VerifyFileContext::resetResults() + { _pimpl->resetResults(); } + + bool VerifyFileContext::fileAccepted() const + { return _pimpl->_fileAccepted; } + + void VerifyFileContext::fileAccepted( bool yesno_r ) + { _pimpl->_fileAccepted = yesno_r; } + + bool VerifyFileContext::fileValidated() const + { return _pimpl->_fileValidated; } + + void VerifyFileContext::fileValidated( bool yesno_r ) + { _pimpl->_fileValidated = yesno_r; } + + const std::string & VerifyFileContext::signatureId() const + { return _pimpl->_signatureId; } + + void VerifyFileContext::signatureId( std::string signatureId_r ) + { _pimpl->_signatureId = std::move(signatureId_r); } + + bool VerifyFileContext::signatureIdTrusted() const + { return _pimpl->_signatureIdTrusted; } + + void VerifyFileContext::signatureIdTrusted( bool yesno_r ) + { _pimpl->_signatureIdTrusted = yesno_r; } + + std::ostream & operator<<( std::ostream & str, const VerifyFileContext & obj ) + { + return str << obj.file() + << "[" << obj.signature().basename() + << " accepted:" << asString( obj.fileAccepted() ) + << ", validated:" << ( obj.fileValidated() ? ( obj.signatureIdTrusted() ? "trusted" : "true" ) : "false" ) + << "(" << obj.signatureId() << ")" + << "]";; + } + +} // namespace zypp::keyring +/////////////////////////////////////////////////////////////////// diff --git a/zypp/KeyRingContexts.h b/zypp/KeyRingContexts.h new file mode 100644 index 0000000..69fde34 --- /dev/null +++ b/zypp/KeyRingContexts.h @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/KeyRingContexts.h + */ +#ifndef ZYPP_KEYRINGCONTEXTS_H +#define ZYPP_KEYRINGCONTEXTS_H + +#include +#include +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp::keyring +{ + /////////////////////////////////////////////////////////////////// + /// I/O context for KeyRing::verifyFileSignatureWorkflow. + /////////////////////////////////////////////////////////////////// + class ZYPP_API VerifyFileContext + { + public: + /** Ctor. */ + VerifyFileContext(); + /** Ctor may take file to verify and detatched signature. */ + explicit VerifyFileContext( Pathname file_r ); + /** Ctor may take file to verify and detatched signature. */ + VerifyFileContext( Pathname file_r, Pathname signature_r ); + + VerifyFileContext(const VerifyFileContext &) = default; + VerifyFileContext(VerifyFileContext &&) noexcept = default; + + VerifyFileContext &operator=(const VerifyFileContext &) = default; + VerifyFileContext &operator=(VerifyFileContext &&) noexcept = default; + + ~VerifyFileContext(); + + /** File to verify. */ + const Pathname & file() const; + void file( Pathname file_r ); + + /** Detached signature or empty. */ + const Pathname & signature() const; + void signature( Pathname signature_r ); + + /** Short name for file (default: basename). */ + std::string shortFile() const; + void shortFile( std::string shortFile_r ); + + /** \ref KeyContext passed to callbacks */ + const KeyContext & keyContext() const; + void keyContext( KeyContext keyContext_r ); + + /** List of key safe key ids to import IFF \ref fileValidated. */ + using BuddyKeys = std::set; + const BuddyKeys & buddyKeys() const; + void addBuddyKey( std::string sid_r ); + + /** \name Results provided by \ref KeyRing::verifyFileSignatureWorkflow. + */ + //@{ + /** Reset all result values to safe defaults. */ + void resetResults(); + + /** May return \c true due to user interaction or global defaults even if the signature was not actually verified. */ + bool fileAccepted() const; + void fileAccepted( bool yesno_r) ; + + /** Whether the signature was actually successfully verified. */ + bool fileValidated() const; + void fileValidated( bool yesno_r ); + + /** The id of the gpg key which signed the file. */ + const std::string & signatureId() const; + void signatureId( std::string signatureId_r ); + + /** Whether the \ref SignatureId is in the trusted keyring (not temp. trusted). */ + bool signatureIdTrusted() const; + void signatureIdTrusted( bool yesno_r ); + //@} + public: + class Impl; ///< Implementation + private: + RWCOW_pointer _pimpl; ///< Pointer to implementation + }; + + /** \relates VerifyFileContext Stream output */ + std::ostream & operator<<( std::ostream & str, const VerifyFileContext & obj ); + +} // namespace zypp::keyring +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_KEYRINGCONTEXTS_H diff --git a/zypp/LanguageCode.cc b/zypp/LanguageCode.cc new file mode 100644 index 0000000..1b5b356 --- /dev/null +++ b/zypp/LanguageCode.cc @@ -0,0 +1,1165 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/LanguageCode.cc + * +*/ +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + /** Wrap static codemap data. */ + struct CodeMaps + { + /** The singleton */ + static CodeMaps & instance() + { + static CodeMaps _instance; + return _instance; + } + + /** Lookup (translated) name for \a index_r.*/ + std::string name( IdString index_r ) + { + Link link( getIndex( index_r ) ); + + std::string ret; + if ( link->second ) + { ret = _(link->second); } + else + { + ret = _("Unknown language: "); + ret += "'"; + ret += index_r.c_str(); + ret += "'"; + } + return ret; + } + + private: + using CodeMap = std::unordered_map; + using Link = CodeMap::const_iterator; + + using IndexMap = std::unordered_map; + + /** Ctor initializes the code maps. + * http://www.loc.gov/standards/iso639-2/ISO-639-2_values_8bits.txt + */ + CodeMaps(); + + /** Return \ref Link for \a index_r, creating it if necessary. */ + Link getIndex( IdString index_r ) + { + auto it = _indexMap.find( index_r ); + return( it != _indexMap.end() + ? it->second + : newIndex( index_r, index_r.asString() ) ); + } + + /** Return the CodeMap Index for \a code_r. */ + Link newIndex( IdString index_r, const std::string & code_r ) + { + Link link = _codeMap.find( code_r ); + if ( link != _codeMap.end() ) + return (_indexMap[index_r] = link); + + // not found: Remember a new code + CodeMap::value_type nval( code_r, nullptr ); + + if ( code_r.size() > 3 || code_r.size() < 2 ) + WAR << "Malformed LanguageCode '" << code_r << "' (expect 2 or 3-letter)" << endl; + + std::string lcode( str::toLower( code_r ) ); + if ( lcode != code_r ) + { + WAR << "Malformed LanguageCode '" << code_r << "' (not lower case)" << endl; + // but maybe we're lucky with the lower case code + // and find a language name. + link = _codeMap.find( lcode ); + if ( link != _codeMap.end() ) + { + nval.second = link->second; + } + } + MIL << "Remember LanguageCode '" << code_r << "': '" << (nval.second?nval.second:"Unknown language") << "'" << endl; + return (_indexMap[index_r] = _codeMap.insert( nval ).first); + } + + private: + CodeMap _codeMap; + IndexMap _indexMap; + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // class LanguageCode + /////////////////////////////////////////////////////////////////// + + const LanguageCode LanguageCode::noCode; + //const LanguageCode LanguageCode::enCode("en"); in Locale.cc as Locale::enCode depends on it + + LanguageCode::LanguageCode() + {} + + LanguageCode::LanguageCode( IdString str_r ) + : _str( str_r ) + {} + + LanguageCode::LanguageCode( const std::string & str_r ) + : _str( str_r ) + {} + + LanguageCode::LanguageCode( const char * str_r ) + : _str( str_r ) + {} + + LanguageCode::~LanguageCode() + {} + + + std::string LanguageCode::name() const + { return CodeMaps::instance().name( _str ); } + + /////////////////////////////////////////////////////////////////// + namespace + { + CodeMaps::CodeMaps() + { + // Defined LanguageCode constants + _codeMap[""] = N_("No Code"); + + struct LangInit + { + const char *iso639_2; + const char *iso639_1; + const char *name; + }; + + // some languages have more than one iso639_2 code + // so there are items with duplicate names + const LangInit langInit[] = { + // language code: aar aa + { "aar", "aa", N_( "Afar" ) }, + // language code: abk ab + { "abk", "ab", N_( "Abkhazian" ) }, + // language code: ace + { "ace", NULL, N_( "Achinese" ) }, + // language code: ach + { "ach", NULL, N_( "Acoli" ) }, + // language code: ada + { "ada", NULL, N_( "Adangme" ) }, + // language code: ady + { "ady", NULL, N_( "Adyghe" ) }, + // language code: afa + { "afa", NULL, N_( "Afro-Asiatic (Other)" ) }, + // language code: afh + { "afh", NULL, N_( "Afrihili" ) }, + // language code: afr af + { "afr", "af", N_( "Afrikaans" ) }, + // language code: ain + { "ain", NULL, N_( "Ainu" ) }, + // language code: aka ak + { "aka", "ak", N_( "Akan" ) }, + // language code: akk + { "akk", NULL, N_( "Akkadian" ) }, + // language code: alb sqi sq + { "alb", "sq", N_( "Albanian" ) }, + // language code: alb sqi sq + { "sqi", NULL, N_( "Albanian" ) }, + // language code: ale + { "ale", NULL, N_( "Aleut" ) }, + // language code: alg + { "alg", NULL, N_( "Algonquian Languages" ) }, + // language code: alt + { "alt", NULL, N_( "Southern Altai" ) }, + // language code: amh am + { "amh", "am", N_( "Amharic" ) }, + // language code: ang + { "ang", NULL, N_( "English, Old (ca.450-1100)" ) }, + // language code: apa + { "apa", NULL, N_( "Apache Languages" ) }, + // language code: ara ar + { "ara", "ar", N_( "Arabic" ) }, + // language code: arc + { "arc", NULL, N_( "Aramaic" ) }, + // language code: arg an + { "arg", "an", N_( "Aragonese" ) }, + // language code: arm hye hy + { "arm", "hy", N_( "Armenian" ) }, + // language code: arm hye hy + { "hye", NULL, N_( "Armenian" ) }, + // language code: arn + { "arn", NULL, N_( "Araucanian" ) }, + // language code: arp + { "arp", NULL, N_( "Arapaho" ) }, + // language code: art + { "art", NULL, N_( "Artificial (Other)" ) }, + // language code: arw + { "arw", NULL, N_( "Arawak" ) }, + // language code: asm as + { "asm", "as", N_( "Assamese" ) }, + // language code: ast + { "ast", NULL, N_( "Asturian" ) }, + // language code: ath + { "ath", NULL, N_( "Athapascan Languages" ) }, + // language code: aus + { "aus", NULL, N_( "Australian Languages" ) }, + // language code: ava av + { "ava", "av", N_( "Avaric" ) }, + // language code: ave ae + { "ave", "ae", N_( "Avestan" ) }, + // language code: awa + { "awa", NULL, N_( "Awadhi" ) }, + // language code: aym ay + { "aym", "ay", N_( "Aymara" ) }, + // language code: aze az + { "aze", "az", N_( "Azerbaijani" ) }, + // language code: bad + { "bad", NULL, N_( "Banda" ) }, + // language code: bai + { "bai", NULL, N_( "Bamileke Languages" ) }, + // language code: bak ba + { "bak", "ba", N_( "Bashkir" ) }, + // language code: bal + { "bal", NULL, N_( "Baluchi" ) }, + // language code: bam bm + { "bam", "bm", N_( "Bambara" ) }, + // language code: ban + { "ban", NULL, N_( "Balinese" ) }, + // language code: baq eus eu + { "baq", "eu", N_( "Basque" ) }, + // language code: baq eus eu + { "eus", NULL, N_( "Basque" ) }, + // language code: bas + { "bas", NULL, N_( "Basa" ) }, + // language code: bat + { "bat", NULL, N_( "Baltic (Other)" ) }, + // language code: bej + { "bej", NULL, N_( "Beja" ) }, + // language code: bel be + { "bel", "be", N_( "Belarusian" ) }, + // language code: bem + { "bem", NULL, N_( "Bemba" ) }, + // language code: ben bn + { "ben", "bn", N_( "Bengali" ) }, + // language code: ber + { "ber", NULL, N_( "Berber (Other)" ) }, + // language code: bho + { "bho", NULL, N_( "Bhojpuri" ) }, + // language code: bih bh + { "bih", "bh", N_( "Bihari" ) }, + // language code: bik + { "bik", NULL, N_( "Bikol" ) }, + // language code: bin + { "bin", NULL, N_( "Bini" ) }, + // language code: bis bi + { "bis", "bi", N_( "Bislama" ) }, + // language code: bla + { "bla", NULL, N_( "Siksika" ) }, + // language code: bnt + { "bnt", NULL, N_( "Bantu (Other)" ) }, + // language code: bos bs + { "bos", "bs", N_( "Bosnian" ) }, + // language code: bra + { "bra", NULL, N_( "Braj" ) }, + // language code: bre br + { "bre", "br", N_( "Breton" ) }, + // language code: btk + { "btk", NULL, N_( "Batak (Indonesia)" ) }, + // language code: bua + { "bua", NULL, N_( "Buriat" ) }, + // language code: bug + { "bug", NULL, N_( "Buginese" ) }, + // language code: bul bg + { "bul", "bg", N_( "Bulgarian" ) }, + // language code: bur mya my + { "bur", "my", N_( "Burmese" ) }, + // language code: bur mya my + { "mya", NULL, N_( "Burmese" ) }, + // language code: byn + { "byn", NULL, N_( "Blin" ) }, + // language code: cad + { "cad", NULL, N_( "Caddo" ) }, + // language code: cai + { "cai", NULL, N_( "Central American Indian (Other)" ) }, + // language code: car + { "car", NULL, N_( "Carib" ) }, + // language code: cat ca + { "cat", "ca", N_( "Catalan" ) }, + // language code: cau + { "cau", NULL, N_( "Caucasian (Other)" ) }, + // language code: ceb + { "ceb", NULL, N_( "Cebuano" ) }, + // language code: cel + { "cel", NULL, N_( "Celtic (Other)" ) }, + // language code: cha ch + { "cha", "ch", N_( "Chamorro" ) }, + // language code: chb + { "chb", NULL, N_( "Chibcha" ) }, + // language code: che ce + { "che", "ce", N_( "Chechen" ) }, + // language code: chg + { "chg", NULL, N_( "Chagatai" ) }, + // language code: chi zho zh + { "chi", "zh", N_( "Chinese" ) }, + // language code: chi zho zh + { "zho", NULL, N_( "Chinese" ) }, + // language code: chk + { "chk", NULL, N_( "Chuukese" ) }, + // language code: chm + { "chm", NULL, N_( "Mari" ) }, + // language code: chn + { "chn", NULL, N_( "Chinook Jargon" ) }, + // language code: cho + { "cho", NULL, N_( "Choctaw" ) }, + // language code: chp + { "chp", NULL, N_( "Chipewyan" ) }, + // language code: chr + { "chr", NULL, N_( "Cherokee" ) }, + // language code: chu cu + { "chu", "cu", N_( "Church Slavic" ) }, + // language code: chv cv + { "chv", "cv", N_( "Chuvash" ) }, + // language code: chy + { "chy", NULL, N_( "Cheyenne" ) }, + // language code: cmc + { "cmc", NULL, N_( "Chamic Languages" ) }, + // language code: cop + { "cop", NULL, N_( "Coptic" ) }, + // language code: cor kw + { "cor", "kw", N_( "Cornish" ) }, + // language code: cos co + { "cos", "co", N_( "Corsican" ) }, + // language code: cpe + { "cpe", NULL, N_( "Creoles and Pidgins, English-Based (Other)" ) }, + // language code: cpf + { "cpf", NULL, N_( "Creoles and Pidgins, French-Based (Other)" ) }, + // language code: cpp + { "cpp", NULL, N_( "Creoles and Pidgins, Portuguese-Based (Other)" ) }, + // language code: cre cr + { "cre", "cr", N_( "Cree" ) }, + // language code: crh + { "crh", NULL, N_( "Crimean Tatar" ) }, + // language code: crp + { "crp", NULL, N_( "Creoles and Pidgins (Other)" ) }, + // language code: csb + { "csb", NULL, N_( "Kashubian" ) }, + // language code: cus + { "cus", NULL, N_( "Cushitic (Other)" ) }, + // language code: cze ces cs + { "cze", "cs", N_( "Czech" ) }, + // language code: cze ces cs + { "ces", NULL, N_( "Czech" ) }, + // language code: dak + { "dak", NULL, N_( "Dakota" ) }, + // language code: dan da + { "dan", "da", N_( "Danish" ) }, + // language code: dar + { "dar", NULL, N_( "Dargwa" ) }, + // language code: day + { "day", NULL, N_( "Dayak" ) }, + // language code: del + { "del", NULL, N_( "Delaware" ) }, + // language code: den + { "den", NULL, N_( "Slave (Athapascan)" ) }, + // language code: dgr + { "dgr", NULL, N_( "Dogrib" ) }, + // language code: din + { "din", NULL, N_( "Dinka" ) }, + // language code: div dv + { "div", "dv", N_( "Divehi" ) }, + // language code: doi + { "doi", NULL, N_( "Dogri" ) }, + // language code: dra + { "dra", NULL, N_( "Dravidian (Other)" ) }, + // language code: dsb + { "dsb", NULL, N_( "Lower Sorbian" ) }, + // language code: dua + { "dua", NULL, N_( "Duala" ) }, + // language code: dum + { "dum", NULL, N_( "Dutch, Middle (ca.1050-1350)" ) }, + // language code: dut nld nl + { "dut", "nl", N_( "Dutch" ) }, + // language code: dut nld nl + { "nld", NULL, N_( "Dutch" ) }, + // language code: dyu + { "dyu", NULL, N_( "Dyula" ) }, + // language code: dzo dz + { "dzo", "dz", N_( "Dzongkha" ) }, + // language code: efi + { "efi", NULL, N_( "Efik" ) }, + // language code: egy + { "egy", NULL, N_( "Egyptian (Ancient)" ) }, + // language code: eka + { "eka", NULL, N_( "Ekajuk" ) }, + // language code: elx + { "elx", NULL, N_( "Elamite" ) }, + // language code: eng en + { "eng", "en", N_( "English" ) }, + // language code: enm + { "enm", NULL, N_( "English, Middle (1100-1500)" ) }, + // language code: epo eo + { "epo", "eo", N_( "Esperanto" ) }, + // language code: est et + { "est", "et", N_( "Estonian" ) }, + // language code: ewe ee + { "ewe", "ee", N_( "Ewe" ) }, + // language code: ewo + { "ewo", NULL, N_( "Ewondo" ) }, + // language code: fan + { "fan", NULL, N_( "Fang" ) }, + // language code: fao fo + { "fao", "fo", N_( "Faroese" ) }, + // language code: fat + { "fat", NULL, N_( "Fanti" ) }, + // language code: fij fj + { "fij", "fj", N_( "Fijian" ) }, + // language code: fil + { "fil", NULL, N_( "Filipino" ) }, + // language code: fin fi + { "fin", "fi", N_( "Finnish" ) }, + // language code: fiu + { "fiu", NULL, N_( "Finno-Ugrian (Other)" ) }, + // language code: fon + { "fon", NULL, N_( "Fon" ) }, + // language code: fre fra fr + { "fre", "fr", N_( "French" ) }, + // language code: fre fra fr + { "fra", NULL, N_( "French" ) }, + // language code: frm + { "frm", NULL, N_( "French, Middle (ca.1400-1600)" ) }, + // language code: fro + { "fro", NULL, N_( "French, Old (842-ca.1400)" ) }, + // language code: fry fy + { "fry", "fy", N_( "Frisian" ) }, + // language code: ful ff + { "ful", "ff", N_( "Fulah" ) }, + // language code: fur + { "fur", NULL, N_( "Friulian" ) }, + // language code: gaa + { "gaa", NULL, N_( "Ga" ) }, + // language code: gay + { "gay", NULL, N_( "Gayo" ) }, + // language code: gba + { "gba", NULL, N_( "Gbaya" ) }, + // language code: gem + { "gem", NULL, N_( "Germanic (Other)" ) }, + // language code: geo kat ka + { "geo", "ka", N_( "Georgian" ) }, + // language code: geo kat ka + { "kat", NULL, N_( "Georgian" ) }, + // language code: ger deu de + { "ger", "de", N_( "German" ) }, + // language code: ger deu de + { "deu", NULL, N_( "German" ) }, + // language code: gez + { "gez", NULL, N_( "Geez" ) }, + // language code: gil + { "gil", NULL, N_( "Gilbertese" ) }, + // language code: gla gd + { "gla", "gd", N_( "Gaelic" ) }, + // language code: gle ga + { "gle", "ga", N_( "Irish" ) }, + // language code: glg gl + { "glg", "gl", N_( "Galician" ) }, + // language code: glv gv + { "glv", "gv", N_( "Manx" ) }, + // language code: gmh + { "gmh", NULL, N_( "German, Middle High (ca.1050-1500)" ) }, + // language code: goh + { "goh", NULL, N_( "German, Old High (ca.750-1050)" ) }, + // language code: gon + { "gon", NULL, N_( "Gondi" ) }, + // language code: gor + { "gor", NULL, N_( "Gorontalo" ) }, + // language code: got + { "got", NULL, N_( "Gothic" ) }, + // language code: grb + { "grb", NULL, N_( "Grebo" ) }, + // language code: grc + { "grc", NULL, N_( "Greek, Ancient (to 1453)" ) }, + // language code: gre ell el + { "gre", "el", N_( "Greek, Modern (1453-)" ) }, + // language code: gre ell el + { "ell", NULL, N_( "Greek, Modern (1453-)" ) }, + // language code: grn gn + { "grn", "gn", N_( "Guarani" ) }, + // language code: guj gu + { "guj", "gu", N_( "Gujarati" ) }, + // language code: gwi + { "gwi", NULL, N_( "Gwich'in" ) }, + // language code: hai + { "hai", NULL, N_( "Haida" ) }, + // language code: hat ht + { "hat", "ht", N_( "Haitian" ) }, + // language code: hau ha + { "hau", "ha", N_( "Hausa" ) }, + // language code: haw + { "haw", NULL, N_( "Hawaiian" ) }, + // language code: heb he + { "heb", "he", N_( "Hebrew" ) }, + // language code: her hz + { "her", "hz", N_( "Herero" ) }, + // language code: hil + { "hil", NULL, N_( "Hiligaynon" ) }, + // language code: him + { "him", NULL, N_( "Himachali" ) }, + // language code: hin hi + { "hin", "hi", N_( "Hindi" ) }, + // language code: hit + { "hit", NULL, N_( "Hittite" ) }, + // language code: hmn + { "hmn", NULL, N_( "Hmong" ) }, + // language code: hmo ho + { "hmo", "ho", N_( "Hiri Motu" ) }, + // language code: hsb + { "hsb", NULL, N_( "Upper Sorbian" ) }, + // language code: hun hu + { "hun", "hu", N_( "Hungarian" ) }, + // language code: hup + { "hup", NULL, N_( "Hupa" ) }, + // language code: iba + { "iba", NULL, N_( "Iban" ) }, + // language code: ibo ig + { "ibo", "ig", N_( "Igbo" ) }, + // language code: ice isl is + { "ice", "is", N_( "Icelandic" ) }, + // language code: ice isl is + { "isl", NULL, N_( "Icelandic" ) }, + // language code: ido io + { "ido", "io", N_( "Ido" ) }, + // language code: iii ii + { "iii", "ii", N_( "Sichuan Yi" ) }, + // language code: ijo + { "ijo", NULL, N_( "Ijo" ) }, + // language code: iku iu + { "iku", "iu", N_( "Inuktitut" ) }, + // language code: ile ie + { "ile", "ie", N_( "Interlingue" ) }, + // language code: ilo + { "ilo", NULL, N_( "Iloko" ) }, + // language code: ina ia + { "ina", "ia", N_( "Interlingua (International Auxiliary Language Association)" ) }, + // language code: inc + { "inc", NULL, N_( "Indic (Other)" ) }, + // language code: ind id + { "ind", "id", N_( "Indonesian" ) }, + // language code: ine + { "ine", NULL, N_( "Indo-European (Other)" ) }, + // language code: inh + { "inh", NULL, N_( "Ingush" ) }, + // language code: ipk ik + { "ipk", "ik", N_( "Inupiaq" ) }, + // language code: ira + { "ira", NULL, N_( "Iranian (Other)" ) }, + // language code: iro + { "iro", NULL, N_( "Iroquoian Languages" ) }, + // language code: ita it + { "ita", "it", N_( "Italian" ) }, + // language code: jav jv + { "jav", "jv", N_( "Javanese" ) }, + // language code: jbo + { "jbo", NULL, N_( "Lojban" ) }, + // language code: jpn ja + { "jpn", "ja", N_( "Japanese" ) }, + // language code: jpr + { "jpr", NULL, N_( "Judeo-Persian" ) }, + // language code: jrb + { "jrb", NULL, N_( "Judeo-Arabic" ) }, + // language code: kaa + { "kaa", NULL, N_( "Kara-Kalpak" ) }, + // language code: kab + { "kab", NULL, N_( "Kabyle" ) }, + // language code: kac + { "kac", NULL, N_( "Kachin" ) }, + // language code: kal kl + { "kal", "kl", N_( "Kalaallisut" ) }, + // language code: kam + { "kam", NULL, N_( "Kamba" ) }, + // language code: kan kn + { "kan", "kn", N_( "Kannada" ) }, + // language code: kar + { "kar", NULL, N_( "Karen" ) }, + // language code: kas ks + { "kas", "ks", N_( "Kashmiri" ) }, + // language code: kau kr + { "kau", "kr", N_( "Kanuri" ) }, + // language code: kaw + { "kaw", NULL, N_( "Kawi" ) }, + // language code: kaz kk + { "kaz", "kk", N_( "Kazakh" ) }, + // language code: kbd + { "kbd", NULL, N_( "Kabardian" ) }, + // language code: kha + { "kha", NULL, N_( "Khasi" ) }, + // language code: khi + { "khi", NULL, N_( "Khoisan (Other)" ) }, + // language code: khm km + { "khm", "km", N_( "Khmer" ) }, + // language code: kho + { "kho", NULL, N_( "Khotanese" ) }, + // language code: kik ki + { "kik", "ki", N_( "Kikuyu" ) }, + // language code: kin rw + { "kin", "rw", N_( "Kinyarwanda" ) }, + // language code: kir ky + { "kir", "ky", N_( "Kirghiz" ) }, + // language code: kmb + { "kmb", NULL, N_( "Kimbundu" ) }, + // language code: kok + { "kok", NULL, N_( "Konkani" ) }, + // language code: kom kv + { "kom", "kv", N_( "Komi" ) }, + // language code: kon kg + { "kon", "kg", N_( "Kongo" ) }, + // language code: kor ko + { "kor", "ko", N_( "Korean" ) }, + // language code: kos + { "kos", NULL, N_( "Kosraean" ) }, + // language code: kpe + { "kpe", NULL, N_( "Kpelle" ) }, + // language code: krc + { "krc", NULL, N_( "Karachay-Balkar" ) }, + // language code: kro + { "kro", NULL, N_( "Kru" ) }, + // language code: kru + { "kru", NULL, N_( "Kurukh" ) }, + // language code: kua kj + { "kua", "kj", N_( "Kuanyama" ) }, + // language code: kum + { "kum", NULL, N_( "Kumyk" ) }, + // language code: kur ku + { "kur", "ku", N_( "Kurdish" ) }, + // language code: kut + { "kut", NULL, N_( "Kutenai" ) }, + // language code: lad + { "lad", NULL, N_( "Ladino" ) }, + // language code: lah + { "lah", NULL, N_( "Lahnda" ) }, + // language code: lam + { "lam", NULL, N_( "Lamba" ) }, + // language code: lao lo + { "lao", "lo", N_( "Lao" ) }, + // language code: lat la + { "lat", "la", N_( "Latin" ) }, + // language code: lav lv + { "lav", "lv", N_( "Latvian" ) }, + // language code: lez + { "lez", NULL, N_( "Lezghian" ) }, + // language code: lim li + { "lim", "li", N_( "Limburgan" ) }, + // language code: lin ln + { "lin", "ln", N_( "Lingala" ) }, + // language code: lit lt + { "lit", "lt", N_( "Lithuanian" ) }, + // language code: lol + { "lol", NULL, N_( "Mongo" ) }, + // language code: loz + { "loz", NULL, N_( "Lozi" ) }, + // language code: ltz lb + { "ltz", "lb", N_( "Luxembourgish" ) }, + // language code: lua + { "lua", NULL, N_( "Luba-Lulua" ) }, + // language code: lub lu + { "lub", "lu", N_( "Luba-Katanga" ) }, + // language code: lug lg + { "lug", "lg", N_( "Ganda" ) }, + // language code: lui + { "lui", NULL, N_( "Luiseno" ) }, + // language code: lun + { "lun", NULL, N_( "Lunda" ) }, + // language code: luo + { "luo", NULL, N_( "Luo (Kenya and Tanzania)" ) }, + // language code: lus + { "lus", NULL, N_( "Lushai" ) }, + // language code: mac mkd mk + { "mac", "mk", N_( "Macedonian" ) }, + // language code: mac mkd mk + { "mkd", NULL, N_( "Macedonian" ) }, + // language code: mad + { "mad", NULL, N_( "Madurese" ) }, + // language code: mag + { "mag", NULL, N_( "Magahi" ) }, + // language code: mah mh + { "mah", "mh", N_( "Marshallese" ) }, + // language code: mai + { "mai", NULL, N_( "Maithili" ) }, + // language code: mak + { "mak", NULL, N_( "Makasar" ) }, + // language code: mal ml + { "mal", "ml", N_( "Malayalam" ) }, + // language code: man + { "man", NULL, N_( "Mandingo" ) }, + // language code: mao mri mi + { "mao", "mi", N_( "Maori" ) }, + // language code: mao mri mi + { "mri", NULL, N_( "Maori" ) }, + // language code: map + { "map", NULL, N_( "Austronesian (Other)" ) }, + // language code: mar mr + { "mar", "mr", N_( "Marathi" ) }, + // language code: mas + { "mas", NULL, N_( "Masai" ) }, + // language code: may msa ms + { "may", "ms", N_( "Malay" ) }, + // language code: may msa ms + { "msa", NULL, N_( "Malay" ) }, + // language code: mdf + { "mdf", NULL, N_( "Moksha" ) }, + // language code: mdr + { "mdr", NULL, N_( "Mandar" ) }, + // language code: men + { "men", NULL, N_( "Mende" ) }, + // language code: mga + { "mga", NULL, N_( "Irish, Middle (900-1200)" ) }, + // language code: mic + { "mic", NULL, N_( "Mi'kmaq" ) }, + // language code: min + { "min", NULL, N_( "Minangkabau" ) }, + // language code: mis + { "mis", NULL, N_( "Miscellaneous Languages" ) }, + // language code: mkh + { "mkh", NULL, N_( "Mon-Khmer (Other)" ) }, + // language code: mlg mg + { "mlg", "mg", N_( "Malagasy" ) }, + // language code: mlt mt + { "mlt", "mt", N_( "Maltese" ) }, + // language code: mnc + { "mnc", NULL, N_( "Manchu" ) }, + // language code: mni + { "mni", NULL, N_( "Manipuri" ) }, + // language code: mno + { "mno", NULL, N_( "Manobo Languages" ) }, + // language code: moh + { "moh", NULL, N_( "Mohawk" ) }, + // language code: mol mo + { "mol", "mo", N_( "Moldavian" ) }, + // language code: mon mn + { "mon", "mn", N_( "Mongolian" ) }, + // language code: mos + { "mos", NULL, N_( "Mossi" ) }, + // language code: mul + { "mul", NULL, N_( "Multiple Languages" ) }, + // language code: mun + { "mun", NULL, N_( "Munda languages" ) }, + // language code: mus + { "mus", NULL, N_( "Creek" ) }, + // language code: mwl + { "mwl", NULL, N_( "Mirandese" ) }, + // language code: mwr + { "mwr", NULL, N_( "Marwari" ) }, + // language code: myn + { "myn", NULL, N_( "Mayan Languages" ) }, + // language code: myv + { "myv", NULL, N_( "Erzya" ) }, + // language code: nah + { "nah", NULL, N_( "Nahuatl" ) }, + // language code: nai + { "nai", NULL, N_( "North American Indian" ) }, + // language code: nap + { "nap", NULL, N_( "Neapolitan" ) }, + // language code: nau na + { "nau", "na", N_( "Nauru" ) }, + // language code: nav nv + { "nav", "nv", N_( "Navajo" ) }, + // language code: nbl nr + { "nbl", "nr", N_( "Ndebele, South" ) }, + // language code: nde nd + { "nde", "nd", N_( "Ndebele, North" ) }, + // language code: ndo ng + { "ndo", "ng", N_( "Ndonga" ) }, + // language code: nds + { "nds", NULL, N_( "Low German" ) }, + // language code: nep ne + { "nep", "ne", N_( "Nepali" ) }, + // language code: new + { "new", NULL, N_( "Nepal Bhasa" ) }, + // language code: nia + { "nia", NULL, N_( "Nias" ) }, + // language code: nic + { "nic", NULL, N_( "Niger-Kordofanian (Other)" ) }, + // language code: niu + { "niu", NULL, N_( "Niuean" ) }, + // language code: nno nn + { "nno", "nn", N_( "Norwegian Nynorsk" ) }, + // language code: nob nb + { "nob", "nb", N_( "Norwegian Bokmal" ) }, + // language code: nog + { "nog", NULL, N_( "Nogai" ) }, + // language code: non + { "non", NULL, N_( "Norse, Old" ) }, + // language code: nor no + { "nor", "no", N_( "Norwegian" ) }, + // language code: nso + { "nso", NULL, N_( "Northern Sotho" ) }, + // language code: nub + { "nub", NULL, N_( "Nubian Languages" ) }, + // language code: nwc + { "nwc", NULL, N_( "Classical Newari" ) }, + // language code: nya ny + { "nya", "ny", N_( "Chichewa" ) }, + // language code: nym + { "nym", NULL, N_( "Nyamwezi" ) }, + // language code: nyn + { "nyn", NULL, N_( "Nyankole" ) }, + // language code: nyo + { "nyo", NULL, N_( "Nyoro" ) }, + // language code: nzi + { "nzi", NULL, N_( "Nzima" ) }, + // language code: oci oc + { "oci", "oc", N_( "Occitan (post 1500)" ) }, + // language code: oji oj + { "oji", "oj", N_( "Ojibwa" ) }, + // language code: ori or + { "ori", "or", N_( "Oriya" ) }, + // language code: orm om + { "orm", "om", N_( "Oromo" ) }, + // language code: osa + { "osa", NULL, N_( "Osage" ) }, + // language code: oss os + { "oss", "os", N_( "Ossetian" ) }, + // language code: ota + { "ota", NULL, N_( "Turkish, Ottoman (1500-1928)" ) }, + // language code: oto + { "oto", NULL, N_( "Otomian Languages" ) }, + // language code: paa + { "paa", NULL, N_( "Papuan (Other)" ) }, + // language code: pag + { "pag", NULL, N_( "Pangasinan" ) }, + // language code: pal + { "pal", NULL, N_( "Pahlavi" ) }, + // language code: pam + { "pam", NULL, N_( "Pampanga" ) }, + // language code: pan pa + { "pan", "pa", N_( "Panjabi" ) }, + // language code: pap + { "pap", NULL, N_( "Papiamento" ) }, + // language code: pau + { "pau", NULL, N_( "Palauan" ) }, + // language code: peo + { "peo", NULL, N_( "Persian, Old (ca.600-400 B.C.)" ) }, + // language code: per fas fa + { "per", "fa", N_( "Persian" ) }, + // language code: per fas fa + { "fas", NULL, N_( "Persian" ) }, + // language code: phi + { "phi", NULL, N_( "Philippine (Other)" ) }, + // language code: phn + { "phn", NULL, N_( "Phoenician" ) }, + // language code: pli pi + { "pli", "pi", N_( "Pali" ) }, + // language code: pol pl + { "pol", "pl", N_( "Polish" ) }, + // language code: pon + { "pon", NULL, N_( "Pohnpeian" ) }, + // language code: por pt + { "por", "pt", N_( "Portuguese" ) }, + // language code: pra + { "pra", NULL, N_( "Prakrit Languages" ) }, + // language code: pro + { "pro", NULL, N_( "Provencal, Old (to 1500)" ) }, + // language code: pus ps + { "pus", "ps", N_( "Pushto" ) }, + // language code: que qu + { "que", "qu", N_( "Quechua" ) }, + // language code: raj + { "raj", NULL, N_( "Rajasthani" ) }, + // language code: rap + { "rap", NULL, N_( "Rapanui" ) }, + // language code: rar + { "rar", NULL, N_( "Rarotongan" ) }, + // language code: roa + { "roa", NULL, N_( "Romance (Other)" ) }, + // language code: roh rm + { "roh", "rm", N_( "Raeto-Romance" ) }, + // language code: rom + { "rom", NULL, N_( "Romany" ) }, + // language code: rum ron ro + { "rum", "ro", N_( "Romanian" ) }, + // language code: rum ron ro + { "ron", NULL, N_( "Romanian" ) }, + // language code: run rn + { "run", "rn", N_( "Rundi" ) }, + // language code: rus ru + { "rus", "ru", N_( "Russian" ) }, + // language code: sad + { "sad", NULL, N_( "Sandawe" ) }, + // language code: sag sg + { "sag", "sg", N_( "Sango" ) }, + // language code: sah + { "sah", NULL, N_( "Yakut" ) }, + // language code: sai + { "sai", NULL, N_( "South American Indian (Other)" ) }, + // language code: sal + { "sal", NULL, N_( "Salishan Languages" ) }, + // language code: sam + { "sam", NULL, N_( "Samaritan Aramaic" ) }, + // language code: san sa + { "san", "sa", N_( "Sanskrit" ) }, + // language code: sas + { "sas", NULL, N_( "Sasak" ) }, + // language code: sat + { "sat", NULL, N_( "Santali" ) }, + // language code: scc srp sr + { "scc", "sr", N_( "Serbian" ) }, + // language code: scc srp sr + { "srp", NULL, N_( "Serbian" ) }, + // language code: scn + { "scn", NULL, N_( "Sicilian" ) }, + // language code: sco + { "sco", NULL, N_( "Scots" ) }, + // language code: scr hrv hr + { "scr", "hr", N_( "Croatian" ) }, + // language code: scr hrv hr + { "hrv", NULL, N_( "Croatian" ) }, + // language code: sel + { "sel", NULL, N_( "Selkup" ) }, + // language code: sem + { "sem", NULL, N_( "Semitic (Other)" ) }, + // language code: sga + { "sga", NULL, N_( "Irish, Old (to 900)" ) }, + // language code: sgn + { "sgn", NULL, N_( "Sign Languages" ) }, + // language code: shn + { "shn", NULL, N_( "Shan" ) }, + // language code: sid + { "sid", NULL, N_( "Sidamo" ) }, + // language code: sin si + { "sin", "si", N_( "Sinhala" ) }, + // language code: sio + { "sio", NULL, N_( "Siouan Languages" ) }, + // language code: sit + { "sit", NULL, N_( "Sino-Tibetan (Other)" ) }, + // language code: sla + { "sla", NULL, N_( "Slavic (Other)" ) }, + // language code: slo slk sk + { "slo", "sk", N_( "Slovak" ) }, + // language code: slo slk sk + { "slk", NULL, N_( "Slovak" ) }, + // language code: slv sl + { "slv", "sl", N_( "Slovenian" ) }, + // language code: sma + { "sma", NULL, N_( "Southern Sami" ) }, + // language code: sme se + { "sme", "se", N_( "Northern Sami" ) }, + // language code: smi + { "smi", NULL, N_( "Sami Languages (Other)" ) }, + // language code: smj + { "smj", NULL, N_( "Lule Sami" ) }, + // language code: smn + { "smn", NULL, N_( "Inari Sami" ) }, + // language code: smo sm + { "smo", "sm", N_( "Samoan" ) }, + // language code: sms + { "sms", NULL, N_( "Skolt Sami" ) }, + // language code: sna sn + { "sna", "sn", N_( "Shona" ) }, + // language code: snd sd + { "snd", "sd", N_( "Sindhi" ) }, + // language code: snk + { "snk", NULL, N_( "Soninke" ) }, + // language code: sog + { "sog", NULL, N_( "Sogdian" ) }, + // language code: som so + { "som", "so", N_( "Somali" ) }, + // language code: son + { "son", NULL, N_( "Songhai" ) }, + // language code: sot st + { "sot", "st", N_( "Sotho, Southern" ) }, + // language code: spa es + { "spa", "es", N_( "Spanish" ) }, + // language code: srd sc + { "srd", "sc", N_( "Sardinian" ) }, + // language code: srr + { "srr", NULL, N_( "Serer" ) }, + // language code: ssa + { "ssa", NULL, N_( "Nilo-Saharan (Other)" ) }, + // language code: ssw ss + { "ssw", "ss", N_( "Swati" ) }, + // language code: suk + { "suk", NULL, N_( "Sukuma" ) }, + // language code: sun su + { "sun", "su", N_( "Sundanese" ) }, + // language code: sus + { "sus", NULL, N_( "Susu" ) }, + // language code: sux + { "sux", NULL, N_( "Sumerian" ) }, + // language code: swa sw + { "swa", "sw", N_( "Swahili" ) }, + // language code: swe sv + { "swe", "sv", N_( "Swedish" ) }, + // language code: syr + { "syr", NULL, N_( "Syriac" ) }, + // language code: tah ty + { "tah", "ty", N_( "Tahitian" ) }, + // language code: tai + { "tai", NULL, N_( "Tai (Other)" ) }, + // language code: tam ta + { "tam", "ta", N_( "Tamil" ) }, + // language code: tat tt + { "tat", "tt", N_( "Tatar" ) }, + // language code: tel te + { "tel", "te", N_( "Telugu" ) }, + // language code: tem + { "tem", NULL, N_( "Timne" ) }, + // language code: ter + { "ter", NULL, N_( "Tereno" ) }, + // language code: tet + { "tet", NULL, N_( "Tetum" ) }, + // language code: tgk tg + { "tgk", "tg", N_( "Tajik" ) }, + // language code: tgl tl + { "tgl", "tl", N_( "Tagalog" ) }, + // language code: tha th + { "tha", "th", N_( "Thai" ) }, + // language code: tib bod bo + { "tib", "bo", N_( "Tibetan" ) }, + // language code: tib bod bo + { "bod", NULL, N_( "Tibetan" ) }, + // language code: tig + { "tig", NULL, N_( "Tigre" ) }, + // language code: tir ti + { "tir", "ti", N_( "Tigrinya" ) }, + // language code: tiv + { "tiv", NULL, N_( "Tiv" ) }, + // language code: tkl + { "tkl", NULL, N_( "Tokelau" ) }, + // language code: tlh + { "tlh", NULL, N_( "Klingon" ) }, + // language code: tli + { "tli", NULL, N_( "Tlingit" ) }, + // language code: tmh + { "tmh", NULL, N_( "Tamashek" ) }, + // language code: tog + { "tog", NULL, N_( "Tonga (Nyasa)" ) }, + // language code: ton to + { "ton", "to", N_( "Tonga (Tonga Islands)" ) }, + // language code: tpi + { "tpi", NULL, N_( "Tok Pisin" ) }, + // language code: tsi + { "tsi", NULL, N_( "Tsimshian" ) }, + // language code: tsn tn + { "tsn", "tn", N_( "Tswana" ) }, + // language code: tso ts + { "tso", "ts", N_( "Tsonga" ) }, + // language code: tuk tk + { "tuk", "tk", N_( "Turkmen" ) }, + // language code: tum + { "tum", NULL, N_( "Tumbuka" ) }, + // language code: tup + { "tup", NULL, N_( "Tupi Languages" ) }, + // language code: tur tr + { "tur", "tr", N_( "Turkish" ) }, + // language code: tut + { "tut", NULL, N_( "Altaic (Other)" ) }, + // language code: tvl + { "tvl", NULL, N_( "Tuvalu" ) }, + // language code: twi tw + { "twi", "tw", N_( "Twi" ) }, + // language code: tyv + { "tyv", NULL, N_( "Tuvinian" ) }, + // language code: udm + { "udm", NULL, N_( "Udmurt" ) }, + // language code: uga + { "uga", NULL, N_( "Ugaritic" ) }, + // language code: uig ug + { "uig", "ug", N_( "Uighur" ) }, + // language code: ukr uk + { "ukr", "uk", N_( "Ukrainian" ) }, + // language code: umb + { "umb", NULL, N_( "Umbundu" ) }, + // language code: und + { "und", NULL, N_( "Undetermined" ) }, + // language code: urd ur + { "urd", "ur", N_( "Urdu" ) }, + // language code: uzb uz + { "uzb", "uz", N_( "Uzbek" ) }, + // language code: vai + { "vai", NULL, N_( "Vai" ) }, + // language code: ven ve + { "ven", "ve", N_( "Venda" ) }, + // language code: vie vi + { "vie", "vi", N_( "Vietnamese" ) }, + // language code: vol vo + { "vol", "vo", N_( "Volapuk" ) }, + // language code: vot + { "vot", NULL, N_( "Votic" ) }, + // language code: wak + { "wak", NULL, N_( "Wakashan Languages" ) }, + // language code: wal + { "wal", NULL, N_( "Walamo" ) }, + // language code: war + { "war", NULL, N_( "Waray" ) }, + // language code: was + { "was", NULL, N_( "Washo" ) }, + // language code: wel cym cy + { "wel", "cy", N_( "Welsh" ) }, + // language code: wel cym cy + { "cym", NULL, N_( "Welsh" ) }, + // language code: wen + { "wen", NULL, N_( "Sorbian Languages" ) }, + // language code: wln wa + { "wln", "wa", N_( "Walloon" ) }, + // language code: wol wo + { "wol", "wo", N_( "Wolof" ) }, + // language code: xal + { "xal", NULL, N_( "Kalmyk" ) }, + // language code: xho xh + { "xho", "xh", N_( "Xhosa" ) }, + // language code: yao + { "yao", NULL, N_( "Yao" ) }, + // language code: yap + { "yap", NULL, N_( "Yapese" ) }, + // language code: yid yi + { "yid", "yi", N_( "Yiddish" ) }, + // language code: yor yo + { "yor", "yo", N_( "Yoruba" ) }, + // language code: ypk + { "ypk", NULL, N_( "Yupik Languages" ) }, + // language code: zap + { "zap", NULL, N_( "Zapotec" ) }, + // language code: zen + { "zen", NULL, N_( "Zenaga" ) }, + // language code: zha za + { "zha", "za", N_( "Zhuang" ) }, + // language code: znd + { "znd", NULL, N_( "Zande" ) }, + // language code: zul zu + { "zul", "zu", N_( "Zulu" ) }, + // language code: zun + { "zun", NULL, N_( "Zuni" ) }, + + { NULL, NULL, NULL } + }; + + for (const LangInit * i = langInit; i->iso639_2 != NULL; ++i) + { + const char * name( i->name ); + _codeMap[i->iso639_2] = name; + if (i->iso639_1 != NULL) + _codeMap[i->iso639_1] = name; + } + } + } // namespace + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/LanguageCode.h b/zypp/LanguageCode.h new file mode 100644 index 0000000..d58bc59 --- /dev/null +++ b/zypp/LanguageCode.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/LanguageCode.h + * +*/ +#ifndef ZYPP_LANGUAGECODE_H +#define ZYPP_LANGUAGECODE_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class LanguageCode + /// \brief Language codes (iso639_2/iso639_1). + /// + /// In fact the class will not prevent to use a non iso language code. + /// Just a warning will appear in the log. + /////////////////////////////////////////////////////////////////// + class ZYPP_API LanguageCode : public IdStringType + { + public: + /** Default Ctor: \ref noCode */ + LanguageCode(); + + /** Ctor from string. */ + explicit LanguageCode( IdString str_r ); + + /** Ctor from string. */ + explicit LanguageCode( const std::string & str_r ); + + /** Ctor from string. */ + explicit LanguageCode( const char * str_r ); + + /** Dtor */ + ~LanguageCode(); + + public: + /** \name LanguageCode constants. */ + //@{ + /** Empty code. */ + static const LanguageCode noCode; + /** Last resort "en". */ + static const LanguageCode enCode; + //@} + + public: + /** Return the language code asString. */ + std::string code() const + { return std::string(_str); } + + /** Return the translated language name; if unknown the language code. */ + std::string name() const; + + private: + friend class IdStringType; + IdString _str; + }; +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +ZYPP_DEFINE_ID_HASHABLE( ::zypp::LanguageCode ); + +#endif // ZYPP_LANGUAGECODE_H diff --git a/zypp/Locale.cc b/zypp/Locale.cc new file mode 100644 index 0000000..f56ae95 --- /dev/null +++ b/zypp/Locale.cc @@ -0,0 +1,229 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Locale.cc + * +*/ +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /** Wrap static codemap data. */ + struct CodeMaps + { + /** Return IdString without trailing garbage. */ + static IdString withoutTrash( IdString code_r ) + { + boost::string_ref::size_type sep = trashStart( code_r ); + if ( sep != boost::string_ref::npos ) + code_r = IdString( code_r.c_str(), sep ); + return code_r; + } + + /** Return IdString without trailing garbage. */ + static IdString withoutTrash( const std::string & code_r ) + { return withoutTrash( boost::string_ref(code_r) ); } + + /** Return IdString without trailing garbage. */ + static IdString withoutTrash( const char * code_r ) + { return( code_r ? withoutTrash( boost::string_ref(code_r) ) : IdString::Null ); } + + /** Return IdString from language/country codes. */ + static IdString combineLC( const LanguageCode& language_r, const CountryCode& country_r ) + { + IdString ret; + if ( language_r ) + { + if ( country_r ) + ret = IdString( std::string(language_r) + "_" + country_r.c_str() ); + else + ret = IdString(language_r); + } + else + { + if ( country_r ) + ret = IdString( "_" + std::string(country_r) ); + else if ( ! ( IdString(language_r) || IdString(country_r) ) ) + ret = IdString::Null; + // else IdString::Empty + } + return ret; + } + + /** The singleton */ + static CodeMaps & instance() + { + static CodeMaps _instance; + return _instance; + } + + LanguageCode language( IdString index_r ) + { return getIndex( index_r )._l; } + + CountryCode country( IdString index_r ) + { return getIndex( index_r )._c; } + + std::string name( IdString index_r ) + { + const LC & lc( getIndex( index_r ) ); + std::string ret( lc._l.name() ); + if ( lc._c ) + { + ret += " ("; + ret += lc._c.name(); + ret += ")"; + } + return ret; + } + + Locale fallback( IdString index_r ) + { + static const IdString special( "pt_BR" ); + Locale ret; + if ( index_r == special ) // "pt_BR"->"en" - by now the only fallback exception + ret = Locale::enCode; + else + { + const LC & lc( getIndex( index_r ) ); + if ( lc._c ) + ret = lc._l; + else if ( lc._l && lc._l != LanguageCode::enCode ) + ret = Locale::enCode; + } + return ret; + } + + private: + static IdString withoutTrash( boost::string_ref code_r ) + { + boost::string_ref::size_type sep = trashStart( code_r ); + if ( sep != boost::string_ref::npos ) + code_r = code_r.substr( 0, sep ); + return IdString( code_r ); + } + + static boost::string_ref::size_type trashStart( boost::string_ref code_r ) + { return code_r.find_first_of( "@." ); } + + static boost::string_ref::size_type trashStart( IdString code_r ) + { return trashStart( boost::string_ref(code_r.c_str()) ); } + + private: + struct LC { + LC() {} + LC( const LanguageCode& l_r ) : _l( l_r ) {} + LC( const LanguageCode& l_r, const CountryCode& c_r ) : _l( l_r ), _c( c_r ) {} + LanguageCode _l; + CountryCode _c; + }; + using CodeMap = std::unordered_map; + + /** Ctor initializes the code maps. */ + CodeMaps() + : _codeMap( { { IdString::Null, LC( LanguageCode(IdString::Null), CountryCode(IdString::Null) ) } + , { IdString::Empty, LC( LanguageCode(IdString::Empty), CountryCode(IdString::Empty) ) } } ) + {} + + /** Return \ref LC for \a index_r, creating it if necessary. */ + const LC & getIndex( IdString index_r ) + { + auto it = _codeMap.find( index_r ); + if ( it == _codeMap.end() ) + { + CodeMap::value_type newval( index_r, LC() ); + + boost::string_ref str( index_r.c_str() ); + boost::string_ref::size_type sep = str.find( '_' ); + if ( sep == boost::string_ref::npos ) + newval.second._l = LanguageCode( index_r ); + else + { + // bsc#1064999: dup! Creating a new IdString may invalidate the IdString.c_str() stored in str. + std::string dup( str ); + str = dup; + newval.second._l = LanguageCode( IdString(str.substr( 0, sep )) ); + newval.second._c = CountryCode( IdString(str.substr( sep+1 )) ); + } + + it = _codeMap.insert( std::move(newval) ).first; + } + return it->second; + } + + private: + CodeMap _codeMap; + }; + + /////////////////////////////////////////////////////////////////// + // class Locale + /////////////////////////////////////////////////////////////////// + + const Locale Locale::noCode; + const LanguageCode LanguageCode::enCode("en"); // from in LanguageCode.cc as Locale::enCode depends on it + const Locale Locale::enCode( LanguageCode::enCode ); + + Locale::Locale() + {} + + Locale::Locale( IdString str_r ) + : _str( CodeMaps::withoutTrash( str_r ) ) + {} + + Locale::Locale( const std::string & str_r ) + : _str( CodeMaps::withoutTrash( str_r ) ) + {} + + Locale::Locale( const char * str_r ) + : _str( CodeMaps::withoutTrash( str_r ) ) + {} + + Locale::Locale( const LanguageCode& language_r, const CountryCode& country_r ) + : _str( CodeMaps::combineLC( language_r, country_r ) ) + {} + + Locale::~Locale() + {} + + LanguageCode Locale::language() const + { return CodeMaps::instance().language( _str ); } + + CountryCode Locale::country() const + { return CodeMaps::instance().country( _str ); } + + std::string Locale::name() const + { return CodeMaps::instance().name( _str ); } + + Locale Locale::fallback() const + { return CodeMaps::instance().fallback( _str ); } + + /////////////////////////////////////////////////////////////////// + + Locale Locale::bestMatch( const LocaleSet & avLocales_r, Locale requested_r ) + { + if ( ! avLocales_r.empty() ) + { + if ( ! requested_r ) + requested_r = ZConfig::instance().textLocale(); + for ( ; requested_r; requested_r = requested_r.fallback() ) + { + if ( avLocales_r.count( requested_r ) ) + return requested_r; + } + } + return Locale(); + } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Locale.h b/zypp/Locale.h new file mode 100644 index 0000000..ca9abbe --- /dev/null +++ b/zypp/Locale.h @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Locale.h + * +*/ +#ifndef ZYPP_LOCALE_H +#define ZYPP_LOCALE_H + +#include +#include + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + class Locale; + using LocaleSet = std::unordered_set; + + /////////////////////////////////////////////////////////////////// + /// \class Locale + /// \brief 'Language[_Country]' codes. + /// + /// In fact the class will not prevent to use a non iso code. + /// Just a warning will appear in the log. Construction from string + /// consider everything up to the first \c '.' or \c '@'. + /// \code + /// Locale l( "de_DE.UTF-8" ); + /// + /// l.code() == "de_DE"; + /// l.language() == "de"; + /// l.country() == "DE"; + /// + /// l.fallback() == "de"; + /// l.fallback().fallback() == Locale::enCode == "en"; + /// l.fallback().fallback().fallback() == Locale::noCode == ""; + /// \endcode + /////////////////////////////////////////////////////////////////// + class ZYPP_API Locale : public IdStringType + { + public: + /** Default Ctor: \ref noCode */ + Locale(); + + /** Ctor from string. */ + explicit Locale( IdString str_r ); + + /** Ctor from string. */ + explicit Locale( const std::string & str_r ); + + /** Ctor from string. */ + explicit Locale( const char * str_r ); + + /** Ctor taking LanguageCode and optional CountryCode. */ + Locale( const LanguageCode& language_r, const CountryCode& country_r = CountryCode() ); + + /** Dtor */ + ~Locale(); + + public: + /** \name Locale constants. */ + //@{ + /** Empty code. */ + static const Locale noCode; + + /** Last resort "en". */ + static const Locale enCode; + //@} + + public: + /** The language part. */ + LanguageCode language() const; + + /** The county part.*/ + CountryCode country() const; + + /** Return the locale code asString. */ + std::string code() const + { return std::string(_str); } + + /** Return the translated locale name. */ + std::string name() const; + + public: + /** Return the fallback locale for this locale, if no fallback exists the empty Locale::noCode. + * The usual fallback sequence is "language_COUNTRY" -> "language" -> Locale::enCode ("en") + * ->Locale::noCode (""). Some exceptions like "pt_BR"->"en"->"" do exist. + */ + Locale fallback() const; + + /** Return the best match for \ref Locale \a requested_r within the available \a avLocales_r. + * + * If \a requested_r is not specified \ref ZConfig::textLocale is assumed. + * + * If neither \c requested_r nor any of its \ref fallback locales are available + * in \a avLocales_r, \ref Locale::noCode is returned. + */ + static Locale bestMatch( const LocaleSet & avLocales_r, Locale requested_r = Locale() ); + + private: + friend class IdStringType; + IdString _str; + }; +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +ZYPP_DEFINE_ID_HASHABLE( ::zypp::Locale ); + +#endif // ZYPP_LOCALE_H diff --git a/zypp/Locks.cc b/zypp/Locks.cc new file mode 100644 index 0000000..7ad5ffe --- /dev/null +++ b/zypp/Locks.cc @@ -0,0 +1,495 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "locks" + +#include + +using std::endl; + +namespace zypp +{ + +Locks& Locks::instance() +{ + static Locks _instance; + return _instance; +} + +using LockSet = std::set; + +template +void remove_if( LockSet & lockset_r, TPredicate pred_r ) +{ + LockSet::iterator first = lockset_r.begin(); + LockSet::iterator last = lockset_r.end(); + while ( first != last ) + { + LockSet::iterator next = first; + ++next; + if ( pred_r( *first ) ) + lockset_r.erase( first ); + first = next; + } +} + +class Locks::Impl +{ +public: + LockSet toAdd; + LockSet toRemove; + bool locksDirty; + + bool mergeList(callback::SendReport& report); + + Impl() + : locksDirty( false ) + , _APIdirty( false ) + {} + + + // need to control manip locks _locks to maintain the legacy API LockList::iterator begin/end + + const LockSet & locks() const + { return _locks; } + + LockSet & MANIPlocks() + { if ( !_APIdirty ) _APIdirty = true; return _locks; } + + const LockList & APIlocks() const + { + if ( _APIdirty ) + { + _APIlocks.clear(); + _APIlocks.insert( _APIlocks.end(), _locks.begin(), _locks.end() ); + _APIdirty = false; + } + return _APIlocks; + } + +private: + // need to control manip in ordert to maintain the legacy API LockList::iterator begin/end + LockSet _locks; + mutable LockList _APIlocks; + mutable bool _APIdirty; +}; + +Locks::Locks() : _pimpl(new Impl){} + +Locks::const_iterator Locks::begin() const +{ return _pimpl->APIlocks().begin(); } + +Locks::const_iterator Locks::end() const +{ return _pimpl->APIlocks().end(); } + +Locks::LockList::size_type Locks::size() const +{ return _pimpl->locks().size(); } + +bool Locks::empty() const +{ return _pimpl->locks().empty(); } + +struct ApplyLock +{ + void operator()(const PoolQuery& query) const + { + for ( const PoolItem & item : query.poolItem() ) + { + item.status().setLock(true,ResStatus::USER); + DBG << "lock "<< item.name(); + } + } +}; + +/** + * iterator that takes lock, lock all solvables from query + * and send query to output iterator + */ +template +struct LockingOutputIterator +{ + LockingOutputIterator(OutputIterator& out_) + : out(out_) + {} + + void operator()(const PoolQuery& query) const + { + ApplyLock a;a(query); + *out++ = query; + } + + private: + OutputIterator& out; +}; + +void Locks::readAndApply( const Pathname& file ) +{ + MIL << "read and apply locks from "< ii( _pimpl->MANIPlocks(), _pimpl->MANIPlocks().end() ); + LockingOutputIterator > lout(ii); + readPoolQueriesFromFile( file, boost::make_function_output_iterator(lout) ); + } + else + MIL << "file does not exist(or cannot be stat), no lock added." << endl; + +} + +void Locks::read( const Pathname& file ) +{ + MIL << "read locks from "<(_pimpl->MANIPlocks(), _pimpl->MANIPlocks().end()) ); + else + MIL << "file does not exist(or cannot be stat), no lock added." << endl; +} + + +void Locks::apply() const +{ + DBG << "apply locks" << endl; + for_each(_pimpl->locks().begin(), _pimpl->locks().end(), ApplyLock()); +} + + +void Locks::addLock( const PoolQuery& query ) +{ + MIL << "add new lock" << endl; + for_( it,query.begin(),query.end() ) + { + PoolItem item(*it); + item.status().setLock(true,ResStatus::USER); + } + if ( _pimpl->toRemove.erase( query ) ) + { + DBG << "query removed from toRemove" << endl; + } + else + { + DBG << "query added as new" << endl; + _pimpl->toAdd.insert( query ); + } +} + +void Locks::addLock( const IdString& ident_r ) +{ + sat::Solvable::SplitIdent id(ident_r); + addLock(id.kind(),id.name()); +} + +void Locks::addLock( const ResKind& kind_r, const C_Str & name_r ) +{ + addLock(kind_r,IdString(name_r)); +} + +void Locks::addLock( const ResKind& kind_r, const IdString& name_r ) +{ + PoolQuery q; + q.addAttribute( sat::SolvAttr::name,name_r.asString() ); + q.addKind( kind_r ); + q.setMatchExact(); + q.setCaseSensitive(true); + DBG << "add lock by identifier" << endl; + addLock( q ); +} + +void Locks::removeLock( const PoolQuery& query ) +{ + MIL << "remove lock" << endl; + for_( it,query.begin(),query.end() ) + { + PoolItem item(*it); + item.status().setLock(false,ResStatus::USER); + } + + if ( _pimpl->toAdd.erase( query ) ) + { + DBG << "query removed from added" << endl; + } + else + { + DBG << "need to remove some old lock" << endl; + _pimpl->toRemove.insert( query ); + } +} + +void Locks::removeLock( const IdString& ident_r ) +{ + sat::Solvable::SplitIdent id(ident_r); + removeLock(id.kind(),id.name()); +} + +void Locks::removeLock( const ResKind& kind_r, const C_Str & name_r ) +{ + removeLock(kind_r,IdString(name_r)); +} + +void Locks::removeLock( const ResKind &kind_r, const IdString &name_r ) +{ + PoolQuery q; + q.addAttribute( sat::SolvAttr::name,name_r.asString() ); + q.addKind( kind_r ); + q.setMatchExact(); + q.setCaseSensitive(true); + DBG << "remove lock by Selectable" << endl; + removeLock(q); +} + +bool Locks::existEmpty() const +{ + for_( it, _pimpl->locks().begin(), _pimpl->locks().end() ) + { + if( it->empty() ) + return true; + } + + return false; +} + +//handle locks during removing +class LocksCleanPredicate{ +private: + bool skip_rest; + size_t searched; + size_t all; + callback::SendReport &report; + +public: + LocksCleanPredicate(size_t count, callback::SendReport &_report): skip_rest(false),searched(0),all(count), report(_report){} + + bool aborted(){ return skip_rest; } + + bool operator()( const PoolQuery & q ) + { + if( skip_rest ) + return false; + searched++; + if( !q.empty() ) + return false; + + if (!report->progress((100*searched)/all)) + { + skip_rest = true; + return false; + } + + switch (report->execute(q)) + { + case CleanEmptyLocksReport::ABORT: + report->finish(CleanEmptyLocksReport::ABORTED); + skip_rest = true; + return false; + case CleanEmptyLocksReport::DELETE: + return true; + case CleanEmptyLocksReport::IGNORE: + return false; + default: + INT << "Unexpected return value from callback. Need to adapt switch statement." << std::endl; + } + + return false; + } + +}; + +void Locks::removeEmpty() +{ + MIL << "clean of locks" << endl; + callback::SendReport report; + report->start(); + size_t sum = _pimpl->locks().size(); + LocksCleanPredicate p(sum, report); + + remove_if( _pimpl->MANIPlocks(), p ); + + if( p.aborted() ) + { + MIL << "cleaning aborted" << endl; + report->finish(CleanEmptyLocksReport::ABORTED); + } + else + { + report->finish(CleanEmptyLocksReport::NO_ERROR); + + } + + if ( sum != _pimpl->locks().size() ) //some locks has been removed + _pimpl->locksDirty = true; +} + +class LocksRemovePredicate +{ +private: + std::set& solvs; + const PoolQuery& query; + callback::SendReport& report; + bool aborted_; + + //1 for subset of set, 2 only intersect, 0 for not intersect + int contains(const PoolQuery& q, std::set& s) + { + bool intersect = false; + for_( it,q.begin(),q.end() ) + { + if ( s.find(*it)!=s.end() ) + { + intersect = true; + } + else + { + if (intersect) + return 2; + } + } + return intersect ? 1 : 0; + } + +public: + LocksRemovePredicate(std::set& s, const PoolQuery& q, + callback::SendReport& r) + : solvs(s), query(q),report(r),aborted_(false) {} + + bool operator()(const PoolQuery& q) + { + if (aborted()) + return false; + if( q==query ) + {//identical + DBG << "identical queries" << endl; + return true; + } + + SavingLocksReport::ConflictState cs; + switch( contains(q,solvs) ) + { + case 0: + return false; //another lock + case 1: + cs = SavingLocksReport::SAME_RESULTS; + break; + case 2: + cs = SavingLocksReport::INTERSECT; + break; + default: + return true; + } + MIL << "find conflict: " << cs << endl; + switch (report->conflict(q,cs)) + { + case SavingLocksReport::ABORT: + aborted_ = true; + DBG << "abort merging" << endl; + return false; + case SavingLocksReport::DELETE: + DBG << "force delete" << endl; + return true; + case SavingLocksReport::IGNORE: + DBG << "skip lock" << endl; + return false; + } + INT << "Unexpected return value from callback. Need to adapt switch statement." << std::endl; + return false; + } + + bool aborted(){ return aborted_; } +}; + +bool Locks::Impl::mergeList(callback::SendReport& report) +{ + MIL << "merge list old: " << locks().size() + << " to add: " << toAdd.size() << " to remove: " << toRemove.size() << endl; + for_(it,toRemove.begin(),toRemove.end()) + { + std::set s(it->begin(),it->end()); + remove_if( MANIPlocks(), LocksRemovePredicate(s,*it, report) ); + } + + if (!report->progress()) + return false; + + for ( const auto & q : toAdd ) { + const auto & [i,b] { MANIPlocks().insert( q ) }; + if ( not b && i->comment() != q.comment() ) + i->setComment( q.comment() ); // update comment if query already exists + } + + toAdd.clear(); + toRemove.clear(); + + return true; +} + +void Locks::merge() +{ + if( (_pimpl->toAdd.size() | _pimpl->toRemove.size())==0) + { + return; //nothing to merge + } + + callback::SendReport report; + report->start(); + if (!_pimpl->mergeList(report)) + { + report->finish(SavingLocksReport::ABORTED); + return; + } + DBG << "locks merged" << endl; + report->finish(SavingLocksReport::NO_ERROR); + _pimpl->locksDirty = true; +} + +void Locks::save( const Pathname& file ) +{ + if( ((_pimpl->toAdd.size() | _pimpl->toRemove.size())==0) + && !_pimpl->locksDirty ) + { + DBG << "nothing changed in locks - no write to file" << endl; + return; + } + + callback::SendReport report; + report->start(); + + if ((_pimpl->toAdd.size() | _pimpl->toRemove.size())!=0) + { + if (!_pimpl->mergeList(report)) + { + report->finish(SavingLocksReport::ABORTED); + return; + } + } + + DBG << "wrote "<< _pimpl->locks().size() << "locks" << endl; + writePoolQueriesToFile( file, _pimpl->locks().begin(), _pimpl->locks().end() ); + report->finish(SavingLocksReport::NO_ERROR); +} + +void Locks::removeDuplicates() +{ /* NOP since implementation uses std::set */ } + +} // ns zypp diff --git a/zypp/Locks.h b/zypp/Locks.h new file mode 100644 index 0000000..b8ac476 --- /dev/null +++ b/zypp/Locks.h @@ -0,0 +1,153 @@ +#ifndef ZYPP_LOCKS_H +#define ZYPP_LOCKS_H + +#include +#include +#include +#include + +namespace zypp +{ + /** \name Locks */ + //@{ + /** + * Singleton class which manipulate with locks file and apply locks on pool. + * for user information about locksfile and its format see + * http://en.opensuse.org/Libzypp/Locksfile + */ + class ZYPP_API Locks + { + public: + using LockList = std::list; + using const_iterator = LockList::const_iterator; + using size_type = LockList::size_type; + public: + class Impl; + + /** + * Gets instance of this class. + * Singleton method. + */ + static Locks& instance(); + + const_iterator begin() const; + const_iterator end() const; + LockList::size_type size() const; + bool empty() const; + + /** + * TODO add: + * toBeAdded{Begin,End,Size,Empty} + * toBeRemoved{Begin,End,Size,Empty} + */ + + /** + * locks result of query and add this lock as toAdd + */ + void addLock( const PoolQuery& query ); + + /** + * add lock by identifier (e.g. Selectable->ident() + * and add this lock as toAdd + */ + void addLock( const IdString& ident_r ); + + /** + * add lock by name and kind and + * add this lock as toAdd + */ + void addLock( const ResKind& kind_r, const IdString& name_r ); + + /** + * add lock by name and kind and + * add this lock as toAdd + */ + void addLock( const ResKind& kind_r, const C_Str& name_r ); + + /** + * unlocks by result of query and add to toRemove. + * + * If unlock non-saved lock (so it is in toAdd list) then both is deleted + * and nothing happens during save + */ + void removeLock( const PoolQuery& query ); + + /** + * remove lock by identifier (e.g. Selectable->ident() + * + * If unlock non-saved lock (so it is in toAdd list) then both is deleted + * and nothing happens during save + */ + void removeLock( const IdString& ident_r ); + + /** + * remove lock by name and kind + * + * If unlock non-saved lock (so it is in toAdd list) then both is deleted + * and nothing happens during save + */ + void removeLock( const ResKind& kind_r, const IdString& name_r ); + void removeLock( const ResKind& kind_r, const C_Str & name_r ); + + /** + * Optimalized version of read and apply. + * \see read + * \see apply + */ + void readAndApply( const Pathname& file = ZConfig::instance().locksFile() ); + + /** + * Read locks from file to list of stable locks (locks which is not changed + * during session) + */ + void read( const Pathname& file = ZConfig::instance().locksFile() ); + + /** + * Applies locks in stable list (locks which is not changed during session). + */ + void apply() const; + + /** + * Merges toAdd and ToRemove list to stable list and + * save that stable list to file. + * \see SavingLocksReport + */ + void save( const Pathname& file = ZConfig::instance().locksFile() ); + + /** + * Merges toAdd and ToRemove list to stable list. + * \note Can call callback if problem during merging occure + * \see SavingLocksReport + */ + void merge(); + + /** + * Gets true if some lock doesn't lock any object in pool + * This can happen e.g. if package is removed or + * due to user bad definition of lock + */ + bool existEmpty() const; + + /** + * Call callback for each empty lock. + * \see existEmpty + * \see CleanEmptyLocksReport + * \note you must call \a save to write cleaned locks to file + */ + void removeEmpty(); + + /** + * Delete all query duplicate in loaded locks. + * \note you must call \a save to write cleaned locks to file + */ + void removeDuplicates(); + //@} + private: + Locks(); + + RW_pointer > _pimpl; + + }; +} + +#endif diff --git a/zypp/ManagedFile.h b/zypp/ManagedFile.h new file mode 100644 index 0000000..d2e7de2 --- /dev/null +++ b/zypp/ManagedFile.h @@ -0,0 +1,12 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ManagedFile.h + * +*/ +#include diff --git a/zypp/MediaProducts.h b/zypp/MediaProducts.h new file mode 100644 index 0000000..13f1057 --- /dev/null +++ b/zypp/MediaProducts.h @@ -0,0 +1,127 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/MediaProducts.h + * Functions to find out products in media + */ +#ifndef ZYPP_MEDIAPRODUCTS_H_ +#define ZYPP_MEDIAPRODUCTS_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace zypp +{ + /** + * \short Represents an available product in media + */ + struct MediaProductEntry + { + Pathname _dir; + std::string _name; + + /** + * \short Ctor + */ + MediaProductEntry( Pathname dir_r = "/", std::string name_r = std::string() ) + : _dir(std::move(dir_r)), _name(std::move(name_r)) + { + } + + bool operator<( const MediaProductEntry &rhs ) const + { + int res = _name.compare( rhs._name ); + return ( res < 0 || ( res == 0 && _dir < rhs._dir ) ); + } + }; + + /** + * A set of available products in media + */ + using MediaProductSet = std::set; + + /** + * FIXME: add a comment here... + */ + template + static void scanProductsFile( const Pathname & file_r, TOutputIterator result ) + { + std::ifstream pfile( file_r.asString().c_str() ); + while ( pfile.good() ) { + + std::string value = str::getline( pfile, str::TRIM ); + if ( pfile.bad() ) { + ERR << "Error parsing " << file_r << std::endl; + ZYPP_THROW(Exception("Error parsing " + file_r.asString())); + } + if ( pfile.fail() ) { + break; // no data on last line + } + std::string tag = str::stripFirstWord( value, true ); + + if ( tag.size() ) { + *result = MediaProductEntry( tag, value ); + } + } + } + + /** + * \short Available products in a url location + * + * \param url_r url to inspect + * \param result output iterator where \ref MediaProductEntry + * items will be inserted. + * \throws MediaException If accessng the media fails + */ + template + void productsInMedia( const Url & url_r, TOutputIterator result ) + { + media::MediaManager media_mgr; + // open the media + media::MediaAccessId id = media_mgr.open(url_r); + media_mgr.attach(id); + Pathname products_file = Pathname("media.1/products"); + + try { + media_mgr.provideFile (id, OnMediaLocation(products_file) ); + products_file = media_mgr.localPath (id, products_file); + scanProductsFile (products_file, result); + } + catch ( const Exception & excpt ) { + ZYPP_CAUGHT(excpt); + MIL << "No products description found on the Url" << std::endl; + } + media_mgr.release(id, ""); + } + + /** + * \short Available products in a url location + * + * \param url_r url to inspect + * \param set ef MediaProductEntry set where + * items will be inserted. + * \throws MediaException If accessng the media fails + */ + void productsInMedia( const Url & url_r, MediaProductSet &set ) + { + productsInMedia(url_r, std::inserter(set, set.end())); + } + +} // ns zypp + +#endif + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/MediaSetAccess.cc b/zypp/MediaSetAccess.cc new file mode 100644 index 0000000..b4295e9 --- /dev/null +++ b/zypp/MediaSetAccess.cc @@ -0,0 +1,501 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::fetcher" + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + +IMPL_PTR_TYPE(MediaSetAccess); + +/////////////////////////////////////////////////////////////////// + + MediaSetAccess::MediaSetAccess(Url url, + Pathname prefered_attach_point) + : _url(std::move(url)) + , _prefAttachPoint(std::move(prefered_attach_point)) + {} + + MediaSetAccess::MediaSetAccess(std::string label_r, + Url url, + Pathname prefered_attach_point) + : _url(std::move(url)) + , _prefAttachPoint(std::move(prefered_attach_point)) + , _label(std::move( label_r )) + {} + + MediaSetAccess::~MediaSetAccess() + { + try + { + media::MediaManager manager; + for ( const auto & mm : _medias ) + manager.close( mm.second ); + } + catch(...) {} // don't let exception escape a dtor. + } + + + void MediaSetAccess::setVerifier( unsigned media_nr, const media::MediaVerifierRef& verifier ) + { + if (_medias.find(media_nr) != _medias.end()) + { + // the media already exists, set theverifier + media::MediaAccessId id = _medias[media_nr]; + media::MediaManager media_mgr; + media_mgr.addVerifier( id, verifier ); + // remove any saved verifier for this media + _verifiers.erase(media_nr); + } + else + { + // save the verifier in the map, and set it when + // the media number is first attached + _verifiers[media_nr] = verifier; + } + } + + void MediaSetAccess::releaseFile( const OnMediaLocation & on_media_file ) + { + releaseFile( on_media_file.filename(), on_media_file.medianr() ); + } + + void MediaSetAccess::releaseFile( const Pathname & file, unsigned media_nr) + { + media::MediaManager media_mgr; + media::MediaAccessId media = getMediaAccessId( media_nr); + DBG << "Going to release file " << file + << " from media number " << media_nr << endl; + + if ( ! media_mgr.isAttached(media) ) + return; //disattached media is free + + media_mgr.releaseFile (media, file); + } + + void MediaSetAccess::dirInfo( filesystem::DirContent &retlist, const Pathname &dirname, + bool dots, unsigned media_nr ) + { + media::MediaManager media_mgr; + media::MediaAccessId media = getMediaAccessId(media_nr); + + // try to attach the media + if ( ! media_mgr.isAttached(media) ) + media_mgr.attach(media); + + media_mgr.dirInfo(media, retlist, dirname, dots); + } + + struct ProvideFileOperation + { + Pathname result; + void operator()( media::MediaAccessId media, const OnMediaLocation &file ) + { + media::MediaManager media_mgr; + media_mgr.provideFile( media, file ); + result = media_mgr.localPath( media, file.filename() ); + } + }; + + struct ProvideDirTreeOperation + { + Pathname result; + void operator()( media::MediaAccessId media, const OnMediaLocation &file ) + { + const auto &fName = file.filename(); + media::MediaManager media_mgr; + media_mgr.provideDirTree( media, fName ); + result = media_mgr.localPath( media, fName ); + } + }; + + struct ProvideDirOperation + { + Pathname result; + void operator()( media::MediaAccessId media, const OnMediaLocation &file ) + { + const auto &fName = file.filename(); + media::MediaManager media_mgr; + media_mgr.provideDir( media, fName ); + result = media_mgr.localPath( media, fName ); + } + }; + + struct ProvideFileExistenceOperation + { + bool result; + ProvideFileExistenceOperation() + : result(false) + {} + + void operator()( media::MediaAccessId media, const OnMediaLocation &file ) + { + const auto &fName = file.filename(); + media::MediaManager media_mgr; + result = media_mgr.doesFileExist( media, fName ); + } + }; + + Pathname MediaSetAccess::provideFile( const OnMediaLocation &resource, ProvideFileOptions options ) + { + ProvideFileOperation op; + provide( std::ref(op), resource, options ); + return op.result; + } + + Pathname MediaSetAccess::provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile ) + { + return provideFile( OnMediaLocation( resource ).setDeltafile( deltafile ), options ); + } + + Pathname MediaSetAccess::provideFile(const Pathname & file, unsigned media_nr, ProvideFileOptions options ) + { + return provideFile( OnMediaLocation( file, media_nr ), options ); + } + + Pathname MediaSetAccess::provideOptionalFile( const Pathname & file, unsigned media_nr ) + { + try + { + return provideFile( OnMediaLocation( file, media_nr ).setOptional( true ), PROVIDE_NON_INTERACTIVE ); + } + catch ( const media::MediaFileNotFoundException & excpt_r ) + { ZYPP_CAUGHT( excpt_r ); } + catch ( const media::MediaForbiddenException & excpt_r ) + { ZYPP_CAUGHT( excpt_r ); } + catch ( const media::MediaNotAFileException & excpt_r ) + { ZYPP_CAUGHT( excpt_r ); } + return Pathname(); + } + + ManagedFile MediaSetAccess::provideFileFromUrl(const Url &file_url, ProvideFileOptions options) + { + Url url(file_url); + Pathname path(url.getPathName()); + + url.setPathName ("/"); + MediaSetAccess access(url); + + ManagedFile tmpFile = filesystem::TmpFile::asManagedFile(); + + bool optional = options & PROVIDE_NON_INTERACTIVE; + Pathname file = access.provideFile( OnMediaLocation(path, 1).setOptional( optional ), options ); + + //prevent the file from being deleted when MediaSetAccess gets out of scope + if ( filesystem::hardlinkCopy(file, tmpFile) != 0 ) + ZYPP_THROW(Exception("Can't copy file from " + file.asString() + " to " + tmpFile->asString() )); + + return tmpFile; + } + + ManagedFile MediaSetAccess::provideOptionalFileFromUrl( const Url & file_url ) + { + try + { + return provideFileFromUrl( file_url, PROVIDE_NON_INTERACTIVE ); + } + catch ( const media::MediaFileNotFoundException & excpt_r ) + { ZYPP_CAUGHT( excpt_r ); } + catch ( const media::MediaNotAFileException & excpt_r ) + { ZYPP_CAUGHT( excpt_r ); } + return ManagedFile(); + } + + bool MediaSetAccess::doesFileExist(const Pathname & file, unsigned media_nr ) + { + ProvideFileExistenceOperation op; + OnMediaLocation resource(file, media_nr); + provide( std::ref(op), resource, PROVIDE_DEFAULT ); + return op.result; + } + + void MediaSetAccess::precacheFiles(const std::vector &files) + { + media::MediaManager media_mgr; + + for ( const auto &resource : files ) { + unsigned media_nr(resource.medianr()); + media::MediaAccessId media = getMediaAccessId( media_nr ); + + if ( !media_mgr.isOpen( media ) ) { + MIL << "Skipping precache of file " << resource.filename() << " media is not open"; + continue; + } + + if ( ! media_mgr.isAttached(media) ) + media_mgr.attach(media); + + media_mgr.precacheFiles( media, { resource } ); + } + } + + void MediaSetAccess::provide( const ProvideOperation& op, + const OnMediaLocation &resource, + ProvideFileOptions options ) + { + const auto &file(resource.filename()); + unsigned media_nr(resource.medianr()); + + callback::SendReport report; + media::MediaManager media_mgr; + + media::MediaAccessId media = 0; + + do + { + // get the mediaId, but don't try to attach it here + media = getMediaAccessId( media_nr); + + try + { + DBG << "Going to try to provide " << (resource.optional() ? "optional" : "") << " file " << file + << " from media number " << media_nr << endl; + // try to attach the media + if ( ! media_mgr.isAttached(media) ) + media_mgr.attach(media); + op(media, resource); + break; + } + catch ( media::MediaException & excp ) + { + ZYPP_CAUGHT(excp); + media::MediaChangeReport::Action user = media::MediaChangeReport::ABORT; + unsigned int devindex = 0; + std::vector devices; + media_mgr.getDetectedDevices(media, devices, devindex); + + do + { + // set up the reason + media::MediaChangeReport::Error reason = media::MediaChangeReport::INVALID; + + if( typeid(excp) == typeid( media::MediaFileNotFoundException ) || + typeid(excp) == typeid( media::MediaNotAFileException ) ) + { + reason = media::MediaChangeReport::NOT_FOUND; + } + else if( typeid(excp) == typeid( media::MediaNotDesiredException) || + typeid(excp) == typeid( media::MediaNotAttachedException) ) + { + reason = media::MediaChangeReport::WRONG; + } + else if( typeid(excp) == typeid( media::MediaTimeoutException) || + typeid(excp) == typeid( media::MediaTemporaryProblemException)) + { + reason = media::MediaChangeReport::IO_SOFT; + } + + // Propagate the original error if _no_ callback receiver is connected, or + // non_interactive mode (for optional files) is used (except for wrong media). + if ( ! callback::SendReport::connected() + || (( options & PROVIDE_NON_INTERACTIVE ) && reason != media::MediaChangeReport::WRONG ) ) + { + MIL << "Can't provide file. Non-Interactive mode." << endl; + ZYPP_RETHROW(excp); + } + else + { + // release all media before requesting another (#336881) + media_mgr.releaseAll(); + + user = report->requestMedia ( + _url, + media_nr, + _label, + reason, + excp.asUserHistory(), + devices, + devindex + ); + } + + MIL << "ProvideFile exception caught, callback answer: " << user << endl; + + if( user == media::MediaChangeReport::ABORT ) + { + DBG << "Aborting" << endl; + AbortRequestException aexcp("Aborting requested by user"); + aexcp.remember(excp); + ZYPP_THROW(aexcp); + } + else if ( user == media::MediaChangeReport::IGNORE ) + { + DBG << "Skipping" << endl; + SkipRequestException nexcp("User-requested skipping of a file"); + nexcp.remember(excp); + ZYPP_THROW(nexcp); + } + else if ( user == media::MediaChangeReport::EJECT ) + { + DBG << "Eject: try to release" << endl; + try + { + media_mgr.releaseAll(); + media_mgr.release (media, devindex < devices.size() ? devices[devindex] : ""); + } + catch ( const Exception & e) + { + ZYPP_CAUGHT(e); + } + } + else if ( user == media::MediaChangeReport::RETRY || + user == media::MediaChangeReport::CHANGE_URL ) + { + // retry + DBG << "Going to try again" << endl; + // invalidate current media access id + media_mgr.close(media); + _medias.erase(media_nr); + + // not attaching, media set will do that for us + // this could generate uncaught exception (#158620) + break; + } + else + { + DBG << "Don't know, let's ABORT" << endl; + ZYPP_RETHROW ( excp ); + } + } while( user == media::MediaChangeReport::EJECT ); + } + + // retry or change URL + } while( true ); + } + + Pathname MediaSetAccess::provideDir(const Pathname & dir, + bool recursive, + unsigned media_nr, + ProvideFileOptions options ) + { + OnMediaLocation resource(dir, media_nr); + if ( recursive ) + { + ProvideDirTreeOperation op; + provide( std::ref(op), resource, options ); + return op.result; + } + ProvideDirOperation op; + provide( std::ref(op), resource, options ); + return op.result; + } + + media::MediaAccessId MediaSetAccess::getMediaAccessId (media::MediaNr medianr) + { + if ( _medias.find( medianr ) != _medias.end() ) + { + return _medias[medianr]; + } + + Url url( medianr > 1 ? rewriteUrl( _url, medianr ) : _url ); + media::MediaManager media_mgr; + media::MediaAccessId id = media_mgr.open( url, _prefAttachPoint ); + _medias[medianr] = id; + + try + { + if ( _verifiers.find(medianr) != _verifiers.end() ) + { + // a verifier is set for this media + // FIXME check the case where the verifier exists + // but we have no access id for the media + media_mgr.delVerifier( id ); + media_mgr.addVerifier( id, _verifiers[medianr] ); + // remove any saved verifier for this media + _verifiers.erase( medianr ); + } + } + catch ( const Exception &e ) + { + ZYPP_CAUGHT(e); + WAR << "Verifier not found" << endl; + } + + return id; + } + + + Url MediaSetAccess::rewriteUrl (const Url & url_r, const media::MediaNr medianr) + { + std::string scheme = url_r.getScheme(); + if (scheme == "cd" || scheme == "dvd") + return url_r; + + DBG << "Rewriting url " << url_r << endl; + + if( scheme == "iso") + { + // TODO the iso parameter will not be required in the future, this + // code has to be adapted together with the MediaISO change. + // maybe some MediaISOURL interface should be used. + std::string isofile = url_r.getQueryParam("iso"); + str::regex e("^(.*)(cd|dvd|media)[0-9]+\\.iso$", str::regex::icase); + + str::smatch what; + if(str::regex_match(isofile, what, e)) + { + Url url( url_r); + isofile = what[1] + what[2] + str::numstring(medianr) + ".iso"; + url.setQueryParam("iso", isofile); + DBG << "Url rewrite result: " << url << endl; + return url; + } + } + else + { + std::string pathname = url_r.getPathName(); + str::regex e("^(.*)(cd|dvd|media)[0-9]+(/)?$", str::regex::icase); + str::smatch what; + if(str::regex_match(pathname, what, e)) + { + Url url( url_r); + pathname = what[1] + what[2] + str::numstring(medianr) + what[3]; + url.setPathName(pathname); + DBG << "Url rewrite result: " << url << endl; + return url; + } + } + return url_r; + } + + void MediaSetAccess::release() + { + DBG << "Releasing all media IDs held by this MediaSetAccess" << endl; + media::MediaManager manager; + for (MediaMap::const_iterator m = _medias.begin(); m != _medias.end(); ++m) + manager.release(m->second, ""); + } + + std::ostream & MediaSetAccess::dumpOn( std::ostream & str ) const + { + str << "MediaSetAccess (URL='" << _url << "', attach_point_hint='" << _prefAttachPoint << "')"; + return str; + } + +///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/MediaSetAccess.h b/zypp/MediaSetAccess.h new file mode 100644 index 0000000..3146296 --- /dev/null +++ b/zypp/MediaSetAccess.h @@ -0,0 +1,398 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_MediaSetAccess_H +#define ZYPP_MediaSetAccess_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(MediaSetAccess); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaSetAccess + // + /** + * Media access layer responsible for handling files distributed on a set + * of media with media change and abort/retry/ingore user callback handling. + * + * This is provided as a means to handle CD or DVD sets accessible through + * dir, iso, nfs or other URL schemes other than cd/dvd (see + * \ref MediaManager for info on different implemented media backends). + * Currently it handles URLs ending on (case insensitive ) CD#, DVD# or MEDIA#, + * where # is the number of a particular medium in the set. + * + * Examples: + * \code + * "iso:/?iso=/path/to/iso/images/openSUSE-10.3-Alpha2plus-DVD-x86_64-DVD1.iso" + * "dir:/path/to/cdset/sources/openSUSE-10.3/Alpha2plus/CD1" + * \endcode + * + * MediaSetAccess accesses files on the desired medium by rewriting + * the original URL, replacing the digit (usually) 1 with requested media + * number and uses \ref MediaManager to get the files from the new URL. + * + * NOTE: Access to medium #1 always uses the url passed to the CTOR! + * + * Additionaly, each media number can be assinged a media verifier which + * checks if the media we are trying to access is the desired one. See + * \ref MediaVerifierBase for more info. + * + * Code example: + * \code + * Url url("dir:/path/to/cdset/sources/openSUSE-10.3/Alpha2plus/CD1"); + * + * MediaSetAccess access(url); + * + * access.setVerifier(1, media1VerifierRef); + * access.setVerifier(2, media2VerifierRef); + * + * Pathname file1 = "/some/file/on/media1"; + * Pathname providedfile1 = access.provideFile(file1, 1); + * Pathname file2 = "/some/file/on/media2"; + * Pathname providedfile2 = access.provideFile(file1, 2); + * + * \endcode + */ + class ZYPP_API MediaSetAccess : public base::ReferenceCounted, private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const MediaSetAccess & obj ); + + public: + /** + * Creates a callback enabled media access for specified \a url. + * + * \param url + * \param prefered_attach_point Prefered attach (mount) point. Use, if + * you want to mount the media to a specific directory. + */ + MediaSetAccess( Url url, Pathname prefered_attach_point = "" ); + /** \overload Also taking a \ref label. */ + MediaSetAccess( std::string label_r, Url url, Pathname prefered_attach_point = "" ); + ~MediaSetAccess() override; + + /** + * Sets a \ref MediaVerifier verifier for given media number. + */ + void setVerifier( unsigned media_nr, const media::MediaVerifierRef& verifier ); + + /** + * The label identifing this media set and to be sent in a media change request. + */ + const std::string & label() const + { return _label; } + + /** + * Set the label identifing this media set and to be sent in a media change request. + */ + void setLabel( const std::string & label_r ) + { _label = label_r; } + + enum ProvideFileOption + { + /** + * The user is not asked anything, and the error + * exception is just propagated */ + PROVIDE_DEFAULT = 0x0, + PROVIDE_NON_INTERACTIVE = 0x1 + }; + ZYPP_DECLARE_FLAGS(ProvideFileOptions,ProvideFileOption); + + /** + * Tries to fetch the given files and precaches them. Those files + * need to be queried using provideFile and can be read from the cache directly. + * The implementation is not allowed to block but needs to use seperate means to + * download the files concurrently. + * A backend can choose to completely ignore this functionaly, the default implementation + * does nothing. + * + * \param files List of files that should be precached + */ + void precacheFiles(const std::vector &files); + + /** + * Provides a file from a media location. + * + * \param resource location of the file on media + * \return local pathname of the requested file + * + * \throws MediaException if a problem occured and user has chosen to + * abort the operation. The calling code should take care + * to quit the current operation. + * \throws SkipRequestException if a problem occured and user has chosen + * to skip the current operation. The calling code should continue + * with the next one, if possible. + * + * + * If the resource is marked as optional, no Exception is thrown + * and Pathname() is returned + * + * the optional deltafile argument describes a file that can + * be used for delta download algorithms. + * + * \note interaction with the user does not ocurr if + * \ref ProvideFileOptions::NON_INTERACTIVE is set. + * + * \note OnMediaLocation::optional() hint has no effect on the transfer. + * + * \see zypp::media::MediaManager::provideFile() + */ + Pathname provideFile( const OnMediaLocation & resource, ProvideFileOptions options = PROVIDE_DEFAULT ); + + /** + * \deprecated The deltafile argument is part of the OnMediaLocation now, use the version of \ref provideFile( const OnMediaLocation & resource, ProvideFileOptions options ) + */ + ZYPP_DEPRECATED Pathname provideFile( const OnMediaLocation & resource, ProvideFileOptions options, const Pathname &deltafile ); + + /** + * Provides \a file from media \a media_nr. + * + * \param file path to the file relative to media URL + * \param media_nr the media number in the media set + * \return local pathname of the requested file + * + * \note interaction with the user does not ocurr if + * \ref ProvideFileOptions::NON_INTERACTIVE is set. + * + * \note OnMediaLocation::optional() hint has no effect on the transfer. + * + * \throws MediaException if a problem occured and user has chosen to + * abort the operation. The calling code should take care + * to quit the current operation. + * \throws SkipRequestException if a problem occured and user has chosen + * to skip the current operation. The calling code should continue + * with the next one, if possible. + * \see zypp::media::MediaManager::provideFile() + */ + Pathname provideFile(const Pathname & file, unsigned media_nr = 1, ProvideFileOptions options = PROVIDE_DEFAULT ); + + /** + * Provides an optional \a file from media \a media_nr. + * + * Like \ref provideFile (NON_INTERACTIVE), but return an empty \ref Pathname + * rather than throwing a \ref MediaException if the file is not present on + * the media. + */ + Pathname provideOptionalFile( const Pathname & file, unsigned media_nr = 1 ); + + /** + * Provides \a file from \a url. + * + * \param absolute url to the file + * \return local pathname of the requested file + * + * \note interaction with the user does not ocurr if + * \ref ProvideFileOptions::NON_INTERACTIVE is set. + * + * \throws MediaException if a problem occured and user has chosen to + * abort the operation. The calling code should take care + * to quit the current operation. + * \throws SkipRequestException if a problem occured and user has chosen + * to skip the current operation. The calling code should continue + * with the next one, if possible. + * \see zypp::media::MediaManager::provideFile() + */ + static ManagedFile provideFileFromUrl( const Url & file_url, ProvideFileOptions options = PROVIDE_DEFAULT ); + + /** + * Provides an optional \a file from \a url. + * + * Like \ref provideFileFromUrl( NON_INTERACTIVE ), but return an empty \ref Pathname + * rather than throwing a \ref MediaException if the file is not present on + * the media. + */ + static ManagedFile provideOptionalFileFromUrl( const Url & file_url ); + + /** + * Release file from media. + * This signal that file is not needed anymore. + * + * \param resource location of the file on media + */ + void releaseFile( const OnMediaLocation &resource ); + + + /** + * Release file from media. + * This signal that file is not needed anymore. + * + * \param file path to the file relative to media URL + * \param media_nr the media number in the media set + */ + void releaseFile(const Pathname & file, unsigned media_nr = 1 ); + + /////////////////////////////////////////////////////////////////// + /// \class MediaSetAccess::ReleaseFileGuard + /// \brief Release a provided file upon destruction. + /// In case you don't want to wait until the \ref MediaSetAccess + /// itself goes out of scope. + /// \code + /// MediaSetAccess media; + /// OnMediaLocation loc; + /// { + /// Pathname file = media.provideFile( loc ); + /// ReleaseFileGuard guard( media, loc ); + /// } // provided file is released here. + /// \endcode + /// \ingroup g_RAII + /////////////////////////////////////////////////////////////////// + struct ReleaseFileGuard + { + NON_COPYABLE( ReleaseFileGuard ); + NON_MOVABLE( ReleaseFileGuard ); + ReleaseFileGuard( MediaSetAccess & media_r, const OnMediaLocation & loc_r ) + : _media( media_r ) + , _loc( loc_r ) + {} + ~ReleaseFileGuard() + { _media.releaseFile( _loc ); } + private: + MediaSetAccess & _media; + const OnMediaLocation & _loc; + }; + + /** + * Provides direcotry \a dir from media number \a media_nr. + * + * \param dir path to the directory relative to media URL + * \param recursive whether to provide the whole directory subtree + * \param media_nr the media number in the media set + * \return local pathname of the requested directory + * + * \throws MediaException if a problem occured and user has chosen to + * abort the operation. The calling code should take care + * to quit the current operation. + * \todo throw SkipRequestException if a problem occured and user has chosen + * to skip the current operation. The calling code should continue + * with the next one, if possible. + * \see zypp::media::MediaManager::provideDir() + * \see zypp::media::MediaManager::provideDirTree() + */ + Pathname provideDir(const Pathname & dir, bool recursive, unsigned media_nr = 1, ProvideFileOptions options = PROVIDE_DEFAULT ); + + /** + * Checks if a file exists on the specified media, with user callbacks. + * + * \param file file to check + * \param media_nr Media number + * + * \throws MediaException if a problem occured and user has chosen to + * abort the operation. The calling code should take care + * to quit the current operation. + * \throws SkipRequestException if a problem occured and user has chosen + * to skip the current operation. The calling code should continue + * with the next one, if possible. + * \see zypp::media::MediaManager::doesFileExist(MediaAccessId,const Pathname&) + */ + bool doesFileExist(const Pathname & file, unsigned media_nr = 1 ); + + /** + * Fills \ref retlist with directory information. + */ + void dirInfo( filesystem::DirContent &retlist, const Pathname &dirname, + bool dots = true, unsigned media_nr = 1 ); + + /** + * Release all attached media of this set. + * + * \throws MediaNotOpenException for invalid access IDs. + */ + void release(); + + /** + * Replaces media number in specified url with given \a medianr. + * + * Media number in the URL is searched for with regex + * "^(.*(cd|dvd|media))([0-9]+)(\\.iso)$" for iso scheme and + * with "^(.*(cd|dvd|media))([0-9]+)(/?)$" for other schemes. + * + * For cd and dvd scheme it returns the original URL, as well as for + * URL which do not match the above regexes. + * + * \param url_r original URL + * \param medianr requested media number + * \return rewritten URL if applicable, the original URL otherwise + */ + static Url rewriteUrl (const Url & url_r, const media::MediaNr medianr); + + protected: + /** + * Provides the \a file from medium number \a media_nr and returns its + * local path. + * + * \note The method must not throw if \a checkonly is true. + * + * \throws MediaException \a checkonly is false and + * a problem occured and user has chosen to + * abort the operation. The calling code should take care + * to quit the current operation. + * \throws SkipRequestException \a checkonly is false and + * a problem occured and user has chosen + * to skip the current operation. The calling code should continue + * with the next one, if possible. + */ + Pathname provideFileInternal( const OnMediaLocation &resource, ProvideFileOptions options ); + + using ProvideOperation = function; + + void provide( const ProvideOperation& op, const OnMediaLocation &resource, ProvideFileOptions options ); + + media::MediaAccessId getMediaAccessId (media::MediaNr medianr); + std::ostream & dumpOn( std::ostream & str ) const override; + + private: + /** Media or media set URL */ + Url _url; + + /** + * Prefered mount point. + * + * \see MediaManager::open(Url,Pathname) + * \see MediaHandler::_attachPoint + */ + Pathname _prefAttachPoint; + + std::string _label; + + using MediaMap = std::map; + using VerifierMap = std::map; + + /** Mapping between media number and Media Access ID */ + MediaMap _medias; + /** Mapping between media number and corespondent verifier */ + VerifierMap _verifiers; + }; + /////////////////////////////////////////////////////////////////// + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(MediaSetAccess::ProvideFileOptions); + + /** \relates MediaSetAccess Stream output */ + inline std::ostream & operator<<( std::ostream & str, const MediaSetAccess & obj ) + { return obj.dumpOn( str ); } + + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SOURCE_MediaSetAccess_H diff --git a/zypp/Misc.h b/zypp/Misc.h new file mode 100644 index 0000000..bf09a4a --- /dev/null +++ b/zypp/Misc.h @@ -0,0 +1,18 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Misc.h + * +*/ +#ifndef ZYPP_MISC_H +#define ZYPP_MISC_H + +#include +#include + +#endif // ZYPP_MISC_H diff --git a/zypp/OnMediaLocation.h b/zypp/OnMediaLocation.h new file mode 100644 index 0000000..643e274 --- /dev/null +++ b/zypp/OnMediaLocation.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Package.cc b/zypp/Package.cc new file mode 100644 index 0000000..c711610 --- /dev/null +++ b/zypp/Package.cc @@ -0,0 +1,305 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Package.cc + * +*/ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zyppintern +{ + using namespace zypp; + + /** getVendorSupportOption return value */ + using GetVendorSupportOptionReturn = std::pair>>; + + /** Get VendorSupportOption and the PKGNAME if VendorSupportSuperseded */ + GetVendorSupportOptionReturn getVendorSupportOption( sat::Solvable solv_r ) + { + static const IdString support_unsupported( "support_unsupported" ); + static const IdString support_acc( "support_acc" ); + static const IdString support_l1( "support_l1" ); + static const IdString support_l2( "support_l2" ); + static const IdString support_l3( "support_l3" ); + static const IdString support_superseded( "support_superseded" ); // opt. followed by "(PKGNAME)" + + GetVendorSupportOptionReturn ret { VendorSupportUnknown, std::nullopt }; + + // max over all identical packages + for ( const auto & solv : sat::WhatProvides( (Capability(solv_r.ident().id())) ) ) + { + if ( solv.edition() == solv_r.edition() + && solv.ident() == solv_r.ident() + && solv_r.identical( solv ) ) + { + for ( PackageKeyword kw : Package::Keywords( sat::SolvAttr::keywords, solv ) ) + { + switch ( ret.first ) + { + case VendorSupportUnknown: + if ( kw == support_unsupported ) { ret.first = VendorSupportUnsupported; break; } + case VendorSupportUnsupported: + if ( kw == support_acc ) { ret.first = VendorSupportACC; break; } + case VendorSupportACC: + if ( kw == support_l1 ) { ret.first = VendorSupportLevel1; break; } + case VendorSupportLevel1: + if ( kw == support_l2 ) { ret.first = VendorSupportLevel2; break; } + case VendorSupportLevel2: + if ( kw == support_l3 ) { ret.first = VendorSupportLevel3; break; } + case VendorSupportLevel3: + case VendorSupportSuperseded: + // VendorSupportSuperseded is special as the kw may also contain a '(PKGNAME)'. + // In fact even multiple (PKGNAMES) derived from multiple keywords. + if ( strv::hasPrefix( kw.asStringView(), support_superseded.asStringView() ) ) { + ret.first = VendorSupportSuperseded; + if ( kw.c_str()[support_superseded.size()] == '(' && kw.c_str()[kw.size()-1] == ')' ) { + std::string_view val { kw.c_str()+support_superseded.size()+1, kw.size()-support_superseded.size()-2 }; + if ( not val.empty() ) { + if ( not ret.second ) + ret.second = std::set(); + ret.second->insert( val ); + } else { + WAR << "No superseding package defined in " << kw << endl; + } + } else { + WAR << "No superseding package defined in " << kw << endl; + } + } + } + } + } + } + return ret; + } + + inline bool schemeIsLocalDir( const Url & url_r ) + { + const std::string & s( url_r.getScheme() ); + return s == "dir" || s == "file"; + } + + // here and from SrcPackage.cc + Pathname cachedLocation( const OnMediaLocation & loc_r, const RepoInfo & repo_r ) + { + PathInfo pi( repo_r.packagesPath() / repo_r.path() / loc_r.filename() ); + + if ( ! pi.isExist() ) + return Pathname(); // no file in cache + + if ( loc_r.checksum().empty() ) + { + Url url( repo_r.url() ); + if ( ! schemeIsLocalDir( url ) ) + return Pathname(); // same name but no checksum to verify + + // for local repos compare with the checksum in repo + if ( CheckSum( CheckSum::md5Type(), std::ifstream( (url.getPathName() / repo_r.path() / loc_r.filename()).c_str() ) ) + != CheckSum( CheckSum::md5Type(), std::ifstream( pi.c_str() ) ) ) + return Pathname(); // same name but wrong checksum + } + else + { + if ( loc_r.checksum() != CheckSum( loc_r.checksum().type(), std::ifstream( pi.c_str() ) ) ) + return Pathname(); // same name but wrong checksum + } + + return pi.path(); // the right one + } +} // namespace zyppintern +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(Package); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Package::Package + // METHOD TYPE : Ctor + // + Package::Package( const sat::Solvable & solvable_r ) + : ResObject( solvable_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Package::~Package + // METHOD TYPE : Dtor + // + Package::~Package() + {} + + VendorSupportOption Package::vendorSupport() const + { return zyppintern::getVendorSupportOption( satSolvable() ).first; } + + bool Package::maybeUnsupported() const + { + switch ( vendorSupport() ) + { + case VendorSupportUnknown: + case VendorSupportUnsupported: + case VendorSupportACC: + case VendorSupportSuperseded: + return true; + + case VendorSupportLevel1: + case VendorSupportLevel2: + case VendorSupportLevel3: + break; // intentionally no default: + } + return false; + } + + std::vector Package::supersededBy() const + { + std::vector ret; + const auto & res = zyppintern::getVendorSupportOption( satSolvable() ); + if ( res.second ) { + // translate the string_view set into stings + for ( const auto & v : *res.second ) + ret.push_back( std::string( v ) ); + } + return ret; + } + + + std::pair,std::vector> Package::supersededByItems() const + { + std::pair,std::vector> ret; + std::vector todo { supersededBy() }; + if ( not todo.empty() ) + { + std::set done; // taken from todo and processed + std::set unresolved; // supersededBy does not name a package + std::set resolved; // supersededBy resolved to package (not superseded) + while ( not todo.empty() ) { + auto doneit { done.insert( std::move(todo.back()) ) }; + todo.pop_back(); + if ( not doneit.second ) + continue; // already processed + const std::string & next { *doneit.first }; + + if ( auto sel = ui::Selectable::get( next ) ) { + const std::vector & more { sel->supersededBy() }; + if ( more.empty() ) { + resolved.insert( sel->ident() ); + } else { + todo.insert( todo.end(), more.begin(), more.end() ); + } + } else { + unresolved.insert( next ); + } + } + if ( not resolved.empty() ) + ret.first.insert( ret.first.end(), resolved.begin(), resolved.end() ); + if ( not unresolved.empty() ) + ret.second.insert( ret.second.end(), unresolved.begin(), unresolved.end() ); + } + return ret; + } + + Changelog Package::changelog() const + { + Target_Ptr target( getZYpp()->getTarget() ); + if ( ! target ) + { + ERR << "Target not initialized. Changelog is not available." << std::endl; + return Changelog(); + } + + if ( repository().isSystemRepo() ) + { + target::rpm::RpmHeader::constPtr header; + target->rpmDb().getData(name(), header); + return header ? header->tag_changelog() : Changelog(); // might be deleted behind our back (bnc #530595) + } + WAR << "changelog is not available for uninstalled packages" << std::endl; + return Changelog(); + } + + std::string Package::buildhost() const + { return lookupStrAttribute( sat::SolvAttr::buildhost ); } + + std::string Package::distribution() const + { return lookupStrAttribute( sat::SolvAttr::distribution ); } + + std::string Package::license() const + { return lookupStrAttribute( sat::SolvAttr::license ); } + + std::string Package::packager() const + { return lookupStrAttribute( sat::SolvAttr::packager ); } + + std::string Package::group() const + { return lookupStrAttribute( sat::SolvAttr::group ); } + + Package::Keywords Package::keywords() const + { return Keywords( sat::SolvAttr::keywords, satSolvable() ); } + + std::string Package::url() const + { return lookupStrAttribute( sat::SolvAttr::url ); } + + ByteCount Package::sourcesize() const + { return lookupNumAttribute( sat::SolvAttr::sourcesize ); } + + std::list Package::authors() const + { + std::list ret; + str::split( lookupStrAttribute( sat::SolvAttr::authors ), std::back_inserter(ret), "\n" ); + return ret; + } + + Package::FileList Package::filelist() const + { return FileList( sat::SolvAttr::filelist, satSolvable() ); } + + CheckSum Package::checksum() const + { return lookupCheckSumAttribute( sat::SolvAttr::checksum ); } + + OnMediaLocation Package::location() const + { return lookupLocation(); } + + Pathname Package::cachedLocation() const + { return zyppintern::cachedLocation( location(), repoInfo() ); } + + std::string Package::sourcePkgName() const + { + // no id means same as package + sat::detail::IdType id( lookupIdAttribute( sat::SolvAttr::sourcename ) ); + return id ? IdString( id ).asString() : name(); + } + + Edition Package::sourcePkgEdition() const + { + // no id means same as package + sat::detail::IdType id( lookupIdAttribute( sat::SolvAttr::sourceevr ) ); + return id ? Edition( id ) : edition(); + } + + std::string Package::sourcePkgType() const + { return lookupStrAttribute( sat::SolvAttr::sourcearch ); } + + std::string Package::sourcePkgLongName() const + { return str::form( "%s-%s.%s", sourcePkgName().c_str(), sourcePkgEdition().c_str(), sourcePkgType().c_str() ); } + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Package.h b/zypp/Package.h new file mode 100644 index 0000000..c27b22b --- /dev/null +++ b/zypp/Package.h @@ -0,0 +1,167 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Package.h + * +*/ +#ifndef ZYPP_PACKAGE_H +#define ZYPP_PACKAGE_H + +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(Package); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Package + // + /** Package interface. + */ + class ZYPP_API Package : public ResObject + { + public: + using Self = Package; + using TraitsType = ResTraits; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + using Keywords = sat::ArrayAttr; + using FileList = sat::ArrayAttr; + + public: + + /** + * Returns the level of supportability the vendor + * gives to this package. + * + * If the identical package happens to appear in multiple + * repos with different support levels, the maximum + * level is returned. + * + * This is one value from \ref VendorSupportOption. + */ + VendorSupportOption vendorSupport() const; + + /** + * True if the vendor support for this package + * is unknown or explicitly unsupported. + */ + bool maybeUnsupported() const; + + /** The name(s) of the successor package if \ref vendorSupport is \ref VendorSupportSuperseded. + * Ideally only one name, but it might be that different repos + * provide different successor names. These are the pure metadata + * values. \see \ref supersededByItems and \ref ui::Selectable::supersededBy + */ + std::vector supersededBy() const; + + /** The successor package(s) if \ref vendorSupport is \ref VendorSupportSuperseded. + * Each name returned by \ref supersededBy is resolved into the + * \ref Solvable::ident of an Item in the pool (collapsing chains + * of superseeded packages). + * + * The std::pair returned contains the IdString idents of superseeding packages and + * any std::strings which could not be resolved into a package name. + * + * Ideally you get back one IdString and no unresolved names. Multiple IdStrings + * express a choice. Unresolved names hint to broken repo metadata, as superseeding + * packages should be available in the repo. + */ + std::pair,std::vector> supersededByItems() const; + + /** Get the package change log */ + Changelog changelog() const; + /** */ + std::string buildhost() const; + /** */ + std::string distribution() const; + /** */ + std::string license() const; + /** */ + std::string packager() const; + /** */ + std::string group() const; + /** */ + Keywords keywords() const; + /** Don't ship it as class Url, because it might be + * in fact anything but a legal Url. */ + std::string url() const; + /** Size of corresponding the source package. */ + ByteCount sourcesize() const; + /** */ + std::list authors() const; + + /** Return the packages filelist (if available). + * The returned \ref FileList appears to be a container of + * \c std::string. In fact it is a query, so it does not + * consume much memory. + */ + FileList filelist() const; + + /** \name Source package handling + */ + //@{ + /** Name of the source rpm this package was built from. + */ + std::string sourcePkgName() const; + + /** Edition of the source rpm this package was built from. + */ + Edition sourcePkgEdition() const; + + /** The type of the source rpm (\c "src" or \c "nosrc"). + */ + std::string sourcePkgType() const; + + /** The source rpms \c "name-version-release.type" + */ + std::string sourcePkgLongName() const; + //@} + + /** + * Checksum the source says this package should have. + * \see \ref location + */ + CheckSum checksum() const; + + /** Location of the resolvable in the repository. + * \ref OnMediaLocation conatins all information required to + * retrieve the packge (url, checksum, etc.). + */ + OnMediaLocation location() const; + + /** Location of the downloaded package in cache or an empty path. */ + Pathname cachedLocation() const; + + /** Whether the package is cached. */ + bool isCached() const + { return ! cachedLocation().empty(); } + + protected: + friend Ptr make( const sat::Solvable & solvable_r ); + /** Ctor */ + Package( const sat::Solvable & solvable_r ); + /** Dtor */ + ~Package() override; + }; + + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PACKAGE_H diff --git a/zypp/PackageKeyword.h b/zypp/PackageKeyword.h new file mode 100644 index 0000000..94f072e --- /dev/null +++ b/zypp/PackageKeyword.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PackageKeyword.h + * +*/ +#ifndef ZYPP_PACKAGEKEYWORD_H +#define ZYPP_PACKAGEKEYWORD_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PackageKeyword + // + /** Package keywords. + * \see \ref IdStringType + */ + class PackageKeyword : public IdStringType + { + public: + /** Default ctor: empty keyword */ + PackageKeyword() {} + + /** Ctor taking keyword as string. */ + explicit PackageKeyword( sat::detail::IdType id_r ) : _str( id_r ) {} + explicit PackageKeyword( const IdString & idstr_r ) : _str( idstr_r ) {} + explicit PackageKeyword( const std::string & str_r ) : _str( str_r ) {} + explicit PackageKeyword( const char * cstr_r ) : _str( cstr_r ) {} + + private: + friend class IdStringType; + IdString _str; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PACKAGEKEYWORD_H diff --git a/zypp/Patch.cc b/zypp/Patch.cc new file mode 100644 index 0000000..be00617 --- /dev/null +++ b/zypp/Patch.cc @@ -0,0 +1,353 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Patch.cc + * +*/ +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE( Patch ); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Patch::Patch + // METHOD TYPE : Ctor + // + Patch::Patch( const sat::Solvable & solvable_r ) + : ResObject( solvable_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Patch::~Patch + // METHOD TYPE : Dtor + // + Patch::~Patch() + {} + + /////////////////////////////////////////////////////////////////// + + std::string Patch::category() const + { return str::toLower(lookupStrAttribute( sat::SolvAttr::patchcategory )); } + + Patch::Category Patch::categoryEnum() const + { return categoryEnum( category() ); } + + bool Patch::isCategory( const std::string & category_r ) const + { + // bsc#1179847: identify the wellknown categories + Category catenum = categoryEnum( category_r ); + return ( catenum == CAT_OTHER && str::compareCI( category_r, category() ) == 0 ) + || ( catenum == categoryEnum() ); + } + + bool Patch::isCategory( Categories category_r ) const + { return category_r.testFlag( categoryEnum() ); } + + Patch::Category Patch::categoryEnum( const std::string & category_r ) + { + switch ( category_r[0] ) + { + // CAT_YAST + case 'y': + case 'Y': + if ( str::compareCI( category_r, "yast" ) == 0 ) + return CAT_YAST; + break; + + // CAT_SECURITY + case 's': + case 'S': + if ( str::compareCI( category_r, "security" ) == 0 ) + return CAT_SECURITY; + break; + + // CAT_RECOMMENDED + case 'r': + case 'R': + if ( str::compareCI( category_r, "recommended" ) == 0 ) + return CAT_RECOMMENDED; + break; + case 'b': + case 'B': + if ( str::compareCI( category_r, "bugfix" ) == 0 ) // rhn + return CAT_RECOMMENDED; + break; + + // CAT_OPTIONAL + case 'o': + case 'O': + if ( str::compareCI( category_r, "optional" ) == 0 ) + return CAT_OPTIONAL; + break; + case 'f': + case 'F': + if ( str::compareCI( category_r, "feature" ) == 0 ) + return CAT_OPTIONAL; + break; + case 'e': + case 'E': + if ( str::compareCI( category_r, "enhancement" ) == 0 ) // rhn + return CAT_OPTIONAL; + break; + + // CAT_DOCUMENT + case 'd': + case 'D': + if ( str::compareCI( category_r, "document" ) == 0 ) + return CAT_DOCUMENT; + break; + } + // default: + INT << "Unrecognized Patch::Category string '" << category_r << "'" << endl; + return CAT_OTHER; + } + + std::string asString( const Patch::Category & obj ) + { + switch ( obj ) + { + case Patch::CAT_OTHER: return std::string( "other" ); break; + case Patch::CAT_YAST: return std::string( "yast" ); break; + case Patch::CAT_SECURITY: return std::string( "security" ); break; + case Patch::CAT_RECOMMENDED: return std::string( "recommended" ); break; + case Patch::CAT_OPTIONAL: return std::string( "optional" ); break; + case Patch::CAT_DOCUMENT: return std::string( "document" ); break; + } + // make gcc happy: + return std::string( "other" ); + } + + /////////////////////////////////////////////////////////////////// + + std::string Patch::severity() const + { return str::toLower(lookupStrAttribute( sat::SolvAttr::severity )); } + + Patch::SeverityFlag Patch::severityFlag() const + { return severityFlag( severity() ); } + + bool Patch::isSeverity( const std::string & severity_r ) const + { return( str::compareCI( severity_r, severity() ) == 0 ); } + + bool Patch::isSeverity( SeverityFlags severity_r ) const + { return severity_r.testFlag( severityFlag() ); } + + Patch::SeverityFlag Patch::severityFlag( const std::string & severity_r ) + { + switch ( severity_r[0] ) + { + case 'l': + case 'L': + if ( str::compareCI( severity_r, "low" ) == 0 ) + return SEV_LOW; + break; + + case 'm': + case 'M': + if ( str::compareCI( severity_r, "moderate" ) == 0 ) + return SEV_MODERATE; + break; + + case 'i': + case 'I': + if ( str::compareCI( severity_r, "important" ) == 0 ) + return SEV_IMPORTANT; + break; + + case 'c': + case 'C': + if ( str::compareCI( severity_r, "critical" ) == 0 ) + return SEV_CRITICAL; + break; + + case 'u': + case 'U': + if ( str::compareCI( severity_r, "unspecified" ) == 0 ) + return SEV_NONE; + break; + + case '\0': + return SEV_NONE; + break; + } + // default: + INT << "Unrecognized Patch::Severity string '" << severity_r << "'" << endl; + return SEV_OTHER; + } + + std::string asString( const Patch::SeverityFlag & obj ) + { + switch ( obj ) + { + case Patch::SEV_OTHER: return std::string( "unknown" ); break; + case Patch::SEV_NONE: return std::string( "unspecified" ); break; + case Patch::SEV_LOW: return std::string( "low" ); break; + case Patch::SEV_MODERATE: return std::string( "moderate" ); break; + case Patch::SEV_IMPORTANT:return std::string( "important" ); break; + case Patch::SEV_CRITICAL: return std::string( "critical" ); break; + } + // make gcc happy: + return std::string( "unknown" ); + } + + /////////////////////////////////////////////////////////////////// + // +std::string Patch::message( const Locale & lang_r ) const + { return lookupStrAttribute( sat::SolvAttr::message, lang_r ); } + + bool Patch::rebootSuggested() const + { return lookupBoolAttribute( sat::SolvAttr::rebootSuggested ); } + + bool Patch::restartSuggested() const + { return lookupBoolAttribute( sat::SolvAttr::restartSuggested ); } + + bool Patch::reloginSuggested() const + { return lookupBoolAttribute( sat::SolvAttr::reloginSuggested ); } + + Patch::InteractiveFlags Patch::interactiveFlags() const + { + InteractiveFlags patchFlags (NoFlags); + if ( rebootSuggested() ) + patchFlags |= Reboot; + + if ( ! message().empty() ) + patchFlags |= Message; + + if ( ! licenseToConfirm().empty() ) + patchFlags |= License; + + Patch::Contents c( contents() ); + for_( it, c.begin(), c.end() ) + { + if ( ! makeResObject(*it)->licenseToConfirm().empty() ) + { + patchFlags |= License; + break; + } + } + return patchFlags; + } + + bool Patch::interactiveWhenIgnoring( InteractiveFlags flags_r ) const + { + if ( interactiveFlags() & ( ~flags_r ) ) + { + return true; + } + else + { + return false; + } + } + + bool Patch::interactive() const + { + return interactiveWhenIgnoring(); + } + + std::string asString( const Patch::InteractiveFlag & obj ) + { + switch ( obj ) + { + case Patch::NoFlags: return ""; break; + case Patch::Reboot: return "reboot"; break; + case Patch::Message: return "message"; break; + case Patch::License: return "license"; break; + } + return str::hexstring(obj); + } + + Patch::Contents Patch::contents() const + { + Contents result; + // DBG << *this << endl; + sat::LookupAttr updateCollection( sat::SolvAttr::updateCollection, satSolvable() ); + for_( entry, updateCollection.begin(), updateCollection.end() ) + { + IdString name ( entry.subFind( sat::SolvAttr::updateCollectionName ).idStr() ); + Edition edition ( entry.subFind( sat::SolvAttr::updateCollectionEvr ).idStr() ); + Arch arch ( entry.subFind( sat::SolvAttr::updateCollectionArch ).idStr() ); + if ( name.empty() ) + { + WAR << "Ignore malformed updateCollection entry: " << name << "-" << edition << "." << arch << endl; + continue; + } + + // The entry is relevant if there is an installed + // package with the same name and arch. + bool relevant = false; + sat::WhatProvides providers( (Capability( name.id() )) ); + for_( it, providers.begin(), providers.end() ) + { + if ( it->isSystem() && it->ident() == name && it->arch() == arch ) + { + relevant = true; + break; + } + } + if ( ! relevant ) + { + // DBG << "Not relevant: " << name << "-" << edition << "." << arch << endl; + continue; + } + + /* find exact providers first (this matches the _real_ 'collection content' of the patch */ + providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::EQ, edition, ResKind::package ) ); + if ( providers.empty() ) + { + /* no exact providers: find 'best' providers: those with a larger evr */ + providers = sat::WhatProvides( Capability( arch, name.c_str(), Rel::GT, edition, ResKind::package ) ); + if ( providers.empty() ) + { + // Hmm, this patch is not installable, no one is providing the package in the collection + // FIXME: raise execption ? fake a solvable ? + WAR << "Missing provider: " << name << "-" << edition << "." << arch << endl; + continue; + } + } + + // FIXME ?! loop over providers and try to find installed ones ? + // DBG << "Found " << name << "-" << edition << "." << arch << ": " << *(providers.begin()) << endl; + result.get().insert( *(providers.begin()) ); + } + + return result; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Patch::ReferenceIterator + // + /////////////////////////////////////////////////////////////////// + + Patch::ReferenceIterator::ReferenceIterator( const sat::Solvable & val_r ) + { base_reference() = sat::LookupAttr( sat::SolvAttr::updateReference, val_r ).begin(); } + + std::string Patch::ReferenceIterator::id() const + { return base_reference().subFind( sat::SolvAttr::updateReferenceId ).asString(); } + std::string Patch::ReferenceIterator::href() const + { return base_reference().subFind( sat::SolvAttr::updateReferenceHref ).asString(); } + std::string Patch::ReferenceIterator::title() const + { return base_reference().subFind( sat::SolvAttr::updateReferenceTitle ).asString(); } + std::string Patch::ReferenceIterator::type() const + { return base_reference().subFind( sat::SolvAttr::updateReferenceType ).asString(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Patch.h b/zypp/Patch.h new file mode 100644 index 0000000..77075e9 --- /dev/null +++ b/zypp/Patch.h @@ -0,0 +1,315 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Patch.h + * +*/ +#ifndef ZYPP_PATCH_H +#define ZYPP_PATCH_H + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + + DEFINE_PTR_TYPE(Patch); + + + /** + * Class representing a patch. + * + * A patch represents a specific problem that + * can be fixed by pulling in the patch dependencies. + * + * Patches can be marked for installation but their + * installation is a no-op. + */ + class ZYPP_API Patch : public ResObject + { + public: + using Self = Patch; + using TraitsType = ResTraits; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + using Contents = sat::SolvableSet; + + enum Category { + CAT_OTHER = 1, //!< unknown value specified + CAT_YAST = 1<<1, //!< + CAT_SECURITY = 1<<2, //!< + CAT_RECOMMENDED = 1<<3, //!< + CAT_OPTIONAL = 1<<4, //!< + CAT_DOCUMENT = 1<<5 //!< + }; + ZYPP_DECLARE_FLAGS(Categories, Category); + + /** + * Flags defining if and why this + * patch is interactive. + */ + enum InteractiveFlag { + NoFlags = 0x0000, + Reboot = 0x0001, + Message = 0x0002, + License = 0x0004 + }; + ZYPP_DECLARE_FLAGS(InteractiveFlags, InteractiveFlag); + + /** + * \brief Possible severity levels for (security) patches. + * Metadata string values are mapped to this enum to ease + * computations. For a string representation call + * \ref asSring( const Patch::SeverityFlag & ). + */ + enum SeverityFlag { + SEV_OTHER = 1, //!< unknown value specified + SEV_NONE = 1<<1, //!< no value specified + SEV_LOW = 1<<2, //!< Low + SEV_MODERATE = 1<<3, //!< Moderate + SEV_IMPORTANT = 1<<4, //!< Important + SEV_CRITICAL = 1<<5 //!< Critical + }; + ZYPP_DECLARE_FLAGS(SeverityFlags, SeverityFlag); + + public: + /** + * Issue date time. For now it is the same as + * \ref buildtime(). + */ + Date timestamp() const + { return buildtime(); } + + /** \name Patch Category */ + //@{ + /** + * Patch category (recommended, security,...) + */ + std::string category() const; + + /** This patch's category as enum of wellknown categories. + * Unknown values are mapped to \ref CAT_OTHER. + */ + Category categoryEnum() const; + + /** Whether this patch's category matches \a category_r */ + bool isCategory( const std::string & category_r ) const; + /** \overload taking OR'ed \ref Categories */ + bool isCategory( Categories category_r ) const; + + /** \overload taking container of category strings + * 2nd template arg just to prevent instantiation for Category + */ + template + bool isCategory( const TContainer & categories_r ) const + { + for ( const std::string & el : categories_r ) + { if ( isCategory( el ) ) return true; } + return false; + } + + /** Patch category as enum of wellknown categories. + * Unknown values are mapped to \ref CAT_OTHER. + */ + static Category categoryEnum( const std::string & category_r ); + //@} + + /** \name Patch Severity */ + //@{ + /** + * Severity string as specified in metadata. + * For use in computaions see \ref severityFlag. + */ + std::string severity() const; + + /** + * Severity string mapped to an enum. + * Unknown string values are mapped to \ref SEV_OTHER + */ + SeverityFlag severityFlag() const; + + /** Whether this patch's severity matches \a severity_r */ + bool isSeverity( const std::string & severity_r ) const; + /** \overload taking OR'ed \ref SeverityFlags */ + bool isSeverity( SeverityFlags severity_r ) const; + + /** \overload taking container of severity strings + * 2nd template arg just to prevent instantiation for SeverityFlag + */ + template + bool isSeverity( const TContainer & severities_r ) const + { + for ( const std::string & el : severities_r ) + { if ( isSeverity( el ) ) return true; } + return false; + } + + /** Severity string mapped to an enum. + * Unknown string values are mapped to \ref SEV_OTHER + */ + static SeverityFlag severityFlag( const std::string & category_r ); + //@} + + /** + * Does the system need to reboot to finish the update process? + */ + bool rebootSuggested() const; + + /** + * Does the patch affect the package manager itself? + * restart is suggested then + */ + bool restartSuggested() const; + + /** + * Does the patch needs the user to relogin to take effect? + * relogin is suggested then + */ + bool reloginSuggested() const; + + /** + * \short Information or warning to be displayed to the user + */ + std::string message( const Locale & lang_r = Locale() ) const; + + /** + * Get the InteractiveFlags of this Patch + */ + InteractiveFlags interactiveFlags() const; + + /** + * Is the patch still interactive when ignoring this flags? + */ + bool interactiveWhenIgnoring( InteractiveFlags flags_r = NoFlags ) const; + + /** + * Is the patch installation interactive? (does it need user input?) + * + * For security reasons patches requiring a reboot are not + * installed in an unattended mode. They are considered to be + * \c interactive so the user gets informed about the need for + * reboot. \a ignoreRebootFlag_r may be used to explicitly turn + * off this behavior and include those patches (unless they actually + * contain interactive components as well, like messages or licenses). + */ + bool interactive() const; + + public: + /** + * The collection of packages associated with this patch. + */ + Contents contents() const; + + public: + + /** Query class for Patch issue references */ + class ReferenceIterator; + /** + * Get an iterator to the beginning of the patch + * references. \see Patch::ReferenceIterator + */ + ReferenceIterator referencesBegin() const; + /** + * Get an iterator to the end of the patch + * references. \see Patch::ReferenceIterator + */ + ReferenceIterator referencesEnd() const; + + protected: + friend Ptr make( const sat::Solvable & solvable_r ); + /** Ctor */ + Patch( const sat::Solvable & solvable_r ); + /** Dtor */ + ~Patch() override; + }; + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Patch::Categories); + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Patch::InteractiveFlags); + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Patch::SeverityFlags); + + /** \relates Patch::Category string representation.*/ + std::string asString( const Patch::Category & obj ) ZYPP_API; + + /** \relates Patch::InteractiveFlag string representation.*/ + std::string asString( const Patch::InteractiveFlag & obj ) ZYPP_API; + + /** \relates Patch::SeverityFlag string representation.*/ + std::string asString( const Patch::SeverityFlag & obj ) ZYPP_API; + + /** + * Query class for Patch issue references + * like bugzilla and security issues the + * patch is supposed to fix. + * + * The iterator does not provide a dereference + * operator so you can do * on it, but you can + * access the attributes of each patch issue reference + * directly from the iterator. + * + * \code + * for ( Patch::ReferenceIterator it = patch->referencesBegin(); + * it != patch->referencesEnd(); + * ++it ) + * { + * cout << it.href() << endl; + * } + * \endcode + * + */ + class Patch::ReferenceIterator : public boost::iterator_adaptor< + Patch::ReferenceIterator // Derived + , sat::LookupAttr::iterator // Base + , int // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , int // Reference + > + { + public: + ReferenceIterator() {} + explicit ReferenceIterator( const sat::Solvable & val_r ); + + /** + * The id of the reference. For bugzilla entries + * this is the bug number as a string. + */ + std::string id() const; + /** + * Url or pointer where to find more information + */ + std::string href() const; + /** + * Title describing the issue + */ + std::string title() const; + /** + * Type of the reference. For example + * "bugzilla" + */ + std::string type() const; + + private: + friend class boost::iterator_core_access; + int dereference() const { return 0; } + }; + + inline Patch::ReferenceIterator Patch::referencesBegin() const + { return ReferenceIterator(satSolvable()); } + + inline Patch::ReferenceIterator Patch::referencesEnd() const + { return ReferenceIterator(); } + + ///////////////////////////////////////////////////////////////// + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PATCH_H diff --git a/zypp/PathInfo.cc b/zypp/PathInfo.cc new file mode 100644 index 0000000..4631160 --- /dev/null +++ b/zypp/PathInfo.cc @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PathInfo.cc + * +*/ + +#include +#include + +using std::endl; +using std::string; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace filesystem + { + + const StrMatcher & matchNoDots() + { + static StrMatcher noDots( "[^.]*", Match::GLOB ); + return noDots; + } + + int dirForEach( const Pathname & dir_r, const StrMatcher & matcher_r, function fnc_r ) + { + if ( ! fnc_r ) + return 0; + + bool nodots = ( &matcher_r == &matchNoDots() ); + return dirForEach( dir_r, + [&]( const Pathname & dir_r, const char *const name_r )->bool + { + if ( ( nodots && name_r[0] == '.' ) || ! matcher_r( name_r ) ) + return true; + return fnc_r( dir_r, name_r ); + } ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace filesystem + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PathInfo.h b/zypp/PathInfo.h new file mode 100644 index 0000000..7d5a3f6 --- /dev/null +++ b/zypp/PathInfo.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PathInfo.h + * +*/ +#ifndef ZYPP_PATHINFO_H +#define ZYPP_PATHINFO_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class StrMatcher; + + /////////////////////////////////////////////////////////////////// + /** Types and functions for filesystem operations. + * \todo move zypp::filesystem stuff into separate header + * \todo Add tmpfile and tmpdir handling. + * \todo think about using Exceptions in zypp::filesystem + * \todo provide a readdir iterator; at least provide an interface + * using an insert_iterator to be independent from std::container. + */ + namespace filesystem + { + + /** + * Convenience returning StrMatcher( "[^.]*", Match::GLOB ) + * \see \ref dirForEach + */ + const StrMatcher & matchNoDots(); + + /** + * \overload taking a \ref StrMatcher to filter the entries for which \a fnc_r is invoked. + * + * For convenience a \ref StrMatcher \ref matchNoDots is provided in this namespace.
+ * + * \code + * bool cbfnc( const Pathname & dir_r, const char *const str_r ) + * { + * D BG <*< " - " << dir_r/str_r << endl; + * return true; + * } + * // Print no-dot files in "/tmp" via callback + * filesystem::dirForEach( "/tmp", filesystem::matchNoDots(), cbfnc ); + * + * // same via lambda + * filesystem::dirForEach( "/tmp", filesystem::matchNoDots(), + * [](const Pathname & dir_r, const std::string & str_r)->bool + * { + * DBG << " - " << dir_r/str_r << endl; + * return true; + * }); + * \endcode + */ + int dirForEach( const Pathname & dir_r, const StrMatcher & matcher_r, function fnc_r ); + + ///////////////////////////////////////////////////////////////// + } // namespace filesystem + /////////////////////////////////////////////////////////////////// + + /** Dragged into namespace zypp. */ + using filesystem::PathInfo; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PATHINFO_H diff --git a/zypp/Pathname.h b/zypp/Pathname.h new file mode 100644 index 0000000..a3151d5 --- /dev/null +++ b/zypp/Pathname.h @@ -0,0 +1 @@ +#include diff --git a/zypp/Pattern.cc b/zypp/Pattern.cc new file mode 100644 index 0000000..2b1c59d --- /dev/null +++ b/zypp/Pattern.cc @@ -0,0 +1,412 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Pattern.cc + * +*/ +#include +#include + +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + inline Capability autoCapability( const Capabilities & provides_r ) + { + static const Capability autopattern( "autopattern()" ); + for ( const auto & cap : provides_r ) + if ( cap.matches( autopattern ) == CapMatch::yes ) + return cap; + return Capability(); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PatternExpander + // + /** Recursively expand a Pattern. + * + * This means recursively expanding Patterns included by this or + * extending this. The result is a \c set of Pattern::constPtr + * accessible via iterator. + */ + class PatternExpander + { + public: + using PatternMap = std::map>; + using size_type = PatternMap::size_type; + using value_type = PatternMap::key_type; + using const_iterator = MapKVIteratorTraits::Key_const_iterator; + + public: + PatternExpander() + {} + + /** Recursively expand Pattern. */ + size_type doExpand( const Pattern::constPtr& pat_r ) + { + // INT << "+++ " << pat_r << " ++++++++++++++++++++++++++++++++++" << endl; + _patternMap.clear(); + if ( pat_r ) + { + _patternMap[pat_r]; + Pattern::constPtr unprocessed( pat_r ); + // MIL << _patternMap << endl; + do { + expandIncludes( unprocessed ); + expandExtending( unprocessed ); + _patternMap[unprocessed] = true; + // MIL << _patternMap << endl; + } while( (unprocessed = nextUnprocessed()) ); + } + // SEC << "--- " << _patternMap.size() << " ----------------------------------" << endl; + return _patternMap.size(); + } + + const_iterator begin() const + { return make_map_key_begin( _patternMap ); } + + const_iterator end() const + { return make_map_key_end( _patternMap ); } + + private: + /** Get the next unprocessed Pattern in \c _patternMap. */ + Pattern::constPtr nextUnprocessed() const + { + for_( it, _patternMap.begin(), _patternMap.end() ) + { + if ( ! it->second ) + return it->first; + } + return NULL; + } + + private: + /** Store all included patterns in \c _patternMap. */ + void expandIncludes( const Pattern::constPtr & pat_r ) + { + Pattern::NameList c( pat_r->includes() ); + for_( it, c.begin(), c.end() ) + { + expandInclude( Capability( it->c_str()/*, *ResKind::pattern*/ ) ); + } + } + + /** Store Patterns matching an \c Includes capability in \c _patternMap. */ + void expandInclude( const Capability & include_r ) + { + sat::WhatProvides w( include_r ); + for_( it, w.begin(), w.end() ) + { + _patternMap[asKind(PoolItem(*it))]; + } + } + + private: + /** Store all patterns extending \c pat_r in \c _patternMap. */ + void expandExtending( const Pattern::constPtr & pat_r ) + { + ResPool pool( ResPool::instance() ); + for_( it, pool.byKindBegin(), pool.byKindEnd() ) + { + expandIfExtends( pat_r, *it ); + } + } + + /** Store \c extending_r if it extends \c pat_r. */ + void expandIfExtends( const Pattern::constPtr & pat_r, const PoolItem & extending_r ) + { + Pattern::constPtr extending( asKind(extending_r) ); + Pattern::NameList c( extending->extends() ); + for_( it, c.begin(), c.end() ) + { + if ( providedBy( pat_r, Capability( it->c_str()/*, *ResKind::pattern*/ ) ) ) + { + // an extends matches the Pattern + _patternMap[extending]; + break; + } + } + } + + /** Return true if Capability \c extends_r is provided by Pattern. */ + bool providedBy( const Pattern::constPtr & pat_r, const Capability & extends_r ) + { + if ( !pat_r ) + return false; + + sat::Solvable pat( pat_r->satSolvable() ); + sat::WhatProvides w( extends_r ); + for_( it, w.begin(), w.end() ) + { + if ( pat == *it ) + return true; + } + return false; + } + + private: + PatternMap _patternMap; + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // Pattern + /////////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(Pattern); + + Pattern::Pattern( const sat::Solvable & solvable_r ) + : ResObject( solvable_r ) + {} + + Pattern::~Pattern() + {} + + bool Pattern::isDefault() const + { return lookupBoolAttribute( sat::SolvAttr::isdefault ); } + + bool Pattern::userVisible() const + { + // bsc#900769: If visibility is a string(solvable ident) the pattern + // is visible IFF ident is available in the pool. + IdString ident( lookupStrAttribute( sat::SolvAttr::isvisible ) ); + return( ident.empty() ? lookupBoolAttribute( sat::SolvAttr::isvisible ) + : ! ResPool::instance().byIdent( ident ).empty() ); + } + + std::string Pattern::category( const Locale & lang_r ) const + { return lookupStrAttribute( sat::SolvAttr::category, lang_r ); } + + Pathname Pattern::icon() const + { return lookupStrAttribute( sat::SolvAttr::icon ); } + + Pathname Pattern::script() const + { return lookupStrAttribute( sat::SolvAttr::script ); } + + std::string Pattern::order() const + { return lookupStrAttribute( sat::SolvAttr::order ); } + + bool Pattern::isAutoPattern() const + { return bool(autoCapability( provides() )); } + + sat::Solvable Pattern::autoPackage() const + { + Capability autocap( autoCapability( provides() ) ); + if ( autocap ) + { + Capability pkgCap( arch(), autocap.detail().ed().asString(), Rel::EQ, edition() ); + for ( const auto & solv: sat::WhatProvides( pkgCap ) ) + if ( solv.repository() == repository() ) + return solv; + } + return sat::Solvable(); + } + + Pattern::NameList Pattern::includes() const + { return NameList( sat::SolvAttr::includes, satSolvable() ); } + + Pattern::NameList Pattern::extends() const + { return NameList( sat::SolvAttr::extends, satSolvable() ); } + + /////////////////////////////////////////////////////////////////// + namespace + { + inline void addCaps( CapabilitySet & caps_r, sat::Solvable solv_r, Dep dep_r ) + { + Capabilities c( solv_r[dep_r] ); + if ( ! c.empty() ) + { + caps_r.insert( c.begin(),c.end() ); + } + } + } //namespace + /////////////////////////////////////////////////////////////////// + + Pattern::Contents Pattern::core() const + { + // Content dependencies are either associated with + // the autoPackage or the (oldstype) pattern itself. + // load requires + CapabilitySet caps; + addCaps( caps, *this, Dep::REQUIRES ); + + sat::Solvable depKeeper( autoPackage() ); + if ( depKeeper ) + addCaps( caps, depKeeper, Dep::REQUIRES ); + // get items providing the requirements + sat::WhatProvides prv( caps ); + // return packages only. + return Pattern::Contents( make_filter_begin( filter::byKind(), prv ), + make_filter_end( filter::byKind(), prv ) ); + } + + Pattern::Contents Pattern::depends( bool includeSuggests_r ) const + { + // Content dependencies are either associated with + // the autoPackage or the (oldstype) pattern itself. + // load requires, recommends[, suggests] + CapabilitySet caps; + addCaps( caps, *this, Dep::REQUIRES ); + addCaps( caps, *this, Dep::RECOMMENDS ); + if ( includeSuggests_r ) + addCaps( caps, *this, Dep::SUGGESTS ); + + sat::Solvable depKeeper( autoPackage() ); + if ( depKeeper ) + { + addCaps( caps, depKeeper, Dep::REQUIRES ); + addCaps( caps, depKeeper, Dep::RECOMMENDS ); + if ( includeSuggests_r ) + addCaps( caps, depKeeper, Dep::SUGGESTS ); + } + // get items providing the above + sat::WhatProvides prv( caps ); + // return packages only. + return Pattern::Contents( make_filter_begin( filter::byKind(), prv ), + make_filter_end( filter::byKind(), prv ) ); + } + + Pattern::Contents Pattern::contents( bool includeSuggests_r ) const + { + PatternExpander expander; + if ( ! expander.doExpand( this ) ) + return Contents(); // empty pattern set + + Contents result; + for_( it, expander.begin(), expander.end() ) + { + Contents c( (*it)->depends( includeSuggests_r ) ); + result.get().insert( c.begin(), c.end() ); + } + return result; + } + + /////////////////////////////////////////////////////////////////// + namespace + { + // Get packages referenced by depKeeper dependency. + inline void dependsSetDoCollect( sat::Solvable depKeeper_r, Dep dep_r, Pattern::Contents & set_r ) + { + CapabilitySet caps; + addCaps( caps, depKeeper_r, dep_r ); + sat::WhatProvides prv( caps ); + for ( ui::Selectable::Ptr sel : prv.selectable() ) + { + const PoolItem & pi( sel->theObj() ); + if ( pi.isKind() ) + set_r.insert( pi ); + } + } + + // Get packages referenced by depKeeper. + inline void dependsSet( sat::Solvable depKeeper_r, Pattern::ContentsSet & collect_r ) + { + dependsSetDoCollect( depKeeper_r, Dep::REQUIRES, collect_r.req ); + dependsSetDoCollect( depKeeper_r, Dep::RECOMMENDS, collect_r.rec ), + dependsSetDoCollect( depKeeper_r, Dep::SUGGESTS, collect_r.sug ); + } + + // Whether this is a patterns depkeeper. + inline bool isPatternsPackage( sat::Solvable depKeeper_r ) + { + static const Capability indicator( "pattern()" ); + return depKeeper_r.provides().matches( indicator ); + } + } // namespace + /////////////////////////////////////////////////////////////////// + void Pattern::contentsSet( ContentsSet & collect_r, bool recursively_r ) const + { + sat::Solvable depKeeper( autoPackage() ); // (my required) patterns-package + if ( ! depKeeper ) + return; + + // step 2 data + std::set recTodo; // recommended patterns-packages to process + std::set allDone; // patterns-packages already expanded + { + // step 1: Expand requirements, remember recommends.... + // step 1 data (scoped to step1) + std::set reqTodo; // required patterns-packages to process + + collect_r.req.insert( depKeeper );// collect the depKeeper + reqTodo.insert( depKeeper ); // and expand it... + + while ( ! reqTodo.empty() ) + { + // pop one patterns-package from todo + depKeeper = ( *reqTodo.begin() ); + reqTodo.erase( reqTodo.begin() ); + allDone.insert( depKeeper ); + + // collects stats + ContentsSet result; + dependsSet( depKeeper, result ); + + // evaluate result.... + for ( sat::Solvable solv : result.req ) // remember unprocessed required patterns-packages... + { + if ( collect_r.req.insert( solv ) && recursively_r && isPatternsPackage( solv ) ) + reqTodo.insert( solv ); + } + for ( sat::Solvable solv : result.rec ) // remember unprocessed recommended patterns-packages... + { + if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) ) + recTodo.insert( solv ); + } + for ( sat::Solvable solv : result.sug ) // NOTE: We don't expand suggested patterns! + { + collect_r.sug.insert( solv ); + } + } + } + // step 2: All requirements are expanded, now check remaining recommends.... + while ( ! recTodo.empty() ) + { + // pop one patterns-package from todo + depKeeper = ( *recTodo.begin() ); + recTodo.erase( recTodo.begin() ); + if ( ! allDone.insert( depKeeper ).second ) + continue; // allready expanded (in requires) + + // collects stats + ContentsSet result; + dependsSet( depKeeper, result ); + + // evaluate result.... + for ( sat::Solvable solv : result.req ) // remember unprocessed required patterns-packages... + { + // NOTE: Requirements of recommended patterns count as 'recommended' + if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) ) + recTodo.insert( solv ); + } + for ( sat::Solvable solv : result.rec ) // remember unprocessed recommended patterns-packages... + { + if ( collect_r.rec.insert( solv ) && recursively_r && isPatternsPackage( solv ) ) + recTodo.insert( solv ); + } + for ( sat::Solvable solv : result.sug ) // NOTE: We don't expand suggested patterns! + { + collect_r.sug.insert( solv ); + } + } + } + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Pattern.h b/zypp/Pattern.h new file mode 100644 index 0000000..5ef8d80 --- /dev/null +++ b/zypp/Pattern.h @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Pattern.h + * +*/ +#ifndef ZYPP_PATTERN_H +#define ZYPP_PATTERN_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(Pattern); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Pattern + // + /** Pattern interface. + */ + class ZYPP_API Pattern : public ResObject + { + public: + using Self = Pattern; + using TraitsType = ResTraits; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + using NameList = sat::ArrayAttr; + using Contents = sat::SolvableSet; + + public: + /** */ + bool isDefault() const; + /** */ + bool userVisible() const; + /** */ + std::string category( const Locale & lang_r = Locale() ) const; + /** */ + Pathname icon() const; + /** */ + Pathname script() const; + /** */ + std::string order() const; + + public: + /** \name Auto patterns (libyzpp-14) + * Patterns are no longer defined by separate metadate files, but via + * special dependencies provided by a corresponding patterns- package. + * The pattern itself requires only its patterns- package. The package + * contains all further dependencies. + * This way, patterns are no longer pseudo-installed objects with a computed + * status, but installed, iff the corresponding patterns- package is + * installed. + */ + //@{ + /** This patterns is auto-defined by a patterns- package. */ + bool isAutoPattern() const; + /** The corresponding patterns- package if \ref isAutoPattern. */ + sat::Solvable autoPackage() const; + //@} + public: + /** Ui hint: included patterns. */ + NameList includes() const; + + /** Ui hint: patterns this one extends. */ + NameList extends() const; + + /** Ui hint: Required Packages. */ + Contents core() const; + + /** Ui hint: Dependent packages. + * This also includes recommended and suggested (optionally exclude) packages. + */ + Contents depends( bool includeSuggests_r = true ) const; + /** \overload Without SUGGESTS. */ + Contents dependsNoSuggests() const + { return depends( false ); } + + /** The collection of packages associated with this pattern. + * This also evaluates the patterns includes/extends relation. + * Optionally exclude \c SUGGESTED packages. + */ + Contents contents( bool includeSuggests_r = true ) const; + /** \overload Without SUGGESTS. */ + Contents contentsNoSuggests() const + { return contents( false ); } + + public: + struct ContentsSet + { + Contents req; ///< required content set + Contents rec; ///< recommended content set + Contents sug; ///< suggested content set + }; + /** Dependency based content set (does not evaluate includes/extends relation). + * If \a recursively_r, required and recommended + * patterns are recursively expanded. + */ + void contentsSet( ContentsSet & collect_r, bool recursively_r = false ) const; + /** \overload Convenience for recursively expanded contentsSet */ + void fullContentsSet( ContentsSet & collect_r ) const + { return contentsSet( collect_r, /*recursively_r*/true ); } + + protected: + friend Ptr make( const sat::Solvable & solvable_r ); + /** Ctor */ + Pattern( const sat::Solvable & solvable_r ); + /** Dtor */ + ~Pattern() override; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PATTERN_H diff --git a/zypp/PluginExecutor.cc b/zypp/PluginExecutor.cc new file mode 100644 index 0000000..826a915 --- /dev/null +++ b/zypp/PluginExecutor.cc @@ -0,0 +1,184 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginExecutor.cc + */ +#include +#include +#include + +#include +#include +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class PluginExecutor::Impl + /// \brief PluginExecutor implementation. + /////////////////////////////////////////////////////////////////// + class PluginExecutor::Impl : private base::NonCopyable + { + public: + Impl() + {} + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() { + if ( ! empty() ) + send( PluginFrame( "PLUGINEND" ) ); + // ~PluginScript will disconnect all remaining plugins! + } + + bool empty() const + { return _scripts.empty(); } + + size_t size() const + { return _scripts.size(); } + + void load( const Pathname & path_r ) + { + PathInfo pi( path_r ); + DBG << "+++++++++++++++ load " << pi << endl; + if ( pi.isDir() ) + { + std::list entries; + if ( filesystem::readdir( entries, pi.path(), false ) != 0 ) + { + WAR << "Plugin dir is not readable: " << pi << endl; + return; + } + for_( it, entries.begin(), entries.end() ) + { + PathInfo pii( *it ); + if ( pii.isFile() && pii.userMayRX() ) + doLoad( pii ); + } + } + else if ( pi.isFile() ) + { + if ( pi.userMayRX() ) + doLoad( pi ); + else + WAR << "Plugin file is not executable: " << pi << endl; + } + else + { + WAR << "Plugin path is neither dir nor file: " << pi << endl; + } + DBG << "--------------- load " << pi << endl; + } + + void send( const PluginFrame & frame_r ) + { + DBG << "+++++++++++++++ send " << frame_r << endl; + for ( auto it = _scripts.begin(); it != _scripts.end(); ) + { + doSend( *it, frame_r ); + if ( it->isOpen() ) + ++it; + else + it = _scripts.erase( it ); + } + DBG << "--------------- send " << frame_r << endl; + } + + const std::list scripts() const + { return _scripts; } + + private: + /** Launch a plugin sending PLUGINSTART message. */ + void doLoad( const PathInfo & pi_r ) + { + MIL << "Load plugin: " << pi_r << endl; + try { + PluginScript plugin( pi_r.path() ); + plugin.open(); + + PluginFrame frame( "PLUGINBEGIN" ); + if ( ZConfig::instance().hasUserData() ) + frame.setHeader( "userdata", ZConfig::instance().userData() ); + + doSend( plugin, frame ); // closes on error + if ( plugin.isOpen() ) + _scripts.push_back( plugin ); + } + catch( const zypp::Exception & e ) + { + WAR << "Failed to load plugin " << pi_r << endl; + } + } + + PluginFrame doSend( PluginScript & script_r, const PluginFrame & frame_r ) + { + PluginFrame ret; + + try { + script_r.send( frame_r ); + ret = script_r.receive(); + } + catch( const zypp::Exception & e ) + { + ZYPP_CAUGHT(e); + WAR << e.asUserHistory() << endl; + } + + // Allow using "/bin/cat" as reflector-script for testing + if ( ! ( ret.isAckCommand() || ret.isEnomethodCommand() || ( script_r.script() == "/bin/cat" && frame_r.command() != "ERROR" ) ) ) + { + WAR << "Bad plugin response from " << script_r << ": " << ret << endl; + WAR << "(Expected " << PluginFrame::ackCommand() << " or " << PluginFrame::enomethodCommand() << ")" << endl; + script_r.close(); + } + + return ret; + } + private: + std::list _scripts; + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PluginExecutor + // + /////////////////////////////////////////////////////////////////// + + PluginExecutor::PluginExecutor() + : _pimpl( new Impl() ) + {} + + PluginExecutor::~PluginExecutor() + {} + + bool PluginExecutor::empty() const + { return _pimpl->empty(); } + + size_t PluginExecutor::size() const + { return _pimpl->size(); } + + void PluginExecutor::load( const Pathname & path_r ) + { _pimpl->load( path_r ); } + + void PluginExecutor::send( const PluginFrame & frame_r ) + { _pimpl->send( frame_r ); } + + std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj ) + { return str << obj._pimpl->scripts(); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PluginExecutor.h b/zypp/PluginExecutor.h new file mode 100644 index 0000000..2751127 --- /dev/null +++ b/zypp/PluginExecutor.h @@ -0,0 +1,97 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginExecutor.h + */ +#ifndef ZYPP_PLUGINEXECUTOR_H +#define ZYPP_PLUGINEXECUTOR_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class PluginExecutor + /// \brief Parallel execution of stateful PluginScripts + /// + /// Sent PluginFrames are distributed to all open PluginScripts and + /// need to be receipted by sending back either \c ACK or \c _ENOMETHOD + /// command. + /// + /// All PluginScripts receive an initial \c PLUGINBEGIN frame, containing + /// a \c userdata header if \ref ZConfig::userData are defined. + /// \see also zypper '--userdata' option + /// + /// A final \c PLUGINEND frame is sent and open scripts are closed, when the + /// executors last reference goes out of scope. Failing PluginScripts are + /// closed immediately. + /// + /// \see PluginScript + /// \ingroup g_RAII + /////////////////////////////////////////////////////////////////// + class ZYPP_API PluginExecutor + { + friend std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj ); + friend bool operator==( const PluginExecutor & lhs, const PluginExecutor & rhs ); + + public: + /** Default ctor: Empty plugin list */ + PluginExecutor(); + + /** Dtor: Send \c PLUGINEND and close all plugins */ + ~PluginExecutor(); + + public: + /** Validate object in a boolean context: There are plugins waiting for input */ + explicit operator bool() const + { return !empty(); } + + /** Whether no plugins are waiting */ + bool empty() const; + + /** Number of open plugins */ + size_t size() const; + + public: + /** Find and launch plugins sending \c PLUGINBEGIN. + * + * If \a path_r is a directory all executable files within are + * expected to be plugins. Otherwise \a path_r must point to an + * executable plugin. + */ + void load( const Pathname & path_r ); + + /** Send \ref PluginFrame to all open plugins. + * Failed plugins are removed from the execution list. + */ + void send( const PluginFrame & frame_r ); + + public: + class Impl; ///< Implementation class. + private: + RW_pointer _pimpl; ///< Pointer to implementation. + }; + + /** \relates PluginExecutor Stream output */ + std::ostream & operator<<( std::ostream & str, const PluginExecutor & obj ); + + /** \relates PluginExecutor Comparison based on reference. */ + inline bool operator==( const PluginExecutor & lhs, const PluginExecutor & rhs ) + { return ( lhs._pimpl == rhs._pimpl ); } + + /** \relates PluginExecutor Comparison based on reference. */ + inline bool operator!=( const PluginExecutor & lhs, const PluginExecutor & rhs ) + { return( ! operator==( lhs, rhs ) ); } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PLUGINEXECUTOR_H diff --git a/zypp/PluginScript.cc b/zypp/PluginScript.cc new file mode 100644 index 0000000..89fcf07 --- /dev/null +++ b/zypp/PluginScript.cc @@ -0,0 +1,532 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginScript.cc + * +*/ +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::plugin" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace + { + const char * PLUGIN_DEBUG = getenv( "ZYPP_PLUGIN_DEBUG" ); + + /** Dump buffer string if PLUGIN_DEBUG is on. + * \ingroup g_RAII + */ + struct PluginDebugBuffer + { + PluginDebugBuffer(const std::string &buffer_r) : _buffer(buffer_r) {} + PluginDebugBuffer(const PluginDebugBuffer &) = delete; + PluginDebugBuffer(PluginDebugBuffer &&) = delete; + PluginDebugBuffer &operator=(const PluginDebugBuffer &) = delete; + PluginDebugBuffer &operator=(PluginDebugBuffer &&) = delete; + ~PluginDebugBuffer() + { + if ( PLUGIN_DEBUG ) + { + if ( _buffer.empty() ) + { + L_DBG("PLUGIN") << "< (empty)" << endl; + } + else + { + std::istringstream datas( _buffer ); + iostr::copyIndent( datas, L_DBG("PLUGIN"), "< " ) << endl; + } + } + } + const std::string & _buffer; + }; + + /** Dump programms stderr. + * \ingroup g_RAII + */ + struct PluginDumpStderr + { + PluginDumpStderr(ExternalProgramWithStderr &prog_r) : _prog(prog_r) {} + PluginDumpStderr(const PluginDumpStderr &) = delete; + PluginDumpStderr(PluginDumpStderr &&) = delete; + PluginDumpStderr &operator=(const PluginDumpStderr &) = delete; + PluginDumpStderr &operator=(PluginDumpStderr &&) = delete; + ~PluginDumpStderr() + { + std::string line; + while ( _prog.stderrGetline( line ) ) + L_WAR("PLUGIN") << "! " << line << endl; + } + ExternalProgramWithStderr & _prog; + }; + + inline void setBlocking( FILE * file_r, bool yesno_r = true ) + { + if ( ! file_r ) + ZYPP_THROW( PluginScriptException( "setNonBlocking" ) ); + + int fd = ::fileno( file_r ); + if ( fd == -1 ) + ZYPP_THROW( PluginScriptException( "setNonBlocking" ) ); + + int flags = ::fcntl( fd, F_GETFL ); + if ( flags == -1 ) + ZYPP_THROW( PluginScriptException( "setNonBlocking" ) ); + + if ( ! yesno_r ) + flags |= O_NONBLOCK; + else if ( flags & O_NONBLOCK ) + flags ^= O_NONBLOCK; + + flags = ::fcntl( fd, F_SETFL, flags ); + if ( flags == -1 ) + ZYPP_THROW( PluginScriptException( "setNonBlocking" ) ); + } + + inline void setNonBlocking( FILE * file_r, bool yesno_r = true ) + { setBlocking( file_r, !yesno_r ); } + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PluginScript::Impl + // + /** \ref PluginScript implementation. */ + struct PluginScript::Impl + { + public: + Impl( Pathname &&script_r = Pathname(), Arguments &&args_r = Arguments() ) + : _sendTimeout( _defaultSendTimeout ) + , _receiveTimeout( _defaultReceiveTimeout ) + , _script(std::move( script_r )) + , _args(std::move( args_r )) + {} + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() { + try { + close(); + } catch (...) { + } + } + + public: + static long _defaultSendTimeout; + static long _defaultReceiveTimeout; + + long _sendTimeout; + long _receiveTimeout; + + public: + const Pathname & script() const + { return _script; } + + const Arguments & args() const + { return _args; } + + pid_t getPid() const + { return _cmd ? _cmd->getpid() : NotConnected; } + + bool isOpen() const + { return _cmd != nullptr; } + + int lastReturn() const + { return _lastReturn; } + + const std::string & lastExecError() const + { return _lastExecError; } + + public: + void open( const Pathname & script_r = Pathname(), const Arguments & args_r = Arguments() ); + + int close(); + + void send( const PluginFrame & frame_r ) const; + + PluginFrame receive() const; + + private: + Pathname _script; + Arguments _args; + scoped_ptr _cmd; + DefaultIntegral _lastReturn; + std::string _lastExecError; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PluginScrip::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const PluginScript::Impl & obj ) + { + return str << "PluginScript[" << obj.getPid() << "] " << obj.script(); + } + + /////////////////////////////////////////////////////////////////// + + namespace + { + const long PLUGIN_TIMEOUT = str::strtonum( getenv( "ZYPP_PLUGIN_TIMEOUT" ) ); + const long PLUGIN_SEND_TIMEOUT = str::strtonum( getenv( "ZYPP_PLUGIN_SEND_TIMEOUT" ) ); + const long PLUGIN_RECEIVE_TIMEOUT = str::strtonum( getenv( "ZYPP_PLUGIN_RECEIVE_TIMEOUT" ) ); + } + + long PluginScript::Impl::_defaultSendTimeout = ( PLUGIN_SEND_TIMEOUT > 0 ? PLUGIN_SEND_TIMEOUT + : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) ); + long PluginScript::Impl::_defaultReceiveTimeout = ( PLUGIN_RECEIVE_TIMEOUT > 0 ? PLUGIN_RECEIVE_TIMEOUT + : ( PLUGIN_TIMEOUT > 0 ? PLUGIN_TIMEOUT : 30 ) ); + + /////////////////////////////////////////////////////////////////// + + void PluginScript::Impl::open( const Pathname & script_r, const Arguments & args_r ) + { + dumpRangeLine( DBG << "Open " << script_r, args_r.begin(), args_r.end() ) << endl; + + if ( _cmd ) + ZYPP_THROW( PluginScriptException( "Already connected", str::Str() << *this ) ); + + { + PathInfo pi( script_r ); + if ( ! ( pi.isFile() && pi.isX() ) ) + ZYPP_THROW( PluginScriptException( "Script is not executable", str::Str() << pi ) ); + } + + // go and launch script + // TODO: ExternalProgram::maybe use Stderr_To_FileDesc for script loging + Arguments args; + args.reserve( args_r.size()+1 ); + args.push_back( script_r.asString() ); + args.insert( args.end(), args_r.begin(), args_r.end() ); + _cmd.reset( new ExternalProgramWithStderr( args ) ); + + // Be protected against full pipe, etc. + setNonBlocking( _cmd->outputFile() ); + setNonBlocking( _cmd->inputFile() ); + + // store running scripts data + _script = script_r; + _args = args_r; + _lastReturn.reset(); + _lastExecError.clear(); + + dumpRangeLine( DBG << *this, _args.begin(), _args.end() ) << endl; + } + + int PluginScript::Impl::close() + { + if ( _cmd ) + { + DBG << "Close:" << *this << endl; + bool doKill = true; + try { + // do not kill script if _DISCONNECT is ACKed. + send( PluginFrame( "_DISCONNECT" ) ); + PluginFrame ret( receive() ); + if ( ret.isAckCommand() ) + { + doKill = false; + str::strtonum( ret.getHeaderNT( "exit" ), _lastReturn.get() ); + _lastExecError = ret.body().asString(); + } + } + catch (...) + { /* NOP */ } + + if ( doKill ) + { + _cmd->kill(); + _lastReturn = _cmd->close(); + _lastExecError = _cmd->execError(); + } + DBG << *this << " -> [" << _lastReturn << "] " << _lastExecError << endl; + _cmd.reset(); + } + return _lastReturn; + } + + void PluginScript::Impl::send( const PluginFrame & frame_r ) const + { + if ( !_cmd ) + ZYPP_THROW( PluginScriptNotConnected( "Not connected", str::Str() << *this ) ); + + if ( frame_r.command().empty() ) + WAR << "Send: No command in frame" << frame_r << endl; + + // prepare frame data to write + std::string data; + { + std::ostringstream datas; + frame_r.writeTo( datas ); + datas.str().swap( data ); + } + DBG << *this << " ->send " << frame_r << endl; + + if ( PLUGIN_DEBUG ) + { + std::istringstream datas( data ); + iostr::copyIndent( datas, L_DBG("PLUGIN") ) << endl; + } + + // try writing the pipe.... + FILE * filep = _cmd->outputFile(); + if ( ! filep ) + ZYPP_THROW( PluginScriptException( "Bad file pointer." ) ); + + int fd = ::fileno( filep ); + if ( fd == -1 ) + ZYPP_THROW( PluginScriptException( "Bad file descriptor" ) ); + + //DBG << " ->[" << fd << " " << (::feof(filep)?'e':'_') << (::ferror(filep)?'F':'_') << "]" << endl; + { + PluginDumpStderr _dump( *_cmd ); // dump scripts stderr before leaving + SignalSaver sigsav( SIGPIPE, SIG_IGN ); + const char * buffer = data.c_str(); + ssize_t buffsize = data.size(); + do { + GPollFD watchFd; + watchFd.fd = fd; + watchFd.events = G_IO_OUT | G_IO_ERR; + watchFd.revents = 0; + + errno = 0; + int retval = g_poll( &watchFd, 1, _sendTimeout * 1000 ); + if ( retval > 0 ) // FD_ISSET( fd, &wfds ) will be true. + { + //DBG << "Ready to write..." << endl; + ssize_t ret = ::write( fd, buffer, buffsize ); + if ( ret == buffsize ) + { + //DBG << "::write(" << buffsize << ") -> " << ret << endl; + ::fflush( filep ); + break; // -> done + } + else if ( ret > 0 ) + { + //WAR << "::write(" << buffsize << ") -> " << ret << " INCOMPLETE..." << endl; + ::fflush( filep ); + buffsize -= ret; + buffer += ret; // -> continue + } + else // ( retval == -1 ) + { + if ( errno != EINTR ) + { + ERR << "write(): " << Errno() << endl; + if ( errno == EPIPE ) + ZYPP_THROW( PluginScriptDiedUnexpectedly( "Send: script died unexpectedly", str::Str() << Errno() ) ); + else + ZYPP_THROW( PluginScriptException( "Send: send error", str::Str() << Errno() ) ); + } + } + } + else if ( retval == 0 ) + { + WAR << "Not ready to write within timeout." << endl; + ZYPP_THROW( PluginScriptSendTimeout( "Not ready to write within timeout." ) ); + } + else // ( retval == -1 ) + { + if ( errno != EINTR ) + { + ERR << "select(): " << Errno() << endl; + ZYPP_THROW( PluginScriptException( "Error waiting on file descriptor", str::Str() << Errno() ) ); + } + } + } while( true ); + } + } + + PluginFrame PluginScript::Impl::receive() const + { + if ( !_cmd ) + ZYPP_THROW( PluginScriptNotConnected( "Not connected", str::Str() << *this ) ); + + // try reading the pipe.... + FILE * filep = _cmd->inputFile(); + if ( ! filep ) + ZYPP_THROW( PluginScriptException( "Bad file pointer." ) ); + + int fd = ::fileno( filep ); + if ( fd == -1 ) + ZYPP_THROW( PluginScriptException( "Bad file descriptor" ) ); + + ::clearerr( filep ); + std::string data; + { + PluginDebugBuffer _debug( data ); // dump receive buffer if PLUGIN_DEBUG + PluginDumpStderr _dump( *_cmd ); // dump scripts stderr before leaving + do { + int ch = fgetc( filep ); + if ( ch != EOF ) + { + data.push_back( ch ); + if ( ch == '\0' ) + break; + } + else if ( ::feof( filep ) ) + { + WAR << "Unexpected EOF" << endl; + ZYPP_THROW( PluginScriptDiedUnexpectedly( "Receive: script died unexpectedly", str::Str() << Errno() ) ); + } + else if ( errno != EINTR ) + { + if ( errno == EWOULDBLOCK ) + { + // wait a while for fd to become ready for reading... + GPollFD rfd; + rfd.fd = fd; + rfd.events = G_IO_IN | G_IO_HUP | G_IO_ERR; + rfd.revents = 0; + + int retval = g_poll( &rfd, 1, _receiveTimeout * 1000 ); + if ( retval > 0 ) // rfd.revents was filled + { + ::clearerr( filep ); + } + else if ( retval == 0 ) + { + WAR << "Not ready to read within timeout." << endl; + ZYPP_THROW( PluginScriptReceiveTimeout( "Not ready to read within timeout." ) ); + } + else // ( retval == -1 ) + { + if ( errno != EINTR ) + { + ERR << "select(): " << Errno() << endl; + ZYPP_THROW( PluginScriptException( "Error waiting on file descriptor", str::Str() << Errno() ) ); + } + } + } + else + { + ERR << "read(): " << Errno() << endl; + ZYPP_THROW( PluginScriptException( "Receive: receive error", str::Str() << Errno() ) ); + } + } + } while ( true ); + } + // DBG << " <-read " << data.size() << endl; + std::istringstream datas( data ); + PluginFrame ret( datas ); + DBG << *this << " <-" << ret << endl; + return ret; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PluginScript + // + /////////////////////////////////////////////////////////////////// + + const pid_t PluginScript::NotConnected( -1 ); + + long PluginScript::defaultSendTimeout() + { return Impl::_defaultSendTimeout; } + + long PluginScript::defaultReceiveTimeout() + { return Impl::_defaultReceiveTimeout; } + + void PluginScript::defaultSendTimeout( long newval_r ) + { Impl::_defaultSendTimeout = newval_r > 0 ? newval_r : 0; } + + void PluginScript::defaultReceiveTimeout( long newval_r ) + { Impl::_defaultReceiveTimeout = newval_r > 0 ? newval_r : 0; } + + long PluginScript::sendTimeout() const + { return _pimpl->_sendTimeout; } + + long PluginScript::receiveTimeout() const + { return _pimpl->_receiveTimeout; } + + void PluginScript::sendTimeout( long newval_r ) + { _pimpl->_sendTimeout = newval_r > 0 ? newval_r : 0; } + + void PluginScript::receiveTimeout( long newval_r ) + { _pimpl->_receiveTimeout = newval_r > 0 ? newval_r : 0; } + + PluginScript::PluginScript() + : _pimpl( new Impl ) + {} + + PluginScript::PluginScript( Pathname script_r ) + : _pimpl( new Impl( std::move(script_r) ) ) + {} + + PluginScript::PluginScript( Pathname script_r, Arguments args_r ) + : _pimpl( new Impl( std::move(script_r), std::move(args_r) ) ) + {} + + const Pathname & PluginScript::script() const + { return _pimpl->script(); } + + const PluginScript::Arguments & PluginScript::args() const + { return _pimpl->args(); } + + bool PluginScript::isOpen() const + { return _pimpl->isOpen(); } + + pid_t PluginScript::getPid() const + { return _pimpl->getPid(); } + + int PluginScript::lastReturn() const + { return _pimpl->lastReturn(); } + + const std::string & PluginScript::lastExecError() const + { return _pimpl->lastExecError(); } + + void PluginScript::open() + { _pimpl->open( _pimpl->script(), _pimpl->args() ); } + + void PluginScript::open( const Pathname & script_r ) + { _pimpl->open( script_r ); } + + void PluginScript::open( const Pathname & script_r, const Arguments & args_r ) + { _pimpl->open( script_r, args_r ); } + + int PluginScript::close() + { return _pimpl->close(); } + + void PluginScript::send( const PluginFrame & frame_r ) const + { _pimpl->send( frame_r ); } + + PluginFrame PluginScript::receive() const + { return _pimpl->receive(); } + + /////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const PluginScript & obj ) + { return str << *obj._pimpl; } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PluginScript.h b/zypp/PluginScript.h new file mode 100644 index 0000000..fc6410c --- /dev/null +++ b/zypp/PluginScript.h @@ -0,0 +1,197 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginScript.h + * +*/ +#ifndef ZYPP_PLUGINSCRIPT_H +#define ZYPP_PLUGINSCRIPT_H + +#include +#include +#include + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** + * \brief Interface to plugin scripts using a \c Stomp inspired communication protocol. + * + * \note \ref PluginScript is copyable and assignable, but the connection is shared + * among multiple copies. It gets automatically closed if the last copy goes out of + * scope. + * + * Timeout when sending/receiving data to/from a plugin default to 30 sec. The value + * (in seconds) my be changed via the environment variables \c ZYPP_PLUGIN_SEND_TIMEOUT, + * \c ZYPP_PLUGIN_RECEIVE_TIMEOUT or \c ZYPP_PLUGIN_TIMEOUT (both: send and receive). + * + * \code + * // Setup comnnection to plugin script + * PluginScript scr; + * PluginScript::Arguments args; + * args.push_back( "-v" ); + * scr.open( "/soem/testplugin", args ); + * + * // send frame to plugin + * PluginFrame f( "COMMAND" ); + * f.setHeader( "key", "value" ); + * f.setBody( "some\ndata" ); + * scr.send( f ); + * + * // receive frame from plugin + * PluginFrame r( scr.receive() ); + * + * // explicitly close or let PluginScript go out of scope + * scr.close(); + * \endcode + * + * \see https://stomp.github.io + */ + class ZYPP_API PluginScript + { + friend std::ostream & operator<<( std::ostream & str, const PluginScript & obj ); + + public: + /** Commandline arguments passed to a script on \ref open. */ + using Arguments = std::vector; + + /** \c pid_t(-1) constant indicating no connection. */ + static const pid_t NotConnected; + + public: + /** \name Get/set the global timeout settings. + * Timeout when sending/receiving data to/from a plugin default to 30 sec. The value + * (in seconds) my be changed via the environment variables \c ZYPP_PLUGIN_SEND_TIMEOUT, + * \c ZYPP_PLUGIN_RECEIVE_TIMEOUT or \c ZYPP_PLUGIN_TIMEOUT (both: send and receive). + */ + //@{ + /** Global default timeout (sec.) when sending data. */ + static long defaultSendTimeout(); + + /** Global default timeout (sec.) when receiving data. */ + static long defaultReceiveTimeout(); + + /** Set global default timeout (sec.) when sending data. */ + static void defaultSendTimeout( long newval_r ); + + /** Set global default timeout (sec.) when receiving data. */ + static void defaultReceiveTimeout( long newval_r ); + + /** Set global default timeout (sec.) (both: send and receive).*/ + static void defaultTimeout( long newval_r ) + { defaultSendTimeout( newval_r ); defaultReceiveTimeout( newval_r ); } + //@} + + public: + /** Default ctor. */ + PluginScript(); + + /** Ctor taking script path and no arguments. */ + PluginScript( Pathname script_r ); + + /** Ctor taking script path and script arguments. */ + PluginScript( Pathname script_r, Arguments args_r ); + + public: + /** Return the script path if set. */ + const Pathname & script() const; + + /** Return the script arguments if set. */ + const Arguments & args() const; + + /** Whether we are connected to a script. */ + bool isOpen() const; + + /** Return a connected scripts pid or \ref NotConnected. */ + pid_t getPid() const; + + /** Remembers a scripts return value after \ref close until next \ref open. */ + int lastReturn() const; + + /** Remembers a scripts execError string after \ref close until next \ref open. + * \see \ref ExternalProgram::execError. + */ + const std::string & lastExecError() const; + + public: + /** \name Get/set local timeout settings. */ + //@{ + /** Local default timeout (sec.) when sending data. */ + long sendTimeout() const; + + /** Local default timeout (sec.) when receiving data. */ + long receiveTimeout() const; + + /** Set local default timeout (sec.) when sending data. */ + void sendTimeout( long newval_r ); + + /** Set local default timeout (sec.) when receiving data. */ + void receiveTimeout( long newval_r ); + + /** Set local default timeout (sec.) (both: send and receive).*/ + void timeout( long newval_r ) + { sendTimeout( newval_r ); receiveTimeout( newval_r ); } + //@} + + public: + /** Setup connection and execute script. + * \throw PluginScriptException if already connected to a script + * \throw PluginScriptException if script does not exist or is not executable + * \throw PluginScriptException on error + */ + void open(); + + /** \overload taking script path and no arguments. */ + void open( const Pathname & script_r ); + + /** \overload taking script path and script arguments. */ + void open( const Pathname & script_r, const Arguments & args_r ); + + /** Close any open connection. */ + int close(); + + public: + /** Send a \ref PluginFrame. + * \throw PluginScriptNotConnected + * \throw PluginScriptSendTimeout + * \throw PluginScriptDiedUnexpectedly (does not \ref close) + * \throw PluginScriptException on error + * + */ + void send( const PluginFrame & frame_r ) const; + + /** Receive a \ref PluginFrame. + * \throw PluginScriptNotConnected + * \throw PluginScriptReceiveTimeout + * \throw PluginScriptDiedUnexpectedly (does not \ref close) + * \throw PluginScriptException on error + */ + PluginFrame receive() const; + + public: + /** Implementation. */ + struct Impl; + private: + /** Pointer to implementation. */ + RW_pointer _pimpl; + }; + + /** \relates PluginScript Stream output */ + std::ostream & operator<<( std::ostream & str, const PluginScript & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PLUGINSCRIPT_H diff --git a/zypp/PluginScriptException.cc b/zypp/PluginScriptException.cc new file mode 100644 index 0000000..6d657ff --- /dev/null +++ b/zypp/PluginScriptException.cc @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginScriptException.cc + * +*/ +#include +//#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + PluginScriptException::PluginScriptException() + : Exception( "PluginScriptException" ) + {} + + PluginScriptException::PluginScriptException( const std::string & msg_r ) + : Exception( msg_r ) + {} + + PluginScriptException::PluginScriptException( const std::string & msg_r, const std::string & hist_r ) + : Exception( msg_r ) + { addHistory( hist_r ); } + + PluginScriptException::~PluginScriptException() throw() + {} + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PluginScriptException.h b/zypp/PluginScriptException.h new file mode 100644 index 0000000..5b5a4b2 --- /dev/null +++ b/zypp/PluginScriptException.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PluginScriptException.h + * +*/ +#ifndef ZYPP_PLUGINSCRIPTEXCEPTION_H +#define ZYPP_PLUGINSCRIPTEXCEPTION_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Base class for \ref PluginScript \ref Exception. */ + class ZYPP_API PluginScriptException : public Exception + { + public: + PluginScriptException(); + PluginScriptException( const std::string & msg_r ); + PluginScriptException( const std::string & msg_r, const std::string & hist_r ); + ~PluginScriptException() throw() override; + }; + + /** Convenience macro to declare more specific PluginScriptExceptions. */ +#define declException( EXCP, BASE ) \ + class ZYPP_API EXCP : public BASE { \ + public: \ + EXCP() : BASE( #EXCP ) {} \ + EXCP( const std::string & msg_r ) : BASE( msg_r ) {} \ + EXCP( const std::string & msg_r, const std::string & hist_r ) : BASE( msg_r, hist_r ) {} \ + virtual ~EXCP() throw() {} \ + } + + /** Script connection not open. */ + declException( PluginScriptNotConnected, PluginScriptException ); + + /** Script died unexpectedly. */ + declException( PluginScriptDiedUnexpectedly, PluginScriptException ); + + + /** Communication timeout. */ + declException( PluginScriptTimeout, PluginScriptException ); + + /** Timeout while sending data. */ + declException( PluginScriptSendTimeout, PluginScriptTimeout ); + + /** Timeout while receiving data. */ + declException( PluginScriptReceiveTimeout, PluginScriptTimeout ); + +#undef declException + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PLUGINSCRIPTEXCEPTION_H diff --git a/zypp/PoolItem.cc b/zypp/PoolItem.cc new file mode 100644 index 0000000..9bdbf03 --- /dev/null +++ b/zypp/PoolItem.cc @@ -0,0 +1,234 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolItem.cc + * +*/ +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolItem::Impl + // + /** PoolItem implementation. + * \c _buddy handling: + * \li \c ==0 no buddy + * \li \c >0 this uses \c _buddy status + * \li \c <0 this status used by \c -_buddy + */ + struct PoolItem::Impl + { + public: + Impl() {} + + Impl( ResObject::constPtr &&res_r, + ResStatus &&status_r ) + : _status( std::move(status_r) ) + , _resolvable( std::move(res_r) ) + {} + + ResStatus & status() const + { return _buddy > 0 ? PoolItem(buddy()).status() : _status; } + + sat::Solvable buddy() const + { + if ( !_buddy ) + return sat::Solvable::noSolvable; + if ( _buddy < 0 ) + return sat::Solvable( -_buddy ); + return sat::Solvable( _buddy ); + } + + void setBuddy( const sat::Solvable & solv_r ); + + ResObject::constPtr resolvable() const + { return _resolvable; } + + ResStatus & statusReset() const + { + _status.setLock( false, zypp::ResStatus::USER ); + _status.resetTransact( zypp::ResStatus::USER ); + return _status; + } + + ResStatus & statusReinit() const + { + _status.setLock( _status.isUserLockQueryMatch(), zypp::ResStatus::USER ); + _status.resetTransact( zypp::ResStatus::USER ); + return _status; + } + + public: + bool isUndetermined() const + { + return status().isUndetermined(); + } + + bool isRelevant() const + { + return !status().isNonRelevant(); + } + + bool isSatisfied() const + { + return status().isSatisfied(); + } + + bool isBroken() const + { + return status().isBroken(); + } + + bool isNeeded() const + { + return status().isToBeInstalled() || ( isBroken() && ! status().isLocked() ); + } + + bool isUnwanted() const + { + return isBroken() && status().isLocked(); + } + + private: + mutable ResStatus _status; + ResObject::constPtr _resolvable; + DefaultIntegral _buddy; + + /** \name Poor man's save/restore state. + * \todo There may be better save/restore state strategies. + */ + //@{ + public: + void saveState() const + { _savedStatus = status(); } + void restoreState() const + { status() = _savedStatus; } + bool sameState() const + { + if ( status() == _savedStatus ) + return true; + // some bits changed... + if ( status().getTransactValue() != _savedStatus.getTransactValue() + && ( ! status().isBySolver() // ignore solver state changes + // removing a user lock also goes to bySolver + || _savedStatus.getTransactValue() == ResStatus::LOCKED ) ) + return false; + if ( status().isLicenceConfirmed() != _savedStatus.isLicenceConfirmed() ) + return false; + return true; + } + private: + mutable ResStatus _savedStatus; + //@} + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PoolItem::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const PoolItem::Impl & obj ) + { + str << obj.status(); + if (obj.resolvable()) + str << *obj.resolvable(); + else + str << "(NULL)"; + return str; + } + + inline void PoolItem::Impl::setBuddy( const sat::Solvable & solv_r ) + { + PoolItem myBuddy( solv_r ); + if ( myBuddy ) + { + if ( myBuddy._pimpl->_buddy ) + { + ERR << *this << " would be buddy2 in " << myBuddy << endl; + return; + } + myBuddy._pimpl->_buddy = -resolvable()->satSolvable().id(); + _buddy = myBuddy.satSolvable().id(); + DBG << *this << " has buddy " << myBuddy << endl; + } + } + + /////////////////////////////////////////////////////////////////// + // class PoolItem + /////////////////////////////////////////////////////////////////// + + PoolItem::PoolItem() + : _pimpl( Impl::nullimpl() ) + {} + + PoolItem::PoolItem( const sat::Solvable & solvable_r ) + : _pimpl( ResPool::instance().find( solvable_r )._pimpl ) + {} + + PoolItem::PoolItem( const ResObject::constPtr & resolvable_r ) + : _pimpl( ResPool::instance().find( resolvable_r )._pimpl ) + {} + + PoolItem::PoolItem( Impl * implptr_r ) + : _pimpl( implptr_r ) + {} + + PoolItem PoolItem::makePoolItem( const sat::Solvable & solvable_r ) + { + return PoolItem( new Impl( makeResObject( solvable_r ), solvable_r.isSystem() ) ); + } + + PoolItem::~PoolItem() + {} + + ResPool PoolItem::pool() const + { return ResPool::instance(); } + + + ResStatus & PoolItem::status() const { return _pimpl->status(); } + ResStatus & PoolItem::statusReset() const { return _pimpl->statusReset(); } + ResStatus & PoolItem::statusReinit() const { return _pimpl->statusReinit(); } + sat::Solvable PoolItem::buddy() const { return _pimpl->buddy(); } + void PoolItem::setBuddy( const sat::Solvable & solv_r ) { _pimpl->setBuddy( solv_r ); } + bool PoolItem::isUndetermined() const { return _pimpl->isUndetermined(); } + bool PoolItem::isRelevant() const { return _pimpl->isRelevant(); } + bool PoolItem::isSatisfied() const { return _pimpl->isSatisfied(); } + bool PoolItem::isBroken() const { return _pimpl->isBroken(); } + bool PoolItem::isNeeded() const { return _pimpl->isNeeded(); } + bool PoolItem::isUnwanted() const { return _pimpl->isUnwanted(); } + + void PoolItem::saveState() const { _pimpl->saveState(); } + void PoolItem::restoreState() const { _pimpl->restoreState(); } + bool PoolItem::sameState() const { return _pimpl->sameState(); } + ResObject::constPtr PoolItem::resolvable() const { return _pimpl->resolvable(); } + + + std::ostream & operator<<( std::ostream & str, const PoolItem & obj ) + { return str << *obj._pimpl; } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PoolItem.h b/zypp/PoolItem.h new file mode 100644 index 0000000..1613bb5 --- /dev/null +++ b/zypp/PoolItem.h @@ -0,0 +1,213 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolItem.h + * +*/ +#ifndef ZYPP_POOLITEM_H +#define ZYPP_POOLITEM_H + +#include +#include + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + class ResPool; + namespace pool + { + class PoolImpl; + } + /////////////////////////////////////////////////////////////////// + /// \class PoolItem + /// \brief Combining \ref sat::Solvable and \ref ResStatus. + /// + /// The "real" PoolItem is usually somewhere in the ResPool. This is + /// a reference to it. All copies made will reference (and modify) + /// the same PoolItem. All changes via a PoolItem are immediately + /// visible in all copies (now COW). + /// + /// \note PoolItem is a SolvableType, which provides direct access to + /// many of the underlying sat::Solvables properties. + /// \see \ref sat::SolvableType + /// + /// \note Constness: Like pointer types, a const PoolItem + /// does \b not refer to a const PoolItem. The reference is + /// \c const, i.e. you can't change the refered PoolItem. The PoolItem + /// (i.e. the status) is always mutable. + /////////////////////////////////////////////////////////////////// + class ZYPP_API PoolItem : public sat::SolvableType + { + friend std::ostream & operator<<( std::ostream & str, const PoolItem & obj ); + public: + /** Default ctor for use in std::container. */ + PoolItem(); + + /** Ctor looking up the \ref sat::Solvable in the \ref ResPool. */ + explicit PoolItem( const sat::Solvable & solvable_r ); + + /** Ctor looking up the \ref sat::Solvable in the \ref ResPool. */ + template + explicit PoolItem( const SolvableType & solvable_r ) + : PoolItem( solvable_r.satSolvable() ) + {} + + /** Ctor looking up the \ref ResObject in the \ref ResPool. */ + explicit PoolItem( const ResObject::constPtr & resolvable_r ); + + /** Dtor */ + ~PoolItem(); + + public: + /** \name Status related methods. */ + //@{ + /** Returns the current status. */ + ResStatus & status() const; + + /** Resets status to the default state (KEEP_STATE bySOLVER; clears any lock!). */ + ResStatus & statusReset() const; + + /** Resets status to it's initial state in the ResPool (KEEP_STATE bySOLVER or LOCKED byUSER). + * The state depends on whether the PoolItem matched a hard lock defined + * in /etc/zypp/locks or not. + */ + ResStatus & statusReinit() const; + //@} + + + /** \name Status validation. + * Performed for non-packages. + */ + //@{ + /** No validation is performed for packages. */ + bool isUndetermined() const; + + /** Returns true if the solvable is relevant which means e.g. for patches + * that at least one package of the patch is installed. + */ + bool isRelevant() const; + + /** Whether a relevant items requirements are met. */ + bool isSatisfied() const; + + /** Whether a relevant items requirements are broken. */ + bool isBroken() const; + + /** This includes \c unlocked broken patches, as well as those already + * selected to be installed (otherwise classified as \c satisfied). + */ + bool isNeeded() const; + + /** Broken (needed) but locked patches. */ + bool isUnwanted() const; + //@} + + public: + /** Return the \ref ResPool the item belongs to. */ + ResPool pool() const; + + /** This is a \ref sat::SolvableType. */ + explicit operator sat::Solvable() const + { return resolvable() ? resolvable()->satSolvable() : sat::Solvable::noSolvable; } + + /** Return the buddy we share our status object with. + * A \ref Product e.g. may share its status with an associated reference \ref Package. + */ + sat::Solvable buddy() const; + + public: + /** Returns the ResObject::constPtr. + * \see \ref operator-> + */ + ResObject::constPtr resolvable() const; + + /** Implicit conversion into ResObject::constPtr to + * support query filters operating on ResObject. + */ + operator ResObject::constPtr() const + { return resolvable(); } + + /** Forward \c -> access to ResObject. */ + ResObject::constPtr operator->() const + { return resolvable(); } + + private: + friend class pool::PoolImpl; + /** \ref PoolItem generator for \ref pool::PoolImpl. */ + static PoolItem makePoolItem( const sat::Solvable & solvable_r ); + /** Buddies are set by \ref pool::PoolImpl.*/ + void setBuddy( const sat::Solvable & solv_r ); + /** internal ctor */ + public: + struct Impl; ///< Expose type only + private: + explicit PoolItem( Impl * implptr_r ); + /** Pointer to implementation */ + RW_pointer _pimpl; + + private: + /** \name tmp hack for save/restore state. */ + /** \todo get rid of it. */ + //@{ + friend struct PoolItemSaver; + void saveState() const; + void restoreState() const; + bool sameState() const; + //@} + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PoolItem Stream output */ + std::ostream & operator<<( std::ostream & str, const PoolItem & obj ) ZYPP_API; + + /** \relates PoolItem Required to disambiguate vs. (PoolItem,ResObject::constPtr) due to implicit PoolItem::operator ResObject::constPtr */ + inline bool operator==( const PoolItem & lhs, const PoolItem & rhs ) + { return lhs.resolvable() == rhs.resolvable(); } + + /** \relates PoolItem Convenience compare */ + inline bool operator==( const PoolItem & lhs, const ResObject::constPtr & rhs ) + { return lhs.resolvable() == rhs; } + + /** \relates PoolItem Convenience compare */ + inline bool operator==( const ResObject::constPtr & lhs, const PoolItem & rhs ) + { return lhs == rhs.resolvable(); } + + + /** \relates PoolItem Required to disambiguate vs. (PoolItem,ResObject::constPtr) due to implicit PoolItem::operator ResObject::constPtr */ + inline bool operator!=( const PoolItem & lhs, const PoolItem & rhs ) + { return ! (lhs==rhs); } + + /** \relates PoolItem Convenience compare */ + inline bool operator!=( const PoolItem & lhs, const ResObject::constPtr & rhs ) + { return ! (lhs==rhs); } + + /** \relates PoolItem Convenience compare */ + inline bool operator!=( const ResObject::constPtr & lhs, const PoolItem & rhs ) + { return ! (lhs==rhs); } + + /** Solvable to PoolItem transform functor. + * \relates PoolItem + * \relates sat::SolvIterMixin + */ + struct asPoolItem + { + using result_type = PoolItem; + + PoolItem operator()( const sat::Solvable & solv_r ) const + { return PoolItem( solv_r ); } + }; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_POOLITEM_H diff --git a/zypp/PoolItemBest.cc b/zypp/PoolItemBest.cc new file mode 100644 index 0000000..68836f1 --- /dev/null +++ b/zypp/PoolItemBest.cc @@ -0,0 +1,104 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolItemBest.cc + * +*/ +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolItemBest::Impl + // + /** PoolItemBest implementation. */ + struct PoolItemBest::Impl + { + Impl( bool preferNotLocked_r ) + : _preferNotLocked { preferNotLocked_r } + {} + + Container _container; + bool _preferNotLocked; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolItemBest + // + /////////////////////////////////////////////////////////////////// + + void PoolItemBest::_ctor_init( bool preferNotLocked_r ) + { _dont_use_this_use_pimpl.reset( new RWCOW_pointer(new Impl( preferNotLocked_r )) ); } + + void PoolItemBest::_ctor_init() + { _ctor_init( /*preferNotLocked*/false ); } + + const PoolItemBest::Container & PoolItemBest::container() const + { return pimpl()->_container; } + + void PoolItemBest::add( const PoolItem & pi_r ) + { + Container & container( pimpl()->_container ); + + PoolItem & ccand( container[pi_r.satSolvable().ident()] ); + if ( ! ccand ) + ccand = pi_r; + else if ( pimpl()->_preferNotLocked ) + { + if ( ! pi_r.status().isLocked() ) + { + if ( ccand.status().isLocked() || ui::SelectableTraits::AVOrder()( pi_r, ccand ) ) + ccand = pi_r; + } + else if ( ccand.status().isLocked() ) + { + if ( ui::SelectableTraits::AVOrder()( pi_r, ccand ) ) + ccand = pi_r; + } + } + else if ( ui::SelectableTraits::AVOrder()( pi_r, ccand ) ) + ccand = pi_r; + } + + PoolItem PoolItemBest::find( IdString ident_r ) const + { + const Container & container( pimpl()->_container ); + Container::const_iterator it( container.find( ident_r ) ); + return it != container.end() ? it->second : PoolItem(); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const PoolItemBest & obj ) + { + return dumpRange( str << "(" << obj.size() << ") ", obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PoolItemBest.h b/zypp/PoolItemBest.h new file mode 100644 index 0000000..0dfff9a --- /dev/null +++ b/zypp/PoolItemBest.h @@ -0,0 +1,163 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolItemBest.h + * +*/ +#ifndef ZYPP_POOLITEMBEST_H +#define ZYPP_POOLITEMBEST_H + +#include + +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolItemBest + // + /** Find the best candidates e.g. in a \ref PoolQuery result. + * + * The class basically maintains a \c map and remembers + * for each \c ident (\ref sat::Solvable::ident) the best \ref PoolItem that + * was added. + * + * The default \ref Predicate to determine the best choice is the same that + * sorts the \ref ui::Selectable list of available objects, thus follows the + * same rules the \ref resolver will apply. + * + * Ctor argument \ref preferNotLocked causes locked packages to be considered + * less than not locked packages. + * + * \code + * PoolQuery q; + * q.addAttribute(sat::SolvAttr::name, "lib*"); + * q.setMatchGlob(); + * + * // get the best matches and tag them for installation: + * PoolItemBest bestMatches( q.begin(), q.end() ); + * if ( ! bestMatches.empty() ) + * { + * for_( it, bestMatches.begin(), bestMatches.end() ) + * { + * ui::asSelectable()( *it )->setOnSystem( *it, ResStatus::USER ); + * } + * } + * \endcode + * + * \todo Support arbitrary Predicates. + */ + class ZYPP_API PoolItemBest + { + using Container = std::unordered_map; + public: + /** Predicate returning \c True if \a lhs is a better choice. */ + using Predicate = boost::function; + + using size_type = Container::size_type; + using value_type = Container::value_type; + using iterator = MapKVIteratorTraits::Value_const_iterator; + using ident_iterator = MapKVIteratorTraits::Key_const_iterator; + + public: + /** Indicator argument for ctor: consider locked packages less than not locked packages. */ + static constexpr bool preferNotLocked = true; + + public: + /** Default ctor. */ + PoolItemBest( bool preferNotLocked_r = false ) + { _ctor_init( preferNotLocked_r ); } + + /** Ctor feeding a \ref sat::Solvable. */ + PoolItemBest( sat::Solvable slv_r, bool preferNotLocked_r = false ) + { _ctor_init( preferNotLocked_r ); add( slv_r ); } + + /** Ctor feeding a \ref PoolItem. */ + PoolItemBest( const PoolItem & pi_r, bool preferNotLocked_r = false ) + { _ctor_init( preferNotLocked_r ); add( pi_r ); } + + /** Ctor feeding a range of \ref sat::Solvable or \ref PoolItem. */ + template + PoolItemBest( TIterator begin_r, TIterator end_r, bool preferNotLocked_r = false ) + { _ctor_init( preferNotLocked_r ); add( begin_r, end_r ); } + + public: + /** Feed one \ref sat::Solvable. */ + void add( sat::Solvable slv_r ) + { add( PoolItem( slv_r ) ); } + + /** Feed one \ref PoolItem. */ + void add( const PoolItem & pi_r ); + + /** Feed a range of \ref sat::Solvable or \ref PoolItem. */ + template + void add( TIterator begin_r, TIterator end_r ) + { + for_( it, begin_r, end_r ) + add( *it ); + } + + public: + /** \name Iterate the collected PoolItems. */ + //@{ + /** Whether PoolItems were collected. */ + bool empty() const { return container().empty(); } + /** Number of PoolItems collected. */ + size_type size() const { return container().size(); } + /** Pointer to the first PoolItem. */ + iterator begin() const { return make_map_value_begin( container() ); } + /** Pointer behind the last PoolItem. */ + iterator end() const { return make_map_value_end( container() ); } + + /** Return the collected \ref PoolItem with \ref sat::Solvable::ident \a ident_r. */ + PoolItem find( IdString ident_r ) const; + /** \overload Use Solvables ident string. */ + PoolItem find( sat::Solvable slv_r ) const { return find( slv_r.ident() ); } + /** \overload Use PoolItems ident string. */ + PoolItem find( const PoolItem & pi_r ) const { return find( pi_r.satSolvable().ident() ); } + //@} + + /** \name Iterate the collected PoolItems ident strings. */ + //@{ + /** Pointer to the first item. */ + ident_iterator identBegin() const { return make_map_key_begin( container() ); } + /** Pointer behind the last item. */ + ident_iterator identEnd() const { return make_map_key_end( container() ); } + //@} + + private: + void _ctor_init( bool preferNotLocked_r ); + void _ctor_init(/*preferNotLocked = false*/); ///< bin.compat legacy + const Container & container() const; + private: + /** Implementation */ + struct Impl; + /** Pointer to implementation */ + RWCOW_pointer & pimpl() { return *(reinterpret_cast*>( _dont_use_this_use_pimpl.get() )); } + /** Pointer to implementation */ + const RWCOW_pointer & pimpl() const { return *(reinterpret_cast*>( _dont_use_this_use_pimpl.get() )); } + /** Avoid need to include Impl definition when inlined ctors (due to tepmlate) are provided. */ + shared_ptr _dont_use_this_use_pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PoolItemBest Stream output */ + std::ostream & operator<<( std::ostream & str, const PoolItemBest & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_POOLITEMBEST_H diff --git a/zypp/PoolQuery.cc b/zypp/PoolQuery.cc new file mode 100644 index 0000000..feec7b4 --- /dev/null +++ b/zypp/PoolQuery.cc @@ -0,0 +1,1863 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolQuery.cc + * +*/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "PoolQuery" + +using std::endl; +using namespace zypp::sat; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + // some Helpers and Predicates + ///////////////////////////////////////////////////////////////// + + bool isDependencyAttribute( const sat::SolvAttr& attr_r ) + { + static sat::SolvAttr deps[] = { + SolvAttr::provides, + SolvAttr::requires, + SolvAttr::recommends, + SolvAttr::obsoletes, + SolvAttr::conflicts, + SolvAttr::suggests, + SolvAttr::supplements, + SolvAttr::enhances, + }; + for_( it, arrayBegin(deps), arrayEnd(deps) ) + if ( *it == attr_r ) + return true; + return false; + } + + /** Whether the current capabilities edition range ovelaps and/or its solvables arch matches. + * Query asserts \a iter_r points to a capability and we + * have to check the range only. + */ + struct EditionRangePredicate + { + EditionRangePredicate( const Rel & op, const Edition & edition ) + : _range( op, edition ) + , _arch( Arch_empty ) + {} + EditionRangePredicate( const Rel & op, const Edition & edition, const Arch & arch ) + : _range( op, edition ) + , _arch( arch ) + {} + + bool operator()( const sat::LookupAttr::iterator& iter_r ) + { + if ( !_arch.empty() && iter_r.inSolvable().arch() != _arch ) + return false; + + CapDetail cap( iter_r.id() ); + if ( ! cap.isSimple() ) + return false; + if ( cap.isNamed() ) // no range to match + return true; + return overlaps( Edition::MatchRange( cap.op(), cap.ed() ), _range ); + } + + std::string serialize() const + { + std::string ret( "EditionRange" ); + str::appendEscaped( ret, _range.op.asString() ); + str::appendEscaped( ret, _range.value.asString() ); + str::appendEscaped( ret, _arch.asString() ); + return ret; + } + + Edition::MatchRange _range; + Arch _arch; + }; + + /** Whether the current Solvables edition is within a given range and/or its arch matches. */ + struct SolvableRangePredicate + { + SolvableRangePredicate( const Rel & op, const Edition & edition ) + : _range( op, edition ) + , _arch( Arch_empty ) + {} + + SolvableRangePredicate( const Rel & op, const Edition & edition, const Arch & arch ) + : _range( op, edition ) + , _arch( arch ) + {} + + bool operator()( const sat::LookupAttr::iterator& iter_r ) + { + if ( !_arch.empty() && iter_r.inSolvable().arch() != _arch ) + return false; + return overlaps( Edition::MatchRange( Rel::EQ, iter_r.inSolvable().edition() ), _range ); + } + + std::string serialize() const + { + std::string ret( "SolvableRange" ); + str::appendEscaped( ret, _range.op.asString() ); + str::appendEscaped( ret, _range.value.asString() ); + str::appendEscaped( ret, _arch.asString() ); + return ret; + } + + Edition::MatchRange _range; + Arch _arch; + }; + + /** Whether the current capability matches a given one. + * Query asserts \a iter_r points to a capability and we + * have to check the match only. + */ + struct CapabilityMatchPredicate + { + CapabilityMatchPredicate( Capability cap_r ) + : _cap( cap_r ) + {} + + bool operator()( const sat::LookupAttr::iterator& iter_r ) const + { + return _cap.matches( iter_r.asType() ) == CapMatch::yes; + } + + std::string serialize() const + { + std::string ret( "CapabilityMatch" ); + str::appendEscaped( ret, _cap.asString() ); + return ret; + } + + Capability _cap; + }; + + ///////////////////////////////////////////////////////////////// + // + ///////////////////////////////////////////////////////////////// + /** Match data per attribtue. + * + * This includes the attribute itself, an optional \ref StrMatcher + * to restrict the query to certain string values, and an optional + * boolean \ref Predicate that may apply further restrictions that can + * not be expressed by the \ref strMatcher. + * + * Example for such a \ref predicate would be an additional edition range + * check whan looking for dependencies. The \ref strMatcher would + * find potential matches by looking at the dependencies name, the + * predicate will then check the edition ranges. + * + * As the \ref predicate takes an iterator pointing to the current + * match, it's also suitable for sub-structure (flexarray) inspection + * (\see \ref sat::LookupAttr::iterator::solvAttrSubEntry). + * + * (bsc#1035729) If SolvAttr::name searches for an explicit \c kind:name, + * this \c kind is stored in \ref kindPredicate and will overwrite any + * 'global' kind restriction applied via \ref PoolQuery::addKind. This + * task can't be passed off to a predicate, as \ref PoolQueryMatcher::isAMatch + * must accept only explicit-kind-checking predicate matches, in case the + * 'global' kind restriction woudl otherwise discard the match. + * + * \note: \see \ref addPredicate for further constraints. + */ + struct AttrMatchData + { + using Predicate = function; + + static bool always( const sat::LookupAttr::iterator& ) { return true; } + static bool never( const sat::LookupAttr::iterator& ) { return false; } + + AttrMatchData() + {} + + AttrMatchData( sat::SolvAttr attr_r ) + : attr(std::move( attr_r )) + {} + + AttrMatchData( sat::SolvAttr attr_r, StrMatcher strMatcher_r ) + : attr(std::move( attr_r )) + , strMatcher(std::move( strMatcher_r )) + {} + + AttrMatchData( sat::SolvAttr attr_r, StrMatcher strMatcher_r, + Predicate predicate_r, std::string predicateStr_r ) + : attr(std::move( attr_r )) + , strMatcher(std::move( strMatcher_r )) + , predicate(std::move( predicate_r )) + , predicateStr(std::move( predicateStr_r )) + {} + + /** A usable Predicate must provide a string serialization. + * As there is no \c operator== for \ref Predicate, we compare its + * string representation instead. If you add new predicate, check the + * deserialization code in \ref deserialize. + */ + template + void addPredicate( const TPredicate & predicate_r ) + { + predicate = predicate_r; + predicateStr = predicate_r.serialize(); + } + + /** Dumb serialization. + * \code + * AttrMatchData ATTRIBUTE SEARCHSTRING [C|SEARCHMODE|X] SERIALIZED_PREDICATE + * \endcode + */ + std::string serialize() const + { + std::string ret( "AttrMatchData" ); + str::appendEscaped( ret, attr.asString() ); + str::appendEscaped( ret, strMatcher.searchstring() ); + str::appendEscaped( ret, serializeMode( strMatcher.flags().mode() ) ); + str::appendEscaped( ret, predicateStr ); + return ret; + } + + /** Dumb restore from serialized string. + * \throw Exception on parse error. + */ + static AttrMatchData deserialize( const std::string & str_r ) + { + std::vector words; + str::splitEscaped( str_r, std::back_inserter(words) ); + if ( words.empty() || words[0] != "AttrMatchData" ) + ZYPP_THROW( Exception( str::Str() << "Expecting AttrMatchData: " << str_r ) ); + if ( words.size() != 5 ) + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + + AttrMatchData ret; + ret.attr = sat::SolvAttr( words[1] ); + ret.strMatcher = StrMatcher( words[2] ); + if ( Match::Mode mode = deserializeMode( words[3] ) ) + ret.strMatcher.setFlags( mode ); + ret.predicateStr = words[4]; + + // now the predicate + words.clear(); + str::splitEscaped( ret.predicateStr, std::back_inserter(words) ); + if ( ! words.empty() ) + { + if ( words[0] == "EditionRange" ) + { + switch( words.size() ) + { + case 3: + ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]) ); + break; + case 4: + ret.predicate = EditionRangePredicate( Rel(words[1]), Edition(words[2]), Arch(words[3]) ); + break; + default: + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + break; + } + } + else if ( words[0] == "SolvableRange" ) + { + switch( words.size() ) + { + case 3: + ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]) ); + break; + case 4: + ret.predicate = SolvableRangePredicate( Rel(words[1]), Edition(words[2]), Arch(words[3]) ); + break; + default: + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + break; + } + } + else if ( words[0] == "CapabilityMatch" ) + { + if ( words.size() != 2 ) + ZYPP_THROW( Exception( str::Str() << "Wrong number of words: " << str_r ) ); + ret.predicate = CapabilityMatchPredicate( Capability(words[1]) ); + } + else + ZYPP_THROW( Exception( str::Str() << "Unknown predicate: " << str_r ) ); + } + return ret; + } + + sat::SolvAttr attr; + StrMatcher strMatcher; + Predicate predicate; + std::string predicateStr; + ResKind kindPredicate = ResKind::nokind; // holds the 'kind' part if SolvAttr:name looks for an explicit 'kind:name' + + private: + /** Serialize \ref strMatcher \ref Match::Mode */ + static std::string serializeMode( Match::Mode mode_r ) + { + // Legacy code used "[C|X]" to differ just between OTHER (need to (C)ompile) and + // using the default search mode. As we now allow to specify a SEARCHMODE we + // need to serialize it: + switch ( mode_r ) + { +#define OUTS(M,S) case Match::M: return #S; break + // (C)ompile + OUTS( OTHER, C ); + // well known modes: + OUTS( STRING, T ); + OUTS( STRINGSTART, S ); + OUTS( STRINGEND, E ); + OUTS( SUBSTRING, B ); + OUTS( GLOB, G ); + OUTS( REGEX, R ); +#undef OUTS + // everything else use default + case Match::NOTHING: + break; + } + return "X"; + } + + /** Deserialize \ref strMatcher \ref Match::Mode */ + static Match::Mode deserializeMode( const std::string & str_r ) + { + switch ( str_r[0] ) + { +#define OUTS(M,C) case *#C: return Match::M; break + // (C)ompile + OUTS( OTHER, C ); + // well known modes: + OUTS( STRING, T ); + OUTS( STRINGSTART, S ); + OUTS( STRINGEND, E ); + OUTS( SUBSTRING, B ); + OUTS( GLOB, G ); + OUTS( REGEX, R ); +#undef OUTS + // everything else use default + default: + break; + } + return Match::NOTHING; + } + }; + + /** \relates AttrMatchData */ + inline std::ostream & operator<<( std::ostream & str, const AttrMatchData & obj ) + { + str << obj.attr << ": " << obj.strMatcher; + if ( obj.kindPredicate ) + str << " +(" << obj.kindPredicate << ")"; + if ( obj.predicate ) + str << " +(" << obj.predicateStr << ")"; + return str; + } + + /** \relates AttrMatchData */ + inline bool operator==( const AttrMatchData & lhs, const AttrMatchData & rhs ) + { + return ( lhs.attr == rhs.attr + && lhs.strMatcher == rhs.strMatcher + && lhs.predicateStr == rhs.predicateStr ); + } + + /** \relates AttrMatchData */ + inline bool operator!=( const AttrMatchData & lhs, const AttrMatchData & rhs ) + { return !( lhs == rhs ); } + + /** \relates AttrMatchData Arbitrary order for std::container. */ + inline bool operator<( const AttrMatchData & lhs, const AttrMatchData & rhs ) + { + if ( lhs.attr != rhs.attr ) + return ( lhs.attr < rhs.attr ); + if ( lhs.strMatcher != rhs.strMatcher ) + return ( lhs.strMatcher < rhs.strMatcher ); + if ( lhs.predicateStr != rhs.predicateStr ) + return ( lhs.predicateStr < rhs.predicateStr ); + return false; + } + + using AttrMatchList = std::list; + + + } ///////////////////////////////////////////////////////////////// + // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolQuery::Impl + // + /** */ + class PoolQuery::Impl + { + public: + Impl() + : _flags( Match::SUBSTRING | Match::NOCASE | Match::SKIP_KIND ) + , _match_word(false) + , _status_flags(ALL) + {} + + Impl(const Impl &) = default; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() {} + + public: + /** String representation */ + std::string asString() const; + + /** \name Raw query options. */ + //@{ + /** Raw search strings. */ + StrContainer _strings; + /** Raw attributes */ + AttrRawStrMap _attrs; + /** Uncompiled attributes with predicate. */ + std::set _uncompiledPredicated; + + /** Sat solver search flags */ + Match _flags; + bool _match_word; + + /** Sat solver status flags */ + StatusFilter _status_flags; + + /** Edition condition operand */ + Edition _edition; + /** Operator for edition condition */ + Rel _op; + + /** Repos to search. */ + StrContainer _repos; + + /** Kinds to search */ + Kinds _kinds; + + /** Optional comment string for serialization. */ + mutable std::string _comment; + //@} + + public: + + bool operator<( const PoolQuery::Impl & rhs ) const + { +#define OUTS(A) if ( A != rhs.A ) return A < rhs.A; + OUTS( _strings ); + OUTS( _attrs ); + OUTS( _uncompiledPredicated ); + OUTS( _flags.get() ); + OUTS( _match_word ); + OUTS( _status_flags ); + OUTS( _edition ); + OUTS( _op.inSwitch() ); + OUTS( _repos ); + OUTS( _kinds ); +#undef OUTS + return false; + } + + bool operator==( const PoolQuery::Impl & rhs ) const + { + if ( _flags == rhs._flags + // bnc#792901: while libzypp uses exact match mode for a single + // package name lock, zypper always uses glob. :( + // We unify those two forms to enable zypper to remove zypp locks + // without need to actually evaluate the query (which would require + // repos to be loaded). + || ( ( ( _flags.isModeString() && rhs._flags.isModeGlob() ) + || ( _flags.isModeGlob() && rhs._flags.isModeString() ) ) + && _strings.empty() + && _attrs.size() == 1 + && _attrs.begin()->first == sat::SolvAttr::name ) ) + { + // ma: Intentionally a different _comment is not considered. + return ( _strings == rhs._strings + && _attrs == rhs._attrs + && _uncompiledPredicated == rhs._uncompiledPredicated + && _match_word == rhs._match_word + && _status_flags == rhs._status_flags + && _edition == rhs._edition + && _op == rhs._op + && _repos == rhs._repos + && _kinds == rhs._kinds ); + } + return false; + } + + bool operator!=( const PoolQuery::Impl & rhs ) const + { return ! operator==( rhs ); } + + public: + /** Compile the regex. + * Basically building the \ref _attrMatchList from strings. + * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile. + */ + void compile() const; + + /** StrMatcher per attribtue. */ + mutable AttrMatchList _attrMatchList; + + private: + /** Join patterns in \a container_r according to \a flags_r into a single \ref StrMatcher. + * The \ref StrMatcher returned will be a REGEX if more than one pattern was passed. + */ + StrMatcher joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + + /////////////////////////////////////////////////////////////////// + + struct MyInserter + { + MyInserter(PoolQuery::StrContainer & cont) : _cont(cont) {} + + bool operator()(const std::string & str) + { + _cont.insert(str); + return true; + } + + PoolQuery::StrContainer & _cont; + }; + + + struct EmptyFilter + { + bool operator()(const std::string & str) + { + return !str.empty(); + } + }; + + void PoolQuery::Impl::compile() const + { + _attrMatchList.clear(); + + if ( _flags.mode() == Match::OTHER ) // this will never succeed... + ZYPP_THROW( MatchUnknownModeException( _flags ) ); + + // 'different' - will have to iterate through all and match by ourselves (slow) + // 'same' - will pass the compiled string to dataiterator_init + // 'one-attr' - will pass it to dataiterator_init + // 'one-non-regex-str' - will pass to dataiterator_init, set flag to SEARCH_STRING or SEARCH_SUBSTRING + + // // NO ATTRIBUTE + // else + // for all _strings + // create regex; store in rcstrings; if more strings flag regex; + if (_attrs.empty()) + { + ; // A default 'query-all' will be added after all sources are processed. + } + + // // ONE ATTRIBUTE + // else if _attrs is not empty but it contains just one attr + // for all _strings and _attr[key] strings + // create regex; flag 'one-attr'; if more strings flag regex; + else if (_attrs.size() == 1) + { + StrContainer joined; + invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined)); + invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined)); + + _attrMatchList.push_back( AttrMatchData( _attrs.begin()->first, joinedStrMatcher( joined, _flags ) ) ); + } + + // // MULTIPLE ATTRIBUTES + else + { + // check whether there are any per-attribute strings + bool attrvals_empty = true; + for_( ai, _attrs.begin(), _attrs.end() ) + { + if ( ai->second.empty() ) + continue; + for_( it, ai->second.begin(), ai->second.end() ) + { + if ( !it->empty() ) + { + attrvals_empty = false; + break; + } + } + if ( ! attrvals_empty ) + break; + } + + // chceck whether the per-attribute strings are all the same + bool attrvals_thesame = true; + AttrRawStrMap::const_iterator ai = _attrs.begin(); + const StrContainer & set1 = ai->second; + ++ai; + for (; ai != _attrs.end(); ++ai) + { + StrContainer result; + set_difference( + set1.begin(), set1.end(), + ai->second.begin(), ai->second.end(), + inserter(result, result.begin())/*, ltstr()*/); + if (!result.empty()) + { + attrvals_thesame = false; + break; + } + } + + // // THE SAME STRINGS FOR DIFFERENT ATTRS + // else if _attrs is not empty but it does not contain strings + // for each key in _attrs take all _strings + // create regex; store in rcstrings; flag 'same'; if more strings flag regex; + if (attrvals_empty || attrvals_thesame) + { + StrContainer joined; + if (attrvals_empty) + { + invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined)); + } + else + { + invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined)); + invokeOnEach(_attrs.begin()->second.begin(), _attrs.begin()->second.end(), EmptyFilter(), MyInserter(joined)); + } + + // May use the same StrMatcher for all + StrMatcher matcher( joinedStrMatcher( joined, _flags ) ); + for_( ai, _attrs.begin(), _attrs.end() ) + { + _attrMatchList.push_back( AttrMatchData( ai->first, matcher ) ); + } + } + + // // DIFFERENT STRINGS FOR DIFFERENT ATTRS + // if _attrs is not empty and it contains non-empty vectors with non-empty strings + // for each key in _attrs take all _strings + all _attrs[key] strings + // create regex; flag 'different'; if more strings flag regex; + else + { + for_(ai, _attrs.begin(), _attrs.end()) + { + StrContainer joined; + invokeOnEach(_strings.begin(), _strings.end(), EmptyFilter(), MyInserter(joined)); + invokeOnEach(ai->second.begin(), ai->second.end(), EmptyFilter(), MyInserter(joined)); + + _attrMatchList.push_back( AttrMatchData( ai->first, joinedStrMatcher( joined, _flags ) ) ); + } + } + } + + // Now handle any predicated queries + if ( ! _uncompiledPredicated.empty() ) + { + StrContainer global; + invokeOnEach( _strings.begin(), _strings.end(), EmptyFilter(), MyInserter(global) ); + for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() ) + { + if ( it->strMatcher.flags().mode() == Match::OTHER ) + { + // need to compile: + StrContainer joined( global ); + const std::string & mstr( it->strMatcher.searchstring() ); + if ( ! mstr.empty() ) + joined.insert( mstr ); + + // copy and exchange the StrMatcher + AttrMatchData nattr( *it ); + nattr.strMatcher = joinedStrMatcher( joined, _flags ); + _attrMatchList.push_back( std::move(nattr) ); + } + else + { + // copy matcher + _attrMatchList.push_back( *it ); + } + } + } + + // If no attributes defined at all, then add 'query all' + if ( _attrMatchList.empty() ) + { + _attrMatchList.push_back( AttrMatchData( sat::SolvAttr::allAttr, joinedStrMatcher( _strings, _flags ) ) ); + } + + // Finally check here, whether all involved regex compile. + for_( it, _attrMatchList.begin(), _attrMatchList.end() ) + { + it->strMatcher.compile(); // throws on error + } + //DBG << asString() << endl; + } + + /////////////////////////////////////////////////////////////////// + namespace + { + /** Escape \a str_r for use in a regex. + * \a flags_r determines whether the input string is interpreted + * as regex, glob or plain string. + */ + std::string rxEscape( std::string str_r, const Match & flags_r ) + { + if ( str_r.empty() || flags_r.isModeRegex() ) + return str_r; + + if ( flags_r.isModeGlob() ) + return str::rxEscapeGlob( std::move(str_r) ); + + return str::rxEscapeStr( std::move(str_r) ); + } + } // namespace + /////////////////////////////////////////////////////////////////// + + StrMatcher PoolQuery::Impl::joinedStrMatcher( const StrContainer & container_r, const Match & flags_r ) const + { + if ( container_r.empty() ) + return StrMatcher( std::string(), flags_r ); + + if ( container_r.size() == 1 && !_match_word ) // use RX to match words + return StrMatcher( *container_r.begin(), flags_r ); + + // Convert to a regex. + // Note: Modes STRING and GLOB match whole strings (anchored ^ $) + // SUBSTRING and REGEX match substrings (match_word anchores SUBSTRING \b) + Match retflags( flags_r ); + retflags.setModeRegex(); + str::Str ret; + + if ( flags_r.isModeString() || flags_r.isModeGlob() ) + ret << "^"; + else if ( _match_word ) + ret << "\\b"; + + // (..|..|..) + char sep = '('; + for ( const::std::string & s : container_r ) + { + ret << sep << rxEscape( s, flags_r ); + if ( sep == '(' ) + sep = '|'; + } + ret << ')'; + + if ( flags_r.isModeString() || flags_r.isModeGlob() ) + ret << "$"; + else if ( _match_word ) + ret << "\\b"; + + return StrMatcher( ret, retflags ); + } + + std::string PoolQuery::Impl::asString() const + { + std::ostringstream o; + + o << "kinds: "; + if ( _kinds.empty() ) + o << "ALL"; + else + { + for(Kinds::const_iterator it = _kinds.begin(); + it != _kinds.end(); ++it) + o << *it << " "; + } + o << endl; + + o << "repos: "; + if ( _repos.empty() ) + o << "ALL"; + else + { + for(StrContainer::const_iterator it = _repos.begin(); + it != _repos.end(); ++it) + o << *it << " "; + } + o << endl; + + o << "version: "<< _op << " " << _edition.asString() << endl; + o << "status: " << ( _status_flags ? ( _status_flags == INSTALLED_ONLY ? "INSTALLED_ONLY" : "UNINSTALLED_ONLY" ) + : "ALL" ) << endl; + + o << "string match flags: " << Match(_flags) << endl; + + // raw + o << "strings: "; + for(StrContainer::const_iterator it = _strings.begin(); + it != _strings.end(); ++it) + o << *it << " "; + o << endl; + + o << "attributes: " << endl; + for(AttrRawStrMap::const_iterator ai = _attrs.begin(); ai != _attrs.end(); ++ai) + { + o << "* " << ai->first << ": "; + for(StrContainer::const_iterator vi = ai->second.begin(); + vi != ai->second.end(); ++vi) + o << *vi << " "; + o << endl; + } + + o << "predicated: " << endl; + for_( it, _uncompiledPredicated.begin(), _uncompiledPredicated.end() ) + { + o << "* " << *it << endl; + } + + // compiled + o << "last attribute matcher compiled: " << endl; + if ( _attrMatchList.empty() ) + { + o << "not yet compiled" << endl; + } + else + { + for_( it, _attrMatchList.begin(), _attrMatchList.end() ) + { + o << "* " << *it << endl; + } + } + return o.str(); + } + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolQuery + // + /////////////////////////////////////////////////////////////////// + + PoolQuery::PoolQuery() + : _pimpl(new Impl()) + {} + + PoolQuery::~PoolQuery() + {} + + void PoolQuery::addRepo(const std::string &repoalias) + { + if (repoalias.empty()) + { + WAR << "ignoring an empty repository alias" << endl; + return; + } + _pimpl->_repos.insert(repoalias); + } + + void PoolQuery::addKind(const ResKind & kind) + { _pimpl->_kinds.insert(kind); } + + void PoolQuery::setComment(const std::string & comment) const + { _pimpl->_comment = comment; } + + void PoolQuery::addString(const std::string & value) + { _pimpl->_strings.insert(value); } + + void PoolQuery::addAttribute(const sat::SolvAttr & attr, const std::string & value) + { _pimpl->_attrs[attr].insert(value); } + + void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition ) + { + // Default Match::OTHER indicates need to compile, i.e. to merge name into the global search string and mode. + return addDependency( attr, name, op, edition, Arch_empty, Match::OTHER ); + } + + void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch ) + { + // Default Match::OTHER indicates need to compile, i.e. to merge name into the global search string and mode. + return addDependency( attr, name, op, edition, arch, Match::OTHER ); + } + + void PoolQuery::addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch, Match::Mode mode ) + { + if ( op == Rel::NONE ) // will never match. + return; + + // SolvAttr::name with explicit 'kind:name' will overwrite the default _kinds + ResKind explicitKind; + if ( attr == sat::SolvAttr::name ) + explicitKind = ResKind::explicitBuiltin( name ); + + // Legacy: Match::OTHER and no additional constraints on edition/arch/kind + // require addAttribute, otherwise de-serialisation breaks (serialized + // and de-serialized query could be !=). + // From the results POV we could also use the predicated case below. + if ( op == Rel::ANY && arch.empty() && !explicitKind && mode == Match::OTHER ) + { + addAttribute( attr, name ); + return; + } + + // Match::OTHER indicates need to compile + // (merge global search strings into name). + AttrMatchData attrMatchData( attr ); + if ( !explicitKind ) + attrMatchData.strMatcher = StrMatcher( name, mode ); + else + { + // ResKind::explicitBuiltin call above asserts the presence of the ':' in name + attrMatchData.strMatcher = StrMatcher( strchr( name.c_str(), ':')+1, mode ); + attrMatchData.kindPredicate = explicitKind; + } + + if ( isDependencyAttribute( attr ) ) + attrMatchData.addPredicate( EditionRangePredicate( op, edition, arch ) ); + else + attrMatchData.addPredicate( SolvableRangePredicate( op, edition, arch ) ); + + _pimpl->_uncompiledPredicated.insert( attrMatchData ); + } + + void PoolQuery::addDependency( const sat::SolvAttr & attr, Capability cap_r ) + { + CapDetail cap( cap_r ); + if ( ! cap.isSimple() ) // will never match. + return; + + // Matches STRING per default. (won't get compiled!) + AttrMatchData attrMatchData( attr, StrMatcher( cap.name().asString() ) ); + + if ( isDependencyAttribute( attr ) ) + attrMatchData.addPredicate( CapabilityMatchPredicate( cap_r ) ); + else + attrMatchData.addPredicate( SolvableRangePredicate( cap.op(), cap.ed() ) ); + + _pimpl->_uncompiledPredicated.insert( attrMatchData ); + } + + void PoolQuery::setEdition(const Edition & edition, const Rel & op) + { + _pimpl->_edition = edition; + _pimpl->_op = op; + } + + void PoolQuery::setMatchSubstring() { _pimpl->_flags.setModeSubstring(); _pimpl->_match_word = false; } + void PoolQuery::setMatchExact() { _pimpl->_flags.setModeString(); _pimpl->_match_word = false; } + void PoolQuery::setMatchRegex() { _pimpl->_flags.setModeRegex(); _pimpl->_match_word = false; } + void PoolQuery::setMatchGlob() { _pimpl->_flags.setModeGlob(); _pimpl->_match_word = false; } + void PoolQuery::setMatchWord() { _pimpl->_flags.setModeSubstring(); _pimpl->_match_word = true; } + + Match PoolQuery::flags() const + { return _pimpl->_flags; } + void PoolQuery::setFlags( const Match & flags ) + { _pimpl->_flags = flags; } + + + void PoolQuery::setInstalledOnly() + { _pimpl->_status_flags = INSTALLED_ONLY; } + void PoolQuery::setUninstalledOnly() + { _pimpl->_status_flags = UNINSTALLED_ONLY; } + void PoolQuery::setStatusFilterFlags( PoolQuery::StatusFilter flags ) + { _pimpl->_status_flags = flags; } + + + const PoolQuery::StrContainer & + PoolQuery::strings() const + { return _pimpl->_strings; } + + const PoolQuery::AttrRawStrMap & + PoolQuery::attributes() const + { return _pimpl->_attrs; } + + const PoolQuery::StrContainer & + PoolQuery::attribute(const sat::SolvAttr & attr) const + { + static const PoolQuery::StrContainer nocontainer; + AttrRawStrMap::const_iterator it = _pimpl->_attrs.find(attr); + return it != _pimpl->_attrs.end() ? it->second : nocontainer; + } + + const Edition PoolQuery::edition() const + { return _pimpl->_edition; } + const Rel PoolQuery::editionRel() const + { return _pimpl->_op; } + + + const PoolQuery::Kinds & + PoolQuery::kinds() const + { return _pimpl->_kinds; } + + const PoolQuery::StrContainer & + PoolQuery::repos() const + { return _pimpl->_repos; } + + const std::string & + PoolQuery::comment() const + { return _pimpl->_comment; } + + bool PoolQuery::caseSensitive() const + { return !_pimpl->_flags.test( Match::NOCASE ); } + void PoolQuery::setCaseSensitive( bool value ) + { _pimpl->_flags.turn( Match::NOCASE, !value ); } + + bool PoolQuery::filesMatchFullPath() const + { return _pimpl->_flags.test( Match::FILES ); } + void PoolQuery::setFilesMatchFullPath( bool value ) + { _pimpl->_flags.turn( Match::FILES, value ); } + + bool PoolQuery::matchExact() const { return _pimpl->_flags.isModeString(); } + bool PoolQuery::matchSubstring() const { return _pimpl->_flags.isModeSubstring() && !_pimpl->_match_word; } + bool PoolQuery::matchGlob() const { return _pimpl->_flags.isModeGlob(); } + bool PoolQuery::matchRegex() const { return _pimpl->_flags.isModeRegex(); } + bool PoolQuery::matchWord() const { return _pimpl->_flags.isModeSubstring() && _pimpl->_match_word; } + + PoolQuery::StatusFilter PoolQuery::statusFilterFlags() const + { return _pimpl->_status_flags; } + + bool PoolQuery::empty() const + { + try { return begin() == end(); } + catch (const Exception & ex) {} + return true; + } + + PoolQuery::size_type PoolQuery::size() const + { + try + { + size_type count = 0; + for_( it, begin(), end() ) + ++count; + return count; + } + catch (const Exception & ex) {} + return 0; + } + + void PoolQuery::execute(ProcessResolvable fnc) + { invokeOnEach( begin(), end(), std::move(fnc)); } + + + /*DEPRECATED LEGACY:*/void PoolQuery::setRequireAll( bool ) {} + /*DEPRECATED LEGACY:*/bool PoolQuery::requireAll() const { return false; } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolQuery::Attr + // + /** + * represents all atributes in PoolQuery except SolvAtributes, which are + * used as is (not needed extend anything if someone adds new solv attr) + */ + struct PoolQueryAttr : public IdStringType + { + private: + friend class IdStringType; + IdString _str; + public: + + //noAttr + PoolQueryAttr(){} + + explicit PoolQueryAttr( const char* cstr_r ) + : _str( cstr_r ) + {} + + explicit PoolQueryAttr( const std::string & str_r ) + : _str( str_r ) + {} + + // unknown atributes + static const PoolQueryAttr noAttr; + + // PoolQuery's own attributes + static const PoolQueryAttr repoAttr; + static const PoolQueryAttr kindAttr; + static const PoolQueryAttr commentAttr; + static const PoolQueryAttr stringAttr; + static const PoolQueryAttr stringTypeAttr; + static const PoolQueryAttr requireAllAttr; // LEAGACY: attribute was defined but never implemented. + static const PoolQueryAttr caseSensitiveAttr; + static const PoolQueryAttr installStatusAttr; + static const PoolQueryAttr editionAttr; + static const PoolQueryAttr complexAttr; + }; + + const PoolQueryAttr PoolQueryAttr::noAttr; + + const PoolQueryAttr PoolQueryAttr::repoAttr( "repo" ); + const PoolQueryAttr PoolQueryAttr::kindAttr( "type" ); + const PoolQueryAttr PoolQueryAttr::commentAttr( "comment" ); + const PoolQueryAttr PoolQueryAttr::stringAttr( "query_string" ); + const PoolQueryAttr PoolQueryAttr::stringTypeAttr("match_type"); + const PoolQueryAttr PoolQueryAttr::requireAllAttr("require_all"); // LEAGACY: attribute was defined but never implemented. + const PoolQueryAttr PoolQueryAttr::caseSensitiveAttr("case_sensitive"); + const PoolQueryAttr PoolQueryAttr::installStatusAttr("install_status"); + const PoolQueryAttr PoolQueryAttr::editionAttr("version"); + const PoolQueryAttr PoolQueryAttr::complexAttr("complex"); + + class StringTypeAttr : public IdStringType + { + friend class IdStringType; + IdString _str; + + public: + StringTypeAttr(){} + explicit StringTypeAttr( const char* cstr_r ) + : _str( cstr_r ){} + explicit StringTypeAttr( const std::string & str_r ) + : _str( str_r ){} + + static const StringTypeAttr noAttr; + + static const StringTypeAttr exactAttr; + static const StringTypeAttr substringAttr; + static const StringTypeAttr regexAttr; + static const StringTypeAttr globAttr; + static const StringTypeAttr wordAttr; + }; + + const StringTypeAttr StringTypeAttr::noAttr; + + const StringTypeAttr StringTypeAttr::exactAttr("exact"); + const StringTypeAttr StringTypeAttr::substringAttr("substring"); + const StringTypeAttr StringTypeAttr::regexAttr("regex"); + const StringTypeAttr StringTypeAttr::globAttr("glob"); + const StringTypeAttr StringTypeAttr::wordAttr("word"); + + /////////////////////////////////////////////////////////////////// + + + //\TODO maybe ctor with stream can be useful + //\TODO let it throw, let it throw, let it throw. + bool PoolQuery::recover( std::istream &str, char delim ) + { + bool finded_something = false; //indicates some atributes is finded + std::string s; + do { + if ( str.eof() ) + break; + + getline( str, s, delim ); + + if ((!s.empty()) && s[0]=='#') //comment + { + continue; + } + + std::string::size_type pos = s.find(':'); + if (s.empty() || pos == s.npos) // some garbage on line... act like blank line + { + if (finded_something) //is first blank line after record? + { + break; + } + else + { + continue; + } + } + + finded_something = true; + + std::string attrName(str::trim(std::string(s,0,pos))); // trimmed name of atribute + std::string attrValue(str::trim(std::string(s,pos+1,s.npos))); //trimmed value + + PoolQueryAttr attribute( attrName ); + + if ( attribute==PoolQueryAttr::repoAttr ) + { + addRepo( attrValue ); + } + /* some backwards compatibility */ + else if ( attribute==PoolQueryAttr::kindAttr || attribute=="kind" ) + { + addKind( ResKind(attrValue) ); + } + else if ( attribute==PoolQueryAttr::commentAttr ) + { + setComment( attrValue ); + } + else if ( attribute==PoolQueryAttr::stringAttr + || attribute=="global_string") + { + addString( attrValue ); + } + else if ( attribute==PoolQueryAttr::stringTypeAttr + || attribute=="string_type" ) + { + StringTypeAttr s(attrValue); + if( s == StringTypeAttr::regexAttr ) + { + setMatchRegex(); + } + else if ( s == StringTypeAttr::globAttr ) + { + setMatchGlob(); + } + else if ( s == StringTypeAttr::exactAttr ) + { + setMatchExact(); + } + else if ( s == StringTypeAttr::substringAttr ) + { + setMatchSubstring(); + } + else if ( s == StringTypeAttr::wordAttr ) + { + setMatchWord(); + } + else if ( s == StringTypeAttr::noAttr ) + { + WAR << "unknown string type " << attrValue << endl; + } + else + { + WAR << "forget recover some attribute defined as String type attribute: " << attrValue << endl; + } + } + else if ( attribute==PoolQueryAttr::requireAllAttr ) + { + // LEAGACY: attribute was defined but never implemented. + // Actually it should not occur outside our testcases. + } + else if ( attribute==PoolQueryAttr::caseSensitiveAttr ) + { + if ( str::strToTrue(attrValue) ) + { + setCaseSensitive(true); + } + else if ( !str::strToFalse(attrValue) ) + { + setCaseSensitive(false); + } + else + { + WAR << "unknown boolean value " << attrValue << endl; + } + } + else if ( attribute==PoolQueryAttr::installStatusAttr ) + { + if( attrValue == "all" ) + { + setStatusFilterFlags( ALL ); + } + else if( attrValue == "installed" ) + { + setInstalledOnly(); + } + else if( attrValue == "not-installed" ) + { + setUninstalledOnly(); + } + else + { + WAR << "Unknown value for install status " << attrValue << endl; + } + } + else if ( attribute == PoolQueryAttr::editionAttr) + { + std::string::size_type pos = 0; + Rel rel("=="); + if (attrValue.find_first_of("=<>!") == 0) + { + pos = attrValue.find_last_of("=<>"); + rel = Rel(attrValue.substr(0, pos+1)); + attrValue = str::trim(attrValue.substr(pos+1, attrValue.npos)); + } + + setEdition(Edition(attrValue), rel); + } + else if ( attribute == PoolQueryAttr::complexAttr ) + { + try + { + _pimpl->_uncompiledPredicated.insert( AttrMatchData::deserialize( attrValue ) ); + } + catch ( const Exception & err ) + { + WAR << "Unparsable value for complex: " << err.asUserHistory() << endl; + + } + } + else if ( attribute==PoolQueryAttr::noAttr ) + { + WAR << "empty attribute name" << endl; + } + else + { + std::string s = attrName; + str::replaceAll( s,"_",":" ); + SolvAttr a(s); + if ( a == SolvAttr::name || isDependencyAttribute( a ) ) + { + Capability c( attrValue ); + CapDetail d( c ); + if ( d.isVersioned() ) + addDependency( a, d.name().asString(), d.op(), d.ed() ); + else + addDependency( a, attrValue ); + } + else + addAttribute( a, attrValue ); + } + + } while ( true ); + + // OLD STYLE VERSIONED LOCKS: + // solvable_name: kernel + // version: > 1 + // + // NEW STYLE VERSIONED LOCKS: + // complex: AttrMatchData solvable:name kernel C SolvableRange\ >\ 1\ \"\" + // or + // solvable_name: kernel > 1 + // + // Semantically equivalent as locks, but due to the different syntax + // the complex lock is wrongly handled by zypper. + // + // bsc#1112911: Unfortunately all styles are found in real-life locks-files. + // libzypp will try to make sure, when parsing the locks-file, that complex + // locks are rewritten into to OLD STYLE queries zypper can handle. + if ( !_pimpl->_attrs.count(SolvAttr::name) && _pimpl->_uncompiledPredicated.size() == 1 ) + { + // No OLD STYLE lock for SolvAttr::name and exactly one complex lock... + const AttrMatchData & attrmatch { *_pimpl->_uncompiledPredicated.begin() }; + if ( attrmatch.attr == SolvAttr::name && attrmatch.strMatcher.flags().mode() == Match::OTHER ) + { + // ...for SolvAttr::name and following the global search flags. + // A candidate for a rewrite? + + std::vector words; + str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) ); + if ( words.size() < 4 || words[3].empty() ) + { + // We have _NO_ arch rule in the complex predicate, so we can simplify it. + // + // NOTE: AFAIK it's not possible to create (or have created) a complex lock + // with arch rule with zypper means. Nevertheless, in case such a rule made it + // into a locks file, it's better to have a strange looking 'zypper locks' list + // than to lock the wrong packages. + // (and remember that you can't use "addAttribute( SolvAttr::arch, ... )" because + // attributes are `OR`ed) + + // kind + if ( attrmatch.kindPredicate ) + { + _pimpl->_kinds.clear(); // an explicit kind overwrites any global one + addKind( attrmatch.kindPredicate ); + } + + // name + addAttribute( SolvAttr::name, attrmatch.strMatcher.searchstring() ); + + // edition + std::vector words; + str::splitEscaped( attrmatch.predicateStr, std::back_inserter(words) ); + if ( ! words.empty() ) + { + if ( words[0] == "EditionRange" || words[0] == "SolvableRange" ) + { + setEdition( Edition(words[2]), Rel(words[1]) ); + } + } + + // finally remove the complex lock + _pimpl->_uncompiledPredicated.clear(); + } + } + } + + return finded_something; + } + + void PoolQuery::serialize( std::ostream &str, char delim ) const + { + //separating delim + str << delim; + //iterate thrue all settings and write it + static const zypp::PoolQuery q; //not save default options, so create default query example + + for_( it, repos().begin(), repos().end() ) + { + str << "repo: " << *it << delim ; + } + + for_( it, kinds().begin(), kinds().end() ) + { + str << PoolQueryAttr::kindAttr.asString() << ": " + << it->idStr() << delim ; + } + + if (editionRel() != Rel::ANY && edition() != Edition::noedition) + str << PoolQueryAttr::editionAttr.asString() << ": " << editionRel() << " " << edition() << delim; + + if (matchMode()!=q.matchMode()) + { + switch( matchMode() ) + { + case Match::STRING: + str << PoolQueryAttr::stringTypeAttr.asString() << ": exact" << delim; + break; + case Match::SUBSTRING: + str << PoolQueryAttr::stringTypeAttr.asString() + << ": substring" << delim; + break; + case Match::GLOB: + str << PoolQueryAttr::stringTypeAttr.asString() << ": glob" << delim; + break; + case Match::REGEX: + str << PoolQueryAttr::stringTypeAttr.asString() << ": regex" << delim; + break; + default: + WAR << "unknown match type " << matchMode() << endl; + } + } + + if( caseSensitive() != q.caseSensitive() ) + { + str << "case_sensitive: "; + if (caseSensitive()) + { + str << "on" << delim; + } + else + { + str << "off" << delim; + } + } + + if( statusFilterFlags() != q.statusFilterFlags() ) + { + switch( statusFilterFlags() ) + { + case ALL: + str << "install_status: all" << delim; + break; + case INSTALLED_ONLY: + str << "install_status: installed" << delim; + break; + case UNINSTALLED_ONLY: + str << "install_status: not-installed" << delim; + break; + } + } + + for_( it, strings().begin(), strings().end() ) + { + str << PoolQueryAttr::stringAttr.asString()<< ": " << *it << delim; + } + + for_( it, attributes().begin(), attributes().end() ) + { + std::string s = it->first.asString(); + str::replaceAll(s,":","_"); + for_( it2,it->second.begin(),it->second.end() ) + { + str << s <<": "<< *it2 << delim; + } + } + + for_( it, _pimpl->_uncompiledPredicated.begin(), _pimpl->_uncompiledPredicated.end() ) + { + str << "complex: "<< it->serialize() << delim; + } + + if ( const std::string & c { comment() }; not c.empty() ) + str << PoolQueryAttr::commentAttr.asString() << ": " << c << delim ; + + //separating delim - protection + str << delim; + } + + std::string PoolQuery::asString() const + { return _pimpl->asString(); } + + std::ostream & operator<<( std::ostream & str, const PoolQuery & obj ) + { return str << obj.asString(); } + + std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj ) + { return dumpRange( str << obj, obj.begin(), obj.end() ); } + + bool PoolQuery::operator==( const PoolQuery & rhs ) const + { return *_pimpl == *rhs._pimpl; } + + bool PoolQuery::operator<( const PoolQuery & rhs ) const + { return *_pimpl < *rhs._pimpl; } + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolQueryMatcher + // + /** Store \ref PoolQuery settings and assist \ref PoolQueryIterator. + * + * Basically the matcher performs a base query, which should preselect + * candidates for a match. And has some filter conditions on top of it. + * Query and fileter depend on the \ref PoolQuery settings. + * + * Matcher must be stateless, as it is shared between multiple + * \ref PoolQueryIterator instances. + * + * If \ref base_iterator is at the \ref end, \ref advance moves it + * to the first match. Otherwise advance moves to the next match, or + * to the \ref end, if there is no more match. + * + * \note The original implementation treated an empty search string as + * "match always". We stay compatible. + */ + class PoolQueryMatcher + { + public: + using base_iterator = sat::LookupAttr::iterator; + + public: + const base_iterator & end() const + { + static base_iterator _end; + return _end; + } + + bool advance( base_iterator & base_r ) const + { + if ( base_r == end() ) + base_r = startNewQyery(); // first candidate + else + { + base_r.nextSkipSolvable(); // assert we don't visit this Solvable again + ++base_r; // advance to next candidate + } + + while ( base_r != end() ) + { + if ( isAMatch( base_r ) ) + return true; + // No match: try next + ++base_r; + } + return false; + } + + /** Provide all matching attributes within this solvable. + * + */ + void matchDetail( const base_iterator & base_r, std::vector & return_r ) const + { + if ( base_r == end() ) + return; + + sat::Solvable inSolvable( base_r.inSolvable() ); + + if ( _attrMatchList.size() == 1 ) + { + // base_r is already on the 1st matching attribute! + // String matching is done by the base iterator. We must check the predicate here. + // Let's see if there are more matches for this solvable: + base_iterator base( base_r ); + base.stayInThisSolvable(); // avoid discarding matches we found far away from here. + return_r.push_back( base ); + + const AttrMatchData::Predicate & predicate( _attrMatchList.front().predicate ); + for ( ++base; base.inSolvable() == inSolvable; ++base ) // safe even if base == end() + { + if ( ! predicate || predicate( base ) ) + return_r.push_back( base ); + } + } + else + { + // Here: search all attributes ;( + for_( mi, _attrMatchList.begin(), _attrMatchList.end() ) + { + const AttrMatchData & matchData( *mi ); + sat::LookupAttr q( matchData.attr, inSolvable ); + if ( matchData.strMatcher ) // an empty searchstring matches always + q.setStrMatcher( matchData.strMatcher ); + + if ( ! q.empty() ) // there are matches. + { + // now check any predicate: + const AttrMatchData::Predicate & predicate( matchData.predicate ); + for_( it, q.begin(), q.end() ) + { + if ( ! predicate || predicate( it ) ) + return_r.push_back( it ); + } + } + } + } + } + + public: + PoolQueryMatcher(const PoolQueryMatcher &) = default; + PoolQueryMatcher(PoolQueryMatcher &&) = default; + PoolQueryMatcher &operator=(const PoolQueryMatcher &) = default; + PoolQueryMatcher &operator=(PoolQueryMatcher &&) = default; + + /** Ctor stores the \ref PoolQuery settings. + * \throw MatchException Any of the exceptions thrown by \ref PoolQuery::Impl::compile. + */ + PoolQueryMatcher( const shared_ptr & query_r ) + { + query_r->compile(); + + // Repo restriction: + sat::Pool satpool( sat::Pool::instance() ); + + for_( it, query_r->_repos.begin(), query_r->_repos.end() ) + { + Repository r( satpool.reposFind( *it ) ); + if ( r ) + _repos.insert( r ); + else + _neverMatchRepo = true; + } + // _neverMatchRepo: we just need to catch the case that no repo + // matched, so we'd interpret the empty list as 'take from all' + if ( _neverMatchRepo && ! _repos.empty() ) + _neverMatchRepo = false; + + // Kind restriction: + _kinds = query_r->_kinds; + // Edition restriction: + _op = query_r->_op; + _edition = query_r->_edition; + // Status restriction: + _status_flags = query_r->_status_flags; + // StrMatcher + _attrMatchList = query_r->_attrMatchList; + } + + ~PoolQueryMatcher() + {} + + private: + /** Initialize a new base query. */ + base_iterator startNewQyery() const + { + sat::LookupAttr q; + + if ( _neverMatchRepo ) + return q.end(); + + // Repo restriction: + if ( _repos.size() == 1 ) + q.setRepo( *_repos.begin() ); + // else: handled in isAMatch. + + // Attribute restriction: + if ( _attrMatchList.size() == 1 ) // all (SolvAttr::allAttr) or 1 attr + { + const AttrMatchData & matchData( _attrMatchList.front() ); + q.setAttr( matchData.attr ); + if ( matchData.strMatcher ) // empty searchstring matches always + q.setStrMatcher( matchData.strMatcher ); + } + else // more than 1 attr (but not all) + { + // no restriction, it's all handled in isAMatch. + q.setAttr( sat::SolvAttr::allAttr ); + } + + return q.begin(); + } + + + /** Check whether we are on a match. + * + * The check covers the whole Solvable, not just the current + * attribute \c base_r points to. If there's no match, also + * prepare \c base_r to advance appropriately. If there is + * a match, simply return \c true. \ref advance always moves + * to the next Solvable if there was a match. + * + * \note: Caller asserts we're not at \ref end. + */ + bool isAMatch( base_iterator & base_r ) const + { + ///////////////////////////////////////////////////////////////////// + Repository inRepo( base_r.inRepo() ); + // Status restriction: + if ( _status_flags + && ( (_status_flags == PoolQuery::INSTALLED_ONLY) != inRepo.isSystemRepo() ) ) + { + base_r.nextSkipRepo(); + return false; + } + // Repo restriction: + if ( _repos.size() > 1 && _repos.find( inRepo ) == _repos.end() ) + { + base_r.nextSkipRepo(); + return false; + } + ///////////////////////////////////////////////////////////////////// + sat::Solvable inSolvable( base_r.inSolvable() ); + // Edition restriction: + if ( _op != Rel::ANY && !compareByRel( _op, inSolvable.edition(), _edition, Edition::Match() ) ) + { + base_r.nextSkipSolvable(); + return false; + } + + // Kind restriction: + // Delay the decision to nextSkipSolvable and return false, as there may be + // some explicit kind:name predicate which overrules the global kinds. + bool globalKindOk =( _kinds.empty() || inSolvable.isKind( _kinds.begin(), _kinds.end() ) ); + + ///////////////////////////////////////////////////////////////////// + // string and predicate matching: + + if ( _attrMatchList.size() == 1 ) + { + // String matching was done by the base iterator. + // Now check any predicate: + const AttrMatchData & matchData( _attrMatchList.front() ); + + if ( matchData.kindPredicate ) + { + if ( matchData.kindPredicate != inSolvable.kind() ) + { + base_r.nextSkipSolvable(); // this matchData will never match in this solvable + return false; + } + } + else if ( !globalKindOk ) + return false; // only matching kindPredicate could overwrite this + + if ( !matchData.predicate || matchData.predicate( base_r ) ) + return true; + + return false; // no skip as there may be more occurrences in this solvable of this attr. + } + + // Here: search all attributes ;( + for_( mi, _attrMatchList.begin(), _attrMatchList.end() ) + { + const AttrMatchData & matchData( *mi ); + + if ( matchData.kindPredicate ) + { + if ( matchData.kindPredicate != inSolvable.kind() ) + continue; // this matchData does not apply + } + else if ( !globalKindOk ) + continue; // only matching kindPredicate could overwrite this + + sat::LookupAttr q( matchData.attr, inSolvable ); + if ( matchData.strMatcher ) // an empty searchstring matches always + q.setStrMatcher( matchData.strMatcher ); + + if ( ! q.empty() ) // there are matches. + { + // now check any predicate: + const AttrMatchData::Predicate & predicate( matchData.predicate ); + if ( predicate ) + { + for_( it, q.begin(), q.end() ) + { + if ( predicate( it ) ) + return true; + } + } + else + return true; + } + } + base_r.nextSkipSolvable(); + return false; + } + + private: + /** Repositories include in the search. */ + std::set _repos; + DefaultIntegral _neverMatchRepo; + /** Resolvable kinds to include. */ + std::set _kinds; + /** Edition filter. */ + Rel _op; + Edition _edition; + /** Installed status filter flags. \see PoolQuery::StatusFilter */ + int _status_flags; + /** StrMatcher per attribtue. */ + AttrMatchList _attrMatchList; + }; + /////////////////////////////////////////////////////////////////// + + void PoolQueryIterator::increment() + { + // matcher restarts if at end! It is called from the ctor + // to get the 1st match. But if the end is reached, it should + // be deleted, otherwise we'd start over again. + if ( !_matcher ) + return; // at end + if ( _matches ) + _matches.reset(); // invalidate old matches + if ( ! _matcher->advance( base_reference() ) ) + _matcher.reset(); + } + + const PoolQueryIterator::Matches & PoolQueryIterator::matches() const + { + if ( _matches ) + return *_matches; + + if ( !_matcher ) + { + // at end of query: + static const Matches _none; + return _none; + } + + _matches.reset( new Matches ); + _matcher->matchDetail( base_reference(), *_matches ); + return *_matches; + } + + std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj ) + { + str << *obj; + if ( ! obj.matchesEmpty() ) + { + for_( it, obj.matchesBegin(), obj.matchesEnd() ) + { + str << endl << " " << it->inSolvAttr() << "\t" << it->asString(); + } + } + return str; + } + + /////////////////////////////////////////////////////////////////// + } //namespace detail + /////////////////////////////////////////////////////////////////// + + detail::PoolQueryIterator PoolQuery::begin() const + { + return shared_ptr( new detail::PoolQueryMatcher( _pimpl.getPtr() ) ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + diff --git a/zypp/PoolQuery.h b/zypp/PoolQuery.h new file mode 100644 index 0000000..3db157b --- /dev/null +++ b/zypp/PoolQuery.h @@ -0,0 +1,628 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolQuery.h + * +*/ +#ifndef ZYPP_POOLQUERY_H +#define ZYPP_POOLQUERY_H + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace detail + { + class PoolQueryIterator; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolQuery + // + /** + * Meta-data query API. Returns solvables of specified kinds from specified + * repositories with attributes matching the specified search strings. + * + * The search strings can be specified via \ref addString() and + * \ref addAttribute() methods. String matching type can be set using the + * setMatch*() methods. Multiple search strings for a particular attribute + * will be combined into a regex (see \ref addString() and + * \ref addAttribute() for more details). + * + * The begin() and end() methods return a PoolQueryIterator returning + * \ref sat::Solvable objects which can easily be turned into \ref Resolvable + * objects. Additionally, thanx to the \ref sat::SolvIterMixin, a Selectable + * and PoolItem iterators are automatically available. + * + * \note You will sometimes face the problem, that when using the \ref PoolItem + * iterator you hit multiple version of the same package, while when using the + * \ref ui::Selectable iterator the information which of the available candidates + * actually matched got lost. In this case class \ref PoolItemBest may help you. + * Use it to pick the best version only. + * + * + * PoolQuery q; + * q.addAttribute(sat::SolvAttr::name, "zypp*"); + * q.addKind(ResKind::package); + * q.setMatchGlob(); + * + * for (PoolQuery::Selectable_iterator it = q.selectableBegin(); + * it != q.selectableEnd(); ++it) + * { + * ui::Selectable::constPtr s = *it; + * // ... + * } + * + * + * Performance considerations + * + * Results of simple queries like those using one string and/or one attribute + * and/or one repository are filtered by sat-solver's Dataiterator directly, + * and thus it is fast. + * + * Queries with multiple strings are implemented using regexes. Queries based + * on kinds, multiple repos, and multiple attributes are filtered inside + * the PoolQuery, so these tend to be slower. + * + * \see detail::PoolQueryIterator on how to inspect matches in detail. + * \see tests/zypp/PoolQuery_test.cc for more examples + * \see sat::SolvIterMixin + */ + class ZYPP_API PoolQuery : public sat::SolvIterMixin + { + public: + using Kinds = std::set; + using StrContainer = std::set; + using AttrRawStrMap = std::map; + + using const_iterator = detail::PoolQueryIterator; + using size_type = unsigned int; + + public: + using ProcessResolvable = function; + + PoolQuery(); + ~PoolQuery(); + + /** Query result accessers. */ + //@{ + /** + * Compile the query and return an iterator to the result. + * + * \return An iterator (\ref detail::PoolQueryIterator) returning + * sat::Solvable objects pointing at the beginning of the query result. + * \throws sat::MatchInvalidRegexException if the query was about to use a regex which + * failed to compile. + * + * \note Note that PoolQuery is derived from \ref sat::SolvIterMixin which + * makes PoolItem and Selectable iterators automatically available. + * \see \ref sat::SolvIterMixin + */ + const_iterator begin() const; + + /** An iterator pointing to the end of the query result. */ + const_iterator end() const; + + /** Whether the result is empty. */ + bool empty() const; + + /** Number of solvables in the query result. */ + size_type size() const; + //@} + + /** + * Executes the query with the current settings. + * Results are yielded via the \a fnc callback. + */ + void execute(ProcessResolvable fnc); + + /** + * Filter by selectable kind. + * + * By default, all kinds will be returned. If addKind() is used, + * only the specified kinds will be returned (multiple kinds will be ORed). + * + * \note This kind filter does not apply if you explicitly specify a ResKind + * when searching for \c sat::SolvAttr::name. The following will always match + * and include the kernel \c packages, no matter which kind filter is set. + * \code + * addDependency( sat::SolvAttr::name, "package:kernel" ); + * \endcode + * + * Pass ResKind constants to this method, (e.g. ResKind::package). + */ + void addKind(const ResKind & kind); + + /** + * Filter by repo. + * + * By default, all repos will be returned. If addRepo() is used, + * only the specified repo will be returned (multiple repos will be ORed). + */ + void addRepo(const std::string &repoalias); + + /** Set an optional comment string describing the purpose of the query. + * Stored and retrieved when serializing the query. E.g. as lock. + */ + void setComment(const std::string & comment) const; + + /** Installed status filter setters. */ + //@{ + + /** + * Filter by status (installed uninstalled) + */ + enum StatusFilter { + ALL = 0, // both install filter and uninstall filter bits are 0 + INSTALLED_ONLY = 1, + UNINSTALLED_ONLY = 2 + }; + + /** Return only @System repo packages */ + void setInstalledOnly(); + /** Return only packages from repos other than @System. */ + void setUninstalledOnly(); + /** Set status filter directly \see StatusFilter */ + void setStatusFilterFlags( StatusFilter flags ); + + //@} + + /** + * Add a global query string. The string added via this method is applied + * to all query attributes as if addAttribute(..., \value) was called + * for all of them. + * + * This method can be used multiple times in which case the query strings + * will be combined (together with strings added via addAttribute()) into + * a regex. Searched attribute value will match this regex if any + * of these strings will match the value. + */ + void addString(const std::string & value); + + /** + * Filter by the \a value of the specified \a attr attribute. This can + * be any of the available solvable attributes. + * + * This method can be used multiple times with the same \a attr in which + * case the query strings will be combined (together with strings added + * via addString()) into a regex. Searched attribute value will match + * this regex if any of these strings will match the value. + * + * \note Though it is possible to use dependency attributes like + * \ref Solv::Attr::provides here, note that the query string is + * matched against a dependencies \c "name" part only. Any + * "op edition" part of a \ref Capability is \b not + * considered at all. \see \ref addDependency on how to query for + * capabilities including edition ranges. + * + * \note Solvables of a kind not supporting the specified attribute will + * not be returned. + * \todo check the above + * + * \param attr Attribute identfier. Use sat::Solvattr::* constants + * \param value What to search for. + * + * \see sat::SolvAttr + */ + void addAttribute( const sat::SolvAttr & attr, const std::string & value = "" ); + + /** \name Filter by dependencies matching a broken down capability name [op edition] and/or architecture. + * + * The capabilities \c name part may be defined as query string + * like with \ref addAttribute. Globing and regex are supported. + * Global query strings defined by \ref addString are considered. + * + * So without any op edition arch addDependency behaves the + * same as \ref addAttribute. If an edition range is given, matches + * are restricted accordingly. There are various overloads, so pick + * the one you like best. + * + * An optional \c arch argument will additionally require the matching + * solvable to be of this arch. + * + * \code + * { + * setMatchGlob(); + * setCaseSensitive( false ); + * addDependency( sat::SolvAttr::provides, "kde*", Rel::EQ, Edition("2.0") ); + * addDependency( sat::SolvAttr::provides, "kde*", Edition("2.0") ); // same as above + * } + * { + * setMatchGlob(); + * setCaseSensitive( false ); + * addString( "kde*" ); + * addDependency( sat::SolvAttr::provides, Rel::EQ, Edition("2.0") );// same as above + * addDependency( sat::SolvAttr::provides, Edition("2.0") ); // same as above + * } + * \endcode + * + * \note Thre's also a version of \ref addDependency provided, that takes a + * complete \ref Capability as argument. This always requires an exact match + * of the name part (as the resolver would do it). + * + * This is the list of valid dependency attributes: + * \code + * SolvAttr::provides + * SolvAttr::obsoletes + * SolvAttr::conflicts + * SolvAttr::requires + * SolvAttr::recommends + * SolvAttr::suggests + * SolvAttr::supplements + * SolvAttr::enhances + * \endcode + * + * \note What happens if a non dependency attribute is passed?<\b> + * If an edition range is given, it is matched against the matching + * solvables edition instead. Without edition range it behaves the + * same as \ref addAttribute. + * + * \code + * // Find all packages providing "kernel > 2.0" + * addDependency( sat::SolvAttr::provides, "kernel", Rel::GT, Edition("2.0") ); + * + * // // Find all packages named "kernel" and with edition "> 2.0" + * addDependency( sat::SolvAttr::name, "kernel", Rel::GT, Edition("2.0") ); + * \endcode + */ + //@{ + /** Query "name|global op edition". */ + void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition ); + /** \overload also restricting architecture */ + void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch ); + /** \overload also use an individual Match::Mode for the \a name */ + void addDependency( const sat::SolvAttr & attr, const std::string & name, const Rel & op, const Edition & edition, const Arch & arch, Match::Mode mode ); + + /** \overload Query "name|global == edition". */ + void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition ) + { addDependency( attr, name, Rel::EQ, edition ); } + /** \overload also restricting architecture */ + void addDependency( const sat::SolvAttr & attr, const std::string & name, const Edition & edition, const Arch & arch ) + { addDependency( attr, name, Rel::EQ, edition, arch ); } + + /** \overload Query "name|global". */ + void addDependency( const sat::SolvAttr & attr, const std::string & name ) + { addDependency( attr, name, Rel::ANY, Edition() ); } + /** \overload also restricting architecture */ + void addDependency( const sat::SolvAttr & attr, const std::string & name, const Arch & arch ) + { addDependency( attr, name, Rel::ANY, Edition(), arch ); } + + /** \overload Query "global op edition".*/ + void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition ) + { addDependency( attr, std::string(), op, edition ); } + /** \overload also restricting architecture */ + void addDependency( const sat::SolvAttr & attr, const Rel & op, const Edition & edition, const Arch & arch ) + { addDependency( attr, std::string(), op, edition, arch ); } + + /** \overload Query "global == edition". */ + void addDependency( const sat::SolvAttr & attr, const Edition & edition ) + { addDependency( attr, std::string(), Rel::EQ, edition ); } + /** \overload also restricting architecture */ + void addDependency( const sat::SolvAttr & attr, const Edition & edition, const Arch & arch ) + { addDependency( attr, std::string(), Rel::EQ, edition, arch ); } + + /** \overload Query "global". */ + void addDependency( const sat::SolvAttr & attr ) + { addDependency( attr, std::string(), Rel::ANY, Edition() ); } + /** \overload also restricting architecture */ + void addDependency( const sat::SolvAttr & attr, const Arch & arch ) + { addDependency( attr, std::string(), Rel::ANY, Edition(), arch ); } + + /** \overload Query taking a \ref Capability (always exact name match). + * \note If a non dependency attribute is passed, the \ref Capability + * will always be matched against the Solvables \c name and \c edition. + */ + void addDependency( const sat::SolvAttr & attr, Capability cap_r ); + //@} + + /** + * Set version condition. This will filter out solvables not matching + * solvableEdition \a op \a edition. + * + * \param edition Edition to look for. + * \param op Found-wanted relation operator. + */ + void setEdition(const Edition & edition, const Rel & op = Rel::EQ); + + /** \name Text Matching Options + * \note The implementation treats an empty search string as + * "match always". So if you want to actually match + * an empty value, try ( "^$", setMatchRegex ). + */ + //@{ + /** + * Turn case sentitivity on or off (unsets or sets \ref SEARCH_NOCASE flag). + * PoolQuery defaults to case insensitive search unless this method + * is used. + * + * \param value Whether to turn the case sensitivity on (default) or off. + */ + void setCaseSensitive( bool value = true ); + + /** + * If set (default), look at the full path when searching in filelists. + * Otherwise just match the the basenames. + * \see \ref Match::FILES + */ + void setFilesMatchFullPath( bool value = true ); + /** \overload */ + void setFilesMatchBasename( bool value = true ) + { setFilesMatchFullPath( !value ); } + + /** Set to match exact string instead of substring.*/ + void setMatchExact(); + /** Set to substring (the default). */ + void setMatchSubstring(); + /** Set to match globs. */ + void setMatchGlob(); + /** Set to use the query strings as regexes */ + void setMatchRegex(); + /** Set substring to match words */ + void setMatchWord(); + //void setLocale(const Locale & locale); + //@} + + /** \name getters */ + //@{ + + /** Search strings added via addString() */ + const StrContainer & strings() const; + /** + * Map (map) of attribute values added via + * addAttribute(), addDep in string form */ + const AttrRawStrMap & attributes() const; + + const StrContainer & attribute(const sat::SolvAttr & attr) const; + + const Kinds & kinds() const; + + const StrContainer & repos() const; + + const std::string & comment() const; + + const Edition edition() const; + const Rel editionRel() const; + + /** + * returns true if search is case sensitive + */ + bool caseSensitive() const; + + /** Whether searching in filelists looks at the full path or just at the basenames. */ + bool filesMatchFullPath() const; + /** \overload */ + bool filesMatchBasename() const + { return !filesMatchFullPath(); } + + bool matchExact() const; + bool matchSubstring() const; + bool matchGlob() const; + bool matchRegex() const; + bool matchWord() const; + + /** Returns string matching mode as enum. + * \see \ref Match::Mode + */ + Match::Mode matchMode() const + { return flags().mode(); } + + StatusFilter statusFilterFlags() const; + //@} + + /** + * Reads from stream query. Attributes is sepated by delim. Query is + * separated by two delim. + * + * \param str input stream which contains query + * \param delim delimeter for attributes + * \return true if non-empty query is recovered + * + * \see readPoolQueriesFromFile + */ + bool recover( std::istream &str, char delim = '\n' ); + + /** + * Writes a machine-readable string representation of the query to stream. + * Use \a delim as attribute delimiter. + * + * \param str output stream to write to + * \param delim delimiter for attributes + * + * \see writePoolQueriesToFile + */ + void serialize( std::ostream &str, char delim = '\n' ) const; + + /** Return a human-readable description of the query */ + std::string asString() const; + + bool operator<(const PoolQuery& b) const; + bool operator==(const PoolQuery& b) const; + bool operator!=(const PoolQuery& b) const { return !(*this == b ); } + + // low level API + + /** + * Free function to get libsolv repo search + * flags. + * + * \see \ref Match + */ + Match flags() const; + + /** + * Free function to set libsolv repo search + * flags. + * + * \see \ref Match + */ + void setFlags( const Match & flags ); + + public: + /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */ + void setRequireAll( bool require_all = true ) ZYPP_DEPRECATED; + /** \deprecated Attribute was defined but never implemented/used. Will be removed in future versions. */ + bool requireAll() const ZYPP_DEPRECATED; + + public: + class Impl; + private: + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PoolQuery Stream output. */ + std::ostream & operator<<( std::ostream & str, const PoolQuery & obj ) ZYPP_API; + + /** \relates PoolQuery Detailed stream output. */ + std::ostream & dumpOn( std::ostream & str, const PoolQuery & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + class PoolQueryMatcher; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolQuery::PoolQueryIterator + // + /** \ref PoolQuery iterator as returned by \ref PoolQuery::begin. + * + * The \ref PoolQueryIterator visits sat::Solavables that do contain matches. + * + * But it also provides an iterator by itself, to allow a detailed inspection of + * the individual attribute matches within the current Solvable. + */ + class ZYPP_API PoolQueryIterator : public boost::iterator_adaptor< + PoolQueryIterator // Derived + , sat::LookupAttr::iterator // Base + , const sat::Solvable // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , const sat::Solvable // Reference + > + { + using Matches = std::vector; + public: + using size_type = Matches::size_type; + using matches_iterator = Matches::const_iterator; + public: + /** Default ctor is also \c end.*/ + PoolQueryIterator() + {} + + /** \Ref PoolQuery ctor. */ + PoolQueryIterator( const shared_ptr & matcher_r ) + : _matcher( matcher_r ) + { increment(); } + + /** \name Detailed inspection of attribute matches within the current Solvable. + * + * The \ref matches_iterator visits all attribute matches within the current Solvable, + * providing a \ref sat::LookupAttr::iterator pointing to attribute. While a + * \ref matches_iterator itself becomes invalid if the PoolQueryIterator is advanced, + * the \ref sat::LookupAttr::iterator it pointed to stays valid, even after the query + * ended. + * + * \code + * // Setup query for "libzypp" in name or requires: + * PoolQuery q; + * q.addString( "libzypp" ); + * q.setMatchSubstring(); + * q.setCaseSensitive( false ); + * q.addAttribute( sat::SolvAttr::name ); + * q.addDependency( sat::SolvAttr::requires ); + * + * // Iterate the result: + * for_( solvIter, q.begin(), q.end() ) + * { + * sat::Solvable solvable( *solvIter ); + * cout << "Found matches in " << solvable << endl; + * if ( verbose ) + * for_( attrIter, solvIter.matchesBegin(), solvIter.matchesEnd() ) + * { + * sat::LookupAttr::iterator attr( *attrIter ); + * cout << " " << attr.inSolvAttr() << "\t\"" << attr.asString() << "\"" << endl; + * } + * } + * + * + * Found matches in PackageKit-0.3.11-1.12.i586(@System) + * solvable:requires "libzypp.so.523" + * Found matches in libqdialogsolver1-1.2.6-1.1.2.i586(@System) + * solvable:requires "libzypp.so.523" + * solvable:requires "libzypp >= 5.25.3-0.1.2" + * Found matches in libzypp-5.30.3-0.1.1.i586(@System) + * solvable:name "libzypp" + * Found matches in libzypp-testsuite-tools-4.2.6-8.1.i586(@System) + * solvable:name "libzypp-testsuite-tools" + * solvable:requires "libzypp.so.523" + * ... + * \endcode + */ + //@{ + /** \c False unless this is the \c end iterator. */ + bool matchesEmpty() const { return ! _matcher; } + /** Number of attribute matches. */ + size_type matchesSize() const { return matches().size(); } + /** Begin of matches. */ + matches_iterator matchesBegin() const { return matches().begin(); } + /** End of matches. */ + matches_iterator matchesEnd() const { return matches().end(); } + //@} + + private: + friend class boost::iterator_core_access; + + sat::Solvable dereference() const + { return base_reference().inSolvable(); } + + void increment(); + + private: + const Matches & matches() const; + + private: + shared_ptr _matcher; + mutable shared_ptr _matches; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PoolQueryIterator Stream output. */ + inline std::ostream & operator<<( std::ostream & str, const PoolQueryIterator & obj ) + { return str << obj.base(); } + + /** \relates PoolQueryIterator Detailed stream output. */ + std::ostream & dumpOn( std::ostream & str, const PoolQueryIterator & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + } //namespace detail + /////////////////////////////////////////////////////////////////// + + inline detail::PoolQueryIterator PoolQuery::end() const + { return detail::PoolQueryIterator(); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif // ZYPP_POOLQUERY_H diff --git a/zypp/PoolQueryResult.cc b/zypp/PoolQueryResult.cc new file mode 100644 index 0000000..2ced865 --- /dev/null +++ b/zypp/PoolQueryResult.cc @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolQueryResult.cc + * +*/ +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const PoolQueryResult & obj ) + { + return dumpRange( str, obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PoolQueryResult.h b/zypp/PoolQueryResult.h new file mode 100644 index 0000000..7eaf029 --- /dev/null +++ b/zypp/PoolQueryResult.h @@ -0,0 +1,234 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolQueryResult.h + * +*/ +#ifndef ZYPP_POOLQUERYRESULT_H +#define ZYPP_POOLQUERYRESULT_H + +#include + +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolQueryResult + // + /** Helper class to collect (not only) \ref PoolQuery results. + * + * \note Unfortunately \ref PoolQuery::begin might throw. Exceptions + * are caught and the query is treated as empty. + * + * \ref PoolQueryResult maintains a set of \ref sat::Solvable. You can + * add/remove solvables to/from the set defined by: + * + * \li a single \ref sat::Solvable + * \li a single \ref PoolItem + * \li a \ref PoolQuery + * \li an other \ref PoolQueryResult + * \li any iterator pair with \c value_type \ref sat::Solvable + * or \ref PoolItem or \ref PoolQuery or any type that fits + * \c operator+=. + * + * The class is a \ref sat::SolvIterMixin, so you can iterate the result + * not just as \ref sat::Solvable, but also as \ref PoolItem or + * \ref ui::Selectable. + * + * \code + * // Constructed from PoolItem iterator pair + * PoolQueryResult result( pool.byKindBegin(), pool.byKindEnd() ); + * MIL << result.size() << endl; + * + * { + * // Removing a PoolQuery result + * PoolQuery q; + * q.addAttribute( sat::SolvAttr::name, "[a-zA-Z]*" ); + * q.setMatchGlob(); + * result -= q; + * MIL << result.size() << endl; + * } + * MIL << result << endl; + * + * // Removing a range of sat::Solvables + * sat::WhatProvides poviders( Capability("3ddiag") ); + * result -= PoolQueryResult( poviders.begin(), poviders.end() ); + * + * // packages not starting with a letter, except 3ddiag + * MIL << result << endl; + * \endcode + */ + class PoolQueryResult : public sat::SolvIterMixin::const_iterator> + { + public: + using ResultSet = std::unordered_set; + using size_type = ResultSet::size_type; + using const_iterator = ResultSet::const_iterator; + + public: + /** Default ctor (empty result) */ + PoolQueryResult() + {} + + /** Ctor adding one \ref sat::Solvable. */ + explicit PoolQueryResult( sat::Solvable result_r ) + { operator+=( result_r ); } + + /** Ctor adding one \ref PoolItem. */ + explicit PoolQueryResult( const PoolItem & result_r ) + { operator+=( result_r ); } + + /** Ctor adding one \ref PoolQuery result. */ + explicit PoolQueryResult( const PoolQuery & query_r ) + { operator+=( query_r ); } + + /** Ctor adding a range of items for which \ref operator+= is defined. */ + template + PoolQueryResult( TQueryResultIter begin_r, TQueryResultIter end_r ) + { + for_( it, begin_r, end_r ) + { + operator+=( *it ); + } + } + + public: + /** Whether the result is empty. */ + bool empty() const + { return _result.empty(); } + /** The number of \ref sat::Solvables. */ + size_type size() const + { return _result.size(); } + /** */ + const_iterator begin() const + { return _result.begin(); } + /** */ + const_iterator end() const + { return _result.end(); } + + /** Test whether some item is in the result set. */ + bool contains(sat::Solvable result_r ) const + { return( _result.find( result_r ) != _result.end() ); } + /** \overload */ + bool contains( const PoolItem & result_r ) const + { return contains( result_r.satSolvable() ); } + + public: + /** Clear the result. */ + void clear() + { _result.clear(); } + + /** Add items to the result. */ + PoolQueryResult & operator+=( const PoolQueryResult & query_r ) + { + if ( ! query_r.empty() ) + _result.insert( query_r.begin(), query_r.end() ); + return *this; + } + /** \overload */ + PoolQueryResult & operator+=( const PoolQuery & query_r ) + { + try + { + for_( it, query_r.begin(), query_r.end() ) + _result.insert( *it ); + } + catch ( const Exception & ) + {} + return *this; + } + /** \overload */ + PoolQueryResult & operator+=( sat::Solvable result_r ) + { + _result.insert( result_r ); + return *this; + } + /** \overload */ + PoolQueryResult & operator+=( const PoolItem & result_r ) + { + _result.insert( result_r.satSolvable() ); + return *this; + } + + /** Remove Items from the result. */ + PoolQueryResult & operator-=( const PoolQueryResult & query_r ) + { + if ( &query_r == this ) // catch self removal! + clear(); + else + for_( it, query_r.begin(), query_r.end() ) + _result.erase( *it ); + return *this; + } + /** \overload */ + PoolQueryResult & operator-=( const PoolQuery & query_r ) + { + try + { + for_( it, query_r.begin(), query_r.end() ) + _result.erase( *it ); + } + catch ( const Exception & ) + {} + return *this; + } + /** \overload */ + PoolQueryResult & operator-=( sat::Solvable result_r ) + { + _result.erase( result_r ); + return *this; + } + /** \overload */ + PoolQueryResult & operator-=( const PoolItem & result_r ) + { + _result.erase( result_r.satSolvable() ); + return *this; + } + + public: + /** Combine results. */ + PoolQueryResult operator+( const PoolQueryResult & query_r ) const + { return PoolQueryResult(*this) += query_r; } + /** \overload */ + PoolQueryResult operator+( const PoolQuery & query_r ) const + { return PoolQueryResult(*this) += query_r; } + /** \overload */ + PoolQueryResult operator+( sat::Solvable result_r ) const + { return PoolQueryResult(*this) += result_r; } + + /** Intersect results. */ + PoolQueryResult operator-( const PoolQueryResult & query_r ) const + { return PoolQueryResult(*this) -= query_r; } + /** \overload */ + PoolQueryResult operator-( const PoolQuery & query_r ) const + { return PoolQueryResult(*this) -= query_r; } + /** \overload */ + PoolQueryResult operator-( sat::Solvable result_r ) const + { return PoolQueryResult(*this) -= result_r; } + + private: + ResultSet _result; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PoolQueryResult Stream output */ + std::ostream & operator<<( std::ostream & str, const PoolQueryResult & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_POOLQUERYRESULT_H diff --git a/zypp/PoolQueryUtil.tcc b/zypp/PoolQueryUtil.tcc new file mode 100644 index 0000000..80ce5f5 --- /dev/null +++ b/zypp/PoolQueryUtil.tcc @@ -0,0 +1,78 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PoolQueryUtil.tcc + * + * including fstream is not hell here because this header only included + * by implementation file, header doesn't need include it. +*/ +#ifndef ZYPP_POOLQUERYUTIL_TCC +#define ZYPP_POOLQUERYUTIL_TCC + +#include + +#include +#include +#include + +namespace zypp +{ + + /** + * sends to output iterator all queries readed from file. + * + * \code + * list s; + * insert_iterator > ii(s, s.end()); + * readPoolQueriesFromStream(f,ii); + * \endcode + */ + template + void readPoolQueriesFromFile(const zypp::filesystem::Pathname &file, + OutputIterator out ) + { + bool found = false; + std::ifstream fin( file.c_str() ); + + if (!fin) + ZYPP_THROW(Exception(str::form("Cannot open file %s",file.c_str()))); + + do + { + zypp::PoolQuery q; + found = q.recover( fin ); + if (found) + *out++ = q; + } while ( found ); + + fin.close(); + } + + /** + * Writes all queries from begin to end. + */ + + template + void writePoolQueriesToFile(const zypp::filesystem::Pathname &file, + InputIterator begin, InputIterator end ) + { + std::ofstream fout( file.c_str(), std::ios_base::out | std::ios_base::trunc ); + + if (!fout) + ZYPP_THROW(Exception(str::form("Cannot open file %s",file.c_str()))); + + for_( it, begin, end ) + { + it->serialize( fout ); + } + + fout.close(); + } + +} +#endif // ZYPP_POOLQUERYUTIL_H diff --git a/zypp/ProblemSolution.cc b/zypp/ProblemSolution.cc new file mode 100644 index 0000000..893841b --- /dev/null +++ b/zypp/ProblemSolution.cc @@ -0,0 +1,179 @@ + +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* ProblemSolution.cc + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#define ZYPP_USE_RESOLVER_INTERNALS +#include + +#include +#include +#include +#include +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + IMPL_PTR_TYPE(ProblemSolution); + + /////////////////////////////////////////////////////////////////// + /// \class ProblemSolution::Impl + /// \brief ProblemSolution implementation. + /////////////////////////////////////////////////////////////////// + struct ProblemSolution::Impl + { + Impl() + {} + + Impl( std::string && description ) + : _description( std::move(description) ) + {} + + Impl( std::string && description, std::string && details ) + : _description( std::move(description) ) + , _details( std::move(details) ) + {} + + std::string _description; + std::string _details; + SolutionActionList _actions; + + std::set collectActionItems() const + { + std::set ret; + for ( const auto & aptr : _actions ) + ret.insert( aptr->item() ); + return ret; + } + + template + bool allActionsMatch( Predicate && predicate ) const + { + if ( _actions.empty() ) + return false; + for ( const auto & aptr : _actions ) + if ( not std::invoke( std::forward(predicate), aptr ) ) + return false; + return true; + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + ProblemSolution::ProblemSolution() + : _pimpl( new Impl() ) + {} + + ProblemSolution::ProblemSolution( std::string description ) + : _pimpl( new Impl( std::move(description) ) ) + {} + + ProblemSolution::ProblemSolution( std::string description, std::string details ) + : _pimpl( new Impl( std::move(description), std::move(details) ) ) + {} + + ProblemSolution::~ProblemSolution() + {} + + + const std::string & ProblemSolution::description() const + { return _pimpl->_description; } + + const std::string & ProblemSolution::details() const + { return _pimpl->_details; } + + const ProblemSolution::SolutionActionList & ProblemSolution::actions() const + { return _pimpl->_actions; } + + + void ProblemSolution::setDescription( std::string description ) + { _pimpl->_description = std::move(description); } + + void ProblemSolution::setDetails( const std::string& details ) + { _pimpl->_details += "\n"; _pimpl->_details += details; } + + void ProblemSolution::pushDescriptionDetail( std::string description, bool front ) + { + if ( _pimpl->_details.empty() ) + { + if ( _pimpl->_description.empty() ) // first entry + { + _pimpl->_description = std::move(description); + return; + } + else // second entry: form headline in _description + { + _pimpl->_description.swap( _pimpl->_details ); + _pimpl->_description = _("Following actions will be done:"); + } + } + if ( front ) + { _pimpl->_details.swap( description ); } + _pimpl->_details += "\n"; + _pimpl->_details += description; + } + + void ProblemSolution::addAction( const solver::detail::SolutionAction_Ptr& action ) + { _pimpl->_actions.push_back( action ); } + + bool ProblemSolution::skipsPatchesOnly() const + { + return _pimpl->allActionsMatch( []( const SolutionAction_Ptr & aptr ) -> bool { + return aptr->skipsPatchesOnly(); + } ); + } + + std::optional> ProblemSolution::getIfSkipsPatchesOnly() const + { + if ( not skipsPatchesOnly() ) + return std::nullopt; + return _pimpl->collectActionItems(); + } + + + std::ostream & operator<<( std::ostream & os, const ProblemSolution & obj ) + { + os << "Solution:" << endl; + os << obj.description() << endl; + if ( ! obj.details().empty() ) + os << obj.details() << endl; + os << obj.actions(); + return os; + } + + std::ostream & operator<<( std::ostream & os, const ProblemSolutionList & obj ) + { + for ( const auto & ptr: obj ) + { os << ptr; } + return os; + } + +} // namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/ProblemSolution.h b/zypp/ProblemSolution.h new file mode 100644 index 0000000..daaaec0 --- /dev/null +++ b/zypp/ProblemSolution.h @@ -0,0 +1,119 @@ +/** + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Author: Stefan Hundhammer + * + **/ + +#ifndef ZYPP_PROBLEMSOLUTION_H +#define ZYPP_PROBLEMSOLUTION_H + +#include +#include +#include +#include + +#include +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + ///////////////////////////////////////////////////////////////////////// + /// \class ProblemSolution + /// \brief Class representing one possible solution to a problem found during resolving + /// + /// All problems should have at least 2-3 (mutually exclusive) solutions: + /// + /// - Undo: Do not perform the offending transaction + /// (do not install the package that had unsatisfied requirements, + /// do not remove the package that would break other packages' requirements) + /// + /// - Remove referrers: Remove all packages that would break because + /// they depend on the package that is requested to be removed + /// + /// - Ignore: Inject artificial "provides" for a missing requirement + /// (pretend that requirement is satisfied) + ///////////////////////////////////////////////////////////////////////// + class ZYPP_API ProblemSolution : public base::ReferenceCounted + { + public: + using SolutionAction_Ptr = solver::detail::SolutionAction_Ptr; + using SolutionActionList = solver::detail::SolutionActionList; + + /** Constructor. */ + ProblemSolution(); + + /** Constructor. */ + ProblemSolution( std::string description ); + + /** Constructor. */ + ProblemSolution( std::string description, std::string details ); + + /** Destructor. */ + ~ProblemSolution() override; + + + /** + * Return a one-line text description of this solution. + **/ + const std::string & description() const; + + /** + * Return a (possibly multi-line) detailed description of this + * solution or an empty string if there are no useful details. + **/ + const std::string & details() const; + + /** + * Return the list of actions forming this solution. + **/ + const SolutionActionList & actions() const; + + /** + * Set description of the solution. + **/ + void setDescription( std::string description ); + + /** + * Set detail description of the solution. + **/ + void setDetails( const std::string& details ); + + /** + * Collect multiple action descriptions in \ref details (NL separated) + **/ + void pushDescriptionDetail( std::string description, bool front = false ); + + + /** + * Add an action to the actions list. + **/ + void addAction( const SolutionAction_Ptr& action ); + + public: + /** The solution contains only 'do not install patch:' actions. */ + bool skipsPatchesOnly() const; + +#ifdef __cpp_lib_optional // YAST/PK explicitly use c++11 until 15-SP3 + /** The patches if \ref skipsPatchesOnly is true. */ + std::optional> getIfSkipsPatchesOnly() const; +#endif + + private: + struct Impl; + RWCOW_pointer _pimpl; + }; + + /** \relates ProblemSolution Stream output */ + std::ostream& operator<<(std::ostream&, const ProblemSolution & obj ) ZYPP_API; + + /** \relates ProblemSolution Stream output */ + std::ostream& operator<<(std::ostream&, const ProblemSolutionList & obj ) ZYPP_API; + +} // namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_PROBLEMSOLUTION_H + diff --git a/zypp/ProblemTypes.h b/zypp/ProblemTypes.h new file mode 100644 index 0000000..2fb65f5 --- /dev/null +++ b/zypp/ProblemTypes.h @@ -0,0 +1,50 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* Types.h + * + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_PROBLEMTYPES_H +#define ZYPP_PROBLEMTYPES_H + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include // SolutionAction type + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + DEFINE_PTR_TYPE(Resolver); + + DEFINE_PTR_TYPE(ProblemSolution); + using ProblemSolutionList = std::list; + + DEFINE_PTR_TYPE(ResolverProblem); + using ResolverProblemList = std::list; + +} // namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_SOLVER_DETAIL_TYPES_H diff --git a/zypp/Product.cc b/zypp/Product.cc new file mode 100644 index 0000000..43e6e4d --- /dev/null +++ b/zypp/Product.cc @@ -0,0 +1,295 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Product.cc + * +*/ +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(Product); + + namespace + { + void fillList( std::list & ret_r, sat::Solvable solv_r, sat::SolvAttr attr_r ) + { + sat::LookupAttr query( std::move(attr_r), solv_r ); + for_( it, query.begin(), query.end() ) + { + ret_r.push_back( it.asString() ); + } + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Product::Product + // METHOD TYPE : Ctor + // + Product::Product( const sat::Solvable & solvable_r ) + : ResObject( solvable_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Product::~Product + // METHOD TYPE : Dtor + // + Product::~Product() + {} + + /////////////////////////////////////////////////////////////////// + + sat::Solvable Product::referencePackage() const + { + // Look for a provider of 'product(name) = version' of same + // architecture and within the same repo. + // + // Code12: Update repos may have multiple release package versions + // providing the same product. Prefer the one matching the buildtime, + // as the product buildtime is derived from the -release package. + Capability identCap( str::form( "product(%s) = %s", name().c_str(), edition().c_str() ) ); + + sat::Solvable found; + bool foundBuildTime = false; + sat::WhatProvides providers( identCap ); + for_( it, providers.begin(), providers.end() ) + { + if ( it->repository() == repository() && it->arch() == arch() ) + { + bool fitsBuildtime = ( it->buildtime() == buildtime() ); + if ( found ) + { + bool lowerEdition = ( it->edition() <= found.edition() ); + if ( ( foundBuildTime && ( !fitsBuildtime || lowerEdition ) ) + || ( !foundBuildTime && ( !fitsBuildtime && lowerEdition ) ) ) + continue; + } + found = *it; + if ( fitsBuildtime ) + foundBuildTime = true; + } + } + + if ( ! found && isSystem() ) + { + // bnc#784900: for installed products check whether the file is owned by + // some package. If so, ust this as buddy. + sat::LookupAttr q( sat::SolvAttr::filelist, repository() ); + std::string refFile( referenceFilename() ); // the basename only! + if ( ! refFile.empty() ) + { + StrMatcher matcher( "/etc/products.d/"+refFile, Match::STRING | Match::FILES ); + q.setStrMatcher( matcher ); + if ( ! q.empty() ) + found = q.begin().inSolvable(); + } + else + INT << "Product referenceFilename unexpectedly empty!" << endl; + } + + if ( ! found ) + WAR << *this << ": no reference package found: " << identCap << endl; + return found; + } + + std::string Product::referenceFilename() const + { return lookupStrAttribute( sat::SolvAttr::productReferenceFile ); } + + Product::ReplacedProducts Product::replacedProducts() const + { + std::vector ret; + // By now we simply collect what is obsoleted by the Product, + // or by the products buddy (release-package). + + // Check our own dependencies. We should not have any, + // but just to be shure. + sat::WhatObsoletes obsoleting( satSolvable() ); + for_( it, obsoleting.begin(), obsoleting.end() ) + { + if ( it->isKind( ResKind::product ) ) + ret.push_back( make( *it ) ); + } + + // If we have a buddy, we check what product buddies the + // buddy replaces. + obsoleting = sat::WhatObsoletes( poolItem().buddy() ); + for_( it, obsoleting.poolItemBegin(), obsoleting.poolItemEnd() ) + { + if ( (*it).buddy().isKind( ResKind::product ) ) + ret.push_back( make( (*it).buddy() ) ); + } + return ret; + } + + CapabilitySet Product::droplist() const + { return poolItem().buddy().valuesOfNamespace( "weakremover" ); } + + std::string Product::productLine() const + { return lookupStrAttribute( sat::SolvAttr::productProductLine ); } + + /////////////////////////////////////////////////////////////////// + + std::string Product::shortName() const + { + std::string ret( lookupStrAttribute( sat::SolvAttr::productShortlabel ) ); + if ( ret.empty() ) ret = name(); + return ret; + + } + + std::string Product::flavor() const + { + // Look for a provider of 'product_flavor(name) = version' + // within the same repo. Unlike the reference package, we + // can be relaxed and ignore the architecture. + Capability identCap( str::form( "product_flavor(%s) = %s", name().c_str(), edition().c_str() ) ); + + sat::WhatProvides providers( identCap ); + for_( it, providers.begin(), providers.end() ) + { + if ( it->repository() == repository() ) + { + // Got the package now try to get the provided 'flavor(...)' + Capabilities provides( it->provides() ); + for_( cap, provides.begin(), provides.end() ) + { + std::string capstr( cap->asString() ); + if ( str::hasPrefix( capstr, "flavor(" ) ) + { + capstr = str::stripPrefix( capstr, "flavor(" ); + capstr.erase( capstr.size()-1 ); // trailing ')' + return capstr; + } + } + } + } + return std::string(); + } + + std::string Product::type() const + { return lookupStrAttribute( sat::SolvAttr::productType ); } + + std::list Product::flags() const + { + std::list ret; + fillList( ret, satSolvable(), sat::SolvAttr::productFlags ); + return ret; + } + + Date Product::endOfLife() const + { return Date( lookupNumAttribute( sat::SolvAttr::productEndOfLife ) );} + + bool Product::hasEndOfLife() const + { return( lookupNumAttribute( sat::SolvAttr::productEndOfLife, -1 ) != (unsigned long long)(-1) ); } + + bool Product::hasEndOfLife( Date & value ) const + { + Date res( lookupNumAttribute( sat::SolvAttr::productEndOfLife, -1 ) ); + if ( res == -1 ) + return false; + // else: + value = res; + return true; + } + + std::vector Product::updateContentIdentifier() const + { + std::vector ret; + sat::LookupAttr q( sat::SolvAttr::productUpdatesRepoid, sat::SolvAttr::productUpdates, *this ); + if ( ! q.empty() ) + { + ret.reserve( 2 ); + for_( it, q.begin(), q.end() ) + ret.push_back( it.asString() ); + } + return ret; + } + + bool Product::hasUpdateContentIdentifier( const Repository::ContentIdentifier & cident_r ) const + { + sat::LookupAttr q( sat::SolvAttr::productUpdatesRepoid, sat::SolvAttr::productUpdates, *this ); + for_( it, q.begin(), q.end() ) + { + if ( it.asString() == cident_r ) + return true; + } + return false; + } + + bool Product::isTargetDistribution() const + { return isSystem() && lookupStrAttribute( sat::SolvAttr::productType ) == "base"; } + + std::string Product::registerTarget() const + { return lookupStrAttribute( sat::SolvAttr::productRegisterTarget ); } + + std::string Product::registerRelease() const + { return lookupStrAttribute( sat::SolvAttr::productRegisterRelease ); } + + std::string Product::registerFlavor() const + { return lookupStrAttribute( sat::SolvAttr::productRegisterFlavor ); } + + ///////////////////////////////////////////////////////////////// + + Product::UrlList Product::urls( const std::string & key_r ) const + { + UrlList ret; + + sat::LookupAttr url( sat::SolvAttr::productUrl, *this ); + sat::LookupAttr url_type( sat::SolvAttr::productUrlType, *this ); + + sat::LookupAttr::iterator url_it(url.begin()); + sat::LookupAttr::iterator url_type_it(url_type.begin()); + + for (;url_it != url.end(); ++url_it, ++url_type_it) + { + /* safety checks, shouldn't happen (tm) */ + if (url_type_it == url_type.end()) + { + ERR << *this << " : The thing that should not happen, happened." << endl; + break; + } + + if ( url_type_it.asString() == key_r ) + { + ret._list.push_back(url_it.asString()); + } + } /* while (attribute array) */ + + return ret; + } + + Product::UrlList Product::releaseNotesUrls() const { return urls( "releasenotes" ); } + Product::UrlList Product::registerUrls() const { return urls( "register" ); } + Product::UrlList Product::smoltUrls() const { return urls( "smolt" ); } + Product::UrlList Product::updateUrls() const { return urls( "update" ); } + Product::UrlList Product::extraUrls() const { return urls( "extra" ); } + Product::UrlList Product::optionalUrls() const { return urls( "optional" ); } + + std::ostream & operator<<( std::ostream & str, const Product::UrlList & obj ) + { return dumpRange( str << obj.key() << ' ', obj.begin(), obj.end() ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Product.h b/zypp/Product.h new file mode 100644 index 0000000..c276a63 --- /dev/null +++ b/zypp/Product.h @@ -0,0 +1,254 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Product.h + * +*/ +#ifndef ZYPP_PRODUCT_H +#define ZYPP_PRODUCT_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(Product); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Product + // + /** Product interface. + */ + class ZYPP_API Product : public ResObject + { + public: + using Self = Product; + using TraitsType = ResTraits; + using Ptr = TraitsType::PtrType; + using constPtr = TraitsType::constPtrType; + + public: + /** The reference package providing the product metadata, + * if such a package exists. + */ + sat::Solvable referencePackage() const; + + /** For installed products the name of the corresponding + * \c /etc/products.d entry. + .*/ + std::string referenceFilename() const; + + /** List of packages included in older versions of this product and now dropped. + * + * This evaluates the \ref referencePackage \c weakremover namespace. It actually + * returns a \ref CapabilitySet, because we support to drop specific versions or + * version ranges of a package. Use \ref sat::WhatProvides to get the actually + * installed and available packages matching this list. + * \code + * const Product & openSUSE; + * sat::WhatProvides dropped( openSUSE.droplist() ); + * for_( it, dropped.poolItemBegin(), dropped.poolItemEnd() ) + * { + * if ( it->status().isInstalled() ) + * { + * MIL << "Installed but no longer supported package: " << *it << endl; + * } + * } + * \endcode + */ + CapabilitySet droplist() const; + + public: + /***/ + using ReplacedProducts = std::vector; + + /** Array of \b installed Products that would be replaced by + * installing this one. + */ + ReplacedProducts replacedProducts() const; + + /** Vendor specific string denoting the product line. */ + std::string productLine() const; + + public: + /** Untranslated short name like SLES 10 (fallback: name) */ + std::string shortName() const; + + /** The product flavor (LiveCD Demo, FTP edition,...). */ + std::string flavor() const; + + /** Get the product type + * Well, in an ideal world there is only one base product. + * It's the installed product denoted by a symlink in + * \c /etc/products.d. + */ + std::string type() const; + + /** The product flags */ + std::list flags() const; + + /** The date when this Product goes out of support as indicated by its medadata. + * Use \ref hasEOfLife if it's important to distinguish whether the value + * is not defined in the metadata, or defined but empty/invalid/TBD. + */ + Date endOfLife() const; + + /** Return whether an EndOfLife value is actually defined in the metadata. + * A missing value (\c false) usually indicates that there will be no EOL, + * while an empty/invalid value indicates that there will be an EOL date, + * but it's not yet known (FATE#320699). + */ + bool hasEndOfLife() const; + /** \overload additionally returning the date (0 if TBD) + * false, ( unchanged ) : no EOL + * true, ( 0 ) : EOL is still TBD + * true, ( !=0 ) : a valid EOL date + */ + bool hasEndOfLife( Date & value ) const; + + /** ContentIdentifier of required update repositories. */ + std::vector updateContentIdentifier() const; + + /** Whether \a cident_r is listed as required update repository. */ + bool hasUpdateContentIdentifier( const Repository::ContentIdentifier & cident_r ) const; + + /** Whether one of the ContentIdentifier is listed as required update repository. */ + template + bool hasUpdateContentIdentifier( TIterator begin, TIterator end ) const + { + for_( it, begin, end ) + if ( hasUpdateContentIdentifier( *it ) ) + return true; + return false; + } + + public: + /** This is the \b installed product that is also targeted by the + * \c /etc/products.d/baseproduct symlink. + */ + bool isTargetDistribution() const; + + /** This is \c register.target attribute of a product. + * Used for registration and filtering service repos. + */ + std::string registerTarget() const; + + /** This is \c register.release attribute of an \b installed product. + * Used for registration. + */ + std::string registerRelease() const; + + /** This is \c register.flavor attribute of a product. + * Used for registration. + */ + std::string registerFlavor() const; + + public: + /***/ + class UrlList; + + /** Retrieve URLs flagged with \c key_r for this product. + * + * This is the most common interface. There are convenience methods for + * wellknown flags like \c "releasenotes", \c "register", \c "updateurls", + * \c "extraurls", \c "optionalurls" and \c "smolt" below. + */ + UrlList urls( const std::string & key_r ) const; + + /** The URL to download the release notes for this product. */ + UrlList releaseNotesUrls() const; + + /** The URL for registration. */ + UrlList registerUrls() const; + + /** The URL for SMOLT \see http://smolts.org/wiki/Main_Page. */ + UrlList smoltUrls() const; + + /** + * Online updates for the product. + * They are complementary, not alternatives. #163192 + */ + UrlList updateUrls() const; + + /** + * Additional software for the product + * They are complementary, not alternatives. + */ + UrlList extraUrls() const; + + /** + * Optional software for the product. + * (for example. Non OSS repositories) + * They are complementary, not alternatives. + */ + UrlList optionalUrls() const; + + protected: + friend Ptr make( const sat::Solvable & solvable_r ); + /** Ctor */ + Product( const sat::Solvable & solvable_r ); + /** Dtor */ + ~Product() override; + }; + + /** Helper to iterate a products URL lists. + * \ref first is a convenience for 'lists' with just + * one entry (e.g. releaseNotesUrls) + */ + class Product::UrlList + { + private: + /** \todo Change to directly iterate the .solv */ + using ListType = std::list; + + public: + using value_type = ListType::value_type; + using size_type = ListType::size_type; + using const_iterator = ListType::const_iterator; + + bool empty() const + { return _list.empty(); } + + size_type size() const + { return _list.size(); } + + const_iterator begin() const + { return _list.begin(); } + + const_iterator end() const + { return _list.end(); } + + /** The first Url or an empty Url. */ + Url first() const + { return empty() ? value_type() : _list.front(); } + + public: + /** The key used to retrieve this list (for debug) */ + std::string key() const + { return _key; } + + private: + friend class Product; + /** Change to directly iterate the .solv */ + std::string _key; + ListType _list; + }; + + /** \relates Product::UrlList Stream output. */ + std::ostream & operator<<( std::ostream & str, const Product::UrlList & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PRODUCT_H diff --git a/zypp/ProgressData.h b/zypp/ProgressData.h new file mode 100644 index 0000000..c78712d --- /dev/null +++ b/zypp/ProgressData.h @@ -0,0 +1 @@ +#include diff --git a/zypp/ProvideFilePolicy.cc b/zypp/ProvideFilePolicy.cc new file mode 100644 index 0000000..ef12aea --- /dev/null +++ b/zypp/ProvideFilePolicy.cc @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ProvideFilePolicy + // + /////////////////////////////////////////////////////////////////// + + bool ProvideFilePolicy::progress( int value ) const + { + if ( _progressCB ) + return _progressCB( value ); + return true; + } + +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ProvideFilePolicy.h b/zypp/ProvideFilePolicy.h new file mode 100644 index 0000000..0a1c4fd --- /dev/null +++ b/zypp/ProvideFilePolicy.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_PROVIDEFILEPOLICY_H +#define ZYPP_PROVIDEFILEPOLICY_H + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class ProvideFilePolicy + /// \brief Policy for \ref provideFile and \ref RepoMediaAccess. + /// + /// Provides callback hook for progress reporting and an optional + /// \ref FileCecker passed down to the \ref Fetcher. + /////////////////////////////////////////////////////////////////// + class ProvideFilePolicy + { + public: + /** Progress callback signature. */ + using ProgressCB = function; + + /** Set callback. */ + ProvideFilePolicy & progressCB( ProgressCB progressCB_r ) + { _progressCB = std::move(progressCB_r); return *this; } + + /** Evaluate callback. */ + bool progress( int value ) const; + + public: + /** Add a \ref FileCecker passed down to the \ref Fetcher */ + ProvideFilePolicy & fileChecker( FileChecker fileChecker_r ) + { _fileChecker = std::move(fileChecker_r); return *this; } + + /** The \ref FileCecker. */ + const FileChecker & fileChecker() const + { return _fileChecker; } + + private: + FileChecker _fileChecker; + ProgressCB _progressCB; + }; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PROVIDEFILEPOLICY_H diff --git a/zypp/PublicKey.cc b/zypp/PublicKey.cc new file mode 100644 index 0000000..c15bd98 --- /dev/null +++ b/zypp/PublicKey.cc @@ -0,0 +1,716 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PublicKey.cc + * +*/ +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::gpg" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace + { + inline bool isExpired( const Date & expires_r ) + { return( expires_r && expires_r < Date::now() ); } + + inline int hasDaysToLive( const Date & expires_r ) + { + if ( expires_r ) + { + Date exp( expires_r - Date::now() ); + int ret = exp / Date::day; + if ( exp < 0 ) ret -= 1; + return ret; + } + return INT_MAX; + } + + inline std::string expiresDetail( const Date & expires_r ) + { + str::Str str; + if ( ! expires_r ) + { + // translators: an annotation to a gpg keys expiry date + str << _("does not expire"); + } + else if ( isExpired( expires_r ) ) + { + // translators: an annotation to a gpg keys expiry date: "expired: 1999-04-12" + str << ( str::Format(_("expired: %1%") ) % expires_r.printDate() ); + } + else + { + // translators: an annotation to a gpg keys expiry date: "expires: 2111-04-12" + str << ( str::Format(_("expires: %1%") ) % expires_r.printDate() ); + } + return str; + } + + inline std::string expiresDetailVerbose( const Date & expires_r ) + { + if ( !expires_r ) + { // translators: an annotation to a gpg keys expiry date + return _("(does not expire)"); + } + std::string ret( expires_r.asString() ); + int ttl( hasDaysToLive( expires_r ) ); + if ( ttl <= 90 ) + { + ret += " "; + if ( ttl < 0 ) + { // translators: an annotation to a gpg keys expiry date + ret += _("(EXPIRED)"); + } + else if ( ttl == 0 ) + { // translators: an annotation to a gpg keys expiry date + ret += _("(expires within 24h)"); + } + else + { // translators: an annotation to a gpg keys expiry date + ret += str::form( PL_("(expires in %d day)", "(expires in %d days)", ttl ), ttl ); + } + } + return ret; + } + + inline std::string keyAlgoName( const gpgme_subkey_t & key_r ) + { + std::string ret; + if ( const char * n = ::gpgme_pubkey_algo_name( key_r->pubkey_algo ) ) + ret = str::Str() << n << ' ' << key_r->length; + else + ret = "?"; + return ret; + } + + inline bool shorterIsSuffixCI( const std::string & lhs, const std::string & rhs ) + { + if ( lhs.size() >= rhs.size() ) + return str::endsWithCI( lhs, rhs ); + return str::endsWithCI( rhs, lhs ); + } + } //namespace + /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + /// \class PublicSubkeyData::Impl + /// \brief PublicSubkeyData implementation. + /////////////////////////////////////////////////////////////////// + + struct PublicSubkeyData::Impl + { + std::string _id; + Date _created; + Date _expires; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl(); + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const; + }; + + shared_ptr PublicSubkeyData::Impl::nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + zypp::PublicSubkeyData::Impl *PublicSubkeyData::Impl::clone() const + { + return new Impl( *this ); + } + + /////////////////////////////////////////////////////////////////// + /// class PublicSubkeyData + /////////////////////////////////////////////////////////////////// + + PublicSubkeyData::PublicSubkeyData() + : _pimpl( Impl::nullimpl() ) + {} + + PublicSubkeyData::PublicSubkeyData(const _gpgme_subkey *rawSubKeyData) + : _pimpl (new Impl) + { + _pimpl->_created = zypp::Date(rawSubKeyData->timestamp); + _pimpl->_expires = zypp::Date(rawSubKeyData->expires); + _pimpl->_id = str::asString(rawSubKeyData->keyid); + } + + PublicSubkeyData::~PublicSubkeyData() + {} + + PublicSubkeyData::operator bool() const + { return !_pimpl->_id.empty(); } + + std::string PublicSubkeyData::id() const + { return _pimpl->_id; } + + Date PublicSubkeyData::created() const + { return _pimpl->_created; } + + Date PublicSubkeyData::expires() const + { return _pimpl->_expires; } + + bool PublicSubkeyData::expired() const + { return isExpired( _pimpl->_expires ); } + + int PublicSubkeyData::daysToLive() const + { return hasDaysToLive( _pimpl->_expires ); } + + std::string PublicSubkeyData::asString() const + { + return str::Str() << id() << " " << created().printDate() << " [" << expiresDetail( expires() ) << "]"; + } + + /////////////////////////////////////////////////////////////////// + /// \class PublicKeySignatureData::Impl + /// \brief PublicKeySignatureData implementation. + /////////////////////////////////////////////////////////////////// + + struct PublicKeySignatureData::Impl + { + std::string _keyid; + std::string _name; + Date _created; + Date _expires; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl(); + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const; + }; + + shared_ptr PublicKeySignatureData::Impl::nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + zypp::PublicKeySignatureData::Impl *PublicKeySignatureData::Impl::clone() const + { + return new Impl( *this ); + } + + /////////////////////////////////////////////////////////////////// + /// class PublicKeySignatureData + /////////////////////////////////////////////////////////////////// + + PublicKeySignatureData::PublicKeySignatureData() + : _pimpl( Impl::nullimpl() ) + {} + + PublicKeySignatureData::PublicKeySignatureData(const _gpgme_key_sig *rawKeySignatureData) + : _pimpl (new Impl) + { + _pimpl->_keyid = str::asString(rawKeySignatureData->keyid); + _pimpl->_name = str::asString(rawKeySignatureData->uid); + _pimpl->_created = zypp::Date(rawKeySignatureData->timestamp); + _pimpl->_expires = zypp::Date(rawKeySignatureData->expires); + } + + PublicKeySignatureData::~PublicKeySignatureData() + {} + + PublicKeySignatureData::operator bool() const + { return !_pimpl->_keyid.empty(); } + + std::string PublicKeySignatureData::id() const + { return _pimpl->_keyid; } + + std::string PublicKeySignatureData::name() const + { return _pimpl->_name; } + + Date PublicKeySignatureData::created() const + { return _pimpl->_created; } + + Date PublicKeySignatureData::expires() const + { return _pimpl->_expires; } + + bool PublicKeySignatureData::expired() const + { return isExpired( _pimpl->_expires ); } + + int PublicKeySignatureData::daysToLive() const + { return hasDaysToLive( _pimpl->_expires ); } + + std::string PublicKeySignatureData::asString() const + { + std::string nameStr; + if (!name().empty()) { + nameStr = str::Str() << name() << " "; + } + else { + nameStr = "[User ID not found] "; + } + return str::Str() << nameStr + << id() << " " + << created().printDate() + << " [" << expiresDetail( expires() ) << "]"; + } + + bool PublicKeySignatureData::inTrustedRing() const + { return getZYpp()->keyRing()->isKeyTrusted(id()); } + + bool PublicKeySignatureData::inKnownRing() const + { return getZYpp()->keyRing()->isKeyKnown(id()); } + + /////////////////////////////////////////////////////////////////// + /// \class PublicKeyData::Impl + /// \brief PublicKeyData implementation. + /////////////////////////////////////////////////////////////////// + /// + struct PublicKeyData::Impl + { + std::string _id; + std::string _name; + std::string _fingerprint; + std::string _algoName; + Date _created; + Date _expires; + + std::vector _subkeys; + std::vector _signatures; + + public: + bool hasSubkeyId( const std::string & id_r ) const; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl(); + static shared_ptr fromGpgmeKey(gpgme_key_t rawData); + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const; + }; + + bool PublicKeyData::Impl::hasSubkeyId( const std::string &id_r) const + { + bool ret = false; + for ( const PublicSubkeyData & sub : _subkeys ) { + if ( shorterIsSuffixCI( sub.id(), id_r ) ) { + ret = true; + break; + } + } + return ret; + } + + shared_ptr PublicKeyData::Impl::nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + shared_ptr PublicKeyData::Impl::fromGpgmeKey(gpgme_key_t rawData) + { + //gpgme stores almost nothing in the top level key + //the information we look for is stored in the subkey, where subkey[0] + //is always the primary key + gpgme_subkey_t sKey = rawData->subkeys; + if (sKey) { + shared_ptr data(new Impl); + //libzypp expects the date of the latest signature on the first uid + if ( rawData->uids && rawData->uids->signatures ) { + data->_created = zypp::Date(rawData->uids->signatures->timestamp); + // bsc#1179222: The keyring does not order the signatures when multiple + // versions of the same key are imported. We take the last signature here, + // the one GPGME_EXPORT_MODE_MINIMAL will later use in export. + for ( auto t = rawData->uids->signatures->next; t; t = t->next ) { + if (t->keyid != nullptr) { + data->_signatures.push_back(PublicKeySignatureData(t)); + } + + if ( t->timestamp > data->_created ) + data->_created = t->timestamp; + } + } + else + data->_created = zypp::Date(sKey->timestamp); + + data->_expires = zypp::Date(sKey->expires); + data->_fingerprint = str::asString(sKey->fpr); + data->_algoName = keyAlgoName( sKey ); + data->_id = str::asString(sKey->keyid); + + //get the primary user ID + if (rawData->uids) { + data->_name = str::asString(rawData->uids->uid); + } + + //the rest of the keys + sKey = sKey->next; + while (sKey) { + data->_subkeys.push_back( PublicSubkeyData(sKey) ); + sKey = sKey->next; + } + return data; + } + return nullimpl(); + } + + zypp::PublicKeyData::Impl *PublicKeyData::Impl::clone() const + { + return new Impl( *this ); + } + + /////////////////////////////////////////////////////////////////// + /// class PublicKeyData + /////////////////////////////////////////////////////////////////// + + PublicKeyData::PublicKeyData() + : _pimpl( Impl::nullimpl() ) + {} + + PublicKeyData::PublicKeyData(shared_ptr data) + : _pimpl( std::move(data) ) + {} + + PublicKeyData::~PublicKeyData() + {} + + PublicKeyData PublicKeyData::fromGpgmeKey(_gpgme_key *data) + { return PublicKeyData(Impl::fromGpgmeKey(data)); } + + PublicKeyData::operator bool() const + { return !_pimpl->_fingerprint.empty(); } + + std::string PublicKeyData::id() const + { return _pimpl->_id; } + + std::string PublicKeyData::name() const + { return _pimpl->_name; } + + std::string PublicKeyData::fingerprint() const + { return _pimpl->_fingerprint; } + + std::string PublicKeyData::algoName() const + { return _pimpl->_algoName; } + + Date PublicKeyData::created() const + { return _pimpl->_created; } + + Date PublicKeyData::expires() const + { return _pimpl->_expires; } + + bool PublicKeyData::expired() const + { return isExpired( _pimpl->_expires ); } + + int PublicKeyData::daysToLive() const + { return hasDaysToLive( _pimpl->_expires ); } + + std::string PublicKeyData::expiresAsString() const + { return expiresDetailVerbose( _pimpl->_expires ); } + + std::string PublicKeyData::gpgPubkeyVersion() const + { return _pimpl->_id.empty() ? _pimpl->_id : str::toLower( _pimpl->_id.substr(8,8) ); } + + std::string PublicKeyData::gpgPubkeyRelease() const + { return _pimpl->_created ? str::hexstring( _pimpl->_created ).substr(2) : std::string(); } + + std::string PublicKeyData::rpmName() const + { return str::Format( "gpg-pubkey-%1%-%2%" ) % gpgPubkeyVersion() % gpgPubkeyRelease(); } + + std::string PublicKeyData::asString() const + { + if ( not *this ) + return "[NO_KEY]"; + + str::Str str; + str << "[" << _pimpl->_id << "-" << gpgPubkeyRelease(); + for ( auto && sub : _pimpl->_subkeys ) + str << ", " << sub.id(); + return str << "] [" << _pimpl->_name.c_str() << "] [" << expiresDetail( _pimpl->_expires ) << "]"; + } + + bool PublicKeyData::hasSubkeys() const + { return !_pimpl->_subkeys.empty(); } + + Iterable PublicKeyData::subkeys() const + { return makeIterable( &(*_pimpl->_subkeys.begin()), &(*_pimpl->_subkeys.end()) ); } + + Iterable PublicKeyData::signatures() const + { return makeIterable( &(*_pimpl->_signatures.begin()), &(*_pimpl->_signatures.end()) ); } + + bool PublicKeyData::providesKey( const std::string & id_r ) const + { + if ( not isSafeKeyId( id_r ) ) + return( id_r.size() == 8 && str::endsWithCI( _pimpl->_id, id_r ) ); + + if ( str::endsWithCI( _pimpl->_fingerprint, id_r ) ) + return true; + + return _pimpl->hasSubkeyId( id_r ); + } + + PublicKeyData::AsciiArt PublicKeyData::asciiArt() const + { return AsciiArt( fingerprint(), algoName() ); } + + std::ostream & dumpOn( std::ostream & str, const PublicKeyData & obj ) + { + str << "[" << obj.name() << "]" << endl; + str << " fpr " << obj.fingerprint() << endl; + str << " id " << obj.id() << endl; + str << " alg " << obj.algoName() << endl; + str << " cre " << Date::ValueType(obj.created()) << ' ' << obj.created() << endl; + str << " exp " << Date::ValueType(obj.expires()) << ' ' << obj.expiresAsString() << endl; + str << " ttl " << obj.daysToLive() << endl; + for ( auto && sub : obj._pimpl->_subkeys ) + str << " sub " << sub << endl; + str << " rpm " << obj.gpgPubkeyVersion() << "-" << obj.gpgPubkeyRelease() << endl; + return str; + } + + bool operator==( const PublicKeyData & lhs, const PublicKeyData & rhs ) + { return ( lhs.fingerprint() == rhs.fingerprint() && lhs.created() == rhs.created() ); } + + + /////////////////////////////////////////////////////////////////// + /// \class PublicKey::Impl + /// \brief PublicKey implementation. + /////////////////////////////////////////////////////////////////// + struct PublicKey::Impl + { + Impl() + {} + + Impl( const Pathname & keyFile_r ) + : _dontUseThisPtrDirectly( new filesystem::TmpFile ) + { + PathInfo info( keyFile_r ); + MIL << "Taking pubkey from " << keyFile_r << " of size " << info.size() << " and sha1 " << filesystem::checksum(keyFile_r, "sha1") << endl; + + if ( !info.isExist() ) + ZYPP_THROW(Exception("Can't read public key from " + keyFile_r.asString() + ", file not found")); + + if ( filesystem::hardlinkCopy( keyFile_r, path() ) != 0 ) + ZYPP_THROW(Exception("Can't copy public key data from " + keyFile_r.asString() + " to " + path().asString() )); + + readFromFile(); + } + + Impl( const filesystem::TmpFile & sharedFile_r ) + : _dontUseThisPtrDirectly( new filesystem::TmpFile( sharedFile_r ) ) + { readFromFile(); } + + // private from keyring + Impl( const filesystem::TmpFile & sharedFile_r, const PublicKeyData & keyData_r ) + : _dontUseThisPtrDirectly( new filesystem::TmpFile( sharedFile_r ) ) + , _keyData( keyData_r ) + { + if ( ! keyData_r ) + { + WAR << "Invalid PublicKeyData supplied: scanning from file" << endl; + readFromFile(); + } + } + + // private from keyring + Impl( const PublicKeyData & keyData_r ) + : _keyData( keyData_r ) + {} + + public: + const PublicKeyData & keyData() const + { return _keyData; } + + Pathname path() const + { return( /*the one and only intended use*/_dontUseThisPtrDirectly ? _dontUseThisPtrDirectly->path() : Pathname() ); } + + const std::list & hiddenKeys() const + { return _hiddenKeys; } + + protected: + void readFromFile() + { + PathInfo info( path() ); + MIL << "Reading pubkey from " << info.path() << " of size " << info.size() << " and sha1 " << filesystem::checksum(info.path(), "sha1") << endl; + + std::list keys = KeyManagerCtx::createForOpenPGP().readKeyFromFile( path() ); + switch ( keys.size() ) + { + case 0: + ZYPP_THROW( BadKeyException( "File " + path().asString() + " doesn't contain public key data" , path() ) ); + break; + + case 1: + // ok. + _keyData = keys.back(); + _hiddenKeys.clear(); + break; + + default: + WAR << "File " << path().asString() << " contains multiple keys: " << keys << endl; + _keyData = keys.back(); + keys.pop_back(); + _hiddenKeys.swap( keys ); + break; + } + + MIL << "Read pubkey from " << info.path() << ": " << _keyData << endl; + } + + private: + shared_ptr _dontUseThisPtrDirectly; // shared_ptr ok because TmpFile itself is a refernce type (no COW) + PublicKeyData _keyData; + std::list _hiddenKeys; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // class PublicKey + /////////////////////////////////////////////////////////////////// + PublicKey::PublicKey() + : _pimpl( Impl::nullimpl() ) + {} + + PublicKey::PublicKey( const Pathname & file ) + : _pimpl( new Impl( file ) ) + {} + + PublicKey::PublicKey( const filesystem::TmpFile & sharedfile ) + : _pimpl( new Impl( sharedfile ) ) + {} + + PublicKey::PublicKey( const filesystem::TmpFile & sharedfile, const PublicKeyData & keyData_r ) + : _pimpl( new Impl( sharedfile, keyData_r ) ) + {} + + PublicKey::PublicKey( const PublicKeyData & keyData_r ) + : _pimpl( new Impl( keyData_r ) ) + {} + + PublicKey::~PublicKey() + {} + + PublicKey PublicKey::noThrow( const Pathname & keyFile_r ) + try { return PublicKey( keyFile_r ); } catch(...) { return PublicKey(); } + + const PublicKeyData & PublicKey::keyData() const + { return _pimpl->keyData(); } + + Pathname PublicKey::path() const + { return _pimpl->path(); } + + const std::list & PublicKey::hiddenKeys() const + { return _pimpl->hiddenKeys(); } + + bool PublicKey::fileProvidesKey( const std::string & id_r ) const + { + if ( providesKey( id_r ) ) + return true; + for ( const auto & keydata : hiddenKeys() ) { + if ( keydata.providesKey( id_r ) ) + return true; + } + return false; + } + + std::string PublicKey::id() const + { return keyData().id(); } + + std::string PublicKey::name() const + { return keyData().name(); } + + std::string PublicKey::fingerprint() const + { return keyData().fingerprint(); } + + std::string PublicKey::algoName() const + { return keyData().algoName(); } + + Date PublicKey::created() const + { return keyData().created(); } + + Date PublicKey::expires() const + { return keyData().expires(); } + + bool PublicKey::expired() const + { return keyData().expired(); } + + int PublicKey::daysToLive() const + { return keyData().daysToLive(); } + + std::string PublicKey::expiresAsString() const + { return keyData().expiresAsString(); } + + std::string PublicKey::gpgPubkeyVersion() const + { return keyData().gpgPubkeyVersion(); } + + std::string PublicKey::gpgPubkeyRelease() const + { return keyData().gpgPubkeyRelease(); } + + std::string PublicKey::asString() const + { return keyData().asString(); } + + std::string PublicKey::rpmName() const + { return keyData().rpmName(); } + + bool PublicKey::operator==( const PublicKey & rhs ) const + { return rhs.keyData() == keyData(); } + + bool PublicKey::operator==( const std::string & sid ) const + { return ( isSafeKeyId( sid ) || sid.size() == 8 ) && str::endsWithCI( fingerprint(), sid ); } + + std::ostream & dumpOn( std::ostream & str, const PublicKey & obj ) + { return dumpOn( str, obj.keyData() ); } + + + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/PublicKey.h b/zypp/PublicKey.h new file mode 100644 index 0000000..0ade799 --- /dev/null +++ b/zypp/PublicKey.h @@ -0,0 +1,484 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PublicKey.h + * +*/ +#ifndef ZYPP_PUBLICKEY_H +#define ZYPP_PUBLICKEY_H + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +struct _gpgme_key; +struct _gpgme_subkey; +struct _gpgme_key_sig; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace filesystem + { + class TmpFile; + } + class PublicKeyData; + class KeyManagerCtx; + + /////////////////////////////////////////////////////////////////// + /// \class BadKeyException + /// \brief Exception thrown when the supplied key is not a valid gpg key + /////////////////////////////////////////////////////////////////// + class ZYPP_API BadKeyException : public Exception + { + public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + BadKeyException() + : Exception( "Bad Key Exception" ) + {} + + Pathname keyFile() const + { return _keyfile; } + + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + BadKeyException( const std::string & msg_r, Pathname keyfile = Pathname() ) + : Exception( msg_r ), _keyfile(std::move(keyfile)) + {} + /** Dtor. */ + ~BadKeyException() throw() override {}; + private: + Pathname _keyfile; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class PublicSubkeyData + /// \brief Class representing a GPG Public Keys subkeys. + /// \see \ref PublicKeyData. + /////////////////////////////////////////////////////////////////// + class ZYPP_API PublicSubkeyData + { + public: + /** Default constructed: empty data. */ + PublicSubkeyData(); + + ~PublicSubkeyData(); + + /** Whether this contains valid data (not default constructed). */ + explicit operator bool() const; + + public: + /** Subkey ID. */ + std::string id() const; + + /** Creation date. */ + Date created() const; + + /** Expiry date, or \c Date() if the key never expires. */ + Date expires() const; + + /** Whether the key has expired. */ + bool expired() const; + + /** Number of days (24h) until the key expires (or since it exired). + * A value of \c 0 means the key will expire within the next 24h. + * Negative values indicate the key has expired less than \c N days ago. + * For keys without expiration date \c INT_MAX is returned. + */ + int daysToLive() const; + + /** Simple string representation. + * Encodes \ref id, \ref created and \ref expires + * \code + * 640DB551 2016-04-12 [expires: 2019-04-12] + * \endcode + */ + std::string asString() const; + + private: + struct Impl; + RWCOW_pointer _pimpl; + friend class PublicKeyData; + friend std::ostream & dumpOn( std::ostream & str, const PublicKeyData & obj ); + PublicSubkeyData(const _gpgme_subkey *rawSubKeyData); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PublicSubkeyData Stream output */ + inline std::ostream & operator<<( std::ostream & str, const PublicSubkeyData & obj ) + { return str << obj.asString(); } + + /////////////////////////////////////////////////////////////////// + /// \class PublicKeySignatureData + /// \brief Class representing a signature on a GPG Public Key. + /// \see \ref PublicKeyData. + /////////////////////////////////////////////////////////////////// + class ZYPP_API PublicKeySignatureData + { + public: + /** Default constructed: empty data. */ + PublicKeySignatureData(); + + ~PublicKeySignatureData(); + + /** Whether this contains valid data (not default constructed). */ + explicit operator bool() const; + + public: + /** The key ID of key used to create the signature. */ + std::string id() const; + + /** The user ID associated with this key, if present. */ + std::string name() const; + + /** Creation date. */ + Date created() const; + + /** Expiry date, or \c Date() if the key never expires. */ + Date expires() const; + + /** Whether the key has expired. */ + bool expired() const; + + /** Number of days (24h) until the key expires (or since it expired). + * A value of \c 0 means the key will expire within the next 24h. + * Negative values indicate the key has expired less than \c N days ago. + * For keys without expiration date \c INT_MAX is returned. + */ + int daysToLive() const; + + /** Whether the signature is trusted in rpmdb. */ + bool inTrustedRing() const; + + /** Whether the key has been seen before. */ + bool inKnownRing() const; + + /** Simple string representation. + * Encodes \ref id, \ref created and \ref expires + * \code + * 640DB551 2016-04-12 [expires: 2019-04-12] + * \endcode + */ + std::string asString() const; + + private: + struct Impl; + RWCOW_pointer _pimpl; + friend class PublicKeyData; + friend std::ostream & dumpOn( std::ostream & str, const PublicKeyData & obj ); + PublicKeySignatureData(const _gpgme_key_sig *rawKeySignatureData); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PublicKeySignatureData Stream output */ + inline std::ostream & operator<<( std::ostream & str, const PublicKeySignatureData & obj ) + { return str << obj.asString(); } + + /////////////////////////////////////////////////////////////////// + /// \class PublicKeyData + /// \brief Class representing one GPG Public Keys data. + /// \ref PublicKeyData are provided e.g. by a \ref PublicKey or + /// a \ref KeyRing. \ref PublicKeyData are usually easier to + /// retrieve and sufficient unless you actually need an ASCII + /// armored version of the key placed in a tempfile. In this + /// case use \ref PublicKey. + /////////////////////////////////////////////////////////////////// + class ZYPP_API PublicKeyData + { + public: + /** Default constructed: empty data. */ + PublicKeyData(); + + ~PublicKeyData(); + + PublicKeyData(const PublicKeyData &) = default; + PublicKeyData(PublicKeyData &&) noexcept = default; + PublicKeyData &operator=(const PublicKeyData &) = default; + PublicKeyData &operator=(PublicKeyData &&) noexcept = default; + + /** Whether this contains valid data (not default constructed). */ + explicit operator bool() const; + + public: + /** Key ID. */ + std::string id() const; + + /** Key name. */ + std::string name() const; + + /** Key fingerprint.*/ + std::string fingerprint() const; + + /** Key algorithm string like `RSA 2048` */ + std::string algoName() const; + + /** Creation / last modification date (latest selfsig). */ + Date created() const; + + /** Expiry date, or \c Date() if the key never expires. */ + Date expires() const; + + /** Whether the key has expired. */ + bool expired() const; + + /** Number of days (24h) until the key expires (or since it exired). + * A value of \c 0 means the key will expire within the next 24h. + * Negative values indicate the key has expired less than \c N days ago. + * For keys without expiration date \c INT_MAX is returned. + */ + int daysToLive() const; + + /** * Expiry info in a human readable form. + * The expiry date plus an annotation if the key has expired, or will + * expire within 90 days. + * \code + * (does not expire) + * Tue May 11 13:37:33 CEST 2010 + * Tue May 11 13:37:33 CEST 2010 (expires in 90 days) + * Tue May 11 13:37:33 CEST 2010 (expires in 1 day) + * Tue May 11 13:37:33 CEST 2010 (expires within 24h) + * Tue May 11 13:37:33 CEST 2010 (EXPIRED) + * \endcode + */ + std::string expiresAsString() const; + + /** Gpg-pubkey version as computed by rpm (trailing 8 byte \ref id) */ + std::string gpgPubkeyVersion() const; + + /** Gpg-pubkey release as computed by rpm (hexencoded \ref created) */ + std::string gpgPubkeyRelease() const; + + /** Gpg-pubkey name as computed by rpm*/ + std::string rpmName () const; + + /** Gpg-pubkey \ref Edition built from version and release.*/ + Edition gpgPubkeyEdition() const + { return Edition( gpgPubkeyVersion(), gpgPubkeyRelease() ); } + + /** Simple string representation. + * Encodes \ref id, \ref gpgPubkeyRelease, \ref name and \ref fingerprint. + * \code + * [E3A5C360307E3D54-4be01a65] [SuSE Package Signing Key ] [4E98E67519D98DC7362A5990E3A5C360307E3D54] + * \endcode + */ + std::string asString() const; + + public: + using SubkeyIterator = const PublicSubkeyData *; + using KeySignatureIterator = const PublicKeySignatureData *; + + /** Whether \ref subkeys is not empty. */ + bool hasSubkeys() const; + + /** Iterate any subkeys. */ + Iterable subkeys() const; + + /** Iterate all key signatures. */ + Iterable signatures() const; + + /** Whether \a id_r is the \ref id or \ref fingerprint of the primary key or of a subkey. + * As a convenience also allows to test the 8byte short ID e.g. rpm uses as version. + */ + bool providesKey( const std::string & id_r ) const; + + /** Whether this is a long id (64bit/16byte) or even better a fingerprint. + * A short Id (32bit/8byte) is not considered to be a safe identifier for a key. + */ + static bool isSafeKeyId( const std::string & id_r ) + { return id_r.size() >= 16; } + + public: + /** Whether \ref signatures is not empty. */ + bool hasSignatures() const; + + public: + /** Random art fingerprint visualization type (\ref base::DrunkenBishop). */ + using AsciiArt = base::DrunkenBishop; + + /** Random art fingerprint visualization (\ref base::DrunkenBishop). + * \code + * PublicKeyData key; + * cout << key.asciiArt( PublicKey::AsciiArt::USE_COLOR ) << endl; + * \endcode + */ + AsciiArt asciiArt() const; + + private: + struct Impl; + RWCOW_pointer _pimpl; + + friend class KeyManagerCtx; + static PublicKeyData fromGpgmeKey(_gpgme_key *data); + + PublicKeyData(shared_ptr data); + friend std::ostream & dumpOn( std::ostream & str, const PublicKeyData & obj ); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PublicKeyData Stream output */ + inline std::ostream & operator<<( std::ostream & str, const PublicKeyData & obj ) + { return str << obj.asString(); } + + /** \relates PublicKeyData Detailed stream output */ + std::ostream & dumpOn( std::ostream & str, const PublicKeyData & obj ) ZYPP_API; + + /** \relates PublicKeyData Equal based on fingerprint anf creation date. */ + bool operator==( const PublicKeyData & lhs, const PublicKeyData & rhs ) ZYPP_API; + + /** \relates PublicKeyData NotEqual. */ + inline bool operator!=( const PublicKeyData & lhs, const PublicKeyData & rhs ) + { return !( lhs == rhs ); } + + /////////////////////////////////////////////////////////////////// + /// \class PublicKey + /// \brief Class representing one GPG Public Key (PublicKeyData + ASCII armored in a tempfile). + /// + /// If you don't need the ASCII armored version of the key stored in + /// a tempfile, using \ref PublicKeyData might be sufficient. + /// + /// \note In case the ASCII armored blob actually contains multiple + /// keys, the \b last keys data are made available via the API. The + /// additional keys data are made available via \ref hiddenKeys. + /////////////////////////////////////////////////////////////////// + class ZYPP_API PublicKey + { + public: + /** Implementation */ + struct Impl; + + public: + /** Default ctor. */ + PublicKey(); + + /** Ctor taking the key from a file. + * + * This is quite expensive, as a copy of the file is created and + * used. If you can construct PublicKey from a \ref filesystem::TmpFile, + * this prevents copying. + * + * \throws when data does not make a key + */ + explicit PublicKey( const Pathname & keyFile_r ); + + /** Ctor reading the key from a \ref TmpFile. + * + * PublicKey holds a reference on the TmpFile providing the key. + * + * \throws when data does not make a key + */ + explicit PublicKey( const filesystem::TmpFile & sharedFile_r ); + + ~PublicKey(); + + /** Static ctor returning an empty PublicKey rather than throwing. */ + static PublicKey noThrow( const Pathname & keyFile_r ); + + public: + /** The public keys data (\see \ref PublicKeyData).*/ + const PublicKeyData & keyData() const; + + using SubkeyIterator = PublicKeyData::SubkeyIterator; + + bool isValid() const + { return ! ( id().empty() || fingerprint().empty() ); } + + std::string id() const; //!< \see \ref PublicKeyData + std::string name() const; //!< \see \ref PublicKeyData + std::string fingerprint() const; //!< \see \ref PublicKeyData + std::string algoName() const; //!< \see \ref PublicKeyData + Date created() const; //!< \see \ref PublicKeyData + Date expires() const; //!< \see \ref PublicKeyData + std::string expiresAsString() const; //!< \see \ref PublicKeyData + bool expired() const; //!< \see \ref PublicKeyData + int daysToLive() const; //!< \see \ref PublicKeyData + std::string gpgPubkeyVersion() const; //!< \see \ref PublicKeyData + std::string gpgPubkeyRelease() const; //!< \see \ref PublicKeyData + std::string asString() const; //!< \see \ref PublicKeyData + std::string rpmName () const; + + Edition gpgPubkeyEdition() const ///!< \see \ref PublicKeyData + { return keyData().gpgPubkeyEdition(); } + + bool hasSubkeys() const ///!< \see \ref PublicKeyData + { return keyData().hasSubkeys(); } + + Iterable subkeys() const ///!< \see \ref PublicKeyData + { return keyData().subkeys(); } + + bool providesKey( const std::string & id_r ) const ///!< \see \ref PublicKeyData + { return keyData().providesKey( id_r ); } + + static bool isSafeKeyId( const std::string & id_r ) ///!< \see \ref PublicKeyData + { return PublicKeyData::isSafeKeyId(id_r); } + + public: + using AsciiArt = PublicKeyData::AsciiArt; ///!< \see \ref PublicKeyData + + AsciiArt asciiArt() const ///!< \see \ref PublicKeyData + { return keyData().asciiArt(); } + + public: + /** File containing the ASCII armored key. */ + Pathname path() const; + + /** Additional keys data in case the ASCII armored blob contains multiple keys. */ + const std::list & hiddenKeys() const; + + /** Extends \ref providesKey to look at the hidden keys too. + * Those 'hidden' keys become visible when the file is imported into a keyring. + */ + bool fileProvidesKey( const std::string & id_r ) const; + + public: + bool operator==( const PublicKey & rhs ) const; + bool operator!=( const PublicKey & rhs ) const + { return not operator==( rhs ); } + bool operator==( const std::string & sid ) const; + bool operator!=( const std::string & sid ) const + { return not operator==( sid ); } + + private: + friend class KeyRing; + /** KeyRing ctor: No need to parse file if KeyRing already had valid KeyData. */ + PublicKey( const filesystem::TmpFile & sharedFile_r, const PublicKeyData & keyData_r ); + /** KeyRing ctor: Legacy callback APIs take PublicKey, but just need the PublicKeyData No need to export to file. */ + explicit PublicKey( const PublicKeyData & keyData_r ); + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PublicKey Stream output */ + inline std::ostream & operator<<( std::ostream & str, const PublicKey & obj ) + { return str << obj.asString(); } + + /** \relates PublicKey Detailed stream output */ + std::ostream & dumpOn( std::ostream & str, const PublicKey & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PUBLICKEY_H diff --git a/zypp/PurgeKernels.cc b/zypp/PurgeKernels.cc new file mode 100644 index 0000000..bb7d16a --- /dev/null +++ b/zypp/PurgeKernels.cc @@ -0,0 +1,697 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PurgeKernels.cc + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "PurgeKernels" + +namespace zypp { + + using Flavour = std::string; + using SolvableList = std::list; + using EditionToSolvableMap = std::map; + using ArchToEditionMap = std::map; + + struct GroupInfo { + + enum GroupType { + None, //<< Just here to support default construction + Kernels, //<< Map contains kernel packages, so need to receive special handling and flavour matching + RelatedBinaries, //<< Map contains related binary packages, so need to receive special handling and flavour matching + Sources //<< Map contains source packages, so when matching those against running we ignore the flavour + } groupType; + + GroupInfo( const GroupType type = None, std::string flav = "") : groupType(type), groupFlavour( std::move(flav) ) { } + + ArchToEditionMap archToEdMap; //<< Map of actual packages + std::string groupFlavour; //<< This would contain a specific flavour if there is one calculated + }; + using GroupMap = std::unordered_map; + + struct PurgeKernels::Impl { + + Impl() { + struct utsname unameData; + if ( uname( &unameData) == 0 ) { + + const auto archStr = str::regex_substitute( unameData.machine, str::regex( "^i.86$", str::regex::match_extended ), "i586" ); + + _kernelArch = Arch( archStr ); + setUnameR( std::string( unameData.release ) ); + + _detectedRunning = true; + + MIL << "Detected running kernel: Flavour: " << _runningKernelFlavour << " Arch: " << _kernelArch << "\n"; + for ( const auto &edVar : _runningKernelEditionVariants ) + MIL << "Edition variant: " << edVar << "\n"; + MIL << std::endl; + + } else { + MIL << "Failed to detect running kernel: " << errno << std::endl; + } + } + + void setUnameR ( const std::string &uname ) { + + _uname_r = uname; + + MIL << "Set uname " << uname << std::endl; + + const std::string flavour = str::regex_substitute( _uname_r, str::regex( ".*-", str::regex::match_extended ), "", true ); + std::string version = str::regex_substitute( _uname_r, str::regex( "-[^-]*$", str::regex::match_extended | str::regex::newline ), "", true ); + + const std::string release = str::regex_substitute( version, str::regex( ".*-", str::regex::match_extended ), "", true ); + + version = str::regex_substitute( version, str::regex( "-[^-]*$", str::regex::match_extended | str::regex::newline ), "", true ); + + + auto makeRcVariant = [ &release ]( std::string myVersion, const std::string &replace ){ + // from purge-kernels script, was copied from kernel-source/rpm/mkspec + myVersion = str::regex_substitute( myVersion, str::regex( "\\.0-rc", str::regex::match_extended ), replace, true ); + myVersion = str::regex_substitute( myVersion, str::regex( "-rc\\d+", str::regex::match_extended ), "", true ); + myVersion = str::regex_substitute( myVersion, str::regex( "-", str::regex::match_extended ), ".", true ); + return Edition( myVersion, release ); + }; + + _runningKernelEditionVariants.clear(); + _runningKernelEditionVariants.insert( makeRcVariant( version, "~rc") ); + _runningKernelEditionVariants.insert( makeRcVariant( version, ".rc") ); + + _runningKernelFlavour = flavour; + + MIL << "Parsed info from uname: " << std::endl; + MIL << "Kernel Flavour: " << _runningKernelFlavour << std::endl; + MIL << "Kernel Edition Variants: \n"; + for ( const auto &var : _runningKernelEditionVariants ) + MIL << " " << var << "\n"; + MIL << std::endl; + } + + bool removePackageAndCheck( const sat::Solvable slv, const std::set &keepList , const std::set &removeList ) const; + static bool versionMatch ( const Edition &a, const Edition &b ); + void parseKeepSpec(); + void fillKeepList(const GroupMap &installedKernels, std::set &keepList , std::set &removeList ) const; + + std::set _keepLatestOffsets = { 0 }; + std::set _keepOldestOffsets; + std::set _keepSpecificEditions; + std::string _uname_r; + /*! + * A kernel uname can expand into multiple variants especially with rc kernels, + * older rc releases replaced the upstream tag -rc with .rc, however newer code + * replaces it with ~rc. We need to check against all variants to match the correct one. + */ + std::set _runningKernelEditionVariants; + Flavour _runningKernelFlavour; + Arch _kernelArch; + std::string _keepSpec = ZConfig::instance().multiversionKernels(); + bool _keepRunning = true; + bool _detectedRunning = false; + }; + + /*! + * tries to remove a the \ref PoolItem \a pi from the pool, solves and checks if no unexpected packages are removed due to the \a validRemovals regex. + * If the constraint fails the changes are reverted and \a false is returned. + */ + bool PurgeKernels::Impl::removePackageAndCheck( const sat::Solvable slv, const std::set &keepList , const std::set &removeList ) const + { + const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled ); + + PoolItem pi ( slv ); + + auto pool = ResPool::instance(); + + // make sure the pool is clean + if ( !pool.resolver().resolvePool() ) { + MIL << "Pool failed to resolve, not doing anything" << std::endl; + return false; + } + + MIL << "Request to remove package: " << pi << std::endl; + + //list of packages that are allowed to be removed automatically. + const str::regex validRemovals("(kernel-syms(-.*)?|kgraft-patch(-.*)?|kernel-(.*)-livepatch(-.*)?|kernel-livepatch(-.*)?|.*-kmp(-.*)?)"); + + if ( pi.status().isLocked() ) { + MIL << "Package " << pi << " is locked by the user, not removing." << std::endl; + return false; + } + + //remember which packages are already marked for removal, we do not need to check them again + std::set currentSetOfRemovals; + for ( const PoolItem & p : pool.byStatus( toBeUninstalledFilter ) ) { + currentSetOfRemovals.insert( p.satSolvable() ); + } + + pi.status().setToBeUninstalled( ResStatus::USER ); + + if ( !pool.resolver().resolvePool() ) { + MIL << "Failed to resolve pool, skipping " << pi << std::endl; + pool.resolver().problems(); + pi.statusReset(); + + return false; + } + + std::set removedInThisRun; + removedInThisRun.insert( slv ); + + for ( const PoolItem & p : pool.byStatus( toBeUninstalledFilter ) ) { + + //check if that package is removeable + if ( p.status().isByUser() //this was set by us, ignore it + || (currentSetOfRemovals.find( p.satSolvable() ) != currentSetOfRemovals.end()) //this was marked by a previous removal, ignore them + ) + continue; + + // remember for later we need remove the debugsource and debuginfo packages as well + removedInThisRun.insert( p.satSolvable() ); + + MIL << "Package " << p << " was marked by the solver for removal." << std::endl; + + // if we do not plan to remove that package anyway, we need to check if its allowed to be removed ( package in removelist can never be in keep list ) + if ( removeList.find( p.satSolvable() ) != removeList.end() ) + continue; + + if ( keepList.find( p.satSolvable() ) != keepList.end() ) { + MIL << "Package " << p << " is in keep spec, skipping" << pi << std::endl; + pi.statusReset(); + return false; + } + + /* + * bsc#1185325 We can not solely rely on name matching to figure out + * which packages are kmod's, in SLES from Leap 15.3 forward we have the + * kernel-flavour-extra packages ( and others similarly named ) that are basically + * a collection of kmod's. So checking the name for .*-kmp(-.*)? is not enough. + * We first check if the package provides kmod(*) or ksym(*) and only fall back to name + * checking if that is not the case. + * Just to be safe I'll leave the regex in the fallback case as well, but it should be completely + * redundant now. + */ + bool mostLikelyKmod = false; + StrMatcher matchMod( "kmod(*)", Match::GLOB ); + StrMatcher matchSym( "ksym(*)", Match::GLOB ); + for ( const auto &prov : p.provides() ) { + if ( matchMod.doMatch( prov.detail().name().c_str()) || matchSym.doMatch( prov.detail().name().c_str() ) ) { + mostLikelyKmod = true; + break; + } + } + + if ( mostLikelyKmod ) { + MIL << "Package " << p << " is most likely a kmod " << std::endl; + } else { + str::smatch what; + if ( !str::regex_match( p.name(), what, validRemovals) ) { + MIL << "Package " << p << " should not be removed, skipping " << pi << std::endl; + pi.statusReset(); + return false; + } + } + } + + MIL << "Successfully marked package: " << pi << " for removal."<= 2 ) { + versionStr.replace( matches.begin(0), (matches.end(0) - matches.begin(0))+1, matches[1] ); + return a == Edition(versionStr); + } + } + return false; + } + + /*! + * Parse the config line keep spec that tells us which kernels should be kept + */ + void PurgeKernels::Impl::parseKeepSpec( ) + { + //keep spec parse regex, make sure to edit the group offsets if changing this regex + const str::regex specRegex( "^(latest|oldest)([+-][0-9]+)?$", str::regex::match_extended ); + + const unsigned tokenGrp = 1; //index of the group matching the token + const unsigned modifierGrp = 2; //index of the group matching the offset modifier + + + MIL << "Parsing keep spec: " << _keepSpec << std::endl; + + std::vector words; + str::split( _keepSpec, std::back_inserter(words), ",", str::TRIM ); + if ( words.empty() ) { + WAR << "Invalid keep spec: " << _keepSpec << " using default latest,running." << std::endl; + return; + } + + _keepRunning = false; + _keepLatestOffsets.clear(); + _keepOldestOffsets.clear(); + + for ( const std::string &word : words ) { + if ( word == "running" ) { + _keepRunning = true; + } else { + str::smatch what; + if ( !str::regex_match( word, what, specRegex ) ) { + // Allow uname_r version numbers by cutting off any postfix that comes after a second dash, including the second dash. + // Github-Issue openSUSE/zypper#418 + std::string_view edition(word); + const auto firstDash = word.find_first_of ('-'); + if ( firstDash != std::string::npos ) { + const auto secondDash = word.find_first_of ('-', firstDash+1 ); + if ( secondDash != std::string::npos ) { + WAR << "Ignoring possible flavor postfix:'"<< word.substr (secondDash) <<"' in keep spec: " << word << std::endl; + edition = std::string_view( word.c_str (), secondDash ); + } + } + _keepSpecificEditions.insert( Edition(IdString(edition)) ); + continue; + } + + auto addKeepOff = []( const auto &off, auto &set, const auto &constraint ){ + const off_t num = off.empty() ? 0 : str::strtonum( off ); + if ( !constraint(num) ) return false; + set.insert( static_cast(std::abs(num)) ); + return true; + }; + + if ( what[tokenGrp] == "oldest" ) { + addKeepOff( what[modifierGrp], _keepOldestOffsets, [ &word ]( off_t num ) { + if ( num < 0 ) { + WAR << "Ignoring invalid modifier in keep spec: " << word << ", oldest supports only positive modifiers." << std::endl; + return false; + } + return true; + }); + } else { + addKeepOff( what[modifierGrp], _keepLatestOffsets, [ &word ]( off_t num ) { + if ( num > 0 ) { + WAR << "Ignoring invalid modifier in keep spec: " << word << ", latest supports only negative modifiers." << std::endl; + return false; + } + return true; + }); + } + } + } + } + + /*! + * Go over the list of available Editions for each flavour/arch combinations, apply the keep spec and mark the + * packages that belong to a matching category as to keep + * + * All packages with Arch_noarch will only be matched against the version but NOT the flavour, reasoning for that is + * simply that source flavours not necessarily match the binary flavours. Without a translation table that would not be + * doable. This is also what the perl script did. + * + */ + void PurgeKernels::Impl::fillKeepList( const GroupMap &installedKernels, std::set &keepList, std::set &removeList ) const + { + + const auto markAsKeep = [ &keepList, &removeList ]( sat::Solvable pck ) { + MIL << "Marking package " << pck << " as to keep." << std::endl; + keepList.insert( pck ) ; + removeList.erase( pck ); + }; + + const auto versionPredicate = []( const auto &editionVariants ){ + return [ &editionVariants ]( const auto &elem ) { + const auto &f = std::bind( versionMatch, _1, elem.first ); + return std::any_of( editionVariants.begin(), editionVariants.end(), f ); + }; + }; + + for ( const auto &groupInfo : installedKernels ) { + + MIL << "Starting with group " << groupInfo.first << std::endl; + + for ( const auto &archMap : groupInfo.second.archToEdMap ) { + + MIL << "Starting with arch " << archMap.first << std::endl; + + size_t currOff = 0; //the current "oldest" offset ( runs from map start to end ) + size_t currROff = archMap.second.size() - 1; // the current "latest" offset ( runs from map end to start ) + + + const EditionToSolvableMap &map = archMap.second; + + if ( _keepRunning + && ( ( archMap.first == _kernelArch && groupInfo.second.groupFlavour == _runningKernelFlavour ) + || groupInfo.second.groupType == GroupInfo::Sources ) ) { + + MIL << "Matching packages against running kernel "<< _runningKernelFlavour << "-" <<_kernelArch << "\nVariants:\n"; + for ( const auto &var : _runningKernelEditionVariants ) + MIL << var << "\n"; + MIL << std::endl; + + const auto &editionPredicate = versionPredicate( _runningKernelEditionVariants ); + auto it = std::find_if( map.begin(), map.end(), editionPredicate ); + if ( it == map.end() ) { + + // If we look at Sources we cannot match the flavour but we still want to keep on checking the rest of the keep spec + if ( groupInfo.second.groupType != GroupInfo::Sources ) { + MIL << "Running kernel " << _runningKernelFlavour << "-" <<_kernelArch << "\n"; + for ( const auto &var : _runningKernelEditionVariants ) + MIL << " Possible Variant:" << var << "\n"; + MIL << "Not installed! \n"; + MIL << "NOT removing any packages for flavor "<<_runningKernelFlavour<<"-"<<_kernelArch<<" ."<first << std::endl; + auto nit = it; + for ( nit++ ; nit != map.end() && editionPredicate( *nit ) ; nit++ ) { + MIL << "Found possible more recent running candidate edition: " << nit->first << std::endl; + it = nit; + } + } + + // mark all packages of the running version as keep + if ( it != map.end() ) { + for( sat::Solvable pck : it->second ) { + markAsKeep(pck); + } + } + } + + for ( const auto &kernelMap : map ) { + //if we find one of the running offsets in the keepspec, we add the kernel id the the list of packages to keep + if ( _keepOldestOffsets.find( currOff ) != _keepOldestOffsets.end() || _keepLatestOffsets.find( currROff ) != _keepLatestOffsets.end() ) { + std::for_each( kernelMap.second.begin(), kernelMap.second.end(), markAsKeep ); + } + currOff++; + currROff--; + + // a kernel package might be explicitly locked by version + // We need to go over all package name provides ( provides is named like the package ) and match + // them against the specified version to know which ones to keep. (bsc#1176740 bsc#1176192) + std::for_each( kernelMap.second.begin(), kernelMap.second.end(), [ & ]( sat::Solvable solv ){ + for ( Capability prov : solv.provides() ) { + if ( prov.detail().name() == solv.name() && _keepSpecificEditions.count( prov.detail().ed() ) ) { + markAsKeep( solv ); + break; + } + } + }); + } + } + } + } + + PurgeKernels::PurgeKernels() + : _pimpl( new Impl() ) + { + + } + + void PurgeKernels::markObsoleteKernels() + { + MIL << std::endl << "--------------------- Starting to mark obsolete kernels ---------------------"<_keepSpec.empty() ) { + WAR << "Keep spec is empty, removing nothing." << std::endl; + return; + } + + _pimpl->parseKeepSpec(); + + if ( _pimpl->_keepRunning && !_pimpl->_detectedRunning ) { + WAR << "Unable to detect running kernel, but keeping the running kernel was requested. Not removing any packages." << std::endl; + return; + } + + auto pool = ResPool::instance(); + pool.resolver().setForceResolve( true ); // set allow uninstall flag + + const filter::ByStatus toBeUninstalledFilter( &ResStatus::isToBeUninstalled ); + + // kernel flavour regex + const str::regex kernelFlavourRegex("^kernel-(.*)$"); + + // the map of all installed kernel packages, grouped by Flavour -> Arch -> Version -> (List of all packages in that category) + // devel and source packages are grouped together + GroupMap installedKrnlPackages; + + + // packages that we plan to remove + std::set packagesToRemove; + + const auto addPackageToMap = [&installedKrnlPackages, &packagesToRemove] ( const GroupInfo::GroupType type, const std::string &ident, const std::string &flavour, const sat::Solvable &installedKrnlPck ) { + + if ( !installedKrnlPackages.count( ident ) ) + installedKrnlPackages.insert( std::make_pair( ident, GroupInfo(type, flavour) ) ); + + auto &groupInfo = installedKrnlPackages[ ident ]; + if ( groupInfo.groupType != type || groupInfo.groupFlavour != flavour ) { + ERR << "Got inconsistent type and flavour for ident this is a BUG: " << ident << std::endl + << "Original Flavour-Type: "< packagesToKeep; + + //collect the list of installed kernel packages + PoolQuery q; + q.addKind( zypp::ResKind::package ); + q.addAttribute( sat::SolvAttr::provides, "multiversion(kernel)" ); + q.setInstalledOnly(); + q.setMatchExact(); + + MIL << "Searching for obsolete multiversion kernel packages." << std::endl; + + for ( sat::Solvable installedKrnlPck : q ) { + + MIL << "Found installed multiversion kernel package " << installedKrnlPck << std::endl; + + if ( installedKrnlPck.provides().matches(Capability("kernel-uname-r")) ) { + MIL << "Identified as a kernel package " << std::endl; + + // we group kernel packages by flavour + str::smatch what; + str::regex_match( installedKrnlPck.name(), what, kernelFlavourRegex ); + if ( what[1].empty() ) { + WAR << "Could not detect flavour for: " << installedKrnlPck << " ...skipping" << std::endl; + continue; + } + + std::string flavour = what[1]; + + // XXX: No dashes in flavor names + const auto dash = flavour.find_first_of('-'); + if ( dash != std::string::npos ) { + flavour = flavour.substr( 0, dash ); + } + + // the ident for kernels is the flavour, to also handle cases like kernel-base and kernel which should be in the same group handled together + addPackageToMap( GroupInfo::Kernels, flavour, flavour, installedKrnlPck ); + + } else { + + // if adapting the groups do not forget to explicitly handle the group when querying the matches + const str::regex explicitlyHandled("kernel-syms(-.*)?|kernel(-.*)?-devel"); + + MIL << "Not a kernel package, inspecting more closely " << std::endl; + + // we directly handle all noarch packages that export multiversion(kernel) + if ( installedKrnlPck.arch() == Arch_noarch ) { + + MIL << "Handling package explicitly due to architecture (noarch)."<< std::endl; + addPackageToMap( GroupInfo::Sources, installedKrnlPck.name(), "", installedKrnlPck ); + + } else if ( str::smatch match; str::regex_match( installedKrnlPck.name(), match, explicitlyHandled ) ) { + + // try to get the flavour from the name + // if we have a kernel-syms getting no flavour means we have the "default" one, otherwise we use the flavour + // getting no flavour for a kernel(-*)?-devel means we have the kernel-devel package otherwise the flavour specific one + // ...yes this is horrible + std::string flav; + + // first group match is a kernel-syms + if ( match.size() > 1 && match[1].size() ) + flav = match[1].substr(1); + // second group match is a kernel-flavour-devel + else if ( match.size() > 2 && match[2].size() ) + flav = match[2].substr(1); + else if ( installedKrnlPck.name() == "kernel-syms" ) + flav = "default"; + + MIL << "Handling package explicitly due to name match."<< std::endl; + addPackageToMap ( GroupInfo::RelatedBinaries, installedKrnlPck.name(), flav, installedKrnlPck ); + } else { + MIL << "Package not explicitly handled" << std::endl; + } + } + + } + + MIL << "Grouped packages: " << std::endl; + std::for_each( installedKrnlPackages.begin(), installedKrnlPackages.end(),[]( const auto &ident ){ + MIL << "\tGroup ident: "<fillKeepList( installedKrnlPackages, packagesToKeep, packagesToRemove ); + + for ( sat::Solvable slv : packagesToRemove ) + _pimpl->removePackageAndCheck( slv, packagesToKeep, packagesToRemove ); + } + + void PurgeKernels::setUnameR( const std::string &val ) + { + _pimpl->setUnameR( val ); + } + + std::string PurgeKernels::unameR() const + { + return _pimpl->_uname_r; + } + + void PurgeKernels::setKernelArch(const Arch &arch) + { + _pimpl->_kernelArch = arch; + } + + Arch PurgeKernels::kernelArch() const + { + return _pimpl->_kernelArch; + } + + void PurgeKernels::setKeepSpec( const std::string &val ) + { + _pimpl->_keepSpec = val; + } + + std::string PurgeKernels::keepSpec() const + { + return _pimpl->_keepSpec; + } + +} diff --git a/zypp/PurgeKernels.h b/zypp/PurgeKernels.h new file mode 100644 index 0000000..1a32fce --- /dev/null +++ b/zypp/PurgeKernels.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/PurgeKernels.h + * +*/ + +#include +#include +#include + +namespace zypp { + + namespace str { + class regex; + } + + /*! + * Implements the logic of the "purge-kernels" command. + * + */ + class ZYPP_API PurgeKernels + { + public: + PurgeKernels(); + + + /*! + * Marks all currently obsolete Kernels according to the keep spec. + * \note This will not commit the changes + */ + void markObsoleteKernels(); + + /*! + * Force a specific uname to be set, only used for testing, + * in production the running kernel is detected. + */ + void setUnameR( const std::string &val ); + std::string unameR() const; + + + /*! + * Force a specific kernel arch to be set, only used for testing, + * in production the running kernel arch is detected. + */ + void setKernelArch( const zypp::Arch &arch ); + Arch kernelArch() const; + + /*! + * Overrides the keep spec, the default value is read from ZConfig. + * The keep spec is a string of tokens seperated by ",". + * It only supports 3 different tokens: + * - "running" matches only the currently running kernel of the system + * - "oldest" matches the kernel version for each flavour/arch combination with the lowest edition + * can be modified with a positive number: oldest+n + * - "latest" matches the kernel version for each flavour/arch combination with the highest edition + * can be modified with a negative number: latest-n + */ + void setKeepSpec( const std::string &val ); + std::string keepSpec () const; + + struct Impl; + private: + RW_pointer _pimpl; + }; + +} + diff --git a/zypp/Range.cc b/zypp/Range.cc new file mode 100644 index 0000000..e556b0c --- /dev/null +++ b/zypp/Range.cc @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Range.cc + * +*/ +#include +//#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace range_detail + { + /** Compute Range overlaps. + * Takes the \a lhs and \a rhs operator and the result + * of comparing \a lhs and \a rhs (-1,0,1). + * + */ + bool overlaps( Rel lhs, Rel rhs, int cmp ) + { + if ( lhs == Rel::NONE || rhs == Rel::NONE ) + return false; + if ( lhs == Rel::ANY || rhs == Rel::ANY ) + return true; + + if ( lhs == Rel::NE ) + { + if ( cmp < 0 ) + { + // lhs < rhs + return( rhs == Rel::GE + || rhs == Rel::EQ ); + } else if ( cmp > 0) + { + // lhs > rhs + return( rhs == Rel::LT + || rhs == Rel::EQ ); + } else + { + //lhs == rhs + return ( rhs == Rel::GT + || rhs == Rel::LT ); + } + } + + if ( rhs == Rel::NE ) + { + if ( cmp < 0 ) + { + // lhs < rhs + return( lhs == Rel::LE + || lhs == Rel::EQ ); + } else if ( cmp > 0) + { + // lhs > rhs + return( lhs == Rel::GT + || lhs == Rel::EQ ); + } else + { + //lhs == rhs + return ( lhs == Rel::GT + || lhs == Rel::LT ); + } + } + + if ( cmp < 0 ) + { + // lhs < rhs: either lhs includes greater values or rhs includes lower. + return( lhs == Rel::GT + || lhs == Rel::GE + || rhs == Rel::LT + || rhs == Rel::LE ); + } + + if ( cmp > 0 ) + { + // lhs > rhs: either lhs includes lower values or rhs includes greater. + return( lhs == Rel::LT + || lhs == Rel::LE + || rhs == Rel::GT + || rhs == Rel::GE ); + } + + // lhs == rhs: either both ranges include Rel::EQ, or both head + // into the same direction. + if ( ( lhs == Rel::LE || lhs == Rel::EQ || lhs == Rel::GE ) + && ( rhs == Rel::LE || rhs == Rel::EQ || rhs == Rel::GE ) ) + return true; + if ( ( lhs == Rel::LT && ( rhs == Rel::LT || rhs == Rel::LE ) ) + || ( lhs == Rel::GT && ( rhs == Rel::GT || rhs == Rel::GE ) ) + || ( rhs == Rel::LT && ( lhs == Rel::LT || lhs == Rel::LE ) ) + || ( rhs == Rel::GT && ( lhs == Rel::GT || lhs == Rel::GE ) ) ) + return true; + // else + return false; + + } + } + + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Range.h b/zypp/Range.h new file mode 100644 index 0000000..af53b01 --- /dev/null +++ b/zypp/Range.h @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Range.h + * +*/ +#ifndef ZYPP_RANGE_H +#define ZYPP_RANGE_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace range_detail + { + bool overlaps( Rel lhs, Rel rhs, int cmp ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Range + // + /** + * + */ + template > + struct Range + { + /** */ + Rel op; + /** */ + Tp value; + + /** Default ctor: \ref Rel::ANY. */ + Range() + : op( Rel::ANY ) + {} + + /** Ctor taking \a Tp (\ref Rel::EQ). */ + Range( const Tp & value_r ) + : op( Rel::EQ ) + , value( value_r ) + {} + + /** Ctor taking \ref Rel and \a Tp. */ + Range( Rel op_r, const Tp & value_r ) + : op( op_r ) + , value( value_r ) + {} + + /** Return whether two Ranges overlap. */ + bool overlaps( const Range & rhs ) const + { return range_detail::overlaps( op, rhs.op, TCompare()( value, rhs.value ) ); } + }; + /////////////////////////////////////////////////////////////////// + + template + inline bool overlaps( const Range & lhs, + const Range & rhs ) + { return lhs.overlaps( rhs ); } + + /////////////////////////////////////////////////////////////////// + + template + inline bool operator==( const Range & lhs, + const Range & rhs ) + { + return( lhs.op == rhs.op + && ( lhs.op == Rel::ANY + || lhs.op == Rel::NONE + || relCompare( Rel::EQ, lhs.value, rhs.value, TCompare() ) + ) + ); + } + + template + inline bool operator!=( const Range & lhs, + const Range & rhs ) + { return ! ( lhs == rhs ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RANGE_H diff --git a/zypp/Rel.cc b/zypp/Rel.cc new file mode 100644 index 0000000..e74b390 --- /dev/null +++ b/zypp/Rel.cc @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Rel.cc + * +*/ +#include +#include + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace + { + std::map _table; + + std::map::const_iterator findStr( const std::string & strval_r ) + { + if ( _table.empty() ) + { + // initialize it + _table["EQ"] = _table["eq"] = _table["=="] = _table["="] = Rel::EQ_e; + _table["NE"] = _table["ne"] = _table["!="] = Rel::NE_e; + _table["LT"] = _table["lt"] = _table["<"] = Rel::LT_e; + _table["LE"] = _table["le"] = _table["lte"] = _table["<="] = Rel::LE_e; + _table["GT"] = _table["gt"] = _table[">"] = Rel::GT_e; + _table["GE"] = _table["ge"] = _table["gte"] = _table[">="] = Rel::GE_e; + _table["ANY"] = _table["any"] = _table["(any)"] = _table[""] = Rel::ANY_e; + _table["NONE"] = _table["none"] = Rel::NONE_e; + } + + return _table.find( strval_r ); + } + + Rel::for_use_in_switch parse( const std::string & strval_r ) + { + std::map::const_iterator it = findStr( strval_r ); + if ( it == _table.end() ) + { + ZYPP_THROW( Exception("Rel parse: illegal string value '"+strval_r+"'") ); + } + return it->second; + } + + Rel::for_use_in_switch parse( const std::string & strval_r, const Rel & default_r ) + { + std::map::const_iterator it = findStr( strval_r ); + if ( it == _table.end() ) + { + return default_r.inSwitch(); + } + return it->second; + } + } + /////////////////////////////////////////////////////////////////// + + const Rel Rel::EQ( Rel::EQ_e ); + const Rel Rel::NE( Rel::NE_e ); + const Rel Rel::LT( Rel::LT_e ); + const Rel Rel::LE( Rel::LE_e ); + const Rel Rel::GT( Rel::GT_e ); + const Rel Rel::GE( Rel::GE_e ); + const Rel Rel::ANY( Rel::ANY_e ); + const Rel Rel::NONE( Rel::NONE_e ); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Rel::Rel + // METHOD TYPE : Constructor + // + Rel::Rel( const std::string & strval_r ) + : _op( parse( strval_r ) ) + {} + + Rel::Rel( const std::string & strval_r, const Rel & default_r ) + : _op( parse( strval_r, default_r ) ) + {} + + bool Rel::parseFrom( const std::string & strval_r ) + { + std::map::const_iterator it = findStr( strval_r ); + if ( it == _table.end() ) + { + return false; + } + _op = it->second; + return true; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Rel::asString + // METHOD TYPE : const std::string & + // + const std::string & Rel::asString() const + { + static std::map _table; + if ( _table.empty() ) + { + // initialize it + _table[EQ_e] = "="; + _table[NE_e] = "!="; + _table[LT_e] = "<"; + _table[LE_e] = "<="; + _table[GT_e] = ">"; + _table[GE_e] = ">="; + _table[ANY_e] = "ANY"; + _table[NONE_e] = "NONE"; + } + return _table[_op]; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/Rel.h b/zypp/Rel.h new file mode 100644 index 0000000..93d5347 --- /dev/null +++ b/zypp/Rel.h @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/Rel.h + * +*/ +#ifndef ZYPP_REL_H +#define ZYPP_REL_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Rel + // + /** Relational operators. + * Yes, it could as well be simply an \c enum.
+ * Yes, you can use the relational operators as if it was an \c enum.
+ * Except for use in a \c switch statement; see \ref inSwitch for this. + * + * But we want to construct them from a string representation, as well as + * providing one. And this way they are wrapped into a namespace, which is + * a good idea anyway. + * + * \ref ANY and \ref NONE are somewhat special. \ref ANY is the + * operator created by the default ctor, and it should always resolve + * to \c true. This may be handy in queries when you're looking for a + * Resolvable in \c ANY Edition if no operator was specified. + * While \ref NONE should always resolve to \c false. + * + * \ingroup g_EnumerationClass + */ + struct ZYPP_API Rel + { + /** \name Relational operators + * These are the \em real relational operator contants to + * use. Don't mind that it's not an enum. See also: \ref zypp::Rel::inSwitch + */ + //@{ + static const Rel EQ; + static const Rel NE; + static const Rel LT; + static const Rel LE; + static const Rel GT; + static const Rel GE; + static const Rel ANY; + static const Rel NONE; + //@} + + /** Enumarators provided \b only for use \ref inSwitch statement. + * \see inSwitch + * \note Enumarator values also correspond to the values libsolv + * uses to encode these relations. + */ + enum for_use_in_switch { + NONE_e = 0U, + GT_e = 1U, + EQ_e = 2U, + LT_e = 4U, + GE_e = GT_e|EQ_e, + LE_e = LT_e|EQ_e, + NE_e = GT_e|LT_e, + ANY_e = GT_e|EQ_e|LT_e, + }; + + /** DefaultCtor ANY. */ + Rel() + : _op( ANY_e ) + {} + + /** Ctor from string. + * Legal values for \a strval_r are: "="/"==", "!=", "<", "<=", ">", ">=",
+ * as well as "EQ", "NE", "LT", "LE", "GT", "GE", "ANY", "NONE"
+ * and "" (empty string resolves to ANY). + * + * Lower case names are accepted as well. + * + * \throw PARSE if \a strval_r is not legal. + * \todo refine exceptions and check throw. + */ + explicit + Rel( const std::string & strval_r ); + + /** Ctor from string (non-throwing). + * Illegal string values resolve to \c default_r + */ + Rel( const std::string & strval_r, const Rel & default_r ); + + /** Assign from string IFF it contains a legal value. + * \return Whether \a strval_r contained a legal value. + */ + bool parseFrom( const std::string & strval_r ); + + /** Ctor from bits. */ + explicit + Rel( unsigned bits_r ) + : _op( for_use_in_switch(bits_r & ANY_e) ) + {} + + /** Test whether \a bits_r is a valid \ref Rel (no extra bits set). */ + static bool isRel( unsigned bits_r ) + { return (bits_r & ANY_e) == bits_r; } + + /** String representation of relational operator. + * \return "=", "!=", "<", "<=", ">", ">=", "ANY" or "NONE" + */ + const std::string & asString() const; + /** \overload */ + const char * c_str() const + { return asString().c_str(); } + + /** Enumarator provided for use in \c switch statement. + * The sole reason for providing enum \ref for_use_in_switch is, + * that we may want to use the relational operators in a \c switch + * statement. Tht's the only case where you should have to use the + * enumarator. + * \code + * Rel op; + * switch ( op.inSwitch() ) + * { + * case Rel::EQ_e: + * ... + * break; + * case Rel::NE_e: + * ... + * + * // No default! Let compiler warn if case is missing + * } + * \endcode + */ + for_use_in_switch inSwitch() const + { return _op; } + + /** Enumarator values suitable for libsolv. */ + unsigned bits() const + { return _op; } + + private: + /** Ctor to initialize the relational operator contants. */ + Rel( for_use_in_switch op_r ) + : _op( op_r ) + {} + /** The operator. */ + for_use_in_switch _op; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Rel Stream output. */ + inline std::ostream & operator<<( std::ostream & str, const Rel & obj ) + { return str << obj.asString(); } + + /////////////////////////////////////////////////////////////////// + + /** \relates Rel */ + inline bool operator==( const Rel & lhs, const Rel & rhs ) + { return lhs.inSwitch() == rhs.inSwitch(); } + + /** \relates Rel */ + inline bool operator!=( const Rel & lhs, const Rel & rhs ) + { return ! ( lhs == rhs ); } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REL_H diff --git a/zypp/RelCompare.h b/zypp/RelCompare.h new file mode 100644 index 0000000..dd0215a --- /dev/null +++ b/zypp/RelCompare.h @@ -0,0 +1,232 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RelCompare.h + * +*/ +#ifndef ZYPP_RELCOMPARE_H +#define ZYPP_RELCOMPARE_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** \defgroup RelCompare Comparison using relational operator zypp::Rel. + * + * . Take a class like zypp::Edition. Editions are comaprable. + * You can compare them lexicographical, or according to their + * version and release values, or match them (i.e. taking empty + * version or release values as wildcard). + * + * No matter which way is appropriate within a certain context. + * You need functions to compare, and may want to use classes like + * zypp::Range, based on the desired comparison. + * + * All the class has to do, is providing a general comparison + * method (preferably static) + * \code + * // Compare two elements returning -1, 0, 1 + * // if the elemants compare <,==,>. + * static int compare( const Tp & lhs, const Tp & rhs ); + * \endcode + * + * Compare\ provides a functor wrapping \c compare. + * In case the general comparison method is named differently, the + * class, or you, have to provide an approriate functor. + * + * compareByRel then compares two elements using a certain + * operator and general comparison method. + * \code + * compareByRel( Rel::EQ, lhs, rhs, Edition::compare ); + * compareByRel( Rel::EQ, lhs, rhs, Edition::match ); + * compareByRel( Rel::EQ, lhs, rhs ); // defaults to Compare\ + * // thus Edition::compare + * \endcode + * + * Furthermore a bunch of functors using a certain operator is + * defined. All templated by type and general comparison + * method (defaults to Compare\). + * \code + * // Editions sets use lexicographical order per default: + * std::set + * + * // An Edition set using Edition::compare as order: + * std::set >; + * + * // Edition::match is not transitive, thus not an appropriate + * // order relation for std::set or std::map. + * \endcode + * + * Classes like zypp:Range are templated by by type and general + * comparison method as well. Thus you may use Edition ranges based + * on Edition::Compare, as well as ranges based on Edition::Match + * (Edition provides these two functors). + * + * Again: Everything a class has to provide is the general + * comparison method. Comparison functors and ranges are then + * immediately available. + */ + //@{ + + /** General compare functor returning -1, 0, 1. + * Expects Tp::compare to be a static comparison method + * returning -1, 0, 1 if the elements compare + * \<,==,\>. + */ + template + struct Compare + { + int operator()( const Tp & lhs, const Tp & rhs ) const + { return Tp::compare( lhs, rhs ); } + }; + + /////////////////////////////////////////////////////////////////// + + /** Comparison of two elements using relational operator \a op. + * Expects \a TCompare to be a binary operator returning + * -1, 0, 1 if the elements compare \<,==,\>. + * \code + * // Signature of compare function or functor: + * int compare( const Tp & lhs, const Tp & rhs ); + * \endcode + * \li If \a op is Rel::ANY, the expression is always \c true. + * \li If \a op is Rel::NONE, the expression is always \c false. + * \li Otherwise the expression is evaluated using \a compare. + * + * \ingroup RelCompare + */ + template + inline bool compareByRel( Rel op, const Tp & lhs, const Tp & rhs, TCompare compare ) + { + switch ( op.inSwitch() ) + { + case Rel::EQ_e: + return compare( lhs, rhs ) == 0; + break; + case Rel::NE_e: + return compare( lhs, rhs ) != 0; + break; + case Rel::LT_e: + return compare( lhs, rhs ) < 0; + break; + case Rel::LE_e: + return compare( lhs, rhs ) <= 0; + break; + case Rel::GT_e: + return compare( lhs, rhs ) > 0; + break; + case Rel::GE_e: + return compare( lhs, rhs ) >= 0; + break; + case Rel::ANY_e: + return true; + break; + case Rel::NONE_e: + return false; + break; + } + return false; + } + + /** \ref compareByRel convenience using Compare as general compare + * functor. + */ + template + inline bool compareByRel( Rel op, const Tp & lhs, const Tp & rhs ) + { return compareByRel( op, lhs, rhs, Compare() ); } + + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + + /** Functor to compare two elements by \ref Rel based on + * a general \a TCompare functor. + * + * Expects \a TCompare to be suitable for use in \ref compareByRel. + * Defaults to Compare\. + */ + template > + struct CompareBy + { + CompareBy( Rel op_r ) + : _op( op_r ) + {} + + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( _op, lhs, rhs, TCompare() ); } + + Rel _op; + }; + + template > + struct CompareByEQ + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::EQ, lhs, rhs, TCompare() ); } + }; + + template > + struct CompareByNE + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::NE, lhs, rhs, TCompare() ); } + }; + + template > + struct CompareByLT + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::LT, lhs, rhs, TCompare() ); } + }; + + template > + struct CompareByLE + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::LE, lhs, rhs, TCompare() ); } + }; + + template > + struct CompareByGT + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::GT, lhs, rhs, TCompare() ); } + }; + + template > + struct CompareByGE + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::GE, lhs, rhs, TCompare() ); } + }; + + template > + struct CompareByANY + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::ANY, lhs, rhs, TCompare() ); } + }; + + template > + struct CompareByNONE + { + bool operator()( const Tp & lhs, const Tp & rhs ) const + { return compareByRel( Rel::NONE, lhs, rhs, TCompare() ); } + }; + + /////////////////////////////////////////////////////////////////// + + //@} + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_RELCOMPARE_H diff --git a/zypp/RepoInfo.cc b/zypp/RepoInfo.cc new file mode 100644 index 0000000..46f04e3 --- /dev/null +++ b/zypp/RepoInfo.cc @@ -0,0 +1,988 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoInfo.cc + * +*/ +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include +#include +#include +#include +#include + +#include + +using std::endl; +using zypp::xml::escape; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace + { + repo::RepoType probeCache( const Pathname & path_r ) + { + repo::RepoType ret = repo::RepoType::NONE; + if ( PathInfo(path_r).isDir() ) + { + if ( PathInfo(path_r/"/repodata/repomd.xml").isFile() ) + { ret = repo::RepoType::RPMMD; } + else if ( PathInfo(path_r/"/content").isFile() ) + { ret = repo::RepoType::YAST2; } + else if ( PathInfo(path_r/"/cookie").isFile() ) + { ret = repo::RepoType::RPMPLAINDIR; } + } + DBG << "Probed cached type " << ret << " at " << path_r << endl; + return ret; + } + } // namespace + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfo::Impl + // + /** RepoInfo implementation. */ + struct RepoInfo::Impl + { + Impl() + : _rawGpgCheck( indeterminate ) + , _rawRepoGpgCheck( indeterminate ) + , _rawPkgGpgCheck( indeterminate ) + , _validRepoSignature( indeterminate ) + , _type(repo::RepoType::NONE_e) + , keeppackages(indeterminate) + , _mirrorListForceMetalink(false) + , emptybaseurls(false) + {} + + Impl(const Impl &) = default; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() {} + + public: + static const unsigned defaultPriority = 99; + static const unsigned noPriority = unsigned(-1); + + void setType( const repo::RepoType & t ) + { _type = t; } + + void setProbedType( const repo::RepoType & t ) const + { + if ( _type == repo::RepoType::NONE && t != repo::RepoType::NONE ) + { const_cast(this)->_type = t; } + } + + repo::RepoType type() const + { + if ( _type == repo::RepoType::NONE ) + setProbedType( probeCache( metadataPath() / path ) ); + return _type; + } + + public: + /** Path to a license tarball in case it exists in the repo. */ + Pathname licenseTgz( const std::string & name_r ) const + { + Pathname ret; + if ( !metadataPath().empty() ) + { + std::string licenseStem( "license" ); + if ( !name_r.empty() ) + { + licenseStem += "-"; + licenseStem += name_r; + } + + filesystem::Glob g; + // TODO: REPOMD: this assumes we know the name of the tarball. In fact + // we'd need to get the file from repomd.xml () + g.add( metadataPath() / path / ("repodata/*"+licenseStem+".tar.gz") ); + if ( g.empty() ) + g.add( metadataPath() / path / (licenseStem+".tar.gz") ); + + if ( !g.empty() ) + ret = *g.begin(); + } + return ret; + } + + const RepoVariablesReplacedUrlList & baseUrls() const + { + const Url & mlurl( _mirrorListUrl.transformed() ); // Variables replaced! + if ( _baseUrls.empty() && ! mlurl.asString().empty() ) + { + emptybaseurls = true; + DBG << "MetadataPath: " << metadataPath() << endl; + repo::RepoMirrorList rmurls( mlurl, metadataPath(), _mirrorListForceMetalink ); + _baseUrls.raw().insert( _baseUrls.raw().end(), rmurls.getUrls().begin(), rmurls.getUrls().end() ); + } + return _baseUrls; + } + + RepoVariablesReplacedUrlList & baseUrls() + { return _baseUrls; } + + bool baseurl2dump() const + { return !emptybaseurls && !_baseUrls.empty(); } + + + const RepoVariablesReplacedUrlList & gpgKeyUrls() const + { return _gpgKeyUrls; } + + RepoVariablesReplacedUrlList & gpgKeyUrls() + { return _gpgKeyUrls; } + + + const std::set & contentKeywords() const + { hasContent()/*init if not yet done*/; return _keywords.second; } + + void addContent( const std::string & keyword_r ) + { _keywords.second.insert( keyword_r ); if ( ! hasContent() ) _keywords.first = true; } + + bool hasContent() const + { + if ( !_keywords.first && ! metadataPath().empty() ) + { + // HACK directly check master index file until RepoManager offers + // some content probing and zypper uses it. + ///////////////////////////////////////////////////////////////// + MIL << "Empty keywords...." << metadataPath() << endl; + Pathname master; + if ( PathInfo( (master=metadataPath()/"/repodata/repomd.xml") ).isFile() ) + { + //MIL << "GO repomd.." << endl; + xml::Reader reader( master ); + while ( reader.seekToNode( 2, "content" ) ) + { + _keywords.second.insert( reader.nodeText().asString() ); + reader.seekToEndNode( 2, "content" ); + } + _keywords.first = true; // valid content in _keywords even if empty + } + else if ( PathInfo( (master=metadataPath()/"/content") ).isFile() ) + { + //MIL << "GO content.." << endl; + iostr::forEachLine( InputStream( master ), + [this]( int num_r, const std::string& line_r )->bool + { + if ( str::startsWith( line_r, "REPOKEYWORDS" ) ) + { + std::vector words; + if ( str::split( line_r, std::back_inserter(words) ) > 1 + && words[0].length() == 12 /*"REPOKEYWORDS"*/ ) + { + this->_keywords.second.insert( ++words.begin(), words.end() ); + } + return true; // mult. occurrances are ok. + } + return( ! str::startsWith( line_r, "META " ) ); // no need to parse into META section. + } ); + _keywords.first = true; // valid content in _keywords even if empty + } + ///////////////////////////////////////////////////////////////// + } + return _keywords.first; + } + + bool hasContent( const std::string & keyword_r ) const + { return( hasContent() && _keywords.second.find( keyword_r ) != _keywords.second.end() ); } + + /** Signature check result needs to be stored/retrieved from _metadataPath. + * Don't call them from outside validRepoSignature/setValidRepoSignature + */ + //@{ + TriBool internalValidRepoSignature() const + { + if ( ! indeterminate(_validRepoSignature) ) + return _validRepoSignature; + // check metadata: + if ( ! metadataPath().empty() ) + { + // A missing ".repo_gpgcheck" might be plaindir(no Downloader) or not yet refreshed signed repo! + TriBool linkval = triBoolFromPath( metadataPath() / ".repo_gpgcheck" ); + return linkval; + } + return indeterminate; + } + + void internalSetValidRepoSignature( TriBool value_r ) + { + if ( PathInfo(metadataPath()).isDir() ) + { + Pathname gpgcheckFile( metadataPath() / ".repo_gpgcheck" ); + if ( PathInfo(gpgcheckFile).isExist() ) + { + TriBool linkval( indeterminate ); + if ( triBoolFromPath( gpgcheckFile, linkval ) && linkval == value_r ) + return; // existing symlink fits value_r + else + filesystem::unlink( gpgcheckFile ); // will write a new one + } + filesystem::symlink( asString(value_r), gpgcheckFile ); + } + _validRepoSignature = value_r; + } + + /** We definitely have a symlink pointing to "indeterminate" (for repoGpgCheckIsMandatory)? + * I.e. user accepted the unsigned repo in Downloader. A test whether `internalValidRepoSignature` + * is indeterminate would include not yet checked repos, which is unwanted here. + */ + bool internalUnsignedConfirmed() const + { + TriBool linkval( true ); // want to see it being switched to indeterminate + return triBoolFromPath( metadataPath() / ".repo_gpgcheck", linkval ) && indeterminate(linkval); + } + + bool triBoolFromPath( const Pathname & path_r, TriBool & ret_r ) const + { + static const Pathname truePath( "true" ); + static const Pathname falsePath( "false" ); + static const Pathname indeterminatePath( "indeterminate" ); + + // Quiet readlink; + static const ssize_t bufsiz = 63; + static char buf[bufsiz+1]; + ssize_t ret = ::readlink( path_r.c_str(), buf, bufsiz ); + buf[ret == -1 ? 0 : ret] = '\0'; + + Pathname linkval( buf ); + + bool known = true; + if ( linkval == truePath ) + ret_r = true; + else if ( linkval == falsePath ) + ret_r = false; + else if ( linkval == indeterminatePath ) + ret_r = indeterminate; + else + known = false; + return known; + } + + TriBool triBoolFromPath( const Pathname & path_r ) const + { TriBool ret(indeterminate); triBoolFromPath( path_r, ret ); return ret; } + + //@} + + private: + TriBool _rawGpgCheck; ///< default gpgcheck behavior: Y/N/ZConf + TriBool _rawRepoGpgCheck; ///< need to check repo sign.: Y/N/(ZConf(Y/N/gpgCheck)) + TriBool _rawPkgGpgCheck; ///< need to check pkg sign.: Y/N/(ZConf(Y/N/gpgCheck)) + + public: + TriBool rawGpgCheck() const { return _rawGpgCheck; } + TriBool rawRepoGpgCheck() const { return _rawRepoGpgCheck; } + TriBool rawPkgGpgCheck() const { return _rawPkgGpgCheck; } + + void rawGpgCheck( TriBool val_r ) { _rawGpgCheck = val_r; } + void rawRepoGpgCheck( TriBool val_r ) { _rawRepoGpgCheck = val_r; } + void rawPkgGpgCheck( TriBool val_r ) { _rawPkgGpgCheck = val_r; } + + bool cfgGpgCheck() const + { return indeterminate(_rawGpgCheck) ? ZConfig::instance().gpgCheck() : (bool)_rawGpgCheck; } + TriBool cfgRepoGpgCheck() const + { return indeterminate(_rawGpgCheck) && indeterminate(_rawRepoGpgCheck) ? ZConfig::instance().repoGpgCheck() : _rawRepoGpgCheck; } + TriBool cfgPkgGpgCheck() const + { return indeterminate(_rawGpgCheck) && indeterminate(_rawPkgGpgCheck) ? ZConfig::instance().pkgGpgCheck() : _rawPkgGpgCheck; } + + private: + TriBool _validRepoSignature; ///< have signed and valid repo metadata + repo::RepoType _type; + public: + TriBool keeppackages; + RepoVariablesReplacedUrl _mirrorListUrl; + bool _mirrorListForceMetalink; + Pathname path; + std::string service; + std::string targetDistro; + + void metadataPath( Pathname new_r ) + { _metadataPath = std::move( new_r ); } + + void packagesPath( Pathname new_r ) + { _packagesPath = std::move( new_r ); } + + bool usesAutoMetadataPaths() const + { return str::hasSuffix( _metadataPath.asString(), "/%AUTO%" ); } + + Pathname metadataPath() const + { + if ( usesAutoMetadataPaths() ) + return _metadataPath.dirname() / "%RAW%"; + return _metadataPath; + } + + Pathname packagesPath() const + { + if ( _packagesPath.empty() && usesAutoMetadataPaths() ) + return _metadataPath.dirname() / "%PKG%"; + return _packagesPath; + } + + DefaultIntegral priority; + mutable bool emptybaseurls; + + private: + Pathname _metadataPath; + Pathname _packagesPath; + + mutable RepoVariablesReplacedUrlList _baseUrls; + mutable std::pair > _keywords; + + RepoVariablesReplacedUrlList _gpgKeyUrls; + + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoInfo::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const RepoInfo::Impl & obj ) + { + return str << "RepoInfo::Impl"; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfo + // + /////////////////////////////////////////////////////////////////// + + const RepoInfo RepoInfo::noRepo; + + RepoInfo::RepoInfo() + : _pimpl( new Impl() ) + {} + + RepoInfo::~RepoInfo() + {} + + unsigned RepoInfo::priority() const + { return _pimpl->priority; } + + unsigned RepoInfo::defaultPriority() + { return Impl::defaultPriority; } + + unsigned RepoInfo::noPriority() + { return Impl::noPriority; } + + void RepoInfo::setPriority( unsigned newval_r ) + { _pimpl->priority = newval_r ? newval_r : Impl::defaultPriority; } + + + bool RepoInfo::gpgCheck() const + { return _pimpl->cfgGpgCheck(); } + + void RepoInfo::setGpgCheck( TriBool value_r ) + { _pimpl->rawGpgCheck( value_r ); } + + void RepoInfo::setGpgCheck( bool value_r ) // deprecated legacy and for squid + { setGpgCheck( TriBool(value_r) ); } + + + bool RepoInfo::repoGpgCheck() const + { return gpgCheck() || bool(_pimpl->cfgRepoGpgCheck()); } + + bool RepoInfo::repoGpgCheckIsMandatory() const + { + bool ret = ( gpgCheck() && indeterminate(_pimpl->cfgRepoGpgCheck()) ) || bool(_pimpl->cfgRepoGpgCheck()); + if ( ret && _pimpl->internalUnsignedConfirmed() ) // relax if unsigned repo was confirmed in the past + ret = false; + return ret; + } + + void RepoInfo::setRepoGpgCheck( TriBool value_r ) + { _pimpl->rawRepoGpgCheck( value_r ); } + + + bool RepoInfo::pkgGpgCheck() const + { return bool(_pimpl->cfgPkgGpgCheck()) || ( gpgCheck() && !bool(validRepoSignature())/*enforced*/ ) ; } + + bool RepoInfo::pkgGpgCheckIsMandatory() const + { return bool(_pimpl->cfgPkgGpgCheck()) || ( gpgCheck() && indeterminate(_pimpl->cfgPkgGpgCheck()) && !bool(validRepoSignature())/*enforced*/ ); } + + void RepoInfo::setPkgGpgCheck( TriBool value_r ) + { _pimpl->rawPkgGpgCheck( value_r ); } + + + void RepoInfo::getRawGpgChecks( TriBool & g_r, TriBool & r_r, TriBool & p_r ) const + { + g_r = _pimpl->rawGpgCheck(); + r_r = _pimpl->rawRepoGpgCheck(); + p_r = _pimpl->rawPkgGpgCheck(); + } + + + TriBool RepoInfo::validRepoSignature() const + { + TriBool ret( _pimpl->internalValidRepoSignature() ); + if ( ret && !repoGpgCheck() ) ret = false; // invalidate any old signature if repoGpgCheck is off + return ret; + } + + void RepoInfo::setValidRepoSignature( TriBool value_r ) + { _pimpl->internalSetValidRepoSignature( value_r ); } + + /////////////////////////////////////////////////////////////////// + namespace + { + inline bool changeGpgCheckTo( TriBool & lhs, TriBool rhs ) + { if ( ! sameTriboolState( lhs, rhs ) ) { lhs = rhs; return true; } return false; } + + inline bool changeGpgCheckTo( TriBool ogpg[3], TriBool g, TriBool r, TriBool p ) + { + bool changed = false; + if ( changeGpgCheckTo( ogpg[0], g ) ) changed = true; + if ( changeGpgCheckTo( ogpg[1], r ) ) changed = true; + if ( changeGpgCheckTo( ogpg[2], p ) ) changed = true; + return changed; + } + } // namespace + /////////////////////////////////////////////////////////////////// + bool RepoInfo::setGpgCheck( GpgCheck mode_r ) + { + TriBool ogpg[3]; // Gpg RepoGpg PkgGpg + getRawGpgChecks( ogpg[0], ogpg[1], ogpg[2] ); + + bool changed = false; + switch ( mode_r ) + { + case GpgCheck::On: + changed = changeGpgCheckTo( ogpg, true, indeterminate, indeterminate ); + break; + case GpgCheck::Strict: + changed = changeGpgCheckTo( ogpg, true, true, true ); + break; + case GpgCheck::AllowUnsigned: + changed = changeGpgCheckTo( ogpg, true, false, false ); + break; + case GpgCheck::AllowUnsignedRepo: + changed = changeGpgCheckTo( ogpg, true, false, indeterminate ); + break; + case GpgCheck::AllowUnsignedPackage: + changed = changeGpgCheckTo( ogpg, true, indeterminate, false ); + break; + case GpgCheck::Default: + changed = changeGpgCheckTo( ogpg, indeterminate, indeterminate, indeterminate ); + break; + case GpgCheck::Off: + changed = changeGpgCheckTo( ogpg, false, indeterminate, indeterminate ); + break; + case GpgCheck::indeterminate: // no change + break; + } + + if ( changed ) + { + setGpgCheck ( ogpg[0] ); + setRepoGpgCheck( ogpg[1] ); + setPkgGpgCheck ( ogpg[2] ); + } + return changed; + } + + void RepoInfo::setMirrorListUrl( const Url & url_r ) // Raw + { _pimpl->_mirrorListUrl.raw() = url_r; _pimpl->_mirrorListForceMetalink = false; } + + void RepoInfo::setMirrorListUrls( url_set urls ) // Raw + { setMirrorListUrl( urls.empty() ? Url() : urls.front() ); } + + void RepoInfo::setMetalinkUrl( const Url & url_r ) // Raw + { _pimpl->_mirrorListUrl.raw() = url_r; _pimpl->_mirrorListForceMetalink = true; } + + void RepoInfo::setMetalinkUrls( url_set urls ) // Raw + { setMetalinkUrl( urls.empty() ? Url() : urls.front() ); } + + void RepoInfo::setGpgKeyUrls( url_set urls ) + { _pimpl->gpgKeyUrls().raw().swap( urls ); } + + void RepoInfo::setGpgKeyUrl( const Url & url_r ) + { + _pimpl->gpgKeyUrls().raw().clear(); + _pimpl->gpgKeyUrls().raw().push_back( url_r ); + } + + + Pathname RepoInfo::provideKey(const std::string &keyID_r, const Pathname &targetDirectory_r) const { + return zyppng::RepoInfoWorkflow::provideKey( zyppng::SyncContext::defaultContext(), *this, keyID_r, targetDirectory_r ); + } + + void RepoInfo::addBaseUrl( Url url_r ) + { + for ( const auto & url : _pimpl->baseUrls().raw() ) // Raw unique! + if ( url == url_r ) + return; + _pimpl->baseUrls().raw().push_back( std::move(url_r) ); + } + + void RepoInfo::setBaseUrl( Url url_r ) + { + _pimpl->baseUrls().raw().clear(); + _pimpl->baseUrls().raw().push_back( std::move(url_r) ); + } + + void RepoInfo::setBaseUrls( url_set urls ) + { _pimpl->baseUrls().raw().swap( urls ); } + + void RepoInfo::setPath( const Pathname &path ) + { _pimpl->path = path; } + + void RepoInfo::setType( const repo::RepoType &t ) + { _pimpl->setType( t ); } + + void RepoInfo::setProbedType( const repo::RepoType &t ) const + { _pimpl->setProbedType( t ); } + + + void RepoInfo::setMetadataPath( const Pathname &path ) + { _pimpl->metadataPath( path ); } + + void RepoInfo::setPackagesPath( const Pathname &path ) + { _pimpl->packagesPath( path ); } + + void RepoInfo::setKeepPackages( bool keep ) + { _pimpl->keeppackages = keep; } + + void RepoInfo::setService( const std::string& name ) + { _pimpl->service = name; } + + void RepoInfo::setTargetDistribution( const std::string & targetDistribution ) + { _pimpl->targetDistro = targetDistribution; } + + bool RepoInfo::keepPackages() const + { return indeterminate(_pimpl->keeppackages) ? false : (bool)_pimpl->keeppackages; } + + Pathname RepoInfo::metadataPath() const + { return _pimpl->metadataPath(); } + + Pathname RepoInfo::packagesPath() const + { return _pimpl->packagesPath(); } + + bool RepoInfo::usesAutoMetadataPaths() const + { return _pimpl->usesAutoMetadataPaths(); } + + repo::RepoType RepoInfo::type() const + { return _pimpl->type(); } + + Url RepoInfo::mirrorListUrl() const // Variables replaced! + { return _pimpl->_mirrorListUrl.transformed(); } + + Url RepoInfo::rawMirrorListUrl() const // Raw + { return _pimpl->_mirrorListUrl.raw(); } + + bool RepoInfo::gpgKeyUrlsEmpty() const + { return _pimpl->gpgKeyUrls().empty(); } + + RepoInfo::urls_size_type RepoInfo::gpgKeyUrlsSize() const + { return _pimpl->gpgKeyUrls().size(); } + + RepoInfo::url_set RepoInfo::gpgKeyUrls() const // Variables replaced! + { return _pimpl->gpgKeyUrls().transformed(); } + + RepoInfo::url_set RepoInfo::rawGpgKeyUrls() const // Raw + { return _pimpl->gpgKeyUrls().raw(); } + + Url RepoInfo::gpgKeyUrl() const // Variables replaced! + { return( _pimpl->gpgKeyUrls().empty() ? Url() : *_pimpl->gpgKeyUrls().transformedBegin() ); } + + Url RepoInfo::rawGpgKeyUrl() const // Raw + { return( _pimpl->gpgKeyUrls().empty() ? Url() : *_pimpl->gpgKeyUrls().rawBegin() ) ; } + + RepoInfo::url_set RepoInfo::baseUrls() const // Variables replaced! + { return _pimpl->baseUrls().transformed(); } + + RepoInfo::url_set RepoInfo::rawBaseUrls() const // Raw + { return _pimpl->baseUrls().raw(); } + + Pathname RepoInfo::path() const + { return _pimpl->path; } + + std::string RepoInfo::service() const + { return _pimpl->service; } + + std::string RepoInfo::targetDistribution() const + { return _pimpl->targetDistro; } + + Url RepoInfo::rawUrl() const + { return( _pimpl->baseUrls().empty() ? Url() : *_pimpl->baseUrls().rawBegin() ); } + + RepoInfo::urls_const_iterator RepoInfo::baseUrlsBegin() const + { return _pimpl->baseUrls().transformedBegin(); } + + RepoInfo::urls_const_iterator RepoInfo::baseUrlsEnd() const + { return _pimpl->baseUrls().transformedEnd(); } + + RepoInfo::urls_size_type RepoInfo::baseUrlsSize() const + { return _pimpl->baseUrls().size(); } + + bool RepoInfo::baseUrlsEmpty() const + { return _pimpl->baseUrls().empty(); } + + bool RepoInfo::baseUrlSet() const + { return _pimpl->baseurl2dump(); } + + const std::set & RepoInfo::contentKeywords() const + { return _pimpl->contentKeywords(); } + + void RepoInfo::addContent( const std::string & keyword_r ) + { _pimpl->addContent( keyword_r ); } + + bool RepoInfo::hasContent() const + { return _pimpl->hasContent(); } + + bool RepoInfo::hasContent( const std::string & keyword_r ) const + { return _pimpl->hasContent( keyword_r ); } + + /////////////////////////////////////////////////////////////////// + + bool RepoInfo::hasLicense() const + { return hasLicense( std::string() ); } + + bool RepoInfo::hasLicense( const std::string & name_r ) const + { return !_pimpl->licenseTgz( name_r ).empty(); } + + + bool RepoInfo::needToAcceptLicense() const + { return needToAcceptLicense( std::string() ); } + + bool RepoInfo::needToAcceptLicense( const std::string & name_r ) const + { + const Pathname & licenseTgz( _pimpl->licenseTgz( name_r ) ); + if ( licenseTgz.empty() ) + return false; // no licenses at all + + ExternalProgram::Arguments cmd; + cmd.push_back( "tar" ); + cmd.push_back( "-t" ); + cmd.push_back( "-z" ); + cmd.push_back( "-f" ); + cmd.push_back( licenseTgz.asString() ); + ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout ); + + bool accept = true; + static const std::string noAcceptanceFile = "no-acceptance-needed\n"; + for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) + { + if ( output == noAcceptanceFile ) + { + accept = false; + } + } + prog.close(); + MIL << "License(" << name_r << ") in " << name() << " has to be accepted: " << (accept?"true":"false" ) << endl; + return accept; + } + + + std::string RepoInfo::getLicense( const Locale & lang_r ) + { return const_cast(this)->getLicense( std::string(), lang_r ); } + + std::string RepoInfo::getLicense( const Locale & lang_r ) const + { return getLicense( std::string(), lang_r ); } + + std::string RepoInfo::getLicense( const std::string & name_r, const Locale & lang_r ) const + { + LocaleSet avlocales( getLicenseLocales( name_r ) ); + if ( avlocales.empty() ) + return std::string(); + + Locale getLang( Locale::bestMatch( avlocales, lang_r ) ); + if ( !getLang && avlocales.find( Locale::noCode ) == avlocales.end() ) + { + WAR << "License(" << name_r << ") in " << name() << " contains no fallback text!" << endl; + // Using the fist locale instead of returning no text at all. + // So the user might recognize that there is a license, even if they + // can't read it. + getLang = *avlocales.begin(); + } + + // now extract the license file. + static const std::string licenseFileFallback( "license.txt" ); + std::string licenseFile( !getLang ? licenseFileFallback + : str::form( "license.%s.txt", getLang.c_str() ) ); + + ExternalProgram::Arguments cmd; + cmd.push_back( "tar" ); + cmd.push_back( "-x" ); + cmd.push_back( "-z" ); + cmd.push_back( "-O" ); + cmd.push_back( "-f" ); + cmd.push_back( _pimpl->licenseTgz( name_r ).asString() ); // if it not exists, avlocales was empty. + cmd.push_back( licenseFile ); + + std::string ret; + ExternalProgram prog( cmd, ExternalProgram::Discard_Stderr ); + for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) + { + ret += output; + } + prog.close(); + return ret; + } + + + LocaleSet RepoInfo::getLicenseLocales() const + { return getLicenseLocales( std::string() ); } + + LocaleSet RepoInfo::getLicenseLocales( const std::string & name_r ) const + { + const Pathname & licenseTgz( _pimpl->licenseTgz( name_r ) ); + if ( licenseTgz.empty() ) + return LocaleSet(); + + ExternalProgram::Arguments cmd; + cmd.push_back( "tar" ); + cmd.push_back( "-t" ); + cmd.push_back( "-z" ); + cmd.push_back( "-f" ); + cmd.push_back( licenseTgz.asString() ); + + LocaleSet ret; + ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout ); + for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) + { + static const C_Str license( "license." ); + static const C_Str dotTxt( ".txt\n" ); + if ( str::hasPrefix( output, license ) && str::hasSuffix( output, dotTxt ) ) + { + if ( output.size() <= license.size() + dotTxt.size() ) // license.txt + ret.insert( Locale() ); + else + ret.insert( Locale( std::string( output.c_str()+license.size(), output.size()- license.size() - dotTxt.size() ) ) ); + } + } + prog.close(); + return ret; + } + + /////////////////////////////////////////////////////////////////// + + std::ostream & RepoInfo::dumpOn( std::ostream & str ) const + { + RepoInfoBase::dumpOn(str); + if ( _pimpl->baseurl2dump() ) + { + for ( const auto & url : _pimpl->baseUrls().raw() ) + { + str << "- url : " << url << std::endl; + } + } + + // print if non empty value + auto strif( [&] ( const std::string & tag_r, const std::string & value_r ) { + if ( ! value_r.empty() ) + str << tag_r << value_r << std::endl; + }); + + strif( (_pimpl->_mirrorListForceMetalink ? "- metalink : " : "- mirrorlist : "), rawMirrorListUrl().asString() ); + strif( "- path : ", path().asString() ); + str << "- type : " << type() << std::endl; + str << "- priority : " << priority() << std::endl; + + // Yes No Default(Y) Default(N) +#define OUTS(T,B) ( indeterminate(T) ? (std::string("D(")+(B?"Y":"N")+")") : ((bool)T?"Y":"N") ) + str << "- gpgcheck : " << OUTS(_pimpl->rawGpgCheck(),gpgCheck()) + << " repo" << OUTS(_pimpl->rawRepoGpgCheck(),repoGpgCheck()) << (repoGpgCheckIsMandatory() ? "* ": " " ) + << "sig" << asString( validRepoSignature(), "?", "Y", "N" ) + << " pkg" << OUTS(_pimpl->rawPkgGpgCheck(),pkgGpgCheck()) << (pkgGpgCheckIsMandatory() ? "* ": " " ) + << std::endl; +#undef OUTS + + for ( const auto & url : _pimpl->gpgKeyUrls().raw() ) + { + str << "- gpgkey : " << url << std::endl; + } + + if ( ! indeterminate(_pimpl->keeppackages) ) + str << "- keeppackages: " << keepPackages() << std::endl; + + strif( "- service : ", service() ); + strif( "- targetdistro: ", targetDistribution() ); + strif( "- filePath: ", filepath().asString() ); + strif( "- metadataPath: ", metadataPath().asString() ); + strif( "- packagesPath: ", packagesPath().asString() ); + + return str; + } + + std::ostream & RepoInfo::dumpAsIniOn( std::ostream & str ) const + { + RepoInfoBase::dumpAsIniOn(str); + + if ( _pimpl->baseurl2dump() ) + { + str << "baseurl="; + std::string indent; + for ( const auto & url : _pimpl->baseUrls().raw() ) + { + str << indent << hotfix1050625::asString( url ) << endl; + if ( indent.empty() ) indent = " "; // "baseurl=" + } + } + + if ( ! _pimpl->path.empty() ) + str << "path="<< path() << endl; + + if ( ! (rawMirrorListUrl().asString().empty()) ) + str << (_pimpl->_mirrorListForceMetalink ? "metalink=" : "mirrorlist=") << hotfix1050625::asString( rawMirrorListUrl() ) << endl; + + if ( type() != repo::RepoType::NONE ) + str << "type=" << type().asString() << endl; + + if ( priority() != defaultPriority() ) + str << "priority=" << priority() << endl; + + if ( ! indeterminate(_pimpl->rawGpgCheck()) ) + str << "gpgcheck=" << (_pimpl->rawGpgCheck() ? "1" : "0") << endl; + + if ( ! indeterminate(_pimpl->rawRepoGpgCheck()) ) + str << "repo_gpgcheck=" << (_pimpl->rawRepoGpgCheck() ? "1" : "0") << endl; + + if ( ! indeterminate(_pimpl->rawPkgGpgCheck()) ) + str << "pkg_gpgcheck=" << (_pimpl->rawPkgGpgCheck() ? "1" : "0") << endl; + + { + std::string indent( "gpgkey="); + for ( const auto & url : _pimpl->gpgKeyUrls().raw() ) + { + str << indent << url << endl; + if ( indent[0] != ' ' ) + indent = " "; + } + } + + if (!indeterminate(_pimpl->keeppackages)) + str << "keeppackages=" << keepPackages() << endl; + + if( ! service().empty() ) + str << "service=" << service() << endl; + + return str; + } + + std::ostream & RepoInfo::dumpAsXmlOn( std::ostream & str, const std::string & content ) const + { + std::string tmpstr; + str + << "rawGpgCheck()) ) + str << " raw_gpgcheck=\"" << (_pimpl->rawGpgCheck() ? "1" : "0") << "\""; + if ( ! indeterminate(_pimpl->rawRepoGpgCheck()) ) + str << " raw_repo_gpgcheck=\"" << (_pimpl->rawRepoGpgCheck() ? "1" : "0") << "\""; + if ( ! indeterminate(_pimpl->rawPkgGpgCheck()) ) + str << " raw_pkg_gpgcheck=\"" << (_pimpl->rawPkgGpgCheck() ? "1" : "0") << "\""; + if (!(tmpstr = gpgKeyUrl().asString()).empty()) + if (!(tmpstr = gpgKeyUrl().asString()).empty()) + str << " gpgkey=\"" << escape(tmpstr) << "\""; + if (!(tmpstr = mirrorListUrl().asString()).empty()) + str << (_pimpl->_mirrorListForceMetalink ? " metalink=\"" : " mirrorlist=\"") << escape(tmpstr) << "\""; + str << ">" << endl; + + if ( _pimpl->baseurl2dump() ) + { + for_( it, baseUrlsBegin(), baseUrlsEnd() ) // !transform iterator replaces variables + str << "" << escape((*it).asString()) << "" << endl; + } + + str << "" << endl; + return str; + } + + + std::ostream & operator<<( std::ostream & str, const RepoInfo & obj ) + { + return obj.dumpOn(str); + } + + std::ostream & operator<<( std::ostream & str, const RepoInfo::GpgCheck & obj ) + { + switch ( obj ) + { +#define OUTS( V ) case RepoInfo::V: return str << #V; break + OUTS( GpgCheck::On ); + OUTS( GpgCheck::Strict ); + OUTS( GpgCheck::AllowUnsigned ); + OUTS( GpgCheck::AllowUnsignedRepo ); + OUTS( GpgCheck::AllowUnsignedPackage ); + OUTS( GpgCheck::Default ); + OUTS( GpgCheck::Off ); + OUTS( GpgCheck::indeterminate ); +#undef OUTS + } + return str << "GpgCheck::UNKNOWN"; + } + + bool RepoInfo::requireStatusWithMediaFile () const + { + // We skip the check for downloading media unless a local copy of the + // media file exists and states that there is more than one medium. + bool canSkipMediaCheck = std::all_of( baseUrlsBegin(), baseUrlsEnd(), []( const zypp::Url &url ) { return url.schemeIsDownloading(); }); + if ( canSkipMediaCheck ) { + const auto &mDataPath = metadataPath(); + if ( not mDataPath.empty() ) { + PathInfo mediafile { mDataPath/"media.1/media" }; + if ( mediafile.isExist() ) { + repo::SUSEMediaVerifier lverifier { mediafile.path() }; + if ( lverifier && lverifier.totalMedia() > 1 ) { + canSkipMediaCheck = false; + } + } + } + } + if ( canSkipMediaCheck ) + DBG << "Can SKIP media.1/media check for status calc of repo " << alias() << endl; + return not canSkipMediaCheck; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/RepoInfo.h b/zypp/RepoInfo.h new file mode 100644 index 0000000..6485397 --- /dev/null +++ b/zypp/RepoInfo.h @@ -0,0 +1,588 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoInfo.h + * +*/ +#ifndef ZYPP2_REPOSITORYINFO_H +#define ZYPP2_REPOSITORYINFO_H + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfo + // + /** + * \short What is known about a repository + * + * The class RepoInfo represents everything that + * is known about a software repository. + * + * It can be used to store information about known + * sources. + * + * This class tries to be compatible with the + * concept of a .repo file used by YUM and + * also available in the openSUSE build service. + * See man yum.conf. + * + * Example file + * + * \code + * [ruby] + * name=Ruby repository (openSUSE_10.2) + * type=rpm-md + * baseurl=http://software.opensuse.org/download/ruby/openSUSE_10.2/ + * http://some.opensuse.mirror/ruby/openSUSE_10.2/ + * gpgcheck=1 + * gpgkey=http://software.opensuse.org/openSUSE-Build-Service.asc + * enabled=1 + * priority=10 + * \endcode + * + * \note A RepoInfo is a hint about how + * to create a Repository. + * + * \note Name, baseUrls and mirrorUrl are subject to repo variable replacement + * (\see \ref RepoVariablesStringReplacer). + */ + class ZYPP_API RepoInfo : public repo::RepoInfoBase + { + friend std::ostream & operator<<( std::ostream & str, const RepoInfo & obj ); + + public: + RepoInfo(); + ~RepoInfo() override; + + RepoInfo(const RepoInfo &) = default; + RepoInfo(RepoInfo &&) = default; + RepoInfo &operator=(const RepoInfo &) = default; + RepoInfo &operator=(RepoInfo &&) = default; + + /** Represents no Repository (one with an empty alias). */ + static const RepoInfo noRepo; + + public: + /** + * The default priority (\c 99). + */ + static unsigned defaultPriority(); + /** + * The least priority (unsigned(-1)). + */ + static unsigned noPriority(); + /** + * Repository priority for solver. + * Some number between \c 1 (highest priority) and \c 99 (\ref defaultPriority). + */ + unsigned priority() const; + /** + * Set repository priority for solver. + * A \c newval_r of \c 0 sets the default priority. + * \see \ref priority. + */ + void setPriority( unsigned newval_r ); + + using url_set = std::list; + using urls_size_type = url_set::size_type; + using urls_const_iterator = transform_iterator; + /** + * whether repository urls are available + */ + bool baseUrlsEmpty() const; + /** + * Whether there are manualy configured repository urls. + * If \c false, a mirrorlist might be used. + */ + bool baseUrlSet() const; + /** + * number of repository urls + */ + urls_size_type baseUrlsSize() const; + /** + * iterator that points at begin of repository urls + */ + urls_const_iterator baseUrlsBegin() const; + /** + * iterator that points at end of repository urls + */ + urls_const_iterator baseUrlsEnd() const; + + /** + * Pars pro toto: The first repository url + */ + Url url() const + { return( baseUrlsEmpty() ? Url() : *baseUrlsBegin()); } + /** + * Pars pro toto: The first repository raw url (no variables replaced) + */ + Url rawUrl() const; + + /** + * The complete set of repository urls + * + * These are either the configured baseurls, or if empty, the downloaded + * mirror list (\see \ref mirrorListUrl) + */ + url_set baseUrls() const; + /** + * The complete set of raw repository urls (no variables replaced) + */ + url_set rawBaseUrls() const; + + /** + * Add a base url. \see baseUrls + * \param url The base url for the repository. + * + * To recreate the base URLs list, use \ref setBaseUrl(const Url &) followed + * by addBaseUrl(). + */ + void addBaseUrl( Url url ); + /** + * Clears current base URL list and adds \a url. + */ + void setBaseUrl( Url url ); + /** + * Clears current base URL list and adds an \ref url_set. + */ + void setBaseUrls( url_set urls ); + + /** + * \short Repository path + * + * Pathname relative to the base Url where the product/repository + * is located + * + * For media containing more than one product, or repositories not + * located at the root of the media it is important to know the path + * to the product directory relative to the media root. So a media + * verifier can be set for that media. You may also read it as + * baseUrl = url to mount and path = path on the + * mounted media. + * + * It is not mandatory, and the default is \c /. + * + * \note As a repository can have multiple Urls, the path is unique and + * the same for all Urls, so it is assumed all the Urls have the + * same media layout. + * + */ + Pathname path() const; + /** + * set the product path. \see path() + * \param path the path to the product + */ + void setPath( const Pathname &path ); + + /** + * Url of a file which contains a list of repository urls + */ + Url mirrorListUrl() const; + /** + * The raw mirrorListUrl (no variables replaced). + */ + Url rawMirrorListUrl() const; + /** + * Set mirror list url. \see mirrorListUrl + * \param url The base url for the list + */ + void setMirrorListUrl( const Url &url ); + /** Like \ref setMirrorListUrl but take an \a url_set */ + void setMirrorListUrls( url_set urls ); + + /** Like \ref setMirrorListUrl but expect metalink format. */ + void setMetalinkUrl( const Url &url ); + /** Like \ref setMirrorListUrls but expect metalink format. */ + void setMetalinkUrls( url_set urls ); + + /** + * Type of repository, + * + */ + repo::RepoType type() const; + /** + * This allows to adjust the \ref RepoType lazy, from \c NONE to + * some probed value, even for const objects. + * + * This is a NOOP if the current type is not \c NONE. + */ + void setProbedType( const repo::RepoType &t ) const; + /** + * set the repository type \see type + * \param t + */ + void setType( const repo::RepoType &t ); + + /** + * \short Path where this repo metadata was read from + * + * \note could be an empty pathname for repo + * infos created in memory. + */ + Pathname metadataPath() const; + /** + * \short Set the path where the local metadata is stored + * + * The path to the repositories metadata is usually provided by + * the RepoManager. If you want to use a temporary repository + * (not under RepoManagers control), and you set a metadataPath + * with basename \c %AUTO%, all data directories (raw metadata, + * solv file and package cache) will be created by replacing \c %AUTO% + * with \c %RAW%, \c %SLV% or \c %PKG% . This will change the value + * of \ref packagesPath accordingly, unless you assigned a custom + * value using \ref setPackagesPath. + * + * \code + * RepoInfo repo; + * repo.setAlias( "Temp" ); + * repo.setBaseUrl( Url("http://someserver/somepath/") ); + * repo.setMetadataPath( "/tmp/temprepodata/%AUTO%" ); + * + * // will use + * // /tmp/temprepodata/%RAW% - raw metadata + * // /%SLV% - solv file + * // /%PKG% - packages + *\endcode + * + * \param path directory path + */ + void setMetadataPath( const Pathname &path ); + + /** Whether \ref metadataPath uses \c %AUTO% setup. */ + bool usesAutoMetadataPaths() const; + + /** + * \short Path where this repo packages are cached + */ + Pathname packagesPath() const; + /** + * \short set the path where the local packages are stored + * + * \param path directory path + */ + void setPackagesPath( const Pathname &path ); + + + /** \name Repository gpgchecks + * How signature checking should be performed for this repo. + * + * The values are computed based in the settings of \c gpgcheck, \c repo_gpgcheck + * end \c pkg_gpgcheck in \c zypp.conf. Explicitly setting these values in the + * repositories \a .repo file will overwrite the defaults from \c zypp.conf for this + * repo. + * + * If \c gpgcheck is \c on (the default) we will check the signature of repo metadata + * (packages are secured via checksum inside the metadata). Using unsigned repos + * needs to be confirmed. + * Packages from signed repos are accepted if their checksum matches the checksum + * stated in the repo metadata. + * Packages from unsigned repos need a valid gpg signature, using unsigned packages + * needs to be confirmed. + * + * The above default behavior can be tuned by explicitly setting \c repo_gpgcheck + * and/or \c pkg_gpgcheck: + * + * \c repo_gpgcheck = \c on same as the default. + * + * \c repo_gpgcheck = \c off will silently accept unsigned repos. It will NOT turn of + * signature checking on the whole. Nevertheless, it's not a secure setting. + * + * \c pkg_gpgcheck = \c on will enforce the package signature checking and the need + * to confirm unsigned packages for all repos (signed and unsigned). + * + * \c pkg_gpgcheck = \c off will silently accept unsigned packages. It will NOT turn of + * signature checking on the whole. Nevertheless, it's not a secure setting. + * + * If \c gpgCheck is \c off (not recommneded), no checks are performed. You can still + * enable them individually by setting \c repo_gpgcheck and/or \c pkg_gpgcheck to \c on. + * + * \code + * R: check repo signature is mandatory, confirm unsigned repos + * r: check repo signature, unsigned repos are ok but enforce p + * : do not check repo signatures + * + * P: check package signature always, confirm unsigned packages + * p: like P for unsigned repos, accepted by checksum for signed repos + * b: like p but accept unsigned packages + * : do not check package signatures + * pkg_ + * gpgcheck 1| * 0 1 + * ------------------------------------ + * repo_ *1| R/p R/b R/P + * 0| r/p r/b r/P + * + * pkg_ + * gpgcheck 0| * 0 1 + * ------------------------------------ + * repo_ *0| P + * 1| R R R/P + * \endcode + */ + //@{ + /** Whether default signature checking should be performed. */ + bool gpgCheck() const; + /** Set the value for \ref gpgCheck (or \c indeterminate to use the default). */ + void setGpgCheck( TriBool value_r ); + /** \overload \deprecated legacy and for squid */ + void setGpgCheck( bool value_r ); + + /** Whether the signature of repo metadata should be checked for this repo. */ + bool repoGpgCheck() const; + /** Mandatory check (\ref repoGpgCheck is \c on) must ask to confirm using unsigned repos. */ + bool repoGpgCheckIsMandatory() const; + /** Set the value for \ref repoGpgCheck (or \c indeterminate to use the default). */ + void setRepoGpgCheck( TriBool value_r ); + + /** Whether the signature of rpm packages should be checked for this repo. */ + bool pkgGpgCheck() const; + /** Mandatory check (\ref pkgGpgCheck is not \c off) must ask to confirm using unsigned packages. */ + bool pkgGpgCheckIsMandatory() const; + /** Set the value for \ref pkgGpgCheck (or \c indeterminate to use the default). */ + void setPkgGpgCheck( TriBool value_r ); + + /** Whether the repo metadata are signed and successfully validated or \c indeterminate if unsigned. + * The value is usually set by \ref repo::Downloader when retrieving the metadata. + */ + TriBool validRepoSignature() const; + /** Set the value for \ref validRepoSignature (or \c indeterminate if unsigned). */ + void setValidRepoSignature( TriBool value_r ); + + /** Some predefined settings */ + enum class GpgCheck { + indeterminate, //< not specified + On, //< 1** --gpgcheck + Strict, //< 111 --gpgcheck-strict + AllowUnsigned, //< 100 --gpgcheck-allow-unsigned + AllowUnsignedRepo, //< 10* --gpgcheck-allow-unsigned-repo + AllowUnsignedPackage, //< 1*0 --gpgcheck-allow-unsigned-package + Default, //< *** --default-gpgcheck + Off, //< 0** --no-gpgcheck + }; + + /** Adjust *GpgCheck settings according to \a mode_r. + * \c GpgCheck::indeterminate will leave the settings as they are. + * \return whether setting were changed + */ + bool setGpgCheck( GpgCheck mode_r ); + //@} + + + /** Whether gpgkey URLs are defined */ + bool gpgKeyUrlsEmpty() const; + /** Number of gpgkey URLs defined */ + urls_size_type gpgKeyUrlsSize() const; + + /** The list of gpgkey URLs defined for this repo */ + url_set gpgKeyUrls() const; + /** The list of raw gpgkey URLs defined for this repo (no variables replaced) */ + url_set rawGpgKeyUrls() const; + /** Set a list of gpgkey URLs defined for this repo */ + void setGpgKeyUrls( url_set urls ); + + /** (leagcy API) The 1st gpgkey URL defined for this repo */ + Url gpgKeyUrl() const; + /** (leagcy API) The 1st raw gpgkey URL defined for this repo (no variables replaced) */ + Url rawGpgKeyUrl() const; + /** (leagcy API) Set the gpgkey URL defined for this repo */ + void setGpgKeyUrl( const Url &gpgkey ); + + /** downloads all configured gpg keys into the defined directory */ + Pathname provideKey(const std::string &keyID_r, const Pathname &targetDirectory_r ) const; + + /** + * \short Whether packages downloaded from this repository will be kept in local cache + */ + bool keepPackages() const; + /** + * \short Set if packaqes downloaded from this repository will be kept in local cache + * + * If the setting is true, all downloaded packages from this repository will be + * copied to the local raw cache. + * + * \param keep true (keep the downloaded packages) or false (delete them after installation) + * + */ + void setKeepPackages( bool keep ); + + /** + * Gets name of the service to which this repository belongs or empty string + * if it has been added manually. + */ + std::string service() const; + /** + * sets service which added this repository + */ + void setService( const std::string& name ); + + /** + * Distribution for which is this repository meant. + */ + std::string targetDistribution() const; + /** + * Sets the distribution for which is this repository meant. This is + * an in-memory value only, does not get written to the .repo file upon + * saving. + */ + void setTargetDistribution(const std::string & targetDistribution); + + + /** Content keywords defined. */ + const std::set & contentKeywords() const; + + /** Add content keywords */ + void addContent( const std::string & keyword_r ); + /** \overload add keywords from container */ + template + void addContentFrom( TIterator begin_r, TIterator end_r ) + { for_( it, begin_r, end_r ) addContent( *it ); } + /** \overload */ + template + void addContentFrom( const TContainer & container_r ) + { addContentFrom( container_r.begin(), container_r.end() ); } + + /** Check for content keywords. + * They may be missing due to missing metadata in disabled repos. + */ + bool hasContent() const; + /** \overload check for a keywords being present */ + bool hasContent( const std::string & keyword_r ) const; + /** \overload check for \b all keywords being present */ + template + bool hasContentAll( TIterator begin_r, TIterator end_r ) const + { for_( it, begin_r, end_r ) if ( ! hasContent( *it ) ) return false; return true; } + /** \overload */ + template + bool hasContentAll( const TContainer & container_r ) const + { return hasContentAll( container_r.begin(), container_r.end() ); } + /** \overload check for \b any keyword being present */ + template + bool hasContentAny( TIterator begin_r, TIterator end_r ) const + { for_( it, begin_r, end_r ) if ( hasContent( *it ) ) return true; return false; } + /** \overload */ + template + bool hasContentAny( const TContainer & container_r ) const + { return hasContentAny( container_r.begin(), container_r.end() ); } + + public: + /** \name Repository/Product license + * In case a repository provides multiple license tarballs in repomd.xml + * \code + * ... + * ... + * ... + * \endcode + * you can address the individual licenses by passing their name + * (e.g. \c "sles" to access the \c type="license-sles"). + * No on an empty name will refer to \c type="license". + */ + //@{ + /** Whether there is a license associated with the repo. */ + bool hasLicense() const; + /** \overload taking a (product)name */ + bool hasLicense( const std::string & name_r ) const; + + /** Whether the repo license has to be accepted, e.g. there is no + * no acceptance needed for openSUSE. + */ + bool needToAcceptLicense() const; + /** \overload taking a (product)name */ + bool needToAcceptLicense( const std::string & name_r ) const; + + /** Return the best license for the current (or a specified) locale. */ + std::string getLicense( const Locale & lang_r = Locale() ) const; + /** \overload not const LEGACY API */ + std::string getLicense( const Locale & lang_r = Locale() ); // LEGACY API + /** \overload taking a (product)name */ + std::string getLicense( const std::string & name_r, const Locale & lang_r = Locale() ) const; + + /** Return the locales the license is available for. + * \ref Locale::noCode is included in case of \c license.txt which does + * not specify a specific locale. + */ + LocaleSet getLicenseLocales() const; + /** \overload taking a (product)name */ + LocaleSet getLicenseLocales( const std::string & name_r ) const; + //@} + + /** + * Returns true if this repository requires the media.1/media file to be included + * in the metadata status and repo status calculations. + */ + bool requireStatusWithMediaFile () const; + + public: + /** + * Write a human-readable representation of this RepoInfo object + * into the \a str stream. Useful for logging. + */ + std::ostream & dumpOn( std::ostream & str ) const override; + + /** + * Write this RepoInfo object into \a str in a .repo
file format. + * Raw values, no variable replacement. + */ + std::ostream & dumpAsIniOn( std::ostream & str ) const override; + + /** + * Write an XML representation of this RepoInfo object. + * Repo variables replaced. + * + * \param str + * \param content this argument is ignored (used in other classed derived + * from RepoInfoBase. + */ + std::ostream & dumpAsXmlOn( std::ostream & str, const std::string & content = "" ) const override; + + /** Raw values for RepoManager + * \internal + */ + void getRawGpgChecks( TriBool & g_r, TriBool & r_r, TriBool & p_r ) const; + + struct Impl; + private: + friend class RepoManager; + + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoInfo */ + using RepoInfo_Ptr = shared_ptr; + /** \relates RepoInfo */ + using RepoInfo_constPtr = shared_ptr; + /** \relates RepoInfo */ + using RepoInfoList = std::list; + + /** \relates RepoInfo Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoInfo & obj ) ZYPP_API; + + /** \relates RepoInfo::GpgCheck Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoInfo::GpgCheck & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP2_REPOSITORYINFO_H diff --git a/zypp/RepoManager.cc b/zypp/RepoManager.cc new file mode 100644 index 0000000..f55d0e5 --- /dev/null +++ b/zypp/RepoManager.cc @@ -0,0 +1,279 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoManager.cc + * +*/ + +#include +#include +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +using std::endl; +using std::string; +using namespace zypp::repo; + +#define OPT_PROGRESS const ProgressData::ReceiverFnc & = ProgressData::ReceiverFnc() + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class RepoManager::Impl + /// \brief RepoManager implementation. + /// + /////////////////////////////////////////////////////////////////// + struct ZYPP_LOCAL RepoManager::Impl + { + public: + Impl( zyppng::SyncContextRef &&ctx, RepoManagerOptions &&opt) { + _ngMgr = zyppng::SyncRepoManager::create( std::move(ctx), std::move(opt) ).unwrap(); + } + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + public: + const zyppng::SyncRepoManager &ngMgr() const { + return *_ngMgr; + } + + zyppng::SyncRepoManager &ngMgr() { + return *_ngMgr; + } + + private: + zyppng::SyncRepoManagerRef _ngMgr; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( zyppng::SyncContextRef(_ngMgr->zyppContext()), RepoManagerOptions(_ngMgr->options()) ); } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoManager::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const RepoManager::Impl & obj ) + { return str << "RepoManager::Impl"; } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoManager + // + /////////////////////////////////////////////////////////////////// + + RepoManager::RepoManager( RepoManagerOptions opt ) + : _pimpl( new Impl( zyppng::SyncContext::defaultContext(), std::move(opt)) ) + {} + + RepoManager::~RepoManager() + {} + + bool RepoManager::repoEmpty() const + { return _pimpl->ngMgr().repoEmpty(); } + + RepoManager::RepoSizeType RepoManager::repoSize() const + { return _pimpl->ngMgr().repoSize(); } + + RepoManager::RepoConstIterator RepoManager::repoBegin() const + { return _pimpl->ngMgr().repoBegin(); } + + RepoManager::RepoConstIterator RepoManager::repoEnd() const + { return _pimpl->ngMgr().repoEnd(); } + + RepoInfo RepoManager::getRepo( const std::string & alias ) const + { return _pimpl->ngMgr().getRepo( alias ); } + + bool RepoManager::hasRepo( const std::string & alias ) const + { return _pimpl->ngMgr().hasRepo( alias ); } + + std::string RepoManager::makeStupidAlias( const Url & url_r ) + { + std::string ret( url_r.getScheme() ); + if ( ret.empty() ) + ret = "repo-"; + else + ret += "-"; + + std::string host( url_r.getHost() ); + if ( ! host.empty() ) + { + ret += host; + ret += "-"; + } + + static Date::ValueType serial = Date::now(); + ret += Digest::digest( Digest::sha1(), str::hexstring( ++serial ) +url_r.asCompleteString() ).substr(0,8); + return ret; + } + + RepoStatus RepoManager::metadataStatus( const RepoInfo & info ) const + { return _pimpl->ngMgr().metadataStatus( info ).unwrap(); } + + RepoManager::RefreshCheckStatus RepoManager::checkIfToRefreshMetadata( const RepoInfo &info, const Url &url, RawMetadataRefreshPolicy policy ) + { return _pimpl->ngMgr().checkIfToRefreshMetadata( info, url, policy ).unwrap(); } + + Pathname RepoManager::metadataPath( const RepoInfo &info ) const + { return _pimpl->ngMgr().metadataPath( info ).unwrap(); } + + Pathname RepoManager::packagesPath( const RepoInfo &info ) const + { return _pimpl->ngMgr().packagesPath( info ).unwrap(); } + + void RepoManager::refreshMetadata( const RepoInfo &info, RawMetadataRefreshPolicy policy, const ProgressData::ReceiverFnc & progressrcv ) + { + // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1) + zypp::media::ScopedDisableMediaChangeReport guard( info.baseUrlsSize() > 1 ); + return _pimpl->ngMgr().refreshMetadata( info, policy, nullptr ).unwrap(); + } + + void RepoManager::cleanMetadata( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().cleanMetadata( info, nullptr ).unwrap(); } + + void RepoManager::cleanPackages( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().cleanPackages( info, nullptr ).unwrap(); } + + RepoStatus RepoManager::cacheStatus( const RepoInfo &info ) const + { return _pimpl->ngMgr().cacheStatus( info ).unwrap(); } + + void RepoManager::buildCache( const RepoInfo &info, CacheBuildPolicy policy, const ProgressData::ReceiverFnc & progressrcv ) + { + callback::SendReport report; + auto adapt = zyppng::ProgressObserverAdaptor( progressrcv, report ); + return _pimpl->ngMgr().buildCache( info, policy, adapt.observer() ).unwrap(); + } + + void RepoManager::cleanCache( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().cleanCache( info, nullptr ).unwrap(); } + + bool RepoManager::isCached( const RepoInfo &info ) const + { return _pimpl->ngMgr().isCached( info ).unwrap(); } + + void RepoManager::loadFromCache( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().loadFromCache( info, nullptr ).unwrap(); } + + void RepoManager::cleanCacheDirGarbage( const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().cleanCacheDirGarbage( nullptr ).unwrap(); } + + repo::RepoType RepoManager::probe( const Url & url, const Pathname & path ) const + { return _pimpl->ngMgr().probe( url, path ).unwrap(); } + + repo::RepoType RepoManager::probe( const Url & url ) const + { return _pimpl->ngMgr().probe( url ).unwrap(); } + + void RepoManager::addRepository( const RepoInfo &info, const ProgressData::ReceiverFnc & progressrcv ) + { + callback::SendReport report; + auto adapt = zyppng::ProgressObserverAdaptor( progressrcv, report ); + RepoInfo updatedRepo = _pimpl->ngMgr().addRepository( info, adapt.observer() ).unwrap(); + + // We should fix the API as we must inject those paths + // into the repoinfo in order to keep it usable. + RepoInfo & oinfo( const_cast(info) ); + oinfo.setFilepath( updatedRepo.filepath() ); + oinfo.setMetadataPath( zyppng::rawcache_path_for_repoinfo( _pimpl->ngMgr().options(), updatedRepo ).unwrap() ); + oinfo.setPackagesPath( zyppng::packagescache_path_for_repoinfo( _pimpl->ngMgr().options(), updatedRepo ).unwrap() ); + } + + void RepoManager::addRepositories( const Url &url, const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().addRepositories( url, nullptr ).unwrap(); } + + void RepoManager::removeRepository( const RepoInfo & info, const ProgressData::ReceiverFnc & progressrcv ) + { + callback::SendReport report; + auto adapt = zyppng::ProgressObserverAdaptor( progressrcv, report ); + return _pimpl->ngMgr().removeRepository( info, adapt.observer() ).unwrap(); + } + + void RepoManager::modifyRepository( const std::string &alias, const RepoInfo & newinfo, const ProgressData::ReceiverFnc & progressrcv ) + { + RepoInfo updated = _pimpl->ngMgr().modifyRepository( alias, newinfo, nullptr ).unwrap(); + // We should fix the API as we must inject those paths + // into the repoinfo in order to keep it usable. + RepoInfo & oinfo( const_cast(newinfo) ); + oinfo.setFilepath( updated.filepath()); + oinfo.setMetadataPath( zyppng::rawcache_path_for_repoinfo( _pimpl->ngMgr().options(), updated ).unwrap() ); + oinfo.setPackagesPath( zyppng::packagescache_path_for_repoinfo( _pimpl->ngMgr().options(), updated ).unwrap() ); + } + + RepoInfo RepoManager::getRepositoryInfo( const std::string &alias, const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().getRepositoryInfo( alias ).unwrap(); } + + RepoInfo RepoManager::getRepositoryInfo( const Url & url, const url::ViewOption & urlview, const ProgressData::ReceiverFnc & progressrcv ) + { return _pimpl->ngMgr().getRepositoryInfo( url, urlview ).unwrap(); } + + bool RepoManager::serviceEmpty() const + { return _pimpl->ngMgr().serviceEmpty(); } + + RepoManager::ServiceSizeType RepoManager::serviceSize() const + { return _pimpl->ngMgr().serviceSize(); } + + RepoManager::ServiceConstIterator RepoManager::serviceBegin() const + { return _pimpl->ngMgr().serviceBegin(); } + + RepoManager::ServiceConstIterator RepoManager::serviceEnd() const + { return _pimpl->ngMgr().serviceEnd(); } + + ServiceInfo RepoManager::getService( const std::string & alias ) const + { return _pimpl->ngMgr().getService( alias ); } + + bool RepoManager::hasService( const std::string & alias ) const + { return _pimpl->ngMgr().hasService( alias ); } + + repo::ServiceType RepoManager::probeService( const Url &url ) const + { return _pimpl->ngMgr().probeService( url ).unwrap(); } + + void RepoManager::addService( const std::string & alias, const Url& url ) + { return _pimpl->ngMgr().addService( alias, url ).unwrap(); } + + void RepoManager::addService( const ServiceInfo & service ) + { return _pimpl->ngMgr().addService( service ).unwrap(); } + + void RepoManager::removeService( const std::string & alias ) + { return _pimpl->ngMgr().removeService( alias ).unwrap(); } + + void RepoManager::removeService( const ServiceInfo & service ) + { return _pimpl->ngMgr().removeService( service ).unwrap(); } + + void RepoManager::refreshServices( const RefreshServiceOptions & options_r ) + { return _pimpl->ngMgr().refreshServices( options_r ).unwrap(); } + + void RepoManager::refreshService( const std::string & alias, const RefreshServiceOptions & options_r ) + { return _pimpl->ngMgr().refreshService( alias, options_r ).unwrap(); } + + void RepoManager::refreshService( const ServiceInfo & service, const RefreshServiceOptions & options_r ) + { return _pimpl->ngMgr().refreshService( service, options_r ).unwrap(); } + + void RepoManager::modifyService( const std::string & oldAlias, const ServiceInfo & service ) + { return _pimpl->ngMgr().modifyService( oldAlias, service ).unwrap(); } + + void RepoManager::refreshGeoIp (const RepoInfo::url_set &urls) + { (void) _pimpl->ngMgr().refreshGeoIp( urls ); } + + //////////////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const RepoManager & obj ) + { return str << *obj._pimpl; } + + std::list readRepoFile(const Url &repo_file) + { + return zyppng::RepoManagerWorkflow::readRepoFile( zyppng::SyncContext::defaultContext (), repo_file ).unwrap(); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/RepoManager.h b/zypp/RepoManager.h new file mode 100644 index 0000000..e9200e6 --- /dev/null +++ b/zypp/RepoManager.h @@ -0,0 +1,665 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/RepoManager.h + * +*/ +#ifndef ZYPP_REPOMANAGER_H +#define ZYPP_REPOMANAGER_H + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** + * Parses \a repo_file and returns a list of \ref RepoInfo objects + * corresponding to repositories found within the file. + * + * \param repo_file Valid URL of the repo file. The URL is subject to + * repo variable expansion. + * + * \return found list + * + * \throws MediaException If the access to the url fails + * \throws ParseException If the file parsing fails + * \throws Exception On other errors. + */ + std::list readRepoFile(const Url & repo_file) ZYPP_API; + + /** + * \short creates and provides information about known sources. + * + */ + class ZYPP_API RepoManager + { + friend std::ostream & operator<<( std::ostream & str, const RepoManager & obj ); + + public: + /** Implementation */ + struct Impl; + + /** ServiceInfo typedefs */ + using ServiceSet = std::set; + using ServiceConstIterator = ServiceSet::const_iterator; + using ServiceSizeType = ServiceSet::size_type; + + /** RepoInfo typedefs */ + using RepoSet = std::set; + using RepoConstIterator = RepoSet::const_iterator; + using RepoSizeType = RepoSet::size_type; + + public: + RepoManager( RepoManagerOptions options = RepoManagerOptions() ); + /** Dtor */ + ~RepoManager(); + + using RawMetadataRefreshPolicy = RepoManagerFlags::RawMetadataRefreshPolicy; + static constexpr RawMetadataRefreshPolicy RefreshIfNeeded = RepoManagerFlags::RefreshIfNeeded; + static constexpr RawMetadataRefreshPolicy RefreshForced = RepoManagerFlags::RefreshForced; + static constexpr RawMetadataRefreshPolicy RefreshIfNeededIgnoreDelay = RepoManagerFlags::RefreshIfNeededIgnoreDelay; + + using CacheBuildPolicy = RepoManagerFlags::CacheBuildPolicy; + static constexpr CacheBuildPolicy BuildIfNeeded = CacheBuildPolicy::BuildIfNeeded; + static constexpr CacheBuildPolicy BuildForced = CacheBuildPolicy::BuildForced; + + /** Flags for tuning RefreshService */ + using RefreshServiceBit = RepoManagerFlags::RefreshServiceBit; + static constexpr RefreshServiceBit RefreshService_restoreStatus = RefreshServiceBit::RefreshService_restoreStatus; + static constexpr RefreshServiceBit RefreshService_forceRefresh = RefreshServiceBit::RefreshService_forceRefresh; + + using RefreshServiceFlags = RepoManagerFlags::RefreshServiceFlags; + + /** Options tuning RefreshService */ + using RefreshServiceOptions = RepoManagerFlags::RefreshServiceFlags; + + /** \name Known repositories. + * + * The known repositories are read from + * \ref RepoManagerOptions::knownReposPath passed on the Ctor. + * Which defaults to ZYpp global settings. + */ + //@{ + bool repoEmpty() const; + RepoSizeType repoSize() const; + RepoConstIterator repoBegin() const; + RepoConstIterator repoEnd() const; + Iterable repos() const; + + /** List of known repositories. */ + std::list knownRepositories() const + { return std::list(repoBegin(),repoEnd()); } + + /** Find RepoInfo by alias or return \ref RepoInfo::noRepo. */ + RepoInfo getRepo( const std::string & alias ) const; + /** \overload Take alias from RepoInfo. */ + RepoInfo getRepo( const RepoInfo & info_r ) const + { return getRepo( info_r.alias() ); } + + /** Return whether there is a known repository for \c alias. */ + bool hasRepo( const std::string & alias ) const; + /** \overload Take alias from RepoInfo. */ + bool hasRepo( const RepoInfo & info_r ) const + { return hasRepo( info_r.alias() ); } + + /** Some stupid string but suitable as alias for your url if nothing better is available. + * Something like \c "http-download.opensuse.org-83df67e5" + */ + static std::string makeStupidAlias( const Url & url_r = Url() ); + //@} + + /** + * \short Status of local metadata + */ + RepoStatus metadataStatus( const RepoInfo &info ) const; + + using RefreshCheckStatus = RepoManagerFlags::RefreshCheckStatus; + static constexpr RefreshCheckStatus REFRESH_NEEDED = RefreshCheckStatus::REFRESH_NEEDED; /**< refresh is needed */ + static constexpr RefreshCheckStatus REPO_UP_TO_DATE = RefreshCheckStatus::REPO_UP_TO_DATE; /**< repository not changed */ + static constexpr RefreshCheckStatus REPO_CHECK_DELAYED = RefreshCheckStatus::REPO_CHECK_DELAYED; /**< refresh is delayed due to settings */ + + /** + * Checks whether to refresh metadata for specified repository and url. + *

FLc!Uf|5MY$|EkI6#uTh3zF1#}?RqfE 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%0DBJl2zQ9N6r#6ip71hz{QC@q1 zzW!X7%=Vf26cM~CCI<8)hQ>L63UN{D@$8XsQxMSO%syHR(%=g?^s z3RfT=*fo$O-9;_4#v?G+Z_gb>893>cWbl>E-~0?MI|cv?y&>c-5{G5_cK4fN(TRM5 z7^eK-D;0sy-uln7d))ThVX*4;$7$~`5kqSi$R_iqM&AuKpH>D$zC~(r1Ejt}xW->R zt02hLk6*H&F*U!KkP7I{bCVP<1Nizj=Izrw)(Huqz_Mt348nam^QGyATibLE7!c0H zY<0dBEjyiliIm>x{yPD44w9vohB@KA32Avls#t(;{#S`$$p4z(<-bPf(M@A20G8G9 zIIWeE{aR8_`%24Lp#sRHcf;D@wMn*<_xNZiZl__D=>pRa)wUq_~u7myVCY4E7EQ=`YwuZ!h38LnP71k((b zZ`9(>G;ZYKePh@NL)R*SJ)aqeVv`8Ixq9D{ zPv^UX_J_Yl=a7mfk|A$kr8L-`wO7ClBpwV(4fm&C>gQx;`i1$P23XTSMC`LmL%eep zIiN!!E3Wl7*yu9t(TC(0zLJ&Kd5j{k30ED46D8-+3UyXmmV z#FID`R;t42RhuJe%!(90X%KTZA_)rs1fZ@?NB%pU?p3!U+4&=Rc|%cGuKIO4-{r(Z z;nvn)OiX?kTM`;<%u>Rlj}BQ#v)Q)BGn%23fiA=D>#%=j-@@WDBTT@A{M0bI`KppG z-JQ7ExNb&RvSGWTWsq>2o+%6OyNkY|mjtOn%79E0+egT1{S0-YhL1?80eFkxZ6_j< zhn_BKtree0MPvSM?||fSz;zuXqra6O1YeWk_U*ZUFNkb_AS1R6+n{Piy~LbNg%w}Z zy-~=emS#`-;m?;Zl9RIYTd4UKEYodY@_j0Lq9*jn``Q_(mW_OT!`9DWwkw=HY+?yffNOAJ__v9s z1RX&2mEUw|p!&*wf82bUZ`VdrX{$|PX3H0R*X*}gkIGLcor*P4QMLdWWoSg03LueN zdeBwxw95C+>Ro)Y9zCHG@h~yfYullDJOLUTv5jkoxbX;rJrl$;RkhSS%)3u(WRmi; z${XzHa~|7TEv?4`LKr;)AJs&l$SDXTwhQ!vr$ZPA+dPQ2$moL+af^E?Un7JRL7?JI zco?ovc%a_mi#3Iu+Fy1lzv3P6QYT-+<}+q=yj378II5eO9BU(eajFM5FRm&WBLK;+~uKZFrBx`71P0o?)LC1PN=o z(Z&waz`%pl`y2?XBc#7`=;R-80_M9swP$1p&y$oy$e>;GGzqrxdwT&mk|jv$`9Sr# zbE2-~bDPypxp;~LgmiR)tKzA8);DDq$N7Z2m9?pY_tySZz()KF3@x;B_Buj<7=~ic zwCplr93$lz(LD%SdZAYK@R!5CU1224s8MZ8Mlr>{6|@+CZ*$P8bGu20Ps07xS3fdU>z#07%lg12as<(o z=kmQaFYMKNYghMr4zI~7Yt3o0ahS%=$5rc&j z0uoW5fY79XQE)p9^Qfsk0@57!UWWZt83JL4x1NSM7|Y<7DHAe{u`eM z4bbC$^XS?bF8-Avo@k{rYlsgabdrJA3F5+hm=obnJiWjNpQ|$d)9&yi6inr&b4gf~ z8l%l zLVfRpqFw*Q0s#$X7c4U>TH=O=g^am+@-w_c2B<<~E8}GBNTY+SQ8oUI5c=2C*wwR@ ziS>gMsM4873sf8HqGy*IC7YW9KXW*_vLkAn*7z`^!QYIS8{_1Lmv zgqBBf2@}RubI^NA7Zj|T6lI|iD&|ddmm_ZePKl)SIj2v2UQTke*3)qI@nmaw61;?J zrK9*_-O$Nu*T&mgu?zTWv}3W~A5f-U{F@?Kp7GZYaal$OY$TheuOCYc4cJQ*Bw=9n z>Hq(#?*Jf;3^-htq!P24g2~)lZ+ef_aGZaB$Kg!PQuwn^wMicZF!) z18?S6B~2Td%`yC!f0tJ2oiJe@%_9%UlDMAUA`O`ec=8u_AwN|z*kl44?KJLx8|ghq zXPBtc{psyA$&Mfthd$PXXiGY$8d@SeyQ*%CDsl6sGv%bI%^B*%EuPDqs)YgF+&@2=()E6Wor|}G6BavNttpCY01Yt`t0Xzj3e{03XRne-~^}C$C_n~uHkBV|y zMH7`4Uh-Ga)>TVLKR^~n531VL1uS%RIPo_clcFbT+4Y8@yhHP}KY+BewyA+{^qO;u z-j9(_H4$2xlcPlxvXk3?)3JTjYLA`YJ8YKOMvC>34Ch*S$i1)1*vu zTi}+Q(hJe+FBgh{_g4)@cF>s6(dk|>E22xpKFu&WmA?)B?mtcZRrEE1pHwlF`}WBq zE^@HJy6>B>kH-PsrB>H|5$D0fBQAvX?RGJ4+u|CrBJ2D5FY8?--}ca1yYO}!hwou@ zFNiDsG;jk$QW<_H$D+U@s%WnBM}2I#;R7VZvLXvf*(rr41&vde4V)IfTG;9GE55%A z)%2(K;C8I0E6Al~-^2^adw-;P(ciCh7*`{kL#v~hYkSIMH~D+P1CgH}-dO0mjK!DqL+ichubkidZipw5@SwO_h9~VDWwLG3qOcL?{w^c zlH-xr;3@{`Yfv-1rNKp@tFdA?lq38;D)1j*&L2kekQ3FxY6Mg9Tia5dlOaSW&6|1| z-U#>4cL@||qr@=T7H%pqHcQIM3Acf-$g;RJ2fdx}VW$}(r2lTGV}K(v03TnP>aQ<5 ztpTO6L=Dj9(JZ_tPT-0GbD&=@z7e#mXi57H7DpI*Hwgmr<{Z24S7lw?FFsvY%|fK> z1BQ2KVh0AnVw?t|IfgHVNviTpu`wjZbGlCaQ*ag9%WX&YpgqxFxIF^EubSI^Qo+RH zV&Z-@!b<5IMMC-Q6F+bRM~hqMx#ZgC6?ChFmkga)xfgIgtiel}eBtR|xybX2m{oxL zolJF((@A>D!f#gjf!tjWP2wws;* z901Aajq3Q+b;>;+-w!K_T|#tZG<4I|PM~*FLVHu!Fh@?f_>e~7a#NZ3y_!q^PKR%f zN04WJBXehMdzxoo>k2-~QO|wB2L}81l+Py_^>0XjWv_sNTlQu!hPs*eVGqRbR^1R& zRjhhwBk0cZ;jTq*Wwi4CQ^MIm+mIfC5;7mAS`r~Dp_-XD z4XrfyCyN+KG#+{udUhdnFgQK_wuDZY6uKf&n}eb-@OeKwAM9~4ESXg+t%&xLYVPD2 z<)%LSNMC)31E>yD!NCo1Rs0!bkN+?}$fZ;qbN@8ROyAGNUc%7Io`95ebSo7FK#V0B zjW3t~6k%wbIdOEldXTo-m!RHHcTH2prqp5!E=%s?G$GY^Ui;!uPf9J~1+@mgS~Xfq zU5!sJ9DiNaNeB)&l(+HPrVZQ%d&+F8G$AZmIaV*+?w+`v{?1sZ*T3ZVqgn4;ef^SV z8CcdqbMS~0IJT9kT^H}w^?Uc>nXFWnNpwN<5-<9Nzs>V|-woZcj6>;?zA^KLPNRu3 z!+VAIR&upDXC-k4#!wb^_TpUv!^MYa%~<==t`s0omzxy3`DA=8H-qNqARDRP5p* zz^@=chic(ytZu(PM4wv3$~+=pe#Tw?lef?E+rsnkV1{>X;nb`nlyTpp?AO5{W24Dz zIr}h?K9B@Jr5l)&e&HOGeKSjDY1SMj@OEa#8o$$NQd>x)e0c3M-UZ7(mMv=Z zBSg*Xxbrva8yNaLPe1zwvw4O;9jn1wJg`#*{^#CbRd~G-(r77o$+0ub9rff%&hnVRy?-?cpHXT5a$!FoS{qEZjHaK6P?n_iUQNIELSCMDr@vn8iG z(W7Kuk)nam1r&5`77q~!h!4;#`CzV9zJL6fs_>c55L~7OquYzXoT*I>(`FxTDp_c1 z|5U~8>3-jm{?XI&<114a;$|I<*ze-4prI4#^84X#)Ujn76zpCunIoe!V}t!mr2_*`BnyXp4djZIdm#z4MSQYm z-fOua{s9bP-GTKKMvpVaIc&M+!EhR}?Ef8Yi!)be4#zJ@qhTjB7DI)0pG8=2h0vrI zOn6Snxg%w|p$yPY4DU$Q_I{@L+5+k{q$x+^H;rHl_3#s;&k7^|Nc3f<)#^PmE19zO zgI#wyjo7AyFRF-^GaqL%LYS@qVx_8{f*~*z4Hr5jRY2I8OSG-GBH2ct=PJMdMRj?; zxo$*}SI2NhZgRo!Q&YL&k5?Y6QW{0-Gc!nGl||GD)iWC~#D#K$2C4?GQY!)Cuzw0eusL0QHGdCr4dMCA7?== z?pYPI-1HMJ)*G%rVjf|fwG+|BXWJ4f;M1Pj*A|0SZ!z~qX*W!k{zmtF<-!8on}NpN z!0%ZD*kOiW&k2P636De8IpIAJKt_r-==CQb8U0^8JUs_9qty5 ze_1Rap%m`hC{=Ut;R-)_v_1}-s8_B5NE&;s`N8x}MIGV6>C6%GN}eUSh=Db|LXnS_ zk7dTfVJGZ}f*@N&$8YxFEZYCZ#!oAo@6OoHlDOn^%WRUH*mq=X|BLI{f0@BNz*=NL z8FWfyCVK~{O6N6c!`q!xy}#|@E!acA%U(y*XriJ*b%n_nf@Z-80%BRLCn`l0aeD4? z#w^5;lZM1OOD`-xkw%MX`?GyJ&JPjY*T6&JRhgD$VVRO{E_zRJgBQFTNKE;K6&SaO zpzcFCch{}%iS@HwNQV>m06KldonPP@c5 z=5M1fCtC%<4|w5fKj;yk(~}+IMqY~BxLgSzA{<8J zK2tdIxb|WG!R9AY6srcKLiX>dd{)^*xt4vJVNkpf9k6gisCHS7 z>pMQ~zGv059sZi9z5q!!0Wxn%$+@xon;U&cW+4NdN_C*ng3-RgHwZn8k#P@K{_3OB z;C;6RtEKBIhK7ap#;WW$e2W;M4A4Ig=mmTRAf>U(B`KMaP6M%g#R|6jcPYkrLy6|R z`J!opU54yT_IALS(Y9z-RBsPL`LFC}CeNewHKU^#^d>yo19ByULL!lV2| zh2l;5esTVY>KNL~wpxZ6p`nj?K$qOLCB*y@F(BRb8Fz%2op60eNO+Xhpvg+k_`#N9$4RiA3EnxPW6 zv(lyTktUgQIXzfaM`*SFjSM9j9J83-Q%x(0L3R(8H|3tOVK zh`LXfx_FK6H+JQn`X}Map?#m_Apu$5dVrjb=KzBF#`8h>@ zi^Vw#4uG$?3;mA7%6-i=ur&how3I;UH_i7s?^K1_X)2f?w*zGDyWhb6{M=D(m6cm&Xt8+a!L+#H!MiO-_ zo{D(+ijLn4y>5oFMJ?)#dLcO+iXJK_*`IU`W?8folD#BezAyQ9bZ>N1vcCKMkfzu+ zy>V?>K=MM!RvV$59gY z;7LqPvKLiG96H>?42Zp>lN1(Dr4tDbR@TvNoO2w&H?=HwH>71U?cr~RZvemch3h0F zog-xgpt$cdb0%2s*6i)4LN+x%Z=!XAGTotM*-Q_T|55WofZs3 znXpPdQc0rYjFO-TJl_eX^3OqpR&0KoF$*RKl?1nseZF!BHvw~N1ko<>KMWkx!6aj#Y+%=sJ8|N*hAqR1w)=O6RR$1 zkx~AvpJ9V%#D1BGi=<3EJF~u><3RLx&KNbkW#h-DOQn~YxGuU~A+-PjVVJ*%?ciq6 zSa~BUl`m(gRyWED=%2A@FF{V~GmT%Ej~QeW-T!zNCB>UARGY+}FpFuIX8cY6iNN_Q zA!DzF5xF9=BEU$ax*rB4#8Ic?QsBv= z@q&IjhjFij{!7n#_>1es-_WE6D_b?3holDTU!qPNyahj^TYL)1sw?J`(I0i>S_Z0t z3V`xZ$B-f*mAgd#6f#rmY=vf?T_%5st=)IXjBJl$<(eHXPPkgK!N^g6`q9<*T&Qa0 zOIe%2++Cb;@w|6p@fFS4rD|!BeS-#G*W?deg=qbLTiJfJzv>_u3AdBENu}*6Ho5Wq~Q$3%&_ivVO+;u zlgzFPKPtB11XK86ZL3?C4`dw3y>+<|lt7bg+7nL*A%cGPH|TC!#WEAZkTw|C8*f#CSVYidL09nAcTu;h>(S!pHUL$iR6er%aF^#p;=WxrDpul&v$su zxB$57(kz69CsK8v3#No{nQ53>irAN956B57oxskHK#R}U;_$UO`U-;)e`C4d$az5~ znYmmOW&m*xbw(OSrj;yFf@~+yD-6c+s2_ArQG2E}FjhMsC8_@-D&$lMWd0%?3M#7zMS_RgIN zGu-7urThxeW#LqWB}c`u?pwp`{tp_A*Mmg1NXP zJRygvAGZcuM=NOCUgF zcXth{fO`6K;Ee!g03(2Dqx@b#lERoB7n`u#-kmAxST3A9oeh2AHo}|q zd*Qa@)Y;kUyA1oj60%PI!zlI9uM%2pPg;VJpzt;zKwXeY-F6F)X)m2^^CVT&;j3oX z#=sfb^;k4zeexu!l{CEXf|9{^xw}4ks(tB_vje{XKkh&)qqRKs)5Mjqz%SMjP@GM~ zCPf@U1fyIvr!~9TR}D7p0&^lMB{TpmObHM%7LHxQjJfE0ueG?XJU}Ind3h>rdsJz? zv!O^qYDzF6u1X3nL^jmRQS*RdBr9DXqb|ztLY*Zg_$RKdg0 zQh@<$t(BWbxwBL5oa(SN%tlt&jf}1{UNb$plcg?Wil{$m@q9)_V?=iwQRzf97C+vJ zJ&qHn(zLeDDPwI1hid&_wtNl17%CY}6`@qKnu5WN=8^xU`#4+Tk?t$R1?!3b%_*2? z`*^>CSSs>Ac{C3|lYpHdf&aGNDxN=O^3iZy@5EGwx?0w4T}D$rCPk$p$v^M3YK=@N zE<2516bbuTox0lw2ZIw9mHlW0kt35K+P+dlNBWnd6FVz%cxdN#*wJv#$w^a0_=?=a zo&`TCuLyHOXXjx|hP9@dselk{3&TW}%#fI>9jXv{-yQ}c2b9FHn>CuWqxpohZyUol zw~P5}T6`ve@7;+h=KdSt7nouOAsKD|>l6aPln|Pk-!hl%4wn_8 zJ?IOMXxxnY-+x~U>uoS6dcnhf*vD&7Pwp_z`;p>^7~^HB-c+7So~g zh{Opa^I3~;6{@Rk*OV_6h7cd?lH&-nm5rmNsHWhS3{H~+zZ(F~^Da-6`(=&cQH-3e zSSyl5FXtT)zXTsNG%)VpLhF?#7`SsHKq8~BHvhqXO}9r8FF@K(VG$KtuQJ7NeKc@{ zNBz__$zhZXiHAe~)hllL<==WO(@h^Lk(d$rMD3}f>s%Mp-fS<6wX6DxBR=R;Pgb!$ z@l@j<2V>#shw%@$*%k{yINyHTLtpZ2P$~nP~Z7>^xj7s~zmqCqXV&|DbxSK=ejF zMm>Fg^JAncK`|p|l}MCL*ss0PW1EC?(>VUEq!Ii>wK+RBh)aKtfG`8gC`bx=5t<2E zk_DB5AaZ85;zyz4fh!TBP4FrZ!|y|UK60F)Z-Gjwu;I+HbGrG#ZzjuAqEd8M3s^u( zwFf1~@`!h8Kq|RGl%N8DjxcJ$aVM||hYd!M??NZ5aQlMfE92_;xmp^=ilhEy%F$KV z*BHu-4#yMYm$o>aG=J&?cq7a|8xlCAqHFFf8~9~YNHj-Epes5;XJ?`OmJIla7A{=y zaro}w|K6H$fOtee#5^xlpK%M!iDE@Y8kUn!Q5P^HR_b~V3>Vb9ejLtw^Rd{^d>A-W zhEwxB%`M)tw+zW55M5pSIZW5F=?Z z>C`s1vg#cVZ@*Q5yzkb@^pa6CF8o(q?|{N60GSNvo<8@2{F_1?JTJ+BD^h2q?Xk{ zlon^kMUl2pkGB-XmNd@fzoyQ>?tgnk)D?b2i;_TZPR4~xjIKFeUku>NFV!NueGNLK zyR=)N0gk8WSsP8dby$n`OOy3pR=&shD3`LiESxyCz+UBALJ9mK+(?q6K(?#Q@FxtK zrhgvnSwVL4R5T_!@F`i;2m%(<`<2HYU$K8OUI*~(xOtUJU{1XN^Xk=G0%n@Rn+Vca z1+?NR=~9Pu$J6?#;a|0ti=W973~$E^N#ON`W8|4d6;gB>0BV3&+&i zeCV;$0gEV`SJdwPCmr^!J(NKdeJ1(;{>>5rrHFvGc|Ir!jf*q&?^!JQx^geHsctuX z8d3otEgi4c3FWRr*Z~~S!x%9v*0Anu@TRv3{VP3C&Xp!ewt_o{kYwY+Y_ zcAYFYeX6M$2%?R+lIv04J44c_tN5xO$5X3&e0lHSL@nIdbgxx3i$i*7O~%F}@O zB8Kkrsl$DT-%Y5g;O6~Et>MgQIVybSNh})}EF!d+PqD^em%cWEay?eobaKR8FaGyD z%CrhwvPPcRR42j$m`^vFdDamf=paswo&?NV!{?j|o7uH^Uj?zWR+#_Ej|D)&Q1Oqx z%3mUy>Ms_(`Ht3n?|A|i5485xhF1Qzgx2WXzE1cEz6hWcKo;t*e-LNPExl&axT3JM zQqKxke5}h&zAoZQY;LfGCR@Az6pEoKhT_raaZzN3Y_r00Cs)l(MmEq=oViBL z_6*X+t*@;`@WRt_bJ)Bl*Aj|F^#JYI*QNMEaAA3Ql;NaGJv6E1!)K1ub{)yu&;1Le z@i&avzeD%g;G4rCGZ*eWH9^ZEc)*TTq zB8sd7iDA+5W!KMGek4sUCeCx*Pjk>P&hdv$hZD2vTe$y$hu)o!@YFwseWkUkak(4o zJ8jPI_s_{vjzPxvgjWxXCmcUJ3Kn% z_745t#Yw#Ny#Z$-Tm~X&7&Zp05zB+6ZrSyYfEm{U**Zvb*K{@YF5v%Q6E7O4nEaIpNS9DvcS&}X1G@)6-e+9}y0f5qgrBF}Sxa)|t z?Y>nF5=~(I+u&3^du2}JowRx@-=fnWX;PBHBcmWEn4YSsgp7YQjP+gAwQWiSqcwqJ zBpPqj5|Gu2v=hgQWg^qD=3VpGQ7p}-VFbUL8njHXYM4&pM~9HzC3a0xKfQV<&Xzh| z)pM?W_@&+R9s8OhPE&wysaAtmMstbIu$(t%XSM3%l5*j8L2-T5)~QB2-U)375TNqG zo-zO9{&}CaAd5zR8S={)B<6FoX()j9%SoS}`NO7OPD83$YcJnG(D(SwF#P75lX7Z_J z=7<2_Jv7XziV%iI$KFdkLz7zgpfYSU2Qirj(3%|>ffaGg8Nk%u3^;~|=Cm}-e{n1e zcmED8hR|P+ZS2+|=Rmk4@LJxx^3ozR8Vn3f#IJC2|AsCAARY<;k_8oq+f@N<#iW1G zNXCY13qeVdCH%@YY*(m^=~xD?ng#?B-k1oIQ2K-vK(3jqtRb|Fql~MRl4ZV5w*u0M;T}C zVK8?)QC)Z=F#n>*^E35BM*?2~r5ONh)6J!0^C#tKVp6`6zyA&qc56g7Aao0t37An1 z?|%|Bp!T_l@v{(;7eX#PD~h#G!cChPBH0MaROG(6Q%#XxeLPz>G8UVWTW-=8+v9@O z^M>X@nOCG;`JrKdR6q@j<*+Kx#uo$S$;GAL0`&(zkKc7jvA~$jm7B#4A6XD)yz4Ug zp){?t@0zZU>u@M67E*5&*2%_^)dmD=kTAQv|LJ@5>CglK#A+4j%yTtgc`!RM6%JCE z39v8~i-r&A^u4?B7W@lCV&|hJrnWe?m`5=tm--~drP^Brbre)-P+9Ck?y)%^jzTa3 z^!>6|GF?tsR(Jo=?j~Q>mpC3y-nRtaPR6Dl-YCMDUKoT=s6nHRXeOsI97Q;5&G`dX z-j{HuS&}8vh$kUd)UxEm_ahEp7h5^BxX}S4n@e5`Z!BOGXD8*&B4A54yM3@u;b^Q>ZvqCGH9+=X}Kb0MwFXy&Uv!`KU%Flj1d8BK6uGK7?2T|C0~>lv`bG!V70R9&KfQIB36z+Ik$lfZjF2|Pg&to~=(@C}Ks37F zdxM(E8Re@=vF`t|k3YO3igIAua-;g!{!!O&wv-aYqJGZrV5157k6kbC3TTV%#hX}; z{X+XO#H$_kpVL~8YOn)8*Qhep5BI2HD!;*XnXk``ek9kO_z&_{ zb3H3#TPb!`-h0Xe?r9w~PD^x}{dar^Bc;*?E;$CeSije*aYuDxD=sx-T^uzW;+dnF z53I3NB$h^gaX9pI>3=lK2HQAmXbY>WjmL-Z$R^wNFT()HF-I=nKyK)M_jH>Y!~T)) z474&#Z|oG0T>AMi>sstlZCL4m##*a3N%70<_iS9tGTMK~-`sQ}4NkAu6cq~7}iVUaQEz-psE;Q1mGG6?B{p|kUlFJJ%*rS4j$X%%r z3;0)Y01$@-QVN!?rUS77MPM0mOjveIAXJMG3<3j&!Kg!VjVYC!oB-LceYX5Ra*5ZD zy~VC9(t=Bkc#M%%auK*m`?8(*xA4yG;(g!M?ISpn&vy}&`3U=33f%&ittNhuO?l}a z6|-q*+-!FEVqog|o4m>;q0IBy5`!3^*warZddXeJ6W%xw(O|A&_BzPuB5{?=N8za* z*U7o(I^G<67=osU0lF@;3_71T)g{U?Art$mu2ST`Y^#DUFc9KqyKI``iSZB8I;_AZ zEC(UZ%VQq7FbCe&hApIFZqdDsl(|V10pmZqgdrg&RJ8!Jx~pl^(J7P9AarpmeRJVW zo2|;4TUo|0*V^i;)fH!-Mw;5(x{GA%`V_O>@)yE-UT|{lL}91;Z-N}Hrv{0O0fHL> zwW&53NN~!*U;iItU)j}W*mRo&2(HE5JrLa8U5h(~;>9YsyGwC*ZE+~>?p|Dq6e$!b z-k#7t&-;7u((6bQ!n^ZV=8Zq<$4(01)#KE5 z_V0S%6j3uKFYFUczg#*DN$~~NHie2-@7#>@UHO2;ef_Nbqa4V_&}6wnAKCfP!w63w z?D`OI)QP>_4w9YoPgiQXS8oY~{UAXK*L5{1cljHC*l>}Y>Vv&18xuN{OJj*^?*+3o zIzmku7)Ffjmzb0H*t=V-c}HT&urgQL@B&7Y;&)$LoF{qjiaSl@`8Sws`Tb}&uT89_ z;^n@p=YOkecWdNrW|K2M-d$vE_=(*OgW~}~IhwGlpWE81-PDEPs#`V0R21*W`Gyzs zve4TNk!~{`)QS?dhIzi#-tsoe!X{I`Iuh>RIc1i`LqcV&Xu0a0y$Jk--Xcy9^=!T% zUB3kP6C)6Ig7D`l(w`hRu8gYJyvhYA3F|?n0Z}2fy@;rTRnU-U9z97Kc2nNX z5Sx`mViN3vOn#GMWH*PC_9k2SEbe_|o(gBy(d`L2OeDLDG8gTwNIu!8gBMYB+xUY< zQN(TG9H-n*8HOfvxPzJakXT7`!hcOm5B$(tv3yMm<4cV&w-LH1>>>R$Y}NBDeD1rm zqhXH;cQILzv#ER7aT5?723;v}4PfHjA?!W`!SNJnb*Ng(DNx#l>RL}MN$_^ko z#a^y!YZ>s*G1qUZKoO1n@Ds4n801pg_9A@-lFe6~Vx_w9A~V7%_1% z6jIzYsGr=hWbC+(jlGM5-FCfGYb_+Tc9Kz^>4fi#$o%HEmhmM#y2cwp*~me&quRG3 zFX+O8Y@A8FIJ`-b3`nsUpD#yoAzk0ra#nVg#?GdfV%-adsfuZ+I1Twf4`;*)K)%b9 z#(RUluD4OPD_G8%{6KD*FsNosu709E&*?$Hjl7Q51)X>;euW&iIeFS|*6c?ZyFV=C z@EzB6X`p63`Kb93Z+0#iKxj51BR)6Z(l715&D>mS^jn8M?s`d6Ci3Yotw%{?ep7ik zSe&dCqUbc7t7p^z0<@D0iV|FE!M=h#WqV;M`-X2C5ZEVw(Q7@XgaA>-{8rr`o<8{r zijVd7SGDM{zo9ep1Uhx)wX7&NYvZj=s;h{HhAM6+TsbixHjyivRUnw?UK>L&@v5-2 zp$j_V)lc=IsMHt-9K(7>FX7cYzl-c{T$V)dD8P`V!UkeKl2QvHZ zz&>7qA?~cJdf~OfQ3aGlq~-Pf5fFt~lPyh=4GR5(FURcS#vjT?ZUjGmF&HksD@K$B z{mijk_7xY)Im!e7gNYeWy8|sCECeZvkrXA#-8govo4h^gE(m>`GuOXel zsL9GqCW24Xu{&g^3(~N2`)W$B338R-hS(Ds_!Sc4io%*=(3Aj_Fd)XKJd||NIQ)xV zEdkK~bLnP##U-ALMb-1mQt6jQ2fuj2+Wl#aIVugh>nm;af+YdiQI8-Xs&PPDE4wzb zoZd6(eiXS&aM!HFy+HTQOt=SIa}@BKvhW`6k&7&jHQhLS*_V12c?HK?MU0ATL0*>e<^kK z^z*4bb{VwETkqSKx>jcuz<)WiZxFW(nvw6Wa(`o%`m2h~>nN~9@i&$sArcPZRp*N0 zI{_d7-LOpVK|~<2;{t*@bBjyn0xR-tGL4v1ZVC*K3GAKlT?e}Sn2twof(@};Ki+>> zL-I+cy-!bgicG)D!R522K5WEeCxlw&Gf?4j&0Qi0!LAW37^UD)?m%m~;$f~-@bDw~ zO~9AYQsP_J@}@b|+v@Yyro4XHCsXQdEucRkaHuJ6AA>>?~pHm4r^K?Ar`$Z6+T{H10%fUokBel7z6(WU2s_&PQU+*l6EaASDKWO z3M>6g=dnQ1dJ+`4OC)cP?lN9GxMI;>X$+~=`_)`%n=RU=rty6`Pr;c{VV+>DuZnwU z$OS|6fNAOjhXA=)xLa0GHrxP3>LCB%%=#=EhEFFWeYj)N_^QrNo8ZG zg=+mA#Z9o_iCCe7SJk)GuHrACn@1DIFHUB+W+i#$`64Goidn6p6;%>>vvW=Ar z4?yDzHo$L4(!^oa81wnyXcyKi)=5x9;fto-wJYazC$K2)%(-;mH!9aA9TihbvgYc%>2wp}PAIY@*NT1tynp(j{QUSLfUCT!qQO@T7P_Id9dNMFHT)a8 z(C5&FHpky4SbSfw6M(5m zl4MLZ$38i}=NXUdU*s5DzRk2Z3%4Xx2dKl&pG~M7-IDlAigE^`5}^h`wNPZS+>2VH z#OC#nSoPR5g-AbD>Dn7)`wOc!AQrhRi0GK;^Q9}AF(>&2Ecs4>-#3QS)xIFa2t8RA0G8KZg|7Sn?1s%k@7(WU3owrQKC3*TXVL~wjvjp0+Sq?K**C4fugI{zIy0t&j1l@rrgEAoj}_GgTvmu-Xi z^1YzI-4stWfNERhy&=|F-b3^i6zxNUx+M_gp949|U;`8(>aLpO?~i*a#;fQ$6J z9xE$u;L#}19afQ?)~PD*wJv9q!D5Kl0~6wwx9gZ}FhSy1>o1KSLE5r;y+()0G*rq0 z@DpezSqp`@C^SIr@jhF?-i2EY-UNW>(9SYq64pz(T{`jR89SqX)gZ)y?NI19m8E@y z=8v#W+?xk11P5BcYr5?SHRn+LisAIgzT+KEZ&TZEImyGzOGM}>AcNii>WBFPJ|Y3| zaRi^Y(opQLLp=Q}8VUv5KVzJU!{oT*E&YOM#L~z6D?Fc9fgFJ6Y#|DF^CBBQm0I($ z1%B5)kDu&qd$rsZ@}PcD%16f4qoLJUakrv=&S3KGb8AFdot@G}o)E<88>T?PVoz*i z6|7zI97BYqX;*y@oqQwa53WmGhX{#1SIyOqctf*1nu^ zoha-GIX2^G#3IMVCzAEpFxZ*QD8vH6R|Ig5!>&4$6lFdxo=Nqqc%sJ+muqh^5p_n- zc9~e;mT_Y;zN#>jg-7E@e<-na!6v`}a8!{R0H_qg8MWZU{T^N~&U8!erbmA{l#OpB zs@(HrLS-;O_@{v<2F!-BL-8ajp|&>uQi6EjnO4{bY(kH(w#>s=-j)I1Ndm3u(cEi- zpV@BwfEe8hd8hBzYF;t)O~|4@d5mTU+ISm+zKVmWTtqCbYmHRl9q*x`(;jb-7UN75 z!N0a1Uf{hNXTNB)!~Lz^n)ZXyMI~*pY>)sqks`?;c`q;Hd*fg=yNaT@(T;YKcYs|9 z{wp0~0R^&=9y*0t{8G@=?w;W6SkL*-_D-`i7>S{^lg(CU`H{Vt?9?)3qU+o79)4Zc zjw{dpD-0J~RNKkMLb6OzzyuO_7^BEo%?{Zn((cz#b&?og=TFf>sS}CJ%{@82`uB{n zF?dcfRKH5J5I*Ky%lHfQ{;5fYxwisIVXt)<_Bw`h4gO=55CG^v0?29# z!2*w)3;SzoS-OS6pSG9o5Q}OZM6Kjr?7|jTE-rd25a-{(EeQjh?x~;5z+rR z(_8KSp;>F&)@o}iM7a7gG0TFlM`L!N;%-&_ih)*oF9uj`r1UMRSSIvP3|Hes9b<7h zM*D?`(;h~y`>{H{C5wJU0X-na?wrd2vLHOaaW(?RsV%WgZoRt3l@V zxolBGg^T3Z>aDC)Vl?@9v2Pj6iG)=)Xb&@pScj(-OsbAFd3*LV*7heX)#MDB*t||3x2B>~r)@5V4Fu6tia8 z;Nkvl%?aRO>{)StCkkJH2~K_eKZpsHL5xs?GvKejUYcnG(k-t2B|w)5hYRtfIy zS@kk`1n2m$Q^dWE@Y}Dw@%;xzfQWb9{q0(p3?ylkA0$s|LJ(KYC_nm9Nje4{#r|kY zQwa#~JC>aJHO}kL#$`G7fu4xmBq{1C2^UhlVg+q9qFLUOL2I8v`0tV$`T6n&tfv5D z&pH5{)2)G+44IEG#lT~s`%$M_sgWv~0`w=C4B z03>Csd~sj-nSOAbT|s|pWW2?vV;di@na6-bghb*bbZ-#L>PH$7sfd?Q&aQ2f#=7V& z6huC#xJ+)f??L$)kOy5<^f|u9yGm1rW~+?)fCBoys75__+5fs?;<%L(@3~1nc14ws zG8r3X1pVyiANRs-77`h&i>(9n7pDV^x&p)z4eLa8IKAYI>gsPRR&F-#pQ=*1E!uza zWPZl^X}1j{$FoZjl@*gE{x zm`7OV`4VVDoES=n!(TwkJQw}VYIt*k(_yMC zvhwJtWC%5g*n#iTiCZRwhfN=LX|D~48;~?3D7AF|s9MG=jx4{-R>4BK=LltxEY}!Q z2a%)L)1o&i$sy$%^p2{C-k*P>e%iWH!Cv7ff$~GgW3!687Ub1KFfRcyb|GoEnp!CS zB$rPu;RglyDs-*HuQ#&4zGyx>qP~cwRg%EM#Yiiur-+8*yf4vydqE~C+l6l!J3z=9 z8Q#0xH^aIZB!CkToWQ;8S@W^xBV~h2Zkza(l$~JJ4-aKxi~wWLz-g~iUN*_H_2S~p z$em+{6^yJ$8j}zK(l-A31zvJw%hdZ%nhR6zao$3osGQE2XbR7661AMriWAs4KMMAr zrpNo+y1&^HG?XRxIs(xrK2kWr95o-?KLgO3zsLKk#Yo$`M~S`=m64;2`mSCaei*bX zJc<0iAc(!=%^hA0SLUia(-T$u)9-kc+^|GxG4_41tS|FVz!_Vu=_%W0(#k7>Lyvho z0q#Q{q(n1LfujMO+WqR`)Vuay}jMV%3+BoK= z10r@%LfHIuf48!7WSw!gF|DoTAaQQ}+J229<+}QokIogmxRuT6*BXEvXlhm(O}?ev zTY@e>%14l}N$K)-_+9I&MJ6%C$sbi|C39U|a_cqBelr3w?Z!-$A{^~_{Sl-HnM2}r zHUmd21TGr=b7CL`Ho_(|B2_9V>OK%|Qx*leo2W2&;59hOM0I*6W_tn1eH71V6Rx!V z%71dbx+C(PR2y1RLFU=NFBM zYgwf(**?hPW5ur963k)y5G`!KL_b2^PS#gXx#1koA2z5^f5(cln`zQ~*mgR0BeA1Lp_T+>732_C5!Us! z@>X2{$2px|I}qW9V7nCA;KN!0@OLt)Tj!Ek&>K@FN#33U`+ z6*~+4G6m8EVb+_y6a+lh-V9)(5$eCmI19cS8(^JhP6MOU=GCYih2D%c%kxPM5+D|Y ze7nBV#U-bsm;(mD1F-;@|I#%In>(iP?;OiE$Pey=zP=7=7$+o9(U*wgNeQraiSFg! zzeN#r;NR#~pKAU7q&9bFWT1J#2Fy z;FOm%N$=T1Z+bg}qG2KeVn`|El<_t2<)7-eRM)@rj+*x~3crL_a_MK;lVTO}Oy*-T zqKCLtyQsLRD3oa>5A{p_NEV3uZL5(=Ae%cX&XvbHZX2Gp)0ZHiBGF3iXS*6p+uy}$ zm}NO_5^b9dcKgw1ud9UXdqLKdb34$C`Lb(Q*XfQ2KRodA%OZm>&PPOtQZIPZ747S< z@vC{yFpOjiuw)OoC{J3JVQ7O3~**!Pyg*Gl7(`P{KA1#+u`Kd|Ho04Ru- zA^s)OR#m!17K8f3^CX#078j)T5BJS}$Fw-)r8IDLgkN?u3iXrSg9nWU7vr~JH+*>M zme^6wJzVAmc91-D0u(6;d~q4_PZZq0SG#LMx>%III;M6wQu5nFOX~v#dej`uG|!bz zlE1>$J%dv?cl*>A=(9RuHFIC_=eX@$FpO$uH{9Wn19BasJn3I?i&0jSPSbr~ojbGA+Qd3NQtcZ9CB__(>9F$HynjJ(15co6He} z)h9s}QBi@*AuJBdUkL!F^*r!AIrw5NSjhEe&0WFkVPQ5}s7}5~Gqv9(!PUu|gM|dO zp$L0TpOTMtL9c2yR~@5mS;dE@u9-&kRlDZrZSIL6uEdC8I~xx4d1$l+uLd?lvIaA; z!k3Ef9+f0P@|zznX6>9MdtoO^Y_S@+D7#RC9eVlQw*8Jf>9|?(eGx)Dsh1Bcmi8i| zbFV!i>I<_cnyhY9GNb7Ei+G(Ml&ZcyMkbsKipy+;n;V!EylnjaQ=QOSc-Yp_I&ZrKaVjPq<_xrf)Z zq9Cdmu4qgG%R9A>B)>mVEto3lM;9|D3%&?g%t5Hv14YfQ%%-s9`#0fK(y88w+|$Sy zn-Kc2;VK83O1;9RV74Yy3f!D~#s{?9;dOYVw;47uPr|?4HYFUre;k3hDQe}6ymt6> z9WD^A2(m5}f@^CiKB}iOo}M3}u$YvH@6Nkfcvm;}bN?wH-TcSj*TWHlED1n&n`%rz zlKzNoQ_i^qjb(Kw{D|QtAaZq?`4oBQBZbT7t8ujwNq}~%k2D!(;R}(dp#DAE^dukd zXVnfx2Y116YJ@r5#~*zpP#Bvm5NZf_?E{=w&U0j=9f8NPprQ>@ry#&&o~H&9>+~W( z*(epw_3HTbUhY_#A)Xc8C6kn~eUM!SX5vu1>82l3c4%@udIkknEi5aN`2#!7=Qm!# zAxGub7CX>G2t~C6kPP?R5jh6)}XA0B^8Spg=J*Ai62gkY7e|C>D<26HTk$cBn7(0P+-qcWpZ z0~foK0FFJ4uq4{iNB8(5_4lm3#3=Iu>#4^VgS;^;JLBz`%aiI2wb zCiN$BXkYf(8J@kLXhLka>oU-_Z}vK+R7n1g7wi;E^8cS>{XnKz|9?65^*P7PiSxuo^3e`rptWY9EmpLLx8&K6S&;Y-?KP|rU7bNt$$q5rMGu4z-Oyhh z;T+1m32O@4ya{>XAxEr)1s@UwJ0W8{@Ynvs^fv!$gL2_D2LN5n_mht>WreqRdm=N% zq=iACw#@TNXYXoy%3i-^z=C|m4gylCO?x;uSb#x$-eNU0zA-S!Sorf@ok} zO36o}(@y_GEJk2$xC~g5HT2s#ihI+$bJg)&Ug(&2Pq%7H`m)37)dJPYRnvfzK~aks z8>8c!6>-qdOULb{s@t+fvN)_(1{Ti!>j2<}V}8_sHYCWv4ivy3o-{S3k`4fFU_)89 z0%t{Z;8XK2{BBvsX^vqPplSLmN=kS}OaU0SF93Kw#Zydm@}-JjYME=m?k-G=iF*JQ zGi>o|Djpg>A7H4wWewm{hNT-X*afT|HThLztoIsTS=uIBO#z2q^nJXlCUqg@czi-} z#6;2v^%wf?FE?rQdFGV(M65M(s?xBglo375Fs%Z|Bn+K6LA**j3OD~h&b{PB#tXnu?XJa9hjbbbJz+0nK3};-u zH-sZ$#KH~vj*cZiYzMIyQ3b~vB_YaN-ZYJ~C6v66g!?Swa=P@8FIBb&d?${+PxJN_ z{wSuU%-ZY%UjzbMiZXhQ8R*|c_Xujl0K8k(goXb)P+Ad#u7~S!*cvYnWesoxXoFhf zYIi9P6fpx)IJutz5LrMJ!`f%IltY0d{ZS}7op>!beiZNHnk9$3o4&)%;sKrFC{W65{BQa zVG$5xb~O*lm9O}Bg*w{ESNg0MRO5-PI0)a%CW3qnYS$gq#bh+#nfW9(QZQIiz+FrG za?RSd+=NlQ!1iR0Jl2NvjeYhM3%7m&J7GxBBN<~hRq1^yM>Jy7!T6bNI<9fg?_;NB zBBD`WquKzP@^`lBh2rLPXTiDm-)x73B8?mYlblSganw@F>itujBUj-Y=d^I{5E~ksdo8J+V@%X6{YYMDlBw>lUp34e#eBuGxz7g_cyZf41JS zo91$ItByozF;ZZoDs(!_@NkFzALR%9oIr~orKzDxynrCRtW*>ndAY~$V;I%@eTA(B zs|ZM|vjBY_Tyt>*K^Pn&2zaBoLm1XjR=0z0tI?QrfoWr}w6OSI+;#9%m05QS@IzsN zE8La2qPGb0Q|LUKfnmRUKsGjeZJZ=fdzTeBUP!A}k9vtECvN_lN(f0tWK0F;JZDIi zW||SPTm_5@3B*pwdxKusUh%o=#n=Kl#3f28E!Y53*8+YEGk?2{#S5f;-EUL1iZ-QF z)T#UsEg}y~qK%A+-`dX33Y3tewog@^qb)m6aWi#1`JxdizvqV7hJs=j4<`ky-;w}MJKDW9 zkOGclK6m3)a_oFOY?e}bc(Q46)RnutZ5rdvLMKE+TUj8w7$$z+LJGsCDNHUgPbT2G zWhdDo7HpcDZiB0s+A&u}4y71!%Z+K@^M_97Pd6dZ=4X7Rsi80nPW>r$HUtPj6MI)?)Bu--q0?-u6L{}NRbfCJ z$Sv_)J*;5W1I0yAQiv%8P*Aof+Roc3wf*@F{Hrf60M_{pL&OMZVO1maBhk7E;0h@j zzE+-Pa;L{)MDvKSp&s8&k!6ecu_Zv?`UTkaVnX^A32ha|3~a-$qm?<(;bt!9H3!D= z&wZn$QZIp9b0=UtEmA&AxP*+(ZHj8_|L_X8FL=LG+>_L?!jCI7H$M*EdurNqyf zA8+Z;`Da0L9;-C;*vONYF{>f{In&6?DaaA_t^#_O%apSj!uL!k0?$YFJTCOKtSksF zSC=za$cLER+J<9x;nq|O;=cN1)nE3g#u`I_P}f5%RkJgZjC{%fQZZ^Gsni;<~U#h=>HE>vseJ z*?5%OmWRKGY9am4(?UQv4uAy!)%}b5{lM2^MIJglQftw(gk81j3j_U#3Z=0%r!B?{ zoLNzlpeSzqy+anr$GjIEL2Z%eL9l{>d5zD?&8l3|QD+)dRxW9)yJcHF_afVF5wyJT zlCsw4)_@$7dk?PccVEow|)Q zzKjbr&wpQ?P=Q9DHhPv+Q7Jiv@_PGGgRhIhjr?RT1HICVEH$Jca1M1+i4CSgjsbH5 z3tk$T!me6j3NnW>WV93R%Hxlh|2Se#DS_1#S7FD?M+$}PT&<^7R($!^+xatF65HN@ zr{#&7w{=BiUn~N{G*4%FQQ?qSJP-j>y!G2cx>(mdt-of2*?KVLyHCm$r{9Mg4H3;~ zxKEcKu=;=^>ECb}j`|KuO>AJ6tGmie)Vx^@F*EYBLrCFZsAC@_J%DMY3(VP%Mls>m zz&2!(W{g5`7T2I~#sG{xNhG91DMz@95250P#|b6EGGS6*VvNAU#_EM(%|X*O7}Sa; zx{P?B@EZb{#K&D8G+r|HG=Uq=l_FM?Fr{w&{h$8PZen3648g6(|E0C${Fl~p@l0zm zFRh2sS_=EIodayWF41XOVYC)HPLH4JIg_$s0}~on8(GEy<#c?3M5Nu69H!GNYX2U^ zSO5eGU_HZ2Zbr8XuvZKHv(hQc-0BWLKfN2(4V?#m^sZ+NmcU>GumRWsRSANMOU%7@ zzIe)2q~*D&`(KGa^d0+P?7tu@ZL!csz$pAyKe*SU$>5x?&j~~*KcNCEC2@{Rw#_3L zQd8mU3)EU)=vtq!jqHY7C6#a&bDD)oTb*`KM30Xh|HM!lcJYr;ciEn?zW}NM2ru{3nW4_ba-T7MIf`JQt#P!^&V1DgHueZ?3Udk?ML~i zzQGu+Nm3z2HZ_pf>OhDJ4Nsmss z3@~Y*@~;R}JWuf{tD00$l`9)5-a^}{244D#-uhT&zfLc&+{0SX-Q(_6Ubkk?vp$O) z0FAnac;Us&g(k6->~{?%1yEWMQ~0dT94D{#)Q7Js|I7QLcnt?e1g|W32)>HLT}R@; zgw62ZhEriP{7KfELkXDV1d7CHWYstWv;j$-lyj>-c|R*wd>G4EEr7O6yeupAbC1A;-l%nC|o3V)g=do ziaYF%tI_;-x+chldOCf19eOG}u)*DuQ3w_N7IY+IrhwgkrIFtNEn=6E1RVdaFzS_9 z%pF%&7Oq(oD2B}N4y;V_h}3e{fOFF~Psa{O(x`7`o=IGZ|Bd$li^N4aaMxv4)Nu#K z$;qwVqj~Ws>?WL&npL!SVSAz%CEmb}MsG_T4QDQJ(di$|{T;9XYq3%lVJ#L6=B~u< ziQHcbcfbr8P3-UOK;^8&Uh&TrD-I0pEp`@%&5z=M$Q14YqG+xRE@HP0f^lLu*tzFr z(QGGsZ0KZI;HI3VMBBL!9O>vl8+r}4&)U&fC=I#w!s}SwurW~{xRVw5Sm6-c@g4lL zX7}hKcn6%Fcn#L^C=+E|HBZbS6x_5Id;RL^Ovtmzjcj9p>_9}fL5r6Dg-C&qVqE_j~JPOm`}d!n@cX9Q}qtC+F;TMAZCS0_XhRhKp8l z^orf^3f=P9FO-7GR#ShiFsUJrhZk~Gjg{&e7(CrkP{-DL6cBEWMgU8gEa&War-y%u zR$te7qhle#?dXj}`J?8++jtf~YVTOHd{so*M#chg5c(bEM~n73ns377Jj5l@)D>eU zSaCPE+oSq$XkBIfJ@f{~8R2G6ga17!r0_4X0Q3~burBLb!aS3RBsMMvhu!28_IrVw zmwzUt?hU61tgzXs%a{e8Ig}az)%j<;I-_w~qn%}aGHgf7K^ab1{gFjBV~kZG98w)S z)DzitoCt2(-jpF8JX)p3ztH(RwQrP2fi>o0H0?o68$u!%<<=1YMd8g^H~-JP&nR}A z-NcO#j)xph2_+&jSj}(+su-Z(rGMOc_ap5ZcJtD+wo@UEdq9Z7*h8qAz?w*BPHM@Y z!k#Tbq`RAqXox7G{bdyN{0l%ic%iSF++HevLyPWV zP^qupf|VMH^QdKWBFv_cfGY2#@HKG6^K`R`Utf;B3;tk^>~#sofr_oB{7nDge5(f1 zaOl`Ip)B1)4SY*xM(NT#9isFvCiVf1Fe!CiSl-!R2Sv!s&Q<4xa&s((@z^xncTF==Cr0@Z$2COk=?WXlxN2mlRxEKVfbiss67*UEF z!xg}&Xpyc4(^gT5ALb3CO`Wx(q3@w#TBOy4+Kuc={0C5|0O?Qzy_ODhb{EZsGOp%c zuu+VueJiZ->bcf!KDIv~Tef~ZZdwj7XAd0i$+hAj_ei7NmfnRrq$y<7wOf}qzz2hr z+mOBqbQVuB`_2BkMr`@%DWrj_zSjVlqub3~Sb*;OUMn!|Hj`6gg*DVBMhEi5;}%tZ zH_DCld2lt=M4rLJ{D0C8@Sn6B`I~kQvNi(TqyFwf`G4_$Pf#&B0BooQW2bQ!!ll0< z6+vxy|L(w|a z??Zqa!-IwxVt}OFo6KG0<{`m1`A2cSXGE&MQm7#2NT`UhyGI(TKu4@pdQa%qrgwu{+k;I6`02i=Y;a-;;5mHh5k6z7>@@JV^GazEGep>gtZ1#y=a-qGK2?ru5JoQ)LE_T|J} z|6Z8jMTv4wOJnlB6SV54573Km1wn+fgiK?-cho>p)^}{&XT9rB7{HjsP$JQbD9i!D zFYqJDB!8@n_vKaOz3}s8Oo2!KdRgbi@{=#+)M1;85v6ZrpM`>YZCm?~d6+*AkU$tQ z&RcLVIJNia*Lu$|Q5V^z7#xF!kn9LdrayUnpog%wIxFio{Le3VmX3FwsgGxML2h&5!Q~Kd(KqDVvd8YmE_Hd?bbw$K45iA%)XPf(Ns(Jn_WhkD3%%BI*Vw703oB zXD->NosyEFSRR$Z@gW}TzhIruB-?pYUS8?2;g9_vA(b5904l&bRsQ+i2?)iuW-%~s zr88-lMcc5u-I7PpL|U)_#HTjn zV(fDvS0^?;_4kheB{jp<(aBE@6V^KOUZrv{TXD(f-Rbc2w0|sl^gXa*b7wV0FJl%b zRoeqP!Lt`$^6gg**4}N3K-6zrl_LUKW`ZIKLeYV+s4oBjZBJHNaqyC=se?-_a*FDs z!^7L}d;$47X10QTT4AdQYb}%KB$eU6d$d^Yam3((aMmFqhnL(L6I)C1N#ycc7=b|n zrKcx{ni30sEa71kN@L0i75!NyTShTm^^RS-=uhKVbhc?PCSc1}tf8!j^Oc3!U_WoU z8V29LtJe7oH;jTjZzn2PleWv>2Z(M3Ok#xxEL$xwu`8J&q*N2NzqlMiM@x@^#*f6& z1lCBD8+SNn($rI(rq&CrTv z8teIrWTsVCQn^-Ez5*c=5|;Aud6nMcYC1FEWm`p`+Th=kb_CTByNs5zNXQT_$|I}N z4lcY$#3kvdxXMVqFvhO>Xb?A2-+4dl+?<*wl<}0Yuc0N_6=h_HTT=*)u;FlEv;YQj zK^q9HAxqO_6Z&X$$Rn4(8wWP#=-O71kRy9PB>Gv&1-o%n`rJxMD{sMt1qL|??nS2# z9yxTuC0^S3`bmM9H11lVUg9sr*!^6@2M2T}8CE<^CoPJXRF^N%&rGw3{5A^S>8y61 zwYTPAzL9QeY$<<==~{O8kJLFx>qx}jfJOMAG3Nh7cqTQCWMbwG&*ZyUj1Z2u^8pd{ z*Hy^)M=_W`o4MOSxg=0f>c4q~96<&LV4eR8MjTkjtR2y`dN^=#Gg@EZ(K|51po|0_ zJiz%--9uF&KdW{`J{ql@hz1anTxN#dTo7Rqqpeq6S}!O+B2MK19nDFupyitl7L}C zKduHLo&{a3o>Eh=TI49Iy@t^2+tD%@@I6sth)RJ%_zu}5BVJ9>^;N!1GM8;ToraCL z|1F&w88Y;!rjgiOlqLG!3vS#nXO@whe$sv;QGNDE%_L)tA8SZsJ16qV4)`PDWa7(^ zz^qZ9$Pzab-+}X1PIG}C4?%ZLYoePgre%Tyz6qU}7FoLL5)Yvq%@=`#8JjgNk&4ab z!~}*(?f#|S5sKcj%Wq#FLsV$YHG+?(?6=*PV#xs0y{Y@({@}A+zpH4+LMwxCV9@w$ zY=Afz<<-T__}~1_EQ)pg)sE@v?7xTJ(Nfv z_#?^O8w1OF@N_ZEwB8w0&9Fplr#*b(PGO}`qE^d!OIZ$;K_Vs>o~b-wnr8(T&G)tF z*Nx=lY51!XESjru+p~cM&+B-CwDcuDZXuJDArE2+@q!)T;UXRhv4csHHx}NE*_0_* zsp~w>;oA*OHW#NUB%>2%5fAzjx1E&ladQH~KQP;`k1{Wc{9}(qHIj>oz`MP$M?a{iRw|`1wQ=26SoXKl(AEx6vyD@S};V|MX+Pzno8{+-$!> z%>cBnGMKfZj{kJ(@iy!wxROe)*}Cct`K55}dkDs0|^*t6Nz zzB5vffA_iaT{(?ul*MlQtL<+8;y|F<^YjC_u(ZSv>G|F$%WT-1Mk1a8A2dc|>ATW^VCWiw40e~H`zV=OiODbepcqE1bW zN_|@mooV**gOt|^qhmBAn;&v#ihVEYxwhZmElfNac$MgpF`Jf~N@y)IcvrHwclRtj zl~KS+NFoAMZ|s$FeQi#sUJ9|R9nZNJ`-ue%5XE{Rnbq90FGhRhS<~kc7Pr9@eaLul zR}1PNX`s(eikDMs2=2KVus{k*Y+oiYgqlI+Y9(0&VO6UjkA*AbLqJddi*}^GFjdF% z^}yi3K*S@yrX|lHYK;`?X)sumaaj(a;c;uP>bn+17KlX2+au206@|16?vC1Rnpsa7Q70VT>bO0C%!g#x?g=FMU=q?I z&!EW)om?t3a#LX)l(qk(9c03a9x}jMON8>-$;R@lyu2gsAsGM7E8skIAKNd|0y4}m~KNf~*M z^i`2hzXC%t2nV9O940>F4HwGhb+P^1bSitljNosyxnfEW&N|edRxsg`E#qhq*b>|%CW{w+undVZj{s^bIcpK znWvv@0;L%;YPoj4T%iHXh`EY%3srgcS9XersRY7viDEpKl=6qx>hhxO#fQ3FNQ8R{ zl%oN8&gc9w;yM~^>AHmL)v+vVs$ z$SrYp>lNEwy+=MHsgvf_-k<`Z)3tH&u@*CIWU@x_$xxoa+7##8xp}?;KTktQ$XQT2R;WY2EskcY~1WUGsZIGyZ&SA<=x6P3G$;oA$ z1O+)nGC-d+F2R}pFZ40j1plDA|5L=%_Dg@ zt9g)z=qB((Tp$KuctliJtN@Pp91(-FY71N|#j^N9q;lpbX2`s|fdzBMkEBDW^_Fsl z+$r#wbTYI|dJIKRKjIITJfe+EdyD5+Zw@x@Kk30+bmW8H2EE1Bfn)K(uTqLElkmu> zkjqJJD1rP=2^N8Qybsvom%eR7{AMeClvLpMx>3~Sk6>wyqVr04W430+l0c9q>hTon zr;}e2-{bUO{y|s{@*ny?)cr+N9NhPX4OStAI~0Yx26uONcXxLP65QS02@(iSaEBnl zJ!k^K0|a+Sx{~+%{RiD^^{fZI7%^i}b@sXUoPGDh&mR74L36*eEuGT%OL1IVqZjzs z8#7E?2fMc&8de*f5g#jDN-(3p{K*YIUB(dA6Ef9MYbIY7@@l|Z@-RC3L2VJnzZldz z#fVRnh^-HoGu)LsAL2Fn-wdDymKzfw^Ua7F)Abf`;wxb$zho!(C=e2gkPmjV&LLe^ z48D5DLV*kb#HnFwKn>rTfEOX`H^&saQNufS56UbwJw7s{=!f=fFFA%%8!v1SQP_k7 zJHGhEht34d1D&3;4^?rB>{l*y1Px<13V6uKaV{Ue8A@NVjzPq_j|#)Ev1?gCsT;={ z87bP|*?mfHaV?g0Gb)8t7xNYf>n7kNijX+S3-UPT*qrS#V3izETG)_lYa;OL7?gf2 zM5wPI;{?=w|14s+_yyy~-)QGZ>`bL$HwX~trl#=bPPpl3_YHpQ8MsmzKU2etxo%xQ znRmjM;%Ns;>aL4gd71T67Xn}|0o|k`tpq`0Y4~H3YvUOzirDv zPm%E02~YPC8twOlOLcRy%e6=#IJ>a@mds?bAnzjmp6{rX)E5{|<0fu&QL-ot zOWjAVNjJqAlKX6;VDEd*;WOwFoQbdAsWX$ z#TCTer+Ce3)w_b2@anUVV7nMT)z3hw)0JIo8n9xRf7&C#d_m1sdOYBXL#6VmTvT#0 z{jr1e#f316LM|q;Ig}CjlK)a0y8yS)CX^{b@t1!qGI0g*8bf@)R&=>(&Wg+!A-A_- zyHu1hs^p{uwd4E+;3jgvr(*DiX_?pIG;WHoqxEMEtWNgo`e9b&QO5gh_5s(?x@1;R zgnQ%^T)_RMlQ28JD`+nEYZ?+_8F!kHnme0*0XL>vBOwF>+v985r=%mT`Onu!B=Km6 zm^R^fSql!-#odG+jZlW=DA0Z?XL~M3A2j?FA9oCkQlSTA+Sf1>rgQ_hR8^ND>|#ds zFr{>w;KK179P-Q1Ctyus)bl;0MLY(iMKfTAvF`!9Bg1n^m#gwb`c+<4L`x%sj_+9Z z`d_;ig11ZvzdB0l6D%DfidFz`na5i#BPmWi!>#kf^7F+C+jug>OX zGGVo3a8JIfH_kO8<(8Ghr!E3;bOwDvZ2#K`!NHzk0DQg~(fmWg55sf(;X5@W-|CKV z#=z;cPf%!*Fx-vYtMmU=&!}rmr~w^ms{v4}?B^Qfza-ak7ggG;c_>(pdN+@{sk|3I zz{YtSK)6C$<(>#{Y2E=UoI$vDI0#xa9NF*r)+AMhr`@j;Dn`DQl+Ou2-%e@?crCeS zkQnzhWf}~Twrl-T#)dRF2-xfBDp*qA3QpM9>kZVp#~Wdoeeb5?j`G$Xn=BbOA3{^b zhdj#cGH704m=mc^>1|)&recn*WZQ;Kyw=t_7%e(dQ^>ENn2&alOu$*}@Umwdr*fN~ z{5}0=-()+}uXZ+-W~NNF(X5}*f5BolN8?2PH8?+*sRP7iuX=2=RBYutV;rUa?Ba+%>=^G5s3TkyN$VNE|Y@T@tNB`~#{Mbwukk ztz|~jSTM0g6E6`Ll72F)6K}AvPK8oH6|b9vySZ~l?bT{#2zT|tKpv<(hOxDvU$uyJ zl*97Eq+7D)TxNRn?w8Qd>H!qs)r@A2N{O)mVbtW?r7&uq5WdS!00WfaPSTTpVCX{L zZARBDsV*dBtA9e{deN1EC&@I}R`K?>-MY!*GZ7t+S=hrYIBzG$D!Jvl>ha*8LSLi`1kS=P7VFlnMAYm#h<1f z^2G1o255QZ48Ti5y;stJdJNE@fIa+h7fx2=Fj->XTwo*ovg?Hc_-4I))BnI3hfB-ar>{XzPQ(SAY98k zRebrwVmJ;Kk*22W!CkTWPBELwN>^72Fcm~XNB9jQy2V(P9!E5LTnhQaKpFW{d!%uk zlR=q-J5dpr?(uEVBMcgIM_-Dxr)LqWSbE_%<5f6krK31b|KGCKQ*o*GmuuN9@js ztP7`i#p)}|WmgEt!Y>LgMVwcN$HSXs`W;mPju_P2NJ7M;erP||utv2_5ok>CvjX}5 zaBZZ~Z*(dB#R#7EYH@9aB>?##{EB6f31AS*?%lGkf#z-0xWO_Fx&$U$NBg(V&}@f2 z@3MFNM`jqPOqL5ZY>MxxxyYqnGOTAqCj_icM<*Q1oBNnt{Yb|GCIf^7Ga-JJ5X{{h zaLjwZsrV4Cb9S^vrqpImm!5X6IL}kGywh6l@kfh9drX>-)+@y5gg0q?RJGhOALaC; zOebbFO_$Gbd^7YtNe|{rPA)|(krM0qR8tucD*83_ZI5*V5poZdbqYDUOc@Z0pYKlJ z>`)iEVXtT7!vIpl7f9Y!_g%Le!4XA&nn`!C)im}j6WaRfhK|X`w60k?#bO$y>-s3n zLyv@v`|dqZmxSWBR_*tivo=b`v6FpW4P%vIYu$}+)t|MmWh69TH=AX8-!t>Oo>1!i zH9&CH_(xX4Y%7>ahmDJP5s@Y)QFuCc)3@ywQ;2oM>nz4k*8GbFr$x(`0{|piToJNv|pt<-{9_{u6AT`Ym zm;xSH9|joAqLmct5v&e+@sG=*!_E1l5RJ2}BAv3;Ae?M%H2-2pt+gIufyR|jpsng3 zw^_HBEfH1oY?uA5e~$<&)uz*Swm=nf^BJxXQO_^f6DBEWmrH4c1c(der2uh$T>Rqy zPQ2a#ZbZP{91oe8Jajnn#sbm4HSiufiIS=gnPbkwwQed;)5pX4W%SoB!2}>#%e|yR z9T|j;p=L|@>_WemdZnsbfE%Kdo%Q%Lb-~z7t5=UX7)RsJF2b=cQUW7{O-+%rc-R@< z)RX=z1KFPBg4##CTC-&18t_xcG9#ws;8GabyhAm7+Fg()4=zI6>Z)K+U2Dmhs$Rga z*PWyQnD+^wPCd`bk=wMr&RySV$<6qr>wD@gcu58k)xwgrcS8AX8izB8SqlK#X3Z{~ z$rokI6R)7MH7QP>Iu@}3>c+2x7|?)d24Qg#j{Ic=2$wlVCGF6KpF_UB-FNmqN;7NC z+JV=Bp;qnx;G)W)NH8GEIf{zhnF~Rk+SB@#p0el_DJI|Dryq=bq(B9U;&10K4FkY{ z(SiWM06ze5zPymSRA>PkSJ^;)U9;c^nAcoJlU9p3Jd~;dJHAmwKPy@*2>0!CDS>Uk;MlWMOP$=QGCSpboz!k68_F7#^d`s6aR_Cxns ztAv8Z_qEVz@o5s7{m(Ub zyjN82$vm07jv+?5!XlkxDLDY`fQ?RIpBojCoSK;4ssdkj(}+P))1v;9=qC+>1N*=a zER7=eme=3D@%~nN9^WFJZ@4J&dbWUlgHw^%a_Mj!PMX&wP&gebKv;XnA3P_H;?=r7 zA(oBlHPfYFe@&i=l?N*9=4JS_xNIG|_s0vJV`bv;gBPEbG*k&fAlx>B&oBvGq08ul zRM8B(Fhee=xi_-v{-KJt2qJycV2p(1setXvTsKFdzHFl5cL$nSrGj+6a*6K_J26Hs z@afP)qOj@33}2hna~$r-x#7*HpAa__8r5b8fFNHjxK9au%LW!CY?dzTFKK9-C{X}G zTDK;6kjCR7B^OW5)9-H}r%L%J^oO(W1EnmdJ%!BnoENcd?c`7)n`Y~~g6%6;uKmN|c?&oHeyZ zWX`%30gR8;m>865^ZxneWQl+M(8QH+?TxT$@9EJ;anYq0CGR#V3c>zQnGvpS-X)#j zG2*}YzmDDi5B#4m6#wV7tltt2pO0jOh)hN`MD@YYsDAe+s~-Jlu_;8p-s9GxE9VI6 z?9l)A{xh(*&{60&LvnHyYlI{V%$db;l|?{`u6T6{Wp8zvTH5pnHu4Z)G*JEDeKgK! zl8!}-R~uylTxt{_m|%bSSaX|H-f7AFlZwSwQR4FtL2ieUN_y-*(3SzIscfK^VE*aa z`nJlUsPObi0-9W}B`{h*n+e zTBW@!$;jNW5;kb?AldXjE2LL?z(Ax-U;MPFxW5;vm!|E9q|(vEDI>pQk??HB7?wH~b$mcP zyRyL$Q4k>w5%Gb#B$8Umb{a=_!+?{#7wBL+qcR}2i8DK!*A36f%m@3zj4~XJC?(@N zGfW?F`v-!A10o+8cIESo`scxYA@pW=V5U8RR8SN0B{c;~6;r)e$}qKB`sa(RU$R z$~>lmzipLrgEcxEeLjyfd-4jA#NBG4EFMEwi0um|g3OWCR^%?htKU!f%$Lgq=L%>S z)d>05MFW2O_Pj`O$}HL&m;=OZ*H$NHRI8jAFahEhK!>wAey8eBvWVL{*aytO6{Vkc zlM=hqQSQWz*y9AispoPg-2Ww9Xu@!#0c>*raTeYLq39rz#pkWGL|EzYGZU{mBskGG zCH;@HAPu!1N(0cZAm3YYSWIvy7MM=6RK+%?%uwhhYMMIaK_G~ee9q7eRYI1cZ+Ghr zZqt0LiaZ*m8|i0nI!>{JBhbt9TLr>p&pHe;DpJzMF-8JhbCBVQ$Rk(UEf%#pIdU1B zLZWOK7m5^rnJzksY{q$MZzIBrRAc;06*oiAd1;e9WEZcXC^#N3N*_EK28%9S+$HQv zqW`_P>ciOz8`@);Cv#z!^dl;Gz3YbFUL>+_(YgXbrQ%3&ix?Taso~>aA;%l)taix2 z)%%kci%u9@${h}%((VF-BB=M5vB2`gYIASGtg@<%QPr)2kN11M=+uqUHa4u(2Xb#U`%}up7X8&-UR{=?Twsxj8aAEx$IN zbhCQp72gkQxJ-DEFhB(Q6CE)&ggLPzjzIG6^nr&sW^B{p0?)s5S#IIm+g8rqH(aAS zvT1xgGBzjg;xdnU3b>7X@=QTB4KXMLtT-4${qzDq-bY|ZM2r`UZKqrNWjs(QZ2rJ~ z8&hzLNnQ)eiyJwEPp4AwtGSXeNplvCB1a7P((T24(}ADnt7S>Vtu0!8`c=NrfzF#Q z>ru_}qLi@e3;NBz)<7^}Sqt{jli@boHlMP#OF|iwdYP05KXqBa_*EM9B_;NjjAc$O zd3?118sX&$9*KRysz#=`L|Ce&=2PTM6VQK~0g>Dny{K{^OIWw_w}H-ggMkYA>OW&_ zdZx&@&?5j`DXEF4XV^1kQKgSr>`cDjTwVbJJmH%3o@ z3&0J4&Dm^TaOlfM+TCkLJgJ#hk6yM~rxWmvKA&-VV8N}~UOstRm^d-qJ!iqUf94=> z#GM!ofx9gSV~b-xR(@I-Vr!ovV-H4PFVxy~Gg*g<2N8P-e{(fjK8n4@T?Kz^${@O-GLIw-^MKGyz zUu8B!^zBG371#&J!dGOGRv5&KSK$PeAgy&oO;4UIkV z3RhzK5y;Fg`Zbm3G5QaQC}?-r{k%a`WJ9$tWLTH^a9rTm^Nm*}eH2wApwAQ3`7-Om z`k0b!&>T1}S-JX2<0hlAAorS%)w@Sk-P6BMU4_xPL_JeuDkm=$2nP^Hgp#c2-)sQn zkKscw#ZS*lB$ayKbHKA=+w`jC!7^dLJ5+5}^}MnqNbqTvfBU$yCg-9ru0p+co*kg!b&>s02aqbU(W5 z-s_+@;L-TatWI2WKOQh3uf0X59#^%e|RK1ai7ndhLr&nz+Mt>^Qkto3-%^Wg> zF&=0KaIX)5CNqxe?7z_;^1X$NMoUsM|IrA~F^JhXK@Bk&l%XWSGT`0S%ci<(ALL3? zzc^3KuU$lwLo{-BOmK?k)~cUcNQlqE8CTz+=kDIs*yAO{5$8kkM`=I!^REVA|AuZI zWXV#BAsqnU+RTH%4y<9xpEl7Gnto4mC0-SR2P~=>m7}t`DF14VFrb$>dX#J2FkwW` zFw$8PNEdm-4dF)7C9J;ypc{pYKX%y16HHG%cZQ)Va!A^tz3A2 z?Mu<|EK}+W;)}OMd{@D=%6^1hW>)6+ukSs-QAKKNBdi)S_Q(=f^}ywHF^51%b(Xyg zIZ5&kgv;%7Y@mQs8FLfWc!a4)PXp7YK51+A9YJrnVWfTC6An2!dX_!@z))5z0BH;| z3}RXMI7J^%|JMo^$M?UCLRy*Pw%(W7oo3+S0OWSXZNZRAdABeSumm}utya=}HesT6 z0*0>QzwBr9$r!Ox*xETtJI)aQOuB#n+@imz7aJliN=!5xz>Mg-9(HRE+_!|lDPG5c zVw@IpFNm}S=&!s0SpM4m#US7lkR*5DtJ#guYJL$E+*L^dyN8eG>I<1Js(3PiIi1oLmUh zyYlzeHjg!`ajMyqP$8yra$SD4UKRKG%$U60m|9DUAc~y4*)%)bpLPl`nO0*w@zvo+ z@cOoK`ke3~GA8My1u}Zp!uXh)-{4omu7w@K7YbG#sxqooOKt;&n=Jev#PgT5nB|?4 zAtPfk?c5Y8ysfP~R4;p>70t}@(T3FLx0V-p5J$|>gF1d{k@!Z6M2gv1S@ zS0RCUwt^{uw8Un%C`pafmWXb8f>r68!-;AFm!QfX&}6ws&BD`brCbq1b&N^n*Z%J%3w&)0SAOy z)a0>K05czaj`J@Z`9wtzlhSyo*BJ5~#elLb$H24?=pncOh{8YDu&O<=U1-tX3%k20 z&841~OJ+bE4Es!&TG76|%Hh6IerIX8L7V~k&FdY&TTHvZjr&cy!{pWHF1&|>0_7Xt zqk__%o1~Gb1bonX;E_?%`i5e6@%R{0x|DJ=-(&@%7e$%kC|p<$C{>TrR{rH&Vu>1= zl1%jYYSyTgQ`Y{tMJid)hE}xeo(pL#w#bUVf_+!OSbtc)`}~SGo`_>UqiLFu6dl!e z`3RC281&+R?NwiIthluUv$%C?iB=scZt03MMx??h*xOnoNGR})(wZENQjD2)Y2^OF;n(VMJEKaFm@h!$c6vbX{b}!v1ewpE2ebVb; z)b=@>lJ|X4#1A2c;Hg!9on5MPof~FyOqk(M1_&uF0C9>&HMsW^)Nen3g}ZZ%JrPbF zXp_-Io`$4JMFkJT?AMMcr4E;Py4Bw9f^2eGAV+cw@%395JRRNr-9Vp3g1F&b7?pqq zq7Q|I=93Ly;!r#Aa&onvud4U+M{6um;ZXnY4P_ZX8%q4r6eWjFE9wpg*kcxY_$SuA zHPKZK6tI{FF=-yuv0IqE9^iQaywLA{L=*TmgB5E1{rvc9(S55K`J)7wfQZV~%7n`} zq)Y|CJf59Wykh(XZzHeYuOTX!M6~{0%a~k?~v(ry8(eMGb_z&HSz~>6+3LH ztY<1ml@68tt#%IaDS=iWg1PsMIN@=q+FFe#>U|pZuSf}syNzOW{UObM-Sos-s*hb~ z)I{08jk=L?;?FYbik|IDg}!QFeKVPUz6lEY>3j8m1z@u9UjcAh{Z{}a>psawy{p$*Dbb6TH+A2FYU zOnrbpKo@X3D63vB6NYnezf#Blyd6O(@34JCJmi3cXK(Ss<{_6ZC>EjscfuJR7f25a{mmH{SKRw;r~`E>Z1)I!onqA*DtS6 zY`2iz7mDhWdJ~xiYMA9PkLgG228&76?;G9$1Y8Zn#Q?kJMuDi+TS0-7gyYkX zS(mrbC~BR<=P92I-~burX&g#cgbC82Kp;m0jS8*E>WZ=xB~JEe*?<{PpFHD%3yj;= zS`bT}LT5p80&-^#`0j)DJB_v=cWN9Mx_BGRCck~!peBdNtRA}fyekf`vL4wY8p8&l zBN2wqFT&|JfjN&bi0q;Gk{9SU1=|bp%MjQ@m=H9y9u6e-PYq6Y1E)<7pN+&(8eUd?af;u?_5lOBF%$KzQxJL>R;6YJ2n#@OhCcbEKgP4&iWa2=WvlU= zkc%}!szhQpPWTVFWVKYrtFH8>Vy4;nh9kkS!oT2cv8%jbC04LUFbfBL-{Dwrri^Si z2qc~r2n~_Uk((t`GLk8JUDCnWdLGVDXo^#(QB2$*k!il>5J7ZwR64SlC>Hl`~0gasz7M!*PP3p;HbsNLIeGRHzam0 zBOLvnOu)aENwz&$C~~hEO1GnXh)2eONBSzby+gdeRC4Sjfubk6nF2BK$99&l?{!~U zMr@pm0Sa5r*HSgXkSCLd{$^DBcMzNU>zTYOG^8L$vDrrN=@zW)T{nxsHd6uWRYC-a z;D9NO1j@z$>TMx)sBc9LP?x%C&~;l^D~?3f{3)taa=BiZR-w%V)A5`+#$y0Kd8MNc z$Md5LFAi7~qpb0KjX(%#_BNp~k_xt~#+cy{BxH~Zo)81f6V5sUFn$G%?k&p3XKs_1lYc>!0sZdru-KJNdx}q92 z5RjB_(B-1fclA~iFiNQq6|$liykcZo$w%_5Nazc>2*XVZb=YS(j!8>wM3#wi@(b}g zKh?%N15If@K}SST-8^n9jw6f)Gc@fO+*`YI?@hw>_k~Nr7NF}LFi(0r%A?kimTMf) z466MAA9~@2A=CK^N$4TKq}Ut?!3-=}s*nANY>^>lYlg0}feeo;_&sh@x+rhM_%ww?0XJf8>T%(QYp7~`yi6P=rFwpT`Q=TC6{|gtM zYKl?_=w~qG{Qc1^shm6(0X=gS<$$KmDXI3*b|aaGL(ahkWo@YA(Oyy?h=A;C)fh6_(Pc13x$ zzMGGkc%T>l=O@P>rkqjm&rKjY%$i2RRp zcR!^Edi27v#{qs*eW5L>!B32FwFrikx(43+pMIV;E8P3bYW3;rrdkvI2)wzrSp)SfOu2xw72Vba*GL0@L9GOVEb?`aeoylXVkrWo2%!WED ztG5jQoVeQ`7Uh<+%!r9lVNV+H3l9Zsfcjrva|_Hg8bBvcostd3W}rvxXL^c>7|+k! z;pTaPzvfwGl32j^cFt7{-vzOz1bBFQ= z>PSbcSvj==rZ=i5xxA&+h}-Xb3QBY^y0Fb<1dR}5nzVT=sxVD(jd9xqZu6~L3TU*p ztfZw{;<*q2?Cr9LxKs{85wTR`6Af%4n8<^Y;E^o#RJalWn7^-#2^Ve7=i@ zhmc_w^TPJ|{k8NYb^|2ja(Z9Pq}|EV8g#vTYsXvzSDF(LU?yD^nOd<)Dk|iw@Wz#7&d z4R=0?Xbvp|9Njj*0e*js<&N4l5Yd~Bwlp%cnnsDEATm(IPn8nc#=uSFaV6gxT^-ws z$9C!i{IAz2!2EqoYiUi*mY5I7my`cO+3mfMr4d6ujh_5t7j<+4VkG4_JkUoN2Tg^s z0GL77D32wzhl9T4k7BfOJKN&&D>~%cnY-rYxEr_>gwpS+ zYqLJe$WtGQ_XZH@Gslm6;voGnlFCr`=yW1}de-k^TX!-^TNRt4E zp)pE&^Uf>(jPxe9dDH#tt^yj)ecKKPt~WDf6OAq@>pT0YFo5^u46Farne_&GI*P5M zrjb;h%#GaG`<)NhY~<+FWV2#75IszpU3V^0EGh>?)DIy%U8I2pqxPh-UrM?Zo%)za|R5!fhLS#yXZgIEjMn`DudK-smh8YH{4w#FPH^Wb^Ym z(ixx~$WG5DQ8Fh0i)rR4gNc614og8c{YgM>ZUhCKwaGX$3A>G0U#5kvmuaMpLe2BV z7-mLJE`j2RY!$X`1;Uqsps~GD|Bz|?E+cT@`AbP73+zHjU>1#*Wr~SoK!v&kC(2n7 zFrn^)JlHMocM_!jea3&++y|I_bigQ)4h?zY5fI2J@lO633Yj%U|GXiuZPK19!dlCC zy8(s&Xuw89bs#GIn_F=8?c2`#lKPzBC3Col;k;Y1dNgOt3k5ldp$kSQH=FcMQP+ktU~pq%k5p}o!ipb5ZB9hF!8SwLt6&-! zHg4~AJSfZEf3{L@qEYjRx+^vlFP2=YWl6pCyx8rUTga8F|)kBCt-SxxmI<#Uidk-%xmDEJ#oE66J?~= zt8hDmt2ed$xKafMTu&KOQZlSnNBEBCtvlENEJqmhVP6RSk5I8@O!gSD5HVsYFzKIK zq+p-9;OsYyLZk_6y{40Bf(mJi*#wxY^9qs^&0+w-1_73luSZK&Z@&~Lg>T^o=I+>$ z`vAGf#bC(gB>WFFfrpfhp(q36%+f|~aE+Kqh#%a526+2RfFCD5Rx#?8!hjA)ZSfYe z1SPa579C(Nr@s9bqS6? z9Z6o9S##9B^PGpS%s6;_i$XuQmb9k*H~W@_QN{%Dytk&ttkVJZYqK<#H^x$+oTZof zPSdZmRLOx`{1yhVAy$GA$^RAkYVD_^W1P~kJI zh6O%%^qPBh3Uyvul^7Wm=9fz>*cI4vV_Az8*pgu(z{c?vjSUl`SE3oBOOm0}g%SSb zf+WEUqslD_!7$f|8s97K>M*=LdyY8wpy<{pW}H5cKtxSnEjqw`y;NB74V&>-keMZw zjlRwt%Pt}+y~#WvBilYJ*u*rAR}l4$08`P8*JTN=&acf>2vhm^!@-KaPoYMKpw1k% z%`k|FBs?iP3J9O-=WqL4Tp164;3aL2n%d2*yHv#}F-54DY4;Fx=|AS8vT7)xc65zE z?NW?S+K1O#9IJoJ@ica>{7TTox!nX}gO+|sN+#%kr5~O`GF>Y`el&x^qgao3zYlbS z(^Y3gs#UHpgU8O_V*%PyQ;%ZaK<82$+#uxrLEMK{!55osp+27NH7hl}Y@q#sfFcf~ z1pr$5xqnN4gmfUGu4Ys}(BG;9$EZDSl#m31 zCz5LbX+@=tqC8sO#@*5PnyN3S0=M34>y{_II=FxQ6M&!adv%%Fy#s+*esT0%)NBZ# z18n%*?bZts@jag>xLv9f(NUMlDs+9(+;6lB@0VhjjDBEJ_kHE*wI1JbZIa(Pimy)Ai@Jn7uh*L&1({Cv z@h)*XU(`3U1QN*=sC8RL&TL$Vgd_nTxoB)xdOk8_6t(m83;l1E_TLwI7p^_1OvF(i zjuQxAfehpT7&BZSPPqV}szS*CCW;<~ppde|q9K}y5fe5)v3!;u0@FcZj_CS8#u@;Y z|Ir5P5iR4_Ij&gpDpw!85{Q+MlHXVWlGI@!)71Mjp z**bh-GzYbGE+rB0ac1!f`M70u{SLyFUac(qq5Q7yS1CLJ)|HPW+Kic6JLVr9X|;XF zf3A)+6yez%UK!~HG9_7O_5Pf4ti{f?9A&Yk&zyJHGb6?(q<_e-dt3bH3|8__L2$!r z6ld#;zANO(bY`#ot2CMFeWLgM1Bnb;9i+P_#pGqarbCI48GI5Dt-jxsU&<9$YAQVF z#v}Udh&r5Id*{8C%-GPngkw!^zm*p1xRB3xI0HZL)u0X6dlfEGs&)!!*;V84yAWY$ zFAUm}rEqFE{g5%}UUL8OlB3OgoK@qJ|1L?_-+d)p+t@+h=S7 z1BSRZpF!3j!P6lGDlR>t8v=&tU+3N{L{%j9rS*Xtl^?zyILL%fIUd9CT`R#gm1_8d zwF9MFTE;L&Q`CHmS8B=imm8priyF>i=*CN=lQyHOeBU z9!MN@1Xqt)dF&z`sx;as0XPW--78CA_%m&l5D5TmusR*?LXyYD-!0=1lQGhH#T?9f zNyjT0i3oZqHncjp#{uNTlb(q;sc464Yn{%CQf_|SM8SK6ocU6(pdZJf_>6Ndcg*C* zO5PnN!xHC}ZWeDAyzp`JerK`6ITHW(mJ0wv!vcUvO=tkg4(1v^$()UW3)8gZryKnT z#29_;QJ&}@3jFUdaCiRvS&YV1hrWnZ1)v{gOeCCmHDGZU9VySS(*D912N&jz^hOT= ziO}~#w(|>S;;)?!vYwb*v1t2Umt_QY?Qd_}s;_j=bb7ruNnB?j(x&MJuy(Qj{nXMl z4Y(SxQiDxVA5AyBWSyFp3_m`tqz#l)y1N!GidE(j%)VeuxZgS~39ZzAf+X&I2u1cxGD)R|3;zo{t9^4xg3&jq0 z!29i5_8WaDCK@h`JPZ>F_H#LqLOcvRw&{ERH{SaKUh~Y}U*CoX^Dk(QN8q6sY8U{O zxjW$39n8X;P-b_a8h-*;5LN{5;ZB-<$X2QwjMpR#z)n3S;X;_>XyM|`5g)BT)kehd z;=@ton?>j^yZ#IEoJMGq))M4t=5yFOCM$?Pdo&aiw<04p!O2{y&GlAaliSP~CbgVg z3@h&LdCb^f7X>d`zYkL+M%N2(fJc>>P>;k3{VFJH$*b83Sj=dbS&EiChz4Q4bClTs zUyAuDoHjmSlri}Kv{B=)HtLxCPaEH3!L8X*R5+vgf@qnCPyzrRP;FfLtc;`ZxoRAC zfqsHZn>rni(l0}XJeQm~*JNKgRTi{BttXa)P=_{(X$^CHvj3WRJt?miZ?Hs*7LQ5m zZ~dY52xwm83Go-pnN*+h(|B0sUl>`QHL7p(s^-#wi>{l=#T~@@Xi1PQ%sQnCO4EyE zgNozU&qT*lY+OzsKS}!t)o_Vnw?^{8@9#RFUtEd!{O?}^MmP$p_h-9?Xa9JB=`zy< zihhxtWbED}@PD#6y%b@5+~H2m#Wg_Hx&K{0Y57+27*;f!WYCpIwA)c>IJdSfu&>nG2(g4yZKJ{R@5oHYz*FZ|obEXT!S12#I|MqjDZ( z`=uPr?!3o?1Mxv)%{EX_-w zld3dI>U&`h1_@K5_gO`Z*V-SHE{ZpPReci_zxvn)7UMlK_Q$>cF8Ng{YkYi(fB`XV?9^wDv$P)2OE>hhhujw0Z_;5Cg+4!LhTLQ{A z%6}JacXIh%lv48hu~x+bRS{r0u5XEX=yJOaddk!8Dh8;vyPPYi`WD?IX!COsLf7KL z&A#Tm;s$|DLokAGgpu@_wpEFYhW2;mHE1Y^XLp<9?7~ALhbMgLiVoMuG3Tacs(G_V zz8|lM>frqbGLo~wm}SWDLoC<><^dZAcYC2XO>Y~tcy4#=%2D4##uoR5_!yG z-zEZaxr#f|ApQGD&tPt`0a;aEG?jKM_m8NUdNEc+HOXA z=w5X6g_0^(X;um~dQgsDcZLn}W#48r8;56qf|6r@&%+BJE8!|kQqr~nPPxJ;HN7M@ zqXo(G4b>kG^Tq@Y?3p(IwyYmK@o=sdMs!1kgspWC-0eOwNHG<^w6`8>a%FNk`yK}; z%GbzXK}d^S$_)qIyaEa*ygguAkD)yApLwR<4>GUroIQVh!-|D+oV?hTPNb>Jh!YUB zg%O+2=Y8A6g=ar9`iPN!0g5Le^ag$tDM!PC#txe469*+Zw9ve}=UH?z?>c8B*mY$e zHtQ$d^waef_&Ap7)N|+3*%ZCyGQ1Q_XMwyEc2h{7(Rlw8{)6tfE$Lm66jDv$^IAg&(EeUM>>WnE&?sd z&6bsPBrXwD21}`4yYW=6oLCQboRau#;~DMHxJNw-{Bpu;E1wJ0MTBr|4x0RY$NbKN zD*^Upl0)0`c)hWLCi`3LrW{a^9w1>s?G3^TQTEFCz;z00-3vaz>JLh4=9CAuB(Y_n z&5^4`!!7|gXv|N)+^AAb@TG!R&^5=aJ#*4q03zU&DiR##mSNAyH8;Q09jZiXd<{g zKsDU`fx985Ew|L_GbN!Udg!njX;{_HA%{wy>1Er=N$-xhA7iy-=lNQBQXh|ov9K|1 z?V^P;#+HxlE!69i+_?f+mp{kL$T9NZgx_-D?ai!z5)qbh?zW*YR;=^6GG18O9Zrr(>04}2sIW~U*G>ppPTC>= z0d84*W86hWBwkUqbW;lp&=5RIonx9~N@)?oL<3<*#=!mnx{JloOOZ7p1qUtkb6*F{ z5^}!O#_G8CTx{FEp{GlPFQboxd3c1kegD^3ipTlX+8LtH^`O28%llV1P^}CAfEySn z99)*gg!cP;dMrM*(E|t(Y+s{VT2#y-a*3My3e{Ap_{xqC$Gv=G6>C~8XO`O)N78C8 z#m9U+mItX-^@=bT^Aaj~W(R+&?$EU7XQIYjl_&JRGv4i#u;_uJ7HI`q0+3gV$^-}A z3hzAfDQ1eQgXbz`xS#z>YaQNyFA#sioM8hhp}GP{bOH#r8HFflA$@ANnfaXaUjDiw zKM}JFtWfbeaOw9S-D5l$cj(#36p&oiRg*{>?<_YU%qWVcnno4sf&?1%ikR_k`r1-Mn%o= zA>=9KQXY!oFt}o`=t%sQ9-10iYd3Sj(N8b2G+@$?M-AjIU|@-(Br z)$yg^avEH&)U`#S79ysOd+XR2u=}wiXjn;{lCGAhykV^d?Yzct6Xo2{$Xt<7PM|Aq zv=wGZPbl@hf6_f^ePxuE@z-5;U%DgiJME-#3ijGw$|MMIu2U!6+I`hOBcFMvyFJ$h zWie3q3t@kJKInOQd!~D6(NDNO0)@6TgZQ=Y{gn8-l|_bPGo+UG^?Q#XhUh`XnS0O0 zt#2b8MuFW^PpG?yZujB(4e}a z=2_dU8;xW7|D>ez!C0dK4%VQQ4b@v9jMZaY+sC!f`D!tjbi0CPIqT%MQ4nu)YHKk> z;Dt0avP&9(pUl&M*ymu;sZWSv$&MzoGq&SdtJ%Qg_)}N{#t(@GM&mn~I;B?ytHZH1 z_J-G&y*~akADcQHxPFUnz;wymYV{5tedHe|6%BpBJ+7{RxzdA{t@RJt=ng?YifEDF zE5)$A(MN>&Zrfe;!uL{@c(r^$ZN;>InUx(DwS(EFuxn@n<@P=3V>Ah0k#ZO3i7&l- zYbw94L=nQ6smb~9dv57_d$BL7@q0~8iC|wCt~ZYwoH4KnRd|Ua)(dBINJza2Wukd# zY(h+@lg9D@wH6b{x~S~|cVeAXCp(?y2ftt@)*xECD%Lkl7m^hql1Z2(oVlrFP3HQ) z!{a~Nc)!sWx9Q^gHgTDvil6EhycwAO4U}}OX#;>H3fs#u`kG=(CJ4w@L!;Q{jJCqMRO4v z8N-oy?)9~cfk~+;MC`sia@c_&q2h7)e~Y3cfHRb)s4Mf2z5z(QA!6pRN2B`^e`60P z7U5-QfD}j+m0F$xUGfPDLUZl}0q54t{Mevdyh&`3y2^}eM)Dor_->v|hNDbTR%Y?% z3vz(TWf)+!c%C_FwjPV!ktbXP-@ABw;_@8~i+zW?qk$*!aL>gK;_*Pz4G$XE*i0_1 zZ7yMUv!W7HF?TSOikA~F^x*}F( z>qY-g9Z+A3N9K}<-`dO)m=R`9>_uVT;OmCpIQrJqMRhqceH z8JLLz$kLIf6pQ`|oD-uSCNYhbo@ls6SXQh$sB1?tI*BM!eigwZf!z~=Ml%WlbS>9H z-O*D@{qiEENlGm@!ZL}TYtdEyUv$0oTUB59CcMu%ba!_n-7Vc6(%nd>gdpAB(v1j6 zcXvukC`d|5gVHhw{ml28x!!qy+ke1*)>`*-7we0}gI~VhD8!A$N`CqHQxae)G z({LVNcfdL&^X;JI6|=k~#ryT+mR_-8CQ?|Th(hkF?BPN0hi#3vithJp^`M-9UaM&f zQ!+ed(&9?CP0rFFoJi>v#IyI}5sdvPf5J~XLHLGN1|AAmSt_nf7!>n%A7F6`z~?12G*%c`$%DArYUbA+&(KXMA2HFF_{&gnpoKtq)Y9!$O7hY+ zw{|W<(U#kRA?v(Kk?^L^hcgbFHIFL#=d8EbA&u1~;raMyY!3a@h^qRqm?{&(f8B zpT}>b^(M3>(Er*67KTB0De;ze0>&b}*a zhb$GP4*O>^GjrbN2G$$b%E_u+PsT=!ct{~4ydPZbO603W|P5bv4UF|`Qd4O1Nn;M`24JvaVw&yv}O(s$qNWDa~%ckASa!cX& z${S50`T*ikx=qF2d*6wAe-L*OeOaee<1KE&R8uDGuV1w|P?g}+QSQs8{dv8>9YC#o zqwu!YJPahFhgh9woTWnqCx%0IQeh!%UH7BuqFZc7+g)*ru@XJEgTqg7?67A3ZUk+cpQMZxU1h6gcacr6&?K9D%$42K z?u6fsoucey#6DNE@n+&4m(fh{SqJIf|b+p}2J zZj?Q7!>b`n=S~oKH87NxOs~OQu+&K>!R`Y1FciriH_*7TX5#apM{^@EP|#pVp-`Z~ zA|lLBp!WA{ZbhZbMXRy%JQ{Inp5l(6l(ENXzv(pXO)VW1aP7>bgVoHFX5prw0Gq~I z>H$JmVB4(TenW(iBNF1~f{iU&0AJXUhn|`$92S>WBsdG9KsX0=ms>f>n$R$GCq2xf zJiLVWC!@F2ku8<@H9J&sgU8dAv|{?2I6>P8A+rcg0qyPewSinT^hxO$V?l=xcSRx6 zo?!ADwRV6nKQ_Itw*#f>+y9h)l7fyA0qqnKaxqz}SXpdXzgH7WFz*z2He+VnQHH#d z5j;67x7gvqJkXRf9zalZ%LPfZmm3~E?w0gKr9uMxt^DYlo)`J36w9)mL8h16d&Tqu z*IVkCQ{z54%YSBs1|y8*Q@E1GgA=d-3bpvE8Bm8g-tQ0bbpDa5+lA?Mu}#blX%?a# zuOovP=tcW+i%5vr0y3OXFI@6YSJ}p$ys>VjXG_rGv)O8CdHIp+C=u-^%@^;#W=WgH zF=DaaD9aO-4f10Wngmrhflr1uV^PJiCtGIHoYoVZmg@9l^CdNgblR`J^d57YsD83H zlUrhA+Ojq}=nb)tzk?7{U|9G51j*mDej9>}Q4lDH#U&eRG-=b3HIpRtwA(i~ZcqoI zNI)W0-3;dH`BvJ$ftfwbskoX0?ECeD-r^L_{+IU`3vomT=!|rqJ2&7#oGmm*xZ08; zV5x4-Qv%La|8?@F*zQdkCIl20ZWX9>P3i9jhff8Q z!k9-yf8u%UI#r7_`oyOCr^sE;8`!PQ;El%Lw0jbeU)gh6pbny`n5>G$n!SNWoWIRF zO?q>)I;-qUtp3aBF8Z5OG`5i<>G!f|j@*yjA8{WmvP1fUSH@LpxDV)RQHVss=E=W< z0d+p)a!s7HhYmz$)Hz{H&{4_L)^1o4e{_rK3^`232#GV^Zo&Y6EY};|hQN(t)2Wlk zy39H#1$MUu2jk`CTVJOO$j}7lYC5w^51BaMA||3fe{j z!~2_af?uoXmrLNdkb$Hid`$5Q6YMXzA9S&pAogcdnHdhfnze989<31iw;pvM7I~!E zDb!K8z{(wV$HrIWV6QKV>5_r>_jp*lg-{|dI0>-^K>DiNwsbs43wL^GokSY&U1Ii7Y zMh!52F5p3!4qcCMzj@WA_DdMATSM7G792K;9l#)U`rEaFe#B5%vA&0-1rbN+3&Qdu zEL=$xn~#RiqL^5p8&w!ax{g6|p3X;B@LlMLIULt=ze8irXg+=j!Km9Bc4y*_l5X{- z)&c67uQ18Gw70isG;b9(JkjAhIOII+&gdv1>-IE$3dAK2$zcM1N%EPCKozaLpPFmi z)kP+>02c)*_~Ug`tA~ctuaXeQ^ItPga0|iL&2V?0Nz(6N_Ny=Ob*D}C{CYWHork%?sQvRW&gM=tgN(n z&Id~y7Vj+`l=p+m}+@;H|*g!gZ;tP`RbRI<&MOS`}v{P>f5wKXbvN5fJuOoEtN5 z^&mO(=beX&L19|LMVr*S52+B})2ToBPQZ>Q(;)MWQF^2ew{-F=*KahFohG|~)Vsp@ zxXY(W@TxmoH@DQ82=q_huQ;cImB{PqZ zQM;>s@sQU6P^e)IR&wW_mJ;LQ+wYk?e$-cKRZq(4ekkaTQ$gcRZ}ZvN(s&!EV&t3g z@U@d6VL4Z4G0iqd~pTdSMc&XevU# zG00u+yeOoI9~(=!nB7IbtSw8l=$hn;l7pcz$rJ;4RU=E|rr!moavO+ytNiM$#cjSs z^av)V&evC97I1hOSY|9=ueNK43R^4?qf=a0r7Km%(Yr|1S5-Z{=^`~nr6Bd$EZ(XL zrY6Wy3P+*Dg}c&qkrPh?0Tu~qZcW0}R$Arfq<0{`$T!l$qcD7I zWI5f^if(#Sq&haYTYsO|oOU+3rA@RBqQe~92Av_`>{MRz6t8B&D+mbqgPwwXFyKQ% zN8WrZsbppulx4|huxVE3YU*sG%|SgnwD7iCG2C8hKNhC!7_oYDBoGcyKq3XrM>I;) zm+>_6w-_%^Q-P2|gU%&+gfMIszOYY%#5KZG3pf(_T)NM%mqj@x(BWcsz&WmSN@Q%Y zTNv4#k&j9e_~vS3UDi^bT*%+IZ5;f+9DWpZDP%At{JSA!f~Ca*!Z)EBqBz@itzB~2 zJ@5gmYqu6TtyoOP#)wRr1eYXOoA^sGPSi_WN41N=<3&@^G!m=~UuGWi;sO^i*jpiexbb~-ZWZGyiuGD3UoYi9Y0 zq+Z!nbDZVC?VQHG*J*m^Q~r(RTI#A>^_|{P9$c#JG=qhGn@zV6{}CsU->q?Z3|u=Gm1^2aKMbba*2vUs&)Bmc^1ezR-0Yq!WDG#KDRg;-4La;|#8 z+HI_-OHpCq3`UkuV)$(Jnsu7^5)SeQNts&;@AB+-^@F9L>qQ{E{SYAh4VHKf*2E80 z-7uC^_@n+ENZ^vIJxh_OE1+rA!j^=2l2l?ZcvYjNjYAB0i?vI856>b>y&|<8#k-RG zv1*GrqYn?xR8Q>XhM%D_!#_P9E9k|<%Q)*bh2eo$qul?*F9&-Sp zq5@?rS~M8Yk$;lGkAz(@mDl64R4j))FFQ~JwiXxtV zt!u$UlwJm+?^Bce&Y!a7ic^({XQ7`w=v^jFJ?p?j|2*}FvumLeHF;qJQ*e>@tb2@} zoFr2|w?=zS5k4jcFT369ou)aN{8JtR!<_}=(q!7c-!`9zI@8_i-=a|jNs*uhN>T}| zm)3Bu#072SB(K;&o`Qm&=YHbNN?8Xf{l(XDwz=$ctrczK4i!1#Z{J7GCR%@|C9t*d zg&niL|6aF8KxXO!v<;kl@hu7%d0khRn((i|LFXPvs?Pm?=3XXkh9HOUZTIH&peU6D zY)Fh1IETYdA&*UI3xgXrGWUHb{Z&D--{;8JHh2oErWQ;^UzwKSaih2XYq7G!houC{ zJWFVSiPul#CDWEmxCOa%I{q0s>@#Gj4a>IIhLkPHYqo(;PoDVR89*{n2w*kNRv-NN zxp{XdQ`vZ1x%YMcIt@>WVc`%CBgKdAJ$`lK@pFJBzUSId>3Y?rv;;KF4X~W5 zIp5!k$%_@0fNWijf3Dum!Lz~;phmz{k5GSzPb}Pc@z@Cef@Xx9kqC^6sBg@;=c@Ro zic<&n5PCP;r%R3dyrkp? z3`XkEMZdiuBwHWisXt;ch>ae6OnX65ldqCE0ez=Ee~JK;rKwr8KO}_~;*10{Tc1P| ziPX3Yn%+4*dcWC|JYDr*(_Z-*@%eP+o$g3=g;nlgml2I_Kv!<-iUkpH5 zSw;N$sy<1>55}|CxS31Zm~-S-qF3;BL*WM@)F1-yfTW! zmNOH%gW{{SI45JGDX097V5DKjsHeb;sSa3sFTkNXELpua6cR1&MTntWi#V)75v5Ck zj1T87|32{`+O=%zzMGA9ljLRM+{7jQ*MKBgrEswnGo4_maZ(^b_xr)l$laUpc18O) z^ze?#Kevyj*}L5MQ|EJ6XJ_(=aVkZQixnI`Dr)G!xk%Vu8`93S83 z^3Y6mI9Zn*u|DQ{e%E0mk6^-p@y(*Dn5#~5vyWEh^CmjaHA(U z^!y8z*TRO^$qcR{j-oFv+5Ji$FR+EygQhtc zpoIJxJ8+}oTMj{1d06~B7Os-ice+r*`S5FxnLJnW22_W66sSOuDsu6n#IAsVX!R?o^nwU$;BSrfpMfCC&eu%s0qfw!3$*#@yRKB zPtY=mof7&>g=!6nxnyoPtW89z;hzg=;xBJ3kC(++0LIflX2Y_SprlE-A2P}@B6sZQL^)C|HSdHWp2_!HB zK9h@wCgn6il}6xD&|9b)(F%Y}7mtjOkWNHVz|3q*p^t7SMO+Fc4U;B02s0>4N=R|( zRZ&4-hY0+PLs8LKGqjPj{KzBylpBH7?;9(L;Voxv>3n0dWw??G;GM5^zZei;$x%xO za}#2TK+5g}oLUK5z$EHaIkr76oOrSA)PQwApP(ozGl6u@w3@W^m*-NME`zsNHZ zX(Q!vv3q>NIvJ}eWu-syb2 z`C7$xK^%iZ|C(@@w!BA)k^%p-T@jV!oC~K0pqDsGs0%x#uNt&%Cq;%z?+cTbaf`j; z5gU=$@9boGHP^jpEKr6!|MdEa|8S`ezUzyh+Z?{YFvFbDJZ8ZG;ZY_z(c4*rll`6c z5vESTW8F`Fi3S!6wD942a@jK{c-lS_jT%)oFZo?h-Q#0@D*5qpD>uT#c?S}i$ySaT ztkU)O*#*7!yiM3%#n0GVU+Iw_=dn3{&k%ZWoBUb5BQx?~^EIa1&uhWm(0U~Ebwz}4 zrjzAF3f)^p5RmESa9U0ME3<58qI5~8dsj5p{Chc{k9$6jnV|I$iX4<;GQ|iL##HO` zkb;rN0OT%BU;a#aq-9nac`!As%d;JT={pEtWyIS2ABVI;nx$gjr!eV{cv4#~__t z8R>#+;Gb~N_Boqj(cl#g;H(SCRvhKVI*OAHi=+o`THTR2rcm)9q%nP9Z}5>qOxL9M!JKc~gs)QUvFY%eCS)Rw6z8 zlH%}(xA68{GG4^%Wfjf*v8q20PI^=FH&K_k_|{UUzF0rjf}03gqMX~>upH@gu>jsA zDVKJ}mt_U==!9jzl9db*y~#Xx48}Qn3*tK2do+}HUJj#%rftUUzuQtA5&baWP)D#o z^>_s>m$PVzjwQWtOoN4o#Rbs)VgolE2}$U;WgCYZhnXGw{zz3fo6;P2L2XaS=JF+& zO)w;T9>L5ZV(U->i#=D5N{0rfwrQhOH%)ra_aP5^$j{VN{DW~d6Ev}UfPo33?GMsa zDiFtHDzMeaUVHsu9kjAhoAMYO!7_m5-rFmjBnd=?${a&#+M`k4LQFT)F%`?bEF#i$%yiVNTlr=$@k?O*jB=r4J27 zH7_73^^{Q}W)i#4Xhfs?GHC-Nm^a9Ar8!rO7lioXkQ4L{a0P4t)L$O#1Ya|&B7()p z;uR4{;(0bAG34knMl7o%cg(~ByXD~ly`ZE;g+qdcT@!8bFw7c0*NAeNG;dOdo*q|5qwFdk#ZHr; z6jh9ACQOzv)=P{fCr$trM~Wqah}bS^n-2(Tp3fSOtJ&_wPp(Sva!)*dqv}2JBKx^y zsma|j7Aj)x_JUyU$6(S1NC@BEq`yzw$vIMuictE`JU4r#%MX37IJ0z(e&J?ooC`4j z`>>hx8Gs%(*{0Is;>`^O4A9et&eKcZlYq3ty|X5PJN}SI=&mZkYdX96WP&t6VE5Oe zTd~E<#v|!<5uwk|rwz$xl^Gb0@1yCo$~RtM;Oxipn!(5c$LGlm#hRM8pCfVtJu~ut zeD+rlJ;=f3dOmFe{~xCfGxOB&TT{c@Jlhc1uz66MJx%}p4#m_DN}~?MDwO&Qq}ixV zQ8}q?8Z!saBi)uZnb4`_4GAQv^7LZRKLw?KX^z6we4xz50fG`w=+c0AJUe3zFrLekQq4y7p~NrgPuQ6 zxqrem|MphaZ#7NDvW(yP6kIo2z7((f34G8v;HeA15S;NNIBU96V3}mfGJ4yy0Bc7? zmR#mLOgVLab$H6^oXx|=)1WgYeX|>zbZC;q0pOQjPrNPIjRVcCMDM&8w!dtSq9Lda zL$qjIQscJBdZH9)&MD&gcp^J|QMIQ3@xEH%xCy??Ap4qIX8z0dPcpfn_{em;cPI_a zpHu2_c}YfQ=eTerA1z5|0!iY~=FPG4Sw@Tt3GbJFL2_*b>=}9k^>_0Lxq5Ujv#-ZJ zVq?BoRJ5OdF~RG&S=0Lb!pebzb@3V|BKOZjl#F3>XS;TL#$!wj3Iuxuzxm-C?^hr> zCPt|o{so?@I|B>^0TTl2fXDZ`$n%`YgGkEGn?{ZfCN($`Vo4R1XN>WOm6dE+Og6O0 z>X*#|deNxo#5Ib&j3SCvO@lUrZ4_IBzAjtQhfT^TDrv5^zuObLRe%&kyN}XswF>QZj z|1xLsh1**`f z*a8ZSM;JAoQo9j#!4Q;GEtVmXGLfRXb(+T%R~WjN zBMB=p(wMIrq@|Dv^Boo|0V$X{s)A|-YC~>16n6Be;p6_QIGfi^{#Z@X9i zyU3;a*M?z?O#sm|K_YwvQn=}SCP*mxmBXTvjm=vYWze08rdz(*51WG2V0cH-DY3>_ zoFvc!)1{eznc32$buf zN(&ZfV5^G{!km-8@dV8T&Z|N91}XrywPES&p(eQb_zR>cJ+>^{aYT(S{ub^ybwm4+ z^3+t#_h0>bJUDeRV36#62T?OE_UH3O*64885E?Xx;m$r2UQFiaL7SCDPSF`KH~m3g zwCofN5wN8+j?(YzCRNY)KauT_6kO+P5YDw=b>-72&LuB43h7v2S?N`bkHGjeF23!F zb;bO|F&qB_U43C3r8xH!PYhmC;*DC9eeB#@xP>}dPV=XFW1{fl+z;)q_tdhyE(T)L zL|;7oA`_3O#U~fN>K@5wwyxoc?7y{ipgbb1HOw`>Umg1s(iIU53%%U~9Km1r9JNG} zHx0?57d!t)m5R7OM~LiBZNpMxLh~j(_HWp!Y)Fu0^b3Z;rLAZCCA6GWk(fMXL2CB# zR%VTtWa`z8kf`77hv6a6o_H1cCNUZvF(DPRS2+0)Ug-61UebUUbpzfH?;UnSVSu?C z5EB;m)&;D*TRl|*?h*MahL(eS%>Y?c2G2!=Hn6tBmX#^`n!sfW@eLwgP;Ro|Sy4YP zabm_gBe)r4TUS4v|2##}f=q32=t^JLHsCnm5JzLXMJyC$=yuV!=MdmW@#h1wj6^GT z_<|8ntXvkEZBc3d{Q&r&M?_$F{w1ZD%{X8=|FZa8g-W=Cw$vUICW9x`sh}$L71j^K zaA|y)f5T)klVF5M@XeJnspWc2{AatbxVB$xaWJzZ49Sx(gk9f0aznjFa z!!Dpnhe1Py9HJ)2!e*+1fZ(A?Bu1y2J^d2hab3#XaZ8?1%E>xn7P^bmAtVGdj?-6c z{pKGUm;CB+-!0pK?~mtOF+Xn=(^%#7?k4eQn;x^Ikm9|;+2eO^XF4J@wogcbyJp{+ z(YJIIkQ))HZiB`lf-#YT>n|63(=?Q&6?o$7Wv++A%Y2WI#wx^RZ(Va%M2SWnjvBOo zyOu^-*Qd4rvigrMk-RDROP4G|>5?Jmhj~-w<74L?`2cQ=tZOYSX$3nsNQ zQH7~>Jk`&Ex>_)`pRE2_0OP?;sDMnC8a2D)l|9pYy}8y$yaRYob;XJMzDD~>#4FL@ zG`Dh1HI03Kcp0bxP!>q&qS9YPflE#bc45o1?rW5`(-+O)=zlphvFexmVI-JAO?Qsz z9ec}6sc1|d9rhx;aXtZc?Jwi8Bvk=xU^nL)K|#2-9bZM2TJw=ckA}rgsnV^9Ry|!* zRh?KJBVsZ6G>t`BYCCfu|2)Hc&U;gGr>Kvg=&>_;?lRFpk04G)bQIceIW^kF;8@@} zL%W;TGNqN@wn%}UI@P3Qe$sbxRiRO?aYemLhVm~J6fsm#weVme%uU1y5e4C>wpU?p z5gV#7MJ8#P&u2g^yNee9(A*~xnLocK!3I^`%fCAbIK^$5Q}wm=JP8j8;0@;N|2|F6 z|9kqO~+UUSoC8mFx z2uVmQ}#bsFEVHd5%{ek{O?YY z4{ZKF@068~Gk{s*6`P~1M}SnWv#~~>Jk%zbAkDS8{@a=#0V6oQ&pH-ync#X+^X6#(C`@3&$coK z-_kOvMV!+4A!cZQDhc~ZUK~GO2F9^y-G;85(bTF!(=bNm-Y9x}7APxVH<3d^_z{=$ zSxZ=O&|o|AG9${~eOOxkVF({ut``RlwTN^~VybR;)Avk&)xIQDblB8TQ4YtVH)B)j z&Jz3e)~1VjDvd19pl*`G_<>MZ9|If7&xks@c)Z# z$NP_Mf56%t{EuySh4`Zbi>o@680g%xHwHB{s-SvJ4^Mnavd~Ovv|+je%Rk6im;i;? zD;21d3`(}QHM#vXSRnF70qYb$6dg8W$U0gHzwTPmo zY)f}~G`PBHlKKVgOwlEod^Dpw%Bg|=?@Shc28Kwuo%j*!@9igi z(Ab##1w5tOVhsb8ghIwASK*s_E6CU;LAX;KL4xM+k)Kl(XCX6gWzYkyr|Wk&^A2W| zxes%1D;7C1@OoOFYQ`s zPSC)jLOQg$MwL+LeURvDj;(?|9!Znw8}Hi7Ok?Lp0zf4u%Q&A-_|X7I4yTM67gSmI z=XKLi>knEL3ev4eC5liAkQ8HBg2$+ujEZG1C7O@+<(k?=wM-U&hdw%D zK5*fNrUr=*N-m0_cr1cVuE4e7VgqhUbTB&uf%rr)%z;e8h8gq&S1<%$w9JE83DhtV z6h8BG)W{tt?-OQ*>;?GU~yAA=jsyGmzE03t0EzML3~!La04-8x(9qP`dPul0*R)Y zG6j4Kmeq|135fs(h3ez1&IG7wP;M2a~!Y9|=%GQReyuK7k}v8?;mp zze|^Kw>?~)U{SF$`lZ7lt*jf35+@73Uir_|9fsD(00SKtOa}pSuDMU|5E`{K4Dcyg z7)&y>G561Q1mLC3B-tK5(7O_p5|-XxDaBl>+T<-cAG(&E*zjwDI^e*hdavxT(`4e< zS7ObY(}eWhFSK=YE?B&5Ytv=AUi*y?pEv&*Ql29+ljygc1pjw`2;YSMy+3Xw!!Ti; z9wtq3lk2M8OwB@2zI4gea++R6+jklq9TMyAPjkD~@f02CZr%?|Bzyh$60--Vp#pSY zmH)5%1NQIz(RnoT7W|lC+p>Cqld45=1M{ryl>(;b;-7C2RM@{a$V7-)>hLV{vEeYn zJr0{a^!=siy8}0Q?0zs^R6h0=xBDly1*Cb6N#vqpxYP6)YX5nqee#OnX zpqgB&_t6lAPCb2~{6ic=q@?}W^*8~2zmHO5%#EV3T_?K67z1iVajuSf@DovdG3gJD zZhM;_)(G4n);hTLmzw^IIk21}w}y(eizv&vFJIkhMF$Lilk5vNc$S_7%{<3Rn;$>E zY|Hxu167ddn$qgw#V!rs!z8R6u#d+?@GOD}Yy=XZVR^?TqHj8`qYdon#r1PLHVbm& z@?u?DE)SH;o^1d)Om}JLnN!CI49Xq%r~1EbyG>4Kke?}cF$}96K+g}Pp|H`2VMss^ ze-{#@8R9f?&`*~K!Q0hCtDuo-StKOx#pwhIk$H-hs-U3Rt^{^IIANZ_0Wt46Km8{+ z86)&A82ug2hXL{P_Z!ChsC0!&5y3GM{8akFf!O%9K%8mNI?Bf8|Ey35A#vEi?w%VB zbiWTs9+Op-EEFC)U)Wy**OCrD<0CtLy%@$DPLrQi=6lNr&DGHHm(8hAZ#iR<}bJL`10aHJvD9v!ep_O%?#q74xAz^(XT4 z2nwzvS6hmpt@#xoFY4=4s6Y+^LUTc-`(_lQ!v~^ZVf^HwOjSRK2;}={U>{v6vWNmL4F4s{ zfqjIGtJHO^L1oEtvRywaTwP&MU12jummr!ZOX|shQ~QxqzvQ(A4hKe56X!n0oI{iZ-VD5ThfEbuhOZ&ILF9q z6i?~gORHN)!Z>e8=2tj>Oq0pnH`=E0NqEx5rEvc+mv5j!^DD~ZS}S+sfEVCL^V4P< zwHYQUVyt{9YYFZtl{FcKG5MBSJ)^xq8vqZ6dt8`rZsMR0P%m7H^a>#d=2nx`FnR;N zCFUTE-x>Ur8D|Qq2f>Xde4W=SQS4(ocFuSuA;d)^X19zzYaHvE7$&l`{kVV?7vL>h zM<0+_zm}-;>z3za_(k8nClVDj6lzx;)wVmZ3Fcd*ecFPe95ck?Ol5bPn81?Pj6$|s zPpZ3b(2=g%7eQCrA4{P7q{g|BnJhdk#xg@SN_4t3hHaV1|M~}&MU^{TbY2+ifBG5{ zNHsQqx9?61xH1D=jUu}8g_0}lKbEqQ$7Ph!5W--|;JguZ;L~Vw*Q3e{Fp2DRW$M<8W4a#Ga%s>Ga#DZMG44UZuC!LSNWX=az`@wJ|#Z2Fp?Orp4yEb0S z=n~l&8CsYXmQj9a)w7de>dn?qBm@5W9<(6UPGPvr(y-Y*kq#83Dl(4R)GuIjIE}T_)?=lPq)R4fHNil)Lw@ zX0=(Y$mgbxk4kiH!RMZrwEO=2*qKtS#76o?l+Q*%>M1%F2Z&;=n)R>9WGbs)xGQBhz+TjA|f#*LLF!0 zvNnEoJ0V1yJLl?4qId0oH?b8TpHW&}6w6Xd?Qdgybh)F5J=fOm>FB|B|4KF@7*Lm$ z$xDXdqwKcHn5z{4^15O+b=f8IgwuV)JT&MqC`qsoL@>;jDdh$8Vd~xaf+!o}Q#=Yh z>lsI#EygdK?>S2a*GTqCAq**9Q~D5z5Et5m&?c_uCQ;@NB#9evfDFZi;f9VESATOM z+z&U`obYklKrG=-F8ZfF7>M1kRWSilxhwz7o3nmagwTu((xf?xMdaJsY8E?mt6Zt# z>`e-mbsDOMzN_Zc>N^Z}+3&$5J11<8g`L8&VTu9<=&zI99=c4zb_;ocr#*xlD3f+empV4Bd-3QO(-24w+*`E>2*;6d+=88@x z{{BR3L;!GI&wVnhMTOCa1z>i)bGXbw06belX&pCx zgbR5V47B>_qONndm5Y1NG-fghe_bhSTbMAPp37CeUrIf7F%z6bhzXYq`(LUlT6*-q zR8#k=-^Qo(A9a#RMR;r#KTm7z=@ZmnPUy??>j=)QMq8kfP+;I}8==eHH2&Rr-u#8B z5@yxNWbq`bHats8W`0FA)8f5!gSsRacChUoAK zdOGW4oaCuPy=rC^vv0|*i!%qY>6%;(BMw^hrRtjnYc7!V^He3@m@nRxmccIttz$QK zg$1slCGddXR0j@afwxJ5=i2xo>Tfu#5>n_AC4T#GrUd58V~ckDmzBu&1PY|N#NkH8 zgi`s1?F;_>d#e~f7iFn|(Rca_QzVp%2K}Z)z80TUQg<`M=NRJzJmsM&Cq`4@j}z^B z1TvC({!JD%N&^oZ+dCR@?>Z;;vHfN&BHB-9bnqHlYz6ek#+Fr%K(580|Z=27e&ZbPuy+<@IfryOF zK|x9Z83?0rKxG%ZNCTAH4FBMqxPAN>X21{=QCCZ4hTN%yc6`V_^z-8QcX`%!cyMqU35QJRkHt0}@WEad`z*A%F?kL#p4w8 zoxvfzR00A61=JKG$B!80M}+k7H_0DOqh@2v8U^2Tt#i7^3H)ZWMsP2hzf)58fdr6~ zp&AgK?+m2WiYPCNWO$>0r`Fxh&n@MQf zdm4>iV(Cy?-PT8op%$Yl{cKtVZKU^iw!QPwfAk-kks%lU3~aA!Vj<|#R?qS0i(L~pA6g@ zjEf2k>nc(Gj|{v?`R8{CuZUMVnuBM8x0ZZEd`$&hIDa@u0$TVk3C!~H1^%g}YubKp)Z`?^Px_-}55m^M2|6r?zmQbUmMa^aExVl=f z%NL#b87g=m$Hruo(jo^;Fo8$zAx5wFIvvaIjtRUdi@V5=eM?~k`<(@I%>vLK!Y#24OjBxO-vvk zpvR&;-&F03!7kOMDX@E5<5cKDHr!vC(?vd9LW_3zz7aAo@k@Y(4PjBxxxiL`e~a$l zGJhQ~LIS)NB%i^6S~obSh9Ko);aDU?>1JH3uVaFIi>BtTngxf_KQ#xnOEfd^zY9#fK*negbQBJr>wnA5ROHE_Ld<#(Aw)gE zBE|knid{_`PvSi@RANA{-j0s}Yupp6=~2|G&0ySsg@T8N{bZ(QjJP8{DuX&<8OaTrpuLvb$64Y5p~e7YG9zu1cC&c#o@in?!jZ)-a2W#f^$9qdrhC zouqOeP%ZE#+3Ui`9Xttda3X3*KgRk<-R6%>>a|Y>KYfTGYy_7%8-}q*9~>m&De+Nr z;rJ~92gR#b9L)vS5)qOr4|3#q(3+z`3K4~~-7i3UudjqV$qdZBC8RU`Ye?$^iJ$*U%W5kx`3eR$+bdEOaGP$J2K=%CM}lGY;7$Iie-3<5BRnmDXs3JP_q0o+JQXNk~!pLMws z5elHli#*DwW)6*b?>HcCgM4~~i_r4fKPGJEPUjJxzES40Knv0vP4`hzLfiFt+{JtElyTttboqGGxPN^7l)N)ti#P7x>EKdy< zg4XT`0i8KzjYA*)Y%JhO2IG2`eQa4EKeEdSR+OSZT(m~-zXyk;ikfCFF#gcgM0W>Q zM=cJyw7YyQcIqutMWo}6jai#&oJYOP(PXf6K)PKGHpNr*-r|YawG3SZiT9fiCJ?1& zxTCRr9Wx`Ip&i95CP^LA+c%6o;7Ph0`TQFnIr8J5xtbYYOVwTw_*xXmEWO7_zo6#3 zKRyU-fGr67Hvgmc$VZVW^ID&pG}1PnPf?N^G>PbUB5TMrrs6Nv=D(6))GpuO&<@hc zfb4qE?mTi!>1r{R-W9j!u4_s`TghWt_PemesF>nEpg;fY+yDLSb^ouQz5UnDATs$?sFmxgAsQm1QkfKz)fEZ6q|MRUu{mS-8fBz{W>OwkFlw zY4)ffC2?P}kimC@vn(a1(=ns7;niiS#a==OOzFN3tYu8BASB zpe@aDO0;_%L@M?aaIi=TFwjK57RK3crr+$pL4qi3bxqj=DTJxe2=EHZv5?-u6HjU8 z6$j7O-El3EuG3d##4j{1=?PJI3}WgrE}|lsdw3`sPi|e}azcd`79TpmTsL6Tyk3yu zvbhffD~^!q3?(y;PxS{Igt@8^?m)p$K3^3`;^}tT_miwLjQ@I2ZNe#dCunbIj?~5| zJt1Pr$}pCEYHrXO3pvR9ZdU$?hsJn@vE0ziZWZjP8Q+B6G!sO7EaR16&S=vs)Dj4t?S!Z-eQGv6jYX+jZ{$^5ji*7Y2&lZrw%uf&NLL zK@SYT#w7icUo}?P%Gr$^kGkQmw_?w6r5X9#rI5y5%mVjrp^_zBhM0dh1BJKQ{Q`ln zNWPa$TFbgtU~qk%Y8~_Oc6u+OCBt#}+E~6QWz-<2k9LYQv6+VKJ8a1Cm2heZlnu-E zbrbZA$8BG_PdaRx(P1<2^_{`s5!KAKHyfQ|vwu!_FKFX|vSH6KL-wZjFU(km!i?a- zUoS4%x4mx`h^^(3+c7^RzVw!&(Mj}jg+80QpcQ$SiFLmW=9iFuL7{ zDLUZwU61Pj02#*!(yP>$@r8-f^|;0SMANMuaEahlIMu(>3aHysh4C4w#}x4|VO&N< z8F0mxK!G|_oB>goe9m0ryZ}dwwNs6N9M@)MncWO$UcI_=5|Xpj$D0{f`&j4@&GwL4 z0LRj&IH8ee-Mqd`m3-fb<#feNo%MnlWOJZtiqP3Pbkzv=eBwwi{N+`DLLCX#gL>py zMY3Sz(S#P{jglv}3r<@&PWnVJQI-GTR(e?zuo#i-@yCs2A-eG%tuH3H$AnvYE;=P~ zqwYiya+SY$*fx@=`4*Ev{j+VT){S7-OP&&4F4edlYx@zZf=EmV4>k!x`mH~#ea7H;FHxuFB?j>Z z_7O;k@~{^Pv4R*#U8MxNLCaeb4p%K!*(%>i!Hw(vl#FD)P-Rm3dt2h+Vlt9U^z5eo z=J}&7RcO{F^BGHsosfd=5K+OuR|DFA*yBH({&$2P1!T}FpGOEh6!*WINd7Tm>&exG z?>vP|3Ay3=3Ni1`Uz(5aMg+4VnxZmH>S4knJbAu!JMhGxie@$bydGNdbS`yu4_0|U zOB>)~vsTgo10ZQr|4eD^`quy71d%auWSZ%s;OnDawJrq{jJ`h8=}KIfv2~uWh7Qq) zy@So33_s#>apd?&NRkV9R6C zhXTQ+sKD>9s?Sfa;&Z9mBG;eJ-@+}v+HMvPgm*dIt_%t`Zxf3!)M~LmODbf538+!~ zC|yTtrIR@^HqD~0pBq_5FImQHk5gu%!n=bfl$y1cAsWHoF;w3-dQyjyv+tc#2l219 zgCvutCZJv9bS@>Zrui=+1^23_+LQbjchMm=0z{7jsaR_)6GlE08kd*$B0@5D3~JWK zp5@0rqI$AZCOQq#5{wBB^BEk1fk6s!Wn6FiUzELNRMk<}_PYZ%-Q6wS-QA6JBQ2eh z(%p?T2oloW-5t^mf*>FuDWPYh_j|w3JI0A|zU|NZzvi54u6fPh#mR#D;=9_{f~M7D zAi+LFAwUu1>{DIxnm4q2pirB$0Fu97FAW$6{d&YYf2U#zn>{H_YD5%B% zq`l0XCpt2RJR9mIu035Rs;Pr8;EE8Hl0)imn)+T#d)K=TA$@_tf2E zO5PL4T&`7WeD}Az_iQ2pKoXG`{+Jh@(bY+8!mM{_xf|aZ2o8Et7u`W%wBB zsPcE~kBPMKQuyX^RAv>6jB$pm)#sB)QIG3hrgX@tTn%&(kK)9*T3Q zL5Cd3G(UGM1qkC#1i8hm(g?oHm`kctHOxMIm9S6KcWL65?EUhe+EoiAK?V%tL3dJa!A86t{>a z6@OYAS=VV&1JS@*`z%V9MtG!WrzOtTXaTfV-R&JB^Iv_;&?w5k`VokNv4y8T4cqlc zV?43jVfK+p#0vg3{$8Tsa@KjvzWE~8Q=w+nB-`350Q-<4MS}?#GlRfc%|ZVyhf-bH z6+X&<9)u8QB=RIn>RzoJ?$9xo!4xhV#KvR*5{ z&vbE>4eQw=m@Ryd+I4K8d6(!4wqzGaejSoyqMw0a_fw_9m zCuINtWDo?X1`Q-AUVi*3IB!@bwSq3}axm+F4RzQ%2LTVpHGrKI*<3t}u^S(WgPs4E zy2zU0oE*$7%yny|Qe{ihA;$o~J`dv)kHQ~Jy)UP*yL#o{#xzz`=xc7Los7a%_p&Eb zTii>NPKNr;t|W`+71ePZigDRJC!3DUgyNTSMr@H;5}nP7tK8ztfEax6S#H#`0FH_`aR_MJh_2BX;JI%vO-4n69L`F+$BCAsi zlMcesblvlsiDPp&_|`C4t*B#Fb>Hs>=9YBw=`o@AP9J2Syi`I=-9n%sv=0s`ID4~a z1>BV`$c?eExR5leGYkw9+L#%up)Le92{=NRm=b>!6qFV%yi%XVI#Od4@I$0I3dBq< zdLUPiA9P_v3fPDUld?1=&I!lqh81lLA_x|bB%xw*Uk|LO*81`!;|VUgyW=&r@UeOK z#Yq$JmpeSj!kg2ZPeg@s!Q5+s^KEF`n z_9N(Yr|c|Fs1w=V$j7wC;;|KNOJ)WQ0*Si*F+YK6lbk)SVRenkd2{_n!({* zr1j5ht{GT@4B#PDqaa7I6sOpa8^{&sZ6+N3IP-`K-xk5T_UYbN|9IYV zusB{}+51s5-{wA#%F^kB9YoTU&xTkhBZZ~-QLUV~qy>Hc z`4w3UKzRU{PM0Z1B|#ZpH&(HZAsX7;{K=ty@+ELm$Gy_jQPeZ6&wOGxKTwOC*~&js zACPH3|4AD|M0zfqQc^#*B7<@aM-F{@9$rN*HU{j%GezRF({P}KW+m!EhIeu&$?Q!> z{lbFMm>O36UXbua7Ai^?=l#sm8YMCge%{!?%lSZCO~H;3ff#GSr9kbxv-FF z1^c9@5B&a(wycERKdfe}+6J4tZ|Du@qKDJ(V65VpXDcf?aW>;r;5u@@5esd6w5w_J zybyaMRlJb=mH!7JkO)*5x!gKX8ypC3o_&x?*9&E)uv37Ugh-l|RTvut=&R(@OSUjv z&p2QYDp&_`qRr{emMJooLs{HoLse+lN*(T(c1|%g^tqx zk9_Y5Yy?g6`DQd1@lYK-<&8a0P`GDn@a9u0Z_E(k6i(@e5|%WCz&a=B+qgED4%Dzz z6VSvz2E+H>X_K&FioXsa5lYoG<91I7Z|6zLa^suB$fXsT7k|%O^2?I97`LaXs?*Fn zKeM*4UKrGLQU+iZ5~goxt|HG7ICqe~<6I*I6wmo;(SFLZ#XiK5+kV$Iu}>pn6(omF zxtytbJIyHS;IMqcelY$g&z!&g#+KrPk2o>V)y54JNwBq=1eRB0u%RH z-;%Z?a=ZT3Y;!*6#Om)QT+5km(`OjrAx{;$4fk7A5z5@Eg}~Kv=)*eJXeu&gUq!u@Igj_St42 zLId?+=Hw1F7mp}_T-Fsh86wR90t19daM3DV*@A;iA9(AhMmJxDP!!r+EXQ$I{zRF0 zWv68+r>pJI-2U3Pee}3?CtF>KmkN@Fdv2wb-XExi@ zg_EhkEHIUUQG!a!l>tlFwJr-xc`&l6iU>8ib#+CTToIAY1R7l7q+xbU_$UJ|U;hHN zZ$Ia8hzy->YH++sK2GDnMl4xZKX0P`wPJ@-kbiC57lE*Z=lOtLvS0B>zvIG3pzS+n ztT{Oy)W`_8dK^}T9Fc*%nD~mCc)2xf#HHGWFd|4hjjf-5SPv1IIDHgc4@J4TyK-H& ztQBAOM=8((y>Y>}{%zkMuko9n2}jiN(^A}-n;!HMc*ng6^!HGVrtU9NU7rgWd95y0 z@TJMbEAXEyOuhnbV^$p_($tRWxrI+MY!DN*lTuhvKtW%D01eUj;sEpbt%hL~S*WEF zuL}OosJ5C4Aukd(J|7=(5*&3PRnLxnTF*k&Yxa*O*+eKq0~p+0?BKV!#G4VzJTzHat2SmH#8G5-X7 z`s7xN-N2ZqT2z7}sX&NHE*HADH~(*72@4Lx0(h2ry#ma%0&4;q+@txL6Wyaz?W#CS zJ${LDDO!ZAq`~?xtCPm3VO0~xzuXU-Z4xWdx{m!nO63n9WP#QeLzN%<| z?ceP#1Cb0Gv*$v@!XQMLv`mTW6=Q3r8gh0m?Xp*T2qjr%^o9lDBcq}qBV!?CPL%XP zxxjgrY5LkF4`(;C4P<5|=_)2R%sw`Ak3wB*l?p$OvU<|I?iH#4XL=d=+XGG1$Q@JS zQ36)@2908m>p~-0K!@+Em8%K~=b`@o2dcLQ?vE3}EAz|e++jC7hmG4LJP+45dC!CI z?B`Bg#%zDD&ulhlFCI^SCu1-&`)Hg0)!$zAx7yUijY5l4_nEa)rW6WuY69)dwH zQj?f}sb9zw!cDfm6|N64OiWeIT8mGY2KhB1+r__ipB&&B5+EE;j#A9-y0@$(w1erb zsEiNywyv~GR&dE4Tf)zGoK7cvJjED5Vdx8o2q3mN-BKQ1Sv>s{etKOJesqr`ji^^0 zsm${H z!E6?bVQ0~{&Z4&S_h=gB)VR{@Pm%KUpr|7Jh!VeZ&R00I`gYOsPw4(ypxse?*qG-r zwGxPOoQ>cTGd6jxtVo+i^Jiy>LzX}a*-6%)u|;EQmi^jwtS@t{5~*&P4|D5 z^YAZX+D}K`wCGdN1dx@i6wOx(O#s*twS$~eks_A9ID@avcesQ2*f9Ws44FU=C_CQ; zkYEccLE!Ml9D92hMT<5;(RY^z8{DfThJ(+F=uil6@ut$spu{V#3&JIxFbZ_B!K@hl zgruxNEsnF66GmMYEWGSfI--!hP@tBiY_V5on&28jnY}&`KqG{QCIRnWKBi{N zp(Kux=Tm!uxSUl%XcE9hL`FhH#DL432&)6ElvdjsbX8ZqZCx3e?v6ERO7jVJo0C;N z=k%~^a&VpaM$95L;IxSN<&$j$VC2xkJInJir!v(`f2d}aX4~%oSQnCpAz*D=$BdO zA3It3^i+=PDV>wi^T~kLP5(B;E$NZd3YrD5_lo~V79fRYfjx-$yZ>eZ-~Y!fP|5wv zttdew5T98xYI5~-&4lMA3lt10K123j-MzU=i`hgekaHy#Rq&E7mtww<;0_$2UsrPi zb$<%~5Qb@8IJ6{j)!hHA5Tv#o7)1N`l3@=fK?mHD82xWCE#-Ii$Fz*6Z>O=Duh}_K zB1JsBt^&yc03ZM=rqzI6G7PrI3GFjWZ85H*Doo6UQmd8+^2@^u{*HZJIfw#l+S8xCMtO} z(q?Y3=MCPnFnzO%JwsYk_<&7gq^q5^(%zlNnP%0_jM|QXU0t6L^O|Ujl}g)H#=EyZ zH`M;jdcUBcgqsv}m8Hh{rB)ve-{)Vi{X6|P$5$v0kVFsUA)v?;MU$D8F1TX^#RM>5 zJ|)J8mX-lGAp}(c5gwfsF8Zj})4jrTt`&Zh$`(J8S`3jIf(8di4SetszZY$D-oqro zh{n|mxYdu@Vyt9muArNq&I%Tf;j&yqutS0mCYO%c$l`_Wu}Qos7y#>EgEIfJmK#o) z5VBKR0hqliq}3BCW>j^{{?5#15ptFLYH5pwTa^Y8QHCfm%NPZxHM^%-;}!kn|i-sWAER4 zv<~C5q4aa^-VA8*t4I2fAvZDQbMg)tL^6{!sNYydd|fzCj07owq{Eoa3*}N5gNGX51b@HP}CLEMM0b(fe*17<`nJQZx!G= z4sQRmG@b+nCEq1b@ngf)lV{WqlEkl;sg%EIwP>NA1Vb6Ku}`I1XOkH9nl9kD`B@@2 zk3FWCc{PC&V1wBoj`#&NZIdZJN83zMt4_m;%hirpktR6d_hpZ${+2Gj^8E#r{v6G( zUk2Z$)!bf=mL_j!3dQjtyJ~H0rjwP%gC-u_-$p zpu(-8^-)k-+t}}pOU0Y1lrjr6niS!zP|)S)q}PSOan9P~HbVaC)X86hsX65zS70*C zPi8+?O32!PFW@r>hW7nVxNf4m##m+a05LqzKMFI_AOUU&Y|xI%u=rYp5h&jd2 zFgR?s$%GnO7{s{_4?~}n6CPrkRh_tXmQzBp^NN2@-*B(^UD0hfJVmu)y( zi!(c$qUPZ|KT`M9lI@M(GkkAM65Q4Q%**d6rM*!UC4_#BPzo}c`^vuo#TSRji70;g zF*r?pIDJrZ^v8U#D2xCMOj6fg@VjgyBQVkpCmu_4vJH>+#qZ`o-?MNWp?|@Y4eEl@ zJ+suIjE-x#y3`i`ia*@}I`gy0kr_&#o09wTt>$@ zi#{k_K%1Xyx8{!aMV3o#L>LtSbXM8<4PX6xj7Ij&fh9SmbFMt*SzwU2^^}2=Sl~`_ zZHNS%O><-+@Qf%ib(S6+8?g;;4$UuN)sfu5d}m<4$QU;abo#}WXPdw+B^%r zYLqk;iDEVnf@7N%`Y*0#4Pc1~2v3(Lhw{h)k?95+GTzq|f-%CZmcc->lr zQcS&&gp_NOJl=UEEXM(JtBBIm_u*RCZsLWNg8)J&pND`iF74@-&j=q!&Ve37@DVJWy80ZcJvb)d_H{Rrg4JCu^pGt@!`o&jfalPKj zPQ(f49tBNG)2b%K_(t!h%GPa%gUIo+^P91ZkCJOz_T8kGTH6pTcyzItM*i1IRK}Z< z=kcnzfXLrPl`SbvM{}6=1x679q_~8fu$&-m-E3_nBWwzMm47}NjzDfCfK|E_g_`13 zuYYo_Q9|T1zJZ5EZV(l=0R+J^;-~g}XB>g{BKY6tBOPq51y6RAOP;bX`60SVn;Od|_n%pW&7kOuGg3>` z)R@tj9Z0s+2s8mX5MOkr0q?iEwH+PENCm%h%4B-=?MNP}&)?`W_bjv}hhi>&cR3Mp z8e812`fbXc|9^Xst1Efa{*QwU4?V~$Iog?i>Y=85g@2n6Ca@)xn~|eWgYGa6r~!|O zqLLBLcVz=)c$_eIwy#-Y7KfCu&bcx{005{LRuwuORtBsH#C>EhuM}3Kn&skeYjQg= z&M|`WOT4-bl%GKsX=qZqD53p(bR}=eJSuIwZJ689 zmiUTom0@}h_n;I;K{E9W16z>pR#+5H#?-t>J}O{{rP_CXsWbMa1$mvjGgBiT1dvTx zxH+(O{j-t9@9~ZCeBt`L^n*bCPr+v-JDK`Vam~YvF}Jz9wl$(A6$vdh1_TEAt>USy zPhVnCVUVi9fH~+291R=`KI(p!95ARKYz8D*idR_Vz=tEclOl!SlOw?_3Zd;G+r+#=$ebo7RjS=KwFPssKl1=8l;jX z1~S}vvntMFFTV4g0)Xd@{~1$o9vRUE)+6+qBav@IdC~!W7;S+Z-Pm|3l9Oi>)8b7- zKrm}RDxt9bR-$9AdXaYsF^Fd8j>0rXfSP}8D_~o~f0e+1lwWHO1a2wje~S+W zy>OSf0DlF7QgCPm6lR536I5$56{tgIhl(9yFC-K8qu3W^+homKY7`2 z1b=?`Im~4ClbMB7>l?0=bEREPlF03QS&Dc*` ztj*X0XV0j=o+INNILF}M^(OanM3?zVEg9~i`7CTm=8>%l-f#Ue$7-KRvrk9Y^y!!Cn5NSZLXL)?j z(6-N&F%Jm6ABDH>ga0aRVUlTHuuHIGCt4S5=9d?rTdWX}1h7`n$s}Y#Wz||*4M(8h zCAG+;OblnA1-r0=ZFoBtFznwy(h2;G3TWQYreH&|{CIcBY{z0-w{ZhbQ(OEz-N>Un zVQ$M{dm;|Z=m);c2owQv$KPVw*3`2au2Wv*w$Rl+$yBMH0}QMN$K+{+x;4E_3-Q!p z^5>js8-8w1HzglmO|O0Sp@?__qE>!Y^k?X*MlbO-i+BWl4O0C>aGNK&%wK73B2-#C z5B%P3z$p3ML26Sp{;OPkI`L?*;aj>hoA9{rsSII?`!vC!Sh1(5a~$~B&m3X4ra2Ms zlm0YTTr>GyC&uWgVR61Ue+*a1-dgnV!9#2BE~ZsKCgw;0V``~*8%8mFYA0n&mXYV@IzckK@aMG z7AvX1<_qL|d65=&MN&$HD?&=K=4&{=w(0NBV-~BnvCnQ6k>H+dVQd@q#Z;&Y z@?Y1oM81sEq;hisMo*yL7ibxN8Pwe+kQA15KA1x&mJqYy2AQ{RXcF{?O^gzfDqt7d zwwFTlGD-X9s>b_^mgfTRl+Ba!qBk62-F}oOk*=--hzum(Y16$fw3O+3!~bI=VC`?r z)N|sjn!R65XrW@xFFvfLR5u3tVb}%!+xx(Hi5Q5cD7hHiHz2w6vH0YgSToHgt)rdV zVvrJSG}fy9t5*Z&N~kX#1rH!?>u%Bp-3EXcYCY`q@$z1`3lq}D)QO$=Lu~ga{gPym zPfLQ11NY?M0>k5!OSW^JqVQ0&a4m86-)#GBcf*V6w3+h68m*B;If z99dW03jS14-a(vd{&ND}~9?hWZeGgl%C+@uofNK9cEwg2t`^u~R@Cje$QT4yx+L+=kDd{}z{$`#>a8ma@{Pp+R(P*LO0Er2OkQJc{dyl8q5MgJ*HmVjT0To$D0F-uLP%oO3sh`wW=%L0)AA~tnkcOt9 zn@vS*5U946BUSOz)9&avtEM04MNo_My(@_-;H?7C-EFH74rt;4gw=Td^u>Svb+~3g zl?6=<4U%3W16mlfC*M<)zK#C9+tWwDYS_L2OfhPNUriMoni5uD{4QC!{Jwvp0z?m8 znu`qB%l5VB{$L|hp@0Zp=y6|PA@3qQ~FZ?h`)YbE#Yy*Yv#GDNE z8W8JBWlGh4$DkIx8dU%%AlLX#>@oZrf{7_eC`JJQb*D&^>3=FSNi;uyzGMC}J-t$& zd%S{zm4h~rm2>9ap`oGJ6hshjfsTHn_aCs*5ge4U{2;E2Larjczh#SN4$J)@{J24 zieGcnimEiLYs$%Y@l@Oh>{SwpgD8;$1KwP0r*R>3BcPxN928Z#lQCAmFAVXEPf6F`Jy_K^+HcCT;~|>pI+{Bm zwtqdwI%Vo>!MYOWZL5FPA+?@8?+=R5oZ zNG3Ca()#pk2cC3Aj!fJai;N@-XQx=osD>sFSHyd}MjE=n`KRGS`-vub0rp==Z#mt| zO_y5gmub1!3twI1!9rgOJloDoK06#VX3(jXd(?{a9}qnpH+tw*AMj3LM*_mN6J+$Lu(xP4x)*2~3yGpo#(AnvfLR=5!E zQlgPq01W;Tn(>76{@gD`Tq?9L1Ztp~g#4ibXeN|K*Xc5BRd-Wp`1`bwhF|7w@I?RV zrgB@O!jY(Avo@ka%nz~>putSdO*O&-?l?T6y%zfjd zN@AX5p)`FSt==0j@02d1$Whj&G@Crhqw;fVEX<;GBLhD-u)7SS+=gp3^6c>Os}3)Vs1(8ix+1uRseE$6ho7~ksrV<2 z$cHESRfZ)6C(F?Q_+*O5q#gRo(u)>3OJQA4OB{}M zbf9w{GG>B!zrt`0w>nWTrmGT6J+G$tSGtrrzT<;I+(eRt27@ZXG5%RSdV1lxd(YZs z-&&$jfJt`zHyuyy@4v~W*r3)`CfqV()y4PElfT79dt1Pw$WCJXa@?znlvJ2O7GHhb zmiU~o#n}jACJl;k>=qug72-m9A3fyWg*G}?#v{qB&tMA*1!g3dFY<*-S`lH@O-L0+ zoyKRudS=m5ocu5$xP`CANe4NpeBreEfC^bi`-B`u8;n!> z@7`Js>Ouv`WNXrp#~lHK*d+Yq9}kF%5+M608K@^b^VWoH9yRGMEQSmeQhl-TFV9i3 zfDKbV;)sto(X!e3!!X^7^^?TlxPcdY^U>Xpl?FAQ*?iJ%5n<8ipCtu7P@l7X#-w;@ zbvD0;A5}Ib@0d8?6=Ywl@JEeJ;j(7PN|_OnPh?tsfSMA&5BkdWa7}J8<eo_DO?3Dt8|^o2Ua;#nDf71<%c!DH!sf4e5BBv40g&A;ovTWCT6HG)NE6sI@>|~ z)wZEjcM#@3BlB?*F+$`fM*u{973pR1&*F`p7+P`}Z0fr|0VhAj z{uLdTKh(H|7R$t9y+;DB9rv*qyW!`EV+o$dJ_1Qqo7CRtd>Sd}3k)#wlaU*B#EGBk z2vJbJ*3}Y1%C-sa;5G_KS4g-Od z4sB8xQ=I_~E`%qXI$hT(rjRQWvf#{BR4UZz#E<}KC=fcO)zDKTU5lQ>k{NkKkg;Hv zY-}2jtQAcV&=s0>kY(Bu3Fa$iOD-qJrqe&zo%`}jmL^>$>G2zik?Y%T^;3Bl8m#}< znuGa2YR+S5GjGhDh`Pyv)$_#CMkeC>g|nnLu5Ja`oL#~p8r?TvFs@-^+0dk?SH|A4 zMr-oN;g^rG(2V{6sX5}nF|O5v?u_c@w1xMSK^iEZQD7kO<%G5cP&zTe#}ooHAO()7 zfcQ46TnVDz_RcRN|DG!DyU98UMnig;OPWSr9u?^;gY9cmCD`Ilb#V@qnVpZEM{6!j zxuc)nMFoe<<8=MtQ$51A3#p!o$J$K6N~IonsX18erQft$j2Z;!2Mbc1Nki7^3nfZX z_7&0qzz}dbg6Jjdeb?0#EJiXc8Z`=`oCd~+XbiJF1?(+8^M;iNHI{(e*<@lW?mkPi z+aI3{^=Yp2X$%-)1vgmnmoW=r5FR}zDpD#NZ`M!6{#$h9Uy2T~oXm_N%d%QwL-Lyi z(s!9I^T(|sA?-O%f=vZ1-}vrZt=?O-Vbj&N!k1)1jI^_9s6@49Vd`EhotK*{B~N~R zswPCdSACe8w~>c%XCUY&uMW$1^N%H-raoeRY=8;uDx;wP|ExNBFcF9I(5hn~^m8x@ zWfpfX#P(1X9mU^US46?jLm%RH14YegB;MFb0bs@wpXDyFmtNl+6xWk7b#OF392~Yz z66%>sk=@i0zGB+A)Wi985WZl|f&CSdG#C5z11%NUcEJHBEb1#|S&9|+WlNU!C=l3i zY@&{h`lhImfhHoHSFBdfkXFn~36g8xTdQ$pC;Nq{Hk3HB_jF1tlDN;pJ?Gff0m)Am z;Z*0djH`&dl!AgPS2xM20~!w;#r^W9ufMu-)7t;ga(+>DNY#l|Z(yWY^=rDh8#$Un_ReW@n%vl zaZK9k$4|vADWGxVs?09%+RSO^!h znP%yhyLd(lUJh})?}&^$Sd>@fM1%7)eaqG&+KbZLO1SCh^6icXb514M9#?9K>Vh`C zD>QzMVCCu0rDvvyd9_xZ`jyCsh$w&j1?TpR1ho!CbE~x7`Xb)DH!MiT&NtnZZ{uL= zAWzuy+Z;Nb5^sE8*AEh96hGEw3f$q#(2^nn;a>^DeycwcblR?~@ZvOvWQCh>^<lv!Cqr1UwJ6f)|GM2Wmr}qj(K;C){cP4&s+=(x6w1@??>bW zE<#C#nTphGQQv`Lb)j?XNnXn8r*dkTKGJf!TbkcTG1r9Um^7@_ z7sA_>*$3IfKu8ToCAQH6O2}4oDf745rc6q1N~|+Kg_QTbsl(L@ zdW+!b;f)TtkaWmuB3i2r`?HGZ^%u&9C_jTqGVUJxM%~*VGaqNtv#Ylw(j=3yv=KM` zdteC5umb~o#hL){>B$#Z&Bl$!a2;tMRl((b{KF?$a%ODLgp+p69T6}Zjf-jo0=X*m zzM`w$4J>=>W8L@6i7*5*UQ2#m1 zeqv8Bx@pv?EwU+Y1$tZJAshJAIYtg;IkG~D({Z4pO_+iyZm87 z;&~3(iNhEdM!EC>sbEO--^^qYtc4Dp%NxA{RDB1UnX-Be2v}yfHV65_^iCqc^$%BW z@B~`CyJss>)1pzs0BJxKFKU4F@!@!|3mblOUgFZFq;ixnSG{%?EAfnAjAGu^ZRnlJ=8BT)x;)SmvY~2Y=oqYOi4i6K}R&2xTDMcK)`|Ra#5$M6j)JOw6I{a>{RB@|go4_OL%^V*-%2!j2GGaAqRM-?)(0HG3l=L-c&U00%!FNoV z5QXqNV$P>&LP6xJF*{xvI#Zj^e5`Re=UsTcwKa0tgC=XuV1DQY&otJ22{3RCGR*FE zZY`kNPUZ-=_DG6M#l3*w718~V-D%-gao1ApIf;DEH#GGbeiw%3qU-n6rm9$?m?=12 zl++APh)os~tHNSR8rG`NxD;mp%I*Qe^o#xI5>v)pJ(rb|UNVO-{dNsV@$O?Q1WWvm zcz_SD?G-;^2*pcOlH$`sqcRirHET^o=O^QS?64v={4nj)@-?ulcaK@DQfbHhMnJW( z`}6x^(nN0alDTbOrJNuEAe3tP1u@W+mhpZ6Qq0ncX-oaJEr6R((c6EI3FTuHVR%TL z4X`6(P~Ck|jsI_8N`CgYHX6KZczAOp%5`wp_1Nh&6oz6ZTYpDuwW?WlwewnEO3Wxw ztFtIjx>tS?l^7bCMLE#Ol#4l<$2Y}gz_?75Fon@=FOl2i-qP}eMkW?wq@-7CptmGB zJ|jfFlRRRhynRAqwN-5EVIrp)&nOVL;-AOO(o0iim7`6K?w|{xD4*o5&KSfUCheu# zI`-_%U`WSM+kcI)WmZ^GK@SpBg0j;U07&M2c{kBfMCOzNpCgBekvV%?hi!3hb5uqJ zxZOgymgH~9%8n{xZQzVQaBJB z{5-_mC5eA5KBjHhC1*aFVzC(Cdm20`(pi&z~L1) zh9&8_Hqstz?n`4P;#(;o+e@88mvILVHU#Qpcv%fj>NWzhUmd}_!|W3iNPNEZ7&P__ z^gXGyXSv*+wv6)V9Tb`nA36|S?WJ3Qg?vxOE_(H{!Mg<=m|FQncLZ|T>_ID^R3EhR zSx>mlf7R~Sj0-sI*AVc;`INo@S#kzJrY!$!NnQzONd@>W9*RVN5o?3fHJn?iWYe#c z7vFX%FnIM}c+L+taTRIpd zNEat@VT8+F<6<}+;3dm}^`u6-{D68=(C0ki*!Tlu(o}ewwd98azFDT7BW_DhXQ8&F zK?y|qo@8CIBtt2CuA7#k^b!o3vmZ*~?O$S1x7bb$A|5;lze}9M@A7<6JwJ9$Fd(}8 za12)9wzstZea(kUacHEtz4kEq<|OR5<|!vWmGQ5;>xp&3&fQ#9R%@qCw^lqI+q2>; zmR8sNw2EaJ=e?3JYdY&1KZ9y{XA!pQlWn*8J7rvoq3WA_FQZG)=I&s2X^a-IAD+J9=L}RE&1-%N3JSq_Q{qTbCd6GKn|5oTTh%vD^rV&3f=9UaHOed%{El7T}C#A zDCvL=f*6@L{2NN%&i5)!gK871S#jU|fdXkVay+?LF3>bzP218XgWX*9|8;g? z+}tGZY9i@STHl1%j@ZJgz}-csF_QWILx&WBaF35#mJtr4^lFyJD(x0ij9q`(O8d83 zUi1BLjT!RG44lo{C~#OvxJty|2^Q>HHKv;`(tJE8Gnq8y2q$3?#6Q+W}rXHhqX z6rBhtt-YyKdO3{Ie&NUdhIE~2WRxl(nswYXz&8_P+duI}kPP1b=FG^JytCM*EA6K| zwdG-QVvs>s;gr%fTB89mbkgxUVbqv*<07#qWd8`8ZjdguJx5%`9BPPgjk@BI+yfFo!j@ z^7ASVywvZ5-Wpzoa!U+XNzmwn930D+6V=ud;fJ*k)%j=?-9@J))a=uqBEOQ3+Oz}& zOJk50bTct={RB!irNT)%Uj-*p@;y|~U+q5a%HkpKV$K71u;us{KzWc5NIil#H>L(NcD z`2Ju-&(Df@S{eW*Q0e#23{^S|{sP^-#yYiT($>!<%-%hk-&EabCaQ`4#(YTa?OaX! zuw;VL-Eo|QMPb^`diHvD|HqC$q&5WJM5kdm<6>Ny?R7N^T}tI+TpdYO3-+n6jiR#- zh&zo%X)fI?|7_{oio=dU-QVUS)i07lMJdtER zjc|HOQleoE_vz>jIZluCCCX6RQhqDx-o3zx5M)CD!q`yOIrsy5DFeSm(maUoV9X3o zn~tqC6XC_v&We&iW^^UnQw$^_6DF7xcb5Yum@}Huw`}~WAFcA3MzHK;?Vw#o@TJQL z{NK9F&q>o#`3Zz=)P_#iQiGCwmg`sydx_`kPb_z>O_;eEN_pyinu7<*aVD6?8%@_$ zRZ~pO`bWwG!a?jiDSpab?LT^mH-23^-7X4+eRND&RN_AiWW3WZ^ZEg%)7S9`b-EpG z+0O(Yf_B?}3(@&(nqt2FuJb2i372)6RH@ywO^c8XH60ERIpzU`q2I{kbFtu%o72JR z^VSu)Ef!uvaNJRBs95F&QSE9DJizh3x6~{ebX z{8%c1fAD&2jb`+Sw97h=>+37c$a?P6dgXR)yrp2(I@c+q4}*hKR;)?Y8s@fDL>RP0 zTk0fGBX(Y{DHoC|Dr~ywfQF%nwJDLBxi!-50FTIc1@>?w!tYx-(o)04&b< z%`2V?o7VBF;>a62Md5d!ua0l(ov)jP3_bc5DNSsYhbch*rKRi{P6+uK8HR9LDg;LV zw>}dJ?K4uAY&v^cML;n%8aLduD)~o(UGFFSGr3oJs+EZGiT(hltd~Ax1no1SFMZ|) z?(n70xGZB8eYGB!`VbxyL|I{PUVO2OKzgoVEJ?l!9vW8s+h@9jP_W2NpnZn*rO#Ax z@wc~Ib};VCP@5hkj*G6VSg|l1TcELu!8&AC%$V1T4wdK)mVCnGYBA0Q{gkk;DJH<( znTVy=68bFCAWTO%A`|#JyC1glB=)OR!dQ%kpEdvGlXYPBp`52I4Jv3p8Ca*TzsUMf z+M^^o%|E!-httSFyb)|7%Ex#UHbtfJ7RK@^1{lha%5b@p` z8R;Znj5&mcO`rG-U(mj!kDj#5SM5aj_*kO6rn?164KIXUD`liNIfeSNgU5U9=YLZL z<~>Z`1+l2^l`o8~@Q?+Di@kwMufoRfMg*<}Pi|#yNPkP(@rJTn7GMc4&6Z|)yIY=K zYzpj%Zyvubo~80VpN|kOA`TV{S{+fUQFnZi+X&4<?PoWqg3j3R|1uzjV3$lDdS-7S8u;WuDmfwJ1s1*h*T&YkQP= z*vvZnx^+^uZ9A*59>1azr2ibrAw{)swnu6Jfx)Z9EcUb3Sb6I zCP@DA>h-8b*O4{+@MzaoOiB~zGbFXJBM%L zt#J)0Ba~7%?pbm|H9Keb+$mpCtvGb(cdPTFLolQnghYi|vL@icZKb;MNn0N;SCH{^ zj8V+MwjXpDAtK=p9qNRCf08jUEEb@7%ZwUg$2}C#Xwm%pEmw!aMm(7k;riG2kmBwJ zgFyGtsY=*jn0PpCfG$7_@H;{C$M|f0qbI>24X1I3?azo*8lCL78ICy^M&7y*)@V#g}1@a)f-~ykiC7f)M=0SF4gO?l;xN&f8o`bO|rBE%zkSd zcUkayT$NcwM~LCwrf%kt;DHf~Mk+k4ptP*Y`JPz*SqtfrKSoFv1c)Nrn-nG`z}q38 zsk??#_xK=5pB#xoZZ}qiG1DCy*`Uf=WvE9#49J>eaQfk^o zir(<+#4&vD)Xmji!}NNk@b;An@v+P%F%djKeJBgTUUdCU1uP+ga6U;7;#J0uuMReyoA-a|0=?!Il;2UJl zkKWBd1xu`~0QT171AN;p+ItE&>eOy#VqzXh8g#?V4Mg+(%)Z+&6YSn?^#>vBp}xV+ zYTWb@L6jXKV0^UtRhpEmvc6#DXoHpqemJu7zejT%;0+=m6k8ag^5y{eVHMf8LRvT} zdSWJRPN93-lfuRy;{+#T+%$;d9}ZGb^`^!EUR}S(290cmmn=S0Eu=C?zIW! zD;i$CI#kRjcCcfV*fH*yRl1xXeq?E+U=xxN!TQW50RTFihG3+A(|upWsvT!p;!}Ho z(l3hFFFhXd#9};j$2xn zgozo*XUCnih@|AC+<2KCt2=ntokQ$p$DxKnq`=C);>eoDomaDwT{fn6rk3TYkxxz| zNot_j%Ht0gOTF<=ET>ZIH7;9qH@EQr$$CoNm#z#zv!3byvYt}swMGX=c@4H_#pZCag#`{XJVaKj;VJ)Q5Q8nhS#!#Gh8+dw6`Js3 zYt@WX`A^!c>-*`MMSWT2rYf4tjUnO2al3p2FjE^2-HmMSG?Eto*0_%}+%ev8 ztF;qNBP;K6tm(Fh?2Y>GU5DX|*p_x%RQLWp54c$Sl=7i6Bg3PCK%-4(H3%pgtuo@N z1gaUt?$vZ0-vLH#E;Y@ScjppEVR|Ci9J#jCn*Ukz`r>j(eCF~nPkp_Te<^T{yQnz0 zpa0plc~C70Y-doy(Om5SL-+2!m=+%nao)DJ*AS6G-EMNdMjm>B<#`u7t zYDrw?^(rDl)bEnb!DptbI7BeKu=m2I$!nr$`W{}YFAAqN@;vv~Dwt@}JQuO4{Q91)#O+u`=lVq}$MtP% zcd6YmkJ3=7sfpi3$?}1G@ZtQKqIuw$xweMhc&VuV$JjfFLL{|}L?m^Lx6)<0C<*hb z1Yj1!0aJD-U6d^0O?Ot2^BHCYbQw0b}d<}ks2x%|CB5E878v{kY9Vj7zM z^q{*uJcBUfpwjoNgZa!4K7ltNmaoM(@fL22XGYdI&bQ`j0^=KS2BJ7NNJ2APH?aXL z*}$&8QZBZ&h))q`2xpQ}QZDe3{vHJZ+hyTcwy#y50PZA6YNKSlcCi?J^F9p%#ly+F zOy$V+pOv%Dw2FAR6ViN0eKR*z)}45povoLXXYY*Dl|@fsxL??l(4A3C|1WQ?P>CP^ zkQ(2|)ffw?vJHvaHH%D9Dr?)Xlg(QCNdW+0p4Nw z1+Xk<<^@l|{u3eU`>h-A|zDA6WR3g|m`CZrj!@>p#eh;e_I&wGE0 z>0_6j>9s;z`L?16>Z-{1`hYvqMFNE^7q}z6m8osRfV)j*j!`XwZm9WTe92*vLe#z? zHNn?WrqO&}Okd<0G%8n5FJ_LU+_ae+QHD-7pxz3sl$a|)RFPcCLFJ%rt|!_wEPVkJ z^cpiI#rx4maECQrM@;1d%d?c7KuLs_iuBTKd5(8jDbXNkalsL=VZpt9zy}YF`>Ukil^L6l z!56(XiI%Q|=*Uk@u*Jc305I&iGqRHTg?rl#gVNE`L6{Z6dDdrEv@T+fmx)HD04Tu^ z7^`H+iSHkuh5McZOppi$Bj|SbL3&0LyQj9w2T$V;SLBoYriNhH$O8qH_gO2{>}jeZoK|dh#In}t&y{>* z&P2FV6^RU+IoKyO)wk_D1a%EMh)GP=Hf?d(ET!H*HJ(^owD)`FPVQ*0y7!DoL+#r0 zKGPSw@D%~z3N!QGfayYmdi|+OfkH)Zz+!K@ul>=7lZw)2zyTyvu%bk$;Z)V5u9G9g zb5;A!!vd8FGWJ~IlG(0l#-kQhSms#`7ti$pSh?vYw6~sf))OtlJzl`{=eN$o4Fack z+WL)7cW#=T-#1|Wvd4s6KY4u9>`1h7b`xpHBfy)KZ0UC&pOl=!&T*uKd@|JXcvS$F zN5K*4CZz36Ym3a~8LHgD@of-bNMH^1tYvmqX0#J_xmanJ)W0)poqg(CV0GUWI2_QH z{birMk3A_)!1Yr982|VBFUUmZ=ACwi}tj(#zP_%!_<|ZsMBd1##qz) z_oBT9gl5?fw3T19snbXL*0Q^|CPnyLh7zvM?vHalAn$(OL0<2qz|dB8v=?cr6aYow z6gQ5C6A!!z*4CHrtCZTc#B(F*9B#X|ZuneUBOQj9EGJaJ=%XU9U%vcVE#dK?@sZso zhU^}D71r{$T|P6|CJ8ob2bw?Z?AhgN`*=<& zPxHr7rGAkWdILKpadRs++7B7fOC3qCrj_@Y4QAz;%2nw%stNbIq@oETI7;q&^;d=F z=g;|NT_4arQS=Js)x>l8dO7KSC7NTvqbbo5`N%Ci=VAP64=zy7L}e4C|30So3ZUGe zZ&NiW&g`~9Hx`vMJaRmSi1b}WHYmX?AZVy>8$1%~Z|?Tq+L57Cy5#qV%yR=i5-4yd zjTpAVsKmFzMGtG0@vpR_kdFg2+U|dV5e}#$dk>~NfqrC9+6c^ad&W&JS(slBjX z#-PQ_^IvbrI&jH1NMcm*`qsOdYm(@b#nZUAUHY_KrrU*@Ja-^)lP!0*hsE$?OH4d?IYM21E>#phx>7&c$^{6|?22_YNc2M7UZXb2P} zu)r~?(oXJBqJ-`&zb(UfPmL2+rb3@0pLO1k`<^K|LKk#A%aSfv+^t6qJ26W?mR@X2 z77iB)-_sFc@?58mka|+iQ^LMLIRzF6WT?~Pd1FAPM6egOczsHpTbu=d?~IEp zINN!q_N;agu+Yi>Zkchdlx5ZR?(&O!>kn1Tu=m$JRd`Pf#X~scdWbZOEXSnIPy0Jb z<<^JPC9W&=Z6+L2W^2lxM7fQVDc|RU6_ew1J~W%-&p1R05XwCa=kWR{3v}k(l9Fez z(!V*x^Q@;9a)+XFsx?MJCb)Ug+SHP-cGSFa`mu$r1M7mqM(@2>4ktgicT+@#F8Ken zeDW9fN7mx{-MWBqWJ&H2D`-Nva#BQU_Lche^@LsiK#~|Pn$!FE!72jEPJvjhsgN44 zXJ2MV1ZA6ns!26|Q;xNiCavPLGR?<{pRNR&bQO0|Se?!Hu@q~!$h}p1XNIwdry^07 zkc)}es4m^z-H&y5u!Y{VyITx2pDZzM9?3hMQR6CG8U;dU#;L?&qVM;-xM`>b*G}4Acd}yho08hk1g`sCuNw3Pm`%iE&i=}sB=4+*7Ee;>c4-&&RE@1 zn5rkZL@uy7atte~bfZnCJ@2+oZs*VlBU`A5d}R!WL|#Za+0N!?-oavH2Yy>D$K?Bc zLNvnUVorQ3>6UH?QYlYqV-WrN>hE*|9W;Rk;L%m5{y$Gn@_8E4U*2ZwU)`dhYOmEn ziOD0efZ{;lzZ|zx-?^?nrX45Mh?W?h0BV>ONU>1+{!4VizIyu)BK>3ZeNu4^q|v6| z(@WB2G|JzCxsBDXr|s_4&T=5XQgo5?NUvD}urMoGqE)>k4Qc$>l;R4!OCRj3kjqLi z%Y{vlO_pbwG+tFT4O-f&;{4LjQu4)o!Rxa|m%5M))@>aowWiNx4hH7#z3sKJc;9Xa zgI=S@l5w8mj`%Ro;)SewBlHlt;-(m+q9VRDTbAQ(0iD`yOHe|mcIw5mbie(rr3_{# z^9_6K%u3#kwvi*}Ppery6zL%YR0IM-*a;RT1u@vDnFu6FAfkeJSfAn+f<;7*yE1=u zDC6<^s!3L`+VgE$(5Oh`Aq!4jfzO?hCZ(X?O|CEBO(BJf2ICHmp_{1OP@-O75hwh! zAMoej&!%C!p;i}IQ86qG2XUYsF6k_?bAi8stc3Z57v5u0LM za4B7-J!lRuw(4&q?X_=!&G5#?{PmJN*z~va8iI};HqpY;uFjc@#tH2Vi$5#W-W*$k zmjK_PlI--dm$8YBSC#^nFonHy{NL)7^Hd**%u_ya=!p1JG}cFeGe zQS)rD>2mW0JQNP9k_l@Al z%87?aEzX~DM`KfE&l)psKhorW3|l3`bsUx=U$gGXee0!gF_WTV{3CILeaL`CxUAew z$w{Y#xk7+eO?~h=x#U9j^!s*2A%!C;oL?3fBM|D^baZ(D;6JwaH${!0U-W{(A9JRfIXD= z|2%gMynLvs@&P@n-08K+zc1p^4Bq+8G}ekURwxeOU`c#WmyI2a;nn6MzXr`& zX;6!@lz%2FjNUMM5DKXobj|*%hxAT4LT1aonQt9oC$>2h&xTT^ehbs-=f<=`1@TVd zsHB>3LqwDqPY+Ol-{3Ybh(F9d^`418=wVq;Xpg>+A<-zwezu)eE8SsSrvh$kOL+;( zg3r*~j{esz}S8=(!(N!3~lu9Fh z#k$ZI2)4oHUd=#Ay#ZmfhQjW1(aUz_ zsQ+T>=X4R{w+eOiitLlc-b<6|>c&}ZXLp>gi9Wp`ef4a`Wym|`I_EA-540fsJzU2P$wX9{XK6Mp=lcu6`mhSl zt<%5xuf3a@35p#Q@SwX2Lq*|OWs85c$wb)@kof!z7ya4BEllUpoUeVL&v09bBl@U6 zcjJu;heQ=a%0%_2k;}xR zOaVgipjJ|NOHOgDJ8+tj70!QvvDgQxa1%nI%u%4_Iq@NoCw-LuqGNcn&g)eD#Af6W zZ+76}Q(;ng1{NxeDn)XLHo<@u5qyFnNfo`6YG{6Tm?KVRw&WH46u2gUw3vJik&a=9vl%@AI~@M zjy;swy_yPn?p!`AUZbji(m{LG*=HoGL-71_n7w4}-c zPeKn7?@hl3VrVHgH-3;m2K}i7a8V(&5BPwi0J{!jq69kN5}iCRu22ynZ1RAog6+df`9_!$KH_FlEX@PAj zJb!Ps`t}`1AwTpTk?SR(tO`haf&DsO%#kDvPG3e^W|7(@VybBio;QYpJlTk1DAH!? z+ap^Hx>o6ppznBx9DWw&-Xgs$phAgPbYvk4q>X=l`l-rUlW=eN1eNLi? z5^181!Ix9#M-RSW+skOZzwj4CmjJ$KLUWBneeHb7q7fwKt_Nbn=M0a8+ueSd^?ul( zJ5m=pwo_klKW3l5b>>S!8a>jHyGc4rZYCr5rFnIoqp$HwXcta(V7lwtIbLDS_&W+f zwaa&|$~j3BH-*SquoCk^R8%`1N0NkIlt2M*?ag?wh{UX)(6fkEYY0{tcjyLZ6lo}Z zgr>ooLw9_KsFilRL$xP+zPudGq$>R+y8;Oo48bMRBrZ4fQN@^z6XbpkvzFN{fFT^Q zeMqjI@34R)8Y|Q4-->5ArYX0r@(snKHFUZV-4ghAXlb6Zfu|B_Zdpzc-gaDoQ=}=N zW-FmCNETh!R#c}`Thbg<3|&WKQ$# zhJ{mr=G5N+lxLAo6q)6MEQus{x!%4do7KjJo1sVlEr~1b$%VU*E4}nIa!GGr%CND& z-IBC;K>_f2Ed`+N4E~KLTn;benV2%P&vk?JHBVC*cqUa$l5sn!=Orr)A3(ctN8KTa z3aguK1%5(>4`NQOI-1xSbHEvw`<|o0Hkq2_u@|0N=&03a6w`04P_%4JA`^f?O&_<9 zgIDwlna)rbz9QFlj;|@_XWCp#I3)%e7%sVxh(r{r@m*G8BiUz}CEbFTBbaUyO$SPT=ztSrHT;;Br+i4ht!WZ~%ER`>&R3&X=JmIy*vOBIEq`%b(z%=@ zD1A_)dzwR>vKX%deX#K3K$Nz=r0-Qm-F<0%X#hE{7q`W^^F zMd@F)o@&DqVFzze3Kv8Y?4IZSr&@hYZF>UFsO$*za1B+d%<~SG@@;o4 zi7X}xTj;DI4wC{m%3}hb+j{fl=5$ko#H9iaS+lPQ^2L{;!Vh9oq<>f>Y(hwmROMys zCLBZg!VfKx6^b_Ama{x~OP-wmVr?eSwKc+_9W|DP$vGDGTM%5%r?z-^M{7#JrQVmI z1T_#7m3tD1zcX-qTj>wEko;3VT_%!mH~qyZcQr@A%cx>chHejmj*lx7?c0HWcQ-jy zi@L;e6?=T|P5q`Bk=_QPZK)z7Ja_t__uRdm_Cy4SWU&e-*f&hL>kX(-@0%H+-qyHm zaL4KClvBkEwI&;pWkyMs;$F~u?#DP5bo3>WSk0En$$fLx!i@9A1^9x}9Uw$4*B3oO zpblCd#!>=NJ1na*IihKe3vm0j2QW0C!p&YzP(owI%bOp%?Y+X>`&%}<#S%60D}OaB zq;m@w%t#~{g^SkynXivA^#6!5`TKv>VhWDI2jDUJ)11d^0mLmI4v=!{!&yc~z+LNp z78qnQ+OUYT1@7g8Q{7jCzbyR$?ogIC2nW_vG}|A?Q)Q-57Bko>9^4fEI+IdGvH$`D zb94bOiQy?&z=fF-X}*&O+qXhX3430+5Mtceb;|{slyIVCs5j<}IJ1Lb(B)-Zv#*Ly z>@`{W><2f-c~Vy~>^B{}nJt+>2cV$h0O~%d>enTI=a5s=URSW!bNyfxJ(x<}em%F{Jk$~=QzK;k-Sq=N>#L+n3xz)0tEY5AwSV%uJ^h{+9M;iw+iXhd$Abb zB6UM-+%~G0PAmai6WOiMJuX=D*U9W>-B7s5CK;KmsvojHb_XV`m;9Z$-z|g)V<7}e zQexx4VxTCXBv7h2x}`MSd=y9NQhucCNxwo`JTbgucV@L$=ylb~O#6B{YLaI*JIwgy z#{j)9W0vwC>P5%OXXDH)ZQdUP3$tHh1v)C9DiocHvFr~LFJ|BQwiMfUKAboW4%->* zj`F{AR%Y|H0u{a{V|#e@^?L%JT6JG<;LRyxbt6R+>Yo$#^B*1WI?QU8-JJs2hdNGV zf&KU6B~{l>+YVtkwk`BF!*+uD+yxYAZ?z6HeMj_#*0rsq^7oeXnG2tfsOjeCzMzF8 zfdYfX#HWU2&11rmBtj(n=ay|&epj5Il7TEs9dkGaA>3RzG$F7=04Tl#C)pg6O(-}q zw1|)?e$++>@S4g*HgJkuC=Jd$Nh`V}Y)be@1Zh21+^f-Ln+p2534W~2zJ8|aZiMb+@Dy4}Dtwz6L%n+}&e!^J3jY1u zqs^EdgC1P;h6UH<*R+Le082Q)FUydl{!mIu%-gg%1Db2rWg{3q18_ktI5XA3Av@%! zb>Ouk;R9tV?$zPlzjb)PdUZ7faiifi3rFMaG{}Bdi4vWB{)(bw z(;p!$R1CO%y@6rwpWeyFL4BfJHkvpUCfOnOTQLu|^)p|HbgE2aNZpYl{-wc0p-{nI za7sQQwz&}&no5<~_IqP(#d&roAH)SYl7?0@*aV-M)w<2;Z{*9%uXGDInmdYw;B z@NN!E9(G&fwxzEu-)E^ng}#2l7%xIs(Y3mUi1J&8dq3&7Lz#KvORL|)C4yLQN`9lf zILitf3xTCjOEbb#`Dv03yHk^3|Gh6%!FLuI*JX2^E)qGCK z>CLBG35W22j*U+rkozyY=LQ3R#a3|-AFO%LP8d-+>H|O8+5AV+Yyr-}2T0rc)4Ys( zLB@WrE%k{6pGInWUhjpi7w8)?ryHu!xnj+({rNLbpV(K`2>WWbgi8s05w)V{iK9hZw6m@UG1W$0+xu5S*g^cO+3gG{FyG3l94~@ zUVmuYgW6(tsSbFy1U^H)i-|hEr0% zlCjoyLe_^D!z>%a`uu8p(1xs~E5q>@_dU-lUnuj)f@U+zD=_pg6&CUK-5tkLrtAJ1 zkx{4)QVZ?(EA2G>c5N?s?gnNga=8CBRDm z=O|-MK)Nhd&0aHpp>36|@N>}eP~9z(^-pusCj58uhr&O(8ZK*iMpEQjv*ZWm4Subs zw*5M(7$c-=@rhx4d_SSsb6<=Sbzs?j#Hi`<6(vzn%|0mb-)XdMM*MrhW^46hjn}w- z-I*!aB<|zF6%58MZ%Om4f>a-=zTsCXLJ5}Li*j_7FKNL(EGKE-7v^$OG;!p7e=KmU z#3^xz3+1djlxm?7AYpikD{+_zsxx6@pktV@T0hqG)_ja^_}_U%je|k`_dp8FE8+tE z??6iaKMthlI5;ykt>~)xG=C{oNtCIX3NZ)t^hrNtVlO;UTziNCp6K*k6@zDbpasdWP#RF&f8h7k>-PxS4m2<~Ykyylpuq5zU?xkfvhFv`}ALYKpFU*KRmU z?8`J65)gi>XfQ=ENbed_GPHCfmwlE6Wsr-@qGgNsb3+=mTu<8!44r(|%QdZkl{jZv z$1&*mB2XQ9K%n?PmRL}hS>4%d{%LR|?I+2LsWnu%w}W>@caa}s=*;jYf9ePJBymYI z4+w=Ot>RINVeLlOBeUVhCK?x260tnMXeNqMvn;PXI?kbtpv<4Mq0lDzkDCyb zP5RX{s%p@C!?ZSr*||Bf8Vx5^ZLtBy*tfP!-RV9ZGCgEV^B)>8&U?VLW>kK)jFght zF*8K}JZ4m}@4oEcX^34*1sgqK2xXO1Qg#I-K7J*x&1Bgj1vZk0N-%xD`9Y|Q!&%0$ zSO^V^l#UP?MOiN%93;(y& z96=YyPNvfl>Pdn@h6TN#1Gxbk*sfQPuES~6)Q$%IG}%DK-eB`e_i00lHp#&lRlX`t)MZMTrIfw22++Jzm;OlYEO zK_b%yRp%c%&?i+c$zrpB<9BlGNKGsH=OA~l( z*0F!g-(E2vTzU_ZAn8+uMhlbysC~6yy;1ic(b1%(R(MS8HQ~*k0UZ1U(S=fKWZ@B? zLTJ+JjC}`It2cj$z)_0<3udU4rl?Ssr_lXHcWB+EV!U$7MRz7XLAqJ8!FoGG))UW?dv8a z!eR1f7PRG~gMSXr=++tUWg+mGfsxDM7Ou8TNnA!5?>W}=aCaC&wS;x=M+-+#!8F=M z9o};f_g@1v-g6M=tky$!;o-$s(0eI}ZXa%=nQ<}{*asmzX#AXJpn%FTW#&ydH$K`R zf202`Wx~CrGMlkQC|`tjCfW*dPdZR7fG3u#nOp($4{Bs6@2#BMilZIsfcXb0f3M-S zi5tGF-)n=HN7#iqv}IE^23l^@8g zcTuF83cer+#|1-b=?dQVa(t9O^(;H3Etm?gJy1!d(#8^~v$(W4SeseCsy1{poQhuX zN-ZX@c@y4eKw|*skGF~As@JcIcG*MsxHZi^B}7O?wP{oBYJ%mCihBpO0w|SUl_Re1h7xZeUF|OigQgyIxVE5M% zbgJS1wL7;LP50tAXa?iInr<7BI-w||2Pcco#Zbt3G>PsI@#epW#DAV{bk1(3r*x>N zyHbHeA9ZlrKZ$D!h8syFZKh`}vPG|JH4KIMZ}q6DDJLLS1gpllK1g6C;mR zyGj9vBi_hmII@f*!*&xV2igyxK>enq4Qb71x0u=5yy)s;4S}G}xhklndks>K?^C`m z(G$2j_9E#vUxthMq%=qV!YKb?C2uHdh=$B0mP|WfV**h9>IM@%m;K`D&b_u6KYQ-s z+kPkew+MVw17~~Eb9Eg!BB4Sq9dx4fclcXIu)?96k}i>AAJ-Tu&c)k_K30~$TBiPxJe zKj(Ob!Tf;V!odC5A+(8SL;DSlSLP%5u+NaWRvU_7*YhmfU+G2};y@tyUofK>I00SX zSk<70l$`)KMKg8ZR`y#q3$m1bPNGa88+V(!f}xI_^>=|OQlUqcgN|Ee0pB_db!)BA zcKHT{CXMZSSH4gXEYY4Jwn$_#Y1wgBU3w`KAwCo{9n~Zlf4pV8@*^NZ3kO~`t53b5 zIS8?y^U7M${G@xya$kwFz{tY~$-{LraT|r#xZt&LBSxgfQ^HlHMw^Dg#8$x-Itw6? z0^`?4s_^bO>U|leAb}^vcO^$V_oQSC{OOoyA=dOJKs>7;`F(2Ej^ig+i|-2^+L!Wp z1O%3R5O3l!;~d+LA_oJkLd0<{l6V@P6pbObvA9#Uku!s*(L#shq!W0Ys>>=D4*{N8 zSc70HA8%G?AA3HCAZT2kihcRLA!14+R8)>Zfc)chy+nxkbc%BJkAd0Q(M|4+_x>Dj zL|jKzO|qd83=t?`29Un^p|WOdM(2EUuO|7!QmfWf3JL=~K)jp491cUJ!W`+HV?YB~ z(jjS!o9o#rwP%hX&$_bov-IM**P>%}S>xy!_VK6*8_)Mowd~Bix>SBPGNgRh#oDOVMXnmtpuVs`KA$hrlx0}l2wZo-5MhGl| zq?fLe0~yIm^JQhcP|`KKvD^DcR_;t!b8Y;&Hno$@>xcA3!s{`d&s>YC z<}@7LL@>`R2Qw@TI=doTG==P`5%gky*3639I-_@K(oJ}XVrqDWZIt@@BLJM6dfgSy zT-)E85jofPTdOmY2$Xh!qzeXht(iHJ&NT z)6Y-i&GqXY)Q;3;?l~`sTo@YYC~i=da7rI=g^*3aKGJJPQ`=U{p92$2GYd^TSscU> zr*mW(L6|qyC7T0gpF2=%(+k+Dqmh|^2-)Xpx`i^Mo5#?hk_#E|7V9!jTOo?E)qsd( znEq#eECoV$qG;DNsUa0@z|C}O1JlQEH-|;)tT&ANpx&U>s%609hut^kOITj9|>R-ZwYP=rP3=M!L!k+_1NjC<*f_dXwMs^#%4x z2go_LJS5>bKIpib%KqTch?*xZJl=1ii+=rC-TntqJRsX%pb%5MJjyvb`9wv{ROs$H z$${0;VLBgMa}Q6gU!{moG}0;)FERB2BCAZDfQ4{K?fVH7%J+wh=b?P-)6?(X zRG(T7()>hhVd!K>B&?T2{#JHF$NjKo7xNn*=xekDx3=waL~uRp7!MXvv~Be1SZvOX z8uj!a&+5CYU*6A}_lb;gOOFo>$mz6s+*m}YhWk*oO2y;R{-@pF$+{nf4<4Efp@kJV z$j14vu3Eb_U^rU!&XF?BUn8I6pcrz!*HWXhIrlo1SyI>ewg1g!pPhi%P5I-;c7S@* zfU+Qoze6m;s!5T5H111Xm1rM1p>Q<&Dpose3`6Vy|K{6YLEIPsT5==k{U@?q#bH%*PYg*}KAkNJGLpDAp00CgB3DAJLY%unlCZpL`+9KHetxA7^2Wp@L z-&qCgXG<6Yc%Enk;!8P(3D(TqqNfHyvs@Zv>Ydv8yGImiRIKqDpR}CpWbF*iGokwf zTd5n)Z$#ZmGatFhKYNV~^t$YK9*$=R*rd$o0 zQx9)aoz~rB9Z_7S16o*6;nQf93aAPwBD)sYly=%U^>bXAjK4uo9^rXjp*4hd;iAjI1%xzAhFrl5+ zVG+m7Y#eCEAm!x3ZSyP$+e!zXJ=)2>N{D7 zm(iQLT#KN`8>W)}Re}TujlyOEZKB`8lI?aDIR0h_!V_7&Q&Fg7^-b97%WX0}^kF+m zGm(>oV;?J^n7Bi~`bre?E-XpaCnph5aP{@S7cZIn#=jS@`+pZNy>kcCi|dLn=19nb z*sbxe@y)H;|1Mqu>2=(HFJ2B{;s0K|d_js(8|=C^B}CB-KKPk5Od#m;JAzbk zW1kz`+n+FV1=V8;C*`0#uqa3sdhJpIKr!u+;#SpJP(M_I5)MYrLW9>fTypW3y(asA zoc5r2zZA2Z3`c5uJ`yNe9V`thd}xZU$MP&^P>x`Sfg*269-zn@f3ZWoNDK~rf(2p} zS{Z@8agPI5hZhSsmdf3>&g-`ys7{0f>BDE^n;YfPVQ0~Z7Z^0+B*H$T$3+~`Ugl~x zalWxC`#56Kb}^W}H?%NfgY=nrm?7r%Ujfs!?Q&OT%0c2u#U`b8+Xy+QKFh-WkN}R4 zv5K%;=_5;5eR@x^kb05Qpqufz|NhB*(>$^7*4k)iKcvqvK=uRX5Uw=YX?q9^04<21 zTuD{)fs=k~<02jUfmiy+8g^Ezi+)!Zj)0IR!8!6$@W2t76N6c94-fM#lYV`8wae9p zR*nm&>_;DNkT~yOI}~7oDv!9t81--Me9HmYKEc#WZ;3la!-H@7x=CP=?ZpTL*S;lv z-2oFDK5>F5oPyqdrA=q#(Z7GKsQT3O9hIyMym2EtH#)U%*)V8FdxwRi#7om8EqHWii94ZA(O_D?@4jZ=N#z9??FA(2rwD%(2_$|8{OG8=~iKyb2h zq_zz$)DHTLn-bTA=&1y?F}+lH%7WR1_1Jv~=qO7X;}A_18_U zE<1w`JDqH^qdLp;Qg&4&+x4uu2zvV?AME|K2xXIiQT9FldQem zw!DJwL_nlLueE+UPNVG8P@|J!$QfsumVwlb7o zKK5Sd?Pu9Ltj#tKz8=%ik3BITU{kQDw0->1jlbR+im1?QF9nY_c{_ zPZat0Ds}ai(SuVLueX~L)!XT-*nLMqSl)Z<0ccH8AF@h)1wvj^@@3gD%%kPk?5P&d zk;hKYNBo|vcI=*>n%j4)9}~+eiQS8H8!?tih63W?Vsu9evtdv!W?(VLGFj=kuSjcq%jVBgySPH}dTxV$3z-*Wcr3Fr?^U)ZC!4`r%7C}ePa@3xyp zbLpX9fKuNGjs1X%N?Wfn)*g~tZhBZ?d~0nZCc25BzGGG5Bm8lI0QzaSbn>~e<)(k* zlRf4+93X19cE&DhLA|8)E6bDVnJ37#jyuN=2alobNe8Lx`fhW>cdGLnP&b9M-6v8AYc>Ria$%^IuRi$RytJ?A zYe8C`B~v09Ox!QNL~pcWV1Gc2Vv#|_8!Vyi%1g7QU}y`j8n@o=OWT*dRvR~t>?Rx4 zVYzE4D<)86dBm$s)2H+qI-Biwe2SLT=*Wyb^p+chA|U_)pv}X{v26kQJK!hh1>1*q zv3p6)069z-qBbpS+r5V;jAaM2Etgli&mHT%SafaYvX-G|P(x`!L&5X53T1zU+mXV-HkeMsBPCQBNBXsNgMp0mAD?K1s%GVdV@*H#k@29tH`8A<^jt#xz{LS4 zD;GqD+Z7C(RH7MsG{imQ-Nu{O1s9r(7y=EkkqOR6I*7?>@*xx^#85Z@4qrIAg^7k} zt-Xnc^zefP60%YO1o6cv{CAC@?viUv;8=$HXn)Z@k?Q(cmX|2#Vl>y+j??N}pCz>?p11w`$!%osaNa z{8K1YR`B$0JCE>p5L_mgGiHzrwI_m17CSW<4jLZ)o73qjXbl0p95a2%ce!unCHWWz z{QtjI;fjB6H6!@XTXn0%D;8GA@+4a**8u-z#rJ_;LIB`gBbxt%ZrI{Z+-v;xKW&7r z9T_9d)FzZV?5QU{{r-9z0a1tX&r|?F%omefCv*5p^E-X{s8YvaA?2 z_q;t5)9vDKf;RE<=oZ>v!d$sY^6U;5UTBbgRjiY4GJ_}xp7|-?!p40-%B)bBh%Wc& ztl97lO3FV(MjTDQ=MzVjUU{p>+IoiJo2Js#>R+`D$~A*H%)fmn>~a^ylpAAkURvrM z`-ZE=_R;r@NBy2>t^A=cUQR+9R4BeLj8L8=n=TH)<qZaOv^j$tt=0UT*7b z0&r4djLKk<)oYI6j`R6?r#Qd5z`+f)3>^5I>AMACg@MuDypd{3s^T z+=Z}=_uiyopoj^eE^MDdhiDs2zJVevL4c@*bWRN(h}@b+((!Fk@-QbXhMKI^ZszSG zDDv*vAtSstv|*@;r&+9Q5=*v~5OW04+`YB$;*Ogm6+?%4=|jNkHTZuV(TAzsbR+s? zon1d6)P7JcwTRu&2Vdg9?TqG;{U_bW1D+rQXfac(aXJVyB!{OH;`X@SDEXI5g^ItPc|WVi@zv7PISZKu7Bki(5U=vIwsoSuoyzfZcNNenV1VrhHb?6c zKk&n%F>hx-ark$zMH5J(wSq;$2JJMrX1i~+ViJyC_!t=7B}fWj@5yED%oGbF&e&`J z2<8x&C-VCm?~QeqxnFYGr2A+1KTssu(G$EJsNa!YU_(|J4}Ur$f@Q)B9wAaF%RZP5 zjN$Y6`+hDkz!({v@mSyGV)m@|u51e{imlkq3mToTvirifD%Ohj6BY3V3Y3J)`Nl3` zSi$MbAv)r^TOkmT6p~TuZ}jR>h`y`+Ha99TzC_e+F&T#;J+h8DAv8l)P$3i>$p=?k zd&IX`M#3dC@AIcSuw5aQ;>uAuF@|7Ij2zPf+?+j-^Z}3Q)4d@n;vcxhtgsB~eGfMm zE{3q1hk>*e7Q~BAJr`W%y>v;Zx*JN={dzzmfFMsDNnxC)t1@scX`fIxM6*KejdKaQ zGYU8;=RIVqK$ed0TR-2W(<(Lmv*5^YCAy_&(d1%zNtQ}{Ej&p?7 zeIKT)u~2e;33`YT((Nb81O0shXu#cnCK#{{fI3h;kT+LA$tcDa*E7|~_^ghJ zgG|t$%Lsdj7#-#-boV~W+S}((uxwCQt0t!=l#pX{I#Ob@a%LhIw%_LUcwH9TVP>8c zUS^vVha_G*4Wq8X0?!zu%MoFLXZjwy^@qo`3U@xTS{<(*kE}FRvGi;6CSQr(_GIJ) zER1d$ehHFXCL)9tQ|KEwj7H0wJbrk_s_04OPBqxDA1h=W5@HCXVM%sRZ?@Vs4)#p{Q zWop@nVL~lRG&*%i!uJBtS`t=@$aht-Hdy1C`*-J`y=J^jq>6fw*i#lJtK_6HTRzBm z=NA7{ZK1*ZwDL$E4Qrnjv6Vj2bU4fZ3P$TA$l;mcJ{RO>QNo5Vqz_D zYEnf_r1_^e0-ffs97m&Q{HKvtbm1}g(_4DwuRqWAZ*6*Hztik%F~f=@q@)bw;s-QV z+GvK@KPD&iclQTw;xAxb(XIeNZVF7RI3%W^cirTcR`BrcL&+eJA+K2K3JstWxU{8g z@7`pQS$SA#f}X3-2Oo0(w+@Usk>5JU^dbJOgGEkob9m6Ne$sMN^r?U2@DRWV8L&6| z5@rUo3pADxilw^Q9W87v!l@BJ6E<76`~5sg$6<+$%)<@fhaHg;Jm8t6UM78-_tv;y zz>3&DmQ1QUaW1vLGwLCpnl1Z=(qcbr!b(n4rk$|ZXOXbd-EatxW}s+76lx;Rmqd?l zpu|Y`OGtn>-p`aYB|H#q4$*%(p3H{hI`5Se=mr z3AD$K_6JN`*T3k%%{V7N@h|VLf8@r+ApaCmw0$u*uL!nWnp+TRyEAY2^q(fo?)iK^zny_{Gug5^&aptvE@v?dey$ zqpjw%axKj>`RSfZ)kxG!paG04v|wibC+?{R+yg7pyQV!W3C4Kd5%dB#gb zVggPBV{*Cx<f=k~DB^DBqUND^Xw`|nEBSHlJaNMvRZHuDPVe=l$p zV1W#PYQgM?U|wHAx?)(^o6`};HHVbh_4gkfXfbBlgNDs%Da(O8e_vqyMi_IXYrUW< z%DUi|SIVxj4L0S-vPdrD&rU@z(D&=ZMj2LLkum9d^9Iz*tmb3Q7lw;;6AhLqEb1h6 z?8WF4(7~K=dIdA%X-0B(-Kmh-{7ZfPnYqzJ%n63KFt8D9S3ZCs-PE2D#5@G%XnY5a zqz!A5IQssAPZOWAT9qKv^(4ER#o}hLm*9~_#jW2amm1a7dE6|1CvIo_Or zhNXZLC#rn^x~@nAi)r|)X`sRM+ust;d`}PKd!{{aKhiW{!`|SDl*29%1NH_7_+S2g zg7}!V&-h!CH|u&{*yOA@UDFGz)oKu~#P{wM!}=!P8t_X;690a+F*pkhSPBIUD1{{- zMf^=ZlE%7x0dMIZ^_nkr&}gIc*ZMmQ%sMCpMT|)CuSqv78#@UW1))|@`w|rQQMEwI z2PR;JC;B>E6uLOk>}A4E^eatO>f5n!a;$cJvrUCJft3xKXgXGHc61Xd^;cL5MSaM3 zs&nz+d4v}>i)wjO?>~?I)2<@hOXb7lDe`T1s704rdb*#4p%C&vXgKnJdRhofPmAtL zaK*08h-Q$Y&~2A$1ADJj%*sHF!8BCjnmr0V877?ttjzFz5ldSA^t4Igm z3&xL8FwMCz8=^__x(!Gl-U%WkY-}G9r1e~i6c8eGdq-?u%l`CikBU4nxm1vXoN7V~ zZ#D6&@XIbyHyYUld37Sse>Z&`U_UZICRzA}8Y0Y^O9q+ZGR}Q=CKgep9}Xj1z`=|C z$=-AJHwF%Z&o(Fh2x*yx1>xQCERYc%&wM+wa8SXNq( zeF@;O8;g29ZN-Qg7jB2QmYWL9l{^t(vEx?nZn)~9lcO39nZjm>o`E7|E}W8Lytry7 zb`yRB+4UOt{ud^xlf+!|Dm3-t^2BSoHJjccjb6U&pejPik9%V{`n$e8jk;JP=B~CL zAtD)L*|+~#RDXwim?>BDzhl1g`MGKMS$>0kBmzH-MMcPe3)^EFJ9Mkc@Qw2!v+Pth z`hNmgVf2sxnR2ax;xGZ>*{}fC|KcRM;}YtBGMAFr;C_~`4%Ikjx%}wkMbA<# zF0Ba)A1hU%VRX}n|0PROAzm0d05QO*q%WmcRbV57+}j|(k}F&lCwJekDrBk&@Ol^s z;qZee*Z3AeT3;DFa;|Zc4ylHMnWgj;QX_(?5yLEFiw8H=Y2KayKkNKnK|_6?oM;Lp zNB}q*x@yY9CI`|1@Y6~=b1{=;jJb>3x>1>M)@j1q{p{(J4v)geXa9mmVuOU8LN^u* zccFbDqf#xOUd(L4>4a7UfC`^)+fA&hsQT@t@A*G2y*ONLO4%$HJKo|Mq?&SoYS3r5pheR+n&G( ziIVplVtGnVI@Yz+f*`YVJ*x84)@`smJYOOy(uf!+VVpQ|~!O{dX9B1@u4zgcE5{liQ7fK$GyB zAj)+8gIkL}b?EkQoulfsqw_R5l;n{>2tGNS46G%}0vdx^^X(LS*oW=NEO~}5M^0#z zFNw4|x|MAbLlXpMKQ{XGzN}u6>sdK9d4A>=d-EL;`Y?ZOB2(aL(jXrHl2zyv)6x=7 zvMBpgWG7mI?8(tcxo<8Af81_RFO8oeA&P@h>602gR8^k8+l>t+Ry-Ldu^){8dpo-q*5>}V7NZ-{4|8K5y zq@VmvH#J$==3nFdK&kenas75szyF4*?waB)_~X_iDpC?N5(=(^WudJ;G-}e3tMT|p(&N5kLHuTXL+on$<|eFJ2)amUp6SF?>Hwl83b zj9VsH?6B_*7oa0?SMJi($=AleDxOYMH0hm}@NXtIkL|A4QTiK$O!ZX;=jG7>0`d4- zzVKMsTln!N93wJ8kug&=IB*MheRmuV`#qmw>O-C}gJO7RXc;C;8UXLy(nub0 zv{3TIe+WgR!hqoyJYMX^Qw47qym}g|xWa|b5>8}7kQC$7%-i8q%)YtK1p2&SOf~b1 zIP{}^!8M4D;1=C>Ek|$fGDaHV!639s`=Sbbn4WTz`N_RhE(0U^`iI;vi*nhHb?B+k z%PHGdnKBZQZv#(mru$Az7il{*W#0B>sm2fs9@z1yl#2NGy}zjNdgtAD-?NT8Y$Q}_lT!}bB2gZt!`!nJVyjiBP2Cv*5m~b) z)ETB8$Q}e5&!Q2J|5jU!MDo?uni{HJ9Q9M9K0HEMw|Zfse#Qie40&P!L%A|Q=N!TP z37L5tX$GE*V1LuZL?O>tZ6Pn|$0a*F-p+nbtJ(s+gc-M25(Xiav?;sjk3gwyY8|!D z?OtfO3K(>a!r1O;-PHM%QSu#xKQ2gcTKJQ8i;{;eP^SgmU++a$5eu##)6bHEZIiAG zbojLRN{;uJd2wR6bMU5LAAw(Qndsi<6QVM9OV=8Z>=I(oLy~L1{J8lBiRaGMz&1uNiQx>L$3K{6r`(GocO*xoQs5^?a)pjvMG_Qq#6%Fv zijH%Tc?!A~>=g{e(3!rX*S!!^(>x{@3sOE6r*vE1<~9^4C$k|%r`5$5Fu{UHhzs)g zUaBoh{)|d$idv>GArfpDsZ<++`5^y;FS6- zK6~@ob>i@+$3T-7N_o;05RV)}9iD?YvU!?s_>28epRdmX$+BCZ&xAMmWG$TL;d{?p zKb`e1i3ha6m_`Us|KXx3>O@-lzXfRdPYmBHJrzn=Z63*ZIvGq-MsME+A{wOZ?qEsr z!`TMv{VK7FjO6Tr{IOb-1)xrID{fOCsXs%Us-$p+Ge~V&RC@T43#^lFnqfBITw9)g z7JY;ZB}G+n3&=uC(29@~Xft#hIq74L2H+&`?EyoVl@VisDuuF%nE#hvdW2%X&$#|q zM`kNd=T4eg!PfH0y2BZT6tO(N+Hxa)7h1>NcQdA%n-GNacL&%~AX}M`q+f0-enMfj zA-R%AS{H0MI+_{9_Ct*OqH0jYbq`nD(m7Yj5xBwk=CF}hHmp--j&NoA-qMJjpooe~ zSDY%p2A+f+?bjY1az+m{E(oC3<~dqB2L75Vqx1!H-F()+>WEi1;pYCGmVj`v|C8D4 zb5(lmxp@itM9Y`=FFHqP9&ACWKL7^IFSA5&w>x*A=12HF|F%vjXNOx{w;8=p6D&T zo%4dn8T%C8kK~YkKo7;5A|dD)Kta0=!B!8$ihiKgZ>S19%FP~Hx`_$;Tol1)^*>KV z+CTmyyabBWkeE`yZ)8Qfm|B-mx&uk^bH{>mCR2Z5!dIn)rUpPjbtEplIP7l}0l=wj z5y_gF^({KYNRgWmed;tZDBvjMJJ6ZUr`a;)Y-uSmOx@8(jRKf zx&19Pwy0pVI3S%|sH0m}SW$6#e7mBm4J&ertA}o6b{^ix?AvLMhIcp4w%)!gA#xL6 z3N-!vO2n>MQri8d(Y^K$Fy_uS-~H67ST+#Qcczrmv52nKM{ZLJN|O0By(Al%t?x6l z)tqi-w&P%V@q&T@NKe@J&%Q(g0X+Lht0KMuVDu9p}*_5j_OA zUswntR$*^5X-+g0Jv_(&dUhcykz=Ls8X?Xylve#vbK6W9Z0XZc;9QcUqW5i6;>czi)b;g|+K-)k5mHZ|ohl>tBXP_=p4 zIsmT)<5{Z$M&Ph$_ElMm_1ICpk+$WDsbFc#`b;lpsx(moTLuMuFwV8{Q>+|@Axh_S-^e%y z+4H(6okD+$?5-evdT|D}K-we1z$Wt_VOI#!TVt?TzYe$bfPbVysnvx@=WBU$55d_C ziW}5wT1*89K-vneWq%rv(mdPZQmmZI)%Wrx=;c)W@FAXZ^%5ziZA$t0@;jnuBV2~G zq+UglJnm@C^D$HW{#9?wg|6vo<~-r!iB+XM!PW4fzv386^^g6vND+8T5G>kqtYJal zu0oo7VR*srA%~&Ef61!smlmF!gvxEpv~wv&^^cxd#7(98^fl-VDnh+CaZ-Cxja@B? z6;eaeu3R-!nYM9tc0z9Goa?g~xf-Q<%6nqM&u}VAFqtS)qggjD#3%(VXe5cxr%_BT z%~S@#jM*99kkQ(0#yA3L_a$S-cjWOG>27ZisiOwnq$8zMt~02C2ZS0ej`$gJI=hv- zYr{p$5}g>S=>n7u;`=DxofQmU5MJY4PD>s0>AuOX-19@?99#-tLhd1S03cWvv!JI& z5Th}Vo!WGcKuj-(`6A*%FHnLN4Yu9?&OFTk7G%JHh7g$=q6H|zA=Z+gW6PeVo{Vx& z5rLnCM|<~?L8DM=niF<^-~v>jH1J=Vp6xIEax^}diKPuPW6Z-_NlFYGoKR^3(~jb@p3Nv5xZ|Lv@6?6m1)c5 zUDgs#(IEC*fx@I0q5mBn7+_-+!I)Zr+mf?`V2tsiB8M|1ZkoV#Mu%K>^MNUTi$U4u zJFc=jOMX0KoXTNrDD5P|8hnVI=dB+4oy(6y2&B))>7!2L=toD#h^#ECbc}XUiP`o> zvmYyPXq9Yrs$d~p*xYTYj`_|JgDMYpe|%6w7$U~h9Qy?wg8%M26o=LDrfzD7VB$Vz zVNPFdhB}QM?zre*Se^{r4Q#o|kcW+k*WxXP?`Dhb-h||c^BC;9c;@AOg^07XewG1; z$fcl2{3W}im}P_-9Y$E=Q^m)=r{qXhgND{JBbzO9vT96v=@_(b4)^? zzc1%8KI%}T618OjmM^>$tpawgz}1_ifa?4e4>}(@Gj38%6~xq;O|;2kvDJWx?mzfT zB%9RJH9cee>D3eN#M7f_#0jv1e`8a@daVA)Tb8&e(Dl>BNqhLK5T_4%UpHkPb<80B z?`m5X^5;AAKUA}x5Q?)|+wS}>ZxliOm!H=l0ZEU6IxPr+wV%{ zCwMj(#u3cU4dV6#3Ml0@liVN@90O2B#*x&lknzRd1hU%Y<$Gia;T#1fq$A{f~{W zR&An8jmIf~!AkW1vs?NNFhT(gXo*vZS&aY!-!sc9!Z%Fj7GA%qOZ&A@7J?@~J3*eQ z?UDfk@&N>37kfm>41>5QsVXxbtil^#4et{=H1Nui)KqKtY7-%hvT74rb|}1?e88G5 zt=*PYg?Gy4jO=3pr^av(lD;$bP1@=I(Go$TK-Jt#f<-ogM`lHV245CcD^}W(0)Mfu z@t|-{WnDgyYsO;Zp+A1zs000;01jbaj3_P%%i4Tcu;gbrPH>j2uPM?FCfm?jU|@U` z5*2f)dcBA4lYN;@)&4_S53+Bt7S>&zTa4Bql&fkXw=G&guRDg5&8c#>%frV{fbr5| zFyK*v5FIzH=t(o|tP6*A3NTTKtwRVqw&8we7va8Vx1jai2zn_TbXI|FeLjk95884* z_Kz%2W#_jz8bTzdBp-~_HS{+Ep*|6c8U50pvn<~dG|yjZ{RjU|15aR|Zyg!f>HZp! zxf)x{QbDov;mZblN{dq!Oc+13dug4Op{zvk687O124p9}n^CqS(~}+{>B0f!dXi?a zcuQ#NS8abcG-W>Pf=5z{MCYen-fD3@XW-4PSVaX8O8{2WoCX<$WetV|AHK^y9{Oo3 zQ6TnX%Y3St%f|@6=%g(=2$*uWUb~`qruG4Tyu&C8qaLJSP#WB~&wie%Sk@R(m2f5k3y>uFxry0j*(N2vJnT9Z7|!}*fBy=QG7_z z(J|sDi5Vw)04kqlZ0~OY8@b19+u2cWd7A@TQ!k;m+upXR1YAM!@VCXn1!aF8)QVY5x4lMF^E23 ze|4429`er8c+vaBz1txFaW}M4q?n_@mZ?hHN$E_m;f*}f(8H-T)0>v;480;I{STMd zt-tU;TC04vACGac9M~tBQc^c!oj&fAw;R!80DL_{MTbX1#1q&os^UsG?@g zzhV0-`Xu#@-@DH7qj`u{<)OC4@&LR*E)wT^F-nmOdLJoux5PsANl~(d?|NjDnsYnA zOffPSU2;|G>ftKYmmssG4i61myFv-t9brxA`GG@T}XH;r4SdEqNj!~xz9#m@uHKXoL3jp-M4d>crQRzIteGFlf+}? z94yp7%S9`bP45=AnwUx8Air6;$hcT0#*mw#`UwjZfUZ-Px%T8lBat9dI@21H0hzY@h!|m?fHhU}!FB19 z9-)(48G`_$D@3nF^F4wfznTY_?JAAcWc`NEvYz%|jo5s=dLKlX3W>`UN!PG^@s8nJ#!bB+j%IKN@xsP0P5D~YI(`MS1n4{{_XFH*G zCW_N)N+s1dx-kWE;jc|gXDbPYc~hvrzQvG~4K$;}bX}pDhv*7Jqod&2qL*ILbU}1? zSke36wcXVxxK~`utV*n8@%!e)FE#K$<=m^it>lP99z|Gv3Kgf)iRpTC?8UjLPGt>1 z-N7Q`b}wC9xBzjy4zU~q)IWQB2tP{heVnf1f@&(AQGb!=Hyq46~$0UN(yw# zv5?YZ{(kp+ST5B~h?UW$(Uey(llpP@(UXl_OrnR|6v62i+#@X<6LN5RwXp(0#~r&% z%GO0F?R)a~2@**jaNJeBq?1(H=gu&kX&`$<;R|edyzT~vk3k8B-X}n7oT}fs2#@}IbDybSDqAr8Q4+798Nl8NH9hp_|ts(U5W1xkvGKebl$bD{3wB9mKB&s#xL3_3SG$1 zJ&LG9I?067S4(U6HtTD}lntOVi55xlZ_UW1H>ycIlNUx9qY(5kHWrwb?eYrs_!S6F zrM5$Qn1^~HDA)vWt~Svl88mu)Om^TyGTONgw)R*170-5e3y1HJ&FU>p#wiRS(ysT^AdSlYiSJp5Ti@~b_5&gam{ zim8pc$DeL-dB=-M5>E!*O-O}5FpJ=<)zP@k)qimZ3mWKuCAHCkh{t)~)FZV0sw}kw zlfzaqD;q?JT1lhMES}AN{flrI^h%kZ7n_d)GER(aCm| zLs79`$sTEb8qi5Gt1wvO5r-@XHK|--&rH{;DYVNDmQ~=3%SLp^{UzVn(nR zd>ab4<7Y_*R&&44a}E#J?{5g-jS^|%E?`v1z)!>J29qbt+^G|G8l7Dv%oWZ!$bBl{ zKxYVEx21rKzR5lqHtG23SK(@XOLeB=+gJJiPkb3m+X6wYnHx*o5>2&737z#VaQ&cm zW*?o-`cUeH>1X!9E=M|{4vm5K>R6bZ5_Z>+QgF(t{1(b^)WJ8WunThd+Rr{PjO?i>syhIg33l1oE-wI%1OV4mjAx|J zu`MG;n9h(UzJM=H$excUuF%MJV_{wxxf3R-=3U5stwHLRIN-}mbt!vd<~P}id!+Ep z>YQn$mVJCp=OUPkJ&_j2C4~5pbdp0)HhowzEp1qV@AW4CmvjjR7NG)UGL&i9WA=d= zGT+9Mz~5xYPvz^6yc**U+t$v+c*N3g=p2ao_oae>;;^nL0jOZ9m_9b2y0+SDE^68B z&bvdd3m3;NU&wsry-qg<`YnU|%aTm~JvKm}q0E%3DobQ6DpLEFaHr96r##Oj?A%D8*+%=ey&8<8m5gm6h9Y4V1v{`u2A1>*`W{Luji5AUC zSu>U$Zg==$+?&s#)NHaP6-pnfWCgxBwYVO=!evAfYJliHocoxQ=@-qP z&7m#@pTqknXugI!PHfCx0J8%miO9j~yKSYFqr$*3AHFwzcVYF`nRMz@|=js1_ zllb9wVa9)%N)%#tS0O=hgyTMn$8@Aj8|oJ)dY%aa{++ZkuyTv0BN@r~*z!q>zS3op;&Bc6TU;2Xr&^kc^=6j8^}#N^Mp4+^UJznR_I ze>-(;z2=t5PIDmZ{#_^qx6v3yDhaxzA!uMF1;l*v59n}}#Eq>ubynP1iEA5oN3^#R zowE?l3d~>px>*b>i}9a_K1cS4Wt(F{*-sm{4mnz9D0)a9iE3T$IZto^G(Jb?{cOfH zmX1ayt;oBqm1_w^I^U1J8EO8jQW#EFi_cz!kD0Y{g$NTe@+Ra_^-FIX3ml7mZ_tf| zRx=o2gGXYZ9S#Vukl*N1&9tanPLx#7^;Jc(!n8uWyz%@~%8xpx!RY>IDTW6+od^wE;%~w? znjoLfSUW^r3;~J6LiC}jUUHnMc2&b#YTuOn$b23mtYrdT(&Rx^hV={m9{r#Apwm!b z%o=ynSo&0><9dzbqRR^6_P(oFqUB|59m#ow^^#9; z4WaS-Pv%RibZoJ<-L)Vrv~pI~BGmlPkdkM8dyWC9Sv8}!0du1+#_pKxoZxgXaS^Q_ ztF%Lrc>MspXyor?nB6R=7B4iqXOil|gpBr824`2*A8QNX8T$2S(ksuP!zM+fG`oY@ z(>$1ouf_qEsIINly3L(&*VM%9E^qBDlM!aCutTxzO2-@edCk;vV8c{mb#u;ylpbIn z6QBt5wNTKk;J}(1Q+=e{yCaj&KKCWie^~>96Fm|`mLHp>;K%7-KUnxckpJdGYH_`# z&(@wC!LQR^yJR7pP83GiLKd1ys2l)PRN3%^FlS<`zBDa}?M@%-FQ%;pL9Y~;fOO4n zAfjN>5fymueFC~5aI?LbQ4-~f2WSOgd|}Mn>QJY*>H-b#7zSgPa&bz?I2_#*{x>Oui>Ujp@W2#fEn5)#(TpuA{)aGIZR=ioNb0 zn$#3~EQ?|AFh@Qi!j8Gpn{!idB5t-7&Tk`8O0M^czbHVu=8jG_ChB3(+H#4_BT#TD zk>Z?cF4mt_LzmP9XB1Kd@&A^#^BX*)9YpaW!-K)50|?8 zw!w>r&BCX`eZ*-1ZX4e*F?hV64J#njtrZgBq9}__R4t2HlYNm0>$k{Fb>AtrA5ayuYG+=Yp4RDjM zmvp_bF-n_k4=)+I|D`E9`Y7PCC4`}^Ae@_00k*iv0%Gw8co6&laN~yfr>W&Xo%gm= ztnBqs4qI~&a4GeW8*Y)1h_af6c;h*J&CTU)g)rS$^G5VeSCrgoB)&W108e51eB6+L zKSD(r&HEGWFn{(W0rOWf)J#MO?uK&}dKs;uJ|7Tkr2EoA>&8GcYi6}uJBpvh1|?WY zVNKRS@WJL@)BX>6*OnPA?3a{xfIgkr>ivl&6}Y@P|a@Hx#0Yz(uxB(euL%Q2~J$2&)?51nG5B zs`lX9jp8hr{aBiDoQ13`L5{IldNi%^*KSvrv8=Zg#?dQMu0t)VPU3J^b&d2E8ZQ^* zw-!yX%=0Z2*1!$#Twy`6bOiL}H{~t=I6v~hCm0Z`rvd|Fbpg6kk2GKNSqmx#y;3m3ml&XmWmKJ{$U94~Lb~AzfgyIQT$*hsMlWX3>y$=v z1y!$LLCdFN8M_7~vtW-R=g-4g6sIH;Kv}`>%i<|>*wjrDH%>p%%`N}ll0#%4+ktXg zEZ#P1FP|jX2Deh4on)H;vYo}nK4sXe1}SomTSm2@L7s8&+vdAlX-y3H-+I7bYxQI&P*3i z6xB`5MCx8a6TVi*D9Z7y;CUuT!aB*%nxVi-yS$dOa>fI4HjG6@8aK3oD$+)oH8_V?Yd(DKtSgfS5O4W42Bnxk8VV zve4H%;*o>(h}3*e=QOg+gZO3cfC+^YlbIZ|*#B%UFXS46 zOeWYM`wey;Y*z8$bZGogg8bwqnN0jGdtJJZSbZrN9x&NhQSE8$W(kk7ljcDnh1n$JRGLp<~|a3cFkRO{Rdc*vUzJypaNrQpkK&tKMl_rg)ziK zZpXR}Rwf1a5B5R2WNC8F96v(kC(^$Zr||?MsB)-9-joOZD-nAD9*pCY$V0AXF#-z2 z$>L+_c_V5kYf%zXCb!v`mB*O0OT%GFiEYdbOHyV67#8h!GGRzRTaZ8a(VtCLJZZK8 zw1bPoEV4bdGZ147Zs)f=IckU>$-glIOOeUdMq|+sM;X24B-3e6#RaJ``(q0Uk2zx0 zPn-+bkt?Hfv{ zBbp#Ekt+$I9Sf1PL4T9}eyhV|5V2VSK^gVeOfN#Q!nFCP^u^ElcA9$&)quMDVs4iN zOn`U4fasvLGc8T_&#FrIl;P>=+axfDdS-|wNpovBdf?~B4$Cnqz z7DdzqSg+~6Nb5mSH6b+WO0xHbX;ZF0{SV!p^emcAtFN1~iS>{;P_=9w=K8*}&;T6A z`F03$Ke0??tZjrd_f1c`x#t}S{_LhFKWIuRPd-a1{Q7+{l{u_}`u&twbwAXVWR~hk z?7>faZ1zRb!Bp!H4uA=20r1luD??a;8o3}?kyD7lB8VE-Y<)Qkrn*aT3O|Z8pgOqw zd6fDs*tsw!u7b=(b7Lj3ZOR?V-b(SXhS+Fo>Il=tfLzXa-_N7NgZF0F>k4LB#Ak^S zd*S5XbiGp9*yxdmHd)jIrPPZu?If0`h>psgRT&XWbIO^?n=thHhaLTa zU{wO=WyXd7B3Si-sW6IXmIf8O;vSI5S{vIsd}=S*QGAU;^U}etE?Pp(cxYrzO2)hp zCa;3EdpQ6!hIQKwq6d|-Nnvr**h|d`=8oJdJVf=3N;dyBp7~rqkI&{KIIR0qdUU-C zOz!7R{B1{nHu51OyHT6&VWIgL64(E|AXNy)@LWJCmT^$lT*B`z^d>K49I5rsby}@6|ckYFhU*ABJ;p?&v$}=qcyOHh2+05y$nLRTJ ztI_w+MIC+&crt3;dhh(|%;jw#&obj9UAuP%uSfl@Ea3k@L9)v}Fp?*tEmloT%AU=r zLcP|#0_{sUDGAhqOHl6zMmAO>{(iLcSti_FKXf1zg#(W3`FoZjY6^E0LR44Ve*xtL z2u2V<@tPhLxx+QEMoVQjz042Y6Atc%ybZm`U`YbuIbvLy5e}FE2LP%4^--y!;*7?` zW6PkiA^Me@i}PBsXba(!jpFua9|`?|VXob4wN>L4z$Y5?+54Lm$b3@!7>oZ?H+8}h zhqR7FEY^~b)6Uq(Yz@Gez&a!}vbyyd;)V`JLGyXzK&ROD=+k`lJQdHL&MZBx9@@}l zqbM{YPd@)v!HB*?vhdN4!A|d$nSM@mW5zr#N|=v34Wru#=FAI*!^@t1O&h4P9Y3W1 zmwvF8{I4R1pYO4Lk9c)+gQ5PI4*fB-CVvzPrQ!7N`tLwOrmUSX{xxZU>!{(U2CGZL z9J`mMjzP=e8}RD;#_5e(ex8Le9yS61!wn<;+w4hiauGlOitRc?adW+&)`8;{wvn!b zB4%SiD^8({Gj&-Fk%Yuo*#Qms9T2!ZoANPJli=#ZQ}lzMEH2%zg8c?OF7op_NH!2g zCMXb}SObHf;m8GpI9`bVxa>nv)@@*?u`s5+r0-7giJy=P{c$frmfgzV+wi`4lBV0+ z*_O_+97}$Lg8frlf)52?m#i_Qui2o?g0IRzmO-@-t-M>AZ_*sJ1g{7Y!h;V)AXw)! zra+ZGK5ZQB$C_8)cIusT2{%PFr9l&JHcq+2Hmm!o658jZtR zM)>?sW*H3V|3@%Y6TboFuk@G9!`se~+_7tMkAqILGR0M1adVc2pYZ%6n6@vO=J_8P zepFdxqV{*l>%@-o|N8M!!1;!v)Py+QJZ>!5QvQ~8z#+smps=7Q4){c(Y7Vy>>S)8I zr#n*)3hXk)zE;BC=wsjEz& zw{E{ZJ!sK0?H`XV2VoZikRgS+4>{b(1~J?B+Tzber6W3jA}-`KCOGC^%j<|x(d-eF&;bMW5x49~(!M(LZ@4|Z;YrmTXh&9@SpGX+|F;b<2 zg^iX~g7{BNhwxj>Vp2g#ZG_zB#)3?!w=cmma~(nDU(?JY2iCTKNTh{u#_~d|mMUxI zbCo>tJd{Wp7~*|k`{FXOEiy_cq)!CzKJM_c>bCh@|zuHVm_GGs+sDq7oI)qFC zr1Jq0dC$4$2~G&NbB4aaU=P3FUbEn$$l}9X_S`I)nU*|$uI|0?iaM=`b=)tI%6p`k z)o%{FlVTLAY3dTLUuwt;n--h%XI{z4^keSh62x+T3z_GdkLO9nBU++!!ZEN-BPXT6 zJFoXSbW*mN{CZ+E`IUQcJ2;2V=X3}GEc;S3C$Ugbzai-S0k^~fCRc-?Y%?lQeX@z( zE@8~fHRU-zMFP=U_<2hp*7$^3xd?-Za=7K@e(oxI+T0Y6^4GjkUg|L#&7DkgIIvWX zV5BDKtpN56Es~SNr>?RrUX=Ibmc}TCW5|WjaqR&@eJ~TK5M~)#sRNW!x!DNA4V6Yw z2kC?6Wn5SOj=-)3La(4Ot30zWL~!hiG-ldiHkH;n_O`N$W@XX@GIkaUZVO(Rf2kZQ z@DOm$0d56Y>~3^Y+Vah>=ax=9BOKYx97yngy-POSYCjFf<0*}RKuH3pS20ksx^@x= zlL?WfCS!T}8zkez5Xna3R3^s!%*-xTv69nV5jMHxf=Zx~P@^PN7?Jp3C+FZ2?1_Qd zKy9J=^|*!b#91KE)flTVs@_6FD|dvr7pvD!J_Ap>j}d90@jZ!UqlFE`VLJls?C1iW zz3<+_&02*&wX-o`OpDFL3KIy6E4bu5X)$G!=33D{;DIEx^y;$-792cMkcZ*8hBW2V za`}%r05=VGBE)EKdBIJ;>Av8m)jyIJF8S8LHex?Ib0FRWVK`4A2XPJ>uR7pi6b$E9F@*hj5zy<(5ZWUm}>riKFb zlbXem{<}^opi_W4HPoj7o&bX%yWWhgeR3;rn^a}Rp7HWqD72%G&tFHy@dRl%)p*rG zn!o~wMA4_sh%P=}bYf>^-zoCt8xQipKE@26p+ItU+8j@wF%e7y3rT3+1fGrG&~bJH zo1uMvaz!?MlJ2W~`Z}?<2k`b?i$E4s4JYVV{;zVv;%er`1O-*OB??}D77~3OM5X1r$;u2599IIbxMUF+Nr( z5;!Tp$$txoAWX0UHQ7JlMkW6%?F=o-Ct?a z?YdHnY7>H1UAC3!r_O&R&69+xLx);tqKKGlrog;Yq(ni<-1TG^{v#qN;XP99aiVU7 zpM$+%RLj9*O4gl2x#^{k3T=!?GGA}Kqtw`kL87O1J0kYv-!b^zRxz(a7bGgUHF=D! zD^e4Nk)MAolm1p}Q5uT&Gk_KbG#vSv9Z(qe5CWEfE9vkOCFBpT$YAtD6EnDYMgMlE zCUc%f@z|MYDc1B_u_2^he6&AwtUnhV*A?w2be6EP0(jH7!fZZ$--2}yEHgc@#WfD8 zGl5FHoRI_&x%D)X0e&vy^w@9fNGNNKXE?C!L-@P7rkh)d?|9n+dN%VXK6$0c)!x)j zfDBpe)_m2N%mTl&c^Mwj^|!Uk{;f{>zZffU_+_zc2EVt{(u^{T;+s`d9=_orzN$au z0tv&^?Iqx%mgo1rK&*lwB{$k=v4W)hMUUw%qNt>D?n?R0w>O2|uKhI|{u1g+8d_5M zBZNe+!hl)1H6ogciB zn4#N0FUHO?VxA%O?8y=w1P9>8awjP`_WAe8qOlRU8w^mk`XD_@y`K+Pk9~nyLxa(x zn6`WhH|2Xs)^s<*-m{D$FeBRa2veqaDPQ_Yac|}+y~}-g$mrU@$>>R;xTWq-)@Wut zN$5a{Kn)Sg(~d(%=&_A(S&Lr5^ENVVYVwFgA~1QK`w#`p5kWr+m|&pH2&rpJ*g?HM z=v??-VV5&#xpzAcMF`xS4!07b%T)e_SmCjAqSPT9+wLmhPitO?C{qSQIvKMq=JAKG z-0or@GK{a=;gE3H4=-9codOyVxH46Ii~jW;GGG<4K(O29FUx12YQ6Kw&f<4>3jZpS zpp6inv(!KR+=}Zg`ENi3&II}(eV{Jm#|v!;Li@fDy9EBhWseGEMD~oAzpn-&+xl6O zp-ozVQNMi{O0yeAM?8579fBBeaMlDKQ_1$}!g)ANfgk3%YDRv%pz;Q-2iB6$&)w0Q z6Re0A6 z?tFXAfbhprmYx5oCvCmM>>_X-+U8~m74D?++PpC>OWmn@1n7O|9p)Nk5F+K%p5z`y zeX?ZjJ^S6^*~ammVI%KAo%?Pf?+5==82Sh98Fscm|2D{#CNi!B8u3`dEw-37Tw51qful5fiJ zpk#>$ATAM=8F!Fb$Fb%O^X)1UpWoT=1Ya5%C|Dh95V2A%FO33-&D4||!UnFIgC|kug3mk+Sm{{iq z*|&w14tM9{sH0q4KWD!+e2fgr`xcOW6V&F!{>5dJI^;Z`Px#)v9YtDkzI^`}^6Qn? zbtfD6?91j_N2|m_a@bb}jQTqmX+K%KD0#bBIU@MCP!^(Z_2{4vrn4?%HpG9bI8cq+ z25VBy%Q)%5+^&bg?cmOaXP3rwo%`BdWnABgw^BIR+r(tU@gN<4Oa9sSG=Pkh&(klT z`bz*INDfmcpb1ZKeYmeOwUB6)_-oE(!MU&r9+KseB0@a9GIFI=^A0IV~0O6&NGl&4f1?Y~h%j)1S45q9Ten6=%Qgkf8YZv6cs8+lR$-BB{TngIS~2_N5C?2qBs?B)v(EEg21m>~B3RTt#1inuW+2<(zf(2#F$ zZ-X!(Q&w~ua9#4b_i{{f2`Uq&pE2@Ei!k8_UE36A|4<&)wja#oRgReHDQ{kF6e;px zM~yTWo4KdRr9pr_M;Y-E$;EoBUs_iQGDpvMX{FDs3$qd=uhq+hC)1jD$ffz9s_XNP z>Sz>uCr7`V6tg(@e(A6!P+k6p!yYV^=?%n_HNXU|%-9SP+9LFZBYEL*UbE|Uu9|*a zarmCpINp44f6|Bmvs${7PkGuLnyG+lWbw^$bMWJ3btpL*KhsVgV>8f|2N+x0PRQ$P zh*)~>GKI_r*3ZU)4M+*{#vWPtj7dx+jz2rvA2QaOs`VvB#;OJtKrTY)=EGpm+-e4u z4x=8N71acyi2h1gJ1&ON@!hkH^>N@4g-zRQ-|q@n^9|9`L}k7EAUP_rtCIr1gI0Ij z=5CTLn%X8*p`wA+;M)5)g0(jKdi&^)gyku~a zzAC>-HPi6Z`Yd*J8MgiN5bl*47aT`*X?3>s)0*P(ffi!#IaiRlC`8P{uaiU5>Y0~v z;@K<&1`fKqTh0FG^?1>hhk;XZuIqd?{RAH+WIS&qAoCYB7QBS0x;dL*?noK8H(FpT z){*SC0Mxppj|h1@(u`t_k~frDLe~vl6Jt-xls0>XM^}9^#z0faeonoi&G2VpAr?=U z8G0XEqNWw~hRxDv^{K$RQ7JF)2P)mxtwhZ%mujb8?QdT`;_s6gy>(Y&GMZ(+@N_tO zy7)dhNybW!aA{TM4)aVG>s+EZy*-u@L=z>5*7j#>-KfMreKk za=70q&kXTtf&qx86hfYqd}fdLw8qv)bZ+v?M=AATe98q!8r+nmp^$t*p%;)%{R6 z0On`ty3?NgvX{Yd`L6v2Uh|rvz(fH^dZ$I{c>KAtH|v|z2~2o7PU}f8ygQ_`?cf{- ztS!|=>MfzoZv^GimGgdHgOple%`i*!Lfpj{S4|?a7Do+G#DE>(ZQcTd*LUBZ3o1XO zw`H6wWSAAJzc}zHK)|Y=YWurAon{qF=s7;|{O2%7L)32u*_TzGk%67$ z0V0)Xd@0q7VyOM4zLvncu>K+^daQovny*6Qy=j{K2)c-nIqfut1eMxv z29`=T`7;rrF?KM;6R`}sR5pTT8|U~4yCtm-#Q%)UUu5~$g7a#OeN~5o@->jV(nv&| z1!brG(cV~`MSR(t6a>%8weH{On;bp`dmIHd+Zje`7F{>!iv48{Hr{N1wLcRf6+=W; z6W+M5K6Ni?iH*xEIY3Q&XyrfsDR35mL9Qs18A~^VIbu^ow8SwnM9DuL(pI+m=e|dl zAYpRgOCXBRo+; zkSfV-ZHkCMh&EarkKED~BS;1r1(0l{2NM^NqIyq?ry8a%l41)@*M2F5nc<;HUGKgjQ4cMNSwj2{b$2|MsSYtaAkAn#+k{dLGMyHZz{@^GIR z2ct4$G|ObK3Th12VLqd5;Tp<*ztU~qN5FX;8Fg^|*j`USMvD$D^Isq&NQw6^2+5_Y zCOKN5e*8wXOgTE8$dQEnBp{l6ftrHBi(-S6tJzaApTsR~9-~{W#3Ik0lJa+joK0UJ z0Tvz)KkdKfp*l1<_u$Na|oC3y=Oa+oa)J)8Zob>|xAsv7;m=xZ*M-OR3{3nAtq( z506~ZZFtV8-?D5++(8A2kgmu2)Xa^Rtm%SI(|^GW3DmaFGH_edOA6b*2yYze07h}) zv=-GNTkKnfCqgmh8^KykfRz+hTD z^8KB>-K^J^_+CH!&o14}O&Y<*2h&g}Kd!*by0jc+=jzdyjl1?tO(fXT$MhwJr9&Y7 zJn0>L``nrLs>02)H(AjyYIH5h{2H41Zl-|%A@_erejxd7Ppm*^Xaf*5RRveNrZX7A%ZrrO^et&G6YX9}{ zS{kvxCuMNKlx>2dv7`BH#jOV|5bA-^(oRK3~LT?4Y zJQwFil>1#xtDabT$Bao4p1s2gpP;B+oz3u0?D?HUXteuJ-u6O}Seorc=wB-iS_U-@ z;oEJ5`P0e4E$6-IzQNt-A82vrwPK)%FRrxh3yzQ)qxsIpb%zgoSD)RK1O0bB_yAIb z2i;C{y;ecEA)I-SN}=7I$< zaiv$@Bu*&&D%)ov1JS5jmH)U@l}B(h(NS%Zzt>fKQWUPY!-R&w$X_fAq`czL=jYBp zqxhaMWEyKN!LA#U3hCM#3Lg+@ELsxY97^4m(akB6G{wtwfy1C^r{EjtN*MTTNu2k` zF1m?A?iZ2wA3iQ99XC8OestIz?uN?A5OT8LYWku{zWiB7gP)ioA-VpN`EKRk#vi|= zviTC)v~!@Hco~=3OJjIIp_8Ip76}ac`lg@4$!I4aEr>y1d8IgL0oF@JI$nUgmbPR2zr)7abld*;LyKWS5Kp zDBI-yLgpI*SC=Jr<02I8Voz*)5ec z?#CV}yME9LhE_hldA4woE{R~2&5L%J$H=QwzsxW9b+2|bkQc-Rsf@%T#ZmG%@zfLJ z!^k1GOv+GatK(I>MCsu{Ly$>elCEnmW2irTG5vMrdj7N2*cg%(Ch@*hSa0Qu#N@Q8 zB=N*!0TX@&SkK8SJ=AycVZ=$%p`nY~!H@S4c(wqWFL--+-NCTWML|_R;yqfSz0ErP z^+7(cjV`coAb3C;j6zx64h}LnfJ) zAOCWi{(}!T`Ae9Y-mLWSFIGEFP+}GSA9D@~I+e7bFtL+p%c8djeynaM25r@=Je~-=Q5h0#_K)WxPA<`=|2qxa-HGU<@PpH_fj~Cp-aXdtW zH1;}19IsGzL2Ne(AqjqGiTzI7JazA`l!M_ccm`4Mz;6k&P3?3=^%P(8(C|RLd{IpJ zgZmMn!PN8H$YxNL`1<i^4>NJztQ_Ic4zeTTREkA}(=iU|$mxu!+&Qf+8Z_p#zYrp07COCt21 zc3*sgu4|&qmH$OKG;JCNSP@vbsx?z3Y~+L|UQ=6UIY$*X z=vI0XKoXo4++>B7tQs@ZKMPWKNjfLjY0a9d4P$d3Amkf$HG!6bHmH`+w?2SzeHbd( zm+Yo(<3ediL<7OQtv;D=Mb|&tS;%z7ls>}GVpEDHQny`Ohc}RpnH2C9*=}9(B-@s( zwMM%je{nga`I{~=U|qJ8K8){%m{Vc)Daqtdy`us}MU7{~!gbPX%TE3B^SE~iA558r zLQ5Y>fH(=k5*?LzG5pmCK}c$a`l6Z@57?dI5%WC~6nrd${pFMpXBo4 z*KE)Z>H!b*wfM7EgJYq61hpKlbVB&3Bn{UQIto_GzG@;5N`nY>Ua#Kw(Z|xjn;YV^%KS`(UU8M!0aMHuFkt;N(p@Qeu(wUPEs0lbHUd=oIcbR;*wTj z8dHA6W(hE*oYvB*RN53mJw7E9a{RNTIjX+Ngu7242%Nv|C|8# z5I=eOih|XJPp;vck@FEOCIaVR1tW^H)deP*`>fMPltlXuh-_^&Sq6+%kmobK2$Z7y zI=!mBNrRzdGO|M&a>=RbL~3D^V@H}!TnJ+41EG(5Qn=QtFl*>H?#z=b{e#4^RzRW9 z2*yTiCtsW2)bPzBtR_<_w>5%igTTF>PgSmH`A3(`vPKR|xd;|~W1&^g=E2R4;10Q< zl|{emm6QG4?zw~79dXC@Mos5u>Akj+%HoeOW#7KD?egmXK#HvAfJbz`U z6c6MK!G=`;o{SvmG6D^YIc>qZ@*sFo?Xy>2ZP@HxQFgp1Ym@@MC?>nS84tmG#uy`I zI$4ylj?C>vGNj8=(iyj+h6VqsUqVw)qealQ`d6nS;Xq6U4B~{hmIH-+M|+^x6-l0; zPHb67ehxf?=(kkQWH(UxPqlV*pHCt;DY~?hstz_D^y#{9)oHPRd`&5xpc9t;lTBC^c;?;W5V9TtVh{Z3U<{nz3x`nb32+GSpl=)WeOE<*3)Nju-r^>i zU3RX;hlaKO`qSRgJQfp!6_uOiBragG`zPZfI%vvOfr$t+-S#`C{Fc#BeKAp_;4975 z>45>V06M8As9?XiC_*`mcyzpTw#dT+?nkVv$81W=r)*%-o1N&q0W~vm@QEOhL)I7Y z#^#Go>%c%gLvZh)i)HjTF}#zF<#?n^$bY!`lA$Sgfd?K~5>vwt?3!V9Q%?$Dj5z{S zonXRgz+e`nS`!qO#xr+iQ#KYj?sb736k~)`bWeJC{}4PQ$6jiHJFr}xAHuNPfD*Mt zZi;{*(_e)(+%?fn%WP;wAXPHd6X7u_q|+cYyd1MfWtbhCIB_+T@a+4ykOhLe0Q6v% zk4z+_90XM;qc6mcq`2{$7dx_D@>fI@D0kF+Zk>Jg(hP$c#0LB(5GNB_kKQ#`{$Sp{ z@ujRr_pX_8@Svn@psEnfQFrcM?;D`i{p_|jfCvf{w6Fz8S$8d{`bF+}laLz$rNGla0 zAa1`Th?`cVn!Y#bgl?N_X4)T0{YD|bQQKJGS3$o6YL|Fk$M7aRM)~9fB15b>qxYI_ zc+FZauzIH7!S3NELS*_IN%rz=e!Z&)yf^s&j67(C2GRwZGqr%L6ArktN$zUGv3!!N zPduj_@{Ag6!~yW)38^k;1R{tk1WEvRpa7cUgcY9wv?^x99_5-W)vB5Kd6y9pIt+NI z`EEXM8Q$om7un!0P9NFRezLUu`du#Lbbyj!kzLZ8509{y`(QLr7)Y&Oa@!!j5FLJm zv_3Q)*L~3|eF*Am#vG);XAanTQJ{;o|4ANK^;wNStJ%}+*LHOIL_S%M>j+Q>l}RCNa$_gN|KRXy||jd|^P@^$nPU+3$@uU=LvWJ}rd3d{6nj>*^T znrEdK3GZlq2D5!nWPTa^HfMeBxMglnaZ8#LL-)MBvbi?a9n=*P2)*ysL8J@@p}t3k z5|d9=&z3z>#=zQ%HV}1YxF8}ctZF8L3e=0D9f>kN-`E)3CTm&Zs`M!w?} zz2h$YT~637{I(@Dp>a`z0gq!a7Ej_|g@B9iAyOC6#x0;)0s9mS2+xOW72!pIN8DRY(x-m%#R;%6CS8-Pz_MMS0`UiLv#Y;Xk0 z;eZrfD)05=qL=rz+od;LzZvmm~fo%?YrxiDQmKk<&Jjs~Gx8 z3811ZkHbh!p#v6sm<4vbl=%bKe4p45_ajpq|5Bnj4EhXdfaXJ+wP_B)-~g^(6$L`5 zKyZ&eS~?rOuvwsVtDgS8p7>&)Wu-~Nyx}0mjh;pwwIo_q3I!UwbTSwR=~k{+AU>t~ z8K2j{<-yMeW73eyuXJnlT>C+L3=WCqTgwh*J`R~L7?l(qmh2YV@owzaE8sM0*UYoo zz`#Ew6b}X;{5_)@CsjC{#Si>1#WD?g9v!4f^0%WHm;b)ZBBf!S8OA| zlJ(X}Ad~7xFDa7A%V|jkvcVn3E4qRY(WwW0ha=2GY&s&C1klCYdVfKcY>#U=7VFCSa&$H;tSC#*!at^-8#Gab{OW*w*HOfHL{3Ex*X?B%-ng(65_$pI@b7J;IM*P_8Lp{S zjWHmH{vvo1=En|CU<-RG&x3sSdp}r~B8U$dh}D!U0FjE;thx&JqdeyM!LWQ8uuf>D zf_;QW;W3WovLWX&HdZoA*RAGuA_eqv%Xy*$nuPJA(l~Xi#!cEQ`yo`_9pb5yf>u$D z-0LFo7xVQdOwr@sYv`0yZpN0Ap0gWryNz!}Sr#x*AR^j3{onqfTcj^(9K+uPU#m!4 z5XOsYza?N2Zkw7JQHFAa@o%@ZsgF6En$%nZA_O>qvl90AoY=5dh!u}@v5{9NJ;e{1 zusCSu(%YX_cZ&!irC%~@r^H!&)+Gx_-{V|yB|H*`J6jvYaU4v2l0tw+r=?bdGtp}+ z?28~npm-{IU5-D2&uDV1I(gMH&ql$zm1~2;Jy;3cZBt}bWDN2sw`Toz^NXU!QV}YW_`Qqg#roYuCLlj7`h;h8YXS1@GylM6 zLjDhxA*T{^3kM}}#Lpau(ur|J!;LJaJ8|yiufFk4Yx@v?{I9c;>|N{Mvl5Akhb0n{5Y`5D4%8q#f&1_mIGO^$zs_KX``cW8MZJXn<^$zgF* z=^6crF?^e3Hb$9_sf3Lio^$E=C+~welU9k)5CPp)9J)?@+RS5&?x7bw{X|(4*w?K% z^B#!b11yUlB2iU3SRaU)Wl0%ZF*!L%>*Ijx1uJxYoe^KEQN4Fy-9ziSKTOVx=o3L83Q zYyW(WAP~P7Q_fA0dBTJQxE57CF+%CFfQ7`UNc}kkqBAfbZ=kbsXON+KSyjj} zlKJd>jJEKp>hRNo)OGVRHx;?!aVCvDNzO&2P+yvMJr(eWKr&fZjDh?k3Gy=QZ_G!D z)(8}6{67|i!~Lh3t9Y4(ZAi3Zw2zoFfWw!XM=cb@GNBFiPd`Nk-g^PvfcS1;lo~Io zEnlX>24h(;!r_HTqS#H>1S%SMLMV} z$Q|i>@&8D-sa^p#vBZK&0ihStjS8dadOkRP`|gA!S5mQ^NU-92Z0+EMFNDn)EjN-) zQo|}+;u|)qKe;JKjG5BKl1XjIHv*;^JWz}uqirntFlH324o8hB0pqrm9de@cq_M=b z7`nE0EF48*o81giYG(Nx7h<$GORscHFkoQO0zC}JUfhbG)9DMls-NJ$OOd-f(H!a1 zlgZz_-;?()S5})ic81DDD7*5T+(CJ*bdHrR%%x$_0k^M1{Zx0Er6KltB?o}rzODTX z-&Q&DEE<>dP9?y-Xe}c*D$9I4PxAWAkA>6&s#uGZ`9ax&nZvHcf5GW!PBak^r2Nbs>pmSr`HkX)lW*a4id;Q%? zKe1ObG|9`kvwsjH{Wym~t)d%q8Sx|zUG5A>J%clXzosKZ zLYuks(jvx%OPl%kndBYckO%gwV3NSuC&n@1hHisAQkeRzja8kZpBsF|7=KLkYvX6|v^h^cCOyST!up+LiQIYINn!u$nBHdA@-erzT8&w3soL&Xmh0k^!TZ33 zqvTIp#zZ6SvRtbpbL`do=-exfR2pn06%405_j0RcgUaec^0R;Pzlor>Q0p48cJnn{Pfe>Grz>T1 zI-(!H^Jd#)yt$mwWDu1(^46m+3&tSVCCe<> zQUV&@Mui^4B4$k6f!g*M2z06+`F>D@9gp_4zPh?IhUHemcI+oCdD9hvER<(VKr)uL zy9IS`dqwnYcJE_2?xSeq5zAzs0a`03v=J+fa^*pF<4_^0PZA@;#y>Z`#&>X2L`ogt z&SEw>R_4NHt_?X6JFWk<=4^gKE`!{XPd+U^cIaIzWs}}#($S5sp;KcEQ(3FnLY9;t zkwI+t{)qTJAzK<&%T>MSdUI!xLDo4mq?Aa4rA$6^ZPe(#-tLoE5xQ-bJEsD3D)$@W zTJ7U4qSv?tnbb+34 zvCOEs^5Fi7>EwAa{;3r3!z->MHo3QR>CCi341nuLysDYG+PJU9v2Ew2Hb%UTgjoD@ znD)nz7$&Fao|fx=jw!P^dJ!U88abKz%Cus4_k(S@X^QaDUG1@i#zFezf^(~;SPzzQ zZ>w5Fv>NF_ItYBVI-3KR7r}S8H*dC6NAT>ba+tN2Y&U>hD6(6#XhH}s)~ad5Nb2CS z?MLt=%pfrobl9&WxzU^+++qTQ)oa%VNGh7ziaZ$9A>Q>)-?0e5ROIPfeU{xUC!!f>A7fIR7@Ud4E|| zga0{-k$tBbL?WZZChzLCp0XU&qd`8xhKU3+fWUxXMlpa6WL1a`wiLj@6{%L4+ptX7 zzEzf(sGy6F{#KybH>*t`YKCuJVS`UrZq<2m0xh^4&$o2p<#p~pnl0PTYRU!V^Nb}3 z^A=&BWd1x9?bR|!Dl*6tJnIy1q&R`bEM~;SL(gmm#C5O@-ReKO?@>SB;M+0URH8J} zze145YY4Xt&Ys|7HD<>CF`H6);?5cGC;L}lr(lLBMJaa<6-OV@)94`1x^3jmq#&MG zg{vNqT)F?dL(@azJ9Bs5A}0Uc!si>p-@B;>-~!Pk`9u9<%nteYp4W%!o6C!G0-1dG z(kCQvNJL!?&0s|7zAr8(M3|29Ephx3nLmvTh%hl1(q?Z3HHTN1`qQCAFOJa$lKt-l zKm@P-_%BB2@;`Fc8_{)YUJrTv{&8 z*-tSguUr`q5?s#5kA*CCftz!xdcO~~EQLt9jBpgG5OQQvks#yCJ8U!hB*@&n)B zN=kpJB;0QTf3s_#3V-L8kUaqQ}#ck~);;dFcA>sX5v>PKyC@*v!v=&eYz+AkC0_rXvhZc_p&%j^;Bn1e#(o=u23{NYZ`F;1nRV8YHbM55%7>g3!W>OAH za=(^PQ4z<1$O99DG9cxz2p3gsWx=wvnDd2x@t^2E38?Q&sYTb*D%H`#m!xOUCZx+v zZcL$N5+4UL;UOVQ306zR)&}Dd07x{DI+F%lKO(ra)M3o+@<4N}cwMtl*BN z%);i4s-i4aTBr(&U$~QPX}@&$>m`i$s7>E58jNo7z`x9MX8IN>Zk-)g&@0dVXNDI8 zww6xN>PARKjHe%eWH>n-S8RQGRDbL<6hQ(SBPUAl?AgzbkrVsFnwcc~a+z8ZyK7xa z1{KX}4&R-j5Nnn$GpDrTTI z5d852I81?56Qe`TJyr(w>v{B}y0Rs%5_+$Ba;HH5TD?ml;ow~Sfx}ed#(8_vJRR-| z*L1eyYNc-c#|4V_6DY|81C8h^lNZW~YLAxc@`Qb$PxuP+^b0)1f8TVMmv)9!JO_y} zCxJihcBKhD_wBm02PV~zjx@XwrU)V>WRN%w90SnGU;uIM2-8{T6xxjGz@V>Oj}_^Oc!5*MUBi zQ~eZ|wyG?Q*g6D;U%c5=n4`JDX^6GwEsGERPHdI3d+zc&1fJiVA7TB0=IU1%rgEsT4Bpb9h7YA>xO*%bP{{9yqpqfxY zu!QO_C^2bq<|-Kz#1Eg|I2a+3j1S@gd3IFBuq?}xBsel~{rTOgt4+7^M!^fneEVM@a}*>$ z+xLZX;?HtDn))=IY((fH&;(FeZg{kf*U4>FC)aZL5;-L^?lLXl5Ezhhiz5pBB2^Q* z2HrsGFj$;91Q&wg1Aff_|Irf&1)4h9AdABB#44PB#m=#$b2K($>Z#P#Mh@f@#gPa5 zIXDsxvwgS-B;^7$Q-PEd5W73bT6QnZm4m)c`@izHRn;TR(->Pa8 z1Wy$LiKI0qlVrs=C>x%0Z`+6B!i&fZ;N)q-DMt`$3P9^aGz$xT&9&yQ;P(lB6c&8z z-aKWTu(6DB!sL{jDPWKE+U?eE+FZtt6)9AZ_UfA_2UW4U>4jRUmvOaS=b%U(aLTzSy=X2z!GR})%OLc-t^ zcm-<6I(>rwxznI8KT|g4(k=29j$ljB2nJjv!t0+_fjYvcDP0c#=TP27ly>RDK6zHa zzye#Jqi9;Wk}VmNIK2lATlNtP&mQfw=O>OO=#l9U?3H9K1H@^siBMdm`k&U(ckxIO z27pu+Goxg(j=-B{x%k2?ZA4ans+$MrF1kcT;rQsMgfs(O745sm0+Y|y{IPErcL2_|EyWT569_nY@1j0an9WgY zGTNI&iHIfC+TjzIS#?%?*cDigXTvS1o7Qd+o0pi5`3fXF{S3i70>}_!&f!OIANXRIgf48hMJjW>*a zBp89eF=_D3;60V(@6X^izSvoFTIxC-sy@$SO0wsepJ`b)$-lq7IuzG#_{q8OG--QmQMD-5Vnj!8a_}rOxg=V< zqBO~3{OfB{?4Vp%lgZ-M%qA&K^2)9`e2>kiYCU@lk3G zMb0pnK&HsArdWdgzSW>6jv`NP9uduX|K5Rx{p^4z^ODfxgx*@x;$Ru&^3}7kr8Z#J z8xKjC?kBU`_-RH-suL998xt0sivOJJ>A@+0Dt75*MCNAIpT95{M8@TiKh{c8VrIBu z^xQe0+;8=IwqKM15&56z9SPPYs-j->l8GBmhg2@;gxOh~!`f9hhbCt6x7g)0zM><) zclyW1WYqCOb&vVOvTQW=C;|i1JlsVj5V^ zbKDdLg6o|rrCrl?40muP`47+gLY-z*{~MqR(u{uete4O>(PrcY-VDTLCK%s zlGNcwm}K;h2R!eapJMTU?tZf!TQsA~_}R#4_EZD6=FjZ^f%fBNISk%!@av_3b)*2a zXx8e&#_b+q4dfC@hXy<0|7$ZcK>G#*ME%-;97yR5$Tu&eGEr}cXi1WDXpa(Vc+W;* zJHD{Sn`LJlZic4;(g0f7XI@EQV>;?9J#&0FHq{A z+7nILol!t&{3v?yVFn(4nk)NPs-MKyFKkDCArfA!%v2WM?HAA|n?RkbmPyYFTJ{r! zt?=5K$Ob~HF2*7lV|s)5{D0XDJ-VGr@Ct?h(ZK$_n)?S)0azpeoX%&b2r?I8yelPx z*sGeevHcmOrQuJuyh}YyGGr>tphp)wnkPz43AKv8od7pjL`s$moKFe?`&0N(!VZ@B ztZQ?)m$`RDT+M>+x8ha0uw3tR;;Qa=m0HLs=@!Hk$9a{&)Q;HNf}G#jqP#_(4qsr(W{O(MgAzqR5@64drF;JXn zy9v1Jj5!l3>^4Nj3O$Vc3f^Z$PQEfFMntnC<8BSavlUEbMpzJ)CoOiJi;9BAReImC zG3-w|1}z*Rc62aNADXeRQs)VK^;|3j`{diAmPT?gjg1^&!vdj$<$SfNGGqDn;#q#p z(K7-T@tX!+-2x-Wd(FiLOGNtRljHtUaaW9ktt6}Mx0trBXxy73akmH%4NTd>K$$fO zmQ5b4!K0DaIKi6;(~>!c-r{x`RaZrWheA#5P1H)25Bd{ca@`?PV-I`@ugrdX2cMcR!?hL?*b_61A*+4+t9<8hHczL4pBl7kUVb)ehIlfuGUgBdxc^B0D`>a}J6ts00yvmdL|9cImqHPwe%-Y&gU*QZv4$bW z(czmh(G=eV1JRxXEXh~Z>6H*wf>`j)cWLR2bkO$63tjG)pozKAye zFS;cMf&j(8dD|&3h;d^NHoWg+r@O}lqNHJ8K2q5KK2nz$UE8>Mz2`hJByC!tgO(=S zfluf>Id$M-7JD7WD=K6+7An~^+7g1#j5~bje{3X=Y^5(blO+pO+m00yGP`fVCdBkN zL6rt0CL=ia1X&LQ8kaOd7$2Ah@)#G&zNftTWcu;)w{=ddr1EQ??*%24d(A4OOFzrr zDy|qJ0$g!R=umadRnZ$GOW^oNWZ}Q91Ku|HxQ9< zV^fM+*zyS-Mn)(>5w6Eh7rZ9C_WBrp@*LO%GALgYC`yW^PyMP1=zWKmmf7E{+KLrd z=)|YbHyI6|Mf1!NMbHr7(^N&i*rm036h>eQLb0c@g&krRCvPefE+JZ?^P?evAj7wW z@u`26#kD-SQ}5yHNARQ>N1Q{s{NDiIA}MNZDUfVEy?^e#>1j!We73F<#nL7QR8dpp zf2QvO!9beaUvaT)GZ=3k_h`MId6T{L35GON-!F51Q4F4dku+(GDhB@LdO#GEvU3od ziWg~0sX$%@t8=oF4&5t4u$ws@%5m66t7CFHM0vs+ zSSD*56eieMO~Kk}p|Y8U=Wi;Acx+*z;7}6N%L|)BRd1(|GQbZ)eA4Y%H z&EJz04Fcw34+q&cL_NACEC%X7etM^#v)_MJYgsXfLYwv2ze_6G8Ozo$*`Aop^2vmh z4_%0qmvlpVu98lRN8V*>TiZPnHY?5GvlU_fF}z>}Bi>4D1>pk0Q)zp-N~$#cw-ZU1 zI4E;z_*#0cw+F}LmjB=I`fAXC%Hkzb2H0nSXS(JRYs;1gJ<((=QyTU|RZ~`gl&${k zHrP;}Q1CxoA2D?6KqEOjEGng#R2$DPULK(an8TfAj7dD#6T)zC`$mdiHndHp+GuWr zt*~>z#+Isl(HxasABLqoK$aF9Eb&gXOUrdv-I2-P^UHf^G7@bAL*77jx(C&cFsM+^ zztcBokdE9h>efE%R^gmY{TM)jCte3A@De0#ikThZ(L=v~ z@H)M;?ib!5J5=j9sA8Z0bwFpk+SHtu3k=_=b%ZvPh|;G!1H(6EYWN_fj!?QVc8t2= zmG!d&AAX{XtCiLXoto{Ct7kc{yAYKk^i)dPX+6R}jW#9)Byt1T0j>VvDW|ginkcGO z_BRg{I9p#|K>c5aOj0~jFSLFo1Cq!+Bs<>tMoJ28^o>Y$t7t>uN3wKIZr7hG%L?+t zB1@(kV+*SoIt057V<52+doF@OU-H12y@5_YT_^br`x0c)f*>o48(6U+9AjKebkYV8 z(E_RXvDz{)Juk?Uh0}^~Rtsk8!>m?>hEIZU8%_1B7#7o&CL?~>+`isxUR@&2>T6d2o<3|~;Zq%J zY?SIQt9s3`qbo7Hvw>n_kJ~DP(pfoVLWHDCRFRO$5UFY=o3JG>PEye#a(-S)OZ<5c zPEgTIYsV3mIB47q@`(!T6Y-p8@zi30@0`}A#MP-Ml5P<3>RtKThaM^#X6?NC%dMMI zg~su!?`5yfaW7u%$*%uxPv#~dfYo?4iC`i3RIz}JUJD5b0MyB_mAPlV*<)ket{!5s zjl5!C_M1P&4KCU#g`GQeuPoXf+bs8xT@daZu4>t}O<=^1L;WTI)XCWJ4ru5q+;hC9 z1UwIoThV8?_awT|=#D(mhf3ct7fkT*V>(1p)Sx_Ya1jZ_@~xM4aUO(Cxc*DpGzstU z3S@cUL5c2k6G2B_> zka6v$fW~IT`W#H_AE{?G+4KvR73I{=4Au7ioc44b0r@wrveq}!Pa=)FFAoK<;4rTb z%&+U(tvw2iAGA{`QC)jo-fkl_@gS6ti|*AcOvsAViq~$*^f21`>h6Nb4UEAXl>#%M z?88D@C5H>83p1#wMTJcD?wT6A`s%ITmFu~ymsKy#!~55!W43Bz{{+CkY93HFAezS8 zjmb5RW2_ync*E5V1&-;NUa7j{IHxw(0Bu>uaF}D2>qh@aM^d6EBB9j2i>hWv$MFD% zfxFNq~d>`g$wZ9Njb9KG?=f6pvw#z<4XjDOCwRw*t zt;AYjDo3gADySEATrvW5C@?`cQ)sB9qXpZdK!i0FRcCc*Z0bI?66Q8?$=GPe?J~O1?3^~6TQ4n`M1xJJ+n$jF-tijP zAJ>%G6AVOGt%&1+sd#EO5gcAO-|NpfA?FQiT;&!*JHpHZzB|iVZUb$_5OQoye?_>8 zB87p^U_8)+!i7;!WDk0K-mGav1HK^oBnFG8t&c5J4c!chG5cUOtuM&HHhi2qt;Vvo z7cyw8uQΠU)-g5qF9@KW&8xCd#?+Udv)e`JZy8gb;u7Cf}icbLkf>Tto{4z6{3Y}GV!;q;tKV;Hkpy2=EuM5)qRN5St^f*DQ9 zBUo3VAdEip_>A!0-j$pEO>U57M!?DL%R%+&uQLMuohY|zw{mvUh{QBS@a6xlKZqVW z799YSZ}it6B>lhrK|>aj`o9s6YoSBL3gG_01Zn_w`3bcO9%OK4>U|QYMIh3C%4E#B zxdWs~KJ1@G$V|kt=q^gfEhzv1V~caTZ(RcT^0} zJ!G5ilx%_!46)%5??KJ?T&NS{LZJ~EL1d!!U4fK{J-Jold}8yqhPOD!GAsc^+UYb7 zI^QYHboHD_SATv_I;2z9rA_ZV;GI^_F{`R&8@`0$5_z+j7w$h&h5Tfg>Y7-sbe02+ z|EA}EnuWw5W+7w)DtYg+vl>yUMr&oiOjft5Nw06o_f^IBc#T(G_vs_Vxsv9x2p0C$ zaqzLZNw}J&#cq(U`LQ@8l=NIZqV>2~5cN|A{)EIW7Gm#+{`MjZne#47Mu~r_6Nk+$ zgP(9c?C-cJ7`_vT)4K3ijLjT>NK1)es(F1=naVtgg6y+#Z8pVRMIgN7AdDo$Ep$-B z2gH8{N&IyS^|1O;6JY6}v{s0ZIwSuY^$Bbfd?h81Gi?I{b%=~EX?UT6=arPeXgVJ^ zb5Dp$a89*_X9@7N6L*0rFrd`fzjW=M;3~XpjJMvHADr2S zk{(8hGPDm3)DWtQ=t0)P8SDOl3ks`HBn!`ZiEmQ@dv2$}X8PcZuH;7Et~eS=Lf!i$ zZ4S)~G=}!2wLksS>=69X!Ik}Yw0oyKXz8Hu^)7XXRg^XU%P_zE|F8@#wDA2l?=HdS z@S4}iEWD}1)O|aW4|Qq(6C?JKoNS@?B_KQ8`2I_zlqe7V(T&NAx^)6t-%idREgMD6 zpJ4Z>%rt^e)sU#56-ZY5Z8gU-AA;5=&``W--dvs5*MuNCn%@VubY+v#JK*Q?8v!FL zaaw*6w{f%}Du?c2-c=v&I;U_2tdWjV!1`hyqlz5erke3p$W4@D zCDt8vbL}Q~&1Oq8>gc@9pJ?~z)4$Q~$1MjN7$fdKmz22e^kE6?n~?tBd4{kdo*^P_ zNR*~U@%JM}J0=?!PXm<%&-!Z5Og}@dBIjn1Q6Yr~TPtQTG=p||U1{$%=veEK8U`N@ zgGd{4@nOxtPw)VgU=@$3#>ITmz$2vZB%sd1U)8$oQAHwCnEFL6a33$}=H#=uX_C~0 zRByjvGDc51ZsS%bI?~wG*S}*qfss#?s)jDGfpXv1s6nLo|HUxm{5Ox^=l<9H4!$@o7@ZY9 z)xE*;cShVmnvX7Ozi5hnjgp^!hql3IkwLiQn70YyJ+NGqj85eQ@Oq`oyK_&T5h|+^|lCsTm`kJlR3X7I;Kpwv**u zhL!C?4Ue=1wO?C$Hw7E$fBFP%cp11PX2#zIsP-*-G0x1l>E^q9Cy&_=WYy)Ck295~cjF`SE&SO26(#l~RZ1Sh9f83-r_z(r~sINiJf_&fnDLYlM zbHUG8=ww`VGAo4$_*MtG!d5)o9a(QDRer2c^Ebr)*A;+4Wv^mmx&rMM5(A`iJgA~rnX z8%0#!t}T}5itBqBA1I8^d+}*h-oq=a{OLY`4V<5!RsY+4poypn0?6^VO3(>6u05;C zlOrjRhx1|KywWXw!NQC{M0&!LeY#8j75Sq_nd;puNtl-MYeD}Up9&Yoog3V�?}B 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

to + // mount /dev/ /tmp_mount + // mount /tmp_mount/ --bind -o ro + // FIXME: try all filesystems + + if(_device.empty()) + ZYPP_THROW(MediaBadUrlEmptyDestinationException(url())); + + PathInfo dev_info(_device); + if(!dev_info.isBlk()) + ZYPP_THROW(MediaBadUrlEmptyDestinationException(url())); +#if DELAYED_VERIFY + DBG << "Verifying " << _device << " ..." << std::endl; + if( !verifyIfDiskVolume( _device)) + { + ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url)); + } +#endif + + if(_filesystem.empty()) + ZYPP_THROW(MediaBadUrlEmptyFilesystemException(url())); + + MediaSourceRef media( new MediaSource( + "disk", _device, dev_info.devMajor(), dev_info.devMinor() + )); + AttachedMedia ret( findAttachedMedia( media)); + + if( ret.mediaSource && + ret.attachPoint && + !ret.attachPoint->empty()) + { + DBG << "Using a shared media " + << ret.mediaSource->name + << " attached on " + << ret.attachPoint->path + << endl; + + removeAttachPoint(); + setAttachPoint(ret.attachPoint); + setMediaSource(ret.mediaSource); + return; + } + + MediaManager manager; + MountEntries entries( manager.getMountEntries()); + MountEntries::const_iterator e; + for( e = entries.begin(); e != entries.end(); ++e) + { + bool is_device = false; + std::string dev_path(Pathname(e->src).asString()); + PathInfo dev_info; + + if( dev_path.compare(0, sizeof("/dev/")-1, "/dev/") == 0 && + dev_info(e->src) && dev_info.isBlk()) + { + is_device = true; + } + + if( is_device && media->maj_nr == dev_info.devMajor() && + media->min_nr == dev_info.devMinor()) + { + AttachPointRef ap( new AttachPoint(e->dir, false)); + AttachedMedia am( media, ap); + { + DBG << "Using a system mounted media " + << media->name + << " attached on " + << ap->path + << endl; + + media->iown = false; // mark attachment as foreign + + setMediaSource(media); + setAttachPoint(ap); + return; + } + } + } + + if( !isUseableAttachPoint( attachPoint() ) ) + { + setAttachPoint( createAttachPoint(), true ); + } + std::string mountpoint( attachPoint().asString() ); + + Mount mount; + std::string options = _url.getQueryParam("mountoptions"); + if(options.empty()) + { + options = "ro"; + } + + if( !media->bdir.empty()) + { + options += ",bind"; + mount.mount(media->bdir, mountpoint, "none", options); + } + else + { + mount.mount(_device, mountpoint, _filesystem, options); + } + + setMediaSource(media); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + while( !(mountsucceeded=isAttached()) && --limit) + { + sleep(1); + } + + if( !mountsucceeded) + { + setMediaSource(MediaSourceRef()); + try + { + mount.umount(attachPoint().asString()); + } + catch (const MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW(MediaMountException( + "Unable to verify that the media was mounted", + _device, mountpoint + )); + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDISK::isAttached + // METHOD TYPE : bool + // + // DESCRIPTION : Override check if media is attached. + // + bool + MediaDISK::isAttached() const + { + return checkAttached(false); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::releaseFrom + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDISK::releaseFrom( const std::string & ejectDev ) + { + AttachedMedia am( attachedMedia()); + if(am.mediaSource && am.mediaSource->iown) + { + Mount mount; + mount.umount(attachPoint().asString()); + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDISK::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDISK::getFile ( const OnMediaLocation &file ) const + { + MediaHandler::getFile( file ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaDISK::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaDISK::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDISK::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaDISK::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaDISK::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + bool MediaDISK::getDoesFileExist( const Pathname & filename ) const + { + return MediaHandler::getDoesFileExist( filename ); + } + + } // namespace media +} // namespace zypp +// vim: set ts=8 sts=2 sw=2 ai noet: diff --git a/zypp/media/MediaDISK.h b/zypp/media/MediaDISK.h new file mode 100644 index 0000000..9a75554 --- /dev/null +++ b/zypp/media/MediaDISK.h @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaDISK.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIADISK_H +#define ZYPP_MEDIA_MEDIADISK_H + +#include + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaDISK + /** + * @short Implementation class for DISK MediaHandler + * @see MediaHandler + **/ + class MediaDISK : public MediaHandler { + + private: + std::string _device; + std::string _filesystem; + + protected: + + void attachTo (bool next = false) override; + void releaseFrom( const std::string & ejectDev ) override; + void getFile( const OnMediaLocation & file ) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + bool getDoesFileExist( const Pathname & filename ) const override; + + public: + + MediaDISK( const Url & url_r, + const Pathname & attach_point_hint_r ); + + ~MediaDISK() override { try { release(); } catch(...) {} } + + bool isAttached() const override; + + bool verifyIfDiskVolume(const Pathname &name); + }; + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIADISK_H diff --git a/zypp/media/MediaException.h b/zypp/media/MediaException.h new file mode 100644 index 0000000..81cbbe3 --- /dev/null +++ b/zypp/media/MediaException.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/MediaHandler.cc b/zypp/media/MediaHandler.cc new file mode 100644 index 0000000..1e78533 --- /dev/null +++ b/zypp/media/MediaHandler.cc @@ -0,0 +1,1358 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaHandler.cc + * +*/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; + +// use directory.yast on every media (not just via ftp/http) +#define NONREMOTE_DIRECTORY_YAST 1 + +namespace zypp { + namespace media { + + Pathname MediaHandler::_attachPrefix(""); + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : MediaHandler +// +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::MediaHandler +// METHOD TYPE : Constructor +// +// DESCRIPTION : +// +MediaHandler::MediaHandler ( Url url_r, + const Pathname & attach_point_r, + Pathname urlpath_below_attachpoint_r, + const bool does_download_r ) + : _mediaSource() + , _attachPoint( new AttachPoint()) + , _attachPointHint() + , _relativeRoot(std::move( urlpath_below_attachpoint_r)) + , _does_download( does_download_r ) + , _attach_mtime(0) + , _url(std::move( url_r )) + , _parentId(0) +{ + Pathname real_attach_point( getRealPath(attach_point_r.asString())); + + if ( !real_attach_point.empty() ) { + /////////////////////////////////////////////////////////////////// + // check if provided attachpoint is usable. + /////////////////////////////////////////////////////////////////// + + PathInfo adir( real_attach_point ); + // + // The verify if attach_point_r isn't a mountpoint of another + // device is done in the particular media handler (if needed). + // + // We just verify, if attach_point_r is a directory and for + // schemes other than "file" and "dir", if it is absolute. + // + if ( !adir.isDir() + || (_url.getScheme() != "file" + && _url.getScheme() != "dir" + && !real_attach_point.absolute()) ) + { + ERR << "Provided attach point is not a absolute directory: " + << adir << endl; + } + else { + attachPointHint( real_attach_point, false); + setAttachPoint( real_attach_point, false); + } + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::~MediaHandler +// METHOD TYPE : Destructor +// +// DESCRIPTION : +// +MediaHandler::~MediaHandler() +{ + try + { + removeAttachPoint(); + } + catch(...) {} +} + +void +MediaHandler::resetParentId() +{ + _parentId = 0; +} + +std::string +MediaHandler::getRealPath(const std::string &path) +{ + return getRealPath(zypp::Pathname(path)).asString(); +} + +zypp::Pathname +MediaHandler::getRealPath(const Pathname &path) +{ + return path.realpath(); +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::removeAttachPoint +// METHOD TYPE : void +// +// DESCRIPTION : +// +void +MediaHandler::removeAttachPoint() +{ + if ( _mediaSource ) { + INT << "MediaHandler deleted with media attached." << endl; + return; // no cleanup if media still mounted! + } + + DBG << "MediaHandler - checking if to remove attach point" << endl; + if ( _attachPoint.unique() && + _attachPoint->temp && + !_attachPoint->path.empty() && + PathInfo(_attachPoint->path).isDir()) + { + Pathname path(_attachPoint->path); + + setAttachPoint("", true); + + int res = recursive_rmdir( path ); + if ( res == 0 ) { + MIL << "Deleted default attach point " << path << endl; + } else { + ERR << "Failed to Delete default attach point " << path + << " errno(" << res << ")" << endl; + } + } + else + { + if( !_attachPoint->path.empty() && !_attachPoint->temp) + DBG << "MediaHandler - attachpoint is not temporary" << endl; + } +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attachPoint +// METHOD TYPE : Pathname +// +// DESCRIPTION : +// +Pathname +MediaHandler::attachPoint() const +{ + return _attachPoint->path; +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attachPoint +// METHOD TYPE : +// +// DESCRIPTION : +// +void +MediaHandler::setAttachPoint(const Pathname &path, bool temporary) +{ + _attachPoint.reset( new AttachPoint(path, temporary)); +} + +Pathname +MediaHandler::localRoot() const +{ + if( _attachPoint->path.empty()) + return Pathname(); + else + return _attachPoint->path + _relativeRoot; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attachPoint +// METHOD TYPE : +// +// DESCRIPTION : +// +void +MediaHandler::setAttachPoint(const AttachPointRef &ref) +{ + if( ref) + AttachPointRef(ref).swap(_attachPoint); + else + _attachPoint.reset( new AttachPoint()); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attachPointHint +// METHOD TYPE : void +// +// DESCRIPTION : +// +void +MediaHandler::attachPointHint(const Pathname &path, bool temporary) +{ + _attachPointHint.path = path; + _attachPointHint.temp = temporary; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attachPointHint +// METHOD TYPE : AttachPoint +// +// DESCRIPTION : +// +AttachPoint +MediaHandler::attachPointHint() const +{ + return _attachPointHint; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::findAttachedMedia +// METHOD TYPE : AttachedMedia +// +// DESCRIPTION : +// +AttachedMedia +MediaHandler::findAttachedMedia(const MediaSourceRef &media) const +{ + return MediaManager().findAttachedMedia(media); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::setAttachPrefix +// METHOD TYPE : void +// +// DESCRIPTION : +// +bool +MediaHandler::setAttachPrefix(const Pathname &attach_prefix) +{ + if( attach_prefix.empty()) + { + MIL << "Resetting to built-in attach point prefixes." + << std::endl; + MediaHandler::_attachPrefix = attach_prefix; + return true; + } + else + if( MediaHandler::checkAttachPoint(attach_prefix, false, true)) + { + MIL << "Setting user defined attach point prefix: " + << attach_prefix << std::endl; + MediaHandler::_attachPrefix = attach_prefix; + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attach +// METHOD TYPE : Pathname +// +// DESCRIPTION : +// +Pathname +MediaHandler::createAttachPoint() const +{ + Pathname aroot; + Pathname apoint; + { + aroot = MediaHandler::_attachPrefix; // explicit request + if ( ! aroot.empty() ) + apoint = createAttachPoint( aroot ); + } + + if ( apoint.empty() ) // fallback to config value + { + aroot = ZConfig::instance().download_mediaMountdir(); + if ( ! aroot.empty() ) + apoint = createAttachPoint( aroot ); + } + + if ( apoint.empty() ) // fall back to temp space + { + aroot = filesystem::TmpPath::defaultLocation(); + if ( ! aroot.empty() ) + apoint = createAttachPoint( aroot ); + } + + if ( apoint.empty() ) + { + auto except = MediaBadAttachPointException( url() ); + except.addHistory( _("Create attach point: Can't find a writable directory to create an attach point") ); + ZYPP_THROW( except ); + } + + MIL << "Created default attach point " << apoint << std::endl; + return apoint; +} + +Pathname +MediaHandler::createAttachPoint(const Pathname &attach_root) const +{ + Pathname apoint; + + if( attach_root.empty() || !attach_root.absolute()) { + ERR << "Create attach point: invalid attach root: '" + << attach_root << "'" << std::endl; + return apoint; + } + + PathInfo adir( attach_root ); + if( !adir.isDir() || (geteuid() != 0 && !adir.userMayRWX())) { + DBG << "Create attach point: attach root is not a writable directory: '" + << attach_root << "'" << std::endl; + return apoint; + } + + static bool cleanup_once( true ); + if ( cleanup_once ) + { + cleanup_once = false; + DBG << "Look for orphaned attach points in " << adir << std::endl; + std::list entries; + filesystem::readdir( entries, attach_root, false ); + for ( const std::string & entry : entries ) + { + if ( ! str::hasPrefix( entry, "AP_0x" ) ) + continue; + PathInfo sdir( attach_root + entry ); + if ( sdir.isDir() + && sdir.dev() == adir.dev() + && ( Date::now()-sdir.mtime() > Date::month ) ) + { + DBG << "Remove orphaned attach point " << sdir << std::endl; + filesystem::recursive_rmdir( sdir.path() ); + } + } + } + + filesystem::TmpDir tmpdir( attach_root, "AP_0x" ); + if ( tmpdir ) + { + apoint = getRealPath( tmpdir.path().asString() ); + if ( ! apoint.empty() ) + { + tmpdir.autoCleanup( false ); // Take responsibility for cleanup. + } + else + { + ERR << "Unable to resolve real path for attach point " << tmpdir << std::endl; + } + } + else + { + ERR << "Unable to create attach point below " << attach_root << std::endl; + } + return apoint; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::isUseableAttachPoint +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool +MediaHandler::isUseableAttachPoint(const Pathname &path, bool mtab) const +{ + MediaManager manager; + return manager.isUseableAttachPoint(path, mtab); +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::setMediaSource +// METHOD TYPE : void +// +// DESCRIPTION : +// +void +MediaHandler::setMediaSource(const MediaSourceRef &ref) +{ + _mediaSource.reset(); + if( ref && !ref->type.empty() && !ref->name.empty()) + _mediaSource = ref; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attachedMedia +// METHOD TYPE : AttachedMedia +// +// DESCRIPTION : +// +AttachedMedia +MediaHandler::attachedMedia() const +{ + if ( _mediaSource && _attachPoint) + return AttachedMedia(_mediaSource, _attachPoint); + else + return AttachedMedia(); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::isSharedMedia +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool +MediaHandler::isSharedMedia() const +{ + return !_mediaSource.unique(); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::checkAttached +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool +MediaHandler::checkAttached(bool matchMountFs) const +{ + bool _isAttached = false; + + AttachedMedia ref( attachedMedia() ); + if( ref.mediaSource ) + { + time_t old_mtime = _attach_mtime; + _attach_mtime = MediaManager::getMountTableMTime(); + if( !(old_mtime <= 0 || _attach_mtime != old_mtime) ) + { + // OK, skip the check (we've seen it at least once) + _isAttached = true; + } + else + { + if( old_mtime > 0) + DBG << "Mount table changed - rereading it" << std::endl; + else + DBG << "Forced check of the mount table" << std::endl; + + MountEntries entries( MediaManager::getMountEntries()); + for_( e, entries.begin(), entries.end() ) + { + if ( ref.attachPoint->path != Pathname(e->dir) ) + continue; // at least the mount points must match + + bool is_device = e->isBlockDevice(); + if( is_device && (ref.mediaSource->maj_nr && + ref.mediaSource->bdir.empty())) + { + PathInfo dev_info(e->src); + std::string mtype(matchMountFs ? e->type : ref.mediaSource->type); + MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor()); + + if( ref.mediaSource->equals( media ) ) + { + DBG << "Found media device " + << ref.mediaSource->asString() + << " in the mount table as " << e->src << std::endl; + _isAttached = true; + break; + } + // differs + } + else + if(!is_device && (!ref.mediaSource->maj_nr || + !ref.mediaSource->bdir.empty())) + { + if( ref.mediaSource->bdir.empty()) + { + // bnc#710269: Type nfs may appear as nfs4 in in the mount table + // and maybe vice versa. Similar cifs/smb. Need to unify these types: + if ( matchMountFs && e->type != ref.mediaSource->type ) + { + if ( str::hasPrefix( e->type, "nfs" ) && str::hasPrefix( ref.mediaSource->type, "nfs" ) ) + matchMountFs = false; + else if ( ( e->type == "cifs" || e->type == "smb" ) && ( ref.mediaSource->type == "cifs" || ref.mediaSource->type == "smb" ) ) + matchMountFs = false; + else + continue; // different types cannot match + } + // Here: Types are ok or not to check. + // Check the name except for nfs (bnc#804544; symlink resolution in mount path) + // + // [fibonacci]$ ls -l /Local/ma/c12.1 + // lrwxrwxrwx /Local/ma/c12.1 -> zypp-SuSE-Code-12_1-Branch/ + // + // [localhost]$ mount -t nfs4 fibonacci:/Local/ma/c12.1 /mnt + // [localhost]$ mount + // fibonacci:/Local/ma/zypp-SuSE-Code-12_1-Branch on /mnt + + // std::string mtype(matchMountFs ? e->type : ref.mediaSource->type); + // MediaSource media(mtype, e->src); + + if( ref.mediaSource->name == e->src || str::hasPrefix( ref.mediaSource->type, "nfs" ) ) + { + DBG << "Found media name " + << ref.mediaSource->asString() + << " in the mount table as " << e->src << std::endl; + _isAttached = true; + break; + } + } + else + { + if ( ref.mediaSource->bdir == e->src ) + { + DBG << "Found bound media " + << ref.mediaSource->asString() + << " in the mount table as " << e->src << std::endl; + _isAttached = true; + break; + } + } + // differs + } + else // mixed cases: + { + // Type ISO: Since 11.1 mtab might contain the name of + // the loop device instead of the iso file: + if ( ref.mediaSource->type == "iso" + && str::hasPrefix( Pathname(e->src).asString(), "/dev/loop" ) + && ref.attachPoint->path == Pathname(e->dir) ) + { + DBG << "Found bound media " + << ref.mediaSource->asString() + << " in the mount table as " << e->src << std::endl; + _isAttached = true; + break; + } + } + } + + if( !_isAttached) + { + MIL << "Looking for " << ref << endl; + if( entries.empty() ) + { + ERR << "Unable to find any entry in the /etc/mtab file" << std::endl; + } + else + { + dumpRange( DBG << "MountEntries: ", entries.begin(), entries.end() ) << endl; + } + if( old_mtime > 0 ) + { + ERR << "Attached media not in mount table any more - forcing reset!" + << std::endl; + + _mediaSource.reset(); + } + else + { + WAR << "Attached media not in mount table ..." << std::endl; + } + + // reset the mtime and force a new check to make sure, + // that we've found the media at least once in the mtab. + _attach_mtime = 0; + } + } + } + return _isAttached; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::attach +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::attach( bool next ) +{ + if ( isAttached() ) + return; + + // reset it in case of overloaded isAttached() + // that checks the media against /etc/mtab ... + setMediaSource(MediaSourceRef()); + + AttachPoint ap( attachPointHint()); + setAttachPoint(ap.path, ap.temp); + + try + { + attachTo( next ); // pass to concrete handler + } + catch(const MediaException &e) + { + removeAttachPoint(); + ZYPP_RETHROW(e); + } + MIL << "Attached: " << *this << endl; +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::localPath +// METHOD TYPE : Pathname +// +Pathname MediaHandler::localPath( const Pathname & pathname ) const +{ + Pathname _localRoot( localRoot()); + if ( _localRoot.empty() ) + return _localRoot; + + // we must check maximum file name length + // this is important for fetching the suseservers, the + // url with all parameters can get too long (bug #42021) + + return _localRoot + pathname.absolutename(); +} + + + + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::disconnect +// METHOD TYPE : PMError +// +void MediaHandler::disconnect() +{ + if ( !isAttached() ) + return; + + disconnectFrom(); // pass to concrete handler + MIL << "Disconnected: " << *this << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::release +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::release( const std::string & ejectDev ) +{ + if ( !isAttached() ) { + DBG << "Request to release media - not attached; eject '" << ejectDev << "'" + << std::endl; + if ( !ejectDev.empty() ) + forceEject(ejectDev); + return; + } + + DBG << "Request to release attached media " + << _mediaSource->asString() + << ", use count=" << _mediaSource.use_count() + << std::endl; + + if( _mediaSource.unique()) + { + DBG << "Releasing media " << _mediaSource->asString() << std::endl; + try { + releaseFrom( ejectDev ); // pass to concrete handler + } + catch(const MediaNotEjectedException &e) + { + // not ejected because the media + // is mounted by somebody else + // (if our attach point is busy, + // we get an umount exception) + _mediaSource.reset(NULL); + removeAttachPoint(); + // OK, retrow now + ZYPP_RETHROW(e); + } + _mediaSource.reset(NULL); + removeAttachPoint(); + } + else if( !ejectDev.empty() ) { + // + // Can't eject a shared media + // + //ZYPP_THROW(MediaIsSharedException(_mediaSource->asString())); + + MediaSourceRef media( new MediaSource(*_mediaSource)); + _mediaSource.reset(NULL); + + MediaManager manager; + manager.forceReleaseShared(media); + + setMediaSource(media); + DBG << "Releasing media (forced) " << _mediaSource->asString() << std::endl; + try { + releaseFrom( ejectDev ); // pass to concrete handler + } + catch(const MediaNotEjectedException &e) + { + // not ejected because the media + // is mounted by somebody else + // (if our attach point is busy, + // we get an umount exception) + _mediaSource.reset(NULL); + removeAttachPoint(); + // OK, retrow now + ZYPP_RETHROW(e); + } + _mediaSource.reset(NULL); + removeAttachPoint(); + } + else { + DBG << "Releasing shared media reference only" << std::endl; + _mediaSource.reset(NULL); + setAttachPoint("", true); + } + MIL << "Released: " << *this << endl; +} + +void MediaHandler::forceRelaseAllMedia(bool matchMountFs) +{ + forceRelaseAllMedia( attachedMedia().mediaSource, matchMountFs); +} + +void MediaHandler::forceRelaseAllMedia(const MediaSourceRef &ref, + bool matchMountFs) +{ + if( !ref) + return; + + MountEntries entries( MediaManager::getMountEntries()); + MountEntries::const_iterator e; + for( e = entries.begin(); e != entries.end(); ++e) + { + bool is_device = false; + PathInfo dev_info; + + if( str::hasPrefix( Pathname(e->src).asString(), "/dev/" ) && + dev_info(e->src) && dev_info.isBlk()) + { + is_device = true; + } + + if( is_device && ref->maj_nr) + { + std::string mtype(matchMountFs ? e->type : ref->type); + MediaSource media(mtype, e->src, dev_info.devMajor(), dev_info.devMinor()); + + if( ref->equals( media) && e->type != "subfs") + { + DBG << "Forcing release of media device " + << ref->asString() + << " in the mount table as " + << e->src << std::endl; + try { + Mount mount; + mount.umount(e->dir); + } + catch (const Exception &e) + { + ZYPP_CAUGHT(e); + } + } + } + else + if(!is_device && !ref->maj_nr) + { + std::string mtype(matchMountFs ? e->type : ref->type); + MediaSource media(mtype, e->src); + if( ref->equals( media)) + { + DBG << "Forcing release of media name " + << ref->asString() + << " in the mount table as " + << e->src << std::endl; + try { + Mount mount; + mount.umount(e->dir); + } + catch (const Exception &e) + { + ZYPP_CAUGHT(e); + } + } + } + } +} + +bool +MediaHandler::checkAttachPoint(const Pathname &apoint) const +{ + return MediaHandler::checkAttachPoint( apoint, true, false); +} + +// STATIC +bool +MediaHandler::checkAttachPoint(const Pathname &apoint, + bool emptydir, + bool writeable) +{ + if( apoint.empty() || !apoint.absolute()) + { + ERR << "Attach point '" << apoint << "' is not absolute" + << std::endl; + return false; + } + if( apoint == "/") + { + ERR << "Attach point '" << apoint << "' is not allowed" + << std::endl; + return false; + } + + PathInfo ainfo(apoint); + if( !ainfo.isDir()) + { + ERR << "Attach point '" << apoint << "' is not a directory" + << std::endl; + return false; + } + + if( emptydir) + { + if( 0 != zypp::filesystem::is_empty_dir(apoint)) + { + ERR << "Attach point '" << apoint << "' is not a empty directory" + << std::endl; + return false; + } + } + + if( writeable) + { + Pathname apath(apoint + "XXXXXX"); + char *atemp = ::strdup( apath.asString().c_str()); + char *atest = NULL; + if( !ainfo.userMayRWX() || atemp == NULL || + (atest=::mkdtemp(atemp)) == NULL) + { + if( atemp != NULL) + ::free(atemp); + + ERR << "Attach point '" << ainfo.path() + << "' is not a writeable directory" << std::endl; + return false; + } + else if( atest != NULL) + ::rmdir(atest); + + if( atemp != NULL) + ::free(atemp); + } + return true; +} + +/////////////////////////////////////////////////////////////////// +// +// METHOD NAME : MediaHandler::dependsOnParent +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool +MediaHandler::dependsOnParent() +{ + return _parentId != 0; +} + +bool +MediaHandler::dependsOnParent(MediaAccessId parentId, bool exactIdMatch) +{ + if( _parentId != 0) + { + if(parentId == _parentId) + return true; + + if( !exactIdMatch) + { + MediaManager mm; + AttachedMedia am1 = mm.getAttachedMedia(_parentId); + AttachedMedia am2 = mm.getAttachedMedia(parentId); + if( am1.mediaSource && am2.mediaSource) + { + return am1.mediaSource->equals( *(am2.mediaSource)); + } + } + } + return false; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::provideFile +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::provideFileCopy( const OnMediaLocation &srcFile, const Pathname& targetFilename ) const +{ + if ( !isAttached() ) { + INT << "Media not_attached on provideFileCopy(" << srcFile + << "," << targetFilename << ")" << endl; + ZYPP_THROW(MediaNotAttachedException(url())); + } + + getFileCopy( srcFile, targetFilename ); // pass to concrete handler + DBG << "provideFileCopy(" << srcFile << "," << targetFilename << ")" << endl; +} + +void MediaHandler::provideFile( const OnMediaLocation &file ) const +{ + if ( !isAttached() ) { + INT << "Error: Not attached on provideFile(" << file << ")" << endl; + ZYPP_THROW(MediaNotAttachedException(url())); + } + + getFile( file ); // pass to concrete handler + DBG << "provideFile(" << file << ")" << endl; +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::provideDir +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::provideDir( const Pathname& dirname ) const +{ + if ( !isAttached() ) { + INT << "Error: Not attached on provideDir(" << dirname << ")" << endl; + ZYPP_THROW(MediaNotAttachedException(url())); + } + + getDir( dirname, /*recursive*/false ); // pass to concrete handler + MIL << "provideDir(" << dirname << ")" << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::provideDirTree +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::provideDirTree( const Pathname& dirname ) const +{ + if ( !isAttached() ) { + INT << "Error Not attached on provideDirTree(" << dirname << ")" << endl; + ZYPP_THROW(MediaNotAttachedException(url())); + } + + getDir( dirname, /*recursive*/true ); // pass to concrete handler + MIL << "provideDirTree(" << dirname << ")" << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::releasePath +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::releasePath( const Pathname& pathname ) const +{ + if ( ! _does_download || _attachPoint->empty() ) + return; + + PathInfo info( localPath( pathname ) ); + + if ( info.isFile() ) { + unlink( info.path() ); + } else if ( info.isDir() ) { + if ( info.path() != localRoot() ) { + recursive_rmdir( info.path() ); + } else { + clean_dir( info.path() ); + } + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::dirInfo +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::dirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const +{ + retlist.clear(); + + if ( !isAttached() ) { + INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl; + ZYPP_THROW(MediaNotAttachedException(url())); + } + + getDirInfo( retlist, dirname, dots ); // pass to concrete handler + MIL << "dirInfo(" << dirname << ")" << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::dirInfo +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void MediaHandler::dirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const +{ + retlist.clear(); + + if ( !isAttached() ) { + INT << "Error: Not attached on dirInfo(" << dirname << ")" << endl; + ZYPP_THROW(MediaNotAttachedException(url())); + } + + getDirInfo( retlist, dirname, dots ); // pass to concrete handler + MIL << "dirInfo(" << dirname << ")" << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::doesFileExist +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +bool MediaHandler::doesFileExist( const Pathname & filename ) const +{ + // TODO do some logging + if ( !isAttached() ) { + INT << "Error Not attached on doesFileExist(" << filename << ")" << endl; + ZYPP_THROW(MediaNotAttachedException(url())); + } + return getDoesFileExist( filename ); + MIL << "doesFileExist(" << filename << ")" << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::getDirectoryYast +// METHOD TYPE : PMError +// +void MediaHandler::getDirectoryYast( std::list & retlist, + const Pathname & dirname, bool dots ) const +{ + retlist.clear(); + + filesystem::DirContent content; + getDirectoryYast( content, dirname, dots ); + + // convert to std::list + for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) { + retlist.push_back( it->name ); + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::getDirectoryYast +// METHOD TYPE : PMError +// +void MediaHandler::getDirectoryYast( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const +{ + retlist.clear(); + + // look for directory.yast + auto dirFile = OnMediaLocation( dirname + "directory.yast" ); + getFile( dirFile ); + DBG << "provideFile(" << dirFile << "): " << "OK" << endl; + + // using directory.yast + std::ifstream dir( localPath( dirFile.filename() ).asString().c_str() ); + if ( dir.fail() ) { + ERR << "Unable to load '" << localPath( dirFile.filename() ) << "'" << endl; + ZYPP_THROW(MediaSystemException(url(), + "Unable to load '" + localPath( dirFile.filename() ).asString() + "'")); + } + + std::string line; + while( getline( dir, line ) ) { + if ( line.empty() ) continue; + if ( line == "directory.yast" ) continue; + + // Newer directory.yast append '/' to directory names + // Remaining entries are unspecified, although most probabely files. + filesystem::FileType type = filesystem::FT_NOT_AVAIL; + if ( *line.rbegin() == '/' ) { + line.erase( line.end()-1 ); + type = filesystem::FT_DIR; + } + + if ( dots ) { + if ( line == "." || line == ".." ) continue; + } else { + if ( *line.begin() == '.' ) continue; + } + + retlist.push_back( filesystem::DirEntry( line, type ) ); + } +} + +/****************************************************************** +** +** +** FUNCTION NAME : operator<< +** FUNCTION TYPE : ostream & +*/ +std::ostream & operator<<( std::ostream & str, const MediaHandler & obj ) +{ + str << obj.url() << ( obj.isAttached() ? "" : " not" ) + << " attached; localRoot \"" << obj.localRoot() << "\""; + return str; +} + +void MediaHandler::getFile( const OnMediaLocation &file ) const +{ + PathInfo info( localPath( file.filename() ) ); + if( info.isFile() ) { + return; + } + + if (info.isExist()) + ZYPP_THROW(MediaNotAFileException(url(), localPath(file.filename()))); + else + ZYPP_THROW(MediaFileNotFoundException(url(), file.filename())); +} + +void MediaHandler::getFileCopy( const OnMediaLocation &file, const Pathname &targetFilename ) const +{ + getFile( file ); + if ( copy( localPath( file.filename() ), targetFilename ) != 0 ) { + ZYPP_THROW(MediaWriteException(targetFilename)); + } +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::getDir +// METHOD TYPE : PMError +// +// DESCRIPTION : Asserted that media is attached. +// Default implementation of pure virtual. +// +void MediaHandler::getDir( const Pathname & dirname, bool recurse_r ) const +{ + PathInfo info( localPath( dirname ) ); + if( info.isDir() ) { + return; + } + + if (info.isExist()) + ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); + else + ZYPP_THROW(MediaFileNotFoundException(url(), dirname)); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::getDirInfo +// METHOD TYPE : PMError +// +// DESCRIPTION : Asserted that media is attached and retlist is empty. +// Default implementation of pure virtual. +// +void MediaHandler::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const +{ + PathInfo info( localPath( dirname ) ); + if( ! info.isDir() ) { + ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); + } + +#if NONREMOTE_DIRECTORY_YAST + // use directory.yast if available + try { + getDirectoryYast( retlist, dirname, dots ); + } + catch (const MediaException & excpt_r) + { +#endif + + // readdir + int res = readdir( retlist, info.path(), dots ); + if ( res ) + { + MediaSystemException nexcpt(url(), "readdir failed"); +#if NONREMOTE_DIRECTORY_YAST + nexcpt.remember(excpt_r); +#endif + ZYPP_THROW(nexcpt); + } + +#if NONREMOTE_DIRECTORY_YAST + } +#endif + + return; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::getDirInfo +// METHOD TYPE : PMError +// +// DESCRIPTION : Asserted that media is attached and retlist is empty. +// Default implementation of pure virtual. +// +void MediaHandler::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const +{ + PathInfo info( localPath( dirname ) ); + if( ! info.isDir() ) { + ZYPP_THROW(MediaNotADirException(url(), localPath(dirname))); + } + +#if NONREMOTE_DIRECTORY_YAST + // use directory.yast if available + try { + getDirectoryYast( retlist, dirname, dots ); + } + catch (const MediaException & excpt_r) + { +#endif + + // readdir + int res = readdir( retlist, info.path(), dots ); + if ( res ) + { + MediaSystemException nexcpt(url(), "readdir failed"); +#if NONREMOTE_DIRECTORY_YAST + nexcpt.remember(excpt_r); +#endif + ZYPP_THROW(nexcpt); + } +#if NONREMOTE_DIRECTORY_YAST + } +#endif +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : MediaHandler::getDoesFileExist +// METHOD TYPE : PMError +// +// DESCRIPTION : Asserted that file is not a directory +// Default implementation of pure virtual. +// +bool MediaHandler::getDoesFileExist( const Pathname & filename ) const +{ + PathInfo info( localPath( filename ) ); + if( info.isDir() ) { + ZYPP_THROW(MediaNotAFileException(url(), localPath(filename))); + } + return info.isExist(); +} + +bool MediaHandler::hasMoreDevices() +{ + return false; +} + +void MediaHandler::getDetectedDevices(std::vector & devices, + unsigned int & index) const +{ + // clear the vector by default + if (!devices.empty()) + devices.clear(); + index = 0; + + DBG << "No devices for this medium" << endl; +} + +void MediaHandler::precacheFiles( const std::vector & ) +{ + /* do nothing */ +} + + } // namespace media +} // namespace zypp +// vim: set ts=8 sts=2 sw=2 ai noet: diff --git a/zypp/media/MediaHandler.h b/zypp/media/MediaHandler.h new file mode 100644 index 0000000..1b293ca --- /dev/null +++ b/zypp/media/MediaHandler.h @@ -0,0 +1,719 @@ + +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaHandler.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIAHANDLERL_H +#define ZYPP_MEDIA_MEDIAHANDLERL_H + +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::media" + +namespace zypp { + namespace media { + + class MediaManager; + + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : MediaHandler +/** + * @short Abstract base class for 'physical' MediaHandler like MediaCD, etc. + * + * Handles the requests forwarded by @ref MediaAccess. The public interface + * contains nonvirtual methods, which should do common sanitychecks and + * logging. For the real action they call virtual methods overloaded by the + * concrete handler. + **/ +class MediaHandler { + friend std::ostream & operator<<( std::ostream & str, const MediaHandler & obj ); + + public: + using Ptr = shared_ptr; + using constPtr = shared_ptr; + + static bool setAttachPrefix(const Pathname &attach_prefix); + + static std::string getRealPath(const std::string &path); + static Pathname getRealPath(const Pathname &path); + + private: + /** + * User defined default attach point prefix. + */ + static Pathname _attachPrefix; + + /** + * The attached media source description reference. + */ + mutable + MediaSourceRef _mediaSource; + + /** + * This is where the media will be actually attached ("mounted"). + * All files are provided bellow this + _relativeRoot directory. + **/ + AttachPointRef _attachPoint; + + /** + * The user provided attach preferred point. It may contain + * following values: + * + * "", true => create temporary attach point bellow of + * _attachPrefix or a built-in default and + * remove it if not needed any more. + * + * dir, false => user specified attach point (not removed) + */ + AttachPoint _attachPointHint; + + /** + * The relative root directory of the data on the media. + * See also localRoot() and urlpath_below_attachpoint_r + * constructor argument. + */ + Pathname _relativeRoot; + + /** + * True if concrete handler downloads files to the local + * filesystem. If true releaseFile/Dir will delete them. + **/ + bool _does_download; + + /** timestamp of the the last attach verification */ + mutable time_t _attach_mtime; + + protected: + /** + * Url to handle + **/ + const Url _url; + + /** + * Access Id of media handler we depend on. + */ + MediaAccessId _parentId; + + public: + + /** + * Check if the current media handler depends on an + * another handler specified by media access id. + * \param parentId The id of the parent handler to check against. + * \return true if it depends, false if not. + */ + bool dependsOnParent(MediaAccessId parentId, + bool exactIdMatch); + bool dependsOnParent(); + + /** + * Called in case, where the media manager takes over the + * destruction of the parent id (e.g. while destruction + * of the media manager). + */ + void resetParentId(); + + /** + * Return the currently used attach point. + **/ + Pathname attachPoint() const; + + /** + * Set a new attach point. + * \param path The attach point directory path. + * \param temp If to remove the attach point while cleanup. + */ + void setAttachPoint(const Pathname &path, bool temp); + + /** + * Set a (shared) attach point. + * \param ref New attach point reference. + */ + void setAttachPoint(const AttachPointRef &ref); + + /** + * Get the actual attach point hint. + */ + AttachPoint attachPointHint() const; + + /** + * Set the attach point hint as specified by the user. + * \param path The attach point directory path. + * \param temp If to remove the attach point while cleanup. + */ + void attachPointHint(const Pathname &path, bool temp); + + /** + * Try to create a default / temporary attach point. + * It tries to create it in attachPrefix if avaliable, + * then in built-in directories. + * \throws MediaBadAttachPointException if no attach point can be created + * \return The name of the new attach point + */ + Pathname createAttachPoint() const; + /** + * Try to create a temporary attach point in specified root. + * \param attach_root The attach root dir where to create the + * attach point in. + * \return The name of the new attach point or empty path name. + */ + Pathname createAttachPoint(const Pathname &attach_root) const; + + /** + * Remove unused attach point. If the attach point is temporary, + * the attach point directory and all it content will be removed. + */ + void removeAttachPoint(); + + /** + * Verify if the specified directory as attach point (root) + * as requires by the particular media handler implementation. + * \param apoint The directory to check. + * \return True, if the directory checks succeeded. + */ + virtual bool checkAttachPoint(const Pathname &apoint) const; + + /** + * Verify if the specified directory as attach point (root) + * using requested checks. + * \param apoint The directory to check. + * \param empty_dir Check if the directory is empty. + * \param writeable Check if the directory is writeable. + * \return True, if the directory checks succeeded. + */ + static bool checkAttachPoint(const Pathname &apoint, + bool empty_dir, + bool writeable); + + /** + * Ask media manager, if the specified path is already used + * as attach point or if there are another attach points + * bellow of it. + * \param path The attach point path to check. + * \param mtab Whether to check against the mtab, too. + * \return True, if the path can be used as attach point. + */ + bool isUseableAttachPoint(const Pathname &path, + bool mtab=true) const; + + /** + * Get the media source name or an empty string. + * \return media source name or empty string. + */ + std::string mediaSourceName() const + { + return _mediaSource ? _mediaSource->name : ""; + } + + /** + * Set new media source reference. + * \param ref The new reference. + */ + void setMediaSource(const MediaSourceRef &ref); + + /** + * Ask the media manager if specified media source + * is already attached. + */ + AttachedMedia + findAttachedMedia(const MediaSourceRef &media) const; + + /** + * Returns the attached media. Used by MediaManager + * to find other handlers using the same source. + * \note This function increments reference counters + * on the mediaSource and attachPoint references + * it contains, for the life time of the returned + * object. That is, it enables a (temporary) sharing + * of them. + * \return The AttachedMedia struct containing (shared) + * references to media source and attach point. + */ + AttachedMedia attachedMedia() const; + + /** + * Returns a hint if the media is shared or not. + * \return true, if media is shared. + */ + bool isSharedMedia() const; + + /** + * Check actual mediaSource attachment against the current + * mount table of the system. Used to implement isAttached(). + * \param matchMountFs If to use the filesystem type from the + * mount table (nfs, smb and cifs) or from mediaSource + * while compare of a mount entry with mediaSource. + * \return true, if the media appears in the mount table. + */ + bool checkAttached(bool matchMountFs) const; + + /** + * Call to this function will try to release all media matching + * the currenlty attached media source, that it is able to find + * in the mount table. This means also foreign (user) mounts! + * \param matchMountFs If to use the filesystem type from the + * mount table (nfs, smb and cifs) or from mediaSource + * while compare of a mount entry with mediaSource. + */ + void forceRelaseAllMedia(bool matchMountFs); + void forceRelaseAllMedia(const MediaSourceRef &ref, + bool matchMountFs); + + protected: + + /////////////////////////////////////////////////////////////////// + // + // Real action interface to be overloaded by concrete handler. + // + /////////////////////////////////////////////////////////////////// + + /** + * Call concrete handler to attach the media. + * + * Asserted that not already attached, and attachPoint is a directory. + * + * @param next try next available device in turn until end of device + * list is reached (for media which are accessible through multiple + * devices like cdroms). + * + * \throws MediaException + * + **/ + virtual void attachTo(bool next = false) = 0; + + /** + * Call concrete handler to disconnect media. + * + * Asserted that media is attached. + * + * This is useful for media which e.g. holds open a connection to a + * server like FTP. After calling disconnect() the media object still is + * valid and files are present. + * + * After calling disconnect(), it's not possible to call provideFile() or + * provideDir() anymore. + * + * \throws MediaException + * + **/ + virtual void disconnectFrom() { return; } + + /** + * Call concrete handler to release the media. + * + * If eject is true, and the media is used in one handler + * instance only, physically eject the media (i.e. CD-ROM). + * + * Asserted that media is attached. + * \param ejectDev Device to eject. None if empty. + * + * \throws MediaException + * + **/ + virtual void releaseFrom( const std::string & ejectDev = "" ) = 0; + + /** + * Call concrete handler to physically eject the media (i.e. CD-ROM) + * in case the media is not attached.. + * + * Asserted that media is not attached. + **/ + virtual void forceEject( const std::string & device ) {} + + /** + * Call concrete handler to provide file below attach point. + * + * Default implementation provided, that returns whether a file + * is located at 'localRoot + filename'. + * + * Asserted that media is attached. + * + * \throws MediaException + * + **/ + virtual void getFile( const OnMediaLocation &file ) const; + + /** + * Call concrete handler to provide a file under a different place + * in the file system (usually not under attach point) as a copy. + * Media must be attached before by callee. + * + * Default implementation provided that calls getFile(srcFilename) + * and copies the result around. + * + * \throws MediaException + * + **/ + virtual void getFileCopy( const OnMediaLocation & file, const Pathname & targetFilename ) const; + + + /** + * Call concrete handler to provide directory content (not recursive!) + * below attach point. + * + * Return E_not_supported_by_media if media does not support retrieval of + * directory content. + * + * Default implementation provided, that returns whether a directory + * is located at 'localRoot + dirname'. + * + * Asserted that media is attached. + * + * \throws MediaException + * + **/ + virtual void getDir( const Pathname & dirname, bool recurse_r ) const = 0; + + /** + * Call concrete handler to provide a content list of directory on media + * via retlist. If dots is false entries starting with '.' are not reported. + * + * Return E_not_supported_by_media if media does not support retrieval of + * directory content. + * + * Default implementation provided, that returns the content of a + * directory at 'localRoot + dirnname' retrieved via 'readdir'. + * + * Asserted that media is attached and retlist is empty. + * + * \throws MediaException + * + **/ + virtual void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const = 0; + + /** + * Basically the same as getDirInfo above. The content list is returned as + * filesystem::DirContent, which includes name and filetype of each directory + * entry. Retrieving the filetype usg. requires an additional ::stat call for + * each entry, thus it's more expensive than a simple readdir. + * + * Asserted that media is attached and retlist is empty. + * + * \throws MediaException + * + **/ + virtual void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const = 0; + + /** + * check if a file exists + * + * Asserted that url is a file and not a dir. + * + * \throws MediaException + * + **/ + virtual bool getDoesFileExist( const Pathname & filename ) const = 0; + + protected: + + /** + * Retrieve and if available scan dirname/directory.yast. + * + * Asserted that media is attached. + * + * \throws MediaException + * + **/ + void getDirectoryYast( std::list & retlist, + const Pathname & dirname, bool dots = true ) const; + + /** + * Retrieve and if available scan dirname/directory.yast. + * + * Asserted that media is attached. + * + * \throws MediaException + * + **/ + void getDirectoryYast( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const; + + public: + + /** + * If the concrete media handler provides a nonempty + * attach_point, it must be an existing directory. + * + * On an empty attach_point, MediaHandler will create + * a temporay directory, which will be erased from + * destructor. + * + * On any error, the attach_point is set to an empty Pathname, + * which should lead to E_bad_attachpoint. + **/ + MediaHandler ( Url url_r, + const Pathname & attach_point_r, + Pathname urlpath_below_attachpoint_r, + const bool does_download_r ); + + /** + * Contolling MediaAccess takes care, that attached media is released + * prior to deleting this. + **/ + virtual ~MediaHandler(); + + public: + + + /////////////////////////////////////////////////////////////////// + // + // MediaAccess interface. Does common checks and logging. + // Invokes real action if necessary. + // + /////////////////////////////////////////////////////////////////// + + /** + * Hint if files are downloaded or not. + */ + bool downloads() const { return _does_download; } + + /** + * Protocol hint for MediaAccess. + **/ + std::string protocol() const { return _url.getScheme(); } + + /** + * Url used. + **/ + Url url() const { return _url; } + + /** + * Use concrete handler to attach the media. + * + * @param next try next available device in turn until end of device + * list is reached (for media which are accessible through multiple + * devices like cdroms). + * + * \throws MediaException + * + **/ + void attach(bool next); + + /** + * True if media is attached. + **/ + virtual bool isAttached() const { return _mediaSource != nullptr; } + + /** + * Return the local directory that corresponds to medias url, + * no matter if media isAttached or not. Files requested will + * be available at 'localRoot() + filename' or better + * 'localPath( filename )'. + * + * Returns empty pathname if E_bad_attachpoint + **/ + Pathname localRoot() const; + + /** + * Files provided will be available at 'localPath(filename)'. + * + * Returns empty pathname if E_bad_attachpoint + **/ + Pathname localPath( const Pathname & pathname ) const; + + /** + * Use concrete handler to isconnect media. + * + * This is useful for media which e.g. holds open a connection to a + * server like FTP. After calling disconnect() the media object still is + * valid and files are present. + * + * After calling disconnect(), it's not possible to call provideFile() or + * provideDir() anymore. + * + * \throws MediaException + * + **/ + void disconnect(); + + /** + * Use concrete handler to release the media. + * @param eject Device to physically eject. None if empty. + * + * \throws MediaException + **/ + void release( const std::string & ejectDev = "" ); + + /** + * Use concrete handler to provide file denoted by path below + * 'localRoot'. Filename is interpreted relative to the + * attached url and a path prefix is preserved. + * + * \throws MediaException + * + **/ + void provideFile( const OnMediaLocation &file ) const; + + /** + * Call concrete handler to provide a copy of a file under a different place + * in the file system (usually not under attach point) as a copy. + * Media must be attached before by callee. + * + * @param srcFilename Filename of source file on the media + * @param targetFilename Filename for the target in the file system + * + * \throws MediaException + * + **/ + void provideFileCopy( const OnMediaLocation &srcFile, const Pathname& targetFilename ) const; + + /** + * Use concrete handler to provide directory denoted + * by path below 'localRoot' (not recursive!). + * dirname is interpreted relative to the + * attached url and a path prefix is preserved. + * + * \throws MediaException + * + **/ + void provideDir( const Pathname& dirname ) const; + + /** + * Use concrete handler to provide directory tree denoted + * by path below 'localRoot' (recursive!!). + * dirname is interpreted relative to the + * attached url and a path prefix is preserved. + * + * \throws MediaException + * + **/ + void provideDirTree( const Pathname& dirname ) const; + + /** + * Remove filename below localRoot IFF handler downloads files + * to the local filesystem. Never remove anything from media. + * + * \throws MediaException + * + **/ + void releaseFile( const Pathname & filename ) const { return releasePath( filename ); } + + /** + * Remove directory tree below localRoot IFF handler downloads files + * to the local filesystem. Never remove anything from media. + * + * \throws MediaException + * + **/ + void releaseDir( const Pathname & dirname ) const { return releasePath( dirname ); } + + /** + * Remove pathname below localRoot IFF handler downloads files + * to the local filesystem. Never remove anything from media. + * + * If pathname denotes a directory it is recursively removed. + * If pathname is empty or '/' everything below the localRoot + * is recursively removed. + * If pathname denotes a file it is unlinked. + * + * \throws MediaException + * + **/ + void releasePath( const Pathname& pathname ) const; + + public: + + /** + * Return content of directory on media via retlist. If dots is false + * entries starting with '.' are not reported. + * + * The request is forwarded to the concrete handler, + * which may atempt to retieve the content e.g. via 'readdir' + * + * Caution: This is not supported by all media types. + * Be prepared to handle E_not_supported_by_media. + * + * \throws MediaException + * + **/ + void dirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const; + + /** + * Basically the same as dirInfo above. The content is returned as + * filesystem::DirContent, which includes name and filetype of each directory + * entry. Retrieving the filetype usg. requires an additional ::stat call for + * each entry, thus it's more expensive than a simple readdir. + * + * Caution: This is not supported by all media types. + * Be prepared to handle E_not_supported_by_media. + * + * \throws MediaException + * + **/ + void dirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const; + + /** + * check if a file exists + * + * Asserted that url is a file and not a dir. + * + * \throws MediaException + * + **/ + bool doesFileExist( const Pathname & filename ) const; + + /** + * Check if the media has one more device available for attach(true). + */ + virtual bool hasMoreDevices(); + + /** + * Fill in a vector of detected ejectable devices and the index of the + * currently attached device within the vector. The contents of the vector + * are the device names (/dev/cdrom and such). + * + * \param devices vector to load with the device names + * \param index index of the currently used device in the devices vector + */ + virtual void + getDetectedDevices(std::vector & devices, + unsigned int & index) const; + + /** + * Tries to fetch the given files and precaches them. Those files + * need to be queried using provideFile and can be read from the cache directly. + * The implementation is not allowed to block but needs to use seperate means to + * download the files concurrently. + * A backend can choose to completely ignore this functionaly, the default implementation + * does nothing. + * + * \param files List of files that should be precached, the OnMediaLocation needs to belong to the handler it is passed to + */ + virtual void + precacheFiles ( const std::vector< OnMediaLocation > &files ); +}; + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + + +#endif // ZYPP_MEDIA_MEDIAHANDLERL_H diff --git a/zypp/media/MediaHandlerFactory.cc b/zypp/media/MediaHandlerFactory.cc new file mode 100644 index 0000000..cb1a5c8 --- /dev/null +++ b/zypp/media/MediaHandlerFactory.cc @@ -0,0 +1,174 @@ +#include "MediaHandlerFactory.h" + + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zypp::media { + + MediaHandlerFactory::MediaHandlerFactory() + { + + } + + std::optional MediaHandlerFactory::handlerType(const Url &url) + { + std::string scheme = url.getScheme(); + if (scheme == "cd" || scheme == "dvd") + return MediaCDType; + else if (scheme == "nfs" || scheme == "nfs4") + return MediaNFSType; + else if (scheme == "iso") + return MediaISOType; + else if (scheme == "file" || scheme == "dir") + return MediaFileType; + else if (scheme == "hd" ) + return MediaDISKType; + else if (scheme == "cifs" || scheme == "smb") + return MediaCIFSType; + else if (scheme == "ftp" || scheme == "tftp" || scheme == "http" || scheme == "https") + return MediaCURLType; + else if (scheme == "plugin" ) + return MediaPluginType; + return {}; + } + + std::unique_ptr MediaHandlerFactory::createHandler( const Url &o_url, const Pathname &preferred_attach_point ) + { + if(!o_url.isValid()) { + MIL << "Url is not valid" << std::endl; + ZYPP_THROW(MediaBadUrlException(o_url)); + } + + UrlResolverPlugin::HeaderList custom_headers; + Url url = UrlResolverPlugin::resolveUrl(o_url, custom_headers); + MIL << "Trying scheme '" << url.getScheme() << "'" << std::endl; + + const auto hdlType = handlerType( url ); + if ( !hdlType ) { + ZYPP_THROW(MediaUnsupportedUrlSchemeException(url)); + } + + std::unique_ptr _handler; + switch(*hdlType) { + case MediaCDType: { + _handler = std::make_unique (url,preferred_attach_point); + break; + } + case MediaNFSType: { + _handler = std::make_unique (url,preferred_attach_point); + break; + } + case MediaISOType: { + _handler = std::make_unique (url,preferred_attach_point); + break; + } + case MediaFileType: { + _handler = std::make_unique (url,preferred_attach_point); + break; + } + case MediaDISKType: { + _handler = std::make_unique (url,preferred_attach_point); + break; + } + case MediaCIFSType: { + _handler = std::make_unique (url,preferred_attach_point); + break; + } + case MediaCURLType: { + enum WhichHandler { choose, curl, multicurl, network }; + WhichHandler which = choose; + // Leagcy: choose handler in UUrl query + if ( const std::string & queryparam = url.getQueryParam("mediahandler"); ! queryparam.empty() ) { + if ( queryparam == "network" ) + which = network; + else if ( queryparam == "multicurl" ) + which = multicurl; + else if ( queryparam == "curl" ) + which = curl; + else + WAR << "Unknown mediahandler='" << queryparam << "' in URL; Choosing the default" << std::endl; + } + // Otherwise choose handler through ENV + if ( which == choose ) { + auto getenvIs = []( std::string_view var, std::string_view val )->bool { + const char * v = ::getenv( var.data() ); + return v && v == val; + }; + + if ( getenvIs( "ZYPP_MEDIANETWORK", "1" ) ) { + WAR << "MediaNetwork backend enabled" << std::endl; + which = network; + } + else if ( getenvIs( "ZYPP_MULTICURL", "0" ) ) { + WAR << "multicurl manually disabled." << std::endl; + which = curl; + } + else + which = multicurl; + } + // Finally use the default + std::unique_ptr handler; + switch ( which ) { + default: + case multicurl: + handler = std::make_unique( url, preferred_attach_point ); + break; + + case network: + handler = std::make_unique( url, preferred_attach_point ); + break; + + case curl: + handler = std::make_unique( url, preferred_attach_point ); + break; + } + // Set up the handler + for ( const auto & el : custom_headers ) { + std::string header { el.first }; + header += ": "; + header += el.second; + MIL << "Added custom header -> " << header << std::endl; + handler->settings().addHeader( std::move(header) ); + } + _handler = std::move(handler); + break; + } + case MediaPluginType: { + // bsc#1228208: MediaPluginType must be resolved to a valid schema by the + // above UrlResolverPlugin::resolveUrl call. MediaPlugin exists as a stub, + // but is not a usable handler type. + ZYPP_THROW(MediaUnsupportedUrlSchemeException(url)); + break; + } + } + + if ( !_handler ) { + ZYPP_THROW(MediaUnsupportedUrlSchemeException(url)); + } + + // check created handler + if ( !_handler ){ + ERR << "Failed to create media handler" << std::endl; + ZYPP_THROW(MediaSystemException(url, "Failed to create media handler")); + } + + MIL << "Opened: " << *_handler << std::endl; + return _handler; + } + +} diff --git a/zypp/media/MediaHandlerFactory.h b/zypp/media/MediaHandlerFactory.h new file mode 100644 index 0000000..12f90e1 --- /dev/null +++ b/zypp/media/MediaHandlerFactory.h @@ -0,0 +1,37 @@ +#ifndef MEDIAHANDLERFACTORY_H +#define MEDIAHANDLERFACTORY_H + +#include +#include +#include +#include + + +namespace zypp::media { + + class MediaHandler; + + class MediaHandlerFactory + { + public: + + enum MediaHandlerType { + MediaCDType, + MediaNFSType, + MediaISOType, + MediaFileType, + MediaDISKType, + MediaCIFSType, + MediaCURLType, + MediaPluginType + }; + + MediaHandlerFactory(); + static std::unique_ptr createHandler (const Url& o_url, const Pathname & preferred_attach_point); + static std::optional handlerType( const Url &url ); + }; + +} + + +#endif // MEDIAHANDLERFACTORY_H diff --git a/zypp/media/MediaISO.cc b/zypp/media/MediaISO.cc new file mode 100644 index 0000000..4cadffe --- /dev/null +++ b/zypp/media/MediaISO.cc @@ -0,0 +1,311 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaISO.cc + * + */ +#include + +#include +#include + +#include + +using std::endl; + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + namespace media + { ////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // MediaISO Url: + // + // Schema: iso + // Path name: subdir to the location of desired files inside + // of the ISO. + // Query parameters: + // url: The iso filename source media url pointing + // to a directory containing the ISO file. + // mnt: Prefered attach point for source media url. + // iso: The name of the iso file. + // filesystem: Optional, defaults to "auto". + // + /////////////////////////////////////////////////////////////////// + MediaISO::MediaISO(const Url &url_r, + const Pathname &attach_point_hint_r) + : MediaHandler(url_r, attach_point_hint_r, + url_r.getPathName(), // urlpath below attachpoint + false) // does_download + { + MIL << "MediaISO::MediaISO(" << url_r << ", " + << attach_point_hint_r << ")" << std::endl; + + _isofile = _url.getQueryParam("iso"); + if( _isofile.empty()) + { + ERR << "Media url does not contain iso filename" << std::endl; + ZYPP_THROW(MediaBadUrlEmptyDestinationException(_url)); + } + + _filesystem = _url.getQueryParam("filesystem"); + if( _filesystem.empty()) + _filesystem = "auto"; + + Url src; + { + const std::string & arg { _url.getQueryParam("url") }; + if ( arg.empty() ) { + src = "dir:/"; + src.setPathName( _isofile.dirname() ); + _isofile = _isofile.basename(); + } + else try { + src = arg; + } + catch( const url::UrlException & e ) + { + ZYPP_CAUGHT(e); + ERR << "Unable to parse iso filename source media url" << std::endl; + MediaBadUrlException ne(_url); + ne.remember(e); + ZYPP_THROW(ne); + } + } + if( !src.isValid()) + { + ERR << "Invalid iso filename source media url" << std::endl; + ZYPP_THROW(MediaBadUrlException(src)); + } + if( src.getScheme() == "iso") + { + ERR << "ISO filename source media url with iso scheme (nested iso): " + << src.asString() << std::endl; + ZYPP_THROW(MediaUnsupportedUrlSchemeException(src)); + } + else + if( !(src.getScheme() == "hd" || + src.getScheme() == "dir" || + src.getScheme() == "file" || + src.getScheme() == "nfs" || + src.getScheme() == "nfs4" || + src.getScheme() == "smb" || + src.getScheme() == "cifs")) + { + ERR << "ISO filename source media url scheme is not supported: " + << src.asString() << std::endl; + ZYPP_THROW(MediaUnsupportedUrlSchemeException(src)); + } + + MediaManager manager; + + _parentId = manager.open(src, _url.getQueryParam("mnt")); + } + + // --------------------------------------------------------------- + MediaISO::~MediaISO() + { + try + { + release(); + + if( _parentId) + { + DBG << "Closing parent handler..." << std::endl; + MediaManager manager; + if(manager.isOpen(_parentId)) + manager.close(_parentId); + _parentId = 0; + } + } + catch( ... ) + {} + } + + // --------------------------------------------------------------- + bool + MediaISO::isAttached() const + { + return checkAttached(false); + } + + // --------------------------------------------------------------- + void MediaISO::attachTo(bool next) + { + if(next) + ZYPP_THROW(MediaNotSupportedException(_url)); + + MediaManager manager; + manager.attach(_parentId); + + try + { + manager.provideFile(_parentId, OnMediaLocation(_isofile) ); + } + catch(const MediaException &e1) + { + ZYPP_CAUGHT(e1); + try + { + manager.release(_parentId); + } + catch(const MediaException &e2) + { + ZYPP_CAUGHT(e2); + } + + MediaMountException e3( + "Unable to find iso filename on source media", + _url.asString(), attachPoint().asString() + ); + e3.remember(e1); + ZYPP_THROW(e3); + } + + // if the provided file is a symlink, expand it (#274651) + // (this will probably work only for file/dir and cd/dvd schemes) + Pathname isofile = expandlink(manager.localPath(_parentId, _isofile)); + if( isofile.empty() || !PathInfo(isofile).isFile()) + { + ZYPP_THROW(MediaNotSupportedException(_url)); + } + + MediaSourceRef media( new MediaSource("iso", isofile.asString() ) ); + + AttachedMedia ret( findAttachedMedia(media)); + if( ret.mediaSource && + ret.attachPoint && + !ret.attachPoint->empty()) + { + DBG << "Using a shared media " + << ret.mediaSource->name + << " attached on " + << ret.attachPoint->path + << std::endl; + removeAttachPoint(); + setAttachPoint(ret.attachPoint); + setMediaSource(ret.mediaSource); + return; + } + + if( !isUseableAttachPoint( attachPoint() ) ) + { + setAttachPoint( createAttachPoint(), true ); + } + std::string mountpoint( attachPoint().asString() ); + std::string mountopts("ro,loop"); + + Mount mount; + mount.mount(isofile.asString(), mountpoint, + _filesystem, mountopts); + + setMediaSource(media); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + while( !(mountsucceeded=isAttached()) && --limit) + { + sleep(1); + } + + if( !mountsucceeded) + { + setMediaSource(MediaSourceRef()); + try + { + mount.umount(attachPoint().asString()); + manager.release(_parentId); + } + catch (const MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW(MediaMountException( + "Unable to verify that the media was mounted", + isofile.asString(), mountpoint + )); + } + } + + // --------------------------------------------------------------- + + void MediaISO::releaseFrom(const std::string & ejectDev) + { + Mount mount; + mount.umount(attachPoint().asString()); + + if( _parentId) + { + // Unmounting the iso already succeeded, + // so don't let exceptions escape. + MediaManager manager; + try + { + manager.release(_parentId); + } + catch ( const Exception & excpt_r ) + { + ZYPP_CAUGHT( excpt_r ); + WAR << "Not been able to cleanup the parent mount." << endl; + } + } + // else: + // the media manager has reset the _parentId + // and will destroy the parent handler itself. + } + + // --------------------------------------------------------------- + void MediaISO::getFile( const OnMediaLocation &file ) const + { + MediaHandler::getFile(file); + } + + // --------------------------------------------------------------- + void MediaISO::getDir(const Pathname &dirname, + bool recurse_r) const + { + MediaHandler::getDir(dirname, recurse_r); + } + + // --------------------------------------------------------------- + void MediaISO::getDirInfo(std::list &retlist, + const Pathname &dirname, + bool dots) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + // --------------------------------------------------------------- + void MediaISO::getDirInfo(filesystem::DirContent &retlist, + const Pathname &dirname, + bool dots) const + { + MediaHandler::getDirInfo(retlist, dirname, dots); + } + + bool MediaISO::getDoesFileExist( const Pathname & filename ) const + { + return MediaHandler::getDoesFileExist( filename ); + } + + ////////////////////////////////////////////////////////////////// + } // namespace media + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// + +// vim: set ts=2 sts=2 sw=2 ai et: + diff --git a/zypp/media/MediaISO.h b/zypp/media/MediaISO.h new file mode 100644 index 0000000..c83e814 --- /dev/null +++ b/zypp/media/MediaISO.h @@ -0,0 +1,77 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaISO.h + * + */ +#ifndef ZYPP_MEDIA_MEDIAISO_H +#define ZYPP_MEDIA_MEDIAISO_H + +#include +#include + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + namespace media + { ////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaISO + // + /** + * @short Implementation class for ISO MediaHandler + * @see MediaHandler + **/ + class MediaISO : public MediaHandler + { + private: + Pathname _isofile; + std::string _filesystem; + + protected: + + void attachTo (bool next = false) override; + void releaseFrom( const std::string & ejectDev = "" ) override; + void getFile( const OnMediaLocation & file ) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + bool getDoesFileExist( const Pathname & filename ) const override; + + public: + + MediaISO(const Url &url_r, + const Pathname &attach_point_hint_r); + + + ~MediaISO() override; + + bool + isAttached() const override; + }; + + + ////////////////////////////////////////////////////////////////// + } // namespace media + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// + +#endif // ZYPP_MEDIA_MEDIAISO_H + +// vim: set ts=2 sts=2 sw=2 ai et: + diff --git a/zypp/media/MediaManager.cc b/zypp/media/MediaManager.cc new file mode 100644 index 0000000..e728d94 --- /dev/null +++ b/zypp/media/MediaManager.cc @@ -0,0 +1,1014 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaManager.cc + * +*/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// + namespace media + { ////////////////////////////////////////////////////////////////// + + ////////////////////////////////////////////////////////////////// + namespace // anonymous + { //////////////////////////////////////////////////////////////// + + struct ManagedMedia; + std::ostream & operator<<( std::ostream & str, const ManagedMedia & obj ); + + // ------------------------------------------------------------- + struct ManagedMedia + { + ~ManagedMedia() + { + try + { + if ( _handler ) + close(); // !!! make sure handler gets properly deleted. + } + catch(...) {} + } + + ManagedMedia(const ManagedMedia &) = delete; + ManagedMedia &operator=(const ManagedMedia &) = delete; + + ManagedMedia(ManagedMedia &&m) noexcept + : desired(m.desired), verifier(std::move(m.verifier)), + _handler(std::move(m._handler)) {} + + static ManagedMedia makeManagedMedia ( const Url &o_url, const Pathname &preferred_attach_point, const MediaVerifierRef &v ) + { + auto handler = MediaHandlerFactory::createHandler( o_url, preferred_attach_point ); + if ( !handler ) { + ERR << "Failed to create media handler" << std::endl; + ZYPP_THROW( MediaSystemException(o_url, "Failed to create media handler")); + } + return ManagedMedia( std::move(handler), v ); + } + + ManagedMedia &operator= ( ManagedMedia &&other ) = default; + + operator bool () const { + return ( _handler ? true : false ); + } + + inline MediaHandler &handler() { + if ( !_handler ) + ZYPP_THROW(MediaNotOpenException("Accessing ManagedMedia after it was closed")); + return *_handler; + } + + inline const MediaHandler &handler() const { + if ( !_handler ) + ZYPP_THROW(MediaNotOpenException("Accessing ManagedMedia after it was closed")); + return *_handler; + } + + std::ostream & dumpOn( std::ostream & str ) const { + if ( !_handler ) + return str << "ManagedMedia( closed )"; + + str << _handler->protocol() << "(" << *_handler << ")"; + return str; + } + + inline void close () + { + /////////////////////////////////////////////////////////////////// + // !!! make shure handler gets properly deleted. + // I.e. release attached media before deleting the handler. + /////////////////////////////////////////////////////////////////// + + try { + handler().release(); + } + catch (const MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + WAR << "Close: " << *this << " (" << excpt_r << ")" << std::endl; + ZYPP_RETHROW(excpt_r); + } + MIL << "Close: " << *this << " (OK)" << std::endl; + } + + inline void + checkAttached(MediaAccessId id) + { + if( !handler().isAttached()) + { + DBG << "checkAttached(" << id << ") not attached" << std::endl; + desired = false; + ZYPP_THROW(MediaNotAttachedException( + handler().url() + )); + } + } + + inline void checkDesired( MediaAccessId id ) + { + checkAttached( id ); + + if ( !desired ) + { + const auto &hdl = handler(); + try { + desired = verifier->isDesiredMedia( handler() ); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT( e ); + + media::MediaNotDesiredException newEx ( hdl.url() ); + newEx.remember( e ); + ZYPP_THROW( newEx ); + } + + if( !desired ) + { + DBG << "checkDesired(" << id << "): not desired (report by " << verifier->info() << ")" << std::endl; + ZYPP_THROW( MediaNotDesiredException( hdl.url() ) ); + } + + DBG << "checkDesired(" << id << "): desired (report by " << verifier->info() << ")" << std::endl; + } else { + DBG << "checkDesired(" << id << "): desired (cached)" << std::endl; + } + } + + bool desired; + MediaVerifierRef verifier; + Pathname deltafile; + + private: + ManagedMedia( std::unique_ptr &&h, MediaVerifierRef v) + : desired (false) + , verifier(std::move(v)) + , _handler ( std::move(h) ) + {} + + std::unique_ptr _handler; + }; + + std::ostream & operator<<( std::ostream & str, const ManagedMedia & obj ) { + return obj.dumpOn( str ); + } + + // ------------------------------------------------------------- + using ManagedMediaMap = std::map; + + //////////////////////////////////////////////////////////////// + } // anonymous + ////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////// + std::string + MediaVerifierBase::info() const + { + return std::string(typeid((*this)).name()); + } + + + ////////////////////////////////////////////////////////////////// + std::string + NoVerifier::info() const + { + return std::string("zypp::media::NoVerifier"); + } + + + ////////////////////////////////////////////////////////////////// + class MediaManager_Impl + { + private: + friend class MediaManager; + + MediaAccessId last_accessid; + ManagedMediaMap mediaMap; + + MediaManager_Impl() + : last_accessid(0) + {} + + public: + + MediaManager_Impl(const MediaManager_Impl &) = delete; + MediaManager_Impl(MediaManager_Impl &&) = delete; + MediaManager_Impl &operator=(const MediaManager_Impl &) = delete; + MediaManager_Impl &operator=(MediaManager_Impl &&) = delete; + + ~MediaManager_Impl() + { + try + { + // remove depending (iso) handlers first + ManagedMediaMap::iterator it; + bool found = false; + do + { + found = false; + for(it = mediaMap.begin(); it != mediaMap.end(); /**/) + { + if( it->second && it->second.handler().dependsOnParent() ) + { + found = true; + // let it forget its parent, we will + // destroy it later (in clear())... + it->second.handler().resetParentId(); + it = mediaMap.erase( it ); // postfix! Incrementing before erase + } else { + ++it; + } + } + } while(found); + + // remove all other handlers + mediaMap.clear(); + } + catch( ... ) + {} + } + + inline MediaAccessId + nextAccessId() + { + return ++last_accessid; + } + + inline bool + hasId(MediaAccessId accessId) const + { + return mediaMap.find(accessId) != mediaMap.end(); + } + + inline ManagedMedia & + findMM(MediaAccessId accessId) + { + ManagedMediaMap::iterator it( mediaMap.find(accessId)); + if( it == mediaMap.end()) + { + ZYPP_THROW(MediaNotOpenException( + "Invalid media access id " + str::numstring(accessId) + )); + } + return it->second; + } + + static inline time_t + getMountTableMTime() + { + return Mount::getMTime(); + } + + static inline MountEntries + getMountEntries() + { + return Mount::getEntries(); + } + + }; + + + ////////////////////////////////////////////////////////////////// + // STATIC + zypp::RW_pointer MediaManager::m_impl; + + + ////////////////////////////////////////////////////////////////// + MediaManager::MediaManager() + { + if( !m_impl) + { + m_impl.reset( new MediaManager_Impl()); + } + } + + // --------------------------------------------------------------- + MediaManager::~MediaManager() + { + } + + // --------------------------------------------------------------- + MediaAccessId + MediaManager::open(const Url &url, const Pathname &preferred_attach_point) + { + // create new access handler for it + MediaVerifierRef verifier( new NoVerifier()); + ManagedMedia tmp = ManagedMedia::makeManagedMedia( url, preferred_attach_point, verifier ); + + MediaAccessId nextId = m_impl->nextAccessId(); + + m_impl->mediaMap.insert( std::make_pair( nextId, std::move(tmp) ) ); + //m_impl->mediaMap[nextId] = std::move(tmp); + + DBG << "Opened new media access using id " << nextId + << " to " << url.asString() << std::endl; + return nextId; + } + + // --------------------------------------------------------------- + void + MediaManager::close(MediaAccessId accessId) + { + // + // The MediaISO handler internally requests an accessId + // of a "parent" handler providing the iso file. + // The parent handler accessId is private to MediaISO, + // but the attached media source may be shared reference. + // This means, that if the accessId exactly matches the + // parent handler id, close was used on uninitialized + // accessId variable (or the accessId was guessed) and + // the close request to this id will be rejected here. + // + ManagedMediaMap::iterator m(m_impl->mediaMap.begin()); + for( ; m != m_impl->mediaMap.end(); ++m) + { + if( m->second.handler().dependsOnParent(accessId, true)) + { + ZYPP_THROW(MediaIsSharedException( + m->second.handler().url().asString() + )); + } + } + + DBG << "Close to access handler using id " + << accessId << " requested" << std::endl; + + ManagedMedia &ref( m_impl->findMM(accessId)); + ref.close(); + + m_impl->mediaMap.erase(accessId); + } + + // --------------------------------------------------------------- + bool + MediaManager::isOpen(MediaAccessId accessId) const + { + ManagedMediaMap::iterator it( m_impl->mediaMap.find(accessId)); + return it != m_impl->mediaMap.end(); + } + + // --------------------------------------------------------------- + std::string + MediaManager::protocol(MediaAccessId accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + return ref.handler().protocol(); + } + + // --------------------------------------------------------------- + bool + MediaManager::downloads(MediaAccessId accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + return ref.handler().downloads(); + } + + // --------------------------------------------------------------- + Url + MediaManager::url(MediaAccessId accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + return ref.handler().url(); + } + + // --------------------------------------------------------------- + void + MediaManager::addVerifier(MediaAccessId accessId, + const MediaVerifierRef &verifier) + { + if( !verifier) + ZYPP_THROW(MediaException("Invalid verifier reference")); + + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.desired = false; + MediaVerifierRef(verifier).swap(ref.verifier); + + DBG << "MediaVerifier change: id=" << accessId << ", verifier=" + << verifier->info() << std::endl; + } + + // --------------------------------------------------------------- + void + MediaManager::delVerifier(MediaAccessId accessId) + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + MediaVerifierRef verifier( new NoVerifier()); + ref.desired = false; + ref.verifier.swap(verifier); + + DBG << "MediaVerifier change: id=" << accessId << ", verifier=" + << verifier->info() << std::endl; + } + + // --------------------------------------------------------------- + bool + MediaManager::setAttachPrefix(const Pathname &attach_prefix) + { + return MediaHandler::setAttachPrefix(attach_prefix); + } + + // --------------------------------------------------------------- + void MediaManager::attach(MediaAccessId accessId) + { + ManagedMedia &ref( m_impl->findMM(accessId)); + auto &hdl = ref.handler(); + + DBG << "attach(id=" << accessId << ")" << std::endl; + + // try first mountable/mounted device + hdl.attach(false); + try + { + ref.checkDesired(accessId); + return; + } + catch (const MediaException & ex) + { + ZYPP_CAUGHT(ex); + + if (!hdl.hasMoreDevices()) + ZYPP_RETHROW(ex); + + if (hdl.isAttached()) + hdl.release(); + } + + MIL << "checkDesired(" << accessId << ") of first device failed," + " going to try others with attach(true)" << std::endl; + + while (hdl.hasMoreDevices()) + { + try + { + // try to attach next device + hdl.attach(true); + ref.checkDesired(accessId); + return; + } + catch (const MediaNotDesiredException & ex) + { + ZYPP_CAUGHT(ex); + + if (!hdl.hasMoreDevices()) + { + MIL << "No desired media found after trying all detected devices." << std::endl; + ZYPP_RETHROW(ex); + } + + AttachedMedia media(hdl.attachedMedia()); + DBG << "Skipping " << media.mediaSource->asString() << ": not desired media." << std::endl; + + hdl.release(); + } + catch (const MediaException & ex) + { + ZYPP_CAUGHT(ex); + + if (!hdl.hasMoreDevices()) + ZYPP_RETHROW(ex); + + AttachedMedia media(hdl.attachedMedia()); + DBG << "Skipping " << media.mediaSource->asString() << " because of exception thrown by attach(true)" << std::endl; + + if (hdl.isAttached()) hdl.release(); + } + } + } + + // --------------------------------------------------------------- + void + MediaManager::release(MediaAccessId accessId, const std::string & ejectDev) + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + DBG << "release(id=" << accessId; + if (!ejectDev.empty()) + DBG << ", " << ejectDev; + DBG << ")" << std::endl; + + if(!ejectDev.empty()) + { + // + // release MediaISO handlers, that are using the one + // specified with accessId, because it provides the + // iso file and it will disappear now (forced release + // with eject). + // + ManagedMediaMap::iterator m(m_impl->mediaMap.begin()); + for( ; m != m_impl->mediaMap.end(); ++m) + { + auto &hdl = m->second.handler(); + if( hdl.dependsOnParent(accessId, false)) + { + try + { + DBG << "Forcing release of handler depending on access id " + << accessId << std::endl; + m->second.desired = false; + hdl.release(); + } + catch(const MediaException &e) + { + ZYPP_CAUGHT(e); + } + } + } + } + ref.desired = false; + ref.handler().release(ejectDev); + } + + // --------------------------------------------------------------- + void + MediaManager::releaseAll() + { + MIL << "Releasing all attached media" << std::endl; + auto releaseAction = []( MediaAccessId mId_r, ManagedMedia & mManagedMedia_r, bool ifDependsOnParent_r ) { + auto & hdl = mManagedMedia_r.handler(); + if ( hdl.dependsOnParent() == ifDependsOnParent_r ) { + try { + if ( hdl.isAttached() ) { + DBG << "Releasing media id " << mId_r << std::endl; + mManagedMedia_r.desired = false; + hdl.release(); + } + else { + DBG << "Media id " << mId_r << " not attached " << std::endl; + } + } + catch ( const MediaException & e ) { + ZYPP_CAUGHT(e); + ERR << "Failed to release media id " << mId_r << std::endl; + } + } + }; + + // 1st pass releases any stacked mounts (ISO) + for ( auto & [ mId, mManagedMedia ] : m_impl->mediaMap ) { + releaseAction( mId, mManagedMedia, /*ifDependsOnParent*/true ); + } + // 2nd pass releases all the rest + for ( auto & [ mId, mManagedMedia ] : m_impl->mediaMap ) { + releaseAction( mId, mManagedMedia, /*ifDependsOnParent*/false ); + } + + MIL << "Exit" << std::endl; + } + + // --------------------------------------------------------------- + void + MediaManager::disconnect(MediaAccessId accessId) + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.handler().disconnect(); + } + + // --------------------------------------------------------------- + bool + MediaManager::isAttached(MediaAccessId accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + return ref.handler().isAttached(); + } + + // --------------------------------------------------------------- + bool MediaManager::isSharedMedia(MediaAccessId accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + return ref.handler().isSharedMedia(); + } + + // --------------------------------------------------------------- + bool + MediaManager::isDesiredMedia(MediaAccessId accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + if( !ref.handler().isAttached()) + { + ref.desired = false; + } + else + { + try { + ref.desired = ref.verifier->isDesiredMedia( ref.handler() ); + } + catch(const zypp::Exception &e) { + ZYPP_CAUGHT(e); + ref.desired = false; + } + } + DBG << "isDesiredMedia(" << accessId << "): " + << (ref.desired ? "" : "not ") + << "desired (report by " + << ref.verifier->info() << ")" << std::endl; + return ref.desired; + } + + // --------------------------------------------------------------- + bool + MediaManager::isDesiredMedia(MediaAccessId accessId, + const MediaVerifierRef &verifier) const + { + MediaVerifierRef v(verifier); + if( !v) + ZYPP_THROW(MediaException("Invalid verifier reference")); + + ManagedMedia &ref( m_impl->findMM(accessId)); + + bool desired = false; + if( ref.handler().isAttached()) + { + try { + desired = v->isDesiredMedia( ref.handler() ); + } + catch(const zypp::Exception &e) { + ZYPP_CAUGHT(e); + desired = false; + } + } + DBG << "isDesiredMedia(" << accessId << "): " + << (desired ? "" : "not ") + << "desired (report by " + << v->info() << ")" << std::endl; + return desired; + } + + // --------------------------------------------------------------- + bool + MediaManager::isChangeable(MediaAccessId accessId) + { + return url(accessId).getScheme() == "cd" || url(accessId).getScheme() == "dvd"; + } + + // --------------------------------------------------------------- + Pathname + MediaManager::localRoot(MediaAccessId accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + Pathname path; + path = ref.handler().localRoot(); + return path; + } + + // --------------------------------------------------------------- + Pathname + MediaManager::localPath(MediaAccessId accessId, + const Pathname & pathname) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + Pathname path; + path = ref.handler().localPath(pathname); + return path; + } + + void + MediaManager::provideFile(MediaAccessId accessId, + const Pathname &filename, + const ByteCount &expectedFileSize ) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + auto loc = OnMediaLocation( filename ) + .setDownloadSize( expectedFileSize ) + .setDeltafile( ref.deltafile ); + + provideFile( accessId, loc ); + } + + // --------------------------------------------------------------- + void + MediaManager::provideFile(MediaAccessId accessId, + const Pathname &filename ) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + auto loc = OnMediaLocation( filename ) + .setDeltafile( ref.deltafile ); + + provideFile( accessId, loc ); + } + + void MediaManager::provideFile( MediaAccessId accessId, const OnMediaLocation &file ) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkDesired(accessId); + + ref.handler().provideFile( file ); + } + + // --------------------------------------------------------------- + void + MediaManager::setDeltafile(MediaAccessId accessId, + const Pathname &filename ) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkDesired(accessId); + + ref.deltafile = filename; + } + + void MediaManager::precacheFiles(MediaAccessId accessId, const std::vector &files) + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkDesired(accessId); + + ref.handler().precacheFiles( files ); + } + + // --------------------------------------------------------------- + void + MediaManager::provideDir(MediaAccessId accessId, + const Pathname &dirname) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkDesired(accessId); + + ref.handler().provideDir(dirname); + } + + // --------------------------------------------------------------- + void + MediaManager::provideDirTree(MediaAccessId accessId, + const Pathname &dirname) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkDesired(accessId); + + ref.handler().provideDirTree(dirname); + } + + // --------------------------------------------------------------- + void + MediaManager::releaseFile(MediaAccessId accessId, + const Pathname &filename) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkAttached(accessId); + + ref.handler().releaseFile(filename); + } + + // --------------------------------------------------------------- + void + MediaManager::releaseDir(MediaAccessId accessId, + const Pathname &dirname) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkAttached(accessId); + + ref.handler().releaseDir(dirname); + } + + + // --------------------------------------------------------------- + void + MediaManager::releasePath(MediaAccessId accessId, + const Pathname &pathname) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + ref.checkAttached(accessId); + + ref.handler().releasePath(pathname); + } + + // --------------------------------------------------------------- + void + MediaManager::dirInfo(MediaAccessId accessId, + std::list &retlist, + const Pathname &dirname, + bool dots) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + // FIXME: ref.checkDesired(accessId); ??? + ref.checkAttached(accessId); + + ref.handler().dirInfo(retlist, dirname, dots); + } + + // --------------------------------------------------------------- + void + MediaManager::dirInfo(MediaAccessId accessId, + filesystem::DirContent &retlist, + const Pathname &dirname, + bool dots) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + // FIXME: ref.checkDesired(accessId); ??? + ref.checkAttached(accessId); + + ref.handler().dirInfo(retlist, dirname, dots); + } + + // --------------------------------------------------------------- + bool + MediaManager::doesFileExist(MediaAccessId accessId, const Pathname & filename ) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + // FIXME: ref.checkDesired(accessId); ??? + ref.checkAttached(accessId); + + return ref.handler().doesFileExist(filename); + } + + // --------------------------------------------------------------- + void + MediaManager::getDetectedDevices(MediaAccessId accessId, + std::vector & devices, + unsigned int & index) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + return ref.handler().getDetectedDevices(devices, index); + } + + // --------------------------------------------------------------- + // STATIC + time_t + MediaManager::getMountTableMTime() + { + return MediaManager_Impl::getMountTableMTime(); + } + + // --------------------------------------------------------------- + // STATIC + MountEntries + MediaManager::getMountEntries() + { + return MediaManager_Impl::getMountEntries(); + } + + // --------------------------------------------------------------- + bool + MediaManager::isUseableAttachPoint(const Pathname &path, + bool mtab) const + { + if( path.empty() || path == "/" || !PathInfo(path).isDir()) + return false; + + // + // check against our current attach points + // + ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin()); + for( ; m != m_impl->mediaMap.end(); ++m) + { + AttachedMedia ret = m->second.handler().attachedMedia(); + if( ret.mediaSource && ret.attachPoint) + { + std::string mnt(ret.attachPoint->path.asString()); + const std::string& our(path.asString()); + + if( our == mnt) + { + // already used as attach point + return false; + } + else + if( mnt.size() > our.size() && + mnt.at(our.size()) == '/' && + !mnt.compare(0, our.size(), our)) + { + // mountpoint is bellow of path + // (would hide the content) + return false; + } + } + } + + if( !mtab) + return true; + + // + // check against system mount entries + // + MountEntries entries( m_impl->getMountEntries()); + MountEntries::const_iterator e; + for( e = entries.begin(); e != entries.end(); ++e) + { + std::string mnt(Pathname(e->dir).asString()); + const std::string& our(path.asString()); + + if( our == mnt) + { + // already used as mountpoint + return false; + } + else + if( mnt.size() > our.size() && + mnt.at(our.size()) == '/' && + !mnt.compare(0, our.size(), our)) + { + // mountpoint is bellow of path + // (would hide the content) + return false; + } + } + + return true; + } + + // --------------------------------------------------------------- + AttachedMedia + MediaManager::getAttachedMedia(MediaAccessId &accessId) const + { + ManagedMedia &ref( m_impl->findMM(accessId)); + + return ref.handler().attachedMedia(); + } + + // --------------------------------------------------------------- + AttachedMedia + MediaManager::findAttachedMedia(const MediaSourceRef &media) const + { + if( !media || media->type.empty()) + return AttachedMedia(); + + ManagedMediaMap::const_iterator m(m_impl->mediaMap.begin()); + for( ; m != m_impl->mediaMap.end(); ++m) + { + if( !m->second.handler().isAttached()) + continue; + + AttachedMedia ret = m->second.handler().attachedMedia(); + if( ret.mediaSource && ret.mediaSource->equals( *media)) + return ret; + } + return AttachedMedia(); + } + + // --------------------------------------------------------------- + void + MediaManager::forceReleaseShared(const MediaSourceRef &media) + { + if( !media || media->type.empty()) + return; + + ManagedMediaMap::iterator m(m_impl->mediaMap.begin()); + for( ; m != m_impl->mediaMap.end(); ++m) + { + if( !m->second.handler().isAttached()) + continue; + + AttachedMedia ret = m->second.handler().attachedMedia(); + if( ret.mediaSource && ret.mediaSource->equals( *media)) + { + m->second.handler().release(); + m->second.desired = false; + } + } + } + + ////////////////////////////////////////////////////////////////// + } // namespace media + //////////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp/media/MediaManager.h b/zypp/media/MediaManager.h new file mode 100644 index 0000000..f1fa81a --- /dev/null +++ b/zypp/media/MediaManager.h @@ -0,0 +1,936 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaManager.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIAMANAGER_H +#define ZYPP_MEDIA_MEDIAMANAGER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace zypp::media +{ + class MediaHandler; + + using MediaNr = unsigned int; + + + /////////////////////////////////////////////////////////////////// + // forward declaration + struct MountEntry; + class MediaManager_Impl; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaVerifierBase + // + /** + * Interface to implement a media verifier. + */ + class MediaVerifierBase //: private zypp::NonCopyable + { + public: + MediaVerifierBase() + {} + + virtual ~MediaVerifierBase() + {} + + /** + * Returns a string with some info about the verifier. + * By default, the type info name is returned. + */ + virtual std::string info() const; + + /* + ** Check if the specified attached media contains + ** the desired media (e.g. SLES10 CD1). + */ + virtual bool isDesiredMedia(const MediaHandler &ref) const = 0; + }; + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : NoVerifier + // + /** + * Dummy default media verifier, which is always happy. + */ + class NoVerifier : public MediaVerifierBase + { + public: + NoVerifier(): MediaVerifierBase() + {} + + ~NoVerifier() override + {} + + /** + * Returns the "zypp::media::NoVerifier" string. + */ + std::string info() const override; + + /* + ** Don't check if the specified attached media contains + ** the desired media number. Always return true. + */ + bool isDesiredMedia(const MediaHandler &ref) const override + { return true; } + }; + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaVerifierRef + // + /** + * A shared reference to the MediaVerifier implementation. + */ + using MediaVerifierRef = zypp::RW_pointer; + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaManager + // + /** + * Manages access to the 'physical' media, e.g CDROM drives, + * Disk volumes, directory trees, etc, using \ref MediaAccessUrl's. + * + * \note The MediaManager class is just an envelope around an + * inner singleton like implementation.
+ * That is, you can create as many managers as you want, + * also temporary in a function call.
+ * But don't declare static MediaManager instances, + * unless you want to force (mutex) initialization order + * problems! + * + * \section MediaAccessUrl Media Access Url + * The MediaManager uses several media access handlers (backends), + * that can be specified by a Media Access URL in its open() method. + * + * All URLs may contain following query parameters, that are + * reserved by the Source classes and unused/ignored by the media + * manager: + * - alias: A source specific media alias string. + * + * Currently, following access handlers (backends) are implemented: + * - \ref MediaCD_Url + * - \ref MediaDISK_Url + * . + * - \ref MediaISO_Url + * - \ref MediaDIR_Url + * . + * - \ref MediaNFS_Url + * - \ref MediaCIFS_Url + * - \ref MediaCurl_Url + * + * \subsection MediaCD_Url MediaCD - CD/DVD drives (cd, dvd) + * The access handler for media on CD / DVD drives. + * - Scheme: + * - cd: Requires a drive supporting CD media. + * - dvd: Prefers a drive supporting DVD media. + * - Examples: + * \code + * "cd:/" + * "cd:/?devices=/dev/hda,/dev/hdb" + * "cd:/subdir?devices=/dev/hda,/dev/hdb" + * + * "dvd:/" + * "dvd:/?devices=/dev/hda,/dev/hdb" + * "dvd:/subdir?devices=/dev/hda,/dev/hdb" + * \endcode + * Note: You can use either "dvd:/" (just path, no authority) + * or "dvd:///" (path and empty authority). + * - Query parameters: + * - devices: + * Optional parameter, containing a comma separated list of + * block device names to use, e.g.: "/dev/sr0,/dev/sr1". + *
+ * The device names will be verified. If one of the provided + * devices is not usable (not a block device, or does not + * support required media type), an exception is thrown. + *
+ * If the devices parameter is not provided (or empty), available + * CD/DVD drives will be auto-detected. The preferred device is + * the one denoted by "/dev/dvd" ("dvd" scheme only) or "/dev/cdrom". + * - Authority: + * A non-empty authority URL component (e.g. containing a host + * name) is not allowed. + * - Path name: + * Mandatory URL component, that specifies a subdirectory on the + * CD/DVD, where the desired files are located. + * + * \subsection MediaDISK_Url MediaDISK - HD disk volumes (hd) + * The access handler for media on a disk volume (partition). + * - Scheme: + * - hd + * - Examples: + * \code + * "hd:/?device=/dev/hda1" + * "hd:/subdir?device=/dev/sda1" + * "hd:/subdir?device=/dev/sda1&filesystem=reiserfs" + * \endcode + * Note: You can use either "hd:/" (just path, no authority) + * or "hd:///" (path and empty authority). + * - Query parameters: + * - device: + * Mandatory parameter specifying the name of the block device of + * the partition to mount. + * - filesystem: + * The name of the filesystem. Defaults to "auto". + * - Authority: + * A non-empty authority URL component is not allowed. + * - Path name: + * Mandatory URL component, that specifies a subdirectory on the disk + * partition, where the desired files are located. + * + * \subsection MediaDIR_Url MediaDIR - Local directory tree (dir, file) + * The access handler to media stored in a local directory tree. + * - Scheme: + * - dir + * - file + * - Examples: + * \code + * "dir:/directory/name" + * "file:/directory/name" + * \endcode + * - Query parameters: + * none + * - Authority: + * A non-empty authority URL component (e.g. containing + * a host name) is not allowed. + * - Path name: + * Mandatory URL component, that specifies a directory, where + * the desired files are located. + * + * \subsection MediaISO_Url MediaISO - Loopback ISO images (iso) + * The access handler for media in a ISO image (loopback mount). + * - Scheme: + * - iso + * - Examples: + * \code + * "iso:/?iso=/path/to/CD1.iso" + * "iso:/?iso=CD1.iso&url=dir:/path/to" + * + * "iso:/?iso=CD1.iso&url=nfs://server/path/to/media" + * "iso:/?iso=CD1.iso&url=hd:/?device=/dev/hda" + * + * "iso:/subdir?iso=DVD1.iso&url=nfs://nfs-server/directory&mnt=/nfs/attach/point&filesystem=udf" + * \endcode + * - Query parameters: + * - iso: + * Mandatory parameter specifying the name of the iso file.
+ * If the url parameter is missed, the iso parameter has to contain + * an absolute iso file name. + * - url: + * Optional parameter specifying the URL to the directory containing + * the iso file.
+ * The supported URL schemes are: hd, dir, + * file, nfs, nfs4, smb, cifs. + * - mnt: + * Optional parameter specifying the prefered attach point for the + * source media url. + * - filesystem: + * Optional name of the filesystem used in the iso file. Defaults + * to "auto". + * - Authority: + * A non-empty authority URL component is not allowed. + * - Path name: + * Mandatory URL component, that specifies a subdirectory inside of + * the iso file, where the desired files are located. + * + * \subsection MediaNFS_Url MediaNFS - NFS directory tree (nfs) + * The access handler for media on NFS exported directory tree. + * - Scheme: + * - nfs + * - nfs + * - Examples: + * \code + * "nfs://nfs-server/exported/path" + * "nfs://nfs-server/exported/path?mountoptions=ro" + * "nfs://nfs-server/exported/path&type=nfs4" + * "nfs4://nfs-server/exported/path" + * \endcode + * - Query parameters: + * - mountoptions: + * The mount options separated by comma ','. + * Default is the "ro" option. + * - type=nfs4: + * Whether to mount as nfs4. This is the default for scheme nfs4. + * - Authority: + * The authority component has to provide a hostname. + * Username, password and port are currently ignored. + * - Path name: + * Mandatory URL component, that specifies the exported + * (sub-)directory on the NFS server, where the desired + * files are located. + * + * \subsection MediaCIFS_Url MediaCIFS - CIFS/SMB directory tree (cifs, smb) + * The access handler for media in a CIFS/SMB shared directory tree. + * - Scheme: + * - cifs + * - smb + * - Examples: + * \code + * "cifs://servername/share/path/on/the/share" + * "cifs://username:passwd@servername/share/path/on/the/share?mountoptions=ro" + * "cifs://username:passwd@servername/share/path/on/the/share?mountoptions=noguest" + * "smb://servername/share/path/on/the/share" + * "smb://username:passwd@servername/share/path/on/the/share?mountoptions=ro" + * \endcode + * Note: There is no difference between cifs and smb scheme + * (any more). In both cases the 'cifs' filesystem is used. + * - Query parameters: + * - mountoptions: + * The mount options separated by a comma ','. Default are the + * "ro" and "guest" options. Specify "noguest" to turn off + * "guest". This is necessary if Samba is configured to reject + * guest connections. + * - workgroup or domain: + * The name of the workgroup. + * - username: + * Alternative username to username in URL authority. + * - password: + * Alternative password to password in URL authority. + * - user: + * Alternative username (cifs specific variant) + * - pass: + * Alternative password (cifs specific variant) + * - Authority: + * The authority component has to provide a hostname. Optionally + * also a username and password. + * - Path name: + * Mandatory URL component, that specifies the share name with + * optional subdirectory, where the desired files are located. + * + * \subsection MediaCurl_Url MediaCurl - FTP/HTTP directory tree (ftp, tftp, http, https) + * The access handler to media directory tree on a ftp/http server. + * - Scheme: + * - ftp + * - tftp + * - http + * - https + * - Examples: + * \code + * "ftp://server/relative/path/to/media/dir" + * "ftp://server/%2fabsolute/path/to/media/dir" + * + * "ftp://user:pass@server/path/to/media/dir" + * "ftp://user:pass@server/%2f/home/user/path/to/media/dir" + * + * "http://server/path/on/server" + * "http://user:pass@server/path" + * "https://user:pass@server/path?proxy=foo&proxyuser=me&proxypass=pw" + * \endcode + * Note: The "ftp" url scheme supports absolute and relative + * paths to the default ftp server directory + * (RFC1738, Section 3.2.2).
+ * To use an absolute path, you have to prepend the path with an + * additional slash, what results in a "/%2f" combination + * (second "/" encoded to "%2f") at the begin of the URL path. + *
+ * This is important, especially in user authenticated ftp, + * where the users home is usually the default directory of the + * server (except when the server chroots into the users home + * directory). + *
+ * For example, if the user "user" has a home directory + * "/home/user", you can use either an URL with a relative path + * to the home directory "ftp://user:pass@server/path/to/media" + * or the absolute path + * "ftp://user:pass@server/%2fhome/user/path/to/media" -- both + * URLs points to the same directory on the server. + * - Query parameters: + * - cookies: + * Turn off using cookies by setting it to "0" (or false, no, off). + * - proxy: + * A proxy hostname or hostname and port separated by ':'. + * Setting the hostname to '_none_' explicitly disables the use of a + * proxy even if configured in /etc/sysconfig/proxy or the environment. + * - proxyport: + * Alternative way to provide the proxy port. + * - proxyuser: + * The proxy username. + * - proxypass: + * The proxy password. + * - ssl_capath: + * The absolute CA directory to use, default is /etc/ssl/certs. + * - ssl_verify: Flag to modify the ssl verify behaviour. + * Valid values are: 'yes', 'no' and a comma separated list of + * 'host' and 'peer' flags. + * - 'no': + * disables ssl verify + * - 'yes': + * enables ssl verify, this is the default + * and is equivalent to 'host,peer'. + * - 'host': The server is considered the intended one, when the + * 'Common Name' field or a 'Subject Alternate Name' field in + * the certificate matches the host name in the URL. + * - 'peer': Verifies whether the certificate provided by the + * server is authentic against the chain of digital signatures + * found in ssl_capath. + * - ssl_clientcert + * Path to the ssl client certificate for authentication to a repo (CURLOPT_SSLCERT). + * - ssl_clientkey + * Path to the ssl client key for authentication to a repo (CURLOPT_SSLKEY). + * - timeout: + * Transfer timeout in seconds between 0 and 3600, 0 disables + * the timeout, default timeout is 180 seconds. + * - auth: A comma separated list of http authentication + * method names to use: 'basic', 'digest', 'ntlm', 'negotiate', + * 'spnego', 'gssnego'. + * Note, that this list depends on the list of methods supported + * by the curl library. + * - mediahandler: Set the mediahandler for this url + * Valid values are: 'curl', 'multicurl' + * - Authority: + * The authority component has to provide a hostname. Optionally + * also a username and password. In case of the 'ftp' scheme, + * username and password defaults to 'anonymous' and 'yast2@'. + * - Path name: + * Mandatory URL component, that specifies the path name on the + * server, where the desired files are located. + * + * Proxy settings: If no proxy settings are present in tha URLs + * query parameters, the media handler reads the system wide proxy + * settings from the /etc/sysconfig/proxy file. + * If a proxy setting was present, but the proxy password not, + * it attempts to read the proxy-user variable from the + * ~/.curlrc (/root/.curlrc) file. + *
+ * If no proxy setting was present, then libzypp does not pass any + * proxy settings to curl, but curl fallbacks to use the content of + * the http_proxy, ftp_proxy, etc environment + * variables. + * + * \subsection MediaPlugin_Url MediaPlugin - custom media handler + * Media access is delegated to a script located in the libzypp + * media plugin directory. The URLs query options are translated + * into commandline arguments passed to the script. + * - Scheme: + * - plugin + * - Examples: + * \code + * "plugin:script?loptv=lvalue&v=optv&lopt=&o&=foo" + * \__________/ \____/ \___/ | \_/ + * __________/__ ____/_ _|_ \ \___ + * / \ / \ / \ /\ / \ + * script --loptv "lvalue" -v "optv" --lopt -o -- foo + * \endcode + * - Query parameters: + * - The URLs query options are translated into commandline + * arguments passed to the script. + * - \b Note: No option may appear twice, as the (option,value) + * pairs are stored in a hash. + * - \b Note: The order in which the query options are passes to the + * script is arbitrary, except for an option with an empty key, which + * is translated into '-- value' and passed as final option. + * - 'c[=[value]]' ist passed as '-c [value]' + * - 'word[=[value]]' ist passed as '--word [value]' + * - '[=value]' ist passed as last args as '-- [value]' + * - \c script<->libzypp communication: + * - \TODO to be documented. + */ + class ZYPP_API MediaManager: private zypp::base::NonCopyable + { + public: + /** + * Creates a MediaManager envelope instance. + * + * In the case, that the inner implementation is not already + * allocated, and the MediaManager constructor was unable to + * allocate it, a std::bad_alloc exception is thrown. + * + * All further instances increase the use counter only. + * + * \throws std::bad_alloc + */ + MediaManager(); + + /** + * Destroys MediaManager envelope instance. + * Decreases the use counter of the inner implementation. + */ + ~MediaManager(); + + /** + * Opens the media access for specified with the url. + * + * If the \p preferred_attach_point parameter does not + * point to a usable attach point directory, the media + * manager automatically creates a temporary attach + * point in a default directory. This default directory + * can be changed using setAttachPrefix() function. + * + * Remember to close() each id you've opened and not + * need any more. It is like a new and delete! + * + * \param url The \ref MediaAccessUrl. + * \param preferred_attach_point The preferred, already + * existing directory, where the media should be + * attached. + * \return a new media access id. + * \throws std::bad_alloc + * \throws MediaException + */ + MediaAccessId + open(const Url &url, const Pathname & preferred_attach_point = ""); + + /** + * Close the media access with specified id. + * \param accessId The media access id to close. + */ + void + close(MediaAccessId accessId); + + /** + * Query if the media access is open / exists. + * + * \param accessId The media access id to query. + * \return true, if access id is known and open. + */ + bool + isOpen(MediaAccessId accessId) const; + + /** + * Query the protocol name used by the media access + * handler. Similar to url().getScheme(). + * + * \param accessId The media access id to query. + * \return The protocol name used by the media access + * handler, otherwise 'unknown'. + * \throws MediaNotOpenException for invalid access id. + */ + std::string + protocol(MediaAccessId accessId) const; + + /** + * Hint if files are downloaded or not. + * \param accessId The media access id to query. + * \return True, if provideFile downloads files. + */ + bool + downloads(MediaAccessId accessId) const; + + /** + * Returns the \ref MediaAccessUrl of the media access id. + * + * \param accessId The media access id to query. + * \return The \ref MediaAccessUrl used by the media access id. + * \throws MediaNotOpenException for invalid access id. + */ + Url + url(MediaAccessId accessId) const; + + public: + /** + * Add verifier implementation for the specified media id. + * By default, the NoVerifier is used. + * + * \param accessId A media access id. + * \param verifier The new verifier. + * \throws MediaNotOpenException for invalid access id. + */ + void + addVerifier(MediaAccessId accessId, + const MediaVerifierRef &verifier); + + /** + * Remove verifier for specified media id. + * It resets the verifier to NoVerifier. + * + * \param accessId A media access id. + * \throws MediaNotOpenException for invalid access id. + */ + void + delVerifier(MediaAccessId accessId); + + public: + /** + * Set or resets the directory name, where the media manager + * handlers create their temporary attach points (see open() + * function). + * It has effect to newly created temporary attach points only. + * + * \param attach_prefix The new prefix for temporary attach + * points, or empty pathname to reset to defaults. + * \return True on success, false if the \p attach_prefix + * parameters contains a path name, that does not + * point to a writable directory. + */ + bool + setAttachPrefix(const Pathname &attach_prefix); + + /** + * Attach the media using the concrete handler (checks all devices). + * + * Remember to release() or close() each id you've attached + * and not need any more. Attach is like an open of a file! + * + * \param accessId A media access id. + * \throws MediaNotOpenException for invalid access id. + */ + void + attach(MediaAccessId accessId); + + /** + * Release the attached media and optionally eject. + * + * If the \p ejectDev parameter is not empty all other access + * id's are released and the specified drive (CD/DVD drive) is + * ejected. + * + * \param accessId A media access id. + * \param ejectDev Device to eject. None if empty. + * \throws MediaNotOpenException for invalid access id. + */ + void + release(MediaAccessId accessId, const std::string & ejectDev = ""); + + /** + * Release all attached media. + */ + void + releaseAll(); + + /** + * Disconnect a remote media. + * + * This is useful for media which e.g. holds open a connection + * to a server like FTP. After calling disconnect() the media + * object (attach point) is still valid and files are present. + * + * But after calling disconnect(), it's not possible to call + * fetch more data using the provideFile() or provideDir() + * functions anymore. + * + * \param accessId A media access id. + * \throws MediaNotOpenException for invalid access id. + */ + void + disconnect(MediaAccessId accessId); + + /** + * Check if media is attached or not. + * + * \param accessId A media access id. + * \return True if media is attached. + * \throws MediaNotOpenException for invalid access id. + */ + bool + isAttached(MediaAccessId accessId) const; + + /** + * Returns information if media is on a shared + * physical device or not. + * + * \param accessId A media access id. + * \return True if it is shared, false if not. + * \throws MediaNotOpenException for invalid access id. + */ + bool + isSharedMedia(MediaAccessId accessId) const; + + /** + * Ask the registered verifier if the attached + * media is the desired one or not. + * + * \param accessId A media access id. + * \return True if media is attached and desired + * according to the actual verifier. + * \throws MediaNotOpenException for invalid access id. + */ + bool + isDesiredMedia(MediaAccessId accessId) const; + + /** + * Ask the specified verifier if the attached + * media is the desired one or not. + * + * \param accessId A media access id. + * \param verifier A verifier to use. + * \return True if media is attached and desired + * according to the specified verifier. + * \throws MediaNotOpenException for invalid access id. + */ + bool + isDesiredMedia(MediaAccessId accessId, + const MediaVerifierRef &verifier) const; + + /** + * Simple check, based on media's URL scheme, telling whether the + * it is possible to physically change the media inside its drive, like + * CDs or DVDs. Useful to decide whether to request media change from + * user or not. + * + * \param accessId The media access id. + * \return false if the media is not changeable, + * true otherwise. + * \throws MediaNotOpenException for invalid access id. + */ + bool + isChangeable(MediaAccessId accessId); + + /** + * Return the local directory that corresponds to medias url, + * no matter if media isAttached or not. Files requested will + * be available at 'localRoot() + filename' or even better + * 'localPath( filename )' + * + * \param accessId A media access id. + * \returns The directory name pointing to the media root + * in local filesystem or an empty pathname if the + * media is not attached. + * \throws MediaNotOpenException for invalid access id. + */ + Pathname + localRoot(MediaAccessId accessId) const; + + /** + * Shortcut for 'localRoot() + pathname', but returns an empty + * pathname if media is not attached. + * Files provided will be available at 'localPath(filename)'. + * + * \param accessId A media access id. + * \param pathname A path name relative to the localRoot(). + * \returns The directory name in local filesystem pointing + * to the desired relative pathname on the media + * or an empty pathname if the media is not attached. + * \throws MediaNotOpenException for invalid access id. + */ + Pathname + localPath(MediaAccessId accessId, const Pathname & pathname) const; + + public: + + /** + * \deprecated Deprecated function, please use the provideFile version that + * takes a \ref OnMediaLocation argument + */ + ZYPP_DEPRECATED void + provideFile(MediaAccessId accessId, + const Pathname &filename, + const ByteCount &expectedFileSize) const; + + /** + * \deprecated Deprecated function, please use the provideFile version that + * takes a \ref OnMediaLocation argument + */ + ZYPP_DEPRECATED void + provideFile(MediaAccessId accessId, + const Pathname &filename ) const; + + + /** + * Provide provide file denoted by relative path below of the + * 'attach point' of the specified media and the path prefix + * on the media. + * + * \param accessId The media access id to use. + * \param file The \ref OnMediaLocation specifiying the file to download + * + * \throws MediaNotOpenException in case of invalid access id. + * \throws MediaNotAttachedException in case, that the media is not attached. + * \throws MediaNotDesiredException in case, that the media verification failed. + * \throws MediaNotAFileException in case, that the requested filename is not a file. + * \throws MediaFileNotFoundException in case, that the requested filenamedoes not exists. + * \throws MediaWriteException in case, that the file can't be copied from from remote source. + * \throws MediaSystemException in case a system operation fails. + * \throws MediaException derived exception, depending on the url (handler). + */ + void + provideFile(MediaAccessId accessId, + const OnMediaLocation &file ) const; + + /** + * FIXME: see MediaAccess class. + */ + void + provideDir(MediaAccessId accessId, + const Pathname &dirname) const; + + /** + * FIXME: see MediaAccess class. + */ + void + provideDirTree(MediaAccessId accessId, + const Pathname &dirname) const; + + /** + * FIXME: see MediaAccess class. + */ + void + releaseFile(MediaAccessId accessId, + const Pathname &filename) const; + + /** + * FIXME: see MediaAccess class. + */ + void + releaseDir(MediaAccessId accessId, + const Pathname &dirname) const; + + /** + * FIXME: see MediaAccess class. + */ + void + releasePath(MediaAccessId accessId, + const Pathname &pathname) const; + + /** + * FIXME: see MediaAccess class. + */ + void + dirInfo(MediaAccessId accessId, + std::list &retlist, + const Pathname &dirname, + bool dots = true) const; + + /** + * FIXME: see MediaAccess class. + */ + void + dirInfo(MediaAccessId accessId, + filesystem::DirContent &retlist, + const Pathname &dirname, + bool dots = true) const; + + /** + * FIXME: see MediaAccess class. + */ + bool doesFileExist(MediaAccessId accessId, + const Pathname & filename ) const; + + /** + * Fill in a vector of detected ejectable devices and the index of the + * currently attached device within the vector. The contents of the vector + * are the device names (/dev/cdrom and such). + * + * \param accessId Medium id. + * \param devices vector to load with the device names + * \param index index of the currently used device in the devices vector + */ + void + getDetectedDevices(MediaAccessId accessId, + std::vector & devices, + unsigned int & index) const; + + ZYPP_DEPRECATED void + setDeltafile(MediaAccessId accessId, + const Pathname &filename ) const; + + /** + * Tries to fetch the given files and precaches them. Those files + * need to be queried using provideFile and can be read from the cache directly. + * The implementation is not allowed to block but needs to use seperate means to + * download the files concurrently. + * A backend can choose to completely ignore this functionaly, the default implementation + * does nothing. + * + * \param accessId Medium id. + * \param files List of files that should be precached + */ + void precacheFiles( MediaAccessId accessId, + const std::vector &files); + + public: + /** + * Get the modification time of the /etc/mtab file. + * \return Modification time of the /etc/mtab file. + */ + static time_t + getMountTableMTime(); + + /** + * Get current mount entries from /etc/mtab file. + * \return Current mount entries from /etc/mtab file. + */ + static std::vector + getMountEntries(); + + /** + * Check if the specified \p path is useable as + * attach point. + * + * \param path The attach point to check. + * \param mtab Whether to check against the mtab, too. + * \return True, if it is a directory and there are + * no another attach points bellow of it. + */ + bool + isUseableAttachPoint(const Pathname &path, + bool mtab=true) const; + + private: + friend class MediaHandler; + + /** + * \internal + * Return the attached media reference of the specified + * media access id. Used to resolve nested attachments + * as used in the MediaISO (iso-loop) handler. + * Causes temporary creation of a shared attachment + * (increases reference counters on attachedMedia). + * \param media A media access id. + */ + AttachedMedia + getAttachedMedia(MediaAccessId &accessId) const; + + /** + * \internal + * Called by media handler in while attach() to retrieve + * attached media reference matching the specified media + * source reference. + * Causes temporary creation of a shared attachment + * (increases reference counters on attachedMedia). + * \param media The media source reference to search for. + */ + AttachedMedia + findAttachedMedia(const MediaSourceRef &media) const; + + /** + * \internal + * Called by media handler in case of relase(eject=true) + * to release all access id's using the specified media. + * Causes temporary creation of a shared attachment + * (increases reference counters on attachedMedia). + * \param media The media source reference to release. + */ + void + forceReleaseShared(const MediaSourceRef &media); + + private: + /** + * Static reference to the implementation (singleton). + */ + static zypp::RW_pointer m_impl; + }; + + //////////////////////////////////////////////////////////////////// +} // namespace zypp::media +////////////////////////////////////////////////////////////////////// + +#endif // ZYPP_MEDIA_MEDIAMANAGER_H + +/* +** vim: set ts=2 sts=2 sw=2 ai et: +*/ diff --git a/zypp/media/MediaMultiCurl.cc b/zypp/media/MediaMultiCurl.cc new file mode 100644 index 0000000..563a9df --- /dev/null +++ b/zypp/media/MediaMultiCurl.cc @@ -0,0 +1,1818 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaMultiCurl.cc + * +*/ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; +using namespace zypp::base; + +#undef CURLVERSION_AT_LEAST +#define CURLVERSION_AT_LEAST(M,N,O) LIBCURL_VERSION_NUM >= ((((M)<<8)+(N))<<8)+(O) + +namespace zypp { + namespace media { + + using MultiByteHandler = zyppng::CurlMultiPartHandler; + + +/*! + * General Idea how the MultiFetchRequest pulls data from the server + * + * We download files in ranges using a worker per mirror URL and we want to limit the number of requests we need to start + * for a download. Since we can not control the size of the ranges we need from files, those + * are defined by the delta algorithm, we need to fetch multiple ranges per request. This however + * adds another factor, the delta argorithm marks all ranges that we can reuse already, but those are scattered + * all across the file we need to download, meaning we will have a list of ranges with gaps between them. + * + * For example we need the ranges: [(0,100), (200,100), (300,100), (1000, 100) ]. + * Because of the gaps we can not just coalesce many ranges into a big range (0, 1100), we need to utilize multi range HTTP requests + * and fetch [(0,100), (200, 200), (1000, 100)] as multibyte HTTP requests. + * + * Based on the filesize we calculate the nr of bytes we want to fetch per request and group the required ranges + * into what we call "Stripes". Doing that will help us with the stealing algorithm that is described later. + * + * The logic is split in 2 main parts: + * - multifetchrequest, which is the class that holds information about the full request itself + * - multifetchworker, which is the worker for a specific mirror working on a specific Stripe + * + * When the algorithm is started, multifetchrequest will spawn a worker ( up to configured max workers ) for each mirror URL, + * then calls multifetchworker::nextjob() for each worker and waits for their results on a internal event loop. + * + * A worker when starting up will first go into a DNS check to see if the mirror it has does resolve, then it will look into the + * request instance to see what the next stripe is it needs to download. There is a simple stripe index , called _stripeNo, in the + * parent request that tells the worker what the next stripe is that needs fetching. If that number is still a valid index the worker + * will increase it and claim the stripe for itself. Building a HTTP request and waiting for its result. + * + * Some servers do only support fetching a max number of ranges, in that instance the worker will finish the request and return true + * for "hasMoreWork". In that cases the event loop in multifetchrequest will tell the worker to continue the job until all blocks were + * fetched. + * + * Before writing to a block or starting a new block, a worker will first check if it was already marked as FINALIZED in the stripe, if that is the case the worker will + * set itself to WORKER_DISCARD and ask for a new job, otherwise it will start writing into the block and set it to COMPETING. + * + * At the end of writing a block, the worker will first check if the data it received was valid via the given digest and go into WORKER_BROKEN if is not. + * When valid data was received it checks the state of the block in the stripe, if it is set to FETCH the block is marked as + * FINALIZED and considered to be done and valid. If the block is already marked as COMPETING, the worker will recalc the checksum and mark the block + * as FINALIZED if the result is valid, otherwise the block is marked with REFETCH to force redownloading it. + * + * In case of a error, the request is stopped and the worker reports back to the multifetchrequest event loop which will set the + * worker into a "Broken" state stopping it from fetching more jobs. If there are more mirrors available, it will spawn a new worker + * which then can also start to claim jobs. This makes sure that even when we have errors, we try all mirrors until we run out of them. + * The broken worker will not be deleted, instead it will stay in the list of workers until another one will "steal" the work from it and + * hopefully finish it. + * + * Now, once all Stripes have been claimed and a worker was asked to get the next job it will start to steal from others. Meaning it will + * go over the list of currently running workers and try to figure out the best candidate for stealing. This is based on the performance of the + * worker and how many workers already compete on a stripe. + * + * - If the worker finds a best candidate it will start competition on the stripe and + * will request all ranges not marked as "FINALIZED" from the server as well. The worker finishing a block first wins, the one loosing will + * stop downloading and report back to get a next job if there is one. + * - If the worker can not find a best candidate , it will set itself to "WORKER_DONE" and stop stealing stripes + * + * + * Once a worker is done it needs to check if all blocks from its current stripe are marked as FINALIZED, otherwise they need to be refetched. + */ + + + + +class multifetchrequest; + +struct Stripe { + + enum RState { + PENDING, //< Pending Range + FETCH, //< Fetch is running! + COMPETING, //< Competing workers, needs checksum recheck + FINALIZED, //< Done, don't write to it anymore + REFETCH //< This block needs a refetch + }; + + std::vector blocks; //< required block numbers from blocklist + std::vector blockStates; //< current state of each block in blocks +}; + +enum MultiFetchWorkerState { + WORKER_STARTING, + WORKER_LOOKUP, + WORKER_FETCH, + WORKER_DISCARD, + WORKER_DONE, + WORKER_SLEEP, + WORKER_BROKEN +}; + +// Hack: we derive from MediaCurl just to get the storage space for +// settings, url, curlerrors and the like +class multifetchworker : private MediaCurl, public zyppng::CurlMultiPartDataReceiver { + friend class multifetchrequest; + +public: + multifetchworker(int no, multifetchrequest &request, const Url &url); + multifetchworker(const multifetchworker &) = delete; + multifetchworker(multifetchworker &&) = delete; + multifetchworker &operator=(const multifetchworker &) = delete; + multifetchworker &operator=(multifetchworker &&) = delete; + ~multifetchworker() override; + + /*! + * Fetches the next job from the parent request, + * then calls runjob to execute it + */ + void nextjob(); + + /*! + * Fetches all jobs from the currently claimed stripe or calls nextjob() + * if the current stripe has all blocks marked as FINALIZED + */ + void runjob(); + + /*! + * Continues a running job, only called by the dispatcher + * if the multibyte handler indicates it has more work + * to trigger fetching the next range batch + */ + bool continueJob(); + + /*! + * Rechecks the checksum of the given block at \a blockIdx. + * The index is relative to the workers blocklist + */ + bool recheckChecksum( off_t blockIdx ); + + /*! + * Stop all competing workers and set them to WORKER_DISCARD + */ + void disableCompetition(); + + /*! + * Starts the dns check + */ + void checkdns(); + void adddnsfd( std::vector &waitFds ); + void dnsevent(const std::vector &waitFds ); + + const int _workerno; + + MultiFetchWorkerState _state = WORKER_STARTING; + bool _competing = false; + + std::vector _blocks; + std::vector _rangeToStripeBlock; + + MultiByteHandler::ProtocolMode _protocolMode = MultiByteHandler::ProtocolMode::Basic; + std::unique_ptr _multiByteHandler; + + off_t _stripe = 0; //< The current stripe we are downloading + size_t _datasize = 0; //< The nr of bytes we need to download overall + + double _starttime = 0; //< When was the current job started + size_t _datareceived = 0; //< Data downloaded in the current job only + off_t _received = 0; //< Overall data"MultiByteHandler::prepare failed" fetched by this worker + + double _avgspeed = 0; + double _maxspeed = 0; + + double _sleepuntil = 0; + +private: + void run(); + void stealjob(); + bool setupHandle(); + MultiByteHandler::Range rangeFromBlock( off_t blockNo ) const; + + size_t writefunction ( char *ptr, std::optional offset, size_t bytes ) override; + size_t headerfunction ( char *ptr, size_t bytes ) override; + bool beginRange ( off_t range, std::string &cancelReason ) override; + bool finishedRange ( off_t range, bool validated, std::string &cancelReason ) override; + + multifetchrequest *_request = nullptr; + int _pass = 0; + std::string _urlbuf; + + pid_t _pid = 0; + int _dnspipe = -1; +}; + +class multifetchrequest : protected internal::CurlPollHelper::CurlPoll { +public: + multifetchrequest(const MediaMultiCurl *context, Pathname filename, + Url baseurl, CURLM *multi, FILE *fp, + callback::SendReport *report, + MediaBlockList &&blklist, off_t filesize); + multifetchrequest(const multifetchrequest &) = delete; + multifetchrequest(multifetchrequest &&) = delete; + multifetchrequest &operator=(const multifetchrequest &) = delete; + multifetchrequest &operator=(multifetchrequest &&) = delete; + ~multifetchrequest(); + + void run(std::vector &urllist); + static ByteCount makeBlksize( uint maxConns, size_t filesize ); + + MediaBlockList &blockList() { + return _blklist; + } + +protected: + friend class multifetchworker; + + const MediaMultiCurl *_context; + const Pathname _filename; + Url _baseurl; + + FILE *_fp = nullptr; + callback::SendReport *_report = nullptr; + MediaBlockList _blklist; + + std::vector _requiredStripes; // all the data we need + + off_t _filesize = 0; //< size of the file we want to download + + std::list< std::unique_ptr > _workers; + bool _stealing = false; + bool _havenewjob = false; + + zypp::ByteCount _defaultBlksize = 0; //< The blocksize to use if the metalink file does not specify one + off_t _stripeNo = 0; //< next stripe to download + + size_t _activeworkers = 0; + size_t _lookupworkers = 0; + size_t _sleepworkers = 0; + double _minsleepuntil = 0; + bool _finished = false; + + off_t _totalsize = 0; //< nr of bytes we need to download ( e.g. filesize - ( bytes reused from deltafile ) ) + off_t _fetchedsize = 0; + off_t _fetchedgoodsize = 0; + + double _starttime = 0; + double _lastprogress = 0; + + double _lastperiodstart = 0; + double _lastperiodfetched = 0; + double _periodavg = 0; + +public: + double _timeout = 0; + double _connect_timeout = 0; + double _maxspeed = 0; + int _maxworkers = 0; +}; + +constexpr auto MIN_REQ_MIRRS = 4; +constexpr auto MAXURLS = 10; + +// TCP communication scales up as a connection proceeds. This is due to TCP slowstart where +// the congestion window scales up. The stripe calculation assumes that every package can be fairly +// downloaded from multiple mirrors omits that attempting to download say 1MB from 4 mirrors +// means 4 requests of 256k, where then you have four congestion windows that need to increase +// meaning the overall download speed is significantly lower. Counter intuitively this leads to +// cases where *more* mirrors being available to zypper significantly lowers performance. +// +// Instead, there should be a minimum stripe size cap. This way any item smaller than the value +// is downloaded in a single request, where as larger items are downloaded from many mirrors +// but each range has enough time to increase it's congestion window to something reasonable. +// +// Initial value 4 MB; +constexpr auto MIN_STRIPE_SIZE_KB = 4096; + +////////////////////////////////////////////////////////////////////// + +static double +currentTime() +{ +#if _POSIX_C_SOURCE >= 199309L + struct timespec ts; + if ( clock_gettime( CLOCK_MONOTONIC, &ts) ) + return 0; + return ts.tv_sec + ts.tv_nsec / 1000000000.; +#else + struct timeval tv; + if (gettimeofday(&tv, NULL)) + return 0; + return tv.tv_sec + tv.tv_usec / 1000000.; +#endif +} + +size_t +multifetchworker::writefunction(char *ptr, std::optional offset, size_t bytes) +{ + if ( _state == WORKER_BROKEN || _state == WORKER_DISCARD ) + return bytes ? 0 : 1; + + double now = currentTime(); + + // update stats of overall data + _datareceived += bytes; + _received += bytes; + _request->_lastprogress = now; + + const auto &currRange = _multiByteHandler->currentRange(); + if (!currRange) + return 0; // we always write to a range + + auto &stripeDesc = _request->_requiredStripes[_stripe]; + if ( !_request->_fp || stripeDesc.blockStates[ _rangeToStripeBlock[*currRange] ] == Stripe::FINALIZED ) { + // someone else finished our block first! + // we stop here and fetch new jobs if there are still some + _state = WORKER_DISCARD; + _competing = false; + return 0; + } + + const auto &blk = _blocks[*currRange]; + off_t seekTo = blk.start + blk.bytesWritten; + + if ( ftell( _request->_fp ) != seekTo ) { + // if we can't seek the file there is no purpose in trying again + if (fseeko(_request->_fp, seekTo, SEEK_SET)) + return bytes ? 0 : 1; + } + + size_t cnt = fwrite(ptr, 1, bytes, _request->_fp); + _request->_fetchedsize += cnt; + return cnt; +} + +bool multifetchworker::beginRange ( off_t workerRangeOff, std::string &cancelReason ) +{ + auto &stripeDesc = _request->_requiredStripes[_stripe]; + auto stripeRangeOff = _rangeToStripeBlock[workerRangeOff]; + const auto &currRangeState = stripeDesc.blockStates[stripeRangeOff]; + + if ( currRangeState == Stripe::FINALIZED ){ + cancelReason = "Cancelled because stripe block is already finalized"; + _state = WORKER_DISCARD; + WAR << "#" << _workerno << ": trying to start a range ("<_stealing << endl; + return false; + } + stripeDesc.blockStates[stripeRangeOff] = currRangeState == Stripe::PENDING ? Stripe::FETCH : Stripe::COMPETING; + return true; +} + +bool multifetchworker::finishedRange ( off_t workerRangeOff, bool validated, std::string &cancelReason ) +{ + auto &stripeDesc = _request->_requiredStripes[_stripe]; + auto stripeRangeOff = _rangeToStripeBlock[workerRangeOff]; + const auto &currRangeState = stripeDesc.blockStates[stripeRangeOff]; + + if ( !validated ) { + // fail, worker will go into WORKER_BROKEN + cancelReason = "Block failed to validate"; + return false; + } + + if ( currRangeState == Stripe::FETCH ) { + // only us who wrote here, block is finalized + stripeDesc.blockStates[stripeRangeOff] = Stripe::FINALIZED; + _request->_fetchedgoodsize += _blocks[workerRangeOff].len; + } else { + // others wrote here, we need to check the full checksum + if ( recheckChecksum ( workerRangeOff ) ) { + stripeDesc.blockStates[stripeRangeOff] = Stripe::FINALIZED; + _request->_fetchedgoodsize += _blocks[workerRangeOff].len; + } else { + // someone messed that block up, set it to refetch but continue since our + // data is valid + WAR << "#" << _workerno << ": Broken data in COMPETING block, requesting refetch. Stealing is: " << _request->_stealing << endl; + stripeDesc.blockStates[stripeRangeOff] = Stripe::REFETCH; + } + } + return true; +} + +size_t +multifetchworker::headerfunction( char *p, size_t bytes ) +{ + size_t l = bytes; + if (l > 9 && !strncasecmp(p, "Location:", 9)) { + std::string line(p + 9, l - 9); + if (line[l - 10] == '\r') + line.erase(l - 10, 1); + XXX << "#" << _workerno << ": redirecting to" << line << endl; + return bytes; + } + + const auto &repSize = _multiByteHandler->reportedFileSize (); + if ( repSize && *repSize != _request->_filesize ) { + XXX << "#" << _workerno << ": filesize mismatch" << endl; + _state = WORKER_BROKEN; + setCurlError("filesize mismatch"); + return 0; + } + + return bytes; +} + +multifetchworker::multifetchworker(int no, multifetchrequest &request, const Url &url) +: MediaCurl(url, Pathname()) +, _workerno( no ) +, _maxspeed( request._maxspeed ) +, _request ( &request ) +{ + Url curlUrl( clearQueryString(url) ); + _urlbuf = curlUrl.asString(); + _curl = _request->_context->fromEasyPool(_url.getHost()); + if (_curl) + XXX << "reused worker from pool" << endl; + if (!_curl && !(_curl = curl_easy_init())) + { + _state = WORKER_BROKEN; + setCurlError("curl_easy_init failed"); + return; + } + + if ( url.getScheme() == "http" || url.getScheme() == "https" ) + _protocolMode = MultiByteHandler::ProtocolMode::HTTP; + + setupHandle(); + checkdns(); +} + +bool multifetchworker::setupHandle() +{ + try { + setupEasy(); + } catch (Exception &ex) { + curl_easy_cleanup(_curl); + _curl = 0; + _state = WORKER_BROKEN; + setCurlError("curl_easy_setopt failed"); + return false; + } + curl_easy_setopt(_curl, CURLOPT_PRIVATE, this); + curl_easy_setopt(_curl, CURLOPT_URL, _urlbuf.c_str()); + + // if this is the same host copy authorization + // (the host check is also what curl does when doing a redirect) + // (note also that unauthorized exceptions are thrown with the request host) + if ( _url.getHost() == _request->_context->_url.getHost()) { + _settings.setUsername(_request->_context->_settings.username()); + _settings.setPassword(_request->_context->_settings.password()); + _settings.setAuthType(_request->_context->_settings.authType()); + if ( _settings.userPassword().size() ) { + curl_easy_setopt(_curl, CURLOPT_USERPWD, _settings.userPassword().c_str()); + std::string use_auth = _settings.authType(); + if (use_auth.empty()) + use_auth = "digest,basic"; // our default + long auth = CurlAuthData::auth_type_str2long(use_auth); + if( auth != CURLAUTH_NONE) + { + XXX << "#" << _workerno << ": Enabling HTTP authentication methods: " << use_auth + << " (CURLOPT_HTTPAUTH=" << auth << ")" << std::endl; + curl_easy_setopt(_curl, CURLOPT_HTTPAUTH, auth); + } + } + } + return true; +} + +multifetchworker::~multifetchworker() +{ + if (_curl) + { + if (_state == WORKER_FETCH || _state == WORKER_DISCARD) + curl_multi_remove_handle(_request->_multi, _curl); + if (_state == WORKER_DONE || _state == WORKER_SLEEP) + { +#if CURLVERSION_AT_LEAST(7,15,5) + curl_easy_setopt(_curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)0); +#endif + curl_easy_setopt(_curl, CURLOPT_PRIVATE, (void *)0); + curl_easy_setopt(_curl, CURLOPT_WRITEFUNCTION, (void *)0); + curl_easy_setopt(_curl, CURLOPT_WRITEDATA, (void *)0); + curl_easy_setopt(_curl, CURLOPT_HEADERFUNCTION, (void *)0); + curl_easy_setopt(_curl, CURLOPT_HEADERDATA, (void *)0); + _request->_context->toEasyPool(_url.getHost(), _curl); + } + else + curl_easy_cleanup(_curl); + _curl = 0; + } + if (_pid) + { + kill(_pid, SIGKILL); + int status = 0; + zyppng::eintrSafeCall( waitpid, _pid, &status, 0); + _pid = 0; + } + if (_dnspipe != -1) + { + close(_dnspipe); + _dnspipe = -1; + } + // the destructor in MediaCurl doesn't call disconnect() if + // the media is not attached, so we do it here manually + disconnectFrom(); +} + +static inline bool env_isset(const std::string& name) +{ + const char *s = getenv(name.c_str()); + return s && *s ? true : false; +} + +void +multifetchworker::checkdns() +{ + std::string host = _url.getHost(); + + if (host.empty()) + return; + + if (_request->_context->isDNSok(host)) + return; + + // no need to do dns checking for numeric hosts + char addrbuf[128]; + if (inet_pton(AF_INET, host.c_str(), addrbuf) == 1) + return; + if (inet_pton(AF_INET6, host.c_str(), addrbuf) == 1) + return; + + // no need to do dns checking if we use a proxy + if (!_settings.proxy().empty()) + return; + if (env_isset("all_proxy") || env_isset("ALL_PROXY")) + return; + std::string schemeproxy = _url.getScheme() + "_proxy"; + if (env_isset(schemeproxy)) + return; + if (schemeproxy != "http_proxy") + { + std::transform(schemeproxy.begin(), schemeproxy.end(), schemeproxy.begin(), ::toupper); + if (env_isset(schemeproxy)) + return; + } + + XXX << "checking DNS lookup of " << host << endl; + int pipefds[2]; + if (pipe(pipefds)) + { + _state = WORKER_BROKEN; + setCurlError("DNS pipe creation failed"); + return; + } + _pid = fork(); + if (_pid == pid_t(-1)) + { + close(pipefds[0]); + close(pipefds[1]); + _pid = 0; + _state = WORKER_BROKEN; + setCurlError("DNS checker fork failed"); + return; + } + else if (_pid == 0) + { + close(pipefds[0]); + // XXX: close all other file descriptors + struct addrinfo *ai = nullptr, aihints; + memset(&aihints, 0, sizeof(aihints)); + aihints.ai_family = PF_UNSPEC; + int tstsock = socket(PF_INET6, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (tstsock == -1) + aihints.ai_family = PF_INET; + else + close(tstsock); + aihints.ai_socktype = SOCK_STREAM; + aihints.ai_flags = AI_CANONNAME; + unsigned int connecttimeout = _request->_connect_timeout; + if (connecttimeout) + alarm(connecttimeout); + signal(SIGALRM, SIG_DFL); + if (getaddrinfo(host.c_str(), NULL, &aihints, &ai)) + _exit(1); + _exit(0); + } + close(pipefds[1]); + _dnspipe = pipefds[0]; + _state = WORKER_LOOKUP; +} + +void +multifetchworker::adddnsfd(std::vector &waitFds) +{ + if (_state != WORKER_LOOKUP) + return; + + waitFds.push_back ( + GPollFD { + .fd = _dnspipe, + .events = G_IO_IN | G_IO_HUP | G_IO_ERR, + .revents = 0 + }); +} + +void +multifetchworker::dnsevent( const std::vector &waitFds ) +{ + bool hasEvent = std::any_of( waitFds.begin (), waitFds.end(),[this]( const GPollFD &waitfd ){ + return ( waitfd.fd == _dnspipe && waitfd.revents != 0 ); + }); + + if (_state != WORKER_LOOKUP || !hasEvent) + return; + int status = 0; + zyppng::eintrSafeCall( waitpid, _pid, &status, 0); + _pid = 0; + if (_dnspipe != -1) + { + close(_dnspipe); + _dnspipe = -1; + } + if (!WIFEXITED(status)) + { + _state = WORKER_BROKEN; + setCurlError("DNS lookup failed"); + _request->_activeworkers--; + return; + } + int exitcode = WEXITSTATUS(status); + XXX << "#" << _workerno << ": DNS lookup returned " << exitcode << endl; + if (exitcode != 0) + { + _state = WORKER_BROKEN; + setCurlError("DNS lookup failed"); + _request->_activeworkers--; + return; + } + _request->_context->setDNSok(_url.getHost()); + nextjob(); +} + +bool multifetchworker::recheckChecksum( off_t workerRangeIdx ) +{ + // XXX << "recheckChecksum block " << _blkno << endl; + if (!_request->_fp || !_datasize || !_blocks.size() ) + return true; + + auto &blk = _blocks[workerRangeIdx]; + if ( !blk._digest ) + return true; + + const auto currOf = ftell( _request->_fp ); + if ( currOf == -1 ) + return false; + + if (fseeko(_request->_fp, blk.start, SEEK_SET)) + return false; + + zypp::Digest newDig = blk._digest->clone(); + + char buf[4096]; + size_t l = blk.len; + while (l) { + size_t cnt = l > sizeof(buf) ? sizeof(buf) : l; + if (fread(buf, cnt, 1, _request->_fp) != 1) + return false; + newDig.update(buf, cnt); + l -= cnt; + } + + if (fseeko(_request->_fp, currOf, SEEK_SET)) + return false; + + blk._digest = std::move(newDig); + if (!_multiByteHandler->validateRange(blk)) { + WAR << "#" << _workerno << " Stripe: " << _stripe << ": Stripe-Block: " << _rangeToStripeBlock[workerRangeIdx] << " failed to validate" << endl; + return false; + } + + return true; +} + +/*! + * Calculates the range information for the given \a blkNo ( actual block index in the request blocklist, NOT the stripe or worker index ) + */ +zyppng::CurlMultiPartHandler::Range multifetchworker::rangeFromBlock( off_t blkNo ) const +{ + UByteArray sum; + std::optional digest; + std::optional relDigLen; + std::optional blkSumPad; + + const auto &blk = _request->_blklist.getBlock( blkNo ); + if ( _request->_blklist.haveChecksum ( blkNo ) ) { + sum = _request->_blklist.getChecksum( blkNo ); + relDigLen = sum.size( ); + blkSumPad = _request->_blklist.checksumPad( ); + digest = zypp::Digest(); + digest->create( _request->_blklist.getChecksumType() ); + } + + return MultiByteHandler::Range::make( + blk.off, + blk.size, + std::move(digest), + std::move(sum), + {}, // empty user data + std::move(relDigLen), + std::move(blkSumPad) ); +} + +void multifetchworker::stealjob() +{ + if (!_request->_stealing) + { + XXX << "start stealing!" << endl; + _request->_stealing = true; + } + + multifetchworker *best = 0; // best choice for the worker we want to compete with + double now = 0; + + // look through all currently running workers to find the best candidate we + // could steal from + for (auto workeriter = _request->_workers.begin(); workeriter != _request->_workers.end(); ++workeriter) + { + multifetchworker *worker = workeriter->get(); + if (worker == this) + continue; + if (worker->_pass == -1) + continue; // do not steal! + if (worker->_state == WORKER_DISCARD || worker->_state == WORKER_DONE || worker->_state == WORKER_SLEEP || !worker->_datasize) + continue; // do not steal finished jobs + if (!worker->_avgspeed && worker->_datareceived) + { + // calculate avg speed for the worker if that was not done yet + if (!now) + now = currentTime(); + if (now > worker->_starttime) + worker->_avgspeed = worker->_datareceived / (now - worker->_starttime); + } + // only consider worker who still have work + if ( worker->_datasize - worker->_datareceived <= 0 ) + continue; + if (!best || best->_pass > worker->_pass) + { + best = worker; + continue; + } + if (best->_pass < worker->_pass) + continue; + // if it is the same stripe, our current best choice is competing with the worker we are looking at + // we need to check if we are faster than the fastest one competing for this stripe, so we want the best. + // Otherwise the worst. + if (worker->_stripe == best->_stripe) + { + if ((worker->_datasize - worker->_datareceived) * best->_avgspeed < (best->_datasize - best->_datareceived) * worker->_avgspeed) + best = worker; + } + else + { + if ((worker->_datasize - worker->_datareceived) * best->_avgspeed > (best->_datasize - best->_datareceived) * worker->_avgspeed) + best = worker; + } + } + if (!best) + { + _state = WORKER_DONE; + _request->_activeworkers--; + _request->_finished = true; + return; + } + // do not sleep twice + if (_state != WORKER_SLEEP) + { + if (!_avgspeed && _datareceived) + { + if (!now) + now = currentTime(); + if (now > _starttime) + _avgspeed = _datareceived / (now - _starttime); + } + + // lets see if we should sleep a bit + XXX << "me #" << _workerno << ": " << _avgspeed << ", size " << best->_datasize << endl; + XXX << "best #" << best->_workerno << ": " << best->_avgspeed << ", size " << (best->_datasize - best->_datareceived) << endl; + + // check if we could download the full data from best faster than best could download its remaining data + if ( _avgspeed && best->_avgspeed // we and best have average speed information + && _avgspeed <= best->_avgspeed ) // and we are not faster than best + { + if (!now) + now = currentTime(); + double sl = (best->_datasize - best->_datareceived) / best->_avgspeed * 2; + if (sl > 1) + sl = 1; + XXX << "#" << _workerno << ": going to sleep for " << sl * 1000 << " ms" << endl; + _sleepuntil = now + sl; + _state = WORKER_SLEEP; + _request->_sleepworkers++; + return; + } + } + + _competing = true; + best->_competing = true; + _stripe = best->_stripe; + + best->_pass++; + _pass = best->_pass; + + runjob(); +} + +void +multifetchworker::disableCompetition() +{ + for ( auto workeriter = _request->_workers.begin(); workeriter != _request->_workers.end(); ++workeriter) + { + multifetchworker *worker = workeriter->get(); + if (worker == this) + continue; + if (worker->_stripe == _stripe) + { + if (worker->_state == WORKER_FETCH) + worker->_state = WORKER_DISCARD; + worker->_pass = -1; /* do not steal this one, we already have it */ + } + } +} + +void multifetchworker::nextjob() +{ + _datasize = 0; + _blocks.clear(); + + // claim next stripe for us, or steal if there nothing left to claim + if ( _request->_stealing || _request->_stripeNo >= _request->_requiredStripes.size() ) { + stealjob(); + return; + } + + _stripe = _request->_stripeNo++; + runjob(); +} + +void multifetchworker::runjob() +{ + _datasize = 0; + _blocks.clear (); + _rangeToStripeBlock.clear (); + + auto &stripeDesc = _request->_requiredStripes[_stripe]; + for ( uint i = 0; i < stripeDesc.blocks.size(); i++ ) { + // ignore verified and finalized ranges + if( stripeDesc.blockStates[i] == Stripe::FINALIZED ) { + continue; + } else { + _blocks.push_back( rangeFromBlock(stripeDesc.blocks[i]) ); + _rangeToStripeBlock.push_back( i ); + _datasize += _blocks.back().len; + } + } + + if ( _datasize == 0 ) { + // no blocks left in this stripe + _state = WORKER_DONE; + _request->_activeworkers--; + if ( !_request->_activeworkers ) + _request->_finished = true; + return; + } + + DBG << "#" << _workerno << "Done adding blocks to download, going to download: " << _blocks.size() << " nr of block with " << _datasize << " nr of bytes" << std::endl; + + _multiByteHandler.reset( nullptr ); + _multiByteHandler = std::make_unique(_protocolMode, _curl, _blocks, *this ); + _starttime = currentTime(); + _datareceived = 0; + run(); +} + +bool multifetchworker::continueJob() +{ + bool hadRangeFail = _multiByteHandler->lastError() == MultiByteHandler::Code::RangeFail; + if ( !_multiByteHandler->prepareToContinue() ) { + setCurlError(_multiByteHandler->lastErrorMessage().c_str()); + return false; + } + + if ( hadRangeFail ) { + // we reset the handle to default values. We do this to not run into + // "transfer closed with outstanding read data remaining" error CURL sometimes returns when + // we cancel a connection because of a range error to request a smaller batch. + // The error will still happen but much less frequently than without resetting the handle. + // + // Note: Even creating a new handle will NOT fix the issue + curl_easy_reset( _curl ); + if ( !setupHandle()) + return false; + } + + run(); + return true; +} + +void +multifetchworker::run() +{ + if (_state == WORKER_BROKEN || _state == WORKER_DONE) + return; // just in case... + + if ( !_multiByteHandler->prepare() ) { + _request->_activeworkers--; + _state = WORKER_BROKEN; + setCurlError(_multiByteHandler->lastErrorMessage ().c_str()); + return; + } + + if (curl_multi_add_handle(_request->_multi, _curl) != CURLM_OK) { + _request->_activeworkers--; + _state = WORKER_BROKEN; + setCurlError("curl_multi_add_handle failed"); + return; + } + + _request->_havenewjob = true; + _state = WORKER_FETCH; +} + + +////////////////////////////////////////////////////////////////////// + + +multifetchrequest::multifetchrequest(const MediaMultiCurl *context, Pathname filename, Url baseurl, CURLM *multi, FILE *fp, callback::SendReport *report, MediaBlockList &&blklist, off_t filesize) + : internal::CurlPollHelper::CurlPoll{ multi } + , _context(context) + , _filename(std::move(filename)) + , _baseurl(std::move(baseurl)) + , _fp(fp) + , _report(report) + , _blklist(std::move(blklist)) + , _filesize(filesize) + , _starttime(currentTime()) + , _timeout(context->_settings.timeout()) + , _connect_timeout(context->_settings.connectTimeout()) + , _maxspeed(context->_settings.maxDownloadSpeed()) + , _maxworkers(context->_settings.maxConcurrentConnections()) + { + _lastperiodstart = _lastprogress = _starttime; + if (_maxworkers > MAXURLS) + _maxworkers = MAXURLS; + if (_maxworkers <= 0) + _maxworkers = 1; + + // calculate the total size of our download + for (size_t blkno = 0; blkno < _blklist.numBlocks(); blkno++) + _totalsize += _blklist.getBlock(blkno).size; + + // equally distribute the data we want to download over all workers + _defaultBlksize = makeBlksize( _maxworkers, _totalsize ); + + // lets build stripe informations + zypp::ByteCount currStripeSize = 0; + for (size_t blkno = 0; blkno < _blklist.numBlocks(); blkno++) { + + const MediaBlock &blk = _blklist.getBlock(blkno); + if ( _requiredStripes.empty() || currStripeSize >= _defaultBlksize ) { + _requiredStripes.push_back( Stripe{} ); + currStripeSize = 0; + } + + _requiredStripes.back().blocks.push_back(blkno); + _requiredStripes.back().blockStates.push_back(Stripe::PENDING); + currStripeSize += blk.size; + } + + MIL << "Downloading " << _blklist.numBlocks() << " blocks via " << _requiredStripes.size() << " stripes on " << _maxworkers << " connections." << endl; +} + +multifetchrequest::~multifetchrequest() +{ + _workers.clear(); +} + +void +multifetchrequest::run(std::vector &urllist) +{ + int workerno = 0; + std::vector::iterator urliter = urllist.begin(); + + internal::CurlPollHelper _curlHelper(*this); + + // kickstart curl + CURLMcode mcode = _curlHelper.handleTimout(); + if (mcode != CURLM_OK) + ZYPP_THROW(MediaCurlException(_baseurl, "curl_multi_socket_action", "unknown error")); + + for (;;) + { + // list of all fds we want to poll + std::vector waitFds; + int dnsFdCount = 0; + + if (_finished) + { + XXX << "finished!" << endl; + break; + } + + if ((int)_activeworkers < _maxworkers && urliter != urllist.end() && _workers.size() < MAXURLS) + { + // spawn another worker! + _workers.push_back(std::make_unique(workerno++, *this, *urliter)); + auto &worker = _workers.back(); + if (worker->_state != WORKER_BROKEN) + { + _activeworkers++; + if (worker->_state != WORKER_LOOKUP) + { + worker->nextjob(); + } + else + _lookupworkers++; + } + ++urliter; + continue; + } + if (!_activeworkers) + { + WAR << "No more active workers!" << endl; + // show the first worker error we find + for (auto workeriter = _workers.begin(); workeriter != _workers.end(); ++workeriter) + { + if ((*workeriter)->_state != WORKER_BROKEN) + continue; + ZYPP_THROW(MediaCurlException(_baseurl, "Server error", (*workeriter)->curlError())); + } + break; + } + + if (_lookupworkers) + for (auto workeriter = _workers.begin(); workeriter != _workers.end(); ++workeriter) + (*workeriter)->adddnsfd( waitFds ); + + // if we added a new job we have to call multi_perform once + // to make it show up in the fd set. do not sleep in this case. + int timeoutMs = _havenewjob ? 0 : 200; + if ( _sleepworkers && !_havenewjob ) { + if (_minsleepuntil == 0) { + for (auto workeriter = _workers.begin(); workeriter != _workers.end(); ++workeriter) { + multifetchworker *worker = workeriter->get(); + if (worker->_state != WORKER_SLEEP) + continue; + if (!_minsleepuntil || _minsleepuntil > worker->_sleepuntil) + _minsleepuntil = worker->_sleepuntil; + } + } + double sl = _minsleepuntil - currentTime(); + if (sl < 0) { + sl = 0; + _minsleepuntil = 0; + } + if (sl < .2) + timeoutMs = sl * 1000; + } + + if ( _curlHelper.timeout_ms.has_value() ) + timeoutMs = std::min( timeoutMs, _curlHelper.timeout_ms.value() ); + + dnsFdCount = waitFds.size(); // remember how many dns fd's we have + waitFds.insert( waitFds.end(), _curlHelper.socks.begin(), _curlHelper.socks.end() ); // add the curl fd's to the poll data + + int r = zypp_detail::zypp_poll( waitFds, timeoutMs ); + if ( r == -1 ) + ZYPP_THROW(MediaCurlException(_baseurl, "zypp_poll() failed", "unknown error")); + if ( r != 0 && _lookupworkers ) { + for (auto workeriter = _workers.begin(); workeriter != _workers.end(); ++workeriter) + { + multifetchworker *worker = workeriter->get(); + if (worker->_state != WORKER_LOOKUP) + continue; + (*workeriter)->dnsevent( waitFds ); + if (worker->_state != WORKER_LOOKUP) + _lookupworkers--; + } + } + _havenewjob = false; + + // run curl + if ( r == 0 ) { + CURLMcode mcode = _curlHelper.handleTimout(); + if (mcode != CURLM_OK) + ZYPP_THROW(MediaCurlException(_baseurl, "curl_multi_socket_action", "unknown error")); + } else { + CURLMcode mcode = _curlHelper.handleSocketActions( waitFds, dnsFdCount ); + if (mcode != CURLM_OK) + ZYPP_THROW(MediaCurlException(_baseurl, "curl_multi_socket_action", "unknown error")); + } + + double now = currentTime(); + + // update periodavg + if (now > _lastperiodstart + .5) + { + if (!_periodavg) + _periodavg = (_fetchedsize - _lastperiodfetched) / (now - _lastperiodstart); + else + _periodavg = (_periodavg + (_fetchedsize - _lastperiodfetched) / (now - _lastperiodstart)) / 2; + _lastperiodfetched = _fetchedsize; + _lastperiodstart = now; + } + + // wake up sleepers + if (_sleepworkers) + { + for (auto workeriter = _workers.begin(); workeriter != _workers.end(); ++workeriter) + { + multifetchworker *worker = workeriter->get(); + if (worker->_state != WORKER_SLEEP) + continue; + if (worker->_sleepuntil > now) + continue; + if (_minsleepuntil == worker->_sleepuntil) + _minsleepuntil = 0; + XXX << "#" << worker->_workerno << ": sleep done, wake up" << endl; + _sleepworkers--; + // nextjob changes the state + worker->nextjob(); + } + } + + // collect all curl results, (re)schedule jobs + CURLMsg *msg = nullptr; + int nqueue = 0; + while ((msg = curl_multi_info_read(_multi, &nqueue)) != 0) + { + if (msg->msg != CURLMSG_DONE) + continue; + CURL *easy = msg->easy_handle; + CURLcode cc = msg->data.result; + multifetchworker *worker = nullptr; + + if (curl_easy_getinfo(easy, CURLINFO_PRIVATE, &worker) != CURLE_OK) + ZYPP_THROW(MediaCurlException(_baseurl, "curl_easy_getinfo", "unknown error")); + + if (worker->_datareceived && now > worker->_starttime) { + if (worker->_avgspeed) + worker->_avgspeed = (worker->_avgspeed + worker->_datareceived / (now - worker->_starttime)) / 2; + else + worker->_avgspeed = worker->_datareceived / (now - worker->_starttime); + } + + XXX << "#" << worker->_workerno << " done code " << cc << " speed " << worker->_avgspeed << endl; + curl_multi_remove_handle(_multi, easy); + + const auto &setWorkerBroken = [&]( const std::string &str = {} ){ + worker->_state = WORKER_BROKEN; + if ( !str.empty () ) + worker->setCurlError(str.c_str()); + _activeworkers--; + + if (!_activeworkers && !(urliter != urllist.end() && _workers.size() < MAXURLS)) { + // end of workers reached! goodbye! + worker->evaluateCurlCode(Pathname(), cc, false); + } + }; + + if ( !worker->_multiByteHandler ) { + WAR << "#" << worker->_workerno << ": has no multibyte handler, this is a bug" << endl; + setWorkerBroken("Multibyte handler error"); + continue; + } + + // tell the worker to finalize the current block + worker->_multiByteHandler->finalize(); + + if ( worker->_multiByteHandler->hasMoreWork() && ( cc == CURLE_OK || worker->_multiByteHandler->canRecover() ) ) { + + WAR << "#" << worker->_workerno << ": still has work to do or can recover from a error, continuing the job!" << endl; + // the current job is not done, or we failed and need to try more, enqueue and start again + if ( !worker->continueJob() ) { + WAR << "#" << worker->_workerno << ": failed to continue (" << worker->_multiByteHandler->lastErrorMessage() << ")" << endl; + setWorkerBroken( worker->_multiByteHandler->lastErrorMessage() ); + } + continue; + } + + // --- from here on worker has no more ranges in its current job, or had a error it can't recover from --- + + if ( cc != CURLE_OK ) { + if ( worker->_state != WORKER_DISCARD ) { + // something went wrong and we can not recover, broken worker! + setWorkerBroken(); + continue; + } else { + WAR << "#" << worker->_workerno << ": failed, but was set to discard, reusing for new requests" << endl; + } + } else { + + // we got what we asked for, maybe. Lets see if all ranges have been marked as finalized + if( !worker->_multiByteHandler->verifyData() ) { + WAR << "#" << worker->_workerno << ": error: " << worker->_multiByteHandler->lastErrorMessage() << ", disable worker" << endl; + setWorkerBroken(); + continue; + } + + // from here on we know THIS worker only got data that verified + // now lets see if the stripe was finished too + // stripe blocks can now be only in FINALIZED or ERROR states + if (worker->_state == WORKER_FETCH ) { + if ( worker->_competing ) { + worker->disableCompetition (); + } + auto &wrkerStripe = _requiredStripes[worker->_stripe]; + bool done = std::all_of( wrkerStripe.blockStates.begin(), wrkerStripe.blockStates.begin(), []( const Stripe::RState s ) { return s == Stripe::FINALIZED; } ); + if ( !done ) { + // all ranges that are not finalized are in a bogus state, refetch them + std::for_each( wrkerStripe.blockStates.begin(), wrkerStripe.blockStates.begin(), []( Stripe::RState &s ) { + if ( s != Stripe::FINALIZED) + s = Stripe::PENDING; + }); + + _finished = false; //reset finished flag + worker->runjob(); + continue; + } + } + + // make bad workers ( bad as in really slow ) sleep a little + double maxavg = 0; + int maxworkerno = 0; + int numbetter = 0; + for (auto workeriter = _workers.begin(); workeriter != _workers.end(); ++workeriter) + { + multifetchworker *oworker = workeriter->get(); + if (oworker->_state == WORKER_BROKEN) + continue; + if (oworker->_avgspeed > maxavg) + { + maxavg = oworker->_avgspeed; + maxworkerno = oworker->_workerno; + } + if (oworker->_avgspeed > worker->_avgspeed) + numbetter++; + } + if (maxavg && !_stealing) + { + double ratio = worker->_avgspeed / maxavg; + ratio = 1 - ratio; + if (numbetter < 3) // don't sleep that much if we're in the top two + ratio = ratio * ratio; + if (ratio > .01) + { + XXX << "#" << worker->_workerno << ": too slow ("<< ratio << ", " << worker->_avgspeed << ", #" << maxworkerno << ": " << maxavg << "), going to sleep for " << ratio * 1000 << " ms" << endl; + worker->_sleepuntil = now + ratio; + worker->_state = WORKER_SLEEP; + _sleepworkers++; + continue; + } + } + + // do rate control (if requested) + // should use periodavg, but that's not what libcurl does + if (_maxspeed && now > _starttime) + { + double avg = _fetchedsize / (now - _starttime); + avg = worker->_maxspeed * _maxspeed / avg; + if (avg < _maxspeed / _maxworkers) + avg = _maxspeed / _maxworkers; + if (avg > _maxspeed) + avg = _maxspeed; + if (avg < 1024) + avg = 1024; + worker->_maxspeed = avg; +#if CURLVERSION_AT_LEAST(7,15,5) + curl_easy_setopt(worker->_curl, CURLOPT_MAX_RECV_SPEED_LARGE, (curl_off_t)(avg)); +#endif + } + + worker->nextjob(); + } + + if ( _filesize > 0 && _fetchedgoodsize > _filesize ) { + ZYPP_THROW(MediaFileSizeExceededException(_baseurl, _filesize)); + } + } + + // send report + if (_report) + { + int percent = _totalsize ? (100 * (_fetchedgoodsize + _fetchedsize)) / (_totalsize + _fetchedsize) : 0; + + double avg = 0; + if (now > _starttime) + avg = _fetchedsize / (now - _starttime); + if (!(*(_report))->progress(percent, _baseurl, avg, _lastperiodstart == _starttime ? avg : _periodavg)) + ZYPP_THROW(MediaCurlException(_baseurl, "User abort", "cancelled")); + } + + if (_timeout && now - _lastprogress > _timeout) + break; + } + + if (!_finished) + ZYPP_THROW(MediaTimeoutException(_baseurl)); + + // print some download stats + WAR << "overall result" << endl; + for (auto workeriter = _workers.begin(); workeriter != _workers.end(); ++workeriter) + { + multifetchworker *worker = workeriter->get(); + WAR << "#" << worker->_workerno << ": state: " << worker->_state << " received: " << worker->_received << " url: " << worker->_url << endl; + } +} + +inline zypp::ByteCount multifetchrequest::makeBlksize ( uint maxConns, size_t filesize ) +{ + // If the calculated strip size is too small and can cause a loss in TCP throughput. Raise + // it to a reasonable value. + return std::max( filesize / std::min( std::max( 1, maxConns ) , MAXURLS ), zypp::ByteCount(MIN_STRIPE_SIZE_KB, zypp::ByteCount::K) ); +} + +////////////////////////////////////////////////////////////////////// + + +MediaMultiCurl::MediaMultiCurl(const Url &url_r, const Pathname & attach_point_hint_r) + : MediaCurl(url_r, attach_point_hint_r) +{ + MIL << "MediaMultiCurl::MediaMultiCurl(" << url_r << ", " << attach_point_hint_r << ")" << endl; + _multi = 0; + _customHeadersMetalink = 0; +} + +MediaMultiCurl::~MediaMultiCurl() +{ + if (_customHeadersMetalink) + { + curl_slist_free_all(_customHeadersMetalink); + _customHeadersMetalink = 0; + } + if (_multi) + { + curl_multi_cleanup(_multi); + _multi = 0; + } + std::map::iterator it; + for (it = _easypool.begin(); it != _easypool.end(); it++) + { + CURL *easy = it->second; + if (easy) + { + curl_easy_cleanup(easy); + it->second = NULL; + } + } +} + +void MediaMultiCurl::setupEasy() +{ + MediaCurl::setupEasy(); + + if (_customHeadersMetalink) + { + curl_slist_free_all(_customHeadersMetalink); + _customHeadersMetalink = 0; + } + struct curl_slist *sl = _customHeaders; + for (; sl; sl = sl->next) + _customHeadersMetalink = curl_slist_append(_customHeadersMetalink, sl->data); + //, application/x-zsync + _customHeadersMetalink = curl_slist_append(_customHeadersMetalink, "Accept: */*, application/x-zsync, application/metalink+xml, application/metalink4+xml"); +} + +// here we try to suppress all progress coming from a metalink download +// bsc#1021291: Nevertheless send alive trigger (without stats), so UIs +// are able to abort a hanging metalink download via callback response. +int MediaMultiCurl::progressCallback( void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow) +{ + CURL *_curl = MediaCurl::progressCallback_getcurl(clientp); + if (!_curl) + return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow); + + // bsc#408814: Don't report any sizes before we don't have data on disk. Data reported + // due to redirection etc. are not interesting, but may disturb filesize checks. + FILE *fp = 0; + if ( curl_easy_getinfo( _curl, CURLINFO_PRIVATE, &fp ) != CURLE_OK || !fp ) + return MediaCurl::aliveCallback( clientp, dltotal, dlnow, ultotal, ulnow ); + if ( ftell( fp ) == 0 ) + return MediaCurl::aliveCallback( clientp, dltotal, 0.0, ultotal, ulnow ); + + // (no longer needed due to the filesize check above?) + // work around curl bug that gives us old data + long httpReturnCode = 0; + if (curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &httpReturnCode ) != CURLE_OK || httpReturnCode == 0) + return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow); + + char *ptr = NULL; + bool ismetalink = false; + if (curl_easy_getinfo(_curl, CURLINFO_CONTENT_TYPE, &ptr) == CURLE_OK && ptr) + { + std::string ct = std::string(ptr); + if (ct.find("application/x-zsync") == 0 || ct.find("application/metalink+xml") == 0 || ct.find("application/metalink4+xml") == 0) + ismetalink = true; + } + if (!ismetalink && dlnow < 256) + { + // can't tell yet, ... + return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow); + } + if (!ismetalink) + { + fflush(fp); + ismetalink = looks_like_meta_file(fp) != MetaDataType::None; + DBG << "looks_like_meta_file: " << ismetalink << endl; + } + if (ismetalink) + { + // this is a metalink file change the expected filesize + MediaCurl::resetExpectedFileSize( clientp, ByteCount( 2, ByteCount::MB) ); + // we're downloading the metalink file. Just trigger aliveCallbacks + curl_easy_setopt(_curl, CURLOPT_XFERINFOFUNCTION, &MediaCurl::aliveCallback); + return MediaCurl::aliveCallback(clientp, dltotal, dlnow, ultotal, ulnow); + } + curl_easy_setopt(_curl, CURLOPT_XFERINFOFUNCTION, &MediaCurl::progressCallback); + return MediaCurl::progressCallback(clientp, dltotal, dlnow, ultotal, ulnow); +} + +void MediaMultiCurl::doGetFileCopy( const OnMediaLocation &srcFile , const Pathname & target, callback::SendReport & report, RequestOptions options ) const +{ + Pathname dest = target.absolutename(); + if( assert_dir( dest.dirname() ) ) + { + DBG << "assert_dir " << dest.dirname() << " failed" << endl; + ZYPP_THROW( MediaSystemException(getFileUrl(srcFile.filename()), "System error on " + dest.dirname().asString()) ); + } + + ManagedFile destNew { target.extend( ".new.zypp.XXXXXX" ) }; + AutoFILE file; + { + AutoFREE buf { ::strdup( (*destNew).c_str() ) }; + if( ! buf ) + { + ERR << "out of memory for temp file name" << endl; + ZYPP_THROW(MediaSystemException(getFileUrl(srcFile.filename()), "out of memory for temp file name")); + } + + AutoFD tmp_fd { ::mkostemp( buf, O_CLOEXEC ) }; + if( tmp_fd == -1 ) + { + ERR << "mkstemp failed for file '" << destNew << "'" << endl; + ZYPP_THROW(MediaWriteException(destNew)); + } + destNew = ManagedFile( (*buf), filesystem::unlink ); + + file = ::fdopen( tmp_fd, "we" ); + if ( ! file ) + { + ERR << "fopen failed for file '" << destNew << "'" << endl; + ZYPP_THROW(MediaWriteException(destNew)); + } + tmp_fd.resetDispose(); // don't close it here! ::fdopen moved ownership to file + } + + DBG << "dest: " << dest << endl; + DBG << "temp: " << destNew << endl; + + // set IFMODSINCE time condition (no download if not modified) + if( PathInfo(target).isExist() && !(options & OPTION_NO_IFMODSINCE) ) + { + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_IFMODSINCE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, (long)PathInfo(target).mtime()); + } + else + { + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L); + } + // change header to include Accept: metalink + curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _customHeadersMetalink); + // change to our own progress funcion + curl_easy_setopt(_curl, CURLOPT_XFERINFOFUNCTION, &progressCallback); + curl_easy_setopt(_curl, CURLOPT_PRIVATE, (*file) ); // important to pass the FILE* explicitly (passing through varargs) + try + { + MediaCurl::doGetFileCopyFile( srcFile, dest, file, report, options ); + } + catch (Exception &ex) + { + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L); + curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _customHeaders); + curl_easy_setopt(_curl, CURLOPT_PRIVATE, (void *)0); + ZYPP_RETHROW(ex); + } + curl_easy_setopt(_curl, CURLOPT_TIMECONDITION, CURL_TIMECOND_NONE); + curl_easy_setopt(_curl, CURLOPT_TIMEVALUE, 0L); + curl_easy_setopt(_curl, CURLOPT_HTTPHEADER, _customHeaders); + curl_easy_setopt(_curl, CURLOPT_PRIVATE, (void *)0); + long httpReturnCode = 0; + CURLcode infoRet = curl_easy_getinfo(_curl, CURLINFO_RESPONSE_CODE, &httpReturnCode); + if (infoRet == CURLE_OK) + { + DBG << "HTTP response: " + str::numstring(httpReturnCode) << endl; + if ( httpReturnCode == 304 + || ( httpReturnCode == 213 && _url.getScheme() == "ftp" ) ) // not modified + { + DBG << "not modified: " << PathInfo(dest) << endl; + return; + } + } + else + { + WAR << "Could not get the response code." << endl; + } + + MetaDataType ismetalink = MetaDataType::None; + + char *ptr = NULL; + if (curl_easy_getinfo(_curl, CURLINFO_CONTENT_TYPE, &ptr) == CURLE_OK && ptr) + { + std::string ct = std::string(ptr); + if (ct.find("application/x-zsync") == 0 ) + ismetalink = MetaDataType::Zsync; + else if (ct.find("application/metalink+xml") == 0 || ct.find("application/metalink4+xml") == 0) + ismetalink = MetaDataType::MetaLink; + } + + if ( ismetalink == MetaDataType::None ) + { + // some proxies do not store the content type, so also look at the file to find + // out if we received a metalink (bnc#649925) + fflush(file); + ismetalink = looks_like_meta_file(destNew); + } + + if ( ismetalink != MetaDataType::None ) + { + bool userabort = false; + Pathname failedFile = ZConfig::instance().repoCachePath() / "MultiCurl.failed"; + file = nullptr; // explicitly close destNew before the parser reads it. + try + { + MediaBlockList bl; + std::vector urls; + if ( ismetalink == MetaDataType::Zsync ) { + ZsyncParser parser; + parser.parse( destNew ); + bl = parser.getBlockList(); + urls = parser.getUrls(); + + XXX << getFileUrl(srcFile.filename()) << " returned zsync meta data." << std::endl; + } else { + MetaLinkParser mlp; + mlp.parse(destNew); + bl = mlp.getBlockList(); + urls = mlp.getUrls(); + + XXX << getFileUrl(srcFile.filename()) << " returned metalink meta data." << std::endl; + } + + if ( bl.numBlocks() ) + XXX << "With " << bl.numBlocks() << " nr of blocks and a blocksize of " << bl.getBlock(0).size << std::endl; + else + XXX << "With no blocks" << std::endl; + + /* + * gihub issue libzipp:#277 Multicurl backend breaks with MirrorCache and Metalink with unknown filesize. + * Fall back to a normal download if we have no knowledge about the filesize we want to download. + */ + if ( !bl.haveFilesize() && ! srcFile.downloadSize() ) { + XXX << "No filesize in metalink file and no expected filesize, aborting multicurl." << std::endl; + ZYPP_THROW( MediaException("Multicurl requires filesize but none was provided.") ); + } + +#if 0 + Disabling this workaround for now, since we now do zip ranges into bigger requests + /* + * bsc#1191609 In certain locations we do not receive a suitable number of metalink mirrors, and might even + * download chunks serially from one and the same server. In those cases we need to fall back to a normal download. + */ + if ( urls.size() < MIN_REQ_MIRRS ) { + ZYPP_THROW( MediaException("Multicurl enabled but not enough mirrors provided") ); + } +#endif + + // XXX << bl << endl; + file = fopen((*destNew).c_str(), "w+e"); + if (!file) + ZYPP_THROW(MediaWriteException(destNew)); + if (PathInfo(target).isExist()) + { + XXX << "reusing blocks from file " << target << endl; + bl.reuseBlocks(file, target.asString()); + XXX << bl << endl; + } + if (bl.haveChecksum(1) && PathInfo(failedFile).isExist()) + { + XXX << "reusing blocks from file " << failedFile << endl; + bl.reuseBlocks(file, failedFile.asString()); + XXX << bl << endl; + filesystem::unlink(failedFile); + } + const Pathname& df = srcFile.deltafile(); + if (!df.empty()) + { + XXX << "reusing blocks from file " << df << endl; + bl.reuseBlocks(file, df.asString()); + XXX << bl << endl; + } + try + { + multifetch(srcFile.filename(), file, &urls, &report, std::move(bl), srcFile.downloadSize()); + } + catch (MediaCurlException &ex) + { + userabort = ex.errstr() == "User abort"; + ZYPP_RETHROW(ex); + } + } + catch (MediaFileSizeExceededException &ex) { + ZYPP_RETHROW(ex); + } + catch (Exception &ex) + { + // something went wrong. fall back to normal download + file = nullptr; // explicitly close destNew before moving it + WAR<< "Failed to multifetch file " << ex << " falling back to single Curl download!" << std::endl; + if (PathInfo(destNew).size() >= 63336) + { + ::unlink(failedFile.asString().c_str()); + filesystem::hardlinkCopy(destNew, failedFile); + } + if (userabort) + { + ZYPP_RETHROW(ex); + } + file = fopen((*destNew).c_str(), "w+e"); + if (!file) + ZYPP_THROW(MediaWriteException(destNew)); + + // use the default progressCallback + curl_easy_setopt(_curl, CURLOPT_XFERINFOFUNCTION, &MediaCurl::progressCallback); + MediaCurl::doGetFileCopyFile(srcFile, dest, file, report, options | OPTION_NO_REPORT_START); + } + } + + if (::fchmod( ::fileno(file), filesystem::applyUmaskTo( 0644 ))) + { + ERR << "Failed to chmod file " << destNew << endl; + } + + file.resetDispose(); // we're going to close it manually here + if (::fclose(file)) + { + filesystem::unlink(destNew); + ERR << "Fclose failed for file '" << destNew << "'" << endl; + ZYPP_THROW(MediaWriteException(destNew)); + } + + if ( rename( destNew, dest ) != 0 ) + { + ERR << "Rename failed" << endl; + ZYPP_THROW(MediaWriteException(dest)); + } + destNew.resetDispose(); // no more need to unlink it + + DBG << "done: " << PathInfo(dest) << endl; +} + +void MediaMultiCurl::multifetch(const Pathname & filename, FILE *fp, std::vector *urllist, MediaBlockList &&blklist, callback::SendReport *report, off_t filesize) const +{ + Url baseurl(getFileUrl(filename)); + if (filesize == off_t(-1) && blklist.haveFilesize()) + filesize = blklist.getFilesize(); + if (!blklist.haveBlocks() && filesize != 0) { + if ( filesize == -1 ) { + ZYPP_THROW(MediaException("No filesize and no blocklist, falling back to normal download.")); + } + + // build a blocklist on demand just so that we have ranges + MIL << "Generate blocklist, since there was none in the metalink file." << std::endl; + + off_t currOff = 0; + const auto prefSize = multifetchrequest::makeBlksize( _settings.maxConcurrentConnections(), filesize ); + + while ( currOff < filesize ) { + + auto blksize = filesize - currOff ; + if ( blksize > prefSize ) + blksize = prefSize; + + blklist.addBlock( currOff, blksize ); + currOff += blksize; + } + + XXX << "Generated blocklist: " << std::endl << blklist << std::endl << " End blocklist " << std::endl; + + } + if (filesize == 0 || !blklist.numBlocks()) { + checkFileDigest(baseurl, fp, blklist); + return; + } + if (filesize == 0) + return; + + if (!_multi) + { + _multi = curl_multi_init(); + if (!_multi) + ZYPP_THROW(MediaCurlInitException(baseurl)); + } + + multifetchrequest req(this, filename, baseurl, _multi, fp, report, std::move(blklist), filesize); + std::vector myurllist; + for (std::vector::iterator urliter = urllist->begin(); urliter != urllist->end(); ++urliter) + { + try + { + std::string scheme = urliter->getScheme(); + if (scheme == "http" || scheme == "https" || scheme == "ftp" || scheme == "tftp") + { + checkProtocol(*urliter); + myurllist.push_back(internal::propagateQueryParams(*urliter, _url)); + } + } + catch (...) + { + } + } + if (!myurllist.size()) + myurllist.push_back(baseurl); + req.run(myurllist); + checkFileDigest(baseurl, fp, req.blockList() ); +} + +void MediaMultiCurl::checkFileDigest(Url &url, FILE *fp, MediaBlockList &blklist) const +{ + if ( !blklist.haveFileChecksum() ) + return; + if (fseeko(fp, off_t(0), SEEK_SET)) + ZYPP_THROW(MediaCurlException(url, "fseeko", "seek error")); + Digest dig; + blklist.createFileDigest(dig); + char buf[4096]; + size_t l = 0; + while ((l = fread(buf, 1, sizeof(buf), fp)) > 0) + dig.update(buf, l); + if (!blklist.verifyFileDigest(dig)) + ZYPP_THROW(MediaCurlException(url, "file verification failed", "checksum error")); +} + +bool MediaMultiCurl::isDNSok(const std::string &host) const +{ + return _dnsok.find(host) == _dnsok.end() ? false : true; +} + +void MediaMultiCurl::setDNSok(const std::string &host) const +{ + _dnsok.insert(host); +} + +CURL *MediaMultiCurl::fromEasyPool(const std::string &host) const +{ + if (_easypool.find(host) == _easypool.end()) + return 0; + CURL *ret = _easypool[host]; + _easypool.erase(host); + return ret; +} + +void MediaMultiCurl::toEasyPool(const std::string &host, CURL *easy) const +{ + CURL *oldeasy = _easypool[host]; + _easypool[host] = easy; + if (oldeasy) + curl_easy_cleanup(oldeasy); +} + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaMultiCurl.h b/zypp/media/MediaMultiCurl.h new file mode 100644 index 0000000..42f3353 --- /dev/null +++ b/zypp/media/MediaMultiCurl.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaMultiCurl.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIAMULTICURL_H +#define ZYPP_MEDIA_MEDIAMULTICURL_H + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace zypp { + namespace media { + +/** + * @short Implementation class for FTP, HTTP and HTTPS MediaHandler + * + * @author Michael Schroeder + * + * @see MediaHandler + **/ + +class multifetchrequest; +class multifetchworker; + +class MediaMultiCurl : public MediaCurl { +public: + friend class multifetchrequest; + friend class multifetchworker; + + MediaMultiCurl(const Url &url_r, const Pathname & attach_point_hint_r); + ~MediaMultiCurl() override; + + void doGetFileCopy( const OnMediaLocation & srcFile, const Pathname & targetFilename, callback::SendReport & _report, RequestOptions options = OPTION_NONE ) const override; + + void multifetch(const Pathname &filename, FILE *fp, std::vector *urllist, MediaBlockList &&blklist, callback::SendReport *report = 0, off_t filesize = off_t(-1)) const; + + /** \overload translating ByteCount(0) into off_t(-1) + * bsc#1153557: In the zypp media backend 'we don't know the size' is + * represented by ByteCount(0). The more C-isch MultiCurl uses off_t(-1). + */ + void multifetch(const Pathname &filename, FILE *fp, std::vector *urllist, callback::SendReport *report, MediaBlockList &&blklist, const ByteCount & filesize ) const + { multifetch( filename, fp, urllist, std::move(blklist), report, ( filesize ? off_t(filesize) : off_t(-1) ) ); } + +protected: + + bool isDNSok(const std::string &host) const; + void setDNSok(const std::string &host) const; + + CURL *fromEasyPool(const std::string &host) const; + void toEasyPool(const std::string &host, CURL *easy) const; + + void setupEasy() override; + void checkFileDigest(Url &url, FILE *fp, MediaBlockList &blklist) const; + static int progressCallback(void *clientp, curl_off_t dltotal, curl_off_t dlnow, curl_off_t ultotal, curl_off_t ulnow ); + +private: + // the custom headers from MediaCurl plus a "Accept: metalink" header + curl_slist *_customHeadersMetalink; + mutable CURLM *_multi; // reused for all fetches so we can make use of the dns cache + mutable std::set _dnsok; + mutable std::map _easypool; +}; + +/////////////////////////////////////////////////////////////////// + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIAMULTICURL_H diff --git a/zypp/media/MediaNFS.cc b/zypp/media/MediaNFS.cc new file mode 100644 index 0000000..b59e6a7 --- /dev/null +++ b/zypp/media/MediaNFS.cc @@ -0,0 +1,261 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaNFS.cc + * +*/ + +#include +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaNFS + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::MediaNFS + // METHOD TYPE : Constructor + // + // DESCRIPTION : + // + MediaNFS::MediaNFS( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, + "/", // urlpath at attachpoint + false ) // does_download + { + MIL << "MediaNFS::MediaNFS(" << url_r << ", " << attach_point_hint_r << ")" << endl; + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::attachTo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that not already attached, and attachPoint is a directory. + // + void MediaNFS::attachTo(bool next) + { + if(_url.getHost().empty()) + ZYPP_THROW(MediaBadUrlEmptyHostException(_url)); + if(next) + ZYPP_THROW(MediaNotSupportedException(_url)); + + std::string path = _url.getHost(); + path += ':'; + path += Pathname(_url.getPathName()).asString(); + + MediaSourceRef media( new MediaSource("nfs", path)); + AttachedMedia ret( findAttachedMedia( media)); + + if( ret.mediaSource && + ret.attachPoint && + !ret.attachPoint->empty()) + { + DBG << "Using a shared media " + << ret.mediaSource->name + << " attached on " + << ret.attachPoint->path + << endl; + + removeAttachPoint(); + setAttachPoint(ret.attachPoint); + setMediaSource(ret.mediaSource); + return; + } + + if( !isUseableAttachPoint( attachPoint() ) ) + { + setAttachPoint( createAttachPoint(), true ); + } + std::string mountpoint( attachPoint().asString() ); + + std::string filesystem( _url.getScheme() ); + if ( filesystem != "nfs4" && _url.getQueryParam("type") == "nfs4" ) + { + filesystem = "nfs4"; + } + + std::string options = _url.getQueryParam("mountoptions"); + if(options.empty()) + { + options="ro"; + } + + std::vector optionList; + str::split( options, std::back_inserter(optionList), "," ); + std::vector::const_iterator it; + bool contains_lock = false, contains_soft = false, + contains_timeo = false, contains_hard = false; + + for( it = optionList.begin(); it != optionList.end(); ++it ) { + if ( *it == "lock" || *it == "nolock" ) contains_lock = true; + else if ( *it == "soft") contains_soft = true; + else if ( *it == "hard") contains_hard = true; + else if ( it->find("timeo") != std::string::npos ) contains_timeo = true; + } + + if ( !(contains_lock && contains_soft) ) { + // Add option "nolock", unless option "lock" or "unlock" is already set. + // This should prevent the mount command hanging when the portmapper isn't + // running. + if ( !contains_lock ) { + optionList.push_back( "nolock" ); + } + // Add options "soft,timeo=NFS_MOUNT_TIMEOUT", unless they are set + // already or "hard" option is explicitly specified. This prevent + // the mount command from hanging when the nfs server is not responding + // and file transactions from an unresponsive to throw an error after + // a short time instead of hanging forever + if ( !(contains_soft || contains_hard) ) { + optionList.push_back( "soft" ); + if ( !contains_timeo ) { + std::ostringstream s; + s << "timeo=" << NFS_MOUNT_TIMEOUT; + optionList.push_back( s.str() ); + } + } + options = str::join( optionList, "," ); + } + + Mount mount; + mount.mount(path,mountpoint,filesystem,options); + + setMediaSource(media); + + // wait for /etc/mtab update ... + // (shouldn't be needed) + int limit = 3; + bool mountsucceeded = false; + while( !(mountsucceeded=isAttached()) && --limit) + { + sleep(1); + } + + if( !mountsucceeded) + { + setMediaSource(MediaSourceRef()); + try + { + mount.umount(attachPoint().asString()); + } + catch (const MediaException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + ZYPP_THROW(MediaMountException( + "Unable to verify that the media was mounted", + path, mountpoint + )); + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaNFS::isAttached + // METHOD TYPE : bool + // + // DESCRIPTION : Override check if media is attached. + // + bool + MediaNFS::isAttached() const + { + return checkAttached(true); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::releaseFrom + // METHOD TYPE : void + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaNFS::releaseFrom( const std::string & ejectDev ) + { + Mount mount; + mount.umount(attachPoint().asString()); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaNFS::getFile + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaNFS::getFile (const OnMediaLocation &file ) const + { + MediaHandler::getFile( file ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaNFS::getDir + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached. + // + void MediaNFS::getDir( const Pathname & dirname, bool recurse_r ) const + { + MediaHandler::getDir( dirname, recurse_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaNFS::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + /////////////////////////////////////////////////////////////////// + // + // + // METHOD NAME : MediaNFS::getDirInfo + // METHOD TYPE : PMError + // + // DESCRIPTION : Asserted that media is attached and retlist is empty. + // + void MediaNFS::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + MediaHandler::getDirInfo( retlist, dirname, dots ); + } + + bool MediaNFS::getDoesFileExist( const Pathname & filename ) const + { + return MediaHandler::getDoesFileExist( filename ); + } + + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaNFS.h b/zypp/media/MediaNFS.h new file mode 100644 index 0000000..208b0e5 --- /dev/null +++ b/zypp/media/MediaNFS.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaNFS.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIANFS_H +#define ZYPP_MEDIA_MEDIANFS_H + +#include + +/** + * Value of NFS mount minor timeout (passed to timeo option + * of the NFS mount) in tenths of a second. + * + * The value of 300 should give a major timeout after 3.5 minutes + * for UDP and 1.5 minutes for TCP. (#350309) + */ +#define NFS_MOUNT_TIMEOUT 300 + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaNFS + /** + * @short Implementation class for NFS MediaHandler + * @see MediaHandler + **/ + class MediaNFS : public MediaHandler { + + protected: + + void attachTo (bool next = false) override; + + void releaseFrom( const std::string & ejectDev ) override; + void getFile( const OnMediaLocation & file ) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + bool getDoesFileExist( const Pathname & filename ) const override; + + public: + + MediaNFS( const Url& url_r, + const Pathname & attach_point_hint_r ); + + ~MediaNFS() override { try { release(); } catch(...) {} } + + bool isAttached() const override; + }; + + /////////////////////////////////////////////////////////////////// + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIANFS_H diff --git a/zypp/media/MediaNetwork.cc b/zypp/media/MediaNetwork.cc new file mode 100644 index 0000000..f50bd1e --- /dev/null +++ b/zypp/media/MediaNetwork.cc @@ -0,0 +1,618 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaCurl.cc + * +*/ + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + + +using std::endl; + +namespace internal { + + + constexpr std::string_view MEDIACACHE_REGEX("^\\/media\\.[1-9][0-9]*\\/media$"); + + struct ProgressTracker { + + using clock = std::chrono::steady_clock; + + std::optional _timeStart; ///< Start total stats + std::optional _timeLast; ///< Start last period(~1sec) + + double _dnlTotal = 0.0; ///< Bytes to download or 0 if unknown + double _dnlLast = 0.0; ///< Bytes downloaded at period start + double _dnlNow = 0.0; ///< Bytes downloaded now + + int _dnlPercent= 0; ///< Percent completed or 0 if _dnlTotal is unknown + + double _drateTotal= 0.0; ///< Download rate so far + double _drateLast = 0.0; ///< Download rate in last period + + void updateStats( double dltotal = 0.0, double dlnow = 0.0 ) + { + clock::time_point now = clock::now(); + + if ( !_timeStart ) + _timeStart = _timeLast = now; + + // If called without args (0.0), recompute based on the last values seen + if ( dltotal && dltotal != _dnlTotal ) + _dnlTotal = dltotal; + + if ( dlnow && dlnow != _dnlNow ) { + _dnlNow = dlnow; + } + + // percentage: + if ( _dnlTotal ) + _dnlPercent = int(_dnlNow * 100 / _dnlTotal); + + // download rates: + _drateTotal = _dnlNow / std::max( std::chrono::duration_cast(now - *_timeStart).count(), int64_t(1) ); + + if ( _timeLast < now ) + { + _drateLast = (_dnlNow - _dnlLast) / int( std::chrono::duration_cast(now - *_timeLast).count() ); + // start new period + _timeLast = now; + _dnlLast = _dnlNow; + } + else if ( _timeStart == _timeLast ) + _drateLast = _drateTotal; + } + }; + + + // All media handler instances share the same EventDispatcher and Downloader + // This is released at application shutdown. + struct SharedData { + + SharedData(const SharedData &) = delete; + SharedData(SharedData &&) = delete; + SharedData &operator=(const SharedData &) = delete; + SharedData &operator=(SharedData &&) = delete; + + ~SharedData() { + MIL << "Releasing internal::SharedData for MediaNetwork." << std::endl; + } + + static std::shared_ptr instance () { + static std::shared_ptr data = std::shared_ptr( new SharedData() ); + return data; + } + + static const zypp::str::regex &mediaRegex () { + static zypp::str::regex reg( MEDIACACHE_REGEX.data() ); + return reg; + } + + // we need to keep a reference + zyppng::EventDispatcherRef _dispatcher; + zyppng::DownloaderRef _downloader; + + struct MediaFileCacheEntry { + + MediaFileCacheEntry( zypp::ManagedFile &&file ) : _file( std::move(file) ) { } + + std::chrono::steady_clock::time_point _creationTime = std::chrono::steady_clock::now(); + zypp::ManagedFile _file; + }; + + auto findInCache( const std::string &mediaCacheKey ) { + auto i = _mediaCacheEntries.find( mediaCacheKey ); + if ( i != _mediaCacheEntries.end() ) { + auto age = std::chrono::steady_clock::now() - i->second._creationTime; + if ( age > std::chrono::minutes( 30 ) ) { + MIL << "Found cached media file, but it's older than 30 mins, requesting a new one" << std::endl; + _mediaCacheEntries.erase(i); + } else { + return i; + } + } + return _mediaCacheEntries.end(); + } + + zypp::filesystem::TmpDir _mediaCacheDir{zypp::filesystem::TmpDir::defaultLocation(), "ZyppMediaCache."}; + std::unordered_map _mediaCacheEntries; + + private: + SharedData() { + MIL << "Initializing internal::SharedData for MediaNetwork" << std::endl; + _dispatcher = zyppng::ThreadData::current().ensureDispatcher(); + _downloader = std::make_shared(); + _downloader->requestDispatcher()->setMaximumConcurrentConnections( zypp::MediaConfig::instance().download_max_concurrent_connections() ); + } + }; + +} + +using namespace internal; +using namespace zypp::base; + +namespace zypp { + + namespace media { + + MediaNetwork::MediaNetwork( const Url & url_r, + const Pathname & attach_point_hint_r ) + : MediaNetworkCommonHandler( url_r, attach_point_hint_r, + "/", // urlpath at attachpoint + true ) // does_download + { + MIL << "MediaNetwork::MediaNetwork(" << url_r << ", " << attach_point_hint_r << ")" << endl; + + // make sure there is a event loop and downloader instance + _shared = internal::SharedData::instance(); + + if( !attachPoint().empty()) + { + PathInfo ainfo(attachPoint()); + Pathname apath(attachPoint() + "XXXXXX"); + char *atemp = ::strdup( apath.asString().c_str()); + char *atest = NULL; + if( !ainfo.isDir() || !ainfo.userMayRWX() || + atemp == NULL || (atest=::mkdtemp(atemp)) == NULL) + { + WAR << "attach point " << ainfo.path() + << " is not useable for " << url_r.getScheme() << endl; + setAttachPoint("", true); + } + else if( atest != NULL) + ::rmdir(atest); + + if( atemp != NULL) + ::free(atemp); + } + } + + void MediaNetwork::attachTo (bool next) + { + if ( next ) + ZYPP_THROW(MediaNotSupportedException(_url)); + + if ( !_url.isValid() ) + ZYPP_THROW(MediaBadUrlException(_url)); + + // use networkdispatcher check if the scheme is supported + if ( !_shared->_downloader->requestDispatcher()->supportsProtocol( _url ) ) { + std::string msg("Unsupported protocol '"); + msg += _url.getScheme(); + msg += "'"; + ZYPP_THROW(MediaBadUrlException(_url, msg)); + } + + if( !isUseableAttachPoint( attachPoint() ) ) + { + setAttachPoint( createAttachPoint(), true ); + } + + disconnectFrom(); + + MediaSourceRef media( new MediaSource(_url.getScheme(), _url.asString())); + setMediaSource(media); + } + + bool + MediaNetwork::checkAttachPoint(const Pathname &apoint) const + { + return MediaHandler::checkAttachPoint( apoint, true, true); + } + + void MediaNetwork::disconnectFrom() + { + } + + void MediaNetwork::releaseFrom( const std::string & ejectDev ) + { + disconnect(); + } + + void MediaNetwork::runRequest ( const zyppng::DownloadSpec &spec, callback::SendReport *report ) const + { + bool retry = true; + + while ( retry ) { + retry = false; + auto ev = zyppng::EventLoop::create(); + std::vector signalConnections; + OnScopeExit deferred([&](){ + while( signalConnections.size() ) { + signalConnections.back().disconnect(); + signalConnections.pop_back(); + } + }); + + zyppng::DownloadRef dl = _shared->_downloader->downloadFile( spec ); + std::optional progTracker; + + const auto &startedSlot = [&]( zyppng::Download &req ){ + if ( !report) return; + (*report)->start( spec.url(), spec.targetPath()); + }; + + const auto &aliveSlot = [&]( zyppng::Download &req, off_t dlNow ){ + if ( !report || !progTracker ) + return; + progTracker->updateStats( 0.0, dlNow ); + if ( !(*report)->progress( progTracker->_dnlPercent, spec.url(), progTracker-> _drateTotal, progTracker->_drateLast ) ) + req.cancel(); + }; + + const auto &progressSlot = [&]( zyppng::Download &req, off_t dlTotal, off_t dlNow ) { + if ( !report || !progTracker ) + return; + + progTracker->updateStats( dlTotal, dlNow ); + if ( !(*report)->progress( progTracker->_dnlPercent, spec.url(), progTracker-> _drateTotal, progTracker->_drateLast ) ) + req.cancel(); + }; + + const auto &finishedSlot = [&]( zyppng::Download & ){ + ev->quit(); + }; + + bool firstTry = true; + const auto &authRequiredSlot = [&]( zyppng::Download &req, zyppng::NetworkAuthData &auth, const std::string &availAuth ){ + + //! \todo need a way to pass different CredManagerOptions here + CredentialManager cm(CredManagerOptions(ZConfig::instance().repoManagerRoot())); + CurlAuthData_Ptr credentials; + + // get stored credentials + AuthData_Ptr cmcred = cm.getCred(_url); + if ( cmcred && auth.lastDatabaseUpdate() < cmcred->lastDatabaseUpdate() ) { + credentials.reset(new CurlAuthData(*cmcred)); + DBG << "got stored credentials:" << endl << *credentials << endl; + + } else { + // if not found, ask user + CurlAuthData_Ptr curlcred; + curlcred.reset(new CurlAuthData()); + callback::SendReport auth_report; + + // preset the username if present in current url + if (!_url.getUsername().empty() && firstTry) + curlcred->setUsername(_url.getUsername()); + // if CM has found some credentials, preset the username from there + else if (cmcred) + curlcred->setUsername(cmcred->username()); + + // indicate we have no good credentials from CM + cmcred.reset(); + + std::string prompt_msg = str::Format(_("Authentication required for '%s'")) % _url.asString(); + + // set available authentication types from the signal + // might be needed in prompt + curlcred->setAuthType( availAuth ); + + // ask user + if (auth_report->prompt(_url, prompt_msg, *curlcred)) + { + DBG << "callback answer: retry" << endl + << "CurlAuthData: " << *curlcred << endl; + + if (curlcred->valid()) + { + credentials = curlcred; + // if (credentials->username() != _url.getUsername()) + // _url.setUsername(credentials->username()); + /** + * \todo find a way to save the url with changed username + * back to repoinfo or dont store urls with username + * (and either forbid more repos with the same url and different + * user, or return a set of credentials from CM and try them one + * by one) + */ + } + } + else + { + DBG << "callback answer: cancel" << endl; + } + } + + if ( !credentials ) { + auth = zyppng::NetworkAuthData(); + return; + } + + auth = *credentials; + if (!cmcred) { + credentials->setUrl(_url); + cm.addCred(*credentials); + cm.save(); + } + }; + + signalConnections.insert( signalConnections.end(), { + dl->connectFunc( &zyppng::Download::sigStarted, startedSlot), + dl->connectFunc( &zyppng::Download::sigFinished, finishedSlot ), + dl->connectFunc( &zyppng::Download::sigAuthRequired, authRequiredSlot ) + }); + + if ( report ) { + progTracker = internal::ProgressTracker(); + signalConnections.insert( signalConnections.end(), { + dl->connectFunc( &zyppng::Download::sigAlive, aliveSlot ), + dl->connectFunc( &zyppng::Download::sigProgress, progressSlot ), + }); + } + + dl->start(); + ev->run(); + + std::for_each( signalConnections.begin(), signalConnections.end(), []( auto &conn ) { conn.disconnect(); }); + + if ( dl->hasError() ) { + auto errCode = zypp::media::DownloadProgressReport::ERROR; + std::exception_ptr excp; + const auto &error = dl->lastRequestError(); + switch ( error.type() ) { + case zyppng::NetworkRequestError::InternalError: + case zyppng::NetworkRequestError::InvalidChecksum: + case zyppng::NetworkRequestError::UnsupportedProtocol: + case zyppng::NetworkRequestError::MalformedURL: + case zyppng::NetworkRequestError::PeerCertificateInvalid: + case zyppng::NetworkRequestError::ConnectionFailed: + case zyppng::NetworkRequestError::ServerReturnedError: + case zyppng::NetworkRequestError::MissingData: + case zyppng::NetworkRequestError::RangeFail: { + excp = ZYPP_EXCPT_PTR( zypp::media::MediaCurlException( spec.url(), error.toString(), error.nativeErrorString() ) ); + break; + } + case zyppng::NetworkRequestError::Cancelled: { + excp = ZYPP_EXCPT_PTR( zypp::media::MediaRequestCancelledException( error.toString() ) ); + break; + } + case zyppng::NetworkRequestError::ExceededMaxLen: { + excp = ZYPP_EXCPT_PTR( zypp::media::MediaFileSizeExceededException( spec.url(), spec.expectedFileSize() ) ); + break; + } + case zyppng::NetworkRequestError::TemporaryProblem: { + excp = ZYPP_EXCPT_PTR( zypp::media::MediaTemporaryProblemException( spec.url(), error.toString() ) ); + break; + } + case zyppng::NetworkRequestError::Timeout: { + excp = ZYPP_EXCPT_PTR( zypp::media::MediaTimeoutException( spec.url(), error.toString() ) ); + break; + } + case zyppng::NetworkRequestError::Forbidden: { + excp = ZYPP_EXCPT_PTR( zypp::media::MediaForbiddenException( spec.url(), error.toString() ) ); + break; + } + case zyppng::NetworkRequestError::NotFound: { + errCode = zypp::media::DownloadProgressReport::NOT_FOUND; + + //@BUG using getPathName() can result in wrong error messages + excp = ZYPP_EXCPT_PTR( zypp::media::MediaFileNotFoundException( _url, spec.url().getPathName() ) ); + break; + } + case zyppng::NetworkRequestError::Unauthorized: + case zyppng::NetworkRequestError::AuthFailed: { + errCode = zypp::media::DownloadProgressReport::ACCESS_DENIED; + excp = ZYPP_EXCPT_PTR( zypp::media::MediaUnauthorizedException( spec.url(), error.toString(), error.nativeErrorString(), "" ) ); + break; + } + case zyppng::NetworkRequestError::NoError: + // should never happen + DBG << "BUG: Download error flag is set , but Error code is NoError" << std::endl; + break; + case zyppng::NetworkRequestError::Http2Error: + case zyppng::NetworkRequestError::Http2StreamError: { + excp = ZYPP_EXCPT_PTR( zypp::media::MediaCurlException( spec.url(), error.toString(), error.nativeErrorString() ) ); + break; + } + } + + if ( excp && !retry ) { + if ( report ) (*report)->finish( spec.url(), errCode, error.toString() ); + std::rethrow_exception( excp ); + } + } + } + if ( report ) (*report)->finish( spec.url(), zypp::media::DownloadProgressReport::NO_ERROR, "" ); + } + + void MediaNetwork::getFile( const OnMediaLocation &file ) const + { + // Use absolute file name to prevent access of files outside of the + // hierarchy below the attach point. + getFileCopy( file, localPath(file.filename()).absolutename() ); + } + + void MediaNetwork::getFileCopy( const OnMediaLocation & file, const Pathname & targetFilename ) const + { + const auto &filename = file.filename(); + Url fileurl(getFileUrl(filename)); + + const bool requestedMediaFile = _shared->mediaRegex().matches( filename.asString() ); + auto &mediaFileCache = _shared->_mediaCacheEntries; + const auto &mediaCacheKey = fileurl.asCompleteString(); + + DBG << "FILEURL IS: " << fileurl << std::endl; + DBG << "Downloading to: " << targetFilename << std::endl; + + if( assert_dir( targetFilename.dirname() ) ) { + DBG << "assert_dir " << targetFilename.dirname() << " failed" << endl; + ZYPP_THROW( MediaSystemException(getFileUrl(file.filename()), "System error on " + targetFilename.dirname().asString()) ); + } + + if ( requestedMediaFile ) { + MIL << "Requested " << filename << " trying media cache first" << std::endl; + + auto i = _shared->findInCache( mediaCacheKey ); + if ( i != mediaFileCache.end() ) { + MIL << "Found cached media file, returning a copy to the file" << std::endl; + if ( zypp::filesystem::hardlinkCopy( i->second._file, targetFilename ) == 0 ) + return; + + mediaFileCache.erase(i); + MIL << "Failed to copy the requested file, proceeding with download" << std::endl; + } + + MIL << "Nothing in the file cache, requesting the file from the server." << std::endl; + } + + zyppng::DownloadSpec spec = zyppng::DownloadSpec( fileurl, targetFilename, file.downloadSize() ) + .setDeltaFile( file.deltafile() ) + .setHeaderSize( file.headerSize()) + .setHeaderChecksum( file.headerChecksum() ) + .setTransferSettings( this->_settings ); + + callback::SendReport report; + + try { + runRequest( spec, &report ); + } catch ( const zypp::media::MediaFileNotFoundException &ex ) { + if ( requestedMediaFile ) { + MIL << "Media file was not found, remembering in the cache" << std::endl; + mediaFileCache.insert_or_assign( mediaCacheKey, internal::SharedData::MediaFileCacheEntry( zypp::ManagedFile() ) ); + } + ZYPP_RETHROW( std::current_exception() ); + } + + // the request was successful + if ( requestedMediaFile ) { + const auto &cacheFileName = (_shared->_mediaCacheDir.path() / zypp::CheckSum::md5FromString( mediaCacheKey).asString() ).extend(".cache"); + zypp::ManagedFile file( cacheFileName, zypp::filesystem::unlink ); + if ( zypp::filesystem::hardlinkCopy( targetFilename, cacheFileName ) == 0 ) { + mediaFileCache.insert_or_assign( mediaCacheKey, internal::SharedData::MediaFileCacheEntry( std::move(file) ) ); + MIL << "Saved requested media file in media cache for future use" << std::endl; + } else { + MIL << "Failed to save requested media file in cache, requesting again next time." << std::endl; + } + } + } + + bool MediaNetwork::getDoesFileExist( const Pathname & filename ) const + { + MIL << "Checking if file " << filename << " does exist" << std::endl; + Url fileurl(getFileUrl(filename)); + const bool requestMediaFile = _shared->mediaRegex().matches( filename.asString() ); + auto &mediaFileCache = _shared->_mediaCacheEntries; + const auto &mediaCacheKey = fileurl.asCompleteString(); + + if ( requestMediaFile ) { + MIL << "Request for " << filename << " is a media file, trying the cache first" << std::endl; + auto i = _shared->findInCache( mediaCacheKey ); + if ( i != mediaFileCache.end() ) { + MIL << "Found a cache entry for requested media file, returning right away" << std::endl; + if ( i->second._file->empty() ) { + return false; + } else { + return true; + } + } + } + + bool result = false; //we are pessimists + try + { + const auto &targetFilePath = localPath(filename).absolutename(); + + zyppng::DownloadSpec spec = zyppng::DownloadSpec( fileurl, targetFilePath ) + .setCheckExistsOnly( true ) + .setTransferSettings( this->_settings ); + + runRequest( spec ); + // if we get to here the request worked. + result = true; + } + catch ( const MediaFileNotFoundException &e ) { + // if the file did not exist then we can return false + ZYPP_CAUGHT(e); + result = false; + } + // unexpected exception + catch (MediaException & excpt_r) + { + ZYPP_RETHROW(excpt_r); + } + + // if the file does not exist remember it right away in our cache + if ( !result && requestMediaFile ) { + MIL << filename << " does not exist on medium, remembering in the cache" << std::endl; + mediaFileCache.insert_or_assign( mediaCacheKey, internal::SharedData::MediaFileCacheEntry( zypp::ManagedFile() ) ); + } + + return result; + } + + void MediaNetwork::getDir( const Pathname & dirname, bool recurse_r ) const + { + filesystem::DirContent content; + getDirInfo( content, dirname, /*dots*/false ); + + for ( filesystem::DirContent::const_iterator it = content.begin(); it != content.end(); ++it ) { + Pathname filename = dirname + it->name; + int res = 0; + + switch ( it->type ) { + case filesystem::FT_NOT_AVAIL: // old directory.yast contains no typeinfo at all + case filesystem::FT_FILE: + getFile( OnMediaLocation( filename ) ); + break; + case filesystem::FT_DIR: // newer directory.yast contain at least directory info + if ( recurse_r ) { + getDir( filename, recurse_r ); + } else { + res = assert_dir( localPath( filename ) ); + if ( res ) { + WAR << "Ignore error (" << res << ") on creating local directory '" << localPath( filename ) << "'" << endl; + } + } + break; + default: + // don't provide devices, sockets, etc. + break; + } + } + } + + void MediaNetwork::getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots ) const + { + getDirectoryYast( retlist, dirname, dots ); + } + + void MediaNetwork::getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots ) const + { + getDirectoryYast( retlist, dirname, dots ); + } + + } // namespace media +} // namespace zypp +// diff --git a/zypp/media/MediaNetwork.h b/zypp/media/MediaNetwork.h new file mode 100644 index 0000000..6a37c46 --- /dev/null +++ b/zypp/media/MediaNetwork.h @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaNetwork.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIANETWORK_H +#define ZYPP_MEDIA_MEDIANETWORK_H + +#include +#include +#include + +namespace internal { + struct SharedData; +} + +namespace zyppng { + class DownloadSpec; +} + +namespace zypp { + namespace media { + // + // CLASS NAME : MediaNetwork + /** + * @short Implementation class for FTP, HTTP and HTTPS MediaHandler + * @see MediaHandler + **/ + class MediaNetwork : public MediaNetworkCommonHandler + { + protected: + + void attachTo (bool next = false) override; + void releaseFrom( const std::string & ejectDev ) override; + void getFile( const OnMediaLocation & file ) const override; + void getFileCopy( const OnMediaLocation & file, const Pathname & targetFilename ) const override; + void getDir( const Pathname & dirname, bool recurse_r ) const override; + void getDirInfo( std::list & retlist, + const Pathname & dirname, bool dots = true ) const override; + void getDirInfo( filesystem::DirContent & retlist, + const Pathname & dirname, bool dots = true ) const override; + /** + * + * \throws MediaException + * + */ + void disconnectFrom() override; + + /** + * + * \throws MediaException + * + */ + bool getDoesFileExist( const Pathname & filename ) const override; + + bool checkAttachPoint(const Pathname &apoint) const override; + + + public: + + MediaNetwork( const Url & url_r, + const Pathname & attach_point_hint_r ); + + ~MediaNetwork() override { try { release(); } catch(...) {} } + + private: + + void runRequest ( const zyppng::DownloadSpec &spec, callback::SendReport *report = nullptr ) const; + + private: + mutable std::shared_ptr<::internal::SharedData> _shared; + }; + + } // namespace media +} // namespace zypp + +#endif // ZYPP_MEDIA_MEDIANETWORK_H diff --git a/zypp/media/MediaNetworkCommonHandler.cc b/zypp/media/MediaNetworkCommonHandler.cc new file mode 100644 index 0000000..25a3240 --- /dev/null +++ b/zypp/media/MediaNetworkCommonHandler.cc @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaNetworkCommonHandler.cc + * +*/ + +#include "MediaNetworkCommonHandler.h" + +#include +#include +#include +#include + +#include + +namespace zypp::media +{ + zypp::Url MediaNetworkCommonHandler::findGeoIPRedirect ( const zypp::Url &url ) + { + try { + const auto &conf = ZConfig::instance(); + if ( !conf.geoipEnabled() ) { + MIL << "GeoIp rewrites disabled via ZConfig." << std::endl; + return Url(); + } + + if ( !( url.getQueryParam("COUNTRY").empty() && url.getQueryParam("AVOID_COUNTRY").empty() )) { + MIL << "GeoIp rewrites disabled since the baseurl " << url << " uses an explicit country setting." << std::endl; + return Url(); + } + + const auto &hostname = url.getHost(); + auto geoipFile = conf.geoipCachePath() / hostname ; + if ( PathInfo( geoipFile ).isFile() ) { + + MIL << "Found GeoIP file for host: " << hostname << std::endl; + + std::ifstream in( geoipFile.asString() ); + if (!in.is_open()) { + MIL << "Failed to open GeoIP for host: " << hostname << std::endl; + return Url(); + } + + try { + std::string newHost; + in >> newHost; + + Url newUrl = url; + newUrl.setHost( newHost ); + + MIL << "Found GeoIP rewrite: " << hostname << " -> " << newHost << std::endl; + + return newUrl; + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + MIL << "No valid GeoIP rewrite target found for " << url << std::endl; + } + } + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + MIL << "Failed to query GeoIP data, url rewriting disabled." << std::endl; + } + + // no rewrite + return Url(); + } + + Url MediaNetworkCommonHandler::getFileUrl( const Pathname & filename_r ) const + { + static const zypp::str::regex invalidRewrites("^.*\\/repomd.xml(.asc|.key)?$|^\\/geoip$"); + + const bool canRedir = _redirTarget.isValid() && !invalidRewrites.matches(filename_r.asString()); + const auto &baseUrl = ( canRedir ) ? _redirTarget : _url; + + if ( canRedir ) + MIL << "Redirecting " << filename_r << " request to geoip location." << std::endl; + + // Simply extend the URLs pathname. An 'absolute' URL path + // is achieved by encoding the leading '/' in an URL path:2 + // URL: ftp://user@server -> ~user + // URL: ftp://user@server/ -> ~user + // URL: ftp://user@server// -> ~user + // URL: ftp://user@server/%2F -> / + // ^- this '/' is just a separator + Url newurl( baseUrl ); + newurl.setPathName( ( Pathname("./"+baseUrl.getPathName()) / filename_r ).asString().substr(1) ); + return newurl; + } +} diff --git a/zypp/media/MediaNetworkCommonHandler.h b/zypp/media/MediaNetworkCommonHandler.h new file mode 100644 index 0000000..514e59c --- /dev/null +++ b/zypp/media/MediaNetworkCommonHandler.h @@ -0,0 +1,70 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaNetworkCommonHandler.h + */ +#ifndef ZYPP_MEDIA_MEDIANETWORKCOMMONHANDLER_H +#define ZYPP_MEDIA_MEDIANETWORKCOMMONHANDLER_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace media + { + /////////////////////////////////////////////////////////////////// + /// \class MediaNetworkCommonHandler + /// \brief Common baseclass for MediaCurl and MediaNetwork + /// + /// Access to commonly used stuff like \ref TransferSettings mainly + // to avoid duplicated code. + /////////////////////////////////////////////////////////////////// + class MediaNetworkCommonHandler : public MediaHandler + { + public: + MediaNetworkCommonHandler( const Url & url_r, + const Pathname & attach_point_r, + const Pathname & urlpath_below_attachpoint_r, + const bool does_download_r ) + : MediaHandler( url_r, attach_point_r, urlpath_below_attachpoint_r, does_download_r ) + , _redirTarget( findGeoIPRedirect(url_r) ) + + {} + + public: + TransferSettings & settings() + { return _settings; } + + protected: + + /** + * concatenate the attach url and the filename to a complete + * download url + **/ + Url getFileUrl(const Pathname & filename) const; + + + /** + * Rewrites the baseURL to the geoIP target if one is found in the metadata cache, + * otherwise simply returns the url again. + */ + static zypp::Url findGeoIPRedirect ( const zypp::Url &url ); + + protected: + mutable TransferSettings _settings; + Url _redirTarget; + }; + + } // namespace media + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_MEDIA_MEDIANETWORKCOMMONHANDLER_H diff --git a/zypp/media/MediaPlugin.cc b/zypp/media/MediaPlugin.cc new file mode 100644 index 0000000..48ba094 --- /dev/null +++ b/zypp/media/MediaPlugin.cc @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaPlugin.cc + * +*/ +#include + +#include +#include + +#include + +#include +#include + +using std::endl; + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// + namespace media + { ////////////////////////////////////////////////////////////////// + + MediaPlugin::MediaPlugin( const Url & url_r, const Pathname & attach_point_hint_r ) + : MediaHandler( url_r, attach_point_hint_r, /*path below attachpoint*/"/", /*does_download*/false ) + { + MIL << "MediaPlugin::MediaPlugin(" << url_r << ", " << attach_point_hint_r << ")" << endl; + } + void MediaPlugin::attachTo( bool next_r ) + {} + + void MediaPlugin::releaseFrom( const std::string & ejectDev_r ) + {} + + void MediaPlugin::getFile( const OnMediaLocation &file ) const + {} + + void MediaPlugin::getDir( const Pathname & dirname_r, bool recurse_r ) const + {} + + void MediaPlugin::getDirInfo( std::list & retlist_r, const Pathname & dirname_r, bool dots_r ) const + {} + + void MediaPlugin::getDirInfo( filesystem::DirContent & retlist_r, const Pathname & dirname_r, bool dots_r ) const + {} + + bool MediaPlugin::getDoesFileExist( const Pathname & filename_r ) const + { return false; } + + ////////////////////////////////////////////////////////////////// + } // namespace media + //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// diff --git a/zypp/media/MediaPlugin.h b/zypp/media/MediaPlugin.h new file mode 100644 index 0000000..998e1ef --- /dev/null +++ b/zypp/media/MediaPlugin.h @@ -0,0 +1,52 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaPlugin.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIAPLUGIN_H +#define ZYPP_MEDIA_MEDIAPLUGIN_H + +#include + +////////////////////////////////////////////////////////////////////// +namespace zypp +{ //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// + namespace media + { ////////////////////////////////////////////////////////////////// + + /** + * \brief Implementation class for plugin MediaHandler + * + * @see MediaHandler + */ + class MediaPlugin : public MediaHandler + { + public: + MediaPlugin( const Url & url_r, const Pathname & attach_point_hint_r ); + + ~MediaPlugin() override { try { release(); } catch(...) {} } + + protected: + void attachTo( bool next_r = false ) override; + void releaseFrom( const std::string & ejectDev_r ) override; + void getFile( const OnMediaLocation & file ) const override; + void getDir( const Pathname & dirname_r, bool recurse_r ) const override; + void getDirInfo( std::list & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const override; + void getDirInfo( filesystem::DirContent & retlist_r, const Pathname & dirname_r, bool dots_r = true ) const override; + bool getDoesFileExist( const Pathname & filename_r ) const override; + }; + + ////////////////////////////////////////////////////////////////// + } // namespace media + //////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////// +} // namespace zypp +////////////////////////////////////////////////////////////////////// +#endif // ZYPP_MEDIA_MEDIAPLUGIN_H diff --git a/zypp/media/MediaPriority.cc b/zypp/media/MediaPriority.cc new file mode 100644 index 0000000..52f8425 --- /dev/null +++ b/zypp/media/MediaPriority.cc @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaPriority.cc + * +*/ +#include +#include + +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace media + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + /** + * 4: local: file,dir,hd + * 3: remote: nfs,cifs,smb + * ?: download: http,https,ftp,sftp, tftp + * ?: volatile: cd,dvd + * 0: the rest + */ + MediaPriority::value_type scheme2priority( const std::string & scheme_r ) + { + switch ( scheme_r[0] ) + { +#define RETURN_IF(scheme,value) \ + if ( ::strcmp( scheme+1, scheme_r.c_str()+1 ) == 0 ) return value; + case 'c': + RETURN_IF( "cd", ZConfig::instance().download_media_prefer_download() ? 1 : 2 ); + RETURN_IF( "cifs", 3 ); + break; + + case 'd': + RETURN_IF( "dvd", ZConfig::instance().download_media_prefer_download() ? 1 : 2 ); + RETURN_IF( "dir", 4 ); + break; + + case 'f': + RETURN_IF( "file", 4 ); + RETURN_IF( "ftp", ZConfig::instance().download_media_prefer_download() ? 2 : 1); + break; + + case 't': + RETURN_IF( "tftp", ZConfig::instance().download_media_prefer_download() ? 2 : 1); + break; + + case 'h': + RETURN_IF( "http", ZConfig::instance().download_media_prefer_download() ? 2 : 1 ); + RETURN_IF( "https", ZConfig::instance().download_media_prefer_download() ? 2 : 1 ); + RETURN_IF( "hd", 4 ); + break; + + case 'n': + RETURN_IF( "nfs", 3 ); + RETURN_IF( "nfs4", 3 ); + break; + + case 's': + RETURN_IF( "sftp", ZConfig::instance().download_media_prefer_download() ? 2 : 1 ); + RETURN_IF( "smb", 3 ); + break; +#undef RETURN_IF + } + return 0; + } + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : MediaPriority::MediaPriority + // METHOD TYPE : Ctor + // + MediaPriority::MediaPriority( const std::string & scheme_r ) + : _val( scheme2priority( scheme_r ) ) + {} + + MediaPriority::MediaPriority( const Url & url_r ) + : _val( scheme2priority( url_r.getScheme() ) ) + {} + + ///////////////////////////////////////////////////////////////// + } // namespace media + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/media/MediaPriority.h b/zypp/media/MediaPriority.h new file mode 100644 index 0000000..e008a18 --- /dev/null +++ b/zypp/media/MediaPriority.h @@ -0,0 +1,101 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaPriority.h + * +*/ +#ifndef ZYPP_MEDIA_MEDIAPRIORITY_H +#define ZYPP_MEDIA_MEDIAPRIORITY_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class Url; + + /////////////////////////////////////////////////////////////////// + namespace media + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : MediaPriority + // + /** Derive a numeric priority from \ref Url scheme according to zypp.conf(download.media_preference). + * + * The class is simple. Constructable and assignable from \ref Url + * or scheme string. Implicit convertible into a numic \ref value_type. + * + * \code + * if ( MediaPriority("cd") \< MediaPriority("ftp") ) + * ... + * \endcode + * + * \todo Maybe introduce a static tribool, to allow overwriting zypp.conf(download.media_preference) default. + */ + class MediaPriority + { + public: + using value_type = int; + + public: + /** Default ctor. Least priority \c 0.*/ + MediaPriority() + : _val( 0 ) + {} + + /** Copy ctor. */ + MediaPriority( value_type val_r ) + : _val( val_r ) + {} + + /** Ctor from scheme string.*/ + MediaPriority( const std::string & scheme_r ); + + /** Ctor from scheme string defined by Url. */ + MediaPriority( const Url & url_r ); + + public: + /** Assign. */ + MediaPriority & operator=( value_type rhs ) + { _val = rhs; return *this; } + + /** Assign priority of scheme string. */ + MediaPriority & operator=( const std::string & scheme_r ) + { _val = MediaPriority(scheme_r); return *this; } + + /** Assign priority of scheme string defined by Url. */ + MediaPriority & operator=( const Url & url_r ) + { _val = MediaPriority(url_r); return *this; } + + public: + /** Conversion to value_type. */ + //@{ + /** Explicit */ + value_type & get() { return _val; } + /** Explicit */ + const value_type & get() const { return _val; } + /** Implicit */ + operator value_type &() { return get(); } + /** Implicit */ + operator const value_type &() const { return get(); } + //@} + + private: + value_type _val; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace media + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_MEDIA_MEDIAPRIORITY_H diff --git a/zypp/media/MediaSource.cc b/zypp/media/MediaSource.cc new file mode 100644 index 0000000..d633480 --- /dev/null +++ b/zypp/media/MediaSource.cc @@ -0,0 +1,29 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaSource.cc +*/ +#include + +#include + +namespace zypp { + namespace media { + + std::ostream & operator<<( std::ostream & str, const AttachPoint & obj ) + { + return str << (obj.temp ? "*" : "") << obj.path; + } + + std::ostream & operator<<( std::ostream & str, const AttachedMedia & obj ) + { + return str << "media(" << obj.mediaSource << ")attached(" << obj.attachPoint << ")"; + } + + } // namespace media +} // namespace zypp diff --git a/zypp/media/MediaSource.h b/zypp/media/MediaSource.h new file mode 100644 index 0000000..8a10204 --- /dev/null +++ b/zypp/media/MediaSource.h @@ -0,0 +1,157 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/MediaSource.h + * + */ +#ifndef ZYPP_MEDIA_MEDIASOURCE_H +#define ZYPP_MEDIA_MEDIASOURCE_H + +#include +#include + +#include +#include +#include + + +namespace zypp { + namespace media { + + /////////////////////////////////////////////////////////////////// + /** + * Media manager access Id type. + */ + using MediaAccessId = unsigned int; + + + /////////////////////////////////////////////////////////////////// + /** + * Media source internally used by MediaManager and MediaHandler. + */ + class MediaSource + { + public: + MediaSource(std::string _type, std::string _name, + unsigned int _maj=0, unsigned int _min=0, + std::string _bdir=std::string(), bool _own=true) + : maj_nr(_maj) + , min_nr(_min) + , type(std::move(_type)) + , name(std::move(_name)) + , bdir(std::move(_bdir)) + , iown(_own) + {} + + MediaSource() + : maj_nr(0) + , min_nr(0) + {} + + virtual + ~MediaSource() + {} + + /** + * Check if the both sources are equal. + */ + virtual bool equals(const MediaSource &src) const + { + if( type == src.type) + { + if( maj_nr == 0) + return name == src.name; + else + return maj_nr == src.maj_nr && + min_nr == src.min_nr; + } + return false; + } + + /** + * Return media source as string for debuging purposes. + */ + virtual std::string asString() const + { + std::string tmp1; + if(maj_nr != 0) + { + tmp1 = "[" + str::numstring(maj_nr) + "," + + str::numstring(min_nr) + "]"; + } + return type + "<" + name + tmp1 + ">"; + } + + unsigned int maj_nr; //!< A major number if source is a device. + unsigned int min_nr; //!< A minor number if source is a device. + std::string type; //!< A media handler specific source type. + std::string name; //!< A media handler specific source name. + std::string bdir; //!< Directory, the media may be bound to. + bool iown; //!< True, if mounted by media manager. + }; + + /** \relates MediaSource Stream output */ + inline std::ostream & operator<<( std::ostream & str, const MediaSource & obj ) + { return str << obj.asString(); } + + /////////////////////////////////////////////////////////////////// + /** + * Attach point of a media source. + */ + class AttachPoint + { + public: + AttachPoint(Pathname _path=Pathname(), + bool _temp=true) + : path(std::move(_path)) + , temp(_temp) + {} + + bool empty() const { return path.empty(); } + + Pathname path; //!< The path name (mount point). + bool temp; //!< If it was created temporary. + }; + + /** \relates AttachPoint Stream output */ + std::ostream & operator<<( std::ostream & str, const AttachPoint & obj ); + + /////////////////////////////////////////////////////////////////// + using MediaSourceRef = zypp::RW_pointer; + using AttachPointRef = zypp::RW_pointer; + + + /////////////////////////////////////////////////////////////////// + /** + * A simple structure containing references + * to a media source and its attach point. + */ + struct AttachedMedia + { + AttachedMedia() + {} + + AttachedMedia(MediaSourceRef _mediaSource, + AttachPointRef _attachPoint) + : mediaSource(std::move( _mediaSource)) + , attachPoint(std::move( _attachPoint)) + {} + + MediaSourceRef mediaSource; + AttachPointRef attachPoint; + }; + + /** \relates AttachedMedia Stream output */ + std::ostream & operator<<( std::ostream & str, const AttachedMedia & obj ); + + } // namespace media +} // namespace zypp + + +#endif // ZYPP_MEDIA_MEDIASOURCE_H + diff --git a/zypp/media/MediaUserAuth.h b/zypp/media/MediaUserAuth.h new file mode 100644 index 0000000..c78fe8c --- /dev/null +++ b/zypp/media/MediaUserAuth.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/MetaLinkParser.h b/zypp/media/MetaLinkParser.h new file mode 100644 index 0000000..712a5da --- /dev/null +++ b/zypp/media/MetaLinkParser.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/Mount.h b/zypp/media/Mount.h new file mode 100644 index 0000000..abb69e9 --- /dev/null +++ b/zypp/media/Mount.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/ProxyInfo.h b/zypp/media/ProxyInfo.h new file mode 100644 index 0000000..eecbe16 --- /dev/null +++ b/zypp/media/ProxyInfo.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/TransferSettings.h b/zypp/media/TransferSettings.h new file mode 100644 index 0000000..b4cb739 --- /dev/null +++ b/zypp/media/TransferSettings.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/UrlResolverPlugin.cc b/zypp/media/UrlResolverPlugin.cc new file mode 100644 index 0000000..6bf7605 --- /dev/null +++ b/zypp/media/UrlResolverPlugin.cc @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/UrlResolverPlugin.cc + * +*/ +#include +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace media + { ///////////////////////////////////////////////////////////////// + + /** UrlResolverPlugin implementation. */ + struct UrlResolverPlugin::Impl + { + + + }; + /////////////////////////////////////////////////////////////////// + + Url UrlResolverPlugin::resolveUrl(const Url & o_url, HeaderList &headers) + { + if (o_url.getScheme() != "plugin") + return o_url; + + Url url(o_url); + std::string name = url.getPathName(); + Pathname plugin_path = (ZConfig::instance().pluginsPath()/"urlresolver")/name; + if (PathInfo(plugin_path).isExist()) { + PluginScript scr; + scr.open(plugin_path); + // send frame to plugin + PluginFrame f("RESOLVEURL"); + + url::ParamMap params = url.getQueryStringMap(); + url::ParamMap::const_iterator param_it; + for( param_it = params.begin(); + param_it != params.end(); + ++param_it) + f.setHeader(param_it->first, param_it->second); + + scr.send(f); + + PluginFrame r(scr.receive()); + if (r.command() == "RESOLVEDURL") { + // now set + url = Url(r.body().asString()); + PluginFrame::HeaderListIterator it; + + for (it = r.headerBegin(); + it != r.headerEnd(); + ++it) { + std::pair values(*it); + // curl resets headers that are empty, so we use a workaround + if (values.second.empty()) { + values.second = "\r\nX-libcurl-Empty-Header-Workaround: *"; + } + headers.insert(values); + } + } + else if (r.command() == "ERROR") { + ZYPP_THROW(MediaException(r.body().asString())); + } + } + return url; + } + + /** \relates UrlResolverPlugin::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const UrlResolverPlugin::Impl & obj ) + { + return str << "UrlResolverPlugin::Impl"; + } + + UrlResolverPlugin::~UrlResolverPlugin() + {} + + std::ostream & operator<<( std::ostream & str, const UrlResolverPlugin & obj ) + { + return str << *obj._pimpl; + } + + ///////////////////////////////////////////////////////////////// + } // namespace media + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/media/UrlResolverPlugin.h b/zypp/media/UrlResolverPlugin.h new file mode 100644 index 0000000..d023c5c --- /dev/null +++ b/zypp/media/UrlResolverPlugin.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/media/UrlResolverPlugin.h + * +*/ +#ifndef ZYPP_MEDIA_URLRESOLVERPLUGIN_H +#define ZYPP_MEDIA_URLRESOLVERPLUGIN_H + +#include +#include +#include + +#include +#include +#include +#include +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace media + { ///////////////////////////////////////////////////////////////// + + // openSUSE/libzypp#560: Keep it public while foreign test depend on it. + class ZYPP_API UrlResolverPlugin + { + friend std::ostream & operator<<( std::ostream & str, const UrlResolverPlugin & obj ); + + public: + + struct Impl; + + using HeaderList = std::multimap; + + /** + * Resolves an url using the installed plugins + * If no plugin is found the url is resolved as + * its current value. + * + * Custom headers are inserted in the provided header list + */ + static Url resolveUrl(const Url &url, HeaderList &headers); + + public: + /** Dtor */ + ~UrlResolverPlugin(); + + private: + + /** Default ctor */ + UrlResolverPlugin(); + + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates UrlResolverPlugin Stream output */ + std::ostream & operator<<( std::ostream & str, const UrlResolverPlugin & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace media + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_MEDIA_URLRESOLVERPLUGIN_H diff --git a/zypp/media/proxyinfo/ProxyInfoImpl.h b/zypp/media/proxyinfo/ProxyInfoImpl.h new file mode 100644 index 0000000..fbf328c --- /dev/null +++ b/zypp/media/proxyinfo/ProxyInfoImpl.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/proxyinfo/ProxyInfoLibproxy.h b/zypp/media/proxyinfo/ProxyInfoLibproxy.h new file mode 100644 index 0000000..ddc5604 --- /dev/null +++ b/zypp/media/proxyinfo/ProxyInfoLibproxy.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/proxyinfo/ProxyInfoSysconfig.h b/zypp/media/proxyinfo/ProxyInfoSysconfig.h new file mode 100644 index 0000000..4d03dc0 --- /dev/null +++ b/zypp/media/proxyinfo/ProxyInfoSysconfig.h @@ -0,0 +1 @@ +#include diff --git a/zypp/media/proxyinfo/ProxyInfos.h b/zypp/media/proxyinfo/ProxyInfos.h new file mode 100644 index 0000000..7d82aa7 --- /dev/null +++ b/zypp/media/proxyinfo/ProxyInfos.h @@ -0,0 +1 @@ +#include diff --git a/zypp/misc/CheckAccessDeleted.cc b/zypp/misc/CheckAccessDeleted.cc new file mode 100644 index 0000000..0f8b1d8 --- /dev/null +++ b/zypp/misc/CheckAccessDeleted.cc @@ -0,0 +1,606 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/CheckAccessDeleted.cc + * +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::misc" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + // + // lsof output lines are a sequence of NUL terminated fields, + // where the 1st char determines the fields type. + // + // (pcuL) pid command userid loginname + // (ftkn).filedescriptor type linkcount filename + // + ///////////////////////////////////////////////////////////////// + + /** lsof output line + files extracted so far for this PID */ + using CacheEntry = std::pair>; + + ///////////////////////////////////////////////////////////////// + /// \class FilterRunsInContainer + /// \brief Functor guessing whether \a PID is running in a container. + /// + /// Use /proc to guess if a process is running in a container + ///////////////////////////////////////////////////////////////// + struct FilterRunsInContainer + { + private: + + enum Type { + IGNORE, + HOST, + CONTAINER + }; + + /*! + * Checks if the given file in proc is part of our root + * or not. If the file was unlinked, IGNORE is returned to signal + * that it is better to check the next file. + */ + Type in_our_root( const Pathname &path ) const { + + const PathInfo procInfoStat( path ); + + // if we can not stat the file continue to the next one + if ( procInfoStat.error() ) return IGNORE; + + // if the file was unlinked ignore it + if ( procInfoStat.nlink() == 0 ) + return IGNORE; + + // get the file the link points to, if that fails continue to the next + const Pathname linkTarget = filesystem::readlink( path ); + if ( linkTarget.empty() ) return IGNORE; + + // Pipe or socket 'type:[inode]' or an 'anon_inode:' + // They may or may not belong to a container... (bsc#1218291) + if ( linkTarget.relative() ) return IGNORE; + + // bsc#1226014. Ignore snaps. Execuables below /snap/ + // (may also be detectable via /proc/PID/cgroup) + if ( str::startsWith( linkTarget.asString(), "/snap/" ) ) + return CONTAINER; + + // get stat info for the target file + const PathInfo linkStat( linkTarget ); + + // Non-existent path means it's not reachable by us. + if ( !linkStat.isExist() ) + return CONTAINER; + + // If the file exists, it could simply mean it exists in and outside a container, check inode to be safe + if ( linkStat.ino() != procInfoStat.ino()) + return CONTAINER; + + // If the inode is the same, it could simply mean it exists in and outside a container but on different devices, check to be safe + if ( linkStat.dev() != procInfoStat.dev() ) + return CONTAINER; + + // assume HOST if all tests fail + return HOST; + } + + public: + + /*! + * Iterates over the /proc contents for the given pid + */ + bool operator()( const pid_t pid ) const { + + // first check the exe file + const Pathname pidDir = Pathname("/proc") / asString(pid); + const Pathname exeFile = pidDir / "exe"; + + auto res = in_our_root( exeFile ); + if ( res > IGNORE ) + return res == CONTAINER; + + // if IGNORE was returned we need to continue testing all the files in /proc//map_files until we hopefully + // find a still existing file. If all tests fail we will simply assume this pid is running on the HOST + + // a map of all already tested files, each file can be mapped multiple times and we do not want to check them more than once + std::unordered_set tested; + + // iterate over all the entries in /proc//map_files + filesystem::dirForEach( pidDir / "map_files", [ this, &tested, &res ]( const Pathname & dir_r, const char *const & name_r ){ + + // some helpers to make the code more self explanatory + constexpr bool contloop = true; + constexpr bool stoploop = false; + + const Pathname entryName = dir_r / name_r; + + // get the links target file and check if we alreadys know it, also if we can not read link information we skip the file + const Pathname linkTarget = filesystem::readlink( entryName ); + if ( linkTarget.empty() || !tested.insert( linkTarget.asString() ).second ) return contloop; + + // try to get file type + const auto mappedFileType = in_our_root( entryName ); + + // if we got something, remember the value and stop the loop + if ( mappedFileType > IGNORE ) { + res = mappedFileType; + return stoploop; + } + return contloop; + }); + + // If res is still IGNORE, we did not find a explicit answer. So, to be safe, we assume it is running on the host. + if ( res == IGNORE ) + return false; // can't tell for sure, lets assume host + + return res == CONTAINER; + } + + FilterRunsInContainer() {} + }; + + + /** bsc#1099847: Check for lsof version < 4.90 which does not support '-K i' + * Just a quick check to allow code15 libzypp runnig in a code12 environment. + * bsc#1036304: '-K i' was backported to older lsof versions, indicated by + * lsof providing 'backported-option-Ki'. + */ + bool lsofNoOptKi() + { + using target::rpm::librpmDb; + // RpmDb access is blocked while the Target is not initialized. + // Launching the Target just for this query would be an overkill. + struct TmpUnblock { + TmpUnblock() + : _wasBlocked( librpmDb::isBlocked() ) + { if ( _wasBlocked ) librpmDb::unblockAccess(); } + TmpUnblock(const TmpUnblock &) = delete; + TmpUnblock(TmpUnblock &&) = delete; + TmpUnblock &operator=(const TmpUnblock &) = delete; + TmpUnblock &operator=(TmpUnblock &&) = delete; + ~TmpUnblock() { + if (_wasBlocked) + librpmDb::blockAccess(); + } + + private: + bool _wasBlocked; + } tmpUnblock; + + librpmDb::db_const_iterator it; + return( it.findPackage( "lsof" ) && it->tag_edition() < Edition("4.90") && !it->tag_provides().count( Capability("backported-option-Ki") ) ); + } + + } //namespace + ///////////////////////////////////////////////////////////////// + + class CheckAccessDeleted::Impl + { + public: + CheckAccessDeleted::Impl *clone() const; + + bool addDataIf( const CacheEntry & cache_r, std::vector *debMap = nullptr ); + void addCacheIf( CacheEntry & cache_r, const std::string & line_r, std::vector *debMap = nullptr ); + + std::map filterInput( externalprogram::ExternalDataSource &source ); + CheckAccessDeleted::size_type createProcInfo( const std::map &in ); + + std::vector _data; + bool _fromLsofFileMode = false; // Set if we currently process data from a debug file + bool _verbose = false; + + std::map> debugMap; //will contain all used lsof files after filtering + Pathname _debugFile; + }; + + CheckAccessDeleted::Impl *CheckAccessDeleted::Impl::clone() const + { + Impl *myClone = new Impl( *this ); + return myClone; + } + + /** Add \c cache to \c data if the process is accessing deleted files. + * \c pid string in \c cache is the proc line \c (pcuLR), \c files + * are already in place. Always clear the \c cache.files! + */ + inline bool CheckAccessDeleted::Impl::addDataIf( const CacheEntry & cache_r, std::vector *debMap ) + { + const auto & filelist( cache_r.second ); + + if ( filelist.empty() ) + return false; + + // at least one file access so keep it: + _data.push_back( CheckAccessDeleted::ProcInfo() ); + CheckAccessDeleted::ProcInfo & pinfo( _data.back() ); + pinfo.files.insert( pinfo.files.begin(), filelist.begin(), filelist.end() ); + + const std::string & pline( cache_r.first ); + std::string commandname; // pinfo.command if still needed... + std::ostringstream pLineStr; //rewrite the first line in debug cache + for_( ch, pline.begin(), pline.end() ) + { + switch ( *ch ) + { + case 'p': + pinfo.pid = &*(ch+1); + if ( debMap ) + pLineStr <<&*(ch)<<'\0'; + break; + case 'R': + pinfo.ppid = &*(ch+1); + if ( debMap ) + pLineStr <<&*(ch)<<'\0'; + break; + case 'u': + pinfo.puid = &*(ch+1); + if ( debMap ) + pLineStr <<&*(ch)<<'\0'; + break; + case 'L': + pinfo.login = &*(ch+1); + if ( debMap ) + pLineStr <<&*(ch)<<'\0'; + break; + case 'c': + if ( pinfo.command.empty() ) { + commandname = &*(ch+1); + // the lsof command name might be truncated, so we prefer /proc//exe + if (!_fromLsofFileMode) + pinfo.command = filesystem::readlink( Pathname("/proc")/pinfo.pid/"exe" ).basename(); + if ( pinfo.command.empty() ) + pinfo.command = std::move(commandname); + if ( debMap ) + pLineStr <<'c'<front() = pLineStr.str(); + } + + //entry was added + return true; + } + + + /** Add file to cache if it refers to a deleted executable or library file: + * - Either the link count \c(k) is \c 0, or no link cout is present. + * - The type \c (t) is set to \c REG or \c DEL + * - The filedescriptor \c (f) is set to \c txt, \c mem or \c DEL + */ + inline void CheckAccessDeleted::Impl::addCacheIf( CacheEntry & cache_r, const std::string & line_r, std::vector *debMap ) + { + const char * f = 0; + const char * t = 0; + const char * n = 0; + + for_( ch, line_r.c_str(), ch+line_r.size() ) + { + switch ( *ch ) + { + case 'k': + if ( *(ch+1) != '0' ) // skip non-zero link counts + return; + break; + case 'f': + f = ch+1; + break; + case 't': + t = ch+1; + break; + case 'n': + n = ch+1; + break; + } + if ( *ch == '\n' ) break; // end of data + do { ++ch; } while ( *ch != '\0' ); // skip to next field + } + + if ( !t || !f || !n ) + return; // wrong filedescriptor/type/name + + if ( !( ( *t == 'R' && *(t+1) == 'E' && *(t+2) == 'G' && *(t+3) == '\0' ) + || ( *t == 'D' && *(t+1) == 'E' && *(t+2) == 'L' && *(t+3) == '\0' ) ) ) + return; // wrong type + + if ( !( ( *f == 'm' && *(f+1) == 'e' && *(f+2) == 'm' && *(f+3) == '\0' ) + || ( *f == 't' && *(f+1) == 'x' && *(f+2) == 't' && *(f+3) == '\0' ) + || ( *f == 'D' && *(f+1) == 'E' && *(f+2) == 'L' && *(f+3) == '\0' ) + || ( *f == 'l' && *(f+1) == 't' && *(f+2) == 'x' && *(f+3) == '\0' ) ) ) + return; // wrong filedescriptor type + + if ( str::contains( n, "(stat: Permission denied)" ) ) + return; // Avoid reporting false positive due to insufficient permission. + + if ( ! _verbose ) + { + if ( ! ( str::contains( n, "/lib" ) || str::contains( n, "bin/" ) ) ) + return; // Try to avoid reporting false positive unless verbose. + } + + if ( *f == 'm' || *f == 'D' ) // skip some wellknown nonlibrary memorymapped files + { + static const char * black[] = { + "/SYSV" + , "/var/" + , "/dev/" + , "/tmp/" + , "/proc/" + , "/memfd:" + , "/snap/" + }; + for_( it, arrayBegin( black ), arrayEnd( black ) ) + { + if ( str::hasPrefix( n, *it ) ) + return; + } + } + // Add if no duplicate + if ( debMap && cache_r.second.find(n) == cache_r.second.end() ) { + debMap->push_back(line_r); + } + cache_r.second.insert( n ); + } + + CheckAccessDeleted::CheckAccessDeleted( bool doCheck_r ) + : _pimpl(new Impl) + { + if ( doCheck_r ) check(); + } + + CheckAccessDeleted::size_type CheckAccessDeleted::check( const Pathname &lsofOutput_r, bool verbose_r ) + { + _pimpl->_verbose = verbose_r; + _pimpl->_fromLsofFileMode = true; + + FILE *inFile = fopen( lsofOutput_r.c_str(), "r" ); + if ( !inFile ) { + ZYPP_THROW( Exception( str::Format("Opening input file %1% failed.") % lsofOutput_r.c_str() ) ); + } + + //inFile is closed by ExternalDataSource + externalprogram::ExternalDataSource inSource( inFile, nullptr ); + auto cache = _pimpl->filterInput( inSource ); + return _pimpl->createProcInfo( cache ); + } + + std::map CheckAccessDeleted::Impl::filterInput( externalprogram::ExternalDataSource &source ) + { + // cachemap: PID => (deleted files) + // NOTE: omit PIDs running in a (lxc/docker) container + std::map cachemap; + + bool debugEnabled = !_debugFile.empty(); + + pid_t cachepid = 0; + FilterRunsInContainer runsInLXC; + MIL << "Silently scanning lsof output..." << endl; + zypp::base::LogControl::TmpLineWriter shutUp; // suppress excessive readdir etc. logging in runsInLXC + for( std::string line = source.receiveLine( 30 * 1000 ); ! line.empty(); line = source.receiveLine( 30 * 1000 ) ) + { + // NOTE: line contains '\0' separeated fields! + if ( line[0] == 'p' ) + { + str::strtonum( line.c_str()+1, cachepid ); // line is "p\0...." + if ( _fromLsofFileMode || !runsInLXC( cachepid ) ) { + if ( debugEnabled ) { + auto &pidMad = debugMap[cachepid]; + if ( pidMad.empty() ) + debugMap[cachepid].push_back( line ); + else + debugMap[cachepid].front() = line; + } + cachemap[cachepid].first.swap( line ); + } else { + cachepid = 0; // ignore this pid + } + } + else if ( cachepid ) + { + auto &dbgMap = debugMap[cachepid]; + addCacheIf( cachemap[cachepid], line, debugEnabled ? &dbgMap : nullptr); + } + } + return cachemap; + } + + CheckAccessDeleted::size_type CheckAccessDeleted::check( bool verbose_r ) + { + static const char* argv[] = { "lsof", "-n", "-FpcuLRftkn0", "-K", "i", NULL }; + if ( lsofNoOptKi() ) + argv[3] = NULL; + + _pimpl->_verbose = verbose_r; + _pimpl->_fromLsofFileMode = false; + + ExternalProgram prog( argv, ExternalProgram::Discard_Stderr ); + std::map cachemap; + + try { + cachemap = _pimpl->filterInput( prog ); + } catch ( const io::TimeoutException &e ) { + ZYPP_CAUGHT( e ); + prog.kill(); + ZYPP_THROW ( Exception( "Reading data from 'lsof' timed out.") ); + } + + int ret = prog.close(); + if ( ret != 0 ) + { + if ( ret == 129 ) + { + ZYPP_THROW( Exception(_("Please install package 'lsof' first.") ) ); + } + Exception err( str::Format("Executing 'lsof' failed (%1%).") % ret ); + err.remember( prog.execError() ); + ZYPP_THROW( err ); + } + + return _pimpl->createProcInfo( cachemap ); + } + + CheckAccessDeleted::size_type CheckAccessDeleted::Impl::createProcInfo(const std::map &in) + { + std::ofstream debugFileOut; + bool debugEnabled = false; + if ( !_debugFile.empty() ) { + debugFileOut.open( _debugFile.c_str() ); + debugEnabled = debugFileOut.is_open(); + + if ( !debugEnabled ) { + ERR<<"Unable to open debug file: "<<_debugFile< *mapPtr = nullptr; + + auto dbgInfo = debugMap.find(cached.first); + if ( dbgInfo != debugMap.end() ) + mapPtr = &(dbgInfo->second); + + if( !addDataIf( cached.second, mapPtr ) ) + continue; + + for ( const std::string &dbgLine: dbgInfo->second ) { + debugFileOut.write( dbgLine.c_str(), dbgLine.length() ); + } + } + } + return _data.size(); + } + + bool CheckAccessDeleted::empty() const + { + return _pimpl->_data.empty(); + } + + CheckAccessDeleted::size_type CheckAccessDeleted::size() const + { + return _pimpl->_data.size(); + } + + CheckAccessDeleted::const_iterator CheckAccessDeleted::begin() const + { + return _pimpl->_data.begin(); + } + + CheckAccessDeleted::const_iterator CheckAccessDeleted::end() const + { + return _pimpl->_data.end(); + } + + void CheckAccessDeleted::setDebugOutputFile(const Pathname &filename_r) + { + _pimpl->_debugFile = filename_r; + } + + std::string CheckAccessDeleted::findService( pid_t pid_r ) + { + ProcInfo p; + p.pid = str::numstring( pid_r ); + return p.service(); + } + + std::string CheckAccessDeleted::ProcInfo::service() const + { + // cgroup entries like: + // 1:name=systemd:/system.slice/systemd-udevd.service + // 0::/system.slice/systemd-udevd.service + // 0::/system.slice/systemd-udevd.service/udev + static const str::regex rx( "(0::|[0-9]+:name=systemd:)/system.slice/(.*/)?(.*).service(/.*)?$" ); + str::smatch what; + std::string ret; + iostr::simpleParseFile( InputStream( Pathname("/proc")/pid/"cgroup" ), + [&]( int num_r, const std::string& line_r )->bool + { + if ( str::regex_match( line_r, what, rx ) ) + { + ret = what[3]; + return false; // stop after match + } + return true; + } ); + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const CheckAccessDeleted & obj ) + { + return dumpRange( str << "CheckAccessDeleted ", + obj.begin(), + obj.end() ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const CheckAccessDeleted::ProcInfo & obj ) + { + if ( obj.pid.empty() ) + return str << ""; + + return dumpRangeLine( str << obj.command + << '<' << obj.pid + << '|' << obj.ppid + << '|' << obj.puid + << '|' << obj.login + << '>', + obj.files.begin(), + obj.files.end() ); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/misc/CheckAccessDeleted.h b/zypp/misc/CheckAccessDeleted.h new file mode 100644 index 0000000..102a484 --- /dev/null +++ b/zypp/misc/CheckAccessDeleted.h @@ -0,0 +1,133 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/CheckAccessDeleted.h + * +*/ +#ifndef ZYPP_MISC_CHECKACCESSDELETED_H +#define ZYPP_MISC_CHECKACCESSDELETED_H + +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** + * Check for running processes which access deleted executables or libraries. + * + * Executed after commit, this gives a hint which processes/services + * need to be restarted. + * + * Per default upon construction or explicit call to \ref check, + * information about running processes which access deleted files + * or libraries is collected and provided as a \ref ProcInfo + * container. + * + * Provides support for reproducing check results from a foreign system by + * creating a debug output file containing all required information, + * enabled by \ref setDebugOutputFile.\n + * This data file can be used as datasource when passed to \ref check(const Pathname &, bool). + */ + class ZYPP_API CheckAccessDeleted + { + + public: + class Impl; + /** + * Data about one running process accessing deleted files. + */ + struct ProcInfo + { + std::string pid; //!< process ID + std::string ppid; //!< parent process ID + std::string puid; //!< process user ID + std::string login; //!< process login name + std::string command; //!< process command name + std::vector files; //!< list of deleted executables or libraries accessed + + /** Guess if command was started by a systemd service script. + * The service name might be used to restart the service. + * \warning This is just a guess. + */ + std::string service() const; + }; + + using size_type = size_t; + using value_type = ProcInfo; + using const_iterator = std::vector::const_iterator; + + public: + /** Default ctor performs check immediately. + * Pass \c false and the initial check is omitted. + * \throws Exception if \ref check throws. + * \see \ref check. + */ + CheckAccessDeleted( bool doCheck_r = true ); + + public: + /** Check for running processes which access deleted executables or libraries. + * + * Per default \ref check will try guess and collect executables and + * libraries only by looking at the files path and name. (e.g named + * \c lib* or located in \c *bin/). + * + * A verbose check will omit this test and collect all processes using + * any deleted file. + * + * \return the number of processes found. + * \throws Exception On error collecting the data (e.g. no lsof installed) + */ + size_type check( bool verbose_r = false ); + + /** + * \overload + * Performs the same checks but instead of investigating the current system it + * uses information from \a lsofOutput_r to support debugging. + * + * \sa setDebugOutputFile + */ + size_type check( const Pathname &lsofOutput_r, bool verbose_r = false ); + + bool empty() const; + size_type size() const; + const_iterator begin() const; + const_iterator end() const; + + /** + * Writes all filtered process entries that make it into the final set into + * a file specified by \a filename_r. + */ + void setDebugOutputFile (const Pathname &filename_r); + + public: + /** Guess if pid was started by a systemd service script. + * The service name might be used to restart the service. + * \warning This is just a guess. + */ + static std::string findService( pid_t pid_r ); + private: + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CheckAccessDeleted Stream output */ + std::ostream & operator<<( std::ostream & str, const CheckAccessDeleted & obj ); + + /** \relates CheckAccessDeleted::ProcInfo Stream output */ + std::ostream & operator<<( std::ostream & str, const CheckAccessDeleted::ProcInfo & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_MISC_CHECKACCESSDELETED_H diff --git a/zypp/misc/DefaultLoadSystem.cc b/zypp/misc/DefaultLoadSystem.cc new file mode 100644 index 0000000..751a9df --- /dev/null +++ b/zypp/misc/DefaultLoadSystem.cc @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/DefaultLoadSystem.cc + * +*/ +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::misc" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace misc + { ///////////////////////////////////////////////////////////////// + + void defaultLoadSystem( const Pathname & sysRoot_r, LoadSystemFlags flags_r ) + { + if ( not flags_r && geteuid() != 0 ) { + flags_r |= LS_NOREFRESH; + } + MIL << str::form( "*** Load system at '%s' (%lx)", sysRoot_r.c_str(), (unsigned long)flags_r ) << endl; + + if ( ! PathInfo( sysRoot_r ).isDir() ) + ZYPP_THROW( Exception(str::form("sysRoot_r argument needs to be a directory. (%s)", sysRoot_r.c_str())) ); + + if ( ZYppFactory::instance().haveZYpp() ) + ZYPP_THROW( Exception("ZYpp instance is already created. (Call this method earlier.)") ); + + if ( flags_r.testFlag( LS_READONLY ) ) + zypp_readonly_hack::IWantIt (); + + sat::Pool satpool( sat::Pool::instance() ); + + if ( 1 ) + { + MIL << "*** load target '" << Repository::systemRepoAlias() << "'\t" << endl; + getZYpp()->initializeTarget( sysRoot_r ); + getZYpp()->target()->load(); + MIL << satpool.systemRepo() << endl; + } + + if ( not flags_r.testFlag( LS_NOREPOS ) ) + { + RepoManager repoManager( sysRoot_r ); + RepoInfoList repos = repoManager.knownRepositories(); + for_( it, repos.begin(), repos.end() ) + { + RepoInfo & nrepo( *it ); + + if ( ! nrepo.enabled() ) + continue; + + if ( ! flags_r.testFlag( LS_NOREFRESH ) ) + { + if ( repoManager.isCached( nrepo ) + && ( nrepo.type() == repo::RepoType::RPMPLAINDIR // refreshes always + || repoManager.checkIfToRefreshMetadata( nrepo, nrepo.url() ) == RepoManager::REFRESH_NEEDED ) ) + { + MIL << str::form( "*** clean cache for repo '%s'\t", nrepo.name().c_str() ) << endl; + repoManager.cleanCache( nrepo ); + MIL << str::form( "*** refresh repo '%s'\t", nrepo.name().c_str() ) << endl; + repoManager.refreshMetadata( nrepo ); + } + } + + if ( ! repoManager.isCached( nrepo ) ) + { + MIL << str::form( "*** build cache for repo '%s'\t", nrepo.name().c_str() ) << endl; + repoManager.buildCache( nrepo ); + } + + MIL << str::form( "*** load repo '%s'\t", nrepo.name().c_str() ) << std::flush; + try + { + repoManager.loadFromCache( nrepo ); + MIL << satpool.reposFind( nrepo.alias() ) << endl; + } + catch ( const Exception & exp ) + { + ERR << "*** load repo failed: " << exp.asString() + "\n" + exp.historyAsString() << endl; + ZYPP_RETHROW ( exp ); + } + } + } + MIL << str::form( "*** Read system at '%s'", sysRoot_r.c_str() ) << endl; + } + + ///////////////////////////////////////////////////////////////// + } // namespace misc + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/misc/DefaultLoadSystem.h b/zypp/misc/DefaultLoadSystem.h new file mode 100644 index 0000000..faa3b0f --- /dev/null +++ b/zypp/misc/DefaultLoadSystem.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/DefaultLoadSystem.h + * +*/ +#ifndef ZYPP_MISC_DEFAULTLOADSYSTEM_H +#define ZYPP_MISC_DEFAULTLOADSYSTEM_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace misc + { ///////////////////////////////////////////////////////////////// + + /** + * Bits for tuning \ref defaultLoadSystem. + * + * Use \ref LoadSystemFlags as a type-safe way of + * storing OR-combinations. + */ + enum LoadSystemFlag + { + LS_READONLY = (1 << 0), //!< // Create readonly ZYpp instance. + LS_NOREFRESH = (1 << 1), //!< // Don't refresh existing repos. + LS_NOREPOS = (1 << 2), //!< // Don't loag existing repos (just Target). + }; + + /** \relates LoadSystemFlag Type-safe way of storing OR-combinations. */ + ZYPP_DECLARE_FLAGS_AND_OPERATORS( LoadSystemFlags, LoadSystemFlag ); + + /** + * Create the ZYpp instance and load target and enabled repositories. + * + * \see LoadSystemFlag for options. + * + * \throws Exception on error + * + * \todo properly handle service refreshs + */ + void defaultLoadSystem( const Pathname & sysRoot_r = "/", LoadSystemFlags flags_r = LoadSystemFlags() ); + + /** \overload */ + inline void defaultLoadSystem( LoadSystemFlags flags_r ) + { defaultLoadSystem( "/", flags_r ); } + + ///////////////////////////////////////////////////////////////// + } // namespace misc + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_MISC_DEFAULTLOADSYSTEM_H diff --git a/zypp/misc/HelixHelpers.h b/zypp/misc/HelixHelpers.h new file mode 100644 index 0000000..2fa8ddd --- /dev/null +++ b/zypp/misc/HelixHelpers.h @@ -0,0 +1,321 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/HelixHelpers.h + * +*/ +#ifndef ZYPP_MISC_HELIXHELPERS_H +#define ZYPP_MISC_HELIXHELPERS_H + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + + +namespace helix::detail { + + template + struct AutoXmlFree : public zypp::AutoDispose + { + AutoXmlFree( Tp* ptr_r = nullptr ) : zypp::AutoDispose( ptr_r, [] ( Tp* ptr_r ) { if ( ptr_r ) ::xmlFree( ptr_r ); } ) {} + }; + + class XmlNode + { + + private: + xmlNodePtr _node; + + public: + XmlNode (const xmlNodePtr node) : _node(node){}; + virtual ~XmlNode (){}; + + // ---------------------------------- accessors + + std::string_view name() const { return (std::string_view((const char *)_node->name)); } + xmlElementType type() const { return (_node->type); } + + xmlNodePtr node() const { return (_node); } + std::optional next() const { return (_node->next == NULL ? std::optional() : XmlNode (_node->next)); } + std::optional children() const { return (_node->xmlChildrenNode == NULL ? std::optional() : XmlNode (_node->xmlChildrenNode)); } + + // ---------------------------------- methods + + bool equals (const std::string_view & n) const { return (strncasecmp ( name().data(), n.data(), n.length() ) == 0); } + bool isElement (void) const { return (type() == XML_ELEMENT_NODE); } + + std::map getAllProps () const { + std::map res; + for( xmlAttrPtr attr = _node->properties; NULL != attr; attr = attr->next ) { + if ( !attr->children ) + continue; + AutoXmlFree value( xmlNodeListGetString( _node->doc, attr->children, 1 ) ); + res.insert( std::make_pair( std::string((char *)attr->name), std::string( (char *)value.value() ) ) ); + } + return res; + } + + std::string getContent (void) const { + AutoXmlFree buf; + std::string ret; + + *buf = xmlNodeGetContent (_node); + + ret = std::string ((const char *)buf.value()); + + return (ret); + } + + std::string getProp (const std::string & name, const std::string & deflt = "") const { + AutoXmlFree ret; + std::string gs; + + *ret = xmlGetProp (_node, (const xmlChar *)name.c_str()); + + if (ret) { + gs = std::string ((const char *)ret.value()); + return gs; + } + return deflt; + } + + + template + T getValue ( const std::string & name, const T& deflt ) const; + + template + bool getValue ( const std::string & name, T& target ) const; + }; + + template<> + bool XmlNode::getValue ( const std::string & name, std::string& target ) const { + AutoXmlFree xml_s; + xmlNode *child; + + *xml_s = xmlGetProp(_node, (const xmlChar *)name.c_str()); + if (xml_s) { + target = std::string ((const char *)xml_s.value()); + return true; + } + + child = _node->xmlChildrenNode; + + while (child) { + if (strcasecmp((const char *)(child->name), name.c_str()) == 0) { + xml_s = xmlNodeGetContent(child); + if (xml_s) { + target = std::string ((const char *)xml_s.value()); + return true; + } + } + child = child->next; + } + return false; + } + + template<> + std::string XmlNode::getValue ( const std::string & name, const std::string& deflt ) const { + std::string res; + if ( !getValue( name, res ) ) + return deflt; + return res; + } + + bool parseSetup ( const XmlNode &setup, zypp::misc::testcase::TestcaseSetup &t, std::string *err ) + { + auto &target = t.data(); + auto architecture = setup.getProp( "arch" ); + if ( !architecture.empty() ) + { + try { + target.architecture = ( zypp::Arch(architecture) ); + } + catch( const zypp::Exception & excpt_r ) { + ZYPP_CAUGHT( excpt_r ); + if ( err ) *err = zypp::str::Str() << "Bad architecture '" << architecture << "' in "; + return false; + } + } + + auto node = setup.children(); + while ( node ) + { + if ( !node->isElement() ) { + node = node->next(); + continue; + } + +#define if_SolverFlag( N ) if ( node->equals( #N ) ) { target.N = true; } + if_SolverFlag( ignorealreadyrecommended ) else if ( node->equals( "ignorealready" ) ) { target.ignorealreadyrecommended = true; } + else if_SolverFlag( onlyRequires ) else if ( node->equals( "ignorerecommended" ) ) { target.onlyRequires = true; } + else if_SolverFlag( forceResolve ) + + else if_SolverFlag( cleandepsOnRemove ) + + else if_SolverFlag( allowDowngrade ) + else if_SolverFlag( allowNameChange ) + else if_SolverFlag( allowArchChange ) + else if_SolverFlag( allowVendorChange ) + + else if_SolverFlag( dupAllowDowngrade ) + else if_SolverFlag( dupAllowNameChange ) + else if_SolverFlag( dupAllowArchChange ) + else if_SolverFlag( dupAllowVendorChange ) +#undef if_SolverFlag + else if ( node->equals("focus") ) { + target.resolverFocus = zypp::resolverFocusFromString( node->getProp("value") ); + } + else if ( node->equals("system") ) { + target.systemRepo = zypp::misc::testcase::RepoDataImpl { + zypp::misc::testcase::TestcaseRepoType::Helix, + "@System", + 99, + node->getProp("file") + }; + } + else if ( node->equals("hardwareInfo") ) { + target.hardwareInfoFile = target.globalPath / node->getProp("path"); + } + else if ( node->equals("modalias") ) { + target.modaliasList.push_back( node->getProp("name") ); + } + else if ( node->equals("multiversion") ) { + target.multiversionSpec.insert( node->getProp("name") ); + } + else if (node->equals ("channel")) { + std::string name = node->getProp("name"); + std::string file = node->getProp("file"); + std::string type = node->getProp("type"); + + unsigned prio = 99; + std::string priority = node->getProp("priority"); + if ( !priority.empty() ) { + prio = zypp::str::strtonum( priority ); + } + + target.repos.push_back( zypp::misc::testcase::RepoDataImpl{ + zypp::misc::testcase::TestcaseRepoType::Helix, + name, + prio, + file + }); + } + else if ( node->equals("source") ) + { + std::string url = node->getProp("url"); + std::string alias = node->getProp("name"); + target.repos.push_back( zypp::misc::testcase::RepoDataImpl{ + zypp::misc::testcase::TestcaseRepoType::Url, + alias, + 99, + url + }); + } + else if ( node->equals("force-install") ) + { + target.forceInstallTasks.push_back( zypp::misc::testcase::ForceInstallImpl{ + node->getProp("channel"), + node->getProp("package"), + node->getProp("kind") + }); + } + else if ( node->equals("mediaid") ) + { + target.show_mediaid = true; + } + else if ( node->equals("arch") ) { + MIL << " deprecated, use instead" << std::endl; + std::string architecture = node->getProp("name"); + if ( architecture.empty() ) { + ERR << "Property 'name=' in missing or empty" << std::endl; + } + else { + MIL << "Setting architecture to '" << architecture << "'" << std::endl; + target.architecture = zypp::Arch( architecture ); + } + } + else if ( node->equals("locale") ) + { + zypp::Locale loc( node->getProp("name") ); + std::string fate = node->getProp("fate"); + if ( !loc ) { + ERR << "Bad or missing name in " << std::endl; + } + else if ( fate == "added" ) { + target.localesTracker.added().insert( loc ); + } + else if ( fate == "removed" ) { + target.localesTracker.removed().insert( loc ); + } + else { + target.localesTracker.current().insert( loc ); + } + } + else if ( node->equals("autoinst") ) { + target.autoinstalled.push( zypp::IdString( node->getProp("name") ).id() ); + } + else if ( node->equals("systemCheck") ) { + target.systemCheck = target.globalPath / node->getProp("path"); + } + else if ( node->equals("setlicencebit") ) { + target.set_licence = true; + } + else { + ERR << "Unrecognized tag '" << node->name() << "' in setup" << std::endl; + } + node = node->next(); + } + return true; + } + + bool parseTrialNode ( const XmlNode &node, zypp::misc::testcase::TestcaseTrial::Node &testcaseNode ) + { + testcaseNode.name() = node.name(); + const auto & content = node.getContent(); + if ( !content.empty() ) { + testcaseNode.value() = content; + } + testcaseNode.properties() = node.getAllProps(); + + for ( auto childNode = node.children(); childNode; childNode = childNode->next() ) { + auto testNode = std::make_shared(); + if ( !parseTrialNode( *childNode, *testNode ) ) + return false; + testcaseNode.children().push_back( testNode ); + } + return true; + } + + bool parseTrial ( const XmlNode &trial, zypp::misc::testcase::TestcaseTrial &target, std::string * ) + { + auto node = trial.children(); + while (node) { + if (!node->isElement()) { + node = node->next(); + continue; + } + + zypp::misc::testcase::TestcaseTrial::Node testcaseNode; + parseTrialNode( *node, testcaseNode ); + target.nodes().push_back( testcaseNode ); + node = node->next(); + } + return true; + } +} + +#endif diff --git a/zypp/misc/LoadTestcase.cc b/zypp/misc/LoadTestcase.cc new file mode 100644 index 0000000..a0eda0b --- /dev/null +++ b/zypp/misc/LoadTestcase.cc @@ -0,0 +1,242 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/LoadTestcase.cc + * +*/ +#include "LoadTestcase.h" +#include "HelixHelpers.h" +#include "YamlTestcaseHelpers.h" +#include +#include + +namespace zypp::misc::testcase { + + static const std::string helixControlFile = "solver-test.xml"; + static const std::string yamlControlFile = "zypp-control.yaml"; + + struct LoadTestcase::Impl { + TestcaseSetup _setup; + TestcaseTrials _trials; + + bool loadHelix (const Pathname &filename, std::string *err); + + bool loadYaml ( const Pathname &path, std::string *err); + }; + + + struct TestcaseTrial::Impl + { + std::vector nodes; + Impl *clone() const { return new Impl(*this); } + }; + + struct TestcaseTrial::Node::Impl + { + std::string name; + std::string value; + std::map properties; + std::vector> children; + Impl *clone() const { return new Impl(*this); } + }; + + TestcaseTrial::TestcaseTrial() : _pimpl ( new Impl() ) + { } + + TestcaseTrial::~TestcaseTrial() + { } + + const std::vector &TestcaseTrial::nodes() const + { return _pimpl->nodes; } + + std::vector &TestcaseTrial::nodes() + { return _pimpl->nodes; } + + TestcaseTrial::Node::Node() : _pimpl ( new Impl() ) + { } + + TestcaseTrial::Node::~Node() + { } + + const std::string &TestcaseTrial::Node::name() const + { return _pimpl->name; } + + std::string &TestcaseTrial::Node::name() + { return _pimpl->name; } + + const std::string &TestcaseTrial::Node::value() const + { return _pimpl->value; } + + std::string &TestcaseTrial::Node::value() + { return _pimpl->value; } + + const std::string &TestcaseTrial::Node::getProp( const std::string &name, const std::string &def ) const + { + auto it { _pimpl->properties.find( name ) }; + return it == _pimpl->properties.end() ? def : it->second; + } + + const std::map &TestcaseTrial::Node::properties() const + { return _pimpl->properties; } + + std::map &TestcaseTrial::Node::properties() + { return _pimpl->properties; } + + const std::vector > &TestcaseTrial::Node::children() const + { return _pimpl->children; } + + std::vector > &TestcaseTrial::Node::children() + { return _pimpl->children; } + + bool LoadTestcase::Impl::loadHelix(const zypp::filesystem::Pathname &filename, std::string *err) + { + xmlDocPtr xml_doc = xmlParseFile ( filename.c_str() ); + if (xml_doc == NULL) { + if ( err ) *err = (str::Str() << "Can't parse test file '" << filename << "'"); + return false; + } + + + auto root = helix::detail::XmlNode (xmlDocGetRootElement (xml_doc)); + + DBG << "Parsing file '" << filename << "'" << std::endl; + + if (!root.equals("test")) { + if ( err ) *err = (str::Str() << "Node not 'test' in parse_xml_test():" << root.name() << "'"); + return false; + } + + bool setupDone = false; + auto node = root.children(); + while (node) { + if (node->type() == XML_ELEMENT_NODE) { + if (node->equals( "setup" )) { + if ( setupDone ) { + if ( err ) *err = "Multiple setup tags found, this is not supported"; + return false; + } + setupDone = true; + if ( !helix::detail::parseSetup( *node, _setup, err ) ) + return false; + + } else if (node->equals( "trial" )) { + if ( !setupDone ) { + if ( err ) *err = "Any trials must be preceded by the setup!"; + return false; + } + TestcaseTrial trial; + if ( !helix::detail::parseTrial( *node, trial, err ) ) + return false; + _trials.push_back( trial ); + } else { + ERR << "Unknown tag '" << node->name() << "' in test" << std::endl; + } + } + node = ( node->next() ); + } + xmlFreeDoc (xml_doc); + return true; + } + + bool LoadTestcase::Impl::loadYaml(const zypp::filesystem::Pathname &path, std::string *err) + { + DBG << "Parsing file '" << path << "'" << std::endl; + + const auto makeError = [&]( const std::string_view &errStr ){ + if ( err ) *err = errStr; + return false; + }; + + YAML::Node control; + try { + control = YAML::LoadFile( path.asString() ); + + if ( control.Type() != YAML::NodeType::Map ) + return makeError("Root node must be of type Map."); + + const auto &setup = control["setup"]; + if ( !setup ) + return makeError("The 'setup' section is required."); + + if ( !yamltest::detail::parseSetup( setup, _setup, err) ) + return false; + + const auto &trials = control["trials"]; + if ( !trials ) + return makeError("The 'trials' section is required."); + if ( trials.Type() != YAML::NodeType::Sequence ) + return makeError("The 'trials' section must be of type Sequence."); + + for ( const auto &trial : trials ) { + zypp::misc::testcase::TestcaseTrial t; + if ( !trial["trial"] ) + return makeError("Every element in the trials sequence needs to have the 'trial' key."); + + if ( !yamltest::detail::parseTrial( trial["trial"], t, err) ) + return false; + _trials.push_back( t ); + } + } catch ( YAML::Exception &e ) { + if ( err ) *err = e.what(); + return false; + } catch ( ... ) { + if ( err ) *err = "Unknown error when parsing the control file"; + return false; + } + return true; + } + + LoadTestcase::LoadTestcase() : _pimpl( new Impl() ) + { } + + LoadTestcase::~LoadTestcase() + { } + + bool LoadTestcase::loadTestcaseAt(const zypp::filesystem::Pathname &path, std::string *err) + { + const auto t = testcaseTypeAt( path ); + if ( t == LoadTestcase::None ) { + if ( err ) *err = "Unsopported or no testcase in directory"; + return false; + } + + // reset everything + _pimpl.reset( new Impl() ); + _pimpl->_setup.data().globalPath = path; + + switch (t) { + case LoadTestcase::Helix: + return _pimpl->loadHelix( path / helixControlFile, err ); + case LoadTestcase::Yaml: + return _pimpl->loadYaml( path / yamlControlFile, err ); + default: + return false; + } + } + + LoadTestcase::Type LoadTestcase::testcaseTypeAt(const zypp::filesystem::Pathname &path) + { + if ( filesystem::PathInfo( path / helixControlFile ).isFile() ) { + return LoadTestcase::Helix; + } else if ( filesystem::PathInfo( path / yamlControlFile ).isFile() ) { + return LoadTestcase::Yaml; + } + return LoadTestcase::None; + } + + const TestcaseSetup &LoadTestcase::setupInfo() const + { + return _pimpl->_setup; + } + + const LoadTestcase::TestcaseTrials &LoadTestcase::trialInfo() const + { + return _pimpl->_trials; + } + +} diff --git a/zypp/misc/LoadTestcase.h b/zypp/misc/LoadTestcase.h new file mode 100644 index 0000000..4d3d039 --- /dev/null +++ b/zypp/misc/LoadTestcase.h @@ -0,0 +1,87 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/LoadTestcase.h + * +*/ +#ifndef ZYPP_MISC_LOADTESTCASE_H +#define ZYPP_MISC_LOADTESTCASE_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace zypp::misc::testcase { + + struct ZYPP_API_DEPTESTOMATIC TestcaseTrial + { + struct Node { + struct Impl; + + Node(); + ~Node(); + const std::string &name () const; + std::string &name (); + const std::string &value () const; + std::string &value (); + + const std::string &getProp( const std::string &name, const std::string &def = std::string() ) const; + const std::map &properties() const; + std::map &properties(); + const std::vector> &children() const; + std::vector> &children(); + + private: + RWCOW_pointer _pimpl; + + }; + + TestcaseTrial(); + ~TestcaseTrial(); + const std::vector &nodes () const; + std::vector &nodes (); + private: + struct Impl; + RWCOW_pointer _pimpl; + }; + + class ZYPP_API LoadTestcase : private zypp::base::NonCopyable + { + public: + struct Impl; + using TestcaseTrials = std::vector; + + enum Type { + None, + Helix, + Yaml + }; + + LoadTestcase(); + ~LoadTestcase(); + + bool loadTestcaseAt ( const zypp::Pathname &path, std::string *err ); + static Type testcaseTypeAt ( const zypp::Pathname &path ); + + const TestcaseSetup &setupInfo() const; + const TestcaseTrials &trialInfo() const; + + private: + std::unique_ptr _pimpl; + }; + +} + + +#endif // ZYPP_MISC_LOADTESTCASE_H diff --git a/zypp/misc/TestcaseSetup.cc b/zypp/misc/TestcaseSetup.cc new file mode 100644 index 0000000..0766b9f --- /dev/null +++ b/zypp/misc/TestcaseSetup.cc @@ -0,0 +1,260 @@ +#include "TestcaseSetupImpl.h" + +namespace zypp::misc::testcase +{ + RepoData::RepoData() : _pimpl( new RepoDataImpl ) + {} + + RepoData::~RepoData() + { } + + RepoData::RepoData(RepoDataImpl &&data) : _pimpl( new RepoDataImpl( std::move(data)) ) + { } + + TestcaseRepoType RepoData::type() const + { return _pimpl->type; } + + const std::string &RepoData::alias() const + { return _pimpl->alias; } + + uint RepoData::priority() const + { return _pimpl->priority; } + + const std::string &RepoData::path() const + { return _pimpl->path; } + + const RepoDataImpl &RepoData::data() const + { return *_pimpl; } + + RepoDataImpl &RepoData::data() + { return *_pimpl; } + + ForceInstall::ForceInstall() : _pimpl( new ForceInstallImpl ) + { } + + ForceInstall::~ForceInstall() + { } + + ForceInstall::ForceInstall(ForceInstallImpl &&data) : _pimpl( new ForceInstallImpl( std::move(data) )) + { } + + const ForceInstallImpl &ForceInstall::data() const + { return *_pimpl; } + + ForceInstallImpl &ForceInstall::data() + { return *_pimpl; } + + const std::string &ForceInstall::channel() const + { return _pimpl->channel; } + + const std::string &ForceInstall::package() const + { return _pimpl->package; } + + const std::string &ForceInstall::kind() const + { return _pimpl->kind; } + + TestcaseSetup::TestcaseSetup() : _pimpl( new TestcaseSetupImpl ) + { } + + TestcaseSetup::~TestcaseSetup() + { } + + Arch TestcaseSetup::architecture() const + { return _pimpl->architecture; } + + const std::optional &TestcaseSetup::systemRepo() const + { return _pimpl->systemRepo; } + + const std::vector &TestcaseSetup::repos() const + { return _pimpl->repos; } + + ResolverFocus TestcaseSetup::resolverFocus() const + { return _pimpl->resolverFocus; } + + const zypp::filesystem::Pathname &TestcaseSetup::globalPath() const + { return _pimpl->globalPath; } + + const zypp::filesystem::Pathname &TestcaseSetup::hardwareInfoFile() const + { return _pimpl->hardwareInfoFile; } + + const zypp::filesystem::Pathname &TestcaseSetup::systemCheck() const + { return _pimpl->systemCheck; } + + const target::Modalias::ModaliasList &TestcaseSetup::modaliasList() const + { return _pimpl->modaliasList; } + + const base::SetTracker &TestcaseSetup::localesTracker() const + { return _pimpl->localesTracker; } + + const std::vector > &TestcaseSetup::vendorLists() const + { return _pimpl->vendorLists; } + + const sat::StringQueue &TestcaseSetup::autoinstalled() const + { return _pimpl->autoinstalled; } + + const std::set &TestcaseSetup::multiversionSpec() const + { return _pimpl->multiversionSpec; } + + const std::vector &TestcaseSetup::forceInstallTasks() const + { return _pimpl->forceInstallTasks; } + + bool TestcaseSetup::set_licence() const + { return _pimpl->set_licence; } + + bool TestcaseSetup::show_mediaid() const + { return _pimpl->show_mediaid; } + + bool TestcaseSetup::ignorealreadyrecommended() const + { return _pimpl->ignorealreadyrecommended; } + + bool TestcaseSetup::onlyRequires() const + { return _pimpl->onlyRequires; } + + bool TestcaseSetup::forceResolve() const + { return _pimpl->forceResolve; } + + bool TestcaseSetup::cleandepsOnRemove() const + { return _pimpl->cleandepsOnRemove; } + + bool TestcaseSetup::allowDowngrade() const + { return _pimpl->allowDowngrade; } + + bool TestcaseSetup::allowNameChange() const + { return _pimpl->allowNameChange; } + + bool TestcaseSetup::allowArchChange() const + { return _pimpl->allowArchChange; } + + bool TestcaseSetup::allowVendorChange() const + { return _pimpl->allowVendorChange; } + + bool TestcaseSetup::dupAllowDowngrade() const + { return _pimpl->dupAllowDowngrade; } + + bool TestcaseSetup::dupAllowNameChange() const + { return _pimpl->dupAllowNameChange; } + + bool TestcaseSetup::dupAllowArchChange() const + { return _pimpl->dupAllowArchChange; } + + bool TestcaseSetup::dupAllowVendorChange() const + { return _pimpl->dupAllowVendorChange; } + + bool TestcaseSetup::applySetup( zypp::RepoManager &manager ) const + { + const auto &setup = data(); + if ( !setup.architecture.empty() ) + { + MIL << "Setting architecture to '" << setup.architecture << "'" << std::endl; + ZConfig::instance().setSystemArchitecture( setup.architecture ); + setenv ("ZYPP_TESTSUITE_FAKE_ARCH", setup.architecture.c_str(), 1); + } + + if ( setup.systemRepo ) { + if (!loadRepo( manager, *this, *setup.systemRepo ) ) + { + ERR << "Can't setup 'system'" << std::endl; + return false; + } + } + + if ( !setup.hardwareInfoFile.empty() ) { + setenv( "ZYPP_MODALIAS_SYSFS", setup.hardwareInfoFile.asString().c_str(), 1 ); + MIL << "setting HardwareInfo to: " << setup.hardwareInfoFile.asString() << std::endl; + } + + for ( const auto &channel : setup.repos ) { + if ( !loadRepo( manager, *this, channel ) ) + { + ERR << "Can't setup 'channel'" << std::endl; + return false; + } + } + + if ( !setup.systemCheck.empty() ) { + MIL << "setting systemCheck to: " << setup.systemCheck.asString() << std::endl; + SystemCheck::instance().setFile( setup.systemCheck ); + } + + return true; + } + + bool TestcaseSetup::loadRepo( zypp::RepoManager &manager, const TestcaseSetup &setup, const RepoData &data ) + { + const auto &repoData = data.data(); + Pathname pathname = setup._pimpl->globalPath + repoData.path; + MIL << "'" << pathname << "'" << std::endl; + + Repository repo; + + using TrType = zypp::misc::testcase::TestcaseRepoType; + + if ( repoData.type == TrType::Url ) { + try { + MIL << "Load from Url '" << repoData.path << "'" << std::endl; + + RepoInfo nrepo; + nrepo.setAlias ( repoData.alias ); + nrepo.setName ( repoData.alias ); + nrepo.setEnabled ( true ); + nrepo.setAutorefresh( false ); + nrepo.setPriority ( repoData.priority ); + nrepo.addBaseUrl ( Url(repoData.path) ); + + manager.refreshMetadata( nrepo ); + manager.buildCache( nrepo ); + manager.loadFromCache( nrepo ); + } + catch ( Exception & excpt_r ) { + ZYPP_CAUGHT (excpt_r); + ERR << "Couldn't load packages from Url '" << repoData.path << "'" << std::endl; + return false; + } + } + else { + try { + MIL << "Load from File '" << pathname << "'" << std::endl; + zypp::Repository satRepo; + + if ( repoData.alias == "@System" ) { + satRepo = zypp::sat::Pool::instance().systemRepo(); + } else { + satRepo = zypp::sat::Pool::instance().reposInsert( repoData.alias ); + } + + RepoInfo nrepo; + + nrepo.setAlias ( repoData.alias ); + nrepo.setName ( repoData.alias ); + nrepo.setEnabled ( true ); + nrepo.setAutorefresh( false ); + nrepo.setPriority ( repoData.priority ); + nrepo.addBaseUrl ( pathname.asUrl() ); + + satRepo.setInfo (nrepo); + if ( repoData.type == TrType::Helix ) + satRepo.addHelix( pathname ); + else + satRepo.addTesttags( pathname ); + MIL << "Loaded " << satRepo.solvablesSize() << " resolvables from " << ( repoData.path.empty()?pathname.asString():repoData.path) << "." << std::endl; + } + catch ( Exception & excpt_r ) { + ZYPP_CAUGHT (excpt_r); + ERR << "Couldn't load packages from XML file '" << repoData.path << "'" << std::endl; + return false; + } + } + return true; + } + + TestcaseSetupImpl &TestcaseSetup::data() + { + return *_pimpl; + } + + const TestcaseSetupImpl &TestcaseSetup::data() const + { + return *_pimpl; + } + +} diff --git a/zypp/misc/TestcaseSetup.h b/zypp/misc/TestcaseSetup.h new file mode 100644 index 0000000..0230f39 --- /dev/null +++ b/zypp/misc/TestcaseSetup.h @@ -0,0 +1,136 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/TestcaseSetup.h + * +*/ + +#ifndef ZYPP_MISC_TESTCASESETUP_H +#define ZYPP_MISC_TESTCASESETUP_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +namespace zypp { + class RepoManager; +} + +namespace zypp::misc::testcase +{ + + enum class TestcaseRepoType { + Helix, + Testtags, + Url + }; + + struct RepoDataImpl; + struct ForceInstallImpl; + struct TestcaseSetupImpl; + + class RepoData { + public: + RepoData (); + ~RepoData (); + RepoData ( RepoDataImpl &&data ); + TestcaseRepoType type() const; + const std::string &alias() const; + uint priority() const; + const std::string &path() const; + + const RepoDataImpl &data() const; + RepoDataImpl &data(); + private: + RWCOW_pointer _pimpl; + }; + + class ZYPP_API_DEPTESTOMATIC ForceInstall { + public: + ForceInstall (); + ~ForceInstall (); + ForceInstall ( ForceInstallImpl &&data ); + const std::string &channel () const; + const std::string &package () const; + const std::string &kind () const; + + const ForceInstallImpl &data() const; + ForceInstallImpl &data(); + private: + RWCOW_pointer _pimpl; + }; + + class ZYPP_API_DEPTESTOMATIC TestcaseSetup + { + public: + + TestcaseSetup(); + ~TestcaseSetup(); + + Arch architecture () const; + + const std::optional &systemRepo() const; + const std::vector &repos() const; + + // solver flags: default to false - set true if mentioned in + ResolverFocus resolverFocus() const; + + const Pathname &globalPath() const; + const Pathname &hardwareInfoFile() const; + const Pathname &systemCheck() const; + + const target::Modalias::ModaliasList &modaliasList() const; + const base::SetTracker &localesTracker() const; + const std::vector> &vendorLists() const; + const sat::StringQueue &autoinstalled() const; + const std::set &multiversionSpec() const; + const std::vector &forceInstallTasks() const; + + bool set_licence() const; + bool show_mediaid() const; + + bool ignorealreadyrecommended() const; + bool onlyRequires() const; + bool forceResolve() const; + bool cleandepsOnRemove() const; + + bool allowDowngrade() const; + bool allowNameChange() const; + bool allowArchChange() const; + bool allowVendorChange() const; + + bool dupAllowDowngrade() const; + bool dupAllowNameChange() const; + bool dupAllowArchChange() const; + bool dupAllowVendorChange() const; + + bool applySetup ( zypp::RepoManager &manager ) const; + + static bool loadRepo (zypp::RepoManager &manager, const TestcaseSetup &setup, const RepoData &data ); + + TestcaseSetupImpl &data(); + const TestcaseSetupImpl &data() const; + + private: + RWCOW_pointer _pimpl; + }; + +} + + +#endif // ZYPP_MISC_TESTCASESETUPIMPL_H diff --git a/zypp/misc/TestcaseSetupImpl.h b/zypp/misc/TestcaseSetupImpl.h new file mode 100644 index 0000000..6598a46 --- /dev/null +++ b/zypp/misc/TestcaseSetupImpl.h @@ -0,0 +1,85 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_MISC_TESTCASESETUPIMPL_H +#define ZYPP_MISC_TESTCASESETUPIMPL_H + +#include +#include +#include +#include +#include +#include + +#define ZYPP_USE_RESOLVER_INTERNALS +#include + +namespace zypp::misc::testcase +{ + struct RepoDataImpl { + TestcaseRepoType type; + std::string alias; + uint priority = 99; + std::string path; + + RepoDataImpl *clone () const { return new RepoDataImpl(*this); } + }; + + struct ForceInstallImpl { + std::string channel; + std::string package; + std::string kind; + + ForceInstallImpl *clone () const { return new ForceInstallImpl(*this); } + }; + + struct TestcaseSetupImpl + { + Arch architecture = Arch_noarch; + + std::optional systemRepo; + std::vector repos; + + // solver flags: default to false - set true if mentioned in + ResolverFocus resolverFocus = ResolverFocus::Default; + + Pathname globalPath; + Pathname hardwareInfoFile; + Pathname systemCheck; + + target::Modalias::ModaliasList modaliasList; + base::SetTracker localesTracker; + std::vector> vendorLists; + sat::StringQueue autoinstalled; + std::set multiversionSpec; + std::vector forceInstallTasks; + + bool set_licence = false; + bool show_mediaid = false; + + bool ignorealreadyrecommended = false; + bool onlyRequires = false; + bool forceResolve = false; + bool cleandepsOnRemove = false; + + bool allowDowngrade = false; + bool allowNameChange = false; + bool allowArchChange = false; + bool allowVendorChange = false; + + bool dupAllowDowngrade = false; + bool dupAllowNameChange = false; + bool dupAllowArchChange = false; + bool dupAllowVendorChange = false; + + TestcaseSetupImpl *clone () const { return new TestcaseSetupImpl(*this); } + }; +} + +#endif diff --git a/zypp/misc/YamlTestcaseHelpers.h b/zypp/misc/YamlTestcaseHelpers.h new file mode 100644 index 0000000..eb8d9b5 --- /dev/null +++ b/zypp/misc/YamlTestcaseHelpers.h @@ -0,0 +1,330 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/misc/YamlTestcaseHelpers.h + * +*/ +#ifndef ZYPP_MISC_YAMLTESTCASEHELPERS_H +#define ZYPP_MISC_YAMLTESTCASEHELPERS_H + +#include +#include "LoadTestcase.h" +#include "TestcaseSetupImpl.h" + +#include + +#include + +namespace yamltest::detail { + + bool parseSetup ( const YAML::Node &setup, zypp::misc::testcase::TestcaseSetup &t, std::string *err ) { + + auto &target = t.data(); + MIL << "Parsing setup node " << std::endl; + for ( YAML::const_iterator it = setup.begin(); it != setup.end(); it++ ) { + + const std::string &key = it->first.as(); + const auto &data = it->second; + + MIL << "Found key " << key << std::endl; + + // reads a sequence either from a file or inline, depending on the type of "data" + auto readListInlineOrFromFile = [&]( const auto &cb , std::string *err ) -> bool { + if ( data.Type() == YAML::NodeType::Sequence ) { + int cnt = 0; + for ( const auto &node: data ) { + if ( !cb( node, err ) ) return false; + cnt ++; + } + MIL << "Loaded " << cnt << " Elements inline" << std::endl; + } else { + const std::string &fName = data.as(); + MIL << "Trying to load list from file " << fName << std::endl; + try { + auto doc = YAML::LoadFile( fName ); + if ( doc.Type() != YAML::NodeType::Sequence ) { + if ( err ) *err = "Expected the top node to be a sequence in external file for key: "; + return false; + } + + int cnt = 0; + for ( const auto &node : doc ) { + if ( !cb( node, err ) ) return false; + cnt ++; + } + MIL << "Loaded " << cnt << " Elements from file" << std::endl; + } catch ( YAML::Exception &e ) { + if ( err ) { + auto errStr = zypp::str::Str(); + errStr << e.what(); + if ( !e.mark.is_null() ) { + errStr << " Line: " << e.mark.line << " Col: " << e.mark.column << " pos: " << e.mark.pos; + } + *err = errStr; + } + return false; + } catch ( ... ) { + if ( err ) *err = zypp::str::Str() << "Unknown error when parsing the file for " << key; + return false; + } + } + return true; + }; + + if ( key == "resolverFlags" ) { +#define if_SolverFlag( N ) if ( data[#N] ) { target.N = data[#N].as(); } + if_SolverFlag( ignorealreadyrecommended ) if ( data["ignorealready"] ) { target.ignorealreadyrecommended = data["ignorealready"].as(); } + if_SolverFlag( onlyRequires ) if ( data["ignorerecommended"] ) { target.onlyRequires = data["ignorerecommended"].as(); } + if_SolverFlag( forceResolve ) + + if_SolverFlag( cleandepsOnRemove ) + + if_SolverFlag( allowDowngrade ) + if_SolverFlag( allowNameChange ) + if_SolverFlag( allowArchChange ) + if_SolverFlag( allowVendorChange ) + + if_SolverFlag( dupAllowDowngrade ) + if_SolverFlag( dupAllowNameChange ) + if_SolverFlag( dupAllowArchChange ) + if_SolverFlag( dupAllowVendorChange ) +#undef if_SolverFlag + if ( data["focus"] ) { + target.resolverFocus = zypp::resolverFocusFromString( data["focus"].as() ); + } + } else if ( key == ("system") ) { + target.systemRepo = zypp::misc::testcase::RepoDataImpl { + zypp::misc::testcase::TestcaseRepoType::Testtags, + "@System", + 99, + data["file"].as() + }; + } + else if ( key == ("hardwareInfo") ) { + target.hardwareInfoFile = data.as(); + } + else if ( key == ("modalias") ) { + bool success = readListInlineOrFromFile( [&target]( const YAML::Node &dataNode, auto ){ + target.modaliasList.push_back( dataNode.as() ); + return true; + }, err ); + if ( !success ) return false; + } + else if ( key == ("multiversion") ) { + bool success = readListInlineOrFromFile( [&target]( const YAML::Node &dataNode, auto ){ + target.multiversionSpec.insert( dataNode.as() ); + return true; + }, err ); + if ( !success ) return false; + } + else if (key == ("channels")) { + bool success = readListInlineOrFromFile( [&target]( const YAML::Node &dataNode, auto ){ + std::string name = dataNode["alias"].as(); + std::string file = dataNode["file"].as(); + + unsigned prio = 99; + if ( dataNode["priority"] ) + prio = dataNode["priority"].as(); + + target.repos.push_back( zypp::misc::testcase::RepoDataImpl{ + zypp::misc::testcase::TestcaseRepoType::Testtags, + name, + prio, + file + }); + return true; + }, err ); + if ( !success ) return false; + } + else if ( key == ("sources") ) + { + bool success = readListInlineOrFromFile( [&target]( const YAML::Node &dataNode, auto ){ + std::string url = dataNode["url"].as(); + std::string alias = dataNode["name"].as(); + target.repos.push_back( zypp::misc::testcase::RepoDataImpl{ + zypp::misc::testcase::TestcaseRepoType::Url, + alias, + 99, + url + }); + return true; + }, err ); + if ( !success ) return false; + } + else if ( key == ("force-install") ) + { + bool success = readListInlineOrFromFile( [&target]( const YAML::Node &dataNode, auto ){ + target.forceInstallTasks.push_back( zypp::misc::testcase::ForceInstallImpl{ + dataNode["channel"].as(), + dataNode["package"].as(), + dataNode["kind"].as() + }); + return true; + }, err ); + if ( !success ) return false; + } + else if ( key == ("mediaid") ) + { + target.show_mediaid = data.as(); + } + else if ( key == ("arch") ) { + std::string architecture = data.as(); + if ( architecture.empty() ) { + if (err) *err = zypp::str::Str() << "Property 'arch' in setup can not be empty." << std::endl; + return false; + } + else { + MIL << "Setting architecture to '" << architecture << "'" << std::endl; + target.architecture = zypp::Arch( architecture ); + } + } + else if ( key == ("locales") ) + { + bool success = readListInlineOrFromFile( [&target]( const YAML::Node &dataNode, std::string *err ){ + zypp::Locale loc( dataNode["name"].as() ); + std::string fate = dataNode["fate"].as(); + if ( !loc ) { + if (err) *err = zypp::str::Str() << "Bad or missing name in locale..." << std::endl; + return false; + } + else if ( fate == "added" ) { + target.localesTracker.added().insert( loc ); + } + else if ( fate == "removed" ) { + target.localesTracker.removed().insert( loc ); + } + else { + target.localesTracker.current().insert( loc ); + } + return true; + }, err ); + if ( !success ) return false; + } + else if ( key == ("vendors") ) + { + bool success = readListInlineOrFromFile( [&target]( const YAML::Node & dataNode, std::string * err ) { + std::vector vlist; + for ( const auto & node : dataNode ) + vlist.push_back( node.as() ); + if ( ! vlist.empty() ) + target.vendorLists.push_back( std::move(vlist) ); + return true; + }, err ); + if ( !success ) return false; + } + else if ( key == ("autoinst") ) { + bool success = readListInlineOrFromFile( [&]( const YAML::Node &dataNode, auto ){ + target.autoinstalled.push( zypp::IdString( dataNode.as() ).id() ); + return true; + }, err ); + if ( !success ) return false; + } + else if ( key == ("systemCheck") ) { + target.systemCheck = data.as(); + } + else if ( key == ("setlicencebit") ) { + target.set_licence = data.as(); + } + else { + ERR << "Ignoring unrecognized tag '" << key << "' in setup" << std::endl; + } + } + return true; + } + + template + bool parseJobs ( const YAML::Node &trial, std::vector &target, std::string *err ); + + template + bool parseSingleJob ( const YAML::Node &jobNode, std::vector &target, std::string *err ) { + + constexpr bool isSubNode = std::is_same_v>; + if ( jobNode["include"] ) { + //handle include + const auto &fName = jobNode["include"].as(); + MIL << "Including file " << fName << std::endl; + try { + auto doc = YAML::LoadFile( fName ); + if ( !parseJobs( doc, target, err ) ) + return false; + MIL << "Including file " << fName << "was successful" << std::endl; + } catch ( YAML::Exception &e ) { + if ( err ) *err = e.what(); + return false; + } catch ( ... ) { + if ( err ) *err = zypp::str::Str() << "Unknown error when parsing the file: " << fName; + return false; + } + return true; + } + + zypp::misc::testcase::TestcaseTrial::Node n; + if ( !jobNode["job"] ) { + if ( err ) { + auto errStr = zypp::str::Str(); + const auto &mark = jobNode.Mark(); + errStr << "'job' key missing from trial node."; + if ( !mark.is_null() ) { + errStr << " Line: " << mark.line << " Col: " << mark.column << " pos: " << mark.pos; + } + *err = errStr; + } + return false; + } + + for ( const auto &elem : jobNode ) { + const std::string &key = elem.first.as(); + const auto &data = elem.second; + if ( key == "job" ) { + n.name() = data.as(); + } else if ( key == "__content") { + n.value() = data.as(); + } else { + if( data.IsScalar() ) { + n.properties().insert( { key, data.as() } ); + } else if ( data.IsSequence() ) { + // if the type of a data field is a sequence, we treat all the elements in there + // as sub elements. Just like in XML you can have sub nodes its the same here + // the key name is ignored in those cases and can be chosen freely + if ( !parseJobs( data, n.children(), err ) ) + return false; + } else if ( data.IsMap() ) { + // if the type of a data field is a map, we build a child node from it. + // Just like with sequence but a single field. + // The key name is ignored in those cases and can be chosen freely + if ( !parseSingleJob( data, n.children(), err) ) + return false; + } else { + ERR << "Ignoring field " << key << " with unsupported type:" << data.Type() << std::endl; + } + } + } + if constexpr ( isSubNode ) { + target.push_back( std::make_shared( std::move(n) ) ); + } else { + target.push_back( std::move(n) ); + } + return true; + } + + template + bool parseJobs ( const YAML::Node &trial, std::vector &target, std::string *err ) { + for ( const auto &jobNode : trial ) { + if ( !parseSingleJob( jobNode, target, err ) ) + return false; + } + return true; + } + + bool parseTrial ( const YAML::Node &trial, zypp::misc::testcase::TestcaseTrial &target, std::string *err ) { + MIL << "Parsing trials." << std::endl; + return parseJobs( trial, target.nodes(), err ); + } +} + +#endif // ZYPP_MISC_YAMLTESTCASEHELPERS_H diff --git a/zypp/ng/Context b/zypp/ng/Context new file mode 100644 index 0000000..7e33fb6 --- /dev/null +++ b/zypp/ng/Context @@ -0,0 +1 @@ +#include "context.h" diff --git a/zypp/ng/RepoManager b/zypp/ng/RepoManager new file mode 100644 index 0000000..1c08302 --- /dev/null +++ b/zypp/ng/RepoManager @@ -0,0 +1 @@ +#include "repomanager.h" diff --git a/zypp/ng/UserRequest b/zypp/ng/UserRequest new file mode 100644 index 0000000..890f836 --- /dev/null +++ b/zypp/ng/UserRequest @@ -0,0 +1 @@ +#include "userrequest.h" diff --git a/zypp/ng/context.cc b/zypp/ng/context.cc new file mode 100644 index 0000000..f5bb6f8 --- /dev/null +++ b/zypp/ng/context.cc @@ -0,0 +1,72 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "private/context_p.h" +#include +#include +#include +#include + +namespace zyppng { + + ZYPP_IMPL_PRIVATE( Context ) + + ZYPP_IMPL_PRIVATE_CONSTR( Context ) + : UserInterface( *new ContextPrivate( *this ) ) + { + Z_D(); + d->_zyppPtr = zypp::getZYpp(); + d->_eventDispatcher = ThreadData::current().ensureDispatcher(); + + d->_provider = Provide::create( d->_providerDir ); + + // @TODO should start be implicit as soon as something is enqueued? + d->_provider->start(); + } + + ProvideRef Context::provider() const + { + Z_D(); + return d->_provider; + } + + KeyRingRef Context::keyRing() const + { + return d_func()->_zyppPtr->keyRing(); + } + + zypp::ZConfig &Context::config() + { + return zypp::ZConfig::instance(); + } + + zypp::ResPool Context::pool() + { + return zypp::ResPool::instance(); + } + + zypp::ResPoolProxy Context::poolProxy() + { + return zypp::ResPool::instance().proxy(); + } + + zypp::sat::Pool Context::satPool() + { + return zypp::sat::Pool::instance(); + } + + void Context::executeImpl(const AsyncOpBaseRef& op) + { + auto loop = EventLoop::create(); + op->sigReady().connect([&](){ + loop->quit(); + }); + loop->run(); + return; + } +} diff --git a/zypp/ng/context.h b/zypp/ng/context.h new file mode 100644 index 0000000..39ae471 --- /dev/null +++ b/zypp/ng/context.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_CONTEXT_INCLUDED +#define ZYPP_NG_CONTEXT_INCLUDED + +#include +#include +#include +#include + +namespace zypp { + DEFINE_PTR_TYPE(KeyRing); + class ZConfig; +} + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS( Context ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( ProgressObserver ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( Provide ); + + using KeyRing = zypp::KeyRing; + using KeyRingRef = zypp::KeyRing_Ptr; + + class ContextPrivate; + + + /*! + * The Context class is the central object of libzypp, carrying all state that is + * required to manage the system. + */ + class Context : public UserInterface + { + ZYPP_DECLARE_PRIVATE(Context) + ZYPP_ADD_CREATE_FUNC(Context) + + public: + + using ProvideType = Provide; + + ZYPP_DECL_PRIVATE_CONSTR(Context); + + template + void execute ( AsyncOpRef op ) { + if ( op->isReady () ) + return; + return executeImpl( op ); + } + + ProvideRef provider() const; + KeyRingRef keyRing () const; + zypp::ZConfig &config(); + + /** + * Access to the resolvable pool. + */ + zypp::ResPool pool(); + + /** Pool of ui::Selectable. + * Based on the ResPool, ui::Selectable groups ResObjetcs of + * same kind and name. + */ + zypp::ResPoolProxy poolProxy(); + + /** + * Access to the sat pool. + */ + zypp::sat::Pool satPool(); + + private: + void executeImpl ( const AsyncOpBaseRef& op ); + }; + + template + auto joinPipeline( ContextRef ctx, AsyncOpRef res ) { + if constexpr ( detail::is_async_op_v ) { + ctx->execute(res); + return res->get(); + } else { + return res; + } + } + +} + + +#endif diff --git a/zypp/ng/private/context_p.h b/zypp/ng/private/context_p.h new file mode 100644 index 0000000..811abab --- /dev/null +++ b/zypp/ng/private/context_p.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_PRIVATE_CONTEXT_P_H +#define ZYPP_NG_PRIVATE_CONTEXT_P_H + +#include +#include +#include +#include +#include + +namespace zyppng +{ + ZYPP_FWD_DECL_TYPE_WITH_REFS ( EventDispatcher ); + + class ContextPrivate : public UserInterfacePrivate + { + public: + ContextPrivate ( Context &b ) : UserInterfacePrivate(b){} + EventDispatcherRef _eventDispatcher; + zypp::filesystem::TmpDir _providerDir; + ProvideRef _provider; + zypp::ZYpp::Ptr _zyppPtr; + }; + +} + + +#endif diff --git a/zypp/ng/private/repomanager_p.h b/zypp/ng/private/repomanager_p.h new file mode 100644 index 0000000..9abba79 --- /dev/null +++ b/zypp/ng/private/repomanager_p.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_PRIVATE_REPOMANAGER_P_H +#define ZYPP_NG_PRIVATE_REPOMANAGER_P_H + +#include +#include +#include + +namespace zyppng { + + class ZYPP_LOCAL RepoManagerPrivate : public BasePrivate, public zypp::RepoManagerBaseImpl + { + ZYPP_DECLARE_PUBLIC(RepoManager) + public: + + RepoManagerPrivate( ContextRef ctx, RepoManagerOptions repoOpts, RepoManager &p ); + + AsyncOpRef> probe( const zypp::Url & url, const zypp::Pathname & path = zypp::Pathname() ) const; + + ContextWeakRef _context; //< weak ref to our context to prevent a ref loop, this should always be valid + + // RepoManagerBaseImpl interface + public: + void removeRepository(const zypp::RepoInfo &info, const zypp::ProgressData::ReceiverFnc &) override; + }; + +} + + +#endif diff --git a/zypp/ng/progressobserveradaptor.cc b/zypp/ng/progressobserveradaptor.cc new file mode 100644 index 0000000..13448a1 --- /dev/null +++ b/zypp/ng/progressobserveradaptor.cc @@ -0,0 +1,63 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "progressobserveradaptor.h" + +namespace zyppng { + + void ProgressObserverAdaptor::init() + { + _observer = ProgressObserver::create(); + _observer->connectFunc( + &ProgressObserver::sigStarted, + [this](auto &obs) { update(); }, *_observer); + _observer->connectFunc( + &ProgressObserver::sigLabelChanged, + [this](auto &obs, const auto &) { if(!_first) update(); }, *_observer); + _observer->connectFunc( + &ProgressObserver::sigProgressChanged, + [this](auto &obs, const auto &p) { update(); }, *_observer); + _observer->connectFunc( + &ProgressObserver::sigFinished, + [this](auto &obs, const auto &) { update(true); }, *_observer); + } + + ProgressObserverAdaptor::ProgressObserverAdaptor( + zypp::callback::SendReport &report) + : _report(report) + { + init(); + } + ProgressObserverAdaptor::ProgressObserverAdaptor( + const zypp::ProgressData::ReceiverFnc &fnc, + zypp::callback::SendReport &report) + : _fnc(fnc), _report(report) + { + init(); + } + ProgressObserverRef ProgressObserverAdaptor::observer() { return _observer; } + bool ProgressObserverAdaptor::update(bool fin) { + zypp::ProgressData progress(0, 100, _observer->progress()); + progress.name(_observer->label()); + + if (_first) { + _report->start(progress); + _first = false; + } + + bool value = _report->progress(progress); + if (_fnc) + value &= _fnc(progress); + + if (fin) { + _report->finish(progress); + } + return value; + } +} // namespace zyppng diff --git a/zypp/ng/progressobserveradaptor.h b/zypp/ng/progressobserveradaptor.h new file mode 100644 index 0000000..b9af810 --- /dev/null +++ b/zypp/ng/progressobserveradaptor.h @@ -0,0 +1,36 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_PROGRESSOBSERVERADAPTOR_INCLUDED +#define ZYPP_NG_PROGRESSOBSERVERADAPTOR_INCLUDED + +#include +#include + +namespace zyppng { + struct ProgressObserverAdaptor + { + + ProgressObserverAdaptor( zypp::callback::SendReport &report ); + + ProgressObserverAdaptor( const zypp::ProgressData::ReceiverFnc &fnc, zypp::callback::SendReport &report ); + + ProgressObserverRef observer(); + + private: + void init(); + bool update(bool fin = false); + + ProgressObserverRef _observer; + zypp::ProgressData::ReceiverFnc _fnc; + zypp::callback::SendReport &_report; + bool _first = true; + }; +} + +#endif // ZYPP_NG_PROGRESSOBSERVERADAPTOR_INCLUDED diff --git a/zypp/ng/repo/Downloader b/zypp/ng/repo/Downloader new file mode 100644 index 0000000..fb93454 --- /dev/null +++ b/zypp/ng/repo/Downloader @@ -0,0 +1 @@ +#include "downloader.h" diff --git a/zypp/ng/repo/Refresh b/zypp/ng/repo/Refresh new file mode 100644 index 0000000..e07ab53 --- /dev/null +++ b/zypp/ng/repo/Refresh @@ -0,0 +1 @@ +#include "refresh.h" diff --git a/zypp/ng/repo/downloader.cc b/zypp/ng/repo/downloader.cc new file mode 100644 index 0000000..35b8e0a --- /dev/null +++ b/zypp/ng/repo/downloader.cc @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "downloader.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +namespace zyppng::repo { + + + using namespace zyppng::operators; + + template + DownloadContext::DownloadContext(ContextRefType zyppContext, const zypp::RepoInfo &info, const zypp::Pathname &destDir ) + : CacheProviderContext( typename CacheProviderContext::private_constr_t{}, std::move(zyppContext), destDir ) + , _repoinfo(info) + {} + + template + const zypp::RepoInfo &DownloadContext::repoInfo() const { return _repoinfo; } + + template + const zypp::filesystem::Pathname &DownloadContext::deltaDir() const { return _deltaDir; } + + template + zypp::RepoInfo &DownloadContext::repoInfo() { return _repoinfo; } + + template + std::vector &DownloadContext::files() { return _files; } + + template + const std::optional::PluginRepoverification> &DownloadContext::pluginRepoverification() const + { return _pluginRepoverification; } + + template + void DownloadContext::setDeltaDir(const zypp::Pathname &newDeltaDir) + { _deltaDir = newDeltaDir; } + + // explicitely intantiate the template types we want to work with + template class DownloadContext; + template class DownloadContext; +} diff --git a/zypp/ng/repo/downloader.h b/zypp/ng/repo/downloader.h new file mode 100644 index 0000000..95d4590 --- /dev/null +++ b/zypp/ng/repo/downloader.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_REPO_DOWNLOADER_INCLUDED +#define ZYPP_NG_REPO_DOWNLOADER_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace zyppng { + ZYPP_FWD_DECL_TYPE_WITH_REFS( Context ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( SyncContext ); +} + +namespace zyppng::repo { + template + class DownloadContext : public CacheProviderContext + { + public: + + using PluginRepoverification = zypp_private::repo::PluginRepoverification; + using ContextType = typename ContextRefType::element_type; + using ProvideType = typename ContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + + DownloadContext( ContextRefType zyppContext, const zypp::RepoInfo &info, const zypp::Pathname &destDir ); + + const zypp::RepoInfo &repoInfo () const; + const zypp::Pathname &deltaDir () const; + + zypp::RepoInfo &repoInfo(); + std::vector &files(); + + const std::optional &pluginRepoverification() const; + + void setPluginRepoverification( std::optional pluginRepoverification_r ) + { _pluginRepoverification = std::move(pluginRepoverification_r); } + + void setNoPluginRepoverification() + { setPluginRepoverification( std::nullopt ); } + + void setDeltaDir(const zypp::Pathname &newDeltaDir); + + private: + zypp::RepoInfo _repoinfo; + zypp::Pathname _deltaDir; + std::vector _files; ///< Files downloaded + std::optional _pluginRepoverification; ///< \see \ref plugin-repoverification + }; + + using SyncDownloadContext = DownloadContext; + using AsyncDownloadContext = DownloadContext; + ZYPP_FWD_DECL_REFS(SyncDownloadContext); + ZYPP_FWD_DECL_REFS(AsyncDownloadContext); +} +#endif diff --git a/zypp/ng/repo/refresh.cc b/zypp/ng/repo/refresh.cc new file mode 100644 index 0000000..2555bc7 --- /dev/null +++ b/zypp/ng/repo/refresh.cc @@ -0,0 +1,154 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "refresh.h" +#include +#include +#include +#include +#include + +namespace zyppng::repo { + + template + RefreshContext::RefreshContext( private_constr_t, ZyppContextRefType &&zyppContext, zypp::RepoInfo &&info, zypp::Pathname &&rawCachePath, zypp::filesystem::TmpDir &&tempDir, RepoManagerRef &&repoManager ) + : _zyppContext( std::move(zyppContext) ) + , _repoManager( std::move(repoManager) ) + , _repoInfo( std::move(info) ) + , _rawCachePath( std::move(rawCachePath) ) + , _tmpDir( std::move(tempDir) ) + {} + + template + expected> RefreshContext::create( ZyppContextRefType zyppContext, zypp::RepoInfo info, RepoManagerRef repoManager ) + { + using namespace operators; + using CtxType = RefreshContext; + using CtxRefType = RefreshContextRef; + + return rawcache_path_for_repoinfo ( repoManager->options(), info ) + | and_then( [&]( zypp::Pathname rawCachePath ) { + + zypp::filesystem::TmpDir tmpdir( zypp::filesystem::TmpDir::makeSibling( rawCachePath, 0755 ) ); + if( tmpdir.path().empty() && geteuid() != 0 ) { + tmpdir = zypp::filesystem::TmpDir(); // non-root user may not be able to write the cache + } + if( tmpdir.path().empty() ) { + return expected::error( ZYPP_EXCPT_PTR(zypp::Exception(_("Can't create metadata cache directory."))) ); + } + + MIL << "Creating RefreshContext " << std::endl; + + return expected::success( std::make_shared( private_constr_t{} + , std::move(zyppContext) + , std::move(info) + , std::move(rawCachePath) + , std::move(tmpdir) + , std::move(repoManager))); + } ); + } + + template + RefreshContext::~RefreshContext() + { + MIL << "Deleting RefreshContext" << std::endl; + } + + template + void RefreshContext::saveToRawCache() + { + zypp::filesystem::exchange( _tmpDir.path(), _rawCachePath ); + } + + template + const zypp::Pathname &RefreshContext::rawCachePath() const + { + return _rawCachePath; + } + + template + zypp::Pathname RefreshContext::targetDir() const + { + return _tmpDir.path(); + } + + template + const ZyppContextRefType &RefreshContext::zyppContext() const + { + return _zyppContext; + } + + template + const zypp::RepoInfo &RefreshContext::repoInfo() const + { + return _repoInfo; + } + + template + zypp::RepoInfo &RefreshContext::repoInfo() + { + return _repoInfo; + } + + template + const RepoManagerRef &RefreshContext::repoManager() const + { + return _repoManager; + } + + template + const zypp::RepoManagerOptions &RefreshContext::repoManagerOptions() const + { + return _repoManager->options(); + } + + template + repo::RawMetadataRefreshPolicy RefreshContext::policy() const + { + return _policy; + } + + template + void RefreshContext::setPolicy(RawMetadataRefreshPolicy newPolicy) + { + _policy = newPolicy; + } + + template + const std::optional::PluginRepoverification> &RefreshContext::pluginRepoverification() const + { + return _pluginRepoverification; + } + + template + void RefreshContext::setProbedType(zypp::repo::RepoType rType) + { + if ( _probedType && *_probedType == rType ) + return; + + _probedType = rType; + _sigProbedTypeChanged.emit(rType); + } + + template + const std::optional &RefreshContext::probedType() const + { + return _probedType; + } + + template + SignalProxy RefreshContext::sigProbedTypeChanged() + { + return _sigProbedTypeChanged; + } + + // explicitely intantiate the template types we want to work with + template class RefreshContext; + template class RefreshContext; + +} diff --git a/zypp/ng/repo/refresh.h b/zypp/ng/repo/refresh.h new file mode 100644 index 0000000..650dd3c --- /dev/null +++ b/zypp/ng/repo/refresh.h @@ -0,0 +1,148 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_REPO_REFRESH_INCLUDED +#define ZYPP_NG_REPO_REFRESH_INCLUDED + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace zyppng { + ZYPP_FWD_DECL_TYPE_WITH_REFS( Context ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( SyncContext ); +} + +namespace zyppng::repo { + + ZYPP_FWD_DECL_TEMPL_TYPE_WITH_REFS_ARG1 (RefreshContext, ZyppContextRefType); + + using RawMetadataRefreshPolicy = zypp::RepoManagerFlags::RawMetadataRefreshPolicy; + using RefreshCheckStatus = zypp::RepoManagerFlags::RefreshCheckStatus; + + /*! + * + * Context class for all refresh workflow operations of a repo, operating + * on a local cache and a remote repository, as defined by the \ref zypp::RepoInfo + * + */ + template + class RefreshContext : public Base, public MaybeAsyncMixin< std::is_same_v > { + ZYPP_ADD_PRIVATE_CONSTR_HELPER(); + ZYPP_ENABLE_MAYBE_ASYNC_MIXIN( (std::is_same_v) ); + public: + using ContextRefType = ZyppContextRefType; + using ContextType = typename ZyppContextRefType::element_type; + using ProvideType = typename ContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using PluginRepoverification = zypp_private::repo::PluginRepoverification; + + static expected> create( ZyppContextRefType zyppContext, zypp::RepoInfo info, RepoManagerRef repoManager ); + ZYPP_DECL_PRIVATE_CONSTR_ARGS(RefreshContext, ZyppContextRefType &&zyppContext, zypp::RepoInfo &&info, zypp::Pathname &&rawCachePath, zypp::filesystem::TmpDir &&tempDir, RepoManagerRef &&repoManager ); + + ~RefreshContext() override; + + /*! + * Commits the internal temporary cache into the raw cache + * of the \ref zypp::RepoInfo this context is currently operating + * on. + */ + void saveToRawCache(); + + /*! + * The raw cache path belonging to this context's \ref zypp::RepoInfo + */ + const zypp::Pathname &rawCachePath() const; + + /*! + * The current temporary target dir where the refresh workflow is + * storing the metadata during operation. Once we have a finished + * set of metadata and cache we exchange it with the rawCache + */ + zypp::Pathname targetDir() const; + + /*! + * Current zypp context we are working on, either \ref zyppng::Context + * or \ref zyppng::SyncContext. + */ + const ZyppContextRefType &zyppContext () const; + + /*! + * Current \ref zypp::RepoInfo this refresh context is operating with, + * the workflow is free to change data in this \ref zypp::RepoInfo , so calling + * code should take care to use it once the workflow has finished. + */ + const zypp::RepoInfo &repoInfo () const; + zypp::RepoInfo &repoInfo (); + + /*! + * Reference to the \ref zyppng::RepoManager that initiated the refresh + */ + const RepoManagerRef &repoManager() const; + const zypp::RepoManagerOptions &repoManagerOptions() const; + + /*! + * The refresh policy, defines wether a refresh is forced, or only done if needed. + */ + RawMetadataRefreshPolicy policy() const; + void setPolicy(RawMetadataRefreshPolicy newPolicy); + + /*! + * Optional repo verification via a plugin + */ + const std::optional &pluginRepoverification() const; + + void setPluginRepoverification( std::optional pluginRepoverification_r ) + { _pluginRepoverification = std::move(pluginRepoverification_r); } + + /*! + * Disabled plugin based repo verification + */ + void setNoPluginRepoverification() + { setPluginRepoverification( std::nullopt ); } + + /*! + * Updated the probed repo type in \ref zypp::RepoInfo, calling code should + * take care to fetch the updated one at the end of the refresh workflow. + */ + void setProbedType( zypp::repo::RepoType rType ); + const std::optional &probedType() const; + SignalProxy sigProbedTypeChanged(); + + private: + ZyppContextRefType _zyppContext; + RepoManagerRef _repoManager; + zypp::RepoInfo _repoInfo; + zypp::Pathname _rawCachePath; + zypp::filesystem::TmpDir _tmpDir; + repo::RawMetadataRefreshPolicy _policy = RawMetadataRefreshPolicy::RefreshIfNeeded; + std::optional _pluginRepoverification; ///< \see \ref plugin-repoverification + + std::optional _probedType; + Signal _sigProbedTypeChanged; + + }; + + using SyncRefreshContext = RefreshContext; + using AsyncRefreshContext = RefreshContext; + ZYPP_FWD_DECL_REFS(SyncRefreshContext); + ZYPP_FWD_DECL_REFS(AsyncRefreshContext); + +} + + + +#endif diff --git a/zypp/ng/repo/workflows/plaindir.cc b/zypp/ng/repo/workflows/plaindir.cc new file mode 100644 index 0000000..5482833 --- /dev/null +++ b/zypp/ng/repo/workflows/plaindir.cc @@ -0,0 +1,98 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "plaindir.h" + +#include +#include +#include + +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +namespace zyppng::PlaindirWorkflows { + + namespace { + template + auto statusLogic( DlContextRefType &&ctx, MediaHandle mediaHandle ) { + constexpr bool isAsync = std::is_same_v; + + // this can only happen if this function is called with a non mounting medium, but those do not support plaindir anyway + if ( !mediaHandle.localPath().has_value() ) { + return makeReadyResult, isAsync>( expected::error( ZYPP_EXCPT_PTR( zypp::Exception("Medium does not support plaindir") )) ); + } + + // dir status + const auto &repoInfo = std::forward(ctx)->repoInfo(); + auto rStatus = zypp::RepoStatus( repoInfo ) && zypp::RepoStatus( mediaHandle.localPath().value() / repoInfo.path() ); + return makeReadyResult, isAsync> ( expected::success(std::move(rStatus)) ); + } + } + + AsyncOpRef > repoStatus(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle) + { + return statusLogic( std::move(dl), std::move(mediaHandle) ); + } + + expected repoStatus(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle) + { + return statusLogic( std::move(dl), std::move(mediaHandle) ); + } + + + namespace { + template + auto dlLogic( DlContextRefType &&ctx, MediaHandle mediaHandle, ProgressObserverRef progressObserver ) { + + constexpr bool isAsync = std::is_same_v; + using Ret = expected; + + try { + // this can only happen if this function is called with a non mounting medium, but those do not support plaindir anyway + if ( !mediaHandle.localPath().has_value() ) { + return makeReadyResult( Ret::error( ZYPP_EXCPT_PTR( zypp::Exception("Medium does not support plaindir") )) ); + } + + if ( progressObserver ) progressObserver->inc(); + + // as substitute for real metadata remember the checksum of the directory we refreshed + const auto &repoInfo = std::forward(ctx)->repoInfo(); + auto newstatus = zypp::RepoStatus( mediaHandle.localPath().value() / repoInfo.path() ); // dir status + + zypp::Pathname productpath( std::forward(ctx)->destDir() / repoInfo.path() ); + zypp::filesystem::assert_dir( productpath ); + newstatus.saveToCookieFile( productpath/"cookie" ); + + if ( progressObserver ) progressObserver->setFinished(); + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + return makeReadyResult( Ret::error( ZYPP_FWD_CURRENT_EXCPT() ) ); + } catch ( ... ) { + return makeReadyResult( Ret::error( ZYPP_FWD_CURRENT_EXCPT() ) ); + } + return makeReadyResult( Ret::success( std::forward(ctx) ) ); + } + } + + AsyncOpRef > download(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return dlLogic( std::move(dl), std::move(mediaHandle), std::move(progressObserver) ); + } + + expected download(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return dlLogic( std::move(dl), std::move(mediaHandle), std::move(progressObserver) ); + } + +} diff --git a/zypp/ng/repo/workflows/plaindir.h b/zypp/ng/repo/workflows/plaindir.h new file mode 100644 index 0000000..2ea7f78 --- /dev/null +++ b/zypp/ng/repo/workflows/plaindir.h @@ -0,0 +1,37 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_PLAINDIR_WORKFLOW_INCLUDED +#define ZYPP_NG_PLAINDIR_WORKFLOW_INCLUDED + +#include +#include +#include +#include + +#include + + +namespace zyppng { + class ProvideMediaHandle; + class SyncMediaHandle; + + ZYPP_FWD_DECL_TYPE_WITH_REFS( ProgressObserver ); + + namespace PlaindirWorkflows { + AsyncOpRef> repoStatus( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle ); + expected repoStatus( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle ); + + AsyncOpRef> download ( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + expected download ( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + } +} + + + +#endif // ZYPP_NG_PLAINDIR_WORKFLOW_INCLUDED diff --git a/zypp/ng/repo/workflows/repodownloaderwf.cc b/zypp/ng/repo/workflows/repodownloaderwf.cc new file mode 100644 index 0000000..31e61f8 --- /dev/null +++ b/zypp/ng/repo/workflows/repodownloaderwf.cc @@ -0,0 +1,419 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "repodownloaderwf.h" +#include +#include "zypp/parser/yum/RepomdFileReader.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// sync workflow helpers +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +namespace zyppng { + namespace { + + using namespace zyppng::operators; + + template < class Executor, class OpType > + struct DownloadMasterIndexLogic : public LogicBase + { + public: + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + using DlContextRefType = std::conditional_t, repo::AsyncDownloadContextRef, repo::SyncDownloadContextRef>; + using ZyppContextType = typename remove_smart_ptr_t::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + DownloadMasterIndexLogic( DlContextRefType &&ctxRef, MediaHandle &&mediaHandle, zypp::filesystem::Pathname &&masterIndex_r ) + : _dlContext( std::move(ctxRef) ) + , _media(std::move( mediaHandle )) + , _masterIndex(std::move( masterIndex_r )) + { } + + public: + MaybeAsyncRef> execute( ) { + // always download them, even if repoGpgCheck is disabled + _sigpath = _masterIndex.extend( ".asc" ); + _keypath = _masterIndex.extend( ".key" ); + _destdir = _dlContext->destDir(); + + auto providerRef = _dlContext->zyppContext()->provider(); + return std::vector { + // fetch signature and keys + providerRef->provide( _media, _sigpath, ProvideFileSpec().setOptional( true ).setDownloadSize( zypp::ByteCount( 20, zypp::ByteCount::MB ) ) ) + | and_then( ProvideType::copyResultToDest ( providerRef, _destdir / _sigpath ) ), + providerRef->provide( _media, _keypath, ProvideFileSpec().setOptional( true ).setDownloadSize( zypp::ByteCount( 20, zypp::ByteCount::MB ) ) ) + | and_then( ProvideType::copyResultToDest ( providerRef, _destdir / _keypath ) ), + } + | join() + | [this]( std::vector> &&res ) { + + // remember downloaded files + std::for_each( res.begin (), res.end(), + [this]( expected &f){ + if (f.is_valid () ) { + _dlContext->files().push_back( std::move(f.get())); + } + }); + + // get the master index file + return provider()->provide( _media, _masterIndex, ProvideFileSpec().setDownloadSize( zypp::ByteCount( 20, zypp::ByteCount::MB ) ) ); + } + // execute plugin verification if there is one + | and_then( std::bind( &DownloadMasterIndexLogic::pluginVerification, this, std::placeholders::_1 ) ) + + // signature checking + | and_then( std::bind( &DownloadMasterIndexLogic::signatureCheck, this, std::placeholders::_1 ) ) + + // copy everything into a directory + | and_then( ProvideType::copyResultToDest ( providerRef, _destdir / _masterIndex ) ) + + // final tasks + | and_then([this]( zypp::ManagedFile &&masterIndex ) { + // Accepted! + _dlContext->repoInfo().setMetadataPath( _destdir ); + _dlContext->repoInfo().setValidRepoSignature( _repoSigValidated ); + + // release the media handle + _media = MediaHandle(); + auto &allFiles = _dlContext->files(); + + // make sure the masterIndex is in front + allFiles.insert( allFiles.begin (), std::move(masterIndex) ); + return make_expected_success( std::move(_dlContext) ); + }); + } + + + private: + auto provider () { + return _dlContext->zyppContext()->provider(); + } + + MaybeAsyncRef> signatureCheck ( ProvideRes &&res ) { + + if ( _dlContext->repoInfo().repoGpgCheck() ) { + + // The local files are in destdir_r, if they were present on the server + zypp::Pathname sigpathLocal { _destdir/_sigpath }; + zypp::Pathname keypathLocal { _destdir/_keypath }; + bool isSigned = zypp::PathInfo(sigpathLocal).isExist(); + + if ( isSigned || _dlContext->repoInfo().repoGpgCheckIsMandatory() ) { + + auto verifyCtx = zypp::keyring::VerifyFileContext( res.file() ); + + // only add the signature if it exists + if ( isSigned ) + verifyCtx.signature( sigpathLocal ); + + // only add the key if it exists + if ( zypp::PathInfo(keypathLocal).isExist() ) { + try { + _dlContext->zyppContext()->keyRing()->importKey( zypp::PublicKey(keypathLocal), false ); + } catch (...) { + return makeReadyResult( expected::error( ZYPP_FWD_CURRENT_EXCPT() ) ); + } + } + + // set the checker context even if the key is not known + // (unsigned repo, key file missing; bnc #495977) + verifyCtx.keyContext( _dlContext->repoInfo() ); + + return getExtraKeysInRepomd( std::move(res ) ) + | and_then([this, vCtx = std::move(verifyCtx) ]( ProvideRes &&res ) mutable { + for ( const auto &keyData : _buddyKeys ) { + DBG << "Keyhint remember buddy " << keyData << std::endl; + vCtx.addBuddyKey( keyData.id() ); + } + + return SignatureFileCheckWorkflow::verifySignature( _dlContext->zyppContext(), std::move(vCtx)) + | and_then([ this, res = std::move(res) ]( zypp::keyring::VerifyFileContext verRes ){ + // remember the validation status + _repoSigValidated = verRes.fileValidated(); + return make_expected_success(std::move(res)); + }); + }); + + } else { + WAR << "Accept unsigned repository because repoGpgCheck is not mandatory for " << _dlContext->repoInfo().alias() << std::endl; + } + } else { + WAR << "Signature checking disabled in config of repository " << _dlContext->repoInfo().alias() << std::endl; + } + return makeReadyResult(expected::success(res)); + } + + // execute the repo verification if there is one + expected pluginVerification ( ProvideRes &&prevRes ) { + // The local files are in destdir_r, if they were present on the server + zypp::Pathname sigpathLocal { _destdir/_sigpath }; + zypp::Pathname keypathLocal { _destdir/_keypath }; + if ( _dlContext->pluginRepoverification() && _dlContext->pluginRepoverification()->isNeeded() ) { + try { + _dlContext->pluginRepoverification()->getChecker( sigpathLocal, keypathLocal, _dlContext->repoInfo() )( prevRes.file() ); + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + } + return make_expected_success(std::move(prevRes)); + } + + /*! + * Returns a sync or async expected result depending on the + * implementation class. + */ + MaybeAsyncRef> getExtraKeysInRepomd ( ProvideRes &&res ) { + + if ( _masterIndex.basename() != "repomd.xml" ) { + return makeReadyResult( expected::success( std::move(res) ) ); + } + + std::vector> keyhints { zypp::parser::yum::RepomdFileReader(res.file()).keyhints() }; + if ( keyhints.empty() ) + return makeReadyResult( expected::success( std::move(res) ) ); + DBG << "Check keyhints: " << keyhints.size() << std::endl; + + auto keyRing { _dlContext->zyppContext()->keyRing() }; + return zypp::parser::yum::RepomdFileReader(res.file()).keyhints() + | transform([this, keyRing]( std::pair val ) { + + const auto& [ file, keyid ] = val; + auto keyData = keyRing->trustedPublicKeyData( keyid ); + if ( keyData ) { + DBG << "Keyhint is already trusted: " << keyid << " (" << file << ")" << std::endl; + return makeReadyResult ( expected::success(keyData) ); // already a trusted key + } + + DBG << "Keyhint search key " << keyid << " (" << file << ")" << std::endl; + + keyData = keyRing->publicKeyData( keyid ); + if ( keyData ) + return makeReadyResult( expected::success(keyData) ); + + // TODO: Enhance the key caching in general... + const zypp::ZConfig & conf = _dlContext->zyppContext()->config(); + zypp::Pathname cacheFile = conf.repoManagerRoot() / conf.pubkeyCachePath() / file; + + return zypp::PublicKey::noThrow(cacheFile) + | [ keyid = keyid ]( auto &&key ){ + if ( key.fileProvidesKey( keyid ) ) + return make_expected_success( std::forward(key) ); + else + return expected::error( std::make_exception_ptr (zypp::Exception("File does not provide key"))); + } + | or_else ([ this, file = file, keyid = keyid, cacheFile ] ( auto ) mutable -> MaybeAsyncRef> { + auto providerRef = _dlContext->zyppContext()->provider(); + return providerRef->provide( _media, file, ProvideFileSpec().setOptional(true) ) + | and_then( ProvideType::copyResultToDest( providerRef, _destdir / file ) ) + | and_then( [this, providerRef, file, keyid , cacheFile = std::move(cacheFile)]( zypp::ManagedFile &&res ) { + + // remember we downloaded the file + _dlContext->files().push_back ( std::move(res) ); + + auto key = zypp::PublicKey::noThrow( _dlContext->files().back() ); + if ( not key.fileProvidesKey( keyid ) ) { + const auto &str = zypp::str::Str() << "Keyhint " << file << " does not contain a key with id " << keyid << ". Skipping it."; + WAR << str << std::endl; + return makeReadyResult(expected::error( std::make_exception_ptr( zypp::Exception(str)) )); + } + + // Try to cache it... + zypp::filesystem::assert_dir( cacheFile.dirname() ); + return providerRef->copyFile( key.path(), cacheFile ) + | [ key ]( expected res ) mutable { + if ( res ) { + // do not delete from cache + res->resetDispose (); + } + return expected::success( std::move(key) ); + }; + }); + }) + | and_then( [ keyRing, keyid = keyid ]( zypp::PublicKey key ){ + keyRing->importKey( key, false ); // store in general keyring (not trusted!) + return expected::success(keyRing->publicKeyData( keyid )); // fetch back from keyring in case it was a hidden key + }); + }) + | [this, res = res] ( std::vector> &&keyHints ) mutable { + std::for_each( keyHints.begin(), keyHints.end(), [this]( expected &keyData ){ + if ( keyData && *keyData ) { + if ( not zypp::PublicKey::isSafeKeyId( keyData->id() ) ) { + WAR << "Keyhint " << keyData->id() << " for " << *keyData << " is not strong enough for auto import. Just caching it." << std::endl; + return; + } + _buddyKeys.push_back ( std::move(keyData.get()) ); + } + }); + + MIL << "Check keyhints done. Buddy keys: " << _buddyKeys.size() << std::endl; + return expected::success (std::move(res)); + }; + } + + DlContextRefType _dlContext; + MediaHandle _media; + zypp::Pathname _masterIndex; + + zypp::Pathname _destdir; + zypp::Pathname _sigpath; + zypp::Pathname _keypath; + zypp::TriBool _repoSigValidated = zypp::indeterminate; + + std::vector _buddyKeys; + }; + + } + + AsyncOpRef > RepoDownloaderWorkflow::downloadMasterIndex(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, zypp::Pathname masterIndex_r) + { + return SimpleExecutor>>::run( std::move(dl), std::move(mediaHandle), std::move(masterIndex_r) ); + } + + expected RepoDownloaderWorkflow::downloadMasterIndex(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, zypp::Pathname masterIndex_r) + { + return SimpleExecutor>>::run( std::move(dl), std::move(mediaHandle), std::move(masterIndex_r) ); + } + + AsyncOpRef> RepoDownloaderWorkflow::downloadMasterIndex ( repo::AsyncDownloadContextRef dl, AsyncLazyMediaHandle mediaHandle, zypp::filesystem::Pathname masterIndex_r ) + { + using namespace zyppng::operators; + return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle ) + | and_then([ dl, mi = std::move(masterIndex_r) ]( ProvideMediaHandle handle ) mutable { + return downloadMasterIndex( std::move(dl), std::move(handle), std::move(mi) ); + }); + } + + expected RepoDownloaderWorkflow::downloadMasterIndex ( repo::SyncDownloadContextRef dl, SyncLazyMediaHandle mediaHandle, zypp::filesystem::Pathname masterIndex_r ) + { + using namespace zyppng::operators; + return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle ) + | and_then([ dl, mi = std::move(masterIndex_r) ]( SyncMediaHandle handle ) mutable { + return downloadMasterIndex( std::move(dl), std::move(handle), std::move(mi) ); + }); + } + + + namespace { + template + auto statusImpl ( DlContextRefType dlCtx, MediaHandleType &&mediaHandle ) { + + constexpr bool isAsync = std::is_same_v; + + const auto finalizeStatus = [ dlCtx ]( zypp::RepoStatus status ){ + return expected::success( zypp::RepoStatus( dlCtx->repoInfo()) && status ); + }; + + switch( dlCtx->repoInfo().type().toEnum()) { + case zypp::repo::RepoType::RPMMD_e: + return RpmmdWorkflows::repoStatus( dlCtx, std::forward(mediaHandle) ) | and_then( std::move(finalizeStatus) ); + case zypp::repo::RepoType::YAST2_e: + return SuseTagsWorkflows::repoStatus( dlCtx, std::forward(mediaHandle) ) | and_then( std::move(finalizeStatus) ); + case zypp::repo::RepoType::RPMPLAINDIR_e: + return PlaindirWorkflows::repoStatus ( dlCtx, std::forward(mediaHandle) ) | and_then( std::move(finalizeStatus) ); + case zypp::repo::RepoType::NONE_e: + break; + } + + return makeReadyResult, isAsync >( expected::error( ZYPP_EXCPT_PTR (zypp::repo::RepoUnknownTypeException(dlCtx->repoInfo()))) ); + } + } + + AsyncOpRef > RepoDownloaderWorkflow::repoStatus(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle) { + return statusImpl( dl, std::move(mediaHandle) ); + } + + expected RepoDownloaderWorkflow::repoStatus(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle) { + return statusImpl( dl, std::move(mediaHandle) ); + } + + AsyncOpRef > RepoDownloaderWorkflow::repoStatus( repo::AsyncDownloadContextRef dl, AsyncLazyMediaHandle mediaHandle ) { + using namespace zyppng::operators; + return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle ) + | and_then([ dl ]( ProvideMediaHandle handle ) { + return repoStatus( dl, std::move(handle) ); + }); + } + + expected RepoDownloaderWorkflow::repoStatus( repo::SyncDownloadContextRef dl, SyncLazyMediaHandle mediaHandle ) { + using namespace zyppng::operators; + return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle ) + | and_then([ dl ]( SyncMediaHandle handle ) { + return repoStatus( dl, std::move(handle) ); + }); + } + + + namespace { + template + auto downloadImpl ( DlContextRefType dlCtx, MediaHandleType &&mediaHandle, ProgressObserverRef &&progressObserver ) { + + constexpr bool isAsync = std::is_same_v; + + switch( dlCtx->repoInfo().type().toEnum()) { + case zypp::repo::RepoType::RPMMD_e: + return RpmmdWorkflows::download( std::move(dlCtx), std::forward(mediaHandle), std::move(progressObserver) ); + case zypp::repo::RepoType::YAST2_e: + return SuseTagsWorkflows::download( std::move(dlCtx), std::forward(mediaHandle), std::move(progressObserver) ); + case zypp::repo::RepoType::RPMPLAINDIR_e: + return PlaindirWorkflows::download ( std::move(dlCtx), std::forward(mediaHandle) ); + case zypp::repo::RepoType::NONE_e: + break; + } + + return makeReadyResult, isAsync >( expected::error( ZYPP_EXCPT_PTR (zypp::repo::RepoUnknownTypeException(dlCtx->repoInfo()))) ); + } + } + + AsyncOpRef > RepoDownloaderWorkflow::download(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return downloadImpl( dl, std::move(mediaHandle), std::move(progressObserver) ); + } + + expected RepoDownloaderWorkflow::download(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return downloadImpl( dl, std::move(mediaHandle), std::move(progressObserver) ); + } + + AsyncOpRef > RepoDownloaderWorkflow::download(repo::AsyncDownloadContextRef dl, AsyncLazyMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + using namespace zyppng::operators; + return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle ) + | and_then([ dl, po = std::move(progressObserver) ]( ProvideMediaHandle handle ) mutable { + return downloadImpl( dl, std::move(handle), std::move(po) ); + }); + } + + expected RepoDownloaderWorkflow::download(repo::SyncDownloadContextRef dl, SyncLazyMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + using namespace zyppng::operators; + return dl->zyppContext()->provider()->attachMediaIfNeeded( mediaHandle ) + | and_then([ dl, po = std::move(progressObserver) ]( SyncMediaHandle handle ) mutable { + return downloadImpl( dl, std::move(handle), std::move(po) ); + }); + } + +} diff --git a/zypp/ng/repo/workflows/repodownloaderwf.h b/zypp/ng/repo/workflows/repodownloaderwf.h new file mode 100644 index 0000000..d41ca71 --- /dev/null +++ b/zypp/ng/repo/workflows/repodownloaderwf.h @@ -0,0 +1,71 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_REPODOWNLOADER_WORKFLOW_INCLUDED +#define ZYPP_NG_REPODOWNLOADER_WORKFLOW_INCLUDED + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace zyppng { + + class Provide; + class MediaSyncFacade; + + class ProvideMediaHandle; + class SyncMediaHandle; + + using AsyncLazyMediaHandle = LazyMediaHandle; + using SyncLazyMediaHandle = LazyMediaHandle; + + namespace RepoDownloaderWorkflow { + AsyncOpRef> downloadMasterIndex ( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, zypp::filesystem::Pathname masterIndex_r ); + AsyncOpRef> downloadMasterIndex ( repo::AsyncDownloadContextRef dl, AsyncLazyMediaHandle mediaHandle, zypp::filesystem::Pathname masterIndex_r ); + expected downloadMasterIndex ( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, zypp::filesystem::Pathname masterIndex_r ); + expected downloadMasterIndex ( repo::SyncDownloadContextRef dl, SyncLazyMediaHandle mediaHandle, zypp::filesystem::Pathname masterIndex_r ); + + AsyncOpRef> repoStatus( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle ); + AsyncOpRef > repoStatus( repo::AsyncDownloadContextRef dl, AsyncLazyMediaHandle mediaHandle ); + expected repoStatus( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle ); + expected repoStatus( repo::SyncDownloadContextRef dl, SyncLazyMediaHandle mediaHandle ); + + AsyncOpRef> download ( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + AsyncOpRef > download(repo::AsyncDownloadContextRef dl, AsyncLazyMediaHandle mediaHandle, ProgressObserverRef progressObserver); + expected download ( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + expected download(repo::SyncDownloadContextRef dl, SyncLazyMediaHandle mediaHandle, ProgressObserverRef progressObserver); + + template + auto downloadMediaInfo ( MediaHandle &&mediaHandle, const zypp::filesystem::Pathname &destdir ) { + using namespace zyppng::operators; + using ProvideType = typename std::decay_t::ParentType; + + // check if we have a async media handle + constexpr bool isAsync = std::is_same_v; + auto provider = mediaHandle.parent(); + if ( !provider ) + return makeReadyResult, isAsync>( expected::error(ZYPP_EXCPT_PTR(zypp::media::MediaException("Invalid handle"))) ); + + return provider->provide( std::forward(mediaHandle), "/media.1/media", ProvideFileSpec().setOptional(true).setDownloadSize( zypp::ByteCount(20, zypp::ByteCount::MB ) )) + | and_then( ProvideType::copyResultToDest( provider, destdir / "/media.1/media" ) ); + + } + } +} + + +#endif diff --git a/zypp/ng/repo/workflows/repomanagerwf.cc b/zypp/ng/repo/workflows/repomanagerwf.cc new file mode 100644 index 0000000..54deb93 --- /dev/null +++ b/zypp/ng/repo/workflows/repomanagerwf.cc @@ -0,0 +1,1211 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "repomanagerwf.h" + +#include "zypp/parser/xml/Reader.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +namespace zyppng::RepoManagerWorkflow { + + using namespace zyppng::operators; + + namespace { + + template + struct ProbeRepoLogic : public LogicBase + { + protected: + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + using ZyppContextRefType = std::conditional_t, ContextRef, SyncContextRef >; + using ProvideType = typename remove_smart_ptr_t::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using LazyMediaHandle = typename ProvideType::LazyMediaHandle; + using ProvideRes = typename ProvideType::Res; + + ProbeRepoLogic(ZyppContextRefType zyppCtx, LazyMediaHandle &&medium, zypp::Pathname &&path, std::optional &&targetPath ) + : _zyppContext(std::move(zyppCtx)) + , _medium(std::move(medium)) + , _path(std::move(path)) + , _targetPath(std::move(targetPath)) + {} + + MaybeAsyncRef> execute( ) { + const auto &url = _medium.baseUrl(); + MIL << "going to probe the repo type at " << url << " (" << _path << ")" << std::endl; + + if ( url.getScheme() == "dir" && ! zypp::PathInfo( url.getPathName()/_path ).isDir() ) { + // Handle non existing local directory in advance + MIL << "Probed type NONE (not exists) at " << url << " (" << _path << ")" << std::endl; + return makeReadyResult(expected::success(zypp::repo::RepoType::NONE)); + } + + // prepare exception to be thrown if the type could not be determined + // due to a media exception. We can't throw right away, because of some + // problems with proxy servers returning an incorrect error + // on ftp file-not-found(bnc #335906). Instead we'll check another types + // before throwing. + + std::shared_ptr providerRef = _zyppContext->provider(); + + // TranslatorExplanation '%s' is an URL + _error = zypp::repo::RepoException (zypp::str::form( _("Error trying to read from '%s'"), url.asString().c_str() )); + + return providerRef->attachMediaIfNeeded( _medium ) + | and_then([this, providerRef]( MediaHandle medium ) + { + // first try rpmmd + return providerRef->provide( medium, _path/"repodata/repomd.xml", ProvideFileSpec().setCheckExistsOnly( !_targetPath.has_value() ) ) + | and_then( maybeCopyResultToDest("repodata/repomd.xml") ) + | and_then( [](){ return expected::success(zypp::repo::RepoType::RPMMD); } ) + // try susetags if rpmmd fails and remember the error + | or_else( [this, providerRef, medium]( std::exception_ptr err ) { + try { + std::rethrow_exception (err); + } catch ( const zypp::media::MediaFileNotFoundException &e ) { + // do nothing + ; + } catch( const zypp::media::MediaException &e ) { + DBG << "problem checking for repodata/repomd.xml file" << std::endl; + _error.remember ( err ); + _gotMediaError = true; + } catch( ... ) { + // any other error, we give up + return makeReadyResult( expected::error( ZYPP_FWD_CURRENT_EXCPT() ) ); + } + return providerRef->provide( medium, _path/"content", ProvideFileSpec().setCheckExistsOnly( !_targetPath.has_value() ) ) + | and_then( maybeCopyResultToDest("content") ) + | and_then( []()->expected{ return expected::success(zypp::repo::RepoType::YAST2); } ); + }) + // no rpmmd and no susetags! + | or_else( [this, medium]( std::exception_ptr err ) { + + try { + std::rethrow_exception (err); + } catch ( const zypp::media::MediaFileNotFoundException &e ) { + // do nothing + ; + } catch( const zypp::media::MediaException &e ) { + DBG << "problem checking for content file" << std::endl; + _error.remember ( err ); + _gotMediaError = true; + } catch( zypp::Exception &e ) { + _error.remember(e); + // any other error, we give up + return expected::error( ZYPP_EXCPT_PTR(_error) ); + } catch(...) { + // any other error, we give up + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + + const auto &url = medium.baseUrl(); + + // if it is a non-downloading URL denoting a directory (bsc#1191286: and no plugin) + if ( ! ( url.schemeIsDownloading() || url.schemeIsPlugin() ) ) { + + if ( medium.localPath() && zypp::PathInfo(medium.localPath().value()/_path).isDir() ) { + // allow empty dirs for now + MIL << "Probed type RPMPLAINDIR at " << url << " (" << _path << ")" << std::endl; + return expected::success(zypp::repo::RepoType::RPMPLAINDIR); + } + } + + if( _gotMediaError ) + return expected::error( ZYPP_EXCPT_PTR( _error )); + + MIL << "Probed type NONE at " << url << " (" << _path << ")" << std::endl; + return expected::success(zypp::repo::RepoType::NONE); + }) + ; + }); + } + + private: + /** + * creates a callback that copies the downloaded file into the target directory if it was given. + * \returns expected::success() if everything worked out + */ + auto maybeCopyResultToDest ( std::string &&subPath ) { + return [this, subPath = std::move(subPath)]( ProvideRes file ) -> MaybeAsyncRef> { + if ( _targetPath ) { + MIL << "Target path is set, copying " << file.file() << " to " << *_targetPath/subPath << std::endl; + return std::move(file) + | ProvideType::copyResultToDest( _zyppContext->provider(), *_targetPath/subPath) + | and_then([]( zypp::ManagedFile file ){ file.resetDispose(); return expected::success(); } ); + } + return makeReadyResult( expected::success() ); + }; + } + + private: + ZyppContextRefType _zyppContext; + LazyMediaHandle _medium; + zypp::Pathname _path; + std::optional _targetPath; + + zypp::repo::RepoException _error; + bool _gotMediaError = false; + }; + + template + auto probeRepoLogic( RefreshContextRef ctx, RepoInfo repo, std::optional targetPath) + { + using namespace zyppng::operators; + return ctx->provider()->prepareMedia( repo.url(), zyppng::ProvideMediaSpec() ) + | and_then( [ctx, path = repo.path() ]( auto &&mediaHandle ) { + return probeRepoType( ctx, std::forward(mediaHandle), path ); + }); + } + } + + AsyncOpRef > probeRepoType(ContextRef ctx, AsyncLazyMediaHandle medium, zypp::Pathname path, std::optional targetPath) + { + return SimpleExecutor< ProbeRepoLogic, AsyncOp> >::run( std::move(ctx), std::move(medium), std::move(path), std::move(targetPath) ); + } + + expected probeRepoType(SyncContextRef ctx, SyncLazyMediaHandle medium, zypp::Pathname path, std::optional targetPath ) + { + return SimpleExecutor< ProbeRepoLogic, SyncOp> >::run( std::move(ctx), std::move(medium), std::move(path), std::move(targetPath) ); + } + + AsyncOpRef > probeRepoType( ContextRef ctx, RepoInfo repo, std::optional targetPath ) + { + return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) ); + } + + expected probeRepoType ( SyncContextRef ctx, RepoInfo repo, std::optional targetPath ) + { + return probeRepoLogic( std::move(ctx), std::move(repo), std::move(targetPath) ); + } + + + namespace { + template + auto readRepoFileLogic( ZyppContextRef ctx, zypp::Url repoFileUrl ) + { + using namespace zyppng::operators; + return ctx->provider()->provide( repoFileUrl, ProvideFileSpec() ) + | and_then([repoFileUrl]( auto local ){ + DBG << "reading repo file " << repoFileUrl << ", local path: " << local.file() << std::endl; + return repositories_in_file( local.file() ); + }); + } + } + + AsyncOpRef > > readRepoFile(ContextRef ctx, zypp::Url repoFileUrl) + { + return readRepoFileLogic( std::move(ctx), std::move(repoFileUrl) ); + } + + expected > readRepoFile(SyncContextRef ctx, zypp::Url repoFileUrl) + { + return readRepoFileLogic( std::move(ctx), std::move(repoFileUrl) ); + } + + namespace { + + template + struct CheckIfToRefreshMetadataLogic : public LogicBase { + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + public: + + using RefreshContextRefType = std::conditional_t, repo::AsyncRefreshContextRef, repo::SyncRefreshContextRef>; + using ZyppContextRefType = typename RefreshContextRefType::element_type::ContextRefType; + using ZyppContextType = typename RefreshContextRefType::element_type::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using LazyMediaHandle = typename ProvideType::LazyMediaHandle; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + CheckIfToRefreshMetadataLogic( RefreshContextRefType refCtx, LazyMediaHandle &&medium, ProgressObserverRef progressObserver ) + : _refreshContext(std::move(refCtx)) + , _progress(std::move( progressObserver )) + , _medium(std::move( medium )) + {} + + MaybeAsyncRef> execute( ) { + + MIL << "Going to CheckIfToRefreshMetadata" << std::endl; + + return assert_alias( _refreshContext->repoInfo() ) + | and_then( [this] { + + const auto &info = _refreshContext->repoInfo(); + MIL << "Check if to refresh repo " << _refreshContext->repoInfo().alias() << " at " << _medium.baseUrl() << " (" << info.type() << ")" << std::endl; + + // first check old (cached) metadata + return zyppng::RepoManager::metadataStatus( info, _refreshContext->repoManagerOptions() ); + }) + | and_then( [this](zypp::RepoStatus oldstatus) { + + const auto &info = _refreshContext->repoInfo(); + + if ( oldstatus.empty() ) { + MIL << "No cached metadata, going to refresh" << std::endl; + return makeReadyResult( expected::success(zypp::RepoManagerFlags::REFRESH_NEEDED) ); + } + + if ( _medium.baseUrl().schemeIsVolatile() ) { + MIL << "Never refresh CD/DVD" << std::endl; + return makeReadyResult( expected::success(zypp::RepoManagerFlags::REPO_UP_TO_DATE) ); + } + + if ( _refreshContext->policy() == zypp::RepoManagerFlags::RefreshForced ) { + MIL << "Forced refresh!" << std::endl; + return makeReadyResult( expected::success(zypp::RepoManagerFlags::REFRESH_NEEDED) ); + } + + if ( _medium.baseUrl().schemeIsLocal() ) { + _refreshContext->setPolicy( zypp::RepoManagerFlags::RefreshIfNeededIgnoreDelay ); + } + + // Check whether repo.refresh.delay applies... + if ( _refreshContext->policy() != zypp::RepoManagerFlags::RefreshIfNeededIgnoreDelay ) + { + // bsc#1174016: Prerequisite to skipping the refresh is that metadata + // and solv cache status match. They will not, if the repos URL was + // changed e.g. due to changed repovars. + expected cachestatus = zyppng::RepoManager::cacheStatus( info, _refreshContext->repoManagerOptions() ); + if ( !cachestatus ) return makeReadyResult( expected::error(cachestatus.error()) ); + + if ( oldstatus == *cachestatus ) { + // difference in seconds + double diff = ::difftime( (zypp::Date::ValueType)zypp::Date::now(), (zypp::Date::ValueType)oldstatus.timestamp() ) / 60; + const auto refDelay = _refreshContext->zyppContext()->config().repo_refresh_delay(); + if ( diff < refDelay ) { + if ( diff < 0 ) { + WAR << "Repository '" << info.alias() << "' was refreshed in the future!" << std::endl; + } + else { + MIL << "Repository '" << info.alias() + << "' has been refreshed less than repo.refresh.delay (" + << refDelay + << ") minutes ago. Advising to skip refresh" << std::endl; + return makeReadyResult( expected::success(zypp::RepoManagerFlags::REPO_CHECK_DELAYED) ); + } + } + } + else { + MIL << "Metadata and solv cache don't match. Check data on server..." << std::endl; + } + } + + return info.type() | [this]( zypp::repo::RepoType repokind ) { + // if unknown: probe it + if ( repokind == zypp::repo::RepoType::NONE ) + return probeRepoType( _refreshContext->zyppContext(), _medium, _refreshContext->repoInfo().path()/*, _refreshContext->targetDir()*/ ); + return makeReadyResult( expected::success(repokind) ); + } | and_then([this, oldstatus]( zypp::repo::RepoType repokind ) { + + // make sure to remember the repo type + _refreshContext->repoInfo().setProbedType( repokind ); + + auto dlContext = std::make_shared>( _refreshContext->zyppContext(), _refreshContext->repoInfo(), _refreshContext->targetDir() ); + return RepoDownloaderWorkflow::repoStatus ( dlContext, _medium ) + | and_then( [this, dlContext, oldstatus]( zypp::RepoStatus newstatus ){ + // check status + if ( oldstatus == newstatus ) { + MIL << "repo has not changed" << std::endl; + return zyppng::RepoManager::touchIndexFile( _refreshContext->repoInfo(), _refreshContext->repoManagerOptions() ) + | and_then([](){ return expected::success(zypp::RepoManagerFlags::REPO_UP_TO_DATE); }); + } + else { // includes newstatus.empty() if e.g. repo format changed + MIL << "repo has changed, going to refresh" << std::endl; + MIL << "Old status: " << oldstatus << " New Status: " << newstatus << std::endl; + return expected::success(zypp::RepoManagerFlags::REFRESH_NEEDED); + } + }); + }); + }); + } + + protected: + RefreshContextRefType _refreshContext; + ProgressObserverRef _progress; + LazyMediaHandle _medium; + }; + } + + AsyncOpRef > checkIfToRefreshMetadata(repo::AsyncRefreshContextRef refCtx, LazyMediaHandle medium, ProgressObserverRef progressObserver) + { + return SimpleExecutor< CheckIfToRefreshMetadataLogic , AsyncOp> >::run( std::move(refCtx), std::move(medium), std::move(progressObserver) ); + } + + expected checkIfToRefreshMetadata(repo::SyncRefreshContextRef refCtx, LazyMediaHandle medium, ProgressObserverRef progressObserver) + { + return SimpleExecutor< CheckIfToRefreshMetadataLogic , SyncOp> >::run( std::move(refCtx), std::move(medium), std::move(progressObserver) ); + } + + + namespace { + + template + struct RefreshMetadataLogic : public LogicBase{ + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + + using RefreshContextRefType = std::conditional_t, repo::AsyncRefreshContextRef, repo::SyncRefreshContextRef>; + using ZyppContextRefType = typename RefreshContextRefType::element_type::ContextRefType; + using ZyppContextType = typename RefreshContextRefType::element_type::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using LazyMediaHandle = typename ProvideType::LazyMediaHandle; + using ProvideRes = typename ProvideType::Res; + + using DlContextType = repo::DownloadContext; + using DlContextRefType = std::shared_ptr; + + RefreshMetadataLogic( RefreshContextRefType refCtx, LazyMediaHandle &&medium, ProgressObserverRef progressObserver ) + : _refreshContext(std::move(refCtx)) + , _progress ( std::move( progressObserver ) ) + , _medium ( std::move( medium ) ) + { } + + MaybeAsyncRef> execute() { + + return assert_alias( _refreshContext->repoInfo() ) + | and_then( [this](){ return assert_urls( _refreshContext->repoInfo() ); }) + | and_then( [this](){ return checkIfToRefreshMetadata ( _refreshContext, _medium, _progress ); }) + | and_then( [this]( repo::RefreshCheckStatus status ){ + + MIL << "RefreshCheckStatus returned: " << status << std::endl; + + // check whether to refresh metadata + // if the check fails for this url, it throws, so another url will be checked + if ( status != zypp::RepoManagerFlags::REFRESH_NEEDED ) + return makeReadyResult ( expected::success( std::move(_refreshContext) ) ); + + MIL << "Going to refresh metadata from " << _medium.baseUrl() << std::endl; + + // bsc#1048315: Always re-probe in case of repo format change. + // TODO: Would be sufficient to verify the type and re-probe + // if verification failed (or type is RepoType::NONE) + return probeRepoType ( _refreshContext->zyppContext(), _medium, _refreshContext->repoInfo().path() /*, _refreshContext->targetDir()*/ ) + | and_then([this]( zypp::repo::RepoType repokind ) { + + auto &info = _refreshContext->repoInfo(); + + if ( info.type() != repokind ) { + _refreshContext->setProbedType( repokind ); + // Adjust the probed type in RepoInfo + info.setProbedType( repokind ); // lazy init! + } + + // no need to continue with an unknown type + if ( repokind.toEnum() == zypp::repo::RepoType::NONE_e ) + return makeReadyResult( expected::error( ZYPP_EXCPT_PTR ( zypp::repo::RepoUnknownTypeException( info ))) ); + + const zypp::Pathname &mediarootpath = _refreshContext->rawCachePath(); + if( zypp::filesystem::assert_dir(mediarootpath) ) { + auto exception = ZYPP_EXCPT_PTR (zypp::Exception(zypp::str::form( _("Can't create %s"), mediarootpath.c_str() ))); + return makeReadyResult( expected::error( std::move(exception) )); + } + + auto dlContext = std::make_shared( _refreshContext->zyppContext(), _refreshContext->repoInfo(), _refreshContext->targetDir() ); + dlContext->setPluginRepoverification( _refreshContext->pluginRepoverification() ); + + return RepoDownloaderWorkflow::download ( dlContext, _medium, _progress ); + + }) + | and_then([this]( DlContextRefType && ) { + + // ok we have the metadata, now exchange + // the contents + _refreshContext->saveToRawCache(); + // if ( ! isTmpRepo( info ) ) + // reposManip(); // remember to trigger appdata refresh + + // we are done. + return expected::success( std::move(_refreshContext) ); + }); + }); + } + + RefreshContextRefType _refreshContext; + ProgressObserverRef _progress; + LazyMediaHandle _medium; + zypp::Pathname _mediarootpath; + + }; + } + + AsyncOpRef > refreshMetadata( repo::AsyncRefreshContextRef refCtx, LazyMediaHandle medium, ProgressObserverRef progressObserver ) + { + return SimpleExecutor>>::run( std::move(refCtx), std::move(medium), std::move(progressObserver)); + } + + expected refreshMetadata( repo::SyncRefreshContextRef refCtx, LazyMediaHandle medium, ProgressObserverRef progressObserver ) + { + return SimpleExecutor>>::run( std::move(refCtx), std::move(medium), std::move(progressObserver)); + } + + namespace { + template + auto refreshMetadataLogic( RefreshContextRef refCtx, ProgressObserverRef progressObserver) + { + // small shared helper struct to pass around the exception and to remember that we tried the first URL + struct ExHelper { + bool isFirst; + // we will throw this later if no URL checks out fine + zypp::repo::RepoException rexception; + }; + + auto helper = std::make_shared( ExHelper{ + false, + zypp::repo::RepoException { refCtx->repoInfo(), PL_("Valid metadata not found at specified URL", + "Valid metadata not found at specified URLs", + refCtx->repoInfo().baseUrlsSize() ) } + }); + + // the actual logic pipeline, attaches the medium and tries to refresh from it + auto refreshPipeline = [ refCtx, progressObserver ]( zypp::Url url ){ + return refCtx->zyppContext()->provider()->prepareMedia( url, zyppng::ProvideMediaSpec() ) + | and_then( [ refCtx , progressObserver]( auto mediaHandle ) mutable { return refreshMetadata ( std::move(refCtx), std::move(mediaHandle), progressObserver ); } ); + }; + + // predicate that accepts only valid results, and in addition collects all errors in rexception + auto predicate = [ info = refCtx->repoInfo(), helper ]( const expected &res ) -> bool{ + if ( !res ) { + try { + ZYPP_RETHROW( res.error() ); + } catch ( const zypp::Exception &e ) { + ERR << "Trying another url..." << std::endl; + + // remember the exception caught for the *first URL* + // if all other URLs fail, the rexception will be thrown with the + // cause of the problem of the first URL remembered + if ( helper->isFirst ) { + helper->rexception.remember( e ); + helper->isFirst = false; + } else { + helper->rexception.addHistory( e.asUserString() ); + } + } + return false; + } + return true; + }; + + // now go over the urls until we find one that works + return refCtx->repoInfo().baseUrls() + | firstOf( std::move(refreshPipeline), expected::error( std::make_exception_ptr(NotFoundException()) ), std::move(predicate) ) + | [helper]( expected result ) { + if ( !result ) { + // none of the URLs worked + ERR << "No more urls..." << std::endl; + return expected::error( ZYPP_EXCPT_PTR(helper->rexception) ); + } + // we are done. + return result; + }; + } + } + + AsyncOpRef > refreshMetadata( repo::AsyncRefreshContextRef refCtx, ProgressObserverRef progressObserver) { + return refreshMetadataLogic ( std::move(refCtx), std::move(progressObserver) ); + } + + expected refreshMetadata( repo::SyncRefreshContextRef refCtx, ProgressObserverRef progressObserver) { + return refreshMetadataLogic ( std::move(refCtx), std::move(progressObserver) ); + } + + + namespace { + + template struct Repo2SolvOp; + + template <> + struct Repo2SolvOp : public AsyncOp> + { + Repo2SolvOp() { } + + static AsyncOpRef> run( zypp::RepoInfo repo, zypp::ExternalProgram::Arguments args ) { + MIL << "Starting repo2solv for repo " << repo.alias () << std::endl; + auto me = std::make_shared>(); + me->_repo = std::move(repo); + me->_proc = Process::create(); + me->_proc->connect( &Process::sigFinished, *me, &Repo2SolvOp::procFinished ); + me->_proc->connect( &Process::sigReadyRead, *me, &Repo2SolvOp::readyRead ); + + std::vector argsIn; + argsIn.reserve ( args.size() ); + std::for_each( args.begin (), args.end(), [&]( const std::string &s ) { argsIn.push_back(s.data()); }); + argsIn.push_back (nullptr); + me->_proc->setOutputChannelMode ( Process::Merged ); + if (!me->_proc->start( argsIn.data() )) { + return makeReadyResult( expected::error(ZYPP_EXCPT_PTR(zypp::repo::RepoException ( me->_repo, _("Failed to cache repo ( unable to start repo2solv ).") ))) ); + } + return me; + } + + void readyRead (){ + const ByteArray &data = _proc->readLine(); + const std::string &line = data.asString(); + WAR << " " << line; + _errdetail += line; + } + + void procFinished( int ret ) { + + while ( _proc->canReadLine() ) + readyRead(); + + if ( ret != 0 ) { + zypp::repo::RepoException ex( _repo, zypp::str::form( _("Failed to cache repo (%d)."), ret )); + ex.addHistory( zypp::str::Str() << _proc->executedCommand() << std::endl << _errdetail << _proc->execError() ); // errdetail lines are NL-terminaled! + setReady( expected::error(ZYPP_EXCPT_PTR(ex)) ); + return; + } + setReady( expected::success() ); + } + + private: + ProcessRef _proc; + zypp::RepoInfo _repo; + std::string _errdetail; + }; + + template <> + struct Repo2SolvOp + { + static expected run( zypp::RepoInfo repo, zypp::ExternalProgram::Arguments args ) { + zypp::ExternalProgram prog( args, zypp::ExternalProgram::Stderr_To_Stdout ); + std::string errdetail; + + for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) { + WAR << " " << output; + errdetail += output; + } + + int ret = prog.close(); + if ( ret != 0 ) + { + zypp::repo::RepoException ex(repo, zypp::str::form( _("Failed to cache repo (%d)."), ret )); + ex.addHistory( zypp::str::Str() << prog.command() << std::endl << errdetail << prog.execError() ); // errdetail lines are NL-terminaled! + return expected::error(ZYPP_EXCPT_PTR(ex)); + } + return expected::success(); + } + }; + + template + struct BuildCacheLogic : public LogicBase{ + + using RefreshContextRefType = std::conditional_t, repo::AsyncRefreshContextRef, repo::SyncRefreshContextRef>; + using ZyppContextRefType = typename RefreshContextRefType::element_type::ContextRefType; + using ZyppContextType = typename RefreshContextRefType::element_type::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + BuildCacheLogic( RefreshContextRefType &&refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef &&progressObserver ) + : _refCtx( std::move(refCtx) ) + , _policy( policy ) + , _progressObserver( std::move(progressObserver) ) + {} + + MaybeAsyncRef> execute() { + + ProgressObserver::setup ( _progressObserver, zypp::str::form(_("Building repository '%s' cache"), _refCtx->repoInfo().label().c_str()), 100 ); + + return assert_alias(_refCtx->repoInfo() ) + | and_then( mtry( [this] { + _mediarootpath = rawcache_path_for_repoinfo( _refCtx->repoManagerOptions(), _refCtx->repoInfo() ).unwrap(); + _productdatapath = rawproductdata_path_for_repoinfo( _refCtx->repoManagerOptions(), _refCtx->repoInfo() ).unwrap(); + })) + | and_then( [this] { + + const auto &options = _refCtx->repoManagerOptions(); + + if( zypp::filesystem::assert_dir( options.repoCachePath ) ) { + auto ex = ZYPP_EXCPT_PTR( zypp::Exception (zypp::str::form( _("Can't create %s"), options.repoCachePath.c_str()) ) ); + return expected::error( std::move(ex) ); + } + + return RepoManager::metadataStatus( _refCtx->repoInfo(), options ); + + }) | and_then( [this](RepoStatus raw_metadata_status ) { + + if ( raw_metadata_status.empty() ) + { + /* if there is no cache at this point, we refresh the raw + in case this is the first time - if it's !autorefresh, + we may still refresh */ + return refreshMetadata( _refCtx, ProgressObserver::makeSubTask( _progressObserver ) ) + | and_then([this]( auto /*refCtx*/) { return RepoManager::metadataStatus( _refCtx->repoInfo(), _refCtx->repoManagerOptions() ); } ); + } + return makeReadyResult( make_expected_success (raw_metadata_status) ); + + }) | and_then( [this]( RepoStatus raw_metadata_status ) { + + bool needs_cleaning = false; + const auto &info = _refCtx->repoInfo(); + if ( _refCtx->repoManager()->isCached( info ) ) + { + MIL << info.alias() << " is already cached." << std::endl; + expected cache_status = RepoManager::cacheStatus( info, _refCtx->repoManagerOptions() ); + if ( !cache_status ) + return makeReadyResult( expected::error(cache_status.error()) ); + + if ( *cache_status == raw_metadata_status ) + { + MIL << info.alias() << " cache is up to date with metadata." << std::endl; + if ( _policy == zypp::RepoManagerFlags::BuildIfNeeded ) + { + // On the fly add missing solv.idx files for bash completion. + return makeReadyResult( + solv_path_for_repoinfo( _refCtx->repoManagerOptions(), info) + | and_then([this]( zypp::Pathname base ){ + if ( ! zypp::PathInfo(base/"solv.idx").isExist() ) + return mtry( zypp::sat::updateSolvFileIndex, base/"solv" ); + return expected::success (); + }) + ); + } + else { + MIL << info.alias() << " cache rebuild is forced" << std::endl; + } + } + + needs_cleaning = true; + } + + ProgressObserver::start( _progressObserver ); + + if (needs_cleaning) + { + auto r = _refCtx->repoManager()->cleanCache(info); + if ( !r ) + return makeReadyResult( expected::error(r.error()) ); + } + + MIL << info.alias() << " building cache..." << info.type() << std::endl; + + expected base = solv_path_for_repoinfo( _refCtx->repoManagerOptions(), info); + if ( !base ) + return makeReadyResult( expected::error(base.error()) ); + + if( zypp::filesystem::assert_dir(*base) ) + { + zypp::Exception ex(zypp::str::form( _("Can't create %s"), base->c_str()) ); + return makeReadyResult( expected::error(ZYPP_EXCPT_PTR(ex)) ); + } + + if( ! zypp::PathInfo(*base).userMayW() ) + { + zypp::Exception ex(zypp::str::form( _("Can't create cache at %s - no writing permissions."), base->c_str()) ); + return makeReadyResult( expected::error(ZYPP_EXCPT_PTR(ex)) ); + } + + zypp::Pathname solvfile = *base / "solv"; + + // do we have type? + zypp::repo::RepoType repokind = info.type(); + + // if the type is unknown, try probing. + switch ( repokind.toEnum() ) + { + case zypp::repo::RepoType::NONE_e: + // unknown, probe the local metadata + repokind = RepoManager::probeCache( _productdatapath ); + break; + default: + break; + } + + MIL << "repo type is " << repokind << std::endl; + + return mountIfRequired( repokind, info ) + | and_then([this, repokind, solvfile = std::move(solvfile) ]( std::optional forPlainDirs ) mutable { + + const auto &info = _refCtx->repoInfo(); + + switch ( repokind.toEnum() ) + { + case zypp::repo::RepoType::RPMMD_e : + case zypp::repo::RepoType::YAST2_e : + case zypp::repo::RepoType::RPMPLAINDIR_e : + { + // Take care we unlink the solvfile on error + zypp::ManagedFile guard( solvfile, zypp::filesystem::unlink ); + + zypp::ExternalProgram::Arguments cmd; +#ifdef ZYPP_REPO2SOLV_PATH + cmd.push_back( ZYPP_REPO2SOLV_PATH ); +#else + cmd.push_back( zypp::PathInfo( "/usr/bin/repo2solv" ).isFile() ? "repo2solv" : "repo2solv.sh" ); +#endif + // repo2solv expects -o as 1st arg! + cmd.push_back( "-o" ); + cmd.push_back( solvfile.asString() ); + cmd.push_back( "-X" ); // autogenerate pattern from pattern-package + // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages + + if ( repokind == zypp::repo::RepoType::RPMPLAINDIR ) + { + // recusive for plaindir as 2nd arg! + cmd.push_back( "-R" ); + + std::optional localPath = forPlainDirs.has_value() ? forPlainDirs->localPath() : zypp::Pathname(); + if ( !localPath ) + return makeReadyResult( expected::error( ZYPP_EXCPT_PTR( zypp::repo::RepoException( zypp::str::Format(_("Failed to cache repo %1%")) % _refCtx->repoInfo() ))) ); + + // FIXME this does only work for dir: URLs + cmd.push_back( (*localPath / info.path().absolutename()).c_str() ); + } + else + cmd.push_back( _productdatapath.asString() ); + + return Repo2SolvOp::run( info, std::move(cmd) ) + | and_then( [this, guard = std::move(guard), solvfile = std::move(solvfile) ]() mutable { + // We keep it. + guard.resetDispose(); + return mtry( zypp::sat::updateSolvFileIndex, solvfile ); // content digest for zypper bash completion + }); + } + break; + default: + return makeReadyResult( expected::error( ZYPP_EXCPT_PTR(zypp::repo::RepoUnknownTypeException( info, _("Unhandled repository type") )) ) ); + break; + } + }) + | and_then([this, raw_metadata_status](){ + // update timestamp and checksum + return _refCtx->repoManager()->setCacheStatus( _refCtx->repoInfo(), raw_metadata_status ); + }); + }) + | and_then( [this](){ + MIL << "Commit cache.." << std::endl; + ProgressObserver::finish( _progressObserver, ProgressObserver::Success ); + return make_expected_success ( _refCtx ); + + }) + | or_else ( [this]( std::exception_ptr e ) { + ProgressObserver::finish( _progressObserver, ProgressObserver::Success ); + return expected::error(e); + }); + } + + private: + MaybeAsyncRef>> mountIfRequired ( zypp::repo::RepoType repokind, zypp::RepoInfo info ) { + if ( repokind != zypp::repo::RepoType::RPMPLAINDIR ) + return makeReadyResult( make_expected_success( std::optional() )); + + return _refCtx->zyppContext()->provider()->attachMedia( info.url(), ProvideMediaSpec() ) + | and_then( [this]( MediaHandle handle ) { + return makeReadyResult( make_expected_success( std::optional( std::move(handle)) )); + }); + } + + private: + RefreshContextRefType _refCtx; + zypp::RepoManagerFlags::CacheBuildPolicy _policy; + ProgressObserverRef _progressObserver; + + zypp::Pathname _mediarootpath; + zypp::Pathname _productdatapath; + }; + } + + AsyncOpRef > buildCache(repo::AsyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver) + { + return SimpleExecutor>>::run( std::move(refCtx), policy, std::move(progressObserver)); + } + + expected buildCache(repo::SyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver) + { + return SimpleExecutor>>::run( std::move(refCtx), policy, std::move(progressObserver)); + } + + + // Add repository logic + namespace { + + template + struct AddRepoLogic : public LogicBase{ + + using RepoManagerPtrType = std::conditional_t, AsyncRepoManagerRef, SyncRepoManagerRef>; + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + AddRepoLogic( RepoManagerPtrType &&repoMgrRef, RepoInfo &&info, ProgressObserverRef &&myProgress ) + : _repoMgrRef( std::move(repoMgrRef) ) + , _info( std::move(info) ) + , _myProgress ( std::move(myProgress) ) + {} + + MaybeAsyncRef > execute() { + using namespace zyppng::operators; + + return assert_alias(_info) + | and_then([this]( ) { + + MIL << "Try adding repo " << _info << std::endl; + ProgressObserver::setup( _myProgress, zypp::str::form(_("Adding repository '%s'"), _info.label().c_str()) ); + ProgressObserver::start( _myProgress ); + + if ( _repoMgrRef->repos().find(_info) != _repoMgrRef->repos().end() ) + return makeReadyResult( expected::error( ZYPP_EXCPT_PTR(zypp::repo::RepoAlreadyExistsException(_info)) ) ); + + // check the first url for now + if ( _repoMgrRef->options().probe ) + { + DBG << "unknown repository type, probing" << std::endl; + return assert_urls(_info) + | and_then([this]{ return probeRepoType( _repoMgrRef->zyppContext(), _info ); }) + | and_then([this]( zypp::repo::RepoType probedtype ) { + + if ( probedtype == zypp::repo::RepoType::NONE ) + return expected::error( ZYPP_EXCPT_PTR(zypp::repo::RepoUnknownTypeException(_info)) ); + + RepoInfo tosave = _info; + tosave.setType(probedtype); + return make_expected_success(tosave); + }); + } + return makeReadyResult( make_expected_success(_info) ); + }) + | inspect( operators::setProgress( _myProgress, 50 ) ) + | and_then( [this]( RepoInfo tosave ){ return _repoMgrRef->addProbedRepository( tosave, tosave.type() ); }) + | and_then( [this]( RepoInfo updated ) { + ProgressObserver::finish( _myProgress ); + MIL << "done" << std::endl; + return expected::success( updated ); + }) + | or_else( [this]( std::exception_ptr e) { + ProgressObserver::finish ( _myProgress, ProgressObserver::Error ); + MIL << "done" << std::endl; + return expected::error(e); + }) + ; + } + + RepoManagerPtrType _repoMgrRef; + RepoInfo _info; + ProgressObserverRef _myProgress; + }; + }; + + AsyncOpRef > addRepository( AsyncRepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress ) + { + return SimpleExecutor>>::run( std::move(mgr), std::move(info), std::move(myProgress) ); + } + + expected addRepository( SyncRepoManagerRef mgr, const RepoInfo &info, ProgressObserverRef myProgress ) + { + return SimpleExecutor>>::run( std::move(mgr), RepoInfo(info), std::move(myProgress) ); + } + + namespace { + + template + struct AddReposLogic : public LogicBase{ + + using RepoManagerPtrType = std::conditional_t, AsyncRepoManagerRef, SyncRepoManagerRef>; + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + AddReposLogic( RepoManagerPtrType &&repoMgrRef, zypp::Url &&url, ProgressObserverRef &&myProgress ) + : _repoMgrRef( std::move(repoMgrRef) ) + , _url( std::move(url) ) + , _myProgress ( std::move(myProgress) ) + {} + + MaybeAsyncRef> execute() { + using namespace zyppng::operators; + + return mtry( zypp::repo::RepoVariablesUrlReplacer(), _url ) + | and_then([this]( zypp::Url repoFileUrl ) { return readRepoFile( _repoMgrRef->zyppContext(), std::move(repoFileUrl) ); } ) + | and_then([this]( std::list repos ) { + + for ( std::list::const_iterator it = repos.begin(); + it != repos.end(); + ++it ) + { + // look if the alias is in the known repos. + for_ ( kit, _repoMgrRef->repoBegin(), _repoMgrRef->repoEnd() ) + { + if ( (*it).alias() == (*kit).alias() ) + { + ERR << "To be added repo " << (*it).alias() << " conflicts with existing repo " << (*kit).alias() << std::endl; + return expected::error(ZYPP_EXCPT_PTR(zypp::repo::RepoAlreadyExistsException(*it))); + } + } + } + + std::string filename = zypp::Pathname(_url.getPathName()).basename(); + if ( filename == zypp::Pathname() ) + { + // TranslatorExplanation '%s' is an URL + return expected::error(ZYPP_EXCPT_PTR(zypp::repo::RepoException(zypp::str::form( _("Invalid repo file name at '%s'"), _url.asString().c_str() )))); + } + + const auto &options = _repoMgrRef->options(); + + // assert the directory exists + zypp::filesystem::assert_dir( options.knownReposPath ); + + zypp::Pathname repofile = _repoMgrRef->generateNonExistingName( options.knownReposPath, filename ); + // now we have a filename that does not exists + MIL << "Saving " << repos.size() << " repo" << ( repos.size() ? "s" : "" ) << " in " << repofile << std::endl; + + std::ofstream file(repofile.c_str()); + if (!file) + { + // TranslatorExplanation '%s' is a filename + return expected::error(ZYPP_EXCPT_PTR( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), repofile.c_str() )))); + } + + for ( std::list::iterator it = repos.begin(); + it != repos.end(); + ++it ) + { + MIL << "Saving " << (*it).alias() << std::endl; + + const auto &rawCachePath = rawcache_path_for_repoinfo( options, *it ); + if ( !rawCachePath ) return expected::error(rawCachePath.error()); + + const auto &pckCachePath = packagescache_path_for_repoinfo( options, *it ) ; + if ( !pckCachePath ) return expected::error(pckCachePath.error()); + + it->dumpAsIniOn(file); + it->setFilepath(repofile); + it->setMetadataPath( *rawCachePath ); + it->setPackagesPath( *pckCachePath ); + _repoMgrRef->reposManip().insert(*it); + + zypp::HistoryLog( _repoMgrRef->options().rootDir).addRepository(*it); + } + + MIL << "done" << std::endl; + return expected::success(); + }); + } + + private: + RepoManagerPtrType _repoMgrRef; + zypp::Url _url; + ProgressObserverRef _myProgress; + }; + + } + + AsyncOpRef> addRepositories( AsyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress ) + { + return SimpleExecutor>>::run( std::move(mgr), std::move(url), std::move(myProgress) ); + } + + expected addRepositories( SyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress) + { + return SimpleExecutor>>::run( std::move(mgr), std::move(url), std::move(myProgress) ); + } + + + namespace { + + template + struct RefreshGeoIpLogic : public LogicBase{ + protected: + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + using ZyppContextRefType = std::conditional_t, ContextRef, SyncContextRef >; + using ZyppContextType = typename ZyppContextRefType::element_type; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + + RefreshGeoIpLogic( ZyppContextRefType &&zyppCtx, RepoInfo::url_set &&urls ) + : _zyppCtx( std::move(zyppCtx) ) + , _urls( std::move(urls) ) + { } + + MaybeAsyncRef> execute() { + + using namespace zyppng::operators; + + if ( !_zyppCtx->config().geoipEnabled() ) { + MIL << "GeoIp disabled via ZConfig, not refreshing the GeoIP information." << std::endl; + return makeReadyResult(expected::success()); + } + + std::vector hosts; + for ( const auto &baseUrl : _urls ) { + const auto &host = baseUrl.getHost(); + if ( zypp::any_of( _zyppCtx->config().geoipHostnames(), [&host]( const auto &elem ){ return ( zypp::str::compareCI( host, elem ) == 0 ); } ) ) { + hosts.push_back( host ); + break; + } + } + + if ( hosts.empty() ) { + MIL << "No configured geoip URL found, not updating geoip data" << std::endl; + return makeReadyResult(expected::success()); + } + + _geoIPCache = _zyppCtx->config().geoipCachePath(); + + if ( zypp::filesystem::assert_dir( _geoIPCache ) != 0 ) { + MIL << "Unable to create cache directory for GeoIP." << std::endl; + return makeReadyResult(expected::success()); + } + + if ( !zypp::PathInfo(_geoIPCache).userMayRWX() ) { + MIL << "No access rights for the GeoIP cache directory." << std::endl; + return makeReadyResult(expected::success()); + } + + // remove all older cache entries + zypp::filesystem::dirForEachExt( _geoIPCache, []( const zypp::Pathname &dir, const zypp::filesystem::DirEntry &entry ) { + if ( entry.type != zypp::filesystem::FT_FILE ) + return true; + + zypp::PathInfo pi( dir/entry.name ); + auto age = std::chrono::system_clock::now() - std::chrono::system_clock::from_time_t( pi.mtime() ); + if ( age < std::chrono::hours(24) ) + return true; + + MIL << "Removing GeoIP file for " << entry.name << " since it's older than 24hrs." << std::endl; + zypp::filesystem::unlink( dir/entry.name ); + return true; + }); + + auto firstOfCb = [this]( std::string hostname ) { + + // do not query files that are still there + if ( zypp::PathInfo( _geoIPCache / hostname ).isExist() ) { + MIL << "Skipping GeoIP request for " << hostname << " since a valid cache entry exists." << std::endl; + return makeReadyResult(false); + } + + MIL << "Query GeoIP for " << hostname << std::endl; + + zypp::Url url; + try { + url.setHost(hostname); + url.setScheme("https"); + + } catch(const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + MIL << "Ignoring invalid GeoIP hostname: " << hostname << std::endl; + return makeReadyResult(false); + } + + // always https ,but attaching makes things easier + return _zyppCtx->provider()->attachMedia( url, ProvideMediaSpec() ) + | and_then( [this]( MediaHandle provideHdl ) { return _zyppCtx->provider()->provide( provideHdl, "/geoip", ProvideFileSpec() ); }) + | inspect_err( [hostname]( const std::exception_ptr& ){ MIL << "Failed to query GeoIP from hostname: " << hostname << std::endl; } ) + | and_then( [hostname, this]( ProvideRes provideRes ) { + + // here we got something from the server, we will stop after this hostname and mark the process as success() + + constexpr auto writeHostToFile = []( const zypp::Pathname &fName, const std::string &host ){ + std::ofstream out; + out.open( fName.asString(), std::ios_base::trunc ); + if ( out.is_open() ) { + out << host << std::endl; + } else { + MIL << "Failed to create/open GeoIP cache file " << fName << std::endl; + } + }; + + std::string geoipMirror; + try { + zypp::xml::Reader reader( provideRes.file() ); + if ( reader.seekToNode( 1, "host" ) ) { + const auto &str = reader.nodeText().asString(); + + // make a dummy URL to ensure the hostname is valid + zypp::Url testUrl; + testUrl.setHost(str); + testUrl.setScheme("https"); + + if ( testUrl.isValid() ) { + MIL << "Storing geoIP redirection: " << hostname << " -> " << str << std::endl; + geoipMirror = str; + } + + } else { + MIL << "No host entry or empty file returned for GeoIP, remembering for 24hrs" << std::endl; + } + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + MIL << "Empty or invalid GeoIP file, not requesting again for 24hrs" << std::endl; + } + + writeHostToFile( _geoIPCache / hostname, geoipMirror ); + return expected::success(); // need to return a expected<> due to and_then requirements + }) + | []( expected res ) { return res.is_valid(); }; + }; + + return std::move(hosts) + | firstOf( std::move(firstOfCb), false, zyppng::detail::ContinueUntilValidPredicate() ) + | []( bool foundGeoIP ){ + + if ( foundGeoIP ) { + MIL << "Successfully queried GeoIP data." << std::endl; + return expected::success (); + } + + MIL << "Failed to query GeoIP data." << std::endl; + return expected::error( std::make_exception_ptr( zypp::Exception("No valid geoIP url found" )) ); + + }; + } + + private: + ZyppContextRefType _zyppCtx; + RepoInfo::url_set _urls; + zypp::Pathname _geoIPCache; + + }; + } + + AsyncOpRef > refreshGeoIPData( ContextRef ctx, RepoInfo::url_set urls ) + { + return SimpleExecutor>>::run( std::move(ctx), std::move(urls) ); + } + + expected refreshGeoIPData( SyncContextRef ctx, RepoInfo::url_set urls ) + { + return SimpleExecutor>>::run( std::move(ctx), std::move(urls) ); + } + + + +} diff --git a/zypp/ng/repo/workflows/repomanagerwf.h b/zypp/ng/repo/workflows/repomanagerwf.h new file mode 100644 index 0000000..247f903 --- /dev/null +++ b/zypp/ng/repo/workflows/repomanagerwf.h @@ -0,0 +1,72 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_REPOMANAGER_WORKFLOW_INCLUDED +#define ZYPP_NG_REPOMANAGER_WORKFLOW_INCLUDED + + +#include +#include +#include + +#include +#include + +//@ TODO move required types into their own files... e.g. CheckStatus +#include + + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (Context); + ZYPP_FWD_DECL_TYPE_WITH_REFS (SyncContext); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProgressObserver); + + class Provide; + class MediaSyncFacade; + + using AsyncLazyMediaHandle = LazyMediaHandle; + using SyncLazyMediaHandle = LazyMediaHandle; + + namespace RepoManagerWorkflow { + + AsyncOpRef > probeRepoType( ContextRef ctx, AsyncLazyMediaHandle medium, zypp::Pathname path, std::optional targetPath = {} ); + expected probeRepoType ( SyncContextRef ctx, SyncLazyMediaHandle medium, zypp::Pathname path, std::optional targetPath = {} ); + + AsyncOpRef > probeRepoType( ContextRef ctx, RepoInfo repo, std::optional targetPath = {} ); + expected probeRepoType ( SyncContextRef ctx, RepoInfo repo, std::optional targetPath = {} ); + + AsyncOpRef>> readRepoFile( ContextRef ctx, zypp::Url repoFileUrl ); + expected> readRepoFile( SyncContextRef ctx, zypp::Url repoFileUrl ); + + AsyncOpRef > checkIfToRefreshMetadata( repo::AsyncRefreshContextRef refCtx, AsyncLazyMediaHandle medium, ProgressObserverRef progressObserver = nullptr ); + expected checkIfToRefreshMetadata( repo::SyncRefreshContextRef refCtx, SyncLazyMediaHandle medium, ProgressObserverRef progressObserver = nullptr ); + + AsyncOpRef > refreshMetadata( repo::AsyncRefreshContextRef refCtx, ProgressObserverRef progressObserver = nullptr ); + expected refreshMetadata( repo::SyncRefreshContextRef refCtx, ProgressObserverRef progressObserver = nullptr ); + + AsyncOpRef > refreshMetadata( repo::AsyncRefreshContextRef refCtx, AsyncLazyMediaHandle medium, ProgressObserverRef progressObserver = nullptr ); + expected refreshMetadata( repo::SyncRefreshContextRef refCtx, SyncLazyMediaHandle medium, ProgressObserverRef progressObserver = nullptr ); + + AsyncOpRef > buildCache( repo::AsyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver = nullptr ); + expected buildCache( repo::SyncRefreshContextRef refCtx, zypp::RepoManagerFlags::CacheBuildPolicy policy, ProgressObserverRef progressObserver = nullptr ); + + AsyncOpRef> addRepository( AsyncRepoManagerRef mgr, RepoInfo info, ProgressObserverRef myProgress = nullptr ); + expected addRepository( SyncRepoManagerRef mgr, const RepoInfo &info, ProgressObserverRef myProgress = nullptr ); + + AsyncOpRef> addRepositories( AsyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress = nullptr ); + expected addRepositories( SyncRepoManagerRef mgr, zypp::Url url, ProgressObserverRef myProgress = nullptr ); + + AsyncOpRef> refreshGeoIPData( ContextRef ctx, RepoInfo::url_set urls ); + expected refreshGeoIPData( SyncContextRef ctx, RepoInfo::url_set urls ); + + } +} + + +#endif diff --git a/zypp/ng/repo/workflows/rpmmd.cc b/zypp/ng/repo/workflows/rpmmd.cc new file mode 100644 index 0000000..c759296 --- /dev/null +++ b/zypp/ng/repo/workflows/rpmmd.cc @@ -0,0 +1,182 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "rpmmd.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +namespace zyppng::RpmmdWorkflows { + + namespace { + + using namespace zyppng::operators; + + template + struct StatusLogic : public LogicBase{ + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + + using DlContextRefType = std::conditional_t, repo::AsyncDownloadContextRef, repo::SyncDownloadContextRef>; + using ZyppContextType = typename DlContextRefType::element_type::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + StatusLogic( DlContextRefType ctx, MediaHandle &&media ) + : _ctx(std::move(ctx)) + , _handle(std::move(media)) + {} + + MaybeAsyncRef> execute() { + return _ctx->zyppContext()->provider()->provide( _handle, _ctx->repoInfo().path() / "/repodata/repomd.xml" , ProvideFileSpec() ) + | [this]( expected repomdFile ) { + + if ( !repomdFile ) + return makeReadyResult( make_expected_success (zypp::RepoStatus() )); + + zypp::RepoStatus status ( repomdFile->file() ); + + if ( !status.empty() && _ctx->repoInfo ().requireStatusWithMediaFile()) { + return _ctx->zyppContext()->provider()->provide( _handle, "/media.1/media" , ProvideFileSpec()) + | [status = std::move(status)]( expected mediaFile ) mutable { + if ( mediaFile ) { + return make_expected_success( status && zypp::RepoStatus( mediaFile->file()) ); + } + return make_expected_success( std::move(status) ); + }; + } + return makeReadyResult( make_expected_success(std::move(status)) ); + }; + } + + DlContextRefType _ctx; + MediaHandle _handle; + }; + } + + AsyncOpRef > repoStatus(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle) + { + return SimpleExecutor< StatusLogic, AsyncOp> >::run( std::move(dl), std::move(mediaHandle) ); + } + + expected repoStatus(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle) + { + return SimpleExecutor< StatusLogic, SyncOp> >::run( std::move(dl), std::move(mediaHandle) ); + } + + + namespace { + + using namespace zyppng::operators; + + template + struct DlLogic : public LogicBase, private zypp::repo::yum::RepomdFileCollector { + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + public: + + using DlContextRefType = std::conditional_t, repo::AsyncDownloadContextRef, repo::SyncDownloadContextRef>; + using ZyppContextType = typename DlContextRefType::element_type::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + DlLogic( DlContextRefType ctx, MediaHandle &&mediaHandle, ProgressObserverRef &&progressObserver ) + : zypp::repo::yum::RepomdFileCollector( ctx->destDir() ) + , _ctx( std::move(ctx)) + , _mediaHandle(std::move(mediaHandle)) + , _progressObserver(std::move(progressObserver)) + {} + + auto execute() { + // download media file here + return RepoDownloaderWorkflow::downloadMediaInfo( _mediaHandle, _ctx->destDir() ) + | [this]( expected &&mediaInfo ) { + + // remember the media info if we had one + if ( mediaInfo ) _ctx->files().push_back ( std::move(mediaInfo.get()) ); + + if ( _progressObserver ) _progressObserver->inc(); + + return RepoDownloaderWorkflow::downloadMasterIndex( _ctx, _mediaHandle, _ctx->repoInfo().path() / "/repodata/repomd.xml" ) + | inspect( incProgress( _progressObserver ) ) + | and_then( [this] ( DlContextRefType && ) { + + zypp::Pathname repomdPath = _ctx->files().front(); + std::vector requiredFiles; + try { + zypp::parser::yum::RepomdFileReader reader( repomdPath, [this]( const zypp::OnMediaLocation & loc_r, const std::string & typestr_r ){ return collect( loc_r, typestr_r ); }); + finalize([&]( const zypp::OnMediaLocation &file ){ + if ( file.medianr () != 1 ) { + // ALL repo files NEED to come from media nr 1 , otherwise we fail + ZYPP_THROW(zypp::repo::RepoException( _ctx->repoInfo(), "Repo can only require metadata files from primary medium.")); + } + requiredFiles.push_back( file ); + }); + } catch ( ... ) { + return makeReadyResult(expected::error( ZYPP_FWD_CURRENT_EXCPT() ) ); + } + + // add the required files to the base steps + if ( _progressObserver ) _progressObserver->setBaseSteps ( _progressObserver->baseSteps () + requiredFiles.size() ); + + return transform_collect ( std::move(requiredFiles), [this]( zypp::OnMediaLocation file ) { + + return DownloadWorkflow::provideToCacheDir( _ctx, _mediaHandle, file.filename(), ProvideFileSpec(file) ) + | inspect ( incProgress( _progressObserver ) ); + + }) | and_then ( [this]( std::vector &&dlFiles ) { + auto &downloadedFiles = _ctx->files(); + downloadedFiles.insert( downloadedFiles.end(), std::make_move_iterator(dlFiles.begin()), std::make_move_iterator(dlFiles.end()) ); + return expected::success( std::move(_ctx) ); + }); + }); + + } | finishProgress( _progressObserver ); + } + + private: + + const zypp::RepoInfo &repoInfo() const override { + return _ctx->repoInfo(); + } + + const zypp::filesystem::Pathname &deltaDir() const override { + return _ctx->deltaDir(); + } + + DlContextRefType _ctx; + MediaHandle _mediaHandle; + ProgressObserverRef _progressObserver; + }; + } + + AsyncOpRef > download(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return SimpleExecutor< DlLogic, AsyncOp> >::run( std::move(dl), std::move(mediaHandle), std::move(progressObserver) ); + } + + expected download(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return SimpleExecutor< DlLogic, SyncOp> >::run( std::move(dl), std::move(mediaHandle), std::move(progressObserver) ); + } + + +} diff --git a/zypp/ng/repo/workflows/rpmmd.h b/zypp/ng/repo/workflows/rpmmd.h new file mode 100644 index 0000000..1dc6829 --- /dev/null +++ b/zypp/ng/repo/workflows/rpmmd.h @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_RPMMD_WORKFLOW_INCLUDED +#define ZYPP_NG_RPMMD_WORKFLOW_INCLUDED + + +#include +#include +#include +#include + +#include + + +namespace zyppng { + class ProvideMediaHandle; + class SyncMediaHandle; + + ZYPP_FWD_DECL_TYPE_WITH_REFS( ProgressObserver ); + + /** + * \short Downloader workspace for YUM (rpm-nmd) repositories + * Encapsulates all the knowledge of which files have + * to be downloaded to the local disk. + */ + namespace RpmmdWorkflows { + AsyncOpRef> repoStatus( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle ); + expected repoStatus(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle ); + + AsyncOpRef> download ( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + expected download ( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + } +} + + +#endif diff --git a/zypp/ng/repo/workflows/serviceswf.cc b/zypp/ng/repo/workflows/serviceswf.cc new file mode 100644 index 0000000..552fae8 --- /dev/null +++ b/zypp/ng/repo/workflows/serviceswf.cc @@ -0,0 +1,749 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "serviceswf.h" + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +namespace zyppng::RepoServicesWorkflow { + + using namespace zyppng::operators; + + + namespace { + + zypp::Url adaptServiceUrlToChroot( zypp::Url serviceUrl, zypp::Pathname root ) { + // if file:// or dir:// path we must prefix with the root_r + const auto &scheme = serviceUrl.getScheme(); + if ( !root.empty() && (scheme == "dir" || scheme == "file") ) { + serviceUrl.setPathName ( root / zypp::Pathname(serviceUrl.getPathName()) ); + } + return serviceUrl; + } + + template + struct FetchRIMServiceLogic : public LogicBase + { + protected: + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + using ZyppContextRefType = std::conditional_t, ContextRef, SyncContextRef >; + using RepoMgrRefType = RepoManagerRef; + + FetchRIMServiceLogic( ZyppContextRefType &&ctx, zypp::Pathname &&root_r, ServiceInfo &&service, ProgressObserverRef &&myProgress ) + : _ctx( std::move(ctx) ) + , _root_r( std::move(root_r) ) + , _service( std::move(service) ) + , _myProgress( std::move(myProgress) ) + {} + + + MaybeAsyncRef >> execute() { + + using namespace zyppng::operators; + + return zyppng::mtry( [this]{ + // repoindex.xml must be fetched always without using cookies (bnc #573897) + zypp::Url serviceUrl = _service.url(); + serviceUrl.setQueryParam( "cookies", "0" ); + return adaptServiceUrlToChroot( serviceUrl, _root_r ); + }) + | and_then( [this]( zypp::Url serviceUrl ){ return _ctx->provider()->attachMedia( serviceUrl, ProvideMediaSpec() ); }) + | and_then( [this]( auto mediaHandle ) { return _ctx->provider()->provide( mediaHandle, "repo/repoindex.xml", ProvideFileSpec() ); } ) + | and_then( [this]( auto provideResult ) { + try { + + zypp::RepoInfoList repos; + auto callback = [&]( const zypp::RepoInfo &r) { repos.push_back(r); return true; }; + + zypp::parser::RepoindexFileReader reader( provideResult.file(), callback); + _service.setProbedTtl( reader.ttl() ); // hack! Modifying the const Service to set parsed TTL + + return make_expected_success( std::make_pair( _service, std::move(repos) ) ); + + } catch ( const zypp::Exception &e ) { + //Reader throws a bare exception, we need to translate it into something our calling + //code expects and handles (bnc#1116840) + ZYPP_CAUGHT ( e ); + zypp::repo::ServicePluginInformalException ex ( e.msg() ); + ex.remember( e ); + return expected>::error( ZYPP_EXCPT_PTR( ex ) ); + } + }); + } + + private: + ZyppContextRefType _ctx; + zypp::Pathname _root_r; + ServiceInfo _service; + ProgressObserverRef _myProgress; + }; + + + template + struct FetchPluginServiceLogic : public LogicBase + { + protected: + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + using ZyppContextRefType = std::conditional_t, ContextRef, SyncContextRef >; + using RepoMgrRefType = RepoManagerRef; + using Ret = expected>; + + FetchPluginServiceLogic( ZyppContextRefType &&ctx, zypp::Pathname &&root_r, ServiceInfo &&service, ProgressObserverRef &&myProgress ) + : _ctx( std::move(ctx) ) + , _root_r( std::move(root_r) ) + , _service( std::move(service) ) + , _myProgress( std::move(myProgress) ) + {} + + + MaybeAsyncRef execute() { + using namespace zyppng::operators; + + // bsc#1080693: Service script needs to be executed chrooted to the RepoManagers rootDir. + // The service is not aware of the rootDir, so it's explicitly passed and needs to be + // stripped from the URLs path. + auto stripped = zypp::Pathname::stripprefix( _root_r, _service.url().getPathName() ).asString(); + + return executor()->runPlugin( std::move(stripped) ) + | and_then( [this]( int exitCode ) { + + if ( exitCode != 0 ) { + // ServicePluginInformalException: + // Ignore this error but we'd like to report it somehow... + ERR << "Capture plugin error:[" << std::endl << _stderrBuf << std::endl << ']' << std::endl; + return Ret::error( ZYPP_EXCPT_PTR( zypp::repo::ServicePluginInformalException( _service, _stderrBuf ) ) ); + } + + try { + zypp::RepoInfoList repos; + auto callback = [&]( const zypp::RepoInfo &r) { repos.push_back(r); return true; }; + + std::stringstream buffer( _stdoutBuf ); + zypp::parser::RepoFileReader parser( buffer, callback ); + return make_expected_success( std::make_pair( _service, std::move(repos) ) ); + + } catch (...) { + return Ret::error( std::current_exception () ); + } + }); + } + + protected: + ZyppContextRefType _ctx; + zypp::Pathname _root_r; + ServiceInfo _service; + ProgressObserverRef _myProgress; + std::string _stdoutBuf; + std::string _stderrBuf; + }; + + + struct SyncFetchPluginService : FetchPluginServiceLogic >>> + { + using FetchPluginServiceLogic::FetchPluginServiceLogic; + expected runPlugin( std::string command ) { + try { + std::stringstream buffer; + + zypp::ExternalProgram::Arguments args; + args.reserve( 3 ); + args.push_back( "/bin/sh" ); + args.push_back( "-c" ); + args.push_back( command ); + + zypp::ExternalProgramWithStderr prog( args, _root_r ); + prog >> buffer; + _stdoutBuf = buffer.str(); + + int retCode = prog.close(); + if ( retCode != 0 ) { + // ServicePluginInformalException: + // Ignore this error but we'd like to report it somehow... + prog.stderrGetUpTo( _stderrBuf, '\0' ); + } + return make_expected_success(retCode); + } catch ( ... ) { + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + }; + + struct ASyncFetchPluginService : FetchPluginServiceLogic >>> + { + using FetchPluginServiceLogic::FetchPluginServiceLogic; + AsyncOpRef> runPlugin( std::string command ) { + using namespace zyppng::operators; + + const char *args[] = { + "/bin/sh", + "-c", + command.c_str(), + nullptr + }; + + auto pluginProcess = Process::create(); + pluginProcess->setChroot ( _root_r ); + + // make sure our process is actually running, if not finalize right away + if ( !pluginProcess->start( args ) || !pluginProcess->isRunning () ) { + return makeReadyResult ( finalize( std::move(pluginProcess) ) ); + } + + return std::move(pluginProcess) + | await( &Process::sigFinished ) // wait for finished sig + | [this]( ProcessRef proc ) { return finalize( std::move(proc) ); }; + } + + expected finalize( ProcessRef proc ) { + if ( proc->isRunning () ) { + proc->stop ( SIGKILL ); + return expected::error( ZYPP_EXCPT_PTR( zypp::Exception("Bug, plugin process was still running after receiving sigFinished")) ); + } + + _stdoutBuf = proc->readAll( Process::StdOut ).asString(); + if ( proc->exitStatus() != 0 ) { + _stderrBuf = proc->readAll( Process::StdErr ).asString(); + } + + return make_expected_success ( proc->exitStatus () ); + } + }; + + + } + + AsyncOpRef>> fetchRepoListfromService( ContextRef ctx, zypp::Pathname root_r, ServiceInfo service, ProgressObserverRef myProgress ) + { + if ( service.type() == zypp::repo::ServiceType::PLUGIN ) + return ASyncFetchPluginService::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) ); + else + return SimpleExecutor >>>::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) ); + } + + expected> fetchRepoListfromService( SyncContextRef ctx, zypp::Pathname root_r, ServiceInfo service, ProgressObserverRef myProgress ) + { + if ( service.type() == zypp::repo::ServiceType::PLUGIN ) + return SyncFetchPluginService::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) ); + else + return SimpleExecutor >>>::run( std::move(ctx), std::move(root_r), std::move(service), std::move(myProgress) ); + } + + + + namespace { + template + auto probeServiceLogic( ContextRefType ctx, const zypp::Url &url ) { + + constexpr bool isAsync = std::is_same_v; + using MediaHandle = std::conditional_t; + using ProvideRes = std::conditional_t; + + return ctx->provider()->attachMedia( url, ProvideMediaSpec() ) + | and_then( [ctx]( MediaHandle medium ) { return ctx->provider()->provide( medium, "/repo/repoindex.xml", ProvideFileSpec().setCheckExistsOnly()); } ) + | [url]( expected result ) { + if ( result ) + return expected::success( zypp::repo::ServiceType::RIS ); + + try{ + std::rethrow_exception( result.error() ); + } catch ( const zypp::media::MediaFileNotFoundException &e ) { + // fall through + } catch ( const zypp::media::MediaException &e ) { + ZYPP_CAUGHT(e); + // TranslatorExplanation '%s' is an URL + zypp::repo::RepoException enew(zypp::str::form( _("Error trying to read from '%s'"), url.asString().c_str() )); + enew.remember(e); + return expected::error( ZYPP_EXCPT_PTR(enew) ); + } + catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + // TranslatorExplanation '%s' is an URL + zypp::Exception enew(zypp::str::form( _("Unknown error reading from '%s'"), url.asString().c_str() )); + enew.remember(e); + return expected::error( ZYPP_EXCPT_PTR(enew) ); + } + catch ( ... ) { + // TranslatorExplanation '%s' is an URL + zypp::Exception enew(zypp::str::form( _("Unknown error reading from '%s'"), url.asString().c_str() )); + enew.remember( std::current_exception() ); + return expected::error( ZYPP_EXCPT_PTR(enew) ); + } + + return expected::success( zypp::repo::ServiceType::NONE ); + }; + } + } + + AsyncOpRef > probeServiceType(ContextRef ctx, const zypp::Url &url) + { + return probeServiceLogic( std::move(ctx), url ); + } + + expected probeServiceType(SyncContextRef ctx, const zypp::Url &url) + { + return probeServiceLogic( std::move(ctx), url ); + } + + namespace { + template + struct RefreshServiceLogic : public LogicBase + { + protected: + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + using ZyppContextRefType = std::conditional_t, ContextRef, SyncContextRef >; + using RepoMgrRefType = RepoManagerRef; + using Ret = expected; + + RefreshServiceLogic( RepoMgrRefType &&repoMgr, zypp::ServiceInfo &&info, zypp::RepoManager::RefreshServiceOptions options ) + : _repoMgr( std::move(repoMgr) ) + , _service( std::move(info) ) + , _options(options) + { } + + MaybeAsyncRef> probeServiceIfNeeded() { + // if the type is unknown, try probing. + if ( _service.type() == zypp::repo::ServiceType::NONE ) { + + return probeServiceType( _repoMgr->zyppContext(), adaptServiceUrlToChroot( _service.url(), _repoMgr->options().rootDir ) ) + | and_then( [this]( zypp::repo::ServiceType type ){ + _service.setProbedType( type ); // lazy init! + _serviceModified = true; + return expected::success(); + } ); + + } + return makeReadyResult( expected::success() ); + } + + MaybeAsyncRef execute() { + + try { + assert_alias( _service ).unwrap(); + assert_url( _service ).unwrap(); + } catch (...) { + return makeReadyResult(Ret::error(ZYPP_FWD_CURRENT_EXCPT())); + } + + MIL << "Going to refresh service '" << _service.alias() << "', url: " << _service.url() << ", opts: " << _options << std::endl; + + if ( _service.ttl() && !( _options.testFlag( zypp::RepoManager::RefreshService_forceRefresh) || _options.testFlag( zypp::RepoManager::RefreshService_restoreStatus ) ) ) + { + // Service defines a TTL; maybe we can re-use existing data without refresh. + zypp::Date lrf = _service.lrf(); + if ( lrf ) + { + zypp::Date now( zypp::Date::now() ); + if ( lrf <= now ) + { + if ( (lrf+=_service.ttl()) > now ) // lrf+= ! + { + MIL << "Skip: '" << _service.alias() << "' metadata valid until " << lrf << std::endl; + return makeReadyResult( Ret::success() ); + } + } + else + WAR << "Force: '" << _service.alias() << "' metadata last refresh in the future: " << lrf << std::endl; + } + } + + //! \todo add callbacks for apps (start, end, repo removed, repo added, repo changed)? + + return probeServiceIfNeeded () // if the type is unknown, try probing. + | and_then( [this]() { + // FIXME bsc#1080693: Shortcoming of (plugin)services (and repos as well) is that they + // are not aware of the RepoManagers rootDir. The service url, as created in known_services, + // contains the full path to the script. The script however has to be executed chrooted. + // Repos would need to know the RepoMangers rootDir to use the correct vars.d to replace + // repos variables. Until RepoInfoBase is aware if the rootDir, we need to explicitly pass it + // to ServiceRepos. + return fetchRepoListfromService( _repoMgr->zyppContext(), _repoMgr->options().rootDir, _service, nullptr ); + } ) + | [this]( expected> serviceReposExp ) { + + if ( !serviceReposExp ) { + try { + std::rethrow_exception( serviceReposExp.error() ); + + } catch ( const zypp::repo::ServicePluginInformalException & e ) { + /* ignore ServicePluginInformalException and throw later */ + _informalError = e; + } catch ( ... ) { + // all other errors cancel the operation + return Ret::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + + std::pair serviceRepos = serviceReposExp.is_valid() ? std::move( serviceReposExp.get() ) : std::make_pair( _service, RepoInfoList{} ); + + // get target distro identifier + std::string servicesTargetDistro = _repoMgr->options().servicesTargetDistro; + if ( servicesTargetDistro.empty() ) { + servicesTargetDistro = zypp::Target::targetDistribution( zypp::Pathname() ); + } + DBG << "ServicesTargetDistro: " << servicesTargetDistro << std::endl; + + // filter repos by target distro + RepoCollector collector( servicesTargetDistro ); + std::for_each( serviceRepos.second.begin(), serviceRepos.second.end(), [&]( const auto &r ){ collector.collect(r); } ); + + if ( _service.ttl () != serviceRepos.first.ttl () ) { + // repoindex.xml changed ttl + if ( !serviceRepos.first.ttl() ) + serviceRepos.first.setLrf( zypp::Date() ); // don't need lrf when zero ttl + + _serviceModified = true; + } + + // service was maybe updated + _service = serviceRepos.first; + + //////////////////////////////////////////////////////////////////////////// + // On the fly remember the new repo states as defined the reopoindex.xml. + // Move into ServiceInfo later. + ServiceInfo::RepoStates newRepoStates; + + // set service alias and base url for all collected repositories + for_( it, collector.repos.begin(), collector.repos.end() ) + { + // First of all: Prepend service alias: + it->setAlias( zypp::str::form( "%s:%s", _service.alias().c_str(), it->alias().c_str() ) ); + // set reference to the parent service + it->setService( _service.alias() ); + + // remember the new parsed repo state + newRepoStates[it->alias()] = *it; + + // - If the repo url was not set by the repoindex parser, set service's url. + // - Libzypp currently has problem with separate url + path handling so just + // append a path, if set, to the baseurls + // - Credentials in the url authority will be extracted later, either if the + // repository is added or if we check for changed urls. + zypp::Pathname path; + if ( !it->path().empty() ) + { + if ( it->path() != "/" ) + path = it->path(); + it->setPath(""); + } + + if ( it->baseUrlsEmpty() ) + { + zypp::Url url( _service.rawUrl() ); + if ( !path.empty() ) + url.setPathName( url.getPathName() / path ); + it->setBaseUrl( std::move(url) ); + } + else if ( !path.empty() ) + { + RepoInfo::url_set urls( it->rawBaseUrls() ); + for ( zypp::Url & url : urls ) + { + url.setPathName( url.getPathName() / path ); + } + it->setBaseUrls( std::move(urls) ); + } + } + + //////////////////////////////////////////////////////////////////////////// + // Now compare collected repos with the ones in the system... + // + RepoInfoList oldRepos; + _repoMgr->getRepositoriesInService( _service.alias(), std::back_inserter( oldRepos ) ); + + //////////////////////////////////////////////////////////////////////////// + // find old repositories to remove... + for_( oldRepo, oldRepos.begin(), oldRepos.end() ) + { + if ( ! foundAliasIn( oldRepo->alias(), collector.repos ) ) + { + if ( oldRepo->enabled() ) + { + // Currently enabled. If this was a user modification remember the state. + const auto & last = _service.repoStates().find( oldRepo->alias() ); + if ( last != _service.repoStates().end() && ! last->second.enabled ) + { + DBG << "Service removes user enabled repo " << oldRepo->alias() << std::endl; + _service.addRepoToEnable( oldRepo->alias() ); + _serviceModified = true; + } + else + DBG << "Service removes enabled repo " << oldRepo->alias() << std::endl; + } + else + DBG << "Service removes disabled repo " << oldRepo->alias() << std::endl; + + auto remRes = _repoMgr->removeRepository( *oldRepo ); + if ( !remRes ) return Ret::error( remRes.error() ); + } + } + + + //////////////////////////////////////////////////////////////////////////// + // create missing repositories and modify existing ones if needed... + zypp::UrlCredentialExtractor urlCredentialExtractor( _repoMgr->options().rootDir ); // To collect any credentials stored in repo URLs + for_( it, collector.repos.begin(), collector.repos.end() ) + { + // User explicitly requested the repo being enabled? + // User explicitly requested the repo being disabled? + // And hopefully not both ;) If so, enable wins. + + zypp::TriBool toBeEnabled( zypp::indeterminate ); // indeterminate - follow the service request + DBG << "Service request to " << (it->enabled()?"enable":"disable") << " service repo " << it->alias() << std::endl; + + if ( _options.testFlag( zypp::RepoManagerFlags::RefreshService_restoreStatus ) ) + { + DBG << "Opt RefreshService_restoreStatus " << it->alias() << std::endl; + // this overrides any pending request! + // Remove from enable request list. + // NOTE: repoToDisable is handled differently. + // It gets cleared on each refresh. + _service.delRepoToEnable( it->alias() ); + // toBeEnabled stays indeterminate! + } + else + { + if ( _service.repoToEnableFind( it->alias() ) ) + { + DBG << "User request to enable service repo " << it->alias() << std::endl; + toBeEnabled = true; + // Remove from enable request list. + // NOTE: repoToDisable is handled differently. + // It gets cleared on each refresh. + _service.delRepoToEnable( it->alias() ); + _serviceModified = true; + } + else if ( _service.repoToDisableFind( it->alias() ) ) + { + DBG << "User request to disable service repo " << it->alias() << std::endl; + toBeEnabled = false; + } + } + + RepoInfoList::iterator oldRepo( findAlias( it->alias(), oldRepos ) ); + if ( oldRepo == oldRepos.end() ) + { + // Not found in oldRepos ==> a new repo to add + + // Make sure the service repo is created with the appropriate enablement + if ( ! indeterminate(toBeEnabled) ) + it->setEnabled( ( bool ) toBeEnabled ); + + DBG << "Service adds repo " << it->alias() << " " << (it->enabled()?"enabled":"disabled") << std::endl; + const auto &addRes = _repoMgr->addRepository( *it ); + if (!addRes) return Ret::error( addRes.error() ); + } + else + { + // ==> an exising repo to check + bool oldRepoModified = false; + + if ( indeterminate(toBeEnabled) ) + { + // No user request: check for an old user modificaton otherwise follow service request. + // NOTE: Assert toBeEnabled is boolean afterwards! + if ( oldRepo->enabled() == it->enabled() ) + toBeEnabled = it->enabled(); // service requests no change to the system + else if ( _options.testFlag( zypp::RepoManagerFlags::RefreshService_restoreStatus ) ) + { + toBeEnabled = it->enabled(); // RefreshService_restoreStatus forced + DBG << "Opt RefreshService_restoreStatus " << it->alias() << " forces " << (toBeEnabled?"enabled":"disabled") << std::endl; + } + else + { + const auto & last = _service.repoStates().find( oldRepo->alias() ); + if ( last == _service.repoStates().end() || last->second.enabled != it->enabled() ) + toBeEnabled = it->enabled(); // service request has changed since last refresh -> follow + else + { + toBeEnabled = oldRepo->enabled(); // service request unchaned since last refresh -> keep user modification + DBG << "User modified service repo " << it->alias() << " may stay " << (toBeEnabled?"enabled":"disabled") << std::endl; + } + } + } + + // changed enable? + if ( toBeEnabled == oldRepo->enabled() ) + { + DBG << "Service repo " << it->alias() << " stays " << (oldRepo->enabled()?"enabled":"disabled") << std::endl; + } + else if ( toBeEnabled ) + { + DBG << "Service repo " << it->alias() << " gets enabled" << std::endl; + oldRepo->setEnabled( true ); + oldRepoModified = true; + } + else + { + DBG << "Service repo " << it->alias() << " gets disabled" << std::endl; + oldRepo->setEnabled( false ); + oldRepoModified = true; + } + + // all other attributes follow the service request: + + // changed name (raw!) + if ( oldRepo->rawName() != it->rawName() ) + { + DBG << "Service repo " << it->alias() << " gets new NAME " << it->rawName() << std::endl; + oldRepo->setName( it->rawName() ); + oldRepoModified = true; + } + + // changed autorefresh + if ( oldRepo->autorefresh() != it->autorefresh() ) + { + DBG << "Service repo " << it->alias() << " gets new AUTOREFRESH " << it->autorefresh() << std::endl; + oldRepo->setAutorefresh( it->autorefresh() ); + oldRepoModified = true; + } + + // changed priority? + if ( oldRepo->priority() != it->priority() ) + { + DBG << "Service repo " << it->alias() << " gets new PRIORITY " << it->priority() << std::endl; + oldRepo->setPriority( it->priority() ); + oldRepoModified = true; + } + + // changed url? + { + RepoInfo::url_set newUrls( it->rawBaseUrls() ); + urlCredentialExtractor.extract( newUrls ); // Extract! to prevent passwds from disturbing the comparison below + if ( oldRepo->rawBaseUrls() != newUrls ) + { + DBG << "Service repo " << it->alias() << " gets new URLs " << newUrls << std::endl; + oldRepo->setBaseUrls( std::move(newUrls) ); + oldRepoModified = true; + } + } + + // changed gpg check settings? + // ATM only plugin services can set GPG values. + if ( _service.type() == zypp::repo::ServiceType::PLUGIN ) + { + zypp::TriBool ogpg[3]; // Gpg RepoGpg PkgGpg + zypp::TriBool ngpg[3]; + oldRepo->getRawGpgChecks( ogpg[0], ogpg[1], ogpg[2] ); + it-> getRawGpgChecks( ngpg[0], ngpg[1], ngpg[2] ); + #define Z_CHKGPG(I,N) \ + if ( ! sameTriboolState( ogpg[I], ngpg[I] ) ) \ + { \ + DBG << "Service repo " << it->alias() << " gets new "#N"Check " << ngpg[I] << std::endl; \ + oldRepo->set##N##Check( ngpg[I] ); \ + oldRepoModified = true; \ + } + Z_CHKGPG( 0, Gpg ); + Z_CHKGPG( 1, RepoGpg ); + Z_CHKGPG( 2, PkgGpg ); + #undef Z_CHKGPG + } + + // save if modified: + if ( oldRepoModified ) + { + auto modRes = _repoMgr->modifyRepository( oldRepo->alias(), *oldRepo ); + if ( !modRes ) return Ret::error( modRes.error() ); + } + } + } + + // Unlike reposToEnable, reposToDisable is always cleared after refresh. + if ( ! _service.reposToDisableEmpty() ) + { + _service.clearReposToDisable(); + _serviceModified = true; + } + + // Remember original service request for next refresh + if ( _service.repoStates() != newRepoStates ) + { + _service.setRepoStates( std::move(newRepoStates) ); + _serviceModified = true; + } + + //////////////////////////////////////////////////////////////////////////// + // save service if modified: (unless a plugin service) + if ( _service.type() != zypp::repo::ServiceType::PLUGIN ) + { + if ( _service.ttl() ) + { + _service.setLrf( zypp::Date::now() ); // remember last refresh + _serviceModified = true; // or use a cookie file + } + + if ( _serviceModified ) + { + // write out modified service file. + auto modRes = _repoMgr->modifyService( _service.alias(), _service ); + if ( !modRes ) return Ret::error( modRes.error() ); + } + } + + if ( _informalError ) { + return Ret::error( std::make_exception_ptr (_informalError.value()) ); + } + + return Ret::success( ); + }; + } + + + RepoMgrRefType _repoMgr; + zypp::ServiceInfo _service; + zypp::RepoManager::RefreshServiceOptions _options; + + // NOTE: It might be necessary to modify and rewrite the service info. + // Either when probing the type, or when adjusting the repositories + // enable/disable state.: + bool _serviceModified = false; + + // FIXME Ugly hack: ServiceRepos may throw ServicePluginInformalException + // which is actually a notification. Using an exception for this + // instead of signal/callback is bad. Needs to be fixed here, in refreshServices() + // and in zypper. + std::optional _informalError; + }; + } + + AsyncOpRef> refreshService(AsyncRepoManagerRef repoMgr, ServiceInfo info, zypp::RepoManagerFlags::RefreshServiceOptions options) + { + return SimpleExecutor>>::run( std::move(repoMgr), std::move(info), std::move(options) ); + } + + expected refreshService(SyncRepoManagerRef repoMgr, ServiceInfo info, zypp::RepoManagerFlags::RefreshServiceOptions options) + { + return SimpleExecutor>>::run( std::move(repoMgr), std::move(info), std::move(options) ); + } + +} diff --git a/zypp/ng/repo/workflows/serviceswf.h b/zypp/ng/repo/workflows/serviceswf.h new file mode 100644 index 0000000..15111ee --- /dev/null +++ b/zypp/ng/repo/workflows/serviceswf.h @@ -0,0 +1,43 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_SERVICES_WORKFLOW_INCLUDED +#define ZYPP_NG_SERVICES_WORKFLOW_INCLUDED + +#include + +#include +#include + +#include +#include + +#include +#include + + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (Context); + ZYPP_FWD_DECL_TYPE_WITH_REFS (SyncContext); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProgressObserver); + + namespace RepoServicesWorkflow { + AsyncOpRef>> fetchRepoListfromService( ContextRef ctx, zypp::Pathname root_r, ServiceInfo service, ProgressObserverRef myProgress = nullptr ); + expected> fetchRepoListfromService( SyncContextRef ctx, zypp::Pathname root_r, ServiceInfo service, ProgressObserverRef myProgress = nullptr ); + + AsyncOpRef > probeServiceType( ContextRef ctx, const zypp::Url &url ); + expected probeServiceType ( SyncContextRef ctx, const zypp::Url &url ); + + AsyncOpRef> refreshService ( AsyncRepoManagerRef repoMgr, zypp::ServiceInfo info, zypp::RepoManagerFlags::RefreshServiceOptions options ); + expected refreshService ( SyncRepoManagerRef repoMgr, zypp::ServiceInfo info, zypp::RepoManagerFlags::RefreshServiceOptions options ); + } +} // namespace zyppng; + + +#endif diff --git a/zypp/ng/repo/workflows/susetags.cc b/zypp/ng/repo/workflows/susetags.cc new file mode 100644 index 0000000..1122d1e --- /dev/null +++ b/zypp/ng/repo/workflows/susetags.cc @@ -0,0 +1,340 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "susetags.h" +#include "zypp-core/base/Regex.h" +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +namespace zyppng::SuseTagsWorkflows { + + namespace { + + using namespace zyppng::operators; + + /*! + * Implementation of the susetags status calculation logic + * + * \TODO this is basically the same as the RPMMD workflow with changed filenames, can we unite them? + */ + template + struct StatusLogic : public LogicBase{ + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + + using DlContextRefType = std::conditional_t, repo::AsyncDownloadContextRef, repo::SyncDownloadContextRef>; + using ZyppContextType = typename DlContextRefType::element_type::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + StatusLogic( DlContextRefType ctx, MediaHandle &&media ) + : _ctx(std::move(ctx)) + , _handle(std::move(media)) + {} + + MaybeAsyncRef> execute() { + return _ctx->zyppContext()->provider()->provide( _handle, _ctx->repoInfo().path() / "content" , ProvideFileSpec() ) + | [this]( expected contentFile ) { + + // mandatory master index is missing -> stay empty + if ( !contentFile ) + return makeReadyResult( make_expected_success (zypp::RepoStatus() )); + + zypp::RepoStatus status ( contentFile->file() ); + + if ( !status.empty() /* && _ctx->repoInfo().requireStatusWithMediaFile() */ ) { + return _ctx->zyppContext()->provider()->provide( _handle, "/media.1/media" , ProvideFileSpec()) + | [status = std::move(status)]( expected mediaFile ) mutable { + if ( mediaFile ) { + return make_expected_success(status && zypp::RepoStatus( mediaFile->file()) ); + } + return make_expected_success( std::move(status) ); + }; + } + return makeReadyResult( make_expected_success(std::move(status)) ); + }; + } + + DlContextRefType _ctx; + MediaHandle _handle; + }; + } + + AsyncOpRef > repoStatus(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle) + { + return SimpleExecutor< StatusLogic, AsyncOp> >::run( std::move(dl), std::move(mediaHandle) ); + } + + expected repoStatus(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle) + { + return SimpleExecutor< StatusLogic, SyncOp> >::run( std::move(dl), std::move(mediaHandle) ); + } + + + + namespace { + + using namespace zyppng::operators; + + // search old repository file file to run the delta algorithm on + static zypp::Pathname search_deltafile( const zypp::Pathname &dir, const zypp::Pathname &file ) + { + zypp::Pathname deltafile(dir + file.basename()); + if (zypp::PathInfo(deltafile).isExist()) + return deltafile; + return zypp::Pathname(); + } + + + template + struct DlLogic : public LogicBase { + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + public: + + using DlContextRefType = std::conditional_t, repo::AsyncDownloadContextRef, repo::SyncDownloadContextRef>; + using ZyppContextType = typename DlContextRefType::element_type::ContextType; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + DlLogic( DlContextRefType ctx, MediaHandle &&mediaHandle, ProgressObserverRef &&progressObserver ) + : _ctx( std::move(ctx)) + , _mediaHandle(std::move(mediaHandle)) + , _progressObserver(std::move(progressObserver)) + {} + + auto execute() { + // download media file here + return RepoDownloaderWorkflow::downloadMediaInfo( _mediaHandle, _ctx->destDir() ) + | [this]( expected &&mediaInfo ) { + + // remember the media info if we had one + if ( mediaInfo ) _ctx->files().push_back ( std::move(mediaInfo.get()) ); + + if ( _progressObserver ) _progressObserver->inc(); + + return RepoDownloaderWorkflow::downloadMasterIndex( _ctx, _mediaHandle, _ctx->repoInfo().path() / "content" ) + | inspect( incProgress( _progressObserver ) ) + | and_then( [this] ( DlContextRefType && ) { + + zypp::Pathname contentPath = _ctx->files().front(); + std::vector requiredFiles; + + // Content file first to get the repoindex + try { + const zypp::Pathname &inputfile = contentPath; + zypp::parser::susetags::ContentFileReader content; + content.setRepoIndexConsumer( [this]( const auto & data_r ) { + MIL << "Consuming repo index" << std::endl; + _repoindex = data_r; + }); + content.parse( inputfile ); + + if ( ! _repoindex ) { + ZYPP_THROW( zypp::parser::ParseException( ( _ctx->destDir() / _ctx->repoInfo().path() ).asString() + ": " + "No repository index in content file." ) ); + } + + MIL << "RepoIndex: " << _repoindex << std::endl; + if ( _repoindex->metaFileChecksums.empty() ) { + ZYPP_THROW( zypp::parser::ParseException( ( _ctx->destDir() / _ctx->repoInfo().path() ).asString() + ": " + "No metadata checksums in content file." ) ); + } + + if ( _repoindex->signingKeys.empty() ) { + WAR << "No signing keys defined." << std::endl; + } + + // Prepare parsing + zypp::Pathname descr_dir = _repoindex->descrdir; // path below reporoot + //_datadir = _repoIndex->datadir; // path below reporoot + + std::map availablePackageTranslations; + + for_( it, _repoindex->metaFileChecksums.begin(), _repoindex->metaFileChecksums.end() ) + { + // omit unwanted translations + if ( zypp::str::hasPrefix( it->first, "packages" ) ) + { + static const zypp::str::regex rx_packages( "^packages((.gz)?|(.([^.]*))(.gz)?)$" ); + zypp::str::smatch what; + + if ( zypp::str::regex_match( it->first, what, rx_packages ) ) { + if ( what[4].empty() // packages(.gz)? + || what[4] == "DU" + || what[4] == "en" ) + { ; /* always downloaded */ } + else if ( what[4] == "FL" ) + { continue; /* never downloaded */ } + else + { + // remember and decide later + availablePackageTranslations[what[4]] = it; + continue; + } + } + else + continue; // discard + + } else if ( it->first == "patterns.pat" + || it->first == "patterns.pat.gz" ) { + // take all patterns in one go + + } else if ( zypp::str::endsWith( it->first, ".pat" ) + || zypp::str::endsWith( it->first, ".pat.gz" ) ) { + + // *** see also zypp/parser/susetags/RepoParser.cc *** + + // omit unwanted patterns, see https://bugzilla.novell.com/show_bug.cgi?id=298716 + // expect "..pat[.gz]", might contain additional dots + // split at dots, take .pat or .pat.gz into account + + std::vector patparts; + unsigned archpos = 2; + // expect "..pat[.gz]", might contain additional dots + unsigned count = zypp::str::split( it->first, std::back_inserter(patparts), "." ); + if ( patparts[count-1] == "gz" ) + archpos++; + + if ( count > archpos ) { + try { // might by an invalid architecture + zypp::Arch patarch( patparts[count-archpos] ); + if ( !patarch.compatibleWith( zConfig().systemArchitecture() ) ) { + // discard, if not compatible + MIL << "Discarding pattern " << it->first << std::endl; + continue; + } + + } catch ( const zypp::Exception & excpt ) { + WAR << "Pattern file name does not contain recognizable architecture: " << it->first << std::endl; + // keep .pat file if it doesn't contain an recognizable arch + } + } + } + + MIL << "adding job " << it->first << std::endl; + auto location = zypp::OnMediaLocation( repoInfo().path() + descr_dir + it->first, 1 ) + .setChecksum( it->second ) + .setDeltafile( search_deltafile( _ctx->deltaDir() + descr_dir, it->first) ); + + requiredFiles.push_back( std::move(location) ); + } + + + // check whether to download more package translations: + { + auto fnc_checkTransaltions( [&]( const zypp::Locale & locale_r ) { + for ( zypp::Locale toGet( locale_r ); toGet; toGet = toGet.fallback() ) { + auto it( availablePackageTranslations.find( toGet.code() ) ); + if ( it != availablePackageTranslations.end() ) { + auto mit( it->second ); + MIL << "adding job " << mit->first << std::endl; + requiredFiles.push_back( zypp::OnMediaLocation( repoInfo().path() + descr_dir + mit->first, 1 ) + .setChecksum( mit->second ) + .setDeltafile( search_deltafile( deltaDir() + descr_dir, mit->first) )); + break; + } + } + }); + + for ( const zypp::Locale & it : zConfig().repoRefreshLocales() ) { + fnc_checkTransaltions( it ); + } + fnc_checkTransaltions( zConfig().textLocale() ); + } + + for( const auto &it : _repoindex->mediaFileChecksums ) { + // Repo adopts license files listed in HASH + if ( it.first != "license.tar.gz" ) + continue; + + MIL << "adding job " << it.first << std::endl; + requiredFiles.push_back( zypp::OnMediaLocation ( repoInfo().path() + it.first, 1 ) + .setChecksum( it.second ) + .setDeltafile( search_deltafile( deltaDir(), it.first ) )); + } + + for( const auto &it : _repoindex->signingKeys ) { + MIL << "adding job " << it.first << std::endl; + zypp::OnMediaLocation location( repoInfo().path() + it.first, 1 ); + location.setChecksum( it.second ); + requiredFiles.push_back( std::move(location) ); + } + + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT( e ); + return makeReadyResult(expected::error( ZYPP_FWD_CURRENT_EXCPT() ) ); + } catch ( ... ) { + return makeReadyResult(expected::error( ZYPP_FWD_CURRENT_EXCPT() ) ); + } + + // add the required files to the base steps + if ( _progressObserver ) _progressObserver->setBaseSteps ( _progressObserver->baseSteps () + requiredFiles.size() ); + + return transform_collect ( std::move(requiredFiles), [this]( zypp::OnMediaLocation file ) { + + return DownloadWorkflow::provideToCacheDir( _ctx, _mediaHandle, file.filename(), ProvideFileSpec(file) ) + | inspect ( incProgress( _progressObserver ) ); + + }) | and_then ( [this]( std::vector &&dlFiles ) { + auto &downloadedFiles = _ctx->files(); + downloadedFiles.insert( downloadedFiles.end(), std::make_move_iterator(dlFiles.begin()), std::make_move_iterator(dlFiles.end()) ); + return expected::success( std::move(_ctx) ); + }); + }); + + } | finishProgress( _progressObserver ); + } + + private: + + const zypp::RepoInfo &repoInfo() const { + return _ctx->repoInfo(); + } + + const zypp::filesystem::Pathname &deltaDir() const { + return _ctx->deltaDir(); + } + + zypp::ZConfig &zConfig() { + return _ctx->zyppContext()->config(); + } + + DlContextRefType _ctx; + zypp::parser::susetags::RepoIndex_Ptr _repoindex; + MediaHandle _mediaHandle; + ProgressObserverRef _progressObserver; + }; + } + + AsyncOpRef > download(repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return SimpleExecutor< DlLogic, AsyncOp> >::run( std::move(dl), std::move(mediaHandle), std::move(progressObserver) ); + } + + expected download(repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver) + { + return SimpleExecutor< DlLogic, SyncOp> >::run( std::move(dl), std::move(mediaHandle), std::move(progressObserver) ); + } + +} diff --git a/zypp/ng/repo/workflows/susetags.h b/zypp/ng/repo/workflows/susetags.h new file mode 100644 index 0000000..eb400a6 --- /dev/null +++ b/zypp/ng/repo/workflows/susetags.h @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_SUSETAGS_WORKFLOW_INCLUDED +#define ZYPP_NG_SUSETAGS_WORKFLOW_INCLUDED + +#include +#include +#include +#include + +#include + + +namespace zyppng { + class ProvideMediaHandle; + class SyncMediaHandle; + + ZYPP_FWD_DECL_TYPE_WITH_REFS( ProgressObserver ); + + /** + * \short Download workflow namespace for SUSETags (YaST2) repositories + * Encapsulates all the knowledge of which files have + * to be downloaded to the local disk and how to calculate the repo status. + */ + namespace SuseTagsWorkflows { + + /*! + * Calculate status of the remote SUSETags repository + */ + AsyncOpRef> repoStatus( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle ); + expected repoStatus( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle ); + + /*! + * Download metadata to a local directory + */ + AsyncOpRef> download ( repo::AsyncDownloadContextRef dl, ProvideMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + expected download ( repo::SyncDownloadContextRef dl, SyncMediaHandle mediaHandle, ProgressObserverRef progressObserver = nullptr ); + } +} + + + +#endif // ZYPP_NG_SUSETAGS_WORKFLOW_INCLUDED diff --git a/zypp/ng/repomanager.cc b/zypp/ng/repomanager.cc new file mode 100644 index 0000000..981a591 --- /dev/null +++ b/zypp/ng/repomanager.cc @@ -0,0 +1,1479 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "repomanager.h" +#include "zypp-core/ExternalProgram.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::repomanager" + +namespace zypp::zypp_readonly_hack { + bool IGotIt(); // in readonly-mode +} + + +namespace zyppng +{ + namespace env + { + /** To trigger appdata refresh unconditionally */ + inline bool ZYPP_PLUGIN_APPDATA_FORCE_COLLECT() + { + const char * env = getenv("ZYPP_PLUGIN_APPDATA_FORCE_COLLECT"); + return( env && zypp::str::strToBool( env, true ) ); + } + } // namespace env + + namespace { + /** Delete \a cachePath_r subdirs not matching known aliases in \a repoEscAliases_r (must be sorted!) + * \note bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise + * we'd need some magic file to identify zypp cache directories. Without this + * we may easily remove user data (zypper --pkg-cache-dir . download ...) + */ + inline void cleanupNonRepoMetadataFolders( const zypp::Pathname & cachePath_r, + const zypp::Pathname & defaultCachePath_r, + const std::list & repoEscAliases_r ) + { + if ( cachePath_r != defaultCachePath_r ) + return; + + std::list entries; + if ( zypp::filesystem::readdir( entries, cachePath_r, false ) == 0 ) + { + entries.sort(); + std::set oldfiles; + set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(), + std::inserter( oldfiles, oldfiles.end() ) ); + + // bsc#1178966: Files or symlinks here have been created by the user + // for whatever purpose. It's our cache, so we purge them now before + // they may later conflict with directories we need. + zypp::PathInfo pi; + for ( const std::string & old : oldfiles ) + { + if ( old == zypp::Repository::systemRepoAlias() ) // don't remove the @System solv file + continue; + pi( cachePath_r/old ); + if ( pi.isDir() ) + zypp::filesystem::recursive_rmdir( pi.path() ); + else + zypp::filesystem::unlink( pi.path() ); + } + } + } + } // namespace + + std::ostream & operator<<( std::ostream & str, zypp::RepoManagerFlags::RawMetadataRefreshPolicy obj ) + { + switch ( obj ) { +#define OUTS(V) case zypp::RepoManagerFlags::V: str << #V; break + OUTS( RefreshIfNeeded ); + OUTS( RefreshForced ); + OUTS( RefreshIfNeededIgnoreDelay ); +#undef OUTS + } + return str; + } + + std::ostream & operator<<( std::ostream & str, zypp::RepoManagerFlags::RefreshCheckStatus obj ) + { + switch ( obj ) { +#define OUTS(V) case zypp::RepoManagerFlags::V: str << #V; break + OUTS( REFRESH_NEEDED ); + OUTS( REPO_UP_TO_DATE ); + OUTS( REPO_CHECK_DELAYED ); +#undef OUTS + } + return str; + } + + std::ostream & operator<<( std::ostream & str, zypp::RepoManagerFlags::CacheBuildPolicy obj ) + { + switch ( obj ) { +#define OUTS(V) case zypp::RepoManagerFlags::V: str << #V; break + OUTS( BuildIfNeeded ); + OUTS( BuildForced ); +#undef OUTS + } + return str; + } + + + std::string filenameFromAlias(const std::string &alias_r, const std::string &stem_r) + { + std::string filename( alias_r ); + // replace slashes with underscores + zypp::str::replaceAll( filename, "/", "_" ); + + filename = zypp::Pathname(filename).extend("."+stem_r).asString(); + MIL << "generating filename for " << stem_r << " [" << alias_r << "] : '" << filename << "'" << std::endl; + return filename; + } + + bool RepoCollector::collect(const RepoInfo &repo) + { + // skip repositories meant for other distros than specified + if (!targetDistro.empty() + && !repo.targetDistribution().empty() + && repo.targetDistribution() != targetDistro) + { + MIL + << "Skipping repository meant for '" << repo.targetDistribution() + << "' distribution (current distro is '" + << targetDistro << "')." << std::endl; + + return true; + } + + repos.push_back(repo); + return true; + } + + expected> repositories_in_file(const zypp::Pathname &file) + { + try { + MIL << "repo file: " << file << std::endl; + RepoCollector collector; + zypp::parser::RepoFileReader parser( file, std::bind( &RepoCollector::collect, &collector, std::placeholders::_1 ) ); + return expected>::success( std::move(collector.repos) ); + } catch ( ... ) { + return expected>::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + + /** + * \short List of RepoInfo's from a directory + * + * Goes trough every file ending with ".repo" in a directory and adds all + * RepoInfo's contained in that file. + * + * \param zyppContext current context used for reports + * \param dir pathname of the directory to read. + */ + template + std::list repositories_in_dir( ZContextRef zyppContext, const zypp::Pathname &dir ) + { + MIL << "directory " << dir << std::endl; + std::list repos; + bool nonroot( geteuid() != 0 ); + if ( nonroot && ! zypp::PathInfo(dir).userMayRX() ) + { + JobReportHelper(zyppContext).warning( zypp::str::Format(_("Cannot read repo directory '%1%': Permission denied")) % dir ); + } + else + { + std::list entries; + if ( zypp::filesystem::readdir( entries, dir, false ) != 0 ) + { + // TranslatorExplanation '%s' is a pathname + ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str()))); + } + + zypp::str::regex allowedRepoExt("^\\.repo(_[0-9]+)?$"); + for ( std::list::const_iterator it = entries.begin(); it != entries.end(); ++it ) + { + if ( zypp::str::regex_match(it->extension(), allowedRepoExt) ) + { + if ( nonroot && ! zypp::PathInfo(*it).userMayR() ) + { + JobReportHelper(zyppContext).warning( zypp::str::Format(_("Cannot read repo file '%1%': Permission denied")) % *it ); + } + else + { + const std::list tmp( repositories_in_file( *it ).unwrap() ); + repos.insert( repos.end(), tmp.begin(), tmp.end() ); + } + } + } + } + return repos; + } + + expected assert_urls(const RepoInfo &info) + { + if ( info.baseUrlsEmpty() ) + return expected::error( ZYPP_EXCPT_PTR ( zypp::repo::RepoNoUrlException( info ) ) ); + return expected::success(); + } + + bool autoPruneInDir(const zypp::Pathname &path_r) + { return not zypp::PathInfo(path_r/".no_auto_prune").isExist(); } + + + template + RepoManager::RepoManager( ZYPP_PRIVATE_CONSTR_ARG, ZyppContextRefType zyppCtx, RepoManagerOptions opt ) + : _zyppContext( std::move(zyppCtx) ) + , _options( std::move(opt) ) + , _pluginRepoverification( _options.pluginsPath / "repoverification", + _options.rootDir) + { + + } + + template + RepoManager::~RepoManager() + { + // trigger appdata refresh if some repos change + if ( ( _reposDirty || env::ZYPP_PLUGIN_APPDATA_FORCE_COLLECT() ) + && geteuid() == 0 && ( _options.rootDir.empty() || _options.rootDir == "/" ) ) + { + try { + std::list entries; + zypp::filesystem::readdir( entries, _options.pluginsPath/"appdata", false ); + if ( ! entries.empty() ) + { + zypp::ExternalProgram::Arguments cmd; + cmd.push_back( "<" ); // discard stdin + cmd.push_back( ">" ); // discard stdout + cmd.push_back( "PROGRAM" ); // [2] - fix index below if changing! + for ( const auto & rinfo : repos() ) + { + if ( ! rinfo.enabled() ) + continue; + cmd.push_back( "-R" ); + cmd.push_back( rinfo.alias() ); + cmd.push_back( "-t" ); + cmd.push_back( rinfo.type().asString() ); + cmd.push_back( "-p" ); + cmd.push_back( (rinfo.metadataPath()/rinfo.path()).asString() ); // bsc#1197684: path to the repodata/ directory inside the cache + } + + for_( it, entries.begin(), entries.end() ) + { + zypp::PathInfo pi( *it ); + //DBG << "/tmp/xx ->" << pi << endl; + if ( pi.isFile() && pi.userMayRX() ) + { + // trigger plugin + cmd[2] = pi.asString(); // [2] - PROGRAM + zypp::ExternalProgram prog( cmd, zypp::ExternalProgram::Stderr_To_Stdout ); + } + } + } + } + catch (...) {} // no throw in dtor + } + } + + template + expected RepoManager::initialize() + { + using namespace zyppng::operators; + return + init_knownServices() + | and_then( [this](){ return init_knownRepositories(); } ); + } + + template + const RepoManagerOptions &RepoManager::options() const + { + return _options; + } + + template + expected RepoManager::metadataStatus(const RepoInfo & info , const RepoManagerOptions &options) + { + try { + using namespace zyppng::operators; + + // ATTENTION when making this pipeline async + // consider moving it into a workflow object + // this var is caputured by ref to modify it from + // inside the pipeline, which would break. + zypp::Pathname mediarootpath; + + return rawcache_path_for_repoinfo( options, info ) + | and_then( [&]( zypp::Pathname mrPath ) { + mediarootpath = std::move(mrPath); + return rawproductdata_path_for_repoinfo( options, info ); + }) + | and_then( [&]( zypp::Pathname productdatapath ) { + zypp::repo::RepoType repokind = info.type(); + // If unknown, probe the local metadata + if ( repokind == zypp::repo::RepoType::NONE ) + repokind = probeCache( productdatapath ); + + // NOTE: The calling code expects an empty RepoStatus being returned + // if the metadata cache is empty. So additional components like the + // RepoInfos status are joined after the switch IFF the status is not + // empty.huhu + RepoStatus status; + switch ( repokind.toEnum() ) + { + case zypp::repo::RepoType::RPMMD_e : + status = RepoStatus( productdatapath/"repodata/repomd.xml"); + if ( info.requireStatusWithMediaFile() ) + status = status && RepoStatus( mediarootpath/"media.1/media" ); + break; + + case zypp::repo::RepoType::YAST2_e : + status = RepoStatus( productdatapath/"content" ) && RepoStatus( mediarootpath/"media.1/media" ); + break; + + case zypp::repo::RepoType::RPMPLAINDIR_e : + // Dir status at last refresh. Plaindir uses the cookiefile as pseudo metadata index file. + // It gets touched if the refresh check finds the data being up-to-date. That's why we use + // the files mtime as timestamp (like the RepoStatus ctor in the other cases above). + status = RepoStatus::fromCookieFileUseMtime( productdatapath/"cookie" ); + break; + + case zypp::repo::RepoType::NONE_e : + // Return default RepoStatus in case of RepoType::NONE + // indicating it should be created? + // ZYPP_THROW(RepoUnknownTypeException()); + break; + } + + if ( ! status.empty() ) + status = status && RepoStatus( info ); + + return expected::success(status); + }); + } catch (...) { + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + + template + expected RepoManager::metadataStatus(const RepoInfo &info) const + { + return metadataStatus( info, _options ); + } + + template + expected RepoManager::cleanMetadata(const RepoInfo &info, ProgressObserverRef myProgress ) + { + try { + + ProgressObserver::setup( myProgress, _("Cleaning metadata"), 100 ); + ProgressObserver::start( myProgress ); + zypp::filesystem::recursive_rmdir( _zyppContext->config().geoipCachePath() ); + ProgressObserver::setCurrent ( myProgress, 50 ); + zypp::filesystem::recursive_rmdir( rawcache_path_for_repoinfo(_options, info).unwrap() ); + ProgressObserver::finish ( myProgress ); + + } catch ( ... ) { + ProgressObserver::finish ( myProgress, ProgressObserver::Error ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + return expected::success(); + } + + template + expected RepoManager::cleanPackages(const RepoInfo &info, ProgressObserverRef myProgress, bool isAutoClean ) + { + try { + ProgressObserver::setup( myProgress, _("Cleaning packages"), 100 ); + ProgressObserver::start( myProgress ); + + // bsc#1204956: Tweak to prevent auto pruning package caches + zypp::Pathname rpc { packagescache_path_for_repoinfo(_options, info).unwrap() }; + if ( not isAutoClean || autoPruneInDir( rpc.dirname() ) ) + zypp::filesystem::recursive_rmdir( rpc ); + + ProgressObserver::finish ( myProgress ); + + } catch (...) { + ProgressObserver::finish ( myProgress, ProgressObserver::Error ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + + return expected::success(); + } + + /** Probe Metadata in a local cache directory + * + * \note Metadata in local cache directories must not be probed using \ref probe as + * a cache path must not be rewritten (bnc#946129) + */ + template + zypp::repo::RepoType RepoManager::probeCache( const zypp::Pathname & path_r ) + { + MIL << "going to probe the cached repo at " << path_r << std::endl; + + zypp::repo::RepoType ret = zypp::repo::RepoType::NONE; + + if ( zypp::PathInfo(path_r/"/repodata/repomd.xml").isFile() ) + { ret = zypp::repo::RepoType::RPMMD; } + else if ( zypp::PathInfo(path_r/"/content").isFile() ) + { ret = zypp::repo::RepoType::YAST2; } + else if ( zypp::PathInfo(path_r/"/cookie").isFile() ) + { ret = zypp::repo::RepoType::RPMPLAINDIR; } + + MIL << "Probed cached type " << ret << " at " << path_r << std::endl; + return ret; + } + + template + expected RepoManager::cleanCacheDirGarbage( ProgressObserverRef myProgress ) + { + try { + MIL << "Going to clean up garbage in cache dirs" << std::endl; + + std::list cachedirs; + cachedirs.push_back(_options.repoRawCachePath); + cachedirs.push_back(_options.repoPackagesCachePath); + cachedirs.push_back(_options.repoSolvCachePath); + + ProgressObserver::setup( myProgress, _("Cleaning up cache dirs"), cachedirs.size() ); + ProgressObserver::start( myProgress ); + + for( const auto &dir : cachedirs ) + { + // increase progress on end of every iteration + zypp_defer { + ProgressObserver::increase( myProgress ); + }; + + if ( zypp::PathInfo(dir).isExist() ) + { + std::list entries; + if ( zypp::filesystem::readdir( entries, dir, false ) != 0 ) + // TranslatorExplanation '%s' is a pathname + ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str()))); + + if ( !entries.size() ) + continue; + + auto dirProgress = ProgressObserver::makeSubTask( myProgress, 1.0, zypp::str::Format( _("Cleaning up directory: %1%") ) % dir, entries.size() ); + for( const auto &subdir : entries ) + { + // if it does not belong known repo, make it disappear + bool found = false; + for_( r, repoBegin(), repoEnd() ) + if ( subdir.basename() == r->escaped_alias() ) + { found = true; break; } + + if ( ! found && ( zypp::Date::now()-zypp::PathInfo(subdir).mtime() > zypp::Date::day ) ) + zypp::filesystem::recursive_rmdir( subdir ); + + ProgressObserver::increase( dirProgress ); + } + ProgressObserver::finish( dirProgress ); + } + } + } catch (...) { + // will finish all subprogress children + ProgressObserver::finish ( myProgress, ProgressObserver::Error ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + ProgressObserver::finish ( myProgress ); + return expected::success(); + } + + template + expected RepoManager::cleanCache(const RepoInfo &info, ProgressObserverRef myProgress ) + { + try { + ProgressObserver::setup( myProgress, _("Cleaning cache"), 100 ); + ProgressObserver::start( myProgress ); + + MIL << "Removing raw metadata cache for " << info.alias() << std::endl; + zypp::filesystem::recursive_rmdir(solv_path_for_repoinfo(_options, info).unwrap()); + + ProgressObserver::finish( myProgress ); + return expected::success(); + + } catch (...) { + // will finish all subprogress children + ProgressObserver::finish ( myProgress, ProgressObserver::Error ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + + template + expected RepoManager::loadFromCache( const RepoInfo & info, ProgressObserverRef myProgress ) + { + using namespace zyppng::operators; + return zyppng::mtry( [this, info, myProgress](){ + ProgressObserver::setup( myProgress, _("Loading from cache"), 3 ); + ProgressObserver::start( myProgress ); + + assert_alias(info).unwrap(); + zypp::Pathname solvfile = solv_path_for_repoinfo(_options, info).unwrap() / "solv"; + + if ( ! zypp::PathInfo(solvfile).isExist() ) + ZYPP_THROW(zypp::repo::RepoNotCachedException(info)); + + _zyppContext->satPool().reposErase( info.alias() ); + + ProgressObserver::increase ( myProgress ); + + zypp::Repository repo = _zyppContext->satPool().addRepoSolv( solvfile, info ); + + ProgressObserver::increase ( myProgress ); + + // test toolversion in order to rebuild solv file in case + // it was written by a different libsolv-tool parser. + const std::string & toolversion( zypp::sat::LookupRepoAttr( zypp::sat::SolvAttr::repositoryToolVersion, repo ).begin().asString() ); + if ( toolversion != LIBSOLV_TOOLVERSION ) { + repo.eraseFromPool(); + ZYPP_THROW(zypp::Exception(zypp::str::Str() << "Solv-file was created by '"<satPool().addRepoSolv( solv_path_for_repoinfo(_options, info).unwrap() / "solv", info ); + })); + }) + | and_then([myProgress]{ + ProgressObserver::finish ( myProgress ); + return expected::success(); + }) + | or_else([myProgress]( auto ex ){ + ProgressObserver::finish ( myProgress, ProgressObserver::Error ); + return expected::error(ex); + }) + ; + } + + template + expected RepoManager::addProbedRepository( RepoInfo info, zypp::repo::RepoType probedType ) + { + try { + auto tosave = info; + + // assert the directory exists + zypp::filesystem::assert_dir(_options.knownReposPath); + + zypp::Pathname repofile = generateNonExistingName( + _options.knownReposPath, generateFilename(tosave)); + // now we have a filename that does not exists + MIL << "Saving repo in " << repofile << std::endl; + + std::ofstream file(repofile.c_str()); + if (!file) + { + // TranslatorExplanation '%s' is a filename + ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), repofile.c_str() ))); + } + + tosave.dumpAsIniOn(file); + tosave.setFilepath(repofile); + tosave.setMetadataPath( rawcache_path_for_repoinfo( _options, tosave ).unwrap() ); + tosave.setPackagesPath( packagescache_path_for_repoinfo( _options, tosave ).unwrap() ); + reposManip().insert(tosave); + + // check for credentials in Urls + zypp::UrlCredentialExtractor( _options.rootDir ).collect( tosave.baseUrls() ); + + zypp::HistoryLog(_options.rootDir).addRepository(tosave); + + // return the new repoinfo + return expected::success( tosave ); + + } catch (...) { + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + + template + expected RepoManager::removeRepository( const RepoInfo & info, ProgressObserverRef myProgress ) + { + try { + ProgressObserver::setup( myProgress, zypp::str::form(_("Removing repository '%s'"), info.label().c_str()), 1 ); + ProgressObserver::start( myProgress ); + + MIL << "Going to delete repo " << info.alias() << std::endl; + + for( const auto &repo : repos() ) + { + // they can be the same only if the provided is empty, that means + // the provided repo has no alias + // then skip + if ( (!info.alias().empty()) && ( info.alias() != repo.alias() ) ) + continue; + + // TODO match by url + + // we have a matching repository, now we need to know + // where it does come from. + RepoInfo todelete = repo; + if (todelete.filepath().empty()) + { + ZYPP_THROW(zypp::repo::RepoException( todelete, _("Can't figure out where the repo is stored.") )); + } + else + { + // figure how many repos are there in the file: + std::list filerepos = repositories_in_file(todelete.filepath()).unwrap(); + if ( filerepos.size() == 0 // bsc#984494: file may have already been deleted + ||(filerepos.size() == 1 && filerepos.front().alias() == todelete.alias() ) ) + { + // easy: file does not exist, contains no or only the repo to delete: delete the file + int ret = zypp::filesystem::unlink( todelete.filepath() ); + if ( ! ( ret == 0 || ret == ENOENT ) ) + { + // TranslatorExplanation '%s' is a filename + ZYPP_THROW(zypp::repo::RepoException( todelete, zypp::str::form( _("Can't delete '%s'"), todelete.filepath().c_str() ))); + } + MIL << todelete.alias() << " successfully deleted." << std::endl; + } + else + { + // there are more repos in the same file + // write them back except the deleted one. + //TmpFile tmp; + //std::ofstream file(tmp.path().c_str()); + + // assert the directory exists + zypp::filesystem::assert_dir(todelete.filepath().dirname()); + + std::ofstream file(todelete.filepath().c_str()); + if (!file) + { + // TranslatorExplanation '%s' is a filename + ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), todelete.filepath().c_str() ))); + } + for ( std::list::const_iterator fit = filerepos.begin(); + fit != filerepos.end(); + ++fit ) + { + if ( (*fit).alias() != todelete.alias() ) + (*fit).dumpAsIniOn(file); + } + } + + // now delete it from cache + if ( isCached(todelete) ) + cleanCache( todelete, ProgressObserver::makeSubTask( myProgress, 0.2 )).unwrap(); + // now delete metadata (#301037) + cleanMetadata( todelete, ProgressObserver::makeSubTask( myProgress, 0.4 )).unwrap(); + cleanPackages( todelete, ProgressObserver::makeSubTask( myProgress, 0.4 ), true/*isAutoClean*/ ).unwrap(); + reposManip().erase(todelete); + MIL << todelete.alias() << " successfully deleted." << std::endl; + zypp::HistoryLog(_options.rootDir).removeRepository(todelete); + + ProgressObserver::finish(myProgress); + return expected::success(); + } // else filepath is empty + } + // should not be reached on a sucess workflow + ZYPP_THROW(zypp::repo::RepoNotFoundException(info)); + } catch (...) { + ProgressObserver::finish( myProgress, ProgressObserver::Error ); + return expected::error( std::current_exception () ); + } + } + + template + expected RepoManager::modifyRepository( const std::string & alias, const RepoInfo & newinfo_r, ProgressObserverRef myProgress ) + { + try { + + ProgressObserver::setup( myProgress, _("Modifying repository"), 5 ); + ProgressObserver::start( myProgress ); + + RepoInfo toedit = getRepositoryInfo(alias).unwrap(); + RepoInfo newinfo( newinfo_r ); // need writable copy to upadte housekeeping data + + // check if the new alias already exists when renaming the repo + if ( alias != newinfo.alias() && hasRepo( newinfo.alias() ) ) + { + ZYPP_THROW(zypp::repo::RepoAlreadyExistsException(newinfo)); + } + + if (toedit.filepath().empty()) + { + ZYPP_THROW(zypp::repo::RepoException( toedit, _("Can't figure out where the repo is stored.") )); + } + else + { + ProgressObserver::increase( myProgress ); + // figure how many repos are there in the file: + std::list filerepos = repositories_in_file(toedit.filepath()).unwrap(); + + // there are more repos in the same file + // write them back except the deleted one. + //TmpFile tmp; + //std::ofstream file(tmp.path().c_str()); + + // assert the directory exists + zypp::filesystem::assert_dir(toedit.filepath().dirname()); + + std::ofstream file(toedit.filepath().c_str()); + if (!file) + { + // TranslatorExplanation '%s' is a filename + ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), toedit.filepath().c_str() ))); + } + for ( std::list::const_iterator fit = filerepos.begin(); + fit != filerepos.end(); + ++fit ) + { + // if the alias is different, dump the original + // if it is the same, dump the provided one + if ( (*fit).alias() != toedit.alias() ) + (*fit).dumpAsIniOn(file); + else + newinfo.dumpAsIniOn(file); + } + + ProgressObserver::increase( myProgress ); + + if ( toedit.enabled() && !newinfo.enabled() ) + { + // On the fly remove solv.idx files for bash completion if a repo gets disabled. + const zypp::Pathname solvidx = solv_path_for_repoinfo(_options, newinfo).unwrap()/"solv.idx"; + if ( zypp::PathInfo(solvidx).isExist() ) + zypp::filesystem::unlink( solvidx ); + } + + newinfo.setFilepath(toedit.filepath()); + newinfo.setMetadataPath( rawcache_path_for_repoinfo( _options, newinfo ).unwrap() ); + newinfo.setPackagesPath( packagescache_path_for_repoinfo( _options, newinfo ).unwrap() ); + + ProgressObserver::increase( myProgress ); + + reposManip().erase(toedit); + reposManip().insert(newinfo); + + ProgressObserver::increase( myProgress ); + + // check for credentials in Urls + zypp::UrlCredentialExtractor( _options.rootDir ).collect( newinfo.baseUrls() ); + zypp::HistoryLog(_options.rootDir).modifyRepository(toedit, newinfo); + MIL << "repo " << alias << " modified" << std::endl; + + ProgressObserver::finish ( myProgress ); + return expected::success( newinfo ); + } + + } catch ( ... ) { + ProgressObserver::finish ( myProgress, ProgressObserver::Error ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + + template + expected RepoManager::getRepositoryInfo( const std::string & alias ) + { + try { + RepoConstIterator it( findAlias( alias, repos() ) ); + if ( it != repos().end() ) + return make_expected_success(*it); + RepoInfo info; + info.setAlias( alias ); + ZYPP_THROW( zypp::repo::RepoNotFoundException(info) ); + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + } + + + template + expected RepoManager::getRepositoryInfo( const zypp::Url & url, const zypp::url::ViewOption & urlview ) + { + try { + + for_( it, repoBegin(), repoEnd() ) + { + for_( urlit, (*it).baseUrlsBegin(), (*it).baseUrlsEnd() ) + { + if ( (*urlit).asString(urlview) == url.asString(urlview) ) + return make_expected_success(*it); + } + } + RepoInfo info; + info.setBaseUrl( url ); + ZYPP_THROW( zypp::repo::RepoNotFoundException(info) ); + + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + } + + template + expected::RefreshCheckStatus> RepoManager::checkIfToRefreshMetadata(const RepoInfo &info, const zypp::Url &url, RawMetadataRefreshPolicy policy) + { + using namespace zyppng::operators; + return joinPipeline( _zyppContext, + RepoManagerWorkflow::refreshGeoIPData( _zyppContext, {url} ) + | [this, info](auto) { return zyppng::repo::RefreshContext::create( _zyppContext, info, shared_this>() ); } + | and_then( [this, url, policy]( zyppng::repo::RefreshContextRef &&refCtx ) { + refCtx->setPolicy ( static_cast( policy ) ); + return _zyppContext->provider()->prepareMedia( url, zyppng::ProvideMediaSpec() ) + | and_then( [ r = std::move(refCtx) ]( auto mediaHandle ) mutable { return zyppng::RepoManagerWorkflow::checkIfToRefreshMetadata ( std::move(r), std::move(mediaHandle), nullptr ); } ); + }) + ); + } + + template + expected RepoManager::refreshMetadata( const RepoInfo &info, RawMetadataRefreshPolicy policy, ProgressObserverRef myProgress ) + { + using namespace zyppng::operators; + // helper callback in case the repo type changes on the remote + // do NOT capture by reference here, since this is possibly executed async + const auto &updateProbedType = [this, info = info]( zypp::repo::RepoType repokind ) { + // update probed type only for repos in system + for( const auto &repo : repos() ) { + if ( info.alias() == repo.alias() ) + { + RepoInfo modifiedrepo = repo; + modifiedrepo.setType( repokind ); + // don't modify .repo in refresh. + // modifyRepository( info.alias(), modifiedrepo ); + break; + } + } + }; + + return joinPipeline( _zyppContext, + // make sure geoIP data is up 2 date, but ignore errors + RepoManagerWorkflow::refreshGeoIPData( _zyppContext, info.baseUrls() ) + | [this, info = info](auto) { return zyppng::repo::RefreshContext::create( _zyppContext, info, shared_this>()); } + | and_then( [policy, myProgress, cb = updateProbedType]( repo::RefreshContextRef refCtx ) { + refCtx->setPolicy( static_cast( policy ) ); + // in case probe detects a different repokind, update our internal repos + refCtx->connectFunc( &repo::RefreshContext::sigProbedTypeChanged, cb ); + + return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), myProgress ); + }) + | and_then([rMgr = shared_this>()]( repo::RefreshContextRef ctx ) { + + if ( ! isTmpRepo( ctx->repoInfo() ) ) + rMgr->reposManip(); // remember to trigger appdata refresh + + return expected::success (); + })); + } + + template + std::vector>> RepoManager::refreshMetadata( std::vector infos, RawMetadataRefreshPolicy policy, ProgressObserverRef myProgress ) + { + using namespace zyppng::operators; + + ProgressObserver::setup( myProgress, "Refreshing repositories" , 1 ); + + auto r = std::move(infos) + | transform( [this, policy, myProgress]( const RepoInfo &info ) { + + auto subProgress = ProgressObserver::makeSubTask( myProgress, 1.0, zypp::str::Str() << _("Refreshing Repository: ") << info.alias(), 3 ); + + // helper callback in case the repo type changes on the remote + // do NOT capture by reference here, since this is possibly executed async + const auto &updateProbedType = [this, info = info]( zypp::repo::RepoType repokind ) { + // update probed type only for repos in system + for( const auto &repo : repos() ) { + if ( info.alias() == repo.alias() ) + { + RepoInfo modifiedrepo = repo; + modifiedrepo.setType( repokind ); + // don't modify .repo in refresh. + // modifyRepository( info.alias(), modifiedrepo ); + break; + } + } + }; + + auto sharedThis = shared_this>(); + + return + // make sure geoIP data is up 2 date, but ignore errors + RepoManagerWorkflow::refreshGeoIPData( _zyppContext, info.baseUrls() ) + | [sharedThis, info = info](auto) { return zyppng::repo::RefreshContext::create( sharedThis->_zyppContext, info, sharedThis); } + | inspect( incProgress( subProgress ) ) + | and_then( [policy, subProgress, cb = updateProbedType]( repo::RefreshContextRef refCtx ) { + refCtx->setPolicy( static_cast( policy ) ); + // in case probe detects a different repokind, update our internal repos + refCtx->connectFunc( &repo::RefreshContext::sigProbedTypeChanged, cb ); + + return zyppng::RepoManagerWorkflow::refreshMetadata ( std::move(refCtx), ProgressObserver::makeSubTask( subProgress ) ); + }) + | inspect( incProgress( subProgress ) ) + | and_then([subProgress]( repo::RefreshContextRef ctx ) { + + if ( ! isTmpRepo( ctx->repoInfo() ) ) + ctx->repoManager()->reposManip(); // remember to trigger appdata refresh + + return zyppng::RepoManagerWorkflow::buildCache ( std::move(ctx), CacheBuildPolicy::BuildIfNeeded, ProgressObserver::makeSubTask( subProgress ) ); + }) + | inspect( incProgress( subProgress ) ) + | [ info = info, subProgress ]( expected> result ) { + if ( result ) { + ProgressObserver::finish( subProgress, ProgressObserver::Success ); + return std::make_pair(info, expected::success() ); + } else { + ProgressObserver::finish( subProgress, ProgressObserver::Error ); + return std::make_pair(info, expected::error( result.error() ) ); + } + }; + } + | [myProgress]( auto res ) { + ProgressObserver::finish( myProgress, ProgressObserver::Success ); + return res; + } + ); + + return joinPipeline( _zyppContext, r ); + } + + /** Probe the metadata type of a repository located at \c url. + * Urls here may be rewritten by \ref MediaSetAccess or \ref zyppng::Provide to reflect the correct media number. + * + * \note Metadata in local cache directories must be probed using \ref probeCache as + * a cache path must not be rewritten (bnc#946129) + */ + template + expected RepoManager::probe(const zypp::Url &url, const zypp::Pathname &path) const + { + using namespace zyppng::operators; + return joinPipeline( _zyppContext, + RepoManagerWorkflow::refreshGeoIPData( _zyppContext, {url} ) + | [this, url=url](auto) { return _zyppContext->provider()->prepareMedia( url, zyppng::ProvideMediaSpec() ); } + | and_then( [this, path = path]( auto mediaHandle ) { + return RepoManagerWorkflow::probeRepoType( _zyppContext, std::forward(mediaHandle), path ); + })); + } + + template + expected RepoManager::buildCache( const RepoInfo &info, CacheBuildPolicy policy, ProgressObserverRef myProgress ) + { + using namespace zyppng::operators; + return joinPipeline( _zyppContext, + zyppng::repo::RefreshContext::create( _zyppContext, info, shared_this>() ) + | and_then( [policy, myProgress]( repo::RefreshContextRef refCtx ) { + return zyppng::RepoManagerWorkflow::buildCache ( std::move(refCtx), policy, myProgress ); + }) + | and_then([]( auto ){ return expected::success(); }) + ); + } + + template + expected RepoManager::addRepository(const RepoInfo &info, ProgressObserverRef myProgress) + { + return joinPipeline( _zyppContext, RepoManagerWorkflow::addRepository( shared_this>(), info, std::move(myProgress) ) ); + } + + template + expected RepoManager::addRepositories(const zypp::Url &url, ProgressObserverRef myProgress) + { + using namespace zyppng::operators; + return joinPipeline( _zyppContext, RepoManagerWorkflow::addRepositories( shared_this>(), url, std::move(myProgress))); + } + + template + expected RepoManager::probeService( const zypp::Url & url ) const + { + return joinPipeline( _zyppContext, RepoServicesWorkflow::probeServiceType ( _zyppContext, url ) ); + } + + template + expected RepoManager::addService( const ServiceInfo & service ) + { + try { + + assert_alias( service ).unwrap(); + + // check if service already exists + if ( hasService( service.alias() ) ) + ZYPP_THROW( zypp::repo::ServiceAlreadyExistsException( service ) ); + + // Writable ServiceInfo is needed to save the location + // of the .service file. Finaly insert into the service list. + ServiceInfo toSave( service ); + saveService( toSave ).unwrap(); + _services.insert( toSave ); + + // check for credentials in Url + zypp::UrlCredentialExtractor( _options.rootDir ).collect( toSave.url() ); + + MIL << "added service " << toSave.alias() << std::endl; + + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + + return expected::success(); + } + + template + expected RepoManager::refreshService( const std::string &alias, const RefreshServiceOptions &options_r ) + { + return joinPipeline ( _zyppContext, RepoServicesWorkflow::refreshService( shared_this>(), getService( alias ), options_r ) ); + } + + /*! + * \todo ignore ServicePluginInformalException in calling code + */ + template + expected RepoManager::refreshServices(const RefreshServiceOptions &options_r) + { + using namespace zyppng::operators; + // copy the set of services since refreshService + // can eventually invalidate the iterator + ServiceSet servicesCopy( serviceBegin(), serviceEnd() ); + + // convert the set into a vector, transform needs a container with push_back support + std::vector servicesVec; + std::copy( std::make_move_iterator(servicesCopy.begin()), std::make_move_iterator(servicesCopy.end()), std::back_inserter(servicesVec)); + + return joinPipeline( _zyppContext, + std::move(servicesVec) + | transform( [options_r, this]( ServiceInfo i ){ return RepoServicesWorkflow::refreshService( shared_this>(), i, options_r ); } ) + | join() + | collect() + ); + } + + //////////////////////////////////////////////////////////////////////////// + + template + expected RepoManager::removeService( const std::string & alias ) + { + try { + MIL << "Going to delete service " << alias << std::endl; + + const ServiceInfo & service = getService( alias ); + + zypp::Pathname location = service.filepath(); + if( location.empty() ) + { + ZYPP_THROW(zypp::repo::ServiceException( service, _("Can't figure out where the service is stored.") )); + } + + ServiceSet tmpSet; + zypp::parser::ServiceFileReader( location, ServiceCollector(tmpSet) ); + + // only one service definition in the file + if ( tmpSet.size() == 1 ) + { + if ( zypp::filesystem::unlink(location) != 0 ) + { + // TranslatorExplanation '%s' is a filename + ZYPP_THROW(zypp::repo::ServiceException( service, zypp::str::form( _("Can't delete '%s'"), location.c_str() ) )); + } + MIL << alias << " successfully deleted." << std::endl; + } + else + { + zypp::filesystem::assert_dir(location.dirname()); + + std::ofstream file(location.c_str()); + if( !file ) + { + // TranslatorExplanation '%s' is a filename + ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), location.c_str() ))); + } + + for_(it, tmpSet.begin(), tmpSet.end()) + { + if( it->alias() != alias ) + it->dumpAsIniOn(file); + } + + MIL << alias << " successfully deleted from file " << location << std::endl; + } + + // now remove all repositories added by this service + RepoCollector rcollector; + getRepositoriesInService( alias, + boost::make_function_output_iterator( std::bind( &RepoCollector::collect, &rcollector, std::placeholders::_1 ) ) ); + // cannot do this directly in getRepositoriesInService - would invalidate iterators + for_(rit, rcollector.repos.begin(), rcollector.repos.end()) + removeRepository(*rit).unwrap(); + + return expected::success(); + + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + } + + template + expected RepoManager::modifyService( const std::string & oldAlias, const ServiceInfo & newService ) + { + try { + + MIL << "Going to modify service " << oldAlias << std::endl; + + // we need a writable copy to link it to the file where + // it is saved if we modify it + ServiceInfo service(newService); + + if ( service.type() == zypp::repo::ServiceType::PLUGIN ) + { + ZYPP_THROW(zypp::repo::ServicePluginImmutableException( service )); + } + + const ServiceInfo & oldService = getService(oldAlias); + + zypp::Pathname location = oldService.filepath(); + if( location.empty() ) + { + ZYPP_THROW(zypp::repo::ServiceException( oldService, _("Can't figure out where the service is stored.") )); + } + + // remember: there may multiple services being defined in one file: + ServiceSet tmpSet; + zypp::parser::ServiceFileReader( location, ServiceCollector(tmpSet) ); + + zypp::filesystem::assert_dir(location.dirname()); + std::ofstream file(location.c_str()); + for_(it, tmpSet.begin(), tmpSet.end()) + { + if( *it != oldAlias ) + it->dumpAsIniOn(file); + } + service.dumpAsIniOn(file); + file.close(); + service.setFilepath(location); + + _services.erase(oldAlias); + _services.insert(service); + // check for credentials in Urls + zypp::UrlCredentialExtractor( _options.rootDir ).collect( service.url() ); + + + // changed properties affecting also repositories + if ( oldAlias != service.alias() // changed alias + || oldService.enabled() != service.enabled() ) // changed enabled status + { + std::vector toModify; + getRepositoriesInService(oldAlias, std::back_inserter(toModify)); + for_( it, toModify.begin(), toModify.end() ) + { + if ( oldService.enabled() != service.enabled() ) + { + if ( service.enabled() ) + { + // reset to last refreshs state + const auto & last = service.repoStates().find( it->alias() ); + if ( last != service.repoStates().end() ) + it->setEnabled( last->second.enabled ); + } + else + it->setEnabled( false ); + } + + if ( oldAlias != service.alias() ) + it->setService(service.alias()); + + modifyRepository(it->alias(), *it).unwrap(); + } + } + + return expected::success(); + + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + + //! \todo refresh the service automatically if url is changed? + } + + + template + expected RepoManager::saveService( ServiceInfo & service ) const + { + try { + + zypp::filesystem::assert_dir( _options.knownServicesPath ); + zypp::Pathname servfile = generateNonExistingName( _options.knownServicesPath, + generateFilename( service ) ); + service.setFilepath( servfile ); + + MIL << "saving service in " << servfile << std::endl; + + std::ofstream file( servfile.c_str() ); + if ( !file ) + { + // TranslatorExplanation '%s' is a filename + ZYPP_THROW( zypp::Exception(zypp::str::form( _("Can't open file '%s' for writing."), servfile.c_str() ))); + } + service.dumpAsIniOn( file ); + MIL << "done" << std::endl; + + return expected::success(); + + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + } + + /** + * Generate a non existing filename in a directory, using a base + * name. For example if a directory contains 3 files + * + * |-- bar + * |-- foo + * `-- moo + * + * If you try to generate a unique filename for this directory, + * based on "ruu" you will get "ruu", but if you use the base + * "foo" you will get "foo_1" + * + * \param dir Directory where the file needs to be unique + * \param basefilename string to base the filename on. + */ + template + zypp::Pathname RepoManager::generateNonExistingName( const zypp::Pathname & dir, + const std::string & basefilename ) const + { + std::string final_filename = basefilename; + int counter = 1; + while ( zypp::PathInfo(dir + final_filename).isExist() ) + { + final_filename = basefilename + "_" + zypp::str::numstring(counter); + ++counter; + } + return dir + zypp::Pathname(final_filename); + } + + template + expected RepoManager::touchIndexFile(const RepoInfo &info, const RepoManagerOptions &options) + { + try { + zypp::Pathname productdatapath = rawproductdata_path_for_repoinfo( options, info ).unwrap(); + + zypp::repo::RepoType repokind = info.type(); + if ( repokind.toEnum() == zypp::repo::RepoType::NONE_e ) + // unknown, probe the local metadata + repokind = probeCache( productdatapath ); + // if still unknown, just return + if (repokind == zypp::repo::RepoType::NONE_e) + return expected::success(); + + zypp::Pathname p; + switch ( repokind.toEnum() ) + { + case zypp::repo::RepoType::RPMMD_e : + p = zypp::Pathname(productdatapath + "/repodata/repomd.xml"); + break; + + case zypp::repo::RepoType::YAST2_e : + p = zypp::Pathname(productdatapath + "/content"); + break; + + case zypp::repo::RepoType::RPMPLAINDIR_e : + p = zypp::Pathname(productdatapath + "/cookie"); + break; + + case zypp::repo::RepoType::NONE_e : + default: + break; + } + + // touch the file, ignore error (they are logged anyway) + zypp::filesystem::touch(p); + } catch ( ... ) { + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + return expected::success(); + } + + template + expected RepoManager::refreshGeoIp( const RepoInfo::url_set &urls ) + { + return joinPipeline( _zyppContext, RepoManagerWorkflow::refreshGeoIPData( _zyppContext, urls) ); + } + + template + expected RepoManager::touchIndexFile( const RepoInfo & info ) + { + return touchIndexFile( info, _options ); + } + + template + expected RepoManager::init_knownServices() + { + try { + zypp::Pathname dir = _options.knownServicesPath; + std::list entries; + if (zypp::PathInfo(dir).isExist()) + { + if ( zypp::filesystem::readdir( entries, dir, false ) != 0 ) + { + // TranslatorExplanation '%s' is a pathname + ZYPP_THROW(zypp::Exception(zypp::str::form(_("Failed to read directory '%s'"), dir.c_str()))); + } + + //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$"); + for_(it, entries.begin(), entries.end() ) + { + zypp::parser::ServiceFileReader(*it, ServiceCollector(_services)); + } + } + + zypp::repo::PluginServices(_options.pluginsPath/"services", ServiceCollector(_services)); + + return expected::success(); + + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + + } + + namespace { + /** Delete \a cachePath_r subdirs not matching known aliases in \a repoEscAliases_r (must be sorted!) + * \note bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise + * we'd need some magic file to identify zypp cache directories. Without this + * we may easily remove user data (zypper --pkg-cache-dir . download ...) + * \note bsc#1210740: Don't cleanup if read-only mode was promised. + */ + inline void cleanupNonRepoMetadtaFolders( const zypp::Pathname & cachePath_r, + const zypp::Pathname & defaultCachePath_r, + const std::list & repoEscAliases_r ) + { + if ( zypp::zypp_readonly_hack::IGotIt() ) + return; + + if ( cachePath_r != defaultCachePath_r ) + return; + + std::list entries; + if ( zypp::filesystem::readdir( entries, cachePath_r, false ) == 0 ) + { + entries.sort(); + std::set oldfiles; + set_difference( entries.begin(), entries.end(), repoEscAliases_r.begin(), repoEscAliases_r.end(), + std::inserter( oldfiles, oldfiles.end() ) ); + + // bsc#1178966: Files or symlinks here have been created by the user + // for whatever purpose. It's our cache, so we purge them now before + // they may later conflict with directories we need. + zypp::PathInfo pi; + for ( const std::string & old : oldfiles ) + { + if ( old == zypp::Repository::systemRepoAlias() ) // don't remove the @System solv file + continue; + pi( cachePath_r/old ); + if ( pi.isDir() ) + zypp::filesystem::recursive_rmdir( pi.path() ); + else + zypp::filesystem::unlink( pi.path() ); + } + } + } + } // namespace + + template + expected RepoManager::init_knownRepositories() + { + try { + + MIL << "start construct known repos" << std::endl; + + if ( zypp::PathInfo(_options.knownReposPath).isExist() ) + { + std::list repoEscAliases; + std::list orphanedRepos; + for ( RepoInfo & repoInfo : repositories_in_dir( _zyppContext, _options.knownReposPath ) ) + { + // set the metadata path for the repo + repoInfo.setMetadataPath( rawcache_path_for_repoinfo(_options, repoInfo).unwrap() ); + // set the downloaded packages path for the repo + repoInfo.setPackagesPath( packagescache_path_for_repoinfo(_options, repoInfo).unwrap() ); + // remember it + _reposX.insert( repoInfo ); // direct access via _reposX in ctor! no reposManip. + + // detect orphaned repos belonging to a deleted service + const std::string & serviceAlias( repoInfo.service() ); + if ( ! ( serviceAlias.empty() || hasService( serviceAlias ) ) ) + { + WAR << "Schedule orphaned service repo for deletion: " << repoInfo << std::endl; + orphanedRepos.push_back( repoInfo ); + continue; // don't remember it in repoEscAliases + } + + repoEscAliases.push_back(repoInfo.escaped_alias()); + } + + // Cleanup orphanded service repos: + if ( ! orphanedRepos.empty() ) + { + for ( const auto & repoInfo : orphanedRepos ) + { + MIL << "Delete orphaned service repo " << repoInfo.alias() << std::endl; + // translators: Cleanup a repository previously owned by a meanwhile unknown (deleted) service. + // %1% = service name + // %2% = repository name + JobReportHelper(_zyppContext).warning( zypp::str::Format(_("Unknown service '%1%': Removing orphaned service repository '%2%'")) + % repoInfo.service() + % repoInfo.alias() ); + try { + removeRepository( repoInfo ).unwrap(); + } + catch ( const zypp::Exception & caugth ) + { + JobReportHelper(_zyppContext).error( caugth.asUserHistory() ); + } + } + } + + // bsc#1210740: Don't cleanup if read-only mode was promised. + if ( not zypp::zypp_readonly_hack::IGotIt() ) { + // delete metadata folders without corresponding repo (e.g. old tmp directories) + // + // bnc#891515: Auto-cleanup only zypp.conf default locations. Otherwise + // we'd need somemagic file to identify zypp cache directories. Without this + // we may easily remove user data (zypper --pkg-cache-dir . download ...) + repoEscAliases.sort(); + cleanupNonRepoMetadtaFolders( _options.repoRawCachePath, + zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoMetadataPath() ), + repoEscAliases ); + cleanupNonRepoMetadtaFolders( _options.repoSolvCachePath, + zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoSolvfilesPath() ), + repoEscAliases ); + // bsc#1204956: Tweak to prevent auto pruning package caches + if ( autoPruneInDir( _options.repoPackagesCachePath ) ) + cleanupNonRepoMetadtaFolders( _options.repoPackagesCachePath, + zypp::Pathname::assertprefix( _options.rootDir, _zyppContext->config().builtinRepoPackagesPath() ), + repoEscAliases ); + } + } + MIL << "end construct known repos" << std::endl; + + return expected::success(); + + } catch ( ... ) { + return expected::error( std::current_exception () ); + } + } + + // explicitely intantiate the template types we want to work with + template class RepoManager; + template class RepoManager; +} // namespace zyppng diff --git a/zypp/ng/repomanager.h b/zypp/ng/repomanager.h new file mode 100644 index 0000000..8b198da --- /dev/null +++ b/zypp/ng/repomanager.h @@ -0,0 +1,510 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/zypp_detail/repomanagerbase_p.h + * +*/ +#ifndef ZYPP_NG_REPOMANAGER_INCLUDED +#define ZYPP_NG_REPOMANAGER_INCLUDED + +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + using RepoInfo = zypp::RepoInfo; + using RepoStatus = zypp::RepoStatus; + using RepoInfoList = zypp::RepoInfoList; + using ServiceInfo = zypp::ServiceInfo; + using RepoManagerOptions = zypp::RepoManagerOptions; + + ZYPP_FWD_DECL_TYPE_WITH_REFS( Context ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( SyncContext ); + ZYPP_FWD_DECL_TYPE_WITH_REFS( ProgressObserver ); + ZYPP_FWD_DECL_TEMPL_TYPE_WITH_REFS_ARG1 ( RepoManager, ZyppContextRefType ); + + using SyncRepoManager = RepoManager; + using SyncRepoManagerRef = RepoManagerRef; + + using AsyncRepoManager = RepoManager; + using AsyncRepoManagerRef = RepoManagerRef; + + /** Whether repo is not under RM control and provides its own methadata paths. */ + inline bool isTmpRepo( const RepoInfo & info_r ) + { return( info_r.filepath().empty() && info_r.usesAutoMetadataPaths() ); } + + inline expected assert_alias(const RepoInfo &info) + { + if ( info.alias().empty() ) + return expected::error( ZYPP_EXCPT_PTR(zypp::repo::RepoNoAliasException( info ) ) ); + // bnc #473834. Maybe we can match the alias against a regex to define + // and check for valid aliases + if ( info.alias()[0] == '.') + return expected::error( ZYPP_EXCPT_PTR( zypp::repo::RepoInvalidAliasException( + info, _("Repository alias cannot start with dot."))) ); + + return expected::success(); + } + + inline expected assert_alias(const ServiceInfo &info) { + if (info.alias().empty()) + return expected::error( ZYPP_EXCPT_PTR(zypp::repo::ServiceNoAliasException(info))); + // bnc #473834. Maybe we can match the alias against a regex to define + // and check for valid aliases + if (info.alias()[0] == '.') + return expected::error( ZYPP_EXCPT_PTR(zypp::repo::ServiceInvalidAliasException( + info, _("Service alias cannot start with dot.")))); + + return expected::success(); + } + + /** Check if alias_r is present in repo/service container. */ + template + inline bool foundAliasIn( const std::string & alias_r, Iterator begin_r, Iterator end_r ) + { + for_( it, begin_r, end_r ) + if ( it->alias() == alias_r ) + return true; + return false; + } + /** \overload */ + template + inline bool foundAliasIn( const std::string & alias_r, const Container & cont_r ) + { return foundAliasIn( alias_r, cont_r.begin(), cont_r.end() ); } + + /** Find alias_r in repo/service container. */ + template + inline Iterator findAlias( const std::string & alias_r, Iterator begin_r, Iterator end_r ) + { + for_( it, begin_r, end_r ) + if ( it->alias() == alias_r ) + return it; + return end_r; + } + /** \overload */ + template + inline typename Container::iterator findAlias( const std::string & alias_r, Container & cont_r ) + { return findAlias( alias_r, cont_r.begin(), cont_r.end() ); } + /** \overload */ + template + inline typename Container::const_iterator findAlias( const std::string & alias_r, const Container & cont_r ) + { return findAlias( alias_r, cont_r.begin(), cont_r.end() ); } + + + /** \short Generate a related filename from a repo/service infos alias */ + std::string filenameFromAlias( const std::string & alias_r, const std::string & stem_r ); + + /** + * \short Simple callback to collect the results + * + * Classes like RepoFileReader call the callback + * once per each repo in a file. + * + * Passing this functor as callback, you can collect + * all results at the end, without dealing with async + * code. + * + * If targetDistro is set, all repos with non-empty RepoInfo::targetDistribution() + * will be skipped. + * + * \todo do this through a separate filter + */ + struct RepoCollector : private zypp::base::NonCopyable + { + RepoCollector() + {} + + RepoCollector(std::string targetDistro_) + : targetDistro(std::move(targetDistro_)) + {} + + bool collect( const RepoInfo &repo ); + + RepoInfoList repos; + std::string targetDistro; + }; + //////////////////////////////////////////////////////////////////////////// + + /** + * Reads RepoInfo's from a repo file. + * + * \param file pathname of the file to read. + */ + expected> repositories_in_file( const zypp::Pathname & file ); + + //////////////////////////////////////////////////////////////////////////// + + expected assert_urls( const RepoInfo & info ); + + inline expected assert_url( const ServiceInfo & info ) + { + if ( ! info.url().isValid() ) + return expected::error( ZYPP_EXCPT_PTR ( zypp::repo::ServiceNoUrlException( info ) ) ); + return expected::success(); + } + + /** + * \short Calculates the raw cache path for a repository, this is usually + * /var/cache/zypp/alias + */ + inline expected rawcache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info ) + { + using namespace zyppng::operators; + return assert_alias(info) | and_then( [&](){ return make_expected_success( isTmpRepo( info ) ? info.metadataPath() : opt.repoRawCachePath / info.escaped_alias()); }); + } + + /** + * \short Calculates the raw product metadata path for a repository, this is + * inside the raw cache dir, plus an optional path where the metadata is. + * + * It should be different only for repositories that are not in the root of + * the media. + * for example /var/cache/zypp/alias/addondir + */ + inline expected rawproductdata_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info ) + { + using namespace zyppng::operators; + return rawcache_path_for_repoinfo( opt, info ) | and_then( [&]( zypp::Pathname p ) { return make_expected_success( p / info.path() ); } ); + } + + /** + * \short Calculates the packages cache path for a repository + */ + inline expected packagescache_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info ) + { + using namespace zyppng::operators; + return assert_alias(info) | + and_then([&](){ return make_expected_success(isTmpRepo( info ) ? info.packagesPath() : opt.repoPackagesCachePath / info.escaped_alias()); }); + } + + /** + * \short Calculates the solv cache path for a repository + */ + inline expected solv_path_for_repoinfo( const RepoManagerOptions &opt, const RepoInfo &info ) + { + using namespace zyppng::operators; + return assert_alias(info) | + and_then([&](){ return make_expected_success(isTmpRepo( info ) ? info.metadataPath().dirname() / "%SLV%" : opt.repoSolvCachePath / info.escaped_alias()); }); + } + + //////////////////////////////////////////////////////////////////////////// + + /** Functor collecting ServiceInfos into a ServiceSet. */ + class ServiceCollector + { + public: + using ServiceSet = std::set; + + ServiceCollector( ServiceSet & services_r ) + : _services( services_r ) + {} + + bool operator()( const ServiceInfo & service_r ) const + { + _services.insert( service_r ); + return true; + } + + private: + ServiceSet & _services; + }; + //////////////////////////////////////////////////////////////////////////// + + /** bsc#1204956: Tweak to prevent auto pruning package caches. */ + bool autoPruneInDir( const zypp::Pathname & path_r ); + + /*! + * \brief The RepoManager class + * Provides knowledge and methods to maintain repo settings and metadata for a given context. + * + * Depending on the \a ZyppContextRefType the convenienve functions execute the workflows in + * a sync or async way. In sync mode libzypp's legacy reports are executed. Otherwise progress report + * is only provided via the \ref ProgressObserver classes. + */ + template + class RepoManager : public Base, private MaybeAsyncMixin> + { + ZYPP_ADD_PRIVATE_CONSTR_HELPER (); + ZYPP_ENABLE_MAYBE_ASYNC_MIXIN( (std::is_same_v) ); + + public: + + using ContextRefType = ZyppContextRefType; + using ContextType = typename ZyppContextRefType::element_type; + + using RawMetadataRefreshPolicy = zypp::RepoManagerFlags::RawMetadataRefreshPolicy; + using CacheBuildPolicy = zypp::RepoManagerFlags::CacheBuildPolicy; + + + using RefreshCheckStatus = zypp::RepoManagerFlags::RefreshCheckStatus; + + /** Flags for tuning RefreshService */ + using RefreshServiceBit = zypp::RepoManagerFlags::RefreshServiceBit; + using RefreshServiceOptions = zypp::RepoManagerFlags::RefreshServiceOptions; + + + ZYPP_DECL_PRIVATE_CONSTR_ARGS (RepoManager, ZyppContextRefType zyppCtx, RepoManagerOptions opt ); + + template < typename ...Args > + inline static expected>> create ( Args && ...args ) { + using namespace zyppng::operators; + auto mgr = std::make_shared< RepoManager >( private_constr_t{}, std::forward(args)... ); + return mgr->initialize() | and_then( [mgr](){ return make_expected_success(mgr); } ); + } + + public: + + /** + * Functor thats filter RepoInfo by service which it belongs to. + */ + struct MatchServiceAlias + { + public: + MatchServiceAlias( std::string alias_ ) : alias(std::move(alias_)) {} + bool operator()( const RepoInfo & info ) const + { return info.service() == alias; } + private: + std::string alias; + }; + + /** ServiceInfo typedefs */ + using ServiceSet = std::set; + using ServiceConstIterator = ServiceSet::const_iterator; + using ServiceSizeType = ServiceSet::size_type; + + /** RepoInfo typedefs */ + using RepoSet = std::set; + using RepoConstIterator = RepoSet::const_iterator; + using RepoSizeType = RepoSet::size_type; + + + virtual ~RepoManager(); + + public: + + expected initialize (); + + ContextRefType zyppContext() const { + return _zyppContext; + } + + const RepoManagerOptions &options() const; + + bool repoEmpty() const { return repos().empty(); } + RepoSizeType repoSize() const { return repos().size(); } + RepoConstIterator repoBegin() const { return repos().begin(); } + RepoConstIterator repoEnd() const { return repos().end(); } + + bool hasRepo( const std::string & alias ) const + { return foundAliasIn( alias, repos() ); } + + RepoInfo getRepo( const std::string & alias ) const + { + RepoConstIterator it( findAlias( alias, repos() ) ); + return it == repos().end() ? RepoInfo::noRepo : *it; + } + + public: + expected metadataPath( const RepoInfo & info ) const + { return rawcache_path_for_repoinfo( _options, info ); } + + expected packagesPath( const RepoInfo & info ) const + { return packagescache_path_for_repoinfo( _options, info ); } + + static expected metadataStatus( const RepoInfo & info, const RepoManagerOptions &options ); + expected metadataStatus( const RepoInfo & info ) const; + + expected cleanMetadata( const RepoInfo & info, ProgressObserverRef myProgress = nullptr ); + + expected cleanPackages( const RepoInfo & info, ProgressObserverRef myProgress = nullptr , bool isAutoClean = false ); + + static zypp::repo::RepoType probeCache( const zypp::Pathname & path_r ); + + expected cleanCacheDirGarbage( ProgressObserverRef myProgress = nullptr ); + + expected cleanCache( const RepoInfo & info, ProgressObserverRef myProgress = nullptr ); + + expected isCached( const RepoInfo & info ) const + { + using namespace zyppng::operators; + return solv_path_for_repoinfo( _options, info ) + | and_then( [&]( zypp::Pathname solvPath) { return make_expected_success( zypp::PathInfo(solvPath / "solv").isExist()); } ); + } + + expected cacheStatus( const RepoInfo & info ) const + { return cacheStatus( info, _options ); } + + static expected cacheStatus( const RepoInfo & info, const RepoManagerOptions &options ) + { + using namespace zyppng::operators; + return solv_path_for_repoinfo( options, info ) + | and_then( [&]( zypp::Pathname solvPath) { + return make_expected_success ( RepoStatus::fromCookieFile(solvPath / "cookie") ); + }); + } + + expected loadFromCache( const RepoInfo & info, ProgressObserverRef myProgress = nullptr ); + + expected addProbedRepository( RepoInfo info, zypp::repo::RepoType probedType ); + + expected removeRepository( const RepoInfo & info, ProgressObserverRef myProgress = nullptr ); + + expected modifyRepository( const std::string & alias, const RepoInfo & newinfo_r, ProgressObserverRef myProgress = nullptr ); + + expected getRepositoryInfo( const std::string & alias ); + expected getRepositoryInfo( const zypp::Url & url, const zypp::url::ViewOption &urlview ); + + expected checkIfToRefreshMetadata( const RepoInfo & info, const zypp::Url & url, RawMetadataRefreshPolicy policy ); + + /** + * \short Refresh local raw cache + * + * Will try to download the metadata + * + * In case of failure the metadata remains as it was before. + * + * The returned expected can contain one of the following errors: + * \ref repo::RepoNoUrlException if no urls are available. + * \ref repo::RepoNoAliasException if can't figure an alias + * \ref repo::RepoUnknownTypeException if the metadata is unknown + * \ref repo::RepoException if the repository is invalid + * (no valid metadata found at any of baseurls) + * + * \todo Currently no progress is generated, especially for the async code + * We might need to change this + */ + expected refreshMetadata( const RepoInfo & info, RawMetadataRefreshPolicy policy, ProgressObserverRef myProgress = nullptr ); + + std::vector > > refreshMetadata(std::vector infos, RawMetadataRefreshPolicy policy, ProgressObserverRef myProgress = nullptr ); + + expected probe( const zypp::Url & url, const zypp::Pathname & path = zypp::Pathname() ) const; + + expected buildCache( const RepoInfo & info, CacheBuildPolicy policy, ProgressObserverRef myProgress = nullptr ); + + /*! + * Adds the repository in \a info and returns the updated \ref RepoInfo object. + */ + expected addRepository( const RepoInfo & info, ProgressObserverRef myProgress = nullptr ); + + expected addRepositories( const zypp::Url & url, ProgressObserverRef myProgress = nullptr ); + + public: + bool serviceEmpty() const { return _services.empty(); } + ServiceSizeType serviceSize() const { return _services.size(); } + ServiceConstIterator serviceBegin() const { return _services.begin(); } + ServiceConstIterator serviceEnd() const { return _services.end(); } + + bool hasService( const std::string & alias ) const + { return foundAliasIn( alias, _services ); } + + ServiceInfo getService( const std::string & alias ) const + { + ServiceConstIterator it( findAlias( alias, _services ) ); + return it == _services.end() ? ServiceInfo::noService : *it; + } + + public: + + expected probeService( const zypp::Url & url ) const; + + expected addService( const ServiceInfo & service ); + expected addService( const std::string & alias, const zypp::Url & url ) + { return addService( ServiceInfo( alias, url ) ); } + + expected removeService( const std::string & alias ); + expected removeService( const ServiceInfo & service ) + { return removeService( service.alias() ); } + + expected refreshService( const std::string & alias, const RefreshServiceOptions & options_r ); + expected refreshService( const ServiceInfo & service, const RefreshServiceOptions & options_r ) + { return refreshService( service.alias(), options_r ); } + + expected refreshServices( const RefreshServiceOptions & options_r ); + + expected modifyService( const std::string & oldAlias, const ServiceInfo & newService ); + + static expected touchIndexFile( const RepoInfo & info, const RepoManagerOptions &options ); + + expected setCacheStatus( const RepoInfo & info, const RepoStatus & status ) + { + using namespace zyppng::operators; + return solv_path_for_repoinfo( _options, info ) + | and_then( [&]( zypp::Pathname base ){ + try { + zypp::filesystem::assert_dir(base); + status.saveToCookieFile( base / "cookie" ); + } catch ( const zypp::Exception &e ) { + return expected::error( std::make_exception_ptr(e) ); + } + return expected::success(); + }); + } + + /*! + * Checks for any of the given \a urls if there is no geoip data available, caches the results + * in the metadata cache for 24hrs. The given urls need to be configured as valid geoIP targets ( usually download.opensuse.org ) + */ + expected refreshGeoIp ( const RepoInfo::url_set &urls ); + + template + void getRepositoriesInService( const std::string & alias, OutputIterator out ) const + { + MatchServiceAlias filter( alias ); + std::copy( boost::make_filter_iterator( filter, repos().begin(), repos().end() ), + boost::make_filter_iterator( filter, repos().end(), repos().end() ), + out); + } + + zypp::Pathname generateNonExistingName( const zypp::Pathname & dir, const std::string & basefilename ) const; + + std::string generateFilename( const RepoInfo & info ) const + { return filenameFromAlias( info.alias(), "repo" ); } + + std::string generateFilename( const ServiceInfo & info ) const + { return filenameFromAlias( info.alias(), "service" ); } + + + protected: + expected saveService( ServiceInfo & service ) const; + expected touchIndexFile( const RepoInfo & info ); + + protected: + expected init_knownServices(); + expected init_knownRepositories(); + + public: + const RepoSet & repos() const { return _reposX; } + RepoSet & reposManip() { if ( ! _reposDirty ) _reposDirty = true; return _reposX; } + + protected: + ContextRefType _zyppContext; + RepoManagerOptions _options; + RepoSet _reposX; + ServiceSet _services; + zypp_private::repo::PluginRepoverification _pluginRepoverification; + zypp::DefaultIntegral _reposDirty; + }; +} + +#endif //ZYPP_NG_REPOMANAGER_INCLUDED diff --git a/zypp/ng/reporthelper.cc b/zypp/ng/reporthelper.cc new file mode 100644 index 0000000..fe36524 --- /dev/null +++ b/zypp/ng/reporthelper.cc @@ -0,0 +1,260 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "reporthelper.h" + +#include +#include + +namespace zyppng { + + template + BasicReportHelper::BasicReportHelper(ZyppContextRef &&ctx) + : _ctx( std::move(ctx) ) + { } + + template + bool DigestReportHelper::askUserToAcceptNoDigest(const zypp::Pathname &file) + { + if constexpr ( async() ) { + std::string label = (zypp::str::Format(_("No digest for file %s.")) % file ).str(); + auto req = BooleanChoiceRequest::create( label, false, AcceptNoDigestRequest::makeData(file) ); + this->_ctx->sendUserRequest( req ); + return req->choice (); + } else { + return _report->askUserToAcceptNoDigest(file); + } + } + + template + bool DigestReportHelper::askUserToAccepUnknownDigest(const zypp::Pathname &file, const std::string &name) + { + if constexpr ( async() ) { + std::string label = (zypp::str::Format(_("Unknown digest %s for file %s.")) %name % file).str(); + auto req = BooleanChoiceRequest::create( label, false, AcceptUnknownDigestRequest::makeData(file, name) ); + this->_ctx->sendUserRequest( req ); + return req->choice (); + } else { + return _report->askUserToAccepUnknownDigest( file, name ); + } + } + + template + bool DigestReportHelper::askUserToAcceptWrongDigest(const zypp::Pathname &file, const std::string &requested, const std::string &found) + { + if constexpr ( async() ) { + std::string label = (zypp::str::Format(_("Digest verification failed for file '%s'")) % file).str(); + auto req = BooleanChoiceRequest::create( label, false, AcceptWrongDigestRequest::makeData(file, requested, found) ); + this->_ctx->sendUserRequest( req ); + return req->choice (); + } else { + return _report->askUserToAcceptWrongDigest( file, requested, found ); + } + } + + template + bool KeyRingReportHelper::askUserToAcceptUnsignedFile(const std::string &file, const zypp::KeyContext &keycontext) + { + if constexpr ( async() ) { + std::string label; + if (keycontext.empty()) + label = zypp::str::Format( + // TranslatorExplanation: speaking of a file + _("File '%s' is unsigned, continue?")) % file; + else + label = zypp::str::Format( + // TranslatorExplanation: speaking of a file + _("File '%s' from repository '%s' is unsigned, continue?")) + % file % keycontext.repoInfo().asUserString(); + + + auto req = BooleanChoiceRequest::create ( label, false, AcceptUnsignedFileRequest::makeData ( file, keycontext ) ); + this->_ctx->sendUserRequest ( req ); + return req->choice (); + } else { + return _report->askUserToAcceptUnsignedFile( file, keycontext ); + } + } + + template + zypp::KeyRingReport::KeyTrust KeyRingReportHelper::askUserToAcceptKey(const zypp::PublicKey &key, const zypp::KeyContext &keycontext) + { + if constexpr ( async() ) { + auto req = TrustKeyRequest::create( + _("Do you want to reject the key, trust temporarily, or trust always?"), + TrustKeyRequest::KEY_DONT_TRUST, + AcceptKeyRequest::makeData ( key, keycontext ) + ); + this->_ctx->sendUserRequest ( req ); + return static_cast(req->choice()); + } else { + return _report->askUserToAcceptKey( key, keycontext ); + } + } + + template + bool KeyRingReportHelper::askUserToAcceptPackageKey(const zypp::PublicKey &key_r, const zypp::KeyContext &keycontext_r) + { + if constexpr ( async() ) { + ERR << "Not implemented yet" << std::endl; + return false; + } else { + return _report->askUserToAcceptPackageKey ( key_r, keycontext_r ); + } + } + + template + void KeyRingReportHelper::infoVerify(const std::string &file_r, const zypp::PublicKeyData &keyData_r, const zypp::KeyContext &keycontext) + { + if constexpr ( async() ) { + std::string label = zypp::str::Format( _("Key Name: %1%")) % keyData_r.name(); + auto req = ShowMessageRequest::create( label, ShowMessageRequest::MType::Info, VerifyInfoEvent::makeData ( file_r, keyData_r, keycontext) ); + this->_ctx->sendUserRequest ( req ); + } else { + return _report->infoVerify( file_r, keyData_r, keycontext ); + } + } + + template + void KeyRingReportHelper::reportAutoImportKey(const std::list &keyDataList_r, const zypp::PublicKeyData &keySigning_r, const zypp::KeyContext &keyContext_r) + { + if constexpr ( async() ) { + const std::string &lbl = zypp::str::Format( PL_( "Received %1% new package signing key from repository \"%2%\":", + "Received %1% new package signing keys from repository \"%2%\":", + keyDataList_r.size() )) % keyDataList_r.size() % keyContext_r.repoInfo().asUserString(); + this->_ctx->sendUserRequest( ShowMessageRequest::create( lbl, ShowMessageRequest::MType::Info, KeyAutoImportInfoEvent::makeData( keyDataList_r, keySigning_r, keyContext_r) ) ); + } else { + return _report->reportAutoImportKey( keyDataList_r, keySigning_r, keyContext_r ); + } + } + + template + bool KeyRingReportHelper::askUserToAcceptVerificationFailed(const std::string &file, const zypp::PublicKey &key, const zypp::KeyContext &keycontext) + { + if constexpr ( async() ) { + std::string label; + if ( keycontext.empty() ) + // translator: %1% is a file name + label = zypp::str::Format(_("Signature verification failed for file '%1%'.") ) % file; + else + // translator: %1% is a file name, %2% a repositories na me + label = zypp::str::Format(_("Signature verification failed for file '%1%' from repository '%2%'.") ) % file % keycontext.repoInfo().asUserString(); + + // @TODO use a centralized Continue string! + label += std::string(" ") + _("Continue?"); + auto req = BooleanChoiceRequest::create ( label, false, AcceptFailedVerificationRequest::makeData ( file, key, keycontext ) ); + this->_ctx->sendUserRequest ( req ); + return req->choice (); + } else { + return _report->askUserToAcceptVerificationFailed( file, key, keycontext ); + } + } + + template + bool KeyRingReportHelper::askUserToAcceptUnknownKey( const std::string &file, const std::string &id, const zypp::KeyContext &keycontext ) + { + if constexpr ( async() ) { + std::string label; + + if (keycontext.empty()) + label = zypp::str::Format( + // translators: the last %s is gpg key ID + _("File '%s' is signed with an unknown key '%s'. Continue?")) % file % id; + else + label = zypp::str::Format( + // translators: the last %s is gpg key ID + _("File '%s' from repository '%s' is signed with an unknown key '%s'. Continue?")) + % file % keycontext.repoInfo().asUserString() % id; + + auto req = BooleanChoiceRequest::create ( label, false, AcceptUnknownKeyRequest::makeData ( file, id, keycontext ) ); + this->_ctx->sendUserRequest ( req ); + return req->choice (); + } else { + return _report->askUserToAcceptUnknownKey( file, id, keycontext ); + } + } + + template + bool JobReportHelper::debug(std::string msg_r, UserData userData_r) + { + if constexpr ( async() ) { + this->_ctx->sendUserRequest( ShowMessageRequest::create( std::move(msg_r), ShowMessageRequest::MType::Debug, std::move(userData_r) ) ); + return true; + } else { + return zypp::JobReport::debug ( msg_r, userData_r ); + } + } + + template + bool JobReportHelper::info( std::string msg_r, UserData userData_r) + { + if constexpr ( async() ) { + this->_ctx->sendUserRequest( ShowMessageRequest::create( std::move(msg_r), ShowMessageRequest::MType::Info, std::move(userData_r) ) ); + return true; + } else { + return zypp::JobReport::info ( msg_r, userData_r ); + } + } + + template + bool JobReportHelper::warning( std::string msg_r, UserData userData_r) + { + if constexpr ( async() ) { + this->_ctx->sendUserRequest( ShowMessageRequest::create( std::move(msg_r), ShowMessageRequest::MType::Warning, std::move(userData_r) ) ); + return true; + } else { + return zypp::JobReport::warning ( msg_r, userData_r ); + } + } + + template + bool JobReportHelper::error( std::string msg_r, UserData userData_r) + { + if constexpr ( async() ) { + this->_ctx->sendUserRequest( ShowMessageRequest::create( std::move(msg_r), ShowMessageRequest::MType::Error, std::move(userData_r) ) ); + return true; + } else { + return zypp::JobReport::error ( msg_r, userData_r ); + } + } + + template + bool JobReportHelper::important( std::string msg_r, UserData userData_r) + { + if constexpr ( async() ) { + this->_ctx->sendUserRequest( ShowMessageRequest::create( std::move(msg_r), ShowMessageRequest::MType::Important, std::move(userData_r) ) ); + return true; + } else { + return zypp::JobReport::important ( msg_r, userData_r ); + } + } + + template + bool JobReportHelper::data( std::string msg_r, UserData userData_r) + { + if constexpr ( async() ) { + this->_ctx->sendUserRequest( ShowMessageRequest::create( std::move(msg_r), ShowMessageRequest::MType::Data, std::move(userData_r) ) ); + return true; + } else { + return zypp::JobReport::data ( msg_r, userData_r ); + } + } + + // explicitely intantiate the template types we want to work with + template class BasicReportHelper; + template class BasicReportHelper; + template class DigestReportHelper; + template class DigestReportHelper; + template class KeyRingReportHelper; + template class KeyRingReportHelper; + template class JobReportHelper; + template class JobReportHelper; + + +} diff --git a/zypp/ng/reporthelper.h b/zypp/ng/reporthelper.h new file mode 100644 index 0000000..ea5142a --- /dev/null +++ b/zypp/ng/reporthelper.h @@ -0,0 +1,169 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/zypp_detail/repomanagerbase_p.h + * +*/ +#ifndef ZYPP_NG_REPORTHELPER_INCLUDED +#define ZYPP_NG_REPORTHELPER_INCLUDED + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace zyppng { + + ZYPP_FWD_DECL_REFS (Context); + + namespace detail { + template + class ReportHolder; + + template + class ReportHolder + {}; + + template + class ReportHolder + { + public: + ReportHolder() : _d( std::make_shared>() ){} + + ReportHolder(const ReportHolder &) = default; + ReportHolder(ReportHolder &&) = default; + ReportHolder &operator=(const ReportHolder &) = default; + ReportHolder &operator=(ReportHolder &&) = default; + + auto &operator->() { + return *_d; + } + + std::shared_ptr> _d; + }; + } + + template + class BasicReportHelper { + public: + BasicReportHelper(const BasicReportHelper &) = default; + BasicReportHelper(BasicReportHelper &&) = default; + BasicReportHelper &operator=(const BasicReportHelper &) = default; + BasicReportHelper &operator=(BasicReportHelper &&) = default; + + const ZyppContextRef &zyppContext() { + return _ctx; + } + + static constexpr bool async () { + return std::is_same(); + } + + protected: + BasicReportHelper( ZyppContextRef &&ctx ); + ZyppContextRef _ctx; + }; + + template + class DigestReportHelper : public BasicReportHelper { + public: + using BasicReportHelper::async; + + DigestReportHelper(ZyppContextRef r) + : BasicReportHelper(std::move(r)) {} + + DigestReportHelper(const DigestReportHelper &) = default; + DigestReportHelper(DigestReportHelper &&) = default; + DigestReportHelper &operator=(const DigestReportHelper &) = default; + DigestReportHelper &operator=(DigestReportHelper &&) = default; + + bool askUserToAcceptNoDigest ( const zypp::Pathname &file ); + bool askUserToAccepUnknownDigest ( const zypp::Pathname &file, const std::string &name ); + bool askUserToAcceptWrongDigest ( const zypp::Pathname &file, const std::string &requested, const std::string &found ); + + private: + detail::ReportHolder _report; + }; + + template + class KeyRingReportHelper : public BasicReportHelper { + public: + using BasicReportHelper::async; + + KeyRingReportHelper(ZyppContextRef r) + : BasicReportHelper(std::move(r)) {} + + KeyRingReportHelper(const KeyRingReportHelper &) = default; + KeyRingReportHelper(KeyRingReportHelper &&) = default; + KeyRingReportHelper &operator=(const KeyRingReportHelper &) = default; + KeyRingReportHelper &operator=(KeyRingReportHelper &&) = default; + + // -- Key Ring reports -- // + + bool askUserToAcceptUnsignedFile( const std::string &file, const zypp::KeyContext &keycontext = {} ); + + zypp::KeyRingReport::KeyTrust askUserToAcceptKey( const zypp::PublicKey &key, const zypp::KeyContext &keycontext = {} ); + + bool askUserToAcceptPackageKey( const zypp::PublicKey &key_r, const zypp::KeyContext &keycontext_r = {} ); + + void infoVerify( const std::string & file_r, const zypp::PublicKeyData & keyData_r, const zypp::KeyContext &keycontext = {} ); + + void reportAutoImportKey( const std::list & keyDataList_r, const zypp::PublicKeyData & keySigning_r, const zypp::KeyContext &keyContext_r ); + + bool askUserToAcceptVerificationFailed( const std::string &file, const zypp::PublicKey &key, const zypp::KeyContext &keycontext = {} ); + + bool askUserToAcceptUnknownKey( const std::string &file, const std::string &id, const zypp::KeyContext &keycontext = {} ); + + private: + detail::ReportHolder _report; + + }; + + template + class JobReportHelper : public BasicReportHelper { + public: + using BasicReportHelper::async; + + JobReportHelper(ZyppContextRef r) + : BasicReportHelper(std::move(r)) {} + + JobReportHelper(const JobReportHelper &) = default; + JobReportHelper(JobReportHelper &&) = default; + JobReportHelper &operator=(const JobReportHelper &) = default; + JobReportHelper &operator=(JobReportHelper &&) = default; + + /** send debug message text */ + bool debug( std::string msg_r, UserData userData_r = UserData() ); + + /** send message text */ + bool info( std::string msg_r, UserData userData_r = UserData() ); + + /** send warning text */ + bool warning( std::string msg_r, UserData userData_r = UserData() ); + + /** send error text */ + bool error( std::string msg_r, UserData userData_r = UserData() ); + + /** send important message text */ + bool important( std::string msg_r, UserData userData_r = UserData() ); + + /** send data message */ + bool data( std::string msg_r, UserData userData_r = UserData() ); + + }; +} + + +#endif //ZYPP_NG_REPORTHELPER_INCLUDED diff --git a/zypp/ng/userrequest.cc b/zypp/ng/userrequest.cc new file mode 100644 index 0000000..e8e901b --- /dev/null +++ b/zypp/ng/userrequest.cc @@ -0,0 +1,118 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "userrequest.h" + +namespace zyppng { + + UserData AcceptNoDigestRequest::makeData(const zypp::Pathname &p) { + UserData d( CTYPE.data() ); + d.set( FILE.data(), p ); + return d; + } + + UserData AcceptUnknownDigestRequest::makeData(const zypp::Pathname &p, const std::string &name) { + UserData d( CTYPE.data() ); + d.set( FILE.data(), p ); + d.set( NAME.data(), name ); + return d; + } + + UserData AcceptWrongDigestRequest::makeData(const zypp::Pathname &p, const std::string &requested, const std::string &found) { + UserData d( CTYPE.data() ); + d.set( FILE.data(), p ); + d.set( NAME_REQUESTED.data(), requested ); + d.set( NAME_FOUND.data(), found ); + return d; + } + + ZYPP_IMPL_PRIVATE_CONSTR_ARGS(TrustKeyRequest, std::string label, KeyTrust trust, UserData userData ) + : UserRequest( std::move(userData) ) + , _label( std::move(label) ) + , _answer(trust) + { } + + void TrustKeyRequest::setChoice(const KeyTrust sel) + { _answer = sel; } + + TrustKeyRequest::KeyTrust TrustKeyRequest::choice() const + { return _answer; } + + const std::string TrustKeyRequest::label() const + { return _label; } + + UserRequestType TrustKeyRequest::type() const + { return UserRequestType::KeyTrust; } + + UserData AcceptKeyRequest::makeData(const zypp::PublicKey &key, const zypp::KeyContext &keycontext) + { + UserData d( CTYPE.data() ); + d.set( KEY.data(), key ); + d.set( KEY_CONTEXT.data(), keycontext ); + return d; + } + + UserData VerifyInfoEvent::makeData(const std::string &file_r, const zypp::PublicKeyData &keyData_r, const zypp::KeyContext &keycontext) + { + UserData d( CTYPE.data() ); + d.set( FILE.data(), file_r ); + d.set( KEY_DATA.data(), keyData_r ); + d.set( KEY_CONTEXT.data(), keycontext ); + return d; + } + + UserData AcceptUnsignedFileRequest::makeData(const std::string &file, const zypp::KeyContext &keycontext) + { + UserData d( CTYPE.data() ); + d.set( FILE.data(), file ); + d.set( KEY_CONTEXT.data(), keycontext ); + return d; + } + + UserData AcceptUnknownKeyRequest::makeData(const std::string &file, const std::string &id, const zypp::KeyContext &keycontext) + { + UserData d( CTYPE.data() ); + d.set( KEYID.data(), id ); + d.set( FILE.data(), file ); + d.set( KEY_CONTEXT.data(), keycontext ); + return d; + } + + UserData AcceptFailedVerificationRequest::makeData(const std::string &file, const zypp::PublicKey &key, const zypp::KeyContext &keycontext) + { + UserData d( CTYPE.data() ); + d.set( KEY.data(), key ); + d.set( FILE.data(), file ); + d.set( KEY_CONTEXT.data(), keycontext ); + return d; + } + + UserData AcceptPackageKeyRequest::makeData(const zypp::PublicKey &key_r, const zypp::KeyContext &keycontext_r) + { + UserData d( CTYPE.data() ); + d.set( KEY.data(), key_r ); + d.set( KEY_CONTEXT.data(), keycontext_r ); + return d; + } + + UserData NonImportedKeysInfoEvent::makeData(const std::set &keys_r) + { + UserData d( CTYPE.data() ); + d.set( KEYS.data(), &keys_r ); + return d; + } + + UserData KeyAutoImportInfoEvent::makeData(const std::list &keyDataList_r, const zypp::PublicKeyData &keySigning_r, const zypp::KeyContext &keyContext_r) + { + UserData d( CTYPE.data() ); + d.set( KEY_DATA_LIST.data(), &keyDataList_r ); + d.set( KEY_DATA.data(), keySigning_r ); + d.set( KEY_CONTEXT.data(), keyContext_r ); + return d; + } +} diff --git a/zypp/ng/userrequest.h b/zypp/ng/userrequest.h new file mode 100644 index 0000000..d0fa090 --- /dev/null +++ b/zypp/ng/userrequest.h @@ -0,0 +1,251 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_USERREQUEST_H_INCLUDED +#define ZYPP_NG_USERREQUEST_H_INCLUDED + +#include +#include +#include + +namespace zyppng { + + /*! + * A digest user request asking the user to accept + * verification of a file that has no checksum available. + * + * Something like: "File foo.bar has no checksum. Continue?" + * + * Userdata fields: + * - "file" Path of the file to be validated + */ + namespace AcceptNoDigestRequest { + constexpr std::string_view CTYPE ("digest/accept-no-digest"); + constexpr std::string_view FILE ("file"); + UserData makeData ( const zypp::Pathname &p); + } + + /*! + * A digest user request asking the user to accept + * verification with a unknown digest. + * + * Something like: "Unknown digest for file ." + * + * Userdata fields: + * - "file" Path of the file to be validated + * - "name" Name of the digest + */ + namespace AcceptUnknownDigestRequest { + constexpr std::string_view CTYPE ("digest/accept-unknown-digest"); + constexpr std::string_view FILE ("file"); + constexpr std::string_view NAME ("name"); + UserData makeData ( const zypp::Pathname &p, const std::string &name ); + } + + /*! + * A digest user request asking the user to accept + * a wrong digest. + * + * Something like: "Unknown digest for file ." + * + * Userdata fields: + * - "file" Path of the file to be validated + * - "name" Name of the digest + */ + namespace AcceptWrongDigestRequest { + constexpr std::string_view CTYPE ("digest/accept-unknown-digest"); + constexpr std::string_view FILE ("file"); + constexpr std::string_view NAME_REQUESTED ("requested"); + constexpr std::string_view NAME_FOUND ("found"); + UserData makeData ( const zypp::Pathname &p, const std::string &requested, const std::string &found ); + } + + + ZYPP_FWD_DECL_TYPE_WITH_REFS(TrustKeyRequest); + class TrustKeyRequest : public UserRequest + { + ZYPP_ADD_CREATE_FUNC(TrustKeyRequest) + public: + /*! + * Keep in sync with zypp::KeyRingReport::KeyTrust, we do not want + * to include old APIs here if possible. + */ + enum KeyTrust + { + /** + * User has chosen not to trust the key. + */ + KEY_DONT_TRUST = 0, + /** + * This basically means, we knew the key, but it was not trusted. User + * has chosen to continue, but not import the key. + */ + KEY_TRUST_TEMPORARILY, + /** + * Import the key. + * This means saving the key in the trusted database so next run it will appear as trusted. + * Nothing to do with KEY_TRUST_TEMPORARILY, as you CAN trust a key without importing it, + * basically you will be asked every time again. + * There are programs who prefer to manage the trust keyring on their own and use trustKey + * without importing it into rpm. + */ + KEY_TRUST_AND_IMPORT + }; + + ZYPP_DECL_PRIVATE_CONSTR_ARGS(TrustKeyRequest, std::string label, KeyTrust trust = KEY_DONT_TRUST, UserData userData = {} ); + + void setChoice ( const KeyTrust sel ); + KeyTrust choice() const; + + const std::string label() const; + + UserRequestType type() const override; + + private: + std::string _label; + KeyTrust _answer = KEY_DONT_TRUST; + }; + + /*! + * Ask user to trust and/or import the key to trusted keyring. + * \see zypp::KeyTrust + * + * Userdata fields: + * - "key" Key to import into the trusted keyring + * - "key-context" context the key is used in + */ + namespace AcceptKeyRequest { + constexpr std::string_view CTYPE ("keyring/accept-key"); + constexpr std::string_view KEY ("key"); + constexpr std::string_view KEY_CONTEXT("key-context"); + UserData makeData ( const zypp::PublicKey &key, const zypp::KeyContext &keycontext = zypp::KeyContext() ); + } + + + /*! + * Informal event showing the trusted key that will be used for verification. + * + * Userdata fields: + * - "file" File that was verified + * - "key-data" Key data that was used to verify the file + * - "key-context" context the key is used in + */ + namespace VerifyInfoEvent { + constexpr std::string_view CTYPE ("keyring/info-verify"); + constexpr std::string_view FILE ("file"); + constexpr std::string_view KEY_DATA("key-data"); + constexpr std::string_view KEY_CONTEXT("key-context"); + UserData makeData ( const std::string & file_r, const zypp::PublicKeyData & keyData_r, const zypp::KeyContext &keycontext = zypp::KeyContext() ); + } + + /*! + * Ask user to accept or reject a unsigned file + * + * Userdata fields: + * - "file" The file zypp needs to be accepted or rejected + * - "key-context" context the file came up in + */ + namespace AcceptUnsignedFileRequest { + constexpr std::string_view CTYPE ("keyring/accept-unsigned-file"); + constexpr std::string_view FILE ("file"); + constexpr std::string_view KEY_CONTEXT("key-context"); + UserData makeData ( const std::string &file, const zypp::KeyContext &keycontext = zypp::KeyContext() ); + } + + /** + * Ask the user to accept a unknown key. + * We DONT know the key, only its id, but we have never seen it, the difference + * with trust key is that if you dont have it, you can't import it later. + * The answer means continue yes or no? + * + * Userdata fields: + * - "keyid" The key ID in question + * - "file" The file signed with the given key id + * - "key-context" context the file came up in + * + */ + namespace AcceptUnknownKeyRequest { + constexpr std::string_view CTYPE ("keyring/accept-unknown-key"); + constexpr std::string_view KEYID ("keyid"); + constexpr std::string_view FILE ("file"); + constexpr std::string_view KEY_CONTEXT("key-context"); + UserData makeData ( const std::string &file, const std::string &id, const zypp::KeyContext &keycontext = zypp::KeyContext() ); + } + + /** + * Ask the user to accept a file that is signed but where the + * signature verification failed. + * + * Userdata fields: + * - "file" The file in question + * - "key" Key zypp tried to verify with + * - "key-context" context the file came up in + */ + namespace AcceptFailedVerificationRequest { + constexpr std::string_view CTYPE ("keyring/accept-failed-verification"); + constexpr std::string_view FILE ("file"); + constexpr std::string_view KEY ("key"); + constexpr std::string_view KEY_CONTEXT ("key-context"); + UserData makeData ( const std::string &file, const zypp::PublicKey &key, const zypp::KeyContext &keycontext = zypp::KeyContext() ); + } + + /** + * Ask user to trust and/or import the package key to trusted keyring + * + * Userdata fields: + * - "key" The PublicKey to be accepted + * - "key-context" The KeyContext + * + * \see zypp::KeyTrust + */ + namespace AcceptPackageKeyRequest { + constexpr std::string_view CTYPE ("keyring/accept-package-key"); + constexpr std::string_view KEY ("key"); + constexpr std::string_view KEY_CONTEXT ("key-context"); + UserData makeData ( const zypp::PublicKey &key_r, const zypp::KeyContext &keycontext_r = zypp::KeyContext() ); + } + + /** + * Notify the user about keys that were not imported from the + * rpm key database into zypp keyring + * + * Userdata fields: + * const std::set * "Keys" set of keys that were not imported + * + */ + namespace NonImportedKeysInfoEvent { + constexpr std::string_view CTYPE ("keyring/keys-not-imported"); + constexpr std::string_view KEYS ("keys"); + UserData makeData ( const std::set &keys_r ); + } + + /** + * Notify that a repository auto imported new package signing keys. + * + * To auto import new package signing keys, the repositories metadata must be + * signed by an already trusted key. + * + * Userdata fields: + * const std::list * "key-data-list" List of KeyData to import + * zypp::PublicKeyData "key-data" KeyData of signing key + * zypp::KeyContext "key-context" The KeyContext + */ + namespace KeyAutoImportInfoEvent { + constexpr std::string_view CTYPE ("keyring/auto-import-key-info"); + constexpr std::string_view KEY_DATA_LIST ("key-data-list"); + constexpr std::string_view KEY_DATA ("key-data"); + constexpr std::string_view KEY_CONTEXT ("key-context"); + UserData makeData ( const std::list & keyDataList_r, + const zypp::PublicKeyData & keySigning_r, + const zypp::KeyContext &keyContext_r ); + } + + +} + +#endif // ZYPP_NG_USERREQUEST_H_INCLUDED diff --git a/zypp/ng/workflows/checksumwf.cc b/zypp/ng/workflows/checksumwf.cc new file mode 100644 index 0000000..caaa999 --- /dev/null +++ b/zypp/ng/workflows/checksumwf.cc @@ -0,0 +1,153 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "checksumwf.h" +#include "logichelpers.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace zyppng::CheckSumWorkflow { + + using namespace zyppng::operators; + + template + struct CheckSumWorkflowLogic : public LogicBase + { + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + using ZyppContextRefType = MaybeAsyncContextRef; + using ZyppContextType = remove_smart_ptr_t; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + CheckSumWorkflowLogic( ZyppContextRefType zyppContext, zypp::CheckSum &&checksum, zypp::Pathname file ) + : _context( std::move(zyppContext) ) + , _report( _context ) + , _checksum(std::move( checksum )) + , _file(std::move( file )) + {} + + auto execute() + { + + //MIL << "checking " << file << " file against checksum '" << _checksum << "'" << endl; + if ( _checksum.empty() ) { + MIL << "File " << _file << " has no checksum available." << std::endl; + if ( _report.askUserToAcceptNoDigest( _file ) ) { + MIL << "User accepted " << _file << " with no checksum." << std::endl; + return makeReadyResult( expected::success() ); + } else { + return makeReadyResult( expected::error( ZYPP_EXCPT_PTR(zypp::FileCheckException( _file.basename() + " has no checksum" ) ) ) ); + } + + } else { + + return _context->provider()->checksumForFile ( _file, _checksum.type() ) + | [] ( expected sum ) { + if ( !sum ) + return zypp::CheckSum( ); + return sum.get(); + } + | [this, _file=_file]( zypp::CheckSum real_checksum ){ + if ( (real_checksum != _checksum) ) + { + // Remember askUserToAcceptWrongDigest decision for at most 12hrs in memory; + // Actually we just want to prevent asking the same question again when the + // previously downloaded file is retrieved from the disk cache. + static std::map exceptions; + static zypp::Date exceptionsAge; + zypp::Date now( zypp::Date::now() ); + if ( !exceptions.empty() && now-exceptionsAge > 12*zypp::Date::hour ) + exceptions.clear(); + + WAR << "File " << _file << " has wrong checksum " << real_checksum << " (expected " << _checksum << ")" << std::endl; + if ( !exceptions.empty() && exceptions[real_checksum.checksum()] == _checksum.checksum() ) + { + WAR << "User accepted " << _file << " with WRONG CHECKSUM. (remembered)" << std::endl; + return expected::success(); + } + else if ( _report.askUserToAcceptWrongDigest( _file, _checksum.checksum(), real_checksum.checksum() ) ) + { + WAR << "User accepted " << _file << " with WRONG CHECKSUM." << std::endl; + exceptions[real_checksum.checksum()] = _checksum.checksum(); + exceptionsAge = now; + return expected::success(); + } + else + { + return expected::error( ZYPP_EXCPT_PTR(zypp::FileCheckException( _file.basename() + " has wrong checksum" ) ) ); + } + } + return expected::success(); + }; + } + } + + protected: + ZyppContextRefType _context; + DigestReportHelper _report; + zypp::CheckSum _checksum; + zypp::Pathname _file; + + }; + + expected verifyChecksum( SyncContextRef zyppCtx, zypp::CheckSum checksum, zypp::Pathname file ) + { + return SimpleExecutor>>::run( std::move(zyppCtx), std::move(checksum), std::move(file) ); + } + + AsyncOpRef > verifyChecksum( ContextRef zyppCtx, zypp::CheckSum checksum, zypp::filesystem::Pathname file ) + { + return SimpleExecutor>>::run( std::move(zyppCtx), std::move(checksum), std::move(file) ); + } + + std::function > (ProvideRes &&)> checksumFileChecker( ContextRef zyppCtx, zypp::CheckSum checksum ) + { + using zyppng::operators::operator|; + return [ zyppCtx, checksum=std::move(checksum) ]( ProvideRes res ) mutable -> AsyncOpRef> { + return verifyChecksum( zyppCtx, std::move(checksum), res.file() ) + | [ res ] ( expected result ) mutable { + if ( result ) + return expected::success( std::move(res) ); + else + return expected::error( std::move(result.error()) ); + }; + }; + } + + std::function (SyncProvideRes &&)> checksumFileChecker(SyncContextRef zyppCtx, zypp::CheckSum checksum) + { + using zyppng::operators::operator|; + return [ zyppCtx = std::move(zyppCtx), checksum=std::move(checksum) ]( SyncProvideRes res ) mutable -> expected { + return verifyChecksum( zyppCtx, std::move(checksum), res.file() ) + | [ res ] ( expected result ) mutable { + if ( result ) + return expected::success( std::move(res) ); + else + return expected::error( std::move(result.error()) ); + }; + }; + } + +} diff --git a/zypp/ng/workflows/checksumwf.h b/zypp/ng/workflows/checksumwf.h new file mode 100644 index 0000000..f4f5eda --- /dev/null +++ b/zypp/ng/workflows/checksumwf.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_CHECKSUMWORKFLOW_INCLUDED +#define ZYPP_NG_CHECKSUMWORKFLOW_INCLUDED + +#include +#include +#include + +#include +#include + +namespace zypp { + namespace filesystem { + class Pathname; + } + using filesystem::Pathname; + class CheckSum; +} + +namespace zyppng { + + class ProvideRes; + ZYPP_FWD_DECL_TYPE_WITH_REFS(Context); + + namespace CheckSumWorkflow { + expected verifyChecksum ( SyncContextRef zyppCtx, zypp::CheckSum checksum, zypp::Pathname file ); + AsyncOpRef> verifyChecksum ( ContextRef zyppCtx, zypp::CheckSum checksum, zypp::Pathname file ); + + /*! + * Returns a callable that executes the verify checksum as part of a pipeline, + * forwarding the \ref ProvideRes if the workflow was successful. + */ + std::function< AsyncOpRef>( ProvideRes && ) > checksumFileChecker( ContextRef zyppCtx, zypp::CheckSum checksum ); + std::function< expected( SyncProvideRes && ) > checksumFileChecker( SyncContextRef zyppCtx, zypp::CheckSum checksum ); + + } +} + + + +#endif diff --git a/zypp/ng/workflows/contextfacade.cc b/zypp/ng/workflows/contextfacade.cc new file mode 100644 index 0000000..485ddce --- /dev/null +++ b/zypp/ng/workflows/contextfacade.cc @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "contextfacade.h" +#include + +namespace zyppng +{ + ZYPP_IMPL_PRIVATE_CONSTR(SyncContext) : _media( MediaSyncFacade::create() ) + { + + } + + + /*! + * Returns the default sync zypp context. + * This is only a workaround to support the Legacy APIs. + * For new style APIs the Context should always explicitely be passed down. So use it + * only in top level external classes where we can not touch the API. + */ + SyncContextRef SyncContext::defaultContext() + { + static SyncContextRef def = SyncContext::create(); + return def; + } + + MediaSyncFacadeRef SyncContext::provider() const + { + return _media; + } + + KeyRingRef SyncContext::keyRing() const + { + return zypp::getZYpp()->keyRing(); + } + + zypp::ZConfig &SyncContext::config() + { + return zypp::ZConfig::instance(); + } + + zypp::ResPool SyncContext::pool() + { + return zypp::ResPool::instance(); + } + + zypp::ResPoolProxy SyncContext::poolProxy() + { + return zypp::ResPool::instance().proxy(); + } + + zypp::sat::Pool SyncContext::satPool() + { + return zypp::sat::Pool::instance(); + } +} diff --git a/zypp/ng/workflows/contextfacade.h b/zypp/ng/workflows/contextfacade.h new file mode 100644 index 0000000..a359e22 --- /dev/null +++ b/zypp/ng/workflows/contextfacade.h @@ -0,0 +1,59 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_CONTEXTFACADE_INCLUDED +#define ZYPP_NG_CONTEXTFACADE_INCLUDED + +#include "zypp/ng/context.h" +#include + +namespace zypp { + DEFINE_PTR_TYPE(KeyRing); + class ZConfig; +} + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS( SyncContext ); + + using KeyRing = zypp::KeyRing; + using KeyRingRef = zypp::KeyRing_Ptr; + + class ZYPP_API SyncContext { + + ZYPP_ADD_CREATE_FUNC(SyncContext) + + public: + ZYPP_DECL_PRIVATE_CONSTR(SyncContext); + + using ProvideType = MediaSyncFacade; + + static SyncContextRef defaultContext(); + + MediaSyncFacadeRef provider() const; + KeyRingRef keyRing () const; + zypp::ZConfig &config(); + zypp::ResPool pool(); + zypp::ResPoolProxy poolProxy(); + zypp::sat::Pool satPool(); + + + private: + MediaSyncFacadeRef _media; + }; + + template + using MaybeAsyncContextRef = std::conditional_t, ContextRef, SyncContextRef>; + + template + auto joinPipeline( SyncContextRef ctx, T &&val ) { + return std::forward(val); + } +} + +#endif diff --git a/zypp/ng/workflows/downloadwf.cc b/zypp/ng/workflows/downloadwf.cc new file mode 100644 index 0000000..d63bcc4 --- /dev/null +++ b/zypp/ng/workflows/downloadwf.cc @@ -0,0 +1,221 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "downloadwf.h" +#include + +#include +#include +#include +#include + + +#include +#include + +#include +#include + +namespace zyppng { + + template + CacheProviderContext::CacheProviderContext( ZYPP_PRIVATE_CONSTR_ARG, ZyppContextRefType zyppContext, zypp::Pathname destDir ) + : _zyppContext( std::move(zyppContext) ) + , _destDir( std::move(destDir) ) + { } + + + template + const typename CacheProviderContext::ContextRefType &CacheProviderContext::zyppContext() const + { + return _zyppContext; + } + + + template + const zypp::Pathname &CacheProviderContext::destDir() const + { + return _destDir; + } + + template + void CacheProviderContext::addCacheDir(const zypp::Pathname &p) + { + _cacheDirs.push_back ( p ); + } + + template + const std::vector &CacheProviderContext::cacheDirs() const + { + return _cacheDirs; + } + + + template class CacheProviderContext; + template class CacheProviderContext; + + + namespace { + + using namespace zyppng::operators; + + class CacheMissException : public zypp::Exception + { + public: + CacheMissException( const zypp::Pathname &filename ) + : zypp::Exception( zypp::str::Str() << filename << " not found in target cache" ) { } + }; + + template + struct showme; + + template + struct ProvideFromCacheOrMediumLogic : public LogicBase { + protected: + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + using CacheProviderContextRefType = std::conditional_t, AsyncCacheProviderContextRef, SyncCacheProviderContextRef>; + using ContextType = typename remove_smart_ptr_t::ContextType; + using ProvideType = typename ContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + public: + ProvideFromCacheOrMediumLogic( CacheProviderContextRefType cacheContext, MediaHandle &&medium, zypp::Pathname &&file, ProvideFileSpec &&filespec ) + : _ctx( std::move(cacheContext) ) + , _medium( std::move(medium) ) + , _file(std::move( file )) + , _filespec( std::move(filespec) ) {} + + MaybeAsyncRef> execute() { + + return findFileInCache( ) + | [this]( expected cached ) -> MaybeAsyncRef> { + if ( !cached ) { + MIL << "Didn't find " << _file << " in the caches, providing from medium" << std::endl; + + // we didn't find it in the caches or the lookup failed, lets provide and check it + std::shared_ptr provider = _ctx->zyppContext()->provider(); + return provider->provide( _medium, _file, _filespec ) + | and_then( [this]( ProvideRes res ) { + return verifyFile( res.file() ) + | and_then( [res = res]() { + return expected::success( std::move(res) ); + }); + }) + | and_then( ProvideType::copyResultToDest( _ctx->zyppContext()->provider(), _ctx->destDir() / _file ) ) + | and_then( []( zypp::ManagedFile &&file ){ + file.resetDispose (); + return make_expected_success (std::move(file)); + }) ; + + } else { + + return verifyFile ( cached.get() ) + | and_then([ this, cachedFile = cached.get() ]() mutable { + if ( cachedFile == _ctx->destDir() / _file ) { + cachedFile.resetDispose(); // make sure dispose is reset + return makeReadyResult( expected::success(std::move(cachedFile) )); + } + + const auto &targetPath = _ctx->destDir() / _file; + zypp::filesystem::assert_dir( targetPath.dirname () ); + + return _ctx->zyppContext()->provider()->copyFile( cachedFile, _ctx->destDir() / _file ) + | and_then( [cachedFile]( zypp::ManagedFile &&f) { f.resetDispose(); return make_expected_success (std::move(f)); }); + }); + } + }; + } + + protected: + /*! + * Looks for a specific file in a cache dir, if it exists there and the checksum matches the one in the \sa ProvideFileSpec + * it is used and returned. + */ + MaybeAsyncRef> findFileInCache( ) { + + // No checksum - no match + if ( _filespec.checksum().empty() ) + return makeReadyResult( expected::error(std::make_exception_ptr( CacheMissException(_file) )) ); + + const auto &confDirs = _ctx->cacheDirs(); + const auto targetFile = _ctx->destDir() / _file ; + std::vector caches; + caches.push_back( _ctx->destDir() ); + caches.insert( caches.end(), confDirs.begin(), confDirs.end() ); + + auto makeSearchPipeline = [this, targetFile]( zypp::Pathname cachePath ){ + zypp::Pathname cacheFilePath( cachePath / _file ); + zypp::PathInfo cacheFileInfo( cacheFilePath ); + if ( !cacheFileInfo.isExist () ) { + return makeReadyResult(expected::error( std::make_exception_ptr (CacheMissException(_file)) )); + } else { + auto provider = _ctx->zyppContext()->provider(); + + // calc checksum, but do not use the workflow. Here we don't want to ask the user if a wrong checksum should + // be accepted + return provider->checksumForFile( cacheFilePath, _filespec.checksum().type() ) + | and_then([this, cacheFilePath, targetFile]( zypp::CheckSum sum ) { + + auto mgdFile = zypp::ManagedFile( cacheFilePath ); + + // if the file is in the target dir, make sure to release it if its not used + if ( cacheFilePath == targetFile ) + mgdFile.setDispose ( zypp::filesystem::unlink ); + + if ( sum == _filespec.checksum () ) { + // we found the file! + return expected::success( std::move(mgdFile) ); + } + + return expected::error( std::make_exception_ptr (CacheMissException(_file)) ); + }); + } + }; + + auto defVal = expected::error( std::make_exception_ptr (CacheMissException(_file) ) ); + return std::move(caches) | firstOf( std::move(makeSearchPipeline), std::move(defVal), detail::ContinueUntilValidPredicate() ); + } + + MaybeAsyncRef> verifyFile ( const zypp::Pathname &dlFilePath ) { + + return zypp::Pathname( dlFilePath ) + | [this]( zypp::Pathname &&dlFilePath ) { + if ( !_filespec.checksum().empty () ) { + return CheckSumWorkflow::verifyChecksum( _ctx->zyppContext(), _filespec.checksum (), std::move(dlFilePath) ); + } + return makeReadyResult(expected::success()); + }; + // add other verifier here via and_then(), like a signature based one + } + + CacheProviderContextRefType _ctx; + MediaHandle _medium; + zypp::Pathname _file; + ProvideFileSpec _filespec; + }; + } + + namespace DownloadWorkflow { + + AsyncOpRef > provideToCacheDir( AsyncCacheProviderContextRef cacheContext, ProvideMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec ) + { + return SimpleExecutor>>::run( std::move(cacheContext), std::move(medium), std::move(file), std::move(filespec) ); + } + + expected provideToCacheDir(SyncCacheProviderContextRef cacheContext, SyncMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec ) + { + return SimpleExecutor>>::run( std::move(cacheContext), std::move(medium), std::move(file), std::move(filespec) ); + } + + } + +} diff --git a/zypp/ng/workflows/downloadwf.h b/zypp/ng/workflows/downloadwf.h new file mode 100644 index 0000000..91e60d7 --- /dev/null +++ b/zypp/ng/workflows/downloadwf.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_WORKFLOWS_DOWNLOAD_INCLUDED +#define ZYPP_NG_WORKFLOWS_DOWNLOAD_INCLUDED + +#include +#include +#include + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (Context); + ZYPP_FWD_DECL_TYPE_WITH_REFS (SyncContext); + ZYPP_FWD_DECL_TYPE_WITH_REFS (ProgressObserver); + + class ProvideMediaHandle; + class SyncMediaHandle; + class ProvideFileSpec; + + template + class CacheProviderContext : public Base + { + protected: + ZYPP_ADD_PRIVATE_CONSTR_HELPER(); + public: + using ContextRefType = ZyppContextRefType; + using ContextType = typename ZyppContextRefType::element_type; + using ProvideType = typename ContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + + ZYPP_DECL_PRIVATE_CONSTR_ARGS(CacheProviderContext, ZyppContextRefType zyppContext, zypp::Pathname destDir ); + + const ContextRefType &zyppContext() const; + const zypp::Pathname &destDir() const; + + void addCacheDir( const zypp::Pathname &p ); + const std::vector &cacheDirs() const; + + + protected: + ContextRefType _zyppContext; + zypp::Pathname _destDir; + std::vector _cacheDirs; + }; + + using AsyncCacheProviderContext = CacheProviderContext; + using SyncCacheProviderContext = CacheProviderContext; + ZYPP_FWD_DECL_REFS(AsyncCacheProviderContext); + ZYPP_FWD_DECL_REFS(SyncCacheProviderContext); + + namespace DownloadWorkflow { + AsyncOpRef> provideToCacheDir( AsyncCacheProviderContextRef cacheContext, ProvideMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec ); + expected provideToCacheDir( SyncCacheProviderContextRef cacheContext, SyncMediaHandle medium, zypp::Pathname file, ProvideFileSpec filespec ); + } + +} + + +#endif // ZYPP_NG_WORKFLOWS_DOWNLOAD_INCLUDED diff --git a/zypp/ng/workflows/keyringwf.cc b/zypp/ng/workflows/keyringwf.cc new file mode 100644 index 0000000..278a6b3 --- /dev/null +++ b/zypp/ng/workflows/keyringwf.cc @@ -0,0 +1,354 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "keyringwf.h" +#include "logichelpers.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng::KeyRingWorkflow { + + template + struct ImportKeyFromRepoLogic : public LogicBase { + + using ZyppContextRefType = MaybeAsyncContextRef; + using ZyppContextType = remove_smart_ptr_t; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + public: + ImportKeyFromRepoLogic( ZyppContextRefType context, std::string &&keyId, zypp::RepoInfo &&info ) + : _context( std::move(context) ), _keyId(std::move(keyId)), _repo( std::move(info) ) + { } + + MaybeAsyncRef execute () { + + using namespace zyppng::operators; + using zyppng::operators::operator|; + using zyppng::expected; + + if ( _keyId.empty() || !_context ) + return makeReadyResult(false); + + const zypp::ZConfig &conf = _context->config(); + zypp::Pathname cacheDir = conf.repoManagerRoot() / conf.pubkeyCachePath(); + + return RepoInfoWorkflow::provideKey( _context, _repo, _keyId, cacheDir ) + | [this, cacheDir]( zypp::Pathname myKey ) { + if ( myKey.empty() ) + // if we did not find any keys, there is no point in checking again, break + return false; + + zypp::PublicKey key; + try { + key = zypp::PublicKey( myKey ); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + return false; + } + + if ( !key.isValid() ) { + ERR << "Key [" << _keyId << "] from cache: " << cacheDir << " is not valid" << std::endl; + return false; + } + + MIL << "Key [" << _keyId << "] " << key.name() << " loaded from cache" << std::endl; + + zypp::KeyContext context; + context.setRepoInfo( _repo ); + if ( !KeyRingReportHelper(_context).askUserToAcceptPackageKey( key, context ) ) { + return false; + } + + MIL << "User wants to import key [" << _keyId << "] " << key.name() << " from cache" << std::endl; + try { + _context->keyRing()->importKey( key, true ); + } catch ( const zypp::KeyRingException &e ) { + ZYPP_CAUGHT(e); + ERR << "Failed to import key: "<<_keyId; + return false; + } + return true; + }; + } + + ZyppContextRefType _context; + std::string _keyId; + zypp::RepoInfo _repo; + }; + + bool provideAndImportKeyFromRepository( SyncContextRef ctx, std::string id_r, zypp::RepoInfo info_r ) + { + return SimpleExecutor>::run( ctx, std::move(id_r), std::move(info_r) ); + } + + AsyncOpRef provideAndImportKeyFromRepository( ContextRef ctx, std::string id_r, zypp::RepoInfo info_r) + { + return SimpleExecutor>::run( ctx, std::move(id_r), std::move(info_r) ); + } + + namespace { + + /*! + * \class VerifyFileSignatureLogic + * Implementation of the logic part for the verifyFileSignature workflow + */ + template + struct VerifyFileSignatureLogic : public LogicBase + { + ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + + using ZyppContextRefType = MaybeAsyncContextRef; + using KeyTrust = zypp::KeyRingReport::KeyTrust; + + VerifyFileSignatureLogic( ZyppContextRefType zyppContext, KeyRingRef &&keyRing, zypp::keyring::VerifyFileContext &&ctx ) + : _zyppContext( std::move(zyppContext) ) + , _keyringReport( _zyppContext ) + , _keyRing( std::move(keyRing) ) + , _verifyContext( std::move(ctx) ) + { } + + struct FoundKeyData { + zypp::PublicKeyData _foundKey; + zypp::Pathname _whichKeyRing; + bool trusted = false; + }; + + MaybeAsyncRef findKey ( const std::string &id ) { + + using zyppng::operators::operator|; + + if ( id.empty() ) + return makeReadyResult(FoundKeyData{zypp::PublicKeyData(), zypp::Pathname()}); + + // does key exists in trusted keyring + zypp::PublicKeyData trustedKeyData( _keyRing->pimpl().publicKeyExists( id, _keyRing->pimpl().trustedKeyRing() ) ); + if ( trustedKeyData ) + { + MIL << "Key is trusted: " << trustedKeyData << std::endl; + + // lets look if there is an updated key in the + // general keyring + zypp::PublicKeyData generalKeyData( _keyRing->pimpl().publicKeyExists( id, _keyRing->pimpl().generalKeyRing() ) ); + if ( generalKeyData ) + { + // bnc #393160: Comment #30: Compare at least the fingerprint + // in case an attacker created a key the the same id. + // + // FIXME: bsc#1008325: For keys using subkeys, we'd actually need + // to compare the subkey sets, to tell whether a key was updated. + // because created() remains unchanged if the primary key is not touched. + // For now we wait until a new subkey signs the data and treat it as a + // new key (else part below). + if ( trustedKeyData.fingerprint() == generalKeyData.fingerprint() + && trustedKeyData.created() < generalKeyData.created() ) + { + MIL << "Key was updated. Saving new version into trusted keyring: " << generalKeyData << std::endl; + _keyRing->importKey( _keyRing->pimpl().exportKey( generalKeyData, _keyRing->pimpl().generalKeyRing() ), true ); + trustedKeyData = _keyRing->pimpl().publicKeyExists( id, _keyRing->pimpl().trustedKeyRing() ); // re-read: invalidated by import? + } + } + + return makeReadyResult( FoundKeyData{ trustedKeyData, _keyRing->pimpl().trustedKeyRing(), true } ); + } + else + { + zypp::PublicKeyData generalKeyData( _keyRing->pimpl().publicKeyExists( id, _keyRing->pimpl().generalKeyRing() ) ); + if ( generalKeyData ) + { + zypp::PublicKey key( _keyRing->pimpl().exportKey( generalKeyData, _keyRing->pimpl().generalKeyRing() ) ); + MIL << "Key [" << id << "] " << key.name() << " is not trusted" << std::endl; + + // ok the key is not trusted, ask the user to trust it or not + zypp::KeyRingReport::KeyTrust reply = _keyringReport.askUserToAcceptKey( key, _verifyContext.keyContext() ); + if ( reply == zypp::KeyRingReport::KEY_TRUST_TEMPORARILY || + reply == zypp::KeyRingReport::KEY_TRUST_AND_IMPORT ) + { + zypp::Pathname whichKeyring; + + MIL << "User wants to trust key [" << id << "] " << key.name() << std::endl; + + if ( reply == zypp::KeyRingReport::KEY_TRUST_AND_IMPORT ) + { + MIL << "User wants to import key [" << id << "] " << key.name() << std::endl; + _keyRing->importKey( key, true ); + whichKeyring = _keyRing->pimpl().trustedKeyRing(); + } + else + whichKeyring = _keyRing->pimpl().generalKeyRing(); + + return makeReadyResult(FoundKeyData { std::move(generalKeyData), std::move(whichKeyring), true }); + } + else + { + MIL << "User does not want to trust key [" << id << "] " << key.name() << std::endl; + return makeReadyResult(FoundKeyData { std::move(generalKeyData), _keyRing->pimpl().generalKeyRing(), false }); + } + } + else if ( ! _verifyContext.keyContext().empty() ) + { + // try to find the key in the repository info + return provideAndImportKeyFromRepository ( _zyppContext, id, _verifyContext.keyContext().repoInfo() ) + | [this, id]( bool success ) { + if ( !success ) { + return FoundKeyData{ zypp::PublicKeyData(), zypp::Pathname() }; + } + return FoundKeyData{ _keyRing->pimpl().publicKeyExists( id, _keyRing->pimpl().trustedKeyRing() ), _keyRing->pimpl().trustedKeyRing(), true }; + }; + } + } + return makeReadyResult(FoundKeyData{ zypp::PublicKeyData(), zypp::Pathname() }); + } + + // returns std::pair + auto execute () { + + _verifyContext.resetResults(); + const zypp::Pathname & file { _verifyContext.file() }; + const zypp::Pathname & signature { _verifyContext.signature() }; + const std::string & filedesc { _verifyContext.shortFile() }; + + MIL << "Going to verify signature for " << filedesc << " ( " << file << " ) with " << signature << std::endl; + + // if signature does not exists, ask user if they want to accept unsigned file. + if( signature.empty() || (!zypp::PathInfo( signature ).isExist()) ) + { + bool res = _keyringReport.askUserToAcceptUnsignedFile( filedesc, _verifyContext.keyContext() ); + MIL << "askUserToAcceptUnsignedFile: " << res << std::endl; + return makeReadyResult( makeReturn(res) ); + } + + // get the id of the signature (it might be a subkey id!) + _verifyContext.signatureId( _keyRing->readSignatureKeyId( signature ) ); //throws ! + const std::string & id = _verifyContext.signatureId(); + + // collect the buddies + std::list buddies; // Could be imported IFF the file is validated by a trusted key + for ( const auto & sid : _verifyContext.buddyKeys() ) { + if ( not zypp::PublicKeyData::isSafeKeyId( sid ) ) { + WAR << "buddy " << sid << ": key id is too short to safely identify a gpg key. Skipping it." << std::endl; + continue; + } + if ( _keyRing->pimpl().trustedPublicKeyExists( sid ) ) { + MIL << "buddy " << sid << ": already in trusted key ring. Not needed." << std::endl; + continue; + } + auto pk = _keyRing->pimpl().publicKeyExists( sid ); + if ( not pk ) { + WAR << "buddy " << sid << ": not available in the public key ring. Skipping it." << std::endl; + continue; + } + if ( pk.providesKey(id) ) { + MIL << "buddy " << sid << ": is the signing key. Handled separately." << std::endl; + continue; + } + MIL << "buddy " << sid << ": candidate for auto import. Remeber it." << std::endl; + buddies.push_back( pk ); + } + + using zyppng::operators::operator|; + return findKey( id ) | [this, id, buddies=std::move(buddies)]( FoundKeyData res ) { + + const zypp::Pathname & file { _verifyContext.file() }; + const zypp::KeyContext & keyContext { _verifyContext.keyContext() }; + const zypp::Pathname & signature { _verifyContext.signature() }; + const std::string & filedesc { _verifyContext.shortFile() }; + + if ( res._foundKey ) { + + // we found a key but it is not trusted ( e.g. user did not want to trust it ) + if ( !res.trusted ) + return makeReturn(false); + + // it exists, is trusted, does it validate? + _verifyContext.signatureIdTrusted( res._whichKeyRing == _keyRing->pimpl().trustedKeyRing() ); + _keyringReport.infoVerify( filedesc, res._foundKey, keyContext ); + if ( _keyRing->pimpl().verifyFile( file, signature, res._whichKeyRing ) ) + { + _verifyContext.fileValidated( true ); + if ( _verifyContext.signatureIdTrusted() && not buddies.empty() ) { + // Check for buddy keys to be imported... + MIL << "Validated with trusted key: importing buddy list..." << std::endl; + _keyringReport.reportAutoImportKey( buddies, res._foundKey, keyContext ); + for ( const auto & kd : buddies ) { + _keyRing->importKey( _keyRing->pimpl().exportKey( kd, _keyRing->pimpl().generalKeyRing() ), true ); + } + } + return makeReturn(_verifyContext.fileValidated()); // signature is actually successfully validated! + } + else + { + bool userAnswer = _keyringReport.askUserToAcceptVerificationFailed( filedesc, _keyRing->pimpl().exportKey( res._foundKey, res._whichKeyRing ), keyContext ); + MIL << "askUserToAcceptVerificationFailed: " << userAnswer << std::endl; + return makeReturn(userAnswer); + } + } else { + // signed with an unknown key... + MIL << "File [" << file << "] ( " << filedesc << " ) signed with unknown key [" << id << "]" << std::endl; + bool res = _keyringReport.askUserToAcceptUnknownKey( filedesc, id, _verifyContext.keyContext() ); + MIL << "askUserToAcceptUnknownKey: " << res << std::endl; + return makeReturn(res); + } + + return makeReturn(false); + }; + } + + protected: + ZyppContextRefType _zyppContext; + KeyRingReportHelper _keyringReport; + KeyRingRef _keyRing; + zypp::keyring::VerifyFileContext _verifyContext; + + private: + inline std::pair makeReturn( bool res ){ + _verifyContext.fileAccepted( res ); + return std::make_pair( res, std::move(_verifyContext) ) ; + } + }; + } + + std::pair verifyFileSignature( SyncContextRef zyppContext, zypp::keyring::VerifyFileContext &&context_r ) + { + auto kr = zyppContext->keyRing(); + return SimpleExecutor >>::run( std::move(zyppContext), std::move(kr), std::move(context_r) ); + } + + AsyncOpRef> verifyFileSignature( ContextRef zyppContext, zypp::keyring::VerifyFileContext &&context_r ) + { + auto kr = zyppContext->keyRing(); + return SimpleExecutor >>::run( std::move(zyppContext), std::move(kr), std::move(context_r) ); + } + + std::pair verifyFileSignature( SyncContextRef zyppContext, zypp::KeyRing_Ptr keyRing, zypp::keyring::VerifyFileContext &&context_r ) + { + return SimpleExecutor >>::run( std::move(zyppContext), std::move(keyRing), std::move(context_r) ); + } + + AsyncOpRef> verifyFileSignature(ContextRef zyppContext, zypp::KeyRing_Ptr keyRing, zypp::keyring::VerifyFileContext &&context_r ) + { + return SimpleExecutor >>::run( std::move(zyppContext), std::move(keyRing), std::move(context_r) ); + } + +} diff --git a/zypp/ng/workflows/keyringwf.h b/zypp/ng/workflows/keyringwf.h new file mode 100644 index 0000000..cd25b08 --- /dev/null +++ b/zypp/ng/workflows/keyringwf.h @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_KEYRINGWORKFLOW_INCLUDED +#define ZYPP_NG_KEYRINGWORKFLOW_INCLUDED + +#include +#include + +namespace zypp { + class RepoInfo; + DEFINE_PTR_TYPE(KeyRing); + + namespace keyring { + class VerifyFileContext; + } + +} + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (Context); + ZYPP_FWD_DECL_TYPE_WITH_REFS (SyncContext); + + /*! + * \namespace KeyRingWorkflow + * Contains all KeyRing related workflows. + * + * \sa zypp::KeyRing + */ + namespace KeyRingWorkflow { + + /** + * Try to find the \a id in key cache or repository specified in \a info. Ask the user to trust + * the key if it was found + */ + bool provideAndImportKeyFromRepository(SyncContextRef ctx, std::string id_r, zypp::RepoInfo info_r ); + AsyncOpRef provideAndImportKeyFromRepository(ContextRef ctx, std::string id_r, zypp::RepoInfo info_r ); + + /** + * Follows a signature verification interacting with the user. + * The bool returned depends on user decision to trust or not. + * + * To propagate user decisions, either connect to the \ref KeyRingReport + * or use its static methods to set the desired defaults. + * + * A second bool passed as reference arg \a sigValid_r tells whether the + * signature was actually successfully verified. If \a sigValid_r returns + * \c false, but the method \c true, you know it's due to user callback or + * defaults. + * + * \code + * struct KeyRingReportReceive : public callback::ReceiveReport + * { + * KeyRingReportReceive() { connect(); } + * + * // Overload the virtual methods to return the appropriate values. + * virtual bool askUserToAcceptUnsignedFile( const std::string &file ); + * ... + * }; + * \endcode + * + * \param keyRing The KeyRing instance the file verification should run against + * \param context_r The verification context containing all required informations + * + * \returns a std::pair, containing a boolean signalling if the verification was successful or not and the \ref zypp::keyring::VerifyFileContext containing + * more detailed informations. + * + * \see \ref zypp::KeyRingReport + */ + std::pair verifyFileSignature( SyncContextRef zyppContext, zypp::keyring::VerifyFileContext && context_r ); + AsyncOpRef> verifyFileSignature( ContextRef zyppContext, zypp::keyring::VerifyFileContext && context_r ); + + std::pair verifyFileSignature( SyncContextRef zyppContext, zypp::KeyRing_Ptr keyRing, zypp::keyring::VerifyFileContext &&context_r ); + AsyncOpRef> verifyFileSignature( ContextRef zyppContext, zypp::KeyRing_Ptr keyRing, zypp::keyring::VerifyFileContext &&context_r ); + } +} + +#endif diff --git a/zypp/ng/workflows/logichelpers.h b/zypp/ng/workflows/logichelpers.h new file mode 100644 index 0000000..97fdad3 --- /dev/null +++ b/zypp/ng/workflows/logichelpers.h @@ -0,0 +1,229 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_LOGICHELPERS_INCLUDED +#define ZYPP_NG_LOGICHELPERS_INCLUDED + +#include + +namespace zyppng +{ + + namespace detail { + template + struct LogicBaseExec : public Op { }; + + template + struct LogicBaseExec>> : public Op + { + protected: + AsyncOpRef _innerPipeline; + }; + + } + + /*! + * Helper Mixin for types that need to return async results if + * they are compiled in a async context. + */ + template + struct MaybeAsyncMixin + { + // Make the isAsync flag accessible for subclasses. + static constexpr bool is_async = isAsync; + + /*! + * Evaluates to either \a AsyncOpRef or \a Type ,based on the \a isAsync template param. + */ + template + using MaybeAsyncRef = std::conditional_t< isAsync, AsyncOpRef, Type>; + + + protected: + /*! + * Returns the value given in \a res either as \ref AsyncOpRef or as T depending on the + * \a isAsync template param. + */ + template + inline auto makeReadyResult( T &&res ) { + return zyppng::makeReadyResult ( std::forward(res) ); + } + }; + + /*! + * Forward declares some convenience functions from MaybeAsyncMixin class so they can be used directly + * See \ref MaybeAsyncMixin for documentation + */ + #define ZYPP_ENABLE_MAYBE_ASYNC_MIXIN( IsAsync ) \ + using MaybeAsyncMixin::makeReadyResult; \ + template \ + using MaybeAsyncRef = typename MaybeAsyncMixin:: template MaybeAsyncRef + + + + /*! + * Logic base class template, this allows us to implement certain workflows + * in a sync/async agnostic way, based on the OpType the code is either + * sync or async: + * + * \code + * + * // ------------------ computeint.h --------------------------- + * + * // the public interface for the workflows are just functions, usually with some + * // context object just save passing a gazillion of arguments to the func and + * // to carry some state. + * AsyncOpRef> computeInt( ContextRef context ); + * expected computeInt( SyncContextRef context ); + * + * // ------------------ computeint.cc --------------------------- + * + * namespace { + * template < + * typename Executor ///< The Final Executor type that subclasses from ComputeIntLogic + * , typename OpType ///< The SyncOp or AsyncOp result type, LogicBase will derive from it + * > + * struct ComputeIntLogic : public LogicBase + * { + * // declare some helper tools from the base + * ZYPP_ENABLE_LOGIC_BASE(Executor, OpType); + * + * // declare our context type based on the OpType we are + * using ZyppContextRefType = MaybeAsyncContextRef; + * + * // all arguments to the sync/async function are passed to the constructor + * LogicImpl( ZyppContextRefType ctx ) + * : LogicBase() + * , _ctx( std::move(ctx) ) + * {} + * + * // every logic type must implement execute() without any arguments, returning + * // the result type. In async world the pipeline will be stored in the object until its ready + * MaybeAsyncRef<> execute() { + * return executor()->computeSomeInt() + * | and_then( [this]( int result ) { + * std::cout<< "Int calculated as: " << result << std::endl; + * return expected::success(result); + * }); + * } + * + * protected: + * ZyppContextRefType _ctx; + * }; + * + * // AsyncOp Executor for ComputeIntLogic implementation, + * // here we put all code that can not be implementedin a + * // sync/async agnostic way. Usually sending reports to the user. + * // If no such code is required, simply use the \ref SimpleExecutor template + * class ComputeIntAsyncExecutor : public ComputeIntLogic> + * { + * // usually we just want to use Logic's constructors + * using ComputeIntLogic>::ComputeIntLogic; + * AsyncOpRef> computeSomeInt() { + * // .... some implementation that asynchronously computes a int and returns it + * } + * }; + * + * // SyncOp Executor for ComputeIntLogic implementation, + * // here we put all the sync variants of code that can not be implemented in a + * // sync/async agnostic way. Usually sending reports to the user. + * // If no such code is required, simply use the \ref SimpleExecutor template + * class ComputeIntSyncExecutor : public ComputeIntLogic> + * { + * using ComputeIntLogic>::ComputeIntLogic; + * expected computeSomeInt(){ + * // .... some implementation that synchronously computes a int and returns it + * } + * }; + * + * } //namespace + * + * // by overloading this function on the (Sync)ContextRef type other workflow implementations + * // can call the async/sync version just by passing the right parameters + * AsyncOpRef> computeInt( ContextRef context ) { + * // the run() static method is provided by the LogicBase subclass + * return ComputeIntAsyncExecutor::run( std::move(context) ); + * } + * + * expected computeInt( SyncContextRef context ) { + * // the run() static method is provided by the LogicBase subclass + * return ComputeIntSyncExecutor::run( std::move(context) ); + * } + * + * \endcode + */ + template + struct LogicBase : public detail::LogicBaseExec, public MaybeAsyncMixin> { + + using ExecutorType = Executor; + using Result = typename OpType::value_type; + + LogicBase( ){ } + virtual ~LogicBase(){} + + template + static std::enable_if_t< detail::is_async_op_v, AsyncOpRef> run( Args &&...args ) { + auto op = std::make_shared( std::forward(args)... ); + op->asyncExecute(); + return op; + } + + template + static std::enable_if_t< !detail::is_async_op_v, Result> run( Args &&...args ) { + return Executor( std::forward(args)... ).execute(); + } + + + /*! + * Allows access to functionality provided by the \a Executor parent class, + * usually used for sending user reports because those are too different for sync and async. + */ + Executor *executor () { + return static_cast(this); + } + + private: + template + std::enable_if_t< detail::is_async_op_v, void> asyncExecute() { + this->_innerPipeline = static_cast(this)->execute(); + this->_innerPipeline->onReady([this]( auto &&val ){ + this->setReady( std::forward(val) ); + }); + } + }; + + /*! + * Helper base class for the sync + * only parts of a logic implementation + */ + template + struct SyncOp : public Base { + using value_type = Result; + }; + + + template typename Logic , typename OpType> + struct SimpleExecutor : public Logic, OpType> + { + public: + template + SimpleExecutor( Args &&...args ) : Logic, OpType>( std::forward(args)...) {} + }; + + + /*! + * Forward declares some convenience functions from Base class so they can be used directly + * See \ref LogicBase for documentation + */ + #define ZYPP_ENABLE_LOGIC_BASE(Executor, OpType) \ + using LogicBase::executor; \ + using LogicBase::makeReadyResult; \ + template \ + using MaybeAsyncRef = typename LogicBase:: template MaybeAsyncRef +} +#endif diff --git a/zypp/ng/workflows/mediafacade.cc b/zypp/ng/workflows/mediafacade.cc new file mode 100644 index 0000000..781d21a --- /dev/null +++ b/zypp/ng/workflows/mediafacade.cc @@ -0,0 +1,600 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "mediafacade.h" +#include "zypp/media/MediaHandlerFactory.h" +#include +#include +#include +#include +#include +#include +#include + +namespace zyppng { + + class AttachedSyncMediaInfo : public zypp::base::ReferenceCounted, private zypp::base::NonCopyable + { + + public: + + AttachedSyncMediaInfo( MediaSyncFacadeRef parentRef, zypp::media::MediaAccessId mediaId, zypp::Url baseUrl, ProvideMediaSpec mediaSpec, const zypp::Pathname &locPath ); + + zypp::media::MediaAccessId mediaId () const; + const ProvideMediaSpec &spec() const; + const zypp::Url &url() const; + const std::optional &rootPath() const; + MediaSyncFacadeRef parent() const; + + /*! + * Returns true if \a other requests the same medium as this instance + */ + bool isSameMedium ( const std::vector &urls, const ProvideMediaSpec &spec ); + + // ReferenceCounted interface + protected: + void unref_to(unsigned int) const override; + + private: + zypp::media::MediaAccessId _id; + zypp::Url _attachedUrl; + ProvideMediaSpec _spec; + MediaSyncFacadeRef _parent; + std::optional _localPath; + }; + + IMPL_PTR_TYPE( AttachedSyncMediaInfo ); + + AttachedSyncMediaInfo::AttachedSyncMediaInfo(MediaSyncFacadeRef parentRef, zypp::media::MediaAccessId mediaId, zypp::Url baseUrl, ProvideMediaSpec mediaSpec, const zypp::Pathname &locPath) + : _id( mediaId ) + , _attachedUrl(std::move( baseUrl )) + , _spec(std::move( mediaSpec )) + , _parent(std::move( parentRef )) + , _localPath( locPath ) + {} + + zypp::media::MediaAccessId AttachedSyncMediaInfo::mediaId() const + { + return _id; + } + + const ProvideMediaSpec &AttachedSyncMediaInfo::spec() const + { + return _spec; + } + + const zypp::Url &AttachedSyncMediaInfo::url() const + { + return _attachedUrl; + } + + const std::optional &AttachedSyncMediaInfo::rootPath() const + { + return _localPath; + } + + MediaSyncFacadeRef AttachedSyncMediaInfo::parent() const + { + return _parent; + } + + bool AttachedSyncMediaInfo::isSameMedium(const std::vector &urls, const ProvideMediaSpec &spec) { + + const auto check = _spec.isSameMedium(spec); + if ( !zypp::indeterminate (check) ) + return (bool)check; + + // let the URL rule + return ( std::find( urls.begin(), urls.end(), _attachedUrl ) != urls.end() ); + } + + void AttachedSyncMediaInfo::unref_to( unsigned int count ) const + { + // once count reaches 1 only the MediaSyncFacade holds a reference, + // time to release the medium + if ( count == 1 ) { + _parent->releaseMedium ( this ); + // !!!! careful from here on out 'this' is most likely invalid !!!! + return; + } + } + + + SyncMediaHandle::SyncMediaHandle(){ } + + SyncMediaHandle::SyncMediaHandle(AttachedSyncMediaInfo_Ptr dataPtr) : _data( std::move(dataPtr) ) + { } + + MediaSyncFacadeRef SyncMediaHandle::parent() const + { + return _data->parent(); + } + + bool SyncMediaHandle::isValid() const + { + return _data.get() != nullptr; + } + + const zypp::Url &SyncMediaHandle::baseUrl() const + { + static zypp::Url invalidHandle; + if ( !_data ) + return invalidHandle; + return _data->url(); + } + + const std::optional &SyncMediaHandle::localPath() const + { + static std::optional invalidPath; + if ( !_data ) + return invalidPath; + return _data->rootPath(); + } + + const AttachedSyncMediaInfo &SyncMediaHandle::info() const + { + return *_data; + } + + MediaSyncFacade::Res::Res(MediaHandle hdl, zypp::ManagedFile file) + : _res( std::move(file) ) + , _provideHandle( std::move (hdl) ) + { } + + const zypp::Pathname MediaSyncFacade::Res::file() const { + return _res; + } + + ZYPP_IMPL_PRIVATE_CONSTR (MediaSyncFacade) { } + + std::vector MediaSyncFacade::sanitizeUrls(const std::vector &urls) const + { + std::vector usableMirrs; + std::optional handlerType; + + for ( auto mirrIt = urls.begin() ; mirrIt != urls.end(); mirrIt++ ) { + const auto &s = zypp::media::MediaHandlerFactory::handlerType ( *mirrIt ); + if ( !s ) { + WAR << "URL: " << *mirrIt << " is not supported, ignoring!" << std::endl; + continue; + } + if ( !handlerType ) { + handlerType = *s; + usableMirrs.push_back ( *mirrIt ); + } else { + if ( handlerType == *s) { + usableMirrs.push_back( *mirrIt ); + } else { + WAR << "URL: " << *mirrIt << " has different handler type than the primary URL: "<< usableMirrs.front() <<", ignoring!" << std::endl; + } + } + } + + if ( !handlerType || usableMirrs.empty() ) { + return {}; + } + + return usableMirrs; + } + + expected MediaSyncFacade::attachMedia( const zypp::Url &url, const ProvideMediaSpec &request ) + { + + bool isVolatile = url.schemeIsVolatile(); + + auto effectiveUrl = url; + + std::optional attachId; + zypp::callback::SendReport report; + + // nothing attached, make a new one + zypp::media::MediaManager mgr; + do { + try { + if ( !attachId ) { + + if ( request.medianr() > 1 ) + effectiveUrl = zypp::MediaSetAccess::rewriteUrl( effectiveUrl, request.medianr() ); + + attachId = mgr.open( effectiveUrl ); + if ( !request.mediaFile().empty() ) { + mgr.addVerifier( *attachId, zypp::media::MediaVerifierRef( new zypp::repo::SUSEMediaVerifier( request.mediaFile(), request.medianr() ) ) ); + } + } + + // attach the medium + mgr.attach( *attachId ); + + auto locPath = mgr.localPath( *attachId, "/" ); + auto attachInfo = AttachedSyncMediaInfo_Ptr( new AttachedSyncMediaInfo( shared_this(), *attachId, url, request, locPath ) ); + _attachedMedia.push_back( attachInfo ); + return expected::success( std::move(attachInfo) ); + + } catch ( const zypp::media::MediaException &excp ) { + + ZYPP_CAUGHT(excp); + + // if no one is listening, just return the error as is + if ( !zypp::callback::SendReport::connected() || !attachId ) { + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + + // default action is to cancel + zypp::media::MediaChangeReport::Action user = zypp::media::MediaChangeReport::ABORT; + + do { + // here: Manager tried all not attached drives and could not find the desired medium + // we need to send the media change report + + // set up the reason + auto reason = zypp::media::MediaChangeReport::INVALID; + if( typeid(excp) == typeid( zypp::media::MediaNotDesiredException) ) { + reason = zypp::media::MediaChangeReport::WRONG; + } + + unsigned int devindex = 0; + + std::vector devices; + mgr.getDetectedDevices(*attachId, devices, devindex); + + std::optional currentlyUsed; + if ( devices.size() ) currentlyUsed = devices[devindex]; + + if ( isVolatile ) { + // filter devices that are mounted, aka used, we can not eject them + const auto &mountedDevs = zypp::media::Mount::getEntries(); + std::remove_if( devices.begin (), devices.end(), [&](const std::string &dev) { + zypp::PathInfo devInfo(dev); + return std::any_of( mountedDevs.begin (), mountedDevs.end(), [&devInfo]( const zypp::media::MountEntry &e ) { + zypp::PathInfo pi( e.src ); + return ( pi.isBlk() && pi.devMajor() == devInfo.devMajor() && pi.devMinor() == devInfo.devMinor() ); + }); + }); + + if ( !devices.size () ) { + // Jammed, no currently free device + MIL << "No free device available, return jammed and try again later ( hopefully) " << std::endl; + if ( attachId ) mgr.close ( *attachId ); + return expected::error( ZYPP_EXCPT_PTR(zypp::media::MediaJammedException()) ); + } + + // update index to currenty used dev + bool foundCurrent = false; + if ( currentlyUsed ) { + for ( unsigned int i = 0; i < devices.size(); i++ ) { + if ( devices[i] == *currentlyUsed ) { + foundCurrent = true; + devindex = i; + break; + } + } + } + + if ( !foundCurrent ){ + devindex = 0; // seems 0 is what is set in the handlers too if there is no current + } + } + + user = report->requestMedia ( + effectiveUrl, + request.medianr(), + request.label(), + reason, + excp.asUserHistory(), + devices, + devindex + ); + + MIL << "ProvideFile exception caught, callback answer: " << user << std::endl; + + switch ( user ) { + case zypp::media::MediaChangeReport::ABORT: { + DBG << "Aborting" << std::endl; + if ( attachId ) mgr.close ( *attachId ); + zypp::AbortRequestException aexcp("Aborting requested by user"); + aexcp.remember(excp); + return expected::error( ZYPP_EXCPT_PTR(aexcp) ); + } + case zypp::media::MediaChangeReport::IGNORE: { + DBG << "Skipping" << std::endl; + if ( attachId ) mgr.close ( *attachId ); + zypp::SkipRequestException nexcp("User-requested skipping of a file"); + nexcp.remember(excp); + return expected::error( ZYPP_EXCPT_PTR(nexcp) ); + } + case zypp::media::MediaChangeReport::EJECT: { + DBG << "Eject: try to release" << std::endl; + try + { + // MediaSetAccess does a releaseAll, but we can not release other devices that are in use + // media_mgr.releaseAll(); + mgr.release (*attachId, devindex < devices.size() ? devices[devindex] : ""); + } + catch ( const zypp::Exception & e) + { + ZYPP_CAUGHT(e); + } + break; + } + case zypp::media::MediaChangeReport::RETRY: + case zypp::media::MediaChangeReport::CHANGE_URL: { + // retry + DBG << "Going to try again" << std::endl; + + // invalidate current media access id + if ( attachId ) { + mgr.close(*attachId); + attachId.reset(); + } + + // not attaching, media set will do that for us + // this could generate uncaught exception (#158620) + break; + } + default: { + DBG << "Don't know, let's ABORT" << std::endl; + if ( attachId ) mgr.close ( *attachId ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } + } while( user == zypp::media::MediaChangeReport::EJECT ); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + if ( attachId ) mgr.close ( *attachId ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } catch (...) { + // didn't work -> clean up + if ( attachId ) mgr.close ( *attachId ); + return expected::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + } while ( true ); + } + + expected MediaSyncFacade::attachMedia( const std::vector &urls, const ProvideMediaSpec &request ) + { + // rewrite and sanitize the urls if required + std::vector useableUrls = sanitizeUrls(urls); + + if ( useableUrls.empty () ) + return expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No valid mirrors available") )); + + // first try and find a already attached medium + auto i = std::find_if( _attachedMedia.begin (), _attachedMedia.end(), [&]( const AttachedSyncMediaInfo_Ptr &medium ) { + return medium->isSameMedium( useableUrls, request ); + }); + + if ( i != _attachedMedia.end() ) { + return expected::success( *i ); + } + + + std::exception_ptr lastError; + std::exception_ptr jammedError; + + + // from here call attachMedia with just one URL + // catch errors, if one of the URLS returns JAMMED, remember it + // continue to try other URLs, if they all fail and JAMMED was remembered + // return it, otherwise the last error + + for ( const auto &url : useableUrls ) { + try { + return expected::success( attachMedia( url, request ).unwrap() ); + } catch ( zypp::media::MediaJammedException &e) { + ZYPP_CAUGHT(e); + if ( !jammedError ) jammedError = std::current_exception (); + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + lastError = std::current_exception(); + } catch (...) { + // didn't work -> clean up + lastError = std::current_exception(); + } + } + + if ( jammedError ) { + // if we encountered a jammed error return it, there might be still a chance + // that invoking the provide again after other pipelines have finished might succeed + return expected::error( ZYPP_FWD_EXCPT(jammedError) ); + } else if ( lastError ) { + // if we have a error stored, return that one + return expected::error( ZYPP_FWD_EXCPT(lastError) ); + } + + return expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaException("No URL to attach") ) ); + } + + zyppng::MediaSyncFacade::~MediaSyncFacade() + { + // this should never happen because every handle has a reference to the media manager, but still add a debug output + // so we know in case we have weird behavior. + if ( _attachedMedia.size () ) { + WAR << "Releasing zyppng::MediaSyncFacade with still valid MediaHandles, this is a bug!" << std::endl; + } + } + + expected MediaSyncFacade::prepareMedia(const std::vector &urls, const ProvideMediaSpec &request) + { + const auto &useableUrls = sanitizeUrls(urls); + if ( useableUrls.empty () ) + return expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("No valid mirrors available") )); + return expected::success( shared_this(), std::move(useableUrls), request ); + } + + expected MediaSyncFacade::prepareMedia(const zypp::Url &url, const ProvideMediaSpec &request) + { + return prepareMedia( std::vector{url}, request ); + } + + expected MediaSyncFacade::attachMediaIfNeeded( LazyMediaHandle lazyHandle) + { + using namespace zyppng::operators; + if ( lazyHandle.attached() ) + return expected::success( *lazyHandle.handle() ); + + MIL << "Attaching lazy medium with label: [" << lazyHandle.spec().label() << "]" << std::endl; + + return attachMedia( lazyHandle.urls(), lazyHandle.spec () ) + | and_then([lazyHandle]( MediaHandle handle ) { + lazyHandle._sharedData->_mediaHandle = handle; + return expected::success( std::move(handle) ); + }); + } + + expected MediaSyncFacade::provide(const std::vector &urls, const ProvideFileSpec &request) + { + using namespace zyppng::operators; + + if ( !urls.size() ) + return expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaException("Can not provide a file without a URL.") )); + + std::optional> lastErr; + for ( const zypp::Url& file_url : urls ) { + + zypp::Url url(file_url); + zypp::Pathname fileName(url.getPathName()); + url.setPathName ("/"); + + expected res = attachMedia( url, ProvideMediaSpec( "" ) ) + | and_then( [&, this]( const MediaSyncFacade::MediaHandle& handle ) { + return provide( handle, fileName, request.asOnMediaLocation(fileName, 1)); + }); + + if ( res ) + return res; + + lastErr = res; + } + + // we always should have a last error, except if the URLs are empty + if ( lastErr ) + return *lastErr; + + // we should not get here, but if we do simply use the first entry to make a not found error + zypp::Url url( urls.front() ); + zypp::Pathname fileName(url.getPathName()); + url.setPathName ("/"); + return expected::error( ZYPP_EXCPT_PTR ( zypp::media::MediaFileNotFoundException( url, fileName ))); + + } + + expected MediaSyncFacade::provide(const zypp::Url &url, const ProvideFileSpec &request) + { + return provide( std::vector{url}, request ); + } + + expected MediaSyncFacade::provide(const MediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request) + { + zypp::media::MediaManager mgr; + const auto &handleInfo = attachHandle.info(); + + try { + if ( request.checkExistsOnly() ) { + if ( !mgr.doesFileExist ( handleInfo.mediaId (), fileName ) ) { + return expected::error( ZYPP_EXCPT_PTR( zypp::media::MediaFileNotFoundException( handleInfo.url(), fileName ) ) ); + } + + // we return a result pointing to a non existant file, since the code just asked us to check if the file exists + return expected::success( attachHandle, zypp::ManagedFile( mgr.localPath( handleInfo.mediaId(), fileName ) ) ); + + } else { + mgr.provideFile( handleInfo.mediaId (), request.asOnMediaLocation( fileName, handleInfo.spec().medianr()) ); + + zypp::ManagedFile locFile( mgr.localPath( handleInfo.mediaId(), fileName ) ); + + // do not clean up files for now, they are cleaned up anyways on detach +#if 0 + // if the file is downloaded we want to clean it up again + if ( handleInfo.url().schemeIsDownloading() ) + locFile.setDispose ( zypp::filesystem::unlink ); +#endif + + return expected::success( attachHandle, locFile ); + } + } catch ( const zypp::Exception &e ) { + ZYPP_CAUGHT(e); + return expected::error(ZYPP_FWD_CURRENT_EXCPT()); + } catch (...) { + return expected::error(ZYPP_FWD_CURRENT_EXCPT()); + } + } + + expected MediaSyncFacade::provide( const LazyMediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request ) + { + using namespace zyppng::operators; + return attachMediaIfNeeded ( attachHandle ) + | and_then([weakMe = weak_this(), fName = fileName, req = request ]( MediaHandle handle ){ + auto me = weakMe.lock(); + if ( !me ) + return expected::error(ZYPP_EXCPT_PTR(zypp::Exception("Provide was released during a operation"))); + return me->provide( handle, fName, req); + }); + } + + zyppng::expected MediaSyncFacade::checksumForFile(const zypp::Pathname &p, const std::string &algorithm) + { + try { + return expected::success( zypp::CheckSum( algorithm, zypp::filesystem::checksum ( p, algorithm ) ) ); + } catch(...) { + return expected::error ( std::current_exception () ); + } + } + + expected MediaSyncFacade::copyFile(const zypp::Pathname &source, const zypp::Pathname &target) + { + try { + // do what Provide would do and make a URL + zypp::Url url("copy:///"); + url.setPathName( source ); + + auto sourcePi = zypp::PathInfo(source); + if ( !sourcePi.isExist() ) { + return expected::error ( ZYPP_EXCPT_PTR( zypp::media::MediaFileNotFoundException( url, "" ) ) ); + } + if ( !sourcePi.isFile () ) + return expected::error ( ZYPP_EXCPT_PTR( zypp::media::MediaNotAFileException( url, "" ) ) ); + + auto res = zypp::filesystem::hardlinkCopy( source, target.asString() ); + if ( res == 0 ) { + return expected::success( zypp::ManagedFile( target, zypp::filesystem::unlink ) ); + } else { + return expected::error ( ZYPP_EXCPT_PTR( zypp::media::MediaException( zypp::str::Str() << "Failed to create file " << target << " errno: " << res ) ) ); + } + } catch(...) { + return expected::error ( std::current_exception () ); + } + } + + expected MediaSyncFacade::copyFile(zyppng::MediaSyncFacade::Res source, const zypp::Pathname &target) + { + // not much to do here, since this will block until the file has been copied we do not need to remember the ProvideRes + return copyFile( source.file(), target ); + } + + void zyppng::MediaSyncFacade::releaseMedium(const AttachedSyncMediaInfo *ptr) + { + if ( !ptr ) return; + + auto i = std::find_if(_attachedMedia.begin (), _attachedMedia.end(), [&]( const auto &p ) { return p.get() == ptr; } ); + + try { + zypp::media::MediaManager mgr; + mgr.close ( ptr->mediaId() ); + } catch ( const zypp::Exception & e ) { + ZYPP_CAUGHT(e); + } + + if ( i != _attachedMedia.end() ) { + _attachedMedia.erase(i); + } else { + ERR << "Releasing unknown medium " << ptr->mediaId () << " should not happen"; + } + } + + +} diff --git a/zypp/ng/workflows/mediafacade.h b/zypp/ng/workflows/mediafacade.h new file mode 100644 index 0000000..034eb14 --- /dev/null +++ b/zypp/ng/workflows/mediafacade.h @@ -0,0 +1,132 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_MEDIASETFACADE_INCLUDED +#define ZYPP_NG_MEDIASETFACADE_INCLUDED + +#include +#include +#include +#include +#include + + +#include + +namespace zyppng { + ZYPP_FWD_DECL_TYPE_WITH_REFS ( MediaSyncFacade ); + DEFINE_PTR_TYPE(AttachedSyncMediaInfo); + + + class SyncMediaHandle { + public: + + using ParentType = MediaSyncFacade; + + SyncMediaHandle(); + SyncMediaHandle( AttachedSyncMediaInfo_Ptr dataPtr ); + MediaSyncFacadeRef parent() const; + bool isValid () const; + const zypp::Url &baseUrl() const; + const std::optional &localPath() const; + const AttachedSyncMediaInfo &info ()const; + + private: + AttachedSyncMediaInfo_Ptr _data; + }; + + /*! + * A Facade class that mimics the behavior of the Provide + * class just in a sync way. Meaning every operation will finish immediately + * instead of returning a \ref AsyncOp. + */ + class ZYPP_API MediaSyncFacade : public Base + { + ZYPP_ADD_CREATE_FUNC(MediaSyncFacade); + public: + + friend class AttachedSyncMediaInfo; + + using MediaHandle = SyncMediaHandle; + using LazyMediaHandle = ::zyppng::LazyMediaHandle; + + class Res { + public: + + Res( MediaHandle hdl, zypp::ManagedFile file ); + + /*! + * Returns the path to the provided file + */ + const zypp::Pathname file () const; + + /*! + * Returns a reference to the internally used managed file instance. + * \note If you obtain this for a file that is inside the providers working directory ( e.g. a provide result for a download ), + * the continued use after the Provide instance was relased is undefined behaviour and not supported! + */ + const zypp::ManagedFile & asManagedFile () const { + return _res; + } + + private: + zypp::ManagedFile _res; + MediaHandle _provideHandle; + }; + + ZYPP_DECL_PRIVATE_CONSTR ( MediaSyncFacade ); + ~MediaSyncFacade() override; + + expected prepareMedia ( const std::vector &urls, const ProvideMediaSpec &request ); + expected prepareMedia ( const zypp::Url &url, const ProvideMediaSpec &request ); + + expected attachMediaIfNeeded( LazyMediaHandle lazyHandle ); + expected attachMedia( const std::vector &urls, const ProvideMediaSpec &request ); + expected attachMedia( const zypp::Url &url, const ProvideMediaSpec &request ); + + expected provide( const std::vector &urls, const ProvideFileSpec &request ); + expected provide( const zypp::Url &url, const ProvideFileSpec &request ); + expected provide( const MediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request ); + expected provide( const LazyMediaHandle &attachHandle, const zypp::Pathname &fileName, const ProvideFileSpec &request ); + + + /*! + * Schedules a job to calculate the checksum for the given file + */ + expected checksumForFile ( const zypp::Pathname &p, const std::string &algorithm ); + + /*! + * Schedules a copy job to copy a file from \a source to \a target + */ + expected copyFile ( const zypp::Pathname &source, const zypp::Pathname &target ); + expected copyFile ( Res source, const zypp::Pathname &target ); + + static auto copyResultToDest ( MediaSyncFacadeRef provider, const zypp::Pathname &targetPath ) { + return [ providerRef=std::move(provider), targetPath = targetPath ]( Res &&file ){ + zypp::filesystem::assert_dir( targetPath.dirname () ); + return providerRef->copyFile( std::move(file), targetPath ); + }; + } + + protected: + void releaseMedium ( const AttachedSyncMediaInfo *ptr ); + + private: + std::vector sanitizeUrls(const std::vector &urls) const; + std::vector _attachedMedia; + }; + + using SyncProvideRes = MediaSyncFacade::Res; + + //template + //using MediaFacade = std::conditional_t; +} + + + +#endif diff --git a/zypp/ng/workflows/repoinfowf.cc b/zypp/ng/workflows/repoinfowf.cc new file mode 100644 index 0000000..cf739e9 --- /dev/null +++ b/zypp/ng/workflows/repoinfowf.cc @@ -0,0 +1,222 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include "repoinfowf.h" +#include "zypp/ng/reporthelper.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +namespace zyppng { + + namespace { + + using namespace zyppng::operators; + + template + struct RepoInfoProvideKeyLogic : public LogicBase { + + using ZyppContextRefType = MaybeAsyncContextRef; + using ZyppContextType = remove_smart_ptr_t; + using ProvideType = typename ZyppContextType::ProvideType; + using MediaHandle = typename ProvideType::MediaHandle; + using ProvideRes = typename ProvideType::Res; + + RepoInfoProvideKeyLogic( ZyppContextRefType &&zyppContext, zypp::RepoInfo &&info, std::string &&keyID_r, zypp::Pathname &&targetDirectory_r ) + : _reports( std::move(zyppContext )) + , _info( std::move(info) ) + , _keyID_r(std::move( keyID_r )) + , _targetDirectory_r(std::move( targetDirectory_r )) + , _keyIDStr( _keyID_r.size() > 8 ? _keyID_r.substr( _keyID_r.size()-8 ) : _keyID_r ) // print short ID in Jobreports + , _tempKeyRing( _tmpKeyRingDir ) + { } + + ZYPP_ENABLE_LOGIC_BASE( Executor, OpType ); + + MaybeAsyncRef execute () { + using namespace zyppng::operators; + using zyppng::operators::operator|; + using zyppng::expected; + + + if ( _keyID_r.empty() ) + return makeReadyResult(zypp::Pathname{}); + + importKeysInTargetDir(); + + if ( _tempKeyRing.isKeyTrusted( _keyID_r) ) { + return makeReadyResult(writeKeysToTargetDir()); + } + + if ( _info.gpgKeyUrlsEmpty() ) { + // translator: %1% is a repositories name + _reports.info( zypp::str::Format(_("Repository %1% does not define additional 'gpgkey=' URLs.") ) % _info.asUserString() ); + return makeReadyResult(writeKeysToTargetDir()); + } + + // no key in the cache is what we are looking for, lets download + // all keys specified in gpgkey= entries + + // translator: %1% is a gpg key ID like 3DBDC284 + // %2% is a repositories name + _reports.info( zypp::str::Format(_("Looking for gpg key ID %1% in repository %2%.") ) % _keyIDStr % _info.asUserString() ); + + return _info.gpgKeyUrls() + | transform( [this]( const zypp::Url &url ) { + + _reports.info( " gpgkey=" + url.asString() ); + return fetchKey( url ) + | and_then( [this, url]( zypp::ManagedFile f ) -> expected { + try { + if ( f->empty() ) + return expected::error(std::make_exception_ptr( zypp::Exception("Empty ManagedFile returned.") )); + + zypp::PublicKey key(f); + if ( !key.isValid() ) + return expected::error(std::make_exception_ptr( zypp::Exception("Invalid public key.") )); + + // import all keys into our temporary keyring + _tempKeyRing.multiKeyImport(f, true); + + } catch ( const std::exception & e ) { + //ignore and continue to next url + ZYPP_CAUGHT(e); + MIL << "Key import from url:'"<::error( ZYPP_FWD_CURRENT_EXCPT() ); + } + + return expected::success(); + }); + + }) + | [this]( std::list> && ) ->zypp::Pathname { + return writeKeysToTargetDir(); + }; + } + + protected: + + MaybeAsyncRef> fetchKey ( const zypp::Url &url ) { + return _reports.zyppContext()->provider ()->provide( url, zyppng::ProvideFileSpec() ) + | and_then( ProvideType::copyResultToDest( _reports.zyppContext()->provider(), _targetDirectory_r / zypp::Pathname( url.getPathName() ).basename() ) ); + } + + void importKeysInTargetDir () { + MIL << "Check for " << _keyID_r << " at " << _targetDirectory_r << std::endl; + + // translator: %1% is a gpg key ID like 3DBDC284 + // %2% is a cache directories path + _reports.info( zypp::str::Format(_("Looking for gpg key ID %1% in cache %2%.") ) % _keyIDStr % _targetDirectory_r ); + zypp::filesystem::dirForEach( _targetDirectory_r, + zypp::StrMatcher(".key", zypp::Match::STRINGEND), + [this]( const zypp::Pathname & dir_r, const std::string & str_r ){ + try { + + // deprecate a month old keys + zypp::PathInfo fileInfo ( dir_r/str_r ); + if ( zypp::Date::now() - fileInfo.mtime() > zypp::Date::month ) { + //if unlink fails, the file will be overriden in the next step, no need + //to show a error + zypp::filesystem::unlink( dir_r/str_r ); + } else { + _tempKeyRing.multiKeyImport(dir_r/str_r, true); + } + } catch (const zypp::KeyRingException& e) { + ZYPP_CAUGHT(e); + ERR << "Error importing cached key from file '"< _reports; + const zypp::RepoInfo _info; + const std::string _keyID_r; + const zypp::Pathname _targetDirectory_r; + const std::string _keyIDStr; + + zypp::filesystem::TmpDir _tmpKeyRingDir; + zypp::KeyRing _tempKeyRing; + }; + + + struct AsyncRepoInfoProvideKey : public RepoInfoProvideKeyLogic> + { + using RepoInfoProvideKeyLogic::RepoInfoProvideKeyLogic; + }; + + struct SyncRepoInfoProvideKey : public RepoInfoProvideKeyLogic> + { + using RepoInfoProvideKeyLogic::RepoInfoProvideKeyLogic; + }; + } + + zypp::filesystem::Pathname RepoInfoWorkflow::provideKey( SyncContextRef ctx, zypp::RepoInfo info, std::string keyID_r, zypp::filesystem::Pathname targetDirectory_r ) + { + return SimpleExecutor>::run( std::move(ctx), std::move(info), std::move(keyID_r), std::move(targetDirectory_r) ); + } + + AsyncOpRef RepoInfoWorkflow::provideKey(ContextRef ctx, zypp::RepoInfo info, std::string keyID_r, zypp::filesystem::Pathname targetDirectory_r ) + { + return SimpleExecutor>::run( std::move(ctx), std::move(info), std::move(keyID_r), std::move(targetDirectory_r) ); + } + +} diff --git a/zypp/ng/workflows/repoinfowf.h b/zypp/ng/workflows/repoinfowf.h new file mode 100644 index 0000000..ff28c60 --- /dev/null +++ b/zypp/ng/workflows/repoinfowf.h @@ -0,0 +1,28 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_REPOINFOWORKFLOW_INCLUDED +#define ZYPP_NG_REPOINFOWORKFLOW_INCLUDED + +#include +#include +#include + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (Context); + ZYPP_FWD_DECL_TYPE_WITH_REFS (SyncContext); + + namespace RepoInfoWorkflow { + zypp::Pathname provideKey ( SyncContextRef ctx, zypp::RepoInfo info, std::string keyID_r, zypp::Pathname targetDirectory_r ); + AsyncOpRef provideKey ( ContextRef ctx, zypp::RepoInfo info, std::string keyID_r, zypp::Pathname targetDirectory_r ); + } +} + + +#endif diff --git a/zypp/ng/workflows/signaturecheckwf.cc b/zypp/ng/workflows/signaturecheckwf.cc new file mode 100644 index 0000000..57d9fc0 --- /dev/null +++ b/zypp/ng/workflows/signaturecheckwf.cc @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "signaturecheckwf.h" +#include "keyringwf.h" +#include "logichelpers.h" + +#include +#include +#include + +namespace zyppng { + + namespace { + + using namespace zyppng::operators; + + template + struct VerifySignatureLogic : public LogicBase { + + ZYPP_ENABLE_LOGIC_BASE(Executor,OpType); + using ZyppContextRefType = MaybeAsyncContextRef; + + VerifySignatureLogic( ZyppContextRefType &&zyppCtx, zypp::keyring::VerifyFileContext &&ctx ) + : _zyppCtx( std::move(zyppCtx) ) + , _verifyCtx( std::move(ctx) ) { } + + MaybeAsyncRef> execute () { + + const zypp::Pathname & sig { _verifyCtx.signature() }; + if ( not ( sig.empty() || zypp::PathInfo(sig).isExist() ) ) { + return makeReadyResult( expected::error(ZYPP_EXCPT_PTR( zypp::SignatureCheckException("Signature " + sig.asString() + " not found.") ))); + } + + MIL << "Checking " << _verifyCtx.file ()<< " file validity using digital signature.." << std::endl; + + return KeyRingWorkflow::verifyFileSignature( _zyppCtx, zypp::keyring::VerifyFileContext( _verifyCtx ) ) + | []( auto &&res ) { + if ( not res.first ) + return expected::error( ZYPP_EXCPT_PTR( zypp::SignatureCheckException( "Signature verification failed for " + res.second.file().basename() ) ) ); + return expected::success ( std::move( res.second ) ); + }; + } + + protected: + ZyppContextRefType _zyppCtx; + zypp::keyring::VerifyFileContext _verifyCtx; + }; + } + + namespace SignatureFileCheckWorkflow { + expected verifySignature(SyncContextRef ctx, zypp::keyring::VerifyFileContext context ) + { + return SimpleExecutor>>::run( std::move(ctx), std::move(context) ); + } + + AsyncOpRef > verifySignature(ContextRef ctx, zypp::keyring::VerifyFileContext context ) + { + return SimpleExecutor>>::run( std::move(ctx), std::move(context) ); + } + } +} diff --git a/zypp/ng/workflows/signaturecheckwf.h b/zypp/ng/workflows/signaturecheckwf.h new file mode 100644 index 0000000..9a24146 --- /dev/null +++ b/zypp/ng/workflows/signaturecheckwf.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#ifndef ZYPP_NG_SIGNATURECHECK_WORKFLOW_INCLUDED +#define ZYPP_NG_SIGNATURECHECK_WORKFLOW_INCLUDED + +#include +#include + +#include +#include +#include + +// async helper +#include + +namespace zyppng { + + ZYPP_FWD_DECL_TYPE_WITH_REFS (Context); + + namespace SignatureFileCheckWorkflow { + expected verifySignature( SyncContextRef ctx, zypp::keyring::VerifyFileContext context ); + AsyncOpRef> verifySignature( ContextRef ctx, zypp::keyring::VerifyFileContext context ); + } + +} + + + +#endif diff --git a/zypp/parser/HistoryLogReader.cc b/zypp/parser/HistoryLogReader.cc new file mode 100644 index 0000000..83b08f3 --- /dev/null +++ b/zypp/parser/HistoryLogReader.cc @@ -0,0 +1,244 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +/** \file HistoryLogReader.cc + * + */ +#include + +#include +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace parser + { + + ///////////////////////////////////////////////////////////////////// + // + // class HistoryLogReader::Impl + // + ///////////////////////////////////////////////////////////////////// + struct HistoryLogReader::Impl + { + Impl( Pathname &&historyFile_r, Options &&options_r, ProcessData &&callback_r ) + : _filename( std::move(historyFile_r) ) + , _options( std::move(options_r) ) + , _callback( std::move(callback_r) ) + {} + + bool parseLine( const std::string & line_r, unsigned int lineNr_r ); + + void readAll( const ProgressData::ReceiverFnc & progress_r ); + void readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r ); + void readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r ); + + void addActionFilter( const HistoryActionID & action_r ) + { + if ( action_r == HistoryActionID::NONE ) + _actionfilter.clear(); + else + _actionfilter.insert( action_r.asString() ); + } + + Pathname _filename; + Options _options; + ProcessData _callback; + std::set _actionfilter; + }; + + bool HistoryLogReader::Impl::parseLine( const std::string & line_r, unsigned lineNr_r ) + { + // parse into fields + HistoryLogData::FieldVector fields; + str::splitEscaped( line_r, std::back_inserter(fields), "|", true ); + + if ( fields.size() < 2 ) { + WAR << "Ignore invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl; + return true; // At least an action field[1] is needed! + } + fields[1] = str::trim( std::move(fields[1]) ); // for whatever reason writer is padding the action field + + if ( !_actionfilter.empty() && !_actionfilter.count( fields[1] ) ) + return true; + + // move into data class + HistoryLogData::Ptr data; + try + { + data = HistoryLogData::create( fields ); + } + catch ( const Exception & excpt ) + { + ZYPP_CAUGHT( excpt ); + if ( _options.testFlag( IGNORE_INVALID_ITEMS ) ) + { + WAR << "Ignore invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl; + return true; + } + else + { + ERR << "Invalid history log entry on line #" << lineNr_r << " '"<< line_r << "'" << endl; + ParseException newexcpt( str::Str() << "Error in history log on line #" << lineNr_r ); + newexcpt.remember( excpt ); + ZYPP_THROW( newexcpt ); + } + } + + // consume data + if ( _callback && !_callback( data ) ) + { + WAR << "Stop parsing requested by consumer callback on line #" << lineNr_r << endl; + return false; + } + return true; + } + + void HistoryLogReader::Impl::readAll( const ProgressData::ReceiverFnc & progress_r ) + { + InputStream is( _filename ); + iostr::EachLine line( is ); + + ProgressData pd; + pd.sendTo( progress_r ); + pd.toMin(); + + for ( ; line; line.next(), pd.tick() ) + { + // ignore comments + if ( (*line)[0] == '#' ) + continue; + + if ( ! parseLine( *line, line.lineNo() ) ) + break; // requested by consumer callback + } + + pd.toMax(); + } + + void HistoryLogReader::Impl::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r ) + { + InputStream is( _filename ); + iostr::EachLine line( is ); + + ProgressData pd; + pd.sendTo( progress_r ); + pd.toMin(); + + bool pastDate = false; + for ( ; line; line.next(), pd.tick() ) + { + const std::string & s = *line; + + // ignore comments + if ( s[0] == '#' ) + continue; + + if ( pastDate ) + { + if ( ! parseLine( s, line.lineNo() ) ) + break; // requested by consumer callback + } + else + { + Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT ); + if ( logDate > date_r ) + { + pastDate = true; + if ( ! parseLine( s, line.lineNo() ) ) + break; // requested by consumer callback + } + } + } + + pd.toMax(); + } + + void HistoryLogReader::Impl::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r ) + { + InputStream is( _filename ); + iostr::EachLine line( is ); + + ProgressData pd; + pd.sendTo( progress_r ); + pd.toMin(); + + bool pastFromDate = false; + for ( ; line; line.next(), pd.tick() ) + { + const std::string & s = *line; + + // ignore comments + if ( s[0] == '#' ) + continue; + + Date logDate( s.substr( 0, s.find('|') ), HISTORY_LOG_DATE_FORMAT ); + + // past toDate - stop reading + if ( logDate >= toDate_r ) + break; + + // past fromDate - start reading + if ( !pastFromDate && logDate > fromDate_r ) + pastFromDate = true; + + if ( pastFromDate ) + { + if ( ! parseLine( s, line.lineNo() ) ) + break; // requested by consumer callback + } + } + + pd.toMax(); + } + + ///////////////////////////////////////////////////////////////////// + // + // class HistoryLogReader + // + ///////////////////////////////////////////////////////////////////// + + HistoryLogReader::HistoryLogReader( Pathname historyFile_r, Options options_r, ProcessData callback_r ) + : _pimpl( new HistoryLogReader::Impl( std::move(historyFile_r), std::move(options_r), std::move(callback_r) ) ) + {} + + HistoryLogReader::~HistoryLogReader() + {} + + void HistoryLogReader::setIgnoreInvalidItems( bool ignoreInvalid_r ) + { _pimpl->_options.setFlag( IGNORE_INVALID_ITEMS, ignoreInvalid_r ); } + + bool HistoryLogReader::ignoreInvalidItems() const + { return _pimpl->_options.testFlag( IGNORE_INVALID_ITEMS ); } + + void HistoryLogReader::readAll( const ProgressData::ReceiverFnc & progress_r ) + { _pimpl->readAll( progress_r ); } + + void HistoryLogReader::readFrom( const Date & date_r, const ProgressData::ReceiverFnc & progress_r ) + { _pimpl->readFrom( date_r, progress_r ); } + + void HistoryLogReader::readFromTo( const Date & fromDate_r, const Date & toDate_r, const ProgressData::ReceiverFnc & progress_r ) + { _pimpl->readFromTo( fromDate_r, toDate_r, progress_r ); } + + void HistoryLogReader::addActionFilter( const HistoryActionID & action_r ) + { _pimpl->addActionFilter( action_r ); } + + } // namespace parser + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/HistoryLogReader.h b/zypp/parser/HistoryLogReader.h new file mode 100644 index 0000000..288e85b --- /dev/null +++ b/zypp/parser/HistoryLogReader.h @@ -0,0 +1,170 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +/** \file zypp/parser/HistoryLogReader.h + * + */ +#ifndef ZYPP_PARSER_HISTORYLOGREADER_H_ +#define ZYPP_PARSER_HISTORYLOGREADER_H_ + +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + + class Date; + + /////////////////////////////////////////////////////////////////// + namespace parser + { + + /////////////////////////////////////////////////////////////////// + /// \class HistoryLogReader + /// \brief Zypp history file parser + /// \ingroup g_ZyppHistory + /// \ingroup g_ZyppParser + /// + /// Reads a zypp history log file and calls the \ref ProcessData callback + /// passed in the constructor for each valid history line read. The callbacks + /// return value indicates whether to continue parsing. + /// + /// \code + /// std::vector history; + /// parser::HistoryLogReader parser( ZConfig::instance().historyLogFile(), + /// HistoryLogReader::Options(), + /// [&history]( HistoryLogData::Ptr ptr )->bool { + /// history.push_back( ptr ); + /// return true; + /// } ); + /// parser.readAll(); + /// ... + /// if ( history[0]->action() == HistoryActionID::INSTALL ) + /// { + /// // generic access to data fields plain string values: + /// MIL << (*p)[HistoryLogDataInstall::USERDATA_INDEX] << endl; + /// + /// // The same maybe more convenient though derived classes: + /// HistoryLogDataInstall::Ptr ip( dynamic_pointer_cast( p ) ); + /// MIL << ip->userdata() << endl; + /// } + /// \endcode + /// \see \ref HistoryLogData for how to access the individual data fields. + /// + /////////////////////////////////////////////////////////////////// + class ZYPP_API HistoryLogReader + { + public: + + enum OptionBits ///< Parser option flags + { + IGNORE_INVALID_ITEMS = (1 << 0) ///< ignore invalid items and continue parsing + }; + ZYPP_DECLARE_FLAGS( Options, OptionBits ); + + public: + /** Callback type to consume a single history line split into fields. + * The return value indicates whether to continue parsing. + */ + using ProcessData = function; + + /** Ctor taking file to parse and data consumer callback. + * As \a options_r argument pass \c HistoryLogReader::Options() to + * use the default stettings, or an OR'ed combination of \ref OptionBits. + */ + HistoryLogReader(Pathname historyFile_r, zypp::parser::HistoryLogReader::Options options_r, ProcessData callback_r ); + + ~HistoryLogReader(); + + /** + * Read the whole log file. + * + * \param progress An optional progress data receiver function. + */ + void readAll( const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() ); + + /** + * Read log from specified \a date. + * + * \param date Date from which to read. + * \param progress An optional progress data receiver function. + * + * \see readFromTo() + */ + void readFrom( const Date & date, const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() ); + + /** + * Read log between \a fromDate and \a toDate. + * + * The date comparison's precision goes to seconds. Omitted time parts + * get replaced by zeroes, so if e.g. the time is not specified at all, the + * date means midnight of the specified date. So + * + * + * fromDate = Date("2009-01-01", "%Y-%m-%d"); + * toDate = Date("2009-01-02", "%Y-%m-%d"); + * + * + * will yield log entries from midnight of January, 1st untill + * one second before midnight of January, 2nd. + * + * \param fromDate Date from which to read. + * \param toDate Date on which to stop reading. + * \param progress An optional progress data receiver function. + */ + void readFromTo( const Date & fromDate, const Date & toDate, const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() ); + + /** + * Set the reader to ignore invalid log entries and continue with the rest. + * + * \param ignoreInvalid true will cause the reader to ignore invalid entries + */ + void setIgnoreInvalidItems( bool ignoreInvalid = false ); + + /** + * Whether the reader is set to ignore invalid log entries. + * + * \see setIngoreInvalidItems() + */ + bool ignoreInvalidItems() const; + + + /** Process only specific HistoryActionIDs. + * Call repeatedly to add multiple HistoryActionIDs to process. + * Passing an empty HistoryActionID (HistoryActionID::NONE) clears + * the filter. + */ + void addActionFilter( const HistoryActionID & action_r ); + + /** Clear any HistoryActionIDs. */ + void clearActionFilter() + { addActionFilter( HistoryActionID::NONE ); } + + private: + /** Implementation */ + struct Impl; + RW_pointer > _pimpl; + }; + + /** \relates HistoryLogReader::Options */ + ZYPP_DECLARE_OPERATORS_FOR_FLAGS( HistoryLogReader::Options ); + + /////////////////////////////////////////////////////////////////// + + } // namespace parser + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif /* ZYPP_PARSER_HISTORYLOGREADER_H_ */ diff --git a/zypp/parser/IniDict.h b/zypp/parser/IniDict.h new file mode 100644 index 0000000..036452f --- /dev/null +++ b/zypp/parser/IniDict.h @@ -0,0 +1 @@ +#include diff --git a/zypp/parser/IniParser.h b/zypp/parser/IniParser.h new file mode 100644 index 0000000..a8459c9 --- /dev/null +++ b/zypp/parser/IniParser.h @@ -0,0 +1 @@ +#include diff --git a/zypp/parser/ParseException.h b/zypp/parser/ParseException.h new file mode 100644 index 0000000..1f22651 --- /dev/null +++ b/zypp/parser/ParseException.h @@ -0,0 +1 @@ +#include diff --git a/zypp/parser/ParserProgress.h b/zypp/parser/ParserProgress.h new file mode 100644 index 0000000..a222147 --- /dev/null +++ b/zypp/parser/ParserProgress.h @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_ParserProgress_H +#define ZYPP_ParserProgress_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +namespace parser +{ ///////////////////////////////////////////////////////////////// + + class ParserProgress + { + public: + using Ptr = boost::shared_ptr; + + /** + * initializes a progress objetc, with a callback functor + * if you are not reporting percentage, then set + * the total_steps to the goal, and report using the same + * unit, then + */ + ParserProgress( boost::function fnc, long int total_steps = 100 ) + : _fnc(std::move(fnc)), _previous_progress(0), _total_steps(total_steps) + { + + }; + + ~ParserProgress() + {}; + + /** + * report progress, which in most cases + * executes the functor associated with + * this progress object to update progress + * information + */ + void progress(long int p) + { + //std::cout << "real " << p << std::endl; + if ( _total_steps != 100 ) + { + long int current_done = p; + p = (long int)(((double) current_done/(double) _total_steps)*100); + } + + if (_fnc && ( p != _previous_progress )) + { + _previous_progress = p; + _fnc(p); + } + } + + void setTotalSteps( long int total_steps ) + { + _total_steps = total_steps; + } + + /** + * report progress finished + */ + void finish() + { + int p = 100; + if (_fnc && ( p != _previous_progress )) + { + _previous_progress = p; + _fnc(p); + } + } + + /** + * report progress started + */ + void start() + { + int p = 0; + if (_fnc && ( p != _previous_progress )) + { + _previous_progress = p; + _fnc(p); + } + } + + private: + boost::function _fnc; + long int _previous_progress; + long int _total_steps; + }; + +} // namespace parser +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ParserProgress_H diff --git a/zypp/parser/ProductFileReader.cc b/zypp/parser/ProductFileReader.cc new file mode 100644 index 0000000..391a271 --- /dev/null +++ b/zypp/parser/ProductFileReader.cc @@ -0,0 +1,290 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/ProductFileReader.cc + * +*/ +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + // + // class ProductFileData::Upgrade + // + ///////////////////////////////////////////////////////////////// + + struct ProductFileData::Upgrade::Impl + { + std::string _name; + std::string _summary; + std::string _repository; + std::string _product; + DefaultIntegral _notify; + std::string _status; + }; + + ProductFileData::Upgrade::Upgrade( Impl * allocated_r ) + : _pimpl( allocated_r ? allocated_r : new Impl ) + {} + + std::string ProductFileData::Upgrade::name() const { return _pimpl->_name; } + std::string ProductFileData::Upgrade::summary() const { return _pimpl->_summary; } + std::string ProductFileData::Upgrade::repository() const { return _pimpl->_repository; } + std::string ProductFileData::Upgrade::product() const { return _pimpl->_product; } + bool ProductFileData::Upgrade::notify() const { return _pimpl->_notify; } + std::string ProductFileData::Upgrade::status() const { return _pimpl->_status; } + + ///////////////////////////////////////////////////////////////// + // + // class ProductFileData + // + ///////////////////////////////////////////////////////////////// + + struct ProductFileData::Impl + { + IdString _vendor; + IdString _name; + Edition _edition; + Arch _arch; + + std::string _shortName; + std::string _summary; + + std::string _productline; + std::string _registerTarget; + std::string _registerRelease; + std::string _registerFlavor; + + std::string _updaterepokey; + + Upgrades _upgrades; + }; + + ProductFileData::ProductFileData( Impl * allocated_r ) + : _pimpl( allocated_r ? allocated_r : new Impl ) + {} + + IdString ProductFileData::vendor() const { return _pimpl->_vendor; } + IdString ProductFileData::name() const { return _pimpl->_name; } + Edition ProductFileData::edition() const { return _pimpl->_edition; } + Arch ProductFileData::arch() const { return _pimpl->_arch; } + + std::string ProductFileData::shortName() const { return _pimpl->_shortName; } + std::string ProductFileData::summary() const { return _pimpl->_summary; } + + std::string ProductFileData::productline() const { return _pimpl->_productline; } + std::string ProductFileData::registerTarget() const { return _pimpl->_registerTarget; } + std::string ProductFileData::registerRelease() const { return _pimpl->_registerRelease; } + std::string ProductFileData::registerFlavor() const { return _pimpl->_registerFlavor; } + + std::string ProductFileData::updaterepokey() const { return _pimpl->_updaterepokey; } + + const ProductFileData::Upgrades & ProductFileData::upgrades() const { return _pimpl->_upgrades; } + + std::ostream & operator<<( std::ostream & str, const ProductFileData & obj ) + { + str << str::form( "|product|%s|%s|%s|%s|", + obj.name().c_str(), + obj.edition().c_str(), + obj.arch().c_str(), + obj.vendor().c_str() ); + if ( ! obj.upgrades().empty() ) + { + for_( it, obj.upgrades().begin(), obj.upgrades().end() ) + str << endl << " " << *it; + } + return str; + } + + std::ostream & operator<<( std::ostream & str, const ProductFileData::Upgrade & obj ) + { + str << str::form( "|upgrade|%s|%s|%s|%s|%s|", + obj.name().c_str(), + obj.repository().c_str(), + obj.product().c_str(), + obj.status().c_str(), + (obj.notify() ? "notify" : "noNotify") ); + return str; + } + ///////////////////////////////////////////////////////////////// + // + // class ProductFileReader + // + ///////////////////////////////////////////////////////////////// + + struct ProductNode : public xml::ParseDef + { + ProductNode( ProductFileData::Impl & pdata_r ) + : ParseDef( "product", MANDTAORY ) + , _pdata( pdata_r ) + { + (*this) + ("vendor", OPTIONAL, xml::parseDefAssign( _pdata._vendor ) ) + ("name", MANDTAORY, xml::parseDefAssign( _pdata._name ) ) + ("version", MANDTAORY, xml::parseDefAssign( _version ) ) + ("release", MANDTAORY, xml::parseDefAssign( _release ) ) + ("arch", MANDTAORY, xml::parseDefAssign( _pdata._arch ) ) + ("shortsummary", OPTIONAL, xml::parseDefAssign( _pdata._shortName ) ) + ("summary", MULTIPLE_OPTIONAL, xml::parseDefAssign( _ttext )( "lang", _tlocale ) + >>std::bind( std::mem_fn(&ProductNode::doneLocalizedDefault), this, _1, std::ref(_pdata._summary) )) + ("productline", OPTIONAL, xml::parseDefAssign( _pdata._productline ) ) + ("register", OPTIONAL) + ("updaterepokey", OPTIONAL, xml::parseDefAssign( _pdata._updaterepokey ) ) + ("upgrades", OPTIONAL) + ; + + (*this)["register"] + ("target", OPTIONAL, xml::parseDefAssign( _pdata._registerTarget ) ) + ("release", OPTIONAL, xml::parseDefAssign( _pdata._registerRelease ) ) + ("flavor", OPTIONAL, xml::parseDefAssign( _pdata._registerFlavor ) ) + ; + + (*this)["upgrades"] + ("upgrade", MULTIPLE_OPTIONAL, xml::parseDefAssign() + >> bind( &ProductNode::doneUpgrade, this, _1 )) + ; + + (*this)["upgrades"]["upgrade"] + ("name", OPTIONAL, xml::parseDefAssign( _upgrade._name ) ) + ("summary", OPTIONAL, xml::parseDefAssign( _upgrade._summary ) ) + ("repository", OPTIONAL, xml::parseDefAssign( _upgrade._repository ) ) + ("product", OPTIONAL, xml::parseDefAssign( _upgrade._product ) ) + ("notify", OPTIONAL, xml::parseDefAssign( _upgrade._notify ) ) + ("status", OPTIONAL, xml::parseDefAssign( _upgrade._status ) ) + ; + + // callback to build edition. + setConsumer( xml::parseDefAssign() >> bind( &ProductNode::done, this, _1 ) ); + // xml::ParseDef::_debug = true; + } + + /** collect _upgrade */ + void doneUpgrade( const xml::Node & _node ) + { + ProductFileData::Upgrade cdata( new ProductFileData::Upgrade::Impl( _upgrade ) ); + _pdata._upgrades.push_back( cdata ); + _upgrade = ProductFileData::Upgrade::Impl(); + } + /** collect localized data */ + void doneLocalizedDefault( const xml::Node & _node, std::string & store_r ) + { + // take 1st or default + if ( store_r.empty() || _tlocale.empty() ) + store_r = _ttext; + } + + /** finally */ + void done( const xml::Node & _node ) + { + _pdata._edition = Edition( _version, _release ); + } + + private: + ProductFileData::Impl & _pdata; + + std::string _version; + std::string _release; + + std::string _ttext; + std::string _tlocale; + + ProductFileData::Upgrade::Impl _upgrade; + }; + + bool ProductFileReader::parse( const InputStream & input_r ) const + { + MIL << "+++" << input_r << endl; + bool ret = true; + + ProductFileData::Impl * pdataImpl = 0; + ProductFileData pdata( (pdataImpl = new ProductFileData::Impl) ); + + try + { + xml::Reader reader( input_r ); + ProductNode rootNode( *pdataImpl ); + rootNode.take( reader ); + + } + catch ( const Exception & err ) + { + // parse error + ERR << err << endl; + ERR << "---" << ret << " - " << input_r << endl; + return ret; + } + + if ( _consumer ) + { + ret = _consumer( pdata ); + } + + MIL << "---" << ret << " - " << input_r << endl; + return ret; + } + + ///////////////////////////////////////////////////////////////// + + bool ProductFileReader::scanDir( const Consumer & consumer_r, const Pathname & dir_r ) + { + std::list retlist; + int res = filesystem::readdir( retlist, dir_r, /*dots*/false ); + if ( res != 0 ) + { + WAR << "scanDir " << dir_r << " failed (" << res << ")" << endl; + return true; + } + + ProductFileReader reader( consumer_r ); + for_( it, retlist.begin(), retlist.end() ) + { + if ( PathInfo( *it, PathInfo::LSTAT ).isFile() && ! reader.parse( *it ) ) + { + return false; // consumer_r request to stop parsing. + } + } + return true; + } + + ProductFileData ProductFileReader::scanFile( const Pathname & file_r ) + { + if ( ! PathInfo( file_r ).isFile() ) + { + WAR << "scanFile " << PathInfo( file_r ) << " is not a file." << endl; + return ProductFileData(); + } + + ProductFileData ret; + ProductFileReader reader( functor::getFirst( ret ), file_r ); + return ret; + } + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/ProductFileReader.h b/zypp/parser/ProductFileReader.h new file mode 100644 index 0000000..b569e26 --- /dev/null +++ b/zypp/parser/ProductFileReader.h @@ -0,0 +1,179 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/ProductFileReader.h + * +*/ +#ifndef ZYPP_PARSER_PRODUCTSDREADER_H +#define ZYPP_PARSER_PRODUCTSDREADER_H + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ProductFileData + // + /** Data returned by \ref ProductFileReader + * \see \ref ProductFileReader + */ + class ZYPP_API ProductFileData + { + public: + struct Impl; + /** Ctor takes ownership of \c allocated_r. */ + ProductFileData( Impl * allocated_r = 0 ); + + /** Whether this is an empty object without valid data. */ + bool empty() const + { return name().empty(); } + + public: + IdString vendor() const; + IdString name() const; + Edition edition() const; + Arch arch() const; + + std::string shortName() const; + std::string summary() const; + + public: + std::string productline() const; + std::string registerTarget() const; + std::string registerRelease() const; + std::string registerFlavor() const; + + public: + std::string updaterepokey() const; + + public: + /////////////////////////////////////////////////////////////////// + /** \see http://en.opensuse.org/Product_Management/Code11/Upgrade */ + struct Upgrade + { + public: + struct Impl; + /** Ctor takes ownership of \c allocated_r. */ + Upgrade( Impl * allocated_r = 0 ); + + public: + std::string name() const; + std::string summary() const; + std::string repository() const; + std::string product() const; + bool notify() const; + std::string status() const; + + private: + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + using Upgrades = std::vector; + const Upgrades & upgrades() const; + + private: + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ProductFileData Stream output */ + std::ostream & operator<<( std::ostream & str, const ProductFileData & obj ) ZYPP_API; + + /** \relates ProductFileData::Upgrade Stream output */ + std::ostream & operator<<( std::ostream & str, const ProductFileData::Upgrade & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ProductFileReader + // + /** Parser for /etc/products.d enries (just relevant entires). + * + * \code + * #include "zypp/base/Functional.h" // functor::getAll + * + * std::vector result; + * ProductFileReader::scanDir( functor::getAll( std::back_inserter( result ) ), + * "/etc/products.d" ); + * \endcode + */ + class ZYPP_API ProductFileReader + { + public: + /** Callback being invoked for each \ref ProductFileData parsed. + * Return \c false to stop parsing. + */ + using Consumer = function; + + public: + ProductFileReader() + {} + + ProductFileReader( Consumer consumer_r ) + : _consumer(std::move( consumer_r )) + {} + + ProductFileReader( Consumer consumer_r, const InputStream & input_r ) + : _consumer(std::move( consumer_r )) + { parse( input_r ); } + + public: + const Consumer & consumer() const + { return _consumer; } + + void setConsumer( const Consumer & consumer_r ) + { _consumer = consumer_r; } + + public: + /** Parse the input stream and call \c _consumer for each + * parsed section. + * + * Returns \c false if the \c _consumer requested to stop parsing. + */ + bool parse( const InputStream & input_r = InputStream() ) const; + + public: + /** Parse all files (no symlinks) in \c dir_r and call \c consumer_r + * for each \ref ProductFileData parsed. + * + * Returns \c false if the \c _consumer requested to stop parsing. + */ + static bool scanDir( const Consumer & consumer_r, const Pathname & dir_r ); + + /** Parse one file (or symlink) and return the \ref ProductFileData parsed. + */ + static ProductFileData scanFile( const Pathname & file_r ); + + private: + Consumer _consumer; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_PRODUCTSDREADER_H diff --git a/zypp/parser/RepoFileReader.cc b/zypp/parser/RepoFileReader.cc new file mode 100644 index 0000000..e3d9090 --- /dev/null +++ b/zypp/parser/RepoFileReader.cc @@ -0,0 +1,264 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoFileReader.cc + * +*/ +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace parser + { + /////////////////////////////////////////////////////////////////// + namespace { + + /////////////////////////////////////////////////////////////////// + /// \class RepoFileParser + /// \brief Modified \ref IniDict to allow parsing multiple 'baseurl=' entries + /////////////////////////////////////////////////////////////////// + class RepoFileParser : public IniDict + { + public: + RepoFileParser( const InputStream & is_r ) + { read( is_r ); } + + using IniDict::consume; // don't hide overloads we don't redefine here + + void consume( const std::string & section_r, const std::string & key_r, const std::string & value_r ) override + { + if ( key_r == "baseurl" ) + { + _inMultiline = MultiLine::baseurl; + storeUrl( _baseurls[section_r], value_r ); + } + else if ( key_r == "gpgkey" ) + { + _inMultiline = MultiLine::gpgkey; + storeUrl( _gpgkeys[section_r], value_r ); + } + else if ( key_r == "mirrorlist" ) + { + _inMultiline = MultiLine::mirrorlist; + storeUrl( _mirrorlist[section_r], value_r ); + } + else if ( key_r == "metalink" ) + { + _inMultiline = MultiLine::metalink; + storeUrl( _metalink[section_r], value_r ); + } + else + { + _inMultiline = MultiLine::none; + IniDict::consume( section_r, key_r, value_r ); + } + } + + void garbageLine( const std::string & section_r, const std::string & line_r ) override + { + switch ( _inMultiline ) + { + case MultiLine::baseurl: + storeUrl( _baseurls[section_r], line_r ); + break; + + case MultiLine::gpgkey: + storeUrl( _gpgkeys[section_r], line_r ); + break; + + case MultiLine::mirrorlist: + storeUrl( _mirrorlist[section_r], line_r ); + break; + + case MultiLine::metalink: + storeUrl( _metalink[section_r], line_r ); + break; + + case MultiLine::none: + IniDict::garbageLine( section_r, line_r ); // throw + break; + } + } + + std::list & baseurls( const std::string & section_r ) + { return _baseurls[section_r]; } + + std::list & gpgkeys( const std::string & section_r ) + { return _gpgkeys[section_r]; } + + std::list & mirrorlist( const std::string & section_r ) + { return _mirrorlist[section_r]; } + + std::list & metalink( const std::string & section_r ) + { return _metalink[section_r]; } + + private: + void storeUrl( std::list & store_r, const std::string & line_r ) + { + // #285: Fedora/dnf allows WS separated urls (and an optional comma) + strv::splitRx( line_r, "[,[:blank:]]*[[:blank:]][,[:blank:]]*", [&store_r]( std::string_view w ) { + if ( ! w.empty() ) + store_r.push_back( Url(std::string(w)) ); + }); + } + + enum class MultiLine { none, baseurl, gpgkey, mirrorlist, metalink }; + MultiLine _inMultiline = MultiLine::none; + + std::map> _baseurls; + std::map> _gpgkeys; + std::map> _mirrorlist; + std::map> _metalink; + }; + + } //namespace + /////////////////////////////////////////////////////////////////// + + /** + * \short List of RepoInfo's from a file. + * \param file pathname of the file to read. + */ + static void repositories_in_stream( const InputStream &is, + const RepoFileReader::ProcessRepo &callback, + const ProgressData::ReceiverFnc &progress ) + try { + RepoFileParser dict(is); + for_( its, dict.sectionsBegin(), dict.sectionsEnd() ) + { + RepoInfo info; + info.setAlias(*its); + std::string proxy; + std::string proxyport; + + for_( it, dict.entriesBegin(*its), dict.entriesEnd(*its) ) + { + //MIL << (*it).first << endl; + if (it->first == "name" ) + info.setName(it-> second); + else if ( it->first == "enabled" ) + info.setEnabled( str::strToTrue( it->second ) ); + else if ( it->first == "priority" ) + info.setPriority( str::strtonum( it->second ) ); + else if ( it->first == "path" ) + info.setPath( Pathname(it->second) ); + else if ( it->first == "type" ) + ; // bsc#1177427 et.al.: type in a .repo file is legacy - ignore it and let RepoManager probe + else if ( it->first == "autorefresh" ) + info.setAutorefresh( str::strToTrue( it->second ) ); + else if ( it->first == "gpgcheck" ) + info.setGpgCheck( str::strToTriBool( it->second ) ); + else if ( it->first == "repo_gpgcheck" ) + info.setRepoGpgCheck( str::strToTrue( it->second ) ); + else if ( it->first == "pkg_gpgcheck" ) + info.setPkgGpgCheck( str::strToTrue( it->second ) ); + else if ( it->first == "keeppackages" ) + info.setKeepPackages( str::strToTrue( it->second ) ); + else if ( it->first == "service" ) + info.setService( it->second ); + else if ( it->first == "proxy" ) + { + // Translate it into baseurl queryparams + // NOTE: The hack here does not add proxy to mirrorlist urls but the + // original code worked without complains, so keep it for now. + static const str::regex ex( ":[0-9]+$" ); // portspec + str::smatch what; + if ( str::regex_match( it->second, what, ex ) ) + { + proxy = it->second.substr( 0, it->second.size() - what[0].size() ); + proxyport = what[0].substr( 1 ); + } + else + { + proxy = it->second; + } + } + else + ERR << "Unknown attribute in [" << *its << "]: " << it->first << "=" << it->second << " ignored" << endl; + } + + for ( auto & url : dict.baseurls( *its ) ) + { + if ( ! proxy.empty() && url.getQueryParam( "proxy" ).empty() ) + { + url.setQueryParam( "proxy", proxy ); + url.setQueryParam( "proxyport", proxyport ); + } + info.addBaseUrl( url ); + } + + if ( ! dict.gpgkeys( *its ).empty() ) + info.setGpgKeyUrls( std::move(dict.gpgkeys( *its )) ); + + if ( ! dict.mirrorlist( *its ).empty() ) + info.setMirrorListUrls( std::move(dict.mirrorlist( *its )) ); + + if ( ! dict.metalink( *its ).empty() ) + info.setMetalinkUrls( std::move(dict.metalink( *its )) ); + + + info.setFilepath(is.path()); + MIL << info << endl; + // add it to the list. + callback(info); + //if (!progress.tick()) + // ZYPP_THROW(AbortRequestException()); + } + } + catch ( Exception & ex ) { + ex.addHistory( "Parsing .repo file "+is.name() ); + ZYPP_RETHROW( ex ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoFileReader + // + /////////////////////////////////////////////////////////////////// + + RepoFileReader::RepoFileReader( const Pathname & repo_file, + ProcessRepo callback, + const ProgressData::ReceiverFnc &progress ) + : _callback(std::move(callback)) + { + repositories_in_stream(InputStream(repo_file), _callback, progress); + } + + RepoFileReader::RepoFileReader( const InputStream &is, + ProcessRepo callback, + const ProgressData::ReceiverFnc &progress ) + : _callback(std::move(callback)) + { + repositories_in_stream(is, _callback, progress); + } + + RepoFileReader::~RepoFileReader() + {} + + + std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj ) + { + return str; + } + + } // namespace parser + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/RepoFileReader.h b/zypp/parser/RepoFileReader.h new file mode 100644 index 0000000..e97c867 --- /dev/null +++ b/zypp/parser/RepoFileReader.h @@ -0,0 +1,118 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoFileReader.h + * +*/ +#ifndef ZYPP_REPO_REPOFILEREADER_H +#define ZYPP_REPO_REPOFILEREADER_H + +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + /** + * \short Read repository data from a .repo file + * + * After each repo is read, a \ref RepoInfo is prepared and \ref _callback + * is called with the object passed in. + * + * The \ref _callback is provided on construction. + * + * \code + * RepoFileReader reader(repo_file, + * bind( &SomeClass::callbackfunc, &SomeClassInstance, _1, _2 ) ); + * \endcode + * + * \note Multiple baseurls in a repo file are supported using this style: + * \code + * baseurl=http://server.a/path/to/repo + * http://server.b/path/to/repo + * http://server.c/path/to/repo + * \endcode + * Repeating the \c baseurl= tag on each line is also accepted, but when the + * file has to be written, the preferred style is used. + */ + class RepoFileReader + { + friend std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj ); + public: + + /** + * Callback definition. + * First parameter is a \ref RepoInfo object with the resource + * second parameter is the resource type. + * + * Return false from the callback to get a \ref AbortRequestException + * to be thrown and the processing to be cancelled. + */ + using ProcessRepo = function; + + /** Implementation */ + class Impl; + + public: + /** + * \short Constructor. Creates the reader and start reading. + * + * \param repo_file A valid .repo file + * \param callback Callback that will be called for each repository. + * \param progress Optional progress function. \see ProgressData + * + * \throws AbortRequestException If the callback returns false + * \throws Exception If a error occurs at reading / parsing + * + */ + RepoFileReader( const Pathname & repo_file, + ProcessRepo callback, + const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() ); + + /** + * \short Constructor. Creates the reader and start reading. + * + * \param is A valid input stream + * \param callback Callback that will be called for each repository. + * \param progress Optional progress function. \see ProgressData + * + * \throws AbortRequestException If the callback returns false + * \throws Exception If a error occurs at reading / parsing + * + */ + RepoFileReader( const InputStream &is, + ProcessRepo callback, + const ProgressData::ReceiverFnc &progress = ProgressData::ReceiverFnc() ); + + /** + * Dtor + */ + ~RepoFileReader(); + private: + ProcessRepo _callback; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoFileReader Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoFileReader & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_REPOFILEREADER_H diff --git a/zypp/parser/RepoindexFileReader.cc b/zypp/parser/RepoindexFileReader.cc new file mode 100644 index 0000000..c8a339a --- /dev/null +++ b/zypp/parser/RepoindexFileReader.cc @@ -0,0 +1,282 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/RepoindexFileReader.cc + * Implementation of repoindex.xml file reader. + */ +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include + +#include + + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "parser" + +using std::endl; + +namespace zypp +{ + namespace parser + { + using xml::Reader; + using xml::XmlString; + + /////////////////////////////////////////////////////////////////// + namespace + { + class VarReplacer : private base::NonCopyable + { + public: + /** */ + void setVar( const std::string & key_r, const std::string & val_r ) + { + //MIL << "*** Inject " << key_r << " = " << val_r; + _vars[key_r] = replace( val_r ); + //MIL << " (" << _vars[key_r] << ")" << endl; + } + + std::string replace( const std::string & val_r ) const + { + std::string::size_type vbeg = val_r.find( "%{", 0 ); + if ( vbeg == std::string::npos ) + return val_r; + + str::Str ret; + std::string::size_type cbeg = 0; + for( ; vbeg != std::string::npos; vbeg = val_r.find( "%{", vbeg ) ) + { + std::string::size_type nbeg = vbeg+2; + std::string::size_type nend = val_r.find( '}', nbeg ); + if ( nend == std::string::npos ) + { + WAR << "Incomplete variable in '" << val_r << "'" << endl; + break; + } + const auto & iter = _vars.find( val_r.substr( nbeg, nend-nbeg ) ); + if ( iter != _vars.end() ) + { + if ( cbeg < vbeg ) + ret << val_r.substr( cbeg, vbeg-cbeg ); + ret << iter->second; + cbeg = nend+1; + } + else + WAR << "Undefined variable %{" << val_r.substr( nbeg, nend-nbeg ) << "} in '" << val_r << "'" << endl; + vbeg = nend+1; + } + if ( cbeg < val_r.size() ) + ret << val_r.substr( cbeg ); + + return ret; + } + private: + std::unordered_map _vars; + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoindexFileReader::Impl + // + class RepoindexFileReader::Impl : private base::NonCopyable + { + public: + /** + * CTOR + * + * \see RepoindexFileReader::RepoindexFileReader(Pathname,ProcessResource) + */ + Impl(const InputStream &is, ProcessResource &&callback); + + /** + * Callback provided to the XML parser. + */ + bool consumeNode( Reader & reader_r ); + + DefaultIntegral _ttl; + + private: + bool getAttrValue( const std::string & key_r, Reader & reader_r, std::string & value_r ) + { + const XmlString & s( reader_r->getAttribute( key_r ) ); + if ( s.get() ) + { + value_r = _replacer.replace( s.asString() ); + return !value_r.empty(); + } + value_r.clear(); + return false; + } + + private: + /** Function for processing collected data. Passed-in through constructor. */ + ProcessResource _callback; + VarReplacer _replacer; + }; + /////////////////////////////////////////////////////////////////////// + + RepoindexFileReader::Impl::Impl(const InputStream &is, + ProcessResource &&callback) + : _callback(std::move(callback)) + { + Reader reader( is ); + MIL << "Reading " << is.path() << endl; + reader.foreachNode( bind( &RepoindexFileReader::Impl::consumeNode, this, _1 ) ); + } + + // -------------------------------------------------------------------------- + + /* + * xpath and multiplicity of processed nodes are included in the code + * for convenience: + * + * // xpath: (?|*|+) + * + * if multiplicity is ommited, then the node has multiplicity 'one'. + */ + + // -------------------------------------------------------------------------- + + bool RepoindexFileReader::Impl::consumeNode( Reader & reader_r ) + { + if ( reader_r->nodeType() == XML_READER_TYPE_ELEMENT ) + { + // xpath: /repoindex + if ( reader_r->name() == "repoindex" ) + { + while ( reader_r.nextNodeAttribute() ) + { + const std::string & name( reader_r->localName().asString() ); + const std::string & value( reader_r->value().asString() ); + _replacer.setVar( name, value ); + // xpath: /repoindex@ttl + if ( name == "ttl" ) + _ttl = str::strtonum(value); + } + return true; + } + + // xpath: /repoindex/data (+) + if ( reader_r->name() == "repo" ) + { + RepoInfo info; + // Set some defaults that are not contained in the repo information + info.setAutorefresh( true ); + info.setEnabled(false); + + std::string attrValue; + + // required alias + // mandatory, so we can allow it in var replacement without reset + if ( getAttrValue( "alias", reader_r, attrValue ) ) + { + info.setAlias( attrValue ); + _replacer.setVar( "alias", attrValue ); + } + else + throw ParseException(str::form(_("Required attribute '%s' is missing."), "alias")); + + // required url + // SLES HACK: or path, but beware of the hardcoded '/repo' prefix! + { + std::string urlstr; + std::string pathstr; + getAttrValue( "url", reader_r, urlstr ); + getAttrValue( "path", reader_r, pathstr ); + if ( urlstr.empty() ) + { + if ( pathstr.empty() ) + throw ParseException(str::form(_("One or both of '%s' or '%s' attributes is required."), "url", "path")); + else + info.setPath( Pathname("/repo") / pathstr ); + } + else + { + if ( pathstr.empty() ) + info.setBaseUrl( Url(urlstr) ); + else + { + Url url( urlstr ); + url.setPathName( Pathname(url.getPathName()) / "repo" / pathstr ); + info.setBaseUrl( url ); + } + } + } + + // optional name + if ( getAttrValue( "name", reader_r, attrValue ) ) + info.setName( attrValue ); + + // optional targetDistro + if ( getAttrValue( "distro_target", reader_r, attrValue ) ) + info.setTargetDistribution( attrValue ); + + // optional priority + if ( getAttrValue( "priority", reader_r, attrValue ) ) + info.setPriority( str::strtonum( attrValue ) ); + + + // optional enabled + if ( getAttrValue( "enabled", reader_r, attrValue ) ) + info.setEnabled( str::strToBool( attrValue, info.enabled() ) ); + + // optional autorefresh + if ( getAttrValue( "autorefresh", reader_r, attrValue ) ) + info.setAutorefresh( str::strToBool( attrValue, info.autorefresh() ) ); + + DBG << info << endl; + + // ignore the rest + _callback(info); + return true; + } + } + + return true; + } + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoindexFileReader + // + /////////////////////////////////////////////////////////////////// + + RepoindexFileReader::RepoindexFileReader( Pathname repoindex_file, ProcessResource callback ) + : _pimpl(new Impl( InputStream(std::move(repoindex_file)), std::move(callback) )) + {} + + RepoindexFileReader::RepoindexFileReader(const InputStream &is, ProcessResource callback ) + : _pimpl(new Impl( is, std::move(callback) )) + {} + + RepoindexFileReader::~RepoindexFileReader() + {} + + Date::Duration RepoindexFileReader::ttl() const { return _pimpl->_ttl; } + + } // ns parser +} // ns zypp + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/parser/RepoindexFileReader.h b/zypp/parser/RepoindexFileReader.h new file mode 100644 index 0000000..9171d2d --- /dev/null +++ b/zypp/parser/RepoindexFileReader.h @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/RepoindexFileReader.h + * Interface of repoindex.xml file reader. + */ +#ifndef zypp_source_yum_RepoindexFileReader_H +#define zypp_source_yum_RepoindexFileReader_H + +#include +#include +#include +#include +#include +#include + +namespace zypp +{ + class RepoInfo; + + namespace parser + { + + /** + * Reads through a repoindex.xml file and collects repositories. + * + * After each repository is read, a \ref RepoInfo + * is prepared and \ref _callback + * is called with this object passed in. + * + * The \ref _callback is provided on construction. + * + * + * \code + * RepoindexFileReader reader(repoindex_file, + * bind( &SomeClass::callbackfunc, &SomeClassInstance, _1) ); + * \endcode + */ + class ZYPP_API RepoindexFileReader : private base::NonCopyable + { + public: + /** + * Callback definition. + * First parameter is a \ref RepoInfo object with the resource + * FIXME return value is ignored + */ + using ProcessResource = function; + + /** + * CTOR. Creates also \ref xml::Reader and starts reading. + * + * \param repoindexFile is the repoindex.xml file you want to read + * \param callback is a function. + * + * \see RepoindexFileReader::ProcessResource + */ + RepoindexFileReader(Pathname repoindexFile, + ProcessResource callback); + + /** + * \short Constructor. Creates the reader and start reading. + * + * \param is a valid input stream + * \param callback Callback that will be called for each repository. + * + * \see RepoindexFileReader::ProcessResource + */ + RepoindexFileReader( const InputStream &is, + ProcessResource callback ); + + /** + * DTOR + */ + ~RepoindexFileReader(); + + /** Metadata TTL (repoindex.xml:xpath:/repoindex@ttl or 0). */ + Date::Duration ttl() const; + + private: + class Impl; + RW_pointer > _pimpl; + }; + + + } // ns parser +} // ns zypp + +#endif /*zypp_source_yum_RepoindexFileReader_H*/ + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/parser/ServiceFileReader.cc b/zypp/parser/ServiceFileReader.cc new file mode 100644 index 0000000..b71740c --- /dev/null +++ b/zypp/parser/ServiceFileReader.cc @@ -0,0 +1,183 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/RepoFileReader.cc + * +*/ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +using std::endl; +using zypp::parser::IniDict; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + class ServiceFileReader::Impl + { + public: + static void parseServices( const Pathname & file, + const ServiceFileReader::ProcessService & callback ); + }; + + void ServiceFileReader::Impl::parseServices( const Pathname & file, + const ServiceFileReader::ProcessService & callback/*, + const ProgressData::ReceiverFnc &progress*/ ) + try { + InputStream is(file); + if( is.stream().fail() ) + { + ZYPP_THROW(Exception("Failed to open service file")); + } + + parser::IniDict dict(is); + for ( parser::IniDict::section_const_iterator its = dict.sectionsBegin(); + its != dict.sectionsEnd(); + ++its ) + { + MIL << (*its) << endl; + + ServiceInfo service(*its); + std::map> repoStates; // > + + for ( IniDict::entry_const_iterator it = dict.entriesBegin(*its); + it != dict.entriesEnd(*its); + ++it ) + { + // MIL << (*it).first << endl; + if ( it->first == "name" ) + service.setName( it->second ); + else if ( it->first == "url" && ! it->second.empty() ) + service.setUrl( Url (it->second) ); + else if ( it->first == "enabled" ) + service.setEnabled( str::strToTrue( it->second ) ); + else if ( it->first == "autorefresh" ) + service.setAutorefresh( str::strToTrue( it->second ) ); + else if ( it->first == "type" ) + service.setType( repo::ServiceType(it->second) ); + else if ( it->first == "ttl_sec" ) + service.setTtl( str::strtonum(it->second) ); + else if ( it->first == "lrf_dat" ) + service.setLrf( Date( it->second ) ); + else if ( it->first == "repostoenable" ) + { + std::vector aliases; + str::splitEscaped( it->second, std::back_inserter(aliases) ); + for_( ait, aliases.begin(), aliases.end() ) + { + service.addRepoToEnable( *ait ); + } + } + else if ( it->first == "repostodisable" ) + { + std::vector aliases; + str::splitEscaped( it->second, std::back_inserter(aliases) ); + for_( ait, aliases.begin(), aliases.end() ) + { + service.addRepoToDisable( *ait ); + } + } + else if ( str::startsWith( it->first, "repo_" ) ) + { + static str::regex rxexpr( "([0-9]+)(_(.*))?" ); + str::smatch what; + if ( str::regex_match( it->first.c_str()+5/*repo_*/, what, rxexpr ) ) + { + std::string tag( what[1] ); + if ( what.size() > 3 ) + { + // attribute + if ( what[3] == "enabled" ) + repoStates[tag].second.enabled = str::strToBool( it->second, repoStates[tag].second.enabled ); + else if ( what[3] == "autorefresh" ) + repoStates[tag].second.autorefresh = str::strToBool( it->second, repoStates[tag].second.autorefresh ); + else if ( what[3] == "priority" ) + str::strtonum( it->second, repoStates[tag].second.priority ); + else + ERR << "Unknown attribute " << it->first << " ignored" << endl; + } + else + { + // alias + repoStates[tag].first = it->second; + } + } + else + ERR << "Unknown attribute " << it->first << " ignored" << endl; + } + else + ERR << "Unknown attribute " << it->first << " ignored" << endl; + } + + if ( ! repoStates.empty() ) + { + ServiceInfo::RepoStates data; + for ( const auto & el : repoStates ) + { + if ( el.second.first.empty() ) + ERR << "Missing alias for repo_" << el.first << "; ignore entry" << endl; + else + data[el.second.first] = el.second.second; + } + if ( ! data.empty() ) + service.setRepoStates( std::move(data) ); + } + + MIL << "Linking ServiceInfo with file " << file << endl; + service.setFilepath(file); + + // add it to the list. + if ( !callback(service) ) + ZYPP_THROW(AbortRequestException()); + } + } + catch ( Exception & ex ) { + ex.addHistory( "Parsing .service file "+file.asString() ); + ZYPP_RETHROW( ex ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoFileReader + // + /////////////////////////////////////////////////////////////////// + + ServiceFileReader::ServiceFileReader( const Pathname & repo_file, + const ProcessService & callback/*, + const ProgressData::ReceiverFnc &progress */) + { + Impl::parseServices(repo_file, callback/*, progress*/); + //MIL << "Done" << endl; + } + + ServiceFileReader::~ServiceFileReader() + {} + + std::ostream & operator<<( std::ostream & str, const ServiceFileReader & obj ) + { + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/ServiceFileReader.h b/zypp/parser/ServiceFileReader.h new file mode 100644 index 0000000..16d467a --- /dev/null +++ b/zypp/parser/ServiceFileReader.h @@ -0,0 +1,90 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/ServiceFileReader.h + * +*/ +#ifndef ZYPP_REPO_SERVICEFILEREADER_H +#define ZYPP_REPO_SERVICEFILEREADER_H + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class ServiceInfo; + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + + /** + * \short Read service data from a .service file + * + * After each service is read, a \ref ServiceInfo is prepared and \ref _callback + * is called with the object passed in. + * + * The \ref _callback is provided on construction. + * + * \code + * ServiceFileReader reader(service_file, + * bind( &SomeClass::callbackfunc, &SomeClassInstance, _1 ) ); + * \endcode + */ + class ServiceFileReader + { + friend std::ostream & operator<<( std::ostream & str, const ServiceFileReader & obj ); + public: + + /** + * Callback definition. + * First parameter is a \ref ServiceInfo object with the resource. + * + * Return false from the callback to get a \ref AbortRequestException + * to be thrown and the processing to be cancelled. + */ + using ProcessService = function; + + /** Implementation */ + class Impl; + + public: + /** + * \short Constructor. Creates the reader and start reading. + * + * \param serviceFile A valid .repo file + * \param callback Callback that will be called for each repository. + * + * \throws AbortRequestException If the callback returns false + * \throws Exception If a error occurs at reading / parsing + * + */ + ServiceFileReader( const Pathname & serviceFile, + const ProcessService & callback); + + /** + * Dtor + */ + ~ServiceFileReader(); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ServiceFileReader Stream output */ + std::ostream & operator<<( std::ostream & str, const ServiceFileReader & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_SERVICEFILEREADER_H diff --git a/zypp/parser/schema/repoindex.rnc b/zypp/parser/schema/repoindex.rnc new file mode 100644 index 0000000..f183cc2 --- /dev/null +++ b/zypp/parser/schema/repoindex.rnc @@ -0,0 +1,40 @@ +# repoindex.xml RNC schema + +start = repoindex-element + +repoindex-element = + element repoindex { + element repo { + # Internal repo identifier + attribute alias { xsd:string }, + + # Human-readable name of the repository + attribute name { xsd:string }?, + + # More detailed description of what's inside + attribute description { xsd:string }?, + ( + # Path relative to the base url of the service + # WARNING 'repo/' is always prepended to this path + # (this is inherited from NU services) + attribute path { xsd:string } + | + # Full URI of the repository (can also be outside of the service base) + attribute url { xsd:anyURI } + ), + # unique identifier of the target distribution (distroname-version-arch) + # if not specified, all the repositories will be added by the client + attribute distro_target { xsd:string }?, + + # An optional repository type. Will be determined automatically if not + # specified. + attribute type { xsd:string }?, + + # Repository priority. Starts from 1 (the highest); the higher number, + # the lowe priority. + attribute priority { xsd:integer }?, + + # legacy attribute, currently not used + attribute pub { xsd:boolean }? + } + } diff --git a/zypp/parser/susetags/ContentFileReader.cc b/zypp/parser/susetags/ContentFileReader.cc new file mode 100644 index 0000000..03409ea --- /dev/null +++ b/zypp/parser/susetags/ContentFileReader.cc @@ -0,0 +1,274 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/susetags/ContentFileReader.cc + * +*/ +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +using std::endl; +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "parser::susetags" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace susetags + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ContentFileReader::Impl + // + /** ContentFileReader implementation. */ + struct ContentFileReader::Impl + { + public: + Impl() + {} + + RepoIndex & repoindex() + { + if ( !_repoindex ) + _repoindex = new RepoIndex; + return *_repoindex; + } + + bool hasRepoIndex() const + { return _repoindex != nullptr; } + + RepoIndex_Ptr handoutRepoIndex() + { + RepoIndex_Ptr ret; + ret.swap( _repoindex ); + _repoindex = nullptr; + return ret; + } + + public: + bool setFileCheckSum( std::map & map_r, const std::string & value ) const + { + bool error = false; + std::vector words; + if ( str::split( value, std::back_inserter( words ) ) == 3 ) + { + map_r[words[2]] = CheckSum( words[0], words[1] ); + } + else + { + error = true; + } + return error; + } + + public: + std::string _inputname; + + private: + RepoIndex_Ptr _repoindex; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ContentFileReader + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ContentFileReader::ContentFileReader + // METHOD TYPE : Ctor + // + ContentFileReader::ContentFileReader() + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ContentFileReader::~ContentFileReader + // METHOD TYPE : Dtor + // + ContentFileReader::~ContentFileReader() + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ContentFileReader::beginParse + // METHOD TYPE : void + // + void ContentFileReader::beginParse() + { + _pimpl.reset( new Impl() ); + // actually mandatory, but in case they were forgotten... + _pimpl->repoindex().descrdir = "suse/setup/descr"; + _pimpl->repoindex().datadir = "suse"; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ContentFileReader::endParse + // METHOD TYPE : void + // + void ContentFileReader::endParse() + { + // consume oldData + if ( _pimpl->hasRepoIndex() ) + { + if ( _repoIndexConsumer ) + _repoIndexConsumer( _pimpl->handoutRepoIndex() ); + } + + MIL << "[Content]" << endl; + _pimpl.reset(); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ContentFileReader::userRequestedAbort + // METHOD TYPE : void + // + void ContentFileReader::userRequestedAbort( unsigned lineNo_r ) + { + ZYPP_THROW( AbortRequestException( errPrefix( lineNo_r ) ) ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ContentFileReader::errPrefix + // METHOD TYPE : std::string + // + std::string ContentFileReader::errPrefix( unsigned lineNo_r, + const std::string & msg_r, + const std::string & line_r ) const + { + return str::form( "%s:%u:%s | %s", + _pimpl->_inputname.c_str(), + lineNo_r, + line_r.c_str(), + msg_r.c_str() ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ContentFileReader::parse + // METHOD TYPE : void + // + void ContentFileReader::parse( const InputStream & input_r, + const ProgressData::ReceiverFnc & fnc_r ) + { + MIL << "Start parsing content repoindex" << input_r << endl; + if ( ! input_r.stream() ) + { + std::ostringstream s; + s << "Can't read bad stream: " << input_r; + ZYPP_THROW( ParseException( s.str() ) ); + } + beginParse(); + _pimpl->_inputname = input_r.name(); + + ProgressData ticks( makeProgressData( input_r ) ); + ticks.sendTo( fnc_r ); + if ( ! ticks.toMin() ) + userRequestedAbort( 0 ); + + iostr::EachLine line( input_r ); + for( ; line; line.next() ) + { + // strip 1st word from line to separate tag and value. + std::string value( *line ); + std::string key( str::stripFirstWord( value, /*ltrim_first*/true ) ); + + if ( key.empty() || *key.c_str() == '#' ) // empty or comment line + { + continue; + } + + // strip modifier if exists + std::string modifier; + std::string::size_type pos = key.rfind( '.' ); + if ( pos != std::string::npos ) + { + modifier = key.substr( pos+1 ); + key.erase( pos ); + } + + // + // ReppoIndex related data: + // + else if ( key == "DESCRDIR" ) + { + _pimpl->repoindex().descrdir = value; + } + else if ( key == "DATADIR" ) + { + _pimpl->repoindex().datadir = value; + } + else if ( key == "KEY" ) + { + if ( _pimpl->setFileCheckSum( _pimpl->repoindex().signingKeys, value ) ) + { + ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [KEY algorithm checksum filename]", *line ) ) ); + } + } + else if ( key == "META" ) + { + if ( _pimpl->setFileCheckSum( _pimpl->repoindex().metaFileChecksums, value ) ) + { + ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [algorithm checksum filename]", *line ) ) ); + } + } + else if ( key == "HASH" ) + { + if ( _pimpl->setFileCheckSum( _pimpl->repoindex().mediaFileChecksums, value ) ) + { + ZYPP_THROW( ParseException( errPrefix( line.lineNo(), "Expected [algorithm checksum filename]", *line ) ) ); + } + } + else + { + DBG << errPrefix( line.lineNo(), "ignored", *line ) << endl; + } + + + if ( ! ticks.set( input_r.stream().tellg() ) ) + userRequestedAbort( line.lineNo() ); + } + + // + // post processing + // + if ( ! ticks.toMax() ) + userRequestedAbort( line.lineNo() ); + + endParse(); + MIL << "Done parsing " << input_r << endl; + } + + ///////////////////////////////////////////////////////////////// + } // namespace susetags + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/susetags/ContentFileReader.h b/zypp/parser/susetags/ContentFileReader.h new file mode 100644 index 0000000..c76d4e0 --- /dev/null +++ b/zypp/parser/susetags/ContentFileReader.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/susetags/ContentFileReader.h + * +*/ +#ifndef ZYPP_PARSER_SUSETAGS_CONTENTFILEREADER_H +#define ZYPP_PARSER_SUSETAGS_CONTENTFILEREADER_H + +#include + +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace susetags + { ///////////////////////////////////////////////////////////////// + + class RepoIndex; + DEFINE_PTR_TYPE(RepoIndex); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ContentFileReader + // + /** Parse repoindex part from a \c content file. + * This is all the downloader needs. + */ + class ContentFileReader : private base::NonCopyable + { + public: + using RepoIndexConsumer = function; + + public: + /** Default ctor */ + ContentFileReader(); + /** Dtor */ + virtual ~ContentFileReader(); + /** Parse the stream. + * \throw ParseException on errors. + * \throw AbortRequestException on user request. + * Invokes \ref consume for each tag. \ref consume might throw + * other exceptions as well. + */ + virtual void parse( const InputStream & imput_r, + const ProgressData::ReceiverFnc & fnc_r = ProgressData::ReceiverFnc() ); + + public: + /** Consumer to call when repo index was parsed. */ + void setRepoIndexConsumer( const RepoIndexConsumer & fnc_r ) + { _repoIndexConsumer = fnc_r; } + + protected: + /** Called when start parsing. */ + virtual void beginParse(); + /** Called when the parse is done. */ + virtual void endParse(); + + protected: + /** Called when user(callback) request to abort. + * \throws AbortRequestException unless overloaded. + */ + virtual void userRequestedAbort( unsigned lineNo_r ); + + protected: + /** Prefix exception message with line information. */ + std::string errPrefix( unsigned lineNo_r, + const std::string & msg_r = std::string(), + const std::string & line_r = "-" ) const; + + private: + struct Impl; + RW_pointer > _pimpl; + RepoIndexConsumer _repoIndexConsumer; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace susetags + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_SUSETAGS_CONTENTFILEREADER_H diff --git a/zypp/parser/susetags/RepoIndex.cc b/zypp/parser/susetags/RepoIndex.cc new file mode 100644 index 0000000..d822ab6 --- /dev/null +++ b/zypp/parser/susetags/RepoIndex.cc @@ -0,0 +1,49 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/susetags/RepoIndex.cc + * +*/ +#include +#include + +#include + +using std::endl; +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "parser::susetags" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace susetags + { ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(RepoIndex); + + std::ostream & RepoIndex::dumpOn( std::ostream & str ) const + { + return str + << "RepoIndex checksums: META files " << metaFileChecksums.size() + << ", HASH files " << mediaFileChecksums.size() + << ", KEY files " << signingKeys.size(); + } + + ///////////////////////////////////////////////////////////////// + } // namespace susetags + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/susetags/RepoIndex.h b/zypp/parser/susetags/RepoIndex.h new file mode 100644 index 0000000..a641451 --- /dev/null +++ b/zypp/parser/susetags/RepoIndex.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/susetags/RepoIndex.h + * +*/ +#ifndef ZYPP_PARSER_SUSETAGS_REPOINDEX_H +#define ZYPP_PARSER_SUSETAGS_REPOINDEX_H + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace parser + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace susetags + { ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(RepoIndex); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoIndex + // + /** Repository content data (from /content file). + * File and Checksum definitions required by Downloader and Parser. + * (Do not confuse with NU's repoindex.xml) + */ + class RepoIndex : public base::ReferenceCounted, private base::NonCopyable + { + friend class ContentFileReader; + public: + using FileChecksumMap = std::map; + + Pathname descrdir; + Pathname datadir; + + FileChecksumMap metaFileChecksums; + FileChecksumMap mediaFileChecksums; + FileChecksumMap signingKeys; + + protected: + /** Overload to realize std::ostream & operator\<\<. */ + std::ostream & dumpOn( std::ostream & str ) const override; + }; + ////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace susetags + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace parser + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_SUSETAGS_REPOINDEX_H diff --git a/zypp/parser/xml/Node.cc b/zypp/parser/xml/Node.cc new file mode 100644 index 0000000..e714c65 --- /dev/null +++ b/zypp/parser/xml/Node.cc @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/Reader.cc + * +*/ +#include +#include + +#include + +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + xmlTextReaderPtr const Node::_no_reader = 0; + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Node::Node + // METHOD TYPE : Constructor + // + Node::Node() + : _reader( _no_reader ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Node::Node + // METHOD TYPE : Constructor + // + Node::Node( xmlTextReaderPtr const & reader_r ) + : _reader( reader_r ) + {} + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Node & obj ) + { + if ( ! obj ) + return str << "NoNode" << endl; +#define X(m) obj.m() + str << X(depth) << ":" << std::string( X(depth), ' ') << X(nodeType) << " <"; + if ( X(nodeType) == XML_READER_TYPE_NONE ) + { + return str << '[' << X(readState) << "]>"; + } + if ( obj.prefix() ) + str << X(prefix) << ':'; + str << X(localName) << "> "; + if ( X(hasAttributes) ) + str << " [attr " << X(attributeCount); + else + str << " [noattr"; + if ( X(isEmptyElement) ) + str << "|empty"; + str << ']'; + if ( X(hasValue) ) + str << " {" << X(value) << '}'; +#undef X + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + diff --git a/zypp/parser/xml/Node.h b/zypp/parser/xml/Node.h new file mode 100644 index 0000000..8630a95 --- /dev/null +++ b/zypp/parser/xml/Node.h @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/Node.h + * +*/ +#ifndef ZYPP_PARSER_XML_NODE_H +#define ZYPP_PARSER_XML_NODE_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Node + // + /** xmlTextReader based interface to \ref Reader's current node. + * Node provides xmlTextReader methods that do not change + * the readers position in the file. Mostly access to the + * nodes attributes. + **/ + class Node + { + public: + /** Default ctor. */ + Node(); + + /** Ctor referencing a \ref Reader. */ + Node( xmlTextReaderPtr const & reader_r ); + + /** Validate Node in a boolean context. */ + explicit operator bool() const + { return _reader; } + + public: + /** Provides the number of attributes of the current node. */ + int attributeCount() const + { return xmlTextReaderAttributeCount( _reader ); } + + /** The base URI of the node. */ + XmlString baseUri() const + { return xmlTextReaderConstBaseUri( _reader ); } + + /** Provide the column number of the current parsing point. */ + int columnNumber() const + { return xmlTextReaderGetParserColumnNumber( _reader ); } + + /** The depth of the node in the tree. */ + int depth() const + { return xmlTextReaderDepth( _reader ); } + + /** Determine the encoding of the document being read. */ + XmlString encoding() const + { return xmlTextReaderConstEncoding( _reader ); } + + /** Provides a copy of the attribute value with the specified + * qualified name. */ + XmlString getAttribute( const char * name_r ) const + { return XmlString( xmlTextReaderGetAttribute( _reader, reinterpret_cast(name_r) ), + XmlString::FREE ); } + /** \overload */ + XmlString getAttribute( const std::string & name_r ) const + { return getAttribute( name_r.c_str() ); } + + /** Provides a copy of the attribute value with the specified + * index relative to the containing element. */ + XmlString getAttributeNo( int no_r ) const + { return XmlString( xmlTextReaderGetAttributeNo( _reader, no_r ), XmlString::FREE ); } + + /** Whether the node has attributes. */ + int hasAttributes() const + { return xmlTextReaderHasAttributes( _reader ); } + + /** Whether the node can have a text value. */ + int hasValue() const + { return xmlTextReaderHasValue( _reader ); } + + /** Whether this is an Attribute node. */ + bool isAttribute() const + { return( nodeType() == XML_READER_TYPE_ATTRIBUTE ); } + + /** Whether an Attribute node was generated from the default value + * defined in the DTD or schema. */ + int isDefault() const + { return xmlTextReaderIsDefault( _reader ); } + + /** Check if the current node is empty. */ + int isEmptyElement() const + { return xmlTextReaderIsEmptyElement( _reader ); } + + /** Determine whether the current node is a namespace declaration + * rather than a regular attribute.*/ + int isNamespaceDecl() const + { return xmlTextReaderIsNamespaceDecl( _reader ); } + + /** Provide the line number of the current parsing point. */ + int lineNumber() const + { return xmlTextReaderGetParserLineNumber( _reader ); } + + /** The local name of the node. */ + XmlString localName() const + { return xmlTextReaderConstLocalName( _reader ); } + + /** The qualified name of the node, equal to Prefix :LocalName. */ + XmlString name() const + { return xmlTextReaderConstName( _reader ); } + + /** The URI defining the namespace associated with the node. */ + XmlString namespaceUri() const + { return xmlTextReaderConstNamespaceUri( _reader ); } + + /** Get the node type of the current node. */ + NodeType nodeType() const + { return (NodeType)xmlTextReaderNodeType( _reader ); } + + /** A shorthand reference to the namespace associated with the node. */ + XmlString prefix() const + { return xmlTextReaderConstPrefix( _reader ); } + + /** The quotation mark character used to enclose the value of an attribute. + * \return \c " or \c ' or -1 in case of error. */ + int quoteChar() const + { return xmlTextReaderQuoteChar( _reader ); } + + /** Gets the read state of the reader. */ + ReadState readState() const + { return (ReadState)xmlTextReaderReadState( _reader ); } + + /** Provides the text value of the node if present. */ + XmlString value() const + { return xmlTextReaderConstValue( _reader ); } + + /** Provides a copy of the text value of the node if present. */ + XmlString getValue() const + { return XmlString( xmlTextReaderValue( _reader ), XmlString::FREE ); } + + /** The xml:lang scope within which the node resides. */ + XmlString xmlLang() const + { return xmlTextReaderConstXmlLang( _reader ); } + + /** Determine the XML version of the document being read. */ + XmlString xmlVersion() const + { return xmlTextReaderConstXmlVersion( _reader ); } + + private: + /** NULL Reader referenced by default ctor. */ + static xmlTextReaderPtr const _no_reader; + /** Reference to the \ref Reader. */ + xmlTextReaderPtr const & _reader; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Node Stream output. */ + std::ostream & operator<<( std::ostream & str, const Node & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_NODE_H diff --git a/zypp/parser/xml/Parse.h b/zypp/parser/xml/Parse.h new file mode 100644 index 0000000..f1b9c88 --- /dev/null +++ b/zypp/parser/xml/Parse.h @@ -0,0 +1,115 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/Parse.h + * +*/ +#ifndef ZYPP_PARSER_XML_PARSE_H +#define ZYPP_PARSER_XML_PARSE_H + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /** Parse xml \c input_r and store data in \c data_r. + * + * \c TData must be defaultconstructible and assignable. + * + * \c TData::RootNode must be a \ref xml::ParseDef constructible + * from \c TData&. + * + * \throws ParseDefException on parse errors. + * + * To parse a xml file like this: + * \code + * + * value + * + * + * + * \endcode + * + * You need something like this: + * \code + * struct XmlData + * { + * // data + * unsigned attr; + * std::string value; + * std:list names; + * + * public: + * // Convenience parsing to *this. + * void parse( const Pathname & path_r ) + * { xml::rnParse( path_r, *this ); } + * + * public: + * // Parser description + * struct RootNode : public xml::ParseDef + * { + * RootNode( XmlData & data ) + * : ParseDef( "test", MANDTAORY ) + * , _data( data ) + * { + * (*this) + * ("setup", MANDTAORY, + * xml::parseDefAssign( data.value ) + * ( "attr", data.attr ) ) + * // Each individual list entry is collected locally + * // and appended to the list after the node is done. + * ("list", MULTIPLE_OPTIONAL, + * xml::parseDefAssign( "name", _cname ) + * >> bind( &RootNode::cdone, this, _1 ) ) + * ; + * } + * + * void cdone( const xml::Node & node_r ) + * { + * _data.push_back( _cname ); + * _cname.clear(); // prepare for next + * } + * + * private: + * XmlData & _data; // stored just because notification callbacks are used. + * std::string _cname; + * }; + * }; + * + * XmlData xmlData; + * xmlData.parse( "/tmp/mytest.xml" ); + * \endcode + */ + template + inline void rnParse( const InputStream & input_r, TData & data_r ) + { + typedef typename TData::RootNode RootNode; + TData pdata; + + xml::Reader reader( input_r ); + RootNode rootNode( pdata ); + rootNode.take( reader ); + + data_r = pdata; + } + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_PARSEDEF_H diff --git a/zypp/parser/xml/ParseDef.cc b/zypp/parser/xml/ParseDef.cc new file mode 100644 index 0000000..3a5c93f --- /dev/null +++ b/zypp/parser/xml/ParseDef.cc @@ -0,0 +1,481 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/ParseDef.cc + * +*/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefImplConsume + // + /** */ + struct ParseDefImplConsume : public ParseDefConsumeRedirect + { + void start( const Node & node_r ) override + { + debuglog( "START ", node_r ); + ParseDefConsumeRedirect::start( node_r ); + } + + void text( const Node & node_r ) override + { + debuglog( "TEXT ", node_r ); + ParseDefConsumeRedirect::text( node_r ); + } + + void cdata( const Node & node_r ) override + { + debuglog( "CDATA ", node_r ); + ParseDefConsumeRedirect::cdata( node_r ); + } + + void done( const Node & node_r ) override + { + debuglog( "DONE ", node_r ); + ParseDefConsumeRedirect::done( node_r ); + } + + void startSubnode( const Node & node_r ) override + { + debuglog( "---> ", node_r ); + ParseDefConsumeRedirect::startSubnode( node_r ); + } + + void doneSubnode( const Node & node_r ) override + { + debuglog( "<--- ", node_r ); + ParseDefConsumeRedirect::doneSubnode( node_r ); + } + + void debuglog( const char *const tag_r, const Node & node_r ) + { + if ( ParseDef::_debug ) + DBG << tag_r << node_r << endl; + } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDef::Impl + // + /** ParseDef implementation. + * \todo Check using share_ptr_from_this for parent in addNode. + */ + class ParseDef::Impl + { + friend std::ostream & operator<<( std::ostream & str, const ParseDef::Impl & obj ); + public: + using ImplPtr = shared_ptr; + using SubNodes = std::map; + + public: + Impl(std::string &&name_r, Mode mode_r, + shared_ptr &&target_r = + shared_ptr()) + : _name(std::move(name_r)), _mode(mode_r), _parent(NULL) { + if ( target_r ) + _callback.setRedirect( std::move(target_r) ); + } + + Impl(const Impl &) = default; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() + { + for ( SubNodes::iterator it = _subnodes.begin(); it != _subnodes.end(); ++it ) + { + it->second->_parent = NULL; + } + } + + bool isOptional() const + { return Traits::ModeBits(_mode).isEqual( Traits::BIT_OPTIONAL ); } + + bool isMandatory() const + { return Traits::ModeBits(_mode).isEqual( Traits::BIT_MANDTAORY ); } + + bool singleDef() const + { return Traits::ModeBits(_mode).isEqual( Traits::BIT_ONCE ); } + + bool multiDef() const + { return Traits::ModeBits(_mode).isEqual( Traits::BIT_MULTIPLE ); } + + public: + void addNode( const ImplPtr & subnode_r ); + + ImplPtr getNode( const std::string & name_r ) const + { + SubNodes::const_iterator it = _subnodes.find( name_r ); + if ( it != _subnodes.end() ) + return it->second; + return ImplPtr(); + } + + void take( Reader & reader_r ); + + private: + /** Skip the current node. + * \pre Current node must be XML_READER_TYPE_ELEMENT. + * \post At the corresponding end node. + (XML_READER_TYPE_END_ELEMENT or atill at the same node, + if it'a an empty element <node />). + * \return last call to xml::Reader::nextNode. + * \throws ParseDefValidateException if no matching end node found. + */ + bool skipNode( Reader & reader_r ); + + std::string exstr( const std::string & what_r, const Impl & impl_r ) const + { + std::ostringstream str; + str << impl_r << ": " << what_r; + return str.str(); + } + std::string exstr( const std::string & what_r, const Impl & impl_r, const Reader & reader_r ) const + { + std::ostringstream str; + str << impl_r << ": " << what_r << " |reading " << *reader_r; + return str.str(); + } + + public: + std::string _name; + Mode _mode; + DefaultIntegral _visited; + + Impl * _parent; + SubNodes _subnodes; + ParseDefImplConsume _callback; + + DefaultIntegral _parseDepth; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDef::Impl::addNode + // METHOD TYPE : void + // + void ParseDef::Impl::addNode( const ImplPtr & subnode_r ) + { + std::pair res + = _subnodes.insert( std::make_pair( subnode_r->_name, subnode_r ) ); + + if ( ! res.second ) + { + ZYPP_THROW( ParseDefBuildException( exstr("Multiple definiton of subnode "+subnode_r->_name, *this) ) ); + } + if ( res.first->second->_parent ) + { + ZYPP_THROW( ParseDefBuildException( exstr("Can not reparent subnode "+subnode_r->_name, *this) ) ); + } + res.first->second->_parent = this; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDef::Impl::take + // METHOD TYPE : void + // + void ParseDef::Impl::take( Reader & reader_r ) + { + if ( reader_r->nodeType() != XML_READER_TYPE_ELEMENT ) + { + if ( reader_r->depth() == 0 ) + { + // on the very first level we skip any initial whitespace and comments... + do { + // advance to next node + if ( ! reader_r.nextNode() ) + { + ZYPP_THROW( ParseDefValidateException( exstr( "Unexpected EOF ", *this ) ) ); + } + } while( reader_r->nodeType() != XML_READER_TYPE_ELEMENT ); + } + else + { + ZYPP_THROW( ParseDefValidateException( exstr("Expected ELEMENT", *this, reader_r) ) ); + } + } + if ( reader_r->name() != _name ) + { + ZYPP_THROW( ParseDefValidateException( exstr("Wrong ELEMENT name", *this, reader_r) ) ); + } + if ( _visited >= 1 && ! multiDef() ) + { + ZYPP_THROW( ParseDefValidateException( exstr("Multiple definitions", *this, reader_r) ) ); + } + + ++_visited; // Accepted to parse + DtorReset x( _parseDepth, -1 ); + _parseDepth = reader_r->depth(); + + // Parse attributes + _callback.start( *reader_r ); + + // Get content up to end node + // Empty element () has no separate end node, so + // there's nothing to parse. + if ( ! reader_r->isEmptyElement() ) + { + // For non empty elements () parse known nodes + // text and cdata elelments skip unknown nodes. + for ( bool done = false; ! done ; /*advance in inside loop*/) + { + // advance to next node + if ( ! reader_r.nextNode() ) + { + ZYPP_THROW( ParseDefValidateException( exstr( "Unexpected EOF ", *this ) ) ); + } + + switch ( reader_r->nodeType() ) + { + case XML_READER_TYPE_ELEMENT: + // Parse or skip unknown. Anyway reader is located at the + // corresponding end node, or an exception was thrown. + { + ImplPtr sub( getNode( reader_r->name().asString() ) ); + if ( sub ) + { + _callback.startSubnode( *reader_r ); + sub->take( reader_r ); + _callback.doneSubnode( *reader_r ); + } + else + { + if ( ParseDef::_debug ) + WAR << "Skip unknown node " << *reader_r << " in "<< *this << endl; + skipNode( reader_r ); + } + } + break; + + case XML_READER_TYPE_END_ELEMENT: + // This must be the corresponding end node! + if ( reader_r->depth() == _parseDepth + && reader_r->name() == _name ) + { + done = true; + } + else + { + ZYPP_THROW( ParseDefValidateException( exstr("unexpected END_ELEMENT name", *this, reader_r) ) ); + } + break; + + case XML_READER_TYPE_TEXT: + // collect or skip + _callback.text( *reader_r ); + break; + + case XML_READER_TYPE_CDATA: + // collect or skip + _callback.cdata( *reader_r ); + break; + + default: + //DBG << exstr("SKIP ", *this, reader_r) << endl; + break; + } + } + } + + // Parsing complete. Check whether all mandatory nodes were + // present. Finally position behind the end node. + for ( SubNodes::iterator it = _subnodes.begin(); it != _subnodes.end(); ++it ) + { + if ( ! it->second->_visited && it->second->isMandatory() ) + { + ZYPP_THROW( ParseDefValidateException( exstr("Mandatory ELEMENT missing", *(it->second), reader_r) ) ); + } + it->second->_visited = 0; // reset to be ready for an other visit to this!! + } + + _callback.done( *reader_r ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDef::Impl::skipNode + // METHOD TYPE : void + // + bool ParseDef::Impl::skipNode( xml::Reader & reader_r ) + { + if ( ! reader_r.seekToEndNode( reader_r->depth(), + reader_r->name().asString() ) ) + { + ZYPP_THROW( ParseDefValidateException + ( exstr( str::form( "EOF while looking for [%d] <\\%s>", + reader_r->depth(), + reader_r->name().c_str() ), + *this ) ) ); + } + return true; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ParseDef::Impl & obj ) + { + return str << "ParseDef(" << obj._name + << ", " << obj._mode + << ", visits " << obj._visited + << ")"; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDef + // + /////////////////////////////////////////////////////////////////// + + bool ParseDef::_debug = false; + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDef::ParseDef + // METHOD TYPE : Ctor + // + ParseDef::ParseDef( std::string name_r, Mode mode_r ) + : _pimpl( new Impl( std::move(name_r), mode_r ) ) + {} + + ParseDef::ParseDef( std::string name_r, Mode mode_r, shared_ptr target_r ) + : _pimpl( new Impl( std::move(name_r), mode_r, std::move(target_r) ) ) + {} + + ParseDef::ParseDef( const shared_ptr & pimpl_r ) + : _pimpl( pimpl_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDef::~ParseDef + // METHOD TYPE : Dtor + // + ParseDef::~ParseDef() + {} + + const std::string & ParseDef::name() const + { return _pimpl->_name; } + + ParseDef::Mode ParseDef::mode() const + { return _pimpl->_mode; } + + bool ParseDef::isOptional() const + { return _pimpl->isOptional(); } + + bool ParseDef::isMandatory() const + { return _pimpl->isMandatory(); } + + bool ParseDef::singleDef() const + { return _pimpl->singleDef(); } + + bool ParseDef::multiDef() const + { return _pimpl->multiDef(); } + + unsigned ParseDef::visited() const + { return _pimpl->_visited; } + + ParseDef & ParseDef::addNode( ParseDef & subnode_r ) + { _pimpl->addNode( subnode_r._pimpl.getPtr() ); return *this; } + + ParseDef ParseDef::operator[]( const std::string & name_r ) + { + shared_ptr retimpl( _pimpl->getNode( name_r ) ); + if ( ! retimpl ) + { + ZYPP_THROW( ParseDefBuildException( "No subnode "+name_r ) ); + } + return retimpl; + } + + void ParseDef::setConsumer( const shared_ptr & target_r ) + { _pimpl->_callback.setRedirect( target_r ); } + + void ParseDef::setConsumer( ParseDefConsume * allocatedTarget_r ) + { _pimpl->_callback.setRedirect( allocatedTarget_r ); } + + void ParseDef::setConsumer( ParseDefConsume & target_r ) + { _pimpl->_callback.setRedirect( target_r ); } + + void ParseDef::cancelConsumer() + { _pimpl->_callback.cancelRedirect(); } + + shared_ptr ParseDef::getConsumer() const + { return _pimpl->_callback.getRedirect(); } + + + void ParseDef::take( Reader & reader_r ) + { _pimpl->take( reader_r ); } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, ParseDef::Mode obj ) + { + switch ( obj ) + { +#define X(T) case ParseDef::T: return str << #T + X(OPTIONAL); + X(MANDTAORY); + X(MULTIPLE_OPTIONAL); + X(MULTIPLE_MANDTAORY); +#undef X + } + return str; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ParseDef & obj ) + { + return str << obj._pimpl; + } + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/xml/ParseDef.h b/zypp/parser/xml/ParseDef.h new file mode 100644 index 0000000..113df6d --- /dev/null +++ b/zypp/parser/xml/ParseDef.h @@ -0,0 +1,245 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/ParseDef.h + * +*/ +#ifndef ZYPP_PARSER_XML_PARSEDEF_H +#define ZYPP_PARSER_XML_PARSEDEF_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + class Reader; + struct ParseDefConsume; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDef + // + /** Define a xml node structure to parse. + * + * An xml file like this: + * \code + * + * + * + * mycollection + * + * All the cool stuff... + * 1165270942 + * + * + * + * + * + * + * \endcode + * + * Could be described by: + * \code + * using namespace xml; + * struct SycontentNode : public ParseDef + * { + * SycontentNode( Mode mode_r ) + * : ParseDef( "syscontent", mode_r ) + * { + * (*this)("ident", OPTIONAL) + * ("onsys", OPTIONAL) + * ; + * + * (*this)["ident"] + * ("name", OPTIONAL) + * ("version", OPTIONAL) + * ("description", OPTIONAL) + * ("created", OPTIONAL) + * ; + * + * (*this)["onsys"] + * ("entry", MULTIPLE_OPTIONAL) + * ; + * } + * }; + * \endcode + * + * To parse it using an \ref xml::Reader: + * \code + * xml::Reader reader( input_r ); + * SycontentNode rootNode( xml::ParseDef::MANDTAORY ); + * // Define data consumers here. + * rootNode.take( reader ); + * \endcode + * + * Whithout data consumers this will just parse the file + * but not retrieve any data. You may attach a consumer + * derived from \ref xml::ParseDefConsume to each node: + * + * \code + * // Parse Edition from ver/rel/eopch attributes. + * struct ConsumeEdition : public ParseDefConsume + * { + * ConsumeEdition( Edition & value_r ) + * : _value( & value_r ) + * {} + * + * virtual void start( const Node & node_r ) + * { + * *_value = Edition( node_r.getAttribute("ver").asString(), + * node_r.getAttribute("rel").asString(), + * node_r.getAttribute("epoch").asString() ); + * } + * + * Edition *_value; + * }; + * \endcode + * \see \ref xml::ParseDefConsume + * + * \code + * xml::Reader reader( input_r ); + * SycontentNode rootNode( xml::ParseDef::MANDTAORY ); + * + * // Define data consumers here. + * Edition _edition; + * rootNode["ident"]["version"].setConsumer + * ( new ConsumeEdition( _edition ) ); + * + * rootNode.take( reader ); + * \endcode + * + * That's just one way to collect the data. You could as well + * use a \ref xml::ParseDefConsumeCallback, and redirect the + * \c start call to some arbitrary function or method. + */ + class ParseDef + { + using Traits = ParseDefTraits; + + public: + enum Mode + { + OPTIONAL = Traits::BIT_OPTIONAL | Traits::BIT_ONCE, + MANDTAORY = Traits::BIT_MANDTAORY | Traits::BIT_ONCE, + MULTIPLE_OPTIONAL = Traits::BIT_OPTIONAL | Traits::BIT_MULTIPLE, + MULTIPLE_MANDTAORY = Traits::BIT_MANDTAORY | Traits::BIT_MULTIPLE + }; + + public: + ParseDef( std::string name_r, Mode mode_r ); + ParseDef( std::string name_r, Mode mode_r, shared_ptr target_r ); + + virtual ~ParseDef(); + + public: + const std::string & name() const; + Mode mode() const; + bool isOptional() const; + bool isMandatory() const; + bool singleDef() const; + bool multiDef() const; + unsigned visited() const; + + public: + /** Add subnode definition. + * \note As ParseDef copies share their implementation you can + * not add the same subnode to multiple parents. + * \return *this. + * \throws ParseDefBuildException if a subnode with the same name + * is already defined, or if the subnode is already + * subnode of an other ParseDef. + */ + ParseDef & addNode( ParseDef & subnode_r ); + + ParseDef & addNode( const std::string & name_r, Mode mode_r ) + { ParseDef tmp( name_r, mode_r ); return addNode( tmp ); } + + ParseDef & addNode( const std::string & name_r, Mode mode_r, const shared_ptr & target_r ) + { ParseDef tmp( name_r, mode_r, target_r ); return addNode( tmp ); } + + /** Add subnode definition. + * \see addNode. + */ + ParseDef & operator()( ParseDef & subnode_r ) + { return addNode( subnode_r ); } + + ParseDef & operator()( const std::string & name_r, Mode mode_r ) + { return addNode( name_r, mode_r ); } + + ParseDef & operator()( const std::string & name_r, Mode mode_r, const shared_ptr & target_r ) + { return addNode( name_r, mode_r, target_r ); } + + /** Get subnode by name. + * \throws ParseDefBuildException if no subnode with \a name_r exists. + */ + ParseDef operator[]( const std::string & name_r ); + + public: + /** Set data consumer. */ + void setConsumer( const shared_ptr & target_r ); + /** Set data consumer. + * \note \a allocatedTarget_r is immediately wraped into a + * shared_ptr. + */ + void setConsumer( ParseDefConsume * allocatedTarget_r ); + /** Set data consumer. */ + void setConsumer( ParseDefConsume & target_r ); + /** Unset data consumer. */ + void cancelConsumer(); + + /** Get data consumer. */ + shared_ptr getConsumer() const; + + /** Parse the node. + * This parses the node and all defined subnodes. Unknown + * subnodes are skipped and leave a warning in the logfile. + * \pre Current node must be XML_READER_TYPE_ELEMENT matching + * this ParseDefs name. + * \post All data parsed. At the corresponding end node. + * (XML_READER_TYPE_END_ELEMENT or atill at the same node, + * if it'a an empty element <node />). + * \throws ParseDefException on error. + */ + void take( Reader & reader_r ); + + private: + /** Implementation */ + class Impl; + /** Pointer to implementation (shared!) */ + RW_pointer _pimpl; + + ParseDef( const shared_ptr & pimpl_r ); + friend std::ostream & operator<<( std::ostream & str, const ParseDef & obj ); + friend std::ostream & operator<<( std::ostream & str, const ParseDef::Impl & obj ); + + public: + static bool _debug; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ParseDef ParseDef::Mode stream output. */ + std::ostream & operator<<( std::ostream & str, ParseDef::Mode obj ); + + /** \relates ParseDef Stream output. */ + std::ostream & operator<<( std::ostream & str, const ParseDef & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_PARSEDEF_H diff --git a/zypp/parser/xml/ParseDefConsume.cc b/zypp/parser/xml/ParseDefConsume.cc new file mode 100644 index 0000000..d69ca50 --- /dev/null +++ b/zypp/parser/xml/ParseDefConsume.cc @@ -0,0 +1,176 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/ParseDefConsume.cc + * +*/ +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefConsume + // + /////////////////////////////////////////////////////////////////// + + ParseDefConsume::~ParseDefConsume() + {} + + void ParseDefConsume::start( const Node & _node ) + {} + + void ParseDefConsume::text( const Node & _node ) + {} + + void ParseDefConsume::cdata( const Node & _node ) + {} + + void ParseDefConsume::done( const Node & _node ) + {} + + void ParseDefConsume::startSubnode( const Node & _node ) + {} + + void ParseDefConsume::doneSubnode( const Node & _node ) + {} + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefConsumeRedirect + // + /////////////////////////////////////////////////////////////////// + + ParseDefConsumeRedirect::ParseDefConsumeRedirect() + {} + + ParseDefConsumeRedirect::ParseDefConsumeRedirect( shared_ptr target_r ) + : _target( std::move(target_r) ) + {} + + ParseDefConsumeRedirect::ParseDefConsumeRedirect( ParseDefConsume * allocatedTarget_r ) + : _target( allocatedTarget_r ) + {} + + ParseDefConsumeRedirect::ParseDefConsumeRedirect( ParseDefConsume & target_r ) + : _target( &target_r, NullDeleter() ) + {} + + ParseDefConsumeRedirect::~ParseDefConsumeRedirect() + {} + + void ParseDefConsumeRedirect::setRedirect( shared_ptr target_r ) + { _target = std::move(target_r); } + + void ParseDefConsumeRedirect::setRedirect( ParseDefConsume * allocatedTarget_r ) + { _target.reset( allocatedTarget_r ); } + + void ParseDefConsumeRedirect::setRedirect( ParseDefConsume & target_r ) + { _target.reset( &target_r, NullDeleter() ); } + + void ParseDefConsumeRedirect::cancelRedirect() + { _target.reset(); } + + shared_ptr ParseDefConsumeRedirect::getRedirect() const + { return _target; } + + void ParseDefConsumeRedirect::start( const Node & _node ) + { + if ( _target ) + _target->start( _node ); + } + + void ParseDefConsumeRedirect::text( const Node & _node ) + { + if ( _target ) + _target->text( _node ); + } + + void ParseDefConsumeRedirect::cdata( const Node & _node ) + { + if ( _target ) + _target->cdata( _node ); + } + + void ParseDefConsumeRedirect::done( const Node & _node ) + { + if ( _target ) + _target->done( _node ); + } + + void ParseDefConsumeRedirect::startSubnode( const Node & _node ) + { + if ( _target ) + _target->startSubnode( _node ); + } + + void ParseDefConsumeRedirect::doneSubnode ( const Node & _node ) + { + if ( _target ) + _target->doneSubnode( _node ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefConsumeCallback + // + /////////////////////////////////////////////////////////////////// + + ParseDefConsumeCallback::ParseDefConsumeCallback() + {} + + ParseDefConsumeCallback::~ParseDefConsumeCallback() + {} + + void ParseDefConsumeCallback::start( const Node & node_r ) + { + if ( _start ) + _start( node_r ); + } + + void ParseDefConsumeCallback::text( const Node & node_r ) + { + if ( _text ) + _text( node_r ); + } + + void ParseDefConsumeCallback::cdata( const Node & node_r ) + { + if ( _cdata ) + _cdata( node_r ); + } + + void ParseDefConsumeCallback::done( const Node & node_r ) + { + if ( _done ) + _done( node_r ); + } + + void ParseDefConsumeCallback::startSubnode( const Node & node_r ) + { + if ( _startSubnode ) + _startSubnode( node_r ); + } + + void ParseDefConsumeCallback::doneSubnode( const Node & node_r ) + { + if ( _doneSubnode ) + _doneSubnode( node_r ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/xml/ParseDefConsume.h b/zypp/parser/xml/ParseDefConsume.h new file mode 100644 index 0000000..ff1ae4c --- /dev/null +++ b/zypp/parser/xml/ParseDefConsume.h @@ -0,0 +1,374 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/ParseDefConsume.h + * +*/ +#ifndef ZYPP_PARSER_XML_PARSEDEFCONSUME_H +#define ZYPP_PARSER_XML_PARSEDEFCONSUME_H + +#include +#include +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + class Node; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefConsume + // + /** Base class for ParseDef consumer. + */ + struct ParseDefConsume + { + virtual ~ParseDefConsume(); + + virtual void start( const Node & _node ); + virtual void text ( const Node & _node ); + virtual void cdata( const Node & _node ); + virtual void done ( const Node & _node ); + + virtual void startSubnode( const Node & _node ); + virtual void doneSubnode ( const Node & _node ); + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefConsumeRedirect + // + /** ParseDef consumer redirecting all events to another consumer. + * \note Allocated ParseDefConsume * passed are + * immediately wraped into a shared_ptr. + */ + class ParseDefConsumeRedirect : public ParseDefConsume + { + public: + ParseDefConsumeRedirect(); + ParseDefConsumeRedirect( shared_ptr target_r ); + ParseDefConsumeRedirect( ParseDefConsume * allocatedTarget_r ); + ParseDefConsumeRedirect( ParseDefConsume & target_r ); + + ~ParseDefConsumeRedirect() override; + + public: + void setRedirect( shared_ptr target_r ); + void setRedirect( ParseDefConsume * allocatedTarget_r ); + void setRedirect( ParseDefConsume & target_r ); + void cancelRedirect(); + + shared_ptr getRedirect() const; + + public: + void start( const Node & _node ) override; + void text ( const Node & _node ) override; + void cdata( const Node & _node ) override; + void done ( const Node & _node ) override; + void startSubnode( const Node & _node ) override; + void doneSubnode ( const Node & _node ) override; + + private: + shared_ptr _target; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefConsumeCallback + // + /** ParseDef consumer that invokes callbacks. + */ + class ParseDefConsumeCallback : public ParseDefConsume + { + public: + using Callback = function; + + ParseDefConsumeCallback(); + + ~ParseDefConsumeCallback() override; + + public: + void start( const Node & node_r ) override; + void text( const Node & node_r ) override; + void cdata( const Node & node_r ) override; + void done( const Node & node_r ) override; + void startSubnode( const Node & node_r ) override; + void doneSubnode( const Node & node_r ) override; + + public: + Callback _start; + Callback _text; + Callback _cdata; + Callback _done; + Callback _startSubnode; + Callback _doneSubnode; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /** \ref parseDefAssign exposed details */ + namespace parse_def_assign + { ///////////////////////////////////////////////////////////////// + template struct Assigner; + + using AssignerRef = shared_ptr>; + + /** Common interface to all Assigner types. */ + template <> + struct Assigner + { + virtual ~Assigner() + {} + virtual void assign( const char * text_r ) + {} + }; + + /** Assigner assigns text to types constructible from \c char*. + * \see \ref assigner convenience constructor. + */ + template + struct Assigner : public Assigner + { + Assigner( Tp & value_r ) + : _value( &value_r ) + {} + + void assign( const char * text_r ) override + { *_value = Tp( text_r ); } + + private: + Tp * _value; + }; + + /** \name Assigner specialisation for numeric and boolean values. + * \relates Assigner + */ + //@{ + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strtonum( text_r, *_value ); } + template <> + inline void Assigner::assign( const char * text_r ) { str::strToBoolNodefault( text_r, *_value ); } + //@} + + /** \name \relates Assigner Convenience constructor */ + //@{ + template + inline AssignerRef assigner( Tp & value_r ) + { return AssignerRef( new Assigner( value_r ) ); } + + template + inline AssignerRef assigner( DefaultIntegral & value_r ) + { return AssignerRef( new Assigner( value_r.get() ) ); } + //@} + + + /** \ref ParseDef consumer assigning \ref Node text and attribues values to variables. + * + * This can be used with all types supported by \ref Assigner. + * Basically all types constructible from \c char*, or where a + * specialisation exists (e.g. numeric and bool). + * + * You may also set a void( const Node & ) notification + * callback which is invoked after the node was processed. + * + * \note Use and see \ref xml::parseDefAssign convenience constructor. + * + * \code + * // parsedef for 'value' + * ParseDef( "attr", MANDTAORY, xml::parseDefAssign( data.value ) + * ( "attr", data.attr ) ) + * \endcode + */ + struct Consumer : public ParseDefConsume + { + /** Extend \ref Consumer. */ + void add( const AssignerRef & assigner_r ) + { _text.push_back( assigner_r ); } + + /** Extend \ref Consumer. */ + void add( const std::string & attr_r, const AssignerRef & assigner_r ) + { _attr[attr_r].push_back( assigner_r ); } + + /** Set pre notification callback. */ + void prenotify( function pre_r ) + { _pre = std::move(pre_r); } + + /** Set post notification callback. */ + void postnotify( function post_r ) + { _post = std::move(post_r); } + + void start( const xml::Node & node_r ) override + { + if ( _pre ) + _pre( node_r ); + + if ( ! _attr.empty() ) + for_( it, _attr.begin(), _attr.end() ) + assign( it->second, node_r.getAttribute( it->first.c_str() ).c_str() ); + } + + void text( const xml::Node & node_r ) override + { + if ( ! _text.empty() ) + assign( _text, node_r.value().c_str() ); + } + + void done( const xml::Node & node_r ) override + { + if ( _post ) + _post( node_r ); + } + + private: + void assign( const std::vector & vec_r, const char * value_r ) + { + if ( value_r ) + for_( it, vec_r.begin(), vec_r.end() ) + (*it)->assign( value_r ); + } + + private: + std::unordered_map > _attr; + std::vector _text; + function _pre; + function _post; + }; + + /** Helper class to build a \ref Consumer. + * \relates Consumer + * + * The class constructs the consumer, allows to extend it via + * \ref operator(), and provides a conversion to + * \c shared_ptr, so it can be passed as a + * node consumer to \ref ParseDef. + * + * You may also set a void( const Node & ) notification + * callback which is invoked before/after the node was processed. + * + * \note Use and see \ref xml::parseDefAssign convenience constructor. + */ + struct Builder + { + /** Contruct \ref Consumer. */ + Builder() + : _ptr( new Consumer ) + {} + + /** Contruct \ref Consumer. */ + template + Builder( Tp & value_r ) + : _ptr( new Consumer ) + { operator()( value_r ); } + + /** Contruct \ref Consumer. */ + template + Builder( const std::string & attr_r, Tp & value_r ) + : _ptr( new Consumer ) + { operator()( attr_r, value_r ); } + + /** Extend \ref Consumer. */ + template + Builder & operator()( Tp & value_r ) + { _ptr->add( assigner( value_r ) ); return *this; } + + /** Extend \ref Consumer. */ + template + Builder & operator()( const std::string & attr_r, Tp & value_r ) + { _ptr->add( attr_r, assigner( value_r ) ); return *this; } + + /** Set pre notification callback. */ + Builder & operator<<( function done_r ) + { _ptr->prenotify( std::move(done_r) ); return *this; } + + /** Set post notification callback. */ + Builder & operator>>( function done_r ) + { _ptr->postnotify( std::move(done_r) ); return *this; } + + /** Type conversion so this can be passed as node consumer to \ref ParseDef. */ + operator shared_ptr () const + { return _ptr; } + + private: + shared_ptr _ptr; + }; + ///////////////////////////////////////////////////////////////// + } // namespace parse_def_assign + /////////////////////////////////////////////////////////////////// + + /** \name \ref ParseDef consumer assigning \ref Node text and attribues values to variables. + * \relates parse_def_assign::Consumer + * \relates parse_def_assign::Builder + * + * This function allows convenient contruction of a \ref parse_def_assign::Consumer + * to be passed as \ref Node conssumer to \ref ParseDef. Simply list each attribute's + * name together with the variable its value should be assigned to. If the attribute + * name is omitted, the node's text value gets assigned. + * + * Target variables can be of any type tsupported by \ref Assigner. + * Basically all types constructible from \c char*, or where a + * specialisation exists (e.g. numeric and bool). + * + * \code + * void setupDone( const xml::Node & _node ) + * { ... } + * + * // parsedef for 'value' + * ParseDef( "attr", MANDTAORY, + * xml::parseDefAssign( data.value ) + * ( "attr", data.attr ) + * >> &setupDone ); + * \endcode + * + * \see \ref xml::rnParse for more example. + */ + //@{ + inline parse_def_assign::Builder parseDefAssign() + { return parse_def_assign::Builder(); } + + template + inline parse_def_assign::Builder parseDefAssign( Tp & value_r ) + { return parse_def_assign::Builder( value_r ); } + + template + inline parse_def_assign::Builder parseDefAssign( const std::string & attr_r, Tp & value_r ) + { return parse_def_assign::Builder( attr_r, value_r ); } + //@} + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_PARSEDEFCONSUME_H diff --git a/zypp/parser/xml/ParseDefException.cc b/zypp/parser/xml/ParseDefException.cc new file mode 100644 index 0000000..c2604c8 --- /dev/null +++ b/zypp/parser/xml/ParseDefException.cc @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/ParseDefException.cc + * +*/ +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDefException::ParseDefException + // METHOD TYPE : Constructor + // + ParseDefException::ParseDefException( const std::string & what_r ) + : Exception( what_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDefBuildException::ParseDefBuildException + // METHOD TYPE : Constructor + // + ParseDefBuildException::ParseDefBuildException( const std::string & what_r ) + : ParseDefException( what_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDefValidateException::ParseDefValidateException + // METHOD TYPE : Constructor + // + ParseDefValidateException::ParseDefValidateException( const std::string & what_r ) + : ParseDefException( what_r ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ParseDefDataException::ParseDefDataException + // METHOD TYPE : Constructor + // + ParseDefDataException::ParseDefDataException( const std::string & what_r ) + : ParseDefException( what_r ) + {} + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/xml/ParseDefException.h b/zypp/parser/xml/ParseDefException.h new file mode 100644 index 0000000..671c79f --- /dev/null +++ b/zypp/parser/xml/ParseDefException.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/ParseDefException.h + * +*/ +#ifndef ZYPP_PARSER_XML_PARSEDEFEXCEPTION_H +#define ZYPP_PARSER_XML_PARSEDEFEXCEPTION_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefException + // + /** Common base class for \ref ParseDef exceptions. */ + struct ParseDefException : public Exception + { + ParseDefException( const std::string & what_r ); + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefBuildException + // + /** Exceptions when building a ParseDef tree. */ + struct ParseDefBuildException : public ParseDefException + { + ParseDefBuildException( const std::string & what_r ); + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefValidateException + // + /** Parse exceptions related to the documents node structure. */ + struct ParseDefValidateException : public ParseDefException + { + ParseDefValidateException( const std::string & what_r ); + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefDataException + // + /** Parse exceptions related to the nodes content. */ + struct ParseDefDataException : public ParseDefException + { + ParseDefDataException( const std::string & what_r ); + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_PARSEDEFEXCEPTION_H diff --git a/zypp/parser/xml/ParseDefTraits.h b/zypp/parser/xml/ParseDefTraits.h new file mode 100644 index 0000000..4027957 --- /dev/null +++ b/zypp/parser/xml/ParseDefTraits.h @@ -0,0 +1,56 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/ParseDefTraits.h + * +*/ +#ifndef ZYPP_PARSER_XML_PARSEDEFTRAITS_H +#define ZYPP_PARSER_XML_PARSEDEFTRAITS_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ParseDefTraits + // + /** */ + struct ParseDefTraits + { + using ModeBitsType = unsigned char; + using ModeBits = bit::BitField; + using TypeBits = bit::Range; + using VisitBits = bit::Range; + + enum TypeValue + { + BIT_OPTIONAL = bit::RangeValue::value, + BIT_MANDTAORY = bit::RangeValue::value + }; + + enum VisitValue + { + BIT_ONCE = bit::RangeValue::value, + BIT_MULTIPLE = bit::RangeValue::value + }; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_PARSEDEFTRAITS_H diff --git a/zypp/parser/xml/Reader.cc b/zypp/parser/xml/Reader.cc new file mode 100644 index 0000000..bf10251 --- /dev/null +++ b/zypp/parser/xml/Reader.cc @@ -0,0 +1,237 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/Reader.cc + * +*/ +#include +#include + +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + int ioread( void * context_r, char * buffer_r, int bufferLen_r ) + { + if ( context_r && buffer_r ) + { + return reinterpret_cast(context_r) + ->stream().read( buffer_r, bufferLen_r ).gcount(); + } + INT << "XML parser error: null pointer check failed " << context_r << ' ' << (void *)buffer_r << endl; + return -1; + } + + int ioclose( void * /*context_r*/ ) + { return 0; } + + + std::list structuredErrors; +#if LIBXML_VERSION >= 21200 + void structuredErrorFunc( void * userData, const xmlError * error ) +#else + void structuredErrorFunc( void * userData, xmlError * error ) +#endif + { + if ( error ) + { + // error->message is NL terminated + std::string err( str::form( "%s[%d] %s", Pathname::basename(error->file).c_str(), error->line, + str::stripSuffix( error->message, "\n" ).c_str() ) ); + structuredErrors.push_back( err ); + WAR << err << endl; + } + } + + struct ParseException : public Exception + { + ParseException() + : Exception( "Parse error: " + ( structuredErrors.empty() ? std::string("unknown error"): structuredErrors.back() ) ) + { + for_( it, structuredErrors.begin(), --structuredErrors.end() ) + addHistory( *it ); + } + }; + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::Reader + // METHOD TYPE : Constructor + // + Reader::Reader( const InputStream & stream_r, + const Validate & validate_r ) + : _stream( stream_r ) + , _reader( xmlReaderForIO( ioread, ioclose, &_stream, + stream_r.path().asString().c_str(), "utf-8", XML_PARSE_PEDANTIC ) ) + , _node( _reader ) + { + MIL << "Start Parsing " << _stream << endl; + if ( ! _reader || ! stream_r.stream().good() ) + ZYPP_THROW( Exception( "Bad input stream" ) ); + // set error handler + // TODO: Fix using a global lastStructuredError string is not reentrant. + structuredErrors.clear(); + xmlTextReaderSetStructuredErrorHandler( _reader, structuredErrorFunc, NULL ); + // TODO: set validation + + // advance to 1st node + nextNode(); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::~Reader + // METHOD TYPE : Destructor + // + Reader::~Reader() + { + if ( _reader ) + { + xmlFreeTextReader( _reader ); + } + MIL << "Done Parsing " << _stream << endl; + } + + XmlString Reader::nodeText() + { + if ( ! _node.isEmptyElement() ) + { + if ( nextNode() ) + { + if ( _node.nodeType() == XML_READER_TYPE_TEXT ) + { + return _node.value(); + } + } + } + return XmlString(); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::nextNode + // METHOD TYPE : bool + // + bool Reader::nextNode() + { + int ret = xmlTextReaderRead( _reader ); + if ( ret == 1 ) + { + return true; + } + xmlTextReaderClose( _reader ); + if ( ret != 0 ) + { + ZYPP_THROW( ParseException() ); + } + return false; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::nextNodeAttribute + // METHOD TYPE : bool + // + bool Reader::nextNodeAttribute() + { + int ret = xmlTextReaderMoveToNextAttribute( _reader ); + if ( ret == 1 ) + { + return true; + } + if ( ret != 0 ) + { + ZYPP_THROW( ParseException() ); + } + return false; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::close + // METHOD TYPE : void + // + void Reader::close() + { + if ( _reader ) + { + xmlTextReaderClose( _reader ); + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::seekToNode + // METHOD TYPE : bool + // + bool Reader::seekToNode( int depth_r, const std::string & name_r ) + { + do + { + if ( _node.depth() == depth_r + && _node.name() == name_r + && _node.nodeType() == XML_READER_TYPE_ELEMENT ) + { + break; + } + } while( nextNode() ); + + return ! atEnd(); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Reader::seekToEndNode + // METHOD TYPE : bool + // + bool Reader::seekToEndNode( int depth_r, const std::string & name_r ) + { + // Empty element has no separate end node: + do + { + if ( _node.depth() == depth_r + && _node.name() == name_r + && ( _node.nodeType() == XML_READER_TYPE_END_ELEMENT + || ( _node.nodeType() == XML_READER_TYPE_ELEMENT + && _node.isEmptyElement() ) ) ) + { + break; + } + } while( nextNode() ); + + return ! atEnd(); + } + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/xml/Reader.h b/zypp/parser/xml/Reader.h new file mode 100644 index 0000000..ee40a2a --- /dev/null +++ b/zypp/parser/xml/Reader.h @@ -0,0 +1,203 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/Reader.h + * +*/ +#ifndef ZYPP_PARSER_XML_READER_H +#define ZYPP_PARSER_XML_READER_H + +#include + +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Validate + // + /** xmlTextReader document validation. + * \todo Implement RelaxNG and W3C XSD + **/ + struct Validate + { + static Validate none() + { return Validate(); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Reader + // + /** xmlTextReader based interface to iterate xml streams. + * + * \code + * // Consume a node. + * bool consumeNode( xml::Reader & reader_r ) + * { + * DBG << *reader_r << endl; + * return true; + * } + * + * // Consume all nodes (omitting attributes) + * void example() + * { + * try + * { + * xml::Reader reader( "/Local/repodata/repomd.xml" ); + * reader.foreachNode( consumeNode ); + * } + * catch ( const Exception & ) + * { ; } // parse error + * } + * \endcode + * + * \code + * // Consume a node. + * bool consumeNodeAndAttribute( xml::Reader & reader_r ) + * { + * consumeNode( reader_r ); + * return reader_r.foreachNodeAttribute( consumeNode ); + * } + * + * // Consume all nodes and their attributes. + * void example() + * { + * Pathname repodata( "/Local/repodata/repomd.xml" ); + * try + * { + * xml::Reader reader( "/Local/repodata/repomd.xml" ); + * reader.foreachNode( consumeNodeAndAttribute ); + * // or: + * // reader.foreachNodeOrAttribute( consumeNode ) + * } + * catch ( const Exception & ) + * { ; } // parse error + * } + * \endcode + **/ + class ZYPP_API Reader : private zypp::base::NonCopyable + { + public: + /** Ctor. Setup xmlTextReader and advance to the 1st Node. */ + Reader( const InputStream & stream_r, + const Validate & validate_r = Validate::none() ); + + /** Dtor. */ + ~Reader(); + + public: + + /** + * If the current node is not empty, advances the reader to the next + * node, and returns the value + * + * \note if the node has a xml subtree you will probably jump to that node + * and get a empty text value back. Use it only if you are sure the node + * has no XML subtree. + */ + XmlString nodeText(); + + /** */ + bool nextNode(); + + /** */ + bool nextNodeAttribute(); + + /** */ + bool nextNodeOrAttribute() + { return( nextNodeAttribute() || nextNode() ); } + + /** */ + bool atEnd() const + { return( _node.readState() == XML_TEXTREADER_MODE_CLOSED ); } + + /** */ + const Node & operator*() const + { return _node; } + + /** */ + const Node * operator->() const + { return &_node; } + + public: + /** */ + using ProcessNode = function; + + /** */ + bool foreachNode( const ProcessNode& fnc_r ) + { + if ( _node.isAttribute() ) + nextNode(); + for ( ; ! atEnd(); nextNode() ) + { + if ( ! fnc_r( *this ) ) + return false; + } + return true; + } + + /** */ + bool foreachNodeAttribute( const ProcessNode& fnc_r ) + { + if ( _node.isAttribute() && ! fnc_r( *this ) ) + return false; + while( nextNodeAttribute() ) + { + if ( ! fnc_r( *this ) ) + return false; + } + return true; + } + + /** */ + bool foreachNodeOrAttribute( const ProcessNode& fnc_r ) + { + for ( ; ! atEnd(); nextNodeOrAttribute() ) + { + if ( ! fnc_r( *this ) ) + return false; + } + return true; + } + + public: + /** */ + bool seekToNode( int depth_r, const std::string & name_r ); + + /** */ + bool seekToEndNode( int depth_r, const std::string & name_r ); + + private: + void close(); + + private: + InputStream _stream; + xmlTextReaderPtr _reader; + Node _node; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_READER_H diff --git a/zypp/parser/xml/XmlEscape.h b/zypp/parser/xml/XmlEscape.h new file mode 100644 index 0000000..76079ef --- /dev/null +++ b/zypp/parser/xml/XmlEscape.h @@ -0,0 +1 @@ +#include diff --git a/zypp/parser/xml/XmlString.cc b/zypp/parser/xml/XmlString.cc new file mode 100644 index 0000000..fe0783a --- /dev/null +++ b/zypp/parser/xml/XmlString.cc @@ -0,0 +1,58 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/XmlString.cc + * +*/ + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : XmlString::XmlString + // METHOD TYPE : Constructor + // + XmlString::XmlString( const xmlChar *const xmlstr_r, + OnDelete ondelete_r ) + { + if ( xmlstr_r ) + { + if ( ondelete_r == FREE ) + _xmlstr.reset( xmlstr_r, Deleter() ); + else + _xmlstr.reset( xmlstr_r, NullDeleter() ); + } + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const XmlString & obj ) + { + if ( obj ) + return str << obj.c_str(); + return str << "NULL"; + } + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/xml/XmlString.h b/zypp/parser/xml/XmlString.h new file mode 100644 index 0000000..7b8390d --- /dev/null +++ b/zypp/parser/xml/XmlString.h @@ -0,0 +1,118 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/XmlString.h + * +*/ +#ifndef ZYPP_PARSER_XML_XMLSTRING_H +#define ZYPP_PARSER_XML_XMLSTRING_H + +#include +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : XmlString + // + /** xmlChar * wrapper. + * + * Common handling of xmlChar * that do or do not need to + * be freed. If the wraped xmlChar * needs to be freed by + * calling \c xmlFree, pass \c FREE as 2nd argument to the ctor. + **/ + class ZYPP_API XmlString + { + /** shared_ptr custom deleter calling \c xmlFree. */ + struct Deleter + { + void operator()( const xmlChar * xmlstr_r ) const + { xmlFree( (void*)(xmlstr_r) ); } + }; + + public: + + /** Dtor policy. */ + enum OnDelete { NOFREE, FREE }; + + /** Ctor from xmlChar. + * Pass \c FREE as 2nd arg if \c xmlFree needs to be called on destruction. + */ + XmlString( const xmlChar *const xmlstr_r = NULL, + OnDelete ondelete_r = NOFREE ); + + /** Access the xmlChar *. */ + const xmlChar * get() const + { + if ( ! _xmlstr ) + return NULL; + return &(*_xmlstr); + } + + /** Implicit conversion to xmlChar *. */ + operator const xmlChar * () const + { return get(); } + + /** Explicit conversion to const char *. */ + const char * c_str() const + { return reinterpret_cast(get()); } + + /** Explicit conversion to std::string. */ + std::string asString() const + { + if ( ! _xmlstr ) + return std::string(); + return c_str(); + } + + bool operator==( const std::string & rhs ) const + { return( rhs == c_str() ); } + + bool operator!=( const std::string & rhs ) const + { return( rhs != c_str() ); } + + bool operator==( const char *const rhs ) const + { return( asString() == rhs ); } + + bool operator!=( const char *const rhs ) const + { return( asString() != rhs ); } + + bool operator==( const XmlString & rhs ) const + { return( asString() == rhs.c_str() ); } + + bool operator!=( const XmlString & rhs ) const + { return( asString() != rhs.c_str() ); } + + private: + /** Wraps the xmlChar *. + * The appropriate custom deleter is set by the ctor. */ + shared_ptr _xmlstr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates XmlString Stream output. */ + std::ostream & operator<<( std::ostream & str, const XmlString & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_XMLSTRING_H diff --git a/zypp/parser/xml/libxmlfwd.cc b/zypp/parser/xml/libxmlfwd.cc new file mode 100644 index 0000000..2e40e2c --- /dev/null +++ b/zypp/parser/xml/libxmlfwd.cc @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/libxmlfwd.cc + * +*/ + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ReadState & obj ) + { + switch ( obj ) + { +#define X(T) case XML_TEXTREADER_MODE_##T: return str << #T + X(INITIAL); + X(INTERACTIVE); + X(ERROR); + X(EOF); + X(CLOSED); + X(READING); +#undef X + } + return str << "UNKNOWN_READ_STATE"; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const NodeType & obj ) + { + switch ( obj ) + { +#define X(T) case XML_READER_TYPE_##T: return str << #T + X(NONE); + X(ELEMENT); + X(ATTRIBUTE); + X(TEXT); + X(CDATA); + X(ENTITY_REFERENCE); + X(ENTITY); + X(PROCESSING_INSTRUCTION); + X(COMMENT); + X(DOCUMENT); + X(DOCUMENT_TYPE); + X(DOCUMENT_FRAGMENT); + X(NOTATION); + X(WHITESPACE); + X(SIGNIFICANT_WHITESPACE); + X(END_ELEMENT); + X(END_ENTITY); + X(XML_DECLARATION); +#undef X + } + return str << "UNKNOWN_NODE_TYPE"; + } + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/parser/xml/libxmlfwd.h b/zypp/parser/xml/libxmlfwd.h new file mode 100644 index 0000000..0cac2ac --- /dev/null +++ b/zypp/parser/xml/libxmlfwd.h @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/xml/libxmlfwd.h + * +*/ +#ifndef ZYPP_PARSER_XML_LIBXMLFWD_H +#define ZYPP_PARSER_XML_LIBXMLFWD_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace xml + { ///////////////////////////////////////////////////////////////// + + using ReadState = xmlTextReaderMode; + /** \relates ReadState Stream output. */ + std::ostream & operator<<( std::ostream & str, const ReadState & obj ); + + using NodeType = xmlReaderTypes; + /** \relates NodeType Stream output. */ + std::ostream & operator<<( std::ostream & str, const NodeType & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace xml + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_XML_LIBXMLFWD_H diff --git a/zypp/parser/yum/RepomdFileReader.cc b/zypp/parser/yum/RepomdFileReader.cc new file mode 100644 index 0000000..753bed3 --- /dev/null +++ b/zypp/parser/yum/RepomdFileReader.cc @@ -0,0 +1,248 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/yum/RepomdFileReader.cc + * Implementation of repomd.xml file reader. + */ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "parser::yum" + +using std::endl; +using namespace zypp::xml; + +namespace zypp +{ + namespace parser + { + namespace yum + { + + + /////////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepomdFileReader::Impl + // + class RepomdFileReader::Impl : private base::NonCopyable + { + public: + /** Ctro taking a ProcessResource callback */ + Impl(const Pathname &repomd_file, ProcessResource &&callback ) + : _callback( std::move(callback) ) + { + Reader reader( repomd_file ); + MIL << "Reading " << repomd_file << endl; + reader.foreachNode( bind( &RepomdFileReader::Impl::consumeNode, this, _1 ) ); + } + + /** + * Callback provided to the XML parser. + */ + bool consumeNode( Reader & reader_r ); + + + /** repo keywords parsed on the fly */ + const std::set & keywords() const + { return _keywords; } + + private: + /** Retrieve a checksum node. */ + CheckSum getChecksum( Reader & reader_r ) + { return CheckSum( reader_r->getAttribute("type").asString(), reader_r.nodeText().asString() ); } + + /** Retrieve a size node. */ + ByteCount getSize( Reader & reader_r ) + { return ByteCount( str::strtonum( reader_r.nodeText().asString() ) ); } + + + private: + /** Function for processing collected data. Passed-in through constructor. */ + ProcessResource _callback; + + /** The resource type string. */ + std::string _typeStr; + + /** Location of metadata file. */ + OnMediaLocation _location; + + std::set _keywords; ///< repo keywords parsed on the fly + }; + /////////////////////////////////////////////////////////////////////// + + /* + * xpath and multiplicity of processed nodes are included in the code + * for convenience: + * + * // xpath: (?|*|+) + * + * if multiplicity is ommited, then the node has multiplicity 'one'. + */ + + // -------------------------------------------------------------------------- + + bool RepomdFileReader::Impl::consumeNode( Reader & reader_r ) + { + if ( reader_r->nodeType() == XML_READER_TYPE_ELEMENT ) + { + // xpath: /repomd + if ( reader_r->name() == "repomd" ) + { + return true; + } + + // xpath: /repomd/data (+) + if ( reader_r->name() == "data" ) + { + _typeStr = reader_r->getAttribute("type").asString(); + return true; + } + + // xpath: /repomd/location + if ( reader_r->name() == "location" ) + { + _location.setLocation( reader_r->getAttribute("href").asString(), 1 ); + // ignoring attribute xml:base + return true; + } + + // xpath: /repomd/checksum + if ( reader_r->name() == "checksum" ) + { + _location.setChecksum( getChecksum( reader_r ) ); + return true; + } + + // xpath: /repomd/header-checksum + if ( reader_r->name() == "header-checksum" ) + { + _location.setHeaderChecksum( getChecksum( reader_r ) ); + return true; + } + + // xpath: /repomd/timestamp + if ( reader_r->name() == "timestamp" ) + { + // ignore it + return true; + } + + // xpath: /repomd/size + if ( reader_r->name() == "size" ) + { + _location.setDownloadSize( getSize( reader_r ) ); + return true; + } + + // xpath: /repomd/header-size + if ( reader_r->name() == "header-size" ) + { + _location.setHeaderSize( getSize( reader_r ) ); + return true; + } + + // xpath: /tags/content + if ( reader_r->name() == "content" ) + { + const auto & tag = reader_r.nodeText(); + if ( tag.c_str() && *tag.c_str() ) + _keywords.insert( tag.asString() ); // remember keyword + return true; + } + } + + else if ( reader_r->nodeType() == XML_READER_TYPE_END_ELEMENT ) + { + // xpath: /repomd/data + if ( reader_r->name() == "data" ) + { + if (_callback) { + _callback( std::move(_location), _typeStr ); + _location = OnMediaLocation(); + _typeStr.clear(); + } + return true; + } + } + + return true; + } + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepomdFileReader + // + /////////////////////////////////////////////////////////////////// + + RepomdFileReader::RepomdFileReader( const Pathname & repomd_file, ProcessResource callback ) + : _pimpl( new Impl(repomd_file, std::move(callback)) ) + {} + + RepomdFileReader::RepomdFileReader( const Pathname & repomd_file ) + : _pimpl( new Impl(repomd_file, ProcessResource()) ) + {} + + RepomdFileReader::~RepomdFileReader() + {} + + const std::set & RepomdFileReader::keywords() const + { return _pimpl->keywords(); } + + std::vector> RepomdFileReader::keyhints() const + { + std::vector> ret; + for ( const std::string & tag : keywords() ) { + // Get keyhints on the fly: + // gpg-pubkey-39db7c82-5847eb1f.asc?fpr=22C07BA534178CD02EFE22AAB88B2FD43DBDC284 + // Fingerprint is explicitly mentioned or id/fpr can be derived from the filename + if ( tag.compare( 0,10,"gpg-pubkey" ) != 0 ) + continue; + + static const str::regex rx( "^(gpg-pubkey([^?]*))(\\?fpr=([[:xdigit:]]{8,}))?$" ); + str::smatch what; + if ( str::regex_match( tag.c_str(), what, rx ) ) { + std::string keyfile { what[1] }; + std::string keyident; + if ( what.size(4) != std::string::npos ) { // with fpr= + keyident = what[4]; + } + else { + static const str::regex rx( /*gpg-pubkey*/"^-([[:xdigit:]]{8,})" ); + if ( str::regex_match( what[2], what, rx ) ) { + keyident = what[1]; + } + else { + DBG << "Tag " << tag << " does not contain a keyident. ignore it." << endl; + continue; + } + } + ret.push_back( std::make_pair( std::move(keyfile), std::move(keyident) ) ); + } + } + return ret; + } + + } // ns yum + } // ns parser +} // ns zypp + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/parser/yum/RepomdFileReader.h b/zypp/parser/yum/RepomdFileReader.h new file mode 100644 index 0000000..65dfd2e --- /dev/null +++ b/zypp/parser/yum/RepomdFileReader.h @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/yum/RepomdFileReader.h + * Interface of repomd.xml file reader. + */ +#ifndef zypp_source_yum_RepomdFileReader_H +#define zypp_source_yum_RepomdFileReader_H + +#include + +#include +#include +#include + +#include + +namespace zypp +{ + namespace parser + { + namespace yum + { + + + /** + * Reads through a repomd.xml file and collects type, location, checksum and + * other data about metadata files to be processed. + * + * After each file entry is read, an \ref OnMediaLocation and the resource type + * string are prepared and passed to the \ref _callback. + */ + class RepomdFileReader : private base::NonCopyable + { + public: + /** Callback taking \ref OnMediaLocation and the resource type string */ + using ProcessResource = function; + + /** + * CTOR. Creates also \ref xml::Reader and starts reading. + * + * \param repomd_file is the repomd.xml file you want to read + * \param callback is a function. + * + * \see RepomdFileReader::ProcessResource + */ + RepomdFileReader(const Pathname & repomd_file, ProcessResource callback ); + /** \overload Quick parsing keywords and keyhints. */ + RepomdFileReader( const Pathname & repomd_file ); + + /** DTOR */ + ~RepomdFileReader(); + + public: + /** repo keywords parsed on the fly */ + const std::set & keywords() const; + + /** gpg key hits shipped in keywords (bsc#1184326) */ + std::vector> keyhints() const; + + private: + class Impl; + RW_pointer > _pimpl; + }; + + + } // namespace yum + } // namespace parser +} // namespace zypp + +#endif // zypp_source_yum_RepomdFileReader_H diff --git a/zypp/parser/yum/schema/common-inc.rnc b/zypp/parser/yum/schema/common-inc.rnc new file mode 100644 index 0000000..6ac8022 --- /dev/null +++ b/zypp/parser/yum/schema/common-inc.rnc @@ -0,0 +1,76 @@ +# private is not an XML namespace, just a holder for reusable +# attribute/element sets + +private.positive = xsd:positiveInteger { pattern="[1-9][0-9]*" } + +private.nonnegative = "0" | private.positive + +# Unix timestamp (seconds since epoch) +# For our purposes, this is always positive +private.unixts = private.positive + +private.size = private.nonnegative + +private.checksum = + (attribute type { "md5" }, xsd:string { length="32" pattern="[0-9a-f]*" }) | + (attribute type { "sha" }, xsd:string { length="40" pattern="[0-9a-f]*" }) | + (attribute type { "sha256" }, xsd:string { length="64" pattern="[0-9a-f]*" }) | + (attribute type { "sha" }, xsd:string { length="32" pattern="[0-9a-f]*" }) +# The last option is totally broken, but is in the wild!!! :( + +private.evr = + attribute epoch { private.nonnegative }?, + attribute ver { text }, + attribute rel { text }? + +private.localizedtext = attribute lang { "en" | "de" }, text + +private.archenum = "noarch" + | "i386" + | "i486" + | "i586" + | "i686" + | "athlon" + | "x86_64" + | "pentium3" + | "pentium4" + | "s390" + | "s390x" + | "ppc" + | "ppc64" + | "ia64" + | "alphaev67" + | "alphaev6" + | "alphapca56" + | "alphaev56" + | "alphaev5" + | "alpha" + | "sparc64v" + | "sparcv9v" + | "sparc64" + | "sparcv9" + | "sparcv8" + | "sparc" + | "aarch64" + | "armv8hl" + | "armv8l" + | "armv7tnhl" + | "armv7thl" + | "armv7nhl" + | "armv7hl" + | "armv7l" + | "armv6l" + | "armv5tejl" + | "armv5tel" + | "armv5l" + | "armv4tl" + | "armv4l" + | "armv3l" + | "riscv64" + | "loong64" + | "sh3" + | "sh4" + | "sh4a" + | "m68k" + | "src" + diff --git a/zypp/parser/yum/schema/common-inc.rng b/zypp/parser/yum/schema/common-inc.rng new file mode 100644 index 0000000..adf65e9 --- /dev/null +++ b/zypp/parser/yum/schema/common-inc.rng @@ -0,0 +1,141 @@ + + + + + + [1-9][0-9]* + + + + + 0 + + + + + + + + + + + + + + + md5 + + + 32 + [0-9a-f]* + + + + + sha + + + 40 + [0-9a-f]* + + + + + sha256 + + + 64 + [0-9a-f]* + + + + + sha + + + 32 + [0-9a-f]* + + + + + + + + + + + + + + + + + + + + en + de + + + + + + + noarch + i386 + i486 + i586 + i686 + athlon + x86_64 + pentium3 + pentium4 + s390 + s390x + ppc + ppc64 + ia64 + alphaev67 + alphaev6 + alphapca56 + alphaev56 + alphaev5 + alpha + sparc64v + sparcv9v + sparc64 + sparcv9 + sparcv8 + sparc + aarch64 + armv8hl + armv8l + armv7tnhl + armv7thl + armv7nhl + armv7hl + armv7l + armv6l + armv5tejl + armv5tel + armv5l + armv4tl + armv4l + armv3l + riscv64 + loong64 + sh3 + sh4 + sh4a + m68k + src + + + diff --git a/zypp/parser/yum/schema/deltainfo.rnc b/zypp/parser/yum/schema/deltainfo.rnc new file mode 100644 index 0000000..71c2c40 --- /dev/null +++ b/zypp/parser/yum/schema/deltainfo.rnc @@ -0,0 +1,21 @@ +include "common-inc.rnc" + +start = element deltainfo { + element newpackage { + attribute name { text }, + attribute arch { private.archenum }, + attribute version { text }, + attribute release { text }, + element delta { + attribute oldepoch { private.nonnegative }, + # two different formats, with different attribute names with same data + ((attribute oldversion { text }, attribute oldrelease { text }) | + (attribute ver { text }, attribute rel { text })), + element filename { text }, + element sequence { text }, + element size { private.size }, + element checksum { private.checksum } + }+ + }* +} + diff --git a/zypp/parser/yum/schema/deltainfo.rng b/zypp/parser/yum/schema/deltainfo.rng new file mode 100644 index 0000000..5fb5946 --- /dev/null +++ b/zypp/parser/yum/schema/deltainfo.rng @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/filelists.rnc b/zypp/parser/yum/schema/filelists.rnc new file mode 100644 index 0000000..da1802b --- /dev/null +++ b/zypp/parser/yum/schema/filelists.rnc @@ -0,0 +1,17 @@ +default namespace = "http://linux.duke.edu/metadata/filelists" + +include "common-inc.rnc" + +start = element filelists { + attribute packages { xsd:nonNegativeInteger }, + element package { + attribute pkgid { text }, + attribute name { text }, + attribute arch { private.archenum }, + element version { private.evr }, + element file { + attribute type { "dir" | "ghost" }?, + text + }* + }* +} diff --git a/zypp/parser/yum/schema/filelists.rng b/zypp/parser/yum/schema/filelists.rng new file mode 100644 index 0000000..48afa75 --- /dev/null +++ b/zypp/parser/yum/schema/filelists.rng @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + dir + ghost + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/other.rnc b/zypp/parser/yum/schema/other.rnc new file mode 100644 index 0000000..3aafe3a --- /dev/null +++ b/zypp/parser/yum/schema/other.rnc @@ -0,0 +1,18 @@ +default namespace = "http://linux.duke.edu/metadata/other" + +include "common-inc.rnc" + +start = element otherdata { + attribute packages { private.nonnegative }, + element package { + attribute pkgid { text }, + attribute name { text }, + attribute arch { private.archenum }, + element version { private.evr }, + element changelog { + attribute author { text }, + attribute date { private.unixts }, + text + }* + }* +} diff --git a/zypp/parser/yum/schema/other.rng b/zypp/parser/yum/schema/other.rng new file mode 100644 index 0000000..45302f0 --- /dev/null +++ b/zypp/parser/yum/schema/other.rng @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/patch.rnc b/zypp/parser/yum/schema/patch.rnc new file mode 100644 index 0000000..46cc255 --- /dev/null +++ b/zypp/parser/yum/schema/patch.rnc @@ -0,0 +1,146 @@ +default namespace = "http://novell.com/package/metadata/suse/patch" +namespace yum = "http://linux.duke.edu/metadata/common" +namespace suse = "http://novell.com/package/metadata/suse/common" + +include "rpm-inc.rnc" + +yum.name = element yum:name { text } + +yum.arch = element yum:arch { private.archenum } + +yum.version = element yum:version { + private.evr +} + +suse.freshens = element suse:freshens { + element suse:entry { + attribute kind { "package" }, + attribute name { text } + }+ +} + +group.deps = rpm.requires?, rpm.obsoletes?, rpm.provides?, rpm.recommends?, rpm.supplements?, rpm.conflicts?, suse.freshens? + +patch.location = element location { + attribute href { xsd:anyURI } +} + +patch.checksum = element checksum { + private.checksum +} + +patch.time = element time { + attribute file { private.unixts }, + attribute build { private.unixts } +} + +patch.size = element size { + attribute package { private.size }, + attribute archive { private.size } +} + +start = element patch { + attribute patchid { text }, + attribute timestamp { private.unixts }, + attribute engine { "1.0" }, + yum.name, + element summary { + private.localizedtext + }+, + element description { + private.localizedtext + }+, + element license-to-confirm { + private.localizedtext + }?, + yum.version, + group.deps, + element reboot-needed { empty }?, + element package-manager { empty }?, + element category { "security" | "recommended" | "optional" }, + # This is in two places (with slightly different definiton) + # because that is what is seen in the wild + element license-to-confirm { + text + }?, + element atoms { + element message { + yum.name, + yum.version, + element text { + private.localizedtext + }, + group.deps + }?, + element yum:package { + attribute type { "rpm" }, + yum.name, + yum.arch, + yum.version, + element yum:checksum { + attribute pkgid { "YES" }, + private.checksum + }, + element yum:time { + attribute file { private.unixts }, + attribute build { private.unixts } + }, + element yum:size { + attribute package { private.size }, + attribute installed { private.size }, + attribute archive { xsd:nonNegativeInteger } + }, + element yum:location { + attribute href { xsd:anyURI } + }, + element yum:format { + group.deps + }, + element pkgfiles { + element patchrpm { + patch.location, + patch.checksum, + patch.time, + patch.size, + element base-version { + private.evr + }+ + }?, + element deltarpm { + patch.location, + patch.checksum, + patch.time, + patch.size, + element base-version { + private.evr, + attribute md5sum { xsd:string { length="32" pattern="[0-9a-f]*" } }, + attribute buildtime { private.unixts }, + attribute sequence_info { text } + } + }* + } + }*, + element message { + yum.name, + yum.version, + element text { + private.localizedtext + }, + group.deps + }?, + element script { + yum.name, + yum.version, + # Script can either be remote (do-location and do-checksum) + # or inline (do), but not both + ((element do-location { + attribute href { xsd:anyURI } + }, + element do-checksum { + private.checksum + }) | element do { text }), + group.deps + }? + }? +} + diff --git a/zypp/parser/yum/schema/patch.rng b/zypp/parser/yum/schema/patch.rng new file mode 100644 index 0000000..8c54b01 --- /dev/null +++ b/zypp/parser/yum/schema/patch.rng @@ -0,0 +1,270 @@ + + + + + + + + + + + + + + + + + + + + + + + + package + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1.0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + security + recommended + optional + + + + + + + + + + + + + + + + + + + + + + + + rpm + + + + + + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 32 + [0-9a-f]* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/patches.rnc b/zypp/parser/yum/schema/patches.rnc new file mode 100644 index 0000000..3819bcd --- /dev/null +++ b/zypp/parser/yum/schema/patches.rnc @@ -0,0 +1,16 @@ +default namespace = "http://novell.com/package/metadata/suse/patches" + +include "common-inc.rnc" + +start = element patches { + element patch { + attribute id { text }, + element checksum { + private.checksum + }, + element location { + attribute href { xsd:anyURI } + }, + element category { "recommended" | "security" | "optional" }? + }* +} diff --git a/zypp/parser/yum/schema/patches.rng b/zypp/parser/yum/schema/patches.rng new file mode 100644 index 0000000..b386da3 --- /dev/null +++ b/zypp/parser/yum/schema/patches.rng @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + recommended + security + optional + + + + + + + + diff --git a/zypp/parser/yum/schema/patterns.rnc b/zypp/parser/yum/schema/patterns.rnc new file mode 100644 index 0000000..6efa68c --- /dev/null +++ b/zypp/parser/yum/schema/patterns.rnc @@ -0,0 +1,30 @@ +namespace suse = "http://novell.com/package/metadata/suse/pattern" +namespace rpm = "http://linux.duke.edu/metadata/rpm" + +include "rpm-inc.rnc" + +suse.uservisible = element suse:uservisible { empty } + +suse.category = element suse:category { private.localizedtext } + +suse.plaincat = element suse:category { text } + +start = element patterns { + # seen missing in the wild + attribute count { xsd:nonNegativeInteger }?, + element suse:pattern { + element suse:name { text }, + element suse:arch { private.archenum }?, + element suse:version { private.evr }?, + element suse:summary { text }, + element suse:description { text }?, + ((suse.uservisible, suse.category?) | (suse.plaincat, suse.uservisible?)), + rpm.provides?, + element rpm:freshens { + rpm.entry+ + }?, + rpm.suggests?, + rpm.requires?, + rpm.recommends? + }+ +} diff --git a/zypp/parser/yum/schema/patterns.rng b/zypp/parser/yum/schema/patterns.rng new file mode 100644 index 0000000..3d0c6bb --- /dev/null +++ b/zypp/parser/yum/schema/patterns.rng @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/primary.rnc b/zypp/parser/yum/schema/primary.rnc new file mode 100644 index 0000000..a8de88b --- /dev/null +++ b/zypp/parser/yum/schema/primary.rnc @@ -0,0 +1,88 @@ +default namespace = "http://linux.duke.edu/metadata/common" +namespace rpm = "http://linux.duke.edu/metadata/rpm" +namespace suse = "http://novell.com/package/metadata/suse/common" + +include "rpm-inc.rnc" + +yum.name = element name { text } + +yum.arch = element arch { private.archenum } + +yum.version = element version { + private.evr +} + +group.deps = rpm.provides?, rpm.requires?, rpm.conflicts?, + rpm.obsoletes?, rpm.suggests?, rpm.recommends?, + rpm.supplements?, rpm.enhances? + +group.deps1 = rpm.provides?, rpm.requires?, rpm.conflicts?, + rpm.obsoletes?, rpm.suggests?, rpm.enhances?, rpm.recommends?, + rpm.supplements? + + +group.deps2 = rpm.provides?, rpm.conflicts?, rpm.obsoletes?, rpm.enhances?, + rpm.supplements?, rpm.suggests?, rpm.recommends?, + rpm.requires? + +yum.location = element location { + attribute href { xsd:anyURI } +} + +yum.checksum = element checksum { + attribute pkgid { "YES" }, + private.checksum +} + +yum.time = element time { + attribute file { private.unixts }, + attribute build { private.unixts } +} + +yum.size = element size { + attribute package { private.size }, + # Found this blank in the wild + attribute archive { private.size | "" }, + attribute installed { private.size } +} + +start = element metadata { + attribute packages { private.nonnegative }, + element package { + attribute type { "rpm" }, + yum.name, + yum.arch, + yum.version, + yum.checksum, + # Found unlocalized in the wild + element summary { private.localizedtext | text }, + element description { private.localizedtext | text }, + element packager { text }, + # 10-SP1 stuff has a broken URL in the wild + element url { xsd:anyURI | text }, + yum.time, + yum.size, + yum.location, + element format { + element rpm:license { text }, + element rpm:vendor { text }, + element rpm:group { text }, + element rpm:buildhost { text }, + # Two different options seen in the wild + # one omits the element, the other leaves the value empty + element rpm:sourcerpm { text | empty }?, + element rpm:header-range { + attribute start { private.positive }, + attribute end { private.positive } + }, + # any of these orders is valid, all are in use + (group.deps | group.deps1 | group.deps2), + element file { + attribute type { "dir" | "ghost" }?, + text + }* + }, + element suse:license-to-confirm { text }? + }* +} + diff --git a/zypp/parser/yum/schema/primary.rng b/zypp/parser/yum/schema/primary.rng new file mode 100644 index 0000000..3f4fc45 --- /dev/null +++ b/zypp/parser/yum/schema/primary.rng @@ -0,0 +1,241 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + YES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + rpm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dir + ghost + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/product.rnc b/zypp/parser/yum/schema/product.rnc new file mode 100644 index 0000000..c8e60d1 --- /dev/null +++ b/zypp/parser/yum/schema/product.rnc @@ -0,0 +1,22 @@ +default namespace = "http://novell.com/package/metadata/suse/product" + +include "rpm-inc.rnc" + +start = element product { + attribute type { "add-on" | "base" }, + element vendor { text }, + element name { text }, + element arch { private.archenum }, + element version { private.evr }, + element displayname { private.localizedtext }, + element shortname { text }, + element distribution-name { text }, + element distribution-edition { text }, + element description { private.localizedtext }, + element release-notes-url { xsd:anyURI }?, + rpm.provides, + rpm.obsoletes?, + rpm.requires?, + rpm.conflicts? +} + diff --git a/zypp/parser/yum/schema/product.rng b/zypp/parser/yum/schema/product.rng new file mode 100644 index 0000000..1b97f32 --- /dev/null +++ b/zypp/parser/yum/schema/product.rng @@ -0,0 +1,56 @@ + + + + + + + + add-on + base + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/products.rnc b/zypp/parser/yum/schema/products.rnc new file mode 100644 index 0000000..8e69fd3 --- /dev/null +++ b/zypp/parser/yum/schema/products.rnc @@ -0,0 +1,15 @@ +include "common-inc.rnc" + +start = element products { + element product { + attribute id { text }?, + attribute schemeversion { "0" }?, + element name { text }, + element version { private.evr }, + element arch { private.archenum }, + element vendor { text }, + element summary { text }, + element description { text } + }+ +} + diff --git a/zypp/parser/yum/schema/products.rng b/zypp/parser/yum/schema/products.rng new file mode 100644 index 0000000..a4a0e2a --- /dev/null +++ b/zypp/parser/yum/schema/products.rng @@ -0,0 +1,38 @@ + + + + + + + + + + + + + 0 + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/repomd.rnc b/zypp/parser/yum/schema/repomd.rnc new file mode 100644 index 0000000..8ae2538 --- /dev/null +++ b/zypp/parser/yum/schema/repomd.rnc @@ -0,0 +1,29 @@ +default namespace = "http://linux.duke.edu/metadata/repo" + +include "common-inc.rnc" + +repomd.location = element location { + attribute href { xsd:anyURI } +} +repomd.meta = element checksum { + private.checksum +}, +# Oddity in the wild: a timestamp wiht a decimal +element timestamp { private.unixts | xsd:decimal }, +element size { private.positive }?, +element open-size { private.positive }?, +element open-checksum { + private.checksum +} + + +start = element repomd { + element revision { private.unixts }?, + element tags { + element repo { xsd:anyURI } + }?, + element data { + attribute type { "deltainfo" | "filelists" | "other" | "primary" | "susedata" | "suseinfo" | "updateinfo" | "patches" | "products" | "product" | "patterns" | "pattern" }, + ((repomd.meta, repomd.location) | (repomd.location, repomd.meta)) + }* +} diff --git a/zypp/parser/yum/schema/repomd.rng b/zypp/parser/yum/schema/repomd.rng new file mode 100644 index 0000000..0233022 --- /dev/null +++ b/zypp/parser/yum/schema/repomd.rng @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + deltainfo + filelists + other + primary + susedata + suseinfo + updateinfo + patches + products + product + patterns + pattern + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/rnc2rng b/zypp/parser/yum/schema/rnc2rng new file mode 100755 index 0000000..cd65ef6 --- /dev/null +++ b/zypp/parser/yum/schema/rnc2rng @@ -0,0 +1,7 @@ +#!/bin/bash +for i in *.rnc; do + g=${i%.rnc}.rng + test $i -ot $g && continue + echo $i... + trang -I rnc -O rng $i $g +done diff --git a/zypp/parser/yum/schema/rpm-inc.rnc b/zypp/parser/yum/schema/rpm-inc.rnc new file mode 100644 index 0000000..e512c7a --- /dev/null +++ b/zypp/parser/yum/schema/rpm-inc.rnc @@ -0,0 +1,45 @@ +namespace rpm = "http://linux.duke.edu/metadata/rpm" + +include "common-inc.rnc" + +rpm.entry = element rpm:entry { + attribute pre { "1" }?, + attribute kind { "atom" | "message" | "package" | "script" | "product" | "patch" | "pattern" }?, + attribute name { text }, + (private.evr, + attribute flags { "EQ" | "GE" | "LE" | "LT" | "GT" })? +} + +rpm.requires = element rpm:requires { + # pre should not be here, but it is in the wild + attribute pre { "1" }?, + rpm.entry* +} + +rpm.obsoletes = element rpm:obsoletes { + rpm.entry+ +} + +rpm.provides = element rpm:provides { + rpm.entry* +} + +rpm.recommends = element rpm:recommends { + rpm.entry* +} + +rpm.supplements = element rpm:supplements { + rpm.entry* +} + +rpm.conflicts = element rpm:conflicts { + rpm.entry+ +} + +rpm.enhances = element rpm:enhances { + rpm.entry+ +} + +rpm.suggests = element rpm:suggests { + rpm.entry* +} diff --git a/zypp/parser/yum/schema/rpm-inc.rng b/zypp/parser/yum/schema/rpm-inc.rng new file mode 100644 index 0000000..1ae4097 --- /dev/null +++ b/zypp/parser/yum/schema/rpm-inc.rng @@ -0,0 +1,101 @@ + + + + + + + + 1 + + + + + + atom + message + package + script + product + patch + pattern + + + + + + + + + EQ + GE + LE + LT + GT + + + + + + + + + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/susedata.rnc b/zypp/parser/yum/schema/susedata.rnc new file mode 100644 index 0000000..aba6301 --- /dev/null +++ b/zypp/parser/yum/schema/susedata.rnc @@ -0,0 +1,31 @@ +namespace susedata = "http://linux.duke.edu/metadata/susedata" + +include "common-inc.rnc" + +ns.susedata = element susedata:susedata { + attribute packages { private.nonnegative }, + element susedata:package { + attribute pkgid { text }, + attribute name { text }, + attribute arch { private.archenum }, + element susedata:version { private.evr }, + element susedata:eula { text }?, + element susedata:keyword { text }? + }* +} + +plain.susedata = element susedata { + attribute packages { private.nonnegative }, + element package { + attribute pkgid { text }, + attribute name { text }, + attribute arch { private.archenum }, + element version { private.evr }, + element eula { text }?, + element keyword { text }? + }* +} + +# Unfortunately there are some susedata files without namespaces in the wild +start = (ns.susedata | plain.susedata) + diff --git a/zypp/parser/yum/schema/susedata.rng b/zypp/parser/yum/schema/susedata.rng new file mode 100644 index 0000000..137b783 --- /dev/null +++ b/zypp/parser/yum/schema/susedata.rng @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/suseinfo.rnc b/zypp/parser/yum/schema/suseinfo.rnc new file mode 100644 index 0000000..d05e718 --- /dev/null +++ b/zypp/parser/yum/schema/suseinfo.rnc @@ -0,0 +1,19 @@ +namespace yum = "http://linux.duke.edu/metadata/repo" + +include "common-inc.rnc" + +# There is a horribly broken suseinfo variant we have to handle +good = element yum:suseinfo { + element yum:expire { private.positive } +} + +bad = element suseinfo { + element keywords { + element k { empty } + }, + element products { + element id { empty } + } +} + +start = (good | bad) diff --git a/zypp/parser/yum/schema/suseinfo.rng b/zypp/parser/yum/schema/suseinfo.rng new file mode 100644 index 0000000..0277bd9 --- /dev/null +++ b/zypp/parser/yum/schema/suseinfo.rng @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/updateinfo.rnc b/zypp/parser/yum/schema/updateinfo.rnc new file mode 100644 index 0000000..fc7b4dc --- /dev/null +++ b/zypp/parser/yum/schema/updateinfo.rnc @@ -0,0 +1,51 @@ +default namespace = "http://novell.com/package/metadata/suse/updateinfo" + +include "common-inc.rnc" + +start = element updates { + element update { + # Seen missing in the wild + attribute from { "maint-coord@suse.de" }?, + attribute status { "stable" }, + attribute type { "recommended" | "security" | "optional" | "feature" }, + attribute version { xsd:string }, + element id { text }, + element title { text }, + # Seen missing in the wild + element release { text }?, + # Usually with date attribute, but seen in the wild with content instead + element issued { + (attribute date { private.unixts } | private.unixts) + }, + # Seen missing in the wild + element references { + element reference { + # Appears to always start with https://bugzilla.novellc.om/show_bug.cgi?id= + # if type="bugzilla" and http://cve.mitre.org/cgi-bin/cvename.cgi?name= + # if type="cve" + attribute href { xsd:anyURI }, + attribute id { xsd:string }, + attribute title { xsd:string }, + attribute type { "bugzilla" | "cve" } + }+ + }?, + element description { text }, + element pkglist { + element collection { + element package { + attribute name { xsd:string }, + attribute arch { private.archenum }, + # not private.evr because "version" and "release" are spelled out + attribute epoch { private.nonnegative }?, + attribute version { text }?, + attribute release { text }?, + element filename { text }, + element restart_suggested { "1" }?, + element reboot_suggested { "1" }?, + element relogin_suggested { "1" }? + }+ + } + } + }+ +} + diff --git a/zypp/parser/yum/schema/updateinfo.rng b/zypp/parser/yum/schema/updateinfo.rng new file mode 100644 index 0000000..1fcf3d0 --- /dev/null +++ b/zypp/parser/yum/schema/updateinfo.rng @@ -0,0 +1,129 @@ + + + + + + + + + + + maint-coord@suse.de + + + + stable + + + + recommended + security + optional + feature + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bugzilla + cve + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1 + + + + + 1 + + + + + 1 + + + + + + + + + + + diff --git a/zypp/parser/yum/schema/validate-all b/zypp/parser/yum/schema/validate-all new file mode 100755 index 0000000..7124e95 --- /dev/null +++ b/zypp/parser/yum/schema/validate-all @@ -0,0 +1,149 @@ +#!/bin/bash +DEBUG=1 + +TARGET=/mounts/you +#TARGET=/mounts/dist/ibs +#TARGET=/mounts/mirror/SuSE/* + +SCHEMAS=$(dirname "$0") + +val_jing_compact() { + gzip -dcf "$2" | jing -c "$SCHEMAS/$1.rnc" /proc/self/fd/0 +} + +val_jing() { + gzip -dcf "$2" | jing "$SCHEMAS/$1.rng" /proc/self/fd/0 +} + +val_xmllint() { + gzip -dcf "$2" | xmllint --noout --relaxng "$SCHEMAS/$1.rng" - 2>/dev/null +} + +validate() { + [ $DEBUG -gt 4 ] && echo "$2" >&2 + if [ ! -f "$2" ]; then + echo "File missing: $2" + return 5 + fi + $VAL "$1" "$2" + if [ $? -ne 0 ]; then + echo "Validation failed: $2 (using $1)" + return 2 + fi +} + +get_xpath_href() { + xpath "$1" "$2" 2>/dev/null | sed -r -e 's/ href="/\n/g;s/$/\n/' \ + | sed -e 's/"$//' | tail -n +2 +} + +get_data_type() { + get_xpath_href "$1" '/repomd/data[@type="'"$2"'"]/location/@href' +} + +get_patches() { + get_xpath_href "$1" '/patches/patch/location/@href' +} + +if [ $(type -p xmllint) ]; then + VAL=val_xmllint +elif [ $(type -p jing) ]; then + VAL=val_jing_compact +else + echo "No validators found!!" + exit 100 +fi + +if [ -z $(type -p xpath) ]; then + echo "xpath command not fond" +fi + +find $TARGET -noleaf -name 'repomd.xml' 2>/dev/null | while read FN; do + [ $DEBUG -gt 0 ] && echo "$FN" >&2 + validate repomd "$FN" +# [ $? -eq 0 ] || break + D=$(dirname "$FN") + BASE=$(dirname "$D") + B=$(basename "$D") + if [ "$B" != "repodata" ]; then + echo "Found $FN not in repodata directory" + exit 3 + fi + + get_data_type "$FN" patterns | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate patterns "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" pattern | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate patterns "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" primary | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate primary "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" other | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate other "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" filelists | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate filelists "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" suseinfo | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate suseinfo "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" susedata | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate susedata "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" product | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate product "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" products | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate products "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" updateinfo | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate updateinfo "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" deltainfo | while read UIFN; do + [ $DEBUG -gt 1 ] && echo "$UIFN" >&2 + validate deltainfo "$BASE/$UIFN" + [ $? -eq 0 ] || exit 11 + done + + get_data_type "$FN" patches | while read PFN; do + [ $DEBUG -gt 1 ] && echo "$PFN" >&2 + validate patches "$BASE/$PFN" + [ $? -eq 0 ] || exit 12 + get_patches "$BASE/$PFN" | while read PATCH; do + [ $DEBUG -gt 2 ] && echo "$PATCH" >&2 + validate patch "$BASE/$PATCH" + [ $? -eq 0 ] || exit 13 + done + done +done diff --git a/zypp/pool/ByIdent.h b/zypp/pool/ByIdent.h new file mode 100644 index 0000000..fa06f1f --- /dev/null +++ b/zypp/pool/ByIdent.h @@ -0,0 +1,105 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/pool/ByIdent.h + * +*/ +#ifndef ZYPP_POOL_BYIDENT_H +#define ZYPP_POOL_BYIDENT_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace pool + { ///////////////////////////////////////////////////////////////// + + /** Main filter selecting PoolItems by \c name and \c kind. + */ + class ByIdent + { + public: + ByIdent() + : _id( 0 ) + {} + + explicit ByIdent( sat::Solvable slv_r ) + : _id( makeIdent( slv_r ) ) + {} + + explicit ByIdent( IdString ident_r ) + : _id( ident_r.id() ) + {} + + ByIdent( ResKind kind_r, IdString name_r ) + : _id( makeIdent( std::move(kind_r), name_r ) ) + {} + + ByIdent( ResKind kind_r, const C_Str & name_r ) + : _id( makeIdent( std::move(kind_r), name_r ) ) + {} + + public: + bool operator()( sat::Solvable slv_r ) const + { + return _id >= 0 ? ( slv_r.ident().id() == _id && ! slv_r.isKind( ResKind::srcpackage ) ) + : ( slv_r.ident().id() == -_id && slv_r.isKind( ResKind::srcpackage ) ); + } + + bool operator()( const PoolItem & pi_r ) const + { return operator()( pi_r.satSolvable() ); } + + bool operator()( const ResObject::constPtr& p_r ) const + { return p_r ? operator()( p_r->satSolvable() ) : !_id; } + + private: + sat::detail::IdType makeIdent( sat::Solvable slv_r ) + { + return slv_r.isKind( ResKind::srcpackage ) ? -slv_r.ident().id() + : slv_r.ident().id(); + } + + sat::detail::IdType makeIdent( const ResKind& kind_r, IdString name_r ) + { + if ( kind_r == ResKind::package ) + return name_r.id(); + else if ( kind_r == ResKind::srcpackage ) + return -name_r.id(); + return IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) ).id(); + } + + sat::detail::IdType makeIdent( const ResKind& kind_r, const C_Str & name_r ) + { + if ( kind_r == ResKind::package ) + return IdString( name_r ).id(); + else if ( kind_r == ResKind::srcpackage ) + return -(IdString( name_r ).id()); + return IdString( str::form( "%s:%s", kind_r.c_str(), name_r.c_str() ) ).id(); + } + + public: + sat::detail::IdType get() const { return _id; } + + private: + /** negative \c _id for \c srcpackage, as they use the same \c ident + * as \c package. + */ + sat::detail::IdType _id; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace pool + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_POOL_BYIDENT_H diff --git a/zypp/pool/PoolImpl.cc b/zypp/pool/PoolImpl.cc new file mode 100644 index 0000000..09236f9 --- /dev/null +++ b/zypp/pool/PoolImpl.cc @@ -0,0 +1,60 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/pool/PoolImpl.cc + * +*/ +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + ResPool::EstablishedStates::~EstablishedStates() + {} + + ResPool::EstablishedStates::ChangedPseudoInstalled ResPool::EstablishedStates::changedPseudoInstalled() const + { return _pimpl->changedPseudoInstalled(); } + + /////////////////////////////////////////////////////////////////// + namespace pool + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // Class PoolImpl::PoolImpl + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : PoolImpl::PoolImpl + // METHOD TYPE : Ctor + // + PoolImpl::PoolImpl() + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : PoolImpl::~PoolImpl + // METHOD TYPE : Dtor + // + PoolImpl::~PoolImpl() + {} + + ///////////////////////////////////////////////////////////////// + } // namespace pool + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/pool/PoolImpl.h b/zypp/pool/PoolImpl.h new file mode 100644 index 0000000..f3214b0 --- /dev/null +++ b/zypp/pool/PoolImpl.h @@ -0,0 +1,498 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/pool/PoolImpl.h + * +*/ +#ifndef ZYPP_POOL_POOLIMPL_H +#define ZYPP_POOL_POOLIMPL_H + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + namespace resstatus + { + /** Manipulator for \ref ResStatus::UserLockQueryField. + * Field is not public available. It is intended to remember the + * initial lock status usually derived from /etc/zypp/locks. So + * we are able to detect changes we have to write back on commit. + */ + struct UserLockQueryManip + { + /** Set lock and UserLockQuery bit according to \c yesno_r. */ + static void setLock( ResStatus & status_r, bool yesno_r ) + { + status_r.setLock( yesno_r, ResStatus::USER ); + status_r.setUserLockQueryMatch( yesno_r ); + } + + /** Update lock and UserLockQuery bit IFF the item gained the bit. */ + static void reapplyLock( ResStatus & status_r, bool yesno_r ) + { + if ( yesno_r && ! status_r.isUserLockQueryMatch() ) + { + status_r.setLock( yesno_r, ResStatus::USER ); + status_r.setUserLockQueryMatch( yesno_r ); + } + } + + /** Test whether the lock status differs from the remembered UserLockQuery bit. */ + static int diffLock( const ResStatus & status_r ) + { + bool userLock( status_r.isUserLocked() ); + if ( userLock == status_r.isUserLockQueryMatch() ) + return 0; + return userLock ? 1 : -1; + } + + }; + } + + namespace + { + inline PoolQuery makeTrivialQuery( IdString ident_r ) + { + sat::Solvable::SplitIdent ident( ident_r ); + + PoolQuery q; + q.addAttribute( sat::SolvAttr::name, ident.name().asString() ); + q.addKind( ident.kind() ); + q.setMatchExact(); + q.setCaseSensitive(true); + return q; + } + + inline bool hardLockQueriesRemove( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r ) + { + unsigned s( activeLocks_r.size() ); + activeLocks_r.remove( makeTrivialQuery( ident_r ) ); + return( activeLocks_r.size() != s ); + } + + inline bool hardLockQueriesAdd( pool::PoolTraits::HardLockQueries & activeLocks_r, IdString ident_r ) + { + PoolQuery q( makeTrivialQuery( ident_r ) ); + for_( it, activeLocks_r.begin(), activeLocks_r.end() ) + { + if ( *it == q ) + return false; + } + activeLocks_r.push_back( q ); + return true; + } + } + + /////////////////////////////////////////////////////////////////// + namespace solver { + namespace detail { + void establish( sat::Queue & pseudoItems_r, sat::Queue & pseudoFlags_r ); // in solver/detail/SATResolver.cc + } + } + /////////////////////////////////////////////////////////////////// + /// Store initial establish status of pseudo installed items. + /// + class ResPool::EstablishedStates::Impl + { + public: + Impl() + { solver::detail::establish( _pseudoItems, _pseudoFlags ); } + + /** Return all pseudo installed items whose current state differs from their initial one. */ + ResPool::EstablishedStates::ChangedPseudoInstalled changedPseudoInstalled() const + { + ChangedPseudoInstalled ret; + + if ( ! _pseudoItems.empty() ) + { + for ( sat::Queue::size_type i = 0; i < _pseudoItems.size(); ++i ) + { + PoolItem pi { sat::Solvable(_pseudoItems[i]) }; + ResStatus::ValidateValue vorig { validateValue( i ) }; + if ( pi.status().validate() != vorig ) + ret[pi] = vorig; + } + } + return ret; + } + + private: + ResStatus::ValidateValue validateValue( sat::Queue::size_type i ) const + { + ResStatus::ValidateValue ret { ResStatus::UNDETERMINED }; + switch ( _pseudoFlags[i] ) + { + case 0: ret = ResStatus::BROKEN /*2*/; break; + case 1: ret = ResStatus::SATISFIED /*4*/; break; + case -1: ret = ResStatus::NONRELEVANT /*6*/; break; + } + return ret; + } + + private: + sat::Queue _pseudoItems; + sat::Queue _pseudoFlags; + }; + + /////////////////////////////////////////////////////////////////// + namespace pool + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolImpl + // + /** */ + class PoolImpl + { + friend std::ostream & operator<<( std::ostream & str, const PoolImpl & obj ); + + public: + /** */ + using ContainerT = PoolTraits::ItemContainerT; + using size_type = PoolTraits::size_type; + using const_iterator = PoolTraits::const_iterator; + using Id2ItemT = PoolTraits::Id2ItemT; + + using repository_iterator = PoolTraits::repository_iterator; + + using SolvableIdType = sat::detail::SolvableIdType; + + using EstablishedStatesImpl = ResPool::EstablishedStates::Impl; + + public: + /** Default ctor */ + PoolImpl(); + /** Dtor */ + ~PoolImpl(); + + public: + /** convenience. */ + const sat::Pool satpool() const + { return sat::Pool::instance(); } + + /** Housekeeping data serial number. */ + const SerialNumber & serial() const + { return satpool().serial(); } + + /////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////// + public: + /** */ + bool empty() const + { return satpool().solvablesEmpty(); } + + /** */ + size_type size() const + { return satpool().solvablesSize(); } + + const_iterator begin() const + { return make_filter_begin( pool::ByPoolItem(), store() ); } + + const_iterator end() const + { return make_filter_end( pool::ByPoolItem(), store() ); } + + public: + /** Return the corresponding \ref PoolItem. + * Pool and sat pool should be in sync. Returns an empty + * \ref PoolItem if there is no corresponding \ref PoolItem. + * \see \ref PoolItem::satSolvable. + */ + PoolItem find( const sat::Solvable & slv_r ) const + { + const ContainerT & mystore( store() ); + return( slv_r.id() < mystore.size() ? mystore[slv_r.id()] : PoolItem() ); + } + + /////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////// + public: + /** \name Save and restore state. */ + //@{ + void SaveState( const ResKind & kind_r ); + + void RestoreState( const ResKind & kind_r ); + //@} + + /////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////// + public: + ResPoolProxy proxy( ResPool self ) const + { + checkSerial(); + if ( !_poolProxy ) + { + _poolProxy.reset( new ResPoolProxy( std::move(self), *this ) ); + } + return *_poolProxy; + } + + /** True factory for \ref ResPool::EstablishedStates. + * Internally we maintain the ResPool::EstablishedStates::Impl + * reference shared_ptr. Updated whenever the pool content changes. + * On demand hand it out as ResPool::EstablishedStates Impl. + */ + ResPool::EstablishedStates establishedStates() const + { store(); return ResPool::EstablishedStates( _establishedStates ); } + + public: + /** Forward list of Repositories that contribute ResObjects from \ref sat::Pool */ + size_type knownRepositoriesSize() const + { checkSerial(); return satpool().reposSize(); } + + repository_iterator knownRepositoriesBegin() const + { checkSerial(); return satpool().reposBegin(); } + + repository_iterator knownRepositoriesEnd() const + { checkSerial(); return satpool().reposEnd(); } + + Repository reposFind( const std::string & alias_r ) const + { checkSerial(); return satpool().reposFind( alias_r ); } + + /////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////// + public: + using HardLockQueries = PoolTraits::HardLockQueries; + using hardLockQueries_iterator = PoolTraits::hardLockQueries_iterator; + + const HardLockQueries & hardLockQueries() const + { return _hardLockQueries; } + + void reapplyHardLocks() const + { + // It is assumed that reapplyHardLocks is called after new + // items were added to the pool, but the _hardLockQueries + // did not change since. Action is to be performed only on + // those items that gained the bit in the UserLockQueryField. + MIL << "Re-apply " << _hardLockQueries.size() << " HardLockQueries" << endl; + PoolQueryResult locked; + for_( it, _hardLockQueries.begin(), _hardLockQueries.end() ) + { + locked += *it; + } + MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl; + for_( it, begin(), end() ) + { + // NOTE bsc#1225267: While reapplyLock sets but never unsets a lock, + // we don't need to care about buddies like in setHardLockQueries. + resstatus::UserLockQueryManip::reapplyLock( it->status(), locked.contains( *it ) ); + } + } + + void setHardLockQueries( const HardLockQueries & newLocks_r ) + { + MIL << "Apply " << newLocks_r.size() << " HardLockQueries" << endl; + _hardLockQueries = newLocks_r; + // now adjust the pool status + PoolQueryResult locked; + for_( it, _hardLockQueries.begin(), _hardLockQueries.end() ) + { + locked += *it; + } + MIL << "HardLockQueries match " << locked.size() << " Solvables." << endl; + for_( it, begin(), end() ) + { + // NOTE bsc#1225267: If the item has a buddy (a shared ResStatus), we lock if + // the item or the buddy is locked. Otherwise the item occurring later in the + // pool would dictate the status (unsetting a previously set lock). + bool yesno = locked.contains( *it ) || ( it->buddy() && locked.contains( PoolItem(it->buddy()) ) ); + resstatus::UserLockQueryManip::setLock( it->status(), yesno ); + } + } + + bool getHardLockQueries( HardLockQueries & activeLocks_r ) + { + activeLocks_r = _hardLockQueries; // current queries + // Now diff to the pool collecting names only. + // Thus added and removed locks are not necessarily + // disjoint. Added locks win. + typedef std::unordered_set IdentSet; + IdentSet addedLocks; + IdentSet removedLocks; + for_( it, begin(), end() ) + { + switch ( resstatus::UserLockQueryManip::diffLock( it->status() ) ) + { + case 0: // unchanged + break; + case 1: + addedLocks.insert( it->satSolvable().ident() ); + break; + case -1: + removedLocks.insert( it->satSolvable().ident() ); + break; + } + } + // now the bad part - adjust the queries + bool setChanged = false; + for_( it, removedLocks.begin(), removedLocks.end() ) + { + if ( addedLocks.find( *it ) != addedLocks.end() ) + continue; // Added locks win + if ( hardLockQueriesRemove( activeLocks_r, *it ) && ! setChanged ) + setChanged = true; + } + for_( it, addedLocks.begin(), addedLocks.end() ) + { + if ( hardLockQueriesAdd( activeLocks_r, *it ) && ! setChanged ) + setChanged = true; + } + return setChanged; + } + + public: + const ContainerT & store() const + { + checkSerial(); + if ( _storeDirty ) + { + sat::Pool pool( satpool() ); + bool addedItems = false; + bool reusedIDs = _watcherIDs.remember( pool.serialIDs() ); + std::list addedProducts; + + _store.resize( pool.capacity() ); + + if ( pool.capacity() ) + { + for ( sat::detail::SolvableIdType i = pool.capacity()-1; i != 0; --i ) + { + sat::Solvable s( i ); + PoolItem & pi( _store[i] ); + if ( ! s && pi ) + { + // the PoolItem got invalidated (e.g unloaded repo) + pi = PoolItem(); + } + else if ( reusedIDs || (s && ! pi) ) + { + // new PoolItem to add + pi = PoolItem::makePoolItem( s ); // the only way to create a new one! + // remember products for buddy processing (requires clean store) + if ( s.isKind( ResKind::product ) ) + addedProducts.push_back( pi ); + if ( !addedItems ) + addedItems = true; + } + } + } + _storeDirty = false; + + // Now, as the pool is adjusted, .... + + // .... we check for product buddies. + if ( ! addedProducts.empty() ) + { + for_( it, addedProducts.begin(), addedProducts.end() ) + { + it->setBuddy( asKind(*it)->referencePackage() ); + } + } + + // .... we must reapply those query based hard locks. + if ( addedItems ) + { + reapplyHardLocks(); + } + + // Compute the initial status of Patches etc. + if ( !_establishedStates ) + _establishedStates.reset( new EstablishedStatesImpl ); + } + return _store; + } + + const Id2ItemT & id2item () const + { + checkSerial(); + if ( _id2itemDirty ) + { + store(); + _id2item = Id2ItemT( size() ); + for_( it, begin(), end() ) + { + const sat::Solvable &s = (*it)->satSolvable(); + sat::detail::IdType id = s.ident().id(); + if ( s.isKind( ResKind::srcpackage ) ) + id = -id; + _id2item.insert( std::make_pair( id, *it ) ); + } + //INT << _id2item << endl; + _id2itemDirty = false; + } + return _id2item; + } + + /////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////// + private: + void checkSerial() const + { + if ( _watcher.remember( serial() ) ) + invalidate(); + satpool().prepare(); // always ajust dependencies. + } + + void invalidate() const + { + _storeDirty = true; + _id2itemDirty = true; + _id2item.clear(); + _poolProxy.reset(); + _establishedStates.reset(); + } + + private: + /** Watch sat pools serial number. */ + SerialNumberWatcher _watcher; + /** Watch sat pools Serial number of IDs - changes whenever resusePoolIDs==true - ResPool must also invalidate its PoolItems! */ + SerialNumberWatcher _watcherIDs; + mutable ContainerT _store; + mutable DefaultIntegral _storeDirty; + mutable Id2ItemT _id2item; + mutable DefaultIntegral _id2itemDirty; + + private: + mutable shared_ptr _poolProxy; + mutable shared_ptr _establishedStates; + + private: + /** Set of queries that define hardlocks. */ + HardLockQueries _hardLockQueries; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace pool + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_POOL_POOLIMPL_H diff --git a/zypp/pool/PoolStats.cc b/zypp/pool/PoolStats.cc new file mode 100644 index 0000000..b064e47 --- /dev/null +++ b/zypp/pool/PoolStats.cc @@ -0,0 +1,46 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/pool/PoolStats.cc + * +*/ +#include +//#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace pool + { ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const PoolStats & obj ) + { + str << "ResObjects: " << obj._total; + for( PoolStats::KindMap::const_iterator it = obj._perKind.begin(); it != obj._perKind.end(); ++it ) + { + str << endl << " " << it->first << ":\t" << it->second; + } + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace pool + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/pool/PoolStats.h b/zypp/pool/PoolStats.h new file mode 100644 index 0000000..97c6671 --- /dev/null +++ b/zypp/pool/PoolStats.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/pool/PoolStats.h + * +*/ +#ifndef ZYPP_POOL_POOLSTATS_H +#define ZYPP_POOL_POOLSTATS_H + +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace pool + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolStats + // + /** Functor counting ResObjects per Kind. + * \see dumpPoolStats + * \code + * Total: 2830 + * language: 81 + * package: 2710 + * product: 2 + * selection: 36 + * system: 1 + * \endcode + */ + struct PoolStats + { + void operator()( const ResObject::constPtr& ptr ) + { + ++_total; + ++_perKind[ptr->kind()]; + } + public: + using KindMap = std::map>; + Counter _total; + KindMap _perKind; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates PoolStats Stream output */ + std::ostream & operator<<( std::ostream & str, const PoolStats & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// + } // namespace pool + /////////////////////////////////////////////////////////////////// + + /** \relates pool::PoolStats Convenience to count and print out the + * number of ResObjects per Kind in a container. + * Fits container of ResObject::Ptr or PoolItem. + */ + template + std::ostream & dumpPoolStats( std::ostream & str, + TIterator begin_r, TIterator end_r ) + { + pool::PoolStats stats; + std::for_each( begin_r, end_r, std::ref(stats) ); + return str << stats; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_POOL_POOLSTATS_H diff --git a/zypp/pool/PoolTraits.h b/zypp/pool/PoolTraits.h new file mode 100644 index 0000000..be4b564 --- /dev/null +++ b/zypp/pool/PoolTraits.h @@ -0,0 +1,100 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/pool/PoolTraits.h + * +*/ +#ifndef ZYPP_POOL_POOLTRAITS_H +#define ZYPP_POOL_POOLTRAITS_H + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class PoolQuery; + + /////////////////////////////////////////////////////////////////// + namespace pool + { ///////////////////////////////////////////////////////////////// + + class PoolImpl; + + /** Pool internal filter skiping invalid/unwanted PoolItems. */ + struct ByPoolItem + { + bool operator()( const PoolItem & pi ) const + { return bool(pi); } + }; + + /** std::_Select2nd + */ + template + struct P_Select2nd + { + typename TPair::second_type& + operator()(TPair& __x) const + { return __x.second; } + + const typename TPair::second_type& + operator()(const TPair& __x) const + { return __x.second; } + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolTraits + // + /** */ + struct PoolTraits + { + public: + using SolvableIdType = sat::detail::SolvableIdType; + + /** pure items */ + using ItemContainerT = std::vector; + using item_iterator = ItemContainerT::const_iterator; + using const_iterator = filter_iterator; + using size_type = ItemContainerT::size_type; + + /** ident index */ + using Id2ItemT = std::unordered_multimap; + using Id2ItemValueSelector = P_Select2nd; + using byIdent_iterator = transform_iterator; + + /** list of known Repositories */ + using repository_iterator = sat::Pool::RepositoryIterator; + + /** hard locks from etc/zypp/locks */ + using HardLockQueries = std::list; + using hardLockQueries_iterator = HardLockQueries::const_iterator; + + using Impl = PoolImpl; + using Impl_Ptr = shared_ptr; + using Impl_constPtr = shared_ptr; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace pool + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_POOL_POOLTRAITS_H diff --git a/zypp/repo/Applydeltarpm.cc b/zypp/repo/Applydeltarpm.cc new file mode 100644 index 0000000..16eb3b0 --- /dev/null +++ b/zypp/repo/Applydeltarpm.cc @@ -0,0 +1,195 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/source/Applydeltarpm.cc + * +*/ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace applydeltarpm + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + const Pathname applydeltarpm_prog( "/usr/bin/applydeltarpm" ); + const str::regex applydeltarpm_tick ( "([0-9]+) percent finished" ); + + /****************************************************************** + ** + ** FUNCTION NAME : applydeltarpm + ** FUNCTION TYPE : bool + */ + bool applydeltarpm( const char *const argv_r[], + const Progress & report_r = Progress() ) + { + ExternalProgram prog( argv_r, ExternalProgram::Stderr_To_Stdout ); + str::smatch what; + for ( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() ) + { + if ( report_r && str::regex_match( line, what, applydeltarpm_tick ) ) + { + report_r( str::strtonum( what[1] ) ); + } + else + DBG << "Applydeltarpm : " << line; + } + return( prog.close() == 0 ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : haveApplydeltarpm + ** FUNCTION TYPE : bool + */ + bool haveApplydeltarpm() + { + // To track changes in availability of applydeltarpm. + static TriBool _last = indeterminate; + PathInfo prog( applydeltarpm_prog ); + bool have = prog.isX(); + if ( _last == have ) + ; // TriBool! 'else' is not '_last != have' + else + { + // _last is 'indeterminate' or '!have' + if ( (_last = have) ) + MIL << "Found executable " << prog << endl; + else + WAR << "No executable " << prog << endl; + } + return ( bool ) _last; + } + + /****************************************************************** + ** + ** FUNCTION NAME : check + ** FUNCTION TYPE : bool + */ + bool check( const std::string & sequenceinfo_r, bool quick_r ) + { + if ( ! haveApplydeltarpm() ) + return false; + + const char *const argv[] = { + "/usr/bin/applydeltarpm", + ( quick_r ? "-C" : "-c" ), + "-s", sequenceinfo_r.c_str(), + NULL + }; + + return( applydeltarpm( argv ) ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : check + ** FUNCTION TYPE : bool + */ + bool check( const Pathname & delta_r, bool quick_r ) + { + if ( ! haveApplydeltarpm() ) + return false; + + const char *const argv[] = { + "/usr/bin/applydeltarpm", + ( quick_r ? "-C" : "-c" ), + delta_r.asString().c_str(), + NULL + }; + + return( applydeltarpm( argv ) ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : provide + ** FUNCTION TYPE : bool + */ + bool provide( const Pathname & delta_r, const Pathname & new_r, + const Progress & report_r ) + { + // cleanup on error + AutoDispose guard( new_r, filesystem::unlink ); + + if ( ! haveApplydeltarpm() ) + return false; + + const char *const argv[] = { + "/usr/bin/applydeltarpm", + "-p", "-p", // twice to get percent output one per line + delta_r.asString().c_str(), + new_r.asString().c_str(), + NULL + }; + + filesystem::assert_dir( new_r.dirname() ); // bsc#1219442: in case .rpm and .drpm are not in the same directory + if ( ! applydeltarpm( argv, report_r ) ) + return false; + + guard.resetDispose(); // no cleanup on success + return true; + } + + /****************************************************************** + ** + ** FUNCTION NAME : provide + ** FUNCTION TYPE : bool + */ + bool provide( const Pathname & old_r, const Pathname & delta_r, + const Pathname & new_r, + const Progress & report_r ) + { + // cleanup on error + AutoDispose guard( new_r, filesystem::unlink ); + + if ( ! haveApplydeltarpm() ) + return false; + + const char *const argv[] = { + "/usr/bin/applydeltarpm", + "-p", "-p", // twice to get percent output one per line + "-r", old_r.asString().c_str(), + delta_r.asString().c_str(), + new_r.asString().c_str(), + NULL + }; + + filesystem::assert_dir( new_r.dirname() ); // bsc#1219442: in case .rpm and .drpm are not in the same directory + if ( ! applydeltarpm( argv, report_r ) ) + return false; + + guard.resetDispose(); // no cleanup on success + return true; + } + + ///////////////////////////////////////////////////////////////// + } // namespace applydeltarpm + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/Applydeltarpm.h b/zypp/repo/Applydeltarpm.h new file mode 100644 index 0000000..d77e380 --- /dev/null +++ b/zypp/repo/Applydeltarpm.h @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/source/Applydeltarpm.h + * +*/ +#ifndef ZYPP_SOURCE_APPLYDELTARPM_H +#define ZYPP_SOURCE_APPLYDELTARPM_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /** Namespace wrapping invocations of /usr/bin/applydeltarpm. */ + /////////////////////////////////////////////////////////////////// + namespace applydeltarpm + { ///////////////////////////////////////////////////////////////// + + /** Test whether an execuatble applydeltarpm program is available. */ + bool haveApplydeltarpm(); + + /** \name Check if reconstruction of rpm is possible. + * \see man applydeltarpm + */ + //@{ + /** Check via sequence info. + * \see applydeltarpm [-c|-C] -s sequence + */ + bool check( const std::string & sequenceinfo_r, bool quick_r = false ); + + /** Check via deltarpm. + * \see applydeltarpm [-c|-C] deltarpm + */ + bool check( const Pathname & delta_r, bool quick_r = false ); + + /** Quick via check sequence info.*/ + inline bool quickcheck( const std::string & sequenceinfo_r ) + { return check( sequenceinfo_r, true ); } + + /** Quick check via deltarpm.*/ + inline bool quickcheck( const Pathname & delta_r ) + { return check( delta_r, true ); } + //@} + + /** \name Re-create a new rpm from binary delta. + * \see man applydeltarpm + */ + //@{ + /** progress reporting */ + using Progress = function; + + /** Apply a binary delta to on-disk data to re-create a new rpm. + * \see applydeltarpm deltarpm newrpm + */ + bool provide( const Pathname & delta_r, const Pathname & new_r, + const Progress & report_r = Progress() ); + + /** Apply a binary delta to an old rpm to re-create a new rpm. + * \see applydeltarpm -r oldrpm deltarpm newrpm + */ + bool provide( const Pathname & old_r, const Pathname & delta_r, + const Pathname & new_r, + const Progress & report_r = Progress() ); + //@} + + ///////////////////////////////////////////////////////////////// + } // namespace applydeltarpm + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SOURCE_APPLYDELTARPM_H diff --git a/zypp/repo/DeltaCandidates.cc b/zypp/repo/DeltaCandidates.cc new file mode 100644 index 0000000..034d3c0 --- /dev/null +++ b/zypp/repo/DeltaCandidates.cc @@ -0,0 +1,118 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +extern "C" +{ +#include +} + +#include +#include +#include +#include +#include +#include + + +using std::endl; +using namespace zypp::packagedelta; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /** DeltaCandidates implementation. */ + struct DeltaCandidates::Impl + { + public: + Impl() + {} + + Impl( std::list &&repos, std::string &&pkgname = "" ) + : repos(std::move(repos)), pkgname(std::move(pkgname)) + {} + + std::list repos; + std::string pkgname; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /** \relates DeltaCandidates::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const DeltaCandidates::Impl & obj ) + { + return str << "DeltaCandidates::Impl"; + } + + /////////////////////////////////////////////////////////////////// + // + // class DeltaCandidates + // + /////////////////////////////////////////////////////////////////// + + DeltaCandidates::DeltaCandidates() + : _pimpl( new Impl ) + {} + + + DeltaCandidates::DeltaCandidates(std::list repos, + std::string pkgname) + : _pimpl( new Impl(std::move(repos), std::move(pkgname)) ) + {} + + DeltaCandidates::~DeltaCandidates() + {} + + std::list DeltaCandidates::deltaRpms(const Package::constPtr & package) const + { + std::list candidates; + + DBG << "package: " << package << endl; + for_( rit, _pimpl->repos.begin(), _pimpl->repos.end() ) + { + sat::LookupRepoAttr q( sat::SolvAttr::repositoryDeltaInfo, *rit ); + for_( it, q.begin(), q.end() ) + { + if ( _pimpl->pkgname.empty() + || it.subFind( sat::SolvAttr(DELTA_PACKAGE_NAME) ).asString() == _pimpl->pkgname ) + { + DeltaRpm delta( it ); + //DBG << "checking delta: " << delta << endl; + if ( ! package + || ( package->name() == delta.name() + && package->edition() == delta.edition() + && package->arch() == delta.arch() ) ) + { + DBG << "got delta candidate: " << delta << endl; + candidates.push_back( delta ); + } + } + } + } + return candidates; + } + + std::ostream & operator<<( std::ostream & str, const DeltaCandidates & obj ) + { + return str << *obj._pimpl; + } + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/DeltaCandidates.h b/zypp/repo/DeltaCandidates.h new file mode 100644 index 0000000..b379f63 --- /dev/null +++ b/zypp/repo/DeltaCandidates.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_REPO_DELTACANDIDATES_H +#define ZYPP_REPO_DELTACANDIDATES_H + +#include +#include + +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /** + * \short Candidate delta and patches for a package + * + * Basically a container that given N repositories, + * gets all patches and deltas from them for a given + * package. + */ + class ZYPP_API DeltaCandidates + { + friend std::ostream & operator<<( std::ostream & str, const DeltaCandidates & obj ); + + public: + /** Implementation */ + struct Impl; + + public: + DeltaCandidates(); + + DeltaCandidates(const DeltaCandidates &) = default; + DeltaCandidates(DeltaCandidates &&) noexcept = default; + DeltaCandidates &operator=(const DeltaCandidates &) = default; + DeltaCandidates &operator=(DeltaCandidates &&) noexcept = default; + /** + * \short Creates a candidate calculator + * \param repos Set of repositories providing patch and delta packages + */ + DeltaCandidates( std::list repos, std::string pkgname = "" ); + /** Dtor */ + ~DeltaCandidates(); + + std::list deltaRpms(const Package::constPtr & package) const; + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates DeltaCandidates Stream output */ + std::ostream & operator<<( std::ostream & str, const DeltaCandidates & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + + /** \relates DeltaCandidates Convenient construction. + * \todo templated ctor + */ + template + inline DeltaCandidates makeDeltaCandidates( RepoIter begin_r, RepoIter end_r ) + { return DeltaCandidates( std::list( begin_r, end_r ) ); } + + /** \relates DeltaCandidates Convenient construction. + * \todo templated ctor + */ + template + inline DeltaCandidates makeDeltaCandidates( const RepoContainer & cont_r ) + { return makeDeltaCandidates( cont_r.begin(), cont_r.end() ); } + + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_DELTACANDIDATES_H diff --git a/zypp/repo/MediaInfoDownloader.cc b/zypp/repo/MediaInfoDownloader.cc new file mode 100644 index 0000000..e7014fc --- /dev/null +++ b/zypp/repo/MediaInfoDownloader.cc @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include + +#include "MediaInfoDownloader.h" +#include + + +namespace zypp +{ +namespace repo +{ + +void downloadMediaInfo( const Pathname &dest_dir, + MediaSetAccess &media, + const ProgressData::ReceiverFnc & progressrcv ) +{ + Fetcher fetcher; + + //hardcode the max filesize to 20MB, to prevent unlimited data downloads but this limit will + //never be reached in a sane setup + fetcher.enqueue( OnMediaLocation("/media.1/media").setOptional(true).setDownloadSize( ByteCount(20, ByteCount::MB ) ) ); + fetcher.start( dest_dir, media, progressrcv ); + // ready, go! + fetcher.reset(); +} + +}// ns repo +} // ns zypp + + + diff --git a/zypp/repo/MediaInfoDownloader.h b/zypp/repo/MediaInfoDownloader.h new file mode 100644 index 0000000..aa18fa4 --- /dev/null +++ b/zypp/repo/MediaInfoDownloader.h @@ -0,0 +1,39 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_REPO_MEDIAINFO_DOWNLOADER +#define ZYPP_REPO_MEDIAINFO_DOWNLOADER + +#include +#include +#include +#include +#include +#include + +namespace zypp +{ + namespace repo + { + + /** + * \short Downloads the media info (/media.1) to a local directory + * \param dest_dir Destination directory + * \param media \ref MediaSetAccess object to some media + * \param progress Progress callback function + * + * \throws Exception on error + */ + void downloadMediaInfo( const Pathname &dest_dir, + MediaSetAccess &media, + const ProgressData::ReceiverFnc & progress = ProgressData::ReceiverFnc() ); + } // ns repo +} // ns zypp + +#endif diff --git a/zypp/repo/PackageDelta.cc b/zypp/repo/PackageDelta.cc new file mode 100644 index 0000000..e55b877 --- /dev/null +++ b/zypp/repo/PackageDelta.cc @@ -0,0 +1,140 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/source/PackageDelta.cc + * +*/ +#include +extern "C" +{ +#include +} + +#include + +#include +#include + + +using std::endl; +using std::string; + + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace packagedelta + { ///////////////////////////////////////////////////////////////// + + DeltaRpm::DeltaRpm( const sat::LookupAttr::iterator& deltaInfo_r ) + { + if ( deltaInfo_r.inSolvAttr() != sat::SolvAttr::repositoryDeltaInfo ) + { + INT << "Illegal non-repositoryDeltaInfo iterator: " << deltaInfo_r << endl; + return; + } + _repo = deltaInfo_r.inRepo(); + + IdString locdir; + IdString locname; + IdString locevr; + IdString locsuffix; + + IdString seqname; + IdString seqevr; + std::string seqnum; + + for_( it, deltaInfo_r.subBegin(), deltaInfo_r.subEnd() ) + { + switch ( it.inSolvAttr().id() ) + { + case DELTA_PACKAGE_NAME: + _name = it.asString(); + break; + + case DELTA_PACKAGE_EVR: + _edition = Edition( it.idStr() ); + break; + + case DELTA_PACKAGE_ARCH: + _arch = Arch( it.idStr() ); + break; + + case DELTA_LOCATION_DIR: + locdir = it.idStr(); + break; + + case DELTA_LOCATION_NAME: + locname = it.idStr(); + break; + + case DELTA_LOCATION_EVR: + locevr = it.idStr(); + break; + + case DELTA_LOCATION_SUFFIX: + locsuffix = it.idStr(); + break; + + case DELTA_DOWNLOADSIZE: + _location.setDownloadSize( ByteCount( it.asUnsignedLL() ) ); + break; + + case DELTA_CHECKSUM: + _location.setChecksum( it.asCheckSum() ); + break; + + case DELTA_BASE_EVR: + _baseversion.setEdition( Edition( it.idStr() ) ); + break; + + case DELTA_SEQ_NAME: + seqname = it.idStr(); + break; + + case DELTA_SEQ_EVR: + seqevr = it.idStr(); + break; + + case DELTA_SEQ_NUM: + seqnum = it.asString(); + break; + + default: + WAR << "Ignore unknown attribute: " << it << endl; + } + } + + _location.setLocation( str::form( "%s/%s-%s.%s", + locdir.c_str(), + locname.c_str(), + locevr.c_str(), + locsuffix.c_str() ) ); + + _baseversion.setSequenceinfo( str::form( "%s-%s-%s", + seqname.c_str(), + seqevr.c_str(), + seqnum.c_str() ) ); + } + + std::ostream & operator<<( std::ostream & str, const DeltaRpm & obj ) + { + return str + << "DeltaRpm[" << obj.name() << "-" << obj.edition() << "." << obj.arch() + << "](" << obj.location() + << '|' << obj.baseversion().edition() + << ')'; + } + + ///////////////////////////////////////////////////////////////// + } // namespace packagedelta + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/PackageDelta.h b/zypp/repo/PackageDelta.h new file mode 100644 index 0000000..05b65bc --- /dev/null +++ b/zypp/repo/PackageDelta.h @@ -0,0 +1,99 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/source/PackageDelta.h + * +*/ +#ifndef ZYPP_SOURCE_PACKAGEDELTA_H +#define ZYPP_SOURCE_PACKAGEDELTA_H + +#include +#include + +#include +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace packagedelta + { ///////////////////////////////////////////////////////////////// + + + /** \todo cheap copy! (switch to RWCOW) */ + class DeltaRpm + { + public: + class BaseVersion + { + public: + BaseVersion() + {} + + public: + const Edition & edition() const { return _edition; } + const std::string & sequenceinfo() const { return _sequenceinfo; } + + public: + BaseVersion & setEdition( const Edition & val_r ) { _edition = val_r; return *this; } + BaseVersion & setSequenceinfo( const std::string & val_r ) { _sequenceinfo = val_r; return *this; } + + private: + Edition _edition; + std::string _sequenceinfo; + }; + + public: + DeltaRpm() {} + DeltaRpm( const sat::LookupAttr::iterator& deltaInfo_r ); + + public: + /** \name Target package ident. */ + //@{ + const std::string & name() const { return _name; } + const Edition & edition() const { return _edition; } + const Arch & arch() const { return _arch; } + //@} + const OnMediaLocation & location() const { return _location; } + const BaseVersion & baseversion() const { return _baseversion; } + const Repository & repository() const { return _repo; } + + public: + DeltaRpm & setName( const std::string & val_r ) { _name = val_r; return *this; } + DeltaRpm & setEdition( const Edition & val_r ) { _edition = val_r; return *this; } + DeltaRpm & setArch( const Arch & val_r ) { _arch = val_r; return *this; } + DeltaRpm & setLocation( const OnMediaLocation & val_r ) { _location = val_r; return *this; } + DeltaRpm & setBaseversion( const BaseVersion & val_r ) { _baseversion = val_r; return *this; } + + private: + std::string _name; + Edition _edition; + Arch _arch; + OnMediaLocation _location; + BaseVersion _baseversion; + Repository _repo; + }; + + /** \relates DeltaRpm Stream output. */ + std::ostream & operator<<( std::ostream & str, const DeltaRpm & obj ); + + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace packagedelta + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SOURCE_PACKAGEDELTA_H diff --git a/zypp/repo/PackageProvider.cc b/zypp/repo/PackageProvider.cc new file mode 100644 index 0000000..ab7c315 --- /dev/null +++ b/zypp/repo/PackageProvider.cc @@ -0,0 +1,720 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/PackageProvider.cc + * +*/ +#include "zypp/ng/workflows/contextfacade.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace repo + { + /////////////////////////////////////////////////////////////////// + /// \class RpmSigCheckException + /// \brief Exception thrown by \ref PackageProviderImpl::rpmSigFileChecker + /////////////////////////////////////////////////////////////////// + class RpmSigCheckException : public FileCheckException + { + public: + RpmSigCheckException( repo::DownloadResolvableReport::Action action_r, std::string msg_r = "RpmSigCheckException" ) + : FileCheckException( std::move(msg_r) ) + , _action( action_r ) + {} + + /** Users final decision how to proceed */ + const repo::DownloadResolvableReport::Action & action() const + { return _action; } + + private: + repo::DownloadResolvableReport::Action _action; + }; + + + /////////////////////////////////////////////////////////////////// + // class PackageProviderPolicy + /////////////////////////////////////////////////////////////////// + + bool PackageProviderPolicy::queryInstalled( const std::string & name_r, + const Edition & ed_r, + const Arch & arch_r ) const + { + if ( _queryInstalledCB ) + return _queryInstalledCB( name_r, ed_r, arch_r ); + return false; + } + + /////////////////////////////////////////////////////////////////// + /// \class PackageProvider::Impl + /// \brief PackageProvider implementation interface. + /////////////////////////////////////////////////////////////////// + struct PackageProvider::Impl : private base::NonCopyable + { + Impl() {} + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + virtual ~Impl() {} + + /** Provide the package. + * The basic workflow. + * \throws Exception. + */ + virtual ManagedFile providePackage() const = 0; + + /** Provide the package if it is cached. */ + virtual ManagedFile providePackageFromCache() const = 0; + + /** Whether the package is cached. */ + virtual bool isCached() const = 0; + }; + + /////////////////////////////////////////////////////////////////// + /// \class PackageProviderImpl + /// \brief PackageProvider implementation for \c Package and \c SrcPackage + /////////////////////////////////////////////////////////////////// + template + class PackageProviderImpl : public PackageProvider::Impl + { + using TPackagePtr = typename TPackage::constPtr; // Package or SrcPackage + using UserData = callback::UserData; + public: + /** Ctor taking the Package to provide. */ + PackageProviderImpl( RepoMediaAccess &access_r, TPackagePtr &&package_r, + PackageProviderPolicy &&policy_r ) + : _policy(std::move( policy_r )) + , _package(std::move( package_r )) + , _access( access_r ) + , _retry(false) + {} + + PackageProviderImpl(const PackageProviderImpl &) = delete; + PackageProviderImpl(PackageProviderImpl &&) = delete; + PackageProviderImpl &operator=(const PackageProviderImpl &) = delete; + PackageProviderImpl &operator=(PackageProviderImpl &&) = delete; + + ~PackageProviderImpl() override {} + + public: + /** Provide the package. + * The basic workflow. + * \throws Exception. + */ + ManagedFile providePackage() const override; + + /** Provide the package if it is cached. */ + ManagedFile providePackageFromCache() const override + { + ManagedFile ret( doProvidePackageFromCache() ); + if ( ! ( ret->empty() || _package->repoInfo().keepPackages() ) ) + ret.setDispose( filesystem::unlink ); + return ret; + } + + /** Whether the package is cached. */ + bool isCached() const override + { return ! doProvidePackageFromCache()->empty(); } + + protected: + using Base = PackageProviderImpl; + using Report = callback::SendReport; + + /** Lookup the final rpm in cache. + * + * A cache hit will return a non empty ManagedFile and an empty one on cache miss. + * + * \note File disposal depending on the repos keepPackages setting + * are not set here, but in \ref providePackage or \ref providePackageFromCache. + */ + ManagedFile doProvidePackageFromCache() const + { return ManagedFile( _package->cachedLocation() ); } + + /** Actually provide the final rpm. + * Report start/problem/finish and retry loop are hadled by \ref providePackage. + * Here you trigger just progress and delta/plugin callbacks as needed. + * + * Proxy method for progressPackageDownload is provided here. + * \code + * ProvideFilePolicy policy; + * policy.progressCB( bind( &Base::progressPackageDownload, this, _1 ) ); + * return _access.provideFile( _package->repoInfo(), loc, policy ); + * \endcode + * + * \note The provided default implementation retrieves the packages default + * location. + */ + virtual ManagedFile doProvidePackage() const + { + ManagedFile ret; + OnMediaLocation loc = _package->location(); + + ProvideFilePolicy policy; + policy.progressCB( bind( &Base::progressPackageDownload, this, _1 ) ); + policy.fileChecker( bind( &Base::rpmSigFileChecker, this, _1 ) ); + return _access.provideFile( _package->repoInfo(), loc, policy ); + } + + protected: + /** Access to the DownloadResolvableReport */ + Report & report() const + { return *_report; } + + /** Redirect ProvideFilePolicy package download progress to this. */ + bool progressPackageDownload( int value ) const + { return report()->progress( value, _package ); } + + + /** \name Validate a rpm packages signature. + * + * This is the \ref FileChecker passed down to the \ref Fetcher to validate + * a provided rpm package. This builtin checker includes the workflow + * communicating with the user in case of a problem with the package + * signature. + * + * \throws RpmSigCheckException if the package is not accepted, propagating + * the users decision how to proceed (\ref DownloadResolvableReport::Action). + * + * \note This check is also needed, if the the rpm is built locally by using + * delta rpms! \ref \see RpmPackageProvider + */ + //@{ + void rpmSigFileChecker( const Pathname & file_r ) const + { + RepoInfo info = _package->repoInfo(); + if ( info.pkgGpgCheck() ) + { + UserData userData( "pkgGpgCheck" ); + ResObject::constPtr roptr( _package ); // gcc6 needs it more explcit. Has problem deducing + userData.set( "ResObject", roptr ); // a type for '_package->asKind()'... + /*legacy:*/userData.set( "Package", roptr->asKind() ); + userData.set( "Localpath", file_r ); + + RpmDb::CheckPackageResult res = RpmDb::CHK_NOKEY; + while ( res == RpmDb::CHK_NOKEY ) { + res = packageSigCheck( file_r, info.pkgGpgCheckIsMandatory(), userData ); + + // publish the checkresult, even if it is OK. Apps may want to report something... + report()->pkgGpgCheck( userData ); + + if ( res == RpmDb::CHK_NOKEY ) { + // if the check fails because we don't know the key + // we try to resolv it with gpgkey urls from the + // repository, if available + + target::rpm::RpmHeader::constPtr hr = target::rpm::RpmHeader::readPackage( file_r ); + if ( !hr ) { + // we did not find any information about the key in the header + // this should never happen + WAR << "Unable to read package header from " << hr << endl; + break; + } + + std::string keyID = hr->signatureKeyID(); + if ( keyID.length() > 0 ) { + if ( !zyppng::KeyRingWorkflow::provideAndImportKeyFromRepository ( zyppng::SyncContext::defaultContext(), keyID, info ) ) + break; + + } else { + // we did not find any information about the key in the header + // this should never happen + WAR << "packageSigCheck returned without setting providing missing key information" << endl; + break; + } + } + } + + if ( res != RpmDb::CHK_OK ) + { + if ( userData.hasvalue( "Action" ) ) // pkgGpgCheck report provided an user error action + { + resolveSignatureErrorAction( userData.get( "Action", repo::DownloadResolvableReport::ABORT ) ); + } + else if ( userData.haskey( "Action" ) ) // pkgGpgCheck requests the default problem report (wo. details) + { + defaultReportSignatureError( res ); + } + else // no advice from user => usedefaults + { + switch ( res ) + { + case RpmDb::CHK_OK: // Signature is OK + break; + + case RpmDb::CHK_NOKEY: // Public key is unavailable + case RpmDb::CHK_NOTFOUND: // Signature is unknown type + case RpmDb::CHK_FAIL: // Signature does not verify + case RpmDb::CHK_NOTTRUSTED: // Signature is OK, but key is not trusted + case RpmDb::CHK_ERROR: // File does not exist or can't be opened + case RpmDb::CHK_NOSIG: // File is unsigned + default: + // report problem (w. details), throw if to abort, else retry/ignore + defaultReportSignatureError( res, str::Str() << userData.get( "CheckPackageDetail" ) ); + break; + } + } + } + } + } + + using RpmDb = target::rpm::RpmDb; + + /** Actual rpm package signature check. */ + RpmDb::CheckPackageResult packageSigCheck( const Pathname & path_r, bool isMandatory_r, UserData & userData ) const + { + if ( !_target ) + _target = getZYpp()->getTarget(); + + RpmDb::CheckPackageResult ret = RpmDb::CHK_ERROR; + RpmDb::CheckPackageDetail detail; + if ( _target ) + { + ret = _target->rpmDb().checkPackageSignature( path_r, detail ); + if ( ret == RpmDb::CHK_NOSIG && !isMandatory_r ) + { + WAR << "Relax CHK_NOSIG: Config says unsigned packages are OK" << endl; + ret = RpmDb::CHK_OK; + } + } + else + detail.push_back( RpmDb::CheckPackageDetail::value_type( ret, "OOps. Target is not initialized!" ) ); + + userData.set( "CheckPackageResult", ret ); + userData.set( "CheckPackageDetail", std::move(detail) ); + return ret; + } + + /** React on signature verification error user action. + * \note: IGNORE == accept insecure file (no SkipRequestException!) + */ + void resolveSignatureErrorAction( repo::DownloadResolvableReport::Action action_r ) const + { + switch ( action_r ) + { + case repo::DownloadResolvableReport::IGNORE: + WAR << _package->asUserString() << ": " << "User requested to accept insecure file" << endl; + break; + default: + case repo::DownloadResolvableReport::RETRY: + case repo::DownloadResolvableReport::ABORT: + ZYPP_THROW(RpmSigCheckException(action_r,"Signature verification failed")); + break; + } + } + + /** Default signature verification error handling. */ + void defaultReportSignatureError( RpmDb::CheckPackageResult ret, const std::string & detail_r = std::string() ) const + { + str::Str msg; + msg << _package->asUserString() << ": " << _("Signature verification failed") << " " << ret; + if ( ! detail_r.empty() ) + msg << "\n" << detail_r; + resolveSignatureErrorAction( report()->problem( _package, repo::DownloadResolvableReport::INVALID, msg.str() ) ); + } + //@} + + protected: + PackageProviderPolicy _policy; + TPackagePtr _package; + RepoMediaAccess & _access; + + private: + using ScopedGuard = shared_ptr; + + ScopedGuard newReport() const + { + _report.reset( new Report ); + // Use a custom deleter calling _report.reset() when guard goes out of + // scope (cast required as reset is overloaded). We want report to end + // when leaving providePackage and not wait for *this going out of scope. + return shared_ptr( static_cast(0), + std::bind( std::mem_fn(static_cast::*)()>(&shared_ptr::reset)), + std::ref(_report) ) ); + } + + mutable bool _retry; + mutable shared_ptr _report; + mutable Target_Ptr _target; + }; + /////////////////////////////////////////////////////////////////// + + template + ManagedFile PackageProviderImpl::providePackage() const + { + ScopedGuard guardReport( newReport() ); + + // check for cache hit: + ManagedFile ret( providePackageFromCache() ); + if ( ! ret->empty() ) + { + MIL << "provided Package from cache " << _package << " at " << ret << endl; + report()->infoInCache( _package, ret ); + return ret; // <-- cache hit + } + + // HERE: cache misss, check toplevel cache or do download: + RepoInfo info = _package->repoInfo(); + + // Check toplevel cache + { + RepoManagerOptions topCache; + if ( info.packagesPath().dirname() != topCache.repoPackagesCachePath ) // not using toplevel cache + { + const OnMediaLocation & loc( _package->location() ); + if ( ! loc.checksum().empty() ) // no cache hit without checksum + { + PathInfo pi( topCache.repoPackagesCachePath / info.packagesPath().basename() / info.path() / loc.filename() ); + if ( pi.isExist() && loc.checksum() == CheckSum( loc.checksum().type(), std::ifstream( pi.c_str() ) ) ) + { + report()->start( _package, pi.path().asFileUrl() ); + const Pathname & dest( info.packagesPath() / info.path() / loc.filename() ); + if ( filesystem::assert_dir( dest.dirname() ) == 0 && filesystem::hardlinkCopy( pi.path(), dest ) == 0 ) + { + ret = ManagedFile( dest ); + if ( ! info.keepPackages() ) + ret.setDispose( filesystem::unlink ); + + MIL << "provided Package from toplevel cache " << _package << " at " << ret << endl; + report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() ); + return ret; // <-- toplevel cache hit + } + } + } + } + } + + // FIXME we only support the first url for now. + if ( info.baseUrlsEmpty() ) + ZYPP_THROW(Exception("No url in repository.")); + + MIL << "provide Package " << _package << endl; + Url url = * info.baseUrlsBegin(); + try { + do { + _retry = false; + if ( ! ret->empty() ) + { + ret.setDispose( filesystem::unlink ); + ret.reset(); + } + report()->start( _package, url ); + try + { + ret = doProvidePackage(); + } + catch ( const UserRequestException & excpt ) + { + ERR << "Failed to provide Package " << _package << endl; + if ( ! _retry ) + ZYPP_RETHROW( excpt ); + } + catch ( const RpmSigCheckException & excpt ) + { + ERR << "Failed to provide Package " << _package << endl; + if ( ! _retry ) + { + // Signature verification error was already reported by the + // rpmSigFileChecker. Just handle the users action decision: + switch ( excpt.action() ) + { + case repo::DownloadResolvableReport::RETRY: + _retry = true; + break; + case repo::DownloadResolvableReport::IGNORE: + ZYPP_THROW(SkipRequestException("User requested skip of corrupted file")); + break; + default: + case repo::DownloadResolvableReport::ABORT: + ZYPP_THROW(AbortRequestException("User requested to abort")); + break; + } + } + } + catch ( const FileCheckException & excpt ) + { + ERR << "Failed to provide Package " << _package << endl; + if ( ! _retry ) + { + const std::string & package_str = _package->asUserString(); + // TranslatorExplanation %s = package being checked for integrity + switch ( report()->problem( _package, repo::DownloadResolvableReport::INVALID, str::form(_("Package %s seems to be corrupted during transfer. Do you want to retry retrieval?"), package_str.c_str() ) ) ) + { + case repo::DownloadResolvableReport::RETRY: + _retry = true; + break; + case repo::DownloadResolvableReport::IGNORE: + ZYPP_THROW(SkipRequestException("User requested skip of corrupted file")); + break; + default: + case repo::DownloadResolvableReport::ABORT: + ZYPP_THROW(AbortRequestException("User requested to abort")); + break; + } + } + } + catch ( const Exception & excpt ) + { + ERR << "Failed to provide Package " << _package << endl; + if ( ! _retry ) + { + // Aything else gets reported + const std::string & package_str = _package->asUserString(); + + // TranslatorExplanation %s = name of the package being processed. + std::string detail_str( str::form(_("Failed to provide Package %s. Do you want to retry retrieval?"), package_str.c_str() ) ); + detail_str += str::form( "\n\n%s", excpt.asUserHistory().c_str() ); + + switch ( report()->problem( _package, repo::DownloadResolvableReport::IO, detail_str.c_str() ) ) + { + case repo::DownloadResolvableReport::RETRY: + _retry = true; + break; + case repo::DownloadResolvableReport::IGNORE: + ZYPP_THROW(SkipRequestException("User requested skip of file", excpt)); + break; + default: + case repo::DownloadResolvableReport::ABORT: + ZYPP_THROW(AbortRequestException("User requested to abort", excpt)); + break; + } + } + } + } while ( _retry ); + } catch(...){ + // bsc#1045735: Be sure no invalid files stay in the cache! + if ( ! ret->empty() ) + ret.setDispose( filesystem::unlink ); + throw; + } + + report()->finish( _package, repo::DownloadResolvableReport::NO_ERROR, std::string() ); + MIL << "provided Package " << _package << " at " << ret << endl; + return ret; + } + + + /////////////////////////////////////////////////////////////////// + /// \class RpmPackageProvider + /// \brief RPM PackageProvider implementation (with deltarpm processing). + /////////////////////////////////////////////////////////////////// + class RpmPackageProvider : public PackageProviderImpl + { + public: + RpmPackageProvider( RepoMediaAccess & access_r, + Package::constPtr &&package_r, + DeltaCandidates &&deltas_r, + PackageProviderPolicy &&policy_r ) + : PackageProviderImpl( access_r, std::move(package_r), std::move(policy_r) ) + , _deltas( std::move(deltas_r) ) + {} + + protected: + ManagedFile doProvidePackage() const override; + + private: + using DeltaRpm = packagedelta::DeltaRpm; + + ManagedFile tryDelta( const DeltaRpm & delta_r ) const; + + bool progressDeltaDownload( int value ) const + { return report()->progressDeltaDownload( value ); } + + void progressDeltaApply( int value ) const + { return report()->progressDeltaApply( value ); } + + bool queryInstalled( const Edition & ed_r = Edition() ) const + { return _policy.queryInstalled( _package->name(), ed_r, _package->arch() ); } + + private: + DeltaCandidates _deltas; + }; + /////////////////////////////////////////////////////////////////// + + ManagedFile RpmPackageProvider::doProvidePackage() const + { + // check whether to process patch/delta rpms + // FIXME we only check the first url for now. + if ( ZConfig::instance().download_use_deltarpm() + && ( _package->repoInfo().url().schemeIsDownloading() || ZConfig::instance().download_use_deltarpm_always() ) ) + { + std::list deltaRpms; + _deltas.deltaRpms( _package ).swap( deltaRpms ); + + if ( ! deltaRpms.empty() && queryInstalled() && applydeltarpm::haveApplydeltarpm() ) + { + for_( it, deltaRpms.begin(), deltaRpms.end()) + { + DBG << "tryDelta " << *it << endl; + ManagedFile ret( tryDelta( *it ) ); + if ( ! ret->empty() ) + return ret; + } + } + } + + // no patch/delta -> provide full package + return Base::doProvidePackage(); + } + + ManagedFile RpmPackageProvider::tryDelta( const DeltaRpm & delta_r ) const + { + if ( delta_r.baseversion().edition() != Edition::noedition + && ! queryInstalled( delta_r.baseversion().edition() ) ) + return ManagedFile(); + + if ( ! applydeltarpm::quickcheck( delta_r.baseversion().sequenceinfo() ) ) + return ManagedFile(); + + report()->startDeltaDownload( delta_r.location().filename(), + delta_r.location().downloadSize() ); + ManagedFile delta; + try + { + ProvideFilePolicy policy; + policy.progressCB( bind( &RpmPackageProvider::progressDeltaDownload, this, _1 ) ); + delta = _access.provideFile( delta_r.repository().info(), delta_r.location(), policy ); + } + catch ( const Exception & excpt ) + { + report()->problemDeltaDownload( excpt.asUserHistory() ); + return ManagedFile(); + } + report()->finishDeltaDownload(); + + report()->startDeltaApply( delta ); + if ( ! applydeltarpm::check( delta_r.baseversion().sequenceinfo() ) ) + { + report()->problemDeltaApply( _("applydeltarpm check failed.") ); + return ManagedFile(); + } + + // Build the package + Pathname cachedest( _package->repoInfo().packagesPath() / _package->repoInfo().path() / _package->location().filename() ); + Pathname builddest( cachedest.extend( ".drpm" ) ); + + if ( ! applydeltarpm::provide( delta, builddest, + bind( &RpmPackageProvider::progressDeltaApply, this, _1 ) ) ) + { + report()->problemDeltaApply( _("applydeltarpm failed.") ); + return ManagedFile(); + } + ManagedFile builddestCleanup( builddest, filesystem::unlink ); + report()->finishDeltaApply(); + + // Check and move it into the cache + // Here the rpm itself is ready. If the packages sigcheck fails, it + // makes no sense to return a ManagedFile() and fallback to download the + // full rpm. It won't be different. So let the exceptions escape... + rpmSigFileChecker( builddest ); + if ( filesystem::hardlinkCopy( builddest, cachedest ) != 0 ) + ZYPP_THROW( Exception( str::Str() << "Can't hardlink/copy " << builddest << " to " << cachedest ) ); + + return ManagedFile( cachedest, filesystem::unlink ); + } + + /////////////////////////////////////////////////////////////////// + // class PackageProvider + /////////////////////////////////////////////////////////////////// + namespace factory + { + inline PackageProvider::Impl * make( RepoMediaAccess & access_r, const PoolItem & pi_r, + DeltaCandidates &&deltas_r, + PackageProviderPolicy &&policy_r ) + { + if ( pi_r.isKind() ) + return new RpmPackageProvider( access_r, pi_r->asKind(), std::move(deltas_r), std::move(policy_r) ); + else if ( pi_r.isKind() ) + return new PackageProviderImpl( access_r, pi_r->asKind(), std::move(policy_r) ); + else + ZYPP_THROW( Exception( str::Str() << "Don't know how to cache non-package " << pi_r.asUserString() ) ); + } + + inline PackageProvider::Impl * make( RepoMediaAccess & access_r, const PoolItem & pi_r, + PackageProviderPolicy &&policy_r ) + { + if ( pi_r.isKind() ) + return new PackageProviderImpl( access_r, pi_r->asKind(), std::move(policy_r) ); + else if ( pi_r.isKind() ) + return new PackageProviderImpl( access_r, pi_r->asKind(), std::move(policy_r) ); + else + ZYPP_THROW( Exception( str::Str() << "Don't know how to cache non-package " << pi_r.asUserString() ) ); + } + + inline PackageProvider::Impl * make( RepoMediaAccess & access_r, + Package::constPtr &&package_r, + DeltaCandidates &&deltas_r, + PackageProviderPolicy &&policy_r ) + { return new RpmPackageProvider( access_r, std::move(package_r), std::move(deltas_r), std::move(policy_r) ); } + + } // namespace factory + /////////////////////////////////////////////////////////////////// + + PackageProvider::PackageProvider( RepoMediaAccess & access_r, const PoolItem & pi_r, + DeltaCandidates deltas_r, PackageProviderPolicy policy_r ) + + : _pimpl( factory::make( access_r, pi_r, std::move(deltas_r), std::move(policy_r) ) ) + {} + + PackageProvider::PackageProvider( RepoMediaAccess & access_r, const PoolItem & pi_r, + PackageProviderPolicy policy_r ) + : _pimpl( factory::make( access_r, pi_r, std::move(policy_r) ) ) + {} + + /* legacy */ + PackageProvider::PackageProvider( RepoMediaAccess & access_r, + Package::constPtr package_r, + DeltaCandidates deltas_r, + PackageProviderPolicy policy_r ) + : _pimpl( factory::make( access_r, std::move(package_r), std::move(deltas_r), std::move(policy_r) ) ) + {} + + PackageProvider::~PackageProvider() + {} + + ManagedFile PackageProvider::providePackage() const + { return _pimpl->providePackage(); } + + ManagedFile PackageProvider::providePackageFromCache() const + { return _pimpl->providePackageFromCache(); } + + bool PackageProvider::isCached() const + { return _pimpl->isCached(); } + + } // namespace repo + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/PackageProvider.h b/zypp/repo/PackageProvider.h new file mode 100644 index 0000000..05c7ee0 --- /dev/null +++ b/zypp/repo/PackageProvider.h @@ -0,0 +1,107 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/PackageProvider.h + * +*/ +#ifndef ZYPP_REPO_PACKAGEPROVIDER_H +#define ZYPP_REPO_PACKAGEPROVIDER_H + +#include + +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace repo + { + + /////////////////////////////////////////////////////////////////// + /// \class PackageProviderPolicy + /// \brief Policies and options for \ref PackageProvider + /////////////////////////////////////////////////////////////////// + class ZYPP_API PackageProviderPolicy + { + public: + /** Get installed Editions callback signature. */ + typedef function QueryInstalledCB; + + /** Set callback. */ + PackageProviderPolicy & queryInstalledCB( QueryInstalledCB queryInstalledCB_r ) + { _queryInstalledCB = queryInstalledCB_r; return *this; } + + /** Evaluate callback. */ + bool queryInstalled( const std::string & name_r, + const Edition & ed_r, + const Arch & arch_r ) const; + + private: + QueryInstalledCB _queryInstalledCB; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class PackageProvider + /// \brief Provide a package from a Repo. + /// + /// Use available deltarpm if apropriate. + /////////////////////////////////////////////////////////////////// + class ZYPP_API PackageProvider + { + public: + /** Ctor taking the package to provide. + * \throws Exception If pi_r refers to neither a \c Package nor a \c SrcPackage. + */ + PackageProvider( RepoMediaAccess & access, const PoolItem & pi_r, + PackageProviderPolicy policy_r = PackageProviderPolicy() ); + + /** \overload Ctor taking additional hint to deltarpms (not used for SrcPackages) + * \throws Exception If pi_r refers to neither a \c Package nor a \c SrcPackage. + */ + PackageProvider( RepoMediaAccess & access, const PoolItem & pi_r, + DeltaCandidates deltas, + PackageProviderPolicy policy_r = PackageProviderPolicy() ); + + /** Legacy Ctor taking a \c Package::constPtr to provide. */ + PackageProvider( RepoMediaAccess & access, + Package::constPtr package, + DeltaCandidates deltas, + PackageProviderPolicy policy_r = PackageProviderPolicy() ); + + ~PackageProvider(); + + public: + /** Provide the package. + * \throws Exception. + */ + ManagedFile providePackage() const; + + /** Provide the package if it is cached. */ + ManagedFile providePackageFromCache() const; + + /** Whether the package is cached. */ + bool isCached() const; + + public: + struct Impl; ///< Implementation class. + private: + RW_pointer _pimpl; ///< Pointer to implementation. + }; + /////////////////////////////////////////////////////////////////// + + } // namespace repo + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SOURCE_PACKAGEPROVIDER_H diff --git a/zypp/repo/PluginRepoverification.cc b/zypp/repo/PluginRepoverification.cc new file mode 100644 index 0000000..c6249e9 --- /dev/null +++ b/zypp/repo/PluginRepoverification.cc @@ -0,0 +1,316 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/PluginRepoverification.cc + */ +#include +#include +#include + +#include "PluginRepoverification.h" + +#include +#include +#include +#include +#include +#include +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp_private +{ + using namespace zypp; + /////////////////////////////////////////////////////////////////// + namespace repo + { + + struct Monitor + { + /** Report a line of output (without trailing NL) otherwise a life ping on timeout. */ + using Callback = std::function)>; + + Monitor( io::timeout_type timeout_r = io::no_timeout ) + : _timeout { timeout_r } + {} + + int operator()( ExternalProgram & prog_r, Callback cb_r = Callback() ) + { + std::string line; + bool goOn = true; + prog_r.setBlocking( false ); + FILE * inputfile = prog_r.inputFile(); + do { + const auto &readResult = io::receiveUpto( inputfile, '\n', _timeout ); + line += readResult.second; // we always may have received a partial line + goOn = true; + switch ( readResult.first ) { + + case io::ReceiveUpToResult::Success: + goOn = reportLine( line, cb_r ); + line.clear(); // in case the CB did not move it out + break; + + case io::ReceiveUpToResult::Timeout: + goOn = reportTimeout( cb_r ); + break; + + case io::ReceiveUpToResult::Error: + case io::ReceiveUpToResult::EndOfFile: + reportFinalLineUnlessEmpty( line, cb_r ); + line.clear(); // in case the CB did not move it out + goOn = false; + break; + } + } while ( goOn ); + + if ( prog_r.running() ) { + WAR << "ABORT by callback: pid " << prog_r.getpid() << endl; + prog_r.kill(); + } + return prog_r.close(); + } + + private: + bool reportLine( std::string & line_r, Callback & cb_r ) + { + if ( cb_r ) { + if ( not line_r.empty() && line_r.back() == '\n' ) + line_r.pop_back(); + return cb_r( std::move(line_r) ); + } + return true; + } + bool reportTimeout( Callback & cb_r ) + { + return cb_r ? cb_r( std::nullopt ) : true; + } + bool reportFinalLineUnlessEmpty( std::string & line_r, Callback & cb_r ) + { + if ( cb_r && not line_r.empty() ) // implies an incomplete line (no NL) + cb_r( std::move(line_r) ); + return false; + } + private: + io::timeout_type _timeout = io::no_timeout; + }; + + /////////////////////////////////////////////////////////////////// + /// \class PluginRepoverification::Checker::Impl + /// \brief PluginRepoverification::Checker data storage. + /////////////////////////////////////////////////////////////////// + class PluginRepoverification::Checker::Impl + { + public: + Impl( RW_pointer parent_r, + Pathname &&sigpathLocal_r, Pathname &&keypathLocal_r, RepoInfo &&repo_r ) + : _parent { std::move( parent_r ) } + , _sigpathLocal { std::move(sigpathLocal_r) } + , _keypathLocal { std::move(keypathLocal_r) } + , _repoinfo { std::move(repo_r) } + {} + + RW_pointer _parent; + Pathname _sigpathLocal; + Pathname _keypathLocal; + RepoInfo _repoinfo; + }; + + /////////////////////////////////////////////////////////////////// + /// \class PluginRepoverification::Impl + /// \brief PluginRepoverification implementation. + /////////////////////////////////////////////////////////////////// + class PluginRepoverification::Impl + { + friend std::ostream & operator<<( std::ostream & str, const Impl & obj ); + friend std::ostream & dumpOn( std::ostream & str, const Impl & obj ); + + public: + Impl() + {} + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + Impl(Pathname &&plugindir_r, Pathname &&chroot_r) + : _watchPlugindir{std::move(plugindir_r), WatchFile::NO_INIT}, + _chroot{std::move(chroot_r)} {} + + ~Impl() + {} + + bool isNeeded() const + { return _isNeeded; } + + bool checkIfNeeded() + { + if ( _watchPlugindir.hasChanged() ) { + _isNeeded = false; + // check for at least one executable plugin inside.. + filesystem::dirForEach( plugindir(), + [this]( const Pathname & dir_r, const char *const name_r ) -> bool { + PathInfo pi ( dir_r/name_r ); + if ( pi.isFile() && pi.userMayRX() ) { + this->_isNeeded = true; + return false; + } + return true; + } ); + } + return _isNeeded; + } + + void verifyWorkflow( const Pathname & file_r, RW_pointer datap_r ) const + { + // Execute the plugins. They will throw if something is wrong... + filesystem::dirForEach( plugindir(), + [&,this]( const Pathname & dir_r, const char *const name_r ) -> bool { + PathInfo pi ( dir_r/name_r ); + if ( pi.isFile() && pi.userMayRX() ) + this->pluginVerify( name_r, file_r, *datap_r ); + return true; + } ); + } + + private: + void pluginVerify( std::string plugin_r, const Pathname & file_r, const PluginRepoverification::Checker::Impl & data_r ) const + { + Pathname pluginPath { plugindir()/plugin_r }; + if ( not _chroot.emptyOrRoot() ) { + pluginPath = Pathname::stripprefix( _chroot, pluginPath ); + // we need to make sure the files are available inside the chroot + INT << "chroot PluginRepoverification does not yet work." << endl; + return; + } + + ExternalProgram::Arguments args; + args.push_back( pluginPath.asString() ); + /// NOTE: Update plugin-repoverification page if new args are supplied + args.push_back( "--file" ); + args.push_back( file_r.asString() ); + args.push_back( "--fsig" ); + args.push_back( data_r._sigpathLocal.asString() ); + args.push_back( "--fkey" ); + args.push_back( data_r._keypathLocal.asString() ); + args.push_back( "--ralias" ); + args.push_back( data_r._repoinfo.alias() ); + ExternalProgram cmd { args, ExternalProgram::Stderr_To_Stdout, false, -1, false, _chroot }; + + // draft: maybe integrate jobReport into Monitor + Monitor monitor( 800 ); + UserDataJobReport jobReport { "cmdout", "monitor" }; + jobReport.set( "CmdId", unsigned(cmd.getpid()) ); + jobReport.set( "CmdTag", str::numstring( cmd.getpid() ) ); + jobReport.set( "CmdName", "Repoverification plugin "+plugin_r ); + jobReport.set( "RepoInfo", data_r._repoinfo ); + + std::optional buffer; // Send output in exception is no one is listening + jobReport.debug( "?" ); // someone listening? + if ( not jobReport.haskey( "!" ) ) // no + buffer = std::ostringstream(); + + int ret = monitor( cmd, [&jobReport,&buffer,&cmd]( std::optional line_r )->bool { + if ( line_r ) { + DBG << "["< " << *line_r << endl; + if ( buffer ) (*buffer) << *line_r << endl; + return jobReport.data( *line_r ); + } + else { + return jobReport.debug( "ping" ); + } + return true; + } ); + + if ( ret ) { + const std::string & msg { str::Format( "Metadata rejected by '%1%' plugin (returned %2%)" ) % plugin_r % ret }; + + ExceptionType excp { msg }; + if ( buffer ) excp.addHistory( buffer->str() ); + excp.addHistory( str::Format( "%1%%2% returned %3%" ) % (_chroot.emptyOrRoot()?"":"("+_chroot.asString()+")") % pluginPath % ret ); + + ZYPP_THROW( excp ); + } + } + + const Pathname & plugindir() const + { return _watchPlugindir.path(); } + + private: + WatchFile _watchPlugindir; + Pathname _chroot; + bool _isNeeded = false; + }; + + /** \relates PluginRepoverification::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const PluginRepoverification::Impl & obj ) + { return str << "PluginRepoverification::Impl"; } + + /** \relates PluginRepoverification::Impl Verbose stream output */ + inline std::ostream & dumpOn( std::ostream & str, const PluginRepoverification::Impl & obj ) + { return str << obj; } + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PluginRepoverification + // + /////////////////////////////////////////////////////////////////// + + PluginRepoverification::PluginRepoverification() + : _pimpl( new Impl ) + {} + + PluginRepoverification::PluginRepoverification( Pathname plugindir_r, Pathname chroot_r ) + : _pimpl( new Impl( std::move(plugindir_r), std::move(chroot_r) ) ) + {} + + PluginRepoverification::~PluginRepoverification() + {} + + + bool PluginRepoverification::isNeeded() const + { return _pimpl->isNeeded(); } + + bool PluginRepoverification::checkIfNeeded() + { return _pimpl->checkIfNeeded(); } + + PluginRepoverification::Checker PluginRepoverification::getChecker( Pathname sigpathLocal_r, Pathname keypathLocal_r, RepoInfo repo_r ) const + { return Checker( new Checker::Impl( _pimpl, std::move(sigpathLocal_r), std::move(keypathLocal_r), std::move(repo_r) ) ); } + + + std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj ) + { return str << *obj._pimpl; } + + std::ostream & dumpOn( std::ostream & str, const PluginRepoverification & obj ) + { return dumpOn( str, *obj._pimpl ); } + + bool operator==( const PluginRepoverification & lhs, const PluginRepoverification & rhs ) + { return lhs._pimpl == rhs._pimpl; } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PluginRepoverification::Checker + // + /////////////////////////////////////////////////////////////////// + PluginRepoverification::Checker::Checker( Impl* pimpl_r ) + : _pimpl { pimpl_r } + {} + + PluginRepoverification::Checker::~Checker() + {} + + void PluginRepoverification::Checker::operator()( const Pathname & file_r ) const + { _pimpl->_parent->verifyWorkflow( file_r, _pimpl ); } + + + } // namespace repo + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/PluginRepoverification.h b/zypp/repo/PluginRepoverification.h new file mode 100644 index 0000000..c6e7620 --- /dev/null +++ b/zypp/repo/PluginRepoverification.h @@ -0,0 +1,128 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/PluginRepoverification.h + */ +#ifndef ZYPP_REPO_PLUGINREPOVERIFICATION_H +#define ZYPP_REPO_PLUGINREPOVERIFICATION_H + +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp_private +{ + using namespace zypp; + /////////////////////////////////////////////////////////////////// + namespace repo + { + /////////////////////////////////////////////////////////////////// + /// \class PluginRepoverificationCheckException + /// \brief Exceptiontype thrown if a plugins verification fails. + /////////////////////////////////////////////////////////////////// + class ZYPP_API PluginRepoverificationCheckException : public FileCheckException + { + public: + PluginRepoverificationCheckException( const std::string &msg ) + : FileCheckException(msg) + {} + }; + + /////////////////////////////////////////////////////////////////// + /// \class PluginRepoverification + /// \brief Repository metadata verification beyond GPG. + /// + /// Implements the repoverification plugin setup and workflow. Also + /// serves as factory for a file \ref FileChecker that can be passed + /// to e.g. \ref repo::Downloader when fetching the repos master index file. + /// + /// If a root dir is defined, plugin scripts will be executed chrooted. + /// + /// \see \ref plugin-repoverification for more details. + /////////////////////////////////////////////////////////////////// + class PluginRepoverification + { + friend std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj ); + friend std::ostream & dumpOn( std::ostream & str, const PluginRepoverification & obj ); + friend bool operator==( const PluginRepoverification & lhs, const PluginRepoverification & rhs ); + + using ExceptionType = PluginRepoverificationCheckException; + + public: + /** Default ctor, do nothing */ + PluginRepoverification(); + + /** Ctor monitoring a \a plugindir_r and optional chroot for plugin execution */ + PluginRepoverification( Pathname plugindir_r, Pathname chroot_r = Pathname() ); + + /** Dtor */ + ~PluginRepoverification(); + + public: + /** Whether the last \ref checkIfNeeded found plugins to execute at all. */ + bool isNeeded() const; + + /** Checks whether there are plugins to execute at all. */ + bool checkIfNeeded(); + + public: + /////////////////////////////////////////////////////////////////// + /// \class Checker + /// \brief \ref FileChecker checking all repoverification plugins. + /////////////////////////////////////////////////////////////////// + class Checker + { + public: + ~Checker(); + + /** Check the downloaded master index file. + * \throws PluginRepoverificationCheckException If a plugins verification fails. + */ + void operator()( const Pathname & file_r ) const; + + public: + class Impl; ///< Implementation class. + private: + friend class PluginRepoverification; ///< Factory for \ref Checker + Checker( Impl* pimpl ); + private: + RW_pointer _pimpl; ///< Pointer to implementation (ref). + }; + /////////////////////////////////////////////////////////////////// + + /** \ref FileChecker factory remembering the location of the master index files GPG signature and key. */ + Checker getChecker( Pathname sigpathLocal_r, Pathname keypathLocal_r, RepoInfo repo_r ) const; + + public: + class Impl; ///< Implementation class. + private: + RW_pointer _pimpl; ///< Pointer to implementation (ref). + }; + + /** \relates PluginRepoverification Stream output */ + std::ostream & operator<<( std::ostream & str, const PluginRepoverification & obj ); + + /** \relates PluginRepoverification Verbose stream output */ + std::ostream & dumOn( std::ostream & str, const PluginRepoverification & obj ); + + /** \relates PluginRepoverification */ + bool operator==( const PluginRepoverification & lhs, const PluginRepoverification & rhs ); + + /** \relates PluginRepoverification */ + inline bool operator!=( const PluginRepoverification & lhs, const PluginRepoverification & rhs ) + { return !( lhs == rhs ); } + + } // namespace repo + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_PLUGINREPOVERIFICATION_H diff --git a/zypp/repo/PluginServices.cc b/zypp/repo/PluginServices.cc new file mode 100644 index 0000000..696c98d --- /dev/null +++ b/zypp/repo/PluginServices.cc @@ -0,0 +1,90 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; +using std::stringstream; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + class PluginServices::Impl + { + public: + static void loadServices( const Pathname &path, + const PluginServices::ProcessService &callback ); + }; + + void PluginServices::Impl::loadServices( const Pathname &path, + const PluginServices::ProcessService & callback/*, + const ProgressData::ReceiverFnc &progress*/ ) + { + std::list entries; + if (PathInfo(path).isExist()) + { + if ( filesystem::readdir( entries, path, false ) != 0 ) + { + // TranslatorExplanation '%s' is a pathname + ZYPP_THROW(Exception(str::form(_("Failed to read directory '%s'"), path.c_str()))); + } + + //str::regex allowedServiceExt("^\\.service(_[0-9]+)?$"); + for_(it, entries.begin(), entries.end() ) + { + ServiceInfo service_info; + service_info.setAlias((*it).basename()); + Url url; + url.setPathName((*it).asString()); + url.setScheme("file"); + service_info.setUrl(url); + service_info.setType(ServiceType::PLUGIN); + service_info.setAutorefresh( true ); + DBG << "Plugin Service: " << service_info << endl; + callback(service_info); + } + + } + } + + PluginServices::PluginServices( const Pathname &path, + const ProcessService & callback/*, + const ProgressData::ReceiverFnc &progress */) + { + Impl::loadServices(path, callback/*, progress*/); + } + + PluginServices::~PluginServices() + {} + + std::ostream & operator<<( std::ostream & str, const PluginServices & obj ) + { + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/PluginServices.h b/zypp/repo/PluginServices.h new file mode 100644 index 0000000..910ce89 --- /dev/null +++ b/zypp/repo/PluginServices.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_REPO_PLUGINSERVICES_H +#define ZYPP_REPO_PLUGINSERVICES_H + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class ServiceInfo; + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + class PluginServices + { + friend std::ostream & operator<<( std::ostream & str, const PluginServices& obj ); + public: + + /** + * Callback definition. + * First parameter is a \ref ServiceInfo object with the resource. + * + * Return false from the callback to get a \ref AbortRequestException + * to be thrown and the processing to be cancelled. + */ + using ProcessService = function; + + /** Implementation */ + class Impl; + + public: + PluginServices(const Pathname &path, + const ProcessService & callback); + + /** + * Dtor + */ + ~PluginServices(); + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ServiceFileReader Stream output */ + std::ostream & operator<<( std::ostream & str, const PluginServices & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_LOCALSERVICES_H diff --git a/zypp/repo/RepoException.cc b/zypp/repo/RepoException.cc new file mode 100644 index 0000000..56aa3ee --- /dev/null +++ b/zypp/repo/RepoException.cc @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoException.cc + * +*/ +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // Repository related exceptions + // + /////////////////////////////////////////////////////////////////// + + RepoException::RepoException() + : Exception( "Repo exception" ) + {} + + RepoException::RepoException( const std::string & msg_r ) + : Exception( msg_r ) + {} + + RepoException::RepoException( const RepoInfo & info ) + : Exception( "Repo exception" ), _info( info ) + {} + + RepoException::RepoException( const RepoInfo & info, const std::string& msg_r ) + : Exception( msg_r ), _info( info ) + {} + + RepoException::~RepoException() throw() + {} + + std::ostream & RepoException::dumpOn( std::ostream & str ) const + { + str << "[" << _info.alias() << "|" << _info.url() << "] "; + return Exception::dumpOn( str ); + } + + /////////////////////////////////////////////////////////////////// + +#define DEF_CTORS( CLASS, MSG ) \ + CLASS::CLASS() : RepoException( MSG ) {} \ + CLASS::CLASS( const std::string & msg_r ) : RepoException( msg_r ) {} \ + CLASS::CLASS( const RepoInfo & service_r ) : RepoException( service_r, MSG ) {} \ + CLASS::CLASS( const RepoInfo & service_r, const std::string & msg_r ) : RepoException( service_r, msg_r ) {} + + DEF_CTORS( RepoNotCachedException, "Repository is not cached" ); + DEF_CTORS( RepoNoUrlException, "Repository has no or invalid url defined." ); + DEF_CTORS( RepoNoAliasException, "Repository has no alias defined." ); + DEF_CTORS( RepoInvalidAliasException, "Repository has an invalid alias." ); + DEF_CTORS( RepoNotFoundException, "Repository not found." ); + DEF_CTORS( RepoAlreadyExistsException, "Repository already exists." ); + DEF_CTORS( RepoUnknownTypeException, "Repository type can't be determined." ); + DEF_CTORS( RepoMetadataException, "Repository metadata not usable." ); + +#undef DEF_CTORS + + /////////////////////////////////////////////////////////////////// + // + // Service related exceptions + // + /////////////////////////////////////////////////////////////////// + + ServiceException::ServiceException() + : Exception( "Service exception" ) + {} + + ServiceException::ServiceException( const std::string & msg_r ) + : Exception( msg_r ) + {} + + ServiceException::ServiceException( const ServiceInfo & service_r ) + : Exception( "Service exception" ), _service( service_r ) + {} + + ServiceException::ServiceException( const ServiceInfo & service_r, const std::string & msg_r ) + : Exception( msg_r ), _service( service_r ) + {} + + ServiceException::~ServiceException() throw() + {} + + std::ostream & ServiceException::dumpOn( std::ostream & str ) const + { + str << "[" << _service.alias() << "|" << _service.url() << "] "; + return Exception::dumpOn( str ); + } + + /////////////////////////////////////////////////////////////////// + +#define DEF_CTORS( CLASS, MSG ) \ + CLASS::CLASS() : DEF_BASECLASS( MSG ) {} \ + CLASS::CLASS( const std::string & msg_r ) : DEF_BASECLASS( msg_r ) {} \ + CLASS::CLASS( const ServiceInfo & service_r ) : DEF_BASECLASS( service_r, MSG ) {} \ + CLASS::CLASS( const ServiceInfo & service_r, const std::string & msg_r ) : DEF_BASECLASS( service_r, msg_r ) {} + +#define DEF_BASECLASS ServiceException + DEF_CTORS( ServiceNoAliasException, "Service has no alias defined." ); + DEF_CTORS( ServiceInvalidAliasException, "Service has an invalid alias." ); + DEF_CTORS( ServiceAlreadyExistsException, "Service already exists." ); + DEF_CTORS( ServiceNoUrlException, "Service has no or invalid url defined." ); + + // sub classes: + DEF_CTORS( ServicePluginException, "PLUGIN service exception." ); + + /////////////////////////////////////////////////////////////////// + // sub class: ServicePluginException +#undef DEF_BASECLASS +#define DEF_BASECLASS ServicePluginException + DEF_CTORS( ServicePluginInformalException, "Service plugin has trouble providing the metadata but this should not be treated as error." ); + DEF_CTORS( ServicePluginImmutableException, _("Service plugin does not support changing an attribute.") ); + +#undef DEF_CTORS + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/RepoException.h b/zypp/repo/RepoException.h new file mode 100644 index 0000000..f2a9aaa --- /dev/null +++ b/zypp/repo/RepoException.h @@ -0,0 +1,289 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/parser/tagfile/RepoException.h + * +*/ +#ifndef ZYPP_REPO_REPOEXCEPTION_H +#define ZYPP_REPO_REPOEXCEPTION_H + +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /** \name Repository related exceptions. + */ + //@{ + + /** + * \short Exception for repository handling. + */ + class ZYPP_API RepoException : public Exception + { + public: + RepoException(); + RepoException( const std::string & msg_r ); + RepoException( const RepoInfo & info ); + RepoException( const RepoInfo & info, const std::string & msg_r ); + ~RepoException() throw() override; + + RepoInfo info() + { return _info; } + + std::string alias() + { return info().alias(); } + + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + + private: + RepoInfo _info; + }; + /////////////////////////////////////////////////////////////////// + + /** + * The repository cache is not built yet + * so you can't create the repostories from + * the cache. + */ + class ZYPP_API RepoNotCachedException : public RepoException + { + public: + RepoNotCachedException(); + RepoNotCachedException( const std::string & msg_r ); + RepoNotCachedException( const RepoInfo & info ); + RepoNotCachedException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** + * thrown when it was impossible to + * determine one url for this repo. + */ + class ZYPP_API RepoNoUrlException : public RepoException + { + public: + RepoNoUrlException(); + RepoNoUrlException( const std::string & msg_r ); + RepoNoUrlException( const RepoInfo & info ); + RepoNoUrlException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** + * thrown when it was impossible to + * determine an alias for this repo. + */ + class ZYPP_API RepoNoAliasException : public RepoException + { + public: + RepoNoAliasException(); + RepoNoAliasException( const std::string & msg_r ); + RepoNoAliasException( const RepoInfo & info ); + RepoNoAliasException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** + * Thrown when the repo alias is found to be invalid. + */ + class ZYPP_API RepoInvalidAliasException : public RepoException + { + public: + RepoInvalidAliasException(); + RepoInvalidAliasException( const std::string & msg_r ); + RepoInvalidAliasException( const RepoInfo & info ); + RepoInvalidAliasException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** + * thrown when it was impossible to + * match a repository + */ + class ZYPP_API RepoNotFoundException : public RepoException + { + public: + RepoNotFoundException(); + RepoNotFoundException( const std::string & msg_r ); + RepoNotFoundException( const RepoInfo & info ); + RepoNotFoundException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** + * Repository already exists and some unique + * attribute can't be duplicated. + */ + class ZYPP_API RepoAlreadyExistsException : public RepoException + { + public: + RepoAlreadyExistsException(); + RepoAlreadyExistsException( const std::string & msg_r ); + RepoAlreadyExistsException( const RepoInfo & info ); + RepoAlreadyExistsException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** + * thrown when it was impossible to + * determine this repo type. + */ + class ZYPP_API RepoUnknownTypeException : public RepoException + { + public: + RepoUnknownTypeException(); + RepoUnknownTypeException( const std::string & msg_r ); + RepoUnknownTypeException( const RepoInfo & info ); + RepoUnknownTypeException( const RepoInfo & info, const std::string & msg_r ); + }; + + /** + * thrown when it was impossible to + * use the raw metadata for this repo. + */ + class ZYPP_API RepoMetadataException : public RepoException + { + public: + RepoMetadataException(); + RepoMetadataException( const std::string & msg_r ); + RepoMetadataException( const RepoInfo & info ); + RepoMetadataException( const RepoInfo & info, const std::string & msg_r ); + }; + + //@} + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + + /** \name Service related exceptions. + */ + //@{ + + /** Base Exception for service handling. + */ + class ZYPP_API ServiceException : public Exception + { + public: + ServiceException(); + ServiceException( const std::string & msg_r ); + ServiceException( const ServiceInfo & service_r ); + ServiceException( const ServiceInfo & service_r, const std::string & msg_r ); + ~ServiceException() throw() override; + + ServiceInfo service() + { return _service; } + + std::string alias() + { return service().alias(); } + + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + + private: + ServiceInfo _service; + }; + /////////////////////////////////////////////////////////////////// + + /** Service without alias was used in an operation. + */ + class ZYPP_API ServiceNoAliasException : public ServiceException + { + public: + ServiceNoAliasException(); + ServiceNoAliasException( const std::string & msg_r ); + ServiceNoAliasException( const ServiceInfo & service_r ); + ServiceNoAliasException( const ServiceInfo & service_r, const std::string & msg_r ); + }; + + /** + * Thrown when the repo alias is found to be invalid. + */ + class ZYPP_API ServiceInvalidAliasException : public ServiceException + { + public: + ServiceInvalidAliasException(); + ServiceInvalidAliasException( const std::string & msg_r ); + ServiceInvalidAliasException( const ServiceInfo & info ); + ServiceInvalidAliasException( const ServiceInfo & info, const std::string & msg_r ); + }; + + /** Service already exists and some unique attribute can't be duplicated. + */ + class ZYPP_API ServiceAlreadyExistsException : public ServiceException + { + public: + ServiceAlreadyExistsException(); + ServiceAlreadyExistsException( const std::string & msg_r ); + ServiceAlreadyExistsException( const ServiceInfo & service_r ); + ServiceAlreadyExistsException( const ServiceInfo & service_r, const std::string & msg_r ); + }; + + /** Service has no or invalid url defined. + */ + class ZYPP_API ServiceNoUrlException : public ServiceException + { + public: + ServiceNoUrlException(); + ServiceNoUrlException( const std::string & msg_r ); + ServiceNoUrlException( const ServiceInfo & service_r ); + ServiceNoUrlException( const ServiceInfo & service_r, const std::string & msg_r ); + }; + //@} + + + /** \name PLUGIN Service related exceptions. + */ + //@{ + + /** PLUGIN Service related exceptions + */ + class ZYPP_API ServicePluginException : public ServiceException + { + public: + ServicePluginException(); + ServicePluginException( const std::string & msg_r ); + ServicePluginException( const ServiceInfo & service_r ); + ServicePluginException( const ServiceInfo & service_r, const std::string & msg_r ); + }; + + /** Service plugin has trouble providing the metadata but this should not be treated as error. + */ + class ZYPP_API ServicePluginInformalException : public ServicePluginException + { + public: + ServicePluginInformalException(); + ServicePluginInformalException( const std::string & msg_r ); + ServicePluginInformalException( const ServiceInfo & service_r ); + ServicePluginInformalException( const ServiceInfo & service_r, const std::string & msg_r ); + }; + + /** Service plugin is immutable. + */ + class ZYPP_API ServicePluginImmutableException : public ServicePluginException + { + public: + ServicePluginImmutableException(); + ServicePluginImmutableException( const std::string & msg_r ); + ServicePluginImmutableException( const ServiceInfo & service_r ); + ServicePluginImmutableException( const ServiceInfo & service_r, const std::string & msg_r ); + }; + //@} + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_PARSER_TAGFILE_PARSEEXCEPTION_H diff --git a/zypp/repo/RepoInfoBase.cc b/zypp/repo/RepoInfoBase.cc new file mode 100644 index 0000000..f36bbe3 --- /dev/null +++ b/zypp/repo/RepoInfoBase.cc @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoInfoBase.cc + * + */ +#include + +#include +#include + +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace repo + { + + /////////////////////////////////////////////////////////////////// + /// \class RepoInfoBase::Impl + /// \brief RepoInfoBase data + /////////////////////////////////////////////////////////////////// + struct RepoInfoBase::Impl + { + Impl() + : _enabled( indeterminate ) + , _autorefresh( indeterminate ) + {} + + Impl( const std::string & alias_r ) + : _enabled( indeterminate ) + , _autorefresh( indeterminate ) + { setAlias( alias_r ); } + + public: + TriBool _enabled; + TriBool _autorefresh; + std::string _alias; + std::string _escaped_alias; + RepoVariablesReplacedString _name; + Pathname _filepath; + + public: + + void setAlias( const std::string & alias_r ) + { + _alias = _escaped_alias = alias_r; + // replace slashes with underscores + str::replaceAll( _escaped_alias, "/", "_" ); + } + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfoBase + // + /////////////////////////////////////////////////////////////////// + + RepoInfoBase::RepoInfoBase() + : _pimpl( new Impl() ) + {} + + RepoInfoBase::RepoInfoBase(const std::string & alias) + : _pimpl( new Impl(alias) ) + {} + + RepoInfoBase::~RepoInfoBase() + {} + + void RepoInfoBase::setEnabled( bool enabled ) + { _pimpl->_enabled = enabled; } + + void RepoInfoBase::setAutorefresh( bool autorefresh ) + { _pimpl->_autorefresh = autorefresh; } + + void RepoInfoBase::setAlias( const std::string &alias ) + { _pimpl->setAlias(alias); } + + void RepoInfoBase::setName( const std::string &name ) + { _pimpl->_name.raw() = name; } + + void RepoInfoBase::setFilepath( const Pathname &filepath ) + { _pimpl->_filepath = filepath; } + + // true by default (if not set by setEnabled()) + bool RepoInfoBase::enabled() const + { return indeterminate(_pimpl->_enabled) ? true : (bool) _pimpl->_enabled; } + + // false by default (if not set by setAutorefresh()) + bool RepoInfoBase::autorefresh() const + { return indeterminate(_pimpl->_autorefresh) ? false : (bool) _pimpl->_autorefresh; } + + std::string RepoInfoBase::alias() const + { return _pimpl->_alias; } + + std::string RepoInfoBase::escaped_alias() const + { return _pimpl->_escaped_alias; } + + std::string RepoInfoBase::name() const + { + if ( rawName().empty() ) + return alias(); + return repo::RepoVariablesStringReplacer()( rawName() ); + } + + std::string RepoInfoBase::rawName() const + { return _pimpl->_name.raw(); } + + std::string RepoInfoBase::label() const + { + if ( ZConfig::instance().repoLabelIsAlias() ) + return alias(); + return name(); + } + + Pathname RepoInfoBase::filepath() const + { return _pimpl->_filepath; } + + + std::ostream & RepoInfoBase::dumpOn( std::ostream & str ) const + { + str << "--------------------------------------" << std::endl; + str << "- alias : " << alias() << std::endl; + if ( ! rawName().empty() ) + str << "- name : " << rawName() << std::endl; + str << "- enabled : " << enabled() << std::endl; + str << "- autorefresh : " << autorefresh() << std::endl; + + return str; + } + + std::ostream & RepoInfoBase::dumpAsIniOn( std::ostream & str ) const + { + // we save the original data without variable replacement + str << "[" << alias() << "]" << endl; + if ( ! rawName().empty() ) + str << "name=" << rawName() << endl; + str << "enabled=" << (enabled() ? "1" : "0") << endl; + str << "autorefresh=" << (autorefresh() ? "1" : "0") << endl; + + return str; + } + + std::ostream & RepoInfoBase::dumpAsXmlOn( std::ostream & str, const std::string & content ) const + { + return str << "" << endl; + } + + std::ostream & operator<<( std::ostream & str, const RepoInfoBase & obj ) + { + return obj.dumpOn(str); + } + + } // namespace repo + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/RepoInfoBase.h b/zypp/repo/RepoInfoBase.h new file mode 100644 index 0000000..28669cc --- /dev/null +++ b/zypp/repo/RepoInfoBase.h @@ -0,0 +1,199 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoInfoBase.h + * + */ +#ifndef REPOINFOBASE_H_ +#define REPOINFOBASE_H_ + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RepoInfoBase + // + /** + * \short Base class implementing common features of \ref RepoInfo and + * \ref ServiceInfo. + * + * \note Name is subject to repo variable replacement + * (\see \ref RepoVariablesStringReplacer). + */ + class ZYPP_API RepoInfoBase + { + friend std::ostream & operator<<( std::ostream & str, const RepoInfoBase & obj ); + + public: + RepoInfoBase(); + RepoInfoBase(const std::string &alias); + virtual ~RepoInfoBase(); + + RepoInfoBase(const RepoInfoBase &) = default; + RepoInfoBase(RepoInfoBase &&) noexcept = default; + RepoInfoBase &operator=(const RepoInfoBase &) = default; + RepoInfoBase &operator=(RepoInfoBase &&) noexcept = default; + + /** + * unique identifier for this source. If not specified + * It should be generated from the base url. + * + * Normally, in a .repo file the section name is used + * ( [somerepo] ) + */ + std::string alias() const; + + /** + * Same as alias(), just escaped in a way to be a valid file name. + */ + std::string escaped_alias() const; + + /** + * \short Repository name + * + * Short label or description of the repository. Defaults to \ref alias. + * Subject to repo variable replacement (\see \ref RepoVariablesStringReplacer). + * ie: "SUSE Linux 10.2 updates" + */ + std::string name() const; + + /** The raw metadata name (no default, no variables replaced). */ + std::string rawName() const; + + /** + * \short Label for use in messages for the user interface. + * + * Returns an alias or name, according to ZConfig::repoLabelIsAlias(). + */ + std::string label() const; + + /** User string: \ref label (alias or name) */ + std::string asUserString() const + { return label(); } + + /** + * If enabled is false, then this repository must be ignored as if does + * not exists, except when checking for duplicate alias. + */ + bool enabled() const; + + /** + * If true, the repostory must be refreshed before creating resolvables + * from it + */ + bool autorefresh() const; + + /** + * \short File where this repo was read from + * + * \note could be an empty pathname for repo + * infos created in memory. + */ + Pathname filepath() const; + + + public: + + /** + * set the repository alias \see alias + * \param alias + */ + void setAlias( const std::string &alias ); + + /** + * set the repository name \see name + * \param name + */ + void setName( const std::string &name ); + + /** + * enable or disable the repository \see enabled + * \param enabled + */ + void setEnabled( bool enabled ); + + /** + * enable or disable autorefresh \see autorefresh + * \param enabled + */ + void setAutorefresh( bool autorefresh ); + + /** + * \short set the path to the .repo file + * + * The path to the .repo file where this repository + * was defined, or empty if nowhere. + * + * \param path File path + */ + void setFilepath( const Pathname &filename ); + + /** + * Write a human-readable representation of this RepoInfoBase object + * into the \a str stream. Useful for logging. + */ + virtual std::ostream & dumpOn( std::ostream & str ) const; + + /** + * Write this RepoInfoBase object into \a str in a .repo
(ini) file format. + * Raw values, no variable replacement. + */ + virtual std::ostream & dumpAsIniOn( std::ostream & str ) const; + + /** + * Write an XML representation of this object with content (if available). + * Repo variables replaced. + */ + virtual std::ostream & dumpAsXmlOn( std::ostream & str, const std::string & content = "" ) const; + + struct Impl; + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RepoInfoBase */ + inline bool operator==( const RepoInfoBase & lhs, const RepoInfoBase & rhs ) + { return lhs.alias() == rhs.alias(); } + + /** \relates RepoInfoBase */ + inline bool operator!=( const RepoInfoBase & lhs, const RepoInfoBase & rhs ) + { return lhs.alias() != rhs.alias(); } + + inline bool operator<( const RepoInfoBase & lhs, const RepoInfoBase & rhs ) + { return lhs.alias() < rhs.alias(); } + + /** \relates RepoInfoBase Stream output */ + std::ostream & operator<<( std::ostream & str, const RepoInfoBase & obj ); + + /** \relates RepoInfoBase */ + using RepoInfoBase_Ptr = shared_ptr; + /** \relates RepoInfoBase */ + using RepoInfoBase_constPtr = shared_ptr; + + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif /*REPOINFOBASE_H_*/ diff --git a/zypp/repo/RepoMirrorList.cc b/zypp/repo/RepoMirrorList.cc new file mode 100644 index 0000000..0d6649f --- /dev/null +++ b/zypp/repo/RepoMirrorList.cc @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoMirrorList.cc + * +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { + /////////////////////////////////////////////////////////////////// + /// \class RepoMirrorListTempProvider + /// \brief Provide access to downloaded mirror list (in temp space) + /// \ingroup g_RAII + /// + /// Tempspace (and mirror list) are deleted when provider goes out + /// of scope. + struct RepoMirrorListTempProvider + { + RepoMirrorListTempProvider() + {} + RepoMirrorListTempProvider( Pathname localfile_r ) + : _localfile(std::move( localfile_r )) + {} + RepoMirrorListTempProvider( const Url & url_r ) + { + Url abs_url( url_r ); + abs_url.setPathName( "/" ); + abs_url.setQueryParam( "mediahandler", "curl" ); + _access.reset( new MediaSetAccess( abs_url ) ); + _localfile = _access->provideFile( url_r.getPathName() ); + } + + const Pathname & localfile() const + { return _localfile; } + + private: + shared_ptr _access; + Pathname _localfile; + }; + /////////////////////////////////////////////////////////////////// + + inline std::vector RepoMirrorListParseXML( const Pathname &tmpfile ) + { + InputStream tmpfstream (tmpfile); + media::MetaLinkParser metalink; + metalink.parse(tmpfstream); + return metalink.getUrls(); + } + + inline std::vector RepoMirrorListParseTXT( const Pathname &tmpfile ) + { + InputStream tmpfstream (tmpfile); + std::vector my_urls; + std::string tmpurl; + while (getline(tmpfstream.stream(), tmpurl)) + { + if ( tmpurl[0] == '#' ) + continue; + try { + my_urls.push_back(Url(tmpurl)); + } + catch (...) + {;} // ignore malformed urls + } + return my_urls; + } + + /** Parse a local mirrorlist \a listfile_r and return usable URLs */ + inline std::vector RepoMirrorListParse( const Url & url_r, const Pathname & listfile_r, bool mirrorListForceMetalink_r ) + { + USR << url_r << " " << listfile_r << endl; + + std::vector mirrorurls; + if ( mirrorListForceMetalink_r || url_r.asString().find( "/metalink" ) != std::string::npos ) + mirrorurls = RepoMirrorListParseXML( listfile_r ); + else + mirrorurls = RepoMirrorListParseTXT( listfile_r ); + + + std::vector ret; + for ( auto & murl : mirrorurls ) + { + if ( murl.getScheme() != "rsync" ) + { + size_t delpos = murl.getPathName().find("repodata/repomd.xml"); + if( delpos != std::string::npos ) + { + murl.setPathName( murl.getPathName().erase(delpos) ); + } + ret.push_back( murl ); + + if ( ret.size() >= 4 ) // why 4? + break; + } + } + return ret; + } + + } // namespace + /////////////////////////////////////////////////////////////////// + + RepoMirrorList::RepoMirrorList( const Url & url_r, const Pathname & metadatapath_r, bool mirrorListForceMetalink_r ) + { + if ( url_r.getScheme() == "file" ) + { + // never cache for local mirrorlist + _urls = RepoMirrorListParse( url_r, url_r.getPathName(), mirrorListForceMetalink_r ); + } + else if ( ! PathInfo( metadatapath_r).isDir() ) + { + // no cachedir + RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of any downloaded files + _urls = RepoMirrorListParse( url_r, provider.localfile(), mirrorListForceMetalink_r ); + } + else + { + // have cachedir + Pathname cachefile( metadatapath_r ); + if ( mirrorListForceMetalink_r || url_r.asString().find( "/metalink" ) != std::string::npos ) + cachefile /= "mirrorlist.xml"; + else + cachefile /= "mirrorlist.txt"; + + zypp::filesystem::PathInfo cacheinfo( cachefile ); + if ( !cacheinfo.isFile() || cacheinfo.mtime() < time(NULL) - (long) ZConfig::instance().repo_refresh_delay() * 60 ) + { + DBG << "Getting MirrorList from URL: " << url_r << endl; + RepoMirrorListTempProvider provider( url_r ); // RAII: lifetime of downloaded file + + // Create directory, if not existing + DBG << "Copy MirrorList file to " << cachefile << endl; + zypp::filesystem::assert_dir( metadatapath_r ); + zypp::filesystem::hardlinkCopy( provider.localfile(), cachefile ); + } + + _urls = RepoMirrorListParse( url_r, cachefile, mirrorListForceMetalink_r ); + if( _urls.empty() ) + { + DBG << "Removing Cachefile as it contains no URLs" << endl; + zypp::filesystem::unlink( cachefile ); + } + } + } + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/RepoMirrorList.h b/zypp/repo/RepoMirrorList.h new file mode 100644 index 0000000..89a556f --- /dev/null +++ b/zypp/repo/RepoMirrorList.h @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_REPO_MIRRORLIST_H_ +#define ZYPP_REPO_MIRRORLIST_H_ + +#include +#include +#include + +namespace zypp +{ + namespace repo + { + class RepoMirrorList + { + public: + RepoMirrorList( const Url & url_r, const Pathname & metadatapath_r, bool mirrorListForceMetalink_r ); + + RepoMirrorList( const Url & url_r ) + : RepoMirrorList( url_r, Pathname(), false ) + {} + + const std::vector & getUrls() const + { return _urls; } + + std::vector & getUrls() + { return _urls; } + + private: + std::vector _urls; + }; + } // ns repo +} // ns zypp + +#endif + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/repo/RepoProvideFile.cc b/zypp/repo/RepoProvideFile.cc new file mode 100644 index 0000000..830b0a3 --- /dev/null +++ b/zypp/repo/RepoProvideFile.cc @@ -0,0 +1,350 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/source/RepoProvideFile.cc + * +*/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; +using std::set; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // provideFile + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + /** Hack to extract progress information from media::DownloadProgressReport. + * We redirect the static report triggered from RepoInfo::provideFile + * to feed the ProvideFilePolicy callbacks in addition to any connected + * media::DownloadProgressReport. + */ + struct DownloadFileReportHack : public callback::ReceiveReport + { + using BaseType = callback::ReceiveReport; + using RedirectType = function; + + DownloadFileReportHack(RedirectType &&redirect_r) + : _oldRec(Distributor::instance().getReceiver()), + _redirect(std::move(redirect_r)) { + connect(); + } + + DownloadFileReportHack(const DownloadFileReportHack &) = delete; + DownloadFileReportHack(DownloadFileReportHack &&) = delete; + DownloadFileReportHack &operator=(const DownloadFileReportHack &) = delete; + DownloadFileReportHack &operator=(DownloadFileReportHack &&) = delete; + + ~DownloadFileReportHack() override + { if ( _oldRec ) Distributor::instance().setReceiver( *_oldRec ); else Distributor::instance().noReceiver(); } + + void start( const Url & file, Pathname localfile ) override + { + if ( _oldRec ) + _oldRec->start( file, localfile ); + else + BaseType::start( file, localfile ); + } + + bool progress( int value, const Url & file, double dbps_avg = -1, double dbps_current = -1 ) override + { + bool ret = true; + if ( _oldRec ) + ret &= _oldRec->progress( value, file, dbps_avg, dbps_current ); + if ( _redirect ) + ret &= _redirect( value ); + return ret; + } + + Action problem( const Url & file, Error error, const std::string & description ) override + { + if ( _oldRec ) + return _oldRec->problem( file, error, description ); + return BaseType::problem( file, error, description ); + } + void finish( const Url & file, Error error, const std::string & reason ) override + { + if ( _oldRec ) + _oldRec->finish( file, error, reason ); + else + BaseType::finish( file, error, reason ); + } + + private: + Receiver * _oldRec; + RedirectType _redirect; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + ManagedFile provideFile( RepoInfo repo_r, + const OnMediaLocation & loc_r, + const ProvideFilePolicy & policy_r ) + { + RepoMediaAccess access; + return access.provideFile(std::move(repo_r), loc_r, policy_r ); + } + + /////////////////////////////////////////////////////////////////// + class RepoMediaAccess::Impl + { + public: + Impl(ProvideFilePolicy &&defaultPolicy_r) + : _defaultPolicy(std::move(defaultPolicy_r)) {} + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() + { + std::map >::iterator it; + for ( it = _medias.begin(); + it != _medias.end(); + ++it ) + { + it->second->release(); + } + } + + /** Provide a MediaSetAccess for \c url with label and verifier adjusted. + * + * As the same url (e.g. \c 'dvd:///' ) might be used for multiple repos + * we must always adjust the repo specific data (label,verifier). + * + * \todo This mixture of media and repos specific data is fragile. + */ + shared_ptr mediaAccessForUrl( const Url &url, RepoInfo repo ) + { + std::map >::const_iterator it; + it = _medias.find(url); + shared_ptr media; + if ( it != _medias.end() ) + { + media = it->second; + } + else + { + media.reset( new MediaSetAccess(url) ); + _medias[url] = media; + } + setVerifierForRepo( std::move(repo), media ); + return media; + } + + private: + void setVerifierForRepo( const RepoInfo& repo, const shared_ptr& media ) + { + // Always set the MediaSetAccess label. + media->setLabel( repo.name() ); + + // set a verifier if the repository has it + + Pathname mediafile = repo.metadataPath() + "/media.1/media"; + if ( ! repo.metadataPath().empty() ) + { + if ( PathInfo(mediafile).isExist() ) + { + std::map, RepoInfo>::const_iterator it; + it = _verifier.find(media); + if ( it != _verifier.end() ) + { + if ( it->second.alias() == repo.alias() ) + { + // this media is already using this repo verifier + return; + } + } + + SUSEMediaVerifier lverifier { mediafile }; + if ( lverifier ) { + DBG << "Verifier for repo '" << repo.alias() << "':" << lverifier << endl; + for ( media::MediaNr i = 1; i <= lverifier.totalMedia(); ++i ) { + media::MediaVerifierRef verifier( new repo::SUSEMediaVerifier( lverifier, i ) ); + media->setVerifier( i, verifier); + } + _verifier[media] = repo; + } + else { + WAR << "Invalid verifier for repo '" << repo.alias() << "' in '" << repo.metadataPath() << "': " << lverifier << endl; + } + } + else + { + DBG << "No media verifier for repo '" << repo.alias() << "' media.1/media does not exist in '" << repo.metadataPath() << "'" << endl; + } + } + else + { + WAR << "'" << repo.alias() << "' metadata path is empty. Can't set verifier. Probably this repository does not come from RepoManager." << endl; + } + } + + private: + std::map, RepoInfo> _verifier; + std::map > _medias; + + public: + ProvideFilePolicy _defaultPolicy; + }; + /////////////////////////////////////////////////////////////////// + + + RepoMediaAccess::RepoMediaAccess( ProvideFilePolicy defaultPolicy_r ) + : _impl( new Impl( std::move(defaultPolicy_r) ) ) + {} + + RepoMediaAccess::~RepoMediaAccess() + {} + + void RepoMediaAccess::setDefaultPolicy( const ProvideFilePolicy & policy_r ) + { _impl->_defaultPolicy = policy_r; } + + const ProvideFilePolicy & RepoMediaAccess::defaultPolicy() const + { return _impl->_defaultPolicy; } + + ManagedFile RepoMediaAccess::provideFile( const RepoInfo& repo_r, + const OnMediaLocation & loc_rx, + const ProvideFilePolicy & policy_r ) + { + const OnMediaLocation locWithPath( OnMediaLocation(loc_rx).prependPath( repo_r.path() ) ); + + MIL << locWithPath << endl; + // Arrange DownloadFileReportHack to recieve the source::DownloadFileReport + // and redirect download progress triggers to call the ProvideFilePolicy + // callback. + DownloadFileReportHack dumb( std::bind( std::mem_fn(&ProvideFilePolicy::progress), std::ref(policy_r), _1 ) ); + + RepoException repo_excpt(repo_r, + str::form(_("Can't provide file '%s' from repository '%s'"), + locWithPath.filename().c_str(), + repo_r.alias().c_str() ) ); + + if ( repo_r.baseUrlsEmpty() ) + { + repo_excpt.remember(RepoException(_("No url in repository."))); + ZYPP_THROW(repo_excpt); + } + + Fetcher fetcher; + fetcher.addCachePath( repo_r.packagesPath() ); + MIL << "Added cache path " << repo_r.packagesPath() << endl; + + // Test whether download destination is writable, if not + // switch into the tmpspace (e.g. bnc#755239, download and + // install srpms as user). + Pathname destinationDir( repo_r.packagesPath() ); + + PathInfo pi( destinationDir ); + if ( ! pi.isExist() ) + { + // try to create it... + assert_dir( destinationDir ); + pi(); + } + if ( geteuid() != 0 && ! pi.userMayW() ) + { + WAR << "Destination dir '" << destinationDir << "' is not user writable, using tmp space." << endl; + destinationDir = getZYpp()->tmpPath() / destinationDir; + assert_dir( destinationDir ); + fetcher.addCachePath( destinationDir ); + MIL << "Added cache path " << destinationDir << endl; + } + + // Suppress (interactive) media::MediaChangeReport if we in have multiple basurls (>1) + media::ScopedDisableMediaChangeReport guard( repo_r.baseUrlsSize() > 1 ); + + for ( RepoInfo::urls_const_iterator it = repo_r.baseUrlsBegin(); + it != repo_r.baseUrlsEnd(); + /* incremented in the loop */ ) + { + Url url( *it ); + ++it; + try + { + MIL << "Providing file of repo '" << repo_r.alias() << "' from " << url << endl; + shared_ptr access = _impl->mediaAccessForUrl( url, repo_r ); + + fetcher.enqueue( locWithPath, policy_r.fileChecker() ); + fetcher.start( destinationDir, *access ); + + // reached if no exception has been thrown, so this is the correct file + ManagedFile ret( destinationDir + locWithPath.filename() ); + if ( !repo_r.keepPackages() ) + { + ret.setDispose( filesystem::unlink ); + } + + MIL << "provideFile at " << ret << endl; + return ret; + } + catch ( const UserRequestException & excpt ) + { + ZYPP_RETHROW( excpt ); + } + catch ( const FileCheckException & excpt ) + { + ZYPP_RETHROW( excpt ); + } + catch ( const Exception &e ) + { + ZYPP_CAUGHT( e ); + + repo_excpt.remember(e); + + WAR << "Trying next url" << endl; + continue; + } + } // iteration over urls + + ZYPP_THROW(repo_excpt); + return ManagedFile(); // not reached + } + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/RepoProvideFile.h b/zypp/repo/RepoProvideFile.h new file mode 100644 index 0000000..9555479 --- /dev/null +++ b/zypp/repo/RepoProvideFile.h @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoProvideFile.h + * +*/ +#ifndef ZYPP_REPO_REPOPROVIDEFILE_H +#define ZYPP_REPO_REPOPROVIDEFILE_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // provideFile + // + /////////////////////////////////////////////////////////////////// + + /** Provide a file from a Repository. + * Let \a source_r provide the file described by \a loc_r. In case + * \a loc_r contains a checksum, the file is verified. \a policy_r + * provides callback hooks for download progress reporting and behaviour + * on failed checksum verification. + * + * \throws Exception + */ + ManagedFile provideFile( RepoInfo repo_r, + const OnMediaLocation & loc_r, + const ProvideFilePolicy & policy_r = ProvideFilePolicy() ); + + /** + * \short Provides files from different repos + * + * Class that allows to get files from repositories + * It handles automatically setting media verifiers if the + * repo is cached, and reuses media set access opened for + * repositories during its scope, so you can provide + * files from different repositories in different order + * without opening and closing medias all the time + */ + class ZYPP_API RepoMediaAccess + { + public: + /** Ctor taking the default \ref ProvideFilePolicy. */ + RepoMediaAccess(ProvideFilePolicy defaultPolicy_r = ProvideFilePolicy() ); + ~RepoMediaAccess(); + + /** Provide a file from a Repository. + * Let \a source_r provide the file described by \a loc_r. In case + * \a loc_r contains a checksum, the file is verified. \a policy_r + * provides callback hooks for download progress reporting and behaviour + * on failed checksum verification. + * + * \throws Exception + * \todo Investigate why this needs a non-const Repository as arg. + */ + ManagedFile provideFile( const RepoInfo& repo_r, + const OnMediaLocation & loc_r, + const ProvideFilePolicy & policy_r ); + + /** \overload Using the current default \ref ProvideFilePolicy. */ + ManagedFile provideFile( RepoInfo repo_r, const OnMediaLocation & loc_r ) + { return provideFile( std::move(repo_r), loc_r, defaultPolicy() ); } + + public: + /** Set a new default \ref ProvideFilePolicy. */ + void setDefaultPolicy( const ProvideFilePolicy & policy_r ); + + /** Get the current default \ref ProvideFilePolicy. */ + const ProvideFilePolicy & defaultPolicy() const; + + private: + class Impl; + RW_pointer _impl; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_REPOPROVIDEFILE_H diff --git a/zypp/repo/RepoType.cc b/zypp/repo/RepoType.cc new file mode 100644 index 0000000..8cd4566 --- /dev/null +++ b/zypp/repo/RepoType.cc @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include "RepoType.h" + +namespace zypp +{ +namespace repo +{ + /////////////////////////////////////////////////////////////////// + namespace + { + static NamedValue & table() + { + static NamedValue & _t( *new NamedValue ); + if ( _t.empty() ) + { + _t( RepoType::RPMMD_e ) | "rpm-md" |"rpm"|"rpmmd"|"repomd"|"yum"|"up2date"; + _t( RepoType::YAST2_e ) | "yast2" |"yast"|"susetags"; + _t( RepoType::RPMPLAINDIR_e ) | "plaindir"; + _t( RepoType::NONE_e ) | "N/A" |"n/a"|"NONE"| "none"; + } + return _t; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + const RepoType RepoType::RPMMD ( RepoType::RPMMD_e ); + const RepoType RepoType::YAST2 ( RepoType::YAST2_e ); + const RepoType RepoType::RPMPLAINDIR ( RepoType::RPMPLAINDIR_e ); + const RepoType RepoType::NONE ( RepoType::NONE_e ); + + RepoType::RepoType(const std::string & strval_r) + : _type(parse(strval_r)) + {} + + RepoType::Type RepoType::parse( const std::string & strval_r ) + { + RepoType::Type type; + if ( ! table().getValue( str::toLower( strval_r ), type ) ) + { + ZYPP_THROW( RepoUnknownTypeException( "Unknown repository type '" + strval_r + "'") ); + } + return type; + } + + const std::string & RepoType::asString() const + { + return table().getName( _type ); + } + + + } // ns repo +} // ns zypp + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/repo/RepoType.h b/zypp/repo/RepoType.h new file mode 100644 index 0000000..e995b5a --- /dev/null +++ b/zypp/repo/RepoType.h @@ -0,0 +1,73 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_REPO_TYPE_H_ +#define ZYPP_REPO_TYPE_H_ + +#include +#include +#include + +namespace zypp +{ + namespace repo + { + + /** + * \short Repository type enumeration + * + * Repositories can be from varous types + * ... + */ + struct ZYPP_API RepoType + { + static const RepoType RPMMD; + static const RepoType YAST2; + static const RepoType RPMPLAINDIR; + static const RepoType NONE; + + enum Type + { + NONE_e, + RPMMD_e, + YAST2_e, + RPMPLAINDIR_e, + }; + + RepoType() : _type(NONE_e) {} + + RepoType(Type type) : _type(type) {} + + explicit RepoType(const std::string & strval_r); + + Type toEnum() const { return _type; } + + RepoType::Type parse(const std::string & strval_r); + + const std::string & asString() const; + + Type _type; + }; + + + inline std::ostream & operator<<( std::ostream & str, const RepoType & obj ) + { return str << obj.asString(); } + + inline bool operator==(const RepoType & obj1, const RepoType & obj2) + { return obj1._type == obj2._type; } + + inline bool operator!=(const RepoType & obj1, const RepoType & obj2) + { return ! (obj1 == obj2); } + + } // ns repo +} // ns zypp + +#endif + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/repo/RepoVariables.cc b/zypp/repo/RepoVariables.cc new file mode 100644 index 0000000..2cb65d2 --- /dev/null +++ b/zypp/repo/RepoVariables.cc @@ -0,0 +1,587 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define ZYPP_DBG_VAREXPAND 0 +#if ( ZYPP_DBG_VAREXPAND ) +#warning ZYPP_DBG_VAREXPAND is on +using std::cout; +#endif // ZYPP_DBG_VAREXPAND + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + namespace env + { + /** Use faked releasever (e.g. for 'zupper dup' to next distro version */ + inline std::string ZYPP_REPO_RELEASEVER() + { + const char * env = getenv("ZYPP_REPO_RELEASEVER"); + return( env ? env : "" ); + } + } + + /////////////////////////////////////////////////////////////////// + namespace repo + { + /////////////////////////////////////////////////////////////////// + // RepoVarExpand + /////////////////////////////////////////////////////////////////// + namespace + { + /////////////////////////////////////////////////////////////////// + /// \class FindVar + /// \brief Helper scanning for variable definitions in a string + /////////////////////////////////////////////////////////////////// + struct FindVar + { + bool _embedded; ///< A (formerly) embedded string may have esacped \c $, \c closebrace and \c backslash + const char * _sbeg; ///< start of string to scan + const char * _vbeg; ///< [$]{variable:-word} / [$]{variable} / if embedded also on [\\] + const char * _nbeg; ///< ${[v]ariable:-word} / ${[v]ariable} + const char * _nend; ///< ${variable[:]-word} / ${variable[}] + const char * _vend; ///< ${variable:-word}[] / ${variable}[] + const char * _send; ///< end of scan (next $ or nullptr if done) + + FindVar( const std::string & str_r, bool embedded_r ) + : _embedded( embedded_r ) + , _sbeg( str_r.c_str() ) + , _vbeg( nullptr ) + , _nbeg( nullptr ) + , _nend( nullptr ) + , _vend( nullptr ) + , _send( findVarStart( _sbeg ) ) + {} + + /** Nullptr in _send indicates we scanned the whole string. */ + bool done() const + { return !_send; } + + /** Advance to first/next var if there is one */ + bool nextVar() + { + if ( done() ) + return false; + + do { + if ( _vbeg && !_vend ) // loop internal: no findVarEnd at current $; skip it + _send = findVarStart( _vbeg+1 ); + _vbeg = _send; // next $ or null if string end + _nbeg = _nend = _vend = _send = nullptr; + if ( ! _vbeg ) // done! + return false; + } while( ! findVarEnd() ); + + return true; + } + + /** Valid _vend indicates valid var data in scan. */ + bool hasVar() const + { return _vend; } + + // + // Methods below are only valid if hasVar() == true + // + + /** Return the full var text */ + std::string var() const + { return std::string( _vbeg, _vend ); } + + /** Return the var name */ + std::string varName() const + { return std::string( _nbeg, _nend ); } + + /** Whether this is a conditional var (${..:[+-]...}) */ + bool varIsConditional() const + { return( *(_vbeg+1) == '{' && *_nend == ':' ); } + + /** The var type: \c \, \c $, \c - , \c + + * \li \c \ backslash escaped literal + * \li \c $ plain variable + * \li \c - conditional: default value + * \li \c + conditional: alternate value + */ + int varType() const + { return( varIsConditional() ? *(_nend+1) : *_vbeg ); } + + /** Return embedded value in conditional vars or empty string */ + std::string varEmbedded() const + { return( varIsConditional() ? std::string( _nend+2, _vend-1 ) : std::string() ); } + + + /** Have unwritten data before var? */ + bool hasVarPrefix() const + { return ( _sbeg != _vbeg ); } + + /** Return unwritten data before var */ + std::string varPrefix() const + { return std::string( _sbeg, _vbeg ); } + + /** Indicate all data up to _vend were written */ + void wroteVar() + { _sbeg = _vend; } + + private: + /** Return next \c $ */ + const char * findVarStart( const char * sbeg_r ) const + { + for ( ; *sbeg_r; ++sbeg_r ) + if ( *sbeg_r == '$' || ( _embedded && *sbeg_r == '\\' ) ) + return sbeg_r; + return nullptr; + } + + /** Valid var name char */ + bool isnamech( int ch ) const + { return ch == '_' || isalnum( ch ); } + + /** Scan for a valid variable starting at _vbeg (storing the values) */ + bool findVarEnd() + { + // asserted: *_vbeg == '$' || '\\' + if ( ! findVarEnd( _vbeg, _nbeg, _nend, _vend ) ) + return false; + _send = findVarStart( _vend ); + return true; + } + + /** Skip over valid variable starting at vbeg (return end in \a vend). */ + const char * findVarEnd( const char * vbeg ) const + { + // asserted: *_vbeg == '$' + const char * nbeg = nullptr; + const char * nend = nullptr; + const char * vend = nullptr; + findVarEnd( vbeg, nbeg, nend, vend ); + return vend; + } + + /** Scan for a valid variable starting at vbeg (const version returning the values). */ + bool findVarEnd( const char * vbeg, const char *& nbeg, const char *& nend, const char *& vend ) const + { + // embedded only: handle backslash escaped chars + if ( *_vbeg == '\\' ) + { + nbeg = vbeg+1; + if ( *nbeg == '$' + || *nbeg == '}' + || *nbeg == '\\' ) + { + nend = vend = vbeg+2; + return true; + } + return false; + } + + // asserted: *vbeg == '$' + // vbeg: [$]{variable:-word} / [$]{variable} + // nbeg: ${[v]ariable:-word} / ${[v]ariable} + bool braced = ( *(vbeg+1) == '{' ); //} + nbeg = vbeg+( braced ? 2 : 1 ); + if ( !isnamech( *nbeg ) ) // don't allow empty var name + return false; + for ( nend = nbeg+1; isnamech( *nend ); ++nend ) + {;} // skip over var name + // nend: ${variable[:]-word} / ${variable[}] + + // vend: ${variable:-word}[] / ${variable}[] + // stay with ( vend == nullptr ) until you know it's valid + if ( braced ) + { + if ( *nend == '}' ) + { + vend = nend+1; + } + else if ( *nend == ':' ) + { + const char * scan = nend+1; + if ( *scan == '+' || *scan == '-' ) + { + ++scan; + // find first not escaped '}' + while ( *scan ) + { + if ( *scan == '\\' ) + { + ++scan; // next char is skipped + if ( *scan ) + ++scan; + } + else if ( *scan == '$' ) + { + // an embedded var? + if ( ! (scan = findVarEnd( scan )) ) + return false; + } + else if ( *scan == '}' ) + { + vend = scan+1; // ==> unesacped '}', we're done! + break; + } + else + ++scan; // literal + } + // ( ! *scan ) => end of string while looking for unesacped '}' + } + else + ; // err: ':' not followed by '+' or '-' + } + else + ; // err: braced name must end with '}' or ':' + } + else + { + vend = nend; // un-braced + } + return( vend != nullptr ); + } + }; + + bool _expand( std::string &, const std::string & value_r, unsigned level_r, RepoVarExpand::VarRetriever & varRetriever_r ); + + inline std::string expand( const std::string & value_r, unsigned level_r, RepoVarExpand::VarRetriever & varRetriever_r ) + { + std::string ret; + if ( ! _expand( ret, value_r, level_r, varRetriever_r ) ) + ret = value_r; + return ret; + } + + inline std::string expand( std::string && value_r, unsigned level_r, RepoVarExpand::VarRetriever & varRetriever_r ) + { + std::string ret; + if ( ! _expand( ret, value_r, level_r, varRetriever_r ) ) + ret = std::move(value_r); + return ret; + } + + /** Expand variables in \a value_r depending on \a level-r + * level_r > 0 may have escaped chars outside braces. + */ + inline bool _expand( std::string & result_r, const std::string & value_r, unsigned level_r, RepoVarExpand::VarRetriever & varRetriever_r ) + { +#if ( ZYPP_DBG_VAREXPAND ) + cout << std::string( 2*level_r, ' ' ) << "\033[7m>>" << value_r << "<<\033[27m" << endl; + std::ostringstream dbg; + const char * dbgsbeg = value_r.c_str(); // track vars we already added to dbg + unsigned dbgi = 0; // color 1-5 var / 6 moved value_r + dbg << std::string( 2*level_r, ' ' ) << ">>"; +#endif // ZYPP_DBG_VAREXPAND + + bool expanded = false; + + if ( ! value_r.empty() ) + { + FindVar scan( value_r, level_r ); // level_r > 0 is embedded + while ( scan.nextVar() ) + { + static const std::string _emptyValue; + const std::string *const knownVar = ( varRetriever_r ? varRetriever_r( scan.varName() ) : nullptr ); + const std::string & varValue( knownVar ? *knownVar : _emptyValue ); + +#if ( ZYPP_DBG_VAREXPAND ) + dbg << std::string(dbgsbeg,scan._vbeg) << "\033[3" << ((dbgi%5)+1) << "m" << scan.var() << "\033[0m"; + cout << dbg.str() << "|<< " << scan.varName() << " " << (knownVar?"("+varValue+")":"-") << " {" << scan.varEmbedded() << "}" << endl; + dbgsbeg = scan._vend; + dbgi++; +#endif // ZYPP_DBG_VAREXPAND + + bool mustSubstitute = false; // keep original text per default + std::string substitutionValue; + + int varType = scan.varType(); + if ( varType == '$' ) // plain var + { + if ( knownVar ) + { + mustSubstitute = true; + substitutionValue = varValue; + } + else + ; // keep original text per default + } + else if ( varType == '-' ) // ':-' default value + { + mustSubstitute = true; + if ( varValue.empty() ) + substitutionValue = expand( scan.varEmbedded(), level_r+1, varRetriever_r ); + else + substitutionValue = varValue; + } + else if ( varType == '+' ) // ':+' alternate value + { + mustSubstitute = true; + if ( ! varValue.empty() ) + substitutionValue = expand( scan.varEmbedded(), level_r+1, varRetriever_r ); + else + ; // empty substitutionValue + } + else if ( varType == '\\' ) // backslash escaped literal (in varName) + { + mustSubstitute = true; + substitutionValue = scan.varName(); + } + else + ; // keep original text per default + + if ( mustSubstitute ) + { + if ( scan.hasVarPrefix() ) + result_r += scan.varPrefix(); + if ( ! substitutionValue.empty() ) + result_r += substitutionValue; + scan.wroteVar(); // this moves scan._sbeg so we can later see what's already written + } + } + +#if ( ZYPP_DBG_VAREXPAND ) + dbg << std::string( dbgsbeg ) << (scan._sbeg == value_r.c_str() ? "<<\033[36m(moved)\033[0m" : ""); +#endif // ZYPP_DBG_VAREXPAND + + // handle unwritten data: + if ( scan._sbeg != value_r.c_str() ) + { + expanded = true; + if ( *scan._sbeg ) + result_r += std::string( scan._sbeg ); + } + else + ; // no replacements at all + } + +#if ( ZYPP_DBG_VAREXPAND ) + dbg << "<<"; + cout << dbg.str() << endl; + cout << std::string( 2*level_r, ' ' ) << "\033[36m->" << result_r << "<-\033[0m" << endl; +#endif // ZYPP_DBG_VAREXPAND + return expanded; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + std::string RepoVarExpand::operator()( const std::string & value_r, VarRetriever varRetriever_r ) const + { return expand( value_r, 0, varRetriever_r ); } + + std::string RepoVarExpand::operator()( std::string && value_r, VarRetriever varRetriever_r ) const + { return expand( std::move(value_r), 0, varRetriever_r ); } + + /////////////////////////////////////////////////////////////////// + // RepoVariables*Replace + /////////////////////////////////////////////////////////////////// + namespace + { + class RepoVarsMap : public std::map + { + public: + static RepoVarsMap & instance() + { static RepoVarsMap _instance; return _instance; } + + static const std::string * lookup( const std::string & name_r ) + { return instance()._lookup( name_r ); } + + private: + const std::string * _lookup( const std::string & name_r ) + { + // Safe guard in case the caller does not own a zypp instance. In this case + // getZYpp()->getTarget() in checkOverride would create a zypp instance which + // would clear the variables parsed so far. + auto guard { getZYpp() }; + + if ( empty() ) // at init / after reset + { + // load user definitions from vars.d + filesystem::dirForEach( ZConfig::instance().repoManagerRoot() / ZConfig::instance().varsPath(), + filesystem::matchNoDots(), bind( &RepoVarsMap::parse, this, _1, _2 ) ); + // releasever_major/_minor are per default derived from releasever. + // If releasever is userdefined, inject missing _major/_minor too. + deriveFromReleasever( "releasever", /*dont't overwrite user defined values*/false ); + + dumpOn( DBG ); + // add builtin vars except for releasever{,_major,_minor} (see checkOverride) + { + const Arch & arch( ZConfig::instance().systemArchitecture() ); + { + std::string & var( operator[]( "arch" ) ); + if ( var.empty() ) var = arch.asString(); + } + { + std::string & var( operator[]( "basearch" ) ); + if ( var.empty() ) var = arch.baseArch().asString(); + } + } + } + + const std::string * ret = checkOverride( name_r ); + if ( !ret ) + { + // get value from map + iterator it = find( name_r ); + if ( it != end() ) + ret = &(it->second); + } + + return ret; + } + + std::ostream & dumpOn( std::ostream & str ) const + { + for ( auto && kv : *this ) + { + str << '{' << kv.first << '=' << kv.second << '}' << endl; + } + return str; + } + + private: + /** Get first line from file */ + bool parse( const Pathname & dir_r, const std::string & str_r ) + { + std::ifstream file( (dir_r/str_r).c_str() ); + operator[]( str_r ) = str::getline( file, /*trim*/false ); + return true; + } + + /** Derive \c releasever_major/_minor from \c releasever, keeping or overwrititing existing values. */ + void deriveFromReleasever( const std::string & stem_r, bool overwrite_r ) + { + if ( count( stem_r ) ) // releasever is defined.. + { + const std::string & stem_major( stem_r+"_major" ); + const std::string & stem_minor( stem_r+"_minor" ); + if ( overwrite_r ) + splitReleaseverTo( operator[]( stem_r ), &operator[]( stem_major ), &operator[]( stem_minor ) ); + else + splitReleaseverTo( operator[]( stem_r ), + count( stem_major ) ? nullptr : &operator[]( stem_major ), + count( stem_minor ) ? nullptr : &operator[]( stem_minor ) ); + } + } + + /** Split \c releasever at \c '.' and store major/minor parts as requested. */ + void splitReleaseverTo( const std::string & releasever_r, std::string * major_r, std::string * minor_r ) const + { + if ( major_r || minor_r ) + { + std::string::size_type pos = releasever_r.find( '.' ); + if ( pos == std::string::npos ) + { + if ( major_r ) *major_r = releasever_r; + if ( minor_r ) minor_r->clear(); + } + else + { + if ( major_r ) *major_r = releasever_r.substr( 0, pos ); + if ( minor_r ) *minor_r = releasever_r.substr( pos+1 ) ; + } + } + } + + /** Check for conditions overwriting the (user) defined values. */ + const std::string * checkOverride( const std::string & name_r ) + { + /////////////////////////////////////////////////////////////////// + // Always check for changing releasever{,_major,_minor} (bnc#943563) + if ( str::startsWith( name_r, "releasever" ) + && ( name_r.size() == 10 + || strcmp( name_r.c_str()+10, "_minor" ) == 0 + || strcmp( name_r.c_str()+10, "_major" ) == 0 ) ) + { + std::string val( env::ZYPP_REPO_RELEASEVER() ); + if ( !val.empty() ) + { + // $ZYPP_REPO_RELEASEVER always overwrites any defined value + if ( val != operator[]( "$releasever" ) ) + { + operator[]( "$releasever" ) = std::move(val); + deriveFromReleasever( "$releasever", /*overwrite previous values*/true ); + } + return &operator[]( "$"+name_r ); + } + else if ( !count( name_r ) ) + { + // No user defined value, so we follow the target + Target_Ptr trg( getZYpp()->getTarget() ); + if ( trg ) + val = trg->distributionVersion(); + else + val = Target::distributionVersion( Pathname()/*guess*/ ); + + if ( val != operator[]( "$_releasever" ) ) + { + operator[]( "$_releasever" ) = std::move(val); + deriveFromReleasever( "$_releasever", /*overwrite previous values*/true ); + } + return &operator[]( "$_"+name_r ); + } + // else: + return nullptr; // get user value from map + } + /////////////////////////////////////////////////////////////////// + + return nullptr; // get user value from map + } + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + std::string RepoVariablesStringReplacer::operator()( const std::string & value ) const + { + return RepoVarExpand()( value, RepoVarsMap::lookup ); + } + std::string RepoVariablesStringReplacer::operator()( std::string && value ) const + { + return RepoVarExpand()( std::move(value), RepoVarsMap::lookup ); + } + + Url RepoVariablesUrlReplacer::operator()( const Url & value ) const + { + Url::ViewOptions toReplace = value.getViewOptions() - url::ViewOption::WITH_USERNAME - url::ViewOption::WITH_PASSWORD; + // Legacy: Not 100% correct because it substitutes inside the 'proxypass=' value, + // but this was done before as well. The final fix will have to keep the proxypasswd + // out side the url in a cedential file. + Url tmpurl { value }; + tmpurl.setViewOptions( toReplace ); + const std::string & replaced( RepoVarExpand()( hotfix1050625::asString( tmpurl ), RepoVarsMap::lookup ) ); + + Url newurl; + if ( !replaced.empty() ) + { + newurl = replaced; + newurl.setUsername( value.getUsername( url::E_ENCODED ), url::E_ENCODED ); + newurl.setPassword( value.getPassword( url::E_ENCODED ), url::E_ENCODED ); + newurl.setViewOptions( value.getViewOptions() ); + } + return newurl; + } + } // namespace repo + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////// +namespace zyppintern +{ + using namespace zypp; + // internal helper called when re-acquiring the lock + void repoVariablesReset() + { repo::RepoVarsMap::instance().clear(); } + +} // namespace zyppintern +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/RepoVariables.h b/zypp/repo/RepoVariables.h new file mode 100644 index 0000000..6c22c99 --- /dev/null +++ b/zypp/repo/RepoVariables.h @@ -0,0 +1,141 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/RepoVariables.h + */ +#ifndef ZYPP_REPO_VARIABLES_H_ +#define ZYPP_REPO_VARIABLES_H_ + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace repo + { + /////////////////////////////////////////////////////////////////// + /// \class RepoVarExpand + /// \brief Functor expanding repo variables in a string + /// + /// Known variables are determined by a callback function taking a variable + /// name and returning a pointer to the variable value or \c nullptr if unset. + /// + /// The \c $ character introduces variable expansion. A valid variable name + /// is any non-empty case-insensitive sequence of [[:alnum:]_]. + /// The variable name to be expanded may be enclosed in braces, which are + /// optional but serve to protect the variable to be expanded from characters + /// immediately following it which could be interpreted as part of the name. + /// + /// When braces are used, the matching ending brace is the first \c } not + /// escaped by a backslash and not within an embedded variable expansion. + /// Within braces only \c $, \c } and \c backslash are escaped by a + /// backslash. There is no escaping outside braces, to stay comaptible + /// with \c YUM (which does not support braces). + /// + ///
    + ///
  • \c ${variable} + /// If \c variable is unset the original is preserved like in \c YUM. + /// Otherwise, the value of \c variable is substituted.
  • + /// + ///
  • \c ${variable:-word} (default value) + /// If \c variable is unset or empty, the expansion of \c word is substituted. + /// Otherwise, the value of \c variable is substituted.
  • + /// + ///
  • \c ${variable:+word} (alternate value) + /// If variable is unset or empty nothing is substituted. + /// Otherwise, the expansion of \c word is substituted.
  • + ///
+ struct ZYPP_API RepoVarExpand + { + /** Function taking a variable name and returning a pointer to the variable value or \c nullptr if unset. */ + using VarRetriever = function; + + /** Return a copy of \a value_r with embedded variables expanded. */ + std::string operator()( const std::string & value_r, VarRetriever varRetriever_r ) const; + + /** \overload moving */ + std::string operator()( std::string && value_r, VarRetriever varRetriever_r ) const; + }; + + /** + * \short Functor replacing repository variables + * + * Replaces the built-in '$arch', '$basearch' and '$releasever' ans also + * custom repo variables (\see \ref zypp-repovars) in a string with the + * assigned values. + * + * Additionally $releasever_major and $releasever_minor can be used + * to refer to $releasever major number (everything up to the 1st \c '.' ) + * and minor number (everything after the 1st \c '.' ). + * + * \note The $releasever value is overwritten by the environment + * variable \c ZYPP_REPO_RELEASEVER. This might be handy for + * distribution upogrades like this: + * \code + * $ export ZYPP_REPO_RELEASEVER=13.2 + * $ zypper lr -u + * $ zypper dup + * ....upgrades to 13.2... + * \endcode + * The same can be achieved by using zyppers --releasever global option: + * \code + * $ zypper --releasever 13.2 lr -u + * $ zypper --releasever 13.2 dup + * ....upgrades to 13.2... + * \endcode + * (see \ref zypp-envars) + * + * \code + * Example: + * ftp://user:secret@site.net/$arch/ -> ftp://user:secret@site.net/i686/ + * http://site.net/?basearch=$basearch -> http://site.net/?basearch=i386 + * \endcode + * + * \see \ref RepoVarExpand for supported variable syntax. + */ + struct ZYPP_API RepoVariablesStringReplacer + { + std::string operator()( const std::string & value_r ) const; + + /** \overload moving */ + std::string operator()( std::string && value_r ) const; + }; + + /** + * \short Functor replacing repository variables + * + * Replaces repository variables in the URL (except for user/pass inside authority) + * \see RepoVariablesStringReplacer + */ + struct ZYPP_API RepoVariablesUrlReplacer + { + Url operator()( const Url & url_r ) const; + }; + } // namespace repo + /////////////////////////////////////////////////////////////////// + + /** \relates RepoVariablesStringReplacer Helper managing repo variables replaced strings */ + using RepoVariablesReplacedString = base::ValueTransform; + + /** \relates RepoVariablesStringReplacer Helper managing repo variables replaced string lists */ + using RepoVariablesReplacedStringList = base::ContainerTransform, repo::RepoVariablesStringReplacer>; + + /** \relates RepoVariablesUrlReplacer Helper managing repo variables replaced urls */ + using RepoVariablesReplacedUrl = base::ValueTransform; + + /** \relates RepoVariablesUrlReplacer Helper managing repo variables replaced url lists */ + using RepoVariablesReplacedUrlList = base::ContainerTransform, repo::RepoVariablesUrlReplacer>; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif diff --git a/zypp/repo/SUSEMediaVerifier.cc b/zypp/repo/SUSEMediaVerifier.cc new file mode 100644 index 0000000..c9756ec --- /dev/null +++ b/zypp/repo/SUSEMediaVerifier.cc @@ -0,0 +1,209 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include + +using std::endl; + +namespace zypp +{ + namespace repo + { + /////////////////////////////////////////////////////////////////// + /// Data parsed from a media.1/media file + /// + struct SMVData + { + SMVData( const Pathname & path_r ) + { + std::ifstream inp( path_r.c_str() ); + if ( !inp ) { + ERR << "Can't setup a SUSEMediaVerifier from file: " << path_r.asString() << endl; + return; + } + getline( inp, _mediaVendor ); + getline( inp, _mediaIdent ); + std::string buffer; + getline( inp, buffer ); + str::strtonum( buffer, _totalMedia ); + //if ( !_totalMedia ) _totalMedia = 1; + } + + /** Validate object in a boolean context: valid */ + explicit operator bool() const + { return valid(); } + + /** Data considered to be valid if we have vendor and ident. */ + bool valid() const + { return ! (_mediaVendor.empty() || _mediaIdent.empty()); } + + /** Whether \a rhs belongs to the same media set. */ + bool matches( const SMVData & rhs ) const + { return valid() && rhs._mediaVendor == _mediaVendor && rhs._mediaIdent == _mediaIdent; } + + std::string _mediaVendor; + std::string _mediaIdent; + media::MediaNr _totalMedia = 0; + }; + + /** \relates SMVData Stream output */ + inline std::ostream & operator<<( std::ostream & str, const SMVData & obj ) + { return str << "[" << obj._mediaVendor << "|" << obj._mediaIdent << "/" << obj._totalMedia << "]"; } + + + /////////////////////////////////////////////////////////////////// + /// SUSEMediaVerifier::Impl + /// + /// Data parsed from the media.1/media file can be shared among different + /// verifiers for this media. + /// + /// This type of verifier however is convenience to tell in advance if the + /// wrong media is inserted. Errors when retrieving the data are logged, + /// but won't let any verification fail. If the medium happens to be right, + /// everything is fine. If it's wrong, download time will tell. + /// + class SUSEMediaVerifier::Impl + { + public: + Impl( const Pathname & path_r, media::MediaNr mediaNr_r ) + : _smvData { new SMVData( path_r ) } + , _mediaNr { mediaNr_r } + {} + + Impl( const Impl & rhs, media::MediaNr mediaNr_r ) + : _smvData { rhs._smvData } + , _mediaNr { mediaNr_r } + {} + + const SMVData & smvData() const + { return *_smvData; } + + media::MediaNr mediaNr() const + { return _mediaNr; } + + Pathname mediaFilePath( media::MediaNr mediaNr_r = 0 ) const + { + str::Format fmt { "/media.%d/media" }; + fmt % str::numstring( mediaNr_r ? mediaNr_r : _mediaNr ); + return fmt.str(); + } + + std::string expectedAsUserString() const + { + // Translator: %1% the expected medium number; %2% the total number of media in the set; %3% the ident file on the medium. + str::Format fmt { _("Expected medium %1%/%2% identified by file '%3%' with content:") }; + return str::Str() + << ( fmt % mediaNr() % smvData()._totalMedia % mediaFilePath() ) << endl + << " " << smvData()._mediaVendor << endl + << " " << smvData()._mediaIdent; + } + + private: + shared_ptr _smvData; + media::MediaNr _mediaNr = 1; + }; + + /** \relates SUSEMediaVerifier::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const SUSEMediaVerifier::Impl & obj ) + { return str << obj.smvData() << "(" << obj.mediaNr() << ")"; } + + + /////////////////////////////////////////////////////////////////// + // SUSEMediaVerifier + /////////////////////////////////////////////////////////////////// + + SUSEMediaVerifier::SUSEMediaVerifier( const Pathname & path_r, media::MediaNr mediaNr_r ) + : _pimpl { new Impl( path_r, mediaNr_r ) } + {} + + SUSEMediaVerifier::SUSEMediaVerifier( const SUSEMediaVerifier & rhs, media::MediaNr mediaNr_r ) + : _pimpl { new Impl( *rhs._pimpl, mediaNr_r ) } + {} + + SUSEMediaVerifier::~SUSEMediaVerifier() + {} + + bool SUSEMediaVerifier::valid() const + { return _pimpl->smvData().valid(); } + + const std::string & SUSEMediaVerifier::vendor() const + { return _pimpl->smvData()._mediaVendor; } + + const std::string & SUSEMediaVerifier::ident() const + { return _pimpl->smvData()._mediaIdent; } + + media::MediaNr SUSEMediaVerifier::totalMedia() const + { return _pimpl->smvData()._totalMedia; } + + media::MediaNr SUSEMediaVerifier::mediaNr() const + { return _pimpl->mediaNr(); } + + + bool SUSEMediaVerifier::isDesiredMedia( const media::MediaHandler & ref ) const + { + bool ret = true; // optimistic return unless we definitely know it does not match + + const SMVData & smvData = _pimpl->smvData(); + if ( ! smvData ) + return ret; // we have no valid data + + // bsc#1180851: If there is just one not-volatile medium in the set + // tolerate a missing (vanished) media identifier and let the URL rule. + bool relaxed = smvData._totalMedia == 1 && ! Url::schemeIsVolatile( ref.protocol() ); + SEC << smvData << endl; + SEC << ref.protocol() << " " << Url::schemeIsVolatile( ref.protocol() ) << endl; + + // if we have a downloading URL and can do relaxed verification we do not check the media file again + if ( relaxed && Url::schemeIsDownloading( ref.protocol() ) ) { + DBG << "Skipping verification due to downloading medium" << std::endl; + return ret; + } + + Pathname mediaFile { _pimpl->mediaFilePath() }; + try { + ref.provideFile( OnMediaLocation(mediaFile) ); + mediaFile = ref.localPath( mediaFile ); + } + catch ( media::MediaFileNotFoundException & excpt_r ) + { + if ( relaxed ) { + ZYPP_CAUGHT( excpt_r ); + return ret; + } + excpt_r.addHistory( _pimpl->expectedAsUserString() ); + ZYPP_RETHROW( excpt_r ); + } + catch ( media::MediaNotAFileException & excpt_r ) + { + if ( relaxed ) { + ZYPP_CAUGHT( excpt_r ); + return ret; + } + excpt_r.addHistory( _pimpl->expectedAsUserString() ); + ZYPP_CAUGHT( excpt_r ); return ret; + } + + SMVData remote { mediaFile }; + ret = smvData.matches( remote ); + if ( ! ret ) { + DBG << "expect: " << smvData << " medium " << mediaNr() << endl; + DBG << "remote: " << remote << endl; + } + return ret; + } + + std::ostream & operator<<( std::ostream & str, const SUSEMediaVerifier & obj ) + { return str << *obj._pimpl; } + + } // namespace repo +} // namespace zypp diff --git a/zypp/repo/SUSEMediaVerifier.h b/zypp/repo/SUSEMediaVerifier.h new file mode 100644 index 0000000..3c6e3b5 --- /dev/null +++ b/zypp/repo/SUSEMediaVerifier.h @@ -0,0 +1,86 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_SUSE_MEDIAVERIFIER_H +#define ZYPP_SUSE_MEDIAVERIFIER_H + +#include + +#include +#include +#include + +namespace zypp +{ + namespace repo + { + /////////////////////////////////////////////////////////////////// + /// + /// \short Implementation of the traditional SUSE media verifier + /// + class SUSEMediaVerifier : public media::MediaVerifierBase + { + public: + /** Ctor creating a verifier by parsing media file + * + * \param path_r Path to media.1/media kind file + */ + explicit SUSEMediaVerifier( const Pathname & path_r, media::MediaNr mediaNr_r = 1 ); + + /** Ctor cloning a verifier for a different \a mediaNr_r + * + * \param path_r Path to media.1/media kind file + */ + SUSEMediaVerifier( const SUSEMediaVerifier & rhs, media::MediaNr mediaNr_r ); + + /** Dtor */ + ~SUSEMediaVerifier() override; + + public: + /** Validate object in a boolean context: valid */ + explicit operator bool() const + { return valid(); } + + /** Data considered to be valid if we have vendor and ident. */ + bool valid() const; + + /** Medias expected vendor string. */ + const std::string & vendor() const; + + /** Medias expected ident string. */ + const std::string & ident() const; + + /** The total number of media in this set (or 0 if not known). */ + media::MediaNr totalMedia() const; + + /** Media number expected by this verifier (starts with 1). */ + media::MediaNr mediaNr() const; + + public: + /** Check if \ref_r accesses the desired media. + * + * The check is optimistic. If we can't get reliable data from the server, + * we nevertheless assume the media is valid. File downloads will fail if + * this was not true. + */ + bool isDesiredMedia( const media::MediaHandler & ref_r ) const override; + + public: + class Impl; ///< Implementation class. + friend std::ostream & operator<<( std::ostream & str, const SUSEMediaVerifier & obj ); + private: + RW_pointer _pimpl; ///< Pointer to implementation. + }; + + /** \relates SUSEMediaVerifier Stream output */ + //std::ostream & operator<<( std::ostream & str, const SUSEMediaVerifier & obj ); + + } // namespace repo +} // namespace zypp +#endif diff --git a/zypp/repo/ServiceType.cc b/zypp/repo/ServiceType.cc new file mode 100644 index 0000000..2358be6 --- /dev/null +++ b/zypp/repo/ServiceType.cc @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include +#include +#include +#include +#include "ServiceType.h" + +namespace zypp +{ + namespace repo + { + /////////////////////////////////////////////////////////////////// + namespace + { + static NamedValue & table() + { + static NamedValue & _t( *new NamedValue ); + if ( _t.empty() ) + { + _t( ServiceType::RIS_e ) | "ris" |"RIS"|"nu"|"NU"; + _t( ServiceType::PLUGIN_e ) | "plugin" |"PLUGIN"; + _t( ServiceType::NONE_e ) | "N/A" |"n/a"|"NONE"|"none"; + } + return _t; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + const ServiceType ServiceType::RIS(ServiceType::RIS_e); + const ServiceType ServiceType::NONE(ServiceType::NONE_e); + const ServiceType ServiceType::PLUGIN(ServiceType::PLUGIN_e); + + ServiceType::ServiceType(const std::string & strval_r) + : _type(parse(strval_r)) + {} + + ServiceType::Type ServiceType::parse(const std::string & strval_r) + { + ServiceType::Type type; + if ( ! table().getValue( str::toLower( strval_r ), type ) ) + { + ZYPP_THROW( RepoUnknownTypeException( "Unknown service type '" + strval_r + "'") ); + } + return type; + } + + const std::string & ServiceType::asString() const + { + return table().getName( _type ); + } + + + } // ns repo +} // ns zypp + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/repo/ServiceType.h b/zypp/repo/ServiceType.h new file mode 100644 index 0000000..9b15b82 --- /dev/null +++ b/zypp/repo/ServiceType.h @@ -0,0 +1,83 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_SERVICE_TYPE_H_ +#define ZYPP_SERVICE_TYPE_H_ + +#include +#include + +namespace zypp +{ + namespace repo + { + + /** + * \short Service type enumeration + * + * Currently we have only RIS service, but more can come later. + */ + struct ZYPP_API ServiceType + { + /** + * Repository Index Service (RIS) + * (formerly known as 'Novell Update' (NU) service) + */ + static const ServiceType RIS ZYPP_API; + /** No service set. */ + static const ServiceType NONE ZYPP_API; + /** + * Plugin services are scripts installed on + * your system that provide the package manager with + * repositories. + * + * The mechanism used to create this repository list + * is completely up to the script + */ + static const ServiceType PLUGIN ZYPP_API; + + enum Type + { + NONE_e, + RIS_e, + PLUGIN_e, + }; + + ServiceType() : _type(NONE_e) {} + + ServiceType(Type type) : _type(type) {} + + explicit ServiceType(const std::string & strval_r); + + Type toEnum() const { return _type; } + + ServiceType::Type parse(const std::string & strval_r); + + const std::string & asString() const; + + Type _type; + }; + + + inline std::ostream & operator<<( std::ostream & str, const ServiceType & obj ) + { return str << obj.asString(); } + + inline bool operator==(const ServiceType & obj1, const ServiceType & obj2) + { return obj1._type == obj2._type; } + + inline bool operator!=(const ServiceType & obj1, const ServiceType & obj2) + { return ! (obj1 == obj2); } + + + } // ns repo +} // ns zypp + +#endif /* ZYPP_SERVICE_TYPE_H_ */ + +// vim: set ts=2 sts=2 sw=2 et ai: diff --git a/zypp/repo/SrcPackageProvider.cc b/zypp/repo/SrcPackageProvider.cc new file mode 100644 index 0000000..a6a95a7 --- /dev/null +++ b/zypp/repo/SrcPackageProvider.cc @@ -0,0 +1,42 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/SrcPackageProvider.cc + * +*/ +#include +#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace repo + { + + SrcPackageProvider::SrcPackageProvider( repo::RepoMediaAccess & access_r ) + : _access( access_r ) + {} + + SrcPackageProvider::~SrcPackageProvider() + {} + + ManagedFile SrcPackageProvider::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ) const + { return _access.provideFile( srcPackage_r->repoInfo(), srcPackage_r->location() ); } + + } // namespace repo + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/repo/SrcPackageProvider.h b/zypp/repo/SrcPackageProvider.h new file mode 100644 index 0000000..b8e5b44 --- /dev/null +++ b/zypp/repo/SrcPackageProvider.h @@ -0,0 +1,61 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/repo/SrcPackageProvider.h + * +*/ +#ifndef ZYPP_REPO_SRCPACKAGEPROVIDER_H +#define ZYPP_REPO_SRCPACKAGEPROVIDER_H + +#include + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace repo + { ///////////////////////////////////////////////////////////////// + + class RepoMediaAccess; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SrcPackageProvider + // + /** */ + class ZYPP_API SrcPackageProvider : private base::NonCopyable + { + public: + /** Ctor */ + SrcPackageProvider( repo::RepoMediaAccess & access_r ); + /** Dtor */ + ~SrcPackageProvider(); + + public: + /** Provide SrcPackage in a local file. */ + ManagedFile provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ) const; + + private: + RepoMediaAccess & _access; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace repo + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_REPO_SRCPACKAGEPROVIDER_H diff --git a/zypp/repo/yum/RepomdFileCollector.cc b/zypp/repo/yum/RepomdFileCollector.cc new file mode 100644 index 0000000..8eb7692 --- /dev/null +++ b/zypp/repo/yum/RepomdFileCollector.cc @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#include "RepomdFileCollector.h" +#include +#include +#include +#include + +namespace zypp::env +{ + bool ZYPP_REPOMD_WITH_OTHER() + { + static bool val = [](){ + const char * env = getenv("ZYPP_REPOMD_WITH_OTHER"); + return( env && zypp::str::strToBool( env, true ) ); + }(); + return val; + } + + bool ZYPP_REPOMD_WITH_FILELISTS() + { + static bool val = [](){ + const char * env = getenv("ZYPP_REPOMD_WITH_FILELISTS"); + return( env && zypp::str::strToBool( env, true ) ); + }(); + return val; + } +} + +namespace zypp::repo::yum +{ + + namespace + { + inline OnMediaLocation loc_with_path_prefix( OnMediaLocation loc_r, const Pathname & prefix_r ) + { + if ( ! prefix_r.empty() && prefix_r != "/" ) + loc_r.changeFilename( prefix_r / loc_r.filename() ); + return loc_r; + } + + // search old repository file to run the delta algorithm on + Pathname search_deltafile( const Pathname & dir, const Pathname & file ) + { + Pathname deltafile; + if ( ! PathInfo(dir).isDir() ) + return deltafile; + + // Strip the checksum preceding the file stem so we can look for an + // old *-primary.xml which may contain some reusable blocks. + std::string base { file.basename() }; + size_t hypoff = base.find( '-' ); + if ( hypoff != std::string::npos ) + base.replace( 0, hypoff + 1, "" ); + + std::list retlist; + if ( ! filesystem::readdir( retlist, dir, false ) ) + { + for ( const auto & fn : retlist ) + { + if ( str::endsWith( fn, base ) ) + deltafile = fn; + } + } + if ( !deltafile.empty() ) + return dir/deltafile; + + return deltafile; + } + } // namespace + + + /** + * \class RepomdFileCollector + * \brief Helper filtering the files offered by a RepomdFileReader + * + * Collected files from repomd.xml: + * File types: + * type (plain) + * type_db (sqlite, ignored by zypp) + * type_zck (zchunk, preferred) + * Localized type: + * susedata.LOCALE + */ + RepomdFileCollector::RepomdFileCollector( const Pathname &destDir_r ) + : _destDir { destDir_r } + { + addWantedLocale( ZConfig::instance().textLocale() ); + for ( const Locale & it : ZConfig::instance().repoRefreshLocales() ) + addWantedLocale( it ); + } + + RepomdFileCollector::~RepomdFileCollector() + { } + + /** The callback invoked by the RepomdFileReader. + * It's a pity, but in the presence of separate "type" and "type_zck" entries, + * we have to scan the whole file before deciding what to download.... + */ + bool RepomdFileCollector::collect(const OnMediaLocation &loc_r, const std::string &typestr_r) + { + if ( str::endsWith( typestr_r, "_db" ) ) + return true; // skip sqlitedb + + bool zchk { str::endsWith( typestr_r, "_zck" ) }; +#if defined(LIBSOLVEXT_FEATURE_ZCHUNK_COMPRESSION) + const std::string & basetype { zchk ? typestr_r.substr( 0, typestr_r.size()-4 ) : typestr_r }; +#else + if ( zchk ) + return true; // skip zchunk if not supported by libsolv + const std::string & basetype { typestr_r }; +#endif + + // filter well known resource types + if ( basetype == "other" && not env::ZYPP_REPOMD_WITH_OTHER() ) + return true; // skip it + + if ( basetype == "filelists" && not env::ZYPP_REPOMD_WITH_FILELISTS() ) + return true; // skip it + + // filter localized susedata + if ( str::startsWith( basetype, "susedata." ) ) + { + // susedata.LANG + if ( ! wantLocale( Locale(basetype.c_str()+9) ) ) + return true; // skip it + } + + // may take it... (prefer zchnk) + if ( zchk || !_wantedFiles.count( basetype ) ) + _wantedFiles[basetype] = loc_r; + + return true; + } + + void RepomdFileCollector::finalize(const FinalizeCb &cb) + { + // schedule fileS for download + for ( const auto & el : _wantedFiles ) { + const OnMediaLocation & loc { el.second }; + const OnMediaLocation & loc_with_path { loc_with_path_prefix( loc, repoInfo().path() ) }; + cb( OnMediaLocation(loc_with_path).setDeltafile( search_deltafile( deltaDir()/"repodata", loc.filename() ) ) ); + } + } + + bool RepomdFileCollector::wantLocale(const Locale &locale_r) const + { return _wantedLocales.count( locale_r ); } + + void RepomdFileCollector::addWantedLocale(Locale locale_r) + { + while ( locale_r ) + { + _wantedLocales.insert( locale_r ); + locale_r = locale_r.fallback(); + } + } + +} diff --git a/zypp/repo/yum/RepomdFileCollector.h b/zypp/repo/yum/RepomdFileCollector.h new file mode 100644 index 0000000..a5875c5 --- /dev/null +++ b/zypp/repo/yum/RepomdFileCollector.h @@ -0,0 +1,54 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ + +#ifndef ZYPP_SOURCE_YUM_REPOMDFILECOLLECTOR +#define ZYPP_SOURCE_YUM_REPOMDFILECOLLECTOR + +#include +#include +#include +#include +#include +#include +#include + +namespace zypp::repo::yum +{ + + struct RepomdFileCollector + { + NON_COPYABLE( RepomdFileCollector ); + NON_MOVABLE( RepomdFileCollector ); + + using FinalizeCb = std::function; + + RepomdFileCollector( const Pathname & destDir_r ); + virtual ~RepomdFileCollector(); + + bool collect( const OnMediaLocation & loc_r, const std::string & typestr_r ); + + void finalize( const FinalizeCb &cb ); + + protected: + virtual const RepoInfo &repoInfo() const = 0; + virtual const Pathname &deltaDir() const = 0; + + private: + + bool wantLocale( const Locale & locale_r ) const; + void addWantedLocale( Locale locale_r ); + + protected: + const Pathname & _destDir; + + LocaleSet _wantedLocales; ///< Locales do download + std::map _wantedFiles; + }; +} +#endif diff --git a/zypp/sat/FileConflicts.cc b/zypp/sat/FileConflicts.cc new file mode 100644 index 0000000..820e7d4 --- /dev/null +++ b/zypp/sat/FileConflicts.cc @@ -0,0 +1,167 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/FileConflicts.cc + */ +#include +#include + +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + std::string FileConflicts::Conflict::asUserString() const + { + if ( lhsFilename() == rhsFilename() ) + { + static const char * text[2][2] = {{ // [lhs][rhs] 0 = installed; 1 = to be installed + // TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) + N_( "File %1%\n" + " from package\n" + " %2%\n" + " conflicts with file from package\n" + " %3%" ), + // TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) + N_( "File %1%\n" + " from package\n" + " %2%\n" + " conflicts with file from install of\n" + " %3%" ) + },{ + // TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) + N_( "File %1%\n" + " from install of\n" + " %2%\n" + " conflicts with file from package\n" + " %3%" ), + // TranslatorExplanation %1%(filename) %2%(package1) %3%(package2) + N_( "File %1%\n" + " from install of\n" + " %2%\n" + " conflicts with file from install of\n" + " %3%" ) + }}; + return str::Format( text[lhsSolvable().isSystem()?0:1][rhsSolvable().isSystem()?0:1] ) + % lhsFilename() + % lhsSolvable().asUserString() + % rhsSolvable().asUserString(); + } + else + { + static const char * text[2][2] = {{ // [lhs][rhs] 0 = installed; 1 = to be installed + // TranslatorExplanation %1%(filename1) %2%(package1) %%3%(filename2) 4%(package2) + N_( "File %1%\n" + " from package\n" + " %2%\n" + " conflicts with file\n" + " %3%\n" + " from package\n" + " %4%" ), + // TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) + N_( "File %1%\n" + " from package\n" + " %2%\n" + " conflicts with file\n" + " %3%\n" + " from install of\n" + " %4%" ) + },{ + // TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) + N_( "File %1%\n" + " from install of\n" + " %2%\n" + " conflicts with file\n" + " %3%\n" + " from package\n" + " %4%" ), + // TranslatorExplanation %1%(filename1) %2%(package1) %3%(filename2) %4%(package2) + N_( "File %1%\n" + " from install of\n" + " %2%\n" + " conflicts with file\n" + " %3%\n" + " from install of\n" + " %4%" ) + }}; + return str::Format( text[lhsSolvable().isSystem()?0:1][rhsSolvable().isSystem()?0:1] ) + % lhsFilename() + % lhsSolvable().asUserString() + % rhsFilename() + % rhsSolvable().asUserString(); + } + } + + std::ostream & operator<<( std::ostream & str, const FileConflicts & obj ) + { return dumpRange( str << "(" << obj.size() << ") ", obj.begin(), obj.end() ); } + + std::ostream & operator<<( std::ostream & str, const FileConflicts::Conflict & obj ) + { + if ( obj.lhsFilename() == obj.rhsFilename() ) + return str << str::Format( "%s:\n %s[%s]\n %s[%s]" ) + % obj.lhsFilename() + % obj.lhsSolvable() + % obj.lhsFilemd5() + % obj.rhsSolvable() + % obj.rhsFilemd5(); + + return str << str::Format( "%s - %s:\n %s[%s]\n %s[%s]" ) + % obj.lhsFilename() + % obj.rhsFilename() + % obj.lhsSolvable() + % obj.lhsFilemd5() + % obj.rhsSolvable() + % obj.rhsFilemd5(); + } + + + std::ostream & dumpAsXmlOn( std::ostream & str, const FileConflicts & obj ) + { + xmlout::Node guard( str, "fileconflicts", { "size", obj.size() } ); + if ( ! obj.empty() ) + { + *guard << "\n"; + for ( const auto & el : obj ) + dumpAsXmlOn( *guard, el ) << "\n"; + } + return str; + } + + namespace + { + std::ostream & dumpAsXmlHelper( std::ostream & str, const std::string & tag_r, IdString filename_r, IdString md5sum_r, Solvable solv_r ) + { + xmlout::Node guard( str, tag_r ); + *xmlout::Node( *guard, "file" ) << filename_r; + dumpAsXmlOn( *guard, CheckSum( md5sum_r.asString() ) ); + dumpAsXmlOn( *guard, solv_r ); + return str; + } + } + + std::ostream & dumpAsXmlOn( std::ostream & str, const FileConflicts::Conflict & obj ) + { + xmlout::Node guard( str, "fileconflict" ); + dumpAsXmlHelper( *guard<<"\n", "lhs", obj.lhsFilename(), obj.lhsFilemd5(), obj.lhsSolvable() ); + dumpAsXmlHelper( *guard<<"\n", "rhs", obj.rhsFilename(), obj.rhsFilemd5(), obj.rhsSolvable() ); + return str; + } + + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/FileConflicts.h b/zypp/sat/FileConflicts.h new file mode 100644 index 0000000..3aa4018 --- /dev/null +++ b/zypp/sat/FileConflicts.h @@ -0,0 +1,96 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/FileConflicts.h + */ +#ifndef ZYPP_SAT_FILECONFLICTS_H +#define ZYPP_SAT_FILECONFLICTS_H + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + /////////////////////////////////////////////////////////////////// + /// \class FileConflicts + /// \brief Libsolv queue representing file conflicts. + /////////////////////////////////////////////////////////////////// + class ZYPP_API FileConflicts : private Queue + { + friend bool operator==( const FileConflicts & lhs, const FileConflicts & rhs ); + static constexpr size_type queueBlockSize = 6; + + public: + /** + * \class Conflict + * \brief A file conflict. + */ + struct Conflict + { + IdString lhsFilename() const { return IdString( _data[0] ); } + Solvable lhsSolvable() const { return Solvable( _data[1] ); } + IdString lhsFilemd5() const { return IdString( _data[2] ); } + + IdString rhsFilename() const { return IdString( _data[3] ); } + Solvable rhsSolvable() const { return Solvable( _data[4] ); } + IdString rhsFilemd5() const { return IdString( _data[5] ); } + + /** Ready to use (translated) string describing the Conflict */ + std::string asUserString() const; + + private: + detail::IdType _data[queueBlockSize]; + }; + + public: + using Queue::size_type; + using value_type = Conflict; + using const_iterator = const value_type *; + + using Queue::empty; + size_type size() const { return Queue::size()/queueBlockSize; } + const_iterator begin() const { return reinterpret_cast(Queue::begin()); } + const_iterator end() const { return reinterpret_cast(Queue::end()); } + + public: + using Queue::operator detail::CQueue *; ///< libsolv backdoor + using Queue::operator const detail::CQueue *; ///< libsolv backdoor + }; + + /** \relates FileConflicts Stream output */ + std::ostream & operator<<( std::ostream & str, const FileConflicts & obj ) ZYPP_API; + + /** \relates FileConflicts::Conflict Stream output */ + std::ostream & operator<<( std::ostream & str, const FileConflicts::Conflict & obj ) ZYPP_API; + + /** \relates FileConflicts XML output */ + std::ostream & dumpAsXmlOn( std::ostream & str, const FileConflicts & obj ) ZYPP_API; + + /** \relates FileConflicts::Conflict XML output */ + std::ostream & dumpAsXmlOn( std::ostream & str, const FileConflicts::Conflict & obj ) ZYPP_API; + + /** \relates FileConflicts */ + inline bool operator==( const FileConflicts & lhs, const FileConflicts & rhs ) + { return static_cast(lhs) == static_cast(rhs); } + + /** \relates FileConflicts */ + inline bool operator!=( const FileConflicts & lhs, const FileConflicts & rhs ) + { return !( lhs == rhs ); } + + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_FILECONFLICTS_H diff --git a/zypp/sat/LocaleSupport.cc b/zypp/sat/LocaleSupport.cc new file mode 100644 index 0000000..4958e73 --- /dev/null +++ b/zypp/sat/LocaleSupport.cc @@ -0,0 +1,51 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/LocaleSupport.cc + * +*/ +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const LocaleSupport & obj ) + { + return str << obj.locale() << '(' << (obj.isAvailable()?'a':'_') << (obj.isRequested()?'R':'_') << ')'; + } + + /****************************************************************** + ** + ** FUNCTION NAME : dumpOn + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & dumpOn( std::ostream & str, const LocaleSupport & obj ) + { + return dumpRange( str << obj, obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/LocaleSupport.h b/zypp/sat/LocaleSupport.h new file mode 100644 index 0000000..8bfc804 --- /dev/null +++ b/zypp/sat/LocaleSupport.h @@ -0,0 +1,129 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/LocaleSupport.h + * +*/ +#ifndef ZYPP_SAT_LOCALESUPPORT_H +#define ZYPP_SAT_LOCALESUPPORT_H + +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LocaleSupport + // + /** Convenience methods to manage support for a specific \ref Locale. + * + * \code + * sat::LocaleSupport myLocale( Locale("de") ); + * + * if ( myLocale.isAvailable() ) + * { + * MIL << "Support for locale '" << myLocale.locale() << "' is available." << endl; + * } + * if ( ! myLocale.isRequested() ) + * { + * MIL << "Will enable support for locale '" << myLocale.locale() << "'." << endl; + * myLocale.setRequested( true ); + * } + * MIL << "Packages supporting locale '" << myLocale.locale() << "':" << endl; + * for_( it, myLocale.begin(), myLocale.end() ) + * { + * // iterate over sat::Solvables + * MIL << " " << *it << endl; + * // or get the PoolItems + * DBG << " " << PoolItem(*it) << endl; + * } + * \endcode + * + * \todo If iterator is too slow install a proxy watching the Pool::serial. + */ + class LocaleSupport : public SolvIterMixin > + , protected detail::PoolMember + { + public: + /** Default ctor */ + LocaleSupport() + {} + /** Ctor taking a \ref Locale. */ + LocaleSupport( const Locale & locale_r ) + : _locale( locale_r ) + {} + + public: + /** My \ref Locale */ + const Locale & locale() const + { return _locale; } + + /** Whether there are language specific packages supporting my \ref Locale. */ + bool isAvailable() const + { return Pool(*this).isAvailableLocale( _locale ); } + + /** Whether the solver will automatically select language specific packages for my \ref Locale. */ + bool isRequested() const + { return Pool(*this).isRequestedLocale( _locale ); } + + /** Turn on/off solver support for my \ref Locale.*/ + void setRequested( bool yesno_r ) + { yesno_r ? Pool(*this).addRequestedLocale( _locale ) : Pool(*this).eraseRequestedLocale( _locale ); } + + public: + /** \name Iterate through all \ref sat::Solvables supporting my \ref Locale. */ + //@{ + using iterator = Solvable_iterator; // from SolvIterMixin + + iterator begin() const + { return Pool(*this).filterBegin( filter::ByLocaleSupport( _locale ) ); } + + iterator end() const + { return Pool(*this).filterEnd( filter::ByLocaleSupport( _locale ) ); } + //@} + + private: + Locale _locale; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates LocaleSupport Stream output */ + std::ostream & operator<<( std::ostream & str, const LocaleSupport & obj ); + + /** \relates LocaleSupport More verbose stream output including dependencies */ + std::ostream & dumpOn( std::ostream & str, const LocaleSupport & obj ); + + /** \relates LocaleSupport */ + inline bool operator==( const LocaleSupport & lhs, const LocaleSupport & rhs ) + { return lhs.locale() == rhs.locale(); } + + /** \relates LocaleSupport */ + inline bool operator!=( const LocaleSupport & lhs, const LocaleSupport & rhs ) + { return lhs.locale() != rhs.locale(); } + + /** \relates LocaleSupport */ + inline bool operator<( const LocaleSupport & lhs, const LocaleSupport & rhs ) + { return lhs.locale() < rhs.locale(); } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_LOCALESUPPORT_H diff --git a/zypp/sat/LookupAttr.cc b/zypp/sat/LookupAttr.cc new file mode 100644 index 0000000..c5c5177 --- /dev/null +++ b/zypp/sat/LookupAttr.cc @@ -0,0 +1,827 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/LookupAttr.cc + * +*/ +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + using detail::noSolvableId; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupAttr::Impl + // + /////////////////////////////////////////////////////////////////// + /** + * LookupAttr implememtation. + * + * Repository and Solvable must not be set at the same time! + * + * \note When looking in pool or repo, \ref Solvable \c _solv is + * somewhat abused to store eiter \c Id \c 0 or \c SOLVID_META, which + * indicates whether the dataiterator should look into solvable or + * repository metadata. Remember that all \ref Solvables with an + * \e invalid \c Id, are treated as == Solvable::noSolvable, + * and in a boolean context evaluate to \c false. Thus \c noSolvable + * may have different \c Ids. + */ + class LookupAttr::Impl + { + public: + Impl() + : _parent( SolvAttr::noAttr ) + {} + Impl( const SolvAttr& attr_r, Location loc_r ) + : _attr( attr_r ), _parent( attr_r.parent() ), _solv( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId ) + {} + Impl( const SolvAttr& attr_r, Repository repo_r, Location loc_r ) + : _attr( attr_r ), _parent( attr_r.parent() ), _repo( repo_r ), _solv( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId ) + {} + Impl( const SolvAttr& attr_r, Solvable solv_r ) + : _attr( attr_r ), _parent( attr_r.parent() ), _solv( solv_r ) + {} + + public: + SolvAttr attr() const + { return _attr; } + + void setAttr( SolvAttr attr_r ) + { + _attr = std::move(attr_r); + SolvAttr p( _attr.parent() ); + if ( p != SolvAttr::noAttr ) + _parent = p; + } + + const StrMatcher & strMatcher() const + { return _strMatcher; } + + void setStrMatcher( const StrMatcher & matcher_r ) + { + matcher_r.compile(); + _strMatcher = matcher_r; + } + + public: + bool pool() const + { return ! (_repo || _solv); } + + void setPool( Location loc_r ) + { + _repo = Repository::noRepository; + _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId ); + } + + Repository repo() const + { return _repo; } + + void setRepo( Repository repo_r, Location loc_r ) + { + _repo = repo_r; + _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId ); + } + + Solvable solvable() const + { return _solv; } + + void setSolvable( Solvable solv_r ) + { + _repo = Repository::noRepository; + _solv = solv_r; + } + + SolvAttr parent() const + { return _parent; } + + void setParent( SolvAttr attr_r ) + { _parent = std::move(attr_r); } + + public: + LookupAttr::iterator begin() const + { + if ( _attr == SolvAttr::noAttr || sat::Pool::instance().reposEmpty() ) + return end(); + + detail::RepoIdType whichRepo = detail::noRepoId; // all repos + if ( _solv ) + whichRepo = _solv.repository().id(); + else if ( _repo ) + whichRepo = _repo.id(); + + detail::DIWrap dip( whichRepo, _solv.id(), _attr.id(), _strMatcher.searchstring(), _strMatcher.flags().get() ); + if ( _parent != SolvAttr::noAttr ) + ::dataiterator_prepend_keyname( dip.get(), _parent.id() ); + + return iterator( dip ); // iterator takes over ownership! + } + + LookupAttr::iterator end() const + { return iterator(); } + + private: + SolvAttr _attr; + SolvAttr _parent; + Repository _repo; + Solvable _solv; + StrMatcher _strMatcher; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupAttr + // + /////////////////////////////////////////////////////////////////// + + LookupAttr::LookupAttr() + : _pimpl( new Impl ) + {} + + LookupAttr::LookupAttr( SolvAttr attr_r, Location loc_r ) + : _pimpl( new Impl( std::move(attr_r), std::move(loc_r) ) ) + {} + LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Location loc_r ) + : _pimpl( new Impl( std::move(attr_r), std::move(loc_r) ) ) + { _pimpl->setParent( std::move(parent_r) ); } + + LookupAttr::LookupAttr( SolvAttr attr_r, Repository repo_r, Location loc_r ) + : _pimpl( new Impl( std::move(attr_r), std::move(repo_r), std::move(loc_r) ) ) + {} + LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Repository repo_r, Location loc_r ) + : _pimpl( new Impl( std::move(attr_r), std::move(repo_r), std::move(loc_r) ) ) + { _pimpl->setParent( std::move(parent_r) ); } + + LookupAttr::LookupAttr( SolvAttr attr_r, Solvable solv_r ) + : _pimpl( new Impl( std::move(attr_r), std::move(solv_r) ) ) + {} + LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Solvable solv_r ) + : _pimpl( new Impl( std::move(attr_r), std::move(solv_r) ) ) + { _pimpl->setParent( std::move(parent_r) ); } + + + /////////////////////////////////////////////////////////////////// + + SolvAttr LookupAttr::attr() const + { return _pimpl->attr(); } + + void LookupAttr::setAttr( SolvAttr attr_r ) + { _pimpl->setAttr( std::move(attr_r) ); } + + const StrMatcher & LookupAttr::strMatcher() const + { return _pimpl->strMatcher(); } + + void LookupAttr::setStrMatcher( const StrMatcher & matcher_r ) + { _pimpl->setStrMatcher( matcher_r ); } + + /////////////////////////////////////////////////////////////////// + + bool LookupAttr::pool() const + { return _pimpl->pool(); } + + void LookupAttr::setPool( Location loc_r ) + { _pimpl->setPool( loc_r ); } + + Repository LookupAttr::repo() const + { return _pimpl->repo(); } + + void LookupAttr::setRepo( Repository repo_r, Location loc_r ) + { _pimpl->setRepo( repo_r, loc_r ); } + + Solvable LookupAttr::solvable() const + { return _pimpl->solvable(); } + + void LookupAttr::setSolvable( Solvable solv_r ) + { _pimpl->setSolvable( solv_r ); } + + SolvAttr LookupAttr::parent() const + { return _pimpl->parent(); } + + void LookupAttr::setParent( SolvAttr attr_r ) + { _pimpl->setParent( std::move(attr_r) ); } + + /////////////////////////////////////////////////////////////////// + + LookupAttr::iterator LookupAttr::begin() const + { return _pimpl->begin(); } + + LookupAttr::iterator LookupAttr::end() const + { return _pimpl->end(); } + + bool LookupAttr::empty() const + { return begin() == end(); } + + LookupAttr::size_type LookupAttr::size() const + { + size_type c = 0; + for_( it, begin(), end() ) + ++c; + return c; + } + + /////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const LookupAttr & obj ) + { + if ( obj.attr() == SolvAttr::noAttr ) + return str << "search nothing"; + + if ( obj.attr() ) + str << "search " << obj.attr() << " in "; + else + str << "search ALL in "; + + if ( obj.solvable() ) + return str << obj.solvable(); + if ( obj.repo() ) + return str << obj.repo(); + return str << "pool"; + } + + std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj ) + { + return dumpRange( str << obj, obj.begin(), obj.end() ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupRepoAttr + // + /////////////////////////////////////////////////////////////////// + + LookupRepoAttr::LookupRepoAttr( SolvAttr attr_r, Repository repo_r ) + : LookupAttr( std::move(attr_r), repo_r, REPO_ATTR ) + {} + + void LookupRepoAttr::setRepo( Repository repo_r ) + { LookupAttr::setRepo( repo_r, REPO_ATTR ); } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : detail::DIWrap + // + /////////////////////////////////////////////////////////////////// + + namespace detail + { + DIWrap::DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r, + std::string mstring_r, int flags_r ) + : _dip( new ::Dataiterator ) + , _mstring(std::move( mstring_r )) + { + ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r, + _mstring.empty() ? 0 : _mstring.c_str(), flags_r ); + } + + DIWrap::DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r, + const char * mstring_r, int flags_r ) + : _dip( new ::Dataiterator ) + , _mstring( mstring_r ? mstring_r : "" ) + { + ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r, + _mstring.empty() ? 0 : _mstring.c_str(), flags_r ); + } + + DIWrap::DIWrap( const DIWrap & rhs ) + : _dip( 0 ) + , _mstring( rhs._mstring ) + { + if ( rhs._dip ) + { + _dip = new ::Dataiterator; + ::dataiterator_init_clone( _dip, rhs._dip ); + ::dataiterator_strdup( _dip ); + } + } + + DIWrap::~DIWrap() + { + if ( _dip ) + { + ::dataiterator_free( _dip ); + delete _dip; + } + } + + std::ostream & operator<<( std::ostream & str, const DIWrap & obj ) + { return str << obj.get(); } + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupAttr::iterator + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // position and moving + /////////////////////////////////////////////////////////////////// + + Repository LookupAttr::iterator::inRepo() const + { return _dip ? Repository( _dip->repo ) : Repository::noRepository; } + + Solvable LookupAttr::iterator::inSolvable() const + { return _dip ? Solvable( _dip->solvid ) : Solvable::noSolvable; } + + SolvAttr LookupAttr::iterator::inSolvAttr() const + { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; } + + void LookupAttr::iterator::nextSkipSolvAttr() + { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); } + + void LookupAttr::iterator::nextSkipSolvable() + { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); } + + void LookupAttr::iterator::nextSkipRepo() + { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); } + + void LookupAttr::iterator::stayInThisSolvable() + { if ( _dip ) { _dip.get()->repoid = -1; _dip.get()->flags |= SEARCH_THISSOLVID; } } + + void LookupAttr::iterator::stayInThisRepo() + { if ( _dip ) { _dip.get()->repoid = -1; } } + + /////////////////////////////////////////////////////////////////// + // attr value type test + /////////////////////////////////////////////////////////////////// + + detail::IdType LookupAttr::iterator::solvAttrType() const + { return _dip ? _dip->key->type : detail::noId; } + + bool LookupAttr::iterator::solvAttrNumeric() const + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_NUM: + case REPOKEY_TYPE_CONSTANT: + return true; + break; + } + return false; + } + + bool LookupAttr::iterator::solvAttrString() const + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_CONSTANTID: + case REPOKEY_TYPE_STR: + case REPOKEY_TYPE_DIRSTRARRAY: + return true; + break; + } + return false; + } + + bool LookupAttr::iterator::solvAttrIdString() const + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_CONSTANTID: + return true; + break; + } + return false; + } + + bool LookupAttr::iterator::solvAttrCheckSum() const + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_MD5: + case REPOKEY_TYPE_SHA1: + case REPOKEY_TYPE_SHA256: + return true; + break; + } + return false; + } + + /////////////////////////////////////////////////////////////////// + namespace + { + enum SubType { ST_NONE, // no sub-structure + ST_FLEX, // flexarray + ST_SUB }; // inside sub-structure + SubType subType( const detail::DIWrap & dip ) + { + if ( ! dip ) + return ST_NONE; + if ( dip.get()->key->type == REPOKEY_TYPE_FLEXARRAY ) + return ST_FLEX; + return dip.get()->kv.parent ? ST_SUB : ST_NONE; + } + } + /////////////////////////////////////////////////////////////////// + + bool LookupAttr::iterator::solvAttrSubEntry() const + { return subType( _dip ) != ST_NONE; } + + /////////////////////////////////////////////////////////////////// + // Iterate sub-structures. + /////////////////////////////////////////////////////////////////// + + bool LookupAttr::iterator::subEmpty() const + { return( subBegin() == subEnd() ); } + + LookupAttr::size_type LookupAttr::iterator::subSize() const + { + size_type c = 0; + for_( it, subBegin(), subEnd() ) + ++c; + return c; + } + + LookupAttr::iterator LookupAttr::iterator::subBegin() const + { + SubType subtype( subType( _dip ) ); + if ( subtype == ST_NONE ) + return subEnd(); + // setup the new sub iterator with the remembered position + detail::DIWrap dip( 0, 0, 0 ); + ::dataiterator_clonepos( dip.get(), _dip.get() ); + switch ( subtype ) + { + case ST_NONE: // not reached + break; + case ST_FLEX: + ::dataiterator_seek( dip.get(), DI_SEEK_CHILD|DI_SEEK_STAY ); + break; + case ST_SUB: + ::dataiterator_seek( dip.get(), DI_SEEK_REWIND|DI_SEEK_STAY ); + break; + } + return iterator( dip ); // iterator takes over ownership! + } + + LookupAttr::iterator LookupAttr::iterator::subEnd() const + { + return iterator(); + } + + LookupAttr::iterator LookupAttr::iterator::subFind( const SolvAttr& attr_r ) const + { + iterator it = subBegin(); + if ( attr_r != sat::SolvAttr::allAttr ) + { + while ( it != subEnd() && it.inSolvAttr() != attr_r ) + ++it; + } + return it; + } + + LookupAttr::iterator LookupAttr::iterator::subFind( const C_Str & attrname_r ) const + { + if ( attrname_r.empty() ) + return subBegin(); + + SubType subtype( subType( _dip ) ); + if ( subtype == ST_NONE ) + return subBegin(); + + std::string subattr( inSolvAttr().asString() ); + if ( subtype == ST_FLEX ) + { + // append ":attrname" + subattr += ":"; + subattr += attrname_r; + } + else + { + // replace "oldname" after ':' with "attrname" + std::string::size_type pos( subattr.rfind( ':' ) ); + if ( pos != std::string::npos ) + { + subattr.erase( pos+1 ); + subattr += attrname_r; + } + else + subattr = attrname_r; // no ':' so replace all. + } + return subFind( SolvAttr( subattr ) ); + } + + /////////////////////////////////////////////////////////////////// + // attr value retrieval + /////////////////////////////////////////////////////////////////// + + int LookupAttr::iterator::asInt() const + { + if ( _dip ) + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_NUM: + case REPOKEY_TYPE_CONSTANT: + return _dip->kv.num; + break; + } + } + return 0; + } + + unsigned LookupAttr::iterator::asUnsigned() const + { return asInt(); } + + unsigned long long LookupAttr::iterator::asUnsignedLL() const + { + if ( _dip ) + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_NUM: + case REPOKEY_TYPE_CONSTANT: + return SOLV_KV_NUM64(&_dip->kv); + break; + } + } + return 0; + } + + bool LookupAttr::iterator::asBool() const + { return asInt(); } + + + const char * LookupAttr::iterator::c_str() const + { + if ( _dip ) + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_CONSTANTID: + if ( _dip->data && _dip->data->localpool ) + return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id ); // in local pool + else + return IdString( _dip->kv.id ).c_str(); // in global pool + break; + + case REPOKEY_TYPE_STR: + return _dip->kv.str; + break; + + case REPOKEY_TYPE_DIRSTRARRAY: + // may or may not be stringified depending on SEARCH_FILES flag + return( _dip->flags & SEARCH_FILES + ? _dip->kv.str + : ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str ) ); + break; + } + } + return 0; + } + + std::string LookupAttr::iterator::asString() const + { + if ( _dip ) + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_CONSTANTID: + { + detail::IdType id = ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 ); + return ISRELDEP(id) ? Capability( id ).asString() + : IdString( id ).asString(); + } + break; + + case REPOKEY_TYPE_STR: + case REPOKEY_TYPE_DIRSTRARRAY: + { + const char * ret( c_str() ); + return ret ? ret : ""; + } + break; + + case REPOKEY_TYPE_NUM: + case REPOKEY_TYPE_CONSTANT: + return str::numstring( asInt() ); + break; + + case REPOKEY_TYPE_MD5: + case REPOKEY_TYPE_SHA1: + case REPOKEY_TYPE_SHA256: + { + return asCheckSum().asString(); + } + break; + + case REPOKEY_TYPE_FLEXARRAY: + { + std::ostringstream str; + str << "{" << endl; + for_( it, subBegin(), subEnd() ) + { + str << " " << it.inSolvAttr() << " = " << it.asString() << endl; + } + str << "}"; + return str.str(); + } + break; + } + } + return std::string(); + } + + IdString LookupAttr::iterator::idStr() const + { + if ( _dip ) + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_ID: + case REPOKEY_TYPE_IDARRAY: + case REPOKEY_TYPE_CONSTANTID: + return IdString( ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 ) ); + break; + } + } + return IdString(); + } + + CheckSum LookupAttr::iterator::asCheckSum() const + { + if ( _dip ) + { + switch ( solvAttrType() ) + { + case REPOKEY_TYPE_MD5: + return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) ); + break; + + case REPOKEY_TYPE_SHA1: + return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) ); + break; + + case REPOKEY_TYPE_SHA224: + return CheckSum::sha224( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) ); + break; + + case REPOKEY_TYPE_SHA256: + return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) ); + break; + + case REPOKEY_TYPE_SHA384: + return CheckSum::sha384( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) ); + break; + + case REPOKEY_TYPE_SHA512: + return CheckSum::sha512( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) ); + break; + } + } + return CheckSum(); + } + + /////////////////////////////////////////////////////////////////// + // internal stuff below + /////////////////////////////////////////////////////////////////// + + LookupAttr::iterator::iterator() + : iterator_adaptor_( 0 ) + {} + + LookupAttr::iterator::iterator( const iterator & rhs ) + : iterator_adaptor_( 0 ) + , _dip( rhs._dip ) + { + base_reference() = _dip.get(); + } + + LookupAttr::iterator::iterator( detail::DIWrap & dip_r ) + : iterator_adaptor_( 0 ) + { + _dip.swap( dip_r ); // take ownership! + base_reference() = _dip.get(); + increment(); + } + + LookupAttr::iterator::~iterator() + {} + + LookupAttr::iterator & LookupAttr::iterator::operator=( const iterator & rhs ) + { + if ( &rhs != this ) + { + _dip = rhs._dip; + base_reference() = _dip.get(); + } + return *this; + } + + /////////////////////////////////////////////////////////////////// + + bool LookupAttr::iterator::dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const + { + // Iterator equal is same position in same container. + // Here: same attribute in same solvable. + return( lhs.solvid == rhs.solvid && lhs.key->name == rhs.key->name ); + } + + detail::IdType LookupAttr::iterator::dereference() const + { + return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 ) + : detail::noId; + } + + void LookupAttr::iterator::increment() + { + if ( _dip ) + { + if ( ! ::dataiterator_step( _dip.get() ) ) + { + _dip.reset(); + base_reference() = 0; + } + else + { + ::dataiterator_strdup( _dip.get() ); + } + } + } + + std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj ) + { + const detail::CDataiterator * dip = obj.get(); + if ( ! dip ) + return str << "EndOfQuery"; + + if ( obj.inSolvable() ) + str << obj.inSolvable(); + else if ( obj.inRepo() ) + str << obj.inRepo(); + + str << '<' << obj.inSolvAttr() << (obj.solvAttrSubEntry() ? ">(*" : ">(") + << IdString(obj.solvAttrType()) << ") = " << obj.asString(); + return str; + } + + template<> CheckSum LookupAttr::iterator::asType() const + { return asCheckSum(); } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator * obj ) +{ + str << "detail::CDataiterator("; + if ( ! obj ) + { + str << "NULL"; + } + else + { + str << "|" << zypp::Repository(obj->repo); + str << "|" << zypp::sat::Solvable(obj->solvid); + str << "|" << zypp::IdString(obj->key->name); + str << "|" << zypp::IdString(obj->key->type); + str << "|" << obj->repodataid; + str << "|" << obj->repoid; + } + return str << ")"; +} + +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/LookupAttr.h b/zypp/sat/LookupAttr.h new file mode 100644 index 0000000..458bfd9 --- /dev/null +++ b/zypp/sat/LookupAttr.h @@ -0,0 +1,616 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/LookupAttr.h + * +*/ +#ifndef ZYPP_SAT_LOOKUPATTR_H +#define ZYPP_SAT_LOOKUPATTR_H + +#include +#include + +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class CheckSum; + class Match; + struct MatchException; + class StrMatcher; + + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupAttr + // + /** Lightweight attribute value lookup. + * + * Search for an attribute in \ref Pool, one \ref Repository + * or one \ref Solvable. \ref LookupAttr builds the query, + * \ref LookupAttr::iterator iterates over the result. + * + * Per default \ref LookupAttr looks for attributes associated with + * a \ref Solvable. But you may also pass \ref REPO_ATTR as + * \ref Location argument, to lookup attributes associated with + * the \ref Repository (e.g. DeltaRpm information). + * + * For convenience \see \ref LookupRepoAttr. + * + * Modifying the query will not affect any running + * iterator. + * + * Use \ref SolvAttr::allAttr to search all attributes. + * + * To search for attributes located in a sub-structure (flexarray) + * you also have to pass the sub-structures attribute as parent. + * Passing \ref SolvAttr::allAttr a parent will lookup the attribute + * in \c any sub-structure. Few attributes are known to have a parent + * (\see \ref SolvAttr::parent). Setting those attributes will automatically + * initialize their parent value. + * + * \code + * // Lookup all 'name' attributes: + * sat::LookupAttr q( sat::SolvAttr::name ); + * // Lookup all 'name' attributes within a sub-structure 'data': + * sat::LookupAttr q( sat::SolvAttr::name, sat::SolvAttr::data ); + * // Lookup all 'name' attributes within any sub-structure: + * sat::LookupAttr q( sat::SolvAttr::name, sat::SolvAttr::allAttr ); + * \endcode + * + * \code + * // look for all attributes of one solvable + * void ditest( sat::Solvable slv_r ) + * { + * sat::LookupAttr q( sat::SolvAttr::allAttr, slv_r ); + * MIL << q << ": " << endl; + * for_( it, q.begin(), q.end() ) + * { + * MIL << " " << it.inSolvAttr() << " = " << it.asString() << endl; + * } + * } + * \endcode + * + * \code + * // look for an attribute in the pool. + * sat::LookupAttr q( sat::SolvAttr("susetags:datadir") ); + * MIL << q << ": " << endl; + * for_( it, q.begin(), q.end() ) + * { + * MIL << " " << it << endl; + * } + * \endcode + * + * \code + * // look for a repo attribute in the pool. + * sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides ); + * MIL << q << ": " << endl; + * for_( it, q.begin(), q.end() ) + * { + * MIL << " " << it << endl; + * } + * \endcode + */ + class ZYPP_API LookupAttr + { + public: + using Exception = MatchException; + + public: + using size_type = unsigned int; + + /** Specify the where to look for the attribule. */ + enum Location { + SOLV_ATTR = 0, //!< Search for solvable attributes (default) + REPO_ATTR = -1 //!< Search for repository attributes + }; + + public: + /** Default ctor finds nothing. */ + LookupAttr(); + + LookupAttr(const LookupAttr &) = default; + LookupAttr(LookupAttr &&) noexcept = default; + LookupAttr &operator=(const LookupAttr &) = default; + LookupAttr &operator=(LookupAttr &&) noexcept = default; + + /** Lookup \ref SolvAttr in \ref Pool (all repositories). */ + explicit LookupAttr( SolvAttr attr_r, Location = SOLV_ATTR ); + /** \overload SolvAttr within sub-structure \a parent_r. */ + LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Location = SOLV_ATTR ); + + /** Lookup \ref SolvAttr in one\ref Repository. */ + LookupAttr( SolvAttr attr_r, Repository repo_r, Location = SOLV_ATTR ); + /** \overload SolvAttr within sub-structure \a parent_r. */ + LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Repository repo_r, Location = SOLV_ATTR ); + + /** Lookup \ref SolvAttr in one \ref Solvable. */ + LookupAttr( SolvAttr attr_r, Solvable solv_r ); + /** \overload SolvAttr within sub-structure \a parent_r. */ + LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Solvable solv_r ); + + public: + /** \name Search result. */ + //@{ + /** Result iterator. */ + class iterator; + + /** Iterator to the begin of query results. */ + iterator begin() const; + + /** Iterator behind the end of query results. */ + iterator end() const; + + /** Whether the query is empty. */ + bool empty() const; + + /** Ammount of results. + * \note This is not a cheap call. It runs the query. + */ + size_type size() const; + + /** TransformIterator returning an \ref iterator vaue of type \c TResult. */ + template + class TransformIterator; + //@} + + public: + /** \name What to search. */ + //@{ + /** The \ref SolvAttr to search. */ + SolvAttr attr() const; + + /** Set the \ref SolvAttr to search. */ + void setAttr( SolvAttr attr_r ); + //@} + + /** \name Restrict attributes to match a pattern. */ + //@{ + /** The pattern to match. + * You can also evaluate \ref StrMatcher in a boolean context, + * in order to test whether an \ref StrMatcher is set: + * \code + * LookupAttr q; + * if ( q.strMatcher() ) + * ...; // an StrMatcher is set + * \endcode + */ + const StrMatcher & strMatcher() const; + + /** Set the pattern to match. + * \throws MatchException Any of the exceptions thrown by \ref StrMatcher::compile. + */ + void setStrMatcher( const StrMatcher & matcher_r ); + + /** Reset the pattern to match. */ + void resetStrMatcher(); + //@} + + public: + /** \name Where to search. */ + //@{ + /** Whether to search in \ref Pool. */ + bool pool() const; + + /** Set search in \ref Pool (all repositories). */ + void setPool( Location = SOLV_ATTR ); + + /** Whether to search in one \ref Repository. */ + Repository repo() const; + + /** Set search in one \ref Repository. */ + void setRepo( Repository repo_r, Location = SOLV_ATTR ); + + /** Whether to search in one \ref Solvable. */ + Solvable solvable() const; + + /** Set search in one \ref Solvable. */ + void setSolvable( Solvable solv_r ); + + /** Whether to search within a sub-structure (\ref SolvAttr::noAttr if not) */ + SolvAttr parent() const; + + /** Set search within a sub-structure (\ref SolvAttr::noAttr for none) */ + void setParent( SolvAttr attr_r ); + //@} + + private: + class Impl; + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates LookupAttr Stream output. */ + std::ostream & operator<<( std::ostream & str, const LookupAttr & obj ) ZYPP_API; + + /** \relates LookupAttr Verbose stream output including the query result. */ + std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupRepoAttr + // + /** Lightweight repository attribute value lookup. + * + * This is just a convenience class that overloads all + * \ref LookupAttr methods which take a \ref LookupAttr::Location + * argument and sets it to \ref REPO_ATTR. + * + * \code + * // look for a repo attribute in the pool: + * sat::LookupAttr p( sat::SolvAttr::repositoryAddedFileProvides, sat::LookupAttr::REPO_ATTR ); + * + * // Equivalent but using LookupRepoAttr: + * sat::LookupRepoAttr q( sat::SolvAttr::repositoryAddedFileProvides ); + * \endcode + * + * \see \ref LookupAttr + */ + class LookupRepoAttr : public LookupAttr + { + public: + /** \copydoc LookupAttr::LookupAttr() */ + LookupRepoAttr() + {} + /** \copydoc LookupAttr::LookupAttr(SolvAttr) */ + explicit LookupRepoAttr( SolvAttr attr_r ) + : LookupAttr( std::move(attr_r), REPO_ATTR ) + {} + /** \copydoc LookupAttr::LookupAttr(SolvAttr,Repository) */ + explicit LookupRepoAttr( SolvAttr attr_r, Repository repo_r ); + + public: + /** \copydoc LookupAttr::setPool */ + void setPool() + { LookupAttr::setPool( REPO_ATTR ); } + /** \copydoc LookupAttr::setRepo */ + void setRepo( Repository repo_r ); + private: + // Hide. You can't look inside and outside Solvables at the same time. + using LookupAttr::solvable; + using LookupAttr::setSolvable; + }; + /////////////////////////////////////////////////////////////////// + + namespace detail + { + /** Wrapper around sat \c detail::CDataiterator. + * + * Manages copy and assign, and release of allocated + * resources like datamatcher inside the dataiterator. + * Also maintains a copy of the matchstring in order to + * keep the char* passed to the dataiterator valid. + */ + class DIWrap + { + public: + /** \c NULL \c detail::CDataiterator */ + DIWrap() + : _dip( 0 ) + {} + /** Initializes */ + DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r, + std::string mstring_r = std::string(), int flags_r = 0 ); + /** \overload to catch \c NULL \a mstring_r. */ + DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r, + const char * mstring_r, int flags_r = 0 ); + DIWrap( const DIWrap & rhs ); + ~DIWrap(); + public: + void swap( DIWrap & rhs ) noexcept + { + if ( &rhs != this ) // prevent self assign! + { + std::swap( _dip, rhs._dip ); + std::swap( _mstring, rhs._mstring ); + } + } + DIWrap & operator=( const DIWrap & rhs ) + { + if ( &rhs != this ) // prevent self assign! + DIWrap( rhs ).swap( *this ); + return *this; + } + void reset() + { DIWrap().swap( *this ); } + public: + /** Evaluate in a boolean context ( _dip != NULL ). */ + explicit operator bool() const + { return _dip; } + + public: + detail::CDataiterator * operator->() const { return _dip; } + detail::CDataiterator * get() const { return _dip; } + const std::string & getstr() const { return _mstring; } + + private: + detail::CDataiterator * _dip; + std::string _mstring; + }; + /** \relates DIWrap Stream output. */ + std::ostream & operator<<( std::ostream & str, const DIWrap & obj ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupAttr::iterator + // + /** Result iterator. + * Extended iterator methods valid only if not @end. + * \note Implementation: Keep iterator_adaptor base and _dip in sync! + */ + class LookupAttr::iterator : public boost::iterator_adaptor< + iterator // Derived + , detail::CDataiterator * // Base + , detail::IdType // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , detail::IdType // Reference + > + { + public: + /** \name Moving fast forward. */ + //@{ + /** On the next call to \ref operator++ advance to the next \ref SolvAttr. */ + void nextSkipSolvAttr(); + + /** On the next call to \ref operator++ advance to the next \ref Solvable. */ + void nextSkipSolvable(); + + /** On the next call to \ref operator++ advance to the next \ref Repository. */ + void nextSkipRepo(); + + /** Immediately advance to the next \ref SolvAttr. */ + void skipSolvAttr() + { nextSkipSolvAttr(); increment(); } + + /** Immediately advance to the next \ref Solvable. */ + void skipSolvable() + { nextSkipSolvable(); increment(); } + + /** Immediately advance to the next \ref Repository. */ + void skipRepo() + { nextSkipRepo(); increment(); } + + /** Stop after all matches in the current \ref Solvable are processed. */ + void stayInThisSolvable(); + + /** Stop after all matches in the current \ref Repository are processed. */ + void stayInThisRepo(); + //@} + + /** \name Current position info. */ + //@{ + /** The current \ref Repository. */ + Repository inRepo() const; + + /** The current \ref Solvable. */ + Solvable inSolvable() const; + + /** The current \ref SolvAttr. */ + SolvAttr inSolvAttr() const; + + /** Whether this points to the end of a query (Iterator is invalid). */ + bool atEnd() const + { return !_dip; } + //@} + + /** \name Test attribute value type. */ + //@{ + /** The current \ref SolvAttr type. */ + detail::IdType solvAttrType() const; + + /** Whether this is a numeric attribute (incl. boolean). */ + bool solvAttrNumeric() const; + + /** Whether this is a string attribute. */ + bool solvAttrString() const; + + /** Whether this string attribute is available as \ref IdString. */ + bool solvAttrIdString() const; + + /** Whether this is a CheckSum attribute.*/ + bool solvAttrCheckSum() const; + + /** Whether this is the entry to a sub-structure (flexarray). + * This is the entry to a sequence of attributes. To + * acces them use \ref subBegin and \ref subEnd. + */ + bool solvAttrSubEntry() const; + //@} + + /** \name Iterate sub-structures. + * + * These are usable iff \ref solvAttrSubEntry is \c true. + * + * \note Unfortunately the underlying libsolv dataiterator as returned + * by \ref subBegin and \ref subFind loses some context when being created. + * Thus, it's not possible to invoke \ref subBegin and \ref subFind on an + * iterator that was previously returned by one of those methods. The result + * will be an \c end iterator. For the same reason, it is not possible for an + * iterator to leave the sub-structure again. + * + * \code + * // Lookup all "update:reference" entries for a specific solvable + * sat::LookupAttr q( sat::SolvAttr::updateReference, p->satSolvable() ); + * for_( res, q.begin(), q.end() ) + * { + * // List all sub values + * for_( sub, res.subBegin(), res.subEnd() ) + * { + * cout << sub.asString() << endl; + * } + * + * // Directly access c specific value: + * sat::LookupAttr::iterator it( res.subFind( sat::SolvAttr::updateReferenceHref ) ); + * if ( it != res.subEnd() ) + * cout << it.asString() << endl; + * } + * \endcode + */ + //@{ + /** Whether the sub-structure is empty. */ + bool subEmpty() const; + + /** Ammount of attributes in the sub-structure. + * \note This is not a cheap call. It runs the query. + */ + size_type subSize() const; + + /** Iterator to the begin of a sub-structure. + * \see \ref solvAttrSubEntry + */ + iterator subBegin() const; + /** Iterator behind the end of a sub-structure. + * \see \ref solvAttrSubEntry + */ + iterator subEnd() const; + /** Iterator pointing to the first occurance of \ref SolvAttr \a attr_r in sub-structure. + * If \ref sat::SolvAttr::allAttr is passed, \ref subBegin is returned. + * \see \ref solvAttrSubEntry + */ + iterator subFind( const SolvAttr& attr_r ) const; + /** \overload Extending the current attribute name with by \c ":attrname_r". + * + * This assumes a sub-structur \c "update:reference" has attributes + * like \c "update:reference:type", \c "update:reference:href". + * + * If an empty \c attrname_r is passed, \ref subBegin is returned. + */ + iterator subFind( const C_Str & attrname_r ) const; + //@} + + /** \name Retrieving attribute values. */ + //@{ + /** Conversion to numeric types. */ + int asInt() const; + /** \overload */ + unsigned asUnsigned() const; + /** \overload */ + bool asBool() const; + /** \overload */ + unsigned long long asUnsignedLL() const; + + /** Conversion to string types. */ + const char * c_str() const; + /** \overload + * If used with non-string types, this method tries to create + * some appropriate string representation. + */ + std::string asString() const; + + /** As \ref IdStr. + * This is only done for poolized string types. Large strings like + * summary or descriptions are not available via \ref IdStr, only + * via \ref c_str and \ref asString. + */ + IdString idStr() const; + /** \overload Directly returning the \c Id */ + detail::IdType id() const + { return idStr().id(); } + + /** As \ref CheckSum. */ + CheckSum asCheckSum() const; + + /** Templated return type. + * Per default assumes an Id based type, so try to construct + * it from the Id. + * + * Should be specialized for supported types above. + */ + template Tp asType() const { return Tp(id()); } + //@} + + /////////////////////////////////////////////////////////////////// + // internal stuff below + /////////////////////////////////////////////////////////////////// + public: + iterator(); + + iterator( const iterator & rhs ); + + iterator & operator=( const iterator & rhs ); + + ~iterator(); + + public: + /** + * C-tor taking over ownership of the passed \c detail::CDataiterator + * and doing its first iteration (::dataiterator_step) + */ + iterator( detail::DIWrap & dip_r ); + + private: + friend class boost::iterator_core_access; + + template + bool equal( const boost::iterator_adaptor & rhs ) const + { + return ( bool(base()) == bool(rhs.base()) ) + && ( ! base() || dip_equal( *base(), *rhs.base() ) ); + } + + bool dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const; + + detail::IdType dereference() const; + + void increment(); + + public: + /** Expert backdoor. */ + detail::CDataiterator * get() const + { return _dip.get(); } + private: + detail::DIWrap _dip; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates LookupAttr::iterator Stream output. */ + std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + + /** \name Helpers and forward declarations from LookupAttrTools.h */ + //@{ + template<> inline int LookupAttr::iterator::asType() const { return asInt(); } + template<> inline unsigned LookupAttr::iterator::asType() const { return asUnsigned(); } + template<> inline unsigned long long LookupAttr::iterator::asType() const { return asUnsignedLL(); } + template<> inline bool LookupAttr::iterator::asType() const { return asBool(); } + template<> inline const char * LookupAttr::iterator::asType() const { return c_str(); } + template<> inline std::string LookupAttr::iterator::asType() const { return asString(); } + template<> inline IdString LookupAttr::iterator::asType() const { return idStr(); } + template<> CheckSum LookupAttr::iterator::asType() const; + + template + class ArrayAttr; + //@} + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +/** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */ +std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator * obj ); + +/** \relates LookupAttr::iterator Stream output of the underlying iterator for debug. */ +inline std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator & obj ) +{ return str << &obj; } + +#endif // ZYPP_SAT_LOOKUPATTR_H diff --git a/zypp/sat/LookupAttrTools.h b/zypp/sat/LookupAttrTools.h new file mode 100644 index 0000000..be70f3e --- /dev/null +++ b/zypp/sat/LookupAttrTools.h @@ -0,0 +1,225 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/LookupAttrTools.h + * +*/ +#ifndef ZYPP_SAT_LOOKUPATTRTOOLS_H +#define ZYPP_SAT_LOOKUPATTRTOOLS_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : LookupAttr::TransformIterator + // + /** TransformIterator returning an \ref iterator value of type \c TResult. + * + * The underlying LookupAttr::iterators value is retrieved \ref asType + * and the returned \ref ResultT is constructed fron that value. + * + * \code + * class Keywords + * { + * public: + * Keywords( sat::Solvable solv_r ) + * : _q( sat::SolvAttr::keywords, solv_r ) + * {} + * + * public: + * typedef sat::LookupAttr::TransformIterator iterator; + * + * iterator begin() const { return iterator( _q.begin() ); } + * iterator end() const { return iterator( _q.end() ); } + * + * private: + * sat::LookupAttr _q; + * }; + * \endcode + * + * \see \ref ArrayAttr. + */ + template + class LookupAttr::TransformIterator : public boost::iterator_adaptor< + TransformIterator // Derived + , LookupAttr::iterator // Base + , TResult // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , TResult // Reference + > + { + public: + TransformIterator() + {} + + explicit + TransformIterator( const LookupAttr::iterator & val_r ) + { this->base_reference() = val_r; } + + public: + + /** \name Moving fast forward. */ + //@{ + /** On the next call to \ref operator++ advance to the next \ref SolvAttr. */ + void nextSkipSolvAttr() + { this->base_reference().nextSkipSolvAttr(); } + + /** On the next call to \ref operator++ advance to the next \ref Solvable. */ + void nextSkipSolvable() + { this->base_reference().nextSkipSolvable(); } + + /** On the next call to \ref operator++ advance to the next \ref Repository. */ + void nextSkipRepo() + { this->base_reference().nextSkipRepo(); } + + /** Immediately advance to the next \ref SolvAttr. */ + void skipSolvAttr() + { this->base_reference().skipSolvAttr(); } + + /** Immediately advance to the next \ref Solvable. */ + void skipSolvable() + { this->base_reference().skipSolvable(); } + + /** Immediately advance to the next \ref Repository. */ + void skipRepo() + { this->base_reference().skipRepo(); } + //@} + + /** \name Current position info. */ + //@{ + /** The current \ref Repository. */ + Repository inRepo() const + { return this->base_reference().inRepo(); } + + /** The current \ref Solvabele. */ + Solvable inSolvable() const + { return this->base_reference().inSolvable(); } + + /** The current \ref SolvAttr. */ + SolvAttr inSolvAttr() const + { return this->base_reference().inSolvAttr(); } + //@} + + private: + friend class boost::iterator_core_access; + + TResult dereference() const + { + const LookupAttr::iterator lit( this->base_reference() ); + return TResult( lit.asType() ); + } + }; + /////////////////////////////////////////////////////////////////// + + template + class ArrayAttr; + + template + std::ostream & operator<<( std::ostream & str, const ArrayAttr & obj ); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ArrayAttr + // + /** \ref LookupAttr::TransformIterator based container to retrieve list attributes. + * + * You may pass \ref LookupAttr::REPO_ATTR as \ref LookupAttr::Location argument, + * to lookup attributes associated with the \ref Repository as a whole + * (e.g. repository keywords). + * + * \see \ref LookupAttr for details. + * + * \code + * typedef ArrayAttr Keywords; + * Keywords k( sat::SolvAttr::keywords ); + * dumpRange( MIL << "All Keywords: ", k.begin(), k.end() ) << endl; + * \endcode + * + * \todo Maybe add some way to unify the result. + */ + template + class ArrayAttr + { + friend std::ostream & operator<< ( std::ostream & str, const ArrayAttr & obj ); + + public: + ArrayAttr() + {} + + ArrayAttr( SolvAttr attr_r, LookupAttr::Location loc_r = LookupAttr::SOLV_ATTR ) + : _q( std::move(attr_r), loc_r ) + {} + + ArrayAttr( SolvAttr attr_r, Repository repo_r, LookupAttr::Location loc_r = LookupAttr::SOLV_ATTR ) + : _q( std::move(attr_r), repo_r, loc_r ) + {} + + ArrayAttr( SolvAttr attr_r, Solvable solv_r ) + : _q( std::move(attr_r), solv_r ) + {} + + public: + using iterator = LookupAttr::TransformIterator; + using size_type = LookupAttr::size_type; + + iterator begin() const + { return iterator( _q.begin() ); } + + iterator end() const + { return iterator( _q.end() ); } + + bool empty() const + { return _q.empty(); } + + size_type size() const + { + size_type count = 0; + for_( it, begin(), end() ) + ++count; + return count; + } + + public: + + iterator find( const TResult & key_r ) const + { + for_( it, begin(), end() ) + { + if ( *it == key_r ) + return it; + } + return end(); + } + + private: + LookupAttr _q; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates LookupAttr::iterator Stream output. */ + template + inline std::ostream & operator<<( std::ostream & str, const ArrayAttr & obj ) + { return dumpOn( str, obj._q ); } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_LOOKUPATTRTOOLS_H diff --git a/zypp/sat/Map.cc b/zypp/sat/Map.cc new file mode 100644 index 0000000..d55ca01 --- /dev/null +++ b/zypp/sat/Map.cc @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Map.cc + */ +extern "C" +{ +#include +} +#include +#include +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + template<> + sat::detail::CMap * rwcowClone( const sat::detail::CMap * rhs ) + { + sat::detail::CMap * ret = new sat::detail::CMap; + ::map_init_clone( ret, const_cast(rhs) ); + return ret; + } + + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + constexpr Map::PoolSizeType Map::poolSize; + + Map::Map() + : _pimpl( new detail::CMap ) + { ::map_init( _pimpl.get(), 0 ); } + + Map::Map( size_type size_r ) + : _pimpl( new detail::CMap ) + { ::map_init( _pimpl.get(), size_r ); } + + Map::Map( PoolSizeType ) + : _pimpl( new detail::CMap ) + { ::map_init( _pimpl.get(), Pool::instance().capacity() ); } + + Map::~Map() + { ::map_free( _pimpl.get() ); } + + bool Map::empty() const + { return( _pimpl->size == 0 ); } + + Map::size_type Map::size() const + { return _pimpl->size << 3; } + + void Map::grow( size_type size_r ) + { ::map_grow( _pimpl.get(), size_r ); } + + void Map::setAll() + { assignAll( true ); } + + void Map::clearAll() + { assignAll( false ); } + + void Map::assignAll( bool val_r ) + { + if ( _pimpl->size ) + ::memset( _pimpl->map, (val_r?-1:0), _pimpl->size ); + } + +#define M_RANGE_CKECK(IDX,LOC) if ( ((IDX) >> 3) >= size_type(_pimpl->size) ) throw std::out_of_range( "zypp::sat::Map::" LOC ) + + void Map::set( size_type idx_r ) + { + M_RANGE_CKECK( idx_r, "set" ); + MAPSET( _pimpl, idx_r ); + } + + void Map::clear( size_type idx_r ) + { + M_RANGE_CKECK( idx_r, "clear" ); + MAPCLR( _pimpl, idx_r ); + } + + void Map::assign( size_type idx_r, bool val_r ) + { + M_RANGE_CKECK( idx_r, "assign" ); + if ( val_r ) + { MAPSET( _pimpl, idx_r ); } + else + { MAPCLR( _pimpl, idx_r ); } + } + + bool Map::test( size_type idx_r ) const + { + M_RANGE_CKECK( idx_r, "test" ); + return MAPTST( _pimpl, idx_r ); + } + + std::string Map::asString( const char on_r, const char off_r ) const + { + if ( empty() ) + return std::string(); + + std::string ret( size(), off_r ); + for_( idx, size_type(0), size() ) + { + if ( test( idx ) ) + ret[idx] = on_r; + } + return ret; + } + + Map::operator detail::CMap *() // COW: nonconst version can't be inlined + { return _pimpl.get(); } // without exposing detail::CMap + + bool operator==( const Map & lhs, const Map & rhs ) + { + const detail::CMap * l = lhs; + const detail::CMap * r = rhs; + return( l == r || ( l->size == r->size && ::memcmp( l->map, r->map, l->size ) == 0 ) ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/Map.h b/zypp/sat/Map.h new file mode 100644 index 0000000..5f5ea8d --- /dev/null +++ b/zypp/sat/Map.h @@ -0,0 +1,136 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Map.h + */ +#ifndef ZYPP_SAT_MAP_H +#define ZYPP_SAT_MAP_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + /////////////////////////////////////////////////////////////////// + /// \class Map + /// \brief Libsolv (bit)Map wrapper. + /// + /// \Note Requested sizes are filled up to the next multiple of eight. + /// Libsolv bitmaps are not shrinkable. + /////////////////////////////////////////////////////////////////// + class ZYPP_API Map + { + public: + using size_type = unsigned long; + + /** Type to indicate the bitmap should match the current pools capacity. */ + struct PoolSizeType {}; + /** An object indicating the bitmap should match the current pools capacity. */ + static constexpr PoolSizeType poolSize = PoolSizeType(); + + public: + /** Default ctor: empty Map */ + Map(); + + /** Ctor taking the Map size */ + explicit Map( size_type size_r ); + + /** Ctor creating a Map matching the current pools capacity */ + Map( PoolSizeType ); + + /** Dtor */ + ~Map(); + + public: + /** Whether Map is empty. */ + bool empty() const; + + /** Size of the Map. */ + size_type size() const; + + /** Grow the Map if necessary. */ + void grow( size_type size_r ); + + public: + /** Set all bits. */ + void setAll(); + + /** Clear all bits. */ + void clearAll(); + + /** Assign \c val_r to all bits. */ + void assignAll( bool val_r ); + + /** Set bit \c idx_r. + * \throws std::out_of_range if \a idx_r is out of range + */ + void set( size_type idx_r ); + + /** Clear bit \c idx_r. + * \throws std::out_of_range if \a idx_r is out of range + */ + void clear( size_type idx_r ); + + /** Assign \c val_r to bit \c idx_r. + * \throws std::out_of_range if \a idx_r is out of range + */ + void assign( size_type idx_r, bool val_r ); + + public: + /** Test bit \c idx_r. + * \throws std::out_of_range if \a idx_r is out of range + */ + bool test( size_type idx_r ) const; + + /** Test bit \c idx_r. + * \throws std::out_of_range if \a idx_r is out of range + */ + bool operator[]( size_type idx_r ) const + { return test( idx_r ); } + + public: + /** String representation */ + std::string asString( const char on_r = '1', const char off_r = '0' ) const; + + public: + operator detail::CMap *(); ///< libsolv backdoor + operator const detail::CMap *() const ///< libsolv backdoor + { return _pimpl.get(); } + private: + RWCOW_pointer _pimpl; ///< Pointer to implementation + }; + + /** \relates Map Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Map & obj ) + { return str << obj.asString(); } + + /** \relates Map */ + bool operator==( const Map & lhs, const Map & rhs ) ZYPP_API; + + /** \relates Map */ + inline bool operator!=( const Map & lhs, const Map & rhs ) + { return !( lhs == rhs ); } + + } // namespace sat + /////////////////////////////////////////////////////////////////// + + /** \relates Map Clone function for RWCOW_pointer */ + template<> sat::detail::CMap * rwcowClone( const sat::detail::CMap * rhs ); + + using Bitmap = sat::Map; + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_MAP_H diff --git a/zypp/sat/Pool.cc b/zypp/sat/Pool.cc new file mode 100644 index 0000000..3eeddbe --- /dev/null +++ b/zypp/sat/Pool.cc @@ -0,0 +1,346 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Pool.cc + * +*/ +#include +#include +#include + +extern "C" +{ +#include +#include +#include +} + +#include +#include + +#include +#include +#include +#include + +#include + +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + const std::string & Pool::systemRepoAlias() + { return detail::PoolImpl::systemRepoAlias(); } + + detail::CPool * Pool::get() const + { return myPool().getPool(); } + + Pool::size_type Pool::capacity() const + { return myPool()->nsolvables; } + + const SerialNumber & Pool::serial() const + { return myPool().serial(); } + + const SerialNumber & Pool::serialIDs() const + { return myPool().serialIDs(); } + + void Pool::prepare() const + { return myPool().prepare(); } + + Pathname Pool::rootDir() const + { return myPool().rootDir(); } + + void Pool::rootDir( const Pathname & root_r ) + { return myPool().rootDir( root_r ); } + + bool Pool::reposEmpty() const + { return ! myPool()->urepos; } + + Pool::size_type Pool::reposSize() const + { return myPool()->urepos; } + + Pool::RepositoryIterator Pool::reposBegin() const + { + if ( myPool()->urepos ) + { // repos[0] == NULL + for_( it, myPool()->repos+1, myPool()->repos+myPool()->nrepos ) + if ( *it ) + return RepositoryIterator( it ); + } + return reposEnd(); + } + + Pool::RepositoryIterator Pool::reposEnd() const + { return RepositoryIterator( myPool()->repos+myPool()->nrepos ); } + + bool Pool::solvablesEmpty() const + { + // return myPool()->nsolvables; + // nsolvables is the array size including + // invalid Solvables. + for_( it, reposBegin(), reposEnd() ) + { + if ( ! it->solvablesEmpty() ) + return false; + } + return true; + } + + Pool::size_type Pool::solvablesSize() const + { + // Do not return myPool()->nsolvables; + // nsolvables is the array size including + // invalid Solvables. + size_type ret = 0; + for_( it, reposBegin(), reposEnd() ) + { + ret += it->solvablesSize(); + } + return ret; + } + + Pool::SolvableIterator Pool::solvablesBegin() const + { return SolvableIterator( myPool().getFirstId() ); } + + Pool::SolvableIterator Pool::solvablesEnd() const + { return SolvableIterator(); } + + sat::Queue Pool::whatMatchesDep( const SolvAttr &attr, const Capability &cap ) const + { + sat::Queue q; + pool_whatmatchesdep( get(), attr.id(), cap.id(), q, 0); + return q; + } + + Queue Pool::whatMatchesSolvable( const SolvAttr &attr, const Solvable &solv ) const + { + sat::Queue q; + pool_whatmatchessolvable( get(), attr.id(), static_cast( solv.id() ), q, 0 ); + return q; + } + + Queue Pool::whatContainsDep( const SolvAttr &attr, const Capability &cap ) const + { + sat::Queue q; + pool_whatcontainsdep( get(), attr.id(), cap.id(), q, 0 ); + return q; + } + + Repository Pool::reposInsert( const std::string & alias_r ) + { + Repository ret( reposFind( alias_r ) ); + if ( ret ) + return ret; + + ret = Repository( myPool()._createRepo( alias_r ) ); + if ( ret.isSystemRepo() ) + { + // autoprovide (dummy) RepoInfo + RepoInfo info; + info.setAlias( alias_r ); + info.setName( alias_r ); + info.setAutorefresh( true ); + info.setEnabled( true ); + ret.setInfo( info ); + } + return ret; + } + + Repository Pool::reposFind( const std::string & alias_r ) const + { + for_( it, reposBegin(), reposEnd() ) + { + if ( alias_r == it->alias() ) + return *it; + } + return Repository(); + } + + Repository Pool::findSystemRepo() const + { + return Repository( myPool().systemRepo() ); + } + + Repository Pool::systemRepo() + { + if ( myPool().systemRepo() ) + return Repository( myPool().systemRepo() ); + return reposInsert( systemRepoAlias() ); + } + + Repository Pool::addRepoSolv( const Pathname & file_r, const std::string & alias_r ) + { + // Using a temporay repo! (The additional parenthesis are required.) + AutoDispose tmprepo( (Repository::EraseFromPool()) ); + *tmprepo = reposInsert( alias_r ); + tmprepo->addSolv( file_r ); + + // no exceptions so we keep it: + tmprepo.resetDispose(); + return tmprepo; + } + + Repository Pool::addRepoSolv( const Pathname & file_r ) + { return addRepoSolv( file_r, file_r.basename() ); } + + Repository Pool::addRepoSolv( const Pathname & file_r, const RepoInfo & info_r ) + { + Repository ret( addRepoSolv( file_r, info_r.alias() ) ); + ret.setInfo( info_r ); + return ret; + } + + ///////////////////////////////////////////////////////////////// + + Repository Pool::addRepoHelix( const Pathname & file_r, const std::string & alias_r ) + { + // Using a temporay repo! (The additional parenthesis are required.) + AutoDispose tmprepo( (Repository::EraseFromPool()) ); + *tmprepo = reposInsert( alias_r ); + tmprepo->addHelix( file_r ); + + // no exceptions so we keep it: + tmprepo.resetDispose(); + return tmprepo; + } + + Repository Pool::addRepoHelix( const Pathname & file_r ) + { return addRepoHelix( file_r, file_r.basename() ); } + + Repository Pool::addRepoHelix( const Pathname & file_r, const RepoInfo & info_r ) + { + Repository ret( addRepoHelix( file_r, info_r.alias() ) ); + ret.setInfo( info_r ); + return ret; + } + + ///////////////////////////////////////////////////////////////// + + void Pool::setTextLocale( const Locale & locale_r ) + { myPool().setTextLocale( locale_r ); } + + void Pool::setRequestedLocales( const LocaleSet & locales_r ) + { myPool().setRequestedLocales( locales_r ); } + + bool Pool::addRequestedLocale( const Locale & locale_r ) + { return myPool().addRequestedLocale( locale_r ); } + + bool Pool::eraseRequestedLocale( const Locale & locale_r ) + { return myPool().eraseRequestedLocale( locale_r ); } + + const LocaleSet & Pool::getRequestedLocales() const + { return myPool().getRequestedLocales(); } + + bool Pool::isRequestedLocale( const Locale & locale_r ) const + { return myPool().isRequestedLocale( locale_r ); } + + void Pool::initRequestedLocales( const LocaleSet & locales_r ) { myPool().initRequestedLocales( locales_r ); } + const LocaleSet & Pool::getAddedRequestedLocales() const { return myPool().getAddedRequestedLocales(); } + const LocaleSet & Pool::getRemovedRequestedLocales() const { return myPool().getRemovedRequestedLocales(); } + + const LocaleSet & Pool::getAvailableLocales() const + { return myPool().getAvailableLocales(); } + + bool Pool::isAvailableLocale( const Locale & locale_r ) const + { return myPool().isAvailableLocale( locale_r ); } + + const Pool::MultiversionList & Pool::multiversion() const + { return myPool().multiversionList(); } + + Queue Pool::autoInstalled() const { return myPool().autoInstalled(); } + void Pool::setAutoInstalled( const Queue & autoInstalled_r ){ myPool().setAutoInstalled( autoInstalled_r ); } + + void Pool::setNeedrebootSpec( sat::SolvableSpec needrebootSpec_r ) { myPool().setNeedrebootSpec( std::move(needrebootSpec_r) ); } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Pool & obj ) + { + return str << "sat::pool(" << obj.serial() << ")[" + << obj.capacity() << "]{" + << obj.reposSize() << "repos|" + << obj.solvablesSize() << "solv}"; + } + + ///////////////////////////////////////////////////////////////// + #undef ZYPP_BASE_LOGGER_LOGGROUP + #define ZYPP_BASE_LOGGER_LOGGROUP "solvidx" + + void updateSolvFileIndex( const Pathname & solvfile_r ) + { + AutoDispose solv( ::fopen( solvfile_r.c_str(), "re" ), ::fclose ); + if ( solv == NULL ) + { + solv.resetDispose(); + ERR << "Can't open solv-file: " << solv << endl; + return; + } + + std::string solvidxfile( solvfile_r.extend(".idx").asString() ); + if ( ::unlink( solvidxfile.c_str() ) == -1 && errno != ENOENT ) + { + ERR << "Can't unlink solv-idx: " << Errno() << endl; + return; + } + { + int fd = ::open( solvidxfile.c_str(), O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0644 ); + if ( fd == -1 ) + { + ERR << "Can't create solv-idx: " << Errno() << endl; + return; + } + ::close( fd ); + } + std::ofstream idx( solvidxfile.c_str() ); + + + detail::CPool * _pool = ::pool_create(); + detail::CRepo * _repo = ::repo_create( _pool, "" ); + if ( ::repo_add_solv( _repo, solv, 0 ) == 0 ) + { + int _id = 0; + detail::CSolvable * _solv = nullptr; + FOR_REPO_SOLVABLES( _repo, _id, _solv ) + { + if ( _solv ) + { +#define SEP '\t' +#define idstr(V) pool_id2str( _pool, _solv->V ) + if ( _solv->arch == ARCH_SRC || _solv->arch == ARCH_NOSRC ) + idx << "srcpackage:" << idstr(name) << SEP << idstr(evr) << SEP << "noarch" << endl; + else + idx << idstr(name) << SEP << idstr(evr) << SEP << idstr(arch) << endl; + } + } + } + else + { + ERR << "Can't read solv-file: " << ::pool_errstr( _pool ) << endl; + } + ::repo_free( _repo, 0 ); + ::pool_free( _pool ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/Pool.h b/zypp/sat/Pool.h new file mode 100644 index 0000000..e57126c --- /dev/null +++ b/zypp/sat/Pool.h @@ -0,0 +1,310 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Pool.h + * +*/ +#ifndef ZYPP_SAT_POOL_H +#define ZYPP_SAT_POOL_H + +#include + +#include + +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class SerialNumber; + class RepoInfo; + + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + class SolvableSpec; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Pool + // + /** Global sat-pool. + * + * Explicitly shared singleton \ref Pool::instance. + */ + class ZYPP_API Pool : protected detail::PoolMember + { + public: + using SolvableIterator = detail::SolvableIterator; + using RepositoryIterator = zypp::detail::RepositoryIterator; + using size_type = detail::size_type; + + public: + /** Singleton ctor. */ + static Pool instance() + { return Pool(); } + + /** Ctor from \ref PoolMember. */ + Pool( const detail::PoolMember & ) + {} + + public: + /** Internal array size for stats only. */ + size_type capacity() const; + + /** Housekeeping data serial number. */ + const SerialNumber & serial() const; + + /** Serial number changing whenever resusePoolIDs==true was used. ResPool must also invalidate its PoolItems! */ + const SerialNumber & serialIDs() const; + + /** Update housekeeping data if necessary (e.g. whatprovides). */ + void prepare() const; + + /** Get rootdir (for file conflicts check) */ + Pathname rootDir() const; + + /** Set rootdir (for file conflicts check) */ + void rootDir( const Pathname & root_r ); + + public: + /** Whether \ref Pool contains repos. */ + bool reposEmpty() const; + + /** Number of repos in \ref Pool. */ + size_type reposSize() const; + + /** Iterator to the first \ref Repository. */ + RepositoryIterator reposBegin() const; + + /** Iterator behind the last \ref Repository. */ + RepositoryIterator reposEnd() const; + + /** Iterate the repositories. */ + Iterable repos() const + { return makeIterable( reposBegin(), reposEnd() ); } + + /** Return a \ref Repository named \c alias_r. + * It a such a \ref Repository does not already exist + * a new empty \ref Repository is created. + */ + Repository reposInsert( const std::string & alias_r ); + + /** Find a \ref Repository named \c alias_r. + * Returns \ref noRepository if there is no such \ref Repository. + */ + Repository reposFind( const std::string & alias_r ) const; + + /** Remove a \ref Repository named \c alias_r. + * \see \ref Repository::eraseFromPool + */ + void reposErase( const std::string & alias_r ) + { reposFind( alias_r ).eraseFromPool(); } + + /** Remove all repos from the pool. + * This also shrinks a pool which may have become large + * after having added and removed repos lots of times. + */ + void reposEraseAll() + { while ( ! reposEmpty() ) reposErase( reposBegin()->alias() ); } + + public: + /** Reserved system repository alias \c @System. */ + static const std::string & systemRepoAlias(); + + /** Return the system repository if it is on the pool. */ + Repository findSystemRepo() const; + + /** Return the system repository, create it if missing. */ + Repository systemRepo(); + + public: + /** Load \ref Solvables from a solv-file into a \ref Repository named \c name_r. + * In case of an exception the \ref Repository is removed from the \ref Pool. + * \throws Exception if loading the solv-file fails. + * \see \ref Repository::EraseFromPool + */ + Repository addRepoSolv( const Pathname & file_r, const std::string & name_r ); + /** \overload Using the files basename as \ref Repository name. */ + Repository addRepoSolv( const Pathname & file_r ); + /** \overload Using the \ref RepoInfo::alias \ref Repo name. + * Additionally stores the \ref RepoInfo. \See \ref Prool::setInfo. + */ + Repository addRepoSolv( const Pathname & file_r, const RepoInfo & info_r ); + + public: + /** Load \ref Solvables from a helix-file into a \ref Repository named \c name_r. + * Supports loading of gzip compressed files (.gz). In case of an exception + * the \ref Repository is removed from the \ref Pool. + * \throws Exception if loading the helix-file fails. + * \see \ref Repository::EraseFromPool + */ + Repository addRepoHelix( const Pathname & file_r, const std::string & name_r ); + /** \overload Using the files basename as \ref Repository name. */ + Repository addRepoHelix( const Pathname & file_r ); + /** \overload Using the \ref RepoInfo::alias \ref Repo name. + * Additionally stores the \ref RepoInfo. \See \ref Prool::setInfo. + */ + Repository addRepoHelix( const Pathname & file_r, const RepoInfo & info_r ); + + public: + /** Whether \ref Pool contains solvables. */ + bool solvablesEmpty() const; + + /** Number of solvables in \ref Pool. */ + size_type solvablesSize() const; + + /** Iterator to the first \ref Solvable. */ + SolvableIterator solvablesBegin() const; + + /** Iterator behind the last \ref Solvable. */ + SolvableIterator solvablesEnd() const; + + /** Iterate the solvables. */ + Iterable solvables() const + { return makeIterable( solvablesBegin(), solvablesEnd() ); } + + public: + /** \name Iterate all Solvables matching a \c TFilter. */ + //@{ + template + filter_iterator filterBegin( const TFilter & filter_r ) const + { return make_filter_iterator( filter_r, solvablesBegin(), solvablesEnd() ); } + + template + filter_iterator filterEnd( const TFilter & filter_r ) const + { return make_filter_iterator( filter_r, solvablesEnd(), solvablesEnd() ); } + //@} + + public: + /** Conainer of all \ref Solvable providing \c cap_r. */ + WhatProvides whatProvides( Capability cap_r ) const + { return WhatProvides( cap_r ); } + + Queue whatMatchesDep( const SolvAttr &attr, const Capability &cap ) const; + Queue whatMatchesSolvable ( const SolvAttr &attr, const Solvable &solv ) const; + Queue whatContainsDep ( const SolvAttr &attr, const Capability &cap ) const; + + public: + /** \name Requested locales. */ + //@{ + /** Set the default language for retrieving translated texts. + * Updated when calling \ref ZConfig::setTextLocale. + */ + void setTextLocale( const Locale & locale_r ); + + /** Set the requested locales. + * Languages to be supported by the system, e.g. language specific + * packages to be installed. + */ + void setRequestedLocales( const LocaleSet & locales_r ); + + /** Add one \ref Locale to the set of requested locales. + * Return \c true if \c locale_r was newly added to the set. + */ + bool addRequestedLocale( const Locale & locale_r ); + + /** Erase one \ref Locale from the set of requested locales. + * Return \c false if \c locale_r was not found in the set. + */ + bool eraseRequestedLocale( const Locale & locale_r ); + + /** Return the requested locales. + * \see \ref setRequestedLocales + */ + const LocaleSet & getRequestedLocales() const; + + /** Whether this \ref Locale is in the set of requested locales. */ + bool isRequestedLocale( const Locale & locale_r ) const; + + + /** Start tracking changes based on this \a locales_r. */ + void initRequestedLocales( const LocaleSet & locales_r ); + + /** Added since last initRequestedLocales. */ + const LocaleSet & getAddedRequestedLocales() const; + + /** Removed since last initRequestedLocales.*/ + const LocaleSet & getRemovedRequestedLocales() const; + + + /** Get the set of available locales. + * This is computed from the package data so it actually + * represents all locales packages claim to support. + */ + const LocaleSet & getAvailableLocales() const; + + /** Whether this \ref Locale is in the set of available locales. */ + bool isAvailableLocale( const Locale & locale_r ) const; + //@} + + public: + /** \name Multiversion install. + * Whether the pool contains packages which are multiversion installable. + * \see \ref Solvable::multiversionInstall + * \see \ref ZConfig::multiversionSpec + */ + //@{ + using MultiversionList = SolvableSet; + const MultiversionList & multiversion() const; + /** \deprecated Legacy, use multiversion().empty() instead. */ + ZYPP_DEPRECATED bool multiversionEmpty() const { return multiversion().empty(); } + //@} + + public: + /** \name Autoinstalled */ + //@{ + /** Get ident list of all autoinstalled solvables. */ + Queue autoInstalled() const; + /** Set ident list of all autoinstalled solvables. */ + void setAutoInstalled( const Queue & autoInstalled_r ); + //@} + + public: + /** \name Needreboot */ + //@{ + /** Solvables which should trigger the reboot-needed hint if installed/updated. */ + void setNeedrebootSpec( sat::SolvableSpec needrebootSpec_r ); + //@} + + public: + /** Expert backdoor. */ + detail::CPool * get() const; + private: + /** Default ctor */ + Pool() {} + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Pool Stream output */ + std::ostream & operator<<( std::ostream & str, const Pool & obj ) ZYPP_API; + + /** \relates Pool */ + inline bool operator==( const Pool & lhs, const Pool & rhs ) + { return lhs.get() == rhs.get(); } + + /** \relates Pool */ + inline bool operator!=( const Pool & lhs, const Pool & rhs ) + { return lhs.get() != rhs.get(); } + + /** Create solv file content digest for zypper bash completion */ + void updateSolvFileIndex( const Pathname & solvfile_r ); + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_POOL_H diff --git a/zypp/sat/Queue.cc b/zypp/sat/Queue.cc new file mode 100644 index 0000000..c4bccd0 --- /dev/null +++ b/zypp/sat/Queue.cc @@ -0,0 +1,146 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Queue.cc + */ +extern "C" +{ +#include +} +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + + template<> + sat::detail::CQueue * rwcowClone( const sat::detail::CQueue * rhs ) + { + sat::detail::CQueue * ret = new sat::detail::CQueue; + ::queue_init_clone( ret, const_cast(rhs) ); + return ret; + } + + /////////////////////////////////////////////////////////////////// + namespace sat + { + + Queue::Queue() + : _pimpl( new detail::CQueue ) + { ::queue_init( _pimpl.get() ); } + + Queue::~Queue() + { ::queue_free( _pimpl.get() ); } + + bool Queue::empty() const + { return( _pimpl->count == 0 ); } + + Queue::size_type Queue::size() const + { return _pimpl->count; } + + Queue::const_iterator Queue::begin() const + { return _pimpl->elements; } + + Queue::const_iterator Queue::end() const + { return _pimpl->elements + _pimpl->count;} + + Queue::const_iterator Queue::find( value_type val_r ) const + { + for_( it, begin(), end() ) + if ( *it == val_r ) + return it; + return end(); + } + + Queue::value_type Queue::first() const + { + if ( _pimpl->count ) + return *_pimpl->elements; + return 0; + } + + Queue::value_type Queue::last() const + { + if ( _pimpl->count ) + return _pimpl->elements[_pimpl->count-1]; + return 0; + } + +#define M_RANGE_CKECK(IDX,LOC) if ( IDX >= size_type(_pimpl->count) ) throw std::out_of_range( "zypp::sat::Queue::" LOC ) + + const Queue::value_type & Queue::at( size_type idx_r ) const + { M_RANGE_CKECK( idx_r, "at" ); return _pimpl->elements[idx_r]; } + + Queue::value_type & Queue::at( size_type idx_r ) + { M_RANGE_CKECK( idx_r, "at" ); return _pimpl->elements[idx_r]; } + + const Queue::value_type & Queue::operator[]( size_type idx_r ) const + { return _pimpl->elements[idx_r]; } + + Queue::value_type & Queue::operator[]( size_type idx_r ) + { return _pimpl->elements[idx_r]; } + + void Queue::clear() + { ::queue_empty( *this ); } + + void Queue::remove( value_type val_r ) + { + for ( const_iterator it( find( val_r ) ); it != end(); it = find( val_r ) ) + ::queue_delete( _pimpl.get(), it - begin() ); + } + + void Queue::push( value_type val_r ) + { ::queue_push( _pimpl.get(), val_r ); } + + void Queue::pushUnique( value_type val_r ) + { ::queue_pushunique( _pimpl.get(), val_r ); } + + Queue::value_type Queue::pop() + { return ::queue_pop( _pimpl.get() ); } + + void Queue::push_front( value_type val_r ) + { ::queue_unshift( _pimpl.get(), val_r ); } + + Queue::value_type Queue::pop_front() + { return ::queue_shift( _pimpl.get() ); } + + Queue::operator detail::CQueue *() // COW: nonconst version can't be inlined + { return _pimpl.get(); } // without exposing detail::CQueue + + std::ostream & operator<<( std::ostream & str, const Queue & obj ) + { return dumpRangeLine( str << "Queue ", obj.begin(), obj.end() ); } + + std::ostream & dumpOn( std::ostream & str, const Queue & obj ) + { + str << "Queue {"; + if ( ! obj.empty() ) + { + str << endl; + for_( it, obj.begin(), obj.end() ) + str << " " << Solvable(*it) << endl; + } + return str << "}"; + } + + bool operator==( const Queue & lhs, const Queue & rhs ) + { + const detail::CQueue * l = lhs; + const detail::CQueue * r = rhs; + return( l == r || ( l->count == r->count && ::memcmp( l->elements, r->elements, l->count ) == 0 ) ); + } + + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/Queue.h b/zypp/sat/Queue.h new file mode 100644 index 0000000..c44a3a6 --- /dev/null +++ b/zypp/sat/Queue.h @@ -0,0 +1,139 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Queue.h + */ +#ifndef ZYPP_SAT_QUEUE_H +#define ZYPP_SAT_QUEUE_H + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + class Queue; + using SolvableQueue = Queue; ///< Queue with Solvable ids + using StringQueue = Queue; ///< Queue with String ids + + /////////////////////////////////////////////////////////////////// + /// \class Queue + /// \brief Libsolv Id queue wrapper. + /// \todo template value_type to work with IString and other Id based types + /////////////////////////////////////////////////////////////////// + class ZYPP_API Queue + { + public: + using size_type = unsigned int; + using value_type = detail::IdType; + using const_iterator = const value_type *; + + public: + /** Default ctor: empty Queue. */ + Queue(); + + /** Dtor */ + ~Queue(); + + bool empty() const; + size_type size() const; + const_iterator begin() const; + const_iterator end() const; + + /** Return iterator to the 1st occurance of \a val_r or \ref end. */ + const_iterator find( value_type val_r ) const; + + /** Return whether the Queue contais at lest one element with value \a val_r. */ + bool contains( value_type val_r ) const + { return( find( val_r ) != end() ); } + + /** Return the 1st Id in the queue or \c 0 if empty. */ + value_type first() const; + + /** Return the last Id in the queue or \c 0 if empty. */ + value_type last() const; + + /** Return the Id at \a idx_r in the queue + * \throws std::out_of_range if \a idx_r is out of range + */ + const value_type & at( size_type idx_r ) const; + + /** Return the Id at \a idx_r in the queue + * \throws std::out_of_range if \a idx_r is out of range + */ + value_type & at( size_type idx_r ); + + /** Return the Id at \a idx_r in the queue (no range check) */ + const value_type & operator[]( size_type idx_r ) const; + + /** Return the Id at \a idx_r in the queue (no range check) */ + value_type & operator[]( size_type idx_r ); + + /** Clear the queue. */ + void clear(); + + /** Remove all occurances of \a val_r from the queue. */ + void remove( value_type val_r ); + + /** Push a value to the end off the Queue. */ + void push( value_type val_r ); + /** \overload */ + void push_back( value_type val_r ) + { push( val_r ); } + + /** Push a value if it's not yet in the Queue. */ + void pushUnique( value_type val_r ); + + /** Pop and return the last Id from the queue or \c 0 if empty. */ + value_type pop(); + /** \overload */ + value_type pop_back() + { return pop(); } + + /** Push a value to the beginning off the Queue. */ + void push_front( value_type val_r ); + + /** Pop and return the 1st Id from the queue or \c 0 if empty. */ + value_type pop_front(); + + public: + operator detail::CQueue *(); ///< libsolv backdoor + operator const detail::CQueue *() const ///< libsolv backdoor + { return _pimpl.get(); } + private: + RWCOW_pointer _pimpl; ///< Pointer to implementation + }; + + /** \relates Queue Stream output */ + std::ostream & operator<<( std::ostream & str, const Queue & obj ) ZYPP_API; + + /** \relates Queue Stream output assuming a Solvable queue. */ + std::ostream & dumpOn( std::ostream & str, const Queue & obj ) ZYPP_API; + + /** \relates Queue */ + bool operator==( const Queue & lhs, const Queue & rhs ) ZYPP_API; + + /** \relates Queue */ + inline bool operator!=( const Queue & lhs, const Queue & rhs ) + { return !( lhs == rhs ); } + + } // namespace sat + /////////////////////////////////////////////////////////////////// + + /** \relates Queue Clone function for RWCOW_pointer */ + template<> sat::detail::CQueue * rwcowClone( const sat::detail::CQueue * rhs ); + +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_QUEUE_H diff --git a/zypp/sat/SolvAttr.cc b/zypp/sat/SolvAttr.cc new file mode 100644 index 0000000..2460eb8 --- /dev/null +++ b/zypp/sat/SolvAttr.cc @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/SolvAttr.cc + * +*/ +extern "C" +{ +#include +} + +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +namespace sat +{ ///////////////////////////////////////////////////////////////// + + const SolvAttr SolvAttr::allAttr( detail::noId ); + const SolvAttr SolvAttr::noAttr; + +// There are some attributes here which are not provided by solv files. +// At least the ones that do nat have a solv/knownid. + + const SolvAttr SolvAttr::name ( SOLVABLE_NAME ); + const SolvAttr SolvAttr::edition ( SOLVABLE_EVR ); + const SolvAttr SolvAttr::arch ( SOLVABLE_ARCH ); + const SolvAttr SolvAttr::vendor ( SOLVABLE_VENDOR ); + + const SolvAttr SolvAttr::provides ( SOLVABLE_PROVIDES ); + const SolvAttr SolvAttr::obsoletes ( SOLVABLE_OBSOLETES ); + const SolvAttr SolvAttr::conflicts ( SOLVABLE_CONFLICTS ); + const SolvAttr SolvAttr::requires ( SOLVABLE_REQUIRES ); + const SolvAttr SolvAttr::recommends ( SOLVABLE_RECOMMENDS ); + const SolvAttr SolvAttr::suggests ( SOLVABLE_SUGGESTS ); + const SolvAttr SolvAttr::supplements ( SOLVABLE_SUPPLEMENTS ); + const SolvAttr SolvAttr::enhances ( SOLVABLE_ENHANCES ); + + const SolvAttr SolvAttr::summary ( SOLVABLE_SUMMARY ); // translated + const SolvAttr SolvAttr::description ( SOLVABLE_DESCRIPTION ); // translated + const SolvAttr SolvAttr::insnotify ( SOLVABLE_MESSAGEINS ); // translated + const SolvAttr SolvAttr::delnotify ( SOLVABLE_MESSAGEDEL ); // translated + const SolvAttr SolvAttr::eula ( SOLVABLE_EULA ); // translated + const SolvAttr SolvAttr::cpeid ( SOLVABLE_CPEID ); + const SolvAttr SolvAttr::installtime ( SOLVABLE_INSTALLTIME ); + const SolvAttr SolvAttr::buildtime ( SOLVABLE_BUILDTIME ); + const SolvAttr SolvAttr::installsize ( SOLVABLE_INSTALLSIZE ); + const SolvAttr SolvAttr::downloadsize ( SOLVABLE_DOWNLOADSIZE ); + const SolvAttr SolvAttr::diskusage ( SOLVABLE_DISKUSAGE ); + + //package + const SolvAttr SolvAttr::checksum ( SOLVABLE_CHECKSUM ); + const SolvAttr SolvAttr::medianr ( SOLVABLE_MEDIANR ); + const SolvAttr SolvAttr::mediafile ( SOLVABLE_MEDIAFILE ); + const SolvAttr SolvAttr::mediadir ( SOLVABLE_MEDIADIR ); + const SolvAttr SolvAttr::changelog ( "changelog" ); + const SolvAttr SolvAttr::buildhost ( SOLVABLE_BUILDHOST ); + const SolvAttr SolvAttr::distribution ( SOLVABLE_DISTRIBUTION ); + const SolvAttr SolvAttr::license ( SOLVABLE_LICENSE ); + const SolvAttr SolvAttr::packager ( SOLVABLE_PACKAGER ); + const SolvAttr SolvAttr::group ( SOLVABLE_GROUP ); + const SolvAttr SolvAttr::keywords ( SOLVABLE_KEYWORDS ); + const SolvAttr SolvAttr::sourcesize ( "sourcesize" ); + const SolvAttr SolvAttr::authors ( SOLVABLE_AUTHORS ); + const SolvAttr SolvAttr::filelist ( SOLVABLE_FILELIST ); + const SolvAttr SolvAttr::sourcearch ( SOLVABLE_SOURCEARCH ); + const SolvAttr SolvAttr::sourcename ( SOLVABLE_SOURCENAME ); + const SolvAttr SolvAttr::sourceevr ( SOLVABLE_SOURCEEVR ); + const SolvAttr SolvAttr::headerend ( SOLVABLE_HEADEREND ); + const SolvAttr SolvAttr::url ( SOLVABLE_URL ); + + // patch + const SolvAttr SolvAttr::patchcategory ( SOLVABLE_PATCHCATEGORY ); + const SolvAttr SolvAttr::rebootSuggested ( UPDATE_REBOOT ); + const SolvAttr SolvAttr::restartSuggested ( UPDATE_RESTART ); + const SolvAttr SolvAttr::reloginSuggested ( UPDATE_RELOGIN ); + const SolvAttr SolvAttr::message ( UPDATE_MESSAGE ); + const SolvAttr SolvAttr::severity ( UPDATE_SEVERITY ); + const SolvAttr SolvAttr::updateStatus ( UPDATE_STATUS ); + const SolvAttr SolvAttr::updateCollection ( UPDATE_COLLECTION ); + const SolvAttr SolvAttr::updateCollectionName ( UPDATE_COLLECTION_NAME ); + const SolvAttr SolvAttr::updateCollectionEvr ( UPDATE_COLLECTION_EVR ); + const SolvAttr SolvAttr::updateCollectionArch ( UPDATE_COLLECTION_ARCH ); + const SolvAttr SolvAttr::updateCollectionFilename ( UPDATE_COLLECTION_FILENAME ); + const SolvAttr SolvAttr::updateCollectionFlags ( UPDATE_COLLECTION_FLAGS ); + const SolvAttr SolvAttr::updateReference ( UPDATE_REFERENCE ); + const SolvAttr SolvAttr::updateReferenceType ( UPDATE_REFERENCE_TYPE ); + const SolvAttr SolvAttr::updateReferenceHref ( UPDATE_REFERENCE_HREF ); + const SolvAttr SolvAttr::updateReferenceId ( UPDATE_REFERENCE_ID ); + const SolvAttr SolvAttr::updateReferenceTitle ( UPDATE_REFERENCE_TITLE ); + + //pattern + const SolvAttr SolvAttr::isvisible ( SOLVABLE_ISVISIBLE ); + const SolvAttr SolvAttr::icon ( SOLVABLE_ICON ); + const SolvAttr SolvAttr::order ( SOLVABLE_ORDER ); + const SolvAttr SolvAttr::isdefault ( "isdefault" ); + const SolvAttr SolvAttr::category ( SOLVABLE_CATEGORY ); // translated + const SolvAttr SolvAttr::script ( "script" ); + const SolvAttr SolvAttr::includes ( SOLVABLE_INCLUDES ); + const SolvAttr SolvAttr::extends ( SOLVABLE_EXTENDS ); + + // product + const SolvAttr SolvAttr::productReferenceFile ( PRODUCT_REFERENCEFILE ); + const SolvAttr SolvAttr::productProductLine ( PRODUCT_PRODUCTLINE ); + const SolvAttr SolvAttr::productShortlabel ( PRODUCT_SHORTLABEL ); + const SolvAttr SolvAttr::productDistproduct ( PRODUCT_DISTPRODUCT ); + const SolvAttr SolvAttr::productDistversion ( PRODUCT_DISTVERSION ); + const SolvAttr SolvAttr::productType ( PRODUCT_TYPE ); + const SolvAttr SolvAttr::productFlags ( PRODUCT_FLAGS ); + const SolvAttr SolvAttr::productEndOfLife ( PRODUCT_ENDOFLIFE ); + const SolvAttr SolvAttr::productRegisterTarget ( PRODUCT_REGISTER_TARGET ); + const SolvAttr SolvAttr::productRegisterRelease( PRODUCT_REGISTER_RELEASE ); + const SolvAttr SolvAttr::productRegisterFlavor ( PRODUCT_REGISTER_FLAVOR ); + const SolvAttr SolvAttr::productUrl ( PRODUCT_URL ); + const SolvAttr SolvAttr::productUrlType ( PRODUCT_URL_TYPE ); + /** array of repoids, hopefully label s too */ + const SolvAttr SolvAttr::productUpdates ( PRODUCT_UPDATES ); + const SolvAttr SolvAttr::productUpdatesRepoid ( PRODUCT_UPDATES_REPOID ); + + // repository + const SolvAttr SolvAttr::repositoryDeltaInfo ( REPOSITORY_DELTAINFO ); + const SolvAttr SolvAttr::repositoryAddedFileProvides ( REPOSITORY_ADDEDFILEPROVIDES ); + const SolvAttr SolvAttr::repositoryRpmDbCookie ( REPOSITORY_RPMDBCOOKIE ); + const SolvAttr SolvAttr::repositoryTimestamp ( REPOSITORY_TIMESTAMP ); + const SolvAttr SolvAttr::repositoryExpire ( REPOSITORY_EXPIRE ); + /** array of repositoryProductLabel repositoryProductCpeid pairs */ + const SolvAttr SolvAttr::repositoryUpdates ( REPOSITORY_UPDATES ); + /** array of repositoryProductLabel repositoryProductCpeid pairs */ + const SolvAttr SolvAttr::repositoryDistros ( REPOSITORY_DISTROS ); + const SolvAttr SolvAttr::repositoryProductLabel ( REPOSITORY_PRODUCT_LABEL ); + const SolvAttr SolvAttr::repositoryProductCpeid ( REPOSITORY_PRODUCT_CPEID ); + const SolvAttr SolvAttr::repositoryRepoid ( REPOSITORY_REPOID ); + const SolvAttr SolvAttr::repositoryKeywords ( REPOSITORY_KEYWORDS ); + const SolvAttr SolvAttr::repositoryRevision ( REPOSITORY_REVISION ); + const SolvAttr SolvAttr::repositoryToolVersion ( REPOSITORY_TOOLVERSION ); + + + + ///////////////////////////////////////////////////////////////// + + SolvAttr SolvAttr::parent() const + { + switch( id() ) + { + case UPDATE_COLLECTION_NAME: + case UPDATE_COLLECTION_EVR: + case UPDATE_COLLECTION_ARCH: + case UPDATE_COLLECTION_FILENAME: + case UPDATE_COLLECTION_FLAGS: + return updateCollection; + break; + + case UPDATE_REFERENCE_TYPE: + case UPDATE_REFERENCE_HREF: + case UPDATE_REFERENCE_ID: + case UPDATE_REFERENCE_TITLE: + return updateReference; + break; + } + return noAttr; + } + +} // namespace sat + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/SolvAttr.h b/zypp/sat/SolvAttr.h new file mode 100644 index 0000000..63d1519 --- /dev/null +++ b/zypp/sat/SolvAttr.h @@ -0,0 +1,214 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvAttr.h + * +*/ +#ifndef ZYPP_SAT_SOLVATTR_H +#define ZYPP_SAT_SOLVATTR_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +namespace sat +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SolvAttr + // + /** Solvable attribute keys. + * + * Attributes associated with individual solvables, + * or with the repository as a whole. + * + * \note If you add well known subsructure attributes, update \ref parent. + * + * \see \ref LookupAttr + */ + class ZYPP_API SolvAttr : public IdStringType + { + public: + /** \name Some builtin SolvAttr constants. */ + //@{ + /** Value to request searching all Attributes (0). */ + static const SolvAttr allAttr; + /** Value representing \c noAttr ("")*/ + static const SolvAttr noAttr; + + /** \name special solvable attributes which are part of the ::Solvable struct */ + //@{ + static const SolvAttr name; + static const SolvAttr edition; + static const SolvAttr arch; + static const SolvAttr vendor; + //@} + + /** \name dependency attributes */ + //@{ + static const SolvAttr provides; + static const SolvAttr obsoletes; + static const SolvAttr conflicts; +#if __GNUC__ >= 10 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wc++20-compat" +#endif + static const SolvAttr requires; +#if __GNUC__ >= 10 +#pragma GCC diagnostic pop +#endif + static const SolvAttr recommends; + static const SolvAttr suggests; + static const SolvAttr supplements; + static const SolvAttr enhances; + + /** \name common */ + //@{ + static const SolvAttr summary; + static const SolvAttr description; + static const SolvAttr insnotify; + static const SolvAttr delnotify; + static const SolvAttr eula; + static const SolvAttr installtime; + static const SolvAttr buildtime; + static const SolvAttr installsize; + static const SolvAttr downloadsize; + static const SolvAttr diskusage; + static const SolvAttr cpeid; + //@} + + /** \name package */ + //@{ + static const SolvAttr checksum; + static const SolvAttr mediadir; + static const SolvAttr medianr; + static const SolvAttr mediafile; + static const SolvAttr changelog; + static const SolvAttr buildhost; + static const SolvAttr distribution; + static const SolvAttr license; + static const SolvAttr packager; + static const SolvAttr group; + static const SolvAttr keywords; + static const SolvAttr sourcesize; + static const SolvAttr authors; + static const SolvAttr filelist; + static const SolvAttr sourcearch; + static const SolvAttr sourcename; + static const SolvAttr sourceevr; + static const SolvAttr headerend; + static const SolvAttr url; + //@} + + /** \name patch */ + //@{ + static const SolvAttr patchcategory; + static const SolvAttr rebootSuggested; + static const SolvAttr restartSuggested; + static const SolvAttr reloginSuggested; + static const SolvAttr message; + static const SolvAttr severity; + static const SolvAttr updateStatus; // "retracted", "stable",... + static const SolvAttr updateCollection; // SUB-STRUCTURE: + static const SolvAttr updateCollectionName; // name + static const SolvAttr updateCollectionEvr; // evr + static const SolvAttr updateCollectionArch; // arch + static const SolvAttr updateCollectionFilename; // filename + static const SolvAttr updateCollectionFlags; // flags + static const SolvAttr updateReference; // SUB-STRUCTURE: + static const SolvAttr updateReferenceType; // type + static const SolvAttr updateReferenceHref; // href + static const SolvAttr updateReferenceId; // id + static const SolvAttr updateReferenceTitle; // title + //@} + + /** \name pattern */ + //@{ + static const SolvAttr isvisible; + static const SolvAttr icon; + static const SolvAttr order; + static const SolvAttr isdefault; + static const SolvAttr category; + static const SolvAttr script; + static const SolvAttr includes; + static const SolvAttr extends; + //@} + + /** \name product */ + //@{ + static const SolvAttr productReferenceFile; + static const SolvAttr productProductLine; + static const SolvAttr productShortlabel; + static const SolvAttr productDistproduct; + static const SolvAttr productDistversion; + static const SolvAttr productType; + static const SolvAttr productFlags; + static const SolvAttr productEndOfLife; + static const SolvAttr productRegisterTarget; + static const SolvAttr productRegisterRelease; + static const SolvAttr productRegisterFlavor; + static const SolvAttr productUrl; + static const SolvAttr productUrlType; + static const SolvAttr productUpdates; // SUB-STRUCTURE: + static const SolvAttr productUpdatesRepoid; // repoid + //@} + + /** \name repository */ + //@{ + static const SolvAttr repositoryDeltaInfo; + static const SolvAttr repositoryAddedFileProvides; + static const SolvAttr repositoryRpmDbCookie; + static const SolvAttr repositoryTimestamp; + static const SolvAttr repositoryExpire; + static const SolvAttr repositoryUpdates; + static const SolvAttr repositoryDistros; + static const SolvAttr repositoryProductLabel; + static const SolvAttr repositoryProductCpeid; + static const SolvAttr repositoryRepoid; + static const SolvAttr repositoryKeywords; + static const SolvAttr repositoryRevision; + static const SolvAttr repositoryToolVersion; + //@} + + //@} + public: + /** Default ctor: \ref noAttr */ + SolvAttr() {} + + /** Ctor taking kind as string. */ + explicit SolvAttr( sat::detail::IdType id_r ) : _str( id_r ) {} + explicit SolvAttr( const IdString & idstr_r ) : _str( idstr_r ) {} + explicit SolvAttr( const std::string & str_r ) : _str( str_r ) {} + explicit SolvAttr( const char * cstr_r ) : _str( cstr_r ) {} + + /** Return the parent of well know sub-structure attributes (\ref SolvAttr::noAttr if none). + * \li \ref updateCollection + * \li \ref updateReference + */ + SolvAttr parent() const; + + /** Whether this is a well know sub-structure attribute. */ + bool hasParent() const + { return parent() != noAttr; } + + private: + friend class IdStringType; + IdString _str; + }; + + ///////////////////////////////////////////////////////////////// +} // namespace sat +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_sat_SolvAttr_H diff --git a/zypp/sat/SolvIterMixin.cc b/zypp/sat/SolvIterMixin.cc new file mode 100644 index 0000000..2c2845c --- /dev/null +++ b/zypp/sat/SolvIterMixin.cc @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvIterMixin.cc + * +*/ +//#include +//#include + +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + namespace solvitermixin_detail + { + bool UnifyByIdent::operator()( const Solvable & solv_r ) const + { + // Need to use pool::ByIdent because packages and srcpackages have the same id. + return( solv_r && _uset->insert( pool::ByIdent( solv_r ).get() ).second ); + } + } + + /////////////////////////////////////////////////////////////////// + // asSolvable + /////////////////////////////////////////////////////////////////// + Solvable asSolvable::operator()( const PoolItem & pi_r ) const + { + return pi_r.satSolvable(); + } + + Solvable asSolvable::operator()( const ResObject_constPtr & res_r ) const + { + return res_r ? res_r->satSolvable() : Solvable(); + } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + Selectable_Ptr asSelectable::operator()( const sat::Solvable & sov_r ) const + { + return ResPool::instance().proxy().lookup( sov_r ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/SolvIterMixin.h b/zypp/sat/SolvIterMixin.h new file mode 100644 index 0000000..8ca7ba0 --- /dev/null +++ b/zypp/sat/SolvIterMixin.h @@ -0,0 +1,213 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvIterMixin.h + * +*/ +#ifndef ZYPP_SAT_SOLVITERMIXIN_H +#define ZYPP_SAT_SOLVITERMIXIN_H + +#include + +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + class Solvable; + //class asSolvable; // transform functor + + namespace solvitermixin_detail + { + /** Unify by \c ident \c (kind:name). + * Return true on the 1st appearance of a new \c ident. This is + * used in \ref SolvIterMixin when mapping a Solvable iterator + * to a Selectable iterator. + */ + struct ZYPP_API UnifyByIdent + { + bool operator()( const Solvable & solv_r ) const; + + using Uset = std::unordered_set; + UnifyByIdent() + : _uset( new Uset ) + {} + shared_ptr _uset; + }; + + + } // namespace solvitermixin_detail + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SolvIterMixin + // + /** Base class providing common iterator types based on a \ref Solvable iterator. + * + * A class deriving from \ref SolvIterMixin must provide two methods + * \c begin and \c end returning iterator over \ref sat::Solvable. + * + * \ref SolvIterMixin will then provide iterators over the corresponding + * \ref PoolItem and \ref ui::Selectable_Ptr. + * + * \ref SolvIterMixin will also provide default implementations for \ref empty + * and \ref size by iterating from \c begin to \c end. In case \c Derived is + * able to provide a more efficient implementation, the methods should be overloaded. + * + * \note You will sometimes face the problem, that when using the \ref PoolItem + * iterator you hit multiple version of the same package, while when using the + * \ref ui::Selectable iterator the information which of the available candidates + * actually matched got lost. In this case class \ref PoolItemBest may help you. + * Use it to pick the best version only. + * + * \code + * namespace detail + * { + * class WhatProvidesIterator; + * } + * + * class WhatProvides : public SolvIterMixin + * { + * public: + * typedef detail::WhatProvidesIterator const_iterator; + * + * // Iterator pointing to the first Solvable. + * const_iterator begin() const; + * + * // Iterator pointing behind the last Solvable. + * const_iterator end() const; + * + * }; + * + * namespace detail + * { + * class WhatProvidesIterator : public boost::iterator_adaptor< + * WhatProvidesIterator // Derived + * , const detail::IdType * // Base + * , const Solvable // Value + * , boost::forward_traversal_tag // CategoryOrTraversal + * , const Solvable // Reference + * > + * { + * ... + * }; + * } + * \endcode + * \ingroup g_CRTP + */ + template + class SolvIterMixin + { + public: + using size_type = size_t; + + public: + /** \name Convenience methods. + * In case \c Derived is able to provide a more efficient implementation, + * the methods should be overloaded. + */ + //@{ + /** Whether the collection is epmty. */ + bool empty() const + { return( self().begin() == self().end() ); } + + /** Size of the collection. */ + size_type size() const + { size_type s = 0; for_( it, self().begin(), self().end() ) ++s; return s;} + + /** Whether collection contains a specific \ref Solvable. */ + template + bool contains( const TSolv & solv_r ) const + { + Solvable solv( asSolvable()( solv_r ) ); + for_( it, self().begin(), self().end() ) + if ( *it == solv ) + return true; + return false; + } + //@} + + public: + /** \name Iterate as Solvable */ + //@{ + using Solvable_iterator = DerivedSolvable_iterator; + Solvable_iterator solvableBegin() const + { return self().begin(); } + Solvable_iterator solvableEnd() const + { return self().end(); } + Iterable solvable() const + { return makeIterable( solvableBegin(), solvableEnd() ); } + //@} + + /** \name Iterate as PoolItem */ + //@{ + using PoolItem_iterator = transform_iterator; + PoolItem_iterator poolItemBegin() const + { return make_transform_iterator( solvableBegin(), asPoolItem() ); } + PoolItem_iterator poolItemEnd() const + { return make_transform_iterator( solvableEnd(), asPoolItem() ); } + Iterable poolItem() const + { return makeIterable( poolItemBegin(), poolItemEnd() ); } + //@} + + private: + using UnifiedSolvable_iterator = filter_iterator; + public: + /** \name Iterate ui::Selectable::Ptr */ + //@{ + using Selectable_iterator = transform_iterator; + Selectable_iterator selectableBegin() const + { return make_transform_iterator( unifiedSolvableBegin(), ui::asSelectable() ); } + Selectable_iterator selectableEnd() const + { return make_transform_iterator( unifiedSolvableEnd(), ui::asSelectable() ); } + Iterable selectable() const + { return makeIterable( selectableBegin(), selectableEnd() ); } + //@} + + private: + /** \name Iterate unified Solbvables to be transformed into Selectable. */ + //@{ + UnifiedSolvable_iterator unifiedSolvableBegin() const + { return make_filter_iterator( solvitermixin_detail::UnifyByIdent(), solvableBegin(), solvableEnd() ); } + UnifiedSolvable_iterator unifiedSolvableEnd() const + { return make_filter_iterator( solvitermixin_detail::UnifyByIdent(), solvableEnd(), solvableEnd() ); } + Iterable unifiedSolvable() const + { return makeIterable( unifiedSolvableBegin(), unifiedSolvableEnd() ); } + //@} + private: + const Derived & self() const + { return *static_cast( this ); } + protected: + SolvIterMixin() {} + ~SolvIterMixin() {} + SolvIterMixin(const SolvIterMixin &) = default; + SolvIterMixin & operator=(const SolvIterMixin &) = default; + SolvIterMixin(SolvIterMixin &&) noexcept = default; + SolvIterMixin &operator=(SolvIterMixin &&) noexcept = default; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_SOLVITERMIXIN_H diff --git a/zypp/sat/Solvable.cc b/zypp/sat/Solvable.cc new file mode 100644 index 0000000..d7c9518 --- /dev/null +++ b/zypp/sat/Solvable.cc @@ -0,0 +1,823 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Solvable.cc + * +*/ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + /////////////////////////////////////////////////////////////////// + namespace + { + void _doSplit( IdString & _ident, ResKind & _kind, IdString & _name ) + { + if ( ! _ident ) + return; + + ResKind explicitKind = ResKind::explicitBuiltin( _ident.c_str() ); + // NOTE: kind package and srcpackage do not have namespaced ident! + if ( ! explicitKind ) + { + _name = _ident; + // No kind defaults to package + if ( !_kind ) + _kind = ResKind::package; + else if ( ! ( _kind == ResKind::package || _kind == ResKind::srcpackage ) ) + _ident = IdString( str::form( "%s:%s", _kind.c_str(), _ident.c_str() ) ); + } + else + { + // strip kind spec from name + _name = IdString( ::strchr( _ident.c_str(), ':' )+1 ); + _kind = explicitKind; + if ( _kind == ResKind::package || _kind == ResKind::srcpackage ) + _ident = _name; + } + return; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + Solvable::SplitIdent::SplitIdent( IdString ident_r ) + : _ident( ident_r ) + { _doSplit( _ident, _kind, _name ); } + + Solvable::SplitIdent::SplitIdent( const char * ident_r ) + : _ident( ident_r ) + { _doSplit( _ident, _kind, _name ); } + + Solvable::SplitIdent::SplitIdent( const std::string & ident_r ) + : _ident( ident_r ) + { _doSplit( _ident, _kind, _name ); } + + Solvable::SplitIdent::SplitIdent( ResKind kind_r, IdString name_r ) + : _ident( name_r ) + , _kind(std::move( kind_r )) + { _doSplit( _ident, _kind, _name ); } + + Solvable::SplitIdent::SplitIdent( ResKind kind_r, const C_Str & name_r ) + : _ident( name_r ) + , _kind(std::move( kind_r )) + { _doSplit( _ident, _kind, _name ); } + + ///////////////////////////////////////////////////////////////// + // class Solvable + ///////////////////////////////////////////////////////////////// + + const Solvable Solvable::noSolvable; + + const IdString Solvable::retractedToken { "retracted-patch-package()" }; + const IdString Solvable::ptfMasterToken { "ptf()" }; + const IdString Solvable::ptfPackageToken { "ptf-package()" }; + + ///////////////////////////////////////////////////////////////// + + detail::CSolvable * Solvable::get() const + { return myPool().getSolvable( _id ); } + +#define NO_SOLVABLE_RETURN( VAL ) \ + detail::CSolvable * _solvable( get() ); \ + if ( ! _solvable ) return VAL + + Solvable Solvable::nextInPool() const + { return Solvable( myPool().getNextId( _id ) ); } + + Solvable Solvable::nextInRepo() const + { + NO_SOLVABLE_RETURN( noSolvable ); + for ( detail::SolvableIdType next = _id+1; next < unsigned(_solvable->repo->end); ++next ) + { + detail::CSolvable * nextS( myPool().getSolvable( next ) ); + if ( nextS && nextS->repo == _solvable->repo ) + { + return Solvable( next ); + } + } + return noSolvable; + } + + std::string Solvable::lookupStrAttribute( const SolvAttr & attr ) const + { + NO_SOLVABLE_RETURN( std::string() ); + const char * s = ::solvable_lookup_str( _solvable, attr.id() ); + return s ? s : std::string(); + } + + std::string Solvable::lookupStrAttribute( const SolvAttr & attr, const Locale & lang_r ) const + { + NO_SOLVABLE_RETURN( std::string() ); + const char * s = 0; + if ( !lang_r ) + { + s = ::solvable_lookup_str_poollang( _solvable, attr.id() ); + } + else + { + for ( Locale l( lang_r ); l; l = l.fallback() ) + { + if ( (s = ::solvable_lookup_str_lang( _solvable, attr.id(), l.c_str(), 0 )) ) + return s; + } + // here: no matching locale, so use default + s = ::solvable_lookup_str_lang( _solvable, attr.id(), 0, 0 ); + } + return s ? s : std::string(); + } + + unsigned long long Solvable::lookupNumAttribute( const SolvAttr & attr ) const + { + NO_SOLVABLE_RETURN( 0 ); + return ::solvable_lookup_num( _solvable, attr.id(), 0 ); + } + + unsigned long long Solvable::lookupNumAttribute( const SolvAttr & attr, unsigned long long notfound_r ) const + { + NO_SOLVABLE_RETURN( notfound_r ); + return ::solvable_lookup_num( _solvable, attr.id(), notfound_r ); + } + + bool Solvable::lookupBoolAttribute( const SolvAttr & attr ) const + { + NO_SOLVABLE_RETURN( false ); + return ::solvable_lookup_bool( _solvable, attr.id() ); + } + + detail::IdType Solvable::lookupIdAttribute( const SolvAttr & attr ) const + { + NO_SOLVABLE_RETURN( detail::noId ); + return ::solvable_lookup_id( _solvable, attr.id() ); + } + + CheckSum Solvable::lookupCheckSumAttribute( const SolvAttr & attr ) const + { + NO_SOLVABLE_RETURN( CheckSum() ); + detail::IdType chksumtype = 0; + const char * s = ::solvable_lookup_checksum( _solvable, attr.id(), &chksumtype ); + if ( ! s ) + return CheckSum(); + switch ( chksumtype ) + { + case REPOKEY_TYPE_MD5: return CheckSum::md5( s ); + case REPOKEY_TYPE_SHA1: return CheckSum::sha1( s ); + case REPOKEY_TYPE_SHA224: return CheckSum::sha224( s ); + case REPOKEY_TYPE_SHA256: return CheckSum::sha256( s ); + case REPOKEY_TYPE_SHA384: return CheckSum::sha384( s ); + case REPOKEY_TYPE_SHA512: return CheckSum::sha512( s ); + } + return CheckSum( std::string(), s ); // try to autodetect + } + + /////////////////////////////////////////////////////////////////// + namespace + { + inline Pathname lookupDatadirIn( Repository repor_r ) + { + static const SolvAttr susetagsDatadir( "susetags:datadir" ); + Pathname ret; + // First look for repo attribute "susetags:datadir". If not found, + // look into the solvables as Code11 libsolv placed it there. + LookupRepoAttr datadir( susetagsDatadir, repor_r ); + if ( ! datadir.empty() ) + ret = datadir.begin().asString(); + else + { + LookupAttr datadir( susetagsDatadir, repor_r ); + if ( ! datadir.empty() ) + ret = datadir.begin().asString(); + } + return ret; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + OnMediaLocation Solvable::lookupLocation() const + { + NO_SOLVABLE_RETURN( OnMediaLocation() ); + // medianumber and path + unsigned medianr = 0; + const char * file = ::solvable_lookup_location( _solvable, &medianr ); + if ( ! file ) + return OnMediaLocation(); + if ( ! medianr ) + medianr = 1; + + OnMediaLocation ret; + + Pathname path; + switch ( repository().info().type().toEnum() ) + { + case repo::RepoType::NONE_e: + { + path = lookupDatadirIn( repository() ); + if ( ! path.empty() ) + repository().info().setProbedType( repo::RepoType::YAST2_e ); + } + break; + + case repo::RepoType::YAST2_e: + { + path = lookupDatadirIn( repository() ); + if ( path.empty() ) + path = "suse"; + } + break; + + default: + break; + } + ret.setLocation ( path/file, medianr ); + ret.setDownloadSize( ByteCount( lookupNumAttribute( SolvAttr::downloadsize ) ) ); + ret.setChecksum ( lookupCheckSumAttribute( SolvAttr::checksum ) ); + // Not needed/available for solvables? + //ret.setOpenSize ( ByteCount( lookupNumAttribute( SolvAttr::opensize ) ) ); + //ret.setOpenChecksum( lookupCheckSumAttribute( SolvAttr::openchecksum ) ); + return ret; + } + + + IdString Solvable::ident() const + { + NO_SOLVABLE_RETURN( IdString() ); + return IdString( _solvable->name ); + } + + ResKind Solvable::kind() const + { + NO_SOLVABLE_RETURN( ResKind() ); + // detect srcpackages by 'arch' + switch ( _solvable->arch ) + { + case ARCH_SRC: + case ARCH_NOSRC: + return ResKind::srcpackage; + break; + } + + // either explicitly prefixed... + const char * ident = IdString( _solvable->name ).c_str(); + ResKind knownKind( ResKind::explicitBuiltin( ident ) ); + if ( knownKind ) + return knownKind; + + // ...or no ':' in package names (hopefully)... + const char * sep = ::strchr( ident, ':' ); + if ( ! sep ) + return ResKind::package; + + // ...or something unknown. + return ResKind( std::string( ident, sep-ident ) ); + } + + bool Solvable::isKind( const ResKind & kind_r ) const + { + NO_SOLVABLE_RETURN( false ); + + // detect srcpackages by 'arch' + switch ( _solvable->arch ) + { + case ARCH_SRC: + case ARCH_NOSRC: + return( kind_r == ResKind::srcpackage ); + break; + } + + // no ':' in package names (hopefully) + const char * ident = IdString( _solvable->name ).c_str(); + if ( kind_r == ResKind::package ) + { + return( ::strchr( ident, ':' ) == 0 ); + } + + // look for a 'kind:' prefix + const char * kind = kind_r.c_str(); + unsigned ksize = ::strlen( kind ); + return( ::strncmp( ident, kind, ksize ) == 0 + && ident[ksize] == ':' ); + } + + std::string Solvable::name() const + { + NO_SOLVABLE_RETURN( std::string() ); + const char * ident = IdString( _solvable->name ).c_str(); + const char * sep = ::strchr( ident, ':' ); + return( sep ? sep+1 : ident ); + } + + Edition Solvable::edition() const + { + NO_SOLVABLE_RETURN( Edition() ); + return Edition( _solvable->evr ); + } + + Arch Solvable::arch() const + { + NO_SOLVABLE_RETURN( Arch_noarch ); //ArchId() ); + switch ( _solvable->arch ) + { + case ARCH_SRC: + case ARCH_NOSRC: + return Arch_noarch; //ArchId( ARCH_NOARCH ); + break; + } + return Arch( IdString(_solvable->arch).asString() ); + //return ArchId( _solvable->arch ); + } + + IdString Solvable::vendor() const + { + NO_SOLVABLE_RETURN( IdString() ); + return IdString( _solvable->vendor ); + } + + Repository Solvable::repository() const + { + NO_SOLVABLE_RETURN( Repository::noRepository ); + return Repository( _solvable->repo ); + } + + RepoInfo Solvable::repoInfo() const + { return repository().info(); } + + + bool Solvable::isSystem() const + { + NO_SOLVABLE_RETURN( _id == detail::systemSolvableId ); + return myPool().isSystemRepo( _solvable->repo ); + } + + bool Solvable::onSystemByUser() const + { + return isSystem() && myPool().isOnSystemByUser( ident() ); + } + + bool Solvable::onSystemByAuto() const + { + return isSystem() && myPool().isOnSystemByAuto( ident() ); + } + + bool Solvable::identIsAutoInstalled( const IdString & ident_r ) + { + return myPool().isOnSystemByAuto( ident_r ); + } + + bool Solvable::isNeedreboot() const + { + NO_SOLVABLE_RETURN( false ); + return myPool().isNeedreboot( *this ); + } + + // TODO: Optimize + bool Solvable::isBlacklisted() const + { return isPtf() || isRetracted(); } + + bool Solvable::isRetracted() const + { + NO_SOLVABLE_RETURN( false ); + if ( isKind() ) + return myPool().isRetracted( *this ); + if ( isKind() ) + return lookupStrAttribute( SolvAttr::updateStatus ) == "retracted"; + return false; + } + + bool Solvable::isPtf() const + { return isPtfPackage() || isPtfMaster(); } + + bool Solvable::isPtfMaster() const + { + NO_SOLVABLE_RETURN( false ); + return myPool().isPtfMaster( *this ); + } + + bool Solvable::isPtfPackage() const + { + NO_SOLVABLE_RETURN( false ); + return myPool().isPtfPackage( *this ); + } + + + bool Solvable::multiversionInstall() const + { + NO_SOLVABLE_RETURN( false ); + return myPool().isMultiversion( *this ); + } + + Date Solvable::buildtime() const + { + NO_SOLVABLE_RETURN( Date() ); + return Date( lookupNumAttribute( SolvAttr::buildtime ) ); + } + + Date Solvable::installtime() const + { + NO_SOLVABLE_RETURN( Date() ); + return Date( lookupNumAttribute( SolvAttr::installtime ) ); + } + + std::string Solvable::asString() const + { + NO_SOLVABLE_RETURN( (_id == detail::systemSolvableId ? "systemSolvable" : "noSolvable") ); + return str::form( "%s-%s.%s", + IdString( _solvable->name ).c_str(), + IdString( _solvable->evr ).c_str(), + IdString( _solvable->arch ).c_str() ); + } + + std::string Solvable::asUserString() const\ + { + NO_SOLVABLE_RETURN( (_id == detail::systemSolvableId ? "systemSolvable" : "noSolvable") ); + return str::form( "%s-%s.%s (%s)", + IdString( _solvable->name ).c_str(), + IdString( _solvable->evr ).c_str(), + IdString( _solvable->arch ).c_str(), + repository().asUserString().c_str() ); + } + + bool Solvable::identical( const Solvable & rhs ) const + { + NO_SOLVABLE_RETURN( ! rhs.get() ); + detail::CSolvable * rhssolvable( rhs.get() ); + return rhssolvable && ( _solvable == rhssolvable || ::solvable_identical( _solvable, rhssolvable ) ); + } + + /////////////////////////////////////////////////////////////////// + namespace + { + inline Capabilities _getCapabilities( detail::IdType * idarraydata_r, ::Offset offs_r ) + { + return offs_r ? Capabilities( idarraydata_r + offs_r ) : Capabilities(); + } + } // namespace + /////////////////////////////////////////////////////////////////// + + Capabilities Solvable::provides() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->provides ); + } + Capabilities Solvable::requires() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->requires ); + } + Capabilities Solvable::conflicts() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->conflicts ); + } + Capabilities Solvable::obsoletes() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->obsoletes ); + } + Capabilities Solvable::recommends() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->recommends ); + } + Capabilities Solvable::suggests() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->suggests ); + } + Capabilities Solvable::enhances() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->enhances ); + } + Capabilities Solvable::supplements() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + return _getCapabilities( _solvable->repo->idarraydata, _solvable->supplements ); + } + Capabilities Solvable::prerequires() const + { + NO_SOLVABLE_RETURN( Capabilities() ); + // prerequires are a subset of requires + ::Offset offs = _solvable->requires; + return offs ? Capabilities( _solvable->repo->idarraydata + offs, detail::solvablePrereqMarker ) + : Capabilities(); + } + + CapabilitySet Solvable::providesNamespace( const std::string & namespace_r ) const + { + NO_SOLVABLE_RETURN( CapabilitySet() ); + CapabilitySet ret; + Capabilities caps( provides() ); + for_( it, caps.begin(), caps.end() ) + { + CapDetail caprep( it->detail() ); + if ( str::hasPrefix( caprep.name().c_str(), namespace_r ) && *(caprep.name().c_str()+namespace_r.size()) == '(' ) + ret.insert( *it ); + } + return ret; + } + + CapabilitySet Solvable::valuesOfNamespace( const std::string & namespace_r ) const + { + NO_SOLVABLE_RETURN( CapabilitySet() ); + CapabilitySet ret; + Capabilities caps( provides() ); + for_( it, caps.begin(), caps.end() ) + { + CapDetail caprep( it->detail() ); + if ( str::hasPrefix( caprep.name().c_str(), namespace_r ) && *(caprep.name().c_str()+namespace_r.size()) == '(' ) + { + std::string value( caprep.name().c_str()+namespace_r.size()+1 ); + value[value.size()-1] = '\0'; // erase the trailing ')' + ret.insert( Capability( value, caprep.op(), caprep.ed() ) ); + } + } + return ret; + } + + std::pair Solvable::matchesSolvable(const SolvAttr &attr, const Solvable &solv) const + { + sat::Queue capQueue; + int res = solvable_matchessolvable( get(), attr.id(), static_cast( solv.id() ), capQueue, 0 ); + + CapabilitySet caps; + if ( capQueue.size() ) + std::for_each( capQueue.begin(), capQueue.end(), [ &caps ]( auto cap ){ caps.insert( Capability(cap) );}); + + return std::make_pair( res == 1, std::move(caps) ); + } + + /////////////////////////////////////////////////////////////////// + namespace + { + /** Expand \ref Capability and call \c fnc_r for each namespace:language + * dependency. Return #invocations of fnc_r, negative if fnc_r returned + * false to indicate abort. + */ + int invokeOnEachSupportedLocale( Capability cap_r, const function& fnc_r ) + { + CapDetail detail( cap_r ); + if ( detail.kind() == CapDetail::EXPRESSION ) + { + switch ( detail.capRel() ) + { + case CapDetail::CAP_AND: + case CapDetail::CAP_OR: + // expand + { + int res = invokeOnEachSupportedLocale( detail.lhs(), fnc_r ); + if ( res < 0 ) + return res; // negative on abort. + int res2 = invokeOnEachSupportedLocale( detail.rhs(), fnc_r ); + if ( res2 < 0 ) + return -res + res2; // negative on abort. + return res + res2; + } + break; + + case CapDetail::CAP_NAMESPACE: + if ( detail.lhs().id() == NAMESPACE_LANGUAGE ) + { + return ( !fnc_r || fnc_r( Locale( IdString(detail.rhs().id()) ) ) ) ? 1 : -1; // negative on abort. + } + break; + + default: + break; // unwanted + } + } + return 0; + } + + /** Expand \ref Capability and call \c fnc_r for each namespace:language + * dependency. Return #invocations of fnc_r, negative if fnc_r returned + * false to indicate abort. + */ + inline int invokeOnEachSupportedLocale( Capabilities cap_r, const function& fnc_r ) + { + int cnt = 0; + for_( cit, cap_r.begin(), cap_r.end() ) + { + int res = invokeOnEachSupportedLocale( *cit, fnc_r ); + if ( res < 0 ) + return -cnt + res; // negative on abort. + cnt += res; + } + return cnt; + } + //@} + + // Functor returning false if a Locale is in the set. + struct NoMatchIn + { + NoMatchIn( const LocaleSet & locales_r ) : _locales( locales_r ) {} + + bool operator()( const Locale & locale_r ) const + { + return _locales.find( locale_r ) == _locales.end(); + } + + const LocaleSet & _locales; + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + bool Solvable::supportsLocales() const + { + // false_c stops on 1st Locale. + return invokeOnEachSupportedLocale( supplements(), functor::false_c() ) < 0; + } + + bool Solvable::supportsLocale( const Locale & locale_r ) const + { + // not_equal_to stops on == Locale. + return invokeOnEachSupportedLocale( supplements(), bind( std::not_equal_to(), locale_r, _1 ) ) < 0; + } + + bool Solvable::supportsLocale( const LocaleSet & locales_r ) const + { + if ( locales_r.empty() ) + return false; + // NoMatchIn stops if Locale is included. + return invokeOnEachSupportedLocale( supplements(), NoMatchIn(locales_r) ) < 0; + } + + bool Solvable::supportsRequestedLocales() const + { return supportsLocale( myPool().getRequestedLocales() ); } + + LocaleSet Solvable::getSupportedLocales() const + { + LocaleSet ret; + invokeOnEachSupportedLocale( supplements(), functor::collector( std::inserter( ret, ret.begin() ) ) ); + return ret; + } + + CpeId Solvable::cpeId() const + { + NO_SOLVABLE_RETURN( CpeId() ); + return CpeId( lookupStrAttribute( SolvAttr::cpeid ), CpeId::noThrow ); + } + + unsigned Solvable::mediaNr() const + { + NO_SOLVABLE_RETURN( 0U ); + // medianumber and path + unsigned medianr = 0U; + const char * file = ::solvable_lookup_location( _solvable, &medianr ); + if ( ! file ) + medianr = 0U; + else if ( ! medianr ) + medianr = 1U; + return medianr; + } + + ByteCount Solvable::installSize() const + { + NO_SOLVABLE_RETURN( ByteCount() ); + return ByteCount( lookupNumAttribute( SolvAttr::installsize ) ); + } + + ByteCount Solvable::downloadSize() const + { + NO_SOLVABLE_RETURN( ByteCount() ); + return ByteCount( lookupNumAttribute( SolvAttr::downloadsize ) ); + } + + std::string Solvable::distribution() const + { + NO_SOLVABLE_RETURN( std::string() ); + return lookupStrAttribute( SolvAttr::distribution ); + } + + std::string Solvable::summary( const Locale & lang_r ) const + { + NO_SOLVABLE_RETURN( std::string() ); + return lookupStrAttribute( SolvAttr::summary, lang_r ); + } + + std::string Solvable::description( const Locale & lang_r ) const + { + NO_SOLVABLE_RETURN( std::string() ); + return lookupStrAttribute( SolvAttr::description, lang_r ); + } + + std::string Solvable::insnotify( const Locale & lang_r ) const + { + NO_SOLVABLE_RETURN( std::string() ); + return lookupStrAttribute( SolvAttr::insnotify, lang_r ); + } + + std::string Solvable::delnotify( const Locale & lang_r ) const + { + NO_SOLVABLE_RETURN( std::string() ); + return lookupStrAttribute( SolvAttr::delnotify, lang_r ); + } + + std::string Solvable::licenseToConfirm( const Locale & lang_r ) const + { + NO_SOLVABLE_RETURN( std::string() ); + std::string ret = lookupStrAttribute( SolvAttr::eula, lang_r ); + if ( ret.empty() && isKind() ) + { + const RepoInfo & ri( repoInfo() ); + std::string riname( name() ); // "license-"+name with fallback "license" + if ( ! ri.hasLicense( riname ) ) + riname.clear(); + + if ( ri.needToAcceptLicense( riname ) || ! ui::Selectable::get( *this )->hasInstalledObj() ) + ret = ri.getLicense( riname, lang_r ); // bnc#908976: suppress informal license upon update + } + return ret; + } + + bool Solvable::needToAcceptLicense() const + { + NO_SOLVABLE_RETURN( false ); + if ( isKind() ) + { + const RepoInfo & ri( repoInfo() ); + std::string riname( name() ); // "license-"+name with fallback "license" + if ( ! ri.hasLicense( riname ) ) + riname.clear(); + + return ri.needToAcceptLicense( riname ); + } + return true; + } + + + std::ostream & operator<<( std::ostream & str, const Solvable & obj ) + { + if ( ! obj ) + return str << (obj.isSystem() ? "systemSolvable" : "noSolvable" ); + + return str << "(" << obj.id() << ")" + << ( obj.isKind( ResKind::srcpackage ) ? "srcpackage:" : "" ) << obj.ident() + << '-' << obj.edition() << '.' << obj.arch() << "(" + << obj.repository().alias() << ")"; + } + + std::ostream & dumpOn( std::ostream & str, const Solvable & obj ) + { + str << obj; + if ( obj ) + { +#define OUTS(X) if ( ! obj[Dep::X].empty() ) str << endl << " " #X " " << obj[Dep::X] + OUTS(PROVIDES); + OUTS(PREREQUIRES); + OUTS(REQUIRES); + OUTS(CONFLICTS); + OUTS(OBSOLETES); + OUTS(RECOMMENDS); + OUTS(SUGGESTS); + OUTS(ENHANCES); + OUTS(SUPPLEMENTS); +#undef OUTS + } + return str; + } + + std::ostream & dumpAsXmlOn( std::ostream & str, const Solvable & obj ) + { + xmlout::Node guard( str, "solvable" ); + + dumpAsXmlOn( *guard, obj.kind() ); + *xmlout::Node( *guard, "name" ) << obj.name(); + dumpAsXmlOn( *guard, obj.edition() ); + dumpAsXmlOn( *guard, obj.arch() ); + dumpAsXmlOn( *guard, obj.repository() ); + return str; + } + + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/Solvable.h b/zypp/sat/Solvable.h new file mode 100644 index 0000000..f48be2c --- /dev/null +++ b/zypp/sat/Solvable.h @@ -0,0 +1,584 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Solvable.h + * +*/ +#ifndef ZYPP_SAT_SOLVABLE_H +#define ZYPP_SAT_SOLVABLE_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + class ByteCount; + class CheckSum; + class CpeId; + class Date; + class OnMediaLocation; + /////////////////////////////////////////////////////////////////// + namespace sat + { + /////////////////////////////////////////////////////////////////// + /// \class Solvable + /// \brief A \ref Solvable object within the sat \ref Pool. + /// + /// \note Unfortunately libsolv combines the objects kind and + /// name in a single identifier \c "pattern:kde_multimedia", + /// \b except for packages and source packes. They are not prefixed + /// by any kind string. Instead the architecture is abused to store + /// \c "src" and \c "nosrc" values. + /// + /// \ref Solvable will hide this inconsistency by treating source + /// packages as an own kind of solvable and map their arch to + /// \ref Arch_noarch. + /////////////////////////////////////////////////////////////////// + class ZYPP_API Solvable : protected detail::PoolMember + { + public: + using IdType = sat::detail::SolvableIdType; + + static const IdString retractedToken; ///< Indicator provides `retracted-patch-package()` + static const IdString ptfMasterToken; ///< Indicator provides `ptf()` + static const IdString ptfPackageToken; ///< Indicator provides `ptf-package()` + + public: + /** Default ctor creates \ref noSolvable.*/ + Solvable() + : _id( detail::noSolvableId ) + {} + + Solvable(const Solvable &) = default; + Solvable(Solvable &&) noexcept = default; + Solvable &operator=(const Solvable &) = default; + Solvable &operator=(Solvable &&) noexcept = default; + + /** \ref PoolImpl ctor. */ + explicit Solvable( IdType id_r ) + : _id( id_r ) + {} + + public: + /** Represents no \ref Solvable. */ + static const Solvable noSolvable; + + /** Evaluate \ref Solvable in a boolean context (\c != \c noSolvable). */ + explicit operator bool() const + { return get(); } + + public: + /** The identifier. + * This is the solvables \ref name, \b except for packages and + * source packes, prefixed by its \ref kind. + */ + IdString ident()const; + + /** The Solvables ResKind. */ + ResKind kind()const; + + /** Test whether a Solvable is of a certain \ref ResKind. + * The test is far cheaper than actually retrieving and + * comparing the \ref kind. + */ + bool isKind( const ResKind & kind_r ) const; + /** \overload */ + template + bool isKind() const + { return isKind( resKind() ); } + /** \overload Extend the test to a range of \ref ResKind. */ + template + bool isKind( TIterator begin, TIterator end ) const + { for_( it, begin, end ) if ( isKind( *it ) ) return true; return false; } + + /** The name (without any ResKind prefix). */ + std::string name() const; + + /** The edition (version-release). */ + Edition edition() const; + + /** The architecture. */ + Arch arch() const; + + /** The vendor. */ + IdString vendor() const; + + /** The \ref Repository this \ref Solvable belongs to. */ + Repository repository() const; + /** The repositories \ref RepoInfo. */ + RepoInfo repoInfo() const; + + /** Return whether this \ref Solvable belongs to the system repo. + * \note This includes the otherwise hidden systemSolvable. + */ + bool isSystem() const; + + /** Whether this is known to be installed on behalf of a user request. + * \note Returns \c false for non-system (uninstalled) solvables. + */ + bool onSystemByUser() const; + + /** Whether this is known to be automatically installed (as dependency of a user request package). + * \note Returns \c false for non-system (uninstalled) solvables. + */ + bool onSystemByAuto() const; + + /** Whether an installed solvable with the same \ref ident is flagged as AutoInstalled. */ + bool identIsAutoInstalled() const + { return identIsAutoInstalled( ident() ); } + /** \overload static version */ + static bool identIsAutoInstalled( const IdString & ident_r ); + + /** Whether different versions of this package can be installed at the same time. + * Per default \c false. \see also \ref ZConfig::multiversion. + */ + bool multiversionInstall() const; + + /** Whether this solvable triggers the reboot-needed hint if installed/updated. */ + bool isNeedreboot() const; + + /** \name Blacklisted packages. + * + * Blacklisted packages are visible in a repository, but no matter how good they + * apparently look like, they must not be considered during normal operations. + * + * Under normal conditions the resolver will avoid selecting blacklisted packages. + * To install a blacklisted package it must be selected explicitly. Whether this + * is a good idea, depends on the reason for having been blacklisted: + * + * - RETRACTED packages are usually buggy packages/patches which have been released + * and can not be removed from the public repositories anymore. Nevertheless those + * packages should not be installed. + * + * - PTFs usually contain special features or fixes which are not yet released as + * an official patch upadate. Installing a PTF will prevent its packages from being + * updated until you decide to remove the PTF and follow the official releases again. + */ + //@{ + /** Whether this solvable is blacklisted (retracted,ptf,...). */ + bool isBlacklisted() const; + + /** Whether this solvable is retracted (provides \ref retractedToken). */ + bool isRetracted() const; + + /** Whether this solvable belongs to a PTF (provides \ref ptfMasterToken or \ref ptfPackageToken). */ + bool isPtf() const; + + /** Subset of \ref isPtf (provides \ref ptfMasterToken). */ + bool isPtfMaster() const; + + /** Subset of \ref isPtf (provides \ref ptfPackageToken). */ + bool isPtfPackage() const; + //@} + + /** The items build time. */ + Date buildtime() const; + + /** The items install time (\c false if not installed). */ + Date installtime() const; + + public: + /** String representation "ident-edition.arch" or \c "noSolvable" + * \code + * product:openSUSE-11.1.x86_64 + * autoyast2-2.16.19-0.1.src + * noSolvable + * \endcode + */ + std::string asString() const; + + /** String representation "ident-edition.arch(repo)" or \c "noSolvable" */ + std::string asUserString() const; + + /** Test whether two Solvables have the same content. + * Basically the same name, edition, arch, vendor and buildtime. + */ + bool identical( const Solvable & rhs ) const; + + /** Test for same name-version-release.arch */ + bool sameNVRA( const Solvable & rhs ) const + { return( get() == rhs.get() || ( ident() == rhs.ident() && edition() == rhs.edition() && arch() == rhs.arch() ) ); } + + public: + /** \name Access to the \ref Solvable dependencies. + * + * \note Prerequires are a subset of requires. + */ + //@{ + Capabilities provides() const; + Capabilities requires() const; + Capabilities conflicts() const; + Capabilities obsoletes() const; + Capabilities recommends() const; + Capabilities suggests() const; + Capabilities enhances() const; + Capabilities supplements() const; + Capabilities prerequires() const; + + /** Return \ref Capabilities selected by \ref Dep constant. */ + Capabilities dep( Dep which_r ) const + { + switch( which_r.inSwitch() ) + { + case Dep::PROVIDES_e: return provides(); break; + case Dep::REQUIRES_e: return requires(); break; + case Dep::CONFLICTS_e: return conflicts(); break; + case Dep::OBSOLETES_e: return obsoletes(); break; + case Dep::RECOMMENDS_e: return recommends(); break; + case Dep::SUGGESTS_e: return suggests(); break; + case Dep::ENHANCES_e: return enhances(); break; + case Dep::SUPPLEMENTS_e: return supplements(); break; + case Dep::PREREQUIRES_e: return prerequires(); break; + } + return Capabilities(); + } + /** \overload operator[] */ + Capabilities operator[]( Dep which_r ) const + { return dep( which_r ); } + + + /** Return the namespaced provides 'namespace([value])[ op edition]' of this Solvable. */ + CapabilitySet providesNamespace( const std::string & namespace_r ) const; + + /** Return 'value[ op edition]' for namespaced provides 'namespace(value)[ op edition]'. + * Similar to \ref providesNamespace, but the namespace is stripped from the + * dependencies. This is convenient if the namespace denotes packages that + * should be looked up. E.g. the \c weakremover namespace used in a products + * release package denotes the packages that were dropped from the distribution. + * \see \ref Product::droplist + */ + CapabilitySet valuesOfNamespace( const std::string & namespace_r ) const; + //@} + + std::pair matchesSolvable ( const SolvAttr &attr, const sat::Solvable &solv ) const; + + public: + /** \name Locale support. */ + //@{ + /** Whether this \c Solvable claims to support locales. */ + bool supportsLocales() const; + /** Whether this \c Solvable supports a specific \ref Locale. */ + bool supportsLocale( const Locale & locale_r ) const; + /** Whether this \c Solvable supports at least one of the specified locales. */ + bool supportsLocale( const LocaleSet & locales_r ) const; + /** Whether this \c Solvable supports at least one requested locale. + * \see \ref Pool::setRequestedLocales + */ + bool supportsRequestedLocales() const; + /** Return the supported locales. */ + LocaleSet getSupportedLocales() const; + /** \overload Legacy return via arg \a locales_r */ + void getSupportedLocales( LocaleSet & locales_r ) const + { locales_r = getSupportedLocales(); } + //@} + + public: + /** The solvables CpeId if available. */ + CpeId cpeId() const; + + /** Media number the solvable is located on (\c 0 if no media access required). */ + unsigned mediaNr() const; + + /** Installed (unpacked) size. + * This is just a total number. Many objects provide even more detailed + * disk usage data. You can use \ref DiskUsageCounter to find out + * how objects data are distributed across partitions/directories. + * \code + * // Load directory set into ducounter + * DiskUsageCounter ducounter( { "/", "/usr", "/var" } ); + * + * // see how noch space the packages use + * for ( const PoolItem & pi : pool ) + * { + * cout << pi << ducounter.disk_usage( pi ) << endl; + * // I__s_(7)GeoIP-1.4.8-3.1.2.x86_64(@System) { + * // dir:[/] [ bs: 0 B ts: 0 B us: 0 B (+-: 1.0 KiB)] + * // dir:[/usr] [ bs: 0 B ts: 0 B us: 0 B (+-: 133.0 KiB)] + * // dir:[/var] [ bs: 0 B ts: 0 B us: 0 B (+-: 1.1 MiB)] + * // } + * } + * \endcode + * \see \ref DiskUsageCounter + */ + ByteCount installSize() const; + + /** Download size. */ + ByteCount downloadSize() const; + + /** The distribution string. */ + std::string distribution() const; + + /** Short (singleline) text describing the solvable (opt. translated). */ + std::string summary( const Locale & lang_r = Locale() ) const; + + /** Long (multiline) text describing the solvable (opt. translated). */ + std::string description( const Locale & lang_r = Locale() ) const; + + /** UI hint text when selecting the solvable for install (opt. translated). */ + std::string insnotify( const Locale & lang_r = Locale() ) const; + /** UI hint text when selecting the solvable for uninstall (opt. translated).*/ + std::string delnotify( const Locale & lang_r = Locale() ) const; + + /** License or agreement to accept before installing the solvable (opt. translated). */ + std::string licenseToConfirm( const Locale & lang_r = Locale() ) const; + /** \c True except for well known exceptions (i.e show license but no need to accept it). */ + bool needToAcceptLicense() const; + + public: + /** Helper that splits an identifier into kind and name or vice versa. + * \note In case \c name_r is preceded by a well known kind spec, the + * \c kind_r argument is ignored, and kind is derived from name. + * \see \ref ident + */ + class SplitIdent + { + public: + SplitIdent() {} + SplitIdent( IdString ident_r ); + SplitIdent( const char * ident_r ); + SplitIdent( const std::string & ident_r ); + SplitIdent( ResKind kind_r, IdString name_r ); + SplitIdent( ResKind kind_r, const C_Str & name_r ); + + IdString ident() const { return _ident; } + ResKind kind() const { return _kind; } + IdString name() const { return _name; } + + private: + IdString _ident; + ResKind _kind; + IdString _name; + }; + + public: + /** \name Attribute lookup. + * \see \ref LookupAttr and \ref ArrayAttr providing a general, more + * query like interface for attribute retrieval. + */ + //@{ + /** + * returns the string attribute value for \ref attr + * or an empty string if it does not exists. + */ + std::string lookupStrAttribute( const SolvAttr & attr ) const; + /** \overload Trying to look up a translated string attribute. + * + * Returns the translation for \c lang_r. + * + * Passing an empty \ref Locale will return the string for the + * current default locale (\see \ref ZConfig::TextLocale), + * \b considering all fallback locales. + * + * Returns an empty string if no translation is available. + */ + std::string lookupStrAttribute( const SolvAttr & attr, const Locale & lang_r ) const; + + /** + * returns the numeric attribute value for \ref attr + * or 0 if it does not exists. + */ + unsigned long long lookupNumAttribute( const SolvAttr & attr ) const; + /** \overload returning custom notfound_r value */ + unsigned long long lookupNumAttribute( const SolvAttr & attr, unsigned long long notfound_r ) const; + + /** + * returns the boolean attribute value for \ref attr + * or \c false if it does not exists. + */ + bool lookupBoolAttribute( const SolvAttr & attr ) const; + + /** + * returns the id attribute value for \ref attr + * or \ref detail::noId if it does not exists. + */ + detail::IdType lookupIdAttribute( const SolvAttr & attr ) const; + + /** + * returns the CheckSum attribute value for \ref attr + * or an empty CheckSum if ir does not exist. + */ + CheckSum lookupCheckSumAttribute( const SolvAttr & attr ) const; + + /** + * returns OnMediaLocation data: This is everything we need to + * download e.g. an rpm (path, checksum, downloadsize, etc.). + */ + OnMediaLocation lookupLocation() const; + //@} + + public: + /** Return next Solvable in \ref Pool (or \ref noSolvable). */ + Solvable nextInPool() const; + /** Return next Solvable in \ref Repo (or \ref noSolvable). */ + Solvable nextInRepo() const; + /** Expert backdoor. */ + detail::CSolvable * get() const; + /** Expert backdoor. */ + IdType id() const { return _id; } + + private: + IdType _id; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Solvable Stream output */ + std::ostream & operator<<( std::ostream & str, const Solvable & obj ) ZYPP_API; + + /** \relates Solvable More verbose stream output including dependencies */ + std::ostream & dumpOn( std::ostream & str, const Solvable & obj ) ZYPP_API; + + /** \relates Solvable XML output */ + std::ostream & dumpAsXmlOn( std::ostream & str, const Solvable & obj ) ZYPP_API; + + /** \relates Solvable */ + inline bool operator==( const Solvable & lhs, const Solvable & rhs ) + { return lhs.get() == rhs.get(); } + + /** \relates Solvable */ + inline bool operator!=( const Solvable & lhs, const Solvable & rhs ) + { return lhs.get() != rhs.get(); } + + /** \relates Solvable */ + inline bool operator<( const Solvable & lhs, const Solvable & rhs ) + { return lhs.get() < rhs.get(); } + + /** \relates Solvable Test whether a \ref Solvable is of a certain Kind. */ + template + inline bool isKind( const Solvable & solvable_r ) + { return solvable_r.isKind( ResTraits::kind ); } + + /** \relates Solvable Test for same content. */ + inline bool identical( const Solvable & lhs, const Solvable & rhs ) + { return lhs.identical( rhs ); } + + /** \relates Solvable Test for same name version release and arch. */ + inline bool sameNVRA( const Solvable & lhs, const Solvable & rhs ) + { return lhs.sameNVRA( rhs ); } + + + /** \relates Solvable Compare according to \a kind and \a name. */ + inline int compareByN( const Solvable & lhs, const Solvable & rhs ) + { + int res = 0; + if ( lhs != rhs ) + { + if ( (res = lhs.kind().compare( rhs.kind() )) == 0 ) + res = lhs.name().compare( rhs.name() ); + } + return res; + } + + /** \relates Solvable Compare according to \a kind, \a name and \a edition. */ + inline int compareByNVR( const Solvable & lhs, const Solvable & rhs ) + { + int res = compareByN( lhs, rhs ); + if ( res == 0 ) + res = lhs.edition().compare( rhs.edition() ); + return res; + } + + /** \relates Solvable Compare according to \a kind, \a name, \a edition and \a arch. */ + inline int compareByNVRA( const Solvable & lhs, const Solvable & rhs ) + { + int res = compareByNVR( lhs, rhs ); + if ( res == 0 ) + res = lhs.arch().compare( rhs.arch() ); + return res; + } + + /////////////////////////////////////////////////////////////////// + namespace detail + { + /////////////////////////////////////////////////////////////////// + /// \class SolvableIterator + /// \brief Iterate over valid Solvables in the pool. + /// If the Solvable passed to the ctor is not valid, advance + /// to the next valid solvable (or Solvable::noSolvable if the + /// end is reached, + class SolvableIterator : public boost::iterator_adaptor< + SolvableIterator // Derived + , CSolvable* // Base + , const Solvable // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , const Solvable // Reference + > + { + public: + SolvableIterator() + : SolvableIterator::iterator_adaptor_( nullptr ) + {} + + explicit SolvableIterator( const Solvable & val_r ) + : SolvableIterator::iterator_adaptor_( nullptr ) + { initialAssignVal( val_r ); } + + explicit SolvableIterator( SolvableIdType id_r ) + : SolvableIterator::iterator_adaptor_( nullptr ) + { initialAssignVal( Solvable(id_r) ); } + + private: + friend class boost::iterator_core_access; + + Solvable dereference() const + { return _val; } + + void increment() + { assignVal( _val.nextInPool() ); } + + private: + void initialAssignVal( const Solvable & val_r ) + { assignVal( val_r ? val_r : val_r.nextInPool() ); } + + void assignVal( const Solvable & val_r ) + { _val = val_r; base_reference() = _val.get(); } + + Solvable _val; + }; + } // namespace detail + /////////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + + class PoolItem; + /////////////////////////////////////////////////////////////////// + namespace sat + { + /** To Solvable transform functor. + * \relates Solvable + * \relates sat::SolvIterMixin + */ + struct ZYPP_API asSolvable + { + using result_type = Solvable; + + Solvable operator()( const Solvable & solv_r ) const + { return solv_r; } + + Solvable operator()( const PoolItem & pi_r ) const; + + Solvable operator()( const ResObject_constPtr & res_r ) const; + }; + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +ZYPP_DEFINE_ID_HASHABLE( ::zypp::sat::Solvable ); + +#endif // ZYPP_SAT_SOLVABLE_H diff --git a/zypp/sat/SolvableSet.cc b/zypp/sat/SolvableSet.cc new file mode 100644 index 0000000..ee9c8f9 --- /dev/null +++ b/zypp/sat/SolvableSet.cc @@ -0,0 +1,41 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvableSet.cc + * +*/ +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const SolvableSet & obj ) + { + return dumpRange( str, obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/SolvableSet.h b/zypp/sat/SolvableSet.h new file mode 100644 index 0000000..9f5e943 --- /dev/null +++ b/zypp/sat/SolvableSet.h @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvableSet.h + * +*/ +#ifndef ZYPP_SAT_SOLVABLESET_H +#define ZYPP_SAT_SOLVABLESET_H + +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SolvableSet + // + /** Solvable set wrapper to allow adding additional convenience iterators. + */ + class SolvableSet : public SolvIterMixin::const_iterator> + { + friend std::ostream & operator<<( std::ostream & str, const SolvableSet & obj ); + + public: + using Container = std::unordered_set; + using value_type = Container::value_type; + using size_type = Container::size_type; + using const_iterator = Solvable_iterator; // from SolvIterMixin + + public: + /** Default ctor */ + SolvableSet() + : _pimpl( new Container ) + {} + + /** Ctor building a set from a range. */ + template + SolvableSet( TInputIterator begin_r, TInputIterator end_r ) + : _pimpl( new Container( begin_r, end_r ) ) + {} + + public: + /** Whether the set is epmty. */ + bool empty() const + { return _pimpl->empty(); } + + /** Size of the set. */ + size_type size() const + { return _pimpl->size(); } + + /** */ + template + bool contains( const TSolv & solv_r ) const + { return( get().count( asSolvable()( solv_r ) ) ); } + + /** Iterator pointing to the first \ref Solvable. */ + const_iterator begin() const + { return _pimpl->begin(); } + + /** Iterator pointing behind the last \ref Solvable. */ + const_iterator end() const + { return _pimpl->end(); } + + public: + /** Clear the container */ + void clear() + { get().clear(); } + + /** Insert a Solvable. + * \return \c true if it was actually inserted, or \c false if already present. + */ + template + bool insert( const TSolv & solv_r ) + { return get().insert( asSolvable()( solv_r ) ).second; } + + /** Insert a range of Solvables. */ + template + void insert( TIterator begin_r, TIterator end_r ) + { for_( it, begin_r, end_r ) insert( *it ); } + + public: + /** The set. */ + Container & get() + { return *_pimpl; } + + /** The set. */ + const Container & get() const + { return *_pimpl; } + + private: + /** Pointer to implementation */ + RWCOW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates SolvableSet Stream output */ + std::ostream & operator<<( std::ostream & str, const SolvableSet & obj ) ZYPP_API; + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_SOLVABLESET_H diff --git a/zypp/sat/SolvableSpec.cc b/zypp/sat/SolvableSpec.cc new file mode 100644 index 0000000..1fdfc15 --- /dev/null +++ b/zypp/sat/SolvableSpec.cc @@ -0,0 +1,207 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvableSpec.cc + */ +#include + +#include +#include + +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + /////////////////////////////////////////////////////////////////// + /// \class SolvableSpec::Impl + /// \brief SolvableSpec implementation. + /////////////////////////////////////////////////////////////////// + class SolvableSpec::Impl + { + public: + void addIdent( IdString ident_r ) + { + if ( ! ident_r.empty() ) + _idents.insert( ident_r ); + } + + void addProvides( Capability provides_r ) + { + if ( ! provides_r.empty() && _provides.insert( provides_r ).second ) + setDirty(); + } + + bool addIdenticalInstalledToo() const + { return _addIdenticalInstalledToo; } + + void addIdenticalInstalledToo( bool yesno_r ) + { + if ( yesno_r != _addIdenticalInstalledToo ) { + _addIdenticalInstalledToo = yesno_r; + if ( not _provides.empty() ) + setDirty(); + } + } + + void parse( const C_Str & spec_r ) + { + if ( str::hasPrefix( spec_r, "provides:" ) ) + addProvides( Capability(spec_r.c_str()+9) ); + else + addIdent( IdString(spec_r) ); + } + + + bool needed() const + { return !_provides.empty(); } + + bool dirty() const + { return needed() && !_cache; } + + void setDirty() const + { _cache.reset(); _cacheIdenticalInstalled.clear(); } + + const WhatProvides & cache() const + { + if ( !_cache ) + { + _cache.reset( new WhatProvides( _provides ) ); + if ( _addIdenticalInstalledToo ) { + for ( const auto & solv : *_cache ) { + if ( solv.isSystem() ) + continue; + auto pi { ui::Selectable::get(solv)->identicalInstalledObj( PoolItem(solv) ) }; + if ( pi ) + _cacheIdenticalInstalled.insert( pi ); + } + } + } + return *_cache; + } + + bool contains( const sat::Solvable & solv_r ) const + { + if ( _idents.count( solv_r.ident() ) ) + return true; + if ( needed() ) { + if ( cache().contains( solv_r ) ) + return true; + if ( _addIdenticalInstalledToo && _cacheIdenticalInstalled.contains( solv_r ) ) + return true; + } + return false; + } + + + const IdStringSet & idents() const + { return _idents; } + + const CapabilitySet & provides() const + { return _provides; } + + private: + IdStringSet _idents; + CapabilitySet _provides; + bool _addIdenticalInstalledToo = false; + mutable SolvableSet _cacheIdenticalInstalled; // follows _cache + mutable shared_ptr _cache; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + + /** \relates SolvableSpec::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const SolvableSpec::Impl & obj ) + { + str << "SolvableSpec {" << endl + << " Idents " << obj.idents() << endl + << " Provides " << obj.provides() << endl + << "}"; + return str; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SolvableSpec + // + /////////////////////////////////////////////////////////////////// + + SolvableSpec::SolvableSpec() + : _pimpl( new Impl ) + {} + + SolvableSpec::~SolvableSpec() + {} + + void SolvableSpec::addIdent( IdString ident_r ) + { _pimpl->addIdent( ident_r ); } + + void SolvableSpec::addProvides( Capability provides_r ) + { _pimpl->addProvides( provides_r ); } + + bool SolvableSpec::addIdenticalInstalledToo() const + { return _pimpl->addIdenticalInstalledToo(); } + void SolvableSpec::addIdenticalInstalledToo( bool yesno_r ) + { _pimpl->addIdenticalInstalledToo( yesno_r ); } + + void SolvableSpec::parse( const C_Str & spec_r ) + { _pimpl->parse( spec_r ); } + + void SolvableSpec::parseFrom( const InputStream & istr_r ) + { + iostr::simpleParseFile( istr_r, + [this]( int num_r, const std::string & line_r )->bool + { + this->parse( line_r ); + return true; + }); + } + + void SolvableSpec::splitParseFrom( const C_Str & multispec_r ) + { + std::vector v; + str::splitEscaped( multispec_r, std::back_inserter( v ), ", \t" ); + parseFrom( v.begin(), v.end() ); + } + + bool SolvableSpec::contains( const sat::Solvable & solv_r ) const + { return _pimpl->contains( solv_r ) && !solv_r.isKind( ResKind::srcpackage ); } + + bool SolvableSpec::dirty() const + { return _pimpl->dirty(); } + + void SolvableSpec::setDirty() const + { _pimpl->setDirty(); } + + bool SolvableSpec::empty() const + { return _pimpl->idents().empty() && _pimpl->provides().empty(); } + + bool SolvableSpec::containsIdent( const IdString & ident_r ) const + { return _pimpl->idents().count( ident_r ); } + + bool SolvableSpec::containsProvides( const Capability & provides_r ) const + { return _pimpl->provides().count( provides_r ); } + + std::ostream & operator<<( std::ostream & str, const SolvableSpec & obj ) + { return str << *obj._pimpl; } + + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/SolvableSpec.h b/zypp/sat/SolvableSpec.h new file mode 100644 index 0000000..63c6915 --- /dev/null +++ b/zypp/sat/SolvableSpec.h @@ -0,0 +1,133 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvableSpec.h + */ +#ifndef ZYPP_SAT_SOLVABLESPEC_H +#define ZYPP_SAT_SOLVABLESPEC_H + +#include + +#include +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + /////////////////////////////////////////////////////////////////// + /// \class SolvableSpec + /// \brief Define a set of \ref Solvables by ident and provides. + /// + /// Able to keep the definition of solvable sets like in 'needreboot' + /// or 'multiversion'. The associated file parser allows reading + /// stored definitions (one `IDENT` or provides:CAPABILITY` per line; + /// empty lines and lines starting with '#' are ignored). + /// + /// The use of provides requires re-computation of the solvable set, + /// whenever the solvable pool changes. This computation via \ref WhatProvides + /// is expensive, that's why a built in cache is also offered. + /// + /// \note \ref contains does not match srcpackage: per default. + /////////////////////////////////////////////////////////////////// + class SolvableSpec + { + public: + /** Default ctor */ + SolvableSpec(); + + /** Dtor */ + ~SolvableSpec(); + + SolvableSpec(const SolvableSpec &) = default; + SolvableSpec(SolvableSpec &&) noexcept = default; + SolvableSpec &operator=(const SolvableSpec &) = default; + SolvableSpec &operator=(SolvableSpec &&) noexcept = default; + + public: + /** Add all \ref sat::Solvable with this \a ident_r */ + void addIdent( IdString ident_r ); + + /** A all \ref sat::Solvable matching this \a provides_r. */ + void addProvides( Capability provides_r ); + + /** Extend the provides set to include idential installed items as well. + * Hack for retracted packages, where the indicator provides is injected + * into the available items, but is not present in the installed items. + */ + bool addIdenticalInstalledToo() const; + void addIdenticalInstalledToo( bool yesno_r ); + + public: + /** Parse and add spec from a string (`IDENT` or provides:CAPABILITY`). */ + void parse( const C_Str & spec_r ); + + /** Parse file \a istr_r and add its specs (one per line, #-comments). */ + void parseFrom( const InputStream & istr_r ); + + /** Parse and add specs from iterator range. */ + template + void parseFrom( TIterator begin, TIterator end ) + { for_( it, begin, end ) parse( *it ); } + + /** Convenience using \ref str::splitEscaped(", \t") to parse multiple specs from one line. */ + void splitParseFrom( const C_Str & multispec_r ); + + public: + /** Test whether \a solv_r matches the spec. + * (Re-)builds the \ref WhatProvides cache on demand. + * + * \note Does not match srcpackage: per default. + */ + bool contains( const sat::Solvable & solv_r ) const; + /** \overload */ + template + bool contains( const SolvableType & solv_r ) const + { return contains( solv_r.satSolvable() ); } + + /** Whether the cache is needed and dirty. */ + bool dirty() const; + + /** Explicitly flag the cache as dirty, so it will be rebuilt on the next request. + * To be called if the \ref ResPool content has changed. Intentionally `const` as + * this does not change the set of spects (though the set of matches might change). + * \note This has no effect if no cache is needed (i.e. no provides: are used). + */ + void setDirty() const; + + public: + /** Whether neither idents nor provides are set. */ + bool empty() const; + + /** Whether \a ident_r has been added to the specs (mainly for parser tests). */ + bool containsIdent( const IdString & ident_r ) const; + + /** Whether \a provides_r has been added to the sepcs (mainly for parser tests).*/ + bool containsProvides( const Capability & provides_r ) const; + + public: + class Impl; ///< Implementation class. + private: + RWCOW_pointer _pimpl; ///< Pointer to implementation. + friend std::ostream & operator<<( std::ostream & str, const SolvableSpec & obj ); + }; + + /** \relates SolvableSpec Stream output */ + std::ostream & operator<<( std::ostream & str, const SolvableSpec & obj ); + + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_SOLVABLESPEC_H diff --git a/zypp/sat/SolvableType.h b/zypp/sat/SolvableType.h new file mode 100644 index 0000000..9dcc013 --- /dev/null +++ b/zypp/sat/SolvableType.h @@ -0,0 +1,284 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/SolvableType.h + */ +#ifndef ZYPP_SAT_SOLVABLETYPE_H +#define ZYPP_SAT_SOLVABLETYPE_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace sat + { + /////////////////////////////////////////////////////////////////// + /// \class SolvableType + /// \brief Base class for creating \ref Solvable based types. + /// \ingroup g_CRTP + /// + /// Derive from this and offer explicit conversion to \ref Solvable + /// to make the \ref Solvable properties directly accessible. + /// + /// Different SolvableTypes are comparable based on the underlying + /// \ref Solvable. + /// + /// \see \ref Solvable + /// + /// \code + /// class MySolvable : public SolvableType + /// { + /// ...... + /// public: + /// explicit operator sat::Solvable() const; + /// + /// }; + /// \endcode + /////////////////////////////////////////////////////////////////// + template + struct SolvableType + { + /** Return the corresponding \ref sat::Solvable. */ + Solvable satSolvable() const { return Solvable(static_cast(*this)); } + + explicit operator bool() const { return bool(satSolvable()); } + + IdString ident() const { return satSolvable().ident(); } + + ResKind kind() const { return satSolvable().kind(); } + bool isKind( const ResKind & kind_r ) const { return satSolvable().isKind( kind_r ); } + template + bool isKind() const { return satSolvable().template isKind(); } + template + bool isKind( TIterator begin, TIterator end ) const { return satSolvable().isKind( begin, end ); } + + std::string name() const { return satSolvable().name(); } + Edition edition() const { return satSolvable().edition(); } + Arch arch() const { return satSolvable().arch(); } + IdString vendor() const { return satSolvable().vendor(); } + + Repository repository() const { return satSolvable().repository(); } + RepoInfo repoInfo() const { return satSolvable().repoInfo(); } + + bool isSystem() const { return satSolvable().isSystem(); } + bool onSystemByUser() const { return satSolvable().onSystemByUser(); } + bool onSystemByAuto() const { return satSolvable().onSystemByAuto(); } + bool identIsAutoInstalled() const { return satSolvable().identIsAutoInstalled(); } + bool multiversionInstall() const { return satSolvable().multiversionInstall(); } + bool isNeedreboot() const { return satSolvable().isNeedreboot(); } + + bool isBlacklisted() const { return satSolvable().isBlacklisted(); } + bool isRetracted() const { return satSolvable().isRetracted(); } + bool isPtf() const { return satSolvable().isPtf(); } + bool isPtfMaster() const { return satSolvable().isPtfMaster(); } + bool isPtfPackage() const { return satSolvable().isPtfPackage(); } + + Date buildtime() const { return satSolvable().buildtime(); } + Date installtime() const { return satSolvable().installtime(); } + + std::string asString() const { return satSolvable().asString(); } + std::string asUserString() const { return satSolvable().asUserString(); } + + bool identical( const Solvable & rhs ) const { return satSolvable().identical( rhs ); } + template + bool identical( const SolvableType & rhs ) const { return satSolvable().identical( rhs.satSolvable() ); } + + bool sameNVRA( const Solvable &rhs ) const { return satSolvable().sameNVRA( rhs ); } + template + bool sameNVRA( const SolvableType & rhs ) const { return satSolvable().sameNVRA( rhs.satSolvable() ); } + + Capabilities provides() const { return satSolvable().provides(); } + Capabilities requires() const { return satSolvable().requires(); } + Capabilities conflicts() const { return satSolvable().conflicts(); } + Capabilities obsoletes() const { return satSolvable().obsoletes(); } + Capabilities recommends() const { return satSolvable().recommends(); } + Capabilities suggests() const { return satSolvable().suggests(); } + Capabilities enhances() const { return satSolvable().enhances(); } + Capabilities supplements() const { return satSolvable().supplements(); } + Capabilities prerequires() const { return satSolvable().prerequires(); } + Capabilities dep( Dep which_r ) const { return satSolvable().dep(which_r); } + Capabilities operator[]( Dep which_r ) const { return satSolvable()[which_r]; } + + CapabilitySet providesNamespace( const std::string & namespace_r ) const { return satSolvable().providesNamespace( namespace_r ); } + CapabilitySet valuesOfNamespace( const std::string & namespace_r ) const { return satSolvable().valuesOfNamespace( namespace_r ); } + + bool supportsLocales() const { return satSolvable().supportsLocales(); } + bool supportsLocale( const Locale & locale_r ) const { return satSolvable().supportsLocale( locale_r ); } + bool supportsLocale( const LocaleSet & locales_r ) const { return satSolvable().supportsLocale( locales_r ); } + bool supportsRequestedLocales() const { return satSolvable().supportsRequestedLocales(); } + LocaleSet getSupportedLocales() const { return satSolvable().getSupportedLocales(); } + + CpeId cpeId() const { return satSolvable().cpeId(); } + unsigned mediaNr() const { return satSolvable().mediaNr(); } + ByteCount installSize() const { return satSolvable().installSize(); } + ByteCount downloadSize() const { return satSolvable().downloadSize(); } + std::string distribution() const { return satSolvable().distribution(); } + + std::string summary( const Locale & lang_r = Locale() ) const { return satSolvable().summary( lang_r ); } + std::string description( const Locale & lang_r = Locale() ) const { return satSolvable().description( lang_r ); } + std::string insnotify( const Locale & lang_r = Locale() ) const { return satSolvable().insnotify( lang_r ); } + std::string delnotify( const Locale & lang_r = Locale() ) const { return satSolvable().delnotify( lang_r ); } + std::string licenseToConfirm( const Locale & lang_r = Locale() ) const { return satSolvable().licenseToConfirm( lang_r ); } + bool needToAcceptLicense() const { return satSolvable().needToAcceptLicense(); } + + public: + std::string lookupStrAttribute( const SolvAttr & attr ) const { return satSolvable().lookupStrAttribute( attr ); } + std::string lookupStrAttribute( const SolvAttr & attr, const Locale & lang_r ) const { return satSolvable().lookupStrAttribute( attr, lang_r ); } + bool lookupBoolAttribute( const SolvAttr & attr ) const { return satSolvable().lookupBoolAttribute( attr ); } + detail::IdType lookupIdAttribute( const SolvAttr & attr ) const { return satSolvable().lookupIdAttribute( attr ); } + unsigned long long lookupNumAttribute( const SolvAttr & attr ) const { return satSolvable().lookupNumAttribute( attr ); } + unsigned long long lookupNumAttribute( const SolvAttr & attr, unsigned long long notfound_r ) const { return satSolvable().lookupNumAttribute( attr, notfound_r ); } + CheckSum lookupCheckSumAttribute( const SolvAttr & attr ) const { return satSolvable().lookupCheckSumAttribute( attr ); } + OnMediaLocation lookupLocation() const { return satSolvable().lookupLocation(); } + Solvable::IdType id() const { return satSolvable().id(); } + + protected: + SolvableType() {} + SolvableType( const SolvableType & ) = default; + SolvableType &operator=( const SolvableType & ) = default; + SolvableType( SolvableType && ) noexcept = default; + SolvableType &operator=( SolvableType && ) noexcept = default; + ~SolvableType() {} + }; + + /** \relates SolvableType Stream output */ + template + inline std::ostream & operator<<( std::ostream & str, const SolvableType & obj ) + { return str << obj.satSolvable(); } + + /** \relates SolvableType More verbose stream output including dependencies */ + template + inline std::ostream & dumpOn( std::ostream & str, const SolvableType & obj ) + { return dumpOn( str, obj.satSolvable() ); } + + /** \relates SolvableType Equal*/ + template + inline bool operator==( const SolvableType & lhs, const SolvableType & rhs ) + { return lhs.satSolvable() == rhs.satSolvable(); } + /** \overload */ + template + inline bool operator==( const SolvableType & lhs, const Solvable & rhs ) + { return lhs.satSolvable() == rhs; } + /** \overload */ + template + inline bool operator==( const Solvable & lhs, const SolvableType & rhs ) + { return lhs == rhs.satSolvable(); } + + /** \relates SolvableType NotEqual */ + template + inline bool operator!=( const SolvableType & lhs, const SolvableType & rhs ) + { return lhs.satSolvable() != rhs.satSolvable(); } + /** \overload */ + template + inline bool operator!=( const SolvableType & lhs, const Solvable & rhs ) + { return lhs.satSolvable() != rhs; } + /** \overload */ + template + inline bool operator!=( const Solvable & lhs, const SolvableType & rhs ) + { return lhs != rhs.satSolvable(); } + + /** \relates SolvableType Less*/ + template + inline bool operator<( const SolvableType & lhs, const SolvableType & rhs ) + { return lhs.satSolvable() < rhs.satSolvable(); } + /** \overload */ + template + inline bool operator<( const SolvableType & lhs, const Solvable & rhs ) + { return lhs.satSolvable() < rhs; } + /** \overload */ + template + inline bool operator<( const Solvable & lhs, const SolvableType & rhs ) + { return lhs < rhs.satSolvable(); } + + /** \relates SolvableType Test whether the \ref Solvable is of a certain \ref ResKind. */ + template + inline bool isKind( const SolvableType & solvable_r ) + { return isKind( solvable_r.satSolvable() ); } + + /** \relates SolvableType Test for same content. */ + template + inline bool identical( const SolvableType & lhs, const SolvableType & rhs ) + { return identical( lhs.satSolvable(), rhs.satSolvable() ); } + /** \overload */ + template + inline bool identical( const SolvableType & lhs, const Solvable & rhs ) + { return identical( lhs.satSolvable(), rhs ); } + /** \overload */ + template + inline bool identical( const Solvable & lhs, const SolvableType & rhs ) + { return identical( lhs, rhs.satSolvable() ); } + + /** \relates SolvableType Test for same name version release and arch. */ + template + inline bool sameNVRA( const SolvableType & lhs, const SolvableType & rhs ) + { return sameNVRA( lhs.satSolvable(), rhs.satSolvable() ); } + /** \overload */ + template + inline bool sameNVRA( const SolvableType & lhs, const Solvable & rhs ) + { return sameNVRA( lhs.satSolvable(), rhs ); } + /** \overload */ + template + inline bool sameNVRA( const Solvable & lhs, const SolvableType & rhs ) + { return sameNVRA( lhs, rhs.satSolvable() ); } + + + /** \relates SolvableType Compare according to \a kind and \a name. */ + template + inline int compareByN( const SolvableType & lhs, const SolvableType & rhs ) + { return compareByN( lhs.satSolvable(), rhs.satSolvable() ); } + /** \overload */ + template + inline bool compareByN( const SolvableType & lhs, const Solvable & rhs ) + { return compareByN( lhs.satSolvable(), rhs ); } + /** \overload */ + template + inline bool compareByN( const Solvable & lhs, const SolvableType & rhs ) + { return compareByN( lhs, rhs.satSolvable() ); } + + + /** \relates SolvableType Compare according to \a kind, \a name and \a edition. */ + template + inline int compareByNVR( const SolvableType & lhs, const SolvableType & rhs ) + { return compareByNVR( lhs.satSolvable(), rhs.satSolvable() ); } + /** \overload */ + template + inline bool compareByNVR( const SolvableType & lhs, const Solvable & rhs ) + { return compareByNVR( lhs.satSolvable(), rhs ); } + /** \overload */ + template + inline bool compareByNVR( const Solvable & lhs, const SolvableType & rhs ) + { return compareByNVR( lhs, rhs.satSolvable() ); } + + /** \relates SolvableType Compare according to \a kind, \a name, \a edition and \a arch. */ + template + inline int compareByNVRA( const SolvableType & lhs, const SolvableType & rhs ) + { return compareByNVRA( lhs.satSolvable(), rhs.satSolvable() ); } + /** \overload */ + template + inline bool compareByNVRA( const SolvableType & lhs, const Solvable & rhs ) + { return compareByNVRA( lhs.satSolvable(), rhs ); } + /** \overload */ + template + inline bool compareByNVRA( const Solvable & lhs, const SolvableType & rhs ) + { return compareByNVRA( lhs, rhs.satSolvable() ); } + + } // namespace sat + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_SOLVABLETYPE_H diff --git a/zypp/sat/Transaction.cc b/zypp/sat/Transaction.cc new file mode 100644 index 0000000..d8fb83e --- /dev/null +++ b/zypp/sat/Transaction.cc @@ -0,0 +1,474 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Transaction.cc + */ +extern "C" +{ +#include +#include +} +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + constexpr Transaction::LoadFromPoolType Transaction::loadFromPool; + + /** Transaction implementation. + * + * \NOTE After commit the @System repo is reloaded. This invalidates + * the ids off all installed items in the transaction, including their + * stepType. Thats why some information (stepType, NVRA) is be stored + * for post mortem access (i.e. tell after commit which NVRA were deleted). + * + */ + struct Transaction::Impl : protected detail::PoolMember + , private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const Impl & obj ); + + public: + using set_type = std::unordered_set; + using map_type = std::unordered_map; + + struct PostMortem + { + PostMortem() + {} + PostMortem( const sat::Solvable & solv_r ) + : _ident( solv_r.ident() ) + , _edition( solv_r.edition() ) + , _arch( solv_r.arch() ) + {} + + IdString _ident; + Edition _edition; + Arch _arch; + }; + using pmmap_type = std::unordered_map; + + public: + Impl() + : _trans( ::transaction_create( nullptr ) ) + { memset( _trans, 0, sizeof(*_trans) ); } + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + Impl(LoadFromPoolType) : _watcher(myPool().serial()), _trans(nullptr) { + Queue decisionq; + for ( const PoolItem & pi : ResPool::instance() ) + { + if ( ! pi.status().transacts() ) + continue; + decisionq.push( pi.isSystem() ? -pi.id() : pi.id() ); + } + Queue noobsq; + for ( const Solvable & solv : myPool().multiversionList() ) + { + noobsq.push( SOLVER_NOOBSOLETES | SOLVER_SOLVABLE ); + noobsq.push( solv.id() ); + } + Map noobsmap; + ::solver_calculate_noobsmap( myPool().getPool(), noobsq, noobsmap ); + _trans = ::transaction_create_decisionq( myPool().getPool(), decisionq, noobsmap ); + + // NOTE: package/product buddies share the same ResStatus + // so we also link the buddies stepStages. This assumes + // only one buddy is acting during commit (package is installed, + // but no extra operation for the product). + for_( it, _trans->steps.elements, _trans->steps.elements + _trans->steps.count ) + { + sat::Solvable solv( *it ); + // buddy list: + if ( ! solv.isKind() ) + { + PoolItem pi( solv ); + if ( pi.buddy() ) + { + _linkMap[*it] = pi.buddy().id(); + } + } + if ( solv.isSystem() ) + { + // to delete list: + if ( stepType( solv ) == TRANSACTION_ERASE ) + { + _systemErase.insert( *it ); + } + // post mortem data + _pmMap[*it] = solv; + } + } + } + + ~Impl() + { ::transaction_free( _trans ); } + + public: + bool valid() const + { return _watcher.isClean( myPool().serial() ); } + + bool order() + { + if ( ! valid() ) + return false; + if ( empty() ) + return true; +#if 0 + // This is hwo we could implement out own order method. + // As ::transaction already groups by MediaNr, we don't + // need it for ORDER_BY_MEDIANR. + ::transaction_order( _trans, SOLVER_TRANSACTION_KEEP_ORDERDATA ); + detail::IdType chosen = 0; + Queue choices; + + while ( true ) + { + int ret = transaction_order_add_choices( _trans, chosen, choices ); + MIL << ret << ": " << chosen << ": " << choices << endl; + chosen = choices.pop_front(); // pick one out of choices + if ( ! chosen ) + break; + } + return true; +#endif + if ( !_ordered ) + { + ::transaction_order( _trans, 0 ); + _ordered = true; + } + return true; + } + + bool empty() const + { return( _trans->steps.count == 0 ); } + + size_t size() const + { return _trans->steps.count; } + + const_iterator begin( const RW_pointer & self_r ) const + { return const_iterator( self_r, _trans->steps.elements ); } + iterator begin( const RW_pointer & self_r ) + { return iterator( self_r, _trans->steps.elements ); } + + const_iterator end( const RW_pointer & self_r ) const + { return const_iterator( self_r, _trans->steps.elements + _trans->steps.count ); } + iterator end( const RW_pointer & self_r ) + { return iterator( self_r, _trans->steps.elements + _trans->steps.count ); } + + const_iterator find(const RW_pointer & self_r, const sat::Solvable & solv_r ) const + { detail::IdType * it( _find( solv_r ) ); return it ? const_iterator( self_r, it ) : end( self_r ); } + iterator find(const RW_pointer & self_r, const sat::Solvable & solv_r ) + { detail::IdType * it( _find( solv_r ) ); return it ? iterator( self_r, it ) : end( self_r ); } + + public: + int installedResult( Queue & result_r ) const + { return ::transaction_installedresult( _trans, result_r ); } + + StringQueue autoInstalled() const + { return _autoInstalled; } + + void autoInstalled( const StringQueue & queue_r ) + { _autoInstalled = queue_r; } + + public: + StepType stepType( Solvable solv_r ) const + { + if ( ! solv_r ) + { + // post mortem @System solvable + return isIn( _systemErase, solv_r.id() ) ? TRANSACTION_ERASE : TRANSACTION_IGNORE; + } + + switch( ::transaction_type( _trans, solv_r.id(), SOLVER_TRANSACTION_RPM_ONLY ) ) + { + case SOLVER_TRANSACTION_ERASE: return TRANSACTION_ERASE; break; + case SOLVER_TRANSACTION_INSTALL: return TRANSACTION_INSTALL; break; + case SOLVER_TRANSACTION_MULTIINSTALL: return TRANSACTION_MULTIINSTALL; break; + } + return TRANSACTION_IGNORE; + } + + StepStage stepStage( Solvable solv_r ) const + { return stepStage( resolve( solv_r ) ); } + + void stepStage( Solvable solv_r, StepStage newval_r ) + { stepStage( resolve( solv_r ), newval_r ); } + + const PostMortem & pmdata( Solvable solv_r ) const + { + static PostMortem _none; + pmmap_type::const_iterator it( _pmMap.find( solv_r.id() ) ); + return( it == _pmMap.end() ? _none : it->second ); + } + + private: + detail::IdType resolve( const Solvable & solv_r ) const + { + map_type::const_iterator res( _linkMap.find( solv_r.id() ) ); + return( res == _linkMap.end() ? solv_r.id() : res->second ); + } + + bool isIn( const set_type & set_r, detail::IdType sid_r ) const + { return( set_r.find( sid_r ) != set_r.end() ); } + + StepStage stepStage( detail::IdType sid_r ) const + { + if ( isIn( _doneSet, sid_r ) ) + return STEP_DONE; + if ( isIn( _errSet, sid_r ) ) + return STEP_ERROR; + return STEP_TODO; + } + + void stepStage( detail::IdType sid_r, StepStage newval_r ) + { + StepStage stage( stepStage( sid_r ) ); + if ( stage != newval_r ) + { + // reset old stage + if ( stage != STEP_TODO ) + { + (stage == STEP_DONE ? _doneSet : _errSet).erase( sid_r ); + } + if ( newval_r != STEP_TODO ) + { + (newval_r == STEP_DONE ? _doneSet : _errSet).insert( sid_r ); + } + } + } + + private: + detail::IdType * _find( const sat::Solvable & solv_r ) const + { + if ( solv_r && _trans->steps.elements ) + { + for_( it, _trans->steps.elements, _trans->steps.elements + _trans->steps.count ) + { + if ( *it == detail::IdType(solv_r.id()) ) + return it; + } + } + return 0; + } + + private: + SerialNumberWatcher _watcher; + mutable ::Transaction * _trans; + DefaultIntegral _ordered; + // + set_type _doneSet; + set_type _errSet; + map_type _linkMap; // buddy map to adopt buddies StepResult + set_type _systemErase; // @System packages to be eased (otherse are TRANSACTION_IGNORE) + pmmap_type _pmMap; // Post mortem data of deleted @System solvables + + StringQueue _autoInstalled; // ident strings of all packages that would be auto-installed after the transaction is run. + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + }; + + /** \relates Transaction::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Transaction::Impl & obj ) + { + return str << "Transaction: " << obj.size() << " (" << (obj.valid()?"valid":"INVALID") << ")"; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Transaction + // + /////////////////////////////////////////////////////////////////// + + Transaction::Transaction() + : _pimpl( Impl::nullimpl() ) + {} + + Transaction::Transaction( LoadFromPoolType ) + : _pimpl( new Impl( loadFromPool ) ) + {} + + Transaction::~Transaction() + {} + + bool Transaction::valid() const + { return _pimpl->valid(); } + + bool Transaction::order() + { return _pimpl->order(); } + + bool Transaction::empty() const + { return _pimpl->empty(); } + + size_t Transaction::size() const + { return _pimpl->size(); } + + Transaction::const_iterator Transaction::begin() const + { return _pimpl->begin( _pimpl ); } + + Transaction::iterator Transaction::begin() + { return _pimpl->begin( _pimpl ); } + + Transaction::const_iterator Transaction::end() const + { return _pimpl->end( _pimpl ); } + + Transaction::iterator Transaction::end() + { return _pimpl->end( _pimpl ); } + + Transaction::const_iterator Transaction::find( const sat::Solvable & solv_r ) const + { return _pimpl->find( _pimpl, solv_r ); } + + Transaction::iterator Transaction::find( const sat::Solvable & solv_r ) + { return _pimpl->find( _pimpl, solv_r ); } + + int Transaction::installedResult( Queue & result_r ) const + { return _pimpl->installedResult( result_r ); } + + StringQueue Transaction::autoInstalled() const + { return _pimpl->autoInstalled(); } + + void Transaction::autoInstalled( const StringQueue & queue_r ) + { _pimpl->autoInstalled( queue_r ); } + + std::ostream & operator<<( std::ostream & str, const Transaction & obj ) + { return str << *obj._pimpl; } + + std::ostream & dumpOn( std::ostream & str, const Transaction & obj ) + { + for_( it, obj.begin(), obj.end() ) + { + str << *it << endl; + } + return str; + } + + bool operator==( const Transaction & lhs, const Transaction & rhs ) + { return lhs._pimpl == rhs._pimpl; } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Transaction::Step + // + /////////////////////////////////////////////////////////////////// + + Transaction::Step::Step() + {} + + Transaction::StepType Transaction::Step::stepType() const + { return _pimpl->stepType( _solv ); } + + Transaction::StepStage Transaction::Step::stepStage() const + { return _pimpl->stepStage( _solv ); } + + void Transaction::Step::stepStage( StepStage val_r ) + { _pimpl->stepStage( _solv, val_r ); } + + IdString Transaction::Step::ident() const + { return _solv ? _solv.ident() : _pimpl->pmdata(_solv )._ident; } + + Edition Transaction::Step::edition() const + { return _solv ? _solv.edition() : _pimpl->pmdata(_solv )._edition; } + + Arch Transaction::Step::arch() const + { return _solv ? _solv.arch() : _pimpl->pmdata(_solv )._arch; } + + std::ostream & operator<<( std::ostream & str, const Transaction::Step & obj ) + { + str << obj.stepType() << obj.stepStage() << " "; + if ( obj.satSolvable() ) + str << PoolItem( obj.satSolvable() ); + else + str << '[' << obj.ident() << '-' << obj.edition() << '.' << obj.arch() << ']'; + return str; + } + + std::ostream & operator<<( std::ostream & str, Transaction::StepType obj ) + { + switch ( obj ) + { + #define OUTS(E,S) case Transaction::E: return str << #S; break + OUTS( TRANSACTION_IGNORE, [ ] ); + OUTS( TRANSACTION_ERASE, [-] ); + OUTS( TRANSACTION_INSTALL, [+] ); + OUTS( TRANSACTION_MULTIINSTALL, [M] ); + #undef OUTS + } + return str << "[?]"; + } + + std::ostream & operator<<( std::ostream & str, Transaction::StepStage obj ) + { + switch ( obj ) + { + #define OUTS(E,S) case Transaction::E: return str << #S; break + OUTS( STEP_TODO, [__] ); + OUTS( STEP_DONE, [OK] ); + OUTS( STEP_ERROR, [**] ); + #undef OUTS + } + return str << "[??]"; + } + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Transaction::const_iterator/iterator + // + /////////////////////////////////////////////////////////////////// + + Transaction_const_iterator::Transaction_const_iterator() + : Transaction_const_iterator::iterator_adaptor_( 0 ) + {} + + Transaction_const_iterator::Transaction_const_iterator( const Transaction_iterator & iter_r ) + : Transaction_const_iterator::iterator_adaptor_( iter_r.base() ) + , _pimpl( iter_r._pimpl ) + {} + + Transaction_iterator::Transaction_iterator() + : Transaction_iterator::iterator_adaptor_( 0 ) + {} + + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/Transaction.h b/zypp/sat/Transaction.h new file mode 100644 index 0000000..fd04887 --- /dev/null +++ b/zypp/sat/Transaction.h @@ -0,0 +1,406 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/Transaction.h + */ +#ifndef ZYPP_SAT_TRANSACTION_H +#define ZYPP_SAT_TRANSACTION_H + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + namespace detail + { + /** Needs to be outside \ref Transaction in order to be usable in SolvIterMixin. */ + class Transaction_iterator; + /** Needs to be outside \ref Transaction in order to be usable in SolvIterMixin. */ + class Transaction_const_iterator; + } + + /** Libsolv transaction wrapper. + * \note Note that Transaction is derived from \ref sat::SolvIterMixin which + * makes PoolItem and Selectable iterators automatically available. + * \note Changing the \ref ResPool content (loading/unloading repositories) + * invalidates all outstanding transaction data. \see \ref valid. + * \note.The transaction may inlude steps of type \ref TRANSACTION_IGNORE which + * do not cause/require any specific action. To skip those informal steps + * when iterating, use the \ref actionBegin /\ref actionEnd methods. + */ + class ZYPP_API Transaction : public SolvIterMixin + { + friend std::ostream & operator<<( std::ostream & str, const Transaction & obj ); + friend std::ostream & dumpOn( std::ostream & str, const Transaction & obj ); + friend bool operator==( const Transaction & lhs, const Transaction & rhs ); + + public: + /** Represents a single step within a \ref Transaction. */ + class Step; + + /** Type of (rpm) action to perform in a \ref Step. */ + enum StepType + { + TRANSACTION_IGNORE = 0x00, /**< [ ] Nothing (includes implicit deletes due to obsoletes and non-package actions) */ + TRANSACTION_ERASE = 0x10, /**< [-] Delete item */ + TRANSACTION_INSTALL = 0x20, /**< [+] Install(update) item */ + TRANSACTION_MULTIINSTALL = 0x30 /**< [M] Install(multiversion) item (\see \ref ZConfig::multiversion) */ + }; + + /** \ref Step action result. */ + enum StepStage + { + STEP_TODO = (1 << 0), /**< [__] unprocessed */ + STEP_DONE = (1 << 1), /**< [OK] success */ + STEP_ERROR = (1 << 2), /**< [**] error */ + }; + + ZYPP_DECLARE_FLAGS(StepStages,StepStage); + + public: + struct LoadFromPoolType {}; ///< Ctor arg type + static constexpr LoadFromPoolType loadFromPool = LoadFromPoolType(); + + public: + /** Default ctor: empty transaction. */ + Transaction(); + + /** Ctor loading the default pools transaction. */ + Transaction( LoadFromPoolType ); + + /** Dtor */ + ~Transaction(); + + public: + /** Whether transaction actually contains data and also fits the current pools content. */ + bool valid() const; + + /** Validate object in a boolean context: valid */ + explicit operator bool() const + { return valid(); } + + /** Order transaction steps for commit. + * It's cheap to call it for an aleready ordered \ref Transaction. + * This invalidates outstanding iterators. Returns whether + * \ref Transaction is \ref valid. + */ + bool order(); + + /** Whether the transaction contains any steps. */ + bool empty() const; + + /** Number of steps in transaction steps. */ + size_t size() const; + + using iterator = detail::Transaction_iterator; + using const_iterator = detail::Transaction_const_iterator; + + /** Iterator to the first \ref TransactionStep */ + const_iterator begin() const; + /** \overload */ + iterator begin(); + + /** Iterator behind the last \ref TransactionStep */ + const_iterator end() const; + /** \overload */ + iterator end(); + + /** Return iterator pointing to \a solv_r or \ref end. */ + const_iterator find( const sat::Solvable & solv_r ) const; + iterator find( const sat::Solvable & solv_r ); + /** \overload */ + const_iterator find( const ResObject::constPtr & resolvable_r ) const; + iterator find( const ResObject::constPtr & resolvable_r ); + /** \overload */ + const_iterator find( const PoolItem & pi_r ) const; + iterator find( const PoolItem & pi_r ); + + public: + /** \name Iterate action steps (omit TRANSACTION_IGNORE steps). + * + * All these methods allow to pass an optional OR'd combination of + * \ref StepStages as filter. Per default all steps are processed/counted. + * + * \code + * Transaction trans; + * for_( it, trans.actionBegin(~sat::Transaction::STEP_DONE), trans.actionEnd() ) + * { + * ... // process all steps not DONE (ERROR and TODO) + * } + * \endcode + */ + //@{ + struct FilterAction; + using action_iterator = filter_iterator; + + /** Whether the [filtered] transaction contains any steps . */ + bool actionEmpty( StepStages filter_r = StepStages() ) const; + + /** Number of steps in [filtered] transaction steps. */ + size_t actionSize( StepStages filter_r = StepStages() ) const; + + /** Pointer to the 1st action step in [filtered] transaction. */ + action_iterator actionBegin( StepStages filter_r = StepStages() ) const; + + /** Pointer behind the last action step in transaction. */ + action_iterator actionEnd() const; + + /** Iterate the [filtered] transaction steps. */ + Iterable action( StepStages filter_r = StepStages() ) const; + //@} + + public: + /** Return all packages that would be installed after the transaction is run. + * The new packages are put at the head of the queue, the number of new + * packages is returned. (wraps libsolv::transaction_installedresult) */ + int installedResult( Queue & result_r ) const; + + /** Return the ident strings of all packages that would be auto-installed after the transaction is run. */ + StringQueue autoInstalled() const; + + /** Set the ident strings of all packages that would be auto-installed after the transaction is run. */ + void autoInstalled( const StringQueue & queue_r ); + + public: + /** Implementation */ + struct Impl; + private: + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + + ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Transaction::StepStages); + + /** \relates Transaction Stream output */ + std::ostream & operator<<( std::ostream & str, const Transaction & obj ) ZYPP_API; + + /** \relates Transaction Verbose stream output */ + std::ostream & dumpOn( std::ostream & str, const Transaction & obj ) ZYPP_API; + + /** \relates Transaction */ + bool operator==( const Transaction & lhs, const Transaction & rhs ) ZYPP_API; + + /** \relates Transaction */ + inline bool operator!=( const Transaction & lhs, const Transaction & rhs ) + { return !( lhs == rhs ); } + + + /** A single step within a \ref Transaction. + * + * \note After commit, when the @System repo (rpm database) is reread, all + * @System solvables within the transaction are invalidated (they got deleted). + * Thats why we internally store the NVRA, so you can access \ref ident + * (\see \ref sat::Solvable::ident), \ref edition, \ref arch of a deleted package, + * even if the \ref satSolvable itself is meanwhile invalid. + * + * \see \ref Transaction. + */ + class Transaction::Step + { + friend std::ostream & operator<<( std::ostream & str, const Step & obj ); + + public: + Step(); + Step( const RW_pointer & pimpl_r, detail::IdType id_r ) + : _solv( id_r ) + , _pimpl( pimpl_r ) + {} + + public: + /** Type of action to perform in this step. */ + StepType stepType() const; + + /** Step action result. */ + StepStage stepStage() const; + + /** Set step action result. */ + void stepStage( StepStage val_r ); + + /** Return the corresponding \ref Solvable. + * Returns \ref Solvable::noSolvable if the item is meanwhile deleted and + * was removed from the pool. \see Post mortem acccess to @System solvables. + */ + Solvable satSolvable() const + { return _solv; } + + /** \name Post mortem acccess to @System solvables + * \code + * Transaction::Step step; + * if ( step.satSolvable() ) + * std::cout << step.satSolvable() << endl; + * else + * std::cout << step.ident() << endl; // deleted @System solvable + * \endcode + */ + //@{ + /** \see \ref sat::Solvable::ident. */ + IdString ident() const; + + /** \see \ref sat::Solvable::edition. */ + Edition edition() const; + + /** \see \ref sat::Solvable::arch. */ + Arch arch() const; + //@} + + /** Implicit conversion to \ref Solvable */ + operator const Solvable &() const { return _solv; } + /** \overload nonconst */ + operator Solvable &() { return _solv; } + + private: + Solvable _solv; + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + + /** \relates Transaction::Step Stream output */ + std::ostream & operator<<( std::ostream & str, const Transaction::Step & obj ) ZYPP_API; + + /** \relates Transaction::StepType Stream output */ + std::ostream & operator<<( std::ostream & str, Transaction::StepType obj ) ZYPP_API; + + /** \relates Transaction::StepStage Stream output */ + std::ostream & operator<<( std::ostream & str, Transaction::StepStage obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + /** \ref Transaction iterator. + */ + class Transaction_iterator : public boost::iterator_adaptor< + Transaction_iterator // Derived + , const detail::IdType * // Base + , Transaction::Step // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , Transaction::Step // Reference + > + { + public: + Transaction_iterator(); + Transaction_iterator( const RW_pointer & pimpl_r, base_type id_r ) + : Transaction_iterator::iterator_adaptor_( id_r ) + , _pimpl( pimpl_r ) + {} + + private: + friend class boost::iterator_core_access; + + reference dereference() const + { return Transaction::Step( _pimpl, *base() ); } + + private: + friend class Transaction_const_iterator; + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + + /** \ref Transaction const_iterator. + */ + class Transaction_const_iterator : public boost::iterator_adaptor< + Transaction_const_iterator // Derived + , const detail::IdType * // Base + , const Transaction::Step // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , const Transaction::Step // Reference + > + { + public: + Transaction_const_iterator(); + Transaction_const_iterator( const Transaction_iterator & iter_r ); + Transaction_const_iterator( const RW_pointer & pimpl_r, base_type id_r ) + : Transaction_const_iterator::iterator_adaptor_( id_r ) + , _pimpl( pimpl_r ) + {} + + private: + friend class boost::iterator_core_access; + + reference dereference() const + { return Transaction::Step( _pimpl, *base() ); } + + private: + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + + inline Transaction::const_iterator Transaction::find( const ResObject::constPtr & resolvable_r ) const + { return( resolvable_r ? find( resolvable_r->satSolvable() ) : end() ); } + + inline Transaction::iterator Transaction::find( const ResObject::constPtr & resolvable_r ) + { return( resolvable_r ? find( resolvable_r->satSolvable() ) : end() ); } + + inline Transaction::const_iterator Transaction::find( const PoolItem & pi_r ) const + { return find( pi_r.satSolvable() ); } + + inline Transaction::iterator Transaction::find( const PoolItem & pi_r ) + { return find( pi_r.satSolvable() ); } + + + struct Transaction::FilterAction + { + FilterAction() {} + FilterAction( StepStages filter_r ) : _filter( filter_r ) {} + + bool operator()( const Transaction::Step & step_r ) const + { + if ( step_r.stepType() == Transaction::TRANSACTION_IGNORE ) + return false; // no action + return !_filter || _filter.testFlag( step_r.stepStage() ); + } + + StepStages _filter; + }; + + inline Transaction::action_iterator Transaction::actionBegin( StepStages filter_r ) const + { return make_filter_begin( FilterAction( filter_r ), *this ); } + + inline Transaction::action_iterator Transaction::actionEnd() const + { return make_filter_end( FilterAction(), *this ); } + + inline bool Transaction::actionEmpty( StepStages filter_r ) const + { return( actionBegin( filter_r ) == actionEnd() ); } + + inline size_t Transaction::actionSize( StepStages filter_r ) const + { + size_t cnt = 0; + for_( it, actionBegin( filter_r ), actionEnd() ) + ++cnt; + return cnt; + } + + inline Iterable Transaction::action( StepStages filter_r ) const + { return makeIterable( actionBegin( filter_r ), actionEnd() ); } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_TRANSACTION_H diff --git a/zypp/sat/WhatObsoletes.cc b/zypp/sat/WhatObsoletes.cc new file mode 100644 index 0000000..ade8c5c --- /dev/null +++ b/zypp/sat/WhatObsoletes.cc @@ -0,0 +1,176 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/WhatObsoletes.cc + * +*/ +#include + +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + // Obsoletes may either match against provides, or names. + // Configuration depends on the behaviour of rpm. +#ifdef _RPM_5 + bool obsoleteUsesProvides = true; +#else + bool obsoleteUsesProvides = false; +#endif + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + using set_type = std::unordered_set; + using vector_type = std::vector; + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + WhatObsoletes::WhatObsoletes( Solvable item_r ) + : _begin( 0 ) + { + ctorAdd( item_r ); + ctorDone(); + } + + WhatObsoletes::WhatObsoletes( const PoolItem & item_r ) + : _begin( 0 ) + { + ctorAdd( item_r ); + ctorDone(); + } + + WhatObsoletes::WhatObsoletes( const ResObject::constPtr& item_r ) + : _begin( 0 ) + { + if ( item_r ) + { + ctorAdd( item_r->satSolvable() ); + ctorDone(); + } + } + + void WhatObsoletes::ctorAdd( const PoolItem & item_r ) + { ctorAdd( item_r->satSolvable() ); } + + void WhatObsoletes::ctorAdd( const ResObject_constPtr& item_r ) + { if ( item_r ) ctorAdd( item_r->satSolvable() ); } + + + namespace + { + /** Add item to the set created on demand. */ + inline void addToSet( Solvable item, set_type *& pdata, shared_ptr& _private ) + { + if ( ! pdata ) + { + _private.reset( (pdata = new set_type) ); + } + pdata->insert( item.id() ); + } + } + + void WhatObsoletes::ctorAdd( Solvable item_r ) + { + if ( item_r.multiversionInstall() ) + return; // multiversion (rpm -i) does not evaluate any obsoletes + + if ( obsoleteUsesProvides ) + { + WhatProvides obsoleted( item_r.obsoletes() ); + if ( obsoleted.empty() ) + return; + + // use allocated private data to collect the results + set_type * pdata = ( _private ? reinterpret_cast( _private.get() ) : 0 ); + for_( it, obsoleted.begin(), obsoleted.end() ) + { + if ( it->isSystem() ) + addToSet( *it, pdata, _private ); + } + } + else // Obsoletes match names + { + Capabilities obsoletes( item_r.obsoletes() ); + if ( obsoletes.empty() ) + return; + + // use allocated private data to collect the results + set_type * pdata = ( _private ? reinterpret_cast( _private.get() ) : 0 ); + for_( it, obsoletes.begin(), obsoletes.end() ) + { + // For each obsoletes find providers, but with the same name + IdString ident( it->detail().name() ); + WhatProvides obsoleted( *it ); + for_( iit, obsoleted.begin(), obsoleted.end() ) + { + if ( iit->isSystem() && iit->ident() == ident ) + addToSet( *iit, pdata, _private ); + } + } + } + } + + void WhatObsoletes::ctorDone() + { + if ( _private ) + { + // copy set to vector and terminate _private + set_type * sdata = reinterpret_cast( _private.get() ); + + vector_type * pdata = new vector_type( sdata->begin(), sdata->end() ); + pdata->push_back( sat::detail::noId ); + _begin = &pdata->front(); + + _private.reset( pdata ); + } + } + + WhatObsoletes::size_type WhatObsoletes::size() const + { + if ( ! _begin ) + return 0; + + Capabilities::size_type ret = 0; + for ( const sat::detail::IdType * end = _begin; *end; ++end ) + { + ++ret; + } + return ret; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const WhatObsoletes & obj ) + { + return dumpRange( str << "(" << obj.size() << ")", obj.begin(), obj.end() ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/WhatObsoletes.h b/zypp/sat/WhatObsoletes.h new file mode 100644 index 0000000..afc5986 --- /dev/null +++ b/zypp/sat/WhatObsoletes.h @@ -0,0 +1,111 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/WhatObsoletes.h + * +*/ +#ifndef ZYPP_SAT_WHATOBSOLETES_H +#define ZYPP_SAT_WHATOBSOLETES_H + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : WhatObsoletes + // + /** Container of \b installed \ref Solvable which would be + * obsoleted by the \ref Solvable passed to the ctor. + * + * \todo Publish obsoleteUsesProvides config option. + */ + class WhatObsoletes : public SolvIterMixin, + protected detail::PoolMember + { + public: + using value_type = Solvable; + using size_type = unsigned int; + + public: + /** Default ctor */ + WhatObsoletes() + : _begin( 0 ) + {} + + /** Ctor from \ref Solvable. */ + explicit + WhatObsoletes( Solvable item_r ); + + /** Ctor from \ref PoolItem. */ + explicit + WhatObsoletes( const PoolItem & item_r ); + + /** Ctor from \ref ResObject::constPtr. */ + explicit + WhatObsoletes( const ResObject_constPtr& item_r ); + + /** Ctor from a range of \ref Solvable, \ref PoolItem or \ref ResObject::constPtr. */ + template + WhatObsoletes( TIterator begin, TIterator end ) + : _begin( 0 ) + { + for_( it, begin, end ) + ctorAdd( *it ); + ctorDone(); + } + + public: + /** Whether the container is empty. */ + bool empty() const + { return ! ( _begin && *_begin ); } + + /** Number of solvables inside. */ + size_type size() const; + + public: + using const_iterator = detail::WhatProvidesIterator; + + /** Iterator pointing to the first \ref Solvable. */ + const_iterator begin() const + { return const_iterator( _begin ); } + + /** Iterator pointing behind the last \ref Solvable. */ + const_iterator end() const + { return const_iterator(); } + + private: + void ctorAdd( const PoolItem & item_r ); + void ctorAdd( const ResObject_constPtr& item_r ); + void ctorAdd( Solvable item_r ); + void ctorDone(); + + private: + const sat::detail::IdType * _begin; + shared_ptr _private; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates WhatObsoletes Stream output */ + std::ostream & operator<<( std::ostream & str, const WhatObsoletes & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_WHATOBSOLETES_H diff --git a/zypp/sat/WhatProvides.cc b/zypp/sat/WhatProvides.cc new file mode 100644 index 0000000..53ab14f --- /dev/null +++ b/zypp/sat/WhatProvides.cc @@ -0,0 +1,188 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/WhatProvides.cc + * +*/ +#include + +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : WhatProvides::Impl + // + /** WhatProvides implementation date. + * Stores the offset into a O terminated Id array. Per default + * libsolvs whatprovidesdata, otherwise private data. + * + * As libsolvs whatprovidesdata might be realocated + * while iterating a result, the iterator takes an + * const IdType *const*. Thats why we explicitly + * provide _private and pass its adress to the iterator, + * even if private data are not reallocated. + */ + class WhatProvides::Impl : protected detail::PoolMember + { + public: + Impl() + : _offset( 0 ), _private( 0 ) + {} + + Impl( unsigned offset_r ) + : _offset( offset_r ), _private( 0 ) + {} + + Impl( const std::unordered_set & ids_r ) + : _offset( 0 ), _private( 0 ) + { + // use private data to store the result (incl. trailing NULL) + _pdata.reserve( ids_r.size()+1 ); + _pdata.insert( _pdata.begin(), ids_r.begin(), ids_r.end() ); + _pdata.push_back( detail::noId ); + + _private = &_pdata.front(); // ptr to 1st element + } + + public: + unsigned _offset; + const detail::IdType * _private; + + private: + std::vector _pdata; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + /** WhatProvides ctor helper collecting providers from Capabilies. */ + template + void collectProviders( Iterator begin_r, Iterator end_r, std::unordered_set & collect_r ) + { + for_( it, begin_r, end_r ) + { + WhatProvides providers( *it ); + for_( prv, providers.begin(), providers.end() ) + { + collect_r.insert( prv->id() ); + } + } + } + + ///////////////////////////////////////////////////////////////// + } //namespace + /////////////////////////////////////////////////////////////////// + + WhatProvides::WhatProvides() + {} + + WhatProvides::WhatProvides( Capability cap_r ) + { + unsigned res( myPool().whatProvides( cap_r ) ); + if ( myPool().whatProvidesData( res ) ) + { + _pimpl.reset( new Impl( res ) ); + } + // else: no Impl for empty result. + } + + WhatProvides::WhatProvides( Capabilities caps_r ) + { + std::unordered_set ids; + collectProviders( caps_r.begin(), caps_r.end(), ids ); + if ( ! ids.empty() ) + { + _pimpl.reset( new Impl( ids ) ); + } + // else: no Impl for empty result. + } + + WhatProvides::WhatProvides( const CapabilitySet & caps_r ) + { + std::unordered_set ids; + collectProviders( caps_r.begin(), caps_r.end(), ids ); + if ( ! ids.empty() ) + { + _pimpl.reset( new Impl( ids ) ); + } + // else: no Impl for empty result. + } + + bool WhatProvides::empty() const + { + return !_pimpl; // Ctor asserts no Impl for empty result. + } + + WhatProvides::size_type WhatProvides::size() const + { + if ( !_pimpl ) + return 0; + + size_type count = 0; + for_( it, begin(), end() ) + ++count; + return count; + } + + WhatProvides::const_iterator WhatProvides::begin() const + { + if ( !_pimpl ) + return const_iterator(); + + if ( _pimpl->_private ) + return const_iterator( _pimpl->_private ); + + // for libsolvs index use one more indirection, as it might get relocated. + return const_iterator( &myPool().getPool()->whatprovidesdata, _pimpl->_offset ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const WhatProvides & obj ) + { + return dumpRange( str << "(" << obj.size() << ")", obj.begin(), obj.end() ); + } + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const WhatProvidesIterator & obj ) + { + str << str::form( "[%5u]", obj._offset ); + str << str::form( "<%p(%p)>", obj.base_reference(), &obj.base_reference() ); + str << str::form( "<%p(%p)>", obj._baseRef, (obj._baseRef ? *obj._baseRef : 0) ); + return str; + } + + ///////////////////////////////////////////////////////////////// + } //namespace detail + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/WhatProvides.h b/zypp/sat/WhatProvides.h new file mode 100644 index 0000000..337f116 --- /dev/null +++ b/zypp/sat/WhatProvides.h @@ -0,0 +1,243 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/WhatProvides.h + * +*/ +#ifndef ZYPP_SAT_WHATPROVIDES_H +#define ZYPP_SAT_WHATPROVIDES_H + +#include +#include + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + namespace detail + { + class WhatProvidesIterator; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : WhatProvides + // + /** Container of \ref Solvable providing a \ref Capability (read only). + * + * \code + * Capability cap("amarok < 1.13"); + * + * WhatProvides q( cap ); + * Solvable firstMatch; + * + * if ( ! q.empty() ) + * { + * cout << "Found " << q.size() << " matches for " << cap << ":" << endl; + * firstMatch = *q.begin(); + * + * for_( it, q.begin(), q.end() ) + * cout << *it << endl; + * } + * + * if ( firstMatch ) + * { + * WhatProvides req( firstMatch.requires() ); + * if ( ! req.empty() ) + * { + * cout << "Found " << req.size() << " items providing requirements of " << firstMatch << ":" << endl; + * } + * } + * \endcode + * + * \note Note that there are capabilities which are not provided by any \ref Solvable, + * but are system properties. For example: + * \code + * rpmlib(PayloadIsBzip2) <= 3.0.5-1 + * \endcode + * In that case a \ref Solvable::noSolvable is returned, which has \c isSystem set \c true, although + * there should never be a \ref Solvable::noSolvable returned with \c isSystem set \c false. If so, + * please file a bugreport. + * \code + * WhatProvides q( Capability("rpmlib(PayloadIsBzip2) <= 3.0.5-1") ); + * for_( it, q.begin(), q.end() ) + * { + * if ( *it ) + * cout << "Capability is provided by package " << *it << endl; + * else if ( it->isSystem() ) + * cout << "Capability is a system property" << endl; + * else + * ; // never reaching this \c else + * } + * \endcode + */ + class ZYPP_API WhatProvides : public SolvIterMixin, + protected detail::PoolMember + { + public: + using value_type = Solvable; + using size_type = unsigned int; + + public: + /** Default ctor */ + WhatProvides(); + + /** Ctor from \ref Capability. */ + explicit + WhatProvides( Capability cap_r ); + + /** Ctor collecting all providers of capabilities in \c caps_r. */ + explicit + WhatProvides( Capabilities caps_r ); + + /** Ctor collecting all providers of capabilities in \c caps_r. */ + explicit + WhatProvides( const CapabilitySet & caps_r ); + + public: + /** Whether the container is empty. */ + bool empty() const; + + /** Number of solvables inside. */ + size_type size() const; + + public: + using const_iterator = detail::WhatProvidesIterator; + + /** Iterator pointing to the first \ref Solvable. */ + const_iterator begin() const; + + /** Iterator pointing behind the last \ref Solvable. */ + const_iterator end() const; + + private: + class Impl; + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates WhatProvides Stream output */ + std::ostream & operator<<( std::ostream & str, const WhatProvides & obj ); + + /////////////////////////////////////////////////////////////////// + /// \brief Container of packages providing `ptf()` + class ZYPP_API AllPTFs : public WhatProvides + { + public: + AllPTFs() : WhatProvides( Capability(Solvable::ptfMasterToken.id()) ) {}; + }; + + namespace detail + { + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : WhatProvides::const_iterator + // + /** \ref WhatProvides iterator. + * Iterate a NULL terminated sat::detail::IdType array. Ctor gets + * the adress of a pointer to the array, and offset into the array. + * This is needed in case the array gets reallocated. + */ + class WhatProvidesIterator : public boost::iterator_adaptor< + WhatProvidesIterator // Derived + , const detail::IdType * // Base + , const Solvable // Value + , boost::forward_traversal_tag // CategoryOrTraversal + , const Solvable // Reference + > + { + friend std::ostream & operator<<( std::ostream & str, const WhatProvidesIterator & obj ); + public: + WhatProvidesIterator() + : iterator_adaptor_( 0 ), _baseRef( 0 ), _offset( 0 ) + {} + + /** Ctor with pointer to 1st elemment of an array. + * Use otherwise unused base as pointer for _baseRef. + */ + explicit WhatProvidesIterator( const detail::IdType *const base_r, unsigned offset_r = 0 ) + : iterator_adaptor_( base_r ), _baseRef( base_r ? &base_reference() : 0 ), _offset( offset_r ) + {} + + /** Ctor with pointer to pointer to 1st elemment of an array. + * Required for arrays that might be relocated while iterating. + */ + explicit WhatProvidesIterator( const detail::IdType *const* baseRef_r, unsigned offset_r ) + : iterator_adaptor_( 0 ), _baseRef( baseRef_r ), _offset( offset_r ) + {} + + /** Copy-ctor required to keep _baseRef adjusted. */ + WhatProvidesIterator( const WhatProvidesIterator & rhs ) + : iterator_adaptor_( rhs.base_reference() ) + , _baseRef( base_reference() ? &base_reference() : rhs._baseRef ) + , _offset( rhs._offset ) + {} + + /** Assignment operator required to keep _baseRef adjusted. */ + WhatProvidesIterator & operator=( const WhatProvidesIterator & rhs ) + { + if ( this != &rhs ) // no self assign + { + base_reference() = rhs.base_reference(); + _baseRef = ( base_reference() ? &base_reference() : rhs._baseRef ); + _offset = rhs._offset; + } + return *this; + } + + private: + friend class boost::iterator_core_access; + + reference dereference() const + { return Solvable( getId() ); } +#if 0 + template + bool equal( const boost::iterator_adaptor & rhs ) const +#endif + bool equal( const WhatProvidesIterator & rhs ) const + { + if ( ! ( getId() || rhs.getId() ) ) + return true; // both @end + if ( _offset != rhs._offset ) + return false; + if ( base_reference() ) + return( base_reference() == rhs.base_reference() ); + return( _baseRef == rhs._baseRef ); + } + + void increment() + { ++_offset; } + + detail::IdType getId() const + { return _baseRef ? (*_baseRef)[_offset] : detail::noId; } + + private: + const detail::IdType *const* _baseRef; + unsigned _offset; + }; + /////////////////////////////////////////////////////////////////// + } + + inline WhatProvides::const_iterator WhatProvides::end() const + { return const_iterator(); } + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_WHATPROVIDES_H diff --git a/zypp/sat/detail/PoolImpl.cc b/zypp/sat/detail/PoolImpl.cc new file mode 100644 index 0000000..6466cec --- /dev/null +++ b/zypp/sat/detail/PoolImpl.cc @@ -0,0 +1,675 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/detail/PoolImpl.cc + * +*/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +extern "C" +{ +// Workaround libsolv project not providing a common include +// directory. (the -devel package does, but the git repo doesn't). +// #include +// #include +int repo_add_helix( ::Repo *repo, FILE *fp, int flags ); +int testcase_add_testtags(Repo *repo, FILE *fp, int flags); +} + +using std::endl; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::satpool" + +// /////////////////////////////////////////////////////////////////// +namespace zypp +{ + ///////////////////////////////////////////////////////////////// + namespace env + { + /** */ + inline int LIBSOLV_DEBUGMASK() + { + const char * envp = getenv("LIBSOLV_DEBUGMASK"); + return envp ? str::strtonum( envp ) : 0; + } + } // namespace env + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + // MPL checks for satlib constants we redefine to avoid + // includes and defines. + BOOST_MPL_ASSERT_RELATION( noId, ==, STRID_NULL ); + BOOST_MPL_ASSERT_RELATION( emptyId, ==, STRID_EMPTY ); + + BOOST_MPL_ASSERT_RELATION( noSolvableId, ==, ID_NULL ); + BOOST_MPL_ASSERT_RELATION( systemSolvableId, ==, SYSTEMSOLVABLE ); + + BOOST_MPL_ASSERT_RELATION( solvablePrereqMarker, ==, SOLVABLE_PREREQMARKER ); + BOOST_MPL_ASSERT_RELATION( solvableFileMarker, ==, SOLVABLE_FILEMARKER ); + + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_AND, ==, REL_AND ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_OR, ==, REL_OR ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_COND, ==, REL_COND ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_UNLESS, ==, REL_UNLESS ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_ELSE, ==, REL_ELSE ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_WITH, ==, REL_WITH ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_WITHOUT, ==, REL_WITHOUT ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_NAMESPACE, ==, REL_NAMESPACE ); + BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_ARCH, ==, REL_ARCH ); + + BOOST_MPL_ASSERT_RELATION( namespaceModalias, ==, NAMESPACE_MODALIAS ); + BOOST_MPL_ASSERT_RELATION( namespaceLanguage, ==, NAMESPACE_LANGUAGE ); + BOOST_MPL_ASSERT_RELATION( namespaceFilesystem, ==, NAMESPACE_FILESYSTEM ); + + ///////////////////////////////////////////////////////////////// + + const std::string & PoolImpl::systemRepoAlias() + { + static const std::string _val( "@System" ); + return _val; + } + + const Pathname & sysconfigStoragePath() + { + static const Pathname _val( "/etc/sysconfig/storage" ); + return _val; + } + + ///////////////////////////////////////////////////////////////// + + static void logSat( CPool *, void *data, int type, const char *logString ) + { + // "1234567890123456789012345678901234567890 + if ( 0 == strncmp( logString, "job: drop orphaned", 18 ) ) + return; + if ( 0 == strncmp( logString, "job: user installed", 19 ) ) + return; + if ( 0 == strncmp( logString, "job: multiversion", 17 ) ) + return; + if ( 0 == strncmp( logString, " - no rule created", 19 ) ) + return; + if ( 0 == strncmp( logString, " next rules: 0 0", 19 ) ) + return; + + if ( type & (SOLV_FATAL|SOLV_ERROR) ) { + L_ERR("libsolv") << logString; + } else if ( type & SOLV_DEBUG_STATS ) { + L_DBG("libsolv") << logString; + } else { + L_MIL("libsolv") << logString; + } + } + + detail::IdType PoolImpl::nsCallback( CPool *, void * data, detail::IdType lhs, detail::IdType rhs ) + { + // lhs: the namespace identifier, e.g. NAMESPACE:MODALIAS + // rhs: the value, e.g. pci:v0000104Cd0000840[01]sv*sd*bc*sc*i* + // return: 0 if not supportded + // 1 if supported by the system + // -1 AFAIK it's also possible to return a list of solvables that support it, but don't know how. + + static const detail::IdType RET_unsupported = 0; + static const detail::IdType RET_systemProperty = 1; + switch ( lhs ) + { + case NAMESPACE_LANGUAGE: + { + const TrackedLocaleIds & localeIds( reinterpret_cast(data)->trackedLocaleIds() ); + return localeIds.contains( IdString(rhs) ) ? RET_systemProperty : RET_unsupported; + } + break; + + case NAMESPACE_MODALIAS: + { + // modalias strings in capability may be hexencoded because rpm does not allow + // ',', ' ' or other special chars. + return target::Modalias::instance().query( str::hexdecode( IdString(rhs).c_str() ) ) + ? RET_systemProperty + : RET_unsupported; + } + break; + + case NAMESPACE_FILESYSTEM: + { + const std::set & requiredFilesystems( reinterpret_cast(data)->requiredFilesystems() ); + return requiredFilesystems.find( IdString(rhs).asString() ) != requiredFilesystems.end() ? RET_systemProperty : RET_unsupported; + } + break; + + } + + WAR << "Unhandled " << Capability( lhs ) << " vs. " << Capability( rhs ) << endl; + return RET_unsupported; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : PoolMember::myPool + // METHOD TYPE : PoolImpl + // + PoolImpl & PoolMember::myPool() + { + static PoolImpl _global; + return _global; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : PoolImpl::PoolImpl + // METHOD TYPE : Ctor + // + PoolImpl::PoolImpl() + : _pool( ::pool_create() ) + { + MIL << "Creating sat-pool." << endl; + if ( ! _pool ) + { + ZYPP_THROW( Exception( _("Can not create sat-pool.") ) ); + } + // by now we support only a RPM backend + ::pool_setdisttype(_pool, DISTTYPE_RPM ); + + // initialialize logging + if ( env::LIBSOLV_DEBUGMASK() ) + { + ::pool_setdebugmask(_pool, env::LIBSOLV_DEBUGMASK() ); + } + else + { + if ( getenv("ZYPP_LIBSOLV_FULLLOG") || getenv("ZYPP_LIBSAT_FULLLOG") ) + ::pool_setdebuglevel( _pool, 3 ); + else if ( getenv("ZYPP_FULLLOG") ) + ::pool_setdebuglevel( _pool, 2 ); + else + ::pool_setdebugmask(_pool, SOLV_DEBUG_JOB|SOLV_DEBUG_STATS ); + } + + ::pool_setdebugcallback( _pool, logSat, NULL ); + + // set namespace callback + _pool->nscallback = &nsCallback; + _pool->nscallbackdata = (void*)this; + + // CAVEAT: We'd like to do it here, but in side the Pool ctor we can not + // yet use IdString types. We do in setDirty, when the 1st + // _retractedSpec.addProvides( Capability( Solvable::retractedToken.id() ) ); + // _ptfMasterSpec.addProvides( Capability( Solvable::ptfMasterToken.id() ) ); + // _ptfPackageSpec.addProvides( Capability( Solvable::ptfPackageToken.id() ) ); + _retractedSpec.addIdenticalInstalledToo( true ); // retracted indicator is not part of the package! + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : PoolImpl::~PoolImpl + // METHOD TYPE : Dtor + // + PoolImpl::~PoolImpl() + { + ::pool_free( _pool ); + } + + /////////////////////////////////////////////////////////////////// + + void PoolImpl::setDirty( const char * a1, const char * a2, const char * a3 ) + { + if ( _retractedSpec.empty() ) { + // lazy init IdString types we can not use inside the ctor + _retractedSpec.addProvides( Capability( Solvable::retractedToken.id() ) ); + _ptfMasterSpec.addProvides( Capability( Solvable::ptfMasterToken.id() ) ); + _ptfPackageSpec.addProvides( Capability( Solvable::ptfPackageToken.id() ) ); + } + + if ( a1 ) + { + if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl; + else if ( a2 ) MIL << a1 << " " << a2 << endl; + else MIL << a1 << endl; + } + _serial.setDirty(); // pool content change + _availableLocalesPtr.reset(); // available locales may change + _multiversionListPtr.reset(); // re-evaluate ZConfig::multiversionSpec. + _needrebootSpec.setDirty(); // re-evaluate needrebootSpec + + _retractedSpec.setDirty(); // re-evaluate blacklisted spec + _ptfMasterSpec.setDirty(); // --"-- + _ptfPackageSpec.setDirty(); // --"-- + + depSetDirty(); // invaldate dependency/namespace related indices + } + + void PoolImpl::localeSetDirty( const char * a1, const char * a2, const char * a3 ) + { + if ( a1 ) + { + if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl; + else if ( a2 ) MIL << a1 << " " << a2 << endl; + else MIL << a1 << endl; + } + _trackedLocaleIdsPtr.reset(); // requested locales changed + depSetDirty(); // invaldate dependency/namespace related indices + } + + void PoolImpl::depSetDirty( const char * a1, const char * a2, const char * a3 ) + { + if ( a1 ) + { + if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl; + else if ( a2 ) MIL << a1 << " " << a2 << endl; + else MIL << a1 << endl; + } + ::pool_freewhatprovides( _pool ); + } + + void PoolImpl::prepare() const + { + // additional /etc/sysconfig/storage check: + static WatchFile sysconfigFile( sysconfigStoragePath(), WatchFile::NO_INIT ); + if ( sysconfigFile.hasChanged() ) + { + _requiredFilesystemsPtr.reset(); // recreated on demand + const_cast(this)->depSetDirty( "/etc/sysconfig/storage change" ); + } + if ( _watcher.remember( _serial ) ) + { + // After repo/solvable add/remove: + // set pool architecture + ::pool_setarch( _pool, ZConfig::instance().systemArchitecture().asString().c_str() ); + } + if ( ! _pool->whatprovides ) + { + MIL << "pool_createwhatprovides..." << endl; + + ::pool_addfileprovides( _pool ); + ::pool_createwhatprovides( _pool ); + } + if ( ! _pool->languages ) + { + // initial seting + const_cast(this)->setTextLocale( ZConfig::instance().textLocale() ); + } + } + + /////////////////////////////////////////////////////////////////// + + CRepo * PoolImpl::_createRepo( const std::string & name_r ) + { + setDirty(__FUNCTION__, name_r.c_str() ); + CRepo * ret = ::repo_create( _pool, name_r.c_str() ); + if ( ret && name_r == systemRepoAlias() ) + ::pool_set_installed( _pool, ret ); + return ret; + } + + void PoolImpl::_deleteRepo( CRepo * repo_r ) + { + setDirty(__FUNCTION__, repo_r->name ); + if ( isSystemRepo( repo_r ) ) + _autoinstalled.clear(); + eraseRepoInfo( repo_r ); + ::repo_free( repo_r, /*resusePoolIDs*/false ); + // If the last repo is removed clear the pool to actually reuse all IDs. + // NOTE: the explicit ::repo_free above asserts all solvables are memset(0)! + if ( !_pool->urepos ) + { + _serialIDs.setDirty(); // Indicate resusePoolIDs - ResPool must also invalidate its PoolItems + ::pool_freeallrepos( _pool, /*resusePoolIDs*/true ); + } + } + + int PoolImpl::_addSolv( CRepo * repo_r, FILE * file_r ) + { + setDirty(__FUNCTION__, repo_r->name ); + int ret = ::repo_add_solv( repo_r, file_r, 0 ); + if ( ret == 0 ) + _postRepoAdd( repo_r ); + return ret; + } + + int PoolImpl::_addHelix( CRepo * repo_r, FILE * file_r ) + { + setDirty(__FUNCTION__, repo_r->name ); + int ret = ::repo_add_helix( repo_r, file_r, 0 ); + if ( ret == 0 ) + _postRepoAdd( repo_r ); + return 0; + } + + int PoolImpl::_addTesttags(CRepo *repo_r, FILE *file_r) + { + setDirty(__FUNCTION__, repo_r->name ); + int ret = ::testcase_add_testtags( repo_r, file_r, 0 ); + if ( ret == 0 ) + _postRepoAdd( repo_r ); + return 0; + } + + void PoolImpl::_postRepoAdd( CRepo * repo_r ) + { + if ( ! isSystemRepo( repo_r ) ) + { + // Filter out unwanted archs + std::set sysids; + { + Arch::CompatSet sysarchs( Arch::compatSet( ZConfig::instance().systemArchitecture() ) ); + for_( it, sysarchs.begin(), sysarchs.end() ) + sysids.insert( it->id() ); + + // unfortunately libsolv treats src/nosrc as architecture: + sysids.insert( ARCH_SRC ); + sysids.insert( ARCH_NOSRC ); + } + + detail::IdType blockBegin = 0; + unsigned blockSize = 0; + for ( detail::IdType i = repo_r->start; i < repo_r->end; ++i ) + { + CSolvable * s( _pool->solvables + i ); + if ( s->repo == repo_r && sysids.find( s->arch ) == sysids.end() ) + { + // Remember an unwanted arch entry: + if ( ! blockBegin ) + blockBegin = i; + ++blockSize; + } + else if ( blockSize ) + { + // Free remembered entries + ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*resusePoolIDs*/false ); + blockBegin = blockSize = 0; + } + } + if ( blockSize ) + { + // Free remembered entries + ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*resusePoolIDs*/false ); + blockBegin = blockSize = 0; + } + } + } + + detail::SolvableIdType PoolImpl::_addSolvables( CRepo * repo_r, unsigned count_r ) + { + setDirty(__FUNCTION__, repo_r->name ); + return ::repo_add_solvable_block( repo_r, count_r ); + } + + void PoolImpl::setRepoInfo( RepoIdType id_r, const RepoInfo & info_r ) + { + CRepo * repo( getRepo( id_r ) ); + if ( repo ) + { + bool dirty = false; + + // libsolv priority is based on '<', while yum's repoinfo + // uses 1(highest)->99(lowest). Thus we use -info_r.priority. + if ( repo->priority != int(-info_r.priority()) ) + { + repo->priority = -info_r.priority(); + dirty = true; + } + + // subpriority is used to e.g. prefer http over dvd iff + // both have same priority. + int mediaPriority( media::MediaPriority( info_r.url() ) ); + if ( repo->subpriority != mediaPriority ) + { + repo->subpriority = mediaPriority; + dirty = true; + } + + if ( dirty ) + setDirty(__FUNCTION__, info_r.alias().c_str() ); + } + _repoinfos[id_r] = info_r; + } + + /////////////////////////////////////////////////////////////////// + + void PoolImpl::setTextLocale( const Locale & locale_r ) + { + if ( ! locale_r ) + { + // We need one, so "en" is the last resort + const char *needone[] { "en" }; + ::pool_set_languages( _pool, needone, 1 ); + return; + } + + std::vector fallbacklist; + for ( Locale l( locale_r ); l; l = l.fallback() ) + { + fallbacklist.push_back( l.code() ); + } + dumpRangeLine( MIL << "pool_set_languages: ", fallbacklist.begin(), fallbacklist.end() ) << endl; + + std::vector fallbacklist_cstr; + for_( it, fallbacklist.begin(), fallbacklist.end() ) + { + fallbacklist_cstr.push_back( it->c_str() ); + } + ::pool_set_languages( _pool, &fallbacklist_cstr.front(), fallbacklist_cstr.size() ); + } + + void PoolImpl::initRequestedLocales( const LocaleSet & locales_r ) + { + if ( _requestedLocalesTracker.setInitial( locales_r ) ) + { + localeSetDirty( "initRequestedLocales" ); + MIL << "Init RequestedLocales: " << _requestedLocalesTracker << " =" << locales_r << endl; + } + } + + void PoolImpl::setRequestedLocales( const LocaleSet & locales_r ) + { + if ( _requestedLocalesTracker.set( locales_r ) ) + { + localeSetDirty( "setRequestedLocales" ); + MIL << "New RequestedLocales: " << _requestedLocalesTracker << " =" << locales_r << endl; + } + } + + bool PoolImpl::addRequestedLocale( const Locale & locale_r ) + { + bool done = _requestedLocalesTracker.add( locale_r ); + if ( done ) + { + localeSetDirty( "addRequestedLocale", locale_r.code().c_str() ); + MIL << "New RequestedLocales: " << _requestedLocalesTracker << " +" << locale_r << endl; + } + return done; + } + + bool PoolImpl::eraseRequestedLocale( const Locale & locale_r ) + { + bool done = _requestedLocalesTracker.remove( locale_r ); + if ( done ) + { + localeSetDirty( "eraseRequestedLocale", locale_r.code().c_str() ); + MIL << "New RequestedLocales: " << _requestedLocalesTracker << " -" << locale_r << endl; + } + return done; + } + + + const PoolImpl::TrackedLocaleIds & PoolImpl::trackedLocaleIds() const + { + if ( ! _trackedLocaleIdsPtr ) + { + _trackedLocaleIdsPtr.reset( new TrackedLocaleIds ); + + const base::SetTracker & localesTracker( _requestedLocalesTracker ); + TrackedLocaleIds & localeIds( *_trackedLocaleIdsPtr ); + + // Add current locales+fallback except for added ones + for ( Locale lang: localesTracker.current() ) + { + if ( localesTracker.wasAdded( lang ) ) + continue; + for ( ; lang; lang = lang.fallback() ) + { localeIds.current().insert( IdString(lang) ); } + } + + // Add added locales+fallback except they are already in current + for ( Locale lang: localesTracker.added() ) + { + for ( ; lang && localeIds.current().insert( IdString(lang) ).second; lang = lang.fallback() ) + { localeIds.added().insert( IdString(lang) ); } + } + + // Add removed locales+fallback except they are still in current + for ( Locale lang: localesTracker.removed() ) + { + for ( ; lang && ! localeIds.current().count( IdString(lang) ); lang = lang.fallback() ) + { localeIds.removed().insert( IdString(lang) ); } + } + + // bsc#1155678: We try to differ between an empty RequestedLocales + // and one containing 'en' (explicit or as fallback). An empty RequestedLocales + // should not even drag in recommended 'en' packages. So we no longer enforce + // 'en' being in the set. + } + return *_trackedLocaleIdsPtr; + } + + + static void _getLocaleDeps( const Capability & cap_r, LocaleSet & store_r ) + { + // Collect locales from any 'namespace:language(lang)' dependency + CapDetail detail( cap_r ); + if ( detail.kind() == CapDetail::EXPRESSION ) + { + switch ( detail.capRel() ) + { + case CapDetail::CAP_AND: + case CapDetail::CAP_OR: + // expand + _getLocaleDeps( detail.lhs(), store_r ); + _getLocaleDeps( detail.rhs(), store_r ); + break; + + case CapDetail::CAP_NAMESPACE: + if ( detail.lhs().id() == NAMESPACE_LANGUAGE ) + { + store_r.insert( Locale( IdString(detail.rhs().id()) ) ); + } + break; + + default: + break; // unwanted + } + } + } + + const LocaleSet & PoolImpl::getAvailableLocales() const + { + if ( !_availableLocalesPtr ) + { + _availableLocalesPtr.reset( new LocaleSet ); + LocaleSet & localeSet( *_availableLocalesPtr ); + + for ( const Solvable & pi : Pool::instance().solvables() ) + { + for ( const Capability & cap : pi.supplements() ) + { + _getLocaleDeps( cap, localeSet ); + } + } + } + return *_availableLocalesPtr; + } + + /////////////////////////////////////////////////////////////////// + + void PoolImpl::multiversionListInit() const + { + _multiversionListPtr.reset( new MultiversionList ); + MultiversionList & multiversionList( *_multiversionListPtr ); + + MultiversionList::size_type size = 0; + for ( const std::string & spec : ZConfig::instance().multiversionSpec() ) + { + static const std::string prefix( "provides:" ); + bool provides = str::hasPrefix( spec, prefix ); + + for ( Solvable solv : WhatProvides( Capability( provides ? spec.c_str() + prefix.size() : spec.c_str() ) ) ) + { + if ( provides || solv.ident() == spec ) + multiversionList.insert( solv ); + } + + MultiversionList::size_type nsize = multiversionList.size(); + MIL << "Multiversion install " << spec << ": " << (nsize-size) << " matches" << endl; + size = nsize; + } + } + + void PoolImpl::multiversionSpecChanged() + { _multiversionListPtr.reset(); } + + const PoolImpl::MultiversionList & PoolImpl::multiversionList() const + { + if ( ! _multiversionListPtr ) + multiversionListInit(); + return *_multiversionListPtr; + } + + bool PoolImpl::isMultiversion( const Solvable & solv_r ) const + { return multiversionList().contains( solv_r ); } + + /////////////////////////////////////////////////////////////////// + + const std::set & PoolImpl::requiredFilesystems() const + { + if ( ! _requiredFilesystemsPtr ) + { + _requiredFilesystemsPtr.reset( new std::set ); + std::set & requiredFilesystems( *_requiredFilesystemsPtr ); + str::split( base::sysconfig::read( sysconfigStoragePath() )["USED_FS_LIST"], + std::inserter( requiredFilesystems, requiredFilesystems.end() ) ); + } + return *_requiredFilesystemsPtr; + } + + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/sat/detail/PoolImpl.h b/zypp/sat/detail/PoolImpl.h new file mode 100644 index 0000000..0e697c5 --- /dev/null +++ b/zypp/sat/detail/PoolImpl.h @@ -0,0 +1,402 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/detail/PoolImpl.h + * +*/ +#ifndef ZYPP_SAT_DETAIL_POOLIMPL_H +#define ZYPP_SAT_DETAIL_POOLIMPL_H +extern "C" +{ +#include +#include +#include +#include +#include +#include +} +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + class SolvableSet; + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolImpl + // + /** */ + class PoolImpl : private base::NonCopyable + { + public: + /** Default ctor */ + PoolImpl(); + + /** Dtor */ + ~PoolImpl(); + + /** Pointer style access forwarded to sat-pool. */ + CPool * operator->() + { return _pool; } + + public: + /** Serial number changing whenever the content changes. */ + const SerialNumber & serial() const + { return _serial; } + + /** Serial number changing whenever resusePoolIDs==true was used. ResPool must also invalidate its PoolItems! */ + const SerialNumber & serialIDs() const + { return _serialIDs; } + + /** Update housekeeping data (e.g. whatprovides). + * \todo actually requires a watcher. + */ + void prepare() const; + + private: + /** Invalidate housekeeping data (e.g. whatprovides) if the + * pools content changed. + */ + void setDirty( const char * a1 = 0, const char * a2 = 0, const char * a3 = 0 ); + + /** Invalidate locale related housekeeping data. + */ + void localeSetDirty( const char * a1 = 0, const char * a2 = 0, const char * a3 = 0 ); + + /** Invalidate housekeeping data (e.g. whatprovides) if dependencies changed. + */ + void depSetDirty( const char * a1 = 0, const char * a2 = 0, const char * a3 = 0 ); + + /** Callback to resolve namespace dependencies (language, modalias, filesystem, etc.). */ + static detail::IdType nsCallback( CPool *, void * data, detail::IdType lhs, detail::IdType rhs ); + + public: + /** Reserved system repository alias \c @System. */ + static const std::string & systemRepoAlias(); + + bool isSystemRepo( CRepo * repo_r ) const + { return repo_r && _pool->installed == repo_r; } + + CRepo * systemRepo() const + { return _pool->installed; } + + /** Get rootdir (for file conflicts check) */ + Pathname rootDir() const + { + const char * rd = ::pool_get_rootdir( _pool ); + return( rd ? rd : "/" ); + } + + /** Set rootdir (for file conflicts check) */ + void rootDir( const Pathname & root_r ) + { + if ( root_r.empty() || root_r == "/" ) + ::pool_set_rootdir( _pool, nullptr ); + else + ::pool_set_rootdir( _pool, root_r.c_str() ); + } + + public: + /** \name Actions invalidating housekeeping data. + * + * All methods expect valid arguments being passed. + */ + //@{ + /** Creating a new repo named \a name_r. */ + CRepo * _createRepo( const std::string & name_r ); + + /** Delete repo \a repo_r from pool. */ + void _deleteRepo( CRepo * repo_r ); + + /** Adding solv file to a repo. + * Except for \c isSystemRepo_r, solvables of incompatible architecture + * are filtered out. + */ + int _addSolv( CRepo * repo_r, FILE * file_r ); + + /** Adding helix file to a repo. + * Except for \c isSystemRepo_r, solvables of incompatible architecture + * are filtered out. + */ + int _addHelix( CRepo * repo_r, FILE * file_r ); + + /** Adding testtags file to a repo. + * Except for \c isSystemRepo_r, solvables of incompatible architecture + * are filtered out. + */ + int _addTesttags( CRepo * repo_r, FILE * file_r ); + + /** Adding Solvables to a repo. */ + detail::SolvableIdType _addSolvables( CRepo * repo_r, unsigned count_r ); + //@} + + /** Helper postprocessing the repo after adding solv or helix files. */ + void _postRepoAdd( CRepo * repo_r ); + + public: + /** a \c valid \ref Solvable has a non NULL repo pointer. */ + bool validSolvable( const CSolvable & slv_r ) const + { return slv_r.repo; } + /** \overload Check also for id_r being in range of _pool->solvables. */ + bool validSolvable( SolvableIdType id_r ) const + { return id_r < unsigned(_pool->nsolvables) && validSolvable( _pool->solvables[id_r] ); } + /** \overload Check also for slv_r being in range of _pool->solvables. */ + bool validSolvable( const CSolvable * slv_r ) const + { return _pool->solvables <= slv_r && slv_r <= _pool->solvables+_pool->nsolvables && validSolvable( *slv_r ); } + + public: + CPool * getPool() const + { return _pool; } + + /** \todo a quick check whether the repo was meanwhile deleted. */ + CRepo * getRepo( RepoIdType id_r ) const + { return id_r; } + + /** Return pointer to the sat-solvable or NULL if it is not valid. + * \see \ref validSolvable. + */ + CSolvable * getSolvable( SolvableIdType id_r ) const + { + if ( validSolvable( id_r ) ) + return &_pool->solvables[id_r]; + return 0; + } + + public: + /** libsolv capability parser */ + sat::detail::IdType parserpmrichdep( const char * capstr_r ) + { return ::pool_parserpmrichdep( _pool, capstr_r ); } + + public: + /** Get id of the first valid \ref Solvable. + * This is the next valid after the system solvable. + */ + SolvableIdType getFirstId() const + { return getNextId( 1 ); } + + /** Get id of the next valid \ref Solvable. + * This goes round robbin. At the end it returns \ref noSolvableId. + * Passing \ref noSolvableId it returns the 1st valid \ref Solvable. + * \see \ref validSolvable. + */ + SolvableIdType getNextId( SolvableIdType id_r ) const + { + for( ++id_r; id_r < unsigned(_pool->nsolvables); ++id_r ) + { + if ( validSolvable( _pool->solvables[id_r] ) ) + return id_r; + } + return noSolvableId; + } + + public: + /** */ + const RepoInfo & repoInfo( RepoIdType id_r ) + { return _repoinfos[id_r]; } + /** Also adjust repo priority and subpriority accordingly. */ + void setRepoInfo( RepoIdType id_r, const RepoInfo & info_r ); + /** */ + void eraseRepoInfo( RepoIdType id_r ) + { _repoinfos.erase( id_r ); } + + public: + /** Returns the id stored at \c offset_r in the internal + * whatprovidesdata array. + */ + const sat::detail::IdType whatProvidesData( unsigned offset_r ) + { return _pool->whatprovidesdata[offset_r]; } + + /** Returns offset into the internal whatprovidesdata array. + * Use \ref whatProvidesData to get the stored Id. + */ + unsigned whatProvides( Capability cap_r ) + { prepare(); return ::pool_whatprovides( _pool, cap_r.id() ); } + + public: + /// \name Requested locales. + /// The requested LocaleSets managed in _requestedLocalesTracker + /// are unexpanded; i.e. they contain just the pure user selection. + /// The resolver however uses expanded sets ('de_DE' will also + /// include its fallback locales 'de', (en); here in the namespace: + /// callback and in the Resolver itself). + //@{ + /** */ + void setTextLocale( const Locale & locale_r ); + + + /** Start tracking changes based on this \a locales_r. + * Usually called on TargetInit. + */ + void initRequestedLocales( const LocaleSet & locales_r ); + + /** Added since last initRequestedLocales. */ + const LocaleSet & getAddedRequestedLocales() const + { return _requestedLocalesTracker.added(); } + + /** Removed since last initRequestedLocales. */ + const LocaleSet & getRemovedRequestedLocales() const + { return _requestedLocalesTracker.removed(); } + + /** Current set of requested Locales. */ + const LocaleSet & getRequestedLocales() const + { return _requestedLocalesTracker.current(); } + + bool isRequestedLocale( const Locale & locale_r ) const + { return _requestedLocalesTracker.contains( locale_r ); } + + /** User change (tracked). */ + void setRequestedLocales( const LocaleSet & locales_r ); + /** User change (tracked). */ + bool addRequestedLocale( const Locale & locale_r ); + /** User change (tracked). */ + bool eraseRequestedLocale( const Locale & locale_r ); + + /** All Locales occurring in any repo. */ + const LocaleSet & getAvailableLocales() const; + + bool isAvailableLocale( const Locale & locale_r ) const + { + const LocaleSet & avl( getAvailableLocales() ); + LocaleSet::const_iterator it( avl.find( locale_r ) ); + return it != avl.end(); + } + + typedef base::SetTracker TrackedLocaleIds; + + /** Expanded _requestedLocalesTracker for solver.*/ + const TrackedLocaleIds & trackedLocaleIds() const; + //@} + + public: + /** \name Multiversion install. */ + //@{ + typedef SolvableSet MultiversionList; + + const MultiversionList & multiversionList() const; + + bool isMultiversion( const Solvable & solv_r ) const; + + void multiversionSpecChanged(); + //@} + + public: + /** \name Installed on behalf of a user request hint. */ + //@{ + /** Get ident list of all autoinstalled solvables. */ + StringQueue autoInstalled() const + { return _autoinstalled; } + + /** Set ident list of all autoinstalled solvables. */ + void setAutoInstalled( const StringQueue & autoInstalled_r ) + { _autoinstalled = autoInstalled_r; } + + bool isOnSystemByUser( IdString ident_r ) const + { return !_autoinstalled.contains( ident_r.id() ); } + + bool isOnSystemByAuto( IdString ident_r ) const + { return _autoinstalled.contains( ident_r.id() ); } + //@} + + public: + /** \name Solvables which should trigger the reboot-needed hint if installed/updated. */ + //@{ + /** Set new Solvable specs.*/ + void setNeedrebootSpec( sat::SolvableSpec needrebootSpec_r ) + { + _needrebootSpec = std::move(needrebootSpec_r); + _needrebootSpec.setDirty(); + } + + /** Whether \a solv_r matches the spec.*/ + bool isNeedreboot( const Solvable & solv_r ) const + { return _needrebootSpec.contains( solv_r ); } + //@} + + public: + /** \name Blacklisted Solvables. */ + //@{ + bool isRetracted( const Solvable & solv_r ) const + { return _retractedSpec.contains( solv_r ); } + bool isPtfMaster( const Solvable & solv_r ) const + { return _ptfMasterSpec.contains( solv_r ); } + bool isPtfPackage( const Solvable & solv_r ) const + { return _ptfPackageSpec.contains( solv_r ); } + //@} + + public: + /** accessor for etc/sysconfig/storage reading file on demand */ + const std::set & requiredFilesystems() const; + + private: + /** sat-pool. */ + CPool * _pool; + /** Serial number - changes with each Pool content change. */ + SerialNumber _serial; + /** Serial number of IDs - changes whenever resusePoolIDs==true - ResPool must also invalidate its PoolItems! */ + SerialNumber _serialIDs; + /** Watch serial number. */ + SerialNumberWatcher _watcher; + /** Additional \ref RepoInfo. */ + std::map _repoinfos; + + /** */ + base::SetTracker _requestedLocalesTracker; + mutable scoped_ptr _trackedLocaleIdsPtr; + + mutable scoped_ptr _availableLocalesPtr; + + /** */ + void multiversionListInit() const; + mutable scoped_ptr _multiversionListPtr; + + /** */ + sat::StringQueue _autoinstalled; + + /** Solvables which should trigger the reboot-needed hint if installed/updated. */ + sat::SolvableSpec _needrebootSpec; + + /** Blacklisted specs: */ + sat::SolvableSpec _retractedSpec; + sat::SolvableSpec _ptfMasterSpec; + sat::SolvableSpec _ptfPackageSpec; + + /** filesystems mentioned in /etc/sysconfig/storage */ + mutable scoped_ptr > _requiredFilesystemsPtr; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#define POOL_SETDIRTY +#endif // ZYPP_SAT_DETAIL_POOLIMPL_H diff --git a/zypp/sat/detail/PoolMember.h b/zypp/sat/detail/PoolMember.h new file mode 100644 index 0000000..076400a --- /dev/null +++ b/zypp/sat/detail/PoolMember.h @@ -0,0 +1,158 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/sat/detail/PoolMember.h + * +*/ +#ifndef ZYPP_SAT_DETAIL_POOLMEMBER_H +#define ZYPP_SAT_DETAIL_POOLMEMBER_H + +#include +#include +#include +#include + +extern "C" +{ + // Those s_Type names are exposed as sat::detail::CType below! + struct s_Dataiterator; + struct s_Datamatcher; + struct s_Map; + struct s_Pool; + struct s_Queue; + struct s_Repo; + struct s_Solvable; + struct s_Solver; + struct s_Transaction; +} + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + class IdString; + class Capability; + class Capabilities; + class Repository; + class RepoInfo; + + /////////////////////////////////////////////////////////////////// + namespace detail + { + class RepoIterator; + struct ByRepository; + } + + /////////////////////////////////////////////////////////////////// + namespace sat + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace detail + { + using CDataiterator = ::s_Dataiterator; ///< Wrapped libsolv C data type exposed as backdoor + using CDatamatcher = ::s_Datamatcher; ///< Wrapped libsolv C data type exposed as backdoor + using CMap = ::s_Map; ///< Wrapped libsolv C data type exposed as backdoor + using CPool = ::s_Pool; ///< Wrapped libsolv C data type exposed as backdoor + using CQueue = ::s_Queue; ///< Wrapped libsolv C data type exposed as backdoor + using CRepo = ::s_Repo; ///< Wrapped libsolv C data type exposed as backdoor + using CSolvable = ::s_Solvable; ///< Wrapped libsolv C data type exposed as backdoor + using CSolver = ::s_Solver; ///< Wrapped libsolv C data type exposed as backdoor + using CTransaction = ::s_Transaction; ///< Wrapped libsolv C data type exposed as backdoor + } // namespace detail + /////////////////////////////////////////////////////////////////// + + class Pool; + class Solvable; + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + class PoolImpl; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : PoolMember + // + /** Backlink to the associated \ref PoolImpl. + * Simple as we currently use one global PoolImpl. If we change our + * minds this is where we'd store and do the \c Id to \ref PoolImpl + * mapping. + */ + struct PoolMember + { + static PoolImpl & myPool(); + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + /** Generic Id type. */ + using IdType = int; + static const IdType noId( 0 ); + static const IdType emptyId( 1 ); + + /** Internal ids satlib includes in dependencies. + * MPL check in PoolImpl.cc + */ + static const IdType solvablePrereqMarker( 15 ); + static const IdType solvableFileMarker ( 16 ); + + static const IdType namespaceModalias ( 18 ); + static const IdType namespaceLanguage ( 20 ); + static const IdType namespaceFilesystem ( 21 ); + + /** Test for internal ids satlib includes in dependencies. */ + inline bool isDepMarkerId( IdType id_r ) + { return( id_r == solvablePrereqMarker || id_r == solvableFileMarker ); } + + /** Id type to connect \ref Solvable and sat-solvable. + * Indext into solvable array. + */ + using SolvableIdType = unsigned int; + using size_type = SolvableIdType; + /** Id to denote \ref Solvable::noSolvable. */ + static const SolvableIdType noSolvableId( 0 ); + /** Id to denote the usually hidden \ref Solvable::systemSolvable. */ + static const SolvableIdType systemSolvableId( 1 ); + + /** Id type to connect \ref Repo and sat-repo. */ + using RepoIdType = CRepo *; + /** Id to denote \ref Repo::noRepository. */ + static const RepoIdType noRepoId( 0 ); + + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + + + /////////////////////////////////////////////////////////////////// + namespace detail + { ///////////////////////////////////////////////////////////////// + + class SolvableIterator; + + ///////////////////////////////////////////////////////////////// + } // namespace detail + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace sat + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_SAT_DETAIL_POOLMEMBER_H diff --git a/zypp/solver/Types.h b/zypp/solver/Types.h new file mode 100644 index 0000000..f2742d0 --- /dev/null +++ b/zypp/solver/Types.h @@ -0,0 +1,24 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/solver/Types.h + * + * Common types used in the Resolver public API and need to be passed + * down to the details tree. Not for common use. + */ +#ifndef ZYPP_SOLVER_TYPES_H +#define ZYPP_SOLVER_TYPES_H + +#include + +#include +#include + +#include + +#endif // ZYPP_SOLVER_TYPES_H diff --git a/zypp/solver/detail/ItemCapKind.h b/zypp/solver/detail/ItemCapKind.h new file mode 100644 index 0000000..7a4a4b9 --- /dev/null +++ b/zypp/solver/detail/ItemCapKind.h @@ -0,0 +1,93 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/solver/detail/ItemCapKind.h + * +*/ + +#ifndef ZYPP_SOLVER_DETAIL_ITEMCAPKIND_H +#define ZYPP_SOLVER_DETAIL_ITEMCAPKIND_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace solver + { + /////////////////////////////////////////////////////////////////// + namespace detail + { + /////////////////////////////////////////////////////////////////// + /// \class ItemCapKind + /////////////////////////////////////////////////////////////////// + struct ItemCapKind + { + public: + ItemCapKind() : _pimpl( new Impl ) {} + + ItemCapKind( PoolItem i, Capability c, Dep k, bool initial ) : _pimpl( new Impl( i, c, k, initial ) ) {} + + /** Capability which has triggerd this selection */ + Capability cap() const + { return _pimpl->_cap; } + + /** Kind of that capability */ + Dep capKind() const + { return _pimpl->_capKind; } + + /** Item which has triggered this selection */ + PoolItem item() const + { return _pimpl->_item; } + + /** This item has triggered the installation (Not already fullfilled requierement only). */ + bool initialInstallation() const + { return _pimpl->_initialInstallation; } + + private: + struct Impl + { + Impl() + : _capKind( Dep::PROVIDES ) + , _initialInstallation( false ) + {} + + Impl( PoolItem i, Capability c, Dep k, bool initial ) + : _cap( c ) + , _capKind( k ) + , _item( i ) + , _initialInstallation( initial ) + {} + + Capability _cap; + Dep _capKind; + PoolItem _item; + bool _initialInstallation; + + private: + friend Impl * rwcowClone( const Impl * rhs ); + /** clone for RWCOW_pointer */ + Impl * clone() const + { return new Impl( *this ); } + }; + RWCOW_pointer _pimpl; + }; + + typedef std::multimap ItemCapKindMap; + typedef std::list ItemCapKindList; + + } // namespace detail + /////////////////////////////////////////////////////////////////// + } // namespace solver + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_ITEMCAPKIND_H diff --git a/zypp/solver/detail/ProblemSolutionCombi.cc b/zypp/solver/detail/ProblemSolutionCombi.cc new file mode 100644 index 0000000..d650ba3 --- /dev/null +++ b/zypp/solver/detail/ProblemSolutionCombi.cc @@ -0,0 +1,57 @@ + +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* ProblemSolution.cc + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +#define ZYPP_USE_RESOLVER_INTERNALS + +#include + +#include + + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////////// + namespace solver + { + ///////////////////////////////////////////////////////////////////// + namespace detail + { + ProblemSolutionCombi::ProblemSolutionCombi() + {} + + void ProblemSolutionCombi::addSingleAction( Capability capability, TransactionKind action) + { addAction( new TransactionSolutionAction( capability, action ) ); } + + void ProblemSolutionCombi::addSingleAction( const PoolItem& item, TransactionKind action ) + { addAction( new TransactionSolutionAction( item, action ) ); } + + void ProblemSolutionCombi::addSingleAction( SolverQueueItem_Ptr item, TransactionKind action ) + { addAction( new TransactionSolutionAction( std::move(item), action ) ); } + + } // namespace detail + ///////////////////////////////////////////////////////////////////// + } // namespace solver + /////////////////////////////////////////////////////////////////////// +} // namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ProblemSolutionCombi.h b/zypp/solver/detail/ProblemSolutionCombi.h new file mode 100644 index 0000000..d0bf265 --- /dev/null +++ b/zypp/solver/detail/ProblemSolutionCombi.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* Resolver_problems.cc + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_PROBLEMSOLUTIONINSTALL_H +#define ZYPP_SOLVER_DETAIL_PROBLEMSOLUTIONINSTALL_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +#include + +#include +#include // TransactionKind + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////////// + namespace solver + { + ///////////////////////////////////////////////////////////////////// + namespace detail + { + ///////////////////////////////////////////////////////////////////////// + /// \class ProblemSolutionCombi + /// \brief Class representing one possible solution to one problem found during resolving. + /// + /// This problem solution is a combination of different actions, + /// e.G. install, delete, keep different resolvables. + ///////////////////////////////////////////////////////////////////////// + class ProblemSolutionCombi : public ProblemSolution + { + public: + /** Constructor. */ + ProblemSolutionCombi(); + + /** + * Add a single action of an item + */ + void addSingleAction( const PoolItem& item, TransactionKind action ); + + /** + * Add a single action of a capability + */ + void addSingleAction( Capability capability, TransactionKind action ); + + /** + * Add a single action of a SolverQueueItem + */ + void addSingleAction( SolverQueueItem_Ptr item, TransactionKind action ); + + /** + * returns the number of actions + */ + size_t actionCount() + { return actions().size(); } + + /** + * Set description text (append) + */ + void addDescription( std::string description ) + { pushDescriptionDetail( std::move(description) ); } + + /** + * Set description text (prepend) + */ + void addFrontDescription( std::string description ) + { pushDescriptionDetail( std::move(description), /*front*/true ); } + }; + + } // namespace detail + ///////////////////////////////////////////////////////////////////// + } // namespace solver + /////////////////////////////////////////////////////////////////////// +} // namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_PROBLEMSOLUTIONAINSTALL_H + diff --git a/zypp/solver/detail/ProblemSolutionIgnore.cc b/zypp/solver/detail/ProblemSolutionIgnore.cc new file mode 100644 index 0000000..937c557 --- /dev/null +++ b/zypp/solver/detail/ProblemSolutionIgnore.cc @@ -0,0 +1,59 @@ + +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* ProblemSolution.cc + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////////// + namespace solver + { + ///////////////////////////////////////////////////////////////////// + namespace detail + { + ProblemSolutionIgnore::ProblemSolutionIgnore( const PoolItem& item ) + // TranslatorExplanation %s = name of package, patch, selection ... + : ProblemSolution( str::form(_("break %s by ignoring some of its dependencies"), item.satSolvable().asString().c_str() ) ) + { + addAction( new InjectSolutionAction( item, WEAK ) ); + } + + ProblemSolutionIgnore::ProblemSolutionIgnore( const PoolItemList& itemList ) + : ProblemSolution( _("generally ignore of some dependencies") ) + { + for ( const auto & item : itemList) + { addAction( new InjectSolutionAction( item, WEAK ) ); } + } + + } // namespace detail + ///////////////////////////////////////////////////////////////////// + } // namespace solver + /////////////////////////////////////////////////////////////////////// +} // namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/ProblemSolutionIgnore.h b/zypp/solver/detail/ProblemSolutionIgnore.h new file mode 100644 index 0000000..98a0d15 --- /dev/null +++ b/zypp/solver/detail/ProblemSolutionIgnore.h @@ -0,0 +1,65 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* Resolver_problems.cc + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_PROBLEMSOLUTIONIGNORE_H +#define ZYPP_SOLVER_DETAIL_PROBLEMSOLUTIONIGNORE_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////////// + namespace solver + { + ///////////////////////////////////////////////////////////////////// + namespace detail + { + ///////////////////////////////////////////////////////////////////////// + /// \class ProblemSolutionIgnore + /// \brief Class representing one possible solution to one problem found during resolving. + /// + /// This problem solution ignores one or more items by setting their + /// dependencies to weak + ///////////////////////////////////////////////////////////////////////// + class ProblemSolutionIgnore : public ProblemSolution + { + public: + typedef std::list PoolItemList; + + ProblemSolutionIgnore( const PoolItem& item ); + ProblemSolutionIgnore( const PoolItemList& itemList ); + }; + + } // namespace detail + ///////////////////////////////////////////////////////////////////// + } // namespace solver + /////////////////////////////////////////////////////////////////////// +} // namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_PROBLEMSOLUTIONIGNORE_H diff --git a/zypp/solver/detail/Resolver.cc b/zypp/solver/detail/Resolver.cc new file mode 100644 index 0000000..2d45f7b --- /dev/null +++ b/zypp/solver/detail/Resolver.cc @@ -0,0 +1,688 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* Resolver.cc + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +#include +#include + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define MAXSOLVERRUNS 5 + +using std::endl; +using std::make_pair; + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::solver" + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +//--------------------------------------------------------------------------- + + +std::ostream & Resolver::dumpOn( std::ostream & os ) const +{ + os << "" << endl; + #define OUTS(t) os << " " << #t << ":\t" << t << endl; + OUTS( _upgradeMode ); + OUTS( _updateMode ); + OUTS( _verifying ); + OUTS( _solveSrcPackages ); + OUTS( _ignoreAlreadyRecommended ); + #undef OUT + return os << ""; +} + + +//--------------------------------------------------------------------------- + +Resolver::Resolver (ResPool pool) + : _pool(std::move(pool)) + , _satResolver(NULL) + , _poolchanged(_pool.serial() ) + , _upgradeMode ( false ) + , _updateMode ( false ) + , _verifying ( false ) + , _solveSrcPackages ( false ) + , _ignoreAlreadyRecommended ( true ) + , _applyDefault_focus ( true ) + , _applyDefault_forceResolve ( true ) + , _applyDefault_cleandepsOnRemove ( true ) + , _applyDefault_onlyRequires ( true ) + , _applyDefault_allowDowngrade ( true ) + , _applyDefault_allowNameChange ( true ) + , _applyDefault_allowArchChange ( true ) + , _applyDefault_allowVendorChange ( true ) + , _applyDefault_dupAllowDowngrade ( true ) + , _applyDefault_dupAllowNameChange ( true ) + , _applyDefault_dupAllowArchChange ( true ) + , _applyDefault_dupAllowVendorChange ( true ) +{ + sat::Pool satPool( sat::Pool::instance() ); + _satResolver = new SATResolver(_pool, satPool.get()); +} + + +Resolver::~Resolver() +{ + delete _satResolver; +} + +sat::detail::CSolver * Resolver::get() const +{ return _satResolver->get(); } + + +void Resolver::setDefaultSolverFlags( bool all_r ) +{ + MIL << "setDefaultSolverFlags all=" << all_r << endl; + + if ( all_r || _applyDefault_focus ) setFocus( ResolverFocus::Default ); + +#define ZOLV_FLAG_DEFAULT( ZSETTER, ZGETTER ) \ + if ( all_r || _applyDefault_##ZGETTER ) ZSETTER( indeterminate ) + + ZOLV_FLAG_DEFAULT( setForceResolve ,forceResolve ); + ZOLV_FLAG_DEFAULT( setCleandepsOnRemove ,cleandepsOnRemove ); + ZOLV_FLAG_DEFAULT( setOnlyRequires ,onlyRequires ); + ZOLV_FLAG_DEFAULT( setAllowDowngrade ,allowDowngrade ); + ZOLV_FLAG_DEFAULT( setAllowNameChange ,allowNameChange ); + ZOLV_FLAG_DEFAULT( setAllowArchChange ,allowArchChange ); + ZOLV_FLAG_DEFAULT( setAllowVendorChange ,allowVendorChange ); + ZOLV_FLAG_DEFAULT( dupSetAllowDowngrade ,dupAllowDowngrade ); + ZOLV_FLAG_DEFAULT( dupSetAllowNameChange ,dupAllowNameChange ); + ZOLV_FLAG_DEFAULT( dupSetAllowArchChange ,dupAllowArchChange ); + ZOLV_FLAG_DEFAULT( dupSetAllowVendorChange ,dupAllowVendorChange ); +#undef ZOLV_FLAG_TRIBOOL +} +//--------------------------------------------------------------------------- +// forward flags too SATResolver +void Resolver::setFocus( ResolverFocus focus_r ) { + _applyDefault_focus = ( focus_r == ResolverFocus::Default ); + _satResolver->_focus = _applyDefault_focus ? ZConfig::instance().solver_focus() : focus_r; +} +ResolverFocus Resolver::focus() const { return _satResolver->_focus; } + +void Resolver::setRemoveOrphaned( bool yesno_r ) { _satResolver->_removeOrphaned = yesno_r; } +bool Resolver::removeOrphaned() const { return _satResolver->_removeOrphaned; } + +void Resolver::setRemoveUnneeded( bool yesno_r ) { _satResolver->_removeUnneeded = yesno_r; } +bool Resolver::removeUnneeded() const { return _satResolver->_removeUnneeded; } + +#define ZOLV_FLAG_TRIBOOL( ZSETTER, ZGETTER, ZVARDEFAULT, ZVARNAME ) \ + void Resolver::ZSETTER( TriBool state_r ) \ + { _applyDefault_##ZGETTER = indeterminate(state_r); \ + bool newval = _applyDefault_##ZGETTER ? ZVARDEFAULT : bool(state_r); \ + if ( ZVARNAME != newval ) { \ + DBG << #ZGETTER << ": changed from " << (bool)ZVARNAME << " to " << newval << endl;\ + ZVARNAME = newval; \ + } \ + } \ + bool Resolver::ZGETTER() const \ + { return ZVARNAME; } \ + +// Flags stored here follow the naming convention,... +// Flags down in _satResolver don't. Could match `_satResolver->_##ZGETTER` +#define ZOLV_FLAG_SATSOLV( ZSETTER, ZGETTER, ZVARDEFAULT, ZVARNAME ) \ + ZOLV_FLAG_TRIBOOL( ZSETTER, ZGETTER, ZVARDEFAULT, _satResolver->ZVARNAME ) + +// NOTE: ZVARDEFAULT must be in sync with SATResolver ctor +ZOLV_FLAG_SATSOLV( setForceResolve ,forceResolve ,false ,_allowuninstall ) +ZOLV_FLAG_SATSOLV( setCleandepsOnRemove ,cleandepsOnRemove ,ZConfig::instance().solver_cleandepsOnRemove() ,_cleandepsOnRemove ) +ZOLV_FLAG_SATSOLV( setOnlyRequires ,onlyRequires ,ZConfig::instance().solver_onlyRequires() ,_onlyRequires ) +ZOLV_FLAG_SATSOLV( setAllowDowngrade ,allowDowngrade ,false ,_allowdowngrade ) +ZOLV_FLAG_SATSOLV( setAllowNameChange ,allowNameChange ,true /*bsc#1071466*/ ,_allownamechange ) +ZOLV_FLAG_SATSOLV( setAllowArchChange ,allowArchChange ,false ,_allowarchchange ) +ZOLV_FLAG_SATSOLV( setAllowVendorChange ,allowVendorChange ,ZConfig::instance().solver_allowVendorChange() ,_allowvendorchange ) +ZOLV_FLAG_SATSOLV( dupSetAllowDowngrade ,dupAllowDowngrade ,ZConfig::instance().solver_dupAllowDowngrade() ,_dup_allowdowngrade ) +ZOLV_FLAG_SATSOLV( dupSetAllowNameChange ,dupAllowNameChange ,ZConfig::instance().solver_dupAllowNameChange() ,_dup_allownamechange ) +ZOLV_FLAG_SATSOLV( dupSetAllowArchChange ,dupAllowArchChange ,ZConfig::instance().solver_dupAllowArchChange() ,_dup_allowarchchange ) +ZOLV_FLAG_SATSOLV( dupSetAllowVendorChange ,dupAllowVendorChange ,ZConfig::instance().solver_dupAllowVendorChange() ,_dup_allowvendorchange ) +#undef ZOLV_FLAG_SATSOLV +#undef ZOLV_FLAG_TRIBOOL +//--------------------------------------------------------------------------- + +ResPool Resolver::pool() const +{ return _pool; } + +void Resolver::reset( bool keepExtras ) +{ + _verifying = false; + + if (!keepExtras) { + _extra_requires.clear(); + _extra_conflicts.clear(); + } + + _isInstalledBy.clear(); + _installs.clear(); + _satifiedByInstalled.clear(); + _installedSatisfied.clear(); +} + +PoolItemList Resolver::problematicUpdateItems() const +{ return _satResolver->problematicUpdateItems(); } + +void Resolver::addExtraRequire( const Capability & capability ) +{ _extra_requires.insert (capability); } + +void Resolver::removeExtraRequire( const Capability & capability ) +{ _extra_requires.erase (capability); } + +void Resolver::addExtraConflict( const Capability & capability ) +{ _extra_conflicts.insert (capability); } + +void Resolver::removeExtraConflict( const Capability & capability ) +{ _extra_conflicts.erase (capability); } + +void Resolver::removeQueueItem( const SolverQueueItem_Ptr& item ) +{ + bool found = false; + for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin(); + iter != _added_queue_items.end(); iter++) { + if (*iter == item) { + _added_queue_items.remove(*iter); + found = true; + break; + } + } + if (!found) { + _removed_queue_items.push_back (item); + _removed_queue_items.unique (); + } +} + +void Resolver::addQueueItem( const SolverQueueItem_Ptr& item ) +{ + bool found = false; + for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin(); + iter != _removed_queue_items.end(); iter++) { + if (*iter == item) { + _removed_queue_items.remove(*iter); + found = true; + break; + } + } + if (!found) { + _added_queue_items.push_back (item); + _added_queue_items.unique (); + } +} + +void Resolver::addWeak( const PoolItem & item ) +{ _addWeak.push_back( item ); } + +//--------------------------------------------------------------------------- + +struct UndoTransact +{ + ResStatus::TransactByValue resStatus; + UndoTransact ( const ResStatus::TransactByValue &status) + :resStatus(status) + { } + + bool operator()( const PoolItem& item ) // only transacts() items go here + { + item.status().resetTransact( resStatus );// clear any solver/establish transactions + return true; + } +}; + + +struct DoTransact +{ + ResStatus::TransactByValue resStatus; + DoTransact ( const ResStatus::TransactByValue &status) + :resStatus(status) + { } + + bool operator()( const PoolItem& item ) // only transacts() items go here + { + item.status().setTransact( true, resStatus ); + return true; + } +}; + +//---------------------------------------------------------------------------- +// undo +void Resolver::undo() +{ + UndoTransact info(ResStatus::APPL_LOW); + MIL << "*** undo ***" << endl; + invokeOnEach ( _pool.begin(), _pool.end(), + resfilter::ByTransact( ), // collect transacts from Pool to resolver queue + std::ref(info) ); + // Regard dependencies of the item weak onl + _addWeak.clear(); + + // Additional QueueItems which has to be regarded by the solver + _removed_queue_items.clear(); + _added_queue_items.clear(); + + return; +} + +void Resolver::solverInit() +{ + // Solving with libsolv + static bool poolDumped = false; + MIL << "-------------- Calling SAT Solver -------------------" << endl; + if ( getenv("ZYPP_FULLLOG") and get() ) { // libzypp/issues/317: get() to make sure a satsolver instance is actually present + Testcase testcase("/var/log/YaST2/autoTestcase"); + if (!poolDumped) { + testcase.createTestcase (*this, true, false); // dump pool + poolDumped = true; + } else { + testcase.createTestcase (*this, false, false); // write control file only + } + } + + // update solver mode flags + _satResolver->setDistupgrade (_upgradeMode); + _satResolver->setUpdatesystem (_updateMode); + _satResolver->setFixsystem ( isVerifyingMode() ); + _satResolver->setSolveSrcPackages ( solveSrcPackages() ); + _satResolver->setIgnorealreadyrecommended ( ignoreAlreadyRecommended() ); + + if (_upgradeMode) { + // Maybe depend on ZConfig::solverUpgradeRemoveDroppedPackages. + // For sure right but a change in behavior for old distros. + // (Will disable weakremover processing in SATResolver) + // _satResolver->setRemoveOrphaned( ... ); + } + + // Resetting additional solver information + _isInstalledBy.clear(); + _installs.clear(); + _satifiedByInstalled.clear(); + _installedSatisfied.clear(); +} + +bool Resolver::verifySystem() +{ + DBG << "Resolver::verifySystem()" << endl; + _verifying = true; + UndoTransact resetting (ResStatus::APPL_HIGH); + invokeOnEach ( _pool.begin(), _pool.end(), + resfilter::ByTransact( ), // Resetting all transcations + std::ref(resetting) ); + return resolvePool(); +} + + +bool Resolver::doUpgrade() +{ + // Setting Resolver to upgrade mode. SAT solver will do the update + _upgradeMode = true; + return resolvePool(); +} + +bool Resolver::resolvePool() +{ + solverInit(); + return _satResolver->resolvePool(_extra_requires, _extra_conflicts, _addWeak, _upgradeRepos ); +} + +void Resolver::doUpdate() +{ + _updateMode = true; + solverInit(); + return _satResolver->doUpdate(); +} + +bool Resolver::resolveQueue( solver::detail::SolverQueueItemList & queue ) +{ + solverInit(); + + // add/remove additional SolverQueueItems + for (SolverQueueItemList::const_iterator iter = _removed_queue_items.begin(); + iter != _removed_queue_items.end(); iter++) { + for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) { + if ( (*iterQueue)->cmp(*iter) == 0) { + MIL << "remove from queue" << *iter; + queue.remove(*iterQueue); + break; + } + } + } + + for (SolverQueueItemList::const_iterator iter = _added_queue_items.begin(); + iter != _added_queue_items.end(); iter++) { + bool found = false; + for (SolverQueueItemList::const_iterator iterQueue = queue.begin(); iterQueue != queue.end(); iterQueue++) { + if ( (*iterQueue)->cmp(*iter) == 0) { + found = true; + break; + } + } + if (!found) { + MIL << "add to queue" << *iter; + queue.push_back(*iter); + } + } + + // The application has to take care to write these solutions back to e.g. selectables in order + // give the user a chance for changing these decisions again. + _removed_queue_items.clear(); + _added_queue_items.clear(); + + return _satResolver->resolveQueue(queue, _addWeak); +} + +sat::Transaction Resolver::getTransaction() +{ + // FIXME: That's an ugly way of pushing autoInstalled into the transaction. + sat::Transaction ret( sat::Transaction::loadFromPool ); + ret.autoInstalled( _satResolver->autoInstalled() ); + return ret; +} + + +//---------------------------------------------------------------------------- +// Getting more information about the solve results + +ResolverProblemList Resolver::problems() const +{ + MIL << "Resolver::problems()" << endl; + return _satResolver->problems(); +} + +void Resolver::applySolutions( const ProblemSolutionList & solutions ) +{ + for ( const ProblemSolution_Ptr& solution : solutions ) + { + if ( ! applySolution( *solution ) ) + break; + } +} + +bool Resolver::applySolution( const ProblemSolution & solution ) +{ + bool ret = true; + DBG << "apply solution " << solution << endl; + for ( const SolutionAction_Ptr& action : solution.actions() ) + { + if ( ! action->execute( *this ) ) + { + WAR << "apply solution action failed: " << action << endl; + ret = false; + break; + } + } + return ret; +} + +//---------------------------------------------------------------------------- + +void Resolver::collectResolverInfo() +{ + if ( _satResolver + && _isInstalledBy.empty() + && _installs.empty()) { + + // generating new + PoolItemList itemsToInstall = _satResolver->resultItemsToInstall(); + + for (PoolItemList::const_iterator instIter = itemsToInstall.begin(); + instIter != itemsToInstall.end(); instIter++) { + // Requires + for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::REQUIRES).begin(); capIt != (*instIter)->dep (Dep::REQUIRES).end(); ++capIt) + { + sat::WhatProvides possibleProviders(*capIt); + for_( iter, possibleProviders.begin(), possibleProviders.end() ) { + PoolItem provider = ResPool::instance().find( *iter ); + + // searching if this provider will already be installed + bool found = false; + bool alreadySetForInstallation = false; + ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider); + while (pos != _isInstalledBy.end() + && pos->first == provider + && !found) { + alreadySetForInstallation = true; + ItemCapKind capKind = pos->second; + if (capKind.item() == *instIter) found = true; + pos++; + } + + if (!found + && provider.status().isToBeInstalled()) { + if (provider.status().isBySolver()) { + ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, !alreadySetForInstallation ); + _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy)); + } else { + // no initial installation cause it has been set be e.g. user + ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::REQUIRES, false ); + _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy)); + } + ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, !alreadySetForInstallation ); + _installs.insert (make_pair( *instIter, capKindisInstalledBy)); + } + + if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed + ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::REQUIRES, false ); + _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy)); + + ItemCapKind installedSatisfied( *instIter, *capIt, Dep::REQUIRES, false ); + _installedSatisfied.insert (make_pair( provider, installedSatisfied)); + } + } + } + + if (!(_satResolver->onlyRequires())) { + //Recommends + for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::RECOMMENDS).begin(); capIt != (*instIter)->dep (Dep::RECOMMENDS).end(); ++capIt) + { + sat::WhatProvides possibleProviders(*capIt); + for_( iter, possibleProviders.begin(), possibleProviders.end() ) { + PoolItem provider = ResPool::instance().find( *iter ); + + // searching if this provider will already be installed + bool found = false; + bool alreadySetForInstallation = false; + ItemCapKindMap::const_iterator pos = _isInstalledBy.find(provider); + while (pos != _isInstalledBy.end() + && pos->first == provider + && !found) { + alreadySetForInstallation = true; + ItemCapKind capKind = pos->second; + if (capKind.item() == *instIter) found = true; + pos++; + } + + if (!found + && provider.status().isToBeInstalled()) { + if (provider.status().isBySolver()) { + ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation ); + _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy)); + } else { + // no initial installation cause it has been set be e.g. user + ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::RECOMMENDS, false ); + _isInstalledBy.insert (make_pair( provider, capKindisInstalledBy)); + } + ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, !alreadySetForInstallation ); + _installs.insert (make_pair( *instIter, capKindisInstalledBy)); + } + + if (provider.status().staysInstalled()) { // Is already satisfied by an item which is installed + ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::RECOMMENDS, false ); + _satifiedByInstalled.insert (make_pair( *instIter, capKindisInstalledBy)); + + ItemCapKind installedSatisfied( *instIter, *capIt, Dep::RECOMMENDS, false ); + _installedSatisfied.insert (make_pair( provider, installedSatisfied)); + } + } + } + + //Supplements + for (Capabilities::const_iterator capIt = (*instIter)->dep (Dep::SUPPLEMENTS).begin(); capIt != (*instIter)->dep (Dep::SUPPLEMENTS).end(); ++capIt) + { + sat::WhatProvides possibleProviders(*capIt); + for_( iter, possibleProviders.begin(), possibleProviders.end() ) { + PoolItem provider = ResPool::instance().find( *iter ); + // searching if this item will already be installed + bool found = false; + bool alreadySetForInstallation = false; + ItemCapKindMap::const_iterator pos = _isInstalledBy.find(*instIter); + while (pos != _isInstalledBy.end() + && pos->first == *instIter + && !found) { + alreadySetForInstallation = true; + ItemCapKind capKind = pos->second; + if (capKind.item() == provider) found = true; + pos++; + } + + if (!found + && instIter->status().isToBeInstalled()) { + if (instIter->status().isBySolver()) { + ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation ); + _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy)); + } else { + // no initial installation cause it has been set be e.g. user + ItemCapKind capKindisInstalledBy( provider, *capIt, Dep::SUPPLEMENTS, false ); + _isInstalledBy.insert (make_pair( *instIter, capKindisInstalledBy)); + } + ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation ); + _installs.insert (make_pair( provider, capKindisInstalledBy)); + } + + if (instIter->status().staysInstalled()) { // Is already satisfied by an item which is installed + ItemCapKind capKindisInstalledBy( *instIter, *capIt, Dep::SUPPLEMENTS, !alreadySetForInstallation ); + _satifiedByInstalled.insert (make_pair( provider, capKindisInstalledBy)); + + ItemCapKind installedSatisfied( provider, *capIt, Dep::SUPPLEMENTS, false ); + _installedSatisfied.insert (make_pair( *instIter, installedSatisfied)); + } + } + } + } + } + } +} + + +ItemCapKindList Resolver::isInstalledBy( const PoolItem & item ) +{ + ItemCapKindList ret; + collectResolverInfo(); + + for (ItemCapKindMap::const_iterator iter = _isInstalledBy.find(item); iter != _isInstalledBy.end();) { + ItemCapKind info = iter->second; + PoolItem iterItem = iter->first; + if (iterItem == item) { + ret.push_back(info); + iter++; + } else { + // exit + iter = _isInstalledBy.end(); + } + } + return ret; +} + +ItemCapKindList Resolver::installs( const PoolItem & item ) +{ + ItemCapKindList ret; + collectResolverInfo(); + + for (ItemCapKindMap::const_iterator iter = _installs.find(item); iter != _installs.end();) { + ItemCapKind info = iter->second; + PoolItem iterItem = iter->first; + if (iterItem == item) { + ret.push_back(info); + iter++; + } else { + // exit + iter = _installs.end(); + } + } + return ret; +} + +ItemCapKindList Resolver::satifiedByInstalled( const PoolItem & item ) +{ + ItemCapKindList ret; + collectResolverInfo(); + + for (ItemCapKindMap::const_iterator iter = _satifiedByInstalled.find(item); iter != _satifiedByInstalled.end();) { + ItemCapKind info = iter->second; + PoolItem iterItem = iter->first; + if (iterItem == item) { + ret.push_back(info); + iter++; + } else { + // exit + iter = _satifiedByInstalled.end(); + } + } + return ret; +} + +ItemCapKindList Resolver::installedSatisfied( const PoolItem & item ) +{ + ItemCapKindList ret; + collectResolverInfo(); + + for (ItemCapKindMap::const_iterator iter = _installedSatisfied.find(item); iter != _installedSatisfied.end();) { + ItemCapKind info = iter->second; + PoolItem iterItem = iter->first; + if (iterItem == item) { + ret.push_back(info); + iter++; + } else { + // exit + iter = _installedSatisfied.end(); + } + } + return ret; +} + + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + diff --git a/zypp/solver/detail/Resolver.h b/zypp/solver/detail/Resolver.h new file mode 100644 index 0000000..7559184 --- /dev/null +++ b/zypp/solver/detail/Resolver.h @@ -0,0 +1,263 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* Resolver.h + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_RESOLVER_H +#define ZYPP_SOLVER_DETAIL_RESOLVER_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +#include +#include +#include +#include + +#include +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + namespace sat + { + class Transaction; + } + /////////////////////////////////////////////////////////////////////// + namespace solver + { + ///////////////////////////////////////////////////////////////////// + namespace detail + { + class SATResolver; + typedef std::list PoolItemList; + typedef std::set PoolItemSet; + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : Resolver +/** A mid layer class we should remove + * \todo Merge this and class SATResolver. Logic and date are horribly + * distributed between this and SATResolver. Either SATResolver becomes + * a pure wrapper adapting the libsolv C interface to fit our needs, and + * all the solver logic and problem handling goes here; or completely merge + * both classes. + */ +class ZYPP_API_DEPTESTOMATIC Resolver : private base::NonCopyable +{ + typedef std::multimap ItemCapKindMap; + private: + ResPool _pool; + SATResolver *_satResolver; + SerialNumberWatcher _poolchanged; + + CapabilitySet _extra_requires; + CapabilitySet _extra_conflicts; + std::set _upgradeRepos; + + // Regard dependencies of the item weak onl + PoolItemList _addWeak; + + /** \name Solver flags */ + //@{ + bool _upgradeMode:1; // Resolver has been called with doUpgrade + bool _updateMode:1; // Resolver has been called with doUpdate + bool _verifying:1; // The system will be checked + bool _solveSrcPackages:1; // whether to generate solver jobs for selected source packges. + bool _ignoreAlreadyRecommended:1; // ignore recommended packages that have already been recommended by the installed packages + //@} + + /** \name applyDefaults + * Remember whether global default or explicit settings are applied to SATResolver. + * Global defaults may change with the Target, explicit settings not. + */ + //@{ + bool _applyDefault_focus:1; + bool _applyDefault_forceResolve:1; + bool _applyDefault_cleandepsOnRemove:1; + bool _applyDefault_onlyRequires:1; + bool _applyDefault_allowDowngrade:1; + bool _applyDefault_allowNameChange:1; + bool _applyDefault_allowArchChange:1; + bool _applyDefault_allowVendorChange:1; + bool _applyDefault_dupAllowDowngrade:1; + bool _applyDefault_dupAllowNameChange:1; + bool _applyDefault_dupAllowArchChange:1; + bool _applyDefault_dupAllowVendorChange:1; + //@} + + // Additional QueueItems which has to be regarded by the solver + // This will be used e.g. by solution actions + solver::detail::SolverQueueItemList _removed_queue_items; + solver::detail::SolverQueueItemList _added_queue_items; + + // Additional information about the solverrun + ItemCapKindMap _isInstalledBy; + ItemCapKindMap _installs; + ItemCapKindMap _satifiedByInstalled; + ItemCapKindMap _installedSatisfied; + + // helpers + void collectResolverInfo(); + + // Unmaintained packages which does not fit to the updated system + // (broken dependencies) will be deleted. + // returns true if solving was successful + bool checkUnmaintainedItems (); + + void solverInit(); + + public: + + Resolver( ResPool pool ); + virtual ~Resolver(); + + // ---------------------------------- I/O + + std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<( std::ostream& str, const Resolver & obj ) + { return obj.dumpOn (str); } + + // ---------------------------------- methods + + ResPool pool() const; + void setPool( const ResPool & pool ) { _pool = pool; } + + /** + * Reset all solver flags to the systems default (e.g. from zypp.conf). + * + * The information whether a \ref SATResolver setting was explicitly set or follows + * the targets default (zypp.conf) is stored here in the \ref Resolver. + * If \a all_r is \c false, only those settings are updated, which still follow + * the target defaults (e.g. after the target has changed). Otherwise all explicit + * settings are discarded and the defaults are applied. + */ + void setDefaultSolverFlags( bool all_r ); + + void addUpgradeRepo( Repository repo_r ) { if ( repo_r && ! repo_r.isSystemRepo() ) _upgradeRepos.insert( repo_r ); } + bool upgradingRepo( Repository repo_r ) const { return( _upgradeRepos.find( repo_r ) != _upgradeRepos.end() ); } + void removeUpgradeRepo( Repository repo_r ) { _upgradeRepos.erase( repo_r ); } + void removeUpgradeRepos() { _upgradeRepos.clear(); } + const std::set & upgradeRepos() const { return _upgradeRepos; } + + void addExtraRequire( const Capability & capability ); + void removeExtraRequire( const Capability & capability ); + void addExtraConflict( const Capability & capability ); + void removeExtraConflict( const Capability & capability ); + + void removeQueueItem( const SolverQueueItem_Ptr& item ); + void addQueueItem( const SolverQueueItem_Ptr& item ); + + CapabilitySet extraRequires() const { return _extra_requires; } + CapabilitySet extraConflicts() const { return _extra_conflicts; } + + void addWeak( const PoolItem & item ); + + bool verifySystem(); + bool resolvePool(); + bool resolveQueue( SolverQueueItemList & queue ); + void doUpdate(); + + bool doUpgrade(); + PoolItemList problematicUpdateItems() const; + + /** \name Solver flags */ + //@{ + bool ignoreAlreadyRecommended() const { return _ignoreAlreadyRecommended; } + void setIgnoreAlreadyRecommended( bool yesno_r ) { _ignoreAlreadyRecommended = yesno_r; } + + bool isUpgradeMode() const { return _upgradeMode; }// Resolver has been called with doUpgrade + void setUpgradeMode( bool yesno_r ) { _upgradeMode = yesno_r; } + + bool isUpdateMode() const { return _updateMode; } // Resolver has been called with doUpdate + void setUpdateMode( bool yesno_r ) { _updateMode = yesno_r; } + + bool isVerifyingMode() const { return _verifying; } // The system will be checked + void setVerifyingMode( TriBool state_r ) { _verifying = indeterminate(state_r) ? false : bool(state_r); } + + bool solveSrcPackages() const { return _solveSrcPackages; } + void setSolveSrcPackages( TriBool state_r ) { _solveSrcPackages = indeterminate(state_r) ? false : bool(state_r); } + //@} + + void setRemoveOrphaned( bool yesno_r ); + bool removeOrphaned() const; + + void setRemoveUnneeded( bool yesno_r ); + bool removeUnneeded() const; + + void setFocus( ResolverFocus focus_r ); + ResolverFocus focus() const; + +#define ZOLV_FLAG_TRIBOOL( ZSETTER, ZGETTER ) \ + void ZSETTER( TriBool state_r ); \ + bool ZGETTER() const; \ + + ZOLV_FLAG_TRIBOOL( setForceResolve ,forceResolve ) + ZOLV_FLAG_TRIBOOL( setCleandepsOnRemove ,cleandepsOnRemove ) + ZOLV_FLAG_TRIBOOL( setOnlyRequires ,onlyRequires ) + ZOLV_FLAG_TRIBOOL( setAllowDowngrade ,allowDowngrade ) + ZOLV_FLAG_TRIBOOL( setAllowNameChange ,allowNameChange ) + ZOLV_FLAG_TRIBOOL( setAllowArchChange ,allowArchChange ) + ZOLV_FLAG_TRIBOOL( setAllowVendorChange ,allowVendorChange ) + ZOLV_FLAG_TRIBOOL( dupSetAllowDowngrade ,dupAllowDowngrade ) + ZOLV_FLAG_TRIBOOL( dupSetAllowNameChange ,dupAllowNameChange ) + ZOLV_FLAG_TRIBOOL( dupSetAllowArchChange ,dupAllowArchChange ) + ZOLV_FLAG_TRIBOOL( dupSetAllowVendorChange ,dupAllowVendorChange ) +#undef ZOLV_FLAG_TRIBOOL + + ResolverProblemList problems() const; + + void applySolutions( const ProblemSolutionList & solutions ); + bool applySolution( const ProblemSolution & solution ); + + // Return the Transaction computed by the last solver run. + sat::Transaction getTransaction(); + + // reset all SOLVER transaction in pool + void undo(); + + void reset( bool keepExtras = false ); + + // Get more information about the solverrun + // Which item will be installed by another item or triggers an item for + // installation + ItemCapKindList isInstalledBy( const PoolItem & item ); + ItemCapKindList installs( const PoolItem & item ); + ItemCapKindList satifiedByInstalled (const PoolItem & item ); + ItemCapKindList installedSatisfied( const PoolItem & item ); + +public: + /** Expert backdoor. */ + sat::detail::CSolver * get() const; +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_RESOLVER_H diff --git a/zypp/solver/detail/SATResolver.cc b/zypp/solver/detail/SATResolver.cc new file mode 100644 index 0000000..8d73351 --- /dev/null +++ b/zypp/solver/detail/SATResolver.cc @@ -0,0 +1,1711 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SATResolver.cc + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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 the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +extern "C" +{ +#include +#include +#include +#include +#include +#include +#include +} + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +using std::endl; + +#define XDEBUG(x) do { if (base::logger::isExcessive()) XXX << x << std::endl;} while (0) + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::solver" + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////////// + namespace + { + inline void solverSetFocus( sat::detail::CSolver & satSolver_r, const ResolverFocus & focus_r ) + { + switch ( focus_r ) + { + case ResolverFocus::Default: // fallthrough to Job + case ResolverFocus::Job: + solver_set_flag( &satSolver_r, SOLVER_FLAG_FOCUS_INSTALLED, 0 ); + solver_set_flag( &satSolver_r, SOLVER_FLAG_FOCUS_BEST, 0 ); + break; + case ResolverFocus::Installed: + solver_set_flag( &satSolver_r, SOLVER_FLAG_FOCUS_INSTALLED, 1 ); + solver_set_flag( &satSolver_r, SOLVER_FLAG_FOCUS_BEST, 0 ); + break; + case ResolverFocus::Update: + solver_set_flag( &satSolver_r, SOLVER_FLAG_FOCUS_INSTALLED, 0 ); + solver_set_flag( &satSolver_r, SOLVER_FLAG_FOCUS_BEST, 1 ); + break; + } + } + + /** Helper collecting pseudo installed items from the pool. + * \todo: pseudoItems are cachable as long as pool content does not change + */ + inline sat::Queue collectPseudoInstalled( const ResPool & pool_r ) + { + sat::Queue ret; + for ( const PoolItem & pi : pool_r ) + if ( traits::isPseudoInstalled( pi.kind() ) ) ret.push( pi.id() ); + return ret; + } + + /** Copy back new \ref WeakValue to \ref PoolItem after solving. + * On the fly collect orphaned items (cached by the solver for the UI) + */ + inline void solverCopyBackWeak( sat::detail::CSolver & satSolver_r, PoolItemList & orphanedItems_r ) + { + // NOTE: assert all items weak stati are reset (resetWeak was called) + { + sat::Queue recommendations; + sat::Queue suggestions; + ::solver_get_recommendations( &satSolver_r, recommendations, suggestions, 0 ); + for ( sat::Queue::size_type i = 0; i < recommendations.size(); ++i ) + PoolItem(sat::Solvable(recommendations[i])).status().setRecommended( true ); + for ( sat::Queue::size_type i = 0; i < suggestions.size(); ++i ) + PoolItem(sat::Solvable(suggestions[i])).status().setSuggested( true ); + } + { + orphanedItems_r.clear(); // cached on the fly + sat::Queue orphaned; + ::solver_get_orphaned( &satSolver_r, orphaned ); + for ( sat::Queue::size_type i = 0; i < orphaned.size(); ++i ) + { + PoolItem pi { sat::Solvable(orphaned[i]) }; + pi.status().setOrphaned( true ); + orphanedItems_r.push_back( pi ); + } + } + { + sat::Queue unneeded; + ::solver_get_unneeded( &satSolver_r, unneeded, 1 ); + for ( sat::Queue::size_type i = 0; i < unneeded.size(); ++i ) + PoolItem(sat::Solvable(unneeded[i])).status().setUnneeded( true ); + } + } + + /** Copy back new \ref ValidateValue to \ref PoolItem after solving. */ + inline void solverCopyBackValidate( sat::detail::CSolver & satSolver_r, const ResPool & pool_r ) + { + sat::Queue pseudoItems { collectPseudoInstalled( pool_r ) }; + if ( ! pseudoItems.empty() ) + { + sat::Queue pseudoFlags; + ::solver_trivial_installable( &satSolver_r, pseudoItems, pseudoFlags ); + + for ( sat::Queue::size_type i = 0; i < pseudoItems.size(); ++i ) + { + PoolItem pi { sat::Solvable(pseudoItems[i]) }; + switch ( pseudoFlags[i] ) + { + case 0: pi.status().setBroken(); break; + case 1: pi.status().setSatisfied(); break; + case -1: pi.status().setNonRelevant(); break; + default: pi.status().setUndetermined(); break; + } + } + } + } + + } //namespace + /////////////////////////////////////////////////////////////////////// + + + +IMPL_PTR_TYPE(SATResolver); + +#define MAYBE_CLEANDEPS (cleandepsOnRemove()?SOLVER_CLEANDEPS:0) + +//--------------------------------------------------------------------------- +// Callbacks for SAT policies +//--------------------------------------------------------------------------- + +int vendorCheck( sat::detail::CPool *pool, Solvable *solvable1, Solvable *solvable2 ) +{ return VendorAttr::instance().equivalent( IdString(solvable1->vendor), IdString(solvable2->vendor) ) ? 0 : 1; } + +int relaxedVendorCheck( sat::detail::CPool *pool, Solvable *solvable1, Solvable *solvable2 ) +{ return VendorAttr::instance().relaxedEquivalent( IdString(solvable1->vendor), IdString(solvable2->vendor) ) ? 0 : 1; } + +/** ResPool helper to compute the initial status of Patches etc. + * An empty solver run (no jobs) just to compute the initial status + * of pseudo installed items (patches). + */ +void establish( sat::Queue & pseudoItems_r, sat::Queue & pseudoFlags_r ) +{ + pseudoItems_r = collectPseudoInstalled( ResPool::instance() ); + if ( ! pseudoItems_r.empty() ) + { + auto satPool = sat::Pool::instance(); + MIL << "Establish..." << endl; + sat::detail::CPool * cPool { satPool.get() }; + ::pool_set_custom_vendorcheck( cPool, &vendorCheck ); + + sat::Queue jobQueue; + // Add rules for parallel installable resolvables with different versions + for ( const sat::Solvable & solv : satPool.multiversion() ) + { + jobQueue.push( SOLVER_NOOBSOLETES | SOLVER_SOLVABLE ); + jobQueue.push( solv.id() ); + } + + AutoDispose cSolver { ::solver_create( cPool ), ::solver_free }; + satPool.prepare(); + if ( ::solver_solve( cSolver, jobQueue ) != 0 ) + INT << "How can establish fail?" << endl; + + ::solver_trivial_installable( cSolver, pseudoItems_r, pseudoFlags_r ); + + for ( sat::Queue::size_type i = 0; i < pseudoItems_r.size(); ++i ) + { + PoolItem pi { sat::Solvable(pseudoItems_r[i]) }; + switch ( pseudoFlags_r[i] ) + { + case 0: pi.status().setBroken(); break; + case 1: pi.status().setSatisfied(); break; + case -1: pi.status().setNonRelevant(); break; + default: pi.status().setUndetermined(); break; + } + } + MIL << "Establish DONE" << endl; + } + else + MIL << "Establish not needed." << endl; +} + +inline std::string itemToString( const PoolItem & item ) +{ + if ( !item ) + return std::string(); + + sat::Solvable slv( item.satSolvable() ); + std::string ret( slv.asString() ); // n-v-r.a + if ( ! slv.isSystem() ) + { + ret += "["; + ret += slv.repository().alias(); + ret += "]"; + } + return ret; +} + +//--------------------------------------------------------------------------- + +std::ostream & +SATResolver::dumpOn( std::ostream & os ) const +{ + os << "" << endl; + if (_satSolver) { +#define OUTS(X) os << " " << #X << "\t= " << solver_get_flag(_satSolver, SOLVER_FLAG_##X) << endl + OUTS( ALLOW_DOWNGRADE ); + OUTS( ALLOW_ARCHCHANGE ); + OUTS( ALLOW_VENDORCHANGE ); + OUTS( ALLOW_NAMECHANGE ); + OUTS( ALLOW_UNINSTALL ); + OUTS( NO_UPDATEPROVIDE ); + OUTS( SPLITPROVIDES ); + OUTS( ONLY_NAMESPACE_RECOMMENDED ); + OUTS( ADD_ALREADY_RECOMMENDED ); + OUTS( NO_INFARCHCHECK ); + OUTS( KEEP_EXPLICIT_OBSOLETES ); + OUTS( BEST_OBEY_POLICY ); + OUTS( NO_AUTOTARGET ); + OUTS( DUP_ALLOW_DOWNGRADE ); + OUTS( DUP_ALLOW_ARCHCHANGE ); + OUTS( DUP_ALLOW_VENDORCHANGE ); + OUTS( DUP_ALLOW_NAMECHANGE ); + OUTS( KEEP_ORPHANS ); + OUTS( BREAK_ORPHANS ); + OUTS( YUM_OBSOLETES ); +#undef OUTS + os << " focus = " << _focus << endl; + os << " distupgrade = " << _distupgrade << endl; + os << " removeOrphaned = " << _removeOrphaned << endl; + os << " solveSrcPackages = " << _solveSrcPackages << endl; + os << " cleandepsOnRemove = " << _cleandepsOnRemove << endl; + os << " fixsystem = " << _fixsystem << endl; + } else { + os << ""; + } + return os << "" << endl; +} + +//--------------------------------------------------------------------------- + +// NOTE: flag defaults must be in sync with ZVARDEFAULT in Resolver.cc +SATResolver::SATResolver (ResPool pool, sat::detail::CPool *satPool) + : _pool(std::move(pool)) + , _satPool(satPool) + , _satSolver(NULL) + , _focus ( ZConfig::instance().solver_focus() ) + , _fixsystem(false) + , _allowdowngrade ( false ) + , _allownamechange ( true ) // bsc#1071466 + , _allowarchchange ( false ) + , _allowvendorchange ( ZConfig::instance().solver_allowVendorChange() ) + , _allowuninstall ( false ) + , _updatesystem(false) + , _noupdateprovide ( false ) + , _dosplitprovides ( true ) + , _onlyRequires (ZConfig::instance().solver_onlyRequires()) + , _ignorealreadyrecommended(true) + , _distupgrade(false) + , _removeOrphaned(false) + , _removeUnneeded(false) + , _dup_allowdowngrade ( ZConfig::instance().solver_dupAllowDowngrade() ) + , _dup_allownamechange ( ZConfig::instance().solver_dupAllowNameChange() ) + , _dup_allowarchchange ( ZConfig::instance().solver_dupAllowArchChange() ) + , _dup_allowvendorchange ( ZConfig::instance().solver_dupAllowVendorChange() ) + , _solveSrcPackages(false) + , _cleandepsOnRemove(ZConfig::instance().solver_cleandepsOnRemove()) +{ +} + + +SATResolver::~SATResolver() +{ + solverEnd(); +} + +//--------------------------------------------------------------------------- + +ResPool +SATResolver::pool (void) const +{ + return _pool; +} + +//--------------------------------------------------------------------------- + +// copy marked item from solution back to pool +// if data != NULL, set as APPL_LOW (from establishPool()) + +static void +SATSolutionToPool (const PoolItem& item, const ResStatus & status, const ResStatus::TransactByValue causer) +{ + // resetting + item.status().resetTransact (causer); + item.status().resetWeak (); + + bool r = false; + + // installation/deletion + if (status.isToBeInstalled()) { + r = item.status().setToBeInstalled (causer); + XDEBUG("SATSolutionToPool install returns " << item << ", " << r); + } + else if (status.isToBeUninstalledDueToUpgrade()) { + r = item.status().setToBeUninstalledDueToUpgrade (causer); + XDEBUG("SATSolutionToPool upgrade returns " << item << ", " << r); + } + else if (status.isToBeUninstalled()) { + r = item.status().setToBeUninstalled (causer); + XDEBUG("SATSolutionToPool remove returns " << item << ", " << r); + } + + return; +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// solverInit +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +///////////////////////////////////////////////////////////////////////// +/// \class SATCollectTransact +/// \brief Commit helper functor distributing PoolItem by status into lists +/// +/// On the fly it clears all PoolItem bySolver/ByApplLow status. +/// The lists are cleared in the Ctor, populated by \ref operator(). +///////////////////////////////////////////////////////////////////////// +struct SATCollectTransact +{ + SATCollectTransact( PoolItemList & items_to_install_r, + PoolItemList & items_to_remove_r, + PoolItemList & items_to_lock_r, + PoolItemList & items_to_keep_r, + bool solveSrcPackages_r ) + : _items_to_install( items_to_install_r ) + , _items_to_remove( items_to_remove_r ) + , _items_to_lock( items_to_lock_r ) + , _items_to_keep( items_to_keep_r ) + , _solveSrcPackages( solveSrcPackages_r ) + { + _items_to_install.clear(); + _items_to_remove.clear(); + _items_to_lock.clear(); + _items_to_keep.clear(); + } + + bool operator()( const PoolItem & item_r ) + { + + ResStatus & itemStatus( item_r.status() ); + bool by_solver = ( itemStatus.isBySolver() || itemStatus.isByApplLow() ); + + if ( by_solver ) + { + // Clear former solver/establish resultd + itemStatus.resetTransact( ResStatus::APPL_LOW ); + return true; // -> back out here, don't re-queue former results + } + + if ( !_solveSrcPackages && item_r.isKind() ) + { + // Later we may continue on a per source package base. + return true; // dont process this source package. + } + + switch ( itemStatus.getTransactValue() ) + { + case ResStatus::TRANSACT: + itemStatus.isUninstalled() ? _items_to_install.push_back( item_r ) + : _items_to_remove.push_back( item_r ); break; + case ResStatus::LOCKED: _items_to_lock.push_back( item_r ); break; + case ResStatus::KEEP_STATE: _items_to_keep.push_back( item_r ); break; + } + return true; + } + +private: + PoolItemList & _items_to_install; + PoolItemList & _items_to_remove; + PoolItemList & _items_to_lock; + PoolItemList & _items_to_keep; + bool _solveSrcPackages; + +}; +///////////////////////////////////////////////////////////////////////// + +void +SATResolver::solverEnd() +{ + // cleanup + if ( _satSolver ) + { + solver_free(_satSolver); + _satSolver = NULL; + queue_free( &(_jobQueue) ); + } +} + +void +SATResolver::solverInit(const PoolItemList & weakItems) +{ + MIL << "SATResolver::solverInit()" << endl; + + // Remove old stuff and create a new jobqueue + solverEnd(); + _satSolver = solver_create( _satPool ); + queue_init( &_jobQueue ); + + { + // bsc#1182629: in dup allow an available -release package providing 'dup-vendor-relax(suse)' + // to let (suse/opensuse) vendor being treated as being equivalent. + bool toRelax = false; + if ( _distupgrade ) { + for ( sat::Solvable solv : sat::WhatProvides( Capability("dup-vendor-relax(suse)") ) ) { + if ( ! solv.isSystem() ) { + MIL << "Relaxed vendor check requested by " << solv << endl; + toRelax = true; + break; + } + } + } + ::pool_set_custom_vendorcheck( _satPool, toRelax ? &relaxedVendorCheck : &vendorCheck ); + } + + // Add rules for user/auto installed packages + ::pool_add_userinstalled_jobs(_satPool, sat::Pool::instance().autoInstalled(), &(_jobQueue), GET_USERINSTALLED_NAMES|GET_USERINSTALLED_INVERTED); + + // Collect PoolItem's tasks and cleanup Pool for solving. + // Todos are kept in _items_to_install, _items_to_remove, _items_to_lock, _items_to_keep + { + SATCollectTransact collector( _items_to_install, _items_to_remove, _items_to_lock, _items_to_keep, solveSrcPackages() ); + invokeOnEach ( _pool.begin(), _pool.end(), std::ref( collector ) ); + } + + // Add rules for previous ProblemSolutions "break %s by ignoring some of its dependencies" + for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) { + Id id = iter->id(); + if (id == ID_NULL) { + ERR << "Weaken: " << *iter << " not found" << endl; + } + MIL << "Weaken dependencies of " << *iter << endl; + queue_push( &(_jobQueue), SOLVER_WEAKENDEPS | SOLVER_SOLVABLE ); + queue_push( &(_jobQueue), id ); + } + + // Add rules for retracted patches and packages + { + queue_push( &(_jobQueue), SOLVER_BLACKLIST|SOLVER_SOLVABLE_PROVIDES ); + queue_push( &(_jobQueue), sat::Solvable::retractedToken.id() ); + queue_push( &(_jobQueue), SOLVER_BLACKLIST|SOLVER_SOLVABLE_PROVIDES ); + queue_push( &(_jobQueue), sat::Solvable::ptfMasterToken.id() ); + // bsc#1186503: ptfPackageToken should not be blacklisted + } + + // Add rules for changed requestedLocales + { + const auto & trackedLocaleIds( myPool().trackedLocaleIds() ); + + // just track changed locakes + for ( const auto & locale : trackedLocaleIds.added() ) + { + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES ); + queue_push( &(_jobQueue), Capability( ResolverNamespace::language, IdString(locale) ).id() ); + } + + for ( const auto & locale : trackedLocaleIds.removed() ) + { + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | SOLVER_CLEANDEPS ); // needs uncond. SOLVER_CLEANDEPS! + queue_push( &(_jobQueue), Capability( ResolverNamespace::language, IdString(locale) ).id() ); + } + } + + // Add rules for parallel installable resolvables with different versions + for ( const sat::Solvable & solv : myPool().multiversionList() ) + { + queue_push( &(_jobQueue), SOLVER_NOOBSOLETES | SOLVER_SOLVABLE ); + queue_push( &(_jobQueue), solv.id() ); + } + + // Add rules to protect PTF removal without repos (bsc#1203248) + // Removing a PTF its packages should be replaced by the official + // versions again. If just the system repo is present, they'd get + // removed instead. + { + _protectPTFs = sat::Pool::instance().reposSize() == 1; + if ( _protectPTFs ) { + for ( const auto & solv : sat::AllPTFs() ) { + if ( solv.isSystem() ) { + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE ); + queue_push( &(_jobQueue), solv.id() ); + } + } + } + } + + // set requirements for a running system + solverInitSetSystemRequirements(); + + // set locks for the solver + solverInitSetLocks(); + + // set mode (verify,up,dup) specific jobs and solver flags + solverInitSetModeJobsAndFlags(); +} + +void SATResolver::solverInitSetSystemRequirements() +{ + CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap(); + CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap(); + + for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); ++iter) { + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES ); + queue_push( &(_jobQueue), iter->id() ); + MIL << "SYSTEM Requires " << *iter << endl; + } + + for (CapabilitySet::const_iterator iter = system_conflicts.begin(); iter != system_conflicts.end(); ++iter) { + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), iter->id() ); + MIL << "SYSTEM Conflicts " << *iter << endl; + } + + // Lock the architecture of the running systems rpm + // package on distupgrade. + if ( _distupgrade && ZConfig::instance().systemRoot() == "/" ) + { + ResPool pool( ResPool::instance() ); + IdString rpm( "rpm" ); + for_( it, pool.byIdentBegin(rpm), pool.byIdentEnd(rpm) ) + { + if ( (*it)->isSystem() ) + { + Capability archrule( (*it)->arch(), rpm.c_str(), Capability::PARSED ); + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_NAME | SOLVER_ESSENTIAL ); + queue_push( &(_jobQueue), archrule.id() ); + + } + } + } +} + +void SATResolver::solverInitSetLocks() +{ + unsigned icnt = 0; + unsigned acnt = 0; + + for (PoolItemList::const_iterator iter = _items_to_lock.begin(); iter != _items_to_lock.end(); ++iter) { + sat::detail::SolvableIdType id( iter->id() ); + if (iter->status().isInstalled()) { + ++icnt; + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE ); + queue_push( &(_jobQueue), id ); + } else { + ++acnt; + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), id ); + } + } + MIL << "Locked " << icnt << " installed items and " << acnt << " NOT installed items." << endl; + + /////////////////////////////////////////////////////////////////// + // Weak locks: Ignore if an item with this name is already installed. + // If it's not installed try to keep it this way using a weak delete + /////////////////////////////////////////////////////////////////// + std::set unifiedByName; + for (PoolItemList::const_iterator iter = _items_to_keep.begin(); iter != _items_to_keep.end(); ++iter) { + IdString ident( iter->ident() ); + if ( unifiedByName.insert( ident ).second ) + { + if ( ! ui::Selectable::get( *iter )->hasInstalledObj() ) + { + MIL << "Keep NOT installed name " << ident << " (" << *iter << ")" << endl; + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | SOLVER_WEAK | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), ident.id() ); + } + } + } +} + +void SATResolver::solverInitSetModeJobsAndFlags() +{ + if (_fixsystem) { + queue_push( &(_jobQueue), SOLVER_VERIFY|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (_updatesystem) { + queue_push( &(_jobQueue), SOLVER_UPDATE|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + if (_distupgrade) { + queue_push( &(_jobQueue), SOLVER_DISTUPGRADE|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + // By now libsolv supports orphan handling just in dup. + // We keep it here in _distupgrade to make sure nothing bad happens + // in case libsolv changes and it's used in remove commands which + // have no repos enabled. I.e. everything would be orphaned. + if (_removeOrphaned) { + queue_push( &(_jobQueue), SOLVER_DROP_ORPHANED|SOLVER_SOLVABLE_ALL); + queue_push( &(_jobQueue), 0 ); + } + } + if (_removeUnneeded) { + invokeOnEach ( _pool.begin(), _pool.end(), [this]( const PoolItem & pi_r ) { + if ( pi_r.status().isUnneeded() ) { + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | SOLVER_WEAK | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), pi_r.ident().id() ); + } + return true; + } ); + } + + solverSetFocus( *_satSolver, _focus ); + solver_set_flag(_satSolver, SOLVER_FLAG_ADD_ALREADY_RECOMMENDED, !_ignorealreadyrecommended); + solver_set_flag(_satSolver, SOLVER_FLAG_ALLOW_DOWNGRADE, _allowdowngrade); + solver_set_flag(_satSolver, SOLVER_FLAG_ALLOW_NAMECHANGE, _allownamechange); + solver_set_flag(_satSolver, SOLVER_FLAG_ALLOW_ARCHCHANGE, _allowarchchange); + solver_set_flag(_satSolver, SOLVER_FLAG_ALLOW_VENDORCHANGE, _allowvendorchange); + solver_set_flag(_satSolver, SOLVER_FLAG_ALLOW_UNINSTALL, _allowuninstall); + solver_set_flag(_satSolver, SOLVER_FLAG_NO_UPDATEPROVIDE, _noupdateprovide); + solver_set_flag(_satSolver, SOLVER_FLAG_SPLITPROVIDES, _dosplitprovides); + solver_set_flag(_satSolver, SOLVER_FLAG_IGNORE_RECOMMENDED, false); // resolve recommended namespaces + solver_set_flag(_satSolver, SOLVER_FLAG_ONLY_NAMESPACE_RECOMMENDED, _onlyRequires); // + solver_set_flag(_satSolver, SOLVER_FLAG_DUP_ALLOW_DOWNGRADE, _dup_allowdowngrade ); + solver_set_flag(_satSolver, SOLVER_FLAG_DUP_ALLOW_NAMECHANGE, _dup_allownamechange ); + solver_set_flag(_satSolver, SOLVER_FLAG_DUP_ALLOW_ARCHCHANGE, _dup_allowarchchange ); + solver_set_flag(_satSolver, SOLVER_FLAG_DUP_ALLOW_VENDORCHANGE, _dup_allowvendorchange ); +} + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// solving..... +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +class CheckIfUpdate +{ + public: + bool is_updated; + sat::Solvable _installed; + + CheckIfUpdate( const sat::Solvable & installed_r ) + : is_updated( false ) + , _installed( installed_r ) + {} + + // check this item will be updated + + bool operator()( const PoolItem & item ) + { + if ( item.status().isToBeInstalled() ) + { + if ( ! item.multiversionInstall() || sameNVRA( _installed, item ) ) + { + is_updated = true; + return false; + } + } + return true; + } +}; + + +bool +SATResolver::solving(const CapabilitySet & requires_caps, + const CapabilitySet & conflict_caps) +{ + sat::Pool::instance().prepare(); + + // Solve ! + MIL << "Starting solving...." << endl; + MIL << *this; + if ( solver_solve( _satSolver, &(_jobQueue) ) == 0 ) + { + // bsc#1155819: Weakremovers of future product not evaluated. + // Do a 2nd run to cleanup weakremovers() of to be installed + // Produtcs unless removeunsupported is active (cleans up all). + if ( _distupgrade ) + { + if ( _removeOrphaned ) + MIL << "Droplist processing not needed. RemoveUnsupported is On." << endl; + else if ( ! ZConfig::instance().solverUpgradeRemoveDroppedPackages() ) + MIL << "Droplist processing is disabled in ZConfig." << endl; + else + { + bool resolve = false; + MIL << "Checking droplists ..." << endl; + // get Solvables to be installed... + sat::SolvableQueue decisionq; + solver_get_decisionqueue( _satSolver, decisionq ); + for ( sat::detail::IdType id : decisionq ) + { + if ( id < 0 ) + continue; + sat::Solvable slv { (sat::detail::SolvableIdType)id }; + // get product buddies (they carry the weakremover)... + static const Capability productCap { "product()" }; + if ( slv && slv.provides().matches( productCap ) ) + { + CapabilitySet droplist { slv.valuesOfNamespace( "weakremover" ) }; + MIL << "Droplist for " << slv << ": size " << droplist.size() << endl; + if ( !droplist.empty() ) + { + for ( const auto & cap : droplist ) + { + queue_push( &_jobQueue, SOLVER_DROP_ORPHANED | SOLVER_SOLVABLE_NAME ); + queue_push( &_jobQueue, cap.id() ); + } + // PIN product - a safety net to prevent cleanup from changing the decision for this product + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE ); + queue_push( &(_jobQueue), id ); + resolve = true; + } + } + } + if ( resolve ) + solver_solve( _satSolver, &(_jobQueue) ); + } + } + } + MIL << "....Solver end" << endl; + + // copying solution back to zypp pool + //----------------------------------------- + _result_items_to_install.clear(); + _result_items_to_remove.clear(); + + /* solvables to be installed */ + Queue decisionq; + queue_init(&decisionq); + solver_get_decisionqueue(_satSolver, &decisionq); + for ( int i = 0; i < decisionq.count; ++i ) + { + Id p = decisionq.elements[i]; + if ( p < 0 ) + continue; + + sat::Solvable slv { (sat::detail::SolvableIdType)p }; + if ( ! slv || slv.isSystem() ) + continue; + + PoolItem poolItem( slv ); + SATSolutionToPool (poolItem, ResStatus::toBeInstalled, ResStatus::SOLVER); + _result_items_to_install.push_back( poolItem ); + } + queue_free(&decisionq); + + /* solvables to be erased */ + Repository systemRepo( sat::Pool::instance().findSystemRepo() ); // don't create if it does not exist + if ( systemRepo && ! systemRepo.solvablesEmpty() ) + { + bool mustCheckObsoletes = false; + for_( it, systemRepo.solvablesBegin(), systemRepo.solvablesEnd() ) + { + if (solver_get_decisionlevel(_satSolver, it->id()) > 0) + continue; + + // Check if this is an update + CheckIfUpdate info( *it ); + PoolItem poolItem( *it ); + invokeOnEach( _pool.byIdentBegin( poolItem ), + _pool.byIdentEnd( poolItem ), + resfilter::ByUninstalled(), // ByUninstalled + std::ref(info) ); + + if (info.is_updated) { + SATSolutionToPool( poolItem, ResStatus::toBeUninstalledDueToUpgrade, ResStatus::SOLVER ); + } else { + SATSolutionToPool( poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER ); + if ( ! mustCheckObsoletes ) + mustCheckObsoletes = true; // lazy check for UninstalledDueToObsolete + } + _result_items_to_remove.push_back (poolItem); + } + if ( mustCheckObsoletes ) + { + sat::WhatObsoletes obsoleted( _result_items_to_install.begin(), _result_items_to_install.end() ); + for_( it, obsoleted.poolItemBegin(), obsoleted.poolItemEnd() ) + { + ResStatus & status( it->status() ); + // WhatObsoletes contains installed items only! + if ( status.transacts() && ! status.isToBeUninstalledDueToUpgrade() ) + status.setToBeUninstalledDueToObsolete(); + } + } + } + + // copy back computed status values to pool + // (on the fly cache orphaned items for the UI) + solverCopyBackWeak( *_satSolver, _problem_items ); + solverCopyBackValidate( *_satSolver, _pool ); + + // Solvables which were selected due requirements which have been made by the user will + // be selected by APPL_LOW. We can't use any higher level, because this setting must + // not serve as a request for the next solver run. APPL_LOW is reset before solving. + for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) { + sat::WhatProvides rpmProviders(*iter); + for_( iter2, rpmProviders.begin(), rpmProviders.end() ) { + PoolItem poolItem(*iter2); + if (poolItem.status().isToBeInstalled()) { + MIL << "User requirement " << *iter << " sets " << poolItem << endl; + poolItem.status().setTransactByValue (ResStatus::APPL_LOW); + } + } + } + for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) { + sat::WhatProvides rpmProviders(*iter); + for_( iter2, rpmProviders.begin(), rpmProviders.end() ) { + PoolItem poolItem(*iter2); + if (poolItem.status().isToBeUninstalled()) { + MIL << "User conflict " << *iter << " sets " << poolItem << endl; + poolItem.status().setTransactByValue (ResStatus::APPL_LOW); + } + } + } + + if (solver_problem_count(_satSolver) > 0 ) + { + ERR << "Solverrun finished with an ERROR" << endl; + return false; + } + + return true; +} + +void SATResolver::solverAddJobsFromPool() +{ + for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) { + Id id = iter->id(); + if (id == ID_NULL) { + ERR << "Install: " << *iter << " not found" << endl; + } else { + MIL << "Install " << *iter << endl; + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE ); + queue_push( &(_jobQueue), id ); + } + } + + for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) { + Id id = iter->id(); + if (id == ID_NULL) { + ERR << "Delete: " << *iter << " not found" << endl; + } else { + MIL << "Delete " << *iter << endl; + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), id); + } + } +} + +void SATResolver::solverAddJobsFromExtraQueues( const CapabilitySet & requires_caps, const CapabilitySet & conflict_caps ) +{ + for (CapabilitySet::const_iterator iter = requires_caps.begin(); iter != requires_caps.end(); iter++) { + queue_push( &(_jobQueue), SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES ); + queue_push( &(_jobQueue), iter->id() ); + MIL << "Requires " << *iter << endl; + } + + for (CapabilitySet::const_iterator iter = conflict_caps.begin(); iter != conflict_caps.end(); iter++) { + queue_push( &(_jobQueue), SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES | MAYBE_CLEANDEPS ); + queue_push( &(_jobQueue), iter->id() ); + MIL << "Conflicts " << *iter << endl; + } +} + +bool +SATResolver::resolvePool(const CapabilitySet & requires_caps, + const CapabilitySet & conflict_caps, + const PoolItemList & weakItems, + const std::set & upgradeRepos) +{ + MIL << "SATResolver::resolvePool()" << endl; + + // Initialize + solverInit(weakItems); + + // Add pool and extra jobs. + solverAddJobsFromPool(); + solverAddJobsFromExtraQueues( requires_caps, conflict_caps ); + // 'dup --from' jobs + for_( iter, upgradeRepos.begin(), upgradeRepos.end() ) + { + queue_push( &(_jobQueue), SOLVER_DISTUPGRADE | SOLVER_SOLVABLE_REPO ); + queue_push( &(_jobQueue), iter->get()->repoid ); + MIL << "Upgrade repo " << *iter << endl; + } + + // Solve! + bool ret = solving(requires_caps, conflict_caps); + + (ret?MIL:WAR) << "SATResolver::resolvePool() done. Ret:" << ret << endl; + return ret; +} + + +bool +SATResolver::resolveQueue(const SolverQueueItemList &requestQueue, + const PoolItemList & weakItems) +{ + MIL << "SATResolver::resolvQueue()" << endl; + + // Initialize + solverInit(weakItems); + + // Add request queue's jobs. + for (SolverQueueItemList::const_iterator iter = requestQueue.begin(); iter != requestQueue.end(); iter++) { + (*iter)->addRule(_jobQueue); + } + + // Add pool jobs; they do contain any problem resolutions. + solverAddJobsFromPool(); + + // Solve! + bool ret = solving(); + + (ret?MIL:WAR) << "SATResolver::resolveQueue() done. Ret:" << ret << endl; + return ret; +} + + +void SATResolver::doUpdate() +{ + MIL << "SATResolver::doUpdate()" << endl; + + // Initialize + solverInit(PoolItemList()); + + // By now, doUpdate has no additional jobs. + // It does not include any pool jobs, and so it does not create an conflicts. + // Combinations like patch_with_update are driven by resolvePool + _updatesystem. + + // TODO: Try to join the following with solving() + sat::Pool::instance().prepare(); + + // Solve! + MIL << "Starting solving for update...." << endl; + MIL << *this; + solver_solve( _satSolver, &(_jobQueue) ); + MIL << "....Solver end" << endl; + + // copying solution back to zypp pool + //----------------------------------------- + + /* solvables to be installed */ + Queue decisionq; + queue_init(&decisionq); + solver_get_decisionqueue(_satSolver, &decisionq); + for (int i = 0; i < decisionq.count; i++) + { + Id p = decisionq.elements[i]; + if ( p < 0 ) + continue; + + sat::Solvable solv { (sat::detail::SolvableIdType)p }; + if ( ! solv || solv.isSystem() ) + continue; + + SATSolutionToPool( PoolItem(solv), ResStatus::toBeInstalled, ResStatus::SOLVER ); + } + queue_free(&decisionq); + + /* solvables to be erased */ + if ( _satSolver->pool->installed ) { + for (int i = _satSolver->pool->installed->start; i < _satSolver->pool->installed->start + _satSolver->pool->installed->nsolvables; i++) + { + if (solver_get_decisionlevel(_satSolver, i) > 0) + continue; + + PoolItem poolItem( _pool.find( sat::Solvable(i) ) ); + if (poolItem) { + // Check if this is an update + CheckIfUpdate info( (sat::Solvable(i)) ); + invokeOnEach( _pool.byIdentBegin( poolItem ), + _pool.byIdentEnd( poolItem ), + resfilter::ByUninstalled(), // ByUninstalled + std::ref(info) ); + + if (info.is_updated) { + SATSolutionToPool (poolItem, ResStatus::toBeUninstalledDueToUpgrade , ResStatus::SOLVER); + } else { + SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER); + } + } else { + ERR << "id " << i << " not found in ZYPP pool." << endl; + } + } + } + + // copy back computed status values to pool + // (on the fly cache orphaned items for the UI) + solverCopyBackWeak( *_satSolver, _problem_items ); + solverCopyBackValidate( *_satSolver, _pool ); + + MIL << "SATResolver::doUpdate() done" << endl; +} + + + +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- +// error handling +//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- + +//---------------------------------------------------------------------------- +// helper function +//---------------------------------------------------------------------------- + +struct FindPackage +{ + ProblemSolutionCombi *problemSolution; + TransactionKind action; + FindPackage (ProblemSolutionCombi *p, const TransactionKind act) + : problemSolution (p) + , action (act) + { + } + + bool operator()( const PoolItem& p) + { + problemSolution->addSingleAction (p, action); + return true; + } +}; + + +//---------------------------------------------------------------------------- +// Checking if this solvable/item has a buddy which reflect the real +// user visible description of an item +// e.g. The release package has a buddy to the concerning product item. +// This user want's the message "Product foo conflicts with product bar" and +// NOT "package release-foo conflicts with package release-bar" +// (ma: that's why we should map just packages to buddies, not vice versa) +//---------------------------------------------------------------------------- +inline sat::Solvable mapBuddy( const PoolItem & item_r ) +{ + if ( item_r.isKind() ) + { + sat::Solvable buddy = item_r.buddy(); + if ( buddy ) + return buddy; + } + return item_r.satSolvable(); +} +inline sat::Solvable mapBuddy( sat::Solvable item_r ) +{ return mapBuddy( PoolItem( item_r ) ); } + +PoolItem SATResolver::mapItem ( const PoolItem & item ) +{ return PoolItem( mapBuddy( item ) ); } + +sat::Solvable SATResolver::mapSolvable ( const Id & id ) +{ return mapBuddy( sat::Solvable(id) ); } + +std::vector SATResolver::SATgetCompleteProblemInfoStrings ( Id problem ) +{ + std::vector ret; + sat::Queue problems; + solver_findallproblemrules( _satSolver, problem, problems ); + + bool nobad = false; + + //filter out generic rule information if more explicit ones are available + for ( sat::Queue::size_type i = 0; i < problems.size(); i++ ) { + SolverRuleinfo ruleClass = solver_ruleclass( _satSolver, problems[i]); + if ( ruleClass != SolverRuleinfo::SOLVER_RULE_UPDATE && ruleClass != SolverRuleinfo::SOLVER_RULE_JOB ) { + nobad = true; + break; + } + } + for ( sat::Queue::size_type i = 0; i < problems.size(); i++ ) { + SolverRuleinfo ruleClass = solver_ruleclass( _satSolver, problems[i]); + if ( nobad && ( ruleClass == SolverRuleinfo::SOLVER_RULE_UPDATE || ruleClass == SolverRuleinfo::SOLVER_RULE_JOB ) ) { + continue; + } + + std::string detail; + Id ignore = 0; + std::string pInfo = SATproblemRuleInfoString( problems[i], detail, ignore ); + + //we get the same string multiple times, reduce the noise + if ( std::find( ret.begin(), ret.end(), pInfo ) == ret.end() ) + ret.push_back( pInfo ); + } + return ret; +} + +std::string SATResolver::SATprobleminfoString(Id problem, std::string &detail, Id &ignoreId) +{ + // FIXME: solver_findallproblemrules to get all rules for this problem + // (the 'most relevabt' one returned by solver_findproblemrule is embedded + Id probr = solver_findproblemrule(_satSolver, problem); + return SATproblemRuleInfoString( probr, detail, ignoreId ); +} + +std::string SATResolver::SATproblemRuleInfoString (Id probr, std::string &detail, Id &ignoreId) +{ + std::string ret; + sat::detail::CPool *pool = _satSolver->pool; + Id dep = 0, source = 0, target = 0; + SolverRuleinfo type = solver_ruleinfo(_satSolver, probr, &source, &target, &dep); + + ignoreId = 0; + + sat::Solvable s = mapSolvable( source ); + sat::Solvable s2 = mapSolvable( target ); + + // @FIXME, these strings are a duplicate copied from the libsolv library + // to provide translations. Instead of having duplicate code we should + // translate those strings directly in libsolv + switch ( type ) + { + case SOLVER_RULE_DISTUPGRADE: + if ( s.isSystem() ) + ret = str::Format(_("the installed %1% does not belong to a distupgrade repository and must be replaced") ) % s.asString(); + else /*just in case*/ + ret = str::Format(_("the to be installed %1% does not belong to a distupgrade repository") ) % s.asString(); + break; + case SOLVER_RULE_INFARCH: + if ( s.isSystem() ) + ret = str::Format(_("the installed %1% has inferior architecture") ) % s.asString(); + else + ret = str::Format(_("the to be installed %1% has inferior architecture") ) % s.asString(); + break; + case SOLVER_RULE_UPDATE: + ret = str::Format(_("problem with the installed %1%") ) % s.asString(); + break; + case SOLVER_RULE_JOB: + ret = _("conflicting requests"); + break; + case SOLVER_RULE_PKG: + ret = _("some dependency problem"); + break; + case SOLVER_RULE_JOB_NOTHING_PROVIDES_DEP: + ret = str::Format(_("nothing provides the requested '%1%'") ) % pool_dep2str(pool, dep); + detail += _("Have you enabled all the required repositories?"); + break; + case SOLVER_RULE_JOB_UNKNOWN_PACKAGE: + ret = str::Format(_("the requested package %1% does not exist") ) % pool_dep2str(pool, dep); + detail += _("Have you enabled all the required repositories?"); + break; + case SOLVER_RULE_JOB_UNSUPPORTED: + ret = _("unsupported request"); + break; + case SOLVER_RULE_JOB_PROVIDED_BY_SYSTEM: + ret = str::Format(_("'%1%' is provided by the system and cannot be erased") ) % pool_dep2str(pool, dep); + break; + case SOLVER_RULE_PKG_NOT_INSTALLABLE: + ret = str::Format(_("%1% is not installable") ) % s.asString(); + break; + case SOLVER_RULE_PKG_NOTHING_PROVIDES_DEP: + ignoreId = source; // for setting weak dependencies + if ( s.isSystem() ) + ret = str::Format(_("nothing provides '%1%' needed by the installed %2%") ) % pool_dep2str(pool, dep) % s.asString(); + else + ret = str::Format(_("nothing provides '%1%' needed by the to be installed %2%") ) % pool_dep2str(pool, dep) % s.asString(); + break; + case SOLVER_RULE_PKG_SAME_NAME: + ret = str::Format(_("cannot install both %1% and %2%") ) % s.asString() % s2.asString(); + break; + case SOLVER_RULE_PKG_CONFLICTS: + if ( s.isSystem() ) { + if ( s2.isSystem() ) + ret = str::Format(_("the installed %1% conflicts with '%2%' provided by the installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + else + ret = str::Format(_("the installed %1% conflicts with '%2%' provided by the to be installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + } + else { + if ( s2.isSystem() ) + ret = str::Format(_("the to be installed %1% conflicts with '%2%' provided by the installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + else + ret = str::Format(_("the to be installed %1% conflicts with '%2%' provided by the to be installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + } + break; + case SOLVER_RULE_PKG_OBSOLETES: + case SOLVER_RULE_PKG_INSTALLED_OBSOLETES: + if ( s.isSystem() ) { + if ( s2.isSystem() ) + ret = str::Format(_("the installed %1% obsoletes '%2%' provided by the installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + else + ret = str::Format(_("the installed %1% obsoletes '%2%' provided by the to be installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + } + else { + if ( s2.isSystem() ) + ret = str::Format(_("the to be installed %1% obsoletes '%2%' provided by the installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + else + ret = str::Format(_("the to be installed %1% obsoletes '%2%' provided by the to be installed %3%") ) % s.asString() % pool_dep2str(pool, dep) % s2.asString(); + } + break; + case SOLVER_RULE_PKG_SELF_CONFLICT: + if ( s.isSystem() ) + ret = str::Format(_("the installed %1% conflicts with '%2%' provided by itself") ) % s.asString() % pool_dep2str(pool, dep); + else + ret = str::Format(_("the to be installed %1% conflicts with '%2%' provided by itself") ) % s.asString() % pool_dep2str(pool, dep); + break; + case SOLVER_RULE_PKG_REQUIRES: { + ignoreId = source; // for setting weak dependencies + Capability cap(dep); + sat::WhatProvides possibleProviders(cap); + + // check, if a provider will be deleted + typedef std::list ProviderList; + ProviderList providerlistInstalled, providerlistUninstalled; + for_( iter1, possibleProviders.begin(), possibleProviders.end() ) { + PoolItem provider1 = ResPool::instance().find( *iter1 ); + // find pair of an installed/uninstalled item with the same NVR + bool found = false; + for_( iter2, possibleProviders.begin(), possibleProviders.end() ) { + PoolItem provider2 = ResPool::instance().find( *iter2 ); + if (compareByNVR (provider1,provider2) == 0 + && ( (provider1.status().isInstalled() && provider2.status().isUninstalled()) + || (provider2.status().isInstalled() && provider1.status().isUninstalled()) )) { + found = true; + break; + } + } + if (!found) { + if (provider1.status().isInstalled()) + providerlistInstalled.push_back(provider1); + else + providerlistUninstalled.push_back(provider1); + } + } + + if ( s.isSystem() ) + ret = str::Format(_("the installed %1% requires '%2%', but this requirement cannot be provided") ) % s.asString() % pool_dep2str(pool, dep); + else + ret = str::Format(_("the to be installed %1% requires '%2%', but this requirement cannot be provided") ) % s.asString() % pool_dep2str(pool, dep); + if (providerlistInstalled.size() > 0) { + detail += _("deleted providers: "); + for (ProviderList::const_iterator iter = providerlistInstalled.begin(); iter != providerlistInstalled.end(); iter++) { + if (iter == providerlistInstalled.begin()) + detail += itemToString( *iter ); + else + detail += "\n " + itemToString( mapItem(*iter) ); + } + } + if (providerlistUninstalled.size() > 0) { + if (detail.size() > 0) + detail += _("\nnot installable providers: "); + else + detail = _("not installable providers: "); + for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) { + if (iter == providerlistUninstalled.begin()) + detail += itemToString( *iter ); + else + detail += "\n " + itemToString( mapItem(*iter) ); + } + } + break; + } + default: { + DBG << "Unknown rule type(" << type << ") going to query libsolv for rule information." << endl; + ret = str::asString( ::solver_problemruleinfo2str( _satSolver, type, static_cast(s.id()), static_cast(s2.id()), dep ) ); + break; + } + } + return ret; +} + +///////////////////////////////////////////////////////////////////////// +namespace { + /// bsc#1194848 hint on ptf<>patch conflicts or common ptf conflicts + struct PtfPatchHint + { + void notInstallPatch( sat::Solvable slv_r ) + { _patch.push_back( slv_r.ident() ); } + + void removePtf( sat::Solvable slv_r, bool showremoveProtectHint_r = false ) + { _ptf.push_back( slv_r.ident() ); if ( showremoveProtectHint_r ) _showremoveProtectHint = true; } + + bool applies() const + { return not _ptf.empty(); } + + std::string description() const { + if ( not _patch.empty() ) { + return str::Str() + // translator: %1% is the name of a PTF, %2% the name of a patch. + << (str::Format( _("%1% is not yet fully integrated into %2%.") ) % printlist(_ptf) % printlist(_patch)) << endl + << _("Typically you want to keep the PTF and choose to not install the maintenance patches."); + } + //else: a common problem due to an installed ptf + + if ( _showremoveProtectHint ) { // bsc#1203248 + const std::string & removeptfCommand { str::Format("zypper removeptf %1%") % printlist(_ptf) }; + return str::Str() + // translator: %1% is the name of a PTF. + << (str::Format( _("Removing the installed %1% in this context will remove (not replace!) the included PTF-packages too." ) ) % printlist(_ptf)) << endl + << (str::Format( _("The PTF should be removed by calling '%1%'. This will update the included PTF-packages rather than removing them." ) ) % removeptfCommand) << endl + << _("Typically you want to keep the PTF or choose to cancel the action."); // ma: When translated, it should replace the '..and choose..' below too + } + + return str::Str() + // translator: %1% is the name of a PTF. + << (str::Format( _("The installed %1% blocks the desired action.") ) % printlist(_ptf)) << endl + << _("Typically you want to keep the PTF and choose to cancel the action."); + } + private: + using StoreType = IdString; + static std::string printlist( const std::vector & list_r ) + { str::Str ret; dumpRange( ret.stream(), list_r.begin(), list_r.end(), "", "", ", ", "", "" ); return ret; } + + std::vector _ptf; + std::vector _patch; + bool _showremoveProtectHint = false; + }; +} +///////////////////////////////////////////////////////////////////////// + +ResolverProblemList +SATResolver::problems () +{ + ResolverProblemList resolverProblems; + if (_satSolver && solver_problem_count(_satSolver)) { + sat::detail::CPool *pool = _satSolver->pool; + int pcnt = 0; + Id p = 0, rp = 0, what = 0; + Id problem = 0, solution = 0, element = 0; + sat::Solvable s, sd; + + CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap(); + CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap(); + + MIL << "Encountered problems! Here are the solutions:\n" << endl; + pcnt = 1; + problem = 0; + while ((problem = solver_next_problem(_satSolver, problem)) != 0) { + MIL << "Problem " << pcnt++ << ":" << endl; + MIL << "====================================" << endl; + std::string detail; + Id ignoreId = 0; + std::string whatString = SATprobleminfoString (problem,detail,ignoreId); + MIL << whatString << endl; + MIL << "------------------------------------" << endl; + ResolverProblem_Ptr resolverProblem = new ResolverProblem (whatString, detail, SATgetCompleteProblemInfoStrings( problem )); + PtfPatchHint ptfPatchHint; // bsc#1194848 hint on ptf<>patch conflicts + solution = 0; + while ((solution = solver_next_solution(_satSolver, problem, solution)) != 0) { + element = 0; + ProblemSolutionCombi *problemSolution = new ProblemSolutionCombi; + while ((element = solver_next_solutionelement(_satSolver, problem, solution, element, &p, &rp)) != 0) { + if (p == SOLVER_SOLUTION_JOB) { + /* job, rp is index into job queue */ + what = _jobQueue.elements[rp]; + switch (_jobQueue.elements[rp-1]&(SOLVER_SELECTMASK|SOLVER_JOBMASK)) + { + case SOLVER_INSTALL | SOLVER_SOLVABLE: { + s = mapSolvable (what); + PoolItem poolItem = _pool.find (s); + if (poolItem) { + if (pool->installed && s.get()->repo == pool->installed) { + problemSolution->addSingleAction (poolItem, REMOVE); + std::string description = str::Format(_("remove lock to allow removal of %1%") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + if ( _protectPTFs && s.isPtfMaster() ) + ptfPatchHint.removePtf( s, _protectPTFs ); // bsc#1203248 + } else { + problemSolution->addSingleAction (poolItem, KEEP); + std::string description = str::Format(_("do not install %1%") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + if ( s.isKind() ) + ptfPatchHint.notInstallPatch( s ); + } + } else { + ERR << "SOLVER_INSTALL_SOLVABLE: No item found for " << s.asString() << endl; + } + } + break; + case SOLVER_ERASE | SOLVER_SOLVABLE: { + s = mapSolvable (what); + PoolItem poolItem = _pool.find (s); + if (poolItem) { + if (pool->installed && s.get()->repo == pool->installed) { + problemSolution->addSingleAction (poolItem, KEEP); + std::string description = str::Format(_("keep %1%") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + } else { + problemSolution->addSingleAction (poolItem, UNLOCK); + std::string description = str::Format(_("remove lock to allow installation of %1%") ) % itemToString( poolItem ); + MIL << description << endl; + problemSolution->addDescription (description); + } + } else { + ERR << "SOLVER_ERASE_SOLVABLE: No item found for " << s.asString() << endl; + } + } + break; + case SOLVER_INSTALL | SOLVER_SOLVABLE_NAME: + { + IdString ident( what ); + SolverQueueItemInstall_Ptr install = + new SolverQueueItemInstall(_pool, ident.asString(), false ); + problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM); + + std::string description = str::Format(_("do not install %1%") ) % ident; + MIL << description << endl; + problemSolution->addDescription (description); + } + break; + case SOLVER_ERASE | SOLVER_SOLVABLE_NAME: + { + // As we do not know, if this request has come from resolvePool or + // resolveQueue we will have to take care for both cases. + IdString ident( what ); + FindPackage info (problemSolution, KEEP); + invokeOnEach( _pool.byIdentBegin( ident ), + _pool.byIdentEnd( ident ), + functor::chain (resfilter::ByInstalled (), // ByInstalled + resfilter::ByTransact ()), // will be deinstalled + std::ref(info) ); + + SolverQueueItemDelete_Ptr del = + new SolverQueueItemDelete(_pool, ident.asString(), false ); + problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM); + + std::string description = str::Format(_("keep %1%") ) % ident; + MIL << description << endl; + problemSolution->addDescription (description); + } + break; + case SOLVER_INSTALL | SOLVER_SOLVABLE_PROVIDES: + { + problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_REQUIRE); + std::string description = ""; + + // Checking if this problem solution would break your system + if (system_requires.find(Capability(what)) != system_requires.end()) { + // Show a better warning + resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() ); + resolverProblem->setDescription(_("This request will break your system!")); + description = _("ignore the warning of a broken system"); + description += std::string(" (requires:")+pool_dep2str(pool, what)+")"; + MIL << description << endl; + problemSolution->addFrontDescription (description); + } else { + description = str::Format(_("do not ask to install a solvable providing %1%") ) % pool_dep2str(pool, what); + MIL << description << endl; + problemSolution->addDescription (description); + } + } + break; + case SOLVER_ERASE | SOLVER_SOLVABLE_PROVIDES: + { + problemSolution->addSingleAction (Capability(what), REMOVE_EXTRA_CONFLICT); + std::string description = ""; + + // Checking if this problem solution would break your system + if (system_conflicts.find(Capability(what)) != system_conflicts.end()) { + // Show a better warning + resolverProblem->setDetails( resolverProblem->description() + "\n" + resolverProblem->details() ); + resolverProblem->setDescription(_("This request will break your system!")); + description = _("ignore the warning of a broken system"); + description += std::string(" (conflicts:")+pool_dep2str(pool, what)+")"; + MIL << description << endl; + problemSolution->addFrontDescription (description); + + } else { + description = str::Format(_("do not ask to delete all solvables providing %1%") ) % pool_dep2str(pool, what); + MIL << description << endl; + problemSolution->addDescription (description); + } + } + break; + case SOLVER_UPDATE | SOLVER_SOLVABLE: + { + s = mapSolvable (what); + PoolItem poolItem = _pool.find (s); + if (poolItem) { + if (pool->installed && s.get()->repo == pool->installed) { + problemSolution->addSingleAction (poolItem, KEEP); + std::string description = str::Format(_("do not install most recent version of %1%") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + } else { + ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE " << poolItem << " is not selected for installation" << endl; + } + } else { + ERR << "SOLVER_INSTALL_SOLVABLE_UPDATE: No item found for " << s.asString() << endl; + } + } + break; + default: + MIL << "- do something different" << endl; + ERR << "No valid solution available" << endl; + break; + } + } else if (p == SOLVER_SOLUTION_INFARCH) { + s = mapSolvable (rp); + PoolItem poolItem = _pool.find (s); + if (pool->installed && s.get()->repo == pool->installed) { + problemSolution->addSingleAction (poolItem, LOCK); + std::string description = str::Format(_("keep %1% despite the inferior architecture") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + } else { + problemSolution->addSingleAction (poolItem, INSTALL); + std::string description = str::Format(_("install %1% despite the inferior architecture") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + } + } else if (p == SOLVER_SOLUTION_DISTUPGRADE) { + s = mapSolvable (rp); + PoolItem poolItem = _pool.find (s); + if (pool->installed && s.get()->repo == pool->installed) { + problemSolution->addSingleAction (poolItem, LOCK); + std::string description = str::Format(_("keep obsolete %1%") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + } else { + problemSolution->addSingleAction (poolItem, INSTALL); + std::string description = str::Format(_("install %1% from excluded repository") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + } + } else if ( p == SOLVER_SOLUTION_BLACK ) { + // Allow to install a blacklisted package (PTF, retracted,...). + // For not-installed items only + s = mapSolvable (rp); + PoolItem poolItem = _pool.find (s); + + problemSolution->addSingleAction (poolItem, INSTALL); + std::string description; + if ( s.isRetracted() ) { + // translator: %1% is a package name + description = str::Format(_("install %1% although it has been retracted")) % s.asString(); + } else if ( s.isPtf() ) { + // translator: %1% is a package name + description = str::Format(_("allow installing the PTF %1%")) % s.asString(); + } else { + // translator: %1% is a package name + description = str::Format(_("install %1% although it is blacklisted")) % s.asString(); + } + MIL << description << endl; + problemSolution->addDescription( description ); + } else if ( p > 0 ) { + /* policy, replace p with rp */ + s = mapSolvable (p); + PoolItem itemFrom = _pool.find (s); + if (rp) + { + int gotone = 0; + + sd = mapSolvable (rp); + PoolItem itemTo = _pool.find (sd); + if (itemFrom && itemTo) { + problemSolution->addSingleAction (itemTo, INSTALL); + int illegal = policy_is_illegal(_satSolver, s.get(), sd.get(), 0); + + if ((illegal & POLICY_ILLEGAL_DOWNGRADE) != 0) + { + std::string description = str::Format(_("downgrade of %1% to %2%") ) % s.asString() % sd.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + gotone = 1; + } + if ((illegal & POLICY_ILLEGAL_ARCHCHANGE) != 0) + { + std::string description = str::Format(_("architecture change of %1% to %2%") ) % s.asString() % sd.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + gotone = 1; + } + if ((illegal & POLICY_ILLEGAL_VENDORCHANGE) != 0) + { + IdString s_vendor( s.vendor() ); + IdString sd_vendor( sd.vendor() ); + std::string description; + if ( s == sd ) // FIXME? Actually .ident() must be eq. But the more verbose 'else' isn't bad either. + description = str::Format(_("install %1% (with vendor change)\n %2% --> %3%") ) + % sd.asString() + % ( s_vendor ? s_vendor.c_str() : " (no vendor) " ) + % ( sd_vendor ? sd_vendor.c_str() : " (no vendor) " ); + else + description = str::Format(_("install %1% from vendor %2%\n replacing %3% from vendor %4%") ) + % sd.asString() % ( sd_vendor ? sd_vendor.c_str() : " (no vendor) " ) + % s.asString() % ( s_vendor ? s_vendor.c_str() : " (no vendor) " ); + + MIL << description << endl; + problemSolution->addDescription (description); + gotone = 1; + } + if (!gotone) { + std::string description = str::Format(_("replacement of %1% with %2%") ) % s.asString() % sd.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + } + } else { + ERR << s.asString() << " or " << sd.asString() << " not found" << endl; + } + } + else + { + if (itemFrom) { + std::string description = str::Format(_("deinstallation of %1%") ) % s.asString(); + MIL << description << endl; + problemSolution->addDescription (description); + problemSolution->addSingleAction (itemFrom, REMOVE); + if ( s.isPtfMaster() ) + ptfPatchHint.removePtf( s ); + } + } + } + else + { + INT << "Unknown solution " << p << endl; + } + + } + resolverProblem->addSolution (problemSolution, + problemSolution->actionCount() > 1 ? true : false); // Solutions with more than 1 action will be shown first. + MIL << "------------------------------------" << endl; + } + + if (ignoreId > 0) { + // There is a possibility to ignore this error by setting weak dependencies + PoolItem item = _pool.find (sat::Solvable(ignoreId)); + ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(item); + resolverProblem->addSolution (problemSolution, + false); // Solutions will be shown at the end + MIL << "ignore some dependencies of " << item << endl; + MIL << "------------------------------------" << endl; + } + + // bsc#1194848 hint on ptf<>patch conflicts + if ( ptfPatchHint.applies() ) { + resolverProblem->setDescription( str::Str() << ptfPatchHint.description() << endl << "(" << resolverProblem->description() << ")" ); + } + // save problem + resolverProblems.push_back (resolverProblem); + } + } + return resolverProblems; +} + +void SATResolver::applySolutions( const ProblemSolutionList & solutions ) +{ Resolver( _pool ).applySolutions( solutions ); } + +sat::StringQueue SATResolver::autoInstalled() const +{ + sat::StringQueue ret; + if ( _satSolver ) + ::solver_get_userinstalled( _satSolver, ret, GET_USERINSTALLED_NAMES|GET_USERINSTALLED_INVERTED ); + return ret; +} + +sat::StringQueue SATResolver::userInstalled() const +{ + sat::StringQueue ret; + if ( _satSolver ) + ::solver_get_userinstalled( _satSolver, ret, GET_USERINSTALLED_NAMES ); + return ret; +} + + +/////////////////////////////////////////////////////////////////// +};// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SATResolver.h b/zypp/solver/detail/SATResolver.h new file mode 100644 index 0000000..fdaf6dd --- /dev/null +++ b/zypp/solver/detail/SATResolver.h @@ -0,0 +1,240 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SATResolver.h + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H +#define ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else +extern "C" +{ +#include +#include +} + +#include +#include +#include +#include + +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + + namespace sat + { + class Transaction; + } + + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : SATResolver +/** + * \todo The way solver options are passed as individual booleans from Resolver + * via solver::detail::Resolver to SATResolver is pedestrian and error prone. + * Introdce a dedicated solver option structure which is passed down as a whole. +*/ +class SATResolver : public base::ReferenceCounted, private base::NonCopyable, private sat::detail::PoolMember +{ + + private: + ResPool _pool; + sat::detail::CPool *_satPool; + sat::detail::CSolver *_satSolver; + sat::detail::CQueue _jobQueue; + + // list of problematic items (orphaned) + PoolItemList _problem_items; + + // list populated by calls to addPoolItemTo*() + PoolItemList _items_to_install; + PoolItemList _items_to_remove; + PoolItemList _items_to_lock; + PoolItemList _items_to_keep; + + // solve results + PoolItemList _result_items_to_install; + PoolItemList _result_items_to_remove; + + public: + ResolverFocus _focus; // The resolver's general attitude + + bool _fixsystem:1; // repair errors in rpm dependency graph + bool _allowdowngrade:1; // allow one to downgrade installed solvable + bool _allownamechange:1; // allow one to change name of installed solvable + bool _allowarchchange:1; // allow one to change architecture of installed solvables + bool _allowvendorchange:1; // allow one to change vendor of installed solvables + bool _allowuninstall:1; // allow removal of installed solvables + bool _updatesystem:1; // update + bool _noupdateprovide:1; // true: update packages needs not to provide old package + bool _dosplitprovides:1; // true: consider legacy split provides + bool _onlyRequires:1; // true: consider required packages only (but recommended namespaces) + bool _ignorealreadyrecommended:1; // true: ignore recommended packages that were already recommended by the installed packages + bool _distupgrade:1; + bool _removeOrphaned:1; + bool _removeUnneeded:1; + bool _dup_allowdowngrade:1; // dup mode: allow one to downgrade installed solvable + bool _dup_allownamechange:1; // dup mode: allow one to change name of installed solvable + bool _dup_allowarchchange:1; // dup mode: allow one to change architecture of installed solvables + bool _dup_allowvendorchange:1; // dup mode: allow one to change vendor of installed solvables + bool _solveSrcPackages:1; // false: generate no job rule for source packages selected in the pool + bool _cleandepsOnRemove:1; // whether removing a package should also remove no longer needed requirements + + private: + bool _protectPTFs:1; // protect from accidental removal of PTFs if only @System is present (bsc#1203248) + + // ---------------------------------- methods + std::string SATprobleminfoString (Id problem, std::string &detail, Id &ignoreId); + std::string SATproblemRuleInfoString (Id rule, std::string &detail, Id &ignoreId); + std::vector SATgetCompleteProblemInfoStrings ( Id problem ); + void resetItemTransaction (PoolItem item); + + // Create a SAT solver and + void solverInit(const PoolItemList & weakItems); + void solverInitSetLocks(); + void solverInitSetSystemRequirements(); + void solverInitSetModeJobsAndFlags(); + + void solverAddJobsFromPool(); + void solverAddJobsFromExtraQueues( const CapabilitySet & requires_caps, const CapabilitySet & conflict_caps ); + + // common solver run with the _jobQueue; Save results back to pool + bool solving(const CapabilitySet & requires_caps = CapabilitySet(), + const CapabilitySet & conflict_caps = CapabilitySet()); + // cleanup solver + void solverEnd(); + + // Checking if this solvable/item has a buddy which reflect the real + // user visible description of an item + // e.g. The release package has a buddy to the concerning product item. + // This user want's the message "Product foo conflicts with product bar" and + // NOT "package release-foo conflicts with package release-bar" + // So these functions return the concerning buddy (e.g. product item) + sat::Solvable mapSolvable (const Id &id); + PoolItem mapItem (const PoolItem &item); + + public: + + SATResolver (ResPool pool, sat::detail::CPool *satPool); + virtual ~SATResolver(); + + // ---------------------------------- I/O + + virtual std::ostream & dumpOn( std::ostream & str ) const; + friend std::ostream& operator<<(std::ostream& str, const SATResolver & obj) + { return obj.dumpOn (str); } + + ResPool pool (void) const; + void setPool (const ResPool & pool) { _pool = pool; } + + // solver run with pool selected items + bool resolvePool(const CapabilitySet & requires_caps, + const CapabilitySet & conflict_caps, + const PoolItemList & weakItems, + const std::set & upgradeRepos + ); + // solver run with the given request queue + bool resolveQueue(const SolverQueueItemList &requestQueue, + const PoolItemList & weakItems + ); + // searching for new packages + void doUpdate(); + + ResolverProblemList problems (); + void applySolutions (const ProblemSolutionList &solutions); + + bool fixsystem () const {return _fixsystem;} + void setFixsystem ( const bool fixsystem) { _fixsystem = fixsystem;} + + bool ignorealreadyrecommended () const {return _ignorealreadyrecommended;} + void setIgnorealreadyrecommended ( const bool ignorealreadyrecommended) { _ignorealreadyrecommended = ignorealreadyrecommended;} + + bool distupgrade () const {return _distupgrade;} + void setDistupgrade ( const bool distupgrade) { _distupgrade = distupgrade;} + + bool removeOrphaned () const {return _removeOrphaned;} + void setRemoveOrphaned ( const bool removeOrphaned) { _removeOrphaned = removeOrphaned;} + + bool allowdowngrade () const {return _allowdowngrade;} + void setAllowdowngrade ( const bool allowdowngrade) { _allowdowngrade = allowdowngrade;} + + bool allowarchchange () const {return _allowarchchange;} + void setAllowarchchange ( const bool allowarchchange) { _allowarchchange = allowarchchange;} + + bool allowvendorchange () const {return _allowvendorchange;} + void setAllowvendorchange ( const bool allowvendorchange) { _allowvendorchange = allowvendorchange;} + + bool allowuninstall () const {return _allowuninstall;} + void setAllowuninstall ( const bool allowuninstall) { _allowuninstall = allowuninstall;} + + bool updatesystem () const {return _updatesystem;} + void setUpdatesystem ( const bool updatesystem) { _updatesystem = updatesystem;} + + bool noupdateprovide () const {return _noupdateprovide;} + void setNoupdateprovide ( const bool noupdateprovide) { _noupdateprovide = noupdateprovide;} + + bool dosplitprovides () const {return _dosplitprovides;} + void setDosplitprovides ( const bool dosplitprovides) { _dosplitprovides = dosplitprovides;} + + bool onlyRequires () const {return _onlyRequires;} + void setOnlyRequires ( const bool onlyRequires) { _onlyRequires = onlyRequires;} + + bool solveSrcPackages() const { return _solveSrcPackages; } + void setSolveSrcPackages( bool state_r ) { _solveSrcPackages = state_r; } + + bool cleandepsOnRemove() const { return _cleandepsOnRemove; } + void setCleandepsOnRemove( bool state_r ) { _cleandepsOnRemove = state_r; } + + PoolItemList problematicUpdateItems( void ) const { return _problem_items; } + PoolItemList problematicUpdateItems() { return _problem_items; } + + PoolItemList resultItemsToInstall () { return _result_items_to_install; } + PoolItemList resultItemsToRemove () { return _result_items_to_remove; } + + sat::StringQueue autoInstalled() const; + sat::StringQueue userInstalled() const; + +public: + /** Expert backdoor. */ + sat::detail::CSolver * get() const { return _satSolver; } +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_SAT_RESOLVER_H diff --git a/zypp/solver/detail/SolutionAction.cc b/zypp/solver/detail/SolutionAction.cc new file mode 100644 index 0000000..3a5fbef --- /dev/null +++ b/zypp/solver/detail/SolutionAction.cc @@ -0,0 +1,172 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SolutionAction.cc + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Copyright (C) 2000-2002 Ximian, Inc. + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include +#include +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp::solver::detail { + + /////////////////////////////////////////////////////////////////////// + // class SolutionAction + /////////////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(SolutionAction); + + SolutionAction::SolutionAction() + {} + + SolutionAction::~SolutionAction() + {} + + std::ostream & SolutionAction::dumpOn( std::ostream & os ) const + { return os << "SolutionAction "; } + + PoolItem SolutionAction::item() const + { return PoolItem(); } + + bool SolutionAction::skipsPatchesOnly() const + { return false; } + + std::ostream & operator<<( std::ostream & str, const SolutionActionList & actionlist ) + { + for ( const auto & itemptr : actionlist ) + str << *itemptr << std::endl; + return str; + } + + /////////////////////////////////////////////////////////////////////// + // class TransactionSolutionAction + /////////////////////////////////////////////////////////////////////// + + std::ostream & TransactionSolutionAction::dumpOn( std::ostream & str ) const + { + str << "TransactionSolutionAction: "; + switch (_action) { + case KEEP: str << "Keep " << _item; break; + case INSTALL: str << "Install " << _item; break; + case REMOVE: str << "Remove " << _item; break; + case UNLOCK: str << "Unlock " << _item; break; + case LOCK: str << "Lock " << _item; break; + case REMOVE_EXTRA_REQUIRE: str << "Remove require " << _capability; break; + case REMOVE_EXTRA_CONFLICT: str << "Remove conflict " << _capability; break; + case ADD_SOLVE_QUEUE_ITEM: str << "Add SolveQueueItem " << _solverQueueItem; break; + case REMOVE_SOLVE_QUEUE_ITEM: str << "Remove SolveQueueItem " << _solverQueueItem; break; + } + return str; + } + + bool TransactionSolutionAction::execute( ResolverInternal & resolver ) const + { + bool ret = true; + switch ( _action ) { + case KEEP: + _item.status().resetTransact( ResStatus::USER ); + ret = _item.status().setTransact( false, ResStatus::APPL_HIGH ); // APPL_HIGH: Locking should not be saved permanently + break; + case INSTALL: + if ( _item.status().isToBeUninstalled() ) + ret = _item.status().setTransact( false, ResStatus::USER ); + else + _item.status().setToBeInstalled( ResStatus::USER ); + break; + case REMOVE: + if ( _item.status().isToBeInstalled() ) { + _item.status().setTransact( false, ResStatus::USER ); + _item.status().setLock( true, ResStatus::USER ); // no other dependency can set it again + } else if ( _item.status().isInstalled() ) + _item.status().setToBeUninstalled( ResStatus::USER ); + else + _item.status().setLock( true,ResStatus::USER ); // no other dependency can set it again + break; + case UNLOCK: + ret = _item.status().setLock( false, ResStatus::USER ); + if ( !ret ) ERR << "Cannot unlock " << _item << endl; + break; + case LOCK: + _item.status().resetTransact( ResStatus::USER ); + ret = _item.status().setLock( true, ResStatus::APPL_HIGH ); // APPL_HIGH: Locking should not be saved permanently + if ( !ret ) ERR << "Cannot lock " << _item << endl; + break; + case REMOVE_EXTRA_REQUIRE: + resolver.removeExtraRequire( _capability ); + break; + case REMOVE_EXTRA_CONFLICT: + resolver.removeExtraConflict( _capability ); + break; + case ADD_SOLVE_QUEUE_ITEM: + resolver.addQueueItem( _solverQueueItem ); + break; + case REMOVE_SOLVE_QUEUE_ITEM: + resolver.removeQueueItem( _solverQueueItem ); + break; + default: + ERR << "Wrong TransactionKind" << endl; + ret = false; + break; + } + return ret; + } + + bool TransactionSolutionAction::skipsPatchesOnly() const + { return _action == KEEP && _item.isKind(); } + + /////////////////////////////////////////////////////////////////////// + // class InjectSolutionAction + /////////////////////////////////////////////////////////////////////// + + std::ostream & InjectSolutionAction::dumpOn( std::ostream & str ) const + { + str << "InjectSolutionAction: "; + switch (_kind) { + case WEAK: str << "Weak"; break; + default: str << "Wrong kind"; break; + } + return str << " " << _item; + } + + bool InjectSolutionAction::execute( ResolverInternal & resolver ) const + { + bool ret = true; + switch (_kind) { + case WEAK: + // set item dependencies to weak + resolver.addWeak( _item ); + break; + default: + ERR << "No valid InjectSolutionAction kind found" << endl; + ret = false; + break; + } + return ret; + } + +} // namespace zypp::solver::detail +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SolutionAction.h b/zypp/solver/detail/SolutionAction.h new file mode 100644 index 0000000..7c0351f --- /dev/null +++ b/zypp/solver/detail/SolutionAction.h @@ -0,0 +1,187 @@ +/* + * + * Easy-to use interface to the ZYPP dependency resolver + * + * Author: Stefan Hundhammer + * + **/ + +#ifndef ZYPP_SOLVER_DETAIL_SOLUTIONACTION_H +#define ZYPP_SOLVER_DETAIL_SOLUTIONACTION_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +#include +#include + +#include +#include + +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + class Resolver; + + DEFINE_PTR_TYPE(SolverQueueItem); + + DEFINE_PTR_TYPE(SolutionAction); + typedef std::list SolutionActionList; + + /** + * Abstract base class for one action of a problem solution. + **/ + class SolutionAction : public base::ReferenceCounted + { + protected: + typedef Resolver ResolverInternal; + SolutionAction(); + + public: + virtual ~SolutionAction(); + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + /** + * Execute this action. + * Returns 'true' on success, 'false' on error. + **/ + virtual bool execute( ResolverInternal & resolver ) const = 0; + + public: + /** The PoolItem the solution refers to (if any). */ + virtual PoolItem item() const; + + /** The solution contains only 'do not install patch:' actions. */ + virtual bool skipsPatchesOnly() const; + }; + + inline std::ostream & operator<<( std::ostream & str, const SolutionAction & action ) + { return action.dumpOn( str ); } + + std::ostream & operator<<( std::ostream & str, const SolutionActionList & actionlist ); + + + /** + * A problem solution action that performs a transaction + * (installs, removes, keep ...) one resolvable + * (package, patch, pattern, product). + **/ + typedef enum + { + KEEP, + INSTALL, + REMOVE, + UNLOCK, + LOCK, + REMOVE_EXTRA_REQUIRE, + REMOVE_EXTRA_CONFLICT, + ADD_SOLVE_QUEUE_ITEM, + REMOVE_SOLVE_QUEUE_ITEM, + } TransactionKind; + + class TransactionSolutionAction: public SolutionAction + { + public: + TransactionSolutionAction( PoolItem item, TransactionKind action ) + : SolutionAction() + , _action( action ) + , _item( item ) + {} + + TransactionSolutionAction( Capability capability, TransactionKind action ) + : SolutionAction() + , _action( action ) + , _capability( capability ) + {} + + TransactionSolutionAction( SolverQueueItem_Ptr item, TransactionKind action ) + : SolutionAction() + , _action( action ) + , _solverQueueItem( item ) + {} + + TransactionSolutionAction( TransactionKind action ) + : SolutionAction() + , _action( action ) + {} + + std::ostream & dumpOn( std::ostream & str ) const override; + + bool execute( ResolverInternal & resolver ) const override; + + public: + PoolItem item() const override + { return _item; } + + bool skipsPatchesOnly() const override; + + protected: + const TransactionKind _action; + + PoolItem _item; + Capability _capability; + SolverQueueItem_Ptr _solverQueueItem; + }; + + + /** + * Type of ignoring; currently only WEAK + **/ + typedef enum + { + WEAK + } InjectSolutionKind; + + /** + * A problem solution action that injects an artificial "provides" to + * the pool to satisfy open requirements or remove the conflict of + * concerning resolvable + * + * This is typically used by "ignore" (user override) solutions. + **/ + class InjectSolutionAction: public SolutionAction + { + public: + InjectSolutionAction( PoolItem item, const InjectSolutionKind & kind ) + : SolutionAction() + , _kind( kind ) + , _item( item ) + {} + + std::ostream & dumpOn( std::ostream & str ) const override; + + bool execute( ResolverInternal & resolver ) const override; + + public: + PoolItem item() const override + { return _item; } + + protected: + const InjectSolutionKind _kind; + + PoolItem _item; + }; + + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_SOLUTIONACTION_H + diff --git a/zypp/solver/detail/SolverQueueItem.cc b/zypp/solver/detail/SolverQueueItem.cc new file mode 100644 index 0000000..86dfe6d --- /dev/null +++ b/zypp/solver/detail/SolverQueueItem.cc @@ -0,0 +1,108 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SolverQueueItem.cc + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +extern "C" +{ +#include +} + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include + +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +IMPL_PTR_TYPE(SolverQueueItem); + +//--------------------------------------------------------------------------- + +std::ostream & +SolverQueueItem::dumpOn( std::ostream & os ) const +{ + switch (_type) { + case QUEUE_ITEM_TYPE_UNKNOWN : os << "unknown"; break; + case QUEUE_ITEM_TYPE_UPDATE : os << "update"; break; + case QUEUE_ITEM_TYPE_LOCK : os << "lock"; break; + case QUEUE_ITEM_TYPE_INSTALL : os << "install"; break; + case QUEUE_ITEM_TYPE_DELETE : os << "delete"; break; + case QUEUE_ITEM_TYPE_INSTALL_ONE_OF: os << "install one of"; break; + default: os << "?solverqueueitem?"; break; + } + return os; +} + + +std::ostream& +operator<<( std::ostream & os, const SolverQueueItemList & itemlist ) +{ + for (SolverQueueItemList::const_iterator iter = itemlist.begin(); iter != itemlist.end(); ++iter) { + if (iter != itemlist.begin()) + os << "," << endl << "\t"; + os << **iter; + } + return os; +} + +//--------------------------------------------------------------------------- + +SolverQueueItem::SolverQueueItem (SolverQueueItemType type, ResPool pool) + : _type (type) + , _pool (std::move(pool)) +{ +} + + +SolverQueueItem::~SolverQueueItem() +{ +} + +//--------------------------------------------------------------------------- + +void +SolverQueueItem::copy (const SolverQueueItem *from) +{ +} + + +//--------------------------------------------------------------------------- + + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SolverQueueItem.h b/zypp/solver/detail/SolverQueueItem.h new file mode 100644 index 0000000..45cd491 --- /dev/null +++ b/zypp/solver/detail/SolverQueueItem.h @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* QueueItem.h + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_QUEUEITEM_H +#define ZYPP_SOLVER_DETAIL_QUEUEITEM_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +#include +#include +#include + +#include +#include +#include +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + +DEFINE_PTR_TYPE(SolverQueueItem); + +DEFINE_PTR_TYPE(SolverQueueItemUpdate); +DEFINE_PTR_TYPE(SolverQueueItemDelete); +DEFINE_PTR_TYPE(SolverQueueItemInstall); +DEFINE_PTR_TYPE(SolverQueueItemInstallOneOf); +DEFINE_PTR_TYPE(SolverQueueItemLock); + + +typedef enum { + QUEUE_ITEM_TYPE_UNKNOWN = 0, + QUEUE_ITEM_TYPE_UPDATE, + QUEUE_ITEM_TYPE_INSTALL, + QUEUE_ITEM_TYPE_DELETE, + QUEUE_ITEM_TYPE_INSTALL_ONE_OF, + QUEUE_ITEM_TYPE_LOCK +} SolverQueueItemType; + + +typedef std::list SolverQueueItemList; + +#define CMP(a,b) (((a) < (b)) - ((b) < (a))) + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : SolverQueueItem + +class SolverQueueItem : public base::ReferenceCounted, private base::NonCopyable { + + private: + + SolverQueueItemType _type; + ResPool _pool; + + protected: + + SolverQueueItem (SolverQueueItemType type, ResPool pool); + + public: + + virtual ~SolverQueueItem(); + + // ---------------------------------- I/O + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream & str, const SolverQueueItem & obj) + { return obj.dumpOn (str); } + friend std::ostream& operator<<(std::ostream & str, const SolverQueueItemList & itemlist); + + // ---------------------------------- accessors + + ResPool pool (void) const { return _pool; } + + // ---------------------------------- methods + + void copy (const SolverQueueItem *from); + + bool isDelete (void) const { return _type == QUEUE_ITEM_TYPE_DELETE; } + bool isInstall (void) const { return _type == QUEUE_ITEM_TYPE_INSTALL; } + bool isUpdate (void) const { return _type == QUEUE_ITEM_TYPE_UPDATE; } + bool isLock (void) const { return _type == QUEUE_ITEM_TYPE_LOCK; } + bool isInstallOneOf (void) const { return _type == QUEUE_ITEM_TYPE_INSTALL_ONE_OF; } + + + virtual SolverQueueItem_Ptr copy (void) const = 0; + virtual bool addRule (sat::detail::CQueue & q) =0 ; + virtual int cmp (SolverQueueItem_constPtr item) const = 0; + int compare (SolverQueueItem_constPtr item) const { return CMP(_type, item->_type); } + +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_QUEUEITEM_H diff --git a/zypp/solver/detail/SolverQueueItemDelete.cc b/zypp/solver/detail/SolverQueueItemDelete.cc new file mode 100644 index 0000000..91ca24a --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemDelete.cc @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SolverQueueItem.cc + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +extern "C" +{ +#include +} + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include +#include + +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +IMPL_PTR_TYPE(SolverQueueItemDelete); + +//--------------------------------------------------------------------------- + +std::ostream & +SolverQueueItemDelete::dumpOn( std::ostream & os ) const +{ + os << "[" << (_soft?"Soft":"") << "Delete: " + << _name << "]"; + + return os; +} + +//--------------------------------------------------------------------------- + +SolverQueueItemDelete::SolverQueueItemDelete (const ResPool & pool, std::string name, bool soft) + : SolverQueueItem (QUEUE_ITEM_TYPE_DELETE, pool) + , _name (std::move(name)) + , _soft (soft) +{ +} + + +SolverQueueItemDelete::~SolverQueueItemDelete() +{ +} + +//--------------------------------------------------------------------------- + +bool SolverQueueItemDelete::addRule (sat::detail::CQueue & q) +{ +#define MAYBE_CLEANDEPS (pool().resolver().cleandepsOnRemove()?SOLVER_CLEANDEPS:0) + + ::Id id = IdString(_name).id(); + if (_soft) { + queue_push( &(q), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | SOLVER_WEAK | MAYBE_CLEANDEPS ); + } else { + queue_push( &(q), SOLVER_ERASE | SOLVER_SOLVABLE_NAME | MAYBE_CLEANDEPS ); + } + queue_push( &(q), id); + + MIL << "Delete " << _name << (_soft ? "(soft)" : "") + << " with SAT-Pool: " << id << endl; + return true; +} + +SolverQueueItem_Ptr +SolverQueueItemDelete::copy (void) const +{ + SolverQueueItemDelete_Ptr new_delete = new SolverQueueItemDelete (pool(), _name); + new_delete->SolverQueueItem::copy(this); + + new_delete->_soft = _soft; + return new_delete; +} + +int +SolverQueueItemDelete::cmp (SolverQueueItem_constPtr item) const +{ + int cmp = this->compare (item); + if (cmp != 0) + return cmp; + SolverQueueItemDelete_constPtr del = dynamic_pointer_cast(item); + if (_name != del->_name) { + return _name.compare(del->_name); + } + return 0; +} + +//--------------------------------------------------------------------------- + + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SolverQueueItemDelete.h b/zypp/solver/detail/SolverQueueItemDelete.h new file mode 100644 index 0000000..6c8c005 --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemDelete.h @@ -0,0 +1,85 @@ + +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* QueueItem.h + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_QUEUEITEMDELETE_H +#define ZYPP_SOLVER_DETAIL_QUEUEITEMDELETE_H + +#include +#include + +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : SolverQueueItemDelete + +class ZYPP_API_DEPTESTOMATIC SolverQueueItemDelete : public SolverQueueItem { + + private: + + std::string _name; + bool _soft; // if triggered by a soft requirement (a recommends) + + public: + + SolverQueueItemDelete (const ResPool & pool, std::string name, bool soft = false); + virtual ~SolverQueueItemDelete(); + + // ---------------------------------- I/O + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream & str, const SolverQueueItemDelete & obj) + { return obj.dumpOn (str); } + + // ---------------------------------- accessors + + bool isSoft (void) const { return _soft; } + + // ---------------------------------- methods + + virtual bool addRule (sat::detail::CQueue & q); + virtual SolverQueueItem_Ptr copy (void) const; + virtual int cmp (SolverQueueItem_constPtr item) const; +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + +#endif // ZYPP_SOLVER_DETAIL_QUEUEITEMDELETE_H diff --git a/zypp/solver/detail/SolverQueueItemInstall.cc b/zypp/solver/detail/SolverQueueItemInstall.cc new file mode 100644 index 0000000..cce4911 --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemInstall.cc @@ -0,0 +1,127 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SolverQueueItem.cc + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +extern "C" +{ +#include +} + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include +#include + +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +IMPL_PTR_TYPE(SolverQueueItemInstall); + +//--------------------------------------------------------------------------- + +std::ostream & +SolverQueueItemInstall::dumpOn( std::ostream & os ) const +{ + os << "[" << (_soft?"Soft":"") << "Install: " + << _name + << "]"; + + return os; +} + +//--------------------------------------------------------------------------- + +SolverQueueItemInstall::SolverQueueItemInstall (const ResPool & pool, std::string name, bool soft) + : SolverQueueItem (QUEUE_ITEM_TYPE_INSTALL, pool) + , _name (std::move(name)) + , _soft (soft) +{ +} + + +SolverQueueItemInstall::~SolverQueueItemInstall() +{ +} + +//--------------------------------------------------------------------------- + +bool SolverQueueItemInstall::addRule (sat::detail::CQueue & q) +{ + ::Id id = IdString(_name).id(); + if (_soft) { + queue_push( &(q), SOLVER_INSTALL | SOLVER_SOLVABLE_NAME | SOLVER_WEAK ); + } else { + queue_push( &(q), SOLVER_INSTALL | SOLVER_SOLVABLE_NAME ); + } + queue_push( &(q), id); + + MIL << "Install " << _name << (_soft ? "(soft)" : "") + << " with SAT-PoolID: " << id << endl; + return true; +} + +SolverQueueItem_Ptr +SolverQueueItemInstall::copy (void) const +{ + SolverQueueItemInstall_Ptr new_install = new SolverQueueItemInstall (pool(), _name); + new_install->SolverQueueItem::copy(this); + + new_install->_soft = _soft; + return new_install; +} + +int +SolverQueueItemInstall::cmp (SolverQueueItem_constPtr item) const +{ + int cmp = this->compare (item); + if (cmp != 0) + return cmp; + SolverQueueItemInstall_constPtr ins = dynamic_pointer_cast(item); + if (_name != ins->_name) { + return _name.compare(ins->_name); + } + return 0; +} + + +//--------------------------------------------------------------------------- + + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SolverQueueItemInstall.h b/zypp/solver/detail/SolverQueueItemInstall.h new file mode 100644 index 0000000..c2f5345 --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemInstall.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* QueueItem.h + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_QUEUEITEMINSTALL_H +#define ZYPP_SOLVER_DETAIL_QUEUEITEMINSTALL_H + +#include +#include + +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : SolverQueueItemInstall + +class ZYPP_API_DEPTESTOMATIC SolverQueueItemInstall : public SolverQueueItem { + + private: + + std::string _name; + bool _soft; // if triggered by a soft requirement (a recommends) + + public: + + SolverQueueItemInstall (const ResPool & pool, std::string name, bool soft = false); + virtual ~SolverQueueItemInstall(); + + // ---------------------------------- I/O + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream & str, const SolverQueueItemInstall & obj) + { return obj.dumpOn (str); } + + // ---------------------------------- accessors + + bool isSoft (void) const { return _soft; } + + // ---------------------------------- methods + + virtual bool addRule (sat::detail::CQueue & q); + virtual SolverQueueItem_Ptr copy (void) const; + virtual int cmp (SolverQueueItem_constPtr item) const; +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + +#endif // ZYPP_SOLVER_DETAIL_QUEUEITEMINSTALL_H diff --git a/zypp/solver/detail/SolverQueueItemInstallOneOf.cc b/zypp/solver/detail/SolverQueueItemInstallOneOf.cc new file mode 100644 index 0000000..6a65e0e --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemInstallOneOf.cc @@ -0,0 +1,143 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SolverQueueItem.cc + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +extern "C" +{ +#include +} + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include + +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +IMPL_PTR_TYPE(SolverQueueItemInstallOneOf); + +//--------------------------------------------------------------------------- + +std::ostream & +SolverQueueItemInstallOneOf::dumpOn( std::ostream & os ) const +{ + os << "[" << (_soft?"Soft":"") << "InstallOneOf: "; + for (PoolItemList::const_iterator iter = _oneOfList.begin(); + iter != _oneOfList.end(); + iter++) + os << *iter; + os << "]"; + + return os; +} + +//--------------------------------------------------------------------------- + +SolverQueueItemInstallOneOf::SolverQueueItemInstallOneOf (const ResPool & pool, PoolItemList itemList, + bool soft) + : SolverQueueItem (QUEUE_ITEM_TYPE_INSTALL_ONE_OF, pool) + , _oneOfList (std::move(itemList)) + , _soft (soft) +{ +} + + +SolverQueueItemInstallOneOf::~SolverQueueItemInstallOneOf() +{ +} + +//--------------------------------------------------------------------------- + +bool SolverQueueItemInstallOneOf::addRule (sat::detail::CQueue & q) +{ + bool ret = true; + MIL << "Install one of " << (_soft ? "(soft):" : ":")<< endl; + Queue qs; + + if (_soft) { + queue_push( &(q), SOLVER_INSTALL | SOLVER_SOLVABLE_ONE_OF | SOLVER_WEAK); + } else { + queue_push( &(q), SOLVER_INSTALL | SOLVER_SOLVABLE_ONE_OF ); + } + + queue_init(&qs); + for (PoolItemList::const_iterator iter = _oneOfList.begin(); iter != _oneOfList.end(); iter++) { + Id id = (*iter)->satSolvable().id(); + if (id == ID_NULL) { + ERR << *iter << " not found" << endl; + ret = false; + } else { + MIL << " candidate:" << *iter << " with the SAT-Pool ID: " << id << endl; + queue_push( &(qs), id ); + } + } + sat::Pool satPool( sat::Pool::instance() ); + queue_push( &(q), pool_queuetowhatprovides(satPool.get(), &qs)); + queue_free(&qs); + + return ret; +} + +SolverQueueItem_Ptr +SolverQueueItemInstallOneOf::copy (void) const +{ + SolverQueueItemInstallOneOf_Ptr new_installOneOf = new SolverQueueItemInstallOneOf (pool(), _oneOfList); + new_installOneOf->SolverQueueItem::copy(this); + new_installOneOf->_soft = _soft; + + return new_installOneOf; +} + +int +SolverQueueItemInstallOneOf::cmp (SolverQueueItem_constPtr item) const +{ + int cmp = this->compare (item); + if (cmp != 0) + return cmp; + SolverQueueItemInstallOneOf_constPtr install = dynamic_pointer_cast(item); + + return (_oneOfList == install->_oneOfList) ? 0 : -1; // more evaluation would be not useful +} + + +//--------------------------------------------------------------------------- + + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SolverQueueItemInstallOneOf.h b/zypp/solver/detail/SolverQueueItemInstallOneOf.h new file mode 100644 index 0000000..fd3d86c --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemInstallOneOf.h @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* QueueItem.h + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_QUEUEITEMINSTALLONEOF_H +#define ZYPP_SOLVER_DETAIL_QUEUEITEMINSTALLONEOF_H + +#include +#include + +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : SolverQueueItemInstallOneOf + +class ZYPP_API_DEPTESTOMATIC SolverQueueItemInstallOneOf : public SolverQueueItem { + + public: + typedef std::list PoolItemList; + + private: + + PoolItemList _oneOfList; // List of candidates + bool _soft; // if triggered by a soft requirement (a recommends) + + public: + + SolverQueueItemInstallOneOf (const ResPool & pool, PoolItemList itemList, bool soft = false); + virtual ~SolverQueueItemInstallOneOf(); + + // ---------------------------------- I/O + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream & str, const SolverQueueItemInstallOneOf & obj) + { return obj.dumpOn (str); } + + // ---------------------------------- accessors + + bool isSoft (void) const { return _soft; } + + // ---------------------------------- methods + + virtual bool addRule (sat::detail::CQueue & q); + virtual SolverQueueItem_Ptr copy (void) const; + virtual int cmp (SolverQueueItem_constPtr item) const; +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + +#endif // ZYPP_SOLVER_DETAIL_QUEUEITEMINSTALLONEOF_H diff --git a/zypp/solver/detail/SolverQueueItemLock.cc b/zypp/solver/detail/SolverQueueItemLock.cc new file mode 100644 index 0000000..033558d --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemLock.cc @@ -0,0 +1,130 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SolverQueueItem.cc + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +extern "C" +{ +#include +} + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +IMPL_PTR_TYPE(SolverQueueItemLock); + +//--------------------------------------------------------------------------- + +std::ostream & +SolverQueueItemLock::dumpOn( std::ostream & os ) const +{ + os << "[" << (_soft?"Soft":"") << "Lock: " << + _item << "]"; + + return os; +} + +//--------------------------------------------------------------------------- + +SolverQueueItemLock::SolverQueueItemLock (const ResPool & pool, + const PoolItem & item, bool soft) + : SolverQueueItem (QUEUE_ITEM_TYPE_LOCK, pool) + , _item (item) + , _soft (soft) +{ +} + + +SolverQueueItemLock::~SolverQueueItemLock() +{ +} + +//--------------------------------------------------------------------------- + +bool SolverQueueItemLock::addRule (sat::detail::CQueue & q) +{ + ::Id id = _item.satSolvable().id(); + if (id == ID_NULL) { + ERR << "Lock : " << _item << " not found" << endl; + return false; + } + MIL << "Lock " << _item << " with the SAT-Pool ID: " << id << endl; + if (_item.status().isInstalled()) { + if (_soft) { + queue_push( &(q), SOLVER_INSTALL | SOLVER_SOLVABLE | SOLVER_WEAK ); + } else { + queue_push( &(q), SOLVER_INSTALL | SOLVER_SOLVABLE ); + } + } else { + if (_soft) { + queue_push( &(q), SOLVER_ERASE | SOLVER_SOLVABLE | SOLVER_WEAK ); + } else { + queue_push( &(q), SOLVER_ERASE | SOLVER_SOLVABLE ); + } + } + queue_push( &(q), id ); + return true; +} + +SolverQueueItem_Ptr +SolverQueueItemLock::copy (void) const +{ + SolverQueueItemLock_Ptr new_lock = new SolverQueueItemLock (pool(), _item); + new_lock->SolverQueueItem::copy(this); + + new_lock->_soft = _soft; + return new_lock; +} + +int +SolverQueueItemLock::cmp (SolverQueueItem_constPtr item) const +{ + int cmp = this->compare (item); + if (cmp != 0) + return cmp; + SolverQueueItemLock_constPtr lock = dynamic_pointer_cast(item); + return compareByNVRA (_item, lock->_item); +} + + +//--------------------------------------------------------------------------- + + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SolverQueueItemLock.h b/zypp/solver/detail/SolverQueueItemLock.h new file mode 100644 index 0000000..3486431 --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemLock.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* QueueItem.h + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_QUEUEITEMLOCK_H +#define ZYPP_SOLVER_DETAIL_QUEUEITEMLOCK_H + +#include +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : SolverQueueItemLock + +class ZYPP_API_DEPTESTOMATIC SolverQueueItemLock : public SolverQueueItem { + + private: + + PoolItem _item; // the item to-be-locked + bool _soft; // if triggered by a soft requirement (a recommends) + + public: + + SolverQueueItemLock (const ResPool & pool, const PoolItem & item, bool soft = false); + virtual ~SolverQueueItemLock(); + + // ---------------------------------- I/O + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream & str, const SolverQueueItemLock & obj) + { return obj.dumpOn (str); } + + // ---------------------------------- accessors + + bool isSoft (void) const { return _soft; } + + // ---------------------------------- methods + + virtual bool addRule (sat::detail::CQueue & q); + virtual SolverQueueItem_Ptr copy (void) const; + virtual int cmp (SolverQueueItem_constPtr item) const; +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + +#endif // ZYPP_SOLVER_DETAIL_QUEUEITEMLOCK_H diff --git a/zypp/solver/detail/SolverQueueItemUpdate.cc b/zypp/solver/detail/SolverQueueItemUpdate.cc new file mode 100644 index 0000000..d16eb89 --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemUpdate.cc @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* SolverQueueItem.cc + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ +extern "C" +{ +#include +} + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + +IMPL_PTR_TYPE(SolverQueueItemUpdate); + +//--------------------------------------------------------------------------- + +std::ostream & +SolverQueueItemUpdate::dumpOn( std::ostream & os ) const +{ + os << "[" << (_soft?"Soft":"") << "Update: " << + _item << "]"; + + return os; +} + +//--------------------------------------------------------------------------- + +SolverQueueItemUpdate::SolverQueueItemUpdate (const ResPool & pool, + const PoolItem & item, bool soft) + : SolverQueueItem (QUEUE_ITEM_TYPE_UPDATE, pool) + , _item (item) + , _soft (soft) +{ +} + + +SolverQueueItemUpdate::~SolverQueueItemUpdate() +{ +} + +//--------------------------------------------------------------------------- + +bool SolverQueueItemUpdate::addRule (sat::detail::CQueue & q) +{ + ::Id id = _item.satSolvable().id(); + if (id == ID_NULL) { + ERR << "Update explicit: " << _item << " not found" << endl; + return false; + } + MIL << "Update explicit " << _item << " with the SAT-Pool ID: " << id << endl; + queue_push( &(q), SOLVER_UPDATE | SOLVER_SOLVABLE ); + queue_push( &(q), id ); + return true; +} + +SolverQueueItem_Ptr +SolverQueueItemUpdate::copy (void) const +{ + SolverQueueItemUpdate_Ptr new_update = new SolverQueueItemUpdate (pool(), _item); + new_update->SolverQueueItem::copy(this); + + new_update->_soft = _soft; + return new_update; +} + +int +SolverQueueItemUpdate::cmp (SolverQueueItem_constPtr item) const +{ + int cmp = this->compare (item); + if (cmp != 0) + return cmp; + SolverQueueItemUpdate_constPtr update = dynamic_pointer_cast(item); + return compareByNVRA (_item, update->_item); +} + + +//--------------------------------------------------------------------------- + + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SolverQueueItemUpdate.h b/zypp/solver/detail/SolverQueueItemUpdate.h new file mode 100644 index 0000000..be90763 --- /dev/null +++ b/zypp/solver/detail/SolverQueueItemUpdate.h @@ -0,0 +1,84 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* QueueItem.h + * + * Copyright (C) 2008 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_QUEUEITEMUPDATE_H +#define ZYPP_SOLVER_DETAIL_QUEUEITEMUPDATE_H + +#include +#include + +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : SolverQueueItemUpdate + +class ZYPP_API_DEPTESTOMATIC SolverQueueItemUpdate : public SolverQueueItem { + + private: + + PoolItem _item; // the item to-be-updated + bool _soft; // if triggered by a soft requirement (a recommends) + + public: + + SolverQueueItemUpdate (const ResPool & pool, const PoolItem & item, bool soft = false); + virtual ~SolverQueueItemUpdate(); + + // ---------------------------------- I/O + + virtual std::ostream & dumpOn( std::ostream & str ) const; + + friend std::ostream& operator<<(std::ostream & str, const SolverQueueItemUpdate & obj) + { return obj.dumpOn (str); } + + // ---------------------------------- accessors + + bool isSoft (void) const { return _soft; } + + // ---------------------------------- methods + + virtual bool addRule (sat::detail::CQueue & q); + virtual SolverQueueItem_Ptr copy (void) const; + virtual int cmp (SolverQueueItem_constPtr item) const; +}; + +/////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// + +#endif // ZYPP_SOLVER_DETAIL_QUEUEITEMUPDATE_H diff --git a/zypp/solver/detail/SystemCheck.cc b/zypp/solver/detail/SystemCheck.cc new file mode 100644 index 0000000..6251455 --- /dev/null +++ b/zypp/solver/detail/SystemCheck.cc @@ -0,0 +1,172 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/solver/detail/SystemCheck.cc + * +*/ +#include +#include +#include + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include + +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + Pathname _file = ""; + Pathname _dir = ""; + CapabilitySet _require; + CapabilitySet _conflict; + + using CapList = std::vector; + + const SystemCheck & SystemCheck::instance() + { + static SystemCheck _val; + return _val; + } + + + SystemCheck::SystemCheck() { + if (_file.empty()) { + _file = ZConfig::instance().solver_checkSystemFile(); + loadFile(_file); + } + if (_dir.empty()) { + _dir = ZConfig::instance().solver_checkSystemFileDir(); + loadFiles(); + } + } + + bool SystemCheck::setFile(const Pathname & file) const{ + MIL << "Setting checkFile to : " << file << endl; + _file = file; + loadFile(_file); + return true; + } + + bool SystemCheck::setDir(const Pathname & dir) const { + MIL << "Setting checkFile directory to : " << dir << endl; + loadFile(_file); + _dir = dir; + loadFiles(); + return true; + } + + const Pathname & SystemCheck::file() { + return _file; + } + + const Pathname & SystemCheck::dir() { + return _dir; + } + + const CapabilitySet & SystemCheck::requiredSystemCap() const{ + return _require; + } + + const CapabilitySet & SystemCheck::conflictSystemCap() const{ + return _conflict; + } + + bool SystemCheck::loadFile(Pathname & file, bool reset_caps) const{ + Target_Ptr trg( getZYpp()->getTarget() ); + if ( trg ) + file = trg->assertRootPrefix( file ); + + PathInfo pi( file ); + if ( ! pi.isFile() ) { + WAR << "Can't read " << file << " " << pi << endl; + return false; + } + + if (reset_caps) { + _require.clear(); + _conflict.clear(); + } + + std::ifstream infile( file.c_str() ); + for( iostr::EachLine in( infile ); in; in.next() ) { + std::string l( str::trim(*in) ); + if ( ! l.empty() && l[0] != '#' ) + { + CapList capList; + str::split( l, back_inserter(capList), ":" ); + if (capList.size() == 2 ) { + CapList::iterator it = capList.begin(); + if (*it == "requires") { + _require.insert(Capability(*(it+1))); + } else if (*it == "conflicts") { + _conflict.insert(Capability(*(it+1))); + } else { + ERR << "Wrong parameter: " << l << endl; + } + } else { + ERR << "Wrong line: " << l << endl; + } + } + } + MIL << "Read " << pi << endl; + return true; + } + + bool SystemCheck::loadFiles() const { + + filesystem::dirForEach(_dir, + [this](const Pathname & dir_r, const char *const & name_r)->bool + { + const std::string wanted = ".check"; + Pathname pth = dir_r/name_r; + if (pth.extension() != wanted) { + MIL << "Skipping " << pth << " (not a *.check file)" << endl; + return true; + } + else { + MIL << "Reading " << pth << endl; + return loadFile(pth, false /* do not reset caps */); + } + }); + return true; + } + + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const SystemCheck & obj ) + { + str << _file << endl; + str << "requires" << endl; + for (CapabilitySet::const_iterator it = _require.begin(); it != _require.end(); ++it) + str << " " << *it << endl; + + str << "conflicts" << endl; + for (CapabilitySet::const_iterator it = _conflict.begin(); it != _conflict.end(); ++it) + str << " " << *it << endl; + + return str; + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/SystemCheck.h b/zypp/solver/detail/SystemCheck.h new file mode 100644 index 0000000..b98a129 --- /dev/null +++ b/zypp/solver/detail/SystemCheck.h @@ -0,0 +1,81 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/SystemCheck.h + * +*/ +#ifndef ZYPP_TARGET_SYSTEMCHECK_H +#define ZYPP_TARGET_SYSTEMCHECK_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SystemCheck + // + /** Save and restore locale set from file. + */ + class SystemCheck : private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const SystemCheck & obj ); + + public: + + /** Singleton */ + static const SystemCheck & instance(); + + /** Return the file path. */ + const Pathname & file(); + + /** Return the directory path. */ + const Pathname & dir(); + + /** Set configuration file of system requirements + * Should be used for testcase only + */ + bool setFile(const Pathname & file) const; + + /** Set configuration directory for files of system + * requirements. + * Should be used for testcase only + */ + bool setDir(const Pathname & dir) const; + + /** Returns a list of required system capabilities. + */ + const CapabilitySet & requiredSystemCap() const; + + /** Returns a list of conflicting system capabilities. + */ + const CapabilitySet & conflictSystemCap() const; + + private: + /** Ctor taking the file to read. */ + SystemCheck(); + bool loadFile(Pathname &file, bool reset_caps = true) const; + bool loadFiles() const; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates SystemCheck Stream output */ + std::ostream & operator<<( std::ostream & str, const SystemCheck & obj ); + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_TARGET_SYSTEMCHECK_H diff --git a/zypp/solver/detail/Testcase.cc b/zypp/solver/detail/Testcase.cc new file mode 100644 index 0000000..e4eab36 --- /dev/null +++ b/zypp/solver/detail/Testcase.cc @@ -0,0 +1,400 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/solver/detail/Testcase.cc + * +*/ +#include +#include +#include +#include +#include + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +extern "C" { +#include +} + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + //--------------------------------------------------------------------------- + + Testcase::Testcase() + :dumpPath("/var/log/YaST2/solverTestcase") + {} + + Testcase::Testcase(std::string path) + :dumpPath(std::move(path)) + {} + + Testcase::~Testcase() + {} + + bool Testcase::createTestcase(Resolver & resolver, bool dumpPool, bool runSolver) + { + // libzypp/issues/317: make sure a satsolver instance is actually present + if ( not resolver.get() ) { + WAR << "Can't createTestcase if the satsolver is not yet initialized." << endl; + return false; + } + + MIL << "createTestcase at " << dumpPath << (dumpPool?" dumpPool":"") << (runSolver?" runSolver":"") << endl; + PathInfo path (dumpPath); + + if ( !path.isExist() ) { + if (zypp::filesystem::assert_dir (dumpPath)!=0) { + ERR << "Cannot create directory " << dumpPath << endl; + return false; + } + } else { + if (!path.isDir()) { + ERR << dumpPath << " is not a directory." << endl; + return false; + } + // remove old stuff if pool will be dump + if (dumpPool) + zypp::filesystem::clean_dir (dumpPath); + } + + if (runSolver) { + zypp::base::LogControl::TmpLineWriter tempRedirect; + zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" ); + zypp::base::LogControl::TmpExcessive excessive; + + resolver.resolvePool(); + } + + ResPool pool = resolver.pool(); + PoolItemList items_to_install; + PoolItemList items_to_remove; + PoolItemList items_locked; + PoolItemList items_keep; + + + const std::string slvTestcaseName = "testcase.t"; + const std::string slvResult = "solver.result"; + + zypp::AutoDispose repoFileNames( testcase_mangle_repo_names( resolver.get()->pool ), + [ nrepos = resolver.get()->pool->nrepos ]( auto **x ){ + if (!x) return; + for ( int i = 1; i < nrepos; i++ ) + solv_free((void *)x[i]); + solv_free((void *)x); + }); + + if ( ::testcase_write( resolver.get(), dumpPath.c_str(), TESTCASE_RESULT_TRANSACTION | TESTCASE_RESULT_PROBLEMS, slvTestcaseName.c_str(), slvResult.c_str() ) == 0 ) { + ERR << "Failed to write solv data, aborting." << endl; + return false; + } + + // HACK: directly access sat::pool + const sat::Pool & satpool( sat::Pool::instance() ); + + YAML::Emitter yOut; + + const auto addTag = [&]( const std::string & tag_r, bool yesno_r = true ){ + yOut << YAML::Key << tag_r << YAML::Value << yesno_r; + }; + + yOut << YAML::BeginMap << YAML::Key << "version" << YAML::Value << "1.0"; + + yOut << YAML::Key << "setup" << YAML::Value << YAML::BeginMap; + + yOut << YAML::Key << "channels"; + yOut << YAML::Value << YAML::BeginSeq; + + std::set repos; + for ( const PoolItem & pi : pool ) { + if ( pi.status().isToBeInstalled() + && !(pi.status().isBySolver())) { + items_to_install.push_back( pi ); + } + if ( pi.status().isKept() + && !(pi.status().isBySolver())) { + items_keep.push_back( pi ); + } + if ( pi.status().isToBeUninstalled() + && !(pi.status().isBySolver())) { + items_to_remove.push_back( pi ); + } + if ( pi.status().isLocked() + && !(pi.status().isBySolver())) { + items_locked.push_back( pi ); + } + + const auto &myRepo = pi.repository(); + const auto &myRepoInfo = myRepo.info(); + if ( repos.find( myRepo.id()) == repos.end() ) { + repos.insert( myRepo.id() ); + yOut << YAML::Value << YAML::BeginMap; + yOut << YAML::Key << "alias" << YAML::Value << myRepo.alias(); + yOut << YAML::Key << "url" << YAML::BeginSeq; + for ( auto itUrl = myRepoInfo.baseUrlsBegin(); itUrl != myRepoInfo.baseUrlsEnd(); ++itUrl ) { + yOut << YAML::Value << itUrl->asString(); + } + yOut << YAML::EndSeq; + yOut << YAML::Key << "path" << YAML::Value << myRepoInfo.path().asString(); + yOut << YAML::Key << "type" << YAML::Value << myRepoInfo.type().asString(); + yOut << YAML::Key << "generated" << YAML::Value << myRepo.generatedTimestamp().form( "%Y-%m-%d %H:%M:%S" ); + yOut << YAML::Key << "outdated" << YAML::Value << myRepo.suggestedExpirationTimestamp().form( "%Y-%m-%d %H:%M:%S" ); + yOut << YAML::Key << "priority" << YAML::Value << myRepoInfo.priority(); + yOut << YAML::Key << "file" << YAML::Value << str::Format("%1%.repo.gz") % repoFileNames[myRepo.id()->repoid]; + + yOut << YAML::EndMap; + } + + } + + yOut << YAML::EndSeq; + + yOut << YAML::Key << "arch" << YAML::Value << ZConfig::instance().systemArchitecture().asString() ; + yOut << YAML::Key << "solverTestcase" << YAML::Value << slvTestcaseName ; + yOut << YAML::Key << "solverResult" << YAML::Value << slvResult ; + + // RequestedLocales + const LocaleSet & addedLocales( satpool.getAddedRequestedLocales() ); + const LocaleSet & removedLocales( satpool.getRemovedRequestedLocales() ); + const LocaleSet & requestedLocales( satpool.getRequestedLocales() ); + + yOut << YAML::Key << "locales" << YAML::Value << YAML::BeginSeq ; + for ( const Locale& l : requestedLocales ) { + yOut << YAML::Value << YAML::BeginMap; + yOut << YAML::Key << "fate" << YAML::Value << ( addedLocales.count(l) ? "added" : "" ) ; + yOut << YAML::Key << "name" << YAML::Value << l.asString() ; + yOut << YAML::EndMap; + } + + for ( const Locale& l : removedLocales ) { + yOut << YAML::Value << YAML::BeginMap; + yOut << YAML::Key << "fate" << YAML::Value << "removed" ; + yOut << YAML::Key << "name" << YAML::Value << l.asString() ; + yOut << YAML::EndMap; + } + yOut << YAML::EndSeq; // locales + + // Vendor settings + yOut << YAML::Key << "vendors" << YAML::Value << YAML::BeginSeq ; + VendorAttr::instance().foreachVendorList( [&]( const VendorAttr::VendorList& vlist )->bool { + if ( ! vlist.empty() ) { + yOut << YAML::Value << YAML::BeginSeq; + for( const auto & v : vlist ) + yOut << YAML::Value << v ; + yOut << YAML::EndSeq; + } + return true; + } ); + yOut << YAML::EndSeq; // vendors + + // helper lambda to write a list of elements into a external file instead of the main file + const auto &writeListOrFile = [&]( const std::string &name, const auto &list, const auto &callback ) { + if ( list.size() > 10 ) { + const std::string fName = str::Format("zypp-%1%.yaml") % name; + yOut << YAML::Key << name << YAML::Value << fName; + + YAML::Emitter yOutFile; + callback( yOutFile, list ); + + std::ofstream fout( dumpPath+"/"+fName ); + fout << yOutFile.c_str(); + } else { + yOut << YAML::Key << name << YAML::Value ; + callback( yOut, list ); + } + }; + + // AutoInstalled + const auto &writeAutoInst = [] ( YAML::Emitter &out, const auto &autoInstalledList ) { + out << YAML::BeginSeq; + for ( IdString::IdType n : autoInstalledList ) { + out << YAML::Value << IdString(n).asString() ; + } + out << YAML::EndSeq; + }; + writeListOrFile( "autoinst", satpool.autoInstalled(), writeAutoInst ); + + // ModAlias + const auto &writeModalias = []( YAML::Emitter &out, const auto &modAliasList ){ + out << YAML::BeginSeq; + for ( const auto &modAlias : modAliasList ) { + out << YAML::Value << modAlias ; + } + out << YAML::EndSeq; + }; + writeListOrFile( "modalias", target::Modalias::instance().modaliasList(), writeModalias ); + + // Multiversion + const auto &writeMultiVersion = [] ( YAML::Emitter &out, const auto &multiversionList ) { + out << YAML::BeginSeq; + for ( const auto &multiver : multiversionList ) { + out << YAML::Value << multiver ; + } + out << YAML::EndSeq; + }; + writeListOrFile( "multiversion", ZConfig::instance().multiversionSpec(), writeMultiVersion ); + + + yOut << YAML::Key << "resolverFlags" << YAML::Value << YAML::BeginMap; + yOut << YAML::Key << "focus" << YAML::Value << asString( resolver.focus() ); + + addTag( "ignorealreadyrecommended", resolver.ignoreAlreadyRecommended() ); + addTag( "onlyRequires", resolver.onlyRequires() ); + addTag( "forceResolve", resolver.forceResolve() ); + + addTag( "cleandepsOnRemove", resolver.cleandepsOnRemove() ); + + addTag( "allowDowngrade", resolver.allowDowngrade() ); + addTag( "allowNameChange", resolver.allowNameChange() ); + addTag( "allowArchChange", resolver.allowArchChange() ); + addTag( "allowVendorChange", resolver.allowVendorChange() ); + + addTag( "dupAllowDowngrade", resolver.dupAllowDowngrade() ); + addTag( "dupAllowNameChange", resolver.dupAllowNameChange() ); + addTag( "dupAllowArchChange", resolver.dupAllowArchChange() ); + addTag( "dupAllowVendorChange", resolver.dupAllowVendorChange() ); + + + yOut << YAML::EndMap; // resolverFlags + yOut << YAML::EndMap; // setup + + yOut << YAML::Key << "trials" << YAML::Value << YAML::BeginSeq; + + yOut << YAML::Value << YAML::BeginMap << YAML::Key << "trial" << YAML::Value; + + yOut << YAML::BeginSeq; + + const auto &writeJobsToFile = [&]( const std::string &fName, const auto &data, const auto &cb ){ + yOut << YAML::Value << YAML::BeginMap; + yOut << YAML::Key << "include" << YAML::Value << fName; + yOut << YAML::EndMap; + + YAML::Emitter yOutFile; + yOutFile << YAML::BeginSeq; + cb( yOutFile, data ); + yOutFile << YAML::EndSeq; + + std::ofstream fout( dumpPath+"/"+fName ); + fout << yOutFile.c_str(); + }; + + // Multiversion + const auto &writePoolItemJobs = []( const std::string &jobName ){ + return [ &jobName ] ( YAML::Emitter &yOut, const PoolItemList &poolItems, bool shortInfo = false ) { + for ( const PoolItem & pi : poolItems ) { + yOut << YAML::Value << YAML::BeginMap; + + std::stringstream status; + status << pi.status(); + + yOut << YAML::Key << "job" << YAML::Value << jobName + << YAML::Key << "kind" << YAML::Value << pi.kind().asString() + << YAML::Key << "name" << YAML::Value << pi.name() + << YAML::Key << "status" << YAML::Value << status.str(); + if ( !shortInfo ) { + yOut << YAML::Key << "channel" << YAML::Value << pi.repoInfo().alias() + << YAML::Key << "arch" << YAML::Value << pi.arch().asString() + << YAML::Key << "version" << YAML::Value << pi.edition().version() + << YAML::Key << "release" << YAML::Value << pi.edition().release(); + } + yOut << YAML::EndMap; + } + }; + }; + + const auto &writeMapJob = []( YAML::Emitter &yOut, const std::string &name, const std::map &values = std::map() ){ + yOut << YAML::Value << YAML::BeginMap; + yOut << YAML::Key << "job" << YAML::Value << name; + for ( const auto &v : values ) + yOut << YAML::Key << v.first << YAML::Value << v.second; + yOut << YAML::EndMap; + }; + + writePoolItemJobs("install")( yOut, items_to_install ); + writePoolItemJobs("keep")( yOut, items_keep ); + writePoolItemJobs("uninstall")( yOut, items_to_remove, true ); + + if ( items_locked.size() ) + writeJobsToFile("zypp-locks.yaml", items_locked, writePoolItemJobs("lock") ); + + for ( const auto &v : resolver.extraRequires() ) + writeMapJob( yOut, "addRequire", { { "name", v.asString() } } ); + for ( const auto &v : SystemCheck::instance().requiredSystemCap() ) + writeMapJob( yOut, "addRequire", { { "name", v.asString() } } ); + + for ( const auto &v : resolver.extraConflicts() ) + writeMapJob( yOut, "addConflict", { { "name", v.asString() } } ); + for ( const auto &v : SystemCheck::instance().conflictSystemCap() ) + writeMapJob( yOut, "addConflict", { { "name", v.asString() } } ); + + for ( const auto &v : resolver.upgradeRepos() ) + writeMapJob( yOut, "upgradeRepo", { { "name", v.alias() } } ); + + if ( resolver.isUpgradeMode() ) + writeMapJob( yOut, "distupgrade" ); + + if ( resolver.isUpdateMode() ) + writeMapJob( yOut, "update" ); + + if ( resolver.isVerifyingMode() ) + writeMapJob( yOut, "verify" ); + + yOut << YAML::EndSeq; + yOut << YAML::EndMap; // trial + yOut << YAML::EndSeq; // trials list + yOut << YAML::EndMap; // trials + yOut << YAML::EndMap; // root + + std::ofstream fout( dumpPath+"/zypp-control.yaml" ); + fout << yOut.c_str(); + + MIL << "createTestcase done at " << dumpPath << endl; + return true; + } + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Testcase.h b/zypp/solver/detail/Testcase.h new file mode 100644 index 0000000..1766981 --- /dev/null +++ b/zypp/solver/detail/Testcase.h @@ -0,0 +1,64 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/solver/detail/Testcase.h + * +*/ + +#ifndef ZYPP_SOLVER_DETAIL_TESTCASE_H +#define ZYPP_SOLVER_DETAIL_TESTCASE_H +#ifndef ZYPP_USE_RESOLVER_INTERNALS +#error Do not directly include this file! +#else + +#include +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + + class Resolver; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Testcase + /** + * Generating a testcase of the current pool and solver state. + **/ + class ZYPP_API_DEPTESTOMATIC Testcase + { + private: + std::string dumpPath; // Path of the generated testcase + + public: + Testcase(); + Testcase( std::string path ); + ~Testcase(); + + bool createTestcase( Resolver & resolver, bool dumpPool = true, bool runSolver = true ); + }; + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_USE_RESOLVER_INTERNALS +#endif // ZYPP_SOLVER_DETAIL_TESTCASE_H diff --git a/zypp/solver/detail/Testcase_helix.cc b/zypp/solver/detail/Testcase_helix.cc new file mode 100644 index 0000000..22154dd --- /dev/null +++ b/zypp/solver/detail/Testcase_helix.cc @@ -0,0 +1,620 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/solver/detail/Testcase.cc + * +*/ +#include +#include +#include +#include + +#define ZYPP_USE_RESOLVER_INTERNALS + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +using std::endl; + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// + namespace solver + { ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + namespace detail + { /////////////////////////////////////////////////////////////////// + +#define TAB "\t" +#define TAB2 "\t\t" + +using namespace zypp::str; + +//--------------------------------------------------------------------------- + +inline std::string xml_escape( const std::string &text ) +{ + return zypp::xml::escape(text); +} + +inline std::string xml_tag_enclose( const std::string &text, const std::string &tag, bool escape = false ) +{ + std::string result; + result += "<" + tag + ">"; + + if ( escape) + result += xml_escape(text); + else + result += text; + + result += ""; + return result; +} + +template +std::string helixXML( const T &obj ); //undefined + +template<> +std::string helixXML( const Edition &edition ) +{ + std::stringstream str; + str << xml_tag_enclose(edition.version(), "version"); + if (!edition.release().empty()) + str << xml_tag_enclose(edition.release(), "release"); + if (edition.epoch() != Edition::noepoch) + str << xml_tag_enclose(numstring(edition.epoch()), "epoch"); + return str.str(); +} + +template<> +std::string helixXML( const Arch &arch ) +{ + std::stringstream str; + str << xml_tag_enclose(arch.asString(), "arch"); + return str.str(); +} + +template<> +std::string helixXML( const Capability &cap ) +{ + std::stringstream str; + CapDetail detail = cap.detail(); + if (detail.isSimple()) { + if (detail.isVersioned()) { + str << "" << endl; + } else { + str << "" << endl; + } + } else if (detail.isExpression()) { + if (detail.capRel() == CapDetail::CAP_AND + && detail.lhs().detail().isNamed() + && detail.rhs().detail().isNamed()) { + // packageand dependency + str << "" << endl; + } else if (detail.capRel() == CapDetail::CAP_NAMESPACE + && detail.lhs().id() == NAMESPACE_OTHERPROVIDERS) { + str << "" << endl; + } else { + // modalias ? + IdString packageName; + if (detail.capRel() == CapDetail::CAP_AND) { + packageName = IdString(detail.lhs().id()); + detail = detail.rhs().detail(); + } + if (detail.capRel() == CapDetail::CAP_NAMESPACE + && detail.lhs().id() == NAMESPACE_MODALIAS) { + str << "" << endl; + } else { + str << "" << endl; + } + } + } else { + str << "" << endl; + } + + return str.str(); +} + +template<> +std::string helixXML( const Capabilities &caps ) +{ + std::stringstream str; + Capabilities::const_iterator it = caps.begin(); + str << endl; + for ( ; it != caps.end(); ++it) + { + str << TAB2 << helixXML((*it)); + } + str << TAB; + return str.str(); +} + +template<> +std::string helixXML( const CapabilitySet &caps ) +{ + std::stringstream str; + CapabilitySet::const_iterator it = caps.begin(); + str << endl; + for ( ; it != caps.end(); ++it) + { + str << TAB2 << helixXML((*it)); + } + str << TAB; + return str.str(); +} + +inline std::string helixXML( const PoolItem & obj, Dep deptag_r ) +{ + std::stringstream out; + Capabilities caps( obj[deptag_r] ); + if ( ! caps.empty() ) + out << TAB << xml_tag_enclose(helixXML(caps), deptag_r.asString()) << endl; + return out.str(); +} + +std::string helixXML( const PoolItem & item ) +{ + std::stringstream str; + str << "<" << item.kind() << ">" << endl; + str << TAB << xml_tag_enclose( item.name(), "name", true ) << endl; + str << TAB << xml_tag_enclose( item.vendor().asString(), "vendor", true ) << endl; + str << TAB << xml_tag_enclose( item.buildtime().asSeconds(), "buildtime", true ) << endl; + if ( isKind( item ) ) { + str << TAB << "" << endl << TAB << "" << endl; + str << TAB2 << helixXML( item.arch() ) << endl; + str << TAB2 << helixXML( item.edition() ) << endl; + str << TAB << "" << endl << TAB << "" << endl; + } else { + str << TAB << helixXML( item.arch() ) << endl; + str << TAB << helixXML( item.edition() ) << endl; + } + str << helixXML( item, Dep::PROVIDES ); + str << helixXML( item, Dep::PREREQUIRES ); + str << helixXML( item, Dep::CONFLICTS ); + str << helixXML( item, Dep::OBSOLETES ); + str << helixXML( item, Dep::REQUIRES ); + str << helixXML( item, Dep::RECOMMENDS ); + str << helixXML( item, Dep::ENHANCES ); + str << helixXML( item, Dep::SUPPLEMENTS ); + str << helixXML( item, Dep::SUGGESTS ); + + str << "" << endl; + return str.str(); +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : HelixResolvable +/** + * Creates a file in helix format which includes all available + * or installed packages,patches,selections..... + **/ +class HelixResolvable : public base::ReferenceCounted, private base::NonCopyable{ + + private: + std::string dumpFile; // Path of the generated testcase + ofgzstream *file; + + public: + HelixResolvable (const std::string & path); + ~HelixResolvable (); + + void addResolvable (const PoolItem item) + { *file << helixXML (item); } + + std::string filename () + { return dumpFile; } +}; + +DEFINE_PTR_TYPE(HelixResolvable); +IMPL_PTR_TYPE(HelixResolvable); + +typedef std::map RepositoryTable; + +HelixResolvable::HelixResolvable(const std::string & path) + :dumpFile (path) +{ + file = new ofgzstream(path.c_str()); + if (!file) { + ZYPP_THROW (Exception( "Can't open " + path ) ); + } + + *file << "" << endl; +} + +HelixResolvable::~HelixResolvable() +{ + *file << "" << endl; + delete(file); +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : HelixControl +/** + * Creates a file in helix format which contains all controll + * action of a testcase ( file is known as *-test.xml) + **/ +class HelixControl { + + private: + std::string dumpFile; // Path of the generated testcase + std::ofstream *file; + bool _inSetup; + + public: + HelixControl (const std::string & controlPath, + const RepositoryTable & sourceTable, + const Arch & systemArchitecture, + const target::Modalias::ModaliasList & modaliasList, + const std::set & multiversionSpec, + const std::string & systemPath); + ~HelixControl (); + + void closeSetup() + { + if ( _inSetup ) + { + *file << "" << endl << "" << endl; + _inSetup = false; + } + } + + std::ostream & writeTag() + { return *file << (_inSetup ? TAB : ""); } + + void addTagIf( const std::string & tag_r, bool yesno_r = true ) + { + if ( yesno_r ) + writeTag() << "<" << tag_r << "/>" << endl; + } + + void installResolvable( const PoolItem & pi_r ); + void lockResolvable( const PoolItem & pi_r ); + void keepResolvable( const PoolItem & pi_r ); + void deleteResolvable( const PoolItem & pi_r ); + void addDependencies (const CapabilitySet &capRequire, const CapabilitySet &capConflict); + void addUpgradeRepos( const std::set & upgradeRepos_r ); + + std::string filename () { return dumpFile; } +}; + +HelixControl::HelixControl(const std::string & controlPath, + const RepositoryTable & repoTable, + const Arch & systemArchitecture, + const target::Modalias::ModaliasList & modaliasList, + const std::set & multiversionSpec, + const std::string & systemPath) + :dumpFile (controlPath) + ,_inSetup( true ) +{ + file = new std::ofstream(controlPath.c_str()); + if (!file) { + ZYPP_THROW (Exception( "Can't open " + controlPath ) ); + } + + *file << "" << endl + << "" << endl + << "" << endl + << "" << endl + << TAB << "" << endl << endl; + for ( RepositoryTable::const_iterator it = repoTable.begin(); + it != repoTable.end(); ++it ) { + RepoInfo repo = it->first.info(); + *file << TAB << "" << endl; + + *file << TAB << "first.id()) + << "-package.xml.gz\" name=\"" << repo.alias() << "\"" + << " priority=\"" << repo.priority() + << "\" />" << endl << endl; + } + + // HACK: directly access sat::pool + const sat::Pool & satpool( sat::Pool::instance() ); + + // RequestedLocales + const LocaleSet & addedLocales( satpool.getAddedRequestedLocales() ); + const LocaleSet & removedLocales( satpool.getRemovedRequestedLocales() ); + const LocaleSet & requestedLocales( satpool.getRequestedLocales() ); + + for ( Locale l : requestedLocales ) + { + const char * fate = ( addedLocales.count(l) ? "\" fate=\"added" : "" ); + *file << TAB << "" << endl; + } + for ( Locale l : removedLocales ) + { + *file << TAB << "" << endl; + } + + // AutoInstalled + for ( IdString::IdType n : satpool.autoInstalled() ) + { + *file << TAB << "" << endl; + } + + + + for_( it, modaliasList.begin(), modaliasList.end() ) { + *file << TAB << "" << endl; + } + + for_( it, multiversionSpec.begin(), multiversionSpec.end() ) { + *file << TAB << "" << endl; + } + + // setup continued outside.... +} + +HelixControl::~HelixControl() +{ + closeSetup(); // in case it is still open + *file << "" << endl + << "" << endl; + delete(file); +} + +void HelixControl::installResolvable( const PoolItem & pi_r ) +{ + *file << "" << endl; +} + +void HelixControl::lockResolvable( const PoolItem & pi_r ) +{ + *file << "" << endl; +} + +void HelixControl::keepResolvable( const PoolItem & pi_r ) +{ + *file << "" << endl; +} + +void HelixControl::deleteResolvable( const PoolItem & pi_r ) +{ + *file << "" << endl; +} + +void HelixControl::addDependencies (const CapabilitySet & capRequire, const CapabilitySet & capConflict) +{ + for (CapabilitySet::const_iterator iter = capRequire.begin(); iter != capRequire.end(); iter++) { + *file << "asString() << "\"" << "/>" << endl; + } + for (CapabilitySet::const_iterator iter = capConflict.begin(); iter != capConflict.end(); iter++) { + *file << "asString() << "\"" << "/>" << endl; + } +} + +void HelixControl::addUpgradeRepos( const std::set & upgradeRepos_r ) +{ + for_( it, upgradeRepos_r.begin(), upgradeRepos_r.end() ) + { + *file << "alias() << "\"/>" << endl; + } +} + +//--------------------------------------------------------------------------- + +Testcase::Testcase() + :dumpPath("/var/log/YaST2/solverTestcase") +{} + +Testcase::Testcase(const std::string & path) + :dumpPath(path) +{} + +Testcase::~Testcase() +{} + +bool Testcase::createTestcase(Resolver & resolver, bool dumpPool, bool runSolver) +{ + PathInfo path (dumpPath); + + if ( !path.isExist() ) { + if (zypp::filesystem::assert_dir (dumpPath)!=0) { + ERR << "Cannot create directory " << dumpPath << endl; + return false; + } + } else { + if (!path.isDir()) { + ERR << dumpPath << " is not a directory." << endl; + return false; + } + // remove old stuff if pool will be dump + if (dumpPool) + zypp::filesystem::clean_dir (dumpPath); + } + + if (runSolver) { + zypp::base::LogControl::TmpLineWriter tempRedirect; + zypp::base::LogControl::instance().logfile( dumpPath +"/y2log" ); + zypp::base::LogControl::TmpExcessive excessive; + + resolver.resolvePool(); + } + + ResPool pool = resolver.pool(); + RepositoryTable repoTable; + PoolItemList items_to_install; + PoolItemList items_to_remove; + PoolItemList items_locked; + PoolItemList items_keep; + HelixResolvable_Ptr system = NULL; + + if (dumpPool) + system = new HelixResolvable(dumpPath + "/solver-system.xml.gz"); + + for ( const PoolItem & pi : pool ) + { + if ( system && pi.status().isInstalled() ) { + // system channel + system->addResolvable( pi ); + } else { + // repo channels + Repository repo = pi.repository(); + if (dumpPool) { + if (repoTable.find (repo) == repoTable.end()) { + repoTable[repo] = new HelixResolvable(dumpPath + "/" + + str::numstring((long)repo.id()) + + "-package.xml.gz"); + } + repoTable[repo]->addResolvable( pi ); + } + } + + if ( pi.status().isToBeInstalled() + && !(pi.status().isBySolver())) { + items_to_install.push_back( pi ); + } + if ( pi.status().isKept() + && !(pi.status().isBySolver())) { + items_keep.push_back( pi ); + } + if ( pi.status().isToBeUninstalled() + && !(pi.status().isBySolver())) { + items_to_remove.push_back( pi ); + } + if ( pi.status().isLocked() + && !(pi.status().isBySolver())) { + items_locked.push_back( pi ); + } + } + + // writing control file "*-test.xml" + HelixControl control (dumpPath + "/solver-test.xml", + repoTable, + ZConfig::instance().systemArchitecture(), + target::Modalias::instance().modaliasList(), + ZConfig::instance().multiversionSpec(), + "solver-system.xml.gz"); + + // In : resolver flags,... + control.writeTag() << "" << endl; + + control.addTagIf( "ignorealreadyrecommended", resolver.ignoreAlreadyRecommended() ); + control.addTagIf( "onlyRequires", resolver.onlyRequires() ); + control.addTagIf( "forceResolve", resolver.forceResolve() ); + + control.addTagIf( "cleandepsOnRemove", resolver.cleandepsOnRemove() ); + + control.addTagIf( "allowDowngrade", resolver.allowDowngrade() ); + control.addTagIf( "allowNameChange", resolver.allowNameChange() ); + control.addTagIf( "allowArchChange", resolver.allowArchChange() ); + control.addTagIf( "allowVendorChange", resolver.allowVendorChange() ); + + control.addTagIf( "dupAllowDowngrade", resolver.dupAllowDowngrade() ); + control.addTagIf( "dupAllowNameChange", resolver.dupAllowNameChange() ); + control.addTagIf( "dupAllowArchChange", resolver.dupAllowArchChange() ); + control.addTagIf( "dupAllowVendorChange", resolver.dupAllowVendorChange() ); + + control.closeSetup(); + // Entering ... + + for ( const PoolItem & pi : items_to_install ) + { control.installResolvable( pi ); } + + for ( const PoolItem & pi : items_locked ) + { control.lockResolvable( pi ); } + + for ( const PoolItem & pi : items_keep ) + { control.keepResolvable( pi ); } + + for ( const PoolItem & pi : items_to_remove ) + { control.deleteResolvable( pi ); } + + control.addDependencies (resolver.extraRequires(), resolver.extraConflicts()); + control.addDependencies (SystemCheck::instance().requiredSystemCap(), + SystemCheck::instance().conflictSystemCap()); + control.addUpgradeRepos( resolver.upgradeRepos() ); + + control.addTagIf( "distupgrade", resolver.isUpgradeMode() ); + control.addTagIf( "update", resolver.isUpdateMode() ); + control.addTagIf( "verify", resolver.isVerifyingMode() ); + + return true; +} + + + /////////////////////////////////////////////////////////////////// + };// namespace detail + ///////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + };// namespace solver + /////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////// +};// namespace zypp +///////////////////////////////////////////////////////////////////////// diff --git a/zypp/solver/detail/Types.h b/zypp/solver/detail/Types.h new file mode 100644 index 0000000..373b510 --- /dev/null +++ b/zypp/solver/detail/Types.h @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */ +/* Types.h + * + * Copyright (C) 2005 SUSE Linux Products GmbH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * 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., 59 Temple Place, Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef ZYPP_SOLVER_DETAIL_TYPES_H +#define ZYPP_SOLVER_DETAIL_TYPES_H + +#include +#include + +///////////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////////// + namespace solver + { + ///////////////////////////////////////////////////////////////////// + namespace detail + { + // A few type names exposed in the public API + // + class Resolver; + using ResolverInternal = Resolver; ///< Preferred name in API + + struct ItemCapKind; + using ItemCapKindList = std::list; + + DEFINE_PTR_TYPE(SolverQueueItem); + using SolverQueueItemList = std::list; + + DEFINE_PTR_TYPE(SolutionAction); + using SolutionActionList = std::list; + + } // namespace detail + ///////////////////////////////////////////////////////////////////// + } // namespace solver + /////////////////////////////////////////////////////////////////////// +} // namespace zypp +///////////////////////////////////////////////////////////////////////// +#endif // ZYPP_SOLVER_DETAIL_TYPES_H diff --git a/zypp/target/CommitPackageCache.cc b/zypp/target/CommitPackageCache.cc new file mode 100644 index 0000000..1a5dee8 --- /dev/null +++ b/zypp/target/CommitPackageCache.cc @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/CommitPackageCache.cc + * +*/ +#include +#include +#include +#include + +#include +#include +#include + +using std::endl; + +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace { + /////////////////////////////////////////////////////////////////// + /// \class QueryInstalledEditionHelper + /// \short Helper for PackageProvider queries during download. + /////////////////////////////////////////////////////////////////// + struct QueryInstalledEditionHelper + { + bool operator()( const std::string & name_r, const Edition & ed_r, const Arch & arch_r ) const + { + rpm::librpmDb::db_const_iterator it; + for ( it.findByName( name_r ); *it; ++it ) + { + if ( arch_r == it->tag_arch() + && ( ed_r == Edition::noedition || ed_r == it->tag_edition() ) ) + { + return true; + } + } + return false; + } + }; + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // class RepoProvidePackage + // + /////////////////////////////////////////////////////////////////// + + struct RepoProvidePackage::Impl + { + repo::RepoMediaAccess _access; + std::list _repos; + repo::PackageProviderPolicy _packageProviderPolicy; + }; + + RepoProvidePackage::RepoProvidePackage() + : _impl( new Impl ) + { + const ResPool & pool( ResPool::instance() ); + _impl->_repos.insert( _impl->_repos.begin(), pool.knownRepositoriesBegin(), pool.knownRepositoriesEnd() ); + _impl->_packageProviderPolicy.queryInstalledCB( QueryInstalledEditionHelper() ); + } + + RepoProvidePackage::~RepoProvidePackage() + {} + + ManagedFile RepoProvidePackage::operator()( const PoolItem & pi_r, bool fromCache_r ) + { + ManagedFile ret; + if ( fromCache_r ) + { + repo::PackageProvider pkgProvider( _impl->_access, pi_r, _impl->_packageProviderPolicy ); + ret = pkgProvider.providePackageFromCache(); + } + else if ( pi_r.isKind() ) // may make use of deltas + { + repo::DeltaCandidates deltas( _impl->_repos, pi_r.name() ); + repo::PackageProvider pkgProvider( _impl->_access, pi_r, deltas, _impl->_packageProviderPolicy ); + return pkgProvider.providePackage(); + } + else // SrcPackage or throws + { + repo::PackageProvider pkgProvider( _impl->_access, pi_r, _impl->_packageProviderPolicy ); + return pkgProvider.providePackage(); + } + return ret; + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CommitPackageCache + // + /////////////////////////////////////////////////////////////////// + + CommitPackageCache::CommitPackageCache( Impl * pimpl_r ) + : _pimpl( pimpl_r ) + { + assert( _pimpl ); + } + + CommitPackageCache::CommitPackageCache( PackageProvider packageProvider_r ) + { + if ( getenv("ZYPP_COMMIT_NO_PACKAGE_CACHE") ) + { + MIL << "$ZYPP_COMMIT_NO_PACKAGE_CACHE is set." << endl; + _pimpl.reset( new Impl( std::move(packageProvider_r) ) ); // no cache + } + else + { + _pimpl.reset( new CommitPackageCacheReadAhead( std::move(packageProvider_r) ) ); + } + assert( _pimpl ); + } + + CommitPackageCache::CommitPackageCache( const Pathname & /*rootDir_r*/, + const PackageProvider & packageProvider_r ) + : CommitPackageCache( packageProvider_r ) + {} + + CommitPackageCache::~CommitPackageCache() + {} + + void CommitPackageCache::setCommitList( std::vector commitList_r ) + { _pimpl->setCommitList( std::move(commitList_r) ); } + + ManagedFile CommitPackageCache::get( const PoolItem & citem_r ) + { return _pimpl->get( citem_r ); } + + bool CommitPackageCache::preloaded() const + { return _pimpl->preloaded(); } + + void CommitPackageCache::preloaded( bool newval_r ) + { _pimpl->preloaded( newval_r ); } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const CommitPackageCache & obj ) + { return str << *obj._pimpl; } + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/CommitPackageCache.h b/zypp/target/CommitPackageCache.h new file mode 100644 index 0000000..bf50c92 --- /dev/null +++ b/zypp/target/CommitPackageCache.h @@ -0,0 +1,119 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/CommitPackageCache.h + * +*/ +#ifndef ZYPP_TARGET_COMMITPACKAGECACHE_H +#define ZYPP_TARGET_COMMITPACKAGECACHE_H + +#include + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class RepoProvidePackage + /// \short Default PackageProvider for \ref CommitPackageCache + /// + /// \p pool_r \ref ResPool used to get candidates + /// \p pi item to be commited + /////////////////////////////////////////////////////////////////// + class ZYPP_API RepoProvidePackage + { + public: + RepoProvidePackage(); + ~RepoProvidePackage(); + + /** Provide package optionally fron cache only. */ + ManagedFile operator()( const PoolItem & pi, bool fromCache_r ); + + private: + struct Impl; + RW_pointer _impl; + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CommitPackageCache + // + /** Target::commit helper optimizing package provision. + */ + class ZYPP_API CommitPackageCache + { + friend std::ostream & operator<<( std::ostream & str, const CommitPackageCache & obj ); + + public: + using PackageProvider = function; + + public: + /** Ctor */ + CommitPackageCache(PackageProvider packageProvider_r = RepoProvidePackage() ); + + /** \deprecated Legacy Ctor; Pathname rootDir_r is not used. + * The repositories RepoInfo::packagesPath defines the cache location. + */ + CommitPackageCache( const Pathname & /*rootDir_r*/, const PackageProvider & packageProvider_r = RepoProvidePackage() ) ZYPP_DEPRECATED; + + /** Dtor */ + ~CommitPackageCache(); + + public: + /** Download(commit) sequence of solvables to compute read ahead. */ + void setCommitList( std::vector commitList_r ); + /** \overload */ + template + void setCommitList( TIterator begin_r, TIterator end_r ) + { setCommitList( std::vector( begin_r, end_r ) ); } + + /** Provide a package. */ + ManagedFile get( const PoolItem & citem_r ); + /** \overload */ + ManagedFile get( sat::Solvable citem_r ) + { return get( PoolItem(citem_r) ); } + + /** Whether preloaded hint is set. + * If preloaded the cache tries to avoid trigering the infoInCache CB, + * based on the assumption this was already done when preloading the cache. + */ + bool preloaded() const; + /** Set preloaded hint. */ + void preloaded( bool newval_r ); + + public: + /** Implementation. */ + class Impl; + /** Ctor taking an implementation. */ + explicit CommitPackageCache( Impl * pimpl_r ); + private: + /** Pointer to implementation. */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CommitPackageCache Stream output */ + std::ostream & operator<<( std::ostream & str, const CommitPackageCache & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_COMMITPACKAGECACHE_H diff --git a/zypp/target/CommitPackageCacheImpl.cc b/zypp/target/CommitPackageCacheImpl.cc new file mode 100644 index 0000000..62d8311 --- /dev/null +++ b/zypp/target/CommitPackageCacheImpl.cc @@ -0,0 +1,33 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/CommitPackageCacheImpl.cc + * +*/ +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/CommitPackageCacheImpl.h b/zypp/target/CommitPackageCacheImpl.h new file mode 100644 index 0000000..95ac849 --- /dev/null +++ b/zypp/target/CommitPackageCacheImpl.h @@ -0,0 +1,122 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/CommitPackageCacheImpl.h + * +*/ +#ifndef ZYPP_TARGET_COMMITPACKAGECACHEIMPL_H +#define ZYPP_TARGET_COMMITPACKAGECACHEIMPL_H + +#include +#include + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CommitPackageCache::Impl + // + /** Base for CommitPackageCache implementations (implements no chache). + * + * All packages are directly retrieved from the source via the + * PackageProvider passed to the ctor. The PackageProvider is expected + * to throw or return an empty ManagedFile if the package can't be provided. + */ + class CommitPackageCache::Impl + { + public: + using PackageProvider = CommitPackageCache::PackageProvider; + + public: + Impl( PackageProvider &&packageProvider_r ) + : _packageProvider(std::move( packageProvider_r )) + {} + + virtual ~Impl() + {} + + public: + /** Provide the package. + * Derived classes overload this. + */ + virtual ManagedFile get( const PoolItem & citem_r ) + { + return sourceProvidePackage( citem_r ); + } + + void setCommitList( std::vector commitList_r ) + { _commitList = std::move(commitList_r); } + + const std::vector & commitList() const + { return _commitList; } + + bool preloaded() const + { return _preloaded; } + + void preloaded( bool newval_r ) + { _preloaded = newval_r; } + + protected: + /** Let the Source provide the package. */ + virtual ManagedFile sourceProvidePackage( const PoolItem & pi ) const + { + if ( ! _packageProvider ) + { + ZYPP_THROW( Exception("No package provider configured.") ); + } + + ManagedFile ret( _packageProvider( pi, /*cached only*/false ) ); + if ( ret.value().empty() ) + { + ZYPP_THROW( Exception("Package provider failed.") ); + } + + return ret; + } + + /** Let the Source provide an already cached package. */ + virtual ManagedFile sourceProvideCachedPackage( const PoolItem & pi ) const + { + if ( ! _packageProvider ) + { + ZYPP_THROW( Exception("No package provider configured.") ); + } + + return _packageProvider( pi, /*cached only*/true ); + } + + private: + std::vector _commitList; + PackageProvider _packageProvider; + DefaultIntegral _preloaded; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates CommitPackageCache::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const CommitPackageCache::Impl & obj ) + { + return str << "CommitPackageCache::Impl"; + } + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_COMMITPACKAGECACHEIMPL_H diff --git a/zypp/target/CommitPackageCacheReadAhead.cc b/zypp/target/CommitPackageCacheReadAhead.cc new file mode 100644 index 0000000..8c6433b --- /dev/null +++ b/zypp/target/CommitPackageCacheReadAhead.cc @@ -0,0 +1,186 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/CommitPackageCacheReadAhead.cc + * +*/ +#include + +#include +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : IMediaKey + // + /////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const IMediaKey & obj ) + { + return str << "[S" << obj._repo.id() << ":" << obj._mediaNr << "]" + << " " << obj._repo.info().alias(); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CommitPackageCacheReadAhead + // + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CommitPackageCacheReadAhead::CommitPackageCacheReadAhead + // METHOD TYPE : Ctor + // + CommitPackageCacheReadAhead::CommitPackageCacheReadAhead( PackageProvider packageProvider_r ) + : CommitPackageCache::Impl( std::move(packageProvider_r) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CommitPackageCacheReadAhead::onInteractiveMedia + // METHOD TYPE : bool + // + bool CommitPackageCacheReadAhead::onInteractiveMedia( const PoolItem & pi ) const + { + if ( pi->mediaNr() == 0 ) // no media access at all + return false; + if ( pi->repoInfo().baseUrlsEmpty() ) + return false; // no Url - should actually not happen + std::string scheme( pi->repoInfo().baseUrlsBegin()->getScheme() ); + return ( scheme == "dvd" || scheme == "cd" ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CommitPackageCacheReadAhead::cacheLastInteractive + // METHOD TYPE : void + // + void CommitPackageCacheReadAhead::cacheLastInteractive( const PoolItem & citem_r ) + { + // Fill cache errors are never proagated. + try + { + doCacheLastInteractive( citem_r ); + } + catch ( const Exception & excpt_r ) + { + ZYPP_CAUGHT( excpt_r ); + WAR << "Failed to cache " << _lastInteractive << endl; + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CommitPackageCacheReadAhead::doCacheLastInteractive + // METHOD TYPE : void + // + void CommitPackageCacheReadAhead::doCacheLastInteractive( const PoolItem & citem_r ) + { + unsigned addToCache = 0; + bool sawCitem = false; + + // Collect all remaining packages to install from + // _lastInteractive media. (just the PoolItem data) + for_( it, commitList().begin(), commitList().end() ) + { + PoolItem pi( *it ); + if ( ! sawCitem ) + { + if ( pi == citem_r ) + sawCitem = true; + continue; + } + if ( IMediaKey( pi ) == _lastInteractive + && pi.status().isToBeInstalled() + && isKind(pi.resolvable()) ) + { + if ( ! pi->asKind()->isCached() ) + { + ManagedFile fromSource( sourceProvidePackage( pi ) ); + if ( fromSource->empty() ) + { + ERR << "Copy to cache failed on " << fromSource << endl; + ZYPP_THROW( Exception("Copy to cache failed.") ); + } + fromSource.resetDispose(); // keep the package file in the cache + ++addToCache; + } + } + } + + if ( addToCache ) + MIL << "Cached " << _lastInteractive << ": " << addToCache << " items." << endl; + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : CommitPackageCacheReadAhead::get + // METHOD TYPE : ManagedFile + // + ManagedFile CommitPackageCacheReadAhead::get( const PoolItem & citem_r ) + { + ManagedFile ret; + if ( preloaded() ) + { + // Check whether it's cached. + ManagedFile ret( sourceProvideCachedPackage( citem_r ) ); + if ( ! ret->empty() ) + return ret; + } + // else: we head for sourceProvidePackage(), even if the package + // was cached. The actual difference is that sourceProvidePackage + // will trigger the infoInCache CB that informs the application. + // Once the cache is preloaded we try to avoid this CB. + + + // Preload cache if a CD/DVD change is pending to avoid + // switching back and forth... + if ( onInteractiveMedia( citem_r ) ) + { + ret = sourceProvideCachedPackage( citem_r ); + if ( ! ret->empty() ) + return ret; + + IMediaKey current( citem_r ); + if ( current != _lastInteractive ) + { + if ( _lastInteractive != IMediaKey() ) + { + cacheLastInteractive( citem_r ); + } + + DBG << "Interactive change [" << ++_dbgChanges << "] from " << _lastInteractive << " to " << current << endl; + _lastInteractive = current; + } + } + + // Provide and return the file from media. + return sourceProvidePackage( citem_r ); + } + + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/CommitPackageCacheReadAhead.h b/zypp/target/CommitPackageCacheReadAhead.h new file mode 100644 index 0000000..a2c8d4e --- /dev/null +++ b/zypp/target/CommitPackageCacheReadAhead.h @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/CommitPackageCacheReadAhead.h + * +*/ +#ifndef ZYPP_TARGET_COMMITPACKAGECACHEREADAHEAD_H +#define ZYPP_TARGET_COMMITPACKAGECACHEREADAHEAD_H + +#include + +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : IMediaKey + // + /** Helper storing a source id and media number. */ + struct IMediaKey + { + IMediaKey() + {} + + explicit + IMediaKey( const PoolItem & obj_r ) + : _repo( obj_r->repository() ) + , _mediaNr( obj_r->mediaNr() ) + {} + + explicit + IMediaKey( const ResObject::constPtr & obj_r ) + : _repo( obj_r->repository() ) + , _mediaNr( obj_r->mediaNr() ) + {} + + IMediaKey( const Repository & repo, unsigned mediaNr_r ) + : _repo( repo ) + , _mediaNr( mediaNr_r ) + {} + + bool operator==( const IMediaKey & rhs ) const + { return( _repo == rhs._repo && _mediaNr == rhs._mediaNr ); } + + bool operator!=( const IMediaKey & rhs ) const + { return ! operator==( rhs ); } + + bool operator<( const IMediaKey & rhs ) const + { + return( _repo.id() < rhs._repo.id() + || ( _repo.id() == rhs._repo.id() + && _mediaNr < rhs._mediaNr ) ); + } + + Repository _repo; + DefaultIntegral _mediaNr; + }; + /////////////////////////////////////////////////////////////////// + + std::ostream & operator<<( std::ostream & str, const IMediaKey & obj ); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : CommitPackageCacheReadAhead + // + /** */ + class CommitPackageCacheReadAhead : public CommitPackageCache::Impl + { + public: + CommitPackageCacheReadAhead(PackageProvider packageProvider_r ); + + public: + /** Provide the package. Either from Source or from cache. */ + ManagedFile get( const PoolItem & citem_r ) override; + + private: + /** Return whether \a pi is located on a CD/DVD */ + bool onInteractiveMedia( const PoolItem & pi ) const; + + private: + /** Fill the cache. + * Called before changing from one interactive media to another. + * Performs the read ahead of packages trying to avoid the necessity + * of switching back to the current media later. + */ + void cacheLastInteractive( const PoolItem & citem_r ); + + /** cacheLastInteractive helper . */ + void doCacheLastInteractive( const PoolItem & citem_r ); + + private: + DefaultIntegral _dbgChanges; + IMediaKey _lastInteractive; + //Pathname _rootDir; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_COMMITPACKAGECACHEREADAHEAD_H diff --git a/zypp/target/HardLocksFile.cc b/zypp/target/HardLocksFile.cc new file mode 100644 index 0000000..2a7540c --- /dev/null +++ b/zypp/target/HardLocksFile.cc @@ -0,0 +1,87 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/HardLocksFile.cc + * +*/ +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + void HardLocksFile::load( const Pathname & file_r, Data & data_r ) + { + PathInfo pi( file_r ); + if ( ! pi.isFile() ) + { + WAR << "Can't read " << pi << endl; + return; + } + + readPoolQueriesFromFile( file_r, std::back_inserter( data_r ) ); + + MIL << "Read " << pi << endl; + } + + void HardLocksFile::store( const Pathname & file_r, const Data & data_r ) + { + filesystem::TmpFile tmp( filesystem::TmpFile::makeSibling( file_r ) ); + filesystem::chmod( tmp.path(), 0644 ); + + writePoolQueriesToFile( tmp.path(), data_r.begin(), data_r.end() ); + + if ( true ) // by now: no error info from writePoolQueriesToFile + { + filesystem::rename( tmp.path(), file_r ); + MIL << "Wrote " << PathInfo(file_r) << endl; + } + else + { + ERR << "Can't write " << PathInfo(tmp.path()) << endl; + } + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const HardLocksFile & obj ) + { + str << obj.file() << ' '; + if ( obj._dataPtr ) + str << obj.data(); + else + str << "(unloaded)"; + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/HardLocksFile.h b/zypp/target/HardLocksFile.h new file mode 100644 index 0000000..5cf03d3 --- /dev/null +++ b/zypp/target/HardLocksFile.h @@ -0,0 +1,127 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/HardLocksFile.h + * +*/ +#ifndef ZYPP_TARGET_HARDLOCKSFILE_H +#define ZYPP_TARGET_HARDLOCKSFILE_H + +#include +#include + +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : HardLocksFile + // + /** Save and restore hardlocks. + */ + class HardLocksFile + { + friend std::ostream & operator<<( std::ostream & str, const HardLocksFile & obj ); + public: + + using Data = pool::PoolTraits::HardLockQueries; + + public: + /** Ctor taking the file to read/write. */ + HardLocksFile( Pathname file_r ) + : _file(std::move( file_r )) + {} + + /** Return the file path. */ + const Pathname & file() const + { return _file; } + + /** Return the data. + * The file is read once on demand. Returns empty \ref Data if + * the file does not exist or is not readable. + */ + const Data & data() const + { + if ( !_dataPtr ) + { + _dataPtr.reset( new Data ); + Data & mydata( *_dataPtr ); + load( _file, mydata ); + } + return *_dataPtr; + } + + /** Store new \ref Data. + * Write the new \ref Data to file, unless we know it + * did not change. The directory containing file must + * exist. + */ + void setData( const Data & data_r ) + { + if ( !_dataPtr ) + { + if ( data_r.empty() ) + return; // bsc#1096803: Prevent against empty commit without Target having been been loaded (!_dataPtr ) + _dataPtr.reset( new Data ); + } + + if ( differs( *_dataPtr, data_r ) ) + { + store( _file, data_r ); + *_dataPtr = data_r; + } + } + + private: + /** Helper testing whether two \ref Data differ. */ + bool differs( const Data & lhs, const Data & rhs ) const + { + if ( lhs.size() != rhs.size() ) + return true; + // Complete diff is too expensive and not necessary here. + // Just check for the same sequence of items. + Data::const_iterator rit = rhs.begin(); + for_( it, lhs.begin(), lhs.end() ) + { + if ( *it != *rit ) + return true; + ++rit; + } + return false; + } + /** Read \ref Data from \c file_r. */ + static void load( const Pathname & file_r, Data & data_r ); + /** Write \ref Data to \c file_r. */ + static void store( const Pathname & file_r, const Data & data_r ); + + private: + Pathname _file; + mutable scoped_ptr _dataPtr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates HardLocksFile Stream output */ + std::ostream & operator<<( std::ostream & str, const HardLocksFile & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_HARDLOCKSFILE_H diff --git a/zypp/target/RequestedLocalesFile.cc b/zypp/target/RequestedLocalesFile.cc new file mode 100644 index 0000000..98fa756 --- /dev/null +++ b/zypp/target/RequestedLocalesFile.cc @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/RequestedLocalesFile.cc + * +*/ +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + void RequestedLocalesFile::load( const Pathname & file_r, LocaleSet & locales_r ) + { + PathInfo pi( file_r ); + if ( ! pi.isFile() ) + { + WAR << "Can't read " << pi << endl; + return; + } + std::ifstream infile( file_r.c_str() ); + for( iostr::EachLine in( infile ); in; in.next() ) + { + std::string l( str::trim(*in) ); + if ( ! l.empty() && l[0] != '#' ) + { + locales_r.insert( Locale(l) ); + } + } + MIL << "Read " << pi << endl; + } + + void RequestedLocalesFile::store( const Pathname & file_r, const LocaleSet & locales_r ) + { + filesystem::TmpFile tmp( filesystem::TmpFile::makeSibling( file_r ) ); + filesystem::chmod( tmp.path(), 0644 ); + + std::ofstream outs( tmp.path().c_str() ); + outs << "# zypp::RequestedLocales generated " << Date::now() << endl; + dumpRange( outs, locales_r.begin(), locales_r.end(), "#", "\n", "\n", "\n", "#\n" ); + outs.close(); + + if ( outs.good() ) + { + filesystem::rename( tmp.path(), file_r ); + MIL << "Wrote " << PathInfo(file_r) << endl; + } + else + { + ERR << "Can't write " << PathInfo(tmp.path()) << endl; + } + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const RequestedLocalesFile & obj ) + { + str << obj.file() << ' '; + if ( obj._localesPtr ) + str << obj.locales(); + else + str << "(unloaded)"; + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/RequestedLocalesFile.h b/zypp/target/RequestedLocalesFile.h new file mode 100644 index 0000000..87b13ad --- /dev/null +++ b/zypp/target/RequestedLocalesFile.h @@ -0,0 +1,114 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/RequestedLocalesFile.h + * +*/ +#ifndef ZYPP_TARGET_REQUESTEDLOCALESFILE_H +#define ZYPP_TARGET_REQUESTEDLOCALESFILE_H + +#include +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RequestedLocalesFile + // + /** Save and restore locale set from file. + */ + class RequestedLocalesFile + { + friend std::ostream & operator<<( std::ostream & str, const RequestedLocalesFile & obj ); + + public: + /** Ctor taking the file to read/write. */ + RequestedLocalesFile( Pathname file_r ) + : _file(std::move( file_r )) + {} + + /** Return the file path. */ + const Pathname & file() const + { return _file; } + + /** Return the loacale set. + * The file is read once on demand. returns an empty set if + * the file does not exist or is not readable. + */ + const LocaleSet & locales() const + { + if ( !_localesPtr ) + { + _localesPtr.reset( new LocaleSet ); + LocaleSet & ls( *_localesPtr ); + load( _file, ls ); + } + return *_localesPtr; + } + + /** Store a new locale set. + * Write the new localeset to file, unless we know it + * did not change. The directory containing file must exist. + */ + void setLocales( const LocaleSet & locales_r ) + { + if ( !_localesPtr ) + _localesPtr.reset( new LocaleSet ); + + if ( differs( *_localesPtr, locales_r ) ) + { + store( _file, locales_r ); + *_localesPtr = locales_r; + } + } + + private: + /** Helper testing whether two \ref LocaleSet differ. */ + bool differs( const LocaleSet & lhs, const LocaleSet & rhs ) const + { + if ( lhs.size() != rhs.size() ) + return true; + for_( it, lhs.begin(), lhs.end() ) + { + if ( rhs.find( *it ) == rhs.end() ) + return true; + } + return false; + } + /** Read \ref LocaleSet from \c file_r. */ + static void load( const Pathname & file_r, LocaleSet & locales_r ); + /** Write \ref LocaleSet to \c file_r. */ + static void store( const Pathname & file_r, const LocaleSet & locales_r ); + + private: + Pathname _file; + mutable scoped_ptr _localesPtr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates RequestedLocalesFile Stream output */ + std::ostream & operator<<( std::ostream & str, const RequestedLocalesFile & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_REQUESTEDLOCALESFILE_H diff --git a/zypp/target/RpmPostTransCollector.cc b/zypp/target/RpmPostTransCollector.cc new file mode 100644 index 0000000..3c21183 --- /dev/null +++ b/zypp/target/RpmPostTransCollector.cc @@ -0,0 +1,444 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/RpmPostTransCollector.cc + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "zypp::posttrans" + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace target + { + /////////////////////////////////////////////////////////////////// + /// \class RpmPostTransCollector::Impl + /// \brief RpmPostTransCollector implementation. + /////////////////////////////////////////////////////////////////// + class RpmPostTransCollector::Impl : private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const Impl & obj ); + friend std::ostream & dumpOn( std::ostream & str, const Impl & obj ); + + /// <%posttrans script basename, pkgname> pairs. + using ScriptList = std::list< std::pair >; + + /// Data regarding the dumpfile used if `rpm --runposttrans` is supported + struct Dumpfile + { + Dumpfile( Pathname dumpfile_r ) + : _dumpfile { std::move(dumpfile_r) } + {} + + Pathname _dumpfile; ///< The file holding the collected dump_posttrans: lines. + size_t _numscripts = 0; ///< Number of scripts we collected (roughly estimated) + bool _runposttrans = true; ///< Set to false if rpm lost --runposttrans support during transaction. + }; + + public: + Impl( Pathname &&root_r ) + : _root(std::move( root_r )) + , _myJobReport { "cmdout", "%posttrans" } + {} + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + ~Impl() + {} + + bool hasPosttransScript( const Pathname & rpmPackage_r ) + { return bool(getHeaderIfPosttrans( rpmPackage_r )); } + + void collectPosttransInfo( const Pathname & rpmPackage_r, const std::vector & runposttrans_r ) + { if ( not collectDumpPosttransLines( runposttrans_r ) ) collectScriptForPackage( rpmPackage_r ); } + + void collectPosttransInfo( const std::vector & runposttrans_r ) + { collectDumpPosttransLines( runposttrans_r ); } + + void collectScriptFromHeader( const rpm::RpmHeader::constPtr& pkg ) + { + if ( pkg ) { + if ( not _scripts ) { + _scripts = ScriptList(); + } + + filesystem::TmpFile script( tmpDir(), pkg->ident() ); + filesystem::addmod( script.path(), 0500 ); // script must be executable + script.autoCleanup( false ); // no autodelete; within a tmpdir + { + std::ofstream out( script.path().c_str() ); + out << "#! " << pkg->tag_posttransprog() << endl + << pkg->tag_posttrans() << endl; + } + + _scripts->push_back( std::make_pair( script.path().basename(), pkg->tag_name() ) ); + MIL << "COLLECT posttrans: '" << PathInfo( script.path() ) << "' for package: '" << pkg->tag_name() << "'" << endl; + } + } + + void collectScriptForPackage( const Pathname & rpmPackage_r ) + { collectScriptFromHeader( getHeaderIfPosttrans( rpmPackage_r ) ); } + + /** Return whether runposttrans lines were collected. + * If runposttrans is supported, rpm issues at least one 'dump_posttrans: enabled' line with + * every install/remove. If no line is issued, rpm does not support --runposttrans. Interesting + * for \ref executeScripts is whether the final call to rpm supported it. + */ + bool collectDumpPosttransLines( const std::vector & runposttrans_r ) + { + if ( runposttrans_r.empty() ) { + if ( _dumpfile and _dumpfile->_runposttrans ) { + MIL << "LOST dump_posttrans support" << endl; + _dumpfile->_runposttrans = false; // rpm was downgraded to a version not supporing --runposttrans + } + return false; + } + + if ( not _dumpfile ) { + filesystem::TmpFile dumpfile( tmpDir(), "dumpfile" ); + filesystem::addmod( dumpfile.path(), 0400 ); // dumpfile must be readable + dumpfile.autoCleanup( false ); // no autodelete; within a tmpdir + _dumpfile = Dumpfile( dumpfile.path() ); + MIL << "COLLECT dump_posttrans to '" << _dumpfile->_dumpfile << endl; + } + + std::ofstream out( _dumpfile->_dumpfile.c_str(), std::ios_base::app ); + for ( const auto & s : runposttrans_r ) { + out << s << endl; + } + _dumpfile->_numscripts += runposttrans_r.size(); + MIL << "COLLECT " << runposttrans_r.size() << " dump_posttrans lines" << endl; + return true; + } + + /** Execute the remembered scripts. + * Crucial is the mixed case, where scripts and dumpfile are present at the end. + * If rpm was updated in the transaction to a version supporting --runposttrans, + * run scripts and then the dumpfile. + * If rpm was downgraded in the transaction to a version no longer supporting + * --runposttrans, we need to extract missing %posttrans scripts from the dumpfile + * and execute them before the collected scripts. + */ + void executeScripts( rpm::RpmDb & rpm_r ) + { + if ( _dumpfile && not _dumpfile->_runposttrans ) { + // Here a downgraded rpm lost the ability to --runposttrans. Extract at least any + // missing %posttrans scripts collected in _dumpfile and prepend them to the _scripts. + MIL << "Extract missing %posttrans scripts and prepend them to the scripts." << endl; + + // collectScriptFromHeader appends to _scripts, so we save here and append again later + std::optional savedscripts; + if ( _scripts ) { + savedscripts = std::move(*_scripts); + _scripts = std::nullopt; + } + + rpm::librpmDb::db_const_iterator it; + recallFromDumpfile( _dumpfile->_dumpfile, [&]( const std::string& n_r, const std::string& v_r, const std::string& r_r, const std::string& a_r ) -> void { + if ( it.findPackage( n_r, Edition( v_r, r_r ) ) && headerHasPosttrans( *it ) ) + collectScriptFromHeader( *it ); + } ); + + // append any savedscripts + if ( savedscripts ) { + if ( _scripts ) { + _scripts->splice( _scripts->end(), *savedscripts ); + } else { + _scripts = std::move(*savedscripts); + } + } + _dumpfile = std::nullopt; + } + + if ( not ( _scripts || _dumpfile ) ) + return; // Nothing todo + + // ProgressReport counting the scripts ( 0:preparation, 1->n:for n scripts, n+1: indicate success) + callback::SendReport report; + ProgressData scriptProgress( [&]() -> ProgressData::value_type { + ProgressData::value_type ret = 1; + if ( _scripts ) + ret += _scripts->size(); + if ( _dumpfile ) + ret += _dumpfile->_numscripts; + return ret; + }() ); + scriptProgress.sendTo( ProgressReportAdaptor( ProgressData::ReceiverFnc(), report ) ); + // Translator: progress bar label + std::string scriptProgressName { _("Running post-transaction scripts") }; + // Translator: progress bar label; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' + str::Format fmtScriptProgressRun { _("Running %1% script") }; + // Translator: headline; %1% is a script identifier like '%posttrans(mypackage-2-0.noarch)' + str::Format fmtRipoff { _("%1% script output:") }; + std::string sendRipoff; + + HistoryLog historylog; + + // lambda to prepare reports for a new script + auto startNewScript = [&] ( const std::string & scriptident_r ) -> void { + // scriptident_r : script identifier like "%transfiletriggerpostun(istrigger-2-0.noarch)" + sendRipoff = fmtRipoff % scriptident_r; + scriptProgress.name( fmtScriptProgressRun % scriptident_r ); + scriptProgress.incr(); + }; + + // lambda to send script output to reports + auto sendScriptOutput = [&] ( const std::string & line_r ) -> void { + OnScopeExit cleanup; // in case we need it + if ( not sendRipoff.empty() ) { + historylog.comment( sendRipoff, true /*timestamp*/); + _myJobReport.set( "ripoff", std::cref(sendRipoff) ); + cleanup.setDispose( [&]() -> void { + _myJobReport.erase( "ripoff" ); + sendRipoff.clear(); + } ); + } + historylog.comment( line_r ); + _myJobReport.info( line_r ); + }; + + // send the initial progress report + scriptProgress.name( scriptProgressName ); + scriptProgress.toMin(); + + // Scripts first... + if ( _scripts ) { + Pathname noRootScriptDir( ZConfig::instance().update_scriptsPath() / tmpDir().basename() ); + // like rpm would report it (intentionally not translated and NL-terminated): + str::Format fmtScriptFailedMsg { "warning: %%posttrans(%1%) scriptlet failed, exit status %2%\n" }; + str::Format fmtPosttrans { "%%posttrans(%1%)" }; + + rpm::librpmDb::db_const_iterator it; // Open DB only once + while ( ! _scripts->empty() ) + { + const auto &scriptPair = _scripts->front(); + const std::string & script = scriptPair.first; + const std::string & pkgident( script.substr( 0, script.size()-6 ) ); // strip tmp file suffix[6] + startNewScript( fmtPosttrans % pkgident ); + + int npkgs = 0; + for ( it.findByName( scriptPair.second ); *it; ++it ) + ++npkgs; + + MIL << "EXECUTE posttrans: " << script << " with argument: " << npkgs << endl; + ExternalProgram::Arguments cmd { + "/bin/sh", + (noRootScriptDir/script).asString(), + str::numstring( npkgs ) + }; + ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout, false, -1, true, _root ); + + for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() ) { + sendScriptOutput( line ); + } + //script was executed, remove it from the list + _scripts->pop_front(); + + int ret = prog.close(); + if ( ret != 0 ) + { + std::string msg { fmtScriptFailedMsg % pkgident % ret }; + WAR << msg; + sendScriptOutput( msg ); // info!, as rpm would have reported it. + } + } + _scripts = std::nullopt; + } + + // ...then 'rpm --runposttrans' + int res = 0; // Indicate a failed call to rpm itself! (a failed script is just a warning) + if ( _dumpfile ) { + res = rpm_r.runposttrans( _dumpfile->_dumpfile, [&] ( const std::string & line_r ) ->void { + if ( str::startsWith( line_r, "RIPOFF:" ) ) + startNewScript( line_r.substr( 7 ) ); // new scripts ident sent by rpm + else + sendScriptOutput( line_r ); + } ); + if ( res != 0 ) + _myJobReport.error( str::Format("rpm --runposttrans returned %1%.") % res ); + + _dumpfile = std::nullopt; + } + + // send a final progress report + scriptProgress.name( scriptProgressName ); + if ( res == 0 ) + scriptProgress.toMax(); // Indicate 100%, in case Dumpfile::_numscripts estimation was off + return; + } + + /** Discard all remembered scrips. + * As we are just logging the omitted actions, we don't pay further attention + * to the mixed case, where scripts and dumpfile are present (see executeScripts). + */ + void discardScripts() + { + if ( not ( _scripts || _dumpfile ) ) + return; // Nothing todo + + str::Str msg; + + if ( _scripts ) { + // Legacy format logs all collected %posttrans + msg << "%posttrans scripts skipped while aborting:" << endl; + for ( const auto & script : *_scripts ) + { + WAR << "UNEXECUTED posttrans: " << script.first << endl; + const std::string & pkgident( script.first.substr( 0, script.first.size()-6 ) ); // strip tmp file suffix[6] + msg << " " << pkgident << "\n"; + } + _scripts = std::nullopt; + } + + if ( _dumpfile ) { + msg << "%posttrans and %transfiletrigger scripts are not executed when aborting!" << endl; + _dumpfile = std::nullopt; + } + + HistoryLog historylog; + historylog.comment( msg, true /*timestamp*/); + _myJobReport.warning( msg ); + } + + private: + /** Lazy create tmpdir on demand. */ + Pathname tmpDir() + { + if ( !_ptrTmpdir ) _ptrTmpdir.reset( new filesystem::TmpDir( _root / ZConfig::instance().update_scriptsPath(), "posttrans" ) ); + DBG << _ptrTmpdir->path() << endl; + return _ptrTmpdir->path(); + } + + /** Return whether RpmHeader has a %posttrans. */ + bool headerHasPosttrans( const rpm::RpmHeader::constPtr& pkg_r ) const + { + bool ret = false; + if ( pkg_r ) { + std::string prog( pkg_r->tag_posttransprog() ); + if ( not prog.empty() && prog != "" ) // by now leave lua to rpm + ret = true; + } + return ret; + } + + /** Cache RpmHeader for consecutive hasPosttransScript / collectScriptForPackage calls. + * @return RpmHeader::constPtr IFF \a rpmPackage_r has a %posttrans + */ + rpm::RpmHeader::constPtr getHeaderIfPosttrans( const Pathname & rpmPackage_r ) + { + if ( _headercache.first == rpmPackage_r ) + return _headercache.second; + + rpm::RpmHeader::constPtr ret { rpm::RpmHeader::readPackage( rpmPackage_r, rpm::RpmHeader::NOVERIFY ) }; + if ( ret ) { + if ( not headerHasPosttrans( ret ) ) + ret = nullptr; + } else { + WAR << "Unexpectedly this is no package: " << rpmPackage_r << endl; + } + _headercache = std::make_pair( rpmPackage_r, ret ); + return ret; + } + + /** Retrieve "dump_posttrans: install" lines from \a dumpfile_r and pass n,v,r,a to the \a consumer_r. */ + void recallFromDumpfile( const Pathname & dumpfile_r, std::function consume_r ) + { + // dump_posttrans: install 10 terminfo-base-6.4.20230819-19.1.x86_64 + static const str::regex rxInstalled { "^dump_posttrans: +install +[0-9]+ +(.+)-([^-]+)-([^-]+)\\.([^.]+)" }; + str::smatch what; + iostr::forEachLine( InputStream( dumpfile_r ), [&]( int num_r, const std::string& line_r ) -> bool { + if( str::regex_match( line_r, what, rxInstalled ) ) + consume_r( what[1], what[2], what[3], what[4] ); + return true; // continue iostr::forEachLine + } ); + } + + private: + Pathname _root; + std::optional _scripts; + std::optional _dumpfile; + boost::scoped_ptr _ptrTmpdir; + + UserDataJobReport _myJobReport; ///< JobReport with ContentType "cmdout/%posttrans" + + std::pair _headercache; + }; + + /** \relates RpmPostTransCollector::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector::Impl & obj ) + { return str << "RpmPostTransCollector::Impl"; } + + /** \relates RpmPostTransCollector::Impl Verbose stream output */ + inline std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector::Impl & obj ) + { return str << obj; } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : RpmPostTransCollector + // + /////////////////////////////////////////////////////////////////// + + RpmPostTransCollector::RpmPostTransCollector( Pathname root_r ) + : _pimpl( new Impl( std::move(root_r) ) ) + {} + + RpmPostTransCollector::~RpmPostTransCollector() + {} + + bool RpmPostTransCollector::hasPosttransScript( const Pathname & rpmPackage_r ) + { return _pimpl->hasPosttransScript( rpmPackage_r ); } + + void RpmPostTransCollector::collectPosttransInfo( const Pathname & rpmPackage_r, const std::vector & runposttrans_r ) + { _pimpl->collectPosttransInfo( rpmPackage_r, runposttrans_r ); } + + void RpmPostTransCollector::collectPosttransInfo( const std::vector & runposttrans_r ) + { _pimpl->collectPosttransInfo( runposttrans_r ); } + + void RpmPostTransCollector::executeScripts( rpm::RpmDb & rpm_r ) + { _pimpl->executeScripts( rpm_r ); } + + void RpmPostTransCollector::discardScripts() + { return _pimpl->discardScripts(); } + + std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector & obj ) + { return str << *obj._pimpl; } + + std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector & obj ) + { return dumpOn( str, *obj._pimpl ); } + + } // namespace target + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/RpmPostTransCollector.h b/zypp/target/RpmPostTransCollector.h new file mode 100644 index 0000000..ee5ef3e --- /dev/null +++ b/zypp/target/RpmPostTransCollector.h @@ -0,0 +1,82 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/RpmPostTransCollector.h + */ +#ifndef ZYPP_TARGET_RPMPOSTTRANSCOLLECTOR_H +#define ZYPP_TARGET_RPMPOSTTRANSCOLLECTOR_H + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace target + { + namespace rpm { class RpmDb; } + + /////////////////////////////////////////////////////////////////// + /// \class RpmPostTransCollector + /// \brief Extract and remember %posttrans scripts for later execution + /// + /// bsc#1041742: Attempt to delay also %transfiletrigger(postun|in) execution + /// iff rpm supports it. Rpm versions supporting --runposttrans will inject + /// "dump_posttrans:..." lines into the output if macro "_dump_posttrans" is + /// defined during execution. Those lines are collected and later fed into + /// "rpm --runposttrans". + /// If rpm does not support it, those lines are not injected. In this case we + /// collect and later execute the %posttrans script on our own. + /////////////////////////////////////////////////////////////////// + class RpmPostTransCollector + { + friend std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector & obj ); + friend std::ostream & dumpOn( std::ostream & str, const RpmPostTransCollector & obj ); + + public: + /** Default ctor */ + RpmPostTransCollector( Pathname root_r ); + + /** Dtor */ + ~RpmPostTransCollector(); + + public: + /** Test whether a package defines a %posttrans script. */ + bool hasPosttransScript( const Pathname & rpmPackage_r ); + + /** Extract and remember a packages %posttrans script or dump_posttrans lines for later execution. */ + void collectPosttransInfo( const Pathname & rpmPackage_r, const std::vector & runposttrans_r ); + /** \overload 'remove' does not trigger a %posttrans, but it may trigger %transfiletriggers. */ + void collectPosttransInfo( const std::vector & runposttrans_r ); + + /** Execute the remembered scripts and/or or dump_posttrans lines. */ + void executeScripts( rpm::RpmDb & rpm_r ); + + /** Discard all remembered scripts and/or or dump_posttrans lines. */ + void discardScripts(); + + public: + class Impl; ///< Implementation class. + private: + RW_pointer _pimpl; ///< Pointer to implementation. + }; + + /** \relates RpmPostTransCollector Stream output */ + std::ostream & operator<<( std::ostream & str, const RpmPostTransCollector & obj ); + + /** \relates RpmPostTransCollector Verbose stream output */ + std::ostream & dumOn( std::ostream & str, const RpmPostTransCollector & obj ); + + } // namespace target + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_RPMPOSTTRANSCOLLECTOR_H diff --git a/zypp/target/SolvIdentFile.cc b/zypp/target/SolvIdentFile.cc new file mode 100644 index 0000000..26b1f9f --- /dev/null +++ b/zypp/target/SolvIdentFile.cc @@ -0,0 +1,103 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/SolvIdentFile.cc + * +*/ +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + void SolvIdentFile::load( const Pathname & file_r, Data & data_r ) + { + PathInfo pi( file_r ); + if ( ! pi.isFile() ) + { + WAR << "Can't read " << pi << endl; + return; + } + std::ifstream infile( file_r.c_str() ); + for( iostr::EachLine in( infile ); in; in.next() ) + { + std::string l( str::trim(*in) ); + if ( ! l.empty() && l[0] != '#' ) + { + data_r.insert( IdString(l) ); + } + } + MIL << "Read " << pi << endl; + } + + void SolvIdentFile::store( const Pathname & file_r, const Data & data_r ) + { + filesystem::TmpFile tmp( filesystem::TmpFile::makeSibling( file_r ) ); + filesystem::chmod( tmp.path(), 0644 ); + + std::ofstream outs( tmp.path().c_str() ); + outs << "# " << file_r.basename() << " generated " << Date::now() << endl; + if ( true ) + { + std::set sorted( data_r.begin(), data_r.end() ); + dumpRange( outs, sorted.begin(), sorted.end(), "#", "\n", "\n", "\n", "#\n" ); + } + else + { + dumpRange( outs, data_r.begin(), data_r.end(), "#", "\n", "\n", "\n", "#\n" ); + } + outs.close(); + + if ( outs.good() ) + { + filesystem::rename( tmp.path(), file_r ); + MIL << "Wrote " << PathInfo(file_r) << endl; + } + else + { + ERR << "Can't write " << PathInfo(tmp.path()) << endl; + } + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const SolvIdentFile & obj ) + { + str << obj.file() << ' '; + if ( obj._dataPtr ) + str << obj.data(); + else + str << "(unloaded)"; + return str; + } + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/SolvIdentFile.h b/zypp/target/SolvIdentFile.h new file mode 100644 index 0000000..2a803dd --- /dev/null +++ b/zypp/target/SolvIdentFile.h @@ -0,0 +1,116 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/SolvIdentFile.h + * +*/ +#ifndef ZYPP_TARGET_SOLVIDENTFILE_H +#define ZYPP_TARGET_SOLVIDENTFILE_H + +#include +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + /// \class SolvIdentFile + /// \short Save and restore a list of solvable names (ident IdString) + /////////////////////////////////////////////////////////////////// + class SolvIdentFile + { + friend std::ostream & operator<<( std::ostream & str, const SolvIdentFile & obj ); + public: + using Data = std::unordered_set; + + public: + /** Ctor taking the file to read/write. */ + SolvIdentFile( Pathname file_r ) + : _file(std::move( file_r )) + {} + + /** Return the file path. */ + const Pathname & file() const + { return _file; } + + /** Return the data. + * The file is read once on demand. Returns empty \ref Data if + * the file does not exist or is not readable. + */ + const Data & data() const + { + if ( !_dataPtr ) + { + _dataPtr.reset( new Data ); + Data & mydata( *_dataPtr ); + load( _file, mydata ); + } + return *_dataPtr; + } + + /** Store new \ref Data. + * Write the new \ref Data to file, unless we know it + * did not change. The directory containing file must + * exist. + */ + void setData( const Data & data_r ) + { + if ( !_dataPtr ) + _dataPtr.reset( new Data ); + + if ( differs( *_dataPtr, data_r ) ) + { + store( _file, data_r ); + *_dataPtr = data_r; + } + } + + private: + /** Helper testing whether two \ref Data differ. */ + bool differs( const Data & lhs, const Data & rhs ) const + { + + if ( lhs.size() != rhs.size() ) + return true; + for_( it, lhs.begin(), lhs.end() ) + { + if ( rhs.find( *it ) == rhs.end() ) + return true; + } + return false; + } + /** Read \ref Data from \c file_r. */ + static void load( const Pathname & file_r, Data & data_r ); + /** Write \ref Data to \c file_r. */ + static void store( const Pathname & file_r, const Data & data_r ); + + private: + Pathname _file; + mutable scoped_ptr _dataPtr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates SolvIdentFile Stream output */ + std::ostream & operator<<( std::ostream & str, const SolvIdentFile & obj ); + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_SOLVIDENTFILE_H diff --git a/zypp/target/TargetCallbackReceiver.cc b/zypp/target/TargetCallbackReceiver.cc new file mode 100644 index 0000000..132e516 --- /dev/null +++ b/zypp/target/TargetCallbackReceiver.cc @@ -0,0 +1,209 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/TargetCallbackReceiver.cc + * +*/ +#include +#include + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + RpmInstallPackageReceiver::RpmInstallPackageReceiver (Resolvable::constPtr res) + : callback::ReceiveReport () + , _resolvable (std::move(res)) + , _level( target::rpm::InstallResolvableReport::RPM ) + , _abort (false) + { + } + + RpmInstallPackageReceiver::~RpmInstallPackageReceiver () + { + } + + void RpmInstallPackageReceiver::reportbegin() + { + } + + void RpmInstallPackageReceiver::reportend() + { + } + + void RpmInstallPackageReceiver::report( const UserData & userData_r ) + { + if ( ! userData_r.haskey( "solvable" ) ) + userData_r.set( "solvable", _resolvable->satSolvable() ); + _report->report( userData_r ); + } + + /** Start the operation */ + void RpmInstallPackageReceiver::start( const Pathname & name ) + { + _report->start( _resolvable ); + _abort = false; + } + + /** + * Inform about progress + * Return true on abort + */ + bool RpmInstallPackageReceiver::progress( unsigned percent ) + { + _abort = ! _report->progress( percent, _resolvable ); + return _abort; + } + + rpm::RpmInstallReport::Action + RpmInstallPackageReceiver::problem( Exception & excpt_r ) + { + rpm::InstallResolvableReport::Action user = + _report->problem( _resolvable + , rpm::InstallResolvableReport::INVALID + , excpt_r.asUserHistory() + , _level + ); + + switch (user) { + case rpm::InstallResolvableReport::RETRY: + return rpm::RpmInstallReport::RETRY; + case rpm::InstallResolvableReport::ABORT: + _abort = true; + return rpm::RpmInstallReport::ABORT; + case rpm::InstallResolvableReport::IGNORE: + return rpm::RpmInstallReport::IGNORE; + } + + return rpm::RpmInstallReport::problem( excpt_r ); + } + + void RpmInstallPackageReceiver::finishInfo( const std::string & info_r ) + { + _finishInfo = info_r; + } + + /** Finish operation in case of success */ + void RpmInstallPackageReceiver::finish() + { + _report->finish( _resolvable, rpm::InstallResolvableReport::NO_ERROR, _finishInfo, _level ); + } + + /** Finish operation in case of success */ + void RpmInstallPackageReceiver::finish( Exception & excpt_r ) + { + _report->finish( _resolvable, rpm::InstallResolvableReport::INVALID, std::string(), _level ); + } + + void RpmInstallPackageReceiver::tryLevel( target::rpm::InstallResolvableReport::RpmLevel level_r ) + { + _level = level_r; + } + + + ///////////////////////////////////////////////////////////////// + /// RpmRemovePackageReceiver + ///////////////////////////////////////////////////////////////// + + RpmRemovePackageReceiver::RpmRemovePackageReceiver (Resolvable::constPtr res) + : callback::ReceiveReport () + , _resolvable (std::move(res)) + , _abort(false) + { + } + + RpmRemovePackageReceiver::~RpmRemovePackageReceiver () + { + } + + void RpmRemovePackageReceiver::reportbegin() + { + } + + void RpmRemovePackageReceiver::reportend() + { + } + + /** Start the operation */ + void RpmRemovePackageReceiver::report( const UserData & userData_r ) + { + if ( ! userData_r.haskey( "solvable" ) ) + userData_r.set( "solvable", _resolvable->satSolvable() ); + _report->report( userData_r ); + } + + void RpmRemovePackageReceiver::start( const std::string & name ) + { + _report->start( _resolvable ); + _abort = false; + } + + /** + * Inform about progress + * Return true on abort + */ + bool RpmRemovePackageReceiver::progress( unsigned percent ) + { + _abort = ! _report->progress( percent, _resolvable ); + return _abort; + } + + rpm::RpmRemoveReport::Action + RpmRemovePackageReceiver::problem( Exception & excpt_r ) + { + rpm::RemoveResolvableReport::Action user = + _report->problem( _resolvable + , rpm::RemoveResolvableReport::INVALID + , excpt_r.asUserHistory() + ); + + switch (user) { + case rpm::RemoveResolvableReport::RETRY: + return rpm::RpmRemoveReport::RETRY; + case rpm::RemoveResolvableReport::ABORT: + _abort = true; + return rpm::RpmRemoveReport::ABORT; + case rpm::RemoveResolvableReport::IGNORE: + return rpm::RpmRemoveReport::IGNORE; + } + + return rpm::RpmRemoveReport::problem( excpt_r ); + } + + void RpmRemovePackageReceiver::finishInfo( const std::string & info_r ) + { + _finishInfo = info_r; + } + + /** Finish operation in case of success */ + void RpmRemovePackageReceiver::finish() + { + _report->progress( 100, _resolvable ); + _report->finish( _resolvable, rpm::RemoveResolvableReport::NO_ERROR, _finishInfo ); + } + + /** Finish operation in case of success */ + void RpmRemovePackageReceiver::finish( Exception & excpt_r ) + { + _report->finish( _resolvable, rpm::RemoveResolvableReport::INVALID, std::string() ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/TargetCallbackReceiver.h b/zypp/target/TargetCallbackReceiver.h new file mode 100644 index 0000000..40952f0 --- /dev/null +++ b/zypp/target/TargetCallbackReceiver.h @@ -0,0 +1,125 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/TargetCallbackReceiver.h + * +*/ +#ifndef ZYPP_TARGET_TARGETCALLBACKRECEIVER_H +#define ZYPP_TARGET_TARGETCALLBACKRECEIVER_H + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + class RpmInstallPackageReceiver + : public callback::ReceiveReport + { + callback::SendReport _report; + Resolvable::constPtr _resolvable; + target::rpm::InstallResolvableReport::RpmLevel _level; + bool _abort; + std::string _finishInfo; + + public: + + RpmInstallPackageReceiver (Resolvable::constPtr res); + virtual ~RpmInstallPackageReceiver (); + + virtual void reportbegin(); + + virtual void reportend(); + + /** Forwards generic reports. */ + void report( const UserData & userData_r ) override; + + /** Start the operation */ + virtual void start( const Pathname & name ); + + void tryLevel( target::rpm::InstallResolvableReport::RpmLevel level_r ); + + bool aborted() const { return _abort; } + + /** + * Inform about progress + * Return true on abort + */ + virtual bool progress( unsigned percent ); + + /** inform user about a problem */ + virtual rpm::RpmInstallReport::Action problem( Exception & excpt_r ); + + /** Additional rpm output to be reported in \ref finish in case of success. */ + virtual void finishInfo( const std::string & info_r ); + + /** Finish operation in case of success */ + virtual void finish(); + + /** Finish operatin in case of fail, report fail exception */ + virtual void finish( Exception & excpt_r ); + }; + + class RpmRemovePackageReceiver + : public callback::ReceiveReport + { + callback::SendReport _report; + Resolvable::constPtr _resolvable; + bool _abort; + std::string _finishInfo; + + public: + + RpmRemovePackageReceiver (Resolvable::constPtr res); + virtual ~RpmRemovePackageReceiver (); + + virtual void reportbegin(); + + virtual void reportend(); + + /** Start the operation */ + /** Forwards generic reports. */ + void report( const UserData & userData_r ) override; + + virtual void start( const std::string & name ); + + /** + * Inform about progress + * Return true on abort + */ + virtual bool progress( unsigned percent ); + + /** + * Returns true if removing is aborted during progress + */ + bool aborted() const { return _abort; } + + /** inform user about a problem */ + virtual rpm::RpmRemoveReport::Action problem( Exception & excpt_r ); + + /** Additional rpm output to be reported in \ref finish in case of success. */ + virtual void finishInfo( const std::string & info_r ); + + /** Finish operation in case of success */ + virtual void finish(); + + /** Finish operatin in case of fail, report fail exception */ + virtual void finish( Exception & excpt_r ); + }; + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_TARGETCALLBACKRECEIVER_H diff --git a/zypp/target/TargetException.cc b/zypp/target/TargetException.cc new file mode 100644 index 0000000..26b69a9 --- /dev/null +++ b/zypp/target/TargetException.cc @@ -0,0 +1,40 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/TargetException.cc + * +*/ + +#include +#include + +#include +#include + + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + namespace target { + ///////////////////////////////////////////////////////////////// + + TargetAbortedException::TargetAbortedException() + : TargetAbortedException ( _("Installation has been aborted as directed.") ) + { } + + std::ostream & TargetAbortedException::dumpOn( std::ostream & str ) const + { + //call base implementation, do not hardcode a string, do not blame user ( fixes bnc#978193 ) + return TargetException::dumpOn( str ); + } + + + ///////////////////////////////////////////////////////////////// + } // namespace target +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/TargetException.h b/zypp/target/TargetException.h new file mode 100644 index 0000000..82dc09d --- /dev/null +++ b/zypp/target/TargetException.h @@ -0,0 +1,74 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/TargetException.h + * +*/ +#ifndef ZYPP_TARGET_TARGETEXCEPTION_H +#define ZYPP_TARGET_TARGETEXCEPTION_H + +#include + +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + namespace target { + /////////////////////////////////////////////////////////////// + // + // CLASS NAME : TargetException + /** Just inherits Exception to separate target exceptions + * + **/ + class ZYPP_API TargetException : public Exception + { + public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + TargetException() + : Exception( "Target Exception" ) + {} + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + TargetException( const std::string & msg_r ) + : Exception( msg_r ) + {} + /** Dtor. */ + ~TargetException() throw() override {}; + }; + + class ZYPP_API TargetAbortedException : public TargetException + { + public: + TargetAbortedException( ); + + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + TargetAbortedException( const std::string & msg_r ) + : TargetException( msg_r ) + {} + /** Dtor. */ + ~TargetAbortedException() throw() override {}; + protected: + std::ostream & dumpOn( std::ostream & str ) const override; + private: + }; + + + ///////////////////////////////////////////////////////////////// + } // namespace target +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_TARGETEXCEPTION_H diff --git a/zypp/target/TargetImpl.cc b/zypp/target/TargetImpl.cc new file mode 100644 index 0000000..690d1c9 --- /dev/null +++ b/zypp/target/TargetImpl.cc @@ -0,0 +1,3068 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/TargetImpl.cc + * +*/ +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include + +// include the error codes from zypp-rpm +#include "tools/zypp-rpm/errorcodes.h" +#include + +#include + +namespace zypp::env { + inline bool TRANSACTIONAL_UPDATE() + { + static bool val = [](){ + const char * env = getenv("TRANSACTIONAL_UPDATE"); + return( env && zypp::str::strToBool( env, true ) ); + }(); + return val; + } +} // namespace zypp::env + +using std::endl; + +/////////////////////////////////////////////////////////////////// +extern "C" +{ +#include +#include +} +namespace zypp +{ + namespace target + { + inline std::string rpmDbStateHash( const Pathname & root_r ) + { + std::string ret; + AutoDispose state { ::rpm_state_create( sat::Pool::instance().get(), root_r.c_str() ), ::rpm_state_free }; + AutoDispose chk { ::solv_chksum_create( REPOKEY_TYPE_SHA1 ), []( Chksum *chk ) -> void { + ::solv_chksum_free( chk, nullptr ); + } }; + if ( ::rpm_hash_database_state( state, chk ) == 0 ) + { + int md5l; + const unsigned char * md5 = ::solv_chksum_get( chk, &md5l ); + ret = ::pool_bin2hex( sat::Pool::instance().get(), md5, md5l ); + } + else + WAR << "rpm_hash_database_state failed" << endl; + return ret; + } + + inline RepoStatus rpmDbRepoStatus( const Pathname & root_r ) + { return RepoStatus( rpmDbStateHash( root_r ), Date() ); } + + } // namespace target +} // namespace +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + ///////////////////////////////////////////////////////////////// + namespace + { + // HACK for bnc#906096: let pool re-evaluate multiversion spec + // if target root changes. ZConfig returns data sensitive to + // current target root. + inline void sigMultiversionSpecChanged() + { + sat::detail::PoolMember::myPool().multiversionSpecChanged(); + } + } //namespace + ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace json + { + // Lazy via template specialisation / should switch to overloading + + template<> + inline std::string toJSON( const ZYppCommitResult::TransactionStepList & steps_r ) + { + using sat::Transaction; + json::Array ret; + + for ( const Transaction::Step & step : steps_r ) + // ignore implicit deletes due to obsoletes and non-package actions + if ( step.stepType() != Transaction::TRANSACTION_IGNORE ) + ret.add( step ); + + return ret.asJSON(); + } + + /** See \ref commitbegin on page \ref plugin-commit for the specs. */ + template<> + inline std::string toJSON( const sat::Transaction::Step & step_r ) + { + static const std::string strType( "type" ); + static const std::string strStage( "stage" ); + static const std::string strSolvable( "solvable" ); + + static const std::string strTypeDel( "-" ); + static const std::string strTypeIns( "+" ); + static const std::string strTypeMul( "M" ); + + static const std::string strStageDone( "ok" ); + static const std::string strStageFailed( "err" ); + + static const std::string strSolvableN( "n" ); + static const std::string strSolvableE( "e" ); + static const std::string strSolvableV( "v" ); + static const std::string strSolvableR( "r" ); + static const std::string strSolvableA( "a" ); + + using sat::Transaction; + json::Object ret; + + switch ( step_r.stepType() ) + { + case Transaction::TRANSACTION_IGNORE: /*empty*/ break; + case Transaction::TRANSACTION_ERASE: ret.add( strType, strTypeDel ); break; + case Transaction::TRANSACTION_INSTALL: ret.add( strType, strTypeIns ); break; + case Transaction::TRANSACTION_MULTIINSTALL: ret.add( strType, strTypeMul ); break; + } + + switch ( step_r.stepStage() ) + { + case Transaction::STEP_TODO: /*empty*/ break; + case Transaction::STEP_DONE: ret.add( strStage, strStageDone ); break; + case Transaction::STEP_ERROR: ret.add( strStage, strStageFailed ); break; + } + + { + IdString ident; + Edition ed; + Arch arch; + if ( sat::Solvable solv = step_r.satSolvable() ) + { + ident = solv.ident(); + ed = solv.edition(); + arch = solv.arch(); + } + else + { + // deleted package; post mortem data stored in Transaction::Step + ident = step_r.ident(); + ed = step_r.edition(); + arch = step_r.arch(); + } + + json::Object s { + { strSolvableN, ident.asString() }, + { strSolvableV, ed.version() }, + { strSolvableR, ed.release() }, + { strSolvableA, arch.asString() } + }; + if ( Edition::epoch_t epoch = ed.epoch() ) + s.add( strSolvableE, epoch ); + + ret.add( strSolvable, s ); + } + + return ret.asJSON(); + } + } // namespace json + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace target + { + /////////////////////////////////////////////////////////////////// + namespace + { + class AssertMountedBase + { + NON_COPYABLE(AssertMountedBase); + NON_MOVABLE(AssertMountedBase); + protected: + AssertMountedBase() + {} + + ~AssertMountedBase() + { + if ( ! _mountpoint.empty() ) { + // we mounted it so we unmount... + MIL << "We mounted " << _mountpoint << " so we unmount it" << endl; + execute({ "umount", "-R", "-l", _mountpoint.asString() }); + } + } + + protected: + int execute( ExternalProgram::Arguments && cmd_r ) const + { + ExternalProgram prog( cmd_r, ExternalProgram::Stderr_To_Stdout ); + for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() ) + { DBG << line; } + return prog.close(); + } + + protected: + Pathname _mountpoint; + + }; + + /// \brief Try to provide /proc fs if not present. + /// bsc#1181328: Some systemd tools require /proc to be mounted + class AssertProcMounted : private AssertMountedBase + { + public: + AssertProcMounted( Pathname root_r ) + { + root_r /= "/proc"; + if ( ! PathInfo(root_r/"self").isDir() ) { + MIL << "Try to make sure proc is mounted at" << root_r << endl; + if ( filesystem::assert_dir(root_r) == 0 + && execute({ "mount", "-t", "proc", "/proc", root_r.asString() }) == 0 ) { + _mountpoint = std::move(root_r); // so we'll later unmount it + } + else { + WAR << "Mounting proc at " << root_r << " failed" << endl; + } + } + } + }; + + /// \brief Try to provide /dev fs if not present. + /// #444: Some packages expect /dev to be mounted + class AssertDevMounted : private AssertMountedBase + { + public: + AssertDevMounted( Pathname root_r ) + { + root_r /= "/dev"; + if ( ! PathInfo(root_r/"null").isChr() ) { + MIL << "Try to make sure dev is mounted at" << root_r << endl; + // https://unix.stackexchange.com/questions/263972/unmount-a-rbind-mount-without-affecting-the-original-mount + // Without --make-rslave unmounting /dev/pts + // may unmount /dev/pts and you're out of ptys. + if ( filesystem::assert_dir(root_r) == 0 + && execute({ "mount", "--rbind", "--make-rslave", "/dev", root_r.asString() }) == 0 ) { + _mountpoint = std::move(root_r); // so we'll later unmount it + } + else { + WAR << "Mounting dev at " << root_r << " failed" << endl; + } + } + } + }; + + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { + SolvIdentFile::Data getUserInstalledFromHistory( const Pathname & historyFile_r ) + { + SolvIdentFile::Data onSystemByUserList; + // go and parse it: 'who' must constain an '@', then it was installed by user request. + // 2009-09-29 07:25:19|install|lirc-remotes|0.8.5-3.2|x86_64|root@opensuse|InstallationImage|a204211eb0... + std::ifstream infile( historyFile_r.c_str() ); + for( iostr::EachLine in( infile ); in; in.next() ) + { + const char * ch( (*in).c_str() ); + // start with year + if ( *ch < '1' || '9' < *ch ) + continue; + const char * sep1 = ::strchr( ch, '|' ); // | after date + if ( !sep1 ) + continue; + ++sep1; + // if logs an install or delete + bool installs = true; + if ( ::strncmp( sep1, "install|", 8 ) ) + { + if ( ::strncmp( sep1, "remove |", 8 ) ) + continue; // no install and no remove + else + installs = false; // remove + } + sep1 += 8; // | after what + // get the package name + const char * sep2 = ::strchr( sep1, '|' ); // | after name + if ( !sep2 || sep1 == sep2 ) + continue; + (*in)[sep2-ch] = '\0'; + IdString pkg( sep1 ); + // we're done, if a delete + if ( !installs ) + { + onSystemByUserList.erase( pkg ); + continue; + } + // now guess whether user installed or not (3rd next field contains 'user@host') + if ( (sep1 = ::strchr( sep2+1, '|' )) // | after version + && (sep1 = ::strchr( sep1+1, '|' )) // | after arch + && (sep2 = ::strchr( sep1+1, '|' )) ) // | after who + { + (*in)[sep2-ch] = '\0'; + if ( ::strchr( sep1+1, '@' ) ) + { + // by user + onSystemByUserList.insert( pkg ); + continue; + } + } + } + MIL << "onSystemByUserList found: " << onSystemByUserList.size() << endl; + return onSystemByUserList; + } + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace + { + inline PluginFrame transactionPluginFrame( const std::string & command_r, ZYppCommitResult::TransactionStepList & steps_r ) + { + return PluginFrame( command_r, json::Object { + { "TransactionStepList", steps_r } + }.asJSON() ); + } + } // namespace + /////////////////////////////////////////////////////////////////// + + /** \internal Manage writing a new testcase when doing an upgrade. */ + void writeUpgradeTestcase() + { + unsigned toKeep( ZConfig::instance().solver_upgradeTestcasesToKeep() ); + MIL << "Testcases to keep: " << toKeep << endl; + if ( !toKeep ) + return; + Target_Ptr target( getZYpp()->getTarget() ); + if ( ! target ) + { + WAR << "No Target no Testcase!" << endl; + return; + } + + std::string stem( "updateTestcase" ); + Pathname dir( target->assertRootPrefix("/var/log/") ); + Pathname next( dir / Date::now().form( stem+"-%Y-%m-%d-%H-%M-%S" ) ); + + { + std::list content; + filesystem::readdir( content, dir, /*dots*/false ); + std::set cases; + for_( c, content.begin(), content.end() ) + { + if ( str::startsWith( *c, stem ) ) + cases.insert( *c ); + } + if ( cases.size() >= toKeep ) + { + unsigned toDel = cases.size() - toKeep + 1; // +1 for the new one + for_( c, cases.begin(), cases.end() ) + { + filesystem::recursive_rmdir( dir/(*c) ); + if ( ! --toDel ) + break; + } + } + } + + MIL << "Write new testcase " << next << endl; + getZYpp()->resolver()->createSolverTestcase( next.asString(), false/*no solving*/ ); + } + + /////////////////////////////////////////////////////////////////// + namespace + { ///////////////////////////////////////////////////////////////// + + /** Execute script and report against report_r. + * Return \c std::pair to indicate if + * execution was successful (first = true), or the desired + * \c PatchScriptReport::Action in case execution failed + * (first = false). + * + * \note The packager is responsible for setting the correct permissions + * of the script. If the script is not executable it is reported as an + * error. We must not modify the permessions. + */ + std::pair doExecuteScript( const Pathname & root_r, + const Pathname & script_r, + callback::SendReport & report_r ) + { + MIL << "Execute script " << PathInfo(Pathname::assertprefix( root_r,script_r)) << endl; + + HistoryLog historylog; + historylog.comment(script_r.asString() + _(" executed"), /*timestamp*/true); + ExternalProgram prog( script_r.asString(), ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r ); + + for ( std::string output = prog.receiveLine(); output.length(); output = prog.receiveLine() ) + { + historylog.comment(output); + if ( ! report_r->progress( PatchScriptReport::OUTPUT, output ) ) + { + WAR << "User request to abort script " << script_r << endl; + prog.kill(); + // the rest is handled by exit code evaluation + // in case the script has meanwhile finished. + } + } + + std::pair ret( std::make_pair( false, PatchScriptReport::ABORT ) ); + + if ( prog.close() != 0 ) + { + ret.second = report_r->problem( prog.execError() ); + WAR << "ACTION" << ret.second << "(" << prog.execError() << ")" << endl; + std::ostringstream sstr; + sstr << script_r << _(" execution failed") << " (" << prog.execError() << ")" << endl; + historylog.comment(sstr.str(), /*timestamp*/true); + return ret; + } + + report_r->finish(); + ret.first = true; + return ret; + } + + /** Execute script and report against report_r. + * Return \c false if user requested \c ABORT. + */ + bool executeScript( const Pathname & root_r, + const Pathname & script_r, + callback::SendReport & report_r ) + { + std::pair action( std::make_pair( false, PatchScriptReport::ABORT ) ); + + do { + action = doExecuteScript( root_r, script_r, report_r ); + if ( action.first ) + return true; // success + + switch ( action.second ) + { + case PatchScriptReport::ABORT: + WAR << "User request to abort at script " << script_r << endl; + return false; // requested abort. + break; + + case PatchScriptReport::IGNORE: + WAR << "User request to skip script " << script_r << endl; + return true; // requested skip. + break; + + case PatchScriptReport::RETRY: + break; // again + } + } while ( action.second == PatchScriptReport::RETRY ); + + // THIS is not intended to be reached: + INT << "Abort on unknown ACTION request " << action.second << " returned" << endl; + return false; // abort. + } + + /** Look for update scripts named 'name-version-release-*' and + * execute them. Return \c false if \c ABORT was requested. + * + * \see http://en.opensuse.org/Software_Management/Code11/Scripts_and_Messages + */ + bool RunUpdateScripts( const Pathname & root_r, + const Pathname & scriptsPath_r, + const std::vector & checkPackages_r, + bool aborting_r ) + { + if ( checkPackages_r.empty() ) + return true; // no installed packages to check + + MIL << "Looking for new update scripts in (" << root_r << ")" << scriptsPath_r << endl; + Pathname scriptsDir( Pathname::assertprefix( root_r, scriptsPath_r ) ); + if ( ! PathInfo( scriptsDir ).isDir() ) + return true; // no script dir + + std::list scripts; + filesystem::readdir( scripts, scriptsDir, /*dots*/false ); + if ( scripts.empty() ) + return true; // no scripts in script dir + + // Now collect and execute all matching scripts. + // On ABORT: at least log all outstanding scripts. + // - "name-version-release" + // - "name-version-release-*" + bool abort = false; + std::map unify; // scripts + for_( it, checkPackages_r.begin(), checkPackages_r.end() ) + { + std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) ); + for_( sit, scripts.begin(), scripts.end() ) + { + if ( ! str::hasPrefix( *sit, prefix ) ) + continue; + + if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' ) + continue; // if not exact match it had to continue with '-' + + PathInfo script( scriptsDir / *sit ); + Pathname localPath( scriptsPath_r/(*sit) ); // without root prefix + std::string unifytag; // must not stay empty + + if ( script.isFile() ) + { + // Assert it's set as executable, unify by md5sum. + filesystem::addmod( script.path(), 0500 ); + unifytag = filesystem::md5sum( script.path() ); + } + else if ( ! script.isExist() ) + { + // Might be a dangling symlink, might be ok if we are in + // instsys (absolute symlink within the system below /mnt). + // readlink will tell.... + unifytag = filesystem::readlink( script.path() ).asString(); + } + + if ( unifytag.empty() ) + continue; + + // Unify scripts + if ( unify[unifytag].empty() ) + { + unify[unifytag] = localPath; + } + else + { + // translators: We may find the same script content in files with different names. + // Only the first occurence is executed, subsequent ones are skipped. It's a one-line + // message for a log file. Preferably start translation with "%s" + std::string msg( str::form(_("%s already executed as %s)"), localPath.asString().c_str(), unify[unifytag].c_str() ) ); + MIL << "Skip update script: " << msg << endl; + HistoryLog().comment( msg, /*timestamp*/true ); + continue; + } + + if ( abort || aborting_r ) + { + WAR << "Aborting: Skip update script " << *sit << endl; + HistoryLog().comment( + localPath.asString() + _(" execution skipped while aborting"), + /*timestamp*/true); + } + else + { + MIL << "Found update script " << *sit << endl; + callback::SendReport report; + report->start( make( *it ), script.path() ); + + if ( ! executeScript( root_r, localPath, report ) ) // script path without root prefix! + abort = true; // requested abort. + } + } + } + return !abort; + } + + /////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////// + + inline void copyTo( std::ostream & out_r, const Pathname & file_r ) + { + std::ifstream infile( file_r.c_str() ); + for( iostr::EachLine in( infile ); in; in.next() ) + { + out_r << *in << endl; + } + } + + inline std::string notificationCmdSubst( const std::string & cmd_r, const UpdateNotificationFile & notification_r ) + { + std::string ret( cmd_r ); +#define SUBST_IF(PAT,VAL) if ( ret.find( PAT ) != std::string::npos ) ret = str::gsub( ret, PAT, VAL ) + SUBST_IF( "%p", notification_r.solvable().asString() ); + SUBST_IF( "%P", notification_r.file().asString() ); +#undef SUBST_IF + return ret; + } + + void sendNotification( const Pathname & root_r, + const UpdateNotifications & notifications_r ) + { + if ( notifications_r.empty() ) + return; + + std::string cmdspec( ZConfig::instance().updateMessagesNotify() ); + MIL << "Notification command is '" << cmdspec << "'" << endl; + if ( cmdspec.empty() ) + return; + + std::string::size_type pos( cmdspec.find( '|' ) ); + if ( pos == std::string::npos ) + { + ERR << "Can't send Notification: Missing 'format |' in command spec." << endl; + HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true ); + return; + } + + std::string formatStr( str::toLower( str::trim( cmdspec.substr( 0, pos ) ) ) ); + std::string commandStr( str::trim( cmdspec.substr( pos + 1 ) ) ); + + enum Format { UNKNOWN, NONE, SINGLE, DIGEST, BULK }; + Format format = UNKNOWN; + if ( formatStr == "none" ) + format = NONE; + else if ( formatStr == "single" ) + format = SINGLE; + else if ( formatStr == "digest" ) + format = DIGEST; + else if ( formatStr == "bulk" ) + format = BULK; + else + { + ERR << "Can't send Notification: Unknown format '" << formatStr << " |' in command spec." << endl; + HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true ); + return; + } + + // Take care: commands are ececuted chroot(root_r). The message file + // pathnames in notifications_r are local to root_r. For physical access + // to the file they need to be prefixed. + + if ( format == NONE || format == SINGLE ) + { + for_( it, notifications_r.begin(), notifications_r.end() ) + { + std::vector command; + if ( format == SINGLE ) + command.push_back( "<"+Pathname::assertprefix( root_r, it->file() ).asString() ); + str::splitEscaped( notificationCmdSubst( commandStr, *it ), std::back_inserter( command ) ); + + ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r ); + if ( true ) // Wait for feedback + { + for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() ) + { + DBG << line; + } + int ret = prog.close(); + if ( ret != 0 ) + { + ERR << "Notification command returned with error (" << ret << ")." << endl; + HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true ); + return; + } + } + } + } + else if ( format == DIGEST || format == BULK ) + { + filesystem::TmpFile tmpfile; + std::ofstream out( tmpfile.path().c_str() ); + for_( it, notifications_r.begin(), notifications_r.end() ) + { + if ( format == DIGEST ) + { + out << it->file() << endl; + } + else if ( format == BULK ) + { + copyTo( out << '\f', Pathname::assertprefix( root_r, it->file() ) ); + } + } + + std::vector command; + command.push_back( "<"+tmpfile.path().asString() ); // redirect input + str::splitEscaped( notificationCmdSubst( commandStr, *notifications_r.begin() ), std::back_inserter( command ) ); + + ExternalProgram prog( command, ExternalProgram::Stderr_To_Stdout, false, -1, true, root_r ); + if ( true ) // Wait for feedback otherwise the TmpFile goes out of scope. + { + for( std::string line = prog.receiveLine(); ! line.empty(); line = prog.receiveLine() ) + { + DBG << line; + } + int ret = prog.close(); + if ( ret != 0 ) + { + ERR << "Notification command returned with error (" << ret << ")." << endl; + HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true ); + return; + } + } + } + else + { + INT << "Can't send Notification: Missing handler for 'format |' in command spec." << endl; + HistoryLog().comment( str::Str() << _("Error sending update message notification."), /*timestamp*/true ); + return; + } + } + + + /** Look for update messages named 'name-version-release-*' and + * send notification according to \ref ZConfig::updateMessagesNotify. + * + * \see http://en.opensuse.org/Software_Management/Code11/Scripts_and_Messages + */ + void RunUpdateMessages( const Pathname & root_r, + const Pathname & messagesPath_r, + const std::vector & checkPackages_r, + ZYppCommitResult & result_r ) + { + if ( checkPackages_r.empty() ) + return; // no installed packages to check + + MIL << "Looking for new update messages in (" << root_r << ")" << messagesPath_r << endl; + Pathname messagesDir( Pathname::assertprefix( root_r, messagesPath_r ) ); + if ( ! PathInfo( messagesDir ).isDir() ) + return; // no messages dir + + std::list messages; + filesystem::readdir( messages, messagesDir, /*dots*/false ); + if ( messages.empty() ) + return; // no messages in message dir + + // Now collect all matching messages in result and send them + // - "name-version-release" + // - "name-version-release-*" + HistoryLog historylog; + for_( it, checkPackages_r.begin(), checkPackages_r.end() ) + { + std::string prefix( str::form( "%s-%s", it->name().c_str(), it->edition().c_str() ) ); + for_( sit, messages.begin(), messages.end() ) + { + if ( ! str::hasPrefix( *sit, prefix ) ) + continue; + + if ( (*sit)[prefix.size()] != '\0' && (*sit)[prefix.size()] != '-' ) + continue; // if not exact match it had to continue with '-' + + PathInfo message( messagesDir / *sit ); + if ( ! message.isFile() || message.size() == 0 ) + continue; + + MIL << "Found update message " << *sit << endl; + Pathname localPath( messagesPath_r/(*sit) ); // without root prefix + result_r.rUpdateMessages().push_back( UpdateNotificationFile( *it, localPath ) ); + historylog.comment( str::Str() << _("New update message") << " " << localPath, /*timestamp*/true ); + } + } + sendNotification( root_r, result_r.updateMessages() ); + } + + /** jsc#SLE-5116: Log patch status changes to history. + * Adjust precomputed set if transaction is incomplete. + */ + void logPatchStatusChanges( const sat::Transaction & transaction_r, TargetImpl & target_r ) + { + ResPool::ChangedPseudoInstalled changedPseudoInstalled { ResPool::instance().changedPseudoInstalled() }; + if ( changedPseudoInstalled.empty() ) + return; + + if ( ! transaction_r.actionEmpty( ~sat::Transaction::STEP_DONE ) ) + { + // Need to recompute the patch list if commit is incomplete! + // We remember the initially established status, then reload the + // Target to get the current patch status. Then compare. + WAR << "Need to recompute the patch status changes as commit is incomplete!" << endl; + ResPool::EstablishedStates establishedStates{ ResPool::instance().establishedStates() }; + target_r.load(); + changedPseudoInstalled = establishedStates.changedPseudoInstalled(); + } + + HistoryLog historylog; + for ( const auto & el : changedPseudoInstalled ) + historylog.patchStateChange( el.first, el.second ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace + /////////////////////////////////////////////////////////////////// + + void XRunUpdateMessages( const Pathname & root_r, + const Pathname & messagesPath_r, + const std::vector & checkPackages_r, + ZYppCommitResult & result_r ) + { RunUpdateMessages( root_r, messagesPath_r, checkPackages_r, result_r ); } + + /////////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(TargetImpl); + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : TargetImpl::TargetImpl + // METHOD TYPE : Ctor + // + TargetImpl::TargetImpl( const Pathname & root_r, bool doRebuild_r ) + : _root( root_r ) + , _requestedLocalesFile( home() / "RequestedLocales" ) + , _autoInstalledFile( home() / "AutoInstalled" ) + , _hardLocksFile( Pathname::assertprefix( _root, ZConfig::instance().locksFile() ) ) + , _vendorAttr( Pathname::assertprefix( _root, ZConfig::instance().vendorPath() ) ) + { + _rpm.initDatabase( root_r, doRebuild_r ); + + HistoryLog::setRoot(_root); + + createAnonymousId(); + sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged + MIL << "Initialized target on " << _root << endl; + } + + /** + * generates a random id using uuidgen + */ + static std::string generateRandomId() + { + std::ifstream uuidprovider( "/proc/sys/kernel/random/uuid" ); + return iostr::getline( uuidprovider ); + } + + /** + * updates the content of \p filename + * if \p condition is true, setting the content + * the the value returned by \p value + */ + void updateFileContent( const Pathname &filename, + boost::function condition, + boost::function value ) + { + std::string val = value(); + // if the value is empty, then just dont + // do anything, regardless of the condition + if ( val.empty() ) + return; + + if ( condition() ) + { + MIL << "updating '" << filename << "' content." << endl; + + // if the file does not exist we need to generate the uuid file + + std::ofstream filestr; + // make sure the path exists + filesystem::assert_dir( filename.dirname() ); + filestr.open( filename.c_str() ); + + if ( filestr.good() ) + { + filestr << val; + filestr.close(); + } + else + { + // FIXME, should we ignore the error? + ZYPP_THROW(Exception("Can't openfile '" + filename.asString() + "' for writing")); + } + } + } + + /** helper functor */ + static bool fileMissing( const Pathname &pathname ) + { + return ! PathInfo(pathname).isExist(); + } + + void TargetImpl::createAnonymousId() const + { + // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine) + if ( root() != "/" ) + return; + + // Create the anonymous unique id, used for download statistics + Pathname idpath( home() / "AnonymousUniqueId"); + + try + { + updateFileContent( idpath, + std::bind(fileMissing, idpath), + generateRandomId ); + } + catch ( const Exception &e ) + { + WAR << "Can't create anonymous id file" << endl; + } + + } + + void TargetImpl::createLastDistributionFlavorCache() const + { + // create the anonymous unique id + // this value is used for statistics + Pathname flavorpath( home() / "LastDistributionFlavor"); + + // is there a product + Product::constPtr p = baseProduct(); + if ( ! p ) + { + WAR << "No base product, I won't create flavor cache" << endl; + return; + } + + std::string flavor = p->flavor(); + + try + { + + updateFileContent( flavorpath, + // only if flavor is not empty + functor::Constant( ! flavor.empty() ), + functor::Constant(flavor) ); + } + catch ( const Exception &e ) + { + WAR << "Can't create flavor cache" << endl; + return; + } + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : TargetImpl::~TargetImpl + // METHOD TYPE : Dtor + // + TargetImpl::~TargetImpl() + { + _rpm.closeDatabase(); + sigMultiversionSpecChanged(); // HACK: see sigMultiversionSpecChanged + MIL << "Closed target on " << _root << endl; + } + + /////////////////////////////////////////////////////////////////// + // + // solv file handling + // + /////////////////////////////////////////////////////////////////// + + Pathname TargetImpl::defaultSolvfilesPath() const + { + return Pathname::assertprefix( _root, ZConfig::instance().repoSolvfilesPath() / sat::Pool::instance().systemRepoAlias() ); + } + + void TargetImpl::clearCache() + { + Pathname base = solvfilesPath(); + filesystem::recursive_rmdir( base ); + } + + bool TargetImpl::buildCache() + { + Pathname base = solvfilesPath(); + Pathname rpmsolv = base/"solv"; + Pathname rpmsolvcookie = base/"cookie"; + + bool build_rpm_solv = true; + // lets see if the rpm solv cache exists + + RepoStatus rpmstatus( rpmDbRepoStatus(_root) && RepoStatus(_root/"etc/products.d") ); + + bool solvexisted = PathInfo(rpmsolv).isExist(); + if ( solvexisted ) + { + // see the status of the cache + PathInfo cookie( rpmsolvcookie ); + MIL << "Read cookie: " << cookie << endl; + if ( cookie.isExist() ) + { + RepoStatus status = RepoStatus::fromCookieFile(rpmsolvcookie); + // now compare it with the rpm database + if ( status == rpmstatus ) + build_rpm_solv = false; + MIL << "Read cookie: " << rpmsolvcookie << " says: " + << (build_rpm_solv ? "outdated" : "uptodate") << endl; + } + } + + if ( build_rpm_solv ) + { + // if the solvfile dir does not exist yet, we better create it + filesystem::assert_dir( base ); + + Pathname oldSolvFile( solvexisted ? rpmsolv : Pathname() ); // to speedup rpmdb2solv + + filesystem::TmpFile tmpsolv( filesystem::TmpFile::makeSibling( rpmsolv ) ); + if ( !tmpsolv ) + { + // Can't create temporary solv file, usually due to insufficient permission + // (user query while @System solv needs refresh). If so, try switching + // to a location within zypps temp. space (will be cleaned at application end). + + bool switchingToTmpSolvfile = false; + Exception ex("Failed to cache rpm database."); + ex.remember(str::form("Cannot create temporary file under %s.", base.c_str())); + + if ( ! solvfilesPathIsTemp() ) + { + base = getZYpp()->tmpPath() / sat::Pool::instance().systemRepoAlias(); + rpmsolv = base/"solv"; + rpmsolvcookie = base/"cookie"; + + filesystem::assert_dir( base ); + tmpsolv = filesystem::TmpFile::makeSibling( rpmsolv ); + + if ( tmpsolv ) + { + WAR << "Using a temporary solv file at " << base << endl; + switchingToTmpSolvfile = true; + _tmpSolvfilesPath = base; + } + else + { + ex.remember(str::form("Cannot create temporary file under %s.", base.c_str())); + } + } + + if ( ! switchingToTmpSolvfile ) + { + ZYPP_THROW(ex); + } + } + + // Take care we unlink the solvfile on exception + ManagedFile guard( base, filesystem::recursive_rmdir ); + + ExternalProgram::Arguments cmd; +#ifdef ZYPP_RPMDB2SOLV_PATH + cmd.push_back( ZYPP_RPMDB2SOLV_PATH ); +#else + cmd.push_back( "rpmdb2solv" ); +#endif + if ( ! _root.empty() ) { + cmd.push_back( "-r" ); + cmd.push_back( _root.asString() ); + } + cmd.push_back( "-D" ); + cmd.push_back( rpm().dbPath().asString() ); + cmd.push_back( "-X" ); // autogenerate pattern/product/... from -package + // bsc#1104415: no more application support // cmd.push_back( "-A" ); // autogenerate application pseudo packages + cmd.push_back( "-p" ); + cmd.push_back( Pathname::assertprefix( _root, "/etc/products.d" ).asString() ); + + if ( ! oldSolvFile.empty() ) + cmd.push_back( oldSolvFile.asString() ); + + cmd.push_back( "-o" ); + cmd.push_back( tmpsolv.path().asString() ); + + ExternalProgram prog( cmd, ExternalProgram::Stderr_To_Stdout ); + std::string errdetail; + + for ( std::string output( prog.receiveLine() ); output.length(); output = prog.receiveLine() ) { + WAR << " " << output; + if ( errdetail.empty() ) { + errdetail = prog.command(); + errdetail += '\n'; + } + errdetail += output; + } + + int ret = prog.close(); + if ( ret != 0 ) + { + Exception ex(str::form("Failed to cache rpm database (%d).", ret)); + ex.remember( errdetail ); + ZYPP_THROW(ex); + } + + ret = filesystem::rename( tmpsolv, rpmsolv ); + if ( ret != 0 ) + ZYPP_THROW(Exception("Failed to move cache to final destination")); + // if this fails, don't bother throwing exceptions + filesystem::chmod( rpmsolv, 0644 ); + + rpmstatus.saveToCookieFile(rpmsolvcookie); + + // We keep it. + guard.resetDispose(); + sat::updateSolvFileIndex( rpmsolv ); // content digest for zypper bash completion + + // system-hook: Finally send notification to plugins + if ( root() == "/" ) + { + PluginExecutor plugins; + plugins.load( ZConfig::instance().pluginsPath()/"system" ); + if ( plugins ) + plugins.send( PluginFrame( "PACKAGESETCHANGED" ) ); + } + } + else + { + // On the fly add missing solv.idx files for bash completion. + if ( ! PathInfo(base/"solv.idx").isExist() ) + sat::updateSolvFileIndex( rpmsolv ); + } + return build_rpm_solv; + } + + void TargetImpl::reload() + { + load( false ); + } + + void TargetImpl::unload() + { + Repository system( sat::Pool::instance().findSystemRepo() ); + if ( system ) + system.eraseFromPool(); + } + + void TargetImpl::load( bool force ) + { + bool newCache = buildCache(); + MIL << "New cache built: " << (newCache?"true":"false") << + ", force loading: " << (force?"true":"false") << endl; + + // now add the repos to the pool + sat::Pool satpool( sat::Pool::instance() ); + Pathname rpmsolv( solvfilesPath() / "solv" ); + MIL << "adding " << rpmsolv << " to pool(" << satpool.systemRepoAlias() << ")" << endl; + + // Providing an empty system repo, unload any old content + Repository system( sat::Pool::instance().findSystemRepo() ); + + if ( system && ! system.solvablesEmpty() ) + { + if ( newCache || force ) + { + system.eraseFromPool(); // invalidates system + } + else + { + return; // nothing to do + } + } + + if ( ! system ) + { + system = satpool.systemRepo(); + } + + try + { + MIL << "adding " << rpmsolv << " to system" << endl; + system.addSolv( rpmsolv ); + } + catch ( const Exception & exp ) + { + ZYPP_CAUGHT( exp ); + MIL << "Try to handle exception by rebuilding the solv-file" << endl; + clearCache(); + buildCache(); + + system.addSolv( rpmsolv ); + } + satpool.rootDir( _root ); + + // (Re)Load the requested locales et al. + // If the requested locales are empty, we leave the pool untouched + // to avoid undoing changes the application applied. We expect this + // to happen on a bare metal installation only. An already existing + // target should be loaded before its settings are changed. + { + const LocaleSet & requestedLocales( _requestedLocalesFile.locales() ); + if ( ! requestedLocales.empty() ) + { + satpool.initRequestedLocales( requestedLocales ); + } + } + { + if ( ! PathInfo( _autoInstalledFile.file() ).isExist() ) + { + // Initialize from history, if it does not exist + Pathname historyFile( Pathname::assertprefix( _root, ZConfig::instance().historyLogFile() ) ); + if ( PathInfo( historyFile ).isExist() ) + { + SolvIdentFile::Data onSystemByUser( getUserInstalledFromHistory( historyFile ) ); + SolvIdentFile::Data onSystemByAuto; + for_( it, system.solvablesBegin(), system.solvablesEnd() ) + { + IdString ident( (*it).ident() ); + if ( onSystemByUser.find( ident ) == onSystemByUser.end() ) + onSystemByAuto.insert( ident ); + } + _autoInstalledFile.setData( onSystemByAuto ); + } + // on the fly removed any obsolete SoftLocks file + filesystem::unlink( home() / "SoftLocks" ); + } + // read from AutoInstalled file + sat::StringQueue q; + for ( const auto & idstr : _autoInstalledFile.data() ) + q.push( idstr.id() ); + satpool.setAutoInstalled( q ); + } + + // Load the needreboot package specs + { + sat::SolvableSpec needrebootSpec; + needrebootSpec.addProvides( Capability("installhint(reboot-needed)") ); + needrebootSpec.addProvides( Capability("kernel") ); + + Pathname needrebootFile { Pathname::assertprefix( root(), ZConfig::instance().needrebootFile() ) }; + if ( PathInfo( needrebootFile ).isFile() ) + needrebootSpec.parseFrom( needrebootFile ); + + Pathname needrebootDir { Pathname::assertprefix( root(), ZConfig::instance().needrebootPath() ) }; + if ( PathInfo( needrebootDir ).isDir() ) + { + static const StrMatcher isRpmConfigBackup( "\\.rpm(new|save|orig)$", Match::REGEX ); + + filesystem::dirForEach( needrebootDir, filesystem::matchNoDots(), + [&]( const Pathname & dir_r, const char *const str_r )->bool + { + if ( ! isRpmConfigBackup( str_r ) ) + { + Pathname needrebootFile { needrebootDir / str_r }; + if ( PathInfo( needrebootFile ).isFile() ) + needrebootSpec.parseFrom( needrebootFile ); + } + return true; + }); + } + satpool.setNeedrebootSpec( std::move(needrebootSpec) ); + } + + if ( ZConfig::instance().apply_locks_file() ) + { + const HardLocksFile::Data & hardLocks( _hardLocksFile.data() ); + if ( ! hardLocks.empty() ) + { + ResPool::instance().setHardLockQueries( hardLocks ); + } + } + + // now that the target is loaded, we can cache the flavor + createLastDistributionFlavorCache(); + + MIL << "Target loaded: " << system.solvablesSize() << " resolvables" << endl; + } + + /////////////////////////////////////////////////////////////////// + // + // COMMIT + // + /////////////////////////////////////////////////////////////////// + ZYppCommitResult TargetImpl::commit( ResPool pool_r, const ZYppCommitPolicy & policy_rX ) + { + // ----------------------------------------------------------------- // + ZYppCommitPolicy policy_r( policy_rX ); + bool explicitDryRun = policy_r.dryRun(); // explicit dry run will trigger a fileconflict check, implicit (download-only) not. + + ShutdownLock lck("zypp", "Zypp commit running."); + + // Fake outstanding YCP fix: Honour restriction to media 1 + // at installation, but install all remaining packages if post-boot. + if ( policy_r.restrictToMedia() > 1 ) + policy_r.allMedia(); + + if ( policy_r.downloadMode() == DownloadDefault ) { + if ( root() == "/" ) + policy_r.downloadMode(DownloadInHeaps); + else { + if ( policy_r.singleTransModeEnabled() ) + policy_r.downloadMode(DownloadInAdvance); + else + policy_r.downloadMode(DownloadAsNeeded); + } + } + // DownloadOnly implies dry-run. + else if ( policy_r.downloadMode() == DownloadOnly ) + policy_r.dryRun( true ); + // ----------------------------------------------------------------- // + + MIL << "TargetImpl::commit(, " << policy_r << ")" << endl; + + /////////////////////////////////////////////////////////////////// + // Compute transaction: + /////////////////////////////////////////////////////////////////// + ZYppCommitResult result( root() ); + result.rTransaction() = pool_r.resolver().getTransaction(); + result.rTransaction().order(); + // steps: this is our todo-list + ZYppCommitResult::TransactionStepList & steps( result.rTransactionStepList() ); + if ( policy_r.restrictToMedia() ) + { + // Collect until the 1st package from an unwanted media occurs. + // Further collection could violate install order. + MIL << "Restrict to media number " << policy_r.restrictToMedia() << endl; + for_( it, result.transaction().begin(), result.transaction().end() ) + { + if ( makeResObject( *it )->mediaNr() > 1 ) + break; + steps.push_back( *it ); + } + } + else + { + result.rTransactionStepList().insert( steps.end(), result.transaction().begin(), result.transaction().end() ); + } + MIL << "Todo: " << result << endl; + + /////////////////////////////////////////////////////////////////// + // Prepare execution of commit plugins: + /////////////////////////////////////////////////////////////////// + PluginExecutor commitPlugins; + + if ( ( root() == "/" || zypp::env::TRANSACTIONAL_UPDATE() ) && ! policy_r.dryRun() ) + { + commitPlugins.load( ZConfig::instance().pluginsPath()/"commit" ); + } + if ( commitPlugins ) + commitPlugins.send( transactionPluginFrame( "COMMITBEGIN", steps ) ); + + /////////////////////////////////////////////////////////////////// + // Write out a testcase if we're in dist upgrade mode. + /////////////////////////////////////////////////////////////////// + if ( pool_r.resolver().upgradeMode() || pool_r.resolver().upgradingRepos() ) + { + if ( ! policy_r.dryRun() ) + { + writeUpgradeTestcase(); + } + else + { + DBG << "dryRun: Not writing upgrade testcase." << endl; + } + } + + /////////////////////////////////////////////////////////////////// + // Store non-package data: + /////////////////////////////////////////////////////////////////// + if ( ! policy_r.dryRun() ) + { + filesystem::assert_dir( home() ); + // requested locales + _requestedLocalesFile.setLocales( pool_r.getRequestedLocales() ); + // autoinstalled + { + SolvIdentFile::Data newdata; + for ( sat::Queue::value_type id : result.rTransaction().autoInstalled() ) + newdata.insert( IdString(id) ); + _autoInstalledFile.setData( newdata ); + } + // hard locks + if ( ZConfig::instance().apply_locks_file() ) + { + HardLocksFile::Data newdata; + pool_r.getHardLockQueries( newdata ); + _hardLocksFile.setData( newdata ); + } + } + else + { + DBG << "dryRun: Not storing non-package data." << endl; + } + + /////////////////////////////////////////////////////////////////// + // First collect and display all messages + // associated with patches to be installed. + /////////////////////////////////////////////////////////////////// + if ( ! policy_r.dryRun() ) + { + for_( it, steps.begin(), steps.end() ) + { + if ( ! it->satSolvable().isKind() ) + continue; + + PoolItem pi( *it ); + if ( ! pi.status().isToBeInstalled() ) + continue; + + Patch::constPtr patch( asKind(pi.resolvable()) ); + if ( ! patch ||patch->message().empty() ) + continue; + + MIL << "Show message for " << patch << endl; + callback::SendReport report; + if ( ! report->show( patch ) ) + { + WAR << "commit aborted by the user" << endl; + ZYPP_THROW( TargetAbortedException( ) ); + } + } + } + else + { + DBG << "dryRun: Not checking patch messages." << endl; + } + + /////////////////////////////////////////////////////////////////// + // Remove/install packages. + /////////////////////////////////////////////////////////////////// + + bool singleTransMode = policy_r.singleTransModeEnabled(); + + DBG << "commit log file is set to: " << HistoryLog::fname() << endl; + if ( ! policy_r.dryRun() || policy_r.downloadMode() == DownloadOnly ) + { + // Prepare the package cache. Pass all items requiring download. + CommitPackageCache packageCache; + packageCache.setCommitList( steps.begin(), steps.end() ); + + bool miss = false; + if ( policy_r.downloadMode() != DownloadAsNeeded ) + { + // Preload the cache. Until now this means pre-loading all packages. + // Once DownloadInHeaps is fully implemented, this will change and + // we may actually have more than one heap. + for_( it, steps.begin(), steps.end() ) + { + switch ( it->stepType() ) + { + case sat::Transaction::TRANSACTION_INSTALL: + case sat::Transaction::TRANSACTION_MULTIINSTALL: + // proceed: only install actionas may require download. + break; + + default: + // next: no download for or non-packages and delete actions. + continue; + break; + } + + PoolItem pi( *it ); + if ( pi->isKind() || pi->isKind() ) + { + ManagedFile localfile; + try + { + localfile = packageCache.get( pi ); + localfile.resetDispose(); // keep the package file in the cache + } + catch ( const AbortRequestException & exp ) + { + it->stepStage( sat::Transaction::STEP_ERROR ); + miss = true; + WAR << "commit cache preload aborted by the user" << endl; + ZYPP_THROW( TargetAbortedException( ) ); + break; + } + catch ( const SkipRequestException & exp ) + { + ZYPP_CAUGHT( exp ); + it->stepStage( sat::Transaction::STEP_ERROR ); + miss = true; + WAR << "Skipping cache preload package " << pi->asKind() << " in commit" << endl; + continue; + } + catch ( const Exception & exp ) + { + // bnc #395704: missing catch causes abort. + // TODO see if packageCache fails to handle errors correctly. + ZYPP_CAUGHT( exp ); + it->stepStage( sat::Transaction::STEP_ERROR ); + miss = true; + INT << "Unexpected Error: Skipping cache preload package " << pi->asKind() << " in commit" << endl; + continue; + } + } + } + packageCache.preloaded( true ); // try to avoid duplicate infoInCache CBs in commit + } + + if ( miss ) + { + ERR << "Some packages could not be provided. Aborting commit."<< endl; + } + else + { + if ( ! policy_r.dryRun() ) + { + if ( policy_r.singleTransModeEnabled() ) { + commitInSingleTransaction( policy_r, packageCache, result ); + } else { + // if cache is preloaded, check for file conflicts + commitFindFileConflicts( policy_r, result ); + commit( policy_r, packageCache, result ); + } + } + else + { + DBG << "dryRun/downloadOnly: Not installing/deleting anything." << endl; + if ( explicitDryRun ) { + if ( policy_r.singleTransModeEnabled() ) { + // single trans mode does a test install via rpm + commitInSingleTransaction( policy_r, packageCache, result ); + } else { + // if cache is preloaded, check for file conflicts + commitFindFileConflicts( policy_r, result ); + } + } + } + } + } + else + { + DBG << "dryRun: Not downloading/installing/deleting anything." << endl; + if ( explicitDryRun ) { + // if cache is preloaded, check for file conflicts + commitFindFileConflicts( policy_r, result ); + } + } + + { + // NOTE: Removing rpm in a transaction, rpm removes the /var/lib/rpm compat symlink. + // We re-create it, in case it was lost to prevent legacy tools from accidentally + // assuming no database is present. + if ( ! PathInfo(_root/"/var/lib/rpm",PathInfo::LSTAT).isExist() + && PathInfo(_root/"/usr/lib/sysimage/rpm").isDir() ) { + WAR << "(rpm removed in commit?) Inject missing /var/lib/rpm compat symlink to /usr/lib/sysimage/rpm" << endl; + filesystem::assert_dir( _root/"/var/lib" ); + filesystem::symlink( "../../usr/lib/sysimage/rpm", _root/"/var/lib/rpm" ); + } + } + + /////////////////////////////////////////////////////////////////// + // Send result to commit plugins: + /////////////////////////////////////////////////////////////////// + if ( commitPlugins ) + commitPlugins.send( transactionPluginFrame( "COMMITEND", steps ) ); + + /////////////////////////////////////////////////////////////////// + // Try to rebuild solv file while rpm database is still in cache + /////////////////////////////////////////////////////////////////// + if ( ! policy_r.dryRun() ) + { + buildCache(); + } + + MIL << "TargetImpl::commit(, " << policy_r << ") returns: " << result << endl; + return result; + } + + /////////////////////////////////////////////////////////////////// + // + // COMMIT internal + // + /////////////////////////////////////////////////////////////////// + namespace + { + struct NotifyAttemptToModify + { + NotifyAttemptToModify( ZYppCommitResult & result_r ) : _result( result_r ) {} + + void operator()() + { if ( _guard ) { _result.attemptToModify( true ); _guard = false; } } + + TrueBool _guard; + ZYppCommitResult & _result; + }; + } // namespace + + void TargetImpl::commit( const ZYppCommitPolicy & policy_r, + CommitPackageCache & packageCache_r, + ZYppCommitResult & result_r ) + { + // steps: this is our todo-list + ZYppCommitResult::TransactionStepList & steps( result_r.rTransactionStepList() ); + MIL << "TargetImpl::commit(" << policy_r << ")" << steps.size() << endl; + + HistoryLog().stampCommand(); + + // Send notification once upon 1st call to rpm + NotifyAttemptToModify attemptToModify( result_r ); + + bool abort = false; + + // bsc#1181328: Some systemd tools require /proc to be mounted + AssertProcMounted assertProcMounted( _root ); + AssertDevMounted assertDevMounted( _root ); // also /dev + + RpmPostTransCollector postTransCollector( _root ); + std::vector successfullyInstalledPackages; + TargetImpl::PoolItemList remaining; + + for_( step, steps.begin(), steps.end() ) + { + PoolItem citem( *step ); + if ( step->stepType() == sat::Transaction::TRANSACTION_IGNORE ) + { + if ( citem->isKind() ) + { + // for packages this means being obsoleted (by rpm) + // thius no additional action is needed. + step->stepStage( sat::Transaction::STEP_DONE ); + continue; + } + } + + if ( citem->isKind() ) + { + Package::constPtr p = citem->asKind(); + if ( citem.status().isToBeInstalled() ) + { + ManagedFile localfile; + try + { + localfile = packageCache_r.get( citem ); + } + catch ( const AbortRequestException &e ) + { + WAR << "commit aborted by the user" << endl; + abort = true; + step->stepStage( sat::Transaction::STEP_ERROR ); + break; + } + catch ( const SkipRequestException &e ) + { + ZYPP_CAUGHT( e ); + WAR << "Skipping package " << p << " in commit" << endl; + step->stepStage( sat::Transaction::STEP_ERROR ); + continue; + } + catch ( const Exception &e ) + { + // bnc #395704: missing catch causes abort. + // TODO see if packageCache fails to handle errors correctly. + ZYPP_CAUGHT( e ); + INT << "Unexpected Error: Skipping package " << p << " in commit" << endl; + step->stepStage( sat::Transaction::STEP_ERROR ); + continue; + } + + // create a installation progress report proxy + RpmInstallPackageReceiver progress( citem.resolvable() ); + progress.connect(); // disconnected on destruction. + + bool success = false; + rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB ); + // Why force and nodeps? + // + // Because zypp builds the transaction and the resolver asserts that + // everything is fine. + // We use rpm just to unpack and register the package in the database. + // We do this step by step, so rpm is not aware of the bigger context. + // So we turn off rpms internal checks, because we do it inside zypp. + flags |= rpm::RPMINST_NODEPS; + flags |= rpm::RPMINST_FORCE; + // + if (p->multiversionInstall()) flags |= rpm::RPMINST_NOUPGRADE; + if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST; + if (policy_r.rpmExcludeDocs()) flags |= rpm::RPMINST_EXCLUDEDOCS; + if (policy_r.rpmNoSignature()) flags |= rpm::RPMINST_NOSIGNATURE; + + attemptToModify(); + try + { + progress.tryLevel( target::rpm::InstallResolvableReport::RPM_NODEPS_FORCE ); + rpm().installPackage( localfile, flags, &postTransCollector ); + HistoryLog().install(citem); + + if ( progress.aborted() ) + { + WAR << "commit aborted by the user" << endl; + localfile.resetDispose(); // keep the package file in the cache + abort = true; + step->stepStage( sat::Transaction::STEP_ERROR ); + break; + } + else + { + if ( citem.isNeedreboot() ) { + auto rebootNeededFile = root() / "/run/reboot-needed"; + if ( filesystem::assert_file( rebootNeededFile ) == EEXIST) + filesystem::touch( rebootNeededFile ); + } + + success = true; + step->stepStage( sat::Transaction::STEP_DONE ); + } + } + catch ( Exception & excpt_r ) + { + ZYPP_CAUGHT(excpt_r); + localfile.resetDispose(); // keep the package file in the cache + + if ( policy_r.dryRun() ) + { + WAR << "dry run failed" << endl; + step->stepStage( sat::Transaction::STEP_ERROR ); + break; + } + // else + if ( progress.aborted() ) + { + WAR << "commit aborted by the user" << endl; + abort = true; + } + else + { + WAR << "Install failed" << endl; + } + step->stepStage( sat::Transaction::STEP_ERROR ); + break; // stop + } + + if ( success && !policy_r.dryRun() ) + { + citem.status().resetTransact( ResStatus::USER ); + successfullyInstalledPackages.push_back( citem.satSolvable() ); + step->stepStage( sat::Transaction::STEP_DONE ); + } + } + else + { + RpmRemovePackageReceiver progress( citem.resolvable() ); + progress.connect(); // disconnected on destruction. + + bool success = false; + rpm::RpmInstFlags flags( policy_r.rpmInstFlags() & rpm::RPMINST_JUSTDB ); + flags |= rpm::RPMINST_NODEPS; + if (policy_r.dryRun()) flags |= rpm::RPMINST_TEST; + + attemptToModify(); + try + { + rpm().removePackage( p, flags, &postTransCollector ); + HistoryLog().remove(citem); + + if ( progress.aborted() ) + { + WAR << "commit aborted by the user" << endl; + abort = true; + step->stepStage( sat::Transaction::STEP_ERROR ); + break; + } + else + { + success = true; + step->stepStage( sat::Transaction::STEP_DONE ); + } + } + catch (Exception & excpt_r) + { + ZYPP_CAUGHT( excpt_r ); + if ( progress.aborted() ) + { + WAR << "commit aborted by the user" << endl; + abort = true; + step->stepStage( sat::Transaction::STEP_ERROR ); + break; + } + // else + WAR << "removal of " << p << " failed"; + step->stepStage( sat::Transaction::STEP_ERROR ); + } + if ( success && !policy_r.dryRun() ) + { + citem.status().resetTransact( ResStatus::USER ); + step->stepStage( sat::Transaction::STEP_DONE ); + } + } + } + else if ( ! policy_r.dryRun() ) // other resolvables (non-Package) + { + // Status is changed as the buddy package buddy + // gets installed/deleted. Handle non-buddies only. + if ( ! citem.buddy() ) + { + if ( citem->isKind() ) + { + Product::constPtr p = citem->asKind(); + if ( citem.status().isToBeInstalled() ) + { + ERR << "Can't install orphan product without release-package! " << citem << endl; + } + else + { + // Deleting the corresponding product entry is all we con do. + // So the product will no longer be visible as installed. + std::string referenceFilename( p->referenceFilename() ); + if ( referenceFilename.empty() ) + { + ERR << "Can't remove orphan product without 'referenceFilename'! " << citem << endl; + } + else + { + Pathname referencePath { Pathname("/etc/products.d") / referenceFilename }; // no root prefix for rpmdb lookup! + if ( ! rpm().hasFile( referencePath.asString() ) ) + { + // If it's not owned by a package, we can delete it. + referencePath = Pathname::assertprefix( _root, referencePath ); // now add a root prefix + if ( filesystem::unlink( referencePath ) != 0 ) + ERR << "Delete orphan product failed: " << referencePath << endl; + } + else + { + WAR << "Won't remove orphan product: '/etc/products.d/" << referenceFilename << "' is owned by a package." << endl; + } + } + } + } + else if ( citem->isKind() && citem.status().isToBeInstalled() ) + { + // SrcPackage is install-only + SrcPackage::constPtr p = citem->asKind(); + installSrcPackage( p ); + } + + citem.status().resetTransact( ResStatus::USER ); + step->stepStage( sat::Transaction::STEP_DONE ); + } + + } // other resolvables + + } // for + + // Process any remembered %posttrans and/or %transfiletrigger(postun|in) + // scripts. If aborting, at least log if scripts were omitted. + if ( not abort ) + postTransCollector.executeScripts( rpm() ); + else + postTransCollector.discardScripts(); + + // Check presence of update scripts/messages. If aborting, + // at least log omitted scripts. + if ( ! successfullyInstalledPackages.empty() ) + { + if ( ! RunUpdateScripts( _root, ZConfig::instance().update_scriptsPath(), + successfullyInstalledPackages, abort ) ) + { + WAR << "Commit aborted by the user" << endl; + abort = true; + } + // send messages after scripts in case some script generates output, + // that should be kept in t %ghost message file. + RunUpdateMessages( _root, ZConfig::instance().update_messagesPath(), + successfullyInstalledPackages, + result_r ); + } + + // jsc#SLE-5116: Log patch status changes to history + // NOTE: Should be the last action as it may need to reload + // the Target in case of an incomplete transaction. + logPatchStatusChanges( result_r.transaction(), *this ); + + if ( abort ) + { + HistoryLog().comment( "Commit was aborted." ); + ZYPP_THROW( TargetAbortedException( ) ); + } + } + + + /////////////////////////////////////////////////////////////////// + /// \brief Convenience SendReport wrapper. + /// + /// Provide convenience methods to invoke a generic \ref report + /// supplied with the proper \ref UserData and \ref ContentType, + /////////////////////////////////////////////////////////////////// + struct SendSingleTransReport : public callback::SendReport + { + /** Convenience to send a \ref contentLogline. */ + void sendLogline( const std::string & line_r, ReportType::loglevel level_r = ReportType::loglevel::msg ) + { + callback::UserData data { ReportType::contentLogline }; + data.set( "line", std::cref(line_r) ); + data.set( "level", level_r ); + report( data ); + } + /** Convenience to send a \ref contentLogline translating a rpm loglevel. */ + void sendLoglineRpm( const std::string & line_r, unsigned rpmlevel_r ) + { + auto u2rpmlevel = []( unsigned rpmlevel_r ) -> ReportType::loglevel { + switch ( rpmlevel_r ) { + case RPMLOG_EMERG: [[fallthrough]]; // system is unusable + case RPMLOG_ALERT: [[fallthrough]]; // action must be taken immediately + case RPMLOG_CRIT: // critical conditions + return ReportType::loglevel::crt; + case RPMLOG_ERR: // error conditions + return ReportType::loglevel::err; + case RPMLOG_WARNING: // warning conditions + return ReportType::loglevel::war; + default: [[fallthrough]]; + case RPMLOG_NOTICE: [[fallthrough]]; // normal but significant condition + case RPMLOG_INFO: // informational + return ReportType::loglevel::msg; + case RPMLOG_DEBUG: + return ReportType::loglevel::dbg; + } + }; + sendLogline( line_r, u2rpmlevel( rpmlevel_r ) ); + } + + private: + void report( const callback::UserData & userData_r ) + { (*this)->report( userData_r ); } + }; + + const callback::UserData::ContentType rpm::SingleTransReport::contentLogline { "zypp-rpm", "logline" }; + + const callback::UserData::ContentType rpm::InstallResolvableReportSA::contentRpmout( "zypp-rpm","installpkgsa" ); + const callback::UserData::ContentType rpm::RemoveResolvableReportSA::contentRpmout( "zypp-rpm","removepkgsa" ); + const callback::UserData::ContentType rpm::CommitScriptReportSA::contentRpmout( "zypp-rpm","scriptsa" ); + const callback::UserData::ContentType rpm::TransactionReportSA::contentRpmout( "zypp-rpm","transactionsa" ); + const callback::UserData::ContentType rpm::CleanupPackageReportSA::contentRpmout( "zypp-rpm","cleanupkgsa" ); + + void TargetImpl::commitInSingleTransaction(const ZYppCommitPolicy &policy_r, CommitPackageCache &packageCache_r, ZYppCommitResult &result_r) + { + SendSingleTransReport report; // active throughout the whole rpm transaction + + // steps: this is our todo-list + ZYppCommitResult::TransactionStepList & steps( result_r.rTransactionStepList() ); + MIL << "TargetImpl::commit(" << policy_r << ")" << steps.size() << endl; + + HistoryLog().stampCommand(); + + // Send notification once upon calling rpm + NotifyAttemptToModify attemptToModify( result_r ); + + // let zypper know we executed in one big transaction so in case of failures it can show extended error information + result_r.setSingleTransactionMode( true ); + + // bsc#1181328: Some systemd tools require /proc to be mounted + AssertProcMounted assertProcMounted( _root ); + AssertDevMounted assertDevMounted( _root ); // also /dev + + // Why nodeps? + // + // Because zypp builds the transaction and the resolver asserts that + // everything is fine, or the user decided to ignore problems. + rpm::RpmInstFlags flags( policy_r.rpmInstFlags() + | rpm::RPMINST_NODEPS + // skip signature checks, we did that already + | rpm::RPMINST_NODIGEST + | rpm::RPMINST_NOSIGNATURE + // ignore untrusted keys since we already checked those earlier + | rpm::RPMINST_ALLOWUNTRUSTED ); + + proto::target::Commit commit; + commit.flags = flags; + commit.ignoreArch = ( !ZConfig::instance().systemArchitecture().compatibleWith( ZConfig::instance().defaultSystemArchitecture() ) ); + commit.arch = ZConfig::instance().systemArchitecture().asString(); + commit.dbPath = rpm().dbPath().asString(); + commit.root = rpm().root().asString(); + commit.lockFilePath = ZYppFactory::lockfileDir().asString(); + + bool abort = false; + zypp::AutoDispose> locCache([]( std::unordered_map &data ){ + for ( auto &[_, value] : data ) { + (void)_; // unsused; for older g++ versions + value.resetDispose(); + } + data.clear(); + }); + + // fill the transaction + for ( int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort ; ++stepId ) { + auto &step = steps[stepId]; + PoolItem citem( step ); + if ( step.stepType() == sat::Transaction::TRANSACTION_IGNORE ) { + if ( citem->isKind() ) + { + // for packages this means being obsoleted (by rpm) + // thius no additional action is needed. + step.stepStage( sat::Transaction::STEP_DONE ); + continue; + } + } + + if ( citem->isKind() ) { + Package::constPtr p = citem->asKind(); + if ( citem.status().isToBeInstalled() ) + { + try { + locCache.value()[stepId] = packageCache_r.get( citem ); + + proto::target::InstallStep tStep; + tStep.stepId = stepId; + tStep.pathname = locCache.value()[stepId]->asString(); + tStep.multiversion = p->multiversionInstall() ; + + commit.transactionSteps.push_back( std::move(tStep) ); + } + catch ( const AbortRequestException &e ) + { + WAR << "commit aborted by the user" << endl; + abort = true; + step.stepStage( sat::Transaction::STEP_ERROR ); + break; + } + catch ( const SkipRequestException &e ) + { + ZYPP_CAUGHT( e ); + WAR << "Skipping package " << p << " in commit" << endl; + step.stepStage( sat::Transaction::STEP_ERROR ); + continue; + } + catch ( const Exception &e ) + { + // bnc #395704: missing catch causes abort. + // TODO see if packageCache fails to handle errors correctly. + ZYPP_CAUGHT( e ); + INT << "Unexpected Error: Skipping package " << p << " in commit" << endl; + step.stepStage( sat::Transaction::STEP_ERROR ); + continue; + } + } else { + + proto::target::RemoveStep tStep; + tStep.stepId = stepId; + tStep.name = p->name(); + tStep.version = p->edition().version(); + tStep.release = p->edition().release(); + tStep.arch = p->arch().asString(); + commit.transactionSteps.push_back(std::move(tStep)); + + } + } else if ( citem->isKind() && citem.status().isToBeInstalled() ) { + // SrcPackage is install-only + SrcPackage::constPtr p = citem->asKind(); + + try { + // provide on local disk + locCache.value()[stepId] = provideSrcPackage( p ); + + proto::target::InstallStep tStep; + tStep.stepId = stepId; + tStep.pathname = locCache.value()[stepId]->asString(); + tStep.multiversion = false; + commit.transactionSteps.push_back(std::move(tStep)); + + } catch ( const Exception &e ) { + ZYPP_CAUGHT( e ); + INT << "Unexpected Error: Skipping package " << p << " in commit" << endl; + step.stepStage( sat::Transaction::STEP_ERROR ); + continue; + } + } + } + + std::vector successfullyInstalledPackages; + + if ( commit.transactionSteps.size() ) { + + // create the event loop early + auto loop = zyppng::EventLoop::create(); + + attemptToModify(); + + const std::vector interceptedSignals { + SIGINT, + SIGTERM, + SIGHUP, + SIGQUIT + }; + + auto unixSignals = loop->eventDispatcher()->unixSignalSource(); + unixSignals->sigReceived ().connect ([]( int signum ){ + // translator: %1% is the received unix signal name, %2% is the numerical value of the received signal + JobReport::error ( str::Format(_("Received signal :\"%1% (%2%)\", to ensure the consistency of the system it is not possible to cancel a running rpm transaction.") ) % strsignal(signum) % signum ); + }); + for( const auto &sig : interceptedSignals ) + unixSignals->addSignal ( sig ); + + Deferred cleanupSigs([&](){ + for( const auto &sig : interceptedSignals ) + unixSignals->removeSignal ( sig ); + }); + + // transaction related variables: + // + // the index of the step in the transaction list that we currenty execute. + // this can be -1 + int currentStepId = -1; + + // sync flag, every time zypp-rpm finishes executing a step it writes a tag into + // the script fd, once we receive it we set this flag to true and ignore all output + // that is written to the pipe ( aside from buffering it ) until we finalize the current report + // and start a new one + bool gotEndOfScript = false; + + // the possible reports we emit during the transaction + std::unique_ptr> transactionreport; + std::unique_ptr> installreport; + std::unique_ptr> uninstallreport; + std::unique_ptr> scriptreport; + std::unique_ptr> cleanupreport; + + // this will be set if we receive a transaction error description + std::optional transactionError; + + // infos about the currently executed script, empty if no script is currently executed + std::string currentScriptType; + std::string currentScriptPackage; + + // buffer to collect rpm output per report, this will be written to the log once the + // report ends + std::string rpmmsg; + + // maximum number of lines that we are buffering in rpmmsg + constexpr auto MAXRPMMESSAGELINES = 10000; + + // current number of lines in the rpmmsg line buffer. This is capped to MAXRPMMESSAGELINES + unsigned lineno = 0; + + // the sources to communicate with zypp-rpm, we will associate pipes with them further down below + auto msgSource = zyppng::AsyncDataSource::create(); + auto scriptSource = zyppng::AsyncDataSource::create(); + + // this will be the communication channel, will be created once the process starts and + // we can receive data + zyppng::StompFrameStreamRef msgStream; + + + // helper function that sends RPM output to the currently active report, writing a warning to the log + // if there is none + const auto &sendRpmLineToReport = [&]( const std::string &line ){ + + const auto &sendLogRep = [&]( auto &report, const auto &cType ){ + callback::UserData cmdout(cType); + if ( currentStepId >= 0 ) + cmdout.set( "solvable", steps.at(currentStepId).satSolvable() ); + cmdout.set( "line", line ); + report->report(cmdout); + }; + + if ( installreport ) { + sendLogRep( (*installreport), rpm::InstallResolvableReportSA::contentRpmout ); + } else if ( uninstallreport ) { + sendLogRep( (*uninstallreport), rpm::RemoveResolvableReportSA::contentRpmout ); + } else if ( scriptreport ) { + sendLogRep( (*scriptreport), rpm::CommitScriptReportSA::contentRpmout ); + } else if ( transactionreport ) { + sendLogRep( (*transactionreport), rpm::TransactionReportSA::contentRpmout ); + } else if ( cleanupreport ) { + sendLogRep( (*cleanupreport), rpm::CleanupPackageReportSA::contentRpmout ); + } else { + WAR << "Got rpm output without active report " << line; // no endl! - readLine does not trim + } + + // remember rpm output + if ( lineno >= MAXRPMMESSAGELINES ) { + if ( line.find( " scriptlet failed, " ) == std::string::npos ) // always log %script errors + return; + } + rpmmsg += line; + if ( line.back() != '\n' ) + rpmmsg += '\n'; + }; + + + // callback and helper function to process data that is received on the script FD + const auto &processDataFromScriptFd = [&](){ + + while ( scriptSource->canReadLine() ) { + + if ( gotEndOfScript ) + return; + + std::string l = scriptSource->readLine().asString(); + if( str::endsWith( l, endOfScriptTag ) ) { + gotEndOfScript = true; + std::string::size_type rawsize { l.size() - endOfScriptTag.size() }; + if ( not rawsize ) + return; + l = l.substr( 0, rawsize ); + } + L_DBG("zypp-rpm") << "[rpm> " << l; // no endl! - readLine does not trim + sendRpmLineToReport( l ); + } + }; + scriptSource->sigReadyRead().connect( processDataFromScriptFd ); + + // helper function that just waits until the end of script tag was received on the scriptSource + const auto &waitForScriptEnd = [&]() { + + // nothing to wait for + if ( gotEndOfScript ) + return; + + // we process all available data + processDataFromScriptFd(); + + // end of script is always sent by zypp-rpm, we need to wait for it to keep order + while ( scriptSource->readFdOpen() && scriptSource->canRead() && !gotEndOfScript ) { + // readyRead will trigger processDataFromScriptFd so no need to call it again + // we still got nothing, lets wait for more + scriptSource->waitForReadyRead( 100 ); + } + }; + + const auto &aboutToStartNewReport = [&](){ + + if ( transactionreport || installreport || uninstallreport || scriptreport || cleanupreport ) { + ERR << "There is still a running report, this is a bug" << std::endl; + assert(false); + } + + gotEndOfScript = false; + }; + + const auto &writeRpmMsgToHistory = [&](){ + if ( rpmmsg.size() == 0 ) + return; + + if ( lineno >= MAXRPMMESSAGELINES ) + rpmmsg += "[truncated]\n"; + + std::ostringstream sstr; + sstr << "rpm output:" << endl << rpmmsg << endl; + HistoryLog().comment(sstr.str()); + }; + + // helper function that closes the current report and cleans up the ressources + const auto &finalizeCurrentReport = [&]() { + sat::Transaction::Step *step = nullptr; + Resolvable::constPtr resObj; + if ( currentStepId >= 0 ) { + step = &steps.at(currentStepId); + resObj = makeResObject( step->satSolvable() ); + } + + if ( installreport ) { + waitForScriptEnd(); + if ( step->stepStage() == sat::Transaction::STEP_ERROR ) { + + HistoryLog().comment( + str::form("%s install failed", step->ident().c_str()), + true /*timestamp*/); + + writeRpmMsgToHistory(); + + ( *installreport)->finish( resObj, rpm::InstallResolvableReportSA::INVALID ); + } else { + ( *installreport)->progress( 100, resObj ); + ( *installreport)->finish( resObj, rpm::InstallResolvableReportSA::NO_ERROR ); + + if ( currentStepId >= 0 ) + locCache.value().erase( currentStepId ); + successfullyInstalledPackages.push_back( step->satSolvable() ); + + PoolItem citem( *step ); + if ( !( flags & rpm::RPMINST_TEST ) ) { + // @TODO are we really doing this just for install? + if ( citem.isNeedreboot() ) { + auto rebootNeededFile = root() / "/run/reboot-needed"; + if ( filesystem::assert_file( rebootNeededFile ) == EEXIST) + filesystem::touch( rebootNeededFile ); + } + citem.status().resetTransact( ResStatus::USER ); + HistoryLog().install(citem); + } + + HistoryLog().comment( + str::form("%s installed ok", step->ident().c_str()), + true /*timestamp*/); + + writeRpmMsgToHistory(); + } + } + if ( uninstallreport ) { + waitForScriptEnd(); + if ( step->stepStage() == sat::Transaction::STEP_ERROR ) { + + HistoryLog().comment( + str::form("%s uninstall failed", step->ident().c_str()), + true /*timestamp*/); + + writeRpmMsgToHistory(); + + ( *uninstallreport)->finish( resObj, rpm::RemoveResolvableReportSA::INVALID ); + } else { + ( *uninstallreport)->progress( 100, resObj ); + ( *uninstallreport)->finish( resObj, rpm::RemoveResolvableReportSA::NO_ERROR ); + + PoolItem citem( *step ); + HistoryLog().remove(citem); + + HistoryLog().comment( + str::form("%s removed ok", step->ident().c_str()), + true /*timestamp*/); + + writeRpmMsgToHistory(); + } + } + if ( scriptreport ) { + waitForScriptEnd(); + ( *scriptreport)->progress( 100, resObj ); + ( *scriptreport)->finish( resObj, rpm::CommitScriptReportSA::NO_ERROR ); + } + if ( transactionreport ) { + waitForScriptEnd(); + ( *transactionreport)->progress( 100 ); + ( *transactionreport)->finish( rpm::TransactionReportSA::NO_ERROR ); + } + if ( cleanupreport ) { + waitForScriptEnd(); + ( *cleanupreport)->progress( 100 ); + ( *cleanupreport)->finish( rpm::CleanupPackageReportSA::NO_ERROR ); + } + currentStepId = -1; + lineno = 0; + rpmmsg.clear(); + currentScriptType.clear(); + currentScriptPackage.clear(); + installreport.reset(); + uninstallreport.reset(); + scriptreport.reset(); + transactionreport.reset(); + cleanupreport.reset(); + }; + + // This sets up the process and pushes the required transactions steps to it + // careful when changing code here, zypp-rpm relies on the exact order data is transferred: + // + // 1) Size of the commit message , sizeof(zyppng::rpc::HeaderSizeType) + // 2) The Commit Proto message, directly serialized to the FD, without Envelope + // 3) 2 writeable FDs that are set up by the parent Process when forking. The first FD is to be used for message sending, the second one for script output + + constexpr std::string_view zyppRpmBinary(ZYPP_RPM_BINARY); + + const char *argv[] = { + //"gdbserver", + //"localhost:10001", + zyppRpmBinary.data(), + nullptr + }; + auto prog = zyppng::Process::create(); + + // we set up a pipe to communicate with the process, it is too dangerous to use stdout since librpm + // might print to it. + auto messagePipe = zyppng::Pipe::create(); + if ( !messagePipe ) + ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to create message pipe" ) ); + + // open a pipe that we are going to use to receive script output, this is a librpm feature, there is no other + // way than a FD to redirect that output + auto scriptPipe = zyppng::Pipe::create(); + if ( !scriptPipe ) + ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to create scriptfd" ) ); + + prog->addFd( messagePipe->writeFd ); + prog->addFd( scriptPipe->writeFd ); + + // set up the AsyncDataSource to read script output + if ( !scriptSource->openFds( std::vector{ scriptPipe->readFd } ) ) + ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to open scriptFD to subprocess" ) ); + + const auto &processMessages = [&] ( ) { + + // lambda function that parses the passed message type and checks if the stepId is a valid offset + // in the steps list. + const auto &checkMsgWithStepId = [&steps]( auto &p ){ + if ( !p ) { + ERR << "Failed to parse message from zypp-rpm." << std::endl; + return false; + } + + auto id = p->stepId; + if ( id < 0 || id >= steps.size() ) { + ERR << "Received invalid stepId: " << id << " in " << p->typeName << " message from zypp-rpm, ignoring." << std::endl; + return false; + } + return true; + }; + + while ( const auto &m = msgStream->nextMessage() ) { + + // due to librpm behaviour we need to make sense of the order of messages we receive + // because we first get a PackageFinished BEFORE getting a PackageError, same applies to + // Script related messages. What we do is remember the current step we are in and only close + // the step when we get the start of the next one + const auto &mName = m->command(); + if ( mName == proto::target::RpmLog::typeName ) { + + const auto &p = proto::target::RpmLog::fromStompMessage (*m); + if ( !p ) { + ERR << "Failed to parse " << proto::target::RpmLog::typeName << " message from zypp-rpm." << std::endl; + continue; + } + ( p->level >= RPMLOG_ERR ? L_ERR("zypp-rpm") + : p->level >= RPMLOG_WARNING ? L_WAR("zypp-rpm") + : L_DBG("zypp-rpm") ) << "[rpm " << p->level << "> " << p->line; // no endl! - readLine does not trim + report.sendLoglineRpm( p->line, p->level ); + + } else if ( mName == proto::target::PackageBegin::typeName ) { + finalizeCurrentReport(); + + const auto &p = proto::target::PackageBegin::fromStompMessage(*m); + if ( !checkMsgWithStepId( p ) ) + continue; + + aboutToStartNewReport(); + + auto & step = steps.at( p->stepId ); + currentStepId = p->stepId; + if ( step.stepType() == sat::Transaction::TRANSACTION_ERASE ) { + uninstallreport = std::make_unique< callback::SendReport > (); + ( *uninstallreport )->start( makeResObject( step.satSolvable() ) ); + } else { + installreport = std::make_unique< callback::SendReport > (); + ( *installreport )->start( makeResObject( step.satSolvable() ) ); + } + + } else if ( mName == proto::target::PackageFinished::typeName ) { + const auto &p = proto::target::PackageFinished::fromStompMessage(*m); + if ( !checkMsgWithStepId( p ) ) + continue; + + // here we only set the step stage to done, we however need to wait for the next start in order to send + // the finished report since there might be a error pending to be reported + steps[ p->stepId ].stepStage( sat::Transaction::STEP_DONE ); + + } else if ( mName == proto::target::PackageProgress::typeName ) { + const auto &p = proto::target::PackageProgress::fromStompMessage(*m); + if ( !checkMsgWithStepId( p ) ) + continue; + + if ( uninstallreport ) + (*uninstallreport)->progress( p->amount, makeResObject( steps.at( p->stepId ) )); + else if ( installreport ) + (*installreport)->progress( p->amount, makeResObject( steps.at( p->stepId ) )); + else + ERR << "Received a " << mName << " message but there is no corresponding report running." << std::endl; + + } else if ( mName == proto::target::PackageError::typeName ) { + const auto &p = proto::target::PackageError::fromStompMessage(*m); + if ( !checkMsgWithStepId( p ) ) + continue; + + if ( p->stepId >= 0 && p->stepId < steps.size() ) + steps[ p->stepId ].stepStage( sat::Transaction::STEP_ERROR ); + + finalizeCurrentReport(); + + } else if ( mName == proto::target::ScriptBegin::typeName ) { + finalizeCurrentReport(); + + const auto &p = proto::target::ScriptBegin::fromStompMessage(*m); + if ( !p ) { + ERR << "Failed to parse " << proto::target::ScriptBegin::typeName << " message from zypp-rpm." << std::endl; + continue; + } + + aboutToStartNewReport(); + + Resolvable::constPtr resPtr; + const auto stepId = p->stepId; + if ( stepId >= 0 && stepId < steps.size() ) { + resPtr = makeResObject( steps.at(stepId).satSolvable() ); + } + + currentStepId = p->stepId; + scriptreport = std::make_unique< callback::SendReport > (); + currentScriptType = p->scriptType; + currentScriptPackage = p->scriptPackage; + (*scriptreport)->start( currentScriptType, currentScriptPackage, resPtr ); + + } else if ( mName == proto::target::ScriptFinished::typeName ) { + + // we just read the message, we do not act on it because a ScriptError is reported after ScriptFinished + + } else if ( mName == proto::target::ScriptError::typeName ) { + + const auto &p = proto::target::ScriptError::fromStompMessage(*m); + if ( !p ) { + ERR << "Failed to parse " << proto::target::ScriptError::typeName << " message from zypp-rpm." << std::endl; + continue; + } + + Resolvable::constPtr resPtr; + const auto stepId = p->stepId; + if ( stepId >= 0 && stepId < steps.size() ) { + resPtr = makeResObject( steps.at(stepId).satSolvable() ); + + if ( p->fatal ) { + steps.at( stepId ).stepStage( sat::Transaction::STEP_ERROR ); + } + + } + + HistoryLog().comment( + str::form("Failed to execute %s script for %s ", currentScriptType.c_str(), currentScriptPackage.size() ? currentScriptPackage.c_str() : "unknown" ), + true /*timestamp*/); + + writeRpmMsgToHistory(); + + if ( !scriptreport ) { + ERR << "Received a ScriptError message, but there is no running report. " << std::endl; + continue; + } + + // before killing the report we need to wait for the script end tag + waitForScriptEnd(); + (*scriptreport)->finish( resPtr, p->fatal ? rpm::CommitScriptReportSA::CRITICAL : rpm::CommitScriptReportSA::WARN ); + + // manually reset the current report since we already sent the finish(), rest will be reset by the new start + scriptreport.reset(); + currentStepId = -1; + + } else if ( mName == proto::target::CleanupBegin::typeName ) { + finalizeCurrentReport(); + + const auto &beg = proto::target::CleanupBegin::fromStompMessage(*m); + if ( !beg ) { + ERR << "Failed to parse " << proto::target::CleanupBegin::typeName << " message from zypp-rpm." << std::endl; + continue; + } + + aboutToStartNewReport(); + cleanupreport = std::make_unique< callback::SendReport > (); + (*cleanupreport)->start( beg->nvra ); + } else if ( mName == proto::target::CleanupFinished::typeName ) { + + finalizeCurrentReport(); + + } else if ( mName == proto::target::CleanupProgress::typeName ) { + const auto &prog = proto::target::CleanupProgress::fromStompMessage(*m); + if ( !prog ) { + ERR << "Failed to parse " << proto::target::CleanupProgress::typeName << " message from zypp-rpm." << std::endl; + continue; + } + + if ( !cleanupreport ) { + ERR << "Received a CleanupProgress message, but there is no running report. " << std::endl; + continue; + } + + (*cleanupreport)->progress( prog->amount ); + + } else if ( mName == proto::target::TransBegin::typeName ) { + finalizeCurrentReport(); + + const auto &beg = proto::target::TransBegin::fromStompMessage(*m); + if ( !beg ) { + ERR << "Failed to parse " << proto::target::TransBegin::typeName << " message from zypp-rpm." << std::endl; + continue; + } + + aboutToStartNewReport(); + transactionreport = std::make_unique< callback::SendReport > (); + (*transactionreport)->start( beg->name ); + } else if ( mName == proto::target::TransFinished::typeName ) { + + finalizeCurrentReport(); + + } else if ( mName == proto::target::TransProgress::typeName ) { + const auto &prog = proto::target::TransProgress::fromStompMessage(*m); + if ( !prog ) { + ERR << "Failed to parse " << proto::target::TransProgress::typeName << " message from zypp-rpm." << std::endl; + continue; + } + + if ( !transactionreport ) { + ERR << "Received a TransactionProgress message, but there is no running report. " << std::endl; + continue; + } + + (*transactionreport)->progress( prog->amount ); + } else if ( mName == proto::target::TransactionError::typeName ) { + + const auto &error = proto::target::TransactionError::fromStompMessage(*m); + if ( !error ) { + ERR << "Failed to parse " << proto::target::TransactionError::typeName << " message from zypp-rpm." << std::endl; + continue; + } + + // this value is checked later + transactionError = std::move(*error); + + } else { + ERR << "Received unexpected message from zypp-rpm: "<< m->command() << ", ignoring" << std::endl; + return; + } + + } + }; + + // setup the rest when zypp-rpm is running + prog->sigStarted().connect( [&](){ + + // close the ends of the pipes we do not care about + messagePipe->unrefWrite(); + scriptPipe->unrefWrite(); + + // read the stdout and stderr and forward it to our log + prog->connectFunc( &zyppng::IODevice::sigChannelReadyRead, [&]( int channel ){ + while( prog->canReadLine( channel ) ) { + L_ERR("zypp-rpm") << ( channel == zyppng::Process::StdOut ? " " : " " ) << prog->channelReadLine( channel ).asStringView(); // no endl! - readLine does not trim + } + }); + + // this is the source for control messages from zypp-rpm , we will get structured data information + // in form of STOMP messages + if ( !msgSource->openFds( std::vector{ messagePipe->readFd }, prog->stdinFd() ) ) + ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to open read stream to subprocess" ) ); + + msgStream = zyppng::StompFrameStream::create(msgSource); + msgStream->connectFunc( &zyppng::StompFrameStream::sigMessageReceived, processMessages ); + + const auto &msg = commit.toStompMessage(); + if ( !msg ) + std::rethrow_exception ( msg.error() ); + + if ( !msgStream->sendMessage( *msg ) ) { + prog->stop( SIGKILL ); + ZYPP_THROW( target::rpm::RpmSubprocessException( "Failed to write commit to subprocess" ) ); + } + }); + + // track the childs lifetime + int zyppRpmExitCode = -1; + prog->connectFunc( &zyppng::Process::sigFinished, [&]( int code ){ + zyppRpmExitCode = code; + loop->quit(); + }); + + if ( !prog->start( argv ) ) { + HistoryLog().comment( "Commit was aborted, failed to run zypp-rpm" ); + ZYPP_THROW( target::rpm::RpmSubprocessException( prog->execError() ) ); + } + + loop->run(); + + if ( msgStream ) { + // pull all messages from the IO device + msgStream->readAllMessages(); + + // make sure to read ALL available messages + processMessages(); + } + + // we will not receive a new start message , so we need to manually finalize the last report + finalizeCurrentReport(); + + // make sure to read all data from the log source + bool readMsgs = false; + while( prog->canReadLine( zyppng::Process::StdErr ) ) { + readMsgs = true; + MIL << "zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdErr ).asStringView(); + } + while( prog->canReadLine( zyppng::Process::StdOut ) ) { + readMsgs = true; + MIL << "zypp-rpm: " << prog->channelReadLine( zyppng::Process::StdOut ).asStringView(); + } + + while ( scriptSource->canReadLine() ) { + readMsgs = true; + MIL << "rpm-script-fd: " << scriptSource->readLine().asStringView(); + } + if ( scriptSource->bytesAvailable() > 0 ) { + readMsgs = true; + MIL << "rpm-script-fd: " << scriptSource->readAll().asStringView(); + } + if ( readMsgs ) + MIL << std::endl; + + switch ( zyppRpmExitCode ) { + // we need to look at the summary, handle finishedwitherrors like no error here + case zypprpm::NoError: + case zypprpm::RpmFinishedWithError: + break; + case zypprpm::RpmFinishedWithTransactionError: { + // here zypp-rpm sent us a error description + if ( transactionError ) { + + std::ostringstream sstr; + sstr << _("Executing the transaction failed because of the following problems:") << "\n"; + for ( const auto & err : transactionError->problems ) { + sstr << " " << err << "\n"; + } + sstr << std::endl; + ZYPP_THROW( rpm::RpmTransactionFailedException( sstr.str() ) ); + + } else { + ZYPP_THROW( rpm::RpmTransactionFailedException("RPM failed with a unexpected error, check the logs for more information.") ); + } + break; + } + case zypprpm::FailedToOpenDb: + ZYPP_THROW( rpm::RpmDbOpenException( rpm().root(), rpm().dbPath() ) ); + break; + case zypprpm::WrongHeaderSize: + case zypprpm::WrongMessageFormat: + ZYPP_THROW( rpm::RpmSubprocessException("Failed to communicate with zypp-rpm, this is most likely a bug. Consider to fall back to legacy transaction strategy.") ); + break; + case zypprpm::RpmInitFailed: + ZYPP_THROW( rpm::RpmInitException( rpm().root(), rpm().dbPath() ) ); + break; + case zypprpm::FailedToReadPackage: + ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm was unable to read a package, check the logs for more information.") ); + break; + case zypprpm::FailedToAddStepToTransaction: + ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm failed to build the transaction, check the logs for more information.") ); + break; + case zypprpm::RpmOrderFailed: + ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm failed to order the transaction, check the logs for more information.") ); + break; + case zypprpm::FailedToCreateLock: + ZYPP_THROW( rpm::RpmSubprocessException("zypp-rpm failed to create its lockfile, check the logs for more information.") ); + break; + } + + for ( int stepId = 0; (ZYppCommitResult::TransactionStepList::size_type)stepId < steps.size() && !abort; ++stepId ) { + auto &step = steps[stepId]; + PoolItem citem( step ); + + if ( step.stepStage() == sat::Transaction::STEP_TODO ) { + // other resolvables (non-Package) that are not handled by zypp-rpm + if ( !citem->isKind() && !policy_r.dryRun() ) { + // Status is changed as the buddy package buddy + // gets installed/deleted. Handle non-buddies only. + if ( ! citem.buddy() && citem->isKind() ) { + Product::constPtr p = citem->asKind(); + + if ( citem.status().isToBeInstalled() ) { + ERR << "Can't install orphan product without release-package! " << citem << endl; + } else { + // Deleting the corresponding product entry is all we con do. + // So the product will no longer be visible as installed. + std::string referenceFilename( p->referenceFilename() ); + + if ( referenceFilename.empty() ) { + ERR << "Can't remove orphan product without 'referenceFilename'! " << citem << endl; + } else { + Pathname referencePath { Pathname("/etc/products.d") / referenceFilename }; // no root prefix for rpmdb lookup! + + if ( ! rpm().hasFile( referencePath.asString() ) ) { + // If it's not owned by a package, we can delete it. + referencePath = Pathname::assertprefix( _root, referencePath ); // now add a root prefix + if ( filesystem::unlink( referencePath ) != 0 ) + ERR << "Delete orphan product failed: " << referencePath << endl; + } else { + WAR << "Won't remove orphan product: '/etc/products.d/" << referenceFilename << "' is owned by a package." << endl; + } + } + } + citem.status().resetTransact( ResStatus::USER ); + step.stepStage( sat::Transaction::STEP_DONE ); + } + } + } + } + } + + // Check presence of update scripts/messages. If aborting, + // at least log omitted scripts. + if ( ! successfullyInstalledPackages.empty() ) + { + if ( ! RunUpdateScripts( _root, ZConfig::instance().update_scriptsPath(), + successfullyInstalledPackages, abort ) ) + { + WAR << "Commit aborted by the user" << endl; + abort = true; + } + // send messages after scripts in case some script generates output, + // that should be kept in t %ghost message file. + RunUpdateMessages( _root, ZConfig::instance().update_messagesPath(), + successfullyInstalledPackages, + result_r ); + } + + // jsc#SLE-5116: Log patch status changes to history + // NOTE: Should be the last action as it may need to reload + // the Target in case of an incomplete transaction. + logPatchStatusChanges( result_r.transaction(), *this ); + + if ( abort ) { + HistoryLog().comment( "Commit was aborted." ); + ZYPP_THROW( TargetAbortedException( ) ); + } + } + + /////////////////////////////////////////////////////////////////// + + rpm::RpmDb & TargetImpl::rpm() + { + return _rpm; + } + + bool TargetImpl::providesFile (const std::string & path_str, const std::string & name_str) const + { + return _rpm.hasFile(path_str, name_str); + } + + /////////////////////////////////////////////////////////////////// + namespace + { + parser::ProductFileData baseproductdata( const Pathname & root_r ) + { + parser::ProductFileData ret; + PathInfo baseproduct( Pathname::assertprefix( root_r, "/etc/products.d/baseproduct" ) ); + + if ( baseproduct.isFile() ) + { + try + { + ret = parser::ProductFileReader::scanFile( baseproduct.path() ); + } + catch ( const Exception & excpt ) + { + ZYPP_CAUGHT( excpt ); + } + } + else if ( PathInfo( Pathname::assertprefix( root_r, "/etc/products.d" ) ).isDir() ) + { + ERR << "baseproduct symlink is dangling or missing: " << baseproduct << endl; + } + return ret; + } + + inline Pathname staticGuessRoot( const Pathname & root_r ) + { + if ( root_r.empty() ) + { + // empty root: use existing Target or assume "/" + Pathname ret ( ZConfig::instance().systemRoot() ); + if ( ret.empty() ) + return Pathname("/"); + return ret; + } + return root_r; + } + + inline std::string firstNonEmptyLineIn( const Pathname & file_r ) + { + std::ifstream idfile( file_r.c_str() ); + for( iostr::EachLine in( idfile ); in; in.next() ) + { + std::string line( str::trim( *in ) ); + if ( ! line.empty() ) + return line; + } + return std::string(); + } + } // namespace + /////////////////////////////////////////////////////////////////// + + Product::constPtr TargetImpl::baseProduct() const + { + ResPool pool(ResPool::instance()); + for_( it, pool.byKindBegin(), pool.byKindEnd() ) + { + Product::constPtr p = (*it)->asKind(); + if ( p->isTargetDistribution() ) + return p; + } + return nullptr; + } + + LocaleSet TargetImpl::requestedLocales( const Pathname & root_r ) + { + const Pathname needroot( staticGuessRoot(root_r) ); + const Target_constPtr target( getZYpp()->getTarget() ); + if ( target && target->root() == needroot ) + return target->requestedLocales(); + return RequestedLocalesFile( home(needroot) / "RequestedLocales" ).locales(); + } + + void TargetImpl::updateAutoInstalled() + { + MIL << "updateAutoInstalled if changed..." << endl; + SolvIdentFile::Data newdata; + for ( auto id : sat::Pool::instance().autoInstalled() ) + newdata.insert( IdString(id) ); // explicit ctor! + _autoInstalledFile.setData( std::move(newdata) ); + } + + std::string TargetImpl::targetDistribution() const + { return baseproductdata( _root ).registerTarget(); } + // static version: + std::string TargetImpl::targetDistribution( const Pathname & root_r ) + { return baseproductdata( staticGuessRoot(root_r) ).registerTarget(); } + + std::string TargetImpl::targetDistributionRelease() const + { return baseproductdata( _root ).registerRelease(); } + // static version: + std::string TargetImpl::targetDistributionRelease( const Pathname & root_r ) + { return baseproductdata( staticGuessRoot(root_r) ).registerRelease();} + + std::string TargetImpl::targetDistributionFlavor() const + { return baseproductdata( _root ).registerFlavor(); } + // static version: + std::string TargetImpl::targetDistributionFlavor( const Pathname & root_r ) + { return baseproductdata( staticGuessRoot(root_r) ).registerFlavor();} + + Target::DistributionLabel TargetImpl::distributionLabel() const + { + Target::DistributionLabel ret; + parser::ProductFileData pdata( baseproductdata( _root ) ); + ret.shortName = pdata.shortName(); + ret.summary = pdata.summary(); + return ret; + } + // static version: + Target::DistributionLabel TargetImpl::distributionLabel( const Pathname & root_r ) + { + Target::DistributionLabel ret; + parser::ProductFileData pdata( baseproductdata( staticGuessRoot(root_r) ) ); + ret.shortName = pdata.shortName(); + ret.summary = pdata.summary(); + return ret; + } + + std::string TargetImpl::distributionVersion() const + { + if ( _distributionVersion.empty() ) + { + _distributionVersion = TargetImpl::distributionVersion(root()); + if ( !_distributionVersion.empty() ) + MIL << "Remember distributionVersion = '" << _distributionVersion << "'" << endl; + } + return _distributionVersion; + } + // static version + std::string TargetImpl::distributionVersion( const Pathname & root_r ) + { + std::string distributionVersion = baseproductdata( staticGuessRoot(root_r) ).edition().version(); + if ( distributionVersion.empty() ) + { + // ...But the baseproduct method is not expected to work on RedHat derivatives. + // On RHEL, Fedora and others the "product version" is determined by the first package + // providing 'system-release'. This value is not hardcoded in YUM and can be configured + // with the $distroverpkg variable. + scoped_ptr tmprpmdb; + if ( ZConfig::instance().systemRoot() == Pathname() ) + { + try + { + tmprpmdb.reset( new rpm::RpmDb ); + tmprpmdb->initDatabase( /*default ctor uses / but no additional keyring exports */ ); + } + catch( ... ) + { + return ""; + } + } + rpm::librpmDb::db_const_iterator it; + if ( it.findByProvides( ZConfig::instance().distroverpkg() ) ) + distributionVersion = it->tag_version(); + } + return distributionVersion; + } + + + std::string TargetImpl::distributionFlavor() const + { + return firstNonEmptyLineIn( home() / "LastDistributionFlavor" ); + } + // static version: + std::string TargetImpl::distributionFlavor( const Pathname & root_r ) + { + return firstNonEmptyLineIn( staticGuessRoot(root_r) / "/var/lib/zypp/LastDistributionFlavor" ); + } + + /////////////////////////////////////////////////////////////////// + namespace + { + std::string guessAnonymousUniqueId( const Pathname & root_r ) + { + // bsc#1024741: Omit creating a new uid for chrooted systems (if it already has one, fine) + std::string ret( firstNonEmptyLineIn( root_r / "/var/lib/zypp/AnonymousUniqueId" ) ); + if ( ret.empty() && root_r != "/" ) + { + // if it has nonoe, use the outer systems one + ret = firstNonEmptyLineIn( "/var/lib/zypp/AnonymousUniqueId" ); + } + return ret; + } + } + + std::string TargetImpl::anonymousUniqueId() const + { + return guessAnonymousUniqueId( root() ); + } + // static version: + std::string TargetImpl::anonymousUniqueId( const Pathname & root_r ) + { + return guessAnonymousUniqueId( staticGuessRoot(root_r) ); + } + + /////////////////////////////////////////////////////////////////// + + void TargetImpl::vendorAttr( VendorAttr vendorAttr_r ) + { + MIL << "New VendorAttr: " << vendorAttr_r << endl; + _vendorAttr = std::move(vendorAttr_r); + } + /////////////////////////////////////////////////////////////////// + + void TargetImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r ) + { + // provide on local disk + ManagedFile localfile = provideSrcPackage(srcPackage_r); + // create a installation progress report proxy + RpmInstallPackageReceiver progress( srcPackage_r ); + progress.connect(); // disconnected on destruction. + // install it + rpm().installPackage ( localfile ); + } + + ManagedFile TargetImpl::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ) + { + // provide on local disk + repo::RepoMediaAccess access_r; + repo::SrcPackageProvider prov( access_r ); + return prov.provideSrcPackage( srcPackage_r ); + } + //////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/TargetImpl.commitFindFileConflicts.cc b/zypp/target/TargetImpl.commitFindFileConflicts.cc new file mode 100644 index 0000000..80ea768 --- /dev/null +++ b/zypp/target/TargetImpl.commitFindFileConflicts.cc @@ -0,0 +1,175 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/TargetImpl.commitFindFileConflicts.cc + */ +extern "C" +{ +#include +#include +#include +#include +#include +#include +#include +} +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace target + { + /////////////////////////////////////////////////////////////////// + namespace + { + /** libsolv::pool_findfileconflicts callback providing package header. */ + struct FileConflictsCB + { + FileConflictsCB( sat::detail::CPool * pool_r, ProgressData & progress_r ) + : _progress( progress_r ) + , _state( ::rpm_state_create( pool_r, ::pool_get_rootdir(pool_r) ), ::rpm_state_free ) + {} + + void * operator()( sat::detail::CPool * pool_r, sat::detail::IdType id_r ) + { + void * ret = lookup( id_r ); + + // report progress on 1st visit only, ticks later + // (there may be up to 3 visits) + if ( _visited.find( id_r ) == _visited.end() ) + { + //DBG << "FCCB: " << sat::Solvable( id_r ) << " " << ret << endl; + _visited.insert( id_r ); + if ( ! ret && sat::Solvable( id_r ).isKind() ) // only packages have filelists + _noFilelist.push( id_r ); + _progress.incr(); + } + else + { + _progress.tick(); + } + return ret; + } + + const sat::Queue & noFilelist() const + { return _noFilelist; } + + static void * invoke( sat::detail::CPool * pool_r, sat::detail::IdType id_r, void * cbdata_r ) + { return (*reinterpret_cast(cbdata_r))( pool_r, id_r ); } + + private: + void * lookup( sat::detail::IdType id_r ) + { + sat::Solvable solv( id_r ); + if ( solv.isSystem() ) + { + Solvable * s = solv.get(); + if ( ! s->repo->rpmdbid ) + return nullptr; + sat::detail::IdType rpmdbid = s->repo->rpmdbid[id_r - s->repo->start]; + if ( ! rpmdbid ) + return nullptr; + return ::rpm_byrpmdbid( _state, rpmdbid ); + } + else + { + Package::Ptr pkg( make( solv ) ); + if ( ! pkg ) + return nullptr; + Pathname localfile( pkg->cachedLocation() ); + if ( localfile.empty() ) + return nullptr; + AutoDispose fp( ::fopen( localfile.c_str(), "re" ), ::fclose ); + return ::rpm_byfp( _state, fp, localfile.c_str() ); + } + } + + private: + ProgressData & _progress; + AutoDispose _state; + std::unordered_set _visited; + sat::Queue _noFilelist; + }; + + } // namespace + /////////////////////////////////////////////////////////////////// + + void TargetImpl::commitFindFileConflicts( const ZYppCommitPolicy & policy_r, ZYppCommitResult & result_r ) + { + sat::Queue todo; + sat::FileConflicts conflicts; + int newpkgs = result_r.transaction().installedResult( todo ); + MIL << "Checking for file conflicts in " << newpkgs << " new packages..." << endl; + if ( ! newpkgs ) + return; + + try { + callback::SendReport report; + ProgressData progress( todo.size() ); + if ( ! report->start( progress ) ) + ZYPP_THROW( AbortRequestException() ); + + FileConflictsCB cb( sat::Pool::instance().get(), progress ); + // lambda receives progress trigger and translates into report + auto sendProgress = [&]( const ProgressData & progress_r )->bool { + if ( ! report->progress( progress_r, cb.noFilelist() ) ) + { + progress.noSend(); // take care progress DTOR does not trigger a final report (2nd exeption) + ZYPP_THROW( AbortRequestException() ); + } + return true; + }; + progress.sendTo( sendProgress ); + + unsigned count = + ::pool_findfileconflicts( sat::Pool::instance().get(), + todo, + newpkgs, + conflicts, + FINDFILECONFLICTS_USE_SOLVABLEFILELIST | FINDFILECONFLICTS_CHECK_DIRALIASING | FINDFILECONFLICTS_USE_ROOTDIR, + &FileConflictsCB::invoke, + &cb ); + progress.toMax(); + progress.noSend(); + + (count?WAR:MIL) << "Found " << count << " file conflicts." << endl; + if ( ! report->result( progress, cb.noFilelist(), conflicts ) ) + ZYPP_THROW( AbortRequestException() ); + } + catch ( const AbortRequestException & e ) + { + TargetAbortedException excpt; + excpt.remember( e ); + ZYPP_THROW( excpt ); + } + } + + } // namespace target + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/TargetImpl.h b/zypp/target/TargetImpl.h new file mode 100644 index 0000000..b3518fd --- /dev/null +++ b/zypp/target/TargetImpl.h @@ -0,0 +1,250 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/TargetImpl.h + * +*/ +#ifndef ZYPP_TARGET_TARGETIMPL_H +#define ZYPP_TARGET_TARGETIMPL_H + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(TargetImpl); + class CommitPackageCache; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : TargetImpl + // + /** Base class for concrete Target implementations. + * + * Constructed by \ref TargetFactory. Public access via \ref Target + * interface. + */ + class TargetImpl : public base::ReferenceCounted, private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const TargetImpl & obj ); + + public: + /** list of pool items */ + using PoolItemList = std::list; + + /** set of pool items */ + using PoolItemSet = std::set; + + public: + /** Ctor. */ + TargetImpl(const Pathname & root_r = "/", bool doRebuild_r = false ); + /** Dtor. */ + ~TargetImpl() override; + + /** + * generates the unique anonymous id which is called + * when creating the target + */ + void createAnonymousId() const; + + /** + * generates a cache of the last product flavor + */ + void createLastDistributionFlavorCache() const; + + /** \name Solv file handling. + * If target solv file is outdated, but (non-root-)user has + * no permission to create it at the default location, we + * use a temporary one. + */ + //@{ + private: + /** The systems default solv file location. */ + Pathname defaultSolvfilesPath() const; + + /** The solv file location actually in use (default or temp). */ + Pathname solvfilesPath() const + { return solvfilesPathIsTemp() ? _tmpSolvfilesPath : defaultSolvfilesPath(); } + + /** Whether we're using a temp. solvfile. */ + bool solvfilesPathIsTemp() const + { return ! _tmpSolvfilesPath.empty(); } + + Pathname _tmpSolvfilesPath; + + public: + void load( bool force = true ); + + void unload(); + + void reload(); + + void clearCache(); + + bool buildCache(); + //@} + + public: + + /** The root set for this target */ + Pathname root() const + { return _root; } + + /** The directory to store things. */ + Pathname home() const + { return home( _root ); } + + static Pathname home( const Pathname & root_r ) + { return root_r / "/var/lib/zypp"; } + + /** Commit changes in the pool */ + ZYppCommitResult commit( ResPool pool_r, const ZYppCommitPolicy & policy_r ); + + /** Install a source package on the Target. */ + void installSrcPackage( const SrcPackage_constPtr & srcPackage_r ); + + /** Provides a source package on the Target. */ + ManagedFile provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ); + + /** Overload to realize stream output. */ + std::ostream & dumpOn( std::ostream & str ) const override + { return str << "Target(" << root() << ")"; } + + /** The RPM database */ + rpm::RpmDb & rpm(); + + /** If the package is installed and provides the file + Needed to evaluate split provides during Resolver::Upgrade() */ + bool providesFile (const std::string & path_str, const std::string & name_str) const; + + /** Return name of package owning \a path_str + * or empty string if no installed package owns \a path_str. */ + std::string whoOwnsFile (const std::string & path_str) const + { return _rpm.whoOwnsFile (path_str); } + + /** \copydoc Target::baseProduct() */ + Product::constPtr baseProduct() const; + + /** \copydoc Target::requestedLocales() */ + LocaleSet requestedLocales() const + { return _requestedLocalesFile.locales(); } + /** \overload */ + static LocaleSet requestedLocales( const Pathname & root_r ); + + /** \copydoc Target::updateAutoInstalled */ + void updateAutoInstalled(); + + /** \copydoc Target::targetDistribution() */ + std::string targetDistribution() const; + /** \overload */ + static std::string targetDistribution( const Pathname & root_r ); + + /** \copydoc Target::targetDistributionRelease()*/ + std::string targetDistributionRelease() const; + /** \overload */ + static std::string targetDistributionRelease( const Pathname & root_r ); + + /** \copydoc Target::targetDistributionFlavor()*/ + std::string targetDistributionFlavor() const; + /** \overload */ + static std::string targetDistributionFlavor( const Pathname & root_r ); + + /** \copydoc Target::distributionLabel()*/ + Target::DistributionLabel distributionLabel() const; + /** \overload */ + static Target::DistributionLabel distributionLabel( const Pathname & root_r ); + + /** \copydoc Target::distributionVersion()*/ + std::string distributionVersion() const; + /** \overload */ + static std::string distributionVersion( const Pathname & root_r ); + + /** \copydoc Target::distributionFlavor() */ + std::string distributionFlavor() const; + /** \overload */ + static std::string distributionFlavor( const Pathname & root_r ); + + /** \copydoc Target::anonymousUniqueId() */ + std::string anonymousUniqueId() const; + /** \overload */ + static std::string anonymousUniqueId( const Pathname & root_r ); + + /** \copydoc Target::vendorAttr() */ + const VendorAttr & vendorAttr() const + { return _vendorAttr; } + /** \overload */ + void vendorAttr( VendorAttr vendorAttr_r ); + //@} + + public: + private: + /** Commit ordered changes (internal helper) */ + void commit( const ZYppCommitPolicy & policy_r, + CommitPackageCache & packageCache_r, + ZYppCommitResult & result_r ); + + /** Commit ordered changes (internal helper) */ + void commitInSingleTransaction( const ZYppCommitPolicy & policy_r, + CommitPackageCache & packageCache_r, + ZYppCommitResult & result_r ); + + + /** Commit helper checking for file conflicts after download. */ + void commitFindFileConflicts( const ZYppCommitPolicy & policy_r, ZYppCommitResult & result_r ); + protected: + /** Path to the target */ + Pathname _root; + /** RPM database */ + rpm::RpmDb _rpm; + /** Requested Locales database */ + RequestedLocalesFile _requestedLocalesFile; + /** user/auto installed database */ + SolvIdentFile _autoInstalledFile; + /** Hard-Locks database */ + HardLocksFile _hardLocksFile; + /** Cache distributionVersion */ + mutable std::string _distributionVersion; + /** vendor equivalence settings. */ + VendorAttr _vendorAttr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates TargetImpl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const TargetImpl & obj ) + { + return obj.dumpOn( str ); + } + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_TARGETIMPL_H diff --git a/zypp/target/modalias/Modalias.cc b/zypp/target/modalias/Modalias.cc new file mode 100644 index 0000000..6c999f0 --- /dev/null +++ b/zypp/target/modalias/Modalias.cc @@ -0,0 +1,245 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/modalias/Modalias.cc + * +*/ +extern "C" +{ +#include +} + +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "MODALIAS" + +#include +#include +#include +#include +#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + namespace target + { + /////////////////////////////////////////////////////////////////// + namespace + { + /** Filter subtrees known to contain no modalias files */ + inline bool isBlackListed( const Pathname & dir_r, const char * file_r ) + { +#define PATH_IS( D, F ) ( ::strcmp( file_r, F ) == 0 && ::strcmp( dir_r.c_str(), D ) == 0 ) + switch ( file_r[0] ) + { + case 'm': + return PATH_IS( "/sys/devices/system", "memory" ); // bnc#824110: huge tree for systems with large RAM + break; + } + return false; +#undef PATH_IS + } + + void foreach_file_recursive( const Pathname & dir_r, std::set & arg_r ) + { + AutoDispose dir( ::opendir( dir_r.c_str() ), ::closedir ); + if ( ! dir ) + return; + + struct dirent * dirent = NULL; + while ( (dirent = ::readdir(dir)) != NULL ) + { + if ( dirent->d_name[0] == '.' ) + continue; + + if ( isBlackListed( dir_r, dirent->d_name ) ) + continue; + + Pathname path; // lazy init as needed + unsigned char d_type = dirent->d_type; + if ( d_type == DT_UNKNOWN ) + { + path = dir_r/dirent->d_name; + PathInfo pi( path, PathInfo::LSTAT ); + if ( pi.isDir() ) + d_type = DT_DIR; + else if ( pi.isFile() ) + d_type = DT_REG; + } + + if ( d_type == DT_DIR ) + { + if ( path.empty() ) + path = dir_r/dirent->d_name; + foreach_file_recursive( path, arg_r ); + } + else if ( d_type == DT_REG && ::strcmp( dirent->d_name, "modalias" ) == 0 ) + { + if ( path.empty() ) + path = dir_r/dirent->d_name; + // read modalias line from file + std::ifstream str( path.c_str() ); + std::string line( iostr::getline( str ) ); + if ( ! line.empty() ) + arg_r.insert( line ); + } + } + } + + /** Recursively scan for modalias files and scan them to \a arg. */ + void foreach_file_recursive( const Pathname & dir_r, Modalias::ModaliasList & arg_r ) + { + std::set arg; // we want the aliases to be unified (the public API uses a vector) + foreach_file_recursive( dir_r, arg ); + arg_r.insert( arg_r.end(), arg.begin(), arg.end() ); + } + } // namespace + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Modalias::Impl + // + /** Modalias implementation. */ + struct Modalias::Impl + { + /** Ctor. */ + Impl() + { + const char * dir = getenv("ZYPP_MODALIAS_SYSFS"); + if ( dir ) + { + PathInfo pi( dir ); + if ( pi.isFile() ) + { + // Debug/testcases: + // find /sys/ -type f -name modalias -print0 | xargs -0 cat >/tmp/modaliases + // ZYPP_MODALIAS_SYSFS=/tmp/modaliases + DBG << "Using $ZYPP_MODALIAS_SYSFS modalias file: " << dir << endl; + iostr::forEachLine( InputStream( pi.path() ), + [&]( int num_r, const std::string& line_r )->bool + { + this->_modaliases.push_back( line_r ); + return true; + } ); + return; + } + DBG << "Using $ZYPP_MODALIAS_SYSFS: " << dir << endl; + } + else + { + dir = "/sys"; + DBG << "Using /sys directory." << endl; + } + + foreach_file_recursive( dir, _modaliases ); + } + + Impl(const Impl &) = delete; + Impl(Impl &&) = delete; + Impl &operator=(const Impl &) = delete; + Impl &operator=(Impl &&) = delete; + + /** Dtor. */ + ~Impl() = default; + + /* + * Check if a device on the system matches a modalias PATTERN. + * + * Returns NULL if no matching device is found, and the modalias + * of the first matching device otherwise. (More than one device + * may match a given pattern.) + * + * On a system that has the following device, + * + * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00 + * + * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") will + * return a non-NULL value. + */ + bool query( const char * cap_r ) const + { + if ( cap_r && *cap_r ) + { + for_( it, _modaliases.begin(), _modaliases.end() ) + { + if ( fnmatch( cap_r, (*it).c_str(), 0 ) == 0 ) + return true; + } + } + return false; + } + + public: + ModaliasList _modaliases; + + public: + /** Offer default Impl. */ + static shared_ptr nullimpl() + { + static shared_ptr _nullimpl( new Impl ); + return _nullimpl; + } + + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Modalias::Impl Stream output + * And maybe std::ostream & operator<< Modalias::Impl below too. + * return libhal version or something like that. + */ + inline std::ostream & operator<<( std::ostream & str, const Modalias::Impl & obj ) + { + return dumpRange( str << "Modaliases: (" << obj._modaliases.size() << ") ", obj._modaliases.begin(), obj._modaliases.end() ); + } + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Modalias + // + /////////////////////////////////////////////////////////////////// + + Modalias::Modalias() + : _pimpl( Impl::nullimpl() ) + {} + + Modalias::~Modalias() + {} + + Modalias & Modalias::instance() + { + static Modalias _singleton; + return _singleton; + } + + bool Modalias::query( const char * cap_r ) const + { return _pimpl->query( cap_r ); } + + const Modalias::ModaliasList & Modalias::modaliasList() const + { return _pimpl->_modaliases; } + + void Modalias::modaliasList( ModaliasList newlist_r ) + { _pimpl->_modaliases.swap( newlist_r ); } + + std::ostream & operator<<( std::ostream & str, const Modalias & obj ) + { return str << *obj._pimpl; } + + } // namespace target + /////////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + diff --git a/zypp/target/modalias/Modalias.h b/zypp/target/modalias/Modalias.h new file mode 100644 index 0000000..b0bed0b --- /dev/null +++ b/zypp/target/modalias/Modalias.h @@ -0,0 +1,102 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/modalias/Modalias.h + * +*/ +#ifndef ZYPP_TARGET_MODALIAS_MODALIAS_H +#define ZYPP_TARGET_MODALIAS_MODALIAS_H + +#include +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Modalias + // + /** Hardware abstaction layer singleton. + */ + class ZYPP_API_DEPTESTOMATIC Modalias + { + friend std::ostream & operator<<( std::ostream & str, const Modalias & obj ); + + public: + /** Implementation */ + struct Impl; + + public: + using ModaliasList = std::vector; + + /** Singleton access. */ + static Modalias & instance(); + + /** Dtor */ + ~Modalias(); + + public: + + /** Checks if a device on the system matches a modalias pattern. + * + * Returns \c false if no matching device is found, and the modalias + * of the first matching device otherwise. (More than one device + * may match a given pattern.) + * + * On a system that has the following device, + * \code + * pci:v00008086d0000265Asv00008086sd00004556bc0Csc03i00 + * \endcode + * the following query will return \c true: + * \code + * modalias_matches("pci:v00008086d0000265Asv*sd*bc*sc*i*") + * \endcode + */ + bool query( IdString cap_r ) const + { return query( cap_r.c_str() ); } + /** \overload */ + bool query( const char * cap_r ) const; + /** \overload */ + bool query( const std::string & cap_r ) const + { return query( cap_r.c_str() ); } + + /** List of modaliases found on system */ + const ModaliasList & modaliasList() const; + + /** Manually set list of modaliases to use */ + void modaliasList( ModaliasList newlist_r ); + + private: + /** Singleton ctor. */ + Modalias(); + + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Modalias Stream output */ + std::ostream & operator<<( std::ostream & str, const Modalias & obj ) ZYPP_API_DEPTESTOMATIC; + + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_MODALIAS_MODALIAS_H diff --git a/zypp/target/rpm/BinHeader.cc b/zypp/target/rpm/BinHeader.cc new file mode 100644 index 0000000..4a25e2b --- /dev/null +++ b/zypp/target/rpm/BinHeader.cc @@ -0,0 +1,458 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/BinHeader.cc + * +*/ +#include "librpm.h" +extern "C" +{ +#ifdef _RPM_5 +#undef RPM_NULL_TYPE +#define RPM_NULL_TYPE rpmTagType(0) +typedef rpmuint32_t rpm_count_t; +#endif +} + +#include + +#include +#include +#include +#include + +#include + +using std::endl; + +#undef Y2LOG +#define Y2LOG "BinHeader" + +namespace zypp +{ +namespace target +{ +namespace rpm +{ + + /** Helper for header data retieval. + * With \c _RPM_4 use \c ::headerGet; with \c _RPM_5 + * use the meanwhile deprecated \c ::headerGetEntry. + * \ingroup g_RAII + */ + struct HeaderEntryGetter : private base::NonCopyable + { + public: + HeaderEntryGetter(const Header &h_r, rpmTag &tag_r); + + HeaderEntryGetter(const HeaderEntryGetter &) = delete; + HeaderEntryGetter(HeaderEntryGetter &&) = delete; + HeaderEntryGetter &operator=(const HeaderEntryGetter &) = delete; + HeaderEntryGetter &operator=(HeaderEntryGetter &&) = delete; + + ~HeaderEntryGetter(); + rpmTagType type(); + rpm_count_t cnt(); + void * val(); + private: +#ifndef _RPM_5 + ::rpmtd _rpmtd; +#else + rpmTagType _type; + rpm_count_t _cnt; + void * _val; +#endif //_RPM_5 + }; + +#ifndef _RPM_5 + inline HeaderEntryGetter::HeaderEntryGetter( const Header & h_r, rpmTag & tag_r ) + : _rpmtd( ::rpmtdNew() ) + { ::headerGet( h_r, tag_r, _rpmtd, HEADERGET_DEFAULT ); } + inline HeaderEntryGetter::~HeaderEntryGetter() + { ::rpmtdFreeData( _rpmtd ); ::rpmtdFree( _rpmtd ); } + inline rpmTagType HeaderEntryGetter::type() { return rpmtdType( _rpmtd ); } + inline rpm_count_t HeaderEntryGetter::cnt() { return _rpmtd->count; } + inline void * HeaderEntryGetter::val() { return _rpmtd->data; } +#else + inline HeaderEntryGetter::HeaderEntryGetter( const Header & h_r, rpmTag & tag_r ) + : _type( RPM_NULL_TYPE ) + , _cnt( 0 ) + , _val( 0 ) + { ::headerGetEntry( h_r, tag_r, hTYP_t(&_type), &_val, &_cnt ); } + inline HeaderEntryGetter::~HeaderEntryGetter() + { if ( _val && _type == RPM_STRING_ARRAY_TYPE ) free( _val ); } + inline rpmTagType HeaderEntryGetter::type() { return _type; } + inline rpm_count_t HeaderEntryGetter::cnt() { return _cnt; } + inline void * HeaderEntryGetter::val() { return _val; } +#endif //_RPM_5 + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::intList +// +/////////////////////////////////////////////////////////////////// + +unsigned BinHeader::intList::set( void * val_r, unsigned cnt_r, rpmTagType type_r ) +{ + _type = type_r; // remember the type! + if ( val_r ) + switch ( _type ) + { +#if RPM_CHAR_TYPE != RPM_INT8_TYPE + case RPM_CHAR_TYPE: + std::vector( (char*)val_r, ((char*)val_r)+cnt_r ).swap( _data ); + break; +#endif + case RPM_INT8_TYPE: + std::vector( (int8_t*)val_r, ((int8_t*)val_r)+cnt_r ).swap( _data ); + break; + case RPM_INT16_TYPE: + std::vector( (int16_t*)val_r, ((int16_t*)val_r)+cnt_r ).swap( _data ); + break; + case RPM_INT32_TYPE: + std::vector( (int32_t*)val_r, ((int32_t*)val_r)+cnt_r ).swap( _data ); + break; +#ifndef _RPM_5 + case RPM_INT64_TYPE: + std::vector( (int64_t*)val_r, ((int64_t*)val_r)+cnt_r ).swap( _data ); + break; +#endif + default: + std::vector( cnt_r, 0L ).swap( _data ); + break; + } + else + _data.clear(); + return _data.size(); +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::stringList +// +/////////////////////////////////////////////////////////////////// + +unsigned BinHeader::stringList::set( char ** val_r, unsigned cnt_r ) +{ + if ( val_r ) + std::vector( val_r, val_r+cnt_r ).swap( _data ); + else + _data.clear(); + return _data.size(); +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader +// +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::BinHeader +// METHOD TYPE : Constructor +// +BinHeader::BinHeader( Header h_r ) + : _h( h_r ) +{ + if ( _h ) + { + headerLink( _h ); + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::BinHeader +// METHOD TYPE : Constructor +// +BinHeader::BinHeader( BinHeader::Ptr & rhs ) +{ + INT << "INJECT from " << rhs; + if ( ! (rhs && rhs->_h) ) + { + _h = 0; + } + else + { + _h = rhs->_h; // ::headerLink already done in rhs + rhs->_h = 0; + } + INT << ": " << *this << " (" << rhs << ")" << endl; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::~BinHeader +// METHOD TYPE : Destructor +// +BinHeader::~BinHeader() +{ + if ( _h ) + { + headerFree( _h ); + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::assertHeader +// METHOD TYPE : void +// +bool BinHeader::assertHeader() +{ + if ( !_h ) + { + _h = ::headerNew(); + if ( !_h ) + { + INT << "OOPS: NULL HEADER created!" << endl; + return false; + } + } + return true; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::has_tag +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool BinHeader::has_tag( tag tag_r ) const +{ + return( !empty() && ::headerIsEntry( _h, tag_r ) ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::int_list +// METHOD TYPE : unsigned +// +// DESCRIPTION : +// +unsigned BinHeader::int_list( tag tag_r, intList & lst_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return lst_r.set( 0, 0, headerget.type() ); +#if RPM_CHAR_TYPE != RPM_INT8_TYPE + case RPM_CHAR_TYPE: +#endif + case RPM_INT8_TYPE: + case RPM_INT16_TYPE: + case RPM_INT32_TYPE: +#ifndef _RPM_5 + case RPM_INT64_TYPE: +#endif + return lst_r.set( headerget.val(), headerget.cnt(), headerget.type() ); + + default: + INT << "RPM_TAG MISMATCH: RPM_INTxx_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return lst_r.set( 0, 0, RPM_NULL_TYPE ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::string_list +// METHOD TYPE : unsigned +// +// DESCRIPTION : +// +unsigned BinHeader::string_list( tag tag_r, stringList & lst_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return lst_r.set( 0, 0 ); + case RPM_STRING_ARRAY_TYPE: + return lst_r.set( (char**)headerget.val(), headerget.cnt() ); + + default: + INT << "RPM_TAG MISMATCH: RPM_STRING_ARRAY_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return lst_r.set( 0, 0 ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::int_val +// METHOD TYPE : int +// +// DESCRIPTION : +// +int BinHeader::int_val( tag tag_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return 0; +#if RPM_CHAR_TYPE != RPM_INT8_TYPE + case RPM_CHAR_TYPE: + return *((char*)headerget.val()); +#endif + case RPM_INT8_TYPE: + return *((int8_t*)headerget.val()); + case RPM_INT16_TYPE: + return *((int16_t*)headerget.val()); + case RPM_INT32_TYPE: + return *((int32_t*)headerget.val()); +#ifndef _RPM_5 + case RPM_INT64_TYPE: + return *((int64_t*)headerget.val()); +#endif + + default: + INT << "RPM_TAG MISMATCH: RPM_INTxx_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return 0; +} + +ByteArray BinHeader::blob_val( tag tag_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return {}; + case RPM_BIN_TYPE: + return ByteArray( reinterpret_cast( headerget.val() ), headerget.cnt() ); + default: + INT << "RPM_TAG MISSMATCH: RPM_BIN_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return {}; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::string_val +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string BinHeader::string_val( tag tag_r ) const +{ + if ( !empty() ) + { + HeaderEntryGetter headerget( _h, tag_r ); + + if ( headerget.val() ) + { + switch ( headerget.type() ) + { + case RPM_NULL_TYPE: + return ""; + case RPM_STRING_TYPE: + return (char*)headerget.val(); + + default: + INT << "RPM_TAG MISMATCH: RPM_STRING_TYPE " << tag_r << " got type " << headerget.type() << endl; + } + } + } + return ""; +} + +std::string BinHeader::format(const char *fmt) const +{ + zypp::AutoDispose form(headerFormat(_h, fmt, NULL), free); + if ( !form ) + return std::string(); + + return std::string(form); +} + +Header BinHeader::get() const +{ + return _h; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::stringList_val +// METHOD TYPE : std::list +// +// DESCRIPTION : +// +std::list BinHeader::stringList_val( tag tag_r ) const +{ + std::list ret; + + if ( !empty() ) + { + stringList lines; + unsigned count = string_list( tag_r, lines ); + for ( unsigned i = 0; i < count; ++i ) + { + ret.push_back( lines[i] ); + } + } + return ret; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : BinHeader::dumpOn +// METHOD TYPE : ostream & +// +// DESCRIPTION : +// +std::ostream & BinHeader::dumpOn( std::ostream & str ) const +{ + ReferenceCounted::dumpOn( str ); + return str << '{' << (void*)_h << '}'; +} + +} // namespace rpm +} // namespace target +} // namespace zypp diff --git a/zypp/target/rpm/BinHeader.h b/zypp/target/rpm/BinHeader.h new file mode 100644 index 0000000..b1ca85b --- /dev/null +++ b/zypp/target/rpm/BinHeader.h @@ -0,0 +1,174 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/BinHeader.h + * +*/ +#ifndef ZYPP_TARGET_RPM_BINHEADER_H +#define ZYPP_TARGET_RPM_BINHEADER_H + +extern "C" +{ +#include +} + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +namespace zypp +{ +namespace target +{ +namespace rpm +{ +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader +/** + * + **/ +class BinHeader : public base::ReferenceCounted, private base::NonCopyable +{ + +public: + + using Ptr = intrusive_ptr; + + using constPtr = intrusive_ptr; + + using tag = rpmTag; + + class intList; + + class stringList; + +private: + + Header _h; + + bool assertHeader(); + +public: + + BinHeader( Header h_r = 0 ); + + /** + * Dangerous!<\B> This one takes the header out of rhs + * and leaves rhs empty. + **/ + BinHeader( BinHeader::Ptr & rhs ); + + ~BinHeader() override; + +public: + + bool empty() const + { + return( _h == NULL ); + } + + bool has_tag( tag tag_r ) const; + + unsigned int_list( tag tag_r, intList & lst_r ) const; + + unsigned string_list( tag tag_r, stringList & lst_r ) const; + + int int_val( tag tag_r ) const; + + ByteArray blob_val ( tag tag_r ) const; + + std::string string_val( tag tag_r ) const; + std::string format ( const char * fmt) const; + + Header get() const; + +public: + + std::list stringList_val( tag tag_r ) const; + +public: + + std::ostream & dumpOn( std::ostream & str ) const override; +}; + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::intList +/** + * + **/ +class BinHeader::intList : private base::NonCopyable +{ + public: + intList() + : _type( RPM_NULL_TYPE ) + {} + + bool empty() const + { return _data.empty(); } + + unsigned size() const + { return _data.size(); } + + long operator[]( const unsigned idx_r ) const + { return idx_r < _data.size() ? _data[idx_r] : 0; } + + private: + friend class BinHeader; + unsigned set( void * val_r, unsigned cnt_r, rpmTagType type_r ); + + private: + std::vector _data; + rpmTagType _type; +}; + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : BinHeader::stringList +/** + * + **/ +class BinHeader::stringList : private base::NonCopyable +{ + public: + bool empty() const + { return _data.empty(); } + + unsigned size() const + { return _data.size(); } + + std::string operator[]( const unsigned idx_r ) const + { return idx_r < _data.size() ? _data[idx_r] : std::string(); } + + private: + friend class BinHeader; + unsigned set( char ** val_r, unsigned cnt_r ); + + private: + std::vector _data; +}; + +/////////////////////////////////////////////////////////////////// + +} // namespace rpm +} // namespace target +} // namespace zypp + +#endif // ZYPP_TARGET_RPM_BINHEADER_H diff --git a/zypp/target/rpm/RpmCallbacks.cc b/zypp/target/rpm/RpmCallbacks.cc new file mode 100644 index 0000000..e984d9e --- /dev/null +++ b/zypp/target/rpm/RpmCallbacks.cc @@ -0,0 +1,17 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmCallbacks.cc + * +*/ + +#include + +#include + +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/rpm/RpmCallbacks.h b/zypp/target/rpm/RpmCallbacks.h new file mode 100644 index 0000000..d2ad720 --- /dev/null +++ b/zypp/target/rpm/RpmCallbacks.h @@ -0,0 +1,109 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmCallbacks.h + * +*/ + +#ifndef ZYPP_TARGET_RPM_RPMCALLBACKS_H +#define ZYPP_TARGET_RPM_RPMCALLBACKS_H + +#include + +#include +#include +#include +#include + +namespace zypp +{ +namespace target +{ +namespace rpm +{ + +/////////////////////////////////////////////////////////////////// +// Reporting progress of package removing +/////////////////////////////////////////////////////////////////// +struct RpmRemoveReport : public callback::ReportBase +{ + + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // ignore + }; + + /** Start the operation */ + virtual void start( const std::string & name ) + {} + /** + * Inform about progress + * Return true on abort + */ + virtual bool progress( unsigned percent ) + { return false; } + + virtual Action problem( Exception & excpt_r ) + { return ABORT; } + + /** Additional rpm output to be reported in \ref finish in case of success. */ + virtual void finishInfo( const std::string & info_r ) + {} + + /** Finish operation in case of success */ + virtual void finish() + {} + /** Finish operation in case of fail, report fail exception */ + virtual void finish( Exception & excpt_r ) + {} +}; + +/////////////////////////////////////////////////////////////////// +// Reporting progress of package installation +/////////////////////////////////////////////////////////////////// +struct RpmInstallReport : public callback::ReportBase +{ + + enum Action { + ABORT, // abort and return error + RETRY, // retry + IGNORE // ignore + }; + + /** Start the operation */ + virtual void start( const Pathname & name ) + {} + /** + * Inform about progress + * Return false on abort + */ + virtual bool progress( unsigned percent ) + { return true; } + + /** Additional rpm output to be reported in \ref finish in case of success. */ + virtual void finishInfo( const std::string & info_r ) + {} + + /** Finish operation in case of success */ + virtual void finish() + {} + + virtual Action problem( Exception & excpt_r ) + { return ABORT; } + + /** Finish operation in case of fail, report fail exception */ + virtual void finish( Exception & excpt_r ) + {} +}; + +} // namespace rpm +} // namespace target +} // namespace zypp + +#endif // ZYPP_TARGET_RPM_RPMCALLBACKS_H diff --git a/zypp/target/rpm/RpmDb.cc b/zypp/target/rpm/RpmDb.cc new file mode 100644 index 0000000..2bb428f --- /dev/null +++ b/zypp/target/rpm/RpmDb.cc @@ -0,0 +1,2278 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmDb.cc + * +*/ +#include "librpm.h" +extern "C" +{ +#include +#include +} +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using std::endl; +using namespace zypp::filesystem; + +#define WARNINGMAILPATH "/var/log/YaST2/" +#define FILEFORBACKUPFILES "YaSTBackupModifiedFiles" +#define MAXRPMMESSAGELINES 10000 + +#define WORKAROUNDRPMPWDBUG + +// bsc#1216091 indicates that 'rpm --runposttrans' does not execute the +// scripts chroot if --root is used. We disable it if --root is not /. +#define WORKAROUNDDUMPPOSTTRANSBUG + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb" + +namespace zypp +{ + namespace zypp_readonly_hack + { + bool IGotIt(); // in readonly-mode + } + namespace env + { + inline bool ZYPP_RPM_DEBUG() + { + static bool val = [](){ + const char * env = getenv("ZYPP_RPM_DEBUG"); + return( env && str::strToBool( env, true ) ); + }(); + return val; + } + } // namespace env +namespace target +{ +namespace rpm +{ + const callback::UserData::ContentType InstallResolvableReport::contentRpmout( "rpmout","installpkg" ); + const callback::UserData::ContentType RemoveResolvableReport::contentRpmout( "rpmout","removepkg" ); + +namespace +{ +#if 1 // No more need to escape whitespace since rpm-4.4.2.3 +const char* quoteInFilename_m = "\'\""; +#else +const char* quoteInFilename_m = " \t\'\""; +#endif +inline std::string rpmQuoteFilename( const Pathname & path_r ) +{ + std::string path( path_r.asString() ); + for ( std::string::size_type pos = path.find_first_of( quoteInFilename_m ); + pos != std::string::npos; + pos = path.find_first_of( quoteInFilename_m, pos ) ) + { + path.insert( pos, "\\" ); + pos += 2; // skip '\\' and the quoted char. + } + return path; +} + + + /** Workaround bnc#827609 - rpm needs a readable pwd so we + * chdir to /. Turn realtive pathnames into absolute ones + * by prepending cwd so rpm still finds them + */ + inline Pathname workaroundRpmPwdBug( Pathname path_r ) + { +#if defined(WORKAROUNDRPMPWDBUG) + if ( path_r.relative() ) + { + // try to prepend cwd + AutoDispose cwd( ::get_current_dir_name(), ::free ); + if ( cwd ) + return Pathname( cwd ) / path_r; + WAR << "Can't get cwd!" << endl; + } +#endif + return path_r; // no problem with absolute pathnames + } +} + +struct KeyRingSignalReceiver : callback::ReceiveReport +{ + KeyRingSignalReceiver(RpmDb &rpmdb) : _rpmdb(rpmdb) { connect(); } + KeyRingSignalReceiver(const KeyRingSignalReceiver &) = delete; + KeyRingSignalReceiver(KeyRingSignalReceiver &&) = delete; + KeyRingSignalReceiver &operator=(const KeyRingSignalReceiver &) = delete; + KeyRingSignalReceiver &operator=(KeyRingSignalReceiver &&) = delete; + + ~KeyRingSignalReceiver() override + { + disconnect(); + } + + void trustedKeyAdded( const PublicKey &key ) override + { + MIL << "trusted key added to zypp Keyring. Importing..." << endl; + _rpmdb.importPubkey( key ); + } + + void trustedKeyRemoved( const PublicKey &key ) override + { + MIL << "Trusted key removed from zypp Keyring. Removing..." << endl; + _rpmdb.removePubkey( key ); + } + + RpmDb &_rpmdb; +}; + +static shared_ptr sKeyRingReceiver; + +unsigned diffFiles(const std::string& file1, const std::string& file2, std::string& out, int maxlines) +{ + const char* argv[] = + { + "diff", + "-u", + file1.c_str(), + file2.c_str(), + NULL + }; + ExternalProgram prog(argv,ExternalProgram::Discard_Stderr, false, -1, true); + + //if(!prog) + //return 2; + + std::string line; + int count = 0; + for (line = prog.receiveLine(), count=0; + !line.empty(); + line = prog.receiveLine(), count++ ) + { + if (maxlines<0?true:count report; + + report->start( root() + dbPath() ); + + try + { + doRebuildDatabase(report); + } + catch (RpmException & excpt_r) + { + report->finish(root() + dbPath(), RebuildDBReport::FAILED, excpt_r.asUserHistory()); + ZYPP_RETHROW(excpt_r); + } + report->finish(root() + dbPath(), RebuildDBReport::NO_ERROR, ""); +} + +void RpmDb::doRebuildDatabase(callback::SendReport & report) +{ + FAILIFNOTINITIALIZED; + MIL << "RpmDb::rebuildDatabase" << *this << endl; + + const Pathname mydbpath { root()/dbPath() }; // the configured path used in reports + { + // For --rebuilddb take care we're using the real db directory + // and not a symlink. Otherwise rpm will rename the symlink and + // replace it with a real directory containing the converted db. + DtorReset guardRoot { _root }; + DtorReset guardDbPath{ _dbPath }; + _root = "/"; + _dbPath = filesystem::expandlink( mydbpath ); + + // run rpm + RpmArgVec opts; + opts.push_back("--rebuilddb"); + opts.push_back("-vv"); + run_rpm (opts, ExternalProgram::Stderr_To_Stdout); + } + + // generate and report progress + ProgressData tics; + { + ProgressData::value_type hdrTotal = 0; + for ( librpmDb::db_const_iterator it; *it; ++it, ++hdrTotal ) + {;} + tics.range( hdrTotal ); + } + tics.sendTo( [&report,&mydbpath]( const ProgressData & tics_r ) -> bool { + return report->progress( tics_r.reportValue(), mydbpath ); + } ); + tics.toMin(); + + std::string line; + std::string errmsg; + while ( systemReadLine( line ) ) + { + static const std::string debugPrefix { "D:" }; + static const std::string progressPrefix { "D: read h#" }; + static const std::string ignoreSuffix { "digest: OK" }; + + if ( ! str::startsWith( line, debugPrefix ) ) + { + if ( ! str::endsWith( line, ignoreSuffix ) ) + { + errmsg += line; + errmsg += '\n'; + WAR << line << endl; + } + } + else if ( str::startsWith( line, progressPrefix ) ) + { + if ( ! tics.incr() ) + { + WAR << "User requested abort." << endl; + systemKill(); + } + } + } + + if ( systemStatus() != 0 ) + { + //TranslatorExplanation after semicolon is error message + ZYPP_THROW(RpmSubprocessException(std::string(_("RPM failed: ")) + (errmsg.empty() ? error_message: errmsg) ) ); + } + else + { + tics.toMax(); + } +} + +/////////////////////////////////////////////////////////////////// +namespace +{ + /** \ref RpmDb::syncTrustedKeys helper + * Compute which keys need to be exprted to / imported from the zypp keyring. + * Return result via argument list. + */ + void computeKeyRingSync( std::set & rpmKeys_r, std::list & zyppKeys_r ) + { + /////////////////////////////////////////////////////////////////// + // Remember latest release and where it ocurred + struct Key + { + Key() + : _inRpmKeys( nullptr ) + , _inZyppKeys( nullptr ) + {} + + void updateIf( const Edition & rpmKey_r ) + { + std::string keyRelease( rpmKey_r.release() ); + int comp = _release.compare( keyRelease ); + if ( comp < 0 ) + { + // update to newer release + _release.swap( keyRelease ); + _inRpmKeys = &rpmKey_r; + _inZyppKeys = nullptr; + if ( !keyRelease.empty() ) + DBG << "Old key in Z: gpg-pubkey-" << rpmKey_r.version() << "-" << keyRelease << endl; + } + else if ( comp == 0 ) + { + // stay with this release + if ( ! _inRpmKeys ) + _inRpmKeys = &rpmKey_r; + } + // else: this is an old release + else + DBG << "Old key in R: gpg-pubkey-" << rpmKey_r.version() << "-" << keyRelease << endl; + } + + void updateIf( const PublicKeyData & zyppKey_r ) + { + std::string keyRelease( zyppKey_r.gpgPubkeyRelease() ); + int comp = _release.compare( keyRelease ); + if ( comp < 0 ) + { + // update to newer release + _release.swap( keyRelease ); + _inRpmKeys = nullptr; + _inZyppKeys = &zyppKey_r; + if ( !keyRelease.empty() ) + DBG << "Old key in R: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << "-" << keyRelease << endl; + } + else if ( comp == 0 ) + { + // stay with this release + if ( ! _inZyppKeys ) + _inZyppKeys = &zyppKey_r; + } + // else: this is an old release + else + DBG << "Old key in Z: gpg-pubkey-" << zyppKey_r.gpgPubkeyVersion() << "-" << keyRelease << endl; + } + + std::string _release; + const Edition * _inRpmKeys; + const PublicKeyData * _inZyppKeys; + }; + /////////////////////////////////////////////////////////////////// + + // collect keys by ID(version) and latest creation(release) + std::map _keymap; + + for_( it, rpmKeys_r.begin(), rpmKeys_r.end() ) + { + _keymap[(*it).version()].updateIf( *it ); + } + + for_( it, zyppKeys_r.begin(), zyppKeys_r.end() ) + { + _keymap[(*it).gpgPubkeyVersion()].updateIf( *it ); + } + + // compute missing keys + std::set rpmKeys; + std::list zyppKeys; + for_( it, _keymap.begin(), _keymap.end() ) + { + DBG << "gpg-pubkey-" << (*it).first << "-" << (*it).second._release << " " + << ( (*it).second._inRpmKeys ? "R" : "_" ) + << ( (*it).second._inZyppKeys ? "Z" : "_" ) << endl; + if ( ! (*it).second._inRpmKeys ) + { + zyppKeys.push_back( *(*it).second._inZyppKeys ); + } + if ( ! (*it).second._inZyppKeys ) + { + rpmKeys.insert( *(*it).second._inRpmKeys ); + } + } + rpmKeys_r.swap( rpmKeys ); + zyppKeys_r.swap( zyppKeys ); + } +} // namespace +/////////////////////////////////////////////////////////////////// + +void RpmDb::syncTrustedKeys( SyncTrustedKeyBits mode_r ) +{ + MIL << "Going to sync trusted keys..." << endl; + std::set rpmKeys( pubkeyEditions() ); + std::list zyppKeys( getZYpp()->keyRing()->trustedPublicKeyData() ); + + if ( ! ( mode_r & SYNC_FROM_KEYRING ) ) + { + // bsc#1064380: We relief PK from removing excess keys in the zypp keyring + // when re-acquiring the zyppp lock. For now we remove all excess keys. + // TODO: Once we can safely assume that all PK versions are updated we + // can think about re-importing newer key versions found in the zypp keyring and + // removing only excess ones (but case is not very likely). Unfixed PK versions + // however will remove the newer version found in the zypp keyring and by doing + // this, the key here will be removed via callback as well (keys are deleted + // via gpg id, regardless of the edition). + MIL << "Removing excess keys in zypp trusted keyring" << std::endl; + // Temporarily disconnect to prevent the attempt to pass back the delete request. + callback::TempConnect tempDisconnect; + bool dirty = false; + for ( const PublicKeyData & keyData : zyppKeys ) + { + if ( ! rpmKeys.count( keyData.gpgPubkeyEdition() ) ) + { + DBG << "Excess key in Z to delete: gpg-pubkey-" << keyData.gpgPubkeyEdition() << endl; + getZYpp()->keyRing()->deleteKey( keyData.id(), /*trusted*/true ); + if ( !dirty ) dirty = true; + } + } + if ( dirty ) + zyppKeys = getZYpp()->keyRing()->trustedPublicKeyData(); + } + + computeKeyRingSync( rpmKeys, zyppKeys ); + MIL << (mode_r & SYNC_TO_KEYRING ? "" : "(skip) ") << "Rpm keys to export into zypp trusted keyring: " << rpmKeys.size() << endl; + MIL << (mode_r & SYNC_FROM_KEYRING ? "" : "(skip) ") << "Zypp trusted keys to import into rpm database: " << zyppKeys.size() << endl; + + /////////////////////////////////////////////////////////////////// + if ( (mode_r & SYNC_TO_KEYRING) && ! rpmKeys.empty() ) + { + // export to zypp keyring + MIL << "Exporting rpm keyring into zypp trusted keyring" < tempDisconnect; + librpmDb::db_const_iterator keepDbOpen; // just to keep a ref. + + TmpFile tmpfile( getZYpp()->tmpPath() ); + { + std::ofstream tmpos( tmpfile.path().c_str() ); + for_( it, rpmKeys.begin(), rpmKeys.end() ) + { + // we export the rpm key into a file + RpmHeader::constPtr result; + getData( "gpg-pubkey", *it, result ); + tmpos << result->tag_description() << endl; + } + } + try + { + getZYpp()->keyRing()->multiKeyImport( tmpfile.path(), true /*trusted*/); + // bsc#1096217: Try to spot and report legacy V3 keys found in the rpm database. + // Modern rpm does not import those keys, but when migrating a pre SLE12 system + // we may find them. rpm>4.13 even complains on sderr if sucha key is present. + std::set missingKeys; + for ( const Edition & key : rpmKeys ) + { + if ( getZYpp()->keyRing()->isKeyTrusted( key.version() ) ) // key.version is the gpgkeys short ID + continue; + ERR << "Could not import key:" << str::Format("gpg-pubkey-%s") % key << " into zypp keyring (V3 key?)" << endl; + missingKeys.insert( key ); + } + if ( ! missingKeys.empty() ) + callback::SendReport()->reportNonImportedKeys(missingKeys); + } + catch ( const Exception & excpt ) + { + ZYPP_CAUGHT( excpt ); + ERR << "Could not import keys into zypp keyring: " << endl; + } + } + + /////////////////////////////////////////////////////////////////// + if ( (mode_r & SYNC_FROM_KEYRING) && ! zyppKeys.empty() ) + { + // import from zypp keyring + MIL << "Importing zypp trusted keyring" << std::endl; + for_( it, zyppKeys.begin(), zyppKeys.end() ) + { + try + { + importPubkey( getZYpp()->keyRing()->exportTrustedPublicKey( *it ) ); + } + catch ( const RpmException & exp ) + { + ZYPP_CAUGHT( exp ); + } + } + } + MIL << "Trusted keys synced." << endl; +} + +void RpmDb::importZyppKeyRingTrustedKeys() +{ syncTrustedKeys( SYNC_FROM_KEYRING ); } + +void RpmDb::exportTrustedKeysInZyppKeyRing() +{ syncTrustedKeys( SYNC_TO_KEYRING ); } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::importPubkey +// METHOD TYPE : PMError +// +void RpmDb::importPubkey( const PublicKey & pubkey_r ) +{ + FAILIFNOTINITIALIZED; + + // bnc#828672: On the fly key import in READONLY + if ( zypp_readonly_hack::IGotIt() ) + { + WAR << "Key " << pubkey_r << " can not be imported. (READONLY MODE)" << endl; + return; + } + + // check if the key is already in the rpm database + Edition keyEd( pubkey_r.gpgPubkeyVersion(), pubkey_r.gpgPubkeyRelease() ); + std::set rpmKeys = pubkeyEditions(); + bool hasOldkeys = false; + + for_( it, rpmKeys.begin(), rpmKeys.end() ) + { + // bsc#1008325: Keys using subkeys for signing don't get a higher release + // if new subkeys are added, because the primary key remains unchanged. + // For now always re-import keys with subkeys. Here we don't want to export the + // keys in the rpm database to check whether the subkeys are the same. The calling + // code should take care, we don't re-import the same kesy over and over again. + if ( keyEd == *it && !pubkey_r.hasSubkeys() ) // quick test (Edition is IdStringType!) + { + MIL << "Key " << pubkey_r << " is already in the rpm trusted keyring. (skip import)" << endl; + return; + } + + if ( keyEd.version() != (*it).version() ) + continue; // different key ID (version) + + if ( keyEd.release() < (*it).release() ) + { + MIL << "Key " << pubkey_r << " is older than one in the rpm trusted keyring. (skip import)" << endl; + return; + } + else + { + hasOldkeys = true; + } + } + MIL << "Key " << pubkey_r << " will be imported into the rpm trusted keyring." << (hasOldkeys?"(update)":"(new)") << endl; + + if ( hasOldkeys ) + { + // We must explicitly delete old key IDs first (all releases, + // that's why we don't call removePubkey here). + std::string keyName( "gpg-pubkey-" + keyEd.version() ); + RpmArgVec opts; + opts.push_back ( "-e" ); + opts.push_back ( "--allmatches" ); + opts.push_back ( "--" ); + opts.push_back ( keyName.c_str() ); + run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); + + std::string line; + while ( systemReadLine( line ) ) + { + ( str::startsWith( line, "error:" ) ? WAR : DBG ) << line << endl; + } + + if ( systemStatus() != 0 ) + { + ERR << "Failed to remove key " << pubkey_r << " from RPM trusted keyring (ignored)" << endl; + } + else + { + MIL << "Key " << pubkey_r << " has been removed from RPM trusted keyring" << endl; + } + } + + // import the new key + RpmArgVec opts; + opts.push_back ( "--import" ); + opts.push_back ( "--" ); + std::string pubkeypath( pubkey_r.path().asString() ); + opts.push_back ( pubkeypath.c_str() ); + run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); + + std::string line; + std::vector excplines; + while ( systemReadLine( line ) ) + { + if ( str::startsWith( line, "error:" ) ) + { + WAR << line << endl; + excplines.push_back( std::move(line) ); + } + else + DBG << line << endl; + } + + if ( systemStatus() != 0 ) + { + // Translator: %1% is a gpg public key + RpmSubprocessException excp( str::Format(_("Failed to import public key %1%") ) % pubkey_r.asString() ); + excp.moveToHistory( excplines ); + excp.addHistory( std::move(error_message) ); + ZYPP_THROW( excp ); + } + else + { + MIL << "Key " << pubkey_r << " imported in rpm trusted keyring." << endl; + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::removePubkey +// METHOD TYPE : PMError +// +void RpmDb::removePubkey( const PublicKey & pubkey_r ) +{ + FAILIFNOTINITIALIZED; + + // check if the key is in the rpm database and just + // return if it does not. + std::set rpm_keys = pubkeyEditions(); + std::set::const_iterator found_edition = rpm_keys.end(); + std::string pubkeyVersion( pubkey_r.gpgPubkeyVersion() ); + + for_( it, rpm_keys.begin(), rpm_keys.end() ) + { + if ( (*it).version() == pubkeyVersion ) + { + found_edition = it; + break; + } + } + + // the key does not exist, cannot be removed + if (found_edition == rpm_keys.end()) + { + WAR << "Key " << pubkey_r.id() << " is not in rpm db" << endl; + return; + } + + std::string rpm_name("gpg-pubkey-" + found_edition->asString()); + + RpmArgVec opts; + opts.push_back ( "-e" ); + opts.push_back ( "--" ); + opts.push_back ( rpm_name.c_str() ); + run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); + + std::string line; + std::vector excplines; + while ( systemReadLine( line ) ) + { + if ( str::startsWith( line, "error:" ) ) + { + WAR << line << endl; + excplines.push_back( std::move(line) ); + } + else + DBG << line << endl; + } + + if ( systemStatus() != 0 ) + { + // Translator: %1% is a gpg public key + RpmSubprocessException excp( str::Format(_("Failed to remove public key %1%") ) % pubkey_r.asString() ); + excp.moveToHistory( excplines ); + excp.addHistory( std::move(error_message) ); + ZYPP_THROW( excp ); + } + else + { + MIL << "Key " << pubkey_r << " has been removed from RPM trusted keyring" << endl; + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::pubkeys +// METHOD TYPE : std::set +// +std::list RpmDb::pubkeys() const +{ + std::list ret; + + librpmDb::db_const_iterator it; + for ( it.findByName( "gpg-pubkey" ); *it; ++it ) + { + Edition edition = it->tag_edition(); + if (edition != Edition::noedition) + { + // we export the rpm key into a file + RpmHeader::constPtr result; + getData( "gpg-pubkey", edition, result ); + TmpFile file(getZYpp()->tmpPath()); + std::ofstream os; + try + { + os.open(file.path().asString().c_str()); + // dump rpm key into the tmp file + os << result->tag_description(); + //MIL << "-----------------------------------------------" << endl; + //MIL << result->tag_description() < RpmDb::pubkeyEditions() const + { + std::set ret; + + librpmDb::db_const_iterator it; + for ( it.findByName( "gpg-pubkey" ); *it; ++it ) + { + Edition edition = it->tag_edition(); + if (edition != Edition::noedition) + ret.insert( edition ); + } + return ret; + } + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::fileList +// METHOD TYPE : bool +// +// DESCRIPTION : +// +std::list +RpmDb::fileList( const std::string & name_r, const Edition & edition_r ) const +{ + std::list result; + + librpmDb::db_const_iterator it; + bool found = false; + if (edition_r == Edition::noedition) + { + found = it.findPackage( name_r ); + } + else + { + found = it.findPackage( name_r, edition_r ); + } + if (!found) + return result; + + return result; +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::hasFile +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool RpmDb::hasFile( const std::string & file_r, const std::string & name_r ) const +{ + librpmDb::db_const_iterator it; + bool res = false; + do + { + res = it.findByFile( file_r ); + if (!res) break; + if (!name_r.empty()) + { + res = (it->tag_name() == name_r); + } + ++it; + } + while (res && *it); + return res; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::whoOwnsFile +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmDb::whoOwnsFile( const std::string & file_r) const +{ + librpmDb::db_const_iterator it; + if (it.findByFile( file_r )) + { + return it->tag_name(); + } + return ""; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::hasProvides +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool RpmDb::hasProvides( const std::string & tag_r ) const +{ + librpmDb::db_const_iterator it; + return it.findByProvides( tag_r ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::hasRequiredBy +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool RpmDb::hasRequiredBy( const std::string & tag_r ) const +{ + librpmDb::db_const_iterator it; + return it.findByRequiredBy( tag_r ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::hasConflicts +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool RpmDb::hasConflicts( const std::string & tag_r ) const +{ + librpmDb::db_const_iterator it; + return it.findByConflicts( tag_r ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::hasPackage +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool RpmDb::hasPackage( const std::string & name_r ) const +{ + librpmDb::db_const_iterator it; + return it.findPackage( name_r ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::hasPackage +// METHOD TYPE : bool +// +// DESCRIPTION : +// +bool RpmDb::hasPackage( const std::string & name_r, const Edition & ed_r ) const +{ + librpmDb::db_const_iterator it; + return it.findPackage( name_r, ed_r ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::getData +// METHOD TYPE : PMError +// +// DESCRIPTION : +// +void RpmDb::getData( const std::string & name_r, + RpmHeader::constPtr & result_r ) const +{ + librpmDb::db_const_iterator it; + it.findPackage( name_r ); + result_r = *it; + if (it.dbError()) + ZYPP_THROW(*(it.dbError())); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::getData +// METHOD TYPE : void +// +// DESCRIPTION : +// +void RpmDb::getData( const std::string & name_r, const Edition & ed_r, + RpmHeader::constPtr & result_r ) const +{ + librpmDb::db_const_iterator it; + it.findPackage( name_r, ed_r ); + result_r = *it; + if (it.dbError()) + ZYPP_THROW(*(it.dbError())); +} + +/////////////////////////////////////////////////////////////////// +namespace +{ + struct RpmlogCapture : public std::vector + { + RpmlogCapture() + { + rpmlogSetCallback( rpmLogCB, this ); + _oldMask = rpmlogSetMask( RPMLOG_UPTO( RPMLOG_PRI(RPMLOG_INFO) ) ); + } + + RpmlogCapture(const RpmlogCapture &) = delete; + RpmlogCapture(RpmlogCapture &&) = delete; + RpmlogCapture &operator=(const RpmlogCapture &) = delete; + RpmlogCapture &operator=(RpmlogCapture &&) = delete; + + ~RpmlogCapture() { + rpmlogSetCallback( nullptr, nullptr ); + rpmlogSetMask( _oldMask ); + } + + static int rpmLogCB( rpmlogRec rec_r, rpmlogCallbackData data_r ) + { return reinterpret_cast(data_r)->rpmLog( rec_r ); } + + int rpmLog( rpmlogRec rec_r ) + { + std::string l { ::rpmlogRecMessage( rec_r ) }; // NL terminated line! + l.pop_back(); // strip trailing NL + push_back( std::move(l) ); + return 0; + } + + private: + int _oldMask = 0; + }; + + std::ostream & operator<<( std::ostream & str, const RpmlogCapture & obj ) + { + char sep = '\0'; + for ( const auto & l : obj ) { + if ( sep ) str << sep; else sep = '\n'; + str << l; + } + return str; + } + + + RpmDb::CheckPackageResult doCheckPackageSig( const Pathname & path_r, // rpm file to check + const Pathname & root_r, // target root + bool requireGPGSig_r, // whether no gpg signature is to be reported + RpmDb::CheckPackageDetail & detail_r ) // detailed result + { + PathInfo file( path_r ); + if ( ! file.isFile() ) + { + ERR << "Not a file: " << file << endl; + return RpmDb::CHK_ERROR; + } + + FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" ); + if ( fd == 0 || ::Ferror(fd) ) + { + ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl; + if ( fd ) + ::Fclose( fd ); + return RpmDb::CHK_ERROR; + } + rpmts ts = ::rpmtsCreate(); + ::rpmtsSetRootDir( ts, root_r.c_str() ); + ::rpmtsSetVSFlags( ts, RPMVSF_DEFAULT ); +#ifdef HAVE_RPM_VERIFY_TRANSACTION_STEP + ::rpmtsSetVfyFlags( ts, RPMVSF_DEFAULT ); +#endif + + RpmlogCapture vresult; + LocaleGuard guard( LC_ALL, "C" ); // bsc#1076415: rpm log output is localized, but we need to parse it :( + static rpmQVKArguments_s qva = ([](){ rpmQVKArguments_s qva; memset( &qva, 0, sizeof(rpmQVKArguments_s) ); return qva; })(); + int res = ::rpmVerifySignatures( &qva, ts, fd, path_r.basename().c_str() ); + guard.restore(); + + ts = rpmtsFree(ts); + ::Fclose( fd ); + + // Check the individual signature/disgest results: + + // To.map back known result strings to enum, everything else is CHK_ERROR. + typedef std::map ResultMap; + static const ResultMap resultMap { + { "OK", RpmDb::CHK_OK }, + { "NOKEY", RpmDb::CHK_NOKEY }, + { "BAD", RpmDb::CHK_FAIL }, + { "UNKNOWN", RpmDb::CHK_NOTFOUND }, + { "NOTRUSTED", RpmDb::CHK_NOTTRUSTED }, + { "NOTFOUND", RpmDb::CHK_NOTFOUND }, + }; + auto getresult = []( const ResultMap & resultMap, ResultMap::key_type key )->ResultMap::mapped_type { + auto it = resultMap.find( key ); + return it != resultMap.end() ? it->second : RpmDb::CHK_ERROR; + }; + + // To track the signature states we saw. + unsigned count[7] = { 0, 0, 0, 0, 0, 0, 0 }; + + // To track the kind off sigs we saw. + enum Saw { + SawNone = 0, + SawHeaderSig = (1 << 0), // Header V3 RSA/SHA256 Signature, key ID 3dbdc284: OK + SawHeaderDigest = (1 << 1), // Header SHA1 digest: OK (a60386347863affefef484ff1f26c889373eb094) + SawPayloadDigest = (1 << 2), // Payload SHA256 digest: OK + SawSig = (1 << 3), // V3 RSA/SHA256 Signature, key ID 3dbdc284: OK + SawDigest = (1 << 4), // MD5 digest: OK (fd5259fe677a406951dcb2e9d08c4dcc) + }; + unsigned saw = SawNone; + + static const str::regex rx( "^ *(Header|Payload)? .*(Signature, key|digest).*: ([A-Z]+)" ); + str::smatch what; + for ( const std::string & line : vresult ) + { + if ( line[0] != ' ' ) // result lines are indented + continue; + + RpmDb::CheckPackageResult lineres = RpmDb::CHK_ERROR; + if ( str::regex_match( line, what, rx ) ) { + + lineres = getresult( resultMap, what[3] ); + if ( lineres == RpmDb::CHK_NOTFOUND ) + continue; // just collect details for signatures found (#229) + + if ( what[1][0] == 'H' ) { + saw |= ( what[2][0] == 'S' ? SawHeaderSig :SawHeaderDigest ); + } + else if ( what[1][0] == 'P' ) { + if ( what[2][0] == 'd' ) saw |= SawPayloadDigest; + } + else { + saw |= ( what[2][0] == 'S' ? SawSig : SawDigest ); + } + } + + ++count[lineres]; + detail_r.push_back( RpmDb::CheckPackageDetail::value_type( lineres, line ) ); + } + + // Now combine the overall result: + RpmDb::CheckPackageResult ret = ( res ? RpmDb::CHK_ERROR : RpmDb::CHK_OK ); + + if ( count[RpmDb::CHK_FAIL] ) + ret = RpmDb::CHK_FAIL; + + else if ( count[RpmDb::CHK_NOTFOUND] ) + ret = RpmDb::CHK_NOTFOUND; + + else if ( count[RpmDb::CHK_NOKEY] ) + ret = RpmDb::CHK_NOKEY; + + else if ( count[RpmDb::CHK_NOTTRUSTED] ) + ret = RpmDb::CHK_NOTTRUSTED; + + else if ( ret == RpmDb::CHK_OK ) { + // Everything is OK, so check whether it's sufficient. + // bsc#1184501: To count as signed the package needs a header signature + // and either a payload digest (secured by the header sig) or a content signature. + bool isSigned = (saw & SawHeaderSig) && ( (saw & SawPayloadDigest) || (saw & SawSig) ); + if ( not isSigned ) { + std::string message { " " }; + if ( not (saw & SawHeaderSig) ) + message += _("Package header is not signed!"); + else + message += _("Package payload is not signed!"); + + detail_r.push_back( RpmDb::CheckPackageDetail::value_type( RpmDb::CHK_NOSIG, std::move(message) ) ); + if ( requireGPGSig_r ) + ret = RpmDb::CHK_NOSIG; + } + } + + if ( ret != RpmDb::CHK_OK ) + { + // In case of an error line results may be reported to the user. In case rpm printed + // only 8byte key IDs to stdout we try to get longer IDs from the header. + bool didReadHeader = false; + std::unordered_map< std::string, std::string> fprs; + + // we replace the data only if the key IDs are actually only 8 bytes + str::regex rxexpr( "key ID ([a-fA-F0-9]{8}):" ); + for ( auto &detail : detail_r ) { + auto &line = detail.second; + str::smatch what; + if ( str::regex_match( line, what, rxexpr ) ) { + + if ( !didReadHeader ) { + didReadHeader = true; + + // Get signature info from the package header, RPM always prints only the 8 byte ID + auto header = RpmHeader::readPackage( path_r, RpmHeader::NOVERIFY ); + if ( header ) { + auto keyMgr = zypp::KeyManagerCtx::createForOpenPGP(); + const auto &addFprs = [&]( auto tag ){ + const auto &list1 = keyMgr.readSignatureFingerprints( header->blob_val( tag ) ); + for ( const auto &id : list1 ) { + if ( id.size() <= 8 ) + continue; + + const auto &lowerId = str::toLower( id ); + fprs.insert( std::make_pair( lowerId.substr( lowerId.size() - 8 ), lowerId ) ); + } + }; + + addFprs( RPMTAG_SIGGPG ); + addFprs( RPMTAG_SIGPGP ); + addFprs( RPMTAG_RSAHEADER ); + addFprs( RPMTAG_DSAHEADER ); + + } else { + ERR << "Failed to read package signatures." << std::endl; + } + } + + // if we have no keys we can substitute we can leave the loop right away + if ( !fprs.size() ) + break; + + { + // replace the short key ID with the long ones parsed from the header + const auto &keyId = str::toLower( what[1] ); + if ( const auto &i = fprs.find( keyId ); i != fprs.end() ) { + str::replaceAll( line, keyId, i->second ); + } + } + } + } + + WAR << path_r << " (" << requireGPGSig_r << " -> " << ret << ")" << endl; + WAR << vresult << endl; + } + else + DBG << path_r << " [0-Signature is OK]" << endl; + return ret; + } + +} // namespace +/////////////////////////////////////////////////////////////////// +// +// METHOD NAME : RpmDb::checkPackage +// METHOD TYPE : RpmDb::CheckPackageResult +// +RpmDb::CheckPackageResult RpmDb::checkPackage( const Pathname & path_r, CheckPackageDetail & detail_r ) +{ return doCheckPackageSig( path_r, root(), false/*requireGPGSig_r*/, detail_r ); } + +RpmDb::CheckPackageResult RpmDb::checkPackage( const Pathname & path_r ) +{ CheckPackageDetail dummy; return checkPackage( path_r, dummy ); } + +RpmDb::CheckPackageResult RpmDb::checkPackageSignature( const Pathname & path_r, RpmDb::CheckPackageDetail & detail_r ) +{ return doCheckPackageSig( path_r, root(), true/*requireGPGSig_r*/, detail_r ); } + + +// determine changed files of installed package +bool +RpmDb::queryChangedFiles(FileList & fileList, const std::string& packageName) +{ + bool ok = true; + + fileList.clear(); + + if ( ! initialized() ) return false; + + RpmArgVec opts; + + opts.push_back ("-V"); + opts.push_back ("--nodeps"); + opts.push_back ("--noscripts"); + opts.push_back ("--nomd5"); + opts.push_back ("--"); + opts.push_back (packageName.c_str()); + + run_rpm (opts, ExternalProgram::Discard_Stderr); + + if ( process == NULL ) + return false; + + /* from rpm manpage + 5 MD5 sum + S File size + L Symlink + T Mtime + D Device + U User + G Group + M Mode (includes permissions and file type) + */ + + std::string line; + while (systemReadLine(line)) + { + if (line.length() > 12 && + (line[0] == 'S' || line[0] == 's' || + (line[0] == '.' && line[7] == 'T'))) + { + // file has been changed + std::string filename; + + filename.assign(line, 11, line.length() - 11); + fileList.insert(filename); + } + } + + systemStatus(); + // exit code ignored, rpm returns 1 no matter if package is installed or + // not + + return ok; +} + + +/****************************************************************/ +/* private member-functions */ +/****************************************************************/ + +/*--------------------------------------------------------------*/ +/* Run rpm with the specified arguments, handling stderr */ +/* as specified by disp */ +/*--------------------------------------------------------------*/ +void +RpmDb::run_rpm (const RpmArgVec& opts, + ExternalProgram::Stderr_Disposition disp) +{ + if ( process ) + { + delete process; + process = NULL; + } + exit_code = -1; + + if ( ! initialized() ) + { + ZYPP_THROW(RpmDbNotOpenException()); + } + + RpmArgVec args; + + // always set root and dbpath +#if defined(WORKAROUNDRPMPWDBUG) + args.push_back("#/"); // chdir to / to workaround bnc#819354 +#endif + args.push_back("rpm"); + args.push_back("--root"); + args.push_back(_root.asString().c_str()); + args.push_back("--dbpath"); + args.push_back(_dbPath.asString().c_str()); + if ( env::ZYPP_RPM_DEBUG() ) + args.push_back("-vv"); + const char* argv[args.size() + opts.size() + 1]; + + const char** p = argv; + p = copy (args.begin (), args.end (), p); + p = copy (opts.begin (), opts.end (), p); + *p = 0; + + // Invalidate all outstanding database handles in case + // the database gets modified. + librpmDb::dbRelease( true ); + + // Launch the program with default locale + process = new ExternalProgram(argv, disp, false, -1, true); + return; +} + +/*--------------------------------------------------------------*/ +/* Read a line from the rpm process */ +/*--------------------------------------------------------------*/ +bool RpmDb::systemReadLine( std::string & line ) +{ + line.erase(); + + if ( process == NULL ) + return false; + + if ( process->inputFile() ) + { + process->setBlocking( false ); + FILE * inputfile = process->inputFile(); + do { + // Check every 5 seconds if the process is still running to prevent against + // daemons launched in rpm %post that do not close their filedescriptors, + // causing us to block for infinity. (bnc#174548) + const auto &readResult = io::receiveUpto( inputfile, '\n', 5 * 1000, false ); + switch ( readResult.first ) { + case io::ReceiveUpToResult::Timeout: { + if ( !process->running() ) + return false; + + // we might have received a partial line, lets not forget about it + line += readResult.second; + break; + } + case io::ReceiveUpToResult::Error: + case io::ReceiveUpToResult::EndOfFile: { + line += readResult.second; + if ( line.size() && line.back() == '\n') + line.pop_back(); + return line.size(); // in case of pending output + } + case io::ReceiveUpToResult::Success: { + line += readResult.second; + + if ( line.size() && line.back() == '\n') + line.pop_back(); + + if ( env::ZYPP_RPM_DEBUG() ) + L_DBG("RPM_DEBUG") << line << endl; + return true; // complete line + } + } + } while( true ); + } + return false; +} + +/*--------------------------------------------------------------*/ +/* Return the exit status of the rpm process, closing the */ +/* connection if not already done */ +/*--------------------------------------------------------------*/ +int +RpmDb::systemStatus() +{ + if ( process == NULL ) + return -1; + + exit_code = process->close(); + if (exit_code == 0) + error_message = ""; + else + error_message = process->execError(); + process->kill(); + delete process; + process = 0; + + // DBG << "exit code " << exit_code << endl; + + return exit_code; +} + +/*--------------------------------------------------------------*/ +/* Forcably kill the rpm process */ +/*--------------------------------------------------------------*/ +void +RpmDb::systemKill() +{ + if (process) process->kill(); +} + + +// generate diff mails for config files +void RpmDb::processConfigFiles(const std::string& line, const std::string& name, const char* typemsg, const char* difffailmsg, const char* diffgenmsg) +{ + std::string msg = line.substr(9); + std::string::size_type pos1 = std::string::npos; + std::string::size_type pos2 = std::string::npos; + std::string file1s, file2s; + Pathname file1; + Pathname file2; + + pos1 = msg.find (typemsg); + for (;;) + { + if ( pos1 == std::string::npos ) + break; + + pos2 = pos1 + strlen (typemsg); + + if (pos2 >= msg.length() ) + break; + + file1 = msg.substr (0, pos1); + file2 = msg.substr (pos2); + + file1s = file1.asString(); + file2s = file2.asString(); + + if (!_root.empty() && _root != "/") + { + file1 = _root + file1; + file2 = _root + file2; + } + + std::string out; + int ret = diffFiles (file1.asString(), file2.asString(), out, 25); + if (ret) + { + Pathname file = _root + WARNINGMAILPATH; + if (filesystem::assert_dir(file) != 0) + { + ERR << "Could not create " << file.asString() << endl; + break; + } + file += Date(Date::now()).form("config_diff_%Y_%m_%d.log"); + std::ofstream notify(file.asString().c_str(), std::ios::out|std::ios::app); + if (!notify) + { + ERR << "Could not open " << file << endl; + break; + } + + // Translator: %s = name of an rpm package. A list of diffs follows + // this message. + notify << str::form(_("Changed configuration files for %s:"), name.c_str()) << endl; + if (ret>1) + { + ERR << "diff failed" << endl; + notify << str::form(difffailmsg, + file1s.c_str(), file2s.c_str()) << endl; + } + else + { + notify << str::form(diffgenmsg, + file1s.c_str(), file2s.c_str()) << endl; + + // remove root for the viewer's pleasure (#38240) + if (!_root.empty() && _root != "/") + { + if (out.substr(0,4) == "--- ") + { + out.replace(4, file1.asString().length(), file1s); + } + std::string::size_type pos = out.find("\n+++ "); + if (pos != std::string::npos) + { + out.replace(pos+5, file2.asString().length(), file2s); + } + } + notify << out << endl; + } + notify.close(); + notify.open("/var/lib/update-messages/yast2-packagemanager.rpmdb.configfiles"); + notify.close(); + } + else + { + WAR << "rpm created " << file2 << " but it is not different from " << file2 << endl; + } + break; + } +} + +/////////////////////////////////////////////////////////////////// +// +// METHOD NAME : RpmDb::installPackage +// +void RpmDb::installPackage( const Pathname & filename, RpmInstFlags flags ) +{ installPackage( filename, flags, nullptr ); } + +void RpmDb::installPackage( const Pathname & filename, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r ) +{ + if ( postTransCollector_r && postTransCollector_r->hasPosttransScript( filename ) ) + flags |= rpm::RPMINST_NOPOSTTRANS; // Just set the flag here. In \ref doInstallPackage we collect what else is needed. + + callback::SendReport report; + + report->start(filename); + + do + try + { + doInstallPackage( filename, flags, postTransCollector_r, report ); + report->finish(); + break; + } + catch (RpmException & excpt_r) + { + RpmInstallReport::Action user = report->problem( excpt_r ); + + if ( user == RpmInstallReport::ABORT ) + { + report->finish( excpt_r ); + ZYPP_RETHROW(excpt_r); + } + else if ( user == RpmInstallReport::IGNORE ) + { + break; + } + } + while (true); +} + +void RpmDb::doInstallPackage( const Pathname & filename, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r, callback::SendReport & report ) +{ + FAILIFNOTINITIALIZED; + HistoryLog historylog; + + MIL << "RpmDb::installPackage(" << filename << "," << flags << ")" << endl; + + // backup + if ( _packagebackups ) + { + // FIXME report->progress( pd.init( -2, 100 ) ); // allow 1% for backup creation. + if ( ! backupPackage( filename ) ) + { + ERR << "backup of " << filename.asString() << " failed" << endl; + } + // FIXME status handling + report->progress( 0 ); // allow 1% for backup creation. + } + + // run rpm + RpmArgVec opts; +#if defined(WORKAROUNDDUMPPOSTTRANSBUG) + if ( postTransCollector_r && _root == "/" ) { +#else + if ( postTransCollector_r ) { +#endif + opts.push_back("--define"); // bsc#1041742: Attempt to delay %transfiletrigger(postun|in) execution iff rpm supports it. + opts.push_back("_dump_posttrans 1"); // Old rpm ignores the --define, new rpm injects 'dump_posttrans:' lines to collect and execute later. + } + if (flags & RPMINST_NOUPGRADE) + opts.push_back("-i"); + else + opts.push_back("-U"); + + opts.push_back("--percent"); + opts.push_back("--noglob"); + + // ZConfig defines cross-arch installation + if ( ! ZConfig::instance().systemArchitecture().compatibleWith( ZConfig::instance().defaultSystemArchitecture() ) ) + opts.push_back("--ignorearch"); + + if (flags & RPMINST_NODIGEST) + opts.push_back("--nodigest"); + if (flags & RPMINST_NOSIGNATURE) + opts.push_back("--nosignature"); + if (flags & RPMINST_EXCLUDEDOCS) + opts.push_back ("--excludedocs"); + if (flags & RPMINST_NOSCRIPTS) + opts.push_back ("--noscripts"); + if (flags & RPMINST_FORCE) + opts.push_back ("--force"); + if (flags & RPMINST_NODEPS) + opts.push_back ("--nodeps"); + if (flags & RPMINST_IGNORESIZE) + opts.push_back ("--ignoresize"); + if (flags & RPMINST_JUSTDB) + opts.push_back ("--justdb"); + if (flags & RPMINST_TEST) + opts.push_back ("--test"); + if (flags & RPMINST_NOPOSTTRANS) + opts.push_back ("--noposttrans"); + + opts.push_back("--"); + + // rpm requires additional quoting of special chars: + std::string quotedFilename( rpmQuoteFilename( workaroundRpmPwdBug( filename ) ) ); + opts.push_back ( quotedFilename.c_str() ); + run_rpm( opts, ExternalProgram::Stderr_To_Stdout ); + + // forward additional rpm output via report; + std::string line; + unsigned lineno = 0; + callback::UserData cmdout( InstallResolvableReport::contentRpmout ); + // Key "solvable" injected by RpmInstallPackageReceiver + cmdout.set( "line", std::cref(line) ); + cmdout.set( "lineno", lineno ); + + // LEGACY: collect and forward additional rpm output in finish + std::string rpmmsg; + std::vector configwarnings; // TODO: immediately process lines rather than collecting + std::vector runposttrans; // bsc#1041742: If rpm supports --runposttrans it injects 'dump_posttrans:' lines we do collect + + while ( systemReadLine( line ) ) + { + if ( str::startsWith( line, "%%" ) ) + { + int percent = 0; + sscanf( line.c_str() + 2, "%d", &percent ); + report->progress( percent ); + continue; + } + if ( str::hasPrefix( line, "dump_posttrans:" ) ) { + runposttrans.push_back( line ); + continue; + } + ++lineno; + cmdout.set( "lineno", lineno ); + report->report( cmdout ); + + if ( lineno >= MAXRPMMESSAGELINES ) { + if ( line.find( " scriptlet failed, " ) == std::string::npos ) // always log %script errors + continue; + } + + rpmmsg += line+'\n'; + + if ( str::startsWith( line, "warning:" ) ) + configwarnings.push_back(line); + } + if ( lineno >= MAXRPMMESSAGELINES ) + rpmmsg += "[truncated]\n"; + + int rpm_status = systemStatus(); + if ( postTransCollector_r && rpm_status == 0 ) { + // Before doing anything else, handle any pending %posttrans script or dump_posttrans lines. + postTransCollector_r->collectPosttransInfo( filename, runposttrans ); + } + + // evaluate result + for (std::vector::iterator it = configwarnings.begin(); + it != configwarnings.end(); ++it) + { + processConfigFiles(*it, Pathname::basename(filename), " saved as ", + // %s = filenames + _("rpm saved %s as %s, but it was impossible to determine the difference"), + // %s = filenames + _("rpm saved %s as %s.\nHere are the first 25 lines of difference:\n")); + processConfigFiles(*it, Pathname::basename(filename), " created as ", + // %s = filenames + _("rpm created %s as %s, but it was impossible to determine the difference"), + // %s = filenames + _("rpm created %s as %s.\nHere are the first 25 lines of difference:\n")); + } + + if ( rpm_status != 0 ) + { + historylog.comment( + str::form("%s install failed", Pathname::basename(filename).c_str()), + true /*timestamp*/); + std::ostringstream sstr; + sstr << "rpm output:" << endl << rpmmsg << endl; + historylog.comment(sstr.str()); + // TranslatorExplanation the colon is followed by an error message + auto excpt { RpmSubprocessException(_("RPM failed: ") + error_message ) }; + if ( not rpmmsg.empty() ) + excpt.addHistory( rpmmsg ); + ZYPP_THROW(excpt); + } + else if ( ! rpmmsg.empty() ) + { + historylog.comment( + str::form("%s installed ok", Pathname::basename(filename).c_str()), + true /*timestamp*/); + std::ostringstream sstr; + sstr << "Additional rpm output:" << endl << rpmmsg << endl; + historylog.comment(sstr.str()); + + // report additional rpm output in finish (LEGACY! Lines are immediately reported as InstallResolvableReport::contentRpmout) + // TranslatorExplanation Text is followed by a ':' and the actual output. + report->finishInfo(str::form( "%s:\n%s\n", _("Additional rpm output"), rpmmsg.c_str() )); + } +} + +/////////////////////////////////////////////////////////////////// +// +// METHOD NAME : RpmDb::removePackage +// +void RpmDb::removePackage( Package::constPtr package, RpmInstFlags flags ) +{ removePackage( std::move(package), flags, nullptr ); } + +void RpmDb::removePackage( const std::string & name_r, RpmInstFlags flags ) +{ removePackage( name_r, flags, nullptr ); } + +void RpmDb::removePackage( const Package::constPtr& package, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r ) +{ // 'rpm -e' does not like epochs + removePackage( package->name() + + "-" + package->edition().version() + + "-" + package->edition().release() + + "." + package->arch().asString(), flags, postTransCollector_r ); +} + +void RpmDb::removePackage( const std::string & name_r, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r ) +{ + callback::SendReport report; + + report->start( name_r ); + + do + try + { + doRemovePackage( name_r, flags, postTransCollector_r, report ); + report->finish(); + break; + } + catch (RpmException & excpt_r) + { + RpmRemoveReport::Action user = report->problem( excpt_r ); + + if ( user == RpmRemoveReport::ABORT ) + { + report->finish( excpt_r ); + ZYPP_RETHROW(excpt_r); + } + else if ( user == RpmRemoveReport::IGNORE ) + { + break; + } + } + while (true); +} + +void RpmDb::doRemovePackage( const std::string & name_r, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r, callback::SendReport & report ) +{ + FAILIFNOTINITIALIZED; + HistoryLog historylog; + + MIL << "RpmDb::doRemovePackage(" << name_r << "," << flags << ")" << endl; + + // backup + if ( _packagebackups ) + { + // FIXME solve this status report somehow + // report->progress( pd.init( -2, 100 ) ); // allow 1% for backup creation. + if ( ! backupPackage( name_r ) ) + { + ERR << "backup of " << name_r << " failed" << endl; + } + report->progress( 0 ); + } + else + { + report->progress( 100 ); + } + + // run rpm + RpmArgVec opts; +#if defined(WORKAROUNDDUMPPOSTTRANSBUG) + if ( postTransCollector_r && _root == "/" ) { +#else + if ( postTransCollector_r ) { +#endif + opts.push_back("--define"); // bsc#1041742: Attempt to delay %transfiletrigger(postun|in) execution iff rpm supports it. + opts.push_back("_dump_posttrans 1"); // Old rpm ignores the --define, new rpm injects 'dump_posttrans:' lines to collect and execute later. + } + opts.push_back("-e"); + opts.push_back("--allmatches"); + + if (flags & RPMINST_NOSCRIPTS) + opts.push_back("--noscripts"); + if (flags & RPMINST_NODEPS) + opts.push_back("--nodeps"); + if (flags & RPMINST_JUSTDB) + opts.push_back("--justdb"); + if (flags & RPMINST_TEST) + opts.push_back ("--test"); + if (flags & RPMINST_FORCE) + { + WAR << "IGNORE OPTION: 'rpm -e' does not support '--force'" << endl; + } + + opts.push_back("--"); + opts.push_back(name_r.c_str()); + run_rpm (opts, ExternalProgram::Stderr_To_Stdout); + + // forward additional rpm output via report; + std::string line; + unsigned lineno = 0; + callback::UserData cmdout( RemoveResolvableReport::contentRpmout ); + // Key "solvable" injected by RpmInstallPackageReceiver + cmdout.set( "line", std::cref(line) ); + cmdout.set( "lineno", lineno ); + + + // LEGACY: collect and forward additional rpm output in finish + std::string rpmmsg; + std::vector runposttrans; // bsc#1041742: If rpm supports --runposttrans it injects 'dump_posttrans:' lines we do collect + + // got no progress from command, so we fake it: + // 5 - command started + // 50 - command completed + // 100 if no error + report->progress( 5 ); + while (systemReadLine(line)) + { + if ( str::hasPrefix( line, "dump_posttrans:" ) ) { + runposttrans.push_back( line ); + continue; + } + ++lineno; + cmdout.set( "lineno", lineno ); + report->report( cmdout ); + + if ( lineno >= MAXRPMMESSAGELINES ) { + if ( line.find( " scriptlet failed, " ) == std::string::npos ) // always log %script errors + continue; + } + rpmmsg += line+'\n'; + } + if ( lineno >= MAXRPMMESSAGELINES ) + rpmmsg += "[truncated]\n"; + report->progress( 50 ); + int rpm_status = systemStatus(); + if ( postTransCollector_r && rpm_status == 0 ) { + // Before doing anything else, handle any pending %posttrans script or dump_posttrans lines. + // 'remove' does not trigger %posttrans, but it may trigger %transfiletriggers. + postTransCollector_r->collectPosttransInfo( runposttrans ); + } + + if ( rpm_status != 0 ) + { + historylog.comment( + str::form("%s remove failed", name_r.c_str()), true /*timestamp*/); + std::ostringstream sstr; + sstr << "rpm output:" << endl << rpmmsg << endl; + historylog.comment(sstr.str()); + // TranslatorExplanation the colon is followed by an error message + auto excpt { RpmSubprocessException(_("RPM failed: ") + error_message ) }; + if ( not rpmmsg.empty() ) + excpt.addHistory( rpmmsg ); + ZYPP_THROW(excpt); + } + else if ( ! rpmmsg.empty() ) + { + historylog.comment( + str::form("%s removed ok", name_r.c_str()), true /*timestamp*/); + + std::ostringstream sstr; + sstr << "Additional rpm output:" << endl << rpmmsg << endl; + historylog.comment(sstr.str()); + + // report additional rpm output in finish (LEGACY! Lines are immediately reported as RemoveResolvableReport::contentRpmout) + // TranslatorExplanation Text is followed by a ':' and the actual output. + report->finishInfo(str::form( "%s:\n%s\n", _("Additional rpm output"), rpmmsg.c_str() )); + } +} + +/////////////////////////////////////////////////////////////////// +// +// METHOD NAME : RpmDb::runposttrans +// +int RpmDb::runposttrans( const Pathname & filename_r, const std::function& output_r ) +{ + FAILIFNOTINITIALIZED; + HistoryLog historylog; + + MIL << "RpmDb::runposttrans(" << filename_r << ")" << endl; + + RpmArgVec opts; + opts.push_back("-vv"); // want vverbose output to see scriptlet execution in the log + opts.push_back("--runposttrans"); + opts.push_back(filename_r.c_str()); + run_rpm (opts, ExternalProgram::Stderr_To_Stdout); + + // Tailored to suit RpmPostTransCollector. + // It's a pity, but we need all those verbose debug lines just + // to figure out which script is currently executed. Otherwise we + // can't tell which output belongs to which script. + static const str::regex rx( "^D: (%.*): scriptlet start$" ); + str::smatch what; + std::string line; + bool silent = true; // discard everything before 1st scriptlet + while ( systemReadLine(line) ) + { + if ( not output_r ) + continue; + + if ( str::startsWith( line, "D:" ) ) { // rpm debug output + if ( str::regex_match( line, what, rx ) ) { + // forward ripoff header + output_r( "RIPOFF:"+what[1] ); + if ( silent ) + silent = false; + } + continue; + } + if ( silent ) { + continue; + } + if ( str::startsWith( line, "+ " ) ) { // shell -x debug output + continue; + } + // forward output line + output_r( line ); + } + + int rpm_status = systemStatus(); + if ( rpm_status != 0 ) { + WAR << "rpm --runposttrans returned " << rpm_status << endl; + } + return rpm_status; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::backupPackage +// METHOD TYPE : bool +// +bool RpmDb::backupPackage( const Pathname & filename ) +{ + RpmHeader::constPtr h( RpmHeader::readPackage( filename, RpmHeader::NOSIGNATURE ) ); + if ( ! h ) + return false; + + return backupPackage( h->tag_name() ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmDb::backupPackage +// METHOD TYPE : bool +// +bool RpmDb::backupPackage(const std::string& packageName) +{ + HistoryLog progresslog; + bool ret = true; + Pathname backupFilename; + Pathname filestobackupfile = _root+_backuppath+FILEFORBACKUPFILES; + + if (_backuppath.empty()) + { + INT << "_backuppath empty" << endl; + return false; + } + + FileList fileList; + + if (!queryChangedFiles(fileList, packageName)) + { + ERR << "Error while getting changed files for package " << + packageName << endl; + return false; + } + + if (fileList.size() <= 0) + { + DBG << "package " << packageName << " not changed -> no backup" << endl; + return true; + } + + if (filesystem::assert_dir(_root + _backuppath) != 0) + { + return false; + } + + { + // build up archive name + time_t currentTime = time(0); + struct tm *currentLocalTime = localtime(¤tTime); + + int date = (currentLocalTime->tm_year + 1900) * 10000 + + (currentLocalTime->tm_mon + 1) * 100 + + currentLocalTime->tm_mday; + + int num = 0; + do + { + backupFilename = _root + _backuppath + + str::form("%s-%d-%d.tar.gz",packageName.c_str(), date, num); + + } + while ( PathInfo(backupFilename).isExist() && num++ < 1000); + + PathInfo pi(filestobackupfile); + if (pi.isExist() && !pi.isFile()) + { + ERR << filestobackupfile.asString() << " already exists and is no file" << endl; + return false; + } + + std::ofstream fp ( filestobackupfile.asString().c_str(), std::ios::out|std::ios::trunc ); + + if (!fp) + { + ERR << "could not open " << filestobackupfile.asString() << endl; + return false; + } + + for (FileList::const_iterator cit = fileList.begin(); + cit != fileList.end(); ++cit) + { + std::string name = *cit; + if ( name[0] == '/' ) + { + // remove slash, file must be relative to -C parameter of tar + name = name.substr( 1 ); + } + DBG << "saving file "<< name << endl; + fp << name << endl; + } + fp.close(); + + const char* const argv[] = + { + "tar", + "-czhP", + "-C", + _root.asString().c_str(), + "--ignore-failed-read", + "-f", + backupFilename.asString().c_str(), + "-T", + filestobackupfile.asString().c_str(), + NULL + }; + + // execute tar in inst-sys (we dont know if there is a tar below _root !) + ExternalProgram tar(argv, ExternalProgram::Stderr_To_Stdout, false, -1, true); + + std::string tarmsg; + + // TODO: it is probably possible to start tar with -v and watch it adding + // files to report progress + for (std::string output = tar.receiveLine(); output.length() ;output = tar.receiveLine()) + { + tarmsg+=output; + } + + int ret = tar.close(); + + if ( ret != 0) + { + ERR << "tar failed: " << tarmsg << endl; + ret = false; + } + else + { + MIL << "tar backup ok" << endl; + progresslog.comment( + str::form(_("created backup %s"), backupFilename.asString().c_str()) + , /*timestamp*/true); + } + + filesystem::unlink(filestobackupfile); + } + + return ret; +} + +void RpmDb::setBackupPath(const Pathname& path) +{ + _backuppath = path; +} + +std::ostream & operator<<( std::ostream & str, RpmDb::CheckPackageResult obj ) +{ + switch ( obj ) + { +#define OUTS(E,S) case RpmDb::E: return str << "["<< (unsigned)obj << "-"<< S << "]"; break + // translators: possible rpm package signature check result [brief] + OUTS( CHK_OK, _("Signature is OK") ); + // translators: possible rpm package signature check result [brief] + OUTS( CHK_NOTFOUND, _("Unknown type of signature") ); + // translators: possible rpm package signature check result [brief] + OUTS( CHK_FAIL, _("Signature does not verify") ); + // translators: possible rpm package signature check result [brief] + OUTS( CHK_NOTTRUSTED, _("Signature is OK, but key is not trusted") ); + // translators: possible rpm package signature check result [brief] + OUTS( CHK_NOKEY, _("Signatures public key is not available") ); + // translators: possible rpm package signature check result [brief] + OUTS( CHK_ERROR, _("File does not exist or signature can't be checked") ); + // translators: possible rpm package signature check result [brief] + OUTS( CHK_NOSIG, _("File is unsigned") ); +#undef OUTS + } + return str << "UnknowSignatureCheckError("+str::numstring(obj)+")"; +} + +std::ostream & operator<<( std::ostream & str, const RpmDb::CheckPackageDetail & obj ) +{ + for ( const auto & el : obj ) + str << el.second << endl; + return str; +} + +} // namespace rpm +} // namespace target +} // namespace zypp diff --git a/zypp/target/rpm/RpmDb.h b/zypp/target/rpm/RpmDb.h new file mode 100644 index 0000000..587b84a --- /dev/null +++ b/zypp/target/rpm/RpmDb.h @@ -0,0 +1,512 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmDb.h + * +*/ + +// -*- C++ -*- + +#ifndef ZYPP_TARGET_RPM_RPMDB_H +#define ZYPP_TARGET_RPM_RPMDB_H + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include + +namespace zypp +{ +namespace target +{ +class RpmPostTransCollector; +namespace rpm +{ + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : RpmDb +/** + * @short Interface to the rpm program + **/ +class ZYPP_API RpmDb : public base::ReferenceCounted, private base::NonCopyable +{ +public: + + /** + * Default error class + **/ + using Error = class InstTargetError; + + /////////////////////////////////////////////////////////////////// + // + // INITALISATION + // + /////////////////////////////////////////////////////////////////// +private: + + /** + * Root directory for all operations. + **/ + Pathname _root; + + /** + * Directory that contains the rpmdb. + **/ + Pathname _dbPath; + +public: + + /** + * Constructor. There's no rpmdb access until @ref initDatabase + * was called. + **/ + RpmDb(); + + /** + * Destructor. + **/ + ~RpmDb() override; + + /** + * @return Root directory for all operations (empty if not initialized). + **/ + const Pathname & root() const + { + return _root; + } + + /** + * @return Directory that contains the rpmdb (empty if not initialized). + **/ + const Pathname & dbPath() const + { + return _dbPath; + } + + /** + * @return Whether we are initialized. + **/ + bool initialized() const + { + return( ! _root.empty() ); + } + + /** + * Prepare access to the rpm database below \a root_r. + * + * An optional argument denotes the root directory for all operations. If + * an empty Pathname is given the default (\c/) is used. + * + * Calling initDatabase a second time with different arguments will return + * an error but leave the database in its original state. + * + * If the database already exists and \c doRebuild_r is true, + * \ref rebuildDatabase is called. + * + * \throws RpmException + **/ + void initDatabase( Pathname root_r = Pathname(), bool doRebuild_r = false ); + + /** + * Block further access to the rpm database and go back to uninitialized + * state. On update: Decides what to do with any converted database + * (see @ref initDatabase). + * + * \throws RpmException + * + **/ + void closeDatabase(); + + /** + * Rebuild the rpm database (rpm --rebuilddb). + * + * \throws RpmException + * + **/ + void rebuildDatabase(); + + /** + * Import ascii armored public key in file pubkey_r. + * + * \throws RpmException + * + **/ + void importPubkey( const PublicKey & pubkey_r ); + + /** + * Remove a public key from the rpm database + * + * \throws RpmException + * + **/ + void removePubkey( const PublicKey & pubkey_r ); + + /** + * Return the long ids of all installed public keys. + **/ + std::list pubkeys() const; + + /** + * Return the edition of all installed public keys. + **/ + std::set pubkeyEditions() const; + + /////////////////////////////////////////////////////////////////// + // + // Direct RPM database retrieval via librpm. + // + /////////////////////////////////////////////////////////////////// +public: + + /** + * return complete file list for installed package name_r (in FileInfo.filename) + * if edition_r != Edition::noedition, check for exact edition + * if full==true, fill all attributes of FileInfo + **/ + std::list fileList( const std::string & name_r, const Edition & edition_r ) const; + + /** + * Return true if at least one package owns a certain file (name_r empty) + * Return true if package name_r owns file file_r (name_r nonempty). + **/ + bool hasFile( const std::string & file_r, const std::string & name_r = "" ) const; + + /** + * Return name of package owning file + * or empty string if no installed package owns file + **/ + std::string whoOwnsFile( const std::string & file_r ) const; + + /** + * Return true if at least one package provides a certain tag. + **/ + bool hasProvides( const std::string & tag_r ) const; + + /** + * Return true if at least one package requires a certain tag. + **/ + bool hasRequiredBy( const std::string & tag_r ) const; + + /** + * Return true if at least one package conflicts with a certain tag. + **/ + bool hasConflicts( const std::string & tag_r ) const; + + /** + * Return true if package is installed. + **/ + bool hasPackage( const std::string & name_r ) const; + + /** + * Return true if package is installed in a certain edition. + **/ + bool hasPackage( const std::string & name_r, const Edition & ed_r ) const; + + /** + * Get an installed packages data from rpmdb. Package is + * identified by name. Data returned via result are NULL, + * if packge is not installed (PMError is not set), or RPM database + * could not be read (PMError is set). + * + * \throws RpmException + * + * FIXME this and following comment + * + **/ + void getData( const std::string & name_r, + RpmHeader::constPtr & result_r ) const; + + /** + * Get an installed packages data from rpmdb. Package is + * identified by name and edition. Data returned via result are NULL, + * if packge is not installed (PMError is not set), or RPM database + * could not be read (PMError is set). + * + * \throws RpmException + * + **/ + void getData( const std::string & name_r, const Edition & ed_r, + RpmHeader::constPtr & result_r ) const; + + /////////////////////////////////////////////////////////////////// + // + /////////////////////////////////////////////////////////////////// +public: + /** Sync mode for \ref syncTrustedKeys */ + enum SyncTrustedKeyBits + { + SYNC_TO_KEYRING = 1<<0, //!< export rpm trusted keys into zypp trusted keyring + SYNC_FROM_KEYRING = 1<<1, //!< import zypp trusted keys into rpm database. + SYNC_BOTH = SYNC_TO_KEYRING | SYNC_FROM_KEYRING + }; + /** + * Sync trusted keys stored in rpm database and zypp trusted keyring. + */ + void syncTrustedKeys( SyncTrustedKeyBits mode_r = SYNC_BOTH ); + /** + * iterates through zypp keyring and import all non-existent keys + * into rpm keyring + */ + void importZyppKeyRingTrustedKeys(); + /** + * insert all rpm trusted keys into zypp trusted keyring + */ + void exportTrustedKeysInZyppKeyRing(); + +private: + /** + * The connection to the rpm process. + */ + ExternalProgram *process; + + using RpmArgVec = std::vector; + + /** + * Run rpm with the specified arguments and handle stderr. + * @param n_opts The number of arguments + * @param options Array of the arguments, @ref n_opts elements + * @param stderr_disp How to handle stderr, merged with stdout by default + * + * \throws RpmException + * + **/ + void run_rpm( const RpmArgVec& options, + ExternalProgram::Stderr_Disposition stderr_disp = + ExternalProgram::Stderr_To_Stdout); + + + /** + * Read a line from the general rpm query + */ + bool systemReadLine(std::string &line); + + /** + * Return the exit status of the general rpm process, + * closing the connection if not already done. + */ + int systemStatus(); + + /** + * Forcably kill the system process + */ + void systemKill(); + + /** + * The exit code of the rpm process, or -1 if not yet known. + */ + int exit_code; + + /** + * Error message from running rpm as external program. + * Use only if something fail. + */ + std::string error_message; + + /** /var/adm/backup */ + Pathname _backuppath; + + /** create package backups? */ + bool _packagebackups; + + /** + * handle rpm messages like "/etc/testrc saved as /etc/testrc.rpmorig" + * + * @param line rpm output starting with warning: + * @param name name of package, appears in subject line + * @param typemsg " saved as " or " created as " + * @param difffailmsg what to put into mail if diff failed, must contain two %s for the two files + * @param diffgenmsg what to put into mail if diff succeeded, must contain two %s for the two files + * */ + void processConfigFiles(const std::string& line, + const std::string& name, + const char* typemsg, + const char* difffailmsg, + const char* diffgenmsg); + + +public: + + using FileList = std::set; + + /** + * checkPackage result + * @see checkPackage + * */ + enum CheckPackageResult + { + CHK_OK = 0, /*!< Signature is OK. */ + CHK_NOTFOUND = 1, /*!< Signature is unknown type. */ + CHK_FAIL = 2, /*!< Signature does not verify. */ + CHK_NOTTRUSTED = 3, /*!< Signature is OK, but key is not trusted. */ + CHK_NOKEY = 4, /*!< Public key is unavailable. */ + CHK_ERROR = 5, /*!< File does not exist or can't be opened. */ + CHK_NOSIG = 6, /*!< File has no gpg signature (only digests). */ + }; + + /** Detailed rpm signature check log messages + * A single multiline message if \ref CHK_OK. Otherwise, each message line + * together with its \ref CheckPackageResult. + */ + struct CheckPackageDetail : std::vector> + {}; + + /** + * Check signature of rpm file on disk (legacy version returning CHK_OK if file is unsigned, like 'rpm -K') + * + * @param path_r which file to check + * @param detail_r Return detailed rpm log messages + * + * @return CheckPackageResult (CHK_OK if file is unsigned) + * + * \see also \ref checkPackageSignature + */ + CheckPackageResult checkPackage( const Pathname & path_r, CheckPackageDetail & detail_r ); + /** \overload Ignoring the \a details_r */ + CheckPackageResult checkPackage( const Pathname & path_r ); + + /** + * Check signature of rpm file on disk (strict check returning CHK_NOSIG if file is unsigned). + * + * @param path_r which file to check + * @param detail_r Return detailed rpm log messages + * + * @return CheckPackageResult (CHK_NOSIG if file is unsigned) + * + * \see also \ref checkPackage + */ + CheckPackageResult checkPackageSignature( const Pathname & path_r, CheckPackageDetail & detail_r ); + + /** install rpm package + * + * @param filename file to install + * @param flags which rpm options to use + * + * @return success + * + * \throws RpmException + * + * */ + void installPackage ( const Pathname & filename, RpmInstFlags flags = RPMINST_NONE ); + /** \overload For delayed %posttrans %transfiletrigger(postun|in) execution if driven by Target::commit. */ + void installPackage( const Pathname & filename, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r ); + + /** remove rpm package + * + * @param name_r Name of the rpm package to remove. + * @param iflags which rpm options to use + * + * @return success + * + * \throws RpmException + * + * */ + void removePackage( const std::string & name_r, RpmInstFlags flags = RPMINST_NONE ); + void removePackage( Package::constPtr package, RpmInstFlags flags = RPMINST_NONE ); + /** \overload For delayed %posttrans %transfiletrigger(postun|in) execution if driven by Target::commit. */ + void removePackage( const std::string & name_r, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r ); + void removePackage( const Package::constPtr& package, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r ); + + /** Run collected %posttrans and %transfiletrigger(postun|in) if `rpm --runposttrans` is supported. + * Output-function receives a "RIPOFF:%scriptident(packageident)" line for every script + * that is executed followed by lines the script outputs to stout/stderr. + */ + int runposttrans( const Pathname & filename_r, const std::function& output_r ); + + /** + * get backup dir for rpm config files + * + * */ + Pathname getBackupPath (void) + { + return _backuppath; + } + + /** + * create tar.gz of all changed files in a Package + * + * @param packageName name of the Package to backup + * + * @see setBackupPath + * */ + bool backupPackage(const std::string& packageName); + + /** + * queries file for name and then calls above backupPackage + * function. For convenience. + * + * @param filename rpm file that is about to be installed + * */ + bool backupPackage(const Pathname& filename); + + /** + * set path where package backups are stored + * + * @see backupPackage + * */ + void setBackupPath(const Pathname& path); + + /** + * whether to create package backups during install or + * removal + * + * @param yes true or false + * */ + void createPackageBackups(bool yes) + { + _packagebackups = yes; + } + + /** + * determine which files of an installed package have been + * modified. + * + * @param fileList (output) where to store modified files + * @param packageName name of package to query + * + * @return false if package couln't be queried for some + * reason + * */ + bool queryChangedFiles(FileList & fileList, const std::string& packageName); + +public: + + /** + * Dump debug info. + **/ + std::ostream & dumpOn( std::ostream & str ) const override; + +protected: + void doRemovePackage( const std::string & name_r, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r, callback::SendReport & report ); + void doInstallPackage( const Pathname & filename, RpmInstFlags flags, RpmPostTransCollector* postTransCollector_r, callback::SendReport & report ); + void doRebuildDatabase(callback::SendReport & report); +}; + +/** \relates RpmDb::CheckPackageResult Stream output */ +std::ostream & operator<<( std::ostream & str, RpmDb::CheckPackageResult obj ) ZYPP_API; + +/** \relates RpmDb::checkPackageDetail Stream output */ +std::ostream & operator<<( std::ostream & str, const RpmDb::CheckPackageDetail & obj ) ZYPP_API; + +} // namespace rpm +} // namespace target +} // namespace zypp + +#endif // ZYPP_TARGET_RPM_RPMDB_H diff --git a/zypp/target/rpm/RpmException.cc b/zypp/target/rpm/RpmException.cc new file mode 100644 index 0000000..7668d72 --- /dev/null +++ b/zypp/target/rpm/RpmException.cc @@ -0,0 +1,87 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmException.cc + * +*/ + +#include +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +namespace target +{ +///////////////////////////////////////////////////////////////// +namespace rpm +{ +///////////////////////////////////////////////////////////////// + +std::ostream & RpmInvalidRootException::dumpOn( std::ostream & str ) const +{ + return str << "Illegal root " << _root + << " or dbPath " << _dbpath; +} + +std::ostream & RpmAccessBlockedException::dumpOn( std::ostream & str ) const +{ + return str << "Access is blocked: Root: " << _root + << " dbPath: " << _dbpath; +} + +std::ostream & RpmSubprocessException::dumpOn( std::ostream & str ) const +{ + return str << "Subprocess failed. Error: " << _errmsg; +} + +std::ostream & RpmInitException::dumpOn( std::ostream & str) const +{ + return str << "Failed to initialize database: Root: " << _root + << " dbPath: " << _dbpath; +} + +std::ostream & RpmDbOpenException::dumpOn( std::ostream & str) const +{ + return str << "Failed to open database: Root: " << _root + << " dbPath: " << _dbpath; +} + +std::ostream & RpmDbAlreadyOpenException::dumpOn( std::ostream & str) const +{ + return str << "Can't switch to " << _new_root << " " << _new_dbpath + << " while accessing " << _old_root << " " << _old_dbpath; +} + +std::ostream & RpmDbNotOpenException::dumpOn( std::ostream & str) const +{ + return str << "RPM database not open"; +} + +std::ostream & RpmDbConvertException::dumpOn( std::ostream & str) const +{ + return str << "RPM database conversion failed"; +} + +std::ostream & RpmNullDatabaseException::dumpOn( std::ostream & str) const +{ + return str << "NULL rpmV4 database passed as argument!"; +} + +std::ostream &RpmTransactionFailedException::dumpOn(std::ostream &str) const +{ + return str << _errmsg; +} + +///////////////////////////////////////////////////////////////// +} // namespace rpm +} // namespace target +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/target/rpm/RpmException.h b/zypp/target/rpm/RpmException.h new file mode 100644 index 0000000..58615d1 --- /dev/null +++ b/zypp/target/rpm/RpmException.h @@ -0,0 +1,265 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmException.h + * +*/ +#ifndef ZYPP_TARGET_RPM_RPMEXCEPTION_H +#define ZYPP_TARGET_RPM_RPMEXCEPTION_H + +#include + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// +namespace target +{ +/////////////////////////////////////////////////////////////// +namespace rpm +{ +/////////////////////////////////////////////////////////////// +// +// CLASS NAME : RpmException +/** Just inherits Exception to separate media exceptions + * + **/ +class ZYPP_API RpmException : public Exception +{ +public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + RpmException() + : Exception( "Rpm Exception" ) + {} + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + RpmException( const std::string & msg_r ) + : Exception( msg_r ) + {} + /** Dtor. */ + ~RpmException() throw() override + {}; +}; + +class ZYPP_API GlobalRpmInitException : public RpmException +{ +public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + GlobalRpmInitException() + : RpmException("Global RPM initialization failed") + {} + /** Dtor. */ + ~GlobalRpmInitException() throw() override + {}; +private: +}; + +class ZYPP_API RpmInvalidRootException : public RpmException +{ +public: + /** Ctor taking message. + * Use \ref ZYPP_THROW to throw exceptions. + */ + RpmInvalidRootException( const Pathname & root_r, + const Pathname & dbpath_r ) + : RpmException() + , _root(root_r.asString()) + , _dbpath(dbpath_r.asString()) + {} + /** Dtor. */ + ~RpmInvalidRootException() throw() override + {}; + std::string root() const + { + return _root; + } + std::string dbpath() const + { + return _dbpath; + } +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: + std::string _root; + std::string _dbpath; +}; + +class ZYPP_API RpmAccessBlockedException : public RpmException +{ +public: + RpmAccessBlockedException( const Pathname & root_r, + const Pathname & dbpath_r ) + : RpmException() + , _root(root_r.asString()) + , _dbpath(dbpath_r.asString()) + {} + ~RpmAccessBlockedException() throw() override + {}; + std::string root() const + { + return _root; + } + std::string dbpath() const + { + return _dbpath; + } +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: + std::string _root; + std::string _dbpath; +}; + +class ZYPP_API RpmSubprocessException : public RpmException +{ +public: + RpmSubprocessException(std::string errmsg_r) + : RpmException() + , _errmsg(std::move(errmsg_r)) + {} + ~RpmSubprocessException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: + std::string _errmsg; +}; + +class ZYPP_API RpmInitException : public RpmException +{ +public: + RpmInitException(const Pathname & root_r, + const Pathname & dbpath_r) + : RpmException() + , _root(root_r.asString()) + , _dbpath(dbpath_r.asString()) + {} + ~RpmInitException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: + std::string _root; + std::string _dbpath; +}; + +class ZYPP_API RpmDbOpenException : public RpmException +{ +public: + RpmDbOpenException(const Pathname & root_r, + const Pathname & dbpath_r) + : RpmException() + , _root(root_r.asString()) + , _dbpath(dbpath_r.asString()) + {} + ~RpmDbOpenException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: + std::string _root; + std::string _dbpath; +}; + +class ZYPP_API RpmDbAlreadyOpenException : public RpmException +{ +public: + RpmDbAlreadyOpenException(const Pathname & old_root_r, + const Pathname & old_dbpath_r, + const Pathname & new_root_r, + const Pathname & new_dbpath_r) + : RpmException() + , _old_root(old_root_r.asString()) + , _old_dbpath(old_dbpath_r.asString()) + , _new_root(new_root_r.asString()) + , _new_dbpath(new_dbpath_r.asString()) + {} + ~RpmDbAlreadyOpenException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: + std::string _old_root; + std::string _old_dbpath; + std::string _new_root; + std::string _new_dbpath; +}; + +class ZYPP_API RpmDbNotOpenException : public RpmException +{ +public: + RpmDbNotOpenException() + : RpmException() + {} + ~RpmDbNotOpenException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: +}; + +class ZYPP_API RpmDbConvertException : public RpmException +{ +public: + RpmDbConvertException() + : RpmException() + {} + ~RpmDbConvertException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: +}; + +class ZYPP_API RpmNullDatabaseException : public RpmException +{ +public: + RpmNullDatabaseException() + : RpmException() + {} + ~RpmNullDatabaseException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: +}; + +class ZYPP_API RpmTransactionFailedException : public RpmException +{ +public: + RpmTransactionFailedException(std::string errmsg_r) + : RpmException() + , _errmsg(std::move(errmsg_r)) + {} + ~RpmTransactionFailedException() throw() override + {}; +protected: + std::ostream & dumpOn( std::ostream & str ) const override; +private: + std::string _errmsg; +}; + + + +///////////////////////////////////////////////////////////////// +} // namespace rpm +} // namespace target +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_RPM_RPMEXCEPTION_H diff --git a/zypp/target/rpm/RpmFlags.h b/zypp/target/rpm/RpmFlags.h new file mode 100644 index 0000000..cf1ca9e --- /dev/null +++ b/zypp/target/rpm/RpmFlags.h @@ -0,0 +1,68 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmFlags.h + * +*/ +#ifndef ZYPP_TARGET_RPM_RPMFLAGS_H +#define ZYPP_TARGET_RPM_RPMFLAGS_H + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace target + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace rpm + { ///////////////////////////////////////////////////////////////// + + /** + * Bits representing rpm installation options. + * + * Use \ref RpmInstFlags as a type-safe way of + * storing OR-combinations. + * + * @see RpmDb::installPackage(), RpmDb::removePackage(), + */ + enum RpmInstFlag + { + RPMINST_NONE = 0x0000, + RPMINST_EXCLUDEDOCS = 0x0001, + RPMINST_NOSCRIPTS = 0x0002, + RPMINST_FORCE = 0x0004, + RPMINST_NODEPS = 0x0008, + RPMINST_IGNORESIZE = 0x0010, + RPMINST_JUSTDB = 0x0020, + RPMINST_NODIGEST = 0x0040, + RPMINST_NOSIGNATURE = 0x0080, + RPMINST_NOUPGRADE = 0x0100, + RPMINST_TEST = 0x0200, + RPMINST_NOPOSTTRANS = 0x0400, + RPMINST_ALLOWDOWNGRADE = 0x0800, + RPMINST_REPLACEFILES = 0x1000, + RPMINST_ALLOWUNTRUSTED = 0x2000, + }; + + /** \relates RpmInstFlag Type-safe way of storing OR-combinations. */ + ZYPP_DECLARE_FLAGS_AND_OPERATORS( RpmInstFlags, RpmInstFlag ); + + ///////////////////////////////////////////////////////////////// + } // namespace rpm + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace target + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_TARGET_RPM_RPMFLAGS_H diff --git a/zypp/target/rpm/RpmHeader.cc b/zypp/target/rpm/RpmHeader.cc new file mode 100644 index 0000000..d35c92a --- /dev/null +++ b/zypp/target/rpm/RpmHeader.cc @@ -0,0 +1,1054 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmHeader.cc + * +*/ +#include "librpm.h" + +#include + +#include + +//////////////////////////////////////////////////////////////////// +// unameToUid and gnameToGid are shamelessly stolen from rpm-4.4. +// (rpmio/ugid.c) Those functions were dropped in RPM_4_7 +extern "C" +{ +#include +#include +} +/* unameToUid(), uidTouname() and the group variants are really poorly + implemented. They really ought to use hash tables. I just made the + guess that most files would be owned by root or the same person/group + who owned the last file. Those two values are cached, everything else + is looked up via getpw() and getgr() functions. If this performs + too poorly I'll have to implement it properly :-( */ + +int unameToUid(const char * thisUname, uid_t * uid) +{ +/*@only@*/ static char * lastUname = NULL; + static size_t lastUnameLen = 0; + static size_t lastUnameAlloced; + static uid_t lastUid; + struct passwd * pwent = nullptr; + size_t thisUnameLen = 0; + + if (!thisUname) { + lastUnameLen = 0; + return -1; + } else if (strcmp(thisUname, "root") == 0) { +/*@-boundswrite@*/ + *uid = 0; +/*@=boundswrite@*/ + return 0; + } + + thisUnameLen = strlen(thisUname); + if (lastUname == NULL || thisUnameLen != lastUnameLen || + strcmp(thisUname, lastUname) != 0) + { + if (lastUnameAlloced < thisUnameLen + 1) { + lastUnameAlloced = thisUnameLen + 10; + lastUname = (char *)realloc(lastUname, lastUnameAlloced); /* XXX memory leak */ + } +/*@-boundswrite@*/ + strcpy(lastUname, thisUname); +/*@=boundswrite@*/ + + pwent = getpwnam(thisUname); + if (pwent == NULL) { + /*@-internalglobs@*/ /* FIX: shrug */ + endpwent(); + /*@=internalglobs@*/ + pwent = getpwnam(thisUname); + if (pwent == NULL) return -1; + } + + lastUid = pwent->pw_uid; + } + +/*@-boundswrite@*/ + *uid = lastUid; +/*@=boundswrite@*/ + + return 0; +} + +int gnameToGid(const char * thisGname, gid_t * gid) +{ +/*@only@*/ static char * lastGname = NULL; + static size_t lastGnameLen = 0; + static size_t lastGnameAlloced; + static gid_t lastGid; + size_t thisGnameLen = 0; + struct group * grent = nullptr; + + if (thisGname == NULL) { + lastGnameLen = 0; + return -1; + } else if (strcmp(thisGname, "root") == 0) { +/*@-boundswrite@*/ + *gid = 0; +/*@=boundswrite@*/ + return 0; + } + + thisGnameLen = strlen(thisGname); + if (lastGname == NULL || thisGnameLen != lastGnameLen || + strcmp(thisGname, lastGname) != 0) + { + if (lastGnameAlloced < thisGnameLen + 1) { + lastGnameAlloced = thisGnameLen + 10; + lastGname = (char *)realloc(lastGname, lastGnameAlloced); /* XXX memory leak */ + } +/*@-boundswrite@*/ + strcpy(lastGname, thisGname); +/*@=boundswrite@*/ + + grent = getgrnam(thisGname); + if (grent == NULL) { + /*@-internalglobs@*/ /* FIX: shrug */ + endgrent(); + /*@=internalglobs@*/ + grent = getgrnam(thisGname); + if (grent == NULL) { + /* XXX The filesystem package needs group/lock w/o getgrnam. */ + if (strcmp(thisGname, "lock") == 0) { +/*@-boundswrite@*/ + *gid = lastGid = 54; +/*@=boundswrite@*/ + return 0; + } else + if (strcmp(thisGname, "mail") == 0) { +/*@-boundswrite@*/ + *gid = lastGid = 12; +/*@=boundswrite@*/ + return 0; + } else + return -1; + } + } + lastGid = grent->gr_gid; + } + +/*@-boundswrite@*/ + *gid = lastGid; +/*@=boundswrite@*/ + + return 0; +} +//////////////////////////////////////////////////////////////////// + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +using std::endl; + +namespace zypp +{ +namespace target +{ +namespace rpm +{ + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::RpmHeader +// METHOD TYPE : Constructor +// +// DESCRIPTION : +// +RpmHeader::RpmHeader( Header h_r ) + : BinHeader( h_r ) +{} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::RpmHeader +// METHOD TYPE : Constructor +// +RpmHeader::RpmHeader( BinHeader::Ptr & rhs ) + : BinHeader( rhs ) +{} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::~RpmHeader +// METHOD TYPE : Destructor +// +// DESCRIPTION : +// +RpmHeader::~RpmHeader() +{} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::readPackage +// METHOD TYPE : constRpmHeaderPtr +// +RpmHeader::constPtr RpmHeader::readPackage( const Pathname & path_r, + VERIFICATION verification_r ) +{ + + librpmDb::globalInit(); + zypp::AutoDispose ts ( ::rpmtsCreate(), ::rpmtsFree ); + unsigned vsflag = RPMVSF_DEFAULT; + if ( verification_r & NODIGEST ) + vsflag |= _RPMVSF_NODIGESTS; + if ( verification_r & NOSIGNATURE ) + vsflag |= _RPMVSF_NOSIGNATURES; + ::rpmtsSetVSFlags( ts, rpmVSFlags(vsflag) ); + + return readPackage( ts, path_r ).first; +} + +std::pair RpmHeader::readPackage( rpmts ts_r, const zypp::filesystem::Pathname &path_r ) +{ + PathInfo file( path_r ); + if ( ! file.isFile() ) + { + ERR << "Not a file: " << file << endl; + return std::make_pair( RpmHeader::Ptr(), -1 ); + } + + FD_t fd = ::Fopen( file.asString().c_str(), "r.ufdio" ); + if ( fd == 0 || ::Ferror(fd) ) + { + ERR << "Can't open file for reading: " << file << " (" << ::Fstrerror(fd) << ")" << endl; + if ( fd ) + ::Fclose( fd ); + return std::make_pair( RpmHeader::Ptr(), -1 ); + } + + Header nh = 0; + int res = ::rpmReadPackageFile( ts_r, fd, path_r.asString().c_str(), &nh ); + ::Fclose( fd ); + + if ( ! nh ) + { + WAR << "Error reading header from " << path_r << " error(" << res << ")" << endl; + return std::make_pair( RpmHeader::Ptr(), res ); + } + + RpmHeader::Ptr h( new RpmHeader( nh ) ); + headerFree( nh ); // clear the reference set in ReadPackageFile + + MIL << h << " from " << path_r << endl; + return std::make_pair( h, res ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::dumpOn +// METHOD TYPE : std::ostream & +// +// DESCRIPTION : +// +std::ostream & RpmHeader::dumpOn( std::ostream & str ) const +{ + BinHeader::dumpOn( str ) << '{' << tag_name() << "-"; + if ( tag_epoch() != 0 ) + str << tag_epoch() << ":"; + str << tag_version() + << (tag_release().empty()?"":(std::string("-")+tag_release())) + << ( isSrc() ? ".src}" : "}"); + return str; +} + + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::isSrc +// METHOD TYPE : bool +// +bool RpmHeader::isSrc() const +{ + return has_tag( RPMTAG_SOURCEPACKAGE ); +} + +bool RpmHeader::isNosrc() const +{ + return has_tag( RPMTAG_SOURCEPACKAGE ) && ( has_tag( RPMTAG_NOSOURCE ) || has_tag( RPMTAG_NOPATCH ) ); +} + +std::string RpmHeader::ident() const +{ + static str::Format fmt { "%1%-%2%-%3%.%4%" }; + std::string ret; + if ( not empty() ) + ret = fmt % tag_name() % tag_version() % tag_release() % tag_arch(); + return ret; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_name +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_name() const +{ + return string_val( RPMTAG_NAME ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_epoch +// METHOD TYPE : Edition::epoch_t +// +// DESCRIPTION : +// +Edition::epoch_t RpmHeader::tag_epoch() const +{ + return int_val ( RPMTAG_EPOCH ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_version +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_version() const +{ + return string_val ( RPMTAG_VERSION ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_release +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_release() const +{ + return string_val( RPMTAG_RELEASE ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_edition +// METHOD TYPE : Edition +// +// DESCRIPTION : +// +Edition RpmHeader::tag_edition () const +{ + return Edition( tag_version(), tag_release(), tag_epoch() ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_arch +// METHOD TYPE : Arch +// +// DESCRIPTION : +// +Arch RpmHeader::tag_arch() const +{ + return Arch( string_val( RPMTAG_ARCH ) ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_installtime +// METHOD TYPE : Date +// +// DESCRIPTION : +// +Date RpmHeader::tag_installtime() const +{ + return int_val( RPMTAG_INSTALLTIME ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_buildtime +// METHOD TYPE : Date +// +// DESCRIPTION : +// +Date RpmHeader::tag_buildtime() const +{ + return int_val( RPMTAG_BUILDTIME ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::PkgRelList_val +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::PkgRelList_val( tag tag_r, bool pre, std::set * freq_r ) const + { + CapabilitySet ret; + + rpmTag kindFlags = rpmTag(0); + rpmTag kindVersion = rpmTag(0); + + switch ( tag_r ) + { + case RPMTAG_REQUIRENAME: + kindFlags = RPMTAG_REQUIREFLAGS; + kindVersion = RPMTAG_REQUIREVERSION; + break; + case RPMTAG_PROVIDENAME: + kindFlags = RPMTAG_PROVIDEFLAGS; + kindVersion = RPMTAG_PROVIDEVERSION; + break; + case RPMTAG_OBSOLETENAME: + kindFlags = RPMTAG_OBSOLETEFLAGS; + kindVersion = RPMTAG_OBSOLETEVERSION; + break; + case RPMTAG_CONFLICTNAME: + kindFlags = RPMTAG_CONFLICTFLAGS; + kindVersion = RPMTAG_CONFLICTVERSION; + break; +#ifdef RPMTAG_OLDSUGGESTS + case RPMTAG_OLDENHANCESNAME: + kindFlags = RPMTAG_OLDENHANCESFLAGS; + kindVersion = RPMTAG_OLDENHANCESVERSION; + break; + case RPMTAG_OLDSUGGESTSNAME: + kindFlags = RPMTAG_OLDSUGGESTSFLAGS; + kindVersion = RPMTAG_OLDSUGGESTSVERSION; + break; + case RPMTAG_RECOMMENDNAME: + kindFlags = RPMTAG_RECOMMENDFLAGS; + kindVersion = RPMTAG_RECOMMENDVERSION; + break; + case RPMTAG_SUPPLEMENTNAME: + kindFlags = RPMTAG_SUPPLEMENTFLAGS; + kindVersion = RPMTAG_SUPPLEMENTVERSION; + break; + case RPMTAG_SUGGESTNAME: + kindFlags = RPMTAG_SUGGESTFLAGS; + kindVersion = RPMTAG_SUGGESTVERSION; + break; + case RPMTAG_ENHANCENAME: + kindFlags = RPMTAG_ENHANCEFLAGS; + kindVersion = RPMTAG_ENHANCEVERSION; + break; +#else + case RPMTAG_ENHANCESNAME: + kindFlags = RPMTAG_ENHANCESFLAGS; + kindVersion = RPMTAG_ENHANCESVERSION; + break; + case RPMTAG_SUGGESTSNAME: + kindFlags = RPMTAG_SUGGESTSFLAGS; + kindVersion = RPMTAG_SUGGESTSVERSION; + break; +#endif + default: + INT << "Illegal RPMTAG_dependencyNAME " << tag_r << endl; + return ret; + break; + } + + stringList names; + unsigned count = string_list( tag_r, names ); + if ( !count ) + return ret; + + intList flags; + int_list( kindFlags, flags ); + + stringList versions; + string_list( kindVersion, versions ); + + for ( unsigned i = 0; i < count; ++i ) + { + + std::string n( names[i] ); + + Rel op = Rel::ANY; + int32_t f = flags[i]; + std::string v = versions[i]; + + if ( n[0] == '/' ) + { + if ( freq_r ) + { + freq_r->insert( n ); + } + } + else + { + if ( v.size() ) + { + switch ( f & RPMSENSE_SENSEMASK ) + { + case RPMSENSE_LESS: + op = Rel::LT; + break; + case RPMSENSE_LESS|RPMSENSE_EQUAL: + op = Rel::LE; + break; + case RPMSENSE_GREATER: + op = Rel::GT; + break; + case RPMSENSE_GREATER|RPMSENSE_EQUAL: + op = Rel::GE; + break; + case RPMSENSE_EQUAL: + op = Rel::EQ; + break; + } + } + } + if ((pre && (f & RPMSENSE_PREREQ)) + || ((! pre) && !(f & RPMSENSE_PREREQ))) + { + try + { + ret.insert( Capability( n, op, Edition(v) ) ); + } + catch (Exception & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + WAR << "Invalid capability: " << n << " " << op << " " + << v << endl; + } + } + } + + return ret; + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_provides +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_provides( std::set * freq_r ) const + { + return PkgRelList_val( RPMTAG_PROVIDENAME, false, freq_r ); + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_requires +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_requires( std::set * freq_r ) const + { + return PkgRelList_val( RPMTAG_REQUIRENAME, false, freq_r ); + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_requires +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_prerequires( std::set * freq_r ) const + { + return PkgRelList_val( RPMTAG_REQUIRENAME, true, freq_r ); + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_conflicts +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_conflicts( std::set * freq_r ) const + { + return PkgRelList_val( RPMTAG_CONFLICTNAME, false, freq_r ); + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_obsoletes +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_obsoletes( std::set * freq_r ) const + { + return PkgRelList_val( RPMTAG_OBSOLETENAME, false, freq_r ); + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_enhances +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_enhances( std::set * freq_r ) const + { +#ifdef RPMTAG_OLDSUGGESTS + return PkgRelList_val( RPMTAG_ENHANCENAME, false, freq_r ); +#else + return PkgRelList_val( RPMTAG_ENHANCESNAME, false, freq_r ); +#endif + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_suggests +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_suggests( std::set * freq_r ) const + { +#ifdef RPMTAG_OLDSUGGESTS + return PkgRelList_val( RPMTAG_SUGGESTNAME, false, freq_r ); +#else + return PkgRelList_val( RPMTAG_SUGGESTSNAME, false, freq_r ); +#endif + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_supplements +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_supplements( std::set * freq_r ) const + { +#ifdef RPMTAG_OLDSUGGESTS + return PkgRelList_val( RPMTAG_SUPPLEMENTNAME, false, freq_r ); +#else + return CapabilitySet(); +#endif + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_recommends +// METHOD TYPE : CapabilitySet +// +// DESCRIPTION : +// +CapabilitySet RpmHeader::tag_recommends( std::set * freq_r ) const + { +#ifdef RPMTAG_OLDSUGGESTS + return PkgRelList_val( RPMTAG_RECOMMENDNAME, false, freq_r ); +#else + return CapabilitySet(); +#endif + } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_size +// METHOD TYPE : ByteCount +// +// DESCRIPTION : +// +ByteCount RpmHeader::tag_size() const +{ + return int_val( RPMTAG_SIZE ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_archivesize +// METHOD TYPE : ByteCount +// +// DESCRIPTION : +// +ByteCount RpmHeader::tag_archivesize() const +{ + return int_val( RPMTAG_ARCHIVESIZE ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_summary +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_summary() const +{ + return string_val( RPMTAG_SUMMARY ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_description +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_description() const +{ + return string_val( RPMTAG_DESCRIPTION ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_group +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_group() const +{ + return string_val( RPMTAG_GROUP ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_vendor +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_vendor() const +{ + return string_val( RPMTAG_VENDOR ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_distribution +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_distribution() const +{ + return string_val( RPMTAG_DISTRIBUTION ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_license +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_license() const +{ + return string_val( RPMTAG_LICENSE ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_buildhost +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_buildhost() const +{ + return string_val( RPMTAG_BUILDHOST ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_packager +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_packager() const +{ + return string_val( RPMTAG_PACKAGER ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_url +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_url() const +{ + return string_val( RPMTAG_URL ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_os +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_os() const +{ + return string_val( RPMTAG_OS ); + +} + +std::string RpmHeader::tag_prein() const +{ return string_val( RPMTAG_PREIN ); } + +std::string RpmHeader::tag_preinprog() const +{ return string_val( RPMTAG_PREINPROG ); } + +std::string RpmHeader::tag_postin() const +{ return string_val( RPMTAG_POSTIN ); } + +std::string RpmHeader::tag_postinprog() const +{ return string_val( RPMTAG_POSTINPROG ); } + +std::string RpmHeader::tag_preun() const +{ return string_val( RPMTAG_PREUN ); } + +std::string RpmHeader::tag_preunprog() const +{ return string_val( RPMTAG_PREUNPROG ); } + +std::string RpmHeader::tag_postun() const +{ return string_val( RPMTAG_POSTUN ); } + +std::string RpmHeader::tag_postunprog() const +{ return string_val( RPMTAG_POSTUNPROG ); } + +std::string RpmHeader::tag_pretrans() const +{ return string_val( RPMTAG_PRETRANS ); } + +std::string RpmHeader::tag_pretransprog() const +{ return string_val( RPMTAG_PRETRANSPROG ); } + +std::string RpmHeader::tag_posttrans() const +{ return string_val( RPMTAG_POSTTRANS ); } + +std::string RpmHeader::tag_posttransprog() const +{ return string_val( RPMTAG_POSTTRANSPROG ); } + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_sourcerpm +// METHOD TYPE : std::string +// +// DESCRIPTION : +// +std::string RpmHeader::tag_sourcerpm() const +{ + return string_val( RPMTAG_SOURCERPM ); +} + +std::string RpmHeader::signatureKeyID() const +{ + std::string sigInfo = format("%|DSAHEADER?{%{DSAHEADER:pgpsig}}:{%|RSAHEADER?{%{RSAHEADER:pgpsig}}:{%|SIGGPG?{%{SIGGPG:pgpsig}}:{%|SIGPGP?{%{SIGPGP:pgpsig}}:{(none)}|}|}|}|"); + + //no signature, return empty string + if ( sigInfo == "(none)" ) + return std::string(); + + std::vector words; + str::split( sigInfo, std::back_inserter(words), ","); + if ( words.size() < 3) + return std::string(); + + const std::string &keyId = words[2]; + if ( !str::startsWith(keyId, " Key ID ")) + return std::string(); + + return str::toUpper( words[2].substr(8) ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_filenames +// METHOD TYPE : std::list +// +// DESCRIPTION : +// +std::list RpmHeader::tag_filenames() const +{ + std::list ret; + + stringList basenames; + if ( string_list( RPMTAG_BASENAMES, basenames ) ) + { + stringList dirnames; + string_list( RPMTAG_DIRNAMES, dirnames ); + intList dirindexes; + int_list( RPMTAG_DIRINDEXES, dirindexes ); + for ( unsigned i = 0; i < basenames.size(); ++ i ) + { + ret.push_back( dirnames[dirindexes[i]] + basenames[i] ); + } + } + + return ret; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_fileinfos +// METHOD TYPE : std::list +// +// DESCRIPTION : +// +std::list RpmHeader::tag_fileinfos() const +{ + std::list ret; + + stringList basenames; + if ( string_list( RPMTAG_BASENAMES, basenames ) ) + { + stringList dirnames; + string_list( RPMTAG_DIRNAMES, dirnames ); + intList dirindexes; + int_list( RPMTAG_DIRINDEXES, dirindexes ); + intList filesizes; + int_list( RPMTAG_FILESIZES, filesizes ); + stringList md5sums; + string_list( RPMTAG_FILEMD5S, md5sums ); + stringList usernames; + string_list( RPMTAG_FILEUSERNAME, usernames ); + stringList groupnames; + string_list( RPMTAG_FILEGROUPNAME, groupnames ); + intList uids; + int_list( RPMTAG_FILEUIDS, uids ); + intList gids; + int_list( RPMTAG_FILEGIDS, gids ); + intList filemodes; + int_list( RPMTAG_FILEMODES, filemodes ); + intList filemtimes; + int_list( RPMTAG_FILEMTIMES, filemtimes ); + intList fileflags; + int_list( RPMTAG_FILEFLAGS, fileflags ); + stringList filelinks; + string_list( RPMTAG_FILELINKTOS, filelinks ); + + for ( unsigned i = 0; i < basenames.size(); ++ i ) + { + uid_t uid = 0; + if (uids.empty()) + { + uid = unameToUid( usernames[i].c_str(), &uid ); + } + else + { + uid =uids[i]; + } + + gid_t gid = 0; + if (gids.empty()) + { + gid = gnameToGid( groupnames[i].c_str(), &gid ); + } + else + { + gid = gids[i]; + } + + FileInfo info = { + dirnames[dirindexes[i]] + basenames[i], + filesizes[i], + md5sums[i], + uid, + gid, + mode_t(filemodes[i]), + filemtimes[i], + bool(fileflags[i] & RPMFILE_GHOST), + filelinks[i] + }; + + ret.push_back( info ); + } + } + + return ret; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : RpmHeader::tag_changelog +// METHOD TYPE : Changelog +// +// DESCRIPTION : +// +Changelog RpmHeader::tag_changelog() const +{ + Changelog ret; + + intList times; + if ( int_list( RPMTAG_CHANGELOGTIME, times ) ) + { + stringList names; + string_list( RPMTAG_CHANGELOGNAME, names ); + stringList texts; + string_list( RPMTAG_CHANGELOGTEXT, texts ); + for ( unsigned i = 0; i < times.size(); ++ i ) + { + ret.push_back( ChangelogEntry( times[i], names[i], texts[i] ) ); + } + } + + return ret; +} + +} // namespace rpm +} // namespace target +} // namespace zypp diff --git a/zypp/target/rpm/RpmHeader.h b/zypp/target/rpm/RpmHeader.h new file mode 100644 index 0000000..c27ac28 --- /dev/null +++ b/zypp/target/rpm/RpmHeader.h @@ -0,0 +1,221 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/RpmHeader.h + * +*/ +#ifndef ZYPP_TARGET_RPM_RPMHEADER_H +#define ZYPP_TARGET_RPM_RPMHEADER_H + +#include +#include +#include + +#include + +#include +#include +#include + + +namespace zypp +{ +namespace target +{ +namespace rpm +{ + +struct FileInfo +{ + Pathname filename; + ByteCount size; + std::string md5sum; + uid_t uid; + gid_t gid; + mode_t mode; + time_t mtime; + bool ghost; + Pathname link_target; +}; + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : RpmHeader +/** + * @short Wrapper class for rpm header struct. + * + * RpmHeader provides methods to query the content + * of a rpm header struct retrieved from the RPM database or by reading + * the rpm header of a package on disk. + * + * The rpm header contains all data associated with a package. So you + * probabely do not want to permanently store too many of them. + * + * NEVER create RpmHeader from a NULL Header! + **/ +class ZYPP_API RpmHeader : public BinHeader +{ +public: + using Ptr = intrusive_ptr; + using constPtr = intrusive_ptr; + +private: + + CapabilitySet PkgRelList_val( tag tag_r, bool pre, std::set * freq_r = 0 ) const; + +public: + + /** + * + **/ + RpmHeader( Header h_r = 0 ); + + /** + * Dangerous!<\B> This one takes the header out of rhs + * and leaves rhs empty. + **/ + RpmHeader( BinHeader::Ptr & rhs ); + + ~RpmHeader() override; + + bool isSrc() const; ///< Either 'src' or 'nosrc' + bool isNosrc() const; ///< Only 'nosrc' + + std::string ident() const; ///< N-V-R.A or empty + +public: + + std::string tag_name() const; + Edition::epoch_t tag_epoch() const; + std::string tag_version() const; + std::string tag_release() const; + Edition tag_edition() const; + Arch tag_arch() const; + + Date tag_installtime() const; + Date tag_buildtime() const; + + /** + * If freq_r is not NULL, file dependencies found are inserted. + **/ + CapabilitySet tag_provides ( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_requires ( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_prerequires ( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_conflicts( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_obsoletes( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_enhances( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_suggests( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_supplements( std::set * freq_r = 0 ) const; + /** + * @see #tag_provides + **/ + CapabilitySet tag_recommends( std::set * freq_r = 0 ) const; + + ByteCount tag_size() const; + ByteCount tag_archivesize() const; + + std::string tag_summary() const; + std::string tag_description() const; + std::string tag_group() const; + std::string tag_vendor() const; + std::string tag_distribution() const; + std::string tag_license() const; + std::string tag_buildhost() const; + std::string tag_packager() const; + std::string tag_url() const; + std::string tag_os() const; + std::string tag_prein() const; + std::string tag_preinprog() const; + std::string tag_postin() const; + std::string tag_postinprog() const; + std::string tag_preun() const; + std::string tag_preunprog() const; + std::string tag_postun() const; + std::string tag_postunprog() const; + std::string tag_pretrans() const; + std::string tag_pretransprog() const; + std::string tag_posttrans() const; + std::string tag_posttransprog()const; + std::string tag_sourcerpm() const; + + /** + * Uses headerFormat to query the signature info from the header. + * \note Query copied from Yum misc/checksig.py + */ + std::string signatureKeyID() const; + + /** just the list of names */ + std::list tag_filenames() const; + + /** + * complete information about the files + * (extended version of tag_filenames()) + */ + std::list tag_fileinfos() const; + + Changelog tag_changelog() const; + +public: + + std::ostream & dumpOn( std::ostream & str ) const override; + +public: + + /** + * Digest and signature verification flags + **/ + enum VERIFICATION + { + VERIFY = 0x0000, + NODIGEST = (1<<0), + NOSIGNATURE = (1<<1), + NOVERIFY = 0xffff + }; + + /** + * Get an accessible packages data from disk. + * Returns NULL on any error. + **/ + static RpmHeader::constPtr readPackage( const Pathname & path, + VERIFICATION verification = VERIFY ); + + /** + * Get an accessible packages data from disk using a existing transaction. + * Returns a std::pair container the header and resultcode from reading it + **/ + static std::pair readPackage( rpmts ts_r, const Pathname & path_r ); +}; + +/////////////////////////////////////////////////////////////////// +} // namespace rpm +} // namespace target +} // namespace zypp + +#endif // ZYPP_TARGET_RPM_RPMHEADER_H + diff --git a/zypp/target/rpm/librpm.h b/zypp/target/rpm/librpm.h new file mode 100644 index 0000000..17e801d --- /dev/null +++ b/zypp/target/rpm/librpm.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/librpm.h + * +*/ +#ifndef ZYPP_TARGET_RPM_LIBRPM_H +#define ZYPP_TARGET_RPM_LIBRPM_H + +#ifdef _RPM_5 +// needs to be outside 'extern "C"' +#include +#endif // _RPM_5 + +extern "C" +{ +#ifdef _RPM_5 +#include +#else +#include +#endif // _RPM_5 + +#include +#include +#include +#include +#include +} + +#endif // ZYPP_TARGET_RPM_LIBRPM_H diff --git a/zypp/target/rpm/librpmDb.cc b/zypp/target/rpm/librpmDb.cc new file mode 100644 index 0000000..fbab129 --- /dev/null +++ b/zypp/target/rpm/librpmDb.cc @@ -0,0 +1,848 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/librpmDb.cc + * +*/ +#include "librpm.h" + +#include +#include + +#include +#include +#include +#include +#include + +#undef ZYPP_BASE_LOGGER_LOGGROUP +#define ZYPP_BASE_LOGGER_LOGGROUP "librpmDb" + +using std::endl; + +namespace zypp +{ +namespace target +{ +namespace rpm +{ +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : librpmDb::D +/** + * @short librpmDb internal database handle + **/ +class librpmDb::D +{ + D ( const D & ) = delete; // NO COPY! + D & operator=( const D & ) = delete; // NO ASSIGNMENT! + D(D &&) = delete; + D &operator=(D &&) = delete; +public: + + const Pathname _root; // root directory for all operations + const Pathname _dbPath; // directory (below root) that contains the rpmdb + rpmts _ts; // transaction handle, includes database + shared_ptr _error; // database error + + friend std::ostream & operator<<( std::ostream & str, const D & obj ) + { + str << "{" << obj._error << "(" << obj._root << ")" << obj._dbPath << "}"; + return str; + } + + D(Pathname root_r, Pathname dbPath_r, bool readonly_r) + : _root(std::move(root_r)), _dbPath(std::move(dbPath_r)), _ts(0) { + _error.reset(); + // set %_dbpath macro + ::addMacro( NULL, "_dbpath", NULL, _dbPath.asString().c_str(), RMIL_CMDLINE ); + + _ts = ::rpmtsCreate(); + ::rpmtsSetRootDir( _ts, _root.c_str() ); + + // open database (creates a missing one on the fly) + int res = ::rpmtsOpenDB( _ts, (readonly_r ? O_RDONLY : O_RDWR )); + if ( res ) + { + ERR << "rpmdbOpen error(" << res << "): " << *this << endl; + _error = shared_ptr(new RpmDbOpenException(_root, _dbPath)); + rpmtsFree(_ts); + ZYPP_THROW(*_error); + return; + } + + DBG << "DBACCESS " << *this << endl; + } + + ~D() + { + if ( _ts ) + { + ::rpmtsFree(_ts); + } + } +}; + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : librpmDb (ststic interface) +// +/////////////////////////////////////////////////////////////////// + +Pathname librpmDb::_defaultRoot { "/" }; +Pathname librpmDb::_defaultDbPath; // set in dbAccess depending on suggestedDbPath below /root +Pathname librpmDb::_rpmDefaultDbPath; // set by globalInit +librpmDb::constPtr librpmDb::_defaultDb; +bool librpmDb::_dbBlocked = true; + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::globalInit +// METHOD TYPE : bool +// +bool librpmDb::globalInit() +{ + static bool initialized = false; + + if ( initialized ) + return true; + + int rc = ::rpmReadConfigFiles( NULL, NULL ); + if ( rc ) + { + ERR << "rpmReadConfigFiles returned " << rc << endl; + return false; + } + + initialized = true; // Necessary to be able to use exand(). + _rpmDefaultDbPath = expand( "%{_dbpath}" ); + + if ( _rpmDefaultDbPath.empty() ) { + _rpmDefaultDbPath = "/usr/lib/sysimage/"; + WAR << "Looks like rpm has no %{_dbpath} set!?! Assuming " << _rpmDefaultDbPath << endl; + } + MIL << "librpm init done: (_target:" << expand( "%{_target}" ) << ") (_dbpath:" << _rpmDefaultDbPath << ")" << endl; + return initialized; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::expand +// METHOD TYPE : std::string +// +std::string librpmDb::expand( const std::string & macro_r ) +{ + if ( ! globalInit() ) + return macro_r; // unexpanded + + char * val = ::rpmExpand( macro_r.c_str(), NULL ); + if ( !val ) + return ""; + + std::string ret( val ); + free( val ); + return ret; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::newLibrpmDb +// METHOD TYPE : librpmDb * +// +librpmDb * librpmDb::newLibrpmDb() +{ + // initialize librpm + if ( ! globalInit() ) + { + ZYPP_THROW(GlobalRpmInitException()); + } + + if ( _defaultDbPath.empty() ) // db_const_iterator access to /(default) without RpmDB/Tareget init. + _defaultDbPath = suggestedDbPath( _defaultRoot ); + + // open rpmdb + librpmDb * ret = 0; + try + { + ret = new librpmDb( _defaultRoot, _defaultDbPath, /*readonly*/true ); + } + catch (const RpmException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + delete ret; + ret = 0; + ZYPP_RETHROW(excpt_r); + } + return ret; +} + + +Pathname librpmDb::suggestedDbPath( const Pathname & root_r ) +{ + if ( ! root_r.absolute() ) + ZYPP_THROW(RpmInvalidRootException( root_r, "" )); + + // initialize librpm (for _rpmDefaultDbPath) + if ( ! globalInit() ) + ZYPP_THROW(GlobalRpmInitException()); + + if ( PathInfo( root_r ).isDir() ) { + // If a known dbpath exsists, we continue to use it + for ( auto p : { "/var/lib/rpm", "/usr/lib/sysimage/rpm" } ) { + if ( PathInfo( root_r/p, PathInfo::LSTAT/*!no symlink*/ ).isDir() ) { + MIL << "Suggest existing database at " << stringPath( root_r, p ) << endl; + return p; + } + } + } + + MIL << "Suggest rpm _dbpath " << stringPath( root_r, _rpmDefaultDbPath ) << endl; + return _rpmDefaultDbPath; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dbAccess +// METHOD TYPE : PMError +// +void librpmDb::dbAccess( const Pathname & root_r ) +{ + if ( _defaultDb ) + { + // already accessing a database: switching is not allowed. + if ( _defaultRoot == root_r ) + return; + else + ZYPP_THROW(RpmDbAlreadyOpenException(_defaultRoot, _defaultDbPath, root_r, _defaultDbPath)); + } + + // got no database: we could switch to a new one (even if blocked!) + _defaultDbPath = suggestedDbPath( root_r ); // also asserts root_r is absolute + _defaultRoot = root_r; + + MIL << "Set new database location: " << stringPath( _defaultRoot, _defaultDbPath ) << endl; + return dbAccess(); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dbAccess +// METHOD TYPE : PMError +// +void librpmDb::dbAccess() +{ + if ( _dbBlocked ) + { + ZYPP_THROW(RpmAccessBlockedException(_defaultRoot, _defaultDbPath)); + } + + if ( !_defaultDb ) + { + // get access + _defaultDb = newLibrpmDb(); + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dbAccess +// METHOD TYPE : PMError +// +void librpmDb::dbAccess( librpmDb::constPtr & ptr_r ) +{ + ptr_r = nullptr; + dbAccess(); + ptr_r = _defaultDb; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dbRelease +// METHOD TYPE : unsigned +// +unsigned librpmDb::dbRelease( bool force_r ) +{ + if ( !_defaultDb ) + { + return 0; + } + + unsigned outstanding = _defaultDb->refCount() - 1; // refCount can't be 0 + + switch ( outstanding ) + { + default: + if ( !force_r ) + { + DBG << "dbRelease: keep access, outstanding " << outstanding << endl; + break; + } + // else fall through: + case 0: + DBG << "dbRelease: release" << (force_r && outstanding ? "(forced)" : "") + << ", outstanding " << outstanding << endl; + + _defaultDb->_d._error = shared_ptr(new RpmAccessBlockedException(_defaultDb->_d._root, _defaultDb->_d._dbPath)); + // tag handle invalid + _defaultDb = 0; + break; + } + + return outstanding; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::blockAccess +// METHOD TYPE : unsigned +// +unsigned librpmDb::blockAccess() +{ + MIL << "Block access" << endl; + _dbBlocked = true; + return dbRelease( /*force*/true ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::unblockAccess +// METHOD TYPE : void +// +void librpmDb::unblockAccess() +{ + MIL << "Unblock access" << endl; + _dbBlocked = false; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dumpState +// METHOD TYPE : ostream & +// +std::ostream & librpmDb::dumpState( std::ostream & str ) +{ + if ( !_defaultDb ) + { + return str << "[librpmDb " << (_dbBlocked?"BLOCKED":"CLOSED") << " " << stringPath( _defaultRoot, _defaultDbPath ) << "]"; + } + return str << "[" << _defaultDb << "]"; +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : librpmDb (internal database handle interface (nonstatic)) +// +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::librpmDb +// METHOD TYPE : Constructor +// +// DESCRIPTION : +// +librpmDb::librpmDb( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r ) + : _d( * new D( root_r, dbPath_r, readonly_r ) ) +{} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::~librpmDb +// METHOD TYPE : Destructor +// +// DESCRIPTION : +// +librpmDb::~librpmDb() +{ + delete &_d; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::unref_to +// METHOD TYPE : void +// +void librpmDb::unref_to( unsigned refCount_r ) const +{ + if ( refCount_r == 1 ) + { + dbRelease(); + } +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::root +// METHOD TYPE : const Pathname & +// +const Pathname & librpmDb::root() const +{ + return _d._root; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dbPath +// METHOD TYPE : const Pathname & +// +const Pathname & librpmDb::dbPath() const +{ + return _d._dbPath; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::error +// METHOD TYPE : PMError +// +shared_ptr librpmDb::error() const +{ + return _d._error; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::empty +// METHOD TYPE : bool +// +bool librpmDb::empty() const +{ + return( valid() && ! *db_const_iterator( this ) ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::size +// METHOD TYPE : unsigned +// +unsigned librpmDb::size() const +{ + unsigned count = 0; + if ( valid() ) + { + db_const_iterator it( this ); + for ( db_const_iterator it( this ); *it; ++it ) + ++count; + } + return count; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dont_call_it +// METHOD TYPE : void * +// +void * librpmDb::dont_call_it() const +{ + return rpmtsGetRdb(_d._ts); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::dumpOn +// METHOD TYPE : ostream & +// +// DESCRIPTION : +// +std::ostream & librpmDb::dumpOn( std::ostream & str ) const +{ + ReferenceCounted::dumpOn( str ) << _d; + return str; +} + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : librpmDb::db_const_iterator::D +/** + * + **/ +class librpmDb::db_const_iterator::D +{ + D & operator=( const D & ) = delete; // NO ASSIGNMENT! + D ( const D & ) = delete; // NO COPY! + D(D &&); + D &operator=(D &&) = delete; +public: + + librpmDb::constPtr _dbptr; + shared_ptr _dberr; + + RpmHeader::constPtr _hptr; + rpmdbMatchIterator _mi; + + D(librpmDb::constPtr dbptr_r) : _dbptr(std::move(dbptr_r)), _mi(0) { + if ( !_dbptr ) + { + try + { + librpmDb::dbAccess( _dbptr ); + } + catch (const RpmException & excpt_r) + { + ZYPP_CAUGHT(excpt_r); + } + if ( !_dbptr ) + { + WAR << "No database access: " << _dberr << endl; + } + } + else + { + destroy(); // Checks whether _dbptr still valid + } + } + + ~D() + { + if ( _mi ) + { + ::rpmdbFreeIterator( _mi ); + } + } + + /** + * Let iterator access a dbindex file. Call @ref advance to access the + * 1st element (if present). + **/ + bool create( int rpmtag, const void * keyp = NULL, size_t keylen = 0 ) + { + destroy(); + if ( ! _dbptr ) + return false; + _mi = ::rpmtsInitIterator( _dbptr->_d._ts, rpmTag(rpmtag), keyp, keylen ); + return _mi; + } + + /** + * Destroy iterator. Invalidates _dbptr, if database was blocked meanwile. + * Always returns false. + **/ + bool destroy() + { + if ( _mi ) + { + _mi = ::rpmdbFreeIterator( _mi ); + _hptr = 0; + } + if ( _dbptr && _dbptr->error() ) + { + _dberr = _dbptr->error(); + WAR << "Lost database access: " << _dberr << endl; + _dbptr = 0; + } + return false; + } + + /** + * Advance to the first/next header in iterator. Destroys iterator if + * no more headers available. + **/ + bool advance() + { + if ( !_mi ) + return false; + Header h = ::rpmdbNextIterator( _mi ); + if ( ! h ) + { + destroy(); + return false; + } + _hptr = new RpmHeader( h ); + return true; + } + + /** + * Access a dbindex file and advance to the 1st header. + **/ + bool init( int rpmtag, const void * keyp = NULL, size_t keylen = 0 ) + { + if ( ! create( rpmtag, keyp, keylen ) ) + return false; + return advance(); + } + + /** + * Create an itertator that contains the database entry located at + * off_r, and advance to the 1st header. + **/ + bool set( int off_r ) + { + if ( ! create( RPMDBI_PACKAGES ) ) + return false; +#ifdef RPMFILEITERMAX // since rpm.4.12 + ::rpmdbAppendIterator( _mi, (const unsigned *)&off_r, 1 ); +#else + ::rpmdbAppendIterator( _mi, &off_r, 1 ); +#endif + return advance(); + } + + unsigned offset() + { + return( _mi ? ::rpmdbGetIteratorOffset( _mi ) : 0 ); + } + + int size() + { + if ( !_mi ) + return 0; + int ret = ::rpmdbGetIteratorCount( _mi ); + return( ret ? ret : -1 ); // -1: sequential access + } +}; + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : librpmDb::Ptr::db_const_iterator +// +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::db_iterator +// METHOD TYPE : Constructor +// +librpmDb::db_const_iterator::db_const_iterator( librpmDb::constPtr dbptr_r ) + : _d( * new D( std::move(dbptr_r) ) ) +{ + findAll(); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::~db_const_iterator +// METHOD TYPE : Destructor +// +librpmDb::db_const_iterator::~db_const_iterator() +{ + delete &_d; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::operator++ +// METHOD TYPE : void +// +void librpmDb::db_const_iterator::operator++() +{ + _d.advance(); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::dbHdrNum +// METHOD TYPE : unsigned +// +unsigned librpmDb::db_const_iterator::dbHdrNum() const +{ + return _d.offset(); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::operator* +// METHOD TYPE : const RpmHeader::constPtr & +// +const RpmHeader::constPtr & librpmDb::db_const_iterator::operator*() const +{ + return _d._hptr; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::dbError +// METHOD TYPE : PMError +// +shared_ptr librpmDb::db_const_iterator::dbError() const +{ + if ( _d._dbptr ) + return _d._dbptr->error(); + + return _d._dberr; +} + +/****************************************************************** +** +** +** FUNCTION NAME : operator<< +** FUNCTION TYPE : ostream & +*/ +std::ostream & operator<<( std::ostream & str, const librpmDb::db_const_iterator & obj ) +{ + str << "db_const_iterator(" << obj._d._dbptr + << " Size:" << obj._d.size() + << " HdrNum:" << obj._d.offset() + << ")"; + return str; +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findAll +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findAll() +{ + return _d.init( RPMDBI_PACKAGES ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findByFile +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findByFile( const std::string & file_r ) +{ + return _d.init( RPMTAG_BASENAMES, file_r.c_str() ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findByProvides +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findByProvides( const std::string & tag_r ) +{ + return _d.init( RPMTAG_PROVIDENAME, tag_r.c_str() ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findByRequiredBy +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findByRequiredBy( const std::string & tag_r ) +{ + return _d.init( RPMTAG_REQUIRENAME, tag_r.c_str() ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findByConflicts +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findByConflicts( const std::string & tag_r ) +{ + return _d.init( RPMTAG_CONFLICTNAME, tag_r.c_str() ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::findByName +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findByName( const std::string & name_r ) +{ + return _d.init( RPMTAG_NAME, name_r.c_str() ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findPackage +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findPackage( const std::string & name_r ) +{ + if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) ) + return false; + + if ( _d.size() == 1 ) + return true; + + // check installtime on multiple entries + int match = 0; + time_t itime = 0; + for ( ; operator*(); operator++() ) + { + if ( operator*()->tag_installtime() > itime ) + { + match = _d.offset(); + itime = operator*()->tag_installtime(); + } + } + + return _d.set( match ); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findPackage +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findPackage( const std::string & name_r, const Edition & ed_r ) +{ + if ( ! _d.init( RPMTAG_NAME, name_r.c_str() ) ) + return false; + + for ( ; operator*(); operator++() ) + { + if ( ed_r == operator*()->tag_edition() ) + { + int match = _d.offset(); + return _d.set( match ); + } + } + + return _d.destroy(); +} + +/////////////////////////////////////////////////////////////////// +// +// +// METHOD NAME : librpmDb::db_const_iterator::findPackage +// METHOD TYPE : bool +// +bool librpmDb::db_const_iterator::findPackage( const Package::constPtr & which_r ) +{ + if ( ! which_r ) + return _d.destroy(); + + return findPackage( which_r->name(), which_r->edition() ); +} + +} // namespace rpm +} // namespace target +} // namespace zypp diff --git a/zypp/target/rpm/librpmDb.h b/zypp/target/rpm/librpmDb.h new file mode 100644 index 0000000..231852d --- /dev/null +++ b/zypp/target/rpm/librpmDb.h @@ -0,0 +1,480 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/target/rpm/librpmDb.h + * +*/ +#ifndef librpmDb_h +#define librpmDb_h + +#include + +#include +#include +#include +#include +#include +#include + +namespace zypp +{ +namespace target +{ +namespace rpm +{ + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : librpmDb +/** + * @short Manage access to librpm database. + **/ +class librpmDb : public base::ReferenceCounted, private base::NonCopyable +{ +public: + using Ptr = intrusive_ptr; + using constPtr = intrusive_ptr; +private: + /** + * INTENTIONALLY UNDEFINED<\B> because of bug in Ptr classes + * which allows implicit conversion from librpmDb::Ptr to + * librpmDb::constPtr. Currently we don't want to provide non const + * handles, as the database is opened READONLY. + * + * \throws RpmException + * + **/ + static void dbAccess( librpmDb::Ptr & ptr_r ); + +public: + + /////////////////////////////////////////////////////////////////// + // + // static interface + // + /////////////////////////////////////////////////////////////////// +private: + + /** + * Current root directory for all operations. + * (initially /) + **/ + static Pathname _defaultRoot; + + /** + * Current directory (below root) that contains the rpmdb. + **/ + static Pathname _defaultDbPath; + + /** + * %_dbpath configured in rpm config. + **/ + static Pathname _rpmDefaultDbPath; + + /** + * Current rpmdb handle. + **/ + static librpmDb::constPtr _defaultDb; + + /** + * Whether access is blocked (no _defaultDb will be available). + **/ + static bool _dbBlocked ZYPP_API; + + /** + * For internal use. Pointer returned should immediately be + * wrapped into librpmDb::Ptr. + * + * \throws RpmException + * + **/ + static librpmDb * newLibrpmDb(); + + /** + * Access the database at the current default location. If necessary + * (eg. after @ref dbRelease), the database is opened. This just creates + * the internal handle. Once the handle is passed to e.g. some + * @ref db_const_iterator, the database will be closed if the last + * outstanding reference goes out of scope. If no external reference is + * created, you'll have to explicitly call @ref dbRelease to close the + * database. + * + * \throws RpmException + * + **/ + static void dbAccess(); + +public: + + /** + * Initialize lib librpm (read configfiles etc.). It's called + * on demand but you may call it anytime. + * + * @return Whether librpm is initialized. + **/ + static bool globalInit(); + + /** + * @return librpm macro expansion. + **/ + static std::string expand( const std::string & macro_r ); + + /** + * @return String '(root_r)sub_r' used in debug output. + **/ + static std::string stringPath( const Pathname & root_r, const Pathname & sub_r ) + { + return std::string( "'(" ) + root_r.asString() + ")" + sub_r.asString() + "'"; + } + +public: + + /** + * @return Current root directory for all operations. + **/ + static const Pathname & defaultRoot() + { + return _defaultRoot; + } + + /** + * @return Current directory (below root) that contains the rpmdb. + **/ + static const Pathname & defaultDbPath() + { + return _defaultDbPath; + } + + /** + * \return The preferred location of the rpmdb below \a root_r. + * It's the location of an already exising db, otherwise the + * default location sugested by rpms config. + * + * \throws RpmInvalidRootException if root is not an absolute path or + * no directory for the rpmdb can determined. + **/ + static Pathname suggestedDbPath( const Pathname & root_r ); + + /** + * Adjust access to the given database location, making it the new + * default location on success. No relative Pathnames are allowed. + * + * It's not possible to access a database while access is blocked + * (see @ref blockAccess), but valid Pathnames provided will be stored + * as new default location. + * + * It's not allowed to switch to another location while a database + * is accessed. Use @ref dbRelease to force releasing the database first. + * + * \throws RpmException + * + **/ + static void dbAccess( const Pathname & root_r ); + + /** + * Same as &ref dbAccess(), but returns the database handle if + * avaialble, otherwise NULL. This creates an external reference, thus + * it should not be used longer than necessary. Be prepared that the + * handle might become invalid (see @ref dbRelease) later. + * + * \throws RpmException + * + **/ + static void dbAccess( librpmDb::constPtr & ptr_r ); + + /** + * If there are no outstanding references to the database (e.g. by @ref db_const_iterator), + * the database is closed. Subsequent calls to @ref dbAccess may however + * open the database again. + * + * If forced, the internal reference is dropped and it will look like + * the database was closed. But physically the database will be closed + * after all outstanding references are gone. + * + * @return The number of outstandig references to the database, 0 if + * if database was physically closed. + **/ + static unsigned dbRelease( bool force_r = false ) ZYPP_API; + + /** + * Blocks further access to rpmdb. Basically the same as @ref dbRelease( true ), + * but subsequent calls to @ref dbAccess will fail returning E_RpmDB_access_blocked. + * + * @return The number of outstandig references to the database, 0 if + * if database was physically closed. + **/ + static unsigned blockAccess() ZYPP_API; + + /** + * @overload Blocks access iff the database is located at root_r/dbPath_r. + **/ + static unsigned blockAccess( const Pathname & root_r, const Pathname & dbPath_r ) + { + return ( root_r == _defaultRoot && dbPath_r == _defaultDbPath ) ? blockAccess() : 0; + } + + /** + * Allow access to rpmdb e.g. after @ref blockAccess. Subsequent calls to + * @ref dbAccess will perform. + * + * NOTE: Initially we're in blocked mode. So you must call @ref unblockAccess + * unblockAccess at least once. Othwise nothing will happen. + * + * @return The number of outstandig references to the database, 0 if + * if database was physically closed. + **/ + static void unblockAccess() ZYPP_API; + + /** + * @return Whether database access is blocked. + **/ + static bool isBlocked() ZYPP_API + { + return _dbBlocked; + } + + /** + * Dump debug info. + **/ + static std::ostream & dumpState( std::ostream & str ); + +public: + + /** + * Subclass to retrieve database content. + **/ + class db_const_iterator; + +private: + /////////////////////////////////////////////////////////////////// + // + // internal database handle interface (nonstatic) + // + /////////////////////////////////////////////////////////////////// + + /** + * Hides librpm specific data + **/ + class D; + D & _d; + +protected: + + /** + * Private constructor! librpmDb objects are to be created via + * static interface only. + **/ + librpmDb( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r ); + + /** + * Trigger from @ref Rep, after refCount was decreased. + **/ + void unref_to( unsigned refCount_r ) const override; + +public: + + /** + * Destructor. Closes rpmdb. + **/ + ~librpmDb() override; + + /** + * @return This handles root directory for all operations. + **/ + const Pathname & root() const; + + /** + * @return This handles directory that contains the rpmdb. + **/ + const Pathname & dbPath() const; + + /** + * Return any database error. Usg. if the database was + * blocked by calling @ref dbRelease(true) or @ref blockAccess. + **/ + shared_ptr error() const; + + /** + * @return Whether handle is valid. + **/ + bool valid() const + { + return( ! error() ); + } + + /** + * @return True if handle is valid and database is empty. + **/ + bool empty() const; + + /** + * @return Number of entries in the database (0 if not valid). + **/ + unsigned size() const; + +public: + + /** + * Dont call it ;) It's for development and testing only. + **/ + void * dont_call_it() const; + + /** + * Dump debug info. + **/ + std::ostream & dumpOn( std::ostream & str ) const override; +}; + +/////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////// +// +// CLASS NAME : librpmDb::db_const_iterator +/** + * @short Subclass to retrieve database content. + * + * + **/ +class ZYPP_API librpmDb::db_const_iterator +{ + db_const_iterator & operator=( const db_const_iterator & ); // NO ASSIGNMENT! + db_const_iterator ( const db_const_iterator & ); // NO COPY! + friend std::ostream & operator<<( std::ostream & str, const db_const_iterator & obj ); + friend class librpmDb; + +private: + + /** + * Hides librpm specific data + **/ + class D; + D & _d; + +public: + + /** + * Constructor. Iterator is initialized to @ref findAll. + * The default form accesses librpmDb's default database. + * Explicitly providing a database handle should not be + * neccesary, except for testing. + **/ + db_const_iterator( librpmDb::constPtr dbptr_r = 0 ); + + /** + * Destructor. + **/ + ~db_const_iterator(); + + /** + * Return any database error. + * + * NOTE: If the database gets blocked (see @ref dbRelease) + * dbError will immediately report this, but an already running + * iteration will proceed to its end. Then the database is dropped. + **/ + shared_ptr dbError() const; + + /** + * Advance to next RpmHeader::constPtr. + **/ + void operator++(); + + /** + * Returns the current headers index in database, + * 0 if no header. + **/ + unsigned dbHdrNum() const; + + /** + * Returns the current RpmHeader::constPtr or + * NULL, if no more entries available. + **/ + const RpmHeader::constPtr & operator*() const; + + /** + * Forwards to the current RpmHeader::constPtr. + **/ + const RpmHeader::constPtr & operator->() const + { + return operator*(); + } + +public: + + /** + * Reset to iterate all packages. Returns true if iterator + * contains at least one entry. + * + * NOTE: No entry (false) migt be returned due to a + * meanwhile blocked database (see @ref dbRelease). Use + * @ref dbError to check this. + **/ + bool findAll(); + + /** + * Reset to iterate all packages that own a certain file. + **/ + bool findByFile( const std::string & file_r ); + + /** + * Reset to iterate all packages that provide a certain tag. + **/ + bool findByProvides( const std::string & tag_r ); + + /** + * Reset to iterate all packages that require a certain tag. + **/ + bool findByRequiredBy( const std::string & tag_r ); + + /** + * Reset to iterate all packages that conflict with a certain tag. + **/ + bool findByConflicts( const std::string & tag_r ); + + /** + * Reset to iterate all packages with a certain name. + * + * NOTE: Multiple entries for one package installed + * in different versions are possible but not desired. Usually + * you'll want to use @ref findPackage instead. + * + * findByName is needed to retrieve pseudo packages like + * 'gpg-pubkey', which in fact exist in multiple instances. + **/ + bool findByName( const std::string & name_r ); + +public: + + /** + * Find package by name. + * + * Multiple entries for one package installed in different versions + * are possible but not desired. If so, the last package installed + * is returned. + **/ + bool findPackage( const std::string & name_r ); + + /** + * Find package by name and edition. + * Commonly used by PMRpmPackageDataProvider. + **/ + bool findPackage( const std::string & name_r, const Edition & ed_r ); + + /** + * Abbr. for findPackage( which_r->name(), which_r->edition() ); + **/ + bool findPackage( const Package::constPtr & which_r ); +}; + +/////////////////////////////////////////////////////////////////// +} //namespace rpm +} //namespace target +} // namespace zypp + +#endif // librpmDb_h + diff --git a/zypp/ui/SelFilters.h b/zypp/ui/SelFilters.h new file mode 100644 index 0000000..9d6d6df --- /dev/null +++ b/zypp/ui/SelFilters.h @@ -0,0 +1,95 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/SelFilters.h + * +*/ +#ifndef ZYPP_UI_SELFILTERS_H +#define ZYPP_UI_SELFILTERS_H + +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace selfilter + { ///////////////////////////////////////////////////////////////// + + /** */ + struct ByKind + { + ByKind( ResKind kind_r ) + : _kind(std::move( kind_r )) + {} + + bool operator()( const Selectable::constPtr & obj ) const + { + return obj && obj->kind() == _kind; + } + + ResKind _kind; + }; + + /** */ + struct ByName + { + ByName( std::string name_r ) + : _name(std::move( name_r )) + {} + + bool operator()( const ui::Selectable::constPtr & obj ) const + { return obj && obj->name() == _name; } + + std::string _name; + }; + + /** */ + struct ByHasInstalledObj + { + bool operator()( const ui::Selectable::constPtr & obj ) const + { return obj && !obj->installedEmpty(); } + }; + + /** */ + struct ByHasCandidateObj + { + bool operator()( const ui::Selectable::constPtr & obj ) const + { return obj && obj->hasCandidateObj(); } + }; + + struct ByStatus + /** */ + { + ByStatus( Status status_r ) + : _status( status_r ) + {} + + bool operator()( const ui::Selectable::constPtr & obj ) const + { return obj && obj->status() == _status; } + + Status _status; + }; + + ///////////////////////////////////////////////////////////////// + } // namespace selfilter + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_UI_SELFILTERS_H diff --git a/zypp/ui/Selectable.cc b/zypp/ui/Selectable.cc new file mode 100644 index 0000000..31dd362 --- /dev/null +++ b/zypp/ui/Selectable.cc @@ -0,0 +1,342 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/Selectable.cc + * +*/ +#include +#include +//#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + IMPL_PTR_TYPE(Selectable); + + Selectable::Ptr Selectable::get( const pool::ByIdent & ident_r ) + { return ResPool::instance().proxy().lookup( ident_r ); } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Selectable::Selectable + // METHOD TYPE : Ctor + // + Selectable::Selectable( Impl_Ptr pimpl_r ) + : _pimpl( std::move(pimpl_r) ) + {} + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : Selectable::~Selectable + // METHOD TYPE : Dtor + // + Selectable::~Selectable() + {} + + /////////////////////////////////////////////////////////////////// + // + // Forward to implementation. + // Restrict PoolItems to ResObject::constPtr! + // + /////////////////////////////////////////////////////////////////// + + IdString Selectable::ident() const + { return _pimpl->ident(); } + + ResKind Selectable::kind() const + { return _pimpl->kind(); } + + const std::string & Selectable::name() const + { return _pimpl->name(); } + + Status Selectable::status() const + { return _pimpl->status(); } + + bool Selectable::setStatus( Status state_r, ResStatus::TransactByValue causer_r ) + { return _pimpl->setStatus( state_r, causer_r ); } + + PoolItem Selectable::installedObj() const + { return _pimpl->installedObj(); } + + PoolItem Selectable::candidateObj() const + { return _pimpl->candidateObj(); } + + PoolItem Selectable::candidateObjFrom( Repository repo_r ) const + { return _pimpl->candidateObjFrom( repo_r ); } + + PoolItem Selectable::updateCandidateObj() const + { return _pimpl->updateCandidateObj(); } + + PoolItem Selectable::highestAvailableVersionObj() const + { return _pimpl->highestAvailableVersionObj(); } + + bool Selectable::identIsAutoInstalled() const + { return _pimpl->identIsAutoInstalled(); } + + bool Selectable::identicalAvailable( const PoolItem & rhs ) const + { return _pimpl->identicalAvailable( rhs ); } + + bool Selectable::identicalInstalled( const PoolItem & rhs ) const + { return _pimpl->identicalInstalled( rhs ); } + + PoolItem Selectable::identicalAvailableObj( const PoolItem & rhs ) const + { return _pimpl->identicalAvailableObj( rhs ); } + + PoolItem Selectable::identicalInstalledObj( const PoolItem & rhs ) const + { return _pimpl->identicalInstalledObj( rhs ); } + + PoolItem Selectable::setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r ) + { return _pimpl->setCandidate( newCandidate_r, causer_r ); } + + PoolItem Selectable::setCandidate( const ResObject::constPtr& newCandidate_r, ResStatus::TransactByValue causer_r ) + { return _pimpl->setCandidate( PoolItem( newCandidate_r ), causer_r ); } + + bool Selectable::setOnSystem( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r ) + { + if ( identicalInstalled( newCandidate_r ) ) + return setFate( UNMODIFIED, causer_r ); + return setCandidate( newCandidate_r, causer_r ) && setFate( TO_INSTALL, causer_r ); + } + + PoolItem Selectable::theObj() const + { return _pimpl->theObj(); } + + std::vector Selectable::supersededBy() const + { return _pimpl->supersededBy(); } + + //////////////////////////////////////////////////////////////////////// + + bool Selectable::availableEmpty() const + { return _pimpl->availableEmpty(); } + + Selectable::available_size_type Selectable::availableSize() const + { return _pimpl->availableSize(); } + + Selectable::available_iterator Selectable::availableBegin() const + { return _pimpl->availableBegin(); } + + Selectable::available_iterator Selectable::availableEnd() const + { return _pimpl->availableEnd(); } + + //////////////////////////////////////////////////////////////////////// + + bool Selectable::installedEmpty() const + { return _pimpl->installedEmpty(); } + + Selectable::installed_size_type Selectable::installedSize() const + { return _pimpl->installedSize(); } + + Selectable::installed_iterator Selectable::installedBegin() const + { return _pimpl->installedBegin(); } + + Selectable::installed_iterator Selectable::installedEnd() const + { return _pimpl->installedEnd(); } + + //////////////////////////////////////////////////////////////////////// + + bool Selectable::picklistEmpty() const + { return _pimpl->picklistEmpty(); } + + Selectable::picklist_size_type Selectable::picklistSize() const + { return _pimpl->picklistSize(); } + + Selectable::picklist_iterator Selectable::picklistBegin() const + { return _pimpl->picklistBegin(); } + + Selectable::picklist_iterator Selectable::picklistEnd() const + { return _pimpl->picklistEnd(); } + + Selectable::picklist_size_type Selectable::picklistPos( const PoolItem & pi_r ) const + { return picklistPos( pi_r.satSolvable() ); } + + Selectable::picklist_size_type Selectable::picklistPos( const sat::Solvable & solv_r ) const + { + picklist_size_type idx = picklist_size_type(0); + for ( const auto & pi : picklist() ) + { + if ( pi == solv_r ) + return idx; + ++idx; + } + return picklistNoPos; + } + + //////////////////////////////////////////////////////////////////////// + + bool Selectable::hasBlacklisted() const + { return _pimpl->hasBlacklisted(); } + + bool Selectable::hasBlacklistedInstalled() const + { return _pimpl->hasBlacklistedInstalled(); } + + bool Selectable::hasRetracted() const + { return _pimpl->hasRetracted(); } + + bool Selectable::hasRetractedInstalled() const + { return _pimpl->hasRetractedInstalled(); } + + bool Selectable::hasPtf() const + { return _pimpl->hasPtf(); } + + bool Selectable::hasPtfInstalled() const + { return _pimpl->hasPtfInstalled(); } + + + bool Selectable::isUnmaintained() const + { return _pimpl->isUnmaintained(); } + + bool Selectable::multiversionInstall() const + { return _pimpl->multiversionInstall(); } + + bool Selectable::pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ) + { return _pimpl->pickInstall( pi_r, causer_r, yesno_r ); } + + bool Selectable::pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ) + { return _pimpl->pickDelete( pi_r, causer_r, yesno_r ); } + + Status Selectable::pickStatus( const PoolItem & pi_r ) const + { return _pimpl->pickStatus( pi_r ); } + + bool Selectable::setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ) + { return _pimpl->setPickStatus( pi_r, state_r, causer_r ); } + + //////////////////////////////////////////////////////////////////////// + + bool Selectable::isUndetermined() const + { return _pimpl->isUndetermined(); } + + bool Selectable::isRelevant() const + { return _pimpl->isRelevant(); } + + bool Selectable::isSatisfied() const + { return _pimpl->isSatisfied(); } + + bool Selectable::isBroken() const + { return _pimpl->isBroken(); } + + bool Selectable::isNeeded() const + { + return fate() == TO_INSTALL || ( ! locked() && isBroken() ); + } + + bool Selectable::isUnwanted() const + { + return locked() && isBroken() ; + } + + ResStatus::TransactByValue Selectable::modifiedBy() const + { return _pimpl->modifiedBy(); } + + bool Selectable::hasLicenceConfirmed() const + { return _pimpl->hasLicenceConfirmed(); } + + void Selectable::setLicenceConfirmed( bool val_r ) + { _pimpl->setLicenceConfirmed( val_r ); } + + bool Selectable::hasLocks() const + { return _pimpl->hasLocks(); } + + Selectable::Fate Selectable::fate() const + { + switch ( status() ) { + case S_Update: + case S_Install: + case S_AutoUpdate: + case S_AutoInstall: + return TO_INSTALL; + break; + + case S_Del: + case S_AutoDel: + return TO_DELETE; + break; + + case S_Protected: + case S_Taboo: + case S_KeepInstalled: + case S_NoInst: + break; + } + return UNMODIFIED; + }; + + bool Selectable::setFate( Fate fate_r, ResStatus::TransactByValue causer_r ) + { + switch ( fate_r ) + { + case TO_INSTALL: + return setStatus( hasInstalledObj() ? S_Update : S_Install, causer_r ); + break; + + case TO_DELETE: + return setStatus( S_Del, causer_r ); + break; + + case UNMODIFIED: + switch ( status() ) { + case S_Protected: + case S_Taboo: + return true; + break; + default: + return setStatus( hasInstalledObj() ? S_KeepInstalled : S_NoInst, causer_r ); + break; + } + break; + } + return false; + } + + bool Selectable::setInstalled( ResStatus::TransactByValue causer_r ) + { + return( hasInstalledObj() || setStatus( S_Install, causer_r ) ); + } + + bool Selectable::setUpToDate( ResStatus::TransactByValue causer_r ) + { + if ( ! hasInstalledObj() ) + return setStatus( S_Install, causer_r ); + + PoolItem cand( candidateObj() ); + if ( ! cand ) + return true; + + return( installedObj()->edition() >= cand->edition() + || setStatus( S_Update, causer_r ) ); + } + + bool Selectable::setDeleted( ResStatus::TransactByValue causer_r ) + { + return( ! hasInstalledObj() || setStatus( S_Del, causer_r ) ); + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const Selectable & obj ) + { return str << *(obj._pimpl); } + + std::ostream & dumpOn( std::ostream & str, const Selectable & obj ) + { return dumpOn( str, *(obj._pimpl) ); } + + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ui/Selectable.h b/zypp/ui/Selectable.h new file mode 100644 index 0000000..c6c24bd --- /dev/null +++ b/zypp/ui/Selectable.h @@ -0,0 +1,602 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/Selectable.h + * +*/ +#ifndef ZYPP_UI_SELECTABLE_H +#define ZYPP_UI_SELECTABLE_H + +#include +#include + +#include +#include +#include +#include + +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + DEFINE_PTR_TYPE(Selectable); + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Selectable + // + /** Collects PoolItems of same kind and name. + * + * Selectable is a status wrapper. The ui::Status is calculated + * from (and transated to) \ref PoolItems individual \ref ResStatus + * values. + * + * Available objects are sorted according the solver policies, 'best' + * packages first (e.g. by repository priority, then Arch, then Edition). + * + * Installed objects are sorted according the installation date, newer install + * time first. + */ + class ZYPP_API Selectable : public base::ReferenceCounted, private base::NonCopyable + { + friend std::ostream & operator<<( std::ostream & str, const Selectable & obj ); + friend std::ostream & dumpOn( std::ostream & str, const Selectable & obj ); + + public: + using Ptr = intrusive_ptr; + using constPtr = intrusive_ptr; + + /** Iterates over ResObject::constPtr */ + using available_iterator = SelectableTraits::available_iterator; + using available_size_type = SelectableTraits::available_size_type; + + using installed_iterator = SelectableTraits::installed_iterator; + using installed_size_type = SelectableTraits::installed_size_type; + + using picklist_iterator = SelectableTraits::picklist_iterator; + using picklist_size_type = SelectableTraits::picklist_size_type; + + public: + /** \name Static ctor substitues picking the item from the pool. + * \code + * Selectable::Ptr item; + * item = Selectable::get( "amarok ); // package amamrok + * item = Selectable::get( ResKind::patch, "amarok ); // patch amamrok + * item = Selectable::get( IdString( "patch:amarok" ); // patch amamrok + * \endcode + */ + //@{ + /** Get the \ref Selctable */ + static Ptr get( const pool::ByIdent & ident_r ); + + /** Get the \ref Selctable by its \c sat-identifier. */ + static Ptr get( IdString ident_r ) + { return get( pool::ByIdent( ident_r ) ); } + + /** Get the \ref Selctable by \c kind and \c name. */ + static Ptr get( ResKind kind_r, const std::string & name_r ) + { return get( pool::ByIdent( std::move(kind_r), name_r ) ); } + + /** Get the \c Package \ref Selctable by \c name. */ + static Ptr get( const std::string & name_r ) + { return get( pool::ByIdent( ResKind::package, name_r ) ); } + + /** Get the \ref Selctable containing a specific \ref sat::Solvable. */ + static Ptr get( const sat::Solvable & solv_r ) + { return get( pool::ByIdent( solv_r ) ); } + + /** Get the \ref Selctable containing a specific \ref ResObject. */ + static Ptr get( const ResObject::constPtr & resolvable_r ) + { return resolvable_r ? get( resolvable_r->satSolvable() ) : Ptr(); } + + /** Get the \ref Selctable containing a specific \ref PoolItem. */ + static Ptr get( const PoolItem & pi_r ) + { return get( pi_r.satSolvable() ); } + //@} + + public: + /** The identifier. + * This is the solvables \ref name, \b except for packages and + * source packes, prefixed by its \ref kind. + * \see \ref sat::Solvable. + */ + IdString ident() const; + + /** The ResObjects kind. */ + ResKind kind() const; + + /** The ResObjects name. */ + const std::string & name() const; + + /** The last Installed object. */ + PoolItem installedObj() const; + + /** The 'best' or 'most interesting' among all available objects. + * One that is, or is likely to be, chosen for installation, unless + * it violated any solver policy (see \ref updateCandidateObj). + * \note Might return a blacklisted item if explicitly set by \ref setCandidate + * or nothing else available. + */ + PoolItem candidateObj() const; + + /** The best candidate provided by a specific \ref Repository, if there is one. + * In contrary to \ref candidateObj, this may return no item even if + * there are available objects. This simply means the \ref Repository + * does not provide this object. + * \note Avoids to return blacklisted items. + */ + PoolItem candidateObjFrom( Repository repo_r ) const; + + /** The best candidate for update, if there is one. + * In contrary to \ref candidateObj, this may return no item even if + * there are available objects. This simply means the best object is + * already installed, and all available objects violate at least one + * update policy. Or all available objects are blacklisted (e.g. a PTF) + * in which there does not need to be an installed item either. + * \note Avoids to return blacklisted items. + */ + PoolItem updateCandidateObj() const; + + /** Simply the highest available version, ignoring priorities and policies. + * It's doubtful whether solely looking at the version makes a good + * candidate, but apps ask for it. Beware that different vendors may + * use different (uncomparable) version schemata. + * \note Avoids to return blacklisted items. + */ + PoolItem highestAvailableVersionObj() const; + + /** Whether this \ref ident is flagged as AutoInstalled. */ + bool identIsAutoInstalled() const; + + /** \c True if \a rhs is installed and one with the same content is available. + * Basically the same name, edition, arch, vendor and buildtime. + * \see \ref sat::Solvable::identical + */ + bool identicalAvailable( const PoolItem & rhs ) const; + + /** \c True if \a rhs has the same content as an installed one. + * Basically the same name, edition, arch, vendor and buildtime. + * \see \ref sat::Solvable::identical + */ + bool identicalInstalled( const PoolItem & rhs ) const; + + /** \c True if the \ref candidateObj is installed (same content). + * \see \ref identicalInstalled. + */ + bool identicalInstalledCandidate() const + { return identicalInstalled( candidateObj() ); } + + /** \c True if the \ref updateCandidateObj is installed (same content). + * \see \ref identicalInstalled. + */ + bool identicalInstalledUpdateCandidate() const + { return identicalInstalled( updateCandidateObj() ); } + + /** Return an available Object with the same content as \c rhs. + * Basically the same name, edition, arch, vendor and buildtime. + * \see \ref sat::Solvable::identical + */ + PoolItem identicalAvailableObj( const PoolItem & rhs ) const; + + /** \Return an installed Object with the same content as \c rhs. + * Basically the same name, edition, arch, vendor and buildtime. + * \see \ref sat::Solvable::identical + */ + PoolItem identicalInstalledObj( const PoolItem & rhs ) const; + + /** Return the \ref installedObj resolvable casted to a specific kind. + * \code + * Selectable mySelectable; + * Package::constPtr p( mySelectable.installedAsKind() ); + * \endcode + */ + template + typename ResTraits::constPtrType installedAsKind() const + { return asKind( candidateObj() ); } + + /** Return the \ref candidateObj resolvable casted to a specific kind. + * \code + * Selectable mySelectable; + * Package::constPtr p( mySelectable.candidateAsKind() ); + * \endcode + */ + template + typename ResTraits::constPtrType candidateAsKind() const + { return asKind( candidateObj() ); } + + /** Set a candidate (out of available objects). + * \return The new candidate, or NULL if choice was invalid + * (NULL or not among availableObjs). An invalid choice + * selects the default candidate. + * In case the causer is not \c ResStatus::USER the operation + * may also fail if there are insufficient permissions to change + * a transacting candidate. + */ + PoolItem setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + /** \overload */ + PoolItem setCandidate( const ResObject::constPtr& newCandidate_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + + /** Arrange the specified candidate (out of available objects) to be on system after commit. + * If the specified candidate is not already installed (\ref identicalInstalled), + * and the \a causer_r has sufficient permission, then \a newCandidate_r is set as the new + * candidate (\ref setCandidate) and selected for installation. + * \returns \c True if \a newCandidate_r is already installed or successfully selected for installation. + */ + bool setOnSystem( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + + /** An object you could use as pars pro toto. + * + * \return the \ref candidateObj, or ,if no available objects + * exist, the \ref installedObj. + */ + PoolItem theObj() const; + + /** The name(s) of the successor package if \ref vendorSupport is \ref VendorSupportSuperseded. + * It returns the value for the newest candidate. + * \see \ref Package::supersededBy + */ + std::vector supersededBy() const; + + //////////////////////////////////////////////////////////////////////// + + /** \name Available objects iterators. + * Oredered according to solver policy. 'Best' first. + */ + //@{ + bool availableEmpty() const; + available_size_type availableSize() const; + available_iterator availableBegin() const; + available_iterator availableEnd() const; + inline Iterable available() const + { return makeIterable( availableBegin(), availableEnd() ); } + //@} + + //////////////////////////////////////////////////////////////////////// + + /** \name Installed objects iterators. + * Ordered by install time. Latest first. + */ + //@{ + bool installedEmpty() const; + installed_size_type installedSize() const; + installed_iterator installedBegin() const; + installed_iterator installedEnd() const; + inline Iterable installed() const + { return makeIterable( installedBegin(), installedEnd() ); } + //@} + + //////////////////////////////////////////////////////////////////////// + + /** \name picklist iterators. + * This is basically the available items list prepended by those + * installed items, that are nolonger \ref identicalAvailable. + */ + //@{ + bool picklistEmpty() const; + picklist_size_type picklistSize() const; + picklist_iterator picklistBegin() const; + picklist_iterator picklistEnd() const; + inline Iterable picklist() const + { return makeIterable( picklistBegin(), picklistEnd() ); } + + /** Returned by \ref picklistPos if the Item does not belong to the picklist. */ + static constexpr const picklist_size_type picklistNoPos = picklist_size_type(-1); + + /** Return the position of \a pi_r in the piclist or \ref picklistNoPos. + * \note \ref picklistNoPos is returned if you pass an installed Poolitem, + * whci has an \ref identicalAvailableObj. + */ + picklist_size_type picklistPos( const PoolItem & pi_r ) const; + + /** \overload taking a sat::Solvable */ + picklist_size_type picklistPos( const sat::Solvable & solv_r ) const; + //@} + + //////////////////////////////////////////////////////////////////////// + + public: + /** \name Query for objects within this Selectable. + */ + //@{ + /** True if either installed or candidate object is present */ + bool hasObject() const + { return (! installedEmpty()) || candidateObj(); } + + /** True if installed object is present. */ + bool hasInstalledObj() const + { return ! installedEmpty(); } + + /** True if candidate object is present. */ + bool hasCandidateObj() const + { return bool(candidateObj()); } + + /** True if installed and candidate object is present */ + bool hasBothObjects() const + { return (! installedEmpty()) && candidateObj(); } + + /** True if installed object is present but no candidate. */ + bool hasInstalledObjOnly() const + { return (! installedEmpty()) && ! candidateObj(); } + + /** True if candidate object is present but no installed. */ + bool hasCandidateObjOnly() const + { return ( installedEmpty() ) && candidateObj(); } + + + /** True if this Selectable contains available blacklisted items (retracted,ptf,...). */ + bool hasBlacklisted() const; + + /** True if this Selectable contains an installed blacklisted item (retracted,ptf,...). */ + bool hasBlacklistedInstalled() const; + + /** True if this Selectable contains available retracted items. */ + bool hasRetracted() const; + + /** True if this Selectable contains an installed retracted item. */ + bool hasRetractedInstalled() const; + + /** True if this Selectable contains available ptf items. */ + bool hasPtf() const; + + /** True if this Selectable contains an installed ptf item. */ + bool hasPtfInstalled() const; + //@} + + /** + * True if this package has no replacement from + * the available repositories + */ + bool isUnmaintained() const; + + /** \name Multiversion install. + * + * Using \ref pickInstall or \ref pickDelete with non-multiversionInstall items + * is possible, but additional constraints will apply. E.g. selecting one item for + * install will deselect any other. + */ + //@{ + /** Whether at least one of the available packages has multiversionInstall set. + * \see \ref Solvable::multiversionInstall + * \see also \ref ZConfig::multiversion. + */ + bool multiversionInstall() const; + + /** Select a specific available item for installation. + */ + bool pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r = ResStatus::USER, bool yesno_r = true ); + + /** Deselect a specific available item from installation. + */ + bool pickNoInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r = ResStatus::USER ) + { return pickInstall( pi_r, causer_r, false ); } + + /** Select a specific installed item for deletion. + */ + bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r = ResStatus::USER, bool yesno_r = true ); + + /** Deselect a specific installed item from deletion. + */ + bool pickNoDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r = ResStatus::USER ) + { return pickDelete( pi_r, causer_r, false ); } + + /** Compute the \ref ui::Status for an individual PoolItem. + * This just takes into account the item and any identical + * installed (or available) one. + * \code + * Assume there are 3 identical 'foo-1.1 (vendor A)' items, + * one 'foo-2.1 (vendor A)' and one ''foo-1.1 (vendor B)': + * + * installed: . foo-1.1 (vendor A) -> S_KeepInstalled + * available: foo-2.1 (vendor A) (repo 1) -> S_NoInst + * . foo-1.1 (vendor A) (repo 1) -> S_KeepInstalled + * . foo-1.1 (vendor A) (repo 2) -> S_KeepInstalled + * foo-1.1 (vendor B) (repo 3) -> S_NoInst + * + * After 'foo-1.1 (vendor A) (repo 1)' was selected to be installed: + * + * installed: . foo-1.1 (vendor A) -> S_Update + * available: foo-2.1 (vendor A) (repo 1) -> S_NoInst + * I foo-1.1 (vendor A) (repo 1) -> S_Update + * . foo-1.1 (vendor A) (repo 2) -> S_KeepInstalled + * foo-1.1 (vendor B) (repo 3) -> S_NoInst + * \endcode + * \see \ref sat::Solvable::identical + */ + Status pickStatus( const PoolItem & pi_r ) const; + + /** Assign a new status to a specific item. */ + bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + //@} + + /** \name Classification of available patches (pseudo installed items). + * A patch is either \c not \c relevant, \c satisfied or \c broken. + * The same applies to other pseudo installed kinds. + * \see \ref traits::isPseudoInstalled + */ + //@{ + /** Returns true for packages, because packages are not + * classified by the solver. + */ + bool isUndetermined() const; + + /** Returns true if the patch is relevant which means that at least + * one package of the patch is installed. + */ + bool isRelevant() const; + + /** Whether a relevant patchs requirements are met. */ + bool isSatisfied() const; + + /** Whether a relevant patchs requirements are broken. */ + bool isBroken() const; + + /** This includes \c unlocked broken patches, as well as those already + * selected to be installed. This is because already selected + * patches will be classified as \c satisfied. \c Locked but broken + * patches will be classified as \ref isUnwanted. + */ + bool isNeeded() const; + + /** Broken (needed) but locked patches. */ + bool isUnwanted() const; + //@} + + public: + /** \name Query and maip objects fate in case of commit. + */ + //@{ + enum Fate { + TO_DELETE = -1, + UNMODIFIED = 0, + TO_INSTALL = 1 + }; + /** */ + Fate fate() const; + + /** True if neither to delete or to install */ + bool unmodified() const + { return fate() == UNMODIFIED; } + + /** True if locked (subclass of unmodified). + * The \ref locked status indicates that \b all installed and/or \b all available + * items are locked. So you can't remove and/or can't install any item. This + * is the common case. + * \see \ref hasLocks + */ + bool locked() const + { Status st( status() ); return( st == S_Protected || st == S_Taboo ); } + + /** True if it includes locked items (don't mix this with the \ref locked status). + * This is also \c true for partially locked items, where only specific versions + * are locked. + * \see \ref locked + */ + bool hasLocks() const; + + /** True if either to delete or to install */ + bool toModify() const + { return fate() != UNMODIFIED; } + + /** True if to delete */ + bool toDelete() const + { return fate() == TO_DELETE; } + + /** True if to install */ + bool toInstall() const + { return fate() == TO_INSTALL; } + + /** True if would be on system after commit. */ + bool onSystem() const + { return( ( hasInstalledObj() && !toDelete() ) + ||( hasCandidateObj() && toInstall() ) ); } + + /** True if would be off system after commit. */ + bool offSystem() const + { return ! onSystem(); } + + /** */ + bool setFate( Fate fate_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + + /** Set the item to be installed (new- or re-install). */ + bool setToInstall( ResStatus::TransactByValue causer_r = ResStatus::USER ) + { return setFate( TO_INSTALL, causer_r ); } + + /** Take care the item gets installed if it is not. */ + bool setInstalled( ResStatus::TransactByValue causer_r = ResStatus::USER ); + + /** Take care the item gets installed if it is not, or is older. */ + bool setUpToDate( ResStatus::TransactByValue causer_r = ResStatus::USER ); + + /** Set the item to be deleted (must be installed). */ + bool setToDelete( ResStatus::TransactByValue causer_r = ResStatus::USER ) + { return setFate( TO_DELETE, causer_r ); } + + /** Take care the item gets deleted if it is installed. */ + bool setDeleted( ResStatus::TransactByValue causer_r = ResStatus::USER ); + + /** Set the item to stay unmodified. */ + bool unset( ResStatus::TransactByValue causer_r = ResStatus::USER ) + { return setFate( UNMODIFIED, causer_r ); } + //@} + + public: + /** + * \name Special inteface for Y2UI. + * \note This interface acts on \ref ResStatus::USER level. + * The \ref Status enum, and allowed state transitions are + * tightly related to the Y2UI. + */ + //@{ + /** Return the current Status */ + Status status() const; + + /** + * Try to set a new Status. + * Returns \c false if the transitions is not allowed. + */ + bool setStatus( Status state_r, ResStatus::TransactByValue causer_r = ResStatus::USER ); + + /** Return who caused the modification. */ + ResStatus::TransactByValue modifiedBy() const; + + /** Return value of LicenceConfirmed bit. */ + bool hasLicenceConfirmed() const; + + /** Set LicenceConfirmed bit. */ + void setLicenceConfirmed( bool val_r = true ); + //@} + + public: + /** Implementation */ + struct Impl; + using Impl_Ptr = shared_ptr; + /** Default ctor */ + Selectable( Impl_Ptr pimpl_r ); + private: + /** Dtor */ + ~Selectable() override; + private: + /** Pointer to implementation */ + RW_pointer _pimpl; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Selectable Stream output */ + std::ostream & operator<<( std::ostream & str, const Selectable & obj ) ZYPP_API; + + /** \relates Selectable More verbose stream output */ + std::ostream & dumpOn( std::ostream & str, const Selectable & obj ) ZYPP_API; + + /** Solvable to Selectable transform functor. + * \relates Selectable + * \relates sat::SolvIterMixin + */ + struct ZYPP_API asSelectable + { + using result_type = Selectable_Ptr; + + Selectable_Ptr operator()( const sat::Solvable & solv_r ) const; + + Selectable_Ptr operator()( const PoolItem & pi_r ) const + { return operator()( pi_r.satSolvable() ); } + }; + + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_UI_SELECTABLE_H diff --git a/zypp/ui/SelectableImpl.cc b/zypp/ui/SelectableImpl.cc new file mode 100644 index 0000000..7805f67 --- /dev/null +++ b/zypp/ui/SelectableImpl.cc @@ -0,0 +1,665 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/SelectableImpl.cc + * +*/ +#include +//#include + +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + /** Simple ResStatus backup stack. + * \ref restore simply rewinds all remembered status. + */ + class StatusBackup + { + public: + using Causer = ResStatus::TransactByValue; + + public: + /** Backup status. */ + ResStatus & backup( ResStatus & status_r ) + { + _backup.push_back( status_r ); + return status_r; + } + /** \overload */ + ResStatus & backup( const PoolItem & pi_r ) + { return backup( pi_r.status() ); } + + /** Backup status. */ + ResStatus & operator()( ResStatus & status_r ) + { return backup( status_r ); } + /** \overload */ + ResStatus & operator()( const PoolItem & pi_r ) + { return backup( pi_r.status() ); } + + /** Restore all status. */ + bool restore() + { + for_( rit, _backup.rbegin(), _backup.rend() ) + rit->replay(); + return false; // restore is done on error - return restore(); + } + + public: + /** lowlevel \c ResStatus::setTransact */ + bool setTransact( const PoolItem & pi_r, bool yesno_r, Causer causer_r ) + { return backup( pi_r ).setTransact( yesno_r, causer_r ); } + + /** lowlevel \c ResStatus::setLock */ + bool setLock( const PoolItem & pi_r, bool yesno_r, Causer causer_r ) + { return backup( pi_r ).setLock( yesno_r, causer_r ); } + + /** lowlevel \c ResStatus::setTransact(true). */ + bool setTransactTrue( const PoolItem & pi_r, Causer causer_r ) + { return setTransact( pi_r, true, causer_r ); } + + /** lowlevel \c ResStatus::setTransact(false). */ + bool setTransactFalse( const PoolItem & pi_r, Causer causer_r ) + { return setTransact( pi_r, false, causer_r ); } + + public: + /** highevel set transact (force unlock). */ + bool transact( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( ! status.setLock( false, causer_r ) ) return false; + if ( ! status.setTransact( true, causer_r ) ) return false; + return true; + } + + /** highlevel set locked. */ + bool lock( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( ! status.setTransact( false, causer_r ) ) return false; + if ( ! status.setLock( true, causer_r ) ) return false; + return true; + } + + /** highlevel unlock (also unsets transact). */ + bool unlock( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( ! status.setTransact( false, causer_r ) ) return false; + if ( ! status.setLock( false, causer_r ) ) return false; + return true; + } + + /** highlevel remove transact from non-multiversion packages. */ + bool unsetNonMultiTransact( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( status.transacts() && ! pi_r.multiversionInstall() ) + { + if ( ! status.setTransact( false, causer_r ) ) return false; + } + return true; + } + + /** highlevel remove transact from multiversion packages. */ + bool unsetMultiTransact( const PoolItem & pi_r, Causer causer_r ) + { + ResStatus & status( backup( pi_r ) ); + if ( status.transacts() && pi_r.multiversionInstall() ) + { + if ( ! status.setTransact( false, causer_r ) ) return false; + } + return true; + } + + /** Highlevel action. */ + using Action = bool (StatusBackup::*)(const PoolItem &, Causer); + + /** Highlevel action on range of items. */ + template + bool forEach( TIter begin_r, TIter end_r, Action action_r, Causer causer_r ) + { + for_( it, begin_r, end_r ) + if ( ! (this->*action_r)( *it, causer_r ) ) + return false; + return true; + } + + private: + std::vector _backup; + }; + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : StatusHelper + // + /** \todo Unify status and pickStatus. + */ + struct StatusHelper + { + StatusHelper( const Selectable::Impl & impl, ResStatus::TransactByValue causer_r ) + : _impl( impl ) + , inst( impl.installedObj() ) + , cand( impl.candidateObj() ) + , causer( causer_r ) + {} + + using available_const_iterator = Selectable::Impl::available_const_iterator; + + // + // Queries + // + bool hasInstalled() const + { return bool(inst); } + + bool hasCandidate() const + { return bool(cand); } + + bool hasInstalledOnly() const + { return inst && !cand; } + + bool hasCandidateOnly() const + { return cand && !inst; } + + bool hasBoth() const + { return inst && cand; } + + /** \name Topevel methods must restore status on failure. */ + //@{ + bool setInstall() + { + if ( cand ) + { + if ( inst ) { + for_( it, _impl.installedBegin(), _impl.installedEnd() ) + { + ResStatus & inststatus( backup( it->status() ) ); + if ( ! inststatus.setTransact( false, causer ) ) return restore(); + if ( ! inststatus.setLock ( false, causer ) ) return restore(); + if ( ! cand->multiversionInstall() ) + { + // This is what the solver most probabely will do. + // If we are wrong the solver will correct it. But + // this way we will get a better disk usage result, + // even if no autosolving is on. + inststatus.setTransact( true, ResStatus::SOLVER ); + } + } + } + if ( ! unlockCandidates() ) return restore(); + ResStatus & candstatus( backup( cand.status() ) ); + if ( ! candstatus.setTransact( true, causer ) ) return restore(); + return true; + } + return false; + } + + bool setDelete() + { + if ( inst ) + { + if ( ! resetTransactingCandidates() ) return restore(); + for_( it, _impl.installedBegin(), _impl.installedEnd() ) + { + ResStatus & inststatus( backup( it->status() ) ); + if ( ! inststatus.setLock( false, causer ) ) return restore(); + if ( ! inststatus.setTransact( true, causer ) ) return restore(); + } + return true; + } + return false; + } + + bool unset() + { + if ( inst ) + { + for_( it, _impl.installedBegin(), _impl.installedEnd() ) + { + ResStatus & inststatus( backup( it->status() ) ); + if ( ! inststatus.setTransact( false, causer ) ) return restore(); + if ( ! inststatus.setLock( false, causer ) ) return restore(); + } + } + if ( ! unlockCandidates() ) return restore(); + return true; + } + + bool setProtected() + { + if ( causer != ResStatus::USER ) // by user only + return false; + + if ( inst ) { + resetTransactingCandidates(); + for_( it, _impl.installedBegin(), _impl.installedEnd() ) + { + it->status().setTransact( false, causer ); + it->status().setLock( true, causer ); + } + return true; + } else + return false; + } + + bool setTaboo() + { + if ( causer != ResStatus::USER ) // by user only + return false; + + if ( cand ) { + lockCandidates(); + return true; + } else + return false; + } + //@} + + private: + /** \name Helper methods backup status but do not replay. */ + //@{ + bool resetTransactingCandidates() + { + for_( it, _impl.availableBegin(), _impl.availableEnd() ) + { + ResStatus & status( backup( (*it).status() ) ); + if ( ! status.setTransact( false, causer ) ) return false; + } + return true; + } + bool unlockCandidates() + { + for_( it, _impl.availableBegin(), _impl.availableEnd() ) + { + ResStatus & status( backup( (*it).status() ) ); + if ( ! status.setTransact( false, causer ) ) return false; + if ( ! status.setLock( false, causer ) ) return false; + } + return true; + } + bool lockCandidates() + { + for_( it, _impl.availableBegin(), _impl.availableEnd() ) + { + ResStatus & status( backup( (*it).status() ) ); + if ( ! status.setTransact( false, causer ) ) return false; + if ( ! status.setLock( true, causer ) ) return false; + } + return true; + } + //@} + + private: + const Selectable::Impl & _impl; + PoolItem inst; + PoolItem cand; + ResStatus::TransactByValue causer; + + private: + bool restore() { return backup.restore(); } + StatusBackup backup; + }; + /////////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Selectable::Impl + // + /////////////////////////////////////////////////////////////////// + + Status Selectable::Impl::status() const + { + PoolItem cand( candidateObj() ); + if ( cand && cand.status().transacts() ) + { + if ( cand.status().isByUser() ) + return( installedObj() ? S_Update : S_Install ); + else + return( installedObj() ? S_AutoUpdate : S_AutoInstall ); + } + + if ( installedObj() && installedObj().status().transacts() ) + { + return( installedObj().status().isByUser() ? S_Del : S_AutoDel ); + } + + if ( installedObj() && allInstalledLocked() ) + return S_Protected; + + if ( !installedObj() && allCandidatesLocked() ) + return S_Taboo; + + // KEEP state: + if ( installedObj() ) + return S_KeepInstalled; + // Report pseudo installed items as installed, if they are satisfied. + if ( traits::isPseudoInstalled( kind() ) + && cand.status().isSatisfied() ) // no installed, so we must have candidate + return S_KeepInstalled; + + return S_NoInst; + } + + bool Selectable::Impl::setStatus( Status state_r, ResStatus::TransactByValue causer_r ) + { + StatusHelper self( *this, causer_r ); + + switch ( state_r ) + { + case S_Protected: + return self.setProtected(); + case S_Taboo: + return self.setTaboo(); + case S_AutoDel: + case S_AutoInstall: + case S_AutoUpdate: + // Auto level is SOLVER level. UI may query, but not + // set at this level. + break; + + case S_Del: + return self.setDelete(); + break; + + case S_Install: + return self.hasCandidateOnly() && self.setInstall(); + break; + + case S_Update: + return self.hasBoth() && self.setInstall(); + break; + + case S_KeepInstalled: + return self.hasInstalled() && self.unset(); + break; + + case S_NoInst: + return !self.hasInstalled() && self.unset(); + break; + } + + return false; + } + + PoolItem Selectable::Impl::setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r ) + { + PoolItem newCandidate; + + if ( newCandidate_r ) // must be in available list + { + for_( it, availableBegin(), availableEnd() ) + { + if ( *it == newCandidate_r ) + { + newCandidate = *it; + break; + } + } + } + + if ( newCandidate ) + { + PoolItem trans( transactingCandidate() ); + if ( trans && trans != newCandidate ) + { + // adjust transact to the new cancidate + if ( trans.status().maySetTransact( false, causer_r ) + && newCandidate.status().maySetTransact( true, causer_r ) ) + { + trans.status().setTransact( false, causer_r ); + newCandidate.status().setTransact( true, causer_r ); + } + else + { + // No permission to change a transacting candidate. + // Leave _candidate untouched and return NULL. + return PoolItem(); + } + } + } + + return _candidate = newCandidate; + } + + /////////////////////////////////////////////////////////////////// + + bool Selectable::Impl::pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ) + { + if ( identicalInstalled( pi_r ) ) + return setPickStatus( pi_r, ( yesno_r ? S_Update : S_KeepInstalled ), causer_r ); + return setPickStatus( pi_r, ( yesno_r ? S_Install : S_NoInst ), causer_r ); + } + + bool Selectable::Impl::pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ) + { + return setPickStatus( pi_r, ( yesno_r ? S_Del : S_KeepInstalled ), causer_r ); + } + + bool Selectable::Impl::setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ) + { + if ( pi_r.ident() != ident() ) + return false; // not my PoolItem + + StatusBackup backup; + std::vector i; + std::vector a; + + for_( it, installedBegin(), installedEnd() ) + if ( identical( *it, pi_r ) ) + i.push_back( *it ); + for_( it, availableBegin(), availableEnd() ) + if ( identical( *it, pi_r ) ) + a.push_back( *it ); + + switch ( state_r ) + { + case S_Protected: + if ( causer_r == ResStatus::USER && ! i.empty() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::lock, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::setTransactFalse, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_Taboo: + if ( causer_r == ResStatus::USER && ! a.empty() ) + { + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::lock, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_AutoDel: + case S_AutoInstall: + case S_AutoUpdate: + // Auto level is SOLVER level. UI may query, but not + // set at this level. + break; + + case S_Del: + if ( ! i.empty() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::transact, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::setTransactFalse, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_Install: + if ( i.empty() && ! a.empty() ) + { + const PoolItem & cand( pi_r.status().isInstalled() ? *a.begin() : pi_r ); + if ( cand.multiversionInstall() ) + { + if ( ! backup.forEach( availableBegin(), availableEnd(), &StatusBackup::unsetNonMultiTransact, causer_r ) ) return backup.restore(); + // maybe unlock candidate only? + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + if ( ! cand.status().setTransact( true, causer_r ) ) return backup.restore(); + return true; + } + else + { + // For non-multiversion use ordinary setStatus + // NOTE that S_Update/S_Install here depends on !installedEmpty() + // and not on picklists identicalInstalled. + if ( ! backup.forEach( availableBegin(), availableEnd(), &StatusBackup::unsetMultiTransact, causer_r ) ) return backup.restore(); + if ( ! setCandidate( cand, causer_r ) ) return backup.restore(); + if ( ! setStatus( installedEmpty() ? S_Install : S_Update, causer_r ) ) return backup.restore(); + return true; + } + } + break; + + case S_Update: + if ( ! i.empty() && ! a.empty() ) + { + const PoolItem & cand( pi_r.status().isInstalled() ? *a.begin() : pi_r ); + if ( cand.multiversionInstall() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::setTransactTrue, ResStatus::SOLVER ) ) return backup.restore(); + if ( ! backup.forEach( availableBegin(), availableEnd(), &StatusBackup::unsetNonMultiTransact, causer_r ) ) return backup.restore(); + // maybe unlock candidate only? + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + if ( ! cand.status().setTransact( true, causer_r ) ) return backup.restore(); + return true; + } + else + { + // For non-multiversion use ordinary setStatus + // NOTE that S_Update/S_Install here depends on !installedEmpty() + // and not on picklists identicalInstalled. + if ( ! backup.forEach( availableBegin(), availableEnd(), &StatusBackup::unsetMultiTransact, causer_r ) ) return backup.restore(); + if ( ! setCandidate( cand, causer_r ) ) return backup.restore(); + if ( ! setStatus( installedEmpty() ? S_Install : S_Update, causer_r ) ) return backup.restore(); + return true; + } + } + break; + + case S_KeepInstalled: + if ( ! i.empty() ) + { + if ( ! backup.forEach( i.begin(), i.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + return true; + } + break; + + case S_NoInst: + if ( i.empty() ) + { + if ( ! backup.forEach( a.begin(), a.end(), &StatusBackup::unlock, causer_r ) ) return backup.restore(); + return true; + } + break; + } + return false; + } + + Status Selectable::Impl::pickStatus( const PoolItem & pi_r ) const + { + if ( pi_r.satSolvable().ident() != ident() ) + return Status(-1); // not my PoolItem + + std::vector i; + std::vector a; + PoolItem ti; + PoolItem ta; + + for_( it, installedBegin(), installedEnd() ) + if ( identical( *it, pi_r ) ) + { + i.push_back( *it ); + if ( ! ti && it->status().transacts() ) + ti = *it; + } + + for_( it, availableBegin(), availableEnd() ) + if ( identical( *it, pi_r ) ) + { + a.push_back( *it ); + if ( ! ta && it->status().transacts() ) + ta = *it; + } + + if ( ta ) + { + if ( ta.status().isByUser() ) + return( i.empty() ? S_Install : S_Update ); + else + return( i.empty() ? S_AutoInstall : S_AutoUpdate ); + } + + if ( ti ) + { + return( ti.status().isByUser() ? S_Del : S_AutoDel ); + } + + for_( it, i.begin(), i.end() ) + if ( it->status().isLocked() ) + return S_Protected; + + if ( i.empty() ) + { + bool allALocked = true; + for_( it, a.begin(), a.end() ) + if ( ! it->status().isLocked() ) + { + allALocked = false; + break; + } + if ( allALocked ) + return S_Taboo; + } + + // KEEP state: + if ( ! i.empty() ) + return S_KeepInstalled; + // Report pseudo installed items as installed, if they are satisfied. + if ( traits::isPseudoInstalled( kind() ) + && ( ta ? ta : *a.begin() ).status().isSatisfied() ) // no installed, so we must have candidate + return S_KeepInstalled; + + return S_NoInst; + } + + /////////////////////////////////////////////////////////////////// + + ResStatus::TransactByValue Selectable::Impl::modifiedBy() const + { + PoolItem cand( candidateObj() ); + if ( cand && cand.status().transacts() ) + return cand.status().getTransactByValue(); + + if ( installedObj() && installedObj().status().transacts() ) + return installedObj().status().getTransactByValue(); + + if ( cand ) + return cand.status().getTransactByValue(); + + if ( installedObj() ) + return installedObj().status().getTransactByValue(); + + return ResStatus::SOLVER; + } + + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ui/SelectableImpl.h b/zypp/ui/SelectableImpl.h new file mode 100644 index 0000000..51b7187 --- /dev/null +++ b/zypp/ui/SelectableImpl.h @@ -0,0 +1,633 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/SelectableImpl.h + * +*/ +#ifndef ZYPP_UI_SELECTABLEIMPL_H +#define ZYPP_UI_SELECTABLEIMPL_H + +#include +#include + +#include + +#include +#include +#include +#include +#include + +using std::endl; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : Selectable::Impl + // + /** Selectable implementation. + * \note Implementation is based in PoolItem, just the Selectable + * inteface restricts them to ResObject::constPtr. + */ + struct Selectable::Impl + { + public: + + using AvailableItemSet = SelectableTraits::AvailableItemSet; + using available_iterator = SelectableTraits::available_iterator; + using available_const_iterator = SelectableTraits::available_const_iterator; + using available_size_type = SelectableTraits::available_size_type; + + using InstalledItemSet = SelectableTraits::InstalledItemSet; + using installed_iterator = SelectableTraits::installed_iterator; + using installed_const_iterator = SelectableTraits::installed_const_iterator; + using installed_size_type = SelectableTraits::installed_size_type; + + using PickList = SelectableTraits::PickList; + + public: + template + Impl( const ResKind & kind_r, + const std::string & name_r, + TIterator begin_r, + TIterator end_r ) + : _ident( sat::Solvable::SplitIdent( kind_r, name_r ).ident() ) + , _kind( kind_r ) + , _name( name_r ) + { + for_( it, begin_r, end_r ) + { + if ( it->status().isInstalled() ) + _installedItems.insert( *it ); + else + _availableItems.insert( *it ); + } + } + + public: + /** */ + IdString ident() const + { return _ident; } + + /** */ + ResKind kind() const + { return _kind; } + + /** */ + const std::string & name() const + { return _name; } + + /** */ + Status status() const; + + /** */ + bool setStatus( Status state_r, ResStatus::TransactByValue causer_r ); + + /** Installed object (transacting ot highest version). */ + PoolItem installedObj() const + { + if ( installedEmpty() ) + return PoolItem(); + PoolItem ret( transactingInstalled() ); + return ret ? ret : *_installedItems.begin(); + } + + /** Best among available objects. + * The transacting candidate or the one scheduled to receive + * the transact bit. + */ + PoolItem candidateObj() const + { + PoolItem ret( transactingCandidate() ); + if ( ! ret ) + ret = _candidate ? _candidate : defaultCandidate(); + return ret; + } + + /** Set a userCandidate (out of available objects). + * \return The new userCandidate or NULL if choice was invalid + * (not among availableObjs). + */ + PoolItem setCandidate( const PoolItem & newCandidate_r, ResStatus::TransactByValue causer_r ); + + /** The best candidate provided by a specific \ref Repository, if there is one. + * In contrary to \ref candidateObj, this may return no item even if + * there are available objects. This simply means the \ref Repository + * does not provide this object. + */ + PoolItem candidateObjFrom( Repository repo_r ) const + { + for ( const PoolItem & pi : available() ) + { + if ( pi.isBlacklisted() ) + continue; + if ( pi.repository() == repo_r ) + return pi; + } + return PoolItem(); + } + + /** The best candidate for update, if there is one. + * In contrary to \ref candidateObj, this may return no item even if + * there are available objects. This simply means the best object is + * already installed, and all available objects violate at least one + * update policy. + */ + PoolItem updateCandidateObj() const + { + PoolItem defaultCand( defaultCandidate() ); + + // multiversionInstall: This returns the candidate for the last + // instance installed. Actually we'd need a list here. + + if ( ! defaultCand || defaultCand.isBlacklisted() ) + return PoolItem(); + + if ( installedEmpty() ) + return defaultCand; + // Here: installed and defaultCand are non NULL and it's not a + // multiversion install. + + PoolItem installed( installedObj() ); + // check vendor change + if ( ! ( ResPool::instance().resolver().allowVendorChange() + || VendorAttr::instance().equivalent( defaultCand->vendor(), installed->vendor() ) ) ) + return PoolItem(); + + // check arch change (arch noarch changes are allowed) + if ( defaultCand->arch() != installed->arch() + && ! ( defaultCand->arch() == Arch_noarch || installed->arch() == Arch_noarch ) ) + return PoolItem(); + + // check greater edition + if ( defaultCand->edition() <= installed->edition() ) + return PoolItem(); + + return defaultCand; + } + + /** \copydoc Selectable::highestAvailableVersionObj()const */ + PoolItem highestAvailableVersionObj() const + { + PoolItem ret; + bool blacklistedOk = false; + for ( const PoolItem & pi : available() ) + { + if ( !blacklistedOk && pi.isBlacklisted() ) + { + if ( ret ) + break; // prefer a not retracted candidate + blacklistedOk = true; + } + if ( !ret || pi.edition() > ret.edition() ) + ret = pi; + } + return ret; + } + + /** \copydoc Selectable::identIsAutoInstalled()const */ + bool identIsAutoInstalled() const + { return sat::Solvable::identIsAutoInstalled( ident() ); } + + /** \copydoc Selectable::identicalAvailable( const PoolItem & )const */ + bool identicalAvailable( const PoolItem & rhs ) const + { return bool(identicalAvailableObj( rhs )); } + + /** \copydoc Selectable::identicalInstalled( const PoolItem & )const */ + bool identicalInstalled( const PoolItem & rhs ) const + { return bool(identicalInstalledObj( rhs )); } + + /** \copydoc Selectable::identicalAvailableObj( const PoolItem & rhs ) const */ + PoolItem identicalAvailableObj( const PoolItem & rhs ) const + { + if ( !availableEmpty() && rhs ) + { + for_( it, _availableItems.begin(), _availableItems.end() ) + { + if ( identical( *it, rhs ) ) + return *it; + } + } + return PoolItem(); + } + + /** \copydoc Selectable::identicalInstalledObj( const PoolItem & rhs ) const */ + PoolItem identicalInstalledObj( const PoolItem & rhs ) const + { + if ( !installedEmpty() && rhs ) + { + for_( it, _installedItems.begin(), _installedItems.end() ) + { + if ( identical( *it, rhs ) ) + return *it; + } + } + return PoolItem(); + } + + /** Best among all objects. */ + PoolItem theObj() const + { + PoolItem ret( candidateObj() ); + if ( ret ) + return ret; + return installedObj(); + } + + std::vector supersededBy() const + { + std::vector ret; + if ( kind() == ResKind::package ) { + for ( const PoolItem & pi : available() ) { + ret = pi->asKind()->supersededBy(); + if ( not ret.empty() ) + break; + } + } + return ret; + } + + //////////////////////////////////////////////////////////////////////// + + bool availableEmpty() const + { return _availableItems.empty(); } + + available_size_type availableSize() const + { return _availableItems.size(); } + + available_iterator availableBegin() const + { return _availableItems.begin(); } + + available_iterator availableEnd() const + { return _availableItems.end(); } + + inline Iterable available() const + { return makeIterable( availableBegin(), availableEnd() ); } + + //////////////////////////////////////////////////////////////////////// + + bool installedEmpty() const + { return _installedItems.empty(); } + + installed_size_type installedSize() const + { return _installedItems.size(); } + + installed_iterator installedBegin() const + { return _installedItems.begin(); } + + installed_iterator installedEnd() const + { return _installedItems.end(); } + + inline Iterable installed() const + { return makeIterable( installedBegin(), installedEnd() ); } + + //////////////////////////////////////////////////////////////////////// + + const PickList & picklist() const + { + if ( ! _picklistPtr ) + { + _picklistPtr.reset( new PickList ); + // installed without identical avaialble first: + for ( const PoolItem & pi : installed() ) + { + if ( ! identicalAvailable( pi ) ) + _picklistPtr->push_back( pi ); + } + _picklistPtr->insert( _picklistPtr->end(), availableBegin(), availableEnd() ); + } + return *_picklistPtr; + } + + bool picklistEmpty() const + { return picklist().empty(); } + + picklist_size_type picklistSize() const + { return picklist().size(); } + + picklist_iterator picklistBegin() const + { return picklist().begin(); } + + picklist_iterator picklistEnd() const + { return picklist().end(); } + + //////////////////////////////////////////////////////////////////////// + bool hasBlacklisted() const + { // Blacklisted items are sorted to the end of the available list. + return !_availableItems.empty() && _availableItems.rbegin()->isBlacklisted(); + } + + bool hasBlacklistedInstalled() const + { // Blacklisted items may be embedded in the installed list. + for ( const PoolItem & pi : installed() ) { + if ( pi.isBlacklisted() ) + return true; + } + return false; + } + + bool hasRetracted() const + { + for ( const PoolItem & pi : makeIterable( _availableItems.rbegin(), _availableItems.rend() ) ) { + if ( not pi.isBlacklisted() ) + break; + if ( pi.isRetracted() ) + return true; + } + return false; + } + + bool hasRetractedInstalled() const + { + for ( const PoolItem & pi : installed() ) { + if ( pi.isRetracted() ) + return true; + } + return false; + } + + bool hasPtf() const + { + for ( const PoolItem & pi : makeIterable( _availableItems.rbegin(), _availableItems.rend() ) ) { + if ( not pi.isBlacklisted() ) + break; + if ( pi.isPtf() ) + return true; + } + return false; + } + + bool hasPtfInstalled() const + { + for ( const PoolItem & pi : installed() ) { + if ( pi.isPtf() ) + return true; + } + return false; + } + + + bool isUnmaintained() const + { return availableEmpty(); } + + bool multiversionInstall() const + { + for ( const PoolItem & pi : picklist() ) + { + if ( pi.multiversionInstall() ) + return true; + } + return false; + } + + bool pickInstall( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ); + + bool pickDelete( const PoolItem & pi_r, ResStatus::TransactByValue causer_r, bool yesno_r ); + + Status pickStatus( const PoolItem & pi_r ) const; + + bool setPickStatus( const PoolItem & pi_r, Status state_r, ResStatus::TransactByValue causer_r ); + + //////////////////////////////////////////////////////////////////////// + + bool isUndetermined() const + { + PoolItem cand( candidateObj() ); + return ! cand || cand.isUndetermined(); + } + bool isRelevant() const + { + PoolItem cand( candidateObj() ); + return cand && cand.isRelevant(); + } + bool isSatisfied() const + { + PoolItem cand( candidateObj() ); + return cand && cand.isSatisfied(); + } + bool isBroken() const + { + PoolItem cand( candidateObj() ); + return cand && cand.isBroken(); + } + + /** Return who caused the modification. */ + ResStatus::TransactByValue modifiedBy() const; + + /** Return value of LicenceConfirmed bit. */ + bool hasLicenceConfirmed() const + { return candidateObj() && candidateObj().status().isLicenceConfirmed(); } + + /** Set LicenceConfirmed bit. */ + void setLicenceConfirmed( bool val_r ) + { if ( candidateObj() ) candidateObj().status().setLicenceConfirmed( val_r ); } + + /** \copydoc Selectable::hasLocks()const */ + bool hasLocks() const + { + for ( const PoolItem & pi : available() ) + { + if ( pi.status().isLocked() ) + return true; + } + for ( const PoolItem & pi : installed() ) + { + if ( pi.status().isLocked() ) + return true; + } + return false; + } + + private: + PoolItem transactingInstalled() const + { + for ( const PoolItem & pi : installed() ) + { + if ( pi.status().transacts() ) + return pi; + } + return PoolItem(); + } + + PoolItem transactingCandidate() const + { + for ( const PoolItem & pi : available() ) + { + if ( pi.status().transacts() ) + return pi; + } + return PoolItem(); + } + + PoolItem defaultCandidate() const + { + if ( ! installedEmpty() ) + { + // prefer the installed objects arch and vendor + bool solver_allowVendorChange( ResPool::instance().resolver().allowVendorChange() ); + for ( const PoolItem & ipi : installed() ) + { + PoolItem sameArch; // in case there's no same vendor at least stay with same arch. + for ( const PoolItem & api : available() ) + { + // 'same arch' includes allowed changes to/from noarch. + if ( ipi.arch() == api.arch() || ipi.arch() == Arch_noarch || api.arch() == Arch_noarch ) + { + if ( ! solver_allowVendorChange ) + { + if ( VendorAttr::instance().equivalent( ipi, api ) ) + return api; + else if ( ! sameArch ) // remember best same arch in case no same vendor found + sameArch = api; + } + else // same arch is sufficient + return api; + } + } + if ( sameArch ) + return sameArch; + } + } + if ( _availableItems.empty() ) + return PoolItem(); + + return *_availableItems.begin(); + } + + bool allCandidatesLocked() const + { + for ( const PoolItem & pi : available() ) + { + if ( ! pi.status().isLocked() ) + return false; + } + return( ! _availableItems.empty() ); + } + + bool allInstalledLocked() const + { + for ( const PoolItem & pi : installed() ) + { + if ( ! pi.status().isLocked() ) + return false; + } + return( ! _installedItems.empty() ); + } + + + private: + const IdString _ident; + const ResKind _kind; + const std::string _name; + InstalledItemSet _installedItems; + AvailableItemSet _availableItems; + //! The object selected by setCandidateObj() method. + PoolItem _candidate; + //! lazy initialized picklist + mutable scoped_ptr _picklistPtr; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates Selectable::Impl Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Selectable::Impl & obj ) + { + return str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status() + << " (I " << obj.installedSize() << ")" + << " (A " << obj.availableSize() << ")" + << obj.candidateObj(); + } + + /** \relates Selectable::Impl Stream output */ + inline std::ostream & dumpOn( std::ostream & str, const Selectable::Impl & obj ) + { + str << '[' << obj.kind() << ']' << obj.name() << ": " << obj.status() + << ( obj.multiversionInstall() ? " (multiversion)" : "") << endl; + + if ( obj.installedEmpty() ) + str << " (I 0) {}" << endl << " "; + else + { + PoolItem icand( obj.installedObj() ); + str << " (I " << obj.installedSize() << ") {" << endl; + for ( const PoolItem & pi : obj.installed() ) + { + char t = ' '; + if ( pi == icand ) + { + t = 'i'; + } + str << " " << t << " " << pi << endl; + } + str << "} "; + } + + if ( obj.availableEmpty() ) + { + str << "(A 0) {}" << endl << " "; + } + else + { + PoolItem cand( obj.candidateObj() ); + PoolItem up( obj.updateCandidateObj() ); + str << "(A " << obj.availableSize() << ") {" << endl; + for ( const PoolItem & pi : obj.available() ) + { + char t = ' '; + if ( pi == cand ) + { + t = pi == up ? 'C' : 'c'; + } + else if ( pi == up ) + { + t = 'u'; + } + str << " " << t << " " << pi << endl; + } + str << "} "; + } + + if ( obj.picklistEmpty() ) + { + str << "(P 0) {}"; + } + else + { + PoolItem cand( obj.candidateObj() ); + PoolItem up( obj.updateCandidateObj() ); + str << "(P " << obj.picklistSize() << ") {" << endl; + for ( const PoolItem & pi : obj.picklist() ) + { + char t = ' '; + if ( pi == cand ) + { + t = pi == up ? 'C' : 'c'; + } + else if ( pi == up ) + { + t = 'u'; + } + str << " " << t << " " << pi << "\t" << obj.pickStatus( pi ) << endl; + } + str << "} "; + } + + return str; + } + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_UI_SELECTABLEIMPL_H diff --git a/zypp/ui/SelectableTraits.h b/zypp/ui/SelectableTraits.h new file mode 100644 index 0000000..26577b0 --- /dev/null +++ b/zypp/ui/SelectableTraits.h @@ -0,0 +1,140 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/SelectableTraits.h + * +*/ +#ifndef ZYPP_UI_SELECTABLETRAITS_H +#define ZYPP_UI_SELECTABLETRAITS_H + +#include +#include + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : SelectableTraits + // + /** */ + struct SelectableTraits + { + /** Oder on AvailableItemSet. + * \li not blacklisted + * \li repository priority + * \li best Arch (arch/noarch changes are ok) + * \li best Edition + * \li newer buildtime + * \li ResObject::constPtr as fallback. + */ + struct AVOrder + { + // NOTE: operator() provides LESS semantics to order the set. + // So LESS means 'prior in set'. We want 'better' archs and + // 'better' editions at the beginning of the set. So we return + // TRUE if (lhs > rhs)! + // + bool operator()( const PoolItem & lhs, const PoolItem & rhs ) const + { + if ( lhs.isBlacklisted() != rhs.isBlacklisted() ) + return rhs.isBlacklisted(); + + int lprio = lhs->satSolvable().repository().satInternalPriority(); + int rprio = rhs->satSolvable().repository().satInternalPriority(); + if ( lprio != rprio ) + return( lprio > rprio ); + + // arch/noarch changes are ok. + if ( lhs->arch() != Arch_noarch && rhs->arch() != Arch_noarch ) + { + int res = lhs->arch().compare( rhs->arch() ); + if ( res ) + return res > 0; + } + + int res = lhs->edition().compare( rhs->edition() ); + if ( res ) + return res > 0; + + lprio = lhs->buildtime(); + rprio = rhs->buildtime(); + if ( lprio != rprio ) + return( lprio > rprio ); + + lprio = lhs->satSolvable().repository().satInternalSubPriority(); + rprio = rhs->satSolvable().repository().satInternalSubPriority(); + if ( lprio != rprio ) + return( lprio > rprio ); + + // no more criteria, still equal: sort by id + return lhs.satSolvable().id() < rhs.satSolvable().id(); + } + }; + + /** Oder on InstalledItemSet. + * \li best Arch + * \li best Edition + * \li newer install time + * \li ResObject::constPtr as fallback. + */ + struct IOrder + { + // NOTE: operator() provides LESS semantics to order the set. + // So LESS means 'prior in set'. We want 'newer' install time + // at the beginning of the set. + // + bool operator()( const PoolItem & lhs, const PoolItem & rhs ) const + { + int res = lhs->arch().compare( rhs->arch() ); + if ( res ) + return res > 0; + res = lhs->edition().compare( rhs->edition() ); + if ( res ) + return res > 0; + Date ldate = lhs->installtime(); + Date rdate = rhs->installtime(); + if ( ldate != rdate ) + return( ldate > rdate ); + + // no more criteria, still equal: sort by id + return lhs.satSolvable().id() < rhs.satSolvable().id(); + } + }; + + using AvailableItemSet = std::set; + using available_iterator = AvailableItemSet::iterator; + using available_const_iterator = AvailableItemSet::const_iterator; + using available_size_type = AvailableItemSet::size_type; + + using InstalledItemSet = std::set; + using installed_iterator = AvailableItemSet::iterator; + using installed_const_iterator = AvailableItemSet::const_iterator; + using installed_size_type = AvailableItemSet::size_type; + + using PickList = std::vector; + using picklist_iterator = PickList::const_iterator; + using picklist_size_type = PickList::size_type; + }; + /////////////////////////////////////////////////////////////////// + + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_UI_SELECTABLETRAITS_H diff --git a/zypp/ui/Status.cc b/zypp/ui/Status.cc new file mode 100644 index 0000000..576add6 --- /dev/null +++ b/zypp/ui/Status.cc @@ -0,0 +1,58 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/Status.cc + * +*/ +#include + +#include + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + /****************************************************************** + ** + ** FUNCTION NAME : asString + ** FUNCTION TYPE : std::string + */ + std::string asString( const Status & obj ) + { + switch ( obj ) { +#define ENUM_OUT(V) case V: return #V; break + + ENUM_OUT( S_Protected ); + ENUM_OUT( S_Taboo ); + ENUM_OUT( S_Del ); + ENUM_OUT( S_Install ); + ENUM_OUT( S_Update ); + ENUM_OUT( S_AutoDel ); + ENUM_OUT( S_AutoInstall ); + ENUM_OUT( S_AutoUpdate ); + ENUM_OUT( S_NoInst ); + ENUM_OUT( S_KeepInstalled ); + +#undef ENUM_OUT + } + + INT << "Unknown ui::Status " << (unsigned)obj << std::endl; + return "Status(UNKNOWN)"; + } + + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/ui/Status.h b/zypp/ui/Status.h new file mode 100644 index 0000000..9c52d09 --- /dev/null +++ b/zypp/ui/Status.h @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/ui/Status.h + * +*/ +#ifndef ZYPP_UI_STATUS_H +#define ZYPP_UI_STATUS_H + +#include +#include +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace ui + { ///////////////////////////////////////////////////////////////// + + /** UI status + * Status values calculated by \ref Selectable. + + * \note The \ref Status enum, and its use within \ref Selectabe + * is tightly related to the Y2UI. It might be not very useful + * outside the Y2UI. + * + * \todo make it an EnumerationClass + */ + enum Status + { + S_Protected, // Keep this unmodified ( have installedObj && S_Protected ) + S_Taboo, // Keep this unmodified ( have no installedObj && S_Taboo) + // requested by user: + S_Del, // delete installedObj ( clears S_Protected if set ) + S_Update, // install candidateObj ( have installedObj, clears S_Protected if set ) + S_Install, // install candidateObj ( have no installedObj, clears S_Taboo if set ) + // not requested by user: + S_AutoDel, // delete installedObj + S_AutoUpdate, // install candidateObj ( have installedObj ) + S_AutoInstall, // install candidateObj ( have no installedObj ) + // no modification: + S_KeepInstalled, // no modification ( have installedObj && !S_Protected, clears S_Protected if set ) + S_NoInst, // no modification ( have no installedObj && !S_Taboo, clears S_Taboo if set ) + }; + + /////////////////////////////////////////////////////////////////// + + /** \relates Status Enum value as string. */ + std::string asString( const Status & obj ) ZYPP_API; + + /////////////////////////////////////////////////////////////////// + + /** \relates Status Stream output */ + inline std::ostream & operator<<( std::ostream & str, const Status & obj ) + { return str << asString( obj ); } + + ///////////////////////////////////////////////////////////////// + } // namespace ui + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_UI_STATUS_H diff --git a/zypp/ui/UserWantedPackages.cc b/zypp/ui/UserWantedPackages.cc new file mode 100644 index 0000000..0054be2 --- /dev/null +++ b/zypp/ui/UserWantedPackages.cc @@ -0,0 +1,120 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/ui/UserWantedPackages.cc + * + * \author Stefan Hundhammer + * + */ +#include +#include + +#include + +#include +#include + +#include +#include +#include + + +using std::string; +using std::set; +using std::endl; + + +namespace zypp +{ + namespace ui + { + using PoolProxyIterator = ResPoolProxy::const_iterator; + + static inline ResPoolProxy poolProxy() { return getZYpp()->poolProxy(); } + + template PoolProxyIterator poolProxyBegin() { return poolProxy().byKindBegin(); } + template PoolProxyIterator poolProxyEnd() { return poolProxy().byKindEnd(); } + + static inline PoolProxyIterator pkgBegin() { return poolProxyBegin(); } + static inline PoolProxyIterator pkgEnd() { return poolProxyEnd(); } + + static inline PoolProxyIterator patchesBegin() { return poolProxyBegin(); } + static inline PoolProxyIterator patchesEnd() { return poolProxyEnd(); } + + template bool contains( const std::set & container, T search ) + { + return container.find( search ) != container.end(); + } + + + + static void addDirectlySelectedPackages ( set & pkgNames ); + template void addPkgSetPackages( set & pkgNames ); + + static void addPatchPackages ( set & pkgNames ); + + + + set userWantedPackageNames() + { + set pkgNames; + + DBG << "Collecting packages the user explicitly asked for" << endl; + + addDirectlySelectedPackages ( pkgNames ); + addPatchPackages ( pkgNames ); + + return pkgNames; + } + + + + static void addDirectlySelectedPackages( set & pkgNames ) + { + for ( PoolProxyIterator it = pkgBegin(); + it != pkgEnd(); + ++it ) + { + // Add all packages the user wanted to transact directly, + // no matter what the transaction is (install, update, delete) + + if ( (*it)->toModify() && (*it)->modifiedBy() == ResStatus::USER ) + { + DBG << "Explicit user transaction on pkg \"" << (*it)->name() << "\"" << endl; + + pkgNames.insert( (*it)->name() ); + } + } + } + + + static void addPatchPackages( set & pkgNames ) + { + for ( PoolProxyIterator patch_it = patchesBegin(); + patch_it != patchesEnd(); + ++patch_it ) + { + Patch::constPtr patch = dynamic_pointer_cast( (*patch_it)->theObj() ? (*patch_it)->theObj().resolvable() : 0 ); + + if ( patch && (*patch_it)->toModify() ) + { + DBG << "Patch will be transacted: \"" << patch->name() + << "\" - \"" << patch->summary() << "\"" << endl; + + Patch::Contents contents( patch->contents() ); + for_( it, contents.begin(), contents.end() ) + { + pkgNames.insert( it->name() ); + } + } + } + } + + } // namespace ui +} // namespace zypp diff --git a/zypp/ui/UserWantedPackages.h b/zypp/ui/UserWantedPackages.h new file mode 100644 index 0000000..c063a86 --- /dev/null +++ b/zypp/ui/UserWantedPackages.h @@ -0,0 +1,45 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** + * \file zypp/ui/UserWantedPackages.h + * + * \author Stefan Hundhammer + * + */ +#ifndef USER_WANTED_PACKAGES_H +#define USER_WANTED_PACKAGES_H + +#include +#include + +namespace zypp +{ + namespace ui + { + /** + * This returns a set of package names the user explicitly wanted to + * transact ( to install, to update, or to delete) for any of the + * following reasons: + * + * - The user wanted to transact the pkg directly + * + * - Pkg is part of a pattern the user wanted to transact + * - Pkg is part of a language the user wanted to transact + * (? No more transacting Languages) + * - Pkg is part of a patch the user wanted to transact + * + * - Pkg is part of a pattern that is required by a pattern the + * user wanted to transact + **/ + std::set userWantedPackageNames() ZYPP_API; + + } // namespace ui +} // namespace zypp + +#endif // USER_WANTED_PACKAGES_H diff --git a/zypp/url/UrlBase.h b/zypp/url/UrlBase.h new file mode 100644 index 0000000..c27d26f --- /dev/null +++ b/zypp/url/UrlBase.h @@ -0,0 +1 @@ +#include diff --git a/zypp/url/UrlException.h b/zypp/url/UrlException.h new file mode 100644 index 0000000..6204fd4 --- /dev/null +++ b/zypp/url/UrlException.h @@ -0,0 +1 @@ +#include diff --git a/zypp/url/UrlUtils.h b/zypp/url/UrlUtils.h new file mode 100644 index 0000000..e869c25 --- /dev/null +++ b/zypp/url/UrlUtils.h @@ -0,0 +1 @@ +#include diff --git a/zypp/zypp_detail/ZYppImpl.cc b/zypp/zypp_detail/ZYppImpl.cc new file mode 100644 index 0000000..39881ad --- /dev/null +++ b/zypp/zypp_detail/ZYppImpl.cc @@ -0,0 +1,351 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/zypp_detail/ZYppImpl.cc + * +*/ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include // JobReport::instance + +using std::endl; + +#include +#include +#include + +namespace { + + // Helper pipe to safely signal libzypp's poll code + // to stop polling and throw a user abort exception. + // Due to the pain that is unix signal handling we need + // to use atomics and be very careful about what we are calling. + // + // Not cleaned up, this happens when the application that is using libzypp + // exits. + volatile sig_atomic_t shutdownPipeRead{-1}; + volatile sig_atomic_t shutdownPipeWrite{-1}; + + bool makeShutdownPipe() { + int pipeFds[]{ -1, -1 }; + #ifdef HAVE_PIPE2 + if ( ::pipe2( pipeFds, O_CLOEXEC ) != 0 ) + return false; + #else + if ( ::pipe( pipeFds ) != 0 ) + return false; + ::fcntl( pipeFds[0], F_SETFD, O_CLOEXEC ); + ::fcntl( pipeFds[1], F_SETFD, O_CLOEXEC ); + #endif + shutdownPipeRead = pipeFds[0]; + shutdownPipeWrite = pipeFds[1]; + return true; + } + + const bool ensureShutdownPipe() { + static auto pipesInitialized = makeShutdownPipe(); + return pipesInitialized; + } + + const int shutdownPipeReadFd() { + if ( !ensureShutdownPipe() ) + return -1; + return static_cast(shutdownPipeRead); + } + + const int shutdownPipeWriteFd() { + return static_cast(shutdownPipeWrite); + } + +} + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + namespace media + { + ScopedDisableMediaChangeReport::ScopedDisableMediaChangeReport( bool condition_r ) + { + static weak_ptr > globalguard; + if ( condition_r && ! (_guard = globalguard.lock()) ) + { + // aquire a new one.... + _guard.reset( new callback::TempConnect() ); + globalguard = _guard; + } + } + } // namespace media + /////////////////////////////////////////////////////////////////// + + callback::SendReport & JobReport::instance() + { + static callback::SendReport _report; + return _report; + } + + + /////////////////////////////////////////////////////////////////// + namespace zypp_detail + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ZYppImpl::ZYppImpl + // METHOD TYPE : Constructor + // + ZYppImpl::ZYppImpl() + : _target( nullptr ) + , _resolver( new Resolver( ResPool::instance()) ) + { + // trigger creation of the shutdown pipe + if ( !ensureShutdownPipe() ) + WAR << "Failed to create shutdown pipe" << std::endl; + + ZConfig::instance().about( MIL ); + MIL << "Initializing keyring..." << std::endl; + _keyring = new KeyRing(tmpPath()); + _keyring->allowPreload( true ); + } + + /////////////////////////////////////////////////////////////////// + // + // METHOD NAME : ZYppImpl::~ZYppImpl + // METHOD TYPE : Destructor + // + ZYppImpl::~ZYppImpl() + {} + + //------------------------------------------------------------------------ + // add/remove resolvables + + DiskUsageCounter::MountPointSet ZYppImpl::diskUsage() + { + if ( ! _disk_usage ) + { + setPartitions( DiskUsageCounter::detectMountPoints() ); + } + return _disk_usage->disk_usage(pool()); + } + + void ZYppImpl::setPartitions(const DiskUsageCounter::MountPointSet &mp) + { + _disk_usage.reset(new DiskUsageCounter()); + _disk_usage->setMountPoints(mp); + } + + DiskUsageCounter::MountPointSet ZYppImpl::getPartitions() const + { + if (_disk_usage) + return _disk_usage->getMountPoints(); + else + return DiskUsageCounter::detectMountPoints(); + } + + //------------------------------------------------------------------------ + // target + + Target_Ptr ZYppImpl::target() const + { + if (! _target) + ZYPP_THROW(Exception("Target not initialized.")); + return _target; + } + + void ZYppImpl::changeTargetTo( const Target_Ptr& newtarget_r ) + { + if ( _target && newtarget_r ) // bsc#1203760: Make sure the old target is deleted before a new one is created! + INT << "2 active targets at the same time must not happen!" << endl; + _target = newtarget_r; + ZConfig::instance().notifyTargetChanged(); + resolver()->setDefaultSolverFlags( /*all_r*/false ); // just changed defaults + } + + void ZYppImpl::initializeTarget( const Pathname & root, bool doRebuild_r ) + { + MIL << "initTarget( " << root << (doRebuild_r?", rebuilddb":"") << ")" << endl; + if (_target) { + if (_target->root() == root) { + MIL << "Repeated call to initializeTarget()" << endl; + return; + } + _target->unload(); + _target = nullptr; // bsc#1203760: Make sure the old target is deleted before a new one is created! + } + changeTargetTo( new Target( root, doRebuild_r ) ); + _target->buildCache(); + } + + void ZYppImpl::finishTarget() + { + if (_target) + _target->unload(); + + changeTargetTo( nullptr ); + } + + //------------------------------------------------------------------------ + // commit + + /** \todo Remove workflow from target, lot's of it could be done here, + * and target used for transact. */ + ZYppCommitResult ZYppImpl::commit( const ZYppCommitPolicy & policy_r ) + { + if ( getenv("ZYPP_TESTSUITE_FAKE_ARCH") ) + { + ZYPP_THROW( Exception("ZYPP_TESTSUITE_FAKE_ARCH set. Commit not allowed and disabled.") ); + } + + MIL << "Attempt to commit (" << policy_r << ")" << endl; + if (! _target) + ZYPP_THROW( Exception("Target not initialized.") ); + + + env::ScopedSet ea { "ZYPP_IS_RUNNING", str::numstring(getpid()).c_str() }; + env::ScopedSet eb; + if ( _target->chrooted() ) + eb = env::ScopedSet( "SYSTEMD_OFFLINE", "1" ); // bsc#1118758 - indicate no systemd if chrooted install + + ZYppCommitResult res = _target->_pimpl->commit( pool(), policy_r ); + + if (! policy_r.dryRun() ) + { + if ( policy_r.syncPoolAfterCommit() ) + { + // reload new status from target + DBG << "reloading " << sat::Pool::instance().systemRepoAlias() << " repo to pool" << endl; + _target->load(); + } + else + { + DBG << "unloading " << sat::Pool::instance().systemRepoAlias() << " repo from pool" << endl; + _target->unload(); + } + } + + MIL << "Commit (" << policy_r << ") returned: " + << res << endl; + return res; + } + + void ZYppImpl::installSrcPackage( const SrcPackage_constPtr & srcPackage_r ) + { + if (! _target) + ZYPP_THROW( Exception("Target not initialized.") ); + _target->_pimpl->installSrcPackage( srcPackage_r ); + } + + ManagedFile ZYppImpl::provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ) + { + if (! _target) + ZYPP_THROW( Exception("Target not initialized.") ); + return _target->_pimpl->provideSrcPackage( srcPackage_r ); + } + + //------------------------------------------------------------------------ + // target store path + + Pathname ZYppImpl::homePath() const + { return _home_path.empty() ? Pathname("/var/lib/zypp") : _home_path; } + + void ZYppImpl::setHomePath( const Pathname & path ) + { _home_path = path; } + + Pathname ZYppImpl::tmpPath() const + { return zypp::myTmpDir(); } + + void ZYppImpl::setShutdownSignal() + { + // ONLY signal safe code here, that means no logging or anything else that is more than using atomics + // or writing a fd + int sigFd = shutdownPipeWriteFd(); + if ( sigFd == -1 ) { + // we have no fd to set this + return; + } + zyppng::eintrSafeCall( write, sigFd, "1", 1 ); + } + + void ZYppImpl::clearShutdownSignal() + { + // ONLY signal safe code here, that means no logging or anything else that is more than using atomics + // or writing a fd + int sigFd = shutdownPipeWriteFd(); + if ( sigFd == -1 ) { + // we have no fd so nothing to clear + return; + } + + char buf = 0; + while( zyppng::eintrSafeCall( read, sigFd, &buf, 1 ) > 0 ) + continue; + } + + /****************************************************************** + ** + ** FUNCTION NAME : operator<< + ** FUNCTION TYPE : std::ostream & + */ + std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj ) + { + return str << "ZYppImpl"; + } + + int zypp_poll( std::vector &fds, int timeout) + { + // request a shutdown fd we can use + const auto shutdownFd = shutdownPipeReadFd(); + if (shutdownFd == -1) { + ZYPP_THROW( zypp::Exception("Failed to get shutdown pipe") ); + } + + fds.push_back( GPollFD { + .fd = shutdownFd, + .events = G_IO_IN, + .revents = 0 + }); + + // make sure to remove our fd again + OnScopeExit removeShutdownFd( [&](){ fds.pop_back(); } ); + + int r = zyppng::eintrSafeCall( g_poll, fds.data(), fds.size(), timeout ); + if ( r > 0 ) { + // at least one fd triggered, if its our's we throw + if ( fds.back().revents ) + ZYPP_THROW( UserRequestException( UserRequestException::ABORT, "Shutdown signal received during poll." ) ); + } + return r; + } + + ///////////////////////////////////////////////////////////////// + } // namespace zypp_detail + /////////////////////////////////////////////////////////////////// + + Pathname myTmpDir() // from TmpPath.h + { + static filesystem::TmpDir _tmpdir( filesystem::TmpPath::defaultLocation(), "zypp." ); + return _tmpdir.path(); + } + + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// diff --git a/zypp/zypp_detail/ZYppImpl.h b/zypp/zypp_detail/ZYppImpl.h new file mode 100644 index 0000000..03b3312 --- /dev/null +++ b/zypp/zypp_detail/ZYppImpl.h @@ -0,0 +1,165 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/zypp_detail/ZYppImpl.h + * +*/ +#ifndef ZYPP_ZYPP_DETAIL_ZYPPIMPL_H +#define ZYPP_ZYPP_DETAIL_ZYPPIMPL_H + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using GPollFD = struct _GPollFD; + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace zypp_detail + { ///////////////////////////////////////////////////////////////// + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : ZYppImpl + // + /** */ + class ZYppImpl + { + friend std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj ); + + public: + /** Default ctor */ + ZYppImpl(); + /** Dtor */ + ~ZYppImpl(); + + public: + /** */ + ResPool pool() const + { return ResPool::instance(); } + + ResPoolProxy poolProxy() const + { return ResPool::instance().proxy(); } + + /** */ + KeyRing_Ptr keyRing() const + { return _keyring; } + + + Resolver_Ptr resolver() const + { return _resolver; } + + public: + /** \todo Signal locale change. */ + /** + * \throws Exception + */ + Target_Ptr target() const; + + /** Same as \ref target but returns NULL if target is not + * initialized, instead of throwing. + */ + Target_Ptr getTarget() const + { return _target; } + + /** + * \throws Exception + * true, just init the target, dont populate store or pool + */ + void initializeTarget( const Pathname & root, bool doRebuild_r ); + + /** + * \throws Exception + */ + void finishTarget(); + + /** Commit changes and transactions. */ + ZYppCommitResult commit( const ZYppCommitPolicy & policy_r ); + + /** Install a source package on the Target. */ + void installSrcPackage( const SrcPackage_constPtr & srcPackage_r ); + + /** Install a source package on the Target. */ + ManagedFile provideSrcPackage( const SrcPackage_constPtr & srcPackage_r ); + + public: + /** Get the path where zypp related plugins store persistent data and caches */ + Pathname homePath() const; + + /** Get the path where zypp related plugins store tmp data */ + Pathname tmpPath() const; + + /** set the home, if you need to change it */ + void setHomePath( const Pathname & path ); + + public: + DiskUsageCounter::MountPointSet diskUsage(); + void setPartitions(const DiskUsageCounter::MountPointSet &mp); + DiskUsageCounter::MountPointSet getPartitions() const; + + public: + /** Hook for actions to trigger if the Target changes (initialize/finish) */ + void changeTargetTo( const Target_Ptr& newtarget_r ); + + /** + * Enable the shutdown signal for \ref zypp_poll calls + */ + static void setShutdownSignal(); + + /** + * Disable the shutdown signal for \ref zypp_poll calls + */ + static void clearShutdownSignal(); + + private: + /** */ + Target_Ptr _target; + /** */ + Resolver_Ptr _resolver; + + KeyRing_Ptr _keyring; + /** */ + Pathname _home_path; + /** defined mount points, used for disk usage counting */ + shared_ptr _disk_usage; + }; + /////////////////////////////////////////////////////////////////// + + /** \relates ZYppImpl Stream output */ + std::ostream & operator<<( std::ostream & str, const ZYppImpl & obj ); + + /** + * Small wrapper around g_poll that additionally listens to the shutdown FD + * returned by \ref ZYpp::shutdownSignalFd. + * + * EINTR is handled internally, no need to explicitely handle it. + * + * For zyppng related code we should use different means to cancel processes, + * e.g via the top level event loop + * + * \throws zypp::UserAbortException in case the shutdown signal was received + */ + int zypp_poll( std::vector &fds, int timeout = -1 ); + + + ///////////////////////////////////////////////////////////////// + } // namespace zypp_detail + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// +#endif // ZYPP_ZYPP_DETAIL_ZYPPIMPL_H diff --git a/zypp/zypp_detail/ZYppReadOnlyHack.h b/zypp/zypp_detail/ZYppReadOnlyHack.h new file mode 100644 index 0000000..0a6d635 --- /dev/null +++ b/zypp/zypp_detail/ZYppReadOnlyHack.h @@ -0,0 +1,35 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/zypp_detail/ZYppReadOnlyHack.h + * +*/ + +#ifndef ZYPP_ZYPP_DETAIL_ZYPPREADONLYHACK_H +#define ZYPP_ZYPP_DETAIL_ZYPPREADONLYHACK_H +#warning ZYPP_ZYPP_DETAIL_ZYPPREADONLYHACK_H + +#include + +/////////////////////////////////////////////////////////////////// +namespace zypp +{ ///////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////// + namespace zypp_readonly_hack + { ///////////////////////////////////////////////////////////////// + + extern void IWantIt() ZYPP_DEPRECATED; + + ///////////////////////////////////////////////////////////////// + } // namespace zypp_readonly_hack + /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////// +} // namespace zypp +/////////////////////////////////////////////////////////////////// + +#endif // ZYPP_ZYPP_DETAIL_ZYPPREADONLYHACK_H diff --git a/zypp/zypp_detail/keyring_p.h b/zypp/zypp_detail/keyring_p.h new file mode 100644 index 0000000..b60e6bd --- /dev/null +++ b/zypp/zypp_detail/keyring_p.h @@ -0,0 +1,189 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/zypp_detail/repomanagerbase_p.h + * +*/ +#ifndef ZYPP_ZYPP_DETAIL_KEYRINGIMPL_H +#define ZYPP_ZYPP_DETAIL_KEYRINGIMPL_H + +#include "zypp-core/fs/TmpPath.h" +#include +#include +#include + +#include + +namespace zypp { + + + /////////////////////////////////////////////////////////////////// + /// \class CachedPublicKeyData + /// \brief Functor returning the keyrings data (cached). + /// \code + /// const std::list & cachedPublicKeyData( const Pathname & keyring ); + /// \endcode + /////////////////////////////////////////////////////////////////// + struct CachedPublicKeyData : private base::NonCopyable + { + const std::list & operator()( const Pathname & keyring_r ) const; + + void setDirty( const Pathname & keyring_r ); + + /////////////////////////////////////////////////////////////////// + /// \brief Helper providing on demand a KeyManagerCtx to manip the cached keyring. + /// + /// The 1st call to \ref keyManagerCtx creates the \ref KeyManagerCtx. Returning + /// the context tags the cached data as dirty. Should be used to import/delete keys + /// in a cache keyring. + struct Manip { + NON_COPYABLE_BUT_MOVE( Manip ); + Manip( CachedPublicKeyData & cache_r, Pathname keyring_r ); + + KeyManagerCtx & keyManagerCtx(); + private: + CachedPublicKeyData & _cache; + Pathname _keyring; + std::optional _context; + }; + /////////////////////////////////////////////////////////////////// + + /** Helper providing on demand a KeyManagerCtx to manip the cached keyring. */ + Manip manip( Pathname keyring_r ); + + private: + struct Cache + { + Cache(); + + void setDirty(); + + void assertCache( const Pathname & keyring_r ); + + bool hasChanged() const; + + std::list _data; + + private: + + scoped_ptr _keyringK; + scoped_ptr _keyringP; + }; + + using CacheMap = std::map; + + const std::list & getData( const Pathname & keyring_r ) const; + + const std::list & getData( const Pathname & keyring_r, Cache & cache_r ) const; + + mutable CacheMap _cacheMap; + }; + + + + /////////////////////////////////////////////////////////////////// + // + // CLASS NAME : KeyRing::Impl + // + /** KeyRing implementation. */ + struct KeyRing::Impl + { + Impl( const Pathname & baseTmpDir ); + + void importKey( const PublicKey & key, bool trusted = false ); + void multiKeyImport( const Pathname & keyfile_r, bool trusted_r = false ); + void deleteKey( const std::string & id, bool trusted ); + + std::string readSignatureKeyId( const Pathname & signature ); + + bool isKeyTrusted( const std::string & id ) + { return bool(publicKeyExists( id, trustedKeyRing() )); } + bool isKeyKnown( const std::string & id ) + { return publicKeyExists( id, trustedKeyRing() ) || publicKeyExists( id, generalKeyRing() ); } + + std::list trustedPublicKeys() + { return publicKeys( trustedKeyRing() ); } + std::list publicKeys() + { return publicKeys( generalKeyRing() ); } + + const std::list & trustedPublicKeyData() + { return publicKeyData( trustedKeyRing() ); } + const std::list & publicKeyData() + { return publicKeyData( generalKeyRing() ); } + + void dumpPublicKey( const std::string & id, bool trusted, std::ostream & stream ) + { dumpPublicKey( id, ( trusted ? trustedKeyRing() : generalKeyRing() ), stream ); } + + PublicKey exportPublicKey( const PublicKeyData & keyData ) + { return exportKey( keyData, generalKeyRing() ); } + PublicKey exportTrustedPublicKey( const PublicKeyData & keyData ) + { return exportKey( keyData, trustedKeyRing() ); } + + bool verifyFileSignature( const Pathname & file, const Pathname & signature ) + { return verifyFile( file, signature, generalKeyRing() ); } + bool verifyFileTrustedSignature( const Pathname & file, const Pathname & signature ) + { return verifyFile( file, signature, trustedKeyRing() ); } + + PublicKeyData publicKeyExists( const std::string & id ) + { return publicKeyExists(id, generalKeyRing());} + PublicKeyData trustedPublicKeyExists( const std::string & id ) + { return publicKeyExists(id, trustedKeyRing());} + + void allowPreload( bool yesno_r ) + { _allowPreload = yesno_r; } + + /** Impl helper providing on demand a KeyManagerCtx to manip a cached keyring. */ + CachedPublicKeyData::Manip keyRingManip( const Pathname & keyring ) + { return cachedPublicKeyData.manip( keyring ); } + + bool verifyFile( const Pathname & file, const Pathname & signature, const Pathname & keyring ); + void importKey( const Pathname & keyfile, const Pathname & keyring ); + + PublicKey exportKey( const std::string & id, const Pathname & keyring ); + PublicKey exportKey( const PublicKeyData & keyData, const Pathname & keyring ); + PublicKey exportKey( const PublicKey & key, const Pathname & keyring ) + { return exportKey( key.keyData(), keyring ); } + + void dumpPublicKey( const std::string & id, const Pathname & keyring, std::ostream & stream ); + filesystem::TmpFile dumpPublicKeyToTmp( const std::string & id, const Pathname & keyring ); + + void deleteKey( const std::string & id, const Pathname & keyring ); + + std::list publicKeys( const Pathname & keyring); + const std::list & publicKeyData( const Pathname & keyring ) + { return cachedPublicKeyData( keyring ); } + + /** Get \ref PublicKeyData for ID (\c false if ID is not found). */ + PublicKeyData publicKeyExists( const std::string & id, const Pathname & keyring ); + /** Load key files cached on the system into the generalKeyRing. */ + void preloadCachedKeys(); + + const Pathname generalKeyRing() const + { return _general_tmp_dir.path(); } + const Pathname trustedKeyRing() const + { return _trusted_tmp_dir.path(); } + + private: + // Used for trusted and untrusted keyrings + filesystem::TmpDir _trusted_tmp_dir; + filesystem::TmpDir _general_tmp_dir; + Pathname _base_dir; + bool _allowPreload = false; //< General keyring may be preloaded with keys cached on the system. + + /** Functor returning the keyrings data (cached). + * \code + * const std::list & cachedPublicKeyData( const Pathname & keyring ); + * \endcode + */ + CachedPublicKeyData cachedPublicKeyData; + }; + +} + + +#endif diff --git a/zypp/zypp_detail/urlcredentialextractor_p.h b/zypp/zypp_detail/urlcredentialextractor_p.h new file mode 100644 index 0000000..f7cf100 --- /dev/null +++ b/zypp/zypp_detail/urlcredentialextractor_p.h @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------\ +| ____ _ __ __ ___ | +| |__ / \ / / . \ . \ | +| / / \ V /| _/ _/ | +| / /__ | | | | | | | +| /_____||_| |_| |_| | +| | +\---------------------------------------------------------------------*/ +/** \file zypp/zypp_detail/urlcredentialextractor_p.h + * +*/ + +#ifndef ZYPP_ZYPP_DETAIL_URLCREDENTIALEXTRACTOR_P_H +#define ZYPP_ZYPP_DETAIL_URLCREDENTIALEXTRACTOR_P_H + +#include +#include + +namespace zypp +{ + /////////////////////////////////////////////////////////////////// + /// \class UrlCredentialExtractor + /// \brief Extract credentials in \ref Url authority and store them via \ref CredentialManager. + /// + /// Lazy init CredentialManager and save collected credentials when + /// going out of scope. + /// + /// Methods return whether a password has been collected/extracted. + /// + /// \code + /// UrlCredentialExtractor( "/rootdir" ).collect( oneUrlOrUrlContainer ); + /// \endcode + /// \code + /// { + /// UrlCredentialExtractor extractCredentials; + /// extractCredentials.collect( oneUrlOrUrlContainer ); + /// extractCredentials.extract( oneMoreUrlOrUrlContainer ); + /// .... + /// } + /// \endcode + /// + class UrlCredentialExtractor + { + public: + UrlCredentialExtractor( const Pathname & root_r ) + : _root( root_r ) + {} + + UrlCredentialExtractor( Pathname & root_r ) + : _root( root_r ) + {} + + ~UrlCredentialExtractor() + { if ( _cmPtr ) _cmPtr->save(); } + + /** Remember credentials stored in URL authority leaving the password in \a url_r. */ + bool collect( const Url & url_r ) + { + bool ret = url_r.hasCredentialsInAuthority(); + if ( ret ) + { + if ( !_cmPtr ) _cmPtr.reset( new media::CredentialManager( _root ) ); + _cmPtr->addUserCred( url_r ); + } + return ret; + } + /** \overload operating on Url container */ + template + bool collect( const TContainer & urls_r ) + { bool ret = false; for ( const Url & url : urls_r ) { if ( collect( url ) && !ret ) ret = true; } return ret; } + + /** Remember credentials stored in URL authority stripping the passowrd from \a url_r. */ + bool extract( Url & url_r ) + { + bool ret = collect( url_r ); + if ( ret ) + url_r.setPassword( std::string() ); + return ret; + } + /** \overload operating on Url container */ + template + bool extract( TContainer & urls_r ) + { bool ret = false; for ( Url & url : urls_r ) { if ( extract( url ) && !ret ) ret = true; } return ret; } + + private: + const Pathname & _root; + scoped_ptr _cmPtr; + }; +} + +#endif -- 2.30.2

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